Isis 3 Programmer Reference
AbstractFilter.cpp
1 
7 /* SPDX-License-Identifier: CC0-1.0 */
8 
9 #include "IsisDebug.h"
10 
11 #include <iostream>
12 #include <limits>
13 
14 #include "AbstractFilter.h"
15 
16 #include <QAction>
17 #include <QAbstractButton>
18 #include <QButtonGroup>
19 #include <QCheckBox>
20 #include <QFlags>
21 #include <QHBoxLayout>
22 #include <QLabel>
23 #include <QMargins>
24 #include <QMenu>
25 #include <QMenuBar>
26 #include <QPair>
27 #include <QRadioButton>
28 #include <QSpinBox>
29 #include <QString>
30 #include <QVBoxLayout>
31 #include <QWriteLocker>
32 
33 #include "ControlMeasure.h"
34 #include "ControlNet.h"
35 #include "ControlPoint.h"
36 
37 #include "AbstractFilterSelector.h"
38 
39 
40 namespace Isis {
41  AbstractFilter::AbstractFilter(FilterEffectivenessFlag effectiveness,
42  int minimumForSuccess) {
43  nullify();
44 
45  m_minForSuccess = minimumForSuccess;
46 
47  m_effectivenessFlags = new FilterEffectivenessFlag(effectiveness);
48 
49  m_smallFont = new QFont("SansSerif", 9);
50 
51  createWidget();
52  }
53 
54 
55  AbstractFilter::AbstractFilter(const AbstractFilter &other) {
56  nullify();
57 
58  m_minForSuccess = other.m_minForSuccess;
59 
60  m_effectivenessFlags = new FilterEffectivenessFlag(*other.m_effectivenessFlags);
61 
62  m_smallFont = new QFont(*other.m_smallFont);
63 
64  createWidget();
65 
66  m_inclusiveExclusiveGroup->button(
67  other.m_inclusiveExclusiveGroup->checkedId())->click();
68  }
69 
70 
71  AbstractFilter::~AbstractFilter() {
72  delete m_effectivenessFlags;
73  m_effectivenessFlags = NULL;
74 
75  delete m_inclusiveExclusiveGroup;
76  m_inclusiveExclusiveGroup = NULL;
77 
78  delete m_smallFont;
79  m_smallFont = NULL;
80  }
81 
82 
83  bool AbstractFilter::canFilterImages() const {
84  return m_effectivenessFlags->testFlag(Images);
85  }
86 
87 
88  bool AbstractFilter::canFilterPoints() const {
89  return m_effectivenessFlags->testFlag(Points);
90  }
91 
92 
93  bool AbstractFilter::canFilterMeasures() const {
94  return m_effectivenessFlags->testFlag(Measures);
95  }
96 
97 
98  QString AbstractFilter::getImageDescription() const {
99  return "have at least " + QString::number(getMinForSuccess()) + " ";
100  }
101 
102 
103  QString AbstractFilter::getPointDescription() const {
104  return QString();
105  }
106 
107 
108  QString AbstractFilter::getMeasureDescription() const {
109  return QString();
110  }
111 
112 
113  void AbstractFilter::nullify() {
114  m_effectivenessGroup = NULL;
115  m_inclusiveExclusiveGroup = NULL;
116  m_inclusiveExclusiveLayout = NULL;
117  m_mainLayout = NULL;
118  m_minWidget = NULL;
119  m_effectivenessFlags = NULL;
120  m_smallFont = NULL;
121  }
122 
123 
124  void AbstractFilter::createWidget() {
125  QRadioButton *inclusiveButton = new QRadioButton("Inclusive");
126  inclusiveButton->setFont(*m_smallFont);
127  QRadioButton *exclusiveButton = new QRadioButton("Exclusive");
128  exclusiveButton->setFont(*m_smallFont);
129 
130  m_inclusiveExclusiveGroup = new QButtonGroup;
131  connect(m_inclusiveExclusiveGroup, SIGNAL(buttonClicked(int)),
132  this, SIGNAL(filterChanged()));
133  m_inclusiveExclusiveGroup->addButton(inclusiveButton, 0);
134  m_inclusiveExclusiveGroup->addButton(exclusiveButton, 1);
135 
136  m_inclusiveExclusiveLayout = new QHBoxLayout;
137  QMargins margins = m_inclusiveExclusiveLayout->contentsMargins();
138  margins.setTop(0);
139  margins.setBottom(0);
140  m_inclusiveExclusiveLayout->setContentsMargins(margins);
141  m_inclusiveExclusiveLayout->addWidget(inclusiveButton);
142  m_inclusiveExclusiveLayout->addWidget(exclusiveButton);
143 
144  QHBoxLayout *controlsLayout = new QHBoxLayout;
145  margins = controlsLayout->contentsMargins();
146  margins.setTop(0);
147  margins.setBottom(0);
148  controlsLayout->setContentsMargins(margins);
149 
150  controlsLayout->addLayout(m_inclusiveExclusiveLayout);
151 
152  m_effectivenessGroup = new QButtonGroup();
153  m_effectivenessGroup->setExclusive(false);
154 
155  if (m_effectivenessFlags->testFlag(Images))
156  m_effectivenessGroup->addButton(
157  createEffectivenessCheckBox("&Images"), 0);
158 
159  if (m_effectivenessFlags->testFlag(Points))
160  m_effectivenessGroup->addButton(
161  createEffectivenessCheckBox("&Points"), 1);
162 
163  if (m_effectivenessFlags->testFlag(Measures))
164  m_effectivenessGroup->addButton(
165  createEffectivenessCheckBox("&Measures"), 2);
166 
167  QString firstGroupEntry;
168  ASSERT(m_effectivenessGroup->buttons().size());
169  if (m_effectivenessGroup->buttons().size()) {
170  firstGroupEntry = m_effectivenessGroup->buttons()[0]->text();
171  firstGroupEntry.remove(0, 1);
172  }
173 
174  QList<QAbstractButton *> buttons = m_effectivenessGroup->buttons();
175  if (m_effectivenessGroup->buttons().size() >= 2) {
176  QHBoxLayout *effectivenessLayout = new QHBoxLayout;
177  QMargins effectivenessMargins = effectivenessLayout->contentsMargins();
178  effectivenessMargins.setTop(0);
179  effectivenessMargins.setBottom(0);
180  effectivenessLayout->setContentsMargins(effectivenessMargins);
181 
182  for (int i = 0; i < buttons.size(); i++)
183  effectivenessLayout->addWidget(buttons[i]);
184 
185  controlsLayout->addLayout(effectivenessLayout);
186  }
187  else {
188  for (int i = 0; i < buttons.size(); i++)
189  delete buttons[i];
190  delete m_effectivenessGroup;
191  m_effectivenessGroup = NULL;
192  }
193 
194  if (m_minForSuccess != -1) {
195  QLabel *label = new QLabel;
196  label->setText(
197  "<span>Min Count<br/>for " + firstGroupEntry + "</span>");
198  label->setFont(QFont("SansSerif", 7));
199  QSpinBox *spinBox = new QSpinBox;
200  spinBox->setRange(1, std::numeric_limits< int >::max());
201  spinBox->setValue(1); // FIXME: QSettings should handle this
202  connect(spinBox, SIGNAL(valueChanged(int)),
203  this, SLOT(updateMinForSuccess(int)));
204  QHBoxLayout *minLayout = new QHBoxLayout;
205  margins = minLayout->contentsMargins();
206  margins.setTop(0);
207  margins.setBottom(0);
208  minLayout->setContentsMargins(margins);
209  minLayout->addWidget(label);
210  minLayout->addWidget(spinBox);
211  m_minWidget = new QWidget;
212  m_minWidget->setLayout(minLayout);
213 
214  controlsLayout->addWidget(m_minWidget);
215  controlsLayout->setAlignment(m_minWidget, Qt::AlignTop);
216  m_minWidget->setVisible(true); // FIXME: QSettings should handle this
217  }
218 
219  controlsLayout->addStretch();
220 
221  m_mainLayout = new QVBoxLayout;
222  margins = m_mainLayout->contentsMargins();
223  margins.setTop(0);
224  margins.setBottom(0);
225  m_mainLayout->setContentsMargins(margins);
226  m_mainLayout->addLayout(controlsLayout);
227 
228 
229  setLayout(m_mainLayout);
230 
231  // FIXME: QSettings should handle this
232  inclusiveButton->click();
233  }
234 
235 
236  QCheckBox *AbstractFilter::createEffectivenessCheckBox(QString text) {
237  QCheckBox *checkBox = new QCheckBox(text, this);
238  checkBox->setChecked(true);
239  checkBox->setFont(*m_smallFont);
240  connect(checkBox, SIGNAL(toggled(bool)),
241  this, SLOT(updateEffectiveness()));
242  connect(checkBox, SIGNAL(toggled(bool)), this, SIGNAL(filterChanged()));
243  return checkBox;
244  }
245 
246 
247  bool AbstractFilter::inclusive() const {
248  return m_inclusiveExclusiveGroup->checkedId() == 0;
249  }
250 
251 
252  AbstractFilter::FilterEffectivenessFlag *
253  AbstractFilter::getEffectivenessFlags() const {
254  return m_effectivenessFlags;
255  }
256 
257 
258  QBoxLayout *AbstractFilter::getMainLayout() const {
259  ASSERT(m_mainLayout);
260 
261  return m_mainLayout;
262  }
263 
264 
265  QBoxLayout *AbstractFilter::getInclusiveExclusiveLayout() const {
266  ASSERT(m_inclusiveExclusiveLayout);
267 
268  return m_inclusiveExclusiveLayout;
269  }
270 
271 
272  bool AbstractFilter::evaluateFromCount(QList< ControlMeasure * > measures,
273  bool usePoints) const {
274  int passedCount = 0;
275 
276  foreach (ControlMeasure * measure, measures) {
277  ASSERT(measure);
278 
279  if (usePoints) {
280  ControlPoint *point = measure->Parent();
281  ASSERT(point);
282  if (point && evaluate(point))
283  passedCount++;
284  }
285  else {
286  if (measure && evaluate(measure))
287  passedCount++;
288  }
289  }
290 
291  return passedCount >= getMinForSuccess();
292  }
293 
294 
295  bool AbstractFilter::evaluateImageFromPointFilter(
296  const QPair<QString, ControlNet *> *imageAndNet) const {
297  bool evaluation = true;
298 
299  if (canFilterImages()) {
300  evaluation = evaluateFromCount(imageAndNet->second->GetMeasuresInCube(imageAndNet->first),
301  true);
302  }
303 
304  return evaluation;
305  }
306 
307 
308  bool AbstractFilter::evaluateImageFromMeasureFilter(
309  const QPair<QString, ControlNet *> *imageAndNet) const {
310  bool evaluation = true;
311 
312  if (canFilterImages()) {
313  evaluation = evaluateFromCount(imageAndNet->second->GetMeasuresInCube(imageAndNet->first),
314  false);
315  }
316 
317  return evaluation;
318  }
319 
320 
321  bool AbstractFilter::evaluatePointFromMeasureFilter(
322  const ControlPoint *point) const {
323  ASSERT(point);
324 
325  bool evaluation = true;
326 
327  if (canFilterPoints())
328  evaluation = evaluateFromCount(point->getMeasures(), false);
329 
330  return evaluation;
331  }
332 
333 
334  bool AbstractFilter::evaluate(const ControlPoint *point,
335  bool (ControlPoint::*meth)() const) const {
336  ASSERT(point);
337 
338  return !((point->*meth)() ^ inclusive());
339  }
340 
341 
342  bool AbstractFilter::evaluate(const ControlMeasure *measure,
343  bool (ControlMeasure::*meth)() const) const {
344  ASSERT(measure);
345 
346  return !((measure->*meth)() ^ inclusive());
347  }
348 
349 
350  void AbstractFilter::updateEffectiveness() {
351  ASSERT(m_effectivenessGroup);
352 
353  if (m_effectivenessGroup) {
354  FilterEffectivenessFlag newFlags;
355 
356  QList< QAbstractButton * > buttons = m_effectivenessGroup->buttons();
357 
358  if (m_minWidget)
359  m_minWidget->setVisible(false);
360 
361  for (int i = 0; i < buttons.size(); i++) {
362  if (buttons[i]->isChecked()) {
363  if (buttons[i]->text() == "&Images")
364  newFlags |= Images;
365  else if (buttons[i]->text() == "&Points")
366  newFlags |= Points;
367  else if (buttons[i]->text() == "&Measures")
368  newFlags |= Measures;
369 
370  if (i == 0 && m_minWidget)
371  m_minWidget->setVisible(true);
372  }
373  }
374 
375  *m_effectivenessFlags = newFlags;
376  }
377  }
378 
379 
380  void AbstractFilter::updateMinForSuccess(int newMin) {
381  m_minForSuccess = newMin;
382  emit filterChanged();
383  }
384 }
QWidget
QList
This is free and unencumbered software released into the public domain.
Definition: BoxcarCachingAlgorithm.h:13
QPair
This is free and unencumbered software released into the public domain.
Definition: CubeIoHandler.h:23
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16
QSpinBox