]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/dolphinview.h
Fix temporary regression of sorting introduced by SVN commit 1126410
[dolphin.git] / src / dolphinview.h
index f1500429b23f577a49c1fe710ef3949437ae9fd7..352841f4a0a28746bf8e36dee3153e1f40790405 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************************************************
- *   Copyright (C) 2006 by Peter Penz <peter.penz@gmx.at>                  *
+ *   Copyright (C) 2006-2009 by Peter Penz <peter.penz@gmx.at>             *
  *   Copyright (C) 2006 by Gregor Kališnik <gregor@podnapisi.net>          *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
 #include <kparts/part.h>
 #include <kfileitem.h>
 #include <kfileitemdelegate.h>
-#include <konq_fileundomanager.h>
+#include <kio/fileundomanager.h>
 #include <kio/job.h>
 
 #include <QBoxLayout>
 #include <QKeyEvent>
 #include <QLinkedList>
 #include <QListView>
+#include <QSet>
 #include <QWidget>
 
-class QActionGroup;
-class DolphinController;
-class DolphinColumnView;
+typedef KIO::FileUndoManager::CommandType CommandType;
+
+class DolphinColumnViewContainer;
 class DolphinDetailsView;
 class DolphinIconsView;
-class DolphinMainWindow;
 class DolphinModel;
 class DolphinSortFilterProxyModel;
-class IconManager;
+class DolphinViewController;
+class KFilePreviewGenerator;
 class KAction;
 class KActionCollection;
 class KDirLister;
-class KFileItemDelegate;
 class KUrl;
-class KToggleAction;
-class QModelIndex;
+class ViewModeController;
 class ViewProperties;
