0.2.0 finalization

This commit is contained in:
Blue 2022-01-09 17:32:23 +03:00
parent 8a2658e4fc
commit 4d3ba6b11f
Signed by untrusted user: blue
GPG Key ID: 9B203B252A63EE38
12 changed files with 194 additions and 179 deletions

View File

@ -1,19 +1,28 @@
# Changelog
## Squawk 0.2.0 (Unreleased)
## Squawk 0.2.0 (Jan 10, 2022)
### Bug fixes
- carbon copies switches on again after reconnection
- requesting the history of the current chat after reconnection
- global availability (in drop down list) gets restored after reconnection
- status icon in active chat changes when presence of the pen pal changes
- infinite progress when open the dialogue with something that has no history to show
- fallback icons for buttons, when no supported theme is installed (shunf4)
- better handling messages with no id (shunf4)
- removed dependency: uuid, now it's on Qt (shunf4)
- better requesting latest history (shunf4)
### Improvements
- slightly reduced the traffic on the startup by not requesting history of all MUCs
- completely rewritten message feed, now it works way faster
- completely rewritten message feed, now it works way faster and looks cooler
- OPTIONAL RUNTIME dependency: "KIO Widgets" that is supposed to allow you to open a file in your default file manager
- show in folder now is supposed to try it's best to show file in folder, even you don't have KIO installed
- once uploaded local files don't get second time uploaded - the remote URL is reused
- way better compilation time (vae)
### New features
- pasting images from clipboard to attachment (shunf4)
- possible compilation for windows and macOS (shunf4)
## Squawk 0.1.5 (Jul 29, 2020)
### Bug fixes

View File

