Git: Remove gitorious code

Gitorious has changed their APIs a while ago and nobody seems to have
noticed. The only bug report I got was from Christian who tests Creator
regularly. So the code seems to be unused, which I find not surprising
considering the limited popularity of gitorious nowadays.

Task-number: QTCREATORBUG-12858
Change-Id: Id92747fd146434ad737315320fa08afd96223a7e
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
Reviewed-by: Christian Stenger <christian.stenger@digia.com>
This commit is contained in:
Tobias Hunger
2014-09-23 12:27:40 +02:00
parent 560e9e15eb
commit 30955a9058
23 changed files with 0 additions and 2672 deletions

View File

@@ -60,8 +60,6 @@ FORMS += changeselectiondialog.ui \
branchadddialog.ui \ branchadddialog.ui \
branchcheckoutdialog.ui branchcheckoutdialog.ui
include(gitorious/gitorious.pri)
RESOURCES += \ RESOURCES += \
git.qrc git.qrc

View File

@@ -75,30 +75,6 @@ QtcPlugin {
"stashdialog.ui", "stashdialog.ui",
] ]
Group {
name: "Gitorious"
prefix: "gitorious/"
files: [
"gitorious.cpp",
"gitorious.h",
"gitoriousclonewizard.cpp",
"gitoriousclonewizard.h",
"gitorioushostwidget.cpp",
"gitorioushostwidget.h",
"gitorioushostwidget.ui",
"gitorioushostwizardpage.cpp",
"gitorioushostwizardpage.h",
"gitoriousprojectwidget.cpp",
"gitoriousprojectwidget.h",
"gitoriousprojectwidget.ui",
"gitoriousprojectwizardpage.cpp",
"gitoriousprojectwizardpage.h",
"gitoriousrepositorywizardpage.cpp",
"gitoriousrepositorywizardpage.h",
"gitoriousrepositorywizardpage.ui",
]
}
Group { Group {
name: "Gerrit" name: "Gerrit"
prefix: "gerrit/" prefix: "gerrit/"

View File

@@ -1,7 +1,6 @@
<RCC> <RCC>
<qresource prefix="/git"> <qresource prefix="/git">
<file>images/git.png</file> <file>images/git.png</file>
<file>images/gitorious.png</file>
<file>images/arrowup.png</file> <file>images/arrowup.png</file>
<file>Git.mimetypes.xml</file> <file>Git.mimetypes.xml</file>
</qresource> </qresource>

View File

@@ -1,594 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "gitorious.h"
#include <QDebug>
#include <QXmlStreamReader>
#include <QSettings>
#include <QNetworkReply>
#include <QUrlQuery>
#include <utils/qtcassert.h>
#include <utils/networkaccessmanager.h>
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 http request
static inline QUrl httpRequest(const QString &host, const QString &request)
{
QUrl url;
url.setScheme(QLatin1String("http"));
const QStringList hostList = host.split(QLatin1Char(':'), QString::SkipEmptyParts);
if (hostList.size() > 0)
{
url.setHost(hostList.at(0));
if (hostList.size() > 1)
url.setPort(hostList.at(1).toInt());
}
url.setPath(QLatin1Char('/') + request);
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() == QLatin1String("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
// QtProject 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)
{
QTC_ASSERT(reader.isStartElement(), return);
while (!reader.atEnd()) {
reader.readNext();
if (reader.isEndElement())
break;
if (reader.isStartElement())
readUnknownElement(reader);
}
}
// --- Gitorious
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>"));
QTC_CHECK(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)
{
QNetworkReply *reply = Utils::NetworkAccessManager::instance()->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":
const QUrl url = httpRequest(hostName(index), QLatin1String("projects"));
createRequest(url, ListCategoriesProtocol, index);
}
void Gitorious::updateProjectList(int hostIndex)
{
startProjectsRequest(hostIndex);
}
void Gitorious::startProjectsRequest(int hostIndex, int page)
{
QUrl url = httpRequest(hostName(hostIndex), QLatin1String("projects"));
QUrlQuery query;
query.addQueryItem(QLatin1String("format"), QLatin1String("xml"));
if (page >= 0)
query.addQueryItem(QLatin1String("page"), QString::number(page));
url.setQuery(query);
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

View File

@@ -1,174 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef GITORIOUS_H
#define GITORIOUS_H
#include <QStringList>
#include <QSharedPointer>
#include <QUrl>
#include <QObject>
QT_BEGIN_NAMESPACE
class QNetworkReply;
class QDebug;
class QUrl;
class QSettings;
QT_END_NAMESPACE
namespace Gitorious {
namespace Internal {
struct GitoriousRepository
{
enum Type {
MainLineRepository,
CloneRepository,
BaselineRepository, // QtProject extension
SharedRepository, // QtProject extension
PersonalRepository // QtProject 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_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;
};
} // namespace Internal
} // namespace Gitorious
#endif // GITORIOUS_H

View File

@@ -1,21 +0,0 @@
QT += network
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

View File

@@ -1,109 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "gitoriousclonewizard.h"
#include "gitorioushostwizardpage.h"
#include "gitoriousprojectwizardpage.h"
#include "gitoriousrepositorywizardpage.h"
#include "../clonewizardpage.h"
#include "../gitplugin.h"
#include <coreplugin/iversioncontrol.h>
#include <vcsbase/vcsbaseconstants.h>
#include <vcsbase/vcsconfigurationpage.h>
#include <utils/qtcassert.h>
#include <QUrl>
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);
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(const Utils::FileName &path, QWidget *parent) :
VcsBase::BaseCheckoutWizard(path, parent)
{
setTitle(tr("Cloning"));
setStartedStatus(tr("Cloning started..."));
const Core::IVersionControl *vc = Git::Internal::GitPlugin::instance()->versionControl();
if (!vc->isConfigured())
addPage(new VcsBase::VcsConfigurationPage(vc));
GitoriousHostWizardPage *hostPage = new GitoriousHostWizardPage;
GitoriousProjectWizardPage *projectPage = new GitoriousProjectWizardPage(hostPage);
GitoriousRepositoryWizardPage *repoPage = new GitoriousRepositoryWizardPage(projectPage);
GitoriousCloneWizardPage *clonePage = new GitoriousCloneWizardPage(repoPage);
clonePage->setPath(path.toString());
addPage(hostPage);
addPage(projectPage);
addPage(repoPage);
addPage(clonePage);
}
VcsBase::VcsCommand *GitoriousCloneWizard::createCommand(Utils::FileName *checkoutDir)
{
const Git::CloneWizardPage *cwp = 0;
foreach (int pageId, pageIds()) {
if ((cwp = qobject_cast<const Git::CloneWizardPage *>(page(pageId))))
break;
}
QTC_ASSERT(cwp, return 0);
return cwp->createCheckoutJob(checkoutDir);
}
} // namespace Internal
} // namespace Gitorius

View File

@@ -1,57 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef GITORIOUSCLONEWIZARD_H
#define GITORIOUSCLONEWIZARD_H
#include <vcsbase/basecheckoutwizardfactory.h>
#include <vcsbase/basecheckoutwizard.h>
namespace Gitorious {
namespace Internal {
// GitoriousCloneWizard: A wizard allowing for browsing
// Gitorious-hosted projects.
class GitoriousCloneWizard : public VcsBase::BaseCheckoutWizard
{
Q_OBJECT
public:
GitoriousCloneWizard(const Utils::FileName &path, QWidget *parent = 0);
protected:
VcsBase::VcsCommand *createCommand(Utils::FileName *checkoutDir);
};
} // namespace Internal
} // namespace Gitorious
#endif // GITORIOUSCLONEWIZARD_H

View File

@@ -1,304 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "gitorioushostwidget.h"
#include "gitorious.h"
#include "ui_gitorioushostwidget.h"
#include <coreplugin/coreconstants.h>
#include <QUrl>
#include <QDebug>
#include <QTimer>
#include <QStandardItem>
#include <QStandardItemModel>
#include <QItemSelectionModel>
#include <QDesktopServices>
#include <QIcon>
#include <QStyle>
enum { debug = 0 };
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::fromLatin1("...");
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(QLatin1String(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
m_model->appendRow(hostEntry(m_newHost, 0, QString(), true));
}
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());
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 &current, 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();
}
} // namespace Internal
} // namespace Gitorious

