mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2024-11-29 07:24:13 +01:00
Branding again....
git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@169 ebee16cc-31ac-478f-84a7-5cbb03baadba
This commit is contained in:
parent
3ffbcb4c0d
commit
690f4cced5
@ -1,48 +1,51 @@
|
||||
<RCC>
|
||||
<qresource prefix="/core" >
|
||||
<file>images/clean_pane_small.png</file>
|
||||
<file>images/clear.png</file>
|
||||
<file>images/closebutton.png</file>
|
||||
<file>images/dir.png</file>
|
||||
<file>images/editcopy.png</file>
|
||||
<file>images/editcut.png</file>
|
||||
<file>images/editpaste.png</file>
|
||||
<file>images/empty14.png</file>
|
||||
<file>images/filenew.png</file>
|
||||
<file>images/fileopen.png</file>
|
||||
<file>images/filesave.png</file>
|
||||
<file>images/find.png</file>
|
||||
<file>images/findnext.png</file>
|
||||
<file>images/qtcreator_logo_128.png</file>
|
||||
<file>images/qtcreator_logo_32.png</file>
|
||||
<file>images/inputfield.png</file>
|
||||
<file>images/inputfield_disabled.png</file>
|
||||
<file>images/linkicon.png</file>
|
||||
<file>images/locked.png</file>
|
||||
<file>images/magnifier.png</file>
|
||||
<file>images/minus.png</file>
|
||||
<file>images/next.png</file>
|
||||
<file>images/panel_button.png</file>
|
||||
<file>images/panel_button_checked.png</file>
|
||||
<file>images/panel_button_checked_hover.png</file>
|
||||
<file>images/panel_button_hover.png</file>
|
||||
<file>images/panel_button_pressed.png</file>
|
||||
<file>images/plus.png</file>
|
||||
<file>images/prev.png</file>
|
||||
<file>images/pushbutton.png</file>
|
||||
<file>images/pushbutton_hover.png</file>
|
||||
<file>images/pushbutton_pressed.png</file>
|
||||
<file>images/qtwatermark.png</file>
|
||||
<file>images/redo.png</file>
|
||||
<file>images/replace.png</file>
|
||||
<file>images/reset.png</file>
|
||||
<file>images/sidebaricon.png</file>
|
||||
<file>images/splitbutton_horizontal.png</file>
|
||||
<file>images/statusbar.png</file>
|
||||
<file>images/undo.png</file>
|
||||
<file>images/unknownfile.png</file>
|
||||
<file>images/unlocked.png</file>
|
||||
<file>images/extension.png</file>
|
||||
<file>images/darkclosebutton.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
<RCC>
|
||||
<qresource prefix="/core" >
|
||||
<file>images/openpilot_logo_256.png</file>
|
||||
<file>images/openpilot_logo_128.png</file>
|
||||
<file>images/openpilot_logo_64.png</file>
|
||||
<file>images/clean_pane_small.png</file>
|
||||
<file>images/clear.png</file>
|
||||
<file>images/closebutton.png</file>
|
||||
<file>images/dir.png</file>
|
||||
<file>images/editcopy.png</file>
|
||||
<file>images/editcut.png</file>
|
||||
<file>images/editpaste.png</file>
|
||||
<file>images/empty14.png</file>
|
||||
<file>images/filenew.png</file>
|
||||
<file>images/fileopen.png</file>
|
||||
<file>images/filesave.png</file>
|
||||
<file>images/find.png</file>
|
||||
<file>images/findnext.png</file>
|
||||
<file>images/qtcreator_logo_128.png</file>
|
||||
<file>images/qtcreator_logo_32.png</file>
|
||||
<file>images/inputfield.png</file>
|
||||
<file>images/inputfield_disabled.png</file>
|
||||
<file>images/linkicon.png</file>
|
||||
<file>images/locked.png</file>
|
||||
<file>images/magnifier.png</file>
|
||||
<file>images/minus.png</file>
|
||||
<file>images/next.png</file>
|
||||
<file>images/panel_button.png</file>
|
||||
<file>images/panel_button_checked.png</file>
|
||||
<file>images/panel_button_checked_hover.png</file>
|
||||
<file>images/panel_button_hover.png</file>
|
||||
<file>images/panel_button_pressed.png</file>
|
||||
<file>images/plus.png</file>
|
||||
<file>images/prev.png</file>
|
||||
<file>images/pushbutton.png</file>
|
||||
<file>images/pushbutton_hover.png</file>
|
||||
<file>images/pushbutton_pressed.png</file>
|
||||
<file>images/qtwatermark.png</file>
|
||||
<file>images/redo.png</file>
|
||||
<file>images/replace.png</file>
|
||||
<file>images/reset.png</file>
|
||||
<file>images/sidebaricon.png</file>
|
||||
<file>images/splitbutton_horizontal.png</file>
|
||||
<file>images/statusbar.png</file>
|
||||
<file>images/undo.png</file>
|
||||
<file>images/unknownfile.png</file>
|
||||
<file>images/unlocked.png</file>
|
||||
<file>images/extension.png</file>
|
||||
<file>images/darkclosebutton.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@ -122,7 +122,7 @@ const char * const MINIMIZE_WINDOW = "QtCreator.MinimizeWindow";
|
||||
const char * const ZOOM_WINDOW = "QtCreator.ZoomWindow";
|
||||
|
||||
const char * const SPLIT = "QtCreator.Split";
|
||||
const char * const SPLIT_SGCS_BY_SIDE = "QtCreator.SplitSideBySide";
|
||||
const char * const SPLIT_SIDE_BY_SIDE = "QtCreator.SplitSideBySide";
|
||||
const char * const REMOVE_CURRENT_SPLIT = "QtCreator.RemoveCurrentSplit";
|
||||
const char * const REMOVE_ALL_SPLITS = "QtCreator.RemoveAllSplits";
|
||||
const char * const GOTO_OTHER_SPLIT = "QtCreator.GotoOtherSplit";
|
||||
|
@ -1,1937 +1,1937 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** Commercial Usage
|
||||
**
|
||||
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||
** accordance with the Qt Commercial License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Nokia.
|
||||
**
|
||||
** 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 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** If you are unsure which license is appropriate for your use, please
|
||||
** contact the sales department at http://qt.nokia.com/contact.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "editormanager.h"
|
||||
#include "editorview.h"
|
||||
#include "openeditorswindow.h"
|
||||
#include "openeditorsview.h"
|
||||
#include "openeditorsmodel.h"
|
||||
#include "openwithdialog.h"
|
||||
#include "filemanager.h"
|
||||
#include "icore.h"
|
||||
#include "iversioncontrol.h"
|
||||
#include "mimedatabase.h"
|
||||
#include "tabpositionindicator.h"
|
||||
#include "vcsmanager.h"
|
||||
|
||||
#include <coreplugin/coreconstants.h>
|
||||
#include <coreplugin/modemanager.h>
|
||||
#include <coreplugin/uniqueidmanager.h>
|
||||
#include <coreplugin/actionmanager/actionmanager.h>
|
||||
#include <coreplugin/editormanager/ieditorfactory.h>
|
||||
#include <coreplugin/editormanager/iexternaleditor.h>
|
||||
#include <coreplugin/baseview.h>
|
||||
#include <coreplugin/imode.h>
|
||||
#include <coreplugin/settingsdatabase.h>
|
||||
#include <coreplugin/variablemanager.h>
|
||||
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
|
||||
#include <utils/consoleprocess.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QProcess>
|
||||
#include <QtCore/QSet>
|
||||
#include <QtCore/QSettings>
|
||||
|
||||
#include <QtGui/QAction>
|
||||
#include <QtGui/QApplication>
|
||||
#include <QtGui/QFileDialog>
|
||||
#include <QtGui/QLayout>
|
||||
#include <QtGui/QMainWindow>
|
||||
#include <QtGui/QMenu>
|
||||
#include <QtGui/QMessageBox>
|
||||
#include <QtGui/QPushButton>
|
||||
#include <QtGui/QSplitter>
|
||||
#include <QtGui/QStackedLayout>
|
||||
|
||||
Q_DECLARE_METATYPE(Core::IEditor*)
|
||||
|
||||
using namespace Core;
|
||||
using namespace Core::Internal;
|
||||
using namespace Utils;
|
||||
|
||||
enum { debugEditorManager=0 };
|
||||
|
||||
static inline ExtensionSystem::PluginManager *pluginManager()
|
||||
{
|
||||
return ExtensionSystem::PluginManager::instance();
|
||||
}
|
||||
|
||||
//===================EditorManager=====================
|
||||
|
||||
EditorManagerPlaceHolder *EditorManagerPlaceHolder::m_current = 0;
|
||||
|
||||
EditorManagerPlaceHolder::EditorManagerPlaceHolder(Core::IMode *mode, QWidget *parent)
|
||||
: QWidget(parent), m_mode(mode)
|
||||
{
|
||||
setLayout(new QVBoxLayout);
|
||||
layout()->setMargin(0);
|
||||
connect(Core::ModeManager::instance(), SIGNAL(currentModeChanged(Core::IMode *)),
|
||||
this, SLOT(currentModeChanged(Core::IMode *)));
|
||||
|
||||
currentModeChanged(Core::ModeManager::instance()->currentMode());
|
||||
}
|
||||
|
||||
EditorManagerPlaceHolder::~EditorManagerPlaceHolder()
|
||||
{
|
||||
if (m_current == this) {
|
||||
EditorManager::instance()->setParent(0);
|
||||
EditorManager::instance()->hide();
|
||||
}
|
||||
}
|
||||
|
||||
void EditorManagerPlaceHolder::currentModeChanged(Core::IMode *mode)
|
||||
{
|
||||
if (m_current == this) {
|
||||
m_current = 0;
|
||||
EditorManager::instance()->setParent(0);
|
||||
EditorManager::instance()->hide();
|
||||
}
|
||||
if (m_mode == mode) {
|
||||
m_current = this;
|
||||
layout()->addWidget(EditorManager::instance());
|
||||
EditorManager::instance()->show();
|
||||
}
|
||||
}
|
||||
|
||||
EditorManagerPlaceHolder* EditorManagerPlaceHolder::current()
|
||||
{
|
||||
return m_current;
|
||||
}
|
||||
|
||||
// ---------------- EditorManager
|
||||
|
||||
namespace Core {
|
||||
|
||||
|
||||
struct EditorManagerPrivate {
|
||||
explicit EditorManagerPrivate(ICore *core, QWidget *parent);
|
||||
~EditorManagerPrivate();
|
||||
Internal::EditorView *m_view;
|
||||
Internal::SplitterOrView *m_splitter;
|
||||
QPointer<IEditor> m_currentEditor;
|
||||
QPointer<SplitterOrView> m_currentView;
|
||||
|
||||
ICore *m_core;
|
||||
|
||||
|
||||
// actions
|
||||
QAction *m_revertToSavedAction;
|
||||
QAction *m_saveAction;
|
||||
QAction *m_saveAsAction;
|
||||
QAction *m_closeCurrentEditorAction;
|
||||
QAction *m_closeAllEditorsAction;
|
||||
QAction *m_closeOtherEditorsAction;
|
||||
QAction *m_gotoNextDocHistoryAction;
|
||||
QAction *m_gotoPreviousDocHistoryAction;
|
||||
QAction *m_goBackAction;
|
||||
QAction *m_goForwardAction;
|
||||
QAction *m_openInExternalEditorAction;
|
||||
QAction *m_splitAction;
|
||||
QAction *m_splitSideBySideAction;
|
||||
QAction *m_removeCurrentSplitAction;
|
||||
QAction *m_removeAllSplitsAction;
|
||||
QAction *m_gotoOtherSplitAction;
|
||||
|
||||
Internal::OpenEditorsWindow *m_windowPopup;
|
||||
Core::BaseView *m_openEditorsView;
|
||||
Internal::EditorClosingCoreListener *m_coreListener;
|
||||
|
||||
QMap<QString, QVariant> m_editorStates;
|
||||
Internal::OpenEditorsViewFactory *m_openEditorsFactory;
|
||||
|
||||
QString fileFilters;
|
||||
QString selectedFilter;
|
||||
|
||||
OpenEditorsModel *m_editorModel;
|
||||
QString m_externalEditor;
|
||||
|
||||
IFile::ReloadBehavior m_reloadBehavior;
|
||||
};
|
||||
}
|
||||
|
||||
EditorManagerPrivate::EditorManagerPrivate(ICore *core, QWidget *parent) :
|
||||
m_view(0),
|
||||
m_splitter(0),
|
||||
m_core(core),
|
||||
m_revertToSavedAction(new QAction(EditorManager::tr("Revert to Saved"), parent)),
|
||||
m_saveAction(new QAction(parent)),
|
||||
m_saveAsAction(new QAction(parent)),
|
||||
m_closeCurrentEditorAction(new QAction(EditorManager::tr("Close"), parent)),
|
||||
m_closeAllEditorsAction(new QAction(EditorManager::tr("Close All"), parent)),
|
||||
m_closeOtherEditorsAction(new QAction(EditorManager::tr("Close Others"), parent)),
|
||||
m_gotoNextDocHistoryAction(new QAction(EditorManager::tr("Next Open Document in History"), parent)),
|
||||
m_gotoPreviousDocHistoryAction(new QAction(EditorManager::tr("Previous Open Document in History"), parent)),
|
||||
m_goBackAction(new QAction(QIcon(QLatin1String(":/help/images/previous.png")), EditorManager::tr("Go Back"), parent)),
|
||||
m_goForwardAction(new QAction(QIcon(QLatin1String(":/help/images/next.png")), EditorManager::tr("Go Forward"), parent)),
|
||||
m_openInExternalEditorAction(new QAction(EditorManager::tr("Open in External Editor"), parent)),
|
||||
m_windowPopup(0),
|
||||
m_coreListener(0),
|
||||
m_reloadBehavior(IFile::AskForReload)
|
||||
{
|
||||
m_editorModel = new OpenEditorsModel(parent);
|
||||
}
|
||||
|
||||
EditorManagerPrivate::~EditorManagerPrivate()
|
||||
{
|
||||
// clearNavigationHistory();
|
||||
}
|
||||
|
||||
EditorManager *EditorManager::m_instance = 0;
|
||||
|
||||
static Command *createSeparator(ActionManager *am, QObject *parent,
|
||||
const QString &name,
|
||||
const QList<int> &context)
|
||||
{
|
||||
QAction *tmpaction = new QAction(parent);
|
||||
tmpaction->setSeparator(true);
|
||||
Command *cmd = am->registerAction(tmpaction, name, context);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
EditorManager::EditorManager(ICore *core, QWidget *parent) :
|
||||
QWidget(parent),
|
||||
m_d(new EditorManagerPrivate(core, parent))
|
||||
{
|
||||
m_instance = this;
|
||||
|
||||
connect(m_d->m_core, SIGNAL(contextAboutToChange(Core::IContext *)),
|
||||
this, SLOT(handleContextChange(Core::IContext *)));
|
||||
|
||||
const QList<int> gc = QList<int>() << Constants::C_GLOBAL_ID;
|
||||
const QList<int> editManagerContext =
|
||||
QList<int>() << m_d->m_core->uniqueIDManager()->uniqueIdentifier(Constants::C_EDITORMANAGER);
|
||||
|
||||
ActionManager *am = m_d->m_core->actionManager();
|
||||
ActionContainer *mfile = am->actionContainer(Constants::M_FILE);
|
||||
|
||||
//Revert to saved
|
||||
Command *cmd = am->registerAction(m_d->m_revertToSavedAction,
|
||||
Constants::REVERTTOSAVED, editManagerContext);
|
||||
cmd->setAttribute(Command::CA_UpdateText);
|
||||
cmd->setDefaultText(tr("Revert File to Saved"));
|
||||
mfile->addAction(cmd, Constants::G_FILE_SAVE);
|
||||
connect(m_d->m_revertToSavedAction, SIGNAL(triggered()), this, SLOT(revertToSaved()));
|
||||
|
||||
//Save Action
|
||||
am->registerAction(m_d->m_saveAction, Constants::SAVE, editManagerContext);
|
||||
connect(m_d->m_saveAction, SIGNAL(triggered()), this, SLOT(saveFile()));
|
||||
|
||||
//Save As Action
|
||||
am->registerAction(m_d->m_saveAsAction, Constants::SAVEAS, editManagerContext);
|
||||
connect(m_d->m_saveAsAction, SIGNAL(triggered()), this, SLOT(saveFileAs()));
|
||||
|
||||
//Window Menu
|
||||
ActionContainer *mwindow = am->actionContainer(Constants::M_WINDOW);
|
||||
|
||||
//Window menu separators
|
||||
QAction *tmpaction = new QAction(this);
|
||||
tmpaction->setSeparator(true);
|
||||
cmd = am->registerAction(tmpaction, QLatin1String("QtCreator.Window.Sep.Split"), editManagerContext);
|
||||
mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT);
|
||||
|
||||
tmpaction = new QAction(this);
|
||||
tmpaction->setSeparator(true);
|
||||
cmd = am->registerAction(tmpaction, QLatin1String("QtCreator.Window.Sep.Navigate"), editManagerContext);
|
||||
mwindow->addAction(cmd, Constants::G_WINDOW_NAVIGATE);
|
||||
|
||||
//Close Action
|
||||
cmd = am->registerAction(m_d->m_closeCurrentEditorAction, Constants::CLOSE, editManagerContext);
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+W")));
|
||||
cmd->setAttribute(Core::Command::CA_UpdateText);
|
||||
cmd->setDefaultText(m_d->m_closeCurrentEditorAction->text());
|
||||
mfile->addAction(cmd, Constants::G_FILE_CLOSE);
|
||||
connect(m_d->m_closeCurrentEditorAction, SIGNAL(triggered()), this, SLOT(closeEditor()));
|
||||
|
||||
//Close All Action
|
||||
cmd = am->registerAction(m_d->m_closeAllEditorsAction, Constants::CLOSEALL, editManagerContext);
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+W")));
|
||||
mfile->addAction(cmd, Constants::G_FILE_CLOSE);
|
||||
connect(m_d->m_closeAllEditorsAction, SIGNAL(triggered()), this, SLOT(closeAllEditors()));
|
||||
|
||||
//Close All Others Action
|
||||
cmd = am->registerAction(m_d->m_closeOtherEditorsAction, Constants::CLOSEOTHERS, editManagerContext);
|
||||
mfile->addAction(cmd, Constants::G_FILE_CLOSE);
|
||||
cmd->setAttribute(Core::Command::CA_UpdateText);
|
||||
connect(m_d->m_closeOtherEditorsAction, SIGNAL(triggered()), this, SLOT(closeOtherEditors()));
|
||||
|
||||
// Goto Previous In History Action
|
||||
cmd = am->registerAction(m_d->m_gotoPreviousDocHistoryAction, Constants::GOTOPREVINHISTORY, editManagerContext);
|
||||
#ifdef Q_WS_MAC
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("Alt+Tab")));
|
||||
#else
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Tab")));
|
||||
#endif
|
||||
mwindow->addAction(cmd, Constants::G_WINDOW_NAVIGATE);
|
||||
connect(m_d->m_gotoPreviousDocHistoryAction, SIGNAL(triggered()), this, SLOT(gotoPreviousDocHistory()));
|
||||
|
||||
// Goto Next In History Action
|
||||
cmd = am->registerAction(m_d->m_gotoNextDocHistoryAction, Constants::GOTONEXTINHISTORY, editManagerContext);
|
||||
#ifdef Q_WS_MAC
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("Alt+Shift+Tab")));
|
||||
#else
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+Tab")));
|
||||
#endif
|
||||
mwindow->addAction(cmd, Constants::G_WINDOW_NAVIGATE);
|
||||
connect(m_d->m_gotoNextDocHistoryAction, SIGNAL(triggered()), this, SLOT(gotoNextDocHistory()));
|
||||
|
||||
// Go back in navigation history
|
||||
cmd = am->registerAction(m_d->m_goBackAction, Constants::GO_BACK, editManagerContext);
|
||||
#ifdef Q_WS_MAC
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+Left")));
|
||||
#else
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("Alt+Left")));
|
||||
#endif
|
||||
mwindow->addAction(cmd, Constants::G_WINDOW_NAVIGATE);
|
||||
connect(m_d->m_goBackAction, SIGNAL(triggered()), this, SLOT(goBackInNavigationHistory()));
|
||||
|
||||
// Go forward in navigation history
|
||||
cmd = am->registerAction(m_d->m_goForwardAction, Constants::GO_FORWARD, editManagerContext);
|
||||
#ifdef Q_WS_MAC
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+Right")));
|
||||
#else
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("Alt+Right")));
|
||||
#endif
|
||||
mwindow->addAction(cmd, Constants::G_WINDOW_NAVIGATE);
|
||||
connect(m_d->m_goForwardAction, SIGNAL(triggered()), this, SLOT(goForwardInNavigationHistory()));
|
||||
|
||||
#ifdef Q_WS_MAC
|
||||
QString prefix = tr("Meta+E");
|
||||
#else
|
||||
QString prefix = tr("Ctrl+E");
|
||||
#endif
|
||||
|
||||
m_d->m_splitAction = new QAction(tr("Split"), this);
|
||||
cmd = am->registerAction(m_d->m_splitAction, Constants::SPLIT, editManagerContext);
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("%1,2").arg(prefix)));
|
||||
mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT);
|
||||
connect(m_d->m_splitAction, SIGNAL(triggered()), this, SLOT(split()));
|
||||
|
||||
m_d->m_splitSideBySideAction = new QAction(tr("Split Side by Side"), this);
|
||||
cmd = am->registerAction(m_d->m_splitSideBySideAction, Constants::SPLIT_SIDE_BY_SIDE, editManagerContext);
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("%1,3").arg(prefix)));
|
||||
mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT);
|
||||
connect(m_d->m_splitSideBySideAction, SIGNAL(triggered()), this, SLOT(splitSideBySide()));
|
||||
|
||||
m_d->m_removeCurrentSplitAction = new QAction(tr("Remove Current Split"), this);
|
||||
cmd = am->registerAction(m_d->m_removeCurrentSplitAction, Constants::REMOVE_CURRENT_SPLIT, editManagerContext);
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("%1,0").arg(prefix)));
|
||||
mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT);
|
||||
connect(m_d->m_removeCurrentSplitAction, SIGNAL(triggered()), this, SLOT(removeCurrentSplit()));
|
||||
|
||||
m_d->m_removeAllSplitsAction = new QAction(tr("Remove All Splits"), this);
|
||||
cmd = am->registerAction(m_d->m_removeAllSplitsAction, Constants::REMOVE_ALL_SPLITS, editManagerContext);
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("%1,1").arg(prefix)));
|
||||
mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT);
|
||||
connect(m_d->m_removeAllSplitsAction, SIGNAL(triggered()), this, SLOT(removeAllSplits()));
|
||||
|
||||
m_d->m_gotoOtherSplitAction = new QAction(tr("Goto Other Split"), this);
|
||||
cmd = am->registerAction(m_d->m_gotoOtherSplitAction, Constants::GOTO_OTHER_SPLIT, editManagerContext);
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("%1,o").arg(prefix)));
|
||||
mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT);
|
||||
connect(m_d->m_gotoOtherSplitAction, SIGNAL(triggered()), this, SLOT(gotoOtherSplit()));
|
||||
|
||||
ActionContainer *medit = am->actionContainer(Constants::M_EDIT);
|
||||
ActionContainer *advancedMenu = am->createMenu(Constants::M_EDIT_ADVANCED);
|
||||
medit->addMenu(advancedMenu, Constants::G_EDIT_ADVANCED);
|
||||
advancedMenu->menu()->setTitle(tr("&Advanced"));
|
||||
advancedMenu->appendGroup(Constants::G_EDIT_FORMAT);
|
||||
advancedMenu->appendGroup(Constants::G_EDIT_COLLAPSING);
|
||||
advancedMenu->appendGroup(Constants::G_EDIT_BLOCKS);
|
||||
advancedMenu->appendGroup(Constants::G_EDIT_FONT);
|
||||
advancedMenu->appendGroup(Constants::G_EDIT_EDITOR);
|
||||
|
||||
// Advanced menu separators
|
||||
cmd = createSeparator(am, this, QLatin1String("QtCreator.Edit.Sep.Collapsing"), editManagerContext);
|
||||
advancedMenu->addAction(cmd, Constants::G_EDIT_COLLAPSING);
|
||||
cmd = createSeparator(am, this, QLatin1String("QtCreator.Edit.Sep.Blocks"), editManagerContext);
|
||||
advancedMenu->addAction(cmd, Constants::G_EDIT_BLOCKS);
|
||||
cmd = createSeparator(am, this, QLatin1String("QtCreator.Edit.Sep.Font"), editManagerContext);
|
||||
advancedMenu->addAction(cmd, Constants::G_EDIT_FONT);
|
||||
cmd = createSeparator(am, this, QLatin1String("QtCreator.Edit.Sep.Editor"), editManagerContext);
|
||||
advancedMenu->addAction(cmd, Constants::G_EDIT_EDITOR);
|
||||
|
||||
cmd = am->registerAction(m_d->m_openInExternalEditorAction, Constants::OPEN_IN_EXTERNAL_EDITOR, editManagerContext);
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("Alt+V,Alt+I")));
|
||||
advancedMenu->addAction(cmd, Constants::G_EDIT_EDITOR);
|
||||
connect(m_d->m_openInExternalEditorAction, SIGNAL(triggered()), this, SLOT(openInExternalEditor()));
|
||||
|
||||
// Connect to VariableManager for CURRENT_DOCUMENT variable setting
|
||||
VariableManager *vm = VariableManager::instance();
|
||||
connect(this, SIGNAL(currentEditorChanged(Core::IEditor *)),
|
||||
vm, SLOT(updateCurrentDocument(Core::IEditor *)));
|
||||
|
||||
|
||||
// other setup
|
||||
m_d->m_splitter = new SplitterOrView(m_d->m_editorModel);
|
||||
m_d->m_view = m_d->m_splitter->view();
|
||||
|
||||
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
layout->setMargin(0);
|
||||
layout->setSpacing(0);
|
||||
layout->addWidget(m_d->m_splitter);
|
||||
|
||||
updateActions();
|
||||
|
||||
m_d->m_windowPopup = new OpenEditorsWindow(this);
|
||||
}
|
||||
|
||||
EditorManager::~EditorManager()
|
||||
{
|
||||
if (m_d->m_core) {
|
||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||
if (m_d->m_coreListener) {
|
||||
pm->removeObject(m_d->m_coreListener);
|
||||
delete m_d->m_coreListener;
|
||||
}
|
||||
pm->removeObject(m_d->m_openEditorsFactory);
|
||||
delete m_d->m_openEditorsFactory;
|
||||
}
|
||||
delete m_d;
|
||||
}
|
||||
|
||||
void EditorManager::init()
|
||||
{
|
||||
QList<int> context;
|
||||
context << m_d->m_core->uniqueIDManager()->uniqueIdentifier("QtCreator.OpenDocumentsView");
|
||||
|
||||
m_d->m_coreListener = new EditorClosingCoreListener(this);
|
||||
|
||||
pluginManager()->addObject(m_d->m_coreListener);
|
||||
|
||||
m_d->m_openEditorsFactory = new OpenEditorsViewFactory();
|
||||
pluginManager()->addObject(m_d->m_openEditorsFactory);
|
||||
}
|
||||
|
||||
QString EditorManager::defaultExternalEditor() const
|
||||
{
|
||||
#ifdef Q_OS_UNIX
|
||||
return ConsoleProcess::defaultTerminalEmulator() + QLatin1String(
|
||||
# ifdef Q_OS_MAC
|
||||
" -async"
|
||||
# endif
|
||||
" -geom %Wx%H+%x+%y -e vi %f +%l +\"normal %c|\"");
|
||||
#else
|
||||
return QLatin1String("notepad %f");
|
||||
#endif
|
||||
}
|
||||
|
||||
void EditorManager::removeEditor(IEditor *editor)
|
||||
{
|
||||
bool isDuplicate = m_d->m_editorModel->isDuplicate(editor);
|
||||
m_d->m_editorModel->removeEditor(editor);
|
||||
if (!isDuplicate) {
|
||||
m_d->m_core->fileManager()->removeFile(editor->file());
|
||||
}
|
||||
m_d->m_core->removeContextObject(editor);
|
||||
}
|
||||
|
||||
void EditorManager::handleContextChange(Core::IContext *context)
|
||||
{
|
||||
if (debugEditorManager)
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
IEditor *editor = context ? qobject_cast<IEditor*>(context) : 0;
|
||||
if (editor) {
|
||||
setCurrentEditor(editor);
|
||||
} else {
|
||||
updateActions();
|
||||
}
|
||||
}
|
||||
|
||||
void EditorManager::setCurrentEditor(IEditor *editor, bool ignoreNavigationHistory)
|
||||
{
|
||||
if (editor)
|
||||
setCurrentView(0);
|
||||
|
||||
if (m_d->m_currentEditor == editor)
|
||||
return;
|
||||
if (m_d->m_currentEditor && !ignoreNavigationHistory)
|
||||
addCurrentPositionToNavigationHistory();
|
||||
|
||||
m_d->m_currentEditor = editor;
|
||||
if (editor) {
|
||||
if (SplitterOrView *splitterOrView = m_d->m_splitter->findView(editor))
|
||||
splitterOrView->view()->setCurrentEditor(editor);
|
||||
m_d->m_view->updateEditorHistory(editor); // the global view should have a complete history
|
||||
}
|
||||
updateActions();
|
||||
emit currentEditorChanged(editor);
|
||||
}
|
||||
|
||||
|
||||
void EditorManager::setCurrentView(Core::Internal::SplitterOrView *view)
|
||||
{
|
||||
if (view == m_d->m_currentView)
|
||||
return;
|
||||
|
||||
SplitterOrView *old = m_d->m_currentView;
|
||||
m_d->m_currentView = view;
|
||||
|
||||
if (old)
|
||||
old->update();
|
||||
if (view)
|
||||
view->update();
|
||||
|
||||
if (view && !view->editor())
|
||||
view->setFocus();
|
||||
}
|
||||
|
||||
Core::Internal::SplitterOrView *EditorManager::currentSplitterOrView() const
|
||||
{
|
||||
SplitterOrView *view = m_d->m_currentView;
|
||||
if (!view)
|
||||
view = m_d->m_currentEditor?
|
||||
m_d->m_splitter->findView(m_d->m_currentEditor):
|
||||
m_d->m_splitter->findFirstView();
|
||||
if (!view)
|
||||
return m_d->m_splitter;
|
||||
return view;
|
||||
}
|
||||
|
||||
Core::Internal::EditorView *EditorManager::currentEditorView() const
|
||||
{
|
||||
return currentSplitterOrView()->view();
|
||||
}
|
||||
|
||||
|
||||
|
||||
QList<IEditor *> EditorManager::editorsForFileName(const QString &filename) const
|
||||
{
|
||||
QList<IEditor *> found;
|
||||
QString fixedname = FileManager::fixFileName(filename);
|
||||
foreach (IEditor *editor, openedEditors()) {
|
||||
if (fixedname == FileManager::fixFileName(editor->file()->fileName()))
|
||||
found << editor;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
QList<IEditor *> EditorManager::editorsForFile(IFile *file) const
|
||||
{
|
||||
QList<IEditor *> found;
|
||||
foreach (IEditor *editor, openedEditors()) {
|
||||
if (editor->file() == file)
|
||||
found << editor;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
IEditor *EditorManager::currentEditor() const
|
||||
{
|
||||
return m_d->m_currentEditor;
|
||||
}
|
||||
|
||||
void EditorManager::emptyView(Core::Internal::EditorView *view)
|
||||
{
|
||||
if (!view)
|
||||
return;
|
||||
|
||||
QList<IEditor *> editors = view->editors();
|
||||
foreach (IEditor *editor, editors) {
|
||||
if (!m_d->m_editorModel->isDuplicate(editor)) {
|
||||
editors.removeAll(editor);
|
||||
view->removeEditor(editor);
|
||||
continue;
|
||||
}
|
||||
emit editorAboutToClose(editor);
|
||||
removeEditor(editor);
|
||||
view->removeEditor(editor);
|
||||
}
|
||||
emit editorsClosed(editors);
|
||||
foreach (IEditor *editor, editors) {
|
||||
delete editor;
|
||||
}
|
||||
}
|
||||
|
||||
void EditorManager::closeView(Core::Internal::EditorView *view)
|
||||
{
|
||||
if (!view)
|
||||
return;
|
||||
|
||||
if (view == m_d->m_view) {
|
||||
if (IEditor *e = view->currentEditor())
|
||||
closeEditors(QList<IEditor *>() << e);
|
||||
return;
|
||||
}
|
||||
|
||||
emptyView(view);
|
||||
|
||||
SplitterOrView *splitterOrView = m_d->m_splitter->findView(view);
|
||||
Q_ASSERT(splitterOrView);
|
||||
Q_ASSERT(splitterOrView->view() == view);
|
||||
SplitterOrView *splitter = m_d->m_splitter->findSplitter(splitterOrView);
|
||||
Q_ASSERT(splitterOrView->hasEditors() == false);
|
||||
splitterOrView->hide();
|
||||
delete splitterOrView;
|
||||
|
||||
splitter->unsplit();
|
||||
|
||||
SplitterOrView *newCurrent = splitter->findFirstView();
|
||||
if (newCurrent) {
|
||||
if (newCurrent->editor())
|
||||
activateEditor(newCurrent->view(), newCurrent->editor());
|
||||
else
|
||||
setCurrentView(newCurrent);
|
||||
}
|
||||
}
|
||||
|
||||
QList<IEditor*>
|
||||
EditorManager::editorsForFiles(QList<IFile*> files) const
|
||||
{
|
||||
const QList<IEditor *> editors = openedEditors();
|
||||
QSet<IEditor *> found;
|
||||
foreach (IFile *file, files) {
|
||||
foreach (IEditor *editor, editors) {
|
||||
if (editor->file() == file && !found.contains(editor)) {
|
||||
found << editor;
|
||||
}
|
||||
}
|
||||
}
|
||||
return found.toList();
|
||||
}
|
||||
|
||||
QList<IFile *> EditorManager::filesForEditors(QList<IEditor *> editors) const
|
||||
{
|
||||
QSet<IEditor *> handledEditors;
|
||||
QList<IFile *> files;
|
||||
foreach (IEditor *editor, editors) {
|
||||
if (!handledEditors.contains(editor)) {
|
||||
files << editor->file();
|
||||
handledEditors.insert(editor);
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
bool EditorManager::closeAllEditors(bool askAboutModifiedEditors)
|
||||
{
|
||||
m_d->m_editorModel->removeAllRestoredEditors();
|
||||
if (closeEditors(openedEditors(), askAboutModifiedEditors)) {
|
||||
// m_d->clearNavigationHistory();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void EditorManager::closeOtherEditors(IEditor *editor)
|
||||
{
|
||||
m_d->m_editorModel->removeAllRestoredEditors();
|
||||
QList<IEditor*> editors = openedEditors();
|
||||
editors.removeAll(editor);
|
||||
closeEditors(editors, true);
|
||||
}
|
||||
|
||||
|
||||
void EditorManager::closeOtherEditors()
|
||||
{
|
||||
IEditor *current = currentEditor();
|
||||
QTC_ASSERT(current, return);
|
||||
closeOtherEditors(current);
|
||||
}
|
||||
|
||||
|
||||
// SLOT connected to action
|
||||
// since this is potentially called in the event handler of the editor
|
||||
// we simply postpone it with a single shot timer
|
||||
void EditorManager::closeEditor()
|
||||
{
|
||||
closeEditor(m_d->m_currentEditor);
|
||||
}
|
||||
|
||||
void EditorManager::closeEditor(Core::IEditor *editor)
|
||||
{
|
||||
if (!editor)
|
||||
return;
|
||||
closeEditors(QList<IEditor *>() << editor);
|
||||
}
|
||||
|
||||
void EditorManager::closeEditor(const QModelIndex &index)
|
||||
{
|
||||
IEditor *editor = index.data(Qt::UserRole).value<Core::IEditor*>();
|
||||
if (editor)
|
||||
closeEditor(editor);
|
||||
else
|
||||
m_d->m_editorModel->removeEditor(index);
|
||||
}
|
||||
|
||||
bool EditorManager::closeEditors(const QList<IEditor*> editorsToClose, bool askAboutModifiedEditors)
|
||||
{
|
||||
if (editorsToClose.isEmpty())
|
||||
return true;
|
||||
|
||||
SplitterOrView *currentSplitterOrView = this->currentSplitterOrView();
|
||||
|
||||
bool closingFailed = false;
|
||||
QList<IEditor*> acceptedEditors;
|
||||
//ask all core listeners to check whether the editor can be closed
|
||||
const QList<ICoreListener *> listeners =
|
||||
pluginManager()->getObjects<ICoreListener>();
|
||||
foreach (IEditor *editor, editorsToClose) {
|
||||
bool editorAccepted = true;
|
||||
if (m_d->m_editorModel->isDuplicate(editor))
|
||||
editor = m_d->m_editorModel->originalForDuplicate(editor);
|
||||
foreach (ICoreListener *listener, listeners) {
|
||||
if (!listener->editorAboutToClose(editor)) {
|
||||
editorAccepted = false;
|
||||
closingFailed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (editorAccepted)
|
||||
acceptedEditors.append(editor);
|
||||
}
|
||||
if (acceptedEditors.isEmpty())
|
||||
return false;
|
||||
//ask whether to save modified files
|
||||
if (askAboutModifiedEditors) {
|
||||
bool cancelled = false;
|
||||
QList<IFile*> list = m_d->m_core->fileManager()->
|
||||
saveModifiedFiles(filesForEditors(acceptedEditors), &cancelled);
|
||||
if (cancelled)
|
||||
return false;
|
||||
if (!list.isEmpty()) {
|
||||
closingFailed = true;
|
||||
QSet<IEditor*> skipSet = editorsForFiles(list).toSet();
|
||||
acceptedEditors = acceptedEditors.toSet().subtract(skipSet).toList();
|
||||
}
|
||||
}
|
||||
if (acceptedEditors.isEmpty())
|
||||
return false;
|
||||
|
||||
// add duplicates
|
||||
foreach(IEditor *editor, acceptedEditors)
|
||||
acceptedEditors += m_d->m_editorModel->duplicatesFor(editor);
|
||||
|
||||
QList<EditorView*> closedViews;
|
||||
|
||||
// remove the editors
|
||||
foreach (IEditor *editor, acceptedEditors) {
|
||||
emit editorAboutToClose(editor);
|
||||
if (!editor->file()->fileName().isEmpty()) {
|
||||
QByteArray state = editor->saveState();
|
||||
if (!state.isEmpty())
|
||||
m_d->m_editorStates.insert(editor->file()->fileName(), QVariant(state));
|
||||
}
|
||||
|
||||
removeEditor(editor);
|
||||
if (SplitterOrView *view = m_d->m_splitter->findView(editor)) {
|
||||
if (editor == view->view()->currentEditor())
|
||||
closedViews += view->view();
|
||||
view->view()->removeEditor(editor);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (EditorView *view, closedViews) {
|
||||
IEditor *newCurrent = view->currentEditor();
|
||||
if (!newCurrent)
|
||||
newCurrent = pickUnusedEditor();
|
||||
if (newCurrent) {
|
||||
activateEditor(view, newCurrent, NoActivate);
|
||||
} else {
|
||||
QModelIndex idx = m_d->m_editorModel->firstRestoredEditor();
|
||||
if (idx.isValid())
|
||||
activateEditor(idx, view, NoActivate);
|
||||
}
|
||||
}
|
||||
|
||||
emit editorsClosed(acceptedEditors);
|
||||
|
||||
foreach (IEditor *editor, acceptedEditors) {
|
||||
delete editor;
|
||||
}
|
||||
|
||||
if (currentSplitterOrView) {
|
||||
if (IEditor *editor = currentSplitterOrView->editor())
|
||||
activateEditor(currentSplitterOrView->view(), editor);
|
||||
}
|
||||
|
||||
if (!currentEditor())
|
||||
emit currentEditorChanged(0);
|
||||
|
||||
return !closingFailed;
|
||||
}
|
||||
|
||||
void EditorManager::closeDuplicate(Core::IEditor *editor)
|
||||
{
|
||||
|
||||
IEditor *original = editor;
|
||||
if (m_d->m_editorModel->isDuplicate(editor))
|
||||
original= m_d->m_editorModel->originalForDuplicate(editor);
|
||||
QList<IEditor *> duplicates = m_d->m_editorModel->duplicatesFor(original);
|
||||
|
||||
if (duplicates.isEmpty()) {
|
||||
closeEditor(editor);
|
||||
return;
|
||||
}
|
||||
|
||||
if (original== editor)
|
||||
m_d->m_editorModel->makeOriginal(duplicates.first());
|
||||
|
||||
SplitterOrView *currentSplitterOrView = this->currentSplitterOrView();
|
||||
|
||||
emit editorAboutToClose(editor);
|
||||
|
||||
EditorView *view = m_d->m_splitter->findView(editor)->view();
|
||||
removeEditor(editor);
|
||||
view->removeEditor(editor);
|
||||
|
||||
IEditor *newCurrent = view->currentEditor();
|
||||
if (!newCurrent)
|
||||
newCurrent = pickUnusedEditor();
|
||||
if (newCurrent) {
|
||||
activateEditor(view, newCurrent, NoActivate);
|
||||
} else {
|
||||
QModelIndex idx = m_d->m_editorModel->firstRestoredEditor();
|
||||
if (idx.isValid())
|
||||
activateEditor(idx, view, NoActivate);
|
||||
}
|
||||
|
||||
emit editorsClosed(QList<IEditor*>() << editor);
|
||||
delete editor;
|
||||
if (currentSplitterOrView) {
|
||||
if (IEditor *currentEditor = currentSplitterOrView->editor())
|
||||
activateEditor(currentSplitterOrView->view(), currentEditor);
|
||||
}
|
||||
}
|
||||
|
||||
Core::IEditor *EditorManager::pickUnusedEditor() const
|
||||
{
|
||||
foreach (IEditor *editor, openedEditors()) {
|
||||
SplitterOrView *view = m_d->m_splitter->findView(editor);
|
||||
if (!view || view->editor() != editor)
|
||||
return editor;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Core::IEditor *EditorManager::activateEditor(const QModelIndex &index, Internal::EditorView *view, OpenEditorFlags flags)
|
||||
{
|
||||
IEditor *editor = index.data(Qt::UserRole).value<IEditor*>();
|
||||
if (editor) {
|
||||
return activateEditor(view, editor, flags);
|
||||
}
|
||||
|
||||
QString fileName = index.data(Qt::UserRole + 1).toString();
|
||||
QByteArray kind = index.data(Qt::UserRole + 2).toByteArray();
|
||||
return openEditor(view, fileName, kind, flags);
|
||||
}
|
||||
|
||||
Core::IEditor *EditorManager::placeEditor(Core::Internal::EditorView *view, Core::IEditor *editor)
|
||||
{
|
||||
Q_ASSERT(view && editor);
|
||||
|
||||
if (view->currentEditor() && view->currentEditor()->file() == editor->file())
|
||||
editor = view->currentEditor();
|
||||
|
||||
if (!view->hasEditor(editor)) {
|
||||
bool duplicateSupported = editor->duplicateSupported();
|
||||
if (SplitterOrView *sourceView = m_d->m_splitter->findView(editor)) {
|
||||
if (editor != sourceView->editor() || !duplicateSupported) {
|
||||
sourceView->view()->removeEditor(editor);
|
||||
view->addEditor(editor);
|
||||
view->setCurrentEditor(editor);
|
||||
if (!sourceView->editor()) {
|
||||
if (IEditor *replacement = pickUnusedEditor()) {
|
||||
sourceView->view()->addEditor(replacement);
|
||||
}
|
||||
}
|
||||
return editor;
|
||||
} else if (duplicateSupported) {
|
||||
editor = duplicateEditor(editor);
|
||||
Q_ASSERT(editor);
|
||||
m_d->m_editorModel->makeOriginal(editor);
|
||||
}
|
||||
}
|
||||
view->addEditor(editor);
|
||||
}
|
||||
return editor;
|
||||
}
|
||||
|
||||
Core::IEditor *EditorManager::activateEditor(Core::IEditor *editor, OpenEditorFlags flags)
|
||||
{
|
||||
return activateEditor(0, editor, flags);
|
||||
}
|
||||
|
||||
Core::IEditor *EditorManager::activateEditor(Core::Internal::EditorView *view, Core::IEditor *editor, OpenEditorFlags flags)
|
||||
{
|
||||
if (!view)
|
||||
view = currentEditorView();
|
||||
|
||||
Q_ASSERT(view);
|
||||
|
||||
if (!editor) {
|
||||
if (!m_d->m_currentEditor)
|
||||
setCurrentEditor(0, (flags & IgnoreNavigationHistory));
|
||||
return 0;
|
||||
}
|
||||
|
||||
editor = placeEditor(view, editor);
|
||||
|
||||
if (!(flags & NoActivate)) {
|
||||
setCurrentEditor(editor, (flags & IgnoreNavigationHistory));
|
||||
if (!(flags & NoModeSwitch))
|
||||
ensureEditorManagerVisible();
|
||||
if (isVisible())
|
||||
editor->widget()->setFocus();
|
||||
}
|
||||
return editor;
|
||||
}
|
||||
|
||||
Core::IEditor *EditorManager::activateEditor(Core::Internal::EditorView *view, Core::IFile *file, OpenEditorFlags flags)
|
||||
{
|
||||
QList<IEditor*> editors = editorsForFile(file);
|
||||
Q_ASSERT(!editors.isEmpty());
|
||||
return activateEditor(view, editors.first(), flags);
|
||||
}
|
||||
|
||||
/* For something that has a 'QStringList mimeTypes' (IEditorFactory
|
||||
* or IExternalEditor), find the one best matching the mimetype passed in.
|
||||
* Recurse over the parent classes of the mimetype to find them. */
|
||||
template <class EditorFactoryLike>
|
||||
static void mimeTypeFactoryRecursion(const MimeDatabase *db,
|
||||
const MimeType &mimeType,
|
||||
const QList<EditorFactoryLike*> &allFactories,
|
||||
bool firstMatchOnly,
|
||||
QList<EditorFactoryLike*> *list)
|
||||
{
|
||||
typedef typename QList<EditorFactoryLike*>::const_iterator EditorFactoryLikeListConstIterator;
|
||||
// Loop factories to find type
|
||||
const QString type = mimeType.type();
|
||||
const EditorFactoryLikeListConstIterator fcend = allFactories.constEnd();
|
||||
for (EditorFactoryLikeListConstIterator fit = allFactories.constBegin(); fit != fcend; ++fit) {
|
||||
// Exclude duplicates when recursing over xml or C++ -> C -> text.
|
||||
EditorFactoryLike *factory = *fit;
|
||||
if (!list->contains(factory) && factory->mimeTypes().contains(type)) {
|
||||
list->push_back(*fit);
|
||||
if (firstMatchOnly)
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Any parent mime type classes? -> recurse
|
||||
QStringList parentTypes = mimeType.subClassesOf();
|
||||
if (parentTypes.empty())
|
||||
return;
|
||||
const QStringList::const_iterator pcend = parentTypes .constEnd();
|
||||
for (QStringList::const_iterator pit = parentTypes .constBegin(); pit != pcend; ++pit) {
|
||||
if (const MimeType parent = db->findByType(*pit))
|
||||
mimeTypeFactoryRecursion(db, parent, allFactories, firstMatchOnly, list);
|
||||
}
|
||||
}
|
||||
|
||||
EditorManager::EditorFactoryList
|
||||
EditorManager::editorFactories(const MimeType &mimeType, bool bestMatchOnly) const
|
||||
{
|
||||
EditorFactoryList rc;
|
||||
const EditorFactoryList allFactories = pluginManager()->getObjects<IEditorFactory>();
|
||||
mimeTypeFactoryRecursion(m_d->m_core->mimeDatabase(), mimeType, allFactories, bestMatchOnly, &rc);
|
||||
if (debugEditorManager)
|
||||
qDebug() << Q_FUNC_INFO << mimeType.type() << " returns " << rc;
|
||||
return rc;
|
||||
}
|
||||
|
||||
EditorManager::ExternalEditorList
|
||||
EditorManager::externalEditors(const MimeType &mimeType, bool bestMatchOnly) const
|
||||
{
|
||||
ExternalEditorList rc;
|
||||
const ExternalEditorList allEditors = pluginManager()->getObjects<IExternalEditor>();
|
||||
mimeTypeFactoryRecursion(m_d->m_core->mimeDatabase(), mimeType, allEditors, bestMatchOnly, &rc);
|
||||
if (debugEditorManager)
|
||||
qDebug() << Q_FUNC_INFO << mimeType.type() << " returns " << rc;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* For something that has a 'QString kind' (IEditorFactory
|
||||
* or IExternalEditor), find the one matching a kind. */
|
||||
template <class EditorFactoryLike>
|
||||
inline EditorFactoryLike *findByKind(ExtensionSystem::PluginManager *pm,
|
||||
const QString &kind)
|
||||
{
|
||||
const QList<EditorFactoryLike *> factories = pm->template getObjects<EditorFactoryLike>();
|
||||
foreach(EditorFactoryLike *efl, factories)
|
||||
if (kind == efl->kind())
|
||||
return efl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
IEditor *EditorManager::createEditor(const QString &editorKind,
|
||||
const QString &fileName)
|
||||
{
|
||||
typedef QList<IEditorFactory*> FactoryList;
|
||||
if (debugEditorManager)
|
||||
qDebug() << Q_FUNC_INFO << editorKind << fileName;
|
||||
|
||||
|
||||
EditorFactoryList factories;
|
||||
if (editorKind.isEmpty()) {
|
||||
// Find by mime type
|
||||
MimeType mimeType = m_d->m_core->mimeDatabase()->findByFile(QFileInfo(fileName));
|
||||
if (!mimeType) {
|
||||
qWarning("%s unable to determine mime type of %s/%s. Falling back to text/plain",
|
||||
Q_FUNC_INFO, fileName.toUtf8().constData(), editorKind.toUtf8().constData());
|
||||
mimeType = m_d->m_core->mimeDatabase()->findByType(QLatin1String("text/plain"));
|
||||
}
|
||||
factories = editorFactories(mimeType, true);
|
||||
} else {
|
||||
// Find by editor kind
|
||||
if (IEditorFactory *factory = findByKind<IEditorFactory>(pluginManager(), editorKind))
|
||||
factories.push_back(factory);
|
||||
}
|
||||
if (factories.empty()) {
|
||||
qWarning("%s: unable to find an editor factory for the file '%s', editor kind '%s'.",
|
||||
Q_FUNC_INFO, fileName.toUtf8().constData(), editorKind.toUtf8().constData());
|
||||
return 0;
|
||||
}
|
||||
|
||||
IEditor *editor = factories.front()->createEditor(this);
|
||||
if (editor)
|
||||
connect(editor, SIGNAL(changed()), this, SLOT(updateActions()));
|
||||
if (editor)
|
||||
emit editorCreated(editor, fileName);
|
||||
return editor;
|
||||
}
|
||||
|
||||
void EditorManager::addEditor(IEditor *editor, bool isDuplicate)
|
||||
{
|
||||
if (!editor)
|
||||
return;
|
||||
m_d->m_core->addContextObject(editor);
|
||||
|
||||
m_d->m_editorModel->addEditor(editor, isDuplicate);
|
||||
if (!isDuplicate) {
|
||||
m_d->m_core->fileManager()->addFile(editor->file());
|
||||
if (!editor->isTemporary()) {
|
||||
m_d->m_core->fileManager()->addToRecentFiles(editor->file()->fileName());
|
||||
}
|
||||
}
|
||||
emit editorOpened(editor);
|
||||
}
|
||||
|
||||
// Run the OpenWithDialog and return the editor kind
|
||||
// selected by the user.
|
||||
QString EditorManager::getOpenWithEditorKind(const QString &fileName,
|
||||
bool *isExternalEditor) const
|
||||
{
|
||||
// Collect editors that can open the file
|
||||
const MimeType mt = m_d->m_core->mimeDatabase()->findByFile(fileName);
|
||||
if (!mt)
|
||||
return QString();
|
||||
QStringList allEditorKinds;
|
||||
QStringList externalEditorKinds;
|
||||
// Built-in
|
||||
const EditorFactoryList editors = editorFactories(mt, false);
|
||||
const int size = editors.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
allEditorKinds.push_back(editors.at(i)->kind());
|
||||
}
|
||||
// External editors
|
||||
const ExternalEditorList exEditors = externalEditors(mt, false);
|
||||
const int esize = exEditors.size();
|
||||
for (int i = 0; i < esize; i++) {
|
||||
externalEditorKinds.push_back(exEditors.at(i)->kind());
|
||||
allEditorKinds.push_back(exEditors.at(i)->kind());
|
||||
}
|
||||
if (allEditorKinds.empty())
|
||||
return QString();
|
||||
// Run dialog.
|
||||
OpenWithDialog dialog(fileName, m_d->m_core->mainWindow());
|
||||
dialog.setEditors(allEditorKinds);
|
||||
dialog.setCurrentEditor(0);
|
||||
if (dialog.exec() != QDialog::Accepted)
|
||||
return QString();
|
||||
const QString selectedKind = dialog.editor();
|
||||
if (isExternalEditor)
|
||||
*isExternalEditor = externalEditorKinds.contains(selectedKind);
|
||||
return selectedKind;
|
||||
}
|
||||
|
||||
static QString formatFileFilters(const Core::ICore *core, QString *selectedFilter)
|
||||
{
|
||||
QString rc;
|
||||
// Compile list of filter strings. If we find a glob matching all files,
|
||||
// put it last and set it as default selectedFilter.
|
||||
QStringList filters = core->mimeDatabase()->filterStrings();
|
||||
filters.sort();
|
||||
selectedFilter->clear();
|
||||
if (filters.empty())
|
||||
return rc;
|
||||
const QString filterSeparator = QLatin1String(";;");
|
||||
bool hasAllFilter = false;
|
||||
const int size = filters.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
const QString &filterString = filters.at(i);
|
||||
if (filterString.isEmpty()) { // binary editor
|
||||
hasAllFilter = true;
|
||||
} else {
|
||||
if (!rc.isEmpty())
|
||||
rc += filterSeparator;
|
||||
rc += filterString;
|
||||
}
|
||||
}
|
||||
if (hasAllFilter) {
|
||||
// prepend all files filter
|
||||
// prepending instead of appending to work around a but in Qt/Mac
|
||||
QString allFilesFilter = EditorManager::tr("All Files (*)");
|
||||
if (!rc.isEmpty())
|
||||
allFilesFilter += filterSeparator;
|
||||
rc.prepend(allFilesFilter);
|
||||
*selectedFilter = allFilesFilter;
|
||||
} else {
|
||||
*selectedFilter = filters.front();
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
IEditor *EditorManager::openEditor(const QString &fileName, const QString &editorKind,
|
||||
EditorManager::OpenEditorFlags flags)
|
||||
{
|
||||
return openEditor(0, fileName, editorKind, flags);
|
||||
}
|
||||
|
||||
IEditor *EditorManager::openEditor(Core::Internal::EditorView *view, const QString &fileName,
|
||||
const QString &editorKind, EditorManager::OpenEditorFlags flags)
|
||||
{
|
||||
if (debugEditorManager)
|
||||
qDebug() << Q_FUNC_INFO << fileName << editorKind;
|
||||
|
||||
if (fileName.isEmpty())
|
||||
return 0;
|
||||
|
||||
const QList<IEditor *> editors = editorsForFileName(fileName);
|
||||
if (!editors.isEmpty()) {
|
||||
return activateEditor(view, editors.first(), flags);
|
||||
}
|
||||
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
|
||||
IEditor *editor = createEditor(editorKind, fileName);
|
||||
if (!editor || !editor->open(fileName)) {
|
||||
QApplication::restoreOverrideCursor();
|
||||
QMessageBox::critical(m_d->m_core->mainWindow(), tr("Opening File"), tr("Cannot open file %1!").arg(QDir::toNativeSeparators(fileName)));
|
||||
delete editor;
|
||||
editor = 0;
|
||||
return 0;
|
||||
}
|
||||
addEditor(editor);
|
||||
|
||||
IEditor *result= activateEditor(view, editor, flags);
|
||||
if (editor == result)
|
||||
restoreEditorState(editor);
|
||||
QApplication::restoreOverrideCursor();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool EditorManager::openExternalEditor(const QString &fileName, const QString &editorKind)
|
||||
{
|
||||
IExternalEditor *ee = findByKind<IExternalEditor>(pluginManager(), editorKind);
|
||||
if (!ee)
|
||||
return false;
|
||||
QString errorMessage;
|
||||
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
|
||||
const bool ok = ee->startEditor(fileName, &errorMessage);
|
||||
QApplication::restoreOverrideCursor();
|
||||
if (!ok)
|
||||
QMessageBox::critical(m_d->m_core->mainWindow(), tr("Opening File"), errorMessage);
|
||||
return ok;
|
||||
}
|
||||
|
||||
QStringList EditorManager::getOpenFileNames() const
|
||||
{
|
||||
static QString dir = QDir::homePath();
|
||||
if (m_d->fileFilters.isEmpty())
|
||||
m_d->fileFilters = formatFileFilters(m_d->m_core, &m_d->selectedFilter);
|
||||
|
||||
QString currentFile = ICore::instance()->fileManager()->currentFile();
|
||||
if (!currentFile.isEmpty()) {
|
||||
const QFileInfo fi(currentFile);
|
||||
dir = fi.absolutePath();
|
||||
}
|
||||
|
||||
QStringList files = QFileDialog::getOpenFileNames(m_d->m_core->mainWindow(), tr("Open File"),
|
||||
dir, m_d->fileFilters, &m_d->selectedFilter);
|
||||
if (!files.isEmpty())
|
||||
dir = QFileInfo(files.at(0)).absolutePath();
|
||||
return files;
|
||||
}
|
||||
|
||||
void EditorManager::ensureEditorManagerVisible()
|
||||
{
|
||||
if (!isVisible())
|
||||
m_d->m_core->modeManager()->activateMode(Constants::MODE_EDIT);
|
||||
}
|
||||
|
||||
IEditor *EditorManager::openEditorWithContents(const QString &editorKind,
|
||||
QString *titlePattern,
|
||||
const QString &contents)
|
||||
{
|
||||
if (debugEditorManager)
|
||||
qDebug() << Q_FUNC_INFO << editorKind << titlePattern << contents;
|
||||
|
||||
if (editorKind.isEmpty())
|
||||
return 0;
|
||||
|
||||
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
|
||||
IEditor *edt = createEditor(editorKind);
|
||||
if (!edt) {
|
||||
QApplication::restoreOverrideCursor();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!edt->createNew(contents)) {
|
||||
QApplication::restoreOverrideCursor();
|
||||
delete edt;
|
||||
edt = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
QString title = edt->displayName();
|
||||
|
||||
if (title.isEmpty() && titlePattern) {
|
||||
const QChar dollar = QLatin1Char('$');
|
||||
const QChar dot = QLatin1Char('.');
|
||||
|
||||
QString base = *titlePattern;
|
||||
if (base.isEmpty())
|
||||
base = QLatin1String("unnamed$");
|
||||
if (base.contains(dollar)) {
|
||||
int i = 1;
|
||||
QSet<QString> docnames;
|
||||
foreach (IEditor *editor, openedEditors()) {
|
||||
QString name = editor->file()->fileName();
|
||||
if (name.isEmpty()) {
|
||||
name = editor->displayName();
|
||||
name.remove(QLatin1Char('*'));
|
||||
} else {
|
||||
name = QFileInfo(name).completeBaseName();
|
||||
}
|
||||
docnames << name;
|
||||
}
|
||||
|
||||
do {
|
||||
title = base;
|
||||
title.replace(QString(dollar), QString::number(i++));
|
||||
} while (docnames.contains(title));
|
||||
} else {
|
||||
title = *titlePattern;
|
||||
}
|
||||
}
|
||||
*titlePattern = title;
|
||||
edt->setDisplayName(title);
|
||||
addEditor(edt);
|
||||
QApplication::restoreOverrideCursor();
|
||||
return edt;
|
||||
}
|
||||
|
||||
bool EditorManager::hasEditor(const QString &fileName) const
|
||||
{
|
||||
return !editorsForFileName(fileName).isEmpty();
|
||||
}
|
||||
|
||||
void EditorManager::restoreEditorState(IEditor *editor)
|
||||
{
|
||||
QTC_ASSERT(editor, return);
|
||||
QString fileName = editor->file()->fileName();
|
||||
if (m_d->m_editorStates.contains(fileName))
|
||||
editor->restoreState(m_d->m_editorStates.value(fileName).toByteArray());
|
||||
}
|
||||
|
||||
bool EditorManager::saveEditor(IEditor *editor)
|
||||
{
|
||||
return saveFile(editor);
|
||||
}
|
||||
|
||||
bool EditorManager::saveFile(IEditor *editor)
|
||||
{
|
||||
if (!editor)
|
||||
editor = currentEditor();
|
||||
if (!editor)
|
||||
return false;
|
||||
|
||||
IFile *file = editor->file();
|
||||
file->checkPermissions();
|
||||
|
||||
const QString &fileName = file->fileName();
|
||||
|
||||
if (fileName.isEmpty())
|
||||
return saveFileAs(editor);
|
||||
|
||||
bool success = false;
|
||||
|
||||
// try saving, no matter what isReadOnly tells us
|
||||
m_d->m_core->fileManager()->blockFileChange(file);
|
||||
success = file->save(fileName);
|
||||
m_d->m_core->fileManager()->unblockFileChange(file);
|
||||
|
||||
if (!success) {
|
||||
MakeWritableResult answer =
|
||||
makeEditorWritable(editor);
|
||||
if (answer == Failed)
|
||||
return false;
|
||||
if (answer == SavedAs)
|
||||
return true;
|
||||
|
||||
file->checkPermissions();
|
||||
|
||||
m_d->m_core->fileManager()->blockFileChange(file);
|
||||
success = file->save(fileName);
|
||||
m_d->m_core->fileManager()->unblockFileChange(file);
|
||||
}
|
||||
|
||||
if (success && !editor->isTemporary())
|
||||
m_d->m_core->fileManager()->addToRecentFiles(editor->file()->fileName());
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
EditorManager::ReadOnlyAction
|
||||
EditorManager::promptReadOnlyFile(const QString &fileName,
|
||||
const IVersionControl *versionControl,
|
||||
QWidget *parent,
|
||||
bool displaySaveAsButton)
|
||||
{
|
||||
QMessageBox msgBox(QMessageBox::Question, tr("File is Read Only"),
|
||||
tr("The file %1 is read only.").arg(QDir::toNativeSeparators(fileName)),
|
||||
QMessageBox::Cancel, parent);
|
||||
|
||||
QPushButton *sccButton = 0;
|
||||
if (versionControl && versionControl->supportsOperation(IVersionControl::OpenOperation))
|
||||
sccButton = msgBox.addButton(tr("Open with VCS (%1)").arg(versionControl->name()), QMessageBox::AcceptRole);
|
||||
|
||||
QPushButton *makeWritableButton = msgBox.addButton(tr("Make writable"), QMessageBox::AcceptRole);
|
||||
|
||||
QPushButton *saveAsButton = 0;
|
||||
if (displaySaveAsButton)
|
||||
saveAsButton = msgBox.addButton(tr("Save as ..."), QMessageBox::ActionRole);
|
||||
|
||||
msgBox.setDefaultButton(sccButton ? sccButton : makeWritableButton);
|
||||
msgBox.exec();
|
||||
|
||||
QAbstractButton *clickedButton = msgBox.clickedButton();
|
||||
if (clickedButton == sccButton)
|
||||
return RO_OpenVCS;
|
||||
if (clickedButton == makeWritableButton)
|
||||
return RO_MakeWriteable;
|
||||
if (clickedButton == saveAsButton)
|
||||
return RO_SaveAs;
|
||||
return RO_Cancel;
|
||||
}
|
||||
|
||||
|
||||
MakeWritableResult
|
||||
EditorManager::makeEditorWritable(IEditor *editor)
|
||||
{
|
||||
if (!editor || !editor->file())
|
||||
return Failed;
|
||||
QString directory = QFileInfo(editor->file()->fileName()).absolutePath();
|
||||
IVersionControl *versionControl = m_d->m_core->vcsManager()->findVersionControlForDirectory(directory);
|
||||
IFile *file = editor->file();
|
||||
const QString &fileName = file->fileName();
|
||||
|
||||
switch (promptReadOnlyFile(fileName, versionControl, m_d->m_core->mainWindow(), true)) {
|
||||
case RO_OpenVCS:
|
||||
if (!versionControl->vcsOpen(fileName)) {
|
||||
QMessageBox::warning(m_d->m_core->mainWindow(), tr("Failed!"), tr("Could not open the file for editing with SCC."));
|
||||
return Failed;
|
||||
}
|
||||
file->checkPermissions();
|
||||
return OpenedWithVersionControl;
|
||||
case RO_MakeWriteable: {
|
||||
const bool permsOk = QFile::setPermissions(fileName, QFile::permissions(fileName) | QFile::WriteUser);
|
||||
if (!permsOk) {
|
||||
QMessageBox::warning(m_d->m_core->mainWindow(), tr("Failed!"), tr("Could not set permissions to writable."));
|
||||
return Failed;
|
||||
}
|
||||
}
|
||||
file->checkPermissions();
|
||||
return MadeWritable;
|
||||
case RO_SaveAs :
|
||||
return saveFileAs(editor) ? SavedAs : Failed;
|
||||
case RO_Cancel:
|
||||
break;
|
||||
}
|
||||
return Failed;
|
||||
}
|
||||
|
||||
bool EditorManager::saveFileAs(IEditor *editor)
|
||||
{
|
||||
if (!editor)
|
||||
editor = currentEditor();
|
||||
if (!editor)
|
||||
return false;
|
||||
|
||||
QString absoluteFilePath = m_d->m_core->fileManager()->getSaveAsFileName(editor->file());
|
||||
if (absoluteFilePath.isEmpty())
|
||||
return false;
|
||||
if (absoluteFilePath != editor->file()->fileName()) {
|
||||
const QList<IEditor *> existList = editorsForFileName(absoluteFilePath);
|
||||
if (!existList.isEmpty()) {
|
||||
closeEditors(existList, false);
|
||||
}
|
||||
}
|
||||
|
||||
m_d->m_core->fileManager()->blockFileChange(editor->file());
|
||||
const bool success = editor->file()->save(absoluteFilePath);
|
||||
m_d->m_core->fileManager()->unblockFileChange(editor->file());
|
||||
editor->file()->checkPermissions();
|
||||
|
||||
if (success && !editor->isTemporary())
|
||||
m_d->m_core->fileManager()->addToRecentFiles(editor->file()->fileName());
|
||||
|
||||
updateActions();
|
||||
return success;
|
||||
}
|
||||
|
||||
void EditorManager::gotoNextDocHistory()
|
||||
{
|
||||
OpenEditorsWindow *dialog = windowPopup();
|
||||
if (dialog->isVisible()) {
|
||||
dialog->selectNextEditor();
|
||||
} else {
|
||||
EditorView *view = currentEditorView();
|
||||
dialog->setEditors(m_d->m_view, view, m_d->m_editorModel);
|
||||
dialog->selectNextEditor();
|
||||
showWindowPopup();
|
||||
}
|
||||
}
|
||||
|
||||
void EditorManager::gotoPreviousDocHistory()
|
||||
{
|
||||
OpenEditorsWindow *dialog = windowPopup();
|
||||
if (dialog->isVisible()) {
|
||||
dialog->selectPreviousEditor();
|
||||
} else {
|
||||
EditorView *view = currentEditorView();
|
||||
dialog->setEditors(m_d->m_view, view, m_d->m_editorModel);
|
||||
dialog->selectPreviousEditor();
|
||||
showWindowPopup();
|
||||
}
|
||||
}
|
||||
|
||||
void EditorManager::makeCurrentEditorWritable()
|
||||
{
|
||||
if (IEditor* curEditor = currentEditor())
|
||||
makeEditorWritable(curEditor);
|
||||
}
|
||||
|
||||
void EditorManager::updateActions()
|
||||
{
|
||||
QString fName;
|
||||
IEditor *curEditor = currentEditor();
|
||||
int openedCount = openedEditors().count() + m_d->m_editorModel->restoredEditorCount();
|
||||
if (curEditor) {
|
||||
if (!curEditor->file()->fileName().isEmpty()) {
|
||||
QFileInfo fi(curEditor->file()->fileName());
|
||||
fName = fi.fileName();
|
||||
} else {
|
||||
fName = curEditor->displayName();
|
||||
}
|
||||
|
||||
|
||||
if (curEditor->file()->isModified() && curEditor->file()->isReadOnly()) {
|
||||
// we are about to change a read-only file, warn user
|
||||
showEditorInfoBar(QLatin1String("Core.EditorManager.MakeWritable"),
|
||||
tr("<b>Warning:</b> You are changing a read-only file."),
|
||||
tr("Make writable"), this, SLOT(makeCurrentEditorWritable()));
|
||||
} else {
|
||||
hideEditorInfoBar(QLatin1String("Core.EditorManager.MakeWritable"));
|
||||
}
|
||||
}
|
||||
|
||||
m_d->m_saveAction->setEnabled(curEditor != 0 && curEditor->file()->isModified());
|
||||
m_d->m_saveAsAction->setEnabled(curEditor != 0 && curEditor->file()->isSaveAsAllowed());
|
||||
m_d->m_revertToSavedAction->setEnabled(curEditor != 0
|
||||
&& !curEditor->file()->fileName().isEmpty() && curEditor->file()->isModified());
|
||||
|
||||
QString quotedName;
|
||||
if (!fName.isEmpty())
|
||||
quotedName = '"' + fName + '"';
|
||||
m_d->m_saveAsAction->setText(tr("Save %1 As...").arg(quotedName));
|
||||
m_d->m_saveAction->setText(tr("&Save %1").arg(quotedName));
|
||||
m_d->m_revertToSavedAction->setText(tr("Revert %1 to Saved").arg(quotedName));
|
||||
|
||||
|
||||
m_d->m_closeCurrentEditorAction->setEnabled(curEditor != 0);
|
||||
m_d->m_closeCurrentEditorAction->setText(tr("Close %1").arg(quotedName));
|
||||
m_d->m_closeAllEditorsAction->setEnabled(openedCount > 0);
|
||||
m_d->m_closeOtherEditorsAction->setEnabled(openedCount > 1);
|
||||
m_d->m_closeOtherEditorsAction->setText((openedCount > 1 ? tr("Close All Except %1").arg(quotedName) : tr("Close Others")));
|
||||
|
||||
m_d->m_gotoNextDocHistoryAction->setEnabled(m_d->m_editorModel->rowCount() != 0);
|
||||
m_d->m_gotoPreviousDocHistoryAction->setEnabled(m_d->m_editorModel->rowCount() != 0);
|
||||
EditorView *view = currentEditorView();
|
||||
m_d->m_goBackAction->setEnabled(view ? view->canGoBack() : false);
|
||||
m_d->m_goForwardAction->setEnabled(view ? view->canGoForward() : false);
|
||||
|
||||
bool hasSplitter = m_d->m_splitter->isSplitter();
|
||||
m_d->m_removeCurrentSplitAction->setEnabled(hasSplitter);
|
||||
m_d->m_removeAllSplitsAction->setEnabled(hasSplitter);
|
||||
m_d->m_gotoOtherSplitAction->setEnabled(hasSplitter);
|
||||
|
||||
m_d->m_openInExternalEditorAction->setEnabled(curEditor != 0);
|
||||
}
|
||||
|
||||
QList<IEditor*> EditorManager::openedEditors() const
|
||||
{
|
||||
return m_d->m_editorModel->editors();
|
||||
}
|
||||
|
||||
OpenEditorsModel *EditorManager::openedEditorsModel() const
|
||||
{
|
||||
return m_d->m_editorModel;
|
||||
}
|
||||
|
||||
void EditorManager::addCurrentPositionToNavigationHistory(IEditor *editor, const QByteArray &saveState)
|
||||
{
|
||||
currentEditorView()->addCurrentPositionToNavigationHistory(editor, saveState);
|
||||
updateActions();
|
||||
}
|
||||
|
||||
void EditorManager::goBackInNavigationHistory()
|
||||
{
|
||||
currentEditorView()->goBackInNavigationHistory();
|
||||
updateActions();
|
||||
ensureEditorManagerVisible();
|
||||
return;
|
||||
}
|
||||
|
||||
void EditorManager::goForwardInNavigationHistory()
|
||||
{
|
||||
currentEditorView()->goForwardInNavigationHistory();
|
||||
updateActions();
|
||||
ensureEditorManagerVisible();
|
||||
}
|
||||
|
||||
OpenEditorsWindow *EditorManager::windowPopup() const
|
||||
{
|
||||
return m_d->m_windowPopup;
|
||||
}
|
||||
|
||||
void EditorManager::showWindowPopup() const
|
||||
{
|
||||
const QPoint p(mapToGlobal(QPoint(0, 0)));
|
||||
m_d->m_windowPopup->move((width()-m_d->m_windowPopup->width())/2 + p.x(),
|
||||
(height()-m_d->m_windowPopup->height())/2 + p.y());
|
||||
m_d->m_windowPopup->setVisible(true);
|
||||
}
|
||||
|
||||
QByteArray EditorManager::saveState() const
|
||||
{
|
||||
QByteArray bytes;
|
||||
QDataStream stream(&bytes, QIODevice::WriteOnly);
|
||||
|
||||
stream << QByteArray("EditorManagerV4");
|
||||
|
||||
QList<IEditor *> editors = openedEditors();
|
||||
foreach (IEditor *editor, editors) {
|
||||
if (!editor->file()->fileName().isEmpty()) {
|
||||
QByteArray state = editor->saveState();
|
||||
if (!state.isEmpty())
|
||||
m_d->m_editorStates.insert(editor->file()->fileName(), QVariant(state));
|
||||
}
|
||||
}
|
||||
|
||||
stream << m_d->m_editorStates;
|
||||
|
||||
QList<OpenEditorsModel::Entry> entries = m_d->m_editorModel->entries();
|
||||
stream << entries.count();
|
||||
|
||||
foreach (OpenEditorsModel::Entry entry, entries) {
|
||||
stream << entry.fileName() << entry.displayName() << entry.kind();
|
||||
}
|
||||
|
||||
stream << m_d->m_splitter->saveState();
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
bool EditorManager::restoreState(const QByteArray &state)
|
||||
{
|
||||
closeAllEditors(true);
|
||||
removeAllSplits();
|
||||
QDataStream stream(state);
|
||||
|
||||
QByteArray version;
|
||||
stream >> version;
|
||||
|
||||
if (version != "EditorManagerV4")
|
||||
return false;
|
||||
|
||||
QMap<QString, QVariant> editorstates;
|
||||
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
stream >> editorstates;
|
||||
|
||||
QMapIterator<QString, QVariant> i(editorstates);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
m_d->m_editorStates.insert(i.key(), i.value());
|
||||
}
|
||||
|
||||
int editorCount = 0;
|
||||
stream >> editorCount;
|
||||
while (--editorCount >= 0) {
|
||||
QString fileName;
|
||||
stream >> fileName;
|
||||
QString displayName;
|
||||
stream >> displayName;
|
||||
QByteArray kind;
|
||||
stream >> kind;
|
||||
|
||||
if (!fileName.isEmpty() && !displayName.isEmpty()){
|
||||
m_d->m_editorModel->addRestoredEditor(fileName, displayName, kind);
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray splitterstates;
|
||||
stream >> splitterstates;
|
||||
m_d->m_splitter->restoreState(splitterstates);
|
||||
|
||||
// splitting and stuff results in focus trouble, that's why we set the focus again after restoration
|
||||
ensureEditorManagerVisible();
|
||||
if (m_d->m_currentEditor) {
|
||||
m_d->m_currentEditor->widget()->setFocus();
|
||||
} else if (Core::Internal::SplitterOrView *view = currentSplitterOrView()) {
|
||||
if (IEditor *e = view->editor())
|
||||
e->widget()->setFocus();
|
||||
else if (view->view())
|
||||
view->view()->setFocus();
|
||||
}
|
||||
|
||||
QApplication::restoreOverrideCursor();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char * const documentStatesKey = "EditorManager/DocumentStates";
|
||||
static const char * const externalEditorKey = "EditorManager/ExternalEditorCommand";
|
||||
static const char * const reloadBehaviorKey = "EditorManager/ReloadBehavior";
|
||||
|
||||
void EditorManager::saveSettings()
|
||||
{
|
||||
SettingsDatabase *settings = m_d->m_core->settingsDatabase();
|
||||
settings->setValue(QLatin1String(documentStatesKey), m_d->m_editorStates);
|
||||
settings->setValue(QLatin1String(externalEditorKey), m_d->m_externalEditor);
|
||||
settings->setValue(QLatin1String(reloadBehaviorKey), m_d->m_reloadBehavior);
|
||||
}
|
||||
|
||||
void EditorManager::readSettings()
|
||||
{
|
||||
// Backward compatibility to old locations for these settings
|
||||
QSettings *qs = m_d->m_core->settings();
|
||||
if (qs->contains(QLatin1String(documentStatesKey))) {
|
||||
m_d->m_editorStates = qs->value(QLatin1String(documentStatesKey))
|
||||
.value<QMap<QString, QVariant> >();
|
||||
qs->remove(QLatin1String(documentStatesKey));
|
||||
}
|
||||
if (qs->contains(QLatin1String(externalEditorKey))) {
|
||||
m_d->m_externalEditor = qs->value(QLatin1String(externalEditorKey)).toString();
|
||||
qs->remove(QLatin1String(externalEditorKey));
|
||||
}
|
||||
|
||||
SettingsDatabase *settings = m_d->m_core->settingsDatabase();
|
||||
if (settings->contains(QLatin1String(documentStatesKey)))
|
||||
m_d->m_editorStates = settings->value(QLatin1String(documentStatesKey))
|
||||
.value<QMap<QString, QVariant> >();
|
||||
if (settings->contains(QLatin1String(externalEditorKey)))
|
||||
m_d->m_externalEditor = settings->value(QLatin1String(externalEditorKey)).toString();
|
||||
|
||||
if (settings->contains(QLatin1String(reloadBehaviorKey)))
|
||||
m_d->m_reloadBehavior = (IFile::ReloadBehavior)settings->value(QLatin1String(reloadBehaviorKey)).toInt();
|
||||
}
|
||||
|
||||
|
||||
void EditorManager::revertToSaved()
|
||||
{
|
||||
IEditor *currEditor = currentEditor();
|
||||
if (!currEditor)
|
||||
return;
|
||||
const QString fileName = currEditor->file()->fileName();
|
||||
if (fileName.isEmpty())
|
||||
return;
|
||||
if (currEditor->file()->isModified()) {
|
||||
QMessageBox msgBox(QMessageBox::Question, tr("Revert to Saved"),
|
||||
tr("You will lose your current changes if you proceed reverting %1.").arg(QDir::toNativeSeparators(fileName)),
|
||||
QMessageBox::Yes|QMessageBox::No, m_d->m_core->mainWindow());
|
||||
msgBox.button(QMessageBox::Yes)->setText(tr("Proceed"));
|
||||
msgBox.button(QMessageBox::No)->setText(tr("Cancel"));
|
||||
msgBox.setDefaultButton(QMessageBox::No);
|
||||
msgBox.setEscapeButton(QMessageBox::No);
|
||||
if (msgBox.exec() == QMessageBox::No)
|
||||
return;
|
||||
|
||||
}
|
||||
IFile::ReloadBehavior temp = IFile::ReloadAll;
|
||||
currEditor->file()->modified(&temp);
|
||||
}
|
||||
|
||||
void EditorManager::showEditorInfoBar(const QString &kind,
|
||||
const QString &infoText,
|
||||
const QString &buttonText,
|
||||
QObject *object, const char *member)
|
||||
{
|
||||
|
||||
currentEditorView()->showEditorInfoBar(kind, infoText, buttonText, object, member);
|
||||
}
|
||||
|
||||
|
||||
void EditorManager::hideEditorInfoBar(const QString &kind)
|
||||
{
|
||||
Core::Internal::EditorView *cev = currentEditorView();
|
||||
if (cev)
|
||||
cev->hideEditorInfoBar(kind);
|
||||
}
|
||||
|
||||
void EditorManager::showEditorStatusBar(const QString &kind,
|
||||
const QString &infoText,
|
||||
const QString &buttonText,
|
||||
QObject *object, const char *member)
|
||||
{
|
||||
|
||||
currentEditorView()->showEditorStatusBar(kind, infoText, buttonText, object, member);
|
||||
}
|
||||
|
||||
void EditorManager::hideEditorStatusBar(const QString &kind)
|
||||
{
|
||||
currentEditorView()->hideEditorStatusBar(kind);
|
||||
}
|
||||
|
||||
QString EditorManager::externalEditorHelpText() const
|
||||
{
|
||||
QString help = tr(
|
||||
"<table border=1 cellspacing=0 cellpadding=3>"
|
||||
"<tr><th>Variable</th><th>Expands to</th></tr>"
|
||||
"<tr><td>%f</td><td>file name</td></tr>"
|
||||
"<tr><td>%l</td><td>current line number</td></tr>"
|
||||
"<tr><td>%c</td><td>current column number</td></tr>"
|
||||
"<tr><td>%x</td><td>editor's x position on screen</td></tr>"
|
||||
"<tr><td>%y</td><td>editor's y position on screen</td></tr>"
|
||||
"<tr><td>%w</td><td>editor's width in pixels</td></tr>"
|
||||
"<tr><td>%h</td><td>editor's height in pixels</td></tr>"
|
||||
"<tr><td>%W</td><td>editor's width in characters</td></tr>"
|
||||
"<tr><td>%H</td><td>editor's height in characters</td></tr>"
|
||||
"<tr><td>%%</td><td>%</td></tr>"
|
||||
"</table>");
|
||||
return help;
|
||||
}
|
||||
|
||||
void EditorManager::openInExternalEditor()
|
||||
{
|
||||
QString command = m_d->m_externalEditor;
|
||||
if (command.isEmpty())
|
||||
command = defaultExternalEditor();
|
||||
|
||||
if (command.isEmpty())
|
||||
return;
|
||||
|
||||
IEditor *editor = currentEditor();
|
||||
if (!editor)
|
||||
return;
|
||||
if (editor->file()->isModified()) {
|
||||
bool cancelled = false;
|
||||
QList<IFile*> list = m_d->m_core->fileManager()->
|
||||
saveModifiedFiles(QList<IFile*>() << editor->file(), &cancelled);
|
||||
if (cancelled)
|
||||
return;
|
||||
}
|
||||
|
||||
QRect rect = editor->widget()->rect();
|
||||
QFont font = editor->widget()->font();
|
||||
QFontMetrics fm(font);
|
||||
rect.moveTo(editor->widget()->mapToGlobal(QPoint(0,0)));
|
||||
|
||||
QString pre = command;
|
||||
QString cmd;
|
||||
for (int i = 0; i < pre.size(); ++i) {
|
||||
QChar c = pre.at(i);
|
||||
if (c == QLatin1Char('%') && i < pre.size()-1) {
|
||||
c = pre.at(++i);
|
||||
QString s;
|
||||
if (c == QLatin1Char('f'))
|
||||
s = editor->file()->fileName();
|
||||
else if (c == QLatin1Char('l'))
|
||||
s = QString::number(editor->currentLine());
|
||||
else if (c == QLatin1Char('c'))
|
||||
s = QString::number(editor->currentColumn());
|
||||
else if (c == QLatin1Char('x'))
|
||||
s = QString::number(rect.x());
|
||||
else if (c == QLatin1Char('y'))
|
||||
s = QString::number(rect.y());
|
||||
else if (c == QLatin1Char('w'))
|
||||
s = QString::number(rect.width());
|
||||
else if (c == QLatin1Char('h'))
|
||||
s = QString::number(rect.height());
|
||||
else if (c == QLatin1Char('W'))
|
||||
s = QString::number(rect.width() / fm.width(QLatin1Char('x')));
|
||||
else if (c == QLatin1Char('H'))
|
||||
s = QString::number(rect.height() / fm.lineSpacing());
|
||||
else if (c == QLatin1Char('%'))
|
||||
s = c;
|
||||
else {
|
||||
s = QLatin1Char('%');
|
||||
cmd += c;
|
||||
}
|
||||
cmd += s;
|
||||
continue;
|
||||
|
||||
}
|
||||
cmd += c;
|
||||
}
|
||||
|
||||
QProcess::startDetached(cmd);
|
||||
}
|
||||
|
||||
void EditorManager::setExternalEditor(const QString &editor)
|
||||
{
|
||||
if (editor.isEmpty() || editor == defaultExternalEditor())
|
||||
m_d->m_externalEditor = defaultExternalEditor();
|
||||
else
|
||||
m_d->m_externalEditor = editor;
|
||||
}
|
||||
|
||||
QString EditorManager::externalEditor() const
|
||||
{
|
||||
if (m_d->m_externalEditor.isEmpty())
|
||||
return defaultExternalEditor();
|
||||
return m_d->m_externalEditor;
|
||||
}
|
||||
|
||||
void EditorManager::setReloadBehavior(IFile::ReloadBehavior behavior)
|
||||
{
|
||||
m_d->m_reloadBehavior = behavior;
|
||||
}
|
||||
|
||||
IFile::ReloadBehavior EditorManager::reloadBehavior() const
|
||||
{
|
||||
return m_d->m_reloadBehavior;
|
||||
}
|
||||
|
||||
Core::IEditor *EditorManager::duplicateEditor(Core::IEditor *editor)
|
||||
{
|
||||
if (!editor->duplicateSupported())
|
||||
return 0;
|
||||
|
||||
IEditor *duplicate = editor->duplicate(0);
|
||||
duplicate->restoreState(editor->saveState());
|
||||
emit editorCreated(duplicate, duplicate->file()->fileName());
|
||||
addEditor(duplicate, true);
|
||||
return duplicate;
|
||||
}
|
||||
|
||||
void EditorManager::split(Qt::Orientation orientation)
|
||||
{
|
||||
SplitterOrView *view = m_d->m_currentView;
|
||||
if (!view)
|
||||
view = m_d->m_currentEditor ? m_d->m_splitter->findView(m_d->m_currentEditor)
|
||||
: m_d->m_splitter->findFirstView();
|
||||
if (view && !view->splitter()) {
|
||||
view->split(orientation);
|
||||
}
|
||||
updateActions();
|
||||
}
|
||||
|
||||
void EditorManager::split()
|
||||
{
|
||||
split(Qt::Vertical);
|
||||
}
|
||||
|
||||
void EditorManager::splitSideBySide()
|
||||
{
|
||||
split(Qt::Horizontal);
|
||||
}
|
||||
|
||||
void EditorManager::removeCurrentSplit()
|
||||
{
|
||||
SplitterOrView *viewToClose = m_d->m_currentView;
|
||||
if (!viewToClose && m_d->m_currentEditor)
|
||||
viewToClose = m_d->m_splitter->findView(m_d->m_currentEditor);
|
||||
|
||||
if (!viewToClose || viewToClose->isSplitter() || viewToClose == m_d->m_splitter)
|
||||
return;
|
||||
|
||||
closeView(viewToClose->view());
|
||||
updateActions();
|
||||
}
|
||||
|
||||
void EditorManager::removeAllSplits()
|
||||
{
|
||||
if (!m_d->m_splitter->isSplitter())
|
||||
return;
|
||||
IEditor *editor = m_d->m_currentEditor;
|
||||
m_d->m_currentEditor = 0; // trigger update below
|
||||
if (editor && m_d->m_editorModel->isDuplicate(editor))
|
||||
editor = m_d->m_editorModel->originalForDuplicate(editor);
|
||||
m_d->m_splitter->unsplitAll();
|
||||
if (!editor)
|
||||
editor = pickUnusedEditor();
|
||||
activateEditor(editor);
|
||||
}
|
||||
|
||||
void EditorManager::gotoOtherSplit()
|
||||
{
|
||||
if (m_d->m_splitter->isSplitter()) {
|
||||
SplitterOrView *currentView = m_d->m_currentView;
|
||||
if (!currentView && m_d->m_currentEditor)
|
||||
currentView = m_d->m_splitter->findView(m_d->m_currentEditor);
|
||||
if (!currentView)
|
||||
currentView = m_d->m_splitter->findFirstView();
|
||||
SplitterOrView *view = m_d->m_splitter->findNextView(currentView);
|
||||
if (!view)
|
||||
view = m_d->m_splitter->findFirstView();
|
||||
if (view) {
|
||||
if (IEditor *editor = view->editor()) {
|
||||
setCurrentEditor(editor, true);
|
||||
editor->widget()->setFocus();
|
||||
} else {
|
||||
setCurrentView(view);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//===================EditorClosingCoreListener======================
|
||||
|
||||
EditorClosingCoreListener::EditorClosingCoreListener(EditorManager *em)
|
||||
: m_em(em)
|
||||
{
|
||||
}
|
||||
|
||||
bool EditorClosingCoreListener::editorAboutToClose(IEditor *)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EditorClosingCoreListener::coreAboutToClose()
|
||||
{
|
||||
// Do not ask for files to save.
|
||||
// MainWindow::closeEvent has already done that.
|
||||
return m_em->closeAllEditors(false);
|
||||
}
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** Commercial Usage
|
||||
**
|
||||
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||
** accordance with the Qt Commercial License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Nokia.
|
||||
**
|
||||
** 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 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** If you are unsure which license is appropriate for your use, please
|
||||
** contact the sales department at http://qt.nokia.com/contact.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "editormanager.h"
|
||||
#include "editorview.h"
|
||||
#include "openeditorswindow.h"
|
||||
#include "openeditorsview.h"
|
||||
#include "openeditorsmodel.h"
|
||||
#include "openwithdialog.h"
|
||||
#include "filemanager.h"
|
||||
#include "icore.h"
|
||||
#include "iversioncontrol.h"
|
||||
#include "mimedatabase.h"
|
||||
#include "tabpositionindicator.h"
|
||||
#include "vcsmanager.h"
|
||||
|
||||
#include <coreplugin/coreconstants.h>
|
||||
#include <coreplugin/modemanager.h>
|
||||
#include <coreplugin/uniqueidmanager.h>
|
||||
#include <coreplugin/actionmanager/actionmanager.h>
|
||||
#include <coreplugin/editormanager/ieditorfactory.h>
|
||||
#include <coreplugin/editormanager/iexternaleditor.h>
|
||||
#include <coreplugin/baseview.h>
|
||||
#include <coreplugin/imode.h>
|
||||
#include <coreplugin/settingsdatabase.h>
|
||||
#include <coreplugin/variablemanager.h>
|
||||
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
|
||||
#include <utils/consoleprocess.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QProcess>
|
||||
#include <QtCore/QSet>
|
||||
#include <QtCore/QSettings>
|
||||
|
||||
#include <QtGui/QAction>
|
||||
#include <QtGui/QApplication>
|
||||
#include <QtGui/QFileDialog>
|
||||
#include <QtGui/QLayout>
|
||||
#include <QtGui/QMainWindow>
|
||||
#include <QtGui/QMenu>
|
||||
#include <QtGui/QMessageBox>
|
||||
#include <QtGui/QPushButton>
|
||||
#include <QtGui/QSplitter>
|
||||
#include <QtGui/QStackedLayout>
|
||||
|
||||
Q_DECLARE_METATYPE(Core::IEditor*)
|
||||
|
||||
using namespace Core;
|
||||
using namespace Core::Internal;
|
||||
using namespace Utils;
|
||||
|
||||
enum { debugEditorManager=0 };
|
||||
|
||||
static inline ExtensionSystem::PluginManager *pluginManager()
|
||||
{
|
||||
return ExtensionSystem::PluginManager::instance();
|
||||
}
|
||||
|
||||
//===================EditorManager=====================
|
||||
|
||||
EditorManagerPlaceHolder *EditorManagerPlaceHolder::m_current = 0;
|
||||
|
||||
EditorManagerPlaceHolder::EditorManagerPlaceHolder(Core::IMode *mode, QWidget *parent)
|
||||
: QWidget(parent), m_mode(mode)
|
||||
{
|
||||
setLayout(new QVBoxLayout);
|
||||
layout()->setMargin(0);
|
||||
connect(Core::ModeManager::instance(), SIGNAL(currentModeChanged(Core::IMode *)),
|
||||
this, SLOT(currentModeChanged(Core::IMode *)));
|
||||
|
||||
currentModeChanged(Core::ModeManager::instance()->currentMode());
|
||||
}
|
||||
|
||||
EditorManagerPlaceHolder::~EditorManagerPlaceHolder()
|
||||
{
|
||||
if (m_current == this) {
|
||||
EditorManager::instance()->setParent(0);
|
||||
EditorManager::instance()->hide();
|
||||
}
|
||||
}
|
||||
|
||||
void EditorManagerPlaceHolder::currentModeChanged(Core::IMode *mode)
|
||||
{
|
||||
if (m_current == this) {
|
||||
m_current = 0;
|
||||
EditorManager::instance()->setParent(0);
|
||||
EditorManager::instance()->hide();
|
||||
}
|
||||
if (m_mode == mode) {
|
||||
m_current = this;
|
||||
layout()->addWidget(EditorManager::instance());
|
||||
EditorManager::instance()->show();
|
||||
}
|
||||
}
|
||||
|
||||
EditorManagerPlaceHolder* EditorManagerPlaceHolder::current()
|
||||
{
|
||||
return m_current;
|
||||
}
|
||||
|
||||
// ---------------- EditorManager
|
||||
|
||||
namespace Core {
|
||||
|
||||
|
||||
struct EditorManagerPrivate {
|
||||
explicit EditorManagerPrivate(ICore *core, QWidget *parent);
|
||||
~EditorManagerPrivate();
|
||||
Internal::EditorView *m_view;
|
||||
Internal::SplitterOrView *m_splitter;
|
||||
QPointer<IEditor> m_currentEditor;
|
||||
QPointer<SplitterOrView> m_currentView;
|
||||
|
||||
ICore *m_core;
|
||||
|
||||
|
||||
// actions
|
||||
QAction *m_revertToSavedAction;
|
||||
QAction *m_saveAction;
|
||||
QAction *m_saveAsAction;
|
||||
QAction *m_closeCurrentEditorAction;
|
||||
QAction *m_closeAllEditorsAction;
|
||||
QAction *m_closeOtherEditorsAction;
|
||||
QAction *m_gotoNextDocHistoryAction;
|
||||
QAction *m_gotoPreviousDocHistoryAction;
|
||||
QAction *m_goBackAction;
|
||||
QAction *m_goForwardAction;
|
||||
QAction *m_openInExternalEditorAction;
|
||||
QAction *m_splitAction;
|
||||
QAction *m_splitSideBySideAction;
|
||||
QAction *m_removeCurrentSplitAction;
|
||||
QAction *m_removeAllSplitsAction;
|
||||
QAction *m_gotoOtherSplitAction;
|
||||
|
||||
Internal::OpenEditorsWindow *m_windowPopup;
|
||||
Core::BaseView *m_openEditorsView;
|
||||
Internal::EditorClosingCoreListener *m_coreListener;
|
||||
|
||||
QMap<QString, QVariant> m_editorStates;
|
||||
Internal::OpenEditorsViewFactory *m_openEditorsFactory;
|
||||
|
||||
QString fileFilters;
|
||||
QString selectedFilter;
|
||||
|
||||
OpenEditorsModel *m_editorModel;
|
||||
QString m_externalEditor;
|
||||
|
||||
IFile::ReloadBehavior m_reloadBehavior;
|
||||
};
|
||||
}
|
||||
|
||||
EditorManagerPrivate::EditorManagerPrivate(ICore *core, QWidget *parent) :
|
||||
m_view(0),
|
||||
m_splitter(0),
|
||||
m_core(core),
|
||||
m_revertToSavedAction(new QAction(EditorManager::tr("Revert to Saved"), parent)),
|
||||
m_saveAction(new QAction(parent)),
|
||||
m_saveAsAction(new QAction(parent)),
|
||||
m_closeCurrentEditorAction(new QAction(EditorManager::tr("Close"), parent)),
|
||||
m_closeAllEditorsAction(new QAction(EditorManager::tr("Close All"), parent)),
|
||||
m_closeOtherEditorsAction(new QAction(EditorManager::tr("Close Others"), parent)),
|
||||
m_gotoNextDocHistoryAction(new QAction(EditorManager::tr("Next Open Document in History"), parent)),
|
||||
m_gotoPreviousDocHistoryAction(new QAction(EditorManager::tr("Previous Open Document in History"), parent)),
|
||||
m_goBackAction(new QAction(QIcon(QLatin1String(":/help/images/previous.png")), EditorManager::tr("Go Back"), parent)),
|
||||
m_goForwardAction(new QAction(QIcon(QLatin1String(":/help/images/next.png")), EditorManager::tr("Go Forward"), parent)),
|
||||
m_openInExternalEditorAction(new QAction(EditorManager::tr("Open in External Editor"), parent)),
|
||||
m_windowPopup(0),
|
||||
m_coreListener(0),
|
||||
m_reloadBehavior(IFile::AskForReload)
|
||||
{
|
||||
m_editorModel = new OpenEditorsModel(parent);
|
||||
}
|
||||
|
||||
EditorManagerPrivate::~EditorManagerPrivate()
|
||||
{
|
||||
// clearNavigationHistory();
|
||||
}
|
||||
|
||||
EditorManager *EditorManager::m_instance = 0;
|
||||
|
||||
static Command *createSeparator(ActionManager *am, QObject *parent,
|
||||
const QString &name,
|
||||
const QList<int> &context)
|
||||
{
|
||||
QAction *tmpaction = new QAction(parent);
|
||||
tmpaction->setSeparator(true);
|
||||
Command *cmd = am->registerAction(tmpaction, name, context);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
EditorManager::EditorManager(ICore *core, QWidget *parent) :
|
||||
QWidget(parent),
|
||||
m_d(new EditorManagerPrivate(core, parent))
|
||||
{
|
||||
m_instance = this;
|
||||
|
||||
connect(m_d->m_core, SIGNAL(contextAboutToChange(Core::IContext *)),
|
||||
this, SLOT(handleContextChange(Core::IContext *)));
|
||||
|
||||
const QList<int> gc = QList<int>() << Constants::C_GLOBAL_ID;
|
||||
const QList<int> editManagerContext =
|
||||
QList<int>() << m_d->m_core->uniqueIDManager()->uniqueIdentifier(Constants::C_EDITORMANAGER);
|
||||
|
||||
ActionManager *am = m_d->m_core->actionManager();
|
||||
ActionContainer *mfile = am->actionContainer(Constants::M_FILE);
|
||||
|
||||
//Revert to saved
|
||||
Command *cmd = am->registerAction(m_d->m_revertToSavedAction,
|
||||
Constants::REVERTTOSAVED, editManagerContext);
|
||||
cmd->setAttribute(Command::CA_UpdateText);
|
||||
cmd->setDefaultText(tr("Revert File to Saved"));
|
||||
mfile->addAction(cmd, Constants::G_FILE_SAVE);
|
||||
connect(m_d->m_revertToSavedAction, SIGNAL(triggered()), this, SLOT(revertToSaved()));
|
||||
|
||||
//Save Action
|
||||
am->registerAction(m_d->m_saveAction, Constants::SAVE, editManagerContext);
|
||||
connect(m_d->m_saveAction, SIGNAL(triggered()), this, SLOT(saveFile()));
|
||||
|
||||
//Save As Action
|
||||
am->registerAction(m_d->m_saveAsAction, Constants::SAVEAS, editManagerContext);
|
||||
connect(m_d->m_saveAsAction, SIGNAL(triggered()), this, SLOT(saveFileAs()));
|
||||
|
||||
//Window Menu
|
||||
ActionContainer *mwindow = am->actionContainer(Constants::M_WINDOW);
|
||||
|
||||
//Window menu separators
|
||||
QAction *tmpaction = new QAction(this);
|
||||
tmpaction->setSeparator(true);
|
||||
cmd = am->registerAction(tmpaction, QLatin1String("QtCreator.Window.Sep.Split"), editManagerContext);
|
||||
mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT);
|
||||
|
||||
tmpaction = new QAction(this);
|
||||
tmpaction->setSeparator(true);
|
||||
cmd = am->registerAction(tmpaction, QLatin1String("QtCreator.Window.Sep.Navigate"), editManagerContext);
|
||||
mwindow->addAction(cmd, Constants::G_WINDOW_NAVIGATE);
|
||||
|
||||
//Close Action
|
||||
cmd = am->registerAction(m_d->m_closeCurrentEditorAction, Constants::CLOSE, editManagerContext);
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+W")));
|
||||
cmd->setAttribute(Core::Command::CA_UpdateText);
|
||||
cmd->setDefaultText(m_d->m_closeCurrentEditorAction->text());
|
||||
mfile->addAction(cmd, Constants::G_FILE_CLOSE);
|
||||
connect(m_d->m_closeCurrentEditorAction, SIGNAL(triggered()), this, SLOT(closeEditor()));
|
||||
|
||||
//Close All Action
|
||||
cmd = am->registerAction(m_d->m_closeAllEditorsAction, Constants::CLOSEALL, editManagerContext);
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+W")));
|
||||
mfile->addAction(cmd, Constants::G_FILE_CLOSE);
|
||||
connect(m_d->m_closeAllEditorsAction, SIGNAL(triggered()), this, SLOT(closeAllEditors()));
|
||||
|
||||
//Close All Others Action
|
||||
cmd = am->registerAction(m_d->m_closeOtherEditorsAction, Constants::CLOSEOTHERS, editManagerContext);
|
||||
mfile->addAction(cmd, Constants::G_FILE_CLOSE);
|
||||
cmd->setAttribute(Core::Command::CA_UpdateText);
|
||||
connect(m_d->m_closeOtherEditorsAction, SIGNAL(triggered()), this, SLOT(closeOtherEditors()));
|
||||
|
||||
// Goto Previous In History Action
|
||||
cmd = am->registerAction(m_d->m_gotoPreviousDocHistoryAction, Constants::GOTOPREVINHISTORY, editManagerContext);
|
||||
#ifdef Q_WS_MAC
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("Alt+Tab")));
|
||||
#else
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Tab")));
|
||||
#endif
|
||||
mwindow->addAction(cmd, Constants::G_WINDOW_NAVIGATE);
|
||||
connect(m_d->m_gotoPreviousDocHistoryAction, SIGNAL(triggered()), this, SLOT(gotoPreviousDocHistory()));
|
||||
|
||||
// Goto Next In History Action
|
||||
cmd = am->registerAction(m_d->m_gotoNextDocHistoryAction, Constants::GOTONEXTINHISTORY, editManagerContext);
|
||||
#ifdef Q_WS_MAC
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("Alt+Shift+Tab")));
|
||||
#else
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+Tab")));
|
||||
#endif
|
||||
mwindow->addAction(cmd, Constants::G_WINDOW_NAVIGATE);
|
||||
connect(m_d->m_gotoNextDocHistoryAction, SIGNAL(triggered()), this, SLOT(gotoNextDocHistory()));
|
||||
|
||||
// Go back in navigation history
|
||||
cmd = am->registerAction(m_d->m_goBackAction, Constants::GO_BACK, editManagerContext);
|
||||
#ifdef Q_WS_MAC
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+Left")));
|
||||
#else
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("Alt+Left")));
|
||||
#endif
|
||||
mwindow->addAction(cmd, Constants::G_WINDOW_NAVIGATE);
|
||||
connect(m_d->m_goBackAction, SIGNAL(triggered()), this, SLOT(goBackInNavigationHistory()));
|
||||
|
||||
// Go forward in navigation history
|
||||
cmd = am->registerAction(m_d->m_goForwardAction, Constants::GO_FORWARD, editManagerContext);
|
||||
#ifdef Q_WS_MAC
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+Right")));
|
||||
#else
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("Alt+Right")));
|
||||
#endif
|
||||
mwindow->addAction(cmd, Constants::G_WINDOW_NAVIGATE);
|
||||
connect(m_d->m_goForwardAction, SIGNAL(triggered()), this, SLOT(goForwardInNavigationHistory()));
|
||||
|
||||
#ifdef Q_WS_MAC
|
||||
QString prefix = tr("Meta+E");
|
||||
#else
|
||||
QString prefix = tr("Ctrl+E");
|
||||
#endif
|
||||
|
||||
m_d->m_splitAction = new QAction(tr("Split"), this);
|
||||
cmd = am->registerAction(m_d->m_splitAction, Constants::SPLIT, editManagerContext);
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("%1,2").arg(prefix)));
|
||||
mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT);
|
||||
connect(m_d->m_splitAction, SIGNAL(triggered()), this, SLOT(split()));
|
||||
|
||||
m_d->m_splitSideBySideAction = new QAction(tr("Split Side by Side"), this);
|
||||
cmd = am->registerAction(m_d->m_splitSideBySideAction, Constants::SPLIT_SIDE_BY_SIDE, editManagerContext);
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("%1,3").arg(prefix)));
|
||||
mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT);
|
||||
connect(m_d->m_splitSideBySideAction, SIGNAL(triggered()), this, SLOT(splitSideBySide()));
|
||||
|
||||
m_d->m_removeCurrentSplitAction = new QAction(tr("Remove Current Split"), this);
|
||||
cmd = am->registerAction(m_d->m_removeCurrentSplitAction, Constants::REMOVE_CURRENT_SPLIT, editManagerContext);
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("%1,0").arg(prefix)));
|
||||
mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT);
|
||||
connect(m_d->m_removeCurrentSplitAction, SIGNAL(triggered()), this, SLOT(removeCurrentSplit()));
|
||||
|
||||
m_d->m_removeAllSplitsAction = new QAction(tr("Remove All Splits"), this);
|
||||
cmd = am->registerAction(m_d->m_removeAllSplitsAction, Constants::REMOVE_ALL_SPLITS, editManagerContext);
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("%1,1").arg(prefix)));
|
||||
mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT);
|
||||
connect(m_d->m_removeAllSplitsAction, SIGNAL(triggered()), this, SLOT(removeAllSplits()));
|
||||
|
||||
m_d->m_gotoOtherSplitAction = new QAction(tr("Goto Other Split"), this);
|
||||
cmd = am->registerAction(m_d->m_gotoOtherSplitAction, Constants::GOTO_OTHER_SPLIT, editManagerContext);
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("%1,o").arg(prefix)));
|
||||
mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT);
|
||||
connect(m_d->m_gotoOtherSplitAction, SIGNAL(triggered()), this, SLOT(gotoOtherSplit()));
|
||||
|
||||
ActionContainer *medit = am->actionContainer(Constants::M_EDIT);
|
||||
ActionContainer *advancedMenu = am->createMenu(Constants::M_EDIT_ADVANCED);
|
||||
medit->addMenu(advancedMenu, Constants::G_EDIT_ADVANCED);
|
||||
advancedMenu->menu()->setTitle(tr("&Advanced"));
|
||||
advancedMenu->appendGroup(Constants::G_EDIT_FORMAT);
|
||||
advancedMenu->appendGroup(Constants::G_EDIT_COLLAPSING);
|
||||
advancedMenu->appendGroup(Constants::G_EDIT_BLOCKS);
|
||||
advancedMenu->appendGroup(Constants::G_EDIT_FONT);
|
||||
advancedMenu->appendGroup(Constants::G_EDIT_EDITOR);
|
||||
|
||||
// Advanced menu separators
|
||||
cmd = createSeparator(am, this, QLatin1String("QtCreator.Edit.Sep.Collapsing"), editManagerContext);
|
||||
advancedMenu->addAction(cmd, Constants::G_EDIT_COLLAPSING);
|
||||
cmd = createSeparator(am, this, QLatin1String("QtCreator.Edit.Sep.Blocks"), editManagerContext);
|
||||
advancedMenu->addAction(cmd, Constants::G_EDIT_BLOCKS);
|
||||
cmd = createSeparator(am, this, QLatin1String("QtCreator.Edit.Sep.Font"), editManagerContext);
|
||||
advancedMenu->addAction(cmd, Constants::G_EDIT_FONT);
|
||||
cmd = createSeparator(am, this, QLatin1String("QtCreator.Edit.Sep.Editor"), editManagerContext);
|
||||
advancedMenu->addAction(cmd, Constants::G_EDIT_EDITOR);
|
||||
|
||||
cmd = am->registerAction(m_d->m_openInExternalEditorAction, Constants::OPEN_IN_EXTERNAL_EDITOR, editManagerContext);
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("Alt+V,Alt+I")));
|
||||
advancedMenu->addAction(cmd, Constants::G_EDIT_EDITOR);
|
||||
connect(m_d->m_openInExternalEditorAction, SIGNAL(triggered()), this, SLOT(openInExternalEditor()));
|
||||
|
||||
// Connect to VariableManager for CURRENT_DOCUMENT variable setting
|
||||
VariableManager *vm = VariableManager::instance();
|
||||
connect(this, SIGNAL(currentEditorChanged(Core::IEditor *)),
|
||||
vm, SLOT(updateCurrentDocument(Core::IEditor *)));
|
||||
|
||||
|
||||
// other setup
|
||||
m_d->m_splitter = new SplitterOrView(m_d->m_editorModel);
|
||||
m_d->m_view = m_d->m_splitter->view();
|
||||
|
||||
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
layout->setMargin(0);
|
||||
layout->setSpacing(0);
|
||||
layout->addWidget(m_d->m_splitter);
|
||||
|
||||
updateActions();
|
||||
|
||||
m_d->m_windowPopup = new OpenEditorsWindow(this);
|
||||
}
|
||||
|
||||
EditorManager::~EditorManager()
|
||||
{
|
||||
if (m_d->m_core) {
|
||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||
if (m_d->m_coreListener) {
|
||||
pm->removeObject(m_d->m_coreListener);
|
||||
delete m_d->m_coreListener;
|
||||
}
|
||||
pm->removeObject(m_d->m_openEditorsFactory);
|
||||
delete m_d->m_openEditorsFactory;
|
||||
}
|
||||
delete m_d;
|
||||
}
|
||||
|
||||
void EditorManager::init()
|
||||
{
|
||||
QList<int> context;
|
||||
context << m_d->m_core->uniqueIDManager()->uniqueIdentifier("QtCreator.OpenDocumentsView");
|
||||
|
||||
m_d->m_coreListener = new EditorClosingCoreListener(this);
|
||||
|
||||
pluginManager()->addObject(m_d->m_coreListener);
|
||||
|
||||
m_d->m_openEditorsFactory = new OpenEditorsViewFactory();
|
||||
pluginManager()->addObject(m_d->m_openEditorsFactory);
|
||||
}
|
||||
|
||||
QString EditorManager::defaultExternalEditor() const
|
||||
{
|
||||
#ifdef Q_OS_UNIX
|
||||
return ConsoleProcess::defaultTerminalEmulator() + QLatin1String(
|
||||
# ifdef Q_OS_MAC
|
||||
" -async"
|
||||
# endif
|
||||
" -geom %Wx%H+%x+%y -e vi %f +%l +\"normal %c|\"");
|
||||
#else
|
||||
return QLatin1String("notepad %f");
|
||||
#endif
|
||||
}
|
||||
|
||||
void EditorManager::removeEditor(IEditor *editor)
|
||||
{
|
||||
bool isDuplicate = m_d->m_editorModel->isDuplicate(editor);
|
||||
m_d->m_editorModel->removeEditor(editor);
|
||||
if (!isDuplicate) {
|
||||
m_d->m_core->fileManager()->removeFile(editor->file());
|
||||
}
|
||||
m_d->m_core->removeContextObject(editor);
|
||||
}
|
||||
|
||||
void EditorManager::handleContextChange(Core::IContext *context)
|
||||
{
|
||||
if (debugEditorManager)
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
IEditor *editor = context ? qobject_cast<IEditor*>(context) : 0;
|
||||
if (editor) {
|
||||
setCurrentEditor(editor);
|
||||
} else {
|
||||
updateActions();
|
||||
}
|
||||
}
|
||||
|
||||
void EditorManager::setCurrentEditor(IEditor *editor, bool ignoreNavigationHistory)
|
||||
{
|
||||
if (editor)
|
||||
setCurrentView(0);
|
||||
|
||||
if (m_d->m_currentEditor == editor)
|
||||
return;
|
||||
if (m_d->m_currentEditor && !ignoreNavigationHistory)
|
||||
addCurrentPositionToNavigationHistory();
|
||||
|
||||
m_d->m_currentEditor = editor;
|
||||
if (editor) {
|
||||
if (SplitterOrView *splitterOrView = m_d->m_splitter->findView(editor))
|
||||
splitterOrView->view()->setCurrentEditor(editor);
|
||||
m_d->m_view->updateEditorHistory(editor); // the global view should have a complete history
|
||||
}
|
||||
updateActions();
|
||||
emit currentEditorChanged(editor);
|
||||
}
|
||||
|
||||
|
||||
void EditorManager::setCurrentView(Core::Internal::SplitterOrView *view)
|
||||
{
|
||||
if (view == m_d->m_currentView)
|
||||
return;
|
||||
|
||||
SplitterOrView *old = m_d->m_currentView;
|
||||
m_d->m_currentView = view;
|
||||
|
||||
if (old)
|
||||
old->update();
|
||||
if (view)
|
||||
view->update();
|
||||
|
||||
if (view && !view->editor())
|
||||
view->setFocus();
|
||||
}
|
||||
|
||||
Core::Internal::SplitterOrView *EditorManager::currentSplitterOrView() const
|
||||
{
|
||||
SplitterOrView *view = m_d->m_currentView;
|
||||
if (!view)
|
||||
view = m_d->m_currentEditor?
|
||||
m_d->m_splitter->findView(m_d->m_currentEditor):
|
||||
m_d->m_splitter->findFirstView();
|
||||
if (!view)
|
||||
return m_d->m_splitter;
|
||||
return view;
|
||||
}
|
||||
|
||||
Core::Internal::EditorView *EditorManager::currentEditorView() const
|
||||
{
|
||||
return currentSplitterOrView()->view();
|
||||
}
|
||||
|
||||
|
||||
|
||||
QList<IEditor *> EditorManager::editorsForFileName(const QString &filename) const
|
||||
{
|
||||
QList<IEditor *> found;
|
||||
QString fixedname = FileManager::fixFileName(filename);
|
||||
foreach (IEditor *editor, openedEditors()) {
|
||||
if (fixedname == FileManager::fixFileName(editor->file()->fileName()))
|
||||
found << editor;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
QList<IEditor *> EditorManager::editorsForFile(IFile *file) const
|
||||
{
|
||||
QList<IEditor *> found;
|
||||
foreach (IEditor *editor, openedEditors()) {
|
||||
if (editor->file() == file)
|
||||
found << editor;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
IEditor *EditorManager::currentEditor() const
|
||||
{
|
||||
return m_d->m_currentEditor;
|
||||
}
|
||||
|
||||
void EditorManager::emptyView(Core::Internal::EditorView *view)
|
||||
{
|
||||
if (!view)
|
||||
return;
|
||||
|
||||
QList<IEditor *> editors = view->editors();
|
||||
foreach (IEditor *editor, editors) {
|
||||
if (!m_d->m_editorModel->isDuplicate(editor)) {
|
||||
editors.removeAll(editor);
|
||||
view->removeEditor(editor);
|
||||
continue;
|
||||
}
|
||||
emit editorAboutToClose(editor);
|
||||
removeEditor(editor);
|
||||
view->removeEditor(editor);
|
||||
}
|
||||
emit editorsClosed(editors);
|
||||
foreach (IEditor *editor, editors) {
|
||||
delete editor;
|
||||
}
|
||||
}
|
||||
|
||||
void EditorManager::closeView(Core::Internal::EditorView *view)
|
||||
{
|
||||
if (!view)
|
||||
return;
|
||||
|
||||
if (view == m_d->m_view) {
|
||||
if (IEditor *e = view->currentEditor())
|
||||
closeEditors(QList<IEditor *>() << e);
|
||||
return;
|
||||
}
|
||||
|
||||
emptyView(view);
|
||||
|
||||
SplitterOrView *splitterOrView = m_d->m_splitter->findView(view);
|
||||
Q_ASSERT(splitterOrView);
|
||||
Q_ASSERT(splitterOrView->view() == view);
|
||||
SplitterOrView *splitter = m_d->m_splitter->findSplitter(splitterOrView);
|
||||
Q_ASSERT(splitterOrView->hasEditors() == false);
|
||||
splitterOrView->hide();
|
||||
delete splitterOrView;
|
||||
|
||||
splitter->unsplit();
|
||||
|
||||
SplitterOrView *newCurrent = splitter->findFirstView();
|
||||
if (newCurrent) {
|
||||
if (newCurrent->editor())
|
||||
activateEditor(newCurrent->view(), newCurrent->editor());
|
||||
else
|
||||
setCurrentView(newCurrent);
|
||||
}
|
||||
}
|
||||
|
||||
QList<IEditor*>
|
||||
EditorManager::editorsForFiles(QList<IFile*> files) const
|
||||
{
|
||||
const QList<IEditor *> editors = openedEditors();
|
||||
QSet<IEditor *> found;
|
||||
foreach (IFile *file, files) {
|
||||
foreach (IEditor *editor, editors) {
|
||||
if (editor->file() == file && !found.contains(editor)) {
|
||||
found << editor;
|
||||
}
|
||||
}
|
||||
}
|
||||
return found.toList();
|
||||
}
|
||||
|
||||
QList<IFile *> EditorManager::filesForEditors(QList<IEditor *> editors) const
|
||||
{
|
||||
QSet<IEditor *> handledEditors;
|
||||
QList<IFile *> files;
|
||||
foreach (IEditor *editor, editors) {
|
||||
if (!handledEditors.contains(editor)) {
|
||||
files << editor->file();
|
||||
handledEditors.insert(editor);
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
bool EditorManager::closeAllEditors(bool askAboutModifiedEditors)
|
||||
{
|
||||
m_d->m_editorModel->removeAllRestoredEditors();
|
||||
if (closeEditors(openedEditors(), askAboutModifiedEditors)) {
|
||||
// m_d->clearNavigationHistory();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void EditorManager::closeOtherEditors(IEditor *editor)
|
||||
{
|
||||
m_d->m_editorModel->removeAllRestoredEditors();
|
||||
QList<IEditor*> editors = openedEditors();
|
||||
editors.removeAll(editor);
|
||||
closeEditors(editors, true);
|
||||
}
|
||||
|
||||
|
||||
void EditorManager::closeOtherEditors()
|
||||
{
|
||||
IEditor *current = currentEditor();
|
||||
QTC_ASSERT(current, return);
|
||||
closeOtherEditors(current);
|
||||
}
|
||||
|
||||
|
||||
// SLOT connected to action
|
||||
// since this is potentially called in the event handler of the editor
|
||||
// we simply postpone it with a single shot timer
|
||||
void EditorManager::closeEditor()
|
||||
{
|
||||
closeEditor(m_d->m_currentEditor);
|
||||
}
|
||||
|
||||
void EditorManager::closeEditor(Core::IEditor *editor)
|
||||
{
|
||||
if (!editor)
|
||||
return;
|
||||
closeEditors(QList<IEditor *>() << editor);
|
||||
}
|
||||
|
||||
void EditorManager::closeEditor(const QModelIndex &index)
|
||||
{
|
||||
IEditor *editor = index.data(Qt::UserRole).value<Core::IEditor*>();
|
||||
if (editor)
|
||||
closeEditor(editor);
|
||||
else
|
||||
m_d->m_editorModel->removeEditor(index);
|
||||
}
|
||||
|
||||
bool EditorManager::closeEditors(const QList<IEditor*> editorsToClose, bool askAboutModifiedEditors)
|
||||
{
|
||||
if (editorsToClose.isEmpty())
|
||||
return true;
|
||||
|
||||
SplitterOrView *currentSplitterOrView = this->currentSplitterOrView();
|
||||
|
||||
bool closingFailed = false;
|
||||
QList<IEditor*> acceptedEditors;
|
||||
//ask all core listeners to check whether the editor can be closed
|
||||
const QList<ICoreListener *> listeners =
|
||||
pluginManager()->getObjects<ICoreListener>();
|
||||
foreach (IEditor *editor, editorsToClose) {
|
||||
bool editorAccepted = true;
|
||||
if (m_d->m_editorModel->isDuplicate(editor))
|
||||
editor = m_d->m_editorModel->originalForDuplicate(editor);
|
||||
foreach (ICoreListener *listener, listeners) {
|
||||
if (!listener->editorAboutToClose(editor)) {
|
||||
editorAccepted = false;
|
||||
closingFailed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (editorAccepted)
|
||||
acceptedEditors.append(editor);
|
||||
}
|
||||
if (acceptedEditors.isEmpty())
|
||||
return false;
|
||||
//ask whether to save modified files
|
||||
if (askAboutModifiedEditors) {
|
||||
bool cancelled = false;
|
||||
QList<IFile*> list = m_d->m_core->fileManager()->
|
||||
saveModifiedFiles(filesForEditors(acceptedEditors), &cancelled);
|
||||
if (cancelled)
|
||||
return false;
|
||||
if (!list.isEmpty()) {
|
||||
closingFailed = true;
|
||||
QSet<IEditor*> skipSet = editorsForFiles(list).toSet();
|
||||
acceptedEditors = acceptedEditors.toSet().subtract(skipSet).toList();
|
||||
}
|
||||
}
|
||||
if (acceptedEditors.isEmpty())
|
||||
return false;
|
||||
|
||||
// add duplicates
|
||||
foreach(IEditor *editor, acceptedEditors)
|
||||
acceptedEditors += m_d->m_editorModel->duplicatesFor(editor);
|
||||
|
||||
QList<EditorView*> closedViews;
|
||||
|
||||
// remove the editors
|
||||
foreach (IEditor *editor, acceptedEditors) {
|
||||
emit editorAboutToClose(editor);
|
||||
if (!editor->file()->fileName().isEmpty()) {
|
||||
QByteArray state = editor->saveState();
|
||||
if (!state.isEmpty())
|
||||
m_d->m_editorStates.insert(editor->file()->fileName(), QVariant(state));
|
||||
}
|
||||
|
||||
removeEditor(editor);
|
||||
if (SplitterOrView *view = m_d->m_splitter->findView(editor)) {
|
||||
if (editor == view->view()->currentEditor())
|
||||
closedViews += view->view();
|
||||
view->view()->removeEditor(editor);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (EditorView *view, closedViews) {
|
||||
IEditor *newCurrent = view->currentEditor();
|
||||
if (!newCurrent)
|
||||
newCurrent = pickUnusedEditor();
|
||||
if (newCurrent) {
|
||||
activateEditor(view, newCurrent, NoActivate);
|
||||
} else {
|
||||
QModelIndex idx = m_d->m_editorModel->firstRestoredEditor();
|
||||
if (idx.isValid())
|
||||
activateEditor(idx, view, NoActivate);
|
||||
}
|
||||
}
|
||||
|
||||
emit editorsClosed(acceptedEditors);
|
||||
|
||||
foreach (IEditor *editor, acceptedEditors) {
|
||||
delete editor;
|
||||
}
|
||||
|
||||
if (currentSplitterOrView) {
|
||||
if (IEditor *editor = currentSplitterOrView->editor())
|
||||
activateEditor(currentSplitterOrView->view(), editor);
|
||||
}
|
||||
|
||||
if (!currentEditor())
|
||||
emit currentEditorChanged(0);
|
||||
|
||||
return !closingFailed;
|
||||
}
|
||||
|
||||
void EditorManager::closeDuplicate(Core::IEditor *editor)
|
||||
{
|
||||
|
||||
IEditor *original = editor;
|
||||
if (m_d->m_editorModel->isDuplicate(editor))
|
||||
original= m_d->m_editorModel->originalForDuplicate(editor);
|
||||
QList<IEditor *> duplicates = m_d->m_editorModel->duplicatesFor(original);
|
||||
|
||||
if (duplicates.isEmpty()) {
|
||||
closeEditor(editor);
|
||||
return;
|
||||
}
|
||||
|
||||
if (original== editor)
|
||||
m_d->m_editorModel->makeOriginal(duplicates.first());
|
||||
|
||||
SplitterOrView *currentSplitterOrView = this->currentSplitterOrView();
|
||||
|
||||
emit editorAboutToClose(editor);
|
||||
|
||||
EditorView *view = m_d->m_splitter->findView(editor)->view();
|
||||
removeEditor(editor);
|
||||
view->removeEditor(editor);
|
||||
|
||||
IEditor *newCurrent = view->currentEditor();
|
||||
if (!newCurrent)
|
||||
newCurrent = pickUnusedEditor();
|
||||
if (newCurrent) {
|
||||
activateEditor(view, newCurrent, NoActivate);
|
||||
} else {
|
||||
QModelIndex idx = m_d->m_editorModel->firstRestoredEditor();
|
||||
if (idx.isValid())
|
||||
activateEditor(idx, view, NoActivate);
|
||||
}
|
||||
|
||||
emit editorsClosed(QList<IEditor*>() << editor);
|
||||
delete editor;
|
||||
if (currentSplitterOrView) {
|
||||
if (IEditor *currentEditor = currentSplitterOrView->editor())
|
||||
activateEditor(currentSplitterOrView->view(), currentEditor);
|
||||
}
|
||||
}
|
||||
|
||||
Core::IEditor *EditorManager::pickUnusedEditor() const
|
||||
{
|
||||
foreach (IEditor *editor, openedEditors()) {
|
||||
SplitterOrView *view = m_d->m_splitter->findView(editor);
|
||||
if (!view || view->editor() != editor)
|
||||
return editor;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Core::IEditor *EditorManager::activateEditor(const QModelIndex &index, Internal::EditorView *view, OpenEditorFlags flags)
|
||||
{
|
||||
IEditor *editor = index.data(Qt::UserRole).value<IEditor*>();
|
||||
if (editor) {
|
||||
return activateEditor(view, editor, flags);
|
||||
}
|
||||
|
||||
QString fileName = index.data(Qt::UserRole + 1).toString();
|
||||
QByteArray kind = index.data(Qt::UserRole + 2).toByteArray();
|
||||
return openEditor(view, fileName, kind, flags);
|
||||
}
|
||||
|
||||
Core::IEditor *EditorManager::placeEditor(Core::Internal::EditorView *view, Core::IEditor *editor)
|
||||
{
|
||||
Q_ASSERT(view && editor);
|
||||
|
||||
if (view->currentEditor() && view->currentEditor()->file() == editor->file())
|
||||
editor = view->currentEditor();
|
||||
|
||||
if (!view->hasEditor(editor)) {
|
||||
bool duplicateSupported = editor->duplicateSupported();
|
||||
if (SplitterOrView *sourceView = m_d->m_splitter->findView(editor)) {
|
||||
if (editor != sourceView->editor() || !duplicateSupported) {
|
||||
sourceView->view()->removeEditor(editor);
|
||||
view->addEditor(editor);
|
||||
view->setCurrentEditor(editor);
|
||||
if (!sourceView->editor()) {
|
||||
if (IEditor *replacement = pickUnusedEditor()) {
|
||||
sourceView->view()->addEditor(replacement);
|
||||
}
|
||||
}
|
||||
return editor;
|
||||
} else if (duplicateSupported) {
|
||||
editor = duplicateEditor(editor);
|
||||
Q_ASSERT(editor);
|
||||
m_d->m_editorModel->makeOriginal(editor);
|
||||
}
|
||||
}
|
||||
view->addEditor(editor);
|
||||
}
|
||||
return editor;
|
||||
}
|
||||
|
||||
Core::IEditor *EditorManager::activateEditor(Core::IEditor *editor, OpenEditorFlags flags)
|
||||
{
|
||||
return activateEditor(0, editor, flags);
|
||||
}
|
||||
|
||||
Core::IEditor *EditorManager::activateEditor(Core::Internal::EditorView *view, Core::IEditor *editor, OpenEditorFlags flags)
|
||||
{
|
||||
if (!view)
|
||||
view = currentEditorView();
|
||||
|
||||
Q_ASSERT(view);
|
||||
|
||||
if (!editor) {
|
||||
if (!m_d->m_currentEditor)
|
||||
setCurrentEditor(0, (flags & IgnoreNavigationHistory));
|
||||
return 0;
|
||||
}
|
||||
|
||||
editor = placeEditor(view, editor);
|
||||
|
||||
if (!(flags & NoActivate)) {
|
||||
setCurrentEditor(editor, (flags & IgnoreNavigationHistory));
|
||||
if (!(flags & NoModeSwitch))
|
||||
ensureEditorManagerVisible();
|
||||
if (isVisible())
|
||||
editor->widget()->setFocus();
|
||||
}
|
||||
return editor;
|
||||
}
|
||||
|
||||
Core::IEditor *EditorManager::activateEditor(Core::Internal::EditorView *view, Core::IFile *file, OpenEditorFlags flags)
|
||||
{
|
||||
QList<IEditor*> editors = editorsForFile(file);
|
||||
Q_ASSERT(!editors.isEmpty());
|
||||
return activateEditor(view, editors.first(), flags);
|
||||
}
|
||||
|
||||
/* For something that has a 'QStringList mimeTypes' (IEditorFactory
|
||||
* or IExternalEditor), find the one best matching the mimetype passed in.
|
||||
* Recurse over the parent classes of the mimetype to find them. */
|
||||
template <class EditorFactoryLike>
|
||||
static void mimeTypeFactoryRecursion(const MimeDatabase *db,
|
||||
const MimeType &mimeType,
|
||||
const QList<EditorFactoryLike*> &allFactories,
|
||||
bool firstMatchOnly,
|
||||
QList<EditorFactoryLike*> *list)
|
||||
{
|
||||
typedef typename QList<EditorFactoryLike*>::const_iterator EditorFactoryLikeListConstIterator;
|
||||
// Loop factories to find type
|
||||
const QString type = mimeType.type();
|
||||
const EditorFactoryLikeListConstIterator fcend = allFactories.constEnd();
|
||||
for (EditorFactoryLikeListConstIterator fit = allFactories.constBegin(); fit != fcend; ++fit) {
|
||||
// Exclude duplicates when recursing over xml or C++ -> C -> text.
|
||||
EditorFactoryLike *factory = *fit;
|
||||
if (!list->contains(factory) && factory->mimeTypes().contains(type)) {
|
||||
list->push_back(*fit);
|
||||
if (firstMatchOnly)
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Any parent mime type classes? -> recurse
|
||||
QStringList parentTypes = mimeType.subClassesOf();
|
||||
if (parentTypes.empty())
|
||||
return;
|
||||
const QStringList::const_iterator pcend = parentTypes .constEnd();
|
||||
for (QStringList::const_iterator pit = parentTypes .constBegin(); pit != pcend; ++pit) {
|
||||
if (const MimeType parent = db->findByType(*pit))
|
||||
mimeTypeFactoryRecursion(db, parent, allFactories, firstMatchOnly, list);
|
||||
}
|
||||
}
|
||||
|
||||
EditorManager::EditorFactoryList
|
||||
EditorManager::editorFactories(const MimeType &mimeType, bool bestMatchOnly) const
|
||||
{
|
||||
EditorFactoryList rc;
|
||||
const EditorFactoryList allFactories = pluginManager()->getObjects<IEditorFactory>();
|
||||
mimeTypeFactoryRecursion(m_d->m_core->mimeDatabase(), mimeType, allFactories, bestMatchOnly, &rc);
|
||||
if (debugEditorManager)
|
||||
qDebug() << Q_FUNC_INFO << mimeType.type() << " returns " << rc;
|
||||
return rc;
|
||||
}
|
||||
|
||||
EditorManager::ExternalEditorList
|
||||
EditorManager::externalEditors(const MimeType &mimeType, bool bestMatchOnly) const
|
||||
{
|
||||
ExternalEditorList rc;
|
||||
const ExternalEditorList allEditors = pluginManager()->getObjects<IExternalEditor>();
|
||||
mimeTypeFactoryRecursion(m_d->m_core->mimeDatabase(), mimeType, allEditors, bestMatchOnly, &rc);
|
||||
if (debugEditorManager)
|
||||
qDebug() << Q_FUNC_INFO << mimeType.type() << " returns " << rc;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* For something that has a 'QString kind' (IEditorFactory
|
||||
* or IExternalEditor), find the one matching a kind. */
|
||||
template <class EditorFactoryLike>
|
||||
inline EditorFactoryLike *findByKind(ExtensionSystem::PluginManager *pm,
|
||||
const QString &kind)
|
||||
{
|
||||
const QList<EditorFactoryLike *> factories = pm->template getObjects<EditorFactoryLike>();
|
||||
foreach(EditorFactoryLike *efl, factories)
|
||||
if (kind == efl->kind())
|
||||
return efl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
IEditor *EditorManager::createEditor(const QString &editorKind,
|
||||
const QString &fileName)
|
||||
{
|
||||
typedef QList<IEditorFactory*> FactoryList;
|
||||
if (debugEditorManager)
|
||||
qDebug() << Q_FUNC_INFO << editorKind << fileName;
|
||||
|
||||
|
||||
EditorFactoryList factories;
|
||||
if (editorKind.isEmpty()) {
|
||||
// Find by mime type
|
||||
MimeType mimeType = m_d->m_core->mimeDatabase()->findByFile(QFileInfo(fileName));
|
||||
if (!mimeType) {
|
||||
qWarning("%s unable to determine mime type of %s/%s. Falling back to text/plain",
|
||||
Q_FUNC_INFO, fileName.toUtf8().constData(), editorKind.toUtf8().constData());
|
||||
mimeType = m_d->m_core->mimeDatabase()->findByType(QLatin1String("text/plain"));
|
||||
}
|
||||
factories = editorFactories(mimeType, true);
|
||||
} else {
|
||||
// Find by editor kind
|
||||
if (IEditorFactory *factory = findByKind<IEditorFactory>(pluginManager(), editorKind))
|
||||
factories.push_back(factory);
|
||||
}
|
||||
if (factories.empty()) {
|
||||
qWarning("%s: unable to find an editor factory for the file '%s', editor kind '%s'.",
|
||||
Q_FUNC_INFO, fileName.toUtf8().constData(), editorKind.toUtf8().constData());
|
||||
return 0;
|
||||
}
|
||||
|
||||
IEditor *editor = factories.front()->createEditor(this);
|
||||
if (editor)
|
||||
connect(editor, SIGNAL(changed()), this, SLOT(updateActions()));
|
||||
if (editor)
|
||||
emit editorCreated(editor, fileName);
|
||||
return editor;
|
||||
}
|
||||
|
||||
void EditorManager::addEditor(IEditor *editor, bool isDuplicate)
|
||||
{
|
||||
if (!editor)
|
||||
return;
|
||||
m_d->m_core->addContextObject(editor);
|
||||
|
||||
m_d->m_editorModel->addEditor(editor, isDuplicate);
|
||||
if (!isDuplicate) {
|
||||
m_d->m_core->fileManager()->addFile(editor->file());
|
||||
if (!editor->isTemporary()) {
|
||||
m_d->m_core->fileManager()->addToRecentFiles(editor->file()->fileName());
|
||||
}
|
||||
}
|
||||
emit editorOpened(editor);
|
||||
}
|
||||
|
||||
// Run the OpenWithDialog and return the editor kind
|
||||
// selected by the user.
|
||||
QString EditorManager::getOpenWithEditorKind(const QString &fileName,
|
||||
bool *isExternalEditor) const
|
||||
{
|
||||
// Collect editors that can open the file
|
||||
const MimeType mt = m_d->m_core->mimeDatabase()->findByFile(fileName);
|
||||
if (!mt)
|
||||
return QString();
|
||||
QStringList allEditorKinds;
|
||||
QStringList externalEditorKinds;
|
||||
// Built-in
|
||||
const EditorFactoryList editors = editorFactories(mt, false);
|
||||
const int size = editors.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
allEditorKinds.push_back(editors.at(i)->kind());
|
||||
}
|
||||
// External editors
|
||||
const ExternalEditorList exEditors = externalEditors(mt, false);
|
||||
const int esize = exEditors.size();
|
||||
for (int i = 0; i < esize; i++) {
|
||||
externalEditorKinds.push_back(exEditors.at(i)->kind());
|
||||
allEditorKinds.push_back(exEditors.at(i)->kind());
|
||||
}
|
||||
if (allEditorKinds.empty())
|
||||
return QString();
|
||||
// Run dialog.
|
||||
OpenWithDialog dialog(fileName, m_d->m_core->mainWindow());
|
||||
dialog.setEditors(allEditorKinds);
|
||||
dialog.setCurrentEditor(0);
|
||||
if (dialog.exec() != QDialog::Accepted)
|
||||
return QString();
|
||||
const QString selectedKind = dialog.editor();
|
||||
if (isExternalEditor)
|
||||
*isExternalEditor = externalEditorKinds.contains(selectedKind);
|
||||
return selectedKind;
|
||||
}
|
||||
|
||||
static QString formatFileFilters(const Core::ICore *core, QString *selectedFilter)
|
||||
{
|
||||
QString rc;
|
||||
// Compile list of filter strings. If we find a glob matching all files,
|
||||
// put it last and set it as default selectedFilter.
|
||||
QStringList filters = core->mimeDatabase()->filterStrings();
|
||||
filters.sort();
|
||||
selectedFilter->clear();
|
||||
if (filters.empty())
|
||||
return rc;
|
||||
const QString filterSeparator = QLatin1String(";;");
|
||||
bool hasAllFilter = false;
|
||||
const int size = filters.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
const QString &filterString = filters.at(i);
|
||||
if (filterString.isEmpty()) { // binary editor
|
||||
hasAllFilter = true;
|
||||
} else {
|
||||
if (!rc.isEmpty())
|
||||
rc += filterSeparator;
|
||||
rc += filterString;
|
||||
}
|
||||
}
|
||||
if (hasAllFilter) {
|
||||
// prepend all files filter
|
||||
// prepending instead of appending to work around a but in Qt/Mac
|
||||
QString allFilesFilter = EditorManager::tr("All Files (*)");
|
||||
if (!rc.isEmpty())
|
||||
allFilesFilter += filterSeparator;
|
||||
rc.prepend(allFilesFilter);
|
||||
*selectedFilter = allFilesFilter;
|
||||
} else {
|
||||
*selectedFilter = filters.front();
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
IEditor *EditorManager::openEditor(const QString &fileName, const QString &editorKind,
|
||||
EditorManager::OpenEditorFlags flags)
|
||||
{
|
||||
return openEditor(0, fileName, editorKind, flags);
|
||||
}
|
||||
|
||||
IEditor *EditorManager::openEditor(Core::Internal::EditorView *view, const QString &fileName,
|
||||
const QString &editorKind, EditorManager::OpenEditorFlags flags)
|
||||
{
|
||||
if (debugEditorManager)
|
||||
qDebug() << Q_FUNC_INFO << fileName << editorKind;
|
||||
|
||||
if (fileName.isEmpty())
|
||||
return 0;
|
||||
|
||||
const QList<IEditor *> editors = editorsForFileName(fileName);
|
||||
if (!editors.isEmpty()) {
|
||||
return activateEditor(view, editors.first(), flags);
|
||||
}
|
||||
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
|
||||
IEditor *editor = createEditor(editorKind, fileName);
|
||||
if (!editor || !editor->open(fileName)) {
|
||||
QApplication::restoreOverrideCursor();
|
||||
QMessageBox::critical(m_d->m_core->mainWindow(), tr("Opening File"), tr("Cannot open file %1!").arg(QDir::toNativeSeparators(fileName)));
|
||||
delete editor;
|
||||
editor = 0;
|
||||
return 0;
|
||||
}
|
||||
addEditor(editor);
|
||||
|
||||
IEditor *result= activateEditor(view, editor, flags);
|
||||
if (editor == result)
|
||||
restoreEditorState(editor);
|
||||
QApplication::restoreOverrideCursor();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool EditorManager::openExternalEditor(const QString &fileName, const QString &editorKind)
|
||||
{
|
||||
IExternalEditor *ee = findByKind<IExternalEditor>(pluginManager(), editorKind);
|
||||
if (!ee)
|
||||
return false;
|
||||
QString errorMessage;
|
||||
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
|
||||
const bool ok = ee->startEditor(fileName, &errorMessage);
|
||||
QApplication::restoreOverrideCursor();
|
||||
if (!ok)
|
||||
QMessageBox::critical(m_d->m_core->mainWindow(), tr("Opening File"), errorMessage);
|
||||
return ok;
|
||||
}
|
||||
|
||||
QStringList EditorManager::getOpenFileNames() const
|
||||
{
|
||||
static QString dir = QDir::homePath();
|
||||
if (m_d->fileFilters.isEmpty())
|
||||
m_d->fileFilters = formatFileFilters(m_d->m_core, &m_d->selectedFilter);
|
||||
|
||||
QString currentFile = ICore::instance()->fileManager()->currentFile();
|
||||
if (!currentFile.isEmpty()) {
|
||||
const QFileInfo fi(currentFile);
|
||||
dir = fi.absolutePath();
|
||||
}
|
||||
|
||||
QStringList files = QFileDialog::getOpenFileNames(m_d->m_core->mainWindow(), tr("Open File"),
|
||||
dir, m_d->fileFilters, &m_d->selectedFilter);
|
||||
if (!files.isEmpty())
|
||||
dir = QFileInfo(files.at(0)).absolutePath();
|
||||
return files;
|
||||
}
|
||||
|
||||
void EditorManager::ensureEditorManagerVisible()
|
||||
{
|
||||
if (!isVisible())
|
||||
m_d->m_core->modeManager()->activateMode(Constants::MODE_EDIT);
|
||||
}
|
||||
|
||||
IEditor *EditorManager::openEditorWithContents(const QString &editorKind,
|
||||
QString *titlePattern,
|
||||
const QString &contents)
|
||||
{
|
||||
if (debugEditorManager)
|
||||
qDebug() << Q_FUNC_INFO << editorKind << titlePattern << contents;
|
||||
|
||||
if (editorKind.isEmpty())
|
||||
return 0;
|
||||
|
||||
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
|
||||
IEditor *edt = createEditor(editorKind);
|
||||
if (!edt) {
|
||||
QApplication::restoreOverrideCursor();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!edt->createNew(contents)) {
|
||||
QApplication::restoreOverrideCursor();
|
||||
delete edt;
|
||||
edt = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
QString title = edt->displayName();
|
||||
|
||||
if (title.isEmpty() && titlePattern) {
|
||||
const QChar dollar = QLatin1Char('$');
|
||||
const QChar dot = QLatin1Char('.');
|
||||
|
||||
QString base = *titlePattern;
|
||||
if (base.isEmpty())
|
||||
base = QLatin1String("unnamed$");
|
||||
if (base.contains(dollar)) {
|
||||
int i = 1;
|
||||
QSet<QString> docnames;
|
||||
foreach (IEditor *editor, openedEditors()) {
|
||||
QString name = editor->file()->fileName();
|
||||
if (name.isEmpty()) {
|
||||
name = editor->displayName();
|
||||
name.remove(QLatin1Char('*'));
|
||||
} else {
|
||||
name = QFileInfo(name).completeBaseName();
|
||||
}
|
||||
docnames << name;
|
||||
}
|
||||
|
||||
do {
|
||||
title = base;
|
||||
title.replace(QString(dollar), QString::number(i++));
|
||||
} while (docnames.contains(title));
|
||||
} else {
|
||||
title = *titlePattern;
|
||||
}
|
||||
}
|
||||
*titlePattern = title;
|
||||
edt->setDisplayName(title);
|
||||
addEditor(edt);
|
||||
QApplication::restoreOverrideCursor();
|
||||
return edt;
|
||||
}
|
||||
|
||||
bool EditorManager::hasEditor(const QString &fileName) const
|
||||
{
|
||||
return !editorsForFileName(fileName).isEmpty();
|
||||
}
|
||||
|
||||
void EditorManager::restoreEditorState(IEditor *editor)
|
||||
{
|
||||
QTC_ASSERT(editor, return);
|
||||
QString fileName = editor->file()->fileName();
|
||||
if (m_d->m_editorStates.contains(fileName))
|
||||
editor->restoreState(m_d->m_editorStates.value(fileName).toByteArray());
|
||||
}
|
||||
|
||||
bool EditorManager::saveEditor(IEditor *editor)
|
||||
{
|
||||
return saveFile(editor);
|
||||
}
|
||||
|
||||
bool EditorManager::saveFile(IEditor *editor)
|
||||
{
|
||||
if (!editor)
|
||||
editor = currentEditor();
|
||||
if (!editor)
|
||||
return false;
|
||||
|
||||
IFile *file = editor->file();
|
||||
file->checkPermissions();
|
||||
|
||||
const QString &fileName = file->fileName();
|
||||
|
||||
if (fileName.isEmpty())
|
||||
return saveFileAs(editor);
|
||||
|
||||
bool success = false;
|
||||
|
||||
// try saving, no matter what isReadOnly tells us
|
||||
m_d->m_core->fileManager()->blockFileChange(file);
|
||||
success = file->save(fileName);
|
||||
m_d->m_core->fileManager()->unblockFileChange(file);
|
||||
|
||||
if (!success) {
|
||||
MakeWritableResult answer =
|
||||
makeEditorWritable(editor);
|
||||
if (answer == Failed)
|
||||
return false;
|
||||
if (answer == SavedAs)
|
||||
return true;
|
||||
|
||||
file->checkPermissions();
|
||||
|
||||
m_d->m_core->fileManager()->blockFileChange(file);
|
||||
success = file->save(fileName);
|
||||
m_d->m_core->fileManager()->unblockFileChange(file);
|
||||
}
|
||||
|
||||
if (success && !editor->isTemporary())
|
||||
m_d->m_core->fileManager()->addToRecentFiles(editor->file()->fileName());
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
EditorManager::ReadOnlyAction
|
||||
EditorManager::promptReadOnlyFile(const QString &fileName,
|
||||
const IVersionControl *versionControl,
|
||||
QWidget *parent,
|
||||
bool displaySaveAsButton)
|
||||
{
|
||||
QMessageBox msgBox(QMessageBox::Question, tr("File is Read Only"),
|
||||
tr("The file %1 is read only.").arg(QDir::toNativeSeparators(fileName)),
|
||||
QMessageBox::Cancel, parent);
|
||||
|
||||
QPushButton *sccButton = 0;
|
||||
if (versionControl && versionControl->supportsOperation(IVersionControl::OpenOperation))
|
||||
sccButton = msgBox.addButton(tr("Open with VCS (%1)").arg(versionControl->name()), QMessageBox::AcceptRole);
|
||||
|
||||
QPushButton *makeWritableButton = msgBox.addButton(tr("Make writable"), QMessageBox::AcceptRole);
|
||||
|
||||
QPushButton *saveAsButton = 0;
|
||||
if (displaySaveAsButton)
|
||||
saveAsButton = msgBox.addButton(tr("Save as ..."), QMessageBox::ActionRole);
|
||||
|
||||
msgBox.setDefaultButton(sccButton ? sccButton : makeWritableButton);
|
||||
msgBox.exec();
|
||||
|
||||
QAbstractButton *clickedButton = msgBox.clickedButton();
|
||||
if (clickedButton == sccButton)
|
||||
return RO_OpenVCS;
|
||||
if (clickedButton == makeWritableButton)
|
||||
return RO_MakeWriteable;
|
||||
if (clickedButton == saveAsButton)
|
||||
return RO_SaveAs;
|
||||
return RO_Cancel;
|
||||
}
|
||||
|
||||
|
||||
MakeWritableResult
|
||||
EditorManager::makeEditorWritable(IEditor *editor)
|
||||
{
|
||||
if (!editor || !editor->file())
|
||||
return Failed;
|
||||
QString directory = QFileInfo(editor->file()->fileName()).absolutePath();
|
||||
IVersionControl *versionControl = m_d->m_core->vcsManager()->findVersionControlForDirectory(directory);
|
||||
IFile *file = editor->file();
|
||||
const QString &fileName = file->fileName();
|
||||
|
||||
switch (promptReadOnlyFile(fileName, versionControl, m_d->m_core->mainWindow(), true)) {
|
||||
case RO_OpenVCS:
|
||||
if (!versionControl->vcsOpen(fileName)) {
|
||||
QMessageBox::warning(m_d->m_core->mainWindow(), tr("Failed!"), tr("Could not open the file for editing with SCC."));
|
||||
return Failed;
|
||||
}
|
||||
file->checkPermissions();
|
||||
return OpenedWithVersionControl;
|
||||
case RO_MakeWriteable: {
|
||||
const bool permsOk = QFile::setPermissions(fileName, QFile::permissions(fileName) | QFile::WriteUser);
|
||||
if (!permsOk) {
|
||||
QMessageBox::warning(m_d->m_core->mainWindow(), tr("Failed!"), tr("Could not set permissions to writable."));
|
||||
return Failed;
|
||||
}
|
||||
}
|
||||
file->checkPermissions();
|
||||
return MadeWritable;
|
||||
case RO_SaveAs :
|
||||
return saveFileAs(editor) ? SavedAs : Failed;
|
||||
case RO_Cancel:
|
||||
break;
|
||||
}
|
||||
return Failed;
|
||||
}
|
||||
|
||||
bool EditorManager::saveFileAs(IEditor *editor)
|
||||
{
|
||||
if (!editor)
|
||||
editor = currentEditor();
|
||||
if (!editor)
|
||||
return false;
|
||||
|
||||
QString absoluteFilePath = m_d->m_core->fileManager()->getSaveAsFileName(editor->file());
|
||||
if (absoluteFilePath.isEmpty())
|
||||
return false;
|
||||
if (absoluteFilePath != editor->file()->fileName()) {
|
||||
const QList<IEditor *> existList = editorsForFileName(absoluteFilePath);
|
||||
if (!existList.isEmpty()) {
|
||||
closeEditors(existList, false);
|
||||
}
|
||||
}
|
||||
|
||||
m_d->m_core->fileManager()->blockFileChange(editor->file());
|
||||
const bool success = editor->file()->save(absoluteFilePath);
|
||||
m_d->m_core->fileManager()->unblockFileChange(editor->file());
|
||||
editor->file()->checkPermissions();
|
||||
|
||||
if (success && !editor->isTemporary())
|
||||
m_d->m_core->fileManager()->addToRecentFiles(editor->file()->fileName());
|
||||
|
||||
updateActions();
|
||||
return success;
|
||||
}
|
||||
|
||||
void EditorManager::gotoNextDocHistory()
|
||||
{
|
||||
OpenEditorsWindow *dialog = windowPopup();
|
||||
if (dialog->isVisible()) {
|
||||
dialog->selectNextEditor();
|
||||
} else {
|
||||
EditorView *view = currentEditorView();
|
||||
dialog->setEditors(m_d->m_view, view, m_d->m_editorModel);
|
||||
dialog->selectNextEditor();
|
||||
showWindowPopup();
|
||||
}
|
||||
}
|
||||
|
||||
void EditorManager::gotoPreviousDocHistory()
|
||||
{
|
||||
OpenEditorsWindow *dialog = windowPopup();
|
||||
if (dialog->isVisible()) {
|
||||
dialog->selectPreviousEditor();
|
||||
} else {
|
||||
EditorView *view = currentEditorView();
|
||||
dialog->setEditors(m_d->m_view, view, m_d->m_editorModel);
|
||||
dialog->selectPreviousEditor();
|
||||
showWindowPopup();
|
||||
}
|
||||
}
|
||||
|
||||
void EditorManager::makeCurrentEditorWritable()
|
||||
{
|
||||
if (IEditor* curEditor = currentEditor())
|
||||
makeEditorWritable(curEditor);
|
||||
}
|
||||
|
||||
void EditorManager::updateActions()
|
||||
{
|
||||
QString fName;
|
||||
IEditor *curEditor = currentEditor();
|
||||
int openedCount = openedEditors().count() + m_d->m_editorModel->restoredEditorCount();
|
||||
if (curEditor) {
|
||||
if (!curEditor->file()->fileName().isEmpty()) {
|
||||
QFileInfo fi(curEditor->file()->fileName());
|
||||
fName = fi.fileName();
|
||||
} else {
|
||||
fName = curEditor->displayName();
|
||||
}
|
||||
|
||||
|
||||
if (curEditor->file()->isModified() && curEditor->file()->isReadOnly()) {
|
||||
// we are about to change a read-only file, warn user
|
||||
showEditorInfoBar(QLatin1String("Core.EditorManager.MakeWritable"),
|
||||
tr("<b>Warning:</b> You are changing a read-only file."),
|
||||
tr("Make writable"), this, SLOT(makeCurrentEditorWritable()));
|
||||
} else {
|
||||
hideEditorInfoBar(QLatin1String("Core.EditorManager.MakeWritable"));
|
||||
}
|
||||
}
|
||||
|
||||
m_d->m_saveAction->setEnabled(curEditor != 0 && curEditor->file()->isModified());
|
||||
m_d->m_saveAsAction->setEnabled(curEditor != 0 && curEditor->file()->isSaveAsAllowed());
|
||||
m_d->m_revertToSavedAction->setEnabled(curEditor != 0
|
||||
&& !curEditor->file()->fileName().isEmpty() && curEditor->file()->isModified());
|
||||
|
||||
QString quotedName;
|
||||
if (!fName.isEmpty())
|
||||
quotedName = '"' + fName + '"';
|
||||
m_d->m_saveAsAction->setText(tr("Save %1 As...").arg(quotedName));
|
||||
m_d->m_saveAction->setText(tr("&Save %1").arg(quotedName));
|
||||
m_d->m_revertToSavedAction->setText(tr("Revert %1 to Saved").arg(quotedName));
|
||||
|
||||
|
||||
m_d->m_closeCurrentEditorAction->setEnabled(curEditor != 0);
|
||||
m_d->m_closeCurrentEditorAction->setText(tr("Close %1").arg(quotedName));
|
||||
m_d->m_closeAllEditorsAction->setEnabled(openedCount > 0);
|
||||
m_d->m_closeOtherEditorsAction->setEnabled(openedCount > 1);
|
||||
m_d->m_closeOtherEditorsAction->setText((openedCount > 1 ? tr("Close All Except %1").arg(quotedName) : tr("Close Others")));
|
||||
|
||||
m_d->m_gotoNextDocHistoryAction->setEnabled(m_d->m_editorModel->rowCount() != 0);
|
||||
m_d->m_gotoPreviousDocHistoryAction->setEnabled(m_d->m_editorModel->rowCount() != 0);
|
||||
EditorView *view = currentEditorView();
|
||||
m_d->m_goBackAction->setEnabled(view ? view->canGoBack() : false);
|
||||
m_d->m_goForwardAction->setEnabled(view ? view->canGoForward() : false);
|
||||
|
||||
bool hasSplitter = m_d->m_splitter->isSplitter();
|
||||
m_d->m_removeCurrentSplitAction->setEnabled(hasSplitter);
|
||||
m_d->m_removeAllSplitsAction->setEnabled(hasSplitter);
|
||||
m_d->m_gotoOtherSplitAction->setEnabled(hasSplitter);
|
||||
|
||||
m_d->m_openInExternalEditorAction->setEnabled(curEditor != 0);
|
||||
}
|
||||
|
||||
QList<IEditor*> EditorManager::openedEditors() const
|
||||
{
|
||||
return m_d->m_editorModel->editors();
|
||||
}
|
||||
|
||||
OpenEditorsModel *EditorManager::openedEditorsModel() const
|
||||
{
|
||||
return m_d->m_editorModel;
|
||||
}
|
||||
|
||||
void EditorManager::addCurrentPositionToNavigationHistory(IEditor *editor, const QByteArray &saveState)
|
||||
{
|
||||
currentEditorView()->addCurrentPositionToNavigationHistory(editor, saveState);
|
||||
updateActions();
|
||||
}
|
||||
|
||||
void EditorManager::goBackInNavigationHistory()
|
||||
{
|
||||
currentEditorView()->goBackInNavigationHistory();
|
||||
updateActions();
|
||||
ensureEditorManagerVisible();
|
||||
return;
|
||||
}
|
||||
|
||||
void EditorManager::goForwardInNavigationHistory()
|
||||
{
|
||||
currentEditorView()->goForwardInNavigationHistory();
|
||||
updateActions();
|
||||
ensureEditorManagerVisible();
|
||||
}
|
||||
|
||||
OpenEditorsWindow *EditorManager::windowPopup() const
|
||||
{
|
||||
return m_d->m_windowPopup;
|
||||
}
|
||||
|
||||
void EditorManager::showWindowPopup() const
|
||||
{
|
||||
const QPoint p(mapToGlobal(QPoint(0, 0)));
|
||||
m_d->m_windowPopup->move((width()-m_d->m_windowPopup->width())/2 + p.x(),
|
||||
(height()-m_d->m_windowPopup->height())/2 + p.y());
|
||||
m_d->m_windowPopup->setVisible(true);
|
||||
}
|
||||
|
||||
QByteArray EditorManager::saveState() const
|
||||
{
|
||||
QByteArray bytes;
|
||||
QDataStream stream(&bytes, QIODevice::WriteOnly);
|
||||
|
||||
stream << QByteArray("EditorManagerV4");
|
||||
|
||||
QList<IEditor *> editors = openedEditors();
|
||||
foreach (IEditor *editor, editors) {
|
||||
if (!editor->file()->fileName().isEmpty()) {
|
||||
QByteArray state = editor->saveState();
|
||||
if (!state.isEmpty())
|
||||
m_d->m_editorStates.insert(editor->file()->fileName(), QVariant(state));
|
||||
}
|
||||
}
|
||||
|
||||
stream << m_d->m_editorStates;
|
||||
|
||||
QList<OpenEditorsModel::Entry> entries = m_d->m_editorModel->entries();
|
||||
stream << entries.count();
|
||||
|
||||
foreach (OpenEditorsModel::Entry entry, entries) {
|
||||
stream << entry.fileName() << entry.displayName() << entry.kind();
|
||||
}
|
||||
|
||||
stream << m_d->m_splitter->saveState();
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
bool EditorManager::restoreState(const QByteArray &state)
|
||||
{
|
||||
closeAllEditors(true);
|
||||
removeAllSplits();
|
||||
QDataStream stream(state);
|
||||
|
||||
QByteArray version;
|
||||
stream >> version;
|
||||
|
||||
if (version != "EditorManagerV4")
|
||||
return false;
|
||||
|
||||
QMap<QString, QVariant> editorstates;
|
||||
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
stream >> editorstates;
|
||||
|
||||
QMapIterator<QString, QVariant> i(editorstates);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
m_d->m_editorStates.insert(i.key(), i.value());
|
||||
}
|
||||
|
||||
int editorCount = 0;
|
||||
stream >> editorCount;
|
||||
while (--editorCount >= 0) {
|
||||
QString fileName;
|
||||
stream >> fileName;
|
||||
QString displayName;
|
||||
stream >> displayName;
|
||||
QByteArray kind;
|
||||
stream >> kind;
|
||||
|
||||
if (!fileName.isEmpty() && !displayName.isEmpty()){
|
||||
m_d->m_editorModel->addRestoredEditor(fileName, displayName, kind);
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray splitterstates;
|
||||
stream >> splitterstates;
|
||||
m_d->m_splitter->restoreState(splitterstates);
|
||||
|
||||
// splitting and stuff results in focus trouble, that's why we set the focus again after restoration
|
||||
ensureEditorManagerVisible();
|
||||
if (m_d->m_currentEditor) {
|
||||
m_d->m_currentEditor->widget()->setFocus();
|
||||
} else if (Core::Internal::SplitterOrView *view = currentSplitterOrView()) {
|
||||
if (IEditor *e = view->editor())
|
||||
e->widget()->setFocus();
|
||||
else if (view->view())
|
||||
view->view()->setFocus();
|
||||
}
|
||||
|
||||
QApplication::restoreOverrideCursor();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char * const documentStatesKey = "EditorManager/DocumentStates";
|
||||
static const char * const externalEditorKey = "EditorManager/ExternalEditorCommand";
|
||||
static const char * const reloadBehaviorKey = "EditorManager/ReloadBehavior";
|
||||
|
||||
void EditorManager::saveSettings()
|
||||
{
|
||||
SettingsDatabase *settings = m_d->m_core->settingsDatabase();
|
||||
settings->setValue(QLatin1String(documentStatesKey), m_d->m_editorStates);
|
||||
settings->setValue(QLatin1String(externalEditorKey), m_d->m_externalEditor);
|
||||
settings->setValue(QLatin1String(reloadBehaviorKey), m_d->m_reloadBehavior);
|
||||
}
|
||||
|
||||
void EditorManager::readSettings()
|
||||
{
|
||||
// Backward compatibility to old locations for these settings
|
||||
QSettings *qs = m_d->m_core->settings();
|
||||
if (qs->contains(QLatin1String(documentStatesKey))) {
|
||||
m_d->m_editorStates = qs->value(QLatin1String(documentStatesKey))
|
||||
.value<QMap<QString, QVariant> >();
|
||||
qs->remove(QLatin1String(documentStatesKey));
|
||||
}
|
||||
if (qs->contains(QLatin1String(externalEditorKey))) {
|
||||
m_d->m_externalEditor = qs->value(QLatin1String(externalEditorKey)).toString();
|
||||
qs->remove(QLatin1String(externalEditorKey));
|
||||
}
|
||||
|
||||
SettingsDatabase *settings = m_d->m_core->settingsDatabase();
|
||||
if (settings->contains(QLatin1String(documentStatesKey)))
|
||||
m_d->m_editorStates = settings->value(QLatin1String(documentStatesKey))
|
||||
.value<QMap<QString, QVariant> >();
|
||||
if (settings->contains(QLatin1String(externalEditorKey)))
|
||||
m_d->m_externalEditor = settings->value(QLatin1String(externalEditorKey)).toString();
|
||||
|
||||
if (settings->contains(QLatin1String(reloadBehaviorKey)))
|
||||
m_d->m_reloadBehavior = (IFile::ReloadBehavior)settings->value(QLatin1String(reloadBehaviorKey)).toInt();
|
||||
}
|
||||
|
||||
|
||||
void EditorManager::revertToSaved()
|
||||
{
|
||||
IEditor *currEditor = currentEditor();
|
||||
if (!currEditor)
|
||||
return;
|
||||
const QString fileName = currEditor->file()->fileName();
|
||||
if (fileName.isEmpty())
|
||||
return;
|
||||
if (currEditor->file()->isModified()) {
|
||||
QMessageBox msgBox(QMessageBox::Question, tr("Revert to Saved"),
|
||||
tr("You will lose your current changes if you proceed reverting %1.").arg(QDir::toNativeSeparators(fileName)),
|
||||
QMessageBox::Yes|QMessageBox::No, m_d->m_core->mainWindow());
|
||||
msgBox.button(QMessageBox::Yes)->setText(tr("Proceed"));
|
||||
msgBox.button(QMessageBox::No)->setText(tr("Cancel"));
|
||||
msgBox.setDefaultButton(QMessageBox::No);
|
||||
msgBox.setEscapeButton(QMessageBox::No);
|
||||
if (msgBox.exec() == QMessageBox::No)
|
||||
return;
|
||||
|
||||
}
|
||||
IFile::ReloadBehavior temp = IFile::ReloadAll;
|
||||
currEditor->file()->modified(&temp);
|
||||
}
|
||||
|
||||
void EditorManager::showEditorInfoBar(const QString &kind,
|
||||
const QString &infoText,
|
||||
const QString &buttonText,
|
||||
QObject *object, const char *member)
|
||||
{
|
||||
|
||||
currentEditorView()->showEditorInfoBar(kind, infoText, buttonText, object, member);
|
||||
}
|
||||
|
||||
|
||||
void EditorManager::hideEditorInfoBar(const QString &kind)
|
||||
{
|
||||
Core::Internal::EditorView *cev = currentEditorView();
|
||||
if (cev)
|
||||
cev->hideEditorInfoBar(kind);
|
||||
}
|
||||
|
||||
void EditorManager::showEditorStatusBar(const QString &kind,
|
||||
const QString &infoText,
|
||||
const QString &buttonText,
|
||||
QObject *object, const char *member)
|
||||
{
|
||||
|
||||
currentEditorView()->showEditorStatusBar(kind, infoText, buttonText, object, member);
|
||||
}
|
||||
|
||||
void EditorManager::hideEditorStatusBar(const QString &kind)
|
||||
{
|
||||
currentEditorView()->hideEditorStatusBar(kind);
|
||||
}
|
||||
|
||||
QString EditorManager::externalEditorHelpText() const
|
||||
{
|
||||
QString help = tr(
|
||||
"<table border=1 cellspacing=0 cellpadding=3>"
|
||||
"<tr><th>Variable</th><th>Expands to</th></tr>"
|
||||
"<tr><td>%f</td><td>file name</td></tr>"
|
||||
"<tr><td>%l</td><td>current line number</td></tr>"
|
||||
"<tr><td>%c</td><td>current column number</td></tr>"
|
||||
"<tr><td>%x</td><td>editor's x position on screen</td></tr>"
|
||||
"<tr><td>%y</td><td>editor's y position on screen</td></tr>"
|
||||
"<tr><td>%w</td><td>editor's width in pixels</td></tr>"
|
||||
"<tr><td>%h</td><td>editor's height in pixels</td></tr>"
|
||||
"<tr><td>%W</td><td>editor's width in characters</td></tr>"
|
||||
"<tr><td>%H</td><td>editor's height in characters</td></tr>"
|
||||
"<tr><td>%%</td><td>%</td></tr>"
|
||||
"</table>");
|
||||
return help;
|
||||
}
|
||||
|
||||
void EditorManager::openInExternalEditor()
|
||||
{
|
||||
QString command = m_d->m_externalEditor;
|
||||
if (command.isEmpty())
|
||||
command = defaultExternalEditor();
|
||||
|
||||
if (command.isEmpty())
|
||||
return;
|
||||
|
||||
IEditor *editor = currentEditor();
|
||||
if (!editor)
|
||||
return;
|
||||
if (editor->file()->isModified()) {
|
||||
bool cancelled = false;
|
||||
QList<IFile*> list = m_d->m_core->fileManager()->
|
||||
saveModifiedFiles(QList<IFile*>() << editor->file(), &cancelled);
|
||||
if (cancelled)
|
||||
return;
|
||||
}
|
||||
|
||||
QRect rect = editor->widget()->rect();
|
||||
QFont font = editor->widget()->font();
|
||||
QFontMetrics fm(font);
|
||||
rect.moveTo(editor->widget()->mapToGlobal(QPoint(0,0)));
|
||||
|
||||
QString pre = command;
|
||||
QString cmd;
|
||||
for (int i = 0; i < pre.size(); ++i) {
|
||||
QChar c = pre.at(i);
|
||||
if (c == QLatin1Char('%') && i < pre.size()-1) {
|
||||
c = pre.at(++i);
|
||||
QString s;
|
||||
if (c == QLatin1Char('f'))
|
||||
s = editor->file()->fileName();
|
||||
else if (c == QLatin1Char('l'))
|
||||
s = QString::number(editor->currentLine());
|
||||
else if (c == QLatin1Char('c'))
|
||||
s = QString::number(editor->currentColumn());
|
||||
else if (c == QLatin1Char('x'))
|
||||
s = QString::number(rect.x());
|
||||
else if (c == QLatin1Char('y'))
|
||||
s = QString::number(rect.y());
|
||||
else if (c == QLatin1Char('w'))
|
||||
s = QString::number(rect.width());
|
||||
else if (c == QLatin1Char('h'))
|
||||
s = QString::number(rect.height());
|
||||
else if (c == QLatin1Char('W'))
|
||||
s = QString::number(rect.width() / fm.width(QLatin1Char('x')));
|
||||
else if (c == QLatin1Char('H'))
|
||||
s = QString::number(rect.height() / fm.lineSpacing());
|
||||
else if (c == QLatin1Char('%'))
|
||||
s = c;
|
||||
else {
|
||||
s = QLatin1Char('%');
|
||||
cmd += c;
|
||||
}
|
||||
cmd += s;
|
||||
continue;
|
||||
|
||||
}
|
||||
cmd += c;
|
||||
}
|
||||
|
||||
QProcess::startDetached(cmd);
|
||||
}
|
||||
|
||||
void EditorManager::setExternalEditor(const QString &editor)
|
||||
{
|
||||
if (editor.isEmpty() || editor == defaultExternalEditor())
|
||||
m_d->m_externalEditor = defaultExternalEditor();
|
||||
else
|
||||
m_d->m_externalEditor = editor;
|
||||
}
|
||||
|
||||
QString EditorManager::externalEditor() const
|
||||
{
|
||||
if (m_d->m_externalEditor.isEmpty())
|
||||
return defaultExternalEditor();
|
||||
return m_d->m_externalEditor;
|
||||
}
|
||||
|
||||
void EditorManager::setReloadBehavior(IFile::ReloadBehavior behavior)
|
||||
{
|
||||
m_d->m_reloadBehavior = behavior;
|
||||
}
|
||||
|
||||
IFile::ReloadBehavior EditorManager::reloadBehavior() const
|
||||
{
|
||||
return m_d->m_reloadBehavior;
|
||||
}
|
||||
|
||||
Core::IEditor *EditorManager::duplicateEditor(Core::IEditor *editor)
|
||||
{
|
||||
if (!editor->duplicateSupported())
|
||||
return 0;
|
||||
|
||||
IEditor *duplicate = editor->duplicate(0);
|
||||
duplicate->restoreState(editor->saveState());
|
||||
emit editorCreated(duplicate, duplicate->file()->fileName());
|
||||
addEditor(duplicate, true);
|
||||
return duplicate;
|
||||
}
|
||||
|
||||
void EditorManager::split(Qt::Orientation orientation)
|
||||
{
|
||||
SplitterOrView *view = m_d->m_currentView;
|
||||
if (!view)
|
||||
view = m_d->m_currentEditor ? m_d->m_splitter->findView(m_d->m_currentEditor)
|
||||
: m_d->m_splitter->findFirstView();
|
||||
if (view && !view->splitter()) {
|
||||
view->split(orientation);
|
||||
}
|
||||
updateActions();
|
||||
}
|
||||
|
||||
void EditorManager::split()
|
||||
{
|
||||
split(Qt::Vertical);
|
||||
}
|
||||
|
||||
void EditorManager::splitSideBySide()
|
||||
{
|
||||
split(Qt::Horizontal);
|
||||
}
|
||||
|
||||
void EditorManager::removeCurrentSplit()
|
||||
{
|
||||
SplitterOrView *viewToClose = m_d->m_currentView;
|
||||
if (!viewToClose && m_d->m_currentEditor)
|
||||
viewToClose = m_d->m_splitter->findView(m_d->m_currentEditor);
|
||||
|
||||
if (!viewToClose || viewToClose->isSplitter() || viewToClose == m_d->m_splitter)
|
||||
return;
|
||||
|
||||
closeView(viewToClose->view());
|
||||
updateActions();
|
||||
}
|
||||
|
||||
void EditorManager::removeAllSplits()
|
||||
{
|
||||
if (!m_d->m_splitter->isSplitter())
|
||||
return;
|
||||
IEditor *editor = m_d->m_currentEditor;
|
||||
m_d->m_currentEditor = 0; // trigger update below
|
||||
if (editor && m_d->m_editorModel->isDuplicate(editor))
|
||||
editor = m_d->m_editorModel->originalForDuplicate(editor);
|
||||
m_d->m_splitter->unsplitAll();
|
||||
if (!editor)
|
||||
editor = pickUnusedEditor();
|
||||
activateEditor(editor);
|
||||
}
|
||||
|
||||
void EditorManager::gotoOtherSplit()
|
||||
{
|
||||
if (m_d->m_splitter->isSplitter()) {
|
||||
SplitterOrView *currentView = m_d->m_currentView;
|
||||
if (!currentView && m_d->m_currentEditor)
|
||||
currentView = m_d->m_splitter->findView(m_d->m_currentEditor);
|
||||
if (!currentView)
|
||||
currentView = m_d->m_splitter->findFirstView();
|
||||
SplitterOrView *view = m_d->m_splitter->findNextView(currentView);
|
||||
if (!view)
|
||||
view = m_d->m_splitter->findFirstView();
|
||||
if (view) {
|
||||
if (IEditor *editor = view->editor()) {
|
||||
setCurrentEditor(editor, true);
|
||||
editor->widget()->setFocus();
|
||||
} else {
|
||||
setCurrentView(view);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//===================EditorClosingCoreListener======================
|
||||
|
||||
EditorClosingCoreListener::EditorClosingCoreListener(EditorManager *em)
|
||||
: m_em(em)
|
||||
{
|
||||
}
|
||||
|
||||
bool EditorClosingCoreListener::editorAboutToClose(IEditor *)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EditorClosingCoreListener::coreAboutToClose()
|
||||
{
|
||||
// Do not ask for files to save.
|
||||
// MainWindow::closeEvent has already done that.
|
||||
return m_em->closeAllEditors(false);
|
||||
}
|
||||
|
BIN
ground/src/plugins/coreplugin/images/openpilot_logo_256.png
Normal file
BIN
ground/src/plugins/coreplugin/images/openpilot_logo_256.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
BIN
ground/src/plugins/coreplugin/images/openpilot_logo_64.png
Normal file
BIN
ground/src/plugins/coreplugin/images/openpilot_logo_64.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.4 KiB |
@ -156,7 +156,7 @@ MainWindow::MainWindow() :
|
||||
|
||||
setWindowTitle(tr("OpenPilot GCS"));
|
||||
#ifndef Q_WS_MAC
|
||||
qApp->setWindowIcon(QIcon(":/core/images/qtcreator_logo_128.png"));
|
||||
qApp->setWindowIcon(QIcon(":/core/images/openpilot_logo_128.png"));
|
||||
#endif
|
||||
QCoreApplication::setApplicationName(QLatin1String("OpenPilotGCS"));
|
||||
QCoreApplication::setApplicationVersion(QLatin1String(Core::Constants::GCS_VERSION_LONG));
|
||||
@ -733,9 +733,9 @@ void MainWindow::registerDefaultActions()
|
||||
|
||||
// About IDE Action
|
||||
#ifdef Q_WS_MAC
|
||||
tmpaction = new QAction(tr("About &Qt Creator"), this); // it's convention not to add dots to the about menu
|
||||
tmpaction = new QAction(tr("About &OpenPilot GCS"), this); // it's convention not to add dots to the about menu
|
||||
#else
|
||||
tmpaction = new QAction(tr("About &Qt Creator..."), this);
|
||||
tmpaction = new QAction(tr("About &OpenPilot GCS..."), this);
|
||||
#endif
|
||||
cmd = am->registerAction(tmpaction, Constants::ABOUT_QTCREATOR, m_globalContext);
|
||||
mhelp->addAction(cmd, Constants::G_HELP_ABOUT);
|
||||
|
@ -98,7 +98,7 @@ VersionDialog::VersionDialog(QWidget *parent)
|
||||
connect(buttonBox , SIGNAL(rejected()), this, SLOT(reject()));
|
||||
|
||||
QLabel *logoLabel = new QLabel;
|
||||
logoLabel->setPixmap(QPixmap(QLatin1String(":/core/images/qtcreator_logo_128.png")));
|
||||
logoLabel->setPixmap(QPixmap(QLatin1String(":/core/images/openpilot_logo_128.png")));
|
||||
layout->addWidget(logoLabel , 0, 0, 1, 1);
|
||||
layout->addWidget(copyRightLabel, 0, 1, 4, 4);
|
||||
layout->addWidget(buttonBox, 4, 0, 1, 5);
|
||||
|
Loading…
Reference in New Issue
Block a user