diff --git a/src/plugins/mercurial/Mercurial.pluginspec b/src/plugins/mercurial/Mercurial.pluginspec new file mode 100644 index 0000000000000000000000000000000000000000..cc7548da31b557cccf7992be844e2efb089bc92d --- /dev/null +++ b/src/plugins/mercurial/Mercurial.pluginspec @@ -0,0 +1,27 @@ +<plugin name="Mercurial" version="1.2.91" compatVersion="1.2.91"> + <vendor>Brian McGillion</vendor> + <copyright>(C) 2008-2009 Brian McGillion</copyright> + <license> +Commercial Usage + +Licensees holding valid Qt Commercial licenses may use this plugin in +accordance with the Qt Commercial License Agreement provided with the +Software or, alternatively, in accordance with the terms contained in +a written agreement between you and Nokia. + +GNU Lesser General Public License Usage + +Alternatively, this plugin may be used under the terms of the GNU Lesser +General Public License version 2.1 as published by the Free Software +Foundation. Please review the following information to +ensure the GNU Lesser General Public License version 2.1 requirements +will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.</license> + <description>Mercurial integration.</description> + <url>http://www.qtsoftware.com</url> + <dependencyList> + <dependency name="TextEditor" version="1.2.91"/> + <dependency name="ProjectExplorer" version="1.2.91"/> + <dependency name="Core" version="1.2.91"/> + <dependency name="VCSBase" version="1.2.91"/> + </dependencyList> +</plugin> diff --git a/src/plugins/mercurial/annotationhighlighter.cpp b/src/plugins/mercurial/annotationhighlighter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1ac75327dbc933c8a2a99840d1ebc20a085a723f --- /dev/null +++ b/src/plugins/mercurial/annotationhighlighter.cpp @@ -0,0 +1,48 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "annotationhighlighter.h" +#include "constants.h" + +using namespace Mercurial::Internal; +using namespace Mercurial; + +MercurialAnnotationHighlighter::MercurialAnnotationHighlighter(const ChangeNumbers &changeNumbers, + QTextDocument *document) + : VCSBase::BaseAnnotationHighlighter(changeNumbers, document), + changeset(Constants::CHANGESETID12) +{ +} + +QString MercurialAnnotationHighlighter::changeNumber(const QString &block) const +{ + if (changeset.indexIn(block) != -1) + return changeset.cap(1); + return QString(); +} diff --git a/src/plugins/mercurial/annotationhighlighter.h b/src/plugins/mercurial/annotationhighlighter.h new file mode 100644 index 0000000000000000000000000000000000000000..7114e5b3a8d67b6f294c7dafae08d21a9f714bd5 --- /dev/null +++ b/src/plugins/mercurial/annotationhighlighter.h @@ -0,0 +1,51 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef ANNOTATIONHIGHLIGHTER_H +#define ANNOTATIONHIGHLIGHTER_H + +#include <vcsbase/baseannotationhighlighter.h> + +namespace Mercurial { +namespace Internal { + +class MercurialAnnotationHighlighter : public VCSBase::BaseAnnotationHighlighter +{ +public: + explicit MercurialAnnotationHighlighter(const ChangeNumbers &changeNumbers, + QTextDocument *document = 0); + +private: + virtual QString changeNumber(const QString &block) const; + QRegExp changeset; +}; + +} //namespace Internal +}// namespace Mercurial +#endif // ANNOTATIONHIGHLIGHTER_H diff --git a/src/plugins/mercurial/clonewizard.cpp b/src/plugins/mercurial/clonewizard.cpp new file mode 100644 index 0000000000000000000000000000000000000000..da6ac7f0462b9aaf16e85aeed7d5bbc4f182ec8a --- /dev/null +++ b/src/plugins/mercurial/clonewizard.cpp @@ -0,0 +1,88 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "clonewizard.h" +#include "clonewizardpage.h" +#include "mercurialplugin.h" +#include "mercurialsettings.h" + +#include <QtCore/QDebug> + +using namespace Mercurial::Internal; + +CloneWizard::CloneWizard(QObject *parent) + : VCSBase::BaseCheckoutWizard(parent), + m_icon(QIcon(":/mercurial/images/hg.png")) +{ +} + +QIcon CloneWizard::icon() const +{ + return m_icon; +} + +QString CloneWizard::description() const +{ + return tr("Clone a Mercurial repository"); +} + +QString CloneWizard::name() const +{ + return tr("Mercurial Clone"); +} + +QList<QWizardPage*> CloneWizard::createParameterPages(const QString &path) +{ + QList<QWizardPage*> wizardPageList; + CloneWizardPage *page = new CloneWizardPage; + page->setPath(path); + wizardPageList.push_back(page); + return wizardPageList; +} + +QSharedPointer<VCSBase::AbstractCheckoutJob> CloneWizard::createJob(const QList<QWizardPage *> ¶meterPages, + QString *checkoutPath) +{ + const CloneWizardPage *page = qobject_cast<const CloneWizardPage *>(parameterPages.front()); + + if (!page) + return QSharedPointer<VCSBase::AbstractCheckoutJob>(); + + MercurialSettings *settings = MercurialPlugin::instance()->settings(); + + QStringList args = settings->standardArguments(); + QString path = page->path(); + QString directory = page->directory(); + + args << "clone" << page->repository() << directory; + *checkoutPath = path + "/" + directory; + + return QSharedPointer<VCSBase::AbstractCheckoutJob>(new VCSBase::ProcessCheckoutJob(settings->binary(), + args, path)); +} diff --git a/src/plugins/mercurial/clonewizard.h b/src/plugins/mercurial/clonewizard.h new file mode 100644 index 0000000000000000000000000000000000000000..873d57896f130f965c7cdeff15ce206a6ae468ae --- /dev/null +++ b/src/plugins/mercurial/clonewizard.h @@ -0,0 +1,62 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef CLONEWIZARD_H +#define CLONEWIZARD_H + +#include <vcsbase/basecheckoutwizard.h> +#include <vcsbase/checkoutjobs.h> + +#include <QtGui/QIcon> + +namespace Mercurial { +namespace Internal { + +class CloneWizard : public VCSBase::BaseCheckoutWizard +{ +public: + CloneWizard(QObject *parent = 0); + + QIcon icon() const; + QString description() const; + QString name() const; + +protected: + QList<QWizardPage *> createParameterPages(const QString &path); + QSharedPointer<VCSBase::AbstractCheckoutJob> createJob(const QList<QWizardPage *> ¶meterPages, + QString *checkoutPath); + +private: + QIcon m_icon; +}; + +} //namespace Internal +} //namespace Mercurial + +#endif // CLONEWIZARD_H diff --git a/src/plugins/mercurial/clonewizardpage.cpp b/src/plugins/mercurial/clonewizardpage.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d100962c8d9ee51c203f7322da3a607d62cee58d --- /dev/null +++ b/src/plugins/mercurial/clonewizardpage.cpp @@ -0,0 +1,50 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "clonewizardpage.h" + +using namespace Mercurial::Internal; + +CloneWizardPage::CloneWizardPage(QWidget *parent) + : VCSBase::BaseCheckoutWizardPage(parent) +{ + setRepositoryLabel("Clone URL:"); +} + +QString CloneWizardPage::directoryFromRepository(const QString &repository) const +{ + //mercruial repositories are generally of the form protocol://repositoryUrl/repository/ + //we are just looking for repository. + QString repo = repository.trimmed(); + if (repo.endsWith('/')) + repo = repo.remove(-1, 1); + + //Take the basename or the repository url + return repo.mid(repo.lastIndexOf('/') + 1); +} diff --git a/src/plugins/mercurial/clonewizardpage.h b/src/plugins/mercurial/clonewizardpage.h new file mode 100644 index 0000000000000000000000000000000000000000..b28b121a2c70c9444d47b313c5321c1a710bd757 --- /dev/null +++ b/src/plugins/mercurial/clonewizardpage.h @@ -0,0 +1,51 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef CLONEWIZARDPAGE_H +#define CLONEWIZARDPAGE_H + +#include <vcsbase/basecheckoutwizardpage.h> + +namespace Mercurial { +namespace Internal { + +class CloneWizardPage : public VCSBase::BaseCheckoutWizardPage +{ + Q_OBJECT +public: + CloneWizardPage(QWidget *parent = 0); + +protected: + QString directoryFromRepository(const QString &rrepository) const; +}; + +} //namespace Internal +} //namespace Mercurial + +#endif // CLONEWIZARDPAGE_H diff --git a/src/plugins/mercurial/commiteditor.cpp b/src/plugins/mercurial/commiteditor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c7667ff131b9c9a92130e3fee15ff1806a2aad4e --- /dev/null +++ b/src/plugins/mercurial/commiteditor.cpp @@ -0,0 +1,97 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "commiteditor.h" +#include "mercurialcommitwidget.h" + +#include <vcsbase/submitfilemodel.h> + +#include <QtCore/QDebug> + +#include <QDir> //TODO REMOVE WHEN BASE FILE CHANGES ARE PULLED + +using namespace Mercurial::Internal; + +CommitEditor::CommitEditor(const VCSBase::VCSBaseSubmitEditorParameters *parameters, QWidget *parent) + : VCSBase::VCSBaseSubmitEditor(parameters, new MercurialCommitWidget(parent)), + fileModel(0) +{ + setDisplayName(tr("Commit Editor")); +} + +MercurialCommitWidget *CommitEditor::commitWidget() +{ + return static_cast<MercurialCommitWidget *>(widget()); +} + +void CommitEditor::setFields(const QFileInfo &repositoryRoot, const QString &branch, + const QString &userName, const QString &email, + const QList<QPair<QString, QString> > &repoStatus) +{ + MercurialCommitWidget *mercurialWidget = commitWidget(); + if (!mercurialWidget) + return; + + mercurialWidget->setFields(repositoryRoot.absoluteFilePath(), branch, userName, email); + + fileModel = new VCSBase::SubmitFileModel(this); + + //TODO Messy tidy this up + typedef QPair<QString, QString> PAIR; + QStringList shouldTrack; + + foreach (PAIR status, repoStatus) { + if (status.first == "Untracked") + shouldTrack.append(status.second); + else + fileModel->addFile(status.second, status.first, false); + } + + VCSBase::VCSBaseSubmitEditor::filterUntrackedFilesOfProject(repositoryRoot.absoluteFilePath(), + &shouldTrack); + + foreach (QString track, shouldTrack) { + foreach (PAIR status, repoStatus) { + if (status.second == track) + fileModel->addFile(status.second, status.first, false); + } + } + + setFileModel(fileModel); +} + +QString CommitEditor::committerInfo() +{ + return commitWidget()->committer(); +} + +QString CommitEditor::repoRoot() +{ + return commitWidget()->repoRoot(); +} diff --git a/src/plugins/mercurial/commiteditor.h b/src/plugins/mercurial/commiteditor.h new file mode 100644 index 0000000000000000000000000000000000000000..0fa3eb78e4e1c22c4c6e601a783adbd06942b6af --- /dev/null +++ b/src/plugins/mercurial/commiteditor.h @@ -0,0 +1,69 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef COMMITEDITOR_H +#define COMMITEDITOR_H + +#include <vcsbase/vcsbasesubmiteditor.h> + +#include <QtCore/QFileInfo> + +namespace VCSBase { +class SubmitFileModel; +} + +namespace Mercurial { +namespace Internal { + +class MercurialCommitWidget; + +class CommitEditor : public VCSBase::VCSBaseSubmitEditor +{ + Q_OBJECT +public: + explicit CommitEditor(const VCSBase::VCSBaseSubmitEditorParameters *parameters, + QWidget *parent); + + void setFields(const QFileInfo &repositoryRoot, const QString &branch, + const QString &userName, const QString &email, + const QList<QPair<QString, QString> > &repoStatus); + + QString committerInfo(); + QString repoRoot(); + + +private: + inline MercurialCommitWidget *commitWidget(); + VCSBase::SubmitFileModel *fileModel; + +}; + +} +} +#endif // COMMITEDITOR_H diff --git a/src/plugins/mercurial/constants.h b/src/plugins/mercurial/constants.h new file mode 100644 index 0000000000000000000000000000000000000000..d623f79f678a7a86de94ed07cbc4174ebb02e52d --- /dev/null +++ b/src/plugins/mercurial/constants.h @@ -0,0 +1,132 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef CONSTANTS_H +#define CONSTANTS_H + +namespace Mercurial { +namespace Constants { + +enum { debug = 1 }; +const char * const MERCURIAL = "mercurial"; +const char * const MECURIALREPO = ".hg"; +const char * const MERCURIALDEFAULT = "hg"; + +//options page items +const char * const MERCURIALPATH = "Mercurial_Path"; +const char * const MERCURIALUSERNAME = "Mercurial_Username"; +const char * const MERCURIALEMAIL = "Mercurial_Email"; +const char * const MERCURIALLOGCOUNT = "Mercurial_LogCount"; +const char * const MERCURIALTIMEOUT = "Mercurial_Timeout"; +const char * const MERCURIALPROMPTSUBMIT = "Mercurial_PromptOnSubmit"; + +//changeset identifiers +const char * const CHANGESETID12 = " ([a-f0-9]{12,12}) "; //match 12 hex chars and capture +const char * const CHANGESETID40 = " ([a-f0-9]{40,40}) "; +const char * const CHANGEIDEXACT12 = "[a-f0-9]{12,12}"; //match 12 hex chars a +const char * const CHANGEIDEXACT40 = "[a-f0-9]{40,40}"; +const char * const DIFFIDENTIFIER = "^[-+]{3,3} [ab]{1,1}.*"; // match e.g. +++ b/filename +//Errors +const char * const ERRORSTARTING = "Unable to start Mercurial Process"; +const char * const TIMEDOUT = "Timed out waiting for Mercurail Process to Finish"; + +//BaseEditorParameters +const char * const COMMANDLOG = "Mercurial Command Log Editor"; +const char * const COMMANDAPP = "application/vnd.nokia.text.scs_mercurial_commandlog"; +const char * const COMMANDEXT = "vcsMercurialCommand"; + +const char * const FILELOG = "Mercurial File Log Editor"; +const char * const LOGAPP = "application/vnd.nokia.text.scs_mercurial_log"; +const char * const LOGEXT = "vcsMercurialLog"; + +const char * const ANNOTATELOG = "Mercurial Annotation Editor"; +const char * const ANNOTATEAPP = "application/vnd.nokia.text.scs_mercurial_annotatelog"; +const char * const ANNOTATEEXT = "vcsMercurialAnnotate"; + +const char * const DIFFLOG = "Mercurial Diff Editor"; +const char * const DIFFAPP = "text/x-patch"; +const char * const DIFFEXT = "diff"; + +//SubmitEditorParameters +const char * const COMMITKIND = "Mercurial Commit Log Editor"; +const char * const COMMITMIMETYPE = "application/vnd.nokia.text.scs_mercurial_commitlog"; + +#ifndef Q_WS_MAC +const char * const MODIFIER = "Alt+"; +const char * const MENUKEY = "Alt+H, "; +#else +const char * const MODIFIER = "Meta+"; +const char * const MENUKEY = "Meta+H, "; +#endif + +//menu items +//File menu actions +const char * const ANNOTATE = "Mercurial.Annotate"; +const char * const DIFF = "Mercurial.DiffSingleFile"; +const char * const LOG = "Mercurial.LogSingleFile"; +const char * const REVERT = "Mercurial.RevertSingleFile"; +const char * const STATUS = "Mercurial.Status"; + +//directory menu Actions +const char * const DIFFMULTI = "Mercurial.Action.DiffMulti"; +const char * const REVERTMULTI = "Mercurial.Action.RevertMulti"; +const char * const STATUSMULTI = "Mercurial.Action.StatusMulti"; +const char * const LOGMULTI = "Mercurial.Action.Logmulti"; + +//repository menu actions +const char * const PULL = "Mercurial.Action.Pull"; +const char * const PUSH = "Mercurial.Action.Push"; +const char * const UPDATE = "Mercurial.Action.Update"; +const char * const IMPORT = "Mercurial.Action.Import"; +const char * const INCOMING = "Mercurial.Action.Incoming"; +const char * const OUTGOING = "Mercurial.Action.Outgoing"; +const char * const COMMIT = "Mercurial.Action.Commit"; + +//Repository Management +const char * const MERGE = "Mercurial.Action.Merge"; +const char * const BRANCH = "Mercurial.Action.Branch"; +const char * const HEADS = "Mercurial.Action.Heads"; +const char * const PARENTS = "Mercurial.Action.Parents"; +const char * const TAGS = "Mercurial.Action.Tags"; +const char * const TIP = "Mercurial.Action.TIP"; +const char * const PATHS = "Mercurial.Action.Paths"; + +//Less commonly used menu actions +const char * const CLONE = "Mercurial.Action.Clone"; +const char * const INIT = "Mercurial.Action.Init"; +const char * const SERVE = "Mercurial.Action.Serve"; + +//submit editor actions +const char * const COMMITEDITOR = "Mercurial.Action.Editor.Commit"; +const char * const DIFFEDITOR = "Mercurial.Action.Editor.Diff"; + +} // namespace Constants +} // namespace mercurial + +#endif // CONSTANTS_H diff --git a/src/plugins/mercurial/images/hg.png b/src/plugins/mercurial/images/hg.png new file mode 100644 index 0000000000000000000000000000000000000000..59a238c222649fb1c1e4139f74ae053076a30a4c Binary files /dev/null and b/src/plugins/mercurial/images/hg.png differ diff --git a/src/plugins/mercurial/mercurial.pro b/src/plugins/mercurial/mercurial.pro new file mode 100644 index 0000000000000000000000000000000000000000..f1cf647adef2136702562ed7d8bd69da3d8416b1 --- /dev/null +++ b/src/plugins/mercurial/mercurial.pro @@ -0,0 +1,41 @@ +TARGET = Mercurial +TEMPLATE = lib +include(../../qtcreatorplugin.pri) +include(mercurial_dependencies.pri) +SOURCES += mercurialplugin.cpp \ + optionspage.cpp \ + mercurialoutputwindow.cpp \ + mercurialcontrol.cpp \ + mercurialclient.cpp \ + mercurialjobrunner.cpp \ + annotationhighlighter.cpp \ + mercurialeditor.cpp \ + revertdialog.cpp \ + srcdestdialog.cpp \ + mercurialcommitwidget.cpp \ + commiteditor.cpp \ + clonewizardpage.cpp \ + clonewizard.cpp \ + mercurialsettings.cpp +HEADERS += mercurialplugin.h \ + constants.h \ + optionspage.h \ + mercurialoutputwindow.h \ + mercurialcontrol.h \ + mercurialclient.h \ + mercurialjobrunner.h \ + annotationhighlighter.h \ + mercurialeditor.h \ + revertdialog.h \ + srcdestdialog.h \ + mercurialcommitwidget.h \ + commiteditor.h \ + clonewizardpage.h \ + clonewizard.h \ + mercurialsettings.h +OTHER_FILES += Mercurial.pluginspec +FORMS += optionspage.ui \ + revertdialog.ui \ + srcdestdialog.ui \ + mercurialcommitpanel.ui +RESOURCES += mercurial.qrc diff --git a/src/plugins/mercurial/mercurial.qrc b/src/plugins/mercurial/mercurial.qrc new file mode 100644 index 0000000000000000000000000000000000000000..b001b7e60b57430ad8a91fc7bc552bd12e4c03f7 --- /dev/null +++ b/src/plugins/mercurial/mercurial.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/mercurial" > + <file>images/hg.png</file> + </qresource> +</RCC> diff --git a/src/plugins/mercurial/mercurial_dependencies.pri b/src/plugins/mercurial/mercurial_dependencies.pri new file mode 100644 index 0000000000000000000000000000000000000000..9e7c28e9e1af2cfb121ef3f697d7ff6b0f80b8ec --- /dev/null +++ b/src/plugins/mercurial/mercurial_dependencies.pri @@ -0,0 +1,5 @@ +include(../../plugins/projectexplorer/projectexplorer.pri) +include(../../plugins/texteditor/texteditor.pri) +include(../../plugins/coreplugin/coreplugin.pri) +include(../../plugins/vcsbase/vcsbase.pri) +include(../../libs/utils/utils.pri) diff --git a/src/plugins/mercurial/mercurialclient.cpp b/src/plugins/mercurial/mercurialclient.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d0b67f021af981cb762c8268a6e708fab8c17152 --- /dev/null +++ b/src/plugins/mercurial/mercurialclient.cpp @@ -0,0 +1,443 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "mercurialclient.h" +#include "mercurialjobrunner.h" +#include "constants.h" +#include "mercurialsettings.h" +#include "mercurialplugin.h" + +#include <coreplugin/icore.h> +#include <coreplugin/editormanager/editormanager.h> + +#include <utils/qtcassert.h> +#include <vcsbase/vcsbaseeditor.h> + +#include <QtCore/QStringList> +#include <QtCore/QSharedPointer> +#include <QtCore/QDir> +#include <QtCore/QProcess> +#include <QtCore/QTextCodec> +#include <QtCore/QtDebug> + +using namespace Mercurial::Internal; +using namespace Mercurial; + +inline Core::IEditor* locateEditor(const Core::ICore *core, const char *property, const QString &entry) +{ + foreach (Core::IEditor *ed, core->editorManager()->openedEditors()) + if (ed->file()->property(property).toString() == entry) + return ed; + return 0; +} + +MercurialClient::MercurialClient() + : core(Core::ICore::instance()) +{ + jobManager = new MercurialJobRunner(); + jobManager->start(); +} + +MercurialClient::~MercurialClient() +{ + if (jobManager) { + delete jobManager; + jobManager = 0; + } +} + +bool MercurialClient::add(const QString &filename) +{ + QFileInfo file(filename); + QStringList args; + args << "add" << file.absoluteFilePath(); + + return hgProcessSync(file, args); +} + +bool MercurialClient::remove(const QString &filename) +{ + QFileInfo file(filename); + QStringList args; + args << "remove" << file.absoluteFilePath(); + + return hgProcessSync(file, args); +} + +bool MercurialClient::manifestSync(const QString &filename) +{ + QFileInfo file(filename); + QStringList args("manifest"); + + QByteArray output; + hgProcessSync(file, args, &output); + + QStringList files = QString::fromLocal8Bit(output).split('\n'); + + foreach (QString fileName, files) { + QFileInfo managedFile(filename); + if (file == managedFile) + return true; + } + + return false; +} + +bool MercurialClient::hgProcessSync(const QFileInfo &file, const QStringList &args, + QByteArray *output) const +{ + QProcess hgProcess; + hgProcess.setWorkingDirectory(file.isDir() ? file.absoluteFilePath() : file.absolutePath()); + + MercurialSettings *settings = MercurialPlugin::instance()->settings(); + QStringList arguments = settings->standardArguments(); + arguments << args; + + hgProcess.start(settings->binary(), arguments); + + if (!hgProcess.waitForStarted()) + return false; + + hgProcess.closeWriteChannel(); + + if (!hgProcess.waitForFinished(settings->timeout())) { + hgProcess.terminate(); + return false; + } + + if ((hgProcess.exitStatus() == QProcess::NormalExit) && (hgProcess.exitCode() == 0)) { + if (output) + *output = hgProcess.readAllStandardOutput(); + return true; + } + + return false; +} + +QString MercurialClient::branchQuerySync(const QFileInfo &repositoryRoot) +{ + QByteArray output; + if (hgProcessSync(repositoryRoot, QStringList("branch"), &output)) + return QTextCodec::codecForLocale()->toUnicode(output).trimmed(); + + return QString("Unknown Branch"); +} + +void MercurialClient::annotate(const QFileInfo &file) +{ + QStringList args; + args << "annotate" << "-u" << "-c" << "-d" << file.absoluteFilePath(); + + const QString kind = Constants::ANNOTATELOG; + const QString title = tr("Hg Annotate %1").arg(file.fileName()); + + VCSBase::VCSBaseEditor *editor = createVCSEditor(kind, title, file.absolutePath(), true, + "annotate", file.absoluteFilePath()); + + QSharedPointer<HgTask> job(new HgTask(file.absolutePath(), args, editor)); + jobManager->enqueueJob(job); +} + +void MercurialClient::diff(const QFileInfo &fileOrDir) +{ + QStringList args; + QString id; + QString workingPath; + + args << "diff" << "-g" << "-p" << "-U 8"; + + if (!fileOrDir.isDir()) { + args.append(fileOrDir.absoluteFilePath()); + id = fileOrDir.absoluteFilePath(); + workingPath = fileOrDir.absolutePath(); + } else { + id = MercurialPlugin::instance()->currentProjectName(); + workingPath = fileOrDir.absoluteFilePath(); + } + + const QString kind = Constants::DIFFLOG; + const QString title = tr("Hg diff %1").arg(fileOrDir.isDir() ? id : fileOrDir.fileName()); + + VCSBase::VCSBaseEditor *editor = createVCSEditor(kind, title, workingPath, true, + "diff", id); + + QSharedPointer<HgTask> job(new HgTask(workingPath, args, editor)); + jobManager->enqueueJob(job); +} + +void MercurialClient::log(const QFileInfo &fileOrDir) +{ + QStringList args; + QString id; + QString workingDir; + + args << "log"; + + if (!fileOrDir.isDir()) { + args.append(fileOrDir.absoluteFilePath()); + id = fileOrDir.absoluteFilePath(); + workingDir = fileOrDir.absolutePath(); + } else { + id = MercurialPlugin::instance()->currentProjectName(); + workingDir = fileOrDir.absoluteFilePath(); + } + + const QString kind = Constants::FILELOG; + const QString title = tr("Hg log %1").arg(fileOrDir.isDir() ? id : fileOrDir.fileName()); + + VCSBase::VCSBaseEditor *editor = createVCSEditor(kind, title, workingDir, true, + "log", id); + + QSharedPointer<HgTask> job(new HgTask(workingDir, args, editor)); + jobManager->enqueueJob(job); +} + +void MercurialClient::revert(const QFileInfo &fileOrDir, const QString &revision) +{ + QStringList args; + args << "revert"; + + if (!revision.isEmpty()) + args << "-r" << revision; + if (!fileOrDir.isDir()) + args.append(fileOrDir.absoluteFilePath()); + else + args.append("--all"); + + QSharedPointer<HgTask> job(new HgTask(fileOrDir.isDir() ? fileOrDir.absoluteFilePath() : + fileOrDir.absolutePath(), args, false)); + jobManager->enqueueJob(job); +} + +void MercurialClient::status(const QFileInfo &fileOrDir) +{ + QStringList args; + args << "status"; + if (!fileOrDir.isDir()) + args.append(fileOrDir.absoluteFilePath()); + + QSharedPointer<HgTask> job(new HgTask(fileOrDir.isDir() ? fileOrDir.absoluteFilePath() : + fileOrDir.absolutePath(), args, false)); + jobManager->enqueueJob(job); +} + +void MercurialClient::statusWithSignal(const QFileInfo &repositoryRoot) +{ + QStringList args; + args << "status"; + + QSharedPointer<HgTask> job(new HgTask(repositoryRoot.absoluteFilePath(), args, true)); + connect(job.data(), SIGNAL(rawData(const QByteArray &)), + this, SLOT(statusParser(const QByteArray &))); + + jobManager->enqueueJob(job); +} + +void MercurialClient::statusParser(const QByteArray &data) +{ + QList<QPair<QString, QString> > statusList; + + QStringList rawStatusList = QTextCodec::codecForLocale()->toUnicode(data).split(QLatin1Char('\n')); + + foreach (QString string, rawStatusList) { + QPair<QString, QString> status; + + if (string.startsWith('M')) + status.first = "Modified"; + else if (string.startsWith('A')) + status.first = "Added"; + else if (string.startsWith('R')) + status.first = "Removed"; + else if (string.startsWith('!')) + status.first = "Deleted"; + else if (string.startsWith('?')) + status.first = "Untracked"; + else + continue; + + //the status string should be similar to "M file_with_Changes" + //so just should take the file name part and store it + status.second = string.mid(2); + statusList.append(status); + } + + emit parsedStatus(statusList); +} + +void MercurialClient::import(const QFileInfo &repositoryRoot, const QStringList &files) +{ + QStringList args; + args << "import" << "--no-commit"; + + foreach (QString file, files) + args.append(file); + + QSharedPointer<HgTask> job(new HgTask(repositoryRoot.absoluteFilePath(), args, false)); + jobManager->enqueueJob(job); +} + +void MercurialClient::pull(const QFileInfo &repositoryRoot, const QString &repository) +{ + QStringList args; + args << "pull"; + if (!repository.isEmpty()) + args.append(repository); + + QSharedPointer<HgTask> job(new HgTask(repositoryRoot.absoluteFilePath(), args, false)); + jobManager->enqueueJob(job); +} + +void MercurialClient::push(const QFileInfo &repositoryRoot, const QString &repository) +{ + QStringList args; + args << "push"; + if (!repository.isEmpty()) + args.append(repository); + + QSharedPointer<HgTask> job(new HgTask(repositoryRoot.absoluteFilePath(), args, false)); + jobManager->enqueueJob(job); +} + +void MercurialClient::incoming(const QFileInfo &repositoryRoot, const QString &repository) +{ + QStringList args; + args << "incoming" << "-g" << "-p"; + if (!repository.isEmpty()) + args.append(repository); + + QString id = MercurialPlugin::instance()->currentProjectName(); + + const QString kind = Constants::DIFFLOG; + const QString title = tr("Hg incoming %1").arg(id); + + VCSBase::VCSBaseEditor *editor = createVCSEditor(kind, title, repositoryRoot.absoluteFilePath(), + true, "incoming", id); + + QSharedPointer<HgTask> job(new HgTask(repositoryRoot.absoluteFilePath(), args, editor)); + jobManager->enqueueJob(job); +} + +void MercurialClient::outgoing(const QFileInfo &repositoryRoot) +{ + QStringList args; + args << "outgoing" << "-g" << "-p"; + + QString id = MercurialPlugin::instance()->currentProjectName(); + + const QString kind = Constants::DIFFLOG; + const QString title = tr("Hg outgoing %1").arg(id); + + VCSBase::VCSBaseEditor *editor = createVCSEditor(kind, title, repositoryRoot.absoluteFilePath(), true, + "outgoing", id); + + QSharedPointer<HgTask> job(new HgTask(repositoryRoot.absoluteFilePath(), args, editor)); + jobManager->enqueueJob(job); +} + +void MercurialClient::view(const QString &source, const QString &id) +{ + QStringList args; + args << "log" << "-p" << "-g" << "-r" << id; + + const QString kind = Constants::DIFFLOG; + const QString title = tr("Hg log %1").arg(id); + + VCSBase::VCSBaseEditor *editor = createVCSEditor(kind, title, source, + true, "view", id); + + QSharedPointer<HgTask> job(new HgTask(source, args, editor)); + jobManager->enqueueJob(job); +} + +void MercurialClient::update(const QFileInfo &repositoryRoot, const QString &revision) +{ + QStringList args; + + args << "update"; + if (!revision.isEmpty()) + args << revision; + + QSharedPointer<HgTask> job(new HgTask(repositoryRoot.absoluteFilePath(), args, false)); + jobManager->enqueueJob(job); +} + +void MercurialClient::commit(const QFileInfo &repositoryRoot, const QStringList &files, + const QString &commiterInfo, const QString &commitMessageFile) +{ + QStringList args; + + args << "commit" << "-u" << commiterInfo << "-l" << commitMessageFile << files; + QSharedPointer<HgTask> job(new HgTask(repositoryRoot.absoluteFilePath(), args, false)); + jobManager->enqueueJob(job); +} + +QString MercurialClient::findTopLevelForFile(const QFileInfo &file) +{ + const QString repositoryTopDir = QLatin1String(Constants::MECURIALREPO); + QDir dir = file.isDir() ? QDir(file.absoluteFilePath()) : QDir(file.absolutePath()); + + do { + if (QFileInfo(dir, repositoryTopDir).exists()) + return dir.absolutePath(); + } while (dir.cdUp()); + + return QString(); +} + +void MercurialClient::settingsChanged() +{ + if (jobManager) + jobManager->restart(); +} + +VCSBase::VCSBaseEditor *MercurialClient::createVCSEditor(const QString &kind, QString title, + const QString &source, bool setSourceCodec, + const char *registerDynamicProperty, + const QString &dynamicPropertyValue) const +{ + VCSBase::VCSBaseEditor *baseEditor = 0; + Core::IEditor* outputEditor = locateEditor(core, registerDynamicProperty, dynamicPropertyValue); + if (outputEditor) { + // Exists already + outputEditor->createNew(tr("Working...")); + baseEditor = VCSBase::VCSBaseEditor::getVcsBaseEditor(outputEditor); + QTC_ASSERT(baseEditor, return 0); + } else { + outputEditor = core->editorManager()->openEditorWithContents(kind, &title, tr("Working...")); + outputEditor->file()->setProperty(registerDynamicProperty, dynamicPropertyValue); + baseEditor = VCSBase::VCSBaseEditor::getVcsBaseEditor(outputEditor); + QTC_ASSERT(baseEditor, return 0); + baseEditor->setSource(source); + if (setSourceCodec) + baseEditor->setCodec(VCSBase::VCSBaseEditor::getCodec(source)); + } + + core->editorManager()->activateEditor(outputEditor); + return baseEditor; +} diff --git a/src/plugins/mercurial/mercurialclient.h b/src/plugins/mercurial/mercurialclient.h new file mode 100644 index 0000000000000000000000000000000000000000..6dee6133c7ea20cd7bde6e6391a55ad324ecaf27 --- /dev/null +++ b/src/plugins/mercurial/mercurialclient.h @@ -0,0 +1,104 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MERCURIALCLIENT_H +#define MERCURIALCLIENT_H + +#include <QtCore/QObject> +#include <QtCore/QFileInfo> +#include <QtCore/QByteArray> +#include <QtCore/QPair> + +namespace Core { +class ICore; +} + +namespace VCSBase{ +class VCSBaseEditor; +} + +namespace Mercurial { +namespace Internal { + +class MercurialJobRunner; + +class MercurialClient : public QObject +{ + Q_OBJECT +public: + MercurialClient(); + ~MercurialClient(); + bool add(const QString &fileName); + bool remove(const QString &fileName); + bool manifestSync(const QString &filename); + QString branchQuerySync(const QFileInfo &repositoryRoot); + void annotate(const QFileInfo &file); + void diff(const QFileInfo &fileOrDir); + void log(const QFileInfo &fileOrDir); + void import(const QFileInfo &repositoryRoot, const QStringList &files); + void pull(const QFileInfo &repositoryRoot, const QString &repository); + void push(const QFileInfo &repositoryRoot, const QString &repository); + void incoming(const QFileInfo &repositoryRoot, const QString &repository); + void outgoing(const QFileInfo &repositoryRoot); + void status(const QFileInfo &fileOrDir); + void statusWithSignal(const QFileInfo &fileOrDir); + void revert(const QFileInfo &fileOrDir, const QString &revision); + void update(const QFileInfo &repositoryRoot, const QString &revision); + void commit(const QFileInfo &repositoryRoot, const QStringList &files, + const QString &commiterInfo, const QString &commitMessageFile); + + static QString findTopLevelForFile(const QFileInfo &file); + +signals: + void parsedStatus(const QList<QPair<QString, QString> > &statusList); + +public slots: + void view(const QString &source, const QString &id); + void settingsChanged(); + +private slots: + void statusParser(const QByteArray &data); + +private: + bool hgProcessSync(const QFileInfo &file, const QStringList &args, + QByteArray *output=0) const; + + MercurialJobRunner *jobManager; + Core::ICore *core; + + VCSBase::VCSBaseEditor *createVCSEditor(const QString &kind, QString title, + const QString &source, bool setSourceCodec, + const char *registerDynamicProperty, + const QString &dynamicPropertyValue) const; +}; + +} //namespace Internal +} //namespace Mercurial + +#endif // MERCURIALCLIENT_H diff --git a/src/plugins/mercurial/mercurialcommitpanel.ui b/src/plugins/mercurial/mercurialcommitpanel.ui new file mode 100644 index 0000000000000000000000000000000000000000..eadd4953e0dad1edd0f06ceda9e145db955bd0c6 --- /dev/null +++ b/src/plugins/mercurial/mercurialcommitpanel.ui @@ -0,0 +1,107 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Mercurial::Internal::MercurialCommitPanel</class> + <widget class="QWidget" name="Mercurial::Internal::MercurialCommitPanel"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>374</width> + <height>229</height> + </rect> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="margin"> + <number>0</number> + </property> + <item> + <widget class="QGroupBox" name="infoGroup"> + <property name="title"> + <string>General Information</string> + </property> + <layout class="QFormLayout" name="infoFormLayout"> + <property name="fieldGrowthPolicy"> + <enum>QFormLayout::ExpandingFieldsGrow</enum> + </property> + <item row="0" column="0"> + <widget class="QLabel" name="repositoryLabelLabel"> + <property name="text"> + <string>Repository:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLabel" name="repositoryLabel"> + <property name="text"> + <string>repository</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="branchLabelLabel"> + <property name="text"> + <string>Branch:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLabel" name="branchLabel"> + <property name="text"> + <string>branch</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="editGroup"> + <property name="title"> + <string>Commit Information</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <layout class="QFormLayout" name="formLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="authorLabel"> + <property name="text"> + <string>Author:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="authorLineEdit"/> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="emailLabel"> + <property name="text"> + <string>Email:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLineEdit" name="emailLineEdit"/> + </item> + </layout> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>161</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/src/plugins/mercurial/mercurialcommitwidget.cpp b/src/plugins/mercurial/mercurialcommitwidget.cpp new file mode 100644 index 0000000000000000000000000000000000000000..21e79daa1b18990fad49b4d71ec9603bfa2979ce --- /dev/null +++ b/src/plugins/mercurial/mercurialcommitwidget.cpp @@ -0,0 +1,146 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "mercurialcommitwidget.h" + +#include <texteditor/texteditorsettings.h> +#include <texteditor/fontsettings.h> +#include <texteditor/texteditorconstants.h> + +#include <QtGui/QSyntaxHighlighter> +#include <QtGui/QTextEdit> + +#include <QtCore/QDebug> +#include <QtCore/QRegExp> + +//see the git submit widget for details of the syntax Highlighter + +//TODO Check to see when the Highlighter has been moved to a base class and use that instead + +namespace Mercurial { +namespace Internal { + +// Retrieve the comment char format from the text editor. +static QTextCharFormat commentFormat() +{ + const TextEditor::FontSettings settings = TextEditor::TextEditorSettings::instance()->fontSettings(); + return settings.toTextCharFormat(QLatin1String(TextEditor::Constants::C_COMMENT)); +} + +// Highlighter for Mercurial submit messages. Make the first line bold, indicates +// comments as such (retrieving the format from the text editor) and marks up +// keywords (words in front of a colon as in 'Task: <bla>'). +class MercurialSubmitHighlighter : QSyntaxHighlighter +{ +public: + explicit MercurialSubmitHighlighter(QTextEdit *parent); + virtual void highlightBlock(const QString &text); + +private: + enum State { Header, Comment, Other }; + const QTextCharFormat m_commentFormat; + const QRegExp m_keywordPattern; + const QChar m_hashChar; +}; + +MercurialSubmitHighlighter::MercurialSubmitHighlighter(QTextEdit * parent) : + QSyntaxHighlighter(parent), + m_commentFormat(commentFormat()), + m_keywordPattern(QLatin1String("^\\w+:")), + m_hashChar(QLatin1Char('#')) +{ + Q_ASSERT(m_keywordPattern.isValid()); +} + +void MercurialSubmitHighlighter::highlightBlock(const QString &text) +{ + // figure out current state + State state = Other; + const QTextBlock block = currentBlock(); + if (block.position() == 0) { + state = Header; + } else { + if (text.startsWith(m_hashChar)) + state = Comment; + } + // Apply format. + switch (state) { + case Header: { + QTextCharFormat charFormat = format(0); + charFormat.setFontWeight(QFont::Bold); + setFormat(0, text.size(), charFormat); + } + break; + case Comment: + setFormat(0, text.size(), m_commentFormat); + break; + case Other: + // Format key words ("Task:") italic + if (m_keywordPattern.indexIn(text, 0, QRegExp::CaretAtZero) == 0) { + QTextCharFormat charFormat = format(0); + charFormat.setFontItalic(true); + setFormat(0, m_keywordPattern.matchedLength(), charFormat); + } + break; + } +} + + +MercurialCommitWidget::MercurialCommitWidget(QWidget *parent) : + Core::Utils::SubmitEditorWidget(parent), + mercurialCommitPanel(new QWidget) +{ + mercurialCommitPanelUi.setupUi(mercurialCommitPanel); + insertTopWidget(mercurialCommitPanel); + new MercurialSubmitHighlighter(descriptionEdit()); +} + +void MercurialCommitWidget::setFields(const QString &repositoryRoot, const QString &branch, + const QString &userName, const QString &email) +{ + mercurialCommitPanelUi.repositoryLabel->setText(repositoryRoot); + mercurialCommitPanelUi.branchLabel->setText(branch); + mercurialCommitPanelUi.authorLineEdit->setText(userName); + mercurialCommitPanelUi.emailLineEdit->setText(email); +} + +QString MercurialCommitWidget::committer() +{ + QString user = mercurialCommitPanelUi.authorLineEdit->text() + QLatin1String(" <") + + mercurialCommitPanelUi.emailLineEdit->text() + QLatin1String(">"); + return user; +} + +QString MercurialCommitWidget::repoRoot() +{ + return mercurialCommitPanelUi.repositoryLabel->text(); +} + +} // namespace Internal +} // namespace Mercurial diff --git a/src/plugins/mercurial/mercurialcommitwidget.h b/src/plugins/mercurial/mercurialcommitwidget.h new file mode 100644 index 0000000000000000000000000000000000000000..50cb9858c9b0f721e92249a46f314359756d5d93 --- /dev/null +++ b/src/plugins/mercurial/mercurialcommitwidget.h @@ -0,0 +1,64 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MERCURIALCOMMITWIDGET_H +#define MERCURIALCOMMITWIDGET_H + +#include "ui_mercurialcommitpanel.h" + +#include <utils/submiteditorwidget.h> + +namespace Mercurial { +namespace Internal { + +/*submit editor widget based on git SubmitEditor + Some extra fields have been added to the standard SubmitEditorWidget, + to help to conform to the commit style that is used by both git and Mercurial*/ + +class MercurialCommitWidget : public Core::Utils::SubmitEditorWidget +{ + +public: + explicit MercurialCommitWidget(QWidget *parent = 0); + + void setFields(const QString &repositoryRoot, const QString &branch, + const QString &userName, const QString &email); + + QString committer(); + QString repoRoot(); + +private: + QWidget *mercurialCommitPanel; + Ui::MercurialCommitPanel mercurialCommitPanelUi; +}; + +} // namespace Internal +} // namespace Mercurial + +#endif // MERCURIALCOMMITWIDGET_H diff --git a/src/plugins/mercurial/mercurialcontrol.cpp b/src/plugins/mercurial/mercurialcontrol.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a2303e02000075b08e248430c3762e3c1da130c3 --- /dev/null +++ b/src/plugins/mercurial/mercurialcontrol.cpp @@ -0,0 +1,109 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "mercurialcontrol.h" +#include "mercurialclient.h" + +#include <QtCore/QFileInfo> + +using namespace Mercurial::Internal; + +MercurialControl::MercurialControl(MercurialClient *client) + : mercurialClient(client), + mercurialEnabled(true) +{ +} + +QString MercurialControl::name() const +{ + return tr("Mercurial"); +} + +bool MercurialControl::isEnabled() const +{ + return mercurialEnabled; +} + +void MercurialControl::setEnabled(bool enabled) +{ + if (mercurialEnabled != enabled) { + mercurialEnabled = enabled; + emit enabledChanged(mercurialEnabled); + } +} + +bool MercurialControl::managesDirectory(const QString &directory) const +{ + QFileInfo dir(directory); + return !mercurialClient->findTopLevelForFile(dir).isEmpty(); +} + +QString MercurialControl::findTopLevelForDirectory(const QString &directory) const +{ + QFileInfo dir(directory); + return mercurialClient->findTopLevelForFile(dir); +} + +bool MercurialControl::supportsOperation(Operation operation) const +{ + bool supported = true; + + switch (operation) { + case Core::IVersionControl::AddOperation: + case Core::IVersionControl::DeleteOperation: + break; + case Core::IVersionControl::OpenOperation: + default: + supported = false; + break; + } + + return supported; +} + +bool MercurialControl::vcsOpen(const QString &filename) +{ + Q_UNUSED(filename) + return true; +} + +bool MercurialControl::vcsAdd(const QString &filename) +{ + return mercurialClient->add(filename); +} + +bool MercurialControl::vcsDelete(const QString &filename) +{ + return mercurialClient->remove(filename); +} + +bool MercurialControl::sccManaged(const QString &filename) +{ + return mercurialClient->manifestSync(filename); +} diff --git a/src/plugins/mercurial/mercurialcontrol.h b/src/plugins/mercurial/mercurialcontrol.h new file mode 100644 index 0000000000000000000000000000000000000000..2085a27d77d3c513ae086366dad4a1cdd74a751c --- /dev/null +++ b/src/plugins/mercurial/mercurialcontrol.h @@ -0,0 +1,70 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MERCURIALCONTROL_H +#define MERCURIALCONTROL_H + +#include <coreplugin/iversioncontrol.h> + +namespace Mercurial { +namespace Internal { + +class MercurialClient; + +//Implements just the basics of the Version Control Interface +//MercurialClient handles all the work +class MercurialControl: public Core::IVersionControl +{ + Q_OBJECT +public: + explicit MercurialControl(MercurialClient *mercurialClient); + + QString name() const; + bool isEnabled() const; + void setEnabled(bool enabled); + bool managesDirectory(const QString &filename) const; + QString findTopLevelForDirectory(const QString &directory) const; + bool supportsOperation(Operation operation) const; + bool vcsOpen(const QString &fileName); + bool vcsAdd(const QString &filename); + bool vcsDelete(const QString &filename); + bool sccManaged(const QString &filename); + +signals: + void enabledChanged(bool); + +private: + MercurialClient *mercurialClient; + bool mercurialEnabled; +}; + +} //namespace Internal +} //namespace Mercurial + +#endif // MERCURIALCONTROL_H diff --git a/src/plugins/mercurial/mercurialeditor.cpp b/src/plugins/mercurial/mercurialeditor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4b20c637acabd319eb3ae3367e268155073acec5 --- /dev/null +++ b/src/plugins/mercurial/mercurialeditor.cpp @@ -0,0 +1,114 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "mercurialeditor.h" +#include "annotationhighlighter.h" +#include "constants.h" +#include "mercurialclient.h" + +#include <coreplugin/editormanager/editormanager.h> +#include <vcsbase/diffhighlighter.h> + +#include <QtCore/QSet> +#include <QtCore/QString> +#include <QtGui/QTextCursor> +#include <QtGui/QTextBlock> +#include <QtCore/QDir> +#include <QtCore/QDebug> + +using namespace Mercurial::Internal; +using namespace Mercurial; + +MercurialEditor::MercurialEditor(const VCSBase::VCSBaseEditorParameters *type, QWidget *parent) + : VCSBase::VCSBaseEditor(type, parent), + exactIdentifier12(Constants::CHANGEIDEXACT12), + exactIdentifier40(Constants::CHANGEIDEXACT40), + changesetIdentifier12(Constants::CHANGESETID12), + changesetIdentifier40(Constants::CHANGESETID40), + diffIdentifier(Constants::DIFFIDENTIFIER) +{ +} + +QSet<QString> MercurialEditor::annotationChanges() const +{ + QSet<QString> changes; + const QString data = toPlainText(); + if (data.isEmpty()) + return changes; + + int position = 0; + while ((position = changesetIdentifier12.indexIn(data, position)) != -1) { + changes.insert(changesetIdentifier12.cap(1)); + position += changesetIdentifier12.matchedLength(); + } + + return changes; +} + +QString MercurialEditor::changeUnderCursor(const QTextCursor &cursorIn) const +{ + QTextCursor cursor = cursorIn; + cursor.select(QTextCursor::WordUnderCursor); + if (cursor.hasSelection()) { + const QString change = cursor.selectedText(); + if (exactIdentifier12.exactMatch(change)) + return change; + if (exactIdentifier40.exactMatch(change)) + return change; + } + return QString(); +} + +VCSBase::DiffHighlighter *MercurialEditor::createDiffHighlighter() const +{ + return new VCSBase::DiffHighlighter(diffIdentifier); +} + +VCSBase::BaseAnnotationHighlighter *MercurialEditor::createAnnotationHighlighter(const QSet<QString> &changes) const +{ + return new MercurialAnnotationHighlighter(changes); +} + +QString MercurialEditor::fileNameFromDiffSpecification(const QTextBlock &diffFileSpec) const +{ + QString filechangeId("+++ b/"); + QTextBlock::iterator iterator; + for (iterator = diffFileSpec.begin(); !(iterator.atEnd()); iterator++) { + QTextFragment fragment = iterator.fragment(); + if(fragment.isValid()) { + if (fragment.text().startsWith(filechangeId)) { + QFileInfo sourceFile(source()); + QDir repository(MercurialClient::findTopLevelForFile(sourceFile)); + QString filename = fragment.text().remove(0, filechangeId.size()); + return repository.absoluteFilePath(filename); + } + } + } + return QString(); +} diff --git a/src/plugins/mercurial/mercurialeditor.h b/src/plugins/mercurial/mercurialeditor.h new file mode 100644 index 0000000000000000000000000000000000000000..ac5c3573387164b21c28280da5f6f5ec85229906 --- /dev/null +++ b/src/plugins/mercurial/mercurialeditor.h @@ -0,0 +1,61 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MERCURIALEDITOR_H +#define MERCURIALEDITOR_H + +#include <vcsbase/vcsbaseeditor.h> + +#include <QtCore/QRegExp> + +namespace Mercurial { +namespace Internal { + +class MercurialEditor : public VCSBase::VCSBaseEditor +{ +public: + explicit MercurialEditor(const VCSBase::VCSBaseEditorParameters *type, QWidget *parent); + +private: + virtual QSet<QString> annotationChanges() const; + virtual QString changeUnderCursor(const QTextCursor &cursor) const; + virtual VCSBase::DiffHighlighter *createDiffHighlighter() const; + virtual VCSBase::BaseAnnotationHighlighter *createAnnotationHighlighter(const QSet<QString> &changes) const; + virtual QString fileNameFromDiffSpecification(const QTextBlock &diffFileSpec) const; + + const QRegExp exactIdentifier12; + const QRegExp exactIdentifier40; + const QRegExp changesetIdentifier12; + const QRegExp changesetIdentifier40; + const QRegExp diffIdentifier; +}; + +} // namespace Internal +} // namespace Mercurial +#endif // MERCURIALEDITOR_H diff --git a/src/plugins/mercurial/mercurialjobrunner.cpp b/src/plugins/mercurial/mercurialjobrunner.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6c37352fb1fa0aef36a379a679264963aaae473b --- /dev/null +++ b/src/plugins/mercurial/mercurialjobrunner.cpp @@ -0,0 +1,205 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "mercurialjobrunner.h" +#include "mercurialplugin.h" +#include "mercurialoutputwindow.h" +#include "constants.h" +#include "mercurialsettings.h" + +#include <vcsbase/vcsbaseeditor.h> + +#include <QtCore/QProcess> +#include <QtCore/QTime> +#include <QtCore/QString> +#include <QtCore/QSettings> + +using namespace Mercurial::Internal; +using namespace Mercurial; + +HgTask::HgTask(const QString &repositoryRoot, QStringList &arguments, bool emitRaw) + : m_repositoryRoot(repositoryRoot), + arguments(arguments), + emitRaw(emitRaw), + editor(0) +{ +} + +HgTask::HgTask(const QString &repositoryRoot, QStringList &arguments, VCSBase::VCSBaseEditor *editor) + : m_repositoryRoot(repositoryRoot), + arguments(arguments), + emitRaw(false), + editor(editor) + +{ + +} + + +MercurialJobRunner::MercurialJobRunner() + : keepRunning(true) +{ + plugin = MercurialPlugin::instance(); + connect(this, SIGNAL(error(const QByteArray &)), plugin->outputPane(), SLOT(append(const QByteArray &))); + connect(this, SIGNAL(info(const QString &)), plugin->outputPane(), SLOT(append(const QString &))); +} + +MercurialJobRunner::~MercurialJobRunner() +{ + stop(); +} + +void MercurialJobRunner::stop() +{ + mutex.lock(); + keepRunning = false; + //Create a dummy task to break the cycle + QSharedPointer<HgTask> job(0); + jobs.enqueue(job); + waiter.wakeAll(); + mutex.unlock(); + + wait(); +} + +void MercurialJobRunner::restart() +{ + stop(); + mutex.lock(); + keepRunning = true; + mutex.unlock(); + start(); +} + +void MercurialJobRunner::getSettings() +{ + MercurialSettings *settings = MercurialPlugin::instance()->settings(); + binary = settings->binary(); + timeout = settings->timeout(); + standardArguments = settings->standardArguments(); +} + +void MercurialJobRunner::enqueueJob(QSharedPointer<HgTask> &job) +{ + mutex.lock(); + jobs.enqueue(job); + waiter.wakeAll(); + mutex.unlock(); +} + +void MercurialJobRunner::run() +{ + getSettings(); + forever { + mutex.lock(); + while (jobs.count() == 0) + waiter.wait(&mutex); + + if (!keepRunning) { + jobs.clear(); + mutex.unlock(); + return; + } + + QSharedPointer<HgTask> job = jobs.dequeue(); + mutex.unlock(); + + task(job); + } +} + +void MercurialJobRunner::task(QSharedPointer<HgTask> &job) +{ + HgTask *taskData = job.data(); + + if (taskData->shouldEmit()) + //Call the job's signal so the Initator of the job can process the data + //Because the QSharedPointer that holds the HgTask will go out of scope and hence be deleted + //we have to block and wait until the signal is delivered + connect(this, SIGNAL(output(const QByteArray&)), taskData, SIGNAL(rawData(const QByteArray&)), + Qt::BlockingQueuedConnection); + else if (taskData->displayEditor()) + //An editor has been created to display the data so send it there + connect(this, SIGNAL(output(const QByteArray&)), taskData->displayEditor(), SLOT(setPlainTextData(const QByteArray&))); + else + //Just output the data to the Mercurial output window + connect(this, SIGNAL(output(const QByteArray &)), plugin->outputPane(), SLOT(append(const QByteArray &))); + + QString time = QTime::currentTime().toString(QLatin1String("HH:mm")); + QString starting = tr("%1 Calling: %2 %3\n").arg(time, "hg", taskData->args().join(" ")); + + //infom the user of what we are going to try and perform + emit info(starting); + + if (Constants::debug) + qDebug() << Q_FUNC_INFO << "Repository root is " << taskData->repositoryRoot(); + + QProcess hgProcess; + hgProcess.setWorkingDirectory(taskData->repositoryRoot()); + + QStringList args = standardArguments; + args << taskData->args(); + + hgProcess.start(binary, args); + + if (!hgProcess.waitForStarted()) { + QByteArray errorArray(Constants::ERRORSTARTING); + emit error(errorArray); + return; + } + + hgProcess.closeWriteChannel(); + + if (!hgProcess.waitForFinished(timeout)) { + hgProcess.terminate(); + QByteArray errorArray(Constants::TIMEDOUT); + emit error(errorArray); + return; + } + + if ((hgProcess.exitStatus() == QProcess::NormalExit) && (hgProcess.exitCode() == 0)) { + QByteArray stdout = hgProcess.readAllStandardOutput(); + /* + * sometimes success means output is actually on error channel (stderr) + * e.g. "hg revert" outputs "no changes needed to 'file'" on stderr if file has not changed + * from revision specified + */ + if (stdout == "") + stdout = hgProcess.readAllStandardError(); + emit output(stdout); + } else { + QByteArray stderr = hgProcess.readAllStandardError(); + emit error(stderr); + } + + hgProcess.close(); + //the signal connection is to last only for the duration of a job/task. next time a new + //output signal connection must be made + disconnect(this, SIGNAL(output(const QByteArray &)), 0, 0); +} diff --git a/src/plugins/mercurial/mercurialjobrunner.h b/src/plugins/mercurial/mercurialjobrunner.h new file mode 100644 index 0000000000000000000000000000000000000000..e053286fbc6b3eaa98460051332280ce62237f7f --- /dev/null +++ b/src/plugins/mercurial/mercurialjobrunner.h @@ -0,0 +1,108 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MERCURIALJOBRUNNER_H +#define MERCURIALJOBRUNNER_H + +#include <QtCore/QThread> +#include <QtCore/QQueue> +#include <QtCore/QMutex> +#include <QtCore/QWaitCondition> +#include <QtCore/QStringList> +#include <QtCore/QSharedPointer> +#include <QtCore/QString> + +namespace VCSBase { +class VCSBaseEditor; +} + +namespace Mercurial { +namespace Internal { + +class MercurialPlugin; + +class HgTask : public QObject +{ + Q_OBJECT +public: + HgTask(const QString &workingDir, QStringList &arguments, bool emitRaw=false); + HgTask(const QString &workingDir, QStringList &arguments, + VCSBase::VCSBaseEditor *editor); + + bool shouldEmit() { return emitRaw; } + VCSBase::VCSBaseEditor* displayEditor() { return editor; } + QStringList args() { return arguments; } + QString repositoryRoot() { return m_repositoryRoot; } + +signals: + void rawData(const QByteArray &data); + +private: + QString m_repositoryRoot; + QStringList arguments; + bool emitRaw; + VCSBase::VCSBaseEditor *editor; +}; + + +class MercurialJobRunner : public QThread +{ + Q_OBJECT +public: + MercurialJobRunner(); + ~MercurialJobRunner(); + void enqueueJob(QSharedPointer<HgTask> &job); + void restart(); + +protected: + void run(); + +signals: + void error(const QByteArray &error); + void info(const QString ¬ice); + void output(const QByteArray &output); + +private: + void task(QSharedPointer<HgTask> &job); + void stop(); + void getSettings(); + + QQueue<QSharedPointer<HgTask> > jobs; + QMutex mutex; + QWaitCondition waiter; + MercurialPlugin *plugin; + bool keepRunning; + QString binary; + QStringList standardArguments; + int timeout; +}; + +} //namespace Internal +} //namespace Mercurial +#endif // MERCURIALJOBRUNNER_H diff --git a/src/plugins/mercurial/mercurialoutputwindow.cpp b/src/plugins/mercurial/mercurialoutputwindow.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3e1779faa36a1253b25e06f0bfdd20273add4d14 --- /dev/null +++ b/src/plugins/mercurial/mercurialoutputwindow.cpp @@ -0,0 +1,131 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "mercurialoutputwindow.h" + +#include <QtGui/QListWidget> +#include <QtCore/QDebug> +#include <QtCore/QTextCodec> + +using namespace Mercurial::Internal; + +MercurialOutputWindow::MercurialOutputWindow() +{ + outputListWidgets = new QListWidget; + outputListWidgets->setWindowTitle(tr("Mercurial Output")); + outputListWidgets->setFrameStyle(QFrame::NoFrame); + outputListWidgets->setSelectionMode(QAbstractItemView::ExtendedSelection); +} + +MercurialOutputWindow::~MercurialOutputWindow() +{ + delete outputListWidgets; + outputListWidgets = 0; +} + +QWidget *MercurialOutputWindow::outputWidget(QWidget *parent) +{ + outputListWidgets->setParent(parent); + return outputListWidgets; +} + +QList<QWidget*> MercurialOutputWindow::toolBarWidgets() const +{ + return QList<QWidget *>(); +} + +QString MercurialOutputWindow::name() const +{ + return tr("Mercurial"); +} + +int MercurialOutputWindow::priorityInStatusBar() const +{ + return -1; +} + +void MercurialOutputWindow::clearContents() +{ + outputListWidgets->clear(); +} + +void MercurialOutputWindow::visibilityChanged(bool visible) +{ + if (visible) + outputListWidgets->setFocus(); +} + +void MercurialOutputWindow::setFocus() +{ +} + +bool MercurialOutputWindow::hasFocus() +{ + return outputListWidgets->hasFocus(); +} + +bool MercurialOutputWindow::canFocus() +{ + return false; +} + +bool MercurialOutputWindow::canNavigate() +{ + return false; +} + +bool MercurialOutputWindow::canNext() +{ + return false; +} + +bool MercurialOutputWindow::canPrevious() +{ + return false; +} + +void MercurialOutputWindow::goToNext() +{ +} + +void MercurialOutputWindow::goToPrev() +{ +} + +void MercurialOutputWindow::append(const QString &text) +{ + outputListWidgets->addItems(text.split(QLatin1Char('\n'))); + outputListWidgets->scrollToBottom(); + popup(true); +} + +void MercurialOutputWindow::append(const QByteArray &array) +{ + append(QTextCodec::codecForLocale()->toUnicode(array)); +} diff --git a/src/plugins/mercurial/mercurialoutputwindow.h b/src/plugins/mercurial/mercurialoutputwindow.h new file mode 100644 index 0000000000000000000000000000000000000000..de8abadd8e391a276c76fab655abe1859af9bddf --- /dev/null +++ b/src/plugins/mercurial/mercurialoutputwindow.h @@ -0,0 +1,78 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MERCURIALOUTPUTWINDOW_H +#define MERCURIALOUTPUTWINDOW_H + +#include <coreplugin/ioutputpane.h> + +QT_BEGIN_NAMESPACE +class QListWidget; +QT_END_NAMESPACE + +#include <QtCore/QByteArray> + +namespace Mercurial { +namespace Internal { + +class MercurialOutputWindow: public Core::IOutputPane +{ + Q_OBJECT + +public: + MercurialOutputWindow(); + ~MercurialOutputWindow(); + + QWidget *outputWidget(QWidget *parent); + QList<QWidget*> toolBarWidgets() const; + QString name() const; + int priorityInStatusBar() const; + void clearContents(); + void visibilityChanged(bool visible); + void setFocus(); + bool hasFocus(); + bool canFocus(); + bool canNavigate(); + bool canNext(); + bool canPrevious(); + void goToNext(); + void goToPrev(); + +public slots: + void append(const QString &text); + void append(const QByteArray &array); + +private: + QListWidget *outputListWidgets; +}; + +} //namespace Internal +} //namespace Mercurial + +#endif // MERCURIALOUTPUTWINDOW_H diff --git a/src/plugins/mercurial/mercurialplugin.cpp b/src/plugins/mercurial/mercurialplugin.cpp new file mode 100644 index 0000000000000000000000000000000000000000..527a623fab20ec31b8946583760d838824c6598b --- /dev/null +++ b/src/plugins/mercurial/mercurialplugin.cpp @@ -0,0 +1,698 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "mercurialplugin.h" +#include "optionspage.h" +#include "mercurialoutputwindow.h" +#include "constants.h" +#include "mercurialclient.h" +#include "mercurialcontrol.h" +#include "mercurialeditor.h" +#include "revertdialog.h" +#include "srcdestdialog.h" +#include "commiteditor.h" +#include "clonewizard.h" +#include "mercurialsettings.h" + +#include <coreplugin/actionmanager/actionmanager.h> +#include <coreplugin/basemode.h> +#include <coreplugin/coreconstants.h> +#include <coreplugin/icore.h> +#include <coreplugin/modemanager.h> +#include <coreplugin/uniqueidmanager.h> +#include <coreplugin/filemanager.h> +#include <coreplugin/editormanager/editormanager.h> + + +#include <projectexplorer/projectexplorer.h> +#include <utils/parameteraction.h> + +#include <vcsbase/basevcseditorfactory.h> +#include <vcsbase/basevcssubmiteditorfactory.h> +#include <vcsbase/vcsbaseeditor.h> + +#include <QtCore/QtPlugin> +#include <QtGui/QAction> +#include <QtGui/QMenu> +#include <QtGui/QMainWindow> +#include <QtCore/QtDebug> +#include <QtCore/QtGlobal> +#include <QtCore/QDir> +#include <QtGui/QDialog> +#include <QtGui/QFileDialog> +#include <QtCore/QTemporaryFile> + + +using namespace Mercurial::Internal; +using namespace Mercurial; + +bool ListenForClose::editorAboutToClose(Core::IEditor *editor) +{ + return MercurialPlugin::instance()->closeEditor(editor); +} + +static const VCSBase::VCSBaseEditorParameters editorParameters[] = { +{ + VCSBase::RegularCommandOutput, //type + Constants::COMMANDLOG, // kind + Constants::COMMANDLOG, // context + Constants::COMMANDAPP, // mime type + Constants::COMMANDEXT}, //extension + +{ VCSBase::LogOutput, + Constants::FILELOG, + Constants::FILELOG, + Constants::LOGAPP, + Constants::LOGEXT}, + +{ VCSBase::AnnotateOutput, + Constants::ANNOTATELOG, + Constants::ANNOTATELOG, + Constants::ANNOTATEAPP, + Constants::ANNOTATEEXT}, + +{ VCSBase::DiffOutput, + Constants::DIFFLOG, + Constants::DIFFLOG, + Constants::DIFFAPP, + Constants::DIFFEXT} +}; + +static const VCSBase::VCSBaseSubmitEditorParameters submitEditorParameters = { + Constants::COMMITMIMETYPE, + Constants::COMMITKIND, + Constants::COMMITKIND +}; + +// Utility to find a parameter set by type +static inline const VCSBase::VCSBaseEditorParameters *findType(int ie) +{ + const VCSBase::EditorContentType et = static_cast<VCSBase::EditorContentType>(ie); + return VCSBase::VCSBaseEditor::findType(editorParameters, + sizeof(editorParameters)/sizeof(VCSBase::VCSBaseEditorParameters), et); +} + +MercurialPlugin *MercurialPlugin::m_instance = 0; + +MercurialPlugin::MercurialPlugin() + : mercurialSettings(new MercurialSettings), + outputWindow(0), + optionsPage(0), + client(0), + mercurialVC(0), + projectExplorer(0), + changeLog(0) +{ + m_instance = this; +} + +MercurialPlugin::~MercurialPlugin() +{ + if (client) { + delete client; + client = 0; + } + + if (mercurialSettings) { + delete mercurialSettings; + mercurialSettings = 0; + } + + deleteCommitLog(); + + m_instance = 0; +} + +bool MercurialPlugin::initialize(const QStringList &arguments, QString *error_message) +{ + Q_UNUSED(arguments) + Q_UNUSED(error_message) + + typedef VCSBase::VCSEditorFactory<MercurialEditor> MercurialEditorFactory; + + core = Core::ICore::instance(); + actionManager = core->actionManager(); + + optionsPage = new OptionsPage(); + addAutoReleasedObject(optionsPage); + + outputWindow = new MercurialOutputWindow(); + addAutoReleasedObject(outputWindow); + + client = new MercurialClient(); + connect(optionsPage, SIGNAL(settingsChanged()), client, SLOT(settingsChanged())); + + mercurialVC = new MercurialControl(client); + addAutoReleasedObject(mercurialVC); + + static const char *describeSlot = SLOT(view(QString,QString)); + const int editorCount = sizeof(editorParameters)/sizeof(VCSBase::VCSBaseEditorParameters); + for (int i = 0; i < editorCount; i++) + addAutoReleasedObject(new MercurialEditorFactory(editorParameters + i, client, describeSlot)); + + addAutoReleasedObject(new VCSBase::VCSSubmitEditorFactory<CommitEditor>(&submitEditorParameters)); + + addAutoReleasedObject(new CloneWizard); + + addAutoReleasedObject(new ListenForClose); + + createMenu(); + + createSubmitEditorActions(); + + return true; +} + +void MercurialPlugin::extensionsInitialized() +{ + projectExplorer = ProjectExplorer::ProjectExplorerPlugin::instance(); + if (projectExplorer) + connect(projectExplorer, SIGNAL(currentProjectChanged(ProjectExplorer::Project *)), + this, SLOT(currentProjectChanged(ProjectExplorer::Project *))); +} + +MercurialOutputWindow *MercurialPlugin::outputPane() +{ + return outputWindow; +} + +MercurialSettings *MercurialPlugin::settings() +{ + return mercurialSettings; +} + +void MercurialPlugin::createMenu() +{ + QList<int> context = QList<int>()<< core->uniqueIDManager()->uniqueIdentifier(Core::Constants::C_GLOBAL); + + // Create menu item for Mercurial + mercurialContainer = actionManager->createMenu("Mercurial.MercurialMenu"); + QMenu *menu = mercurialContainer->menu(); + menu->setTitle(tr("Mercurial")); + + if (QAction *visibleAction = menu->menuAction()) { + visibleAction->setEnabled(mercurialVC->isEnabled()); + connect(mercurialVC, SIGNAL(enabledChanged(bool)), visibleAction, SLOT(setVisible(bool))); + } + + createFileActions(context); + createSeparator(context, "FileDirSeperator"); + createDirectoryActions(context); + createSeparator(context, "DirRepoSeperator"); + createRepositoryActions(context); + createSeparator(context, "Repository Management"); + createRepositoryManagementActions(context); + createSeparator(context, "LessUsedfunctionality"); + createLessUsedActions(context); + + // Request the Tools menu and add the Mercurial menu to it + Core::ActionContainer *toolsMenu = actionManager->actionContainer(Core::Constants::M_TOOLS); + toolsMenu->addMenu(mercurialContainer); + + connect(core, SIGNAL(contextChanged(Core::IContext *)), this, SLOT(updateActions())); + connect(core->fileManager(), SIGNAL(currentFileChanged(const QString &)), + this, SLOT(updateActions())); + +} + +void MercurialPlugin::createFileActions(QList<int> &context) +{ + Core::Command *command; + + annotateFile = new Core::Utils::ParameterAction(tr("Annotate Current File"), tr("Annotate \"%1\""), Core::Utils::ParameterAction::AlwaysEnabled, this); + command = actionManager->registerAction(annotateFile, Constants::ANNOTATE, context); + command->setAttribute(Core::Command::CA_UpdateText); + connect(annotateFile, SIGNAL(triggered()), this, SLOT(annotateCurrentFile())); + mercurialContainer->addAction(command); + + diffFile = new Core::Utils::ParameterAction(tr("Diff Current File"), tr("Diff \"%1\""), Core::Utils::ParameterAction::AlwaysEnabled, this); + command = actionManager->registerAction(diffFile, Constants::DIFF, context); + command->setAttribute(Core::Command::CA_UpdateText); + command->setDefaultKeySequence(QKeySequence(tr(Constants::MENUKEY) + tr(Constants::MODIFIER) + "D")); + connect(diffFile, SIGNAL(triggered()), this, SLOT(diffCurrentFile())); + mercurialContainer->addAction(command); + + logFile = new Core::Utils::ParameterAction(tr("Log Current File"), tr("Log \"%1\""), Core::Utils::ParameterAction::AlwaysEnabled, this); + command = actionManager->registerAction(logFile, Constants::LOG, context); + command->setAttribute(Core::Command::CA_UpdateText); + command->setDefaultKeySequence(QKeySequence(tr(Constants::MENUKEY) + tr(Constants::MODIFIER) + "L")); + connect(logFile, SIGNAL(triggered()), this, SLOT(logCurrentFile())); + mercurialContainer->addAction(command); + + revertFile = new Core::Utils::ParameterAction(tr("Revert Current File"), tr("Revert \"%1\""), Core::Utils::ParameterAction::AlwaysEnabled, this); + command = actionManager->registerAction(revertFile, Constants::REVERT, context); + command->setAttribute(Core::Command::CA_UpdateText); + connect(revertFile, SIGNAL(triggered()), this, SLOT(revertCurrentFile())); + mercurialContainer->addAction(command); + + statusFile = new Core::Utils::ParameterAction(tr("Status Current File"), tr("Status \"%1\""), Core::Utils::ParameterAction::AlwaysEnabled, this); + command = actionManager->registerAction(statusFile, Constants::STATUS, context); + command->setAttribute(Core::Command::CA_UpdateText); + command->setDefaultKeySequence(QKeySequence(tr(Constants::MENUKEY) + tr(Constants::MODIFIER) + "S")); + connect(statusFile, SIGNAL(triggered()), this, SLOT(statusCurrentFile())); + mercurialContainer->addAction(command); +} + +void MercurialPlugin::annotateCurrentFile() +{ + client->annotate(currentFile()); +} + +void MercurialPlugin::diffCurrentFile() +{ + client->diff(currentFile()); +} + +void MercurialPlugin::logCurrentFile() +{ + client->log(currentFile()); +} + +void MercurialPlugin::revertCurrentFile() +{ + RevertDialog reverter; + if (reverter.exec() != QDialog::Accepted) + return; + const QString revision = reverter.m_ui->revisionLineEdit->text(); + client->revert(currentFile(), revision); +} + +void MercurialPlugin::statusCurrentFile() +{ + client->status(currentFile()); +} + +void MercurialPlugin::createDirectoryActions(QList<int> &context) +{ + QAction *action; + Core::Command *command; + + action = new QAction(tr("Diff"), this); + actionList.append(action); + command = actionManager->registerAction(action, Constants::DIFFMULTI, context); + connect(action, SIGNAL(triggered()), this, SLOT(diffRepository())); + mercurialContainer->addAction(command); + + action = new QAction(tr("Log"), this); + actionList.append(action); + command = actionManager->registerAction(action, Constants::LOGMULTI, context); + connect(action, SIGNAL(triggered()), this, SLOT(logRepository())); + mercurialContainer->addAction(command); + + action = new QAction(tr("Revert"), this); + actionList.append(action); + command = actionManager->registerAction(action, Constants::REVERTMULTI, context); + connect(action, SIGNAL(triggered()), this, SLOT(revertMulti())); + mercurialContainer->addAction(command); + + action = new QAction(tr("Status"), this); + actionList.append(action); + command = actionManager->registerAction(action, Constants::STATUSMULTI, context); + connect(action, SIGNAL(triggered()), this, SLOT(statusMulti())); + mercurialContainer->addAction(command); +} + +void MercurialPlugin::diffRepository() +{ + client->diff(currentProjectRoot()); +} + +void MercurialPlugin::logRepository() +{ + client->log(currentProjectRoot()); +} + +void MercurialPlugin::revertMulti() +{ + RevertDialog reverter; + if (reverter.exec() != QDialog::Accepted) + return; + const QString revision = reverter.m_ui->revisionLineEdit->text(); + client->revert(currentProjectRoot(), revision); +} + +void MercurialPlugin::statusMulti() +{ + client->status(currentProjectRoot()); +} + +void MercurialPlugin::createRepositoryActions(QList<int> &context) +{ + QAction *action = new QAction(tr("Pull"), this); + actionList.append(action); + Core::Command *command = actionManager->registerAction(action, Constants::PULL, context); + connect(action, SIGNAL(triggered()), this, SLOT(pull())); + mercurialContainer->addAction(command); + + action = new QAction(tr("Push"), this); + actionList.append(action); + command = actionManager->registerAction(action, Constants::PUSH, context); + connect(action, SIGNAL(triggered()), this, SLOT(push())); + mercurialContainer->addAction(command); + + action = new QAction(tr("Update"), this); + actionList.append(action); + command = actionManager->registerAction(action, Constants::UPDATE, context); + connect(action, SIGNAL(triggered()), this, SLOT(update())); + mercurialContainer->addAction(command); + + action = new QAction(tr("Import"), this); + actionList.append(action); + command = actionManager->registerAction(action, Constants::IMPORT, context); + connect(action, SIGNAL(triggered()), this, SLOT(import())); + mercurialContainer->addAction(command); + + action = new QAction(tr("Incoming"), this); + actionList.append(action); + command = actionManager->registerAction(action, Constants::INCOMING, context); + connect(action, SIGNAL(triggered()), this, SLOT(incoming())); + mercurialContainer->addAction(command); + + action = new QAction(tr("Outgoing"), this); + actionList.append(action); + command = actionManager->registerAction(action, Constants::OUTGOING, context); + connect(action, SIGNAL(triggered()), this, SLOT(outgoing())); + mercurialContainer->addAction(command); + + action = new QAction(tr("Commit"), this); + actionList.append(action); + command = actionManager->registerAction(action, Constants::COMMIT, context); + command->setDefaultKeySequence(QKeySequence(tr(Constants::MENUKEY) + tr(Constants::MODIFIER) + "C")); + connect(action, SIGNAL(triggered()), this, SLOT(commit())); + mercurialContainer->addAction(command); +} + +void MercurialPlugin::pull() +{ + SrcDestDialog dialog; + dialog.setWindowTitle("Pull Source"); + if (dialog.exec() != QDialog::Accepted) + return; + QString repository = dialog.getRepositoryString(); + client->pull(currentProjectRoot(), repository); +} + +void MercurialPlugin::push() +{ + SrcDestDialog dialog; + dialog.setWindowTitle("Push Destination"); + if (dialog.exec() != QDialog::Accepted) + return; + QString repository = dialog.getRepositoryString(); + client->push(currentProjectRoot(), repository); +} + +void MercurialPlugin::update() +{ + RevertDialog updateDialog; + updateDialog.setWindowTitle("Update"); + if (updateDialog.exec() != QDialog::Accepted) + return; + const QString revision = updateDialog.m_ui->revisionLineEdit->text(); + client->update(currentProjectRoot(), revision); +} + +void MercurialPlugin::import() +{ + QFileDialog importDialog; + importDialog.setFileMode(QFileDialog::ExistingFiles); + importDialog.setViewMode(QFileDialog::Detail); + + if (importDialog.exec() != QDialog::Accepted) + return; + + const QStringList fileNames = importDialog.selectedFiles(); + client->import(currentProjectRoot(), fileNames); +} + +void MercurialPlugin::incoming() +{ + SrcDestDialog dialog; + dialog.setWindowTitle("Incoming Source"); + if (dialog.exec() != QDialog::Accepted) + return; + QString repository = dialog.getRepositoryString(); + client->incoming(currentProjectRoot(), repository); +} + +void MercurialPlugin::outgoing() +{ + client->outgoing(currentProjectRoot()); +} + +void MercurialPlugin::createSubmitEditorActions() +{ + QList<int> context = QList<int>()<< core->uniqueIDManager()->uniqueIdentifier(Constants::COMMITKIND); + Core::Command *command; + + editorCommit = new QAction(VCSBase::VCSBaseSubmitEditor::submitIcon(), tr("Commit"), this); + command = actionManager->registerAction(editorCommit, Constants::COMMIT, context); + connect(editorCommit, SIGNAL(triggered()), this, SLOT(commitFromEditor())); + + editorDiff = new QAction(VCSBase::VCSBaseSubmitEditor::diffIcon(), tr("Diff Selected Files"), this); + command = actionManager->registerAction(editorDiff, Constants::DIFFEDITOR, context); + + editorUndo = new QAction(tr("&Undo"), this); + command = actionManager->registerAction(editorUndo, Core::Constants::UNDO, context); + + editorRedo = new QAction(tr("&Redo"), this); + command = actionManager->registerAction(editorRedo, Core::Constants::REDO, context); +} + +void MercurialPlugin::commit() +{ + if (VCSBase::VCSBaseSubmitEditor::raiseSubmitEditor()) + return; + + connect(client, SIGNAL(parsedStatus(const QList<QPair<QString,QString> > &)), + this, SLOT(showCommitWidget(const QList<QPair<QString,QString> > &))); + client->statusWithSignal(currentProjectRoot()); +} + +void MercurialPlugin::showCommitWidget(const QList<QPair<QString, QString> > &status) +{ + //Once we receive our data release the connection so it can be reused elsewhere + disconnect(client, SIGNAL(parsedStatus(const QList<QPair<QString,QString> > &)), + this, SLOT(showCommitWidget(const QList<QPair<QString,QString> > &))); + + if (status.isEmpty()) { + outputWindow->append(tr("There are no changes to commit")); + return; + } + + deleteCommitLog(); + + changeLog = new QTemporaryFile(this); + if (!changeLog->open()) { + outputWindow->append(tr("Unable to generate a Tempory File for the Commit Editor")); + return; + } + + Core::IEditor *editor = core->editorManager()->openEditor(changeLog->fileName(), + Constants::COMMITKIND); + if (!editor) { + outputWindow->append(tr("Unable to generate an Editor for the commit")); + return; + } + + core->editorManager()->ensureEditorManagerVisible(); + + CommitEditor *commitEditor = qobject_cast<CommitEditor *>(editor); + + if (!commitEditor) { + outputWindow->append(tr("Unable to generate a Commit Editor")); + return; + } + + commitEditor->setDisplayName(tr("Commit changes for \"") + currentProjectName() + tr("\"")); + + QString branch = client->branchQuerySync(currentProjectRoot()); + + commitEditor->setFields(currentProjectRoot(), branch, mercurialSettings->userName(), + mercurialSettings->email(), status); + + commitEditor->registerActions(editorUndo, editorRedo, editorCommit, editorDiff); + connect(commitEditor, SIGNAL(diffSelectedFiles(const QStringList &)), + this, SLOT(diffFromEditorSelected(const QStringList &))); +} + +void MercurialPlugin::diffFromEditorSelected(const QStringList &files) +{ + foreach (QString file, files) { + QFileInfo toDiff(QDir(currentProjectRoot().absoluteFilePath()).absoluteFilePath(file)); + client->diff(toDiff); + } +} + +void MercurialPlugin::commitFromEditor() +{ + if (!changeLog) + return; + + //use the same functionality than if the user closes the file without completing the commit + core->editorManager()->closeEditors(core->editorManager()->editorsForFileName(changeLog->fileName())); +} + +bool MercurialPlugin::closeEditor(Core::IEditor *editor) +{ + if (!changeLog || !editor || qstrcmp(editor->kind(), Constants::COMMITKIND)) + return true; + Core::IFile *editorFile = editor->file(); + CommitEditor *commitEditor = qobject_cast<CommitEditor *>(editor); + if (!editorFile || !commitEditor) + return true; + + bool dummyPrompt = settings()->prompt(); + const VCSBase::VCSBaseSubmitEditor::PromptSubmitResult response = + commitEditor->promptSubmit(tr("Close commit editor"), tr("Do you want to commit the changes?"), + tr("Message check failed. Do you want to proceed?"), + &dummyPrompt, settings()->prompt()); + + switch (response) { + case VCSBase::VCSBaseSubmitEditor::SubmitCanceled: + return false; + case VCSBase::VCSBaseSubmitEditor::SubmitDiscarded: + deleteCommitLog(); + return true; + default: + break; + } + + const QStringList files = commitEditor->checkedFiles(); + if (!files.empty()) { + //save the commit message + core->fileManager()->blockFileChange(editorFile); + editorFile->save(); + core->fileManager()->unblockFileChange(editorFile); + + const QFileInfo repoRoot(commitEditor->repoRoot()); + client->commit(repoRoot, files, commitEditor->committerInfo(), + editorFile->fileName()); + } + return true; +} +void MercurialPlugin::deleteCommitLog() +{ + if (changeLog) { + delete changeLog; + changeLog = 0; + } +} + +void MercurialPlugin::createRepositoryManagementActions(QList<int> &context) +{ + //TODO create menu for these options + Q_UNUSED(context); + return; + // QAction *action = new QAction(tr("Branch"), this); + // actionList.append(action); + // Core::Command *command = actionManager->registerAction(action, Constants::BRANCH, context); + // // connect(action, SIGNAL(triggered()), this, SLOT(branch())); + // mercurialContainer->addAction(command); +} + +void MercurialPlugin::createLessUsedActions(QList<int> &context) +{ + //TODO create menue for these options + Q_UNUSED(context); + return; +} + +void MercurialPlugin::createSeparator(const QList<int> &context, const QString &id) +{ + QAction *action = new QAction(this); + action->setSeparator(true); + mercurialContainer->addAction(actionManager->registerAction(action, id, context)); +} + +void MercurialPlugin::updateActions() +{ + const QFileInfo file = currentFile(); + const QString filename = file.fileName(); + const QString repoRoot = client->findTopLevelForFile(file); + bool enable = false; + + //File menu Items should only be enabled for files that are below a mercurial repository + enable = !repoRoot.isEmpty(); + annotateFile->setParameter(filename); + annotateFile->setEnabled(enable); + diffFile->setParameter(filename); + diffFile->setEnabled(enable); + logFile->setParameter(filename); + logFile->setEnabled(enable); + revertFile->setParameter(filename); + revertFile->setEnabled(enable); + statusFile->setParameter(filename); + statusFile->setEnabled(enable); + + //repository actions + if (projectMapper.contains(currentProjectName())) + enable = true; + else + enable = false; + + foreach (QAction *action, actionList) + action->setEnabled(enable); +} + +QFileInfo MercurialPlugin::currentFile() +{ + QString fileName = core->fileManager()->currentFile(); + QFileInfo fileInfo(fileName); + return fileInfo; +} + +QString MercurialPlugin::currentProjectName() +{ + if (projectExplorer) + if (projectExplorer->currentProject()) + return projectExplorer->currentProject()->name(); + return QString(); +} + +void MercurialPlugin::currentProjectChanged(ProjectExplorer::Project *project) +{ + if (!project) + return; + + if (projectMapper.contains(project->name())) + return; + + QString repoRoot = client->findTopLevelForFile(QFileInfo(project->file()->fileName())); + + if (!repoRoot.isEmpty()) + projectMapper.insert(project->name(), QFileInfo(repoRoot)); +} + +QFileInfo MercurialPlugin::currentProjectRoot() +{ + return projectMapper.value(currentProjectName()); +} + +Q_EXPORT_PLUGIN(MercurialPlugin) diff --git a/src/plugins/mercurial/mercurialplugin.h b/src/plugins/mercurial/mercurialplugin.h new file mode 100644 index 0000000000000000000000000000000000000000..0f21212b09f16cbcccbd1bc9a1e435212b71514f --- /dev/null +++ b/src/plugins/mercurial/mercurialplugin.h @@ -0,0 +1,194 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MERCURIALPLUGIN_H +#define MERCURIALPLUGIN_H + +#include <extensionsystem/iplugin.h> +#include <coreplugin/icorelistener.h> + +#include <QtCore/QFileInfo> +#include <QtCore/QHash> +#include <QtCore/qglobal.h> + +QT_BEGIN_NAMESPACE +class QAction; +class QTemporaryFile; +QT_END_NAMESPACE + +namespace Core { +class ActionManager; +class ActionContainer; +class ICore; +class IVersionControl; +class IEditorFactory; +class IEditor; + +namespace Utils { +class ParameterAction; +} //namespace Utils +} // namespace Core + +namespace ProjectExplorer { +class ProjectExplorerPlugin; +class Project; +} + +namespace Mercurial { +namespace Internal { + +class MercurialOutputWindow; +class OptionsPage; +class MercurialClient; +class MercurialControl; +class MercurialEditor; +class MercurialSettings; + +class MercurialPlugin : public ExtensionSystem::IPlugin +{ + Q_OBJECT + +public: + MercurialPlugin(); + virtual ~MercurialPlugin(); + bool initialize(const QStringList &arguments, QString *error_message); + void extensionsInitialized(); + static MercurialPlugin *instance() { return m_instance; } + QFileInfo currentFile(); + QString currentProjectName(); + QFileInfo currentProjectRoot(); + bool closeEditor(Core::IEditor *editor); + + MercurialSettings *settings(); + MercurialOutputWindow *outputPane(); + + +private slots: + // File menu action Slots + void annotateCurrentFile(); + void diffCurrentFile(); + void logCurrentFile(); + void revertCurrentFile(); + void statusCurrentFile(); + + //Directory menu Action slots + void diffRepository(); + void logRepository(); + void revertMulti(); + void statusMulti(); + + //repository menu action slots + void pull(); + void push(); + void update(); + void import(); + void incoming(); + void outgoing(); + void commit(); + void showCommitWidget(const QList<QPair<QString, QString> > &status); + void commitFromEditor(); + void diffFromEditorSelected(const QStringList &files); + + //TODO implement + /* //repository management action slots + void merge(); + void branch(); + void heads(); + void parents(); + void tags(); + void tip(); + void paths(); + + //less used repository action + void init(); + void serve();*/ + + //change the sates of the actions in the Mercurial Menu i.e. 2 be context sensitive + void updateActions(); + void currentProjectChanged(ProjectExplorer::Project *project); + + +private: + //methods + void createMenu(); + void createSubmitEditorActions(); + void createSeparator(const QList<int> &context, const QString &id); + void createFileActions(QList<int> &context); + void createDirectoryActions(QList<int> &context); + void createRepositoryActions(QList<int> &context); + void createRepositoryManagementActions(QList<int> &context); + void createLessUsedActions(QList<int> &context); + void deleteCommitLog(); + //QString getSettingsByKey(const char * const key); + + //Variables + static MercurialPlugin *m_instance; + MercurialSettings *mercurialSettings; + MercurialOutputWindow *outputWindow; + OptionsPage *optionsPage; + MercurialClient *client; + + Core::IVersionControl *mercurialVC; + Core::ICore *core; + Core::ActionManager *actionManager; + Core::ActionContainer *mercurialContainer; + ProjectExplorer::ProjectExplorerPlugin *projectExplorer; + + //provide a mapping of projectName -> repositoryRoot for each project + QHash<QString, QFileInfo> projectMapper; + QList<QAction *> actionList; + QTemporaryFile *changeLog; + + //Menu Items (file actions) + Core::Utils::ParameterAction *annotateFile; + Core::Utils::ParameterAction *diffFile; + Core::Utils::ParameterAction *logFile; + Core::Utils::ParameterAction *renameFile; + Core::Utils::ParameterAction *revertFile; + Core::Utils::ParameterAction *statusFile; + + //submit editor actions + QAction *editorCommit; + QAction *editorDiff; + QAction *editorUndo; + QAction *editorRedo; +}; + +class ListenForClose : public Core::ICoreListener +{ + Q_OBJECT +public: + ListenForClose(QObject *parent=0) : Core::ICoreListener(parent) {} + bool editorAboutToClose(Core::IEditor *editor); +}; + +} //namespace Internal +} //namespace Mercurial + +#endif // MERCURIALPLUGIN_H diff --git a/src/plugins/mercurial/mercurialsettings.cpp b/src/plugins/mercurial/mercurialsettings.cpp new file mode 100644 index 0000000000000000000000000000000000000000..48d7000d658d566101627e15da3fe2d96d79f04e --- /dev/null +++ b/src/plugins/mercurial/mercurialsettings.cpp @@ -0,0 +1,143 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "mercurialsettings.h" +#include "constants.h" + +#include <coreplugin/icore.h> + +#include <QtCore/QSettings> + + +using namespace Mercurial::Internal; + +MercurialSettings::MercurialSettings() +{ + readSettings(); +} + +QString MercurialSettings::binary() +{ + return bin; +} + +QString MercurialSettings::application() +{ + return app; +} + +QStringList MercurialSettings::standardArguments() +{ + return standardArgs; +} + +QString MercurialSettings::userName() +{ + return user; +} + +QString MercurialSettings::email() +{ + return mail; +} + +int MercurialSettings::logCount() +{ + return m_logCount; +} + +int MercurialSettings::timeout() +{ + //return timeout is in Ms + return m_timeout * 1000; +} + +int MercurialSettings::timeoutSeconds() +{ + //return timeout in seconds (as the user specifies on the options page + return m_timeout; +} + +bool MercurialSettings::prompt() +{ + return m_prompt; +} + +void MercurialSettings::writeSettings(const QString &application, const QString &userName, + const QString &email, int logCount, int timeout, bool prompt) +{ + QSettings *settings = Core::ICore::instance()->settings(); + if (settings) { + settings->beginGroup("Mercurial"); + settings->setValue(Constants::MERCURIALPATH, application); + settings->setValue(Constants::MERCURIALUSERNAME, userName); + settings->setValue(Constants::MERCURIALEMAIL, email); + settings->setValue(Constants::MERCURIALLOGCOUNT, logCount); + settings->setValue(Constants::MERCURIALTIMEOUT, timeout); + settings->setValue(Constants::MERCURIALPROMPTSUBMIT, prompt); + settings->endGroup(); + } + + app = application; + user = userName; + mail = email; + m_logCount = logCount; + m_timeout = timeout; + m_prompt = prompt; + setBinAndArgs(); +} + +void MercurialSettings::readSettings() +{ + QSettings *settings = Core::ICore::instance()->settings(); + if (settings) { + settings->beginGroup("Mercurial"); + app = settings->value(Constants::MERCURIALPATH, Constants::MERCURIALDEFAULT).toString(); + user = settings->value(Constants::MERCURIALUSERNAME, "").toString(); + mail = settings->value(Constants::MERCURIALEMAIL, "").toString(); + m_logCount = settings->value(Constants::MERCURIALLOGCOUNT, 0).toInt(); + m_timeout = settings->value(Constants::MERCURIALTIMEOUT, 30).toInt(); + m_prompt = settings->value(Constants::MERCURIALPROMPTSUBMIT, true).toBool(); + settings->endGroup(); + } + + setBinAndArgs(); +} + +void MercurialSettings::setBinAndArgs() +{ + standardArgs.clear(); + +#ifdef Q_OS_WIN + bin = QLatin1String("cmd.exe"); + standardArgs << "/c" << app; +#else + bin = app; +#endif +} diff --git a/src/plugins/mercurial/mercurialsettings.h b/src/plugins/mercurial/mercurialsettings.h new file mode 100644 index 0000000000000000000000000000000000000000..df1155afff511285c1306598173508245b6a9da1 --- /dev/null +++ b/src/plugins/mercurial/mercurialsettings.h @@ -0,0 +1,74 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MERCURIALSETTINGS_H +#define MERCURIALSETTINGS_H + +#include <QtCore/QString> +#include <QtCore/QStringList> + +namespace Mercurial { +namespace Internal { + +class MercurialSettings +{ +public: + MercurialSettings(); + + QString binary(); + QString application(); + QStringList standardArguments(); + QString userName(); + QString email(); + int logCount(); + int timeout(); + int timeoutSeconds(); + bool prompt(); + void writeSettings(const QString &application, const QString &userName, + const QString &email, int logCount, int timeout, bool prompt); +private: + + void readSettings(); + void setBinAndArgs(); + + QString bin; // used because windows requires cmd.exe to run the mercurial binary + // in this case the actual mercurial binary will be part of the standard args + QString app; // this is teh actual mercurial executable + QStringList standardArgs; + QString user; + QString mail; + int m_logCount; + int m_timeout; + bool m_prompt; +}; + +} //namespace Internal +} //namespace Mercurial + +#endif // MERCURIALSETTINGS_H diff --git a/src/plugins/mercurial/optionspage.cpp b/src/plugins/mercurial/optionspage.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8b48e1a8c8ddbdede9a677a99098009da8764a0e --- /dev/null +++ b/src/plugins/mercurial/optionspage.cpp @@ -0,0 +1,108 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "optionspage.h" +#include "mercurialsettings.h" +#include "mercurialplugin.h" + +#include <utils/pathchooser.h> +#include <vcsbase/vcsbaseconstants.h> + +using namespace Mercurial::Internal; +using namespace Mercurial; + +OptionsPageWidget::OptionsPageWidget(QWidget *parent) : + QWidget(parent) +{ + m_ui.setupUi(this); + m_ui.commandChooser->setExpectedKind(Core::Utils::PathChooser::Command); + m_ui.commandChooser->setPromptDialogTitle(tr("Mercurial Command")); +} + +void OptionsPageWidget::updateOptions() +{ + MercurialSettings *settings = MercurialPlugin::instance()->settings(); + m_ui.commandChooser->setPath(settings->application()); + m_ui.defaultUsernameLineEdit->setText(settings->userName()); + m_ui.defaultEmailLineEdit->setText(settings->email()); + m_ui.logEntriesCount->setValue(settings->logCount()); + m_ui.timeout->setValue(settings->timeoutSeconds()); + m_ui.promptOnSubmitCheckBox->setChecked(settings->prompt()); +} + +void OptionsPageWidget::saveOptions() +{ + MercurialSettings *settings = MercurialPlugin::instance()->settings(); + + settings->writeSettings(m_ui.commandChooser->path(), m_ui.defaultUsernameLineEdit->text(), + m_ui.defaultEmailLineEdit->text(), m_ui.logEntriesCount->value(), + m_ui.timeout->value(), m_ui.promptOnSubmitCheckBox->isChecked()); +} + +OptionsPage::OptionsPage() +{ +} + +QString OptionsPage::id() const +{ + return QLatin1String("Mercurial"); +} + +QString OptionsPage::trName() const +{ + return tr("Mercurial"); +} + +QString OptionsPage::category() const +{ + return QLatin1String(VCSBase::Constants::VCS_SETTINGS_CATEGORY); +} + +QString OptionsPage::trCategory() const +{ + return QCoreApplication::translate("VCSBase", VCSBase::Constants::VCS_SETTINGS_CATEGORY); +} + +QWidget *OptionsPage::createPage(QWidget *parent) +{ + if (!optionsPageWidget) + optionsPageWidget = new OptionsPageWidget(parent); + optionsPageWidget.data()->updateOptions(); + return optionsPageWidget; +} + +void OptionsPage::apply() +{ + if (!optionsPageWidget) + return; + optionsPageWidget.data()->saveOptions(); + //assume success and emit signal that settings are changed; + emit settingsChanged(); +} + diff --git a/src/plugins/mercurial/optionspage.h b/src/plugins/mercurial/optionspage.h new file mode 100644 index 0000000000000000000000000000000000000000..1e68c31b95444a35590b2e30b0437094d278a06a --- /dev/null +++ b/src/plugins/mercurial/optionspage.h @@ -0,0 +1,81 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef OPTIONSPAGE_H +#define OPTIONSPAGE_H + +#include "ui_optionspage.h" + +#include <coreplugin/dialogs/ioptionspage.h> + +#include <QtGui/QWidget> +#include <QtCore/QPointer> + +namespace Mercurial { +namespace Internal { + +class OptionsPageWidget : public QWidget +{ + Q_OBJECT +public: + explicit OptionsPageWidget(QWidget *parent = 0); + void updateOptions(); + void saveOptions(); + +private: + Ui::OptionsPage m_ui; +}; + + +class OptionsPage : public Core::IOptionsPage +{ + Q_OBJECT + +public: + OptionsPage(); + QString id() const; + QString trName() const; + QString category() const; + QString trCategory() const; + + QWidget *createPage(QWidget *parent); + void apply(); + void finish() { } + +signals: + void settingsChanged(); + +private: + QPointer<OptionsPageWidget> optionsPageWidget; +}; + +} // namespace Internal +} // namespace Mercurial + +#endif // OPTIONSPAGE_H diff --git a/src/plugins/mercurial/optionspage.ui b/src/plugins/mercurial/optionspage.ui new file mode 100644 index 0000000000000000000000000000000000000000..7c149f283a43d215ae1272239bd72f5d243b63f7 --- /dev/null +++ b/src/plugins/mercurial/optionspage.ui @@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Mercurial::Internal::OptionsPage</class> + <widget class="QWidget" name="Mercurial::Internal::OptionsPage"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>300</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QFormLayout" name="formLayout"> + <property name="fieldGrowthPolicy"> + <enum>QFormLayout::AllNonFixedFieldsGrow</enum> + </property> + <item row="0" column="0"> + <widget class="QLabel" name="mercurialCommandLabel"> + <property name="text"> + <string>Mercurial Command:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="Core::Utils::PathChooser" name="commandChooser" native="true"/> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="showLogEntriesLabel"> + <property name="text"> + <string>Show Log Entries:</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QSpinBox" name="logEntriesCount"> + <property name="toolTip"> + <string>The number of recent commit logs to show, choose 0 to see all enteries</string> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="timeoutSecondsLabel"> + <property name="text"> + <string>Timeout (Seconds):</string> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QSpinBox" name="timeout"> + <property name="value"> + <number>30</number> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QLabel" name="promptOnSubmitLabel"> + <property name="text"> + <string>Prompt On Submit</string> + </property> + </widget> + </item> + <item row="5" column="1"> + <widget class="QCheckBox" name="promptOnSubmitCheckBox"> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="defaultUsernameLabel"> + <property name="toolTip"> + <string>Username to use by default on commit.</string> + </property> + <property name="text"> + <string>Default Username:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLineEdit" name="defaultUsernameLineEdit"> + <property name="toolTip"> + <string>Username to use by default on commit.</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="defaultEmailLabel"> + <property name="toolTip"> + <string>Email to use by default on commit.</string> + </property> + <property name="text"> + <string>Default Email:</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLineEdit" name="defaultEmailLineEdit"> + <property name="toolTip"> + <string>Email to use by default on commit.</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>Core::Utils::PathChooser</class> + <extends>QWidget</extends> + <header location="global">utils/pathchooser.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/src/plugins/mercurial/revertdialog.cpp b/src/plugins/mercurial/revertdialog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d16345feb05817cecedeef41e526aa2dacc0e582 --- /dev/null +++ b/src/plugins/mercurial/revertdialog.cpp @@ -0,0 +1,56 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "revertdialog.h" + +using namespace Mercurial::Internal; + +RevertDialog::RevertDialog(QWidget *parent) : + QDialog(parent), + m_ui(new Ui::RevertDialog) +{ + m_ui->setupUi(this); +} + +RevertDialog::~RevertDialog() +{ + delete m_ui; +} + +void RevertDialog::changeEvent(QEvent *e) +{ + QDialog::changeEvent(e); + switch (e->type()) { + case QEvent::LanguageChange: + m_ui->retranslateUi(this); + break; + default: + break; + } +} diff --git a/src/plugins/mercurial/revertdialog.h b/src/plugins/mercurial/revertdialog.h new file mode 100644 index 0000000000000000000000000000000000000000..3bb345e0e2936a18a4eecc53b62b551453fc99ea --- /dev/null +++ b/src/plugins/mercurial/revertdialog.h @@ -0,0 +1,60 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef REVERTDIALOG_H +#define REVERTDIALOG_H + +#include "ui_revertdialog.h" + +#include <QtGui/QDialog> + + +namespace Mercurial { +namespace Internal { + +class mercurialPlugin; + +class RevertDialog : public QDialog +{ + Q_OBJECT +public: + RevertDialog(QWidget *parent = 0); + ~RevertDialog(); + +protected: + void changeEvent(QEvent *e); + +private: + Ui::RevertDialog *m_ui; + friend class MercurialPlugin; +}; + +} // namespace Internal +} // namespace Mercurial +#endif // REVERTDIALOG_H diff --git a/src/plugins/mercurial/revertdialog.ui b/src/plugins/mercurial/revertdialog.ui new file mode 100644 index 0000000000000000000000000000000000000000..66876dc6f938e66a23ba47fecb673f62d5976020 --- /dev/null +++ b/src/plugins/mercurial/revertdialog.ui @@ -0,0 +1,99 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Mercurial::Internal::RevertDialog</class> + <widget class="QDialog" name="Mercurial::Internal::RevertDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>162</height> + </rect> + </property> + <property name="windowTitle"> + <string>Revert</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Specify a revision other than the default?</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <widget class="QWidget" name="formLayoutWidget"> + <property name="geometry"> + <rect> + <x>10</x> + <y>30</y> + <width>361</width> + <height>51</height> + </rect> + </property> + <layout class="QFormLayout" name="formLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="revisionLabel"> + <property name="text"> + <string>Revision:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="revisionLineEdit"/> + </item> + </layout> + </widget> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>Mercurial::Internal::RevertDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>Mercurial::Internal::RevertDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/plugins/mercurial/srcdestdialog.cpp b/src/plugins/mercurial/srcdestdialog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b78c9d0d4e9d803ea18c608615c9d03e01494d9f --- /dev/null +++ b/src/plugins/mercurial/srcdestdialog.cpp @@ -0,0 +1,74 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "srcdestdialog.h" +#include "ui_srcdestdialog.h" + + +using namespace Mercurial::Internal; + +SrcDestDialog::SrcDestDialog(QWidget *parent) : + QDialog(parent), + m_ui(new Ui::SrcDestDialog) +{ + m_ui->setupUi(this); + m_ui->localPathChooser->setExpectedKind(Core::Utils::PathChooser::Directory); +} + +SrcDestDialog::~SrcDestDialog() +{ + delete m_ui; +} + +void SrcDestDialog::setPathChooserKind(Core::Utils::PathChooser::Kind kind) +{ + m_ui->localPathChooser->setExpectedKind(kind); +} + +QString SrcDestDialog::getRepositoryString() +{ + if (m_ui->defaultButton->isChecked()) + return QString(); + else if (m_ui->localButton->isChecked()) + return m_ui->localPathChooser->path(); + else + return m_ui->urlLineEdit->text(); +} + +void SrcDestDialog::changeEvent(QEvent *e) +{ + QDialog::changeEvent(e); + switch (e->type()) { + case QEvent::LanguageChange: + m_ui->retranslateUi(this); + break; + default: + break; + } +} diff --git a/src/plugins/mercurial/srcdestdialog.h b/src/plugins/mercurial/srcdestdialog.h new file mode 100644 index 0000000000000000000000000000000000000000..d0d0080eba4e0bbcff9c5a20ab3e3df9a7d8b9ac --- /dev/null +++ b/src/plugins/mercurial/srcdestdialog.h @@ -0,0 +1,62 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Brian McGillion +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef SRCDESTDIALOG_H +#define SRCDESTDIALOG_H + +#include <QtGui/QDialog> +#include <utils/pathchooser.h> + +namespace Mercurial { +namespace Internal { + +namespace Ui { +class SrcDestDialog; +} + +class SrcDestDialog : public QDialog +{ + Q_OBJECT +public: + + SrcDestDialog(QWidget *parent = 0); + ~SrcDestDialog(); + void setPathChooserKind(Core::Utils::PathChooser::Kind kind); + QString getRepositoryString(); + +protected: + void changeEvent(QEvent *e); + +private: + Ui::SrcDestDialog *m_ui; +}; + +} // namespace Internal +} // namespace Mercurial +#endif // SRCDESTDIALOG_H diff --git a/src/plugins/mercurial/srcdestdialog.ui b/src/plugins/mercurial/srcdestdialog.ui new file mode 100644 index 0000000000000000000000000000000000000000..9677363ee95ac75deac2708f31542920ad00a69f --- /dev/null +++ b/src/plugins/mercurial/srcdestdialog.ui @@ -0,0 +1,152 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Mercurial::Internal::SrcDestDialog</class> + <widget class="QDialog" name="Mercurial::Internal::SrcDestDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>187</height> + </rect> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QRadioButton" name="defaultButton"> + <property name="text"> + <string>Default Location:</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QRadioButton" name="localButton"> + <property name="text"> + <string>Local filesystem:</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QRadioButton" name="urlButton"> + <property name="toolTip"> + <string>e.g. https://[user[:pass]@]host[:port]/[path]</string> + </property> + <property name="text"> + <string>Specify Url:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="Core::Utils::PathChooser" name="localPathChooser" native="true"> + <property name="enabled"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLineEdit" name="urlLineEdit"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="toolTip"> + <string>e.g. https://[user[:pass]@]host[:port]/[path]</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>Core::Utils::PathChooser</class> + <extends>QWidget</extends> + <header location="global">utils/pathchooser.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>Mercurial::Internal::SrcDestDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>257</x> + <y>177</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>Mercurial::Internal::SrcDestDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>325</x> + <y>177</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>urlButton</sender> + <signal>toggled(bool)</signal> + <receiver>urlLineEdit</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>80</x> + <y>121</y> + </hint> + <hint type="destinationlabel"> + <x>332</x> + <y>123</y> + </hint> + </hints> + </connection> + <connection> + <sender>localButton</sender> + <signal>toggled(bool)</signal> + <receiver>localPathChooser</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>112</x> + <y>81</y> + </hint> + <hint type="destinationlabel"> + <x>346</x> + <y>81</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index c74bda15a2abbaccc25408e3b96ba4dca4853a4e..77cf85e11dbb9be2eef081bcf5053b1af897ab42 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -34,6 +34,7 @@ SUBDIRS = plugin_coreplugin \ plugin_genericprojectmanager \ plugin_qmleditor \ plugin_qmlprojectmanager \ + plugin_mercurial \ debugger/dumper.pro plugin_coreplugin.subdir = coreplugin @@ -178,3 +179,9 @@ plugin_qmlprojectmanager.depends = plugin_texteditor plugin_qmlprojectmanager.depends += plugin_projectexplorer plugin_qmlprojectmanager.depends += plugin_help plugin_qmlprojectmanager.depends += plugin_qmleditor + +plugin_mercurial.subdir = mercurial +plugin_mercurial.depends = plugin_texteditor +plugin_mercurial.depends = plugin_vcsbase +plugin_mercurial.depends += plugin_projectexplorer +plugin_mercurial.depends += plugin_coreplugin diff --git a/src/plugins/vcsbase/basecheckoutwizardpage.ui b/src/plugins/vcsbase/basecheckoutwizardpage.ui index 7be84e63cb90832461ab5f3c7c680f3d2121a74b..6dc045d4985e3a0d73d99f8d02cea1641fa93543 100644 --- a/src/plugins/vcsbase/basecheckoutwizardpage.ui +++ b/src/plugins/vcsbase/basecheckoutwizardpage.ui @@ -29,6 +29,9 @@ </property> </widget> </item> + <item row="1" column="1"> + <widget class="Utils::ProjectNameValidatingLineEdit" name="checkoutDirectoryLineEdit"/> + </item> <item row="2" column="0"> <widget class="QLabel" name="pathLabel"> <property name="text"> @@ -39,9 +42,6 @@ <item row="2" column="1"> <widget class="Utils::PathChooser" name="pathChooser"/> </item> - <item row="1" column="1"> - <widget class="Utils::ProjectNameValidatingLineEdit" name="checkoutDirectoryLineEdit"/> - </item> </layout> </item> </layout>