7 #include "activities/action/SActivityLauncher.hpp" 9 #include <fwActivities/IActivityValidator.hpp> 10 #include <fwActivities/IBuilder.hpp> 11 #include <fwActivities/IValidator.hpp> 13 #include <fwCom/Signal.hpp> 14 #include <fwCom/Signal.hxx> 15 #include <fwCom/Slot.hpp> 16 #include <fwCom/Slots.hpp> 17 #include <fwCom/Slots.hxx> 19 #include <fwData/Composite.hpp> 20 #include <fwData/String.hpp> 21 #include <fwData/Vector.hpp> 23 #include <fwDataCamp/getObject.hpp> 25 #include <fwGui/dialog/MessageDialog.hpp> 26 #include <fwGui/dialog/SelectorDialog.hpp> 28 #include <fwMedData/ActivitySeries.hpp> 30 #include <fwRuntime/Bundle.hpp> 31 #include <fwRuntime/Convert.hpp> 32 #include <fwRuntime/operations.hpp> 34 #include <fwServices/IAppConfigManager.hpp> 35 #include <fwServices/macros.hpp> 36 #include <fwServices/registry/ActiveWorkers.hpp> 37 #include <fwServices/registry/AppConfig.hpp> 39 #include <fwTools/UUID.hpp> 41 #include <boost/foreach.hpp> 43 #include <QApplication> 45 #include <QHBoxLayout> 46 #include <QListWidget> 47 #include <QPushButton> 48 #include <QStandardItemModel> 49 #include <QVBoxLayout> 64 const ::fwCom::Slots::SlotKeyType SActivityLauncher::s_LAUNCH_SERIES_SLOT =
"launchSeries";
65 const ::fwCom::Slots::SlotKeyType SActivityLauncher::s_LAUNCH_ACTIVITY_SERIES_SLOT =
"launchActivitySeries";
66 const ::fwCom::Slots::SlotKeyType SActivityLauncher::s_UPDATE_STATE_SLOT =
"updateState";
67 const ::fwCom::Signals::SignalKeyType SActivityLauncher::s_ACTIVITY_LAUNCHED_SIG =
"activityLaunched";
69 static const ::fwServices::IService::KeyType s_SERIES_INPUT =
"series";
73 SActivityLauncher::SActivityLauncher() noexcept :
76 m_sigActivityLaunched = newSignal< ActivityLaunchedSignalType >(s_ACTIVITY_LAUNCHED_SIG);
78 newSlot(s_LAUNCH_SERIES_SLOT, &SActivityLauncher::launchSeries,
this);
79 newSlot(s_LAUNCH_ACTIVITY_SERIES_SLOT, &SActivityLauncher::launchActivitySeries,
this);
80 newSlot(s_UPDATE_STATE_SLOT, &SActivityLauncher::updateState,
this);
85 SActivityLauncher::~SActivityLauncher() noexcept
91 void SActivityLauncher::starting()
93 this->actionServiceStarting();
99 void SActivityLauncher::stopping()
102 this->actionServiceStopping();
107 void SActivityLauncher::configuring()
110 typedef ::fwServices::IService::ConfigType ConfigType;
112 m_parameters.clear();
113 if(this->getConfigTree().count(
"config") > 0)
115 SLM_ASSERT(
"There must be one (and only one) <config/> element.",
116 this->getConfigTree().count(
"config") == 1 );
118 const ::fwServices::IService::ConfigType srvconfig = this->getConfigTree();
119 const ::fwServices::IService::ConfigType& config = srvconfig.get_child(
"config");
121 m_mode = config.get_optional<std::string>(
"mode").get_value_or(
"message");
122 SLM_ASSERT(
"SActivityLauncher mode must be either 'immediate' or 'message'",
123 "message" == m_mode ||
"immediate" == m_mode);
125 if(config.count(
"parameters") == 1 )
127 const ::fwServices::IService::ConfigType& configParameters = config.get_child(
"parameters");
128 BOOST_FOREACH(
const ConfigType::value_type& v, configParameters.equal_range(
"parameter") )
130 ParametersType::value_type parameter( v.second );
131 m_parameters.push_back( parameter );
134 OSLM_ASSERT(
"A maximum of 1 <parameters> tag is allowed", config.count(
"parameters") < 2);
136 if(config.count(
"filter") == 1 )
138 const ::fwServices::IService::ConfigType& configFilter = config.get_child(
"filter");
139 OSLM_ASSERT(
"A maximum of 1 <mode> tag is allowed", configFilter.count(
"mode") < 2);
141 const std::string mode = configFilter.get< std::string >(
"mode");
142 OSLM_ASSERT(
"'" << mode <<
"' value for <mode> tag isn't valid. Allowed values are : 'include', 'exclude'.",
143 mode ==
"include" || mode ==
"exclude");
146 BOOST_FOREACH(
const ConfigType::value_type& v, configFilter.equal_range(
"id") )
148 m_keys.push_back(v.second.get<std::string>(
""));
151 OSLM_ASSERT(
"A maximum of 1 <filter> tag is allowed", config.count(
"filter") < 2);
153 if(config.count(
"quickLaunch") == 1 )
155 m_quickLaunch.clear();
156 const ::fwServices::IService::ConfigType& configQuickLaunch = config.get_child(
"quickLaunch");
157 BOOST_FOREACH(
const ConfigType::value_type& v, configQuickLaunch.equal_range(
"association") )
159 const ::fwServices::IService::ConfigType& association = v.second;
160 const ::fwServices::IService::ConfigType xmlattr = association.get_child(
"<xmlattr>");
162 SLM_FATAL_IF(
"The attribute \"type\" is missing", xmlattr.count(
"type") != 1 );
163 SLM_FATAL_IF(
"The attribute \"id\" is missing", xmlattr.count(
"id") != 1 );
165 std::string type = xmlattr.get<std::string>(
"type");
166 std::string
id = xmlattr.get<std::string>(
"id");
168 m_quickLaunch[type] = id;
171 SLM_ASSERT(
"A maximum of 1 <quickLaunch> tag is allowed", config.count(
"quickLaunch") < 2);
179 QWidget* parent = qApp->activeWindow();
181 QDialog* dialog =
new QDialog(parent);
182 dialog->setWindowTitle(QString::fromStdString(
"Choose an activity"));
184 QStandardItemModel* model =
new QStandardItemModel(dialog);
188 if(info.title.empty())
194 text = info.title + (info.description.empty() ?
"" :
"\n" + info.description);
197 QStandardItem* item =
new QStandardItem(QIcon(info.icon.c_str()), QString::fromStdString(text));
198 item->setData(QVariant::fromValue(info));
199 item->setEditable(
false);
200 model->appendRow(item);
203 QListView* selectionList =
new QListView();
204 selectionList->setIconSize(QSize(100, 100));
205 selectionList->setUniformItemSizes(
true);
206 selectionList->setModel(model);
208 QModelIndex index = model->index( 0, 0 );
209 if ( index.isValid() )
211 selectionList->selectionModel()->select( index, QItemSelectionModel::Select );
214 QPushButton* okButton =
new QPushButton(
"Ok");
215 QPushButton* cancelButton =
new QPushButton(
"Cancel");
217 QHBoxLayout* hLayout =
new QHBoxLayout();
218 hLayout->addWidget(okButton);
219 hLayout->addWidget(cancelButton);
221 QVBoxLayout* vLayout =
new QVBoxLayout();
222 vLayout->addWidget(selectionList);
223 vLayout->addLayout(hLayout);
225 dialog->setLayout(vLayout);
226 QObject::connect(okButton, SIGNAL(clicked()), dialog, SLOT(accept()));
227 QObject::connect(cancelButton, SIGNAL(clicked()), dialog, SLOT(reject()));
228 QObject::connect(selectionList, SIGNAL(doubleClicked(
const QModelIndex&)), dialog, SLOT(accept()));
233 QModelIndex currentIndex = selectionList->selectionModel()->currentIndex();
234 QStandardItem* item = model->itemFromIndex( currentIndex );
235 QVariant var = item->data();
244 SActivityLauncher::ActivityInfoContainer SActivityLauncher::getEnabledActivities(
const ActivityInfoContainer& infos)
246 ActivityInfoContainer configs;
248 if(m_filterMode ==
"include" || m_filterMode ==
"exclude")
250 const bool isIncludeMode = m_filterMode ==
"include";
252 for(ActivityInfoContainer::const_iterator iter = infos.begin(); iter != infos.end(); ++iter)
254 KeysType::iterator keyIt = std::find(m_keys.begin(), m_keys.end(), iter->id);
256 if(keyIt != m_keys.end() && isIncludeMode)
258 configs.push_back(*iter);
260 else if(keyIt == m_keys.end() && !isIncludeMode)
262 configs.push_back(*iter);
276 void SActivityLauncher::updating()
278 ::fwData::Vector::csptr selection = this->getInput< ::fwData::Vector >(s_SERIES_INPUT);
282 selection = this->getObject< ::fwData::Vector >();
285 bool launchAS = this->launchAS(selection);
289 infos = this->getEnabledActivities(infos);
294 if((m_keys.size() == 1 && m_filterMode ==
"include") || (infos.size() == 1))
300 info = this->show( infos );
303 if( !info.id.empty() )
305 this->sendConfig( info );
311 "Not available activity for the current selection.",
312 ::fwGui::dialog::MessageDialog::WARNING);
319 void SActivityLauncher::updateState()
321 ::fwData::Vector::csptr selection = this->getInput< ::fwData::Vector >(s_SERIES_INPUT);
325 selection = this->getObject< ::fwData::Vector >();
328 bool isExecutable =
false;
330 if(selection->size() == 1 && ::fwMedData::ActivitySeries::dynamicCast((*selection)[0]))
332 ::fwMedData::ActivitySeries::sptr as = ::fwMedData::ActivitySeries::dynamicCast((*selection)[0]);
334 if(m_filterMode ==
"include" || m_filterMode ==
"exclude")
336 const bool isIncludeMode = m_filterMode ==
"include";
338 KeysType::iterator keyIt = std::find(m_keys.begin(), m_keys.end(), as->getActivityConfigId());
340 if(keyIt != m_keys.end() && isIncludeMode)
344 else if(keyIt == m_keys.end() && !isIncludeMode)
349 as->getActivityConfigId());
354 as->getActivityConfigId());
359 ::fwActivities::registry::ActivityInfo::DataCountType dataCount;
361 if(m_filterMode.empty() && dataCount.size() == 1)
363 ::fwData::Object::sptr obj = selection->front();
364 if (::fwMedData::ActivitySeries::dynamicCast(obj))
371 infos = this->getEnabledActivities(infos);
373 isExecutable |= !infos.empty();
376 this->setIsExecutable(isExecutable);
381 void SActivityLauncher::buildActivity(const ::fwActivities::registry::ActivityInfo& info,
382 const ::fwData::Vector::csptr& selection)
384 ::fwData::Composite::sptr replaceMap = ::fwData::Composite::New();
385 ::fwActivities::IBuilder::sptr builder;
386 builder = ::fwActivities::builder::factory::New(info.builderImpl);
387 OSLM_ASSERT(info.builderImpl <<
" instantiation failed", builder);
389 ::fwMedData::ActivitySeries::sptr actSeries;
390 actSeries = builder->buildData(info, selection);
394 std::string msg =
"The activity <" + info.title +
"> can't be launched. Builder <" + info.builderImpl +
397 ::fwGui::dialog::IMessageDialog::WARNING);
403 if (!info.validatorsImpl.empty())
405 for (std::string validatorImpl : info.validatorsImpl)
408 ::fwActivities::IValidator::sptr validator = ::fwActivities::validator::factory::New(validatorImpl);
410 ::fwActivities::IActivityValidator::sptr activityValidator =
411 ::fwActivities::IActivityValidator::dynamicCast(validator);
413 if (activityValidator)
416 if(!validation.first)
418 std::string message =
"The activity '" + info.title +
"' can not be launched:\n" +
422 ::fwGui::dialog::IMessageDialog::CRITICAL);
429 ParametersType parameters = this->translateParameters(m_parameters);
432 if( m_mode ==
"message" )
434 m_sigActivityLaunched->asyncEmit(msg);
441 ::fwActivities::registry::ActivityMsg::ReplaceMapType replaceMap = msg.
getReplaceMap();
442 replaceMap[
"GENERIC_UID"] =
446 helper->setConfig( viewConfigID, replaceMap );
448 helper->stopAndDestroy();
454 void SActivityLauncher::sendConfig( const ::fwActivities::registry::ActivityInfo& info )
457 std::shared_ptr< ::fwRuntime::Bundle > bundle = ::fwRuntime::findBundle(info.bundleId, info.bundleVersion);
458 SLM_WARN_IF(
"Bundle '" + info.bundleId +
"' used by activity '" + info.id +
"' is already started.",
459 bundle->isStarted());
460 if (!bundle->isStarted())
462 SLM_DEBUG(
"Start bundle '" + info.bundleId +
"' used by activity '" + info.id +
"'");
466 ::fwData::Vector::csptr selection = this->getInput< ::fwData::Vector >(s_SERIES_INPUT);
470 selection = this->getObject< ::fwData::Vector >();
474 validation.first =
true;
476 for(
auto const& validatorImpl : info.validatorsImpl)
478 ::fwActivities::IValidator::sptr validator = ::fwActivities::validator::factory::New(validatorImpl);
479 OSLM_ASSERT(validatorImpl <<
" instantiation failed", validator);
482 validation.first &= valid.first;
485 validation.second +=
"\n" + valid.second;
489 if(!validation.first)
492 "Activity can not be launched",
493 "The activity " + info.title +
" can't be launched. Reason : " + validation.second,
494 ::fwGui::dialog::IMessageDialog::WARNING
499 this->buildActivity(info, selection);
505 bool SActivityLauncher::launchAS(const ::fwData::Vector::csptr& selection)
507 bool launchAS =
false;
508 ::fwActivities::registry::ActivityInfo::DataCountType dataCount;
510 if(dataCount.size() == 1)
512 for(::fwData::Object::sptr obj : *selection)
514 ::fwMedData::ActivitySeries::sptr as = ::fwMedData::ActivitySeries::dynamicCast(obj);
522 this->launchActivitySeries(as);
532 void SActivityLauncher::launchSeries(::fwMedData::Series::sptr series)
534 ::fwMedData::ActivitySeries::sptr as = ::fwMedData::ActivitySeries::dynamicCast(series);
537 this->launchActivitySeries(as);
541 ::fwData::Vector::sptr selection = ::fwData::Vector::New();
542 selection->getContainer().push_back(series);
545 if( m_quickLaunch.find( series->getClassname() ) != m_quickLaunch.end() )
547 std::string activityId = m_quickLaunch[ series->getClassname() ];
548 SLM_ASSERT(
"Activity information not found for" + activityId,
552 else if ( !infos.empty() )
554 this->sendConfig( infos.front() );
559 "Not available activity for the current selection.",
560 ::fwGui::dialog::MessageDialog::WARNING);
567 void SActivityLauncher::launchActivitySeries(::fwMedData::ActivitySeries::sptr series)
578 ::fwActivities::IValidator::sptr validator = ::fwActivities::validator::factory::New(validatorImpl);
580 ::fwActivities::IActivityValidator::sptr activityValidator =
581 ::fwActivities::IActivityValidator::dynamicCast(validator);
583 if (activityValidator)
586 if(!validation.first)
588 std::string message =
"The activity '" + info.title +
"' can not be launched:\n" +
592 ::fwGui::dialog::IMessageDialog::CRITICAL);
599 ParametersType parameters = this->translateParameters(m_parameters);
602 m_sigActivityLaunched->asyncEmit(msg);
607 SActivityLauncher::ParametersType SActivityLauncher::translateParameters(
const ParametersType& parameters )
609 ParametersType transParams = parameters;
610 ::fwData::Object::csptr workingObj = this->getInput< ::fwData::Object >(s_SERIES_INPUT);
614 workingObj = this->getObject();
616 for(ParametersType::value_type& param : transParams)
620 std::string parameterToReplace = param.by;
621 if (parameterToReplace.substr(0, 1) ==
"!")
623 parameterToReplace.replace(0, 1,
"@");
626 ::fwData::Object::sptr obj = ::fwDataCamp::getObject(workingObj, parameterToReplace);
627 OSLM_ASSERT(
"Invalid seshat path : '"<<param.by<<
"'", obj);
629 ::fwData::String::sptr stringParameter = ::fwData::String::dynamicCast(obj);
631 std::string parameterValue = obj->getID();
633 if(stringParameter && param.by.substr(0, 1) ==
"!")
635 parameterValue = stringParameter->getValue();
637 param.by = parameterValue;
661 if (this->getInput< ::fwData::Object >(s_SERIES_INPUT))
#define FW_DEPRECATED_KEY(newKey, access, version)
Use this macro when deprecating a service key to warn the developer.
This class is a helper to define the connections of a service and its data.
std::pair< bool, std::string > ValidationType
Defines validation result of an activity. First element tells if the activity is validated or not by ...
const ReplaceMapType & getReplaceMap() const
Return the map of the string association to replace in config.
Holds Activities configuration.
#define OSLM_ASSERT(message, cond)
work like 'assert' from 'cassert', with in addition a message logged by spylog (with FATAL loglevel) ...
#define SLM_TRACE_FUNC()
Trace contextual function signature.
static FWGUI_API IMessageDialog::Buttons showMessageDialog(const std::string &title, const std::string &message,::fwGui::dialog::IMessageDialog::Icons icon=INFO)
static FWACTIVITIES_API Activities::sptr getDefault()
Return the default global instance of Activities.
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_ADDED_OBJECTS_SIG
Type of signal when objects are added.
#define SLM_DEBUG(message)
Defines the service interface managing the menu items.
This class defines a vector of objects.
Activity information sent by signal to launch new activities in a tab.
const std::string & getAppConfigID() const
Return appConfig identifier.
#define OSLM_ERROR(message)
This action launchs an activity according to the selected data.
#define SLM_ASSERT(message, cond)
work like 'assert' from 'cassert', with in addition a message logged by spylog (with FATAL loglevel) ...
FWGUI_API void initialize()
Initialize the action.
The namespace activities contains helpers and services allowing to launch activities.
::fwCom::helper::SigSlotConnection::KeyConnectionsType KeyConnectionsType
Returns proposals to connect service slots to associated object signals, this method is used for obj/...
#define SLM_FATAL_IF(message, cond)
static FWSERVICES_API std::shared_ptr< IAppConfigManager > New()
static FWSERVICES_API std::string getUniqueIdentifier(const std::string &serviceUid="")
Create an unique identifier.
std::vector< std::string > validatorsImpl
Validator implementations.
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_REMOVED_OBJECTS_SIG
Type of signal when objects are added.
#define SLM_WARN_IF(message, cond)