#
#
# patch "NEWS"
# from [650c6f31c4d3d4348cec5b8d5e15bf56a7164d31]
# to [6892374b7a0ec727e85b24288786b9ec45d8ac30]
#
# patch "res/forms/commit_revision.ui"
# from [470e5fbd3fe58caff240d35dac1ce475dd64dc61]
# to [5c31cbc645279d4894459c84b71ac1a2fa5a6589]
#
# patch "res/forms/file_diff.ui"
# from [80ef8d2f2e9421f0fb8a026b00159e6e6e15df61]
# to [6608573b8c72a21523ea07b110636abda6a8c815]
#
# patch "res/forms/preferences.ui"
# from [0d11100970f4e76902c87bc53331a28b5f0cd993]
# to [893f76e7dddd80eb90ab81b393a7d879019806aa]
#
# patch "res/forms/revision_diff.ui"
# from [b4c9054581ea1f9e5cd89d2556fb30c858f3bd37]
# to [462da831393f381934149847d2bb24b126b38fe3]
#
# patch "src/model/Ancestors.cpp"
# from [40b168cdabbc4fbab891933ff9bd174bc434e4c6]
# to [ff279efc1a19d894af6db12104e7462b12cce760]
#
# patch "src/model/AutomateCommand.cpp"
# from [008019a4c691a5f977d2a6cb8b8cf347b652a63b]
# to [1c819d32c321a539d0d59e100a632d17fdba16ca]
#
# patch "src/model/Branches.cpp"
# from [d0a1ee6db5af0f1a7cdf864d070868a6d87d4532]
# to [6a240a83de4e8cf7aaf21467ba9b4205e586e487]
#
# patch "src/model/Certs.cpp"
# from [8b011be58c9224fb726884374bd3d4941a8c7e36]
# to [285dd2004b058cc9a7082ca34d0cd21fdc8d9765]
#
# patch "src/model/ContentDiff.cpp"
# from [74852b2ba64c28376d51ada0f718228ba4612d5f]
# to [fba40b0f3894f67596c8ea99293ab78212535b53]
#
# patch "src/model/ContentDiff.h"
# from [e89ba83d45953a4cfc745a4c7ad475e9733c37ff]
# to [38035d0dec91320d0fa33e58ffc5238a11109852]
#
# patch "src/model/GetAttributes.cpp"
# from [ed421d842b53dc2400e2c1adaae282c53e34c250]
# to [bd51d4f673480a28c18b78bf4290a4a5e0897589]
#
# patch "src/model/GetContentChanged.cpp"
# from [d0d630e76c1b8c7fee93d511fbfd1fd2eecb4bc7]
# to [784b1572425d9af21934de417f6cbc65db3419f3]
#
# patch "src/model/GetDatabaseVariables.cpp"
# from [daa9eb7f0b0a9bb2f684182b2c4a499814c1c028]
# to [b9ad21e33c9994caf29bdadcb74103c4bb3973de]
#
# patch "src/model/GetFile.cpp"
# from [3fffb3be172e0e28451322370f80dbf80408f132]
# to [735189cbe8ffb4e7cffd1a40e07fef37a0068ea4]
#
# patch "src/model/GetFile.h"
# from [f185acd189190ef2d6d519a8f5adbfd727a3093d]
# to [73a82bb540ba6ca45cd9c6fcdc4f165a6ded958b]
#
# patch "src/model/GetRevision.cpp"
# from [95014c1468ada6b5e60ed31407eec63f1a50975b]
# to [a59701ac07d146aab3ebb5f021c2ee92bb6bb085]
#
# patch "src/model/Inventory.cpp"
# from [4affff131bf9b3bbf87b6d2c38112754af3dfba9]
# to [7056e6451d09ab9dbb5793d2b9529a5fddff9420]
#
# patch "src/model/Keys.cpp"
# from [19dfda529004934172d6ceb4511eae24e30af3f6]
# to [11aae606f14aaa15d64c9f68f651bf3630733dd6]
#
# patch "src/model/Manifest.cpp"
# from [235f3ddeb0e0514934b9df6f619e87ceb9d6f387]
# to [362e3fe7a8399c28ab69235376d5955421b2cd66]
#
# patch "src/model/Select.cpp"
# from [ca967f456759195df4c53ec6922c0a8967273c35]
# to [a82a300f0787e9ae330c0c8ca96083da99d82476]
#
# patch "src/model/Tags.cpp"
# from [80d62375cd40c37849eacf93a0bcb61d3983175b]
# to [31c3f32539c54fb7bc7d676d18ad0581356f844c]
#
# patch "src/model/Toposort.cpp"
# from [d081059ec2bc33341fc9b6fc75292072cb29a3fe]
# to [c5f0896d43e6e9763571e201281ee49db94ad22e]
#
# patch "src/monotone/FileExporter.cpp"
# from [d8841a939d1676436370923e9b88c9dbe0b64a9c]
# to [8d23af2f0072da14f8c79d2d71b3db6701693729]
#
# patch "src/monotone/MonotoneThread.cpp"
# from [e3f258605fd1557753b903f13d1515b6e98d976b]
# to [b5fd6caedca9f2cbc910e172ffbee6c0e3d2d3f0]
#
# patch "src/monotone/MonotoneThread.h"
# from [b00320bbdc44039934898127d9093016adec9f16]
# to [dd3abaa03d5a86ab9141e3da15c0e62766e016aa]
#
# patch "src/monotone/MonotoneUtil.cpp"
# from [2679a231bcdd46393acc15364976563938c05325]
# to [c18789f0f92cceb714cca6b981e50ab2437ea9ff]
#
# patch "src/monotone/MonotoneUtil.h"
# from [7173990600fd78e4e75a5bc0111d2c29e2a06ed7]
# to [2859545454f0987d0bb5141a06a1f34667a9dc51]
#
# patch "src/monotone/WorkspaceCommitter.cpp"
# from [d2a5ce169d18495c84ed56ecf92732b2c6646812]
# to [3efc567b8ef22e48f152f8b728a3b168ea0f3d0d]
#
# patch "src/view/TreeView.cpp"
# from [dcf826574e06d65e22db5a586caeb918673c00d0]
# to [bf98bd50c56ec9d93411832cd4e3c5d5f08184b8]
#
# patch "src/view/TreeView.h"
# from [7b872f64c09770fed7e6cf2dd321b6a798a05f90]
# to [651169fd52a772a8c03d883a3d75c35f52cb9524]
#
# patch "src/view/WorkspaceWindow.cpp"
# from [9ae0a5ea1f3095ecc8824221b1d1523956942144]
# to [ade47c546f628f21ee7457e923e57d4a910370c4]
#
# patch "src/view/WorkspaceWindow.h"
# from [3c181a5026143baf9e58dc86a97cf4ee5469356b]
# to [a463caf3a560c81ada20f1cd3eae8677644018b8]
#
# patch "src/view/dialogs/FileDiff.cpp"
# from [699fafa30f746354fb9218fc18bc135e01e21e02]
# to [f9e9afd79cc644e82dc4987ca845ae2e37dcc473]
#
# patch "src/view/dialogs/FileDiff.h"
# from [14c54d84f6d8f41b74cb461a378d942ec0db690f]
# to [752ff0409384d3e4220754274ea638604e4a278d]
#
# patch "src/view/dialogs/GenerateKeypair.cpp"
# from [6ed24f6d1bcee46cd89605ecbe0c3c5a6b17475c]
# to [17c560ed391524a64ae4f86642641999a1eb99d7]
#
# patch "src/view/dialogs/Preferences.cpp"
# from [1e3bc13f16b3a04e84f5fc8ce2add567a35db359]
# to [211cc5978c8f41c19d41165fe4e56951043989cf]
#
# patch "src/view/dialogs/RevisionDiff.cpp"
# from [c03a05117e11c00a098e0fd55b09385dc7cb205c]
# to [24e17c91450da9413c36beea817d744f313c2341]
#
# patch "src/view/dialogs/RevisionDiff.h"
# from [e536991efd9001e62a385f86c7130ea26b2cbee7]
# to [bce21301eb5596f48b36be6f32947ec6b5cfea71]
#
# patch "src/view/dialogs/RevisionManifest.cpp"
# from [6316625d53d8349258ae940ddc1f5c8d5dc641ec]
# to [f329b383c8b9aced2fe93ecda59f704f53f17427]
#
============================================================
--- NEWS 650c6f31c4d3d4348cec5b8d5e15bf56a7164d31
+++ NEWS 6892374b7a0ec727e85b24288786b9ec45d8ac30
@@ -1,3 +1,14 @@
+????-??-?? (0.9)
+ - new: possibility to select the file encoding of a file in the diff dialog;
+ the preference can be saved to the special file attribute
+ "guitone:file-encoding" which is read out next time you diff the file.
+ Note that you need a checked-out workspace for this; if you diff a
+ not-checked-out file, the attribute must already be present in the manifest
+ of the base revision and an encoding change cannot be saved there.
+ - bugfix: if you change the selection of items in the workspace view the
+ attribute view should now get properly updated properly under all
+ circumstances
+
2008-05-25 (0.8)
- starting from this version (0.8) guitone is distributed under the terms
of the GNU General Public License Version 3
============================================================
--- res/forms/commit_revision.ui 470e5fbd3fe58caff240d35dac1ce475dd64dc61
+++ res/forms/commit_revision.ui 5c31cbc645279d4894459c84b71ac1a2fa5a6589
@@ -6,7 +6,7 @@
0
0
417
- 509
+ 513
@@ -54,11 +54,46 @@
-
-
-
- Double-click on a patch to open the diff dialog.
-
-
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+ 11
+
+
+
+ Double-click on a patch to open the diff dialog.
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
============================================================
--- res/forms/file_diff.ui 80ef8d2f2e9421f0fb8a026b00159e6e6e15df61
+++ res/forms/file_diff.ui 6608573b8c72a21523ea07b110636abda6a8c815
@@ -13,119 +13,118 @@
File differences of "%1"
- :/icons/guitone.png
+
+ :/icons/guitone.png:/icons/guitone.png
-
+
-
-
+
-
-
-
-
-
-
- false
-
-
- false
-
-
-
- -
-
-
-
+
+
+ false
+
+
+ false
+
+
-
-
-
- Show
+
+
+
+
+ -
+
+
+ Display Options
+
+
+
-
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QSizePolicy::MinimumExpanding
+
+
+
+ 20
+ 20
+
+
+
+
+ -
+
+
+ only left (%1)
+
+
+
+ -
+
+
+ only right (%2)
+
+
+
+ -
+
+
+ both
+
+
+ true
+
+
+
+
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
-
-
-
-
-
-
-
-
- first (%1)
-
-
-
- -
-
-
- second (%2)
-
-
-
- -
-
-
- both
-
-
- true
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
-
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Prev
+
-
-
-
-
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- Prev
-
-
-
- -
-
-
- Next
-
-
-
- -
-
-
- Close
-
-
- true
-
-
-
-
+
+
+ Next
+
+
+ -
+
+
+ Close
+
+
+ true
+
+
+
@@ -134,7 +133,7 @@
TreeView
QTreeView
-
+
DiffStatusView
============================================================
--- res/forms/preferences.ui 0d11100970f4e76902c87bc53331a28b5f0cd993
+++ res/forms/preferences.ui 893f76e7dddd80eb90ab81b393a7d879019806aa
@@ -38,7 +38,7 @@
QTabWidget::Rounded
- 0
+ 2
false
@@ -317,7 +317,7 @@
- -
+
-
ask before opening executable files and files with
@@ -328,7 +328,7 @@ the following extensions (comma-separate
- -
+
-
-
@@ -351,7 +351,7 @@ the following extensions (comma-separate
- -
+
-
Qt::Vertical
@@ -364,6 +364,16 @@ the following extensions (comma-separate
+ -
+
+
+ save encoding preference as file attribute
+
+
+ true
+
+
+
============================================================
--- res/forms/revision_diff.ui b4c9054581ea1f9e5cd89d2556fb30c858f3bd37
+++ res/forms/revision_diff.ui 462da831393f381934149847d2bb24b126b38fe3
@@ -5,58 +5,92 @@
0
0
- 528
- 431
+ 539
+ 500
- :/icons/guitone.png
+
+ :/icons/guitone.png:/icons/guitone.png
-
+
-
-
+
+
+ false
+
+
+
+ -
+
-
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
-
-
-
-
-
-
- false
-
-
- Show detailed differences
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- Close
-
-
- true
-
-
-
-
+
+
+
+ 11
+ true
+
+
+
+ Double-click on a file node to display the differences in context.
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Close
+
+
+ true
+
+
+
+
+
============================================================
--- src/model/Ancestors.cpp 40b168cdabbc4fbab891933ff9bd174bc434e4c6
+++ src/model/Ancestors.cpp ff279efc1a19d894af6db12104e7462b12cce760
@@ -50,13 +50,13 @@ void Ancestors::processTaskResult(const
{
if (task.getReturnCode() == 2)
{
- emit invalidAncestor(task.getOutputUtf8());
+ emit invalidAncestor(task.getDecodedOutput());
}
if (task.getReturnCode() != 0)
{
C(QString("Command returned with a non-zero return code (%1)")
- .arg(task.getOutputUtf8()));
+ .arg(task.getDecodedOutput()));
return;
}
@@ -65,7 +65,7 @@ void Ancestors::processTaskResult(const
selRevisions->clear();
delete selRevisions;
selRevisions = new RevisionList(
- task.getOutputUtf8().split('\n', QString::SkipEmptyParts)
+ task.getDecodedOutput().split('\n', QString::SkipEmptyParts)
);
// reset the view
reset();
============================================================
--- src/model/AutomateCommand.cpp 008019a4c691a5f977d2a6cb8b8cf347b652a63b
+++ src/model/AutomateCommand.cpp 1c819d32c321a539d0d59e100a632d17fdba16ca
@@ -112,7 +112,7 @@ void AutomateCommandHelper::taskAborted(
.arg(task.getCommandNumber())
.arg(QString::fromUtf8(task.getEncodedInput()))
.arg(task.getReturnCode())
- .arg(task.getOutputUtf8())
+ .arg(task.getDecodedOutput())
);
}
============================================================
--- src/model/Branches.cpp d0a1ee6db5af0f1a7cdf864d070868a6d87d4532
+++ src/model/Branches.cpp 6a240a83de4e8cf7aaf21467ba9b4205e586e487
@@ -45,7 +45,7 @@ void Branches::processTaskResult(const M
if (task.getReturnCode() != 0)
{
C(QString("Command returned with a non-zero return code (%1)")
- .arg(task.getOutputUtf8()));
+ .arg(task.getDecodedOutput()));
return;
}
@@ -73,11 +73,11 @@ void Branches::processTaskResult(const M
branches.appendRow(root);
builder = new TreeBuilder(root, this);
- builder->addList(task.getOutputUtf8());
+ builder->addList(task.getDecodedOutput());
}
else
{
- QStringList branchList = task.getOutputUtf8()
+ QStringList branchList = task.getDecodedOutput()
.split("\n", QString::SkipEmptyParts);
foreach (QString branch, branchList)
{
============================================================
--- src/model/Certs.cpp 8b011be58c9224fb726884374bd3d4941a8c7e36
+++ src/model/Certs.cpp 285dd2004b058cc9a7082ca34d0cd21fdc8d9765
@@ -44,11 +44,11 @@ void Certs::processTaskResult(const Mono
if (task.getReturnCode() != 0)
{
C(QString("Command returned with a non-zero return code (%1)")
- .arg(task.getOutputUtf8()));
+ .arg(task.getDecodedOutput()));
return;
}
- BasicIOParser parser(task.getOutputUtf8());
+ BasicIOParser parser(task.getDecodedOutput());
I(parser.parse());
StanzaList list = parser.getStanzas();
============================================================
--- src/model/ContentDiff.cpp 74852b2ba64c28376d51ada0f718228ba4612d5f
+++ src/model/ContentDiff.cpp fba40b0f3894f67596c8ea99293ab78212535b53
@@ -24,10 +24,8 @@ ContentDiff::ContentDiff(QObject * paren
#include
ContentDiff::ContentDiff(QObject * parent)
- : QAbstractItemModel(parent), AutomateCommand(0)
-{
- diffParser = 0;
-}
+ : QAbstractItemModel(parent), AutomateCommand(0), diffParser(0)
+{}
ContentDiff::~ContentDiff()
{
@@ -37,16 +35,16 @@ void ContentDiff::cleanup()
void ContentDiff::cleanup()
{
if (diffParser) delete diffParser;
+ diffParser = 0;
qDeleteAll(lines);
lines.clear();
reset();
}
void ContentDiff::readDatabaseDiff(const DatabaseFile & db, const QString & fileName,
- const QString & base, const QString & target)
+ const QString & base, const QString & target,
+ const QString & encoding)
{
- cleanup();
-
QStringList cmd;
cmd << "content_diff";
@@ -59,14 +57,19 @@ void ContentDiff::readDatabaseDiff(const
opts << "r" << base << "r" << target;
MonotoneTask task(cmd, opts);
+
+ if (!encoding.isEmpty())
+ {
+ task.setOutputEncoding(encoding);
+ }
+
AutomateCommand::enqueueDatabaseTask(db, task);
}
void ContentDiff::readWorkspaceDiff(const WorkspacePath & ws, const QString & fileName,
- const QString & base, const QString & target)
+ const QString & base, const QString & target,
+ const QString & encoding)
{
- cleanup();
-
QStringList cmd;
cmd << "content_diff";
@@ -87,20 +90,52 @@ void ContentDiff::readWorkspaceDiff(cons
}
MonotoneTask task(cmd, opts);
+
+ if (!encoding.isEmpty())
+ {
+ task.setOutputEncoding(encoding);
+ }
+
AutomateCommand::enqueueWorkspaceTask(ws, task);
}
+void ContentDiff::switchOutputEncoding(const QString & codec)
+{
+ if (!lastTask.isFinished())
+ {
+ D("task not yet finished, skip encoding switch");
+ return;
+ }
+
+ cleanup();
+
+ loadOutputIntoModel(lastTask.getDecodedOutput(codec));
+
+ emit encodingChanged(codec);
+}
+
void ContentDiff::processTaskResult(const MonotoneTask & task)
{
if (task.getReturnCode() != 0)
{
C(QString("Command returned with a non-zero return code (%1)")
- .arg(task.getOutputUtf8()));
+ .arg(task.getDecodedOutput()));
return;
}
- diffParser = new DiffParser(task.getOutputUtf8());
+ cleanup();
+ lastTask = task;
+ loadOutputIntoModel(task.getDecodedOutput());
+
+ emit diffRead();
+}
+
+void ContentDiff::loadOutputIntoModel(const QString & output)
+{
+ I(!diffParser);
+ diffParser = new DiffParser(output);
+
// flatten the data for the current view
FileDiffs fileDiffs = diffParser->getAllDiffs();
@@ -174,8 +209,6 @@ void ContentDiff::processTaskResult(cons
}
reset();
-
- emit diffRead();
}
int ContentDiff::columnCount(const QModelIndex & parent) const
============================================================
--- src/model/ContentDiff.h e89ba83d45953a4cfc745a4c7ad475e9733c37ff
+++ src/model/ContentDiff.h 38035d0dec91320d0fa33e58ffc5238a11109852
@@ -104,18 +104,22 @@ public slots:
inline FileDiffs getAllDiffs() { return diffParser->getAllDiffs(); }
public slots:
- void readDatabaseDiff(const DatabaseFile &, const QString &, const QString &, const QString &);
- void readWorkspaceDiff(const WorkspacePath &, const QString &, const QString &, const QString &);
+ void readDatabaseDiff(const DatabaseFile &, const QString &, const QString &, const QString &, const QString & encoding = QString());
+ void readWorkspaceDiff(const WorkspacePath &, const QString &, const QString &, const QString &, const QString & encoding = QString());
+ void switchOutputEncoding(const QString &);
signals:
void diffRead();
+ void encodingChanged(const QString &);
private:
void processTaskResult(const MonotoneTask &);
+ void loadOutputIntoModel(const QString &);
void cleanup();
DiffParser * diffParser;
ListLines lines;
+ MonotoneTask lastTask;
};
#endif
============================================================
--- src/model/GetAttributes.cpp ed421d842b53dc2400e2c1adaae282c53e34c250
+++ src/model/GetAttributes.cpp bd51d4f673480a28c18b78bf4290a4a5e0897589
@@ -67,11 +67,11 @@ void GetAttributes::processTaskResult(co
if (task.getReturnCode() != 0)
{
C(QString("Command returned with a non-zero return code (%1)")
- .arg(task.getOutputUtf8()));
+ .arg(task.getDecodedOutput()));
return;
}
- BasicIOParser parser(task.getOutputUtf8());
+ BasicIOParser parser(task.getDecodedOutput());
I(parser.parse());
StanzaList list = parser.getStanzas();
============================================================
--- src/model/GetContentChanged.cpp d0d630e76c1b8c7fee93d511fbfd1fd2eecb4bc7
+++ src/model/GetContentChanged.cpp 784b1572425d9af21934de417f6cbc65db3419f3
@@ -105,12 +105,12 @@ void GetContentChanged::processTaskResul
if (task.getReturnCode() != 0)
{
C(QString("Command returned with a non-zero return code (%1)")
- .arg(task.getOutputUtf8()));
+ .arg(task.getDecodedOutput()));
return;
}
QString current = task.getArguments().at(0);
- QString output = task.getOutputUtf8();
+ QString output = task.getDecodedOutput();
if (current == "parents")
{
============================================================
--- src/model/GetDatabaseVariables.cpp daa9eb7f0b0a9bb2f684182b2c4a499814c1c028
+++ src/model/GetDatabaseVariables.cpp b9ad21e33c9994caf29bdadcb74103c4bb3973de
@@ -40,7 +40,7 @@ void GetDatabaseVariables::processTaskRe
void GetDatabaseVariables::processTaskResult(const MonotoneTask & task)
{
- QString output = task.getOutputUtf8();
+ QString output = task.getOutput();
if (task.getReturnCode() != 0)
{
if (output.indexOf("No variables found") != -1)
@@ -51,7 +51,7 @@ void GetDatabaseVariables::processTaskRe
}
C(QString("Command returned with a non-zero return code (%1)")
- .arg(task.getOutputUtf8()));
+ .arg(task.getDecodedOutput()));
return;
}
============================================================
--- src/model/GetFile.cpp 3fffb3be172e0e28451322370f80dbf80408f132
+++ src/model/GetFile.cpp 735189cbe8ffb4e7cffd1a40e07fef37a0068ea4
@@ -23,13 +23,14 @@
#include
#include
-GetFile::GetFile(QObject * parent, const DatabaseFile & db)
- : QAbstractItemModel(parent), AutomateCommand(0), databaseFile(db)
+GetFile::GetFile(QObject * parent)
+ : QAbstractItemModel(parent), AutomateCommand(0)
{}
GetFile::~GetFile() {}
-void GetFile::readFileByName(const QString & fileName, const QString & rev)
+void GetFile::readFileByName(const DatabaseFile & db, const QString & fileName,
+ const QString & rev, const QString & encoding)
{
QStringList cmd;
cmd << "get_file_of" << fileName;
@@ -37,23 +38,30 @@ void GetFile::readFileByName(const QStri
QStringList opts;
opts << "r" << rev;
- readFile(cmd, opts);
+ readFile(db, cmd, opts, encoding);
}
-void GetFile::readFileById(const QString & fileID)
+void GetFile::readFileById(const DatabaseFile & db, const QString & fileID,
+ const QString & encoding)
{
QStringList cmd;
cmd << "get_file" << fileID;
- readFile(cmd, QStringList());
+ readFile(db, cmd, QStringList(), encoding);
}
-void GetFile::readFile(QStringList cmd, QStringList opts)
+void GetFile::readFile(const DatabaseFile & db, const QStringList & cmd,
+ const QStringList & opts, const QString & encoding)
{
- // reset attached views
reset();
MonotoneTask task(cmd, opts);
- AutomateCommand::enqueueDatabaseTask(databaseFile, task);
+
+ if (!encoding.isEmpty())
+ {
+ task.setOutputEncoding(encoding);
+ }
+
+ AutomateCommand::enqueueDatabaseTask(db, task);
}
void GetFile::processTaskResult(const MonotoneTask & task)
@@ -61,15 +69,31 @@ void GetFile::processTaskResult(const Mo
if (task.getReturnCode() != 0)
{
C(QString("Command returned with a non-zero return code (%1)")
- .arg(task.getOutputUtf8()));
+ .arg(task.getDecodedOutput()));
return;
}
+ lastTask = task;
- // FIXME: if the file contents is misinterpreted as utf-8, we have a
- // problem here. The only thing we could do here is to let the user
- // select the charset of the file and re-read it afterwards
- QString output = task.getOutputUtf8();
+ loadOutputIntoModel(task.getDecodedOutput());
+ emit fileRead();
+}
+
+void GetFile::switchOutputEncoding(const QString & codec)
+{
+ if (!lastTask.isFinished())
+ {
+ D("task not yet finished, skip encoding switch");
+ return;
+ }
+
+ loadOutputIntoModel(lastTask.getDecodedOutput(codec));
+
+ emit encodingChanged(codec);
+}
+
+void GetFile::loadOutputIntoModel(const QString & output)
+{
QRegExp rx("\\0x00");
if (rx.indexIn(output) != -1)
{
@@ -78,6 +102,9 @@ void GetFile::processTaskResult(const Mo
return;
}
+ Content oldContents = fileContents;
+ fileContents.clear();
+
QStringList lines(output.split(QRegExp("\\n|\\r\\n")));
for (int i=0, s=lines.size(); ihunks.size(); ihunks.at(i);
@@ -277,7 +302,7 @@ QVariant GetFile::data(const QModelIndex
case 1: return QVariant(line->rightLineCount == 0 ?
"-" : QString::number(line->rightLineCount));
case 2: return QVariant(line->content);
- default: I(false);
+ default: return QVariant();
}
}
else
============================================================
--- src/model/GetFile.h f185acd189190ef2d6d519a8f5adbfd727a3093d
+++ src/model/GetFile.h 73a82bb540ba6ca45cd9c6fcdc4f165a6ded958b
@@ -43,7 +43,7 @@ public:
{
Q_OBJECT
public:
- GetFile(QObject *, const DatabaseFile &);
+ GetFile(QObject *);
virtual ~GetFile();
// needed Qt Model methods
@@ -58,19 +58,22 @@ public slots:
QModelIndex getPrevGroup(const QModelIndex &, bool recurse = false);
public slots:
- void readFileById(const QString &);
- void readFileByName(const QString &, const QString &);
+ void readFileById(const DatabaseFile &, const QString &, const QString & encoding = QString());
+ void readFileByName(const DatabaseFile &, const QString &, const QString &, const QString & encoding = QString());
+ void switchOutputEncoding(const QString &);
void applyDiff(Diff * diff);
signals:
void fileRead();
+ void encodingChanged(const QString &);
private:
- void readFile(QStringList, QStringList);
+ void readFile(const DatabaseFile &, const QStringList &, const QStringList &, const QString & encoding = QString());
void processTaskResult(const MonotoneTask &);
+ void loadOutputIntoModel(const QString &);
Content fileContents;
- DatabaseFile databaseFile;
+ MonotoneTask lastTask;
};
#endif
============================================================
--- src/model/GetRevision.cpp 95014c1468ada6b5e60ed31407eec63f1a50975b
+++ src/model/GetRevision.cpp a59701ac07d146aab3ebb5f021c2ee92bb6bb085
@@ -57,11 +57,11 @@ void GetRevision::processTaskResult(cons
{
if (task.getReturnCode() != 0)
{
- emit readFailed(MonotoneUtil::stripMtnPrefix(task.getOutputUtf8()));
+ emit readFailed(MonotoneUtil::stripMtnPrefix(task.getDecodedOutput()));
return;
}
- BasicIOParser parser(task.getOutputUtf8());
+ BasicIOParser parser(task.getDecodedOutput());
I(parser.parse());
StanzaList list = parser.getStanzas();
============================================================
--- src/model/Inventory.cpp 4affff131bf9b3bbf87b6d2c38112754af3dfba9
+++ src/model/Inventory.cpp 7056e6451d09ab9dbb5793d2b9529a5fddff9420
@@ -95,7 +95,7 @@ void Inventory::processTaskResult(const
}
}
- QString output = task.getOutputUtf8();
+ QString output = task.getDecodedOutput();
// internal errors
if (task.getReturnCode() == 1)
============================================================
--- src/model/Keys.cpp 19dfda529004934172d6ceb4511eae24e30af3f6
+++ src/model/Keys.cpp 11aae606f14aaa15d64c9f68f651bf3630733dd6
@@ -39,14 +39,14 @@ void Keys::processTaskResult(const Monot
if (task.getReturnCode() != 0)
{
C(QString("Command returned with a non-zero return code (%1)")
- .arg(task.getOutputUtf8()));
+ .arg(task.getDecodedOutput()));
return;
}
reset();
keys.clear();
- BasicIOParser parser(task.getOutputUtf8());
+ BasicIOParser parser(task.getDecodedOutput());
I(parser.parse());
StanzaList list = parser.getStanzas();
============================================================
--- src/model/Manifest.cpp 235f3ddeb0e0514934b9df6f619e87ceb9d6f387
+++ src/model/Manifest.cpp 362e3fe7a8399c28ab69235376d5955421b2cd66
@@ -45,11 +45,11 @@ void Manifest::processTaskResult(const M
if (task.getReturnCode() != 0)
{
C(QString("Command returned with a non-zero return code (%1)")
- .arg(task.getOutputUtf8()));
+ .arg(task.getDecodedOutput()));
return;
}
- BasicIOParser parser(task.getOutputUtf8());
+ BasicIOParser parser(task.getDecodedOutput());
I(parser.parse());
StanzaList list = parser.getStanzas();
============================================================
--- src/model/Select.cpp ca967f456759195df4c53ec6922c0a8967273c35
+++ src/model/Select.cpp a82a300f0787e9ae330c0c8ca96083da99d82476
@@ -48,20 +48,20 @@ void Select::processTaskResult(const Mon
// is always fired if a invalid selector syntax has been given
if (task.getReturnCode() == 2)
{
- emit invalidSelection(task.getOutputUtf8());
+ emit invalidSelection(task.getDecodedOutput());
return;
}
if (task.getReturnCode() != 0)
{
C(QString("Command returned with a non-zero return code (%1)")
- .arg(task.getOutputUtf8()));
+ .arg(task.getDecodedOutput()));
return;
}
delete selRevisions;
selRevisions = new RevisionList(
- task.getOutputUtf8().split('\n', QString::SkipEmptyParts)
+ task.getDecodedOutput().split('\n', QString::SkipEmptyParts)
);
// reset the view
reset();
============================================================
--- src/model/Tags.cpp 80d62375cd40c37849eacf93a0bcb61d3983175b
+++ src/model/Tags.cpp 31c3f32539c54fb7bc7d676d18ad0581356f844c
@@ -49,13 +49,13 @@ void Tags::processTaskResult(const Monot
if (task.getReturnCode() != 0)
{
C(QString("Command returned with a non-zero return code (%1)")
- .arg(task.getOutputUtf8()));
+ .arg(task.getDecodedOutput()));
return;
}
tags->clear();
- BasicIOParser parser(task.getOutputUtf8());
+ BasicIOParser parser(task.getDecodedOutput());
I(parser.parse());
StanzaList list = parser.getStanzas();
============================================================
--- src/model/Toposort.cpp d081059ec2bc33341fc9b6fc75292072cb29a3fe
+++ src/model/Toposort.cpp c5f0896d43e6e9763571e201281ee49db94ad22e
@@ -120,11 +120,11 @@ void Toposort::processTaskResult(const M
if (task.getReturnCode() != 0)
{
C(QString("Command returned with a non-zero return code (%1)")
- .arg(task.getOutputUtf8()));
+ .arg(task.getDecodedOutput()));
return;
}
- QStringList sortedRevs(task.getOutputUtf8().split("\n"));
+ QStringList sortedRevs(task.getDecodedOutput().split("\n"));
for (int i=0, j=sortedRevs.size(); iinsert(sortedRevs.at(i), i);
============================================================
--- src/monotone/FileExporter.cpp d8841a939d1676436370923e9b88c9dbe0b64a9c
+++ src/monotone/FileExporter.cpp 8d23af2f0072da14f8c79d2d71b3db6701693729
@@ -93,7 +93,7 @@ bool FileExporter::exportFile(const File
if (out.getReturnCode() > 0)
{
C(QString("get_file_of '%1' (rev: %2) failed: %3")
- .arg(entry.path).arg(revision).arg(out.getOutputUtf8()));
+ .arg(entry.path).arg(revision).arg(out.getDecodedOutput()));
return false;
}
============================================================
--- src/monotone/MonotoneThread.cpp e3f258605fd1557753b903f13d1515b6e98d976b
+++ src/monotone/MonotoneThread.cpp b5fd6caedca9f2cbc910e172ffbee6c0e3d2d3f0
@@ -21,6 +21,7 @@
#include "BasicIOParser.h"
#include
+#include
MonotoneTask::MonotoneTask()
{
@@ -37,6 +38,7 @@ MonotoneTask::MonotoneTask(const Monoton
options = other.options;
output = other.output;
abortTask = other.abortTask;
+ outputEncoding = other.outputEncoding;
}
MonotoneTask::MonotoneTask(const QStringList & args)
@@ -66,6 +68,7 @@ void MonotoneTask::init(const ByteArrayL
returnCode = -1;
finished = false;
abortTask = false;
+ outputEncoding = "UTF-8";
static bool initialized = false;
if (!initialized)
@@ -121,6 +124,23 @@ QByteArray MonotoneTask::getEncodedInput
return commandLine;
}
+QString MonotoneTask::getDecodedOutput(const QString & enc) const
+{
+ QString encoding = enc;
+ if (encoding.isEmpty())
+ {
+ encoding = outputEncoding;
+ }
+ I(!encoding.isEmpty());
+
+ // QTextCodec implements codecForName as factory and caches multiple
+ // requests, so we don't need to do that ourselves
+ QTextCodec * codec = QTextCodec::codecForName(encoding.toLatin1());
+ I(codec);
+ return codec->toUnicode(output);
+}
+
+
const int MonotoneThread::StdioBufferSize = 50 * 1024 * 1024;
MonotoneThread::MonotoneThread(
============================================================
--- src/monotone/MonotoneThread.h b00320bbdc44039934898127d9093016adec9f16
+++ src/monotone/MonotoneThread.h dd3abaa03d5a86ab9141e3da15c0e62766e016aa
@@ -53,6 +53,9 @@ public:
//! marks that the task has been finished
void setFinished() { finished = true; }
+ //! set the output encoding
+ void setOutputEncoding(const QString & e) { outputEncoding = e; }
+
//! returns the command input stdio-encoded
QByteArray getEncodedInput() const;
@@ -65,8 +68,8 @@ public:
//! returns the raw monotone output
QByteArray getOutput() const { return output; }
- //! returns the monotone output as utf-8 encoded string
- QString getOutputUtf8() const { return QString::fromUtf8(output); }
+ //! converts the raw byte output into a unicode encoded QString
+ QString getDecodedOutput(const QString & enc = QString()) const;
//! returns the command's return code
int getReturnCode() const { return returnCode; }
@@ -99,6 +102,7 @@ private:
ByteArrayList arguments;
ByteArrayList options;
QByteArray output;
+ QString outputEncoding;
};
class MonotoneThread : public QThread
============================================================
--- src/monotone/MonotoneUtil.cpp 2679a231bcdd46393acc15364976563938c05325
+++ src/monotone/MonotoneUtil.cpp c18789f0f92cceb714cca6b981e50ab2437ea9ff
@@ -87,7 +87,7 @@ QString MonotoneUtil::getBaseWorkspaceRe
MonotoneTask out = runSynchronousWorkspaceTask(workspace, in);
if (!out.isFinished()) F("task aborted");
- QString data = out.getOutputUtf8();
+ QString data = out.getDecodedOutput();
if (out.getReturnCode() > 0)
{
C(QString("Could not execute get_base_revision_id: %1").arg(data));
@@ -108,7 +108,7 @@ QString MonotoneUtil::getOption(const Wo
MonotoneTask out = runSynchronousWorkspaceTask(workspace, in);
if (!out.isFinished()) F("task aborted");
- QString data = out.getOutputUtf8();
+ QString data = out.getDecodedOutput();
if (out.getReturnCode() > 0)
{
C(QString("Couldn't retrieve option %1: %2").arg(opt).arg(data));
@@ -169,7 +169,7 @@ QStringList MonotoneUtil::resolveSelecto
MonotoneTask out = runSynchronousDatabaseTask(db, in);
if (!out.isFinished()) F("task aborted");
- QString data = out.getOutputUtf8();
+ QString data = out.getDecodedOutput();
if (out.getReturnCode() > 0)
{
C(QString("Couldn't resolve selector %1: %2").arg(selector).arg(data));
@@ -186,7 +186,7 @@ RevisionCerts MonotoneUtil::getRevisionC
MonotoneTask out = runSynchronousDatabaseTask(db, in);
if (!out.isFinished()) F("task aborted");
- QString data = out.getOutputUtf8();
+ QString data = out.getDecodedOutput();
if (out.getReturnCode() > 0)
{
C(QString("Couldn't query revision certs for %1: %2").arg(revision).arg(data));
@@ -231,7 +231,7 @@ FileEntryList MonotoneUtil::getRevisionM
MonotoneTask out = runSynchronousDatabaseTask(db, in);
if (!out.isFinished()) F("task aborted");
- QString data = out.getOutputUtf8();
+ QString data = out.getDecodedOutput();
if (out.getReturnCode() > 0)
{
C(QString("Couldn't query manifest entries for %1: %2").arg(revision).arg(data));
@@ -294,7 +294,7 @@ QStringList MonotoneUtil::getPrivateKeyL
MonotoneTask out = runSynchronousDatabaseTask(db, in);
if (!out.isFinished()) F("task aborted");
- QString data = out.getOutputUtf8();
+ QString data = out.getDecodedOutput();
if (out.getReturnCode() > 0)
{
C(QString("Couldn't query keys: %1").arg(data));
@@ -338,7 +338,7 @@ QString MonotoneUtil::getFileId(const Da
MonotoneTask out = runSynchronousDatabaseTask(db, in);
if (!out.isFinished()) F("task aborted");
- QString data = out.getOutputUtf8();
+ QString data = out.getDecodedOutput();
if (out.getReturnCode() > 0)
{
C(QString("Couldn't identify path: %1").arg(data));
@@ -349,6 +349,56 @@ QString MonotoneUtil::getFileId(const Da
return data;
}
+bool MonotoneUtil::getAttribute(const WorkspacePath & ws, const QString & path,
+ const QString & attrname, QPair & attrval)
+{
+ MonotoneTask in(QStringList() << "get_attributes" << path);
+ MonotoneTask out = runSynchronousWorkspaceTask(ws, in);
+ if (!out.isFinished()) F("task aborted");
+
+ QString data = out.getDecodedOutput();
+ if (out.getReturnCode() > 0)
+ {
+ C(QString("Couldn't run get_attributes: %1").arg(data));
+ return false;
+ }
+
+ BasicIOParser parser(data);
+ I(parser.parse());
+ StanzaList stanzas = parser.getStanzas();
+
+ foreach (Stanza st, stanzas)
+ {
+ if (st.at(0).sym != "attr") continue;
+ if (st.at(0).vals.at(0) == attrname)
+ {
+ attrval.first = st.at(0).vals.at(1);
+ attrval.second = st.at(1).vals.at(0);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool MonotoneUtil::getAttribute(const DatabaseFile & db, const QString & revision,
+ const QString & path, const QString & attrname, QString & attrval)
+{
+ FileEntryList entryList = getRevisionManifest(db, revision);
+
+ foreach (FileEntry en, entryList)
+ {
+ if (en.path != path) continue;
+ if (en.attrs.contains(attrname))
+ {
+ attrval = en.attrs.value(attrname);
+ return true;
+ }
+ }
+
+ return false;
+}
+
/*!
Strips mtn: warning: and alike from error strings coming from mtn
and unwraps them, if this fails we add the original string unwrapped
============================================================
--- src/monotone/MonotoneUtil.h 7173990600fd78e4e75a5bc0111d2c29e2a06ed7
+++ src/monotone/MonotoneUtil.h 2859545454f0987d0bb5141a06a1f34667a9dc51
@@ -40,6 +40,8 @@ public:
static FileEntryList getRevisionManifest(const DatabaseFile &, const QString &);
static QStringList getPrivateKeyList(const DatabaseFile &);
static QString getFileId(const DatabaseFile &, const QString &);
+ static bool getAttribute(const WorkspacePath &, const QString &, const QString &, QPair &);
+ static bool getAttribute(const DatabaseFile &, const QString &, const QString &, const QString &, QString &);
// FIXME: decide what to do with that
static QString stripMtnPrefix(const QString &);
============================================================
--- src/monotone/WorkspaceCommitter.cpp d2a5ce169d18495c84ed56ecf92732b2c6646812
+++ src/monotone/WorkspaceCommitter.cpp 3efc567b8ef22e48f152f8b728a3b168ea0f3d0d
@@ -84,7 +84,7 @@ bool WorkspaceCommitter::run(const QStri
);
if (!out.isFinished()) F("task aborted");
- QString data = out.getOutputUtf8();
+ QString data = out.getDecodedOutput();
if (out.getReturnCode() > 0)
{
C(QString("Couldn't commit revision: %1").arg(data));
@@ -214,7 +214,7 @@ bool WorkspaceCommitter::putFile(const Q
MonotoneTask out = MonotoneUtil::runSynchronousWorkspaceTask(workspacePath, in);
if (!out.isFinished()) F("task aborted");
- QString data = out.getOutputUtf8();
+ QString data = out.getDecodedOutput();
if (out.getReturnCode() > 0)
{
C(QString("Cannot execute put_file: %1").arg(data));
@@ -248,7 +248,7 @@ bool WorkspaceCommitter::putCert(const Q
);
if (!out.isFinished()) F("task aborted");
- QString data = out.getOutputUtf8();
+ QString data = out.getDecodedOutput();
if (out.getReturnCode() > 0)
{
C(QString("Couldn't attach cert %1: %2").arg(key).arg(data));
============================================================
--- src/view/TreeView.cpp dcf826574e06d65e22db5a586caeb918673c00d0
+++ src/view/TreeView.cpp bf98bd50c56ec9d93411832cd4e3c5d5f08184b8
@@ -21,8 +21,12 @@
#include "vocab.h"
#include
+#include
-TreeView::TreeView(QWidget * parent) : QTreeView(parent) {}
+TreeView::TreeView(QWidget * parent) : QTreeView(parent)
+{
+ init();
+}
TreeView::TreeView(QWidget * parent, const QString & objName) : QTreeView(parent)
{
@@ -43,7 +47,26 @@ void TreeView::setModel(QAbstractItemMod
void TreeView::setModel(QAbstractItemModel * model)
{
+ QItemSelectionModel * oldSelectionModel = selectionModel();
+ if (oldSelectionModel != 0)
+ {
+ disconnect(
+ oldSelectionModel, SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
+ this, SLOT(itemSelectionChanged(const QItemSelection &, const QItemSelection &))
+ );
+ }
+
+ // each time a new model is set, a new selection model is internally
+ // created by Qt, so we need to re-connect to this new model to get
+ // notified about selection changes
QTreeView::setModel(model);
+ QItemSelectionModel * newSelectionModel = selectionModel();
+
+ connect(
+ newSelectionModel, SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
+ this, SLOT(itemSelectionChanged(const QItemSelection &, const QItemSelection &))
+ );
+
Settings::restoreHeaderViewState(header(), QString(objectName()).append("_header"));
stateLoaded = true;
}
@@ -104,3 +127,24 @@ void TreeView::contextMenuEvent(QContext
emit contextMenuRequested(currentSelection, mapToGlobal(pos));
}
+void TreeView::itemSelectionChanged(const QItemSelection & selected, const QItemSelection & deselected)
+{
+ // we're not interested in these
+ Q_UNUSED(deselected);
+
+ QModelIndexList selectedIndexes = selected.indexes();
+
+ for (int i=0; i 0)
+ {
+ selectedIndexes.removeAt(i);
+ continue;
+ }
+ i++;
+ }
+
+ emit selectedRows(selectedIndexes);
+}
+
============================================================
--- src/view/TreeView.h 7b872f64c09770fed7e6cf2dd321b6a798a05f90
+++ src/view/TreeView.h 651169fd52a772a8c03d883a3d75c35f52cb9524
@@ -37,11 +37,15 @@ signals:
signals:
void contextMenuRequested(const QModelIndexList &, const QPoint &);
+ void selectedRows(const QModelIndexList &);
private:
void saveHeaderViewState();
bool stateLoaded;
void contextMenuEvent(QContextMenuEvent *);
+
+private slots:
+ void itemSelectionChanged(const QItemSelection &, const QItemSelection &);
};
#endif
============================================================
--- src/view/WorkspaceWindow.cpp 9ae0a5ea1f3095ecc8824221b1d1523956942144
+++ src/view/WorkspaceWindow.cpp ade47c546f628f21ee7457e923e57d4a910370c4
@@ -114,12 +114,12 @@ void WorkspaceWindow::setup()
attrView->setAlternatingRowColors(true);
connect(
- treeView, SIGNAL(clicked(const QModelIndex &)),
- this, SLOT(readAttributes(const QModelIndex &))
+ treeView, SIGNAL(selectedRows(const QModelIndexList &)),
+ this, SLOT(maybeReadAttributes(const QModelIndexList &))
);
connect(
- listView, SIGNAL(clicked(const QModelIndex &)),
- this, SLOT(readAttributes(const QModelIndex &))
+ listView, SIGNAL(selectedRows(const QModelIndexList &)),
+ this, SLOT(maybeReadAttributes(const QModelIndexList &))
);
connect(
@@ -301,10 +301,17 @@ void WorkspaceWindow::openFile(const QSt
Platform::openFile(workspacePath + "/" + filePath);
}
-void WorkspaceWindow::readAttributes(const QModelIndex & index)
+void WorkspaceWindow::maybeReadAttributes(const QModelIndexList & indexes)
{
+ if (indexes.size() != 1)
+ {
+ D("multiple or no items selected");
+ attrModel->revert();
+ return;
+ }
+
QModelIndex sourceIndex = static_cast
- (index.model())->mapToSource(index);
+ (indexes.at(0).model())->mapToSource(indexes.at(0));
ModelItem * item = static_cast
(sourceIndex.internalPointer());
InventoryItem * invitem = dynamic_cast
@@ -312,14 +319,14 @@ void WorkspaceWindow::readAttributes(con
if (!invitem)
{
- D("item is not inventory item");
+ D("selected item is not inventory item");
attrModel->revert();
return;
}
if (invitem->isOldNode() || !invitem->isTracked())
{
- D("item is old node or not tracked");
+ D("selected item is old node or not tracked");
attrModel->revert();
return;
}
============================================================
--- src/view/WorkspaceWindow.h 3c181a5026143baf9e58dc86a97cf4ee5469356b
+++ src/view/WorkspaceWindow.h a463caf3a560c81ada20f1cd3eae8677644018b8
@@ -63,7 +63,7 @@ private slots:
InventoryWatcher * invWatcher;
private slots:
- void readAttributes(const QModelIndex &);
+ void maybeReadAttributes(const QModelIndexList &);
void invalidWorkspaceFormat(const QString &);
void openFile(const QString &);
};
============================================================
--- src/view/dialogs/FileDiff.cpp 699fafa30f746354fb9218fc18bc135e01e21e02
+++ src/view/dialogs/FileDiff.cpp f9e9afd79cc644e82dc4987ca845ae2e37dcc473
@@ -23,6 +23,7 @@
#include
#include
#include
+#include
FileDiff::FileDiff(QWidget * parent)
: Dialog(parent), diffModel(0), fileModel(0), fileProxyModel(0)
@@ -64,27 +65,8 @@ FileDiff::FileDiff(QWidget * parent)
scrollToPrev, SIGNAL(clicked()),
this, SLOT(getPrevGroup())
);
-}
-void FileDiff::forDatabase(const DatabaseFile & db, const QString & file,
- const QString & base, const QString & target)
-{
- fileName = file;
- loaded = false;
-
- QString title = windowTitle();
- setWindowTitle(title.arg(fileName));
-
- firstRevision->setText(
- firstRevision->text().arg(base.left(12).append("..."))
- );
-
- secondRevision->setText(
- secondRevision->text().arg(target.left(12).append("..."))
- );
-
- fileModel = new GetFile(this, db);
-
+ fileModel = new GetFile(this);
fileProxyModel = new GetFileProxyModel(this);
fileProxyModel->setSourceModel(fileModel);
@@ -103,19 +85,81 @@ void FileDiff::forDatabase(const Databas
this, SLOT(applyDiff())
);
- fileModel->readFileByName(fileName, base);
- diffModel->readDatabaseDiff(db, fileName, base, target);
+ ByteArrayList codecNamesAndAliases = QTextCodec::availableCodecs();
+ QSet codecNameSet;
+
+ // eliminate aliases
+ foreach (QByteArray codec, codecNamesAndAliases)
+ {
+ codecNameSet.insert(QTextCodec::codecForName(codec)->name());
+ }
+
+ ByteArrayList codecNames = codecNameSet.toList();
+ qSort(codecNames);
+
+ foreach (QByteArray codec, codecNames)
+ {
+ //! FIXME: better ordering, i.e. popular ones on top
+ textEncoding->addItem(QString(codec));
+ }
+
+ connect(
+ textEncoding, SIGNAL(currentIndexChanged(const QString &)),
+ this, SLOT(switchOutputEncoding(const QString &))
+ );
}
+void FileDiff::forDatabase(const DatabaseFile & db, const QString & file,
+ const QString & base, const QString & target)
+{
+ fileName = file;
+ loaded = false;
+ workspace = QString();
+
+ QString encoding = "UTF-8";
+ if (!MonotoneUtil::getAttribute(db, base, file, "guitone:file-encoding",
+ encoding))
+ {
+ L(QString("could not query file encoding of %1, using default").arg(file));
+ }
+ textEncoding->setCurrentIndex(textEncoding->findText(encoding));
+
+ setWindowTitle(tr("File differences of \"%1\"").arg(fileName));
+
+ firstRevision->setText(
+ tr("only left (%1)").arg(base.left(12).append("..."))
+ );
+
+ secondRevision->setText(
+ tr("only right (%1)").arg(target.left(12).append("..."))
+ );
+
+ fileModel->readFileByName(db, fileName, base, encoding);
+ diffModel->readDatabaseDiff(db, fileName, base, target, encoding);
+}
+
void FileDiff::forWorkspace(const WorkspacePath & ws, const QString & file,
const QString & base, const QString & target)
{
fileName = file;
loaded = false;
+ workspace = ws;
- QString title = windowTitle();
- setWindowTitle(title.arg(fileName));
+ QString encoding = "UTF-8";
+ QPair attrval;
+ if (!MonotoneUtil::getAttribute(ws, file, "guitone:file-encoding", attrval) ||
+ attrval.second == "dropped")
+ {
+ L(QString("could not query file encoding of %1, using default").arg(file));
+ }
+ else
+ {
+ encoding = attrval.first;
+ }
+ textEncoding->setCurrentIndex(textEncoding->findText(encoding));
+ setWindowTitle(tr("File differences of \"%1\"").arg(fileName));
+
QString left = tr("workspace parent");
QString right = tr("workspace revision");
@@ -129,46 +173,27 @@ void FileDiff::forWorkspace(const Worksp
right = target.left(12).append("...");
}
- firstRevision->setText(left);
- secondRevision->setText(right);
+ firstRevision->setText(tr("only left (%1)").arg(left));
+ secondRevision->setText(tr("only right (%1)").arg(right));
- fileModel = new GetFile(this, MonotoneUtil::getDatabaseFile(ws));
-
- fileProxyModel = new GetFileProxyModel(this);
- fileProxyModel->setSourceModel(fileModel);
-
- diffModel = new ContentDiff(this);
-
- diffView->setModel(fileProxyModel);
- diffStatusView->setModel(fileProxyModel);
-
- connect(
- fileModel, SIGNAL(fileRead()),
- this, SLOT(applyDiff())
- );
-
- connect(
- diffModel, SIGNAL(diffRead()),
- this, SLOT(applyDiff())
- );
-
+ DatabaseFile db = MonotoneUtil::getDatabaseFile(ws);
if (base.isEmpty())
{
QString workspaceParent = MonotoneUtil::getBaseWorkspaceRevision(ws);
- fileModel->readFileByName(fileName, workspaceParent);
- diffModel->readWorkspaceDiff(ws, fileName, workspaceParent, target);
+ fileModel->readFileByName(db, fileName, workspaceParent, encoding);
+ diffModel->readWorkspaceDiff(ws, fileName, workspaceParent, target, encoding);
return;
}
- fileModel->readFileByName(fileName, base);
- diffModel->readWorkspaceDiff(ws, fileName, base, target);
+ fileModel->readFileByName(db, fileName, base, encoding);
+ diffModel->readWorkspaceDiff(ws, fileName, base, target, encoding);
}
FileDiff::~FileDiff()
{
- if (fileModel) delete fileModel;
+ if (fileModel) delete fileModel;
if (fileProxyModel) delete fileProxyModel;
- if (diffModel) delete diffModel;
+ if (diffModel) delete diffModel;
}
void FileDiff::applyDiff()
@@ -279,3 +304,31 @@ void FileDiff::changeCurrentIndex(int po
}
}
+void FileDiff::switchOutputEncoding(const QString & encoding)
+{
+ // if we're not yet fully loaded the models, don't do anything
+ if (!loaded) return;
+
+ fileModel->switchOutputEncoding(encoding);
+ diffModel->switchOutputEncoding(encoding);
+
+ // the model data are converted instantly, so we don't have
+ // to wait for signals this time...
+ applyDiff();
+
+ if (!workspace.isEmpty())
+ {
+ MonotoneTask in(QStringList() << "set_attribute"
+ << fileName
+ << "guitone:file-encoding"
+ << encoding);
+ MonotoneTask out = MonotoneUtil::runSynchronousWorkspaceTask(workspace, in);
+
+ if (out.getReturnCode() != 0)
+ {
+ W(QString("couldn't set guitone:file-encoding on %1: %2")
+ .arg(fileName).arg(out.getDecodedOutput()));
+ }
+ }
+}
+
============================================================
--- src/view/dialogs/FileDiff.h 14c54d84f6d8f41b74cb461a378d942ec0db690f
+++ src/view/dialogs/FileDiff.h 752ff0409384d3e4220754274ea638604e4a278d
@@ -42,6 +42,7 @@ private slots:
void getPrevGroup();
void getNextGroup();
void changeCurrentIndex(int);
+ void switchOutputEncoding(const QString &);
private:
ContentDiff * diffModel;
@@ -49,6 +50,7 @@ private:
GetFileProxyModel * fileProxyModel;
QModelIndex currentIndex;
QString fileName;
+ WorkspacePath workspace;
bool loaded;
};
============================================================
--- src/view/dialogs/GenerateKeypair.cpp 6ed24f6d1bcee46cd89605ecbe0c3c5a6b17475c
+++ src/view/dialogs/GenerateKeypair.cpp 17c560ed391524a64ae4f86642641999a1eb99d7
@@ -72,7 +72,7 @@ void GenerateKeypair::accept()
this,
tr("Error creating keypair"),
tr("There was an error creating the keypair:\n%1")
- .arg(out.getOutputUtf8()),
+ .arg(out.getDecodedOutput()),
QMessageBox::Ok, 0, 0
);
return;
============================================================
--- src/view/dialogs/Preferences.cpp 1e3bc13f16b3a04e84f5fc8ce2add567a35db359
+++ src/view/dialogs/Preferences.cpp 211cc5978c8f41c19d41165fe4e56951043989cf
@@ -100,6 +100,11 @@ void Preferences::init()
Qt::Checked : Qt::Unchecked
);
+ saveEncodingAsFileAttribute->setCheckState(
+ Settings::getBool("SaveEncodingAsFileAttribute", true) ?
+ Qt::Checked : Qt::Unchecked
+ );
+
colorPickerAddedLines->setSelectedColor(
QColor(Settings::getString("DiffColorAddedLines", "green"))
);
@@ -180,6 +185,7 @@ void Preferences::accept()
Settings::setLogLevel(level);
Settings::setBool("CheckForUpdates", checkForUpdates->isChecked());
+ Settings::setBool("SaveEncodingAsFileAttribute", saveEncodingAsFileAttribute->isChecked());
Settings::setBool("RelaxedVersionCheck", relaxedVersionCheck->isChecked());
Settings::setBool("AskFileOpen", askFileOpen->isChecked());
Settings::setString("AskFileOpenExt", askFileOpenExtensions->text());
============================================================
--- src/view/dialogs/RevisionDiff.cpp c03a05117e11c00a098e0fd55b09385dc7cb205c
+++ src/view/dialogs/RevisionDiff.cpp 24e17c91450da9413c36beea817d744f313c2341
@@ -31,24 +31,12 @@ RevisionDiff::RevisionDiff(QWidget * par
diffView->setIndentation(10);
connect(
- diffView, SIGNAL(clicked(const QModelIndex &)),
- this, SLOT(enableDisableFileDiff(const QModelIndex &))
- );
-
- connect(
diffView, SIGNAL(doubleClicked(const QModelIndex &)),
this, SLOT(triggerFileDiff(const QModelIndex &))
);
- connect(
- showFileDiff, SIGNAL(clicked()),
- this, SLOT(triggerFileDiff())
- );
-
diffModel = new ContentDiff(this);
diffView->setModel(diffModel);
-
- showFileDiff->setEnabled(false);
}
RevisionDiff::~RevisionDiff()
@@ -108,33 +96,12 @@ void RevisionDiff::forWorkspace(const Wo
diffModel->readWorkspaceDiff(ws, filePath, base, target);
}
-void RevisionDiff::enableDisableFileDiff(const QModelIndex & index)
-{
- ListLine * line = static_cast(index.internalPointer());
- if (line->isFileLineAndDiffable())
- {
- fileName = line->fileName;
- showFileDiff->setEnabled(true);
- }
- else
- {
- showFileDiff->setEnabled(false);
- }
-}
-
void RevisionDiff::triggerFileDiff(const QModelIndex & index)
{
ListLine * line = static_cast(index.internalPointer());
if (line->isFileLineAndDiffable())
{
- fileName = line->fileName;
- triggerFileDiff();
+ emit fileDiff(line->fileName, baseRevision, targetRevision);
}
}
-void RevisionDiff::triggerFileDiff()
-{
- I(!fileName.isEmpty());
- emit fileDiff(fileName, baseRevision, targetRevision);
-}
-
============================================================
--- src/view/dialogs/RevisionDiff.h e536991efd9001e62a385f86c7130ea26b2cbee7
+++ src/view/dialogs/RevisionDiff.h bce21301eb5596f48b36be6f32947ec6b5cfea71
@@ -38,14 +38,11 @@ private:
private:
ContentDiff * diffModel;
- QString fileName;
QString baseRevision;
QString targetRevision;
private slots:
- void enableDisableFileDiff(const QModelIndex &);
void triggerFileDiff(const QModelIndex &);
- void triggerFileDiff();
};
#endif
============================================================
--- src/view/dialogs/RevisionManifest.cpp 6316625d53d8349258ae940ddc1f5c8d5dc641ec
+++ src/view/dialogs/RevisionManifest.cpp f329b383c8b9aced2fe93ecda59f704f53f17427
@@ -86,7 +86,7 @@ void RevisionManifest::openFile(const QM
if (out.getReturnCode() > 0)
{
- C(QString("Cannot execute get_file: %1").arg(out.getOutputUtf8()));
+ C(QString("Cannot execute get_file: %1").arg(out.getDecodedOutput()));
return;
}