]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/kitemviews/kitemlistcontroller.h
Fix selection rect after porting from QFontMetrics::width()
[dolphin.git] / src / kitemviews / kitemlistcontroller.h
index 49442c643ff74de9107c73704d79fa091ae37780..6d9b2ac6ab3644f6d9feb6f4e443ea79fd2444be 100644 (file)
@@ -1,8 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
  *                                                                         *
- *   Based on the Itemviews NG project from Trolltech Labs:                *
- *   http://qt.gitorious.org/qt-labs/itemviews-ng                          *
+ *   Based on the Itemviews NG project from Trolltech Labs                 *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  *   it under the terms of the GNU General Public License as published by  *
 #ifndef KITEMLISTCONTROLLER_H
 #define KITEMLISTCONTROLLER_H
 
-#include <libdolphin_export.h>
+#include "dolphin_export.h"
+#include "kitemset.h"
 
 #include <QObject>
+#include <QPointF>
 
+class QTimer;
 class KItemModelBase;
+class KItemListKeyboardSearchManager;
 class KItemListSelectionManager;
 class KItemListView;
+class KItemListWidget;
 class QGraphicsSceneHoverEvent;
 class QGraphicsSceneDragDropEvent;
 class QGraphicsSceneMouseEvent;
 class QGraphicsSceneResizeEvent;
 class QGraphicsSceneWheelEvent;
-class QHideEvent;
 class QInputMethodEvent;
 class QKeyEvent;
-class QShowEvent;
 class QTransform;
 
 /**
@@ -51,13 +53,14 @@ class QTransform;
  * @see KItemModelBase
  * @see KItemListSelectionManager
  */
-class LIBDOLPHINPRIVATE_EXPORT KItemListController : public QObject
+class DOLPHIN_EXPORT KItemListController : public QObject
 {
     Q_OBJECT
-    Q_ENUMS(SelectionBehavior)
     Q_PROPERTY(KItemModelBase* model READ model WRITE setModel)
     Q_PROPERTY(KItemListView *view READ view WRITE setView)
     Q_PROPERTY(SelectionBehavior selectionBehavior READ selectionBehavior WRITE setSelectionBehavior)
+    Q_PROPERTY(AutoActivationBehavior autoActivationBehavior READ autoActivationBehavior WRITE setAutoActivationBehavior)
+    Q_PROPERTY(MouseDoubleClickAction mouseDoubleClickAction READ mouseDoubleClickAction WRITE setMouseDoubleClickAction)
 
 public:
     enum SelectionBehavior {
@@ -65,9 +68,25 @@ public:
         SingleSelection,
         MultiSelection
     };
+    Q_ENUM(SelectionBehavior)
 
-    KItemListController(QObject* parent = 0);
-    virtual ~KItemListController();
+    enum AutoActivationBehavior {
+        ActivationAndExpansion,
+        ExpansionOnly
+    };
+
+    enum MouseDoubleClickAction {
+        ActivateAndExpandItem,
+        ActivateItemOnly
+    };
+
+    /**
+     * @param model  Model of the controller. The ownership is passed to the controller.
+     * @param view   View of the controller. The ownership is passed to the controller.
+     * @param parent Optional parent object.
+     */
+    KItemListController(KItemModelBase* model, KItemListView* view, QObject* parent = nullptr);
+    ~KItemListController() override;
 
     void setModel(KItemModelBase* model);
     KItemModelBase* model() const;
@@ -80,27 +99,72 @@ public:
     void setSelectionBehavior(SelectionBehavior behavior);
     SelectionBehavior selectionBehavior() const;
 
-    virtual bool showEvent(QShowEvent* event);
-    virtual bool hideEvent(QHideEvent* event);
-    virtual bool keyPressEvent(QKeyEvent* event);
-    virtual bool inputMethodEvent(QInputMethodEvent* event);
-    virtual bool mousePressEvent(QGraphicsSceneMouseEvent* event, const QTransform& transform);
-    virtual bool mouseMoveEvent(QGraphicsSceneMouseEvent* event, const QTransform& transform);
-    virtual bool mouseReleaseEvent(QGraphicsSceneMouseEvent* event, const QTransform& transform);
-    virtual bool mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event, const QTransform& transform);
-    virtual bool dragEnterEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform);
-    virtual bool dragLeaveEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform);
-    virtual bool dragMoveEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform);
-    virtual bool dropEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform);
-    virtual bool hoverEnterEvent(QGraphicsSceneHoverEvent* event, const QTransform& transform);
-    virtual bool hoverMoveEvent(QGraphicsSceneHoverEvent* event, const QTransform& transform);
-    virtual bool hoverLeaveEvent(QGraphicsSceneHoverEvent* event, const QTransform& transform);
-    virtual bool wheelEvent(QGraphicsSceneWheelEvent* event, const QTransform& transform);
-    virtual bool resizeEvent(QGraphicsSceneResizeEvent* event, const QTransform& transform);
-    virtual bool processEvent(QEvent* event, const QTransform& transform);
+    void setAutoActivationBehavior(AutoActivationBehavior behavior);
+    AutoActivationBehavior autoActivationBehavior() const;
+
+    void setMouseDoubleClickAction(MouseDoubleClickAction action);
+    MouseDoubleClickAction mouseDoubleClickAction() const;
+
+    int indexCloseToMousePressedPosition() const;
+
+    /**
+     * Sets the delay in milliseconds when dragging an object above an item
+     * until the item gets activated automatically. A value of -1 indicates
+     * that no automatic activation will be done at all (= default value).
+     *
+     * The hovered item must support dropping (see KItemModelBase::supportsDropping()),
+     * otherwise the automatic activation is not available.
+     *
+     * After activating the item the signal itemActivated() will be
+     * emitted. If the view supports the expanding of items
+     * (KItemListView::supportsItemExpanding() returns true) and the item
+     * itself is expandable (see KItemModelBase::isExpandable()) then instead
+     * of activating the item it gets expanded instead (see
+     * KItemModelBase::setExpanded()).
+     */
+    void setAutoActivationDelay(int delay);
+    int autoActivationDelay() const;
+
+    /**
+     * If set to true, the signals itemActivated() and itemsActivated() are emitted
+     * after a single-click of the left mouse button. If set to false (the default),
+     * the setting from style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick) is used.
+     */
+    void setSingleClickActivationEnforced(bool singleClick);
+    bool singleClickActivationEnforced() const;
+
+    bool processEvent(QEvent* event, const QTransform& transform);
 
 signals:
