qtmessagelogitemdelegate.cpp 14.3 KB
Newer Older
Aurindam Jana's avatar
Aurindam Jana committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

33
34
#include "qtmessagelogitemdelegate.h"
#include "qtmessagelogeditor.h"
Aurindam Jana's avatar
Aurindam Jana committed
35

Denis Mingulov's avatar
Denis Mingulov committed
36
37
#include <QPainter>
#include <QTreeView>
38
#include <QScrollBar>
Aurindam Jana's avatar
Aurindam Jana committed
39

40
41
42
const char CONSOLE_LOG_BACKGROUND_COLOR[] = "#E8EEF2";
const char CONSOLE_WARNING_BACKGROUND_COLOR[] = "#F6F4EB";
const char CONSOLE_ERROR_BACKGROUND_COLOR[] = "#F6EBE7";
Aurindam Jana's avatar
Aurindam Jana committed
43
44
const char CONSOLE_EDITOR_BACKGROUND_COLOR[] = "#F7F7F7";

45
46
47
48
49
const char CONSOLE_LOG_BACKGROUND_SELECTED_COLOR[] = "#CDDEEA";
const char CONSOLE_WARNING_BACKGROUND_SELECTED_COLOR[] = "#F3EED1";
const char CONSOLE_ERROR_BACKGROUND_SELECTED_COLOR[] = "#F5D4CB";
const char CONSOLE_EDITOR_BACKGROUND_SELECTED_COLOR[] = "#DEDEDE";

Aurindam Jana's avatar
Aurindam Jana committed
50
51
52
53
54
const char CONSOLE_LOG_TEXT_COLOR[] = "#333333";
const char CONSOLE_WARNING_TEXT_COLOR[] = "#666666";
const char CONSOLE_ERROR_TEXT_COLOR[] = "#1D5B93";
const char CONSOLE_EDITOR_TEXT_COLOR[] = "#000000";

55
const char CONSOLE_BORDER_COLOR[] = "#C9C9C9";
Aurindam Jana's avatar
Aurindam Jana committed
56

57
58
const int ELLIPSIS_GRADIENT_WIDTH = 16;

