X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/93cb7e02616df9746f7cdae09434e7488f4e7d28..47de53916904d04464d135c0efb4fd365d8368c6:/src/views/versioncontrol/versioncontrolobserver.cpp diff --git a/src/views/versioncontrol/versioncontrolobserver.cpp b/src/views/versioncontrol/versioncontrolobserver.cpp index c8d9d6874..6affe80d3 100644 --- a/src/views/versioncontrol/versioncontrolobserver.cpp +++ b/src/views/versioncontrol/versioncontrolobserver.cpp @@ -21,15 +21,15 @@ #include "dolphin_versioncontrolsettings.h" -#include #include #include #include #include -#include +#include #include "updateitemstatesthread.h" +#include #include #include @@ -87,31 +87,41 @@ KFileItemModel* VersionControlObserver::model() const return m_model; } -QList VersionControlObserver::contextMenuActions(const KFileItemList& items) const +QList VersionControlObserver::actions(const KFileItemList& items) const { QList actions; - if (isVersioned()) { - if (m_updateItemStatesThread && m_updateItemStatesThread->lockPlugin()) { - actions = m_plugin->contextMenuActions(items); - m_updateItemStatesThread->unlockPlugin(); - } else { - actions = m_plugin->contextMenuActions(items); + + bool hasNullItems = false; + foreach (const KFileItem& item, items) { + if (item.isNull()) { + kWarning() << "Requesting version-control-actions for empty items"; + hasNullItems = true; + break; } } - return actions; -} + if (!m_model || hasNullItems) { + return actions; + } -QList VersionControlObserver::contextMenuActions(const QString& directory) const -{ - QList actions; - if (isVersioned()) { - if (m_updateItemStatesThread && m_updateItemStatesThread->lockPlugin()) { - actions = m_plugin->contextMenuActions(directory); - m_updateItemStatesThread->unlockPlugin(); - } else { - actions = m_plugin->contextMenuActions(directory); + KVersionControlPlugin2* pluginV2 = qobject_cast(m_plugin); + if (pluginV2) { + // Use version 2 of the KVersionControlPlugin which allows providing actions + // also for non-versioned directories. + actions = pluginV2->actions(items); + } else if (isVersioned()) { + // Support deprecated interfaces from KVersionControlPlugin version 1. + // Context menu actions where only available for versioned directories. + QString directory; + if (items.count() == 1) { + const KFileItem rootItem = m_model->rootItem(); + if (!rootItem.isNull() && items.first().url() == rootItem.url()) { + directory = rootItem.url().path(KUrl::AddTrailingSlash); + } } + + actions = directory.isEmpty() ? m_plugin->contextMenuActions(items) + : m_plugin->contextMenuActions(directory); } return actions; @@ -135,8 +145,8 @@ void VersionControlObserver::verifyDirectory() return; } - const KUrl versionControlUrl = m_model->rootDirectory(); - if (!versionControlUrl.isLocalFile()) { + const KFileItem rootItem = m_model->rootItem(); + if (rootItem.isNull() || !rootItem.url().isLocalFile()) { return; } @@ -144,10 +154,16 @@ void VersionControlObserver::verifyDirectory() m_plugin->disconnect(this); } - m_plugin = searchPlugin(versionControlUrl); + m_plugin = searchPlugin(rootItem.url()); if (m_plugin) { - connect(m_plugin, SIGNAL(versionStatesChanged()), - this, SLOT(silentDirectoryVerification())); + KVersionControlPlugin2* pluginV2 = qobject_cast(m_plugin); + if (pluginV2) { + connect(pluginV2, SIGNAL(itemVersionsChanged()), + this, SLOT(silentDirectoryVerification())); + } else { + connect(m_plugin, SIGNAL(versionStatesChanged()), + this, SLOT(silentDirectoryVerification())); + } connect(m_plugin, SIGNAL(infoMessage(QString)), this, SIGNAL(infoMessage(QString))); connect(m_plugin, SIGNAL(errorMessage(QString)), @@ -178,21 +194,20 @@ void VersionControlObserver::slotThreadFinished() UpdateItemStatesThread* thread = m_updateItemStatesThread; m_updateItemStatesThread = 0; // The thread deletes itself automatically (see updateItemStates()) - if (!m_plugin) { + if (!m_plugin || !thread) { return; } - if (!thread->retrievedItems()) { - // Ignore m_silentUpdate for an error message - emit errorMessage(i18nc("@info:status", "Update of version information failed.")); - return; - } + const QMap >& itemStates = thread->itemStates(); + QMap >::const_iterator it = itemStates.constBegin(); + for (; it != itemStates.constEnd(); ++it) { + const QVector& items = it.value(); - const QList itemStates = thread->itemStates(); - foreach (const ItemState& itemState, itemStates) { - QHash values; - values.insert("version", QVariant(itemState.version)); - m_model->setData(itemState.index, values); + foreach (const ItemState& item, items) { + QHash values; + values.insert("version", QVariant(item.version)); + m_model->setData(m_model->index(item.item), values); + } } if (!m_silentUpdate) { @@ -211,42 +226,65 @@ void VersionControlObserver::slotThreadFinished() void VersionControlObserver::updateItemStates() { Q_ASSERT(m_plugin); - if (!m_updateItemStatesThread) { - m_updateItemStatesThread = new UpdateItemStatesThread(); - connect(m_updateItemStatesThread, SIGNAL(finished()), - this, SLOT(slotThreadFinished())); - connect(m_updateItemStatesThread, SIGNAL(finished()), - m_updateItemStatesThread, SLOT(deleteLater())); - } - if (m_updateItemStatesThread->isRunning()) { + if (m_updateItemStatesThread) { // An update is currently ongoing. Wait until the thread has finished // the update (see slotThreadFinished()). m_pendingItemStatesUpdate = true; return; } - QList itemStates; - const int itemCount = m_model->count(); - itemStates.reserve(itemCount); - - for (int i = 0; i < itemCount; ++i) { - ItemState itemState; - itemState.index = i; - itemState.item = m_model->fileItem(i); - itemState.version = KVersionControlPlugin::UnversionedVersion; - - itemStates.append(itemState); - } + QMap > itemStates; + createItemStatesList(itemStates); if (!itemStates.isEmpty()) { if (!m_silentUpdate) { emit infoMessage(i18nc("@info:status", "Updating version information...")); } - m_updateItemStatesThread->setData(m_plugin, itemStates); + m_updateItemStatesThread = new UpdateItemStatesThread(m_plugin, itemStates); + connect(m_updateItemStatesThread, SIGNAL(finished()), + this, SLOT(slotThreadFinished())); + connect(m_updateItemStatesThread, SIGNAL(finished()), + m_updateItemStatesThread, SLOT(deleteLater())); + m_updateItemStatesThread->start(); // slotThreadFinished() is called when finished } } +int VersionControlObserver::createItemStatesList(QMap >& itemStates, + const int firstIndex) +{ + const int itemCount = m_model->count(); + const int currentExpansionLevel = m_model->expandedParentsCount(firstIndex); + + QVector items; + items.reserve(itemCount - firstIndex); + + int index; + for (index = firstIndex; index < itemCount; ++index) { + const int expansionLevel = m_model->expandedParentsCount(index); + + if (expansionLevel == currentExpansionLevel) { + ItemState itemState; + itemState.item = m_model->fileItem(index); + itemState.version = KVersionControlPlugin2::UnversionedVersion; + + items.append(itemState); + } else if (expansionLevel > currentExpansionLevel) { + // Sub folder + index += createItemStatesList(itemStates, index) - 1; + } else { + break; + } + } + + if (items.count() > 0) { + const KUrl& url = items.first().item.url(); + itemStates.insert(url.directory(KUrl::AppendTrailingSlash), items); + } + + return index - firstIndex; // number of processed items +} + KVersionControlPlugin* VersionControlObserver::searchPlugin(const KUrl& directory) const { static bool pluginsAvailable = true; @@ -278,12 +316,18 @@ KVersionControlPlugin* VersionControlObserver::searchPlugin(const KUrl& director } } + // We use the number of upUrl() calls to find the best matching plugin + // for the given directory. The smaller value, the better it is (0 is best). + KVersionControlPlugin* bestPlugin = 0; + int bestScore = INT_MAX; + // Verify whether the current directory contains revision information // like .svn, .git, ... foreach (KVersionControlPlugin* plugin, plugins) { - // Use the KDirLister cache to check for .svn, .git, ... files const QString fileName = directory.path(KUrl::AddTrailingSlash) + plugin->fileName(); if (QFile::exists(fileName)) { + // The score of this plugin is 0 (best), so we can just return this plugin, + // instead of going through the plugin scoring procedure, we can't find a better one ;) return plugin; } @@ -296,18 +340,24 @@ KVersionControlPlugin* VersionControlObserver::searchPlugin(const KUrl& director if (m_versionedDirectory) { KUrl dirUrl(directory); KUrl upUrl = dirUrl.upUrl(); - while (upUrl != dirUrl) { + int upUrlCounter = 1; + while ((upUrlCounter < bestScore) && (upUrl != dirUrl)) { const QString fileName = dirUrl.path(KUrl::AddTrailingSlash) + plugin->fileName(); if (QFile::exists(fileName)) { - return plugin; + if (upUrlCounter < bestScore) { + bestPlugin = plugin; + bestScore = upUrlCounter; + } + break; } dirUrl = upUrl; upUrl = dirUrl.upUrl(); + ++upUrlCounter; } } } - return 0; + return bestPlugin; } bool VersionControlObserver::isVersioned() const