Index: mercurialplugin.cpp =================================================================== --- mercurialplugin.cpp +++ mercurialplugin.cpp @@ -527,10 +527,9 @@ VcsJob *MercurialPlugin::heads(const QUrl &localLocation) { - DVcsJob *job = new DVcsJob(findWorkingDir(localLocation), this); + DVcsJob *job = new DVcsJob(findWorkingDir(localLocation), this, KDevelop::OutputJob::Silent); - *job << "hg" << "heads" << "--template" - << logTemplate() << "--" << localLocation; + *job << "hg" << "heads" << "--template" << logTemplate(); connect(job, &DVcsJob::readyForParsing, this, &MercurialPlugin::parseLogOutputBasicVersionControl); Index: models/mercurialheadsmodel.h =================================================================== --- models/mercurialheadsmodel.h +++ models/mercurialheadsmodel.h @@ -1,40 +1,59 @@ -/*************************************************************************** - * Copyright 2011 Andrey Batyiev * - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of the GNU General Public License as * - * published by the Free Software Foundation; either version 2 of * - * the License or (at your option) version 3 or any later version * - * accepted by the membership of KDE e.V. (or its successor approved * - * by the membership of KDE e.V.), which shall act as a proxy * - * defined in Section 14 of version 3 of the license. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see . * - ***************************************************************************/ +/* + This file is part of KDevelop + + Copyright 2011 Andrey Batyiev + Copyright 2017 Sergey Kalinichev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ #ifndef MERCURIALHEADSMODEL_H #define MERCURIALHEADSMODEL_H #include "vcs/models/vcseventmodel.h" -class MercurialHeadsModel : public KDevelop::VcsEventModel +#include + +namespace KDevelop +{ + class VcsJob; +} + +class MercurialPlugin; + +class MercurialHeadsModel : public KDevelop::VcsBasicEventModel { Q_OBJECT public: - MercurialHeadsModel(KDevelop::IBasicVersionControl *iface, const KDevelop::VcsRevision &rev, const QUrl &url, QObject *parent); + MercurialHeadsModel(MercurialPlugin* plugin, const QUrl& url, QObject* parent); QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - void setCurrentHeads(const QList ¤tHeads) { - m_currentHeads = currentHeads; - emit headerDataChanged(Qt::Vertical, 0, m_currentHeads.count()); - } + + void update(); + +signals: + void updateComplete(); + +private slots: + void headsReceived(KDevelop::VcsJob* job); + void identifyReceived(KDevelop::VcsJob* job); private: + bool m_updating; + MercurialPlugin* m_plugin; + QUrl m_url; QList m_currentHeads; }; Index: models/mercurialheadsmodel.cpp =================================================================== --- models/mercurialheadsmodel.cpp +++ models/mercurialheadsmodel.cpp @@ -1,36 +1,46 @@ -/*************************************************************************** - * Copyright 2011 Andrey Batyiev * - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of the GNU General Public License as * - * published by the Free Software Foundation; either version 2 of * - * the License or (at your option) version 3 or any later version * - * accepted by the membership of KDE e.V. (or its successor approved * - * by the membership of KDE e.V.), which shall act as a proxy * - * defined in Section 14 of version 3 of the license. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see . * - ***************************************************************************/ +/* + This file is part of KDevelop + + Copyright 2011 Andrey Batyiev + Copyright 2017 Sergey Kalinichev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ #include "mercurialheadsmodel.h" +#include "../mercurialplugin.h" + #include +#include +#include + +#include #include #include using namespace KDevelop; -MercurialHeadsModel::MercurialHeadsModel(IBasicVersionControl *iface, const KDevelop::VcsRevision &rev, const QUrl &url, QObject *parent) - : VcsEventModel(iface, rev, url, parent) +MercurialHeadsModel::MercurialHeadsModel(MercurialPlugin* plugin, const QUrl& url, QObject* parent) + : VcsBasicEventModel(parent) + , m_updating(false) + , m_plugin(plugin) + , m_url(url) { - } QVariant MercurialHeadsModel::headerData(int section, Qt::Orientation orientation, int role) const @@ -43,6 +53,47 @@ return QVariant(); } } else { - return VcsEventModel::headerData(section, orientation, role); + return VcsBasicEventModel::headerData(section, orientation, role); + } +} + +void MercurialHeadsModel::update() +{ + VcsJob *identifyJob = m_plugin->identify(m_url); + connect(identifyJob, &VcsJob::resultsReady, this, &MercurialHeadsModel::identifyReceived); + ICore::self()->runController()->registerJob(identifyJob); + + VcsJob *headsJob = m_plugin->heads(m_url); + connect(headsJob, &VcsJob::resultsReady, this, &MercurialHeadsModel::headsReceived); + ICore::self()->runController()->registerJob(headsJob); +} + +void MercurialHeadsModel::identifyReceived(VcsJob *job) +{ + QList currentHeads; + foreach (const QVariant& value, job->fetchResults().toList()) { + currentHeads << value.value(); + } + m_currentHeads = currentHeads; + if (m_updating) { + emit updateComplete(); + m_updating = false; + } else { + m_updating = true; + } +} + +void MercurialHeadsModel::headsReceived(VcsJob *job) +{ + QList events; + foreach (const QVariant& value, job->fetchResults().toList()) { + events << value.value(); + } + addEvents(events); + if (m_updating) { + emit updateComplete(); + m_updating = false; + } else { + m_updating = true; } } Index: tests/test_mercurial.h =================================================================== --- tests/test_mercurial.h +++ tests/test_mercurial.h @@ -51,6 +51,7 @@ void testAnnotate(); void testDiff(); void testAnnotateFailed(); + void testHeads(); void initTestCase(); void cleanupTestCase(); Index: tests/test_mercurial.cpp =================================================================== --- tests/test_mercurial.cpp +++ tests/test_mercurial.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -36,6 +37,7 @@ #include "../mercurialplugin.h" #include "../mercurialannotatejob.h" +#include "../models/mercurialheadsmodel.h" #include "debug.h" using namespace KDevelop; @@ -361,4 +363,34 @@ //verifyAnnotateJobFailed(MercurialAnnotateJob::TestCase::Strip); } +void MercurialTest::testHeads() +{ + repoInit(); + addFiles(); + commitFiles(); + + VcsRevision revision; + revision.setRevisionValue(0, KDevelop::VcsRevision::GlobalNumber); + auto job = m_proxy->checkoutHead(QUrl::fromLocalFile(mercurialTest_BaseDir), revision); + verifyJobSucceed(job); + + writeToFile(mercurialTest_BaseDir + mercurialTest_FileName, "new head content", QIODevice::Append); + + auto j = m_proxy->commit(QString("new head"), {QUrl::fromLocalFile(mercurialTest_BaseDir)}, KDevelop::IBasicVersionControl::Recursive); + verifyJobSucceed(j); + + QScopedPointer headsModel(new MercurialHeadsModel(m_proxy, QUrl::fromLocalFile(mercurialTest_BaseDir), nullptr)); + headsModel->update(); + + QSignalSpy waiter(headsModel.data(), &MercurialHeadsModel::updateComplete); + QVERIFY(waiter.wait()); + QVERIFY(waiter.count() == 1); + + QCOMPARE(headsModel->rowCount(), 2); + auto rev2 = headsModel->data(headsModel->index(0, VcsBasicEventModel::RevisionColumn)).toLongLong(); + auto rev1 = headsModel->data(headsModel->index(1, VcsBasicEventModel::RevisionColumn)).toLongLong(); + QCOMPARE(rev2, 2); + QCOMPARE(rev1, 1); +} + QTEST_MAIN(MercurialTest) Index: ui/mercurialheadswidget.h =================================================================== --- ui/mercurialheadswidget.h +++ ui/mercurialheadswidget.h @@ -45,7 +45,7 @@ private slots: void updateModel(); - void identifyReceived(KDevelop::VcsJob *job); + void checkoutRequested(); void mergeRequested(); Index: ui/mercurialheadswidget.cpp =================================================================== --- ui/mercurialheadswidget.cpp +++ ui/mercurialheadswidget.cpp @@ -35,7 +35,7 @@ : QDialog(), m_ui(new Ui::MercurialHeadsWidget), m_plugin(plugin), m_url(url) { m_ui->setupUi(this); - m_headsModel = new MercurialHeadsModel(plugin, VcsRevision(), url, this); + m_headsModel = new MercurialHeadsModel(plugin, url, this); m_ui->headsTableView->setModel(static_cast(m_headsModel)); connect(m_ui->checkoutPushButton, &QPushButton::clicked, this, &MercurialHeadsWidget::checkoutRequested); @@ -48,18 +48,7 @@ void MercurialHeadsWidget::updateModel() { - VcsJob *identifyJob = m_plugin->identify(m_url); - connect(identifyJob, &VcsJob::resultsReady, this, &MercurialHeadsWidget::identifyReceived); - ICore::self()->runController()->registerJob(identifyJob); -} - -void MercurialHeadsWidget::identifyReceived(VcsJob *job) -{ - QList currentHeads; - foreach (const QVariant & value, job->fetchResults().toList()) { - currentHeads << value.value(); - } - m_headsModel->setCurrentHeads(currentHeads); + m_headsModel->update(); } void MercurialHeadsWidget::checkoutRequested()