X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/66ad27aba14cdfea777b9ebe1beb161f80f26463..79a6e75b6567e8cf2ef677cea6bb2c34075d07c7:/src/revisioncontrolobserver.cpp diff --git a/src/revisioncontrolobserver.cpp b/src/revisioncontrolobserver.cpp index 1e7347a9b..87f0a3aa7 100644 --- a/src/revisioncontrolobserver.cpp +++ b/src/revisioncontrolobserver.cpp @@ -23,6 +23,7 @@ #include "revisioncontrolplugin.h" #include +#include #include #include @@ -41,11 +42,13 @@ public: void setData(RevisionControlPlugin* plugin, const QList& itemStates); QList itemStates() const; - + bool retrievedItems() const; + protected: virtual void run(); private: + bool m_retrievedItems; RevisionControlPlugin* m_plugin; QMutex* m_pluginMutex; QList m_itemStates; @@ -53,7 +56,9 @@ private: UpdateItemStatesThread::UpdateItemStatesThread(QObject* parent, QMutex* pluginMutex) : QThread(parent), - m_pluginMutex(pluginMutex) + m_retrievedItems(false), + m_pluginMutex(pluginMutex), + m_itemStates() { } @@ -68,17 +73,22 @@ void UpdateItemStatesThread::run() { Q_ASSERT(!m_itemStates.isEmpty()); Q_ASSERT(m_plugin != 0); - - // it is assumed that all items have the same parent directory - const QString directory = m_itemStates.first().item.url().directory(KUrl::AppendTrailingSlash); + + // The items from m_itemStates may be located in different directory levels. The revision + // plugin requires the root directory for RevisionControlPlugin::beginRetrieval(). Instead + // of doing an expensive search, we utilize the knowledge of the implementation of + // RevisionControlObserver::addDirectory() to be sure that the last item contains the root. + const QString directory = m_itemStates.last().item.url().directory(KUrl::AppendTrailingSlash); QMutexLocker locker(m_pluginMutex); + m_retrievedItems = false; if (m_plugin->beginRetrieval(directory)) { const int count = m_itemStates.count(); for (int i = 0; i < count; ++i) { m_itemStates[i].revision = m_plugin->revisionState(m_itemStates[i].item); } m_plugin->endRetrieval(); + m_retrievedItems = true; } } @@ -87,12 +97,18 @@ QList UpdateItemStatesThread::itemStates() c return m_itemStates; } +bool UpdateItemStatesThread::retrievedItems() const +{ + return m_retrievedItems; +} + // ------------------------------------------------------------------------------------------------ RevisionControlObserver::RevisionControlObserver(QAbstractItemView* view) : QObject(view), m_pendingItemStatesUpdate(false), m_revisionedDirectory(false), + m_silentUpdate(false), m_view(view), m_dirLister(0), m_dolphinModel(0), @@ -127,6 +143,10 @@ RevisionControlObserver::RevisionControlObserver(QAbstractItemView* view) : RevisionControlObserver::~RevisionControlObserver() { + if (m_updateItemStatesThread != 0) { + m_updateItemStatesThread->terminate(); + m_updateItemStatesThread->wait(); + } delete m_plugin; m_plugin = 0; } @@ -152,6 +172,13 @@ QList RevisionControlObserver::contextMenuActions(const QString& direc void RevisionControlObserver::delayedDirectoryVerification() { + m_silentUpdate = false; + m_dirVerificationTimer->start(); +} + +void RevisionControlObserver::silentDirectoryVerification() +{ + m_silentUpdate = true; m_dirVerificationTimer->start(); } @@ -165,6 +192,12 @@ void RevisionControlObserver::verifyDirectory() if (m_plugin == 0) { // TODO: just for testing purposes. A plugin approach will be used later. m_plugin = new SubversionPlugin(); + connect(m_plugin, SIGNAL(infoMessage(const QString&)), + this, SIGNAL(infoMessage(const QString&))); + connect(m_plugin, SIGNAL(errorMessage(const QString&)), + this, SIGNAL(errorMessage(const QString&))); + connect(m_plugin, SIGNAL(operationCompletedMessage(const QString&)), + this, SIGNAL(operationCompletedMessage(const QString&))); } revisionControlUrl.addPath(m_plugin->fileName()); @@ -190,8 +223,8 @@ void RevisionControlObserver::verifyDirectory() this, SLOT(delayedDirectoryVerification())); connect(m_dirLister, SIGNAL(newItems(const KFileItemList&)), this, SLOT(delayedDirectoryVerification())); - connect(m_plugin, SIGNAL(revisionStatesChanged(const QString&)), - this, SLOT(delayedDirectoryVerification())); + connect(m_plugin, SIGNAL(revisionStatesChanged()), + this, SLOT(silentDirectoryVerification())); } updateItemStates(); } else if (m_revisionedDirectory) { @@ -205,13 +238,19 @@ void RevisionControlObserver::verifyDirectory() this, SLOT(delayedDirectoryVerification())); disconnect(m_dirLister, SIGNAL(newItems(const KFileItemList&)), this, SLOT(delayedDirectoryVerification())); - disconnect(m_plugin, SIGNAL(revisionStatesChanged(const QString&)), - this, SLOT(delayedDirectoryVerification())); + disconnect(m_plugin, SIGNAL(revisionStatesChanged()), + this, SLOT(silentDirectoryVerification())); } } void RevisionControlObserver::applyUpdatedItemStates() { + if (!m_updateItemStatesThread->retrievedItems()) { + // ignore m_silentUpdate for an error message + emit errorMessage(i18nc("@info:status", "Update of revision information failed.")); + return; + } + // QAbstractItemModel::setData() triggers a bottleneck in combination with QListView // (a detailed description of the root cause is given in the class KFilePreviewGenerator // from kdelibs). To bypass this bottleneck, the signals of the model are temporary blocked. @@ -228,6 +267,13 @@ void RevisionControlObserver::applyUpdatedItemStates() m_dolphinModel->blockSignals(signalsBlocked); m_view->viewport()->repaint(); + + if (!m_silentUpdate) { + // Using an empty message results in clearing the previously shown information message and showing + // the default status bar information. This is useful as the user already gets feedback that the + // operation has been completed because of the icon emblems. + emit operationCompletedMessage(QString()); + } if (m_pendingItemStatesUpdate) { m_pendingItemStatesUpdate = false; @@ -250,25 +296,31 @@ void RevisionControlObserver::updateItemStates() return; } - const int rowCount = m_dolphinModel->rowCount(); - if (rowCount > 0) { - // Build a list of all items in the current directory and delegate - // this list to the thread, which adjusts the revision states. - QList itemStates; - for (int row = 0; row < rowCount; ++row) { - const QModelIndex index = m_dolphinModel->index(row, DolphinModel::Revision); - - ItemState itemState; - itemState.index = index; - itemState.item = m_dolphinModel->itemForIndex(index); - itemState.revision = RevisionControlPlugin::UnversionedRevision; - - itemStates.append(itemState); + QList itemStates; + addDirectory(QModelIndex(), itemStates); + if (!itemStates.isEmpty()) { + if (!m_silentUpdate) { + emit infoMessage(i18nc("@info:status", "Updating revision information...")); } - m_updateItemStatesThread->setData(m_plugin, itemStates); m_updateItemStatesThread->start(); // applyUpdatedItemStates() is called when finished } } +void RevisionControlObserver::addDirectory(const QModelIndex& parentIndex, QList& itemStates) +{ + const int rowCount = m_dolphinModel->rowCount(parentIndex); + for (int row = 0; row < rowCount; ++row) { + const QModelIndex index = m_dolphinModel->index(row, DolphinModel::Revision, parentIndex); + addDirectory(index, itemStates); + + ItemState itemState; + itemState.index = index; + itemState.item = m_dolphinModel->itemForIndex(index); + itemState.revision = RevisionControlPlugin::UnversionedRevision; + + itemStates.append(itemState); + } +} + #include "revisioncontrolobserver.moc"