OSDN Git Service

change createEditor() error handling
[qt-creator-jp/qt-creator-jp.git] / src / plugins / coreplugin / editormanager / editormanager.cpp
index a3bce52..0650599 100644 (file)
@@ -2,28 +2,31 @@
 **
 ** This file is part of Qt Creator
 **
-** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
 **
-** Contact: Nokia Corporation (qt-info@nokia.com)
+** Contact: Nokia Corporation (info@qt.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.
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
 **
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at http://qt.nokia.com/contact.
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at info@qt.nokia.com.
 **
 **************************************************************************/
 
 #include <QtGui/QSplitter>
 #include <QtGui/QStackedLayout>
 
-#include <algorithm>
-
-Q_DECLARE_METATYPE(Core::IEditor*)
-
 enum { debugEditorManager=0 };
 
+static const char kCurrentDocumentFilePath[] = "CurrentDocument:FilePath";
+static const char kCurrentDocumentPath[] = "CurrentDocument:Path";
+static const char kCurrentDocumentXPos[] = "CurrentDocument:XPos";
+static const char kCurrentDocumentYPos[] = "CurrentDocument:YPos";
+
 static inline ExtensionSystem::PluginManager *pluginManager()
 {
     return ExtensionSystem::PluginManager::instance();
@@ -200,7 +204,6 @@ struct EditorManagerPrivate {
     QAction *m_gotoPreviousDocHistoryAction;
     QAction *m_goBackAction;
     QAction *m_goForwardAction;
-    QAction *m_openInExternalEditorAction;
     QAction *m_splitAction;
     QAction *m_splitSideBySideAction;
     QAction *m_removeCurrentSplitAction;
@@ -214,9 +217,10 @@ struct EditorManagerPrivate {
     Internal::OpenEditorsViewFactory *m_openEditorsFactory;
 
     OpenEditorsModel *m_editorModel;
-    QString m_externalEditor;
 
     IFile::ReloadSetting m_reloadSetting;
+
+    QString m_titleAddition;
 };
 }
 
@@ -234,7 +238,6 @@ EditorManagerPrivate::EditorManagerPrivate(ICore *core, QWidget *parent) :
     m_gotoPreviousDocHistoryAction(new QAction(EditorManager::tr("Previous Open Document in History"), parent)),
     m_goBackAction(new QAction(QIcon(QLatin1String(Constants::ICON_PREV)), EditorManager::tr("Go Back"), parent)),
     m_goForwardAction(new QAction(QIcon(QLatin1String(Constants::ICON_NEXT)), EditorManager::tr("Go Forward"), parent)),
-    m_openInExternalEditorAction(new QAction(EditorManager::tr("Open in External Editor"), parent)),
     m_windowPopup(0),
     m_coreListener(0),
     m_reloadSetting(IFile::AlwaysAsk)
@@ -307,7 +310,7 @@ EditorManager::EditorManager(ICore *core, QWidget *parent) :
     mwindow->addAction(cmd, Constants::G_WINDOW_NAVIGATE);
 
     // Close Action
-    cmd = am->registerAction(m_d->m_closeCurrentEditorAction, Constants::CLOSE, editManagerContext);
+    cmd = am->registerAction(m_d->m_closeCurrentEditorAction, Constants::CLOSE, editManagerContext, true);
     cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+W")));
     cmd->setAttribute(Core::Command::CA_UpdateText);
     cmd->setDefaultText(m_d->m_closeCurrentEditorAction->text());
@@ -324,13 +327,13 @@ EditorManager::EditorManager(ICore *core, QWidget *parent) :
 #endif
 
     // Close All Action
-    cmd = am->registerAction(m_d->m_closeAllEditorsAction, Constants::CLOSEALL, editManagerContext);
+    cmd = am->registerAction(m_d->m_closeAllEditorsAction, Constants::CLOSEALL, editManagerContext, true);
     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);
+    cmd = am->registerAction(m_d->m_closeOtherEditorsAction, Constants::CLOSEOTHERS, editManagerContext, true);
     mfile->addAction(cmd, Constants::G_FILE_CLOSE);
     cmd->setAttribute(Core::Command::CA_UpdateText);
     connect(m_d->m_closeOtherEditorsAction, SIGNAL(triggered()), this, SLOT(closeOtherEditors()));
@@ -414,7 +417,7 @@ EditorManager::EditorManager(ICore *core, QWidget *parent) :
     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->menu()->setTitle(tr("Ad&vanced"));
     advancedMenu->appendGroup(Constants::G_EDIT_FORMAT);
     advancedMenu->appendGroup(Constants::G_EDIT_COLLAPSING);
     advancedMenu->appendGroup(Constants::G_EDIT_BLOCKS);
@@ -431,13 +434,6 @@ EditorManager::EditorManager(ICore *core, QWidget *parent) :
     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::initEditorManagerConnections();
     // other setup
     m_d->m_splitter = new SplitterOrView(m_d->m_editorModel);
     m_d->m_view = m_d->m_splitter->view();
@@ -455,6 +451,7 @@ EditorManager::EditorManager(ICore *core, QWidget *parent) :
 
 EditorManager::~EditorManager()
 {
+    m_instance = 0;
     if (m_d->m_core) {
         ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
         if (m_d->m_coreListener) {
@@ -474,6 +471,18 @@ void EditorManager::init()
 
     m_d->m_openEditorsFactory = new OpenEditorsViewFactory();
     pluginManager()->addObject(m_d->m_openEditorsFactory);
+
+    VariableManager *vm = VariableManager::instance();
+    vm->registerVariable(QLatin1String(kCurrentDocumentFilePath),
+        tr("Full path of the current document including file name."));
+    vm->registerVariable(QLatin1String(kCurrentDocumentPath),
+        tr("Full path of the current document excluding file name."));
+    vm->registerVariable(QLatin1String(kCurrentDocumentXPos),
+        tr("X-coordinate of the current editor's upper left corner, relative to screen."));
+    vm->registerVariable(QLatin1String(kCurrentDocumentYPos),
+        tr("Y-coordinate of the current editor's upper left corner, relative to screen."));
+    connect(vm, SIGNAL(variableUpdateRequested(QString)),
+            this, SLOT(updateVariable(QString)));
 }
 
 
@@ -482,19 +491,6 @@ EditorToolBar *EditorManager::createToolBar(QWidget *parent)
     return new EditorToolBar(parent);
 }
 
-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);
@@ -534,6 +530,7 @@ void EditorManager::setCurrentEditor(IEditor *editor, bool ignoreNavigationHisto
         m_d->m_view->updateEditorHistory(editor); // the global view should have a complete history
     }
     updateActions();
+    updateWindowTitle();
     emit currentEditorChanged(editor);
 }
 
