kde-workspace/dolphin/plugins/hg/fileviewhgplugin.cpp
Ivailo Monev f68295ea28 generic: move sub-projects from kde-baseapps [ci reset]
Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
2022-05-14 21:56:54 +03:00

841 lines
28 KiB
C++

/***************************************************************************
* Copyright (C) 2011 by Vishesh Yadav <vishesh3y@gmail.com> *
* *
* 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 "fileviewhgplugin.h"
#include "hgconfig.h"
#include "configdialog.h"
#include "renamedialog.h"
#include "commitdialog.h"
#include "branchdialog.h"
#include "tagdialog.h"
#include "updatedialog.h"
#include "clonedialog.h"
#include "createdialog.h"
#include "pushdialog.h"
#include "pulldialog.h"
#include "mergedialog.h"
#include "bundledialog.h"
#include "exportdialog.h"
#include "importdialog.h"
#include "servedialog.h"
#include "backoutdialog.h"
#include <QtCore/QTextCodec>
#include <QtCore/QDir>
#include <kaction.h>
#include <kmenu.h>
#include <kicon.h>
#include <klocale.h>
#include <kdebug.h>
#include <kurl.h>
#include <kmessagebox.h>
#include <kfiledialog.h>
#include <kconfig.h>
#include <kconfiggroup.h>
#include <kservice.h>
#include <kmimetypetrader.h>
#include <KPluginFactory>
#include <KPluginLoader>
K_PLUGIN_FACTORY(FileViewHgPluginFactory, registerPlugin<FileViewHgPlugin>();)
K_EXPORT_PLUGIN(FileViewHgPluginFactory("fileviewhgplugin"))
//TODO: Build a proper status signal system to sync HgWrapper/Dialgs with this
//TODO: Show error messages and set their message approproately(hg output)
//TODO: Use i18nc rather thn i18c throughout plugin
FileViewHgPlugin::FileViewHgPlugin(QObject *parent, const QList<QVariant> &args):
KVersionControlPlugin(parent),
m_mainContextMenu(0),
m_addAction(0),
m_removeAction(0),
m_renameAction(0),
m_commitAction(0),
m_branchAction(0),
m_tagAction(0),
m_updateAction(0),
m_cloneAction(0),
m_createAction(0),
m_globalConfigAction(0),
m_repoConfigAction(0),
m_pushAction(0),
m_pullAction(0),
m_revertAction(0),
m_revertAllAction(0),
m_rollbackAction(0),
m_mergeAction(0),
m_bundleAction(0),
m_exportAction(0),
m_unbundleAction(0),
m_importAction(0),
m_diffAction(0),
m_serveAction(0),
m_backoutAction(0),
m_hgWrapper(0),
m_retrievalHgw(0)
{
Q_UNUSED(args);
m_addAction = new KAction(this);
m_addAction->setIcon(KIcon("list-add"));
m_addAction->setText(i18nc("@action:inmenu",
"<application>Hg</application> Add"));
connect(m_addAction, SIGNAL(triggered()),
this, SLOT(addFiles()));
m_removeAction = new KAction(this);
m_removeAction->setIcon(KIcon("list-remove"));
m_removeAction->setText(i18nc("@action:inmenu",
"<application>Hg</application> Remove"));
connect(m_removeAction, SIGNAL(triggered()),
this, SLOT(removeFiles()));
m_renameAction = new KAction(this);
m_renameAction->setIcon(KIcon("list-rename"));
m_renameAction->setText(i18nc("@action:inmenu",
"<application>Hg</application> Rename"));
connect(m_renameAction, SIGNAL(triggered()),
this, SLOT(renameFile()));
m_commitAction = new KAction(this);
m_commitAction->setIcon(KIcon("svn-commit"));
m_commitAction->setText(i18nc("@action:inmenu",
"<application>Hg</application> Commit"));
connect(m_commitAction, SIGNAL(triggered()),
this, SLOT(commit()));
m_tagAction = new KAction(this);
m_tagAction->setIcon(KIcon("bookmark-new"));
m_tagAction->setText(i18nc("@action:inmenu",
"<application>Hg</application> Tag"));
connect(m_tagAction, SIGNAL(triggered()),
this, SLOT(tag()));
m_branchAction = new KAction(this);
m_branchAction->setIcon(KIcon("bookmark-new"));
m_branchAction->setText(i18nc("@action:inmenu",
"<application>Hg</application> Branch"));
connect(m_branchAction, SIGNAL(triggered()),
this, SLOT(branch()));
m_cloneAction = new KAction(this);
m_cloneAction->setIcon(KIcon("hg-clone"));
m_cloneAction->setText(i18nc("@action:inmenu",
"<application>Hg</application> Clone"));
connect(m_cloneAction, SIGNAL(triggered()),
this, SLOT(clone()));
m_createAction = new KAction(this);
m_createAction->setIcon(KIcon("hg-create"));
m_createAction->setText(i18nc("@action:inmenu",
"<application>Hg</application> Init"));
connect(m_createAction, SIGNAL(triggered()),
this, SLOT(create()));
m_updateAction = new KAction(this);
m_updateAction->setIcon(KIcon("svn-update"));
m_updateAction->setText(i18nc("@action:inmenu",
"<application>Hg</application> Update"));
connect(m_updateAction, SIGNAL(triggered()),
this, SLOT(update()));
m_globalConfigAction = new KAction(this);
m_globalConfigAction->setIcon(KIcon("hg-config"));
m_globalConfigAction->setText(i18nc("@action:inmenu",
"<application>Hg</application> Global Config"));
connect(m_globalConfigAction, SIGNAL(triggered()),
this, SLOT(global_config()));
m_repoConfigAction = new KAction(this);
m_repoConfigAction->setIcon(KIcon("hg-config"));
m_repoConfigAction->setText(i18nc("@action:inmenu",
"<application>Hg</application> Repository Config"));
connect(m_repoConfigAction, SIGNAL(triggered()),
this, SLOT(repo_config()));
m_pushAction = new KAction(this);
m_pushAction->setIcon(KIcon("git-push"));
m_pushAction->setText(i18nc("@action:inmenu",
"<application>Hg</application> Push"));
connect(m_pushAction, SIGNAL(triggered()),
this, SLOT(push()));
m_pullAction = new KAction(this);
m_pullAction->setIcon(KIcon("git-pull"));
m_pullAction->setText(i18nc("@action:inmenu",
"<application>Hg</application> Pull"));
connect(m_pullAction, SIGNAL(triggered()),
this, SLOT(pull()));
m_revertAction = new KAction(this);
m_revertAction->setIcon(KIcon("hg-revert"));
m_revertAction->setText(i18nc("@action:inmenu",
"<application>Hg</application> Revert"));
connect(m_revertAction, SIGNAL(triggered()),
this, SLOT(revert()));
m_revertAllAction = new KAction(this);
m_revertAllAction->setIcon(KIcon("hg-revert"));
m_revertAllAction->setText(i18nc("@action:inmenu",
"<application>Hg</application> Revert All"));
connect(m_revertAllAction, SIGNAL(triggered()),
this, SLOT(revertAll()));
m_rollbackAction = new KAction(this);
m_rollbackAction->setIcon(KIcon("hg-rollback"));
m_rollbackAction->setText(i18nc("@action:inmenu",
"<application>Hg</application> Rollback"));
connect(m_rollbackAction, SIGNAL(triggered()),
this, SLOT(rollback()));
m_mergeAction = new KAction(this);
m_mergeAction->setIcon(KIcon("hg-merge"));
m_mergeAction->setText(i18nc("@action:inmenu",
"<application>Hg</application> Merge"));
connect(m_mergeAction, SIGNAL(triggered()),
this, SLOT(merge()));
m_bundleAction = new KAction(this);
m_bundleAction->setIcon(KIcon("hg-bundle"));
m_bundleAction->setText(i18nc("@action:inmenu",
"<application>Hg</application> Bundle"));
connect(m_bundleAction, SIGNAL(triggered()),
this, SLOT(bundle()));
m_exportAction = new KAction(this);
m_exportAction->setIcon(KIcon("hg-export"));
m_exportAction->setText(i18nc("@action:inmenu",
"<application>Hg</application> Export"));
connect(m_exportAction, SIGNAL(triggered()),
this, SLOT(exportChangesets()));
m_importAction = new KAction(this);
m_importAction->setIcon(KIcon("hg-import"));
m_importAction->setText(i18nc("@action:inmenu",
"<application>Hg</application> Import"));
connect(m_importAction, SIGNAL(triggered()),
this, SLOT(importChangesets()));
m_unbundleAction = new KAction(this);
m_unbundleAction->setIcon(KIcon("hg-unbundle"));
m_unbundleAction->setText(i18nc("@action:inmenu",
"<application>Hg</application> Unbundle"));
connect(m_unbundleAction, SIGNAL(triggered()),
this, SLOT(unbundle()));
m_serveAction = new KAction(this);
m_serveAction->setIcon(KIcon("hg-serve"));
m_serveAction->setText(i18nc("@action:inmenu",
"<application>Hg</application> Serve"));
connect(m_serveAction, SIGNAL(triggered()),
this, SLOT(serve()));
m_backoutAction = new KAction(this);
m_backoutAction->setIcon(KIcon("hg-backout"));
m_backoutAction->setText(i18nc("@action:inmenu",
"<application>Hg</application> Backout"));
connect(m_backoutAction, SIGNAL(triggered()),
this, SLOT(backout()));
m_diffAction = new KAction(this);
m_diffAction->setIcon(KIcon("hg-diff"));
m_diffAction->setText(i18nc("@action:inmenu",
"<application>Hg</application> Diff"));
connect(m_diffAction, SIGNAL(triggered()),
this, SLOT(diff()));
/* Submenu to make the main menu less cluttered */
m_mainContextMenu = new KMenu;
m_mainContextMenu->addAction(m_updateAction);
m_mainContextMenu->addAction(m_branchAction);
m_mainContextMenu->addAction(m_tagAction);
m_mainContextMenu->addAction(m_mergeAction);
m_mainContextMenu->addAction(m_revertAllAction);
m_mainContextMenu->addAction(m_rollbackAction);
m_mainContextMenu->addAction(m_backoutAction);
m_mainContextMenu->addAction(m_bundleAction);
m_mainContextMenu->addAction(m_unbundleAction);
m_mainContextMenu->addAction(m_exportAction);
m_mainContextMenu->addAction(m_importAction);
m_mainContextMenu->addAction(m_serveAction);
m_mainContextMenu->addAction(m_globalConfigAction);
m_mainContextMenu->addAction(m_repoConfigAction);
m_menuAction = new KAction(this);
m_menuAction->setIcon(KIcon("hg-main"));
m_menuAction->setText(i18nc("@action:inmenu",
"<application>Mercurial</application>"));
m_menuAction->setMenu(m_mainContextMenu);
}
FileViewHgPlugin::~FileViewHgPlugin()
{
}
void FileViewHgPlugin::createHgWrapper() const
{
static bool created = false;
if (created && m_hgWrapper != 0) {
return;
}
created = true;
m_hgWrapper = HgWrapper::instance();
connect(m_hgWrapper,
SIGNAL(primaryOperationFinished(int, QProcess::ExitStatus)),
this, SLOT(slotOperationCompleted(int, QProcess::ExitStatus)));
connect(m_hgWrapper, SIGNAL(primaryOperationError(QProcess::ProcessError)),
this, SLOT(slotOperationError()));
}
QString FileViewHgPlugin::fileName() const
{
return QLatin1String(".hg");
}
bool FileViewHgPlugin::beginRetrieval(const QString &directory)
{
clearMessages();
m_currentDir = directory;
m_versionInfoHash.clear();
//createHgWrapper();
//m_hgWrapper->setCurrentDir(directory);
//m_hgWrapper->getItemVersions(m_versionInfoHash);
if (m_retrievalHgw == 0) {
m_retrievalHgw = new HgWrapper;
}
m_retrievalHgw->setCurrentDir(directory);
m_retrievalHgw->getItemVersions(m_versionInfoHash);
return true;
}
void FileViewHgPlugin::endRetrieval()
{
}
KVersionControlPlugin::ItemVersion FileViewHgPlugin::itemVersion(const KFileItem &item) const
{
//FIXME: When folder is empty or all files within untracked.
const QString itemUrl = item.localPath();
if (item.isDir()) {
QHash<QString, ItemVersion>::const_iterator it
= m_versionInfoHash.constBegin();
while (it != m_versionInfoHash.constEnd()) {
if (it.key().startsWith(itemUrl)) {
const ItemVersion state = m_versionInfoHash.value(it.key());
if (state == LocallyModifiedVersion ||
state == AddedVersion ||
state == RemovedVersion) {
return LocallyModifiedVersion;
}
}
++it;
}
// Making folders with all files within untracked 'Unversioned'
// will disable the context menu there. Will enable recursive
// add however.
QDir dir(item.localPath());
QStringList filesInside = dir.entryList();
foreach (const QString &fileName, filesInside) {
if (fileName == "." || fileName == ".." ) {
continue;
}
KUrl tempUrl(dir.absoluteFilePath(fileName));
KFileItem tempFileItem(KFileItem::Unknown,
KFileItem::Unknown, tempUrl);
if (itemVersion(tempFileItem) == NormalVersion) {
return NormalVersion;
}
}
return UnversionedVersion;
}
if (m_versionInfoHash.contains(itemUrl)) {
return m_versionInfoHash.value(itemUrl);
}
return NormalVersion;
}
QList<QAction*> FileViewHgPlugin::actions(const KFileItemList &items) const
{
//TODO: Make it work with universal context menu when imlpemented
// in dolphin
kDebug() << items.count();
if (items.count() == 1 && items.first().isDir()) {
return directoryContextMenu(m_currentDir);
}
else {
return itemContextMenu(items);
}
return QList<QAction*>();
}
QList<QAction*> FileViewHgPlugin::universalContextMenuActions(const QString &directory) const
{
QList<QAction*> result;
m_universalCurrentDirectory = directory;
result.append(m_createAction);
result.append(m_cloneAction);
return result;
}
QList<QAction*> FileViewHgPlugin::itemContextMenu(const KFileItemList &items) const
{
Q_ASSERT(!items.isEmpty());
clearMessages();
createHgWrapper();
m_hgWrapper->setCurrentDir(m_currentDir);
if (!m_hgWrapper->isBusy()) {
m_contextItems.clear();
foreach (const KFileItem &item, items) {
m_contextItems.append(item);
}
//see which actions should be enabled
int versionedCount = 0;
int addableCount = 0;
int revertableCount = 0;
foreach (const KFileItem &item, items) {
const ItemVersion state = itemVersion(item);
if (state != UnversionedVersion && state != RemovedVersion) {
++versionedCount;
}
if (state == UnversionedVersion ||
state == LocallyModifiedUnstagedVersion) {
++addableCount;
}
if (state == LocallyModifiedVersion ||
state == AddedVersion ||
state == RemovedVersion) {
++revertableCount;
}
}
m_addAction->setEnabled(addableCount == items.count());
m_removeAction->setEnabled(versionedCount == items.count());
m_revertAction->setEnabled(revertableCount == items.count());
m_diffAction->setEnabled(revertableCount == items.count() &&
items.size() == 1);
m_renameAction->setEnabled(items.size() == 1 &&
itemVersion(items.first()) != UnversionedVersion);
}
else {
m_addAction->setEnabled(false);
m_removeAction->setEnabled(false);
m_renameAction->setEnabled(false);
m_revertAction->setEnabled(false);
m_diffAction->setEnabled(false);
}
QList<QAction*> actions;
actions.append(m_addAction);
actions.append(m_removeAction);
actions.append(m_renameAction);
actions.append(m_revertAction);
actions.append(m_diffAction);
return actions;
}
QList<QAction*> FileViewHgPlugin::directoryContextMenu(const QString &directory) const
{
QList<QAction*> actions;
clearMessages();
createHgWrapper();
m_hgWrapper->setCurrentDir(directory);
if (!m_hgWrapper->isBusy()) {
actions.append(m_commitAction);
}
actions.append(m_pushAction);
actions.append(m_pullAction);
actions.append(m_diffAction);
actions.append(m_menuAction);
return actions;
}
void FileViewHgPlugin::addFiles()
{
Q_ASSERT(!m_contextItems.isEmpty());
QString infoMsg = i18nc("@info:status",
"Adding files to <application>Hg</application> repository...");
m_errorMsg = i18nc("@info:status",
"Adding files to <application>Hg</application> repository failed.");
m_operationCompletedMsg = i18nc("@info:status",
"Added files to <application>Hg</application> repository.");
emit infoMessage(infoMsg);
m_hgWrapper->addFiles(m_contextItems);
}
void FileViewHgPlugin::removeFiles()
{
Q_ASSERT(!m_contextItems.isEmpty());
int answer = KMessageBox::questionYesNo(0, i18nc("@message:yesorno",
"Would you like to remove selected files "
"from the repository?"));
if (answer == KMessageBox::No) {
return;
}
QString infoMsg = i18nc("@info:status",
"Removing files from <application>Hg</application> repository...");
m_errorMsg = i18nc("@info:status",
"Removing files from <application>Hg</application> repository failed.");
m_operationCompletedMsg = i18nc("@info:status",
"Removed files from <application>Hg</application> repository.");
emit infoMessage(infoMsg);
m_hgWrapper->removeFiles(m_contextItems);
}
void FileViewHgPlugin::renameFile()
{
Q_ASSERT(m_contextItems.size() == 1);
m_errorMsg = i18nc("@info:status",
"Renaming of file in <application>Hg</application> repository failed.");
m_operationCompletedMsg = i18nc("@info:status",
"Renamed file in <application>Hg</application> repository successfully.");
emit infoMessage(i18nc("@info:status",
"Renaming file in <application>Hg</application> repository."));
HgRenameDialog dialog(m_contextItems.first());
dialog.exec();
m_contextItems.clear();
}
void FileViewHgPlugin::commit()
{
if (m_hgWrapper->isWorkingDirectoryClean()) {
KMessageBox::information(0, i18nc("@message", "No changes for commit!"));
return;
}
//FIXME: Disable emitting of status messages when executing sub tasks.
m_errorMsg = i18nc("@info:status",
"Commit to <application>Hg</application> repository failed.");
m_operationCompletedMsg = i18nc("@info:status",
"Committed to <application>Hg</application> repository.");
emit infoMessage(i18nc("@info:status",
"Commit <application>Hg</application> repository."));
HgCommitDialog dialog;
if (dialog.exec() == QDialog::Accepted) {
emit itemVersionsChanged();
};
}
void FileViewHgPlugin::tag()
{
m_errorMsg = i18nc("@info:status",
"Tag operation in <application>Hg</application> repository failed.");
m_operationCompletedMsg = i18nc("@info:status",
"Tagging operation in <application>Hg</application> repository is successful.");
emit infoMessage(i18nc("@info:status",
"Tagging operation in <application>Hg</application> repository."));
HgTagDialog dialog;
dialog.exec();
}
void FileViewHgPlugin::update()
{
m_errorMsg = i18nc("@info:status",
"Update of <application>Hg</application> working directory failed.");
m_operationCompletedMsg = i18nc("@info:status",
"Update of <application>Hg</application> working directory is successful.");
emit infoMessage(i18nc("@info:status",
"Updating <application>Hg</application> working directory."));
HgUpdateDialog dialog;
dialog.exec();
}
void FileViewHgPlugin::branch()
{
m_errorMsg = i18nc("@info:status",
"Branch operation on <application>Hg</application> repository failed.");
m_operationCompletedMsg = i18nc("@info:status",
"Branch operation on <application>Hg</application> repository completed successfully.");
emit infoMessage(i18nc("@info:status",
"Branch operation on <application>Hg</application> repository."));
HgBranchDialog dialog;
dialog.exec();
}
void FileViewHgPlugin::clone()
{
clearMessages();
HgCloneDialog dialog(m_universalCurrentDirectory);
dialog.exec();
}
void FileViewHgPlugin::create()
{
clearMessages();
HgCreateDialog dialog(m_universalCurrentDirectory);
dialog.exec();
}
void FileViewHgPlugin::global_config()
{
clearMessages();
HgConfigDialog diag(HgConfig::GlobalConfig);
diag.exec();
}
void FileViewHgPlugin::repo_config()
{
clearMessages();
HgConfigDialog diag(HgConfig::RepoConfig);
diag.exec();
}
void FileViewHgPlugin::push()
{
clearMessages();
HgPushDialog diag;
diag.exec();
}
void FileViewHgPlugin::pull()
{
clearMessages();
HgPullDialog diag;
diag.exec();
}
void FileViewHgPlugin::merge()
{
clearMessages();
HgMergeDialog diag;
diag.exec();
}
void FileViewHgPlugin::bundle()
{
clearMessages();
HgBundleDialog diag;
diag.exec();
}
void FileViewHgPlugin::unbundle()
{
clearMessages();
QString bundle = KFileDialog::getOpenFileName();
if (bundle.isEmpty()) {
return;
}
QStringList args;
args << bundle;
if (m_hgWrapper->executeCommandTillFinished(QLatin1String("unbundle"), args)) {
}
else {
KMessageBox::error(0, m_hgWrapper->readAllStandardError());
}
}
void FileViewHgPlugin::importChangesets()
{
clearMessages();
HgImportDialog diag;
diag.exec();
}
void FileViewHgPlugin::exportChangesets()
{
clearMessages();
HgExportDialog diag;
diag.exec();
}
void FileViewHgPlugin::revert()
{
clearMessages();
int answer = KMessageBox::questionYesNo(0, i18nc("@message:yesorno",
"Would you like to revert changes "
"made to selected files?"));
if (answer == KMessageBox::No) {
return;
}
QString infoMsg = i18nc("@info:status",
"Reverting files in <application>Hg</application> repository...");
m_errorMsg = i18nc("@info:status",
"Reverting files in <application>Hg</application> repository failed.");
m_operationCompletedMsg = i18nc("@info:status",
"Reverting files in <application>Hg</application> repository completed successfully.");
emit infoMessage(infoMsg);
m_hgWrapper->revert(m_contextItems);
}
void FileViewHgPlugin::revertAll()
{
int answer = KMessageBox::questionYesNo(0, i18nc("@message:yesorno",
"Would you like to revert all changes "
"made to current working directory?"));
if (answer == KMessageBox::No) {
return;
}
QString infoMsg = i18nc("@info:status",
"Reverting files in <application>Hg</application> repository...");
m_errorMsg = i18nc("@info:status",
"Reverting files in <application>Hg</application> repository failed.");
m_operationCompletedMsg = i18nc("@info:status",
"Reverting files in <application>Hg</application> repository completed successfully.");
emit infoMessage(infoMsg);
m_hgWrapper->revertAll();
}
void FileViewHgPlugin::diff()
{
QString infoMsg = i18nc("@info:status",
"Generating diff for <application>Hg</application> repository...");
m_errorMsg = i18nc("@info:status",
"Could not get <application>Hg</application> repository diff.");
m_operationCompletedMsg = i18nc("@info:status",
"Generated <application>Hg</application> diff successfully.");
emit infoMessage(infoMsg);
QStringList args;
args << QLatin1String("--config");
args << QLatin1String("extensions.hgext.extdiff=");
args << QLatin1String("-p");
args << this->visualDiffExecPath();
if (m_contextItems.length() == 1) {
args << m_contextItems.takeFirst().localPath();
}
m_hgWrapper->executeCommand(QLatin1String("extdiff"), args);
}
void FileViewHgPlugin::serve()
{
clearMessages();
HgServeDialog diag;
diag.exec();
}
void FileViewHgPlugin::backout()
{
clearMessages();
m_hgWrapper = HgWrapper::instance();
if (!m_hgWrapper->isWorkingDirectoryClean()) {
KMessageBox::error(0, i18nc("@message:error",
"abort: Uncommitted changes in working directory!"));
return;
}
HgBackoutDialog diag;
diag.exec();
}
void FileViewHgPlugin::rollback()
{
// execute a dry run rollback first to see if there is anything to
// be rolled back, or check what will be rolled back
if (!m_hgWrapper->rollback(true)) {
KMessageBox::error(0, i18nc("@info:message", "No rollback "
"information available!"));
return;
}
// get what will be rolled back
QString lastTransaction = m_hgWrapper->readAllStandardOutput();
int cutOfFrom = lastTransaction.indexOf(QRegExp("\\d"));
lastTransaction = lastTransaction.mid(cutOfFrom);
// ask
int answer = KMessageBox::questionYesNo(0, i18nc("@message:yesorno",
"Would you like to rollback last transaction?")
+ "\nrevision: " + lastTransaction);
if (answer == KMessageBox::No) {
return;
}
QString infoMsg = i18nc("@info:status",
"Executing Rollback <application>Hg</application> repository...");
m_errorMsg = i18nc("@info:status",
"Rollback of <application>Hg</application> repository failed.");
m_operationCompletedMsg = i18nc("@info:status",
"Rollback of <application>Hg</application> repository completed successfully.");
emit infoMessage(infoMsg);
m_hgWrapper->rollback();
KMessageBox::information(0, m_hgWrapper->readAllStandardOutput());
emit itemVersionsChanged();
}
void FileViewHgPlugin::slotOperationCompleted(int exitCode, QProcess::ExitStatus exitStatus)
{
if ((exitStatus != QProcess::NormalExit) || (exitCode != 0)) {
emit errorMessage(m_errorMsg);
}
else {
m_contextItems.clear();
emit operationCompletedMessage(m_operationCompletedMsg);
emit itemVersionsChanged();
}
}
void FileViewHgPlugin::slotOperationError()
{
m_contextItems.clear();
emit errorMessage(m_errorMsg);
}
void FileViewHgPlugin::clearMessages() const
{
m_operationCompletedMsg.clear();
m_errorMsg.clear();
}
QString FileViewHgPlugin::visualDiffExecPath()
{
KUrl url = KUrl::fromPath(QDir::homePath());
url.addPath(".dolphin-hg");
KConfig config(url.path(), KConfig::SimpleConfig);
KConfigGroup group(&config, QLatin1String("diff"));
QString result = group.readEntry(QLatin1String("exec"), QString()).trimmed();
if (result.length() > 0) {
return result;
}
KService::List services = KMimeTypeTrader::self()->query("text/x-diff");
return services.first()->exec().split(' ').takeFirst();
}
#include "moc_fileviewhgplugin.cpp"