View File

@@ -1,100 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef GITORIOUSHOSTWIDGET_H
#define GITORIOUSHOSTWIDGET_H
#include <QWizardPage>
#include <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);
private slots:
void slotBrowse();
void slotDelete();
void slotCurrentChanged(const QModelIndex &current, 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 &current);
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

View File

@@ -1,63 +0,0 @@
<?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>

View File

@@ -1,101 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "gitorioushostwizardpage.h"
#include "gitorioushostwidget.h"
#include "gitorious.h"
#include <coreplugin/icore.h>
#include <QSettings>
#include <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::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);
setTitle(tr("Host"));
setSubTitle(tr("Select a host."));
}
GitoriousHostWizardPage::~GitoriousHostWizardPage()
{
// Write out settings + selected row.
QSettings *settings = Core::ICore::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

View File

@@ -1,58 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef GITORIOUSHOSTWIZARDPAGE_H
#define GITORIOUSHOSTWIZARDPAGE_H
#include <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);
~GitoriousHostWizardPage();
bool isComplete() const;
int selectedHostIndex() const;
private:
GitoriousHostWidget *m_widget;
};
} // namespace Internal
} // namespace Gitorious
#endif // GITORIOUSHOSTWIZARDPAGE_H

View File

@@ -1,288 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "gitoriousprojectwidget.h"
#include "gitorious.h"
#include "ui_gitoriousprojectwidget.h"
#include <utils/qtcassert.h>
#include <QRegExp>
#include <QDebug>
#include <QStandardItemModel>
#include <QSortFilterProxyModel>
#include <QStandardItem>
#include <QItemSelectionModel>
#include <QDesktopServices>
#include <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(filterChanged(QString)), m_filterModel, SLOT(setFilterFixedString(QString)));
// 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 &current, 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 QRegExp urlRegExp(QLatin1String("(http://[\\w\\.-]+/[a-zA-Z0-9/\\-&]*)"));
QTC_CHECK(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);
}
} // namespace Internal
} // namespace Gitorious