-    void itemClicked(int index, Qt::MouseButton button);
+    /**
+     * Is emitted if exactly one item has been activated by e.g. a mouse-click
+     * or by pressing Return/Enter.
+     */
+    void itemActivated(int index);
+
+    /**
+     * Is emitted if more than one item has been activated by pressing Return/Enter
+     * when having a selection.
+     */
+    void itemsActivated(const KItemSet& indexes);
+
+    void itemMiddleClicked(int index);
+
+    /**
+     * Emitted if a context-menu is requested for the item with
+     * the index \a index. It is assured that the index is valid.
+     */
+    void itemContextMenuRequested(int index, const QPointF& pos);
+
+    /**
+     * Emitted if a context-menu is requested for the KItemListView.
+     */
+    void viewContextMenuRequested(const QPointF& pos);
+
+    /**
+     * Emitted if a context-menu is requested for the header of the KItemListView.
+     */
+    void headerContextMenuRequested(const QPointF& pos);
 
     /**
      * Is emitted if the item with the index \p index gets hovered.
@@ -114,13 +178,51 @@ signals:
      */
     void itemUnhovered(int index);
 
+    /**
+     * Is emitted if a mouse-button has been pressed above an item.
+     * If the index is smaller than 0, the mouse-button has been pressed
+     * above the viewport.
+     */
+    void mouseButtonPressed(int itemIndex, Qt::MouseButtons buttons);
+
+    /**
+     * Is emitted if a mouse-button has been released above an item.
+     * It is assured that the signal mouseButtonPressed() has been emitted before.
+     * If the index is smaller than 0, the mouse-button has been pressed
+     * above the viewport.
+     */
+    void mouseButtonReleased(int itemIndex, Qt::MouseButtons buttons);
+
     void itemExpansionToggleClicked(int index);
 
+    /**
+     * Is emitted if a drop event is done above the item with the index
+     * \a index. If \a index is < 0 the drop event is done above an
+     * empty area of the view.
+     * TODO: Introduce a new signal viewDropEvent(QGraphicsSceneDragDropEvent),
+     *       which is emitted if the drop event occurs on an empty area in
+     *       the view, and make sure that index is always >= 0 in itemDropEvent().
+     */
+    void itemDropEvent(int index, QGraphicsSceneDragDropEvent* event);
+
+    /**
+     * Is emitted if a drop event is done between the item with the index
+     * \a index and the previous item.
+     */
+    void aboveItemDropEvent(int index, QGraphicsSceneDragDropEvent* event);
+
+    /**
+     * Is emitted if the Escape key is pressed.
+     */
+    void escapePressed();
+
     void modelChanged(KItemModelBase* current, KItemModelBase* previous);
     void viewChanged(KItemListView* current, KItemListView* previous);
 
+    void selectedItemTextPressed(int index);
+
 private slots:
-    void slotViewOffsetChanged(qreal current, qreal previous);
+    void slotViewScrollOffsetChanged(qreal current, qreal previous);
 
     /**
      * Is invoked when the rubberband boundaries have been changed and will select
@@ -128,12 +230,119 @@ private slots:
      */
     void slotRubberBandChanged();
 
