File indexing completed on 2024-04-28 17:06:18

0001 /*
0002     SPDX-FileCopyrightText: 2000-2002 Shie Erlich <krusader@users.sourceforge.net>
0003     SPDX-FileCopyrightText: 2000-2002 Rafi Yanai <krusader@users.sourceforge.net>
0004     SPDX-FileCopyrightText: 2004-2022 Krusader Krew <https://krusader.org>
0005 
0006     SPDX-License-Identifier: GPL-2.0-or-later
0007 */
0008 
0009 #ifndef KRVIEW_H
0010 #define KRVIEW_H
0011 
0012 // QtCore
0013 #include <QHash>
0014 #include <QList>
0015 #include <QModelIndex>
0016 #include <QRegExp>
0017 #include <QTimer>
0018 #include <QVariant>
0019 // QtGui
0020 #include <QDropEvent>
0021 #include <QPixmap>
0022 #include <utility>
0023 
0024 #include "krviewproperties.h"
0025 
0026 class KrView;
0027 class KrViewItem;
0028 class KrPreviews;
0029 class KrViewInstance;
0030 class DirListerInterface;
0031 
0032 typedef QList<KrViewItem *> KrViewItemList;
0033 
0034 // operator can handle two ways of doing things:
0035 // 1. if the view is a widget (inherits krview and klistview for example)
0036 // 2. if the view HAS A widget (a krview-son has a member of klistview)
0037 // this is done by specifying the view and the widget in the constructor,
0038 // even if they are actually the same object (specify it twice in that case)
0039 class KrViewOperator : public QObject
0040 {
0041     Q_OBJECT
0042 public:
0043     KrViewOperator(KrView *view, QWidget *widget);
0044     ~KrViewOperator() override;
0045 
0046     KrView *view() const
0047     {
0048         return _view;
0049     }
0050     QWidget *widget() const
0051     {
0052         return _widget;
0053     }
0054     void startDrag();
0055 
0056     void emitGotDrop(QDropEvent *e)
0057     {
0058         emit gotDrop(e);
0059     }
0060     void emitLetsDrag(QStringList items, const QPixmap &icon)
0061     {
0062         emit letsDrag(std::move(items), icon);
0063     }
0064     void emitItemDescription(const QString &desc)
0065     {
0066         emit itemDescription(desc);
0067     }
0068     void emitContextMenu(const QPoint &point)
0069     {
0070         emit contextMenu(point);
0071     }
0072     void emitEmptyContextMenu(const QPoint &point)
0073     {
0074         emit emptyContextMenu(point);
0075     }
0076     void emitRenameItem(const QString &oldName, const QString &newName)
0077     {
0078         emit renameItem(oldName, newName);
0079     }
0080     void emitExecuted(const QString &name)
0081     {
0082         emit executed(name);
0083     }
0084     void emitGoInside(const QString &name)
0085     {
0086         emit goInside(name);
0087     }
0088     void emitNeedFocus()
0089     {
0090         emit needFocus();
0091     }
0092     void emitMiddleButtonClicked(KrViewItem *item)
0093     {
0094         emit middleButtonClicked(item);
0095     }
0096     void emitCurrentChanged(KrViewItem *item)
0097     {
0098         emit currentChanged(item);
0099     }
0100     void emitPreviewJobStarted(KJob *job)
0101     {
0102         emit previewJobStarted(job);
0103     }
0104     void emitGoHome()
0105     {
0106         emit goHome();
0107     }
0108     void emitDirUp()
0109     {
0110         emit dirUp();
0111     }
0112     void emitQuickCalcSpace(KrViewItem *item)
0113     {
0114         emit quickCalcSpace(item);
0115     }
0116     void emitDefaultDeleteFiles()
0117     {
0118         emit defaultDeleteFiles();
0119     }
0120     void emitRefreshActions()
0121     {
0122         emit refreshActions();
0123     }
0124     void emitGoBack()
0125     {
0126         emit goBack();
0127     }
0128     void emitGoForward()
0129     {
0130         emit goForward();
0131     }
0132 
0133     /**
0134      * Search for an item by file name beginning at the current cursor position and set the
0135      * cursor to it.
0136      *
0137      * @param text file name to search for, can be regex
0138      * @param caseSensitive whether the search is case sensitive
0139      * @param direction @c 0 is for forward, @c 1 is for backward
0140      * @return true if there is a next/previous item matching the text, else false
0141      */
0142     bool searchItem(const QString &text, bool caseSensitive, int direction = 0);
0143     /**
0144      * Filter view items.
0145      */
0146     bool filterSearch(const QString &, bool);
0147     void setMassSelectionUpdate(bool upd);
0148     bool isMassSelectionUpdate()
0149     {
0150         return _massSelectionUpdate;
0151     }
0152     void settingsChanged(KrViewProperties::PropertyType properties);
0153 
0154 public slots:
0155     void emitSelectionChanged()
0156     {
0157         if (!_massSelectionUpdate)
0158             emit selectionChanged();
0159     }
0160 
0161     void startUpdate();
0162     void cleared();
0163     void fileAdded(FileItem *fileitem);
0164     void fileUpdated(FileItem *newFileitem);
0165 
0166 signals:
0167     void selectionChanged();
0168     void gotDrop(QDropEvent *e);
0169     void letsDrag(QStringList items, QPixmap icon);
0170     void itemDescription(const QString &desc);
0171     void contextMenu(const QPoint &point);
0172     void emptyContextMenu(const QPoint &point);
0173     void renameItem(const QString &oldName, const QString &newName);
0174     void executed(const QString &name);
0175     void goInside(const QString &name);
0176     void needFocus();
0177     void middleButtonClicked(KrViewItem *item);
0178     void currentChanged(KrViewItem *item);
0179     void previewJobStarted(KJob *job);
0180     void goHome();
0181     void defaultDeleteFiles();
0182     void dirUp();
0183     void quickCalcSpace(KrViewItem *item);
0184     void refreshActions();
0185     void goBack();
0186     void goForward();
0187 
0188 protected slots:
0189     void saveDefaultSettings();
0190 
0191 protected:
0192     // never delete those
0193     KrView *_view;
0194     QWidget *_widget;
0195 
0196 private:
0197     bool _massSelectionUpdate;
0198     QTimer _saveDefaultSettingsTimer;
0199     static KrViewProperties::PropertyType _changedProperties;
0200     static KrView *_changedView;
0201 };
0202 
0203 /****************************************************************************
0204  * READ THIS FIRST: Using the view
0205  *
0206  * You always hold a pointer to KrView, thus you can only use functions declared
0207  * in this class. If you need something else, either this class is missing something
0208  * or you are ;-)
0209  *
0210  * The functions you'd usually want:
0211  * 1) getSelectedItems - returns all selected items, or (if none) the current item.
0212  *    it never returns anything which includes the "..", and thus can return an empty list!
0213  * 2) getSelectedKrViewItems - the same as (1), but returns a QValueList with KrViewItems
0214  * 3) getCurrentItem, setCurrentItem - work with QString
0215  * 4) getFirst, getNext, getPrev, getCurrentKrViewItem - all work with KrViewItems, and
0216  *    used to iterate through a list of items. note that getNext and getPrev accept a pointer
0217  *    to the current item (used in detailedview for safe iterating), thus your loop should be:
0218  *       for (KrViewItem *it = view->getFirst(); it!=0; it = view->getNext(it)) { blah; }
0219  * 5) nameToMakeCurrent(), setNameToMakeCurrent() - work with QString
0220  *
0221  * IMPORTANT NOTE: every one who subclasses this must call initProperties() in the constructor !!!
0222  */
0223 class KrView
0224 {
0225     friend class KrViewItem;
0226     friend class KrViewOperator;
0227 
0228 public:
0229     class IconSizes : public QVector<int>
0230     {
0231     public:
0232         IconSizes()
0233         {
0234             *this << 12 << 16 << 22 << 32 << 48 << 64 << 128 << 256;
0235         }
0236     };
0237 
0238     // instantiating a new view
0239     // 1. new KrView
0240     // 2. view->init()
0241     // notes: constructor does as little as possible, setup() does the rest. esp, note that
0242     // if you need something from operator or properties, move it into setup()
0243     void init(bool enableUpdateDefaultSettings = true);
0244     KrViewInstance *instance()
0245     {
0246         return &_instance;
0247     }
0248     static const IconSizes iconSizes;
0249 
0250 protected:
0251     void initProperties();
0252     KrViewOperator *createOperator()
0253     {
0254         return new KrViewOperator(this, _widget);
0255     }
0256     virtual void setup() = 0;
0257 
0258     ///////////////////////////////////////////////////////
0259     // Every view must implement the following functions //
0260     ///////////////////////////////////////////////////////
0261 public:
0262     // interview related functions
0263     virtual QModelIndex getCurrentIndex() = 0;
0264     virtual bool isSelected(const QModelIndex &) = 0;
0265     virtual bool ensureVisibilityAfterSelect() = 0;
0266     virtual void selectRegion(KrViewItem *, KrViewItem *, bool) = 0;
0267 
0268     virtual uint numSelected() const = 0;
0269     virtual QList<QUrl> selectedUrls() = 0;
0270     virtual void setSelectionUrls(const QList<QUrl> urls) = 0;
0271     virtual KrViewItem *getFirst() = 0;
0272     virtual KrViewItem *getLast() = 0;
0273     virtual KrViewItem *getNext(KrViewItem *current) = 0;
0274     virtual KrViewItem *getPrev(KrViewItem *current) = 0;
0275     virtual KrViewItem *getCurrentKrViewItem() = 0;
0276     virtual KrViewItem *getKrViewItemAt(const QPoint &vp) = 0;
0277     virtual KrViewItem *findItemByName(const QString &name) = 0;
0278     virtual KrViewItem *findItemByUrl(const QUrl &url) = 0;
0279     virtual QString getCurrentItem() const = 0;
0280     virtual void setCurrentItem(const QString &name, bool scrollToCurrent = true, const QModelIndex &fallbackToIndex = QModelIndex()) = 0;
0281     virtual void setCurrentKrViewItem(KrViewItem *item, bool scrollToCurrent = true) = 0;
0282     virtual void makeItemVisible(const KrViewItem *item) = 0;
0283     virtual bool isItemVisible(const KrViewItem *item) = 0;
0284     virtual void updateView() = 0;
0285     virtual void sort() = 0;
0286     virtual void refreshColors() = 0;
0287     virtual void redraw() = 0;
0288     virtual bool handleKeyEvent(QKeyEvent *e);
0289     virtual void prepareForActive() = 0;
0290     virtual void prepareForPassive() = 0;
0291     virtual void renameCurrentItem() = 0; // Rename current item. returns immediately
0292     virtual int itemsPerPage() = 0;
0293     virtual void showContextMenu(const QPoint &point = QPoint(0, 0)) = 0;
0294 
0295 protected:
0296     virtual KrViewItem *preAddItem(FileItem *fileitem) = 0;
0297     virtual void preDeleteItem(KrViewItem *item) = 0;
0298     virtual void copySettingsFrom(KrView *other) = 0;
0299     virtual void populate(const QList<FileItem *> &fileItems, FileItem *dummy) = 0;
0300     virtual void intSetSelected(const FileItem *fileitem, bool select) = 0;
0301     virtual void clear();
0302 
0303     void addItem(FileItem *fileItem, bool onUpdate = false);
0304     void deleteItem(const QString &name, bool onUpdate = false);
0305     void updateItem(FileItem *newFileItem);
0306 
0307 public:
0308     //////////////////////////////////////////////////////
0309     // the following functions are already implemented, //
0310     // and normally - should NOT be re-implemented.     //
0311     //////////////////////////////////////////////////////
0312     uint numFiles() const
0313     {
0314         return _count - _numDirs;
0315     }
0316     uint numDirs() const
0317     {
0318         return _numDirs;
0319     }
0320     uint count() const
0321     {
0322         return _count;
0323     }
0324     void getSelectedItems(QStringList *names, bool fallbackToFocused = true);
0325     void getItemsByMask(const QString &mask, QStringList *names, bool dirs = true, bool files = true);
0326     KrViewItemList getSelectedKrViewItems();
0327     void selectAllIncludingDirs()
0328     {
0329         changeSelection(KrQuery("*"), true, true);
0330     }
0331     void select(const KrQuery &filter = KrQuery("*"))
0332     {
0333         changeSelection(filter, true);
0334     }
0335     void unselect(const KrQuery &filter = KrQuery("*"))
0336     {
0337         changeSelection(filter, false);
0338     }
0339     void unselectAll()
0340     {
0341         changeSelection(KrQuery("*"), false, true);
0342     }
0343     void invertSelection();
0344     QString nameToMakeCurrent() const
0345     {
0346         return _nameToMakeCurrent;
0347     }
0348     void setNameToMakeCurrent(const QString &name)
0349     {
0350         _nameToMakeCurrent = name;
0351     }
0352     QString firstUnmarkedBelowCurrent(const bool skipCurrent);
0353     QString statistics();
0354     const KrViewProperties *properties() const
0355     {
0356         return _properties;
0357     }
0358     KrViewOperator *op() const
0359     {
0360         return _operator;
0361     }
0362     void showPreviews(bool show);
0363     bool previewsShown()
0364     {
0365         return _previews != nullptr;
0366     }
0367     void applySettingsToOthers();
0368 
0369     void setFiles(DirListerInterface *files);
0370 
0371     /**
0372      * Refresh the file view items after the underlying file model changed.
0373      *
0374      * Tries to preserve current file and file selection if applicable.
0375      */
0376     void refresh();
0377 
0378     bool changeSelection(const KrQuery &filter, bool select);
0379     bool changeSelection(const KrQuery &filter, bool select, bool includeDirs, bool makeVisible = false);
0380     bool isFiltered(FileItem *fileitem);
0381     void setSelected(const FileItem *fileitem, bool select);
0382 
0383     /////////////////////////////////////////////////////////////
0384     // the following functions have a default and minimalistic //
0385     // implementation, and may be re-implemented if needed     //
0386     /////////////////////////////////////////////////////////////
0387     virtual void setSortMode(KrViewProperties::ColumnType sortColumn, bool descending)
0388     {
0389         sortModeUpdated(sortColumn, descending);
0390     }
0391     const KrQuery &filterMask() const
0392     {
0393         return _properties->filterMask;
0394     }
0395     KrViewProperties::FilterSpec filter() const
0396     {
0397         return _properties->filter;
0398     }
0399     void setFilter(KrViewProperties::FilterSpec filter);
0400     void setFilter(KrViewProperties::FilterSpec filter, const FilterSettings &customFilter, bool applyToDirs);
0401     void customSelection(bool select);
0402     int defaultFileIconSize();
0403     virtual void setFileIconSize(int size);
0404     void setDefaultFileIconSize()
0405     {
0406         setFileIconSize(defaultFileIconSize());
0407     }
0408     void zoomIn();
0409     void zoomOut();
0410 
0411     // save this view's settings to be restored after restart
0412     virtual void saveSettings(KConfigGroup grp, KrViewProperties::PropertyType properties = KrViewProperties::AllProperties);
0413 
0414     inline QWidget *widget()
0415     {
0416         return _widget;
0417     }
0418     inline int fileIconSize() const
0419     {
0420         return _fileIconSize;
0421     }
0422     inline bool isFocused() const
0423     {
0424         return _focused;
0425     }
0426 
0427     QPixmap getIcon(FileItem *fileitem);
0428 
0429     void setMainWindow(QWidget *mainWindow)
0430     {
0431         _mainWindow = mainWindow;
0432     }
0433 
0434     // save this view's settings as default for new views of this type
0435     void saveDefaultSettings(KrViewProperties::PropertyType properties = KrViewProperties::AllProperties);
0436     // restore the default settings for this view type
0437     void restoreDefaultSettings();
0438     // call this to restore this view's settings after restart
0439     void restoreSettings(const KConfigGroup &grp);
0440 
0441     void saveSelection();
0442     void restoreSelection();
0443     bool canRestoreSelection()
0444     {
0445         return !_savedSelection.isEmpty();
0446     }
0447     void clearSavedSelection();
0448 
0449     void markSameBaseName();
0450     void markSameExtension();
0451 
0452     // todo: what about selection modes ???
0453     virtual ~KrView();
0454 
0455     static QPixmap getIcon(FileItem *fileitem, bool active, int size = 0);
0456     static QPixmap processIcon(const QPixmap &icon, bool dim, const QColor &dimColor, int dimFactor, bool symlink);
0457 
0458     // Get GUI strings for file item properties
0459     static QString krPermissionText(const FileItem *fileitem);
0460     static QString permissionsText(const KrViewProperties *properties, const FileItem *fileItem);
0461     static QString sizeText(const KrViewProperties *properties, KIO::filesize_t size);
0462     static QString mimeTypeText(FileItem *fileItem);
0463 
0464 protected:
0465     KrView(KrViewInstance &instance, KConfig *cfg);
0466 
0467     virtual void doRestoreSettings(KConfigGroup grp);
0468     virtual KIO::filesize_t calcSize() = 0;
0469     virtual KIO::filesize_t calcSelectedSize() = 0;
0470     void sortModeUpdated(KrViewProperties::ColumnType sortColumn, bool descending);
0471     inline void setWidget(QWidget *w)
0472     {
0473         _widget = w;
0474     }
0475     bool drawCurrent() const;
0476 
0477     KConfig *_config;
0478     KrViewProperties *_properties;
0479     KrViewOperator *_operator;
0480     bool _focused;
0481     int _fileIconSize;
0482 
0483 private:
0484     void updatePreviews();
0485     void saveSortMode(KConfigGroup &group);
0486     void restoreSortMode(KConfigGroup &group);
0487 
0488     KrViewInstance &_instance;
0489     DirListerInterface *_files;
0490     QWidget *_mainWindow;
0491     QWidget *_widget;
0492     QList<QUrl> _savedSelection;
0493     QString _nameToMakeCurrent;
0494     KrPreviews *_previews;
0495     bool _updateDefaultSettings;
0496     bool _ignoreSettingsChange;
0497     QRegExp _quickFilterMask;
0498     uint _count, _numDirs;
0499     FileItem *_dummyFileItem;
0500 };
0501 
0502 #endif /* KRVIEW_H */