diff --git a/Desktop.qml b/Desktop.qml index 9326d169..eb37d590 100644 --- a/Desktop.qml +++ b/Desktop.qml @@ -1,317 +1,317 @@ // Skeleton from https://github.com/achipa/outqross_blog.git // Almost everything has been re-adapted import QtQuick 2.7 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.2 import QtQuick.Window 2.2 import QtQuick.Dialogs 1.2 import QtQuick.Layouts 1.1 import Qt.labs.settings 1.0 import QtGraphicalEffects 1.0 import KDE.Ruqola.UserData 1.0 import KDE.Ruqola.DDPClient 1.0 import KDE.Ruqola.Notification 1.0 // import "Log.js" as Log // import "Data.js" as Data ApplicationWindow { property int margin: 11 property string statusText property string lightGreen: "#6ab141"; property string darkGreen: "#00613a"; property string selectedRoomID: ""; id: appid title: qsTr("Ruqola") width: 800 height: 600 visible: true Shortcut { sequence: StandardKey.Quit context: Qt.ApplicationShortcut onActivated: Qt.quit() } Login { id: loginTab visible: (UserData.loginStatus == DDPClient.LoginFailed || UserData.loginStatus == DDPClient.LoggedOut) anchors.fill:parent z: 10 serverURL: UserData.serverURL username: UserData.userName onAccepted: { UserData.password = loginTab.password; UserData.userName = loginTab.username; UserData.serverURL = loginTab.serverURL; UserData.tryLogin(); } } BusyIndicator { id: busy anchors.centerIn: parent visible: UserData.loginStatus == DDPClient.LoggingIn } Item { id: mainWidget anchors.fill: parent visible: !loginTab.visible Rectangle { id: userBox anchors.top: parent.top width: parent.width anchors.left: parent.left anchors.right: roomsList.right height: 40 color: darkGreen Text { verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignRight anchors.rightMargin: 10 anchors.fill: parent font.pointSize: 12 color: "white" text: "Hello, " + UserData.userName } } RoomsView { anchors.top: userBox.bottom anchors.left: parent.left anchors.bottom: parent.bottom anchors.margins: 0 width: 200 height: appid.height id: roomsList model: UserData.roomModel() visible: parent.visible selectedRoomID: appid.selectedRoomID; onRoomSelected: { if (roomID == selectedRoomID) { return; } console.log("Choosing room", roomID); appid.selectedRoomID = roomID; activeChat.model = UserData.getModelForRoom(roomID) topicWidget.selectedRoom = UserData.getRoom(roomID) } onCountChanged: { // console.log("We have", roomsList.count, "rooms") } LinearGradient { id: greenGradient anchors.fill: parent start: Qt.point(0, 0) end: Qt.point(roomsList.width, 0) gradient: Gradient { GradientStop { position: 0.0; color: "#6ab141" } GradientStop { position: 1.0; color: "#00613a" } } z: -1; } } Item { anchors.right: parent.right anchors.left: roomsList.right anchors.top: parent.top anchors.bottom: messageLine.top // Item { // anchors.fill: parent // id: greeter // visible: false // // visible: selectedRoomID.empty // Text { // text: "Welcome to Ruqola!"; // } // } Rectangle { id: topicWidget color: "#fff" anchors.top: parent.top anchors.right: parent.right anchors.left: parent.left height: nameLabel.height + topicLabel.height property var selectedRoom; Text { id: nameLabel text: "#" + parent.selectedRoom.name font.pointSize: 18 verticalAlignment: Text.AlignVCenter anchors.leftMargin: 20 height: 40 // height: font.pixelSize + 10 anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right } Text { id: topicLabel text: topicWidget.selectedRoom.topic anchors.top: nameLabel.bottom anchors.bottom: parent.bottom anchors.left: parent.left anchors.right: parent.right horizontalAlignment: Text.AlignHCenter height: font.pixelSize + 10 } } ScrollView { anchors.right: parent.right anchors.left: parent.left anchors.top: topicWidget.bottom anchors.bottom: parent.bottom verticalScrollBarPolicy: Qt.ScrollBarAlwaysOn // visible: parent.visible && (UserData.loginStatus != DDPClient.LoggingIn) // visible: !greeter.visible ListView { id: activeChat // model: UserData.getModelForRoom(selectedRoomID) onCountChanged: { // console.log("changed") // var newIndex = count - 1 // last index // positionViewAtEnd() positionViewAtIndex(count - 1, ListView.Beginning) // currentIndex = newIndex } // Component.onCompleted: positionViewAtEnd() Component.onCompleted: positionViewAtIndex(count - 1, ListView.Beginning) // onSelectedRoomIDChanged: { console.log("CHANGED"); activeChat.positionViewAtEnd(); } // model: myModel anchors.fill:parent visible : count > 0 z: -1 // ScrollBar.vertical: ScrollBar { } delegate: Message { i_messageText: messageText i_username: username i_systemMessage: systemMessage i_systemMessageType: type width: parent.width } } } } TextField { id: messageLine anchors.right: parent.right anchors.left: roomsList.right anchors.bottom: parent.bottom placeholderText: if (UserData.loginStatus != DDPClient.LoggedIn || (selectedRoomID=="")){ qsTr("Please Select a room") } else{ qsTr("Enter message") } height: 2.7*font.pixelSize onAccepted: { if (text != "" && UserData.loginStatus == DDPClient.LoggedIn && !(selectedRoomID=="")) { UserData.sendMessage(selectedRoomID, text); text = ""; } } } } Rectangle { z: -10 anchors.fill: parent color: "white" } onClosing: { console.log("Minimizing to systray..."); Notification.windowClosed = true; hide(); } function toggleShow(reason) { console.log ("Showing"); if (visible) { Notification.windowClosed = true; hide(); } else { systrayIcon.iconActivated(); show(); raise(); requestActivate(); Notification.windowClosed = false; } } Component.onCompleted: { - systrayIcon.iconActivated.connect(toggleShow); +// systrayIcon.iconActivated.connect(toggleShow); // roomsList.model = UserData.roomModel(); // systrayIcon.showMessage("Connected", "We are CONNECTED!"); // timer.start(); // timer.fire(); } /* Timer { id: timer interval: 1000 onTriggered: { // console.log("FIRE"); switch (UserData.loginStatus) { case UserData.NotConnected: statusText = qsTr("Not connected."); break; case UserData.LoggedIn: statusText = qsTr("Connected to " + UserData.serverURL); break; } } repeat: true }*/ // onStatusTextChanged: timer.restart(); } diff --git a/src/notification.cpp b/src/notification.cpp index 1fb66453..67793552 100644 --- a/src/notification.cpp +++ b/src/notification.cpp @@ -1,101 +1,106 @@ /* * * 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 "userdata.h" #include "ddpclient.h" #include "notification.h" #include #include #include #include bool Notification::windowClosed() const { return m_windowClosed; } void Notification::setWindowClosed(bool val){ m_windowClosed = val; } //Opens the room having new message //void Notification::notificationClicked(){ /* * 1. Maximize systray * 2. switch to unread room * */ //} void Notification::createActions(){ + qDebug() << "i m in create action"; m_quitAction = new QAction(tr("&Quit"), this); connect(m_quitAction, &QAction::triggered, qApp, &QCoreApplication::quit); // QWindow window; // m_restore = new QAction(tr("&Restore"),this); // connect(m_restore, &QAction::triggered, window, &QWindow::showMaximized ); } void Notification::createTrayIcon(){ + + qDebug() << "i m in create tray"; if (!QSystemTrayIcon::isSystemTrayAvailable()) { QMessageBox::critical(0, QObject::tr("Systray"), QObject::tr("Cannot detect SystemTray on this system.")); return; } m_trayIconMenu = new QMenu(); m_trayIconMenu->addAction(m_quitAction); m_trayIconMenu->addSeparator(); -// m_trayIconMenu->addAction(m_restore); - - m_systrayIcon->setContextMenu(m_trayIconMenu); - m_systrayIcon->setToolTip("Ruqola"); - m_systrayIcon->setIcon(QIcon(":/systray.png")); - m_systrayIcon->setVisible(true); -} + this->setContextMenu(m_trayIconMenu); + this->setToolTip("Ruqola"); + this->setIcon(QIcon(":/systray.png")); + this->setVisible(true); -void Notification::toggle(){ - m_restore->setEnabled(windowClosed()); - m_systrayIcon->setVisible(windowClosed()); } - Notification::Notification(): m_windowClosed(false) { - m_systrayIcon = new QSystemTrayIcon(); + + qDebug() << "i m in constructor"; +// m_systrayIcon = new QSystemTrayIcon(); createActions(); createTrayIcon(); - connect(m_systrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), + connect(this, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason))); } void Notification::iconActivated(QSystemTrayIcon::ActivationReason reason){ qDebug() << "Icon activated"; if (reason == QSystemTrayIcon::Trigger) { - this->show(); //isn't working + + if (m_windowClosed){ + m_windowClosed = false; +// m_restore->setDisabled(m_windowClosed); /* - * this->raise(); - this->activateWindow(); - this->showNormal(); + * raise(); + activateWindow(); + showNormal(); */ - m_windowClosed = false; - toggle(); + } else { + m_windowClosed = true; + hide(); +// m_restore->setEnabled(m_windowClosed); + + } } } diff --git a/src/notification.h b/src/notification.h index e498329f..be78fcdc 100644 --- a/src/notification.h +++ b/src/notification.h @@ -1,62 +1,62 @@ /* * * Copyright 2016 Riccardo Iaconelli * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #ifndef NOTIFICATION_H #define NOTIFICATION_H #include #include #include class Notification: public QSystemTrayIcon{ Q_OBJECT Q_PROPERTY (bool windowClosed READ windowClosed WRITE setWindowClosed NOTIFY windowClosedChanged) public: void setWindowClosed(bool val); bool windowClosed() const; void toggle(); Notification(); signals: void windowClosedChanged(); public slots: void iconActivated(QSystemTrayIcon::ActivationReason reason); private: void createActions(); void createTrayIcon(); QAction *m_quitAction; QAction *m_restore; QMenu *m_trayIconMenu; - QSystemTrayIcon *m_systrayIcon; //have to discuss it through +// QSystemTrayIcon *m_systrayIcon; //have to discuss it through bool m_windowClosed; }; #endif // NOTIFICATION_H diff --git a/src/userdata.cpp b/src/userdata.cpp index f1111c06..5851b123 100644 --- a/src/userdata.cpp +++ b/src/userdata.cpp @@ -1,254 +1,260 @@ /* * * 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 "userdata.h" #include "roommodel.h" #include "ddpclient.h" #include "notification.h" UserData *UserData::m_self = 0; QString UserData::authToken() const { return m_authToken; } QString UserData::userName() const { return m_userName; } QString UserData::userID() const { return m_userID; } QString UserData::password() const { return m_password; } void UserData::setAuthToken(const QString& token) { qDebug() << "Setting token to" << token; QSettings s; m_authToken = token; s.setValue("authToken", token); } void UserData::setPassword(const QString& password) { m_password = password; } void UserData::setUserName(const QString& username) { m_userName = username; QSettings s; s.setValue("username", username); emit userNameChanged(); } void UserData::setUserID(const QString& userID) { m_userName = userID; QSettings s; s.setValue("userID", userID); emit userIDChanged(); } RoomModel * UserData::roomModel() { if (!m_roomModel) { qDebug() << "creating new RoomModel"; m_roomModel = new RoomModel(this); qDebug() << m_roomModel; // m_roomModel->reset(); } return m_roomModel; } DDPClient * UserData::ddp() { if (!m_ddp) { m_ddp = new DDPClient(serverURL()); connect(m_ddp, &DDPClient::loginStatusChanged, this, &UserData::loginStatusChanged); // connect(m_ddp, &DDPClient::loginStatusChanged, this, [=](){qDebug() << "Signal received";}); } return m_ddp; } Notification * UserData::notification() { + qDebug() <<"self notification()"; if (!m_notification) { - qDebug() << "creating new Notification object"; + qDebug() << "if: creating new Notification object"; m_notification = new Notification(); m_notification->show(); - qDebug() << m_notification; +// qDebug() << m_notification; + } else { + m_notification->show(); } return m_notification; } void UserData::showNotification(const QString userName, QString message ) { + qDebug() << "showNotification() self"; if ( UserData::m_notification->windowClosed() && ( UserData::self()->loginStatus() == DDPClient::LoggedIn) ){ QString title("New Message"); //This can be enhanced later QString msg = QString("%1 \n %2").arg(userName).arg(message); if ( msg.length() >= 20 ){ msg.replace(20, msg.length()-20, "..."); } m_notification->showMessage(title, msg, QSystemTrayIcon::Information, 5000 ); } } void UserData::sendMessage(const QString &roomID, const QString &message) { QString json = "{\"rid\": \"%1\", \"msg\": \"%2\"}"; json = json.arg(roomID, message); ddp()->method("sendMessage", QJsonDocument::fromJson(json.toUtf8())); } MessageModel * UserData::getModelForRoom(const QString& roomID) { if (m_messageModels.contains(roomID)) { // qDebug() << "Returning old model for " << roomID; return m_messageModels.value(roomID); } else { // qDebug() << "Creating a new model"; m_messageModels[roomID] = new MessageModel(roomID, this); return m_messageModels[roomID]; } } QString UserData::serverURL() const { return m_serverURL; } void UserData::setServerURL(const QString& serverURL) { if (m_serverURL == serverURL) { return; } QSettings s; s.setValue("serverURL", serverURL); m_serverURL = serverURL; // m_roomModel->reset(); emit serverURLChanged(); } DDPClient::LoginStatus UserData::loginStatus() { if (m_ddp) { return ddp()->loginStatus(); } else { return DDPClient::LoggedOut; } } void UserData::tryLogin() { qDebug() << "Attempting login" << userName() << "on" << serverURL(); // Reset model views foreach (const QString key, m_messageModels.keys()) { MessageModel *m = m_messageModels.take(key); delete m; } delete m_ddp; m_ddp = 0; // In the meantime, load cache... m_roomModel->reset(); // This creates a new ddp() object. // DDP will automatically try to connect and login. ddp(); } void UserData::logOut() { setAuthToken(QString()); setPassword(QString()); // m_ddp->logOut(); foreach (const QString key, m_messageModels.keys()) { MessageModel *m = m_messageModels.take(key); delete m; } delete m_ddp; m_ddp = 0; emit loginStatusChanged(); m_roomModel->clear(); } QString UserData::cacheBasePath() const { if (m_serverURL.isEmpty()) { return QString(); } return QStandardPaths::writableLocation(QStandardPaths::CacheLocation)+'/'+m_serverURL; } // QString UserData::activeRoom() const // { // return m_activeRoom; // } // void UserData::setActiveRoom(const QString& activeRoom) // { // m_activeRoom = activeRoom; // // roomModel()->setActiveRoom(activeRoom); // emit activeRoomChanged(); // } RoomWrapper * UserData::getRoom(const QString& roomID) { return roomModel()->findRoom(roomID); } UserData::UserData(QObject* parent): QObject(parent), m_ddp(0), m_roomModel(0) { QSettings s; m_serverURL = s.value("serverURL", "demo.rocket.chat").toString(); m_userName = s.value("username").toString(); m_userID = s.value("userID").toString(); m_authToken = s.value("authToken").toString(); // roomModel()->reset(); } UserData * UserData::self() { +// qDebug()<<"in self"; if (!m_self) { + qDebug() << "i m in if of self"; m_self = new UserData; m_self->ddp(); // Create DDP object so we try to connect at startup m_self->notification(); m_self->roomModel()->reset(); // m_self->getModelForRoom("GENERAL"); } return m_self; }