LogTable.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#include "LogTable.h"
23
24#include <filesystem>
25
26#include <QApplication>
27#include <QHeaderView>
28#include <QScrollBar>
29#include <QTimer>
30
31#include "LogMessageDelegate.h"
32#include "LogTableModel.h"
33
34namespace armarx
35{
36#define MAX_BUFFER_SIZE 10000
37#define BUFFER_SIZE_FACTOR 1.3
38
39 LogTable::LogTable(QWidget* parent) :
40 QTableView(parent), newMessageCount(0), maxNewLogLevelType(eUNDEFINED)
41 {
42 autoscrollActive = true;
44
45 this->setVerticalScrollMode(ScrollMode::ScrollPerPixel);
46
47 setObjectName(QString::fromUtf8("tableLog"));
48 QSizePolicy sizePolicy2(QSizePolicy::Expanding, QSizePolicy::Expanding);
49 sizePolicy2.setHorizontalStretch(10);
50 sizePolicy2.setVerticalStretch(10);
51 sizePolicy2.setHeightForWidth(sizePolicy().hasHeightForWidth());
52 setSizePolicy(sizePolicy2);
53 setSizeIncrement(QSize(1, 0));
54 setEditTriggers(QAbstractItemView::DoubleClicked); //QAbstractItemView::NoEditTriggers
55 setAlternatingRowColors(true);
56 setShowGrid(true);
57 setGridStyle(Qt::SolidLine);
58 setSortingEnabled(false);
59 setWordWrap(true);
60 setCornerButtonEnabled(true);
61
62 setSelectionMode(QAbstractItemView::SingleSelection);
63 setSelectionBehavior(QAbstractItemView::SelectRows);
64
65 horizontalHeader()->setVisible(true);
66 horizontalHeader()->setCascadingSectionResizes(true);
67 horizontalHeader()->setDefaultSectionSize(100);
68 horizontalHeader()->setMinimumSectionSize(20);
69 horizontalHeader()->setStretchLastSection(true);
70 verticalHeader()->setVisible(false);
71 verticalHeader()->setDefaultSectionSize(20);
72
73 // verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
74
75 setModel(new LogTableModel(this));
76 //connect(model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(dataChanged(QModelIndex,QModelIndex)));
77 setColumnWidth(0, 90);
78 setColumnWidth(1, 90);
79 setColumnWidth(2, 90);
80 setColumnWidth(3, 60);
81 setColumnWidth(4, 700);
82 setColumnWidth(5, 150);
83 setColumnWidth(6, 200);
84 hideColumn(7);
85
86 QFont font;
87 font.setPointSize(8);
88 setFont(font);
89
90
91 setItemDelegateForColumn(getModel()->getColumn(ARMARX_LOG_MESSAGESTR),
92 new LogMessageDelegate());
93
94 QAbstractItemModel* absmodel = qobject_cast<QAbstractItemModel*>(model());
95 connect(absmodel,
96 SIGNAL(rowsAboutToBeInserted(QModelIndex, int, int)),
97 this,
98 SLOT(checkAutoScroll(QModelIndex, int, int)));
99 connect(
100 this, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(doubleClickOnCell(QModelIndex)));
101 connect(absmodel,
102 SIGNAL(dataChanged(QModelIndex, QModelIndex)),
103 this,
104 SLOT(itemsAdded(QModelIndex, QModelIndex)));
105 connect(verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(checkAutoScroll()));
106
107 // connect(this, SIGNAL(scrollToEnd()), this, SLOT(scrollToBottom()));
108 }
109
111 {
112 }
113
114 QString
116 {
117 return currentLiveFilter;
118 }
119
120 void
121 LogTable::liveFilterRow(const QString& filterStr, int row)
122 {
123 LogTableModel* logModel = getModel();
124 bool contains = logModel->rowContainsString(row, filterStr);
125 if (!isRowHidden(row) && !contains)
126 {
127 setRowHidden(row, true);
128 }
129 else if (isRowHidden(row) && contains)
130 {
131 setRowHidden(row, false);
132 }
133 }
134
135 void
136 LogTable::liveFilter(const QString& filterStr, int startRow)
137 {
138 LogTableModel* logModel = getModel();
139 currentLiveFilter = filterStr;
140 if (filterStr.length() && filterStr.contains(lastLiveFilter))
141 {
142 // incremental filter - Only remove not fitting entries
143 int rowCount = model()->rowCount();
144
145 for (int i = startRow; i < rowCount; i++)
146 {
147 if (!isRowHidden(i) && !logModel->rowContainsString(i, filterStr))
148 {
149 setRowHidden(i, true);
150 }
151 if (i % 1000 == 0)
152 {
153 qApp->processEvents();
154 }
155 if (filterStr != currentLiveFilter)
156 {
157 break; // filterstring already changed again -> cancel
158 }
159 }
160 }
161 else
162 {
163 // filter from scratch
164 // clear();
165 // setRowCount(0);
166 // QList<QTableWidgetItem*>results = findItems(filterStr,Qt::MatchContains);
167 // foreach(QTableWidgetItem*item, results)
168 // {
169 // if(applyFilters(item))
170 // item->
171 // }
172 int rowCount = model()->rowCount();
173
174 for (int i = startRow; i < rowCount; i++)
175 {
176 if (isRowHidden(i))
177 {
178 if (logModel->rowContainsString(i, filterStr))
179 {
180 setRowHidden(i, false);
181 }
182 }
183 else if (!logModel->rowContainsString(i, filterStr))
184 {
185 setRowHidden(i, true);
186 }
187 if (i % 1000 == 0)
188 {
189 qApp->processEvents();
190 }
191 if (filterStr != currentLiveFilter)
192 {
193 break; // filterstring already changed again -> cancel
194 }
195 }
196
197 // std::cout << "logBuffer: " << logBuffer.size() << std::endl;
198 // for(unsigned int i=0; i < logBuffer.size(); i++)
199 // {
200 // if(msgContainsString(logBuffer[i], filterStr) && applyFilters(logBuffer[i]) )
201 // addEntry(logBuffer[i], true);
202 // }
203 }
204
205 lastLiveFilter = filterStr;
206 }
207
208 bool
209 LogTable::liveSearch(const QString& search)
210 {
211 getModel()->search(search);
212 // scrollToBottom();
213 clearSelection();
214 return selectNextSearchResult(true, true);
215 }
216
217 void
219 {
220 // ARMARX_WARNING_S << "LiveFilterReseted";
222 lastLiveFilter = "";
223 liveFilter("");
224 }
225
226 void
228 {
229 getModel()->search("");
230 // repaint();
231 }
232
235 {
236 return dynamic_cast<LogTableModel*>(model());
237 }
238
239 bool
240 LogTable::checkAutoScroll(const QModelIndex& parent, int start, int end)
241 {
242 return checkAutoScroll();
243 }
244
245 bool
247 {
248 if (verticalScrollBar()->value() == verticalScrollBar()->maximum())
249 {
250 autoscrollActive = true;
251 }
252 else
253 {
254 autoscrollActive = false;
255 }
256
257
258 return autoscrollActive;
259 }
260
261 void
262 LogTable::itemsAdded(QModelIndex leftTop, QModelIndex bottomRight)
263 {
264 }
265
266 void
267 LogTable::showEvent(QShowEvent* event)
268 {
270
271 // verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
272 // resizeRowsToContents();
273 // verticalHeader()->setResizeMode(QHeaderView::Fixed);
275 {
276 QTimer::singleShot(
277 50,
278 this,
279 SLOT(
280 scrollToBottom())); // delayed because something is inserting one line after this function or something
281 }
282 }
283
284 void
286 {
287 if (verticalScrollBar()->value() == verticalScrollBar()->maximum())
288 {
289 autoscrollActive = true;
290 }
291 else
292 {
293 autoscrollActive = false;
294 }
295 }
296
297 void
298 LogTable::rowsInserted(const QModelIndex& parent, int start, int end)
299 {
300 auto logModel = getModel();
301 auto fontHeight = QFontMetrics(font()).height();
302 // ARMARX_INFO << "Adjusting height for " << start << " to " << end << " count: " << logModel->rowCount();
303 for (int i = start; i <= end && i < logModel->rowCount(); ++i)
304 {
305 // auto stringRows = armarx::Split(logModel->getLogEntry(i).what, "\n", true, true);
306 auto index = model()->index(i, 4, parent);
307 auto stringRows = model()->data(index).toString().split("\n").size();
308 if (stringRows > 1)
309 {
310 setRowHeight(i, fontHeight * stringRows + 1);
311 }
312 }
313
314 if (!isVisible())
315 {
316 newMessageCount += end - start + 1;
317
319 {
321 }
322
323 // LogTableModel * logModel = getModel();
324 // if(start> end)
325 // std::swap(start, end);
326 // if(lastLiveFilter.length() > 0)
327 // {
328 // for (int i = start; i <= end; ++i) {
329 // if(!logModel->rowContainsString(i, lastLiveFilter))
330 // setRowHidden(i, true);
331 // }
332 // }
333 }
334 // resizeRowsToContents();
335 else
336 {
337 // verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
338
339 // for(int i = start; i < end; i++)
340 // resizeRowToContents(i);
341 // verticalHeader()->setResizeMode(QHeaderView::Fixed);
342 }
343
345 {
346 scrollToBottom();
347 }
348 }
349
350 void
351 LogTable::rowsAboutToBeRemoved(const QModelIndex& parent, int start, int end)
352 {
353 if (end - start >= model()->rowCount() - 1)
354 {
356 }
357 }
358
359 bool
360 LogTable::selectNextSearchResult(bool backwards, bool keepSelectionIfPossible)
361 {
362
363 int checkCounter = 0; // just a counter for avoiding inifite loops
364 int tempSelectedSearchIndex = indexAt(QPoint(10, 10)).row();
365
366 if (selectedIndexes().size() > 0)
367 {
368 tempSelectedSearchIndex = selectedIndexes()[0].row();
369 }
370
371 int oldSelectedSearchIndex = tempSelectedSearchIndex;
372
373 do // search until we reach old line again
374 {
375
376 if ((tempSelectedSearchIndex != oldSelectedSearchIndex || keepSelectionIfPossible) &&
377 getModel()->rowContainsString(tempSelectedSearchIndex,
378 getModel()->getCurrentSearchStr()))
379 {
380 selectRow(tempSelectedSearchIndex);
381 return true;
382 }
383
384 if (backwards)
385 {
386 tempSelectedSearchIndex--;
387 }
388 else
389 {
390 tempSelectedSearchIndex++;
391 }
392
393 if (tempSelectedSearchIndex >= model()->rowCount())
394 {
395 tempSelectedSearchIndex = 0;
396 }
397
398 if (tempSelectedSearchIndex < 0)
399 {
400 tempSelectedSearchIndex = model()->rowCount() - 1;
401 }
402
403
404 checkCounter++;
405
406 if (checkCounter > model()->rowCount())
407 {
408 break;
409 }
410 } while (tempSelectedSearchIndex != oldSelectedSearchIndex);
411
412 return false;
413 }
414
415 void
417 {
418 if (index.column() != getModel()->getColumn(ARMARX_LOG_FILESTR))
419 {
420 return;
421 }
422
423 QString fileWithLineNumber = model()->data(index).toString();
424 std::string file = fileWithLineNumber.toStdString();
425 file.erase(file.rfind(':'));
426 std::string line = fileWithLineNumber.toStdString();
427 line = line.erase(0, line.rfind(':') + 1);
428
429 if (!std::filesystem::exists(file))
430 {
431 ARMARX_INFO << "File '" << file << "' does not exists - cannot open it.";
432 return;
433 }
434
435 fileOpener.openFileWithDefaultEditor(file, atoi(line.c_str()));
436 // std::string command = "qtcreator -client " + fileWithLineNumber.toStdString() + "&";
437 // if(system(command.c_str())){}
438 }
439} // namespace armarx
uint8_t index
#define ARMARX_LOG_FILESTR
Definition LogTable.h:45
#define ARMARX_LOG_MESSAGESTR
Definition LogTable.h:44
MessageType getMaxNewLogLevelType()
bool rowContainsString(int row, const QString &searchStr) const
void search(const QString &searchStr)
MessageType getMaxNewLogLevelType()
Definition LogTable.h:80
void liveFilter(const QString &search, int startRow=0)
Definition LogTable.cpp:136
void doubleClickOnCell(const QModelIndex &index)
Definition LogTable.cpp:416
bool selectNextSearchResult(bool backwards=true, bool keepSelectionIfPossible=false)
Definition LogTable.cpp:360
void showEvent(QShowEvent *event) override
Definition LogTable.cpp:267
bool autoscrollActive
Definition LogTable.h:110
QString lastLiveFilter
Definition LogTable.h:115
QString currentLiveFilter
Definition LogTable.h:115
void liveFilterRow(const QString &filterStr, int row)
Definition LogTable.cpp:121
bool liveSearch(const QString &search)
Definition LogTable.cpp:209
LogTableModel * getModel()
Definition LogTable.cpp:234
~LogTable() override
Definition LogTable.cpp:110
void resetLiveFilter()
Definition LogTable.cpp:218
MessageType maxNewLogLevelType
Definition LogTable.h:112
void hideEvent(QHideEvent *) override
Definition LogTable.cpp:285
QString getCurrentLiveFilter() const
Definition LogTable.cpp:115
LogTable(QWidget *parent=0)
Definition LogTable.cpp:39
bool checkAutoScroll(const QModelIndex &parent, int start, int end)
Definition LogTable.cpp:240
void itemsAdded(QModelIndex leftTop, QModelIndex bottomRight)
Definition LogTable.cpp:262
void resetLiveSearch()
Definition LogTable.cpp:227
void resetNewMessageCount()
Definition LogTable.h:60
int selectedSearchIndex
Definition LogTable.h:116
EditorFileOpener fileOpener
Definition LogTable.h:117
void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) override
Definition LogTable.cpp:351
void rowsInserted(const QModelIndex &parent, int start, int end) override
Definition LogTable.cpp:298
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
This file offers overloads of toIce() and fromIce() functions for STL container types.