diff options
| author | Peter Penz <[email protected]> | 2009-07-17 19:26:46 +0000 |
|---|---|---|
| committer | Peter Penz <[email protected]> | 2009-07-17 19:26:46 +0000 |
| commit | a447eb391c53e2731f61375411007b73bf95a0a3 (patch) | |
| tree | 88a20ddc638713a2e6bb758bc97697ccc39a4de3 /src/revisioncontrolobserver.cpp | |
| parent | 93ce7f40e2d067eba48b317ef4028c2c75eebebd (diff) | |
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.
Still open issue: Applying the revision control property to the model is a bottleneck in QListView (a detailed description of the reason is in kdelibs/kfile/kfilepreviewgenerator.cpp, class LayoutBlocker). But the approach used in KFilePreviewGenerator destroys the textlayout in this case and is temporary disabled until I could track down the reason.
svn path=/trunk/KDE/kdebase/apps/; revision=998492
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" |
