diff options
Diffstat (limited to 'src/revisioncontrolobserver.cpp')
| -rw-r--r-- | src/revisioncontrolobserver.cpp | 130 |
1 files changed, 118 insertions, 12 deletions
diff --git a/src/revisioncontrolobserver.cpp b/src/revisioncontrolobserver.cpp index 9b8cb2583..9d11154e0 100644 --- a/src/revisioncontrolobserver.cpp +++ b/src/revisioncontrolobserver.cpp @@ -26,15 +26,75 @@ #include <QAbstractProxyModel> #include <QAbstractItemView> +#include <QListView> #include <QTimer> +/** + * The performance of updating the revision 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 +{ +public: + UpdateItemStatesThread(QObject* parent); + void setData(RevisionControlPlugin* plugin, + const QList<RevisionControlObserver::ItemState>& itemStates); + QList<RevisionControlObserver::ItemState> itemStates() const; + +protected: + virtual void run(); + +private: + RevisionControlPlugin* m_plugin; + QList<RevisionControlObserver::ItemState> m_itemStates; +}; + +UpdateItemStatesThread::UpdateItemStatesThread(QObject* parent) : + QThread(parent) +{ +} + +void UpdateItemStatesThread::setData(RevisionControlPlugin* plugin, + const QList<RevisionControlObserver::ItemState>& itemStates) +{ + m_plugin = plugin; + m_itemStates = itemStates; +} + +void UpdateItemStatesThread::run() +{ + Q_ASSERT(m_itemStates.count() > 0); + 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); + + 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(); + } +} + +QList<RevisionControlObserver::ItemState> UpdateItemStatesThread::itemStates() const +{ + return m_itemStates; +} + +// --- + RevisionControlObserver::RevisionControlObserver(QAbstractItemView* view) : QObject(view), + m_pendingItemStatesUpdate(false), m_view(view), m_dirLister(0), m_dolphinModel(0), m_dirVerificationTimer(0), - m_plugin(0) + m_plugin(0), + m_updateItemStatesThread(0) { Q_ASSERT(view != 0); @@ -101,24 +161,70 @@ void RevisionControlObserver::verifyDirectory() } } +void RevisionControlObserver::applyUpdatedItemStates() +{ + // Updating items with non-uniform item sizes is a serious bottleneck + // in QListView. Temporary disable the non-uniform item sizes. + QListView* listView = qobject_cast<QListView*>(m_view); + bool uniformSizes = true; + if (listView != 0) { + uniformSizes = listView->uniformItemSizes(); + //listView->setUniformItemSizes(true); TODO: does not work as well as in KFilePreviewGenerator + } + + const QList<ItemState> itemStates = m_updateItemStatesThread->itemStates(); + foreach (const ItemState& itemState, itemStates) { + m_dolphinModel->setData(itemState.index, + QVariant(static_cast<int>(itemState.revision)), + Qt::DecorationRole); + } + + if (listView != 0) { + listView->setUniformItemSizes(uniformSizes); + } + + m_view->viewport()->repaint(); // TODO: this should not be necessary, as DolphinModel::setData() calls dataChanged() + + if (m_pendingItemStatesUpdate) { + m_pendingItemStatesUpdate = false; + updateItemStates(); + } +} + void RevisionControlObserver::updateItemStates() { Q_ASSERT(m_plugin != 0); - const KUrl directory = m_dirLister->url(); - if (!m_plugin->beginRetrieval(directory.toLocalFile(KUrl::AddTrailingSlash))) { + if (m_updateItemStatesThread == 0) { + m_updateItemStatesThread = new UpdateItemStatesThread(this); + connect(m_updateItemStatesThread, SIGNAL(finished()), + this, SLOT(applyUpdatedItemStates())); + } + if (m_updateItemStatesThread->isRunning()) { + // An update is currently ongoing. Wait until the thread has finished + // the update (see applyUpdatedItemStates()). + m_pendingItemStatesUpdate = true; return; } - + const int rowCount = m_dolphinModel->rowCount(); - for (int row = 0; row < rowCount; ++row) { - const QModelIndex index = m_dolphinModel->index(row, DolphinModel::Revision); - const KFileItem item = m_dolphinModel->itemForIndex(index); - const RevisionControlPlugin::RevisionState revision = m_plugin->revisionState(item); - m_dolphinModel->setData(index, QVariant(static_cast<int>(revision)), Qt::DecorationRole); + 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<ItemState> 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::LocalRevision; + + itemStates.append(itemState); + } + + m_updateItemStatesThread->setData(m_plugin, itemStates); + m_updateItemStatesThread->start(); // applyUpdatedItemStates() is called when finished } - m_view->viewport()->repaint(); // TODO: this should not be necessary, as DolphinModel::setData() calls dataChanged() - - m_plugin->endRetrieval(); } #include "revisioncontrolobserver.moc" |