View File

@@ -1,110 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef GITORIOUSPROJECTWIDGET_H
#define GITORIOUSPROJECTWIDGET_H
#include <QSharedPointer>
#include <QWidget>
QT_BEGIN_NAMESPACE
class QStandardItemModel;
class QStandardItem;
class QModelIndex;
class QSortFilterProxyModel;
QT_END_NAMESPACE
namespace Gitorious {
namespace Internal {
class GitoriousHostWizardPage;
struct 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();
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 &current, const QModelIndex &previous);
void slotInfo();
void slotUpdateProjects(int hostIndex);
void slotUpdateCheckBoxChanged(int);
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

View File

@@ -1,65 +0,0 @@
<?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="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>
<item row="0" column="0">
<widget class="Utils::FancyLineEdit" name="filterLineEdit"/>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Utils::FancyLineEdit</class>
<extends>QLineEdit</extends>
<header location="global">utils/fancylineedit.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@@ -1,133 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "gitoriousprojectwizardpage.h"
#include "gitoriousprojectwidget.h"
#include "gitorioushostwizardpage.h"
#include "gitorious.h"
#include <QStackedWidget>
#include <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);
setTitle(tr("Project"));
}
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 QString hostName = Gitorious::instance().hostName(hostIndex);
const int existingStackIndex = stackIndexOf(hostName);
// Found? - pop up that page
if (existingStackIndex != -1) {
m_stackedWidget->setCurrentIndex(existingStackIndex);
setSubTitle(msgChooseProject(hostName));
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 name to a stack index.
int GitoriousProjectWizardPage::stackIndexOf(const QString &hostName) const
{
const int count = m_stackedWidget->count();
for (int i = 0; i < count; i++)
if (projectWidgetAt(i)->hostName() == hostName)
return i;
return -1;
}
} // namespace Internal
} // namespace Gitorious

