26 #include <QFileDialog>
27 #include <QMessageBox>
28 #include <QtConcurrentMap>
39 ImportImagesWorkOrder::ImportImagesWorkOrder(Project *project) :
43 QAction::setText(tr(
"Import &Images..."));
44 QUndoCommand::setText(tr(
"Import Images"));
49 ImportImagesWorkOrder::ImportImagesWorkOrder(
const ImportImagesWorkOrder &other) :
55 ImportImagesWorkOrder::~ImportImagesWorkOrder() {
61 ImportImagesWorkOrder *ImportImagesWorkOrder::clone()
const {
62 return new ImportImagesWorkOrder(*
this);
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 (*)"));
76 if (!fileNames.isEmpty()) {
77 foreach (
FileName fileName, fileNames) {
78 if (fileName.extension() ==
"lis") {
79 TextFile listFile(fileName.expanded());
80 QString lineOfListFile;
82 while (listFile.GetLine(lineOfListFile)) {
83 stateToSave.append(lineOfListFile);
87 stateToSave.append(fileName.original());
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 "
99 QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
103 if (saveProjectAnswer == QMessageBox::Yes) {
105 saveWorkOrder.trigger();
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,
117 bool copyDnData = (copyImagesAnswer == QMessageBox::Yes);
119 stateToSave.prepend(copyDnData?
"copy" :
"nocopy");
121 if (fileNames.count() > 1) {
122 QUndoCommand::setText(tr(
"Import %1 Images").arg(stateToSave.count() - 1));
124 else if (fileNames.count() == 1) {
125 QUndoCommand::setText(tr(
"Import %1").arg(fileNames.first()));
130 bool doImport = fileNames.count() > 0 && saveProjectAnswer != QMessageBox::Cancel &&
131 copyImagesAnswer != QMessageBox::Cancel;
138 project()->waitForImageReaderFinished();
144 QPointer<ImageList> imagesWeAdded =
project()->
images().last();
146 foreach (
Image *image, *imagesWeAdded) {
149 delete imagesWeAdded;
161 if (!m_newImages->isEmpty()) {
168 if (m_warning !=
"") {
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;
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;
192 ImportImagesWorkOrder::OriginalFileToProjectCubeFunctor::~OriginalFileToProjectCubeFunctor() {
193 m_destinationFolder = QDir();
194 m_copyDnData =
false;
199 Cube *ImportImagesWorkOrder::OriginalFileToProjectCubeFunctor::operator()(
200 const FileName &original) {
203 if (*m_numErrors < 20) {
205 QString destination = QFileInfo(m_destinationFolder, original.name())
207 Cube *input =
new Cube(original,
"r");
210 Cube *copiedCube = input->copy(destination, CubeAttributeOutput());
215 FileName externalLabelFile(destination);
216 externalLabelFile = externalLabelFile.setExtension(
"ecub");
218 Cube *projectImage = input->copy(externalLabelFile, CubeAttributeOutput(
"+External"));
222 projectImage->relocateDnData(FileName(destination).name());
227 result = projectImage;
229 catch (IException &e) {
235 m_errorsLock.unlock();
243 IException ImportImagesWorkOrder::OriginalFileToProjectCubeFunctor::errors()
const {
246 result.append(*m_errors);
248 if (*m_numErrors >= 20) {
251 tr(
"Aborted import images due to a high number of errors"),
275 if (!confirmedImages.isEmpty()) {
281 m_newImages->reserve(confirmedImages.count());
286 foreach (QString confirmedImage, confirmedImages) {
287 QStringList fileNameAndId = confirmedImage.split(
",");
289 confirmedImagesFileNames.append(fileNameAndId.first());
291 if (fileNameAndId.count() == 2) {
292 confirmedImagesIds.append(fileNameAndId.last());
295 confirmedImagesIds.append(QString());
300 QFuture<Cube *> future = QtConcurrent::mapped(confirmedImagesFileNames, functor);
305 QThreadPool::globalInstance()->releaseThread();
306 for (
int i = 0; i < confirmedImages.count(); i++) {
309 Cube *cube = future.resultAt(i);
312 Image *newImage =
new Image(future.resultAt(i));
314 if (confirmedImagesIds[i].isEmpty()) {
315 confirmedImagesIds[i] = newImage->
id();
318 newImage->
setId(confirmedImagesIds[i]);
322 imageInternalData.append(confirmedImagesFileNames[i]);
323 imageInternalData.append(confirmedImagesIds[i]);
325 newInternalData.append(imageInternalData.join(
","));
327 m_newImages->append(newImage);
329 newImage->moveToThread(thread());
335 QThreadPool::globalInstance()->reserveThread();
337 m_warning = functor.errors().
toString();
339 m_newImages->moveToThread(thread());
QDir addImageFolder(QString prefix)
Create and return the name of a folder for placing images.
void setProgressValue(int)
Sets the current progress value for the WorkOrder.
Internalizes a list of images and allows for operations on the entire list.
QString id() const
Get a unique, identifying string associated with this image.
File name manipulation and expansion.
Project * project() const
Returns the Project this WorkOrder is attached to.
void asyncRedo()
This method is designed to be implemented by children work orders.
QStringList internalData() const
Gets the internal data for this WorkOrder.
void setId(QString id)
Override the automatically generated ID with the given ID.
static QStringList images(QStringList)
Verify that the input fileNames are image files.
WorkOrder(Project *project)
Create a work order that will work with the given project.
#define _FILEINFO_
Macro for the filename and line number.
void postSyncUndo()
This method is designed to be implemented by children work orders.
A type of error that cannot be classified as any of the other error types.
This represents a cube in a project-based GUI interface.
ImageDisplayProperties * displayProperties()
Get the display (GUI) properties (information) associated with this image.
void addImages(QStringList imageFiles)
Read the given cube file names as Images and add them to the project.
void setProgressRange(int, int)
Sets the progress range of the WorkOrder.
void importConfirmedImages(QStringList confirmedImages, bool copyDnData)
Creates a project image folder and copies the cubes into it.
void setModifiesDiskState(bool changesProjectOnDisk)
.
Provides access to sequential ASCII stream I/O.
QString toString() const
Returns a string representation of this exception.
void postSyncRedo()
This method is designed to be implemented by children work orders.
Saves a project to disk (File->Save Project...)
This copies the given cube(s) into the project.
virtual bool execute()
The (child) implementation of this method should prompt the user/gather state by any means necessary...
bool execute()
The (child) implementation of this method should prompt the user/gather state by any means necessary...
void setInternalData(QStringList data)
Sets the internal data for this WorkOrder.
void closeCube()
Cleans up the Cube pointer.
void asyncUndo()
This method is designed to be implemented by children work orders.
IO Handler for Isis Cubes.