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_
28 class ChatWidgetContents;
30 //!\brief Scroll area showing part of the chat messages for a given buffer.
31 /** The contents of the scroll area, i.e. a widget of type ChatWidgetContents,
32 * needs to be provided by calling init(). We don't create this widget ourselves, because
33 * while a ChatWidget will be destroyed and recreated quite often (for example when switching
34 * buffers), there ususally is no need to re-render its content every time (which can be time-consuming).
35 * Before a ChatWidget is destroyed, it gives up its ownership of its contents, referring responsibility
36 * back to where it came from.
38 * Because we use this as a custom widget in Qt Designer, we cannot use a constructor that takes custom
39 * parameters. Instead, it is mandatory to call init() before using this widget.
41 class ChatWidget : public QScrollArea {
45 ChatWidget(QWidget *parent = 0);
47 void init(QString net, QString buf, ChatWidgetContents *contents);
51 void appendMsg(Message);
54 void resizeEvent(QResizeEvent *event);
57 QString networkName, bufferName;
58 ChatWidgetContents *contents;
63 //!\brief Renders the complete contents of a Buffer.
64 /** Usually, this widget is used within a scroll
65 * area. Because Qt's rich-text rendering engine is much too slow for our purposes, we do everything
66 * except for the actual glyph painting ourselves. While this makes managing text quite cumbersome
67 * (we cannot, for example, use any of Qt's text editing, selecting or layouting features), it is
68 * also orders of magnitudes faster than any of the usual methods.
70 class ChatWidgetContents : public QWidget {
74 ChatWidgetContents(QString net, QString buf, QWidget *parent = 0);
75 ~ChatWidgetContents();
76 //int heightForWidth(int w) const;
77 virtual QSize sizeHint() const;
81 void appendMsg(Message);
85 virtual void paintEvent(QPaintEvent *event);
88 virtual void mousePressEvent(QMouseEvent *event);
89 virtual void mouseReleaseEvent(QMouseEvent *event);
90 virtual void mouseMoveEvent(QMouseEvent *event);
93 void layout(bool timer = false);
97 enum SelectionMode { NoSelection, TextSelected, LinesSelected };
98 enum MouseMode { Normal, Pressed, DragTsSep, DragTextSep, MarkText, MarkLines };
99 enum MousePos { None, OverTsSep, OverTextSep, OverUrl };
103 MouseMode dragStartMode;
108 SelectionMode selectionMode;
109 int selectionStart, selectionEnd, selectionLine;
110 QString networkName, bufferName;
114 QList<ChatLine *> lines;
115 QList<qreal> ycoords;
122 int tsGrabPos; ///< X-Position for changing the timestamp width
124 void computePositions();
130 int yToLineIdx(qreal y);
131 void clearSelection();
132 QString selectionToString();
135 //!\brief Containing the layout and providing the rendering of a single message.
136 /** A ChatLine takes a Message object,
137 * formats it (by turning the various message types into a human-readable form and afterwards pumping it through
138 * our Style engine), and stores it as a number of QTextLayouts representing the three fields of a chat line
139 * (timestamp, sender and text). These layouts already include any rendering information such as font,
140 * color, or selected characters. By calling layout(), they can be quickly layouted to fit a given set of field widths.
141 * Afterwards, they can quickly be painted whenever necessary.
143 * By separating the complex and slow task of interpreting and formatting Message objects (which happens exactly once
144 * per message) from the actual layouting and painting, we gain a lot of speed compared to the standard Qt rendering
147 class ChatLine : public QObject {
151 ChatLine(Message message, QString networkName, QString bufferName);
154 qreal layout(qreal tsWidth, qreal nickWidth, qreal textWidth);
155 qreal height() { return hght; }
156 int posToCursor(QPointF pos);
157 void draw(QPainter *p, const QPointF &pos);
159 enum SelectionMode { None, Partial, Full };
160 void setSelection(SelectionMode, int start = 0, int end = 0);
161 QDateTime getTimeStamp();
167 QString networkName, bufferName;
168 //QString ts, nick, text;
169 qreal tsWidth, senderWidth, textWidth;
170 QTextLayout tsLayout;
171 QTextLayout senderLayout;
172 QTextLayout textLayout;
173 QVector<QTextLayout::FormatRange> tsFormat, senderFormat, textFormat;
174 Style::StringFormats tsFormatted, senderFormatted, textFormatted;
176 SelectionMode selectionMode;
177 int selectionStart, selectionEnd;
178 void formatMsg(Message);