View File

@@ -1,85 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef GITORIOUSPROJECTWIZARDPAGE_H
#define GITORIOUSPROJECTWIZARDPAGE_H
#include <QSharedPointer>
#include <QWizardPage>
QT_BEGIN_NAMESPACE
class QStackedWidget;
QT_END_NAMESPACE
namespace Gitorious {
namespace Internal {
class GitoriousHostWizardPage;
struct 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);
void initializePage();
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 stackIndexOf(const QString &hostName) const;
const GitoriousHostWizardPage *m_hostPage;
QStackedWidget *m_stackedWidget;
bool m_isValid;
};
} // namespace Internal
} // namespace Gitorious
#endif // GITORIOUSPROJECTWIZARDPAGE_H

View File

@@ -1,244 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "gitoriousrepositorywizardpage.h"
#include "gitoriousprojectwizardpage.h"
#include "gitoriousprojectwidget.h"
#include "gitorious.h"
#include "ui_gitoriousrepositorywizardpage.h"
#include <QDebug>
#include <QStandardItemModel>
#include <QStandardItem>
#include <QItemSelectionModel>
#include <QSortFilterProxyModel>
enum { TypeRole = Qt::UserRole + 1};
enum { HeaderType, RepositoryType };
enum { debug = 0 };
namespace Gitorious {
namespace Internal {
// A filter model that returns true for the parent (category) nodes
// (which by default do not match the search string and are thus collapsed).
class RepositoryFilterModel : public QSortFilterProxyModel {
public:
explicit RepositoryFilterModel(QObject *parent = 0) : QSortFilterProxyModel(parent) {}
protected:
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
};
bool RepositoryFilterModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
if (!source_parent.isValid())
return true; // Always true for parents.
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
}
// ----------- GitoriousRepositoryWizardPage
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_filterModel(new RepositoryFilterModel),
m_valid(false)
{
QStringList headers;
headers << tr("Name") << tr("Owner") << tr("Description");
m_model->setHorizontalHeaderLabels(headers);
// Filter on all columns
m_filterModel->setSourceModel(m_model);
m_filterModel->setFilterKeyColumn(-1);
m_filterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
m_filterModel->setSortCaseSensitivity(Qt::CaseInsensitive);
ui->setupUi(this);
// Filter
connect(ui->filterLineEdit, SIGNAL(filterChanged(QString)), m_filterModel, SLOT(setFilterFixedString(QString)));
// Tree view
ui->repositoryTreeView->setModel(m_filterModel);
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)));
setTitle(tr("Repository"));
}
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);
ui->filterLineEdit->clear();
// 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 filterIndex = m_filterModel->mapFromSource(m_model->indexFromItem(firstEntry));
ui->repositoryTreeView->selectionModel()->setCurrentIndex(filterIndex,
QItemSelectionModel::Select
| QItemSelectionModel::Current
| QItemSelectionModel::Rows);
}
ui->repositoryTreeView->setFocus();
}
QStandardItem *GitoriousRepositoryWizardPage::currentItem0() const
{
return item0FromIndex(ui->repositoryTreeView->selectionModel()->currentIndex());
}
QStandardItem *GitoriousRepositoryWizardPage::item0FromIndex(const QModelIndex &filterIndex) const
{
if (filterIndex.isValid()) {
const QModelIndex sourceIndex = m_filterModel->mapToSource(filterIndex);
if (sourceIndex.column() == 0)
return m_model->itemFromIndex(sourceIndex);
const QModelIndex sibling0 = sourceIndex.sibling(sourceIndex.row(), 0);
return m_model->itemFromIndex(sibling0);
}
return 0;
}
void GitoriousRepositoryWizardPage::slotCurrentChanged(const QModelIndex &current, const QModelIndex & /*previous */)
{
const QStandardItem *item = item0FromIndex(current);
const bool isValid = item && item->data(TypeRole).toInt() == RepositoryType;
if (isValid != m_valid) {
m_valid = isValid;
emit completeChanged();
}
}
QString GitoriousRepositoryWizardPage::repositoryName() const
{
if (const QStandardItem *item = currentItem0())
if (item->data(TypeRole).toInt() == RepositoryType)
return item->text();
return QString();
}
QUrl GitoriousRepositoryWizardPage::repositoryURL() const
{
// Find by name (as we sorted 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;
}
} // namespace Internal
} // namespace Gitorious

