1 /* ============================================================
2  *
3  * This file is a part of digiKam project
4  * https://www.digikam.org
5  *
6  * Date        : 2012-20-07
7  * Description : Thumbnail bar for import tool
8  *
9  * Copyright (C) 2012      by Islam Wazery <wazery at ubuntu dot com>
10  * Copyright (C) 2012-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 "importthumbnailbar.h"
26 
27 // Local includes
28 
29 #include "digikam_debug.h"
30 #include "applicationsettings.h"
31 #include "importsettings.h"
32 #include "importdelegate.h"
33 #include "importfiltermodel.h"
34 #include "importoverlays.h"
35 
36 namespace Digikam
37 {
38 
39 class Q_DECL_HIDDEN ImportThumbnailBar::Private
40 {
41 public:
42 
Private()43     explicit Private()
44       : scrollPolicy(Qt::ScrollBarAlwaysOn),
45         duplicatesFilter(nullptr)
46     {
47     }
48 
49     Qt::ScrollBarPolicy            scrollPolicy;
50     NoDuplicatesImportFilterModel* duplicatesFilter;
51 };
52 
ImportThumbnailBar(QWidget * const parent)53 ImportThumbnailBar::ImportThumbnailBar(QWidget* const parent)
54     : ImportCategorizedView(parent),
55       d(new Private())
56 {
57     setItemDelegate(new ImportThumbnailDelegate(this));
58     setSpacing(3);
59     setUsePointingHandCursor(false);
60     setScrollStepGranularity(5);
61     setScrollBarPolicy(Qt::ScrollBarAlwaysOn);
62 
63     setDragEnabled(true);
64     setAcceptDrops(true);
65     setDropIndicatorShown(false);
66 
67     setScrollCurrentToCenter(ApplicationSettings::instance()->getScrollItemToCenter());
68     setToolTipEnabled(ImportSettings::instance()->showToolTipsIsValid());
69 
70     // --- NOTE: use dynamic binding as slotSetupChanged() is a virtual method which can be re-implemented in derived classes.
71 
72     connect(ImportSettings::instance(), &ImportSettings::setupChanged,
73             this, &ImportThumbnailBar::slotSetupChanged);
74 
75     this->slotSetupChanged();
76 
77     // ---
78 
79     setFlow(LeftToRight);
80 }
81 
~ImportThumbnailBar()82 ImportThumbnailBar::~ImportThumbnailBar()
83 {
84     delete d;
85 }
86 
setModelsFiltered(ImportItemModel * model,ImportSortFilterModel * filterModel)87 void ImportThumbnailBar::setModelsFiltered(ImportItemModel* model, ImportSortFilterModel* filterModel)
88 {
89     if (!d->duplicatesFilter)
90     {
91         d->duplicatesFilter = new NoDuplicatesImportFilterModel(this);
92     }
93 
94     d->duplicatesFilter->setSourceFilterModel(filterModel);
95     ImportCategorizedView::setModels(model, d->duplicatesFilter);
96 }
97 
installOverlays()98 void ImportThumbnailBar::installOverlays()
99 {
100     ImportRatingOverlay* const ratingOverlay = new ImportRatingOverlay(this);
101     addOverlay(ratingOverlay);
102 
103     connect(ratingOverlay, SIGNAL(ratingEdited(QList<QModelIndex>,int)),
104             this, SLOT(assignRating(QList<QModelIndex>,int)));
105 
106     addOverlay(new ImportLockOverlay(this));
107     addOverlay(new ImportDownloadOverlay(this));
108     addOverlay(new ImportCoordinatesOverlay(this));
109 }
110 
slotDockLocationChanged(Qt::DockWidgetArea area)111 void ImportThumbnailBar::slotDockLocationChanged(Qt::DockWidgetArea area)
112 {
113     if ((area == Qt::LeftDockWidgetArea) || (area == Qt::RightDockWidgetArea))
114     {
115         setFlow(TopToBottom);
116     }
117     else
118     {
119         setFlow(LeftToRight);
120     }
121 
122     scrollTo(currentIndex());
123 }
124 
setScrollBarPolicy(Qt::ScrollBarPolicy policy)125 void ImportThumbnailBar::setScrollBarPolicy(Qt::ScrollBarPolicy policy)
126 {
127     if (policy == Qt::ScrollBarAsNeeded)
128     {
129         // Delegate resizing will cause endless relayouting, see bug #228807
130 
131         qCDebug(DIGIKAM_IMPORTUI_LOG) << "The Qt::ScrollBarAsNeeded policy is not supported by ImportThumbnailBar";
132     }
133 
134     d->scrollPolicy = policy;
135 
136     if (flow() == TopToBottom)
137     {
138         setVerticalScrollBarPolicy(d->scrollPolicy);
139         setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
140     }
141     else
142     {
143         setHorizontalScrollBarPolicy(d->scrollPolicy);
144         setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
145     }
146 }
147 
setFlow(QListView::Flow flow)148 void ImportThumbnailBar::setFlow(QListView::Flow flow)
149 {
150     setWrapping(false);
151 
152     ImportCategorizedView::setFlow(flow);
153 
154     ImportThumbnailDelegate* del = static_cast<ImportThumbnailDelegate*>(delegate());
155     del->setFlow(flow);
156 
157     // Reset the minimum and maximum sizes.
158 
159     setMinimumSize(QSize(0, 0));
160     setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
161 
162     // Adjust minimum and maximum width to thumbnail sizes.
163 
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 ImportThumbnailBar::slotSetupChanged()
181 {
182     setScrollCurrentToCenter(ApplicationSettings::instance()->getScrollItemToCenter());
183     setToolTipEnabled(ImportSettings::instance()->showToolTipsIsValid());
184     setFont(ImportSettings::instance()->getIconViewFont());
185 
186     ImportCategorizedView::slotSetupChanged();
187 }
188 
assignRating(const QList<QModelIndex> & indexes,int rating)189 void ImportThumbnailBar::assignRating(const QList<QModelIndex>& indexes, int rating)
190 {
191    QList<QModelIndex> mappedIndexes = importSortFilterModel()->mapListToSource(indexes);
192 
193    foreach (const QModelIndex& index, mappedIndexes)
194    {
195        if (index.isValid())
196        {
197             importItemModel()->camItemInfoRef(index).rating = rating;
198        }
199    }
200 }
201 
event(QEvent * e)202 bool ImportThumbnailBar::event(QEvent* e)
203 {
204     // reset widget max/min sizes
205 
206     if ((e->type() == QEvent::StyleChange) || (e->type() == QEvent::Show))
207     {
208         setFlow(flow());
209     }
210 
211     return ImportCategorizedView::event(e);
212 }
213 
nextIndex(const QModelIndex & index) const214 QModelIndex ImportThumbnailBar::nextIndex(const QModelIndex& index) const
215 {
216     return importFilterModel()->index(index.row() + 1, 0);
217 }
218 
previousIndex(const QModelIndex & index) const219 QModelIndex ImportThumbnailBar::previousIndex(const QModelIndex& index) const
220 {
221     return importFilterModel()->index(index.row() - 1, 0);
222 }
223 
firstIndex() const224 QModelIndex ImportThumbnailBar::firstIndex() const
225 {
226     return importFilterModel()->index(0, 0);
227 }
228 
lastIndex() const229 QModelIndex ImportThumbnailBar::lastIndex() const
230 {
231     return importFilterModel()->index(importFilterModel()->rowCount() - 1, 0);
232 }
233 
234 } // namespace Digikam
235