OSDN Git Service

add auto-saving of modified editors
authorOswald Buddenhagen <oswald.buddenhagen@nokia.com>
Tue, 10 May 2011 18:43:03 +0000 (20:43 +0200)
committerOswald Buddenhagen <oswald.buddenhagen@nokia.com>
Thu, 12 May 2011 18:10:03 +0000 (20:10 +0200)
Task-number: QTCREATORBUG-2847

48 files changed:
src/plugins/bineditor/bineditorplugin.cpp
src/plugins/cmakeprojectmanager/cmakeproject.cpp
src/plugins/cmakeprojectmanager/cmakeproject.h
src/plugins/coreplugin/editormanager/editormanager.cpp
src/plugins/coreplugin/editormanager/editormanager.h
src/plugins/coreplugin/editormanager/ieditor.h
src/plugins/coreplugin/filemanager.cpp
src/plugins/coreplugin/generalsettings.cpp
src/plugins/coreplugin/generalsettings.ui
src/plugins/coreplugin/ifile.cpp
src/plugins/coreplugin/ifile.h
src/plugins/cppeditor/cppeditor.cpp
src/plugins/cppeditor/cppeditor.h
src/plugins/designer/formwindoweditor.cpp
src/plugins/designer/formwindoweditor.h
src/plugins/designer/formwindowfile.cpp
src/plugins/designer/formwindowfile.h
src/plugins/genericprojectmanager/genericproject.cpp
src/plugins/genericprojectmanager/genericproject.h
src/plugins/genericprojectmanager/genericprojectfileseditor.cpp
src/plugins/genericprojectmanager/genericprojectfileseditor.h
src/plugins/glsleditor/glsleditor.cpp
src/plugins/glsleditor/glsleditoreditable.h
src/plugins/imageviewer/imageviewer.cpp
src/plugins/imageviewer/imageviewer.h
src/plugins/imageviewer/imageviewerfile.cpp
src/plugins/imageviewer/imageviewerfile.h
src/plugins/qmljseditor/qmljseditor.cpp
src/plugins/qmljseditor/qmljseditoreditable.h
src/plugins/qmlprojectmanager/qmlprojectfile.cpp
src/plugins/qmlprojectmanager/qmlprojectfile.h
src/plugins/qt4projectmanager/qt4nodes.cpp
src/plugins/qt4projectmanager/qt4nodes.h
src/plugins/qt4projectmanager/qt4project.cpp
src/plugins/qt4projectmanager/qt4project.h
src/plugins/resourceeditor/resourceeditorw.cpp
src/plugins/resourceeditor/resourceeditorw.h
src/plugins/tasklist/taskfile.cpp
src/plugins/tasklist/taskfile.h
src/plugins/texteditor/basetextdocument.cpp
src/plugins/texteditor/basetextdocument.h
src/plugins/texteditor/basetexteditor.cpp
src/plugins/texteditor/basetexteditor.h
src/plugins/vcsbase/submiteditorfile.cpp
src/plugins/vcsbase/submiteditorfile.h
src/plugins/vcsbase/vcsbasesubmiteditor.cpp
src/plugins/vcsbase/vcsbasesubmiteditor.h
src/shared/qrceditor/qrceditor.h

index ad4c424..2ea43ac 100644 (file)
@@ -203,8 +203,9 @@ public:
         return QLatin1String(Constants::C_BINEDITOR_MIMETYPE);
     }
 
-    bool save(QString *errorString, const QString &fileName = QString())
+    bool save(QString *errorString, const QString &fileName, bool autoSave)
     {
+        QTC_ASSERT(!autoSave, return true); // bineditor does not support autosave - it would be a bit expensive
         const QString fileNameToUse
             = fileName.isEmpty() ? m_fileName : fileName;
         if (m_editor->save(errorString, m_fileName, fileNameToUse)) {
@@ -363,7 +364,8 @@ public:
         m_file->setFilename(QString());
         return true;
     }
-    bool open(QString *errorString, const QString &fileName = QString()) {
+    bool open(QString *errorString, const QString &fileName, const QString &realFileName) {
+        QTC_ASSERT(fileName == realFileName, return false); // The bineditor can do no autosaving
         return m_file->open(errorString, fileName);
     }
     Core::IFile *file() { return m_file; }
index d61b326..f63849d 100644 (file)
@@ -738,12 +738,13 @@ CMakeFile::CMakeFile(CMakeProject *parent, QString fileName)
 
 }
 
-bool CMakeFile::save(QString *errorString, const QString &fileName)
+bool CMakeFile::save(QString *errorString, const QString &fileName, bool autoSave)
 {
     // Once we have an texteditor open for this file, we probably do
     // need to implement this, don't we.
     Q_UNUSED(errorString)
     Q_UNUSED(fileName)
+    Q_UNUSED(autoSave)
     return false;
 }
 
index 6027e38..116fa3c 100644 (file)
@@ -199,7 +199,7 @@ class CMakeFile : public Core::IFile
 public:
     CMakeFile(CMakeProject *parent, QString fileName);
 
-    bool save(QString *errorString, const QString &fileName = QString());
+    bool save(QString *errorString, const QString &fileName, bool autoSave);
     QString fileName() const;
 
     QString defaultPath() const;
index 5a73c4e..d53b3b5 100644 (file)
@@ -64,6 +64,7 @@
 #include <utils/consoleprocess.h>
 #include <utils/qtcassert.h>
 
+#include <QtCore/QDateTime>
 #include <QtCore/QDebug>
 #include <QtCore/QFileInfo>
 #include <QtCore/QMap>
@@ -71,6 +72,7 @@
 #include <QtCore/QSet>
 #include <QtCore/QSettings>
 #include <QtCore/QTextCodec>
+#include <QtCore/QTimer>
 
 #include <QtGui/QAction>
 #include <QtGui/QShortcut>
@@ -190,6 +192,7 @@ struct EditorManagerPrivate {
     Internal::SplitterOrView *m_splitter;
     QPointer<IEditor> m_currentEditor;
     QPointer<SplitterOrView> m_currentView;
+    QTimer *m_autoSaveTimer;
 
     ICore *m_core;
 
@@ -222,12 +225,16 @@ struct EditorManagerPrivate {
     IFile::ReloadSetting m_reloadSetting;
 
     QString m_titleAddition;
+
+    bool m_autoSaveEnabled;
+    int m_autoSaveInterval;
 };
 }
 
 EditorManagerPrivate::EditorManagerPrivate(ICore *core, QWidget *parent) :
     m_view(0),
     m_splitter(0),
+    m_autoSaveTimer(0),
     m_core(core),
     m_revertToSavedAction(new QAction(EditorManager::tr("Revert to Saved"), parent)),
     m_saveAction(new QAction(parent)),
@@ -241,7 +248,9 @@ EditorManagerPrivate::EditorManagerPrivate(ICore *core, QWidget *parent) :
     m_goForwardAction(new QAction(QIcon(QLatin1String(Constants::ICON_NEXT)), EditorManager::tr("Go Forward"), parent)),
     m_windowPopup(0),
     m_coreListener(0),
-    m_reloadSetting(IFile::AlwaysAsk)
+    m_reloadSetting(IFile::AlwaysAsk),
+    m_autoSaveEnabled(true),
+    m_autoSaveInterval(5)
 {
     m_editorModel = new OpenEditorsModel(parent);
 }
@@ -448,6 +457,10 @@ EditorManager::EditorManager(ICore *core, QWidget *parent) :
     updateActions();
 
     m_d->m_windowPopup = new OpenEditorsWindow(this);
+
+    m_d->m_autoSaveTimer = new QTimer(this);
+    connect(m_d->m_autoSaveTimer, SIGNAL(timeout()), SLOT(autoSave()));
+    updateAutoSave();
 }
 
 EditorManager::~EditorManager()
