LogMessageDelegate.cpp
Go to the documentation of this file.
1/*
2* This file is part of ArmarX.
3*
4* ArmarX is free software; you can redistribute it and/or modify
5* it under the terms of the GNU General Public License version 2 as
6* published by the Free Software Foundation.
7*
8* ArmarX is distributed in the hope that it will be useful, but
9* WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details.
12*
13* You should have received a copy of the GNU General Public License
14* along with this program. If not, see <http://www.gnu.org/licenses/>.
15*
16* @package ArmarX::
17* @author Mirko Waechter ( mirko.waechter at kit dot edu)
18* @date 2012
19* @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20* GNU General Public License
21*/
22
23#include "LogMessageDelegate.h"
24
25#include <algorithm>
26#include <iostream>
27
28#include <QFontMetrics>
29#include <QPainter>
30#include <QPalette>
31#include <QStringList>
32#include <QTableView>
33#include <QTextEdit>
34#include <QtGlobal>
35
36#include "LogTableModel.h"
37
38namespace armarx
39{
40 namespace
41 {
42 //! Width of \p text in pixels.
43 //!
44 //! QFontMetrics::horizontalAdvance() was added in Qt 5.11; width() is the older
45 //! spelling of the same thing and is only deprecated from 5.11 onwards. Ubuntu
46 //! 18.04 ships Qt 5.9, so each version has to use its own spelling: width() does
47 //! not compile away the deprecation warning on new Qt, and horizontalAdvance()
48 //! does not exist on old Qt.
49 int
50 advanceWidth(const QFontMetrics& metrics, const QString& text)
51 {
52#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
53 return metrics.horizontalAdvance(text);
54#else
55 return metrics.width(text);
56#endif
57 }
58 } // namespace
59
60 LogMessageDelegate::LogMessageDelegate(QObject* parent) : QStyledItemDelegate(parent)
61 {
62 // _lineEdit = new QLabel();
63 // _lineEdit->setWordWrap(true);
64 }
65
67 {
68 // delete _lineEdit;
69 }
70
71 //void LogMessageDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
72 //{
73
74 // QString logMessageStr = index.data().toString();
75 // _lineEdit->setText(logMessageStr);
76 // int lines = std::count(logMessageStr.begin(), logMessageStr.end(), '\n')+1;
77 // if(lines > 5)
78 // lines = 5;
79 // QRect rect = option.rect;
80
81 // rect.setHeight(15*lines);
82 // _lineEdit->resize(rect.size());
83 // std::cout << "lines:" << lines << "old height: " << option.rect.height() << " new: " << rect.height() << " lineedit height: " << _lineEdit->height() << std::endl;
84 // // Change background color if the item is selected
85 // QPalette pal;
86 // if ((option.state & QStyle::State_Selected) == QStyle::State_Selected)
87 // {
88 // pal.setBrush(QPalette::Window, QBrush(QColor(Qt::lightGray)));
89 // }
90 // else
91 // {
92 // pal.setBrush(QPalette::Window, QBrush(QColor(Qt::transparent)));
93 // }
94 // _lineEdit->setPalette(pal);
95
96 // // Paint the widget now.
97 // painter->save();
98 // painter->translate(option.rect.topLeft());
99 // _lineEdit->render(painter);
100 // painter->restore();
101 //}
102
103 //QSize LogMessageDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
104 //{
105 // const int width = 350;
106
107 // const int height = 200;
108 // std::cout << "height: " << _lineEdit->height() << std::endl;
109 // return QSize(width, _lineEdit->height());
110 //}
111
112 QWidget*
114 const QStyleOptionViewItem& option,
115 const QModelIndex& index) const
116 {
117 if (index.column() == 4)
118 {
119 // QTableView* tableView = qobject_cast<QTableView*>(parent);
120 QTextEdit* editor = new QTextEdit(parent);
121 // editor->resize(100,100);
122 editor->adjustSize();
123 editor->setReadOnly(true);
124 // connect(this, SIGNAL(resizeRow(int)),
125 // tableView, SLOT(resizeRowToContents(int)));
126 // emit resizeRow(index.column());
127 // tableView->resizeRowToContents(index.column());
128 return editor;
129 }
130 else
131 {
132 return QStyledItemDelegate::createEditor(parent, option, index);
133 }
134 }
135
136 void
137 LogMessageDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
138 {
139 QTextEdit* textEdit = qobject_cast<QTextEdit*>(editor);
140 if (!textEdit)
141 {
142 QStyledItemDelegate::setEditorData(editor, index);
143 return;
144 }
145 textEdit->setText(index.data((int)LogTableModel::UserRoles::FullMsgRole).toString());
146 }
147
148 void
150 const QStyleOptionViewItem& option,
151 const QModelIndex& index) const
152 {
153 QTextEdit* textEdit = qobject_cast<QTextEdit*>(editor);
154 if (!textEdit)
155 {
156 QStyledItemDelegate::updateEditorGeometry(editor, option, index);
157 return;
158 }
159
160 // Anchor the overlay at the cell and size it to the message content, clamped to the
161 // parent viewport so it never overflows the widget.
162 //
163 // The size is derived from the message *text*, never from the editor's current
164 // document layout: document()->size() reports the layout at the editor's present
165 // width, so using it here would add the padding below on top of the width set by
166 // the previous call. Since this runs on every updateEditorGeometries() -- i.e.
167 // whenever rows are appended -- that made the overlay creep to the right as new
168 // messages arrived. Everything below depends only on the text, the font and the
169 // cell rect, so repeated calls produce the same geometry.
170 const QString text =
171 index.data(static_cast<int>(LogTableModel::UserRoles::FullMsgRole)).toString();
172 const QStringList lines = text.split('\n');
173 const QFontMetrics metrics(textEdit->document()->defaultFont());
174
175 QRect r = option.rect;
176 const QWidget* parent = editor->parentWidget();
177 // Anything past the parent's width is clamped away below, so stop measuring there:
178 // a backtrace can run to well over a hundred lines.
179 const int maxUsefulWidth = parent ? parent->width() : r.width() * 4;
180
181 int textWidth = 0;
182 for (const QString& line : lines)
183 {
184 textWidth = std::max(textWidth, advanceWidth(metrics, line));
185 if (textWidth >= maxUsefulWidth)
186 {
187 break;
188 }
189 }
190
191 // Frame and document margin are independent of the editor's width.
192 const int padding = 2 * textEdit->frameWidth() +
193 2 * static_cast<int>(textEdit->document()->documentMargin());
194
195 int width = std::max(r.width(), textWidth + padding);
196 int height = std::max(r.height(), lines.size() * metrics.lineSpacing() + padding);
197
198 if (parent)
199 {
200 width = std::min(width, parent->width() - r.x());
201 height = std::min(height, parent->height() - r.y());
202 }
203 r.setSize(QSize(width, height));
204 editor->setGeometry(r);
205 }
206
207 void
209 {
210 emit closeEditor(qobject_cast<QWidget*>(sender()));
211 }
212} // namespace armarx
uint8_t index
#define option(type, fn)
LogMessageDelegate(QObject *parent=0)
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override
QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override
void setEditorData(QWidget *editor, const QModelIndex &index) const override
This file offers overloads of toIce() and fromIce() functions for STL container types.