Commit e6a98f36 authored by hjk's avatar hjk

Core: Replace ICoreListener by std::functions

ICoreListener::coreAboutToClose() remains in the core,
ICoreListener::editorAboutToClose() is handled by a new
EditorManager::addCloseEditorListener() function.

This removes the need for some boiler plate code resulting
from the need to implement the interface in custom classes
(DesignModeCoreListener, EditorClosingCoreListener,
PojectEplorer::CoreListener and VcsBase::CoreListener).

EditorManager::addCloseEditorListener

Change-Id: Ie554c987b5455b555be6d77b77e4013639201d22
Reviewed-by: default avatarEike Ziller <eike.ziller@theqtcompany.com>
parent ed25b429
...@@ -101,7 +101,6 @@ SOURCES += corejsextensions.cpp \ ...@@ -101,7 +101,6 @@ SOURCES += corejsextensions.cpp \
removefiledialog.cpp \ removefiledialog.cpp \
iversioncontrol.cpp \ iversioncontrol.cpp \
dialogs/addtovcsdialog.cpp \ dialogs/addtovcsdialog.cpp \
icorelistener.cpp \
ioutputpane.cpp \ ioutputpane.cpp \
patchtool.cpp \ patchtool.cpp \
windowsupport.cpp \ windowsupport.cpp \
...@@ -177,7 +176,6 @@ HEADERS += corejsextensions.h \ ...@@ -177,7 +176,6 @@ HEADERS += corejsextensions.h \
coreconstants.h \ coreconstants.h \
iversioncontrol.h \ iversioncontrol.h \
ifilewizardextension.h \ ifilewizardextension.h \
icorelistener.h \
versiondialog.h \ versiondialog.h \
core_global.h \ core_global.h \
statusbarwidget.h \ statusbarwidget.h \
......
...@@ -57,7 +57,6 @@ QtcPlugin { ...@@ -57,7 +57,6 @@ QtcPlugin {
"helpmanager.cpp", "helpmanager.h", "helpmanager.cpp", "helpmanager.h",
"icontext.cpp", "icontext.h", "icontext.cpp", "icontext.h",
"icore.cpp", "icore.h", "icore.cpp", "icore.h",
"icorelistener.cpp", "icorelistener.h",
"id.cpp", "id.h", "id.cpp", "id.h",
"idocument.cpp", "idocument.h", "idocument.cpp", "idocument.h",
"idocumentfactory.cpp", "idocumentfactory.h", "idocumentfactory.cpp", "idocumentfactory.h",
......
...@@ -35,9 +35,7 @@ ...@@ -35,9 +35,7 @@
#include <coreplugin/modemanager.h> #include <coreplugin/modemanager.h>
#include <coreplugin/editormanager/editormanager.h> #include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/coreconstants.h> #include <coreplugin/coreconstants.h>
#include <coreplugin/icorelistener.h>
#include <coreplugin/editormanager/ieditor.h> #include <coreplugin/editormanager/ieditor.h>
#include <extensionsystem/pluginmanager.h>
#include <QPointer> #include <QPointer>
#include <QStringList> #include <QStringList>
...@@ -49,36 +47,6 @@ static Core::DesignMode *m_instance = 0; ...@@ -49,36 +47,6 @@ static Core::DesignMode *m_instance = 0;
namespace Core { namespace Core {
class EditorManager;
enum {
debug = false
};
namespace Internal {
class DesignModeCoreListener : public ICoreListener
{
public:
DesignModeCoreListener(DesignMode* mode);
bool coreAboutToClose();
private:
DesignMode *m_mode;
};
DesignModeCoreListener::DesignModeCoreListener(DesignMode *mode) :
m_mode(mode)
{
}
bool DesignModeCoreListener::coreAboutToClose()
{
m_mode->currentEditorChanged(0);
return true;
}
} // namespace Internal
struct DesignEditorInfo struct DesignEditorInfo
{ {
int widgetIndex; int widgetIndex;
...@@ -90,10 +58,9 @@ struct DesignEditorInfo ...@@ -90,10 +58,9 @@ struct DesignEditorInfo
class DesignModePrivate class DesignModePrivate
{ {
public: public:
explicit DesignModePrivate(DesignMode *q); DesignModePrivate();
public: public:
Internal::DesignModeCoreListener *m_coreListener;
QPointer<IEditor> m_currentEditor; QPointer<IEditor> m_currentEditor;
bool m_isActive; bool m_isActive;
bool m_isRequired; bool m_isRequired;
...@@ -102,18 +69,22 @@ public: ...@@ -102,18 +69,22 @@ public:
Context m_activeContext; Context m_activeContext;
}; };
DesignModePrivate::DesignModePrivate(DesignMode *q) DesignModePrivate::DesignModePrivate()
: m_coreListener(new Internal::DesignModeCoreListener(q)), : m_isActive(false),
m_isActive(false), m_isRequired(false),
m_isRequired(false), m_stackWidget(new QStackedWidget)
m_stackWidget(new QStackedWidget) {}
{
}
DesignMode::DesignMode() DesignMode::DesignMode()
: d(new DesignModePrivate(this)) : d(new DesignModePrivate)
{ {
m_instance = this; m_instance = this;
ICore::addPreCloseListener([]() -> bool {
m_instance->currentEditorChanged(0);
return true;
});
setObjectName(QLatin1String("DesignMode")); setObjectName(QLatin1String("DesignMode"));
setEnabled(false); setEnabled(false);
setContext(Context(Constants::C_DESIGN_MODE)); setContext(Context(Constants::C_DESIGN_MODE));
...@@ -123,8 +94,6 @@ DesignMode::DesignMode() ...@@ -123,8 +94,6 @@ DesignMode::DesignMode()
setPriority(Constants::P_MODE_DESIGN); setPriority(Constants::P_MODE_DESIGN);
setId(Constants::MODE_DESIGN); setId(Constants::MODE_DESIGN);
ExtensionSystem::PluginManager::addObject(d->m_coreListener);
connect(EditorManager::instance(), &EditorManager::currentEditorChanged, connect(EditorManager::instance(), &EditorManager::currentEditorChanged,
this, &DesignMode::currentEditorChanged); this, &DesignMode::currentEditorChanged);
...@@ -134,9 +103,6 @@ DesignMode::DesignMode() ...@@ -134,9 +103,6 @@ DesignMode::DesignMode()
DesignMode::~DesignMode() DesignMode::~DesignMode()
{ {
ExtensionSystem::PluginManager::removeObject(d->m_coreListener);
delete d->m_coreListener;
qDeleteAll(d->m_editors); qDeleteAll(d->m_editors);
delete d; delete d;
} }
......
...@@ -51,7 +51,6 @@ ...@@ -51,7 +51,6 @@
#include <coreplugin/fileutils.h> #include <coreplugin/fileutils.h>
#include <coreplugin/findplaceholder.h> #include <coreplugin/findplaceholder.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <coreplugin/icorelistener.h>
#include <coreplugin/imode.h> #include <coreplugin/imode.h>
#include <coreplugin/infobar.h> #include <coreplugin/infobar.h>
#include <coreplugin/iversioncontrol.h> #include <coreplugin/iversioncontrol.h>
...@@ -115,26 +114,6 @@ static const char fileSystemCaseSensitivityKey[] = "Core/FileSystemCaseSensitivi ...@@ -115,26 +114,6 @@ static const char fileSystemCaseSensitivityKey[] = "Core/FileSystemCaseSensitivi
static const char scratchBufferKey[] = "_q_emScratchBuffer"; static const char scratchBufferKey[] = "_q_emScratchBuffer";
//===================EditorClosingCoreListener======================
namespace Core {
namespace Internal {
class EditorClosingCoreListener : public ICoreListener
{
public:
bool editorAboutToClose(IEditor *) { return true; }
bool coreAboutToClose()
{
// Do not ask for files to save.
// MainWindow::closeEvent has already done that.
return EditorManager::closeAllEditors(false);
}
};
} // namespace Internal
} // namespace Core
using namespace Core; using namespace Core;
using namespace Core::Internal; using namespace Core::Internal;
using namespace Utils; using namespace Utils;
...@@ -284,7 +263,6 @@ EditorManagerPrivate::EditorManagerPrivate(QObject *parent) : ...@@ -284,7 +263,6 @@ EditorManagerPrivate::EditorManagerPrivate(QObject *parent) :
m_openTerminalAction(new QAction(FileUtils::msgTerminalAction(), this)), m_openTerminalAction(new QAction(FileUtils::msgTerminalAction(), this)),
m_findInDirectoryAction(new QAction(FileUtils::msgFindInDirectory(), this)), m_findInDirectoryAction(new QAction(FileUtils::msgFindInDirectory(), this)),
m_windowPopup(0), m_windowPopup(0),
m_coreListener(0),
m_reloadSetting(IDocument::AlwaysAsk), m_reloadSetting(IDocument::AlwaysAsk),
m_autoSaveEnabled(true), m_autoSaveEnabled(true),
m_autoSaveInterval(5), m_autoSaveInterval(5),
...@@ -297,10 +275,6 @@ EditorManagerPrivate::EditorManagerPrivate(QObject *parent) : ...@@ -297,10 +275,6 @@ EditorManagerPrivate::EditorManagerPrivate(QObject *parent) :
EditorManagerPrivate::~EditorManagerPrivate() EditorManagerPrivate::~EditorManagerPrivate()
{ {
if (ICore::instance()) { if (ICore::instance()) {
if (m_coreListener) {
ExtensionSystem::PluginManager::removeObject(m_coreListener);
delete m_coreListener;
}
ExtensionSystem::PluginManager::removeObject(m_openEditorsFactory); ExtensionSystem::PluginManager::removeObject(m_openEditorsFactory);
delete m_openEditorsFactory; delete m_openEditorsFactory;
} }
...@@ -516,8 +490,9 @@ void EditorManagerPrivate::init() ...@@ -516,8 +490,9 @@ void EditorManagerPrivate::init()
connect(m_autoSaveTimer, SIGNAL(timeout()), SLOT(autoSave())); connect(m_autoSaveTimer, SIGNAL(timeout()), SLOT(autoSave()));
updateAutoSave(); updateAutoSave();
d->m_coreListener = new EditorClosingCoreListener(); // Do not ask for files to save.
ExtensionSystem::PluginManager::addObject(d->m_coreListener); // MainWindow::closeEvent has already done that.
ICore::addPreCloseListener([]() -> bool { return EditorManager::closeAllEditors(false); });
d->m_openEditorsFactory = new OpenEditorsViewFactory(); d->m_openEditorsFactory = new OpenEditorsViewFactory();
ExtensionSystem::PluginManager::addObject(d->m_openEditorsFactory); ExtensionSystem::PluginManager::addObject(d->m_openEditorsFactory);
...@@ -2351,12 +2326,10 @@ bool EditorManager::closeEditors(const QList<IEditor*> &editorsToClose, bool ask ...@@ -2351,12 +2326,10 @@ bool EditorManager::closeEditors(const QList<IEditor*> &editorsToClose, bool ask
// 2. keep track of the document and all the editors that might remain open for it // 2. keep track of the document and all the editors that might remain open for it
QSet<IEditor*> acceptedEditors; QSet<IEditor*> acceptedEditors;
QMap<IDocument *, QList<IEditor *> > documentMap; QMap<IDocument *, QList<IEditor *> > documentMap;
const QList<ICoreListener *> listeners =
ExtensionSystem::PluginManager::getObjects<ICoreListener>();
foreach (IEditor *editor, editorsToClose) { foreach (IEditor *editor, editorsToClose) {
bool editorAccepted = true; bool editorAccepted = true;
foreach (ICoreListener *listener, listeners) { foreach (const std::function<bool(IEditor*)> listener, d->m_closeEditorListeners) {
if (!listener->editorAboutToClose(editor)) { if (!listener(editor)) {
editorAccepted = false; editorAccepted = false;
closingFailed = true; closingFailed = true;
break; break;
...@@ -2620,6 +2593,22 @@ bool EditorManager::openExternalEditor(const QString &fileName, Id editorId) ...@@ -2620,6 +2593,22 @@ bool EditorManager::openExternalEditor(const QString &fileName, Id editorId)
return ok; return ok;
} }
/*!
\fn EditorManager::addCloseEditorListener
\brief The \c EditorManager::addCloseEditorListener function provides
a hook for plugins to veto on closing editors.
When an editor requests a close, all listeners are called. If one of these
calls returns \c false, the process is aborted and the event is ignored.
If all calls return \c true, \c EditorManager::editorAboutToClose()
is emitted and the event is accepted.
*/
void EditorManager::addCloseEditorListener(const std::function<bool (IEditor *)> &listener)
{
d->m_closeEditorListeners.append(listener);
}
QStringList EditorManager::getOpenFileNames() QStringList EditorManager::getOpenFileNames()
{ {
QString selectedFilter; QString selectedFilter;
......
...@@ -121,6 +121,7 @@ public: ...@@ -121,6 +121,7 @@ public:
OpenEditorFlags flags = NoFlags); OpenEditorFlags flags = NoFlags);
static bool openExternalEditor(const QString &fileName, Id editorId); static bool openExternalEditor(const QString &fileName, Id editorId);
static void addCloseEditorListener(const std::function<bool(IEditor *)> &listener);
static QStringList getOpenFileNames(); static QStringList getOpenFileNames();
......
...@@ -56,7 +56,6 @@ class EditorManager; ...@@ -56,7 +56,6 @@ class EditorManager;
namespace Internal { namespace Internal {
class EditorClosingCoreListener;
class MainWindow; class MainWindow;
class OpenEditorsViewFactory; class OpenEditorsViewFactory;
class OpenEditorsWindow; class OpenEditorsWindow;
...@@ -243,7 +242,6 @@ private: ...@@ -243,7 +242,6 @@ private:
IEditor *m_contextMenuEditor; IEditor *m_contextMenuEditor;
OpenEditorsWindow *m_windowPopup; OpenEditorsWindow *m_windowPopup;
EditorClosingCoreListener *m_coreListener;
QMap<QString, QVariant> m_editorStates; QMap<QString, QVariant> m_editorStates;
OpenEditorsViewFactory *m_openEditorsFactory; OpenEditorsViewFactory *m_openEditorsFactory;
...@@ -260,6 +258,7 @@ private: ...@@ -260,6 +258,7 @@ private:
int m_bigFileSizeLimitInMB; int m_bigFileSizeLimitInMB;
QString m_placeholderText; QString m_placeholderText;
QList<std::function<bool(IEditor *)>> m_closeEditorListeners;
}; };
} // Internal } // Internal
......
...@@ -564,6 +564,23 @@ void ICore::openFiles(const QStringList &arguments, ICore::OpenFilesFlags flags) ...@@ -564,6 +564,23 @@ void ICore::openFiles(const QStringList &arguments, ICore::OpenFilesFlags flags)
m_mainwindow->openFiles(arguments, flags); m_mainwindow->openFiles(arguments, flags);
} }
/*!
\fn ICore::addCloseCoreListener
\brief The \c ICore::addCloseCoreListener function provides a hook for plugins
to veto on closing the application.
When the application window requests a close, all listeners are called.
If one if these calls returns \c false, the process is aborted and the
event is ignored. If all calls return \c true, \c ICore::coreAboutToClose()
is emitted and the event is accepted or performed..
*/
void ICore::addPreCloseListener(const std::function<bool ()> &listener)
{
m_mainwindow->addPreCloseListener(listener);
}
void ICore::saveSettings() void ICore::saveSettings()
{ {
emit m_instance->saveSettingsRequested(); emit m_instance->saveSettingsRequested();
......
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
#include <QObject> #include <QObject>
#include <QSettings> #include <QSettings>
#include <functional>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QPrinter; class QPrinter;
class QStatusBar; class QStatusBar;
...@@ -132,6 +134,8 @@ public: ...@@ -132,6 +134,8 @@ public:
}; };
static void openFiles(const QStringList &fileNames, OpenFilesFlags flags = None); static void openFiles(const QStringList &fileNames, OpenFilesFlags flags = None);
static void addPreCloseListener(const std::function<bool()> &listener);
public slots: public slots:
static void saveSettings(); static void saveSettings();
......
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
**
** 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 The Qt Company. For licensing terms and
** conditions see http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "icorelistener.h"
/*!
\class Core::ICoreListener
\brief The ICoreListener class provides a hook for plugins to veto on
certain events emitted from the core plugin.
Implement this interface to prevent certain events from occurring. For
example, to prevent the closing of the whole application
or to prevent the closing of an editor window under certain conditions.
For example, if the application window requests a close,
\c ICoreListener::coreAboutToClose() is called (in arbitrary order) on all
registered objects implementing this interface. If one if these calls
returns \c false, the process is aborted and the event is ignored. If all
calls return \c true, the corresponding signal is emitted and the event is
accepted or performed.
Guidelines for implementing the class:
\list
\li Return \c false from the implemented function if you want to prevent
the event.
\li Add your implementing object to the plugin managers objects:
\c{ExtensionSystem::PluginManager::instance()->addObject(yourImplementingObject)}
\li Do not forget to remove the object again at deconstruction
(for example, in the destructor of your plugin).
\endlist
*/
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
**
** 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 The Qt Company. For licensing terms and
** conditions see http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef ICORELISTENER_H
#define ICORELISTENER_H
#include "core_global.h"
#include <QObject>
namespace Core {
class IEditor;
class CORE_EXPORT ICoreListener : public QObject
{
Q_OBJECT
public:
ICoreListener(QObject *parent = 0) : QObject(parent) {}
virtual ~ICoreListener() {}
virtual bool editorAboutToClose(IEditor * /*editor*/) { return true; }
virtual bool coreAboutToClose() { return true; }
};
} // namespace Core
#endif // ICORELISTENER_H
...@@ -69,7 +69,6 @@ ...@@ -69,7 +69,6 @@
#include <coreplugin/editormanager/editormanager.h> #include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/editormanager_p.h> #include <coreplugin/editormanager/editormanager_p.h>
#include <coreplugin/editormanager/ieditor.h> #include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/icorelistener.h>
#include <coreplugin/inavigationwidgetfactory.h> #include <coreplugin/inavigationwidgetfactory.h>
#include <coreplugin/progressmanager/progressmanager_p.h> #include <coreplugin/progressmanager/progressmanager_p.h>
#include <coreplugin/progressmanager/progressview.h> #include <coreplugin/progressmanager/progressview.h>
...@@ -250,6 +249,11 @@ void MainWindow::appendAboutInformation(const QString &line) ...@@ -250,6 +249,11 @@ void MainWindow::appendAboutInformation(const QString &line)
m_aboutInformation.append(line); m_aboutInformation.append(line);
} }
void MainWindow::addPreCloseListener(const std::function<bool ()> &listener)
{
m_preCloseListeners.append(listener);
}
MainWindow::~MainWindow() MainWindow::~MainWindow()
{ {
// explicitly delete window support, because that calls methods from ICore that call methods // explicitly delete window support, because that calls methods from ICore that call methods
...@@ -370,10 +374,8 @@ void MainWindow::closeEvent(QCloseEvent *event) ...@@ -370,10 +374,8 @@ void MainWindow::closeEvent(QCloseEvent *event)
return; return;
} }
const QList<ICoreListener *> listeners = foreach (const std::function<bool()> &listener, m_preCloseListeners) {
PluginManager::getObjects<ICoreListener>(); if (!listener()) {
foreach (ICoreListener *listener, listeners) {
if (!listener->coreAboutToClose()) {
event->ignore(); event->ignore();
return; return;
} }
......
...@@ -40,6 +40,8 @@ ...@@ -40,6 +40,8 @@
#include <QMap> #include <QMap>
#include <QColor> #include <QColor>
#include <functional>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QSettings; class QSettings;
class QPrinter; class QPrinter;
...@@ -113,6 +115,8 @@ public: ...@@ -113,6 +115,8 @@ public:
QStringList additionalAboutInformation() const; QStringList additionalAboutInformation() const;
void appendAboutInformation(const QString &line); void appendAboutInformation(const QString &line);
void addPreCloseListener(const std::function<bool()> &listener);