#
#
# patch "i18n/guitone_de.ts"
# from [79bc887d4ffadd3faba7d75ed3cc3ccec81e6c9e]
# to [6be3e2fa47d6c27f9251ae59f70d35cde5bd8afe]
#
# patch "src/model/Monotone.cpp"
# from [e0c6415cf076a4202bb07b1450ba8dc4c849f895]
# to [4cc05b131cecb36322a3d7d429284b85a8bfd712]
#
# patch "src/model/Monotone.h"
# from [56a26664cc846b890ac19ab47e9ce2e0a3686a94]
# to [2d1520727dceebdf384cf8b6f93b44164917b119]
#
# patch "src/model/Workspace.cpp"
# from [d9af7b5957edc7427aba2ce770b58693b668a155]
# to [2da2321fcd0d8925d6a5438a86029e1411624c76]
#
# patch "src/view/Guitone.cpp"
# from [b7382268b4b19157b7f3490d031f72bc601c2e1b]
# to [613f05389f207af2e7a267b624a7d754e1d86e71]
#
# patch "src/view/Guitone.h"
# from [8420bd69cc67c4cb78a9c4cc528bdf3bc0c4f15c]
# to [8f614347750418fabecb935530e5037eda3b703d]
#
============================================================
--- i18n/guitone_de.ts 79bc887d4ffadd3faba7d75ed3cc3ccec81e6c9e
+++ i18n/guitone_de.ts 6be3e2fa47d6c27f9251ae59f70d35cde5bd8afe
@@ -67,6 +67,10 @@
&Importiere Arbeitsbereich
+
+
+
+
Monotone
@@ -80,20 +84,28 @@
- Prozess beendet
+ Prozess beendet
- Die interne Verbindung zum Monotone-Prozess wurde beendet (Code %1, Status %2)
+ Die interne Verbindung zum Monotone-Prozess wurde beendet (Code %1, Status %2)
- Fehler beim Starten von Monotone
+ Fehler beim Starten von Monotone
- Konnte den monotone-Prozess nicht starten (ProcessError %1). Ist das Programm korrekt installiert?
+ Konnte den monotone-Prozess nicht starten (ProcessError %1). Ist das Programm korrekt installiert?
+
+
+
+
+
+
+
+
SandboxItem
============================================================
--- src/model/Monotone.cpp e0c6415cf076a4202bb07b1450ba8dc4c849f895
+++ src/model/Monotone.cpp 4cc05b131cecb36322a3d7d429284b85a8bfd712
@@ -22,87 +22,75 @@
Monotone* Monotone::instance = 0;
-Monotone::Monotone(QDir *workingDirectory) : QProcess()
+Monotone::Monotone(QObject * parent) : QObject(parent), process(0)
{
isProcessingData = false;
output = new QStringList();
-
+}
+
+void Monotone::setup(QDir *workingDirectory)
+{
+ if (process) { delete process; process = 0; }
+
+ process = new QProcess(this);
+
// read & parse mtn's output as soon as it gets available
connect(
- this, SIGNAL(readyReadStandardOutput()),
+ process, SIGNAL(readyReadStandardOutput()),
this, SLOT(parseLineFromStdout())
);
-
+
// monitor if the process is exited unexpectedly
connect(
- this, SIGNAL(finished(int, QProcess::ExitStatus)),
+ process, SIGNAL(finished(int, QProcess::ExitStatus)),
this, SLOT(processTerminated(int, QProcess::ExitStatus))
);
-
+
// check if there occurs an startup error
connect(
- this, SIGNAL(error(QProcess::ProcessError)),
+ process, SIGNAL(error(QProcess::ProcessError)),
this, SLOT(startupError(QProcess::ProcessError))
);
-
- setWorkingDirectory(workingDirectory->absolutePath());
+
+ process->setWorkingDirectory(workingDirectory->absolutePath());
+
QStringList args;
args << "automate";
args << "stdio";
-
+
// Start up monotone's executable 'mtn'
- start("mtn", args);
+ qDebug("Starting mtn...");
+ process->start("mtn", args);
+ qDebug("Start returned.");
}
Monotone::~Monotone()
{
// terminate any running process
- terminate();
+ process->terminate();
+ delete process;
+ process = 0;
}
-Monotone* Monotone::singleton(QDir *workingDirectory = NULL)
+Monotone* Monotone::singleton(QObject * parent)
{
- // if we have no instance created yet we need a workspace directory
- Q_ASSERT( !(workingDirectory == NULL && instance == 0) );
-
- // create a new instance if there is either no instance
- // or a new working directory has been explicitely given
- if (instance == 0 || workingDirectory != NULL)
- {
- instance = new Monotone(workingDirectory);
- }
+ // create a new instance if there is no instance
+ if (instance == 0) { instance = new Monotone(parent); }
return instance;
}
-void Monotone::startupError(QProcess::ProcessError error)
+void Monotone::startupError(QProcess::ProcessError /* error */)
{
- QMessageBox::critical(
- NULL,
- tr("Monotone startup error"),
- tr("Couldn't startup the monotone process (ProcessError %1). Have you installed it properly?")
- .arg(error),
- QMessageBox::Ok, 0, 0
- );
- qApp->exit(1);
+ emit criticalError(tr("Monotone failed to start. Have you installed it properly?"));
}
-void Monotone::processTerminated(int code, QProcess::ExitStatus status)
+void Monotone::processTerminated(int code, QProcess::ExitStatus /* status */)
{
// this was a normal exit
if (code == 0) return;
-
- // TODO: log the error output somewhere or at least output it on guitone's STDERR
- // QProcess' buffers are still intact at this point
- QMessageBox::critical(
- NULL,
- tr("Process exited"),
- tr("The internal connection to the monotone process was terminated (code %1, status %2)")
- .arg(code)
- .arg(status),
- QMessageBox::Ok, 0, 0
- );
- qApp->exit(1);
+
+ emit criticalError(tr("The connection to the monotone process was terminated."));
}
bool Monotone::triggerCommand(QString cmd)
@@ -110,26 +98,28 @@
// wait until the process has been started up if it is not already
// running. Notice that if waitForStartup times out after 15 seconds
// the error handler is called and the program is terminated!
- if (state() != QProcess::Running && !waitForStarted(15000))
+ if (process->state() != QProcess::Running && !process->waitForStarted(15000))
{
+ qDebug("QProcess is not running.");
return false;
}
-
+
// check if we're already processing a command
if (isProcessingData)
{
+ qDebug("Process is already busy.");
return false;
}
-
+
isProcessingData = true;
output->clear();
-
+
QString finalCmd;
QStringList parts = QStringList::split(' ', cmd);
-
+
// a command starts with a lowercase L
finalCmd += "l";
-
+
// and each part of the command is prefixed with its size
// separated by a colon
for (QStringList::Iterator it = parts.begin(); it != parts.end(); ++it)
@@ -138,47 +128,47 @@
finalCmd += ":";
finalCmd += *it;
}
-
+
// finally, the cmd ends with "e\n"
finalCmd += "e\n";
qDebug("Final command: %s", finalCmd.latin1());
-
+
// QProcess in QT4 dosen't have a writeToStdin().
// So we need the following QTextStream
- QTextStream streamStdIn(this);
-
+ QTextStream streamStdIn(process);
+
// Write our finalCmd to mtn's StdIn
streamStdIn << finalCmd;
-
+
return true;
}
void Monotone::parseLineFromStdout()
{
QByteArray byteArray;
-
+
// read all data from stdin
//byteArray = readStdout();
- byteArray = readAllStandardOutput();
+ byteArray = process->readAllStandardOutput();
QString temp(byteArray);
-
+
// splits the input into lines
- QStringList inputList = QStringList::split("\n", temp);
-
+ QStringList inputList = QStringList::split("\n", temp);
+
QString lineFromStdIn("");
-
+
// parse out the contents of each line
- QRegExp regex("^(\\d+):(\\d+):([ml]):(\\d+):([^\\n]*)");
+ QRegExp regex("^(\\d+):(\\d+):([ml]):(\\d+):([^\\n]*)");
for (QStringList::Iterator it = inputList.begin(); it != inputList.end(); ++it )
{
- lineFromStdIn = *it;
+ lineFromStdIn = *it;
if (regex.search(lineFromStdIn) == -1)
{
qWarning("Monotone::parseLineFromStdout: Can't parse data %s", lineFromStdIn.latin1());
continue;
}
- QStringList list = regex.capturedTexts();
-
+ QStringList list = regex.capturedTexts();
+
// last output? then this contains just the status,
// and no additional information
if (list[3].compare("l") == 0)
@@ -186,9 +176,9 @@
isProcessingData = false;
emit commandFinished(list[2].toInt());
break;
- }
+ }
// valid output, append it
- output->append(list[5]);
+ output->append(list[5]);
}
}
============================================================
--- src/model/Monotone.h 56a26664cc846b890ac19ab47e9ce2e0a3686a94
+++ src/model/Monotone.h 2d1520727dceebdf384cf8b6f93b44164917b119
@@ -21,45 +21,45 @@
#ifndef MONOTONE_H
#define MONOTONE_H
+#include
//
// Forward class declarations
//
class QDir;
-//#include
-//
-// Lib Includes
-//
-#include
-
-
-class Monotone : public QProcess
+class Monotone : public QObject
{
Q_OBJECT
-
+
public:
- static Monotone* singleton(QDir*);
- void init(QDir*);
- ~Monotone();
+ static Monotone* singleton(QObject * parent = 0);
+
+ void setup(QDir*);
+ virtual ~Monotone();
+
bool triggerCommand(QString cmd);
QStringList* getOutput();
-
+
protected:
- Monotone(QDir*);
-
- private:
+ Monotone(QObject *);
+
+ private:
QStringList *output;
bool isProcessingData;
static Monotone* instance;
+ QProcess * process;
+
private slots:
void parseLineFromStdout();
void processTerminated(int, QProcess::ExitStatus);
void startupError(QProcess::ProcessError);
-
+
signals:
void commandFinished(int returnCode);
+
+ void criticalError(const QString &);
};
#endif
============================================================
--- src/model/Workspace.cpp d9af7b5957edc7427aba2ce770b58693b668a155
+++ src/model/Workspace.cpp 2da2321fcd0d8925d6a5438a86029e1411624c76
@@ -66,24 +66,26 @@
{
// enable the wait cursor
qApp->setOverrideCursor(Qt::WaitCursor);
-
- monotone = Monotone::singleton(workspaceDir);
-
+
+ monotone = Monotone::singleton();
+
connect(
monotone, SIGNAL(commandFinished(int)),
this, SLOT(parseInventory(int))
);
+ monotone->setup(workspaceDir);
+
return monotone->triggerCommand("inventory");
}
void Workspace::parseInventory(int returnCode)
{
QStringList *output = monotone->getOutput();
-
+
// TODO: Better error reporting!
if ((returnCode > 0) && (!output->isEmpty()))
- {
+ {
QString error = output->front();
qWarning("A error occured: %s", error.latin1());
// restore the normal cursor
@@ -97,16 +99,16 @@
qApp->restoreOverrideCursor();
return;
}
-
+
QRegExp regex("^(R|D|[ ])(R|A|[ ])(M|P|U|I|[ ])\\s(\\d+)\\s(\\d+)\\s(.+)$");
regex.setMinimal(true);
-
+
QMap renameMap;
QMap::iterator renameIter;
WorkspaceItem *item;
QList* tempItems = new QList();
-
+
for (QStringList::Iterator it = output->begin(); it != output->end(); ++it)
{
if (regex.search(*it) == -1)
@@ -199,7 +201,7 @@
}
// Display the item properties
- //qDebug("Item: Name %s, PATH %s, Status %s, IsDir %d",
+ //qDebug("Item: Name %s, PATH %s, Status %s, IsDir %d",
// item->getFilename().trimmed().latin1(),
// item->getPath().trimmed().latin1(),
// item->statusString().trimmed().latin1(),
@@ -219,7 +221,7 @@
renameMap[id]->setRenamedFrom(renameMap[-id]);
renameMap[-id]->setRenamedTo(renameMap[id]);
}
-
+
// clear the map to avoid memory leaks by having pointers to objects
// in more than one container
// TODO: we should still look out for some tool which allows us to
@@ -229,11 +231,11 @@
rootItem->setChildren(*(buildTreeRecursive(tempItems, NULL)));
delete tempItems;
-
+
// reset the model to repaint the view completly
// (all QModelIndexes are discarded through that, e.g. selections!)
this->reset();
-
+
// restore the normal cursor
qApp->restoreOverrideCursor();
@@ -281,10 +283,10 @@
{
currentItem->setChildren(*(buildTreeRecursive(items, currentItem)));
}
-
+
// append item to final list
finalItems->push_back(currentItem);
-
+
}
return finalItems;
}
@@ -304,13 +306,13 @@
}
WorkspaceItem *childItem = parentItem->child(row);
-
+
if (childItem)
{
return createIndex(row, column, childItem);
}
-
- return QModelIndex();
+
+ return QModelIndex();
}
int Workspace::columnCount(const QModelIndex &parent) const
@@ -331,7 +333,7 @@
}
WorkspaceItem *item = static_cast(index.internalPointer());
-
+
if((role == Qt::DecorationRole))
{
return iconProvider->getIcon(item);
@@ -349,7 +351,7 @@
return Qt::ItemIsEnabled;
}
- // TODO: add Qt::ItemIsDragEnabled and Qt::ItemIsDropEnabled as soon as this works...
+ // TODO: add Qt::ItemIsDragEnabled and Qt::ItemIsDropEnabled as soon as this works...
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
@@ -370,7 +372,7 @@
{
return QModelIndex();
}
-
+
WorkspaceItem *childItem = static_cast(index.internalPointer());
WorkspaceItem *parentItem = childItem->parent();
@@ -381,8 +383,8 @@
return createIndex(parentItem->row(), 0, parentItem);
}
-
-int Workspace::rowCount(const QModelIndex& parent) const
+
+int Workspace::rowCount(const QModelIndex& parent) const
{
WorkspaceItem *parentItem = rootItem;
@@ -391,6 +393,6 @@
parentItem = static_cast(parent.internalPointer());
}
- return parentItem->childCount();
+ return parentItem->childCount();
}
+
-
============================================================
--- src/view/Guitone.cpp b7382268b4b19157b7f3490d031f72bc601c2e1b
+++ src/view/Guitone.cpp 613f05389f207af2e7a267b624a7d754e1d86e71
@@ -19,22 +19,28 @@
***************************************************************************/
#include "Guitone.h"
+#include "../model/Monotone.h"
Guitone::Guitone()
: QMainWindow()
{
+ gotError = false;
setCaption(tr("guitone - a frontend for monotone"));
-
+
// create Workspace model
myWorkspace = new Workspace(this);
+ // connect Monotone:
+ connect(Monotone::singleton(this), SIGNAL(criticalError(const QString &)),
+ this, SLOT(criticalMtnError(const QString &)));
+
//
// Menubar
//
menu = menuBar()->addMenu(tr("&File"));
QAction* act = menu->addAction(tr("&Import Working Directory..."), this, SLOT(chooseWorkspace()));
act->setShortcut(tr("Ctrl+I", "Import"));
-
+
act = menu->addAction(tr("&Quit"), this, SLOT(close()));
act->setShortcut(tr("Ctrl+Q", "Quit"));
@@ -43,8 +49,8 @@
//
toolBar = new QToolBar(this);
toolBar->setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea);
- addToolBar(toolBar);
-
+ addToolBar(toolBar);
+
//
// Main view
//
@@ -57,7 +63,7 @@
listView = new WorkspaceView(mainSplitter, WorkspaceView::FileList);
listView->setModel(myWorkspace);
- listView->setSelectionModel(selection);
+ listView->setSelectionModel(selection);
/*
treeView->setRootIndex(mySandbox->index(0,0));
listView->setRootIndex(mySandbox->index(0,0));
@@ -68,13 +74,13 @@
connect(treeView, SIGNAL(updateDisplay(std::list*)),
listView, SLOT(display(std::list*)));
-
+
connect(treeView, SIGNAL(findAndSelectItem(SandboxItem*)),
this, SLOT(doFindAndSelectItem(SandboxItem*)));
connect(listView, SIGNAL(findAndSelectItem(SandboxItem*)),
this, SLOT(doFindAndSelectItem(SandboxItem*)));
-
- */
+
+ */
setCentralWidget(mainSplitter);
resize(450, 600);
@@ -85,6 +91,16 @@
Guitone::~Guitone() {}
+void Guitone::criticalMtnError(const QString & msg)
+{
+ if (gotError == false)
+ {
+ gotError = true;
+ QMessageBox::critical(NULL, tr("Critical Monotone Error"),
+ msg, QMessageBox::Ok, 0, 0);
+ qApp->exit(1);
+ }
+}
void Guitone::chooseWorkspace()
{
@@ -138,14 +154,14 @@
treeView->selectItem(sbItem);
return;
}
-
- // check if the element can be selected in the current list
+
+ // check if the element can be selected in the current list
if (listView->selectItem(sbItem))
{
return;
}
-
- // the item doesn't seem to be in the current list,
+
+ // the item doesn't seem to be in the current list,
// lets try to select its parent first, this updates
// the list and we may have then luck and see the correct
// selected item
============================================================
--- src/view/Guitone.h 8420bd69cc67c4cb78a9c4cc528bdf3bc0c4f15c
+++ src/view/Guitone.h 8f614347750418fabecb935530e5037eda3b703d
@@ -48,6 +48,7 @@
~Guitone();
private slots:
void chooseWorkspace();
+ void criticalMtnError(const QString &);
//void doFindAndSelectItem( WorkspaceItem* );
private:
@@ -56,6 +57,8 @@
Workspace *myWorkspace;
WorkspaceView *treeView;
WorkspaceView *listView;
+
+ bool gotError;
};