1 /* ============================================================
2  *
3  * This file is a part of digiKam project
4  * https://www.digikam.org
5  *
6  * Date        : 2010-07-15
7  * Description : Model for central Map view
8  *
9  * Copyright (C) 2010      by Gabriel Voicu <ping dot gabi at gmail dot com>
10  * Copyright (C) 2010-2011 by Michael G. Hansen <mike at mghansen dot de>
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) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * ============================================================ */
23 
24 #include "itemgpsmodelhelper.h"
25 
26 namespace Digikam
27 {
28 
29 class Q_DECL_HIDDEN ItemGPSModelHelper::Private
30 {
31 public:
32 
Private()33     explicit Private()
34       : itemModel          (nullptr),
35         itemSelectionModel (nullptr),
36         thumbnailLoadThread(nullptr)
37     {
38     }
39 
40     QStandardItemModel*  itemModel;
41     QItemSelectionModel* itemSelectionModel;
42     ThumbnailLoadThread* thumbnailLoadThread;
43 };
44 
ItemGPSModelHelper(QStandardItemModel * const itemModel,QObject * const parent)45 ItemGPSModelHelper::ItemGPSModelHelper(QStandardItemModel* const itemModel, QObject* const parent)
46     : GeoModelHelper(parent),
47       d             (new Private())
48 {
49 
50     d->itemModel           = itemModel;
51     d->itemSelectionModel  = new QItemSelectionModel(d->itemModel);
52     d->thumbnailLoadThread = new ThumbnailLoadThread(this);
53 
54     connect(d->thumbnailLoadThread, SIGNAL(signalThumbnailLoaded(LoadingDescription,QPixmap)),
55             this, SLOT(slotThumbnailLoaded(LoadingDescription,QPixmap)));
56 
57     connect(d->itemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
58             this, SIGNAL(signalModelChangedDrastically()));
59 }
60 
~ItemGPSModelHelper()61 ItemGPSModelHelper::~ItemGPSModelHelper()
62 {
63     delete d;
64 }
65 
model() const66 QAbstractItemModel* ItemGPSModelHelper::model() const
67 {
68     return d->itemModel;
69 }
70 
selectionModel() const71 QItemSelectionModel* ItemGPSModelHelper::selectionModel() const
72 {
73     return d->itemSelectionModel;
74 }
75 
itemCoordinates(const QModelIndex & index,GeoCoordinates * const coordinates) const76 bool ItemGPSModelHelper::itemCoordinates(const QModelIndex& index,
77                                          GeoCoordinates* const coordinates) const
78 {
79     const GPSItemInfo currentGPSItemInfo = index.data(RoleGPSItemInfo).value<GPSItemInfo>();
80     *coordinates                         = currentGPSItemInfo.coordinates;
81 
82     if (currentGPSItemInfo.coordinates.hasCoordinates())
83     {
84         return true;
85     }
86     else
87     {
88         return false;
89     }
90 }
91 
pixmapFromRepresentativeIndex(const QPersistentModelIndex & index,const QSize & size)92 QPixmap ItemGPSModelHelper::pixmapFromRepresentativeIndex(const QPersistentModelIndex& index,
93                                                           const QSize& size)
94 {
95     if (!index.isValid())
96     {
97         return QPixmap();
98     }
99 
100     const QModelIndex currentIndex(index);
101     const GPSItemInfo currentGPSItemInfo = currentIndex.data(RoleGPSItemInfo).value<GPSItemInfo>();
102 
103     QPixmap thumbnail;
104     ThumbnailIdentifier thumbId;
105     thumbId.filePath = currentGPSItemInfo.url.toLocalFile();
106     thumbId.id       = currentGPSItemInfo.id;
107 
108     if (d->thumbnailLoadThread->find(thumbId, thumbnail, qMax(size.width(), size.height())))
109     {
110         // digikam returns thumbnails with a border around them,
111         // but the geolocation interface expects them without a border.
112 
113         return thumbnail.copy(1, 1, thumbnail.size().width()-2, thumbnail.size().height()-2);
114     }
115     else
116     {
117         return QPixmap();
118     }
119 }
120 
bestRepresentativeIndexFromList(const QList<QPersistentModelIndex> & list,const int sortKey)121 QPersistentModelIndex ItemGPSModelHelper::bestRepresentativeIndexFromList(const QList<QPersistentModelIndex>& list,
122                                                                           const int sortKey)
123 {
124     QModelIndex bestIndex       = list.first();
125     GPSItemInfo bestGPSItemInfo = bestIndex.data(RoleGPSItemInfo).value<GPSItemInfo>();
126 
127     for (int i = 1 ; i < list.count() ; ++i)
128     {
129         const QModelIndex currentIndex(list.at(i));
130         const GPSItemInfo currentGPSItemInfo = currentIndex.data(RoleGPSItemInfo).value<GPSItemInfo>();
131         const bool currentFitsBetter         = GPSItemInfoSorter::fitsBetter(bestGPSItemInfo,
132                                                                              SelectedNone,
133                                                                              currentGPSItemInfo,
134                                                                              SelectedNone,
135                                                                              SelectedNone,
136                                                                              GPSItemInfoSorter::SortOptions(sortKey));
137 
138         if (currentFitsBetter)
139         {
140             bestGPSItemInfo = currentGPSItemInfo;
141             bestIndex       = currentIndex;
142         }
143     }
144 
145     return QPersistentModelIndex(bestIndex);
146 }
147 
slotThumbnailLoaded(const LoadingDescription & loadingDescription,const QPixmap & thumb)148 void ItemGPSModelHelper::slotThumbnailLoaded(const LoadingDescription& loadingDescription,
149                                              const QPixmap& thumb)
150 {
151     for (int i = 0 ; i < d->itemModel->rowCount() ; ++i)
152     {
153         const QStandardItem* const item      = static_cast<QStandardItem*>(d->itemModel->item(i));
154         const GPSItemInfo currentGPSItemInfo = item->data(RoleGPSItemInfo).value<GPSItemInfo>();
155 
156         if (currentGPSItemInfo.url.toLocalFile() == loadingDescription.filePath)
157         {
158             const QPersistentModelIndex goodIndex(d->itemModel->index(i, 0));
159 
160             emit signalThumbnailAvailableForIndex(goodIndex, thumb);
161         }
162     }
163 }
164 
165 } // namespace Digikam
166