1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00
qTox/src/chatlog/chatline.cpp

270 lines
6.2 KiB
C++
Raw Normal View History

2014-11-16 19:58:43 +08:00
/*
Copyright © 2014-2019 by The qTox Project Contributors
2014-11-16 19:58:43 +08:00
This file is part of qTox, a Qt-based graphical interface for Tox.
qTox is libre software: you can redistribute it and/or modify
2014-11-16 19:58:43 +08:00
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.
qTox is distributed in the hope that it will be useful,
2014-11-16 19:58:43 +08:00
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.
2014-11-16 19:58:43 +08:00
You should have received a copy of the GNU General Public License
along with qTox. If not, see <http://www.gnu.org/licenses/>.
2014-11-16 19:58:43 +08:00
*/
2014-11-12 21:11:25 +08:00
#include "chatline.h"
#include "chatlinecontent.h"
#include <QDebug>
#include <QGraphicsScene>
2015-01-05 01:21:35 +08:00
ChatLine::ChatLine()
2014-11-12 21:11:25 +08:00
{
}
ChatLine::~ChatLine()
{
for (ChatLineContent* c : content) {
if (c->scene())
2015-01-05 01:21:35 +08:00
c->scene()->removeItem(c);
2015-01-04 20:29:14 +08:00
2014-11-12 21:11:25 +08:00
delete c;
}
}
2015-01-20 17:31:50 +08:00
void ChatLine::setRow(int idx)
2014-11-12 21:11:25 +08:00
{
2015-01-20 17:31:50 +08:00
row = idx;
2014-11-12 21:11:25 +08:00
for (int c = 0; c < static_cast<int>(content.size()); ++c)
2015-01-20 17:31:50 +08:00
content[c]->setIndex(row, c);
2014-11-12 21:11:25 +08:00
}
void ChatLine::visibilityChanged(bool visible)
{
if (isVisible != visible) {
for (ChatLineContent* c : content)
2014-11-12 21:11:25 +08:00
c->visibilityChanged(visible);
}
isVisible = visible;
}
2015-01-20 17:31:50 +08:00
int ChatLine::getRow() const
2014-11-12 21:11:25 +08:00
{
2015-01-20 17:31:50 +08:00
return row;
2014-11-12 21:11:25 +08:00
}
ChatLineContent* ChatLine::getContent(int col) const
2014-12-14 04:11:03 +08:00
{
if (col < static_cast<int>(content.size()) && col >= 0)
2014-12-14 04:11:03 +08:00
return content[col];
return nullptr;
}
ChatLineContent* ChatLine::getContent(QPointF scenePos) const
2015-01-07 00:47:57 +08:00
{
for (ChatLineContent* c : content) {
if (c->sceneBoundingRect().contains(scenePos))
2015-01-07 00:47:57 +08:00
return c;
}
return nullptr;
}
2015-01-04 20:29:14 +08:00
void ChatLine::removeFromScene()
{
for (ChatLineContent* c : content) {
if (c->scene())
2015-01-05 01:21:35 +08:00
c->scene()->removeItem(c);
2015-01-04 20:29:14 +08:00
}
}
void ChatLine::addToScene(QGraphicsScene* scene)
2015-01-05 01:21:35 +08:00
{
if (!scene)
2015-01-05 01:21:35 +08:00
return;
for (ChatLineContent* c : content)
2015-01-05 01:21:35 +08:00
scene->addItem(c);
}
2015-01-10 18:57:46 +08:00
void ChatLine::setVisible(bool visible)
{
for (ChatLineContent* c : content)
2015-01-10 18:57:46 +08:00
c->setVisible(visible);
}
2014-11-12 21:11:25 +08:00
void ChatLine::selectionCleared()
{
for (ChatLineContent* c : content)
2014-11-12 21:11:25 +08:00
c->selectionCleared();
}
void ChatLine::selectionFocusChanged(bool focusIn)
{
for (ChatLineContent* c : content)
c->selectionFocusChanged(focusIn);
}
void ChatLine::fontChanged(const QFont& font)
{
for (ChatLineContent* c : content)
c->fontChanged(font);
}
2019-02-21 21:53:31 +08:00
void ChatLine::reloadTheme()
{
for (ChatLineContent* c : content) {
c->reloadTheme();
}
}
2014-11-12 21:11:25 +08:00
int ChatLine::getColumnCount()
{
return content.size();
}
void ChatLine::updateBBox()
{
2015-01-06 21:58:50 +08:00
bbox.setHeight(0);
2014-11-12 21:11:25 +08:00
bbox.setWidth(width);
for (ChatLineContent* c : content)
bbox.setHeight(qMax(c->sceneBoundingRect().top() - bbox.top() + c->sceneBoundingRect().height(),
bbox.height()));
2014-11-12 21:11:25 +08:00
}
QRectF ChatLine::sceneBoundingRect() const
2014-11-12 21:11:25 +08:00
{
return bbox;
}
void ChatLine::addColumn(ChatLineContent* item, ColumnFormat fmt)
{
if (!item)
2014-11-12 21:11:25 +08:00
return;
format.push_back(fmt);
content.push_back(item);
2014-11-12 21:11:25 +08:00
}
void ChatLine::replaceContent(int col, ChatLineContent* lineContent)
2014-11-12 23:45:24 +08:00
{
if (col >= 0 && col < static_cast<int>(content.size()) && lineContent) {
2015-01-05 01:21:35 +08:00
QGraphicsScene* scene = content[col]->scene();
2014-11-12 23:45:24 +08:00
delete content[col];
content[col] = lineContent;
2015-01-20 17:31:50 +08:00
lineContent->setIndex(row, col);
2015-01-05 01:21:35 +08:00
if (scene)
2015-01-05 01:21:35 +08:00
scene->addItem(content[col]);
2014-11-14 01:27:32 +08:00
2015-01-06 21:58:50 +08:00
layout(width, bbox.topLeft());
2014-11-14 01:27:32 +08:00
content[col]->visibilityChanged(isVisible);
content[col]->update();
2014-11-12 23:45:24 +08:00
}
}
2014-11-12 21:11:25 +08:00
void ChatLine::layout(qreal w, QPointF scenePos)
{
2016-01-16 09:23:56 +08:00
if (!content.size())
return;
2014-11-12 21:11:25 +08:00
width = w;
2015-01-06 21:58:50 +08:00
bbox.setTopLeft(scenePos);
2014-11-12 21:11:25 +08:00
qreal fixedWidth = (content.size() - 1) * columnSpacing;
2014-11-12 21:11:25 +08:00
qreal varWidth = 0.0; // used for normalisation
for (int i = 0; i < format.size(); ++i) {
if (format[i].policy == ColumnFormat::FixedSize)
2014-11-12 21:11:25 +08:00
fixedWidth += format[i].size;
else
varWidth += format[i].size;
}
if (varWidth == 0.0)
2014-11-12 21:11:25 +08:00
varWidth = 1.0;
qreal leftover = qMax(0.0, width - fixedWidth);
2014-12-09 05:08:23 +08:00
qreal maxVOffset = 0.0;
2014-11-12 21:11:25 +08:00
qreal xOffset = 0.0;
QVector<qreal> xPos(content.size());
2015-02-10 00:45:48 +08:00
for (int i = 0; i < content.size(); ++i) {
2014-11-12 21:11:25 +08:00
// calculate the effective width of the current column
qreal width;
if (format[i].policy == ColumnFormat::FixedSize)
2014-11-12 21:11:25 +08:00
width = format[i].size;
else
width = format[i].size / varWidth * leftover;
2014-11-14 01:27:32 +08:00
// set the width of the current column
2014-11-12 21:11:25 +08:00
content[i]->setWidth(width);
// calculate horizontal alignment
qreal xAlign = 0.0;
2015-01-04 03:37:40 +08:00
switch (format[i].hAlign) {
case ColumnFormat::Left:
break;
case ColumnFormat::Right:
xAlign = width - content[i]->boundingRect().width();
break;
case ColumnFormat::Center:
xAlign = (width - content[i]->boundingRect().width()) / 2.0;
break;
2014-11-12 21:11:25 +08:00
}
// reposition
2015-02-10 00:45:48 +08:00
xPos[i] = scenePos.x() + xOffset + xAlign;
2014-11-12 21:11:25 +08:00
2015-01-20 18:51:34 +08:00
xOffset += width + columnSpacing;
2015-02-10 00:45:48 +08:00
maxVOffset = qMax(maxVOffset, content[i]->getAscent());
2014-11-12 21:11:25 +08:00
}
for (int i = 0; i < content.size(); ++i) {
2014-11-14 01:27:32 +08:00
// calculate vertical alignment
// vertical alignment may depend on width, so we do it in a second pass
2015-02-10 00:45:48 +08:00
qreal yOffset = maxVOffset - content[i]->getAscent();
2014-11-14 01:27:32 +08:00
// reposition
2015-02-10 00:45:48 +08:00
content[i]->setPos(xPos[i], scenePos.y() + yOffset);
2014-11-14 01:27:32 +08:00
}
2014-11-12 21:11:25 +08:00
updateBBox();
}
2015-01-05 21:06:14 +08:00
void ChatLine::moveBy(qreal deltaY)
2014-11-12 21:11:25 +08:00
{
// reposition only
for (ChatLineContent* c : content)
2015-01-05 21:06:14 +08:00
c->moveBy(0, deltaY);
2014-11-12 21:11:25 +08:00
2015-01-06 21:58:50 +08:00
bbox.moveTop(bbox.top() + deltaY);
2014-11-12 21:11:25 +08:00
}
2015-04-13 05:49:24 +08:00
bool ChatLine::lessThanBSRectTop(const ChatLine::Ptr& lhs, const qreal& rhs)
{
return lhs->sceneBoundingRect().top() < rhs;
}
2015-04-13 05:49:24 +08:00
bool ChatLine::lessThanBSRectBottom(const ChatLine::Ptr& lhs, const qreal& rhs)
{
return lhs->sceneBoundingRect().bottom() < rhs;
}
2015-04-13 05:49:24 +08:00
bool ChatLine::lessThanRowIndex(const ChatLine::Ptr& lhs, const ChatLine::Ptr& rhs)
{
2015-01-20 17:31:50 +08:00
return lhs->getRow() < rhs->getRow();
}