forked from blue/squawk
Date dividers between messages from different dates
This commit is contained in:
parent
5f925217fc
commit
3f09b8f838
@ -22,6 +22,16 @@ option(WITH_KIO "Build KIO support module" ON)
|
|||||||
# Dependencies
|
# Dependencies
|
||||||
## Qt
|
## Qt
|
||||||
find_package(Qt5 COMPONENTS Widgets DBus Gui Xml Network Core REQUIRED)
|
find_package(Qt5 COMPONENTS Widgets DBus Gui Xml Network Core REQUIRED)
|
||||||
|
find_package(Boost COMPONENTS)
|
||||||
|
|
||||||
|
target_include_directories(squawk PRIVATE ${Boost_INCLUDE_DIRS})
|
||||||
|
target_include_directories(squawk PRIVATE ${Qt5_INCLUDE_DIRS})
|
||||||
|
target_include_directories(squawk PRIVATE ${Qt5Widgets_INCLUDE_DIRS})
|
||||||
|
target_include_directories(squawk PRIVATE ${Qt5DBus_INCLUDE_DIRS})
|
||||||
|
target_include_directories(squawk PRIVATE ${Qt5Gui_INCLUDE_DIRS})
|
||||||
|
target_include_directories(squawk PRIVATE ${Qt5Xml_INCLUDE_DIRS})
|
||||||
|
target_include_directories(squawk PRIVATE ${Qt5Network_INCLUDE_DIRS})
|
||||||
|
target_include_directories(squawk PRIVATE ${Qt5Core_INCLUDE_DIRS})
|
||||||
|
|
||||||
## QXmpp
|
## QXmpp
|
||||||
if (SYSTEM_QXMPP)
|
if (SYSTEM_QXMPP)
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
constexpr int maxMessageHeight = 10000;
|
constexpr int maxMessageHeight = 10000;
|
||||||
constexpr int approximateSingleMessageHeight = 20;
|
constexpr int approximateSingleMessageHeight = 20;
|
||||||
constexpr int progressSize = 70;
|
constexpr int progressSize = 70;
|
||||||
|
constexpr int dateDeviderMargin = 10;
|
||||||
|
|
||||||
const std::set<int> FeedView::geometryChangingRoles = {
|
const std::set<int> FeedView::geometryChangingRoles = {
|
||||||
Models::MessageFeed::Attach,
|
Models::MessageFeed::Attach,
|
||||||
@ -46,7 +47,9 @@ FeedView::FeedView(QWidget* parent):
|
|||||||
specialModel(false),
|
specialModel(false),
|
||||||
clearWidgetsMode(false),
|
clearWidgetsMode(false),
|
||||||
modelState(Models::MessageFeed::complete),
|
modelState(Models::MessageFeed::complete),
|
||||||
progress()
|
progress(),
|
||||||
|
dividerFont(),
|
||||||
|
dividerMetrics(dividerFont)
|
||||||
{
|
{
|
||||||
horizontalScrollBar()->setRange(0, 0);
|
horizontalScrollBar()->setRange(0, 0);
|
||||||
verticalScrollBar()->setSingleStep(approximateSingleMessageHeight);
|
verticalScrollBar()->setSingleStep(approximateSingleMessageHeight);
|
||||||
@ -56,6 +59,15 @@ FeedView::FeedView(QWidget* parent):
|
|||||||
|
|
||||||
progress.setParent(viewport());
|
progress.setParent(viewport());
|
||||||
progress.resize(progressSize, progressSize);
|
progress.resize(progressSize, progressSize);
|
||||||
|
|
||||||
|
dividerFont = getFont();
|
||||||
|
dividerFont.setBold(true);
|
||||||
|
float ndps = dividerFont.pointSizeF();
|
||||||
|
if (ndps != -1) {
|
||||||
|
dividerFont.setPointSizeF(ndps * 1.2);
|
||||||
|
} else {
|
||||||
|
dividerFont.setPointSize(dividerFont.pointSize() + 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FeedView::~FeedView()
|
FeedView::~FeedView()
|
||||||
@ -187,8 +199,16 @@ void FeedView::updateGeometries()
|
|||||||
|
|
||||||
hints.clear();
|
hints.clear();
|
||||||
uint32_t previousOffset = 0;
|
uint32_t previousOffset = 0;
|
||||||
|
QDateTime lastDate;
|
||||||
for (int i = 0, size = m->rowCount(); i < size; ++i) {
|
for (int i = 0, size = m->rowCount(); i < size; ++i) {
|
||||||
QModelIndex index = m->index(i, 0, rootIndex());
|
QModelIndex index = m->index(i, 0, rootIndex());
|
||||||
|
QDateTime currentDate = index.data(Models::MessageFeed::Date).toDateTime();
|
||||||
|
if (i > 0) {
|
||||||
|
if (currentDate.daysTo(lastDate) > 0) {
|
||||||
|
previousOffset += dividerMetrics.height() + dateDeviderMargin * 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastDate = currentDate;
|
||||||
int height = itemDelegate(index)->sizeHint(option, index).height();
|
int height = itemDelegate(index)->sizeHint(option, index).height();
|
||||||
hints.emplace_back(Hint({
|
hints.emplace_back(Hint({
|
||||||
false,
|
false,
|
||||||
@ -222,8 +242,16 @@ bool FeedView::tryToCalculateGeometriesWithNoScrollbars(const QStyleOptionViewIt
|
|||||||
{
|
{
|
||||||
uint32_t previousOffset = 0;
|
uint32_t previousOffset = 0;
|
||||||
bool success = true;
|
bool success = true;
|
||||||
|
QDateTime lastDate;
|
||||||
for (int i = 0, size = m->rowCount(); i < size; ++i) {
|
for (int i = 0, size = m->rowCount(); i < size; ++i) {
|
||||||
QModelIndex index = m->index(i, 0, rootIndex());
|
QModelIndex index = m->index(i, 0, rootIndex());
|
||||||
|
QDateTime currentDate = index.data(Models::MessageFeed::Date).toDateTime();
|
||||||
|
if (i > 0) {
|
||||||
|
if (currentDate.daysTo(lastDate) > 0) {
|
||||||
|
previousOffset += dateDeviderMargin * 2 + dividerMetrics.height();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastDate = currentDate;
|
||||||
int height = itemDelegate(index)->sizeHint(option, index).height();
|
int height = itemDelegate(index)->sizeHint(option, index).height();
|
||||||
|
|
||||||
if (previousOffset + height > totalHeight) {
|
if (previousOffset + height > totalHeight) {
|
||||||
@ -266,6 +294,7 @@ void FeedView::paintEvent(QPaintEvent* event)
|
|||||||
toRener.emplace_back(m->index(i, 0, rootIndex()));
|
toRener.emplace_back(m->index(i, 0, rootIndex()));
|
||||||
}
|
}
|
||||||
if (y1 > relativeY1) {
|
if (y1 > relativeY1) {
|
||||||
|
inZone = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -282,11 +311,32 @@ void FeedView::paintEvent(QPaintEvent* event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDateTime lastDate;
|
||||||
|
bool first = true;
|
||||||
for (const QModelIndex& index : toRener) {
|
for (const QModelIndex& index : toRener) {
|
||||||
|
QDateTime currentDate = index.data(Models::MessageFeed::Date).toDateTime();
|
||||||
option.rect = visualRect(index);
|
option.rect = visualRect(index);
|
||||||
|
if (first) {
|
||||||
|
int ind = index.row() - 1;
|
||||||
|
if (ind > 0) {
|
||||||
|
QDateTime underDate = m->index(ind, 0, rootIndex()).data(Models::MessageFeed::Date).toDateTime();
|
||||||
|
if (currentDate.daysTo(underDate) > 0) {
|
||||||
|
drawDateDevider(option.rect.bottom(), underDate, painter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
bool mouseOver = option.rect.contains(cursor) && vp->rect().contains(cursor);
|
bool mouseOver = option.rect.contains(cursor) && vp->rect().contains(cursor);
|
||||||
option.state.setFlag(QStyle::State_MouseOver, mouseOver);
|
option.state.setFlag(QStyle::State_MouseOver, mouseOver);
|
||||||
itemDelegate(index)->paint(&painter, option, index);
|
itemDelegate(index)->paint(&painter, option, index);
|
||||||
|
|
||||||
|
if (!lastDate.isNull() && currentDate.daysTo(lastDate) > 0) {
|
||||||
|
drawDateDevider(option.rect.bottom(), lastDate, painter);
|
||||||
|
}
|
||||||
|
lastDate = currentDate;
|
||||||
|
}
|
||||||
|
if (!lastDate.isNull() && inZone) { //if after drawing all messages there is still space
|
||||||
|
drawDateDevider(option.rect.bottom(), lastDate, painter);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clearWidgetsMode && specialDelegate) {
|
if (clearWidgetsMode && specialDelegate) {
|
||||||
@ -300,6 +350,16 @@ void FeedView::paintEvent(QPaintEvent* event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FeedView::drawDateDevider(int top, const QDateTime& date, QPainter& painter)
|
||||||
|
{
|
||||||
|
int divisionHeight = dateDeviderMargin * 2 + dividerMetrics.height();
|
||||||
|
QRect r(QPoint(0, top), QSize(viewport()->width(), divisionHeight));
|
||||||
|
painter.save();
|
||||||
|
painter.setFont(dividerFont);
|
||||||
|
painter.drawText(r, Qt::AlignCenter, date.toString("d MMMM"));
|
||||||
|
painter.restore();
|
||||||
|
}
|
||||||
|
|
||||||
void FeedView::verticalScrollbarValueChanged(int value)
|
void FeedView::verticalScrollbarValueChanged(int value)
|
||||||
{
|
{
|
||||||
vo = verticalScrollBar()->maximum() - value;
|
vo = verticalScrollBar()->maximum() - value;
|
||||||
|
@ -73,6 +73,7 @@ protected:
|
|||||||
private:
|
private:
|
||||||
bool tryToCalculateGeometriesWithNoScrollbars(const QStyleOptionViewItem& option, const QAbstractItemModel* model, uint32_t totalHeight);
|
bool tryToCalculateGeometriesWithNoScrollbars(const QStyleOptionViewItem& option, const QAbstractItemModel* model, uint32_t totalHeight);
|
||||||
void positionProgress();
|
void positionProgress();
|
||||||
|
void drawDateDevider(int top, const QDateTime& date, QPainter& painter);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Hint {
|
struct Hint {
|
||||||
@ -87,6 +88,8 @@ private:
|
|||||||
bool clearWidgetsMode;
|
bool clearWidgetsMode;
|
||||||
Models::MessageFeed::SyncState modelState;
|
Models::MessageFeed::SyncState modelState;
|
||||||
Progress progress;
|
Progress progress;
|
||||||
|
QFont dividerFont;
|
||||||
|
QFontMetrics dividerMetrics;
|
||||||
|
|
||||||
static const std::set<int> geometryChangingRoles;
|
static const std::set<int> geometryChangingRoles;
|
||||||
|
|
||||||
|
@ -130,12 +130,13 @@ void MessageDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optio
|
|||||||
}
|
}
|
||||||
messageSize.rheight() += nickMetrics.lineSpacing();
|
messageSize.rheight() += nickMetrics.lineSpacing();
|
||||||
messageSize.rheight() += dateMetrics.height();
|
messageSize.rheight() += dateMetrics.height();
|
||||||
|
QString dateString = data.date.toLocalTime().toString("hh:mm");
|
||||||
if (messageSize.width() < opt.rect.width()) {
|
if (messageSize.width() < opt.rect.width()) {
|
||||||
QSize senderSize = nickMetrics.boundingRect(messageRect, 0, data.sender).size();
|
QSize senderSize = nickMetrics.boundingRect(messageRect, 0, data.sender).size();
|
||||||
if (senderSize.width() > messageSize.width()) {
|
if (senderSize.width() > messageSize.width()) {
|
||||||
messageSize.setWidth(senderSize.width());
|
messageSize.setWidth(senderSize.width());
|
||||||
}
|
}
|
||||||
QSize dateSize = dateMetrics.boundingRect(messageRect, 0, data.date.toLocalTime().toString()).size();
|
QSize dateSize = dateMetrics.boundingRect(messageRect, 0, dateString).size();
|
||||||
int addition = 0;
|
int addition = 0;
|
||||||
|
|
||||||
if (data.correction.corrected) {
|
if (data.correction.corrected) {
|
||||||
@ -211,7 +212,7 @@ void MessageDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optio
|
|||||||
QColor q = painter->pen().color();
|
QColor q = painter->pen().color();
|
||||||
q.setAlpha(180);
|
q.setAlpha(180);
|
||||||
painter->setPen(q);
|
painter->setPen(q);
|
||||||
painter->drawText(opt.rect, opt.displayAlignment, data.date.toLocalTime().toString(), &rect);
|
painter->drawText(opt.rect, opt.displayAlignment, dateString, &rect);
|
||||||
int currentY = opt.rect.y();
|
int currentY = opt.rect.y();
|
||||||
if (data.sentByMe) {
|
if (data.sentByMe) {
|
||||||
QLabel* statusIcon = getStatusIcon(data);
|
QLabel* statusIcon = getStatusIcon(data);
|
||||||
|
Loading…
Reference in New Issue
Block a user