+    void slotChangeCurrentItem(const QString& text, bool searchFromNextItem);
+
+    void slotAutoActivationTimeout();
+
+private:
+    /**
+     * Creates a QDrag object and initiates a drag-operation.
+     */
+    void startDragging();
+
+    /**
+     * @return Widget that is currently in the hovered state. 0 is returned
+     *         if no widget is marked as hovered.
+     */
+    KItemListWidget* hoveredWidget() const;
+
+    /**
+     * @return Widget that is below the position \a pos. 0 is returned
+     *         if no widget is below the position.
+     */
+    KItemListWidget* widgetForPos(const QPointF& pos) const;
+
+    /**
+     * Updates m_keyboardAnchorIndex and m_keyboardAnchorPos. If no anchor is
+     * set, it will be adjusted to the current item. If it is set it will be
+     * checked whether it is still valid, otherwise it will be reset to the
+     * current item.
+     */
+    void updateKeyboardAnchor();
+
+    /**
+     * @return Index for the next row based on \a index.
+     *         If there is no next row \a index will be returned.
+     */
+    int nextRowIndex(int index) const;
+
+    /**
+     * @return Index for the previous row based on  \a index.
+     *         If there is no previous row \a index will be returned.
+     */
+    int previousRowIndex(int index) const;
+
+    /**
+     * Helper method for updateKeyboardAnchor(), previousRowIndex() and nextRowIndex().
+     * @return The position of the keyboard anchor for the item with the index \a index.
+     *         If a horizontal scrolling is used the y-position of the item will be returned,
+     *         for the vertical scrolling the x-position will be returned.
+     */
+    qreal keyboardAnchorPos(int index) const;
+
+    /**
+     * Dependent on the selection-behavior the extendedSelectionRegion-property
+     * of the KItemListStyleOption from the view should be adjusted: If no
+     * rubberband selection is used the property should be enabled.
+     */
+    void updateExtendedSelectionRegion();
+
+    bool keyPressEvent(QKeyEvent* event);
+    bool inputMethodEvent(QInputMethodEvent* event);
+    bool mousePressEvent(QGraphicsSceneMouseEvent* event, const QTransform& transform);
+    bool mouseMoveEvent(QGraphicsSceneMouseEvent* event, const QTransform& transform);
+    bool mouseReleaseEvent(QGraphicsSceneMouseEvent* event, const QTransform& transform);
+    bool mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event, const QTransform& transform);
+    bool dragEnterEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform);
+    bool dragLeaveEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform);
+    bool dragMoveEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform);
+    bool dropEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform);
+    bool hoverEnterEvent(QGraphicsSceneHoverEvent* event, const QTransform& transform);
+    bool hoverMoveEvent(QGraphicsSceneHoverEvent* event, const QTransform& transform);
+    bool hoverLeaveEvent(QGraphicsSceneHoverEvent* event, const QTransform& transform);
+    bool wheelEvent(QGraphicsSceneWheelEvent* event, const QTransform& transform);
+    bool resizeEvent(QGraphicsSceneResizeEvent* event, const QTransform& transform);
+
 private:
+    bool m_singleClickActivationEnforced;
+    bool m_selectionTogglePressed;
+    bool m_clearSelectionIfItemsAreNotDragged;
     SelectionBehavior m_selectionBehavior;
+    AutoActivationBehavior m_autoActivationBehavior;
+    MouseDoubleClickAction m_mouseDoubleClickAction;
     KItemModelBase* m_model;
     KItemListView* m_view;
     KItemListSelectionManager* m_selectionManager;
+    KItemListKeyboardSearchManager* m_keyboardManager;
     int m_pressedIndex;
+    QPointF m_pressedMousePos;
+
+    QTimer* m_autoActivationTimer;
+
+    /**
+     * When starting a rubberband selection during a Shift- or Control-key has been
+     * pressed the current selection should never be deleted. To be able to restore
+     * the current selection it is remembered in m_oldSelection before the
+     * rubberband gets activated.
+     */
+    KItemSet m_oldSelection;
+
+    /**
+     * Assuming a view is given with a vertical scroll-orientation, grouped items and
+     * a maximum of 4 columns:
+     *
+     *  1  2  3  4
+     *  5  6  7
+     *  8  9 10 11
+     * 12 13 14
+     *
+     * If the current index is on 4 and key-down is pressed, then item 7 gets the current
+     * item. Now when pressing key-down again item 11 should get the current item and not
+     * item 10. This makes it necessary to keep track of the requested column to have a
+     * similar behavior like in a text editor:
+     */
+    int m_keyboardAnchorIndex;
+    qreal m_keyboardAnchorPos;
 };
 
 #endif