Isis 3.0 Programmer Reference
Back | Home
ProjectionConfigDialog.cpp
1 #include "ProjectionConfigDialog.h"
2 
3 #include <sstream>
4 
5 #include <QCheckBox>
6 #include <QFileDialog>
7 #include <QGridLayout>
8 #include <QLabel>
9 #include <QMessageBox>
10 #include <QPushButton>
11 #include <QTextEdit>
12 
13 #include "IException.h"
14 #include "MosaicSceneWidget.h"
15 #include "Projection.h"
16 #include "ProjectionFactory.h"
17 #include "Pvl.h"
18 
19 using std::stringstream;
20 
21 namespace Isis {
30  QDialog(parent) {
31  m_scene = scene;
32  m_dirty = false;
33  m_quick = false;
34 
35  QGridLayout *mainLayout = new QGridLayout;
36 
37  /*
38  * The layout is shown below:
39  *
40  * |--------------------------------------------------------------|
41  * | Header |
42  * |--------------------------------------------------------------|
43  * | Description |
44  * |--------------------------------------------------------------|
45  * | Load From File... Save To File... |
46  * |--------------------------------------------------------------|
47  * | Text Edit |
48  * |--------------------------------------------------------------|
49  * | Errors |
50  * |--------------------------------------------------------------|
51  * | Show Errors Ok Apply Cancel |
52  * |--------------------------------------------------------------|
53  */
54 
55  int row = 0;
56  QLabel *headerLabel = new QLabel("<h3>Configure Projection/Mapping Parameters</h3>");
57  mainLayout->addWidget(headerLabel, row, 0);
58  row++;
59 
60  QLabel *descriptionLabel = new QLabel("The projection determines how the footprints will be "
61  "shown on the scene. This projection will be used to convert from latitude/longitude to "
62  "scene coordinates (x, y).<br/><br/>Please keep in mind:<br/><b>Load Map File...</b> will "
63  "read all of the keywords in the mapping group from the input file (unnecessary keywords "
64  "included).<br/>"
65  "<b>Save Map File...</b> will save what's currently in the display (unnecessary keywords "
66  "included).<br/>"
67  "<b>Ok and Apply</b> will remove all unnecessary or unknown keywords immediately.<br/>");
68  descriptionLabel->setWordWrap(true);
69  mainLayout->addWidget(descriptionLabel, row, 0);
70  row++;
71 
72  QHBoxLayout *loadSaveLayout = new QHBoxLayout;
73 
74  QPushButton *saveToFile = new QPushButton("&Save Map File...");
75  connect(saveToFile, SIGNAL(clicked()),
76  this, SLOT(saveToFile()));
77  loadSaveLayout->addWidget(saveToFile);
78 
79  m_readFromFileButton = new QPushButton("&Load Map File...");
80  connect(m_readFromFileButton, SIGNAL(clicked()),
81  this, SLOT(loadFromFile()));
82  loadSaveLayout->addWidget(m_readFromFileButton);
83 
84  loadSaveLayout->addStretch();
85  mainLayout->addLayout(loadSaveLayout, row, 0);
86  row++;
87 
88  QFont font("Monospace");
89  font.setStyleHint(QFont::TypeWriter);
90 
91  m_mapFileEdit = new QTextEdit;
92  m_mapFileEdit->setFont(font);
93  connect(m_mapFileEdit, SIGNAL(textChanged()),
94  this, SLOT(refreshWidgetStates()));
95  mainLayout->addWidget(m_mapFileEdit, row, 0);
96  row++;
97 
98  m_stateLabel = new QLabel;
99  mainLayout->addWidget(m_stateLabel, row, 0);
100  row++;
101 
102  m_errorsLabel = new QLabel;
103  m_errorsLabel->setWordWrap(true);
104  mainLayout->addWidget(m_errorsLabel, row, 0);
105  row++;
106 
107  QHBoxLayout *applyButtonsLayout = new QHBoxLayout;
108 
109  QCheckBox *showErrorsCheckBox = new QCheckBox(tr("Show Errors"));
110  connect(showErrorsCheckBox, SIGNAL(stateChanged(int)),
111  this, SLOT(showErrors(int)));
112  showErrors(showErrorsCheckBox->isChecked());
113  applyButtonsLayout->addWidget(showErrorsCheckBox);
114 
115  applyButtonsLayout->addStretch();
116 
117  m_okayButton = new QPushButton("&Ok");
118  m_okayButton->setIcon(QIcon::fromTheme("dialog-ok"));
119  connect(m_okayButton, SIGNAL(clicked()),
120  this, SLOT(applySettings()));
121  connect(m_okayButton, SIGNAL(clicked()),
122  this, SLOT(accept()));
123  applyButtonsLayout->addWidget(m_okayButton);
124 
125  m_applyButton = new QPushButton("&Apply");
126  m_applyButton->setIcon(QIcon::fromTheme("dialog-ok-apply"));
127  connect(m_applyButton, SIGNAL(clicked()),
128  this, SLOT(applySettings()));
129  applyButtonsLayout->addWidget(m_applyButton);
130 
131  QPushButton *cancelButton = new QPushButton("&Cancel");
132  cancelButton->setIcon(QIcon::fromTheme("dialog-cancel"));
133  connect(cancelButton, SIGNAL(clicked()),
134  this, SLOT(reject()));
135  applyButtonsLayout->addWidget(cancelButton);
136 
137  QWidget *applyButtonsWrapper = new QWidget;
138  applyButtonsWrapper->setLayout(applyButtonsLayout);
139  mainLayout->addWidget(applyButtonsWrapper, row, 0);
140  row++;
141 
142  setLayout(mainLayout);
143 
144  readSettings();
145 
146  connect(this, SIGNAL(shown()),
147  this, SLOT(beginQuickLoad()),
148  Qt::QueuedConnection);
149  }
150 
151 
152  ProjectionConfigDialog::~ProjectionConfigDialog() {
153  m_scene = NULL;
154  }
155 
156 
165  m_quick = quick;
166  }
167 
168 
173  try {
174  if (m_scene && m_dirty) {
175  m_scene->setProjection(createProjection());
176  }
177  }
178  catch (IException &) {
179  }
180 
181  readSettings();
182  }
183 
184 
190  if (m_scene && m_scene->getProjection()) {
191  Pvl mapFilePvl;
192  mapFilePvl += m_scene->getProjection()->Mapping();
193 
194  stringstream mapFileStringStream;
195  mapFileStringStream << mapFilePvl;
196 
197  m_mapFileEdit->setText(QString::fromStdString(mapFileStringStream.str()));
198  }
199 
201 
202  m_dirty = false;
203  }
204 
205 
206 
207  void ProjectionConfigDialog::showEvent(QShowEvent *event) {
208  QDialog::showEvent(event);
209 
210  emit shown();
211  }
212 
213 
218  PvlGroup &mapping = mappingPvl.findGroup("Mapping", Pvl::Traverse);
219 
220  if(!mapping.hasKeyword("MinimumLatitude"))
221  mapping += PvlKeyword("MinimumLatitude", "-90");
222 
223  if(!mapping.hasKeyword("MaximumLatitude"))
224  mapping += PvlKeyword("MaximumLatitude", "90");
225 
226  if(!mapping.hasKeyword("MinimumLongitude")) {
227  if(mapping["LongitudeDomain"][0] == "360")
228  mapping += PvlKeyword("MinimumLongitude", "0");
229  else
230  mapping += PvlKeyword("MinimumLongitude", "-180");
231  }
232 
233  if(!mapping.hasKeyword("MaximumLongitude")) {
234  if(mapping["LongitudeDomain"][0] == "360")
235  mapping += PvlKeyword("MaximumLongitude", "360");
236  else
237  mapping += PvlKeyword("MaximumLongitude", "180");
238  }
239 
240  return mappingPvl;
241  }
242 
243 
250  stringstream mapFileStringStream;
251  mapFileStringStream.str(m_mapFileEdit->toPlainText().toStdString());
252 
253  Pvl mapFilePvl;
254  mapFileStringStream >> mapFilePvl;
255  mapFilePvl = addMissingKeywords(mapFilePvl);
256 
257  return ProjectionFactory::Create(mapFilePvl);
258  }
259 
260 
267  if (m_quick && m_readFromFileButton) {
268  m_readFromFileButton->click();
269  }
270  }
271 
272 
278  QString mapFile = QFileDialog::getOpenFileName(this, tr("Select Map File"), QString("."),
279  tr("Map Files (*.map *.pvl *.cub);;Text Files (*.txt);;All Files (*)"));
280 
281  if (!mapFile.isEmpty()) {
282  bool success = false;
283 
284  try {
285  Pvl mapFilePvl(mapFile);
286  PvlGroup &mapping = mapFilePvl.findGroup("Mapping", PvlObject::Traverse);
287 
288  Pvl trimmedMapFilePvl;
289  trimmedMapFilePvl += mapping;
290 
291  stringstream trimmedMapFileStringStream;
292  trimmedMapFileStringStream << trimmedMapFilePvl;
293  m_mapFileEdit->setText(QString::fromStdString(trimmedMapFileStringStream.str()));
294 
295  success = true;
296  }
297  catch (IException &e) {
298  QMessageBox::warning(this, tr("Failed to Load Map File"),
299  tr("Failed to load projection from the given file.\n") +
300  e.toString());
301  }
302 
303 
304  if (m_quick && m_okayButton && success) {
305  try {
306  delete createProjection();
307  m_okayButton->click();
308  close();
309  }
310  catch (IException &) {
311  }
312  }
313  }
314 
315  // After we've tried one load, quick turns off. They either completed what they wanted, or
316  // need to evaluate what this dialog is telling them and modify their input.
317  m_quick = false;
318  }
319 
320 
326  QString mapFile = QFileDialog::getSaveFileName(this, tr("Save Map File"), QString("."),
327  tr("Map Files (*.map *.pvl);;Text Files (*.txt);;All Files (*)"));
328 
329  if (!mapFile.isEmpty()) {
330  QFile outputFile(mapFile);
331 
332  if (outputFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
333  QString mapFileInfo = m_mapFileEdit->toPlainText() + "\n";
334  if (outputFile.write(mapFileInfo.toLatin1()) == -1) {
335  QMessageBox::warning(this, tr("Failed to Write Text to File"),
336  tr("Failed to write the map file to [%1] due to an I/O failure").arg(mapFile));
337  }
338  }
339  else {
340  QMessageBox::warning(this, tr("Failed to Create Output File"),
341  tr("Failed to open file [%1] for writing").arg(mapFile));
342  }
343  }
344  }
345 
346 
352  bool projectionIsGood = true;
353 
354  if (m_mapFileEdit->toPlainText().trimmed().isEmpty()) {
355  m_stateLabel->setText("<strong>Please load (or type in) a map file</strong>");
356  m_errorsLabel->setText("");
357  projectionIsGood = false;
358  }
359  else {
360  try {
361  delete createProjection();
362  m_stateLabel->setText("<strong>The currently displayed text is valid</strong>");
363  m_errorsLabel->setText("");
364  }
365  catch (IException &e) {
366  m_stateLabel->setText("<strong>The currently displayed text is not valid"
367  "</strong>");
368  m_errorsLabel->setText(
369  QString("<font color='red'>&nbsp;&nbsp;") +
370  QString(e.what()).replace("\n", "<br/>&nbsp;&nbsp;") +
371  QString("</font>"));
372  projectionIsGood = false;
373  }
374  }
375 
376  m_dirty = true;
377 
378  m_okayButton->setEnabled(projectionIsGood);
379  m_applyButton->setEnabled(projectionIsGood);
380  }
381 
382 
389  void ProjectionConfigDialog::showErrors(int shouldShowErrors) {
390  m_errorsLabel->setVisible(shouldShowErrors);
391  }
392 }
static Isis::Projection * Create(Isis::Pvl &label, bool allowDefaults=false)
This method returns a pointer to a Projection object.
Pvl addMissingKeywords(Pvl mappingPvl)
Get a modified mapping pvl that the mosaic scene will be compatible with.
void beginQuickLoad()
If using quick load, this will prompt the user for an input file right after the show event...
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
Definition: PvlObject.h:141
void setQuickConfig(bool quick)
Enable/disable minimal interaction mode.
This widget encompasses the entire mosaic scene.
void saveToFile()
Save mapping parameters to the given file.
void refreshWidgetStates()
Update the enabled/disabled states of the various widgets based on the current user inputs&#39; states...
ProjectionConfigDialog(MosaicSceneWidget *scene, QWidget *parent=NULL)
Create a projection configuration dialog.
QPointer< QTextEdit > m_mapFileEdit
This is the text area that a user can type in for editing the projection.
void readSettings()
Update the current widgets&#39; states with the current settings in the mosaic scene. ...
Search child objects.
Definition: PvlObject.h:170
void applySettings()
Take the settings that have been configured and apply them to the mosaic scene.
QPointer< QLabel > m_stateLabel
This shows a general idea of the current state of the mapping pvl (always shown)
const char * what() const
Returns a string representation of this exception in its current state.
Definition: IException.cpp:391
QPointer< MosaicSceneWidget > m_scene
The mosaic scene we&#39;re configuring the projection for.
void showErrors(int)
This is called when &quot;Show Errors&quot; is checked.
Base class for Map Projections.
Definition: Projection.h:169
bool m_quick
Should we minimize the user interaction?
Contains multiple PvlContainers.
Definition: PvlGroup.h:57
QPointer< QPushButton > m_readFromFileButton
This button corresponds to &#39;Load Map File...&#39; and causes a prompt for file input. ...
A single keyword-value pair.
Definition: PvlKeyword.h:98
Projection * createProjection()
Convert the current text in the text edit to a projection.
Container for cube-like labels.
Definition: Pvl.h:135
QPointer< QLabel > m_errorsLabel
This shows errors generated by trying to create a projection from the current mapping pvl...
QString toString() const
Returns a string representation of this exception.
Definition: IException.cpp:553
Isis exception class.
Definition: IException.h:99
bool m_dirty
To reduce redundant computations, keep track of dirty state of the dialog.
QPointer< QPushButton > m_okayButton
This button applies the current projection to the scene and closes the dialog.
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
void loadFromFile()
Read mapping parameters from a file (prompts user for the file name).
QPointer< QPushButton > m_applyButton
This button applies the current projection to the scene.

U.S. Department of the Interior | U.S. Geological Survey
ISIS | Privacy & Disclaimers | Astrogeology Research Program
To contact us, please post comments and questions on the ISIS Support Center
File Modified: 07/12/2023 23:26:53