#
#
# add_file "res/forms/file_history.ui"
# content [1dda121627d78bc7d2eedd22f134c967ac4db66c]
#
# add_file "src/model/GetContentChanged.cpp"
# content [f3b84782ab44fdf363e2af70d5bee4b961afeefe]
#
# add_file "src/model/GetContentChanged.h"
# content [441bbf74054ad6b6c8d316db82096d3b62fcedb1]
#
# add_file "src/view/dialogs/FileHistory.cpp"
# content [822c638698d0c97987e1bc2c58e9a9e144391f84]
#
# add_file "src/view/dialogs/FileHistory.h"
# content [a55e76d5c71b96d4ed70a74ab97a4e5ebcec8fcc]
#
# patch "guitone.pro"
# from [aca01447662a0cd5ace5f48f12d15759f1f6cb17]
# to [62bc1f270a3784fd51110c8236bc2aac67344929]
#
# patch "src/monotone/MonotoneDelegate.cpp"
# from [84dbd3a0dff4a0ffddf39e6a7e25d1735d3b5f14]
# to [97e18875b8b50bf0d64b6e5d6bedfba1c77a24e6]
#
# patch "src/view/InventoryView.cpp"
# from [9ab95e9d6627610fb2567709fb8a912e93eeb281]
# to [058bd961e53ade94bbe566cf309f57a1ea3d4298]
#
# patch "src/view/InventoryView.h"
# from [0ad2ef23cc24538fcd3fd656b712f7b6dca17e3e]
# to [fd0d9c5eb87a628057d22b2a41426dcbbe84ca03]
#
============================================================
--- res/forms/file_history.ui 1dda121627d78bc7d2eedd22f134c967ac4db66c
+++ res/forms/file_history.ui 1dda121627d78bc7d2eedd22f134c967ac4db66c
@@ -0,0 +1,135 @@
+
+ FileHistoryDialog
+
+
+
+ 0
+ 0
+ 470
+ 372
+
+
+
+ History of %1
+
+
+ :/icons/guitone.png
+
+
+
+ 9
+
+
+ 6
+
+ -
+
+
+ 0
+
+
+ 6
+
+
-
+
+
+ Qt::Vertical
+
+
+
+ true
+
+
+ QAbstractItemView::SingleSelection
+
+
+ false
+
+
+ false
+
+
+
+
+ true
+
+
+ QAbstractItemView::NoSelection
+
+
+ false
+
+
+ false
+
+
+
+
+ -
+
+
+ 0
+
+
+ 6
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Close
+
+
+
+
+
+
+
+
+
+
+
+ TreeView
+ QTreeView
+
+
+
+ Splitter
+ QSplitter
+
+
+
+
+
+
+
+
+ closeButton
+ clicked()
+ FileHistoryDialog
+ close()
+
+
+ 229
+ 252
+
+
+ 199
+ 149
+
+
+
+
+
============================================================
--- src/model/GetContentChanged.cpp f3b84782ab44fdf363e2af70d5bee4b961afeefe
+++ src/model/GetContentChanged.cpp f3b84782ab44fdf363e2af70d5bee4b961afeefe
@@ -0,0 +1,338 @@
+/***************************************************************************
+ * Copyright (C) 2007 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 2 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, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include "GetContentChanged.h"
+#include "BasicIOParser.h"
+
+#include
+
+GetContentChanged::GetContentChanged(QObject *parent)
+ : QAbstractItemModel(parent)
+{
+ mtnDelegate = new MonotoneDelegate(this);
+}
+
+GetContentChanged::~GetContentChanged()
+{
+ revisions.clear();
+ delete mtnDelegate;
+}
+
+//
+// The basic flow is the following:
+//
+// [ workspace parent revision ] [ path in this revision ]
+// \ /
+// \ /
+// \ /
+// |
+// V
+// |---------------> [ get content changed ]
+// | |
+// | V
+// | [ add the rev(s) to the set ]
+// | |
+// | V
+// |------ < ------ [ get parents of rev(s) ] -> stop if no parents
+// | |
+// | V
+// | [ get corresponding path in the parent ] -> stop if no path
+// | |
+// -------------- < -------------
+//
+bool GetContentChanged::readChanges(const QString & path)
+{
+ // clear current attributes list
+ revisions.clear();
+ // reset the view
+ reset();
+
+ // find a starting point
+ // FIXME: we assume that the given path is part of this revision!
+ QString startRev = MonotoneDelegate::getBaseWorkspaceRevision(this);
+ Q_ASSERT(!startRev.isNull());
+ D(QString("Starting with %1").arg(startRev));
+
+ pathInRevision.insert(startRev, path);
+ startPath = path;
+
+ return queryContentChanged(startRev, path);
+}
+
+bool GetContentChanged::queryContentChanged(const QString & rev, const QString & path)
+{
+ D(QString("get_content_changed for %1 starting from %2").arg(path).arg(rev));
+
+ commandStack.enqueue(ContentChanged);
+
+ QStringList cmd;
+ cmd << "get_content_changed" << rev << path;
+ return mtnDelegate->triggerCommand(cmd);
+}
+
+bool GetContentChanged::queryParents(const QString & rev)
+{
+ D(QString("parents for %1").arg(rev));
+
+ commandStack.enqueue(Parents);
+ revisionStack.enqueue(rev);
+
+ QStringList cmd;
+ cmd << "parents" << rev;
+ return mtnDelegate->triggerCommand(cmd);
+}
+
+bool GetContentChanged::queryCorrespondingPath(const QString & par)
+{
+ commandStack.enqueue(CorrespondingPath);
+ Q_ASSERT(!revisionStack.isEmpty());
+ QString rev = revisionStack.dequeue();
+ Q_ASSERT(pathInRevision.contains(rev));
+ QString path = pathInRevision.value(rev);
+
+ D(QString("get_corresponding_path for %1, base %1, parent %2").arg(path).arg(rev).arg(par));
+
+ QStringList cmd;
+ cmd << "get_corresponding_path" << rev << path << par;
+ return mtnDelegate->triggerCommand(cmd);
+}
+
+
+void GetContentChanged::parseOutput()
+{
+ // this method is called when we either called get_content_changed,
+ // parents or get_corresponding_path
+ // to decide what to do next, we need to know what was triggered
+ // lately in the queue
+ Command current = commandStack.dequeue();
+
+ if (current == Parents)
+ {
+ if (AutomateCommand::data.isEmpty())
+ {
+ D("No parents found");
+
+ // no more commands in the queue? we're finished!
+ if (commandStack.size() == 0)
+ {
+ D("Finished");
+ reset();
+ emit changesRead();
+ }
+ return;
+ }
+
+ QStringList parents = AutomateCommand::data.split(
+ '\n', QString::SkipEmptyParts
+ );
+
+ D(QString("Found parents %1").arg(parents.join(",")));
+
+ foreach (QString par, parents)
+ {
+ parentStack.enqueue(par);
+ Q_ASSERT(queryCorrespondingPath(par));
+ }
+ return;
+ }
+
+ if (current == ContentChanged)
+ {
+ // since we're looking for a file in a certain revision
+ // _beforehand_ via get_corresponding_path, we should always
+ // get a stanza out here
+ BasicIOParser parser(AutomateCommand::data);
+ Q_ASSERT(parser.parse());
+ StanzaList stanzas = parser.getStanzas();
+ foreach (Stanza st, stanzas)
+ {
+ Q_ASSERT(st.size() == 1);
+ QString rev = st.at(0).hash;
+ Q_ASSERT(!rev.isNull());
+
+ D(QString("Next rev with content mark %1").arg(rev));
+
+ if (!revisions.contains(rev))
+ {
+ // ensure that the current revision is also in the
+ // set of known revisions for this file
+ if (revisions.size() > 0)
+ {
+ QString lastMarkedRev = revisions.last();
+ Q_ASSERT(pathInRevision.contains(lastMarkedRev));
+ QString lastPath = pathInRevision.value(lastMarkedRev);
+ pathInRevision.insert(rev, lastPath);
+ }
+ else
+ {
+ // apparently this is the first marked revision we
+ // encounter, assign the startPath to it
+ pathInRevision.insert(rev, startPath);
+ }
+
+ // now append the revision itself in the ordered list
+ revisions.append(rev);
+ }
+ Q_ASSERT(queryParents(rev));
+ }
+ return;
+ }
+
+ if (current == CorrespondingPath)
+ {
+ // check if the file exists in the current revision,
+ // if not, stop here
+ if (AutomateCommand::data.isEmpty())
+ {
+ D("No corresponding path");
+
+ // no more commands in the queue? we're finished!
+ if (commandStack.size() == 0)
+ {
+ D("Finished");
+ reset();
+ emit changesRead();
+ }
+ return;
+ }
+
+ BasicIOParser parser(AutomateCommand::data);
+ Q_ASSERT(parser.parse());
+ StanzaList stanzas = parser.getStanzas();
+ Q_ASSERT(stanzas.size() == 1);
+ Stanza st = stanzas.at(0);
+ Q_ASSERT(st.size() == 1);
+ StanzaEntry en = st.at(0);
+ Q_ASSERT(en.sym == "file" && en.vals.size() == 1);
+ QString path = en.vals.at(0);
+
+ D(QString("Found path %1").arg(path));
+
+ Q_ASSERT(!parentStack.isEmpty());
+ Q_ASSERT(queryContentChanged(parentStack.dequeue(), path));
+ return;
+ }
+
+ Q_ASSERT(false);
+}
+
+bool GetContentChanged::handleError(int retCode)
+{
+ if (retCode == 2)
+ {
+ Q_ASSERT(commandStack.size() > 0);
+
+ // FIXME: this is a big hack, since we assume that the only error 2
+ // we can get here for this command basically reads like
+ // file "foo" doesn't exists in revision "bar"
+ // but yeah, localized string parsing is stupid as well
+ if (commandStack.head() == CorrespondingPath)
+ {
+ AutomateCommand::data.clear();
+ parseOutput();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+int GetContentChanged::columnCount(const QModelIndex & parent) const
+{
+ return 2;
+}
+
+QVariant GetContentChanged::data(const QModelIndex & index, int role) const
+{
+ if (!index.isValid())
+ {
+ return QVariant();
+ }
+
+ int col = index.column();
+
+ if (role == Qt::FontRole && col == 0)
+ {
+ QFont font;
+ font.setStyleHint(QFont::Courier);
+ font.setFamily("Courier");
+ return QVariant(font);
+ }
+
+ if (role == Qt::DisplayRole)
+ {
+ int row = index.row();
+ if (row >= revisions.size()) return QVariant();
+ QString rev = revisions.at(row);
+ Q_ASSERT(pathInRevision.contains(rev));
+
+ switch (col)
+ {
+ case 0: return QVariant(rev);
+ case 1: return QVariant(pathInRevision.value(rev));
+ }
+ return QVariant();
+ }
+
+ return QVariant();
+}
+
+Qt::ItemFlags GetContentChanged::flags(const QModelIndex & index) const
+{
+ if (index.isValid())
+ {
+ return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
+ }
+ return 0;
+}
+
+QVariant GetContentChanged::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
+ {
+ switch (section)
+ {
+ case 0: return QVariant(tr("Revision ID"));
+ case 1: return QVariant(tr("Path"));
+ }
+ }
+ return QVariant();
+}
+
+int GetContentChanged::rowCount(const QModelIndex & parent) const
+{
+ return revisions.size();
+}
+
+QModelIndex GetContentChanged::index(int row, int column, const QModelIndex & parent) const
+{
+ if (!hasIndex(row, column, parent))
+ {
+ return QModelIndex();
+ }
+
+ return createIndex(row, column, 0);
+}
+
+QModelIndex GetContentChanged::parent(const QModelIndex & index) const
+{
+ return QModelIndex();
+}
+
============================================================
--- src/model/GetContentChanged.h 441bbf74054ad6b6c8d316db82096d3b62fcedb1
+++ src/model/GetContentChanged.h 441bbf74054ad6b6c8d316db82096d3b62fcedb1
@@ -0,0 +1,77 @@
+/***************************************************************************
+ * Copyright (C) 2007 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 2 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, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#ifndef GETCONTENTCHANGED_H
+#define GETCONTENTCHANGED_H
+
+#include "AutomateCommand.h"
+#include "MonotoneDelegate.h"
+
+#include
+#include
+#include
+
+typedef QList RevisionList;
+
+class GetContentChanged : public QAbstractItemModel, public AutomateCommand
+{
+ Q_OBJECT
+public:
+ GetContentChanged(QObject*);
+ virtual ~GetContentChanged();
+
+ // 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:
+ bool readChanges(const QString &);
+
+signals:
+ void changesRead();
+
+private:
+ bool queryContentChanged(const QString &, const QString &);
+ bool queryParents(const QString &);
+ bool queryCorrespondingPath(const QString &);
+
+ void parseOutput();
+ bool handleError(int);
+
+ RevisionList revisions;
+ MonotoneDelegate * mtnDelegate;
+
+ enum Command { ContentChanged, CorrespondingPath, Parents };
+
+ QQueue commandStack;
+ QQueue revisionStack;
+ QQueue parentStack;
+
+ QMap pathInRevision;
+ QString startPath;
+};
+
+#endif
+
============================================================
--- src/view/dialogs/FileHistory.cpp 822c638698d0c97987e1bc2c58e9a9e144391f84
+++ src/view/dialogs/FileHistory.cpp 822c638698d0c97987e1bc2c58e9a9e144391f84
@@ -0,0 +1,71 @@
+/***************************************************************************
+ * Copyright (C) 2006 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 2 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, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include "FileHistory.h"
+
+FileHistory::FileHistory(QWidget * parent, const QString & path): Dialog(parent)
+{
+ setupUi(this);
+ Dialog::init();
+
+ // OSX sheet-alike dialog
+ setWindowFlags(Qt::Sheet);
+
+ splitter->init();
+
+ changeModel = new GetContentChanged(this);
+ certsModel = new Certs(this);
+
+ // assign the models to the views
+ revisionList->setModel(changeModel);
+ certList->setModel(certsModel);
+
+ // display the certs of a selected revision on click
+ connect(
+ revisionList, SIGNAL(clicked(const QModelIndex &)),
+ this, SLOT(readCerts(const QModelIndex &))
+ );
+
+ QString title = windowTitle();
+ setWindowTitle(title.arg(path));
+
+ // read the changes
+ Q_ASSERT(changeModel->readChanges(path));
+}
+
+FileHistory::~FileHistory()
+{
+ delete changeModel;
+ delete certsModel;
+}
+
+void FileHistory::readCerts(const QModelIndex & index)
+{
+ if (!index.isValid()) return;
+
+ QModelIndex revIdx = changeModel->index(index.row(), 0, QModelIndex());
+ QString rev(revIdx.data().toString());
+
+ if (!certsModel->readCerts(rev))
+ {
+ C(QString("Couldn't read certs for %1").arg(rev));
+ }
+}
+
============================================================
--- src/view/dialogs/FileHistory.h a55e76d5c71b96d4ed70a74ab97a4e5ebcec8fcc
+++ src/view/dialogs/FileHistory.h a55e76d5c71b96d4ed70a74ab97a4e5ebcec8fcc
@@ -0,0 +1,45 @@
+/***************************************************************************
+ * Copyright (C) 2007 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 2 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, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#ifndef FILE_HISTORY_H
+#define FILE_HISTORY_H
+
+#include "Dialog.h"
+#include "ui_file_history.h"
+#include "Certs.h"
+#include "GetContentChanged.h"
+
+class FileHistory : public Dialog, private Ui::FileHistoryDialog
+{
+ Q_OBJECT
+
+public:
+ FileHistory(QWidget *, const QString &);
+ ~FileHistory();
+
+private:
+ GetContentChanged * changeModel;
+ Certs * certsModel;
+
+private slots:
+ void readCerts(const QModelIndex &);
+};
+
+#endif
============================================================
--- guitone.pro aca01447662a0cd5ace5f48f12d15759f1f6cb17
+++ guitone.pro 62bc1f270a3784fd51110c8236bc2aac67344929
@@ -36,6 +36,7 @@ HEADERS += src/view/MainWindow.h \
src/view/dialogs/ChangesetBrowser.h \
src/view/dialogs/RevisionManifest.h \
src/view/dialogs/CommitRevision.h \
+ src/view/dialogs/FileHistory.h \
src/monotone/Monotone.h \
src/monotone/MonotoneDelegate.h \
src/monotone/FileExporter.h \
@@ -60,6 +61,7 @@ HEADERS += src/view/MainWindow.h \
src/model/Ancestors.h \
src/model/GetBranchLog.h \
src/model/GetRevision.h \
+ src/model/GetContentChanged.h \
src/util/IconProvider.h \
src/util/AbstractParser.h \
src/util/BasicIOParser.h \
@@ -94,6 +96,7 @@ SOURCES += src/view/MainWindow.cpp \
src/view/dialogs/ChangesetBrowser.cpp \
src/view/dialogs/RevisionManifest.cpp \
src/view/dialogs/CommitRevision.cpp \
+ src/view/dialogs/FileHistory.cpp \
src/monotone/Monotone.cpp \
src/monotone/MonotoneDelegate.cpp \
src/monotone/FileExporter.cpp \
@@ -118,6 +121,7 @@ SOURCES += src/view/MainWindow.cpp \
src/model/Ancestors.cpp \
src/model/GetBranchLog.cpp \
src/model/GetRevision.cpp \
+ src/model/GetContentChanged.cpp \
src/util/IconProvider.cpp \
src/util/AbstractParser.cpp \
src/util/BasicIOParser.cpp \
@@ -145,7 +149,9 @@ FORMS += res/forms/select_revision.ui
res/forms/changeset_browser.ui \
res/forms/manifest.ui \
res/forms/commit_revision.ui \
- res/forms/application_update.ui
+ res/forms/application_update.ui \
+ res/forms/file_history.ui
+
UI_DIR = tmp
OBJECTS_DIR = tmp
============================================================
--- src/monotone/MonotoneDelegate.cpp 84dbd3a0dff4a0ffddf39e6a7e25d1735d3b5f14
+++ src/monotone/MonotoneDelegate.cpp 97e18875b8b50bf0d64b6e5d6bedfba1c77a24e6
@@ -91,16 +91,20 @@ QString MonotoneDelegate::getBaseWorkspa
Monotone * mtn = MTN(obj);
int commandNumber;
- if (!mtn->executeCommand(QStringList() << "get_base_revision_id", commandNumber) ||
- mtn->getReturnCode(commandNumber) > 0)
+ bool ret = mtn->executeCommand(
+ QStringList() << "get_base_revision_id", commandNumber
+ );
+
+ QString data = mtn->getDecodedData(commandNumber);
+
+ if (!ret || mtn->getReturnCode(commandNumber) > 0)
{
- qWarning("Could not execute get_base_revision_id");
- return false;
+ C(QString("Could not execute get_base_revision_id: %1").arg(data));
+ return QString();
}
- QString baseRevision = mtn->getDecodedData(commandNumber);
- baseRevision.chop(1);
- return baseRevision;
+ data.chop(1);
+ return data;
}
QString MonotoneDelegate::getOption(QObject * obj, const QString & opt)
@@ -114,8 +118,7 @@ QString MonotoneDelegate::getOption(QObj
if (mtn->getReturnCode(cmdNum) > 0)
{
- qCritical("Couldn't retrieve option %s: %s",
- qPrintable(opt), qPrintable(data));
+ C(QString("Couldn't retrieve option %1: %2").arg(opt).arg(data));
return QString();
}
============================================================
--- src/view/InventoryView.cpp 9ab95e9d6627610fb2567709fb8a912e93eeb281
+++ src/view/InventoryView.cpp 058bd961e53ade94bbe566cf309f57a1ea3d4298
@@ -24,6 +24,7 @@
#include "InventoryItem.h"
#include "Monotone.h"
#include "FileDiff.h"
+#include "FileHistory.h"
#include "RevisionDiff.h"
#include "Guitone.h"
@@ -87,17 +88,93 @@ void InventoryView::setType(Type t)
}
}
+void InventoryView::createAndConnectContextActions()
+{
+ actChdir = new QAction(tr("Go into"), this);
+ actChdir->setStatusTip(tr("Go into the directory"));
+ connect(actChdir, SIGNAL(triggered()), this, SLOT(slotChdir()));
+
+ actOpen = new QAction(tr("Open"), this);
+ actOpen->setStatusTip(tr("Open in default program"));
+ connect(actOpen, SIGNAL(triggered()), this, SLOT(slotOpen()));
+
+ actAdd = new QAction(tr("Add"), this);
+ actAdd->setStatusTip(tr("Add to workspace"));
+ connect(actAdd, SIGNAL(triggered()), this, SLOT(slotAdd()));
+
+ actRemove = new QAction(tr("Remove"), this);
+ actRemove->setStatusTip(tr("Remove from workspace"));
+ connect(actRemove, SIGNAL(triggered()), this, SLOT(slotRemove()));
+
+ actCommit = new QAction(tr("Commit"), this);
+ actCommit->setStatusTip(tr("Commit"));
+ connect(actCommit, SIGNAL(triggered()), this, SLOT(slotCommit()));
+
+ actIgnore = new QAction(tr("Ignore"), this);
+ actIgnore->setStatusTip(tr("Ignore file"));
+ connect(actIgnore, SIGNAL(triggered()), this, SLOT(slotIgnore()));
+
+ actUnignore = new QAction(tr("Unignore"), this);
+ actUnignore->setStatusTip(tr("Unignore file"));
+ connect(actUnignore, SIGNAL(triggered()), this, SLOT(slotUnignore()));
+
+ actRevert = new QAction(tr("Revert"), this);
+ actRevert->setStatusTip(tr("Revert uncommitted changes"));
+ connect(actRevert, SIGNAL(triggered()), this, SLOT(slotRevert()));
+
+ actFileDiff = new QAction(tr("Diff"), this);
+ actFileDiff->setStatusTip(tr("Diff against base revision"));
+ connect(actFileDiff, SIGNAL(triggered()), this, SLOT(slotFileDiff()));
+
+ actFileHistory = new QAction(tr("History"), this);
+ actFileHistory->setStatusTip(tr("Display the history of this file"));
+ connect(actFileHistory, SIGNAL(triggered()), this, SLOT(slotFileHistory()));
+
+ actRevisionDiff = new QAction(tr("Diff all"), this);
+ actRevisionDiff->setStatusTip(tr("Show all differences"));
+ connect(actRevisionDiff, SIGNAL(triggered()), this, SLOT(slotRevisionDiff()));
+
+ actRename = new QAction(tr("Rename"), this);
+ actRename->setStatusTip(tr("Rename file"));
+ connect(actRename, SIGNAL(triggered()), this, SLOT(slotRename()));
+
+ actAddMultiple = new QAction(tr("Add %1 items"), this);
+ actAddMultiple->setStatusTip(tr("Add multiple items"));
+ connect(actAddMultiple, SIGNAL(triggered()), this, SLOT(slotAdd()));
+
+ actRemoveMultiple = new QAction(tr("Remove %1 items"), this);
+ actRemoveMultiple->setStatusTip(tr("Remove multiple items"));
+ connect(actRemoveMultiple, SIGNAL(triggered()), this, SLOT(slotRemove()));
+
+ actCommitMultiple = new QAction(tr("Commit %1 items"), this);
+ actCommitMultiple->setStatusTip(tr("Commit multiple items"));
+ connect(actCommitMultiple, SIGNAL(triggered()), this, SLOT(slotCommit()));
+
+ actIgnoreMultiple = new QAction(tr("Ignore %1 items"), this);
+ actIgnoreMultiple->setStatusTip(tr("Ignore multiple items"));
+ connect(actIgnoreMultiple, SIGNAL(triggered()), this, SLOT(slotIgnore()));
+
+ actUnignoreMultiple = new QAction(tr("Unignore %1 items"), this);
+ actUnignoreMultiple->setStatusTip(tr("Unignore multiple items"));
+ connect(actUnignoreMultiple, SIGNAL(triggered()), this, SLOT(slotUnignore()));
+
+ actRevertMultiple = new QAction(tr("Revert %1 items"), this);
+ actRevertMultiple->setStatusTip(tr("Revert multiple items"));
+ connect(actRevertMultiple, SIGNAL(triggered()), this, SLOT(slotRevert()));
+}
+
InventoryView::~InventoryView()
{
delete actChdir;
- delete actOpen;
- delete actAdd;
- delete actRemove;
- delete actCommit;
- delete actIgnore;
- delete actUnignore;
+ delete actOpen;
+ delete actAdd;
+ delete actRemove;
+ delete actCommit;
+ delete actIgnore;
+ delete actUnignore;
delete actRevert;
- delete actFileDiff;
+ delete actFileDiff;
+ delete actFileHistory;
delete actRevisionDiff;
delete actRename;
delete actAddMultiple;
@@ -215,6 +292,8 @@ void InventoryView::slotContextMenuReque
menu.addAction(actFileDiff);
}
}
+
+ menu.addAction(actFileHistory);
}
//
@@ -330,77 +409,6 @@ void InventoryView::slotContextMenuReque
}
}
-void InventoryView::createAndConnectContextActions(void)
-{
- actChdir = new QAction(tr("Go into"), this);
- actChdir->setStatusTip(tr("Go into the directory"));
- connect(actChdir, SIGNAL(triggered()), this, SLOT(slotChdir()));
-
- actOpen = new QAction(tr("Open"), this);
- actOpen->setStatusTip(tr("Open in default program"));
- connect(actOpen, SIGNAL(triggered()), this, SLOT(slotOpen()));
-
- actAdd = new QAction(tr("Add"), this);
- actAdd->setStatusTip(tr("Add to workspace"));
- connect(actAdd, SIGNAL(triggered()), this, SLOT(slotAdd()));
-
- actRemove = new QAction(tr("Remove"), this);
- actRemove->setStatusTip(tr("Remove from workspace"));
- connect(actRemove, SIGNAL(triggered()), this, SLOT(slotRemove()));
-
- actCommit = new QAction(tr("Commit"), this);
- actCommit->setStatusTip(tr("Commit"));
- connect(actCommit, SIGNAL(triggered()), this, SLOT(slotCommit()));
-
- actIgnore = new QAction(tr("Ignore"), this);
- actIgnore->setStatusTip(tr("Ignore file"));
- connect(actIgnore, SIGNAL(triggered()), this, SLOT(slotIgnore()));
-
- actUnignore = new QAction(tr("Unignore"), this);
- actUnignore->setStatusTip(tr("Unignore file"));
- connect(actUnignore, SIGNAL(triggered()), this, SLOT(slotUnignore()));
-
- actRevert = new QAction(tr("Revert"), this);
- actRevert->setStatusTip(tr("Revert uncommitted changes"));
- connect(actRevert, SIGNAL(triggered()), this, SLOT(slotRevert()));
-
- actFileDiff = new QAction(tr("Diff"), this);
- actFileDiff->setStatusTip(tr("Diff against base revision"));
- connect(actFileDiff, SIGNAL(triggered()), this, SLOT(slotFileDiff()));
-
- actRevisionDiff = new QAction(tr("Diff all"), this);
- actRevisionDiff->setStatusTip(tr("Show all differences"));
- connect(actRevisionDiff, SIGNAL(triggered()), this, SLOT(slotRevisionDiff()));
-
- actRename = new QAction(tr("Rename"), this);
- actRename->setStatusTip(tr("Rename file"));
- connect(actRename, SIGNAL(triggered()), this, SLOT(slotRename()));
-
- actAddMultiple = new QAction(tr("Add %1 items"), this);
- actAddMultiple->setStatusTip(tr("Add multiple items"));
- connect(actAddMultiple, SIGNAL(triggered()), this, SLOT(slotAdd()));
-
- actRemoveMultiple = new QAction(tr("Remove %1 items"), this);
- actRemoveMultiple->setStatusTip(tr("Remove multiple items"));
- connect(actRemoveMultiple, SIGNAL(triggered()), this, SLOT(slotRemove()));
-
- actCommitMultiple = new QAction(tr("Commit %1 items"), this);
- actCommitMultiple->setStatusTip(tr("Commit multiple items"));
- connect(actCommitMultiple, SIGNAL(triggered()), this, SLOT(slotCommit()));
-
- actIgnoreMultiple = new QAction(tr("Ignore %1 items"), this);
- actIgnoreMultiple->setStatusTip(tr("Ignore multiple items"));
- connect(actIgnoreMultiple, SIGNAL(triggered()), this, SLOT(slotIgnore()));
-
- actUnignoreMultiple = new QAction(tr("Unignore %1 items"), this);
- actUnignoreMultiple->setStatusTip(tr("Unignore multiple items"));
- connect(actUnignoreMultiple, SIGNAL(triggered()), this, SLOT(slotUnignore()));
-
- actRevertMultiple = new QAction(tr("Revert %1 items"), this);
- actRevertMultiple->setStatusTip(tr("Revert multiple items"));
- connect(actRevertMultiple, SIGNAL(triggered()), this, SLOT(slotRevert()));
-}
-
void InventoryView::slotChdir()
{
QItemSelectionModel *selectionModel = this->selectionModel();
@@ -446,7 +454,7 @@ void InventoryView::changeDirectory(cons
);
}
-void InventoryView::slotOpen(void)
+void InventoryView::slotOpen()
{
QModelIndex index(getSingleSelection());
if (!index.isValid()) return;
@@ -478,27 +486,27 @@ void InventoryView::slotOpen(void)
}
}
-void InventoryView::slotAdd(void)
+void InventoryView::slotAdd()
{
qDebug("InventoryView::slotAdd!!!");
}
-void InventoryView::slotRemove(void)
+void InventoryView::slotRemove()
{
qDebug("InventoryView::slotRemove!!!");
}
-void InventoryView::slotCommit(void)
+void InventoryView::slotCommit()
{
qDebug("InventoryView::slotCommit!!!");
}
-void InventoryView::slotRevert(void)
+void InventoryView::slotRevert()
{
qDebug("InventoryView::slotRevert!!!");
}
-void InventoryView::slotRename(void)
+void InventoryView::slotRename()
{
qDebug("InventoryView::slotRename!!!");
}
@@ -509,17 +517,17 @@ void InventoryView::slotRename(void)
// Q: If this file is under version control, should a change
// be committed in the background?
//
-void InventoryView::slotIgnore(void)
+void InventoryView::slotIgnore()
{
qDebug("InventoryView::slotIgnore!!!");
}
-void InventoryView::slotUnignore(void)
+void InventoryView::slotUnignore()
{
qDebug("InventoryView::slotUnignore!!!");
}
-void InventoryView::slotFileDiff(void)
+void InventoryView::slotFileDiff()
{
QModelIndex index(getSingleSelection());
if (!index.isValid()) return;
@@ -538,13 +546,41 @@ void InventoryView::slotFileDiff(void)
clearSelection();
}
-void InventoryView::slotRevisionDiff(void)
+void InventoryView::slotFileHistory()
{
QModelIndex index(getSingleSelection());
if (!index.isValid()) return;
InventoryItem * item = static_cast(index.internalPointer());
+ QString path = item->getPath();
+ // determine the original path, if needed
+ if (item->hasStatus(InventoryItem::RenamedFrom))
+ {
+ InventoryItem * newItem = item->getRenamedTo();
+ Q_ASSERT(newItem);
+ path = newItem->getPath();
+ }
+ if (item->hasStatus(InventoryItem::RenamedTo))
+ {
+ InventoryItem * oldItem = item->getRenamedFrom();
+ Q_ASSERT(oldItem);
+ path = oldItem->getPath();
+ }
+
+ FileHistory dlg(this, path);
+ dlg.exec();
+
+ clearSelection();
+}
+
+void InventoryView::slotRevisionDiff()
+{
+ QModelIndex index(getSingleSelection());
+ if (!index.isValid()) return;
+
+ InventoryItem * item = static_cast(index.internalPointer());
+
RevisionDiff dlg(this);
dlg.init(item->getPath(), QString(), QString());
dlg.exec();
============================================================
--- src/view/InventoryView.h 0ad2ef23cc24538fcd3fd656b712f7b6dca17e3e
+++ src/view/InventoryView.h fd0d9c5eb87a628057d22b2a41426dcbbe84ca03
@@ -31,15 +31,15 @@ class InventoryView : public TreeView
class InventoryView : public TreeView
{
- Q_OBJECT
+ Q_OBJECT
public:
- enum Type { FolderTree, FileList };
-
- InventoryView(QWidget*);
- ~InventoryView();
+ enum Type { FolderTree, FileList };
+
+ InventoryView(QWidget*);
+ ~InventoryView();
- void setModel(QSortFilterProxyModel *);
+ void setModel(QSortFilterProxyModel *);
void setType(Type);
signals:
@@ -47,20 +47,21 @@ private:
private:
void setModel(QAbstractItemModel *);
- void createAndConnectContextActions(void);
- void closeEvent(void);
+ void createAndConnectContextActions();
+ void closeEvent();
QModelIndex getSingleSelection(bool mapToSource = true);
QAction * actChdir;
QAction * actOpen;
- QAction * actAdd;
- QAction * actRemove;
- QAction * actCommit;
- QAction * actIgnore;
+ QAction * actAdd;
+ QAction * actRemove;
+ QAction * actCommit;
+ QAction * actIgnore;
QAction * actUnignore;
QAction * actRevert;
QAction * actRename;
QAction * actFileDiff;
+ QAction * actFileHistory;
QAction * actRevisionDiff;
QAction * actAddMultiple;
@@ -82,17 +83,18 @@ private slots:
void itemClicked(const QModelIndex & index);
void slotContextMenuRequested(const QModelIndexList &, const QPoint &);
- void slotChdir(void);
- void slotOpen(void);
- void slotAdd(void);
- void slotRemove(void);
- void slotCommit(void);
- void slotIgnore(void);
- void slotUnignore(void);
- void slotRevert(void);
- void slotRename(void);
- void slotFileDiff(void);
- void slotRevisionDiff(void);
+ void slotChdir();
+ void slotOpen();
+ void slotAdd();
+ void slotRemove();
+ void slotCommit();
+ void slotIgnore();
+ void slotUnignore();
+ void slotRevert();
+ void slotRename();
+ void slotFileDiff();
+ void slotFileHistory();
+ void slotRevisionDiff();
};
#endif