diff --git a/autotests/roomtest.cpp b/autotests/roomtest.cpp index 16ed8c9b..630d2669 100644 --- a/autotests/roomtest.cpp +++ b/autotests/roomtest.cpp @@ -1,376 +1,371 @@ /* Copyright (c) 2017-2019 Montel Laurent This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License or ( at your option ) version 3 or, at the discretion of KDE e.V. ( which shall act as a proxy as in section 14 of the GPLv3 ), any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "roomtest.h" #include "room.h" #include "ruqola_autotest_helper.h" #include "model/usersforroommodel.h" #include "model/usersforroomfilterproxymodel.h" #include "model/filesforroomfilterproxymodel.h" #include "model/filesforroommodel.h" #include "model/threadsfilterproxymodel.h" #include "model/threadsmodel.h" #include #include #include QTEST_GUILESS_MAIN(RoomTest) RoomTest::RoomTest(QObject *parent) : QObject(parent) { } void RoomTest::shouldHaveDefaultValue() { Room input(nullptr); QVERIFY(input.usersModelForRoom()); QVERIFY(input.usersModelForRoomProxyModel()); - QVERIFY(input.threadsModelForRoom()); - QVERIFY(input.threadsModelForRoomFilterProxyModel()); - QCOMPARE(input.threadsModelForRoomFilterProxyModel()->sourceModel(), input.threadsModelForRoom()); - - QCOMPARE(input.usersModelForRoomProxyModel()->sourceModel(), input.usersModelForRoom()); QVERIFY(input.messageModel()); QVERIFY(input.inputMessage().isEmpty()); QVERIFY(input.description().isEmpty()); QVERIFY(input.announcement().isEmpty()); QVERIFY(!input.readOnly()); //Add more QCOMPARE(input.userMentions(), 0); QCOMPARE(input.unread(), 0); QCOMPARE(input.blocked(), false); QCOMPARE(input.blocker(), false); QVERIFY(input.roles().isEmpty()); QVERIFY(!input.archived()); QVERIFY(input.name().isEmpty()); QVERIFY(input.ignoredUsers().isEmpty()); QVERIFY(input.e2EKey().isEmpty()); QVERIFY(input.e2eKeyId().isEmpty()); QVERIFY(!input.encrypted()); QVERIFY(!input.alert()); QVERIFY(!input.readOnly()); QVERIFY(!input.joinCodeRequired()); QVERIFY(!input.wasInitialized()); QVERIFY(input.rolesForRooms().isEmpty()); QVERIFY(input.parentRid().isEmpty()); QVERIFY(!input.broadcast()); QVERIFY(input.fName().isEmpty()); } //TODO add notification, userMentions too void RoomTest::shouldSerialized() { Room input(nullptr); input.setRoomId(QStringLiteral("foo")); input.setChannelType(QStringLiteral("p")); input.setName(QStringLiteral("d")); input.setAnnouncement(QStringLiteral("AA")); input.setRoomCreatorUserName(QStringLiteral("pp")); input.setRoomCreatorUserId(QStringLiteral("sdfsdfs")); input.setTopic(QStringLiteral("topic")); input.setMutedUsers(QStringList{QStringLiteral("mutedUsers"), QStringLiteral("muted2")}); input.setJitsiTimeout(55); input.setReadOnly(true); input.setUnread(66); input.setSelected(true); input.setFavorite(true); input.setAlert(true); input.setOpen(true); input.setBlocker(true); input.setBlocked(true); input.setArchived(true); input.setDescription(QStringLiteral("dd")); input.setUserMentions(3); input.setRoles({QStringLiteral("foo"), QStringLiteral("bla")}); input.setIgnoredUsers({QStringLiteral("gg"), QStringLiteral("gg2")}); input.setJoinCodeRequired(true); const QByteArray ba = Room::serialize(&input); //qDebug() << QJsonObject(QJsonDocument::fromBinaryData(ba).object()); Room *output = Room::fromJSon(QJsonObject(QJsonDocument::fromBinaryData(ba).object())); //qDebug() << "after" << QJsonObject(QJsonDocument::fromBinaryData(Room::serialize(output)).object()); QVERIFY(input.isEqual(*output)); delete output; } void RoomTest::shouldEmitSignals() { Room input(nullptr); QSignalSpy spyNameChanged(&input, &Room::nameChanged); QSignalSpy spyannouncementChanged(&input, &Room::announcementChanged); QSignalSpy spytopicChanged(&input, &Room::topicChanged); QSignalSpy spyfavoriteChanged(&input, &Room::favoriteChanged); QSignalSpy spyalertChanged(&input, &Room::alertChanged); QSignalSpy spyreadOnlyChanged(&input, &Room::readOnlyChanged); QSignalSpy spyunreadChanged(&input, &Room::unreadChanged); QSignalSpy spyblockerChanged(&input, &Room::blockerChanged); QSignalSpy spyarchivedChanged(&input, &Room::archivedChanged); QSignalSpy spydescriptionChanged(&input, &Room::descriptionChanged); QSignalSpy spyblockedChanged(&input, &Room::blockedChanged); QSignalSpy spyrolesChanged(&input, &Room::rolesChanged); QSignalSpy spyignoredUsersChanged(&input, &Room::ignoredUsersChanged); QSignalSpy spymutedUsersChanged(&input, &Room::mutedUsersChanged); QSignalSpy spyencryptedChanged(&input, &Room::encryptedChanged); QSignalSpy spyjoinCodeRequiredChanged(&input, &Room::joinCodeRequiredChanged); QSignalSpy spychannelTypeChanged(&input, &Room::channelTypeChanged); QSignalSpy spyparentRidChanged(&input, &Room::parentRidChanged); input.setRoomId(QStringLiteral("foo")); input.setChannelType(QStringLiteral("p")); input.setName(QStringLiteral("d")); input.setAnnouncement(QStringLiteral("AA")); input.setRoomCreatorUserName(QStringLiteral("pp")); input.setRoomCreatorUserId(QStringLiteral("sdfsdfs")); input.setTopic(QStringLiteral("topic")); input.setMutedUsers(QStringList{QStringLiteral("mutedUsers"), QStringLiteral("muted2")}); input.setJitsiTimeout(55); input.setReadOnly(true); input.setUnread(66); input.setSelected(true); input.setFavorite(true); input.setAlert(true); input.setOpen(true); input.setBlocker(true); input.setBlocked(true); input.setArchived(true); input.setEncrypted(true); input.setJoinCodeRequired(true); input.setDescription(QStringLiteral("ddd")); input.setRoles({QStringLiteral("bla"), QStringLiteral("blu")}); input.setIgnoredUsers({QStringLiteral("bla"), QStringLiteral("blu3")}); input.setParentRid(QStringLiteral("bla")); QCOMPARE(spyNameChanged.count(), 1); QCOMPARE(spyannouncementChanged.count(), 1); QCOMPARE(spytopicChanged.count(), 1); QCOMPARE(spyfavoriteChanged.count(), 1); QCOMPARE(spyalertChanged.count(), 1); QCOMPARE(spyreadOnlyChanged.count(), 1); QCOMPARE(spyunreadChanged.count(), 1); QCOMPARE(spyblockerChanged.count(), 1); QCOMPARE(spyarchivedChanged.count(), 1); QCOMPARE(spyblockedChanged.count(), 1); QCOMPARE(spydescriptionChanged.count(), 1); QCOMPARE(spyrolesChanged.count(), 1); QCOMPARE(spyignoredUsersChanged.count(), 1); QCOMPARE(spymutedUsersChanged.count(), 1); QCOMPARE(spyencryptedChanged.count(), 1); QCOMPARE(spyjoinCodeRequiredChanged.count(), 1); QCOMPARE(spychannelTypeChanged.count(), 1); QCOMPARE(spyparentRidChanged.count(), 1); } void RoomTest::shouldChangeInputMessage() { Room input(nullptr); QString inputMsg = QStringLiteral("Foo"); input.setInputMessage(inputMsg); QCOMPARE(input.inputMessage(), inputMsg); inputMsg = QString(); input.setInputMessage(inputMsg); QCOMPARE(input.inputMessage(), inputMsg); inputMsg = QStringLiteral("foo"); input.setInputMessage(inputMsg); QCOMPARE(input.inputMessage(), inputMsg); } void RoomTest::shouldParseRoom_data() { QTest::addColumn("fileName"); //Missing _updatedAt/ts/_id/groupMentions/ls/roles (implement roles ! ) QTest::newRow("notification-room") << QStringLiteral("notification-room"); QTest::newRow("unread-usermentions-room") << QStringLiteral("unread-usermentions-room"); QTest::newRow("muted-users") << QStringLiteral("muted-users"); QTest::newRow("userignored-room") << QStringLiteral("userignored-room"); } void RoomTest::shouldParseRoom() { QFETCH(QString, fileName); const QString originalJsonFile = QLatin1String(RUQOLA_DATA_DIR) + QStringLiteral("/room/") + fileName + QStringLiteral(".json"); QFile f(originalJsonFile); QVERIFY(f.open(QIODevice::ReadOnly)); const QByteArray content = f.readAll(); f.close(); const QJsonDocument doc = QJsonDocument::fromJson(content); const QJsonObject fields = doc.object(); Room r; r.parseSubscriptionRoom(fields); //qDebug() << " fields"<("fileNameinit"); QTest::addColumn("fileNameupdate"); //Missing _updatedAt/ts/_id/groupMentions/ls/roles (implement roles ! ) QTest::newRow("notification-roomupdate") << QStringLiteral("notification-room") << (QStringList() <("fileNameinit"); QTest::addColumn("UpdateRoomfileNames"); QTest::addColumn("UpdateSubscriptionFileNames"); //Missing _updatedAt/ts/_id/groupMentions/ls/roles (implement roles ! ) QTest::newRow("notification-roomupdate") << QStringLiteral("notification-room") << (QStringList() << QStringLiteral("notification-roomupdate1")) << (QStringList() << QStringLiteral("notification-roomsubscription1")); QTest::newRow("room-blocked") << QStringLiteral("room-blocked") << (QStringList() << QStringLiteral("room-blockedupdate1")) << QStringList(); QTest::newRow("room-encryption") << QStringLiteral("room-encryption") << (QStringList() << QStringLiteral("room-encryptionupdate1")) << QStringList(); QTest::newRow("room-broadcasted") << QStringLiteral("room-broadcasted") << (QStringList() << QStringLiteral("room-broadcastedupdate1")) << QStringList(); } void RoomTest::shouldParseRoomAndUpdateSubscription() { QFETCH(QString, fileNameinit); QFETCH(QStringList, UpdateRoomfileNames); QFETCH(QStringList, UpdateSubscriptionFileNames); const QString originalJsonFile = QLatin1String(RUQOLA_DATA_DIR) + QStringLiteral("/room-updated/") + fileNameinit + QStringLiteral(".json"); QFile f(originalJsonFile); QVERIFY(f.open(QIODevice::ReadOnly)); const QByteArray content = f.readAll(); f.close(); const QJsonDocument doc = QJsonDocument::fromJson(content); const QJsonObject fields = doc.object(); Room r; r.parseSubscriptionRoom(fields); for (const QString &updateFile : UpdateRoomfileNames) { const QString originalUpdateJsonFile = QLatin1String(RUQOLA_DATA_DIR) + QStringLiteral("/room-update-subscription/") + updateFile + QStringLiteral(".json"); QFile f(originalUpdateJsonFile); QVERIFY(f.open(QIODevice::ReadOnly)); const QByteArray content = f.readAll(); f.close(); const QJsonDocument doc = QJsonDocument::fromJson(content); const QJsonObject fields = doc.object(); r.parseUpdateRoom(fields); } for (const QString &updateFile : UpdateSubscriptionFileNames) { const QString originalUpdateJsonFile = QLatin1String(RUQOLA_DATA_DIR) + QStringLiteral("/room-update-subscription/") + updateFile + QStringLiteral(".json"); QFile f(originalUpdateJsonFile); QVERIFY(f.open(QIODevice::ReadOnly)); const QByteArray content = f.readAll(); f.close(); const QJsonDocument doc = QJsonDocument::fromJson(content); const QJsonObject fields = doc.object(); r.updateSubscriptionRoom(fields); } //qDebug() << " fields"< * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "roommodel.h" #include "ruqola_debug.h" #include "rocketchataccount.h" #include "usersforroommodel.h" #include "threadsmodel.h" #include "roomwrapper.h" #include #include #include #include #include RoomModel::RoomModel(RocketChatAccount *account, QObject *parent) : QAbstractListModel(parent) , mRocketChatAccount(account) { } RoomModel::~RoomModel() { #if 0 if (mRocketChatAccount && mRocketChatAccount->settings()) { const QString cachePath = mRocketChatAccount->settings()->cacheBasePath(); if (cachePath.isEmpty()) { qCWarning(RUQOLA_LOG) << " Cache Path is not defined"; return; } QDir cacheDir(cachePath); if (!cacheDir.exists(cacheDir.path())) { cacheDir.mkpath(cacheDir.path()); } QFile f(cacheDir.absoluteFilePath(QStringLiteral("rooms"))); if (f.open(QIODevice::WriteOnly)) { QDataStream out(&f); for (Room *m : qAsConst(mRoomsList)) { qCDebug(RUQOLA_LOG) << " save cache for room " << m->name(); const QByteArray ms = Room::serialize(m); out.writeBytes(ms.constData(), ms.size()); } } } #endif qDeleteAll(mRoomsList); } void RoomModel::clear() { if (!mRoomsList.isEmpty()) { beginRemoveRows(QModelIndex(), 0, rowCount() - 1); qDeleteAll(mRoomsList); mRoomsList.clear(); endRemoveRows(); } } Room *RoomModel::findRoom(const QString &roomID) const { for (Room *r : qAsConst(mRoomsList)) { if (r->roomId() == roomID) { return r; } } return nullptr; } RoomWrapper *RoomModel::findRoomWrapper(const QString &roomID) const { for (Room *r : qAsConst(mRoomsList)) { if (r->roomId() == roomID) { RoomWrapper *wrapper = new RoomWrapper(r); return wrapper; } } return nullptr; } // Clear data and refill it with data in the cache, if there is void RoomModel::reset() { clear(); if (!mRocketChatAccount) { return; } if (mRocketChatAccount->settings()->cacheBasePath().isEmpty()) { return; } //Laurent disable cache for the moment /* QDir cacheDir(Ruqola::self()->cacheBasePath()); // load cache if (cacheDir.exists(cacheDir.path())) { QFile f(cacheDir.absoluteFilePath(QStringLiteral("rooms"))); if (f.open(QIODevice::ReadOnly)) { QDataStream in(&f); while (!f.atEnd()) { char *byteArray; quint32 length; in.readBytes(byteArray, length); QByteArray arr = QByteArray::fromRawData(byteArray, length); Room m = Room::fromJSon(QJsonDocument::fromBinaryData(arr).object()); qDebug() <<" Load from cache room name: " << m.name; addRoom(m.id, m.name, m.selected); } } qCDebug(RUQOLA_LOG) << "Cache Loaded"; } */ } QHash RoomModel::roleNames() const { QHash roles; roles[RoomName] = QByteArrayLiteral("name"); roles[RoomFName] = QByteArrayLiteral("fname"); roles[RoomID] = QByteArrayLiteral("room_id"); roles[RoomSelected] = QByteArrayLiteral("selected"); roles[RoomUnread] = QByteArrayLiteral("unread"); roles[RoomType] = QByteArrayLiteral("type"); roles[RoomOwnerUserName] = QByteArrayLiteral("username"); roles[RoomOwnerUserID] = QByteArrayLiteral("userID"); roles[RoomTopic] = QByteArrayLiteral("topic"); roles[RoomMutedUsers] = QByteArrayLiteral("mutedUsers"); roles[RoomJitsiTimeout] = QByteArrayLiteral("jitsiTimeout"); roles[RoomRo] = QByteArrayLiteral("readOnly"); roles[RoomAnnouncement] = QByteArrayLiteral("announcement"); roles[RoomOpen] = QByteArrayLiteral("open"); roles[RoomAlert] = QByteArrayLiteral("alert"); roles[RoomOrder] = QByteArrayLiteral("roomorder"); roles[RoomFavorite] = QByteArrayLiteral("favorite"); roles[RoomSection] = QByteArrayLiteral("sectionname"); roles[RoomIcon] = QByteArrayLiteral("channelicon"); roles[RoomUserMentions] = QByteArrayLiteral("userMentions"); return roles; } int RoomModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return mRoomsList.size(); } QVariant RoomModel::data(const QModelIndex &index, int role) const { if (index.row() < 0 || index.row() >= mRoomsList.count()) { return QVariant(); } Room *r = mRoomsList.at(index.row()); switch (role) { case RoomModel::RoomName: return r->name(); case RoomModel::RoomFName: return r->displayFName(); case RoomModel::RoomID: return r->roomId(); case RoomModel::RoomSelected: return r->selected(); case RoomModel::RoomType: return r->channelType(); case RoomModel::RoomOwnerUserID: return r->roomCreatorUserId(); case RoomModel::RoomOwnerUserName: return r->roomOwnerUserName(); case RoomModel::RoomTopic: return r->topic(); case RoomModel::RoomMutedUsers: return r->mutedUsers(); case RoomModel::RoomJitsiTimeout: return r->jitsiTimeout(); case RoomModel::RoomRo: return r->readOnly(); case RoomModel::RoomAnnouncement: return r->announcement(); case RoomModel::RoomUnread: return r->unread(); case RoomModel::RoomOpen: return r->open(); case RoomModel::RoomAlert: return r->alert(); case RoomModel::RoomFavorite: return r->favorite(); case RoomModel::RoomSection: return sectionName(r); case RoomModel::RoomOrder: return order(r); case RoomModel::RoomIcon: return icon(r); case RoomModel::RoomOtr: //TODO implement it. return {}; case RoomModel::RoomUserMentions: return r->userMentions(); case RoomModel::RoomIgnoredUsers: return r->ignoredUsers(); } return {}; } void RoomModel::addRoom(const QString &roomID, const QString &roomName, bool selected) { if (roomID.isEmpty() || roomName.isEmpty()) { qCDebug(RUQOLA_LOG) << " Impossible to add a room"; return; } qCDebug(RUQOLA_LOG) << "Adding room : roomId: " << roomID << " room Name " << roomName << " isSelected : " << selected; Room *r = createNewRoom(); r->setRoomId(roomID); r->setName(roomName); r->setSelected(selected); addRoom(r); } Room *RoomModel::createNewRoom() { Room *r = new Room(mRocketChatAccount); connect(r, &Room::alertChanged, this, &RoomModel::needToUpdateNotification); connect(r, &Room::unreadChanged, this, &RoomModel::needToUpdateNotification); return r; } void RoomModel::getUnreadAlertFromAccount(bool &hasAlert, int &nbUnread) { for (int i = 0; i < mRoomsList.count(); ++i) { if (mRoomsList.at(i)->open()) { if (mRoomsList.at(i)->alert()) { hasAlert = true; } nbUnread += mRoomsList.at(i)->unread(); } } } void RoomModel::updateSubscriptionRoom(const QJsonObject &roomData) { //TODO fix me! //Use "_id" QString rId = roomData.value(QLatin1String("rid")).toString(); if (rId.isEmpty()) { rId = roomData.value(QLatin1String("_id")).toString(); } if (!rId.isEmpty()) { const int roomCount = mRoomsList.size(); for (int i = 0; i < roomCount; ++i) { if (mRoomsList.at(i)->roomId() == rId) { qCDebug(RUQOLA_LOG) << " void RoomModel::updateSubscriptionRoom(const QJsonArray &array) room found"; Room *room = mRoomsList.at(i); room->updateSubscriptionRoom(roomData); Q_EMIT dataChanged(createIndex(i, 0), createIndex(i, 0)); break; } } } else { //qCWarning(RUQOLA_LOG) << "RoomModel::updateRoom incorrect jsonobject "<< roomData; qWarning() << "RoomModel::updateSubscriptionRoom incorrect jsonobject "<< roomData; } } QString RoomModel::insertRoom(const QJsonObject &room) { Room *r = createNewRoom(); r->parseInsertRoom(room); qCDebug(RUQOLA_LOG) << "Inserting room" << r->name() << r->roomId() << r->topic(); addRoom(r); return r->roomId(); } Room *RoomModel::addRoom(const QJsonObject &room) { Room *r = createNewRoom(); r->parseSubscriptionRoom(room); qCDebug(RUQOLA_LOG) << "Adding room subscription" << r->name() << r->roomId() << r->topic(); addRoom(r); return r; } void RoomModel::addRoom(Room *room) { qCDebug(RUQOLA_LOG) << " void RoomModel::addRoom(const Room &room)"<name(); int roomCount = mRoomsList.count(); for (int i = 0; i < roomCount; ++i) { if (mRoomsList.at(i)->roomId() == room->roomId()) { delete mRoomsList.takeAt(i); break; } } roomCount = mRoomsList.count(); beginInsertRows(QModelIndex(), roomCount, roomCount); qCDebug(RUQOLA_LOG) << "Inserting room at position" <roomId() == id) { beginRemoveRows(QModelIndex(), i, i); mRoomsList.remove(i); endRemoveRows(); break; } } } else if (actionName == QStringLiteral("inserted")) { qCDebug(RUQOLA_LOG) << "INSERT ROOM name " << roomData.value(QLatin1String("name")) << " rid " << roomData.value(QLatin1String("rid")); //TODO fix me! addRoom(roomData); //addRoom(roomData.value(QLatin1String("rid")).toString(), roomData.value(QLatin1String("name")).toString(), false); } else if (actionName == QStringLiteral("updated")) { //qCDebug(RUQOLA_LOG) << "UPDATE ROOM name " << roomData.value(QLatin1String("name")).toString() << " rid " << roomData.value(QLatin1String("rid")) << " roomData " << roomData; qDebug() << "UPDATE ROOM name " << roomData.value(QLatin1String("name")).toString() << " rid " << roomData.value(QLatin1String("rid")) << " roomData " << roomData; updateSubscriptionRoom(roomData); } else if (actionName == QStringLiteral("changed")) { //qDebug() << "CHANGED ROOM name " << roomData.value(QLatin1String("name")).toString() << " rid " << roomData.value(QLatin1String("rid")) << " roomData " << roomData; qCDebug(RUQOLA_LOG) << "CHANGED ROOM name " << roomData.value(QLatin1String("name")).toString() << " rid " << roomData.value(QLatin1String("rid")) << " roomData " << roomData; qCDebug(RUQOLA_LOG) << "RoomModel::updateSubscription Not implementer changed room yet" << array; updateRoom(roomData); } else { qCDebug(RUQOLA_LOG) << "RoomModel::updateSubscription Undefined type" << actionName; } } void RoomModel::updateRoom(const QJsonObject &roomData) { qCDebug(RUQOLA_LOG) << " void RoomModel::updateRoom(const QJsonObject &roomData)"; //TODO fix me! //Use "_id" QString rId = roomData.value(QLatin1String("rid")).toString(); if (rId.isEmpty()) { rId = roomData.value(QLatin1String("_id")).toString(); } if (!rId.isEmpty()) { const int roomCount = mRoomsList.size(); for (int i = 0; i < roomCount; ++i) { if (mRoomsList.at(i)->roomId() == rId) { qCDebug(RUQOLA_LOG) << " void RoomModel::updateRoom(const QJsonArray &array) room found"; Room *room = mRoomsList.at(i); room->parseUpdateRoom(roomData); Q_EMIT dataChanged(createIndex(i, 0), createIndex(i, 0)); break; } } } else { //qCWarning(RUQOLA_LOG) << "RoomModel::updateRoom incorrect jsonobject "<< roomData; qWarning() << "RoomModel::updateRoom incorrect jsonobject "<< roomData; } } void RoomModel::userStatusChanged(const User &user) { const int roomCount = mRoomsList.count(); for (int i = 0; i < roomCount; ++i) { Room *room = mRoomsList.at(i); if (room->name() == user.userName()) { const QModelIndex idx = createIndex(i, 0); Q_EMIT dataChanged(idx, idx); } room->usersModelForRoom()->userStatusChanged(user); } } UsersForRoomModel *RoomModel::usersModelForRoom(const QString &roomId) const { const int roomCount = mRoomsList.count(); for (int i = 0; i < roomCount; ++i) { Room *room = mRoomsList.at(i); if (room->roomId() == roomId) { return room->usersModelForRoom(); } } qCWarning(RUQOLA_LOG) << " Users model for room undefined !"; return nullptr; } UsersForRoomFilterProxyModel *RoomModel::usersForRoomFilterProxyModel(const QString &roomId) const { const int roomCount = mRoomsList.count(); for (int i = 0; i < roomCount; ++i) { Room *room = mRoomsList.at(i); if (room->roomId() == roomId) { return room->usersModelForRoomProxyModel(); } } return {}; } MessageModel *RoomModel::messageModel(const QString &roomId) const { const int roomCount = mRoomsList.count(); for (int i = 0; i < roomCount; ++i) { Room *room = mRoomsList.at(i); if (room->roomId() == roomId) { return room->messageModel(); } } return {}; } -ThreadsModel *RoomModel::threadsModelForRoom(const QString &roomId) const -{ - const int roomCount = mRoomsList.count(); - for (int i = 0; i < roomCount; ++i) { - Room *room = mRoomsList.at(i); - if (room->roomId() == roomId) { - return room->threadsModelForRoom(); - } - } - return {}; -} - -ThreadsFilterProxyModel *RoomModel::threadsModelForRoomProxyModel(const QString &roomId) const -{ - const int roomCount = mRoomsList.count(); - for (int i = 0; i < roomCount; ++i) { - Room *room = mRoomsList.at(i); - if (room->roomId() == roomId) { - return room->threadsModelForRoomFilterProxyModel(); - } - } - return {}; -} - QString RoomModel::inputMessage(const QString &roomId) const { const int roomCount = mRoomsList.count(); for (int i = 0; i < roomCount; ++i) { Room *room = mRoomsList.at(i); if (room->roomId() == roomId) { return room->inputMessage(); } } return {}; } void RoomModel::setInputMessage(const QString &roomId, const QString &inputMessage) { const int roomCount = mRoomsList.count(); for (int i = 0; i < roomCount; ++i) { Room *room = mRoomsList.at(i); if (room->roomId() == roomId) { room->setInputMessage(inputMessage); return; } } } QString RoomModel::sectionName(Room *r) const { QString str; if (r->favorite()) { str = i18n("Favorites"); } else { const QString channelTypeStr = r->channelType(); if (channelTypeStr == QLatin1String("p")) { if (r->parentRid().isEmpty()) { str = i18n("Rooms"); } else { str = i18n("Discussions"); } } else if (channelTypeStr == QLatin1String("c")) { str = i18n("Rooms"); } else if (channelTypeStr == QLatin1String("d")) { str = i18n("Private Message"); } } return str; } int RoomModel::order(Room *r) const { int order = 0; //First item are favorites channels if (!r->favorite()) { order += 10; } const QString channelTypeStr = r->channelType(); if (channelTypeStr == QLatin1String("c")) { order += 1; } else if (channelTypeStr == QLatin1String("d")) { order += 2; } else if (channelTypeStr == QLatin1String("p")) { if (r->parentRid().isEmpty()) { order += 1; } else { order += 4; } } else { qCDebug(RUQOLA_LOG) << r->name() << "has unhandled channel type" << channelTypeStr; order += 5; } return order; } QIcon RoomModel::icon(Room *r) const { if (r->channelType() == QLatin1String("c")) { if (r->unread() > 0 || r->alert()) { return QIcon::fromTheme(QStringLiteral("irc-channel-active")); } else { return QIcon::fromTheme(QStringLiteral("irc-channel-inactive")); } } else if (r->channelType() == QLatin1String("d")) { const QString userStatusIconFileName = mRocketChatAccount ? mRocketChatAccount->userStatusIconFileName(r->name()) : QString(); if (userStatusIconFileName.isEmpty()) { return QIcon::fromTheme(QStringLiteral("user-available")); } else { return QIcon::fromTheme(userStatusIconFileName); } } else if (r->channelType() == QLatin1String("p")) { return QIcon::fromTheme(QStringLiteral("lock")); } return {}; } diff --git a/src/ruqolacore/model/roommodel.h b/src/ruqolacore/model/roommodel.h index defe044d..bd8d113f 100644 --- a/src/ruqolacore/model/roommodel.h +++ b/src/ruqolacore/model/roommodel.h @@ -1,138 +1,134 @@ /* * Copyright 2016 Riccardo Iaconelli * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #ifndef ROOMMODEL_H #define ROOMMODEL_H #include "libruqolacore_export.h" #include "room.h" #include "user.h" #include #include class RoomWrapper; class RocketChatAccount; class MessageModel; -class ThreadsModel; -class ThreadsFilterProxyModel; class LIBRUQOLACORE_EXPORT RoomModel : public QAbstractListModel { Q_OBJECT public: enum RoomRoles { RoomName = Qt::UserRole + 1, RoomFName, RoomSelected, RoomID, RoomUnread, RoomType, RoomOwnerUserName, //created by UserName RoomOwnerUserID, RoomTopic, RoomMutedUsers, RoomJitsiTimeout, RoomRo, RoomAnnouncement, RoomOpen, RoomAlert, RoomOrder, RoomFavorite, RoomSection, RoomIcon, RoomOtr, RoomUserMentions, RoomIgnoredUsers, }; Q_ENUM(RoomRoles) explicit RoomModel(RocketChatAccount *account = nullptr, QObject *parent = nullptr); ~RoomModel() override; Q_REQUIRED_RESULT int rowCount(const QModelIndex &parent = QModelIndex()) const override; Q_REQUIRED_RESULT QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; /** * @brief Constructs room object from @param roomID and @param roomName and @param selected, then calls @method addRoom * * @param roomID The unique room ID * @param roomName The name of the room * @param selected True if room if @param roomID is selected, else false */ Q_INVOKABLE void addRoom(const QString &roomID, const QString &roomName, bool selected = false); /** * @brief Finds a room with @param roomID in m_roomsList * * @param roomID The ID of the room to find * @return RoomWrapper Pointer, The pointer to room with @param roomID in m_roomsList, if exists. Else return a new RoomWrapper object */ RoomWrapper *findRoomWrapper(const QString &roomID) const; //Clear data and refill it with data in the cache, if there is void reset(); void clear(); void updateSubscription(const QJsonArray &array); void updateRoom(const QJsonObject &array); Room *addRoom(const QJsonObject &room); /** * @brief Adds a room to m_roomsList with @param room * * @param room The room to be added */ void addRoom(Room *room); void removeRoom(const QString &roomId); void getUnreadAlertFromAccount(bool &hasAlert, int &nbUnread); void userStatusChanged(const User &user); UsersForRoomModel *usersModelForRoom(const QString &roomId) const; UsersForRoomFilterProxyModel *usersForRoomFilterProxyModel(const QString &roomId) const; MessageModel *messageModel(const QString &roomId) const; Q_REQUIRED_RESULT QHash roleNames() const override; Q_REQUIRED_RESULT QString inputMessage(const QString &roomId) const; void setInputMessage(const QString &roomId, const QString &inputMessage); Q_REQUIRED_RESULT Room *findRoom(const QString &roomID) const; void updateSubscriptionRoom(const QJsonObject &room); Q_REQUIRED_RESULT QString insertRoom(const QJsonObject &room); - ThreadsModel *threadsModelForRoom(const QString &roomId) const; - ThreadsFilterProxyModel *threadsModelForRoomProxyModel(const QString &roomId) const; Q_SIGNALS: void needToUpdateNotification(); private: Q_DISABLE_COPY(RoomModel) Room *createNewRoom(); QIcon icon(Room *r) const; int order(Room *r) const; QString sectionName(Room *r) const; RocketChatAccount *mRocketChatAccount = nullptr; QVector mRoomsList; }; #endif // ROOMMODEL_H diff --git a/src/ruqolacore/room.cpp b/src/ruqolacore/room.cpp index 6689777a..024c23fa 100644 --- a/src/ruqolacore/room.cpp +++ b/src/ruqolacore/room.cpp @@ -1,1125 +1,1106 @@ /* * Copyright 2016 Riccardo Iaconelli * Copyright 2017-2018 Laurent Montel * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "rocketchataccount.h" #include "notificationoptionswrapper.h" #include "room.h" #include "utils.h" #include "ruqola_debug.h" #include "model/usersforroommodel.h" #include "model/usersforroomfilterproxymodel.h" #include "model/messagemodel.h" #include "model/threadsmodel.h" #include "model/threadsfilterproxymodel.h" #include #include #include Room::Room(RocketChatAccount *account, QObject *parent) : QObject(parent) , mRocketChatAccount(account) { mUsersModelForRoom = new UsersForRoomModel(this); mUsersModelForRoom->setObjectName(QStringLiteral("usersforroommodel")); mUsersModelForRoomProxyModel = new UsersForRoomFilterProxyModel(this); mUsersModelForRoomProxyModel->setObjectName(QStringLiteral("usersforroommodelproxymodel")); mUsersModelForRoomProxyModel->setSourceModel(mUsersModelForRoom); mMessageModel = new MessageModel(QString(), mRocketChatAccount, this, this); - - mThreadsModel = new ThreadsModel(this); - mThreadsModel->setObjectName(QStringLiteral("threadsmodel")); - - mThreadsFilterProxyModel = new ThreadsFilterProxyModel(this); - mThreadsFilterProxyModel->setObjectName(QStringLiteral("threadsfiltermodelproxy")); - mThreadsFilterProxyModel->setSourceModel(mThreadsModel); - - //TODO necessary to define mChannelType } bool Room::operator==(const Room &other) const { //qDebug() << " other.id"< we need to clear it. setRoomCreatorUserId(QString()); setRoomCreatorUserName(QString()); } if (json.contains(QLatin1String("prid"))) { setParentRid(json[QStringLiteral("prid")].toString()); } } bool Room::selected() const { return mSelected; } void Room::setSelected(bool selected) { if (mSelected != selected) { mSelected = selected; //Add signal otherwise it's not necessary to check value } } int Room::unread() const { return mUnread; } void Room::setUnread(int unread) { if (mUnread != unread) { mUnread = unread; Q_EMIT unreadChanged(); } } qint64 Room::jitsiTimeout() const { return mJitsiTimeout; } void Room::setJitsiTimeout(const qint64 &jitsiTimeout) { if (mJitsiTimeout != jitsiTimeout) { mJitsiTimeout = jitsiTimeout; Q_EMIT jitsiTimeoutChanged(); } } QStringList Room::mutedUsers() const { return mMutedUsers; } void Room::setMutedUsers(const QStringList &mutedUsers) { if (mMutedUsers != mutedUsers) { mMutedUsers = mutedUsers; Q_EMIT mutedUsersChanged(); } } QString Room::roomCreatorUserId() const { return mRoomCreateUserId; } void Room::setRoomCreatorUserId(const QString &userId) { mRoomCreateUserId = userId; } QString Room::roomOwnerUserName() const { return mRoomCreatorUserName; } void Room::setRoomCreatorUserName(const QString &userName) { mRoomCreatorUserName = userName; } QString Room::roomId() const { return mRoomId; } void Room::setRoomId(const QString &id) { if (mRoomId != id) { mRoomId = id; mMessageModel->setRoomID(id); } } bool Room::alert() const { return mAlert; } void Room::setBlocker(bool block) { if (mBlocker != block) { mBlocker = block; Q_EMIT blockerChanged(); } } bool Room::blocker() const { return mBlocker; } void Room::setAlert(bool alert) { if (mAlert != alert) { mAlert = alert; Q_EMIT alertChanged(); } } bool Room::open() const { return mOpen; } void Room::setOpen(bool open) { if (mOpen != open) { mOpen = open; Q_EMIT openChanged(); } } bool Room::readOnly() const { return mReadOnly; } void Room::setReadOnly(bool readOnly) { if (mReadOnly != readOnly) { mReadOnly = readOnly; Q_EMIT readOnlyChanged(); } } QString Room::topic() const { return mTopic; } void Room::setTopic(const QString &topic) { if (mTopic != topic) { mTopic = topic; Q_EMIT topicChanged(); } } bool Room::favorite() const { return mFavorite; } void Room::setFavorite(bool favorite) { if (mFavorite != favorite) { mFavorite = favorite; Q_EMIT favoriteChanged(); } } QString Room::channelType() const { return mChannelType; } void Room::setChannelType(const QString &channelType) { if (mChannelType != channelType) { mChannelType = channelType; Q_EMIT channelTypeChanged(); } } QString Room::markdownAnnouncement() const { return Utils::markdownToRichText(mAnnouncement); } QString Room::announcement() const { return mAnnouncement; } void Room::setAnnouncement(const QString &announcement) { if (mAnnouncement != announcement) { mAnnouncement = announcement; Q_EMIT announcementChanged(); } } void Room::setName(const QString &name) { if (mName != name) { mName = name; Q_EMIT nameChanged(); } } void Room::parseInsertRoom(const QJsonObject &json) { QString roomID = json.value(QLatin1String("_id")).toString(); setRoomId(roomID); setName(json[QStringLiteral("name")].toString()); setFName(json[QStringLiteral("fname")].toString()); setJitsiTimeout(Utils::parseDate(QStringLiteral("jitsiTimeout"), json)); //topic/announcement/description is not part of update subscription const QString roomType = json.value(QLatin1String("t")).toString(); setChannelType(roomType); const QJsonValue favoriteValue = json.value(QLatin1String("f")); if (!favoriteValue.isUndefined()) { setFavorite(favoriteValue.toBool()); } setReadOnly(json[QStringLiteral("ro")].toBool()); if (json.contains(QLatin1String("userMentions"))) { setUserMentions(json[QStringLiteral("userMentions")].toInt()); } if (json.contains(QLatin1String("announcement"))) { setAnnouncement(json[QStringLiteral("announcement")].toString()); } if (json.contains(QLatin1String("description"))) { setDescription(json[QStringLiteral("description")].toString()); } setUpdatedAt(Utils::parseDate(QStringLiteral("_updatedAt"), json)); setUnread(json[QStringLiteral("unread")].toInt()); setOpen(json[QStringLiteral("open")].toBool()); setAlert(json[QStringLiteral("alert")].toBool()); const QJsonValue blockerValue = json.value(QLatin1String("blocker")); if (!blockerValue.isUndefined()) { setBlocker(blockerValue.toBool()); } else { setBlocker(false); } //setE2eKeyId(json[QStringLiteral("e2eKeyId")].toString()); setE2EKey(json[QStringLiteral("E2EKey")].toString()); if (json.contains(QLatin1String("encrypted"))) { setEncrypted(json[QStringLiteral("encrypted")].toBool()); } else { setEncrypted(false); } //Blocked ??? const QJsonValue archivedValue = json.value(QLatin1String("archived")); if (!archivedValue.isUndefined()) { setArchived(archivedValue.toBool()); } else { setArchived(false); } parseCommonData(json); const QJsonValue ownerValue = json.value(QLatin1String("u")); if (!ownerValue.isUndefined()) { const QJsonObject objOwner = ownerValue.toObject(); setRoomCreatorUserId(objOwner.value(QLatin1String("_id")).toString()); setRoomCreatorUserName(objOwner.value(QLatin1String("username")).toString()); } else { //When room is initialized we are the owner. When we update room we have the real //owner and if it's empty => we need to clear it. setRoomCreatorUserId(QString()); setRoomCreatorUserName(QString()); } //qDebug() << " *thus" << *this; mNotificationOptions.parseNotificationOptions(json); } qint64 Room::lastSeeAt() const { return mLastSeeAt; } void Room::setLastSeeAt(qint64 lastSeeAt) { mLastSeeAt = lastSeeAt; //Add signal otherwise it's not necessary to check value } bool Room::blocked() const { return mBlocked; } void Room::setBlocked(bool blocked) { if (mBlocked != blocked) { mBlocked = blocked; Q_EMIT blockedChanged(); } } QStringList Room::roles() const { return mRoles; } void Room::setRoles(const QStringList &roles) { if (mRoles != roles) { mRoles = roles; Q_EMIT rolesChanged(); } } QStringList Room::ignoredUsers() const { return mIgnoredUsers; } void Room::setIgnoredUsers(const QStringList &ignoredUsers) { if (mIgnoredUsers != ignoredUsers) { mIgnoredUsers = ignoredUsers; Q_EMIT ignoredUsersChanged(); } } void Room::parseSubscriptionRoom(const QJsonObject &json) { QString roomID = json.value(QLatin1String("rid")).toString(); if (roomID.isEmpty()) { roomID = json.value(QLatin1String("_id")).toString(); } setRoomId(roomID); setName(json[QStringLiteral("name")].toString()); setFName(json[QStringLiteral("fname")].toString()); setJitsiTimeout(Utils::parseDate(QStringLiteral("jitsiTimeout"), json)); //topic/announcement/description is not part of update subscription const QString roomType = json.value(QLatin1String("t")).toString(); setChannelType(roomType); const QJsonValue favoriteValue = json.value(QLatin1String("f")); if (!favoriteValue.isUndefined()) { setFavorite(favoriteValue.toBool()); } setE2EKey(json[QStringLiteral("E2EKey")].toString()); setReadOnly(json[QStringLiteral("ro")].toBool()); setUpdatedAt(Utils::parseDate(QStringLiteral("_updatedAt"), json)); setUnread(json[QStringLiteral("unread")].toInt()); setUserMentions(json[QStringLiteral("userMentions")].toInt()); setOpen(json[QStringLiteral("open")].toBool()); setAlert(json[QStringLiteral("alert")].toBool()); const QJsonValue blockerValue = json.value(QLatin1String("blocker")); if (!blockerValue.isUndefined()) { setBlocker(blockerValue.toBool()); } else { setBlocker(false); } //TODO e2ekey //TODO blocked ? const QJsonValue archivedValue = json.value(QLatin1String("archived")); if (!archivedValue.isUndefined()) { setArchived(archivedValue.toBool()); } else { setArchived(false); } parseCommonData(json); // const QJsonValue ownerValue = json.value(QLatin1String("u")); // if (!ownerValue.isUndefined()) { // const QJsonObject objOwner = ownerValue.toObject(); // setRoomCreatorUserId(objOwner.value(QLatin1String("_id")).toString()); // setRoomCreatorUserName(objOwner.value(QLatin1String("username")).toString()); // } else { // //When room is initialized we are the owner. When we update room we have the real // //owner and if it's empty => we need to clear it. // setRoomCreatorUserId(QString()); // setRoomCreatorUserName(QString()); // } //qDebug() << " *thus" << *this; mNotificationOptions.parseNotificationOptions(json); //TODO add muted } void Room::parseCommonData(const QJsonObject &json) { const QJsonArray mutedArray = json.value(QLatin1String("muted")).toArray(); QStringList lst; lst.reserve(mutedArray.count()); for (int i = 0; i < mutedArray.count(); ++i) { lst << mutedArray.at(i).toString(); } setMutedUsers(lst); const QJsonArray ignoredArray = json.value(QLatin1String("ignored")).toArray(); QStringList lstIgnored; lstIgnored.reserve(ignoredArray.count()); for (int i = 0; i < ignoredArray.count(); ++i) { lstIgnored << ignoredArray.at(i).toString(); } setIgnoredUsers(lstIgnored); const QJsonArray rolesArray = json.value(QLatin1String("roles")).toArray(); QStringList lstRoles; lstRoles.reserve(rolesArray.count()); for (int i = 0; i < rolesArray.count(); ++i) { lstRoles << rolesArray.at(i).toString(); } setRoles(lstRoles); } QString Room::displayFName() const { if (mFName.isEmpty()) { return mName; } return mFName; } QString Room::fName() const { return mFName; } void Room::setFName(const QString &value) { if (mFName != value) { mFName = value; Q_EMIT fnameChanged(); } } bool Room::isDiscussionRoom() const { return !mParentRid.isEmpty(); } QString Room::parentRid() const { return mParentRid; } void Room::setParentRid(const QString &parentRid) { if (mParentRid != parentRid) { mParentRid = parentRid; Q_EMIT parentRidChanged(); } } bool Room::broadcast() const { return mBroadcast; } void Room::setBroadcast(bool broadcast) { if (mBroadcast != broadcast) { mBroadcast = broadcast; Q_EMIT broadcastChanged(); } } Roles Room::rolesForRooms() const { return mRolesForRooms; } void Room::setRolesForRooms(const Roles &rolesForRooms) { mRolesForRooms = rolesForRooms; } QStringList Room::rolesForUserId(const QString &userId) { QStringList lstRoles; const Role r = mRolesForRooms.findRoleByUserId(userId); if (r.isValid()) { if (r.isOwner()) { lstRoles.append(i18n("Owner")); } if (r.isLeader()) { lstRoles.append(i18n("Leader")); } if (r.isModerator()) { lstRoles.append(i18n("Moderator")); } } return lstRoles; } bool Room::wasInitialized() const { return mWasInitialized; } void Room::setWasInitialized(bool wasInitialized) { mWasInitialized = wasInitialized; } bool Room::joinCodeRequired() const { return mJoinCodeRequired; } void Room::setJoinCodeRequired(bool joinCodeRequired) { if (mJoinCodeRequired != joinCodeRequired) { mJoinCodeRequired = joinCodeRequired; Q_EMIT joinCodeRequiredChanged(); } } QString Room::e2eKeyId() const { return mE2eKeyId; } void Room::setE2eKeyId(const QString &e2eKeyId) { if (mE2eKeyId != e2eKeyId) { mE2eKeyId = e2eKeyId; Q_EMIT encryptionKeyIdChanged(); } } QString Room::e2EKey() const { return mE2EKey; } void Room::setE2EKey(const QString &e2EKey) { if (mE2EKey != e2EKey) { mE2EKey = e2EKey; Q_EMIT encryptionKeyChanged(); } } bool Room::encrypted() const { return mEncrypted; } void Room::setEncrypted(bool encrypted) { if (mEncrypted != encrypted) { mEncrypted = encrypted; Q_EMIT encryptedChanged(); } } Room *Room::fromJSon(const QJsonObject &o) { //FIXME Room *r = new Room(nullptr); r->setRoomId(o[QStringLiteral("rid")].toString()); r->setChannelType(o[QStringLiteral("t")].toString()); r->setName(o[QStringLiteral("name")].toString()); r->setFName(o[QStringLiteral("fname")].toString()); r->setRoomCreatorUserName(o[QStringLiteral("roomCreatorUserName")].toString()); r->setRoomCreatorUserId(o[QStringLiteral("roomCreatorUserID")].toString()); r->setTopic(o[QStringLiteral("topic")].toString()); r->setJitsiTimeout(static_cast(o[QStringLiteral("jitsiTimeout")].toDouble())); r->setReadOnly(o[QStringLiteral("ro")].toBool()); r->setUnread(o[QStringLiteral("unread")].toInt(0)); r->setUserMentions(o[QStringLiteral("userMentions")].toInt(0)); r->setAnnouncement(o[QStringLiteral("announcement")].toString()); r->setSelected(o[QStringLiteral("selected")].toBool()); r->setFavorite(o[QStringLiteral("favorite")].toBool()); r->setAlert(o[QStringLiteral("alert")].toBool()); r->setOpen(o[QStringLiteral("open")].toBool()); r->setArchived(o[QStringLiteral("archived")].toBool()); r->setDescription(o[QStringLiteral("description")].toString()); r->setBlocker(o[QStringLiteral("blocker")].toBool()); r->setBlocked(o[QStringLiteral("blocked")].toBool()); r->setEncrypted(o[QStringLiteral("encrypted")].toBool()); r->setBroadcast(o[QStringLiteral("broadcast")].toBool()); r->setE2EKey(o[QStringLiteral("e2ekey")].toString()); r->setE2eKeyId(o[QStringLiteral("e2ekeyid")].toString()); r->setJoinCodeRequired(o[QStringLiteral("joinCodeRequired")].toBool()); r->setUpdatedAt(static_cast(o[QStringLiteral("updatedAt")].toDouble())); r->setLastSeeAt(static_cast(o[QStringLiteral("lastSeeAt")].toDouble())); const QJsonArray mutedArray = o.value(QLatin1String("mutedUsers")).toArray(); QStringList lst; lst.reserve(mutedArray.count()); for (int i = 0; i < mutedArray.count(); ++i) { lst <setMutedUsers(lst); const QJsonArray ignoredArray = o.value(QLatin1String("ignored")).toArray(); QStringList lstIgnored; const int ignoredArrayCount = ignoredArray.count(); lstIgnored.reserve(ignoredArrayCount); for (int i = 0; i < ignoredArrayCount; ++i) { lstIgnored <setIgnoredUsers(lstIgnored); const QJsonArray rolesArray = o.value(QLatin1String("roles")).toArray(); QStringList lstRoles; lstRoles.reserve(rolesArray.count()); for (int i = 0; i < rolesArray.count(); ++i) { lstRoles <setRoles(lstRoles); const QJsonObject notificationsObj = o.value(QLatin1String("notifications")).toObject(); const NotificationOptions notifications = NotificationOptions::fromJSon(notificationsObj); r->setNotificationOptions(notifications); //TODO add parent RID return r; } QByteArray Room::serialize(Room *r, bool toBinary) { QJsonDocument d; QJsonObject o; //todo add timestamp o[QStringLiteral("rid")] = r->roomId(); o[QStringLiteral("t")] = r->channelType(); o[QStringLiteral("name")] = r->name(); o[QStringLiteral("fname")] = r->fName(); o[QStringLiteral("roomCreatorUserName")] = r->roomOwnerUserName(); o[QStringLiteral("roomCreatorUserID")] = r->roomCreatorUserId(); if (!r->topic().isEmpty()) { o[QStringLiteral("topic")] = r->topic(); } o[QStringLiteral("jitsiTimeout")] = r->jitsiTimeout(); o[QStringLiteral("updatedAt")] = r->updatedAt(); o[QStringLiteral("lastSeeAt")] = r->lastSeeAt(); o[QStringLiteral("ro")] = r->readOnly(); o[QStringLiteral("unread")] = r->unread(); if (!r->announcement().isEmpty()) { o[QStringLiteral("announcement")] = r->announcement(); } o[QStringLiteral("selected")] = r->selected(); o[QStringLiteral("favorite")] = r->favorite(); o[QStringLiteral("alert")] = r->alert(); o[QStringLiteral("open")] = r->open(); o[QStringLiteral("blocker")] = r->blocker(); o[QStringLiteral("blocked")] = r->blocked(); o[QStringLiteral("encrypted")] = r->encrypted(); o[QStringLiteral("archived")] = r->archived(); o[QStringLiteral("broadcast")] = r->broadcast(); if (r->joinCodeRequired()) { o[QStringLiteral("joinCodeRequired")] = true; } if (!r->e2EKey().isEmpty()) { o[QStringLiteral("e2ekey")] = r->e2EKey(); } if (!r->e2eKeyId().isEmpty()) { o[QStringLiteral("e2ekeyid")] = r->e2eKeyId(); } if (!r->description().isEmpty()) { o[QStringLiteral("description")] = r->description(); } o[QStringLiteral("userMentions")] = r->userMentions(); if (!r->mutedUsers().isEmpty()) { QJsonArray array; const int nbMuted = r->mutedUsers().count(); for (int i = 0; i < nbMuted; ++i) { array.append(r->mutedUsers().at(i)); } o[QStringLiteral("mutedUsers")] = array; } if (!r->ignoredUsers().isEmpty()) { QJsonArray array; const int nbIgnoredUsers = r->ignoredUsers().count(); for (int i = 0; i < nbIgnoredUsers; ++i) { array.append(r->ignoredUsers().at(i)); } o[QStringLiteral("ignored")] = array; } if (!r->roles().isEmpty()) { QJsonArray array; const int nbRoles = r->roles().count(); for (int i = 0; i < nbRoles; ++i) { array.append(r->roles().at(i)); } o[QStringLiteral("roles")] = array; } o[QStringLiteral("notifications")] = NotificationOptions::serialize(r->notificationOptions()); d.setObject(o); if (toBinary) { return d.toBinaryData(); } return d.toJson(QJsonDocument::Indented); } UsersForRoomModel *Room::usersModelForRoom() const { return mUsersModelForRoom; } UsersForRoomFilterProxyModel *Room::usersModelForRoomProxyModel() const { return mUsersModelForRoomProxyModel; } -ThreadsFilterProxyModel *Room::threadsModelForRoomFilterProxyModel() const -{ - return mThreadsFilterProxyModel; -} - -ThreadsModel *Room::threadsModelForRoom() const -{ - return mThreadsModel; -} - MessageModel *Room::messageModel() const { return mMessageModel; } QString Room::inputMessage() const { return mInputMessage; } void Room::setInputMessage(const QString &inputMessage) { mInputMessage = inputMessage; } bool Room::archived() const { return mArchived; } void Room::setArchived(bool archived) { if (mArchived != archived) { mArchived = archived; Q_EMIT archivedChanged(); } } QString Room::description() const { return mDescription; } void Room::setDescription(const QString &description) { if (mDescription != description) { mDescription = description; Q_EMIT descriptionChanged(); } } bool Room::encryptedEnabled() const { if (mRocketChatAccount) { return mRocketChatAccount->encryptedEnabled(); } return false; } bool Room::userIsIgnored(const QString &userId) { return mIgnoredUsers.contains(userId); } QString Room::roomMessageInfo() const { if (mReadOnly && !canChangeRoles()) { return i18n("Channel is read only."); } if (mBlocker) { return i18n("You have blocked this channel."); } if (mBlocked) { return i18n("Channel was blocked."); } return QString(); } bool Room::canChangeRoles() const { return mRoles.contains(QStringLiteral("owner")); } bool Room::userHasOwnerRole(const QString &userId) const { Role r = mRolesForRooms.findRoleByUserId(userId); if (r.isValid()) { return r.isOwner(); } return false; } bool Room::userHasLeaderRole(const QString &userId) const { Role r = mRolesForRooms.findRoleByUserId(userId); if (r.isValid()) { return r.isLeader(); } return false; } bool Room::userHasModeratorRole(const QString &userId) const { Role r = mRolesForRooms.findRoleByUserId(userId); if (r.isValid()) { return r.isModerator(); } return false; } void Room::updateRoles(const QJsonObject &obj) { mRolesForRooms.updateRoles(obj); } diff --git a/src/ruqolacore/room.h b/src/ruqolacore/room.h index 4201e962..99b0ec1c 100644 --- a/src/ruqolacore/room.h +++ b/src/ruqolacore/room.h @@ -1,349 +1,341 @@ /* * Copyright 2016 Riccardo Iaconelli * Copyright 2017-2018 Laurent Montel * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #ifndef ROOM_H #define ROOM_H #include #include #include "notificationoptions.h" #include "roles.h" #include "libruqola_private_export.h" class UsersForRoomModel; class UsersForRoomFilterProxyModel; class MessageModel; class RocketChatAccount; class NotificationOptionsWrapper; -class ThreadsModel; -class ThreadsFilterProxyModel; class LIBRUQOLACORE_TESTS_EXPORT Room : public QObject { Q_OBJECT Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) Q_PROPERTY(QString fname READ fName WRITE setFName NOTIFY fnameChanged) Q_PROPERTY(QString announcement READ announcement WRITE setAnnouncement NOTIFY announcementChanged) Q_PROPERTY(QString topic READ topic WRITE setTopic NOTIFY topicChanged) Q_PROPERTY(bool favorite READ favorite WRITE setFavorite NOTIFY favoriteChanged) Q_PROPERTY(bool readOnly READ readOnly WRITE setReadOnly NOTIFY readOnlyChanged) Q_PROPERTY(bool alert READ alert WRITE setAlert NOTIFY alertChanged) Q_PROPERTY(bool blocker READ blocker WRITE setBlocker NOTIFY blockerChanged) Q_PROPERTY(bool archived READ archived WRITE setArchived NOTIFY archivedChanged) Q_PROPERTY(bool blocked READ blocked WRITE setBlocked NOTIFY blockedChanged) Q_PROPERTY(bool open READ open WRITE setOpen NOTIFY openChanged) Q_PROPERTY(bool encrypted READ encrypted WRITE setEncrypted NOTIFY encryptedChanged) Q_PROPERTY(bool broadcast READ broadcast WRITE setBroadcast NOTIFY broadcastChanged) Q_PROPERTY(QString description READ description WRITE setDescription NOTIFY descriptionChanged) Q_PROPERTY(QStringList roles READ roles WRITE setRoles NOTIFY rolesChanged) Q_PROPERTY(QString e2eKeyId READ e2eKeyId WRITE setE2eKeyId NOTIFY encryptionKeyIdChanged) Q_PROPERTY(bool joinCodeRequired READ joinCodeRequired WRITE setJoinCodeRequired NOTIFY joinCodeRequiredChanged) Q_PROPERTY(QString channelType READ channelType WRITE setChannelType NOTIFY channelTypeChanged) Q_PROPERTY(bool wasInitialized READ wasInitialized CONSTANT) public: explicit Room(RocketChatAccount *account = nullptr, QObject *parent = nullptr); // To be used in ID find: message ID Q_REQUIRED_RESULT bool operator==(const Room &other) const; //we can't use operator== as it tests only id. We need it for autotest Q_REQUIRED_RESULT bool isEqual(const Room &other) const; Q_REQUIRED_RESULT QString roomOwnerUserName() const; void setRoomCreatorUserName(const QString &userName); Q_REQUIRED_RESULT QString roomCreatorUserId() const; void setRoomCreatorUserId(const QString &userId); Q_REQUIRED_RESULT QStringList mutedUsers() const; void setMutedUsers(const QStringList &mutedUsers); Q_REQUIRED_RESULT qint64 jitsiTimeout() const; void setJitsiTimeout(const qint64 &jitsiTimeout); Q_REQUIRED_RESULT int unread() const; void setUnread(int unread); Q_REQUIRED_RESULT bool selected() const; void setSelected(bool selected); /** * @brief Return room name * * @return QString, The name of the room */ Q_REQUIRED_RESULT QString name() const; void setName(const QString &name); Q_REQUIRED_RESULT QString displayRoomName() const; Q_REQUIRED_RESULT QString announcement() const; void setAnnouncement(const QString &announcement); Q_REQUIRED_RESULT QString channelType() const; void setChannelType(const QString &channelType); Q_REQUIRED_RESULT bool favorite() const; void setFavorite(bool favorite); QString topic() const; void setTopic(const QString &topic); Q_REQUIRED_RESULT bool readOnly() const; void setReadOnly(bool readOnly); Q_REQUIRED_RESULT bool open() const; void setOpen(bool open); Q_REQUIRED_RESULT bool alert() const; void setAlert(bool alert); Q_REQUIRED_RESULT QString roomId() const; void setRoomId(const QString &id); void setBlocker(bool alert); Q_REQUIRED_RESULT bool blocker() const; void parseSubscriptionRoom(const QJsonObject &json); void parseUpdateRoom(const QJsonObject &json); /** * @brief Constructs Room object from QJsonObject (cache) * * @param source The Json containing room attributes * @return Room object, The room constructed from Json */ static Room *fromJSon(const QJsonObject &source); /** * @brief Constructs QBytearray from Room object * * @param message The Room object * @return QByteArray, The Json containing room attributes */ static QByteArray serialize(Room *r, bool toBinary = true); UsersForRoomModel *usersModelForRoom() const; UsersForRoomFilterProxyModel *usersModelForRoomProxyModel() const; - ThreadsModel *threadsModelForRoom() const; - ThreadsFilterProxyModel *threadsModelForRoomFilterProxyModel() const; - MessageModel *messageModel() const; Q_REQUIRED_RESULT QString inputMessage() const; void setInputMessage(const QString &inputMessage); Q_REQUIRED_RESULT bool archived() const; void setArchived(bool archived); QString description() const; void setDescription(const QString &description); Q_REQUIRED_RESULT bool encryptedEnabled() const; Q_REQUIRED_RESULT bool canBeModify() const; Q_REQUIRED_RESULT NotificationOptions notificationOptions() const; void setNotificationOptions(const NotificationOptions ¬ificationOptions); Q_REQUIRED_RESULT int userMentions() const; void setUserMentions(int userMentions); void updateSubscriptionRoom(const QJsonObject &json); Q_REQUIRED_RESULT qint64 updatedAt() const; void setUpdatedAt(qint64 updatedAt); void parseInsertRoom(const QJsonObject &json); Q_REQUIRED_RESULT qint64 lastSeeAt() const; void setLastSeeAt(qint64 lastSeeAt); Q_REQUIRED_RESULT bool blocked() const; void setBlocked(bool blocked); Q_REQUIRED_RESULT QStringList roles() const; void setRoles(const QStringList &roles); Q_REQUIRED_RESULT QStringList ignoredUsers() const; void setIgnoredUsers(const QStringList &ignoredUsers); Q_REQUIRED_RESULT bool encrypted() const; void setEncrypted(bool encrypted); Q_REQUIRED_RESULT bool userIsIgnored(const QString &userId); Q_REQUIRED_RESULT QString markdownAnnouncement() const; Q_REQUIRED_RESULT QString roomMessageInfo() const; Q_REQUIRED_RESULT QString e2EKey() const; void setE2EKey(const QString &e2EKey); Q_REQUIRED_RESULT QString e2eKeyId() const; void setE2eKeyId(const QString &e2eKeyId); NotificationOptionsWrapper *getNotificationWrapper(); Q_REQUIRED_RESULT bool joinCodeRequired() const; void setJoinCodeRequired(bool joinCodeRequired); Q_REQUIRED_RESULT bool wasInitialized() const; void setWasInitialized(bool wasInitialized); Q_REQUIRED_RESULT Roles rolesForRooms() const; void setRolesForRooms(const Roles &rolesForRooms); Q_REQUIRED_RESULT QStringList rolesForUserId(const QString &userId); Q_REQUIRED_RESULT bool canChangeRoles() const; Q_REQUIRED_RESULT bool userHasOwnerRole(const QString &userId) const; Q_REQUIRED_RESULT bool userHasLeaderRole(const QString &userId) const; Q_REQUIRED_RESULT bool userHasModeratorRole(const QString &userId) const; void updateRoles(const QJsonObject &obj); Q_REQUIRED_RESULT bool broadcast() const; void setBroadcast(bool broadcast); Q_REQUIRED_RESULT QString parentRid() const; void setParentRid(const QString &parentRid); Q_REQUIRED_RESULT QString fName() const; void setFName(const QString &value); Q_REQUIRED_RESULT QString displayFName() const; Q_REQUIRED_RESULT bool isDiscussionRoom() const; Q_SIGNALS: void nameChanged(); void fnameChanged(); void announcementChanged(); void topicChanged(); void favoriteChanged(); void alertChanged(); void readOnlyChanged(); void unreadChanged(); void openChanged(); void encryptedChanged(); void encryptionKeyChanged(); void encryptionKeyIdChanged(); //Blocker we blocked the channel void blockerChanged(); //Blocked the channel was blocked void blockedChanged(); void archivedChanged(); void descriptionChanged(); void rolesChanged(); void mutedUsersChanged(); void ignoredUsersChanged(); void jitsiTimeoutChanged(); void joinCodeRequiredChanged(); void channelTypeChanged(); void broadcastChanged(); void parentRidChanged(); private: Q_DISABLE_COPY(Room) void parseCommonData(const QJsonObject &json); //Room Object Fields NotificationOptions mNotificationOptions; // muted - collection of muted users by its usernames QStringList mMutedUsers; QStringList mIgnoredUsers; //Roles QStringList mRoles; QString mInputMessage; // _id QString mRoomId; // t (can take values "d" , "c" or "p" or "l") QString mChannelType; // Parent Rid when we have a discussion. QString mParentRid; // name QString mName; QString mFName; // Announcement QString mAnnouncement; // u QString mRoomCreatorUserName; QString mRoomCreateUserId; // topic QString mTopic; QString mDescription; // jitsiTimeout qint64 mJitsiTimeout = -1; qint64 mUpdatedAt = -1; qint64 mLastSeeAt = -1; //Encryption Key QString mE2EKey; QString mE2eKeyId; //Roles In Room Roles mRolesForRooms; //quint64 ? int mUnread = 0; int mUserMentions = 0; int mThreadCount = 0; // ro - read-only chat or not bool mReadOnly = false; bool mSelected = false; bool mFavorite = false; //We can hide it or not. bool mOpen = false; bool mAlert = false; bool mBlocker = false; bool mArchived = false; bool mBlocked = false; bool mEncrypted = false; bool mJoinCodeRequired = false; bool mWasInitialized = false; bool mBroadcast = false; - ThreadsModel *mThreadsModel = nullptr; - ThreadsFilterProxyModel *mThreadsFilterProxyModel = nullptr; - UsersForRoomModel *mUsersModelForRoom = nullptr; UsersForRoomFilterProxyModel *mUsersModelForRoomProxyModel = nullptr; MessageModel *mMessageModel = nullptr; RocketChatAccount *mRocketChatAccount = nullptr; }; LIBRUQOLACORE_EXPORT QDebug operator <<(QDebug d, const Room &t); #endif // ROOM_H