1 /*
2  * Strawberry Music Player
3  * This file was part of Clementine.
4  * Copyright 2010, David Sansome <me@davidsansome.com>
5  *
6  * Strawberry is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Strawberry is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Strawberry.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 #ifndef GROUPEDICONVIEW_H
22 #define GROUPEDICONVIEW_H
23 
24 #include "config.h"
25 
26 #include <QObject>
27 #include <QListView>
28 #include <QAbstractItemModel>
29 #include <QAbstractItemView>
30 #include <QItemSelectionModel>
31 #include <QString>
32 #include <QFont>
33 #include <QPalette>
34 #include <QPoint>
35 #include <QRect>
36 #include <QRegion>
37 #include <QVector>
38 
39 class QWidget;
40 class QPainter;
41 class QModelIndex;
42 class QPaintEvent;
43 class QResizeEvent;
44 class MultiSortFilterProxy;
45 
46 class GroupedIconView : public QListView {
47   Q_OBJECT
48 
49   // Vertical space separating a header from the items above and below it.
50   Q_PROPERTY(int header_spacing READ header_spacing WRITE set_header_spacing)
51 
52   // Horizontal space separating a header from the left and right edges of the widget.
53   Q_PROPERTY(int header_indent READ header_indent WRITE set_header_indent)
54 
55   // Horizontal space separating an item from the left and right edges of the widget.
56   Q_PROPERTY(int item_indent READ item_indent WRITE set_item_indent)
57 
58   // The text of each group's header.  Must contain "%1".
59   Q_PROPERTY(QString header_text READ header_text WRITE set_header_text)
60 
61  public:
62   explicit GroupedIconView(QWidget *parent = nullptr);
63 
64   enum Role {
65     Role_Group = 1158300,
66   };
67 
68   void AddSortSpec(const int role, const Qt::SortOrder order = Qt::AscendingOrder);
69 
header_spacing()70   int header_spacing() const { return header_spacing_; }
header_indent()71   int header_indent() const { return header_indent_; }
item_indent()72   int item_indent() const { return item_indent_; }
header_text()73   const QString &header_text() const { return header_text_;}
74 
set_header_spacing(const int value)75   void set_header_spacing(const int value) { header_spacing_ = value; }
set_header_indent(const int value)76   void set_header_indent(const int value) { header_indent_ = value; }
set_item_indent(const int value)77   void set_item_indent(const int value) { item_indent_ = value; }
set_header_text(const QString & value)78   void set_header_text(const QString &value) { header_text_ = value; }
79 
80   // QAbstractItemView
81   QModelIndex moveCursor(CursorAction action, Qt::KeyboardModifiers modifiers) override;
82   void setModel(QAbstractItemModel *model) override;
83 
84   static void DrawHeader(QPainter *painter, const QRect rect, const QFont &font, const QPalette &palette, const QString &text);
85 
86  protected:
87   virtual int header_height() const;
88 
89   // QWidget
90   void paintEvent(QPaintEvent *e) override;
91   void resizeEvent(QResizeEvent *e) override;
92 
93   // QAbstractItemView
94   void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int>& = QVector<int>()) override;
95   QModelIndex indexAt(const QPoint &p) const override;
96   void rowsInserted(const QModelIndex &parent, int start, int end) override;
97   void setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command) override;
98   QRect visualRect(const QModelIndex &idx) const override;
99   QRegion visualRegionForSelection(const QItemSelection &selection) const override;
100 
101  private slots:
102   void LayoutItems();
103 
104  private:
105   static const int kBarThickness;
106   static const int kBarMarginTop;
107 
108   struct Header {
109     int y;
110     int first_row;
111     QString text;
112   };
113 
114   // Returns the items that are wholly or partially inside the rect.
115   QVector<QModelIndex> IntersectingItems(const QRect rect) const;
116 
117   // Returns the index of the item above (d=-1) or below (d=+1) the given item.
118   int IndexAboveOrBelow(int index, const int d) const;
119 
120   MultiSortFilterProxy *proxy_model_;
121   QVector<QRect> visual_rects_;
122   QVector<Header> headers_;
123 
124   const int default_header_height_;
125   int header_spacing_;
126   int header_indent_;
127   int item_indent_;
128   QString header_text_;
129 };
130 
131 #endif  // GROUPEDICONVIEW_H
132