forked from qt-creator/qt-creator
Gerrit: Allow custom query
Change-Id: I8ee0967a8f0013c785bc4d6e98ff7b634f488e97 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@nokia.com>
This commit is contained in:
committed by
Friedemann Kleint
parent
a8debd265f
commit
cb8c8ca19e
@@ -60,6 +60,38 @@ namespace Internal {
|
||||
static const int layoutSpacing = 5;
|
||||
static const int maxTitleWidth = 350;
|
||||
|
||||
QueryValidatingLineEdit::QueryValidatingLineEdit(QWidget *parent)
|
||||
: Utils::FilterLineEdit(parent)
|
||||
, m_valid(true)
|
||||
, m_okTextColor(palette().color(QPalette::Active, QPalette::Text))
|
||||
, m_errorTextColor(Qt::red)
|
||||
{
|
||||
connect(this, SIGNAL(textChanged(QString)), this, SLOT(setValid()));
|
||||
}
|
||||
|
||||
void QueryValidatingLineEdit::setTextColor(const QColor &c)
|
||||
{
|
||||
QPalette pal = palette();
|
||||
pal.setColor(QPalette::Active, QPalette::Text, c);
|
||||
setPalette(pal);
|
||||
}
|
||||
|
||||
void QueryValidatingLineEdit::setValid()
|
||||
{
|
||||
if (!m_valid) {
|
||||
m_valid = true;
|
||||
setTextColor(m_okTextColor);
|
||||
}
|
||||
}
|
||||
|
||||
void QueryValidatingLineEdit::setInvalid()
|
||||
{
|
||||
if (m_valid) {
|
||||
m_valid = false;
|
||||
setTextColor(m_errorTextColor);
|
||||
}
|
||||
}
|
||||
|
||||
GerritDialog::GerritDialog(const QSharedPointer<GerritParameters> &p,
|
||||
QWidget *parent)
|
||||
: QDialog(parent)
|
||||
@@ -68,6 +100,7 @@ GerritDialog::GerritDialog(const QSharedPointer<GerritParameters> &p,
|
||||
, m_model(new GerritModel(p, this))
|
||||
, m_treeView(new QTreeView)
|
||||
, m_detailsBrowser(new QTextBrowser)
|
||||
, m_queryLineEdit(new QueryValidatingLineEdit)
|
||||
, m_filterLineEdit(new Utils::FilterLineEdit)
|
||||
, m_buttonBox(new QDialogButtonBox(QDialogButtonBox::Close))
|
||||
{
|
||||
@@ -78,11 +111,20 @@ GerritDialog::GerritDialog(const QSharedPointer<GerritParameters> &p,
|
||||
QVBoxLayout *changesLayout = new QVBoxLayout(changesGroup);
|
||||
changesLayout->setMargin(layoutSpacing);
|
||||
QHBoxLayout *filterLayout = new QHBoxLayout;
|
||||
QLabel *queryLabel = new QLabel(tr("&Query:"));
|
||||
queryLabel->setBuddy(m_queryLineEdit);
|
||||
m_queryLineEdit->setFixedWidth(400);
|
||||
m_queryLineEdit->setPlaceholderText(tr("Change #, SHA-1, tr:id, owner:email or reviewer:email"));
|
||||
filterLayout->addWidget(queryLabel);
|
||||
filterLayout->addWidget(m_queryLineEdit);
|
||||
filterLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Ignored));
|
||||
m_filterLineEdit->setFixedWidth(300);
|
||||
filterLayout->addWidget(m_filterLineEdit);
|
||||
connect(m_filterLineEdit, SIGNAL(filterChanged(QString)),
|
||||
m_filterModel, SLOT(setFilterFixedString(QString)));
|
||||
connect(m_queryLineEdit, SIGNAL(returnPressed()),
|
||||
this, SLOT(slotRefresh()));
|
||||
connect(m_model, SIGNAL(queryError()), m_queryLineEdit, SLOT(setInvalid()));
|
||||
m_filterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||
changesLayout->addLayout(filterLayout);
|
||||
changesLayout->addWidget(m_treeView);
|
||||
@@ -130,9 +172,10 @@ GerritDialog::GerritDialog(const QSharedPointer<GerritParameters> &p,
|
||||
mainLayout->addWidget(m_buttonBox);
|
||||
|
||||
slotCurrentChanged();
|
||||
m_model->refresh();
|
||||
slotRefresh();
|
||||
|
||||
resize(QSize(950, 600));
|
||||
m_treeView->setFocus();
|
||||
}
|
||||
|
||||
QPushButton *GerritDialog::addActionButton(const QString &text, const char *buttonSlot)
|
||||
@@ -182,7 +225,7 @@ void GerritDialog::slotFetchCheckout()
|
||||
|
||||
void GerritDialog::slotRefresh()
|
||||
{
|
||||
m_model->refresh();
|
||||
m_model->refresh(m_queryLineEdit->text());
|
||||
}
|
||||
|
||||
const QStandardItem *GerritDialog::itemAt(const QModelIndex &i, int column) const
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
#ifndef GERRIT_INTERNAL_GERRITDIALOG_H
|
||||
#define GERRIT_INTERNAL_GERRITDIALOG_H
|
||||
|
||||
#include <utils/filterlineedit.h>
|
||||
|
||||
#include <QDialog>
|
||||
#include <QSharedPointer>
|
||||
|
||||
@@ -47,15 +49,30 @@ class QDialogButtonBox;
|
||||
class QTextBrowser;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Utils {
|
||||
class FilterLineEdit;
|
||||
}
|
||||
namespace Gerrit {
|
||||
namespace Internal {
|
||||
class GerritParameters;
|
||||
class GerritModel;
|
||||
class GerritChange;
|
||||
|
||||
class QueryValidatingLineEdit : public Utils::FilterLineEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QueryValidatingLineEdit(QWidget *parent = 0);
|
||||
void setTextColor(const QColor &c);
|
||||
|
||||
public slots:
|
||||
void setValid();
|
||||
void setInvalid();
|
||||
|
||||
private:
|
||||
bool m_valid;
|
||||
const QColor m_okTextColor;
|
||||
const QColor m_errorTextColor;
|
||||
};
|
||||
|
||||
class GerritDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -88,6 +105,7 @@ private:
|
||||
GerritModel *m_model;
|
||||
QTreeView *m_treeView;
|
||||
QTextBrowser *m_detailsBrowser;
|
||||
QueryValidatingLineEdit *m_queryLineEdit;
|
||||
Utils::FilterLineEdit *m_filterLineEdit;
|
||||
QDialogButtonBox *m_buttonBox;
|
||||
QPushButton *m_displayButton;
|
||||
|
||||
@@ -410,7 +410,7 @@ int GerritModel::indexOf(int gerritNumber) const
|
||||
return -1;
|
||||
}
|
||||
|
||||
void GerritModel::refresh()
|
||||
void GerritModel::refresh(const QString &query)
|
||||
{
|
||||
if (m_query) {
|
||||
qWarning("%s: Another query is still running", Q_FUNC_INFO);
|
||||
@@ -419,22 +419,27 @@ void GerritModel::refresh()
|
||||
clearData();
|
||||
|
||||
// Assemble list of queries
|
||||
const QString statusOpenQuery = QLatin1String("status:open");
|
||||
|
||||
QStringList queries;
|
||||
if (m_parameters->user.isEmpty()) {
|
||||
queries.push_back(statusOpenQuery);
|
||||
} else {
|
||||
// Owned by:
|
||||
queries.push_back(statusOpenQuery + QLatin1String(" owner:") + m_parameters->user);
|
||||
// For Review by:
|
||||
queries.push_back(statusOpenQuery + QLatin1String(" reviewer:") + m_parameters->user);
|
||||
}
|
||||
// Any custom queries?
|
||||
if (!m_parameters->additionalQueries.isEmpty()) {
|
||||
foreach (const QString &customQuery, m_parameters->additionalQueries.split(QString::SkipEmptyParts)) {
|
||||
if (!customQuery.trimmed().isEmpty())
|
||||
queries.push_back(customQuery);
|
||||
if (!query.trimmed().isEmpty())
|
||||
queries.push_back(query);
|
||||
else
|
||||
{
|
||||
const QString statusOpenQuery = QLatin1String("status:open");
|
||||
if (m_parameters->user.isEmpty()) {
|
||||
queries.push_back(statusOpenQuery);
|
||||
} else {
|
||||
// Owned by:
|
||||
queries.push_back(statusOpenQuery + QLatin1String(" owner:") + m_parameters->user);
|
||||
// For Review by:
|
||||
queries.push_back(statusOpenQuery + QLatin1String(" reviewer:") + m_parameters->user);
|
||||
}
|
||||
// Any custom queries?
|
||||
if (!m_parameters->additionalQueries.isEmpty()) {
|
||||
foreach (const QString &customQuery, m_parameters->additionalQueries.split(QString::SkipEmptyParts)) {
|
||||
if (!customQuery.trimmed().isEmpty())
|
||||
queries.push_back(customQuery);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -473,8 +478,9 @@ void GerritModel::clearData()
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
// Qt 5 using the QJsonDocument classes.
|
||||
static QList<GerritChangePtr> parseOutput(const QSharedPointer<GerritParameters> ¶meters,
|
||||
const QByteArray &output)
|
||||
static bool parseOutput(const QSharedPointer<GerritParameters> ¶meters,
|
||||
const QByteArray &output,
|
||||
QList<GerritChangePtr> &result)
|
||||
{
|
||||
// The output consists of separate lines containing a document each
|
||||
const QString typeKey = QLatin1String("type");
|
||||
@@ -498,7 +504,8 @@ static QList<GerritChangePtr> parseOutput(const QSharedPointer<GerritParameters>
|
||||
const QString approvalsTypeKey = QLatin1String("type");
|
||||
const QString approvalsDescriptionKey = QLatin1String("description");
|
||||
|
||||
QList<GerritChangePtr> result;
|
||||
bool res = true;
|
||||
result.clear();
|
||||
result.reserve(lines.size());
|
||||
|
||||
foreach (const QByteArray &line, lines) {
|
||||
@@ -507,8 +514,12 @@ static QList<GerritChangePtr> parseOutput(const QSharedPointer<GerritParameters>
|
||||
QJsonParseError error;
|
||||
const QJsonDocument doc = QJsonDocument::fromJson(line, &error);
|
||||
if (doc.isNull()) {
|
||||
qWarning("Parse error: '%s' -> %s", line.constData(),
|
||||
qPrintable(error.errorString()));
|
||||
QString errorMessage = GerritModel::tr("Parse error: '%1' -> %2")
|
||||
.arg(QString::fromLocal8Bit(line))
|
||||
.arg(error.errorString());
|
||||
qWarning() << errorMessage;
|
||||
VcsBase::VcsBaseOutputWindow::instance()->appendError(errorMessage);
|
||||
res = false;
|
||||
continue;
|
||||
}
|
||||
GerritChangePtr change(new GerritChange);
|
||||
@@ -554,10 +565,14 @@ static QList<GerritChangePtr> parseOutput(const QSharedPointer<GerritParameters>
|
||||
if (change->isValid()) {
|
||||
result.push_back(change);
|
||||
} else {
|
||||
qWarning("%s: Parse error in line '%s'.", Q_FUNC_INFO, line.constData());
|
||||
qWarning("%s: Parse error: '%s'.", Q_FUNC_INFO, line.constData());
|
||||
VcsBase::VcsBaseOutputWindow::instance()
|
||||
->appendError(GerritModel::tr("Parse error: '%1'")
|
||||
.arg(QString::fromLocal8Bit(line)));
|
||||
res = false;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return res;
|
||||
}
|
||||
#else // QT_VERSION >= 0x050000
|
||||
// Qt 4.8 using the Json classes from utils.
|
||||
@@ -588,8 +603,9 @@ static inline QString jsonStringMember(Utils::JsonObjectValue *object,
|
||||
return QString();
|
||||
}
|
||||
|
||||
static QList<GerritChangePtr> parseOutput(const QSharedPointer<GerritParameters> ¶meters,
|
||||
const QByteArray &output)
|
||||
static bool parseOutput(const QSharedPointer<GerritParameters> ¶meters,
|
||||
const QByteArray &output,
|
||||
QList<GerritChangePtr> &result)
|
||||
{
|
||||
// The output consists of separate lines containing a document each
|
||||
const QList<QByteArray> lines = output.split('\n');
|
||||
@@ -612,7 +628,8 @@ static QList<GerritChangePtr> parseOutput(const QSharedPointer<GerritParameters>
|
||||
const QString approvalsTypeKey = QLatin1String("type");
|
||||
const QString approvalsDescriptionKey = QLatin1String("description");
|
||||
const QString lastUpdatedKey = QLatin1String("lastUpdated");
|
||||
QList<GerritChangePtr> result;
|
||||
bool res = true;
|
||||
result.clear();
|
||||
result.reserve(lines.size());
|
||||
|
||||
foreach (const QByteArray &line, lines) {
|
||||
@@ -620,7 +637,11 @@ static QList<GerritChangePtr> parseOutput(const QSharedPointer<GerritParameters>
|
||||
continue;
|
||||
QScopedPointer<Utils::JsonValue> objectValue(Utils::JsonValue::create(QString::fromUtf8(line)));
|
||||
if (objectValue.isNull()) {
|
||||
qWarning("Parse error: '%s'", line.constData());
|
||||
QString errorMessage = GerritModel::tr("Parse error: '%1'")
|
||||
.arg(QString::fromLocal8Bit(line));
|
||||
qWarning() << errorMessage;
|
||||
VcsBase::VcsBaseOutputWindow::instance()->appendError(errorMessage);
|
||||
res = false;
|
||||
continue;
|
||||
}
|
||||
Utils::JsonObjectValue *object = objectValue->toObject();
|
||||
@@ -687,7 +708,11 @@ static QList<GerritChangePtr> parseOutput(const QSharedPointer<GerritParameters>
|
||||
if (change->isValid()) {
|
||||
result.push_back(change);
|
||||
} else {
|
||||
QString errorMessage = GerritModel::tr("Parse error in line '%1'")
|
||||
.arg(QString::fromLocal8Bit(line));
|
||||
VcsBase::VcsBaseOutputWindow::instance()->appendError(errorMessage);
|
||||
qWarning("%s: Parse error in line '%s'.", Q_FUNC_INFO, line.constData());
|
||||
res = false;
|
||||
}
|
||||
}
|
||||
if (debug) {
|
||||
@@ -695,7 +720,7 @@ static QList<GerritChangePtr> parseOutput(const QSharedPointer<GerritParameters>
|
||||
foreach (const GerritChangePtr &p, result)
|
||||
qDebug() << *p;
|
||||
}
|
||||
return result;
|
||||
return res;
|
||||
}
|
||||
#endif // QT_VERSION < 0x050000
|
||||
|
||||
@@ -707,7 +732,9 @@ bool changeDateLessThan(const GerritChangePtr &c1, const GerritChangePtr &c2)
|
||||
void GerritModel::queryFinished(const QByteArray &output)
|
||||
{
|
||||
const QDate today = QDate::currentDate();
|
||||
QList<GerritChangePtr> changes = parseOutput(m_parameters, output);
|
||||
QList<GerritChangePtr> changes;
|
||||
if (!parseOutput(m_parameters, output, changes))
|
||||
emit queryError();
|
||||
qStableSort(changes.begin(), changes.end(), changeDateLessThan);
|
||||
foreach (const GerritChangePtr &c, changes) {
|
||||
// Avoid duplicate entries for example in the (unlikely)
|
||||
@@ -744,15 +771,11 @@ void GerritModel::queryFinished(const QByteArray &output)
|
||||
row[ApprovalsColumn]->setText(c->currentPatchSet.approvalsColumn());
|
||||
// Mark changes awaiting action using a bold font.
|
||||
bool bold = false;
|
||||
switch (m_query->currentQuery()) {
|
||||
case 0: { // Owned changes: Review != 0,1. Submit or amend.
|
||||
if (c->owner == m_userName) { // Owned changes: Review != 0,1. Submit or amend.
|
||||
const int level = c->currentPatchSet.approvalLevel();
|
||||
bold = level != 0 && level != 1;
|
||||
}
|
||||
break;
|
||||
case 1: // Changes pending for review: No review yet.
|
||||
} else if (m_query->currentQuery() == 1) { // Changes pending for review: No review yet.
|
||||
bold = !m_userName.isEmpty() && !c->currentPatchSet.hasApproval(m_userName);
|
||||
break;
|
||||
}
|
||||
if (bold) {
|
||||
QFont font = row.first()->font();
|
||||
|
||||
@@ -124,10 +124,11 @@ public:
|
||||
int indexOf(int gerritNumber) const;
|
||||
|
||||
public slots:
|
||||
void refresh();
|
||||
void refresh(const QString &query);
|
||||
|
||||
signals:
|
||||
void refreshStateChanged(bool isRefreshing); // For disabling the "Refresh" button.
|
||||
void queryError();
|
||||
|
||||
private slots:
|
||||
void queryFinished(const QByteArray &);
|
||||
|
||||
Reference in New Issue
Block a user