From bd5c119f537dcfb9dc58cc73367e166f89bc9f6d Mon Sep 17 00:00:00 2001 From: Black Hat Date: Thu, 6 Sep 2018 16:22:00 +0800 Subject: [PATCH] Add ImageItem. --- matrique.pro | 6 ++-- qml/form/RoomListForm.qml | 31 ++++++++++++++++-- src/imageitem.cpp | 68 +++++++++++++++++++++++++++++++++++++++ src/imageitem.h | 42 ++++++++++++++++++++++++ src/main.cpp | 2 ++ src/roomlistmodel.cpp | 6 ++-- 6 files changed, 146 insertions(+), 9 deletions(-) create mode 100644 src/imageitem.cpp create mode 100644 src/imageitem.h diff --git a/matrique.pro b/matrique.pro index f27d296..4cd7c0b 100644 --- a/matrique.pro +++ b/matrique.pro @@ -29,7 +29,8 @@ SOURCES += src/main.cpp \ src/imageproviderconnection.cpp \ src/emojimodel.cpp \ src/matriqueroom.cpp \ - src/userlistmodel.cpp + src/userlistmodel.cpp \ + src/imageitem.cpp RESOURCES += \ res.qrc @@ -89,4 +90,5 @@ HEADERS += \ src/imageproviderconnection.h \ src/emojimodel.h \ src/matriqueroom.h \ - src/userlistmodel.h + src/userlistmodel.h \ + src/imageitem.h diff --git a/qml/form/RoomListForm.qml b/qml/form/RoomListForm.qml index d1d90ae..5af52d3 100644 --- a/qml/form/RoomListForm.qml +++ b/qml/form/RoomListForm.qml @@ -142,12 +142,24 @@ Item { spacing: 12 - ImageStatus { + // ImageStatus { + // Layout.preferredWidth: height + // Layout.fillHeight: true + + // source: avatar ? "image://mxc/" + avatar : "" + // displayText: name + // } + + ImageItem { + id: imageItem + Layout.preferredWidth: height Layout.fillHeight: true - source: avatar ? "image://mxc/" + avatar : "" - displayText: name + hint: name || "No Name" + defaultColor: stringToColor(name || "No Name") + + image: avatar } ColumnLayout { @@ -212,4 +224,17 @@ Item { } } } + + function stringToColor(str) { + var hash = 0; + for (var i = 0; i < str.length; i++) { + hash = str.charCodeAt(i) + ((hash << 5) - hash); + } + var colour = '#'; + for (var j = 0; j < 3; j++) { + var value = (hash >> (j * 8)) & 0xFF; + colour += ('00' + value.toString(16)).substr(-2); + } + return colour; + } } diff --git a/src/imageitem.cpp b/src/imageitem.cpp new file mode 100644 index 0000000..bff488c --- /dev/null +++ b/src/imageitem.cpp @@ -0,0 +1,68 @@ +#include "imageitem.h" + +#include +#include +#include + +ImageItem::ImageItem(QQuickItem *parent) : QQuickPaintedItem(parent) {} + +void ImageItem::paint(QPainter *painter) { + QRectF bounding_rect = boundingRect(); + + painter->setRenderHint(QPainter::Antialiasing, true); + + 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())); + painter->setPen(QPen(Qt::white, 2)); + QFont font; + font.setPixelSize(22); + font.setBold(true); + painter->setFont(font); + painter->drawText( + QRect(0, 0, int(bounding_rect.width()), int(bounding_rect.height())), + Qt::AlignCenter, m_hint.at(0).toUpper()); + return; + } + + QImage scaled = m_image.scaled( + int(bounding_rect.width()) + 1, int(bounding_rect.height()) + 1, + Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); + + 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 (center.x() < 0) center.setX(0); + if (center.y() < 0) center.setY(0); + + painter->drawImage(center, scaled); +} + +void ImageItem::setImage(const QImage &image) { + m_image = image; + emit imageChanged(); + update(); +} + +void ImageItem::setHint(QString newHint) { + if (m_hint != newHint) { + m_hint = newHint; + emit hintChanged(); + update(); + } +} + +void ImageItem::setDefaultColor(QString color) { + if (color != m_color) { + m_color = color; + emit defaultColorChanged(); + update(); + } +} diff --git a/src/imageitem.h b/src/imageitem.h new file mode 100644 index 0000000..b743f0e --- /dev/null +++ b/src/imageitem.h @@ -0,0 +1,42 @@ +#ifndef IMAGEITEM_H +#define IMAGEITEM_H + +#include +#include +#include +#include +#include + +class ImageItem : public QQuickPaintedItem { + Q_OBJECT + Q_PROPERTY(QImage image READ image WRITE setImage NOTIFY imageChanged) + Q_PROPERTY(QString hint READ hint WRITE setHint NOTIFY hintChanged) + Q_PROPERTY(QString defaultColor READ defaultColor WRITE setDefaultColor NOTIFY + defaultColorChanged) + + public: + ImageItem(QQuickItem *parent = nullptr); + + void paint(QPainter *painter); + + QImage image() const { return m_image; } + void setImage(const QImage &image); + + QString hint() { return m_hint; } + void setHint(QString hint); + + QString defaultColor() { return m_color; } + void setDefaultColor(QString color); + + signals: + void imageChanged(); + void hintChanged(); + void defaultColorChanged(); + + private: + QImage m_image; + QString m_hint; + QString m_color = "#000000"; +}; + +#endif // IMAGEITEM_H diff --git a/src/main.cpp b/src/main.cpp index fccb6b8..a661494 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,6 +3,7 @@ #include #include +#include "imageitem.h" #include "controller.h" #include "emojimodel.h" #include "imageprovider.h" @@ -35,6 +36,7 @@ int main(int argc, char *argv[]) { qRegisterMetaType("MessageEventType"); qRegisterMetaType("MatriqueRoom"); + qmlRegisterType("Matrique", 0, 1, "ImageItem"); qmlRegisterType("Matrique", 0, 1, "Controller"); qmlRegisterType("Matrique", 0, 1, "RoomListModel"); qmlRegisterType("Matrique", 0, 1, "UserListModel"); diff --git a/src/roomlistmodel.cpp b/src/roomlistmodel.cpp index 1a460ec..5fa027a 100644 --- a/src/roomlistmodel.cpp +++ b/src/roomlistmodel.cpp @@ -139,10 +139,8 @@ QVariant RoomListModel::data(const QModelIndex& index, int role) const { MatriqueRoom* room = m_rooms.at(index.row()); if (role == NameRole) return room->displayName(); if (role == AvatarRole) { - if (room->avatarUrl().toString() != "") { - return room->avatarUrl(); - } - return QVariant(); + if (room->avatarUrl().toString() != "") return room->avatar(64, 64); + return QImage(); } if (role == TopicRole) return room->topic(); if (role == CategoryRole) {