Developer Documentation

postProcessorWidget.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openflipper.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenFlipper. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41
42
43
44 #include <OpenFlipper/BasePlugin/PluginFunctions.hh>
45 #include <OpenFlipper/common/RendererInfo.hh>
46 #include <OpenFlipper/common/GlobalOptions.hh>
47
48 #include <QtWidgets>
49
50 #include "postProcessorWidget.hh"
51
52
53 PostProcessorDialog::PostProcessorDialog(QWidget *_parent)
54 : QDialog(_parent)
55 {
56 setupUi(this);
57
58 list->setContextMenuPolicy(Qt::CustomContextMenu);
59 activeList->setContextMenuPolicy(Qt::CustomContextMenu);
60
61 connect(closeButton, SIGNAL(clicked()), this, SLOT(accept()));
62 connect(list,SIGNAL(customContextMenuRequested(const QPoint&)),this,SLOT(slotContextMenuActivate(const QPoint&)));
63 connect(activeList,SIGNAL(customContextMenuRequested(const QPoint&)),this,SLOT(slotContextMenuDeactivate(const QPoint&)));
64 connect(activateButton,SIGNAL(clicked()),this,SLOT(slotActivatePostProcessor()));
65 connect(deactivateButton,SIGNAL(clicked()),this,SLOT(slotDeactivatePostProcessor()));
66 connect(upButton,SIGNAL(clicked()),this,SLOT(slotMoveUp()));
67 connect(downButton,SIGNAL(clicked()),this,SLOT(slotMoveDown()));
68 connect(saveButton,SIGNAL(clicked()),this,SLOT(slotSaveActive()));
69 connect(refreshButton,SIGNAL(clicked()), this,SLOT(refresh()));
70
71 //set icons
72 QString iconPath = OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator();
73
74 closeButton->setIcon( QIcon(iconPath + "window-close.png"));
75 saveButton->setIcon( QIcon(iconPath + "document-save.png"));
76 refreshButton->setIcon( QIcon(iconPath + "edit-redo.png"));
77
78 }
79
80 void PostProcessorDialog::closeEvent(QCloseEvent *_event)
81 {
82 _event->accept();
83 accept();
84 }
85
86 void PostProcessorDialog::showEvent ( QShowEvent * )
87 {
88 initWindow();
89 }
90
91 void PostProcessorDialog::initWindow()
92 {
93 currentExaminer_ = PluginFunctions::activeExaminer();
94 list->clear();
95 activeList->clear();
96 activeRowToRow_.clear();
97
98 //first, fill already activated processors in the right order
99 for (int i = 0; i < postProcessorManager().numActive(currentExaminer_); ++i)
100 {
101 unsigned int id = postProcessorManager().activeId(currentExaminer_, i);
102 activeRowToRow_.push_back(id);
103
104 QListWidgetItem *activeItem = new QListWidgetItem("");
105 activeList->addItem(activeItem);
106 QFrame* frame = createFrame(*postProcessorManager()[id]);
107 activeItem->setSizeHint(frame->sizeHint());
108 activeList->setItemWidget(activeItem,frame);
109 }
110
111 //list all available post processors (hidden, if active)
112 for ( unsigned int i = 0 ; i < postProcessorManager().available() ; ++i)
113 {
114
115 // Get and check post processor
116 PostProcessorInfo* processor = postProcessorManager()[i];
117 if ( ! processor )
118 continue;
119
120 QFrame* frame = createFrame(*processor);
121
122 QListWidgetItem *item = new QListWidgetItem("");
123 item->setSizeHint( frame->sizeHint() );
124
125 list->addItem(item);
126
127 list->setItemWidget(item, frame);
128
129 //is the postProcess active? if so, hide it
130 bool found = false;
131 for (std::vector<unsigned>::iterator iter = activeRowToRow_.begin(); iter != activeRowToRow_.end() && !found; ++iter)
132 found = (*iter == i);
133 if ( found )
134 list->setRowHidden(list->row(item),true);
135 }
136
137 }
138
139 void PostProcessorDialog::slotActivatePostProcessor()
140 {
141 QList<QListWidgetItem*> selectedItems = list->selectedItems();
142
143 for (int i=0; i < selectedItems.size(); ++i)
144 {
145 QListWidgetItem* item = selectedItems[i];
146 const int currentRow = list->row( item );
147
148 postProcessorManager().append( currentRow, currentExaminer_);
149
150 //disable in aviable list
151 item->setHidden(true);
152 item->setSelected(false);
153
154 //add to active list
155 QListWidgetItem *activeItem = new QListWidgetItem("");
156 activeList->addItem(activeItem);
157 activeItem->setSelected(true);
158
159 QFrame* frame = createFrame(*postProcessorManager()[currentRow]);
160 activeItem->setSizeHint( frame->sizeHint() );
161 activeList->setItemWidget(activeItem,frame);
162 activeRowToRow_.push_back(currentRow);
163 }
164
165 emit updateExaminer(currentExaminer_);
166
167 }
168
169 void PostProcessorDialog::slotDeactivatePostProcessor()
170 {
171 QList<QListWidgetItem*> selectedItems = activeList->selectedItems();
172
173 for (int i=0; i < selectedItems.size(); ++i)
174 {
175 QListWidgetItem* activeItem = selectedItems[i];
176
177 const unsigned chainPos = activeList->row(activeItem);
178 const unsigned activeID = activeRowToRow_[chainPos];
179 QListWidgetItem* item = list->item(activeID);
180
181 //remove postprocessor
182 postProcessorManager().remove(currentExaminer_, chainPos);
183
184 //enable in aviable list
185 item->setHidden(false);
186 item->setSelected(true);
187
188 //remove from active list
189 //update active row ids
190 for (unsigned i = chainPos; i < activeRowToRow_.size()-1; ++i)
191 activeRowToRow_[i] = activeRowToRow_[i+1];
192
193 //from qt doc: Items removed from a list widget will not be managed by Qt, and will need to be deleted manually.
194 activeItem = activeList->takeItem(activeList->row(activeItem));
195 delete activeItem;
196 }
197 activeRowToRow_.erase( activeRowToRow_.end()-selectedItems.size(), activeRowToRow_.end());
198
199 emit updateExaminer(currentExaminer_);
200 }
201
202 void PostProcessorDialog::slotMovePostProcessor(unsigned _from,unsigned _to)
203 {
204
205 if (_from >= static_cast<unsigned>(activeList->count()))
206 return;
207
208 if (_to >= static_cast<unsigned>(activeList->count()))
209 _to = activeList->count()-1;
210
211 if (_from == _to)
212 return;
213
214 //swap widget
215 QListWidgetItem* activeItem = activeList->takeItem(_from);
216 activeList->insertItem(_to,activeItem);
217 QFrame* frame = createFrame(*postProcessorManager()[activeRowToRow_[_from]]);
218 activeItem->setSizeHint(frame->sizeHint());
219 activeList->setItemWidget(activeItem,frame);
220 activeList->setItemSelected(activeItem,true);
221
222 //swap postprocessor
223 const int chainPos = _from;
224 const int activeID = activeRowToRow_[_from];
225 postProcessorManager().remove(currentExaminer_, chainPos);
226 postProcessorManager().insert(activeID,_to,currentExaminer_);
227
228 //swap active ID to current chain position map
229 int inc = (_from > _to)? -1: +1;
230 for(unsigned int currentRow = _from;currentRow != _to; currentRow += inc)
231 std::swap(activeRowToRow_[currentRow+inc],activeRowToRow_[currentRow]);
232
233 emit updateExaminer(currentExaminer_);
234 }
235
236
237 void PostProcessorDialog::slotContextMenuActivate(const QPoint& _point)
238 {
239 if (!list->count())
240 return;
241
242 QMenu *menu = new QMenu(list);
243 QAction* action = 0;
244
245 action = menu->addAction(tr("Activate"));
246 connect(action,SIGNAL(triggered(bool)),this,SLOT(slotActivatePostProcessor()));
247
248 menu->exec(list->mapToGlobal(_point),0);
249
250 }
251
252 void PostProcessorDialog::slotContextMenuDeactivate(const QPoint& _point)
253 {
254 if (!activeList->count())
255 return;
256
257 QMenu *menu = new QMenu(activeList);
258 QAction* action = 0;
259
260 action = menu->addAction(tr("Up"));
261 connect(action,SIGNAL(triggered(bool)),this,SLOT(slotMoveUp()));
262 action = menu->addAction(tr("Down"));
263 connect(action,SIGNAL(triggered(bool)),this,SLOT(slotMoveDown()));
264 action = menu->addAction(tr("Deactivate"));
265 connect(action,SIGNAL(triggered(bool)),this,SLOT(slotDeactivatePostProcessor()));
266
267 menu->exec(activeList->mapToGlobal(_point),0);
268
269 }
270
271 QFrame* PostProcessorDialog::createFrame(const PostProcessorInfo& _pPI)
272 {
273 QFrame* frame = new QFrame();
274 QHBoxLayout* hlayout = new QHBoxLayout;
275
276 QLabel* name = new QLabel( _pPI.name );
277 QFont font;
278 font.setBold(true);
279 font.setPointSize(10);
280 name->setFont(font);
281 QLabel* version = new QLabel( _pPI.version );
282 QPushButton* optionsButton = new QPushButton("Options");
283 hlayout->addWidget(name);
284 hlayout->addStretch();
285 hlayout->addWidget(version);
286
287 optionsButton->setEnabled(false);
288 if (_pPI.optionsAction != 0)
289 {
290 optionsButton->setEnabled(true);
291 connect(optionsButton,SIGNAL(clicked()),_pPI.optionsAction,SLOT(trigger()));
292 }
293
294 QVBoxLayout* vlayout = new QVBoxLayout;
295
296 QLabel* description = new QLabel( _pPI.description );
297
298 vlayout->addLayout(hlayout,20);
299
300 QHBoxLayout* optionsLayout = new QHBoxLayout();
301 vlayout->addLayout(optionsLayout);
302 optionsLayout->addWidget(description);
303 optionsLayout->addStretch();
304 optionsLayout->addWidget(optionsButton);
305
306 frame->setLayout(vlayout);
307 frame->adjustSize();
308
309 return frame;
310 }
311
312
313
314 template<typename TCmp>
315 class QListWidgetRowCmp
316 {
317 QListWidget* list_;
318 public:
319 explicit QListWidgetRowCmp(QListWidget* _list):list_(_list){}
320 bool operator()(QListWidgetItem* left, QListWidgetItem* right)
321 {
322 return TCmp()(list_->row(left) , list_->row(right));
323 }
324 };
325
326 void PostProcessorDialog::slotMoveDown()
327 {
328 int start = 0;
329 QList<QListWidgetItem*> selectedItems = activeList->selectedItems();
330
331 //sort list, so the top is the last element
332 std::sort(selectedItems.begin(), selectedItems.end(), QListWidgetRowCmp<std::greater<int> >(activeList));
333
334 //dont move the last one
335 //if the last one wasnt moved, dont move the direct followers
336 for(int i=0; i < selectedItems.size() && activeList->row(selectedItems[i]) == activeList->count()-1-i;++i)
337 --start;
338
339 //move bottom first
340 for (int i=selectedItems.size()-1+start; i >= 0 ; --i)
341 {
342 QListWidgetItem* activeItem = activeList->selectedItems()[i];
343 unsigned selectedRow = activeList->row(activeItem);
344 slotMovePostProcessor(selectedRow,selectedRow+1);
345 }
346 }
347
348
349 void PostProcessorDialog::slotMoveUp()
350 {
351 int start = 0;
352 QList<QListWidgetItem*> selectedItems = activeList->selectedItems();
353
354 //sort list, so the top is the first element
355 std::sort(selectedItems.begin(), selectedItems.end(), QListWidgetRowCmp<std::less<int> >(activeList));
356
357 //dont move the first one
358 //if the first one wasnt moved, dont move the direct followers
359 for(int i=0; i < selectedItems.size() && activeList->row(selectedItems[i]) == i;++i)
360 ++start;
361
362 //move top first
363 for (int i=start; i < selectedItems.size(); ++i)
364 {
365 QListWidgetItem* activeItem = selectedItems[i];
366 unsigned selectedRow = activeList->row(activeItem);
367 slotMovePostProcessor(selectedRow,selectedRow-1);
368 }
369 }
370
371 void PostProcessorDialog::slotSaveActive()
372 {
373 QStringList activeList("");
374
375 for (int i = 0; i < postProcessorManager().numActive(currentExaminer_); ++i)
376 {
377 unsigned int id = postProcessorManager().activeId(currentExaminer_, i);
378 activeList.push_back(postProcessorManager()[id]->name);
379 }
380
381 OpenFlipperSettings().setValue(QString("PostProcessor/Viewer/%1").arg(currentExaminer_),activeList);
382 }
383
384 QStringList PostProcessorDialog::getSavedPostProcessorNames(const unsigned _examiner)
385 {
386 return OpenFlipperSettings().value(QString("PostProcessor/Viewer/%1").arg(_examiner),QStringList("")).toStringList();
387 }
388
389 void PostProcessorDialog::loadSavedPostProcessors(const unsigned _examiner)
390 {
391 QStringList active = getSavedPostProcessorNames(_examiner);
392 for (QStringList::iterator iter = active.begin(); iter != active.end(); ++iter)
393 {
394 postProcessorManager().append(*iter,_examiner);
395 }
396 }
397
398 void PostProcessorDialog::refresh()
399 {
400 initWindow();
401 }
PostProcessorDialog::loadSavedPostProcessors
static void loadSavedPostProcessors(const unsigned _examiner)
append all saved post processors
Definition: postProcessorWidget.cc:389
PostProcessorDialog::slotDeactivatePostProcessor
void slotDeactivatePostProcessor()
Deactivates the current postProcessor.
Definition: postProcessorWidget.cc:169
PostProcessorInfo::description
QString description
Description of the plugin.
Definition: RendererInfo.hh:199
PostProcessorInfo::version
QString version
Version of the plugin.
Definition: RendererInfo.hh:202
PostProcessorManager::available
size_t available()
number of available post processor
Definition: RendererInfo.cc:274
PostProcessorDialog::initWindow
void initWindow()
initiaize the window with the post processors of the current examiner
Definition: postProcessorWidget.cc:91
PostProcessorDialog::slotMovePostProcessor
void slotMovePostProcessor(unsigned _from, unsigned _to)
Move the position/ordering of postprocessor in the postprocessor.
Definition: postProcessorWidget.cc:202
PostProcessorDialog::slotMoveUp
void slotMoveUp()
move the selected active postprocessor 1 up
Definition: postProcessorWidget.cc:349
GlobalOptions.hh
PluginFunctions::activeExaminer
unsigned int activeExaminer()
Get the id of the examiner which got the last mouse events.
Definition: PluginFunctions.cc:194
PluginFunctions.hh
PostProcessorManager::remove
void remove(int _id, int _chainIdx)
Remove a post processor at the specified chain index.
Definition: RendererInfo.cc:439
PostProcessorInfo::name
QString name
Name of the plugin ( requested from the plugin on load)
Definition: RendererInfo.hh:196
PostProcessorManager::append
void append(unsigned int _active, int _viewerId)
Append the active post processor to the chain for viewer.
Definition: RendererInfo.cc:362
PostProcessorInfo
Definition: RendererInfo.hh:184
PostProcessorManager::insert
void insert(unsigned int _active, int _chainIdx, int _viewerId)
Insert the active post processor to the chain for viewer.
Definition: RendererInfo.cc:401
PostProcessorDialog::refresh
void refresh()
refreshes the content of the dialog with current examiner
Definition: postProcessorWidget.cc:398
OpenFlipperQSettings::value
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Definition: OpenFlipperQSettings.cc:46
PostProcessorManager::activeId
unsigned int activeId(int _id, int _chainIdx=0)
Get the id of the active post processor for viewer at chain index.
Definition: RendererInfo.cc:333
PostProcessorDialog::slotContextMenuDeactivate
void slotContextMenuDeactivate(const QPoint &_point)
Show the custom context menu for deactivation.
Definition: postProcessorWidget.cc:252
PostProcessorManager::numActive
int numActive(int _id)
Get the number of active post processors for viewer.
Definition: RendererInfo.cc:349
OpenFlipperQSettings::setValue
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...
Definition: OpenFlipperQSettings.cc:61
PostProcessorDialog::slotMoveDown
void slotMoveDown()
move the selected active postprocessor 1 down
Definition: postProcessorWidget.cc:326
OpenFlipperSettings
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
Definition: GlobalOptions.cc:1038
PostProcessorDialog::getSavedPostProcessorNames
static QStringList getSavedPostProcessorNames(const unsigned _examiner)
return the names of all saved post processors
Definition: postProcessorWidget.cc:384
PostProcessorDialog::slotActivatePostProcessor
void slotActivatePostProcessor()
Activates the post processor (triggered via the context menu)
Definition: postProcessorWidget.cc:139
PostProcessorInfo::optionsAction
QAction * optionsAction
Possible action to add an options action or menu to the system.
Definition: RendererInfo.hh:205
QListWidgetRowCmp
Definition: postProcessorWidget.cc:315
PostProcessorDialog::slotSaveActive
void slotSaveActive()
saves active post processor chain
Definition: postProcessorWidget.cc:371
PostProcessorDialog::slotContextMenuActivate
void slotContextMenuActivate(const QPoint &_point)
Show the custom context menu for activation.
Definition: postProcessorWidget.cc:237