Reuse code for open documents and open help pages panes

Change-Id: I4924e72e732eb447d2e581d60f5e4426f5ff7cb2
Reviewed-by: David Schulz <david.schulz@digia.com>
This commit is contained in:
Eike Ziller
2014-09-23 12:56:28 +02:00
parent e1a084ccf8
commit 0f39b4e9e7
9 changed files with 282 additions and 241 deletions

View File

@@ -101,7 +101,8 @@ SOURCES += corejsextensions.cpp \
icorelistener.cpp \
ioutputpane.cpp \
patchtool.cpp \
windowsupport.cpp
windowsupport.cpp \
opendocumentstreeview.cpp
HEADERS += corejsextensions.h \
mainwindow.h \
@@ -206,7 +207,8 @@ HEADERS += corejsextensions.h \
removefiledialog.h \
dialogs/addtovcsdialog.h \
patchtool.h \
windowsupport.h
windowsupport.h \
opendocumentstreeview.h
FORMS += dialogs/newdialog.ui \
dialogs/saveitemsdialog.ui \

View File

@@ -82,6 +82,7 @@ QtcPlugin {
"modemanager.cpp", "modemanager.h",
"navigationsubwidget.cpp", "navigationsubwidget.h",
"navigationwidget.cpp", "navigationwidget.h",
"opendocumentstreeview.cpp", "opendocumentstreeview.h",
"outputpane.cpp", "outputpane.h",
"outputpanemanager.cpp", "outputpanemanager.h",
"outputwindow.cpp", "outputwindow.h",

View File

@@ -37,49 +37,10 @@
#include <QApplication>
#include <QMenu>
#include <QPainter>
#include <QStyle>
#include <QHeaderView>
#include <QKeyEvent>
using namespace Core;
using namespace Core::Internal;
OpenEditorsDelegate::OpenEditorsDelegate(QObject *parent)
: QStyledItemDelegate(parent)
{
}
void OpenEditorsDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
if (option.state & QStyle::State_MouseOver) {
if ((QApplication::mouseButtons() & Qt::LeftButton) == 0)
pressedIndex = QModelIndex();
QBrush brush = option.palette.alternateBase();
if (index == pressedIndex)
brush = option.palette.dark();
painter->fillRect(option.rect, brush);
}
QStyledItemDelegate::paint(painter, option, index);
if (index.column() == 1 && option.state & QStyle::State_MouseOver) {
const QIcon icon(QLatin1String((option.state & QStyle::State_Selected) ?
Constants::ICON_CLOSE_BUTTON : Constants::ICON_DARK_CLOSE_BUTTON));
QRect iconRect(option.rect.right() - option.rect.height(),
option.rect.top(),
option.rect.height(),
option.rect.height());
icon.paint(painter, iconRect, Qt::AlignRight | Qt::AlignVCenter);
}
}
////
// OpenEditorsWidget
////
@@ -90,37 +51,22 @@ OpenEditorsWidget::OpenEditorsWidget()
setWindowIcon(QIcon(QLatin1String(Constants::ICON_DIR)));
setDragEnabled(true);
setDragDropMode(QAbstractItemView::DragOnly);
setUniformRowHeights(true);
viewport()->setAttribute(Qt::WA_Hover);
setItemDelegate((m_delegate = new OpenEditorsDelegate(this)));
header()->hide();
setIndentation(0);
setTextElideMode(Qt::ElideMiddle);
setFrameStyle(QFrame::NoFrame);
setAttribute(Qt::WA_MacShowFocusRect, false);
m_model = new ProxyModel(this);
m_model->setSourceModel(DocumentModel::model());
setModel(m_model);
setSelectionMode(QAbstractItemView::SingleSelection);
setSelectionBehavior(QAbstractItemView::SelectRows);
setActivationMode(Utils::SingleClickActivation);
header()->setStretchLastSection(false);
header()->setSectionResizeMode(0, QHeaderView::Stretch);
header()->setSectionResizeMode(1, QHeaderView::Fixed);
header()->resizeSection(1, 16);
setContextMenuPolicy(Qt::CustomContextMenu);
installEventFilter(this);
viewport()->installEventFilter(this);
connect(EditorManager::instance(), SIGNAL(currentEditorChanged(Core::IEditor*)),
this, SLOT(updateCurrentItem(Core::IEditor*)));
connect(this, SIGNAL(activated(QModelIndex)),
this, SLOT(handleActivated(QModelIndex)));
connect(this, SIGNAL(pressed(QModelIndex)),
this, SLOT(handlePressed(QModelIndex)));
connect(EditorManager::instance(), &EditorManager::currentEditorChanged,
this, &OpenEditorsWidget::updateCurrentItem);
connect(this, &OpenDocumentsTreeView::activated,
this, &OpenEditorsWidget::handleActivated);
connect(this, &OpenDocumentsTreeView::closeActivated,
this, &OpenEditorsWidget::closeDocument);
connect(this, SIGNAL(customContextMenuRequested(QPoint)),
this, SLOT(contextMenuRequested(QPoint)));
connect(this, &OpenDocumentsTreeView::customContextMenuRequested,
this, &OpenEditorsWidget::contextMenuRequested);
}
OpenEditorsWidget::~OpenEditorsWidget()
@@ -141,43 +87,12 @@ void OpenEditorsWidget::updateCurrentItem(Core::IEditor *editor)
scrollTo(currentIndex());
}
bool OpenEditorsWidget::eventFilter(QObject *obj, QEvent *event)
{
if (obj == this && event->type() == QEvent::KeyPress
&& currentIndex().isValid()) {
QKeyEvent *ke = static_cast<QKeyEvent*>(event);
if ((ke->key() == Qt::Key_Delete
|| ke->key() == Qt::Key_Backspace)
&& ke->modifiers() == 0) {
closeEditor(currentIndex());
}
} else if (obj == viewport()
&& event->type() == QEvent::MouseButtonRelease) {
QMouseEvent * me = static_cast<QMouseEvent*>(event);
if (me->button() == Qt::MiddleButton
&& me->modifiers() == Qt::NoModifier) {
QModelIndex index = indexAt(me->pos());
if (index.isValid()) {
closeEditor(index);
return true;
}
}
}
return false;
}
void OpenEditorsWidget::handlePressed(const QModelIndex &index)
{
if (index.column() == 1)
m_delegate->pressedIndex = index;
}
void OpenEditorsWidget::handleActivated(const QModelIndex &index)
{
if (index.column() == 0) {
activateEditor(index);
} else if (index.column() == 1) { // the funky close button
closeEditor(index);
closeDocument(index);
// work around a bug in itemviews where the delegate wouldn't get the QStyle::State_MouseOver
QPoint cursorPos = QCursor::pos();
@@ -194,7 +109,7 @@ void OpenEditorsWidget::activateEditor(const QModelIndex &index)
DocumentModel::entryAtRow(m_model->mapToSource(index).row()));
}
void OpenEditorsWidget::closeEditor(const QModelIndex &index)
void OpenEditorsWidget::closeDocument(const QModelIndex &index)
{
EditorManager::closeDocument(
DocumentModel::entryAtRow(m_model->mapToSource(index).row()));

View File

@@ -30,12 +30,10 @@
#ifndef OPENEDITORSVIEW_H
#define OPENEDITORSVIEW_H
#include <utils/itemviews.h>
#include <coreplugin/inavigationwidgetfactory.h>
#include <coreplugin/opendocumentstreeview.h>
#include <QAbstractProxyModel>
#include <QStyledItemDelegate>
#include <QTreeView>
namespace Core {
class IEditor;
@@ -70,18 +68,7 @@ private slots:
void sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end);
};
class OpenEditorsDelegate : public QStyledItemDelegate
{
public:
explicit OpenEditorsDelegate(QObject *parent = 0);
void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const;
mutable QModelIndex pressedIndex;
};
class OpenEditorsWidget : public Utils::TreeView
class OpenEditorsWidget : public OpenDocumentsTreeView
{
Q_OBJECT
@@ -89,20 +76,15 @@ public:
OpenEditorsWidget();
~OpenEditorsWidget();
bool eventFilter(QObject *obj, QEvent *event);
private slots:
void handleActivated(const QModelIndex &);
void handlePressed(const QModelIndex &);
void updateCurrentItem(Core::IEditor*);
void contextMenuRequested(QPoint pos);
private:
void activateEditor(const QModelIndex &index);
void closeEditor(const QModelIndex &index);
using QAbstractItemView::closeEditor;
void closeDocument(const QModelIndex &index);
OpenEditorsDelegate *m_delegate;
ProxyModel *m_model;
};

