1 /* 2 SPDX-FileCopyrightText: 2008 Fredrik Höglund <fredrik@kde.org> 3 SPDX-FileCopyrightText: 2011 Marco Martin <mart@kde.org> 4 SPDX-FileCopyrightText: 2014 Eike Hein <hein@kde.org> 5 6 SPDX-License-Identifier: GPL-2.0-or-later 7 */ 8 9 #ifndef FOLDERMODEL_H 10 #define FOLDERMODEL_H 11 12 #include <QImage> 13 #include <QItemSelection> 14 #include <QPointer> 15 #include <QQmlParserStatus> 16 #include <QRegExp> 17 #include <QSet> 18 #include <QSortFilterProxyModel> 19 #include <QStringList> 20 21 #include <KAbstractViewAdapter> 22 #include <KActionCollection> 23 #include <KDirLister> 24 #include <KFilePreviewGenerator> 25 26 #include <KNewFileMenu> 27 28 #include "folderplugin_private_export.h" 29 30 class QDrag; 31 class QItemSelectionModel; 32 class QQuickItem; 33 34 class KFileCopyToMenu; 35 class KActionCollection; 36 class KDirModel; 37 class KDirWatch; 38 class KFileItem; 39 class KFileItemActions; 40 class KJob; 41 class KNewFileMenu; 42 43 namespace KIO 44 { 45 class DropJob; 46 class StatJob; 47 } 48 49 class ScreenMapper; 50 51 class DirLister : public KDirLister 52 { 53 Q_OBJECT 54 55 public: 56 explicit DirLister(QObject *parent = nullptr); 57 ~DirLister() override; 58 59 Q_SIGNALS: 60 void error(const QString &string); 61 62 protected: 63 void handleError(KIO::Job *job) override; 64 }; 65 66 class FOLDERPLUGIN_TESTS_EXPORT FolderModel : public QSortFilterProxyModel, public QQmlParserStatus 67 { 68 Q_OBJECT 69 Q_INTERFACES(QQmlParserStatus) 70 71 Q_PROPERTY(QString url READ url WRITE setUrl NOTIFY urlChanged) 72 Q_PROPERTY(QString iconName READ iconName NOTIFY iconNameChanged) 73 Q_PROPERTY(QUrl resolvedUrl READ resolvedUrl NOTIFY resolvedUrlChanged) 74 Q_PROPERTY(Status status READ status NOTIFY statusChanged) 75 Q_PROPERTY(QString errorString READ errorString NOTIFY errorStringChanged) 76 Q_PROPERTY(bool dragging READ dragging NOTIFY draggingChanged) 77 Q_PROPERTY(bool usedByContainment READ usedByContainment WRITE setUsedByContainment NOTIFY usedByContainmentChanged) 78 Q_PROPERTY(bool locked READ locked WRITE setLocked NOTIFY lockedChanged) 79 Q_PROPERTY(int sortMode READ sortMode WRITE setSortMode NOTIFY sortModeChanged) 80 Q_PROPERTY(bool sortDesc READ sortDesc WRITE setSortDesc NOTIFY sortDescChanged) 81 Q_PROPERTY(bool sortDirsFirst READ sortDirsFirst WRITE setSortDirsFirst NOTIFY sortDirsFirstChanged) 82 Q_PROPERTY(bool parseDesktopFiles READ parseDesktopFiles WRITE setParseDesktopFiles NOTIFY parseDesktopFilesChanged) 83 Q_PROPERTY(QObject *viewAdapter READ viewAdapter WRITE setViewAdapter NOTIFY viewAdapterChanged) 84 Q_PROPERTY(bool previews READ previews WRITE setPreviews NOTIFY previewsChanged) 85 Q_PROPERTY(QStringList previewPlugins READ previewPlugins WRITE setPreviewPlugins NOTIFY previewPluginsChanged) 86 Q_PROPERTY(int filterMode READ filterMode WRITE setFilterMode NOTIFY filterModeChanged) 87 Q_PROPERTY(QString filterPattern READ filterPattern WRITE setFilterPattern NOTIFY filterPatternChanged) 88 Q_PROPERTY(QStringList filterMimeTypes READ filterMimeTypes WRITE setFilterMimeTypes NOTIFY filterMimeTypesChanged) 89 Q_PROPERTY(QObject *newMenu READ newMenu CONSTANT) 90 Q_PROPERTY(QObject *appletInterface READ appletInterface WRITE setAppletInterface NOTIFY appletInterfaceChanged) 91 92 public: 93 enum DataRole { 94 BlankRole = Qt::UserRole + 1, 95 SelectedRole, 96 IsDirRole, 97 IsLinkRole, 98 IsHiddenRole, 99 UrlRole, 100 LinkDestinationUrl, 101 SizeRole, 102 TypeRole, 103 FileNameRole, 104 FileNameWrappedRole, 105 }; 106 107 enum FilterMode { 108 NoFilter = 0, 109 FilterShowMatches, 110 FilterHideMatches, 111 }; 112 113 enum Status { 114 None, 115 Ready, 116 Listing, 117 Canceled, 118 }; 119 Q_ENUM(Status) 120 121 explicit FolderModel(QObject *parent = nullptr); 122 ~FolderModel() override; 123 124 QHash<int, QByteArray> roleNames() const override; 125 static QHash<int, QByteArray> staticRoleNames(); 126 127 void classBegin() override; 128 void componentComplete() override; 129 130 QString url() const; 131 void setUrl(const QString &url); 132 133 QString iconName() const; 134 135 QUrl resolvedUrl() const; 136 Q_INVOKABLE QUrl resolve(const QString &url); 137 138 Status status() const; 139 140 QString errorString() const; 141 142 bool dragging() const; 143 144 bool usedByContainment() const; 145 void setUsedByContainment(bool used); 146 147 bool locked() const; 148 void setLocked(bool locked); 149 150 int sortMode() const; 151 void setSortMode(int mode); 152 153 bool sortDesc() const; 154 void setSortDesc(bool desc); 155 156 bool sortDirsFirst() const; 157 void setSortDirsFirst(bool enable); 158 159 bool parseDesktopFiles() const; 160 void setParseDesktopFiles(bool enable); 161 162 QObject *viewAdapter() const; 163 void setViewAdapter(QObject *adapter); 164 165 bool previews() const; 166 void setPreviews(bool previews); 167 168 QStringList previewPlugins() const; 169 void setPreviewPlugins(const QStringList &previewPlugins); 170 171 int filterMode() const; 172 void setFilterMode(int filterMode); 173 174 QString filterPattern() const; 175 void setFilterPattern(const QString &pattern); 176 177 QStringList filterMimeTypes() const; 178 void setFilterMimeTypes(const QStringList &mimeList); 179 180 QObject *appletInterface() const; 181 void setAppletInterface(QObject *appletInterface); 182 183 KFileItem rootItem() const; 184 185 Q_INVOKABLE void up(); 186 Q_INVOKABLE void cd(int row); 187 188 Q_INVOKABLE void run(int row); 189 Q_INVOKABLE void runSelected(); 190 191 Q_INVOKABLE void rename(int row, const QString &name); 192 Q_INVOKABLE int fileExtensionBoundary(int row); 193 194 Q_INVOKABLE bool hasSelection() const; 195 Q_INVOKABLE bool isSelected(int row); 196 Q_INVOKABLE void setSelected(int row); 197 Q_INVOKABLE void toggleSelected(int row); 198 Q_INVOKABLE void setRangeSelected(int anchor, int to); 199 Q_INVOKABLE void updateSelection(const QVariantList &rows, bool toggle); 200 Q_INVOKABLE void clearSelection(); 201 Q_INVOKABLE void pinSelection(); 202 Q_INVOKABLE void unpinSelection(); 203 204 Q_INVOKABLE void addItemDragImage(int row, int x, int y, int width, int height, const QVariant &image); 205 Q_INVOKABLE void clearDragImages(); 206 Q_INVOKABLE void setDragHotSpotScrollOffset(int x, int y); // FIXME TODO: Propify. 207 Q_INVOKABLE QPoint dragCursorOffset(int row); 208 Q_INVOKABLE void dragSelected(int x, int y); 209 Q_INVOKABLE void drop(QQuickItem *target, QObject *dropEvent, int row, bool showMenuManually = false); 210 Q_INVOKABLE void dropCwd(QObject *dropEvent); 211 212 Q_INVOKABLE bool isBlank(int row) const; 213 214 Q_INVOKABLE QAction *action(const QString &name) const; 215 QObject *newMenu() const; 216 Q_INVOKABLE void updateActions(); 217 Q_INVOKABLE void openContextMenu(QQuickItem *visualParent = nullptr, Qt::KeyboardModifiers modifiers = Qt::NoModifier); 218 219 Q_INVOKABLE void linkHere(const QUrl &sourceUrl); 220 221 Q_INVOKABLE void openPropertiesDialog(); 222 223 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; 224 int indexForUrl(const QUrl &url) const; 225 KFileItem itemForIndex(const QModelIndex &index) const; 226 bool isDir(const QModelIndex &index, const KDirModel *dirModel) const; 227 bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; 228 Qt::DropActions supportedDragActions() const override; 229 Qt::DropActions supportedDropActions() const override; 230 231 Q_INVOKABLE void paste(); 232 Q_INVOKABLE void copy(); 233 Q_INVOKABLE void cut(); 234 Q_INVOKABLE void deleteSelected(); 235 Q_INVOKABLE void openSelected(); 236 Q_INVOKABLE void undo(); 237 Q_INVOKABLE void refresh(); 238 Q_INVOKABLE void createFolder(); 239 240 void setScreen(int screen); 241 242 Q_SIGNALS: 243 void urlChanged() const; 244 void listingCompleted() const; 245 void listingCanceled() const; 246 void iconNameChanged() const; 247 void resolvedUrlChanged() const; 248 void statusChanged() const; 249 void errorStringChanged() const; 250 void draggingChanged() const; 251 void usedByContainmentChanged() const; 252 void lockedChanged() const; 253 void sortModeChanged() const; 254 void sortDescChanged() const; 255 void sortDirsFirstChanged() const; 256 void parseDesktopFilesChanged() const; 257 void viewAdapterChanged(); 258 void previewsChanged() const; 259 void previewPluginsChanged() const; 260 void filterModeChanged() const; 261 void filterPatternChanged() const; 262 void filterMimeTypesChanged() const; 263 void screenChanged() const; 264 void appletInterfaceChanged() const; 265 void requestRename() const; 266 void move(int x, int y, QList<QUrl> urls); 267 void popupMenuAboutToShow(KIO::DropJob *dropJob, QMimeData *mimeData, int x, int y); 268 269 protected: 270 bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; 271 bool matchMimeType(const KFileItem &item) const; 272 bool matchPattern(const KFileItem &item) const; 273 274 private Q_SLOTS: 275 void dragSelectedInternal(int x, int y); 276 void dirListFailed(const QString &error); 277 void statResult(KJob *job); 278 void evictFromIsDirCache(const KFileItemList &items); 279 void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected); 280 void pasteTo(); 281 void moveSelectedToTrash(); 282 void emptyTrashBin(); 283 void restoreSelectedFromTrash(); 284 void undoTextChanged(const QString &text); 285 void invalidateIfComplete(); 286 void invalidateFilterIfComplete(); 287 void newFileMenuItemCreated(const QUrl &url); 288 289 private: 290 struct DragImage { 291 int row; 292 QRect rect; 293 QPoint cursorOffset; 294 QImage image; 295 bool blank; 296 }; 297 298 QPoint localMenuPosition() const; 299 void createActions(); 300 void addDragImage(QDrag *drag, int x, int y); 301 void setStatus(Status status); 302 static bool isTrashEmpty(); 303 static bool isDeleteCommandShown(); 304 QList<QUrl> selectedUrls() const; 305 KDirModel *m_dirModel; 306 KDirWatch *m_dirWatch; 307 QString m_url; 308 mutable QHash<QUrl, bool> m_isDirCache; 309 mutable QHash<QUrl, KIO::StatJob *> m_isDirJobs; 310 QItemSelectionModel *m_selectionModel; 311 QItemSelection m_pinnedSelection; 312 QModelIndexList m_dragIndexes; 313 QHash<int, DragImage *> m_dragImages; 314 QPoint m_dragHotSpotScrollOffset; 315 bool m_dragInProgress; 316 bool m_urlChangedWhileDragging; 317 // target filename to target position of a drop event, note that this deliberately 318 // is not using the URL to easily support desktop:/ URL schemes 319 QHash<QString, QPoint> m_dropTargetPositions; 320 QTimer *m_dropTargetPositionsCleanup; 321 QPointer<KFilePreviewGenerator> m_previewGenerator; 322 QPointer<KAbstractViewAdapter> m_viewAdapter; 323 KActionCollection m_actionCollection; 324 KNewFileMenu *m_newMenu; 325 KFileItemActions *m_fileItemActions; 326 KFileCopyToMenu *m_copyToMenu; 327 Status m_status = Status::None; 328 QString m_errorString; 329 bool m_usedByContainment; 330 bool m_locked; 331 int m_sortMode; // FIXME TODO: Enumify. 332 bool m_sortDesc; 333 bool m_sortDirsFirst; 334 bool m_parseDesktopFiles; 335 bool m_previews; 336 // An empty previewPlugin list means use default. 337 // We don't want to leak that fact to the QML side, however, so the property stays empty 338 // and internally we operate on effectivePreviewPlugins instead. 339 QStringList m_previewPlugins; 340 QStringList m_effectivePreviewPlugins; 341 FilterMode m_filterMode; 342 QString m_filterPattern; 343 bool m_filterPatternMatchAll; 344 QSet<QString> m_mimeSet; 345 QList<QRegExp> m_regExps; 346 int m_screen = -1; 347 bool m_screenUsed; 348 ScreenMapper *m_screenMapper = nullptr; 349 QObject *m_appletInterface = nullptr; 350 bool m_complete; 351 QPoint m_menuPosition; 352 }; 353 354 #endif 355