forked from blue/squawk
Some basic message painting
This commit is contained in:
parent
e1eea2f3a2
commit
e0ef1ef797
@ -40,6 +40,7 @@ set(squawkUI_SRC
|
|||||||
utils/comboboxdelegate.cpp
|
utils/comboboxdelegate.cpp
|
||||||
utils/dropshadoweffect.cpp
|
utils/dropshadoweffect.cpp
|
||||||
utils/feedview.cpp
|
utils/feedview.cpp
|
||||||
|
utils/messagedelegate.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# Tell CMake to create the helloworld executable
|
# Tell CMake to create the helloworld executable
|
||||||
|
@ -231,7 +231,7 @@ void Models::Account::toOfflineState()
|
|||||||
Item::toOfflineState();
|
Item::toOfflineState();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Models::Account::getAvatarPath()
|
QString Models::Account::getAvatarPath() const
|
||||||
{
|
{
|
||||||
return avatarPath;
|
return avatarPath;
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ namespace Models {
|
|||||||
QString getError() const;
|
QString getError() const;
|
||||||
|
|
||||||
void setAvatarPath(const QString& path);
|
void setAvatarPath(const QString& path);
|
||||||
QString getAvatarPath();
|
QString getAvatarPath() const;
|
||||||
|
|
||||||
void setAvailability(Shared::Availability p_avail);
|
void setAvailability(Shared::Availability p_avail);
|
||||||
void setAvailability(unsigned int p_avail);
|
void setAvailability(unsigned int p_avail);
|
||||||
|
@ -27,7 +27,7 @@ Models::Element::Element(Type p_type, const Models::Account* acc, const QString&
|
|||||||
avatarPath(),
|
avatarPath(),
|
||||||
avatarState(Shared::Avatar::empty),
|
avatarState(Shared::Avatar::empty),
|
||||||
account(acc),
|
account(acc),
|
||||||
feed(new MessageFeed())
|
feed(new MessageFeed(this))
|
||||||
{
|
{
|
||||||
connect(feed, &MessageFeed::requestArchive, this, &Element::requestArchive);
|
connect(feed, &MessageFeed::requestArchive, this, &Element::requestArchive);
|
||||||
|
|
||||||
@ -149,3 +149,8 @@ void Models::Element::responseArchive(const std::list<Shared::Message> list)
|
|||||||
{
|
{
|
||||||
feed->responseArchive(list);
|
feed->responseArchive(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Models::Element::isRoom() const
|
||||||
|
{
|
||||||
|
return type != contact;
|
||||||
|
}
|
||||||
|
@ -42,6 +42,7 @@ public:
|
|||||||
void changeMessage(const QString& id, const QMap<QString, QVariant>& data);
|
void changeMessage(const QString& id, const QMap<QString, QVariant>& data);
|
||||||
unsigned int getMessagesCount() const;
|
unsigned int getMessagesCount() const;
|
||||||
void responseArchive(const std::list<Shared::Message> list);
|
void responseArchive(const std::list<Shared::Message> list);
|
||||||
|
bool isRoom() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void requestArchive(const QString& before);
|
void requestArchive(const QString& before);
|
||||||
|
@ -283,6 +283,15 @@ Shared::ConnectionState Models::Item::getAccountConnectionState() const
|
|||||||
return acc->getState();
|
return acc->getState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Models::Item::getAccountAvatarPath() const
|
||||||
|
{
|
||||||
|
const Account* acc = getParentAccount();
|
||||||
|
if (acc == nullptr) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return acc->getAvatarPath();
|
||||||
|
}
|
||||||
|
|
||||||
QString Models::Item::getDisplayedName() const
|
QString Models::Item::getDisplayedName() const
|
||||||
{
|
{
|
||||||
return name;
|
return name;
|
||||||
|
@ -80,6 +80,7 @@ class Item : public QObject{
|
|||||||
QString getAccountName() const;
|
QString getAccountName() const;
|
||||||
QString getAccountJid() const;
|
QString getAccountJid() const;
|
||||||
QString getAccountResource() const;
|
QString getAccountResource() const;
|
||||||
|
QString getAccountAvatarPath() const;
|
||||||
Shared::ConnectionState getAccountConnectionState() const;
|
Shared::ConnectionState getAccountConnectionState() const;
|
||||||
Shared::Availability getAccountAvailability() const;
|
Shared::Availability getAccountAvailability() const;
|
||||||
|
|
||||||
|
@ -17,35 +17,39 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "messagefeed.h"
|
#include "messagefeed.h"
|
||||||
|
#include "element.h"
|
||||||
|
#include "room.h"
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
const QHash<int, QByteArray> MessageFeed::roles = {
|
const QHash<int, QByteArray> Models::MessageFeed::roles = {
|
||||||
{Text, "text"},
|
{Text, "text"},
|
||||||
{Sender, "sender"},
|
{Sender, "sender"},
|
||||||
{Date, "date"},
|
{Date, "date"},
|
||||||
{DeliveryState, "deliveryState"},
|
{DeliveryState, "deliveryState"},
|
||||||
{Correction, "correction"},
|
{Correction, "correction"},
|
||||||
{SentByMe,"sentByMe"}
|
{SentByMe,"sentByMe"},
|
||||||
|
{Avatar, "avatar"}
|
||||||
};
|
};
|
||||||
|
|
||||||
MessageFeed::MessageFeed(QObject* parent):
|
Models::MessageFeed::MessageFeed(const Element* ri, QObject* parent):
|
||||||
QAbstractListModel(parent),
|
QAbstractListModel(parent),
|
||||||
storage(),
|
storage(),
|
||||||
indexById(storage.get<id>()),
|
indexById(storage.get<id>()),
|
||||||
indexByTime(storage.get<time>()),
|
indexByTime(storage.get<time>()),
|
||||||
|
rosterItem(ri),
|
||||||
syncState(incomplete)
|
syncState(incomplete)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageFeed::~MessageFeed()
|
Models::MessageFeed::~MessageFeed()
|
||||||
{
|
{
|
||||||
for (Shared::Message* message : storage) {
|
for (Shared::Message* message : storage) {
|
||||||
delete message;
|
delete message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageFeed::addMessage(const Shared::Message& msg)
|
void Models::MessageFeed::addMessage(const Shared::Message& msg)
|
||||||
{
|
{
|
||||||
QString id = msg.getId();
|
QString id = msg.getId();
|
||||||
StorageById::const_iterator itr = indexById.find(id);
|
StorageById::const_iterator itr = indexById.find(id);
|
||||||
@ -67,15 +71,15 @@ void MessageFeed::addMessage(const Shared::Message& msg)
|
|||||||
endInsertRows();
|
endInsertRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageFeed::changeMessage(const QString& id, const Shared::Message& msg)
|
void Models::MessageFeed::changeMessage(const QString& id, const Shared::Message& msg)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageFeed::removeMessage(const QString& id)
|
void Models::MessageFeed::removeMessage(const QString& id)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant MessageFeed::data(const QModelIndex& index, int role) const
|
QVariant Models::MessageFeed::data(const QModelIndex& index, int role) const
|
||||||
{
|
{
|
||||||
int i = index.row();
|
int i = index.row();
|
||||||
QVariant answer;
|
QVariant answer;
|
||||||
@ -90,7 +94,19 @@ QVariant MessageFeed::data(const QModelIndex& index, int role) const
|
|||||||
answer = msg->getBody();
|
answer = msg->getBody();
|
||||||
break;
|
break;
|
||||||
case Sender:
|
case Sender:
|
||||||
answer = msg->getFrom();
|
if (rosterItem->isRoom()) {
|
||||||
|
if (sentByMe(*msg)) {
|
||||||
|
answer = rosterItem->getDisplayedName();
|
||||||
|
} else {
|
||||||
|
answer = msg->getFromResource();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (sentByMe(*msg)) {
|
||||||
|
answer = rosterItem->getAccountName();
|
||||||
|
} else {
|
||||||
|
answer = rosterItem->getDisplayedName();
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case Date:
|
case Date:
|
||||||
answer = msg->getTime();
|
answer = msg->getTime();
|
||||||
@ -102,19 +118,29 @@ QVariant MessageFeed::data(const QModelIndex& index, int role) const
|
|||||||
answer = msg->getEdited();
|
answer = msg->getEdited();
|
||||||
break;
|
break;
|
||||||
case SentByMe:
|
case SentByMe:
|
||||||
answer = msg->getOutgoing();
|
answer = sentByMe(*msg);
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
break;
|
||||||
|
case Avatar: {
|
||||||
|
QString path;
|
||||||
|
if (sentByMe(*msg)) {
|
||||||
|
path = rosterItem->getAccountAvatarPath();
|
||||||
|
} else if (!rosterItem->isRoom()) {
|
||||||
|
if (rosterItem->getAvatarState() != Shared::Avatar::empty) {
|
||||||
|
path = rosterItem->getAvatarPath();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (role) {
|
const Room* room = static_cast<const Room*>(rosterItem);
|
||||||
case Qt::DisplayRole:
|
path = room->getParticipantIconPath(msg->getFromResource());
|
||||||
case Text:
|
}
|
||||||
answer = "loading...";
|
|
||||||
|
if (path.size() == 0) {
|
||||||
|
answer = Shared::iconPath("user", true);
|
||||||
|
} else {
|
||||||
|
answer = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
answer = "";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,31 +148,25 @@ QVariant MessageFeed::data(const QModelIndex& index, int role) const
|
|||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MessageFeed::rowCount(const QModelIndex& parent) const
|
int Models::MessageFeed::rowCount(const QModelIndex& parent) const
|
||||||
{
|
{
|
||||||
int count = storage.size();
|
return storage.size();
|
||||||
if (syncState == syncing) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int MessageFeed::unreadMessagesCount() const
|
unsigned int Models::MessageFeed::unreadMessagesCount() const
|
||||||
{
|
{
|
||||||
return storage.size(); //let's say they are all new for now =)
|
return storage.size(); //let's say they are all new for now =)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MessageFeed::canFetchMore(const QModelIndex& parent) const
|
bool Models::MessageFeed::canFetchMore(const QModelIndex& parent) const
|
||||||
{
|
{
|
||||||
return syncState == incomplete;
|
return syncState == incomplete;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageFeed::fetchMore(const QModelIndex& parent)
|
void Models::MessageFeed::fetchMore(const QModelIndex& parent)
|
||||||
{
|
{
|
||||||
if (syncState == incomplete) {
|
if (syncState == incomplete) {
|
||||||
beginInsertRows(QModelIndex(), storage.size(), storage.size());
|
emit requestStateChange(true);
|
||||||
syncState = syncing;
|
|
||||||
endInsertRows();
|
|
||||||
|
|
||||||
if (storage.size() == 0) {
|
if (storage.size() == 0) {
|
||||||
emit requestArchive("");
|
emit requestArchive("");
|
||||||
@ -156,13 +176,11 @@ void MessageFeed::fetchMore(const QModelIndex& parent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageFeed::responseArchive(const std::list<Shared::Message> list)
|
void Models::MessageFeed::responseArchive(const std::list<Shared::Message> list)
|
||||||
{
|
{
|
||||||
Storage::size_type size = storage.size();
|
Storage::size_type size = storage.size();
|
||||||
if (syncState == syncing) {
|
if (syncState == syncing) {
|
||||||
beginRemoveRows(QModelIndex(), size, size);
|
emit requestStateChange(false);
|
||||||
syncState = incomplete;
|
|
||||||
endRemoveRows();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
beginInsertRows(QModelIndex(), size, size + list.size() - 1);
|
beginInsertRows(QModelIndex(), size, size + list.size() - 1);
|
||||||
@ -173,7 +191,17 @@ void MessageFeed::responseArchive(const std::list<Shared::Message> list)
|
|||||||
endInsertRows();
|
endInsertRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
QHash<int, QByteArray> MessageFeed::roleNames() const
|
QHash<int, QByteArray> Models::MessageFeed::roleNames() const
|
||||||
{
|
{
|
||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Models::MessageFeed::sentByMe(const Shared::Message& msg) const
|
||||||
|
{
|
||||||
|
if (rosterItem->isRoom()) {
|
||||||
|
const Room* room = static_cast<const Room*>(rosterItem);
|
||||||
|
return room->getNick().toLower() == msg.getFromResource().toLower();
|
||||||
|
} else {
|
||||||
|
return msg.getOutgoing();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -29,13 +29,17 @@
|
|||||||
#include <boost/multi_index/mem_fun.hpp>
|
#include <boost/multi_index/mem_fun.hpp>
|
||||||
|
|
||||||
#include <shared/message.h>
|
#include <shared/message.h>
|
||||||
|
#include <shared/icons.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace Models {
|
||||||
|
class Element;
|
||||||
|
|
||||||
class MessageFeed : public QAbstractListModel
|
class MessageFeed : public QAbstractListModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
MessageFeed(QObject *parent = nullptr);
|
MessageFeed(const Element* rosterItem, QObject *parent = nullptr);
|
||||||
~MessageFeed();
|
~MessageFeed();
|
||||||
|
|
||||||
void addMessage(const Shared::Message& msg);
|
void addMessage(const Shared::Message& msg);
|
||||||
@ -55,6 +59,10 @@ public:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void requestArchive(const QString& before);
|
void requestArchive(const QString& before);
|
||||||
|
void requestStateChange(bool requesting);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool sentByMe(const Shared::Message& msg) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum MessageRoles {
|
enum MessageRoles {
|
||||||
@ -63,7 +71,8 @@ public:
|
|||||||
Date,
|
Date,
|
||||||
DeliveryState,
|
DeliveryState,
|
||||||
Correction,
|
Correction,
|
||||||
SentByMe
|
SentByMe,
|
||||||
|
Avatar
|
||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
enum SyncState {
|
enum SyncState {
|
||||||
@ -104,10 +113,11 @@ private:
|
|||||||
StorageById& indexById;
|
StorageById& indexById;
|
||||||
StorageByTime& indexByTime;
|
StorageByTime& indexByTime;
|
||||||
|
|
||||||
|
const Element* rosterItem;
|
||||||
SyncState syncState;
|
SyncState syncState;
|
||||||
|
|
||||||
static const QHash<int, QByteArray> roles;
|
static const QHash<int, QByteArray> roles;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MESSAGEFEED_H
|
#endif // MESSAGEFEED_H
|
||||||
|
@ -310,8 +310,13 @@ QString Models::Room::getParticipantIconPath(const QString& name) const
|
|||||||
{
|
{
|
||||||
std::map<QString, Models::Participant*>::const_iterator itr = participants.find(name);
|
std::map<QString, Models::Participant*>::const_iterator itr = participants.find(name);
|
||||||
if (itr == participants.end()) {
|
if (itr == participants.end()) {
|
||||||
|
std::map<QString, QString>::const_iterator eitr = exParticipantAvatars.find(name);
|
||||||
|
if (eitr != exParticipantAvatars.end()) {
|
||||||
|
return eitr->second;
|
||||||
|
} else {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return itr->second->getAvatarPath();
|
return itr->second->getAvatarPath();
|
||||||
}
|
}
|
||||||
|
@ -232,3 +232,8 @@ void FeedView::verticalScrollbarValueChanged(int value)
|
|||||||
|
|
||||||
QAbstractItemView::verticalScrollbarValueChanged(vo);
|
QAbstractItemView::verticalScrollbarValueChanged(vo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QFont FeedView::getFont() const
|
||||||
|
{
|
||||||
|
return viewOptions().font;
|
||||||
|
}
|
||||||
|
@ -43,6 +43,8 @@ public:
|
|||||||
void setSelection(const QRect & rect, QItemSelectionModel::SelectionFlags command) override;
|
void setSelection(const QRect & rect, QItemSelectionModel::SelectionFlags command) override;
|
||||||
QRegion visualRegionForSelection(const QItemSelection & selection) const override;
|
QRegion visualRegionForSelection(const QItemSelection & selection) const override;
|
||||||
|
|
||||||
|
QFont getFont() const;
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void rowsInserted(const QModelIndex & parent, int start, int end) override;
|
void rowsInserted(const QModelIndex & parent, int start, int end) override;
|
||||||
void verticalScrollbarValueChanged(int value) override;
|
void verticalScrollbarValueChanged(int value) override;
|
||||||
|
130
ui/utils/messagedelegate.cpp
Normal file
130
ui/utils/messagedelegate.cpp
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
/*
|
||||||
|
* Squawk messenger.
|
||||||
|
* Copyright (C) 2019 Yury Gubich <blue@macaw.me>
|
||||||
|
*
|
||||||
|
* 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 3 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. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QApplication>
|
||||||
|
#include "messagedelegate.h"
|
||||||
|
#include "ui/models/messagefeed.h"
|
||||||
|
|
||||||
|
constexpr int avatarHeight = 50;
|
||||||
|
constexpr int margin = 6;
|
||||||
|
|
||||||
|
MessageDelegate::MessageDelegate(QObject* parent):
|
||||||
|
QStyledItemDelegate(parent),
|
||||||
|
bodyFont(),
|
||||||
|
nickFont(),
|
||||||
|
dateFont(),
|
||||||
|
bodyMetrics(bodyFont),
|
||||||
|
nickMetrics(nickFont),
|
||||||
|
dateMetrics(dateFont)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageDelegate::~MessageDelegate()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||||
|
{
|
||||||
|
bool sentByMe = false;
|
||||||
|
QVariant sbm = index.data(Models::MessageFeed::SentByMe);
|
||||||
|
if (sbm.isValid()) {
|
||||||
|
sentByMe = sbm.toBool();
|
||||||
|
}
|
||||||
|
painter->save();
|
||||||
|
painter->setRenderHint(QPainter::Antialiasing, true);
|
||||||
|
QIcon icon(index.data(Models::MessageFeed::Avatar).toString());
|
||||||
|
|
||||||
|
if (sentByMe) {
|
||||||
|
painter->drawPixmap(option.rect.width() - avatarHeight - margin, option.rect.y() + margin / 2, icon.pixmap(avatarHeight, avatarHeight));
|
||||||
|
} else {
|
||||||
|
painter->drawPixmap(margin, option.rect.y() + margin / 2, icon.pixmap(avatarHeight, avatarHeight));
|
||||||
|
}
|
||||||
|
|
||||||
|
QStyleOptionViewItem opt = option;
|
||||||
|
QRect messageRect = option.rect.adjusted(margin, margin / 2, -(avatarHeight + 2 * margin), -margin / 2);
|
||||||
|
if (!sentByMe) {
|
||||||
|
opt.displayAlignment = Qt::AlignLeft | Qt::AlignTop;
|
||||||
|
messageRect.adjust(avatarHeight + margin, 0, avatarHeight + margin, 0);
|
||||||
|
} else {
|
||||||
|
opt.displayAlignment = Qt::AlignRight | Qt::AlignTop;
|
||||||
|
}
|
||||||
|
opt.rect = messageRect;
|
||||||
|
|
||||||
|
QRect rect;
|
||||||
|
painter->setFont(nickFont);
|
||||||
|
painter->drawText(opt.rect, opt.displayAlignment, index.data(Models::MessageFeed::Sender).toString(), &rect);
|
||||||
|
|
||||||
|
opt.rect.adjust(0, rect.height(), 0, 0);
|
||||||
|
painter->setFont(bodyFont);
|
||||||
|
painter->drawText(opt.rect, opt.displayAlignment | Qt::TextWordWrap, index.data(Models::MessageFeed::Text).toString(), &rect);
|
||||||
|
|
||||||
|
opt.rect.adjust(0, rect.height(), 0, 0);
|
||||||
|
painter->setFont(dateFont);
|
||||||
|
QColor q = painter->pen().color();
|
||||||
|
q.setAlpha(180);
|
||||||
|
painter->setPen(q);
|
||||||
|
painter->drawText(opt.rect, opt.displayAlignment, index.data(Models::MessageFeed::Date).toDateTime().toLocalTime().toString(), &rect);
|
||||||
|
|
||||||
|
painter->restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize MessageDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||||
|
{
|
||||||
|
QRect messageRect = option.rect.adjusted(0, margin / 2, -(avatarHeight + 3 * margin), -margin);
|
||||||
|
QStyleOptionViewItem opt = option;
|
||||||
|
opt.rect = messageRect;
|
||||||
|
QSize messageSize = bodyMetrics.boundingRect(messageRect, Qt::TextWordWrap, index.data(Models::MessageFeed::Text).toString()).size();
|
||||||
|
|
||||||
|
messageSize.rheight() += nickMetrics.lineSpacing();
|
||||||
|
messageSize.rheight() += dateMetrics.height();
|
||||||
|
|
||||||
|
if (messageSize.height() < avatarHeight) {
|
||||||
|
messageSize.setHeight(avatarHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
messageSize.rheight() += margin;
|
||||||
|
|
||||||
|
return messageSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageDelegate::initializeFonts(const QFont& font)
|
||||||
|
{
|
||||||
|
bodyFont = font;
|
||||||
|
nickFont = font;
|
||||||
|
dateFont = font;
|
||||||
|
|
||||||
|
nickFont.setBold(true);
|
||||||
|
dateFont.setItalic(true);
|
||||||
|
float dps = dateFont.pointSizeF();
|
||||||
|
if (dps != -1) {
|
||||||
|
dateFont.setPointSizeF(dps * 0.7);
|
||||||
|
} else {
|
||||||
|
dateFont.setPointSize(dateFont.pointSize() - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
bodyMetrics = QFontMetrics(bodyFont);
|
||||||
|
nickMetrics = QFontMetrics(nickFont);
|
||||||
|
dateMetrics = QFontMetrics(dateFont);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// void MessageDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
|
||||||
|
// {
|
||||||
|
//
|
||||||
|
// }
|
50
ui/utils/messagedelegate.h
Normal file
50
ui/utils/messagedelegate.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Squawk messenger.
|
||||||
|
* Copyright (C) 2019 Yury Gubich <blue@macaw.me>
|
||||||
|
*
|
||||||
|
* 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 3 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. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MESSAGEDELEGATE_H
|
||||||
|
#define MESSAGEDELEGATE_H
|
||||||
|
|
||||||
|
#include <QStyledItemDelegate>
|
||||||
|
#include <QFont>
|
||||||
|
#include <QFontMetrics>
|
||||||
|
|
||||||
|
#include "shared/icons.h"
|
||||||
|
|
||||||
|
class MessageDelegate : public QStyledItemDelegate
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
MessageDelegate(QObject *parent = nullptr);
|
||||||
|
~MessageDelegate();
|
||||||
|
|
||||||
|
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||||
|
QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||||
|
//void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const override;
|
||||||
|
|
||||||
|
void initializeFonts(const QFont& font);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QFont bodyFont;
|
||||||
|
QFont nickFont;
|
||||||
|
QFont dateFont;
|
||||||
|
QFontMetrics bodyMetrics;
|
||||||
|
QFontMetrics nickMetrics;
|
||||||
|
QFontMetrics dateMetrics;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MESSAGEDELEGATE_H
|
@ -46,6 +46,7 @@ Conversation::Conversation(bool muc, Models::Account* acc, Models::Element* el,
|
|||||||
overlay(new QWidget()),
|
overlay(new QWidget()),
|
||||||
filesToAttach(),
|
filesToAttach(),
|
||||||
feed(new FeedView()),
|
feed(new FeedView()),
|
||||||
|
delegate(new MessageDelegate()),
|
||||||
scroll(down),
|
scroll(down),
|
||||||
manualSliderChange(false),
|
manualSliderChange(false),
|
||||||
requestingHistory(false),
|
requestingHistory(false),
|
||||||
@ -54,6 +55,8 @@ Conversation::Conversation(bool muc, Models::Account* acc, Models::Element* el,
|
|||||||
{
|
{
|
||||||
m_ui->setupUi(this);
|
m_ui->setupUi(this);
|
||||||
|
|
||||||
|
feed->setItemDelegate(delegate);
|
||||||
|
delegate->initializeFonts(feed->getFont());
|
||||||
feed->setModel(el->feed);
|
feed->setModel(el->feed);
|
||||||
m_ui->widget->layout()->addWidget(feed);
|
m_ui->widget->layout()->addWidget(feed);
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "ui/utils/flowlayout.h"
|
#include "ui/utils/flowlayout.h"
|
||||||
#include "ui/utils/badge.h"
|
#include "ui/utils/badge.h"
|
||||||
#include "ui/utils/feedview.h"
|
#include "ui/utils/feedview.h"
|
||||||
|
#include "ui/utils/messagedelegate.h"
|
||||||
#include "shared/icons.h"
|
#include "shared/icons.h"
|
||||||
#include "shared/utils.h"
|
#include "shared/utils.h"
|
||||||
|
|
||||||
@ -147,6 +148,7 @@ protected:
|
|||||||
QWidget* overlay;
|
QWidget* overlay;
|
||||||
W::Order<Badge*, Badge::Comparator> filesToAttach;
|
W::Order<Badge*, Badge::Comparator> filesToAttach;
|
||||||
FeedView* feed;
|
FeedView* feed;
|
||||||
|
MessageDelegate* delegate;
|
||||||
Scroll scroll;
|
Scroll scroll;
|
||||||
bool manualSliderChange;
|
bool manualSliderChange;
|
||||||
bool requestingHistory;
|
bool requestingHistory;
|
||||||
|
Loading…
Reference in New Issue
Block a user