Isis 3 Programmer Reference
FilterGroup.cpp
1 
7 /* SPDX-License-Identifier: CC0-1.0 */
8 
9 #include "IsisDebug.h"
10 
11 #include "FilterGroup.h"
12 
13 #include <QButtonGroup>
14 #include <QGroupBox>
15 #include <QPushButton>
16 #include <QHBoxLayout>
17 #include <QIcon>
18 #include <QLabel>
19 #include <QRadioButton>
20 #include <QString>
21 #include <QVBoxLayout>
22 
23 #include "IException.h"
24 #include "IString.h"
25 #include "FileName.h"
26 
27 #include "AbstractFilterSelector.h"
28 #include "ImageImageFilterSelector.h"
29 #include "PointMeasureFilterSelector.h"
30 #include "ImagePointFilterSelector.h"
31 
32 
33 using std::nothrow;
34 using std::swap;
35 
36 namespace Isis {
37  FilterGroup::FilterGroup(QString type) {
38  nullify();
39 
40  m_filterType = new QString(type);
41 
42  init();
43  addSelector();
44  }
45 
46 
47  FilterGroup::FilterGroup(const FilterGroup &other) {
48  nullify();
49 
50  m_filterType = new QString(*other.m_filterType);
51 
52  init();
53 
54  foreach (AbstractFilterSelector * selector, *other.m_selectors) {
55  AbstractFilterSelector *newSelector = NULL;
56  if (*m_filterType == "Points and Measures") {
57  newSelector = new PointMeasureFilterSelector(
58  *((PointMeasureFilterSelector *) selector));
59  }
60  else {
61  if (*m_filterType == "Images and Points") {
62  newSelector = new ImagePointFilterSelector(
63  *((ImagePointFilterSelector *) selector));
64  }
65  else {
66  if (*m_filterType == "Connections") {
67  newSelector = new ImageImageFilterSelector(
68  *((ImageImageFilterSelector *) selector));
69  }
70  }
71  }
72 
73  addSelector(newSelector);
74  }
75 
76  m_buttonGroup->button(other.m_buttonGroup->checkedId())->click();
77  }
78 
79 
80  FilterGroup::~FilterGroup() {
81  if (m_buttonGroup) {
82  delete m_buttonGroup;
83  m_buttonGroup = NULL;
84  }
85 
86  if (m_selectors) {
87  delete m_selectors;
88  m_selectors = NULL;
89  }
90 
91  if (m_filterType) {
92  delete m_filterType;
93  m_filterType = NULL;
94  }
95  }
96 
97 
98  bool FilterGroup::hasFilter(bool (AbstractFilter::*meth)() const) const {
99  bool found = false;
100 
101  for (int i = 0; !found && i < m_selectors->size(); i++)
102  if (meth)
103  found = m_selectors->at(i)->hasFilter(meth);
104  else
105  found = m_selectors->at(i)->hasFilter();
106 
107  return found;
108  }
109 
110 
111  void FilterGroup::nullify() {
112  m_buttonGroup = NULL;
113  m_closeButton = NULL;
114  m_groupBoxLayout = NULL;
115  m_selectors = NULL;
116  }
117 
118 
119  void FilterGroup::init() {
120  m_selectors = new QList< AbstractFilterSelector * >;
121 
122  QLabel *descriptionLabel = new QLabel("Combine filters using logic "
123  "type: ");
124  QFont descriptionFont("SansSerif", 11);
125  descriptionLabel->setFont(descriptionFont);
126  QFont logicTypeFont("SansSerif", 12, QFont::Bold);
127  QRadioButton *andButton = new QRadioButton("and");
128  andButton->setFont(logicTypeFont);
129  QRadioButton *orButton = new QRadioButton("or");
130  orButton->setFont(logicTypeFont);
131  m_buttonGroup = new QButtonGroup;
132  m_buttonGroup->addButton(andButton, 0);
133  m_buttonGroup->addButton(orButton, 1);
134  connect(m_buttonGroup, SIGNAL(buttonClicked(int)), this,
135  SLOT(changeFilterCombinationLogic(int)));
136 
137  // FIXME: this should be controlled by QSettings
138  andButton->click();
139 
140  QHBoxLayout *logicLayout = new QHBoxLayout;
141  QMargins margins = logicLayout->contentsMargins();
142  margins.setBottom(4);
143  logicLayout->setContentsMargins(margins);
144  logicLayout->addStretch();
145  logicLayout->addWidget(descriptionLabel);
146  logicLayout->addWidget(andButton);
147  logicLayout->addWidget(orButton);
148  logicLayout->addStretch();
149  m_logicWidget = new QWidget;
150  m_logicWidget->setLayout(logicLayout);
151 
152  m_newSelectorButton = new QPushButton;
153  m_newSelectorButton->setIcon(QIcon(
154  FileName("$ISISROOT/appdata/images/icons/add.png").expanded()));
155  QString newSelectorTooltip = "Add new filter";
156  m_newSelectorButton->setToolTip(newSelectorTooltip);
157  m_newSelectorButton->setStatusTip(newSelectorTooltip);
158 
159  connect(m_newSelectorButton, SIGNAL(clicked()), this, SLOT(addSelector()));
160  QHBoxLayout *newSelectorLayout = new QHBoxLayout;
161  newSelectorLayout->addWidget(m_newSelectorButton);
162  newSelectorLayout->addStretch();
163 
164  m_groupBoxLayout = new QVBoxLayout;
165  m_groupBoxLayout->addWidget(m_logicWidget);
166  m_groupBoxLayout->addLayout(newSelectorLayout);
167  QGroupBox *groupBox = new QGroupBox;
168  groupBox->setLayout(m_groupBoxLayout);
169 
170  QVBoxLayout *mainLayout = new QVBoxLayout;
171  margins = mainLayout->contentsMargins();
172  margins.setTop(2);
173  margins.setBottom(2);
174  mainLayout->setContentsMargins(margins);
175  mainLayout->addWidget(groupBox);
176 
177  setLayout(mainLayout);
178  }
179 
180 
181  void FilterGroup::addSelector() {
182  AbstractFilterSelector *filterSelector = NULL;
183  if (*m_filterType == "Points and Measures")
184  filterSelector = new PointMeasureFilterSelector;
185  else if (*m_filterType == "Images and Points")
186  filterSelector = new ImagePointFilterSelector;
187  else if (*m_filterType == "Connections")
188  filterSelector = new ImageImageFilterSelector;
189 
190  addSelector(filterSelector);
191  }
192 
193 
194  void FilterGroup::addSelector(AbstractFilterSelector *newSelector) {
195  ASSERT(newSelector);
196 
197  if (newSelector) {
198  connect(newSelector, SIGNAL(close(AbstractFilterSelector *)),
199  this, SLOT(deleteSelector(AbstractFilterSelector *)));
200  connect(newSelector, SIGNAL(filterChanged()),
201  this, SIGNAL(filterChanged()));
202  connect(newSelector, SIGNAL(sizeChanged()),
203  this, SLOT(sendSizeChanged()));
204  m_groupBoxLayout->insertWidget(m_groupBoxLayout->count() - 1, newSelector);
205  m_selectors->append(newSelector);
206  m_selectors->size() > 1 ? m_logicWidget->show() : m_logicWidget->hide();
207  }
208 
209  sendSizeChanged();
210  }
211 
212 
213  void FilterGroup::deleteSelector(AbstractFilterSelector *filterSelector) {
214  m_groupBoxLayout->removeWidget(filterSelector);
215  delete filterSelector;
216  m_selectors->removeOne(filterSelector);
217 
218  int m_selectorsSize = m_selectors->size();
219  m_selectorsSize > 1 ? m_logicWidget->show() : m_logicWidget->hide();
220  if (!m_selectorsSize)
221  emit close(this);
222  else
223  emit filterChanged();
224  }
225 
226 
227  void FilterGroup::sendClose() {
228  emit close(this);
229  }
230 
231 
232  void FilterGroup::sendSizeChanged() {
233  emit sizeChanged(this);
234  }
235 
236 
237  void FilterGroup::changeFilterCombinationLogic(int button) {
238  m_andFiltersTogether = button == 0;
239  emit filterChanged();
240  }
241 
242 
243  bool FilterGroup::filtersAreAndedTogether() const {
244  return m_andFiltersTogether;
245  }
246 
247 
248  FilterGroup &FilterGroup::operator=(FilterGroup other) {
249  ASSERT(m_filterType);
250  ASSERT(m_selectors);
251  ASSERT(m_buttonGroup);
252 
253  // create temporary list of new selectors
255  foreach (AbstractFilterSelector * selector, *other.m_selectors) {
256  AbstractFilterSelector *newSelector = NULL;
257  if (*m_filterType == "Points and Measures") {
258  newSelector = new(nothrow) PointMeasureFilterSelector(
259  *((PointMeasureFilterSelector *) selector));
260  }
261  else {
262  if (*m_filterType == "Images and Points") {
263  newSelector = new(nothrow) ImagePointFilterSelector(
264  *((ImagePointFilterSelector *) selector));
265  }
266  else {
267  if (*m_filterType == "Connections") {
268  newSelector = new(nothrow) ImageImageFilterSelector(
269  *((ImageImageFilterSelector *) selector));
270  }
271  }
272  }
273 
274  if (newSelector) {
275  *newSelector = *selector;
276  newSelectors.append(newSelector);
277  }
278  }
279 
280  // if all is ok, and it is safe to assign
281  if (newSelectors.size() == other.m_selectors->size()) {
282  foreach (AbstractFilterSelector * selector, *m_selectors) {
283  deleteSelector(selector);
284  }
285 
286  foreach (AbstractFilterSelector * newSelector, newSelectors) {
287  addSelector(newSelector);
288  }
289 
290  swap(*m_filterType, *other.m_filterType);
291  m_buttonGroup->button(other.m_buttonGroup->checkedId())->click();
292  }
293  else {
294  // clean up any temp groups
295  foreach (AbstractFilterSelector * newSelector, newSelectors) {
296  if (newSelector) {
297  delete newSelector;
298  newSelector = NULL;
299  }
300  }
301 
302  IString msg = "Assignment of FilterGroup failed";
303  throw IException(IException::Programmer, msg, _FILEINFO_);
304  }
305 
306  return *this;
307  }
308 
309 
310  QString FilterGroup::getDescription(
311  bool (AbstractFilter::*hasFilterMeth)() const,
312  QString(AbstractFilter::*descriptionMeth)() const) const {
313  QString description;
314 
315  ASSERT(m_selectors);
316 
317  QList< AbstractFilterSelector * > selectorsWithFilters;
318  for (int i = 0; i < m_selectors->size(); i++)
319  if (m_selectors->at(i)->hasFilter(hasFilterMeth))
320  selectorsWithFilters.append(m_selectors->at(i));
321 
322  int numFilters = selectorsWithFilters.size();
323 
324  if (numFilters) {
325  QString logic = "<b> ";
326  if (m_andFiltersTogether)
327  logic += "and";
328  else
329  logic += "or";
330  logic += " </b>";
331 
332  for (int i = 0; i < numFilters - 1; i++) {
333  description += selectorsWithFilters[i]->getDescription(descriptionMeth)
334  + logic;
335  }
336 
337  description += selectorsWithFilters[numFilters - 1]->getDescription(
338  descriptionMeth);
339  }
340 
341  return description;
342  }
343 }
QWidget
QList
This is free and unencumbered software released into the public domain.
Definition: BoxcarCachingAlgorithm.h:13
Isis::IException::Programmer
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition: IException.h:146
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16