X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/e73389e2090e05a30f20381e7f229f9bba319672..e6ea3ab4c41dcc115143a237aafd3a1152849433:/src/kitemviews/kfileitemmodelrolesupdater.h diff --git a/src/kitemviews/kfileitemmodelrolesupdater.h b/src/kitemviews/kfileitemmodelrolesupdater.h index 5ed45a6ec..e21cd30df 100644 --- a/src/kitemviews/kfileitemmodelrolesupdater.h +++ b/src/kitemviews/kfileitemmodelrolesupdater.h @@ -20,20 +20,34 @@ #ifndef KFILEITEMMODELROLESUPDATER_H #define KFILEITEMMODELROLESUPDATER_H -#include +#include "dolphin_export.h" +#include "kitemviews/kitemmodelbase.h" #include -#include +#include #include #include #include #include +class KDirectoryContentsCounter; class KFileItemModel; -class KJob; class QPixmap; class QTimer; +class KOverlayIconPlugin; + +namespace KIO { + class PreviewJob; +} + +#ifdef HAVE_BALOO + namespace Baloo + { + class FileMonitor; + } + #include +#endif /** * @brief Resolves expensive roles asynchronously and applies them to the KFileItemModel. @@ -41,14 +55,46 @@ class QTimer; * KFileItemModel only resolves roles that are inexpensive like e.g. the file name or * the permissions. Creating previews or determining the MIME-type can be quite expensive * and KFileItemModelRolesUpdater takes care to update such roles asynchronously. + * + * To prevent a huge CPU and I/O load, these roles are not updated for all + * items, but only for the visible items, some items around the visible area, + * and the items on the first and last pages of the view. This is a compromise + * that aims to minimize the risk that the user sees items with unknown icons + * in the view when scrolling or pressing Home or End. + * + * Determining the roles is done in several phases: + * + * 1. If the sort role is "slow", it is determined for all items. If this + * cannot be finished synchronously in 200 ms, the remaining items are + * handled asynchronously by \a resolveNextSortRole(). + * + * 2. The function startUpdating(), which is called if either the sort role + * has been successfully determined for all items, or items are inserted + * in the view, or the visible items might have changed because items + * were removed or moved, tries to determine the icons for all visible + * items synchronously for 200 ms. Then: + * + * (a) If previews are disabled, icons and all other roles are determined + * asynchronously for the interesting items. This is done by the + * function \a resolveNextPendingRoles(). + * + * (b) If previews are enabled, a \a KIO::PreviewJob is started that loads + * the previews for the interesting items. At the same time, the icons + * for these items are determined asynchronously as fast as possible + * by \a resolveNextPendingRoles(). This minimizes the risk that the + * user sees "unknown" icons when scrolling before the previews have + * arrived. + * + * 3. Finally, the entire process is repeated for any items that might have + * changed in the mean time. */ -class LIBDOLPHINPRIVATE_EXPORT KFileItemModelRolesUpdater : public QObject +class DOLPHIN_EXPORT KFileItemModelRolesUpdater : public QObject { Q_OBJECT public: - explicit KFileItemModelRolesUpdater(KFileItemModel* model, QObject* parent = 0); - virtual ~KFileItemModelRolesUpdater(); + explicit KFileItemModelRolesUpdater(KFileItemModel* model, QObject* parent = nullptr); + ~KFileItemModelRolesUpdater() override; void setIconSize(const QSize& size); QSize iconSize() const; @@ -59,13 +105,23 @@ public: */ void setVisibleIndexRange(int index, int count); + void setMaximumVisibleItems(int count); + /** * If \a show is set to true, the "iconPixmap" role will be filled with a preview * of the file. If \a show is false the MIME type icon will be used for the "iconPixmap" * role. */ - void setPreviewShown(bool show); - bool isPreviewShown() const; + void setPreviewsShown(bool show); + bool previewsShown() const; + + /** + * If enabled a small preview gets upscaled to the icon size in case where + * the icon size is larger than the preview. Per default enlarging is + * enabled. + */ + void setEnlargeSmallPreviews(bool enlarge); + bool enlargeSmallPreviews() const; /** * If \a paused is set to true the asynchronous resolving of roles will be paused. @@ -101,8 +157,11 @@ public: private slots: void slotItemsInserted(const KItemRangeList& itemRanges); void slotItemsRemoved(const KItemRangeList& itemRanges); + void slotItemsMoved(const KItemRange& itemRange, const QList &movedToIndexes); void slotItemsChanged(const KItemRangeList& itemRanges, const QSet& roles); + void slotSortRoleChanged(const QByteArray& current, + const QByteArray& previous); /** * Is invoked after a preview has been received successfully. @@ -117,58 +176,113 @@ private slots: void slotPreviewFailed(const KFileItem& item); /** - * Is invoked when the preview job has been finished and - * removes the job from the m_previewJobs list. + * Is invoked when the preview job has been finished. Starts a new preview + * job if there are any interesting items without previews left, or updates + * the changed items otherwise. * * @see startPreviewJob() */ - void slotPreviewJobFinished(KJob* job); + void slotPreviewJobFinished(); - void resolvePendingRoles(); + /** + * Is invoked when one of the KOverlayIconPlugin emit the signal that an overlay has changed + */ + void slotOverlaysChanged(const QUrl& url, const QStringList&); + + /** + * Resolves the sort role of the next item in m_pendingSortRole, applies it + * to the model, and invokes itself if there are any pending items left. If + * that is not the case, \a startUpdating() is called. + */ + void resolveNextSortRole(); + + /** + * Resolves the icon name and (if previews are disabled) all other roles + * for the next interesting item. If there are no pending items left, any + * changed items are updated. + */ void resolveNextPendingRoles(); /** * Resolves items that have not been resolved yet after the change has been * notified by slotItemsChanged(). Is invoked if the m_changedItemsTimer - * exceeds. + * expires. */ - void resolveChangedItems(); + void resolveRecentlyChangedItems(); + + void applyChangedBalooRoles(const QString& file); + void applyChangedBalooRolesForItem(const KFileItem& file); + + void slotDirectoryContentsCountReceived(const QString& path, int count, long size); private: /** - * Updates the roles for the given item ranges. The roles for the currently - * visible items will get updated first. + * Starts the updating of all roles. The visible items are handled first. + */ + void startUpdating(); + + /** + * Loads the icons for the visible items. After 200 ms, the function + * stops determining mime types and only loads preliminary icons. + * This is a compromise that prevents that + * (a) the GUI is blocked for more than 200 ms, and + * (b) "unknown" icons could be shown in the view. */ - void startUpdating(const KItemRangeList& itemRanges); + void updateVisibleIcons(); /** - * Creates previews for the items starting from the first item of the - * given list. + * Creates previews for the items starting from the first item in + * m_pendingPreviewItems. * @see slotGotPreview() * @see slotPreviewFailed() * @see slotPreviewJobFinished() */ - void startPreviewJob(const KFileItemList& items); + void startPreviewJob(); + + /** + * Ensures that icons, previews, and other roles are determined for any + * items that have been changed. + */ + void updateChangedItems(); + + /** + * Resolves the sort role of the item and applies it to the model. + */ + void applySortRole(int index); - bool hasPendingRoles() const; - void resetPendingRoles(); - void triggerPendingRolesResolving(int count); - void sortAndResolveAllRoles(); - void sortAndResolvePendingRoles(); + void applySortProgressToModel(); enum ResolveHint { ResolveFast, ResolveAll }; - bool applyResolvedRoles(const KFileItem& item, ResolveHint hint); - QHash rolesData(const KFileItem& item) const; + bool applyResolvedRoles(int index, ResolveHint hint); + QHash rolesData(const KFileItem& item); + + /** + * @return The number of items of the path \a path. + */ + int subItemsCount(const QString& path) const; + + /** + * Must be invoked if a property has been changed that affects + * the look of the preview. Takes care to update all previews. + */ + void updateAllPreviews(); - KFileItemList sortedItems(const QSet& items) const; + void killPreviewJob(); - int subDirectoriesCount(const QString& path) const; + QList indexesToResolve() const; private: - // Property for setPaused()/isPaused(). - bool m_paused; + enum State { + Idle, + Paused, + ResolvingSortRole, + ResolvingAllRoles, + PreviewJobRunning + }; + + State m_state; // Property changes during pausing must be remembered to be able // to react when unpausing again: @@ -176,34 +290,62 @@ private: bool m_iconSizeChangedDuringPausing; bool m_rolesChangedDuringPausing; - // Property for setPreviewShown()/previewShown(). + // Property for setPreviewsShown()/previewsShown(). bool m_previewShown; + // Property for setEnlargeSmallPreviews()/enlargeSmallPreviews() + bool m_enlargeSmallPreviews; + // True if the role "iconPixmap" should be cleared when resolving the next // role with resolveRole(). Is necessary if the preview gets disabled // during the roles-updater has been paused by setPaused(). bool m_clearPreviews; + // Remembers which items have been handled already, to prevent that + // previews and other expensive roles are determined again. + QSet m_finishedItems; + KFileItemModel* m_model; QSize m_iconSize; int m_firstVisibleIndex; int m_lastVisibleIndex; + int m_maximumVisibleItems; QSet m_roles; + QSet m_resolvableRoles; QStringList m_enabledPlugins; - QSet m_pendingVisibleItems; - QSet m_pendingInvisibleItems; - QList m_previewJobs; + // Items for which the sort role still has to be determined. + QSet m_pendingSortRoleItems; + + // Indexes of items which still have to be handled by + // resolveNextPendingRoles(). + QList m_pendingIndexes; - QTimer* m_resolvePendingRolesTimer; + // Items which have been left over from the last call of startPreviewJob(). + // A new preview job will be started from them once the first one finishes. + KFileItemList m_pendingPreviewItems; + + KIO::PreviewJob* m_previewJob; // When downloading or copying large files, the slot slotItemsChanged() // will be called periodically within a quite short delay. To prevent // a high CPU-load by generating e.g. previews for each notification, the update // will be postponed until no file change has been done within a longer period // of time. - QTimer* m_changedItemsTimer; + QTimer* m_recentlyChangedItemsTimer; + QSet m_recentlyChangedItems; + + // Items which have not been changed repeatedly recently. QSet m_changedItems; + + KDirectoryContentsCounter* m_directoryContentsCounter; + + QList m_overlayIconsPlugin; + +#ifdef HAVE_BALOO + Baloo::FileMonitor* m_balooFileMonitor; + Baloo::IndexerConfig m_balooConfig; +#endif }; #endif