@@ -575,9 +572,9 @@ Core::Internal::EditorView *EditorManager::currentEditorView() const
 QList<IEditor *> EditorManager::editorsForFileName(const QString &filename) const
 {
     QList<IEditor *> found;
-    QString fixedname = FileManager::fixFileName(filename);
+    QString fixedname = FileManager::fixFileName(filename, FileManager::KeepLinks);
     foreach (IEditor *editor, openedEditors()) {
-        if (fixedname == FileManager::fixFileName(editor->file()->fileName()))
+        if (fixedname == FileManager::fixFileName(editor->file()->fileName(), FileManager::KeepLinks))
             found << editor;
     }
     return found;
@@ -768,7 +765,7 @@ bool EditorManager::closeEditors(const QList<IEditor*> &editorsToClose, bool ask
         foreach (ICoreListener *listener, listeners) {
             if (!listener->editorAboutToClose(editor)) {
                 editorAccepted = false;
-                closingFailed = false;
+                closingFailed = true;
                 break;
             }
         }
@@ -802,7 +799,8 @@ bool EditorManager::closeEditors(const QList<IEditor*> &editorsToClose, bool ask
     // remove the editors
     foreach (IEditor *editor, acceptedEditors) {
         emit editorAboutToClose(editor);
-        if (!editor->file()->fileName().isEmpty()) {
+        if (!editor->file()->fileName().isEmpty()
+                && !editor->isTemporary()) {
             QByteArray state = editor->saveState();
             if (!state.isEmpty())
                 m_d->m_editorStates.insert(editor->file()->fileName(), QVariant(state));
@@ -825,7 +823,7 @@ bool EditorManager::closeEditors(const QList<IEditor*> &editorsToClose, bool ask
         } else {
             QModelIndex idx = m_d->m_editorModel->firstRestoredEditor();
             if (idx.isValid())
-                activateEditor(idx, view, NoActivate);
+                activateEditorForIndex(view, idx, NoActivate);
         }
     }
 
@@ -843,6 +841,7 @@ bool EditorManager::closeEditors(const QList<IEditor*> &editorsToClose, bool ask
     if (!currentEditor()) {
         emit currentEditorChanged(0);
         updateActions();
+        updateWindowTitle();
     }
 
     return !closingFailed;
@@ -881,7 +880,7 @@ void EditorManager::closeDuplicate(Core::IEditor *editor)
         } else {
             QModelIndex idx = m_d->m_editorModel->firstRestoredEditor();
             if (idx.isValid())
-                activateEditor(idx, view, NoActivate);
+                activateEditorForIndex(view, idx, NoActivate);
         }
     }
 
@@ -903,16 +902,23 @@ Core::IEditor *EditorManager::pickUnusedEditor() const
     return 0;
 }
 
-Core::IEditor *EditorManager::activateEditor(const QModelIndex &index, Internal::EditorView *view, OpenEditorFlags flags)
+void EditorManager::activateEditorForIndex(const QModelIndex &index, OpenEditorFlags flags)
 {
+    activateEditorForIndex(currentEditorView(), index, flags);
+}
+
+void EditorManager::activateEditorForIndex(Internal::EditorView *view, const QModelIndex &index, OpenEditorFlags flags)
+{
+    Q_ASSERT(view);
     IEditor *editor = index.data(Qt::UserRole).value<IEditor*>();
     if (editor)  {
-        return activateEditor(view, editor, flags);
+        activateEditor(view, editor, flags);
+        return;
     }
 
     QString fileName = index.data(Qt::UserRole + 1).toString();
     QString id = index.data(Qt::UserRole + 2).toString();
-    return openEditor(view, fileName, id, flags);
+    openEditor(view, fileName, id, flags);
 }
 
 Core::IEditor *EditorManager::placeEditor(Core::Internal::EditorView *view, Core::IEditor *editor)
@@ -946,16 +952,18 @@ Core::IEditor *EditorManager::placeEditor(Core::Internal::EditorView *view, Core
     return editor;
 }
 
-Core::IEditor *EditorManager::activateEditor(Core::IEditor *editor, OpenEditorFlags flags)
+void EditorManager::activateEditor(Core::IEditor *editor, OpenEditorFlags flags)
 {
-    return activateEditor(0, editor, flags);
+    SplitterOrView *splitterOrView = m_d->m_splitter->findView(editor);
+    EditorView *view = (splitterOrView ? splitterOrView->view() : 0);
+    // TODO an IEditor doesn't have to belong to a view, which makes this method a bit funny
+    if (!view)
+        view = currentEditorView();
+    activateEditor(view, editor, flags);
 }
 
 Core::IEditor *EditorManager::activateEditor(Core::Internal::EditorView *view, Core::IEditor *editor, OpenEditorFlags flags)
 {
-    if (!view)
-        view = currentEditorView();
-
     Q_ASSERT(view);
 
     if (!editor) {
@@ -977,13 +985,15 @@ Core::IEditor *EditorManager::activateEditor(Core::Internal::EditorView *view, C
     return editor;
 }
 
-Core::IEditor *EditorManager::activateEditor(Core::Internal::EditorView *view, Core::IFile *file, OpenEditorFlags flags)
+Core::IEditor *EditorManager::activateEditorForFile(Core::Internal::EditorView *view, Core::IFile *file, OpenEditorFlags flags)
 {
+    Q_ASSERT(view);
     const QList<IEditor*> editors = editorsForFile(file);
     if (editors.isEmpty())
         return 0;
 
-    return activateEditor(view, editors.first(), flags);
+    activateEditor(view, editors.first(), flags);
+    return editors.first();
 }
 
 /* For something that has a 'QStringList mimeTypes' (IEditorFactory
@@ -1089,7 +1099,7 @@ IEditor *EditorManager::createEditor(const QString &editorId,
 
     IEditor *editor = factories.front()->createEditor(this);
     if (editor)
-        connect(editor, SIGNAL(changed()), this, SLOT(updateActions()));
+        connect(editor, SIGNAL(changed()), this, SLOT(handleEditorStateChange()));
     if (editor)
         emit editorCreated(editor, fileName);
     return editor;
@@ -1107,7 +1117,8 @@ void EditorManager::addEditor(IEditor *editor, bool isDuplicate)
         const bool addWatcher = !isTemporary;
         m_d->m_core->fileManager()->addFile(editor->file(), addWatcher);
         if (!isTemporary)
-            m_d->m_core->fileManager()->addToRecentFiles(editor->file()->fileName());
+            m_d->m_core->fileManager()->addToRecentFiles(editor->file()->fileName(),
+                                                         editor->id());
     }
     emit editorOpened(editor);
 }
@@ -1150,34 +1161,10 @@ QString EditorManager::getOpenWithEditorId(const QString &fileName,
     return selectedId;
 }
 
-static QString formatFileFilters(const Core::ICore *core, QString *selectedFilter = 0)
-{
-    if (selectedFilter)
-        selectedFilter->clear();
-
-    // Compile list of filter strings, sort, and remove duplicates (different mime types might
-    // generate the same filter).
-    QStringList filters = core->mimeDatabase()->filterStrings();
-    if (filters.empty())
-        return QString();
-    filters.sort();
-    filters.erase(std::unique(filters.begin(), filters.end()), filters.end());
-
-    static const QString allFilesFilter =
-        QCoreApplication::translate("Core", Constants::ALL_FILES_FILTER);
-    if (selectedFilter)
-        *selectedFilter = allFilesFilter;
-
-    // Prepend all files filter (instead of appending to work around a bug in Qt/Mac).
-    filters.prepend(allFilesFilter);
-
-    return filters.join(QLatin1String(";;"));
-}
-
 IEditor *EditorManager::openEditor(const QString &fileName, const QString &editorId,
                                    OpenEditorFlags flags, bool *newEditor)
 {
-    return openEditor(0, fileName, editorId, flags, newEditor);
+    return openEditor(currentEditorView(), fileName, editorId, flags, newEditor);
 }
 
 int extractLineNumber(QString *fileName)
@@ -1191,8 +1178,10 @@ int extractLineNumber(QString *fileName)
         return -1;
     if (fileName->at(i) == ':' || fileName->at(i) == '+') {
         int result = fileName->mid(i+1).toInt();
-        *fileName = fileName->left(i);
-        return result;
+        if (result) {
+            *fileName = fileName->left(i);
+            return result;
+        }
     }
     return -1;
 }
@@ -1222,17 +1211,20 @@ IEditor *EditorManager::openEditor(Core::Internal::EditorView *view, const QStri
         return activateEditor(view, editor, flags);
     }
 
-    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
     IEditor *editor = createEditor(editorId, fn);
     // If we could not open the file in the requested editor, fall
     // back to the default editor:
     if (!editor)
         editor = createEditor(QString(), fn);
-    if (!editor || !editor->open(fn)) {
+    if (!editor) // Internal error
+        return 0;
+
+    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
+    QString errorString;
+    if (!editor->open(&errorString, fn)) {
         QApplication::restoreOverrideCursor();
-        QMessageBox::critical(m_d->m_core->mainWindow(), tr("Opening File"), tr("Cannot open file %1!").arg(QDir::toNativeSeparators(fn)));
+        QMessageBox::critical(m_d->m_core->mainWindow(), tr("File Error"), errorString);
         delete editor;
-        editor = 0;
         return 0;
     }
     addEditor(editor);
@@ -1268,7 +1260,7 @@ bool EditorManager::openExternalEditor(const QString &fileName, const QString &e
 QStringList EditorManager::getOpenFileNames() const
 {
     QString selectedFilter;
-    const QString &fileFilters = formatFileFilters(m_d->m_core, &selectedFilter);
+    const QString &fileFilters = m_d->m_core->mimeDatabase()->allFiltersString(&selectedFilter);
     return ICore::instance()->fileManager()->getOpenFileNames(fileFilters,
                                                               QString(), &selectedFilter);
 }
@@ -1280,16 +1272,14 @@ QStringList EditorManager::getOpenFileNames() const
 void EditorManager::switchToPreferedMode()
 {
     QString preferedMode;
-    // Figure out prefered mode for editor
+    // Figure out preferred mode for editor
     if (m_d->m_currentEditor)
         preferedMode = m_d->m_currentEditor->preferredModeType();
 
     if (preferedMode.isEmpty())
         preferedMode = Constants::MODE_EDIT_TYPE;
 
-    if (m_d->m_core->modeManager()->currentMode()->type() != preferedMode) {
-        m_d->m_core->modeManager()->activateModeType(preferedMode);
-    }
+    m_d->m_core->modeManager()->activateModeType(preferedMode);
 }
 
 IEditor *EditorManager::openEditorWithContents(const QString &editorId,
@@ -1299,28 +1289,11 @@ IEditor *EditorManager::openEditorWithContents(const QString &editorId,
     if (debugEditorManager)
         qDebug() << Q_FUNC_INFO << editorId << titlePattern << contents;
 
-    if (editorId.isEmpty())
-        return 0;
-
     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
-    IEditor *edt = createEditor(editorId);
-    if (!edt) {
-        QApplication::restoreOverrideCursor();
-        return 0;
-    }
-
-    if (!edt->createNew(contents)) {
-        QApplication::restoreOverrideCursor();
-        delete edt;
-        edt = 0;
-        return 0;
-    }
-
-    QString title = edt->displayName();
 
+    QString title;
     if (titlePattern) {
         const QChar dollar = QLatin1Char('$');
-        const QChar dot = QLatin1Char('.');
 
         QString base = *titlePattern;
         if (base.isEmpty())
@@ -1332,7 +1305,6 @@ IEditor *EditorManager::openEditorWithContents(const QString &editorId,
                 QString name = editor->file()->fileName();
                 if (name.isEmpty()) {
                     name = editor->displayName();
-                    name.remove(QLatin1Char('*'));
                 } else {
                     name = QFileInfo(name).completeBaseName();
                 }
@@ -1348,6 +1320,23 @@ IEditor *EditorManager::openEditorWithContents(const QString &editorId,
         }
         *titlePattern = title;
     }
+
+    IEditor *edt = createEditor(editorId, title);
+    if (!edt) {
+        QApplication::restoreOverrideCursor();
+        return 0;
+    }
+
+    if (!edt->createNew(contents)) {
+        QApplication::restoreOverrideCursor();
+        delete edt;
+        edt = 0;
+        return 0;
+    }
+
+    if (title.isEmpty())
+        title = edt->displayName();
+
     edt->setDisplayName(title);
     addEditor(edt);
     QApplication::restoreOverrideCursor();
@@ -1368,34 +1357,33 @@ void EditorManager::restoreEditorState(IEditor *editor)
 
 bool EditorManager::saveEditor(IEditor *editor)
 {
-    return saveFile(editor);
+    return saveFile(editor->file());
 }
 
-bool EditorManager::saveFile(IEditor *editor)
+bool EditorManager::saveFile(IFile *fileParam)
 {
-    if (!editor)
-        editor = currentEditor();
-    if (!editor)
+    IFile *file = fileParam;
+    if (!file && currentEditor())
+        file = currentEditor()->file();
+    if (!file)
         return false;
 
-    IFile *file = editor->file();
     file->checkPermissions();
 
     const QString &fileName = file->fileName();
 
     if (fileName.isEmpty())
-        return saveFileAs(editor);
+        return saveFileAs(file);
 
     bool success = false;
+    bool isReadOnly;
 
     // 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);
+    success = m_d->m_core->fileManager()->saveFile(file, QString(), &isReadOnly);
 
-    if (!success) {
+    if (!success && isReadOnly) {
         MakeWritableResult answer =
-                makeEditorWritable(editor);
+                makeFileWritable(file);
         if (answer == Failed)
             return false;
         if (answer == SavedAs)
@@ -1403,79 +1391,34 @@ bool EditorManager::saveFile(IEditor *editor)
 
         file->checkPermissions();
 
-        m_d->m_core->fileManager()->blockFileChange(file);
-        success = file->save(fileName);
-        m_d->m_core->fileManager()->unblockFileChange(file);
+        success = m_d->m_core->fileManager()->saveFile(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)
-{
-    // Version Control: If automatic open is desired, open right away.
-    bool promptVCS = false;
-    if (versionControl && versionControl->supportsOperation(IVersionControl::OpenOperation)) {
-        if (versionControl->settingsFlags() & IVersionControl::AutoOpen)
-            return RO_OpenVCS;
-        promptVCS = true;
+    if (success) {
+        addFileToRecentFiles(file);
     }
 
-    // Create message box.
-    QMessageBox msgBox(QMessageBox::Question, tr("File is Read Only"),
-                       tr("The file <i>%1</i> is read only.").arg(QDir::toNativeSeparators(fileName)),
-                       QMessageBox::Cancel, parent);
-
-    QPushButton *vcsButton = 0;
-    if (promptVCS)
-        vcsButton = msgBox.addButton(tr("Open with VCS (%1)").arg(versionControl->displayName()), 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(vcsButton ? vcsButton : makeWritableButton);
-    msgBox.exec();
-
-    QAbstractButton *clickedButton = msgBox.clickedButton();
-    if (clickedButton == vcsButton)
-        return RO_OpenVCS;
-    if (clickedButton == makeWritableButton)
-        return RO_MakeWriteable;
-    if (clickedButton == saveAsButton)
-        return RO_SaveAs;
-    return  RO_Cancel;
+    return success;
 }
 
-
 MakeWritableResult
-EditorManager::makeEditorWritable(IEditor *editor)
+EditorManager::makeFileWritable(IFile *file)
 {
-    if (!editor || !editor->file())
+    if (!file)
         return Failed;
-    QString directory = QFileInfo(editor->file()->fileName()).absolutePath();
+    QString directory = QFileInfo(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:
+    switch (FileManager::promptReadOnlyFile(fileName, versionControl, m_d->m_core->mainWindow(), file->isSaveAsAllowed())) {
+    case FileManager::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: {
+    case FileManager::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."));
@@ -1484,23 +1427,23 @@ EditorManager::makeEditorWritable(IEditor *editor)
     }
         file->checkPermissions();
         return MadeWritable;
-    case RO_SaveAs :
-        return saveFileAs(editor) ? SavedAs : Failed;
-    case RO_Cancel:
+    case FileManager::RO_SaveAs :
+        return saveFileAs(file) ? SavedAs : Failed;
+    case FileManager::RO_Cancel:
         break;
     }
     return Failed;
 }
 
-bool EditorManager::saveFileAs(IEditor *editor)
+bool EditorManager::saveFileAs(IFile *fileParam)
 {
-    if (!editor)
-        editor = currentEditor();
-    if (!editor)
+    IFile *file = fileParam;
+    if (!file && currentEditor())
+        file = currentEditor()->file();
+    if (!file)
         return false;
 
-    IFile *file = editor->file();
-    const QString &filter = formatFileFilters(m_d->m_core);
+    const QString &filter = m_d->m_core->mimeDatabase()->allFiltersString();
     QString selectedFilter =
         m_d->m_core->mimeDatabase()->findByFile(QFileInfo(file->fileName())).filterString();
     const QString &absoluteFilePath =
@@ -1508,16 +1451,16 @@ bool EditorManager::saveFileAs(IEditor *editor)
 
     if (absoluteFilePath.isEmpty())
         return false;
+
     if (absoluteFilePath != file->fileName()) {
+        // close existing editors for the new file name
         const QList<IEditor *> existList = editorsForFileName(absoluteFilePath);
         if (!existList.isEmpty()) {
             closeEditors(existList, false);
         }
     }
 
-    m_d->m_core->fileManager()->blockFileChange(file);
-    const bool success = file->save(absoluteFilePath);
-    m_d->m_core->fileManager()->unblockFileChange(file);
+    const bool success = m_d->m_core->fileManager()->saveFile(file, absoluteFilePath);
     file->checkPermissions();
 
     // @todo: There is an issue to be treated here. The new file might be of a different mime
@@ -1526,13 +1469,30 @@ bool EditorManager::saveFileAs(IEditor *editor)
     // a good way out either (also the undo stack would be lost). Perhaps the best is to
     // re-think part of the editors design.
 
-    if (success && !editor->isTemporary())
-        m_d->m_core->fileManager()->addToRecentFiles(file->fileName());
-
+    if (success) {
+        addFileToRecentFiles(file);
+    }
     updateActions();
     return success;
 }
 
+/* Adds the file name to the recent files if there is at least one non-temporary editor for it */
+void EditorManager::addFileToRecentFiles(IFile *file)
+{
+    bool isTemporary = true;
+    QString editorId;
+    QList<IEditor *> editors = editorsForFile(file);
+    foreach (IEditor *editor, editors) {
+        if (!editor->isTemporary()) {
+            editorId = editor->id();
+            isTemporary = false;
+            break;
+        }
+    }
+    if (!isTemporary)
+        m_d->m_core->fileManager()->addToRecentFiles(file->fileName(), editorId);
+}
+
 void EditorManager::gotoNextDocHistory()
 {
     OpenEditorsWindow *dialog = windowPopup();
@@ -1562,7 +1522,37 @@ void EditorManager::gotoPreviousDocHistory()
 void EditorManager::makeCurrentEditorWritable()
 {
     if (IEditor* curEditor = currentEditor())
-        makeEditorWritable(curEditor);
+        makeFileWritable(curEditor->file());
+}
+
+void EditorManager::updateWindowTitle()
+{
+    QString windowTitle = tr("Qt Creator");
+    if (!m_d->m_titleAddition.isEmpty()) {
+        windowTitle.prepend(m_d->m_titleAddition + " - ");
+    }
+    IEditor *curEditor = currentEditor();
+    if (curEditor) {
+        QString editorName = curEditor->displayName();
+        if (!editorName.isEmpty())
+            windowTitle.prepend(editorName + " - ");
+        QString filePath = QFileInfo(curEditor->file()->fileName()).absoluteFilePath();
+        if (!filePath.isEmpty())
+            m_d->m_core->mainWindow()->setWindowFilePath(filePath);
+    } else {
+        m_d->m_core->mainWindow()->setWindowFilePath(QString());
+    }
+    m_d->m_core->mainWindow()->setWindowTitle(windowTitle);
+}
+
+void EditorManager::handleEditorStateChange()
+{
+    updateActions();
+    IEditor *currEditor = currentEditor();
+    if (qobject_cast<IEditor *>(sender()) == currEditor) {
+        updateWindowTitle();
+        emit currentEditorStateChanged(currEditor);
+    }
 }
 
 void EditorManager::updateActions()
@@ -1626,8 +1616,6 @@ void EditorManager::updateActions()
     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);
 }
 
 bool EditorManager::hasSplitter() const
@@ -1635,6 +1623,27 @@ bool EditorManager::hasSplitter() const
     return m_d->m_splitter->isSplitter();
 }
 
+QList<IEditor*> EditorManager::visibleEditors() const
+{
+    QList<IEditor *> editors;
+    if (m_d->m_splitter->isSplitter()) {
+        SplitterOrView *firstView = m_d->m_splitter->findFirstView();
+        SplitterOrView *view = firstView;
+        if (view) {
+            do {
+                if (view->editor())
+                    editors.append(view->editor());
+                view = m_d->m_splitter->findNextView(view);
+            } while (view && view != firstView);
+        }
+    } else {
+        if (m_d->m_splitter->editor()) {
+            editors.append(m_d->m_splitter->editor());
+        }
+    }
+    return editors;
+}
+
 QList<IEditor*> EditorManager::openedEditors() const
 {
     return m_d->m_editorModel->editors();
@@ -1742,17 +1751,9 @@ bool EditorManager::restoreState(const QByteArray &state)
     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());
-    }
+    stream >> m_d->m_editorStates;
 
     int editorCount = 0;
     stream >> editorCount;
@@ -1787,15 +1788,13 @@ bool EditorManager::restoreState(const QByteArray &state)
     return true;
 }
 
-static const char * const documentStatesKey = "EditorManager/DocumentStates";
-static const char * const externalEditorKey = "EditorManager/ExternalEditorCommand";
-static const char * const reloadBehaviorKey = "EditorManager/ReloadBehavior";
+static const char documentStatesKey[] = "EditorManager/DocumentStates";
+static const char 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_reloadSetting);
 }
 
