Fix closing editor with ctrl+w or "x" or File > Close

If there are other editors on the document visible in some split, it
should not close the document, but only the editor.

Task-number: QTCREATORBUG-9346
Change-Id: Idce1ae2f518d4c6e875d86f9831d41c46c06361c
Reviewed-by: Eike Ziller <eike.ziller@digia.com>
This commit is contained in:
Eike Ziller
2014-08-19 16:15:57 +02:00
parent 8213a88d3e
commit 6772ba622a
15 changed files with 136 additions and 62 deletions
+2 -1
View File
@@ -691,7 +691,8 @@ void BazaarPlugin::commitFromEditor()
{
// Close the submit editor
m_submitActionTriggered = true;
EditorManager::closeEditor(submitEditor());
QTC_ASSERT(submitEditor(), return);
EditorManager::closeDocument(submitEditor()->document());
}
void BazaarPlugin::uncommit()
+2 -1
View File
@@ -1475,7 +1475,8 @@ void ClearCasePlugin::describe(const QString &source, const QString &changeNr)
void ClearCasePlugin::checkInSelected()
{
m_submitActionTriggered = true;
EditorManager::closeEditor(submitEditor());
QTC_ASSERT(submitEditor(), return);
EditorManager::closeDocument(submitEditor()->document());
}
QString ClearCasePlugin::runCleartoolSync(const QString &workingDir,
@@ -322,7 +322,8 @@ void EditorManagerPrivate::init()
cmd->setAttribute(Core::Command::CA_UpdateText);
cmd->setDescription(m_closeCurrentEditorAction->text());
mfile->addAction(cmd, Constants::G_FILE_CLOSE);
connect(m_closeCurrentEditorAction, SIGNAL(triggered()), m_instance, SLOT(closeEditor()));
connect(m_closeCurrentEditorAction, SIGNAL(triggered()),
m_instance, SLOT(slotCloseCurrentEditorOrDocument()));
if (Utils::HostOsInfo::isWindowsHost()) {
// workaround for QTCREATORBUG-72
@@ -330,7 +331,7 @@ void EditorManagerPrivate::init()
cmd = ActionManager::registerAction(action, Constants::CLOSE_ALTERNATIVE, editManagerContext);
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+F4")));
cmd->setDescription(EditorManager::tr("Close"));
connect(action, SIGNAL(triggered()), m_instance, SLOT(closeEditor()));
connect(action, SIGNAL(triggered()), m_instance, SLOT(slotCloseCurrentEditorOrDocument()));
}
// Close All Action
@@ -1023,6 +1024,20 @@ void EditorManagerPrivate::activateEditorForEntry(EditorView *view, DocumentMode
DocumentModel::removeEntry(entry);
}
void EditorManagerPrivate::closeEditorOrDocument(IEditor *editor)
{
QTC_ASSERT(editor, return);
QList<IEditor *> visible = EditorManager::visibleEditors();
if (Utils::contains(visible,
[&editor](IEditor *other) {
return editor != other && other->document() == editor->document();
})) {
EditorManager::closeEditor(editor);
} else {
EditorManager::closeDocument(editor->document());
}
}
void EditorManagerPrivate::activateView(EditorView *view)
{
QTC_ASSERT(view, return);
@@ -1597,10 +1612,14 @@ void EditorManagerPrivate::revertToSavedFromContextMenu()
void EditorManagerPrivate::closeEditorFromContextMenu()
{
if (d->m_contextMenuEditor) {
closeEditorOrDocument(d->m_contextMenuEditor);
} else {
IDocument *document = d->m_contextMenuEntry ? d->m_contextMenuEntry->document : 0;
if (document)
EditorManager::closeDocument(document);
}
}
void EditorManagerPrivate::closeOtherDocumentsFromContextMenu()
{
@@ -1856,12 +1875,12 @@ void EditorManager::closeOtherDocuments(IDocument *document)
}
// SLOT connected to action
void EditorManager::closeEditor()
void EditorManager::slotCloseCurrentEditorOrDocument()
{
if (!d->m_currentEditor)
return;
addCurrentPositionToNavigationHistory();
closeEditor(d->m_currentEditor);
d->closeEditorOrDocument(d->m_currentEditor);
}
void EditorManager::closeOtherDocuments()
@@ -1878,10 +1897,12 @@ static void assignAction(QAction *self, QAction *other)
self->setIconVisibleInMenu(other->isIconVisibleInMenu());
}
void EditorManager::addSaveAndCloseEditorActions(QMenu *contextMenu, DocumentModel::Entry *entry)
void EditorManager::addSaveAndCloseEditorActions(QMenu *contextMenu, DocumentModel::Entry *entry,
IEditor *editor)
{
QTC_ASSERT(contextMenu, return);
d->m_contextMenuEntry = entry;
d->m_contextMenuEditor = editor;
const QString filePath = entry ? entry->fileName() : QString();
const bool copyActionsEnabled = !filePath.isEmpty();
@@ -1929,6 +1950,7 @@ void EditorManager::addSaveAndCloseEditorActions(QMenu *contextMenu, DocumentMod
void EditorManager::addNativeDirAndOpenWithActions(QMenu *contextMenu, DocumentModel::Entry *entry)
{
QTC_ASSERT(contextMenu, return);
d->m_contextMenuEntry = entry;
bool enabled = entry && !entry->fileName().isEmpty();
d->m_openGraphicalShellAction->setEnabled(enabled);
d->m_openTerminalAction->setEnabled(enabled);
@@ -1980,13 +2002,18 @@ bool EditorManager::closeEditors(const QList<IEditor*> &editorsToClose, bool ask
{
if (editorsToClose.isEmpty())
return true;
bool closingFailed = false;
// close Editor History list
EditorManagerPrivate::windowPopup()->setVisible(false);
EditorView *currentView = EditorManagerPrivate::currentEditorView();
bool closingFailed = false;
// go through all editors to close and
// 1. ask all core listeners to check whether the editor can be closed
// 2. keep track of the document and all the editors that might remain open for it
QSet<IEditor*> acceptedEditors;
QSet<IDocument *> acceptedDocuments;
//ask all core listeners to check whether the editor can be closed
QMap<IDocument *, QList<IEditor *> > documentMap;
const QList<ICoreListener *> listeners =
ExtensionSystem::PluginManager::getObjects<ICoreListener>();
foreach (IEditor *editor, editorsToClose) {
@@ -1999,32 +2026,40 @@ bool EditorManager::closeEditors(const QList<IEditor*> &editorsToClose, bool ask
}
}
if (editorAccepted) {
acceptedEditors += DocumentModel::editorsForDocument(editor->document()).toSet();
acceptedDocuments.insert(editor->document());
}
}
if (acceptedEditors.isEmpty())
return false;
//ask whether to save modified files
if (askAboutModifiedEditors) {
bool cancelled = false;
QList<IDocument *> list;
DocumentManager::saveModifiedDocuments(acceptedDocuments.toList(), QString(), &cancelled,
QString(), 0, &list);
if (cancelled)
return false;
if (!list.isEmpty()) {
closingFailed = true;
acceptedDocuments.subtract(list.toSet());
QSet<IEditor*> skipSet = DocumentModel::editorsForDocuments(list).toSet();
acceptedEditors = acceptedEditors.subtract(skipSet);
acceptedEditors.insert(editor);
IDocument *document = editor->document();
if (!documentMap.contains(document)) // insert the document to track
documentMap.insert(document, DocumentModel::editorsForDocument(document));
// keep track that we'll close this editor for the document
documentMap[document].removeAll(editor);
}
}
if (acceptedEditors.isEmpty())
return false;
// close Editor History list
EditorManagerPrivate::windowPopup()->setVisible(false);
//ask whether to save modified documents that we are about to close
if (askAboutModifiedEditors) {
// Check for which documents we will close all editors, and therefore might have to ask the user
QList<IDocument *> documentsToClose;
for (auto i = documentMap.constBegin(); i != documentMap.constEnd(); ++i) {
if (i.value().isEmpty())
documentsToClose.append(i.key());
}
bool cancelled = false;
QList<IDocument *> rejectedList;
DocumentManager::saveModifiedDocuments(documentsToClose, QString(), &cancelled,
QString(), 0, &rejectedList);
if (cancelled)
return false;
if (!rejectedList.isEmpty()) {
closingFailed = true;
QSet<IEditor*> skipSet = DocumentModel::editorsForDocuments(rejectedList).toSet();
acceptedEditors = acceptedEditors.subtract(skipSet);
}
}
if (acceptedEditors.isEmpty())
return false;
QList<EditorView*> closedViews;
@@ -2051,6 +2086,16 @@ bool EditorManager::closeEditors(const QList<IEditor*> &editorsToClose, bool ask
}
}
// TODO doesn't work as expected with multiple areas in main window and some other cases
// instead each view should have its own file history and handle solely themselves
// which editor is shown if their current editor closes
EditorView *forceViewToShowEditor = 0;
if (!closedViews.isEmpty() && visibleEditors().isEmpty()) {
if (closedViews.contains(currentView))
forceViewToShowEditor = currentView;
else
forceViewToShowEditor = closedViews.first();
}
bool currentViewHandled = false;
foreach (EditorView *view, closedViews) {
OpenEditorFlags flags;
@@ -2059,11 +2104,11 @@ bool EditorManager::closeEditors(const QList<IEditor*> &editorsToClose, bool ask
else
flags = OpenEditorFlags(DoNotChangeCurrentEditor);
IEditor *newCurrent = view->currentEditor();
if (!newCurrent)
if (!newCurrent && forceViewToShowEditor == view)
newCurrent = EditorManagerPrivate::pickUnusedEditor();
if (newCurrent) {
EditorManagerPrivate::activateEditor(view, newCurrent, flags);
} else {
} else if (forceViewToShowEditor == view) {
DocumentModel::Entry *entry = DocumentModel::firstRestoredEntry();
if (entry) {
EditorManagerPrivate::activateEditorForEntry(view, entry, flags);
@@ -2363,9 +2408,9 @@ bool EditorManager::closeDocument(IDocument *document, bool askAboutModifiedEdit
return closeDocuments(QList<IDocument *>() << document, askAboutModifiedEditors);
}
bool EditorManager::closeDocuments(const QList<IDocument *> &document, bool askAboutModifiedEditors)
bool EditorManager::closeDocuments(const QList<IDocument *> &documents, bool askAboutModifiedEditors)
{
return m_instance->closeEditors(DocumentModel::editorsForDocuments(document), askAboutModifiedEditors);
return m_instance->closeEditors(DocumentModel::editorsForDocuments(documents), askAboutModifiedEditors);
}
void EditorManager::addCurrentPositionToNavigationHistory(IEditor *editor, const QByteArray &saveState)
@@ -167,7 +167,8 @@ public:
static void setWindowTitleAdditionHandler(WindowTitleHandler handler);
static void setWindowTitleVcsTopicHandler(WindowTitleHandler handler);
static void addSaveAndCloseEditorActions(QMenu *contextMenu, DocumentModel::Entry *entry);
static void addSaveAndCloseEditorActions(QMenu *contextMenu, DocumentModel::Entry *entry,
IEditor *editor = 0);
static void addNativeDirAndOpenWithActions(QMenu *contextMenu, DocumentModel::Entry *entry);
signals:
@@ -184,7 +185,7 @@ public slots:
static void saveDocumentAs();
static void revertToSaved();
static bool closeAllEditors(bool askAboutModifiedEditors = true);
static void closeEditor();
static void slotCloseCurrentEditorOrDocument();
static void closeOtherDocuments();
static void splitSideBySide();
static void gotoOtherSplit();
@@ -82,6 +82,9 @@ public:
EditorManager::OpenEditorFlags flags = 0);
static void activateEditorForEntry(EditorView *view, DocumentModel::Entry *entry,
EditorManager::OpenEditorFlags flags = EditorManager::NoFlags);
/* closes the document if there is no other editor on the document visible */
static void closeEditorOrDocument(IEditor *editor);
static EditorView *viewForEditor(IEditor *editor);
static void setCurrentView(EditorView *view);
@@ -214,6 +217,7 @@ private:
QAction *m_openTerminalAction;
QAction *m_findInDirectoryAction;
DocumentModel::Entry *m_contextMenuEntry;
IEditor *m_contextMenuEditor;
OpenEditorsWindow *m_windowPopup;
EditorClosingCoreListener *m_coreListener;
@@ -76,12 +76,14 @@ EditorView::EditorView(SplitterOrView *parentSplitterOrView, QWidget *parent) :
{
connect(m_toolBar, SIGNAL(goBackClicked()), this, SLOT(goBackInNavigationHistory()));
connect(m_toolBar, SIGNAL(goForwardClicked()), this, SLOT(goForwardInNavigationHistory()));
connect(m_toolBar, SIGNAL(closeClicked()), this, SLOT(closeView()));
connect(m_toolBar, SIGNAL(closeClicked()), this, SLOT(closeCurrentEditor()));
connect(m_toolBar, SIGNAL(listSelectionActivated(int)), this, SLOT(listSelectionActivated(int)));
connect(m_toolBar, SIGNAL(horizontalSplitClicked()), this, SLOT(splitHorizontally()));
connect(m_toolBar, SIGNAL(verticalSplitClicked()), this, SLOT(splitVertically()));
connect(m_toolBar, SIGNAL(splitNewWindowClicked()), this, SLOT(splitNewWindow()));
connect(m_toolBar, SIGNAL(closeSplitClicked()), this, SLOT(closeSplit()));
connect(m_toolBar, &EditorToolBar::listContextMenuRequested,
this, &EditorView::showListContextMenu);
tl->addWidget(m_toolBar);
}
@@ -159,11 +161,11 @@ EditorView *EditorView::findNextView()
return 0;
}
void EditorView::closeView()
void EditorView::closeCurrentEditor()
{
IEditor *editor = currentEditor();
if (editor)
EditorManager::closeEditor(editor);
EditorManagerPrivate::closeEditorOrDocument(editor);
}
void EditorView::showEditorStatusBar(const QString &id,
@@ -311,6 +313,18 @@ void EditorView::listSelectionActivated(int index)
EditorManagerPrivate::activateEditorForEntry(this, DocumentModel::entryAtRow(index));
}
void EditorView::showListContextMenu(QPoint pos)
{
IEditor *editor = currentEditor();
DocumentModel::Entry entry;
entry.document = editor ? editor->document() : 0;
QMenu menu;
EditorManager::addSaveAndCloseEditorActions(&menu, &entry, editor);
menu.addSeparator();
EditorManager::addNativeDirAndOpenWithActions(&menu, &entry);
menu.exec(pos);
}
void EditorView::splitHorizontally()
{
if (m_parentSplitterOrView)
@@ -112,8 +112,9 @@ protected:
void focusInEvent(QFocusEvent *);
private slots:
void closeView();
void closeCurrentEditor();
void listSelectionActivated(int index);
void showListContextMenu(QPoint pos);
void splitHorizontally();
void splitVertically();
void splitNewWindow();
+10 -9
View File
@@ -233,12 +233,8 @@ void EditorToolBar::setCloseSplitIcon(const QIcon &icon)
void EditorToolBar::closeEditor()
{
IEditor *current = EditorManager::currentEditor();
if (!current)
return;
if (d->m_isStandalone)
EditorManager::closeEditor(current);
EditorManager::slotCloseCurrentEditorOrDocument();
emit closeClicked();
}
@@ -314,13 +310,18 @@ void EditorToolBar::changeActiveEditor(int row)
void EditorToolBar::listContextMenu(QPoint pos)
{
DocumentModel::Entry *entry = DocumentModel::entryAtRow(
d->m_editorList->currentIndex());
if (d->m_isStandalone) {
IEditor *editor = EditorManager::currentEditor();
DocumentModel::Entry entry;
entry.document = editor ? editor->document() : 0;
QMenu menu;
EditorManager::addSaveAndCloseEditorActions(&menu, entry);
EditorManager::addSaveAndCloseEditorActions(&menu, &entry, editor);
menu.addSeparator();
EditorManager::addNativeDirAndOpenWithActions(&menu, entry);
EditorManager::addNativeDirAndOpenWithActions(&menu, &entry);
menu.exec(d->m_editorList->mapToGlobal(pos));
} else {
emit listContextMenuRequested(d->m_editorList->mapToGlobal(pos));
}
}
void EditorToolBar::makeEditorWritable()
+1
View File
@@ -93,6 +93,7 @@ signals:
void splitNewWindowClicked();
void closeSplitClicked();
void listSelectionActivated(int row);
void listContextMenuRequested(QPoint globalpos);
private slots:
void updateEditorListSelection(Core::IEditor *newSelection);
+2 -1
View File
@@ -1131,7 +1131,8 @@ bool CvsPlugin::describe(const QString &repositoryPath,
void CvsPlugin::submitCurrentLog()
{
m_submitActionTriggered = true;
EditorManager::closeEditor(submitEditor());
QTC_ASSERT(submitEditor(), return);
EditorManager::closeDocument(submitEditor()->document());
}
// Run CVS. At this point, file arguments must be relative to
+2 -1
View File
@@ -1034,7 +1034,8 @@ void GitPlugin::submitCurrentLog()
{
// Close the submit editor
m_submitActionTriggered = true;
EditorManager::closeEditor(submitEditor());
QTC_ASSERT(submitEditor(), return);
EditorManager::closeDocument(submitEditor()->document());
}
bool GitPlugin::submitEditorAboutToClose()
+2 -1
View File
@@ -612,7 +612,8 @@ void MercurialPlugin::commitFromEditor()
{
// Close the submit editor
m_submitActionTriggered = true;
Core::EditorManager::closeEditor(submitEditor());
QTC_ASSERT(submitEditor(), return);
Core::EditorManager::closeDocument(submitEditor()->document());
}
bool MercurialPlugin::submitEditorAboutToClose()
+2 -1
View File
@@ -1329,7 +1329,8 @@ void PerforcePlugin::describe(const QString & source, const QString &n)
void PerforcePlugin::submitCurrentLog()
{
m_submitActionTriggered = true;
EditorManager::closeEditor(submitEditor());
QTC_ASSERT(submitEditor(), return);
EditorManager::closeDocument(submitEditor()->document());
}
void PerforcePlugin::cleanCommitMessageFile()
+1 -1
View File
@@ -92,7 +92,7 @@ void ShortCutManager::registerActions(const Core::Context &qmlDesignerMainContex
//Close Editor
Core::ActionManager::registerAction(&m_closeCurrentEditorAction, Core::Constants::CLOSE, qmlDesignerMainContext);
connect(&m_closeCurrentEditorAction, SIGNAL(triggered()), em, SLOT(closeEditor()));
connect(&m_closeCurrentEditorAction, SIGNAL(triggered()), em, SLOT(slotCloseCurrentEditorOrDocument()));
//Close All
Core::ActionManager::registerAction(&m_closeAllEditorsAction, Core::Constants::CLOSEALL, qmlDesignerMainContext);
+2 -1
View File
@@ -990,7 +990,8 @@ void SubversionPlugin::slotDescribe()
void SubversionPlugin::submitCurrentLog()
{
m_submitActionTriggered = true;
EditorManager::closeEditor(submitEditor());
QTC_ASSERT(submitEditor(), return);
EditorManager::closeDocument(submitEditor()->document());
}
SubversionResponse