1
/***************************************************************************
2
* Copyright (C) 2005/06 by The Quassel Team *
3
* devel@quassel-irc.org *
5
* This program is free software; you can redistribute it and/or modify *
6
* it under the terms of the GNU General Public License as published by *
7
* the Free Software Foundation; either version 2 of the License, or *
8
* (at your option) any later version. *
10
* This program is distributed in the hope that it will be useful, *
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13
* GNU General Public License for more details. *
15
* You should have received a copy of the GNU General Public License *
16
* along with this program; if not, write to the *
17
* Free Software Foundation, Inc., *
18
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19
***************************************************************************/
21
#ifndef _CHATWIDGET_H_
22
#define _CHATWIDGET_H_
32
//!\brief Scroll area showing part of the chat messages for a given buffer.
33
/** The contents of the scroll area, i.e. a widget of type ChatWidgetContents,
34
* needs to be provided by calling init(). We don't create this widget ourselves, because
35
* while a ChatWidget will be destroyed and recreated quite often (for example when switching
36
* buffers), there ususally is no need to re-render its content every time (which can be time-consuming).
37
* Before a ChatWidget is destroyed, it gives up its ownership of its contents, referring responsibility
38
* back to where it came from.
40
* Because we use this as a custom widget in Qt Designer, we cannot use a constructor that takes custom
41
* parameters. Instead, it is mandatory to call init() before using this widget.
43
class ChatWidget : public QAbstractScrollArea {
47
ChatWidget(QWidget *parent = 0);
49
void init(QString net, QString buf);
51
virtual QSize sizeHint() const;
55
void prependChatLine(ChatLine *);
56
void appendChatLine(ChatLine *);
57
void prependChatLines(QList<ChatLine *>);
58
void appendChatLines(QList<ChatLine *>);
59
void setContents(QList<ChatLine *>);
62
virtual void resizeEvent(QResizeEvent *event);
63
virtual void paintEvent(QPaintEvent * event);
64
virtual void mousePressEvent(QMouseEvent *event);
65
virtual void mouseReleaseEvent(QMouseEvent *event);
66
virtual void mouseMoveEvent(QMouseEvent *event);
67
virtual void mouseDoubleClickEvent(QMouseEvent *event);
71
void scrollBarAction(int);
72
void scrollBarValChanged(int);
73
void ensureVisible(int line);
74
void handleScrollTimer();
77
QString networkName, bufferName;
78
enum SelectionMode { NoSelection, TextSelected, LinesSelected };
79
enum MouseMode { Normal, Pressed, DragTsSep, DragTextSep, MarkText, MarkLines };
80
enum MousePos { None, OverTsSep, OverTextSep, OverUrl };
84
MouseMode dragStartMode;
89
SelectionMode selectionMode;
90
int selectionStart, selectionEnd, selectionLine;
92
int bottomLine, bottomLineOffset;
94
QList<ChatLine *> lines;
97
QPoint pointerPosition;
104
int tsGrabPos; ///< X-Position for changing the timestamp width
106
void computePositions();
112
void adjustScrollBar();
114
int yToLineIdx(qreal y);
115
void clearSelection();
116
QString selectionToString();
117
void handleMouseMoveEvent(const QPoint &pos);
121
//FIXME: chatline doku
122
//!\brief Containing the layout and providing the rendering of a single message.
123
/** A ChatLine takes a Message object,
124
* formats it (by turning the various message types into a human-readable form and afterwards pumping it through
125
* our Style engine), and stores it as a number of QTextLayouts representing the three fields of a chat line
126
* (timestamp, sender and text). These layouts already include any rendering information such as font,
127
* color, or selected characters. By calling layout(), they can be quickly layouted to fit a given set of field widths.
128
* Afterwards, they can quickly be painted whenever necessary.
130
* By separating the complex and slow task of interpreting and formatting Message objects (which happens exactly once
131
* per message) from the actual layouting and painting, we gain a lot of speed compared to the standard Qt rendering
134
class ChatLine : public QObject {
138
ChatLine(Message message);
141
qreal layout(qreal tsWidth, qreal nickWidth, qreal textWidth);
142
qreal height() { return hght; }
143
int posToCursor(QPointF pos);
144
void draw(QPainter *p, const QPointF &pos);
146
enum SelectionMode { None, Partial, Full };
147
void setSelection(SelectionMode, int start = 0, int end = 0);
148
QDateTime timeStamp();
155
QUrl getUrl(int pos);
162
qreal tsWidth, senderWidth, textWidth;
163
Style::FormattedString tsFormatted, senderFormatted, textFormatted;
169
QTextCharFormat format;
183
QVector<int> charPos;
184
QVector<int> charWidths;
185
QVector<int> charHeights;
186
QVector<int> charUrlIdx;
187
QList<FormatRange> tsFormat, senderFormat, textFormat;
189
QList<LineLayout> lineLayouts;
192
SelectionMode selectionMode;
193
int selectionStart, selectionEnd;
194
void formatMsg(Message);
195
void precomputeLine();
196
QList<FormatRange> calcFormatRanges(const Style::FormattedString &, QTextLayout::FormatRange additional = QTextLayout::FormatRange());
201
QList<Message> messages;
204
QList<ChatLine *> lines;
207
Q_DECLARE_METATYPE(LayoutTask);
209
class LayoutThread : public QThread {
214
virtual ~LayoutThread();
218
void processTask(LayoutTask task);
221
void taskProcessed(LayoutTask task);
224
QList<LayoutTask> queue;
226
QWaitCondition condition;