1 /*****************************************************************************
2  * Copyright (C) 2000-2002 Shie Erlich <krusader@users.sourceforge.net>      *
3  * Copyright (C) 2000-2002 Rafi Yanai <krusader@users.sourceforge.net>       *
4  * Copyright (C) 2004-2019 Krusader Krew [https://krusader.org]              *
5  *                                                                           *
6  * This file is part of Krusader [https://krusader.org].                     *
7  *                                                                           *
8  * Krusader is free software: you can redistribute it and/or modify          *
9  * it under the terms of the GNU General Public License as published by      *
10  * the Free Software Foundation, either version 2 of the License, or         *
11  * (at your option) any later version.                                       *
12  *                                                                           *
13  * Krusader is distributed in the hope that it will be useful,               *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
16  * GNU General Public License for more details.                              *
17  *                                                                           *
18  * You should have received a copy of the GNU General Public License         *
19  * along with Krusader.  If not, see [http://www.gnu.org/licenses/].         *
20  *****************************************************************************/
21 
22 #ifndef KRVIEW_H
23 #define KRVIEW_H
24 
25 // QtCore
26 #include <QHash>
27 #include <QList>
28 #include <QModelIndex>
29 #include <QRegExp>
30 #include <QTimer>
31 #include <QVariant>
32 // QtGui
33 #include <QDropEvent>
34 #include <QPixmap>
35 
36 #include "krviewproperties.h"
37 
38 class KrView;
39 class KrViewItem;
40 class KrPreviews;
41 class KrViewInstance;
42 class DirListerInterface;
43 
44 typedef QList<KrViewItem *> KrViewItemList;
45 
46 // operator can handle two ways of doing things:
47 // 1. if the view is a widget (inherits krview and klistview for example)
48 // 2. if the view HAS A widget (a krview-son has a member of klistview)
49 // this is done by specifying the view and the widget in the constructor,
50 // even if they are actually the same object (specify it twice in that case)
51 class KrViewOperator : public QObject
52 {
53     Q_OBJECT
54 public:
55     KrViewOperator(KrView *view, QWidget *widget);
56     ~KrViewOperator();
57 
view()58     KrView *view() const { return _view; }
widget()59     QWidget *widget() const { return _widget; }
60     void startDrag();
61 
emitGotDrop(QDropEvent * e)62     void emitGotDrop(QDropEvent *e) { emit gotDrop(e); }
emitLetsDrag(QStringList items,QPixmap icon)63     void emitLetsDrag(QStringList items, QPixmap icon) { emit letsDrag(items, icon); }
emitItemDescription(const QString & desc)64     void emitItemDescription(const QString &desc) { emit itemDescription(desc); }
emitContextMenu(const QPoint & point)65     void emitContextMenu(const QPoint &point) { emit contextMenu(point); }
emitEmptyContextMenu(const QPoint & point)66     void emitEmptyContextMenu(const QPoint &point) { emit emptyContextMenu(point); }
emitRenameItem(const QString & oldName,const QString & newName)67     void emitRenameItem(const QString &oldName, const QString &newName) {
68         emit renameItem(oldName, newName);
69     }
emitExecuted(const QString & name)70     void emitExecuted(const QString &name) { emit executed(name); }
emitGoInside(const QString & name)71     void emitGoInside(const QString &name) { emit goInside(name); }
emitNeedFocus()72     void emitNeedFocus() { emit needFocus(); }
emitMiddleButtonClicked(KrViewItem * item)73     void emitMiddleButtonClicked(KrViewItem *item) { emit middleButtonClicked(item); }
emitCurrentChanged(KrViewItem * item)74     void emitCurrentChanged(KrViewItem *item) { emit currentChanged(item); }
emitPreviewJobStarted(KJob * job)75     void emitPreviewJobStarted(KJob *job) { emit previewJobStarted(job); }
emitGoHome()76     void emitGoHome() { emit goHome(); }
emitDirUp()77     void emitDirUp() { emit dirUp(); }
emitQuickCalcSpace(KrViewItem * item)78     void emitQuickCalcSpace(KrViewItem *item) { emit quickCalcSpace(item); }
emitDefaultDeleteFiles()79     void emitDefaultDeleteFiles() { emit defaultDeleteFiles(); }
emitRefreshActions()80     void emitRefreshActions() { emit refreshActions(); }
emitGoBack()81     void emitGoBack() { emit goBack(); }
emitGoForward()82     void emitGoForward() { emit goForward(); }
83 
84     /**
85      * Search for an item by file name beginning at the current cursor position and set the
86      * cursor to it.
87      *
88      * @param text file name to search for, can be regex
89      * @return true if there is a next/previous item matching the text, else false
90      */
91     bool searchItem(const QString &text, bool caseSensitive, int direction = 0);
92     /**
93      * Filter view items.
94      */
95     bool filterSearch(const QString &, bool);
96     void setMassSelectionUpdate(bool upd);
isMassSelectionUpdate()97     bool isMassSelectionUpdate() { return _massSelectionUpdate; }
98     void settingsChanged(KrViewProperties::PropertyType properties);
99 
100 public slots:
emitSelectionChanged()101     void emitSelectionChanged() {
102         if (!_massSelectionUpdate)
103             emit selectionChanged();
104     }
105 
106     void startUpdate();
107     void cleared();
108     void fileAdded(FileItem *fileitem);
109     void fileUpdated(FileItem *newFileitem);
110 
111 signals:
112     void selectionChanged();
113     void gotDrop(QDropEvent *e);
114     void letsDrag(QStringList items, QPixmap icon);
115     void itemDescription(const QString &desc);
116     void contextMenu(const QPoint &point);
117     void emptyContextMenu(const QPoint &point);
118     void renameItem(const QString &oldName, const QString &newName);
119     void executed(const QString &name);
120     void goInside(const QString &name);
121     void needFocus();
122     void middleButtonClicked(KrViewItem *item);
123     void currentChanged(KrViewItem *item);
124     void previewJobStarted(KJob *job);
125     void goHome();
126     void defaultDeleteFiles();
127     void dirUp();
128     void quickCalcSpace(KrViewItem *item);
129     void refreshActions();
130     void goBack();
131     void goForward();
132 
133 protected slots:
134     void saveDefaultSettings();
135 
136 protected:
137     // never delete those
138     KrView *_view;
139     QWidget *_widget;
140 
141 private:
142     bool _massSelectionUpdate;
143     QTimer _saveDefaultSettingsTimer;
144     static KrViewProperties::PropertyType _changedProperties;
145     static KrView *_changedView;
146 };
147 
148 /****************************************************************************
149  * READ THIS FIRST: Using the view
150  *
151  * You always hold a pointer to KrView, thus you can only use functions declared
152  * in this class. If you need something else, either this class is missing something
153  * or you are ;-)
154  *
155  * The functions you'd usually want:
156  * 1) getSelectedItems - returns all selected items, or (if none) the current item.
157  *    it never returns anything which includes the "..", and thus can return an empty list!
158  * 2) getSelectedKrViewItems - the same as (1), but returns a QValueList with KrViewItems
159  * 3) getCurrentItem, setCurrentItem - work with QString
160  * 4) getFirst, getNext, getPrev, getCurrentKrViewItem - all work with KrViewItems, and
161  *    used to iterate through a list of items. note that getNext and getPrev accept a pointer
162  *    to the current item (used in detailedview for safe iterating), thus your loop should be:
163  *       for (KrViewItem *it = view->getFirst(); it!=0; it = view->getNext(it)) { blah; }
164  * 5) nameToMakeCurrent(), setNameToMakeCurrent() - work with QString
165  *
166  * IMPORTANT NOTE: every one who subclasses this must call initProperties() in the constructor !!!
167  */
168 class KrView
169 {
170     friend class KrViewItem;
171     friend class KrViewOperator;
172 
173 public:
174     class IconSizes : public QVector<int>
175     {
176       public:
IconSizes()177         IconSizes() : QVector<int>() { *this << 12 << 16 << 22 << 32 << 48 << 64 << 128 << 256; }
178     };
179 
180     // instantiating a new view
181     // 1. new KrView
182     // 2. view->init()
183     // notes: constructor does as little as possible, setup() does the rest. esp, note that
184     // if you need something from operator or properties, move it into setup()
185     void init(bool enableUpdateDefaultSettings = true);
instance()186     KrViewInstance *instance() { return &_instance; }
187     static const IconSizes iconSizes;
188 
189 protected:
190     void initProperties();
createOperator()191     KrViewOperator *createOperator() { return new KrViewOperator(this, _widget); }
192     virtual void setup() = 0;
193 
194     ///////////////////////////////////////////////////////
195     // Every view must implement the following functions //
196     ///////////////////////////////////////////////////////
197 public:
198     // interview related functions
199     virtual QModelIndex getCurrentIndex() = 0;
200     virtual bool isSelected(const QModelIndex &) = 0;
201     virtual bool ensureVisibilityAfterSelect() = 0;
202     virtual void selectRegion(KrViewItem *, KrViewItem *, bool) = 0;
203 
204     virtual uint numSelected() const = 0;
205     virtual QList<QUrl> selectedUrls() = 0;
206     virtual void setSelectionUrls(const QList<QUrl> urls) = 0;
207     virtual KrViewItem *getFirst() = 0;
208     virtual KrViewItem *getLast() = 0;
209     virtual KrViewItem *getNext(KrViewItem *current) = 0;
210     virtual KrViewItem *getPrev(KrViewItem *current) = 0;
211     virtual KrViewItem *getCurrentKrViewItem() = 0;
212     virtual KrViewItem *getKrViewItemAt(const QPoint &vp) = 0;
213     virtual KrViewItem *findItemByName(const QString &name) = 0;
214     virtual KrViewItem *findItemByUrl(const QUrl &url) = 0;
215     virtual QString getCurrentItem() const = 0;
216     virtual void setCurrentItem(const QString &name, bool scrollToCurrent = true,
217                                 const QModelIndex &fallbackToIndex = QModelIndex()) = 0;
218     virtual void setCurrentKrViewItem(KrViewItem *item, bool scrollToCurrent = true) = 0;
219     virtual void makeItemVisible(const KrViewItem *item) = 0;
220     virtual bool isItemVisible(const KrViewItem *item) = 0;
221     virtual void updateView() = 0;
222     virtual void sort() = 0;
223     virtual void refreshColors() = 0;
224     virtual void redraw() = 0;
225     virtual bool handleKeyEvent(QKeyEvent *e);
226     virtual void prepareForActive() = 0;
227     virtual void prepareForPassive() = 0;
228     virtual void renameCurrentItem() = 0; // Rename current item. returns immediately
229     virtual int itemsPerPage() = 0;
230     virtual void showContextMenu(const QPoint &point = QPoint(0, 0)) = 0;
231 
232 protected:
233     virtual KrViewItem *preAddItem(FileItem *fileitem) = 0;
234     virtual void preDeleteItem(KrViewItem *item) = 0;
235     virtual void copySettingsFrom(KrView *other) = 0;
236     virtual void populate(const QList<FileItem *> &fileItems, FileItem *dummy) = 0;
237     virtual void intSetSelected(const FileItem *fileitem, bool select) = 0;
238     virtual void clear();
239 
240 
241     void addItem(FileItem *fileItem, bool onUpdate = false);
242     void deleteItem(const QString &name, bool onUpdate = false);
243     void updateItem(FileItem *newFileItem);
244 
245 public:
246     //////////////////////////////////////////////////////
247     // the following functions are already implemented, //
248     // and normally - should NOT be re-implemented.     //
249     //////////////////////////////////////////////////////
numFiles()250     uint numFiles() const { return _count - _numDirs; }
numDirs()251     uint numDirs() const { return _numDirs; }
count()252     uint count() const { return _count; }
253     void getSelectedItems(QStringList *names, bool fallbackToFocused = true);
254     void getItemsByMask(QString mask, QStringList *names, bool dirs = true, bool files = true);
255     KrViewItemList getSelectedKrViewItems();
selectAllIncludingDirs()256     void selectAllIncludingDirs() { changeSelection(KRQuery("*"), true, true); }
257     void select(const KRQuery &filter = KRQuery("*")) { changeSelection(filter, true); }
258     void unselect(const KRQuery &filter = KRQuery("*")) { changeSelection(filter, false); }
unselectAll()259     void unselectAll() { changeSelection(KRQuery("*"), false, true); }
260     void invertSelection();
nameToMakeCurrent()261     QString nameToMakeCurrent() const { return _nameToMakeCurrent; }
setNameToMakeCurrent(const QString name)262     void setNameToMakeCurrent(const QString name) { _nameToMakeCurrent = name; }
263     QString firstUnmarkedBelowCurrent(const bool skipCurrent);
264     QString statistics();
properties()265     const KrViewProperties *properties() const { return _properties; }
op()266     KrViewOperator *op() const { return _operator; }
267     void showPreviews(bool show);
previewsShown()268     bool previewsShown() { return _previews != 0; }
269     void applySettingsToOthers();
270 
271     void setFiles(DirListerInterface *files);
272 
273     /**
274      * Refresh the file view items after the underlying file model changed.
275      *
276      * Tries to preserve current file and file selection if applicable.
277      */
278     void refresh();
279 
280     bool changeSelection(const KRQuery &filter, bool select);
281     bool changeSelection(const KRQuery &filter, bool select, bool includeDirs,
282                          bool makeVisible = false);
283     bool isFiltered(FileItem *fileitem);
284     void setSelected(const FileItem *fileitem, bool select);
285 
286     /////////////////////////////////////////////////////////////
287     // the following functions have a default and minimalistic //
288     // implementation, and may be re-implemented if needed     //
289     /////////////////////////////////////////////////////////////
setSortMode(KrViewProperties::ColumnType sortColumn,bool descending)290     virtual void setSortMode(KrViewProperties::ColumnType sortColumn, bool descending) {
291         sortModeUpdated(sortColumn, descending);
292     }
filterMask()293     const KRQuery &filterMask() const { return _properties->filterMask; }
filter()294     KrViewProperties::FilterSpec filter() const { return _properties->filter; }
295     void setFilter(KrViewProperties::FilterSpec filter);
296     void setFilter(KrViewProperties::FilterSpec filter, FilterSettings customFilter,
297                    bool applyToDirs);
298     void customSelection(bool select);
299     int defaultFileIconSize();
300     virtual void setFileIconSize(int size);
setDefaultFileIconSize()301     void setDefaultFileIconSize() { setFileIconSize(defaultFileIconSize()); }
302     void zoomIn();
303     void zoomOut();
304 
305     // save this view's settings to be restored after restart
306     virtual void
307     saveSettings(KConfigGroup grp,
308                  KrViewProperties::PropertyType properties = KrViewProperties::AllProperties);
309 
widget()310     inline QWidget *widget() { return _widget; }
fileIconSize()311     inline int fileIconSize() const { return _fileIconSize; }
isFocused()312     inline bool isFocused() const { return _focused; }
313 
314     QPixmap getIcon(FileItem *fileitem);
315 
setMainWindow(QWidget * mainWindow)316     void setMainWindow(QWidget *mainWindow) { _mainWindow = mainWindow; }
317 
318     // save this view's settings as default for new views of this type
319     void saveDefaultSettings(
320         KrViewProperties::PropertyType properties = KrViewProperties::AllProperties);
321     // restore the default settings for this view type
322     void restoreDefaultSettings();
323     // call this to restore this view's settings after restart
324     void restoreSettings(KConfigGroup grp);
325 
326     void saveSelection();
327     void restoreSelection();
canRestoreSelection()328     bool canRestoreSelection() { return !_savedSelection.isEmpty(); }
329     void clearSavedSelection();
330 
331     void markSameBaseName();
332     void markSameExtension();
333 
334     // todo: what about selection modes ???
335     virtual ~KrView();
336 
337     static QPixmap getIcon(FileItem *fileitem, bool active, int size = 0);
338     static QPixmap processIcon(const QPixmap &icon, bool dim, const QColor &dimColor, int dimFactor,
339                                bool symlink);
340 
341     // Get GUI strings for file item properties
342     static QString krPermissionText(const FileItem *fileitem);
343     static QString permissionsText(const KrViewProperties *properties, const FileItem *fileItem);
344     static QString sizeText(const KrViewProperties *properties, KIO::filesize_t size);
345     static QString mimeTypeText(FileItem *fileItem);
346 
347 protected:
348     KrView(KrViewInstance &instance, KConfig *cfg);
349 
350     virtual void doRestoreSettings(KConfigGroup grp);
351     virtual KIO::filesize_t calcSize() = 0;
352     virtual KIO::filesize_t calcSelectedSize() = 0;
353     void sortModeUpdated(KrViewProperties::ColumnType sortColumn, bool descending);
setWidget(QWidget * w)354     inline void setWidget(QWidget *w) { _widget = w; }
355     bool drawCurrent() const;
356 
357     KConfig *_config;
358     KrViewProperties *_properties;
359     KrViewOperator *_operator;
360     bool _focused;
361     int _fileIconSize;
362 
363 private:
364     void updatePreviews();
365     void saveSortMode(KConfigGroup &group);
366     void restoreSortMode(KConfigGroup &group);
367 
368     KrViewInstance &_instance;
369     DirListerInterface *_files;
370     QWidget *_mainWindow;
371     QWidget *_widget;
372     QList<QUrl> _savedSelection;
373     QString _nameToMakeCurrent;
374     KrPreviews *_previews;
375     bool _updateDefaultSettings;
376     bool _ignoreSettingsChange;
377     QRegExp _quickFilterMask;
378     uint _count, _numDirs;
379     FileItem *_dummyFileItem;
380 };
381 
382 #endif /* KRVIEW_H */
383