VCS[hg, git]: Add support for repository creation.

Add repository creation operation to IVersionControl, implement for hg
and git, add convenience slot with prompts to VCSBasePlugin.
Add respective menu options and make menus are visible in case no VCS is
active.
Change project wizards extension page to list VCS that are capable of
repository creation in a QComboBox in case the directory is not managed
by another VCS (in which case it lists that one for operation 'add').
On that occasion, polish the Project selection to use a QComboBox as
well and add some smartness to find the most suitable project to add via
path matching.
This commit is contained in:
Friedemann Kleint
2010-01-12 16:45:21 +01:00
parent 5ab250fe57
commit d5271a086d
30 changed files with 454 additions and 188 deletions
+8 -5
View File
@@ -41,9 +41,10 @@ class CORE_EXPORT IVersionControl : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
enum Operation { AddOperation, DeleteOperation, OpenOperation }; enum Operation { AddOperation, DeleteOperation, OpenOperation,
CreateRepositoryOperation };
IVersionControl(QObject *parent = 0) : QObject(parent) {} explicit IVersionControl(QObject *parent = 0) : QObject(parent) {}
virtual ~IVersionControl() {} virtual ~IVersionControl() {}
virtual QString displayName() const = 0; virtual QString displayName() const = 0;
@@ -93,12 +94,14 @@ public:
/*! /*!
* Called after a file has been removed from the project (if the user * Called after a file has been removed from the project (if the user
* wants), e.g. 'p4 delete', 'svn delete'. * wants), e.g. 'p4 delete', 'svn delete'.
*
* You probably want to call VcsManager::showDeleteDialog, which asks the
* user to confirm the deletion.
*/ */
virtual bool vcsDelete(const QString &filename) = 0; virtual bool vcsDelete(const QString &filename) = 0;
/*!
* Called to initialize the version control systemin a directory.
*/
virtual bool vcsCreateRepository(const QString &directory) = 0;
signals: signals:
void repositoryChanged(const QString &repository); void repositoryChanged(const QString &repository);
void filesChanged(const QStringList &files); void filesChanged(const QStringList &files);
+6
View File
@@ -54,6 +54,7 @@ bool CVSControl::supportsOperation(Operation operation) const
case DeleteOperation: case DeleteOperation:
break; break;
case OpenOperation: case OpenOperation:
case CreateRepositoryOperation:
rc = false; rc = false;
break; break;
} }
@@ -78,6 +79,11 @@ bool CVSControl::vcsDelete(const QString &fileName)
return m_plugin->vcsDelete(fi.absolutePath(), fi.fileName()); return m_plugin->vcsDelete(fi.absolutePath(), fi.fileName());
} }
bool CVSControl::vcsCreateRepository(const QString &)
{
return false;
}
bool CVSControl::managesDirectory(const QString &directory) const bool CVSControl::managesDirectory(const QString &directory) const
{ {
return m_plugin->managesDirectory(directory); return m_plugin->managesDirectory(directory);
+1
View File
@@ -52,6 +52,7 @@ public:
virtual bool vcsOpen(const QString &fileName); virtual bool vcsOpen(const QString &fileName);
virtual bool vcsAdd(const QString &fileName); virtual bool vcsAdd(const QString &fileName);
virtual bool vcsDelete(const QString &filename); virtual bool vcsDelete(const QString &filename);
virtual bool vcsCreateRepository(const QString &directory);
void emitRepositoryChanged(const QString &s); void emitRepositoryChanged(const QString &s);
void emitFilesChanged(const QStringList &l); void emitFilesChanged(const QStringList &l);
+1 -1
View File
@@ -498,7 +498,7 @@ CVSSubmitEditor *CVSPlugin::openCVSSubmitEditor(const QString &fileName)
void CVSPlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as) void CVSPlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as)
{ {
if (!VCSBase::VCSBasePlugin::enableMenuAction(as, m_menuAction)) if (!enableMenuAction(as, m_menuAction))
return; return;
m_logRepositoryAction->setEnabled(currentState().hasTopLevel()); m_logRepositoryAction->setEnabled(currentState().hasTopLevel());
+16
View File
@@ -446,6 +446,22 @@ bool GitClient::synchronousReset(const QString &workingDirectory,
return true; return true;
} }
// Initialize repository
bool GitClient::synchronousInit(const QString &workingDirectory)
{
if (Git::Constants::debug)
qDebug() << Q_FUNC_INFO << workingDirectory;
QByteArray outputText;
QByteArray errorText;
const QStringList arguments(QLatin1String("init"));
const bool rc = synchronousGit(workingDirectory, arguments, &outputText, &errorText);
// '[Re]Initialized...'
VCSBase::VCSBaseOutputWindow::instance()->append(QString::fromLocal8Bit(outputText));
if (!rc)
VCSBase::VCSBaseOutputWindow::instance()->append(QString::fromLocal8Bit(errorText));
return rc;
}
bool GitClient::synchronousCheckout(const QString &workingDirectory, bool GitClient::synchronousCheckout(const QString &workingDirectory,
const QStringList &files, const QStringList &files,
QString *errorMessage) QString *errorMessage)
+1
View File
@@ -92,6 +92,7 @@ public:
bool synchronousAdd(const QString &workingDirectory, const QStringList &files); bool synchronousAdd(const QString &workingDirectory, const QStringList &files);
bool synchronousReset(const QString &workingDirectory, const QStringList &files); bool synchronousReset(const QString &workingDirectory, const QStringList &files);
bool synchronousReset(const QString &workingDirectory, const QStringList &files, QString *errorMessage); bool synchronousReset(const QString &workingDirectory, const QStringList &files, QString *errorMessage);
bool synchronousInit(const QString &workingDirectory);
bool synchronousCheckout(const QString &workingDirectory, const QStringList &files, QString *errorMessage); bool synchronousCheckout(const QString &workingDirectory, const QStringList &files, QString *errorMessage);
bool synchronousStash(const QString &workingDirectory, QString *errorMessage); bool synchronousStash(const QString &workingDirectory, QString *errorMessage);
bool synchronousBranchCmd(const QString &workingDirectory, QStringList branchArgs, bool synchronousBranchCmd(const QString &workingDirectory, QStringList branchArgs,
+13 -2
View File
@@ -122,6 +122,7 @@ GitPlugin::GitPlugin() :
m_undoFileAction(0), m_undoFileAction(0),
m_logRepositoryAction(0), m_logRepositoryAction(0),
m_undoRepositoryAction(0), m_undoRepositoryAction(0),
m_createRepositoryAction(0),
m_showAction(0), m_showAction(0),
m_stageAction(0), m_stageAction(0),
m_unstageAction(0), m_unstageAction(0),
@@ -306,6 +307,11 @@ bool GitPlugin::initialize(const QStringList &arguments, QString *errorMessage)
connect(m_undoRepositoryAction, SIGNAL(triggered()), this, SLOT(undoRepositoryChanges())); connect(m_undoRepositoryAction, SIGNAL(triggered()), this, SLOT(undoRepositoryChanges()));
gitContainer->addAction(command); gitContainer->addAction(command);
m_createRepositoryAction = new QAction(tr("Create Repository..."), this);
command = actionManager->registerAction(m_createRepositoryAction, "Git.CreateRepository", globalcontext);
connect(m_createRepositoryAction, SIGNAL(triggered()), this, SLOT(createRepository()));
gitContainer->addAction(command);
gitContainer->addAction(createSeparator(actionManager, globalcontext, QLatin1String("Git.Sep.Global"), this)); gitContainer->addAction(createSeparator(actionManager, globalcontext, QLatin1String("Git.Sep.Global"), this));
m_stashAction = new QAction(tr("Stash"), this); m_stashAction = new QAction(tr("Stash"), this);
@@ -677,9 +683,10 @@ void GitPlugin::stashList()
void GitPlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as) void GitPlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as)
{ {
if (!VCSBase::VCSBasePlugin::enableMenuAction(as, m_menuAction)) if (!enableMenuAction(as, m_menuAction))
return; return;
// Note: This menu is visible if there is no repository. Only
// 'Create Repository'/'Show' actions should be available.
const QString fileName = currentState().currentFileName(); const QString fileName = currentState().currentFileName();
m_diffAction->setParameter(fileName); m_diffAction->setParameter(fileName);
m_logAction->setParameter(fileName); m_logAction->setParameter(fileName);
@@ -708,9 +715,13 @@ void GitPlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as)
m_statusRepositoryAction->setEnabled(repositoryEnabled); m_statusRepositoryAction->setEnabled(repositoryEnabled);
m_branchListAction->setEnabled(repositoryEnabled); m_branchListAction->setEnabled(repositoryEnabled);
m_stashListAction->setEnabled(repositoryEnabled); m_stashListAction->setEnabled(repositoryEnabled);
m_stashAction->setEnabled(repositoryEnabled);
m_pullAction->setEnabled(repositoryEnabled);
m_commitAction->setEnabled(repositoryEnabled);
m_stashPopAction->setEnabled(repositoryEnabled); m_stashPopAction->setEnabled(repositoryEnabled);
m_logRepositoryAction->setEnabled(repositoryEnabled); m_logRepositoryAction->setEnabled(repositoryEnabled);
m_undoRepositoryAction->setEnabled(repositoryEnabled); m_undoRepositoryAction->setEnabled(repositoryEnabled);
m_pushAction->setEnabled(repositoryEnabled);
// Prompts for repo. // Prompts for repo.
m_showAction->setEnabled(true); m_showAction->setEnabled(true);
+1
View File
@@ -131,6 +131,7 @@ private:
Utils::ParameterAction *m_undoFileAction; Utils::ParameterAction *m_undoFileAction;
QAction *m_logRepositoryAction; QAction *m_logRepositoryAction;
QAction *m_undoRepositoryAction; QAction *m_undoRepositoryAction;
QAction *m_createRepositoryAction;
QAction *m_showAction; QAction *m_showAction;
Utils::ParameterAction *m_stageAction; Utils::ParameterAction *m_stageAction;
+9 -1
View File
@@ -29,6 +29,7 @@
#include "gitversioncontrol.h" #include "gitversioncontrol.h"
#include "gitclient.h" #include "gitclient.h"
#include "gitplugin.h"
namespace Git { namespace Git {
namespace Internal { namespace Internal {
@@ -52,6 +53,9 @@ bool GitVersionControl::supportsOperation(Operation operation) const
case DeleteOperation: case DeleteOperation:
case OpenOperation: case OpenOperation:
break; break;
case CreateRepositoryOperation:
rc = true;
break;
} }
return rc; return rc;
} }
@@ -72,10 +76,14 @@ bool GitVersionControl::vcsDelete(const QString & /*fileName*/)
return false; return false;
} }
bool GitVersionControl::vcsCreateRepository(const QString &directory)
{
return GitPlugin::instance()->gitClient()->synchronousInit(directory);
}
bool GitVersionControl::managesDirectory(const QString &directory) const bool GitVersionControl::managesDirectory(const QString &directory) const
{ {
return !GitClient::findRepositoryForDirectory(directory).isEmpty(); return !GitClient::findRepositoryForDirectory(directory).isEmpty();
} }
QString GitVersionControl::findTopLevelForDirectory(const QString &directory) const QString GitVersionControl::findTopLevelForDirectory(const QString &directory) const
+1
View File
@@ -53,6 +53,7 @@ public:
virtual bool vcsOpen(const QString &fileName); virtual bool vcsOpen(const QString &fileName);
virtual bool vcsAdd(const QString &fileName); virtual bool vcsAdd(const QString &fileName);
virtual bool vcsDelete(const QString &filename); virtual bool vcsDelete(const QString &filename);
virtual bool vcsCreateRepository(const QString &directory);
void emitFilesChanged(const QStringList &); void emitFilesChanged(const QStringList &);
+1
View File
@@ -107,6 +107,7 @@ const char * const IMPORT = "Mercurial.Action.Import";
const char * const INCOMING = "Mercurial.Action.Incoming"; const char * const INCOMING = "Mercurial.Action.Incoming";
const char * const OUTGOING = "Mercurial.Action.Outgoing"; const char * const OUTGOING = "Mercurial.Action.Outgoing";
const char * const COMMIT = "Mercurial.Action.Commit"; const char * const COMMIT = "Mercurial.Action.Commit";
const char * const CREATE_REPOSITORY = "Mercurial.Action.CreateRepository";
//Repository Management //Repository Management
const char * const MERGE = "Mercurial.Action.Merge"; const char * const MERGE = "Mercurial.Action.Merge";
+12
View File
@@ -366,6 +366,18 @@ void MercurialClient::revert(const QString &workingDir,
enqueueJob(job); enqueueJob(job);
} }
bool MercurialClient::createRepositorySync(const QString &workingDirectory)
{
const QStringList args(QLatin1String("init"));
QByteArray outputData;
if (!executeHgSynchronously(workingDirectory, args, &outputData))
return false;
QString output = QString::fromLocal8Bit(outputData);
output.remove(QLatin1Char('\r'));
VCSBase::VCSBaseOutputWindow::instance()->append(output);
return true;
}
void MercurialClient::status(const QString &workingDir, const QString &file) void MercurialClient::status(const QString &workingDir, const QString &file)
{ {
QStringList args(QLatin1String("status")); QStringList args(QLatin1String("status"));
+1
View File
@@ -88,6 +88,7 @@ public:
void statusWithSignal(const QString &repository); void statusWithSignal(const QString &repository);
void revertFile(const QString &workingDir, const QString &file, const QString &revision = QString()); void revertFile(const QString &workingDir, const QString &file, const QString &revision = QString());
void revertRepository(const QString &workingDir, const QString &revision = QString()); void revertRepository(const QString &workingDir, const QString &revision = QString());
bool createRepositorySync(const QString &workingDir);
void update(const QString &repositoryRoot, const QString &revision = QString()); void update(const QString &repositoryRoot, const QString &revision = QString());
void commit(const QString &repositoryRoot, void commit(const QString &repositoryRoot,
const QStringList &files, const QStringList &files,
+6 -3
View File
@@ -62,17 +62,15 @@ QString MercurialControl::findTopLevelForDirectory(const QString &directory) con
bool MercurialControl::supportsOperation(Operation operation) const bool MercurialControl::supportsOperation(Operation operation) const
{ {
bool supported = true; bool supported = true;
switch (operation) { switch (operation) {
case Core::IVersionControl::AddOperation: case Core::IVersionControl::AddOperation:
case Core::IVersionControl::DeleteOperation: case Core::IVersionControl::DeleteOperation:
case Core::IVersionControl::CreateRepositoryOperation:
break; break;
case Core::IVersionControl::OpenOperation: case Core::IVersionControl::OpenOperation:
default:
supported = false; supported = false;
break; break;
} }
return supported; return supported;
} }
@@ -94,6 +92,11 @@ bool MercurialControl::vcsDelete(const QString &filename)
return mercurialClient->remove(fi.absolutePath(), fi.fileName()); return mercurialClient->remove(fi.absolutePath(), fi.fileName());
} }
bool MercurialControl::vcsCreateRepository(const QString &directory)
{
return mercurialClient->createRepositorySync(directory);
}
bool MercurialControl::sccManaged(const QString &filename) bool MercurialControl::sccManaged(const QString &filename)
{ {
const QFileInfo fi(filename); const QFileInfo fi(filename);
+1
View File
@@ -56,6 +56,7 @@ public:
bool vcsOpen(const QString &fileName); bool vcsOpen(const QString &fileName);
bool vcsAdd(const QString &filename); bool vcsAdd(const QString &filename);
bool vcsDelete(const QString &filename); bool vcsDelete(const QString &filename);
bool vcsCreateRepository(const QString &directory);
bool sccManaged(const QString &filename); bool sccManaged(const QString &filename);
public slots: public slots:
+7 -1
View File
@@ -127,6 +127,7 @@ MercurialPlugin::MercurialPlugin() :
changeLog(0), changeLog(0),
m_addAction(0), m_addAction(0),
m_deleteAction(0), m_deleteAction(0),
m_createRepositoryAction(0),
m_menuAction(0) m_menuAction(0)
{ {
m_instance = this; m_instance = this;
@@ -429,6 +430,11 @@ void MercurialPlugin::createRepositoryActions(const QList<int> &context)
command->setDefaultKeySequence(QKeySequence(tr("Alt+H,Alt+C"))); command->setDefaultKeySequence(QKeySequence(tr("Alt+H,Alt+C")));
connect(action, SIGNAL(triggered()), this, SLOT(commit())); connect(action, SIGNAL(triggered()), this, SLOT(commit()));
mercurialContainer->addAction(command); mercurialContainer->addAction(command);
m_createRepositoryAction = new QAction(tr("Create Repository..."), this);
command = actionManager->registerAction(m_createRepositoryAction, QLatin1String(Constants::CREATE_REPOSITORY), context);
connect(m_createRepositoryAction, SIGNAL(triggered()), this, SLOT(createRepository()));
mercurialContainer->addAction(command);
} }
void MercurialPlugin::pull() void MercurialPlugin::pull()
@@ -675,7 +681,7 @@ void MercurialPlugin::createSeparator(const QList<int> &context, const QString &
void MercurialPlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as) void MercurialPlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as)
{ {
if (!VCSBase::VCSBasePlugin::enableMenuAction(as, m_menuAction)) if (!enableMenuAction(as, m_menuAction))
return; return;
const QString filename = currentState().currentFileName(); const QString filename = currentState().currentFileName();
+1
View File
@@ -166,6 +166,7 @@ private:
Utils::ParameterAction *revertFile; Utils::ParameterAction *revertFile;
Utils::ParameterAction *statusFile; Utils::ParameterAction *statusFile;
QAction *m_createRepositoryAction;
//submit editor actions //submit editor actions
QAction *editorCommit; QAction *editorCommit;
QAction *editorDiff; QAction *editorDiff;
+1 -1
View File
@@ -788,7 +788,7 @@ void PerforcePlugin::filelog(const QString &workingDir, const QStringList &fileN
void PerforcePlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as) void PerforcePlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as)
{ {
if (!VCSBase::VCSBasePlugin::enableMenuAction(as, m_menuAction)) if (!enableMenuAction(as, m_menuAction))
return; return;
m_logRepositoryAction->setEnabled(currentState().hasTopLevel()); m_logRepositoryAction->setEnabled(currentState().hasTopLevel());
@@ -50,14 +50,15 @@ QString PerforceVersionControl::displayName() const
bool PerforceVersionControl::supportsOperation(Operation operation) const bool PerforceVersionControl::supportsOperation(Operation operation) const
{ {
bool rc = true;
switch (operation) { switch (operation) {
case AddOperation: case AddOperation:
case DeleteOperation: case DeleteOperation:
case OpenOperation: case OpenOperation:
return true;
case CreateRepositoryOperation:
break; break;
} }
return rc; return false;
} }
bool PerforceVersionControl::vcsOpen(const QString &fileName) bool PerforceVersionControl::vcsOpen(const QString &fileName)
@@ -78,6 +79,11 @@ bool PerforceVersionControl::vcsDelete(const QString &fileName)
return m_plugin->vcsDelete(fi.absolutePath(), fi.fileName()); return m_plugin->vcsDelete(fi.absolutePath(), fi.fileName());
} }
bool PerforceVersionControl::vcsCreateRepository(const QString &)
{
return false;
}
bool PerforceVersionControl::managesDirectory(const QString &directory) const bool PerforceVersionControl::managesDirectory(const QString &directory) const
{ {
const bool rc = m_plugin->managesDirectory(directory); const bool rc = m_plugin->managesDirectory(directory);
@@ -52,6 +52,7 @@ public:
virtual bool vcsOpen(const QString &fileName); virtual bool vcsOpen(const QString &fileName);
virtual bool vcsAdd(const QString &fileName); virtual bool vcsAdd(const QString &fileName);
virtual bool vcsDelete(const QString &filename); virtual bool vcsDelete(const QString &filename);
virtual bool vcsCreateRepository(const QString &directory);
void emitRepositoryChanged(const QString &s); void emitRepositoryChanged(const QString &s);
void emitFilesChanged(const QStringList &l); void emitFilesChanged(const QStringList &l);
@@ -34,17 +34,23 @@
#include "nodesvisitor.h" #include "nodesvisitor.h"
#include "projectwizardpage.h" #include "projectwizardpage.h"
#include <utils/qtcassert.h>
#include <utils/stringutils.h>
#include <coreplugin/basefilewizard.h> #include <coreplugin/basefilewizard.h>
#include <coreplugin/dialogs/iwizard.h> #include <coreplugin/dialogs/iwizard.h>
#include <coreplugin/filemanager.h> #include <coreplugin/filemanager.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <coreplugin/iversioncontrol.h> #include <coreplugin/iversioncontrol.h>
#include <coreplugin/vcsmanager.h> #include <coreplugin/vcsmanager.h>
#include <extensionsystem/pluginmanager.h>
#include <QtCore/QVariant> #include <QtCore/QVariant>
#include <QtCore/QtAlgorithms>
#include <QtCore/QDebug> #include <QtCore/QDebug>
#include <QtCore/QFileInfo> #include <QtCore/QFileInfo>
#include <QtCore/QMultiMap> #include <QtCore/QMultiMap>
#include <QtCore/QDir>
enum { debugExtension = 0 }; enum { debugExtension = 0 };
@@ -54,43 +60,111 @@ typedef QList<ProjectNode *> ProjectNodeList;
namespace Internal { namespace Internal {
// --------- AllProjectNodesVisitor. Figure out all projects. // AllProjectNodesVisitor: Retrieve all projects (*.pri/*.pro).
// No sooner said then done.
class AllProjectNodesVisitor : public NodesVisitor class AllProjectNodesVisitor : public NodesVisitor
{ {
AllProjectNodesVisitor(ProjectNodeList &l) : m_projectNodes(l) {}
public: public:
static ProjectNodeList allProjects();
static ProjectNodeList allProjects(const ProjectExplorerPlugin *pe);
virtual void visitProjectNode(ProjectNode *node); virtual void visitProjectNode(ProjectNode *node);
private: private:
ProjectNodeList &m_projectNodes; ProjectNodeList m_projectNodes;
}; };
ProjectNodeList AllProjectNodesVisitor::allProjects(const ProjectExplorerPlugin *pe) ProjectNodeList AllProjectNodesVisitor::allProjects()
{ {
ProjectNodeList rc; AllProjectNodesVisitor visitor;
AllProjectNodesVisitor visitor(rc); ProjectExplorerPlugin::instance()->session()->sessionNode()->accept(&visitor);
pe->session()->sessionNode()->accept(&visitor); return visitor.m_projectNodes;
return rc;
} }
void AllProjectNodesVisitor::visitProjectNode(ProjectNode *node) void AllProjectNodesVisitor::visitProjectNode(ProjectNode *node)
{ {
if (node->supportedActions().contains(ProjectNode::AddFile)) if (node->supportedActions().contains(ProjectNode::AddFile))
m_projectNodes << node; m_projectNodes.push_back(node);
}
// ProjectEntry: Context entry for a *.pri/*.pro file. Stores name and path
// for quick sort and path search, provides operator<() for maps.
struct ProjectEntry {
enum Type { ProFile, PriFile }; // Sort order: 'pro' before 'pri'
ProjectEntry() : node(0), type(ProFile) {}
explicit ProjectEntry(ProjectNode *node);
int compare(const ProjectEntry &rhs) const;
ProjectNode *node;
QString nativeDirectory; // For matching against wizards' files, which are native.
QString fileName;
QString baseName;
Type type;
};
ProjectEntry::ProjectEntry(ProjectNode *n) :
node(n),
type(ProFile)
{
const QFileInfo fi(node->path());
fileName = fi.fileName();
baseName = fi.baseName();
if (fi.suffix() != QLatin1String("pro"))
type = PriFile;
nativeDirectory = QDir::toNativeSeparators(fi.absolutePath());
}
// Sort helper that sorts by base name and puts '*.pro' before '*.pri'
int ProjectEntry::compare(const ProjectEntry &rhs) const
{
if (const int brc = baseName.compare(rhs.baseName))
return brc;
if (type < rhs.type)
return -1;
if (type > rhs.type)
return 1;
return 0;
}
inline bool operator<(const ProjectEntry &pe1, const ProjectEntry &pe2)
{
return pe1.compare(pe2) < 0;
}
QDebug operator<<(QDebug d, const ProjectEntry &e)
{
d.nospace() << e.nativeDirectory << ' ' << e.fileName << ' ' << e.type;
return d;
} }
// --------- ProjectWizardContext // --------- ProjectWizardContext
struct ProjectWizardContext struct ProjectWizardContext
{ {
Core::IVersionControl *versionControl; ProjectWizardContext();
ProjectNodeList projects; void clear();
QList<Core::IVersionControl*> versionControls;
QList<ProjectEntry> projects;
ProjectWizardPage *page; ProjectWizardPage *page;
bool repositoryExists; // Is VCS 'add' sufficient, or should a repository be created?
QString commonDirectory;
}; };
ProjectWizardContext::ProjectWizardContext() :
page(0),
repositoryExists(false)
{
}
void ProjectWizardContext::clear()
{
versionControls.clear();
projects.clear();
commonDirectory.clear();
page = 0;
repositoryExists = false;
}
// ---- ProjectFileWizardExtension // ---- ProjectFileWizardExtension
ProjectFileWizardExtension::ProjectFileWizardExtension() ProjectFileWizardExtension::ProjectFileWizardExtension()
: m_context(0) : m_context(0)
@@ -102,85 +176,184 @@ ProjectFileWizardExtension::~ProjectFileWizardExtension()
delete m_context; delete m_context;
} }
// Find the project the new files should be added to given their common
// path. Either a direct match on the directory or the directory with
// the longest matching path (list containing"/project/subproject1" matching
// common path "/project/subproject1/newuserpath").
// This relies on 'pro' occurring before 'pri' in the list.
static int findMatchingProject(const QList<ProjectEntry> &projects,
const QString &commonPath)
{
if (projects.isEmpty() || commonPath.isEmpty())
return -1;
int bestMatch = -1;
int bestMatchLength = 0;
const int count = projects.size();
for (int p = 0; p < count; p++) {
// Direct match or better match? (note that the wizards' files are native).
const QString &projectDirectory = projects.at(p).nativeDirectory;
if (projectDirectory == commonPath)
return p;
if (projectDirectory.size() > bestMatchLength
&& commonPath.startsWith(projectDirectory)) {
bestMatchLength = projectDirectory.size();
bestMatch = p;
}
}
return bestMatch;
}
void ProjectFileWizardExtension::firstExtensionPageShown(const QList<Core::GeneratedFile> &files) void ProjectFileWizardExtension::firstExtensionPageShown(const QList<Core::GeneratedFile> &files)
{ {
if (debugExtension) if (debugExtension)
qDebug() << Q_FUNC_INFO << files.size(); qDebug() << Q_FUNC_INFO << files.size();
// Setup files display and version control depending on path // Parametrize wizard page: find best project to add to, set up files display and
// version control depending on path
QStringList fileNames; QStringList fileNames;
foreach (const Core::GeneratedFile &f, files) foreach (const Core::GeneratedFile &f, files)
fileNames.push_back(f.path()); fileNames.push_back(f.path());
m_context->commonDirectory = Utils::commonPath(fileNames);
const QString directory = QFileInfo(fileNames.front()).absolutePath(); m_context->page->setFilesDisplay(m_context->commonDirectory, fileNames);
m_context->versionControl = Core::ICore::instance()->vcsManager()->findVersionControlForDirectory(directory); // Find best project (Entry at 0 is 'None').
const int bestProjectIndex = findMatchingProject(m_context->projects, m_context->commonDirectory);
m_context->page->setFilesDisplay(fileNames); if (bestProjectIndex == -1) {
m_context->page->setCurrentProjectIndex(0);
const bool canAddToVCS = m_context->versionControl && m_context->versionControl->supportsOperation(Core::IVersionControl::AddOperation); } else {
if (m_context->versionControl) m_context->page->setCurrentProjectIndex(bestProjectIndex + 1);
m_context->page->setVCSDisplay(m_context->versionControl->displayName()); }
m_context->page->setAddToVersionControlEnabled(canAddToVCS); initializeVersionControlChoices();
} }
static ProjectNode *currentProject() void ProjectFileWizardExtension::initializeVersionControlChoices()
{ {
if (Node *currentNode = ProjectExplorerPlugin::instance()->currentNode()) // Figure out version control situation:
if (ProjectNode *currentProjectNode = qobject_cast<ProjectNode *>(currentNode)) // 1) Directory is managed and VCS supports "Add" -> List it
return currentProjectNode; // 2) Directory is managed and VCS does not support "Add" -> None available
return 0; // 3) Directory is not managed -> Offer all VCS that support "CreateRepository"
if (!m_context->commonDirectory.isEmpty()) {
Core::IVersionControl *managingControl = Core::ICore::instance()->vcsManager()->findVersionControlForDirectory(m_context->commonDirectory);
if (managingControl) {
// Under VCS
if (managingControl->supportsOperation(Core::IVersionControl::AddOperation)) {
m_context->versionControls.push_back(managingControl);
m_context->repositoryExists = true;
}
} else {
// Create
foreach (Core::IVersionControl *vc, ExtensionSystem::PluginManager::instance()->getObjects<Core::IVersionControl>())
if (vc->supportsOperation(Core::IVersionControl::CreateRepositoryOperation))
m_context->versionControls.push_back(vc);
m_context->repositoryExists = false;
}
} // has a common root.
// Compile names
//: No version control system selected
QStringList versionControlChoices = QStringList(tr("<None>"));
foreach(const Core::IVersionControl *c, m_context->versionControls)
versionControlChoices.push_back(c->displayName());
m_context->page->setVersionControls(versionControlChoices);
// Enable adding to version control by default.
if (m_context->repositoryExists && versionControlChoices.size() >= 2)
m_context->page->setVersionControlIndex(1);
} }
QList<QWizardPage *> ProjectFileWizardExtension::extensionPages(const Core::IWizard *wizard) QList<QWizardPage *> ProjectFileWizardExtension::extensionPages(const Core::IWizard *wizard)
{ {
if (!m_context) if (!m_context) {
m_context = new ProjectWizardContext; m_context = new ProjectWizardContext;
} else {
m_context->clear();
}
// Init context with page and projects // Init context with page and projects
m_context->page = new ProjectWizardPage; m_context->page = new ProjectWizardPage;
m_context->versionControl = 0; // Project list remains the same over duration of wizard execution
m_context->projects = AllProjectNodesVisitor::allProjects(ProjectExplorerPlugin::instance()); // Note that projects cannot be added to projects.
// Set up project list which remains the same over duration of wizard execution initProjectChoices(wizard->kind() != Core::IWizard::ProjectWizard);
// Disable "add project to project"
const bool hasProjects = !m_context->projects.empty();
if (hasProjects) {
m_context->page->setProjects(m_context->projects);
m_context->page->setCurrentProject(currentProject());
}
m_context->page->setAddToProjectEnabled(hasProjects && wizard->kind() != Core::IWizard::ProjectWizard);
return QList<QWizardPage *>() << m_context->page; return QList<QWizardPage *>() << m_context->page;
} }
void ProjectFileWizardExtension::initProjectChoices(bool enabled)
{
// Set up project list which remains the same over duration of wizard execution
//: No project selected
QStringList projectChoices(tr("<None>"));
if (enabled) {
typedef QMap<ProjectEntry, bool> ProjectEntryMap;
// Sort by base name and purge duplicated entries (resulting from dependencies)
// via Map.
ProjectEntryMap entryMap;
foreach(ProjectNode *n, AllProjectNodesVisitor::allProjects())
entryMap.insert(ProjectEntry(n), true);
// Collect names
const ProjectEntryMap::const_iterator cend = entryMap.constEnd();
for (ProjectEntryMap::const_iterator it = entryMap.constBegin(); it != cend; ++it) {
m_context->projects.push_back(it.key());
projectChoices.push_back(it.key().fileName);
}
}
m_context->page->setProjects(projectChoices);
}
bool ProjectFileWizardExtension::process(const QList<Core::GeneratedFile> &files, QString *errorMessage) bool ProjectFileWizardExtension::process(const QList<Core::GeneratedFile> &files, QString *errorMessage)
{
return processProject(files, errorMessage) &&
processVersionControl(files, errorMessage);
}
// Add files to project && version control
bool ProjectFileWizardExtension::processProject(const QList<Core::GeneratedFile> &files, QString *errorMessage)
{ {
typedef QMultiMap<FileType, QString> TypeFileMap; typedef QMultiMap<FileType, QString> TypeFileMap;
// Add files to project && version control
if (m_context->page->addToProject()) { // Add files to project (Entry at 0 is 'None').
ProjectNode *project = m_context->page->currentProject(); const int projectIndex = m_context->page->currentProjectIndex() - 1;
// Split into lists by file type and add if (projectIndex < 0 || projectIndex >= m_context->projects.size())
TypeFileMap typeFileMap; return true;
foreach (const Core::GeneratedFile &generatedFile, files) { ProjectNode *project = m_context->projects.at(projectIndex).node;
const QString path = generatedFile.path(); // Split into lists by file type and bulk-add them.
typeFileMap.insert(typeForFileName(Core::ICore::instance()->mimeDatabase(), path), path); TypeFileMap typeFileMap;
} const Core::MimeDatabase *mdb = Core::ICore::instance()->mimeDatabase();
foreach (FileType type, typeFileMap.uniqueKeys()) { foreach (const Core::GeneratedFile &generatedFile, files) {
const QStringList files = typeFileMap.values(type); const QString path = generatedFile.path();
if (!project->addFiles(type, files)) { typeFileMap.insert(typeForFileName(mdb, path), path);
*errorMessage = tr("Failed to add one or more files to project\n'%1' (%2)."). }
arg(project->path(), files.join(QLatin1String(","))); foreach (FileType type, typeFileMap.uniqueKeys()) {
return false; const QStringList files = typeFileMap.values(type);
} if (!project->addFiles(type, files)) {
*errorMessage = tr("Failed to add one or more files to project\n'%1' (%2).").
arg(project->path(), files.join(QString(QLatin1Char(','))));
return false;
} }
} }
// Add files to version control return true;
if (m_context->page->addToVersionControl()) { }
bool ProjectFileWizardExtension::processVersionControl(const QList<Core::GeneratedFile> &files, QString *errorMessage)
{
// Add files to version control (Entry at 0 is 'None').
const int vcsIndex = m_context->page->versionControlIndex() - 1;
if (vcsIndex < 0 || vcsIndex >= m_context->versionControls.size())
return true;
QTC_ASSERT(!m_context->commonDirectory.isEmpty(), return false);
Core::IVersionControl *versionControl = m_context->versionControls.at(vcsIndex);
// Create repository?
if (!m_context->repositoryExists) {
QTC_ASSERT(versionControl->supportsOperation(Core::IVersionControl::CreateRepositoryOperation), return false);
if (!versionControl->vcsCreateRepository(m_context->commonDirectory)) {
*errorMessage = tr("A version control system repository could not be created in '%1'.").arg(m_context->commonDirectory);
return false;
}
}
// Add files if supported.
if (versionControl->supportsOperation(Core::IVersionControl::AddOperation)) {
foreach (const Core::GeneratedFile &generatedFile, files) { foreach (const Core::GeneratedFile &generatedFile, files) {
if (!m_context->versionControl->vcsAdd(generatedFile.path())) { if (!versionControl->vcsAdd(generatedFile.path())) {
*errorMessage = tr("Failed to add '%1' to the version control system.").arg(generatedFile.path()); *errorMessage = tr("Failed to add '%1' to the version control system.").arg(generatedFile.path());
return false; return false;
} }
} }
} }
return true; return true;
} }
@@ -38,10 +38,10 @@ namespace Internal {
struct ProjectWizardContext; struct ProjectWizardContext;
/* /* Final file wizard processing steps:
Adds final page allowing the user to add files to project && version control * 1) Add to a project file (*.pri/ *.pro)
to BaseFileWizard. * 2) Initialize a version control repository (unless the path is already
*/ * managed) and do 'add' if the VCS supports it. */
class ProjectFileWizardExtension : public Core::IFileWizardExtension class ProjectFileWizardExtension : public Core::IFileWizardExtension
{ {
Q_OBJECT Q_OBJECT
@@ -56,6 +56,11 @@ public slots:
virtual void firstExtensionPageShown(const QList<Core::GeneratedFile> &); virtual void firstExtensionPageShown(const QList<Core::GeneratedFile> &);
private: private:
void initProjectChoices(bool enabled);
void initializeVersionControlChoices();
bool processProject(const QList<Core::GeneratedFile> &files, QString *errorMessage);
bool processVersionControl(const QList<Core::GeneratedFile> &files, QString *errorMessage);
ProjectWizardContext *m_context; ProjectWizardContext *m_context;
}; };
@@ -29,27 +29,17 @@
#include "projectwizardpage.h" #include "projectwizardpage.h"
#include "ui_projectwizardpage.h" #include "ui_projectwizardpage.h"
#include "projectnodes.h"
#include <utils/stringutils.h>
#include <QtCore/QDebug>
#include <QtCore/QFileInfo>
#include <QtCore/QTextStream> #include <QtCore/QTextStream>
using namespace ProjectExplorer; using namespace ProjectExplorer;
using namespace Internal; using namespace Internal;
Q_DECLARE_METATYPE(ProjectExplorer::ProjectNode*)
ProjectWizardPage::ProjectWizardPage(QWidget *parent) : ProjectWizardPage::ProjectWizardPage(QWidget *parent) :
QWizardPage(parent), QWizardPage(parent),
m_ui(new Ui::WizardPage) m_ui(new Ui::WizardPage)
{ {
m_ui->setupUi(this); m_ui->setupUi(this);
connect(m_ui->addToProjectCheckBox, SIGNAL(toggled(bool)),
m_ui->projectComboBox, SLOT(setEnabled(bool)));
} }
ProjectWizardPage::~ProjectWizardPage() ProjectWizardPage::~ProjectWizardPage()
@@ -57,63 +47,36 @@ ProjectWizardPage::~ProjectWizardPage()
delete m_ui; delete m_ui;
} }
void ProjectWizardPage::setProjects(const QList<ProjectNode*> &projectNodes) void ProjectWizardPage::setProjects(const QStringList &p)
{ {
QMap<QString,ProjectNode*> projectMap;
foreach (ProjectNode *node, projectNodes) {
QString name = QFileInfo(node->path()).fileName();
if (!projectMap.contains(name))
projectMap.insert(name, node);
}
m_ui->projectComboBox->clear(); m_ui->projectComboBox->clear();
foreach (const QString &name, projectMap.keys()) { m_ui->projectComboBox->addItems(p);
m_ui->projectComboBox->addItem(name, qVariantFromValue(projectMap.value(name)));
}
} }
void ProjectWizardPage::setAddToProjectEnabled(bool b) int ProjectWizardPage::currentProjectIndex() const
{ {
m_ui->projectLabel->setEnabled(b); return m_ui->projectComboBox->currentIndex();
m_ui->addToProjectLabel->setEnabled(b);
m_ui->addToProjectCheckBox->setChecked(b);
m_ui->addToProjectCheckBox->setEnabled(b);
m_ui->projectComboBox->setEnabled(b);
} }
ProjectNode *ProjectWizardPage::currentProject() const void ProjectWizardPage::setCurrentProjectIndex(int idx)
{ {
QVariant variant = m_ui->projectComboBox->itemData(m_ui->projectComboBox->currentIndex()); m_ui->projectComboBox->setCurrentIndex(idx);
return qVariantValue<ProjectNode*>(variant);
} }
void ProjectWizardPage::setCurrentProject(ProjectNode *projectNode) void ProjectWizardPage::setVersionControls(const QStringList &vcs)
{ {
if (!projectNode) m_ui->addToVersionControlComboBox->clear();
return; m_ui->addToVersionControlComboBox->addItems(vcs);
for (int i = 0; i < m_ui->projectComboBox->count(); ++i) {
if (qVariantValue<ProjectNode*>(m_ui->projectComboBox->itemData(i)) == projectNode) {
m_ui->projectComboBox->setCurrentIndex(i);
return;
}
}
} }
bool ProjectWizardPage::addToProject() const int ProjectWizardPage::versionControlIndex() const
{ {
return m_ui->addToProjectCheckBox->isChecked(); return m_ui->addToVersionControlComboBox->currentIndex();
} }
bool ProjectWizardPage::addToVersionControl() const void ProjectWizardPage::setVersionControlIndex(int idx)
{ {
return m_ui->addToVersionControlCheckBox->isChecked(); m_ui->addToVersionControlComboBox->setCurrentIndex(idx);
}
void ProjectWizardPage::setAddToVersionControlEnabled(bool b)
{
m_ui->addToVersionControlLabel->setEnabled(b);
m_ui->addToVersionControlCheckBox->setChecked(b);
m_ui->addToVersionControlCheckBox->setEnabled(b);
} }
void ProjectWizardPage::changeEvent(QEvent *e) void ProjectWizardPage::changeEvent(QEvent *e)
@@ -128,15 +91,9 @@ void ProjectWizardPage::changeEvent(QEvent *e)
} }
} }
void ProjectWizardPage::setVCSDisplay(const QString &vcsName) void ProjectWizardPage::setFilesDisplay(const QString &commonPath, const QStringList &files)
{
m_ui->addToVersionControlLabel->setText(tr("Add to &VCS (%1)").arg(vcsName));
}
void ProjectWizardPage::setFilesDisplay(const QStringList &files)
{ {
QString fileMessage; QString fileMessage;
const QString commonPath = Utils::commonPath(files);
{ {
QTextStream str(&fileMessage); QTextStream str(&fileMessage);
str << "<qt>" str << "<qt>"
@@ -32,16 +32,7 @@
#include <QtGui/QWizardPage> #include <QtGui/QWizardPage>
namespace Core {
class IVersionControl;
class SCCManager;
class FileManager;
}
namespace ProjectExplorer { namespace ProjectExplorer {
class ProjectNode;
namespace Internal { namespace Internal {
namespace Ui { namespace Ui {
@@ -55,19 +46,17 @@ public:
explicit ProjectWizardPage(QWidget *parent = 0); explicit ProjectWizardPage(QWidget *parent = 0);
virtual ~ProjectWizardPage(); virtual ~ProjectWizardPage();
void setProjects(const QList<ProjectNode *> &); void setProjects(const QStringList &);
void setCurrentProject(ProjectNode *); int currentProjectIndex() const;
void setCurrentProjectIndex(int);
ProjectNode *currentProject() const; void setVersionControls(const QStringList &);
void setAddToProjectEnabled(bool b); int versionControlIndex() const;
bool addToProject() const; void setVersionControlIndex(int);
bool addToVersionControl() const; // Returns the common path
void setAddToVersionControlEnabled(bool b); void setFilesDisplay(const QString &commonPath, const QStringList &files);
void setVCSDisplay(const QString &vcsName);
void setFilesDisplay(const QStringList &files);
protected: protected:
virtual void changeEvent(QEvent *e); virtual void changeEvent(QEvent *e);
@@ -20,43 +20,42 @@
<enum>QFormLayout::ExpandingFieldsGrow</enum> <enum>QFormLayout::ExpandingFieldsGrow</enum>
</property> </property>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="addToProjectLabel">
<property name="text">
<string>&amp;Add to Project</string>
</property>
<property name="buddy">
<cstring>addToProjectCheckBox</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="addToProjectCheckBox"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="projectLabel"> <widget class="QLabel" name="projectLabel">
<property name="text"> <property name="text">
<string>&amp;Project</string> <string>Add to &amp;project:</string>
</property> </property>
<property name="buddy"> <property name="buddy">
<cstring>projectComboBox</cstring> <cstring>projectComboBox</cstring>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item row="0" column="1">
<widget class="QComboBox" name="projectComboBox"/> <widget class="QComboBox" name="projectComboBox">
<item>
<property name="text">
<string notr="true">A very long project name indeed</string>
</property>
</item>
</widget>
</item> </item>
<item row="2" column="0"> <item row="1" column="0">
<widget class="QLabel" name="addToVersionControlLabel"> <widget class="QLabel" name="addToVersionControlLabel">
<property name="text"> <property name="text">
<string>Add to &amp;version control</string> <string>Add to &amp;version control:</string>
</property> </property>
<property name="buddy"> <property name="buddy">
<cstring>addToVersionControlCheckBox</cstring> <cstring>addToVersionControlComboBox</cstring>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="1" column="1">
<widget class="QCheckBox" name="addToVersionControlCheckBox"/> <widget class="QComboBox" name="addToVersionControlComboBox">
<item>
<property name="text">
<string notr="true">A very long version control system name</string>
</property>
</item>
</widget>
</item> </item>
</layout> </layout>
</item> </item>
@@ -96,7 +95,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>611</width> <width>611</width>
<height>305</height> <height>328</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
@@ -54,6 +54,7 @@ bool SubversionControl::supportsOperation(Operation operation) const
case DeleteOperation: case DeleteOperation:
break; break;
case OpenOperation: case OpenOperation:
case CreateRepositoryOperation:
rc = false; rc = false;
break; break;
} }
@@ -78,6 +79,11 @@ bool SubversionControl::vcsDelete(const QString &fileName)
return m_plugin->vcsDelete(fi.absolutePath(), fi.fileName()); return m_plugin->vcsDelete(fi.absolutePath(), fi.fileName());
} }
bool SubversionControl::vcsCreateRepository(const QString &)
{
return false;
}
bool SubversionControl::managesDirectory(const QString &directory) const bool SubversionControl::managesDirectory(const QString &directory) const
{ {
return m_plugin->managesDirectory(directory); return m_plugin->managesDirectory(directory);
@@ -52,6 +52,7 @@ public:
virtual bool vcsOpen(const QString &fileName); virtual bool vcsOpen(const QString &fileName);
virtual bool vcsAdd(const QString &fileName); virtual bool vcsAdd(const QString &fileName);
virtual bool vcsDelete(const QString &filename); virtual bool vcsDelete(const QString &filename);
virtual bool vcsCreateRepository(const QString &directory);
void emitRepositoryChanged(const QString &); void emitRepositoryChanged(const QString &);
void emitFilesChanged(const QStringList &); void emitFilesChanged(const QStringList &);
+1 -1
View File
@@ -528,7 +528,7 @@ SubversionSubmitEditor *SubversionPlugin::openSubversionSubmitEditor(const QStri
void SubversionPlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as) void SubversionPlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as)
{ {
if (!VCSBase::VCSBasePlugin::enableMenuAction(as, m_menuAction)) if (!enableMenuAction(as, m_menuAction))
return; return;
m_logRepositoryAction->setEnabled(currentState().hasTopLevel()); m_logRepositoryAction->setEnabled(currentState().hasTopLevel());
+55 -4
View File
@@ -47,6 +47,8 @@
#include <QtGui/QAction> #include <QtGui/QAction>
#include <QtGui/QMessageBox> #include <QtGui/QMessageBox>
#include <QtGui/QFileDialog>
#include <QtGui/QMainWindow>
enum { debug = 0 }; enum { debug = 0 };
@@ -345,6 +347,8 @@ VCSBASE_EXPORT QDebug operator<<(QDebug in, const VCSBasePluginState &state)
struct VCSBasePluginPrivate { struct VCSBasePluginPrivate {
explicit VCSBasePluginPrivate(const QString &submitEditorId); explicit VCSBasePluginPrivate(const QString &submitEditorId);
inline bool supportsRepositoryCreation() const;
const QString m_submitEditorId; const QString m_submitEditorId;
Core::IVersionControl *m_versionControl; Core::IVersionControl *m_versionControl;
VCSBasePluginState m_state; VCSBasePluginState m_state;
@@ -360,6 +364,11 @@ VCSBasePluginPrivate::VCSBasePluginPrivate(const QString &submitEditorId) :
{ {
} }
bool VCSBasePluginPrivate::supportsRepositoryCreation() const
{
return m_versionControl && m_versionControl->supportsOperation(Core::IVersionControl::CreateRepositoryOperation);
}
Internal::StateListener *VCSBasePluginPrivate::m_listener = 0; Internal::StateListener *VCSBasePluginPrivate::m_listener = 0;
VCSBasePlugin::VCSBasePlugin(const QString &submitEditorId) : VCSBasePlugin::VCSBasePlugin(const QString &submitEditorId) :
@@ -427,15 +436,17 @@ const VCSBasePluginState &VCSBasePlugin::currentState() const
return d->m_state; return d->m_state;
} }
bool VCSBasePlugin::enableMenuAction(ActionState as, QAction *menuAction) bool VCSBasePlugin::enableMenuAction(ActionState as, QAction *menuAction) const
{ {
if (debug) if (debug)
qDebug() << "enableMenuAction" << menuAction->text() << as; qDebug() << "enableMenuAction" << menuAction->text() << as;
switch (as) { switch (as) {
case VCSBase::VCSBasePlugin::NoVCSEnabled: case VCSBase::VCSBasePlugin::NoVCSEnabled: {
const bool supportsCreation = d->supportsRepositoryCreation();
menuAction->setVisible(true); menuAction->setVisible(true);
menuAction->setEnabled(false); menuAction->setEnabled(supportsCreation);
return false; return supportsCreation;
}
case VCSBase::VCSBasePlugin::OtherVCSEnabled: case VCSBase::VCSBasePlugin::OtherVCSEnabled:
menuAction->setVisible(false); menuAction->setVisible(false);
return false; return false;
@@ -456,6 +467,46 @@ void VCSBasePlugin::promptToDeleteCurrentFile()
QMessageBox::warning(0, tr("Version Control"), tr("The file '%1' could not be deleted.").arg(state.currentFile()), QMessageBox::Ok); QMessageBox::warning(0, tr("Version Control"), tr("The file '%1' could not be deleted.").arg(state.currentFile()), QMessageBox::Ok);
} }
static inline bool ask(QWidget *parent, const QString &title, const QString &question, bool defaultValue = true)
{
const QMessageBox::StandardButton defaultButton = defaultValue ? QMessageBox::Yes : QMessageBox::No;
return QMessageBox::question(parent, title, question, QMessageBox::Yes|QMessageBox::No, defaultButton) == QMessageBox::Yes;
}
void VCSBasePlugin::createRepository()
{
QTC_ASSERT(d->m_versionControl->supportsOperation(Core::IVersionControl::CreateRepositoryOperation), return);
// Find current starting directory
QString directory;
if (const ProjectExplorer::Project *currentProject = ProjectExplorer::ProjectExplorerPlugin::instance()->currentProject())
directory = QFileInfo(currentProject->file()->fileName()).absolutePath();
// Prompt for a directory that is not under version control yet
QMainWindow *mw = Core::ICore::instance()->mainWindow();
do {
directory = QFileDialog::getExistingDirectory(mw, tr("Choose repository directory"), directory);
if (directory.isEmpty())
return;
const Core::IVersionControl *managingControl = Core::ICore::instance()->vcsManager()->findVersionControlForDirectory(directory);
if (managingControl == 0)
break;
const QString question = tr("The directory '%1' is already managed by a version control system (%2)."
" Would you like to specify another directory?").arg(directory, managingControl->displayName());
if (!ask(mw, tr("Repository already under version control"), question))
return;
} while (true);
// Create
const bool rc = d->m_versionControl->vcsCreateRepository(directory);
if (rc) {
QMessageBox::information(mw, tr("Repository created"),
tr("A version control repository has been created in %1.").arg(directory));
} else {
QMessageBox::warning(mw, tr("Repository creation failed"),
tr("A version control repository could not be created in %1.").arg(directory));
}
}
} // namespace VCSBase } // namespace VCSBase
#include "vcsbaseplugin.moc" #include "vcsbaseplugin.moc"
+8 -3
View File
@@ -153,6 +153,9 @@ public slots:
// Convenience slot for "Delete current file" action. Prompts to // Convenience slot for "Delete current file" action. Prompts to
// delete the file via VCSManager. // delete the file via VCSManager.
void promptToDeleteCurrentFile(); void promptToDeleteCurrentFile();
// Prompt to initalize version control in a directory, initially
// pointing to the current project.
void createRepository();
protected: protected:
enum ActionState { NoVCSEnabled, OtherVCSEnabled, VCSEnabled }; enum ActionState { NoVCSEnabled, OtherVCSEnabled, VCSEnabled };
@@ -163,9 +166,11 @@ protected:
virtual bool submitEditorAboutToClose(VCSBaseSubmitEditor *submitEditor) = 0; virtual bool submitEditorAboutToClose(VCSBaseSubmitEditor *submitEditor) = 0;
// A helper to enable the VCS menu action according to state: // A helper to enable the VCS menu action according to state:
// NoVCSEnabled->(visible,disabled), OtherVCSEnabled->(invisible), else // NoVCSEnabled -> visible, enabled if repository creation is supported
// enabled. Returns whether actions should be set up further. // OtherVCSEnabled -> invisible
static bool enableMenuAction(ActionState as, QAction *in); // Else: -> fully enabled.
// Returns whether actions should be set up further.
bool enableMenuAction(ActionState as, QAction *in) const;
private slots: private slots:
void slotSubmitEditorAboutToClose(VCSBaseSubmitEditor *submitEditor, bool *result); void slotSubmitEditorAboutToClose(VCSBaseSubmitEditor *submitEditor, bool *result);