View File

@@ -0,0 +1,167 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "opendocumentstreeview.h"
#include "coreconstants.h"
#include <QApplication>
#include <QHeaderView>
#include <QPainter>
#include <QStyledItemDelegate>
namespace Core {
namespace Internal {
class OpenDocumentsDelegate : public QStyledItemDelegate
{
public:
explicit OpenDocumentsDelegate(QObject *parent = 0);
void setCloseButtonVisible(bool visible);
void handlePressed(const QModelIndex &index);
void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const;
mutable QModelIndex pressedIndex;
bool closeButtonVisible;
};
OpenDocumentsDelegate::OpenDocumentsDelegate(QObject *parent)
: QStyledItemDelegate(parent),
closeButtonVisible(true)
{
}
void OpenDocumentsDelegate::setCloseButtonVisible(bool visible)
{
closeButtonVisible = visible;
}
void OpenDocumentsDelegate::handlePressed(const QModelIndex &index)
{
if (index.column() == 1)
pressedIndex = index;
}
void OpenDocumentsDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
if (option.state & QStyle::State_MouseOver) {
if ((QApplication::mouseButtons() & Qt::LeftButton) == 0)
pressedIndex = QModelIndex();
QBrush brush = option.palette.alternateBase();
if (index == pressedIndex)
brush = option.palette.dark();
painter->fillRect(option.rect, brush);
}
QStyledItemDelegate::paint(painter, option, index);
if (closeButtonVisible && index.column() == 1 && option.state & QStyle::State_MouseOver) {
const QIcon icon(QLatin1String((option.state & QStyle::State_Selected) ?
Constants::ICON_CLOSE_BUTTON : Constants::ICON_DARK_CLOSE_BUTTON));
QRect iconRect(option.rect.right() - option.rect.height(),
option.rect.top(),
option.rect.height(),
option.rect.height());
icon.paint(painter, iconRect, Qt::AlignRight | Qt::AlignVCenter);
}
}
} // namespace Internal
OpenDocumentsTreeView::OpenDocumentsTreeView(QWidget *parent) :
Utils::TreeView(parent)
{
m_delegate = new Internal::OpenDocumentsDelegate(this);
setItemDelegate(m_delegate);
setIndentation(0);
setUniformRowHeights(true);
setTextElideMode(Qt::ElideMiddle);
setFrameStyle(QFrame::NoFrame);
setAttribute(Qt::WA_MacShowFocusRect, false);
viewport()->setAttribute(Qt::WA_Hover);
setSelectionMode(QAbstractItemView::SingleSelection);
setSelectionBehavior(QAbstractItemView::SelectRows);
setActivationMode(Utils::SingleClickActivation);
installEventFilter(this);
viewport()->installEventFilter(this);
connect(this, &OpenDocumentsTreeView::pressed,
m_delegate, &Internal::OpenDocumentsDelegate::handlePressed);
}
void OpenDocumentsTreeView::setModel(QAbstractItemModel *model)
{
Utils::TreeView::setModel(model);
header()->hide();
header()->setStretchLastSection(false);
header()->setSectionResizeMode(0, QHeaderView::Stretch);
header()->setSectionResizeMode(1, QHeaderView::Fixed);
header()->resizeSection(1, 16);
}
void OpenDocumentsTreeView::setCloseButtonVisible(bool visible)
{
m_delegate->setCloseButtonVisible(visible);
}
bool OpenDocumentsTreeView::eventFilter(QObject *obj, QEvent *event)
{
if (obj == this && event->type() == QEvent::KeyPress
&& currentIndex().isValid()) {
QKeyEvent *ke = static_cast<QKeyEvent*>(event);
if ((ke->key() == Qt::Key_Delete
|| ke->key() == Qt::Key_Backspace)
&& ke->modifiers() == 0) {
emit closeActivated(currentIndex());
}
} else if (obj == viewport()
&& event->type() == QEvent::MouseButtonRelease) {
QMouseEvent * me = static_cast<QMouseEvent*>(event);
if (me->button() == Qt::MiddleButton
&& me->modifiers() == Qt::NoModifier) {
QModelIndex index = indexAt(me->pos());
if (index.isValid()) {
emit closeActivated(index);
return true;
}
}
}
return false;
}
} // namespace Core

