diff --git a/src/libs/utils/reloadpromptutils.cpp b/src/libs/utils/reloadpromptutils.cpp
index 8eec9e92e1b..798a4876a70 100644
--- a/src/libs/utils/reloadpromptutils.cpp
+++ b/src/libs/utils/reloadpromptutils.cpp
@@ -35,6 +35,7 @@ namespace Utils {
QTCREATOR_UTILS_EXPORT ReloadPromptAnswer reloadPrompt(const FileName &fileName,
bool modified,
+ bool enableDiffOption,
QWidget *parent)
{
@@ -50,12 +51,13 @@ QTCREATOR_UTILS_EXPORT ReloadPromptAnswer reloadPrompt(const FileName &fileName,
"The file %1 has changed outside Qt Creator. Do you want to reload it?");
}
msg = msg.arg(fileName.fileName());
- return reloadPrompt(title, msg, fileName.toUserOutput(), parent);
+ return reloadPrompt(title, msg, fileName.toUserOutput(), enableDiffOption, parent);
}
QTCREATOR_UTILS_EXPORT ReloadPromptAnswer reloadPrompt(const QString &title,
const QString &prompt,
const QString &details,
+ bool enableDiffOption,
QWidget *parent)
{
QMessageBox msg(parent);
@@ -69,7 +71,19 @@ QTCREATOR_UTILS_EXPORT ReloadPromptAnswer reloadPrompt(const QString &title,
msg.button(QMessageBox::Close)->setText(QCoreApplication::translate("Utils::reloadPrompt",
"&Close"));
- switch (msg.exec()) {
+ QPushButton *diffButton = nullptr;
+ if (enableDiffOption) {
+ diffButton = msg.addButton(QCoreApplication::translate(
+ "Utils::reloadPrompt", "No to All && &Diff"),
+ QMessageBox::NoRole);
+ }
+
+ const int result = msg.exec();
+
+ if (msg.clickedButton() == diffButton)
+ return ReloadNoneAndDiff;
+
+ switch (result) {
case QMessageBox::Yes:
return ReloadCurrent;
case QMessageBox::YesToAll:
diff --git a/src/libs/utils/reloadpromptutils.h b/src/libs/utils/reloadpromptutils.h
index b01bd25b53b..8991d52b59b 100644
--- a/src/libs/utils/reloadpromptutils.h
+++ b/src/libs/utils/reloadpromptutils.h
@@ -40,15 +40,19 @@ enum ReloadPromptAnswer {
ReloadAll,
ReloadSkipCurrent,
ReloadNone,
+ ReloadNoneAndDiff,
CloseCurrent
};
QTCREATOR_UTILS_EXPORT ReloadPromptAnswer reloadPrompt(const FileName &fileName,
bool modified,
+ bool enableDiffOption,
QWidget *parent);
QTCREATOR_UTILS_EXPORT ReloadPromptAnswer reloadPrompt(const QString &title,
const QString &prompt,
- const QString &details, QWidget *parent);
+ const QString &details,
+ bool enableDiffOption,
+ QWidget *parent);
enum FileDeletedPromptAnswer {
FileDeletedClose,
diff --git a/src/plugins/coreplugin/coreplugin.pro b/src/plugins/coreplugin/coreplugin.pro
index 9c8be5cfa76..6de7837acfc 100644
--- a/src/plugins/coreplugin/coreplugin.pro
+++ b/src/plugins/coreplugin/coreplugin.pro
@@ -218,7 +218,8 @@ HEADERS += corejsextensions.h \
iwelcomepage.h \
systemsettings.h \
coreicons.h \
- editormanager/documentmodel_p.h
+ editormanager/documentmodel_p.h \
+ diffservice.h
FORMS += dialogs/newdialog.ui \
dialogs/saveitemsdialog.ui \
diff --git a/src/plugins/coreplugin/coreplugin.qbs b/src/plugins/coreplugin/coreplugin.qbs
index ed50f54985d..fe6b3cb75e9 100644
--- a/src/plugins/coreplugin/coreplugin.qbs
+++ b/src/plugins/coreplugin/coreplugin.qbs
@@ -41,6 +41,7 @@ Project {
"corejsextensions.cpp", "corejsextensions.h",
"coreplugin.cpp", "coreplugin.h",
"designmode.cpp", "designmode.h",
+ "diffservice.h",
"documentmanager.cpp", "documentmanager.h",
"editmode.cpp", "editmode.h",
"editortoolbar.cpp", "editortoolbar.h",
diff --git a/src/plugins/coreplugin/dialogs/saveitemsdialog.cpp b/src/plugins/coreplugin/dialogs/saveitemsdialog.cpp
index 885b08e9346..a36ecd9d485 100644
--- a/src/plugins/coreplugin/dialogs/saveitemsdialog.cpp
+++ b/src/plugins/coreplugin/dialogs/saveitemsdialog.cpp
@@ -25,12 +25,15 @@
#include "saveitemsdialog.h"
+#include
#include
#include
#include
#include
+#include
+
#include
#include
#include
@@ -51,6 +54,12 @@ SaveItemsDialog::SaveItemsDialog(QWidget *parent,
// QDialogButtonBox's behavior for "destructive" is wrong, the "do not save" should be left-aligned
const QDialogButtonBox::ButtonRole discardButtonRole = Utils::HostOsInfo::isMacHost()
? QDialogButtonBox::ResetRole : QDialogButtonBox::DestructiveRole;
+
+ if (ExtensionSystem::PluginManager::getObject()) {
+ m_diffButton = m_ui.buttonBox->addButton(tr("&Diff"), discardButtonRole);
+ connect(m_diffButton, &QAbstractButton::clicked, this, &SaveItemsDialog::collectFilesToDiff);
+ }
+
QPushButton *discardButton = m_ui.buttonBox->addButton(tr("Do not Save"), discardButtonRole);
m_ui.buttonBox->button(QDialogButtonBox::Save)->setDefault(true);
m_ui.treeWidget->setFocus();
@@ -80,13 +89,13 @@ SaveItemsDialog::SaveItemsDialog(QWidget *parent,
if (Utils::HostOsInfo::isMacHost())
m_ui.treeWidget->setAlternatingRowColors(true);
adjustButtonWidths();
- updateSaveButton();
+ updateButtons();
connect(m_ui.buttonBox->button(QDialogButtonBox::Save), &QAbstractButton::clicked,
this, &SaveItemsDialog::collectItemsToSave);
connect(discardButton, &QAbstractButton::clicked, this, &SaveItemsDialog::discardAll);
connect(m_ui.treeWidget, &QTreeWidget::itemSelectionChanged,
- this, &SaveItemsDialog::updateSaveButton);
+ this, &SaveItemsDialog::updateButtons);
}
void SaveItemsDialog::setMessage(const QString &msg)
@@ -94,19 +103,27 @@ void SaveItemsDialog::setMessage(const QString &msg)
m_ui.msgLabel->setText(msg);
}
-void SaveItemsDialog::updateSaveButton()
+void SaveItemsDialog::updateButtons()
{
int count = m_ui.treeWidget->selectedItems().count();
- QPushButton *button = m_ui.buttonBox->button(QDialogButtonBox::Save);
+ QPushButton *saveButton = m_ui.buttonBox->button(QDialogButtonBox::Save);
+ bool buttonsEnabled = true;
+ QString saveText = tr("Save");
+ QString diffText = tr("&Diff && Cancel");
if (count == m_ui.treeWidget->topLevelItemCount()) {
- button->setEnabled(true);
- button->setText(tr("Save All"));
+ saveText = tr("Save All");
+ diffText = tr("&Diff All && Cancel");
} else if (count == 0) {
- button->setEnabled(false);
- button->setText(tr("Save"));
+ buttonsEnabled = false;
} else {
- button->setEnabled(true);
- button->setText(tr("Save Selected"));
+ saveText = tr("Save Selected");
+ diffText = tr("&Diff Selected && Cancel");
+ }
+ saveButton->setEnabled(buttonsEnabled);
+ saveButton->setText(saveText);
+ if (m_diffButton) {
+ m_diffButton->setEnabled(buttonsEnabled);
+ m_diffButton->setText(diffText);
}
}
@@ -145,6 +162,16 @@ void SaveItemsDialog::collectItemsToSave()
accept();
}
+void SaveItemsDialog::collectFilesToDiff()
+{
+ m_filesToDiff.clear();
+ foreach (QTreeWidgetItem *item, m_ui.treeWidget->selectedItems()) {
+ if (IDocument *doc = item->data(0, Qt::UserRole).value())
+ m_filesToDiff.append(doc->filePath().toString());
+ }
+ reject();
+}
+
void SaveItemsDialog::discardAll()
{
m_ui.treeWidget->clearSelection();
@@ -156,6 +183,11 @@ QList SaveItemsDialog::itemsToSave() const
return m_itemsToSave;
}
+QStringList SaveItemsDialog::filesToDiff() const
+{
+ return m_filesToDiff;
+}
+
void SaveItemsDialog::setAlwaysSaveMessage(const QString &msg)
{
m_ui.saveBeforeBuildCheckBox->setText(msg);
diff --git a/src/plugins/coreplugin/dialogs/saveitemsdialog.h b/src/plugins/coreplugin/dialogs/saveitemsdialog.h
index 623cb2e85f7..1048ca03481 100644
--- a/src/plugins/coreplugin/dialogs/saveitemsdialog.h
+++ b/src/plugins/coreplugin/dialogs/saveitemsdialog.h
@@ -54,15 +54,19 @@ public:
void setAlwaysSaveMessage(const QString &msg);
bool alwaysSaveChecked();
QList itemsToSave() const;
+ QStringList filesToDiff() const;
private:
void collectItemsToSave();
+ void collectFilesToDiff();
void discardAll();
- void updateSaveButton();
+ void updateButtons();
void adjustButtonWidths();
Ui::SaveItemsDialog m_ui;
QList m_itemsToSave;
+ QStringList m_filesToDiff;
+ QPushButton *m_diffButton = nullptr;
};
} // namespace Internal
diff --git a/src/plugins/coreplugin/diffservice.h b/src/plugins/coreplugin/diffservice.h
new file mode 100644
index 00000000000..3b282170ddc
--- /dev/null
+++ b/src/plugins/coreplugin/diffservice.h
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "core_global.h"
+#include
+
+QT_FORWARD_DECLARE_CLASS(QStringList)
+
+namespace Core {
+
+class CORE_EXPORT DiffService
+{
+public:
+ virtual ~DiffService() {}
+
+ virtual void diffModifiedFiles(const QStringList &fileNames) = 0;
+};
+
+} // namespace Core
+
+QT_BEGIN_NAMESPACE
+Q_DECLARE_INTERFACE(Core::DiffService, "Core::DiffService")
+QT_END_NAMESPACE
diff --git a/src/plugins/coreplugin/documentmanager.cpp b/src/plugins/coreplugin/documentmanager.cpp
index 6ba6d61ca24..5a936731fa0 100644
--- a/src/plugins/coreplugin/documentmanager.cpp
+++ b/src/plugins/coreplugin/documentmanager.cpp
@@ -29,6 +29,7 @@
#include "idocument.h"
#include "coreconstants.h"
+#include
#include
#include
#include
@@ -38,6 +39,8 @@
#include
#include
+#include
+
#include
#include
#include
@@ -606,6 +609,11 @@ static bool saveModifiedFilesHelper(const QList &documents,
(*alwaysSave) = dia.alwaysSaveChecked();
if (failedToSave)
(*failedToSave) = modifiedDocuments;
+ const QStringList filesToDiff = dia.filesToDiff();
+ if (!filesToDiff.isEmpty()) {
+ if (auto diffService = ExtensionSystem::PluginManager::getObject())
+ diffService->diffModifiedFiles(filesToDiff);
+ }
return false;
}
if (alwaysSave)
@@ -978,6 +986,7 @@ void DocumentManager::checkForReload()
// handle the IDocuments
QStringList errorStrings;
+ QStringList filesToDiff;
foreach (IDocument *document, changedIDocuments) {
IDocument::ChangeTrigger trigger = IDocument::TriggerInternal;
IDocument::ChangeType type = IDocument::TypePermissions;
@@ -1067,7 +1076,7 @@ void DocumentManager::checkForReload()
// IDocument wants us to ask
} else if (type == IDocument::TypeContents) {
// content change, IDocument wants to ask user
- if (previousReloadAnswer == ReloadNone) {
+ if (previousReloadAnswer == ReloadNone || previousReloadAnswer == ReloadNoneAndDiff) {
// answer already given, ignore
success = document->reload(&errorString, IDocument::FlagIgnore, IDocument::TypeContents);
} else if (previousReloadAnswer == ReloadAll) {
@@ -1076,7 +1085,8 @@ void DocumentManager::checkForReload()
} else {
// Ask about content change
previousReloadAnswer = reloadPrompt(document->filePath(), document->isModified(),
- ICore::dialogParent());
+ ExtensionSystem::PluginManager::getObject(),
+ ICore::dialogParent());
switch (previousReloadAnswer) {
case ReloadAll:
case ReloadCurrent:
@@ -1084,6 +1094,7 @@ void DocumentManager::checkForReload()
break;
case ReloadSkipCurrent:
case ReloadNone:
+ case ReloadNoneAndDiff:
success = document->reload(&errorString, IDocument::FlagIgnore, IDocument::TypeContents);
break;
case CloseCurrent:
@@ -1091,6 +1102,9 @@ void DocumentManager::checkForReload()
break;
}
}
+ if (previousReloadAnswer == ReloadNoneAndDiff)
+ filesToDiff.append(document->filePath().toString());
+
// IDocument wants us to ask, and it's the TypeRemoved case
} else {
// Ask about removed file
@@ -1134,6 +1148,12 @@ void DocumentManager::checkForReload()
d->m_blockedIDocument = 0;
}
+
+ if (!filesToDiff.isEmpty()) {
+ if (auto diffService = ExtensionSystem::PluginManager::getObject())
+ diffService->diffModifiedFiles(filesToDiff);
+ }
+
if (!errorStrings.isEmpty())
QMessageBox::critical(ICore::dialogParent(), tr("File Error"),
errorStrings.join(QLatin1Char('\n')));
diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp
index 7f344ecd95f..4f13bcec2b3 100644
--- a/src/plugins/coreplugin/editormanager/editormanager.cpp
+++ b/src/plugins/coreplugin/editormanager/editormanager.cpp
@@ -39,6 +39,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -2168,11 +2169,21 @@ void EditorManagerPrivate::revertToSaved(IDocument *document)
QMessageBox::Yes|QMessageBox::No, ICore::mainWindow());
msgBox.button(QMessageBox::Yes)->setText(tr("Proceed"));
msgBox.button(QMessageBox::No)->setText(tr("Cancel"));
+
+ QPushButton *diffButton = nullptr;
+ auto diffService = ExtensionSystem::PluginManager::getObject();
+ if (diffService)
+ diffButton = msgBox.addButton(tr("Cancel && &Diff"), QMessageBox::RejectRole);
+
msgBox.setDefaultButton(QMessageBox::No);
msgBox.setEscapeButton(QMessageBox::No);
if (msgBox.exec() == QMessageBox::No)
return;
+ if (diffService && msgBox.clickedButton() == diffButton) {
+ diffService->diffModifiedFiles(QStringList() << fileName);
+ return;
+ }
}
QString errorString;
if (!document->reload(&errorString, IDocument::FlagReload, IDocument::TypeContents))
diff --git a/src/plugins/diffeditor/diffeditorplugin.cpp b/src/plugins/diffeditor/diffeditorplugin.cpp
index db7936f34af..a04b4b2b862 100644
--- a/src/plugins/diffeditor/diffeditorplugin.cpp
+++ b/src/plugins/diffeditor/diffeditorplugin.cpp
@@ -211,6 +211,66 @@ void DiffAllModifiedFilesController::reload()
/////////////////
+class DiffModifiedFilesController : public DiffFilesController
+{
+ Q_OBJECT
+public:
+ DiffModifiedFilesController(Core::IDocument *document, const QStringList &fileNames);
+
+protected:
+ void reload();
+
+private:
+ QStringList m_fileNames;
+};
+
+DiffModifiedFilesController::DiffModifiedFilesController(Core::IDocument *document, const QStringList &fileNames) :
+ DiffFilesController(document), m_fileNames(fileNames)
+{ }
+
+void DiffModifiedFilesController::reload()
+{
+ QList fileDataList;
+
+ foreach (const QString fileName, m_fileNames) {
+ TextEditor::TextDocument *textDocument = qobject_cast(
+ Core::DocumentModel::documentForFilePath(fileName));
+
+ if (textDocument && textDocument->isModified()) {
+ QString errorString;
+ Utils::TextFileFormat format = textDocument->format();
+
+ QString leftText;
+ bool leftFileExists = true;
+ const QString fileName = textDocument->filePath().toString();
+ if (Utils::TextFileFormat::readFile(fileName,
+ format.codec,
+ &leftText, &format, &errorString)
+ != Utils::TextFileFormat::ReadSuccess) {
+ leftFileExists = false;
+ }
+
+ const QString rightText = textDocument->plainText();
+
+ FileData fileData = diffFiles(leftText, rightText);
+ fileData.leftFileInfo.fileName = fileName;
+ fileData.rightFileInfo.fileName = fileName;
+ fileData.leftFileInfo.typeInfo = tr("Saved");
+ fileData.rightFileInfo.typeInfo = tr("Modified");
+
+ if (!leftFileExists)
+ fileData.fileOperation = FileData::NewFile;
+
+ fileDataList << fileData;
+ }
+ }
+
+ setDiffFiles(fileDataList);
+ reloadFinished(true);
+}
+
+/////////////////
+
class DiffExternalFilesController : public DiffFilesController
{
Q_OBJECT
@@ -273,6 +333,26 @@ void DiffExternalFilesController::reload()
/////////////////
+DiffEditorServiceImpl::DiffEditorServiceImpl(QObject *parent) :
+ QObject(parent)
+{
+}
+
+void DiffEditorServiceImpl::diffModifiedFiles(const QStringList &fileNames)
+{
+ const QString documentId = QLatin1String("Diff Modified Files");
+ const QString title = tr("Diff Modified Files");
+ auto const document = qobject_cast(
+ DiffEditorController::findOrCreateDocument(documentId, title));
+ if (!document)
+ return;
+
+ if (!DiffEditorController::controller(document))
+ new DiffModifiedFilesController(document, fileNames);
+ Core::EditorManager::activateEditorForDocument(document);
+ document->reload();
+}
+
bool DiffEditorPlugin::initialize(const QStringList &arguments, QString *errorMessage)
{
Q_UNUSED(arguments)
@@ -309,6 +389,7 @@ bool DiffEditorPlugin::initialize(const QStringList &arguments, QString *errorMe
updateActions();
addAutoReleasedObject(new DiffEditorFactory(this));
+ addAutoReleasedObject(new DiffEditorServiceImpl(this));
return true;
}
diff --git a/src/plugins/diffeditor/diffeditorplugin.h b/src/plugins/diffeditor/diffeditorplugin.h
index ba0cab24337..66485660024 100644
--- a/src/plugins/diffeditor/diffeditorplugin.h
+++ b/src/plugins/diffeditor/diffeditorplugin.h
@@ -27,6 +27,7 @@
#include "diffeditor_global.h"
+#include
#include
#include
@@ -37,6 +38,16 @@ namespace Core { class IEditor; }
namespace DiffEditor {
namespace Internal {
+class DiffEditorServiceImpl : public QObject, public Core::DiffService
+{
+ Q_OBJECT
+ Q_INTERFACES(Core::DiffService)
+public:
+ explicit DiffEditorServiceImpl(QObject *parent = nullptr);
+
+ void diffModifiedFiles(const QStringList &fileNames) override;
+};
+
class DiffEditorPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT