File indexing completed on 2024-04-28 15:39:05
0001 // SPDX-FileCopyrightText: 2021-2022 Tobias Leupold <tl at stonemx dot de> 0002 // 0003 // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0004 0005 // Local includes 0006 #include "GeoDataModel.h" 0007 #include "KGeoTag.h" 0008 #include "MimeHelper.h" 0009 0010 // Marble includes 0011 #include <marble/GeoDataCoordinates.h> 0012 0013 // Qt includes 0014 #include <QDebug> 0015 #include <QFileInfo> 0016 #include <QMimeData> 0017 0018 // C++ includes 0019 #include <algorithm> 0020 0021 GeoDataModel::GeoDataModel(QObject *parent) : QAbstractListModel(parent) 0022 { 0023 } 0024 0025 int GeoDataModel::rowCount(const QModelIndex &) const 0026 { 0027 return m_loadedFiles.count(); 0028 } 0029 0030 QVariant GeoDataModel::data(const QModelIndex &index, int role) const 0031 { 0032 if (! index.isValid() || index.row() > m_loadedFiles.count()) { 0033 return QVariant(); 0034 } 0035 0036 if (role == Qt::DisplayRole) { 0037 return m_displayFileNames.at(index.row()); 0038 } 0039 0040 return QVariant(); 0041 } 0042 0043 bool GeoDataModel::contains(const QString &path) 0044 { 0045 return m_loadedFiles.contains(canonicalPath(path)); 0046 } 0047 0048 void GeoDataModel::addTrack(const QString &path, const QVector<QVector<QDateTime>> ×, 0049 const QVector<QVector<Coordinates>> &segments) 0050 { 0051 Marble::GeoDataLatLonAltBox marbleTrackBox; 0052 QVector<Marble::GeoDataLineString> marbleTracks; 0053 0054 QVector<QDateTime> dateTimes; 0055 QHash<QDateTime, Coordinates> trackPoints; 0056 0057 for (int i = 0; i < times.count(); i++) { 0058 Marble::GeoDataLineString lineString; 0059 0060 for (int j = 0; j < times.at(i).count(); j++) { 0061 const auto &coordinates = segments.at(i).at(j); 0062 const Marble::GeoDataCoordinates marbleCoordinates 0063 = Marble::GeoDataCoordinates(coordinates.lon(), coordinates.lat(), 0.0, 0064 Marble::GeoDataCoordinates::Degree); 0065 lineString.append(marbleCoordinates); 0066 0067 const auto &dateTime = times.at(i).at(j); 0068 dateTimes.append(dateTime); 0069 trackPoints[dateTime] = coordinates; 0070 } 0071 0072 const auto box = lineString.latLonAltBox(); 0073 if (marbleTrackBox.isEmpty()) { 0074 marbleTrackBox = box; 0075 } else { 0076 marbleTrackBox |= box; 0077 } 0078 marbleTracks.append(lineString); 0079 } 0080 0081 m_marbleTracks.append(marbleTracks); 0082 m_marbleTrackBoxes.append(marbleTrackBox); 0083 0084 std::sort(dateTimes.begin(), dateTimes.end()); 0085 m_dateTimes.append(dateTimes); 0086 m_trackPoints.append(trackPoints); 0087 0088 m_loadedFiles.append(canonicalPath(path)); 0089 const QFileInfo info(path); 0090 m_displayFileNames.append(info.completeBaseName()); 0091 0092 const auto modelIndex = index(m_displayFileNames.count() - 1, 0); 0093 Q_EMIT dataChanged(modelIndex, modelIndex, { Qt::DisplayRole }); 0094 } 0095 0096 void GeoDataModel::removeTrack(int row) 0097 { 0098 beginRemoveRows(QModelIndex(), row, row); 0099 const auto modelIndex = index(row, 0); 0100 m_loadedFiles.remove(row); 0101 m_displayFileNames.remove(row); 0102 m_marbleTracks.remove(row); 0103 m_marbleTrackBoxes.remove(row); 0104 m_dateTimes.remove(row); 0105 m_trackPoints.remove(row); 0106 Q_EMIT dataChanged(modelIndex, modelIndex, { Qt::DisplayRole }); 0107 endRemoveRows(); 0108 } 0109 0110 void GeoDataModel::removeAllTracks() 0111 { 0112 const auto lastRow = m_loadedFiles.count() - 1; 0113 const auto firstModelIndex = index(0, 0); 0114 const auto lastModelIndex = index(lastRow, 0); 0115 beginRemoveRows(QModelIndex(), 0, lastRow); 0116 m_loadedFiles.clear(); 0117 m_displayFileNames.clear(); 0118 m_marbleTracks.clear(); 0119 m_marbleTrackBoxes.clear(); 0120 m_dateTimes.clear(); 0121 m_trackPoints.clear(); 0122 Q_EMIT dataChanged(firstModelIndex, lastModelIndex, { Qt::DisplayRole }); 0123 endRemoveRows(); 0124 } 0125 0126 QString GeoDataModel::canonicalPath(const QString &path) const 0127 { 0128 const QFileInfo info(path); 0129 return info.canonicalFilePath(); 0130 } 0131 0132 Marble::GeoDataLatLonAltBox GeoDataModel::trackBox(const QString &path) const 0133 { 0134 return m_marbleTrackBoxes.at(m_loadedFiles.indexOf(canonicalPath(path))); 0135 } 0136 0137 Coordinates GeoDataModel::trackBoxCenter(const QString &path) const 0138 { 0139 const auto center = trackBox(path).center(); 0140 return Coordinates(center.longitude(Marble::GeoDataCoordinates::Degree), 0141 center.latitude(Marble::GeoDataCoordinates::Degree), 0142 0.0, 0143 true); 0144 } 0145 0146 Marble::GeoDataLatLonAltBox GeoDataModel::trackBox(const QModelIndex &index) const 0147 { 0148 return m_marbleTrackBoxes.at(index.row()); 0149 } 0150 0151 const QVector<QVector<Marble::GeoDataLineString>> &GeoDataModel::marbleTracks() const 0152 { 0153 return m_marbleTracks; 0154 } 0155 0156 const QVector<QVector<QDateTime>> &GeoDataModel::dateTimes() const 0157 { 0158 return m_dateTimes; 0159 } 0160 0161 const QVector<QHash<QDateTime, Coordinates>> &GeoDataModel::trackPoints() const 0162 { 0163 return m_trackPoints; 0164 } 0165 0166 Qt::DropActions GeoDataModel::supportedDropActions() const 0167 { 0168 return Qt::CopyAction | Qt::MoveAction; 0169 } 0170 0171 Qt::ItemFlags GeoDataModel::flags(const QModelIndex &index) const 0172 { 0173 Qt::ItemFlags defaultFlags = QAbstractListModel::flags(index); 0174 0175 if (index.isValid()) { 0176 return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags; 0177 } else { 0178 return Qt::ItemIsDropEnabled | defaultFlags; 0179 } 0180 } 0181 0182 bool GeoDataModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int, int, 0183 const QModelIndex &) const 0184 { 0185 if (! (action & (Qt::CopyAction | Qt::MoveAction)) || ! data->hasUrls()) { 0186 return false; 0187 } 0188 0189 if (MimeHelper::getUsablePaths(KGeoTag::DroppedOnTrackList, data).isEmpty()) { 0190 return false; 0191 } 0192 0193 return true; 0194 } 0195 0196 bool GeoDataModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int, int, 0197 const QModelIndex &) 0198 { 0199 if (! (action & (Qt::CopyAction | Qt::MoveAction)) || ! data->hasUrls()) { 0200 return false; 0201 } 0202 0203 Q_EMIT requestAddFiles(MimeHelper::getUsablePaths(KGeoTag::DroppedOnTrackList, data)); 0204 0205 return true; 0206 }