File indexing completed on 2024-05-12 04:38:54
0001 /* 0002 SPDX-FileCopyrightText: 2008 Evgeniy Ivanov <powerfox@kde.ru> 0003 SPDX-FileCopyrightText: 2012 Aleix Pol Gonzalez <aleixpol@kde.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0006 */ 0007 0008 #include "brancheslistmodel.h" 0009 #include "debug.h" 0010 #include <vcs/interfaces/ibranchingversioncontrol.h> 0011 #include <vcs/vcsjob.h> 0012 #include <vcs/vcsrevision.h> 0013 #include <interfaces/icore.h> 0014 #include <interfaces/iprojectcontroller.h> 0015 #include <interfaces/iproject.h> 0016 #include <interfaces/iplugin.h> 0017 #include <interfaces/iruncontroller.h> 0018 #include "util/path.h" 0019 0020 #include <QIcon> 0021 0022 #include <KMessageBox> 0023 #include <KMessageBox_KDevCompat> 0024 #include <KLocalizedString> 0025 0026 using namespace std; 0027 using namespace KDevelop; 0028 0029 class KDevelop::BranchesListModelPrivate 0030 { 0031 public: 0032 BranchesListModelPrivate() 0033 { 0034 } 0035 0036 IBranchingVersionControl * dvcsplugin; 0037 QUrl repo; 0038 }; 0039 0040 class BranchItem : public QStandardItem 0041 { 0042 public: 0043 explicit BranchItem(const QString& name, bool current=false) : 0044 QStandardItem(name) 0045 { 0046 setEditable(true); 0047 setCurrent(current); 0048 } 0049 0050 void setCurrent(bool current) 0051 { 0052 setData(current, BranchesListModel::CurrentRole); 0053 setIcon(current ? QIcon::fromTheme(QStringLiteral("arrow-right")) : QIcon()); 0054 } 0055 0056 void setData(const QVariant& value, int role = Qt::UserRole + 1) override 0057 { 0058 if(role==Qt::EditRole && value.toString()!=text()) { 0059 QString newBranch = value.toString(); 0060 0061 auto* bmodel = qobject_cast<BranchesListModel*>(model()); 0062 if(!bmodel->findItems(newBranch).isEmpty()) 0063 { 0064 KMessageBox::error(nullptr, i18n("Branch \"%1\" already exists.", newBranch)); 0065 return; 0066 } 0067 0068 int ret = KMessageBox::warningTwoActions( 0069 nullptr, i18n("Are you sure you want to rename \"%1\" to \"%2\"?", text(), newBranch), {}, 0070 KGuiItem(i18nc("@action:button", "Rename"), QStringLiteral("edit-rename")), 0071 KStandardGuiItem::cancel()); 0072 if (ret == KMessageBox::SecondaryAction) { 0073 return; // ignore event 0074 } 0075 0076 KDevelop::VcsJob *branchJob = bmodel->interface()->renameBranch(bmodel->repository(), newBranch, text()); 0077 ret = branchJob->exec(); 0078 qCDebug(VCS) << "Renaming " << text() << " to " << newBranch << ':' << ret; 0079 if (!ret) { 0080 return; // ignore event 0081 } 0082 } 0083 0084 QStandardItem::setData(value, role); 0085 } 0086 }; 0087 0088 static QVariant runSynchronously(KDevelop::VcsJob* job) 0089 { 0090 job->setVerbosity(KDevelop::OutputJob::Silent); 0091 QVariant ret; 0092 if(job->exec() && job->status()==KDevelop::VcsJob::JobSucceeded) { 0093 ret = job->fetchResults(); 0094 } 0095 delete job; 0096 return ret; 0097 } 0098 0099 BranchesListModel::BranchesListModel(QObject* parent) 0100 : QStandardItemModel(parent) 0101 , d_ptr(new BranchesListModelPrivate()) 0102 { 0103 } 0104 0105 BranchesListModel::~BranchesListModel() 0106 { 0107 } 0108 0109 QHash<int, QByteArray> BranchesListModel::roleNames() const 0110 { 0111 auto roles = QAbstractItemModel::roleNames(); 0112 roles.insert(CurrentRole, "isCurrent"); 0113 return roles; 0114 } 0115 0116 void BranchesListModel::createBranch(const QString& baseBranch, const QString& newBranch) 0117 { 0118 Q_D(BranchesListModel); 0119 0120 qCDebug(VCS) << "Creating " << baseBranch << " based on " << newBranch; 0121 KDevelop::VcsRevision rev; 0122 rev.setRevisionValue(baseBranch, KDevelop::VcsRevision::GlobalNumber); 0123 KDevelop::VcsJob* branchJob = d->dvcsplugin->branch(d->repo, rev, newBranch); 0124 0125 qCDebug(VCS) << "Adding new branch"; 0126 if (branchJob->exec()) 0127 appendRow(new BranchItem(newBranch)); 0128 } 0129 0130 void BranchesListModel::removeBranch(const QString& branch) 0131 { 0132 Q_D(BranchesListModel); 0133 0134 KDevelop::VcsJob *branchJob = d->dvcsplugin->deleteBranch(d->repo, branch); 0135 0136 qCDebug(VCS) << "Removing branch:" << branch; 0137 if (branchJob->exec()) { 0138 const QList<QStandardItem*> items = findItems(branch); 0139 for (QStandardItem* item : items) { 0140 removeRow(item->row()); 0141 } 0142 } 0143 } 0144 0145 QUrl BranchesListModel::repository() const 0146 { 0147 Q_D(const BranchesListModel); 0148 0149 return d->repo; 0150 } 0151 0152 KDevelop::IBranchingVersionControl* BranchesListModel::interface() const 0153 { 0154 Q_D(const BranchesListModel); 0155 0156 return d->dvcsplugin; 0157 } 0158 0159 void BranchesListModel::initialize(KDevelop::IBranchingVersionControl* branching, const QUrl& r) 0160 { 0161 Q_D(BranchesListModel); 0162 0163 d->dvcsplugin = branching; 0164 d->repo = r; 0165 refresh(); 0166 } 0167 0168 void BranchesListModel::refresh() 0169 { 0170 Q_D(BranchesListModel); 0171 0172 const QStringList branches = runSynchronously(d->dvcsplugin->branches(d->repo)).toStringList(); 0173 QString curBranch = runSynchronously(d->dvcsplugin->currentBranch(d->repo)).toString(); 0174 0175 for (const QString& branch : branches) { 0176 appendRow(new BranchItem(branch, branch == curBranch)); 0177 } 0178 } 0179 0180 void BranchesListModel::resetCurrent() 0181 { 0182 refresh(); 0183 emit currentBranchChanged(); 0184 } 0185 0186 QString BranchesListModel::currentBranch() const 0187 { 0188 Q_D(const BranchesListModel); 0189 0190 return runSynchronously(d->dvcsplugin->currentBranch(d->repo)).toString(); 0191 } 0192 0193 KDevelop::IProject* BranchesListModel::project() const 0194 { 0195 Q_D(const BranchesListModel); 0196 0197 return KDevelop::ICore::self()->projectController()->findProjectForUrl(d->repo); 0198 } 0199 0200 void BranchesListModel::setProject(KDevelop::IProject* p) 0201 { 0202 if(!p || !p->versionControlPlugin()) { 0203 qCDebug(VCS) << "null or invalid project" << p; 0204 return; 0205 } 0206 0207 auto* branching = p->versionControlPlugin()->extension<KDevelop::IBranchingVersionControl>(); 0208 if(branching) { 0209 initialize(branching, p->path().toUrl()); 0210 } else 0211 qCDebug(VCS) << "not a branching vcs project" << p->name(); 0212 } 0213 0214 void BranchesListModel::setCurrentBranch(const QString& branch) 0215 { 0216 Q_D(BranchesListModel); 0217 0218 KDevelop::VcsJob* job = d->dvcsplugin->switchBranch(d->repo, branch); 0219 connect(job, &VcsJob::finished, this, &BranchesListModel::currentBranchChanged); 0220 KDevelop::ICore::self()->runController()->registerJob(job); 0221 } 0222 0223 #include "moc_brancheslistmodel.cpp"