diff options
-rw-r--r-- | src/plugins/perforce/perforceeditor.cpp | 2 | ||||
-rw-r--r-- | src/plugins/perforce/perforceplugin.cpp | 346 | ||||
-rw-r--r-- | src/plugins/perforce/perforceplugin.h | 234 | ||||
-rw-r--r-- | src/plugins/perforce/settingspage.cpp | 28 | ||||
-rw-r--r-- | src/plugins/perforce/settingspage.h | 4 |
5 files changed, 287 insertions, 327 deletions
diff --git a/src/plugins/perforce/perforceeditor.cpp b/src/plugins/perforce/perforceeditor.cpp index 3494c30a1ab..e686d4e427b 100644 --- a/src/plugins/perforce/perforceeditor.cpp +++ b/src/plugins/perforce/perforceeditor.cpp @@ -106,7 +106,7 @@ VcsBase::BaseAnnotationHighlighter *PerforceEditorWidget::createAnnotationHighli QString PerforceEditorWidget::findDiffFile(const QString &f) const { QString errorMessage; - const QString fileName = PerforcePluginPrivate::fileNameFromPerforceName(f.trimmed(), false, &errorMessage); + const QString fileName = PerforcePlugin::fileNameFromPerforceName(f.trimmed(), false, &errorMessage); if (fileName.isEmpty()) qWarning("%s", qPrintable(errorMessage)); return fileName; diff --git a/src/plugins/perforce/perforceplugin.cpp b/src/plugins/perforce/perforceplugin.cpp index da4dfdda9aa..0f42638e6ae 100644 --- a/src/plugins/perforce/perforceplugin.cpp +++ b/src/plugins/perforce/perforceplugin.cpp @@ -27,11 +27,11 @@ #include "changenumberdialog.h" #include "pendingchangesdialog.h" +#include "perforcechecker.h" #include "perforceeditor.h" +#include "perforcesettings.h" #include "perforcesubmiteditor.h" -#include "perforcechecker.h" #include "settingspage.h" -#include "perforcesettings.h" #include <coreplugin/actionmanager/actionmanager.h> #include <coreplugin/actionmanager/actioncontainer.h> @@ -52,9 +52,11 @@ #include <vcsbase/basevcseditorfactory.h> #include <vcsbase/basevcssubmiteditorfactory.h> +#include <vcsbase/vcsbaseconstants.h> +#include <vcsbase/vcsbaseeditorconfig.h> #include <vcsbase/vcsbaseeditor.h> +#include <vcsbase/vcsbaseplugin.h> #include <vcsbase/vcsoutputwindow.h> -#include <vcsbase/vcsbaseeditorconfig.h> #include <QAction> #include <QDebug> @@ -159,23 +161,16 @@ const char CMD_ID_FILELOG_CURRENT[] = "Perforce.FilelogCurrent"; const char CMD_ID_FILELOG[] = "Perforce.Filelog"; const char CMD_ID_UPDATEALL[] = "Perforce.UpdateAll"; -//// -// PerforcePlugin -//// - -PerforceResponse::PerforceResponse() : - error(true), - exitCode(-1) -{ -} - -static PerforcePluginPrivate *dd = nullptr; +// Helpers -PerforcePlugin::~PerforcePlugin() +struct PerforceResponse { - delete dd; - dd = nullptr; -} + bool error = true; + int exitCode = -1; + QString stdOut; + QString stdErr; + QString message; +}; static const VcsBaseSubmitEditorParameters submitParameters = { SUBMIT_MIMETYPE, @@ -184,15 +179,200 @@ static const VcsBaseSubmitEditorParameters submitParameters = { VcsBaseSubmitEditorParameters::DiffFiles }; -bool PerforcePlugin::initialize(const QStringList & /* arguments */, QString *errorMessage) +// Flags for runP4Cmd. +enum RunFlags +{ + CommandToWindow = 0x1, + StdOutToWindow = 0x2, + StdErrToWindow = 0x4, + ErrorToWindow = 0x8, + OverrideDiffEnvironment = 0x10, + // Run completely synchronously, no signals emitted + RunFullySynchronous = 0x20, + IgnoreExitCode = 0x40, + ShowBusyCursor = 0x80, + LongTimeOut = 0x100, + SilentStdOut = 0x200, +}; + +struct PerforceDiffParameters { - Q_UNUSED(errorMessage) - dd = new PerforcePluginPrivate; - return true; -} + QString workingDir; + QStringList diffArguments; + QStringList files; +}; + +class PerforcePluginPrivate final : public VcsBasePluginPrivate +{ + Q_DECLARE_TR_FUNCTIONS(Perforce::Internal::PerforcePlugin) + +public: + PerforcePluginPrivate(); + + // IVersionControl + QString displayName() const final { return {"perforce"}; } + Id id() const final { return VcsBase::Constants::VCS_ID_PERFORCE; } + + bool isVcsFileOrDirectory(const FilePath &fileName) const final; + bool managesDirectory(const QString &directory, QString *topLevel = nullptr) const final; + bool managesFile(const QString &workingDirectory, const QString &fileName) const final; + + bool isConfigured() const final; + bool supportsOperation(Operation operation) const final; + OpenSupportMode openSupportMode(const QString &fileName) const final; + bool vcsOpen(const QString &fileName) final; + SettingsFlags settingsFlags() const final; + bool vcsAdd(const QString &fileName) final; + bool vcsDelete(const QString &filename) final; + bool vcsMove(const QString &from, const QString &to) final; + bool vcsCreateRepository(const QString &directory) final; + bool vcsAnnotate(const QString &file, int line) final; + QString vcsOpenText() const final; + QString vcsMakeWritableText() const final; + + /// + bool vcsOpen(const QString &workingDir, const QString &fileName, bool silently = false); + bool vcsAdd(const QString &workingDir, const QString &fileName); + bool vcsDelete(const QString &workingDir, const QString &filename); + bool vcsMove(const QString &workingDir, const QString &from, const QString &to); + + void p4Diff(const QString &workingDir, const QStringList &files); + + IEditor *openPerforceSubmitEditor(const QString &fileName, const QStringList &depotFileNames); + + void describe(const QString &source, const QString &n); + void vcsAnnotate(const QString &workingDirectory, const QString &file, + const QString &revision, int lineNumber); + + void getTopLevel(const QString &workingDirectory = QString(), bool isSync = false); + + void updateActions(ActionState) override; + bool submitEditorAboutToClose() override; + + QString commitDisplayName() const final; + void p4Diff(const PerforceDiffParameters &p); + + void openCurrentFile(); + void addCurrentFile(); + void revertCurrentFile(); + void printOpenedFileList(); + void diffCurrentFile(); + void diffCurrentProject(); + void updateCurrentProject(); + void revertCurrentProject(); + void revertUnchangedCurrentProject(); + void updateAll(); + void diffAllOpened(); + void startSubmitProject(); + void describeChange(); + void annotateCurrentFile(); + void annotateFile(); + void filelogCurrentFile(); + void filelogFile(); + void logProject(); + void logRepository(); + + void commitFromEditor() override; + void printPendingChanges(); + void slotSubmitDiff(const QStringList &files); + void setTopLevel(const QString &); + void slotTopLevelFailed(const QString &); + + class DirectoryCacheEntry + { + public: + DirectoryCacheEntry(bool isManaged, const QString &topLevel): + m_isManaged(isManaged), m_topLevel(topLevel) + { } + + bool m_isManaged; + QString m_topLevel; + }; + + typedef QHash<QString, DirectoryCacheEntry> ManagedDirectoryCache; + + IEditor *showOutputInEditor(const QString &title, const QString &output, + int editorType, const QString &source, + QTextCodec *codec = nullptr); + + // args are passed as command line arguments + // extra args via a tempfile and the option -x "temp-filename" + PerforceResponse runP4Cmd(const QString &workingDir, + const QStringList &args, + unsigned flags = CommandToWindow|StdErrToWindow|ErrorToWindow, + const QStringList &extraArgs = {}, + const QByteArray &stdInput = {}, + QTextCodec *outputCodec = nullptr) const; + + PerforceResponse synchronousProcess(const QString &workingDir, + const QStringList &args, + unsigned flags, + const QByteArray &stdInput, + QTextCodec *outputCodec) const; + + PerforceResponse fullySynchronousProcess(const QString &workingDir, + const QStringList &args, + unsigned flags, + const QByteArray &stdInput, + QTextCodec *outputCodec) const; + + QString clientFilePath(const QString &serverFilePath); + void annotate(const QString &workingDir, const QString &fileName, + const QString &changeList = QString(), int lineNumber = -1); + void filelog(const QString &workingDir, const QString &fileName = QString(), + bool enableAnnotationContextMenu = false); + void changelists(const QString &workingDir, const QString &fileName = QString()); + void cleanCommitMessageFile(); + bool isCommitEditorOpen() const; + static QSharedPointer<TempFileSaver> createTemporaryArgumentFile(const QStringList &extraArgs, + QString *errorString); + + QString pendingChangesData(); + + void updateCheckout(const QString &workingDir = QString(), + const QStringList &dirs = QStringList()); + bool revertProject(const QString &workingDir, const QStringList &args, bool unchangedOnly); + bool managesDirectoryFstat(const QString &directory); + + void applySettings(); + + CommandLocator *m_commandLocator = nullptr; + ParameterAction *m_editAction = nullptr; + ParameterAction *m_addAction = nullptr; + ParameterAction *m_deleteAction = nullptr; + QAction *m_openedAction = nullptr; + ParameterAction *m_revertFileAction = nullptr; + ParameterAction *m_diffFileAction = nullptr; + ParameterAction *m_diffProjectAction = nullptr; + ParameterAction *m_updateProjectAction = nullptr; + ParameterAction *m_revertProjectAction = nullptr; + ParameterAction *m_revertUnchangedAction = nullptr; + QAction *m_diffAllAction = nullptr; + ParameterAction *m_submitProjectAction = nullptr; + QAction *m_pendingAction = nullptr; + QAction *m_describeAction = nullptr; + ParameterAction *m_annotateCurrentAction = nullptr; + QAction *m_annotateAction = nullptr; + ParameterAction *m_filelogCurrentAction = nullptr; + QAction *m_filelogAction = nullptr; + ParameterAction *m_logProjectAction = nullptr; + QAction *m_logRepositoryAction = nullptr; + QAction *m_updateAllAction = nullptr; + bool m_submitActionTriggered = false; + QString m_commitMessageFileName; + mutable QString m_tempFilePattern; + QAction *m_menuAction = nullptr; + + PerforceSettings m_settings; + SettingsPage m_settingsPage{&m_settings, [this] { applySettings(); }}; + + ManagedDirectoryCache m_managedDirectoryCache; +}; + +static PerforcePluginPrivate *dd = nullptr; PerforcePluginPrivate::PerforcePluginPrivate() - : VcsBase::VcsBasePluginPrivate(Context(PERFORCE_CONTEXT)) + : VcsBasePluginPrivate(Context(PERFORCE_CONTEXT)) { Context context(PERFORCE_CONTEXT); @@ -200,8 +380,6 @@ PerforcePluginPrivate::PerforcePluginPrivate() m_settings.fromSettings(ICore::settings()); - new SettingsPage(this); - // Editor factories new VcsSubmitEditorFactory(&submitParameters, []() { return new PerforceSubmitEditor(&submitParameters); }, this); @@ -537,7 +715,7 @@ void PerforcePluginPrivate::printOpenedFileList() mapped.clear(); const int delimiterPos = line.indexOf(delimiter); if (delimiterPos > 0) - mapped = fileNameFromPerforceName(line.left(delimiterPos), true, &errorMessage); + mapped = PerforcePlugin::fileNameFromPerforceName(line.left(delimiterPos), true, &errorMessage); if (mapped.isEmpty()) VcsOutputWindow::appendSilently(line); else @@ -925,7 +1103,7 @@ PerforcePluginPrivate::createTemporaryArgumentFile(const QStringList &extraArgs, // create pattern QString pattern = dd->m_tempFilePattern; if (pattern.isEmpty()) { - pattern = Utils::TemporaryDirectory::masterDirectoryPath() + "/qtc_p4_XXXXXX.args"; + pattern = TemporaryDirectory::masterDirectoryPath() + "/qtc_p4_XXXXXX.args"; dd->m_tempFilePattern = pattern; } QSharedPointer<TempFileSaver> rc(new TempFileSaver(pattern)); @@ -941,7 +1119,7 @@ PerforcePluginPrivate::createTemporaryArgumentFile(const QStringList &extraArgs, return rc; } -bool PerforcePluginPrivate::isVcsFileOrDirectory(const Utils::FilePath &fileName) const +bool PerforcePluginPrivate::isVcsFileOrDirectory(const FilePath &fileName) const { Q_UNUSED(fileName) return false; // Perforce does not seem to litter its files into the source tree. @@ -949,7 +1127,7 @@ bool PerforcePluginPrivate::isVcsFileOrDirectory(const Utils::FilePath &fileName bool PerforcePluginPrivate::isConfigured() const { - const QString binary = settings().p4BinaryPath(); + const QString binary = m_settings.p4BinaryPath(); if (binary.isEmpty()) return false; QFileInfo fi(binary); @@ -973,7 +1151,7 @@ bool PerforcePluginPrivate::supportsOperation(Operation operation) const return false; } -Core::IVersionControl::OpenSupportMode PerforcePluginPrivate::openSupportMode(const QString &fileName) const +IVersionControl::OpenSupportMode PerforcePluginPrivate::openSupportMode(const QString &fileName) const { Q_UNUSED(fileName) return OpenOptional; @@ -985,7 +1163,7 @@ bool PerforcePluginPrivate::vcsOpen(const QString &fileName) return vcsOpen(fi.absolutePath(), fi.fileName(), true); } -Core::IVersionControl::SettingsFlags PerforcePluginPrivate::settingsFlags() const +IVersionControl::SettingsFlags PerforcePluginPrivate::settingsFlags() const { SettingsFlags rc; if (m_settings.autoOpen()) @@ -1058,17 +1236,17 @@ static inline QString msgExitCode(int ex) // Run using a SynchronousProcess, emitting signals to the message window PerforceResponse PerforcePluginPrivate::synchronousProcess(const QString &workingDir, - const QStringList &args, - unsigned flags, - const QByteArray &stdInput, - QTextCodec *outputCodec) + const QStringList &args, + unsigned flags, + const QByteArray &stdInput, + QTextCodec *outputCodec) const { QTC_ASSERT(stdInput.isEmpty(), return PerforceResponse()); // Not supported here VcsOutputWindow *outputWindow = VcsOutputWindow::instance(); // Run, connect stderr to the output window SynchronousProcess process; - const int timeOutS = (flags & LongTimeOut) ? settings().longTimeOutS() : settings().timeOutS(); + const int timeOutS = (flags & LongTimeOut) ? m_settings.longTimeOutS() : m_settings.timeOutS(); process.setTimeoutS(timeOutS); if (outputCodec) process.setCodec(outputCodec); @@ -1100,7 +1278,7 @@ PerforceResponse PerforcePluginPrivate::synchronousProcess(const QString &workin } } process.setTimeOutMessageBoxEnabled(true); - const SynchronousProcessResponse sp_resp = process.run({settings().p4BinaryPath(), args}); + const SynchronousProcessResponse sp_resp = process.run({m_settings.p4BinaryPath(), args}); PerforceResponse response; response.error = true; @@ -1119,7 +1297,7 @@ PerforceResponse PerforcePluginPrivate::synchronousProcess(const QString &workin response.message = msgCrash(); break; case SynchronousProcessResponse::StartFailed: - response.message = msgNotStarted(settings().p4BinaryPath()); + response.message = msgNotStarted(m_settings.p4BinaryPath()); break; case SynchronousProcessResponse::Hang: response.message = msgCrash(); @@ -1130,10 +1308,10 @@ PerforceResponse PerforcePluginPrivate::synchronousProcess(const QString &workin // Run using a QProcess, for short queries PerforceResponse PerforcePluginPrivate::fullySynchronousProcess(const QString &workingDir, - const QStringList &args, - unsigned flags, - const QByteArray &stdInput, - QTextCodec *outputCodec) + const QStringList &args, + unsigned flags, + const QByteArray &stdInput, + QTextCodec *outputCodec) const { QProcess process; @@ -1143,13 +1321,13 @@ PerforceResponse PerforcePluginPrivate::fullySynchronousProcess(const QString &w process.setWorkingDirectory(workingDir); PerforceResponse response; - process.start(settings().p4BinaryPath(), args); + process.start(m_settings.p4BinaryPath(), args); if (stdInput.isEmpty()) process.closeWriteChannel(); if (!process.waitForStarted(3000)) { response.error = true; - response.message = msgNotStarted(settings().p4BinaryPath()); + response.message = msgNotStarted(m_settings.p4BinaryPath()); return response; } if (!stdInput.isEmpty()) { @@ -1157,7 +1335,7 @@ PerforceResponse PerforcePluginPrivate::fullySynchronousProcess(const QString &w SynchronousProcess::stopProcess(process); response.error = true; response.message = tr("Unable to write input data to process %1: %2"). - arg(QDir::toNativeSeparators(settings().p4BinaryPath()), + arg(QDir::toNativeSeparators(m_settings.p4BinaryPath()), process.errorString()); return response; } @@ -1166,7 +1344,7 @@ PerforceResponse PerforcePluginPrivate::fullySynchronousProcess(const QString &w QByteArray stdOut; QByteArray stdErr; - const int timeOutS = (flags & LongTimeOut) ? settings().longTimeOutS() : settings().timeOutS(); + const int timeOutS = (flags & LongTimeOut) ? m_settings.longTimeOutS() : m_settings.timeOutS(); if (!SynchronousProcess::readDataFromProcess(process, timeOutS, &stdOut, &stdErr, true)) { SynchronousProcess::stopProcess(process); response.error = true; @@ -1195,20 +1373,20 @@ PerforceResponse PerforcePluginPrivate::fullySynchronousProcess(const QString &w } PerforceResponse PerforcePluginPrivate::runP4Cmd(const QString &workingDir, - const QStringList &args, - unsigned flags, - const QStringList &extraArgs, - const QByteArray &stdInput, - QTextCodec *outputCodec) + const QStringList &args, + unsigned flags, + const QStringList &extraArgs, + const QByteArray &stdInput, + QTextCodec *outputCodec) const { - if (!settings().isValid()) { + if (!m_settings.isValid()) { PerforceResponse invalidConfigResponse; invalidConfigResponse.error = true; invalidConfigResponse.message = tr("Perforce is not correctly configured."); VcsOutputWindow::appendError(invalidConfigResponse.message); return invalidConfigResponse; } - QStringList actualArgs = settings().commonP4Arguments(workingDir); + QStringList actualArgs = m_settings.commonP4Arguments(workingDir); QString errorMessage; QSharedPointer<TempFileSaver> tempFile = createTemporaryArgumentFile(extraArgs, &errorMessage); if (!tempFile.isNull()) { @@ -1222,7 +1400,7 @@ PerforceResponse PerforcePluginPrivate::runP4Cmd(const QString &workingDir, actualArgs.append(args); if (flags & CommandToWindow) - VcsOutputWindow::appendCommand(workingDir, {settings().p4BinaryPath(), actualArgs}); + VcsOutputWindow::appendCommand(workingDir, {m_settings.p4BinaryPath(), actualArgs}); if (flags & ShowBusyCursor) QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); @@ -1276,13 +1454,6 @@ void PerforcePluginPrivate::slotSubmitDiff(const QStringList &files) p4Diff(m_settings.topLevel(), files); } -struct PerforceDiffParameters -{ - QString workingDir; - QStringList diffArguments; - QStringList files; -}; - // Parameter widget controlling whitespace diff mode, associated with a parameter class PerforceDiffConfig : public VcsBaseEditorConfig { @@ -1356,7 +1527,7 @@ void PerforcePluginPrivate::p4Diff(const PerforceDiffParameters &p) return; } // Create new editor - IEditor *editor = showOutputInEditor(tr("p4 diff %1").arg(id), result.stdOut, VcsBase::DiffOutput, + IEditor *editor = showOutputInEditor(tr("p4 diff %1").arg(id), result.stdOut, DiffOutput, VcsBaseEditor::getSource(p.workingDir, p.files), codec); VcsBaseEditor::tagEditor(editor, tag); @@ -1380,7 +1551,7 @@ void PerforcePluginPrivate::describe(const QString & source, const QString &n) const PerforceResponse result = runP4Cmd(m_settings.topLevel(), args, CommandToWindow|StdErrToWindow|ErrorToWindow, QStringList(), QByteArray(), codec); if (!result.error) - showOutputInEditor(tr("p4 describe %1").arg(n), result.stdOut, VcsBase::DiffOutput, source, codec); + showOutputInEditor(tr("p4 describe %1").arg(n), result.stdOut, DiffOutput, source, codec); } void PerforcePluginPrivate::commitFromEditor() @@ -1495,22 +1666,6 @@ QString PerforcePluginPrivate::pendingChangesData() return dataResponse.error ? QString() : dataResponse.stdOut; } -const PerforceSettings& PerforcePluginPrivate::settings() -{ - return dd->m_settings; -} - -void PerforcePluginPrivate::setSettings(const Settings &newSettings) -{ - if (newSettings != dd->m_settings.settings()) { - dd->m_settings.setSettings(newSettings); - dd->m_managedDirectoryCache.clear(); - dd->m_settings.toSettings(ICore::settings()); - getTopLevel(); - emit dd->configurationChanged(); - } -} - static inline QString msgWhereFailed(const QString & file, const QString &why) { //: Failed to run p4 "where" to resolve a Perforce file name to a local @@ -1520,7 +1675,7 @@ static inline QString msgWhereFailed(const QString & file, const QString &why) } // Map a perforce name "//xx" to its real name in the file system -QString PerforcePluginPrivate::fileNameFromPerforceName(const QString& perforceName, +QString PerforcePlugin::fileNameFromPerforceName(const QString& perforceName, bool quiet, QString *errorMessage) { @@ -1533,7 +1688,7 @@ QString PerforcePluginPrivate::fileNameFromPerforceName(const QString& perforceN unsigned flags = RunFullySynchronous; if (!quiet) flags |= CommandToWindow|StdErrToWindow|ErrorToWindow; - const PerforceResponse response = runP4Cmd(settings().topLevelSymLinkTarget(), args, flags); + const PerforceResponse response = dd->runP4Cmd(dd->m_settings.topLevelSymLinkTarget(), args, flags); if (response.error) { *errorMessage = msgWhereFailed(perforceName, response.message); return QString(); @@ -1565,6 +1720,14 @@ void PerforcePluginPrivate::setTopLevel(const QString &topLevel) VcsOutputWindow::appendSilently(msg); } +void PerforcePluginPrivate::applySettings() +{ + m_settings.toSettings(ICore::settings()); + m_managedDirectoryCache.clear(); + getTopLevel(); + emit configurationChanged(); +} + void PerforcePluginPrivate::slotTopLevelFailed(const QString &errorMessage) { VcsOutputWindow::appendSilently(tr("Perforce: Unable to determine the repository: %1").arg(errorMessage)); @@ -1573,7 +1736,7 @@ void PerforcePluginPrivate::slotTopLevelFailed(const QString &errorMessage) void PerforcePluginPrivate::getTopLevel(const QString &workingDirectory, bool isSync) { // Run a new checker - if (dd->m_settings.p4BinaryPath().isEmpty()) + if (m_settings.p4BinaryPath().isEmpty()) return; auto checker = new PerforceChecker(dd); connect(checker, &PerforceChecker::failed, dd, &PerforcePluginPrivate::slotTopLevelFailed); @@ -1581,13 +1744,26 @@ void PerforcePluginPrivate::getTopLevel(const QString &workingDirectory, bool is connect(checker, &PerforceChecker::succeeded, dd, &PerforcePluginPrivate::setTopLevel); connect(checker, &PerforceChecker::succeeded,checker, &QObject::deleteLater); - checker->start(settings().p4BinaryPath(), workingDirectory, - settings().commonP4Arguments(QString()), 30000); + checker->start(m_settings.p4BinaryPath(), workingDirectory, + m_settings.commonP4Arguments(QString()), 30000); if (isSync) checker->waitForFinished(); } +PerforcePlugin::~PerforcePlugin() +{ + delete dd; + dd = nullptr; +} + +bool PerforcePlugin::initialize(const QStringList & /* arguments */, QString *errorMessage) +{ + Q_UNUSED(errorMessage) + dd = new PerforcePluginPrivate; + return true; +} + #ifdef WITH_TESTS void PerforcePlugin::testLogResolving() { diff --git a/src/plugins/perforce/perforceplugin.h b/src/plugins/perforce/perforceplugin.h index 6bb7721ab4c..5c9de244324 100644 --- a/src/plugins/perforce/perforceplugin.h +++ b/src/plugins/perforce/perforceplugin.h @@ -25,236 +25,10 @@ #pragma once -#include "perforcesettings.h" - -#include <coreplugin/editormanager/ieditorfactory.h> -#include <coreplugin/iversioncontrol.h> - -#include <vcsbase/vcsbaseconstants.h> -#include <vcsbase/vcsbaseplugin.h> - -#include <QObject> -#include <QProcess> -#include <QStringList> -#include <QSharedPointer> -#include <QHash> - -QT_BEGIN_NAMESPACE -class QFile; -class QAction; -class QTextCodec; -QT_END_NAMESPACE - -namespace Utils { - class ParameterAction; - class TempFileSaver; -} - -namespace Core { -class ActionContainer; -class CommandLocator; -} +#include <extensionsystem/iplugin.h> namespace Perforce { namespace Internal { -struct PerforceDiffParameters; -class PerforceVersionControl; - -struct PerforceResponse -{ - PerforceResponse(); - - bool error; - int exitCode; - QString stdOut; - QString stdErr; - QString message; -}; - -class PerforcePluginPrivate final : public VcsBase::VcsBasePluginPrivate -{ - Q_OBJECT - -public: - PerforcePluginPrivate(); - - // IVersionControl - QString displayName() const final { return {"perforce"}; } - Core::Id id() const final { return Core::Id(VcsBase::Constants::VCS_ID_PERFORCE); } - - bool isVcsFileOrDirectory(const Utils::FilePath &fileName) const final; - bool managesDirectory(const QString &directory, QString *topLevel = nullptr) const final; - bool managesFile(const QString &workingDirectory, const QString &fileName) const final; - - bool isConfigured() const final; - bool supportsOperation(Operation operation) const final; - OpenSupportMode openSupportMode(const QString &fileName) const final; - bool vcsOpen(const QString &fileName) final; - SettingsFlags settingsFlags() const final; - bool vcsAdd(const QString &fileName) final; - bool vcsDelete(const QString &filename) final; - bool vcsMove(const QString &from, const QString &to) final; - bool vcsCreateRepository(const QString &directory) final; - bool vcsAnnotate(const QString &file, int line) final; - QString vcsOpenText() const final; - QString vcsMakeWritableText() const final; - - /// - bool vcsOpen(const QString &workingDir, const QString &fileName, bool silently = false); - bool vcsAdd(const QString &workingDir, const QString &fileName); - bool vcsDelete(const QString &workingDir, const QString &filename); - bool vcsMove(const QString &workingDir, const QString &from, const QString &to); - - void p4Diff(const QString &workingDir, const QStringList &files); - - Core::IEditor *openPerforceSubmitEditor(const QString &fileName, const QStringList &depotFileNames); - - static const PerforceSettings& settings(); - static void setSettings(const Settings &s); - - // Map a perforce name "//xx" to its real name in the file system - static QString fileNameFromPerforceName(const QString& perforceName, - bool quiet, - QString *errorMessage); - - void describe(const QString &source, const QString &n); - void vcsAnnotate(const QString &workingDirectory, const QString &file, - const QString &revision, int lineNumber); - - static void getTopLevel(const QString &workingDirectory = QString(), bool isSync = false); - -protected: - void updateActions(VcsBase::VcsBasePluginPrivate::ActionState) override; - bool submitEditorAboutToClose() override; - -private: - QString commitDisplayName() const final; - void p4Diff(const PerforceDiffParameters &p); - - void openCurrentFile(); - void addCurrentFile(); - void revertCurrentFile(); - void printOpenedFileList(); - void diffCurrentFile(); - void diffCurrentProject(); - void updateCurrentProject(); - void revertCurrentProject(); - void revertUnchangedCurrentProject(); - void updateAll(); - void diffAllOpened(); - void startSubmitProject(); - void describeChange(); - void annotateCurrentFile(); - void annotateFile(); - void filelogCurrentFile(); - void filelogFile(); - void logProject(); - void logRepository(); - - void commitFromEditor() override; - void printPendingChanges(); - void slotSubmitDiff(const QStringList &files); - void setTopLevel(const QString &); - void slotTopLevelFailed(const QString &); - - class DirectoryCacheEntry - { - public: - DirectoryCacheEntry(bool isManaged, const QString &topLevel): - m_isManaged(isManaged), m_topLevel(topLevel) - { } - - bool m_isManaged; - QString m_topLevel; - }; - - typedef QHash<QString, DirectoryCacheEntry> ManagedDirectoryCache; - - Core::IEditor *showOutputInEditor(const QString &title, const QString &output, - int editorType, const QString &source, - QTextCodec *codec = nullptr); - - // Flags for runP4Cmd. - enum RunFlags { CommandToWindow = 0x1, StdOutToWindow = 0x2, - StdErrToWindow = 0x4, ErrorToWindow = 0x8, - OverrideDiffEnvironment = 0x10, - // Run completely synchronously, no signals emitted - RunFullySynchronous = 0x20, - IgnoreExitCode = 0x40, - ShowBusyCursor = 0x80, - LongTimeOut = 0x100, - SilentStdOut = 0x200, - }; - - // args are passed as command line arguments - // extra args via a tempfile and the option -x "temp-filename" - static PerforceResponse runP4Cmd(const QString &workingDir, - const QStringList &args, - unsigned flags = CommandToWindow|StdErrToWindow|ErrorToWindow, - const QStringList &extraArgs = QStringList(), - const QByteArray &stdInput = QByteArray(), - QTextCodec *outputCodec = nullptr); - - static PerforceResponse synchronousProcess(const QString &workingDir, - const QStringList &args, - unsigned flags, - const QByteArray &stdInput, - QTextCodec *outputCodec); - - static PerforceResponse fullySynchronousProcess(const QString &workingDir, - const QStringList &args, - unsigned flags, - const QByteArray &stdInput, - QTextCodec *outputCodec); - - QString clientFilePath(const QString &serverFilePath); - void annotate(const QString &workingDir, const QString &fileName, - const QString &changeList = QString(), int lineNumber = -1); - void filelog(const QString &workingDir, const QString &fileName = QString(), - bool enableAnnotationContextMenu = false); - void changelists(const QString &workingDir, const QString &fileName = QString()); - void cleanCommitMessageFile(); - bool isCommitEditorOpen() const; - static QSharedPointer<Utils::TempFileSaver> createTemporaryArgumentFile(const QStringList &extraArgs, - QString *errorString); - - QString pendingChangesData(); - - void updateCheckout(const QString &workingDir = QString(), - const QStringList &dirs = QStringList()); - bool revertProject(const QString &workingDir, const QStringList &args, bool unchangedOnly); - bool managesDirectoryFstat(const QString &directory); - - Core::CommandLocator *m_commandLocator = nullptr; - Utils::ParameterAction *m_editAction = nullptr; - Utils::ParameterAction *m_addAction = nullptr; - Utils::ParameterAction *m_deleteAction = nullptr; - QAction *m_openedAction = nullptr; - Utils::ParameterAction *m_revertFileAction = nullptr; - Utils::ParameterAction *m_diffFileAction = nullptr; - Utils::ParameterAction *m_diffProjectAction = nullptr; - Utils::ParameterAction *m_updateProjectAction = nullptr; - Utils::ParameterAction *m_revertProjectAction = nullptr; - Utils::ParameterAction *m_revertUnchangedAction = nullptr; - QAction *m_diffAllAction = nullptr; - Utils::ParameterAction *m_submitProjectAction = nullptr; - QAction *m_pendingAction = nullptr; - QAction *m_describeAction = nullptr; - Utils::ParameterAction *m_annotateCurrentAction = nullptr; - QAction *m_annotateAction = nullptr; - Utils::ParameterAction *m_filelogCurrentAction = nullptr; - QAction *m_filelogAction = nullptr; - Utils::ParameterAction *m_logProjectAction = nullptr; - QAction *m_logRepositoryAction = nullptr; - QAction *m_updateAllAction = nullptr; - bool m_submitActionTriggered = false; - QString m_commitMessageFileName; - mutable QString m_tempFilePattern; - QAction *m_menuAction = nullptr; - - PerforceSettings m_settings; - ManagedDirectoryCache m_managedDirectoryCache; -}; class PerforcePlugin final : public ExtensionSystem::IPlugin { @@ -266,6 +40,12 @@ class PerforcePlugin final : public ExtensionSystem::IPlugin bool initialize(const QStringList &arguments, QString *errorMessage) final; void extensionsInitialized() final; +public: + // Map a perforce name "//xx" to its real name in the file system + static QString fileNameFromPerforceName(const QString& perforceName, + bool quiet, + QString *errorMessage); + #ifdef WITH_TESTS private slots: void testLogResolving(); diff --git a/src/plugins/perforce/settingspage.cpp b/src/plugins/perforce/settingspage.cpp index 445b8c1b0f8..17db6352702 100644 --- a/src/plugins/perforce/settingspage.cpp +++ b/src/plugins/perforce/settingspage.cpp @@ -45,7 +45,7 @@ class SettingsPageWidget final : public Core::IOptionsPageWidget Q_DECLARE_TR_FUNCTIONS(Perforce::Internal::SettingsPage) public: - SettingsPageWidget(); + SettingsPageWidget(PerforceSettings *settings, const std::function<void()> &onApply); ~SettingsPageWidget() final; private: @@ -60,9 +60,12 @@ private: Ui::SettingsPage m_ui; PerforceChecker *m_checker = nullptr; + PerforceSettings *m_settings = nullptr; + std::function<void()> m_onApply; }; -SettingsPageWidget::SettingsPageWidget() +SettingsPageWidget::SettingsPageWidget(PerforceSettings *settings, const std::function<void()> &onApply) + : m_settings(settings), m_onApply(onApply) { m_ui.setupUi(this); m_ui.errorLabel->clear(); @@ -71,7 +74,7 @@ SettingsPageWidget::SettingsPageWidget() m_ui.pathChooser->setExpectedKind(PathChooser::Command); connect(m_ui.testPushButton, &QPushButton::clicked, this, &SettingsPageWidget::slotTest); - const PerforceSettings &s = PerforcePluginPrivate::settings(); + const PerforceSettings &s = *settings; m_ui.pathChooser->setPath(s.p4Command()); m_ui.environmentGroupBox->setChecked(!s.defaultEnv()); m_ui.portLineEdit->setText(s.p4Port()); @@ -101,7 +104,7 @@ void SettingsPageWidget::slotTest() return; setStatusText(tr("Testing...")); - const Settings s = settings(); + const Settings s = m_settings->settings(); m_checker->start(s.p4BinaryPath, QString(), s.commonP4Arguments(), 10000); } @@ -110,7 +113,7 @@ void SettingsPageWidget::testSucceeded(const QString &repo) setStatusText(tr("Test succeeded (%1).").arg(QDir::toNativeSeparators(repo))); } -Settings SettingsPageWidget::settings() const +void SettingsPageWidget::apply() { Settings settings; settings.p4Command = m_ui.pathChooser->rawPath(); @@ -123,12 +126,12 @@ Settings SettingsPageWidget::settings() const settings.logCount = m_ui.logCountSpinBox->value(); settings.promptToSubmit = m_ui.promptToSubmitCheckBox->isChecked(); settings.autoOpen = m_ui.autoOpenCheckBox->isChecked(); - return settings; -} -void SettingsPageWidget::apply() -{ - PerforcePluginPrivate::setSettings(settings()); + if (settings == m_settings->settings()) + return; + + m_settings->setSettings(settings); + m_onApply(); } void SettingsPageWidget::setStatusText(const QString &t) @@ -143,13 +146,12 @@ void SettingsPageWidget::setStatusError(const QString &t) m_ui.errorLabel->setText(t); } -SettingsPage::SettingsPage(QObject *parent) - : Core::IOptionsPage(parent) +SettingsPage::SettingsPage(PerforceSettings *settings, const std::function<void ()> &onApply) { setId(VcsBase::Constants::VCS_ID_PERFORCE); setDisplayName(SettingsPageWidget::tr("Perforce")); setCategory(VcsBase::Constants::VCS_SETTINGS_CATEGORY); - setWidgetCreator([] { return new SettingsPageWidget; }); + setWidgetCreator([settings, onApply] { return new SettingsPageWidget(settings, onApply); }); } } // Internal diff --git a/src/plugins/perforce/settingspage.h b/src/plugins/perforce/settingspage.h index aec873b102a..a718c43ea65 100644 --- a/src/plugins/perforce/settingspage.h +++ b/src/plugins/perforce/settingspage.h @@ -32,10 +32,12 @@ namespace Perforce { namespace Internal { +class PerforceSettings; + class SettingsPage final : public Core::IOptionsPage { public: - explicit SettingsPage(QObject *parent); + SettingsPage(PerforceSettings *settings, const std::function<void()> &onApply); }; } // namespace Internal |