diff --git a/svn/CMakeLists.txt b/svn/CMakeLists.txt --- a/svn/CMakeLists.txt +++ b/svn/CMakeLists.txt @@ -8,9 +8,10 @@ svncommitdialog.cpp svnlogdialog.cpp svncheckoutdialog.cpp + svnprogressdialog.cpp ) -ki18n_wrap_ui(fileviewsvnplugin_SRCS svnlogdialog.ui svncheckoutdialog.ui) +ki18n_wrap_ui(fileviewsvnplugin_SRCS svnlogdialog.ui svncheckoutdialog.ui svnprogressdialog.ui) kconfig_add_kcfg_files(fileviewsvnplugin_SRCS fileviewsvnpluginsettings.kcfgc diff --git a/svn/fileviewsvnplugin.cpp b/svn/fileviewsvnplugin.cpp --- a/svn/fileviewsvnplugin.cpp +++ b/svn/fileviewsvnplugin.cpp @@ -47,6 +47,7 @@ #include "svncommitdialog.h" #include "svnlogdialog.h" #include "svncheckoutdialog.h" +#include "svnprogressdialog.h" #include "svncommands.h" @@ -343,6 +344,9 @@ void FileViewSvnPlugin::updateFiles() { + SvnProgressDialog *progress = new SvnProgressDialog(i18nc("@title:window", "SVN Update")); + progress->connectToProcess(&m_process); + execSvnCommand(QLatin1String("update"), QStringList(), i18nc("@info:status", "Updating SVN repository..."), i18nc("@info:status", "Update of SVN repository failed."), @@ -441,6 +445,9 @@ arguments << QLatin1String("--depth") << QLatin1String("infinity"); } + SvnProgressDialog *progress = new SvnProgressDialog(i18nc("@title:window", "SVN Revert")); + progress->connectToProcess(&m_process); + execSvnCommand(QStringLiteral("revert"), arguments, i18nc("@info:status", "Reverting files from SVN repository..."), i18nc("@info:status", "Reverting of files from SVN repository failed."), @@ -512,6 +519,9 @@ } m_contextDir.clear(); + SvnProgressDialog *progress = new SvnProgressDialog(i18nc("@title:window", "SVN Revert")); + progress->connectToProcess(&m_process); + execSvnCommand(QLatin1String("revert"), QStringList() << filesPath, i18nc("@info:status", "Reverting changes to file..."), i18nc("@info:status", "Revert file failed."), @@ -615,6 +625,9 @@ m_contextDir.clear(); m_contextItems.clear(); + SvnProgressDialog *progress = new SvnProgressDialog(i18nc("@title:window", "SVN Commit")); + progress->connectToProcess(&m_process); + execSvnCommand(QLatin1String("commit"), arguments, i18nc("@info:status", "Committing SVN changes..."), i18nc("@info:status", "Commit of SVN changes failed."), diff --git a/svn/svncommands.h b/svn/svncommands.h --- a/svn/svncommands.h +++ b/svn/svncommands.h @@ -112,17 +112,17 @@ static QString remoteRelativeUrl(const QString& filePath); /** - * Updates selected \p filePath to revision \p revision. \p filePath could be a sigle file or a + * Updates selected \p filePath to revision \p revision. \p filePath could be a single file or a * directory. It also could be an absolute or relative. * * \return True on success, false either. * - * \note This function uses only local SVN data without connection to a remote so it's fast. + * \note This function can be really time consuming. */ static bool updateToRevision(const QString& filePath, ulong revision); /** - * Discards all local changes in a \p filePath. \p filePath could be a sigle file or a directory. + * Discards all local changes in a \p filePath. \p filePath could be a single file or a directory. * It also could be an absolute or relative. * * \return True on success, false either. @@ -132,7 +132,7 @@ static bool revertLocalChanges(const QString& filePath); /** - * Reverts selected \p filePath to revision \p revision. \p filePath could be a sigle file or a + * Reverts selected \p filePath to revision \p revision. \p filePath could be a single file or a * directory. It also could be an absolute or relative. * * \return True on success, false either. diff --git a/svn/svnprogressdialog.h b/svn/svnprogressdialog.h new file mode 100644 --- /dev/null +++ b/svn/svnprogressdialog.h @@ -0,0 +1,59 @@ +/*************************************************************************** + * Copyright (C) 2019-2020 * + * by Nikolai Krasheninnikov * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef SVNPROGRESSDIALOG_H +#define SVNPROGRESSDIALOG_H + +#include + +#include "ui_svnprogressdialog.h" + +class QProcess; + +class SvnProgressDialog : public QDialog { + Q_OBJECT +public: + SvnProgressDialog(const QString& title, QWidget *parent = nullptr); + virtual ~SvnProgressDialog() override; + + void connectToProcess(QProcess *process); + void disconnectFromProcess(); + +public slots: + void appendInfoText(const QString& text); + void appendErrorText(const QString& text); + void operationCompeleted(); + + virtual void reject() override; + +signals: + void cancelPressed(); + +private: + Ui::SvnProgressDialog m_ui; + + QMetaObject::Connection m_conCancel; + QMetaObject::Connection m_conCompeted; + QMetaObject::Connection m_conProcessError; + QMetaObject::Connection m_conStdOut; + QMetaObject::Connection m_conStrErr; +}; + +#endif // SVNPROGRESSDIALOG_H diff --git a/svn/svnprogressdialog.cpp b/svn/svnprogressdialog.cpp new file mode 100644 --- /dev/null +++ b/svn/svnprogressdialog.cpp @@ -0,0 +1,115 @@ +/*************************************************************************** + * Copyright (C) 2019-2020 * + * by Nikolai Krasheninnikov * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#include "svnprogressdialog.h" + +#include + +SvnProgressDialog::SvnProgressDialog(const QString& title, QWidget *parent) : + QDialog(parent) +{ + m_ui.setupUi(this); + + /* + * Add actions, establish connections. + */ + QObject::connect(m_ui.pbOk, &QPushButton::clicked, this, &QDialog::close); + QObject::connect(m_ui.pbCancel, &QPushButton::clicked, this, &SvnProgressDialog::cancelPressed); + + /* + * Additional setup. + */ + setAttribute(Qt::WA_DeleteOnClose); + setWindowTitle(title); + show(); + activateWindow(); +} + +SvnProgressDialog::~SvnProgressDialog() +{ + disconnectFromProcess(); +} + +void SvnProgressDialog::connectToProcess(QProcess *process) +{ + disconnectFromProcess(); + + m_conCancel = connect(this, &SvnProgressDialog::cancelPressed, process, &QProcess::terminate); + m_conCompeted = connect(process, QOverload::of(&QProcess::finished), this, &SvnProgressDialog::operationCompeleted); + m_conProcessError = connect(process, &QProcess::errorOccurred, this, [process, this] (QProcess::ProcessError) { + const QString commandLine = process->program() + process->arguments().join(' '); + appendErrorText(i18nc("@info:status", "Error starting: %1", commandLine)); + operationCompeleted(); + } ); + m_conStdOut = connect(process, &QProcess::readyReadStandardOutput, [process, this] () { + appendInfoText( process->readAllStandardOutput() ); + } ); + m_conStrErr = connect(process, &QProcess::readyReadStandardError, [process, this] () { + appendErrorText( process->readAllStandardError() ); + } ); +} + +void SvnProgressDialog::disconnectFromProcess() +{ + QObject::disconnect(m_conCancel); + QObject::disconnect(m_conCompeted); + QObject::disconnect(m_conProcessError); + QObject::disconnect(m_conStdOut); + QObject::disconnect(m_conStrErr); +} + +void SvnProgressDialog::appendInfoText(const QString& text) +{ + const QTextCursor pos = m_ui.teMessage->textCursor(); + + m_ui.teMessage->moveCursor(QTextCursor::End); + m_ui.teMessage->insertPlainText(text); + m_ui.teMessage->setTextCursor(pos); +} + +void SvnProgressDialog::appendErrorText(const QString& text) +{ + static const QString htmlBegin = ""; + static const QString htmlEnd = "
"; + + QString message = QString(text).replace('\n', "
"); + if (message.endsWith("
")) { + message.chop(4); + } + + m_ui.teMessage->appendHtml(htmlBegin + message + htmlEnd); +} + +void SvnProgressDialog::operationCompeleted() +{ + disconnectFromProcess(); + + m_ui.pbOk->setEnabled(true); + m_ui.pbCancel->setEnabled(false); +} + +void SvnProgressDialog::reject() +{ + if (m_ui.pbOk->isEnabled()) { + QDialog::reject(); + } else { + emit cancelPressed(); + } +} diff --git a/svn/svnprogressdialog.ui b/svn/svnprogressdialog.ui new file mode 100644 --- /dev/null +++ b/svn/svnprogressdialog.ui @@ -0,0 +1,78 @@ + + + SvnProgressDialog + + + + 0 + 0 + 521 + 409 + + + + + 0 + 0 + + + + + + + + + + true + + + + + + + Cancel + + + + .. + + + + + + + false + + + OK + + + + .. + + + true + + + true + + + + + + + Qt::Horizontal + + + + 328 + 20 + + + + + + + + +