# # # patch "res/forms/dialogs/changeset_browser.ui" # from [acec562b32d453228b3fbc2438da26e41002a1fe] # to [99f5dc0833e89b92c770a805ac4b9ea8c78a0317] # # patch "src/model/Branches.cpp" # from [67a145d13304dbdd83a59c9db10f33cfa8f56dc5] # to [9707d8b1361016c41f96729adc0da88b988e51a3] # # patch "src/model/Branches.h" # from [f2ddb8c1991b32f53e190ae3f1e05902461196c4] # to [cf346cdfd0b86ffc8711859f029b44b94c9bc280] # # patch "src/model/GetBranchLog.cpp" # from [721cc582a4dcce9b60b515667d07c7062e65791f] # to [e9ac73db95e5524f1970dbbed89be13c87659baa] # # patch "src/model/GetBranchLog.h" # from [60a32c3d8e56bdf26e1a426af0265f2654cd95de] # to [fb34c7f1a38c677e60b4945456567b104922e82e] # # patch "src/view/dialogs/ChangesetBrowser.cpp" # from [b0865decf7393809ac01fb964696001f2a8c90fc] # to [0bd8c4543e61ef1e17cfc742f5a94092287e70b4] # # patch "src/view/dialogs/ChangesetBrowser.h" # from [ae5ea7b80db4220b1c4f6dab9814da35a6eae401] # to [2af4dcc3a6843e8545d98b7054fb7c9b398e7aaa] # # patch "src/view/dialogs/DatabaseDialogManager.cpp" # from [9fd20e3bd733cf36a534882f32eaaa7c1095c225] # to [052e2022d9c33fe5a22d8ada9d29dcaa8dc13c4e] # # patch "src/view/widgets/BranchView.cpp" # from [62590eb879a129b84bd7c81464c6fba5233a6e5e] # to [df060172ca18afedc0ab1e936f69cfb86590d9aa] # # patch "src/view/widgets/BranchView.h" # from [9c5e1248688a2729c1e96c6de1463ecbd906fd45] # to [ae0d3f7ebea4e65ce3a8f477881593bf40705146] # ============================================================ --- res/forms/dialogs/changeset_browser.ui acec562b32d453228b3fbc2438da26e41002a1fe +++ res/forms/dialogs/changeset_browser.ui 99f5dc0833e89b92c770a805ac4b9ea8c78a0317 @@ -29,18 +29,7 @@ 0 - - - - - Filter branches - - - - - - - + @@ -251,7 +240,7 @@ QPushButton:pressed, QPushButton:checked 0 - 24636 + 24896 ============================================================ --- src/model/Branches.cpp 67a145d13304dbdd83a59c9db10f33cfa8f56dc5 +++ src/model/Branches.cpp 9707d8b1361016c41f96729adc0da88b988e51a3 @@ -73,6 +73,14 @@ void Branches::processTaskResult(const M branches = task->getDecodedOutput() .split("\n", QString::SkipEmptyParts); + rebuildBranchModel(); + + emit branchesRead(); + + setHorizontalHeaderItem(0, new QStandardItem( + tr("Branches (determining suspended branches)") + )); + foreach (const QString & branch, branches) { MonotoneTaskPtr task(new MonotoneTask( @@ -81,10 +89,6 @@ void Branches::processTaskResult(const M )); AutomateCommand::enqueueDatabaseTask(databaseFile, task); } - - displayBranchesAsTree(branchesAsTree); - - emit branchesRead(); } else if (cmd == "select") { @@ -121,6 +125,9 @@ void Branches::processTaskResult(const M if (!hasQueuedCommands()) { markSuspendedBranches(invisibleRootItem()); + + setHorizontalHeaderItem(0, new QStandardItem(tr("Branches"))); + reset(); } } @@ -142,14 +149,22 @@ Qt::ItemFlags Branches::flags(const QMod return flags; } -void Branches::displayBranchesAsTree(bool tree) +void Branches::markBranchSuspended(const QString & branch) { + if (activeHeadsMap.contains(branch)) + { + activeHeadsMap[branch].clear(); + markSuspendedBranches(invisibleRootItem()); + reset(); + } +} + +void Branches::rebuildBranchModel() +{ branchItemMap.clear(); clear(); - setHorizontalHeaderItem(0, new QStandardItem(tr("Branches"))); - - if (tree) + if (branchesAsTree) { builder = new TreeBuilder(branchItemMap, invisibleRootItem(), this); builder->addList(branches); @@ -166,10 +181,15 @@ void Branches::displayBranchesAsTree(boo } } - branchesAsTree = tree; + reset(); +} +void Branches::displayBranchesAsTree(bool tree) +{ + branchesAsTree = tree; + rebuildBranchModel(); markSuspendedBranches(invisibleRootItem()); - + setHorizontalHeaderItem(0, new QStandardItem(tr("Branches"))); reset(); } ============================================================ --- src/model/Branches.h f2ddb8c1991b32f53e190ae3f1e05902461196c4 +++ src/model/Branches.h cf346cdfd0b86ffc8711859f029b44b94c9bc280 @@ -33,6 +33,8 @@ public: Branches(QObject *, const DatabaseFile &); ~Branches(); + void markBranchSuspended(const QString &); + Qt::ItemFlags flags(const QModelIndex & index) const; public slots: @@ -44,6 +46,7 @@ private: private: void processTaskResult(const MonotoneTaskPtr &); + void rebuildBranchModel(); bool markSuspendedBranches(QStandardItem *); bool branchesAsTree, suspendedBranches; ============================================================ --- src/model/GetBranchLog.cpp 721cc582a4dcce9b60b515667d07c7062e65791f +++ src/model/GetBranchLog.cpp e9ac73db95e5524f1970dbbed89be13c87659baa @@ -50,7 +50,7 @@ CertList GetBranchLog::getCerts(const QS return certMap.value(rev); } -void GetBranchLog::invalidateCerts(const QString & rev) +void GetBranchLog::invalidateCertCache(const QString & rev) { if (certMap.contains(rev)) { @@ -61,6 +61,23 @@ void GetBranchLog::invalidateCerts(const } } +void GetBranchLog::invalidateBranchCache(const QString & branch) +{ + if (revisionMap.contains(branch)) + revisionMap.remove(branch); + + if (nextRevs.contains(branch)) + nextRevs.remove(branch); + + if (branch == currentBranch) + { + AutomateCommand::abortThreads(); + currentBranch = QString(); + reset(); + emit readingStopped(); + } +} + void GetBranchLog::readAll(const QString & branch) { readMore(branch, -1); @@ -232,8 +249,6 @@ void GetBranchLog::processTaskResult(con if (current == "certs") { QString queriedRev = task->getArguments().at(1); - int row = revisionMap[currentBranch].indexOf(queriedRev); - I(row >= 0); BasicIOParser parser(output); I(parser.parse()); @@ -243,7 +258,14 @@ void GetBranchLog::processTaskResult(con certs.fill(parser.getStanzas()); certMap.insert(queriedRev, certs); - emit dataChanged(index(row, 0, QModelIndex()), index(row, 3, QModelIndex())); + int row = revisionMap[currentBranch].indexOf(queriedRev); + if (row >= 0) + { + emit dataChanged( + index(row, 0, QModelIndex()), + index(row, 3, QModelIndex()) + ); + } } } ============================================================ --- src/model/GetBranchLog.h 60a32c3d8e56bdf26e1a426af0265f2654cd95de +++ src/model/GetBranchLog.h fb34c7f1a38c677e60b4945456567b104922e82e @@ -35,7 +35,8 @@ public: QString getCurrentBranch() const; QStringList getParents(const QString &) const; CertList getCerts(const QString &) const; - void invalidateCerts(const QString &); + void invalidateCertCache(const QString &); + void invalidateBranchCache(const QString &); // needed Qt Model methods QVariant data(const QModelIndex &, int) const; ============================================================ --- src/view/dialogs/ChangesetBrowser.cpp b0865decf7393809ac01fb964696001f2a8c90fc +++ src/view/dialogs/ChangesetBrowser.cpp 0bd8c4543e61ef1e17cfc742f5a94092287e70b4 @@ -22,6 +22,8 @@ #include #include +#include +#include ChangesetBrowser::ChangesetBrowser(QWidget * parent, const DatabaseFile & db) : Dialog(parent), databaseFile(db), branchModel(0) @@ -72,6 +74,16 @@ ChangesetBrowser::ChangesetBrowser(QWidg this, SLOT(branchViewClicked(const QModelIndex &)) ); + connect( + branchView, SIGNAL(suspendBranch(const QString &)), + this, SLOT(suspendBranch(const QString &)) + ); + + connect( + branchView, SIGNAL(reloadBranchList()), + branchModel, SLOT(readBranches()) + ); + changeLog->setKeyMap(MonotoneUtil::getPublicKeyMap(databaseFile)); branchLogModel = new GetBranchLog(this, databaseFile); @@ -390,8 +402,96 @@ void ChangesetBrowser::closeEvent(QClose event->accept(); } -void ChangesetBrowser::invalidateCerts(const QString & revision) +void ChangesetBrowser::handleCertCreation(const QString & revision, + const QString & certName, + const QString & certValue, + const QString & key) { - branchLogModel->invalidateCerts(revision); + Q_UNUSED(key); + + if (certName == "suspend") + { + branchModel->markBranchSuspended(certValue); + branchLogModel->invalidateBranchCache(certValue); + branchLogModel->invalidateCertCache(revision); + } + else + { + branchLogModel->invalidateCertCache(revision); + } } +void ChangesetBrowser::suspendBranch(const QString & branch) +{ + // since suspend certs are ignored by default already, we should not + // need to check if the returned revisions have already been suspended + QStringList revisions = + MonotoneUtil::resolveSelector(databaseFile, "h:" + branch); + + if (revisions.size() == 0) + { + QMessageBox::critical( + this, + tr("Branch is empty"), + tr("The branch '%1' is empty - maybe all heads " + "have already been suspended?").arg(branch), + QMessageBox::Ok + ); + return; + } + + QMap privateKeys = + MonotoneUtil::getPrivateKeyMap(databaseFile); + + if (privateKeys.size() == 0) + { + QMessageBox::critical( + this, + tr("No private key found"), + tr("There are no private keys available with which to sign your " + "suspend cert(s). Please go to Database > Key Management and " + "create a new private key first."), + QMessageBox::Ok + ); + return; + } + + QString key; + if (privateKeys.size() > 1) + { + bool ok; + QString keyname = QInputDialog::getItem( + this, + tr("Multiple private keys found"), + tr("Please select the private key with which you want " + "to sign the suspend cert(s):"), + QStringList(privateKeys.values()), + 0, false, &ok + ); + if (!ok) + return; + + key = privateKeys.key(keyname); + } + else + { + key = privateKeys.begin().key(); + } + + foreach (const QString & revision, revisions) + { + if (!MonotoneUtil::createCert(databaseFile, revision, "suspend", branch, key)) + { + QMessageBox::critical( + this, + tr("Cert creation failed"), + tr("Could not create certificate. Please check the logs for details."), + QMessageBox::Ok + ); + return; + } + + emit certCreated(revision, "suspend", branch, key); + } +} + ============================================================ --- src/view/dialogs/ChangesetBrowser.h ae5ea7b80db4220b1c4f6dab9814da35a6eae401 +++ src/view/dialogs/ChangesetBrowser.h 2af4dcc3a6843e8545d98b7054fb7c9b398e7aaa @@ -43,9 +43,10 @@ signals: void diffFile(const QString &, const QString &, const QString &); void annotateFile(const QString &, const QString &); void createCert(const QString &, const QString &); + void certCreated(const QString &, const QString &, const QString &, const QString &); public slots: - void invalidateCerts(const QString &); + void handleCertCreation(const QString &, const QString &, const QString &, const QString &); protected: void closeEvent(QCloseEvent *); @@ -66,7 +67,9 @@ private slots: void updateParentsList(); - private: + void suspendBranch(const QString &); + +private: DatabaseFile databaseFile; BranchesProxyModel * branchProxyModel; Branches * branchModel; ============================================================ --- src/view/dialogs/DatabaseDialogManager.cpp 9fd20e3bd733cf36a534882f32eaaa7c1095c225 +++ src/view/dialogs/DatabaseDialogManager.cpp 052e2022d9c33fe5a22d8ada9d29dcaa8dc13c4e @@ -81,6 +81,13 @@ void DatabaseDialogManager::showChangese changesetBrowser = new ChangesetBrowser(parentWidget(), databaseFile); connect( + changesetBrowser, SIGNAL(certCreated(const QString &, const QString &, + const QString &, const QString &)), + this, SIGNAL(certCreated(const QString &, const QString &, + const QString &, const QString &)) + ); + + connect( changesetBrowser, SIGNAL(revisionManifest(const QString &)), this, SLOT(showRevisionManifest(const QString &)) ); @@ -108,7 +115,8 @@ void DatabaseDialogManager::showChangese connect( this, SIGNAL(certCreated(const QString &, const QString &, const QString &, const QString &)), - changesetBrowser, SLOT(invalidateCerts(const QString &)) + changesetBrowser, SLOT(handleCertCreation(const QString &, const QString &, + const QString &, const QString &)) ); } ============================================================ --- src/view/widgets/BranchView.cpp 62590eb879a129b84bd7c81464c6fba5233a6e5e +++ src/view/widgets/BranchView.cpp df060172ca18afedc0ab1e936f69cfb86590d9aa @@ -21,21 +21,19 @@ BranchView::BranchView(QWidget * parent) BranchView::BranchView(QWidget * parent) : TreeView(parent) { - popupMenu = new QMenu(); - setRootIsDecorated(false); setItemsExpandable(true); - QAction * toggleTree = new QAction(tr("display branches as tree"), this); - toggleTree->setCheckable(true); - toggleTree->setData(toggle_tree); - popupMenu->addAction(toggleTree); + actSuspendBranch = new QAction(tr("suspend this branch"), this); - QAction * toggleSuspended = new QAction(tr("show suspended branches"), this); - toggleSuspended->setCheckable(true); - toggleSuspended->setData(toggle_suspended); - popupMenu->addAction(toggleSuspended); + actDisplayAsTree = new QAction(tr("display branches as tree"), this); + actDisplayAsTree->setCheckable(true); + actShowSuspended = new QAction(tr("show suspended branches"), this); + actShowSuspended->setCheckable(true); + + actReloadList = new QAction(tr("reload branches"), this); + connect( this, SIGNAL(contextMenuRequested(const QModelIndexList &, const QPoint &)), this, SLOT(slotContextMenuRequested(const QModelIndexList &, const QPoint &)) @@ -44,27 +42,53 @@ BranchView::~BranchView() BranchView::~BranchView() { - delete popupMenu; + delete actSuspendBranch; + delete actDisplayAsTree; + delete actShowSuspended; + delete actReloadList; } void BranchView::slotContextMenuRequested(const QModelIndexList & indexes, const QPoint & pt) { - Q_UNUSED(indexes); + QModelIndex index; + if (indexes.size() > 0) + index = indexes.at(0); - QAction * act = popupMenu->exec(pt); + QMenu popupMenu; - if (act == 0) - return; + if (index.isValid() && !index.data(Qt::UserRole).toBool()) + { + popupMenu.addAction(actSuspendBranch); + popupMenu.addSeparator(); + } - if (act->data().toInt() == toggle_tree) + popupMenu.addAction(actDisplayAsTree); + popupMenu.addAction(actShowSuspended); + popupMenu.addSeparator(); + popupMenu.addAction(actReloadList); + + QAction * act = popupMenu.exec(pt); + + if (act == actSuspendBranch) { + I(index.isValid()); + emit suspendBranch(index.data(Qt::ToolTipRole).toString()); + } + else + if (act == actDisplayAsTree) + { emit displayBranchesAsTree(act->isChecked()); } else - if (act->data().toInt() == toggle_suspended) + if (act == actShowSuspended) { emit showSuspendedBranches(act->isChecked()); } + else + if (act == actReloadList) + { + emit reloadBranchList(); + } } ============================================================ --- src/view/widgets/BranchView.h 9c5e1248688a2729c1e96c6de1463ecbd906fd45 +++ src/view/widgets/BranchView.h ae0d3f7ebea4e65ce3a8f477881593bf40705146 @@ -30,15 +30,19 @@ signals: ~BranchView(); signals: + void suspendBranch(const QString &); void displayBranchesAsTree(bool); void showSuspendedBranches(bool); + void reloadBranchList(); private slots: void slotContextMenuRequested(const QModelIndexList &, const QPoint &); private: - QMenu * popupMenu; - enum { toggle_tree, toggle_suspended } action; + QAction * actSuspendBranch; + QAction * actDisplayAsTree; + QAction * actShowSuspended; + QAction * actReloadList; }; #endif