diff --git a/src/apps/qml/Desktop.qml b/src/apps/qml/Desktop.qml index e1b97db7..6ed88d73 100644 --- a/src/apps/qml/Desktop.qml +++ b/src/apps/qml/Desktop.qml @@ -1,317 +1,320 @@ /* * Copyright 2016 Riccardo Iaconelli * Copyright (c) 2017-2019 Montel Laurent * * 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 . * */ import QtQuick 2.9 import QtQuick.Window 2.2 import QtQuick.Dialogs 1.2 import QtQuick.Layouts 1.12 import QtQuick.Controls 2.5 as QQC2 import KDE.Ruqola.RuqolaUtils 1.0 import KDE.Ruqola.Ruqola 1.0 import KDE.Ruqola.DDPClient 1.0 import KDE.Ruqola.RoomFilterProxyModel 1.0 import org.kde.kirigami 2.7 as Kirigami import KDE.Ruqola.DebugCategory 1.0 import KDE.Ruqola.Channel 1.0 import KDE.Ruqola.AccountManager 1.0 Kirigami.ApplicationWindow { id: appid readonly property int margin: 11 property string selectedRoomID: ""; property QtObject selectedRoom property QtObject messageModel property QtObject userModel property QtObject filesModel property QtObject threadsModel property QtObject discussionsModel property QtObject accountManager: Ruqola.accountManager() property QtObject accountManagerModel: accountManager.rocketChatAccountModel() property QtObject rocketChatAccount: accountManager.firstAccount() property QtObject inputCompleterModel: rocketChatAccount.inputCompleterModel() property QtObject searchMessageModel: rocketChatAccount.searchMessageFilterProxyModel() property QtObject emojiModel: rocketChatAccount.emoticonModel() property string userInputMessageText: ""; width: Kirigami.Units.gridUnit * 55 height: Kirigami.Units.gridUnit * 40 title: i18n("Ruqola") function switchToRoom(roomID) { if (roomID === selectedRoomID) { return; } //TODO remove duplicate code !!!! appid.rocketChatAccount.switchingToRoom(roomID) appid.rocketChatAccount.setUserCurrentMessage(appid.userInputMessageText, selectedRoomID) appid.selectedRoomID = roomID; appid.messageModel = appid.rocketChatAccount.messageModelForRoom(roomID) appid.selectedRoom = appid.rocketChatAccount.getRoomWrapper(roomID) appid.userModel = appid.rocketChatAccount.usersForRoomFilterProxyModel(roomID) appid.filesModel = appid.rocketChatAccount.filesForRoomFilterProxyModel(roomID) appid.threadsModel = appid.rocketChatAccount.threadsFilterProxyModel(roomID) appid.discussionsModel = appid.rocketChatAccount.discussionsFilterProxyModel(roomID) } pageStack.globalToolBar.style: Kirigami.ApplicationHeaderStyle.None pageStack.initialPage: [roomsComponent, mainComponent] pageStack.visible: rocketChatAccount.loginStatus === DDPClient.LoggedIn globalDrawer: Kirigami.GlobalDrawer { drawerOpen: false handleVisible: true resetMenuOnTriggered: true topContent: [ QQC2.Label { text: rocketChatAccount.userName === "" ? "" : i18n("Hello, %1", rocketChatAccount.userName) } ] actions: [ Kirigami.Action { text: i18n("About") iconName: ":/icons/systray.png" onTriggered: { aboutDataDialog.open() } }, Kirigami.Action { text: i18n("Report a Bug") iconName: "tools-report-bug" onTriggered: { Qt.openUrlExternally("https://bugs.kde.org/report.cgi"); } }, Kirigami.Action { text: i18n("Configure Account") iconName: "settings-configure" onTriggered: { configureServerList.visible = true pageStack.visible = false } }, Kirigami.Action { text: i18n("Handbook") iconName: "system-help" onTriggered: { rocketChatAccount.openDocumentation(); } }, Kirigami.Action { separator: true }, Kirigami.Action { text: i18n("Log out") iconName: "system-log-out" onTriggered: { rocketChatAccount.logOut(); appid.globalDrawer.drawerOpen = false; } }, Kirigami.Action { separator: true }, Kirigami.Action { shortcut: StandardKey.Quit text: i18n("Quit") iconName: "application-exit" onTriggered: { Qt.quit(); } } ] } ConfigureServerList { id: configureServerList accountModel: accountManagerModel visible: false onCloseConfigureServer: { configureServerList.visible = false pageStack.visible = true } } LoginPage { id: loginTab rcAccount: rocketChatAccount } AboutDialog { id: aboutDataDialog applicationData: Ruqola.applicationData() onOpenurl: { RuqolaUtils.openUrl(link); } } PrivateChannelInfoDialog { id: privateChannelInfoDialog onBlockUser: { rocketChatAccount.blockUser(rid, block) } } NotificationOptionsDialog { id: notificationsDialog rid: (appid && appid.selectedRoomID) ? appid.selectedRoomID : "" onModifyNotificationsSetting: { rocketChatAccount.changeNotificationsSettings(roomId, type, newVal) } } ChannelInfoDialog { id: channelInfoDialog channelName: (appid && appid.selectedRoomID) ? appid.selectedRoomID : "" onDeleteRoom: { rocketChatAccount.eraseRoom(roomId, appid.selectedRoom.channelType) } onModifyChannelSetting: { rocketChatAccount.changeChannelSettings(roomId, type, newVal, channelType) } } LeaveChannelDialog { id: leaveChannelDialog onLeaveChannel: { rocketChatAccount.leaveRoom(roomId, channelType) } } AddUserDialog { id: addUserDialog completerModel: rocketChatAccount.userCompleterFilterModelProxy() onSearchUserName: { rocketChatAccount.userAutocomplete(pattern, ""); } onAddUser: { rocketChatAccount.addUserToRoom(userId, rid, channelType) } } ShowSearchMessageDialog { id: searchMessageDialog searchMessageModel: appid.searchMessageModel onSearchMessage: { rocketChatAccount.messageSearch(pattern, rid) } onClosed: { rocketChatAccount.clearSearchModel() } + onGoToMessage: { + console.log("Show history to message: " + messageId) + } } JobErrorMessageDialog { id: jobErrorMessageDialog } CreateNewChannelDialog { id: createNewChannelDialog onCreateNewChannel: { rocketChatAccount.createNewChannel(name, readOnly, privateRoom, usernames, encryptedRoom, password, broadcast); } } ServerInfoDialog { id: serverinfodialog } SearchChannelDialog { id: searchChannelDialog searchChannelModel: rocketChatAccount.searchChannelFilterProxyModel() onSearchChannel: { rocketChatAccount.channelAndPrivateAutocomplete(pattern); } onOpenChannel: { if (channeltype === Channel.Room) { rocketChatAccount.openChannel(channelid) } else if (channeltype === Channel.PrivateChannel) { if (rocketChatAccount.userName !== channelid) { rocketChatAccount.openDirectChannel(channelid) } } else { console.log(RuqolaDebugCategorySingleton.category, "Unknown open channel type : " + channeltype + " channelid : " + channelid + " channelname : " + channelname) } } } TakeVideoMessageDialog { id: takeVideoMessage rcAccount: rocketChatAccount } QQC2.BusyIndicator { id: busy anchors.centerIn: parent visible: rocketChatAccount.loginStatus === DDPClient.LoggingIn } RoomsComponent { id: roomsComponent } MainComponent { id: mainComponent } ChannelPasswordDialog { id: channelPasswordDialog onJoinRoom: { rocketChatAccount.joinRoom(roomId, password) } } Connections { target: rocketChatAccount onMissingChannelPassword: { channelPasswordDialog.roomId = roomId channelPasswordDialog.visible = true } onJobFailed: { jobErrorMessageDialog.jobMessageError = message jobErrorMessageDialog.open() } } onClosing: { Qt.quit(); } function toggleShow() { if (visible) { hide(); } else { show(); raise(); requestActivate(); } } Component.onCompleted: { systrayIcon.activateRequested.connect(toggleShow); } } diff --git a/src/apps/qml/ShowSearchMessageDialog.qml b/src/apps/qml/ShowSearchMessageDialog.qml index 69ba6695..49cbece1 100644 --- a/src/apps/qml/ShowSearchMessageDialog.qml +++ b/src/apps/qml/ShowSearchMessageDialog.qml @@ -1,77 +1,96 @@ /* Copyright (c) 2018-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. */ import QtQuick.Layouts 1.12 import QtQuick.Controls 2.5 as QQC2 import QtQuick.Window 2.2 import QtQuick 2.9 import KDE.Ruqola.UsersForRoomFilterProxyModel 1.0 import org.kde.kirigami 2.7 as Kirigami - +import "common" +import "messages" QQC2.Dialog { id: showSearchMessageDialog title: i18n("Search Message") signal searchMessage(string pattern, string rid) + signal goToMessage(string messageId) + property QtObject searchMessageModel property string roomId x: parent.width / 2 - width / 2 y: parent.height / 2 - height / 2 modal: true focus: true standardButtons: QQC2.Dialog.Close function initializeAndOpen() { searchField.text = ""; open(); } ColumnLayout { LineEditWithClearButton { id: searchField placeholderText: i18n("Search Word...") Layout.fillWidth: true onAccepted: { showSearchMessageDialog.searchMessage(text, roomId) } } ListView { id: listview width: 400; height: 200 clip: true // Scrollars QQC2.ScrollIndicator.vertical: QQC2.ScrollIndicator { } QQC2.ScrollIndicator.horizontal: QQC2.ScrollIndicator { } model: searchMessageModel delegate: Kirigami.BasicListItem { - label: messagetext reserveSpaceForIcon: false + RowLayout { +// AvatarImage { +// id: avatarRect +// avatarurl: i_avatar +// aliasname: i_aliasname +// username: i_username +// } + QQC2.Label { + text: messagetext + elide: Text.ElideRight + wrapMode: QQC2.Label.Wrap + } + TimestampText { + id: timestampText + timestamp: messagetimestamp + } + } } } } } diff --git a/src/apps/qml/common/AvatarImage.qml b/src/apps/qml/common/AvatarImage.qml index 42f374f3..3d7c74b8 100644 --- a/src/apps/qml/common/AvatarImage.qml +++ b/src/apps/qml/common/AvatarImage.qml @@ -1,111 +1,111 @@ /* * Copyright (C) 2017-2019 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 . * */ import QtQuick 2.9 import QtQuick.Controls 2.5 as QQC2 import org.kde.kirigami 2.7 as Kirigami import QtQuick.Layouts 1.12 import "../js/message.js" as MessageScript; import QtQuick.Window 2.2 import KDE.Ruqola.RocketChatAccount 1.0 import KDE.Ruqola.DebugCategory 1.0 Rectangle { id: avatarRect property string avatarurl property string aliasname property string username - + property int defaultWidth: Kirigami.Units.iconSizes.medium signal showUserInfo() Layout.alignment: Qt.AlignTop | Qt.AlignCenter Layout.fillHeight: false //Customize it. - implicitWidth: Kirigami.Units.iconSizes.medium + implicitWidth: defaultWidth implicitHeight: implicitWidth radius: 3 anchors.rightMargin: 2*Kirigami.Units.smallSpacing color: avatarurl !== "" ? "transparent" : MessageScript.stringToColour(username) Image { id: avatarImage anchors.fill: parent visible: avatarurl !== "" source: avatarurl fillMode: Image.PreserveAspectFit MouseArea { anchors.fill: parent onClicked: { avatarRect.showUserInfo(); } } onStatusChanged: { if (avatarImage.status === Image.Error) { console.log(RuqolaDebugCategorySingleton.category, "An error occurred when we try to load image"); } } } QQC2.Label { id: avatarText visible: avatarurl == "" anchors.fill: parent anchors.margins: Kirigami.Units.smallSpacing renderType: Text.QtRendering color: Kirigami.Theme.backgroundColor font.weight: Font.Bold font.pointSize: 40 fontSizeMode: Text.Fit horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter text: { //TODO verify if it works with non latin char. if (aliasname.length > 0) { var match = aliasname.match(/([a-zA-Z0-9])([a-zA-Z0-9])/); var abbrev = match[1].toUpperCase(); if (match.length > 2) { abbrev += match[2].toLowerCase(); } return abbrev; } return ""; } } Connections { target: appid.rocketChatAccount onFileDownloaded: { //console.log(" filePath " + filePath + " username: " + username) if (filePath === "/avatar/" + username) { avatarurl = cacheImageUrl } } } } diff --git a/src/rocketchatrestapi-qt5/autotests/channelgetallusermentionsjobtest.cpp b/src/rocketchatrestapi-qt5/autotests/channelgetallusermentionsjobtest.cpp index 6fa0f6cf..6686b541 100644 --- a/src/rocketchatrestapi-qt5/autotests/channelgetallusermentionsjobtest.cpp +++ b/src/rocketchatrestapi-qt5/autotests/channelgetallusermentionsjobtest.cpp @@ -1,147 +1,147 @@ /* Copyright (c) 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 "channelgetallusermentionsjobtest.h" #include "channels/channelgetallusermentionsjob.h" #include "restapimethod.h" #include "ruqola_restapi_helper.h" #include QTEST_GUILESS_MAIN(ChannelGetAllUserMentionsJobTest) using namespace RocketChatRestApi; ChannelGetAllUserMentionsJobTest::ChannelGetAllUserMentionsJobTest(QObject *parent) : QObject(parent) { } void ChannelGetAllUserMentionsJobTest::shouldHaveDefaultValue() { ChannelGetAllUserMentionsJob job; QVERIFY(!job.restApiMethod()); QVERIFY(!job.networkAccessManager()); QVERIFY(!job.start()); QVERIFY(job.requireHttpAuthentication()); QVERIFY(job.roomId().isEmpty()); QVERIFY(!job.restApiLogger()); QVERIFY(job.hasQueryParameterSupport()); } void ChannelGetAllUserMentionsJobTest::shouldHaveParameterSupport() { ChannelGetAllUserMentionsJob job; RestApiMethod *method = new RestApiMethod; method->setServerUrl(QStringLiteral("http://www.kde.org")); job.setRestApiMethod(method); const QString roomId = QStringLiteral("avat"); job.setRoomId(roomId); QueryParameters parameters; parameters.setCount(5); parameters.setOffset(12); job.setQueryParameters(parameters); QNetworkRequest request = job.request(); verifyAuthentication(&job, request); QCOMPARE(request.url(), QUrl(QStringLiteral("http://www.kde.org/api/v1/channels.getAllUserMentionsByChannel?roomId=avat&count=5&offset=12"))); delete method; } void ChannelGetAllUserMentionsJobTest::shouldHaveParameterSupportSorting() { ChannelGetAllUserMentionsJob job; RestApiMethod *method = new RestApiMethod; method->setServerUrl(QStringLiteral("http://www.kde.org")); job.setRestApiMethod(method); const QString roomId = QStringLiteral("avat"); job.setRoomId(roomId); QueryParameters parameters; parameters.setCount(5); parameters.setOffset(12); QMap map; map.insert(QStringLiteral("foo"), QueryParameters::SortOrder::Descendant); parameters.setSorting(map); job.setQueryParameters(parameters); QNetworkRequest request = job.request(); verifyAuthentication(&job, request); - QCOMPARE(request.url(), QUrl(QStringLiteral("http://www.kde.org/api/v1/channels.getAllUserMentionsByChannel?roomId=avat&count=5&offset=12"))); + QCOMPARE(request.url(), QUrl(QStringLiteral("http://www.kde.org/api/v1/channels.getAllUserMentionsByChannel?roomId=avat&count=5&offset=12&sort=%7B%22foo%22:-1%7D"))); delete method; } void ChannelGetAllUserMentionsJobTest::shouldHaveParameterSupportSortingTwoParameters() { ChannelGetAllUserMentionsJob job; RestApiMethod *method = new RestApiMethod; method->setServerUrl(QStringLiteral("http://www.kde.org")); job.setRestApiMethod(method); const QString roomId = QStringLiteral("avat"); job.setRoomId(roomId); QueryParameters parameters; parameters.setCount(5); parameters.setOffset(12); QMap map; map.insert(QStringLiteral("foo"), QueryParameters::SortOrder::Descendant); map.insert(QStringLiteral("bla"), QueryParameters::SortOrder::Ascendant); parameters.setSorting(map); job.setQueryParameters(parameters); QNetworkRequest request = job.request(); verifyAuthentication(&job, request); QCOMPARE(request.url(), QUrl(QStringLiteral("http://www.kde.org/api/v1/channels.getAllUserMentionsByChannel?roomId=avat&count=5&offset=12"))); delete method; } void ChannelGetAllUserMentionsJobTest::shouldGenerateRequest() { ChannelGetAllUserMentionsJob job; RestApiMethod *method = new RestApiMethod; method->setServerUrl(QStringLiteral("http://www.kde.org")); job.setRestApiMethod(method); const QString roomId = QStringLiteral("avat"); job.setRoomId(roomId); QNetworkRequest request = job.request(); verifyAuthentication(&job, request); QCOMPARE(request.url(), QUrl(QStringLiteral("http://www.kde.org/api/v1/channels.getAllUserMentionsByChannel?roomId=avat"))); delete method; } void ChannelGetAllUserMentionsJobTest::shouldNotStarting() { ChannelGetAllUserMentionsJob job; RestApiMethod *method = new RestApiMethod; method->setServerUrl(QStringLiteral("http://www.kde.org")); job.setRestApiMethod(method); QNetworkAccessManager *mNetworkAccessManager = new QNetworkAccessManager; job.setNetworkAccessManager(mNetworkAccessManager); QVERIFY(!job.canStart()); const QString auth = QStringLiteral("foo"); const QString userId = QStringLiteral("foo"); job.setAuthToken(auth); QVERIFY(!job.canStart()); job.setUserId(userId); QVERIFY(!job.canStart()); const QString roomId = QStringLiteral("foo1"); job.setRoomId(roomId); QVERIFY(job.canStart()); delete method; delete mNetworkAccessManager; } diff --git a/src/ruqolacore/model/emoticoncategoriesmodel.cpp b/src/ruqolacore/model/emoticoncategoriesmodel.cpp index b3d0b5b8..150e6620 100644 --- a/src/ruqolacore/model/emoticoncategoriesmodel.cpp +++ b/src/ruqolacore/model/emoticoncategoriesmodel.cpp @@ -1,82 +1,82 @@ /* Copyright (c) 2018-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 "emoticoncategoriesmodel.h" EmoticonCategoriesModel::EmoticonCategoriesModel(QObject *parent) : QAbstractListModel(parent) { } EmoticonCategoriesModel::~EmoticonCategoriesModel() { } int EmoticonCategoriesModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return mCategories.count(); } QVariant EmoticonCategoriesModel::data(const QModelIndex &index, int role) const { if (index.row() < 0 || index.row() >= mCategories.count()) { return {}; } const EmoticonCategory cat = mCategories.at(index.row()); switch (role) { case Name: return cat.name(); case Category: return cat.category(); } - Q_UNREACHABLE(); + return {}; } QHash EmoticonCategoriesModel::roleNames() const { QHash roles; roles[Name] = QByteArrayLiteral("name"); roles[Category] = QByteArrayLiteral("category"); //Add tooltip ? we need to extract info from json file. return roles; } void EmoticonCategoriesModel::setEmoticons(const QMap > &emoticons) { if (rowCount() != 0) { beginRemoveRows(QModelIndex(), 0, mCategories.count() - 1); mCategories.clear(); endRemoveRows(); } if (!emoticons.isEmpty()) { beginInsertRows(QModelIndex(), 0, emoticons.count() - 1); QMap >::const_iterator i = emoticons.constBegin(); while (i != emoticons.constEnd()) { EmoticonCategory cat; cat.setCategory(i.key()); cat.setName(i.value().at(0).unicode()); ++i; mCategories.append(cat); } endInsertRows(); } } diff --git a/src/ruqolacore/model/emoticonmodel.cpp b/src/ruqolacore/model/emoticonmodel.cpp index 402300ea..ba248814 100644 --- a/src/ruqolacore/model/emoticonmodel.cpp +++ b/src/ruqolacore/model/emoticonmodel.cpp @@ -1,113 +1,113 @@ /* Copyright (c) 2018-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 "emoticonmodel.h" EmoticonModel::EmoticonModel(QObject *parent) : QAbstractListModel(parent) { mEmoticonCategoriesModel = new EmoticonCategoriesModel(this); } EmoticonModel::~EmoticonModel() { } int EmoticonModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); if (mEmoticons.contains(mCurrentCategory)) { return mEmoticons[mCurrentCategory].count(); } return 0; } QVariant EmoticonModel::data(const QModelIndex &index, int role) const { const QVector emoticonsFromCategoryList = mEmoticons.value(mCurrentCategory); if (index.row() < 0 || index.row() >= emoticonsFromCategoryList.count()) { return {}; } const UnicodeEmoticon unicodeEmoti = emoticonsFromCategoryList.at(index.row()); switch (role) { case Identifier: return unicodeEmoti.identifier(); case Text: return unicodeEmoti.key(); case UnicodeEmoji: return unicodeEmoti.unicode(); case Order: return unicodeEmoti.order(); } - Q_UNREACHABLE(); + return {}; } QHash EmoticonModel::roleNames() const { QHash roles; roles[Identifier] = QByteArrayLiteral("identifier"); roles[Text] = QByteArrayLiteral("text"); roles[UnicodeEmoji] = QByteArrayLiteral("unicodeEmoji"); roles[Order] = QByteArrayLiteral("order"); return roles; } QMap > EmoticonModel::emoticons() const { return mEmoticons; } void EmoticonModel::setEmoticons(const QMap > &emoticons) { if (rowCount() != 0) { beginRemoveRows(QModelIndex(), 0, mEmoticons.count() - 1); mEmoticons.clear(); endRemoveRows(); } if (!emoticons.isEmpty()) { beginInsertRows(QModelIndex(), 0, emoticons.count() - 1); mEmoticons = emoticons; endInsertRows(); } if (!mEmoticons.isEmpty()) { mCurrentCategory = mEmoticons.keys().at(0); mEmoticonCategoriesModel->setEmoticons(emoticons); } } void EmoticonModel::setCurrentCategory(const QString &category) { if (mCurrentCategory != category) { beginResetModel(); mCurrentCategory = category; endResetModel(); } } QString EmoticonModel::currentCategory() const { return mCurrentCategory; } EmoticonCategoriesModel *EmoticonModel::emoticonCategoriesModel() const { return mEmoticonCategoriesModel; } diff --git a/src/ruqolacore/model/inputcompletermodel.cpp b/src/ruqolacore/model/inputcompletermodel.cpp index f887ed45..45c0f723 100644 --- a/src/ruqolacore/model/inputcompletermodel.cpp +++ b/src/ruqolacore/model/inputcompletermodel.cpp @@ -1,176 +1,176 @@ /* Copyright (c) 2018-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 "inputcompletermodel.h" #include "ruqola_debug.h" #include #include #include #include #include InputCompleterModel::InputCompleterModel(QObject *parent) : QAbstractListModel(parent) { } InputCompleterModel::~InputCompleterModel() { } void InputCompleterModel::setChannels(const QVector &channels) { if (rowCount() != 0) { beginRemoveRows(QModelIndex(), 0, mChannel.count() - 1); mChannel.clear(); endRemoveRows(); } if (!channels.isEmpty()) { beginInsertRows(QModelIndex(), 0, channels.count() - 1); mChannel = channels; endInsertRows(); } } void InputCompleterModel::parseChannels(const QJsonObject &obj) { QVector channelList; const QJsonArray rooms = obj.value(QLatin1String("rooms")).toArray(); for (int i = 0; i < rooms.size(); i++) { const QJsonObject o = rooms.at(i).toObject(); Channel channel; channel.parseChannel(o, Channel::ChannelType::Room); //Verify that it's valid channelList.append(channel); } const QJsonArray users = obj.value(QLatin1String("users")).toArray(); for (int i = 0; i < users.size(); i++) { const QJsonObject o = users.at(i).toObject(); Channel channel; channel.parseChannel(o, Channel::ChannelType::PrivateChannel); //Verify that it's valid channelList.append(channel); } setChannels(channelList); } void InputCompleterModel::clear() { if (!mChannel.isEmpty()) { beginRemoveRows(QModelIndex(), 0, mChannel.count() - 1); mChannel.clear(); endRemoveRows(); } } int InputCompleterModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return mChannel.count(); } QVariant InputCompleterModel::data(const QModelIndex &index, int role) const { if (index.row() < 0 || index.row() >= mChannel.count()) { return {}; } const Channel channel = mChannel.at(index.row()); switch (role) { case InputCompleterModel::DisplayName: return channelName(channel); case InputCompleterModel::CompleterName: return completerName(channel); case InputCompleterModel::IconName: return channelIconName(channel); case InputCompleterModel::ChannelType: return channel.type(); } return {}; } QString InputCompleterModel::completerName(const Channel &channel) const { //Specific channelId for opening room //For private channel we need to use username for channel we need roomId switch (channel.type()) { case Channel::ChannelType::PrivateChannel: return channel.user().userName(); case Channel::ChannelType::Room: return channel.roomName(); case Channel::ChannelType::Unknown: qCWarning(RUQOLA_LOG) << "Unknown channel type!"; return {}; } - Q_UNREACHABLE(); + return {}; } QString InputCompleterModel::channelName(const Channel &channel) const { switch (channel.type()) { case Channel::ChannelType::PrivateChannel: { QString text = channel.user().userName(); const QString name = channel.user().name(); if (!name.isEmpty()) { text += QStringLiteral(" (") + channel.user().name() + QLatin1Char(')'); } return text; } case Channel::ChannelType::Room: return channel.roomName(); case Channel::ChannelType::Unknown: qCWarning(RUQOLA_LOG) << "Unknown channel type!"; return {}; } return {}; } QIcon InputCompleterModel::channelIconName(const Channel &channel) const { switch (channel.type()) { case Channel::ChannelType::PrivateChannel: return QIcon::fromTheme(channel.user().iconFromStatus()); case Channel::ChannelType::Room: if (channel.roomType() == QLatin1String("c")) { return QIcon::fromTheme(QStringLiteral("irc-channel-inactive")); } else if (channel.roomType() == QLatin1String("p")) { return QIcon::fromTheme(QStringLiteral("lock")); } qCWarning(RUQOLA_LOG) << "Unknown room type!" << channel.roomType(); return {}; case Channel::ChannelType::Unknown: qCWarning(RUQOLA_LOG) << "Unknown channel type!"; return {}; } return {}; } QHash InputCompleterModel::roleNames() const { QHash roles; roles[InputCompleterModel::DisplayName] = QByteArrayLiteral("displayname"); roles[InputCompleterModel::CompleterName] = QByteArrayLiteral("completername"); roles[InputCompleterModel::IconName] = QByteArrayLiteral("iconname"); roles[InputCompleterModel::ChannelType] = QByteArrayLiteral("channeltype"); return roles; } diff --git a/src/ruqolacore/model/loginmethodmodel.cpp b/src/ruqolacore/model/loginmethodmodel.cpp index c2fd2957..2df2dc3e 100644 --- a/src/ruqolacore/model/loginmethodmodel.cpp +++ b/src/ruqolacore/model/loginmethodmodel.cpp @@ -1,107 +1,107 @@ /* Copyright (c) 2018-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 "loginmethodmodel.h" #include "ruqola_debug.h" #include LoginMethodModel::LoginMethodModel(QObject *parent) : QAbstractListModel(parent) { } LoginMethodModel::~LoginMethodModel() { } int LoginMethodModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return mAuthentications.count(); } void LoginMethodModel::clear() { if (!mAuthentications.isEmpty()) { beginRemoveRows(QModelIndex(), 0, mAuthentications.count() - 1); mAuthentications.clear(); endRemoveRows(); } } AuthenticationManager::OauthType LoginMethodModel::loginType(int index) { return mAuthentications.at(index).oauthType(); } int LoginMethodModel::currentLoginMethod() const { return mCurrentLoginMethod; } void LoginMethodModel::setCurrentLoginMethod(int currentLoginMethod) { if (mCurrentLoginMethod != currentLoginMethod) { mCurrentLoginMethod = currentLoginMethod; Q_EMIT currentLoginMethodChanged(); } } QVariant LoginMethodModel::data(const QModelIndex &index, int role) const { if (index.row() < 0 || index.row() >= mAuthentications.count()) { return QVariant(); } const AuthenticationInfo info = mAuthentications.at(index.row()); switch (role) { case Name: return info.name(); case IconName: return info.iconName(); case Type: return info.oauthType(); } - Q_UNREACHABLE(); + return {}; } void LoginMethodModel::setAuthenticationInfos(const QVector &infos) { if (rowCount() != 0) { beginRemoveRows(QModelIndex(), 0, mAuthentications.count() - 1); mAuthentications.clear(); endRemoveRows(); } if (!infos.isEmpty()) { beginInsertRows(QModelIndex(), 0, infos.count() - 1); mAuthentications = infos; endInsertRows(); } } QHash LoginMethodModel::roleNames() const { QHash roles; roles[Name] = QByteArrayLiteral("name"); roles[IconName] = QByteArrayLiteral("iconname"); roles[Type] = QByteArrayLiteral("type"); return roles; } diff --git a/src/ruqolacore/model/messagemodel.cpp b/src/ruqolacore/model/messagemodel.cpp index 938ae6c8..5fdd580b 100644 --- a/src/ruqolacore/model/messagemodel.cpp +++ b/src/ruqolacore/model/messagemodel.cpp @@ -1,373 +1,373 @@ /* * 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 . * */ #include #include #include #include #include #include "messagemodel.h" #include "ruqolaserverconfig.h" #include "room.h" #include "ruqola_debug.h" #include "utils.h" #include "rocketchataccount.h" #include "texthighlighter.h" #include "textconverter.h" #include "loadrecenthistorymanager.h" #include //TODO reactivate when we will able to load message between cache and official server. //#define STORE_MESSAGE 1 MessageModel::MessageModel(const QString &roomID, RocketChatAccount *account, Room *room, QObject *parent) : QAbstractListModel(parent) , mRoomID(roomID) , mRocketChatAccount(account) , mRoom(room) { mTextConverter = new TextConverter(mRocketChatAccount ? mRocketChatAccount->emojiManager() : nullptr); mLoadRecentHistoryManager = new LoadRecentHistoryManager; qCDebug(RUQOLA_LOG) << "Creating message Model"; #ifdef STORE_MESSAGE if (mRocketChatAccount) { const QString cachePath = mRocketChatAccount->settings()->cacheBasePath(); if (cachePath.isEmpty()) { qCWarning(RUQOLA_LOG) << " Cache Path is not defined"; return; } QDir cacheDir(cachePath + QStringLiteral("/rooms_cache")); // load cache if (QFile::exists(cacheDir.absoluteFilePath(roomID)) && !roomID.isEmpty()) { QFile f(cacheDir.absoluteFilePath(roomID)); if (f.open(QIODevice::ReadOnly)) { QDataStream in(&f); while (!f.atEnd()) { char *byteArray; quint32 length; in.readBytes(byteArray, length); const QByteArray arr = QByteArray::fromRawData(byteArray, length); Message m = Message::fromJSon(QJsonDocument::fromBinaryData(arr).object()); addMessage(m); } } } } #endif connect(mRoom, &Room::rolesChanged, this, &MessageModel::refresh); connect(mRoom, &Room::ignoredUsersChanged, this, &MessageModel::refresh); } MessageModel::~MessageModel() { #ifdef STORE_MESSAGE if (mRocketChatAccount) { const QString cachePath = mRocketChatAccount->settings()->cacheBasePath(); if (cachePath.isEmpty()) { qCWarning(RUQOLA_LOG) << " Cache Path is not defined"; return; } QDir cacheDir(cachePath + QStringLiteral("/rooms_cache")); qCDebug(RUQOLA_LOG) << "Caching to..." << cacheDir.path(); if (!cacheDir.exists(cacheDir.path())) { cacheDir.mkpath(cacheDir.path()); } QFile f(cacheDir.absoluteFilePath(mRoomID)); if (f.open(QIODevice::WriteOnly)) { QDataStream out(&f); for (const Message &m : qAsConst(mAllMessages)) { const QByteArray ms = Message::serialize(m); out.writeBytes(ms, ms.size()); } } } #endif delete mTextConverter; delete mLoadRecentHistoryManager; } void MessageModel::refresh() { beginResetModel(); endResetModel(); } QHash MessageModel::roleNames() const { QHash roles; roles[OriginalMessage] = QByteArrayLiteral("originalMessage"); roles[MessageConvertedText] = QByteArrayLiteral("messageConverted"); roles[Username] = QByteArrayLiteral("username"); roles[Timestamp] = QByteArrayLiteral("timestamp"); roles[UserId] = QByteArrayLiteral("userID"); roles[SystemMessageType] = QByteArrayLiteral("type"); roles[MessageId] = QByteArrayLiteral("messageID"); roles[RoomId] = QByteArrayLiteral("roomID"); roles[UpdatedAt] = QByteArrayLiteral("updatedAt"); roles[EditedAt] = QByteArrayLiteral("editedAt"); roles[EditedByUserName] = QByteArrayLiteral("editedByUsername"); roles[EditedByUserId] = QByteArrayLiteral("editedByUserID"); roles[Alias] = QByteArrayLiteral("alias"); roles[Avatar] = QByteArrayLiteral("avatar"); roles[Groupable] = QByteArrayLiteral("groupable"); roles[MessageType] = QByteArrayLiteral("messagetype"); roles[Attachments] = QByteArrayLiteral("attachments"); roles[Urls] = QByteArrayLiteral("urls"); roles[Date] = QByteArrayLiteral("date"); roles[CanEditingMessage] = QByteArrayLiteral("canEditingMessage"); roles[Starred] = QByteArrayLiteral("starred"); roles[UsernameUrl] = QByteArrayLiteral("usernameurl"); roles[Roles] = QByteArrayLiteral("roles"); roles[Reactions] = QByteArrayLiteral("reactions"); roles[Ignored] = QByteArrayLiteral("userIsIgnored"); roles[Pinned] = QByteArrayLiteral("pinned"); roles[DiscussionCount] = QByteArrayLiteral("discussionCount"); roles[DiscussionRoomId] = QByteArrayLiteral("discussionRoomId"); roles[DiscussionLastMessage] = QByteArrayLiteral("discussionLastMessage"); roles[ThreadCount] = QByteArrayLiteral("threadCount"); roles[ThreadLastMessage] = QByteArrayLiteral("threadLastMessage"); roles[ThreadMessageId] = QByteArrayLiteral("threadMessageId"); return roles; } qint64 MessageModel::lastTimestamp() const { if (!mAllMessages.isEmpty()) { //qCDebug(RUQOLA_LOG) << "returning timestamp" << mAllMessages.last().timeStamp(); return mAllMessages.first().timeStamp(); } else { return 0; } } int MessageModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return mAllMessages.size(); } void MessageModel::addMessage(const Message &message) { auto it = std::upper_bound(mAllMessages.begin(), mAllMessages.end(), message, [](const Message &lhs, const Message &rhs) -> bool { return lhs.timeStamp() < rhs.timeStamp(); } ); //When we have 1 element. if (mAllMessages.count() == 1 && (*mAllMessages.begin()).messageId() == message.messageId()) { (*mAllMessages.begin()) = message; //const QModelIndex index = createIndex(0, 0); qCDebug(RUQOLA_LOG) << "Update Message"; //Q_EMIT dataChanged(index, index); //For the moment !!!! It's not optimal but Q_EMIT dataChanged(index, index); doesn't work beginRemoveRows(QModelIndex(), 0, 0); endRemoveRows(); beginInsertRows(QModelIndex(), 0, 0); endInsertRows(); } else if (((it) != mAllMessages.begin() && (*(it - 1)).messageId() == message.messageId())) { qCDebug(RUQOLA_LOG) << "Update Message"; (*(it-1)) = message; //const QModelIndex index = createIndex(it - 1 - mAllMessages.begin(), 0); //For the moment !!!! It's not optimal but Q_EMIT dataChanged(index, index); doesn't work beginRemoveRows(QModelIndex(), it - 1 - mAllMessages.begin(), it - 1 - mAllMessages.begin()); endRemoveRows(); beginInsertRows(QModelIndex(), it - 1 - mAllMessages.begin(), it - 1 - mAllMessages.begin()); endInsertRows(); //Q_EMIT dataChanged(index, index); } else { const int pos = it - mAllMessages.begin(); beginInsertRows(QModelIndex(), pos, pos); mAllMessages.insert(it, message); endInsertRows(); } } QVariant MessageModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) { qCWarning(RUQOLA_LOG) << "ERROR: invalid index"; return {}; } const int idx = index.row(); switch (role) { case MessageModel::Username: return mAllMessages.at(idx).username(); case MessageModel::OriginalMessage: return mAllMessages.at(idx).text(); case MessageModel::MessageConvertedText: //TODO improve it. if (mAllMessages.at(idx).messageType() == Message::System) { return mAllMessages.at(idx).messageTypeText(); } else { if (mRoom && mRoom->userIsIgnored(mAllMessages.at(idx).userId())) { return QString(QStringLiteral("") + i18n("Ignored Message") + QStringLiteral("")); } const QString userName = mRocketChatAccount ? mRocketChatAccount->userName() : QString(); return convertMessageText(mAllMessages.at(idx).text(), mAllMessages.at(idx).mentions(), userName); } case MessageModel::Timestamp: return mAllMessages.at(idx).timeStamp(); case MessageModel::UserId: return mAllMessages.at(idx).userId(); case MessageModel::SystemMessageType: return mAllMessages.at(idx).systemMessageType(); case MessageModel::MessageId: return mAllMessages.at(idx).messageId(); case MessageModel::Alias: return mAllMessages.at(idx).alias(); case MessageModel::MessageType: return mAllMessages.at(idx).messageType(); case MessageModel::Avatar: return mAllMessages.at(idx).avatar(); case MessageModel::EditedAt: return mAllMessages.at(idx).editedAt(); case MessageModel::EditedByUserName: return mAllMessages.at(idx).editedByUsername(); case MessageModel::Attachments: { QVariantList lst; lst.reserve(mAllMessages.at(idx).attachements().count()); const auto attachs = mAllMessages.at(idx).attachements(); for (const MessageAttachment &att : attachs) { lst.append(QVariant::fromValue(att)); } return lst; } case MessageModel::Urls: { QVariantList lst; lst.reserve(mAllMessages.at(idx).urls().count()); const auto urls = mAllMessages.at(idx).urls(); for (const MessageUrl &url : urls) { lst.append(QVariant::fromValue(url)); } return lst; } case MessageModel::Date: if (idx > 0) { QDateTime previewDate; previewDate.setMSecsSinceEpoch(mAllMessages.at(idx - 1).timeStamp()); QDateTime currentDate; currentDate.setMSecsSinceEpoch(mAllMessages.at(idx).timeStamp()); if (previewDate.date() != currentDate.date()) { return currentDate.date().toString(); } } return QString(); case MessageModel::CanEditingMessage: return (mAllMessages.at(idx).timeStamp() + (mRocketChatAccount ? mRocketChatAccount->ruqolaServerConfig()->blockEditingMessageInMinutes() * 60 * 1000 : 0)) > QDateTime::currentMSecsSinceEpoch(); case MessageModel::Starred: return mAllMessages.at(idx).starred(); case MessageModel::UsernameUrl: { const QString username = mAllMessages.at(idx).username(); if (username.isEmpty()) { return {}; } return QStringLiteral("@%1").arg(mAllMessages.at(idx).username()); } case MessageModel::Roles: return roomRoles(mAllMessages.at(idx).userId()); case MessageModel::Reactions: { QVariantList lst; const auto reactions = mAllMessages.at(idx).reactions().reactions(); lst.reserve(reactions.count()); for (const Reaction &react : reactions) { //Convert reactions lst.append(QVariant::fromValue(react)); } return lst; } case MessageModel::Ignored: return mRoom && mRoom->userIsIgnored(mAllMessages.at(idx).userId()); case MessageModel::Pinned: return mAllMessages.at(idx).messagePinned().pinned(); case MessageModel::DiscussionCount: return mAllMessages.at(idx).discussionCount(); case MessageModel::DiscussionRoomId: return mAllMessages.at(idx).discussionRoomId(); case MessageModel::DiscussionLastMessage: return mAllMessages.at(idx).discussionLastMessage(); case MessageModel::ThreadCount: return mAllMessages.at(idx).threadCount(); case MessageModel::ThreadLastMessage: return mAllMessages.at(idx).threadLastMessage(); case MessageModel::ThreadMessageId: return mAllMessages.at(idx).threadMessageId(); case MessageModel::Groupable: return mAllMessages.at(idx).groupable(); } - Q_UNREACHABLE(); + return {}; } QStringList MessageModel::roomRoles(const QString &userId) const { if (mRoom) { return mRoom->rolesForUserId(userId); } return QStringList(); } QString MessageModel::convertMessageText(const QString &str, const QMap &mentions, const QString &userName) const { return mTextConverter->convertMessageText(str, mentions, userName); } void MessageModel::setRoomID(const QString &roomID) { mRoomID = roomID; } bool MessageModel::isEmpty() const { return mAllMessages.isEmpty(); } void MessageModel::deleteMessage(const QString &messageId) { for (int i = 0, total = mAllMessages.count(); i < total; ++i) { if (mAllMessages.at(i).messageId() == messageId) { beginRemoveRows(QModelIndex(), i, i); mAllMessages.remove(i); endRemoveRows(); break; } } } qint64 MessageModel::generateNewStartTimeStamp(qint64 lastTimeStamp) { return mLoadRecentHistoryManager->generateNewStartTimeStamp(lastTimeStamp); } diff --git a/src/ruqolacore/model/notificationdesktopdurationpreferencemodel.cpp b/src/ruqolacore/model/notificationdesktopdurationpreferencemodel.cpp index 57377ea2..97b27f9a 100644 --- a/src/ruqolacore/model/notificationdesktopdurationpreferencemodel.cpp +++ b/src/ruqolacore/model/notificationdesktopdurationpreferencemodel.cpp @@ -1,103 +1,103 @@ /* Copyright (c) 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 "notificationdesktopdurationpreferencemodel.h" #include NotificationDesktopDurationPreferenceModel::NotificationDesktopDurationPreferenceModel(QObject *parent) : QAbstractListModel(parent) { fillModel(); } NotificationDesktopDurationPreferenceModel::~NotificationDesktopDurationPreferenceModel() { } int NotificationDesktopDurationPreferenceModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return mNotificationDestktopDurationPreferenceList.count(); } QVariant NotificationDesktopDurationPreferenceModel::data(const QModelIndex &index, int role) const { const int rowIndex = index.row(); if (rowIndex < 0 || rowIndex >= mNotificationDestktopDurationPreferenceList.count()) { return {}; } NotificationDesktopDurationPreferenceInfo preferenceInfo = mNotificationDestktopDurationPreferenceList.at(rowIndex); switch (role) { case NotificationPreferenceI18n: return preferenceInfo.displayText; case NotificationPreference: return preferenceInfo.preference; } - Q_UNREACHABLE(); + return {}; } QHash NotificationDesktopDurationPreferenceModel::roleNames() const { QHash roles; roles[NotificationPreferenceI18n] = QByteArrayLiteral("preferencei18n"); roles[NotificationPreference] = QByteArrayLiteral("preference"); return roles; } void NotificationDesktopDurationPreferenceModel::fillModel() { mNotificationDestktopDurationPreferenceList.reserve(6); { //Default ???? Verify it. Perhaps 0 ? Don't know NotificationDesktopDurationPreferenceInfo preferenceInfo; preferenceInfo.displayText = i18n("Default"); preferenceInfo.preference = QStringLiteral("default"); mNotificationDestktopDurationPreferenceList.append(preferenceInfo); } for (int i = 1; i <= 5; ++i) { NotificationDesktopDurationPreferenceInfo preferenceInfo; preferenceInfo.displayText = i18np("1 second", "%1 seconds", i); preferenceInfo.preference = QString::number(i); mNotificationDestktopDurationPreferenceList.append(preferenceInfo); } } int NotificationDesktopDurationPreferenceModel::setCurrentNotificationPreference(const QString &preference) { int newStatusIndex = 0; for (int i = 0; i < mNotificationDestktopDurationPreferenceList.count(); ++i) { if (mNotificationDestktopDurationPreferenceList.at(i).preference == preference) { newStatusIndex = i; break; } } if (mCurrentPreference != newStatusIndex) { mCurrentPreference = newStatusIndex; Q_EMIT currentNotificationPreferenceChanged(); } return mCurrentPreference; } QString NotificationDesktopDurationPreferenceModel::currentPreference(int index) const { const QString str = mNotificationDestktopDurationPreferenceList.at(index).preference; return str; } diff --git a/src/ruqolacore/model/notificationdesktopsoundpreferencemodel.cpp b/src/ruqolacore/model/notificationdesktopsoundpreferencemodel.cpp index e823a69e..e2b8d17a 100644 --- a/src/ruqolacore/model/notificationdesktopsoundpreferencemodel.cpp +++ b/src/ruqolacore/model/notificationdesktopsoundpreferencemodel.cpp @@ -1,139 +1,139 @@ /* Copyright (c) 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 "notificationdesktopsoundpreferencemodel.h" #include NotificationDesktopSoundPreferenceModel::NotificationDesktopSoundPreferenceModel(QObject *parent) : QAbstractListModel(parent) { fillModel(); } NotificationDesktopSoundPreferenceModel::~NotificationDesktopSoundPreferenceModel() { } int NotificationDesktopSoundPreferenceModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return mNotificationDestktopSoundPreferenceList.count(); } QVariant NotificationDesktopSoundPreferenceModel::data(const QModelIndex &index, int role) const { const int rowIndex = index.row(); if (rowIndex < 0 || rowIndex >= mNotificationDestktopSoundPreferenceList.count()) { return {}; } NotificationDesktopSoundPreferenceInfo preferenceInfo = mNotificationDestktopSoundPreferenceList.at(rowIndex); switch (role) { case NotificationPreferenceI18n: return preferenceInfo.displayText; case NotificationPreference: return preferenceInfo.preference; } - Q_UNREACHABLE(); + return {}; } QHash NotificationDesktopSoundPreferenceModel::roleNames() const { QHash roles; roles[NotificationPreferenceI18n] = QByteArrayLiteral("preferencei18n"); roles[NotificationPreference] = QByteArrayLiteral("preference"); return roles; } void NotificationDesktopSoundPreferenceModel::fillModel() { mNotificationDestktopSoundPreferenceList.reserve(8); //This one must be first one. { NotificationDesktopSoundPreferenceInfo preferenceInfo; preferenceInfo.displayText = i18n("Default"); preferenceInfo.preference = QStringLiteral("default"); mNotificationDestktopSoundPreferenceList.append(preferenceInfo); } { NotificationDesktopSoundPreferenceInfo preferenceInfo; preferenceInfo.displayText = i18n("Nothing"); preferenceInfo.preference = QStringLiteral("none"); mNotificationDestktopSoundPreferenceList.append(preferenceInfo); } { NotificationDesktopSoundPreferenceInfo preferenceInfo; preferenceInfo.displayText = i18n("Beep"); preferenceInfo.preference = QStringLiteral("beep"); mNotificationDestktopSoundPreferenceList.append(preferenceInfo); } { NotificationDesktopSoundPreferenceInfo preferenceInfo; preferenceInfo.displayText = i18n("Chelle"); preferenceInfo.preference = QStringLiteral("chelle"); mNotificationDestktopSoundPreferenceList.append(preferenceInfo); } { NotificationDesktopSoundPreferenceInfo preferenceInfo; preferenceInfo.displayText = i18n("Ding"); preferenceInfo.preference = QStringLiteral("ding"); mNotificationDestktopSoundPreferenceList.append(preferenceInfo); } { NotificationDesktopSoundPreferenceInfo preferenceInfo; preferenceInfo.displayText = i18n("Droplet"); preferenceInfo.preference = QStringLiteral("droplet"); mNotificationDestktopSoundPreferenceList.append(preferenceInfo); } { NotificationDesktopSoundPreferenceInfo preferenceInfo; preferenceInfo.displayText = i18n("Highbell"); preferenceInfo.preference = QStringLiteral("highbell"); mNotificationDestktopSoundPreferenceList.append(preferenceInfo); } { NotificationDesktopSoundPreferenceInfo preferenceInfo; preferenceInfo.displayText = i18n("Seasons"); preferenceInfo.preference = QStringLiteral("seasons"); mNotificationDestktopSoundPreferenceList.append(preferenceInfo); } } int NotificationDesktopSoundPreferenceModel::setCurrentNotificationPreference(const QString &preference) { int newStatusIndex = 0; for (int i = 0; i < mNotificationDestktopSoundPreferenceList.count(); ++i) { if (mNotificationDestktopSoundPreferenceList.at(i).preference == preference) { newStatusIndex = i; break; } } if (mCurrentPreference != newStatusIndex) { mCurrentPreference = newStatusIndex; Q_EMIT currentNotificationPreferenceChanged(); } return mCurrentPreference; } QString NotificationDesktopSoundPreferenceModel::currentPreference(int index) const { const QString str = mNotificationDestktopSoundPreferenceList.at(index).preference; return str; } diff --git a/src/ruqolacore/model/notificationpreferencemodel.cpp b/src/ruqolacore/model/notificationpreferencemodel.cpp index 72256b0c..1a8570a6 100644 --- a/src/ruqolacore/model/notificationpreferencemodel.cpp +++ b/src/ruqolacore/model/notificationpreferencemodel.cpp @@ -1,113 +1,113 @@ /* Copyright (c) 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 "notificationpreferencemodel.h" #include #include NotificationPreferenceModel::NotificationPreferenceModel(QObject *parent) : QAbstractListModel(parent) { fillModel(); } NotificationPreferenceModel::~NotificationPreferenceModel() { } int NotificationPreferenceModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return mNotificationPreferenceList.count(); } QVariant NotificationPreferenceModel::data(const QModelIndex &index, int role) const { if (index.row() < 0 || index.row() >= mNotificationPreferenceList.count()) { return {}; } NotificationPreferenceInfo preferenceInfo = mNotificationPreferenceList.at(index.row()); switch (role) { case NotificationPreferenceI18n: return preferenceInfo.displayText; case NotificationPreference: return preferenceInfo.preference; } - Q_UNREACHABLE(); + return {}; } QHash NotificationPreferenceModel::roleNames() const { QHash roles; roles[NotificationPreferenceI18n] = QByteArrayLiteral("preferencei18n"); roles[NotificationPreference] = QByteArrayLiteral("preference"); return roles; } void NotificationPreferenceModel::fillModel() { mNotificationPreferenceList.reserve(4); { NotificationPreferenceInfo preferenceInfo; preferenceInfo.displayText = i18n("Default"); preferenceInfo.preference = QStringLiteral("default"); mNotificationPreferenceList.append(preferenceInfo); } { NotificationPreferenceInfo preferenceInfo; preferenceInfo.displayText = i18n("All Messages"); preferenceInfo.preference = QStringLiteral("all"); mNotificationPreferenceList.append(preferenceInfo); } { NotificationPreferenceInfo preferenceInfo; preferenceInfo.displayText = i18n("Mentions"); preferenceInfo.preference = QStringLiteral("mentions"); mNotificationPreferenceList.append(preferenceInfo); } { NotificationPreferenceInfo preferenceInfo; preferenceInfo.displayText = i18n("Nothing"); preferenceInfo.preference = QStringLiteral("nothing"); mNotificationPreferenceList.append(preferenceInfo); } } int NotificationPreferenceModel::setCurrentNotificationPreference(const QString &preference) { int newStatusIndex = 0; for (int i = 0; i < mNotificationPreferenceList.count(); ++i) { if (mNotificationPreferenceList.at(i).preference == preference) { newStatusIndex = i; break; } } if (mCurrentPreference != newStatusIndex) { mCurrentPreference = newStatusIndex; Q_EMIT currentNotificationPreferenceChanged(); } return mCurrentPreference; } QString NotificationPreferenceModel::currentPreference(int index) const { const QString str = mNotificationPreferenceList.at(index).preference; return str; } diff --git a/src/ruqolacore/model/searchchannelmodel.cpp b/src/ruqolacore/model/searchchannelmodel.cpp index 29d76aa0..88de2487 100644 --- a/src/ruqolacore/model/searchchannelmodel.cpp +++ b/src/ruqolacore/model/searchchannelmodel.cpp @@ -1,166 +1,166 @@ /* Copyright (c) 2018-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 "searchchannelmodel.h" #include "ruqola_debug.h" #include #include #include SearchChannelModel::SearchChannelModel(QObject *parent) : QAbstractListModel(parent) { } SearchChannelModel::~SearchChannelModel() { } void SearchChannelModel::setChannels(const QVector &channels) { if (rowCount() != 0) { beginRemoveRows(QModelIndex(), 0, mChannel.count() - 1); mChannel.clear(); endRemoveRows(); } if (!channels.isEmpty()) { beginInsertRows(QModelIndex(), 0, channels.count() - 1); mChannel = channels; endInsertRows(); } } void SearchChannelModel::parseChannels(const QJsonObject &obj) { QVector channelList; const QJsonArray rooms = obj.value(QLatin1String("rooms")).toArray(); for (int i = 0; i < rooms.size(); i++) { const QJsonObject o = rooms.at(i).toObject(); Channel channel; channel.parseChannel(o, Channel::ChannelType::Room); //Verify that it's valid channelList.append(channel); } const QJsonArray users = obj.value(QLatin1String("users")).toArray(); for (int i = 0; i < users.size(); i++) { const QJsonObject o = users.at(i).toObject(); Channel channel; channel.parseChannel(o, Channel::ChannelType::PrivateChannel); //Verify that it's valid channelList.append(channel); } setChannels(channelList); } void SearchChannelModel::clear() { if (!mChannel.isEmpty()) { beginRemoveRows(QModelIndex(), 0, mChannel.count() - 1); mChannel.clear(); endRemoveRows(); } } int SearchChannelModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return mChannel.count(); } QVariant SearchChannelModel::data(const QModelIndex &index, int role) const { if (index.row() < 0 || index.row() >= mChannel.count()) { return {}; } const Channel channel = mChannel.at(index.row()); switch (role) { case SearchChannelModel::ChannelId: return channelId(channel); case SearchChannelModel::ChannelName: return channelName(channel); case SearchChannelModel::IconName: return channelIconName(channel); case SearchChannelModel::ChannelType: return channel.type(); } - Q_UNREACHABLE(); + return {}; } QString SearchChannelModel::channelId(const Channel &channel) const { //Specific channelId for opening room //For private channel we need to use username for channel we need roomId switch (channel.type()) { case Channel::ChannelType::PrivateChannel: return channel.user().userName(); case Channel::ChannelType::Room: return channel.roomId(); case Channel::ChannelType::Unknown: qCWarning(RUQOLA_LOG) << "Unknown channel type!"; return {}; } return {}; } QString SearchChannelModel::channelName(const Channel &channel) const { switch (channel.type()) { case Channel::ChannelType::PrivateChannel: return channel.user().userName(); case Channel::ChannelType::Room: return channel.roomName(); case Channel::ChannelType::Unknown: qCWarning(RUQOLA_LOG) << "Unknown channel type!"; return {}; } return {}; } QIcon SearchChannelModel::channelIconName(const Channel &channel) const { switch (channel.type()) { case Channel::ChannelType::PrivateChannel: return QIcon::fromTheme(channel.user().iconFromStatus()); case Channel::ChannelType::Room: if (channel.roomType() == QLatin1String("c")) { return QIcon::fromTheme(QStringLiteral("irc-channel-inactive")); } else if (channel.roomType() == QLatin1String("p")) { return QIcon::fromTheme(QStringLiteral("lock")); } qCWarning(RUQOLA_LOG) << "Unknown room type!" << channel.roomType(); return {}; case Channel::ChannelType::Unknown: qCWarning(RUQOLA_LOG) << "Unknown channel type!"; return {}; } return {}; } QHash SearchChannelModel::roleNames() const { QHash roles; roles[SearchChannelModel::ChannelName] = QByteArrayLiteral("channelname"); roles[SearchChannelModel::ChannelId] = QByteArrayLiteral("channelid"); roles[SearchChannelModel::IconName] = QByteArrayLiteral("iconname"); roles[SearchChannelModel::ChannelType] = QByteArrayLiteral("channeltype"); return roles; } diff --git a/src/ruqolacore/model/searchmessagemodel.cpp b/src/ruqolacore/model/searchmessagemodel.cpp index 08ad366d..e6d978a0 100644 --- a/src/ruqolacore/model/searchmessagemodel.cpp +++ b/src/ruqolacore/model/searchmessagemodel.cpp @@ -1,110 +1,109 @@ /* Copyright (c) 2018-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 "searchmessagemodel.h" #include "ruqola_debug.h" #include SearchMessageModel::SearchMessageModel(QObject *parent) : QAbstractListModel(parent) { } SearchMessageModel::~SearchMessageModel() { } QVariant SearchMessageModel::data(const QModelIndex &index, int role) const { if (index.row() < 0 || index.row() >= mSearchMessages.count()) { return {}; } const SearchMessage message = mSearchMessages.at(index.row()); switch (role) { case MessageConvertedText: return message.text(); case Timestamp: return message.timeStamp(); case MessageId: - //TODO ? - return {}; + return message.messageId(); case UserId: - //TODO ? - return {}; + return message.userId(); case SystemMessageType: //TODO ? return {}; } return {}; } QHash SearchMessageModel::roleNames() const { QHash roles; roles[SearchMessageModel::MessageConvertedText] = QByteArrayLiteral("messagetext"); - roles[SearchMessageModel::Timestamp] = QByteArrayLiteral("timestamp"); + roles[SearchMessageModel::Timestamp] = QByteArrayLiteral("messagetimestamp"); roles[SearchMessageModel::MessageId] = QByteArrayLiteral("messageid"); + roles[SearchMessageModel::SystemMessageType] = QByteArrayLiteral("systemmessagetype"); //Add more ???? return roles; } int SearchMessageModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return mSearchMessages.count(); } void SearchMessageModel::parseResult(const QJsonObject &obj, bool restApi) { QVector messages; const QJsonArray messagesObj = obj.value(QLatin1String("messages")).toArray(); for (int i = 0; i < messagesObj.size(); i++) { const QJsonObject o = messagesObj.at(i).toObject(); SearchMessage msg; - msg.parseResult(o, restApi); + msg.parseMessage(o, restApi); //Verify that it's valid messages.append(msg); } setMessages(messages); } void SearchMessageModel::clear() { if (!mSearchMessages.isEmpty()) { beginRemoveRows(QModelIndex(), 0, mSearchMessages.count() - 1); mSearchMessages.clear(); endRemoveRows(); } } void SearchMessageModel::setMessages(const QVector &messages) { if (rowCount() != 0) { beginRemoveRows(QModelIndex(), 0, mSearchMessages.count() - 1); mSearchMessages.clear(); endRemoveRows(); } if (!messages.isEmpty()) { beginInsertRows(QModelIndex(), 0, messages.count() - 1); mSearchMessages = messages; endInsertRows(); } } diff --git a/src/ruqolacore/model/statusmodel.cpp b/src/ruqolacore/model/statusmodel.cpp index 57d1a183..72fdbe70 100644 --- a/src/ruqolacore/model/statusmodel.cpp +++ b/src/ruqolacore/model/statusmodel.cpp @@ -1,128 +1,128 @@ /* 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 "statusmodel.h" #include "ruqola_debug.h" #include StatusModel::StatusModel(QObject *parent) : QAbstractListModel(parent) { fillModel(); } StatusModel::~StatusModel() { } User::PresenceStatus StatusModel::currentUserStatus() const { return mStatusList.at(mCurrentStatus).status; } User::PresenceStatus StatusModel::status(int index) const { return mStatusList.at(index).status; } QHash StatusModel::roleNames() const { QHash roles; roles[StatusI18n] = QByteArrayLiteral("statusi18n"); roles[Status] = QByteArrayLiteral("status"); roles[Icon] = QByteArrayLiteral("icon"); return roles; } void StatusModel::setCurrentPresenceStatus(User::PresenceStatus status) { int newStatusIndex = 0; for (int i = 0; i < mStatusList.count(); ++i) { if (mStatusList.at(i).status == status) { newStatusIndex = i; break; } } if (mCurrentStatus != newStatusIndex) { mCurrentStatus = newStatusIndex; Q_EMIT currentStatusChanged(); } } void StatusModel::fillModel() { { StatusInfo statusInfo; statusInfo.displayText = i18n("Online"); statusInfo.icon = QIcon::fromTheme(QStringLiteral("im-user-online")); statusInfo.status = User::PresenceStatus::PresenceOnline; mStatusList.append(statusInfo); } { StatusInfo statusInfo; statusInfo.displayText = i18n("Busy"); statusInfo.icon = QIcon::fromTheme(QStringLiteral("im-user-busy")); statusInfo.status = User::PresenceStatus::PresenceBusy; mStatusList.append(statusInfo); } { StatusInfo statusInfo; statusInfo.displayText = i18n("Away"); statusInfo.icon = QIcon::fromTheme(QStringLiteral("im-user-away")); statusInfo.status = User::PresenceStatus::PresenceAway; mStatusList.append(statusInfo); } { StatusInfo statusInfo; statusInfo.displayText = i18n("Offline"); statusInfo.icon = QIcon::fromTheme(QStringLiteral("im-user-offline")); statusInfo.status = User::PresenceStatus::PresenceOffline; mStatusList.append(statusInfo); } } int StatusModel::currentStatus() const { return mCurrentStatus; } int StatusModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return mStatusList.count(); } QVariant StatusModel::data(const QModelIndex &index, int role) const { if (index.row() < 0 || index.row() >= mStatusList.count()) { return {}; } StatusInfo statusInfo = mStatusList.at(index.row()); switch (role) { case StatusI18n: return statusInfo.displayText; case Status: return QVariant::fromValue(statusInfo.status); case Icon: return statusInfo.icon; } - Q_UNREACHABLE(); + return {}; } diff --git a/src/ruqolacore/model/usercompletermodel.cpp b/src/ruqolacore/model/usercompletermodel.cpp index 7e65b695..8871b79c 100644 --- a/src/ruqolacore/model/usercompletermodel.cpp +++ b/src/ruqolacore/model/usercompletermodel.cpp @@ -1,88 +1,88 @@ /* 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 "usercompletermodel.h" #include "ruqola_debug.h" #include UserCompleterModel::UserCompleterModel(QObject *parent) : QAbstractListModel(parent) { } UserCompleterModel::~UserCompleterModel() { } void UserCompleterModel::clear() { if (!mUsers.isEmpty()) { beginRemoveRows(QModelIndex(), 0, rowCount() - 1); mUsers.clear(); endRemoveRows(); } } void UserCompleterModel::insertUsers(const QVector &users) { if (rowCount() != 0) { beginRemoveRows(QModelIndex(), 0, mUsers.count() - 1); mUsers.clear(); endRemoveRows(); } if (!users.isEmpty()) { beginInsertRows(QModelIndex(), 0, users.count() - 1); mUsers = users; endInsertRows(); } } int UserCompleterModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return mUsers.count(); } QVariant UserCompleterModel::data(const QModelIndex &index, int role) const { if (index.row() < 0 || index.row() >= mUsers.count()) { return QVariant(); } const User user = mUsers.at(index.row()); switch (role) { case UserName: return user.userName(); case UserId: return user.userId(); case UserIconStatus: return user.iconFromStatus(); } - Q_UNREACHABLE(); + return {}; } QHash UserCompleterModel::roleNames() const { QHash roles; roles[UserName] = QByteArrayLiteral("username"); roles[UserId] = QByteArrayLiteral("userid"); roles[UserIconStatus] = QByteArrayLiteral("iconstatus"); return roles; } diff --git a/src/ruqolacore/model/usersforroommodel.cpp b/src/ruqolacore/model/usersforroommodel.cpp index 978ad54e..f689e901 100644 --- a/src/ruqolacore/model/usersforroommodel.cpp +++ b/src/ruqolacore/model/usersforroommodel.cpp @@ -1,196 +1,196 @@ /* 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 "usersforroommodel.h" #include "usersmodel.h" #include "ruqola_debug.h" #include #include UsersForRoomModel::UsersForRoomModel(QObject *parent) : QAbstractListModel(parent) { } UsersForRoomModel::~UsersForRoomModel() { } void UsersForRoomModel::removeUser(const QString &userId) { //TODO verify if it } void UsersForRoomModel::addUser(const User &users) { //TODO verify if it } void UsersForRoomModel::setUsers(const QVector &users) { if (rowCount() != 0) { beginRemoveRows(QModelIndex(), 0, mUsers.count() - 1); mUsers.clear(); endRemoveRows(); } if (!users.isEmpty()) { beginInsertRows(QModelIndex(), 0, users.count() - 1); mUsers = users; endInsertRows(); } } int UsersForRoomModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return mUsers.count(); } QVariant UsersForRoomModel::data(const QModelIndex &index, int role) const { if (index.row() < 0 || index.row() >= mUsers.count()) { return QVariant(); } const User user = mUsers.at(index.row()); switch (role) { case DisplayName: return generateDisplayName(user); case UserName: return user.userName(); case IconStatus: return user.iconFromStatus(); case UserId: return user.userId(); case Name: return user.name(); } - Q_UNREACHABLE(); + return {}; } QString UsersForRoomModel::generateDisplayName(const User &user) const { const QString displayName = QStringLiteral("%1").arg(user.userName().isEmpty() ? user.name() : user.userName()); return displayName; } QHash UsersForRoomModel::roleNames() const { QHash roles; roles[UserName] = QByteArrayLiteral("username"); roles[Name] = QByteArrayLiteral("name"); roles[UserId] = QByteArrayLiteral("userid"); roles[IconStatus] = QByteArrayLiteral("iconstatus"); roles[DisplayName] = QByteArrayLiteral("displayname"); return roles; } void UsersForRoomModel::parseUsersForRooms(const QJsonObject &root, UsersModel *model, bool restapi) { if (restapi) { int total = root[QLatin1String("total")].toInt(); const QJsonArray members = root[QStringLiteral("members")].toArray(); QVector users; users.reserve(members.count()); for (const QJsonValue ¤t : members) { if (current.type() == QJsonValue::Object) { const QJsonObject userObject = current.toObject(); const QString userName = userObject[QStringLiteral("username")].toString(); const QString name = userObject[QStringLiteral("name")].toString(); const QString id = userObject[QStringLiteral("_id")].toString(); const int utcOffset = userObject[QStringLiteral("utcOffset")].toInt(); const QString status = userObject[QStringLiteral("status")].toString(); User user; user.setName(name); user.setUserName(userName); user.setUserId(id); user.setUtcOffset(utcOffset); user.setStatus(status); if (user.isValid()) { users.append(user); } else { qCWarning(RUQOLA_LOG) << "Invalid user" << user; total--; } } else { qCWarning(RUQOLA_LOG) << "Parse records: Error in users for rooms json" << root; } } if (users.count() != total) { qCWarning(RUQOLA_LOG) << "Users for rooms, parsing error. Parse " << users.count() << " users but json give us a total number : "<< total; } setUsers(users); } else { const QJsonObject result = root[QLatin1String("result")].toObject(); if (!result.isEmpty()) { const QJsonArray records = result[QStringLiteral("records")].toArray(); int total = result[QLatin1String("total")].toInt(); QVector users; users.reserve(records.count()); for (const QJsonValue ¤t : records) { if (current.type() == QJsonValue::Object) { const QJsonObject userObject = current.toObject(); const QString userName = userObject[QStringLiteral("username")].toString(); const QString name = userObject[QStringLiteral("name")].toString(); const QString id = userObject[QStringLiteral("_id")].toString(); User user; user.setName(name); user.setUserName(userName); user.setUserId(id); if (model) { user.setStatus(model->status(id)); } //Add status! if (user.isValid()) { users.append(user); } else { qCWarning(RUQOLA_LOG) << "Invalid user" << user; total--; } } else { qCWarning(RUQOLA_LOG) << "Parse records: Error in users for rooms json" << root; } } if (users.count() != total) { qCWarning(RUQOLA_LOG) << "Users for rooms, parsing error. Parse " << users.count() << " users but json give us a total number : "<< total; } setUsers(users); } else { qCWarning(RUQOLA_LOG) << "Error in users for rooms json" << root; } } } void UsersForRoomModel::userStatusChanged(const User &newuser) { const int roomCount = mUsers.count(); for (int i = 0; i < roomCount; ++i) { User user = mUsers.at(i); if (newuser.userId() == user.userId()) { user.setStatus(newuser.status()); mUsers.replace(i, user); const QModelIndex idx = createIndex(i, 0); Q_EMIT dataChanged(idx, idx); } } } diff --git a/src/ruqolacore/model/usersmodel.cpp b/src/ruqolacore/model/usersmodel.cpp index 76267649..392dcc8f 100644 --- a/src/ruqolacore/model/usersmodel.cpp +++ b/src/ruqolacore/model/usersmodel.cpp @@ -1,174 +1,174 @@ /* 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 "usersmodel.h" #include "ruqola_debug.h" #include UsersModel::UsersModel(QObject *parent) : QAbstractListModel(parent) { } UsersModel::~UsersModel() { } int UsersModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return mUsers.size(); } QVariant UsersModel::data(const QModelIndex &index, int role) const { if (index.row() < 0 || index.row() >= mUsers.count()) { return QVariant(); } const User user = mUsers.at(index.row()); switch (role) { case UserName: return user.name(); case UserId: return user.userId(); case UserStatus: return user.status(); case UserIcon: return user.iconFromStatus(); } - Q_UNREACHABLE(); + return {}; } QString UsersModel::userStatusIconFileName(const QString &name) { const int userCount = mUsers.count(); for (int i = 0; i < userCount; ++i) { if (mUsers.at(i).userName() == name) { return mUsers.at(i).iconFromStatus(); } } //qCWarning(RUQOLA_LOG) << "User for name " << name << " not defined yet"; return QStringLiteral("user-offline"); } QString UsersModel::status(const QString &userId) const { const int userCount = mUsers.count(); for (int i = 0; i < userCount; ++i) { if (mUsers.at(i).userId() == userId) { return mUsers.at(i).status(); } } //Return offline as default; return QStringLiteral("offline"); } void UsersModel::removeUser(const QString &userId) { qCDebug(RUQOLA_LOG) << " User removed " << userId; const int userCount = mUsers.count(); for (int i = 0; i < userCount; ++i) { if (mUsers.at(i).userId() == userId) { qCDebug(RUQOLA_LOG) << " User removed " << mUsers.at(i).name(); //Send info as it's disconnected. But don't remove it from list User user = mUsers.at(i); user.setStatus(QStringLiteral("offline")); mUsers.replace(i, user); const QModelIndex idx = createIndex(i, 0); Q_EMIT userStatusChanged(user); Q_EMIT dataChanged(idx, idx); break; } } } void UsersModel::addUser(const User &newuser) { //It can be duplicate as we don't remove user from list when user is disconnected. Otherwise it will not sync with // user for room list qCDebug(RUQOLA_LOG) << " User added " << newuser; const int userCount = mUsers.count(); bool found = false; for (int i = 0; i < userCount; ++i) { if (mUsers.at(i).userId() == newuser.userId()) { found = true; User user = mUsers.at(i); user.setStatus(newuser.status()); mUsers.replace(i, user); const QModelIndex idx = createIndex(i, 0); Q_EMIT userStatusChanged(user); Q_EMIT dataChanged(idx, idx); break; } } if (!found) { const int pos = mUsers.size(); beginInsertRows(QModelIndex(), pos, pos); mUsers.append(newuser); endInsertRows(); } } void UsersModel::updateUser(const QJsonObject &array) { const QString id = array.value(QLatin1String("id")).toString(); const int userCount = mUsers.count(); for (int i = 0; i < userCount; ++i) { if (mUsers.at(i).userId() == id) { User user = mUsers.at(i); const QJsonObject fields = array.value(QLatin1String("fields")).toObject(); const QString newStatus = fields.value(QLatin1String("status")).toString(); bool userDataChanged = false; if (!newStatus.isEmpty()) { user.setStatus(newStatus); mUsers.replace(i, user); const QModelIndex idx = createIndex(i, 0); Q_EMIT dataChanged(idx, idx); Q_EMIT userStatusChanged(user); userDataChanged = true; } const QString newName = fields.value(QLatin1String("name")).toString(); if (!newName.isEmpty()) { user.setName(newName); mUsers.replace(i, user); const QModelIndex idx = createIndex(i, 0); Q_EMIT dataChanged(idx, idx); Q_EMIT userNameChanged(user); userDataChanged = true; } const QString newuserName = fields.value(QLatin1String("username")).toString(); if (!newuserName.isEmpty()) { user.setUserName(newuserName); mUsers.replace(i, user); const QModelIndex idx = createIndex(i, 0); Q_EMIT dataChanged(idx, idx); Q_EMIT nameChanged(user); userDataChanged = true; } if (!userDataChanged) { qCWarning(RUQOLA_LOG) << " Unsupported yet user data modification " << array; } break; } } } diff --git a/src/ruqolacore/searchmessage.cpp b/src/ruqolacore/searchmessage.cpp index 747980c6..efc47cdb 100644 --- a/src/ruqolacore/searchmessage.cpp +++ b/src/ruqolacore/searchmessage.cpp @@ -1,46 +1,24 @@ /* Copyright (c) 2018-2019 Montel Laurent 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) any later version. 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; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "searchmessage.h" SearchMessage::SearchMessage() { } - -void SearchMessage::parseResult(const QJsonObject &obj, bool restApi) -{ - mMessage.parseMessage(obj, restApi); -} - -qint64 SearchMessage::timeStamp() const -{ - return mMessage.timeStamp(); -} - -QString SearchMessage::text() const -{ - return mMessage.text(); -} - -QDebug operator <<(QDebug d, const SearchMessage &t) -{ - d << "text " << t.text(); - d << "timeStamp " << t.timeStamp(); - return d; -} diff --git a/src/ruqolacore/searchmessage.h b/src/ruqolacore/searchmessage.h index 367d1df6..9b3f2ce0 100644 --- a/src/ruqolacore/searchmessage.h +++ b/src/ruqolacore/searchmessage.h @@ -1,44 +1,37 @@ /* Copyright (c) 2018-2019 Montel Laurent 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) any later version. 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; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef SEARCHMESSAGE_H #define SEARCHMESSAGE_H #include #include #include "libruqola_private_export.h" #include "messages/message.h" -class LIBRUQOLACORE_TESTS_EXPORT SearchMessage +class LIBRUQOLACORE_TESTS_EXPORT SearchMessage : public Message { Q_GADGET public: SearchMessage(); - - void parseResult(const QJsonObject &obj, bool restApi); - Q_REQUIRED_RESULT QString text() const; - Q_REQUIRED_RESULT qint64 timeStamp() const; -private: - Message mMessage; }; Q_DECLARE_METATYPE(SearchMessage) Q_DECLARE_TYPEINFO(SearchMessage, Q_MOVABLE_TYPE); -LIBRUQOLACORE_EXPORT QDebug operator <<(QDebug d, const SearchMessage &t); #endif // SEARCHMESSAGE_H diff --git a/src/ruqolacore/utils.cpp b/src/ruqolacore/utils.cpp index 81d28747..1bfc0397 100644 --- a/src/ruqolacore/utils.cpp +++ b/src/ruqolacore/utils.cpp @@ -1,166 +1,166 @@ /* 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 "utils.h" #include "ruqola_debug.h" #include #include #include #include #include QUrl Utils::generateServerUrl(const QString &url) { if (url.isEmpty()) { return {}; } QString serverUrl = url; if (serverUrl.startsWith(QLatin1String("https://"))) { serverUrl.replace(QLatin1String("https://"), QLatin1String("wss://")); } else if (serverUrl.startsWith(QLatin1String("http://"))) { serverUrl.replace(QLatin1String("http://"), QLatin1String("ws://")); } else { serverUrl = QStringLiteral("wss://") + serverUrl; } return QUrl(serverUrl + QStringLiteral("/websocket")); } QString Utils::extractRoomUserFromUrl(QString url) { url.remove(QStringLiteral("ruqola:/user/")); url.remove(QStringLiteral("ruqola:/room/")); return url; } QString Utils::markdownToRichText(const QString &markDown) { //qCDebug(RUQOLA_LOG) << "BEFORE markdownToRichText "< need to investigate //str.remove(QStringLiteral("
")); //qCDebug(RUQOLA_LOG) << "markdownToRichText "< &mentions, const QString &username) { //Not using mentions for the moment. Q_UNUSED(mentions) QString newStr = Utils::markdownToRichText(str); static const QRegularExpression regularExpressionUser(QStringLiteral("(^|\\s+)@([\\w._-]+)")); QRegularExpressionMatchIterator userIterator = regularExpressionUser.globalMatch(newStr); while (userIterator.hasNext()) { const QRegularExpressionMatch match = userIterator.next(); const QString word = match.captured(2); //Highlight only if it's yours if (word == username) { //Improve color newStr.replace(QLatin1Char('@') + word, QStringLiteral("@%1").arg(word)); } else { newStr.replace(QLatin1Char('@') + word, QStringLiteral("@%1").arg(word)); } } static const QRegularExpression regularExpressionRoom(QStringLiteral("(^|\\s+)#([\\w._-]+)")); QRegularExpressionMatchIterator roomIterator = regularExpressionRoom.globalMatch(newStr); while (roomIterator.hasNext()) { const QRegularExpressionMatch match = roomIterator.next(); const QString word = match.captured(2); newStr.replace(QLatin1Char('#') + word, QStringLiteral("#%1").arg(word)); } return newStr; } QString Utils::presenceStatusToString(User::PresenceStatus status) { switch (status) { case User::PresenceStatus::PresenceOnline: return QStringLiteral("online"); case User::PresenceStatus::PresenceBusy: return QStringLiteral("busy"); case User::PresenceStatus::PresenceAway: return QStringLiteral("away"); case User::PresenceStatus::PresenceOffline: return QStringLiteral("offline"); case User::PresenceStatus::Unknown: return {}; } - Q_UNREACHABLE(); + return {}; } User::PresenceStatus Utils::presenceStatusFromString(const QString &status) { if (status == QStringLiteral("online")) { return User::PresenceStatus::PresenceOnline; } else if (status == QStringLiteral("busy")) { return User::PresenceStatus::PresenceBusy; } else if (status == QStringLiteral("away")) { return User::PresenceStatus::PresenceAway; } else if (status == QStringLiteral("offline")) { return User::PresenceStatus::PresenceOffline; } else { qCDebug(RUQOLA_LOG) << "Problem with status " << status; return User::PresenceStatus::Unknown; } } void Utils::parseNotification(const QJsonArray &contents, QString &message, QString &title, QString &sender) { QJsonObject obj = contents.at(0).toObject(); message = obj[QStringLiteral("text")].toString(); title = obj[QStringLiteral("title")].toString(); obj = obj.value(QLatin1String("payload")).toObject(); if (!obj.isEmpty()) { obj = obj.value(QLatin1String("sender")).toObject(); if (!obj.isEmpty()) { sender = obj.value(QLatin1String("_id")).toString(); } else { qCDebug(RUQOLA_LOG) << "Problem with notification json: missing sender"; } } else { qCDebug(RUQOLA_LOG) << "Problem with notification json: missing payload"; } } QString Utils::userIdFromDirectChannel(const QString &rid, const QString &userId) { QString newUserId = rid; newUserId.remove(userId); return newUserId; } qint64 Utils::parseDate(const QString &key, const QJsonObject &o) { return o.value(key).toObject().value(QLatin1String("$date")).toDouble(-1); } qint64 Utils::parseIsoDate(const QString &key, const QJsonObject &o) { if (o.contains(key)) { return QDateTime::fromString(o.value(key).toString(), Qt::ISODate).toMSecsSinceEpoch(); } else { return -1; } }