+class DolphinDetailsViewExpander;
 
 /**
  * @short Represents a view for the directory content.
@@ -76,16 +76,17 @@ class LIBDOLPHINPRIVATE_EXPORT DolphinView : public QWidget
 
 public:
     /**
-        * Defines the view mode for a directory. The view mode
-        * can be defined when constructing a DolphinView. The
-        * view mode is automatically updated if the directory itself
-        * defines a view mode (see class ViewProperties for details).
-        */
+     * Defines the view mode for a directory. The view mode
+     * can be defined when constructing a DolphinView. The
+     * view mode is automatically updated if the directory itself
+     * defines a view mode (see class ViewProperties for details).
+     */
     enum Mode
     {
         /**
          * The directory items are shown as icons including an
-         * icon name. */
+         * icon name.
+         */
         IconsView = 0,
 
         /**
@@ -112,26 +113,20 @@ public:
         SortByOwner,
         SortByGroup,
         SortByType,
-        SortByRating,
-        SortByTags,
-        MaxSortEnum = SortByTags
+        SortByDestination,
+        SortByPath,
+        MaxSortingEnum = SortByPath
     };
 
     /**
      * @param parent           Parent widget of the view.
      * @param url              Specifies the content which should be shown.
-     * @param dirLister        Used directory lister. The lister is not owned
-     *                         by the view and won't get deleted.
-     * @param dolphinModel     Used directory model. The model is not owned
-     *                         by the view and won't get deleted.
      * @param proxyModel       Used proxy model which specifies the sorting. The
      *                         model is not owned by the view and won't get
      *                         deleted.
      */
     DolphinView(QWidget* parent,
                 const KUrl& url,
-                KDirLister* dirLister,
-                DolphinModel* dolphinModel,
                 DolphinSortFilterProxyModel* proxyModel);
 
     virtual ~DolphinView();
@@ -140,7 +135,7 @@ public:
      * Returns the current active URL, where all actions are applied.
      * The URL navigator is synchronized with this URL.
      */
-    const KUrl& url() const;
+    KUrl url() const;
 
     /**
      * Returns the root URL of the view, which is defined as the first
@@ -187,22 +182,12 @@ public:
     bool supportsCategorizedSorting() const;
 
     /**
-     * Selects all items.
-     * @see DolphinView::selectedItems()
+     * Marks the items indicated by \p urls to get selected after the
+     * directory DolphinView::url() has been loaded. Note that nothing
+     * gets selected if no loading of a directory has been triggered
+     * by DolphinView::setUrl() or DolphinView::reload().
      */
-    void selectAll();
-
-    /**
-     * Inverts the current selection: selected items get unselected,
-     * unselected items get selected.
-     * @see DolphinView::selectedItems()
-     */
-    void invertSelection();
-
-    /** Returns true, if at least one item is selected. */
-    bool hasSelection() const;
-
-    void clearSelection();
+    void markUrlsAsSelected(const QList<KUrl>& urls);
 
     /**
      * Returns the selected items. The list is empty if no item has been
@@ -219,35 +204,30 @@ public:
     KUrl::List selectedUrls() const;
 
     /**
-     * Returns the file item for the given model index \a index.
+     * Returns the number of selected items (this is faster than
+     * invoking selectedItems().count()).
      */
-    KFileItem fileItem(const QModelIndex& index) const;
+    int selectedItemsCount() const;
+
+    QItemSelectionModel* selectionModel() const;
 
     /**
-     * Sets the upper left position of the view content
-     * to (x,y). The content of the view might be larger than the visible area
-     * and hence a scrolling must be done.
+     * Sets the zoom level to \a level. It is assured that the used
+     * level is adjusted to be inside the range ZoomLevelInfo::minimumLevel() and
+     * ZoomLevelInfo::maximumLevel().
      */
-    void setContentsPosition(int x, int y);
-
-    /** Returns the upper left position of the view content. */
-    QPoint contentsPosition() const;
-
-    /** Increases the size of the current set view mode. */
-    void zoomIn();
-
-    /** Decreases the size of the current set view mode. */
-    void zoomOut();
+    void setZoomLevel(int level);
+    int zoomLevel() const;
 
     /**
      * Returns true, if zooming in is possible. If false is returned,
-     * the minimal zoom size is possible.
+     * the maximum zooming level has been reached.
      */
     bool isZoomInPossible() const;
 
     /**
      * Returns true, if zooming out is possible. If false is returned,
-     * the maximum zoom size is possible.
+     * the minimum zooming level has been reached.
      */
     bool isZoomOutPossible() const;
 
@@ -263,6 +243,12 @@ public:
     /** Returns the current used sort order (Qt::Ascending or Qt::Descending). */
     Qt::SortOrder sortOrder() const;
 
+    /** Sets a separate sorting with folders first (true) or a mixed sorting of files and folders (false). */
+    void setSortFoldersFirst(bool foldersFirst);
+
+    /** Returns if files and folders are sorted separately or not. */
+    bool sortFoldersFirst() const;
+
     /** Sets the additional information which should be shown for the items. */
     void setAdditionalInfo(KFileItemDelegate::InformationList info);
 
@@ -279,16 +265,6 @@ public:
      */
     void refresh();
 
-    /**
-     * Changes the directory of the view to \a url. If \a rootUrl is empty, the view
-     * properties from \a url are used for adjusting the view mode and the other properties.
-     * If \a rootUrl is not empty, the view properties from the root URL are considered
-     * instead. Specifying a root URL is only required if a view having a different root URL
-     * (e. g. the column view) should be restored. Usually using DolphinView::setUrl()
-     * is enough for changing the current URL.
-     */
-    void updateView(const KUrl& url, const KUrl& rootUrl);
-
     /**
      * Filters the currently shown items by \a nameFilter. All items
      * which contain the given filter string will be shown.
@@ -298,40 +274,30 @@ public:
     /**
      * 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.
      */
-    void calculateItemCount(int& fileCount, int& folderCount);
-
-    /**
-     * Returns the "switch to icons mode" action.
-     * This code is here to share it between the mainwindow and the part
-     */
-    static KToggleAction* iconsModeAction(KActionCollection* collection);
+    void calculateItemCount(int& fileCount, int& folderCount, KIO::filesize_t& totalFileSize) const;
 
     /**
-     * Returns the "switch to details mode" action.
-     * This code is here to share it between the mainwindow and the part
+     * Returns a textual representation of the state of the current
+     * folder or selected items, suitable for use in the status bar.
      */
-    static KToggleAction* detailsModeAction(KActionCollection* collection);
+    QString statusBarText() const;
 
     /**
-     * Returns the "switch to columns mode" action.
-     * This code is here to share it between the mainwindow and the part
+     * Returns the version control actions that are provided for the items \p items.
+     * Usually the actions are presented in the context menu.
      */
-    static KToggleAction* columnsModeAction(KActionCollection* collection);
+    QList<QAction*> versionControlActions(const KFileItemList& items) const;
 
     /**
      * Updates the state of the 'Additional Information' actions in \a collection.
      */
     void updateAdditionalInfoActions(KActionCollection* collection);
 
-    /**
-     * Returns the action name corresponding to the current view mode
-     */
-    QString currentViewModeActionName() const;
-
     /**
      * Returns the state of the paste action:
      * first is whether the action should be enabled
@@ -339,6 +305,31 @@ public:
      */
     QPair<bool, QString> pasteInfo() const;
 
+    /**
+     * If \a tabsForFiles is true, the signal tabRequested() will also
+     * emitted also for files. Per default tabs for files is disabled
+     * and hence the signal tabRequested() will only be emitted for
+     * directories.
+     */
+    void setTabsForFilesEnabled(bool tabsForFiles);
+    bool isTabsForFilesEnabled() const;
+
+    /**
+     * Returns true if the current view allows folders to be expanded,
+     * i.e. presents a hierarchical view to the user.
+     */
+    bool itemsExpandable() const;
+
+    /**
+     * Restores the view state (current item, contents position, details view expansion state)
+     */
+    void restoreState(QDataStream& stream);
+
+    /**
+     * Saves the view state (current item, contents position, details view expansion state)
+     */
+    void saveState(QDataStream& stream);
+
 public slots:
     /**
      * Changes the directory to \a url. If the current directory is equal to
@@ -347,12 +338,22 @@ public slots:
     void setUrl(const KUrl& url);
 
     /**
-     * Request of a selection change. The view will do its best to accommodate
-     * the request, but it is not guaranteed that all items in \a selection
-     * will actually get selected. The view will e.g. not select items which
-     * are not in the currently displayed folder.
+     * Selects all items.
+     * @see DolphinView::selectedItems()
      */
-    void changeSelection(const KFileItemList& selection);
+    void selectAll();
+
+    /**
+     * Inverts the current selection: selected items get unselected,
+     * unselected items get selected.
+     * @see DolphinView::selectedItems()
+     */
+    void invertSelection();
+
+    /** Returns true, if at least one item is selected. */
+    bool hasSelection() const;
+
+    void clearSelection();
 
     /**
      * Triggers the renaming of the currently selected items, where
@@ -372,7 +373,7 @@ public slots:
 
     /**
      * Copies all selected items to the clipboard and marks
-     * the items as cutted.
+     * the items as cut.
      */
     void cutSelectedItems();
 
@@ -382,6 +383,13 @@ public slots:
     /** Pastes the clipboard data to this view. */
     void paste();
 
+    /**
+     * Pastes the clipboard data into the currently selected
+     * folder. If the current selection is not exactly one folder, no
+     * paste operation is done.
+     */
+    void pasteIntoFolder();
+
     /**
      * Turns on the file preview for the all files of the current directory,
      * if \a show is true.
@@ -412,6 +420,9 @@ public slots:
     /** Switches between an ascending and descending sorting order. */
     void toggleSortOrder();
 
+    /** Switches between a separate sorting (with folders first) and a mixed sorting of files and folders. */
+    void toggleSortFoldersFirst();
+
     /**
      * Switches on or off the displaying of additional information
      * as specified by \a action.
@@ -428,10 +439,15 @@ signals:
     void urlChanged(const KUrl& url);
 
     /**
-     * Is emitted when clicking on an item
+     * Is emitted when clicking on an item with the left mouse button.
      */
     void itemTriggered(const KFileItem& item);
 
+    /**
+     * Is emitted if a new tab should be opened for the URL \a url.
+     */
+    void tabRequested(const KUrl& url);
+
     /**
      * Is emitted if the view mode (IconsView, DetailsView,
      * PreviewsView) has been changed.
@@ -453,18 +469,21 @@ signals:
     /** Is emitted if the sort order (ascending or descending) has been changed. */
     void sortOrderChanged(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 additional information shown for this view has been changed. */
     void additionalInfoChanged();
 
+    /** Is emitted if the zoom level has been changed by zooming in or out. */
+    void zoomLevelChanged(int level);
+
     /**
-     * Is emitted if information of an item is requested to be shown e. g. in the sidebar.
+     * 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);
 
-    /** Is emitted if the contents has been moved to \a x, \a y. */
-    void contentsMoved(int x, int y);
-
     /**
      * Is emitted whenever the selection has been changed.
      */
@@ -472,10 +491,13 @@ signals:
 
     /**
      * Is emitted if a context menu is requested for the item \a item,
-     * which is part of \a url. If the item is 0, the context menu
-     * for the URL should be shown.
+     * 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.
      */
-    void requestContextMenu(const KFileItem& item, const KUrl& url);
+    void requestContextMenu(const KFileItem& item,
+                            const KUrl& url,
+                            const QList<QAction*>& customActions);
 
     /**
      * Is emitted if an information message with the content \a msg
@@ -504,15 +526,15 @@ signals:
     void startedPathLoading(const KUrl& url);
 
     /**
-     * Is emitted when renaming, copying, moving, linking etc.
-     * Used for feedback in the mainwindow.
+     * Emitted when KDirLister emits redirection.
+     * Testcase: fish://localhost
      */
-    void doingOperation(KonqFileUndoManager::CommandType type);
+    void redirection(const KUrl& oldUrl, const KUrl& newUrl);
 
 protected:
     /** @see QWidget::mouseReleaseEvent */
     virtual void mouseReleaseEvent(QMouseEvent* event);
-    virtual void wheelEvent(QWheelEvent* event);
+    virtual bool eventFilter(QObject* watched, QEvent* event);
 
 private slots:
     /**
@@ -528,6 +550,19 @@ private slots:
      */
     void triggerItem(const KFileItem& index);
 
+    /**
+     * Emits the signal \a selectionChanged() with a small delay. This is
+     * because getting all file items for the signal can be an expensive
+     * operation. Fast selection changes are collected in this case and
+     * the signal is emitted only after no selection change has been done
+     * within a small delay.
+     */
+    void slotSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected);
+
+    /**
+     * Is called by emitDelayedSelectionChangedSignal() and emits the
+     * signal \a selectionChanged() with all selected file items as parameter.
+     */
     void emitSelectionChangedSignal();
 
     /**
@@ -535,23 +570,17 @@ private slots:
      * is used to check whether the context menu is related to an
      * item or to the viewport.
      */
-    void openContextMenu(const QPoint& pos);
+    void openContextMenu(const QPoint& pos, const QList<QAction*>& customActions);
 
     /**
-     * Drops the URLs \a urls to the destination path \a destPath. If
+     * Drops dragged URLs to the destination path \a destPath. If
      * the URLs are dropped above an item inside the destination path,
      * the item is indicated by \a destItem.
      */
-    void dropUrls(const KUrl::List& urls,
+    void dropUrls(const KFileItem& destItem,
                   const KUrl& destPath,
-                  const KFileItem& destItem);
+                  QDropEvent* event);
 
-    /**
-     * Handles the dropping of URLs to the given destination.
-     * @see DolphinDropController
-     */
-    void dropUrls(const KUrl::List& urls,
-                  const KUrl& destination);
     /**
      * Updates the view properties of the current URL to the
      * sorting given by \a sorting.
@@ -566,15 +595,15 @@ private slots:
 
     /**
      * Updates the view properties of the current URL to the
-     * additional information given by \a info.
+     * sorting of files and folders (separate with folders first or mixed) given by \a foldersFirst.
      */
-    void updateAdditionalInfo(const KFileItemDelegate::InformationList& info);
+    void updateSortFoldersFirst(bool foldersFirst);
 
     /**
-     * Emits the signal contentsMoved with the current coordinates
-     * of the viewport as parameters.
+     * Updates the view properties of the current URL to the
+     * additional information given by \a info.
      */
-    void emitContentsMoved();
+    void updateAdditionalInfo(const KFileItemDelegate::InformationList& info);
 
     /**
      * Updates the status bar to show hover information for the
@@ -596,23 +625,57 @@ private slots:
      */
     void slotDeleteFileFinished(KJob* job);
 
-private:
-    void loadDirectory(const KUrl& url, bool reload = false);
+    /**
+     * Invoked when the directory lister has completed the loading of
+     * items. Assures that pasted items and renamed items get seleced.
+     */
+    void slotDirListerCompleted();
+
+    /**
+     * Invoked when the loading of the directory is finished.
+     * Restores the active item and the scroll position if possible.
+     */
+    void slotLoadingCompleted();
 
     /**
-     * Returns the URL where the view properties should be stored. Usually
-     * DolphinView::url() is returned, but in the case of a Column View the
-     * view properties are always stored in the directory represented by the
-     * first column. It is recommendend whenever using the ViewProperties class
-     * to use DolphinView::viewPropertiesUrl() as URL.
+     * Is invoked when the KDirLister indicates refreshed items.
      */
-    KUrl viewPropertiesUrl() const;
+    void slotRefreshItems();
+
+    /**
+     * Observes the item with the URL \a url. As soon as the directory
+     * model indicates that the item is available, the item will
+     * get selected and it is assure that the item stays visible.
+     *
+     * @see selectAndScrollToCreatedItem()
+     */
+    void observeCreatedItem(const KUrl& url);
+
+    /**
+     * Selects and scrolls to the item that got observed
+     * by observeCreatedItem().
+     */
+    void selectAndScrollToCreatedItem();
+
+    /**
+     * Called when a redirection happens.
+     * Testcase: fish://localhost
+     */
+    void slotRedirection(const KUrl& oldUrl, const KUrl& newUrl);
+
+    /**
+     * Restores the contents position, if history information about the old position is available.
+     */
+    void restoreContentsPosition();
+
+private:
+    void loadDirectory(const KUrl& url, bool reload = false);
 
     /**
      * Applies the view properties which are defined by the current URL
-     * m_url to the DolphinView properties.
+     * to the DolphinView properties.
      */
-    void applyViewProperties(const KUrl& url);
+    void applyViewProperties();
 
     /**
      * Creates a new view representing the given view mode (DolphinView::mode()).
@@ -623,51 +686,131 @@ private:
     void deleteView();
 
     /**
-     * Returns a pointer to the currently used item view, which is either
-     * a ListView or a TreeView.
+     * Helper method for DolphinView::paste() and DolphinView::pasteIntoFolder().
+     * Pastes the clipboard data into the URL \a url.
      */
-    QAbstractItemView* itemView() const;
+    void pasteToUrl(const KUrl& url);
 
     /**
-     * Returns true, if the item \a item has been cut into
-     * the clipboard.
+     * Checks whether the current item view has the same zoom level
+     * as \a oldZoomLevel. If this is not the case, the zoom level
+     * of the controller is updated and a zoomLevelChanged() signal
+     * is emitted.
      */
-    bool isCutItem(const KFileItem& item) const;
+    void updateZoomLevel(int oldZoomLevel);
 
     /**
-     * Returns true, if the ColumnView is activated. As the column view
-     * requires some special handling for iterating through directories,
-     * this method has been introduced for convenience.
+     * Returns a list of URLs for all selected items. The list is
+     * simplified, so that when the URLs are part of different tree
+     * levels, only the parent is returned.
      */
-    bool isColumnViewActive() const
-    {
-        return m_columnView != 0;
-    }
+    KUrl::List simplifiedSelectedUrls() const;
+
+    /**
+     * Returns the MIME data for all selected items.
+     */
+    QMimeData* selectionMimeData() const;
+
+    /**
+     * Is invoked after a paste operation or a drag & drop
+     * operation and adds the filenames of all URLs from \a mimeData to
+     * m_newFileNames. This allows to select all newly added
+     * items in slotDirListerCompleted().
+     */
+    void addNewFileNames(const QMimeData* mimeData);
 
 private:
-    bool m_active;
-    bool m_showPreview;
-    bool m_loadingDirectory;
-    bool m_storedCategorizedSorting;
+    /**
+     * Abstracts the access to the different view implementations
+     * for icons-, details- and column-view.
+     */
+    class ViewAccessor
+    {
+    public:
+        ViewAccessor(DolphinSortFilterProxyModel* proxyModel);
+        ~ViewAccessor();
+
+        void createView(QWidget* parent,
+                        DolphinViewController* dolphinViewController,
+                        const ViewModeController* viewModeController,
+                        Mode mode);
+        void deleteView();
+
+        /**
+         * Must be invoked before the URL has been changed and allows view implementations
+         * like the column view to create a new column.
+         */
+        void prepareUrlChange(const KUrl& url);
+
+        QAbstractItemView* itemView() const;
+        KFileItemDelegate* itemDelegate() const;
+
+        /**
+         * Returns the widget that should be added to the layout as target. Usually
+         * the item view itself is returned, but in the case of the column view
+         * a container widget is returned.
+         */
+        QWidget* layoutTarget() const;
+
+        KUrl rootUrl() const;
+
+        bool supportsCategorizedSorting() const;
+        bool itemsExpandable() const;
+        QSet<KUrl> expandedUrls() const;
+        const DolphinDetailsViewExpander* setExpandedUrls(const QSet<KUrl>& urlsToExpand);
+
+        /**
+         * Returns true, if a reloading of the items is required
+         * when the additional information properties have been changed
+         * by the user.
+         */
+        bool reloadOnAdditionalInfoChange() const;
+
+        DolphinModel* dirModel() const;
+        DolphinSortFilterProxyModel* proxyModel() const;
+        KDirLister* dirLister() const;
+
+    private:
+        DolphinIconsView* m_iconsView;
+        DolphinDetailsView* m_detailsView;
+        DolphinColumnViewContainer* m_columnsContainer;
+        DolphinSortFilterProxyModel* m_proxyModel;
+        QAbstractItemView* m_dragSource;
+        QPointer<DolphinDetailsViewExpander> m_detailsViewExpander;
+    };
+
+    bool m_active : 1;
+    bool m_showPreview : 1;
+    bool m_storedCategorizedSorting : 1;
+    bool m_tabsForFiles : 1;
+    bool m_isContextMenuOpen : 1;   // TODO: workaround for Qt-issue 207192
+    bool m_ignoreViewProperties : 1;
+    bool m_assureVisibleCurrentIndex : 1;
+    bool m_expanderActive : 1;
+
     Mode m_mode;
 
-    DolphinMainWindow* m_mainWindow;
     QVBoxLayout* m_topLayout;
 
-    DolphinController* m_controller;
-    DolphinIconsView* m_iconsView;
-    DolphinDetailsView* m_detailsView;
-    DolphinColumnView* m_columnView;
-    KFileItemDelegate* m_fileItemDelegate;
-    QItemSelectionModel* m_selectionModel;
+    DolphinViewController* m_dolphinViewController;
+    ViewModeController* m_viewModeController;
+    ViewAccessor m_viewAccessor;
 
-    DolphinModel* m_dolphinModel;
-    KDirLister* m_dirLister;
-    DolphinSortFilterProxyModel* m_proxyModel;
-
-    IconManager* m_iconManager;
+    QItemSelectionModel* m_selectionModel; // allow to switch views without losing the selection
+    QTimer* m_selectionChangedTimer;
 
     KUrl m_rootUrl;
+    KUrl m_activeItemUrl;
+    QPoint m_restoredContentsPosition;
+    KUrl m_createdItemUrl; // URL for a new item that got created by the "Create New..." menu
+    KFileItemList m_selectedItems; // this is used for making the View to remember selections after F5
+
+    /**
+     * Remembers the filenames that have been added by a paste operation
+     * or a drag & drop operation. Allows to select the items in
+     * slotDirListerCompleted().
+     */
+    QSet<QString> m_newFileNames;
 };
 
 /// Allow using DolphinView::Mode in QVariant