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