1 /* ============================================================
2 *
3 * This file is a part of digiKam project
4 * https://www.digikam.org
5 *
6 * Date : 2010-02-06
7 * Description : Thumbnail bar for items
8 *
9 * Copyright (C) 2009-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
10 * Copyright (C) 2009-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
11 *
12 * This program is free software you can redistribute it
13 * and/or modify it under the terms of the GNU General
14 * Public License as published by the Free Software Foundation
15 * either version 2, or (at your option)
16 * any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * ============================================================ */
24
25 #include "itemthumbnailbar.h"
26
27 // Qt includes
28
29 #include <QEvent>
30
31 // Local includes
32
33 #include "digikam_debug.h"
34 #include "applicationsettings.h"
35 #include "itemalbumfiltermodel.h"
36 #include "itemalbummodel.h"
37 #include "itemdragdrop.h"
38 #include "itemratingoverlay.h"
39 #include "itemcoordinatesoverlay.h"
40 #include "itemthumbnaildelegate.h"
41 #include "fileactionmngr.h"
42
43 namespace Digikam
44 {
45
46 class Q_DECL_HIDDEN ItemThumbnailBar::Private
47 {
48 public:
49
Private()50 explicit Private()
51 {
52 scrollPolicy = Qt::ScrollBarAlwaysOn;
53 duplicatesFilter = nullptr;
54 }
55
56 Qt::ScrollBarPolicy scrollPolicy;
57 NoDuplicatesItemFilterModel* duplicatesFilter;
58 };
59
ItemThumbnailBar(QWidget * const parent)60 ItemThumbnailBar::ItemThumbnailBar(QWidget* const parent)
61 : ItemCategorizedView(parent),
62 d(new Private())
63 {
64 setItemDelegate(new ItemThumbnailDelegate(this));
65 setSpacing(3);
66 setUsePointingHandCursor(false);
67 setScrollStepGranularity(5);
68 setScrollBarPolicy(Qt::ScrollBarAlwaysOn);
69
70 setDragEnabled(true);
71 setAcceptDrops(true);
72 setDropIndicatorShown(false);
73
74 setScrollCurrentToCenter(ApplicationSettings::instance()->getScrollItemToCenter());
75 setToolTipEnabled(ApplicationSettings::instance()->showToolTipsIsValid());
76
77 // --- NOTE: use dynamic binding as slotSetupChanged() is a virtual slot which can be re-implemented in derived classes.
78 connect(ApplicationSettings::instance(), &ApplicationSettings::setupChanged,
79 this, &ItemThumbnailBar::slotSetupChanged);
80
81 this->slotSetupChanged();
82 // ---
83
84 setFlow(LeftToRight);
85 }
86
~ItemThumbnailBar()87 ItemThumbnailBar::~ItemThumbnailBar()
88 {
89 delete d;
90 }
91
setModelsFiltered(ItemModel * model,ImageSortFilterModel * filterModel)92 void ItemThumbnailBar::setModelsFiltered(ItemModel* model, ImageSortFilterModel* filterModel)
93 {
94 if (!d->duplicatesFilter)
95 {
96 d->duplicatesFilter = new NoDuplicatesItemFilterModel(this);
97 }
98
99 d->duplicatesFilter->setSourceFilterModel(filterModel);
100 ItemCategorizedView::setModels(model, d->duplicatesFilter);
101 }
102
installOverlays()103 void ItemThumbnailBar::installOverlays()
104 {
105 ItemRatingOverlay* const ratingOverlay = new ItemRatingOverlay(this);
106 addOverlay(ratingOverlay);
107
108 connect(ratingOverlay, SIGNAL(ratingEdited(QList<QModelIndex>,int)),
109 this, SLOT(assignRating(QList<QModelIndex>,int)));
110
111 addOverlay(new ItemCoordinatesOverlay(this));
112 }
113
slotDockLocationChanged(Qt::DockWidgetArea area)114 void ItemThumbnailBar::slotDockLocationChanged(Qt::DockWidgetArea area)
115 {
116 if (area == Qt::LeftDockWidgetArea || area == Qt::RightDockWidgetArea)
117 {
118 setFlow(TopToBottom);
119 }
120 else
121 {
122 setFlow(LeftToRight);
123 }
124
125 scrollTo(currentIndex());
126 }
127
setScrollBarPolicy(Qt::ScrollBarPolicy policy)128 void ItemThumbnailBar::setScrollBarPolicy(Qt::ScrollBarPolicy policy)
129 {
130 if (policy == Qt::ScrollBarAsNeeded)
131 {
132 // Delegate resizing will cause endless relayouting, see bug #228807
133 qCDebug(DIGIKAM_GENERAL_LOG) << "The Qt::ScrollBarAsNeeded policy is not supported by ItemThumbnailBar";
134 }
135
136 d->scrollPolicy = policy;
137
138 if (flow() == TopToBottom)
139 {
140 setVerticalScrollBarPolicy(d->scrollPolicy);
141 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
142 }
143 else
144 {
145 setHorizontalScrollBarPolicy(d->scrollPolicy);
146 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
147 }
148 }
149
setFlow(QListView::Flow flow)150 void ItemThumbnailBar::setFlow(QListView::Flow flow)
151 {
152 setWrapping(false);
153
154 ItemCategorizedView::setFlow(flow);
155
156 ItemThumbnailDelegate* const del = static_cast<ItemThumbnailDelegate*>(delegate());
157 del->setFlow(flow);
158
159 // Reset the minimum and maximum sizes.
160 setMinimumSize(QSize(0, 0));
161 setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
162
163 // Adjust minimum and maximum width to thumbnail sizes.
164 if (flow == TopToBottom)
165 {
166 int viewportFullWidgetOffset = size().width() - viewport()->size().width();
167 setMinimumWidth(del->minimumSize() + viewportFullWidgetOffset);
168 setMaximumWidth(del->maximumSize() + viewportFullWidgetOffset);
169 }
170 else
171 {
172 int viewportFullWidgetOffset = size().height() - viewport()->size().height();
173 setMinimumHeight(del->minimumSize() + viewportFullWidgetOffset);
174 setMaximumHeight(del->maximumSize() + viewportFullWidgetOffset);
175 }
176
177 setScrollBarPolicy(d->scrollPolicy);
178 }
179
slotSetupChanged()180 void ItemThumbnailBar::slotSetupChanged()
181 {
182 setScrollCurrentToCenter(ApplicationSettings::instance()->getScrollItemToCenter());
183 setToolTipEnabled(ApplicationSettings::instance()->showToolTipsIsValid());
184 setFont(ApplicationSettings::instance()->getIconViewFont());
185
186 ItemCategorizedView::slotSetupChanged();
187 }
188
assignRating(const QList<QModelIndex> & indexes,int rating)189 void ItemThumbnailBar::assignRating(const QList<QModelIndex>& indexes, int rating)
190 {
191 FileActionMngr::instance()->assignRating(imageSortFilterModel()->imageInfos(indexes), rating);
192 }
193
event(QEvent * e)194 bool ItemThumbnailBar::event(QEvent* e)
195 {
196 // reset widget max/min sizes
197 if (e->type() == QEvent::StyleChange || e->type() == QEvent::Show)
198 {
199 setFlow(flow());
200 }
201
202 return ItemCategorizedView::event(e);
203 }
204
nextIndex(const QModelIndex & index) const205 QModelIndex ItemThumbnailBar::nextIndex(const QModelIndex& index) const
206 {
207 return imageFilterModel()->index(index.row() + 1, 0);
208 }
209
previousIndex(const QModelIndex & index) const210 QModelIndex ItemThumbnailBar::previousIndex(const QModelIndex& index) const
211 {
212 return imageFilterModel()->index(index.row() - 1, 0);
213 }
214
firstIndex() const215 QModelIndex ItemThumbnailBar::firstIndex() const
216 {
217 return imageFilterModel()->index(0, 0);
218 }
219
lastIndex() const220 QModelIndex ItemThumbnailBar::lastIndex() const
221 {
222 return imageFilterModel()->index(imageFilterModel()->rowCount() - 1, 0);
223 }
224
225 } // namespace Digikam
226