From 896ee459af10c73d20d0ae093b4c02348ffedb18 Mon Sep 17 00:00:00 2001 From: Peter Penz Date: Fri, 6 Nov 2009 15:43:08 +0000 Subject: [PATCH] * enable the loading of version control plugins (thanks to Aaron for the hint) * Don't terminate the thread that receives the item states when changing a view. Instead let the thread get finished and ignore the result. svn path=/trunk/KDE/kdebase/apps/; revision=1045674 --- src/CMakeLists.txt | 9 +- src/dolphincolumnview.cpp | 2 +- .../fileviewsvnplugin.cpp | 11 +- .../fileviewsvnplugin.desktop | 0 src/{ => versioncontrol}/fileviewsvnplugin.h | 2 +- .../fileviewversioncontrolplugin.desktop | 0 src/versioncontrol/updateitemstatesthread.cpp | 94 +++++++++ src/versioncontrol/updateitemstatesthread.h | 68 +++++++ .../versioncontrolobserver.cpp | 185 +++++++----------- .../versioncontrolobserver.h | 14 +- src/viewextensionsfactory.cpp | 2 +- 11 files changed, 265 insertions(+), 122 deletions(-) rename src/{ => versioncontrol}/fileviewsvnplugin.cpp (97%) rename src/{ => versioncontrol}/fileviewsvnplugin.desktop (100%) rename src/{ => versioncontrol}/fileviewsvnplugin.h (98%) rename src/{ => versioncontrol}/fileviewversioncontrolplugin.desktop (100%) create mode 100644 src/versioncontrol/updateitemstatesthread.cpp create mode 100644 src/versioncontrol/updateitemstatesthread.h rename src/{ => versioncontrol}/versioncontrolobserver.cpp (67%) rename src/{ => versioncontrol}/versioncontrolobserver.h (93%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0c3416c1e..4bac99705 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -46,7 +46,8 @@ set(dolphinprivate_LIB_SRCS tooltips/ktooltip.cpp tooltips/ktooltipwindow.cpp tooltips/tooltipmanager.cpp - versioncontrolobserver.cpp + versioncontrol/updateitemstatesthread.cpp + versioncontrol/versioncontrolobserver.cpp viewextensionsfactory.cpp viewproperties.cpp zoomlevelinfo.cpp @@ -92,7 +93,7 @@ set(dolphinpart_SRCS ) set(fileviewsvnplugin_SRCS - fileviewsvnplugin.cpp + versioncontrol/fileviewsvnplugin.cpp ) kde4_add_plugin(dolphinpart ${dolphinpart_SRCS}) @@ -106,8 +107,8 @@ install(TARGETS fileviewsvnplugin DESTINATION ${PLUGIN_INSTALL_DIR}) install(FILES dolphinpart.rc DESTINATION ${DATA_INSTALL_DIR}/dolphinpart) install(FILES dolphinpart.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) -install(FILES fileviewsvnplugin.desktop DESTINATION ${SERVICES_INSTALL_DIR}) -install(FILES fileviewversioncontrolplugin.desktop DESTINATION ${SERVICETYPES_INSTALL_DIR}) +install(FILES versioncontrol/fileviewsvnplugin.desktop DESTINATION ${SERVICES_INSTALL_DIR}) +install(FILES versioncontrol/fileviewversioncontrolplugin.desktop DESTINATION ${SERVICETYPES_INSTALL_DIR}) ########################################## diff --git a/src/dolphincolumnview.cpp b/src/dolphincolumnview.cpp index 9157c7ed4..d1f7e9d64 100644 --- a/src/dolphincolumnview.cpp +++ b/src/dolphincolumnview.cpp @@ -31,7 +31,7 @@ #include "draganddrophelper.h" #include "folderexpander.h" #include "tooltips/tooltipmanager.h" -#include "versioncontrolobserver.h" +#include "versioncontrol/versioncontrolobserver.h" #include "viewextensionsfactory.h" #include "zoomlevelinfo.h" diff --git a/src/fileviewsvnplugin.cpp b/src/versioncontrol/fileviewsvnplugin.cpp similarity index 97% rename from src/fileviewsvnplugin.cpp rename to src/versioncontrol/fileviewsvnplugin.cpp index a54329954..7e56c724c 100644 --- a/src/fileviewsvnplugin.cpp +++ b/src/versioncontrol/fileviewsvnplugin.cpp @@ -20,6 +20,7 @@ #include "fileviewsvnplugin.h" #include +#include #include #include #include @@ -35,7 +36,13 @@ #include #include -FileViewSvnPlugin::FileViewSvnPlugin() : +#include +#include +K_PLUGIN_FACTORY(FileViewSvnPluginFactory, registerPlugin();) +K_EXPORT_PLUGIN(FileViewSvnPluginFactory("fileviewsvnplugin")) + +FileViewSvnPlugin::FileViewSvnPlugin(QObject* parent, const QList& args) : + KVersionControlPlugin(parent), m_versionInfoHash(), m_versionInfoKeys(), m_updateAction(0), @@ -50,6 +57,8 @@ FileViewSvnPlugin::FileViewSvnPlugin() : m_contextItems(), m_tempFile() { + Q_UNUSED(args); + m_updateAction = new KAction(this); m_updateAction->setIcon(KIcon("view-refresh")); m_updateAction->setText(i18nc("@item:inmenu", "SVN Update")); diff --git a/src/fileviewsvnplugin.desktop b/src/versioncontrol/fileviewsvnplugin.desktop similarity index 100% rename from src/fileviewsvnplugin.desktop rename to src/versioncontrol/fileviewsvnplugin.desktop diff --git a/src/fileviewsvnplugin.h b/src/versioncontrol/fileviewsvnplugin.h similarity index 98% rename from src/fileviewsvnplugin.h rename to src/versioncontrol/fileviewsvnplugin.h index 2cb3d71fb..4804971c0 100644 --- a/src/fileviewsvnplugin.h +++ b/src/versioncontrol/fileviewsvnplugin.h @@ -33,7 +33,7 @@ class FileViewSvnPlugin : public KVersionControlPlugin Q_OBJECT public: - FileViewSvnPlugin(); + FileViewSvnPlugin(QObject* parent, const QList& args); virtual ~FileViewSvnPlugin(); virtual QString fileName() const; virtual bool beginRetrieval(const QString& directory); diff --git a/src/fileviewversioncontrolplugin.desktop b/src/versioncontrol/fileviewversioncontrolplugin.desktop similarity index 100% rename from src/fileviewversioncontrolplugin.desktop rename to src/versioncontrol/fileviewversioncontrolplugin.desktop diff --git a/src/versioncontrol/updateitemstatesthread.cpp b/src/versioncontrol/updateitemstatesthread.cpp new file mode 100644 index 000000000..7483e056e --- /dev/null +++ b/src/versioncontrol/updateitemstatesthread.cpp @@ -0,0 +1,94 @@ +/*************************************************************************** + * Copyright (C) 2009 by Peter Penz * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#include "updateitemstatesthread.h" + +UpdateItemStatesThread::UpdateItemStatesThread(QObject* parent) : + QThread(parent), + m_retrievedItems(false), + m_mutex(QMutex::Recursive), + m_itemStates() +{ +} + +UpdateItemStatesThread::~UpdateItemStatesThread() +{ +} + +void UpdateItemStatesThread::setData(KVersionControlPlugin* plugin, + const QList& itemStates) +{ + m_plugin = plugin; + m_itemStates = itemStates; +} + +void UpdateItemStatesThread::run() +{ + Q_ASSERT(!m_itemStates.isEmpty()); + Q_ASSERT(m_plugin != 0); + + // The items from m_itemStates may be located in different directory levels. The version + // plugin requires the root directory for KVersionControlPlugin::beginRetrieval(). Instead + // of doing an expensive search, we utilize the knowledge of the implementation of + // VersionControlObserver::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_mutex); + m_retrievedItems = false; + if (m_plugin->beginRetrieval(directory)) { + const int count = m_itemStates.count(); + for (int i = 0; i < count; ++i) { + m_itemStates[i].version = m_plugin->versionState(m_itemStates[i].item); + } + m_plugin->endRetrieval(); + m_retrievedItems = true; + } +} + +bool UpdateItemStatesThread::beginReadItemStates() +{ + return m_mutex.tryLock(300); +} + +void UpdateItemStatesThread::endReadItemStates() +{ + m_mutex.unlock(); +} + +QList UpdateItemStatesThread::itemStates() const +{ + return m_itemStates; +} + +bool UpdateItemStatesThread::retrievedItems() const +{ + return m_retrievedItems; +} + +void UpdateItemStatesThread::deleteWhenFinished() +{ + connect(this, SIGNAL(finished()), this, SLOT(slotFinished())); +} + +void UpdateItemStatesThread::slotFinished() +{ + deleteLater(); +} + +#include "updateitemstatesthread.moc" diff --git a/src/versioncontrol/updateitemstatesthread.h b/src/versioncontrol/updateitemstatesthread.h new file mode 100644 index 000000000..36768d0e9 --- /dev/null +++ b/src/versioncontrol/updateitemstatesthread.h @@ -0,0 +1,68 @@ +/*************************************************************************** + * Copyright (C) 2009 by Peter Penz * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef UPDATEITEMSTATESTHREAD_H +#define UPDATEITEMSTATESTHREAD_H + +#include +#include + +#include +#include + +class KVersionControlPlugin; + +/** + * The performance of updating the version state of items depends + * on the used plugin. To prevent that Dolphin gets blocked by a + * slow plugin, the updating is delegated to a thread. + */ +class LIBDOLPHINPRIVATE_EXPORT UpdateItemStatesThread : public QThread +{ + Q_OBJECT + +public: + UpdateItemStatesThread(QObject* parent); + virtual ~UpdateItemStatesThread(); + + void setData(KVersionControlPlugin* plugin, + const QList& itemStates); + + bool beginReadItemStates(); + void endReadItemStates(); + QList itemStates() const; + + bool retrievedItems() const; + + void deleteWhenFinished(); + +protected: + virtual void run(); + +private slots: + void slotFinished(); + +private: + bool m_retrievedItems; + KVersionControlPlugin* m_plugin; + QMutex m_mutex; + QList m_itemStates; +}; + +#endif // UPDATEITEMSTATESTHREAD_H diff --git a/src/versioncontrolobserver.cpp b/src/versioncontrol/versioncontrolobserver.cpp similarity index 67% rename from src/versioncontrolobserver.cpp rename to src/versioncontrol/versioncontrolobserver.cpp index 9dc7daa41..aea60b28d 100644 --- a/src/versioncontrolobserver.cpp +++ b/src/versioncontrol/versioncontrolobserver.cpp @@ -19,7 +19,7 @@ #include "versioncontrolobserver.h" -#include "dolphinmodel.h" +#include #include #include @@ -27,85 +27,13 @@ #include #include +#include "updateitemstatesthread.h" + #include #include #include #include -/** - * The performance of updating the version state of items depends - * on the used plugin. To prevent that Dolphin gets blocked by a - * slow plugin, the updating is delegated to a thread. - */ -class UpdateItemStatesThread : public QThread -{ -public: - UpdateItemStatesThread(QObject* parent, QMutex* pluginMutex); - void setData(KVersionControlPlugin* plugin, - const QList& itemStates); - QList itemStates() const; - bool retrievedItems() const; - -protected: - virtual void run(); - -private: - bool m_retrievedItems; - KVersionControlPlugin* m_plugin; - QMutex* m_pluginMutex; - QList m_itemStates; -}; - -UpdateItemStatesThread::UpdateItemStatesThread(QObject* parent, QMutex* pluginMutex) : - QThread(parent), - m_retrievedItems(false), - m_pluginMutex(pluginMutex), - m_itemStates() -{ -} - -void UpdateItemStatesThread::setData(KVersionControlPlugin* plugin, - const QList& itemStates) -{ - m_plugin = plugin; - m_itemStates = itemStates; -} - -void UpdateItemStatesThread::run() -{ - Q_ASSERT(!m_itemStates.isEmpty()); - Q_ASSERT(m_plugin != 0); - - // The items from m_itemStates may be located in different directory levels. The version - // plugin requires the root directory for KVersionControlPlugin::beginRetrieval(). Instead - // of doing an expensive search, we utilize the knowledge of the implementation of - // VersionControlObserver::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].version = m_plugin->versionState(m_itemStates[i].item); - } - m_plugin->endRetrieval(); - m_retrievedItems = true; - } -} - -QList UpdateItemStatesThread::itemStates() const -{ - return m_itemStates; -} - -bool UpdateItemStatesThread::retrievedItems() const -{ - return m_retrievedItems; -} - -// ------------------------------------------------------------------------------------------------ - VersionControlObserver::VersionControlObserver(QAbstractItemView* view) : QObject(view), m_pendingItemStatesUpdate(false), @@ -115,7 +43,6 @@ VersionControlObserver::VersionControlObserver(QAbstractItemView* view) : m_dirLister(0), m_dolphinModel(0), m_dirVerificationTimer(0), - m_pluginMutex(QMutex::Recursive), m_plugin(0), m_updateItemStatesThread(0) { @@ -146,30 +73,32 @@ VersionControlObserver::VersionControlObserver(QAbstractItemView* view) : VersionControlObserver::~VersionControlObserver() { if (m_updateItemStatesThread != 0) { - m_updateItemStatesThread->terminate(); - m_updateItemStatesThread->wait(); + disconnect(m_updateItemStatesThread, SIGNAL(finished()), + this, SLOT(applyUpdatedItemStates())); + m_updateItemStatesThread->deleteWhenFinished(); + m_updateItemStatesThread = 0; } - delete m_plugin; - m_plugin = 0; } QList VersionControlObserver::contextMenuActions(const KFileItemList& items) const { - if (m_dolphinModel->hasVersionData() && (m_plugin != 0)) { - QMutexLocker locker(&m_pluginMutex); - return m_plugin->contextMenuActions(items); + QList actions; + if (isVersioned() && m_updateItemStatesThread->beginReadItemStates()) { + actions = m_plugin->contextMenuActions(items); + m_updateItemStatesThread->endReadItemStates(); } - return QList(); + return actions; } QList VersionControlObserver::contextMenuActions(const QString& directory) const { - if (m_dolphinModel->hasVersionData() && (m_plugin != 0)) { - QMutexLocker locker(&m_pluginMutex); - return m_plugin->contextMenuActions(directory); + QList actions; + if (isVersioned() && m_updateItemStatesThread->beginReadItemStates()) { + actions = m_plugin->contextMenuActions(directory); + m_updateItemStatesThread->endReadItemStates(); } - return QList(); + return actions; } void VersionControlObserver::delayedDirectoryVerification() @@ -184,7 +113,6 @@ void VersionControlObserver::silentDirectoryVerification() m_dirVerificationTimer->start(); } -#include void VersionControlObserver::verifyDirectory() { KUrl versionControlUrl = m_dirLister->url(); @@ -192,28 +120,12 @@ void VersionControlObserver::verifyDirectory() return; } - if (m_plugin == 0) { - return; // TODO: does not work yet, m_plugin will always be 0 - - kDebug() << "Searching FileViewVersionControlPlugins..."; - const KService::List plugins = KServiceTypeTrader::self()->query("FileViewVersionControlPlugin"); - for (KService::List::ConstIterator it = plugins.constBegin(); it != plugins.constEnd(); ++it) { - kDebug() << "found plugin" << (*it)->desktopEntryName(); - m_plugin = (*it)->createInstance(); - } - - 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&))); + if (m_plugin != 0) { + m_plugin->disconnect(); } - versionControlUrl.addPath(m_plugin->fileName()); - const KFileItem item = m_dirLister->findByUrl(versionControlUrl); - - bool foundVersionInfo = !item.isNull(); + m_plugin = searchPlugin(versionControlUrl); + const bool foundVersionInfo = (m_plugin != 0); if (!foundVersionInfo && m_versionedDirectory) { // Version control systems like Git provide the version information // file only in the root directory. Check whether the version information file can @@ -235,6 +147,12 @@ void VersionControlObserver::verifyDirectory() this, SLOT(delayedDirectoryVerification())); connect(m_plugin, SIGNAL(versionStatesChanged()), this, SLOT(silentDirectoryVerification())); + 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&))); } updateItemStates(); } else if (m_versionedDirectory) { @@ -248,8 +166,6 @@ void VersionControlObserver::verifyDirectory() this, SLOT(delayedDirectoryVerification())); disconnect(m_dirLister, SIGNAL(newItems(const KFileItemList&)), this, SLOT(delayedDirectoryVerification())); - disconnect(m_plugin, SIGNAL(versionStatesChanged()), - this, SLOT(silentDirectoryVerification())); } } @@ -295,7 +211,7 @@ void VersionControlObserver::updateItemStates() { Q_ASSERT(m_plugin != 0); if (m_updateItemStatesThread == 0) { - m_updateItemStatesThread = new UpdateItemStatesThread(this, &m_pluginMutex); + m_updateItemStatesThread = new UpdateItemStatesThread(this); connect(m_updateItemStatesThread, SIGNAL(finished()), this, SLOT(applyUpdatedItemStates())); } @@ -333,4 +249,49 @@ void VersionControlObserver::addDirectory(const QModelIndex& parentIndex, QList< } } +KVersionControlPlugin* VersionControlObserver::searchPlugin(const KUrl& directory) const +{ + static bool pluginsAvailable = true; + static QList plugins; + + if (!pluginsAvailable) { + // a searching for plugins has already been done, but no + // plugins are installed + return 0; + } + + if (plugins.isEmpty()) { + // No searching for plugins has been done yet. Query the KServiceTypeTrader for + // all fileview version control plugins and remember them in 'plugins'. + const KService::List pluginServices = KServiceTypeTrader::self()->query("FileViewVersionControlPlugin"); + for (KService::List::ConstIterator it = pluginServices.constBegin(); it != pluginServices.constEnd(); ++it) { + KVersionControlPlugin* plugin = (*it)->createInstance(); + Q_ASSERT(plugin != 0); + plugins.append(plugin); + } + if (plugins.isEmpty()) { + pluginsAvailable = false; + return 0; + } + } + + // verify whether the current directory contains revision information + // like .svn, .git, ... + foreach (KVersionControlPlugin* plugin, plugins) { + KUrl fileUrl = directory; + fileUrl.addPath(plugin->fileName()); + const KFileItem item = m_dirLister->findByUrl(fileUrl); + if (!item.isNull()) { + return plugin; + } + } + + return 0; +} + +bool VersionControlObserver::isVersioned() const +{ + return m_dolphinModel->hasVersionData() && (m_plugin != 0); +} + #include "versioncontrolobserver.moc" diff --git a/src/versioncontrolobserver.h b/src/versioncontrol/versioncontrolobserver.h similarity index 93% rename from src/versioncontrolobserver.h rename to src/versioncontrol/versioncontrolobserver.h index 44a0adcad..2d1cd02b3 100644 --- a/src/versioncontrolobserver.h +++ b/src/versioncontrol/versioncontrolobserver.h @@ -111,6 +111,17 @@ private: */ void addDirectory(const QModelIndex& parentIndex, QList& itemStates); + /** + * Returns a matching plugin for the given directory. + * 0 is returned, if no matching plugin has been found. + */ + KVersionControlPlugin* searchPlugin(const KUrl& directory) const; + + /** + * Returns true, if the directory contains a version control information. + */ + bool isVersioned() const; + private: bool m_pendingItemStatesUpdate; bool m_versionedDirectory; @@ -122,8 +133,7 @@ private: DolphinModel* m_dolphinModel; QTimer* m_dirVerificationTimer; - - mutable QMutex m_pluginMutex; + KVersionControlPlugin* m_plugin; UpdateItemStatesThread* m_updateItemStatesThread; diff --git a/src/viewextensionsfactory.cpp b/src/viewextensionsfactory.cpp index e3ec64664..86311e28d 100644 --- a/src/viewextensionsfactory.cpp +++ b/src/viewextensionsfactory.cpp @@ -28,7 +28,7 @@ #include "selectionmanager.h" #include "settings/dolphinsettings.h" #include "tooltips/tooltipmanager.h" -#include "versioncontrolobserver.h" +#include "versioncontrol/versioncontrolobserver.h" #include "dolphin_generalsettings.h" -- 2.47.3