diff --git a/matrique.pro b/matrique.pro index 5ba689a..4111400 100644 --- a/matrique.pro +++ b/matrique.pro @@ -30,7 +30,8 @@ SOURCES += src/main.cpp \ src/matriqueroom.cpp \ src/userlistmodel.cpp \ src/imageitem.cpp \ - src/accountlistmodel.cpp + src/accountlistmodel.cpp \ + src/matriqueuser.cpp RESOURCES += \ res.qrc @@ -91,4 +92,5 @@ HEADERS += \ src/matriqueroom.h \ src/userlistmodel.h \ src/imageitem.h \ - src/accountlistmodel.h + src/accountlistmodel.h \ + src/matriqueuser.h diff --git a/qml/component/MessageDelegate.qml b/qml/component/MessageDelegate.qml index 60f1c30..5d6b26c 100644 --- a/qml/component/MessageDelegate.qml +++ b/qml/component/MessageDelegate.qml @@ -4,6 +4,7 @@ import QtQuick.Layouts 1.3 import QtQuick.Controls.Material 2.2 import Matrique 0.1 import Matrique.Settings 0.1 +import "qrc:/js/util.js" as Util RowLayout { readonly property bool avatarVisible: !(sentByMe || (aboveAuthor === author && section === aboveSection)) @@ -22,15 +23,16 @@ RowLayout { spacing: 6 - ImageStatus { + ImageItem { Layout.preferredWidth: 40 Layout.preferredHeight: 40 Layout.alignment: Qt.AlignTop round: false visible: avatarVisible - source: author.avatarUrl != "" ? "image://mxc/" + author.avatarUrl : null - displayText: author.displayName + hint: author.displayName + defaultColor: Util.stringToColor(author.displayName) + image: author.avatar } Rectangle { @@ -61,6 +63,11 @@ RowLayout { Material.foreground: Material.accent coloredBackground: highlighted font.bold: true + + MouseArea { + anchors.fill: parent + onClicked: inputField.insert(inputField.cursorPosition, author.displayName) + } } AutoLabel { diff --git a/qml/component/RoomDrawer.qml b/qml/component/RoomDrawer.qml index 2239150..a776444 100644 --- a/qml/component/RoomDrawer.qml +++ b/qml/component/RoomDrawer.qml @@ -24,13 +24,14 @@ Drawer { anchors.fill: parent anchors.margins: 32 - ImageStatus { + ImageItem { Layout.preferredWidth: 64 Layout.preferredHeight: 64 Layout.alignment: Qt.AlignHCenter - source: room && room.avatarUrl != "" ? "image://mxc/" + room.avatarUrl : null - displayText: room ? room.displayName : "" + hint: room ? room.displayName : "No name" + defaultColor: Util.stringToColor(room ? room.displayName : "No name") + image: matriqueController.safeImage(room ? room.avatar : null) } Label { diff --git a/qml/form/RoomForm.qml b/qml/form/RoomForm.qml index 91741e8..57bf62c 100644 --- a/qml/form/RoomForm.qml +++ b/qml/form/RoomForm.qml @@ -9,6 +9,7 @@ import Matrique.Settings 0.1 import "../component" import "qrc:/js/md.js" as Markdown +import "qrc:/js/util.js" as Util Item { property var currentRoom: null @@ -57,12 +58,13 @@ Item { spacing: 12 - ImageStatus { + ImageItem { Layout.preferredWidth: height Layout.fillHeight: true - source: currentRoom && currentRoom.avatarUrl != "" ? "image://mxc/" + currentRoom.avatarUrl : null - displayText: currentRoom ? currentRoom.displayName : "" + hint: currentRoom ? currentRoom.displayName : "No name" + defaultColor: Util.stringToColor(currentRoom ? currentRoom.displayName : "No name") + image: matriqueController.safeImage(currentRoom ? currentRoom.avatar : null) } ColumnLayout { diff --git a/src/controller.cpp b/src/controller.cpp index cb3310e..4c03435 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -1,6 +1,7 @@ #include "controller.h" #include "matriqueroom.h" +#include "matriqueuser.h" #include "settings.h" #include "events/eventcontent.h" @@ -39,6 +40,7 @@ Controller::Controller(QObject* parent) : QObject(parent) { tray->show(); Connection::setRoomType(); + Connection::setUserType(); QTimer::singleShot(0, this, SLOT(invokeLogin())); } @@ -215,3 +217,8 @@ void Controller::showMessage(const QString& title, const QString& msg, const QIcon& icon) { tray->showMessage(title, msg, icon); } + +QImage Controller::safeImage(QImage image) { + if (image.isNull()) return QImage(); + return image; +} diff --git a/src/controller.h b/src/controller.h index 46ae4f5..e42bd37 100644 --- a/src/controller.h +++ b/src/controller.h @@ -72,6 +72,8 @@ class Controller : public QObject { void copyToClipboard(const QString& text); void playAudio(QUrl localFile); void showMessage(const QString& title, const QString& msg, const QIcon& icon); + + static QImage safeImage(QImage image); }; #endif // CONTROLLER_H diff --git a/src/imageitem.cpp b/src/imageitem.cpp index bff488c..69a8acc 100644 --- a/src/imageitem.cpp +++ b/src/imageitem.cpp @@ -14,8 +14,12 @@ void ImageItem::paint(QPainter *painter) { if (m_image.isNull()) { painter->setPen(Qt::NoPen); painter->setBrush(QColor(m_color)); - painter->drawEllipse(0, 0, int(bounding_rect.width()), - int(bounding_rect.height())); + if (m_round) + painter->drawEllipse(0, 0, int(bounding_rect.width()), + int(bounding_rect.height())); + else + painter->drawRect(0, 0, int(bounding_rect.width()), + int(bounding_rect.height())); painter->setPen(QPen(Qt::white, 2)); QFont font; font.setPixelSize(22); @@ -33,11 +37,13 @@ void ImageItem::paint(QPainter *painter) { QPointF center = bounding_rect.center() - scaled.rect().center(); - QPainterPath clip; - clip.addEllipse( - 0, 0, bounding_rect.width(), - bounding_rect.height()); // this is the shape we want to clip to - painter->setClipPath(clip); + if (m_round) { + QPainterPath clip; + clip.addEllipse( + 0, 0, bounding_rect.width(), + bounding_rect.height()); // this is the shape we want to clip to + painter->setClipPath(clip); + } if (center.x() < 0) center.setX(0); if (center.y() < 0) center.setY(0); @@ -66,3 +72,11 @@ void ImageItem::setDefaultColor(QString color) { update(); } } + +void ImageItem::setRound(bool value) { + if (m_round != value) { + m_round = value; + emit roundChanged(); + update(); + } +} diff --git a/src/imageitem.h b/src/imageitem.h index cda0471..0d7cb39 100644 --- a/src/imageitem.h +++ b/src/imageitem.h @@ -13,6 +13,7 @@ class ImageItem : public QQuickPaintedItem { Q_PROPERTY(QString hint READ hint WRITE setHint NOTIFY hintChanged) Q_PROPERTY(QString defaultColor READ defaultColor WRITE setDefaultColor NOTIFY defaultColorChanged) + Q_PROPERTY(bool round READ round WRITE setRound NOTIFY roundChanged) public: ImageItem(QQuickItem *parent = nullptr); @@ -28,15 +29,20 @@ class ImageItem : public QQuickPaintedItem { QString defaultColor() { return m_color; } void setDefaultColor(QString color); + bool round() { return m_round; } + void setRound(bool value); + signals: void imageChanged(); void hintChanged(); void defaultColorChanged(); + void roundChanged(); private: QImage m_image; QString m_hint = "H"; QString m_color = "#000000"; + bool m_round = true; }; #endif // IMAGEITEM_H diff --git a/src/matriqueroom.h b/src/matriqueroom.h index eb0f1bf..8250ca5 100644 --- a/src/matriqueroom.h +++ b/src/matriqueroom.h @@ -10,6 +10,7 @@ using namespace QMatrixClient; class MatriqueRoom : public Room { Q_OBJECT + Q_PROPERTY(QImage avatar READ getAvatar NOTIFY avatarChanged) Q_PROPERTY(bool hasUsersTyping READ hasUsersTyping NOTIFY typingChanged) Q_PROPERTY(QString usersTyping READ getUsersTyping NOTIFY typingChanged) Q_PROPERTY(QString cachedInput READ cachedInput WRITE setCachedInput NOTIFY @@ -18,6 +19,8 @@ class MatriqueRoom : public Room { explicit MatriqueRoom(Connection* connection, QString roomId, JoinState joinState = {}); + QImage getAvatar() { return avatar(64); } + const QString& cachedInput() const { return m_cachedInput; } void setCachedInput(const QString& input) { if (input != m_cachedInput) { diff --git a/src/matriqueuser.cpp b/src/matriqueuser.cpp new file mode 100644 index 0000000..a8bf365 --- /dev/null +++ b/src/matriqueuser.cpp @@ -0,0 +1,6 @@ +#include "matriqueuser.h" + +MatriqueUser::MatriqueUser(QString userId, Connection* connection) + : User(userId, connection) { + connect(this, &User::avatarChanged, this, &MatriqueUser::inheritedAvatarChanged); +} diff --git a/src/matriqueuser.h b/src/matriqueuser.h new file mode 100644 index 0000000..49df02d --- /dev/null +++ b/src/matriqueuser.h @@ -0,0 +1,23 @@ +#ifndef MATRIQUEUSER_H +#define MATRIQUEUSER_H + +#include "user.h" +#include "room.h" + +#include + +using namespace QMatrixClient; + +class MatriqueUser : public User { + Q_OBJECT + Q_PROPERTY(QImage avatar READ getAvatar NOTIFY inheritedAvatarChanged) + public: + MatriqueUser(QString userId, Connection* connection); + + QImage getAvatar() { return avatar(64); } + + signals: + void inheritedAvatarChanged(User* user, const Room* roomContext); +}; + +#endif // MATRIQUEUSER_H