@@ -1808,17 +1807,11 @@ void EditorManager::readSettings()
             .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_reloadSetting = (IFile::ReloadSetting)settings->value(QLatin1String(reloadBehaviorKey)).toInt();
@@ -1845,7 +1838,9 @@ void EditorManager::revertToSaved()
             return;
 
     }
-    currEditor->file()->reload(IFile::FlagReload, IFile::TypeContents);
+    QString errorString;
+    if (!currEditor->file()->reload(&errorString, IFile::FlagReload, IFile::TypeContents))
+        QMessageBox::critical(m_d->m_core->mainWindow(), tr("File Error"), errorString);
 }
 
 void EditorManager::showEditorInfoBar(const QString &id,
@@ -1879,106 +1874,6 @@ void EditorManager::hideEditorStatusBar(const QString &id)
     currentEditorView()->hideEditorStatusBar(id);
 }
 
-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('%');
-                s += 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::setReloadSetting(IFile::ReloadSetting behavior)
 {
     m_d->m_reloadSetting = behavior;
@@ -1989,7 +1884,7 @@ IFile::ReloadSetting EditorManager::reloadSetting() const
     return m_d->m_reloadSetting;
 }
 
-QTextCodec *EditorManager::defaultTextEncoding() const
+QTextCodec *EditorManager::defaultTextCodec() const
 {
     QSettings *settings = Core::ICore::instance()->settings();
     if (QTextCodec *candidate = QTextCodec::codecForName(
@@ -2005,6 +1900,7 @@ Core::IEditor *EditorManager::duplicateEditor(Core::IEditor *editor)
 
     IEditor *duplicate = editor->duplicate(0);
     duplicate->restoreState(editor->saveState());
+    connect(duplicate, SIGNAL(changed()), this, SLOT(handleEditorStateChange()));
     emit editorCreated(duplicate, duplicate->file()->fileName());
     addEditor(duplicate, true);
     return duplicate;
@@ -2050,7 +1946,8 @@ void EditorManager::removeAllSplits()
     if (!m_d->m_splitter->isSplitter())
         return;
     IEditor *editor = m_d->m_currentEditor;
-    m_d->m_currentEditor = 0; // trigger update below
+    // trigger update below
+    m_d->m_currentEditor = 0;
     if (editor && m_d->m_editorModel->isDuplicate(editor))
         m_d->m_editorModel->makeOriginal(editor);
     m_d->m_splitter->unsplitAll();
@@ -2085,5 +1982,47 @@ qint64 EditorManager::maxTextFileSize()
 {
     return (qint64(3) << 24);
 }
-//===================EditorClosingCoreListener======================
 
+void EditorManager::setWindowTitleAddition(const QString &addition)
+{
+    m_d->m_titleAddition = addition;
+    updateWindowTitle();
+}
+
+QString EditorManager::windowTitleAddition() const
+{
+    return m_d->m_titleAddition;
+}
+
+void EditorManager::updateVariable(const QString &variable)
+{
+    if (variable == QLatin1String(kCurrentDocumentFilePath)
+            || variable == QLatin1String(kCurrentDocumentPath)) {
+        QString value;
+        IEditor *curEditor = currentEditor();
+        if (curEditor) {
+            QString fileName = curEditor->file()->fileName();
+            if (!fileName.isEmpty()) {
+                if (variable == QLatin1String(kCurrentDocumentFilePath))
+                    value = QFileInfo(fileName).filePath();
+                else if (variable == QLatin1String(kCurrentDocumentPath))
+                    value = QFileInfo(fileName).path();
+            }
+        }
+        VariableManager::instance()->insert(variable, value);
+    } else if (variable == QLatin1String(kCurrentDocumentXPos)) {
+        QString value;
+        IEditor *curEditor = currentEditor();
+        if (curEditor) {
+            value = QString::number(curEditor->widget()->mapToGlobal(QPoint(0,0)).x());
+        }
+        VariableManager::instance()->insert(variable, value);
+    } else if (variable == QLatin1String(kCurrentDocumentYPos)) {
+        QString value;
+        IEditor *curEditor = currentEditor();
+        if (curEditor) {
+            value = QString::number(curEditor->widget()->mapToGlobal(QPoint(0,0)).y());
+        }
+        VariableManager::instance()->insert(variable, value);
+    }
+}