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