File indexing completed on 2025-01-26 05:06:21
0001 /* 0002 SPDX-FileCopyrightText: 2008 Fredrik Höglund <fredrik@kde.org> 0003 SPDX-FileCopyrightText: 2011 Marco Martin <mart@kde.org> 0004 SPDX-FileCopyrightText: 2014 Eike Hein <hein@kde.org> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #pragma once 0010 0011 #include <QImage> 0012 #include <QItemSelection> 0013 #include <QPointer> 0014 #include <QQmlParserStatus> 0015 #include <QRegularExpression> 0016 #include <QSet> 0017 #include <QSortFilterProxyModel> 0018 #include <QStringList> 0019 0020 #include <KAbstractViewAdapter> 0021 #include <KActionCollection> 0022 #include <KDirLister> 0023 #include <KFilePreviewGenerator> 0024 0025 #include <KNewFileMenu> 0026 0027 #include <Plasma/Applet> 0028 0029 #include "folderplugin_private_export.h" 0030 0031 class QDrag; 0032 class QItemSelectionModel; 0033 class QQuickItem; 0034 0035 class KFileCopyToMenu; 0036 class KDirModel; 0037 class KDirWatch; 0038 class KFileItem; 0039 class KFileItemActions; 0040 class KJob; 0041 0042 namespace KIO 0043 { 0044 class DropJob; 0045 class StatJob; 0046 } 0047 0048 class ScreenMapper; 0049 0050 class DirLister : public KDirLister 0051 { 0052 Q_OBJECT 0053 0054 public: 0055 explicit DirLister(QObject *parent = nullptr); 0056 ~DirLister() override; 0057 0058 Q_SIGNALS: 0059 void error(const QString &string); 0060 0061 private: 0062 void handleJobError(KIO::Job *job); 0063 }; 0064 0065 class FOLDERPLUGIN_TESTS_EXPORT FolderModel : public QSortFilterProxyModel, public QQmlParserStatus 0066 { 0067 Q_OBJECT 0068 Q_INTERFACES(QQmlParserStatus) 0069 0070 Q_PROPERTY(QString url READ url WRITE setUrl NOTIFY urlChanged) 0071 Q_PROPERTY(QString iconName READ iconName NOTIFY iconNameChanged) 0072 Q_PROPERTY(QUrl resolvedUrl READ resolvedUrl NOTIFY resolvedUrlChanged) 0073 Q_PROPERTY(Status status READ status NOTIFY statusChanged) 0074 Q_PROPERTY(QString errorString READ errorString NOTIFY errorStringChanged) 0075 Q_PROPERTY(bool dragging READ dragging NOTIFY draggingChanged) 0076 Q_PROPERTY(bool dragInProgressAnywhere READ isDragInProgressAnywhere NOTIFY dragInProgressAnywhereChanged) 0077 Q_PROPERTY(bool usedByContainment READ usedByContainment WRITE setUsedByContainment NOTIFY usedByContainmentChanged) 0078 Q_PROPERTY(bool locked READ locked WRITE setLocked NOTIFY lockedChanged) 0079 Q_PROPERTY(int sortMode READ sortMode WRITE setSortMode NOTIFY sortModeChanged) 0080 Q_PROPERTY(bool sortDesc READ sortDesc WRITE setSortDesc NOTIFY sortDescChanged) 0081 Q_PROPERTY(bool sortDirsFirst READ sortDirsFirst WRITE setSortDirsFirst NOTIFY sortDirsFirstChanged) 0082 Q_PROPERTY(bool parseDesktopFiles READ parseDesktopFiles WRITE setParseDesktopFiles NOTIFY parseDesktopFilesChanged) 0083 Q_PROPERTY(QObject *viewAdapter READ viewAdapter WRITE setViewAdapter NOTIFY viewAdapterChanged) 0084 Q_PROPERTY(bool previews READ previews WRITE setPreviews NOTIFY previewsChanged) 0085 Q_PROPERTY(QStringList previewPlugins READ previewPlugins WRITE setPreviewPlugins NOTIFY previewPluginsChanged) 0086 Q_PROPERTY(int filterMode READ filterMode WRITE setFilterMode NOTIFY filterModeChanged) 0087 Q_PROPERTY(QString filterPattern READ filterPattern WRITE setFilterPattern NOTIFY filterPatternChanged) 0088 Q_PROPERTY(QStringList filterMimeTypes READ filterMimeTypes WRITE setFilterMimeTypes NOTIFY filterMimeTypesChanged) 0089 Q_PROPERTY(QObject *newMenu READ newMenu CONSTANT) 0090 Q_PROPERTY(Plasma::Applet *applet READ applet WRITE setApplet NOTIFY appletChanged) 0091 Q_PROPERTY(bool showHiddenFiles READ showHiddenFiles WRITE setShowHiddenFiles NOTIFY showHiddenFilesChanged) 0092 0093 public: 0094 enum DataRole { 0095 BlankRole = Qt::UserRole + 1, 0096 SelectedRole, 0097 IsDirRole, 0098 IsLinkRole, 0099 IsHiddenRole, 0100 UrlRole, 0101 LinkDestinationUrl, 0102 SizeRole, 0103 TypeRole, 0104 FileNameRole, 0105 FileNameWrappedRole, 0106 }; 0107 0108 enum FilterMode { 0109 NoFilter = 0, 0110 FilterShowMatches, 0111 FilterHideMatches, 0112 }; 0113 0114 enum Status { 0115 None, 0116 Ready, 0117 Listing, 0118 Canceled, 0119 }; 0120 Q_ENUM(Status) 0121 0122 explicit FolderModel(QObject *parent = nullptr); 0123 ~FolderModel() override; 0124 0125 QHash<int, QByteArray> roleNames() const override; 0126 static QHash<int, QByteArray> staticRoleNames(); 0127 0128 void classBegin() override; 0129 void componentComplete() override; 0130 0131 QString url() const; 0132 void setUrl(const QString &url); 0133 0134 QString iconName() const; 0135 0136 QUrl resolvedUrl() const; 0137 Q_INVOKABLE QUrl resolve(const QString &url); 0138 0139 Status status() const; 0140 0141 QString errorString() const; 0142 0143 bool dragging() const; 0144 bool isDragInProgressAnywhere() const; 0145 0146 bool usedByContainment() const; 0147 void setUsedByContainment(bool used); 0148 0149 bool locked() const; 0150 void setLocked(bool locked); 0151 0152 int sortMode() const; 0153 void setSortMode(int mode); 0154 0155 bool sortDesc() const; 0156 void setSortDesc(bool desc); 0157 0158 bool sortDirsFirst() const; 0159 void setSortDirsFirst(bool enable); 0160 0161 bool parseDesktopFiles() const; 0162 void setParseDesktopFiles(bool enable); 0163 0164 QObject *viewAdapter() const; 0165 void setViewAdapter(QObject *adapter); 0166 0167 bool previews() const; 0168 void setPreviews(bool previews); 0169 0170 QStringList previewPlugins() const; 0171 void setPreviewPlugins(const QStringList &previewPlugins); 0172 0173 int filterMode() const; 0174 void setFilterMode(int filterMode); 0175 0176 QString filterPattern() const; 0177 void setFilterPattern(const QString &pattern); 0178 0179 QStringList filterMimeTypes() const; 0180 void setFilterMimeTypes(const QStringList &mimeList); 0181 0182 Plasma::Applet *applet() const; 0183 void setApplet(Plasma::Applet *applet); 0184 0185 bool showHiddenFiles() const; 0186 void setShowHiddenFiles(bool enable); 0187 0188 KFileItem rootItem() const; 0189 0190 Q_INVOKABLE void up(); 0191 Q_INVOKABLE void cd(int row); 0192 0193 Q_INVOKABLE void run(int row); 0194 Q_INVOKABLE void runSelected(); 0195 0196 Q_INVOKABLE void rename(int row, const QString &name); 0197 Q_INVOKABLE int fileExtensionBoundary(int row); 0198 0199 Q_INVOKABLE bool hasSelection() const; 0200 Q_INVOKABLE bool isSelected(int row); 0201 Q_INVOKABLE void setSelected(int row); 0202 Q_INVOKABLE void toggleSelected(int row); 0203 Q_INVOKABLE void setRangeSelected(int anchor, int to); 0204 Q_INVOKABLE void updateSelection(const QVariantList &rows, bool toggle); 0205 Q_INVOKABLE void clearSelection(); 0206 Q_INVOKABLE void pinSelection(); 0207 Q_INVOKABLE void unpinSelection(); 0208 0209 Q_INVOKABLE void addItemDragImage(int row, int x, int y, int width, int height, const QVariant &image); 0210 Q_INVOKABLE void clearDragImages(); 0211 Q_INVOKABLE void setDragHotSpotScrollOffset(int x, int y); // FIXME TODO: Propify. 0212 Q_INVOKABLE QPoint dragCursorOffset(int row); 0213 Q_INVOKABLE void dragSelected(int x, int y); 0214 Q_INVOKABLE void drop(QQuickItem *target, QObject *dropEvent, int row, bool showMenuManually = false); 0215 Q_INVOKABLE void dropCwd(QObject *dropEvent); 0216 0217 Q_INVOKABLE bool isBlank(int row) const; 0218 0219 Q_INVOKABLE QAction *action(const QString &name) const; 0220 QObject *newMenu() const; 0221 Q_INVOKABLE void updateActions(); 0222 Q_INVOKABLE void openContextMenu(QQuickItem *visualParent = nullptr, Qt::KeyboardModifiers modifiers = Qt::NoModifier); 0223 0224 Q_INVOKABLE void linkHere(const QUrl &sourceUrl); 0225 0226 Q_INVOKABLE void openPropertiesDialog(); 0227 0228 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; 0229 int indexForUrl(const QUrl &url) const; 0230 KFileItem itemForIndex(const QModelIndex &index) const; 0231 bool isDir(const QModelIndex &index, const KDirModel *dirModel) const; 0232 bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; 0233 Qt::DropActions supportedDragActions() const override; 0234 Qt::DropActions supportedDropActions() const override; 0235 0236 Q_INVOKABLE void paste(); 0237 Q_INVOKABLE void copy(); 0238 Q_INVOKABLE void cut(); 0239 Q_INVOKABLE void deleteSelected(); 0240 Q_INVOKABLE void undo(); 0241 Q_INVOKABLE void refresh(); 0242 Q_INVOKABLE void createFolder(); 0243 0244 void setScreen(int screen); 0245 0246 Q_SIGNALS: 0247 void urlChanged() const; 0248 void listingCompleted() const; 0249 void listingCanceled() const; 0250 void iconNameChanged() const; 0251 void resolvedUrlChanged() const; 0252 void statusChanged() const; 0253 void errorStringChanged() const; 0254 void draggingChanged() const; 0255 void dragInProgressAnywhereChanged() const; 0256 void usedByContainmentChanged() const; 0257 void lockedChanged() const; 0258 void sortModeChanged() const; 0259 void sortDescChanged() const; 0260 void sortDirsFirstChanged() const; 0261 void parseDesktopFilesChanged() const; 0262 void viewAdapterChanged(); 0263 void previewsChanged() const; 0264 void previewPluginsChanged() const; 0265 void filterModeChanged() const; 0266 void filterPatternChanged() const; 0267 void filterMimeTypesChanged() const; 0268 void screenChanged() const; 0269 void appletChanged() const; 0270 void requestRename() const; 0271 void move(int x, int y, QList<QUrl> urls); 0272 void popupMenuAboutToShow(KIO::DropJob *dropJob, QMimeData *mimeData, int x, int y); 0273 void selectionChanged() const; 0274 void showHiddenFilesChanged() const; 0275 0276 protected: 0277 bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; 0278 bool matchMimeType(const KFileItem &item) const; 0279 bool matchPattern(const KFileItem &item) const; 0280 0281 private Q_SLOTS: 0282 void dragSelectedInternal(int x, int y); 0283 void dirListFailed(const QString &error); 0284 void statResult(KJob *job); 0285 void evictFromIsDirCache(const KFileItemList &items); 0286 void changeSelection(const QItemSelection &selected, const QItemSelection &deselected); 0287 void pasteTo(); 0288 void moveSelectedToTrash(); 0289 void emptyTrashBin(); 0290 void restoreSelectedFromTrash(); 0291 void undoTextChanged(const QString &text); 0292 void invalidateIfComplete(); 0293 void invalidateFilterIfComplete(); 0294 void newFileMenuItemCreated(const QUrl &url); 0295 0296 private: 0297 struct DragImage { 0298 int row; 0299 QRect rect; 0300 QPoint cursorOffset; 0301 QImage image; 0302 bool blank; 0303 }; 0304 0305 QPoint localMenuPosition() const; 0306 void createActions(); 0307 void addDragImage(QDrag *drag, int x, int y); 0308 void setStatus(Status status); 0309 static bool isTrashEmpty(); 0310 static bool isDeleteCommandShown(); 0311 QList<QUrl> selectedUrls() const; 0312 KDirModel *m_dirModel; 0313 KDirWatch *m_dirWatch; 0314 QString m_url; 0315 mutable QHash<QUrl, bool> m_isDirCache; 0316 mutable QHash<QUrl, KIO::StatJob *> m_isDirJobs; 0317 QItemSelectionModel *m_selectionModel; 0318 QItemSelection m_pinnedSelection; 0319 QModelIndexList m_dragIndexes; 0320 QHash<int, DragImage *> m_dragImages; 0321 QPoint m_dragHotSpotScrollOffset; 0322 bool m_urlChangedWhileDragging; 0323 // target filename to target position of a drop event, note that this deliberately 0324 // is not using the URL to easily support desktop:/ URL schemes 0325 QHash<QString, QPoint> m_dropTargetPositions; 0326 QTimer *m_dropTargetPositionsCleanup; 0327 QPointer<KFilePreviewGenerator> m_previewGenerator; 0328 QPointer<KAbstractViewAdapter> m_viewAdapter; 0329 KActionCollection m_actionCollection; 0330 KNewFileMenu *m_newMenu; 0331 KFileItemActions *m_fileItemActions; 0332 KFileCopyToMenu *m_copyToMenu; 0333 Status m_status = Status::None; 0334 QString m_errorString; 0335 bool m_usedByContainment; 0336 bool m_locked; 0337 int m_sortMode; // FIXME TODO: Enumify. 0338 bool m_sortDesc; 0339 bool m_sortDirsFirst; 0340 bool m_parseDesktopFiles; 0341 bool m_previews; 0342 // An empty previewPlugin list means use default. 0343 // We don't want to leak that fact to the QML side, however, so the property stays empty 0344 // and internally we operate on effectivePreviewPlugins instead. 0345 QStringList m_previewPlugins; 0346 QStringList m_effectivePreviewPlugins; 0347 FilterMode m_filterMode; 0348 QString m_filterPattern; 0349 bool m_filterPatternMatchAll; 0350 QSet<QString> m_mimeSet; 0351 QList<QRegularExpression> m_regExps; 0352 int m_screen = -1; 0353 bool m_screenUsed; 0354 ScreenMapper *m_screenMapper = nullptr; 0355 Plasma::Applet *m_applet = nullptr; 0356 bool m_complete; 0357 QPoint m_menuPosition; 0358 0359 /** 0360 * This property is used to save the current activity when FolderModel is initialized. 0361 */ 0362 QString m_currentActivity; 0363 bool m_showHiddenFiles; 0364 }; 0365 0366 class DragTracker : public QObject 0367 { 0368 Q_OBJECT 0369 public: 0370 DragTracker(QObject *parent = nullptr); 0371 ~DragTracker(); 0372 0373 bool isDragInProgress() const; 0374 void setDragInProgress(FolderModel *dragOwner, bool drag); 0375 0376 FolderModel *dragOwner(); 0377 0378 static DragTracker *self(); 0379 0380 Q_SIGNALS: 0381 void dragInProgressChanged(bool dragInProgress); 0382 0383 private: 0384 bool m_dragInProgress = false; 0385 QPointer<FolderModel> m_dragOwner; 0386 };