# # # patch "res/forms/dialogs/changeset_browser.ui" # from [af8778a57187e81545e76be62629c2bbb7722347] # to [715176abd5b2dd44f77eb144f2708726635b10af] # # patch "res/forms/dialogs/create_cert.ui" # from [71eaa2f7fce2a6ee447593d7c87833174c078b8f] # to [48376187f7412990ee83134bf20649f1fccee835] # # patch "src/model/GetBranchLog.cpp" # from [56afc57e9129674fa09fe2bedfed7f32dab5c20c] # to [c6c392250d7e5835c7b8b3923b20a7a99899d35f] # # patch "src/model/GetBranchLog.h" # from [97000c8ec8f60f975c9d6a2a9f0d35edf6d4e863] # to [8c6b149a3d9ad230eb4ca690641a5f9def40b94e] # # patch "src/view/dialogs/ChangesetBrowser.cpp" # from [d073f6a120f33c2aa2912d1fafe96e59cd713696] # to [f6eb52560513763c1104eb48c8739c8275b54ace] # # patch "src/view/dialogs/ChangesetBrowser.h" # from [2b802dfbe7d0b78c79722dc5803b63b104ccfb30] # to [e3e968d6eb92455c2397370254a986138f2fbf80] # # patch "src/view/dialogs/CreateCert.cpp" # from [05238fd66b0cee0254fee998b842d86ca318dfc8] # to [ac94b7b337dad8ddffb2ed525df90360bd54e261] # # patch "src/view/dialogs/CreateCert.h" # from [01ecab2ec3ad9bdd66c164f6ef547749079d1230] # to [3252da5f64e71bb138f3450c7d9ed48066f9382b] # # patch "src/view/dialogs/DatabaseDialogManager.cpp" # from [8ee187423848967f7ac8ed5155761d5033da7506] # to [ed1529ba7e99b5c50809084dae59b68e567de617] # # patch "src/view/dialogs/DatabaseDialogManager.h" # from [54603a3a6e7ef08dc551533ef451e75e517e6a33] # to [6fcc736dab49c005d9e30c7ee5d53978f2d09c83] # ============================================================ --- res/forms/dialogs/changeset_browser.ui af8778a57187e81545e76be62629c2bbb7722347 +++ res/forms/dialogs/changeset_browser.ui 715176abd5b2dd44f77eb144f2708726635b10af @@ -33,9 +33,6 @@ 5 - - 0 - @@ -314,7 +311,7 @@ QPushButton:pressed, QPushButton:checked - + true @@ -371,6 +368,11 @@ QPushButton:pressed, QPushButton:checked
Splitter.h
1 + + CertListBrowser + QTextBrowser +
CertListBrowser.h
+
============================================================ --- res/forms/dialogs/create_cert.ui 71eaa2f7fce2a6ee447593d7c87833174c078b8f +++ res/forms/dialogs/create_cert.ui 48376187f7412990ee83134bf20649f1fccee835 @@ -6,61 +6,90 @@ 0 0 - 397 - 248 + 428 + 286 + + + 0 + 0 + + Create a new certificate - + - + Revision + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + - - - - - true - - - - - - - Select - - - - + + + + 200 + 0 + + + + true + + + + + + Select + + + - + + + 0 + - false + true + + QComboBox::AdjustToContents + - - - false + + + Qt::Vertical - + + QSizePolicy::MinimumExpanding + + + + 20 + 0 + + + - + + + 0 + @@ -81,9 +110,12 @@ Sign with key + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter +
- + ============================================================ --- src/model/GetBranchLog.cpp 56afc57e9129674fa09fe2bedfed7f32dab5c20c +++ src/model/GetBranchLog.cpp c6c392250d7e5835c7b8b3923b20a7a99899d35f @@ -40,6 +40,22 @@ QStringList GetBranchLog::getParents(con return QStringList(); } +CertList GetBranchLog::getCerts(const QString & rev) const +{ + return certMap.value(rev); +} + +void GetBranchLog::invalidateCerts(const QString & rev) +{ + if (certMap.contains(rev)) + { + certMap.remove(rev); + + MonotoneTaskPtr task(new MonotoneTask(QStringList() << "certs" << rev)); + AutomateCommand::enqueueDatabaseTask(databaseFile, task); + } +} + void GetBranchLog::readAll(const QString & branch) { readMore(branch, -1); @@ -240,21 +256,6 @@ QVariant GetBranchLog::data(const QModel QString rev = revisionMap[currentBranch].at(row); - if (role == Qt::UserRole) - { - if (certMap.contains(rev)) - { - QList changeLogCerts = certMap[rev].findByName("changelog"); - QStringList changeLogs; - foreach (Cert cert, changeLogCerts) - { - changeLogs.push_back(cert.htmlValue()); - } - - return QVariant(changeLogs.join("\n
\n")); - } - } - if (role == Qt::ForegroundRole) { if (certMap.contains(rev)) ============================================================ --- src/model/GetBranchLog.h 97000c8ec8f60f975c9d6a2a9f0d35edf6d4e863 +++ src/model/GetBranchLog.h 8c6b149a3d9ad230eb4ca690641a5f9def40b94e @@ -33,6 +33,8 @@ public: ~GetBranchLog(); QStringList getParents(const QString &) const; + CertList getCerts(const QString &) const; + void invalidateCerts(const QString &); // needed Qt Model methods QVariant data(const QModelIndex &, int) const; ============================================================ --- src/view/dialogs/ChangesetBrowser.cpp d073f6a120f33c2aa2912d1fafe96e59cd713696 +++ src/view/dialogs/ChangesetBrowser.cpp f6eb52560513763c1104eb48c8739c8275b54ace @@ -18,6 +18,7 @@ #include "ChangesetBrowser.h" #include "Settings.h" +#include "MonotoneUtil.h" #include #include @@ -46,6 +47,8 @@ ChangesetBrowser::ChangesetBrowser(QWidg initTreeWidget(); + changeLog->setKeyMap(MonotoneUtil::getPublicKeyMap(databaseFile)); + connect( branches, SIGNAL(clicked(const QModelIndex &)), this, SLOT(branchesClicked(const QModelIndex &)) @@ -191,7 +194,7 @@ void ChangesetBrowser::changesetsClicked { QModelIndex revIdx = branchLogModel->index(idx.row(), 3, QModelIndex()); currentRevision = branchLogModel->data(revIdx, Qt::DisplayRole).toString(); - changeLog->setHtml(branchLogModel->data(revIdx, Qt::UserRole).toString()); + changeLog->setCertList(branchLogModel->getCerts(currentRevision)); revisionModel->readDatabaseRevision(databaseFile, currentRevision); revisionParents->clear(); multipleParents->setVisible(false); @@ -270,6 +273,8 @@ void ChangesetBrowser::changesetsContext QAction * actOpenManifest = menu.addAction(tr("View files in this revision")); QAction * actCopyRevisionId = menu.addAction(tr("Copy revision ID")); + menu.addSeparator(); + QAction * actAddCert = menu.addAction(tr("Add tag or other certificate")); if (actParentDiff.size() == 0) { @@ -292,7 +297,12 @@ void ChangesetBrowser::changesetsContext clipboard->setText(rev); } else + if (act == actAddCert) { + emit createCert(rev, "tag"); + } + else + { int pos = actParentDiff.indexOf(act); if (pos != -1) { @@ -364,7 +374,6 @@ void ChangesetBrowser::revisionViewConte else I(false); - if (label.data().toString() != QObject::tr("Patched")) return; @@ -393,3 +402,8 @@ void ChangesetBrowser::closeEvent(QClose event->accept(); } +void ChangesetBrowser::invalidateCerts(const QString & revision) +{ + branchLogModel->invalidateCerts(revision); +} + ============================================================ --- src/view/dialogs/ChangesetBrowser.h 2b802dfbe7d0b78c79722dc5803b63b104ccfb30 +++ src/view/dialogs/ChangesetBrowser.h e3e968d6eb92455c2397370254a986138f2fbf80 @@ -39,7 +39,11 @@ signals: void diffRevision(const QString &, const QString &, const QString &); void diffFile(const QString &, const QString &, const QString &); void annotateFile(const QString &, const QString &); + void createCert(const QString &, const QString &); +public slots: + void invalidateCerts(const QString &); + protected: void closeEvent(QCloseEvent *); ============================================================ --- src/view/dialogs/CreateCert.cpp 05238fd66b0cee0254fee998b842d86ca318dfc8 +++ src/view/dialogs/CreateCert.cpp ac94b7b337dad8ddffb2ed525df90360bd54e261 @@ -19,6 +19,8 @@ #include "CreateCert.h" #include "MonotoneUtil.h" +#include + CreateCert::CreateCert(QWidget * parent, const DatabaseFile & db) : Dialog(parent), database(db) { @@ -30,10 +32,6 @@ CreateCert::CreateCert(QWidget * parent, name->addItem(tr("Comment"), "comment"); name->addItem(tr("Custom..."), ""); - type->addItem(tr("single line"), "single"); - type->addItem(tr("multi line"), "multi"); - type->addItem(tr("boolean"), "boolean"); - nameTypeMap.insert("tag", "single"); nameTypeMap.insert("testresult", "boolean"); nameTypeMap.insert("comment", "multi"); @@ -47,55 +45,72 @@ CreateCert::CreateCert(QWidget * parent, this, SLOT(nameIndexChanged(int)) ); - init(); + connect( + btnSelectRevision, SIGNAL(clicked()), + this, SIGNAL(selectRevision()) + ); } CreateCert::~CreateCert() {} -void CreateCert::init(const QString & certName) +void CreateCert::init(const QString & rev, const QString & certName) { signingKey->clear(); QMap privateKeys = - MonotoneUtil::getPrivateKeyMap(db); + MonotoneUtil::getPrivateKeyMap(database); + if (privateKeys.size() == 0) + { + QMessageBox::critical( + this, + tr("No private key found"), + tr("There are no private keys available with which to sign your " + "certificate. Please go to Database > Key Management and " + "create a new private key first."), + QMessageBox::Ok + ); + done(0); + return; + } + QMapIterator it(privateKeys); - for (; it.hasNext(); it.next()) + while (it.hasNext()) { + it.next(); signingKey->addItem(it.value(), it.key()); } + revision->setText(rev); selectCertName(certName); } -void CreateCert::selectCertName(const QString & name) +void CreateCert::selectCertName(const QString & certName) { - bool knownName = nameTypeMap.contains(name); - QString typeValue = knownName ? nameTypeMap.value(name) : "single"; + bool knownName = nameTypeMap.contains(certName); + QString typeValue = knownName ? nameTypeMap.value(certName) : "single"; - int pos = type->findData(typeValue); - I(pos >= 0); - - type->setCurrentIndex(pos); - type->setEnabled(!knownName); - QMapIterator it(typeWidgetMap); - for (; it.hasNext(); it.next()) + while (it.hasNext()) { + it.next(); it.value()->setVisible(false); } I(typeWidgetMap.contains(typeValue)); typeWidgetMap.value(typeValue)->setVisible(true); + resize(sizeHint()); + if (!knownName) { - name->setEditable(true); - name->setCurrentText("x-"); + name->lineEdit()->setReadOnly(false); + name->setCurrentIndex(name->findData("")); + name->lineEdit()->setText("x-"); } else { - name->setEditable(false); + name->lineEdit()->setReadOnly(true); } } @@ -106,3 +121,84 @@ void CreateCert::nameIndexChanged(int po selectCertName(certName); } +void CreateCert::setSelectedRevision(const QString & rev) +{ + revision->setText(rev); +} + +void CreateCert::accept() +{ + QString certName = name->itemData(name->currentIndex()).toString(); + if (certName.isEmpty()) + { + certName = name->currentText(); + if (certName.isEmpty()) + { + QMessageBox::critical( + this, + tr("No name for certificate"), + tr("Please select a name for the certificate or enter one."), + QMessageBox::Ok + ); + return; + } + + if (certName.indexOf(QRegExp("^x(-+[a-zA-Z0-9]+)+$")) != 0) + { + QMessageBox::critical( + this, + tr("Invalid certificate name"), + tr("Custom certificates should always start with 'x-' and " + "should only contain ASCII letters, numbers and dashes."), + QMessageBox::Ok + ); + return; + } + } + + QString certValue; + if (certName == "testresult") + { + certValue = booleanValue->isChecked() ? "true" : "false"; + } + else + if (certName == "comment") + { + certValue = multiLineValue->toPlainText(); + } + else + { + certValue = singleLineValue->text(); + } + + certValue = certValue.trimmed(); + + if (certValue.isEmpty()) + { + QMessageBox::critical( + this, + tr("Empty certificate value"), + tr("Please enter a non-empty certificate value."), + QMessageBox::Ok + ); + return; + } + + QString rev = revision->text(); + QString key = signingKey->itemData(signingKey->currentIndex()).toString(); + + if (!MonotoneUtil::createCert(database, rev, certName, certValue, key)) + { + QMessageBox::critical( + this, + tr("Cert creation failed"), + tr("Could not create certificate. Please check the logs for details."), + QMessageBox::Ok + ); + return; + } + + emit certCreated(rev, certName, certValue, key); + done(1); +} + ============================================================ --- src/view/dialogs/CreateCert.h 01ecab2ec3ad9bdd66c164f6ef547749079d1230 +++ src/view/dialogs/CreateCert.h 3252da5f64e71bb138f3450c7d9ed48066f9382b @@ -33,10 +33,12 @@ public: CreateCert(QWidget *, const DatabaseFile &); ~CreateCert(); - void init(const QString & certName = QString()); + void init(const QString &, const QString & certName = QString()); signals: void selectRevision(); + void certCreated(const QString &, const QString &, + const QString &, const QString &); public slots: void selectCertName(const QString &); @@ -50,6 +52,7 @@ private slots: private slots: void nameIndexChanged(int index); + void accept(); }; #endif ============================================================ --- src/view/dialogs/DatabaseDialogManager.cpp 8ee187423848967f7ac8ed5155761d5033da7506 +++ src/view/dialogs/DatabaseDialogManager.cpp ed1529ba7e99b5c50809084dae59b68e567de617 @@ -99,6 +99,17 @@ void DatabaseDialogManager::showChangese changesetBrowser, SIGNAL(annotateFile(const QString &, const QString &)), this, SLOT(showAnnotation(const QString &, const QString &)) ); + + connect( + changesetBrowser, SIGNAL(createCert(const QString &, const QString &)), + this, SLOT(showCreateCert(const QString &, const QString &)) + ); + + connect( + this, SIGNAL(certCreated(const QString &, const QString &, + const QString &, const QString &)), + changesetBrowser, SLOT(invalidateCerts(const QString &)) + ); } showDialog(changesetBrowser); @@ -354,9 +365,16 @@ void DatabaseDialogManager::showCreateCe this, SIGNAL(revisionSelected(const QString &)), createCert, SLOT(setSelectedRevision(const QString &)) ); + + connect( + createCert, SIGNAL(certCreated(const QString &, const QString &, + const QString &, const QString &)), + this, SIGNAL(certCreated(const QString &, const QString &, + const QString &, const QString &)) + ); } - createCert->init(certName); + createCert->init(rev, certName); showDialog(createCert); } ============================================================ --- src/view/dialogs/DatabaseDialogManager.h 54603a3a6e7ef08dc551533ef451e75e517e6a33 +++ src/view/dialogs/DatabaseDialogManager.h 6fcc736dab49c005d9e30c7ee5d53978f2d09c83 @@ -50,6 +50,8 @@ signals: void revisionCheckedOut(const QString &); void newProjectCreated(const QString &); void keypairGenerated(const QString &); + void certCreated(const QString &, const QString &, + const QString &, const QString &); public slots: void showChangesetBrowser();