Implement proper layouting for QmlChatLine
[quassel.git] / src / qmlui / qmlchatline.h
1 /***************************************************************************
2  *   Copyright (C) 2005-2011 by the Quassel Project                        *
3  *   devel@quassel-irc.org                                                 *
4  *                                                                         *
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) version 3.                                           *
9  *                                                                         *
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.                          *
14  *                                                                         *
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  ***************************************************************************/
20
21 #ifndef QMLCHATLINE_H_
22 #define QMLCHATLINE_H_
23
24 #include <QDeclarativeItem>
25
26 #include "uistyle.h"
27
28 class QAbstractItemModel;
29
30 #include <QAbstractItemModel>
31
32 class QmlChatLine : public QDeclarativeItem {
33   Q_OBJECT
34
35   Q_PROPERTY(QObject *model READ modelPointer WRITE setModelPointer)
36   Q_PROPERTY(QmlChatLine::RenderData renderData READ renderData WRITE setRenderData)
37   Q_PROPERTY(qreal timestampWidth READ timestampWidth WRITE setTimestampWidth NOTIFY timestampWidthChanged)
38   Q_PROPERTY(qreal senderWidth READ senderWidth WRITE setSenderWidth NOTIFY senderWidthChanged)
39   Q_PROPERTY(qreal contentsWidth READ contentsWidth WRITE setContentsWidth NOTIFY contentsWidthChanged)
40   Q_PROPERTY(qreal columnSpacing READ columnSpacing WRITE setColumnSpacing NOTIFY columnSpacingChanged)
41   Q_PROPERTY(QVariant test READ test WRITE setTest)
42
43 public:
44   enum ColumnType {
45     TimestampColumn,
46     SenderColumn,
47     ContentsColumn,
48     NumColumns
49   };
50
51   //! Contains all model data needed to render a QmlChatLine
52   struct RenderData {
53     struct Column {
54       QString text;
55       UiStyle::FormatList formats;
56       QBrush background;
57       QBrush selectedBackground;
58     };
59
60     qint32 messageLabel;
61     bool isValid;
62
63     Column &operator[](ColumnType col) {
64       return _data[col];
65     }
66
67     Column const &operator[](ColumnType col) const {
68       return _data[col];
69     }
70
71     RenderData() { messageLabel = 0; isValid = false; }
72
73   private:
74     Column _data[NumColumns];
75   };
76
77   class ColumnLayout;
78   class TimestampLayout;
79   class SenderLayout;
80   class ContentsLayout;
81   class Layout;
82
83   QmlChatLine(QDeclarativeItem *parent = 0);
84   virtual ~QmlChatLine();
85
86   inline QAbstractItemModel *model() const { return _model; }
87   inline QObject *modelPointer() const { return _model; }
88   void setModelPointer(QObject *model) { _model = qobject_cast<QAbstractItemModel *>(model); }
89
90   inline RenderData renderData() const { return _data; }
91   void setRenderData(const RenderData &data);
92
93   Layout *layout();
94
95   inline qreal timestampWidth() const { return _timestampWidth; }
96   void setTimestampWidth(qreal w);
97   inline qreal senderWidth() const { return _senderWidth; }
98   void setSenderWidth(qreal w);
99   inline qreal contentsWidth() const { return _contentsWidth; }
100   void setContentsWidth(qreal w);
101   inline qreal columnSpacing() const { return _columnSpacing; }
102   void setColumnSpacing(qreal s);
103
104   inline QString text() const { return renderData()[ContentsColumn].text; }
105
106   void setTest(const QVariant &test) { _test = test; qDebug() << "set test" << test; }
107   QVariant test() const { return _test; }
108
109   QPointF columnPos(ColumnType colType) const;
110   qreal columnWidth(ColumnType colType) const;
111   QRectF columnBoundingRect(ColumnType colType) const;
112
113   virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
114
115   static void registerTypes();
116
117 signals:
118   void timestampWidthChanged(qreal);
119   void senderWidthChanged(qreal);
120   void contentsWidthChanged(qreal);
121   void columnWidthChanged(ColumnType column);
122   void columnSpacingChanged(qreal);
123
124 public slots:
125   void onClicked(qreal mouseX, qreal mouseY) { qDebug() << "clicked" << mouseX << mouseY; }
126   void onPressed(qreal mouseX, qreal mouseY) { qDebug() << "pressed" << mouseX << mouseY; }
127   void onMousePositionChanged(qreal mouseX, qreal mouseY) { qDebug() << "moved" << mouseX << mouseY; }
128
129 protected:
130
131 protected slots:
132   void onColumnWidthChanged(ColumnType column);
133
134 private:
135   QAbstractItemModel *_model;
136   RenderData _data;
137
138   qreal _timestampWidth, _senderWidth, _contentsWidth;
139   qreal _columnSpacing;
140
141   QVariant _test;
142
143   mutable Layout *_layout;
144 };
145
146 QDataStream &operator<<(QDataStream &out, const QmlChatLine::RenderData &data);
147 QDataStream &operator>>(QDataStream &in, QmlChatLine::RenderData &data);
148
149 Q_DECLARE_METATYPE(QmlChatLine::RenderData)
150
151 /** Layout classes */
152
153 class QmlChatLine::Layout {
154 public:
155   explicit Layout(QmlChatLine *parent);
156   ~Layout();
157
158   inline const QmlChatLine *chatLine() const { return _parent; }
159
160   qreal height() const;
161   void compute();
162   void draw(QPainter *p);
163
164 private:
165   QmlChatLine *_parent;
166   QmlChatLine::ColumnLayout *_timestampLayout, *_senderLayout, *_contentsLayout;
167 };
168
169 class QmlChatLine::ColumnLayout {
170 public:
171   explicit ColumnLayout(QmlChatLine::ColumnType col, QmlChatLine *chatLine);
172   virtual ~ColumnLayout();
173
174   inline QmlChatLine *chatLine() const { return _parent; }
175   inline ColumnType columnType() const { return _type; }
176
177   virtual qreal height() const;
178   virtual void compute();
179   virtual void draw(QPainter *p);
180
181 protected:
182   inline QTextLayout *layout() const { return _layout; }
183   void initLayout(QTextOption::WrapMode wrapMode, Qt::Alignment alignment);
184   QVector<QTextLayout::FormatRange> selectionFormats() const;
185
186 private:
187   QmlChatLine *_parent;
188   ColumnType _type;
189   QTextLayout *_layout;
190 };
191
192 class QmlChatLine::TimestampLayout : public QmlChatLine::ColumnLayout {
193 public:
194   explicit TimestampLayout(QmlChatLine *chatLine);
195
196 };
197
198 class QmlChatLine::SenderLayout : public QmlChatLine::ColumnLayout {
199 public:
200   explicit SenderLayout(QmlChatLine *chatLine);
201
202 };
203
204 class QmlChatLine::ContentsLayout : public QmlChatLine::ColumnLayout {
205 public:
206   explicit ContentsLayout(QmlChatLine *chatLine);
207
208   void compute();
209 };
210
211 #endif