Medical Imaging Interaction Toolkit  2018.4.99-b585543d
Medical Imaging Interaction Toolkit
QmitkPreferencesDialog.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 #include "QmitkPreferencesDialog.h"
14 
15 #include "berryPlatform.h"
16 #include "berryPlatformUI.h"
17 #include "berryIWorkbench.h"
20 #include "berryIExtension.h"
22 #include <berryIQtPreferencePage.h>
23 
24 #include "internal/org_mitk_gui_qt_application_Activator.h"
25 
26 #include <ui_QmitkPreferencesDialog.h>
27 
28 #include <QFileDialog>
29 #include <QMessageBox>
30 #include <QPushButton>
31 
32 #include <algorithm>
33 
34 #include <mitkLogMacros.h>
35 
36 using namespace std;
37 
38 static std::vector<std::string> splitString(const std::string &s, char delim=' ')
39 {
40  std::vector < std::string > elems;
41  std::stringstream ss(s);
42  std::string item;
43  while (std::getline(ss, item, delim))
44  {
45  elems.push_back(item);
46  }
47  return elems;
48 }
49 
50 class QmitkPreferencesDialogPrivate : public Ui::QmitkPreferencesDialog
51 {
52 public:
53 
57  struct PrefPage
58  {
59  PrefPage(QString _id, QString _name, QString _category
60  , QString _className, QString _keywords, berry::IConfigurationElement::Pointer _confElem)
61  : id(_id), name(_name), category(_category), className(_className), keywords(_keywords),
62  prefPage(nullptr), confElem(_confElem), treeWidgetItem(nullptr)
63  {}
64 
65  bool operator==(const PrefPage& other)
66  { return id == other.id; }
67 
68  bool operator<(const PrefPage& other)
69  { return name < other.name; }
70 
71  QString id;
72  QString name;
73  QString category;
74  QString className;
75  QString keywords;
76  berry::IQtPreferencePage* prefPage;
78  QTreeWidgetItem* treeWidgetItem;
79  };
80 
81  QmitkPreferencesDialogPrivate()
82  : m_CurrentPage(0)
83  {
85 
86  // m_PrefPages
87  QList<berry::IConfigurationElement::Pointer> prefPages(xpService->GetConfigurationElementsFor("org.blueberry.ui.preferencePages"));
88  QList<berry::IConfigurationElement::Pointer> keywordExts(xpService->GetConfigurationElementsFor("org.blueberry.ui.keywords"));
89  QList<berry::IConfigurationElement::Pointer>::iterator prefPagesIt;
90 
91  QList<berry::IConfigurationElement::Pointer>::iterator keywordRefsIt;
92 
93  for (prefPagesIt = prefPages.begin(); prefPagesIt != prefPages.end(); ++prefPagesIt)
94  {
95  QString id = (*prefPagesIt)->GetAttribute("id");
96  QString name = (*prefPagesIt)->GetAttribute("name");
97  QString className = (*prefPagesIt)->GetAttribute("class");
98  if(!id.isEmpty() && !name.isEmpty() && !className.isEmpty())
99  {
100  QString keywordLabels;
101 
102  QString category = (*prefPagesIt)->GetAttribute("category");
103  //# collect keywords
104  QList<berry::IConfigurationElement::Pointer> keywordRefs = (*prefPagesIt)->GetChildren("keywordreference"); // get all keyword references
105  for (keywordRefsIt = keywordRefs.begin()
106  ; keywordRefsIt != keywordRefs.end(); ++keywordRefsIt) // iterate over all refs
107  {
108  QString keywordRefId = (*keywordRefsIt)->GetAttribute("id"); // get referenced id
109 
110  for (QList<berry::IConfigurationElement::Pointer>::iterator keywordExtsIt = keywordExts.begin();
111  keywordExtsIt != keywordExts.end(); ++keywordExtsIt) // iterate over all keywords
112  {
113  QString keywordId = (*keywordExtsIt)->GetAttribute("id"); // get keyword id
114  if(keywordId == keywordRefId) // if referenced id is equals the current keyword id
115  {
116  //# collect all keywords from label attribute with a tokenizer
117  QString currLabel = (*keywordExtsIt)->GetAttribute("label");
118  currLabel = currLabel.toLower();
119  if (!currLabel.isEmpty()) keywordLabels += QString(" ") + currLabel;
120 
121  //break; // break here; possibly search for other referenced keywords
122  }
123  }
124  }
125 
126  // add information as PrefPage
127  m_PrefPages.push_back(PrefPage(id, name, category, className, keywordLabels, berry::IConfigurationElement::Pointer(*prefPagesIt)));
128  }
129 
130  }
131  }
132 
136  QList<PrefPage> m_PrefPages;
137  int m_CurrentPage;
138 
139 };
140 
141 QmitkPreferencesDialog::QmitkPreferencesDialog(QWidget * parent, Qt::WindowFlags f)
142  : QDialog(parent, f), d(new QmitkPreferencesDialogPrivate)
143 {
144  d->setupUi(this);
145 
146  QObject::connect(d->m_Keyword, SIGNAL(editingFinished()), this, SLOT(OnKeywordEditingFinished()));
147  QObject::connect(d->m_Keyword, SIGNAL(textChanged(QString)), this, SLOT(OnKeywordTextChanged(QString)));
148 
149  QObject::connect(d->m_PreferencesTree, SIGNAL(itemSelectionChanged()), this, SLOT(OnPreferencesTreeItemSelectionChanged()));
150 
151  QPushButton* importButton = d->buttonBox->addButton("Import...", QDialogButtonBox::ActionRole);
152  QObject::connect(importButton, SIGNAL(clicked()), this, SLOT(OnImportButtonClicked()));
153 
154  QPushButton* exportButton = d->buttonBox->addButton("Export...", QDialogButtonBox::ActionRole);
155  QObject::connect(exportButton, SIGNAL(clicked()), this, SLOT(OnExportButtonClicked()));
156 
157  QObject::connect(this, SIGNAL(accepted()), this, SLOT(OnDialogAccepted()));
158  QObject::connect(this, SIGNAL(rejected()), this, SLOT(OnDialogRejected()));
159 
160  this->UpdateTree();
161 }
162 
164 {
165 }
166 
168 {
169  for(QList<QmitkPreferencesDialogPrivate::PrefPage>::iterator it = d->m_PrefPages.begin(); it != d->m_PrefPages.end(); ++it)
170  {
171  if(it->id == id)
172  {
173  d->m_PreferencesTree->setCurrentItem(it->treeWidgetItem);
174  break;
175  }
176  }
177 }
178 
180 {
181  int answer = QMessageBox::question(this, "Importing Preferences"
182  , "All existing preferences will be overwritten!\nAre you sure that you want to import other preferences?", QMessageBox::Yes | QMessageBox::No );
183  if(answer == QMessageBox::No)
184  return;
185 
186  try
187  {
188  berry::IBerryPreferencesService* berryPrefService =
190  if(berryPrefService != nullptr)
191  {
192  static QString importDir = "";
193  QString fileName = QFileDialog::getOpenFileName(this, tr("Choose file to import preferences"),
194  importDir, tr("XML files (*.xml)"));
195 
196  if(!fileName.isEmpty())
197  {
198  importDir = QFileInfo(fileName).absoluteDir().path();
199  berryPrefService->ImportPreferences(fileName, "");
200  berry::IQtPreferencePage* prefPage = d->m_PrefPages[d->m_CurrentPage].prefPage;
201  if(prefPage)
202  prefPage->Update();
203 
204  MITK_INFO("QmitkPreferencesDialog") << "Preferences successfully imported from " << fileName;
205  }
206  }
207  }
208  catch (Poco::Exception& pe)
209  {
210  QMessageBox::critical(this, "Error Importing", pe.message().c_str());
211  MITK_ERROR("QmitkPreferencesDialog") << pe.what();
212  }
213  catch (std::exception& e)
214  {
215  QMessageBox::critical(this, "Error Importing", e.what());
216  MITK_ERROR("QmitkPreferencesDialog") << e.what();
217  }
218 }
219 
221 {
222  try
223  {
224  berry::IBerryPreferencesService* berryPrefService =
226  if(berryPrefService != nullptr)
227  {
228  SavePreferences();
229  static QString exportDir = "";
230  QString fileName = QFileDialog::getSaveFileName(this, tr("Choose file to export preferences"),
231  exportDir, tr("XML files (*.xml)"));
232 
233  if(!fileName.isEmpty())
234  {
235  if(QFileInfo(fileName).suffix() != ".xml")
236  {
237  fileName += ".xml";
238  }
239  exportDir = QFileInfo(fileName).absoluteDir().path();
240  berryPrefService->ExportPreferences(fileName, "");
241  MITK_INFO("QmitkPreferencesDialog") << "Preferences successfully exported to " << fileName;
242  }
243  }
244  }
245  catch (Poco::Exception& pe)
246  {
247  QMessageBox::critical(this, "Error Exporting", pe.message().c_str());
248  MITK_ERROR("QmitkPreferencesDialog") << pe.what();
249  }
250  catch (std::exception& e)
251  {
252  QMessageBox::critical(this, "Error Exporting", e.what());
253  MITK_ERROR("QmitkPreferencesDialog") << e.what();
254  }
255 }
256 
258 {
259  berry::IQtPreferencePage* prefPage = nullptr;
260 
261  for(QList<QmitkPreferencesDialogPrivate::PrefPage>::iterator it = d->m_PrefPages.begin(); it != d->m_PrefPages.end(); ++it)
262  {
263  prefPage = it->prefPage;
264  if(prefPage) {
265  prefPage->PerformOk();
266  }
267  }
268 
276 }
277 
279 {
280  this->SavePreferences();
281 }
282 
284 {
285  berry::IQtPreferencePage* prefPage = d->m_PrefPages[d->m_CurrentPage].prefPage;
286  if(prefPage)
287  prefPage->PerformCancel();
288 }
289 
291 {
292  // search for text
293  this->UpdateTree();
294 }
295 
297 {
298 }
299 
300 //bool QmitkPreferencesDialog::eventFilter( QObject *obj, QEvent *event )
301 //{
302 // if(obj == d->m_Keyword)
303 // {
304 // if(event->type() == QEvent::FocusIn && d->m_Keyword->text() == "search ...")
305 // {
306 // d->m_Keyword->setText("");
307 // d->m_Keyword->setStyleSheet("color: black;");
308 // }
309 // else if(event->type() == QEvent::FocusOut && d->m_Keyword->text() == "")
310 // {
311 // d->m_Keyword->setText("search ...");
312 // d->m_Keyword->setStyleSheet("color: gray;");
313 // }
314 // }
315 // return true;
316 //}
317 
319 {
320  if(d->m_PreferencesTree == nullptr)
321  return;
322 
323  // TODO: create page and show it
324  QList<QTreeWidgetItem *> selectedItems = d->m_PreferencesTree->selectedItems();
325  if(selectedItems.size()>0)
326  {
327 
328  d->m_CurrentPage = 0;
330  for(QList<QmitkPreferencesDialogPrivate::PrefPage>::iterator it = d->m_PrefPages.begin(); it != d->m_PrefPages.end(); ++it, ++d->m_CurrentPage)
331  {
332  if(it->treeWidgetItem == selectedItems.at(0))
333  {
334  d->m_Headline->setText(it->name);
335  if(it->prefPage == nullptr)
336  {
337  berry::IPreferencePage* page = it->confElem->CreateExecutableExtension<berry::IPreferencePage>("class");
338  it->prefPage = dynamic_cast<berry::IQtPreferencePage*>(page);
339  it->prefPage->Init(berry::IWorkbench::Pointer(workbench));
340  it->prefPage->CreateQtControl(d->m_PreferencesPanel);
341  d->m_PreferencesPanel->addWidget(it->prefPage->GetQtControl());
342  }
343  d->m_PreferencesPanel->setCurrentWidget(it->prefPage->GetQtControl());
344 
345  break;
346  }
347  }
348  }
349 }
350 
352 {
353  if(d->m_PreferencesTree == nullptr)
354  return;
355 
356  d->m_PreferencesTree->sortByColumn(0, Qt::AscendingOrder);
357 
358  //m_PreferencesTree->clear();
359  QString keyword = d->m_Keyword->text().toLower();
360 
361  map<QString, QTreeWidgetItem*> items;
362  std::list< QList<QmitkPreferencesDialogPrivate::PrefPage>::iterator > deferredItems;
363 
364  for (QList<QmitkPreferencesDialogPrivate::PrefPage>::iterator it = d->m_PrefPages.begin();
365  it != d->m_PrefPages.end(); ++it)
366  {
367  if (it->treeWidgetItem == nullptr)
368  {
369  if (it->category.isEmpty())
370  {
371  it->treeWidgetItem = new QTreeWidgetItem(d->m_PreferencesTree);
372  it->treeWidgetItem->setText(0, it->name);
373  items[it->id] = it->treeWidgetItem;
374  }
375  else
376  {
377  // the parent might not be created yet
378  deferredItems.push_back(it);
379  }
380  }
381  }
382 
383  // deal with deferred items. We do not know how many levels
384  // of parents need to be created
385  auto currentItem = deferredItems.begin();
386 
387  while (currentItem != deferredItems.end())
388  {
389  auto currentItemContent = *currentItem;
390  if (items[currentItemContent->category] != nullptr)
391  {
392  currentItemContent->treeWidgetItem = new QTreeWidgetItem(items[currentItemContent->category]);
393  currentItemContent->treeWidgetItem->setText(0, currentItemContent->name);
394  items[currentItemContent->id] = currentItemContent->treeWidgetItem;
395 
396  deferredItems.erase(currentItem);
397  currentItem = deferredItems.begin();
398  }
399  else
400  {
401  ++currentItem;
402  }
403  }
404 
405  if (!deferredItems.empty())
406  {
407  MITK_ERROR << "Unknown preference category. They are added top-level.";
408 
409  for (const auto &currentItemContent : deferredItems)
410  {
411  currentItemContent->treeWidgetItem = new QTreeWidgetItem(d->m_PreferencesTree);
412  currentItemContent->treeWidgetItem->setText(0, currentItemContent->name);
413  items[currentItemContent->id] = currentItemContent->treeWidgetItem;
414  }
415  }
416 
417  //First, set all pages to hidden to avoid prolems
418  //when iterating over the child page first which contains a specific keyword
419  //and sets the parent to visible
420  //but after this the parent is searched for the keyword. However, the keyword might not be available
421  //so the parent and all of its children will be set to hidden.
422  if(!keyword.isEmpty())
423  {
424  for (QList<QmitkPreferencesDialogPrivate::PrefPage>::iterator it = d->m_PrefPages.begin();
425  it != d->m_PrefPages.end(); ++it)
426  {
427  it->treeWidgetItem->setHidden(true);
428  }
429  }
430  // we have to iterate over the list a second time, as only
431  // now all parents and items are guaranteed to be created
432  for (QList<QmitkPreferencesDialogPrivate::PrefPage>::iterator it = d->m_PrefPages.begin();
433  it != d->m_PrefPages.end(); ++it)
434  {
435  // hide treeWidgetItem if keyword not matches
436  if(!keyword.isEmpty())
437  {
438  //Split text of search box into multiple single strings
439  vector<string> keywordsAvailable = splitString(keyword.toUtf8().constData());
440  bool foundAll = true;
441 
442  //perform an AND-search
443  for(unsigned int i = 0; i < keywordsAvailable.size(); i++)
444  {
445  if (it->keywords.indexOf(QString::fromStdString(keywordsAvailable[i])) == -1)
446  {
447  foundAll = false;
448  break;
449  }
450  }
451 
452  if(foundAll)
453  {
454  //#make the whole branch visible
455  QTreeWidgetItem* treeWidgetParent = it->treeWidgetItem->parent();
456  while(treeWidgetParent!=nullptr)
457  {
458  treeWidgetParent->setHidden(false);
459  treeWidgetParent->setExpanded(true);
460  treeWidgetParent = treeWidgetParent->parent();
461  }
462 
463  it->treeWidgetItem->setHidden(false);
464  QFont f = it->treeWidgetItem->font(0);
465  f.setBold(true);
466  it->treeWidgetItem->setFont(0, f);
467  }
468  }
469  else
470  {
471  QFont f = it->treeWidgetItem->font(0);
472  f.setBold(false);
473  it->treeWidgetItem->setFont(0, f);
474  it->treeWidgetItem->setHidden(false);
475  }
476  }
477 
478  if(d->m_PrefPages.size()>0)
479  {
480  if(d->m_PrefPages.front().treeWidgetItem != nullptr)
481  d->m_PrefPages.front().treeWidgetItem->setSelected(true);
482  }
483 
484  d->m_PreferencesTree->expandAll();
485 }
virtual void Init(IWorkbench::Pointer workbench)=0
virtual void ExportPreferences(const QString &f, const QString &name="")=0
#define MITK_INFO
Definition: mitkLogMacros.h:18
static std::vector< std::string > splitString(const std::string &s, char delim=' ')
#define MITK_ERROR
Definition: mitkLogMacros.h:20
bool operator<(const StaticParameterMap::ValueType &a, const StaticParameterMap::ValueType &b)
Compares two var lists and returns true if the first list&#39;s first item is lower than the second one&#39;s...
STL namespace.
virtual void Update()=0
virtual SmartPointer< IPreferences > GetSystemPreferences()=0
virtual bool PerformOk()=0
MITKCORE_EXPORT bool operator==(const InteractionEvent &a, const InteractionEvent &b)
static IWorkbench * GetWorkbench()
virtual QList< SmartPointer< IConfigurationElement > > GetConfigurationElementsFor(const QString &extensionPointId) const =0
static IExtensionRegistry * GetExtensionRegistry()
QScopedPointer< QmitkPreferencesDialogPrivate > d
virtual void PerformCancel()=0
void SetSelectedPage(const QString &id)
virtual void ImportPreferences(const QString &f, const QString &name="")=0
QmitkPreferencesDialog(QWidget *parent=nullptr, Qt::WindowFlags f=nullptr)
void OnKeywordTextChanged(const QString &s)
static IPreferencesService * GetPreferencesService()