@@ -486,6 +499,13 @@ void EditorManager::init()
             this, SLOT(updateVariable(QString)));
 }
 
+void EditorManager::updateAutoSave()
+{
+    if (m_d->m_autoSaveEnabled)
+        m_d->m_autoSaveTimer->start(m_d->m_autoSaveInterval * (60 * 1000));
+    else
+        m_d->m_autoSaveTimer->stop();
+}
 
 EditorToolBar *EditorManager::createToolBar(QWidget *parent)
 {
@@ -1187,6 +1207,11 @@ int extractLineNumber(QString *fileName)
     return -1;
 }
 
+static QString autoSaveName(const QString &fileName)
+{
+    return fileName + QLatin1String(".autosave");
+}
+
 IEditor *EditorManager::openEditor(Core::Internal::EditorView *view, const QString &fileName,
                         const QString &editorId, OpenEditorFlags flags, bool *newEditor)
 {
@@ -1212,6 +1237,14 @@ IEditor *EditorManager::openEditor(Core::Internal::EditorView *view, const QStri
         return activateEditor(view, editor, flags);
     }
 
+    QString realFn = autoSaveName(fn);
+    QFileInfo fi(fn);
+    QFileInfo rfi(realFn);
+    if (!fi.exists() || !rfi.exists() || fi.lastModified() >= rfi.lastModified()) {
+        QFile::remove(realFn);
+        realFn = fn;
+    }
+
     IEditor *editor = createEditor(editorId, fn);
     // If we could not open the file in the requested editor, fall
     // back to the default editor:
@@ -1222,12 +1255,14 @@ IEditor *EditorManager::openEditor(Core::Internal::EditorView *view, const QStri
 
     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
     QString errorString;
-    if (!editor->open(&errorString, fn)) {
+    if (!editor->open(&errorString, fn, realFn)) {
         QApplication::restoreOverrideCursor();
         QMessageBox::critical(m_d->m_core->mainWindow(), tr("File Error"), errorString);
         delete editor;
         return 0;
     }
+    if (realFn != fn)
+        editor->file()->setRestoredFrom(realFn);
     addEditor(editor);
 
     if (newEditor)
@@ -1402,6 +1437,25 @@ bool EditorManager::saveFile(IFile *fileParam)
     return success;
 }
 
+void EditorManager::autoSave()
+{
+    QStringList errors;
+    // FIXME: the saving should be staggered
+    foreach (IEditor *editor, openedEditors()) {
+        IFile *file = editor->file();
+        if (!file->isModified() || !file->shouldAutoSave())
+            continue;
+        if (file->fileName().isEmpty()) // FIXME: save them to a dedicated directory
+            continue;
+        QString errorString;
+        if (!file->autoSave(&errorString, autoSaveName(file->fileName())))
+            errors << errorString;
+    }
+    if (!errors.isEmpty())
+        QMessageBox::critical(m_d->m_core->mainWindow(), tr("File Error"),
+                              errors.join(QLatin1String("\n")));
+}
+
 MakeWritableResult
 EditorManager::makeFileWritable(IFile *file)
 {
@@ -1549,8 +1603,11 @@ void EditorManager::updateWindowTitle()
 void EditorManager::handleEditorStateChange()
 {
     updateActions();
+    IEditor *theEditor = qobject_cast<IEditor *>(sender());
+    if (!theEditor->file()->isModified())
+        theEditor->file()->removeAutoSaveFile();
     IEditor *currEditor = currentEditor();
-    if (qobject_cast<IEditor *>(sender()) == currEditor) {
+    if (theEditor == currEditor) {
         updateWindowTitle();
         emit currentEditorStateChanged(currEditor);
     }
@@ -1771,8 +1828,15 @@ bool EditorManager::restoreState(const QByteArray &state)
         QByteArray id;
         stream >> id;
 
-        if (!fileName.isEmpty() && !displayName.isEmpty())
-            m_d->m_editorModel->addRestoredEditor(fileName, displayName, QString::fromUtf8(id));
+        if (!fileName.isEmpty() && !displayName.isEmpty()) {
+            QFileInfo fi(fileName);
+            QFileInfo rfi(autoSaveName(fileName));
+            if (fi.exists() && rfi.exists() && fi.lastModified() < rfi.lastModified()) {
+                openEditor(fileName, QString::fromUtf8(id));
+            } else {
+                m_d->m_editorModel->addRestoredEditor(fileName, displayName, QString::fromUtf8(id));
+            }
+        }
     }
 
     QByteArray splitterstates;
@@ -1796,12 +1860,16 @@ bool EditorManager::restoreState(const QByteArray &state)
 
 static const char documentStatesKey[] = "EditorManager/DocumentStates";
 static const char reloadBehaviorKey[] = "EditorManager/ReloadBehavior";
+static const char autoSaveEnabledKey[] = "EditorManager/AutoSaveEnabled";
+static const char autoSaveIntervalKey[] = "EditorManager/AutoSaveInterval";
 
 void EditorManager::saveSettings()
 {
     SettingsDatabase *settings = m_d->m_core->settingsDatabase();
     settings->setValue(QLatin1String(documentStatesKey), m_d->m_editorStates);
     settings->setValue(QLatin1String(reloadBehaviorKey), m_d->m_reloadSetting);
+    settings->setValue(QLatin1String(autoSaveEnabledKey), m_d->m_autoSaveEnabled);
+    settings->setValue(QLatin1String(autoSaveIntervalKey), m_d->m_autoSaveInterval);
 }
 
 void EditorManager::readSettings()
@@ -1821,6 +1889,12 @@ void EditorManager::readSettings()
 
     if (settings->contains(QLatin1String(reloadBehaviorKey)))
         m_d->m_reloadSetting = (IFile::ReloadSetting)settings->value(QLatin1String(reloadBehaviorKey)).toInt();
+
+    if (settings->contains(QLatin1String(autoSaveEnabledKey))) {
+        m_d->m_autoSaveEnabled = settings->value(QLatin1String(autoSaveEnabledKey)).toBool();
+        m_d->m_autoSaveInterval = settings->value(QLatin1String(autoSaveIntervalKey)).toInt();
+    }
+    updateAutoSave();
 }
 
 
@@ -1873,6 +1947,28 @@ IFile::ReloadSetting EditorManager::reloadSetting() const
     return m_d->m_reloadSetting;
 }
 
+void EditorManager::setAutoSaveEnabled(bool enabled)
+{
+    m_d->m_autoSaveEnabled = enabled;
+    updateAutoSave();
+}
+
+bool EditorManager::autoSaveEnabled() const
+{
+    return m_d->m_autoSaveEnabled;
+}
+
+void EditorManager::setAutoSaveInterval(int interval)
+{
+    m_d->m_autoSaveInterval = interval;
+    updateAutoSave();
+}
+
+int EditorManager::autoSaveInterval() const
+{
+    return m_d->m_autoSaveInterval;
+}
+
 QTextCodec *EditorManager::defaultTextCodec() const
 {
     QSettings *settings = Core::ICore::instance()->settings();
index 68749d0..e9e8897 100644 (file)
@@ -178,6 +178,11 @@ public:
     void setReloadSetting(IFile::ReloadSetting behavior);
     IFile::ReloadSetting reloadSetting() const;
 
+    void setAutoSaveEnabled(bool enabled);
+    bool autoSaveEnabled() const;
+    void setAutoSaveInterval(int interval);
+    int autoSaveInterval() const;
+
     QTextCodec *defaultTextCodec() const;
 
     static qint64 maxTextFileSize();
@@ -211,6 +216,7 @@ private slots:
     void updateWindowTitle();
     void handleEditorStateChange();
     void updateVariable(const QString &variable);
+    void autoSave();
 
 public slots:
     void goBackInNavigationHistory();
@@ -251,6 +257,7 @@ private:
     IEditor *pickUnusedEditor() const;
     void addFileToRecentFiles(IFile *file);
     void switchToPreferedMode();
+    void updateAutoSave();
 
     static EditorManager *m_instance;
     EditorManagerPrivate *m_d;
index 5edf4ee..11862e0 100644 (file)
@@ -50,7 +50,7 @@ public:
     virtual ~IEditor() {}
 
     virtual bool createNew(const QString &contents = QString()) = 0;
-    virtual bool open(QString *errorString, const QString &fileName = QString()) = 0;
+    virtual bool open(QString *errorString, const QString &fileName, const QString &realFileName) = 0;
     virtual IFile *file() = 0;
     virtual QString id() const = 0;
     virtual QString displayName() const = 0;
index f60c529..f93a03f 100644 (file)
@@ -624,7 +624,7 @@ bool FileManager::saveFile(IFile *file, const QString &fileName, bool *isReadOnl
     bool addWatcher = removeFile(file); // So that our own IFile gets no notification at all
 
     QString errorString;
-    if (!file->save(&errorString, fileName)) {
+    if (!file->save(&errorString, fileName, false)) {
         if (isReadOnly) {
             QFile ofi(effName);
             // Check whether the existing file is writable
index e43265f..0398908 100644 (file)
@@ -151,6 +151,9 @@ QWidget *GeneralSettings::createPage(QWidget *parent)
     m_page->helpExternalFileBrowserButton->hide();
 #endif
 
+    m_page->autoSaveCheckBox->setChecked(EditorManager::instance()->autoSaveEnabled());
+    m_page->autoSaveInterval->setValue(EditorManager::instance()->autoSaveInterval());
+
     connect(m_page->resetButton, SIGNAL(clicked()),
             this, SLOT(resetInterfaceColor()));
 #ifdef Q_OS_UNIX
@@ -199,6 +202,8 @@ void GeneralSettings::apply()
     Utils::UnixUtils::setFileBrowser(Core::ICore::instance()->settings(), m_page->externalFileBrowserEdit->text());
 #endif
 #endif
+    EditorManager::instance()->setAutoSaveEnabled(m_page->autoSaveCheckBox->isChecked());
+    EditorManager::instance()->setAutoSaveInterval(m_page->autoSaveInterval->value());
 }
 
 void GeneralSettings::finish()
index d276625..52b386b 100644 (file)
@@ -7,7 +7,7 @@
     <x>0</x>
     <y>0</y>
     <width>527</width>
-    <height>295</height>
+    <height>306</height>
    </rect>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout">
         </property>
        </widget>
       </item>
+      <item row="3" column="0" colspan="4">
+       <layout class="QHBoxLayout" name="horizontalLayout_5">
+        <item>
+         <widget class="QCheckBox" name="autoSaveCheckBox">
+          <property name="toolTip">
+           <string>If checked, temporary copies of modified files will be created automatically. If Qt Creator is restarted after a crash or power failure, it will ask whether the auto-saved content should be recovered.</string>
+          </property>
+          <property name="text">
+           <string>Auto-save modified files</string>
+          </property>
+          <property name="checked">
+           <bool>true</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <spacer name="horizontalSpacer_6">
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeType">
+           <enum>QSizePolicy::Fixed</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>20</width>
+            <height>20</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+        <item>
+         <widget class="QLabel" name="autoSaveIntervalLabel">
+          <property name="text">
+           <string>Interval:</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QSpinBox" name="autoSaveInterval">
+          <property name="suffix">
+           <string extracomment="unit for minutes">min</string>
+          </property>
+          <property name="minimum">
+           <number>1</number>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <spacer name="horizontalSpacer_5">
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>40</width>
+            <height>20</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+       </layout>
+      </item>
      </layout>
     </widget>
    </item>
  <resources>
   <include location="core.qrc"/>
  </resources>
- <connections/>
+ <connections>
+  <connection>
+   <sender>autoSaveCheckBox</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>autoSaveInterval</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>161</x>
+     <y>262</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>342</x>
+     <y>263</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
 </ui>
index 9a87306..122bdd5 100644 (file)
 
 #include "infobar.h"
 
+#include <QtCore/QFile>
+
 namespace Core {
 
-IFile::IFile(QObject *parent) : QObject(parent), m_infoBar(0), m_hasWriteWarning(false)
+IFile::IFile(QObject *parent) : QObject(parent), m_infoBar(0), m_hasWriteWarning(false), m_restored(false)
 {
 }
 
 IFile::~IFile()
 {
+    removeAutoSaveFile();
     delete m_infoBar;
 }
 
@@ -58,6 +61,43 @@ void IFile::checkPermissions()
 {
 }
 
+bool IFile::shouldAutoSave() const
+{
+    return false;
+}
+
+bool IFile::autoSave(QString *errorString, const QString &fileName)
+{
+    if (!save(errorString, fileName, true))
+        return false;
+    m_autoSaveName = fileName;
+    return true;
+}
+
+static const char kRestoredAutoSave[] = "RestoredAutoSave";
+
+void IFile::setRestoredFrom(const QString &name)
+{
+    m_autoSaveName = name;
+    m_restored = true;
+    InfoBarEntry info(QLatin1String(kRestoredAutoSave),
+          tr("File was restored from auto-saved copy. "
+             "Use <i>Save</i> to confirm, or <i>Revert to Saved</i> to discard changes."));
+    infoBar()->addInfo(info);
+}
+
+void IFile::removeAutoSaveFile()
+{
+    if (!m_autoSaveName.isEmpty()) {
+        QFile::remove(m_autoSaveName);
+        m_autoSaveName.clear();
+        if (m_restored) {
+            m_restored = false;
+            infoBar()->removeInfo(QLatin1String(kRestoredAutoSave));
+        }
+    }
+}
+
 InfoBar *IFile::infoBar()
 {
     if (!m_infoBar)
index 424de53..2a1452d 100644 (file)
@@ -84,13 +84,14 @@ public:
     IFile(QObject *parent = 0);
     virtual ~IFile();
 
-    virtual bool save(QString *errorString, const QString &fileName = QString()) = 0;
+    virtual bool save(QString *errorString, const QString &fileName = QString(), bool autoSave = false) = 0;
     virtual QString fileName() const = 0;
 
     virtual QString defaultPath() const = 0;
     virtual QString suggestedFileName() const = 0;
     virtual QString mimeType() const = 0;
 
+    virtual bool shouldAutoSave() const;
     virtual bool isModified() const = 0;
     virtual bool isReadOnly() const = 0;
     virtual bool isSaveAsAllowed() const = 0;
@@ -101,6 +102,10 @@ public:
 
     virtual void checkPermissions();
 
+    bool autoSave(QString *errorString, const QString &fileName);
+    void setRestoredFrom(const QString &name);
+    void removeAutoSaveFile();
+
     bool hasWriteWarning() const { return m_hasWriteWarning; }
     void setWriteWarning(bool has) { m_hasWriteWarning = has; }
 
@@ -113,8 +118,10 @@ signals:
     void reloaded();
 
 private:
+    QString m_autoSaveName;
     InfoBar *m_infoBar;
     bool m_hasWriteWarning;
+    bool m_restored;
 };
 
 } // namespace Core
index 66abc54..354d4ce 100644 (file)
@@ -1746,9 +1746,9 @@ QString CPPEditor::id() const
     return QLatin1String(CppEditor::Constants::CPPEDITOR_ID);
 }
 
-bool CPPEditor::open(QString *errorString, const QString & fileName)
+bool CPPEditor::open(QString *errorString, const QString &fileName, const QString &realFileName)
 {
-    bool b = TextEditor::BaseTextEditor::open(errorString, fileName);
+    bool b = TextEditor::BaseTextEditor::open(errorString, fileName, realFileName);
     editorWidget()->setMimeType(Core::ICore::instance()->mimeDatabase()->findByFile(QFileInfo(fileName)).type());
     return b;
 }
index c59be32..9250ba1 100644 (file)
@@ -152,7 +152,7 @@ public:
     QString id() const;
 
     bool isTemporary() const { return false; }
-    virtual bool open(QString *errorString, const QString & fileName);
+    virtual bool open(QString *errorString, const QString &fileName, const QString &realFileName);
 };
 
 class CPPEditorWidget : public TextEditor::BaseTextEditorWidget
index 9bd6723..4117a3b 100644 (file)
@@ -124,15 +124,16 @@ bool FormWindowEditor::createNew(const QString &contents)
 
     syncXmlEditor(contents);
     d->m_file.setFileName(QString());
+    d->m_file.setShouldAutoSave(false);
     return true;
 }
 
 void FormWindowEditor::slotOpen(QString *errorString, const QString &fileName)
 {
-    open(errorString, fileName);
+    open(errorString, fileName, fileName);
 }
 
-bool FormWindowEditor::open(QString *errorString, const QString &fileName)
+bool FormWindowEditor::open(QString *errorString, const QString &fileName, const QString &realFileName)
 {
     if (Designer::Constants::Internal::debug)
         qDebug() << "FormWindowEditor::open" << fileName;
@@ -149,7 +150,7 @@ bool FormWindowEditor::open(QString *errorString, const QString &fileName)
     const QString absfileName = fi.absoluteFilePath();
 
     Utils::FileReader reader;
-    if (!reader.fetch(absfileName, QIODevice::Text, errorString))
+    if (!reader.fetch(realFileName, QIODevice::Text, errorString))
         return false;
 
     form->setFileName(absfileName);
@@ -158,11 +159,12 @@ bool FormWindowEditor::open(QString *errorString, const QString &fileName)
     form->setContents(contents);
     if (!form->mainContainer())
         return false;
-    form->setDirty(false);
+    form->setDirty(fileName != realFileName);
     syncXmlEditor(contents);
 
     setDisplayName(fi.fileName());
     d->m_file.setFileName(absfileName);
+    d->m_file.setShouldAutoSave(false);
 
     if (Internal::ResourceHandler *rh = qFindChild<Designer::Internal::ResourceHandler*>(form))
         rh->updateResources();
index 0950ea1..3260917 100644 (file)
@@ -71,7 +71,7 @@ public:
 
     // IEditor
     virtual bool createNew(const QString &contents = QString());
-    virtual bool open(QString *errorString, const QString &fileName = QString());
+    virtual bool open(QString *errorString, const QString &fileName, const QString &realFileName);
     virtual Core::IFile *file();
     virtual QString id() const;
     virtual QString displayName() const;
index 3116299..9d729c9 100644 (file)
@@ -45,6 +45,7 @@
 
 #include <QtGui/QMessageBox>
 #include <QtGui/QMainWindow>
+#include <QtGui/QUndoStack>
 
 #include <QtCore/QFile>
 #include <QtCore/QFileInfo>
@@ -57,13 +58,16 @@ namespace Internal {
 FormWindowFile::FormWindowFile(QDesignerFormWindowInterface *form, QObject *parent)
   : Core::IFile(parent),
     m_mimeType(QLatin1String(Designer::Constants::FORM_MIMETYPE)),
+    m_shouldAutoSave(false),
     m_formWindow(form)
 {
     connect(m_formWindow->core()->formWindowManager(), SIGNAL(formWindowRemoved(QDesignerFormWindowInterface*)),
             this, SLOT(slotFormWindowRemoved(QDesignerFormWindowInterface*)));
+    connect(m_formWindow->commandHistory(), SIGNAL(indexChanged(int)),
+            this, SLOT(setShouldAutoSave()));
 }
 
-bool FormWindowFile::save(QString *errorString, const QString &name /* = QString() */)
+bool FormWindowFile::save(QString *errorString, const QString &name, bool autoSave)
 {
     const QString actualName = name.isEmpty() ? fileName() : name;
 
@@ -77,12 +81,16 @@ bool FormWindowFile::save(QString *errorString, const QString &name /* = QString
 
     const QFileInfo fi(actualName);
     const QString oldFormName = m_formWindow->fileName();
-    const QString formName = fi.absoluteFilePath();
-    m_formWindow->setFileName(formName);
+    if (!autoSave)
+        m_formWindow->setFileName(fi.absoluteFilePath());
 
     const bool warningsEnabled = qdesigner_internal::QSimpleResource::setWarningsEnabled(false);
     const bool writeOK = writeFile(actualName, errorString);
     qdesigner_internal::QSimpleResource::setWarningsEnabled(warningsEnabled);
+    m_shouldAutoSave = false;
+    if (autoSave)
+        return writeOK;
+
     if (!writeOK) {
         m_formWindow->setFileName(oldFormName);
         return false;
@@ -111,6 +119,11 @@ QString FormWindowFile::fileName() const
     return m_fileName;
 }
 
+bool FormWindowFile::shouldAutoSave() const
+{
+    return m_shouldAutoSave;
+}
+
 bool FormWindowFile::isModified() const
 {
     return m_formWindow && m_formWindow->isDirty();
index 1b074ca..13d4956 100644 (file)
@@ -53,8 +53,9 @@ public:
     explicit FormWindowFile(QDesignerFormWindowInterface *form, QObject *parent = 0);
 
     // IFile
-    virtual bool save(QString *errorString, const QString &fileName = QString());
+    virtual bool save(QString *errorString, const QString &fileName, bool autoSave);
     virtual QString fileName() const;
+    virtual bool shouldAutoSave() const;
     virtual bool isModified() const;
     virtual bool isReadOnly() const;
     virtual bool isSaveAsAllowed() const;
@@ -79,6 +80,7 @@ signals:
 
 public slots:
     void setFileName(const QString &);
+    void setShouldAutoSave(bool sad = true) { m_shouldAutoSave = sad; }
 
 private slots:
     void slotFormWindowRemoved(QDesignerFormWindowInterface *w);
@@ -88,6 +90,7 @@ private:
 
     QString m_fileName;
     QString m_suggestedName;
+    bool m_shouldAutoSave;
     // Might actually go out of scope before the IEditor due
     // to deleting the WidgetHost which owns it.
     QPointer<QDesignerFormWindowInterface> m_formWindow;
index cd6cb22..ff1fe41 100644 (file)
@@ -566,7 +566,7 @@ GenericProjectFile::GenericProjectFile(GenericProject *parent, QString fileName)
 GenericProjectFile::~GenericProjectFile()
 { }
 
-bool GenericProjectFile::save(QString *, const QString &)
+bool GenericProjectFile::save(QString *, const QString &, bool)
 {
     return false;
 }
index ed25acf..31146ba 100644 (file)
@@ -159,7 +159,7 @@ public:
     GenericProjectFile(GenericProject *parent, QString fileName);
     virtual ~GenericProjectFile();
 
-    virtual bool save(QString *errorString, const QString &fileName = QString());
+    virtual bool save(QString *errorString, const QString &fileName, bool autoSave);
     virtual QString fileName() const;
 
     virtual QString defaultPath() const;
index 777ae91..941738c 100644 (file)
@@ -173,11 +173,12 @@ ProjectFilesDocument::ProjectFilesDocument(Manager *manager)
 ProjectFilesDocument::~ProjectFilesDocument()
 { }
 
-bool ProjectFilesDocument::save(QString *errorString, const QString &name)
+bool ProjectFilesDocument::save(QString *errorString, const QString &name, bool autoSave)
 {
-    if (! BaseTextDocument::save(errorString, name))
+    if (!BaseTextDocument::save(errorString, name, autoSave))
         return false;
 
-    m_manager->notifyChanged(name);
+    if (!autoSave)
+        m_manager->notifyChanged(name);
     return true;
 }
index a197380..cdda0d7 100644 (file)
@@ -113,7 +113,7 @@ public:
     ProjectFilesDocument(Manager *manager);
     virtual ~ProjectFilesDocument();
 
-    virtual bool save(QString *errorString, const QString &name);
+    virtual bool save(QString *errorString, const QString &name, bool autoSave);
 
 private:
     Manager *m_manager;
index 78950c0..83c84d1 100644 (file)
@@ -205,10 +205,10 @@ QString GLSLEditorEditable::id() const
     return QLatin1String(GLSLEditor::Constants::C_GLSLEDITOR_ID);
 }
 
-bool GLSLEditorEditable::open(QString *errorString, const QString &fileName)
+bool GLSLEditorEditable::open(QString *errorString, const QString &fileName, const QString &realFileName)
 {
     editorWidget()->setMimeType(Core::ICore::instance()->mimeDatabase()->findByFile(QFileInfo(fileName)).type());
-    bool b = TextEditor::BaseTextEditor::open(errorString, fileName);
+    bool b = TextEditor::BaseTextEditor::open(errorString, fileName, realFileName);
     return b;
 }
 
index 5fc8f45..5be119b 100644 (file)
@@ -51,7 +51,7 @@ public:
     Core::IEditor *duplicate(QWidget *parent);
     QString id() const;
     bool isTemporary() const { return false; }
-    virtual bool open(QString *errorString, const QString &fileName);
+    virtual bool open(QString *errorString, const QString &fileName, const QString &realFileName);
     virtual QString preferredModeType() const;
 };
 
index 8f2d18c..730f0df 100644 (file)
@@ -117,10 +117,10 @@ bool ImageViewer::createNew(const QString &contents)
     return false;
 }
 
-bool ImageViewer::open(QString *errorString, const QString &fileName)
+bool ImageViewer::open(QString *errorString, const QString &fileName, const QString &realFileName)
 {
-    if (!d_ptr->imageView->openFile(fileName)) {
-        *errorString = tr("Cannot open image file %1").arg(QDir::toNativeSeparators(fileName));
+    if (!d_ptr->imageView->openFile(realFileName)) {
+        *errorString = tr("Cannot open image file %1").arg(QDir::toNativeSeparators(realFileName));
         return false;
     }
     setDisplayName(QFileInfo(fileName).fileName());
index ee09d83..81b8c42 100644 (file)
@@ -56,7 +56,7 @@ public:
     ~ImageViewer();
 
     bool createNew(const QString &contents = QString());
-    bool open(QString *errorString, const QString &fileName = QString());
+    bool open(QString *errorString, const QString &fileName, const QString &realFileName);
     Core::IFile *file();
     QString id() const;
     QString displayName() const;
index 728d0fe..a33e17f 100644 (file)
@@ -74,14 +74,15 @@ bool ImageViewerFile::reload(QString *errorString,
         emit changed();
         return true;
     } else {
-        return d_ptr->editor->open(errorString, d_ptr->fileName);
+        return d_ptr->editor->open(errorString, d_ptr->fileName, d_ptr->fileName);
     }
 }
 
-bool ImageViewerFile::save(QString *errorString, const QString &fileName)
+bool ImageViewerFile::save(QString *errorString, const QString &fileName, bool autoSave)
 {
     Q_UNUSED(errorString)
     Q_UNUSED(fileName);
+    Q_UNUSED(autoSave)
     return false;
 }
 
index 39516cb..c223490 100644 (file)
@@ -49,7 +49,7 @@ public:
     explicit ImageViewerFile(ImageViewer *parent = 0);
     ~ImageViewerFile();
 
-    bool save(QString *errorString, const QString &fileName = QString());
+    bool save(QString *errorString, const QString &fileName, bool autoSave);
     void rename(const QString &newName);
     QString fileName() const;
 
index 88349d6..41f9646 100644 (file)
@@ -740,9 +740,9 @@ QString QmlJSEditorEditable::id() const
     return QLatin1String(QmlJSEditor::Constants::C_QMLJSEDITOR_ID);
 }
 
-bool QmlJSEditorEditable::open(QString *errorString, const QString &fileName)
+bool QmlJSEditorEditable::open(QString *errorString, const QString &fileName, const QString &realFileName)
 {
-    bool b = TextEditor::BaseTextEditor::open(errorString, fileName);
+    bool b = TextEditor::BaseTextEditor::open(errorString, fileName, realFileName);
     editorWidget()->setMimeType(Core::ICore::instance()->mimeDatabase()->findByFile(QFileInfo(fileName)).type());
     return b;
 }
index fdabc8f..4cdbfdb 100644 (file)
@@ -50,7 +50,7 @@ public:
     Core::IEditor *duplicate(QWidget *parent);
     QString id() const;
     bool isTemporary() const { return false; }
-    virtual bool open(QString *errorString, const QString & fileName);
+    virtual bool open(QString *errorString, const QString &fileName, const QString &realFileName);
     virtual QString preferredModeType() const;
     void setTextCodec(QTextCodec *codec, TextCodecReason = TextCodecOtherReason);
 };
index d296285..44189f1 100644 (file)
@@ -46,7 +46,7 @@ QmlProjectFile::QmlProjectFile(QmlProject *parent, QString fileName)
 QmlProjectFile::~QmlProjectFile()
 { }
 
-bool QmlProjectFile::save(QString *, const QString &)
+bool QmlProjectFile::save(QString *, const QString &, bool)
 {
     return false;
 }
index 3c392b5..e7533b0 100644 (file)
@@ -49,7 +49,7 @@ public:
     QmlProjectFile(QmlProject *parent, QString fileName);
     virtual ~QmlProjectFile();
 
-    virtual bool save(QString *errorString, const QString &fileName = QString());
+    virtual bool save(QString *errorString, const QString &fileName, bool autoSave);
     virtual QString fileName() const;
     virtual void rename(const QString &newName);
 
index 3ae8cc2..8c60947 100644 (file)
@@ -176,10 +176,11 @@ Qt4PriFile::Qt4PriFile(Qt4PriFileNode *qt4PriFile)
 
 }
 
-bool Qt4PriFile::save(QString *errorString, const QString &fileName)
+bool Qt4PriFile::save(QString *errorString, const QString &fileName, bool autoSave)
 {
     Q_UNUSED(errorString);
     Q_UNUSED(fileName);
+    Q_UNUSED(autoSave);
     return false;
 }
 
index 2854009..9f72455 100644 (file)
@@ -115,7 +115,7 @@ class Qt4PriFile : public Core::IFile
     Q_OBJECT
 public:
     Qt4PriFile(Qt4PriFileNode *qt4PriFile);
-    virtual bool save(QString *errorString, const QString &fileName = QString());
+    virtual bool save(QString *errorString, const QString &fileName, bool autoSave);
     virtual QString fileName() const;
     virtual void rename(const QString &newName);
 
index 977b4a7..b700b24 100644 (file)
@@ -183,7 +183,7 @@ Qt4ProjectFile::Qt4ProjectFile(Qt4Project *project, const QString &filePath, QOb
 {
 }
 
-bool Qt4ProjectFile::save(QString *, const QString &)
+bool Qt4ProjectFile::save(QString *, const QString &, bool)
 {
     // This is never used
     return false;
index 26290d7..1389aad 100644 (file)
@@ -80,7 +80,7 @@ class Qt4ProjectFile : public Core::IFile
 public:
     Qt4ProjectFile(Qt4Project *project, const QString &filePath, QObject *parent = 0);
 
-    bool save(QString *errorString, const QString &fileName = QString());
+    bool save(QString *errorString, const QString &fileName, bool autoSave);
     QString fileName() const;
     virtual void rename(const QString &newName);
 
index e9fb06b..d307a6f 100644 (file)
@@ -75,7 +75,9 @@ ResourceEditorW::ResourceEditorW(const Core::Context &context,
                                QWidget *parent)
       : m_resourceEditor(new SharedTools::QrcEditor(parent)),
         m_resourceFile(new ResourceEditorFile(this)),
-        m_plugin(plugin)
+        m_plugin(plugin),
+        m_shouldAutoSave(false),
+        m_diskIo(false)
 {
     setContext(context);
     setWidget(m_resourceEditor);
@@ -85,6 +87,8 @@ ResourceEditorW::ResourceEditorW(const Core::Context &context,
     connect(m_resourceEditor, SIGNAL(dirtyChanged(bool)), this, SLOT(dirtyChanged(bool)));
     connect(m_resourceEditor, SIGNAL(undoStackChanged(bool, bool)),
             this, SLOT(onUndoStackChanged(bool, bool)));
+    connect(m_resourceEditor->commandHistory(), SIGNAL(indexChanged(int)),
+            this, SLOT(setShouldAutoSave()));
     connect(m_resourceFile, SIGNAL(changed()), this, SIGNAL(changed()));
     if (debugResourceEditorW)
         qDebug() <<  "ResourceEditorW::ResourceEditorW()";
@@ -105,12 +109,13 @@ bool ResourceEditorW::createNew(const QString &contents)
 
     const bool rc = m_resourceEditor->load(saver.fileName());
     m_resourceEditor->setFileName(QString());
+    m_shouldAutoSave = false;
     if (debugResourceEditorW)
         qDebug() <<  "ResourceEditorW::createNew: " << contents << " (" << saver.fileName() << ") returns " << rc;
     return rc;
 }
 
-bool ResourceEditorW::open(QString *errorString, const QString &fileName /* = QString() */)
+bool ResourceEditorW::open(QString *errorString, const QString &fileName, const QString &realFileName)
 {
     if (debugResourceEditorW)
         qDebug() <<  "ResourceEditorW::open: " << fileName;
@@ -122,20 +127,24 @@ bool ResourceEditorW::open(QString *errorString, const QString &fileName /* = QS
 
     const QFileInfo fi(fileName);
 
-    const QString absFileName = fi.absoluteFilePath();
-
-    if (!m_resourceEditor->load(absFileName)) {
+    m_diskIo = true;
+    if (!m_resourceEditor->load(realFileName)) {
         *errorString = m_resourceEditor->errorMessage();
+        m_diskIo = false;
         return false;
     }
 
+    m_resourceEditor->setFileName(fileName);
+    m_resourceEditor->setDirty(fileName != realFileName);
     setDisplayName(fi.fileName());
+    m_shouldAutoSave = false;
+    m_diskIo = false;
 
     emit changed();
     return true;
 }
 
-bool ResourceEditorFile::save(QString *errorString, const QString &name /* = QString() */)
+bool ResourceEditorFile::save(QString *errorString, const QString &name, bool autoSave)
 {
     if (debugResourceEditorW)
         qDebug(">ResourceEditorW::save: %s", qPrintable(name));
@@ -145,15 +154,25 @@ bool ResourceEditorFile::save(QString *errorString, const QString &name /* = QSt
     if (actualName.isEmpty())
         return false;
 
+    m_parent->m_diskIo = true;
     m_parent->m_resourceEditor->setFileName(actualName);
     if (!m_parent->m_resourceEditor->save()) {
         *errorString = m_parent->m_resourceEditor->errorMessage();
         m_parent->m_resourceEditor->setFileName(oldFileName);
+        m_parent->m_diskIo = false;
         return false;
     }
 
-    m_parent->m_resourceEditor->setDirty(false);
+    m_parent->m_shouldAutoSave = false;
+    if (autoSave) {
+        m_parent->m_resourceEditor->setFileName(oldFileName);
+        m_parent->m_resourceEditor->setDirty(true);
+        m_parent->m_diskIo = false;
+        return true;
+    }
+
     m_parent->setDisplayName(QFileInfo(actualName).fileName());
+    m_parent->m_diskIo = false;
 
     emit changed();
     return true;
@@ -174,6 +193,11 @@ QString ResourceEditorFile::fileName() const
     return m_parent->m_resourceEditor->fileName();
 }
 
+bool ResourceEditorFile::shouldAutoSave() const
+{
+    return m_parent->m_shouldAutoSave;
+}
+
 bool ResourceEditorFile::isModified() const
 {
     return m_parent->m_resourceEditor->isDirty();
@@ -201,7 +225,8 @@ bool ResourceEditorFile::reload(QString *errorString, ReloadFlag flag, ChangeTyp
         emit changed();
     } else {
         emit aboutToReload();
-        if (!m_parent->open(errorString, m_parent->m_resourceEditor->fileName()))
+        QString fn = m_parent->m_resourceEditor->fileName();
+        if (!m_parent->open(errorString, fn, fn))
             return false;
         emit reloaded();
     }
@@ -225,10 +250,12 @@ QString ResourceEditorFile::suggestedFileName() const
 
 void ResourceEditorW::dirtyChanged(bool dirty)
 {
+    if (m_diskIo)
+        return; // We emit changed() afterwards, unless it was an autosave
+
     if (debugResourceEditorW)
         qDebug() << " ResourceEditorW::dirtyChanged" <<  dirty;
-    if (dirty)
-        emit changed();
+    emit changed();
 }
 
 void ResourceEditorW::onUndoStackChanged(bool canUndo, bool canRedo)
index a5e50d9..25c3bd7 100644 (file)
@@ -57,8 +57,9 @@ public:
     ResourceEditorFile(ResourceEditorW *parent = 0);
 
     //IFile
-    bool save(QString *errorString, const QString &fileName = QString());
+    bool save(QString *errorString, const QString &fileName, bool autoSave);
     QString fileName() const;
+    bool shouldAutoSave() const;
     bool isModified() const;
     bool isReadOnly() const;
     bool isSaveAsAllowed() const;
@@ -85,7 +86,7 @@ public:
 
     // IEditor
     bool createNew(const QString &contents);
-    bool open(QString *errorString, const QString &fileName = QString());
+    bool open(QString *errorString, const QString &fileName, const QString &realFileName);
     bool duplicateSupported() const { return false; }
     Core::IEditor *duplicate(QWidget *) { return 0; }
     Core::IFile *file() { return m_resourceFile; }
@@ -102,6 +103,7 @@ public:
 private slots:
     void dirtyChanged(bool);
     void onUndoStackChanged(bool canUndo, bool canRedo);
+    void setShouldAutoSave(bool sad = true) { m_shouldAutoSave = sad; }
 
 private:
     const QString m_extension;
@@ -111,6 +113,8 @@ private:
     QPointer<SharedTools::QrcEditor> m_resourceEditor;
     ResourceEditorFile *m_resourceFile;
     ResourceEditorPlugin *m_plugin;
+    bool m_shouldAutoSave;
+    bool m_diskIo;
 
 public:
     void onUndo();
index 3c3001c..ab56d84 100644 (file)
@@ -48,10 +48,11 @@ TaskFile::TaskFile(QObject *parent) : Core::IFile(parent),
 TaskFile::~TaskFile()
 { }
 
-bool TaskFile::save(QString *errorString, const QString &fileName)
+bool TaskFile::save(QString *errorString, const QString &fileName, bool autoSave)
 {
     Q_UNUSED(errorString)
     Q_UNUSED(fileName);
+    Q_UNUSED(autoSave)
     return false;
 }
 
index 71e09dd..210360a 100644 (file)
@@ -48,7 +48,7 @@ public:
     TaskFile(QObject *parent);
     ~TaskFile();
 
-    bool save(QString *errorString, const QString &fileName = QString());
+    bool save(QString *errorString, const QString &fileName, bool autoSave);
     QString fileName() const;
 
     QString defaultPath() const;
index b7c2e70..7c5b599 100644 (file)
@@ -230,6 +230,8 @@ public:
     bool m_hasDecodingError;
     QByteArray m_decodingErrorSample;
     static const int kChunkSize;
+
+    int m_autoSaveRevision;
 };
 
 const int BaseTextDocumentPrivate::kChunkSize = 65536;
@@ -242,7 +244,8 @@ BaseTextDocumentPrivate::BaseTextDocumentPrivate(BaseTextDocument *q) :
     m_codec(Core::EditorManager::instance()->defaultTextCodec()),
     m_fileHasUtf8Bom(false),
     m_fileIsReadOnly(false),
-    m_hasDecodingError(false)
+    m_hasDecodingError(false),
+    m_autoSaveRevision(-1)
 {
 }
 
@@ -363,7 +366,7 @@ ITextMarkable *BaseTextDocument::documentMarker() const
     return d->m_documentMarker;
 }
 
-bool BaseTextDocument::save(QString *errorString, const QString &fileName)
+bool BaseTextDocument::save(QString *errorString, const QString &fileName, bool autoSave)
 {
     QTextCursor cursor(d->m_document);
 
@@ -405,6 +408,9 @@ bool BaseTextDocument::save(QString *errorString, const QString &fileName)
     }
     if (!saver.finalize(errorString))
         return false;
+    d->m_autoSaveRevision = d->m_document->revision();
+    if (autoSave)
+        return true;
 
     const QFileInfo fi(fName);
     d->m_fileName = QDir::cleanPath(fi.absoluteFilePath());
@@ -419,6 +425,11 @@ bool BaseTextDocument::save(QString *errorString, const QString &fileName)
     return true;
 }
 
+bool BaseTextDocument::shouldAutoSave() const
+{
+    return d->m_autoSaveRevision != d->m_document->revision();
+}
+
 void BaseTextDocument::rename(const QString &newName)
 {
     const QFileInfo fi(newName);
@@ -454,7 +465,7 @@ void BaseTextDocument::checkPermissions()
         emit changed();
 }
 
-bool BaseTextDocument::open(QString *errorString, const QString &fileName)
+bool BaseTextDocument::open(QString *errorString, const QString &fileName, const QString &realFileName)
 {
     QString title = tr("untitled");
     if (!fileName.isEmpty()) {
@@ -467,7 +478,7 @@ bool BaseTextDocument::open(QString *errorString, const QString &fileName)
         QByteArray buf;
         try {
             Utils::FileReader reader;
-            if (!reader.fetch(fileName, errorString))
+            if (!reader.fetch(realFileName, errorString))
                 return false;
             buf = reader.data();
         } catch (std::bad_alloc) {
@@ -583,8 +594,8 @@ bool BaseTextDocument::open(QString *errorString, const QString &fileName)
         BaseTextDocumentLayout *documentLayout =
             qobject_cast<BaseTextDocumentLayout*>(d->m_document->documentLayout());
         QTC_ASSERT(documentLayout, return true);
-        documentLayout->lastSaveRevision = d->m_document->revision();
-        d->m_document->setModified(false);
+        documentLayout->lastSaveRevision = d->m_autoSaveRevision = d->m_document->revision();
+        d->m_document->setModified(fileName != realFileName);
         emit titleChanged(title);
         emit changed();
     }
@@ -603,7 +614,7 @@ bool BaseTextDocument::reload(QString *errorString)
     emit aboutToReload();
     documentClosing(); // removes text marks non-permanently
 
-    if (!open(errorString, d->m_fileName))
+    if (!open(errorString, d->m_fileName, d->m_fileName))
         return false;
     emit reloaded();
     return true;
index 9404871..481baae 100644 (file)
@@ -70,8 +70,9 @@ public:
     ITextMarkable *documentMarker() const;
 
     // IFile implementation.
-    virtual bool save(QString *errorString, const QString &fileName = QString());
+    virtual bool save(QString *errorString, const QString &fileName, bool autoSave);
     virtual QString fileName() const;
+    virtual bool shouldAutoSave() const;
     virtual bool isReadOnly() const;
     virtual bool isModified() const;
     virtual bool isSaveAsAllowed() const;
@@ -87,7 +88,7 @@ public:
     void setDefaultPath(const QString &defaultPath);
     void setSuggestedFileName(const QString &suggestedFileName);
 
-    virtual bool open(QString *errorString, const QString &fileName = QString());
+    virtual bool open(QString *errorString, const QString &fileName, const QString &realFileName);
     virtual bool reload(QString *errorString);
 
     QTextDocument *document() const;
index d89c7ce..f4dc040 100644 (file)
@@ -555,9 +555,9 @@ void BaseTextEditorWidget::updateCannotDecodeInfo()
     }
 }
 
-bool BaseTextEditorWidget::open(QString *errorString, const QString &fileName)
+bool BaseTextEditorWidget::open(QString *errorString, const QString &fileName, const QString &realFileName)
 {
-    if (d->m_document->open(errorString, fileName)) {
+    if (d->m_document->open(errorString, fileName, realFileName)) {
         moveCursor(QTextCursor::Start);
         updateCannotDecodeInfo();
         return true;
index 9c49764..083cbce 100644 (file)
@@ -138,7 +138,7 @@ public:
     // EditorInterface
     Core::IFile * file();
     bool createNew(const QString &contents);
-    virtual bool open(QString *errorString, const QString &fileName = QString());
+    virtual bool open(QString *errorString, const QString &fileName, const QString &realFileName);
     QByteArray saveState() const;
     bool restoreState(const QByteArray &state);
     QString displayName() const;
@@ -560,7 +560,7 @@ public:
     //QWidget *widget() { return e; }
     Core::IFile * file() { return e->file(); }
     bool createNew(const QString &contents) { return e->createNew(contents); }
-    bool open(QString *errorString, const QString &fileName = QString()) { return e->open(errorString, fileName); }
+    bool open(QString *errorString, const QString &fileName, const QString &realFileName) { return e->open(errorString, fileName, realFileName); }
     QString displayName() const { return e->displayName(); }
     void setDisplayName(const QString &title) { e->setDisplayName(title); emit changed(); }
 
index f8cb41c..1a99a6e 100644 (file)
@@ -69,9 +69,9 @@ void SubmitEditorFile::setModified(bool modified)
     emit changed();
 }
 
-bool SubmitEditorFile::save(QString *errorString, const QString &fileName)
+bool SubmitEditorFile::save(QString *errorString, const QString &fileName, bool autoSave)
 {
-    emit saveMe(errorString, fileName);
+    emit saveMe(errorString, fileName, autoSave);
     if (!errorString->isEmpty())
         return false;
     emit changed();
index d219a9f..4e879cd 100644 (file)
@@ -53,7 +53,7 @@ public:
     virtual QString mimeType() const;
     bool isReadOnly() const { return false; }
     bool isSaveAsAllowed() const { return false; }
-    bool save(QString *errorString, const QString &fileName);
+    bool save(QString *errorString, const QString &fileName, bool autoSave);
     ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const;
     bool reload(QString *errorString, ReloadFlag flag, ChangeType type);
     void rename(const QString &newName);
@@ -62,7 +62,7 @@ public:
     void setModified(bool modified = true);
 
 signals:
-    void saveMe(QString *errorString, const QString &fileName);
+    void saveMe(QString *errorString, const QString &fileName, bool autoSave);
 
 private:
     const QString m_mimeType;
index dae9271..86c5dd1 100644 (file)
@@ -165,7 +165,8 @@ VCSBaseSubmitEditor::VCSBaseSubmitEditor(const VCSBaseSubmitEditorParameters *pa
 
     m_d->m_file->setModified(false);
     // We are always clean to prevent the editor manager from asking to save.
-    connect(m_d->m_file, SIGNAL(saveMe(QString*, QString)), this, SLOT(save(QString*, QString)));
+    connect(m_d->m_file, SIGNAL(saveMe(QString*, QString, bool)),
+            this, SLOT(save(QString*, QString, bool)));
 
     connect(m_d->m_widget, SIGNAL(diffSelected(QStringList)), this, SLOT(slotDiffSelectedVCSFiles(QStringList)));
     connect(m_d->m_widget->descriptionEdit(), SIGNAL(textChanged()), this, SLOT(slotDescriptionChanged()));
@@ -328,13 +329,13 @@ bool VCSBaseSubmitEditor::createNew(const QString &contents)
     return true;
 }
 
-bool VCSBaseSubmitEditor::open(QString *errorString, const QString &fileName)
+bool VCSBaseSubmitEditor::open(QString *errorString, const QString &fileName, const QString &realFileName)
 {
     if (fileName.isEmpty())
         return false;
 
     Utils::FileReader reader;
-    if (!reader.fetch(fileName, QIODevice::Text, errorString))
+    if (!reader.fetch(realFileName, QIODevice::Text, errorString))
         return false;
 
     const QString text = QString::fromLocal8Bit(reader.data());
@@ -342,6 +343,7 @@ bool VCSBaseSubmitEditor::open(QString *errorString, const QString &fileName)
         return false;
 
     m_d->m_file->setFileName(QFileInfo(fileName).absoluteFilePath());
+    m_d->m_file->setModified(fileName != realFileName);
     return true;
 }
 
@@ -450,13 +452,15 @@ void VCSBaseSubmitEditor::slotDiffSelectedVCSFiles(const QStringList &rawList)
      emit diffSelectedFiles(rawList);
 }
 
-bool VCSBaseSubmitEditor::save(QString *errorString, const QString &fileName)
+bool VCSBaseSubmitEditor::save(QString *errorString, const QString &fileName, bool autoSave)
 {
     const QString fName = fileName.isEmpty() ? m_d->m_file->fileName() : fileName;
     Utils::FileSaver saver(fName, QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text);
     saver.write(fileContents().toLocal8Bit());
     if (!saver.finalize(errorString))
         return false;
+    if (autoSave)
+        return true;
     const QFileInfo fi(fName);
     m_d->m_file->setFileName(fi.absoluteFilePath());
     m_d->m_file->setModified(false);
index b48b3c5..c73b087 100644 (file)
@@ -119,7 +119,7 @@ public:
 
     // Core::IEditor
     virtual bool createNew(const QString &contents);
-    virtual bool open(QString *errorString, const QString &fileName);
+    virtual bool open(QString *errorString, const QString &fileName, const QString &realFileName);
     virtual Core::IFile *file();
     virtual QString displayName() const;
     virtual void setDisplayName(const QString &title);
@@ -159,7 +159,7 @@ signals:
 
 private slots:
     void slotDiffSelectedVCSFiles(const QStringList &rawList);
-    bool save(QString *errorString, const QString &fileName);
+    bool save(QString *errorString, const QString &fileName, bool autoSave);
     void slotDescriptionChanged();
     void slotCheckSubmitMessage();
     void slotInsertNickName();
index 38f71d2..ddd53f8 100644 (file)
@@ -67,6 +67,8 @@ public:
     void addFile(const QString &prefix, const QString &file);
 //    void removeFile(const QString &prefix, const QString &file);
 
+    const QUndoStack *commandHistory() const { return &m_history; }
+
 signals:
     void dirtyChanged(bool dirty);
     void addFilesTriggered(const QString &prefix);