Commit 7dd81eca authored by Eike Ziller's avatar Eike Ziller

Add a <no document> entry to editor views.

This fixes issues with splitting when an editor is active that doesn't
support it.

Task-number: QTCREATORBUG-6827

Change-Id: Ib71117cb5723482b4212f99a7c4136005273ae44
Reviewed-by: default avatarEike Ziller <eike.ziller@digia.com>
parent 3557603b
......@@ -1258,7 +1258,12 @@ void EditorManager::activateEditorForEntry(OpenEditorsModel::Entry *entry, OpenE
void EditorManager::activateEditorForEntry(Internal::EditorView *view, OpenEditorsModel::Entry *entry, OpenEditorFlags flags)
{
QTC_ASSERT(view, return);
QTC_ASSERT(entry, return);
if (!entry) { // no document
view->setCurrentEditor(0);
setCurrentView(view);
setCurrentEditor(0);
return;
}
IEditor *editor = entry->editor;
if (editor) {
activateEditor(view, editor, flags);
......
......@@ -113,6 +113,11 @@ EditorView::EditorView(SplitterOrView *parentSplitterOrView, QWidget *parent) :
tl->addWidget(m_statusWidget);
}
// for the case of no document selected
QWidget *empty = new QWidget;
m_container->addWidget(empty);
m_widgetEditorMap.insert(empty, 0);
updateNavigatorActions();
}
......@@ -225,7 +230,7 @@ void EditorView::paintEvent(QPaintEvent *)
if (editorView != this)
return;
if (editorCount() > 0)
if (m_container->currentIndex() != 0) // so a document is selected
return;
// Discreet indication where an editor would be if there is none
......@@ -291,7 +296,7 @@ void EditorView::removeEditor(IEditor *editor)
IEditor *EditorView::currentEditor() const
{
if (m_editors.size() > 0)
if (m_editors.count() > 0)
return m_widgetEditorMap.value(m_container->currentWidget());
return 0;
}
......@@ -337,11 +342,11 @@ void EditorView::setParentSplitterOrView(SplitterOrView *splitterOrView)
void EditorView::setCurrentEditor(IEditor *editor)
{
if (!editor || m_container->count() <= 0
|| m_container->indexOf(editor->widget()) == -1) {
m_toolBar->updateEditorStatus(0);
if (!editor || m_container->indexOf(editor->widget()) == -1) {
QTC_CHECK(!editor);
m_toolBar->setCurrentEditor(0);
m_infoBarDisplay->setInfoBar(0);
QTC_CHECK(m_container->count() == 0);
m_container->setCurrentIndex(0);
return;
}
......@@ -518,6 +523,17 @@ SplitterOrView::SplitterOrView(Core::IEditor *editor)
m_layout->addWidget(m_view);
}
SplitterOrView::SplitterOrView(EditorView *view)
{
QTC_CHECK(view);
m_layout = new QStackedLayout(this);
m_layout->setSizeConstraint(QLayout::SetNoConstraint);
m_view = view;
m_view->setParentSplitterOrView(this);
m_splitter = 0;
m_layout->addWidget(m_view);
}
SplitterOrView::~SplitterOrView()
{
delete m_layout;
......@@ -591,34 +607,22 @@ void SplitterOrView::split(Qt::Orientation orientation)
m_splitter = new MiniSplitter(this);
m_splitter->setOrientation(orientation);
m_layout->addWidget(m_splitter);
m_layout->removeWidget(m_view);
EditorView *editorView = m_view;
m_view = 0;
EditorManager *em = ICore::editorManager();
Core::IEditor *e = m_view->currentEditor();
Core::IEditor *e = editorView->currentEditor();
SplitterOrView *view = 0;
SplitterOrView *otherView = 0;
if (e) {
foreach (IEditor *editor, m_view->editors())
m_view->removeEditor(editor);
m_splitter->addWidget((view = new SplitterOrView(e)));
if (e->duplicateSupported()) {
Core::IEditor *duplicate = em->duplicateEditor(e);
m_splitter->addWidget((otherView = new SplitterOrView(duplicate)));
} else {
m_splitter->addWidget((otherView = new SplitterOrView()));
}
} else {
m_splitter->addWidget((view = new SplitterOrView()));
m_splitter->addWidget((otherView = new SplitterOrView()));
}
Core::IEditor *duplicate = e && e->duplicateSupported() ? em->duplicateEditor(e) : 0;
m_splitter->addWidget((view = new SplitterOrView(duplicate)));
m_splitter->addWidget((otherView = new SplitterOrView(editorView)));
m_layout->setCurrentWidget(m_splitter);
view->view()->copyNavigationHistoryFrom(m_view);
view->view()->setCurrentEditor(view->view()->currentEditor());
otherView->view()->copyNavigationHistoryFrom(m_view);
otherView->view()->setCurrentEditor(otherView->view()->currentEditor());
view->view()->copyNavigationHistoryFrom(editorView);
view->view()->setCurrentEditor(duplicate);
if (orientation == Qt::Horizontal) {
view->view()->setCloseSplitIcon(QIcon(QLatin1String(Constants::ICON_CLOSE_SPLIT_LEFT)));
......@@ -628,16 +632,10 @@ void SplitterOrView::split(Qt::Orientation orientation)
otherView->view()->setCloseSplitIcon(QIcon(QLatin1String(Constants::ICON_CLOSE_SPLIT_BOTTOM)));
}
if (m_view) {
em->emptyView(m_view);
delete m_view;
m_view = 0;
}
if (e)
em->activateEditor(view->view(), e);
em->activateEditor(otherView->view(), e);
else
em->setCurrentView(view->view());
em->setCurrentView(otherView->view());
}
void SplitterOrView::unsplitAll()
......
......@@ -164,6 +164,7 @@ class SplitterOrView : public QWidget
Q_OBJECT
public:
explicit SplitterOrView(Core::IEditor *editor = 0);
explicit SplitterOrView(EditorView *view);
~SplitterOrView();
void split(Qt::Orientation orientation);
......
......@@ -103,7 +103,7 @@ int OpenEditorsModel::columnCount(const QModelIndex &parent) const
int OpenEditorsModel::rowCount(const QModelIndex &parent) const
{
if (!parent.isValid())
return d->m_editors.count();
return d->m_editors.count() + 1/*<no document>*/;
return 0;
}
......@@ -214,10 +214,11 @@ void OpenEditorsModel::removeEditor(const QString &fileName)
void OpenEditorsModel::removeEditor(int idx)
{
if (idx < 0 || idx >= d->m_editors.size())
if (idx < 0)
return;
QTC_ASSERT(idx < d->m_editors.size(), return);
IEditor *editor = d->m_editors.at(idx)->editor;
int row = idx;
int row = idx + 1/*<no document>*/;
beginRemoveRows(QModelIndex(), row, row);
d->m_editors.removeAt(idx);
endRemoveRows();
......@@ -229,7 +230,7 @@ void OpenEditorsModel::removeAllRestoredEditors()
{
for (int i = d->m_editors.count()-1; i >= 0; --i) {
if (!d->m_editors.at(i)->editor) {
int row = i;
int row = i + 1/*<no document>*/;
beginRemoveRows(QModelIndex(), row, row);
d->m_editors.removeAt(i);
endRemoveRows();
......@@ -286,21 +287,21 @@ void OpenEditorsModel::emitDataChanged(IEditor *editor)
int idx = findEditor(editor);
if (idx < 0)
return;
QModelIndex mindex = index(idx, 0);
QModelIndex mindex = index(idx + 1/*<no document>*/, 0);
emit dataChanged(mindex, mindex);
}
QModelIndex OpenEditorsModel::index(int row, int column, const QModelIndex &parent) const
{
Q_UNUSED(parent)
if (column < 0 || column > 1 || row < 0 || row >= d->m_editors.count())
if (column < 0 || column > 1 || row < 0 || row >= d->m_editors.count() + 1/*<no document>*/)
return QModelIndex();
return createIndex(row, column);
}
OpenEditorsModel::Entry *OpenEditorsModel::entryAtRow(int row) const
{
int editorIndex = row;
int editorIndex = row - 1/*<no document>*/;
if (editorIndex < 0)
return 0;
return d->m_editors[editorIndex];
......@@ -315,7 +316,7 @@ QVariant OpenEditorsModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || (index.column() != 0 && role < Qt::UserRole))
return QVariant();
int editorIndex = index.row();
int editorIndex = index.row() - 1/*<no document>*/;
if (editorIndex < 0) {
// <no document> entry
switch (role) {
......@@ -364,8 +365,8 @@ QVariant OpenEditorsModel::data(const QModelIndex &index, int role) const
int OpenEditorsModel::rowOfEditor(IEditor *editor) const
{
if (!editor)
return -1;
return findEditor(originalForDuplicate(editor));
return 0 /*<no document>*/;
return findEditor(originalForDuplicate(editor)) + 1/*<no document>*/;
}
QString OpenEditorsModel::displayNameForDocument(IDocument *document) const
......
......@@ -96,7 +96,9 @@ OpenEditorsWidget::OpenEditorsWidget()
setFrameStyle(QFrame::NoFrame);
setAttribute(Qt::WA_MacShowFocusRect, false);
EditorManager *em = EditorManager::instance();
setModel(em->openedEditorsModel());
m_model = new ProxyModel(this);
m_model->setSourceModel(em->openedEditorsModel());
setModel(m_model);
setSelectionMode(QAbstractItemView::SingleSelection);
setSelectionBehavior(QAbstractItemView::SelectRows);
header()->setStretchLastSection(false);
......@@ -125,7 +127,7 @@ OpenEditorsWidget::~OpenEditorsWidget()
void OpenEditorsWidget::updateCurrentItem(Core::IEditor *editor)
{
EditorManager *em = EditorManager::instance();
QModelIndex index = model()->index(em->openedEditorsModel()->rowOfEditor(editor), 0);
QModelIndex index = m_model->index(em->openedEditorsModel()->indexOfEditor(editor), 0);
if (!index.isValid()) {
clearSelection();
return;
......@@ -191,13 +193,13 @@ void OpenEditorsWidget::activateEditor(const QModelIndex &index)
{
selectionModel()->select(index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
EditorManager *em = EditorManager::instance();
em->activateEditorForEntry(em->openedEditorsModel()->entryAtRow(index.row()));
em->activateEditorForEntry(em->openedEditorsModel()->entryAtRow(m_model->mapToSource(index).row()));
}
void OpenEditorsWidget::closeEditor(const QModelIndex &index)
{
EditorManager *em = EditorManager::instance();
em->closeEditor(em->openedEditorsModel()->entryAtRow(index.row()));
em->closeEditor(em->openedEditorsModel()->entryAtRow(m_model->mapToSource(index).row()));
// work around selection changes
updateCurrentItem(EditorManager::currentEditor());
}
......@@ -207,7 +209,7 @@ void OpenEditorsWidget::contextMenuRequested(QPoint pos)
QMenu contextMenu;
QModelIndex editorIndex = indexAt(pos);
OpenEditorsModel::Entry *entry = EditorManager::instance()->openedEditorsModel()->entryAtRow(
editorIndex.row());
m_model->mapToSource(editorIndex).row());
EditorManager::instance()->addSaveAndCloseEditorActions(&contextMenu, entry);
contextMenu.addSeparator();
EditorManager::instance()->addNativeDirActions(&contextMenu, entry);
......@@ -252,3 +254,132 @@ OpenEditorsViewFactory::OpenEditorsViewFactory()
OpenEditorsViewFactory::~OpenEditorsViewFactory()
{
}
ProxyModel::ProxyModel(QObject *parent) : QAbstractProxyModel(parent)
{
}
QModelIndex ProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
{
// root
if (!sourceIndex.isValid())
return QModelIndex();
// hide the <no document>
int row = sourceIndex.row() - 1;
if (row < 0)
return QModelIndex();
return createIndex(row, sourceIndex.column());
}
QModelIndex ProxyModel::mapToSource(const QModelIndex &proxyIndex) const
{
if (!proxyIndex.isValid())
return QModelIndex();
// handle missing <no document>
return sourceModel()->index(proxyIndex.row() + 1, proxyIndex.column());
}
QModelIndex ProxyModel::index(int row, int column, const QModelIndex &parent) const
{
if (parent.isValid() || row < 0 || row >= sourceModel()->rowCount(mapToSource(parent)) - 1
|| column < 0 || column > 1)
return QModelIndex();
return createIndex(row, column);
}
QModelIndex ProxyModel::parent(const QModelIndex &child) const
{
Q_UNUSED(child)
return QModelIndex();
}
int ProxyModel::rowCount(const QModelIndex &parent) const
{
if (!parent.isValid())
return sourceModel()->rowCount(mapToSource(parent)) - 1;
return 0;
}
int ProxyModel::columnCount(const QModelIndex &parent) const
{
return sourceModel()->columnCount(mapToSource(parent));
}
void ProxyModel::setSourceModel(QAbstractItemModel *sm)
{
QAbstractItemModel *previousModel = sourceModel();
if (previousModel) {
disconnect(previousModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
this, SLOT(sourceDataChanged(QModelIndex,QModelIndex)));
disconnect(previousModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
this, SLOT(sourceRowsInserted(QModelIndex,int,int)));
disconnect(previousModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
this, SLOT(sourceRowsRemoved(QModelIndex,int,int)));
disconnect(previousModel, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
this, SLOT(sourceRowsAboutToBeInserted(QModelIndex,int,int)));
disconnect(previousModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
this, SLOT(sourceRowsAboutToBeRemoved(QModelIndex,int,int)));
}
QAbstractProxyModel::setSourceModel(sm);
if (sm) {
connect(sm, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
this, SLOT(sourceDataChanged(QModelIndex,QModelIndex)));
connect(sm, SIGNAL(rowsInserted(QModelIndex,int,int)),
this, SLOT(sourceRowsInserted(QModelIndex,int,int)));
connect(sm, SIGNAL(rowsRemoved(QModelIndex,int,int)),
this, SLOT(sourceRowsRemoved(QModelIndex,int,int)));
connect(sm, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
this, SLOT(sourceRowsAboutToBeInserted(QModelIndex,int,int)));
connect(sm, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
this, SLOT(sourceRowsAboutToBeRemoved(QModelIndex,int,int)));
}
}
#if QT_VERSION >= 0x050000
QModelIndex ProxyModel::sibling(int row, int column, const QModelIndex &idx) const
{
return QAbstractItemModel::sibling(row, column, idx);
}
#endif
void ProxyModel::sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
{
QModelIndex topLeftIndex = mapFromSource(topLeft);
if (!topLeftIndex.isValid())
topLeftIndex = index(0, topLeft.column());
QModelIndex bottomRightIndex = mapFromSource(bottomRight);
if (!bottomRightIndex.isValid())
bottomRightIndex = index(0, bottomRight.column());
emit dataChanged(topLeftIndex, bottomRightIndex);
}
void ProxyModel::sourceRowsRemoved(const QModelIndex &parent, int start, int end)
{
Q_UNUSED(parent)
Q_UNUSED(start)
Q_UNUSED(end)
endRemoveRows();
}
void ProxyModel::sourceRowsInserted(const QModelIndex &parent, int start, int end)
{
Q_UNUSED(parent)
Q_UNUSED(start)
Q_UNUSED(end)
endInsertRows();
}
void ProxyModel::sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
{
int realStart = parent.isValid() || start == 0 ? start : start - 1;
int realEnd = parent.isValid() || end == 0 ? end : end - 1;
beginRemoveRows(parent, realStart, realEnd);
}
void ProxyModel::sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end)
{
int realStart = parent.isValid() || start == 0 ? start : start - 1;
int realEnd = parent.isValid() || end == 0 ? end : end - 1;
beginInsertRows(parent, realStart, realEnd);
}
......@@ -32,6 +32,7 @@
#include <coreplugin/inavigationwidgetfactory.h>
#include <QAbstractProxyModel>
#include <QStyledItemDelegate>
#include <QTreeView>
......@@ -40,6 +41,34 @@ class IEditor;
namespace Internal {
class ProxyModel : public QAbstractProxyModel
{
Q_OBJECT
public:
explicit ProxyModel(QObject *parent = 0);
QModelIndex mapFromSource(const QModelIndex & sourceIndex) const;
QModelIndex mapToSource(const QModelIndex & proxyIndex) const;
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
QModelIndex parent(const QModelIndex &child) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
void setSourceModel(QAbstractItemModel *sourceModel);
#if QT_VERSION >= 0x050000
// QAbstractProxyModel::sibling is broken in Qt 5
QModelIndex sibling(int row, int column, const QModelIndex &idx) const;
#endif
private slots:
void sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
void sourceRowsRemoved(const QModelIndex &parent, int start, int end);
void sourceRowsInserted(const QModelIndex &parent, int start, int end);
void sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
void sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end);
};
class OpenEditorsDelegate : public QStyledItemDelegate
{
public:
......@@ -73,6 +102,7 @@ private:
using QAbstractItemView::closeEditor;
OpenEditorsDelegate *m_delegate;
ProxyModel *m_model;
};
class OpenEditorsViewFactory : public Core::INavigationWidgetFactory
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment