# # # add_file "guitone/src/model/ContentDiff.cpp" # content [1e58b03ad145e7e21ddab17e527ea21ed37aad4c] # # add_file "guitone/src/model/ContentDiff.h" # content [c520819fe390978f21f38ac1914b7a56f1d009f0] # # add_file "guitone/src/view/DiffView.cpp" # content [4b68037cf4a8ed4fcbe5439c091e8efae2b20d0e] # # add_file "guitone/src/view/DiffView.h" # content [3bc969b89d93fc3adb7c2fe49d108bad5d5467ea] # ============================================================ --- guitone/src/model/ContentDiff.cpp 1e58b03ad145e7e21ddab17e527ea21ed37aad4c +++ guitone/src/model/ContentDiff.cpp 1e58b03ad145e7e21ddab17e527ea21ed37aad4c @@ -0,0 +1,295 @@ +/*************************************************************************** + * 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 "ContentDiff.h" +#include "../monotone/Monotone.h" + +#include + +ContentDiff::ContentDiff(QObject *parent) + : AutomateCommand(parent) +{ +} + +ContentDiff::~ContentDiff() +{ + if (diffParser) delete diffParser; +} + +bool ContentDiff::readDiff(QString fileName) +{ + Monotone * mtn = Monotone::singleton(); + + QStringList cmd; + cmd << "get_base_revision_id"; + + if (!mtn->executeCommand(cmd)) + { + qWarning("ContentDiff::readDiff: could not execute get_base_revision_id"); + return false; + } + + QString rev = mtn->getOutput(); + rev.chop(1); + return readDiff(fileName, rev); +} + +bool ContentDiff::readDiff(QString fileName, QString leftRevision) +{ + return readDiff(fileName, leftRevision, QString()); +} + +bool ContentDiff::readDiff( + QString fileName, QString leftRevision, QString rightRevision +) +{ + // reset the view + reset(); + + Monotone *mtn = Monotone::singleton(); + + // + // read in the original file + // + baseFileName = fileName; + + QStringList cmd; + cmd << "get_file_of" << diffFileName; + + QStringList opts; + opts << "r" << leftRevision; + + if (!mtn->executeCommand(cmd, opts)) + { + qWarning("ContentDiff::readDiff: could not execute get_file_of"); + return false; + } + + baseFileContents = mtn->getOutput().split(QRegExp("/[\r\n]+/")); + + QStringList cmd; + cmd << "content_diff" << fileName; + + QStringList opts; + opts << "r" << leftRevision; + + if (rightRevision.length() > 0) + { + opts << "r" << rightRevision; + } + + Monotone *mtn = Monotone::singleton(); + + return mtn->triggerCommand(this, cmd, opts); +} + +void ContentDiff::parseOutput(AutomateCommand *caller) +{ + // if not we are the caller, omit the parsing + if (caller != this) return; + + diffParser = new diffParser(AutomateCommand::data); + Diff * diff = diffParser->getDiff(diffFileName); + + if (diff->is_binary) + { + emit parsingError(tr("Binary file %1 can't be diffed.").arg(baseFileName)); + return; + } + + int leftLastHunk = 0, rightLastHunk = 0; + + for (int i=0, s=diff->hunks.size(); ihunks.at(i); + + // push unrelated left lines + if (hunk->leftStart > 0) + { + pushNewLines(Left, + ContentLine::Unchanged, + baseFileContents.mid(leftLastHunk, hunk->leftStart) + ); + } + + // push unrelated right lines + if (hunk->rightStart > 0) + { + pushNewLines(Right, + ContentLine::Unchanged, + baseFileContents.mid(rightLastHunk, hunk->rightStart) + ); + } + + leftLastHunk = hunk->leftStart + hunk->leftCount; + rightLastHunk = hunk->rightStart + hunk->rightCount; + + int leftLastLine = 0, rightLastLine = 0; + + // now parse each line group in the hunk + for (int j=0, t=hunk->lines.size(); jlines.at(j); + + if (line->state == DiffLines::Removed) + { + if (leftLastLine < line->startPos) + { + int pos = leftLastHunk + leftLastLine; + int count = line->startPos - leftLastLine; + + pushNewLines(Left, + ContentLine::Unchanged, + baseFileContents.mid(pos, count) + ); + } + + // TODO: Take care of line relations + pushNewLines(Left, + ContentLine::Changed, + line->contents); + + leftLastLine = line->startPos + line->changeLen; + continue; + } + + // DiffLines::Added + if (rightLastLine < line->startPos) + { + int pos = rightLastHunk + rightLastLine; + int count = line->startPos - rightLastLine; + + pushNewLines(Right, + ContentLine::Unchanged, + baseFileContents.mid(pos, count) + ); + } + + // TODO: Take care of line relations + pushNewLines(Right, + ContentLine::Changed, + line->contents); + + rightLastLine = line->startPos + line->changeLen; + } + } + + // signal that we've finished (whoever listens to that) + emit diffRead(); +} + +void ContentDiff::pushNewLines(FileVersion version, ContentLine::Marker marker, const QStringList & contents) +{ + for (int i=0, s=contents.size(); i= attributes->size()) return QVariant(); + + Attribute attr = attributes->at(row); + + switch (index.column()) + { + case 0: return QVariant(attr.key); + case 1: return QVariant(attr.value); + case 2: + switch (attr.state) + { + case Attribute::Added: return QVariant(tr("added")); + case Attribute::Dropped: return QVariant(tr("dropped")); + case Attribute::Changed: return QVariant(tr("changed")); + case Attribute::Unchanged: return QVariant(tr("unchanged")); + } + } + + return QVariant(); +} + +Qt::ItemFlags ContentDiff::flags(const QModelIndex &index) const +{ + // TODO: add ItemIsEditable as soon as we can set/drop attributes through + // the automation interface, implement setData() then as well + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; +} + +QVariant ContentDiff::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) + { + switch (section) + { + case 0: return QVariant(tr("Key")); + case 1: return QVariant(tr("Value")); + case 2: return QVariant(tr("State")); + } + } + return QVariant(); +} + +int ContentDiff::rowCount(const QModelIndex& parent) const +{ + return attributes->size(); +} + +QModelIndex ContentDiff::index(int row, int column, const QModelIndex& parent) const +{ + return hasIndex(row, column, parent) ? createIndex(row, column, 0) : QModelIndex(); +} + +QModelIndex ContentDiff::parent(const QModelIndex& index) const +{ + return QModelIndex(); +} ============================================================ --- guitone/src/model/ContentDiff.h c520819fe390978f21f38ac1914b7a56f1d009f0 +++ guitone/src/model/ContentDiff.h c520819fe390978f21f38ac1914b7a56f1d009f0 @@ -0,0 +1,73 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ + +// TODO: enable editing of items as well as dropping/adding them + +#ifndef CONTENT_DIFF_H +#define CONTENT_DIFF_H + +#include "AutomateCommand.h" +#include "../util/DiffParser.h" + +struct ContentLine { + QString content; + enum Marker {Changed, Unchanged} marker; +} + +typedef QVector Content; + +class ContentDiff : public AutomateCommand +{ + Q_OBJECT +public: + ContentDiff(QObject*); + virtual ~ContentDiff(); + + // 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; + + enum FileVersion { Left, Right } fileVersion; + +public slots: + bool readDiff(QString); + bool readDiff(QString, QString); + bool readDiff(QString, QString, QString); + +signals: + void diffRead(); + +private: + void parseOutput(AutomateCommand*); + + DiffParser * diffParser; + QString baseFileName; + QStringList baseFileContents; + + Content leftFile; + Content rightFile; +}; + +#endif ============================================================ --- guitone/src/view/DiffView.cpp 4b68037cf4a8ed4fcbe5439c091e8efae2b20d0e +++ guitone/src/view/DiffView.cpp 4b68037cf4a8ed4fcbe5439c091e8efae2b20d0e @@ -0,0 +1,31 @@ +/*************************************************************************** + * 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 "DiffView.h" +#include "../util/Settings.h" + +DiffView::DiffView(QWidget* parent, QString objName) +: TreeView(parent, objName) +{ + setRootIsDecorated(false); + setItemsExpandable(false); +} + +DiffView::~DiffView() {} ============================================================ --- guitone/src/view/DiffView.h 3bc969b89d93fc3adb7c2fe49d108bad5d5467ea +++ guitone/src/view/DiffView.h 3bc969b89d93fc3adb7c2fe49d108bad5d5467ea @@ -0,0 +1,35 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ + +#ifndef DIFF_VIEW_H +#define DIFF_VIEW_H + +#include "TreeView.h" + +class DiffView : public TreeView +{ + Q_OBJECT + +public: + DiffView(QWidget*, QString); + ~DiffView(); +}; + +#endif