CustusX  2023.01.05-dev+develop.0da12
An IGT application
cxFiltersWidget.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) SINTEF Department of Medical Technology.
5 All rights reserved.
6 
7 CustusX is released under a BSD 3-Clause license.
8 
9 See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
10 =========================================================================*/
11 
12 #include "cxFiltersWidget.h"
13 
14 #include "cxStringProperty.h"
15 
16 
19 #include "cxLogger.h"
20 #include "cxDummyFilter.h"
23 #include "cxContourFilter.h"
24 #include "cxSmoothingImageFilter.h"
25 #include "cxGenericScriptFilter.h"
26 #include "cxResampleImageFilter.h"
27 #include "cxColorVariationFilter.h"
28 #include "cxFilterPresetWidget.h"
29 #include "cxDilationFilter.h"
30 #include "cxPluginFramework.h"
31 #include "cxLogicManager.h"
32 #include <boost/bind.hpp>
33 #include <boost/shared_ptr.hpp>
34 #include <boost/shared_ptr.hpp>
35 #include "cxNullDeleter.h"
36 #include "cxProfile.h"
37 
38 namespace cx {
39 
40 FiltersWidget::FiltersWidget(VisServicesPtr services, QWidget* parent, QStringList wantedFilters, QString optionfileTag) :
41  BaseWidget(parent, "algorithm_widgets_configurable_filter", "All Filters"),
42  mWantedFilters(wantedFilters)
43 {
44  XmlOptionFile options = profile()->getXmlSettings().descend(optionfileTag);
45  mFilters.reset(new FilterGroup(options));
46 
47  this->appendFilters(services);
48 
49  this->setWindowTitleAndObjectNameBasedOnWantedFilters();
50 
51  this->configureFilterSelector(options);
52 
53  this->setupLayout(services, options);
54 
55  this->filterChangedSlot();
56 }
57 
59 {
60  return QString("<html>"
61  "<h3>Filter Widget.</h3>"
62  "<p>Select one type of filter.</p>"
63  "<p><i>Currently selected filter:</i></p>"
64  "<p>%1</p>"
65  "</html>").arg(mSetupWidget->generateHelpText());
66 }
67 
68 void FiltersWidget::filterChangedSlot()
69 {
70  for (unsigned i=0; i<mFilters->size(); ++i)
71  {
72  if (mFilters->get(i)->getUid() == mFilterSelector->getValue())
73  {
74  mCurrentFilter = mFilters->get(i);
75  }
76  }
77 
78  mSetupWidget->setFilter(mCurrentFilter);
79  mFilterSelector->setHelp(this->generateHelpText());
80 }
81 
82 void FiltersWidget::toggleDetailsSlot()
83 {
84  mSetupWidget->toggleDetailed();
85 
86 }
87 
88 void FiltersWidget::runFilterSlot()
89 {
90  if (!mCurrentFilter)
91  return;
92  if (mThread)
93  {
94  reportWarning(QString("Last operation on %1 is not finished. Could not start filtering").arg(mThread->getFilter()->getName()));
95  return;
96  }
97 
98  mThread.reset(new FilterTimedAlgorithm(mCurrentFilter));
99  connect(mThread.get(), SIGNAL(finished()), this, SLOT(finishedSlot()));
100  mTimedAlgorithmProgressBar->attach(mThread);
101 
102  mThread->execute();
103 }
104 
105 void FiltersWidget::finishedSlot()
106 {
107  mTimedAlgorithmProgressBar->detach(mThread);
108  disconnect(mThread.get(), SIGNAL(finished()), this, SLOT(finishedSlot()));
109  mThread.reset();
110 }
111 
112 void FiltersWidget::onServiceAdded(Filter* service)
113 {
114  this->appendFilterIfWanted(FilterPtr(service, null_deleter()));
115 }
116 
117 void FiltersWidget::onServiceRemoved(Filter *service)
118 {
119  mFilters->remove(service);
120 }
121 
122 void FiltersWidget::appendFiltersThatAreNotServices(VisServicesPtr services)
123 {
124  this->appendFilterIfWanted(FilterPtr(new BinaryThresholdImageFilter(services)));
125  this->appendFilterIfWanted(FilterPtr(new BinaryThinningImageFilter3DFilter(services)));
126  this->appendFilterIfWanted(FilterPtr(new ContourFilter(services)));
127  this->appendFilterIfWanted(FilterPtr(new ColorVariationFilter(services)));
128  this->appendFilterIfWanted(FilterPtr(new SmoothingImageFilter(services)));
129  this->appendFilterIfWanted(FilterPtr(new GenericScriptFilter(services)));
130  this->appendFilterIfWanted(FilterPtr(new ResampleImageFilter(services)));
131  this->appendFilterIfWanted(FilterPtr(new DilationFilter(services)));
132 }
133 
134 void FiltersWidget::appendFilterServices()
135 {
136  mServiceListener.reset(
138  LogicManager::getInstance()->getPluginContext(),
139  boost::bind(&FiltersWidget::onServiceAdded, this, _1),
140  boost::function<void(Filter*)>(),
141  boost::bind(&FiltersWidget::onServiceRemoved, this, _1)));
142  mServiceListener->open();
143 }
144 
145 void FiltersWidget::appendFilters(VisServicesPtr services)
146 {
147  this->appendFiltersThatAreNotServices(services);
148  this->appendFilterServices();
149 }
150 
151 void FiltersWidget::appendFilterIfWanted(FilterPtr filter)
152 {
153  if(mWantedFilters.empty() || mWantedFilters.contains(filter->getName()))
154  mFilters->append(filter);
155 }
156 
157 void FiltersWidget::configureFilterSelector(XmlOptionFile options)
158 {
159  QStringList availableFilters;
160  std::map<QString,QString> names;
161  for (unsigned i=0; i<mFilters->size(); ++i)
162  {
163  availableFilters << mFilters->get(i)->getUid();
164  names[mFilters->get(i)->getUid()] = mFilters->get(i)->getName();
165  }
166  if(availableFilters.isEmpty())
167  {
168  availableFilters << "FILTER NOT FOUND";
169  }
170  mFilterSelector = StringProperty::initialize("filterSelector",
171  "Filter",
172  "Select which filter to use.",
173  availableFilters[0],
174  availableFilters,
175  options.getElement());
176  mFilterSelector->setDisplayNames(names);
177  connect(mFilterSelector.get(), &StringProperty::valueWasSet, this, &FiltersWidget::filterChangedSlot);
178 }
179 
180 void FiltersWidget::addDetailedButton(QHBoxLayout* filterLayout)
181 {
182  QAction* detailsAction = this->createAction(this,
183  QIcon(":/icons/open_icon_library/system-run-5.png"),
184  "Details", "Toggle Details",
185  SLOT(toggleDetailsSlot()),
186  NULL);
187 
188  QToolButton* detailsButton = new QToolButton();
189  detailsButton->setObjectName("DetailedButton");
190  detailsButton->setDefaultAction(detailsAction);
191  filterLayout->addWidget(detailsButton);
192 }
193 
194 void FiltersWidget::addRunButton(QHBoxLayout* filterLayout)
195 {
196  QAction* runAction = this->createAction(this,
197  QIcon(":/icons/open_icon_library/arrow-right-3.png"),
198  "Run Filter", "",
199  SLOT(runFilterSlot()),
200  NULL);
201 
202  CXSmallToolButton* button = new CXSmallToolButton();
203  button->setObjectName("RunFilterButton");
204  button->setDefaultAction(runAction);
205  filterLayout->addWidget(button);
206 }
207 
208 QHBoxLayout * FiltersWidget::addFilterSelector(QVBoxLayout* topLayout)
209 {
210  QHBoxLayout* filterLayout = new QHBoxLayout;
211  topLayout->addLayout(filterLayout);
212  LabeledComboBoxWidget* filterSelectorWidget = new LabeledComboBoxWidget(this, mFilterSelector);
213  filterSelectorWidget->showLabel(false);
214  filterLayout->addWidget(filterSelectorWidget);
215 
216  return filterLayout;
217 }
218 
219 void FiltersWidget::addProgressBar(QVBoxLayout* topLayout)
220 {
221  mTimedAlgorithmProgressBar = new cx::TimedAlgorithmProgressBar;
222  topLayout->addWidget(mTimedAlgorithmProgressBar);
223 }
224 
225 void FiltersWidget::addFilterWidget(XmlOptionFile options, VisServicesPtr services, QVBoxLayout* topLayout)
226 {
227  mSetupWidget = new FilterSetupWidget(services, this, options, false);
228  topLayout->addWidget(mSetupWidget);
229 }
230 
231 void FiltersWidget::setWindowTitleAndObjectNameBasedOnWantedFilters()
232 {
233  if(mWantedFilters.size() == 1)
234  {
235  this->setWindowTitle(mWantedFilters.first());
236  this->setObjectName(mWantedFilters.first()+" Widget");
237  }
238  else if(mWantedFilters.empty())
239  {
240  this->setWindowTitle("All Filters");
241  this->setObjectName("algorithm_widgets_configurable_filter");
242  }
243 }
244 
245 void FiltersWidget::setupLayout(VisServicesPtr services, XmlOptionFile options)
246 {
247  QVBoxLayout* topLayout = new QVBoxLayout(this);
248  QHBoxLayout* filterLayout = addFilterSelector(topLayout);
249  this->addDetailedButton(filterLayout);
250  this->addRunButton(filterLayout);
251  this->addProgressBar(topLayout);
252  this->addFilterWidget(options, services, topLayout);
253  topLayout->addStretch();
254 }
255 
256 } /* namespace cx */
cxResource_EXPORT ProfilePtr profile()
Definition: cxProfile.cpp:160
boost::shared_ptr< class VisServices > VisServicesPtr
Definition: cxMainWindow.h:40
FiltersWidget(VisServicesPtr services, QWidget *parent, QStringList wantedFilters=QStringList(), QString optionfileTag="filterwidget")
FiltersWidget Widget for displaying N image filters.
Composite widget for string selection.
Show progress for a TimedBaseAlgorithm.
QDomElement getElement()
return the current element
void addRunButton(QHBoxLayout *filterLayout)
QAction * createAction(QObject *parent, QIcon iconName, QString text, QString tip, T slot, QLayout *layout=NULL, QToolButton *button=new QToolButton())
Definition: cxBaseWidget.h:129
void detach(TimedAlgorithmPtr algorithm)
boost::shared_ptr< class Filter > FilterPtr
void reportWarning(QString msg)
Definition: cxLogger.cpp:70
static LogicManager * getInstance()
QString generateHelpText() const
void setFilter(FilterPtr filter)
void attach(TimedAlgorithmPtr algorithm)
static StringPropertyPtr initialize(const QString &uid, QString name, QString help, QString value, QStringList range, QDomNode root=QDomNode())
Helper class for listening to services being added, modified and removed.
Interface for QWidget which handles widgets uniformly for the system.
Definition: cxBaseWidget.h:88
QString generateHelpText() const
Helper class for xml files used to store ssc/cx data.
Namespace for all CustusX production code.