forked from qt-creator/qt-creator
Added a gitorious clone wizard.
... based on the git clone wizard. Provide a wizard for browsing gitorious hosts. Task-number: 44831
This commit is contained in:
@@ -29,8 +29,6 @@
|
||||
|
||||
#include "clonewizard.h"
|
||||
#include "clonewizardpage.h"
|
||||
#include "gitplugin.h"
|
||||
#include "gitclient.h"
|
||||
|
||||
#include <vcsbase/checkoutjobs.h>
|
||||
#include <utils/qtcassert.h>
|
||||
@@ -75,18 +73,7 @@ QSharedPointer<VCSBase::AbstractCheckoutJob> CloneWizard::createJob(const QList<
|
||||
// Collect parameters for the clone command.
|
||||
const CloneWizardPage *cwp = qobject_cast<const CloneWizardPage *>(parameterPages.front());
|
||||
QTC_ASSERT(cwp, return QSharedPointer<VCSBase::AbstractCheckoutJob>())
|
||||
const GitClient *client = GitPlugin::instance()->gitClient();
|
||||
QStringList args = client->binary();
|
||||
const QString workingDirectory = cwp->path();
|
||||
const QString directory = cwp->directory();
|
||||
*checkoutPath = workingDirectory + QLatin1Char('/') + directory;
|
||||
args << QLatin1String("clone") << cwp->repository() << directory;
|
||||
const QString binary = args.front();
|
||||
args.pop_front();
|
||||
|
||||
VCSBase::AbstractCheckoutJob *job = new VCSBase::ProcessCheckoutJob(binary, args, workingDirectory,
|
||||
client->processEnvironment());
|
||||
return QSharedPointer<VCSBase::AbstractCheckoutJob>(job);
|
||||
return cwp->createCheckoutJob(checkoutPath);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -28,20 +28,42 @@
|
||||
**************************************************************************/
|
||||
|
||||
#include "clonewizardpage.h"
|
||||
#include "gitplugin.h"
|
||||
#include "gitclient.h"
|
||||
|
||||
#include <vcsbase/checkoutjobs.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
namespace Git {
|
||||
namespace Internal {
|
||||
|
||||
struct CloneWizardPagePrivate {
|
||||
CloneWizardPagePrivate();
|
||||
|
||||
const QString mainLinePostfix;
|
||||
const QString gitPostFix;
|
||||
const QString protocolDelimiter;
|
||||
};
|
||||
|
||||
CloneWizardPagePrivate::CloneWizardPagePrivate() :
|
||||
mainLinePostfix(QLatin1String("/mainline.git")),
|
||||
gitPostFix(QLatin1String(".git")),
|
||||
protocolDelimiter(QLatin1String("://"))
|
||||
{
|
||||
}
|
||||
|
||||
CloneWizardPage::CloneWizardPage(QWidget *parent) :
|
||||
VCSBase::BaseCheckoutWizardPage(parent),
|
||||
m_mainLinePostfix(QLatin1String("/mainline.git")),
|
||||
m_gitPostFix(QLatin1String(".git")),
|
||||
m_protocolDelimiter(QLatin1String("://"))
|
||||
d(new CloneWizardPagePrivate)
|
||||
{
|
||||
setSubTitle(tr("Specify repository URL, checkout directory and path."));
|
||||
setRepositoryLabel(tr("Clone URL:"));
|
||||
}
|
||||
|
||||
CloneWizardPage::~CloneWizardPage()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
QString CloneWizardPage::directoryFromRepository(const QString &urlIn) const
|
||||
{
|
||||
/* Try to figure out a good directory name from something like:
|
||||
@@ -51,19 +73,19 @@ QString CloneWizardPage::directoryFromRepository(const QString &urlIn) const
|
||||
QString url = urlIn.trimmed();
|
||||
const QChar slash = QLatin1Char('/');
|
||||
// remove host
|
||||
const int protocolDelimiterPos = url.indexOf(m_protocolDelimiter); // "://"
|
||||
const int startRepoSearchPos = protocolDelimiterPos == -1 ? 0 : protocolDelimiterPos + m_protocolDelimiter.size();
|
||||
const int protocolDelimiterPos = url.indexOf(d->protocolDelimiter); // "://"
|
||||
const int startRepoSearchPos = protocolDelimiterPos == -1 ? 0 : protocolDelimiterPos + d->protocolDelimiter.size();
|
||||
int repoPos = url.indexOf(QLatin1Char(':'), startRepoSearchPos);
|
||||
if (repoPos == -1)
|
||||
repoPos = url.indexOf(slash, startRepoSearchPos);
|
||||
if (repoPos != -1)
|
||||
url.remove(0, repoPos + 1);
|
||||
// Remove postfixes
|
||||
if (url.endsWith(m_mainLinePostfix)) {
|
||||
url.truncate(url.size() - m_mainLinePostfix.size());
|
||||
if (url.endsWith(d->mainLinePostfix)) {
|
||||
url.truncate(url.size() - d->mainLinePostfix.size());
|
||||
} else {
|
||||
if (url.endsWith(m_gitPostFix)) {
|
||||
url.truncate(url.size() - m_gitPostFix.size());
|
||||
if (url.endsWith(d->gitPostFix)) {
|
||||
url.truncate(url.size() - d->gitPostFix.size());
|
||||
}
|
||||
}
|
||||
// Check for equal parts, something like "qt/qt" -> "qt"
|
||||
@@ -79,5 +101,19 @@ QString CloneWizardPage::directoryFromRepository(const QString &urlIn) const
|
||||
return url;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
QSharedPointer<VCSBase::AbstractCheckoutJob> CloneWizardPage::createCheckoutJob(QString *checkoutPath) const
|
||||
{
|
||||
const Internal::GitClient *client = Internal::GitPlugin::instance()->gitClient();
|
||||
QStringList args = client->binary();
|
||||
const QString workingDirectory = path();
|
||||
const QString checkoutDir = directory();
|
||||
*checkoutPath = workingDirectory + QLatin1Char('/') + checkoutDir;
|
||||
args << QLatin1String("clone") << repository() << checkoutDir;
|
||||
const QString binary = args.front();
|
||||
args.pop_front();
|
||||
VCSBase::AbstractCheckoutJob *job = new VCSBase::ProcessCheckoutJob(binary, args, workingDirectory,
|
||||
client->processEnvironment());
|
||||
return QSharedPointer<VCSBase::AbstractCheckoutJob>(job);
|
||||
}
|
||||
|
||||
} // namespace Git
|
||||
|
||||
@@ -32,25 +32,32 @@
|
||||
|
||||
#include <vcsbase/basecheckoutwizardpage.h>
|
||||
|
||||
namespace Git {
|
||||
namespace Internal {
|
||||
#include <QtCore/QSharedPointer>
|
||||
|
||||
namespace VCSBase {
|
||||
class AbstractCheckoutJob;
|
||||
}
|
||||
|
||||
namespace Git {
|
||||
|
||||
struct CloneWizardPagePrivate;
|
||||
|
||||
// Used by gitorious as well.
|
||||
class CloneWizardPage : public VCSBase::BaseCheckoutWizardPage
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CloneWizardPage(QWidget *parent = 0);
|
||||
explicit CloneWizardPage(QWidget *parent = 0);
|
||||
virtual ~CloneWizardPage();
|
||||
|
||||
QSharedPointer<VCSBase::AbstractCheckoutJob> createCheckoutJob(QString *checkoutPath) const;
|
||||
|
||||
protected:
|
||||
virtual QString directoryFromRepository(const QString &r) const;
|
||||
|
||||
private:
|
||||
const QString m_mainLinePostfix;
|
||||
const QString m_gitPostFix;
|
||||
const QString m_protocolDelimiter;
|
||||
CloneWizardPagePrivate *d;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Git
|
||||
#endif // CLONEWIZARDPAGE_H
|
||||
|
||||
|
||||
@@ -47,3 +47,4 @@ FORMS += changeselectiondialog.ui \
|
||||
branchdialog.ui
|
||||
|
||||
OTHER_FILES += ScmGit.pluginspec
|
||||
include(gitorious/gitorious.pri)
|
||||
|
||||
600
src/plugins/git/gitorious/gitorious.cpp
Normal file
600
src/plugins/git/gitorious/gitorious.cpp
Normal file
@@ -0,0 +1,600 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** Commercial Usage
|
||||
**
|
||||
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||
** accordance with the Qt Commercial License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Nokia.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** If you are unsure which license is appropriate for your use, please
|
||||
** contact the sales department at http://www.qtsoftware.com/contact.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "gitorious.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QXmlStreamReader>
|
||||
#include <QtCore/QSettings>
|
||||
|
||||
#include <QtNetwork/QNetworkAccessManager>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
|
||||
enum { debug = 0 };
|
||||
|
||||
enum Protocol { ListCategoriesProtocol, ListProjectsProtocol };
|
||||
|
||||
static const char *protocolPropertyC = "gitoriousProtocol";
|
||||
static const char *hostNamePropertyC = "gitoriousHost";
|
||||
static const char *pagePropertyC = "requestPage";
|
||||
|
||||
static const char *settingsKeyC = "GitoriousHosts";
|
||||
|
||||
// Gitorious paginates projects as 20 per page. It starts with page 1.
|
||||
enum { ProjectsPageSize = 20 };
|
||||
|
||||
// Format an URL for a XML request
|
||||
static inline QUrl xmlRequest(const QString &host, const QString &request, int page = -1)
|
||||
{
|
||||
QUrl url;
|
||||
url.setScheme(QLatin1String("http"));
|
||||
url.setHost(host);
|
||||
url.setPath(QLatin1Char('/') + request);
|
||||
url.addQueryItem(QLatin1String("format"), QLatin1String("xml"));
|
||||
if (page >= 0)
|
||||
url.addQueryItem(QLatin1String("page"), QString::number(page));
|
||||
return url;
|
||||
}
|
||||
|
||||
namespace Gitorious {
|
||||
namespace Internal {
|
||||
|
||||
GitoriousRepository::GitoriousRepository() :
|
||||
type(BaselineRepository),
|
||||
id(0)
|
||||
{
|
||||
}
|
||||
|
||||
static inline GitoriousRepository::Type repositoryType(const QString &nspace)
|
||||
{
|
||||
if (nspace == QLatin1String("Repository::Namespace::BASELINE"))
|
||||
return GitoriousRepository::BaselineRepository;
|
||||
if (nspace == QLatin1String("Repository::Namespace::SHARED"))
|
||||
return GitoriousRepository::SharedRepository;
|
||||
if (nspace == QLatin1String("Repository::Namespace::PERSONAL"))
|
||||
return GitoriousRepository::PersonalRepository;
|
||||
return GitoriousRepository::BaselineRepository;
|
||||
}
|
||||
|
||||
GitoriousCategory::GitoriousCategory(const QString &n) :
|
||||
name(n)
|
||||
{
|
||||
}
|
||||
|
||||
GitoriousHost::GitoriousHost(const QString &h, const QString &d) :
|
||||
hostName(h),
|
||||
description(d),
|
||||
state(ProjectsQueryRunning)
|
||||
{
|
||||
}
|
||||
|
||||
int GitoriousHost::findCategory(const QString &n) const
|
||||
{
|
||||
const int count = categories.size();
|
||||
for (int i = 0; i < count; i++)
|
||||
if (categories.at(i)->name == n)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug d, const GitoriousRepository &r)
|
||||
{
|
||||
QDebug nospace = d.nospace();
|
||||
nospace << "name=" << r.name << '/' << r.id << '/' << r.type << r.owner
|
||||
<<" push=" << r.pushUrl << " clone=" << r.cloneUrl << " descr=" << r.description;
|
||||
return d;
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug d, const GitoriousProject &p)
|
||||
{
|
||||
QDebug nospace = d.nospace();
|
||||
nospace << " project=" << p.name << " description=" << p.description << '\n';
|
||||
foreach(const GitoriousRepository &r, p.repositories)
|
||||
nospace << " " << r << '\n';
|
||||
return d;
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug d, const GitoriousCategory &c)
|
||||
{
|
||||
d.nospace() << " category=" << c.name << '\n';
|
||||
return d;
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug d, const GitoriousHost &h)
|
||||
{
|
||||
QDebug nospace = d.nospace();
|
||||
nospace << " Host=" << h.hostName << " description=" << h.description << '\n';
|
||||
foreach(const QSharedPointer<GitoriousCategory> &c, h.categories)
|
||||
nospace << *c;
|
||||
foreach(const QSharedPointer<GitoriousProject> &p, h.projects)
|
||||
nospace << *p;
|
||||
return d;
|
||||
}
|
||||
|
||||
/* GitoriousProjectReader: Helper class for parsing project list output
|
||||
* \code
|
||||
projects...>
|
||||
<project>
|
||||
<bugtracker-url>
|
||||
<created-at>
|
||||
<description>... </description>
|
||||
<home-url> (rarely set)
|
||||
<license>
|
||||
<mailinglist-url>
|
||||
<slug> (name)
|
||||
<title>MuleFTW</title>
|
||||
<owner>
|
||||
<repositories>
|
||||
<mainlines> // Optional
|
||||
<repository>
|
||||
<id>
|
||||
<name>
|
||||
<owner>
|
||||
<clone_url>
|
||||
</repository>
|
||||
</mainlines>
|
||||
<clones> // Optional
|
||||
</clones>
|
||||
</repositories>
|
||||
</project>
|
||||
|
||||
* \endcode */
|
||||
|
||||
class GitoriousProjectReader
|
||||
{
|
||||
Q_DISABLE_COPY(GitoriousProjectReader)
|
||||
public:
|
||||
typedef GitoriousCategory::ProjectList ProjectList;
|
||||
|
||||
GitoriousProjectReader();
|
||||
ProjectList read(const QByteArray &a, QString *errorMessage);
|
||||
|
||||
private:
|
||||
void readProjects(QXmlStreamReader &r);
|
||||
QSharedPointer<GitoriousProject> readProject(QXmlStreamReader &r);
|
||||
QList<GitoriousRepository> readRepositories(QXmlStreamReader &r);
|
||||
GitoriousRepository readRepository(QXmlStreamReader &r, int defaultType = -1);
|
||||
void readUnknownElement(QXmlStreamReader &r);
|
||||
|
||||
const QString m_mainLinesElement;
|
||||
const QString m_clonesElement;
|
||||
ProjectList m_projects;
|
||||
};
|
||||
|
||||
GitoriousProjectReader::GitoriousProjectReader() :
|
||||
m_mainLinesElement(QLatin1String("mainlines")),
|
||||
m_clonesElement(QLatin1String("clones"))
|
||||
{
|
||||
}
|
||||
|
||||
GitoriousProjectReader::ProjectList GitoriousProjectReader::read(const QByteArray &a, QString *errorMessage)
|
||||
{
|
||||
m_projects.clear();
|
||||
QXmlStreamReader reader(a);
|
||||
|
||||
while (!reader.atEnd()) {
|
||||
reader.readNext();
|
||||
if (reader.isStartElement()) {
|
||||
if (reader.name() == QLatin1String("projects")) {
|
||||
readProjects(reader);
|
||||
} else {
|
||||
readUnknownElement(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (reader.hasError()) {
|
||||
*errorMessage = QString::fromLatin1("Error at %1:%2: %3").arg(reader.lineNumber()).arg(reader.columnNumber()).arg(reader.errorString());
|
||||
m_projects.clear();
|
||||
}
|
||||
|
||||
return m_projects;
|
||||
}
|
||||
|
||||
bool gitoriousProjectLessThan(const QSharedPointer<GitoriousProject> &p1, const QSharedPointer<GitoriousProject> &p2)
|
||||
{
|
||||
return p1->name.compare(p2->name, Qt::CaseInsensitive) < 0;
|
||||
}
|
||||
|
||||
void GitoriousProjectReader::readProjects(QXmlStreamReader &reader)
|
||||
{
|
||||
while (!reader.atEnd()) {
|
||||
reader.readNext();
|
||||
|
||||
if (reader.isEndElement())
|
||||
break;
|
||||
|
||||
if (reader.isStartElement()) {
|
||||
if (reader.name() == "project") {
|
||||
const QSharedPointer<GitoriousProject> p = readProject(reader);
|
||||
if (!p->name.isEmpty())
|
||||
m_projects.push_back(p);
|
||||
} else {
|
||||
readUnknownElement(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QSharedPointer<GitoriousProject> GitoriousProjectReader::readProject(QXmlStreamReader &reader)
|
||||
{
|
||||
QSharedPointer<GitoriousProject> project(new GitoriousProject);
|
||||
|
||||
while (!reader.atEnd()) {
|
||||
reader.readNext();
|
||||
if (reader.isEndElement())
|
||||
break;
|
||||
|
||||
if (reader.isStartElement()) {
|
||||
const QStringRef name = reader.name();
|
||||
if (name == QLatin1String("description")) {
|
||||
project->description = reader.readElementText();
|
||||
} else if (name == QLatin1String("title")) {
|
||||
project->name = reader.readElementText();
|
||||
} else if (name == QLatin1String("slug") && project->name.isEmpty()) {
|
||||
project->name = reader.readElementText();
|
||||
} else if (name == QLatin1String("repositories")) {
|
||||
project->repositories = readRepositories(reader);
|
||||
} else {
|
||||
readUnknownElement(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
return project;
|
||||
}
|
||||
|
||||
QList<GitoriousRepository> GitoriousProjectReader::readRepositories(QXmlStreamReader &reader)
|
||||
{
|
||||
QList<GitoriousRepository> repositories;
|
||||
int defaultType = -1;
|
||||
|
||||
// The "mainlines"/"clones" elements are not used in the
|
||||
// Nokia setup, handle them optionally.
|
||||
while (!reader.atEnd()) {
|
||||
reader.readNext();
|
||||
|
||||
if (reader.isEndElement()) {
|
||||
const QStringRef name = reader.name();
|
||||
if (name == m_mainLinesElement || name == m_clonesElement) {
|
||||
defaultType = -1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (reader.isStartElement()) {
|
||||
const QStringRef name = reader.name();
|
||||
if (reader.name() == QLatin1String("repository")) {
|
||||
repositories.push_back(readRepository(reader, defaultType));
|
||||
} else if (name == m_mainLinesElement) {
|
||||
defaultType = GitoriousRepository::MainLineRepository;
|
||||
} else if (name == m_clonesElement) {
|
||||
defaultType = GitoriousRepository::CloneRepository;
|
||||
} else {
|
||||
readUnknownElement(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
return repositories;
|
||||
}
|
||||
|
||||
GitoriousRepository GitoriousProjectReader::readRepository(QXmlStreamReader &reader, int defaultType)
|
||||
{
|
||||
GitoriousRepository repository;
|
||||
if (defaultType >= 0)
|
||||
repository.type = static_cast<GitoriousRepository::Type>(defaultType);
|
||||
|
||||
while (!reader.atEnd()) {
|
||||
reader.readNext();
|
||||
|
||||
if (reader.isEndElement())
|
||||
break;
|
||||
|
||||
if (reader.isStartElement()) {
|
||||
const QStringRef name = reader.name();
|
||||
if (name == QLatin1String("name")) {
|
||||
repository.name = reader.readElementText();
|
||||
} else if (name == QLatin1String("owner")) {
|
||||
repository.owner = reader.readElementText();
|
||||
} else if (name == QLatin1String("id")) {
|
||||
repository.id = reader.readElementText().toInt();
|
||||
} else if (name == QLatin1String("description")) {
|
||||
repository.description = reader.readElementText();
|
||||
} else if (name == QLatin1String("push_url")) {
|
||||
repository.pushUrl = reader.readElementText();
|
||||
} else if (name == QLatin1String("clone_url")) {
|
||||
repository.cloneUrl = reader.readElementText();
|
||||
} else if (name == QLatin1String("namespace")) {
|
||||
repository.type = repositoryType(reader.readElementText());
|
||||
} else {
|
||||
readUnknownElement(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
return repository;
|
||||
}
|
||||
|
||||
void GitoriousProjectReader::readUnknownElement(QXmlStreamReader &reader)
|
||||
{
|
||||
Q_ASSERT(reader.isStartElement());
|
||||
|
||||
while (!reader.atEnd()) {
|
||||
reader.readNext();
|
||||
|
||||
if (reader.isEndElement())
|
||||
break;
|
||||
|
||||
if (reader.isStartElement())
|
||||
readUnknownElement(reader);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Gitorious
|
||||
|
||||
Gitorious::Gitorious() :
|
||||
m_networkManager(0)
|
||||
{
|
||||
}
|
||||
|
||||
Gitorious &Gitorious::instance()
|
||||
{
|
||||
static Gitorious gitorious;
|
||||
return gitorious;
|
||||
}
|
||||
|
||||
void Gitorious::emitError(const QString &e)
|
||||
{
|
||||
qWarning("%s\n", qPrintable(e));
|
||||
emit error(e);
|
||||
}
|
||||
|
||||
void Gitorious::addHost(const QString &addr, const QString &description)
|
||||
{
|
||||
addHost(GitoriousHost(addr, description));
|
||||
}
|
||||
|
||||
void Gitorious::addHost(const GitoriousHost &host)
|
||||
{
|
||||
if (debug)
|
||||
qDebug() << host;
|
||||
const int index = m_hosts.size();
|
||||
m_hosts.push_back(host);
|
||||
if (host.categories.empty()) {
|
||||
updateCategories(index);
|
||||
m_hosts.back().state = GitoriousHost::ProjectsQueryRunning;
|
||||
} else {
|
||||
m_hosts.back().state = GitoriousHost::ProjectsComplete;
|
||||
}
|
||||
if (host.projects.empty())
|
||||
updateProjectList(index);
|
||||
emit hostAdded(index);
|
||||
}
|
||||
|
||||
void Gitorious::removeAt(int index)
|
||||
{
|
||||
m_hosts.removeAt(index);
|
||||
emit hostRemoved(index);
|
||||
}
|
||||
|
||||
int Gitorious::findByHostName(const QString &hostName) const
|
||||
{
|
||||
const int size = m_hosts.size();
|
||||
for (int i = 0; i < size; i++)
|
||||
if (m_hosts.at(i).hostName == hostName)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Gitorious::setHostDescription(int index, const QString &s)
|
||||
{
|
||||
m_hosts[index].description = s;
|
||||
}
|
||||
|
||||
QString Gitorious::hostDescription(int index) const
|
||||
{
|
||||
return m_hosts.at(index).description;
|
||||
}
|
||||
|
||||
void Gitorious::listCategoriesReply(int index, QByteArray dataB)
|
||||
{
|
||||
/* For now, parse the HTML of the projects site for "Popular Categories":
|
||||
* \code
|
||||
* <h4>Popular Categories:</h4>
|
||||
* <ul class="...">
|
||||
* <li class="..."><a href="..."><category></a> </li>
|
||||
* \endcode */
|
||||
do {
|
||||
const int catIndex = dataB.indexOf("Popular Categories:");
|
||||
const int endIndex = catIndex != -1 ? dataB.indexOf("</ul>", catIndex) : -1;
|
||||
if (debug)
|
||||
qDebug() << "listCategoriesReply cat pos=" << catIndex << endIndex;
|
||||
if (endIndex == -1)
|
||||
break;
|
||||
dataB.truncate(endIndex);
|
||||
dataB.remove(0, catIndex);
|
||||
const QString data = QString::fromUtf8(dataB);
|
||||
// Cut out the contents of the anchors
|
||||
QRegExp pattern = QRegExp(QLatin1String("<a href=[^>]+>([^<]+)</a>"));
|
||||
Q_ASSERT(pattern.isValid());
|
||||
GitoriousHost::CategoryList &categories = m_hosts[index].categories;
|
||||
for (int pos = pattern.indexIn(data) ; pos != -1; ) {
|
||||
const QString cat = pattern.cap(1);
|
||||
categories.push_back(QSharedPointer<GitoriousCategory>(new GitoriousCategory(cat)));
|
||||
pos = pattern.indexIn(data, pos + pattern.matchedLength());
|
||||
}
|
||||
} while (false);
|
||||
|
||||
emit categoryListReceived(index);
|
||||
}
|
||||
|
||||
void Gitorious::listProjectsReply(int hostIndex, int page, const QByteArray &data)
|
||||
{
|
||||
// Receive projects.
|
||||
QString errorMessage;
|
||||
GitoriousCategory::ProjectList projects = GitoriousProjectReader().read(data, &errorMessage);
|
||||
|
||||
if (debug) {
|
||||
qDebug() << "listProjectsReply" << hostName(hostIndex)
|
||||
<< "page=" << page << " got" << projects.size();
|
||||
if (debug > 1)
|
||||
qDebug() << '\n' <<data;
|
||||
}
|
||||
|
||||
if (!errorMessage.isEmpty()) {
|
||||
emitError(tr("Error parsing reply from '%1': %2").arg(hostName(hostIndex), errorMessage));
|
||||
if (projects.empty())
|
||||
m_hosts[hostIndex].state = GitoriousHost::Error;
|
||||
}
|
||||
|
||||
// Add the projects and start next request if 20 projects received
|
||||
GitoriousCategory::ProjectList &hostProjects = m_hosts[hostIndex].projects;
|
||||
if (!projects.empty())
|
||||
hostProjects.append(projects);
|
||||
|
||||
if (projects.size() == ProjectsPageSize) {
|
||||
startProjectsRequest(hostIndex, page + 1);
|
||||
emit projectListPageReceived(hostIndex, page);
|
||||
} else {
|
||||
// We are done
|
||||
m_hosts[hostIndex].state = GitoriousHost::ProjectsComplete;
|
||||
emit projectListReceived(hostIndex);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int replyPage(const QNetworkReply *reply)
|
||||
{ return reply->property(pagePropertyC).toInt(); }
|
||||
|
||||
void Gitorious::slotReplyFinished()
|
||||
{
|
||||
// Dispatch the answers via dynamic properties
|
||||
if (QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender())) {
|
||||
const int protocol = reply->property(protocolPropertyC).toInt();
|
||||
// Locate host by name (in case one was deleted in the meantime)
|
||||
const QString hostName = reply->property(hostNamePropertyC).toString();
|
||||
const int hostIndex = findByHostName(hostName);
|
||||
if (hostIndex == -1) // Entry deleted in-between?
|
||||
return;
|
||||
if (reply->error() == QNetworkReply::NoError) {
|
||||
const QByteArray data = reply->readAll();
|
||||
switch (protocol) {
|
||||
case ListProjectsProtocol:
|
||||
listProjectsReply(hostIndex, replyPage(reply), data);
|
||||
break;
|
||||
case ListCategoriesProtocol:
|
||||
listCategoriesReply(hostIndex, data);
|
||||
break;
|
||||
|
||||
} // switch protocol
|
||||
} else {
|
||||
const QString msg = tr("Request failed for '%1': %2").arg(m_hosts.at(hostIndex).hostName, reply->errorString());
|
||||
emitError(msg);
|
||||
}
|
||||
reply->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
// Create a network request. Set dynamic properties on it to be able to
|
||||
// dispatch. Use host name in case an entry is removed in-between
|
||||
QNetworkReply *Gitorious::createRequest(const QUrl &url, int protocol, int hostIndex, int page)
|
||||
{
|
||||
if (!m_networkManager)
|
||||
m_networkManager = new QNetworkAccessManager(this);
|
||||
QNetworkReply *reply = m_networkManager->get(QNetworkRequest(url));
|
||||
connect(reply, SIGNAL(finished()), this, SLOT(slotReplyFinished()));
|
||||
reply->setProperty(protocolPropertyC, QVariant(protocol));
|
||||
reply->setProperty(hostNamePropertyC, QVariant(hostName(hostIndex)));
|
||||
if (page >= 0)
|
||||
reply->setProperty(pagePropertyC, QVariant(page));
|
||||
if (debug)
|
||||
qDebug() << "createRequest" << url;
|
||||
return reply;
|
||||
}
|
||||
|
||||
void Gitorious::updateCategories(int index)
|
||||
{
|
||||
// For now, parse the HTML of the projects site for "Popular Categories":
|
||||
QUrl url;
|
||||
url.setScheme(QLatin1String("http"));
|
||||
url.setHost(hostName(index));
|
||||
url.setPath(QLatin1String("/projects"));
|
||||
createRequest(url, ListCategoriesProtocol, index);
|
||||
}
|
||||
|
||||
void Gitorious::updateProjectList(int hostIndex)
|
||||
{
|
||||
startProjectsRequest(hostIndex);
|
||||
}
|
||||
|
||||
void Gitorious::startProjectsRequest(int hostIndex, int page)
|
||||
{
|
||||
const QUrl url = xmlRequest(hostName(hostIndex), QLatin1String("projects"), page);
|
||||
createRequest(url, ListProjectsProtocol, hostIndex, page);
|
||||
}
|
||||
|
||||
// Serialize hosts/descriptions as a list of "<host>|descr".
|
||||
void Gitorious::saveSettings(const QString &group, QSettings *s)
|
||||
{
|
||||
const QChar separator = QLatin1Char('|');
|
||||
QStringList hosts;
|
||||
foreach(const GitoriousHost &h, m_hosts) {
|
||||
QString entry = h.hostName;
|
||||
if (!h.description.isEmpty()) {
|
||||
entry += separator;
|
||||
entry += h.description;
|
||||
}
|
||||
hosts.push_back(entry);
|
||||
}
|
||||
s->beginGroup(group);
|
||||
s->setValue(QLatin1String(settingsKeyC), hosts);
|
||||
s->endGroup();
|
||||
}
|
||||
|
||||
void Gitorious::restoreSettings(const QString &group, const QSettings *s)
|
||||
{
|
||||
m_hosts.clear();
|
||||
const QChar separator = QLatin1Char('|');
|
||||
const QStringList hosts = s->value(group + QLatin1Char('/') + QLatin1String(settingsKeyC), QStringList()).toStringList();
|
||||
foreach (const QString &h, hosts) {
|
||||
const int sepPos = h.indexOf(separator);
|
||||
if (sepPos == -1) {
|
||||
addHost(GitoriousHost(h));
|
||||
} else {
|
||||
addHost(GitoriousHost(h.mid(0, sepPos), h.mid(sepPos + 1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GitoriousHost Gitorious::gitoriousOrg()
|
||||
{
|
||||
return GitoriousHost(QLatin1String("gitorious.org"), tr("Open source projects that use Git."));
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Gitorious
|
||||
177
src/plugins/git/gitorious/gitorious.h
Normal file
177
src/plugins/git/gitorious/gitorious.h
Normal file
@@ -0,0 +1,177 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** Commercial Usage
|
||||
**
|
||||
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||
** accordance with the Qt Commercial License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Nokia.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** If you are unsure which license is appropriate for your use, please
|
||||
** contact the sales department at http://www.qtsoftware.com/contact.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef GITORIOUS_H
|
||||
#define GITORIOUS_H
|
||||
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QSharedPointer>
|
||||
#include <QtCore/QUrl>
|
||||
#include <QtCore/QObject>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QNetworkAccessManager;
|
||||
class QNetworkReply;
|
||||
class QDebug;
|
||||
class QUrl;
|
||||
class QSettings;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Gitorious {
|
||||
namespace Internal {
|
||||
|
||||
struct GitoriousRepository
|
||||
{
|
||||
enum Type {
|
||||
MainLineRepository,
|
||||
CloneRepository,
|
||||
BaselineRepository, // Nokia extension
|
||||
SharedRepository, // Nokia extension
|
||||
PersonalRepository, // Nokia extension
|
||||
};
|
||||
|
||||
GitoriousRepository();
|
||||
|
||||
QString name;
|
||||
QString owner;
|
||||
QUrl pushUrl;
|
||||
QUrl cloneUrl;
|
||||
QString description;
|
||||
Type type;
|
||||
int id;
|
||||
};
|
||||
|
||||
struct GitoriousProject
|
||||
{
|
||||
QString name;
|
||||
QString description;
|
||||
QList<GitoriousRepository> repositories;
|
||||
};
|
||||
|
||||
struct GitoriousCategory
|
||||
{
|
||||
typedef QList<QSharedPointer<GitoriousProject > > ProjectList;
|
||||
|
||||
GitoriousCategory(const QString &name = QString());
|
||||
|
||||
QString name;
|
||||
};
|
||||
|
||||
struct GitoriousHost
|
||||
{
|
||||
enum State { ProjectsQueryRunning, ProjectsComplete, Error };
|
||||
typedef QList<QSharedPointer<GitoriousCategory> > CategoryList;
|
||||
typedef QList<QSharedPointer<GitoriousProject > > ProjectList;
|
||||
|
||||
GitoriousHost(const QString &hostName = QString(), const QString &description = QString());
|
||||
int findCategory(const QString &) const;
|
||||
|
||||
QString hostName;
|
||||
QString description;
|
||||
CategoryList categories;
|
||||
ProjectList projects;
|
||||
State state;
|
||||
};
|
||||
|
||||
QDebug operator<<(QDebug d, const GitoriousRepository &r);
|
||||
QDebug operator<<(QDebug d, const GitoriousProject &p);
|
||||
QDebug operator<<(QDebug d, const GitoriousCategory &p);
|
||||
QDebug operator<<(QDebug d, const GitoriousHost &p);
|
||||
|
||||
/* Singleton that manages a list of gitorious hosts, running network queries
|
||||
* in the background. It models hosts with a flat list of projects (Gitorious
|
||||
* has a concept of categories, but this is not enforced, and there is no
|
||||
* way to query them).
|
||||
* As 24.07.2009, the only supported XML request of the host is a paginated
|
||||
* "list-all-projects". */
|
||||
|
||||
class Gitorious : public QObject
|
||||
{
|
||||
Q_DISABLE_COPY(Gitorious)
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static Gitorious &instance();
|
||||
|
||||
const QList<GitoriousHost> &hosts() const { return m_hosts; }
|
||||
int hostCount() const { return m_hosts.size(); }
|
||||
int categoryCount(int hostIndex) const { return m_hosts.at(hostIndex).categories.size(); }
|
||||
int projectCount(int hostIndex) const { return m_hosts.at(hostIndex).projects.size(); }
|
||||
GitoriousHost::State hostState(int hostIndex) const { return m_hosts.at(hostIndex).state; }
|
||||
|
||||
// If no projects are set, start an asynchronous request querying
|
||||
// the projects/categories of the host.
|
||||
void addHost(const QString &addr, const QString &description = QString());
|
||||
void addHost(const GitoriousHost &host);
|
||||
void removeAt(int index);
|
||||
|
||||
int findByHostName(const QString &hostName) const;
|
||||
QString hostName(int i) const { return m_hosts.at(i).hostName; }
|
||||
QString categoryName(int hostIndex, int categoryIndex) const { return m_hosts.at(hostIndex).categories.at(categoryIndex)->name; }
|
||||
|
||||
QString hostDescription(int index) const;
|
||||
void setHostDescription(int index, const QString &s);
|
||||
|
||||
void saveSettings(const QString &group, QSettings *s);
|
||||
void restoreSettings(const QString &group, const QSettings *s);
|
||||
|
||||
// Return predefined entry for "gitorious.org".
|
||||
static GitoriousHost gitoriousOrg();
|
||||
|
||||
signals:
|
||||
void error(const QString &);
|
||||
void projectListReceived(int hostIndex);
|
||||
void projectListPageReceived(int hostIndex, int page);
|
||||
void categoryListReceived(int index);
|
||||
void hostAdded(int index);
|
||||
void hostRemoved(int index);
|
||||
|
||||
public slots:
|
||||
void updateProjectList(int hostIndex);
|
||||
void updateCategories(int index);
|
||||
|
||||
private slots:
|
||||
void slotReplyFinished();
|
||||
|
||||
private:
|
||||
Gitorious();
|
||||
void listProjectsReply(int hostIndex, int page, const QByteArray &data);
|
||||
void listCategoriesReply(int index, QByteArray data);
|
||||
void emitError(const QString &e);
|
||||
QNetworkReply *createRequest(const QUrl &url, int protocol, int hostIndex, int page = -1);
|
||||
void startProjectsRequest(int index, int page = 1);
|
||||
|
||||
QList<GitoriousHost> m_hosts;
|
||||
QNetworkAccessManager *m_networkManager;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Gitorious
|
||||
|
||||
#endif // GITORIOUS_H
|
||||
22
src/plugins/git/gitorious/gitorious.pri
Normal file
22
src/plugins/git/gitorious/gitorious.pri
Normal file
@@ -0,0 +1,22 @@
|
||||
QT += network
|
||||
INCLUDEPATH+=$$PWD
|
||||
|
||||
HEADERS += $$PWD/gitoriousclonewizard.h \
|
||||
$$PWD/gitorioushostwizardpage.h \
|
||||
$$PWD/gitoriousrepositorywizardpage.h \
|
||||
$$PWD/gitoriousprojectwizardpage.h \
|
||||
$$PWD/gitoriousprojectwidget.h \
|
||||
$$PWD/gitorioushostwidget.h \
|
||||
$$PWD/gitorious.h
|
||||
|
||||
SOURCES += $$PWD/gitoriousclonewizard.cpp \
|
||||
$$PWD/gitorioushostwizardpage.cpp \
|
||||
$$PWD/gitoriousrepositorywizardpage.cpp \
|
||||
$$PWD/gitoriousprojectwizardpage.cpp \
|
||||
$$PWD/gitoriousprojectwidget.cpp \
|
||||
$$PWD/gitorioushostwidget.cpp \
|
||||
$$PWD/gitorious.cpp
|
||||
|
||||
FORMS += $$PWD/gitorioushostwidget.ui \
|
||||
$$PWD/gitoriousrepositorywizardpage.ui \
|
||||
$$PWD/gitoriousprojectwidget.ui
|
||||
111
src/plugins/git/gitorious/gitoriousclonewizard.cpp
Normal file
111
src/plugins/git/gitorious/gitoriousclonewizard.cpp
Normal file
@@ -0,0 +1,111 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** Commercial Usage
|
||||
**
|
||||
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||
** accordance with the Qt Commercial License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Nokia.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** If you are unsure which license is appropriate for your use, please
|
||||
** contact the sales department at http://www.qtsoftware.com/contact.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "gitoriousclonewizard.h"
|
||||
#include "gitorioushostwizardpage.h"
|
||||
#include "gitoriousprojectwizardpage.h"
|
||||
#include "gitoriousrepositorywizardpage.h"
|
||||
#include "clonewizardpage.h"
|
||||
|
||||
#include <vcsbase/checkoutjobs.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QtCore/QUrl>
|
||||
#include <QtGui/QIcon>
|
||||
|
||||
namespace Gitorious {
|
||||
namespace Internal {
|
||||
|
||||
// GitoriousCloneWizardPage: A git clone page taking its URL from the
|
||||
// projects page.
|
||||
|
||||
class GitoriousCloneWizardPage : public Git::CloneWizardPage {
|
||||
public:
|
||||
explicit GitoriousCloneWizardPage(const GitoriousRepositoryWizardPage *rp, QWidget *parent = 0);
|
||||
virtual void initializePage();
|
||||
|
||||
private:
|
||||
const GitoriousRepositoryWizardPage *m_repositoryPage;
|
||||
};
|
||||
|
||||
GitoriousCloneWizardPage::GitoriousCloneWizardPage(const GitoriousRepositoryWizardPage *rp, QWidget *parent) :
|
||||
Git::CloneWizardPage(parent),
|
||||
m_repositoryPage(rp)
|
||||
{
|
||||
}
|
||||
|
||||
void GitoriousCloneWizardPage::initializePage()
|
||||
{
|
||||
setRepository(m_repositoryPage->repositoryURL().toString());
|
||||
}
|
||||
|
||||
// -------- GitoriousCloneWizard
|
||||
GitoriousCloneWizard::GitoriousCloneWizard(QObject *parent) :
|
||||
VCSBase::BaseCheckoutWizard(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QIcon GitoriousCloneWizard::icon() const
|
||||
{
|
||||
return QIcon();
|
||||
}
|
||||
|
||||
QString GitoriousCloneWizard::description() const
|
||||
{
|
||||
return tr("Clones a project from a Gitorious repository.");
|
||||
}
|
||||
|
||||
QString GitoriousCloneWizard::name() const
|
||||
{
|
||||
return tr("Gitorious Repository Clone");
|
||||
}
|
||||
|
||||
QList<QWizardPage*> GitoriousCloneWizard::createParameterPages(const QString &path)
|
||||
{
|
||||
GitoriousHostWizardPage *hostPage = new GitoriousHostWizardPage;
|
||||
GitoriousProjectWizardPage *projectPage = new GitoriousProjectWizardPage(hostPage);
|
||||
GitoriousRepositoryWizardPage *repoPage = new GitoriousRepositoryWizardPage(projectPage);
|
||||
GitoriousCloneWizardPage *clonePage = new GitoriousCloneWizardPage(repoPage);
|
||||
clonePage->setPath(path);
|
||||
|
||||
QList<QWizardPage*> rc;
|
||||
rc << hostPage << projectPage << repoPage << clonePage;
|
||||
return rc;
|
||||
}
|
||||
|
||||
QSharedPointer<VCSBase::AbstractCheckoutJob> GitoriousCloneWizard::createJob(const QList<QWizardPage*> ¶meterPages,
|
||||
QString *checkoutPath)
|
||||
{
|
||||
const Git::CloneWizardPage *cwp = qobject_cast<const Git::CloneWizardPage *>(parameterPages.back());
|
||||
QTC_ASSERT(cwp, return QSharedPointer<VCSBase::AbstractCheckoutJob>())
|
||||
return cwp->createCheckoutJob(checkoutPath);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Gitorius
|
||||
60
src/plugins/git/gitorious/gitoriousclonewizard.h
Normal file
60
src/plugins/git/gitorious/gitoriousclonewizard.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** Commercial Usage
|
||||
**
|
||||
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||
** accordance with the Qt Commercial License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Nokia.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** If you are unsure which license is appropriate for your use, please
|
||||
** contact the sales department at http://www.qtsoftware.com/contact.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef GITORIOUSCLONEWIZARD_H
|
||||
#define GITORIOUSCLONEWIZARD_H
|
||||
|
||||
#include <vcsbase/basecheckoutwizard.h>
|
||||
|
||||
namespace Gitorious {
|
||||
namespace Internal {
|
||||
|
||||
// GitoriousCloneWizard: A wizard allowing for browsing
|
||||
// Gitorious-hosted projects.
|
||||
class GitoriousCloneWizard : public VCSBase::BaseCheckoutWizard
|
||||
{
|
||||
public:
|
||||
explicit GitoriousCloneWizard(QObject *parent = 0);
|
||||
|
||||
// IWizard
|
||||
virtual QIcon icon() const;
|
||||
virtual QString description() const;
|
||||
virtual QString name() const;
|
||||
|
||||
protected:
|
||||
// BaseCheckoutWizard
|
||||
virtual QList<QWizardPage*> createParameterPages(const QString &path);
|
||||
virtual QSharedPointer<VCSBase::AbstractCheckoutJob> createJob(const QList<QWizardPage*> ¶meterPages,
|
||||
QString *checkoutPath);
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Gitorious
|
||||
|
||||
#endif // GITORIOUSCLONEWIZARD_H
|
||||
319
src/plugins/git/gitorious/gitorioushostwidget.cpp
Normal file
319
src/plugins/git/gitorious/gitorioushostwidget.cpp
Normal file
@@ -0,0 +1,319 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** Commercial Usage
|
||||
**
|
||||
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||
** accordance with the Qt Commercial License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Nokia.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** If you are unsure which license is appropriate for your use, please
|
||||
** contact the sales department at http://www.qtsoftware.com/contact.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "gitorious.h"
|
||||
#include "gitorioushostwidget.h"
|
||||
#include "ui_gitorioushostwidget.h"
|
||||
|
||||
#include <coreplugin/coreconstants.h>
|
||||
|
||||
#include <QtCore/QUrl>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QTimer>
|
||||
|
||||
#include <QtGui/QStandardItem>
|
||||
#include <QtGui/QStandardItemModel>
|
||||
#include <QtGui/QItemSelectionModel>
|
||||
#include <QtGui/QDesktopServices>
|
||||
#include <QtGui/QIcon>
|
||||
#include <QtGui/QStyle>
|
||||
|
||||
enum { debug = 0 };
|
||||
|
||||
enum { NewDummyEntryRole = Qt::UserRole + 1 };
|
||||
|
||||
namespace Gitorious {
|
||||
namespace Internal {
|
||||
|
||||
enum { HostNameColumn, ProjectCountColumn, DescriptionColumn, ColumnCount };
|
||||
|
||||
// Create a model row for a host. Make the host name editable as specified by
|
||||
// flag.
|
||||
static QList<QStandardItem *> hostEntry(const QString &host,
|
||||
int projectCount,
|
||||
const QString &description, bool isDummyEntry)
|
||||
{
|
||||
const Qt::ItemFlags nonEditableFlags = (Qt::ItemIsSelectable|Qt::ItemIsEnabled);
|
||||
const Qt::ItemFlags editableFlags = nonEditableFlags|Qt::ItemIsEditable;
|
||||
QStandardItem *hostItem = new QStandardItem(host);
|
||||
hostItem->setFlags(isDummyEntry ? editableFlags : nonEditableFlags);
|
||||
// Empty for dummy, else "..." or count
|
||||
QStandardItem *projectCountItem = 0;
|
||||
QString countItemText;
|
||||
if (!isDummyEntry) {
|
||||
countItemText = projectCount ? QString::number(projectCount) : QString(QLatin1String("..."));
|
||||
}
|
||||
projectCountItem = new QStandardItem(countItemText);
|
||||
projectCountItem->setFlags(nonEditableFlags);
|
||||
QStandardItem *descriptionItem = new QStandardItem(description);
|
||||
descriptionItem->setFlags(editableFlags);
|
||||
QList<QStandardItem *> rc;
|
||||
rc << hostItem << projectCountItem << descriptionItem;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline QList<QStandardItem *> hostEntry(const GitoriousHost &h)
|
||||
{
|
||||
return hostEntry(h.hostName, h.projects.size(), h.description, false);
|
||||
}
|
||||
|
||||
GitoriousHostWidget::GitoriousHostWidget(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
m_newHost(tr("<New Host>")),
|
||||
ui(new Ui::GitoriousHostWidget),
|
||||
m_model(new QStandardItemModel(0, ColumnCount)),
|
||||
m_errorClearTimer(0),
|
||||
m_isValid(false),
|
||||
m_isHostListDirty(false)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->errorLabel->setVisible(false);
|
||||
ui->browseToolButton->setIcon(style()->standardIcon(QStyle::SP_MessageBoxInformation));
|
||||
connect(ui->browseToolButton, SIGNAL(clicked()), this, SLOT(slotBrowse()));
|
||||
ui->browseToolButton->setEnabled(false);
|
||||
ui->deleteToolButton->setIcon(QIcon(Core::Constants::ICON_MINUS));
|
||||
connect(ui->deleteToolButton, SIGNAL(clicked()), this, SLOT(slotDelete()));
|
||||
ui->deleteToolButton->setEnabled(false);
|
||||
|
||||
// Model
|
||||
QStringList headers;
|
||||
headers << tr("Host") << tr("Projects") << tr("Description");
|
||||
m_model->setHorizontalHeaderLabels(headers);
|
||||
|
||||
Gitorious &gitorious = Gitorious::instance();
|
||||
foreach( const GitoriousHost &gh, gitorious.hosts())
|
||||
m_model->appendRow(hostEntry(gh));
|
||||
appendNewDummyEntry();
|
||||
connect(m_model, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(slotItemEdited(QStandardItem*)));
|
||||
ui->hostView->setModel(m_model);
|
||||
|
||||
// View
|
||||
ui->hostView->setRootIsDecorated(false);
|
||||
ui->hostView->setUniformRowHeights(true);
|
||||
connect(ui->hostView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
|
||||
this, SLOT(slotCurrentChanged(QModelIndex,QModelIndex)));
|
||||
|
||||
ui->hostView->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
if (m_model->rowCount())
|
||||
selectRow(0);
|
||||
|
||||
connect(&gitorious, SIGNAL(projectListPageReceived(int,int)),
|
||||
this, SLOT(slotProjectListPageReceived(int)));
|
||||
connect(&gitorious, SIGNAL(projectListReceived(int)),
|
||||
this, SLOT(slotProjectListPageReceived(int)));
|
||||
|
||||
connect(&gitorious, SIGNAL(error(QString)), this, SLOT(slotError(QString)));
|
||||
|
||||
setMinimumWidth(700);
|
||||
}
|
||||
|
||||
GitoriousHostWidget::~GitoriousHostWidget()
|
||||
{
|
||||
// Prevent crash?
|
||||
Gitorious *gitorious = &Gitorious::instance();
|
||||
disconnect(gitorious, SIGNAL(projectListPageReceived(int,int)),
|
||||
this, SLOT(slotProjectListPageReceived(int)));
|
||||
disconnect(gitorious, SIGNAL(projectListReceived(int)),
|
||||
this, SLOT(slotProjectListPageReceived(int)));
|
||||
disconnect(gitorious, SIGNAL(error(QString)), this, SLOT(slotError(QString)));
|
||||
delete ui;
|
||||
}
|
||||
|
||||
int GitoriousHostWidget::selectedRow() const
|
||||
{
|
||||
const QModelIndex idx = ui->hostView->selectionModel()->currentIndex();
|
||||
if (idx.isValid())
|
||||
return idx.row();
|
||||
return -1;
|
||||
}
|
||||
|
||||
void GitoriousHostWidget::selectRow(int r)
|
||||
{
|
||||
if (r >= 0 && r != selectedRow()) {
|
||||
const QModelIndex index = m_model->index(r, 0);
|
||||
ui->hostView->selectionModel()->setCurrentIndex(index, QItemSelectionModel::Select|QItemSelectionModel::Current|QItemSelectionModel::Rows);
|
||||
}
|
||||
}
|
||||
|
||||
void GitoriousHostWidget::appendNewDummyEntry()
|
||||
{
|
||||
// Append a new entry where a host name is editable
|
||||
const QList<QStandardItem *> dummyRow = hostEntry(m_newHost, 0, QString(), true);
|
||||
dummyRow.front()->setData(QVariant(true), NewDummyEntryRole);
|
||||
m_model->appendRow(dummyRow);
|
||||
}
|
||||
|
||||
void GitoriousHostWidget::slotItemEdited(QStandardItem *item)
|
||||
{
|
||||
// Synchronize with Gitorious singleton.
|
||||
// Did someone enter a valid host name into the dummy item?
|
||||
// -> Create a new one.
|
||||
const int row = item->row();
|
||||
const bool isDummyEntry = row >= Gitorious::instance().hostCount();
|
||||
switch (item->column()) {
|
||||
case HostNameColumn:
|
||||
if (isDummyEntry) {
|
||||
Gitorious::instance().addHost(item->text(), m_model->item(row, DescriptionColumn)->text());
|
||||
item->setData(QVariant(false), NewDummyEntryRole);
|
||||
m_isHostListDirty = true;
|
||||
appendNewDummyEntry();
|
||||
selectRow(row);
|
||||
}
|
||||
break;
|
||||
case ProjectCountColumn:
|
||||
break;
|
||||
case DescriptionColumn:
|
||||
if (!isDummyEntry) {
|
||||
const QString description = item->text();
|
||||
if (description != Gitorious::instance().hostDescription(row)) {
|
||||
Gitorious::instance().setHostDescription(row, item->text());
|
||||
m_isHostListDirty = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GitoriousHostWidget::slotProjectListPageReceived(int row)
|
||||
{
|
||||
if (debug)
|
||||
qDebug() << Q_FUNC_INFO << row;
|
||||
// Update column
|
||||
const int projectCount = Gitorious::instance().projectCount(row);
|
||||
m_model->item(row, ProjectCountColumn)->setText(QString::number(projectCount));
|
||||
// If it is the currently selected host, re-check validity if not enabled
|
||||
if (!m_isValid) {
|
||||
const QModelIndex current = ui->hostView->selectionModel()->currentIndex();
|
||||
if (current.isValid() && current.row() == row)
|
||||
checkValid(current);
|
||||
}
|
||||
}
|
||||
|
||||
QStandardItem *GitoriousHostWidget::currentItem() const
|
||||
{
|
||||
const QModelIndex idx = ui->hostView->selectionModel()->currentIndex();
|
||||
if (idx.isValid())
|
||||
return m_model->itemFromIndex(idx.column() != 0 ? idx.sibling(idx.row(), 0) : idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GitoriousHostWidget::slotBrowse()
|
||||
{
|
||||
if (const QStandardItem *item = currentItem()) {
|
||||
const QUrl url(QLatin1String("http://") + item->text() + QLatin1Char('/'));
|
||||
if (url.isValid())
|
||||
QDesktopServices::openUrl(url);
|
||||
}
|
||||
}
|
||||
|
||||
void GitoriousHostWidget::slotDelete()
|
||||
{
|
||||
const QModelIndex index = ui->hostView->selectionModel()->currentIndex();
|
||||
ui->hostView->selectionModel()->clear();
|
||||
if (index.isValid()) {
|
||||
const int row = index.row();
|
||||
qDeleteAll(m_model->takeRow(row));
|
||||
Gitorious::instance().removeAt(row);
|
||||
m_isHostListDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void GitoriousHostWidget::slotCurrentChanged(const QModelIndex ¤t, const QModelIndex & /* previous */)
|
||||
{
|
||||
checkValid(current);
|
||||
}
|
||||
|
||||
void GitoriousHostWidget::checkValid(const QModelIndex &index)
|
||||
{
|
||||
if (debug)
|
||||
qDebug() << Q_FUNC_INFO << index;
|
||||
bool hasSelectedHost = false;
|
||||
bool hasProjects = false;
|
||||
if (index.isValid()) {
|
||||
// Are we on the new dummy item?
|
||||
Gitorious &gitorious = Gitorious::instance();
|
||||
const int row = index.row();
|
||||
hasSelectedHost = row < gitorious.hostCount();
|
||||
hasProjects = hasSelectedHost && gitorious.projectCount(row) > 0;
|
||||
}
|
||||
ui->deleteToolButton->setEnabled(hasSelectedHost);
|
||||
ui->browseToolButton->setEnabled(hasSelectedHost);
|
||||
|
||||
const bool valid = hasSelectedHost && hasProjects;
|
||||
if (valid != m_isValid) {
|
||||
m_isValid = valid;
|
||||
emit validChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool GitoriousHostWidget::isValid() const
|
||||
{
|
||||
return m_isValid;
|
||||
}
|
||||
|
||||
bool GitoriousHostWidget::isHostListDirty() const
|
||||
{
|
||||
return m_isHostListDirty;
|
||||
}
|
||||
|
||||
void GitoriousHostWidget::slotClearError()
|
||||
{
|
||||
ui->errorLabel->setVisible(false);
|
||||
ui->errorLabel->clear();
|
||||
}
|
||||
|
||||
void GitoriousHostWidget::slotError(const QString &e)
|
||||
{
|
||||
// Display error for a while
|
||||
ui->errorLabel->setText(e);
|
||||
ui->errorLabel->setVisible(true);
|
||||
if (!m_errorClearTimer) {
|
||||
m_errorClearTimer = new QTimer(this);
|
||||
m_errorClearTimer->setSingleShot(true);
|
||||
m_errorClearTimer->setInterval(5000);
|
||||
connect(m_errorClearTimer, SIGNAL(timeout()), this, SLOT(slotClearError()));
|
||||
}
|
||||
if (!m_errorClearTimer->isActive())
|
||||
m_errorClearTimer->start();
|
||||
}
|
||||
|
||||
void GitoriousHostWidget::changeEvent(QEvent *e)
|
||||
{
|
||||
QWidget::changeEvent(e);
|
||||
switch (e->type()) {
|
||||
case QEvent::LanguageChange:
|
||||
ui->retranslateUi(this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Gitorious
|
||||
103
src/plugins/git/gitorious/gitorioushostwidget.h
Normal file
103
src/plugins/git/gitorious/gitorioushostwidget.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** Commercial Usage
|
||||
**
|
||||
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||
** accordance with the Qt Commercial License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Nokia.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** If you are unsure which license is appropriate for your use, please
|
||||
** contact the sales department at http://www.qtsoftware.com/contact.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef GITORIOUSHOSTWIDGET_H
|
||||
#define GITORIOUSHOSTWIDGET_H
|
||||
|
||||
#include <QtGui/QWizardPage>
|
||||
#include <QtGui/QStandardItemModel>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QStandardItemModel;
|
||||
class QStandardItem;
|
||||
class QModelIndex;
|
||||
class QTimer;
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Gitorious {
|
||||
namespace Internal {
|
||||
|
||||
namespace Ui {
|
||||
class GitoriousHostWidget;
|
||||
}
|
||||
|
||||
/* A page listing gitorious hosts with browse/add options. isValid() and the
|
||||
* related change signals are provided for use within a QWizardPage.
|
||||
* Connects to the signals of Gitorious and updates the project count as the
|
||||
* it receives the projects. As soon as there are projects, isValid() becomes
|
||||
* true. */
|
||||
|
||||
class GitoriousHostWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
GitoriousHostWidget(QWidget *parent = 0);
|
||||
~GitoriousHostWidget();
|
||||
|
||||
// Has a host selected that has projects.
|
||||
bool isValid() const;
|
||||
int selectedRow() const;
|
||||
// hosts modified?
|
||||
bool isHostListDirty() const;
|
||||
|
||||
signals:
|
||||
void validChanged();
|
||||
|
||||
public slots:
|
||||
void selectRow(int);
|
||||
|
||||
protected:
|
||||
void changeEvent(QEvent *e);
|
||||
|
||||
private slots:
|
||||
void slotBrowse();
|
||||
void slotDelete();
|
||||
void slotCurrentChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
||||
void slotItemEdited(QStandardItem *item);
|
||||
void slotProjectListPageReceived(int row);
|
||||
void slotClearError();
|
||||
void slotError(const QString &e);
|
||||
|
||||
private:
|
||||
void appendNewDummyEntry();
|
||||
void checkValid(const QModelIndex ¤t);
|
||||
QStandardItem *currentItem() const;
|
||||
|
||||
const QString m_newHost;
|
||||
|
||||
Ui::GitoriousHostWidget *ui;
|
||||
QStandardItemModel *m_model;
|
||||
QTimer *m_errorClearTimer;
|
||||
bool m_isValid;
|
||||
bool m_isHostListDirty;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Gitorious
|
||||
#endif // GITORIOUSHOSTWIDGET_H
|
||||
63
src/plugins/git/gitorious/gitorioushostwidget.ui
Normal file
63
src/plugins/git/gitorious/gitorioushostwidget.ui
Normal file
@@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Gitorious::Internal::GitoriousHostWidget</class>
|
||||
<widget class="QWidget" name="Gitorious::Internal::GitoriousHostWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>356</width>
|
||||
<height>265</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QTreeView" name="hostView"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="buttonLayout">
|
||||
<item>
|
||||
<widget class="QToolButton" name="browseToolButton">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="deleteToolButton">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="buttonSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="errorLabel">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: red;</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
100
src/plugins/git/gitorious/gitorioushostwizardpage.cpp
Normal file
100
src/plugins/git/gitorious/gitorioushostwizardpage.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** Commercial Usage
|
||||
**
|
||||
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||
** accordance with the Qt Commercial License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Nokia.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** If you are unsure which license is appropriate for your use, please
|
||||
** contact the sales department at http://www.qtsoftware.com/contact.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#include "gitorioushostwizardpage.h"
|
||||
#include "gitorioushostwidget.h"
|
||||
#include "gitorious.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
|
||||
#include <QtCore/QSettings>
|
||||
#include <QtGui/QVBoxLayout>
|
||||
|
||||
static const char *settingsGroupC = "Gitorious";
|
||||
static const char *selectionKeyC = "/SelectedHost";
|
||||
|
||||
namespace Gitorious {
|
||||
namespace Internal {
|
||||
|
||||
// Ensure Gitorious is populated and create widget in right order.
|
||||
static GitoriousHostWidget *createHostWidget()
|
||||
{
|
||||
// First time? Populate gitorious from settings.
|
||||
// If there is still no host, add "gitorious.org"
|
||||
Gitorious &gitorious = Gitorious::instance();
|
||||
const QSettings *settings = Core::ICore::instance()->settings();
|
||||
const QString group = QLatin1String(settingsGroupC);
|
||||
if (!gitorious.hostCount()) {
|
||||
gitorious.restoreSettings(group, settings);
|
||||
if (!gitorious.hostCount())
|
||||
gitorious.addHost(Gitorious::gitoriousOrg());
|
||||
}
|
||||
// Now create widget
|
||||
GitoriousHostWidget *rc = new GitoriousHostWidget;
|
||||
// Restore selection
|
||||
const int selectedRow = settings->value(group + QLatin1String(selectionKeyC)).toInt();
|
||||
if (selectedRow >= 0 && selectedRow < gitorious.hostCount())
|
||||
rc->selectRow(selectedRow);
|
||||
return rc;
|
||||
}
|
||||
|
||||
GitoriousHostWizardPage::GitoriousHostWizardPage(QWidget *parent) :
|
||||
QWizardPage(parent),
|
||||
m_widget(createHostWidget())
|
||||
{
|
||||
connect(m_widget, SIGNAL(validChanged()), this, SIGNAL(completeChanged()));
|
||||
QVBoxLayout *lt = new QVBoxLayout;
|
||||
lt->addWidget(m_widget);
|
||||
setLayout(lt);
|
||||
setSubTitle(tr("Select a host."));
|
||||
}
|
||||
|
||||
GitoriousHostWizardPage::~GitoriousHostWizardPage()
|
||||
{
|
||||
// Write out settings + selected row.
|
||||
QSettings *settings = Core::ICore::instance()->settings();
|
||||
if (m_widget->isHostListDirty())
|
||||
Gitorious::instance().saveSettings(QLatin1String(settingsGroupC), settings);
|
||||
if (m_widget->isValid())
|
||||
settings->setValue(QLatin1String(settingsGroupC) + QLatin1String(selectionKeyC), m_widget->selectedRow());
|
||||
}
|
||||
|
||||
bool GitoriousHostWizardPage::isComplete() const
|
||||
{
|
||||
return m_widget->isValid();
|
||||
}
|
||||
|
||||
int GitoriousHostWizardPage::selectedHostIndex() const
|
||||
{
|
||||
return m_widget->selectedRow();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Gitorious
|
||||
58
src/plugins/git/gitorious/gitorioushostwizardpage.h
Normal file
58
src/plugins/git/gitorious/gitorioushostwizardpage.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** Commercial Usage
|
||||
**
|
||||
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||
** accordance with the Qt Commercial License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Nokia.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** If you are unsure which license is appropriate for your use, please
|
||||
** contact the sales department at http://www.qtsoftware.com/contact.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef GITORIOUSHOSTWIZARDPAGE_H
|
||||
#define GITORIOUSHOSTWIZARDPAGE_H
|
||||
|
||||
#include <QtGui/QWizardPage>
|
||||
|
||||
namespace Gitorious {
|
||||
namespace Internal {
|
||||
|
||||
class GitoriousHostWidget;
|
||||
|
||||
/* A page listing gitorious hosts with browse/add options. */
|
||||
|
||||
class GitoriousHostWizardPage : public QWizardPage {
|
||||
Q_OBJECT
|
||||
public:
|
||||
GitoriousHostWizardPage(QWidget *parent = 0);
|
||||
virtual ~GitoriousHostWizardPage();
|
||||
|
||||
virtual bool isComplete() const;
|
||||
|
||||
int selectedHostIndex() const;
|
||||
|
||||
private:
|
||||
GitoriousHostWidget *m_widget;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Gitorious
|
||||
#endif // GITORIOUSHOSTWIZARDPAGE_H
|
||||
304
src/plugins/git/gitorious/gitoriousprojectwidget.cpp
Normal file
304
src/plugins/git/gitorious/gitoriousprojectwidget.cpp
Normal file
@@ -0,0 +1,304 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** Commercial Usage
|
||||
**
|
||||
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||
** accordance with the Qt Commercial License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Nokia.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** If you are unsure which license is appropriate for your use, please
|
||||
** contact the sales department at http://www.qtsoftware.com/contact.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "gitoriousprojectwidget.h"
|
||||
#include "gitorioushostwizardpage.h"
|
||||
#include "gitorious.h"
|
||||
#include "ui_gitoriousprojectwidget.h"
|
||||
|
||||
#include <coreplugin/coreconstants.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QtCore/QRegExp>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#include <QtGui/QStandardItemModel>
|
||||
#include <QtGui/QSortFilterProxyModel>
|
||||
#include <QtGui/QStandardItem>
|
||||
#include <QtGui/QItemSelectionModel>
|
||||
#include <QtGui/QDesktopServices>
|
||||
#include <QtGui/QIcon>
|
||||
#include <QtGui/QStyle>
|
||||
|
||||
enum {
|
||||
urlRole = Qt::UserRole + 1 // Project has a URL in the description
|
||||
};
|
||||
|
||||
enum { debug = 1 };
|
||||
|
||||
namespace Gitorious {
|
||||
namespace Internal {
|
||||
|
||||
enum { ProjectColumn, DescriptionColumn, ColumnCount };
|
||||
|
||||
GitoriousProjectWidget::GitoriousProjectWidget(int hostIndex,
|
||||
QWidget *parent) :
|
||||
QWidget(parent),
|
||||
m_hostName(Gitorious::instance().hostName(hostIndex)),
|
||||
ui(new Ui::GitoriousProjectWidget),
|
||||
m_model(new QStandardItemModel(0, ColumnCount, this)),
|
||||
m_filterModel(new QSortFilterProxyModel),
|
||||
m_valid(false)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->infoToolButton->setIcon(style()->standardIcon(QStyle::SP_MessageBoxInformation));
|
||||
ui->infoToolButton->setEnabled(false);
|
||||
connect(ui->infoToolButton, SIGNAL(clicked()), this, SLOT(slotInfo()));
|
||||
// Filter
|
||||
connect(ui->filterLineEdit, SIGNAL(textChanged(QString)), m_filterModel, SLOT(setFilterFixedString(QString)));
|
||||
ui->filterClearButton->setIcon(QIcon(Core::Constants::ICON_RESET));
|
||||
connect(ui->filterClearButton, SIGNAL(clicked()), ui->filterLineEdit, SLOT(clear()));
|
||||
// Updater
|
||||
ui->updateCheckBox->setChecked(true);
|
||||
if (Gitorious::instance().hostState(hostIndex) != GitoriousHost::ProjectsQueryRunning)
|
||||
ui->updateCheckBox->setVisible(false);
|
||||
connect(ui->updateCheckBox, SIGNAL(stateChanged(int)), this, SLOT(slotUpdateCheckBoxChanged(int)));
|
||||
// Model
|
||||
QStringList headers;
|
||||
headers << tr("Project") << tr("Description");
|
||||
m_model->setHorizontalHeaderLabels(headers);
|
||||
// Populate the model
|
||||
slotUpdateProjects(hostIndex);
|
||||
// Filter on all columns
|
||||
m_filterModel->setSourceModel(m_model);
|
||||
m_filterModel->setFilterKeyColumn(-1);
|
||||
m_filterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||
m_filterModel->setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||
ui->projectTreeView->setModel(m_filterModel);
|
||||
// View
|
||||
ui->projectTreeView->setAlternatingRowColors(true);
|
||||
ui->projectTreeView->setRootIsDecorated(false);
|
||||
ui->projectTreeView->setUniformRowHeights(true);
|
||||
ui->projectTreeView->setSortingEnabled(true);
|
||||
connect(ui->projectTreeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
|
||||
this, SLOT(slotCurrentChanged(QModelIndex,QModelIndex)));
|
||||
ui->projectTreeView->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
// Select first, resize columns
|
||||
if (Gitorious::instance().projectCount(hostIndex)) {
|
||||
for (int r = 0; r < ColumnCount; r++)
|
||||
ui->projectTreeView->resizeColumnToContents(r);
|
||||
// Select first
|
||||
const QModelIndex index = m_filterModel->index(0, 0);
|
||||
ui->projectTreeView->selectionModel()->setCurrentIndex(index, QItemSelectionModel::Select|QItemSelectionModel::Current|QItemSelectionModel::Rows);
|
||||
}
|
||||
|
||||
// Continuous update
|
||||
Gitorious *gitorious = &Gitorious::instance();
|
||||
connect(gitorious, SIGNAL(projectListPageReceived(int,int)), this, SLOT(slotUpdateProjects(int)));
|
||||
connect(gitorious, SIGNAL(projectListReceived(int)), this, SLOT(slotUpdateProjects(int)));
|
||||
}
|
||||
|
||||
GitoriousProjectWidget::~GitoriousProjectWidget()
|
||||
{
|
||||
Gitorious *gitorious = &Gitorious::instance();
|
||||
disconnect(gitorious, SIGNAL(projectListPageReceived(int,int)), this, SLOT(slotUpdateProjects(int)));
|
||||
disconnect(gitorious, SIGNAL(projectListReceived(int)), this, SLOT(slotUpdateProjects(int)));
|
||||
delete ui;
|
||||
}
|
||||
|
||||
// Map indexes back via filter
|
||||
QStandardItem *GitoriousProjectWidget::itemFromIndex(const QModelIndex &index) const
|
||||
{
|
||||
if (index.isValid())
|
||||
return m_model->itemFromIndex(m_filterModel->mapToSource(index));
|
||||
return 0;
|
||||
}
|
||||
|
||||
QStandardItem *GitoriousProjectWidget::currentItem() const
|
||||
{
|
||||
return itemFromIndex(ui->projectTreeView->selectionModel()->currentIndex());
|
||||
}
|
||||
|
||||
void GitoriousProjectWidget::slotCurrentChanged(const QModelIndex ¤t, const QModelIndex & /* previous */)
|
||||
{
|
||||
// Any info URL to show?
|
||||
QString url;
|
||||
if (current.isValid())
|
||||
if (QStandardItem *item = itemFromIndex(current)) {
|
||||
// Project: URL in description?
|
||||
const QVariant urlV = item->data(urlRole);
|
||||
if (urlV.isValid())
|
||||
url = urlV.toString();
|
||||
}
|
||||
|
||||
ui->infoToolButton->setEnabled(!url.isEmpty());
|
||||
ui->infoToolButton->setToolTip(url);
|
||||
|
||||
const bool isValid = current.isValid();
|
||||
if (isValid != m_valid) {
|
||||
m_valid = isValid;
|
||||
emit validChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void GitoriousProjectWidget::slotInfo()
|
||||
{
|
||||
if (const QStandardItem *item = currentItem()) {
|
||||
const QVariant url = item->data(urlRole);
|
||||
if (url.isValid())
|
||||
QDesktopServices::openUrl(QUrl(url.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
// Create a model row for a project
|
||||
static inline QList<QStandardItem *> projectEntry(const GitoriousProject &p)
|
||||
{
|
||||
enum { maxNameLength = 30 };
|
||||
// Truncate names with colons
|
||||
QString name = p.name;
|
||||
const int colonPos = name.indexOf(QLatin1Char(':'));
|
||||
if (colonPos != -1)
|
||||
name.truncate(colonPos);
|
||||
if (name.size() > maxNameLength) {
|
||||
name.truncate(maxNameLength);
|
||||
name += QLatin1String("...");
|
||||
}
|
||||
QStandardItem *nameItem = new QStandardItem(name);
|
||||
nameItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled);
|
||||
// Description
|
||||
QStandardItem *descriptionItem = new QStandardItem;
|
||||
descriptionItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled);
|
||||
QList<QStandardItem *> rc;
|
||||
rc << nameItem << descriptionItem;
|
||||
// Should the text contain an URL, store it under 'urlRole' for the info button
|
||||
QString url;
|
||||
GitoriousProjectWidget::setDescription(p.description, DescriptionColumn, &rc, &url);
|
||||
if (!url.isEmpty()) {
|
||||
const QVariant urlV = QVariant(url);
|
||||
nameItem->setData(urlV, urlRole);
|
||||
descriptionItem->setData(urlV, urlRole);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
// Utility to set description column and tooltip for a row from a free
|
||||
// format/HTMLish gitorious description. Make sure the description is just one
|
||||
// row for the item and set a tooltip with full contents. If desired, extract
|
||||
// an URL.
|
||||
|
||||
void GitoriousProjectWidget::setDescription(const QString &description,
|
||||
int descriptionColumn,
|
||||
QList<QStandardItem *> *items,
|
||||
QString *url /* =0 */)
|
||||
{
|
||||
enum { MaxDescriptionLineLength = 70 };
|
||||
// Trim description to 1 sensibly long line for the item view
|
||||
QString descLine = description;
|
||||
const int newLinePos = descLine.indexOf(QLatin1Char('\n'));
|
||||
if (newLinePos != -1)
|
||||
descLine.truncate(newLinePos);
|
||||
if (descLine.size() > MaxDescriptionLineLength) {
|
||||
const int dotPos = descLine.lastIndexOf(QLatin1Char('.'), MaxDescriptionLineLength);
|
||||
if (dotPos != -1) {
|
||||
descLine.truncate(dotPos);
|
||||
} else {
|
||||
descLine.truncate(MaxDescriptionLineLength);
|
||||
}
|
||||
descLine += QLatin1String("...");
|
||||
}
|
||||
items->at(descriptionColumn)->setText(descLine);
|
||||
// Set a HTML tooltip to make lines wrap and the markup sprinkled within work
|
||||
const QString htmlTip = QLatin1String("<html><body>") + description + QLatin1String("</body></html>");
|
||||
const int size = items->size();
|
||||
for (int i = 0; i < size; i++)
|
||||
items->at(i)->setToolTip(htmlTip);
|
||||
if (url) {
|
||||
// Should the text contain an URL, extract
|
||||
// Do not fall for "(http://XX)", strip special characters
|
||||
static const QRegExp urlRegExp(QLatin1String("(http://[\\w\\.-]+/[a-zA-Z0-9/\\-&]*)"));
|
||||
Q_ASSERT(urlRegExp.isValid());
|
||||
if (urlRegExp.indexIn(description) != -1) {
|
||||
*url= urlRegExp.cap(1);
|
||||
} else {
|
||||
url->clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GitoriousProjectWidget::grabFocus()
|
||||
{
|
||||
ui->projectTreeView->setFocus();
|
||||
}
|
||||
|
||||
void GitoriousProjectWidget::slotUpdateCheckBoxChanged(int state)
|
||||
{
|
||||
if (state == Qt::Checked)
|
||||
slotUpdateProjects(Gitorious::instance().findByHostName(m_hostName));
|
||||
}
|
||||
|
||||
void GitoriousProjectWidget::slotUpdateProjects(int hostIndex)
|
||||
{
|
||||
if (!ui->updateCheckBox->isChecked())
|
||||
return;
|
||||
const Gitorious &gitorious = Gitorious::instance();
|
||||
// Complete list of projects
|
||||
if (m_hostName != gitorious.hostName(hostIndex))
|
||||
return;
|
||||
// Fill in missing projects
|
||||
const GitoriousHost::ProjectList &projects = gitorious.hosts().at(hostIndex).projects;
|
||||
const int size = projects.size();
|
||||
for (int i = m_model->rowCount(); i < size; i++)
|
||||
m_model->appendRow(projectEntry(*projects.at(i)));
|
||||
if (gitorious.hostState(hostIndex) == GitoriousHost::ProjectsComplete)
|
||||
ui->updateCheckBox->setVisible(false);
|
||||
}
|
||||
|
||||
bool GitoriousProjectWidget::isValid() const
|
||||
{
|
||||
return m_valid;
|
||||
}
|
||||
|
||||
int GitoriousProjectWidget::hostIndex() const
|
||||
{
|
||||
return Gitorious::instance().findByHostName(m_hostName);
|
||||
}
|
||||
|
||||
QSharedPointer<GitoriousProject> GitoriousProjectWidget::project() const
|
||||
{
|
||||
if (const QStandardItem *item = currentItem()) {
|
||||
const int projectIndex = item->row();
|
||||
return Gitorious::instance().hosts().at(hostIndex()).projects.at(projectIndex);
|
||||
}
|
||||
return QSharedPointer<GitoriousProject>(new GitoriousProject);
|
||||
}
|
||||
|
||||
void GitoriousProjectWidget::changeEvent(QEvent *e)
|
||||
{
|
||||
QWidget::changeEvent(e);
|
||||
switch (e->type()) {
|
||||
case QEvent::LanguageChange:
|
||||
ui->retranslateUi(this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Gitorious
|
||||
113
src/plugins/git/gitorious/gitoriousprojectwidget.h
Normal file
113
src/plugins/git/gitorious/gitoriousprojectwidget.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** Commercial Usage
|
||||
**
|
||||
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||
** accordance with the Qt Commercial License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Nokia.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** If you are unsure which license is appropriate for your use, please
|
||||
** contact the sales department at http://www.qtsoftware.com/contact.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef GITORIOUSPROJECTWIDGET_H
|
||||
#define GITORIOUSPROJECTWIDGET_H
|
||||
|
||||
#include <QtCore/QSharedPointer>
|
||||
#include <QtGui/QWidget>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QStandardItemModel;
|
||||
class QStandardItem;
|
||||
class QModelIndex;
|
||||
class QSortFilterProxyModel;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Gitorious {
|
||||
namespace Internal {
|
||||
|
||||
class GitoriousHostWizardPage;
|
||||
class GitoriousProject;
|
||||
|
||||
namespace Ui {
|
||||
class GitoriousProjectWidget;
|
||||
}
|
||||
|
||||
/* Let the user select a project from a host. Displays name and description
|
||||
* with tooltip and info button that opens URLs contained in the description.
|
||||
* Connects to the signals of Gitorious and updates the project list as the
|
||||
* it receives the projects. isValid() and signal validChanged are
|
||||
* provided for use in a QWizardPage. Host matching happens via name as the
|
||||
* hostIndex might change due to deleting hosts. */
|
||||
class GitoriousProjectWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit GitoriousProjectWidget(int hostIndex,
|
||||
QWidget *parent = 0);
|
||||
~GitoriousProjectWidget();
|
||||
|
||||
virtual bool isValid() const;
|
||||
|
||||
QSharedPointer<GitoriousProject> project() const;
|
||||
|
||||
QString hostName() const { return m_hostName; }
|
||||
int hostIndex() const;
|
||||
|
||||
// Utility to set description column and tooltip for a row from a free
|
||||
// format/HTMLish gitorious description. Make sure the description is
|
||||
// just one row for the item and set a tooltip with full contents.
|
||||
// If desired, extract an URL.
|
||||
static void setDescription(const QString &description,
|
||||
int descriptionColumn,
|
||||
QList<QStandardItem *> *items,
|
||||
QString *url = 0);
|
||||
|
||||
signals:
|
||||
void validChanged();
|
||||
|
||||
public slots:
|
||||
void grabFocus();
|
||||
|
||||
private slots:
|
||||
void slotCurrentChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
||||
void slotInfo();
|
||||
void slotUpdateProjects(int hostIndex);
|
||||
void slotUpdateCheckBoxChanged(int);
|
||||
|
||||
protected:
|
||||
void changeEvent(QEvent *e);
|
||||
|
||||
private:
|
||||
QStandardItem *itemFromIndex(const QModelIndex &idx) const;
|
||||
QStandardItem *currentItem() const;
|
||||
|
||||
const QString m_hostName;
|
||||
|
||||
Ui::GitoriousProjectWidget *ui;
|
||||
const GitoriousHostWizardPage *m_hostPage;
|
||||
QStandardItemModel *m_model;
|
||||
QSortFilterProxyModel *m_filterModel;
|
||||
bool m_valid;
|
||||
};
|
||||
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Gitorious
|
||||
#endif // GITORIOUSPROJECTWIDGET_H
|
||||
76
src/plugins/git/gitorious/gitoriousprojectwidget.ui
Normal file
76
src/plugins/git/gitorious/gitoriousprojectwidget.ui
Normal file
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Gitorious::Internal::GitoriousProjectWidget</class>
|
||||
<widget class="QWidget" name="Gitorious::Internal::GitoriousProjectWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>WizardPage</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="filterLabel">
|
||||
<property name="text">
|
||||
<string>Filter:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="filterLineEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="filterClearButton">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QTreeView" name="projectTreeView"/>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QToolButton" name="infoToolButton">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="buttonVerticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="updateCheckBox">
|
||||
<property name="text">
|
||||
<string>Keep updating</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
133
src/plugins/git/gitorious/gitoriousprojectwizardpage.cpp
Normal file
133
src/plugins/git/gitorious/gitoriousprojectwizardpage.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** Commercial Usage
|
||||
**
|
||||
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||
** accordance with the Qt Commercial License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Nokia.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** If you are unsure which license is appropriate for your use, please
|
||||
** contact the sales department at http://www.qtsoftware.com/contact.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "gitoriousprojectwizardpage.h"
|
||||
#include "gitoriousprojectwidget.h"
|
||||
#include "gitorioushostwizardpage.h"
|
||||
#include "gitorious.h"
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QtGui/QStackedWidget>
|
||||
#include <QtGui/QVBoxLayout>
|
||||
|
||||
namespace Gitorious {
|
||||
namespace Internal {
|
||||
|
||||
GitoriousProjectWizardPage::GitoriousProjectWizardPage(const GitoriousHostWizardPage *hostPage,
|
||||
QWidget *parent) :
|
||||
QWizardPage(parent),
|
||||
m_hostPage(hostPage),
|
||||
m_stackedWidget(new QStackedWidget),
|
||||
m_isValid(false)
|
||||
{
|
||||
QVBoxLayout *lt = new QVBoxLayout;
|
||||
lt->addWidget(m_stackedWidget);
|
||||
setLayout(lt);
|
||||
}
|
||||
|
||||
static inline QString msgChooseProject(const QString &h)
|
||||
{
|
||||
return GitoriousProjectWizardPage::tr("Choose a project from '%1'").arg((h));
|
||||
}
|
||||
|
||||
QString GitoriousProjectWizardPage::selectedHostName() const
|
||||
{
|
||||
if (const GitoriousProjectWidget *w = currentProjectWidget())
|
||||
return w->hostName();
|
||||
return QString();
|
||||
}
|
||||
|
||||
void GitoriousProjectWizardPage::initializePage()
|
||||
{
|
||||
// Try to find the page by hostindex
|
||||
const int hostIndex = m_hostPage->selectedHostIndex();
|
||||
const int existingStackIndex = hostIndexToStackIndex(hostIndex);
|
||||
// Found? - pop up that page
|
||||
if (existingStackIndex != -1) {
|
||||
m_stackedWidget->setCurrentIndex(existingStackIndex);
|
||||
setSubTitle(msgChooseProject(selectedHostName()));
|
||||
return;
|
||||
}
|
||||
// Add a new page
|
||||
GitoriousProjectWidget *widget = new GitoriousProjectWidget(hostIndex);
|
||||
connect(widget, SIGNAL(validChanged()), this, SLOT(slotCheckValid()));
|
||||
m_stackedWidget->addWidget(widget);
|
||||
m_stackedWidget->setCurrentIndex(m_stackedWidget->count() - 1);
|
||||
setSubTitle(msgChooseProject(widget->hostName()));
|
||||
slotCheckValid();
|
||||
}
|
||||
|
||||
bool GitoriousProjectWizardPage::isComplete() const
|
||||
{
|
||||
return m_isValid;
|
||||
}
|
||||
|
||||
void GitoriousProjectWizardPage::slotCheckValid()
|
||||
{
|
||||
const GitoriousProjectWidget *w = currentProjectWidget();
|
||||
const bool isValid = w ? w->isValid() : false;
|
||||
if (isValid != m_isValid) {
|
||||
m_isValid = isValid;
|
||||
emit completeChanged();
|
||||
}
|
||||
}
|
||||
|
||||
QSharedPointer<GitoriousProject> GitoriousProjectWizardPage::project() const
|
||||
{
|
||||
if (const GitoriousProjectWidget *w = currentProjectWidget())
|
||||
return w->project();
|
||||
return QSharedPointer<GitoriousProject>();
|
||||
}
|
||||
|
||||
GitoriousProjectWidget *GitoriousProjectWizardPage::projectWidgetAt(int index) const
|
||||
{
|
||||
return qobject_cast<GitoriousProjectWidget *>(m_stackedWidget->widget(index));
|
||||
}
|
||||
|
||||
GitoriousProjectWidget *GitoriousProjectWizardPage::currentProjectWidget() const
|
||||
{
|
||||
const int index = m_stackedWidget->currentIndex();
|
||||
if (index < 0)
|
||||
return 0;
|
||||
return projectWidgetAt(index);
|
||||
}
|
||||
|
||||
// Convert a host index to a stack index.
|
||||
int GitoriousProjectWizardPage::hostIndexToStackIndex(int hostIndex) const
|
||||
{
|
||||
const int count = m_stackedWidget->count();
|
||||
for(int i = 0; i < count; i++)
|
||||
if (projectWidgetAt(i)->hostIndex() == hostIndex)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Gitorious
|
||||
87
src/plugins/git/gitorious/gitoriousprojectwizardpage.h
Normal file
87
src/plugins/git/gitorious/gitoriousprojectwizardpage.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** Commercial Usage
|
||||
**
|
||||
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||
** accordance with the Qt Commercial License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Nokia.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** If you are unsure which license is appropriate for your use, please
|
||||
** contact the sales department at http://www.qtsoftware.com/contact.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef GITORIOUSPROJECTWIZARDPAGE_H
|
||||
#define GITORIOUSPROJECTWIZARDPAGE_H
|
||||
|
||||
#include <QtCore/QSharedPointer>
|
||||
#include <QtGui/QWizardPage>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QStackedWidget;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Gitorious {
|
||||
namespace Internal {
|
||||
|
||||
class GitoriousHostWizardPage;
|
||||
class GitoriousProject;
|
||||
class GitoriousProjectWidget;
|
||||
|
||||
namespace Ui {
|
||||
class GitoriousProjectWizardPage;
|
||||
}
|
||||
|
||||
/* GitoriousProjectWizardPage: Let the user select a project via
|
||||
* GitoriousProjectWidget. As switching back and forth hosts (repopulating
|
||||
* the sorting projects model/treeviews) might get slow when the host has
|
||||
* lots of projects, it manages a stack of project widgets and activates
|
||||
* the one selected in the host page (or creates a new one) in
|
||||
* initializePage. */
|
||||
|
||||
class GitoriousProjectWizardPage : public QWizardPage {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit GitoriousProjectWizardPage(const GitoriousHostWizardPage *hostPage,
|
||||
QWidget *parent = 0);
|
||||
|
||||
virtual void initializePage();
|
||||
virtual bool isComplete() const;
|
||||
|
||||
QSharedPointer<GitoriousProject> project() const;
|
||||
int selectedHostIndex() const;
|
||||
QString selectedHostName() const;
|
||||
|
||||
private slots:
|
||||
void slotCheckValid();
|
||||
|
||||
private:
|
||||
GitoriousProjectWidget *projectWidgetAt(int index) const;
|
||||
GitoriousProjectWidget *currentProjectWidget() const;
|
||||
int hostIndexToStackIndex(int hostIndex) const;
|
||||
|
||||
const GitoriousHostWizardPage *m_hostPage;
|
||||
QStackedWidget *m_stackedWidget;
|
||||
bool m_isValid;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Gitorious
|
||||
#endif // GITORIOUSPROJECTWIZARDPAGE_H
|
||||
211
src/plugins/git/gitorious/gitoriousrepositorywizardpage.cpp
Normal file
211
src/plugins/git/gitorious/gitoriousrepositorywizardpage.cpp
Normal file
@@ -0,0 +1,211 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** Commercial Usage
|
||||
**
|
||||
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||
** accordance with the Qt Commercial License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Nokia.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** If you are unsure which license is appropriate for your use, please
|
||||
** contact the sales department at http://www.qtsoftware.com/contact.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "gitoriousrepositorywizardpage.h"
|
||||
#include "gitoriousprojectwizardpage.h"
|
||||
#include "gitoriousprojectwidget.h"
|
||||
#include "gitorious.h"
|
||||
#include "ui_gitoriousrepositorywizardpage.h"
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#include <QtGui/QStandardItemModel>
|
||||
#include <QtGui/QStandardItem>
|
||||
#include <QtGui/QItemSelectionModel>
|
||||
|
||||
enum { TypeRole = Qt::UserRole + 1};
|
||||
enum { HeaderType, RepositoryType };
|
||||
|
||||
enum { debug = 0 };
|
||||
|
||||
namespace Gitorious {
|
||||
namespace Internal {
|
||||
|
||||
enum { RepositoryColumn, OwnerColumn, DescriptionColumn, ColumnCount };
|
||||
|
||||
GitoriousRepositoryWizardPage::GitoriousRepositoryWizardPage(const GitoriousProjectWizardPage *projectPage,
|
||||
QWidget *parent) :
|
||||
QWizardPage(parent),
|
||||
ui(new Ui::GitoriousRepositoryWizardPage),
|
||||
m_projectPage(projectPage),
|
||||
m_model(new QStandardItemModel(0, ColumnCount)),
|
||||
m_valid(false)
|
||||
{
|
||||
QStringList headers;
|
||||
headers << tr("Name") << tr("Owner") << tr("Description");
|
||||
m_model->setHorizontalHeaderLabels(headers);
|
||||
|
||||
ui->setupUi(this);
|
||||
ui->repositoryTreeView->setModel(m_model);
|
||||
ui->repositoryTreeView->setUniformRowHeights(true);
|
||||
ui->repositoryTreeView->setAlternatingRowColors(true);
|
||||
ui->repositoryTreeView->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
connect(ui->repositoryTreeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
|
||||
this, SLOT(slotCurrentChanged(QModelIndex,QModelIndex)));
|
||||
}
|
||||
|
||||
GitoriousRepositoryWizardPage::~GitoriousRepositoryWizardPage()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
bool gitRepoLessThanByType(const GitoriousRepository &r1, const GitoriousRepository &r2)
|
||||
{
|
||||
return r1.type < r2.type;
|
||||
}
|
||||
|
||||
static inline QList<QStandardItem *> headerEntry(const QString &h)
|
||||
{
|
||||
QStandardItem *nameItem = new QStandardItem(h);
|
||||
nameItem->setFlags(Qt::ItemIsEnabled);
|
||||
nameItem->setData(QVariant(HeaderType), TypeRole);
|
||||
QStandardItem *ownerItem = new QStandardItem;
|
||||
ownerItem->setFlags(Qt::ItemIsEnabled);
|
||||
ownerItem->setData(QVariant(HeaderType), TypeRole);
|
||||
QStandardItem *descriptionItem = new QStandardItem;
|
||||
descriptionItem->setFlags(Qt::ItemIsEnabled);
|
||||
descriptionItem->setData(QVariant(HeaderType), TypeRole);
|
||||
QList<QStandardItem *> rc;
|
||||
rc << nameItem << ownerItem << descriptionItem;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline QList<QStandardItem *> repositoryEntry(const GitoriousRepository &r)
|
||||
{
|
||||
QStandardItem *nameItem = new QStandardItem(r.name);
|
||||
nameItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled);
|
||||
nameItem->setData(QVariant(RepositoryType), TypeRole);
|
||||
QStandardItem *ownerItem = new QStandardItem(r.owner);
|
||||
ownerItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled);
|
||||
ownerItem->setData(QVariant(RepositoryType), TypeRole);
|
||||
QStandardItem *descriptionItem = new QStandardItem;
|
||||
descriptionItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled);
|
||||
descriptionItem->setData(QVariant(RepositoryType), TypeRole);
|
||||
QList<QStandardItem *> rc;
|
||||
rc << nameItem << ownerItem << descriptionItem;
|
||||
GitoriousProjectWidget::setDescription(r.description, DescriptionColumn, &rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
void GitoriousRepositoryWizardPage::initializePage()
|
||||
{
|
||||
// Populate the model
|
||||
ui->repositoryTreeView->selectionModel()->clearSelection();
|
||||
if (const int oldRowCount = m_model->rowCount())
|
||||
m_model->removeRows(0, oldRowCount);
|
||||
// fill model
|
||||
const QSharedPointer<GitoriousProject> proj = m_projectPage->project();
|
||||
setSubTitle(tr("Choose a repository of the project '%1'.").arg(proj->name));
|
||||
// Create a hierarchical list by repository type, sort by type
|
||||
QList<GitoriousRepository> repositories = proj->repositories;
|
||||
QStandardItem *firstEntry = 0;
|
||||
if (!repositories.empty()) {
|
||||
int lastRepoType = -1;
|
||||
QStandardItem *header = 0;
|
||||
qStableSort(repositories.begin(), repositories.end(), gitRepoLessThanByType);
|
||||
const QString types[GitoriousRepository::PersonalRepository + 1] =
|
||||
{ tr("Mainline Repositories"), tr("Clones"), tr("Baseline Repositories"), tr("Shared Project Repositories"), tr("Personal Repositories") };
|
||||
foreach(const GitoriousRepository &r, repositories) {
|
||||
// New Header?
|
||||
if (r.type != lastRepoType || !header) {
|
||||
lastRepoType = r.type;
|
||||
const QList<QStandardItem *> headerRow = headerEntry(types[r.type]);
|
||||
m_model->appendRow(headerRow);
|
||||
header = headerRow.front();
|
||||
}
|
||||
// Repository row
|
||||
const QList<QStandardItem *> row = repositoryEntry(r);
|
||||
header->appendRow(row);
|
||||
if (!firstEntry)
|
||||
firstEntry = row.front();
|
||||
}
|
||||
}
|
||||
ui->repositoryTreeView->expandAll();
|
||||
for (int r = 0; r < ColumnCount; r++)
|
||||
ui->repositoryTreeView->resizeColumnToContents(r);
|
||||
// Select first
|
||||
if (firstEntry) {
|
||||
const QModelIndex idx = m_model->indexFromItem(firstEntry);
|
||||
ui->repositoryTreeView->selectionModel()->setCurrentIndex(idx, QItemSelectionModel::Select|QItemSelectionModel::Current|QItemSelectionModel::Rows);
|
||||
}
|
||||
}
|
||||
|
||||
void GitoriousRepositoryWizardPage::slotCurrentChanged(const QModelIndex ¤t, const QModelIndex & /*previous */)
|
||||
{
|
||||
const QStandardItem *item = current.isValid() ? m_model->itemFromIndex(current) : static_cast<const QStandardItem *>(0);
|
||||
const bool isValid = item && item->data(TypeRole).toInt() == RepositoryType;
|
||||
if (isValid != m_valid) {
|
||||
m_valid = isValid;
|
||||
emit completeChanged();
|
||||
}
|
||||
}
|
||||
|
||||
QString GitoriousRepositoryWizardPage::repositoryName() const
|
||||
{
|
||||
const QModelIndex idx = ui->repositoryTreeView->selectionModel()->currentIndex();
|
||||
if (idx.isValid()) {
|
||||
const QModelIndex sibling0 = idx.column() ? idx.sibling(idx.row(), 0) : idx;
|
||||
if (const QStandardItem *item = m_model->itemFromIndex(sibling0))
|
||||
if (item->data(TypeRole).toInt() == RepositoryType)
|
||||
return item->text();
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
QUrl GitoriousRepositoryWizardPage::repositoryURL() const
|
||||
{
|
||||
// Find by name (as we sorted the the repositories)
|
||||
const QString repoName = repositoryName();
|
||||
foreach (const GitoriousRepository &r, m_projectPage->project()->repositories)
|
||||
if (r.name == repoName)
|
||||
return r.cloneUrl;
|
||||
return QUrl();
|
||||
}
|
||||
|
||||
bool GitoriousRepositoryWizardPage::isComplete() const
|
||||
{
|
||||
return m_valid;
|
||||
}
|
||||
|
||||
void GitoriousRepositoryWizardPage::changeEvent(QEvent *e)
|
||||
{
|
||||
QWizardPage::changeEvent(e);
|
||||
switch (e->type()) {
|
||||
case QEvent::LanguageChange:
|
||||
ui->retranslateUi(this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Gitorious
|
||||
80
src/plugins/git/gitorious/gitoriousrepositorywizardpage.h
Normal file
80
src/plugins/git/gitorious/gitoriousrepositorywizardpage.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** Commercial Usage
|
||||
**
|
||||
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||
** accordance with the Qt Commercial License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Nokia.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** If you are unsure which license is appropriate for your use, please
|
||||
** contact the sales department at http://www.qtsoftware.com/contact.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef GITORIOUSREPOSITORYWIZARDPAGE_H
|
||||
#define GITORIOUSREPOSITORYWIZARDPAGE_H
|
||||
|
||||
#include <QtGui/QWizardPage>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QStandardItemModel;
|
||||
class QStandardItem;
|
||||
class QModelIndex;
|
||||
class QUrl;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Gitorious {
|
||||
namespace Internal {
|
||||
|
||||
class GitoriousProjectWizardPage;
|
||||
|
||||
namespace Ui {
|
||||
class GitoriousRepositoryWizardPage;
|
||||
}
|
||||
|
||||
// A wizard page listing Gitorious repositories in a tree, by repository type.
|
||||
|
||||
class GitoriousRepositoryWizardPage : public QWizardPage {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit GitoriousRepositoryWizardPage(const GitoriousProjectWizardPage *projectPage,
|
||||
QWidget *parent = 0);
|
||||
~GitoriousRepositoryWizardPage();
|
||||
|
||||
virtual void initializePage();
|
||||
virtual bool isComplete() const;
|
||||
|
||||
QString repositoryName() const;
|
||||
QUrl repositoryURL() const;
|
||||
|
||||
public slots:
|
||||
void slotCurrentChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
||||
|
||||
protected:
|
||||
void changeEvent(QEvent *e);
|
||||
|
||||
Ui::GitoriousRepositoryWizardPage *ui;
|
||||
const GitoriousProjectWizardPage *m_projectPage;
|
||||
QStandardItemModel *m_model;
|
||||
bool m_valid;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Gitorious
|
||||
#endif // GITORIOUSREPOSITORYWIZARDPAGE_H
|
||||
24
src/plugins/git/gitorious/gitoriousrepositorywizardpage.ui
Normal file
24
src/plugins/git/gitorious/gitoriousrepositorywizardpage.ui
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Gitorious::Internal::GitoriousRepositoryWizardPage</class>
|
||||
<widget class="QWizardPage" name="Gitorious::Internal::GitoriousRepositoryWizardPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>WizardPage</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTreeView" name="repositoryTreeView"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "gitversioncontrol.h"
|
||||
#include "branchdialog.h"
|
||||
#include "clonewizard.h"
|
||||
#include "gitoriousclonewizard.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/coreconstants.h>
|
||||
@@ -216,6 +217,7 @@ bool GitPlugin::initialize(const QStringList &arguments, QString *errorMessage)
|
||||
addAutoReleasedObject(versionControl);
|
||||
|
||||
addAutoReleasedObject(new CloneWizard);
|
||||
addAutoReleasedObject(new Gitorious::Internal::GitoriousCloneWizard);
|
||||
|
||||
//register actions
|
||||
Core::ActionManager *actionManager = m_core->actionManager();
|
||||
|
||||
@@ -63,6 +63,16 @@ void BaseCheckoutWizardPage::setRepositoryLabel(const QString &l)
|
||||
d->ui.repositoryLabel->setText(l);
|
||||
}
|
||||
|
||||
bool BaseCheckoutWizardPage::isRepositoryReadOnly() const
|
||||
{
|
||||
return d->ui.repositoryLineEdit->isReadOnly();
|
||||
}
|
||||
|
||||
void BaseCheckoutWizardPage::setRepositoryReadOnly(bool v)
|
||||
{
|
||||
d->ui.repositoryLineEdit->setReadOnly(v);
|
||||
}
|
||||
|
||||
QString BaseCheckoutWizardPage::path() const
|
||||
{
|
||||
return d->ui.pathChooser->path();
|
||||
|
||||
@@ -62,6 +62,9 @@ public:
|
||||
QString repository() const;
|
||||
void setRepository(const QString &r);
|
||||
|
||||
bool isRepositoryReadOnly() const;
|
||||
void setRepositoryReadOnly(bool v);
|
||||
|
||||
virtual bool isComplete() const;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -44,19 +44,6 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
|
||||
Reference in New Issue
Block a user