View File

@@ -0,0 +1,61 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef OPENDOCUMENTSTREEVIEW_H
#define OPENDOCUMENTSTREEVIEW_H
#include "core_global.h"
#include <utils/itemviews.h>
namespace Core {
namespace Internal { class OpenDocumentsDelegate; }
class CORE_EXPORT OpenDocumentsTreeView : public Utils::TreeView
{
Q_OBJECT
public:
explicit OpenDocumentsTreeView(QWidget *parent = 0);
void setModel(QAbstractItemModel *model);
void setCloseButtonVisible(bool visible);
signals:
void closeActivated(const QModelIndex &index);
protected:
bool eventFilter(QObject *obj, QEvent *event);
private:
Internal::OpenDocumentsDelegate *m_delegate;
};
} // namespace Core
#endif // OPENDOCUMENTSTREEVIEW_H

View File

@@ -97,7 +97,6 @@ QWidget *OpenPagesManager::openPagesWidget() const
{
if (!m_openPagesWidget) {
m_openPagesWidget = new OpenPagesWidget(m_model);
m_openPagesWidget->setFrameStyle(QFrame::NoFrame);
connect(m_openPagesWidget, SIGNAL(setCurrentPage(QModelIndex)), this,
SLOT(setCurrentPage(QModelIndex)));
connect(m_openPagesWidget, SIGNAL(closePage(QModelIndex)), this,

View File

@@ -34,84 +34,33 @@
#include <coreplugin/coreconstants.h>
#include <QAbstractItemModel>
#include <QApplication>
#include <QPainter>
#include <QHeaderView>
#include <QKeyEvent>
#include <QMouseEvent>
#include <QMenu>
using namespace Help::Internal;
// -- OpenPagesDelegate
OpenPagesDelegate::OpenPagesDelegate(QObject *parent)
: QStyledItemDelegate(parent)
{
}
void OpenPagesDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
if (option.state & QStyle::State_MouseOver) {
if ((QApplication::mouseButtons() & Qt::LeftButton) == 0)
pressedIndex = QModelIndex();
QBrush brush = option.palette.alternateBase();
if (index == pressedIndex)
brush = option.palette.dark();
painter->fillRect(option.rect, brush);
}
QStyledItemDelegate::paint(painter, option, index);
if (index.column() == 1 && index.model()->rowCount() > 1
&& option.state & QStyle::State_MouseOver) {
const QIcon icon(QLatin1String((option.state & QStyle::State_Selected) ?
Core::Constants::ICON_CLOSE_BUTTON : Core::Constants::ICON_DARK_CLOSE_BUTTON));
const QRect iconRect(option.rect.right() - option.rect.height(),
option.rect.top(), option.rect.height(), option.rect.height());
icon.paint(painter, iconRect, Qt::AlignRight | Qt::AlignVCenter);
}
}
// -- OpenPagesWidget
OpenPagesWidget::OpenPagesWidget(OpenPagesModel *model, QWidget *parent)
: QTreeView(parent)
OpenPagesWidget::OpenPagesWidget(OpenPagesModel *sourceModel, QWidget *parent)
: OpenDocumentsTreeView(parent)
, m_allowContextMenu(true)
{
setModel(model);
setIndentation(0);
setItemDelegate((m_delegate = new OpenPagesDelegate(this)));
setModel(sourceModel);
setTextElideMode(Qt::ElideMiddle);
setAttribute(Qt::WA_MacShowFocusRect, false);
viewport()->setAttribute(Qt::WA_Hover);
setSelectionBehavior(QAbstractItemView::SelectRows);
setSelectionMode(QAbstractItemView::SingleSelection);
header()->hide();
header()->setStretchLastSection(false);
header()->setSectionResizeMode(0, QHeaderView::Stretch);
header()->setSectionResizeMode(1, QHeaderView::Fixed);
header()->resizeSection(1, 18);
installEventFilter(this);
setUniformRowHeights(true);
setContextMenuPolicy(Qt::CustomContextMenu);
updateCloseButtonVisibility();
connect(this, SIGNAL(clicked(QModelIndex)), this,
SLOT(handleClicked(QModelIndex)));
connect(this, SIGNAL(pressed(QModelIndex)), this,
SLOT(handlePressed(QModelIndex)));
connect(this, SIGNAL(customContextMenuRequested(QPoint)), this,
SLOT(contextMenuRequested(QPoint)));
connect(this, &OpenDocumentsTreeView::activated,
this, &OpenPagesWidget::handleActivated);
connect(this, &OpenDocumentsTreeView::closeActivated,
this, &OpenPagesWidget::handleCloseActivated);
connect(this, &OpenDocumentsTreeView::customContextMenuRequested,
this, &OpenPagesWidget::contextMenuRequested);
connect(model(), SIGNAL(rowsInserted(QModelIndex,int,int)),
this, SLOT(updateCloseButtonVisibility()));
connect(model(), SIGNAL(rowsRemoved(QModelIndex,int,int)),
this, SLOT(updateCloseButtonVisibility()));
}
OpenPagesWidget::~OpenPagesWidget()
@@ -160,47 +109,29 @@ void OpenPagesWidget::contextMenuRequested(QPoint pos)
emit closePagesExcept(index);
}
void OpenPagesWidget::handlePressed(const QModelIndex &index)
void OpenPagesWidget::handleActivated(const QModelIndex &index)
{
if (index.column() == 0)
if (index.column() == 0) {
emit setCurrentPage(index);
if (index.column() == 1)
m_delegate->pressedIndex = index;
}
void OpenPagesWidget::handleClicked(const QModelIndex &index)
{
// implemented here to handle the funky close button and to work around a
// bug in item views where the delegate wouldn't get the QStyle::State_MouseOver
if (index.column() == 1) {
} else if (index.column() == 1) { // the funky close button
if (model()->rowCount() > 1)
emit closePage(index);
// work around a bug in itemviews where the delegate wouldn't get the QStyle::State_MouseOver
QWidget *vp = viewport();
const QPoint &cursorPos = QCursor::pos();
QMouseEvent e(QEvent::MouseMove, vp->mapFromGlobal(cursorPos), cursorPos,
Qt::NoButton, 0, 0);
QMouseEvent e(QEvent::MouseMove, vp->mapFromGlobal(cursorPos), cursorPos, Qt::NoButton, 0, 0);
QCoreApplication::sendEvent(vp, &e);
}
}
// -- private
bool OpenPagesWidget::eventFilter(QObject *obj, QEvent *event)
void OpenPagesWidget::handleCloseActivated(const QModelIndex &index)
{
if (obj == this && event->type() == QEvent::KeyPress) {
if (currentIndex().isValid()) {
QKeyEvent *ke = static_cast<QKeyEvent*>(event);
const int key = ke->key();
if ((key == Qt::Key_Return || key == Qt::Key_Enter || key == Qt::Key_Space)
&& ke->modifiers() == 0) {
emit setCurrentPage(currentIndex());
} else if ((key == Qt::Key_Delete || key == Qt::Key_Backspace)
&& ke->modifiers() == 0 && model()->rowCount() > 1) {
emit closePage(currentIndex());
}
}
}
return QWidget::eventFilter(obj, event);
if (model()->rowCount() > 1)
emit closePage(index);
}
void OpenPagesWidget::updateCloseButtonVisibility()
{
setCloseButtonVisible(model() && model()->rowCount() > 1);
}

View File

@@ -30,28 +30,14 @@
#ifndef OPENPAGESWIDGET_H
#define OPENPAGESWIDGET_H
#include <QStyledItemDelegate>
#include <QTreeView>
#include <coreplugin/opendocumentstreeview.h>
namespace Help {
namespace Internal {
namespace Internal {
class OpenPagesModel;
class OpenPagesDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit OpenPagesDelegate(QObject *parent = 0);
void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const;
mutable QModelIndex pressedIndex;
};
class OpenPagesWidget : public QTreeView
class OpenPagesWidget : public Core::OpenDocumentsTreeView
{
Q_OBJECT
@@ -70,15 +56,12 @@ signals:
private slots:
void contextMenuRequested(QPoint pos);
void handlePressed(const QModelIndex &index);
void handleClicked(const QModelIndex &index);
private:
bool eventFilter(QObject *obj, QEvent *event);
void handleActivated(const QModelIndex &index);
void handleCloseActivated(const QModelIndex &index);
void updateCloseButtonVisibility();
private:
bool m_allowContextMenu;
OpenPagesDelegate *m_delegate;
};
} // namespace Internal