# # # patch "res/forms/file_diff.ui" # from [7892257391ce4faa476cd26cb04e424ac91a4e2d] # to [9b8103ba53247d189bb0e6ef1205bceeb45d7c13] # # patch "res/forms/file_history.ui" # from [04c75b2e86e456fdfdc70174cc8894274b26bec7] # to [4276a79e7a6dc28d7aeffbd5210ff5d9cadc0043] # # patch "src/model/ContentDiff.cpp" # from [af2b8ba1408305c6413d2b0900bc9f7d1e76cb3c] # to [330cf8f074e03c6fc73d6581933660f2e5ac411c] # # patch "src/model/ContentDiff.h" # from [91ee6ba1a90506ce0890d45c4f55d9b146b2d871] # to [9f0b45bde2c813734bf6f4a9a5c8cb88e629a41d] # # patch "src/model/GetFile.cpp" # from [5151a9eccdcf6f92a140dc662d5c845f79484c34] # to [0416604eb10e3a6e93a4ddb990dc078c5550085c] # # patch "src/model/GetFile.h" # from [2542dad0537061ec09b64b453ac07a972788b1c6] # to [4d33901d2eba3e5f57b453101c5245cd075e0a2f] # # patch "src/model/Inventory.cpp" # from [3cceb0b22340f61c7beba6c6d2e05392d1839cc2] # to [38d53b03b3303315ba61b72f5241ffa81e24f8f3] # # patch "src/util/DiffParser.cpp" # from [e98a52a2c7bee64b13376f3cf71b47629a213a7d] # to [4a0256295820e64a621bee2c82c34357ac711b91] # # patch "src/view/dialogs/FileDiff.cpp" # from [3dae40899816900fb362793fef3deda6d2809e5c] # to [8f186d00a2f425b1f13f3089486832a4dea35007] # # patch "src/view/dialogs/FileDiff.h" # from [dcba92805d020b9d0d83de903f27abda0a5a7c74] # to [4992d27618b9504b8f042b545afb13d374bc0e73] # # patch "src/view/dialogs/FileHistory.cpp" # from [47ab8b46f70a4e81ecadd0c686f00dc8874c3fde] # to [86e856616418ed7875cbd92515116b406947abc4] # # patch "src/view/dialogs/FileHistory.h" # from [a55e76d5c71b96d4ed70a74ab97a4e5ebcec8fcc] # to [ed76ac56e2b114a67196d38bae14c01b8b9fda63] # ============================================================ --- res/forms/file_diff.ui 7892257391ce4faa476cd26cb04e424ac91a4e2d +++ res/forms/file_diff.ui 9b8103ba53247d189bb0e6ef1205bceeb45d7c13 @@ -57,7 +57,7 @@ - Show Version + Show @@ -70,23 +70,23 @@ 6 - + - Left + first (%1) - + - Right + second (%2) - + - Both + both true @@ -123,15 +123,15 @@ + DiffStatusView + QWidget +
../DiffStatusView.h
+
+ DiffView QTreeView
../DiffView.h
- - DiffStatusView - QWidget -
../DiffStatusView.h
-
============================================================ --- res/forms/file_history.ui 04c75b2e86e456fdfdc70174cc8894274b26bec7 +++ res/forms/file_history.ui 4276a79e7a6dc28d7aeffbd5210ff5d9cadc0043 @@ -5,8 +5,8 @@ 0 0 - 470 - 372 + 611 + 411 @@ -35,19 +35,84 @@ Qt::Vertical - - - true - - - QAbstractItemView::SingleSelection - - - false - - - false - + + + + 0 + + + 6 + + + + + true + + + QAbstractItemView::SingleSelection + + + false + + + false + + + + + + + 0 + + + 6 + + + + + false + + + Select as first revision + + + + + + + false + + + Select as second revision + + + + + + + Qt::Horizontal + + + + 538 + 20 + + + + + + + + false + + + Show differences + + + + + + @@ -104,15 +169,15 @@ + TreeView + QTreeView +
TreeView.h
+
+ Splitter QSplitter
Splitter.h
- - TreeView - QTreeView -
TreeView.h
-
============================================================ --- src/model/ContentDiff.cpp af2b8ba1408305c6413d2b0900bc9f7d1e76cb3c +++ src/model/ContentDiff.cpp 330cf8f074e03c6fc73d6581933660f2e5ac411c @@ -39,18 +39,8 @@ ContentDiff::~ContentDiff() delete mtnDelegate; } -bool ContentDiff::readDiff(QString fileName) -{ - return readDiff(fileName, QString(), QString()); -} - -bool ContentDiff::readDiff(QString fileName, QString leftRevision) -{ - return readDiff(fileName, leftRevision, QString()); -} - bool ContentDiff::readDiff( - QString fileName, QString leftRevision, QString rightRevision + const QString & fileName, const QString & base, const QString & target ) { // reset the view @@ -61,16 +51,18 @@ bool ContentDiff::readDiff( QStringList opts; - if (leftRevision.length() == 0) + if (base.isEmpty()) { - leftRevision = MonotoneDelegate::getBaseWorkspaceRevision(this); + opts << "r" << MonotoneDelegate::getBaseWorkspaceRevision(this); } + else + { + opts << "r" << base; + } - opts << "r" << leftRevision; - - if (rightRevision.length() > 0) + if (!target.isEmpty()) { - opts << "r" << rightRevision; + opts << "r" << target; } return mtnDelegate->triggerCommand(cmd, opts); ============================================================ --- src/model/ContentDiff.h 91ee6ba1a90506ce0890d45c4f55d9b146b2d871 +++ src/model/ContentDiff.h 9f0b45bde2c813734bf6f4a9a5c8cb88e629a41d @@ -76,9 +76,7 @@ public slots: inline FileDiffs getAllDiffs() { return diffParser->getAllDiffs(); } public slots: - bool readDiff(QString); - bool readDiff(QString, QString); - bool readDiff(QString, QString, QString); + bool readDiff(const QString &, const QString & baseRev = QString(), const QString & targetRev = QString()); signals: void diffRead(); ============================================================ --- src/model/GetFile.cpp 5151a9eccdcf6f92a140dc662d5c845f79484c34 +++ src/model/GetFile.cpp 0416604eb10e3a6e93a4ddb990dc078c5550085c @@ -33,23 +33,25 @@ GetFile::~GetFile() delete mtnDelegate; } -bool GetFile::readFileByName(QString fileName) +bool GetFile::readFileByName(const QString & fileName, const QString & rev) { - return readFileByName(fileName, MonotoneDelegate::getBaseWorkspaceRevision(this)); -} - -bool GetFile::readFileByName(QString fileName, QString revision) -{ QStringList cmd; cmd << "get_file_of" << fileName; QStringList opts; - opts << "r" << revision; + if (rev.isEmpty()) + { + opts << "r" << MonotoneDelegate::getBaseWorkspaceRevision(this); + } + else + { + opts << "r" << rev; + } return readFile(cmd, opts); } -bool GetFile::readFileById(QString fileID) +bool GetFile::readFileById(const QString & fileID) { QStringList cmd; cmd << "get_file" << fileID; ============================================================ --- src/model/GetFile.h 2542dad0537061ec09b64b453ac07a972788b1c6 +++ src/model/GetFile.h 4d33901d2eba3e5f57b453101c5245cd075e0a2f @@ -55,9 +55,8 @@ public slots: int columnCount(const QModelIndex&) const; public slots: - bool readFileById(QString); - bool readFileByName(QString); - bool readFileByName(QString, QString); + bool readFileById(const QString &); + bool readFileByName(const QString &, const QString & rev = QString()); void applyDiff(Diff * diff); signals: ============================================================ --- src/model/Inventory.cpp 3cceb0b22340f61c7beba6c6d2e05392d1839cc2 +++ src/model/Inventory.cpp 38d53b03b3303315ba61b72f5241ffa81e24f8f3 @@ -472,7 +472,8 @@ QMap Inventory FileEntry entry; // this is a new entry not recorded in the base roster - if (missingItem->hasStatus(InventoryItem::Added)) + if (missingItem->hasStatus(InventoryItem::Added) || + missingItem->hasStatus(InventoryItem::RenamedTo)) { entry.path = missingItem->getPath(); entry.is_dir = missingItem->isDirectory(); @@ -491,75 +492,43 @@ QMap Inventory I(found); } - // at first check if the simple case: the item was renamed - // in the bookkeeping dir, but not physically - if (missingItem->hasStatus(InventoryItem::RenamedTo)) + foreach (InventoryItem * unknownItem, unknownItems) { - InventoryItem * oldItem = missingItem->getRenamedFrom(); - I(oldItem); + QString unknownPath = unknownItem->getPath(); - // yes, there is an unknown path with the same name! - if (oldItem->hasStatus(InventoryItem::Unknown)) + // calculate the file id of the unknown file + if (!unknownItem->isDirectory() && + !fileIds.contains(unknownPath)) { - bool found = false; - FileEntry oldEntry; - foreach (oldEntry, parentList) - { - if (oldEntry.path == oldItem->getPath()) - { - found = true; - break; - } - } - I(found); - candidates.append(oldEntry); + QString fileid = MonotoneDelegate::getFileId(this, unknownPath); + // file was not readable, etc. + if (fileid.isEmpty()) continue; + fileIds.insert(unknownPath, fileid); } - else + + // at first do a simple file name check + if ((missingItem->getFilename() == unknownItem->getFilename()) && + (missingItem->isDirectory() == unknownItem->isDirectory())) { + FileEntry can(unknownPath, unknownItem->isDirectory()); + if (fileIds.contains(unknownPath)) + { + can.fileid = fileIds.value(unknownPath); + } + candidates.append(can); continue; } - } - else - { - foreach (InventoryItem * unknownItem, unknownItems) + + // we can't do anything for directories from here on + if (missingItem->isDirectory() || unknownItem->isDirectory()) + continue; + + // we now rely on the fact that we have a fileid + I(fileIds.contains(unknownPath)); + + if (fileIds.value(unknownPath) == entry.fileid) { - QString unknownPath = unknownItem->getPath(); - - // calculate the file id of the unknown file - if (!unknownItem->isDirectory() && - !fileIds.contains(unknownPath)) - { - QString fileid = MonotoneDelegate::getFileId(this, unknownPath); - // file was not readable, etc. - if (fileid.isEmpty()) continue; - fileIds.insert(unknownPath, fileid); - } - - // at first do a simple file name check - if ((missingItem->getFilename() == unknownItem->getFilename()) && - (missingItem->isDirectory() == unknownItem->isDirectory())) - { - FileEntry can(unknownPath, unknownItem->isDirectory()); - if (fileIds.contains(unknownPath)) - { - can.fileid = fileIds.value(unknownPath); - } - candidates.append(can); - continue; - } - - // we can't do anything for directories from here on - if (missingItem->isDirectory() || unknownItem->isDirectory()) - continue; - - D(unknownPath); - // we now rely on the fact that we have a fileid - I(fileIds.contains(unknownPath)); - - if (fileIds.value(unknownPath) == entry.fileid) - { - candidates.append(FileEntry(unknownPath, false, entry.fileid)); - } + candidates.append(FileEntry(unknownPath, false, entry.fileid)); } } ============================================================ --- src/util/DiffParser.cpp e98a52a2c7bee64b13376f3cf71b47629a213a7d +++ src/util/DiffParser.cpp 4a0256295820e64a621bee2c82c34357ac711b91 @@ -37,7 +37,11 @@ void DiffParser::parse(const QString & i void DiffParser::parse(const QString & input) { - if (input.length() == 0) return; + if (input.length() == 0) + { + W("Nothing to parse"); + return; + } // remove last newline character QString in(input); @@ -139,9 +143,9 @@ void DiffParser::parse(const QString & i } } -Diff* DiffParser::getDiff(const QString & filename) +Diff * DiffParser::getDiff(const QString & filename) { - I(fileDiffs.contains(filename)); + if (!fileDiffs.contains(filename)) return 0; return fileDiffs.value(filename); } ============================================================ --- src/view/dialogs/FileDiff.cpp 3dae40899816900fb362793fef3deda6d2809e5c +++ src/view/dialogs/FileDiff.cpp 8f186d00a2f425b1f13f3089486832a4dea35007 @@ -20,10 +20,10 @@ #include "FileDiff.h" #include "Monotone.h" -#include "SignalWaiter.h" #include "Settings.h" #include +#include FileDiff::FileDiff(QWidget* parent) : Dialog(parent) { @@ -31,77 +31,120 @@ FileDiff::FileDiff(QWidget* parent) : Di Dialog::init(); } -FileDiff::FileDiff(QWidget* parent, QString fileName) : Dialog(parent) +FileDiff::FileDiff(QWidget * parent, const QString & fileName, + const QString & base, const QString & target): Dialog(parent) { setupUi(this); Dialog::init(); - init(fileName); + init(fileName, base, target); } -void FileDiff::init(QString fileName) +void FileDiff::init( + const QString & fileName, const QString & base, const QString & target +) { - connect( - showVersionLeft, SIGNAL(toggled(bool)), - this, SLOT(versionToggled(bool)) - ); - connect( - showVersionRight, SIGNAL(toggled(bool)), - this, SLOT(versionToggled(bool)) - ); - connect( - showVersionBoth, SIGNAL(toggled(bool)), - this, SLOT(versionToggled(bool)) - ); + file = fileName; + loaded = false; QString title = windowTitle(); setWindowTitle(title.arg(fileName)); + if (base.isEmpty()) + { + firstRevision->setText(tr("workspace parent")); + } + else + { + firstRevision->setText( + firstRevision->text().arg(base.left(12).append("...")) + ); + } + + if (target.isEmpty()) + { + secondRevision->setText(tr("workspace revision")); + } + else + { + secondRevision->setText( + secondRevision->text().arg(target.left(12).append("...")) + ); + } + fileModel = new GetFile(this); - fileModel->readFileByName(fileName); fileProxyModel = new GetFileProxyModel(this); fileProxyModel->setSourceModel(fileModel); + diffModel = new ContentDiff(this); + diffView->setModel(fileProxyModel); diffStatusView->setModel(fileProxyModel); // make the line number col a little smaller diffView->header()->resizeSection(0, 40); + + connect( + firstRevision, SIGNAL(toggled(bool)), + this, SLOT(versionToggled(bool)) + ); + connect( + secondRevision, SIGNAL(toggled(bool)), + this, SLOT(versionToggled(bool)) + ); + connect( + bothRevisions, SIGNAL(toggled(bool)), + this, SLOT(versionToggled(bool)) + ); - SignalWaiter fileWaiter(fileModel, SIGNAL(fileRead())); + connect( + fileModel, SIGNAL(fileRead()), + this, SLOT(applyDiff()) + ); - if (fileWaiter.wait()) + connect( + diffModel, SIGNAL(diffRead()), + this, SLOT(applyDiff()) + ); + + fileModel->readFileByName(fileName, base); + diffModel->readDiff(fileName, base, target); +} + +FileDiff::~FileDiff() {} + +void FileDiff::applyDiff() +{ + if (!loaded) { - diffModel = new ContentDiff(this); - diffModel->readDiff(fileName); - - SignalWaiter diffWaiter(diffModel, SIGNAL(diffRead())); - - if (diffWaiter.wait()) - { - fileModel->applyDiff(diffModel->getDiff(fileName)); - diffStatusView->update(); - } - else - { - C("diffWaiter timed out"); - } + loaded = true; + return; } - else + + Diff * diff = diffModel->getDiff(file); + if (diff == 0) { - C("fileWaiter timed out"); + QMessageBox::information( + this, + tr("File has not changed"), + tr("The file has not been changed between these revisions."), + QMessageBox::Ok + ); + reject(); + return; } + + fileModel->applyDiff(diff); + diffStatusView->update(); } -FileDiff::~FileDiff() {} - void FileDiff::versionToggled(bool dummy) { - if (showVersionLeft->isChecked()) + if (firstRevision->isChecked()) fileProxyModel->setFileVersion(GetFileProxyModel::Left); - if (showVersionRight->isChecked()) + if (secondRevision->isChecked()) fileProxyModel->setFileVersion(GetFileProxyModel::Right); - if (showVersionBoth->isChecked()) + if (bothRevisions->isChecked()) fileProxyModel->setFileVersion(GetFileProxyModel::Both); diffStatusView->update(); ============================================================ --- src/view/dialogs/FileDiff.h dcba92805d020b9d0d83de903f27abda0a5a7c74 +++ src/view/dialogs/FileDiff.h 4992d27618b9504b8f042b545afb13d374bc0e73 @@ -32,19 +32,22 @@ public: Q_OBJECT public: - FileDiff(QWidget*); - FileDiff(QWidget*, QString); - void init(QString); + FileDiff(QWidget *); + FileDiff(QWidget *, const QString &, const QString & base = QString(), const QString & target = QString()); + void init(const QString &, const QString & base = QString(), const QString & target = QString()); ~FileDiff(); private slots: + void applyDiff(); void versionToggled(bool); - + private: ContentDiff * diffModel; GetFile * fileModel; GetFileProxyModel * fileProxyModel; + QString file; + bool loaded; }; #endif ============================================================ --- src/view/dialogs/FileHistory.cpp 47ab8b46f70a4e81ecadd0c686f00dc8874c3fde +++ src/view/dialogs/FileHistory.cpp 86e856616418ed7875cbd92515116b406947abc4 @@ -19,8 +19,10 @@ ***************************************************************************/ #include "FileHistory.h" +#include "FileDiff.h" -FileHistory::FileHistory(QWidget * parent, const QString & path): Dialog(parent) +FileHistory::FileHistory(QWidget * parent, const QString & fileName) + : Dialog(parent) { setupUi(this); Dialog::init(); @@ -43,11 +45,31 @@ FileHistory::FileHistory(QWidget * paren this, SLOT(readCerts(const QModelIndex &)) ); + connect( + selectFirst, SIGNAL(clicked()), + this, SLOT(setFirstRevision()) + ); + + connect( + selectSecond, SIGNAL(clicked()), + this, SLOT(setSecondRevision()) + ); + + connect( + showDiff, SIGNAL(clicked()), + this, SLOT(showDiffDialog()) + ); + + connect( + revisionFileList, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(revisionFileListClicked(const QModelIndex &)) + ); + QString title = windowTitle(); - setWindowTitle(title.arg(path)); + setWindowTitle(title.arg(fileName)); // read the changes - I(changeModel->readChanges(path)); + I(changeModel->readChanges(fileName)); } FileHistory::~FileHistory() @@ -69,3 +91,49 @@ void FileHistory::readCerts(const QModel } } +void FileHistory::setFirstRevision() +{ + QModelIndex revIdx = changeModel->index(curRow, 0, QModelIndex()); + QModelIndex fileIdx = changeModel->index(curRow, 1, QModelIndex()); + I(revIdx.isValid() && fileIdx.isValid()); + + firstRevision = revIdx.data().toString(); + fileName = fileIdx.data().toString(); + + if (secondRevision.size() > 0) showDiff->setEnabled(true); + + selectFirst->setText(tr("First: %1...").arg(firstRevision.left(12))); +} + +void FileHistory::setSecondRevision() +{ + QModelIndex revIdx = changeModel->index(curRow, 0, QModelIndex()); + I(revIdx.isValid()); + + secondRevision = revIdx.data().toString(); + + if (firstRevision.size() > 0) showDiff->setEnabled(true); + + selectSecond->setText(tr("Second: %1...").arg(secondRevision.left(12))); +} + +void FileHistory::revisionFileListClicked(const QModelIndex & index) +{ + if (!index.isValid()) return; + + curRow = index.row(); + + // make sure both button are enabled + selectFirst->setEnabled(true); + selectSecond->setEnabled(true); +} + +void FileHistory::showDiffDialog() +{ + I(firstRevision.size() > 0 && secondRevision.size() > 0); + + FileDiff dlg(this); + dlg.init(fileName, firstRevision, secondRevision); + dlg.exec(); +} + ============================================================ --- src/view/dialogs/FileHistory.h a55e76d5c71b96d4ed70a74ab97a4e5ebcec8fcc +++ src/view/dialogs/FileHistory.h ed76ac56e2b114a67196d38bae14c01b8b9fda63 @@ -38,8 +38,17 @@ private: GetContentChanged * changeModel; Certs * certsModel; + int curRow; + QString firstRevision; + QString secondRevision; + QString fileName; + private slots: void readCerts(const QModelIndex &); + void setFirstRevision(); + void setSecondRevision(); + void revisionFileListClicked(const QModelIndex &); + void showDiffDialog(); }; #endif