OpenWalnut  1.5.0dev
WQtModuleConfig.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include <algorithm>
26 #include <fstream>
27 #include <iostream>
28 #include <string>
29 #include <vector>
30 
31 #include <boost/filesystem.hpp>
32 #include <boost/program_options.hpp>
33 
34 #include <QtCore/QDir>
35 #include <QCheckBox>
36 #include <QComboBox>
37 #include <QDialogButtonBox>
38 #include <QFileDialog>
39 #include <QGridLayout>
40 #include <QLabel>
41 #include <QPushButton>
42 #include <QTabWidget>
43 #include <QVBoxLayout>
44 
45 #include "core/common/WPathHelper.h"
46 #include "core/kernel/WModuleFactory.h"
47 #include "WMainWindow.h"
48 #include "WQtGui.h"
49 #include "WQtModuleConfig.h"
50 
51 bool nameSort( WModule::ConstSPtr i, WModule::ConstSPtr j )
52 {
53  return ( i->getName() < j->getName() );
54 }
55 
56 WQtModuleConfig::WQtModuleConfig( QWidget* parent, Qt::WindowFlags f ):
57  QDialog( parent, f )
58 {
59  // configure the dialog
60  setModal( true );
61 
62  // some minimum size
63  resize( 600, 400 );
64 
65  // get a list of all the modules available
68  for( ProtoIter iter = r->get().begin(); iter != r->get().end(); ++iter )
69  {
70  m_moduleList.push_back( *iter );
71  }
72  std::sort( m_moduleList.begin(), m_moduleList.end(), nameSort );
73 
74  // initialize members
75  QVBoxLayout* layoutAllowedModules = new QVBoxLayout;
76  QWidget* p1 = new QWidget();
77  p1->setLayout( layoutAllowedModules );
78 
79  QVBoxLayout* layoutModulePaths = new QVBoxLayout;
80  QWidget* p2 = new QWidget();
81  p2->setLayout( layoutModulePaths );
82 
83  // setup tab widget.
84  QTabWidget* tab = new QTabWidget( this );
85  tab->addTab( p1, "Allowed Modules" );
86  tab->addTab( p2, "Module Paths" );
87  QVBoxLayout* mainLayout = new QVBoxLayout();
88  mainLayout->addWidget( tab );
89  setLayout( mainLayout );
90 
91  QString helpText = "This dialog allows you to modify the list of modules used everywhere in OpenWalnut. The list contains all loaded modules. "
92  "By default, the list is interpreted as white-list. This means, you have to select the modules you want "
93  "to use and disable those you won't use. You can switch to black-listing. This allows you to select all modules "
94  "that should not be used.";
95  QLabel* hint = new QLabel( helpText );
96  hint->setWordWrap( true );
97  layoutAllowedModules->addWidget( hint );
98 
99  QString helpTextPaths = "You can add more search paths here, where OpenWalnut searches modules during startup. Each path is searched "
100  "recursively. Use this list to help OpenWalnut find your downloaded or self-made modules. An alternative option is to "
101  "set the environment variable \"OW_MODULE_PATH\", which is a semicolon-separated list of search paths. After "
102  "restarting OpenWalnut, the modules in the added paths appear in the list of allowed modules.";
103  QLabel* hintPaths = new QLabel( helpTextPaths );
104  hintPaths->setWordWrap( true );
105  layoutModulePaths->addWidget( hintPaths );
106 
107 
108 
109  // always show all modules?
110  m_showThemAll = new QCheckBox( "Always show all modules.", this );
111  m_showThemAll->setToolTip(
112  "Recommended option. This ensures that all modules get shown all them time, regardless of the list below."
113  );
114  connect( m_showThemAll, SIGNAL( stateChanged( int ) ), this, SLOT( showThemAllUpdated() ) );
115  layoutAllowedModules->addWidget( m_showThemAll );
116 
117  m_asBlackList = new QCheckBox( "Use as black-list", this );
118  m_asBlackList->setToolTip( "Activate this option if you want all modules to be active in OpenWalnut that are not explicitly deactivated here." );
119  layoutAllowedModules->addWidget( m_asBlackList );
120 
121  QHBoxLayout* blacklistPresetRow = new QHBoxLayout();
122  layoutAllowedModules->addLayout( blacklistPresetRow );
123 
124  m_usePreset = new QCheckBox( "Use a preset module list", this );
125  m_usePreset->setToolTip( "Activate this option if you want to use a list of preselected "
126  "modules which may be specific for different research areas. " );
127  connect( m_usePreset, SIGNAL( stateChanged( int ) ), this, SLOT( refreshModuleCheckboxes() ) );
128  connect( m_usePreset, SIGNAL( stateChanged( int ) ), this, SLOT( toggleComboboxVisibility( int ) ) );
129  blacklistPresetRow->addWidget( m_usePreset );
130 
131  // Set presets here
132  QString presetSIVERT = "Anisotropic Filter,Calculate GFA,Calculate Tensors,Cluster Display,ClusterDisplayVoxels,"
133  "Data Type Conversion,Diffusion Tensor Scalars,EEG View,Effective Connectivity Cluster,Fiber Data Creator,"
134  "Fiber translator,Functional MRI Viewer,Hierarchical Clustering Display,Image Space LIC,Image Space Tensor LIC,"
135  "Merge Components To Vector,Mori Det. Tracking,Partition To Mesh,Picking in DVR Evaluation,"
136  "Probabilistic Tract Rendering with multi transparent iso surfaces.,"
137  "Read Amira Mesh,Read Dipoles,Read Raw Data,Read Simple Text Line Data,Read Spherical Harmonics,Read VCL,"
138  "Read VIM,Scalar Data Creator,Spline Surface,Superquadric Glyphs,Surface Parameter Animator,"
139  "Template,Template Colormapping,Template Containers,Template Data Loader,Template Render Pipelines,"
140  "Template Shaders,Template UI,Vector Align,Vector Data Creator,Vector Normalize,Vector Operator,"
141  "Vector Plot,Vector Scaling,WebGL Support,Write Amira Mesh,Write Dendrogram,";
142 
143  WQtGui::getSettings().setValue( "qtgui/modules/preset/ ", QString::fromStdString( "" ) );
144  WQtGui::getSettings().setValue( "qtgui/modules/preset/SIVERT", presetSIVERT );
145 
146  // combobox for black-list presets
147  m_selectPresetBlacklist = new QComboBox( this );
148  m_selectPresetBlacklist->setDisabled( true );
149  m_selectPresetBlacklist->setToolTip( "Select a preset or create a new one by selecting modules in the list below "
150  "and type in a name here." );
151  m_selectPresetBlacklist->setFixedSize( 120, 26 );
152  m_selectPresetBlacklist->setEditable( true );
153  m_selectPresetBlacklist->setInsertPolicy( QComboBox::InsertAtBottom );
154 
156 
157  if( m_asBlackList->checkState() )
158  {
159  m_selectPresetBlacklist->setDisabled( false );
160  }
161  connect( m_selectPresetBlacklist, SIGNAL( currentIndexChanged( int ) ), this, SLOT( refreshModuleCheckboxes() ) );
162  blacklistPresetRow->addWidget( m_selectPresetBlacklist );
163  QSpacerItem* horizSpacer = new QSpacerItem( 1, 1, QSizePolicy::Expanding, QSizePolicy::Fixed );
164  blacklistPresetRow->addSpacerItem( horizSpacer );
165 
166  // create the module list
167  m_list = new QListWidget();
168  layoutAllowedModules->addWidget( m_list );
169 
170  // the path list
171  m_pathList = new QListWidget();
172  layoutModulePaths->addWidget( m_pathList );
173 
174  // the path list also needs some add/remove buttons
175  QHBoxLayout* addRemLayout = new QHBoxLayout();
176  QWidget* addRemWidget = new QWidget();
177  addRemWidget->setLayout( addRemLayout );
178  layoutModulePaths->addWidget( addRemWidget );
179  QPushButton* addButton = new QPushButton( "Add Path" );
180  m_removePathButton = new QPushButton( "Remove Path" );
181  m_removePathButton->setEnabled( false );
182  addRemLayout->addWidget( addButton );
183  addRemLayout->addWidget( m_removePathButton );
184 
185  connect( addButton, SIGNAL( clicked( bool ) ), this, SLOT( addModulePath() ) );
186  connect( m_removePathButton, SIGNAL( clicked( bool ) ), this, SLOT( removeModulePath() ) );
187  connect( m_pathList, SIGNAL( itemSelectionChanged() ), this, SLOT( pathListSelectionChanged() ) );
188 
189  // for modules without icon, use this
190  QIcon noIcon = WQtGui::getMainWindow()->getIconManager()->getIcon( "DefaultModuleIcon" );
191 
192  // fill the list item
193  for( std::vector< WModule::ConstSPtr >::const_iterator iter = m_moduleList.begin(); iter != m_moduleList.end(); ++iter )
194  {
195  // Create a custom widget which contains the name and description
196  QWidget* widget = new QWidget( m_list );
197  {
198  QGridLayout* layoutWidget = new QGridLayout();
199 
200  QSizePolicy sizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ); // <-- scale it down
201 
202  int column = 0;
203 
204  // create a checkbox for this module
205  QCheckBox* check = new QCheckBox();
206  check->setSizePolicy( sizePolicy );
207  layoutWidget->addWidget( check, 0, 0, 2, 1 );
208 
209  // we later need to find the checkbox for one module easily:
210  m_moduleItemMap[ ( *iter )->getName() ] = check;
211 
212  ++column;
213 
214  // now, an icon
215  QLabel* icon = new QLabel();
216  icon->setSizePolicy( sizePolicy );
217 
218  // we need to enforce some size
219  QIcon modIco = WQtGui::getMainWindow()->getIconManager()->getIcon( ( *iter )->getName(), noIcon );
220  QPixmap qicon( modIco.pixmap( 32, 32 ) );
221  qicon = qicon.scaled( 32, 32, Qt::KeepAspectRatio );
222  icon->setPixmap( qicon );
223 
224  layoutWidget->addWidget( icon, 0, column, 2, 1 );
225  ++column;
226 
227  // Add Name and Description
228  layoutWidget->addWidget( new QLabel( "<b>" + QString::fromStdString( ( *iter )->getName() )+ "</b>" ), 0, column );
229  // if there is no description -> no widget added to save space
230  if( !( *iter )->getDescription().empty() )
231  {
232  layoutWidget->addWidget( new QLabel( QString::fromStdString( ( *iter )->getDescription() ) ), 1, column );
233  }
234 
235  layoutWidget->setSizeConstraint( QLayout::SetMaximumSize );
236  widget->setLayout( layoutWidget );
237  }
238 
239  QListWidgetItem* item = new QListWidgetItem( m_list );
240  item->setSizeHint( widget->sizeHint() );
241 
242  m_list->addItem( item );
243  m_list->setItemWidget( item, widget );
244  m_list->setMinimumHeight( 150 );
245  }
246 
247  // provide some default buttons here
248  QDialogButtonBox* defButtons = new QDialogButtonBox( QDialogButtonBox::Save | QDialogButtonBox::Cancel | QDialogButtonBox::RestoreDefaults,
249  Qt::Horizontal, this );
250  connect( defButtons, SIGNAL( accepted() ), this, SLOT( accept() ) );
251  connect( defButtons, SIGNAL( rejected() ), this, SLOT( reject() ) );
252  connect( defButtons->button( QDialogButtonBox::RestoreDefaults ), SIGNAL( clicked() ), this, SLOT( reset() ) );
253  mainLayout->addWidget( defButtons );
254 
255  // initialize the widgets
257 }
258 
260 {
261  // cleanup
262 }
263 
265 {
266  // we allow the user to specify additional module paths. They need to be loaded before the WModuleFactory initiates the module-load stuff.
267  // Therefore, we grab the setting here and add it to WPathHelper
268  QList< QVariant > paths = WQtGui::getSettings().value( "qtgui/additionalModulePaths" ).toList();
269  for( QList< QVariant >::const_iterator it = paths.begin(); it != paths.end(); ++it )
270  {
271  std::string p = ( *it ).toString().toStdString();
272  WPathHelper::getPathHelper()->addAdditionalModulePath( p );
273  }
274 }
275 
276 void WQtModuleConfig::loadListsFromSettings( bool defaultModulePaths )
277 {
278  // update checkbox too
279  bool ignoreAllowedList = WQtGui::getSettings().value( "qtgui/modules/IgnoreAllowedList", true ).toBool();
280  m_showThemAll->setCheckState( ignoreAllowedList ? Qt::Checked : Qt::Unchecked );
281 
282  bool asBlackList = WQtGui::getSettings().value( "qtgui/modules/asBlackList", false ).toBool();
283  m_asBlackList->setCheckState( asBlackList ? Qt::Checked : Qt::Unchecked );
284 
285  bool usePreset = WQtGui::getSettings().value( "qtgui/modules/usePreset", false ).toBool();
286  m_usePreset->setCheckState( usePreset ? Qt::Checked : Qt::Unchecked );
287 
288  if( !defaultModulePaths )
289  {
290  // now, also fill the list
291  // NOTE: we do not use the list in WPathHelper. This list will NOT be updated directly to ensure consistency between the path list in
292  // WPathHelper and the loaded modules in WModuleFactory. WPathHelper is set correctly on next restart.
293  QList< QVariant > paths = WQtGui::getSettings().value( "qtgui/additionalModulePaths" ).toList();
294  for( QList< QVariant >::const_iterator it = paths.begin(); it != paths.end(); ++it )
295  {
296  std::string p = ( *it ).toString().toStdString();
297  m_pathList->addItem( QString::fromStdString( p ) );
298  }
299  }
300 }
301 
303 {
304  // rebuild list of allowed modules
305  m_allowedModules.clear();
306  std::string allowedAsString; // this is needed since QList cannot be stored in a QSettings in a read-able format right now.
307 
308  // iterate the widgets and store in settings:
309  for( ModuleItemMapType::const_iterator iter = m_moduleItemMap.begin(); iter != m_moduleItemMap.end(); ++iter )
310  {
311  // if it is checked, use.
312  if( iter->second->checkState() == Qt::Checked ) // save only checked items
313  {
314  m_allowedModules.push_back( iter->first );
315  allowedAsString += iter->first + ",";
316  }
317  }
318 
319  // store this list in settings
320  WQtGui::getSettings().setValue( "qtgui/modules/allowedList", QString::fromStdString( allowedAsString ) );
321  WQtGui::getSettings().setValue( "qtgui/modules/IgnoreAllowedList", ( m_showThemAll->checkState() == Qt::Checked ) );
322  WQtGui::getSettings().setValue( "qtgui/modules/asBlackList", ( m_asBlackList->checkState() == Qt::Checked ) );
323 
324  WQtGui::getSettings().setValue( "qtgui/modules/usePreset", m_usePreset->checkState() );
325  WQtGui::getSettings().setValue( "qtgui/modules/selectedPreset", m_selectPresetBlacklist->currentText() );
326 
327  // -1 means, that the preset name is not in the list of presets
328  if( m_selectPresetBlacklist->findText( m_selectPresetBlacklist->currentText() ) == -1 )
329  {
330  WQtGui::getSettings().setValue( "qtgui/modules/preset/" + m_selectPresetBlacklist->currentText(), QString::fromStdString( allowedAsString ) );
331  }
332 
333  // also write the path list
334  QList< QVariant > paths;
335  for( int i = 0; i < m_pathList->count(); ++i )
336  {
337  paths.push_back( m_pathList->item( i )->text() );
338  }
339  WQtGui::getSettings().setValue( "qtgui/additionalModulePaths", paths );
340 }
341 
342 bool WQtModuleConfig::operator()( std::string const& name ) const
343 {
344  bool blackList = ( m_asBlackList->checkState() == Qt::Checked );
345  bool ignoreList = ( m_showThemAll->checkState() == Qt::Checked );
346  bool isInList = ( std::find( m_allowedModules.begin(), m_allowedModules.end(), name ) != m_allowedModules.end() );
347 
348  return !ignoreList && ( ( blackList && isInList ) || ( !blackList && !isInList ) );
349 }
350 
352 {
353  return operator()( module->getName() );
354 }
355 
357 {
358  show();
359 }
360 
362 {
363  QAction* a = new QAction( "Configure Modules", parent() );
364  a->setToolTip( "Allows you to configure the list of modules, which is used for selecting modules in OpenWalnut (i.e. in the toolbar)." );
365  connect( a, SIGNAL( triggered( bool ) ), this, SLOT( configure() ) );
366  return a;
367 }
368 
370 {
373  emit updated();
374  QDialog::accept();
375 }
376 
378 {
379  // reset everything to the current state in the settings:
381 
382  QDialog::reject();
383 }
384 
386 {
387  if( m_showThemAll->checkState() == Qt::Checked )
388  {
389  m_list->setDisabled( true );
390  }
391  else
392  {
393  m_list->setDisabled( false );
394  }
395 }
396 
398 {
399  m_pathList->clear();
400 
402  loadListsFromSettings( true );
403 
404  m_showThemAll->setCheckState( Qt::Unchecked );
405  m_asBlackList->setCheckState( Qt::Unchecked );
406  m_usePreset->setCheckState( Qt::Unchecked );
407 
408  m_list->setDisabled( false );
409 }
410 
412 {
413  QString dir = QFileDialog::getExistingDirectory( this, "Select Directory",
414  QString::fromStdString( WPathHelper::getHomePath().string() ),
415  QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks );
416  m_pathList->addItem( dir );
417 }
418 
420 {
421  qDeleteAll( m_pathList->selectedItems() );
422 }
423 
425 {
426  if( m_pathList->selectedItems().size() )
427  {
428  m_removePathButton->setEnabled( true );
429  }
430  else
431  {
432  m_removePathButton->setEnabled( false );
433  }
434 }
435 
437 {
438  for( std::vector< WModule::ConstSPtr >::const_iterator iter = m_moduleList.begin(); iter != m_moduleList.end(); ++iter )
439  {
440  // we later need to find the checkbox for one module easily:
441  m_moduleItemMap[ ( *iter )->getName() ]->setCheckState( Qt::Unchecked );
442  }
443 }
444 
446 {
448  std::string allowedModules = "";
449 
450  // read settings
451  if( m_usePreset->isChecked() )
452  {
453  allowedModules = WQtGui::getSettings().value( "qtgui/modules/preset/" + m_selectPresetBlacklist->currentText(), "" ).toString().toStdString();
454  }
455  else
456  {
457  allowedModules = WQtGui::getSettings().value( "qtgui/modules/allowedList", "" ).toString().toStdString();
458  }
459 
460  m_allowedModules = string_utils::tokenize( allowedModules, "," );
461 
462  // set dialog according to the settings
463  for( AllowedModuleList::const_iterator iter = m_allowedModules.begin(); iter != m_allowedModules.end(); ++iter )
464  {
465  if( m_moduleItemMap.count( *iter ) )
466  {
467  m_moduleItemMap[ *iter ]->setCheckState( Qt::Checked );
468  }
469  }
470 }
471 
473 {
474  // 0 = checkbox not ticked, 2 = checkbox is ticked
475  if( usePresetState == 0 )
476  {
477  m_selectPresetBlacklist->setDisabled( true );
478  }
479  else
480  {
481  m_selectPresetBlacklist->setDisabled( false );
482  }
483 }
484 
486 {
487  //Clear list before updating
488  m_selectPresetBlacklist->clear();
489 
490  // read preset names from settings
491  QSettings* settings = &WQtGui::getSettings();
492  settings->beginGroup( "qtgui/modules/preset/" );
493  QStringList childKeys = settings->childKeys();
494  m_selectPresetBlacklist->addItems( childKeys );
495  settings->endGroup();
496 
497  int selectedPresetIndex = m_selectPresetBlacklist->findText( WQtGui::getSettings().value( "qtgui/modules/selectedPreset", "" ).toString() );
498  // -1 means selectedPresetIndex not found
499  if( selectedPresetIndex != -1 )
500  {
501  m_selectPresetBlacklist->setCurrentIndex( selectedPresetIndex );
502  }
503  else
504  {
505  m_selectPresetBlacklist->setCurrentIndex( 0 );
506  }
507 }
QIcon getIcon(const std::string name)
Searches icons in the internal map and all modules for the given icon name.
WIconManager * getIconManager()
Return icon manager.
std::set< std::shared_ptr< WModule > >::const_iterator PrototypeContainerConstIteratorType
Const iterator for the prototype set.
static SPtr getModuleFactory()
Returns instance of the module factory to use to create modules.
std::shared_ptr< const WModule > ConstSPtr
Shared pointer to a const WModule.
Definition: WModule.h:111
static boost::filesystem::path getHomePath()
The path to the OW dir in the user's home.
static std::shared_ptr< WPathHelper > getPathHelper()
Returns instance of the path helper.
Definition: WPathHelper.cpp:52
static QSettings & getSettings()
Returns the settings object.
Definition: WQtGui.cpp:394
static WMainWindow * getMainWindow()
Returns the current main window instance or NULL if not existent.
Definition: WQtGui.cpp:88
virtual void pathListSelectionChanged()
Call this notify the remove button whether something is selected in m_pathList or not.
QCheckBox * m_showThemAll
Checkbox controlling whether all modules should be shown all the time.
QPushButton * m_removePathButton
Button responsible for removing the currently selected path in m_pathList.
void configure()
Uses a modal dialog to allow the user modifying it.
QListWidget * m_list
This widget contains the allowed module list.
WQtModuleConfig(QWidget *parent=0, Qt::WindowFlags f=Qt::WindowFlags())
Constructs excluder dialog and loads needed settings.
QListWidget * m_pathList
This list widget contains all additional search paths.
virtual void removeModulePath()
Remove the selected item from m_pathList;.
void resetAllModuleCheckboxes()
Call this to reset all checkboxes in the list of modules.
QCheckBox * m_asBlackList
Control whether the list is interpreted as black list.
void showThemAllUpdated()
Triggered by the m_showThemAll checkbox.
std::vector< WModule::ConstSPtr > m_moduleList
The list of available modules.
static void initPathHelper()
This function initializes the path helper by loading the module path settings.
virtual void accept()
Hides the dialog, updates the internal lists and emits updated-signal.
bool operator()(std::string const &name) const
Checks exclusion by name.
void refreshComboboxItems()
Call this to refresh the combobox items.
void updated()
Signal getting emitted if the exclusion-lists changes.
void reset()
called by the reset button
virtual void addModulePath()
Add a path to m_pathList;.
QComboBox * m_selectPresetBlacklist
Combobox to select a black list.
void loadListsFromSettings(bool defaultModulePaths=false)
Reloads the whitelist and the blacklist from the QSettings.
virtual ~WQtModuleConfig()
Destructor.
QAction * getConfigureAction() const
Creates an action instance allowing the configuration.
QCheckBox * m_usePreset
Check if you want to use a preset module list.
virtual void reject()
Hides the dialog, does not update the internal lists.
void refreshModuleCheckboxes()
Call this to refresh the list of selected modules, e.g.
ModuleItemMapType m_moduleItemMap
Maps between module name and item.
AllowedModuleList m_allowedModules
The list of modules that are allowed.
void toggleComboboxVisibility(int)
Call this to show or hide the preset combobox.
void saveListToSettings()
Saves the whitelist and the blacklist to the settings.
std::shared_ptr< WSharedObjectTicketRead< T > > ReadTicket
Type for read tickets.
Definition: WSharedObject.h:65
std::vector< std::string > tokenize(const std::string &source, const std::string &delim=WHITESPACE, bool compress=true)
Splits the given string into a vector of strings (so called tokens).