fw4spl
editor/SCreateActivity.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2016-2018.
3  * Distributed under the terms of the GNU Lesser General Public License (LGPL) as
4  * published by the Free Software Foundation.
5  * ****** END LICENSE BLOCK ****** */
6 
7 #include "activities/editor/SCreateActivity.hpp"
8 
9 #include <fwActivities/IBuilder.hpp>
10 #include <fwActivities/IValidator.hpp>
11 
12 #include <fwCom/Signal.hpp>
13 #include <fwCom/Signal.hxx>
14 #include <fwCom/Slot.hpp>
15 #include <fwCom/Slots.hpp>
16 #include <fwCom/Slots.hxx>
17 
18 #include <fwData/Composite.hpp>
19 #include <fwData/String.hpp>
20 #include <fwData/Vector.hpp>
21 
22 #include <fwGui/dialog/MessageDialog.hpp>
23 #include <fwGui/dialog/SelectorDialog.hpp>
24 
25 #include <fwGuiQt/container/QtContainer.hpp>
26 
27 #include <fwMedData/ActivitySeries.hpp>
28 
29 #include <fwRuntime/Bundle.hpp>
30 #include <fwRuntime/Convert.hpp>
31 #include <fwRuntime/operations.hpp>
32 
33 #include <fwServices/macros.hpp>
34 
35 #include <boost/foreach.hpp>
36 
37 #include <QGridLayout>
38 #include <QGroupBox>
39 #include <QLabel>
40 #include <QPainter>
41 #include <QPushButton>
42 #include <QScrollArea>
43 #include <QVBoxLayout>
44 
45 Q_DECLARE_METATYPE(::fwActivities::registry::ActivityInfo)
46 
47 namespace activities
48 {
49 namespace editor
50 {
51 
52 //------------------------------------------------------------------------------
53 
54 fwServicesRegisterMacro( ::fwGui::editor::IEditor, ::activities::editor::SCreateActivity );
55 
56 //------------------------------------------------------------------------------
57 
58 const ::fwCom::Signals::SignalKeyType SCreateActivity::s_ACTIVITY_ID_SELECTED_SIG = "activityIDSelected";
59 const ::fwCom::Signals::SignalKeyType SCreateActivity::s_LOAD_REQUESTED_SIG = "loadRequested";
60 
61 //------------------------------------------------------------------------------
62 
63 SCreateActivity::SCreateActivity() noexcept
64 {
65  newSignal< ActivityIDSelectedSignalType >(s_ACTIVITY_ID_SELECTED_SIG);
66  newSignal< LoadRequestedSignalType >(s_LOAD_REQUESTED_SIG);
67 }
68 
69 //------------------------------------------------------------------------------
70 
71 SCreateActivity::~SCreateActivity() noexcept
72 {
73 }
74 
75 //------------------------------------------------------------------------------
76 
77 void SCreateActivity::configuring()
78 {
80 
81  const auto cfg = this->getConfigTree();
82 
83  if(cfg.count("filter") == 1 )
84  {
85  const ::fwServices::IService::ConfigType& configFilter = cfg.get_child("filter");
86  SLM_ASSERT("A maximum of 1 <mode> tag is allowed", configFilter.count("mode") < 2);
87 
88  const std::string mode = configFilter.get< std::string >("mode");
89  SLM_ASSERT("'" + mode + "' value for <mode> tag isn't valid. Allowed values are : 'include', 'exclude'.",
90  mode == "include" || mode == "exclude");
91  m_filterMode = mode;
92 
93  BOOST_FOREACH( const ConfigType::value_type& v, configFilter.equal_range("id") )
94  {
95  m_keys.push_back(v.second.get<std::string>(""));
96  }
97  }
98  SLM_ASSERT("A maximum of 1 <filter> tag is allowed", cfg.count("filter") < 2);
99 }
100 
101 //------------------------------------------------------------------------------
102 
103 void SCreateActivity::starting()
104 {
106 
107  fwGuiQt::container::QtContainer::sptr qtContainer = fwGuiQt::container::QtContainer::dynamicCast(getContainer());
108 
109  QGroupBox* groupBox = new QGroupBox(tr("Activities") );
110 
111  QScrollArea* scrollArea = new QScrollArea();
112  scrollArea->setWidget(groupBox);
113  scrollArea->setWidgetResizable(true);
114 
115  QVBoxLayout* mainLayout = new QVBoxLayout();
116  mainLayout->addWidget(scrollArea);
117 
118  m_buttonGroup = new QButtonGroup(groupBox);
119 
120  ActivityInfoContainer infos = ::fwActivities::registry::Activities::getDefault()->getInfos();
121  m_activitiesInfo = this->getEnabledActivities(infos);
122 
123  // Add the load button
125  infoLoad.title = "Load activity";
126  infoLoad.icon = ::fwRuntime::getBundleResourceFilePath("media", "icons/LoadActivity.svg").string();
127  infoLoad.description = "Load a previously saved activity.";
128 
129  m_activitiesInfo.insert(m_activitiesInfo.begin(), infoLoad);
130 
131  size_t indexButton = 0;
132  size_t numCols = static_cast<size_t>(std::ceil(std::sqrt(static_cast<float>(m_activitiesInfo.size()))));
133  int numRows = static_cast<int>(std::floor(std::sqrt(static_cast<float>(m_activitiesInfo.size()))));
134  numCols = numCols + numCols + 1;
135 
136  QWidget* const container = qtContainer->getQtContainer();
137  container->setObjectName("activities");
138  std::string styleGrid("QGridLayout#activities {"
139  "border-width: 4px;"
140  "}");
141  container->setStyleSheet(QString::fromUtf8(styleGrid.c_str()));
142 
143  QGridLayout* activitiesLayout = new QGridLayout();
144  activitiesLayout->setRowMinimumHeight(0, 5);
145  activitiesLayout->setRowStretch(0, 2);
146  groupBox->setLayout(activitiesLayout);
147 
148  QFont font;
149  font.setPointSize(12);
150  font.setBold(true);
151 
152  std::string style("QPushButton#activityButton {"
153  "padding: 16px;"
154  "text-align:bottom"
155  "}");
156 
157  int i = 1;
158  int j = 0;
159 
160  for(const ::fwActivities::registry::ActivityInfo& info : m_activitiesInfo)
161  {
162  QPushButton* button = new QPushButton(QIcon(info.icon.c_str()), QString::fromStdString(" " + info.title));
163  button->setToolTip(QString::fromStdString(info.description));
164  button->setIconSize(QSize(80, 80));
165  button->setObjectName("activityButton");
166  button->setFont(font);
167 
168  button->setStyleSheet(QString::fromUtf8(style.c_str()));
169  m_buttonGroup->addButton(button, static_cast<int>(indexButton));
170 
171  QLabel* label = new QLabel(QString::fromStdString(info.description));
172  label->setWordWrap(true);
173 
174  activitiesLayout->setColumnMinimumWidth(j, 10);
175  activitiesLayout->setColumnStretch(j, 5);
176  activitiesLayout->addWidget(button, i, j + 1);
177 
178  activitiesLayout->addWidget(label, i + 1, j + 1);
179  j += 2;
180  if(j == static_cast<int>(numCols) - 1 )
181  {
182  activitiesLayout->setColumnMinimumWidth(j, 10);
183  activitiesLayout->setColumnStretch(j, 5);
184  i += 3;
185  j = 0;
186  }
187 
188  activitiesLayout->setRowMinimumHeight(i + 2, 5);
189  activitiesLayout->setRowStretch(i + 2, 1);
190 
191  ++indexButton;
192  }
193 
194  activitiesLayout->setRowMinimumHeight(numRows * 3, 5);
195  activitiesLayout->setRowStretch(numRows * 3, 2);
196 
197  qtContainer->setLayout(mainLayout);
198 
199  this->connect(m_buttonGroup, SIGNAL(buttonClicked(int)), SLOT(onClicked(int)));
200 }
201 
202 //------------------------------------------------------------------------------
203 
204 void SCreateActivity::stopping()
205 {
206  this->disconnect();
207  this->destroy();
208 }
209 
210 //------------------------------------------------------------------------------
211 
212 void SCreateActivity::updating()
213 {
214 }
215 
216 //------------------------------------------------------------------------------
217 
218 void SCreateActivity::onClicked(int id)
219 {
220  if(id == 0)
221  {
222  auto sig = this->signal<LoadRequestedSignalType>(s_LOAD_REQUESTED_SIG);
223  sig->asyncEmit();
224  }
225  else
226  {
227  auto sig = this->signal<ActivityIDSelectedSignalType>(s_ACTIVITY_ID_SELECTED_SIG);
228  sig->asyncEmit(m_activitiesInfo[ static_cast<size_t>(id)].id);
229  }
230 }
231 
232 //------------------------------------------------------------------------------
233 
234 SCreateActivity::ActivityInfoContainer SCreateActivity::getEnabledActivities(const ActivityInfoContainer& infos)
235 {
236  ActivityInfoContainer configs;
237 
238  if(m_filterMode == "include" || m_filterMode == "exclude")
239  {
240  const bool isIncludeMode = m_filterMode == "include";
241 
242  for(ActivityInfoContainer::const_iterator iter = infos.begin(); iter != infos.end(); ++iter)
243  {
244  KeysType::iterator keyIt = std::find(m_keys.begin(), m_keys.end(), iter->id);
245 
246  if(keyIt != m_keys.end() && isIncludeMode)
247  {
248  configs.push_back(*iter);
249  }
250  else if(keyIt == m_keys.end() && !isIncludeMode)
251  {
252  configs.push_back(*iter);
253  }
254  }
255  }
256  else
257  {
258  configs = infos;
259  }
260 
261  return configs;
262 }
263 
264 //------------------------------------------------------------------------------
265 
266 } // namespace editor
267 } // namespace activities
Holds Activities configuration.
Definition: Activities.hpp:175
Defines the service interface managing the editor service for object.
Definition: IEditor.hpp:25
static FWACTIVITIES_API Activities::sptr getDefault()
Return the default global instance of Activities.
Definition: Activities.cpp:226
This editor launchs an activity according to the given configuration.
#define SLM_ASSERT(message, cond)
work like &#39;assert&#39; from &#39;cassert&#39;, with in addition a message logged by spylog (with FATAL loglevel) ...
Definition: spyLog.hpp:308
The namespace activities contains helpers and services allowing to launch activities.
FWGUI_API void create()
Creates view, sub-views and toolbar containers. Manages sub-views and toobar services.
FWGUI_API void initialize()
Initialize managers.