diff --git a/src/messagemodel.cpp b/src/messagemodel.cpp index b388cab0..61a1c06a 100644 --- a/src/messagemodel.cpp +++ b/src/messagemodel.cpp @@ -1,265 +1,267 @@ /* * * 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 #include #include #include "messagemodel.h" #include "ruqola.h" #include "ruqola_debug.h" //Message::MessageStatus Message::messageStatus() const //{ // return m_messageStatus; //} //void Message::setMessageStatus(MessageStatus m) //{ // if (m_messageStatus!= m){ // m_messageStatus = m; // emit messageStatusChanged(); // } //} Message MessageModel::fromJSon(const QJsonObject& o) { Message message; message.messageID = o[QStringLiteral("messageID")].toString(); message.roomID = o[QStringLiteral("roomID")].toString(); message.message = o[QStringLiteral("message")].toString(); message.timestamp = (qint64) o[QStringLiteral("timestamp")].toDouble(); message.username = o[QStringLiteral("username")].toString(); message.userID = o[QStringLiteral("userID")].toString(); message.updatedAt = (qint64) o[QStringLiteral("updatedAt")].toDouble(); message.editedAt = (qint64) o[QStringLiteral("editedAt")].toDouble(); message.editedByUsername = o[QStringLiteral("editedByUsername")].toString(); message.editedByUserID = o[QStringLiteral("editedByUserID")].toString(); message.url = o[QStringLiteral("url")].toString(); message.meta = o[QStringLiteral("meta")].toString(); message.headers = o[QStringLiteral("headers")].toString(); message.parsedUrl = o[QStringLiteral("parsedUrl")].toString(); message.imageUrl = o[QStringLiteral("imageUrl")].toString(); message.color = o[QStringLiteral("color")].toString(); message.alias = o[QStringLiteral("alias")].toString(); message.avatar = o[QStringLiteral("avatar")].toString(); message.groupable = o[QStringLiteral("groupable")].toBool(); message.parseUrls = o[QStringLiteral("parseUrls")].toBool(); message.systemMessage = o[QStringLiteral("systemMessage")].toBool(); message.systemMessageType = o[QStringLiteral("type")].toString(); return message; } QByteArray MessageModel::serialize(const Message& message) { QJsonDocument d; QJsonObject o; o[QStringLiteral("messageID")] = message.messageID; o[QStringLiteral("roomID")] = message.roomID; o[QStringLiteral("message")] = message.message; o[QStringLiteral("timestamp")] = message.timestamp; o[QStringLiteral("username")] = message.username; o[QStringLiteral("userID")] = message.userID; o[QStringLiteral("updatedAt")] = message.updatedAt; o[QStringLiteral("editedAt")] = message.editedAt; o[QStringLiteral("editedByUsername")] = message.editedByUsername; o[QStringLiteral("editedByUserID")] = message.editedByUserID; o[QStringLiteral("url")] = message.url; o[QStringLiteral("meta")] = message.meta; o[QStringLiteral("headers")] = message.headers; o[QStringLiteral("parsedUrl")] = message.parsedUrl; o[QStringLiteral("imageUrl")] = message.imageUrl; o[QStringLiteral("color")] = message.color; o[QStringLiteral("alias")] = message.alias; o[QStringLiteral("avatar")] = message.avatar; o[QStringLiteral("groupable")] = message.groupable; o[QStringLiteral("parseUrls")] = message.parseUrls; o[QStringLiteral("systemMessage")] = message.systemMessage; o[QStringLiteral("type")] = message.systemMessageType; d.setObject(o); return d.toBinaryData(); } MessageModel::MessageModel(const QString &roomID, QObject* parent) : QAbstractListModel(parent), m_roomID(roomID) { qCDebug(RUQOLA_LOG) << "Creating message Model"; QDir cacheDir(Ruqola::self()->cacheBasePath()+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); QByteArray arr = QByteArray::fromRawData(byteArray, length); Message m = MessageModel::fromJSon(QJsonDocument::fromBinaryData(arr).object()); addMessage(m); } } } } MessageModel::~MessageModel() { QDir cacheDir(Ruqola::self()->cacheBasePath()+QStringLiteral("/rooms_cache")); qCDebug(RUQOLA_LOG) << "Caching to..." << cacheDir.path(); if (!cacheDir.exists(cacheDir.path())) { cacheDir.mkpath(cacheDir.path()); } QFile f(cacheDir.absoluteFilePath(m_roomID)); if (f.open(QIODevice::WriteOnly)) { QDataStream out(&f); foreach (const Message m, m_allMessages) { QByteArray ms = MessageModel::serialize(m); out.writeBytes(ms, ms.size()); } } } QHash MessageModel::roleNames() const { QHash roles; roles[MessageText] = "messageText"; roles[Username] = "username"; roles[Timestamp] = "timestamp"; roles[UserID] = "userID"; roles[SystemMessage] = "systemMessage"; roles[SystemMessageType] = "type"; roles[MessageID] = "messageID"; roles[RoomID] = "roomID"; roles[UpdatedAt] = "updatedAt"; roles[EditedAt] = "editedAt"; roles[EditedByUserName] = "editedByUsername"; roles[EditedByUserID] = "editedByUserID"; roles[Url] = "URL"; roles[Meta] = "meta"; roles[Headers] = "headers"; roles[ParsedUrl] = "parsedUrl"; roles[ImageUrl] = "imageUrl"; roles[Color] = "color"; roles[Alias] = "alias"; roles[Avatar] = "avatar"; roles[Groupable] = "groupable"; roles[ParseUrls] = "parseUrls"; return roles; } qint64 MessageModel::lastTimestamp() const { if (m_allMessages.size()) { qCDebug(RUQOLA_LOG) << "returning timestamp" << m_allMessages.last().timestamp; return m_allMessages.last().timestamp; } else { return 0; } } int MessageModel::rowCount(const QModelIndex& parent) const { return m_allMessages.size(); (void)parent; } void MessageModel::addMessage(const Message& message) { // Don't add empty messages if (message.message.isEmpty()) { return; } auto existingMessage = qFind(m_allMessages.begin(), m_allMessages.end(), message); bool present = (existingMessage != m_allMessages.end()); auto i = std::upper_bound(m_allMessages.begin(), m_allMessages.end(), message); int pos = i-m_allMessages.begin(); bool messageChanged = false; // if (qFind(m_allMessages.begin(), m_allMessages.end(), message) != m_allMessages.end()) { if (present){ // if (pos != m_allMessages.size()) { // we're at the end // qCDebug(RUQOLA_LOG) << "detecting a message change"; messageChanged = true; //Figure out a better way to update just the really changed message } else { beginInsertRows(QModelIndex(), pos, pos); } if (messageChanged) { m_allMessages.replace(pos-1, message); } else { m_allMessages.insert(i, message); } if (messageChanged) { emit dataChanged(createIndex(1, 1), createIndex(pos, 1)); } else { endInsertRows(); } } QVariant MessageModel::data(const QModelIndex& index, int role) const { int idx = index.row(); if (role == MessageModel::Username) { return m_allMessages.at(idx).username; } else if (role == MessageModel::MessageText) { return m_allMessages.at(idx).message; } else if (role == MessageModel::Timestamp) { return QVariant(m_allMessages.at(idx).timestamp); } else if (role == MessageModel::UserID) { return QVariant(m_allMessages.at(idx).userID); } else if (role == MessageModel::SystemMessage) { return QVariant(m_allMessages.at(idx).systemMessage); } else if (role == MessageModel::SystemMessageType) { return QVariant(m_allMessages.at(idx).systemMessageType); - } else if (role == MessageModel::Alias) { + } else if (role == MessageModel::MessageID) { + return QVariant(m_allMessages.at(idx).messageID); + }else if (role == MessageModel::Alias) { return QVariant(m_allMessages.at(idx).alias); } else { return QVariant(QString()); } } // #include "messagelist.moc" diff --git a/src/qml/Desktop.qml b/src/qml/Desktop.qml index f6742010..a7b6969c 100644 --- a/src/qml/Desktop.qml +++ b/src/qml/Desktop.qml @@ -1,379 +1,380 @@ /* * * 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 . * */ import QtQuick 2.7 import QtQuick.Controls 1.4 import QtQuick.Controls 2.0 as QQC2 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.Ruqola 1.0 import KDE.Ruqola.DDPClient 1.0 //import KDE.Ruqola.Notification 1.0 // import "Log.js" as Log // import "Data.js" as Data import org.kde.kirigami 2.1 as Kirigami Kirigami.ApplicationWindow { id: appid property int margin: 11 property string statusText property string lightGreen: "#6ab141"; property string darkGreen: "#00613a"; property string selectedRoomID: ""; property QtObject selectedRoom property QtObject model width: Kirigami.Units.gridUnit * 55 height: Kirigami.Units.gridUnit * 40 title: qsTr("Ruqola") header: Kirigami.ApplicationHeader {} pageStack.initialPage: [roomsComponent, mainComponent] pageStack.visible: Ruqola.loginStatus == DDPClient.LoggedIn // Keys.onShortcutOverride: event.accepted = (event.key === StandardKey.Quit) // Shortcut { // sequence: StandardKey.Quit // context: Qt.ApplicationShortcut // onActivated: { // console.log("QUITTING (trying)"); // Qt.quit(); // } // } globalDrawer: Kirigami.GlobalDrawer { drawerOpen: false handleVisible: true resetMenuOnTriggered: true topContent: [ Text { text: qsTr("Hello, %1").arg(Ruqola.userName) } ] actions: [ Kirigami.Action { text: "Preferences" iconName: "user-available" Kirigami.Action { text: "Change theme" iconName: "preferences-desktop-theme" } Kirigami.Action { text: "action 2" } Kirigami.Action { text: "action 3" } }, Kirigami.Action { text: "Log out" iconName: "system-log-out" onTriggered: { Ruqola.logOut(); appid.globalDrawer.drawerOpen = false; } }, Kirigami.Action { shortcut: StandardKey.Quit text: "Quit" iconName: "application-exit" onTriggered: { Qt.quit(); } } ] } Login { id: loginTab anchors.fill: parent visible: Ruqola.loginStatus != DDPClient.LoggedIn serverURL: Ruqola.serverURL username: Ruqola.userName onAccepted: { Ruqola.password = loginTab.password; Ruqola.userName = loginTab.username; Ruqola.serverURL = loginTab.serverURL; // DDPClient.loginType = Password; Ruqola.tryLogin(); } } BusyIndicator { id: busy // indeterminate: true anchors.centerIn: parent visible: Ruqola.loginStatus == DDPClient.LoggingIn } Component { id: roomsComponent Kirigami.ScrollablePage { id: roomsPage actions.main: Kirigami.Action { id: editAction iconName: "list-add" // checkable: true onTriggered: { channelsList.open(); } } actions.left: Kirigami.Action { // enabled: editAction.checked iconName: "edit-symbolic" checkable: true onToggled: { if (checked) { roomsList.editingMode = true } else { roomsList.editingMode = false } // do stuff } } background: Rectangle { color: Kirigami.Theme.viewBackgroundColor } mainItem: // QQC2.TextField { // id: searchField // placeholderText: qsTr("Search...") // width: parent.width // } RoomsView { id: roomsList implicitWidth: Kirigami.Units.gridUnit * 10 anchors.fill: parent // width: parent.width // height: parent.height model: Ruqola.roomModel() selectedRoomID: appid.selectedRoomID; onRoomSelected: { if (roomID == selectedRoomID) { return; } console.log("Choosing room", roomID); appid.selectedRoomID = roomID; appid.model = Ruqola.getModelForRoom(roomID) appid.selectedRoom = Ruqola.getRoom(roomID) } } //RoomsView Kirigami.OverlaySheet { id: channelsList contentItem: ChannelsList { // anchors.fill: parent } } } } Component { id: mainComponent Kirigami.ScrollablePage { // anchors.right: parent.right // anchors.top: parent.top // anchors.bottom: parent.bottom // anchors.left: roomsComponent.right // anchors.fill: parent id: mainWidget leftPadding: Kirigami.Units.smallSpacing rightPadding: Kirigami.Units.smallSpacing topPadding: Kirigami.Units.smallSpacing bottomPadding: Kirigami.Units.smallSpacing title: appid.selectedRoom ? "" : "#" + appid.selectedRoom.name ListView { id: activeChat model: appid.model // model: Ruqola.getModelForRoom(selectedRoomID) anchors.fill: parent onCountChanged: { positionViewAtIndex(count - 1, ListView.Beginning) // positionViewAtEnd() } Component.onCompleted: positionViewAtEnd();// positionViewAtIndex(count - 1, ListView.End) visible : count > 0 - z: -1 +// z: -1 delegate: FancyMessageDelegate { width: parent.width i_messageText: messageText i_username: username i_systemMessage: systemMessage i_systemMessageType: type i_timestamp: timestamp + i_messageID: messageID //width: parent.width } } footer: Item { anchors.bottom: parent.bottom anchors.left: parent.left anchors.right: parent.right id: input height: 40 TextField { id: messageLine anchors.left: parent.left anchors.bottom: parent.bottom anchors.top: parent.top anchors.right: emoticonsButton.left placeholderText: if (Ruqola.loginStatus != DDPClient.LoggedIn || (selectedRoomID=="")){ qsTr("Please Select a room") } else{ qsTr("Enter message") } // height: 2.7*font.pixelSize property string type: "text"; onAccepted: { if (text != "" && Ruqola.loginStatus == DDPClient.LoggedIn && !(selectedRoomID=="")) { Ruqola.sendMessage(selectedRoomID, text, type); text = ""; } } } Button { anchors.bottom: parent.bottom anchors.top: parent.top anchors.right: attachmentsButton.left width: 50 id : emoticonsButton iconName: "emoticonsButton" iconSource: "qrc:/Emoticon.png" visible: true } Button { anchors.bottom: parent.bottom anchors.top: parent.top anchors.right: parent.right width: 50 id : attachmentsButton iconName: "attachmentsButton" iconSource: "qrc:/icons/attach-button.jpg" visible: true onClicked: Ruqola.attachmentButtonClicked(); } }//Item input }// mainWidget Item } // Image { // id: receivedImage // source:" " // width: 60 // height: 80 // fillMode: Image.PreserveAspectFit //// visible: //only when an image is recieved from server // sourceSize.width: 1024 // sourceSize.height: 1024 // } onClosing: { console.log("Minimizing to systray..."); hide(); } function toggleShow() { if (visible) { hide(); } else { show(); raise(); requestActivate(); } } Component.onCompleted: { systrayIcon.activated.connect(toggleShow); systrayIcon.messageClicked.connect(toggleShow); // roomsList.model = Ruqola.roomModel(); // timer.start(); // timer.fire(); } /* Timer { id: timer interval: 1000 onTriggered: { // console.log("FIRE"); switch (Ruqola.loginStatus) { case Ruqola.NotConnected: statusText = qsTr("Not connected."); break; case Ruqola.LoggedIn: statusText = qsTr("Connected to " + Ruqola.serverURL); break; } } repeat: true }*/ // onStatusTextChanged: timer.restart(); } diff --git a/src/qml/FancyMessageDelegate.qml b/src/qml/FancyMessageDelegate.qml index 976d0b1a..92453580 100644 --- a/src/qml/FancyMessageDelegate.qml +++ b/src/qml/FancyMessageDelegate.qml @@ -1,102 +1,113 @@ /* * * 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 . * */ import QtQuick 2.0 // import "marked.js" as Markdown import "js/marked.js" as MarkDown; import QtQuick.Controls 2.2 import org.kde.kirigami 2.1 as Kirigami import QtQuick.Layouts 1.1 Rectangle { function getTextFor(type) { if (type === "uj") { return qsTr("has joined the channel"); } else if (type === "ul") { return qsTr("has left the channel"); } else if (type === "room_changed_topic") { return qsTr("changed topic to \"%1\"").arg(i_messageText) } else if (type === "au") { return qsTr("added %1 to the conversation").arg(i_messageText) } else if (type === "r") { return qsTr("changed room name to \"%1\"").arg(i_messageText) } else if (type === "room_changed_description") { return qsTr("changed room description to \"%1\"").arg(i_messageText) } else { console.log("Unkown type for message"); console.log(type); console.log(i_messageText) return qsTr("Unknown action!"); } } + property string i_messageID property string i_messageText property string i_username property bool i_systemMessage property string i_systemMessageType property string i_avatar property var i_timestamp id: messageMain color: "#eeeeee" // implicitHeight: textLabel.contentHeight implicitHeight: 4*Kirigami.Units.smallSpacing + loaded.implicitHeight implicitWidth: 150 anchors.bottomMargin: 200 // anchors.margins: 50 - + function linkActivated(link) { + console.log("Link clicked: " + link) + } + Loader { id: loaded anchors.topMargin: Kirigami.Units.smallSpacing anchors.fill: parent + Component.onCompleted: { if (i_systemMessage) { setSource("messages/SystemMessage.qml", { i_messageText: i_messageText, i_username: i_username, i_timestamp: i_timestamp, - i_systemMessageType: i_systemMessageType + i_systemMessageType: i_systemMessageType, + i_messageID: i_messageID } ) } else { setSource("messages/UserMessage.qml", { i_messageText: i_messageText, i_username: i_username, - i_timestamp: i_timestamp + i_timestamp: i_timestamp, + i_messageID: i_messageID } ) } +// loaded.linkActivated.connect(linkActivated) } - + } + Connections { + target: loaded.item + onLinkActivated: linkActivated(link) } } diff --git a/src/qml/messages/SystemMessage.qml b/src/qml/messages/SystemMessage.qml index db307ab4..adb53621 100644 --- a/src/qml/messages/SystemMessage.qml +++ b/src/qml/messages/SystemMessage.qml @@ -1,145 +1,155 @@ /* * * 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 . * */ import QtQuick 2.0 // import "marked.js" as Markdown // import "js/marked.js" as MarkDown; import QtQuick.Controls 2.2 import org.kde.kirigami 2.1 as Kirigami import QtQuick.Layouts 1.1 Rectangle { function getTextFor(type) { if (type === "uj") { return qsTr("has joined the channel"); } else if (type === "ul") { return qsTr("has left the channel"); } else if (type === "room_changed_topic") { return qsTr("changed topic to: %1").arg(i_messageText) } else if (type === "au") { return qsTr("added %1 to the conversation").arg(i_messageText) } else if (type === "r") { - return qsTr("changed room name to #%1").arg(i_messageText) + return qsTr("changed room name to #%1").arg(i_messageText) } else if (type === "room_changed_description") { return qsTr("changed room description to %1").arg(i_messageText) } else if (type === "room_changed_privacy") { return qsTr("changed room privacy to %1").arg(i_messageText) } else { console.log("Unkown type for message"); console.log(type); console.log(i_messageText) return qsTr("Unknown action!"); } } property string i_messageText property string i_username property bool i_systemMessage property string i_systemMessageType property var i_timestamp + signal linkActivated(string link) + id: messageMain color: "#eeeeee" implicitHeight: 2*Kirigami.Units.smallSpacing + textLabel.implicitHeight implicitWidth: 150 anchors.bottomMargin: 200 // anchors.margins: 50 Rectangle { + anchors.rightMargin: 2*Kirigami.Units.largeSpacing + anchors.leftMargin: 2*Kirigami.Units.largeSpacing + anchors.centerIn: parent width: textLabel.width + 6*Kirigami.Units.smallSpacing - height: textLabel.height + 2*Kirigami.Units.smallSpacing + height: textLabel.height //+ 2*Kirigami.Units.smallSpacing color: Kirigami.Theme.disabledTextColor // opacity: .2 radius: height - Label { + Kirigami.Label { id: textLabel color: Kirigami.Theme.textColor opacity: 1 anchors.centerIn: parent anchors.leftMargin: Kirigami.Units.smallSpacing anchors.rightMargin: Kirigami.Units.smallSpacing + text: i_username + " " + getTextFor(i_systemMessageType) wrapMode: Label.Wrap + + renderType: Text.NativeRendering + + onLinkActivated: messageMain.linkActivated(link) } } // Rectangle { // // anchors.topMargin: Kirigami.Units.smallSpacing // // anchors.centerIn: parent // color: "red" // anchors.top: parent.top // anchors.bottom: parent.bottom // // // // // spacing: Kirigami.Units.smallSpacing // // Rectangle { // id: textRect // color: "blue" // radius: height // // anchors.fill: parent // // // color: "#eeeeee" // // anchors.top: parent.top // // anchors.bottom: parent.bottom // anchors.bottomMargin: Kirigami.Units.smallSpacing // // anchors.horizontalCenter: parent.horizontalCenter // // // height: textLabel.implicitHeight + usernameLabel.implicitHeight // // // } // Kirigami.Label { // id: timeLabel // text: "["+(new Date(i_timestamp)).toLocaleTimeString(Locale.ShortFormat)+"]" // // anchors.top: parent.top // anchors.bottom: parent.bottom // // color: Kirigami.Theme.textColor // opacity: .5 // // z:1 // } // } // } diff --git a/src/qml/messages/UserMessage.qml b/src/qml/messages/UserMessage.qml index bb76c3cc..e3318153 100644 --- a/src/qml/messages/UserMessage.qml +++ b/src/qml/messages/UserMessage.qml @@ -1,145 +1,198 @@ /* * * 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 . * */ import QtQuick 2.0 // import "marked.js" as Markdown // import "js/marked.js" as MarkDown; import QtQuick.Controls 2.2 import org.kde.kirigami 2.1 as Kirigami import QtQuick.Layouts 1.1 +import KDE.Ruqola.Ruqola 1.0 Rectangle { - - function getTextFor(type) { - - if (type === "uj") { - return qsTr("has joined the channel"); - } else if (type === "ul") { - return qsTr("has left the channel"); - } else if (type === "room_changed_topic") { - return qsTr("changed topic to \"%1\"").arg(i_messageText) - } else if (type === "au") { - return qsTr("added %1 to the conversation").arg(i_messageText) - } else if (type === "r") { - return qsTr("changed room name to \"%1\"").arg(i_messageText) - } else if (type === "room_changed_description") { - return qsTr("changed room description to \"%1\"").arg(i_messageText) - } else { - console.log("Unkown type for message"); - console.log(type); - console.log(i_messageText) - return qsTr("Unknown action!"); + + function stringToColour(str) { + var hash = 0; + for (var i = 0; i < str.length; i++) { + hash = str.charCodeAt(i) + ((hash << 5) - hash); + } + var colour = '#'; + for (var i = 0; i < 3; i++) { + var value = (hash >> (i * 8)) & 0xFF; + colour += ('00' + value.toString(16)).substr(-2); } + return colour; } property string i_messageText + property string i_messageID property string i_username property bool i_systemMessage property string i_systemMessageType property string i_avatar property var i_timestamp + + signal linkActivated(string link) + + id: messageMain color: "#eeeeee" -// implicitHeight: textLabel.contentHeight implicitHeight: 4*Kirigami.Units.smallSpacing + Math.max(textLabel.implicitHeight+usernameLabel.implicitHeight, avatarRect.implicitHeight) implicitWidth: 150 anchors.bottomMargin: 200 -// anchors.margins: 50 + Menu { + id: menu + + MenuItem { +// enabled: i_username == Ruqola.userName + contentItem: Kirigami.Label { + text: "Edit" + enabled: i_username == Ruqola.userName + } + onTriggered: { + console.log("Edit", i_messageID, i_messageText); + console.log("User", Ruqola.userName, i_username); + } + } + MenuItem { + contentItem: Kirigami.Label { + text: "Reply" + } + onTriggered: { + console.log("Reply to", i_messageID); + } + } + } RowLayout { anchors.topMargin: Kirigami.Units.smallSpacing anchors.fill: parent + anchors.rightMargin: Kirigami.Units.largeSpacing + anchors.leftMargin: Kirigami.Units.largeSpacing // implicitHeight: textLabel.contentHeight spacing: Kirigami.Units.smallSpacing // spacing: 12 Rectangle { Layout.fillHeight: false id: avatarRect implicitWidth: 24 implicitHeight: 24 - anchors.margins: Kirigami.Units.smallSpacing + radius: 3 + + anchors.rightMargin: 2*Kirigami.Units.smallSpacing + + color: stringToColour(i_username) - color: "gray" anchors.top: parent.top } Rectangle { id: textRect Layout.fillWidth: true -// radius: 4 -// color: "#eeeeee" + radius: 3 anchors.top: parent.top anchors.bottom: parent.bottom anchors.bottomMargin: Kirigami.Units.smallSpacing anchors.leftMargin: Kirigami.Units.smallSpacing -// height: textLabel.implicitHeight + usernameLabel.implicitHeight + + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.RightButton + + onClicked: { + console.log("clicked"); + if (mouse.button == Qt.RightButton) { + menu.x = mouse.x + menu.y = mouse.y + menu.open(); + console.log("Menu opened", mouse.x); + + } + } + } Column { anchors.leftMargin: Kirigami.Units.smallSpacing anchors.rightMargin: Kirigami.Units.smallSpacing anchors.fill: parent Kirigami.Heading { level: 5 id: usernameLabel font.bold: true text: i_username - // anchors.top: parent.top + anchors.right: parent.right anchors.left: parent.left + height: avatarRect.height } Kirigami.Label { id: textLabel - // anchors.top: usernameLabel.bottom anchors.right: parent.right anchors.left: parent.left - // anchors.bottom: parent.bottom + + anchors.leftMargin: Kirigami.Units.smallSpacing + anchors.rightMargin: Kirigami.Units.smallSpacing + text: i_messageText wrapMode: Label.Wrap - } + + renderType: Text.NativeRendering + + onLinkActivated: messageMain.linkActivated(link) + + -// Rectangle { -// color: "red" -// // anchors.top: textLabel.bottom -// anchors.right: parent.right -// anchors.left: parent.left -// // anchors.bottom: parent.bottom -// implicitHeight: 2*Kirigami.Units.smallSpacing -// } + } } + + + } + Kirigami.Label { + id: timestampText + text: Qt.formatTime(new Date(i_timestamp), "hh:mm") + opacity: .5 + + anchors.top: parent.top + anchors.right: parent.right + anchors.leftMargin: Kirigami.Units.smallSpacing + + z: 10 } } + +// Component.onCompleted: console.log(i_timestamp) }