View File

@@ -1,85 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef GITORIOUSREPOSITORYWIZARDPAGE_H
#define GITORIOUSREPOSITORYWIZARDPAGE_H
#include <QWizardPage>
QT_BEGIN_NAMESPACE
class QSortFilterProxyModel;
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();
void initializePage();
bool isComplete() const;
QString repositoryName() const;
QUrl repositoryURL() const;
public slots:
void slotCurrentChanged(const QModelIndex &current, const QModelIndex &previous);
private:
// return the repository (column 0) item.
QStandardItem *currentItem0() const;
// return the repository (column 0) item of index.
QStandardItem *item0FromIndex(const QModelIndex &filterIndex) const;
Ui::GitoriousRepositoryWizardPage *ui;
const GitoriousProjectWizardPage *m_projectPage;
QStandardItemModel *m_model;
QSortFilterProxyModel *m_filterModel;
bool m_valid;
};
} // namespace Internal
} // namespace Gitorious
#endif // GITORIOUSREPOSITORYWIZARDPAGE_H

View File

@@ -1,42 +0,0 @@
<?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="Utils::FancyLineEdit" name="filterLineEdit">
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
</widget>
</item>
<item>
<widget class="QTreeView" name="repositoryTreeView"/>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Utils::FancyLineEdit</class>
<extends>QLineEdit</extends>
<header location="global">utils/fancylineedit.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>filterLineEdit</tabstop>
<tabstop>repositoryTreeView</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@@ -39,7 +39,6 @@
#include "branchdialog.h" #include "branchdialog.h"
#include "remotedialog.h" #include "remotedialog.h"
#include "clonewizard.h" #include "clonewizard.h"
#include "gitorious/gitoriousclonewizard.h"
#include "stashdialog.h" #include "stashdialog.h"
#include "settingspage.h" #include "settingspage.h"
#include "logchangedialog.h" #include "logchangedialog.h"
@@ -301,17 +300,6 @@ bool GitPlugin::initialize(const QStringList &arguments, QString *errorMessage)
}); });
addAutoReleasedObject(cloneWizardFactory); addAutoReleasedObject(cloneWizardFactory);
// A wizard allowing for browsing Gitorious-hosted projects.
cloneWizardFactory = new VcsBase::BaseCheckoutWizardFactory;
cloneWizardFactory->setId(QLatin1String(VcsBase::Constants::VCS_ID_GIT));
cloneWizardFactory->setIcon(QIcon(QLatin1String(":/git/images/gitorious.png")));
cloneWizardFactory->setDescription(tr("Clones a Gitorious repository and tries to load the contained project."));
cloneWizardFactory->setDisplayName(tr("Gitorious Repository Clone"));
cloneWizardFactory->setWizardCreator([this] (const Utils::FileName &path, QWidget *parent) {
return new Gitorious::Internal::GitoriousCloneWizard(path, parent);
});
addAutoReleasedObject(cloneWizardFactory);
const QString prefix = QLatin1String("git"); const QString prefix = QLatin1String("git");
m_commandLocator = new CommandLocator("Git", prefix, prefix); m_commandLocator = new CommandLocator("Git", prefix, prefix);
addAutoReleasedObject(m_commandLocator); addAutoReleasedObject(m_commandLocator);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB