Commit 6772ba62 authored by Eike Ziller's avatar Eike Ziller

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: default avatarEike Ziller <eike.ziller@digia.com>
parent 8213a88d
......@@ -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()
......
......@@ -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,9 +1612,13 @@ void EditorManagerPrivate::revertToSavedFromContextMenu()
void EditorManagerPrivate::closeEditorFromContextMenu()
{
IDocument *document = d->m_contextMenuEntry ? d->m_contextMenuEntry->document : 0;
if (document)
EditorManager::closeDocument(document);
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,33 +2026,41 @@ bool EditorManager::closeEditors(const QList<IEditor*> &editorsToClose, bool ask
}
}
if (editorAccepted) {
acceptedEditors += DocumentModel::editorsForDocument(editor->document()).toSet();
acceptedDocuments.insert(editor->document());
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;
//ask whether to save modified files
//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 *> list;
DocumentManager::saveModifiedDocuments(acceptedDocuments.toList(), QString(), &cancelled,
QString(), 0, &list);
QList<IDocument *> rejectedList;
DocumentManager::saveModifiedDocuments(documentsToClose, QString(), &cancelled,
QString(), 0, &rejectedList);
if (cancelled)
return false;
if (!list.isEmpty()) {
if (!rejectedList.isEmpty()) {
closingFailed = true;
acceptedDocuments.subtract(list.toSet());
QSet<IEditor*> skipSet = DocumentModel::editorsForDocuments(list).toSet();
QSet<IEditor*> skipSet = DocumentModel::editorsForDocuments(rejectedList).toSet();
acceptedEditors = acceptedEditors.subtract(skipSet);
}
}
if (acceptedEditors.isEmpty())
return false;
// close Editor History list
EditorManagerPrivate::windowPopup()->setVisible(false);
QList<EditorView*> closedViews;
// remove the editors
......@@ -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();
......
......@@ -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());
QMenu menu;
EditorManager::addSaveAndCloseEditorActions(&menu, entry);
menu.addSeparator();
EditorManager::addNativeDirAndOpenWithActions(&menu, entry);
menu.exec(d->m_editorList->mapToGlobal(pos));
if (d->m_isStandalone) {
IEditor *editor = EditorManager::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(d->m_editorList->mapToGlobal(pos));
} else {
emit listContextMenuRequested(d->m_editorList->mapToGlobal(pos));
}
}
void EditorToolBar::makeEditorWritable()
......
......@@ -93,6 +93,7 @@ signals:
void splitNewWindowClicked();
void closeSplitClicked();
void listSelectionActivated(int row);
void listContextMenuRequested(QPoint globalpos);
private slots:
void updateEditorListSelection(Core::IEditor *newSelection);
......
......@@ -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
......
......@@ -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()
......
......@@ -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()
......
......@@ -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()
......
......@@ -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);
......
......@@ -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
......
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