diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/kitemviews/kfileitemmodel.cpp | 19 | ||||
| -rw-r--r-- | src/kitemviews/kfileitemmodelrolesupdater.cpp | 22 | ||||
| -rw-r--r-- | src/kitemviews/kfileitemmodelrolesupdater.h | 2 | ||||
| -rw-r--r-- | src/kitemviews/kitemlistview.cpp | 4 | ||||
| -rw-r--r-- | src/kitemviews/kitemlistview.h | 12 | ||||
| -rw-r--r-- | src/kitemviews/kitemlistwidget.h | 2 | ||||
| -rw-r--r-- | src/kitemviews/kstandarditemlistwidget.cpp | 180 | ||||
| -rw-r--r-- | src/kitemviews/kstandarditemlistwidget.h | 6 | ||||
| -rw-r--r-- | src/kitemviews/private/kdirectorycontentscounter.cpp | 23 | ||||
| -rw-r--r-- | src/kitemviews/private/kdirectorycontentscounter.h | 4 | ||||
| -rw-r--r-- | src/kitemviews/private/kitemlistsizehintresolver.cpp | 26 | ||||
| -rw-r--r-- | src/kitemviews/private/kitemlistsizehintresolver.h | 4 | ||||
| -rw-r--r-- | src/kitemviews/private/kitemlistviewlayouter.cpp | 77 | ||||
| -rw-r--r-- | src/kitemviews/private/kitemlistviewlayouter.h | 8 | ||||
| -rw-r--r-- | src/main.cpp | 2 | ||||
| -rw-r--r-- | src/views/versioncontrol/updateitemstatesthread.cpp | 16 | ||||
| -rw-r--r-- | src/views/versioncontrol/updateitemstatesthread.h | 3 | ||||
| -rw-r--r-- | src/views/versioncontrol/versioncontrolobserver.cpp | 11 |
18 files changed, 251 insertions, 170 deletions
diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp index 87006718a..b3c56e1c6 100644 --- a/src/kitemviews/kfileitemmodel.cpp +++ b/src/kitemviews/kfileitemmodel.cpp @@ -21,7 +21,6 @@ #include "kfileitemmodel.h" -#include <KDirModel> #include <KGlobalSettings> #include <KLocale> #include <KStringHandler> @@ -247,9 +246,23 @@ QMimeData* KFileItemModel::createMimeData(const KItemSet& indexes) const KUrl::List urls; KUrl::List mostLocalUrls; bool canUseMostLocalUrls = true; + const ItemData* lastAddedItem = 0; foreach (int index, indexes) { - const KFileItem item = fileItem(index); + const ItemData* itemData = m_itemData.at(index); + const ItemData* parent = itemData->parent; + + while (parent && parent != lastAddedItem) { + parent = parent->parent; + } + + if (parent && parent == lastAddedItem) { + // A parent of 'itemData' has been added already. + continue; + } + + lastAddedItem = itemData; + const KFileItem& item = itemData->item; if (!item.isNull()) { urls << item.targetUrl(); @@ -262,9 +275,7 @@ QMimeData* KFileItemModel::createMimeData(const KItemSet& indexes) const } const bool different = canUseMostLocalUrls && mostLocalUrls != urls; - urls = KDirModel::simplifiedUrlList(urls); // TODO: Check if we still need KDirModel for this in KDE 5.0 if (different) { - mostLocalUrls = KDirModel::simplifiedUrlList(mostLocalUrls); urls.populateMimeData(mostLocalUrls, data); } else { urls.populateMimeData(data); diff --git a/src/kitemviews/kfileitemmodelrolesupdater.cpp b/src/kitemviews/kfileitemmodelrolesupdater.cpp index d6445c981..f11d5a5d3 100644 --- a/src/kitemviews/kfileitemmodelrolesupdater.cpp +++ b/src/kitemviews/kfileitemmodelrolesupdater.cpp @@ -587,7 +587,7 @@ void KFileItemModelRolesUpdater::slotPreviewFailed(const KFileItem& item) connect(m_model, SIGNAL(itemsChanged(KItemRangeList,QSet<QByteArray>)), this, SLOT(slotItemsChanged(KItemRangeList,QSet<QByteArray>))); - applyResolvedRoles(item, ResolveAll); + applyResolvedRoles(index, ResolveAll); m_finishedItems.insert(item); } } @@ -664,7 +664,7 @@ void KFileItemModelRolesUpdater::resolveNextPendingRoles() continue; } - applyResolvedRoles(item, ResolveAll); + applyResolvedRoles(index, ResolveAll); m_finishedItems.insert(item); m_changedItems.remove(item); break; @@ -850,8 +850,7 @@ void KFileItemModelRolesUpdater::updateVisibleIcons() // Try to determine the final icons for all visible items. int index; for (index = m_firstVisibleIndex; index <= lastVisibleIndex && timer.elapsed() < MaxBlockTimeout; ++index) { - const KFileItem item = m_model->fileItem(index); - applyResolvedRoles(item, ResolveFast); + applyResolvedRoles(index, ResolveFast); } // KFileItemListView::initializeItemListWidget(KItemListWidget*) will load @@ -1024,27 +1023,20 @@ void KFileItemModelRolesUpdater::applySortProgressToModel() m_model->emitSortProgress(resolvedCount); } -bool KFileItemModelRolesUpdater::applyResolvedRoles(const KFileItem& item, ResolveHint hint) +bool KFileItemModelRolesUpdater::applyResolvedRoles(int index, ResolveHint hint) { - if (item.isNull()) { - return false; - } - + const KFileItem item = m_model->fileItem(index); const bool resolveAll = (hint == ResolveAll); bool iconChanged = false; if (!item.isMimeTypeKnown() || !item.isFinalIconKnown()) { item.determineMimeType(); iconChanged = true; - } else { - const int index = m_model->index(item); - if (!m_model->data(index).contains("iconName")) { - iconChanged = true; - } + } else if (!m_model->data(index).contains("iconName")) { + iconChanged = true; } if (iconChanged || resolveAll || m_clearPreviews) { - const int index = m_model->index(item); if (index < 0) { return false; } diff --git a/src/kitemviews/kfileitemmodelrolesupdater.h b/src/kitemviews/kfileitemmodelrolesupdater.h index fced44a85..19207575e 100644 --- a/src/kitemviews/kfileitemmodelrolesupdater.h +++ b/src/kitemviews/kfileitemmodelrolesupdater.h @@ -261,7 +261,7 @@ private: ResolveFast, ResolveAll }; - bool applyResolvedRoles(const KFileItem& item, ResolveHint hint); + bool applyResolvedRoles(int index, ResolveHint hint); QHash<QByteArray, QVariant> rolesData(const KFileItem& item); /** diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp index 7f497210c..38ce63af0 100644 --- a/src/kitemviews/kitemlistview.cpp +++ b/src/kitemviews/kitemlistview.cpp @@ -460,9 +460,9 @@ int KItemListView::lastVisibleIndex() const return m_layouter->lastVisibleIndex(); } -QSizeF KItemListView::itemSizeHint(int index) const +void KItemListView::calculateItemSizeHints(QVector<QSizeF>& sizeHints) const { - return widgetCreator()->itemSizeHint(index, this); + widgetCreator()->calculateItemSizeHints(sizeHints, this); } void KItemListView::setSupportsItemExpanding(bool supportsExpanding) diff --git a/src/kitemviews/kitemlistview.h b/src/kitemviews/kitemlistview.h index dbe923086..f39e73a97 100644 --- a/src/kitemviews/kitemlistview.h +++ b/src/kitemviews/kitemlistview.h @@ -194,12 +194,12 @@ public: int lastVisibleIndex() const; /** - * @return Required size for the item with the index \p index. + * @return Required size for all items in the model. * The returned value might be larger than KItemListView::itemSize(). * In this case the layout grid will be stretched to assure an * unclipped item. */ - QSizeF itemSizeHint(int index) const; + void calculateItemSizeHints(QVector<QSizeF>& sizeHints) const; /** * If set to true, items having child-items can be expanded to show the child-items as @@ -802,7 +802,7 @@ public: virtual void recycle(KItemListWidget* widget); - virtual QSizeF itemSizeHint(int index, const KItemListView* view) const = 0; + virtual void calculateItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const = 0; virtual qreal preferredRoleColumnWidth(const QByteArray& role, int index, @@ -821,7 +821,7 @@ public: virtual KItemListWidget* create(KItemListView* view); - virtual QSizeF itemSizeHint(int index, const KItemListView* view) const; + virtual void calculateItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const; virtual qreal preferredRoleColumnWidth(const QByteArray& role, int index, @@ -854,9 +854,9 @@ KItemListWidget* KItemListWidgetCreator<T>::create(KItemListView* view) } template<class T> -QSizeF KItemListWidgetCreator<T>::itemSizeHint(int index, const KItemListView* view) const +void KItemListWidgetCreator<T>::calculateItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const { - return m_informant->itemSizeHint(index, view); + return m_informant->calculateItemSizeHints(sizeHints, view); } template<class T> diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h index 55181faa8..954629ddd 100644 --- a/src/kitemviews/kitemlistwidget.h +++ b/src/kitemviews/kitemlistwidget.h @@ -49,7 +49,7 @@ public: KItemListWidgetInformant(); virtual ~KItemListWidgetInformant(); - virtual QSizeF itemSizeHint(int index, const KItemListView* view) const = 0; + virtual void calculateItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const = 0; virtual qreal preferredRoleColumnWidth(const QByteArray& role, int index, diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp index acdf839ac..9a9a734ed 100644 --- a/src/kitemviews/kstandarditemlistwidget.cpp +++ b/src/kitemviews/kstandarditemlistwidget.cpp @@ -55,84 +55,25 @@ KStandardItemListWidgetInformant::~KStandardItemListWidgetInformant() { } -QSizeF KStandardItemListWidgetInformant::itemSizeHint(int index, const KItemListView* view) const +void KStandardItemListWidgetInformant::calculateItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const { - const KItemListStyleOption& option = view->styleOption(); - const int additionalRolesCount = qMax(view->visibleRoles().count() - 1, 0); - switch (static_cast<const KStandardItemListView*>(view)->itemLayout()) { - case KStandardItemListWidget::IconsLayout: { - const QString text = KStringHandler::preProcessWrap(itemText(index, view)); - - const qreal itemWidth = view->itemSize().width(); - const qreal maxWidth = itemWidth - 2 * option.padding; - QTextLine line; - - // Calculate the number of lines required for wrapping the name - QTextOption textOption(Qt::AlignHCenter); - textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); - - qreal textHeight = 0; - QTextLayout layout(text, option.font); - layout.setTextOption(textOption); - layout.beginLayout(); - while ((line = layout.createLine()).isValid()) { - line.setLineWidth(maxWidth); - line.naturalTextWidth(); - textHeight += line.height(); - } - layout.endLayout(); - - // Add one line for each additional information - textHeight += additionalRolesCount * option.fontMetrics.lineSpacing(); - - const qreal maxTextHeight = option.maxTextSize.height(); - if (maxTextHeight > 0 && textHeight > maxTextHeight) { - textHeight = maxTextHeight; - } - - return QSizeF(itemWidth, textHeight + option.iconSize + option.padding * 3); - } - - case KStandardItemListWidget::CompactLayout: { - // For each row exactly one role is shown. Calculate the maximum required width that is necessary - // to show all roles without horizontal clipping. - qreal maximumRequiredWidth = 0.0; - - const QList<QByteArray>& visibleRoles = view->visibleRoles(); - const bool showOnlyTextRole = (visibleRoles.count() == 1) && (visibleRoles.first() == "text"); - - if (showOnlyTextRole) { - maximumRequiredWidth = option.fontMetrics.width(itemText(index, view)); - } else { - const QHash<QByteArray, QVariant> values = view->model()->data(index); - foreach (const QByteArray& role, view->visibleRoles()) { - const QString text = roleText(role, values); - const qreal requiredWidth = option.fontMetrics.width(text); - maximumRequiredWidth = qMax(maximumRequiredWidth, requiredWidth); - } - } + case KStandardItemListWidget::IconsLayout: + calculateIconsLayoutItemSizeHints(sizeHints, view); + break; - qreal width = option.padding * 4 + option.iconSize + maximumRequiredWidth; - const qreal maxWidth = option.maxTextSize.width(); - if (maxWidth > 0 && width > maxWidth) { - width = maxWidth; - } - const qreal height = option.padding * 2 + qMax(option.iconSize, (1 + additionalRolesCount) * option.fontMetrics.lineSpacing()); - return QSizeF(width, height); - } + case KStandardItemListWidget::CompactLayout: + calculateCompactLayoutItemSizeHints(sizeHints, view); + break; - case KStandardItemListWidget::DetailsLayout: { - const qreal height = option.padding * 2 + qMax(option.iconSize, option.fontMetrics.height()); - return QSizeF(-1, height); - } + case KStandardItemListWidget::DetailsLayout: + calculateDetailsLayoutItemSizeHints(sizeHints, view); + break; default: Q_ASSERT(false); break; } - - return QSize(); } qreal KStandardItemListWidgetInformant::preferredRoleColumnWidth(const QByteArray& role, @@ -181,6 +122,107 @@ QString KStandardItemListWidgetInformant::roleText(const QByteArray& role, return values.value(role).toString(); } +void KStandardItemListWidgetInformant::calculateIconsLayoutItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const +{ + const KItemListStyleOption& option = view->styleOption(); + const QFont& font = option.font; + const int additionalRolesCount = qMax(view->visibleRoles().count() - 1, 0); + + const qreal itemWidth = view->itemSize().width(); + const qreal maxWidth = itemWidth - 2 * option.padding; + const qreal maxTextHeight = option.maxTextSize.height(); + const qreal additionalRolesSpacing = additionalRolesCount * option.fontMetrics.lineSpacing(); + const qreal spacingAndIconHeight = option.iconSize + option.padding * 3; + + QTextOption textOption(Qt::AlignHCenter); + textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); + + for (int index = 0; index < sizeHints.count(); ++index) { + if (!sizeHints.at(index).isEmpty()) { + continue; + } + + const QString& text = KStringHandler::preProcessWrap(itemText(index, view)); + + // Calculate the number of lines required for wrapping the name + qreal textHeight = 0; + QTextLayout layout(text, font); + layout.setTextOption(textOption); + layout.beginLayout(); + QTextLine line; + while ((line = layout.createLine()).isValid()) { + line.setLineWidth(maxWidth); + line.naturalTextWidth(); + textHeight += line.height(); + } + layout.endLayout(); + + // Add one line for each additional information + textHeight += additionalRolesSpacing; + + if (maxTextHeight > 0 && textHeight > maxTextHeight) { + textHeight = maxTextHeight; + } + + sizeHints[index] = QSizeF(itemWidth, textHeight + spacingAndIconHeight); + } +} + +void KStandardItemListWidgetInformant::calculateCompactLayoutItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const +{ + const KItemListStyleOption& option = view->styleOption(); + const QFontMetrics& fontMetrics = option.fontMetrics; + const int additionalRolesCount = qMax(view->visibleRoles().count() - 1, 0); + + const QList<QByteArray>& visibleRoles = view->visibleRoles(); + const bool showOnlyTextRole = (visibleRoles.count() == 1) && (visibleRoles.first() == "text"); + const qreal maxWidth = option.maxTextSize.width(); + const qreal paddingAndIconWidth = option.padding * 4 + option.iconSize; + const qreal height = option.padding * 2 + qMax(option.iconSize, (1 + additionalRolesCount) * option.fontMetrics.lineSpacing()); + + for (int index = 0; index < sizeHints.count(); ++index) { + if (!sizeHints.at(index).isEmpty()) { + continue; + } + + // For each row exactly one role is shown. Calculate the maximum required width that is necessary + // to show all roles without horizontal clipping. + qreal maximumRequiredWidth = 0.0; + + if (showOnlyTextRole) { + maximumRequiredWidth = fontMetrics.width(itemText(index, view)); + } else { + const QHash<QByteArray, QVariant>& values = view->model()->data(index); + foreach (const QByteArray& role, visibleRoles) { + const QString& text = roleText(role, values); + const qreal requiredWidth = fontMetrics.width(text); + maximumRequiredWidth = qMax(maximumRequiredWidth, requiredWidth); + } + } + + qreal width = paddingAndIconWidth + maximumRequiredWidth; + if (maxWidth > 0 && width > maxWidth) { + width = maxWidth; + } + + sizeHints[index] = QSizeF(width, height); + } +} + +void KStandardItemListWidgetInformant::calculateDetailsLayoutItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const +{ + const KItemListStyleOption& option = view->styleOption(); + const qreal height = option.padding * 2 + qMax(option.iconSize, option.fontMetrics.height()); + + for (int index = 0; index < sizeHints.count(); ++index) { + if (!sizeHints.at(index).isEmpty()) { + continue; + } + + sizeHints[index] = QSizeF(-1, height); + } +} + KStandardItemListWidget::KStandardItemListWidget(KItemListWidgetInformant* informant, QGraphicsItem* parent) : KItemListWidget(informant, parent), m_isCut(false), diff --git a/src/kitemviews/kstandarditemlistwidget.h b/src/kitemviews/kstandarditemlistwidget.h index 7dd93b2b8..ca198c36b 100644 --- a/src/kitemviews/kstandarditemlistwidget.h +++ b/src/kitemviews/kstandarditemlistwidget.h @@ -38,7 +38,7 @@ public: KStandardItemListWidgetInformant(); virtual ~KStandardItemListWidgetInformant(); - virtual QSizeF itemSizeHint(int index, const KItemListView* view) const; + virtual void calculateItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const; virtual qreal preferredRoleColumnWidth(const QByteArray& role, int index, @@ -61,6 +61,10 @@ protected: virtual QString roleText(const QByteArray& role, const QHash<QByteArray, QVariant>& values) const; + void calculateIconsLayoutItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const; + void calculateCompactLayoutItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const; + void calculateDetailsLayoutItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const; + friend class KStandardItemListWidget; // Accesses roleText() }; diff --git a/src/kitemviews/private/kdirectorycontentscounter.cpp b/src/kitemviews/private/kdirectorycontentscounter.cpp index fd8479feb..65afb7c3e 100644 --- a/src/kitemviews/private/kdirectorycontentscounter.cpp +++ b/src/kitemviews/private/kdirectorycontentscounter.cpp @@ -30,7 +30,6 @@ KDirectoryContentsCounter::KDirectoryContentsCounter(KFileItemModel* model, QObj QObject(parent), m_model(model), m_queue(), - m_workerThread(0), m_worker(0), m_workerIsBusy(false), m_dirWatcher(0), @@ -39,25 +38,34 @@ KDirectoryContentsCounter::KDirectoryContentsCounter(KFileItemModel* model, QObj connect(m_model, SIGNAL(itemsRemoved(KItemRangeList)), this, SLOT(slotItemsRemoved())); - m_workerThread = new QThread(this); + if (!m_workerThread) { + m_workerThread = new QThread(); + m_workerThread->start(); + } + m_worker = new KDirectoryContentsCounterWorker(); m_worker->moveToThread(m_workerThread); + ++m_workersCount; connect(this, SIGNAL(requestDirectoryContentsCount(QString,KDirectoryContentsCounterWorker::Options)), m_worker, SLOT(countDirectoryContents(QString,KDirectoryContentsCounterWorker::Options))); connect(m_worker, SIGNAL(result(QString,int)), this, SLOT(slotResult(QString,int))); - m_workerThread->start(); - m_dirWatcher = new KDirWatch(this); connect(m_dirWatcher, SIGNAL(dirty(QString)), this, SLOT(slotDirWatchDirty(QString))); } KDirectoryContentsCounter::~KDirectoryContentsCounter() { - m_workerThread->quit(); - m_workerThread->wait(); + --m_workersCount; + + if (m_workersCount == 0) { + m_workerThread->quit(); + m_workerThread->wait(); + delete m_workerThread; + m_workerThread = 0; + } delete m_worker; } @@ -162,3 +170,6 @@ void KDirectoryContentsCounter::startWorker(const QString& path) m_workerIsBusy = true; } } + +QThread* KDirectoryContentsCounter::m_workerThread = 0; +int KDirectoryContentsCounter::m_workersCount = 0;
\ No newline at end of file diff --git a/src/kitemviews/private/kdirectorycontentscounter.h b/src/kitemviews/private/kdirectorycontentscounter.h index 425c3632a..c03d0249c 100644 --- a/src/kitemviews/private/kdirectorycontentscounter.h +++ b/src/kitemviews/private/kdirectorycontentscounter.h @@ -78,7 +78,9 @@ private: QQueue<QString> m_queue; - QThread* m_workerThread; + static QThread* m_workerThread; + static int m_workersCount; + KDirectoryContentsCounterWorker* m_worker; bool m_workerIsBusy; diff --git a/src/kitemviews/private/kitemlistsizehintresolver.cpp b/src/kitemviews/private/kitemlistsizehintresolver.cpp index 0e2286b45..029beddf9 100644 --- a/src/kitemviews/private/kitemlistsizehintresolver.cpp +++ b/src/kitemviews/private/kitemlistsizehintresolver.cpp @@ -23,7 +23,8 @@ KItemListSizeHintResolver::KItemListSizeHintResolver(const KItemListView* itemListView) : m_itemListView(itemListView), - m_sizeHintCache() + m_sizeHintCache(), + m_needsResolving(false) { } @@ -31,14 +32,10 @@ KItemListSizeHintResolver::~KItemListSizeHintResolver() { } -QSizeF KItemListSizeHintResolver::sizeHint(int index) const +QSizeF KItemListSizeHintResolver::sizeHint(int index) { - QSizeF size = m_sizeHintCache.at(index); - if (size.isEmpty()) { - size = m_itemListView->itemSizeHint(index); - m_sizeHintCache[index] = size; - } - return size; + updateCache(); + return m_sizeHintCache.at(index); } void KItemListSizeHintResolver::itemsInserted(const KItemRangeList& itemRanges) @@ -77,6 +74,8 @@ void KItemListSizeHintResolver::itemsInserted(const KItemRangeList& itemRanges) } } + m_needsResolving = true; + Q_ASSERT(m_sizeHintCache.count() == m_itemListView->model()->count()); } @@ -135,9 +134,20 @@ void KItemListSizeHintResolver::itemsChanged(int index, int count, const QSet<QB ++index; --count; } + + m_needsResolving = true; } void KItemListSizeHintResolver::clearCache() { m_sizeHintCache.fill(QSizeF()); + m_needsResolving = true; +} + +void KItemListSizeHintResolver::updateCache() +{ + if (m_needsResolving) { + m_itemListView->calculateItemSizeHints(m_sizeHintCache); + m_needsResolving = false; + } } diff --git a/src/kitemviews/private/kitemlistsizehintresolver.h b/src/kitemviews/private/kitemlistsizehintresolver.h index 486f9b631..86580bf7b 100644 --- a/src/kitemviews/private/kitemlistsizehintresolver.h +++ b/src/kitemviews/private/kitemlistsizehintresolver.h @@ -36,7 +36,7 @@ class LIBDOLPHINPRIVATE_EXPORT KItemListSizeHintResolver public: KItemListSizeHintResolver(const KItemListView* itemListView); virtual ~KItemListSizeHintResolver(); - QSizeF sizeHint(int index) const; + QSizeF sizeHint(int index); void itemsInserted(const KItemRangeList& itemRanges); void itemsRemoved(const KItemRangeList& itemRanges); @@ -44,10 +44,12 @@ public: void itemsChanged(int index, int count, const QSet<QByteArray>& roles); void clearCache(); + void updateCache(); private: const KItemListView* m_itemListView; mutable QVector<QSizeF> m_sizeHintCache; + bool m_needsResolving; }; #endif diff --git a/src/kitemviews/private/kitemlistviewlayouter.cpp b/src/kitemviews/private/kitemlistviewlayouter.cpp index f5f63d5ab..73f3d6182 100644 --- a/src/kitemviews/private/kitemlistviewlayouter.cpp +++ b/src/kitemviews/private/kitemlistviewlayouter.cpp @@ -46,6 +46,8 @@ KItemListViewLayouter::KItemListViewLayouter(QObject* parent) : m_columnWidth(0), m_xPosInc(0), m_columnCount(0), + m_rowOffsets(), + m_columnOffsets(), m_groupItemIndexes(), m_groupHeaderHeight(0), m_groupHeaderMargin(0), @@ -207,7 +209,7 @@ const KItemModelBase* KItemListViewLayouter::model() const return m_model; } -void KItemListViewLayouter::setSizeHintResolver(const KItemListSizeHintResolver* sizeHintResolver) +void KItemListViewLayouter::setSizeHintResolver(KItemListSizeHintResolver* sizeHintResolver) { if (m_sizeHintResolver != sizeHintResolver) { m_sizeHintResolver = sizeHintResolver; @@ -246,11 +248,13 @@ QRectF KItemListViewLayouter::itemRect(int index) const sizeHint = m_itemSize; } + const qreal x = m_columnOffsets.at(m_itemInfos.at(index).column); + const qreal y = m_rowOffsets.at(m_itemInfos.at(index).row); + if (m_scrollOrientation == Qt::Horizontal) { // Rotate the logical direction which is always vertical by 90° // to get the physical horizontal direction - const QPointF logicalPos = m_itemInfos[index].pos; - QPointF pos(logicalPos.y(), logicalPos.x()); + QPointF pos(y, x); pos.rx() -= m_scrollOffset; return QRectF(pos, sizeHint); } @@ -260,8 +264,7 @@ QRectF KItemListViewLayouter::itemRect(int index) const sizeHint.rwidth() = m_itemSize.width(); } - QPointF pos = m_itemInfos[index].pos; - pos -= QPointF(m_itemOffset, m_scrollOffset); + const QPointF pos(x - m_itemOffset, y - m_scrollOffset); return QRectF(pos, sizeHint); } @@ -284,16 +287,15 @@ QRectF KItemListViewLayouter::groupHeaderRect(int index) const pos.rx() -= m_itemMargin.width(); pos.ry() = 0; - // Determine the maximum width used in the - // current column. As the scroll-direction is - // Qt::Horizontal and m_itemRects is accessed directly, - // the logical height represents the visual width. + // Determine the maximum width used in the current column. As the + // scroll-direction is Qt::Horizontal and m_itemRects is accessed + // directly, the logical height represents the visual width, and + // the logical row represents the column. qreal headerWidth = minimumGroupHeaderWidth(); - const qreal y = m_itemInfos[index].pos.y(); + const int row = m_itemInfos[index].row; const int maxIndex = m_itemInfos.count() - 1; while (index <= maxIndex) { - const QPointF pos = m_itemInfos[index].pos; - if (pos.y() != y) { + if (m_itemInfos[index].row != row) { break; } @@ -422,21 +424,40 @@ void KItemListViewLayouter::doLayout() m_itemInfos.resize(itemCount); + // Calculate the offset of each column, i.e., the x-coordinate where the column starts. + m_columnOffsets.resize(m_columnCount); + qreal currentOffset = m_xPosInc; + + if (grouped && horizontalScrolling) { + // All group headers will always be aligned on the top and not + // flipped like the other properties. + currentOffset += m_groupHeaderHeight; + } + + for (int column = 0; column < m_columnCount; ++column) { + m_columnOffsets[column] = currentOffset; + currentOffset += m_columnWidth; + } + + // Prepare the QVector which stores the y-coordinate for each new row. + int numberOfRows = (itemCount + m_columnCount - 1) / m_columnCount; + if (grouped && m_columnCount > 1) { + // In the worst case, a new row will be started for every group. + // We could calculate the exact number of rows now to prevent that we reserve + // too much memory, but the code required to do that might need much more + // memory than it would save in the average case. + numberOfRows += m_groupItemIndexes.count(); + } + m_rowOffsets.resize(numberOfRows); + qreal y = m_headerHeight + itemMargin.height(); int row = 0; int index = 0; while (index < itemCount) { - qreal x = m_xPosInc; qreal maxItemHeight = itemSize.height(); if (grouped) { - if (horizontalScrolling) { - // All group headers will always be aligned on the top and not - // flipped like the other properties - x += m_groupHeaderHeight; - } - if (m_groupItemIndexes.contains(index)) { // The item is the first item of a group. // Increase the y-position to provide space @@ -456,6 +477,8 @@ void KItemListViewLayouter::doLayout() } } + m_rowOffsets[row] = y; + int column = 0; while (index < itemCount && column < m_columnCount) { qreal requiredItemHeight = itemSize.height(); @@ -468,7 +491,6 @@ void KItemListViewLayouter::doLayout() } ItemInfo& itemInfo = m_itemInfos[index]; - itemInfo.pos = QPointF(x, y); itemInfo.column = column; itemInfo.row = row; @@ -492,7 +514,6 @@ void KItemListViewLayouter::doLayout() } maxItemHeight = qMax(maxItemHeight, requiredItemHeight); - x += m_columnWidth; ++index; ++column; @@ -547,7 +568,7 @@ void KItemListViewLayouter::updateVisibleIndexes() int mid = 0; do { mid = (min + max) / 2; - if (m_itemInfos[mid].pos.y() < m_scrollOffset) { + if (m_rowOffsets.at(m_itemInfos[mid].row) < m_scrollOffset) { min = mid + 1; } else { max = mid - 1; @@ -557,13 +578,13 @@ void KItemListViewLayouter::updateVisibleIndexes() if (mid > 0) { // Include the row before the first fully visible index, as it might // be partly visible - if (m_itemInfos[mid].pos.y() >= m_scrollOffset) { + if (m_rowOffsets.at(m_itemInfos[mid].row) >= m_scrollOffset) { --mid; - Q_ASSERT(m_itemInfos[mid].pos.y() < m_scrollOffset); + Q_ASSERT(m_rowOffsets.at(m_itemInfos[mid].row) < m_scrollOffset); } - const qreal rowTop = m_itemInfos[mid].pos.y(); - while (mid > 0 && m_itemInfos[mid - 1].pos.y() == rowTop) { + const int firstVisibleRow = m_itemInfos[mid].row; + while (mid > 0 && m_itemInfos[mid - 1].row == firstVisibleRow) { --mid; } } @@ -580,14 +601,14 @@ void KItemListViewLayouter::updateVisibleIndexes() max = maxIndex; do { mid = (min + max) / 2; - if (m_itemInfos[mid].pos.y() <= bottom) { + if (m_rowOffsets.at(m_itemInfos[mid].row) <= bottom) { min = mid + 1; } else { max = mid - 1; } } while (min <= max); - while (mid > 0 && m_itemInfos[mid].pos.y() > bottom) { + while (mid > 0 && m_rowOffsets.at(m_itemInfos[mid].row) > bottom) { --mid; } m_lastVisibleIndex = mid; diff --git a/src/kitemviews/private/kitemlistviewlayouter.h b/src/kitemviews/private/kitemlistviewlayouter.h index a3b0893a1..5ae472411 100644 --- a/src/kitemviews/private/kitemlistviewlayouter.h +++ b/src/kitemviews/private/kitemlistviewlayouter.h @@ -103,7 +103,7 @@ public: void setModel(const KItemModelBase* model); const KItemModelBase* model() const; - void setSizeHintResolver(const KItemListSizeHintResolver* sizeHintResolver); + void setSizeHintResolver(KItemListSizeHintResolver* sizeHintResolver); const KItemListSizeHintResolver* sizeHintResolver() const; /** @@ -205,7 +205,7 @@ private: QSizeF m_itemMargin; qreal m_headerHeight; const KItemModelBase* m_model; - const KItemListSizeHintResolver* m_sizeHintResolver; + KItemListSizeHintResolver* m_sizeHintResolver; qreal m_scrollOffset; qreal m_maximumScrollOffset; @@ -220,6 +220,9 @@ private: qreal m_xPosInc; int m_columnCount; + QVector<qreal> m_rowOffsets; + QVector<qreal> m_columnOffsets; + // Stores all item indexes that are the first item of a group. // Assures fast access for KItemListViewLayouter::isFirstGroupItem(). QSet<int> m_groupItemIndexes; @@ -227,7 +230,6 @@ private: qreal m_groupHeaderMargin; struct ItemInfo { - QPointF pos; int column; int row; }; diff --git a/src/main.cpp b/src/main.cpp index ea889d1e3..a8e785a0d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -36,7 +36,7 @@ KDE_EXPORT int kdemain(int argc, char **argv) KDE_VERSION_STRING, ki18nc("@title", "File Manager"), KAboutData::License_GPL, - ki18nc("@info:credit", "(C) 2006-2013 Peter Penz and Frank Reininghaus")); + ki18nc("@info:credit", "(C) 2006-2014 Peter Penz and Frank Reininghaus")); about.setHomepage("http://dolphin.kde.org"); about.addAuthor(ki18nc("@info:credit", "Frank Reininghaus"), ki18nc("@info:credit", "Maintainer (since 2012) and developer"), diff --git a/src/views/versioncontrol/updateitemstatesthread.cpp b/src/views/versioncontrol/updateitemstatesthread.cpp index 6be07d361..6bc389098 100644 --- a/src/views/versioncontrol/updateitemstatesthread.cpp +++ b/src/views/versioncontrol/updateitemstatesthread.cpp @@ -28,7 +28,6 @@ UpdateItemStatesThread::UpdateItemStatesThread(KVersionControlPlugin* plugin, QThread(), m_globalPluginMutex(0), m_plugin(plugin), - m_retrievedItems(false), m_itemStates(itemStates) { // Several threads may share one instance of a plugin. A global @@ -47,12 +46,11 @@ void UpdateItemStatesThread::run() Q_ASSERT(!m_itemStates.isEmpty()); Q_ASSERT(m_plugin); - m_retrievedItems = false; - QMutexLocker pluginLocker(m_globalPluginMutex); - foreach (const QString& directory, m_itemStates.keys()) { - if (m_plugin->beginRetrieval(directory)) { - QVector<VersionControlObserver::ItemState>& items = m_itemStates[directory]; + QMap<QString, QVector<VersionControlObserver::ItemState> >::iterator it = m_itemStates.begin(); + for (; it != m_itemStates.end(); ++it) { + if (m_plugin->beginRetrieval(it.key())) { + QVector<VersionControlObserver::ItemState>& items = it.value(); const int count = items.count(); KVersionControlPlugin2* pluginV2 = qobject_cast<KVersionControlPlugin2*>(m_plugin); @@ -68,7 +66,6 @@ void UpdateItemStatesThread::run() } m_plugin->endRetrieval(); - m_retrievedItems = true; } } } @@ -88,9 +85,4 @@ QMap<QString, QVector<VersionControlObserver::ItemState> > UpdateItemStatesThrea return m_itemStates; } -bool UpdateItemStatesThread::retrievedItems() const -{ - return m_retrievedItems; -} - #include "updateitemstatesthread.moc" diff --git a/src/views/versioncontrol/updateitemstatesthread.h b/src/views/versioncontrol/updateitemstatesthread.h index 2914bc2b7..0e92a4cfd 100644 --- a/src/views/versioncontrol/updateitemstatesthread.h +++ b/src/views/versioncontrol/updateitemstatesthread.h @@ -65,8 +65,6 @@ public: QMap<QString, QVector<VersionControlObserver::ItemState> > itemStates() const; - bool retrievedItems() const; - protected: virtual void run(); @@ -74,7 +72,6 @@ private: QMutex* m_globalPluginMutex; // Protects the m_plugin globally KVersionControlPlugin* m_plugin; - bool m_retrievedItems; QMap<QString, QVector<VersionControlObserver::ItemState> > m_itemStates; }; diff --git a/src/views/versioncontrol/versioncontrolobserver.cpp b/src/views/versioncontrol/versioncontrolobserver.cpp index 4d939ee0d..888d93461 100644 --- a/src/views/versioncontrol/versioncontrolobserver.cpp +++ b/src/views/versioncontrol/versioncontrolobserver.cpp @@ -198,15 +198,10 @@ void VersionControlObserver::slotThreadFinished() return; } - if (!thread->retrievedItems()) { - // Ignore m_silentUpdate for an error message - emit errorMessage(i18nc("@info:status", "Update of version information failed.")); - return; - } - const QMap<QString, QVector<ItemState> >& itemStates = thread->itemStates(); - foreach (const QString& directory, itemStates.keys()) { - const QVector<ItemState>& items = itemStates.value(directory); + QMap<QString, QVector<ItemState> >::const_iterator it = itemStates.constBegin(); + for (; it != itemStates.constEnd(); ++it) { + const QVector<ItemState>& items = it.value(); foreach (const ItemState& item, items) { QHash<QByteArray, QVariant> values; |
