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