@ -4,13 +4,13 @@
[![AUR version](https://img.shields.io/aur/version/squawk?style=flat-square)](https://aur.archlinux.org/packages/squawk/)
[![Liberapay patrons](https://img.shields.io/liberapay/patrons/macaw.me?logo=liberapay&style=flat-square)](https://liberapay.com/macaw.me)
![Squawk screenshot](https://macaw.me/images/squawk/0.1.4.png)
![Squawk screenshot](https://macaw.me/images/squawk/0.2.0.png)
### Prerequisites
- QT 5.12 *(lower versions might work but it wasn't tested)*
- lmdb
- CMake 3.0 or higher
- CMake 3.3 or higher
- qxmpp 1.1.0 or higher
- KDE Frameworks: kwallet (optional)
- KDE Frameworks: KIO (optional)

View File

@ -54,7 +54,7 @@ int main(int argc, char *argv[])
#endif
QApplication::setApplicationName("squawk");
QApplication::setApplicationDisplayName("Squawk");
QApplication::setApplicationVersion("0.1.5");
QApplication::setApplicationVersion("0.2.0");
QTranslator qtTranslator;
qtTranslator.load("qt_" + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath));

View File

@ -1,6 +1,6 @@
# Maintainer: Yury Gubich <blue@macaw.me>
pkgname=squawk
pkgver=0.1.5
pkgver=0.2.0
pkgrel=1
pkgdesc="An XMPP desktop messenger, written on pure c++ (qt)"
arch=('i686' 'x86_64')
@ -11,7 +11,7 @@ makedepends=('cmake>=3.3' 'imagemagick' 'qt5-tools')
optdepends=('kwallet: secure password storage (requires rebuild)')
source=("$pkgname-$pkgver.tar.gz")
sha256sums=('e1a4c88be9f0481d2aa21078faf42fd0e9d66b490b6d8af82827d441cb58df25')
sha256sums=('8e93d3dbe1fc35cfecb7783af409c6a264244d11609b2241d4fe77d43d068419')
build() {
cd "$srcdir/squawk"
cmake . -D CMAKE_INSTALL_PREFIX=/usr -D CMAKE_BUILD_TYPE=Release

View File

@ -144,7 +144,7 @@ Shared::Global::FileInfo Shared::Global::getFileInfo(const QString& path)
size = defaultIconFileInfoHeight;
}
itr = instance->fileCache.insert(std::make_pair(path, FileInfo({info.fileName(), size, type, p}))).first;
itr = instance->fileCache.insert(std::make_pair(path, FileInfo({info.absoluteFilePath(), info.fileName(), size, type, p}))).first;
}
return itr->second;

View File

@ -55,6 +55,7 @@ namespace Shared {
animation
};
QString path;
QString name;
QSize size;
QMimeType mime;

View File

@ -43,6 +43,7 @@ FeedView::FeedView(QWidget* parent):
QAbstractItemView(parent),
hints(),
vo(0),
elementMargin(0),
specialDelegate(false),
specialModel(false),
clearWidgetsMode(false),
@ -106,7 +107,7 @@ QRect FeedView::visualRect(const QModelIndex& index) const
} else {
const Hint& hint = hints.at(row);
const QWidget* vp = viewport();
return QRect(0, vp->height() - hint.height - hint.offset + vo, vp->width(), hint.height);
return QRect(hint.x, vp->height() - hint.height - hint.offset + vo, hint.width, hint.height);
}
}
@ -198,7 +199,7 @@ void FeedView::updateGeometries()
option.rect.setWidth(layoutBounds.width());
hints.clear();
uint32_t previousOffset = 0;
uint32_t previousOffset = elementMargin;
QDateTime lastDate;
for (int i = 0, size = m->rowCount(); i < size; ++i) {
QModelIndex index = m->index(i, 0, rootIndex());
@ -206,19 +207,32 @@ void FeedView::updateGeometries()
if (i > 0) {
if (currentDate.daysTo(lastDate) > 0) {
previousOffset += dividerMetrics.height() + dateDeviderMargin * 2;
} else {
previousOffset += elementMargin;
}
}
lastDate = currentDate;
int height = itemDelegate(index)->sizeHint(option, index).height();
QSize messageSize = itemDelegate(index)->sizeHint(option, index);
uint32_t offsetX(0);
if (specialDelegate) {
if (index.data(Models::MessageFeed::SentByMe).toBool()) {
offsetX = layoutBounds.width() - messageSize.width() - MessageDelegate::avatarHeight - MessageDelegate::margin * 2;
} else {
offsetX = MessageDelegate::avatarHeight + MessageDelegate::margin * 2;
}
}
hints.emplace_back(Hint({
false,
previousOffset,
static_cast<uint32_t>(height)
static_cast<uint32_t>(messageSize.height()),
static_cast<uint32_t>(messageSize.width()),
offsetX
}));
previousOffset += height;
previousOffset += messageSize.height();
}
int totalHeight = previousOffset - layoutBounds.height();
int totalHeight = previousOffset - layoutBounds.height() + dividerMetrics.height() + dateDeviderMargin * 2;
if (modelState != Models::MessageFeed::complete) {
totalHeight += progressSize;
}
@ -240,7 +254,7 @@ void FeedView::updateGeometries()
bool FeedView::tryToCalculateGeometriesWithNoScrollbars(const QStyleOptionViewItem& option, const QAbstractItemModel* m, uint32_t totalHeight)
{
uint32_t previousOffset = 0;
uint32_t previousOffset = elementMargin;
bool success = true;
QDateTime lastDate;
for (int i = 0, size = m->rowCount(); i < size; ++i) {
@ -249,21 +263,39 @@ bool FeedView::tryToCalculateGeometriesWithNoScrollbars(const QStyleOptionViewIt
if (i > 0) {
if (currentDate.daysTo(lastDate) > 0) {
previousOffset += dateDeviderMargin * 2 + dividerMetrics.height();
} else {
previousOffset += elementMargin;
}
}
lastDate = currentDate;
int height = itemDelegate(index)->sizeHint(option, index).height();
QSize messageSize = itemDelegate(index)->sizeHint(option, index);
if (previousOffset + height > totalHeight) {
if (previousOffset + messageSize.height() + elementMargin > totalHeight) {
success = false;
break;
}
uint32_t offsetX(0);
if (specialDelegate) {
if (index.data(Models::MessageFeed::SentByMe).toBool()) {
offsetX = option.rect.width() - messageSize.width() - MessageDelegate::avatarHeight - MessageDelegate::margin * 2;
} else {
offsetX = MessageDelegate::avatarHeight + MessageDelegate::margin * 2;
}
}
hints.emplace_back(Hint({
false,
previousOffset,
static_cast<uint32_t>(height)
static_cast<uint32_t>(messageSize.height()),
static_cast<uint32_t>(messageSize.width()),
offsetX
}));
previousOffset += height;
previousOffset += messageSize.height();
}
previousOffset += dateDeviderMargin * 2 + dividerMetrics.height();
if (previousOffset > totalHeight) {
success = false;
}
return success;
@ -336,7 +368,7 @@ void FeedView::paintEvent(QPaintEvent* event)
lastDate = currentDate;
}
if (!lastDate.isNull() && inZone) { //if after drawing all messages there is still space
drawDateDevider(option.rect.bottom(), lastDate, painter);
drawDateDevider(option.rect.top() - dateDeviderMargin * 2 - dividerMetrics.height(), lastDate, painter);
}
if (clearWidgetsMode && specialDelegate) {
@ -423,10 +455,12 @@ void FeedView::setItemDelegate(QAbstractItemDelegate* delegate)
MessageDelegate* del = dynamic_cast<MessageDelegate*>(delegate);
if (del) {
specialDelegate = true;
elementMargin = MessageDelegate::margin;
connect(del, &MessageDelegate::buttonPushed, this, &FeedView::onMessageButtonPushed);
connect(del, &MessageDelegate::invalidPath, this, &FeedView::onMessageInvalidPath);
} else {
specialDelegate = false;
elementMargin = 0;
}
}

View File

@ -80,9 +80,12 @@ private:
bool dirty;
uint32_t offset;
uint32_t height;
uint32_t width;
uint32_t x;
};
std::deque<Hint> hints;
int vo;
int elementMargin;
bool specialDelegate;
bool specialModel;
bool clearWidgetsMode;

View File

@ -26,8 +26,8 @@
#include "messagedelegate.h"
#include "messagefeed.h"
constexpr int avatarHeight = 50;
constexpr int margin = 6;
int MessageDelegate::avatarHeight(50);
int MessageDelegate::margin(6);
constexpr int textMargin = 2;
constexpr int statusIconSize = 16;
constexpr float nickFontMultiplier = 1.1;
@ -45,6 +45,7 @@ MessageDelegate::MessageDelegate(QObject* parent):
nickMetrics(nickFont),
dateMetrics(dateFont),
buttonHeight(0),
buttonWidth(0),
barHeight(0),
buttons(new std::map<QString, FeedButton*>()),
bars(new std::map<QString, QProgressBar*>()),
@ -55,8 +56,9 @@ MessageDelegate::MessageDelegate(QObject* parent):
idsToKeep(new std::set<QString>()),
clearingWidgets(false)
{
QPushButton btn;
QPushButton btn(QCoreApplication::translate("MessageLine", "Download"));
buttonHeight = btn.sizeHint().height();
buttonWidth = btn.sizeHint().width();
QProgressBar bar;
barHeight = bar.sizeHint().height();
@ -107,141 +109,79 @@ void MessageDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optio
painter->save();
painter->setRenderHint(QPainter::Antialiasing, true);
// if (option.state & QStyle::State_MouseOver) {
// painter->fillRect(option.rect, option.palette.brush(QPalette::Inactive, QPalette::Highlight));
// }
paintBubble(data, painter, option);
bool ntds = needToDrawSender(index, data);
if (ntds || option.rect.y() < 1) {
paintAvatar(data, index, option, painter);
}
QStyleOptionViewItem opt = option;
QRect messageRect = option.rect.adjusted(margin, margin / 2, -(avatarHeight + 2 * margin), -margin / 2);
opt.rect = option.rect.adjusted(bubbleMargin, bubbleMargin, -bubbleMargin, -bubbleMargin / 2);
if (!data.sentByMe) {
opt.displayAlignment = Qt::AlignLeft | Qt::AlignTop;
messageRect.adjust(avatarHeight + margin, 0, avatarHeight + margin, 0);
} else {
opt.displayAlignment = Qt::AlignRight | Qt::AlignTop;
}
QPoint bubbleBegin = messageRect.topLeft();
messageRect.adjust(bubbleMargin, bubbleMargin, -bubbleMargin, -bubbleMargin / 2);
opt.rect = messageRect;
QSize messageSize(0, 0);
QSize bodySize(0, 0);
if (data.text.size() > 0) {
messageSize = bodyMetrics.boundingRect(messageRect, Qt::TextWordWrap, data.text).size();
bodySize = messageSize;
}
messageSize.rheight() += dateMetrics.height();
QString dateString = data.date.toLocalTime().toString("hh:mm");
if (messageSize.width() < opt.rect.width()) {
if (ntds) {
QSize senderSize = nickMetrics.boundingRect(messageRect, 0, data.sender).size();
if (senderSize.width() > messageSize.width()) {
messageSize.setWidth(senderSize.width());
}
}
QSize dateSize = dateMetrics.boundingRect(messageRect, 0, dateString).size();
int addition = 0;
if (data.correction.corrected) {
addition += margin + statusIconSize;
}
if (data.sentByMe) {
addition += margin + statusIconSize;
}
if (dateSize.width() + addition > messageSize.width()) {
messageSize.setWidth(dateSize.width() + addition);
}
} else {
messageSize.setWidth(opt.rect.width());
}
painter->save();
int storedY = opt.rect.y();
if (ntds) {
opt.rect.adjust(0, nickMetrics.lineSpacing() + textMargin, 0, 0);
}
int attWidth(0);
switch (data.attach.state) {
case Models::none:
clearHelperWidget(data); //i can't imagine the situation where it's gonna be needed
break; //but it's a possible performance problem
case Models::uploading:
attWidth = std::max(paintPreview(data, painter, opt), attWidth);
[[fallthrough]];
case Models::downloading:
messageSize.setWidth(opt.rect.width());
messageSize.rheight() += barHeight + textMargin + opt.rect.y() - storedY;
paintBubble(data, painter, messageSize, opt, bubbleBegin);
attWidth = std::max(paintBar(getBar(data), painter, data.sentByMe, opt), attWidth);
break;
case Models::remote:
attWidth = std::max(paintButton(getButton(data), painter, data.sentByMe, opt), attWidth);
break;
case Models::ready:
case Models::local:
clearHelperWidget(data);
attWidth = std::max(paintPreview(data, painter, opt), attWidth);
break;
case Models::errorDownload: {
attWidth = std::max(paintButton(getButton(data), painter, data.sentByMe, opt), attWidth);
attWidth = std::max(paintComment(data, painter, opt), attWidth);
}
break;
case Models::errorUpload:{
clearHelperWidget(data);
attWidth = std::max(paintPreview(data, painter, opt), attWidth);
attWidth = std::max(paintComment(data, painter, opt), attWidth);
}
break;
}
painter->restore();
if (data.attach.state != Models::uploading && data.attach.state != Models::downloading) {
messageSize.rheight() += opt.rect.y() - storedY;
messageSize.setWidth(std::max(attWidth, messageSize.width()));
paintBubble(data, painter, messageSize, opt, bubbleBegin);
bodySize = bodyMetrics.boundingRect(opt.rect, Qt::TextWordWrap, data.text).size();
}
QRect rect;
if (ntds) {
painter->setFont(nickFont);
int storedY2 = opt.rect.y();
opt.rect.setY(storedY);
painter->drawText(opt.rect, opt.displayAlignment, data.sender, &rect);
opt.rect.setY(storedY2);
opt.rect.adjust(0, nickMetrics.lineSpacing() + textMargin, 0, 0);
}
int messageLeft = INT16_MAX;
int messageRight = opt.rect.x() + messageSize.width();
painter->save();
switch (data.attach.state) {
case Models::none:
clearHelperWidget(data); //i can't imagine the situation where it's gonna be needed
break; //but it's a possible performance problem
case Models::uploading:
paintPreview(data, painter, opt);
[[fallthrough]];
case Models::downloading:
paintBar(getBar(data), painter, data.sentByMe, opt);
break;
case Models::remote:
paintButton(getButton(data), painter, data.sentByMe, opt);
break;
case Models::ready:
case Models::local:
clearHelperWidget(data);
paintPreview(data, painter, opt);
break;
case Models::errorDownload: {
paintButton(getButton(data), painter, data.sentByMe, opt);
paintComment(data, painter, opt);
}
break;
case Models::errorUpload:{
clearHelperWidget(data);
paintPreview(data, painter, opt);
paintComment(data, painter, opt);
}
break;
}
painter->restore();
QWidget* vp = static_cast<QWidget*>(painter->device());
if (data.text.size() > 0) {
QLabel* body = getBody(data);
body->setParent(vp);
body->setMaximumWidth(bodySize.width());
body->setMinimumWidth(bodySize.width());
body->setMinimumHeight(bodySize.height());
body->setMaximumHeight(bodySize.height());
body->setAlignment(opt.displayAlignment);
messageLeft = opt.rect.x();
if (data.sentByMe) {
messageLeft = opt.rect.topRight().x() - bodySize.width();
}
body->move(messageLeft, opt.rect.y());
body->setMinimumSize(bodySize);
body->setMaximumSize(bodySize);
body->move(opt.rect.left(), opt.rect.y());
body->show();
opt.rect.adjust(0, bodySize.height() + textMargin, 0, 0);
}
painter->setFont(dateFont);
QColor q = painter->pen().color();
QString dateString = data.date.toLocalTime().toString("hh:mm");
q.setAlpha(180);
painter->setPen(q);
painter->drawText(opt.rect, opt.displayAlignment, dateString, &rect);
@ -250,7 +190,7 @@ void MessageDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optio
QLabel* statusIcon = getStatusIcon(data);
statusIcon->setParent(vp);
statusIcon->move(opt.rect.topRight().x() - messageSize.width(), currentY);
statusIcon->move(opt.rect.left(), currentY);
statusIcon->show();
opt.rect.adjust(0, statusIconSize + textMargin, 0, 0);
@ -261,9 +201,9 @@ void MessageDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optio
pencilIcon->setParent(vp);
if (data.sentByMe) {
pencilIcon->move(opt.rect.topRight().x() - messageSize.width() + statusIconSize + margin, currentY);
pencilIcon->move(opt.rect.left() + statusIconSize + margin, currentY);
} else {
pencilIcon->move(messageRight - statusIconSize - margin, currentY);
pencilIcon->move(opt.rect.right() - statusIconSize - margin, currentY);
}
pencilIcon->show();
} else {
@ -281,19 +221,16 @@ void MessageDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optio
}
}
void MessageDelegate::paintBubble(const Models::FeedItem& data, QPainter* painter, const QSize& messageSize, QStyleOptionViewItem& option, QPoint bubbleBegin) const
void MessageDelegate::paintBubble(const Models::FeedItem& data, QPainter* painter, const QStyleOptionViewItem& option) const
{
painter->save();
if (data.sentByMe) {
bubbleBegin.setX(option.rect.topRight().x() - messageSize.width() - bubbleMargin);
painter->setBrush(option.palette.brush(QPalette::Inactive, QPalette::Highlight));
} else {
painter->setBrush(option.palette.brush(QPalette::Window));
}
QSize bubbleAddition(2 * bubbleMargin, 1.5 * bubbleMargin);
QRect bubble(bubbleBegin, messageSize + bubbleAddition);
painter->setPen(Qt::NoPen);
painter->drawRoundedRect(bubble, bubbleBorderRadius, bubbleBorderRadius);
painter->drawRoundedRect(option.rect, bubbleBorderRadius, bubbleBorderRadius);
painter->restore();
}
@ -330,7 +267,7 @@ void MessageDelegate::paintAvatar(const Models::FeedItem& data, const QModelInde
int ax;
if (data.sentByMe) {
ax = option.rect.width() - avatarHeight - margin;
ax = option.rect.x() + option.rect.width() + margin;
} else {
ax = margin;
}
@ -381,36 +318,51 @@ QSize MessageDelegate::sizeHint(const QStyleOptionViewItem& option, const QModel
[[fallthrough]];
case Models::downloading:
messageSize.rheight() += barHeight + textMargin;
messageSize.setWidth(messageRect.width());
break;
case Models::remote:
messageSize.rheight() += buttonHeight + textMargin;
messageSize.setWidth(std::max(messageSize.width(), buttonWidth));
break;
case Models::ready:
case Models::local:
messageSize.rheight() += Preview::calculateAttachSize(data.attach.localPath, messageRect).height() + textMargin;
case Models::local: {
QSize aSize = Preview::calculateAttachSize(data.attach.localPath, messageRect);
messageSize.rheight() += aSize.height() + textMargin;
messageSize.setWidth(std::max(messageSize.width(), aSize.width()));
}
break;
case Models::errorDownload:
messageSize.rheight() += buttonHeight + textMargin;
messageSize.rheight() += dateMetrics.boundingRect(messageRect, Qt::TextWordWrap, data.attach.error).size().height() + textMargin;
case Models::errorDownload: {
QSize commentSize = dateMetrics.boundingRect(messageRect, Qt::TextWordWrap, data.attach.error).size();
messageSize.rheight() += commentSize.height() + buttonHeight + textMargin * 2;
messageSize.setWidth(std::max(messageSize.width(), std::max(commentSize.width(), buttonWidth)));
}
break;
case Models::errorUpload:
messageSize.rheight() += Preview::calculateAttachSize(data.attach.localPath, messageRect).height() + textMargin;
messageSize.rheight() += dateMetrics.boundingRect(messageRect, Qt::TextWordWrap, data.attach.error).size().height() + textMargin;
case Models::errorUpload: {
QSize aSize = Preview::calculateAttachSize(data.attach.localPath, messageRect);
QSize commentSize = dateMetrics.boundingRect(messageRect, Qt::TextWordWrap, data.attach.error).size();
messageSize.rheight() += aSize.height() + commentSize.height() + textMargin * 2;
messageSize.setWidth(std::max(messageSize.width(), std::max(commentSize.width(), aSize.width())));
}
break;
}
if (needToDrawSender(index, data)) {
messageSize.rheight() += nickMetrics.lineSpacing() + textMargin;
QSize senderSize = nickMetrics.boundingRect(messageRect, 0, data.sender).size();
messageSize.rheight() += senderSize.height() + textMargin;
messageSize.setWidth(std::max(senderSize.width(), messageSize.width()));
}
messageSize.rheight() += bubbleMargin + bubbleMargin / 2;
messageSize.rheight() += dateMetrics.height() > statusIconSize ? dateMetrics.height() : statusIconSize;
QString dateString = data.date.toLocalTime().toString("hh:mm");
QSize dateSize = dateMetrics.boundingRect(messageRect, 0, dateString).size();
messageSize.rheight() += bubbleMargin * 1.5;
messageSize.rheight() += dateSize.height() > statusIconSize ? dateSize.height() : statusIconSize;
// if (messageSize.height() < avatarHeight) {
// messageSize.setHeight(avatarHeight);
// }
messageSize.rheight() += margin;
int statusWidth = dateSize.width() + statusIconSize + margin;
if (data.correction.corrected) {
statusWidth += statusIconSize + margin;
}
messageSize.setWidth(std::max(statusWidth, messageSize.width()));
messageSize.rwidth() += 2 * bubbleMargin;
return messageSize;
}
@ -508,7 +460,7 @@ int MessageDelegate::paintPreview(const Models::FeedItem& data, QPainter* painte
preview->actualize(data.attach.localPath, size, option.rect.topLeft());
} else {
QWidget* vp = static_cast<QWidget*>(painter->device());
preview = new Preview(data.attach.localPath, size, option.rect.topLeft(), data.sentByMe, vp);
preview = new Preview(data.attach.localPath, size, option.rect.topLeft(), vp);
previews->insert(std::make_pair(data.id, preview));
}

View File

@ -56,6 +56,9 @@ public:
void endClearWidgets();
void beginClearWidgets();
static int avatarHeight;
static int margin;
signals:
void buttonPushed(const QString& messageId) const;
void invalidPath(const QString& messageId) const;
@ -66,7 +69,7 @@ protected:
int paintPreview(const Models::FeedItem& data, QPainter* painter, QStyleOptionViewItem& option) const;
int paintComment(const Models::FeedItem& data, QPainter* painter, QStyleOptionViewItem& option) const;
void paintAvatar(const Models::FeedItem& data, const QModelIndex& index, const QStyleOptionViewItem& option, QPainter* painter) const;
void paintBubble(const Models::FeedItem& data, QPainter* painter, const QSize& messageSize, QStyleOptionViewItem& option, QPoint bubbleBegin) const;
void paintBubble(const Models::FeedItem& data, QPainter* painter, const QStyleOptionViewItem& option) const;
QPushButton* getButton(const Models::FeedItem& data) const;
QProgressBar* getBar(const Models::FeedItem& data) const;
QLabel* getStatusIcon(const Models::FeedItem& data) const;
@ -94,6 +97,7 @@ private:
QFontMetrics dateMetrics;
int buttonHeight;
int buttonWidth;
int barHeight;
std::map<QString, FeedButton*>* buttons;

View File

@ -25,9 +25,8 @@ constexpr int maxAttachmentHeight = 500;
QFont Preview::font;
QFontMetrics Preview::metrics(Preview::font);
Preview::Preview(const QString& pPath, const QSize& pMaxSize, const QPoint& pos, bool pRight, QWidget* pParent):
Preview::Preview(const QString& pPath, const QSize& pMaxSize, const QPoint& pos, QWidget* pParent):
info(Shared::Global::getFileInfo(pPath)),
path(pPath),
maxSize(pMaxSize),
actualSize(constrainAttachSize(info.size, maxSize)),
cachedLabelSize(0, 0),
@ -37,8 +36,7 @@ Preview::Preview(const QString& pPath, const QSize& pMaxSize, const QPoint& pos,
parent(pParent),
movie(0),
fileReachable(true),
actualPreview(false),
right(pRight)
actualPreview(false)
{
initializeElements();
@ -104,9 +102,6 @@ void Preview::actualize(const QString& newPath, const QSize& newSize, const QPoi
}
} else if (maxSizeChanged) {
applyNewMaxSize();
if (right) {
positionChanged = true;
}
}
if (positionChanged || !actualPreview) {
positionElements();
@ -135,9 +130,6 @@ void Preview::setSize(const QSize& newSize)
}
if (maxSizeChanged || !actualPreview) {
applyNewMaxSize();
if (right) {
positionElements();
}
}
}
}
@ -146,7 +138,7 @@ void Preview::applyNewSize()
{
switch (info.preview) {
case Shared::Global::FileInfo::Preview::picture: {
QImageReader img(path);
QImageReader img(info.path);
if (!img.canRead()) {
delete widget;
fileReachable = false;
@ -216,9 +208,8 @@ void Preview::setPosition(const QPoint& newPoint)
bool Preview::setPath(const QString& newPath)
{
if (path != newPath) {
path = newPath;
info = Shared::Global::getFileInfo(path);
if (info.path != newPath) {
info = Shared::Global::getFileInfo(newPath);
actualSize = constrainAttachSize(info.size, maxSize);
clean();
initializeElements();
@ -235,7 +226,7 @@ void Preview::initializeElements()
{
switch (info.preview) {
case Shared::Global::FileInfo::Preview::picture: {
QImageReader img(path);
QImageReader img(info.path);
if (!img.canRead()) {
fileReachable = false;
} else {
@ -248,7 +239,7 @@ void Preview::initializeElements()
}
break;
case Shared::Global::FileInfo::Preview::animation:{
movie = new QMovie(path);
movie = new QMovie(info.path);
QObject::connect(movie, &QMovie::error,
std::bind(&Preview::handleQMovieError, this, std::placeholders::_1)
);
@ -289,9 +280,6 @@ void Preview::initializeElements()
void Preview::positionElements()
{
int start = position.x();
if (right) {
start += maxSize.width() - size().width();
}
widget->move(start, position.y());
if (!actualPreview) {
int x = start + actualSize.width() + margin;
@ -300,11 +288,36 @@ void Preview::positionElements()
}
}
bool Preview::canVisualize(const Shared::Global::FileInfo& info)
{
switch (info.preview) {
case Shared::Global::FileInfo::Preview::picture: {
QImageReader img(info.path);
return img.canRead();
}
break;
case Shared::Global::FileInfo::Preview::animation:{
QMovie movie(info.path);
return movie.isValid();
}
break;
default: {
return false;
}
}
}
QSize Preview::calculateAttachSize(const QString& path, const QRect& bounds)
{
Shared::Global::FileInfo info = Shared::Global::getFileInfo(path);
return constrainAttachSize(info.size, bounds.size());
QSize constrained = constrainAttachSize(info.size, bounds.size());
if (!canVisualize(info)) {
int maxLabelWidth = bounds.width() - info.size.width() - margin;
QString elidedName = metrics.elidedText(info.name, Qt::ElideMiddle, maxLabelWidth);
int labelWidth = metrics.boundingRect(elidedName).size().width();
constrained.rwidth() += margin + labelWidth;
}
return constrained;
}
QSize Preview::constrainAttachSize(QSize src, QSize bounds)

View File

@ -38,7 +38,7 @@
*/
class Preview {
public:
Preview(const QString& pPath, const QSize& pMaxSize, const QPoint& pos, bool pRight, QWidget* parent);
Preview(const QString& pPath, const QSize& pMaxSize, const QPoint& pos, QWidget* parent);
~Preview();
void actualize(const QString& newPath, const QSize& newSize, const QPoint& newPoint);
@ -51,6 +51,7 @@ public:
static void initializeFont(const QFont& newFont);
static QSize constrainAttachSize(QSize src, QSize bounds);
static QSize calculateAttachSize(const QString& path, const QRect& bounds);
static bool canVisualize(const Shared::Global::FileInfo& info);
static QFont font;
static QFontMetrics metrics;
@ -64,7 +65,6 @@ private:
private:
Shared::Global::FileInfo info;
QString path;
QSize maxSize;
QSize actualSize;
QSize cachedLabelSize;
@ -75,7 +75,6 @@ private:
QMovie* movie;
bool fileReachable;
bool actualPreview;
bool right;
};
#endif // PREVIEW_H