diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt index 038de5bc..407c2335 100644 --- a/autotests/CMakeLists.txt +++ b/autotests/CMakeLists.txt @@ -1,53 +1,54 @@ add_definitions( -DRUQOLA_DATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data") macro(add_ruqola_test _source) set( _test ${_source}) get_filename_component( _name ${_source} NAME_WE ) add_executable( ${_name} ${_test} ) add_test(NAME ${_name} COMMAND ${_name} ) ecm_mark_as_test(${_name}) target_link_libraries( ${_name} Qt5::Test libruqolacore) endmacro() add_ruqola_test(rocketchatmessagetest.cpp) add_ruqola_test(roommodeltest.cpp) add_ruqola_test(messagemodeltest.cpp) add_ruqola_test(typingnotificationtest.cpp) add_ruqola_test(utilstest.cpp) add_ruqola_test(usertest.cpp) add_ruqola_test(messageattachmenttest.cpp) add_ruqola_test(restapiutiltest.cpp) add_ruqola_test(rocketchataccountsettingstest.cpp) add_ruqola_test(messagetest.cpp) add_ruqola_test(messageurltest.cpp) add_ruqola_test(roomtest.cpp) add_ruqola_test(ruqolaserverconfigtest.cpp) add_ruqola_test(statusmodeltest.cpp) add_ruqola_test(rocketchatcachetest.cpp) add_ruqola_test(textconvertertest.cpp) add_ruqola_test(loadrecenthistorymanagertest.cpp) add_ruqola_test(notificationtest.cpp) add_ruqola_test(emojitest.cpp) add_ruqola_test(emojimanagertest.cpp) add_ruqola_test(otrtest.cpp) add_ruqola_test(otrmanagertest.cpp) add_ruqola_test(rocketchataccounttest.cpp) add_ruqola_test(usersmodeltest.cpp) add_ruqola_test(usersforroommodeltest.cpp) add_ruqola_test(filetest.cpp) add_ruqola_test(filesforroommodeltest.cpp) add_ruqola_test(filesforroomfilterproxymodeltest.cpp) add_ruqola_test(channeltest.cpp) add_ruqola_test(usersforroomfilterproxymodeltest.cpp) add_ruqola_test(usercompletermodeltest.cpp) add_ruqola_test(roomfilterproxymodeltest.cpp) add_ruqola_test(usercompleterfilterproxymodeltest.cpp) add_ruqola_test(searchchannelmodeltest.cpp) add_ruqola_test(searchchannelfilterproxymodeltest.cpp) add_ruqola_test(inputcompletermodeltest.cpp) add_ruqola_test(loginmethodmodeltest.cpp) add_ruqola_test(inputtextmanagertest.cpp) add_ruqola_test(clipboardproxytest.cpp) add_ruqola_test(authenticationinfotest.cpp) add_ruqola_test(searchmessagemodeltest.cpp) add_ruqola_test(searchmessagefilterproxymodeltest.cpp) +add_ruqola_test(searchmessagetest.cpp) add_subdirectory(qml) diff --git a/autotests/searchmessagetest.cpp b/autotests/searchmessagetest.cpp new file mode 100644 index 00000000..06d40276 --- /dev/null +++ b/autotests/searchmessagetest.cpp @@ -0,0 +1,29 @@ +/* + Copyright (C) 2018 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 "searchmessagetest.h" +#include +QTEST_GUILESS_MAIN(SearchMessageTest) + +SearchMessageTest::SearchMessageTest(QObject *parent) + : QObject(parent) +{ + +} diff --git a/autotests/searchmessagetest.h b/autotests/searchmessagetest.h new file mode 100644 index 00000000..f58cab10 --- /dev/null +++ b/autotests/searchmessagetest.h @@ -0,0 +1,33 @@ +/* + Copyright (C) 2018 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 SEARCHMESSAGETEST_H +#define SEARCHMESSAGETEST_H + +#include + +class SearchMessageTest : public QObject +{ + Q_OBJECT +public: + explicit SearchMessageTest(QObject *parent = nullptr); + ~SearchMessageTest() = default; +}; + +#endif // SEARCHMESSAGETEST_H diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1e295cf0..3ad88bc9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,143 +1,144 @@ set (Ruqola_restapi_SRCS restapi/restapirequest.cpp restapi/restapiutil.cpp ) set(Ruqola_ddpapi_SRCS ddpapi/ddpclient.cpp ) set (Ruqola_model_core_srcs model/messagemodel.cpp model/roommodel.cpp model/roomfilterproxymodel.cpp model/usersforroommodel.cpp model/usersforroomfilterproxymodel.cpp model/usersmodel.cpp model/usercompleterfilterproxymodel.cpp model/usercompletermodel.cpp model/statusmodel.cpp model/filesforroommodel.cpp model/filesforroomfilterproxymodel.cpp model/searchchannelmodel.cpp model/searchchannelfilterproxymodel.cpp model/inputcompletermodel.cpp model/loginmethodmodel.cpp model/searchmessagemodel.cpp model/searchmessagefilterproxymodel.cpp ) set(Ruqola_plugins_srcs plugins/pluginauthenticationinterface.cpp plugins/pluginauthentication.cpp ) set(Ruqola_aboutdata_srcs aboutdata/qmlaboutdata.cpp aboutdata/qmlaboutdataauthormodel.cpp ) set (Ruqola_core_srcs ${Ruqola_model_core_srcs} ${Ruqola_plugins_srcs} ${Ruqola_aboutdata_srcs} ${Ruqola_ddpapi_SRCS} ${Ruqola_restapi_SRCS} authenticationinfo.cpp message.cpp room.cpp roomwrapper.cpp ruqola.cpp ruqolautils.cpp rocketchatbackend.cpp notification.cpp messagequeue.cpp rocketchatmessage.cpp typingnotification.cpp changetemporarystatus.cpp user.cpp utils.cpp emoji.cpp emojimanager.cpp clipboardproxy.cpp otr.cpp otrmanager.cpp abstractwebsocket.cpp ruqolawebsocket.cpp messageattachment.cpp messageurl.cpp rocketchataccount.cpp rocketchataccountsettings.cpp ruqolalogger.cpp ruqolaregisterengine.cpp ruqolaserverconfig.cpp rocketchatcache.cpp texthighlighter.cpp textconverter.cpp loadrecenthistorymanager.cpp unityservicemanager.cpp file.cpp channel.cpp inputtextmanager.cpp authenticationmanager.cpp + searchmessage.cpp ) ecm_qt_declare_logging_category(Ruqola_core_srcs HEADER ruqola_debug.h IDENTIFIER RUQOLA_LOG CATEGORY_NAME org.kde.ruqola) ecm_qt_declare_logging_category(Ruqola_core_srcs HEADER ruqola_ddpapi_debug.h IDENTIFIER RUQOLA_DDPAPI_LOG CATEGORY_NAME org.kde.ruqola.ddpapi) ecm_qt_declare_logging_category(Ruqola_core_srcs HEADER ruqola_ddpapi_command_debug.h IDENTIFIER RUQOLA_DDPAPI_COMMAND_LOG CATEGORY_NAME org.kde.ruqola.ddpapi.command) ecm_qt_declare_logging_category(Ruqola_core_srcs HEADER ruqola_restapi_debug.h IDENTIFIER RUQOLA_RESTAPI_LOG CATEGORY_NAME org.kde.ruqola.restapi) add_library(libruqolacore ${Ruqola_core_srcs}) generate_export_header(libruqolacore BASE_NAME libruqolacore) target_link_libraries(libruqolacore Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Qml Qt5::Quick Qt5::WebSockets Qt5::Network Qt5::NetworkAuth Qt5::DBus KF5::CoreAddons KF5::I18n KF5::Crash KF5::Notifications KF5::KIOCore KF5::SyntaxHighlighting ) if (WIN32 OR APPLE) target_link_libraries(libruqolacore KF5::IconThemes) endif() set_target_properties(libruqolacore PROPERTIES OUTPUT_NAME ruqolacore VERSION ${RUQOLA_LIB_VERSION} SOVERSION ${RUQOLA_LIB_SOVERSION} ) qt5_add_resources(RuqolaResources qml/qml.qrc) add_executable(ruqola main.cpp ${RuqolaResources}) target_link_libraries(ruqola libruqolacore) install(TARGETS ruqola ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) install(TARGETS libruqolacore ${KDE_INSTALL_TARGETS_DEFAULT_ARGS} LIBRARY NAMELINK_SKIP) install(PROGRAMS data/org.kde.ruqola.desktop DESTINATION ${KDE_INSTALL_APPDIR}) add_subdirectory(plugins) diff --git a/src/model/searchmessagemodel.cpp b/src/model/searchmessagemodel.cpp index a4eae3e9..5ad9ef7f 100644 --- a/src/model/searchmessagemodel.cpp +++ b/src/model/searchmessagemodel.cpp @@ -1,56 +1,63 @@ /* Copyright (c) 2018 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" SearchMessageModel::SearchMessageModel(QObject *parent) : QAbstractListModel(parent) { } SearchMessageModel::~SearchMessageModel() { } QVariant SearchMessageModel::data(const QModelIndex &index, int role) const { //TODO return {}; } QHash SearchMessageModel::roleNames() const { //TODO return {}; } int SearchMessageModel::rowCount(const QModelIndex &parent) const { - //TODO - return {}; + Q_UNUSED(parent); + return mSearchMessages.count(); } void SearchMessageModel::parseResult(const QJsonObject &obj) { //TODO + qDebug() << " void SearchMessageModel::parseResult(const QJsonObject &obj)"< 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. */ #ifndef SEARCHMESSAGEMODEL_H #define SEARCHMESSAGEMODEL_H #include #include #include "libruqola_private_export.h" +#include "searchmessage.h" class LIBRUQOLACORE_TESTS_EXPORT SearchMessageModel : public QAbstractListModel { Q_OBJECT public: explicit SearchMessageModel(QObject *parent = nullptr); ~SearchMessageModel() override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QHash roleNames() const override; int rowCount(const QModelIndex &parent) const override; void parseResult(const QJsonObject &obj); + void clear(); private: Q_DISABLE_COPY(SearchMessageModel) + QVector mSearchMessages; }; #endif // SEARCHMESSAGEMODEL_H diff --git a/src/qml/Desktop.qml b/src/qml/Desktop.qml index c1c69f78..cb905099 100644 --- a/src/qml/Desktop.qml +++ b/src/qml/Desktop.qml @@ -1,214 +1,217 @@ /* * Copyright 2016 Riccardo Iaconelli * Copyright (c) 2017-2018 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.Controls 1.4 import QtQuick.Window 2.2 import QtQuick.Dialogs 1.2 import QtQuick.Layouts 1.1 import QtQuick.Controls 2.2 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.1 as Kirigami import KDE.Ruqola.DebugCategory 1.0 import KDE.Ruqola.Channel 1.0 Kirigami.ApplicationWindow { id: appid readonly property int margin: 11 property string selectedRoomID: ""; property QtObject selectedRoom property QtObject model property QtObject userModel property QtObject filesModel property QtObject rocketChatAccount: Ruqola.rocketChatAccount() property QtObject inputCompleterModel: rocketChatAccount.inputCompleterModel() property QtObject searchMessageModel //TODO property string userInputMessageText: ""; width: Kirigami.Units.gridUnit * 55 height: Kirigami.Units.gridUnit * 40 title: i18n("Ruqola") pageStack.initialPage: [roomsComponent, mainComponent] pageStack.visible: rocketChatAccount.loginStatus === DDPClient.LoggedIn globalDrawer: Kirigami.GlobalDrawer { drawerOpen: false handleVisible: true resetMenuOnTriggered: true topContent: [ Text { 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("Log out") iconName: "system-log-out" onTriggered: { rocketChatAccount.logOut(); appid.globalDrawer.drawerOpen = false; } }, Kirigami.Action { text: i18n("Report a Bug") iconName: "tools-report-bug" onTriggered: { Qt.openUrlExternally("https://bugs.kde.org/report.cgi"); } }, Kirigami.Action { shortcut: StandardKey.Quit text: i18n("Quit") iconName: "application-exit" onTriggered: { Qt.quit(); } } ] } LoginPage { id: loginTab rcAccount: rocketChatAccount } AboutDialog { id: aboutDataDialog applicationData: Ruqola.applicationData() onOpenurl: { RuqolaUtils.openUrl(link); } } ChannelInfoDialog { id: channelInfoDialog channelName: (appid && appid.selectedRoomID) ? appid.selectedRoomID : "" onDeleteRoom: { rocketChatAccount.eraseRoom(roomId) } onModifyChannelSetting: { rocketChatAccount.changeChannelSettings(roomId, type, newVal) } } CreateNewChannelDialog { id: createNewChannelDialog onCreateNewChannel: { rocketChatAccount.createNewChannel(name, readOnly, privateRoom, usernames); } } HideChannelDialog { id: hideChannelDialog onHideChannel: { rocketChatAccount.hideRoom(roomId) } } AddUserDialog { id: addUserDialog completerModel: rocketChatAccount.userCompleterFilterModelProxy() onSearchUserName: { rocketChatAccount.userAutocomplete(pattern, ""); } onAddUser: { rocketChatAccount.addUserToRoom(name, rid) } } ShowSearchMessageDialog { id: searchMessageDialog + onSearchMessage: { + rocketChatAccount.messageSearch(pattern, rid) + } } SearchChannelDialog { id: searchChannelDialog searchChannelModel: rocketChatAccount.searchChannelFilterProxyModel() onSearchChannel: { rocketChatAccount.channelAndPrivateAutocomplete(pattern); } onOpenChannel: { if (channeltype === Channel.Room) { rocketChatAccount.openChannel(channelname) } else if (channeltype === Channel.PrivateChannel) { rocketChatAccount.openDirectChannel(channelname) } else { console.log(RuqolaDebugCategorySingleton.category, "Unknown open channel type : " + channeltype + " name : " + channelname) } } } TakeVideoMessageDialog { id: takeVideoMessage rcAccount: rocketChatAccount } BusyIndicator { id: busy anchors.centerIn: parent visible: rocketChatAccount.loginStatus === DDPClient.LoggingIn } RoomsComponent { id: roomsComponent } MainComponent { id: mainComponent } onClosing: { console.log(RuqolaDebugCategorySingleton.category, "Minimizing to systray..."); hide(); } function toggleShow() { if (visible) { hide(); } else { show(); raise(); requestActivate(); } } Component.onCompleted: { systrayIcon.activateRequested.connect(toggleShow); } } diff --git a/src/qml/MainComponent.qml b/src/qml/MainComponent.qml index 625bb32f..1fc5ffd7 100644 --- a/src/qml/MainComponent.qml +++ b/src/qml/MainComponent.qml @@ -1,339 +1,340 @@ /* * Copyright 2016 Riccardo Iaconelli * Copyright (C) 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 . * */ import QtQuick 2.9 import QtQuick.Controls 1.4 import QtQuick.Window 2.2 import QtQuick.Dialogs 1.2 import QtQuick.Layouts 1.1 import QtQuick.Controls 2.2 as QQC2 import KDE.Ruqola.RuqolaUtils 1.0 import KDE.Ruqola.Ruqola 1.0 import KDE.Ruqola.Clipboard 1.0 import KDE.Ruqola.RoomFilterProxyModel 1.0 import org.kde.kirigami 2.1 as Kirigami import KDE.Ruqola.DebugCategory 1.0 Component { id: mainComponent Kirigami.Page { id: mainWidget leftPadding: Kirigami.Units.smallSpacing rightPadding: Kirigami.Units.smallSpacing topPadding: Kirigami.Units.smallSpacing bottomPadding: Kirigami.Units.smallSpacing header: Column { RowLayout { anchors.left: parent.left anchors.right: parent.right anchors.leftMargin: 2*Kirigami.Units.smallSpacing visible: appid.selectedRoom ToolButton { iconName: "favorite" checkable: true Binding on checked { value: appid.selectedRoom && appid.selectedRoom.favorite } onCheckedChanged: { appid.rocketChatAccount.changeFavorite(appid.selectedRoomID, checked) } } Kirigami.Heading { text: "#" + (appid.selectedRoom ? appid.selectedRoom.name : "") level: 3 font.bold: true } Item { Layout.fillWidth: true } ToolButton { id: showUsersButton iconName: "system-users" checkable: true } ToolButton { id: searchMessage iconName: "edit-find" onClicked: { - searchMessageDialog.open(); + searchMessageDialog.roomId = appid.selectedRoomID + searchMessageDialog.initializeAndOpen(); } } ToolButton { iconName: "settings-configure" onClicked: menu.open(); QQC2.Menu { id: menu y: parent.height QQC2.MenuItem { text: i18n("Create New Channel") onTriggered: { createNewChannelDialog.initializeAndOpen() } } RuqolaMenuSeparator { } QQC2.MenuItem { text: i18n("Channel Info") onTriggered: { channelInfoDialog.initializeAndOpen() } } RuqolaMenuSeparator { } QQC2.MenuItem { text: i18n("Video Chat") onTriggered: { appid.rocketChatAccount.createJitsiConfCall(appid.selectedRoomID); } } RuqolaMenuSeparator { } QQC2.MenuItem { text: i18n("Add User In Room") onTriggered: { addUserDialog.roomId = appid.selectedRoomID addUserDialog.initializeAndOpen() } } RuqolaMenuSeparator { } QQC2.MenuItem { text: i18n("Take a Video Message") onTriggered: { takeVideoMessage.open(); } } RuqolaMenuSeparator {} QQC2.MenuItem { text: i18n("Load Recent History") onTriggered: { appid.rocketChatAccount.loadHistory(appid.selectedRoomID); } } RuqolaMenuSeparator { } QQC2.MenuItem { text: i18n("Show Files Attachment In Room") onTriggered: { appid.rocketChatAccount.roomFiles(appid.selectedRoomID); showFilesInRoomDialog.initializeAndOpen() } } } } } QQC2.Label { visible: appid.selectedRoom && (appid.selectedRoom.topic !== "") text: appid.selectedRoom ? appid.selectedRoom.topic : "" font.italic: true anchors.right: parent.right anchors.left: parent.left anchors.margins: 2*Kirigami.Units.smallSpacing wrapMode: QQC2.Label.Wrap } QQC2.Label { visible: appid.selectedRoom && (appid.selectedRoom.announcement !== "") text: appid.selectedRoom ? appid.selectedRoom.announcement : "" anchors.right: parent.right anchors.left: parent.left anchors.margins: 2*Kirigami.Units.smallSpacing wrapMode: QQC2.Label.Wrap } Rectangle { color: Kirigami.Theme.textColor height:1 anchors.right: parent.right anchors.left: parent.left opacity: .5 visible: appid.selectedRoom } Flow { id: topBarUserList readonly property bool isActive: showUsersButton.checked anchors { left: parent.left right: parent.right margins: Kirigami.Units.smallSpacing } opacity: topBarUserList.isActive ? 1 : 0 Behavior on opacity { NumberAnimation { duration: 650; easing.type: Easing.InOutQuad } } Repeater { model: parent.opacity > 0.5 ? appid.userModel : 0 RowLayout { Kirigami.Icon { source: model.iconstatus //FIXME height: 22 width: 22 } Text { text: model.displayname onLinkActivated: { openDirectChannelDialog.username = link; openDirectChannelDialog.open() } } } } Item { width: parent.width height: topBarUserList.isActive ? 1 : 0 Rectangle { height: parent.height width: height > 0 ? parent.width : 0 anchors.centerIn: parent Behavior on width { NumberAnimation { duration: 650; easing.type: Easing.InOutQuad } } color: Kirigami.Theme.textColor } } } } Clipboard { id: clipboard } QQC2.ScrollView { anchors.fill: parent ActiveChat { id: activeChat model: appid.model rcAccount: appid.rocketChatAccount roomId: appid.selectedRoomID onOpenDirectChannel: { openDirectChannelDialog.username = userName; openDirectChannelDialog.open() } onJitsiCallConfActivated: { appid.rocketChatAccount.joinJitsiConfCall(roomId) } onDeleteMessage: { deleteMessageDialog.msgId = messageId deleteMessageDialog.open() } onDownloadAttachment: { downloadFileDialog.fileToSaveUrl = url downloadFileDialog.open() } onEditMessage: { userInputMessage.messageId = messageId; userInputMessage.setOriginalMessage(messageStr) //console.log(RuqolaDebugCategorySingleton.category, "edit! messageId : " + messageId + " messageStr " + messageStr) } onCopyMessage: { clipboard.text = messageStr //console.log(RuqolaDebugCategorySingleton.category, "copy! messageId : " + messageId + " messageStr " + messageStr) } onReplyMessage: { console.log(RuqolaDebugCategorySingleton.category, "Not implemented reply message : " + messageId) } onSetFavoriteMessage: { appid.rocketChatAccount.starMessage(messageId, roomId, starred) } onDisplayImage: { displayImageDialog.iUrl = imageUrl displayImageDialog.title = title displayImageDialog.clearScaleAndOpen(); } OpenDirectChannelDialog { id: openDirectChannelDialog onOpenDirectChannel: { appid.rocketChatAccount.openDirectChannel(userName); } } DeleteMessageDialog { id: deleteMessageDialog onDeleteMessage: { appid.rocketChatAccount.deleteMessage(messageId) } } DownloadFileDialog { id: downloadFileDialog onAccepted: { if (fileUrl != "") { console.log(RuqolaDebugCategorySingleton.category, "You chose: " + fileUrl) appid.rocketChatAccount.downloadFile(fileToSaveUrl, fileUrl) } else { console.log(RuqolaDebugCategorySingleton.category, "No file selected"); } } } DisplayImageDialog { id: displayImageDialog } UploadFileDialog { id: uploadFileDialog onUploadFile: { appid.rocketChatAccount.uploadFile(description, filename) } } ShowFilesInRoomDialog { id: showFilesInRoomDialog filesModel: appid.filesModel onDownloadFile: { downloadFileDialog.fileToSaveUrl = file downloadFileDialog.open() } } } } footer: UserInput { id: userInputMessage rcAccount: appid.rocketChatAccount visible: appid.selectedRoom && (appid.selectedRoom.readOnly === false) anchors.bottom: mainWidget.bottom messageLineText: rcAccount.getUserCurrentMessage(appid.selectedRoomID) onTextEditing: { rcAccount.textEditing(appid.selectedRoomID, str) appid.userInputMessageText = str; } onClearUnreadMessages: { rcAccount.clearUnreadMessages(appid.selectedRoomID) } onUploadFile: { uploadFileDialog.initializeAndOpen() } } }// mainWidget Item } diff --git a/src/qml/ShowSearchMessageDialog.qml b/src/qml/ShowSearchMessageDialog.qml index eaefdfe3..8cc1f412 100644 --- a/src/qml/ShowSearchMessageDialog.qml +++ b/src/qml/ShowSearchMessageDialog.qml @@ -1,82 +1,85 @@ /* Copyright (c) 2018 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.3 import QtQuick.Controls 2.2 import QtQuick.Window 2.0 import QtQuick 2.9 import KDE.Ruqola.UsersForRoomFilterProxyModel 1.0 import org.kde.kirigami 2.1 as Kirigami Dialog { id: showSearchMessageDialog title: i18n("Search Message") - property QtObject searchMessageModel + signal searchMessage(string pattern, string rid) + property QtObject searchMessageModel + property string roomId x: parent.width / 2 - width / 2 y: parent.height / 2 - height / 2 modal: true standardButtons: Dialog.Close function initializeAndOpen() { searchField.text = ""; open(); } ColumnLayout { TextField { id: searchField focus: true Layout.minimumHeight: Layout.maximumHeight Layout.maximumHeight: Kirigami.Units.iconSizes.smallMedium + Kirigami.Units.smallSpacing * 2 Layout.fillWidth: true placeholderText: i18n("Search word...") - onTextChanged: { - //searchMessageModel.setFilterString(text); + //onAccepted: or onTextChanged: ???? + onAccepted: { + showSearchMessageDialog.searchMessage(text, roomId) } } ListView { id: listview width: 300; height: 200 model: searchMessageModel delegate: RowLayout { Kirigami.Icon { source: iconstatus //FIXME height: 22 width: 22 } Text { text: username == "" ? name : username } } } } } diff --git a/src/rocketchataccount.cpp b/src/rocketchataccount.cpp index 2be1ddee..9cb364c3 100644 --- a/src/rocketchataccount.cpp +++ b/src/rocketchataccount.cpp @@ -1,891 +1,893 @@ /* Copyright (c) 2017-2018 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 "model/messagemodel.h" #include "rocketchataccount.h" #include "model/roommodel.h" #include "roomwrapper.h" #include "typingnotification.h" #include "model/usersmodel.h" #include "ruqola_debug.h" #include "ruqola.h" #include "messagequeue.h" #include "rocketchatbackend.h" #include "model/roomfilterproxymodel.h" #include "ruqolalogger.h" #include "ruqolaserverconfig.h" #include "model/usercompletermodel.h" #include "model/usercompleterfilterproxymodel.h" #include "model/statusmodel.h" #include "utils.h" #include "rocketchatcache.h" #include "emojimanager.h" #include "otrmanager.h" #include "inputtextmanager.h" #include "model/usersforroommodel.h" #include "model/filesforroommodel.h" #include "model/searchchannelfilterproxymodel.h" #include "model/searchchannelmodel.h" #include "model/loginmethodmodel.h" #include "model/inputcompletermodel.h" #include "model/searchmessagemodel.h" #include "model/searchmessagefilterproxymodel.h" #include "authenticationmanager.h" #include "ddpapi/ddpclient.h" #include "restapi/restapirequest.h" #include #include #include #include #include #include RocketChatAccount::RocketChatAccount(const QString &accountFileName, QObject *parent) : QObject(parent) { //create an uniq file for each account if (!qEnvironmentVariableIsEmpty("RUQOLA_LOGFILE")) { mRuqolaLogger = new RuqolaLogger; } //Create it before loading settings mLoginMethodModel = new LoginMethodModel(this); mInputTextManager = new InputTextManager(this); mRuqolaServerConfig = new RuqolaServerConfig; initializeAuthenticationPlugins(); //TODO add account name. mSettings = new RocketChatAccountSettings(accountFileName, this); connect(mSettings, &RocketChatAccountSettings::loginStatusChanged, this, &RocketChatAccount::loginStatusChanged); connect(mSettings, &RocketChatAccountSettings::serverURLChanged, this, &RocketChatAccount::serverUrlChanged); connect(mSettings, &RocketChatAccountSettings::userIDChanged, this, &RocketChatAccount::userIDChanged); connect(mSettings, &RocketChatAccountSettings::userNameChanged, this, &RocketChatAccount::userNameChanged); mRocketChatBackend = new RocketChatBackend(this, this); loadSettings(); //After loadSettings mEmojiManager = new EmojiManager(this); mEmojiManager->setServerUrl(mSettings->serverUrl()); mOtrManager = new OtrManager(this); mRoomFilterProxyModel = new RoomFilterProxyModel(this); mUserCompleterModel = new UserCompleterModel(this); mUserCompleterFilterModelProxy = new UserCompleterFilterProxyModel(this); mUserCompleterFilterModelProxy->setSourceModel(mUserCompleterModel); mSearchChannelModel = new SearchChannelModel(this); mSearchChannelFilterProxyModel = new SearchChannelFilterProxyModel(this); mSearchChannelFilterProxyModel->setSourceModel(mSearchChannelModel); mSearchMessageModel = new SearchMessageModel(this); mSearchMessageFilterProxyModel = new SearchMessageFilterProxyModel(this); mSearchMessageFilterProxyModel->setSourceModel(mSearchMessageModel); mStatusModel = new StatusModel(this); mRoomModel = new RoomModel(this); connect(mRoomModel, &RoomModel::needToUpdateNotification, this, &RocketChatAccount::slotNeedToUpdateNotification); mRoomFilterProxyModel->setSourceModel(mRoomModel); mUserModel = new UsersModel(this); connect(mUserModel, &UsersModel::userStatusChanged, mRoomModel, &RoomModel::userStatusChanged); mMessageQueue = new MessageQueue(this); mTypingNotification = new TypingNotification(this); mCache = new RocketChatCache(this, this); connect(mCache, &RocketChatCache::fileDownloaded, this, &RocketChatAccount::fileDownloaded); connect(mTypingNotification, &TypingNotification::informTypingStatus, this, &RocketChatAccount::slotInformTypingStatus); QTimer::singleShot(0, this, &RocketChatAccount::clearModels); } RocketChatAccount::~RocketChatAccount() { delete mCache; mCache = nullptr; delete mRuqolaServerConfig; delete mRuqolaLogger; } void RocketChatAccount::slotNeedToUpdateNotification() { bool hasAlert = false; int nbUnread = 0; mRoomModel->getUnreadAlertFromAccount(hasAlert, nbUnread); Q_EMIT updateNotification(hasAlert, nbUnread, accountName()); } void RocketChatAccount::clearModels() { // Clear rooms data and refill it with data in the cache, if there is mRoomModel->reset(); mMessageQueue->loadCache(); //Try to send queue message mMessageQueue->processQueue(); } SearchChannelFilterProxyModel *RocketChatAccount::searchChannelFilterProxyModel() const { return mSearchChannelFilterProxyModel; } SearchChannelModel *RocketChatAccount::searchChannelModel() const { return mSearchChannelModel; } UserCompleterModel *RocketChatAccount::userCompleterModel() const { return mUserCompleterModel; } UserCompleterFilterProxyModel *RocketChatAccount::userCompleterFilterModelProxy() const { return mUserCompleterFilterModelProxy; } EmojiManager *RocketChatAccount::emojiManager() const { return mEmojiManager; } QString RocketChatAccount::userStatusIconFileName(const QString &name) { return mUserModel->userStatusIconFileName(name); } StatusModel *RocketChatAccount::statusModel() const { return mStatusModel; } RuqolaServerConfig *RocketChatAccount::ruqolaServerConfig() const { return mRuqolaServerConfig; } RuqolaLogger *RocketChatAccount::ruqolaLogger() const { return mRuqolaLogger; } RoomFilterProxyModel *RocketChatAccount::roomFilterProxyModel() const { return mRoomFilterProxyModel; } UsersForRoomFilterProxyModel *RocketChatAccount::usersForRoomFilterProxyModel(const QString &roomId) const { return mRoomModel->usersForRoomFilterProxyModel(roomId); } FilesForRoomFilterProxyModel *RocketChatAccount::filesForRoomFilterProxyModel(const QString &roomId) const { return mRoomModel->filesForRoomFilterProxyModel(roomId); } RocketChatBackend *RocketChatAccount::rocketChatBackend() const { return mRocketChatBackend; } void RocketChatAccount::loadSettings() { mSettings->loadSettings(); } MessageQueue *RocketChatAccount::messageQueue() const { return mMessageQueue; } RocketChatAccountSettings *RocketChatAccount::settings() const { return mSettings; } void RocketChatAccount::slotInformTypingStatus(const QString &room, bool typing) { ddp()->informTypingStatus(room, typing, mSettings->userName()); } RoomModel *RocketChatAccount::roomModel() const { return mRoomModel; } UsersModel *RocketChatAccount::usersModel() const { return mUserModel; } Room *RocketChatAccount::getRoom(const QString &roomId) { return mRoomModel->findRoom(roomId); } RoomWrapper *RocketChatAccount::getRoomWrapper(const QString &roomId) { return mRoomModel->findRoomWrapper(roomId); } MessageModel *RocketChatAccount::messageModelForRoom(const QString &roomID) { return mRoomModel->messageModel(roomID); } QString RocketChatAccount::getUserCurrentMessage(const QString &roomId) { return mRoomModel->inputMessage(roomId); } void RocketChatAccount::setUserCurrentMessage(const QString &message, const QString &roomId) { mRoomModel->setInputMessage(roomId, message); //Only for test qDebug() << " message " << message; mInputTextManager->setInputText(message); } void RocketChatAccount::textEditing(const QString &roomId, const QString &str) { mTypingNotification->setText(roomId, str); } void RocketChatAccount::sendMessage(const QString &roomID, const QString &message) { QJsonObject json; json[QStringLiteral("rid")] = roomID; json[QStringLiteral("msg")] = message; ddp()->method(QStringLiteral("sendMessage"), QJsonDocument(json), DDPClient::Persistent); } void RocketChatAccount::updateMessage(const QString &roomID, const QString &messageId, const QString &message) { QJsonObject json; json[QStringLiteral("rid")] = roomID; json[QStringLiteral("msg")] = message; json[QStringLiteral("_id")] = messageId; ddp()->method(QStringLiteral("updateMessage"), QJsonDocument(json), DDPClient::Persistent); } QString RocketChatAccount::avatarUrl(const QString &userId) { return mCache->avatarUrl(userId); } void RocketChatAccount::insertAvatarUrl(const QString &userId, const QString &url) { mCache->insertAvatarUrl(userId, url); } RestApiRequest *RocketChatAccount::restApi() { if (!mRestApi) { mRestApi = new RestApiRequest(this); mRestApi->setServerUrl(mSettings->serverUrl()); } return mRestApi; } void RocketChatAccount::leaveRoom(const QString &roomId) { ddp()->leaveRoom(roomId); } void RocketChatAccount::hideRoom(const QString &roomId) { ddp()->hideRoom(roomId); } DDPClient *RocketChatAccount::ddp() { if (!mDdp) { mDdp = new DDPClient(this, this); connect(mDdp, &DDPClient::loginStatusChanged, this, &RocketChatAccount::loginStatusChanged); connect(mDdp, &DDPClient::connectedChanged, this, &RocketChatAccount::connectedChanged); connect(mDdp, &DDPClient::changed, this, &RocketChatAccount::changed); connect(mDdp, &DDPClient::added, this, &RocketChatAccount::added); connect(mDdp, &DDPClient::removed, this, &RocketChatAccount::removed); mDdp->setServerUrl(mSettings->serverUrl()); mDdp->start(); } return mDdp; } DDPClient::LoginStatus RocketChatAccount::loginStatus() { if (mDdp) { return ddp()->loginStatus(); } else { return DDPClient::LoggedOut; } } void RocketChatAccount::tryLogin() { qCDebug(RUQOLA_LOG) << "Attempting login" << mSettings->userName() << "on" << mSettings->serverUrl(); delete mDdp; mDdp = nullptr; // This creates a new ddp() object. // DDP will automatically try to connect and login. ddp(); // In the meantime, load cache... mRoomModel->reset(); } void RocketChatAccount::logOut() { mSettings->logout(); mRoomModel->clear(); QJsonObject user; user[QStringLiteral("username")] = mSettings->userName(); QJsonObject json; json[QStringLiteral("user")] = user; ddp()->method(QStringLiteral("logout"), QJsonDocument(json)); delete mDdp; mDdp = nullptr; Q_EMIT logoutDone(accountName()); Q_EMIT loginStatusChanged(); qCDebug(RUQOLA_LOG) << "Successfully logged out!"; } void RocketChatAccount::clearUnreadMessages(const QString &roomId) { ddp()->clearUnreadMessages(roomId); } void RocketChatAccount::changeFavorite(const QString &roomId, bool checked) { ddp()->toggleFavorite(roomId, checked); } void RocketChatAccount::openChannel(const QString &url) { qCDebug(RUQOLA_LOG) << " void RocketChatAccount::openChannel(const QString &url)"<joinRoom(url, QString()); //TODO search correct room + select it. } void RocketChatAccount::joinJitsiConfCall(const QString &roomId) { qCDebug(RUQOLA_LOG) << " void RocketChatAccount::joinJitsiConfCall(const QString &roomId)"<uniqueId() + roomId).toUtf8(), QCryptographicHash::Md5).toHex()); #if defined(Q_OS_IOS) || defined(Q_OS_ANDROID) const QString scheme = "org.jitsi.meet://"; #else const QString scheme = QStringLiteral("https://"); #endif const QString url = scheme + mRuqolaServerConfig->jitsiMeetUrl() + QLatin1Char('/') + mRuqolaServerConfig->jitsiMeetPrefix() + hash; const QUrl clickedUrl = QUrl::fromUserInput(url); QDesktopServices::openUrl(clickedUrl); } void RocketChatAccount::eraseRoom(const QString &roomId) { ddp()->eraseRoom(roomId); } void RocketChatAccount::openDirectChannel(const QString &username) { ddp()->openDirectChannel(username); } void RocketChatAccount::createNewChannel(const QString &name, bool readOnly, bool privateRoom, const QString &userNames) { if (!name.trimmed().isEmpty()) { const QStringList lstUsers = userNames.split(QLatin1Char(','), QString::SkipEmptyParts); if (privateRoom) { ddp()->createPrivateGroup(name, lstUsers); } else { ddp()->createChannel(name, lstUsers, readOnly); } } else { qCDebug(RUQOLA_LOG) << "Channel name can't be empty"; } } void RocketChatAccount::joinRoom(const QString &roomId, const QString &joinCode) { ddp()->joinRoom(roomId, joinCode); ddp()->subscribeRoomMessage(roomId); } void RocketChatAccount::channelAndPrivateAutocomplete(const QString &pattern) { if (pattern.isEmpty()) { searchChannelModel()->clear(); } else { //Avoid to show own user const QString addUserNameToException = userName(); ddp()->channelAndPrivateAutocomplete(pattern, addUserNameToException); } } void RocketChatAccount::listEmojiCustom() { ddp()->listEmojiCustom(); } void RocketChatAccount::setDefaultStatus(User::PresenceStatus status) { ddp()->setDefaultStatus(status); } void RocketChatAccount::changeDefaultStatus(int index) { setDefaultStatus(mStatusModel->status(index)); } void RocketChatAccount::loadEmoji(const QJsonObject &obj) { mEmojiManager->loadEmoji(obj); } void RocketChatAccount::deleteMessage(const QString &messageId) { ddp()->deleteMessage(messageId); } void RocketChatAccount::insertFilesList(const QString &roomId) { FilesForRoomModel *filesForRoomModel = roomModel()->filesModelForRoom(roomId); if (filesForRoomModel) { filesForRoomModel->setFiles(rocketChatBackend()->files()); } else { qCWarning(RUQOLA_LOG) << " Impossible to find room " << roomId; } } void RocketChatAccount::insertCompleterUsers() { userCompleterModel()->insertUsers(rocketChatBackend()->users()); } void RocketChatAccount::userAutocomplete(const QString &searchText, const QString &exception) { //Clear before to create new search userCompleterModel()->clear(); rocketChatBackend()->clearUsersList(); if (!searchText.isEmpty()) { //Avoid to show own user QString addUserNameToException; if (exception.isEmpty()) { addUserNameToException = userName(); } else { addUserNameToException += QLatin1Char(',') + userName(); } ddp()->userAutocomplete(searchText, addUserNameToException); } } void RocketChatAccount::getUsersOfRoom(const QString &roomId) { ddp()->getUsersOfRoom(roomId, true); } void RocketChatAccount::parseUsersForRooms(const QString &roomId, const QJsonObject &root) { UsersForRoomModel *usersModelForRoom = roomModel()->usersModelForRoom(roomId); if (usersModelForRoom) { usersModelForRoom->parseUsersForRooms(root); } else { qCWarning(RUQOLA_LOG) << " Impossible to find room " << roomId; } } void RocketChatAccount::loadAutoCompleteChannel(const QJsonObject &obj) { mSearchChannelModel->parseChannels(obj); } UsersForRoomModel *RocketChatAccount::usersModelForRoom(const QString &roomId) const { return mRoomModel->usersModelForRoom(roomId); } void RocketChatAccount::roomFiles(const QString &roomId) { rocketChatBackend()->clearFilesList(); ddp()->roomFiles(roomId); } void RocketChatAccount::createJitsiConfCall(const QString &roomId) { ddp()->createJitsiConfCall(roomId); joinJitsiConfCall(roomId); } void RocketChatAccount::addUserToRoom(const QString &username, const QString &roomId) { ddp()->addUserToRoom(username, roomId); } -void RocketChatAccount::messageSearch(const QString &rid, const QString &pattern) +void RocketChatAccount::messageSearch(const QString &pattern, const QString &rid) { - ddp()->messageSearch(rid, pattern); + if (pattern.isEmpty()) { + mSearchMessageModel->clear(); + } else { + ddp()->messageSearch(rid, pattern); + } } void RocketChatAccount::starMessage(const QString &messageId, const QString &rid, bool starred) { ddp()->starMessage(messageId, rid, starred); } void RocketChatAccount::uploadFile(const QString &description, const QUrl &fileUrl) { qDebug() << " void RocketChatAccount::uploadFile(const QString &description, const QUrl &fileUrl)"<setRoomAnnouncement(roomId, newValue.toString()); break; case Description: ddp()->setRoomDescription(roomId, newValue.toString()); break; case Name: ddp()->setRoomName(roomId, newValue.toString()); break; case Topic: ddp()->setRoomTopic(roomId, newValue.toString()); break; case ReadOnly: ddp()->setRoomIsReadOnly(roomId, newValue.toBool()); break; case Archive: //No argument here. ddp()->archiveRoom(roomId); break; } } void RocketChatAccount::parsePublicSettings(const QJsonObject &obj) { QJsonArray configs = obj.value(QLatin1String("result")).toArray(); for (QJsonValueRef currentConfig : configs) { QJsonObject currentConfObject = currentConfig.toObject(); const QString id = currentConfObject[QStringLiteral("_id")].toString(); const QVariant value = currentConfObject[QStringLiteral("value")].toVariant(); if (id == QLatin1String("uniqueID")) { mRuqolaServerConfig->setUniqueId(value.toString()); } else if (id == QLatin1String("Jitsi_Domain")) { mRuqolaServerConfig->setJitsiMeetUrl(value.toString()); } else if (id == QLatin1String("Jitsi_URL_Room_Prefix")) { mRuqolaServerConfig->setJitsiMeetPrefix(value.toString()); } else if (id == QLatin1String("FileUpload_Storage_Type")) { mRuqolaServerConfig->setFileUploadStorageType(value.toString()); } else if (id == QLatin1String("Message_AllowEditing")) { mRuqolaServerConfig->setAllowMessageEditing(value.toBool()); } else if (id == QLatin1String("Message_AllowEditing_BlockEditInMinutes")) { mRuqolaServerConfig->setBlockEditingMessageInMinutes(value.toInt()); } else if (id == QLatin1String("OTR_Enable")) { mRuqolaServerConfig->setOtrEnabled(value.toBool()); } else if (id.contains(QRegularExpression(QStringLiteral("^Accounts_OAuth_\\w+")))) { if (value.toBool()) { mRuqolaServerConfig->addOauthService(id); } } else { qCDebug(RUQOLA_LOG) << "Other public settings id " << id << value; } } fillOauthModel(); } void RocketChatAccount::fillOauthModel() { QVector fillModel; for (int i = 0; i < mLstInfos.count(); ++i) { if (mRuqolaServerConfig->canShowOauthService(mLstInfos.at(i).oauthType())) { fillModel.append(mLstInfos.at(i)); } } - qDebug()<< "void RocketChatAccount::fillOauthModel()"<setAuthenticationInfos(fillModel); } void RocketChatAccount::changeDefaultAuthentication(int index) { setDefaultAuthentication(mLoginMethodModel->loginType(index)); } void RocketChatAccount::setDefaultAuthentication(AuthenticationManager::OauthType type) { - qDebug() <<" void RocketChatAccount::setDefaultAuthentication(AuthenticationManager::OauthType type)"< lstPlugins = AuthenticationManager::self()->pluginsList(); qCDebug(RUQOLA_LOG) <<" void RocketChatAccount::initializeAuthenticationPlugins()" << lstPlugins.count(); mLstPluginAuthenticationInterface.clear(); mLstInfos.clear(); for (PluginAuthentication *abstractPlugin : lstPlugins) { AuthenticationInfo info; info.setIconName(abstractPlugin->iconName()); info.setName(abstractPlugin->name()); info.setOauthType(abstractPlugin->type()); if (info.isValid()) { mLstInfos.append(info); } PluginAuthenticationInterface *interface = abstractPlugin->createInterface(this); interface->setAccount(this); mRuqolaServerConfig->addRuqolaAuthenticationSupport(abstractPlugin->type()); mLstPluginAuthenticationInterface.insert(abstractPlugin->type(), interface); //For the moment initialize default interface if (abstractPlugin->type() == AuthenticationManager::OauthType::Password) { mDefaultAuthenticationInterface = interface; } qCDebug(RUQOLA_LOG) << " plugin type " << abstractPlugin->type(); } //TODO fill ??? or store QVector } PluginAuthenticationInterface *RocketChatAccount::defaultAuthenticationInterface() const { return mDefaultAuthenticationInterface; } InputCompleterModel *RocketChatAccount::inputCompleterModel() const { return mInputTextManager->inputCompleterModel(); } LoginMethodModel *RocketChatAccount::loginMethodModel() const { return mLoginMethodModel; } QString RocketChatAccount::authToken() const { return settings()->authToken(); } QString RocketChatAccount::userName() const { return settings()->userName(); } void RocketChatAccount::setAccountName(const QString &servername) { settings()->setAccountName(servername); } QString RocketChatAccount::accountName() const { return settings()->accountName(); } QString RocketChatAccount::userID() const { return settings()->userId(); } QString RocketChatAccount::password() const { return settings()->password(); } void RocketChatAccount::setAuthToken(const QString &token) { settings()->setAuthToken(token); } void RocketChatAccount::setPassword(const QString &password) { settings()->setPassword(password); } void RocketChatAccount::setUserName(const QString &username) { settings()->setUserName(username); } void RocketChatAccount::setUserID(const QString &userID) { settings()->setUserId(userID); } QString RocketChatAccount::serverUrl() const { return settings()->serverUrl(); } void RocketChatAccount::setServerUrl(const QString &serverURL) { settings()->setServerUrl(serverURL); restApi()->setServerUrl(serverURL); mEmojiManager->setServerUrl(serverURL); } QString RocketChatAccount::recordingVideoPath() const { return mCache->recordingVideoPath(accountName()); } QString RocketChatAccount::recordingImagePath() const { return mCache->recordingImagePath(accountName()); } void RocketChatAccount::downloadFile(const QString &downloadFileUrl, const QUrl &localFile) { mCache->downloadFile(downloadFileUrl, localFile, false); } QUrl RocketChatAccount::attachmentUrl(const QString &url) { return mCache->attachmentUrl(url); } void RocketChatAccount::loadHistory(const QString &roomID, bool initial) { MessageModel *roomModel = messageModelForRoom(roomID); if (roomModel) { QJsonArray params; params.append(QJsonValue(roomID)); // Load history const qint64 endDateTime = roomModel->lastTimestamp(); if (initial) { params.append(QJsonValue(QJsonValue::Null)); } else { const qint64 startDateTime = roomModel->generateNewStartTimeStamp(endDateTime); QJsonObject dateObject; dateObject[QStringLiteral("$date")] = QJsonValue(startDateTime); //qDebug() << " QDATE TIME END" << QDateTime::fromMSecsSinceEpoch(endDateTime) << " START " << QDateTime::fromMSecsSinceEpoch(startDateTime); params.append(dateObject); } params.append(QJsonValue(50)); // Max number of messages to load; QJsonObject dateObject; //qDebug() << "roomModel->lastTimestamp()" << roomModel->lastTimestamp() << " ROOMID " << roomID; dateObject[QStringLiteral("$date")] = QJsonValue(endDateTime); params.append(dateObject); ddp()->loadHistory(params); } else { qCWarning(RUQOLA_LOG) << "Room is not found " << roomID; } } void RocketChatAccount::setServerVersion(const QString &version) { qCDebug(RUQOLA_LOG) << " void RocketChatAccount::setServerVersion(const QString &version)" << version; mRuqolaServerConfig->setServerVersion(version); } bool RocketChatAccount::needAdaptNewSubscriptionRC60() const { return mRuqolaServerConfig->needAdaptNewSubscriptionRC60(); } bool RocketChatAccount::otrEnabled() const { return mRuqolaServerConfig->otrEnabled(); } bool RocketChatAccount::allowEditingMessages() const { return mRuqolaServerConfig->allowMessageEditing(); } void RocketChatAccount::parseOtr(const QJsonArray &contents) { const Otr t = mOtrManager->parseOtr(contents); qDebug() << " void RocketChatAccount::parseOtr(const QJsonArray &contents)"<avatarUrlFromCacheOnly(sender); //qDebug() << " iconFileName"<inputChannelAutocomplete(pattern, exceptions); } void RocketChatAccount::inputUserAutocomplete(const QString &pattern, const QString &exceptions) { ddp()->inputUserAutocomplete(pattern, exceptions); } void RocketChatAccount::inputTextCompleter(const QJsonObject &obj) { mInputTextManager->inputTextCompleter(obj); } void RocketChatAccount::displaySearchedMessage(const QJsonObject &obj) { mSearchMessageModel->parseResult(obj); } diff --git a/src/rocketchataccount.h b/src/rocketchataccount.h index 411c8fd2..b39265ca 100644 --- a/src/rocketchataccount.h +++ b/src/rocketchataccount.h @@ -1,271 +1,271 @@ /* Copyright (c) 2017-2018 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. */ #ifndef ROCKETCHATACCOUNT_H #define ROCKETCHATACCOUNT_H #include #include #include #include "rocketchataccountsettings.h" #include "libruqola_private_export.h" #include "authenticationinfo.h" class TypingNotification; class UsersModel; class RoomModel; class RoomWrapper; class MessageModel; class DDPClient; class RestApiRequest; class MessageQueue; class RocketChatBackend; class RoomFilterProxyModel; class RuqolaLogger; class RuqolaServerConfig; class UserCompleterModel; class UserCompleterFilterProxyModel; class StatusModel; class RocketChatCache; class EmojiManager; class OtrManager; class UsersForRoomFilterProxyModel; class UsersForRoomModel; class FilesForRoomModel; class FilesForRoomFilterProxyModel; class SearchChannelModel; class SearchChannelFilterProxyModel; class LoginMethodModel; class InputCompleterModel; class InputTextManager; class PluginAuthenticationInterface; class Room; class SearchMessageModel; class SearchMessageFilterProxyModel; class LIBRUQOLACORE_TESTS_EXPORT RocketChatAccount : public QObject { Q_OBJECT Q_PROPERTY(QString userName READ userName WRITE setUserName NOTIFY userNameChanged) Q_PROPERTY(QString userID READ userID WRITE setUserID NOTIFY userIDChanged) Q_PROPERTY(QString serverUrl READ serverUrl WRITE setServerUrl NOTIFY serverUrlChanged) Q_PROPERTY(QString accountName READ accountName WRITE setAccountName NOTIFY accountNameChanged) Q_PROPERTY(QString password WRITE setPassword) Q_PROPERTY(DDPClient::LoginStatus loginStatus READ loginStatus NOTIFY loginStatusChanged) public: explicit RocketChatAccount(const QString &accountName = QString(), QObject *parent = nullptr); ~RocketChatAccount(); enum RoomInfoType { Announcement, Description, Name, Topic, ReadOnly, Archive }; Q_ENUM(RoomInfoType) Q_INVOKABLE UsersModel *usersModel() const; Q_INVOKABLE RoomModel *roomModel() const; Q_INVOKABLE RoomFilterProxyModel *roomFilterProxyModel() const; Q_INVOKABLE UsersForRoomFilterProxyModel *usersForRoomFilterProxyModel(const QString &roomId) const; Q_INVOKABLE UsersForRoomModel *usersModelForRoom(const QString &roomId) const; Q_INVOKABLE RoomWrapper *getRoomWrapper(const QString &roomId); Q_INVOKABLE MessageModel *messageModelForRoom(const QString &roomID); Q_INVOKABLE QString getUserCurrentMessage(const QString &roomId); Q_INVOKABLE void setUserCurrentMessage(const QString &message, const QString &roomId); Q_INVOKABLE void textEditing(const QString &roomId, const QString &str); Q_INVOKABLE void leaveRoom(const QString &roomId); Q_INVOKABLE void hideRoom(const QString &roomId); Q_INVOKABLE void tryLogin(); Q_INVOKABLE void logOut(); Q_INVOKABLE void clearUnreadMessages(const QString &roomId); Q_INVOKABLE void changeFavorite(const QString &roomId, bool checked); Q_INVOKABLE void sendMessage(const QString &roomID, const QString &message); Q_INVOKABLE void updateMessage(const QString &roomID, const QString &messageId, const QString &message); Q_INVOKABLE void openChannel(const QString &url); Q_INVOKABLE void joinJitsiConfCall(const QString &roomId); Q_INVOKABLE void createNewChannel(const QString &name, bool readOnly, bool privateRoom, const QString &userNames); Q_INVOKABLE void joinRoom(const QString &roomId, const QString &joinCode = QString()); Q_INVOKABLE void openDirectChannel(const QString &username); Q_INVOKABLE void listEmojiCustom(); Q_INVOKABLE void setDefaultStatus(User::PresenceStatus status); Q_INVOKABLE void changeDefaultStatus(int index); Q_INVOKABLE void createJitsiConfCall(const QString &roomId); Q_INVOKABLE void deleteMessage(const QString &messageId); Q_INVOKABLE void userAutocomplete(const QString &searchText, const QString &exception); Q_INVOKABLE void eraseRoom(const QString &roomId); Q_INVOKABLE void changeChannelSettings(const QString &roomId, RocketChatAccount::RoomInfoType infoType, const QVariant &newValue); Q_INVOKABLE QString recordingVideoPath() const; Q_INVOKABLE QString recordingImagePath() const; Q_INVOKABLE void downloadFile(const QString &downloadFileUrl, const QUrl &localFile); Q_INVOKABLE void starMessage(const QString &messageId, const QString &rid, bool starred); Q_INVOKABLE void uploadFile(const QString &description, const QUrl &fileUrl); Q_INVOKABLE QString serverUrl() const; Q_INVOKABLE QString avatarUrl(const QString &userId); Q_INVOKABLE StatusModel *statusModel() const; Q_INVOKABLE QUrl attachmentUrl(const QString &url); Q_INVOKABLE void loadHistory(const QString &roomID, bool initial = false); Q_INVOKABLE bool allowEditingMessages() const; Q_INVOKABLE bool otrEnabled() const; Q_INVOKABLE void channelAndPrivateAutocomplete(const QString &pattern); Q_INVOKABLE UserCompleterFilterProxyModel *userCompleterFilterModelProxy() const; Q_INVOKABLE void roomFiles(const QString &roomId); Q_INVOKABLE FilesForRoomFilterProxyModel *filesForRoomFilterProxyModel(const QString &roomId) const; Q_INVOKABLE void addUserToRoom(const QString &username, const QString &roomId); Q_INVOKABLE SearchChannelFilterProxyModel *searchChannelFilterProxyModel() const; Q_INVOKABLE InputCompleterModel *inputCompleterModel() const; Q_INVOKABLE LoginMethodModel *loginMethodModel() const; Q_INVOKABLE Room *getRoom(const QString &roomId); Q_INVOKABLE void changeDefaultAuthentication(int index); - Q_INVOKABLE void messageSearch(const QString &rid, const QString &pattern); + Q_INVOKABLE void messageSearch(const QString &pattern, const QString &rid); SearchChannelModel *searchChannelModel() const; UserCompleterModel *userCompleterModel() const; RocketChatAccountSettings *settings() const; DDPClient *ddp(); DDPClient::LoginStatus loginStatus(); RestApiRequest *restApi(); //Make it private in future void slotInformTypingStatus(const QString &room, bool typing); MessageQueue *messageQueue() const; RocketChatBackend *rocketChatBackend() const; RuqolaLogger *ruqolaLogger() const; void loadEmoji(const QJsonObject &obj); void parsePublicSettings(const QJsonObject &obj); RuqolaServerConfig *ruqolaServerConfig() const; void setUserName(const QString &username); QString userName() const; void setAccountName(const QString &servername); QString accountName() const; void setUserID(const QString &userID); QString userID() const; void setPassword(const QString &password); QString password() const; void setAuthToken(const QString &token); QString authToken() const; void setServerUrl(const QString &serverUrl); void sendNotification(const QJsonArray &contents); void parseOtr(const QJsonArray &contents); void setServerVersion(const QString &version); bool needAdaptNewSubscriptionRC60() const; EmojiManager *emojiManager() const; QString userStatusIconFileName(const QString &id); void getUsersOfRoom(const QString &roomId); void parseUsersForRooms(const QString &roomId, const QJsonObject &root); void loadAutoCompleteChannel(const QJsonObject &obj); void insertCompleterUsers(); void insertFilesList(const QString &roomId); void inputChannelAutocomplete(const QString &pattern, const QString &exceptions); void inputUserAutocomplete(const QString &pattern, const QString &exceptions); void inputTextCompleter(const QJsonObject &obj); PluginAuthenticationInterface *defaultAuthenticationInterface() const; SearchMessageModel *searchMessageModel() const; SearchMessageFilterProxyModel *searchMessageFilterProxyModel() const; void displaySearchedMessage(const QJsonObject &obj); Q_SIGNALS: void connectedChanged(); void accountNameChanged(); void userNameChanged(); void userIDChanged(); void serverUrlChanged(); void loginStatusChanged(); void logoutDone(const QString &accountname); void added(const QJsonObject &item); void changed(const QJsonObject &item); void removed(const QJsonObject &item); void notification(const QString &title, const QString &message, const QPixmap &pixmap); void fileDownloaded(const QString &filePath, const QUrl &cacheImageUrl); void updateNotification(bool hasAlert, int nbUnread, const QString &accountName); private: Q_DISABLE_COPY(RocketChatAccount) void slotNeedToUpdateNotification(); void insertAvatarUrl(const QString &userId, const QString &url); void loadSettings(); void clearModels(); void fillOauthModel(); void initializeAuthenticationPlugins(); void setDefaultAuthentication(AuthenticationManager::OauthType type); PluginAuthenticationInterface *mDefaultAuthenticationInterface = nullptr; QHash mLstPluginAuthenticationInterface; QVector mLstInfos; RocketChatAccountSettings *mSettings = nullptr; EmojiManager *mEmojiManager = nullptr; TypingNotification *mTypingNotification = nullptr; UsersModel *mUserModel = nullptr; RoomModel *mRoomModel = nullptr; RoomFilterProxyModel *mRoomFilterProxyModel = nullptr; DDPClient *mDdp = nullptr; RestApiRequest *mRestApi = nullptr; MessageQueue *mMessageQueue = nullptr; RocketChatBackend *mRocketChatBackend = nullptr; RuqolaLogger *mRuqolaLogger = nullptr; RuqolaServerConfig *mRuqolaServerConfig = nullptr; UserCompleterModel *mUserCompleterModel = nullptr; UserCompleterFilterProxyModel *mUserCompleterFilterModelProxy = nullptr; StatusModel *mStatusModel = nullptr; RocketChatCache *mCache = nullptr; OtrManager *mOtrManager = nullptr; SearchChannelModel *mSearchChannelModel = nullptr; SearchChannelFilterProxyModel *mSearchChannelFilterProxyModel = nullptr; LoginMethodModel *mLoginMethodModel = nullptr; InputTextManager *mInputTextManager = nullptr; SearchMessageModel *mSearchMessageModel = nullptr; SearchMessageFilterProxyModel *mSearchMessageFilterProxyModel = nullptr; }; #endif // ROCKETCHATACCOUNT_H diff --git a/src/searchmessage.cpp b/src/searchmessage.cpp new file mode 100644 index 00000000..834f794e --- /dev/null +++ b/src/searchmessage.cpp @@ -0,0 +1,42 @@ +/* + Copyright (C) 2018 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() +{ + +} + +SearchMessage::~SearchMessage() +{ + +} + +void SearchMessage::parseResult() +{ + //TODO +} + +QDebug operator <<(QDebug d, const SearchMessage &t) +{ + //TODO + return d; +} diff --git a/src/searchmessage.h b/src/searchmessage.h new file mode 100644 index 00000000..5fa5584f --- /dev/null +++ b/src/searchmessage.h @@ -0,0 +1,41 @@ +/* + Copyright (C) 2018 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" + +class LIBRUQOLACORE_TESTS_EXPORT SearchMessage +{ + Q_GADGET +public: + SearchMessage(); + ~SearchMessage(); + + void parseResult(); +}; +Q_DECLARE_METATYPE(SearchMessage) +Q_DECLARE_TYPEINFO(SearchMessage, Q_MOVABLE_TYPE); +LIBRUQOLACORE_EXPORT QDebug operator <<(QDebug d, const SearchMessage &t); + +#endif // SEARCHMESSAGE_H