File indexing completed on 2024-05-12 12:54:41
0001 // SPDX-FileCopyrightText: 2023 Tobias Fella <tobias.fella@kde.org> 0002 // SPDX-License-Identifier: GPL-2.0-or-later 0003 0004 #include "locationsmodel.h" 0005 0006 using namespace Quotient; 0007 0008 LocationsModel::LocationsModel(QObject *parent) 0009 : QAbstractListModel(parent) 0010 { 0011 connect(this, &LocationsModel::roomChanged, this, [this]() { 0012 for (const auto &event : m_room->messageEvents()) { 0013 if (!is<RoomMessageEvent>(*event)) { 0014 continue; 0015 } 0016 if (event->contentJson()["msgtype"] == "m.location") { 0017 const auto &e = *event; 0018 addLocation(eventCast<const RoomMessageEvent>(&e)); 0019 } 0020 } 0021 connect(m_room, &NeoChatRoom::aboutToAddHistoricalMessages, this, [this](const auto &events) { 0022 for (const auto &event : events) { 0023 if (!is<RoomMessageEvent>(*event)) { 0024 continue; 0025 } 0026 if (event->contentJson()["msgtype"] == "m.location") { 0027 const auto &e = *event; 0028 addLocation(eventCast<const RoomMessageEvent>(&e)); 0029 } 0030 } 0031 }); 0032 connect(m_room, &NeoChatRoom::aboutToAddNewMessages, this, [this](const auto &events) { 0033 for (const auto &event : events) { 0034 if (!is<RoomMessageEvent>(*event)) { 0035 continue; 0036 } 0037 if (event->contentJson()["msgtype"] == "m.location") { 0038 const auto &e = *event; 0039 addLocation(eventCast<const RoomMessageEvent>(&e)); 0040 } 0041 } 0042 }); 0043 }); 0044 0045 connect(this, &LocationsModel::rowsInserted, this, &LocationsModel::boundingBoxChanged); 0046 } 0047 0048 void LocationsModel::addLocation(const RoomMessageEvent *event) 0049 { 0050 const auto uri = event->contentJson()["org.matrix.msc3488.location"]["uri"].toString(); 0051 const auto parts = uri.mid(4).split(QLatin1Char(',')); 0052 if (parts.size() < 2) { 0053 qWarning() << "invalid geo: URI" << uri; 0054 return; 0055 } 0056 const auto latitude = parts[0].toFloat(); 0057 const auto longitude = parts[1].toFloat(); 0058 beginInsertRows(QModelIndex(), m_locations.size(), m_locations.size() + 1); 0059 m_locations += LocationData{ 0060 .eventId = event->id(), 0061 .latitude = latitude, 0062 .longitude = longitude, 0063 .content = event->contentJson(), 0064 .author = dynamic_cast<NeoChatUser *>(m_room->user(event->senderId())), 0065 }; 0066 endInsertRows(); 0067 } 0068 0069 NeoChatRoom *LocationsModel::room() const 0070 { 0071 return m_room; 0072 } 0073 0074 void LocationsModel::setRoom(NeoChatRoom *room) 0075 { 0076 if (m_room) { 0077 disconnect(this, nullptr, m_room, nullptr); 0078 } 0079 m_room = room; 0080 Q_EMIT roomChanged(); 0081 } 0082 0083 QHash<int, QByteArray> LocationsModel::roleNames() const 0084 { 0085 return { 0086 {LongitudeRole, "longitude"}, 0087 {LatitudeRole, "latitude"}, 0088 {TextRole, "text"}, 0089 {AssetRole, "asset"}, 0090 {AuthorRole, "author"}, 0091 }; 0092 } 0093 0094 QVariant LocationsModel::data(const QModelIndex &index, int roleName) const 0095 { 0096 auto row = index.row(); 0097 if (roleName == LongitudeRole) { 0098 return m_locations[row].longitude; 0099 } else if (roleName == LatitudeRole) { 0100 return m_locations[row].latitude; 0101 } else if (roleName == TextRole) { 0102 return m_locations[row].content["body"_ls].toString(); 0103 } else if (roleName == AssetRole) { 0104 return m_locations[row].content["org.matrix.msc3488.asset"_ls].toObject()["type"_ls].toString(); 0105 } else if (roleName == AuthorRole) { 0106 return m_room->getUser(m_locations[row].author); 0107 } 0108 return {}; 0109 } 0110 0111 int LocationsModel::rowCount(const QModelIndex &parent) const 0112 { 0113 Q_UNUSED(parent); 0114 return m_locations.size(); 0115 } 0116 0117 QRectF LocationsModel::boundingBox() const 0118 { 0119 QRectF bbox(QPointF(180.0, 90.0), QPointF(-180.0, -90.0)); 0120 for (auto i = 0; i < rowCount(); ++i) { 0121 const auto lat = data(index(i, 0), LatitudeRole).toDouble(); 0122 const auto lon = data(index(i, 0), LongitudeRole).toDouble(); 0123 0124 bbox.setLeft(std::min(bbox.left(), lon)); 0125 bbox.setRight(std::max(bbox.right(), lon)); 0126 bbox.setTop(std::min(bbox.top(), lat)); 0127 bbox.setBottom(std::max(bbox.bottom(), lat)); 0128 } 0129 return bbox; 0130 } 0131 0132 #include "moc_locationsmodel.cpp"