# # # patch "src/model/AutomateCommand.cpp" # from [419f678ac1d3f6cf45698f159f768211f70a0473] # to [5f6eda24fc7823b2827e33dd0c70108ca4f1f4ef] # # patch "src/model/AutomateCommand.h" # from [9793ba5d7cb5b1b5e7199bd0783dcf074098892f] # to [93a7d2bbd7d51d8b0f75ff9d63092ffc69aaa247] # # patch "src/model/GetContentChanged.cpp" # from [722cb14ca2adcc68a73ce4407f8b47caf0dd1cb8] # to [d0d630e76c1b8c7fee93d511fbfd1fd2eecb4bc7] # # patch "src/model/GetContentChanged.h" # from [f906c204fe129f2b10e00f9514efeaff8750ded3] # to [be46c46e9e3222c6acb9a2d63b7ec274b98b9aa3] # # patch "src/monotone/MonotoneManager.cpp" # from [b9855a52aab2aa5bb2aedaebf691a8ccdd3649e8] # to [54e438b649a9ec2fef348acd644a838725744103] # # patch "src/monotone/MonotoneManager.h" # from [4d6839413e423765e63f7eb98352c45342f1fbda] # to [a3047e1cacbd06d1d46cfae6a8c8fd32957d8be6] # # patch "src/monotone/MonotoneThread.cpp" # from [108dcf4c1eca755f70892a76fe5014ef791e3984] # to [05acb212fc9dce4c276d00cce24105fc8c6bc1f3] # # patch "src/monotone/MonotoneThread.h" # from [63077cbecc190aab81276698cd375d67e4c42df8] # to [b00320bbdc44039934898127d9093016adec9f16] # # patch "src/view/dialogs/Dialog.cpp" # from [5d9964b17b91997764ac1e42447afeef2d4c039f] # to [de467d48aa140cb218789df1069f24b4eb8550da] # # patch "src/view/dialogs/Dialog.h" # from [4e6ee1ac9f09821bd37f888f8aaabb12663a6a5b] # to [ae5a57894efa5fe15da18bb165997f5fd0535856] # # patch "src/view/dialogs/FileHistory.cpp" # from [57e211a968aec67716db2f91d43d9c64c6299865] # to [4fe062ee0d08f3ccd2fc323efa664208e62f4891] # ============================================================ --- src/model/AutomateCommand.cpp 419f678ac1d3f6cf45698f159f768211f70a0473 +++ src/model/AutomateCommand.cpp 5f6eda24fc7823b2827e33dd0c70108ca4f1f4ef @@ -70,6 +70,7 @@ void AutomateCommand::enqueueTask(Monoto ); } + void AutomateCommand::enqueueWorkspaceTask(const WorkspacePath & ws, const MonotoneTask & task) { MonotoneThread * thread = APP->manager()->getThreadForWorkspace(ws); @@ -82,12 +83,29 @@ void AutomateCommand::enqueueDatabaseTas enqueueTask(thread, task); } +void AutomateCommand::stopAllTasks() +{ + QMutexLocker locker(&lock); + + QMapIterator > it(queuedCommands); + + while (it.hasNext()) + { + it.next(); + if (it.value().size() == 0) continue; + APP->manager()->getThreadByNumber(it.key())->removeTasks(it.value()); + } +} + AutomateCommandHelper::AutomateCommandHelper(AutomateCommand * cmd) : command(cmd) {} void AutomateCommandHelper::taskAborted(const MonotoneTask & task) { + // the task was aborted explicitely, no need to be verbose here + if (task.isAborted()) return; + // do sth more reasonable here in a subclass, // i.e. try to query the data again C(QString("Task %1 (%2) aborted: %3") @@ -102,12 +120,14 @@ void AutomateCommandHelper::taskFinished int threadNumber = task.getThreadNumber(); int cmdNumber = task.getCommandNumber(); - if (!command->queuedCommands.contains(threadNumber) || - !command->queuedCommands[threadNumber].contains(cmdNumber)) - { + bool threadFound = command->queuedCommands.contains(threadNumber); + int commandIdx = !threadFound ? -1 : + command->queuedCommands[threadNumber].indexOf(cmdNumber); + + if (commandIdx == -1) return; - } + command->queuedCommands[threadNumber].removeAt(commandIdx); command->processTaskResult(task); } ============================================================ --- src/model/AutomateCommand.h 9793ba5d7cb5b1b5e7199bd0783dcf074098892f +++ src/model/AutomateCommand.h 93a7d2bbd7d51d8b0f75ff9d63092ffc69aaa247 @@ -38,6 +38,7 @@ protected: virtual void processTaskResult(const MonotoneTask &) = 0; void enqueueWorkspaceTask(const WorkspacePath &, const MonotoneTask &); void enqueueDatabaseTask(const DatabaseFile &, const MonotoneTask &); + void stopAllTasks(); private: void enqueueTask(MonotoneThread * thread, const MonotoneTask &); ============================================================ --- src/model/GetContentChanged.cpp 722cb14ca2adcc68a73ce4407f8b47caf0dd1cb8 +++ src/model/GetContentChanged.cpp d0d630e76c1b8c7fee93d511fbfd1fd2eecb4bc7 @@ -30,6 +30,7 @@ GetContentChanged::~GetContentChanged() { revisions.clear(); pathInRevision.clear(); + revsForPathStack.clear(); } // @@ -59,6 +60,8 @@ void GetContentChanged::readChanges(cons { revisions.clear(); pathInRevision.clear(); + revsForPathStack.clear(); + stopReadingChanges = false; // reset the view reset(); @@ -70,20 +73,29 @@ void GetContentChanged::readChanges(cons queryContentChanged(startRev, startPath); } +void GetContentChanged::stopReading() +{ + stopReadingChanges = true; + AutomateCommand::stopAllTasks(); +} + void GetContentChanged::queryContentChanged(const QString & rev, const QString & path) { + if (stopReadingChanges) return; MonotoneTask task(QStringList() << "get_content_changed" << rev << path); AutomateCommand::enqueueDatabaseTask(databaseFile, task); } void GetContentChanged::queryParents(const QString & rev) { + if (stopReadingChanges) return; MonotoneTask task(QStringList() << "parents" << rev); AutomateCommand::enqueueDatabaseTask(databaseFile, task); } void GetContentChanged::queryCorrespondingPath(const QString & rev, const QString & path, const QString & par) { + if (stopReadingChanges) return; MonotoneTask task(QStringList() << "get_corresponding_path" << rev << path << par); AutomateCommand::enqueueDatabaseTask(databaseFile, task); } @@ -105,7 +117,6 @@ void GetContentChanged::processTaskResul if (output.isEmpty()) { - reset(); emit rootReached(); return; } @@ -147,7 +158,9 @@ void GetContentChanged::processTaskResul if (revisions.contains(rev)) continue; // append the revision to the ordered list + beginInsertRows(QModelIndex(), revisions.size(), revisions.size()); revisions.append(rev); + endInsertRows(); // check if we already know the path in that revision if (!pathInRevision.contains(rev)) @@ -176,7 +189,6 @@ void GetContentChanged::processTaskResul // revision, we've reached the end of this development line if (output.isEmpty()) { - reset(); emit endOfLineReached(); return; } @@ -196,7 +208,15 @@ void GetContentChanged::processTaskResul // however the only list that counts is revisions pathInRevision.insert(rev, path); - // try to get the next marked node + // if this revision is one of the interesting ones, notify the views + // to re-read the data + int row = revisions.indexOf(rev); + if (row != -1) + { + QModelIndex index = createIndex(row, 1, 0); + emit dataChanged(index, index); + } + queryContentChanged(rev, path); return; } @@ -232,12 +252,12 @@ QVariant GetContentChanged::data(const Q int row = index.row(); if (row >= revisions.size()) return QVariant(); QString rev = revisions.at(row); - I(pathInRevision.contains(rev)); + QString path = pathInRevision.contains(rev) ? pathInRevision.value(rev) : ""; switch (col) { case 0: return QVariant(rev); - case 1: return QVariant(pathInRevision.value(rev)); + case 1: return QVariant(path); } return QVariant(); } ============================================================ --- src/model/GetContentChanged.h f906c204fe129f2b10e00f9514efeaff8750ded3 +++ src/model/GetContentChanged.h be46c46e9e3222c6acb9a2d63b7ec274b98b9aa3 @@ -43,6 +43,7 @@ public slots: public slots: void readChanges(const QString &, const QString &); + void stopReading(); signals: // is emitted each time the algorithm reaches the end of a @@ -69,6 +70,7 @@ private: QString startPath; DatabaseFile databaseFile; + bool stopReadingChanges; }; #endif ============================================================ --- src/monotone/MonotoneManager.cpp b9855a52aab2aa5bb2aedaebf691a8ccdd3649e8 +++ src/monotone/MonotoneManager.cpp 54e438b649a9ec2fef348acd644a838725744103 @@ -106,6 +106,15 @@ MonotoneThread * MonotoneManager::getThr return getThread(database, QString()); } +MonotoneThread * MonotoneManager::getThreadByNumber(int threadNumber) +{ + if (!threadMap.contains(threadNumber)) + { + throw GuitoneException(tr("No such thread: %1").arg(threadNumber)); + } + return threadMap.value(threadNumber); +} + MonotoneThread * MonotoneManager::getThread(const DatabaseFile & database, const WorkspacePath & workspace) { QMutexLocker locker(&lock); ============================================================ --- src/monotone/MonotoneManager.h 4d6839413e423765e63f7eb98352c45342f1fbda +++ src/monotone/MonotoneManager.h a3047e1cacbd06d1d46cfae6a8c8fd32957d8be6 @@ -45,6 +45,9 @@ public: //! returns an appropriate MonotoneThread for the given database MonotoneThread * getThreadForDatabase(const DatabaseFile &); + //! returns a thread by a given thread number + MonotoneThread * getThreadByNumber(int); + //! runs a single command and returns its output static bool singleRun(const QString &, const QStringList &, QByteArray &); ============================================================ --- src/monotone/MonotoneThread.cpp 108dcf4c1eca755f70892a76fe5014ef791e3984 +++ src/monotone/MonotoneThread.cpp 05acb212fc9dce4c276d00cce24105fc8c6bc1f3 @@ -64,6 +64,7 @@ void MonotoneTask::init(const ByteArrayL options = opts; returnCode = -1; finished = false; + abortTask = false; static bool initialized = false; if (!initialized) @@ -146,6 +147,19 @@ int MonotoneThread::enqueueTask(const Mo return commandNumber; } +void MonotoneThread::removeTasks(QList commandNumbers) +{ + QMutexLocker locker(&lock); + + for (int i=0; iwrite(in) == -1) @@ -260,7 +287,6 @@ void MonotoneThread::run() task = queue.dequeue(); task.setOutput(err); task.setReturnCode(-1); - task.setFinished(); emit taskAborted(task); continue; @@ -288,17 +314,16 @@ void MonotoneThread::run() QByteArray err = process->readAllStandardError(); if (err.size() != 0) { - MonotoneTask task = queue.head(); // FIXME: expand / edit this list further if (task.getArguments().at(0) != "genkey") { - task = queue.dequeue(); task.setOutput(err); task.setReturnCode(-1); - task.setFinished(); processingTask = false; + buffer.clear(); output.clear(); + queue.dequeue(); emit taskAborted(task); continue; @@ -324,12 +349,13 @@ void MonotoneThread::run() continue; } - MonotoneTask task = queue.dequeue(); task.setOutput(output); task.setReturnCode(returnCode); task.setFinished(); + + queue.dequeue(); + processingTask = false; - output.clear(); D(QString("thread %1: task %2 (%3) finished").arg(threadNumber) .arg(task.getCommandNumber()).arg(QString(task.getEncodedInput()))); ============================================================ --- src/monotone/MonotoneThread.h 63077cbecc190aab81276698cd375d67e4c42df8 +++ src/monotone/MonotoneThread.h b00320bbdc44039934898127d9093016adec9f16 @@ -80,6 +80,12 @@ public: //! true, if the task has already been completed bool isFinished() const { return finished; } + //! aborts the processing of the task + void setAborted() { abortTask = true; } + + //! checks if the task should be aborted + bool isAborted() const { return abortTask; } + private: void init(const ByteArrayList &, const ByteArrayList &); ByteArrayList stringToByteArrayList(const QStringList &); @@ -88,6 +94,7 @@ private: int commandNumber; int threadNumber; bool finished; + bool abortTask; ByteArrayList arguments; ByteArrayList options; @@ -117,6 +124,9 @@ public: //! enqueue a new task for this thread int enqueueTask(const MonotoneTask &); + //! removes one or more tasks from the local queue by deactivating it + void removeTasks(QList); + //! abort task execution on this thread /*! ATTENTION: all unfinished tasks will be aborted! ============================================================ --- src/view/dialogs/Dialog.cpp 5d9964b17b91997764ac1e42447afeef2d4c039f +++ src/view/dialogs/Dialog.cpp de467d48aa140cb218789df1069f24b4eb8550da @@ -57,3 +57,9 @@ void Dialog::setStayOnTop() setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); } +void Dialog::closeEvent(QCloseEvent * event) +{ + emit dialogClosed(); + event->accept(); +} + ============================================================ --- src/view/dialogs/Dialog.h 4e6ee1ac9f09821bd37f888f8aaabb12663a6a5b +++ src/view/dialogs/Dialog.h ae5a57894efa5fe15da18bb165997f5fd0535856 @@ -20,9 +20,7 @@ #define DIALOG_H #include -#include -#include -#include +#include class Dialog : public QDialog { @@ -35,9 +33,14 @@ public: void setStayOnTop(); int execDocumentModal(); +signals: + void dialogClosed(); + private: void restoreState(void); void saveState(void); + void closeEvent(QCloseEvent *); }; #endif + ============================================================ --- src/view/dialogs/FileHistory.cpp 57e211a968aec67716db2f91d43d9c64c6299865 +++ src/view/dialogs/FileHistory.cpp 4fe062ee0d08f3ccd2fc323efa664208e62f4891 @@ -29,6 +29,11 @@ FileHistory::FileHistory(QWidget * paren changeModel = new GetContentChanged(this, databaseFile); certsModel = new Certs(this, databaseFile); + connect( + this, SIGNAL(dialogClosed()), + changeModel, SLOT(stopReading()) + ); + // assign the models to the views revisionFileList->setModel(changeModel); certList->setModel(certsModel);