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 parent(const QModelIndex &index) const const=0
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const override
QString currentPath()
bool setCurrent(const QString &path)
QString errorString() 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)
void start(OpenMode mode)
bool waitForFinished(int msecs)
bool waitForStarted(int msecs)
DisplayRole
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Jan 24 2025 11:57:49 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.