#ifndef DOLPHINVIEW_H
#define DOLPHINVIEW_H
-#include "dolphintabwidget.h"
#include "dolphin_export.h"
+#include "dolphintabwidget.h"
#include "tooltips/tooltipmanager.h"
+#include "config-dolphin.h"
#include <KFileItem>
-#include <KIO/Job>
-#include <config-baloo.h>
+#include <KIO/StatJob>
#include <kio/fileundomanager.h>
#include <kparts/part.h>
#include <QMimeData>
+#include <QPointer>
#include <QUrl>
#include <QWidget>
+#include <memory>
+
typedef KIO::FileUndoManager::CommandType CommandType;
class QVBoxLayout;
class DolphinItemListView;
class ToolTipManager;
class VersionControlObserver;
class ViewProperties;
+class QLabel;
class QGraphicsSceneDragDropEvent;
+class QHelpEvent;
+class QProxyStyle;
class QRegularExpression;
/**
* - show hidden files
* - show previews
* - enable grouping
+ * - grouping order
+ * - grouping type
*/
class DOLPHIN_EXPORT DolphinView : public QWidget
{
* view mode is automatically updated if the directory itself
* defines a view mode (see class ViewProperties for details).
*/
- enum Mode
- {
+ enum Mode {
/**
* The items are shown as icons with a name-label below.
*/
* @param url Specifies the content which should be shown.
* @param parent Parent widget of the view.
*/
- DolphinView(const QUrl& url, QWidget* parent);
+ DolphinView(const QUrl &url, QWidget *parent);
~DolphinView() override;
* (GeneralSettings::globalViewProps() returns false), then the
* changed view mode will be stored automatically.
*/
- void setMode(Mode mode);
- Mode mode() const;
+ void setViewMode(Mode mode);
+ Mode viewMode() const;
+
+ /**
+ * Enables or disables a mode for quick and easy selection of items.
+ */
+ void setSelectionModeEnabled(bool enabled);
+ bool selectionMode() const;
/**
* Turns on the file preview for the all files of the current directory,
* Marks the item indicated by \p url to be scrolled to and as the
* current item after directory DolphinView::url() has been loaded.
*/
- void markUrlAsCurrent(const QUrl& url);
+ void markUrlAsCurrent(const QUrl &url);
/**
* All items that match the regular expression \a regexp will get selected
*/
void resetZoomLevel();
- void setSortRole(const QByteArray& role);
+ /**
+ * Updates the view properties of the current URL to the
+ * sorting given by \a role.
+ */
+ void setSortRole(const QByteArray &role);
QByteArray sortRole() const;
+ /**
+ * Updates the view properties of the current URL to the
+ * sort order given by \a order.
+ */
void setSortOrder(Qt::SortOrder order);
Qt::SortOrder sortOrder() const;
+ /**
+ * Updates the view properties of the current URL to the
+ * grouping given by \a role.
+ */
+ void setGroupRole(const QByteArray &role);
+ QByteArray groupRole() const;
+
+ /**
+ * Updates the view properties of the current URL to the
+ * sort order given by \a order.
+ */
+ void setGroupOrder(Qt::SortOrder order);
+ Qt::SortOrder groupOrder() const;
+
/** Sets a separate sorting with folders first (true) or a mixed sorting of files and folders (false). */
void setSortFoldersFirst(bool foldersFirst);
bool sortFoldersFirst() const;
+ /** Sets a separate sorting with hidden files and folders last (true) or not (false). */
+ void setSortHiddenLast(bool hiddenLast);
+ bool sortHiddenLast() const;
+
/** Sets the additional information which should be shown for the items. */
- void setVisibleRoles(const QList<QByteArray>& roles);
+ void setVisibleRoles(const QList<QByteArray> &roles);
/** Returns the additional information which should be shown for the items. */
QList<QByteArray> visibleRoles() const;
- void reload();
-
/**
* Refreshes the view to get synchronized with the settings (e.g. icons size,
* font, ...).
* Filters the currently shown items by \a nameFilter. All items
* which contain the given filter string will be shown.
*/
- void setNameFilter(const QString& nameFilter);
+ void setNameFilter(const QString &nameFilter);
QString nameFilter() const;
/**
* whose content-type matches those given by the list of filters
* will be shown.
*/
- void setMimeTypeFilters(const QStringList& filters);
+ void setMimeTypeFilters(const QStringList &filters);
QStringList mimeTypeFilters() const;
/**
- * Returns a textual representation of the state of the current
+ * Tells the view to generate an updated status bar text. The result
+ * is returned through the statusBarTextChanged(QString statusBarText) signal.
+ * It will carry a textual representation of the state of the current
* folder or selected items, suitable for use in the status bar.
+ * Any pending requests of status bar text are killed.
*/
- QString statusBarText() const;
+ void requestStatusBarText();
/**
* Returns the version control actions that are provided for the items \p items.
* Usually the actions are presented in the context menu.
*/
- QList<QAction*> versionControlActions(const KFileItemList& items) const;
+ QList<QAction *> versionControlActions(const KFileItemList &items) const;
/**
* Returns the state of the paste action:
*/
bool itemsExpandable() const;
+ /**
+ * @returns true if the @p item is one of the items() of this view and
+ * is currently expanded. false otherwise.
+ * Only directories in view modes that allow expanding can ever be expanded.
+ */
+ bool isExpanded(const KFileItem &item) const;
+
/**
* Restores the view state (current item, contents position, details view expansion state)
*/
- void restoreState(QDataStream& stream);
+ void restoreState(QDataStream &stream);
/**
* Saves the view state (current item, contents position, details view expansion state)
*/
- void saveState(QDataStream& stream);
+ void saveState(QDataStream &stream);
/**
* Returns the root item which represents the current URL.
* makes sense if specific types of URLs (e.g. search-URLs) should
* share common view-properties.
*/
- void setViewPropertiesContext(const QString& context);
+ void setViewPropertiesContext(const QString &context);
QString viewPropertiesContext() const;
/**
* @return a valid and adjusted url if the item can be opened as folder,
* otherwise return an empty url.
*/
- static QUrl openItemAsFolderUrl(const KFileItem& item, const bool browseThroughArchives = true);
+ static QUrl openItemAsFolderUrl(const KFileItem &item, const bool browseThroughArchives = true);
/**
* Hides tooltip displayed over element.
*/
void hideToolTip(const ToolTipManager::HideBehavior behavior = ToolTipManager::HideBehavior::Later);
-public slots:
+ /**
+ * Check if the space key should be handled as a normal key, even if it's
+ * used as a keyboard shortcut.
+ *
+ * See BUG 465489
+ */
+ bool handleSpaceAsNormalKey() const;
+
+ /** Activates the view if the item list container gets focus. */
+ bool eventFilter(QObject *watched, QEvent *event) override;
+
+ /**
+ * Returns whether the folder represented by the current URL is writable.
+ */
+ bool isFolderWritable() const;
+
+ /**
+ * @returns the height of the scrollbar at the bottom of the view or zero if no such scroll bar is visible.
+ */
+ int horizontalScrollBarHeight() const;
+
+ /**
+ * Set the offset for any view items that small statusbar would otherwise
+ * cover. For example, in compact view this is used to make sure no
+ * item is covered by statusbar.
+ */
+ void setStatusBarOffset(int offset);
+
+public Q_SLOTS:
+
+ void reload();
+
/**
* Changes the directory to \a url. If the current directory is equal to
* \a url, nothing will be done (use DolphinView::reload() instead).
*/
- void setUrl(const QUrl& url);
+ void setUrl(const QUrl &url);
/**
* Selects all items.
*/
void updateViewState();
- /** Activates the view if the item list container gets focus. */
- bool eventFilter(QObject* watched, QEvent* event) override;
-
-signals:
+Q_SIGNALS:
/**
* Is emitted if the view has been activated by e. g. a mouse click.
*/
void activated();
/** Is emitted if the URL of the view has been changed to \a url. */
- void urlChanged(const QUrl& url);
+ void urlChanged(const QUrl &url);
/**
* Is emitted when clicking on an item with the left mouse button.
*/
- void itemActivated(const KFileItem& item);
+ void itemActivated(const KFileItem &item);
+
+ /**
+ * Is emitted when clicking on a file with the middle mouse button.
+ * @note: This will not be emitted for folders or file archives that will/can be opened like folders.
+ */
+ void fileMiddleClickActivated(const KFileItem &item);
/**
* Is emitted when multiple items have been activated by e. g.
* context menu open with.
*/
- void itemsActivated(const KFileItemList& items);
+ void itemsActivated(const KFileItemList &items);
/**
* Is emitted if items have been added or deleted.
/**
* Is emitted if a new tab should be opened for the URL \a url.
*/
- void tabRequested(const QUrl& url, DolphinTabWidget::TabPlacement tabPlacement);
+ void tabRequested(const QUrl &url);
+
+ /**
+ * Is emitted if a new tab should be opened for the URL \a url and set as active.
+ */
+ void activeTabRequested(const QUrl &url);
+
+ /**
+ * Is emitted if a new window should be opened for the URL \a url.
+ */
+ void windowRequested(const QUrl &url);
/**
* Is emitted if the view mode (IconsView, DetailsView,
/** Is emitted if the 'grouped sorting' property has been changed. */
void groupedSortingChanged(bool groupedSorting);
+ /** Is emitted in reaction to a requestStatusBarText() call.
+ * @see requestStatusBarText() */
+ void statusBarTextChanged(QString statusBarText);
+
/** Is emitted if the sorting by name, size or date has been changed. */
- void sortRoleChanged(const QByteArray& role);
+ void sortRoleChanged(const QByteArray &role);
/** Is emitted if the sort order (ascending or descending) has been changed. */
void sortOrderChanged(Qt::SortOrder order);
+ /** Is emitted if the grouping by name, size or date has been changed. */
+ void groupRoleChanged(const QByteArray &role);
+
+ /** Is emitted if the group order (ascending or descending) has been changed. */
+ void groupOrderChanged(Qt::SortOrder order);
+
/**
* Is emitted if the sorting of files and folders (separate with folders
* first or mixed) has been changed.
*/
void sortFoldersFirstChanged(bool foldersFirst);
+ /**
+ * Is emitted if the sorting of hidden files has been changed.
+ */
+ void sortHiddenLastChanged(bool hiddenLast);
+
/** Is emitted if the additional information shown for this view has been changed. */
- void visibleRolesChanged(const QList<QByteArray>& current,
- const QList<QByteArray>& previous);
+ void visibleRolesChanged(const QList<QByteArray> ¤t, const QList<QByteArray> &previous);
/** Is emitted if the zoom level has been changed by zooming in or out. */
void zoomLevelChanged(int current, int previous);
* Is emitted if information of an item is requested to be shown e. g. in the panel.
* If item is null, no item information request is pending.
*/
- void requestItemInfo(const KFileItem& item);
+ void requestItemInfo(const KFileItem &item);
/**
* Is emitted whenever the selection has been changed.
*/
- void selectionChanged(const KFileItemList& selection);
+ void selectionChanged(const KFileItemList &selection);
/**
* Is emitted if a context menu is requested for the item \a item,
* which is part of \a url. If the item is null, the context menu
- * for the URL should be shown and the custom actions \a customActions
- * will be added.
+ * for the URL should be shown.
*/
- void requestContextMenu(const QPoint& pos,
- const KFileItem& item,
- const QUrl& url,
- const QList<QAction*>& customActions);
+ void requestContextMenu(const QPoint &pos, const KFileItem &item, const KFileItemList &selectedItems, const QUrl &url);
/**
* Is emitted if an information message with the content \a msg
* should be shown.
*/
- void infoMessage(const QString& msg);
+ void infoMessage(const QString &msg);
/**
* Is emitted if an error message with the content \a msg
* should be shown.
*/
- void errorMessage(const QString& msg);
+ void errorMessage(const QString &message, const int kioErrorCode);
/**
* Is emitted if an "operation completed" message with the content \a msg
* should be shown.
*/
- void operationCompletedMessage(const QString& msg);
+ void operationCompletedMessage(const QString &msg);
/**
* Is emitted after DolphinView::setUrl() has been invoked and
* Emitted when the file-item-model emits redirection.
* Testcase: fish://localhost
*/
- void redirection(const QUrl& oldUrl, const QUrl& newUrl);
+ void redirection(const QUrl &oldUrl, const QUrl &newUrl);
/**
* Is emitted when the URL set by DolphinView::setUrl() represents a file.
* In this case no signal errorMessage() will be emitted.
*/
- void urlIsFileError(const QUrl& url);
+ void urlIsFileError(const QUrl &url);
/**
* Is emitted when the write state of the folder has been changed. The application
*/
void goForwardRequested();
+ /**
+ * Used to request either entering or leaving of selection mode
+ * Entering is typically requested on press and hold.
+ * Leaving by pressing Escape when no item is selected.
+ */
+ void selectionModeChangeRequested(bool enabled);
+
/**
* Is emitted when the user wants to move the focus to another view.
*/
* Is emitted when the user clicks a tag or a link
* in the metadata widget of a tooltip.
*/
- void urlActivated(const QUrl& url);
+ void urlActivated(const QUrl &url);
void goUpRequested();
+ void fileItemsChanged(const KFileItemList &changedFileItems);
+
+ /**
+ * Emitted when the current directory of the model was removed.
+ */
+ void currentDirectoryRemoved();
+
+ /**
+ * Emitted when the view's background is double-clicked.
+ * Used to trigger an user configured action.
+ */
+ void doubleClickViewBackground(Qt::MouseButton button);
+
protected:
/** Changes the zoom level if Control is pressed during a wheel event. */
- void wheelEvent(QWheelEvent* event) override;
+ void wheelEvent(QWheelEvent *event) override;
- void hideEvent(QHideEvent* event) override;
- bool event(QEvent* event) override;
+ void hideEvent(QHideEvent *event) override;
+ bool event(QEvent *event) override;
-private slots:
+private Q_SLOTS:
/**
* Marks the view as active (DolphinView:isActive() will return true)
* and emits the 'activated' signal if it is not already active.
void activate();
void slotItemActivated(int index);
- void slotItemsActivated(const KItemSet& indexes);
+ void slotItemsActivated(const KItemSet &indexes);
void slotItemMiddleClicked(int index);
- void slotItemContextMenuRequested(int index, const QPointF& pos);
- void slotViewContextMenuRequested(const QPointF& pos);
- void slotHeaderContextMenuRequested(const QPointF& pos);
- void slotHeaderColumnWidthChangeFinished(const QByteArray& role, qreal current);
+ void slotItemContextMenuRequested(int index, const QPointF &pos);
+ void slotViewContextMenuRequested(const QPointF &pos);
+ void slotHeaderContextMenuRequested(const QPointF &pos);
+ void slotHeaderColumnWidthChangeFinished(const QByteArray &role, qreal current);
+ void slotSidePaddingWidthChanged(qreal leftPaddingWidth, qreal rightPaddingWidth);
void slotItemHovered(int index);
void slotItemUnhovered(int index);
- void slotItemDropEvent(int index, QGraphicsSceneDragDropEvent* event);
- void slotModelChanged(KItemModelBase* current, KItemModelBase* previous);
+ void slotItemDropEvent(int index, QGraphicsSceneDragDropEvent *event);
+ void slotModelChanged(KItemModelBase *current, KItemModelBase *previous);
void slotMouseButtonPressed(int itemIndex, Qt::MouseButtons buttons);
- void slotRenameDialogRenamingFinished(const QList<QUrl>& urls);
void slotSelectedItemTextPressed(int index);
- void slotCopyingDone(KIO::Job *, const QUrl &, const QUrl &to);
+ void slotItemCreatedFromJob(KIO::Job *, const QUrl &, const QUrl &to);
+ void slotItemLinkCreatedFromJob(KIO::Job *, const QUrl &, const QString &, const QUrl &to);
void slotIncreaseZoom();
void slotDecreaseZoom();
void slotSwipeUp();
* the signal is emitted only after no selection change has been done
* within a small delay.
*/
- void slotSelectionChanged(const KItemSet& current, const KItemSet& previous);
+ void slotSelectionChanged(const KItemSet ¤t, const KItemSet &previous);
/**
* Is called by emitDelayedSelectionChangedSignal() and emits the
void emitSelectionChangedSignal();
/**
- * Updates the view properties of the current URL to the
- * sorting given by \a role.
+ * Helper method for DolphinView::requestStatusBarText().
+ * Calculates the amount of folders and files and their total size in
+ * response to a KStatJob::result(), then calls emitStatusBarText().
+ * @see requestStatusBarText()
+ * @see emitStatusBarText()
*/
- void updateSortRole(const QByteArray& role);
+ void slotStatJobResult(KJob *job);
/**
* Updates the view properties of the current URL to the
- * sort order given by \a order.
+ * sorting of files and folders (separate with folders first or mixed) given by \a foldersFirst.
*/
- void updateSortOrder(Qt::SortOrder order);
+ void updateSortFoldersFirst(bool foldersFirst);
/**
* Updates the view properties of the current URL to the
- * sorting of files and folders (separate with folders first or mixed) given by \a foldersFirst.
+ * sorting of hidden files given by \a hiddenLast.
*/
- void updateSortFoldersFirst(bool foldersFirst);
+ void updateSortHiddenLast(bool hiddenLast);
/**
* Indicates in the status bar that the delete operation
* of the job \a job has been finished.
*/
- void slotDeleteFileFinished(KJob* job);
+ void slotDeleteFileFinished(KJob *job);
/**
* Indicates in the status bar that the trash operation
* of the job \a job has been finished.
*/
- void slotTrashFileFinished(KJob* job);
+ void slotTrashFileFinished(KJob *job);
/**
* Invoked when the rename job is done, for error handling.
*/
- void slotRenamingResult(KJob* job);
+ void slotRenamingResult(KJob *job);
/**
* Invoked when the file item model has started the loading
*/
void slotDirectoryLoadingCompleted();
+ /**
+ * Invoked when the file item model indicates that the loading of a directory has
+ * been canceled.
+ */
+ void slotDirectoryLoadingCanceled();
+
/**
* Is invoked when items of KFileItemModel have been changed.
*/
* Is invoked when the sort role has been changed by the user by clicking
* on a header item. The view properties of the directory will get updated.
*/
- void slotSortRoleChangedByHeader(const QByteArray& current, const QByteArray& previous);
+ void slotSortRoleChangedByHeader(const QByteArray ¤t, const QByteArray &previous);
/**
* Is invoked when the visible roles have been changed by the user by dragging
* a header item. The view properties of the directory will get updated.
*/
- void slotVisibleRolesChangedByHeader(const QList<QByteArray>& current,
- const QList<QByteArray>& previous);
+ void slotVisibleRolesChangedByHeader(const QList<QByteArray> ¤t, const QList<QByteArray> &previous);
void slotRoleEditingCanceled();
- void slotRoleEditingFinished(int index, const QByteArray& role, const QVariant& value);
+ void slotRoleEditingFinished(int index, const QByteArray &role, const QVariant &value);
/**
* Observes the item with the URL \a url. As soon as the directory
void observeCreatedItem(const QUrl &url);
/**
- * Called when a redirection happens.
- * Testcase: fish://localhost
+ * Selects the next item after prev selection deleted/trashed
*/
- void slotDirectoryRedirection(const QUrl& oldUrl, const QUrl& newUrl);
+ void selectNextItem();
/**
- * Calculates the number of currently shown files into
- * \a fileCount and the number of folders into \a folderCount.
- * The size of all files is written into \a totalFileSize.
- * It is recommend using this method instead of asking the
- * directory lister or the model directly, as it takes
- * filtering and hierarchical previews into account.
+ * Called when a redirection happens.
+ * Testcase: fish://localhost
*/
- void calculateItemCount(int& fileCount, int& folderCount, KIO::filesize_t& totalFileSize) const;
+ void slotDirectoryRedirection(const QUrl &oldUrl, const QUrl &newUrl);
void slotTwoClicksRenamingTimerTimeout();
+ void onDirectoryLoadingCompletedAfterJob();
+
private:
- void loadDirectory(const QUrl& url, bool reload = false);
+ void loadDirectory(const QUrl &url, bool reload = false);
/**
* Applies the view properties which are defined by the current URL
/**
* Applies the given view properties to the DolphinView.
*/
- void applyViewProperties(const ViewProperties& props);
+ void applyViewProperties(const ViewProperties &props);
/**
* Applies the m_mode property to the corresponding
*/
void applyModeToView();
+ /**
+ * Changes the current view based on the content of the directory.
+ */
+ void applyDynamicView();
+
+ enum Selection { HasSelection, NoSelection };
+ /**
+ * Helper method for DolphinView::requestStatusBarText().
+ * Generates the status bar text from the parameters and
+ * then emits statusBarTextChanged().
+ * @param totalFileSize the sum of the sizes of the files
+ * @param selection if HasSelection is passed, the emitted status bar text will say
+ * that the folders and files which are counted here are selected.
+ */
+ void emitStatusBarText(const int folderCount, const int fileCount, KIO::filesize_t totalFileSize, const Selection selection);
+
/**
* Helper method for DolphinView::paste() and DolphinView::pasteIntoFolder().
* Pastes the clipboard data into the URL \a url.
*/
- void pasteToUrl(const QUrl& url);
+ void pasteToUrl(const QUrl &url);
/**
* Returns a list of URLs for all selected items. The list is
/**
* Returns the MIME data for all selected items.
*/
- QMimeData* selectionMimeData() const;
+ QMimeData *selectionMimeData() const;
/**
* Updates m_isFolderWritable dependent on whether the folder represented by
* the current URL is writable. If the state has changed, the signal
- * writeableStateChanged() will be emitted.
+ * writeStateChanged() will be emitted.
*/
void updateWritableState();
* @param current URL to be set as current
* @param selected list of selected items
*/
- void forceUrlsSelection(const QUrl& current, const QList<QUrl>& selected);
+ void forceUrlsSelection(const QUrl ¤t, const QList<QUrl> &selected);
void abortTwoClicksRenaming();
+ void updatePlaceholderLabel();
+
+ bool tryShowNameToolTip(QHelpEvent *event);
+
private:
void updatePalette();
+ void showLoadingPlaceholder();
bool m_active;
bool m_tabsForFiles;
bool m_isFolderWritable;
bool m_dragging; // True if a dragging is done. Required to be able to decide whether a
// tooltip may be shown when hovering an item.
+ bool m_selectNextItem;
+
+ enum class LoadingState { Idle, Loading, Canceled, Completed };
+ LoadingState m_loadingState = LoadingState::Idle;
QUrl m_url;
QString m_viewPropertiesContext;
Mode m_mode;
QList<QByteArray> m_visibleRoles;
- QVBoxLayout* m_topLayout;
+ QPointer<KIO::StatJob> m_statJobForStatusBarText;
+
+ QVBoxLayout *m_topLayout;
- KFileItemModel* m_model;
- DolphinItemListView* m_view;
- KItemListContainer* m_container;
+ KFileItemModel *m_model;
+ DolphinItemListView *m_view;
+ KItemListContainer *m_container;
- ToolTipManager* m_toolTipManager;
+ ToolTipManager *m_toolTipManager;
- QTimer* m_selectionChangedTimer;
+ QTimer *m_selectionChangedTimer;
QUrl m_currentItemUrl; // Used for making the view to remember the current URL after F5
bool m_scrollToCurrentItem; // Used for marking we need to scroll to current item or not
QPoint m_restoredContentsPosition;
- QList<QUrl> m_selectedUrls; // Used for making the view to remember selections after F5
+ // Used for tracking the accumulated scroll amount (for zooming with high
+ // resolution scroll wheels)
+ int m_controlWheelAccumulatedDelta;
+
+ QList<QUrl> m_selectedUrls; // Used for making the view to remember selections after F5 and file operations
bool m_clearSelectionBeforeSelectingNewItems;
bool m_markFirstNewlySelectedItemAsCurrent;
+ /// Decides whether items created by jobs should automatically be selected.
+ bool m_selectJobCreatedItems;
- VersionControlObserver* m_versionControlObserver;
+ VersionControlObserver *m_versionControlObserver;
- QTimer* m_twoClicksRenamingTimer;
+ QTimer *m_twoClicksRenamingTimer;
QUrl m_twoClicksRenamingItemUrl;
+ QLabel *m_placeholderLabel;
+ QTimer *m_showLoadingPlaceholderTimer;
+
+ /// The information roleIndex of the list column header currently hovered
+ std::optional<int> m_hoveredColumnHeaderIndex;
+
+ /// Used for selection mode. @see setSelectionMode()
+ std::unique_ptr<QProxyStyle> m_proxyStyle;
// For unit tests
friend class TestBase;
friend class DolphinDetailsViewTest;
- friend class DolphinPart; // Accesses m_model
+ friend class DolphinMainWindowTest;
+ friend class DolphinPart; // Accesses m_model
+ void updateSelectionState();
};
/// Allow using DolphinView::Mode in QVariant