Purpose

difflistmodel.cpp
1/*
2 SPDX-FileCopyrightText: 2017 René J.V. Bertin <rjvbertin@gmail.com>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "difflistmodel.h"
8#include "phabricatorjobs.h"
9
10#include <QBrush>
11#include <QDebug>
12#include <QDir>
13#include <QTemporaryDir>
14
15DiffListModel::DiffListModel(QObject *parent)
16 : QAbstractListModel(parent)
17 , m_initialDir(QDir::currentPath())
18 , m_tempDir(nullptr)
19{
20 refresh();
21}
22
23void DiffListModel::refresh()
24{
25 if (m_tempDir) {
26 qCritical() << "DiffListModel::refresh() called while still active!";
27 return;
28 }
29
31 m_values.clear();
33
34 // our CWD should be the directory from which the application was launched, which
35 // may or may not be a git, mercurial or svn working copy, so we create a temporary
36 // directory in which we initialise a git repository. This may be an empty repo.
37
38 m_initialDir = QDir::currentPath();
39 m_tempDir = new QTemporaryDir;
40 if (!m_tempDir->isValid()) {
41 qCritical() << "DiffListModel::refresh() failed to create temporary directory" << m_tempDir->path() << ":" << m_tempDir->errorString();
42 } else {
43 if (QDir::setCurrent(m_tempDir->path())) {
44 // the directory will be removed in receivedDiffRevs()
45 m_tempDir->setAutoRemove(false);
46 QProcess initGit;
47 bool ok = false;
48 // create the virgin git repo. This is a very cheap operation that should
49 // never fail in a fresh temporary directory we ourselves created, so it
50 // should be OK to do this with a synchronous call.
51 initGit.start(QLatin1String("git init"), QStringList());
52 if (initGit.waitForStarted(1000)) {
53 ok = initGit.waitForFinished(500);
54 }
55 if (!ok) {
56 qCritical() << "DiffListModel::refresh() : couldn't create temp. git repo:" << initGit.errorString();
57 }
58 } else {
59 qCritical() << "DiffListModel::refresh() failed to chdir to" << m_tempDir->path();
60 }
61 }
62 // create a list request with the current (= temp.) directory as the project directory.
63 // This request is executed asynchronously, which is why we cannot restore the initial
64 // working directory just yet, nor remove the temporary directory.
65 Phabricator::DiffRevList *repo = new Phabricator::DiffRevList(QDir::currentPath(), this);
66 connect(repo, &Phabricator::DiffRevList::finished, this, &DiffListModel::receivedDiffRevs);
67 repo->start();
68}
69
70void DiffListModel::receivedDiffRevs(KJob *job)
71{
72 if (job->error() != 0) {
73 qWarning() << "error getting differential revision list" << job->errorString();
75 m_values.clear();
77 return;
78 }
79
80 const auto diffRevList = dynamic_cast<Phabricator::DiffRevList *>(job);
81 const auto revs = diffRevList->reviews();
82
84 m_values.clear();
85 for (const auto &review : revs) {
86 auto status = diffRevList->statusMap()[review.second];
87 m_values += Value{review.second, review.first, status};
88 }
90
91 // now we can restore the initial working directory and remove the temp directory
92 // (in that order!).
93 if (!QDir::setCurrent(m_initialDir)) {
94 qCritical() << "DiffListModel::receivedDiffRevs() failed to restore initial directory" << m_initialDir;
95 }
96 if (m_tempDir) {
97 m_tempDir->remove();
98 delete m_tempDir;
99 m_tempDir = nullptr;
100 }
101}
102
103QHash<int, QByteArray> DiffListModel::roleNames() const
104{
105 const QHash<int, QByteArray> roles = {{Qt::DisplayRole, QByteArrayLiteral("display")},
106 {Qt::ToolTipRole, QByteArrayLiteral("toolTip")},
107 {Qt::ForegroundRole, QByteArrayLiteral("textColor")}};
108 return roles;
109}
110
111QVariant DiffListModel::data(const QModelIndex &idx, int role) const
112{
113 if (!idx.isValid() || idx.column() != 0 || idx.row() >= m_values.size()) {
114 return QVariant();
115 }
116
117 switch (role) {
118 case Qt::DisplayRole:
119 return m_values[idx.row()].summary;
120 case Qt::ToolTipRole:
121 return m_values[idx.row()].id;
123 // Use the colours arc also uses
124 switch (m_values[idx.row()].status.value<Phabricator::DiffRevList::Status>()) {
125 case Phabricator::DiffRevList::Accepted:
126 // alternative: KColorScheme::ForegroundRole::PositiveText
127 return QBrush(Qt::green);
128 case Phabricator::DiffRevList::NeedsReview:
129 // alternative: KColorScheme::ForegroundRole::NeutralText
130 return QBrush(Qt::magenta);
131 case Phabricator::DiffRevList::NeedsRevision:
132 // alternative: KColorScheme::ForegroundRole::NegativeText
133 return QBrush(Qt::red);
134 default:
135 return {};
136 }
137 }
138 return {};
139}
140
141int DiffListModel::rowCount(const QModelIndex &parent) const
142{
143 return parent.isValid() ? 0 : m_values.count();
144}
145
146QVariant DiffListModel::get(int row, const QByteArray &role)
147{
148 return index(row, 0).data(roleNames().key(role));
149}
150
151void DiffListModel::setStatus(const QString &status)
152{
153 if (m_status != status) {
154 m_status = status;
155 refresh();
156 }
157}
158
159#include "moc_difflistmodel.cpp"
virtual QString errorString() const
int error() const
void finished(KJob *job)
Q_SCRIPTABLE CaptureState status()
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const override
QString currentPath()
bool setCurrent(const QString &path)
QString errorString() const const
void clear()
qsizetype count() const const
qsizetype size() const const
int column() const const
QVariant data(int role) const const
bool isValid() const const
int row() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QObject * parent() const const
void start(OpenMode mode)
bool waitForFinished(int msecs)
bool waitForStarted(int msecs)
DisplayRole
QString errorString() const const
bool isValid() const const
QString path() const const
void setAutoRemove(bool b)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:14:05 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.