From 7d986f0486dc48b718a974682e7d37ecb2b12844 Mon Sep 17 00:00:00 2001 From: Eike Ziller <eike.ziller@digia.com> Date: Wed, 22 May 2013 16:00:26 +0200 Subject: [PATCH] Cycle through extra editor windows when cycling through splits Change-Id: I1bd5654d62b11456c35cc5bf1099e41fb3559bc7 Reviewed-by: David Schulz <david.schulz@digia.com> --- src/plugins/coreplugin/coreconstants.h | 2 +- .../editormanager/editormanager.cpp | 118 ++++++++++++++---- .../coreplugin/editormanager/editormanager.h | 7 +- .../coreplugin/editormanager/editorview.cpp | 4 +- src/plugins/cppeditor/cppeditor.cpp | 2 - src/plugins/cpptools/cpptoolsplugin.cpp | 2 +- src/plugins/fakevim/fakevimplugin.cpp | 2 +- src/plugins/texteditor/basetexteditor.cpp | 2 - 8 files changed, 103 insertions(+), 36 deletions(-) diff --git a/src/plugins/coreplugin/coreconstants.h b/src/plugins/coreplugin/coreconstants.h index 1bdc864a074..db0b96591fa 100644 --- a/src/plugins/coreplugin/coreconstants.h +++ b/src/plugins/coreplugin/coreconstants.h @@ -109,7 +109,7 @@ const char SPLIT_SIDE_BY_SIDE[] = "QtCreator.SplitSideBySide"; const char SPLIT_NEW_WINDOW[] = "QtCreator.SplitNewWindow"; const char REMOVE_CURRENT_SPLIT[] = "QtCreator.RemoveCurrentSplit"; const char REMOVE_ALL_SPLITS[] = "QtCreator.RemoveAllSplits"; -const char GOTO_OTHER_SPLIT[] = "QtCreator.GotoOtherSplit"; +const char GOTO_NEXT_SPLIT[] = "QtCreator.GotoOtherSplit"; const char CLOSE[] = "QtCreator.Close"; const char CLOSE_ALTERNATIVE[] = "QtCreator.Close_Alternative"; // temporary, see QTCREATORBUG-72 const char CLOSEALL[] = "QtCreator.CloseAll"; diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp index 88762f1f298..b31a5d131b5 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.cpp +++ b/src/plugins/coreplugin/editormanager/editormanager.cpp @@ -196,7 +196,7 @@ struct EditorManagerPrivate QAction *m_splitNewWindowAction; QAction *m_removeCurrentSplitAction; QAction *m_removeAllSplitsAction; - QAction *m_gotoOtherSplitAction; + QAction *m_gotoNextSplitAction; QAction *m_saveCurrentEditorContextAction; QAction *m_saveAsCurrentEditorContextAction; @@ -399,11 +399,11 @@ EditorManager::EditorManager(QWidget *parent) : mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT); connect(d->m_removeAllSplitsAction, SIGNAL(triggered()), this, SLOT(removeAllSplits())); - d->m_gotoOtherSplitAction = new QAction(tr("Go to Next Split"), this); - cmd = ActionManager::registerAction(d->m_gotoOtherSplitAction, Constants::GOTO_OTHER_SPLIT, editManagerContext); + d->m_gotoNextSplitAction = new QAction(tr("Go to Next Split"), this); + cmd = ActionManager::registerAction(d->m_gotoNextSplitAction, Constants::GOTO_NEXT_SPLIT, editManagerContext); cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("Meta+E,o") : tr("Ctrl+E,o"))); mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT); - connect(d->m_gotoOtherSplitAction, SIGNAL(triggered()), this, SLOT(gotoOtherSplit())); + connect(d->m_gotoNextSplitAction, SIGNAL(triggered()), this, SLOT(gotoNextSplit())); ActionContainer *medit = ActionManager::actionContainer(Constants::M_EDIT); ActionContainer *advancedMenu = ActionManager::createMenu(Constants::M_EDIT_ADVANCED); @@ -604,13 +604,20 @@ EditorView *EditorManager::viewForEditor(IEditor *editor) return 0; } -SplitterOrView *EditorManager::findRoot(EditorView *view) +SplitterOrView *EditorManager::findRoot(const EditorView *view, int *rootIndex) { SplitterOrView *current = view->parentSplitterOrView(); - while (current && !m_instance->d->m_root.contains(current)) { + while (current) { + int index = m_instance->d->m_root.indexOf(current); + if (index >= 0) { + if (rootIndex) + *rootIndex = index; + return current; + } current = current->findParentSplitter(); } - return current; + QTC_CHECK(false); // we should never have views without a root + return 0; } QList<IEditor *> EditorManager::editorsForFileName(const QString &filename) const @@ -1151,6 +1158,18 @@ void EditorManager::activateEditorForIndex(Internal::EditorView *view, const QMo d->m_editorModel->removeEditor(index); } +void EditorManager::activateView(EditorView *view) +{ + QTC_ASSERT(view, return); + if (IEditor *editor = view->currentEditor()) { + setCurrentEditor(editor, true); + editor->widget()->setFocus(); + ICore::raiseWindow(editor->widget()); + } else { + setCurrentView(view); + } +} + Core::IEditor *EditorManager::placeEditor(Core::Internal::EditorView *view, Core::IEditor *editor) { Q_ASSERT(view && editor); @@ -1398,11 +1417,8 @@ IEditor *EditorManager::openEditor(const QString &fileName, const Id &editorId, fileName, editorId, flags, newEditor); } -IEditor *EditorManager::openEditorInNextSplit(const QString &fileName, const Id &editorId, OpenEditorFlags flags, bool *newEditor) +IEditor *EditorManager::openEditorInOtherSplit(const QString &fileName, const Id &editorId, OpenEditorFlags flags, bool *newEditor) { - if (!m_instance->hasSplitter()) - m_instance->splitSideBySide(); - m_instance->gotoOtherSplit(); return m_instance->openEditor(m_instance->currentEditorView(), fileName, editorId, flags, newEditor); @@ -1973,7 +1989,7 @@ void EditorManager::updateActions() bool hasSplitter = parentSplitter && parentSplitter->isSplitter(); d->m_removeCurrentSplitAction->setEnabled(hasSplitter); d->m_removeAllSplitsAction->setEnabled(hasSplitter); - d->m_gotoOtherSplitAction->setEnabled(hasSplitter); + d->m_gotoNextSplitAction->setEnabled(hasSplitter || d->m_root.size() > 1); } void EditorManager::setCloseSplitEnabled(SplitterOrView *splitterOrView, bool enable) @@ -2010,7 +2026,8 @@ QList<IEditor*> EditorManager::visibleEditors() const if (view->currentEditor()) editors.append(view->currentEditor()); view = view->findNextView(); - } while (view && view != firstView); + QTC_ASSERT(view != firstView, break); // we start with firstView and shouldn't have cycles + } while (view); } } else { if (root->editor()) @@ -2375,26 +2392,77 @@ void EditorManager::removeAllSplits() root->unsplitAll(); } +/*! + * Moves focus to the next split, cycling through windows. + */ +void EditorManager::gotoNextSplit() +{ + EditorView *view = currentEditorView(); + if (!view) + return; + EditorView *nextView = view->findNextView(); + if (!nextView) { + // we are in the "last" view in this root + int rootIndex = -1; + SplitterOrView *root = findRoot(view, &rootIndex); + QTC_ASSERT(root, return); + QTC_ASSERT(rootIndex >= 0 && rootIndex < d->m_root.size(), return); + // find next root. this might be the same root if there's only one. + int nextRootIndex = rootIndex + 1; + if (nextRootIndex >= d->m_root.size()) + nextRootIndex = 0; + nextView = d->m_root.at(nextRootIndex)->findFirstView(); + QTC_CHECK(nextView); + } + + if (nextView) + activateView(nextView); +} + +/*! + * Moves focus to "other" split, possibly creating a split if necessary. + * If there's no split and no other window, a side-by-side split is created. + * If the current window is split, focus is moved to the next split within this window, cycling. + * If the current window is not split, focus is moved to the next window. + */ void EditorManager::gotoOtherSplit() { EditorView *view = currentEditorView(); if (!view) return; - SplitterOrView *root = findRoot(view); - QTC_ASSERT(root, return); - if (!root->isSplitter()) - splitSideBySide(); - - view = view->findNextView(); - if (view) { - if (IEditor *editor = view->currentEditor()) { - setCurrentEditor(editor, true); - editor->widget()->setFocus(); - ICore::raiseWindow(editor->widget()); + EditorView *nextView = view->findNextView(); + if (!nextView) { + // we are in the "last" view in this root + int rootIndex = -1; + SplitterOrView *root = findRoot(view, &rootIndex); + QTC_ASSERT(root, return); + QTC_ASSERT(rootIndex >= 0 && rootIndex < d->m_root.size(), return); + // stay in same window if it is split + if (root->isSplitter()) { + nextView = root->findFirstView(); + QTC_CHECK(nextView != view); } else { - setCurrentView(view); + // find next root. this might be the same root if there's only one. + int nextRootIndex = rootIndex + 1; + if (nextRootIndex >= d->m_root.size()) + nextRootIndex = 0; + nextView = d->m_root.at(nextRootIndex)->findFirstView(); + QTC_CHECK(nextView); + // if we had only one root with only one view, we end up at the startpoint + // in that case we need to split + if (nextView == view) { + QTC_CHECK(!root->isSplitter()); + splitSideBySide(); // that deletes 'view' + view = root->findFirstView(); + nextView = view->findNextView(); + QTC_CHECK(nextView != view); + QTC_CHECK(nextView); + } } } + + if (nextView) + activateView(nextView); } qint64 EditorManager::maxTextFileSize() diff --git a/src/plugins/coreplugin/editormanager/editormanager.h b/src/plugins/coreplugin/editormanager/editormanager.h index 1dabf2f3685..74297304602 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.h +++ b/src/plugins/coreplugin/editormanager/editormanager.h @@ -117,7 +117,7 @@ public: static QString splitLineNumber(QString *fileName); static IEditor *openEditor(const QString &fileName, const Id &editorId = Id(), OpenEditorFlags flags = 0, bool *newEditor = 0); - static IEditor *openEditorInNextSplit(const QString &fileName, const Id &editorId = Id(), + static IEditor *openEditorInOtherSplit(const QString &fileName, const Id &editorId = Id(), OpenEditorFlags flags = 0, bool *newEditor = 0); static IEditor *openEditorWithContents(const Id &editorId, QString *titlePattern = 0, const QString &contents = QString()); @@ -234,6 +234,8 @@ private slots: void rootDestroyed(QObject *root); void setCurrentEditorFromContextChange(); + void gotoNextSplit(); + public slots: void goBackInNavigationHistory(); void goForwardInNavigationHistory(); @@ -257,6 +259,7 @@ private: IEditor *duplicateEditor(IEditor *editor); IEditor *activateEditor(Internal::EditorView *view, IEditor *editor, OpenEditorFlags flags = 0); void activateEditorForIndex(Internal::EditorView *view, const QModelIndex &index, OpenEditorFlags = 0); + void activateView(Internal::EditorView *view); IEditor *openEditor(Internal::EditorView *view, const QString &fileName, const Id &id = Id(), OpenEditorFlags flags = 0, bool *newEditor = 0); @@ -264,7 +267,7 @@ private: void setCurrentView(Internal::EditorView *view); Internal::EditorView *currentEditorView() const; static Internal::EditorView *viewForEditor(IEditor *editor); - static Internal::SplitterOrView *findRoot(Internal::EditorView *view); + static Internal::SplitterOrView *findRoot(const Internal::EditorView *view, int *rootIndex = 0); void closeEditor(IEditor *editor); void closeDuplicate(IEditor *editor); diff --git a/src/plugins/coreplugin/editormanager/editorview.cpp b/src/plugins/coreplugin/editormanager/editorview.cpp index 87e4ecee5aa..30cbb9c0233 100644 --- a/src/plugins/coreplugin/editormanager/editorview.cpp +++ b/src/plugins/coreplugin/editormanager/editorview.cpp @@ -144,8 +144,8 @@ EditorView *EditorView::findNextView() current = parent; parent = current->findParentSplitter(); } - // current has no parent, so just take the very first view - return current->findFirstView(); + // current has no parent, so we are at the top and there is no "next" view + return 0; } void EditorView::closeView() diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index dd42d6cb7f2..00e6a932378 100644 --- a/src/plugins/cppeditor/cppeditor.cpp +++ b/src/plugins/cppeditor/cppeditor.cpp @@ -1994,8 +1994,6 @@ bool CPPEditorWidget::openCppEditorAt(const Link &link, bool inNextSplit) Core::EditorManager *editorManager = Core::EditorManager::instance(); if (inNextSplit) { - if (!editorManager->hasSplitter()) - editorManager->splitSideBySide(); editorManager->gotoOtherSplit(); } else if (baseTextDocument()->fileName() == link.targetFileName) { editorManager->addCurrentPositionToNavigationHistory(); diff --git a/src/plugins/cpptools/cpptoolsplugin.cpp b/src/plugins/cpptools/cpptoolsplugin.cpp index 7f70a37640c..66e8a689660 100644 --- a/src/plugins/cpptools/cpptoolsplugin.cpp +++ b/src/plugins/cpptools/cpptoolsplugin.cpp @@ -164,7 +164,7 @@ void CppToolsPlugin::switchHeaderSourceInNextSplit() QString otherFile = correspondingHeaderOrSource( Core::EditorManager::currentEditor()->document()->fileName()); if (!otherFile.isEmpty()) - Core::EditorManager::openEditorInNextSplit(otherFile); + Core::EditorManager::openEditorInOtherSplit(otherFile); } static QStringList findFilesInProject(const QString &name, diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp index 235696eda64..3d9c30356a8 100644 --- a/src/plugins/fakevim/fakevimplugin.cpp +++ b/src/plugins/fakevim/fakevimplugin.cpp @@ -1324,7 +1324,7 @@ void FakeVimPluginPrivate::windowCommand(const QString &map, int count) else if (key == _("S") || key == _("<C-S>")) triggerAction(Core::Constants::SPLIT); else if (key == _("W") || key == _("<C-W>")) - triggerAction(Core::Constants::GOTO_OTHER_SPLIT); + triggerAction(Core::Constants::GOTO_NEXT_SPLIT); else if (key.contains(_("RIGHT")) || key == _("L") || key == _("<S-L>")) moveSomewhere(&moveRightWeight, key == _("<S-L>") ? -1 : count); else if (key.contains(_("LEFT")) || key == _("H") || key == _("<S-H>")) diff --git a/src/plugins/texteditor/basetexteditor.cpp b/src/plugins/texteditor/basetexteditor.cpp index 2b3f5eef3ab..3984a4ca9b7 100644 --- a/src/plugins/texteditor/basetexteditor.cpp +++ b/src/plugins/texteditor/basetexteditor.cpp @@ -4910,8 +4910,6 @@ bool BaseTextEditorWidget::openLink(const Link &link, bool inNextSplit) Core::EditorManager *editorManager = Core::EditorManager::instance(); if (inNextSplit) { - if (!editorManager->hasSplitter()) - editorManager->splitSideBySide(); editorManager->gotoOtherSplit(); } else if (baseTextDocument()->fileName() == link.targetFileName) { editorManager->addCurrentPositionToNavigationHistory(); -- GitLab