USGS

Isis 3.0 Object Programmers' Reference

Home

ImportImagesWorkOrder.cpp
Go to the documentation of this file.
1 
23 #include "ImportImagesWorkOrder.h"
24 
25 #include <QDebug>
26 #include <QFileDialog>
27 #include <QMessageBox>
28 #include <QtConcurrentMap>
29 
30 #include "Cube.h"
31 #include "CubeAttribute.h"
32 #include "FileName.h"
33 #include "Project.h"
34 #include "SaveProjectWorkOrder.h"
35 #include "TextFile.h"
36 
37 namespace Isis {
38 
39  ImportImagesWorkOrder::ImportImagesWorkOrder(Project *project) :
40  WorkOrder(project) {
41  m_newImages = NULL;
42 
43  QAction::setText(tr("Import &Images..."));
44  QUndoCommand::setText(tr("Import Images"));
45  setModifiesDiskState(true);
46  }
47 
48 
49  ImportImagesWorkOrder::ImportImagesWorkOrder(const ImportImagesWorkOrder &other) :
50  WorkOrder(other) {
51  m_newImages = NULL;
52  }
53 
54 
55  ImportImagesWorkOrder::~ImportImagesWorkOrder() {
56  delete m_newImages;
57  m_newImages = NULL;
58  }
59 
60 
61  ImportImagesWorkOrder *ImportImagesWorkOrder::clone() const {
62  return new ImportImagesWorkOrder(*this);
63  }
64 
65 
68 
69  QStringList fileNames = QFileDialog::getOpenFileNames(
70  qobject_cast<QWidget *>(parent()),
71  tr("Import Images"), "",
72  tr("Isis cubes and list files (*.cub *.lis);;All Files (*)"));
73 
74  QStringList stateToSave;
75 
76  if (!fileNames.isEmpty()) {
77  foreach (FileName fileName, fileNames) {
78  if (fileName.extension() == "lis") {
79  TextFile listFile(fileName.expanded());
80  QString lineOfListFile;
81 
82  while (listFile.GetLine(lineOfListFile)) {
83  stateToSave.append(lineOfListFile);
84  }
85  }
86  else {
87  stateToSave.append(fileName.original());
88  }
89  }
90  }
91 
92  QMessageBox::StandardButton saveProjectAnswer = QMessageBox::No;
93  if (stateToSave.count() >= 100 && project()->isTemporaryProject()) {
94  saveProjectAnswer = QMessageBox::question(qobject_cast<QWidget *>(parent()),
95  tr("Save Project Before Importing Images"),
96  tr("Would you like to save your project <b>before</b> importing images? It can be "
97  "slow to save your project after these images have been loaded if you do not "
98  "save now."),
99  QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
100  QMessageBox::Yes);
101  }
102 
103  if (saveProjectAnswer == QMessageBox::Yes) {
104  SaveProjectWorkOrder saveWorkOrder(project());
105  saveWorkOrder.trigger();
106  }
107 
108  QMessageBox::StandardButton copyImagesAnswer = QMessageBox::No;
109  if (!fileNames.isEmpty() && saveProjectAnswer != QMessageBox::Cancel) {
110  copyImagesAnswer = QMessageBox::question(qobject_cast<QWidget *>(parent()),
111  tr("Copy Images into Project"),
112  tr("Should images (DN data) be copied into project?"),
113  QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
114  QMessageBox::Yes);
115  }
116 
117  bool copyDnData = (copyImagesAnswer == QMessageBox::Yes);
118 
119  stateToSave.prepend(copyDnData? "copy" : "nocopy");
120 
121  if (fileNames.count() > 1) {
122  QUndoCommand::setText(tr("Import %1 Images").arg(stateToSave.count() - 1));
123  }
124  else if (fileNames.count() == 1) {
125  QUndoCommand::setText(tr("Import %1").arg(fileNames.first()));
126  }
127 
128  setInternalData(stateToSave);
129 
130  bool doImport = fileNames.count() > 0 && saveProjectAnswer != QMessageBox::Cancel &&
131  copyImagesAnswer != QMessageBox::Cancel;
132 
133  return doImport;
134  }
135 
136 
138  project()->waitForImageReaderFinished();
139  project()->images().last()->deleteFromDisk(project());
140  }
141 
142 
144  QPointer<ImageList> imagesWeAdded = project()->images().last();
145 
146  foreach (Image *image, *imagesWeAdded) {
147  delete image;
148  }
149  delete imagesWeAdded;
150  }
151 
152 
154  if (internalData().count() > 0) {
155  importConfirmedImages(internalData().mid(1), (internalData()[0] == "copy"));
156  }
157  }
158 
159 
161  if (!m_newImages->isEmpty()) {
162  project()->addImages(*m_newImages);
163 
164  delete m_newImages;
165  m_newImages = NULL;
166  }
167 
168  if (m_warning != "") {
169  project()->warn(m_warning);
170  }
171  }
172 
173 
174  ImportImagesWorkOrder::OriginalFileToProjectCubeFunctor::OriginalFileToProjectCubeFunctor(
175  QThread *guiThread, QDir destinationFolder, bool copyDnData) : m_errors(new IException),
176  m_numErrors(new int(0)) {
177  m_destinationFolder = destinationFolder;
178  m_copyDnData = copyDnData;
179  m_guiThread = guiThread;
180  }
181 
182 
183  ImportImagesWorkOrder::OriginalFileToProjectCubeFunctor::OriginalFileToProjectCubeFunctor(
184  const OriginalFileToProjectCubeFunctor &other) : m_errors(other.m_errors),
185  m_numErrors(other.m_numErrors) {
186  m_destinationFolder = other.m_destinationFolder;
187  m_copyDnData = other.m_copyDnData;
188  m_guiThread = other.m_guiThread;
189  }
190 
191 
192  ImportImagesWorkOrder::OriginalFileToProjectCubeFunctor::~OriginalFileToProjectCubeFunctor() {
193  m_destinationFolder = QDir();
194  m_copyDnData = false;
195  m_guiThread = NULL;
196  }
197 
198 
199  Cube *ImportImagesWorkOrder::OriginalFileToProjectCubeFunctor::operator()(
200  const FileName &original) {
201  Cube *result = NULL;
202 
203  if (*m_numErrors < 20) {
204  try {
205  QString destination = QFileInfo(m_destinationFolder, original.name())
206  .absoluteFilePath();
207  Cube *input = new Cube(original, "r");
208 
209  if (m_copyDnData) {
210  Cube *copiedCube = input->copy(destination, CubeAttributeOutput());
211  delete input;
212  input = copiedCube;
213  }
214 
215  FileName externalLabelFile(destination);
216  externalLabelFile = externalLabelFile.setExtension("ecub");
217 
218  Cube *projectImage = input->copy(externalLabelFile, CubeAttributeOutput("+External"));
219 
220  if (m_copyDnData) {
221  // Make sure the external label has a fully relative path to the DN data
222  projectImage->relocateDnData(FileName(destination).name());
223  }
224 
225  delete input;
226 
227  result = projectImage;
228  }
229  catch (IException &e) {
230  m_errorsLock.lock();
231 
232  m_errors->append(e);
233  (*m_numErrors)++;
234 
235  m_errorsLock.unlock();
236  }
237  }
238 
239  return result;
240  }
241 
242 
243  IException ImportImagesWorkOrder::OriginalFileToProjectCubeFunctor::errors() const {
244  IException result;
245 
246  result.append(*m_errors);
247 
248  if (*m_numErrors >= 20) {
249  result.append(
250  IException(IException::Unknown,
251  tr("Aborted import images due to a high number of errors"),
252  _FILEINFO_));
253  }
254  return result;
255  }
256 
257 
274  void ImportImagesWorkOrder::importConfirmedImages(QStringList confirmedImages, bool copyDnData) {
275  if (!confirmedImages.isEmpty()) {
276  QDir folder = project()->addImageFolder("import");
277 
278  setProgressRange(0, confirmedImages.count());
279 
280  m_newImages = new ImageList;
281  m_newImages->reserve(confirmedImages.count());
282 
283  QStringList confirmedImagesFileNames;
284  QStringList confirmedImagesIds;
285 
286  foreach (QString confirmedImage, confirmedImages) {
287  QStringList fileNameAndId = confirmedImage.split(",");
288 
289  confirmedImagesFileNames.append(fileNameAndId.first());
290 
291  if (fileNameAndId.count() == 2) {
292  confirmedImagesIds.append(fileNameAndId.last());
293  }
294  else {
295  confirmedImagesIds.append(QString());
296  }
297  }
298 
299  OriginalFileToProjectCubeFunctor functor(thread(), folder, copyDnData);
300  QFuture<Cube *> future = QtConcurrent::mapped(confirmedImagesFileNames, functor);
301 
302  QStringList newInternalData;
303  newInternalData.append(internalData().first());
304 
305  QThreadPool::globalInstance()->releaseThread();
306  for (int i = 0; i < confirmedImages.count(); i++) {
307  setProgressValue(i);
308 
309  Cube *cube = future.resultAt(i);
310 
311  if (cube) {
312  Image *newImage = new Image(future.resultAt(i));
313 
314  if (confirmedImagesIds[i].isEmpty()) {
315  confirmedImagesIds[i] = newImage->id();
316  }
317  else {
318  newImage->setId(confirmedImagesIds[i]);
319  }
320 
321  QStringList imageInternalData;
322  imageInternalData.append(confirmedImagesFileNames[i]);
323  imageInternalData.append(confirmedImagesIds[i]);
324 
325  newInternalData.append(imageInternalData.join(","));
326 
327  m_newImages->append(newImage);
328 
329  newImage->moveToThread(thread());
330  newImage->displayProperties()->moveToThread(thread());
331 
332  newImage->closeCube();
333  }
334  }
335  QThreadPool::globalInstance()->reserveThread();
336 
337  m_warning = functor.errors().toString();
338 
339  m_newImages->moveToThread(thread());
340 
341  setInternalData(newInternalData);
342  }
343  }
344 }