# # # add_file "res/forms/dialogs/annotate.ui" # content [839c5a5809de9e5e4068a70480edcf919da79991] # # add_file "src/model/Annotate.cpp" # content [7a4d854c9c3abf7a9adfd6b6115a6be691e7b4b0] # # add_file "src/model/Annotate.h" # content [e9ce3f67005fb232769e9546289d06e05d990438] # # add_file "src/view/dialogs/AnnotateFile.cpp" # content [1edd1c4cfe1705865f6fe06566c61c8cc9d45548] # # add_file "src/view/dialogs/AnnotateFile.h" # content [685e5a17947635dbb3d8a90ef57f52ed030ef5de] # # patch "guitone.pro" # from [2c4b59235aaabdc70220a1008e72e6dd6c6a32a5] # to [f1810a37e0dc9125bfd25e8c94b29ec0f40a1e83] # # patch "src/view/dialogs/DatabaseDialogManager.cpp" # from [8eb586843e869bb306a69457e39499435a3b8761] # to [c10a551cff23278f9abbec80adc6e6f980dae650] # # patch "src/view/dialogs/DatabaseDialogManager.h" # from [29d744124aca70d56b42c1c4d11a4d585872bd7d] # to [b52f6da5ed64a9f9b354f0843e5e013a177ca23b] # # patch "src/view/dialogs/WorkspaceDialogManager.cpp" # from [9f10add1de839ff515bc18addc0f1d0c411e6476] # to [ef40f0ecdc9c58eed29e5f1eca307d4bd5853d15] # # patch "src/view/dialogs/WorkspaceDialogManager.h" # from [281d6f2d68e274a9eeeaddd738626bdd59bf170f] # to [31e363829c58f3e3e4c3488f158d88e5e13ba8e0] # # patch "src/view/mainwindows/WorkspaceWindow.cpp" # from [2a1b36678ab053784f449ed7c4540fb8a2268e9e] # to [7bfa8963e4dc39d2a1d07eedc843b31dbd720162] # # patch "src/view/widgets/InventoryView.cpp" # from [096d37b7f13cfb43d92d324f2f59082e072292a3] # to [a0f3acfdf95730b2384e1385334aa4bc82f0f543] # # patch "src/view/widgets/InventoryView.h" # from [dafe99dceceea43ffa850cd3a891eb29c916551e] # to [7ccc453cf7ac4036ad6f9ec23b7e9f5bda23690f] # ============================================================ --- res/forms/dialogs/annotate.ui 839c5a5809de9e5e4068a70480edcf919da79991 +++ res/forms/dialogs/annotate.ui 839c5a5809de9e5e4068a70480edcf919da79991 @@ -0,0 +1,197 @@ + + + AnnotateFile + + + + 0 + 0 + 566 + 646 + + + + Annotation of %1 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Base revision: + + + + + + + + 0 + 0 + + + + + 150 + 0 + + + + true + + + + + + + Select + + + + + + + + + Qt::Vertical + + + + + 0 + 400 + + + + QAbstractItemView::NoEditTriggers + + + false + + + false + + + false + + + true + + + false + + + + + Details + + + + + + + + + + + + + + + + 0 + + + + + Loading annotation + + + + + + + + 0 + 0 + + + + + 200 + 0 + + + + 0 + + + + + + + + + + Qt::Horizontal + + + + 0 + 20 + + + + + + + + Close + + + + + + + + + + TreeView + QTreeView +
TreeView.h
+
+
+ + + + pushButton + clicked() + AnnotateFile + accept() + + + 553 + 604 + + + 394 + 441 + + + + +
============================================================ --- src/model/Annotate.cpp 7a4d854c9c3abf7a9adfd6b6115a6be691e7b4b0 +++ src/model/Annotate.cpp 7a4d854c9c3abf7a9adfd6b6115a6be691e7b4b0 @@ -0,0 +1,210 @@ +/*************************************************************************** + * Copyright (C) 2010 by Thomas Keller * + * address@hidden * + * * + * 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 3 of the License, or * + * (at your option) any later version. * + * * + * 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 . * + ***************************************************************************/ + +#include "Annotate.h" +#include "MonotoneUtil.h" +#include "Settings.h" + +#include + +Annotate::Annotate(QObject * parent) + : QAbstractItemModel(parent), proc(0) +{ + proc = new MonotoneProcess(); + connect( + proc, SIGNAL(finished(int, QProcess::ExitStatus)), + this, SLOT(processFinished(int, QProcess::ExitStatus)) + ); +} + +Annotate::~Annotate() +{ + if (proc) delete proc; +} + +void Annotate::readAnnotation(const DatabaseFile & db, + const QString & rev, + const QString & file) +{ + brushMap.clear(); + inverseBrushMap.clear(); + annotationLines.clear(); + reset(); + + databaseFile = db; + proc->start( + QStringList() << "annotate" << "-d" << db + << "-r" << rev << "--revs-only" << file + ); +} + +void Annotate::processFinished(int exitCode, QProcess::ExitStatus exitStatus) +{ + QString output(proc->getBufferedOutput()); + if (exitCode != 0 || exitStatus != QProcess::NormalExit) + { + C(QString("Could not read annotation: %1").arg(output)); + return; + } + + QStringList lines = output.split('\n', QString::SkipEmptyParts); + + QRegExp rx("([0-9a-f]{40}):"); + + QSet revisions; + QString lastRevision; + + foreach (QString line, lines) + { + if (line.indexOf(rx) != 0) + { + W(QString("Could not parse annotation line: %1").arg(line)); + continue; + } + + QString code = line.mid(rx.matchedLength() + 1); + QString revision = rx.cap(1); + bool showAnnotation = revision != lastRevision; + lastRevision = revision; + + annotationLines.append( + Annotation(revision, code, showAnnotation) + ); + revisions.insert(revision); + } + + QStringList sortedRevisions = + MonotoneUtil::topsortRevisions(databaseFile, revisions.toList()); + + QColor startColor = QColor(Settings::getString("AnnotationColorOldestRevision")); + QColor endColor = QColor(Settings::getString("AnnotationColorNewestRevision")); + + float rStep = (endColor.redF() - startColor.redF()) / sortedRevisions.size(); + float gStep = (endColor.greenF() - startColor.greenF()) / sortedRevisions.size(); + float bStep = (endColor.blueF() - startColor.blueF()) / sortedRevisions.size(); + float r = startColor.redF(), g = startColor.greenF(), b = startColor.blueF(); + + foreach (QString rev, sortedRevisions) + { + brushMap.insert(rev, QBrush(QColor::fromRgbF(r, g, b))); + inverseBrushMap.insert(rev, QBrush(QColor::fromRgbF(1.0 - r, 1.0 - g, 1.0 - b))); + + r += rStep; g += gStep; b += bStep; + } + + highlightBrush = QBrush(QColor( + Settings::getString("AnnotationColorHighlight") + )); + + reset(); + emit annotationRead(); +} + +int Annotate::columnCount(const QModelIndex & parent) const +{ + Q_UNUSED(parent); + return 2; +} + +QVariant Annotate::data(const QModelIndex & index, int role) const +{ + if (!index.isValid()) + { + return QVariant(); + } + + int row = index.row(), col = index.column(); + + if (row >= annotationLines.size()) + return QVariant(); + + Annotation ann = annotationLines.at(row); + + if (role == Qt::BackgroundRole && col == 0) + { + return QVariant(brushMap.value(ann.revision)); + } + + if (role == Qt::ForegroundRole && col == 0) + { + return QVariant(inverseBrushMap.value(ann.revision)); + } + + if (role == Qt::BackgroundRole && col == 1 && ann.revision == selectedRevision) + { + return QVariant(highlightBrush); + } + + return ann.data(col, role); +} + +Qt::ItemFlags Annotate::flags(const QModelIndex & index) const +{ + if (index.isValid()) + { + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; + } + return 0; +} + +QVariant Annotate::headerData(int section, Qt::Orientation orientation, int role) const +{ + Q_UNUSED(section); + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) + { + switch (section) + { + case 0: return QVariant(tr("Annotation")); + case 1: return QVariant(tr("Code")); + } + return QVariant(); + } + return QVariant(); +} + +int Annotate::rowCount(const QModelIndex & parent) const +{ + Q_UNUSED(parent); + return annotationLines.size(); +} + +QModelIndex Annotate::index(int row, int column, const QModelIndex & parent) const +{ + if (!hasIndex(row, column, parent)) + { + return QModelIndex(); + } + + return createIndex(row, column, 0); +} + +QModelIndex Annotate::parent(const QModelIndex & index) const +{ + Q_UNUSED(index); + return QModelIndex(); +} + +void Annotate::setSelectedRevision(const QString & rev) +{ + if (selectedRevision != rev) + { + selectedRevision = rev; + reset(); + } +} + ============================================================ --- src/model/Annotate.h e9ce3f67005fb232769e9546289d06e05d990438 +++ src/model/Annotate.h e9ce3f67005fb232769e9546289d06e05d990438 @@ -0,0 +1,114 @@ +/*************************************************************************** + * Copyright (C) 2010 Thomas Keller * + * address@hidden * + * * + * 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 3 of the License, or * + * (at your option) any later version. * + * * + * 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 . * + ***************************************************************************/ + +#ifndef ANNOTATE_H +#define ANNOTATE_H + +#include +#include +#include +#include > +#include "MonotoneProcess.h" +#include "vocab.h" + +struct Annotation +{ + QString revision; + QString code; + bool show_info; + + QFont annotationFont; + QFont codeFont; + + Annotation(QString rev, QString c, bool s) + : revision(rev), code(c), show_info(s) + { + annotationFont.setPointSize(10); + + codeFont.setStyleHint(QFont::Courier); + codeFont.setFamily("Courier"); + } + + QVariant data(int col, int role) const + { + if (role == Qt::DisplayRole) + { + if (col == 0) + { + if (!show_info) return QVariant(); + return QVariant(revision); + } + + if (col == 1) + return QVariant(code); + } + + if (role == Qt::FontRole) + { + if (col == 0) + return QVariant(annotationFont); + + if (col == 1) + return QVariant(codeFont); + } + + if (role == Qt::UserRole) + { + return QVariant(revision); + } + + return QVariant(); + } +}; + +class Annotate : public QAbstractItemModel +{ + Q_OBJECT +public: + Annotate(QObject *); + virtual ~Annotate(); + + // needed Qt Model methods + QVariant data(const QModelIndex &, int) const; + Qt::ItemFlags flags(const QModelIndex &) const; + QVariant headerData(int, Qt::Orientation, int) const; + QModelIndex index(int, int, const QModelIndex &) const; + QModelIndex parent(const QModelIndex &) const; + int rowCount(const QModelIndex &) const; + int columnCount(const QModelIndex &) const; + +public slots: + void readAnnotation(const DatabaseFile &, const QString &, const QString &); + void setSelectedRevision(const QString &); + +signals: + void annotationRead(); + +private: + DatabaseFile databaseFile; + QList annotationLines; + MonotoneProcess * proc; + QMap brushMap, inverseBrushMap; + QBrush highlightBrush; + QString selectedRevision; + +private slots: + void processFinished(int exitCode, QProcess::ExitStatus exitStatus); +}; + +#endif ============================================================ --- src/view/dialogs/AnnotateFile.cpp 1edd1c4cfe1705865f6fe06566c61c8cc9d45548 +++ src/view/dialogs/AnnotateFile.cpp 1edd1c4cfe1705865f6fe06566c61c8cc9d45548 @@ -0,0 +1,116 @@ +/*************************************************************************** + * Copyright (C) 2010 by Thomas Keller * + * address@hidden * + * * + * 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 3 of the License, or * + * (at your option) any later version. * + * * + * 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 . * + ***************************************************************************/ + +#include "AnnotateFile.h" +#include "MonotoneUtil.h" + +#include + +AnnotateFile::AnnotateFile(QWidget * parent) : Dialog(parent), annotateModel(0) +{ + setupUi(this); + Dialog::init(); + + annotateModel = new Annotate(this); + annotationView->setModel(annotateModel); + + connect( + annotateModel, SIGNAL(annotationRead()), + progressWidget, SLOT(hide()) + ); + + connect( + annotationView, SIGNAL(selectedRows(const QModelIndexList &)), + this, SLOT(rowsSelected(const QModelIndexList &)) + ); + + connect( + selectRevisionButton, SIGNAL(clicked()), + this, SIGNAL(selectRevision()) + ); + + progressWidget->hide(); +} + +AnnotateFile::~AnnotateFile() +{ + if (annotateModel) delete annotateModel; +} + +void AnnotateFile::forWorkspace(const WorkspacePath & workspace, const QString & file) +{ + forDatabase( + MonotoneUtil::getDatabaseFile(workspace), + MonotoneUtil::getBaseWorkspaceRevision(workspace), + file + ); +} + +void AnnotateFile::forDatabase(const DatabaseFile & db, const QString & rev, const QString & file) +{ + databaseFile = db; + filePath = file; + baseRevision->setText(rev); + + setWindowTitle(tr("Annotation of %1").arg(filePath)); + annotateModel->readAnnotation(databaseFile, rev, filePath); + progressWidget->show(); +} + +void AnnotateFile::setSelectedRevision(const QString & rev) +{ + QString newPath = MonotoneUtil::getCorrespondingPath( + databaseFile, baseRevision->text(), filePath, rev + ); + + if (newPath.isEmpty()) + { + QMessageBox::information( + this, + tr("File does not exist"), + tr("The file '%1' does not exist in the selected revision '%2'.") + .arg(filePath).arg(rev), + QMessageBox::Ok + ); + return; + } + + forDatabase(databaseFile, rev, newPath); +} + +void AnnotateFile::rowsSelected(const QModelIndexList & indexes) +{ + if (indexes.size() == 0) + { + return; + } + + QModelIndex selectedIndex = indexes.at(0); + QString rev = selectedIndex.data(Qt::UserRole).toString(); + annotateModel->setSelectedRevision(rev); + + // clear the selection so the text under the selected row gets + // easier readable. Beware that this fires this slot again and + // if the guard above which checks for no selected indexes is + // removed, then this leads to infinite recursion! + annotationView->selectionModel()->clearSelection(); + + // FIXME: temporary + changelog->setText(rev); +} + ============================================================ --- src/view/dialogs/AnnotateFile.h 685e5a17947635dbb3d8a90ef57f52ed030ef5de +++ src/view/dialogs/AnnotateFile.h 685e5a17947635dbb3d8a90ef57f52ed030ef5de @@ -0,0 +1,52 @@ +/*************************************************************************** + * Copyright (C) 2010 by Thomas Keller * + * address@hidden * + * * + * 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 3 of the License, or * + * (at your option) any later version. * + * * + * 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 . * + ***************************************************************************/ + +#ifndef ANNOTATE_FILE_H +#define ANNOTATE_FILE_H + +#include "Dialog.h" +#include "Annotate.h" +#include "Certs.h" +#include "ui_annotate.h" + +class AnnotateFile : public Dialog, private Ui::AnnotateFile +{ + Q_OBJECT + +public: + AnnotateFile(QWidget *); + ~AnnotateFile(); + +public slots: + void forWorkspace(const WorkspacePath &, const QString &); + void forDatabase(const DatabaseFile &, const QString &, const QString &); + void setSelectedRevision(const QString &); + +signals: + void selectRevision(); + +private: + Annotate * annotateModel; + DatabaseFile databaseFile; + QString filePath; + +private slots: + void rowsSelected(const QModelIndexList &); +}; + +#endif ============================================================ --- guitone.pro 2c4b59235aaabdc70220a1008e72e6dd6c6a32a5 +++ guitone.pro f1810a37e0dc9125bfd25e8c94b29ec0f40a1e83 @@ -67,6 +67,7 @@ HEADERS = src/view/widgets/TreeView.h \ src/view/dialogs/Netsync.h \ src/view/dialogs/NewProjectSetup.h \ src/view/dialogs/Message.h \ + src/view/dialogs/AnnotateFile.h \ src/view/panels/IconHelp.h \ src/view/panels/DatabaseVariables.h \ src/view/panels/NodeInfo.h \ @@ -101,6 +102,7 @@ HEADERS = src/view/widgets/TreeView.h \ src/model/GetRevision.h \ src/model/GetContentChanged.h \ src/model/GetDatabaseVariables.h \ + src/model/Annotate.h \ src/util/IconProvider.h \ src/util/AbstractParser.h \ src/util/BasicIOParser.h \ @@ -159,6 +161,7 @@ SOURCES += src/view/widgets/TreeView.cpp src/view/dialogs/Netsync.cpp \ src/view/dialogs/NewProjectSetup.cpp \ src/view/dialogs/Message.cpp \ + src/view/dialogs/AnnotateFile.cpp \ src/view/panels/IconHelp.cpp \ src/view/panels/DatabaseVariables.cpp \ src/view/panels/NodeInfo.cpp \ @@ -193,6 +196,7 @@ SOURCES += src/view/widgets/TreeView.cpp src/model/GetRevision.cpp \ src/model/GetContentChanged.cpp \ src/model/GetDatabaseVariables.cpp \ + src/model/Annotate.cpp \ src/util/IconProvider.cpp \ src/util/AbstractParser.cpp \ src/util/BasicIOParser.cpp \ @@ -231,6 +235,7 @@ FORMS += res/forms/dialogs/select_revi res/forms/dialogs/create_database.ui \ res/forms/dialogs/netsync.ui \ res/forms/dialogs/new_project_setup.ui \ + res/forms/dialogs/annotate.ui \ res/forms/panels/icon_help.ui \ res/forms/panels/db_variables.ui \ res/forms/panels/nodeinfo.ui ============================================================ --- src/view/dialogs/DatabaseDialogManager.cpp 8eb586843e869bb306a69457e39499435a3b8761 +++ src/view/dialogs/DatabaseDialogManager.cpp c10a551cff23278f9abbec80adc6e6f980dae650 @@ -23,7 +23,8 @@ DatabaseDialogManager::DatabaseDialogMan : DialogManager(parent), changesetBrowser(0), checkoutRevision(0), fileDiff(0), fileHistory(0), generateKeypair(0), netsync(0), keyManagement(0), revisionDiff(0), - revisionManifest(0), selectRevision(0), newProjectSetup(0) + revisionManifest(0), selectRevision(0), newProjectSetup(0), + annotateFile(0) {} DatabaseDialogManager::~DatabaseDialogManager() @@ -44,6 +45,7 @@ void DatabaseDialogManager::cleanup() if (revisionManifest) { delete revisionManifest; revisionManifest = 0; } if (selectRevision) { delete selectRevision; selectRevision = 0; } if (newProjectSetup) { delete newProjectSetup; newProjectSetup = 0; } + if (annotateFile) { delete annotateFile; annotateFile = 0; } } void DatabaseDialogManager::closeAllDialogs() @@ -59,6 +61,7 @@ void DatabaseDialogManager::closeAllDial if (revisionManifest) revisionManifest->close(); if (selectRevision) selectRevision->close(); if (newProjectSetup) newProjectSetup->close(); + if (annotateFile) annotateFile->close(); DialogManager::closeAllDialogs(); } @@ -231,6 +234,11 @@ void DatabaseDialogManager::showRevision showDialog(revisionManifest); } +void DatabaseDialogManager::showSelectRevision() +{ + showSelectRevision(QString()); +} + void DatabaseDialogManager::showSelectRevision(const QString & selector) { if (!selectRevision) @@ -278,3 +286,24 @@ void DatabaseDialogManager::showNewProje showDialog(newProjectSetup); } +void DatabaseDialogManager::showAnnotation(const QString & rev, const QString & file) +{ + if (!annotateFile) + { + annotateFile = new AnnotateFile(parentWidget()); + + connect( + annotateFile, SIGNAL(selectRevision(const QString &)), + this, SLOT(showSelectRevision(const QString &)) + ); + + connect( + this, SIGNAL(revisionSelected(const QString &)), + annotateFile, SLOT(setSelectedRevision(const QString &)) + ); + } + + annotateFile->forDatabase(databaseFile, rev, file); + showDialog(annotateFile); +} + ============================================================ --- src/view/dialogs/DatabaseDialogManager.h 29d744124aca70d56b42c1c4d11a4d585872bd7d +++ src/view/dialogs/DatabaseDialogManager.h b52f6da5ed64a9f9b354f0843e5e013a177ca23b @@ -31,6 +31,7 @@ #include "RevisionManifest.h" #include "SelectRevision.h" #include "NewProjectSetup.h" +#include "AnnotateFile.h" class DatabaseDialogManager : public DialogManager { @@ -60,7 +61,9 @@ public slots: void showKeyManagement(); virtual void showRevisionDiff(const QString & path, const QString & base, const QString & target); void showRevisionManifest(const QString & revision); + void showSelectRevision(); void showSelectRevision(const QString & selector); + void showAnnotation(const QString &, const QString &); protected: ChangesetBrowser * changesetBrowser; @@ -74,6 +77,7 @@ protected: RevisionManifest * revisionManifest; SelectRevision * selectRevision; NewProjectSetup * newProjectSetup; + AnnotateFile * annotateFile; private: void cleanup(); ============================================================ --- src/view/dialogs/WorkspaceDialogManager.cpp 9f10add1de839ff515bc18addc0f1d0c411e6476 +++ src/view/dialogs/WorkspaceDialogManager.cpp ef40f0ecdc9c58eed29e5f1eca307d4bd5853d15 @@ -162,3 +162,24 @@ void WorkspaceDialogManager::showUpdateW showDialog(updateWorkspace); } +void WorkspaceDialogManager::showAnnotation(const QString & file) +{ + if (!annotateFile) + { + annotateFile = new AnnotateFile(parentWidget()); + + connect( + annotateFile, SIGNAL(selectRevision()), + this, SLOT(showSelectRevision()) + ); + + connect( + this, SIGNAL(revisionSelected(const QString &)), + annotateFile, SLOT(setSelectedRevision(const QString &)) + ); + } + + annotateFile->forWorkspace(workspacePath, file); + showDialog(annotateFile); +} + ============================================================ --- src/view/dialogs/WorkspaceDialogManager.h 281d6f2d68e274a9eeeaddd738626bdd59bf170f +++ src/view/dialogs/WorkspaceDialogManager.h 31e363829c58f3e3e4c3488f158d88e5e13ba8e0 @@ -46,13 +46,14 @@ public slots: public slots: void showCommitRevision(); - void showCommitRevision(const QStringList & paths); + void showCommitRevision(const QStringList &); void checkForUnaccountedRenames(); void showUpdateWorkspace(); - void showFileDiff(const QString & file); - void showFileDiff(const QString & file, const QString & base, const QString & target); - void showFileHistory(const QString & file); - void showRevisionDiff(const QString & path, const QString & base, const QString & target); + void showFileDiff(const QString &); + void showFileDiff(const QString &, const QString &, const QString &); + void showFileHistory(const QString &); + void showRevisionDiff(const QString &, const QString &, const QString &); + void showAnnotation(const QString &); protected: CommitRevision * commitRevision; ============================================================ --- src/view/mainwindows/WorkspaceWindow.cpp 2a1b36678ab053784f449ed7c4540fb8a2268e9e +++ src/view/mainwindows/WorkspaceWindow.cpp 7bfa8963e4dc39d2a1d07eedc843b31dbd720162 @@ -163,6 +163,11 @@ void WorkspaceWindow::setup() ); connect( + listView, SIGNAL(annotateFile(const QString &)), + dialogManager, SLOT(showAnnotation(const QString &)) + ); + + connect( listView, SIGNAL(commitRevision(const QStringList &)), dialogManager, SLOT(showCommitRevision(const QStringList &)) ); ============================================================ --- src/view/widgets/InventoryView.cpp 096d37b7f13cfb43d92d324f2f59082e072292a3 +++ src/view/widgets/InventoryView.cpp a0f3acfdf95730b2384e1385334aa4bc82f0f543 @@ -151,6 +151,10 @@ void InventoryView::createAndConnectCont actRevisionDiff->setStatusTip(tr("Show all differences")); connect(actRevisionDiff, SIGNAL(triggered()), this, SLOT(slotRevisionDiff())); + actAnnotate = new QAction(tr("Annotate"), this); + actAnnotate->setStatusTip(tr("Annotates the contents of this file")); + connect(actAnnotate, SIGNAL(triggered()), this, SLOT(slotAnnotate())); + actRename = new QAction(tr("Rename"), this); actRename->setStatusTip(tr("Rename file")); connect(actRename, SIGNAL(triggered()), this, SLOT(slotRename())); @@ -209,6 +213,7 @@ InventoryView::~InventoryView() delete actFileDiff; delete actFileHistory; delete actRevisionDiff; + delete actAnnotate; delete actRename; delete actRefresh; delete actNewFile; @@ -424,6 +429,7 @@ void InventoryView::slotContextMenuReque invitem->hasNotStatus(InventoryItem::Added)) { menu.addAction(actFileHistory); + menu.addAction(actAnnotate); } } @@ -1007,6 +1013,19 @@ void InventoryView::slotRevisionDiff() emit diffRevision(invitem->getPath(), QString(), QString()); } +void InventoryView::slotAnnotate() +{ + QSet items = getSelectedItems(); + if (items.size() == 0) return; + + const InventoryItem * invitem = dynamic_cast(*items.begin()); + + if (!invitem) + return; + + emit annotateFile(invitem->getPath()); +} + QString InventoryView::getNewPath(const QModelIndex & parent, const QString & prefix) { I(!prefix.isEmpty()); ============================================================ --- src/view/widgets/InventoryView.h dafe99dceceea43ffa850cd3a891eb29c916551e +++ src/view/widgets/InventoryView.h 7ccc453cf7ac4036ad6f9ec23b7e9f5bda23690f @@ -54,6 +54,7 @@ signals: void revertPaths(const QStringList &); void ignorePaths(const QStringList &); void unignorePaths(const QStringList &); + void annotateFile(const QString &); void newFile(const QString &); void newDirectory(const QString &); void deleteLocalPath(const QString &); @@ -85,6 +86,7 @@ private: QAction * actFileDiff; QAction * actFileHistory; QAction * actRevisionDiff; + QAction * actAnnotate; QAction * actRefresh; QAction * actNewFile; QAction * actNewDirectory; @@ -124,6 +126,7 @@ private slots: void slotFileDiff(); void slotFileHistory(); void slotRevisionDiff(); + void slotAnnotate(); void slotRefresh(); void slotNewFile(); void slotNewDirectory();