#include <kservicetypetrader.h>
#include <kversioncontrolplugin.h>
+#include "pendingthreadsmaintainer.h"
#include "updateitemstatesthread.h"
#include <QAbstractProxyModel>
#include <QMutexLocker>
#include <QTimer>
-/*
- * Maintains a list of pending threads, that get regulary checked
- * whether they are finished and hence can get deleted. QThread::wait()
- * is never used to prevent any blocking of the user interface.
- */
-struct PendingThreadsSingleton
-{
- QList<UpdateItemStatesThread*> list;
-};
-K_GLOBAL_STATIC(PendingThreadsSingleton, s_pendingThreads)
-
-
VersionControlObserver::VersionControlObserver(QAbstractItemView* view) :
QObject(view),
m_pendingItemStatesUpdate(false),
m_dirLister = m_dolphinModel->dirLister();
connect(m_dirLister, SIGNAL(completed()),
this, SLOT(delayedDirectoryVerification()));
-
+
// The verification timer specifies the timeout until the shown directory
// is checked whether it is versioned. Per default it is assumed that users
// don't iterate through versioned directories and a high timeout is used
} else {
// The version controller gets deleted, while a thread still
// is working to get the version information. To avoid a blocking
- // user interface, no waiting for the finished() signal of the thread is
- // done. Instead the thread will be remembered inside the global
- // list s_pendingThreads, which will checked regulary. The thread does
- // not work on shared data that is part of the VersionController instance,
- // so skipping the waiting is save.
+ // user interface, the thread will be forwarded to the
+ // PendingThreadsMaintainer, which will delete the thread later.
disconnect(m_updateItemStatesThread, SIGNAL(finished()),
this, SLOT(slotThreadFinished()));
- s_pendingThreads->list.append(m_updateItemStatesThread);
+ PendingThreadsMaintainer::instance().append(m_updateItemStatesThread);
m_updateItemStatesThread = 0;
}
}
- m_plugin->disconnect();
- m_plugin = 0;
+ if (m_plugin != 0) {
+ m_plugin->disconnect();
+ m_plugin = 0;
+ }
}
QList<QAction*> VersionControlObserver::contextMenuActions(const KFileItemList& items) const
{
QList<QAction*> actions;
- if (isVersioned() && m_updateItemStatesThread->beginReadItemStates()) {
+ if (isVersioned() && m_updateItemStatesThread->lockPlugin()) {
actions = m_plugin->contextMenuActions(items);
- m_updateItemStatesThread->endReadItemStates();
+ m_updateItemStatesThread->unlockPlugin();
}
return actions;
}
QList<QAction*> VersionControlObserver::contextMenuActions(const QString& directory) const
{
QList<QAction*> actions;
- if (isVersioned() && m_updateItemStatesThread->beginReadItemStates()) {
+ if (isVersioned() && m_updateItemStatesThread->lockPlugin()) {
actions = m_plugin->contextMenuActions(directory);
- m_updateItemStatesThread->endReadItemStates();
+ m_updateItemStatesThread->unlockPlugin();
}
return actions;
void VersionControlObserver::verifyDirectory()
{
- if (!s_pendingThreads->list.isEmpty()) {
- // Try to cleanup pending threads (see explanation in destructor)
- QList<UpdateItemStatesThread*>::iterator it = s_pendingThreads->list.begin();
- while (it != s_pendingThreads->list.end()) {
- if ((*it)->isFinished()) {
- (*it)->deleteLater();
- it = s_pendingThreads->list.erase(it);
- } else {
- ++it;
- }
- }
- }
-
- KUrl versionControlUrl = m_dirLister->url();
+ const KUrl versionControlUrl = m_dirLister->url();
if (!versionControlUrl.isLocalFile()) {
return;
}
}
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
- // be found in one of the parent directories.
-
- // TODO...
- }
+ if (m_plugin != 0) {
+ connect(m_plugin, SIGNAL(versionStatesChanged()),
+ this, SLOT(silentDirectoryVerification()));
+ connect(m_plugin, SIGNAL(infoMessage(QString)),
+ this, SIGNAL(infoMessage(QString)));
+ connect(m_plugin, SIGNAL(errorMessage(QString)),
+ this, SIGNAL(errorMessage(QString)));
+ connect(m_plugin, SIGNAL(operationCompletedMessage(QString)),
+ this, SIGNAL(operationCompletedMessage(QString)));
- if (foundVersionInfo) {
if (!m_versionedDirectory) {
m_versionedDirectory = true;
this, SLOT(delayedDirectoryVerification()));
connect(m_dirLister, SIGNAL(newItems(const KFileItemList&)),
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) {
m_pendingItemStatesUpdate = true;
return;
}
-
+
QList<ItemState> itemStates;
addDirectory(QModelIndex(), itemStates);
if (!itemStates.isEmpty()) {
for (int row = 0; row < rowCount; ++row) {
const QModelIndex index = m_dolphinModel->index(row, DolphinModel::Version, parentIndex);
addDirectory(index, itemStates);
-
+
ItemState itemState;
itemState.index = index;
itemState.item = m_dolphinModel->itemForIndex(index);
static QList<KVersionControlPlugin*> plugins;
if (!pluginsAvailable) {
- // a searching for plugins has already been done, but no
+ // 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 QString disabledPlugins = VersionControlSettings::disabledPlugins();
- const QStringList disabledPluginsList = disabledPlugins.split(',');
+ const QStringList enabledPlugins = VersionControlSettings::enabledPlugins();
const KService::List pluginServices = KServiceTypeTrader::self()->query("FileViewVersionControlPlugin");
for (KService::List::ConstIterator it = pluginServices.constBegin(); it != pluginServices.constEnd(); ++it) {
- if (!disabledPluginsList.contains((*it)->name())) {
+ if (enabledPlugins.contains((*it)->name())) {
KVersionControlPlugin* plugin = (*it)->createInstance<KVersionControlPlugin>();
Q_ASSERT(plugin != 0);
plugins.append(plugin);
}
}
- // verify whether the current directory contains revision information
+ // Verify whether the current directory contains revision information
// like .svn, .git, ...
foreach (KVersionControlPlugin* plugin, plugins) {
- KUrl fileUrl = directory;
+ // Use the KDirLister cache to check for .svn, .git, ... files
+ KUrl dirUrl(directory);
+ KUrl fileUrl = dirUrl;
fileUrl.addPath(plugin->fileName());
const KFileItem item = m_dirLister->findByUrl(fileUrl);
if (!item.isNull()) {
return plugin;
}
+
+ // Version control systems like Git provide the version information
+ // file only in the root directory. Check whether the version information file can
+ // be found in one of the parent directories. For performance reasons this
+ // step is only done, if the previous directory was marked as versioned by
+ // m_versionedDirectory. Drawback: Until e. g. Git is recognized, the root directory
+ // must be shown at least once.
+ if (m_versionedDirectory) {
+ KUrl upUrl = dirUrl.upUrl();
+ while (upUrl != dirUrl) {
+ const QString filePath = dirUrl.pathOrUrl(KUrl::AddTrailingSlash) + plugin->fileName();
+ QFileInfo file(filePath);
+ if (file.exists()) {
+ return plugin;
+ }
+ dirUrl = upUrl;
+ upUrl = dirUrl.upUrl();
+ }
+ }
}
return 0;