7 #include "uiTF/TransferFunctionEditor.hpp" 9 #include <fwCore/base.hpp> 11 #include <fwData/Composite.hpp> 12 #include <fwData/TransferFunction.hpp> 14 #include <fwDataTools/helper/Composite.hpp> 16 #include <fwGui/dialog/InputDialog.hpp> 17 #include <fwGui/dialog/LocationDialog.hpp> 18 #include <fwGui/dialog/MessageDialog.hpp> 20 #include <fwGuiQt/container/QtContainer.hpp> 22 #include <fwIO/ioTypes.hpp> 23 #include <fwIO/IReader.hpp> 24 #include <fwIO/IWriter.hpp> 26 #include <fwRuntime/EConfigurationElement.hpp> 27 #include <fwRuntime/operations.hpp> 29 #include <fwServices/macros.hpp> 30 #include <fwServices/op/Add.hpp> 32 #include <boost/filesystem/convenience.hpp> 33 #include <boost/filesystem/operations.hpp> 34 #include <boost/foreach.hpp> 39 #include <QPushButton> 46 static const ::fwServices::IService::KeyType s_TF_POOL_INOUT =
"tfPool";
47 static const ::fwServices::IService::KeyType s_TF_OUTPUT =
"tf";
48 static const ::fwServices::IService::KeyType s_CURRENT_TF_INPUT =
"currentTF";
74 bool useDefaultPath =
true;
75 if (srvConfig.count(
"config"))
77 const ConfigType config = srvConfig.get_child(
"config");
79 const auto pathCfg = config.equal_range(
"path");
80 for(
auto itCfg = pathCfg.first; itCfg != pathCfg.second; ++itCfg)
82 const auto path = ::fwRuntime::getBundleResourceFilePath(itCfg->second.get_value<std::string>());
83 m_paths.push_back(path);
86 const std::string value = config.get(
"<xmlattr>.useDefaultPath",
"yes");
87 SLM_FATAL_IF(
"'useDefaultPath' value must be 'yes' or 'no'", value !=
"yes" && value !=
"no");
89 useDefaultPath = (value ==
"yes");
93 const auto pathRoot = ::fwRuntime::getBundleResourceFilePath(
"uiTF",
"tf");
94 m_paths.push_back(pathRoot);
105 ::fwGuiQt::container::QtContainer::sptr qtContainer
106 = ::fwGuiQt::container::QtContainer::dynamicCast(this->getContainer());
109 m_pTransferFunctionPreset =
new QComboBox();
111 ::boost::filesystem::path bundlePath = ::fwRuntime::getBundleResourcePath(std::string(
"uiTF"));
113 const auto deletePath = bundlePath /
"delete.png";
114 m_deleteButton =
new QPushButton(QIcon(deletePath.string().c_str()),
"");
115 m_deleteButton->setToolTip(QString(
"Delete"));
117 const auto newPath = bundlePath /
"new.png";
118 m_newButton =
new QPushButton(QIcon(newPath.string().c_str()),
"");
119 m_newButton->setToolTip(QString(
"New"));
121 const auto reinitializePath = bundlePath /
"reinitialize.png";
122 m_reinitializeButton =
new QPushButton(QIcon(reinitializePath.string().c_str()),
"");
123 m_reinitializeButton->setToolTip(QString(
"Reinitialize"));
125 const auto renamePath = bundlePath /
"rename.png";
126 m_renameButton =
new QPushButton(QIcon(renamePath.string().c_str()),
"");
127 m_renameButton->setToolTip(QString(
"Rename"));
129 const auto importPath = bundlePath /
"import.png";
130 m_importButton =
new QPushButton(QIcon(importPath.string().c_str()),
"");
131 m_importButton->setToolTip(QString(
"Import"));
133 const auto exportPath = bundlePath /
"export.png";
134 m_exportButton =
new QPushButton(QIcon(exportPath.string().c_str()),
"");
135 m_exportButton->setToolTip(QString(
"Export"));
138 QBoxLayout* layout =
new QBoxLayout(QBoxLayout::LeftToRight);
140 layout->addWidget(m_pTransferFunctionPreset);
141 layout->addWidget(m_deleteButton);
142 layout->addWidget(m_newButton);
143 layout->addWidget(m_reinitializeButton);
144 layout->addWidget(m_renameButton);
145 layout->addWidget(m_importButton);
146 layout->addWidget(m_exportButton);
148 qtContainer->setLayout(layout);
151 QObject::connect(m_pTransferFunctionPreset, SIGNAL(activated(
int)),
this, SLOT(presetChoice(
int)));
152 QObject::connect(m_deleteButton, SIGNAL(clicked()),
this, SLOT(deleteTF()));
153 QObject::connect(m_newButton, SIGNAL(clicked()),
this, SLOT(newTF()));
154 QObject::connect(m_reinitializeButton, SIGNAL(clicked()),
this, SLOT(reinitializeTFPool()));
155 QObject::connect(m_renameButton, SIGNAL(clicked()),
this, SLOT(renameTF()));
156 QObject::connect(m_importButton, SIGNAL(clicked()),
this, SLOT(importTF()));
157 QObject::connect(m_exportButton, SIGNAL(clicked()),
this, SLOT(exportTF()));
175 QObject::disconnect(m_pTransferFunctionPreset, SIGNAL(activated(
int)),
this, SLOT(presetChoice(
int)));
176 QObject::disconnect(m_deleteButton, SIGNAL(clicked()),
this, SLOT(deleteTF()));
177 QObject::disconnect(m_newButton, SIGNAL(clicked()),
this, SLOT(newTF()));
178 QObject::disconnect(m_reinitializeButton, SIGNAL(clicked()),
this, SLOT(reinitializeTFPool()));
179 QObject::disconnect(m_renameButton, SIGNAL(clicked()),
this, SLOT(renameTF()));
180 QObject::disconnect(m_importButton, SIGNAL(clicked()),
this, SLOT(importTF()));
181 QObject::disconnect(m_exportButton, SIGNAL(clicked()),
this, SLOT(exportTF()));
190 if (key == s_CURRENT_TF_INPUT)
198 void TransferFunctionEditor::presetChoice(
int index)
200 m_pTransferFunctionPreset->setCurrentIndex(index);
203 std::string tfName = m_pTransferFunctionPreset->currentText().toStdString();
206 m_renameButton->setEnabled(isEnabled);
207 m_deleteButton->setEnabled(isEnabled);
212 void TransferFunctionEditor::deleteTF()
215 messageBox.
setTitle(
"Deleting confirmation");
216 messageBox.
setMessage(
"Are you sure you want to delete this transfer function?");
217 messageBox.
setIcon(::fwGui::dialog::IMessageDialog::QUESTION);
218 messageBox.
addButton(::fwGui::dialog::IMessageDialog::YES);
219 messageBox.
addButton(::fwGui::dialog::IMessageDialog::CANCEL);
222 if (answerCopy != ::fwGui::dialog::IMessageDialog::CANCEL)
224 ::fwData::Composite::sptr poolTF = this->getInOut< ::fwData::Composite >(s_TF_POOL_INOUT);
225 SLM_ASSERT(
"inout '" + s_TF_POOL_INOUT +
"' is not defined.", poolTF);
227 if( poolTF->size() > 1 )
229 int indexSelectedTF = m_pTransferFunctionPreset->currentIndex();
230 std::string selectedTFKey = m_pTransferFunctionPreset->currentText().toStdString();
234 compositeHelper.
remove(selectedTFKey);
243 m_pTransferFunctionPreset->removeItem(indexSelectedTF);
246 int index = m_pTransferFunctionPreset->findText(QString::fromStdString(defaultTFName));
247 index = std::max(index, 0);
248 this->presetChoice(index);
254 "You can not remove this transfer function because the program requires at least one.",
255 ::fwGui::dialog::IMessageDialog::WARNING );
262 void TransferFunctionEditor::newTF()
264 std::string newName = m_selectedTF->getName();
271 inputDialog.
setTitle(
"Creating transfer function");
272 inputDialog.
setMessage(
"Transfer function name:");
276 if (!newName.empty())
280 ::fwData::TransferFunction::sptr pNewTransferFunction;
283 pNewTransferFunction->setName(newName);
285 ::fwData::Composite::sptr poolTF = this->getInOut< ::fwData::Composite >(s_TF_POOL_INOUT);
286 SLM_ASSERT(
"inout '" + s_TF_POOL_INOUT +
"' is not defined.", poolTF);
289 compositeHelper.
add(newName, pNewTransferFunction);
291 m_pTransferFunctionPreset->addItem(QString(newName.c_str()));
292 m_pTransferFunctionPreset->setCurrentIndex(m_pTransferFunctionPreset->count()-1);
301 "This transfer function name already exists so you can not overwrite it.",
302 ::fwGui::dialog::IMessageDialog::WARNING);
309 void TransferFunctionEditor::reinitializeTFPool()
312 messageBox.
setTitle(
"Reinitializing confirmation");
313 messageBox.
setMessage(
"Are you sure you want to reinitialize all transfer functions?");
314 messageBox.
setIcon(::fwGui::dialog::IMessageDialog::QUESTION);
315 messageBox.
addButton(::fwGui::dialog::IMessageDialog::YES);
316 messageBox.
addButton(::fwGui::dialog::IMessageDialog::CANCEL);
319 if (answerCopy != ::fwGui::dialog::IMessageDialog::CANCEL)
321 ::fwData::Composite::sptr poolTF = this->getInOut< ::fwData::Composite >(s_TF_POOL_INOUT);
322 SLM_ASSERT(
"inout '" + s_TF_POOL_INOUT +
"' is not defined.", poolTF);
325 compositeHelper.
clear();
336 void TransferFunctionEditor::renameTF()
338 std::string str = m_pTransferFunctionPreset->currentText().toStdString();
339 std::string newName(str);
342 inputDialog.
setTitle(
"Creating transfer function");
343 inputDialog.
setMessage(
"Transfer function name:");
347 if (!newName.empty() && newName != str)
351 ::fwData::Composite::sptr poolTF = this->getInOut< ::fwData::Composite >(s_TF_POOL_INOUT);
352 SLM_ASSERT(
"inout '" + s_TF_POOL_INOUT +
"' is not defined.", poolTF);
354 ::fwData::TransferFunction::sptr pTF;
355 pTF = ::fwData::TransferFunction::dynamicCast((*poolTF)[str]);
356 pTF->setName(newName);
359 compositeHelper.
remove(str);
360 compositeHelper.
add(newName, pTF);
363 m_pTransferFunctionPreset->setItemText(m_pTransferFunctionPreset->currentIndex(), QString(newName.c_str()));
364 m_pTransferFunctionPreset->setCurrentIndex(m_pTransferFunctionPreset->findText(QString(newName.c_str())));
372 messageBox.
setMessage(
"This transfer function name already exists so you can not overwrite it.");
373 messageBox.
setIcon(::fwGui::dialog::IMessageDialog::WARNING);
374 messageBox.
addButton(::fwGui::dialog::IMessageDialog::OK);
378 if ( newName.empty() )
382 messageBox.
setMessage(
"You have to give a name to your transfer function.");
383 messageBox.
setIcon(::fwGui::dialog::IMessageDialog::WARNING);
384 messageBox.
addButton(::fwGui::dialog::IMessageDialog::OK);
391 void TransferFunctionEditor::importTF()
393 ::fwData::Composite::sptr poolTF = this->getInOut< ::fwData::Composite >(s_TF_POOL_INOUT);
394 SLM_ASSERT(
"inout '" + s_TF_POOL_INOUT +
"' is not defined.", poolTF);
398 ::fwData::TransferFunction::sptr tf = ::fwData::TransferFunction::New();
399 ::fwIO::IReader::sptr reader = ::fwServices::add< ::fwIO::IReader >(
"::ioAtoms::SReader");
401 reader->registerInOut(tf, ::fwIO::s_DATA_KEY);
404 reader->configureWithIHM();
405 reader->update().wait();
406 reader->stop().wait();
407 ::fwServices::OSR::unregisterService(reader);
409 if (!tf->getName().empty())
416 compositeHelper.
add(tf->getName(), tf);
417 m_pTransferFunctionPreset->addItem(QString(tf->getName().c_str()));
418 this->presetChoice(static_cast<int>((*poolTF).size()-1));
426 void TransferFunctionEditor::exportTF()
428 ::fwIO::IWriter::sptr writer = ::fwServices::add< ::fwIO::IWriter >(
"::ioAtoms::SWriter");
430 writer->registerInput(m_selectedTF, ::fwIO::s_DATA_KEY);
433 writer->configureWithIHM();
434 writer->update().wait();
435 writer->stop().wait();
436 ::fwServices::OSR::unregisterService(writer);
444 ::fwData::Composite::sptr poolTF = this->getInOut< ::fwData::Composite >(s_TF_POOL_INOUT);
445 SLM_ASSERT(
"inout '" + s_TF_POOL_INOUT +
"' is not defined.", poolTF);
452 ::fwData::TransferFunction::sptr defaultTf = ::fwData::TransferFunction::createDefaultTF();
453 compositeHelper.
add(defaultTFName, defaultTf);
457 if( poolTF->size() <= 1 )
460 std::vector< ::boost::filesystem::path > paths;
461 for(::boost::filesystem::path dirPath : m_paths)
463 SLM_ASSERT(
"Invalid directory path '"+dirPath.string()+
"'", ::boost::filesystem::exists(dirPath));
464 for(::boost::filesystem::directory_iterator it(dirPath);
465 it != ::boost::filesystem::directory_iterator();
468 if(!::boost::filesystem::is_directory(*it) &&
469 ::boost::filesystem::extension(*it) ==
".json")
471 paths.push_back(*it);
476 ::fwData::TransferFunction::sptr tf = ::fwData::TransferFunction::New();
477 ::fwIO::IReader::sptr reader = ::fwServices::add< ::fwIO::IReader >(
"::ioAtoms::SReader");
478 reader->registerInOut(tf, ::fwIO::s_DATA_KEY);
480 ::fwRuntime::EConfigurationElement::sptr srvCfg = ::fwRuntime::EConfigurationElement::New(
"service");
481 ::fwRuntime::EConfigurationElement::sptr fileCfg = ::fwRuntime::EConfigurationElement::New(
"file");
482 srvCfg->addConfigurationElement(fileCfg);
484 for( ::boost::filesystem::path file : paths )
486 fileCfg->setValue(file.string());
487 reader->setConfiguration(srvCfg);
493 if (!tf->getName().empty())
495 ::fwData::TransferFunction::sptr newTF = ::fwData::Object::copy< ::fwData::TransferFunction >(tf);
501 compositeHelper.
add(newTF->getName(), newTF);
505 ::fwServices::OSR::unregisterService(reader);
516 ::fwData::Composite::sptr poolTF = this->getInOut< ::fwData::Composite >(s_TF_POOL_INOUT);
517 SLM_ASSERT(
"inout '" + s_TF_POOL_INOUT +
"' is not defined.", poolTF);
521 m_pTransferFunctionPreset->clear();
524 m_pTransferFunctionPreset->addItem( elt.first.c_str() );
527 std::string currentTFName = defaultTFName;
528 ::fwData::TransferFunction::csptr tf = this->getInput< ::fwData::TransferFunction >(s_CURRENT_TF_INPUT);
532 currentTFName = tf->getName();
534 else if (m_selectedTF)
536 currentTFName = m_selectedTF->getName();
539 int index = m_pTransferFunctionPreset->findText( QString::fromStdString(currentTFName) );
540 index = std::max(index, 0);
542 this->presetChoice(index);
549 ::fwData::Composite::sptr poolTF = this->getInOut< ::fwData::Composite >(s_TF_POOL_INOUT);
550 SLM_ASSERT(
"inout '" + s_TF_POOL_INOUT +
"' is not defined.", poolTF);
551 return poolTF->find(_sName) != poolTF->end();
558 bool bHasTransferFunctionName =
true;
559 std::string newName = _sBasename;
561 while (bHasTransferFunctionName)
563 std::stringstream tmpStr;
564 tmpStr << _sBasename <<
"_" << cpt;
565 newName = tmpStr.str();
577 ::fwData::Composite::sptr poolTF = this->getInOut< ::fwData::Composite >(s_TF_POOL_INOUT);
578 SLM_ASSERT(
"inout '" + s_TF_POOL_INOUT +
"' is not defined.", poolTF);
580 std::string newSelectedTFKey = m_pTransferFunctionPreset->currentText().toStdString();
581 SLM_DEBUG(
"Transfer function selected : " + newSelectedTFKey);
585 ::fwData::Object::sptr newSelectedTF = (*poolTF)[newSelectedTFKey];
587 if(newSelectedTF && m_selectedTF != newSelectedTF)
589 this->
setOutput(s_TF_OUTPUT, newSelectedTF);
590 m_selectedTF = ::fwData::TransferFunction::dynamicCast(newSelectedTF);
UITF_API bool hasTransferFunctionName(const std::string &_sName) const
Check if the image contain the specified TF.
This class is a helper to define the connections of a service and its data.
virtual UITF_API KeyConnectionsMap getAutoConnections() const override
Returns proposals to connect service slots to associated object signals, this method is used for obj/...
virtual UITF_API ~TransferFunctionEditor() noexcept
Basic destructor, do nothing.
static FWDATA_API const std::string s_DEFAULT_TF_NAME
Default transfer function name.
virtual UITF_API void stopping() override
Stop the TransferFunctionEditor, disconnect Buttons and Combo Box, delete them and clean the containe...
Class allowing to block a Connection.
virtual FWGUI_API void setMessage(const std::string &msg) override
Set the message.
Defines the service interface managing the editor service for object.
Defines the generic message box for IHM. Use the Delegate design pattern.
static FWGUI_API IMessageDialog::Buttons showMessageDialog(const std::string &title, const std::string &message,::fwGui::dialog::IMessageDialog::Icons icon=INFO)
FWGUI_API void destroy()
Stops sub-views and toobar services. Destroys view, sub-views and toolbar containers.
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_CHANGED_OBJECTS_SIG
Type of signal when objects are added.
virtual UITF_API void starting() override
Start the TransferFunctionEditor, create Container, place in Buttons, ComboBox, Layout, and connect them.
ContainerType::value_type value_type
virtual void swapping()
Swap the service from associated object to another object.
#define SLM_DEBUG(message)
UpdateSlotType::sptr m_slotUpdate
Slot to call update method.
FWSERVICES_API void setOutput(const ::fwServices::IService::KeyType &key, const ::fwData::Object::sptr &object, size_t index=0)
Register an output object at a given key in the OSR, replacing it if it already exists.
Editor to select a transfer function.
virtual FWGUI_API void addButton(IMessageDialog::Buttons button) override
Add a button (OK, YES_NO, YES, NO, CANCEL)
virtual FWGUI_API IMessageDialog::Buttons show() override
Show the message box and return the clicked button.
Transfert functions editor.
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_REMOVED_OBJECTS_SIG
Type of signal when objects are added.
UITF_API void updateTransferFunction()
Update the output transferFunction with the selected TF in the ComboBox.
#define SLM_ASSERT(message, cond)
work like 'assert' from 'cassert', with in addition a message logged by spylog (with FATAL loglevel) ...
static FWDATA_API::fwData::Object::sptr copy(const ::fwData::Object::csptr &source)
return a copy of the source. if source is a null pointer, return a null pointer.
virtual UITF_API void updating() override
Update the TransferFunctionEditor, do nothing.
FWGUI_API void create()
Creates view, sub-views and toolbar containers. Manages sub-views and toobar services.
virtual FWGUI_API void setIcon(IMessageDialog::Icons icon) override
Set the icon (CRITICAL, WARNING, INFO or QUESTION)
#define SLM_FATAL_IF(message, cond)
UITF_API void updateTransferFunctionPreset()
Update the TF preset from the TF pool.
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_ADDED_OBJECTS_SIG
Type of signal when objects are added.
UITF_API void initTransferFunctions()
Initialize the transfer functions.
virtual UITF_API void configuring() override
Configure the transfer function editor.
static FWSERVICES_APIconst::fwCom::Slots::SlotKeyType s_UPDATE_SLOT
Slot to call start method.
virtual FWGUI_API void setTitle(const std::string &title) override
Set the title of the message box.
UITF_API std::string createTransferFunctionName(const std::string &_sBasename) const
FWGUI_API void initialize()
Initialize managers.
UITF_API TransferFunctionEditor()
Basic constructor, do nothing.
FWSERVICES_API ConfigType getConfigTree() const
Return the configuration, in an boost property tree.