diff --git a/src/plugins/coreplugin/iversioncontrol.h b/src/plugins/coreplugin/iversioncontrol.h index ecb1f418c003cec4846cc9cc99b4d80c9fde8d15..90831b2323f4ec6255e2180b57100dcefd685a8a 100644 --- a/src/plugins/coreplugin/iversioncontrol.h +++ b/src/plugins/coreplugin/iversioncontrol.h @@ -41,9 +41,10 @@ class CORE_EXPORT IVersionControl : public QObject { Q_OBJECT 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 QString displayName() const = 0; @@ -93,12 +94,14 @@ public: /*! * Called after a file has been removed from the project (if the user * 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; + /*! + * Called to initialize the version control systemin a directory. + */ + virtual bool vcsCreateRepository(const QString &directory) = 0; + signals: void repositoryChanged(const QString &repository); void filesChanged(const QStringList &files); diff --git a/src/plugins/cvs/cvscontrol.cpp b/src/plugins/cvs/cvscontrol.cpp index f633e4c7afd547124858f36ec51a30f26eab209f..da57f43d5a96c17e269139935c857d3e6d4751e9 100644 --- a/src/plugins/cvs/cvscontrol.cpp +++ b/src/plugins/cvs/cvscontrol.cpp @@ -54,6 +54,7 @@ bool CVSControl::supportsOperation(Operation operation) const case DeleteOperation: break; case OpenOperation: + case CreateRepositoryOperation: rc = false; break; } @@ -78,6 +79,11 @@ bool CVSControl::vcsDelete(const QString &fileName) return m_plugin->vcsDelete(fi.absolutePath(), fi.fileName()); } +bool CVSControl::vcsCreateRepository(const QString &) +{ + return false; +} + bool CVSControl::managesDirectory(const QString &directory) const { return m_plugin->managesDirectory(directory); diff --git a/src/plugins/cvs/cvscontrol.h b/src/plugins/cvs/cvscontrol.h index e89a292408e8b9c83499c3b828254461feb51ee4..f53c38b92574179797a966d7fba6759a84551a96 100644 --- a/src/plugins/cvs/cvscontrol.h +++ b/src/plugins/cvs/cvscontrol.h @@ -52,6 +52,7 @@ public: virtual bool vcsOpen(const QString &fileName); virtual bool vcsAdd(const QString &fileName); virtual bool vcsDelete(const QString &filename); + virtual bool vcsCreateRepository(const QString &directory); void emitRepositoryChanged(const QString &s); void emitFilesChanged(const QStringList &l); diff --git a/src/plugins/cvs/cvsplugin.cpp b/src/plugins/cvs/cvsplugin.cpp index 3a070507b5f482f2a2141c8d762c83629cac2547..ff6c00505744f20b5e93ce15564a683de568417e 100644 --- a/src/plugins/cvs/cvsplugin.cpp +++ b/src/plugins/cvs/cvsplugin.cpp @@ -498,7 +498,7 @@ CVSSubmitEditor *CVSPlugin::openCVSSubmitEditor(const QString &fileName) void CVSPlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as) { - if (!VCSBase::VCSBasePlugin::enableMenuAction(as, m_menuAction)) + if (!enableMenuAction(as, m_menuAction)) return; m_logRepositoryAction->setEnabled(currentState().hasTopLevel()); diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index aad68a5ee02ed1164d431af2eb813984ebc2f784..6e45bc7818c13e42fab66c6bb24716a7b2538878 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -446,6 +446,22 @@ bool GitClient::synchronousReset(const QString &workingDirectory, 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, const QStringList &files, QString *errorMessage) diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h index 54be3a2e3825363fcba9f01c882acf29a2a518fb..6d6e0c253736e38ac57d95a066ec90f65bcc39df 100644 --- a/src/plugins/git/gitclient.h +++ b/src/plugins/git/gitclient.h @@ -92,6 +92,7 @@ public: bool synchronousAdd(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 synchronousInit(const QString &workingDirectory); bool synchronousCheckout(const QString &workingDirectory, const QStringList &files, QString *errorMessage); bool synchronousStash(const QString &workingDirectory, QString *errorMessage); bool synchronousBranchCmd(const QString &workingDirectory, QStringList branchArgs, diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp index 7227085a367e4ae49a93b62634684046aefc736c..a25b5f93c1ea2dc7d412f5c57c71e50145e715cf 100644 --- a/src/plugins/git/gitplugin.cpp +++ b/src/plugins/git/gitplugin.cpp @@ -122,6 +122,7 @@ GitPlugin::GitPlugin() : m_undoFileAction(0), m_logRepositoryAction(0), m_undoRepositoryAction(0), + m_createRepositoryAction(0), m_showAction(0), m_stageAction(0), m_unstageAction(0), @@ -306,6 +307,11 @@ bool GitPlugin::initialize(const QStringList &arguments, QString *errorMessage) connect(m_undoRepositoryAction, SIGNAL(triggered()), this, SLOT(undoRepositoryChanges())); 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)); m_stashAction = new QAction(tr("Stash"), this); @@ -677,9 +683,10 @@ void GitPlugin::stashList() void GitPlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as) { - if (!VCSBase::VCSBasePlugin::enableMenuAction(as, m_menuAction)) + if (!enableMenuAction(as, m_menuAction)) return; - + // Note: This menu is visible if there is no repository. Only + // 'Create Repository'/'Show' actions should be available. const QString fileName = currentState().currentFileName(); m_diffAction->setParameter(fileName); m_logAction->setParameter(fileName); @@ -708,9 +715,13 @@ void GitPlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as) m_statusRepositoryAction->setEnabled(repositoryEnabled); m_branchListAction->setEnabled(repositoryEnabled); m_stashListAction->setEnabled(repositoryEnabled); + m_stashAction->setEnabled(repositoryEnabled); + m_pullAction->setEnabled(repositoryEnabled); + m_commitAction->setEnabled(repositoryEnabled); m_stashPopAction->setEnabled(repositoryEnabled); m_logRepositoryAction->setEnabled(repositoryEnabled); m_undoRepositoryAction->setEnabled(repositoryEnabled); + m_pushAction->setEnabled(repositoryEnabled); // Prompts for repo. m_showAction->setEnabled(true); diff --git a/src/plugins/git/gitplugin.h b/src/plugins/git/gitplugin.h index d89290841da2a391f57590a2b19f8b4c9a3dded5..415efef5c3d28aaacef6f0593588c67d49810bc8 100644 --- a/src/plugins/git/gitplugin.h +++ b/src/plugins/git/gitplugin.h @@ -131,6 +131,7 @@ private: Utils::ParameterAction *m_undoFileAction; QAction *m_logRepositoryAction; QAction *m_undoRepositoryAction; + QAction *m_createRepositoryAction; QAction *m_showAction; Utils::ParameterAction *m_stageAction; diff --git a/src/plugins/git/gitversioncontrol.cpp b/src/plugins/git/gitversioncontrol.cpp index f241396e22d4ee570c674ed6f19a2dda4bc93b69..76541548ccbbf0949be4f41813265fbb37df51ca 100644 --- a/src/plugins/git/gitversioncontrol.cpp +++ b/src/plugins/git/gitversioncontrol.cpp @@ -29,6 +29,7 @@ #include "gitversioncontrol.h" #include "gitclient.h" +#include "gitplugin.h" namespace Git { namespace Internal { @@ -52,6 +53,9 @@ bool GitVersionControl::supportsOperation(Operation operation) const case DeleteOperation: case OpenOperation: break; + case CreateRepositoryOperation: + rc = true; + break; } return rc; } @@ -72,10 +76,14 @@ bool GitVersionControl::vcsDelete(const QString & /*fileName*/) return false; } +bool GitVersionControl::vcsCreateRepository(const QString &directory) +{ + return GitPlugin::instance()->gitClient()->synchronousInit(directory); +} + bool GitVersionControl::managesDirectory(const QString &directory) const { return !GitClient::findRepositoryForDirectory(directory).isEmpty(); - } QString GitVersionControl::findTopLevelForDirectory(const QString &directory) const diff --git a/src/plugins/git/gitversioncontrol.h b/src/plugins/git/gitversioncontrol.h index e7dbf0dabec039d58441150e4cb5d91482d48596..e5013cce6e09a2116ff4c2245567babae6511e16 100644 --- a/src/plugins/git/gitversioncontrol.h +++ b/src/plugins/git/gitversioncontrol.h @@ -53,6 +53,7 @@ public: virtual bool vcsOpen(const QString &fileName); virtual bool vcsAdd(const QString &fileName); virtual bool vcsDelete(const QString &filename); + virtual bool vcsCreateRepository(const QString &directory); void emitFilesChanged(const QStringList &); diff --git a/src/plugins/mercurial/constants.h b/src/plugins/mercurial/constants.h index 070d2c784c45f08294b79395c3006e85773da1b7..f091a481f90012c181c81c32915dc5f336931411 100644 --- a/src/plugins/mercurial/constants.h +++ b/src/plugins/mercurial/constants.h @@ -107,6 +107,7 @@ 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"; +const char * const CREATE_REPOSITORY = "Mercurial.Action.CreateRepository"; //Repository Management const char * const MERGE = "Mercurial.Action.Merge"; diff --git a/src/plugins/mercurial/mercurialclient.cpp b/src/plugins/mercurial/mercurialclient.cpp index 205cf76021d75a249b018178a53643b6442e1772..59b13b9eb4b62ee9329140056edf55d8e7b5ac6b 100644 --- a/src/plugins/mercurial/mercurialclient.cpp +++ b/src/plugins/mercurial/mercurialclient.cpp @@ -366,6 +366,18 @@ void MercurialClient::revert(const QString &workingDir, 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) { QStringList args(QLatin1String("status")); diff --git a/src/plugins/mercurial/mercurialclient.h b/src/plugins/mercurial/mercurialclient.h index 8dbfb073c9c67d2aa972344e3b782a8bcf1ccca0..cd626adfb59d2a1d46032aaa4d14f3c8da497711 100644 --- a/src/plugins/mercurial/mercurialclient.h +++ b/src/plugins/mercurial/mercurialclient.h @@ -88,6 +88,7 @@ public: void statusWithSignal(const QString &repository); void revertFile(const QString &workingDir, const QString &file, 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 commit(const QString &repositoryRoot, const QStringList &files, diff --git a/src/plugins/mercurial/mercurialcontrol.cpp b/src/plugins/mercurial/mercurialcontrol.cpp index 44c6ee04a04a33ff8356fa1e032a19abfd63c00e..3ca94573be47988b2b4a63f014bc0ec5680d5530 100644 --- a/src/plugins/mercurial/mercurialcontrol.cpp +++ b/src/plugins/mercurial/mercurialcontrol.cpp @@ -62,17 +62,15 @@ QString MercurialControl::findTopLevelForDirectory(const QString &directory) con bool MercurialControl::supportsOperation(Operation operation) const { bool supported = true; - switch (operation) { case Core::IVersionControl::AddOperation: case Core::IVersionControl::DeleteOperation: + case Core::IVersionControl::CreateRepositoryOperation: break; case Core::IVersionControl::OpenOperation: - default: supported = false; break; } - return supported; } @@ -94,6 +92,11 @@ bool MercurialControl::vcsDelete(const QString &filename) return mercurialClient->remove(fi.absolutePath(), fi.fileName()); } +bool MercurialControl::vcsCreateRepository(const QString &directory) +{ + return mercurialClient->createRepositorySync(directory); +} + bool MercurialControl::sccManaged(const QString &filename) { const QFileInfo fi(filename); diff --git a/src/plugins/mercurial/mercurialcontrol.h b/src/plugins/mercurial/mercurialcontrol.h index df3b99ef64cca071c80eed250f8fd0c1d68ca3de..d447a5bc1643c0651be07f23b4c1f4828ec4d296 100644 --- a/src/plugins/mercurial/mercurialcontrol.h +++ b/src/plugins/mercurial/mercurialcontrol.h @@ -56,6 +56,7 @@ public: bool vcsOpen(const QString &fileName); bool vcsAdd(const QString &filename); bool vcsDelete(const QString &filename); + bool vcsCreateRepository(const QString &directory); bool sccManaged(const QString &filename); public slots: diff --git a/src/plugins/mercurial/mercurialplugin.cpp b/src/plugins/mercurial/mercurialplugin.cpp index 6da681bc283f5a5b756659590cacf4815411dd61..a3487f7641566f4080a1aa1c86b1c722b8560b5f 100644 --- a/src/plugins/mercurial/mercurialplugin.cpp +++ b/src/plugins/mercurial/mercurialplugin.cpp @@ -127,6 +127,7 @@ MercurialPlugin::MercurialPlugin() : changeLog(0), m_addAction(0), m_deleteAction(0), + m_createRepositoryAction(0), m_menuAction(0) { m_instance = this; @@ -429,6 +430,11 @@ void MercurialPlugin::createRepositoryActions(const QList<int> &context) command->setDefaultKeySequence(QKeySequence(tr("Alt+H,Alt+C"))); connect(action, SIGNAL(triggered()), this, SLOT(commit())); 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() @@ -675,7 +681,7 @@ void MercurialPlugin::createSeparator(const QList<int> &context, const QString & void MercurialPlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as) { - if (!VCSBase::VCSBasePlugin::enableMenuAction(as, m_menuAction)) + if (!enableMenuAction(as, m_menuAction)) return; const QString filename = currentState().currentFileName(); diff --git a/src/plugins/mercurial/mercurialplugin.h b/src/plugins/mercurial/mercurialplugin.h index 0a441965ab51a9c141c686bd5e664fe9a823902b..8bc5fe902c9a29935083e181fdb0823f89c76efe 100644 --- a/src/plugins/mercurial/mercurialplugin.h +++ b/src/plugins/mercurial/mercurialplugin.h @@ -166,6 +166,7 @@ private: Utils::ParameterAction *revertFile; Utils::ParameterAction *statusFile; + QAction *m_createRepositoryAction; //submit editor actions QAction *editorCommit; QAction *editorDiff; diff --git a/src/plugins/perforce/perforceplugin.cpp b/src/plugins/perforce/perforceplugin.cpp index 34d2f383d2ea505a2dae8c620a37434633f02272..e4e16bd6d6b90368d18e837bb9a79d762d6a745a 100644 --- a/src/plugins/perforce/perforceplugin.cpp +++ b/src/plugins/perforce/perforceplugin.cpp @@ -788,7 +788,7 @@ void PerforcePlugin::filelog(const QString &workingDir, const QStringList &fileN void PerforcePlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as) { - if (!VCSBase::VCSBasePlugin::enableMenuAction(as, m_menuAction)) + if (!enableMenuAction(as, m_menuAction)) return; m_logRepositoryAction->setEnabled(currentState().hasTopLevel()); diff --git a/src/plugins/perforce/perforceversioncontrol.cpp b/src/plugins/perforce/perforceversioncontrol.cpp index bfa9f8827afa5924098a44b2efc17d7bfdaa7127..0be2ef59019e472ef078c7b5f151e1ff37f7a16a 100644 --- a/src/plugins/perforce/perforceversioncontrol.cpp +++ b/src/plugins/perforce/perforceversioncontrol.cpp @@ -50,14 +50,15 @@ QString PerforceVersionControl::displayName() const bool PerforceVersionControl::supportsOperation(Operation operation) const { - bool rc = true; switch (operation) { case AddOperation: case DeleteOperation: case OpenOperation: + return true; + case CreateRepositoryOperation: break; } - return rc; + return false; } bool PerforceVersionControl::vcsOpen(const QString &fileName) @@ -78,6 +79,11 @@ bool PerforceVersionControl::vcsDelete(const QString &fileName) return m_plugin->vcsDelete(fi.absolutePath(), fi.fileName()); } +bool PerforceVersionControl::vcsCreateRepository(const QString &) +{ + return false; +} + bool PerforceVersionControl::managesDirectory(const QString &directory) const { const bool rc = m_plugin->managesDirectory(directory); diff --git a/src/plugins/perforce/perforceversioncontrol.h b/src/plugins/perforce/perforceversioncontrol.h index 8d6660fc021a971657324db24c80d5e377ddc680..815b743053976815c1d50c64032aa983b196e0a2 100644 --- a/src/plugins/perforce/perforceversioncontrol.h +++ b/src/plugins/perforce/perforceversioncontrol.h @@ -52,6 +52,7 @@ public: virtual bool vcsOpen(const QString &fileName); virtual bool vcsAdd(const QString &fileName); virtual bool vcsDelete(const QString &filename); + virtual bool vcsCreateRepository(const QString &directory); void emitRepositoryChanged(const QString &s); void emitFilesChanged(const QStringList &l); diff --git a/src/plugins/projectexplorer/projectfilewizardextension.cpp b/src/plugins/projectexplorer/projectfilewizardextension.cpp index 5e6b7e575d9f509a06c6959e77f9e70670fb5f65..c07894ffb6f66e891e6ebff6f450d57746b71409 100644 --- a/src/plugins/projectexplorer/projectfilewizardextension.cpp +++ b/src/plugins/projectexplorer/projectfilewizardextension.cpp @@ -34,17 +34,23 @@ #include "nodesvisitor.h" #include "projectwizardpage.h" +#include <utils/qtcassert.h> +#include <utils/stringutils.h> + #include <coreplugin/basefilewizard.h> #include <coreplugin/dialogs/iwizard.h> #include <coreplugin/filemanager.h> #include <coreplugin/icore.h> #include <coreplugin/iversioncontrol.h> #include <coreplugin/vcsmanager.h> +#include <extensionsystem/pluginmanager.h> #include <QtCore/QVariant> +#include <QtCore/QtAlgorithms> #include <QtCore/QDebug> #include <QtCore/QFileInfo> #include <QtCore/QMultiMap> +#include <QtCore/QDir> enum { debugExtension = 0 }; @@ -54,43 +60,111 @@ typedef QList<ProjectNode *> ProjectNodeList; namespace Internal { -// --------- AllProjectNodesVisitor. Figure out all projects. -// No sooner said then done. +// AllProjectNodesVisitor: Retrieve all projects (*.pri/*.pro). class AllProjectNodesVisitor : public NodesVisitor { - AllProjectNodesVisitor(ProjectNodeList &l) : m_projectNodes(l) {} public: - - static ProjectNodeList allProjects(const ProjectExplorerPlugin *pe); + static ProjectNodeList allProjects(); virtual void visitProjectNode(ProjectNode *node); private: - ProjectNodeList &m_projectNodes; + ProjectNodeList m_projectNodes; }; -ProjectNodeList AllProjectNodesVisitor::allProjects(const ProjectExplorerPlugin *pe) +ProjectNodeList AllProjectNodesVisitor::allProjects() { - ProjectNodeList rc; - AllProjectNodesVisitor visitor(rc); - pe->session()->sessionNode()->accept(&visitor); - return rc; + AllProjectNodesVisitor visitor; + ProjectExplorerPlugin::instance()->session()->sessionNode()->accept(&visitor); + return visitor.m_projectNodes; } void AllProjectNodesVisitor::visitProjectNode(ProjectNode *node) { 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 struct ProjectWizardContext { - Core::IVersionControl *versionControl; - ProjectNodeList projects; + ProjectWizardContext(); + void clear(); + + QList<Core::IVersionControl*> versionControls; + QList<ProjectEntry> projects; 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() : m_context(0) @@ -102,85 +176,184 @@ ProjectFileWizardExtension::~ProjectFileWizardExtension() 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) { if (debugExtension) 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; foreach (const Core::GeneratedFile &f, files) fileNames.push_back(f.path()); - - const QString directory = QFileInfo(fileNames.front()).absolutePath(); - m_context->versionControl = Core::ICore::instance()->vcsManager()->findVersionControlForDirectory(directory); - - m_context->page->setFilesDisplay(fileNames); - - const bool canAddToVCS = m_context->versionControl && m_context->versionControl->supportsOperation(Core::IVersionControl::AddOperation); - if (m_context->versionControl) - m_context->page->setVCSDisplay(m_context->versionControl->displayName()); - m_context->page->setAddToVersionControlEnabled(canAddToVCS); + m_context->commonDirectory = Utils::commonPath(fileNames); + m_context->page->setFilesDisplay(m_context->commonDirectory, fileNames); + // Find best project (Entry at 0 is 'None'). + const int bestProjectIndex = findMatchingProject(m_context->projects, m_context->commonDirectory); + if (bestProjectIndex == -1) { + m_context->page->setCurrentProjectIndex(0); + } else { + m_context->page->setCurrentProjectIndex(bestProjectIndex + 1); + } + initializeVersionControlChoices(); } -static ProjectNode *currentProject() +void ProjectFileWizardExtension::initializeVersionControlChoices() { - if (Node *currentNode = ProjectExplorerPlugin::instance()->currentNode()) - if (ProjectNode *currentProjectNode = qobject_cast<ProjectNode *>(currentNode)) - return currentProjectNode; - return 0; + // Figure out version control situation: + // 1) Directory is managed and VCS supports "Add" -> List it + // 2) Directory is managed and VCS does not support "Add" -> None available + // 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) { - if (!m_context) + if (!m_context) { m_context = new ProjectWizardContext; + } else { + m_context->clear(); + } // Init context with page and projects m_context->page = new ProjectWizardPage; - m_context->versionControl = 0; - m_context->projects = AllProjectNodesVisitor::allProjects(ProjectExplorerPlugin::instance()); + // Project list remains the same over duration of wizard execution + // Note that projects cannot be added to projects. + initProjectChoices(wizard->kind() != Core::IWizard::ProjectWizard); + return QList<QWizardPage *>() << m_context->page; +} + +void ProjectFileWizardExtension::initProjectChoices(bool enabled) +{ // Set up project list which remains the same over duration of wizard execution - // 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()); + //: 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->setAddToProjectEnabled(hasProjects && wizard->kind() != Core::IWizard::ProjectWizard); - - return QList<QWizardPage *>() << m_context->page; + m_context->page->setProjects(projectChoices); } 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; - // Add files to project && version control - if (m_context->page->addToProject()) { - ProjectNode *project = m_context->page->currentProject(); - // Split into lists by file type and add - TypeFileMap typeFileMap; - foreach (const Core::GeneratedFile &generatedFile, files) { - const QString path = generatedFile.path(); - typeFileMap.insert(typeForFileName(Core::ICore::instance()->mimeDatabase(), path), path); + + // Add files to project (Entry at 0 is 'None'). + const int projectIndex = m_context->page->currentProjectIndex() - 1; + if (projectIndex < 0 || projectIndex >= m_context->projects.size()) + return true; + ProjectNode *project = m_context->projects.at(projectIndex).node; + // Split into lists by file type and bulk-add them. + TypeFileMap typeFileMap; + const Core::MimeDatabase *mdb = Core::ICore::instance()->mimeDatabase(); + foreach (const Core::GeneratedFile &generatedFile, files) { + const QString path = generatedFile.path(); + typeFileMap.insert(typeForFileName(mdb, path), path); + } + foreach (FileType type, typeFileMap.uniqueKeys()) { + 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; } - foreach (FileType type, typeFileMap.uniqueKeys()) { - 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(QLatin1String(","))); - return false; - } + } + return true; +} + +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 to version control - if (m_context->page->addToVersionControl()) { + // Add files if supported. + if (versionControl->supportsOperation(Core::IVersionControl::AddOperation)) { 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()); return false; } } } - return true; } diff --git a/src/plugins/projectexplorer/projectfilewizardextension.h b/src/plugins/projectexplorer/projectfilewizardextension.h index 487d8cf090ae6cdb722505a63c31dbc323aef2ea..c5eee0c7b0579699448603a4b65cfa31ab5a0507 100644 --- a/src/plugins/projectexplorer/projectfilewizardextension.h +++ b/src/plugins/projectexplorer/projectfilewizardextension.h @@ -38,10 +38,10 @@ namespace Internal { struct ProjectWizardContext; -/* - Adds final page allowing the user to add files to project && version control - to BaseFileWizard. - */ +/* Final file wizard processing steps: + * 1) Add to a project file (*.pri/ *.pro) + * 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 { Q_OBJECT @@ -56,6 +56,11 @@ public slots: virtual void firstExtensionPageShown(const QList<Core::GeneratedFile> &); 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; }; diff --git a/src/plugins/projectexplorer/projectwizardpage.cpp b/src/plugins/projectexplorer/projectwizardpage.cpp index 58db1e95025a23cbdb8ef0d0e39ef06a3ab5fa09..dfc11d7665efce1557521126e5db4ecb31cf3ff2 100644 --- a/src/plugins/projectexplorer/projectwizardpage.cpp +++ b/src/plugins/projectexplorer/projectwizardpage.cpp @@ -29,27 +29,17 @@ #include "projectwizardpage.h" #include "ui_projectwizardpage.h" -#include "projectnodes.h" -#include <utils/stringutils.h> - -#include <QtCore/QDebug> -#include <QtCore/QFileInfo> #include <QtCore/QTextStream> using namespace ProjectExplorer; using namespace Internal; -Q_DECLARE_METATYPE(ProjectExplorer::ProjectNode*) - ProjectWizardPage::ProjectWizardPage(QWidget *parent) : QWizardPage(parent), m_ui(new Ui::WizardPage) { m_ui->setupUi(this); - - connect(m_ui->addToProjectCheckBox, SIGNAL(toggled(bool)), - m_ui->projectComboBox, SLOT(setEnabled(bool))); } ProjectWizardPage::~ProjectWizardPage() @@ -57,63 +47,36 @@ ProjectWizardPage::~ProjectWizardPage() 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(); - foreach (const QString &name, projectMap.keys()) { - m_ui->projectComboBox->addItem(name, qVariantFromValue(projectMap.value(name))); - } -} - -void ProjectWizardPage::setAddToProjectEnabled(bool b) -{ - m_ui->projectLabel->setEnabled(b); - m_ui->addToProjectLabel->setEnabled(b); - m_ui->addToProjectCheckBox->setChecked(b); - m_ui->addToProjectCheckBox->setEnabled(b); - m_ui->projectComboBox->setEnabled(b); + m_ui->projectComboBox->addItems(p); } -ProjectNode *ProjectWizardPage::currentProject() const +int ProjectWizardPage::currentProjectIndex() const { - QVariant variant = m_ui->projectComboBox->itemData(m_ui->projectComboBox->currentIndex()); - return qVariantValue<ProjectNode*>(variant); + return m_ui->projectComboBox->currentIndex(); } -void ProjectWizardPage::setCurrentProject(ProjectNode *projectNode) +void ProjectWizardPage::setCurrentProjectIndex(int idx) { - if (!projectNode) - return; - 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; - } - } + m_ui->projectComboBox->setCurrentIndex(idx); } -bool ProjectWizardPage::addToProject() const +void ProjectWizardPage::setVersionControls(const QStringList &vcs) { - return m_ui->addToProjectCheckBox->isChecked(); + m_ui->addToVersionControlComboBox->clear(); + m_ui->addToVersionControlComboBox->addItems(vcs); } -bool ProjectWizardPage::addToVersionControl() const +int ProjectWizardPage::versionControlIndex() const { - return m_ui->addToVersionControlCheckBox->isChecked(); + return m_ui->addToVersionControlComboBox->currentIndex(); } -void ProjectWizardPage::setAddToVersionControlEnabled(bool b) +void ProjectWizardPage::setVersionControlIndex(int idx) { - m_ui->addToVersionControlLabel->setEnabled(b); - m_ui->addToVersionControlCheckBox->setChecked(b); - m_ui->addToVersionControlCheckBox->setEnabled(b); + m_ui->addToVersionControlComboBox->setCurrentIndex(idx); } void ProjectWizardPage::changeEvent(QEvent *e) @@ -128,15 +91,9 @@ void ProjectWizardPage::changeEvent(QEvent *e) } } -void ProjectWizardPage::setVCSDisplay(const QString &vcsName) -{ - m_ui->addToVersionControlLabel->setText(tr("Add to &VCS (%1)").arg(vcsName)); -} - -void ProjectWizardPage::setFilesDisplay(const QStringList &files) +void ProjectWizardPage::setFilesDisplay(const QString &commonPath, const QStringList &files) { QString fileMessage; - const QString commonPath = Utils::commonPath(files); { QTextStream str(&fileMessage); str << "<qt>" diff --git a/src/plugins/projectexplorer/projectwizardpage.h b/src/plugins/projectexplorer/projectwizardpage.h index 021b2a4bb5e976de9eba43214cb07927d403185c..5751d1516b0a01a7c13a3112b7f93285ad41f675 100644 --- a/src/plugins/projectexplorer/projectwizardpage.h +++ b/src/plugins/projectexplorer/projectwizardpage.h @@ -32,16 +32,7 @@ #include <QtGui/QWizardPage> -namespace Core { - class IVersionControl; - class SCCManager; - class FileManager; -} - namespace ProjectExplorer { - -class ProjectNode; - namespace Internal { namespace Ui { @@ -55,19 +46,17 @@ public: explicit ProjectWizardPage(QWidget *parent = 0); virtual ~ProjectWizardPage(); - void setProjects(const QList<ProjectNode *> &); - void setCurrentProject(ProjectNode *); - - ProjectNode *currentProject() const; + void setProjects(const QStringList &); + int currentProjectIndex() const; + void setCurrentProjectIndex(int); - void setAddToProjectEnabled(bool b); - bool addToProject() const; + void setVersionControls(const QStringList &); - bool addToVersionControl() const; - void setAddToVersionControlEnabled(bool b); + int versionControlIndex() const; + void setVersionControlIndex(int); - void setVCSDisplay(const QString &vcsName); - void setFilesDisplay(const QStringList &files); + // Returns the common path + void setFilesDisplay(const QString &commonPath, const QStringList &files); protected: virtual void changeEvent(QEvent *e); diff --git a/src/plugins/projectexplorer/projectwizardpage.ui b/src/plugins/projectexplorer/projectwizardpage.ui index 89d15be8683def8f161612452c38d4f6c95ad951..22dc2f3fbe74d7fc5cc7afbb5648b4ea0d2e5e58 100644 --- a/src/plugins/projectexplorer/projectwizardpage.ui +++ b/src/plugins/projectexplorer/projectwizardpage.ui @@ -20,44 +20,43 @@ <enum>QFormLayout::ExpandingFieldsGrow</enum> </property> <item row="0" column="0"> - <widget class="QLabel" name="addToProjectLabel"> + <widget class="QLabel" name="projectLabel"> <property name="text"> - <string>&Add to Project</string> + <string>Add to &project:</string> </property> <property name="buddy"> - <cstring>addToProjectCheckBox</cstring> + <cstring>projectComboBox</cstring> </property> </widget> </item> <item row="0" column="1"> - <widget class="QCheckBox" name="addToProjectCheckBox"/> + <widget class="QComboBox" name="projectComboBox"> + <item> + <property name="text"> + <string notr="true">A very long project name indeed</string> + </property> + </item> + </widget> </item> <item row="1" column="0"> - <widget class="QLabel" name="projectLabel"> + <widget class="QLabel" name="addToVersionControlLabel"> <property name="text"> - <string>&Project</string> + <string>Add to &version control:</string> </property> <property name="buddy"> - <cstring>projectComboBox</cstring> + <cstring>addToVersionControlComboBox</cstring> </property> </widget> </item> <item row="1" column="1"> - <widget class="QComboBox" name="projectComboBox"/> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="addToVersionControlLabel"> - <property name="text"> - <string>Add to &version control</string> - </property> - <property name="buddy"> - <cstring>addToVersionControlCheckBox</cstring> - </property> + <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 row="2" column="1"> - <widget class="QCheckBox" name="addToVersionControlCheckBox"/> - </item> </layout> </item> <item> @@ -96,7 +95,7 @@ <x>0</x> <y>0</y> <width>611</width> - <height>305</height> + <height>328</height> </rect> </property> <layout class="QVBoxLayout" name="verticalLayout_2"> diff --git a/src/plugins/subversion/subversioncontrol.cpp b/src/plugins/subversion/subversioncontrol.cpp index a3913fe561b4e10efbac19564f60a9f476d051f6..f8b795e5f48a508b34e42b7bc5dfb23a62bd85a8 100644 --- a/src/plugins/subversion/subversioncontrol.cpp +++ b/src/plugins/subversion/subversioncontrol.cpp @@ -54,6 +54,7 @@ bool SubversionControl::supportsOperation(Operation operation) const case DeleteOperation: break; case OpenOperation: + case CreateRepositoryOperation: rc = false; break; } @@ -78,6 +79,11 @@ bool SubversionControl::vcsDelete(const QString &fileName) return m_plugin->vcsDelete(fi.absolutePath(), fi.fileName()); } +bool SubversionControl::vcsCreateRepository(const QString &) +{ + return false; +} + bool SubversionControl::managesDirectory(const QString &directory) const { return m_plugin->managesDirectory(directory); diff --git a/src/plugins/subversion/subversioncontrol.h b/src/plugins/subversion/subversioncontrol.h index 99512e53f71ec38223bebcd114ea30a600c4c8f8..5aa60373acee78d72f5997768cef6553ea0aa2ed 100644 --- a/src/plugins/subversion/subversioncontrol.h +++ b/src/plugins/subversion/subversioncontrol.h @@ -52,6 +52,7 @@ public: virtual bool vcsOpen(const QString &fileName); virtual bool vcsAdd(const QString &fileName); virtual bool vcsDelete(const QString &filename); + virtual bool vcsCreateRepository(const QString &directory); void emitRepositoryChanged(const QString &); void emitFilesChanged(const QStringList &); diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp index f0ccf0f6d06bef24e733a40aeac59a773ea97fd2..2cab3832665fa3edee676fb68bb2953a9ad17021 100644 --- a/src/plugins/subversion/subversionplugin.cpp +++ b/src/plugins/subversion/subversionplugin.cpp @@ -528,7 +528,7 @@ SubversionSubmitEditor *SubversionPlugin::openSubversionSubmitEditor(const QStri void SubversionPlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as) { - if (!VCSBase::VCSBasePlugin::enableMenuAction(as, m_menuAction)) + if (!enableMenuAction(as, m_menuAction)) return; m_logRepositoryAction->setEnabled(currentState().hasTopLevel()); diff --git a/src/plugins/vcsbase/vcsbaseplugin.cpp b/src/plugins/vcsbase/vcsbaseplugin.cpp index b672fba110a3b45bc44bfda73464d66ae985d773..0cb54a70087d6cc09871ae4e066661c650774ede 100644 --- a/src/plugins/vcsbase/vcsbaseplugin.cpp +++ b/src/plugins/vcsbase/vcsbaseplugin.cpp @@ -47,6 +47,8 @@ #include <QtGui/QAction> #include <QtGui/QMessageBox> +#include <QtGui/QFileDialog> +#include <QtGui/QMainWindow> enum { debug = 0 }; @@ -345,6 +347,8 @@ VCSBASE_EXPORT QDebug operator<<(QDebug in, const VCSBasePluginState &state) struct VCSBasePluginPrivate { explicit VCSBasePluginPrivate(const QString &submitEditorId); + inline bool supportsRepositoryCreation() const; + const QString m_submitEditorId; Core::IVersionControl *m_versionControl; 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; VCSBasePlugin::VCSBasePlugin(const QString &submitEditorId) : @@ -427,15 +436,17 @@ const VCSBasePluginState &VCSBasePlugin::currentState() const return d->m_state; } -bool VCSBasePlugin::enableMenuAction(ActionState as, QAction *menuAction) +bool VCSBasePlugin::enableMenuAction(ActionState as, QAction *menuAction) const { if (debug) qDebug() << "enableMenuAction" << menuAction->text() << as; switch (as) { - case VCSBase::VCSBasePlugin::NoVCSEnabled: + case VCSBase::VCSBasePlugin::NoVCSEnabled: { + const bool supportsCreation = d->supportsRepositoryCreation(); menuAction->setVisible(true); - menuAction->setEnabled(false); - return false; + menuAction->setEnabled(supportsCreation); + return supportsCreation; + } case VCSBase::VCSBasePlugin::OtherVCSEnabled: menuAction->setVisible(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); } +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 #include "vcsbaseplugin.moc" diff --git a/src/plugins/vcsbase/vcsbaseplugin.h b/src/plugins/vcsbase/vcsbaseplugin.h index c5760032aa1f0eaee212940c9b6d04878349a6ce..a9351ed47039409cdfa888519b7d0dd4217b900e 100644 --- a/src/plugins/vcsbase/vcsbaseplugin.h +++ b/src/plugins/vcsbase/vcsbaseplugin.h @@ -153,6 +153,9 @@ public slots: // Convenience slot for "Delete current file" action. Prompts to // delete the file via VCSManager. void promptToDeleteCurrentFile(); + // Prompt to initalize version control in a directory, initially + // pointing to the current project. + void createRepository(); protected: enum ActionState { NoVCSEnabled, OtherVCSEnabled, VCSEnabled }; @@ -163,9 +166,11 @@ protected: virtual bool submitEditorAboutToClose(VCSBaseSubmitEditor *submitEditor) = 0; // A helper to enable the VCS menu action according to state: - // NoVCSEnabled->(visible,disabled), OtherVCSEnabled->(invisible), else - // enabled. Returns whether actions should be set up further. - static bool enableMenuAction(ActionState as, QAction *in); + // NoVCSEnabled -> visible, enabled if repository creation is supported + // OtherVCSEnabled -> invisible + // Else: -> fully enabled. + // Returns whether actions should be set up further. + bool enableMenuAction(ActionState as, QAction *in) const; private slots: void slotSubmitEditorAboutToClose(VCSBaseSubmitEditor *submitEditor, bool *result);