Aurindam Jana's avatar
Aurindam Jana committed
59
60
61
62
63
namespace Debugger {
namespace Internal {

///////////////////////////////////////////////////////////////////////
//
64
// QtMessageLogItemDelegate
Aurindam Jana's avatar
Aurindam Jana committed
65
66
67
//
///////////////////////////////////////////////////////////////////////

68
QtMessageLogItemDelegate::QtMessageLogItemDelegate(QObject *parent) :
Aurindam Jana's avatar
Aurindam Jana committed
69
70
71
72
73
74
    QStyledItemDelegate(parent),
    m_logIcon(QLatin1String(":/debugger/images/log.png")),
    m_warningIcon(QLatin1String(":/debugger/images/warning.png")),
    m_errorIcon(QLatin1String(":/debugger/images/error.png")),
    m_expandIcon(QLatin1String(":/debugger/images/expand.png")),
    m_collapseIcon(QLatin1String(":/debugger/images/collapse.png")),
75
    m_prompt(QLatin1String(":/debugger/images/prompt.png")),
76
77
    m_itemModel(0),
    m_cachedHeight(0)
Aurindam Jana's avatar
Aurindam Jana committed
78
79
80
{
}

81
void QtMessageLogItemDelegate::emitSizeHintChanged(const QModelIndex &index)
Aurindam Jana's avatar
Aurindam Jana committed
82
83
84
85
{
    emit sizeHintChanged(index);
}

86
QColor QtMessageLogItemDelegate::drawBackground(QPainter *painter, const QRect &rect,
87
                                         const QModelIndex &index,
Aurindam Jana's avatar
Aurindam Jana committed
88
89
                                         bool selected) const
{
90
91
92
    painter->save();
    QtMessageLogHandler::ItemType itemType = (QtMessageLogHandler::ItemType)index.data(
                QtMessageLogHandler::TypeRole).toInt();
Aurindam Jana's avatar
Aurindam Jana committed
93
94
    QColor backgroundColor;
    switch (itemType) {
95
96
97
    case QtMessageLogHandler::DebugType:
        backgroundColor = selected ? QColor(CONSOLE_LOG_BACKGROUND_SELECTED_COLOR) :
                                     QColor(CONSOLE_LOG_BACKGROUND_COLOR);
Aurindam Jana's avatar
Aurindam Jana committed
98
        break;
99
100
101
    case QtMessageLogHandler::WarningType:
        backgroundColor = selected ? QColor(CONSOLE_WARNING_BACKGROUND_SELECTED_COLOR) :
                                     QColor(CONSOLE_WARNING_BACKGROUND_COLOR);
Aurindam Jana's avatar
Aurindam Jana committed
102
        break;
103
104
105
    case QtMessageLogHandler::ErrorType:
        backgroundColor = selected ? QColor(CONSOLE_ERROR_BACKGROUND_SELECTED_COLOR) :
                                     QColor(CONSOLE_ERROR_BACKGROUND_COLOR);
Aurindam Jana's avatar
Aurindam Jana committed
106
        break;
107
    case QtMessageLogHandler::InputType:
Aurindam Jana's avatar
Aurindam Jana committed
108
    default:
109
110
        backgroundColor = selected ? QColor(CONSOLE_EDITOR_BACKGROUND_SELECTED_COLOR) :
                                     QColor(CONSOLE_EDITOR_BACKGROUND_COLOR);
Aurindam Jana's avatar
Aurindam Jana committed
111
112
        break;
    }
113
114
    if (!(index.flags() & Qt::ItemIsEditable))
        painter->setBrush(backgroundColor);
Aurindam Jana's avatar
Aurindam Jana committed
115
116
    painter->setPen(Qt::NoPen);
    painter->drawRect(rect);
117
118
119
120
121
122

    // Separator lines
    painter->setPen(QColor(CONSOLE_BORDER_COLOR));
    if (!(index.flags() & Qt::ItemIsEditable))
        painter->drawLine(0, rect.bottom(), rect.right(),
                      rect.bottom());
123
    painter->restore();
124
    return backgroundColor;
Aurindam Jana's avatar
Aurindam Jana committed
125
126
}

127
void QtMessageLogItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
Aurindam Jana's avatar
Aurindam Jana committed
128
129
130
131
132
133
134
135
136
                         const QModelIndex &index) const
{
    QStyleOptionViewItemV4 opt = option;
    initStyleOption(&opt, index);
    painter->save();

    //Set Colors
    QColor textColor;
    QIcon taskIcon;
137
138
    QtMessageLogHandler::ItemType type = (QtMessageLogHandler::ItemType)index.data(
                QtMessageLogHandler::TypeRole).toInt();
Aurindam Jana's avatar
Aurindam Jana committed
139
    switch (type) {
140
    case QtMessageLogHandler::DebugType:
Aurindam Jana's avatar
Aurindam Jana committed
141
142
143
        textColor = QColor(CONSOLE_LOG_TEXT_COLOR);
        taskIcon = m_logIcon;
        break;
144
    case QtMessageLogHandler::WarningType:
Aurindam Jana's avatar
Aurindam Jana committed
145
146
147
        textColor = QColor(CONSOLE_WARNING_TEXT_COLOR);
        taskIcon = m_warningIcon;
        break;
148
    case QtMessageLogHandler::ErrorType:
Aurindam Jana's avatar
Aurindam Jana committed
149
150
151
        textColor = QColor(CONSOLE_ERROR_TEXT_COLOR);
        taskIcon = m_errorIcon;
        break;
152
    case QtMessageLogHandler::InputType:
Aurindam Jana's avatar
Aurindam Jana committed
153
154
155
156
157
158
159
160
161
        textColor = QColor(CONSOLE_EDITOR_TEXT_COLOR);
        taskIcon = m_prompt;
        break;
    default:
        textColor = QColor(CONSOLE_EDITOR_TEXT_COLOR);
        break;
    }

    //Paint background
162
    QColor backgroundColor = drawBackground(painter, opt.rect, index,
Aurindam Jana's avatar
Aurindam Jana committed
163
164
165
166
167
168
169
170
171
172
                   bool(opt.state & QStyle::State_Selected));

    //Calculate positions
    const QTreeView *view = qobject_cast<const QTreeView *>(opt.widget);
    int level = 0;
    QModelIndex idx(index);
    while (idx.parent() != QModelIndex()) {
        idx = idx.parent();
        level++;
    }
173
174
    int width = view->width() - level * view->indentation() -
            view->verticalScrollBar()->width();
Aurindam Jana's avatar
Aurindam Jana committed
175
    bool showTypeIcon = index.parent() == QModelIndex();
176
    bool showExpandableIcon = type == QtMessageLogHandler::UndefinedType;
Aurindam Jana's avatar
Aurindam Jana committed
177
178
179

    QRect rect(opt.rect.x(), opt.rect.top(), width, opt.rect.height());
    ConsoleItemPositions positions(rect, opt.font, showTypeIcon,
180
                        showExpandableIcon, m_itemModel);
Aurindam Jana's avatar
Aurindam Jana committed
181
182
183
184
185
186
187
188
189
190
191

    // Paint TaskIconArea:
    if (showTypeIcon)
        painter->drawPixmap(positions.adjustedLeft(), positions.adjustedTop(),
                            taskIcon.pixmap(positions.typeIconWidth(),
                                            positions.typeIconHeight()));

    // Set Text Color
    painter->setPen(textColor);
    // Paint TextArea:
    // Layout the description
192
193
    QString str = index.data(Qt::DisplayRole).toString();
    bool showFileLineInfo = true;
194
195
196
197
198
199
200
201
202
203
204
    // show complete text if selected
    if (view->selectionModel()->currentIndex() == index) {
        QTextLayout tl(str, opt.font);
        layoutText(tl, positions.textAreaWidth(), &showFileLineInfo);
        tl.draw(painter, QPoint(positions.textAreaLeft(), positions.adjustedTop()));
    } else {
        QFontMetrics fm(opt.font);
        painter->drawText(positions.textArea(),
                          fm.elidedText(str, Qt::ElideRight,
                                        positions.textAreaWidth()));
    }
Aurindam Jana's avatar
Aurindam Jana committed
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
    //skip if area is editable
    if (showExpandableIcon) {
        // Paint ExpandableIconArea:
        QIcon expandCollapseIcon;
        if (index.model()->rowCount(index)) {
            if (view->isExpanded(index))
                expandCollapseIcon = m_collapseIcon;
            else
                expandCollapseIcon = m_expandIcon;
        }
        painter->drawPixmap(positions.expandCollapseIconLeft(),
                            positions.adjustedTop(),
                            expandCollapseIcon.pixmap(
                                positions.expandCollapseIconWidth(),
                                positions.expandCollapseIconHeight()));
    }

222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
    if (showFileLineInfo) {
        //Check for file info
        QString file = index.data(QtMessageLogHandler::FileRole).toString();
        if (!file.isEmpty()) {
            QFontMetrics fm(option.font);
            // Paint FileArea
            const int pos = file.lastIndexOf(QLatin1Char('/'));
            if (pos != -1)
                file = file.mid(pos +1);
            const int realFileWidth = fm.width(file);
            painter->setClipRect(positions.fileArea());
            painter->drawText(positions.fileAreaLeft(),
                              positions.adjustedTop() + fm.ascent(), file);
            if (realFileWidth > positions.fileAreaWidth()) {
                // draw a gradient to mask the text
                int gradientStart = positions.fileAreaLeft() - 1;
                QLinearGradient lg(gradientStart +
                                   ELLIPSIS_GRADIENT_WIDTH, 0, gradientStart, 0);
                lg.setColorAt(0, Qt::transparent);
                lg.setColorAt(1, backgroundColor);
                painter->fillRect(gradientStart, positions.adjustedTop(),
                                  ELLIPSIS_GRADIENT_WIDTH, positions.lineHeight(),
                                  lg);
            }

            // Paint LineArea
            QString lineText  = index.data(QtMessageLogHandler::LineRole).toString();
            painter->setClipRect(positions.lineArea());
            const int realLineWidth = fm.width(lineText);
            painter->drawText(positions.lineAreaRight() - realLineWidth,
                              positions.adjustedTop() + fm.ascent(), lineText);
253
254
255
        }
    }
    painter->setClipRect(opt.rect);
Aurindam Jana's avatar
Aurindam Jana committed
256
257
258
    painter->restore();
}

259
QSize QtMessageLogItemDelegate::sizeHint(const QStyleOptionViewItem &option,
Aurindam Jana's avatar
Aurindam Jana committed
260
261
262
263
264
265
266
267
268
269
270
271
                             const QModelIndex &index) const
{
    QStyleOptionViewItemV4 opt = option;
    initStyleOption(&opt, index);

    const QTreeView *view = qobject_cast<const QTreeView *>(opt.widget);
    int level = 0;
    QModelIndex idx(index);
    while (idx.parent() != QModelIndex()) {
        idx = idx.parent();
        level++;
    }
272
273
    int width = view->width() - level * view->indentation() -
            view->verticalScrollBar()->width();
Aurindam Jana's avatar
Aurindam Jana committed
274
275
276
    if (index.flags() & Qt::ItemIsEditable)
        return QSize(width, view->height() * 1/2);

277
278
279
280
    const bool selected = (view->selectionModel()->currentIndex() == index);
    if (!selected && option.font == m_cachedFont && m_cachedHeight > 0)
        return QSize(width, m_cachedHeight);

281
282
    QtMessageLogHandler::ItemType type = (QtMessageLogHandler::ItemType)index.data(
                QtMessageLogHandler::TypeRole).toInt();
Aurindam Jana's avatar
Aurindam Jana committed
283
    bool showTypeIcon = index.parent() == QModelIndex();
284
    bool showExpandableIcon = type == QtMessageLogHandler::UndefinedType;
Aurindam Jana's avatar
Aurindam Jana committed
285
286
287

    QRect rect(level * view->indentation(), 0, width, 0);
    ConsoleItemPositions positions(rect, opt.font,
288
                        showTypeIcon, showExpandableIcon, m_itemModel);
Aurindam Jana's avatar
Aurindam Jana committed
289

290
    QFontMetrics fm(option.font);
291
292
293
294
295
296
297
298
299
    qreal height = fm.height();

    if (selected) {
        QString str = index.data(Qt::DisplayRole).toString();

        QTextLayout tl(str, option.font);
        height = layoutText(tl, positions.textAreaWidth());
    }

Aurindam Jana's avatar
Aurindam Jana committed
300
    height += 2 * ConsoleItemPositions::ITEM_PADDING;
301

Aurindam Jana's avatar
Aurindam Jana committed
302
303
304
    if (height < positions.minimumHeight())
        height = positions.minimumHeight();

305
306
307
308
309
    if (!selected) {
        m_cachedHeight = height;
        m_cachedFont = option.font;
    }

Aurindam Jana's avatar
Aurindam Jana committed
310
311
312
    return QSize(width, height);
}

313
QWidget *QtMessageLogItemDelegate::createEditor(QWidget *parent,
Aurindam Jana's avatar
Aurindam Jana committed
314
315
316
317
                                    const QStyleOptionViewItem &/*option*/,
                                    const QModelIndex &index) const

{
318
    QtMessageLogEditor *editor = new QtMessageLogEditor(index, parent);
Aurindam Jana's avatar
Aurindam Jana committed
319
320
321
322
323
    connect(editor, SIGNAL(editingFinished()),
            this, SLOT(commitAndCloseEditor()));
    return editor;
}

324
void QtMessageLogItemDelegate::setEditorData(QWidget *editor,
Aurindam Jana's avatar
Aurindam Jana committed
325
326
                                 const QModelIndex &index) const
{
327
    QtMessageLogEditor *edtr = qobject_cast<QtMessageLogEditor *>(editor);
Aurindam Jana's avatar
Aurindam Jana committed
328
329
330
    edtr->insertPlainText(index.data(Qt::DisplayRole).toString());
}

331
void QtMessageLogItemDelegate::setModelData(QWidget *editor,
Aurindam Jana's avatar
Aurindam Jana committed
332
333
334
                                       QAbstractItemModel *model,
                                const QModelIndex &index) const
{
335
    QtMessageLogEditor *edtr = qobject_cast<QtMessageLogEditor *>(editor);
Aurindam Jana's avatar
Aurindam Jana committed
336
    model->setData(index, edtr->getCurrentScript(), Qt::DisplayRole);
337
    model->setData(index, QtMessageLogHandler::InputType, QtMessageLogHandler::TypeRole);
Aurindam Jana's avatar
Aurindam Jana committed
338
339
}

340
void QtMessageLogItemDelegate::updateEditorGeometry(QWidget *editor,
Aurindam Jana's avatar
Aurindam Jana committed
341
342
343
344
345
346
347
348
                                               const QStyleOptionViewItem &option,
                                               const QModelIndex &/*index*/) const
{
    QStyleOptionViewItemV4 opt = option;
    editor->setGeometry(QRect(opt.rect.x(), opt.rect.top(),
                              opt.rect.width(), opt.rect.bottom()));
}

349
void QtMessageLogItemDelegate::currentChanged(const QModelIndex &current,
Aurindam Jana's avatar
Aurindam Jana committed
350
351
352
353
354
355
                                         const QModelIndex &previous)
{
    emit sizeHintChanged(current);
    emit sizeHintChanged(previous);
}

356
void QtMessageLogItemDelegate::commitAndCloseEditor()
Aurindam Jana's avatar
Aurindam Jana committed
357
{
358
    QtMessageLogEditor *editor = qobject_cast<QtMessageLogEditor *>(sender());
Aurindam Jana's avatar
Aurindam Jana committed
359
360
361
362
    emit commitData(editor);
    emit closeEditor(editor);
}

363
364
qreal QtMessageLogItemDelegate::layoutText(QTextLayout &tl, int width,
                                           bool *showFileLineInfo) const
Aurindam Jana's avatar
Aurindam Jana committed
365
366
367
368
369
370
371
372
373
374
{
    qreal height = 0;
    tl.beginLayout();
    while (true) {
        QTextLine line = tl.createLine();

        if (!line.isValid())
            break;
        line.setLeadingIncluded(true);
        line.setLineWidth(width);
375
376
        if (width < line.naturalTextWidth() && showFileLineInfo)
            *showFileLineInfo = false;
Aurindam Jana's avatar
Aurindam Jana committed
377
378
379
380
381
382
383
        line.setPosition(QPoint(0, height));
        height += line.height();
    }
    tl.endLayout();
    return height;
}

384
385
386
387
388
void QtMessageLogItemDelegate::setItemModel(QtMessageLogHandler *model)
{
    m_itemModel = model;
}

Aurindam Jana's avatar
Aurindam Jana committed
389
390
} //Internal
} //Debugger