1 /*=========================================================================
2
3 Library: CTK
4
5 Copyright (c) Kitware Inc.
6
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
10
11 http://www.apache.org/licenses/LICENSE-2.0.txt
12
13 Unless required by applicable law or agreed to in writing, software
14 distributed under the License is distributed on an "AS IS" BASIS,
15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 See the License for the specific language governing permissions and
17 limitations under the License.
18
19 =========================================================================*/
20
21 // Qt includes
22 #include <QDebug>
23 #include <QAbstractItemModel>
24 #include <QStandardItemModel>
25
26 // CTK includes
27 #include "ctkErrorLogWidget.h"
28 #include "ui_ctkErrorLogWidget.h"
29 #include <ctkErrorLogModel.h>
30
31 class ctkErrorLogWidgetPrivate : public Ui_ctkErrorLogWidget
32 {
33 Q_DECLARE_PUBLIC(ctkErrorLogWidget);
34 protected:
35 ctkErrorLogWidget* const q_ptr;
36 public:
37 typedef ctkErrorLogWidgetPrivate Self;
38 ctkErrorLogWidgetPrivate(ctkErrorLogWidget& object);
39
40 ctkErrorLogLevel::LogLevels ErrorButtonFilter;
41 ctkErrorLogLevel::LogLevels WarningButtonFilter;
42 ctkErrorLogLevel::LogLevels InfoButtonFilter;
43
44 void init();
45
46 QSharedPointer<QItemSelectionModel> SelectionModel;
47 };
48
49 // --------------------------------------------------------------------------
50 // ctkErrorLogWidgetPrivate methods
51
52 // --------------------------------------------------------------------------
ctkErrorLogWidgetPrivate(ctkErrorLogWidget & object)53 ctkErrorLogWidgetPrivate::ctkErrorLogWidgetPrivate(ctkErrorLogWidget& object)
54 : q_ptr(&object)
55 {
56 this->ErrorButtonFilter = ctkErrorLogLevel::Error | ctkErrorLogLevel::Critical | ctkErrorLogLevel::Fatal;
57 this->WarningButtonFilter = ctkErrorLogLevel::Warning;
58 this->InfoButtonFilter = ctkErrorLogLevel::Info | ctkErrorLogLevel::Debug | ctkErrorLogLevel::Trace | ctkErrorLogLevel::Status;
59 }
60
61 // --------------------------------------------------------------------------
init()62 void ctkErrorLogWidgetPrivate::init()
63 {
64 Q_Q(ctkErrorLogWidget);
65
66 // this->ShowAllEntryButton->setIcon();
67 this->ShowErrorEntryButton->setIcon(q->style()->standardIcon(QStyle::SP_MessageBoxCritical));
68 this->ShowWarningEntryButton->setIcon(q->style()->standardIcon(QStyle::SP_MessageBoxWarning));
69 this->ShowInfoEntryButton->setIcon(q->style()->standardIcon(QStyle::SP_MessageBoxInformation));
70 this->ClearButton->setIcon(q->style()->standardIcon(QStyle::SP_DialogDiscardButton));
71
72 QObject::connect(this->ShowAllEntryButton, SIGNAL(clicked()),
73 q, SLOT(setAllEntriesVisible()));
74
75 QObject::connect(this->ShowErrorEntryButton, SIGNAL(clicked(bool)),
76 q, SLOT(setErrorEntriesVisible(bool)));
77
78 QObject::connect(this->ShowWarningEntryButton, SIGNAL(clicked(bool)),
79 q, SLOT(setWarningEntriesVisible(bool)));
80
81 QObject::connect(this->ShowInfoEntryButton, SIGNAL(clicked(bool)),
82 q, SLOT(setInfoEntriesVisible(bool)));
83
84 QObject::connect(this->ClearButton, SIGNAL(clicked()),
85 q, SLOT(removeEntries()));
86 }
87
88 // --------------------------------------------------------------------------
89 // ctkErrorLogWidget methods
90
91 //------------------------------------------------------------------------------
ctkErrorLogWidget(QWidget * newParent)92 ctkErrorLogWidget::ctkErrorLogWidget(QWidget * newParent)
93 : Superclass(newParent)
94 , d_ptr(new ctkErrorLogWidgetPrivate(*this))
95 {
96 Q_D(ctkErrorLogWidget);
97
98 d->setupUi(this);
99 d->init();
100
101 this->setErrorLogModel(new ctkErrorLogModel(d->ErrorLogTableView));
102 }
103
104 //------------------------------------------------------------------------------
~ctkErrorLogWidget()105 ctkErrorLogWidget::~ctkErrorLogWidget()
106 {
107 }
108
109 //------------------------------------------------------------------------------
errorLogModel() const110 ctkErrorLogModel* ctkErrorLogWidget::errorLogModel()const
111 {
112 Q_D(const ctkErrorLogWidget);
113 QAbstractItemModel* model = d->ErrorLogTableView->model();
114 ctkErrorLogModel * errorLogModel = qobject_cast<ctkErrorLogModel*>(model);
115 Q_ASSERT(model ? errorLogModel != 0 : true);
116 return errorLogModel;
117 }
118
119 //------------------------------------------------------------------------------
setErrorLogModel(ctkErrorLogModel * newErrorLogModel)120 void ctkErrorLogWidget::setErrorLogModel(ctkErrorLogModel * newErrorLogModel)
121 {
122 Q_D(ctkErrorLogWidget);
123
124 if (newErrorLogModel == this->errorLogModel())
125 {
126 return;
127 }
128
129 if (this->errorLogModel())
130 {
131 disconnect(this->errorLogModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
132 this, SLOT(onRowsInserted(QModelIndex,int,int)));
133
134 disconnect(this->errorLogModel(), SIGNAL(logLevelFilterChanged()),
135 this, SLOT(onLogLevelFilterChanged()));
136
137 disconnect(d->SelectionModel.data(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
138 this, SLOT(onSelectionChanged(QItemSelection,QItemSelection)));
139
140 d->SelectionModel.clear();
141 }
142
143 d->ErrorLogTableView->setModel(newErrorLogModel);
144
145 if (newErrorLogModel)
146 {
147 connect(this->errorLogModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
148 this, SLOT(onRowsInserted(QModelIndex,int,int)));
149
150 connect(this->errorLogModel(), SIGNAL(logLevelFilterChanged()),
151 this, SLOT(onLogLevelFilterChanged()));
152
153 ctkErrorLogLevel::LogLevels logLevelFilter = newErrorLogModel->logLevelFilter();
154 this->setErrorEntriesVisible(logLevelFilter & d->ErrorButtonFilter);
155 this->setWarningEntriesVisible(logLevelFilter & d->WarningButtonFilter);
156 this->setInfoEntriesVisible(logLevelFilter & d->InfoButtonFilter);
157 this->errorLogModel()->filterEntry(logLevelFilter & ctkErrorLogLevel::Unknown);
158
159 // Setup selection model
160 d->SelectionModel = QSharedPointer<QItemSelectionModel>(new QItemSelectionModel(this->errorLogModel()));
161 d->SelectionModel->reset();
162
163 connect(d->SelectionModel.data(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
164 this, SLOT(onSelectionChanged(QItemSelection,QItemSelection)));
165
166 d->ErrorLogTableView->setSelectionModel(d->SelectionModel.data());
167
168 // Resize time column only if there are rows
169 if (this->errorLogModel()->rowCount() > 0)
170 {
171 d->ErrorLogTableView->resizeColumnToContents(ctkErrorLogModel::TimeColumn);
172 }
173 }
174 else
175 {
176 this->setAllEntriesVisible(0);
177 }
178
179 d->ErrorLogTableView->setColumnHidden(ctkErrorLogModel::ThreadIdColumn, true);
180 }
181
182 // --------------------------------------------------------------------------
setColumnHidden(int columnId,bool hidden) const183 void ctkErrorLogWidget::setColumnHidden(int columnId, bool hidden) const
184 {
185 Q_D(const ctkErrorLogWidget);
186 d->ErrorLogTableView->setColumnHidden(columnId, hidden);
187 }
188
189 // --------------------------------------------------------------------------
setAllEntriesVisible(bool visibility)190 void ctkErrorLogWidget::setAllEntriesVisible(bool visibility)
191 {
192 this->setErrorEntriesVisible(visibility);
193 this->setWarningEntriesVisible(visibility);
194 this->setInfoEntriesVisible(visibility);
195 this->setUnknownEntriesVisible(visibility);
196 }
197
198 // --------------------------------------------------------------------------
setErrorEntriesVisible(bool visibility)199 void ctkErrorLogWidget::setErrorEntriesVisible(bool visibility)
200 {
201 Q_D(ctkErrorLogWidget);
202 if (!this->errorLogModel())
203 {
204 return;
205 }
206 this->errorLogModel()->filterEntry(d->ErrorButtonFilter, /* disableFilter= */ !visibility);
207 }
208
209 // --------------------------------------------------------------------------
setWarningEntriesVisible(bool visibility)210 void ctkErrorLogWidget::setWarningEntriesVisible(bool visibility)
211 {
212 Q_D(ctkErrorLogWidget);
213 if (!this->errorLogModel())
214 {
215 return;
216 }
217 this->errorLogModel()->filterEntry(d->WarningButtonFilter, /* disableFilter= */ !visibility);
218 }
219
220 // --------------------------------------------------------------------------
setInfoEntriesVisible(bool visibility)221 void ctkErrorLogWidget::setInfoEntriesVisible(bool visibility)
222 {
223 Q_D(ctkErrorLogWidget);
224 if (!this->errorLogModel())
225 {
226 return;
227 }
228 this->errorLogModel()->filterEntry(d->InfoButtonFilter, /* disableFilter= */ !visibility);
229 }
230
231 // --------------------------------------------------------------------------
setUnknownEntriesVisible(bool visibility)232 void ctkErrorLogWidget::setUnknownEntriesVisible(bool visibility)
233 {
234 if (!this->errorLogModel())
235 {
236 return;
237 }
238 this->errorLogModel()->filterEntry(ctkErrorLogLevel::Unknown,
239 /* disableFilter= */ !visibility);
240 }
241
242 // --------------------------------------------------------------------------
onRowsInserted(const QModelIndex &,int,int)243 void ctkErrorLogWidget::onRowsInserted(const QModelIndex &/*parent*/, int /*first*/, int /*last*/)
244 {
245 Q_D(ctkErrorLogWidget);
246 if (d->ErrorLogTableView->model()->rowCount() == 1)
247 {
248 // For performance reason, resize first column only when first entry is added
249 d->ErrorLogTableView->resizeColumnToContents(ctkErrorLogModel::TimeColumn);
250 }
251 }
252
253 // --------------------------------------------------------------------------
onLogLevelFilterChanged()254 void ctkErrorLogWidget::onLogLevelFilterChanged()
255 {
256 Q_D(ctkErrorLogWidget);
257 Q_ASSERT(this->errorLogModel());
258 ctkErrorLogLevel::LogLevels logLevelFilter = this->errorLogModel()->logLevelFilter();
259 d->ShowErrorEntryButton->setChecked(logLevelFilter & d->ErrorButtonFilter);
260 d->ShowWarningEntryButton->setChecked(logLevelFilter & d->WarningButtonFilter);
261 d->ShowInfoEntryButton->setChecked(logLevelFilter & d->InfoButtonFilter);
262 }
263
264 // --------------------------------------------------------------------------
removeEntries()265 void ctkErrorLogWidget::removeEntries()
266 {
267 Q_ASSERT(this->errorLogModel());
268 this->errorLogModel()->clear();
269 }
270
271 // --------------------------------------------------------------------------
onSelectionChanged(const QItemSelection & selected,const QItemSelection & deselected)272 void ctkErrorLogWidget::onSelectionChanged(const QItemSelection & selected,
273 const QItemSelection & deselected)
274 {
275 // QTime start = QTime::currentTime();
276
277 Q_D(ctkErrorLogWidget);
278 Q_UNUSED(selected);
279 Q_UNUSED(deselected);
280
281 QModelIndexList selectedRows =
282 d->SelectionModel->selectedRows(ctkErrorLogModel::DescriptionColumn);
283
284 qSort(selectedRows.begin(), selectedRows.end());
285
286 QStringList descriptions;
287
288 foreach(const QModelIndex& index, selectedRows)
289 {
290 descriptions << index.data(ctkErrorLogModel::DescriptionTextRole).toString();
291 }
292
293 d->ErrorLogDescription->setText(descriptions.join("\n"));
294
295 // fprintf(stdout, "onSelectionChanged: %d\n", start.msecsTo(QTime::currentTime()));
296 }
297