Isis 3 Programmer Reference
ImageReader.cpp
1 #include "ImageReader.h"
2 
3 #include <QAction>
4 #include <QApplication>
5 #include <QDebug>
6 #include <QFuture>
7 #include <QFutureWatcher>
8 #include <QInputDialog>
9 #include <QList>
10 #include <QProgressBar>
11 #include <QSettings>
12 #include <QString>
13 #include <QtConcurrentMap>
14 #include <QVariant>
15 
16 #include "IException.h"
17 #include "Image.h"
18 #include "ImageDisplayProperties.h"
19 #include "IString.h"
20 #include "FileName.h"
21 #include "ProgressBar.h"
22 #include "PvlObject.h"
23 
24 namespace Isis {
25 
35  ImageReader::ImageReader(QMutex *cameraMutex, bool requireFootprints, QObject *parent) :
36  QObject(parent) {
37  m_watcher = NULL;
38 
39  m_cameraMutex = cameraMutex;
40  m_requireFootprints = requireFootprints;
41 
42  m_progress = new ProgressBar("Reading Images");
43  m_watcher = new QFutureWatcher<Image *>;
44 
45  initProgress();
46 
47  connect(m_watcher, SIGNAL(resultReadyAt(int)),
48  this, SLOT(imageReady(int)));
49  connect(m_watcher, SIGNAL(finished()),
50  this, SLOT(mappedFinished()));
51 
52  m_safeFileOpen = false;
53  m_openFilled = true;
54  m_defaultAlpha = 60;
55 
56  m_mappedRunning = false;
57 
58  readSettings();
59  }
60 
61 
66  writeSettings();
67 
68  if (m_watcher) {
69  m_watcher->cancel();
70  m_watcher->waitForFinished();
71  }
72 
73  delete m_watcher;
74  m_watcher = NULL;
75 
76  m_backlog.clear();
77 
78  m_cameraMutex = NULL;
79 
80  delete m_progress;
81  }
82 
83 
84  QList<QAction *> ImageReader::actions(ImageDisplayProperties::Property relevantDispProperties) {
85  QList<QAction *> results;
86 
87  if (!m_safeFileOpenAct) {
88  m_safeFileOpenAct = new QAction(tr("&Safe File Open"), this);
89  m_safeFileOpenAct->setCheckable(true);
90  m_safeFileOpenAct->setChecked(m_safeFileOpen);
91  m_safeFileOpenAct->setWhatsThis(tr("This lowers the number of "
92  "simulataneously open files drastically in order to stay under the "
93  "operating system limit. Only use this if you are having trouble "
94  "loading large numbers of images."));
95  connect(m_safeFileOpenAct, SIGNAL(toggled(bool)),
96  this, SLOT(setSafeFileOpen(bool)));
97  }
98 
99  results.append(m_safeFileOpenAct);
100 
101  if ((relevantDispProperties & ImageDisplayProperties::ShowFill) == ImageDisplayProperties::ShowFill) {
102  if (!m_openFilledAct) {
103  m_openFilledAct = new QAction(tr("Default Images &Filled"), this);
104  m_openFilledAct->setCheckable(true);
105  m_openFilledAct->setChecked(m_openFilled);
106  m_openFilledAct->setWhatsThis(tr("When this is enabled, images will be overlayed with "
107  "a color."));
108  connect(m_openFilledAct, SIGNAL(toggled(bool)),
109  this, SLOT(setOpenFilled(bool)));
110  }
111 
112  results.append(m_openFilledAct);
113  }
114 
115  if ((relevantDispProperties & ImageDisplayProperties::Color) == ImageDisplayProperties::Color) {
116  if (!m_askAlphaAct) {
117  m_askAlphaAct = new QAction(tr("Set Default &Transparency"), this);
118  connect(m_askAlphaAct, SIGNAL(triggered(bool)),
119  this, SLOT(askDefaultAlpha()));
120  }
121 
122  results.append(m_askAlphaAct);
123  }
124 
125  return results;
126  }
127 
128 
129  QProgressBar *ImageReader::progress() {
130  return m_progress;
131  }
132 
133 
134  void ImageReader::askDefaultAlpha() {
135  bool ok = false;
136  int alpha = QInputDialog::getInt(NULL, tr("Transparency Value"),
137  tr("Set the default transparency value\n"
138  "Values are 0 (invisible) to 255 (solid)"),
139  m_defaultAlpha, 0, 255, 1, &ok);
140 
141  if(ok) {
142  m_defaultAlpha = alpha;
143  }
144  }
145 
146 
147  void ImageReader::read(PvlObject imagesObject) {
148  read(imagesObject.beginObject(), imagesObject.endObject());
149  }
150 
151 
155  void ImageReader::read(QStringList cubeNames) {
156  read(cubeNames.begin(), cubeNames.end());
157  }
158 
159 
160  void ImageReader::setOpenFilled(bool openFilled) {
161  m_openFilled = openFilled;
162  if (m_openFilledAct) {
163  m_openFilledAct->setChecked(m_openFilled);
164  }
165  }
166 
167 
168  void ImageReader::setSafeFileOpen(bool safeFileOpen) {
169  m_safeFileOpen = safeFileOpen;
170  if (m_safeFileOpen) {
171  m_safeFileOpenAct->setChecked(m_safeFileOpen);
172  }
173  }
174 
175 
176  void ImageReader::initProgress() {
177  m_progress->setVisible(false);
178  m_progress->setRange(0, 0);
179  m_progress->setValue(0);
180  }
181 
182 
183  void ImageReader::start() {
184  if (!m_backlog.isEmpty() && !m_mappedRunning) {
185  m_progress->setVisible(true);
186 
187  int maxOpenImages = m_safeFileOpen? 20 : 400;
188  QList<QVariant> culledBacklog = m_backlog.mid(0, maxOpenImages);
189  m_backlog = m_backlog.mid(maxOpenImages);
190 
191  QFuture< Image * > images = QtConcurrent::mapped(
192  culledBacklog,
193  VariantToImageFunctor(m_cameraMutex, m_requireFootprints, QThread::currentThread(),
194  m_openFilled, m_defaultAlpha));
195 
196  m_watcher->setFuture(images);
197  m_mappedRunning = true;
198  }
199  }
200 
201 
202  void ImageReader::readSettings() {
203  QSettings settings(
204  FileName("$HOME/.Isis/" + QApplication::applicationName() + "/Image Reader.config")
205  .expanded(),
206  QSettings::NativeFormat);
207 
208  m_safeFileOpen = settings.value("safeFileOpen", m_safeFileOpen).toBool();
209  m_openFilled = settings.value("openFilled", m_openFilled).toBool();
210  m_defaultAlpha = settings.value("defaultAlpha", m_defaultAlpha).toInt();
211  }
212 
213 
214  void ImageReader::writeSettings() {
215  QSettings settings(
216  FileName("$HOME/.Isis/" + QApplication::applicationName() + "/Image Reader.config")
217  .expanded(),
218  QSettings::NativeFormat);
219 
220  settings.setValue("safeFileOpen", m_safeFileOpen);
221  settings.setValue("openFilled", m_openFilled);
222  settings.setValue("defaultAlpha", m_defaultAlpha);
223  }
224 
225 
226  void ImageReader::imageReady(int index) {
227  m_progress->setValue(m_progress->value() + 1);
228  }
229 
230 
231  void ImageReader::mappedFinished() {
232  ImageList images(m_watcher->future().results());
233 
234  // Tracie Sucharski: Go through list & get rid of NULLs. This is a temporary fix to get rid
235  // of seg faulting when something goes wrong. This is not a good solution & needs to be
236  // properly fixed
237  foreach (Image *image, images) {
238  if (!image) {
239  images.removeAll(image);
240  }
241  }
242 
243  emit imagesReady(images);
244 
245  m_mappedRunning = false;
246  if (!m_backlog.isEmpty()) {
247  start();
248  }
249  else {
250  initProgress();
251  }
252  }
253 
254 
261  QMutex *cameraMutex, bool requireFootprints, QThread *targetThread, bool openFilled,
262  int defaultAlpha) {
263  m_mutex = cameraMutex;
264  m_targetThread = targetThread;
265  m_openFilled = openFilled;
266  m_defaultAlpha = defaultAlpha;
267  m_requireFootprints = requireFootprints;
268  }
269 
270 
279  const QVariant &imageData) {
280  Image *result = NULL;
281 
282  try {
283  QString fileName;
284  if (imageData.canConvert<QString>()) {
285  fileName = imageData.value<QString>();
286 
287  result = new Image(FileName(fileName).expanded());
288  ImageDisplayProperties *prop = result->displayProperties();
289  prop->setShowFill(m_openFilled);
290 
291  QColor newColor = prop->getValue(ImageDisplayProperties::Color).value<QColor>();
292  newColor.setAlpha(m_defaultAlpha);
293 
294  prop->setColor(newColor);
295  }
296  else if (imageData.canConvert<PvlObject>()) {
297  PvlObject imageObj = imageData.value<PvlObject>();
298  fileName = ((IString)imageObj["FileName"][0]).ToQt();
299  result = new Image(FileName(fileName).expanded());
300  result->fromPvl(imageObj);
301  }
302 
303  if (m_requireFootprints) {
304  try {
305  result->initFootprint(m_mutex);
306  }
307  catch (IException &) {
308  throw;
309  }
310  }
311 
312  result->moveToThread(m_targetThread);
313  }
314  catch(IException &e) {
315  e.print();
316  result = NULL;
317  }
318 
319  return result;
320  }
321 }
True if the cube should show a fill area if possible (bool)
File name manipulation and expansion.
Definition: FileName.h:116
VariantToImageFunctor(QMutex *cameraMutex, bool requireFootprints, QThread *targetThread, bool openFilled, int defaultAlpha)
Create a functor for converting from QVariant to an Image *.
virtual ~ImageReader()
Free the allocated memory by this object.
Definition: ImageReader.cpp:65
ImageReader(QMutex *cameraMutex, bool requireFootprints=true, QObject *parent=NULL)
MosaicWidget constructor.
Definition: ImageReader.cpp:35
QVariant getValue(int property) const
Get a property&#39;s associated data.
QPointer< QAction > m_askAlphaAct
Variant Internal Format: (QString|PvlObject).
Definition: ImageReader.h:96
This is the GUI communication mechanism for cubes.
This represents a cube in a project-based GUI interface.
Definition: Image.h:107
void setColor(QColor newColor)
Change the color associated with this cube.
Image * operator()(const QVariant &)
Read the QString filename and make an Image from it.
Property
This is a list of properties and actions that are possible.
void print() const
Prints a string representation of this exception to stderr.
Definition: IException.cpp:461
bool initFootprint(QMutex *cameraMutex)
Calculate a footprint for this image.
Definition: Image.cpp:409
Isis exception class.
Definition: IException.h:107
Adds specific functionality to C++ strings.
Definition: IString.h:181
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
The color of the cube, default randomized (QColor)
void fromPvl(const PvlObject &pvl)
Read the image settings from a Pvl.
Definition: Image.cpp:194
Contains Pvl Groups and Pvl Objects.
Definition: PvlObject.h:74
void setShowFill(bool)
Change the visibility of the fill area associated with this cube.