Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
QmitkCmdLineModuleMenuComboBox.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 
14 #include <iostream>
15 #include <QString>
16 #include <QStringList>
17 #include <QDebug>
18 #include <QMenu>
19 #include <QAction>
20 #include <QList>
21 #include <cassert>
22 #include <ctkCmdLineModuleDescription.h>
23 #include <ctkCmdLineModuleReference.h>
24 #include <ctkCmdLineModuleManager.h>
25 
26 // -------------------------------------------------------------------------
28 : ctkMenuComboBox(parent)
29 , m_ModuleManager(nullptr)
30 {
31  qRegisterMetaType<ctkCmdLineModuleReference>();
32 }
33 
34 
35 // -------------------------------------------------------------------------
37 {
38 
39 }
40 
41 
42 // -------------------------------------------------------------------------
43 void QmitkCmdLineModuleMenuComboBox::SetManager(ctkCmdLineModuleManager* manager)
44 {
45  if (m_ModuleManager != nullptr)
46  {
47  QObject::disconnect(manager, nullptr, this, nullptr);
48  }
49 
50  m_ModuleManager = manager;
51 
52  connect(m_ModuleManager, SIGNAL(moduleRegistered(const ctkCmdLineModuleReference&)), this, SLOT(OnModuleRegistered(const ctkCmdLineModuleReference&)));
53  connect(m_ModuleManager, SIGNAL(moduleUnregistered(const ctkCmdLineModuleReference&)), this, SLOT(OnModuleUnRegistered(const ctkCmdLineModuleReference&)));
54 }
55 
56 
57 // -------------------------------------------------------------------------
58 ctkCmdLineModuleManager* QmitkCmdLineModuleMenuComboBox::GetManager() const
59 {
60  return m_ModuleManager;
61 }
62 
63 
64 // -------------------------------------------------------------------------
65 void QmitkCmdLineModuleMenuComboBox::OnModuleRegistered(const ctkCmdLineModuleReference&)
66 {
67  this->RebuildMenu();
68 }
69 
70 
71 // -------------------------------------------------------------------------
72 void QmitkCmdLineModuleMenuComboBox::OnModuleUnRegistered(const ctkCmdLineModuleReference&)
73 {
74  this->RebuildMenu();
75 }
76 
77 
78 // -------------------------------------------------------------------------
79 void QmitkCmdLineModuleMenuComboBox::AddName(
80  QList< QHash<QString, QMenu*>* >& listOfHashMaps,
81  const int& depth,
82  const QString& name,
83  QMenu* menu
84  )
85 {
86  if (depth >= listOfHashMaps.size())
87  {
88  int need = depth - listOfHashMaps.size();
89  for (int i = 0; i <= need; i++)
90  {
91  auto newHashMap = new QHash<QString, QMenu*>();
92  listOfHashMaps.push_back(newHashMap);
93  }
94  }
95  listOfHashMaps[depth]->insert(name, menu);
96 }
97 
98 
99 // -------------------------------------------------------------------------
100 void QmitkCmdLineModuleMenuComboBox::RebuildMenu()
101 {
102  if (m_ModuleManager == nullptr)
103  {
104  qDebug() << "QmitkCmdLineModuleMenuComboBox::RebuildMenu(): Module Manager is nullptr? Surely a bug?";
105  return;
106  }
107 
108  // Can't see another way to get a nested menu, without rebuilding the whole thing each time.
109  // :-(
110 
111  auto menu = new QMenu();
112  QStringList listOfModules;
113 
114  QList<ctkCmdLineModuleReference> references = m_ModuleManager->moduleReferences();
115 
116  // Get full names
117  for (int i = 0; i < references.size(); i++)
118  {
119  ctkCmdLineModuleReference reference = references[i];
120  ctkCmdLineModuleDescription description = reference.description();
121  QString title = description.title();
122  QString category = description.category();
123  QString fullName = category + "." + title;
124  listOfModules << fullName;
125  }
126 
127  // Sort list, so menu comes out in some sort of nice order.
128  listOfModules.sort();
129 
130  // Temporary data structure to enable connecting menus together.
131  QList< QHash<QString, QMenu*>* > list;
132 
133  // Iterate through all modules.
134  foreach (QString fullName, listOfModules)
135  {
136  // Pointer to keep track of where we are in the menu tree.
137  QMenu *currentMenu = menu;
138 
139  // Get individual parts, as they correspond to menu levels.
140  QStringList nameParts = fullName.split(".", QString::SkipEmptyParts);
141 
142  // Iterate over each part, building up either a QMenu or QAction.
143  for (int i = 0; i < nameParts.size(); i++)
144  {
145  QString part = nameParts[i];
146 
147  if (i != nameParts.size() - 1)
148  {
149  // Need to add a menu/submenu, not an action.
150  if (list.size() <= i || list[i] == nullptr || !list[i]->contains(part))
151  {
152  auto newMenu = new QMenu(part);
153  currentMenu->addMenu(newMenu);
154  currentMenu = newMenu;
155 
156  // Add this newMenu pointer to temporary datastructure,
157  // so we know we have already created it.
158  this->AddName(list, i, part, newMenu);
159  }
160  else
161  {
162  currentMenu = list[i]->value(part);
163  }
164  }
165  else
166  {
167  // Leaf node, just add the action.
168  QAction *action = currentMenu->addAction(part);
169 
170  // We set the object name, so we can retrieve it later when we want to
171  // rebuild a new GUI depending on the name of the action.
172  // see QmitkCmdLineModuleProgressWidget.
173  action->setObjectName(fullName);
174  }
175  }
176  }
177 
178  // Clearup termporary data structure
179  for (int i = 0; i < list.size(); i++)
180  {
181  delete list[i];
182  }
183 
184  // Set the constructed menu on the base class combo box.
185  this->setMenu(menu);
186 }
void SetManager(ctkCmdLineModuleManager *manager)
Inject the module manager, so that this widget can still easily be used via widget promotion in Qt De...
QmitkCmdLineModuleMenuComboBox(QWidget *parent=nullptr)
ctkCmdLineModuleManager * GetManager() const
Returns the ctkCmdLineModuleManager.
The custom viewer plugin implements simple viewer functionality presented in a customized look and feel It was developed to demonstrate extensibility and customizability of the blueberry application framework As an example for the GUI customization capabilities provided by the BlueBerry application the custom viewer plugin was developed It features simple viewer functionality presented in a customized look and feel The custom viewer consists of two i e a viewer perspective and a DICOM perspective As part of the viewer an instance of QmitkDataManagerView allows for data selection Visualization of the selected data is then performed by a simple render window view According data can either be directly loaded from file or be imported as DICOM data DICOM import functionality is accessible from the DICOM perspective incorporating the QmitkDicomExternalDataWidget The customization of Qt Stylesheets is used to give the application a non native look and feel This is further emphasized by a Tab Widget like unification of the perspectives with the according perspective bar In addition to an absence of menu