diff --git a/Modules/QmitkExt/QmitkApplicationBase/QmitkIOUtil.cpp b/Modules/QmitkExt/QmitkApplicationBase/QmitkIOUtil.cpp index 9b0262c61c..2029557776 100644 --- a/Modules/QmitkExt/QmitkApplicationBase/QmitkIOUtil.cpp +++ b/Modules/QmitkExt/QmitkApplicationBase/QmitkIOUtil.cpp @@ -1,287 +1,315 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkIOUtil.h" #include #include +#include // QT #include #include //ITK #include #include void mitk::QmitkIOUtil::SaveBaseDataWithDialog(mitk::BaseData* data, std::string fileName, QWidget* parent) { try { if (data != NULL) { - //########### Check if we can save as standard image type via itkImageWriter + /* //########### Check if we can save as standard image type via itkImageWriter mitk::Image::Pointer image = dynamic_cast(data); QString classname(data->GetNameOfClass()); if ( image.IsNotNull() && (classname.compare("Image")==0 || classname.compare("SeedsImage")==0 ) ) { SaveImageWithDialog(image, fileName, parent); return; //succes. we can return } //########### End Check if we can save as standard image type via itkImageWriter - +*/ //########### Check if we can save as standard pointset type via mitkPointSetWriter mitk::PointSet::Pointer pointset = dynamic_cast(data); if(pointset.IsNotNull()) { SavePointSetWithDialog(pointset, fileName, parent); return; //succes. we can return } //########### End Check if we can save as standard pointset type via mitkPointSetWriter //########### Check if we can save as standard surface type via mitkVtkSurfaceWriter mitk::Surface::Pointer surface = dynamic_cast(data); if(surface.IsNotNull()) { SaveSurfaceWithDialog(surface, fileName, parent); return; //succes. we can return } //########### End Check if we can save as standard surface type via mitkVtkSurfaceWriter //########### None standard data type was found, try to save with extensions. // now try the file writers provided by the CoreObjectFactory mitk::CoreObjectFactory::FileWriterList fileWriters = mitk::CoreObjectFactory::GetInstance()->GetFileWriters(); - bool writerFound = false; + mitk::CoreObjectFactory::FileWriterList fileWriterCandidates; + QString fileDialogPattern; for (mitk::CoreObjectFactory::FileWriterList::iterator it = fileWriters.begin() ; it != fileWriters.end() ; ++it) { if ( (*it)->CanWriteBaseDataType(data) ) { - writerFound = true; - SaveToFileWriter(*it, data, fileName.c_str()); - //TODO: testen ob das so bleiben kann: - // std::string tmpFileName = (*it)->GetFileName(); - return; - // correct writer has been found->break - // if(!(tmpFileName.length()>0)){ - // return; - // } else { - // writingSuccessful = true; - // break; - // } + fileWriterCandidates.push_back(*it); + fileDialogPattern += QString::fromStdString((*it)->GetFileDialogPattern()) + ";;"; } } - if(!writerFound) + + if (!fileWriterCandidates.empty()) { - // no appropriate writer has been found - QMessageBox::critical(parent,"ERROR","Could not find file writer for this data type"); + // remove last ';;' from pattern + fileDialogPattern.remove( fileDialogPattern.size()-2, 2); + + // Ensure a valid filename + QString qFileName(QString::fromStdString(fileName)); + QString qProposedFileName( qFileName ); + QString selectedFilter; + if(qFileName.isEmpty()) + { + qProposedFileName.append(fileWriterCandidates.front()->GetDefaultFilename()); + } + qProposedFileName.append(fileWriterCandidates.front()->GetDefaultExtension()); + qFileName = GetFileNameWithQDialog("Save file", qProposedFileName, + fileDialogPattern, &selectedFilter); + //do nothing if the user presses cancel + if ( qFileName.isEmpty() ) return; + + QString extension = "."+QFileInfo(qFileName).completeSuffix(); + for (mitk::CoreObjectFactory::FileWriterList::iterator it = fileWriterCandidates.begin() ; + it != fileWriterCandidates.end() ; ++it) + { + if ((*it)->IsExtensionValid(extension.toStdString())) + { + (*it)->SetFileName( qPrintable(qFileName) ); + (*it)->DoWrite( data ); + return; + } + } } + // returnes earlier when successfull + // no appropriate writer has been found + QMessageBox::critical(parent,"ERROR","Could not find file writer for this data type"); + return; } }catch(itk::ExceptionObject e) { QMessageBox::critical( parent, "Exception during saving", e.GetDescription(),QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); } } void mitk::QmitkIOUtil::SaveSurfaceWithDialog(mitk::Surface::Pointer surface, std::string fileName, QWidget* parent) { //default selected suffix for surfaces QString selected_suffix("STL File (*.stl)"); QString possible_suffixes("STL File (*.stl);; VTK File (*.vtk);; VTP File (*.vtp)"); //default initial file name QString initialFilename("NewSurface"); //default image extension initialFilename.append((mitk::IOUtil::DEFAULTSURFACEEXTENSION).c_str()); //if any filename is supplied by the user, use it if( !fileName.empty() ) { initialFilename = fileName.c_str(); } QString qfileName = GetFileNameWithQDialog("Save Surface", initialFilename , possible_suffixes, &selected_suffix, parent); //do nothing if the user presses cancel if ( qfileName.isEmpty() ) return; try{ mitk::IOUtil::SaveSurface(surface,qfileName.toLocal8Bit().constData()); } catch(mitk::Exception &e) { MITK_ERROR << "error saving file: " << e.what(); std::string msg("Could not save surface.\n Error: "); msg.append(e.what()); QMessageBox::critical( NULL, "Exception during saving", msg.c_str(), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); } } void mitk::QmitkIOUtil::SaveImageWithDialog(mitk::Image::Pointer image, std::string fileName, QWidget *parent) { //default selected suffix for images QString selected_suffix("Nearly Raw Raster Data (*.nrrd)"); //default initial file name QString initialFilename("NewImage"); //default image extension initialFilename.append((mitk::IOUtil::DEFAULTIMAGEEXTENSION).c_str()); //if any filename is supplied by the user, use it if( !fileName.empty() ) { initialFilename = fileName.c_str(); } - QString qfileName = GetFileNameWithQDialog("Save Image", initialFilename ,mitk::CoreObjectFactory::GetInstance()->GetSaveFileExtensions(),&selected_suffix,parent); + QString qfileName = GetFileNameWithQDialog("Save Image", initialFilename, + mitk::ImageWriter::New()->GetFileDialogPattern(), + &selected_suffix,parent); //do nothing if the user presses cancel if ( qfileName.isEmpty() ) return; try { mitk::IOUtil::SaveImage(image, qfileName.toLocal8Bit().constData()); } catch(mitk::Exception &e) { MITK_ERROR << "error saving file: " << e.what(); std::string msg("Could not save image.\n Error: "); msg.append(e.what()); QMessageBox::critical( NULL, "Exception during saving", msg.c_str(), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); } } void mitk::QmitkIOUtil::SavePointSetWithDialog(mitk::PointSet::Pointer pointset, std::string fileName, QWidget *parent) { //default selected suffix for point sets QString selected_suffix("MITK Point-Sets (*.mps)"); QString possible_suffixes("MITK Point-Sets (*.mps)"); //default initial file name QString initialFilename("NewPointSet"); //default image extension initialFilename.append((mitk::IOUtil::DEFAULTPOINTSETEXTENSION).c_str()); //if any filename is supplied by the user, use it if( !fileName.empty() ) { initialFilename = fileName.c_str(); } QString qfileName = GetFileNameWithQDialog("Save PointSet", initialFilename , possible_suffixes, &selected_suffix, parent); //do nothing if the user presses cancel if ( qfileName.isEmpty() ) return; try{ mitk::IOUtil::SavePointSet(pointset,qfileName.toLocal8Bit().constData()); } catch(mitk::Exception &e) { MITK_ERROR << "error saving file: " << e.what(); std::string msg("Could not save pointset.\n Error: "); msg.append(e.what()); QMessageBox::critical( NULL, "Exception during saving", msg.c_str(), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); } } QString mitk::QmitkIOUtil::GetFileNameWithQDialog(QString caption, QString defaultFilename, QString filter, QString* selectedFilter, QWidget* parent) { QString returnfileName = ""; static QString lastDirectory = ""; - QString filename = lastDirectory + defaultFilename; - returnfileName = QFileDialog::getSaveFileName(parent,caption,filename,filter,selectedFilter, QFileDialog::DontConfirmOverwrite); + QString filename = lastDirectory +"/"+ defaultFilename; + QString selectedFilterInternal = selectedFilter ? *selectedFilter : QString::null; + returnfileName = QFileDialog::getSaveFileName(parent,caption,filename,filter,&selectedFilterInternal, QFileDialog::DontConfirmOverwrite); + if (selectedFilter) + { + *selectedFilter = selectedFilterInternal; + } if (!returnfileName.isEmpty()) { - std::string dir = itksys::SystemTools::GetFilenamePath( returnfileName.toStdString() ); - dir += Poco::Path::separator(); - lastDirectory = dir.c_str(); // remember path for next save dialog - std::string extension = itksys::SystemTools::GetFilenameLastExtension( returnfileName.toStdString() ); - if(extension.empty()) // if no extension has been entered manually into the filename + QFileInfo fileInfo(returnfileName); + lastDirectory = fileInfo.absolutePath(); // remember path for next save dialog + if(fileInfo.completeSuffix().isEmpty()) // if no extension has been entered manually into the filename + { + // get from combobox selected file extension + QString selectedExtensions = selectedFilterInternal.split(" (", QString::SkipEmptyParts).back().trimmed(); + selectedExtensions = selectedExtensions.split(")", QString::SkipEmptyParts).front().trimmed(); + QString selectedExtension = selectedExtensions.split(" ", QString::SkipEmptyParts).front(); + if (selectedExtension.size() < 3) // at least something like "*.?" { - // get from combobox selected file extension - extension = itksys::SystemTools::GetFilenameLastExtension( selectedFilter->toLocal8Bit().constData()); - extension = extension.substr(0, extension.size()-1); //remove the last char ")" from the extension - returnfileName += QString::fromStdString(extension); //add it to the path which is returned + QMessageBox::critical(parent, "File extension error", "Unable to deduce a valid file extension."); + return QString::null; } - } + selectedExtension = selectedExtension.mid(1); + returnfileName += selectedExtension; //add it to the path which is returned + } - //check if the file exists - if( itksys::SystemTools::FileExists( returnfileName.toLocal8Bit().constData() )) - { + //check if the file exists + if(fileInfo.exists()) + { int answer = QMessageBox::question( parent, "Warning", QString("File %1 already exists. Overwrite?").arg( returnfileName ), QMessageBox::Yes, QMessageBox::No ); if( answer == QMessageBox::No ) { - //if the user doesn't want to overwrite the file, return an emtpy string. - return QString(""); + returnfileName.clear(); } + } } + return returnfileName; } -void mitk::QmitkIOUtil::SaveToFileWriter( mitk::FileWriterWithInformation::Pointer fileWriter, mitk::BaseData::Pointer data, const std::string fileName ) +bool mitk::QmitkIOUtil::SaveToFileWriter( mitk::FileWriterWithInformation::Pointer fileWriter, mitk::BaseData::Pointer data, const std::string fileName ) { - if (! fileWriter->CanWriteBaseDataType(data) ) - { - QMessageBox::critical(NULL,"ERROR","Could not write file. Invalid data type for file writer."); - return; - } - // Ensure a valid filename QString qFileName(QString::fromStdString(fileName)); QString qProposedFileName(qFileName); if(qFileName.isEmpty()) { qProposedFileName.append(fileWriter->GetDefaultFilename()); } qProposedFileName.append(fileWriter->GetDefaultExtension()); qFileName = GetFileNameWithQDialog("Save file", qProposedFileName, QString::fromAscii(fileWriter->GetFileDialogPattern())); //do nothing if the user presses cancel - if ( qFileName.isEmpty() ) return; + if ( qFileName.isEmpty() ) + return false; // Check if an extension exists already and if not, append the default extension if ( !qFileName.contains( QRegExp("\\.\\w+$") ) ) { qFileName.append( fileWriter->GetDefaultExtension() ); } else { std::string extension = itksys::SystemTools::GetFilenameLastExtension( qFileName.toLocal8Bit().constData() ); if (!fileWriter->IsExtensionValid(extension)) { - QString message; - message.append("File extension not suitable for writing given data. Choose one extension of this list: "); - message.append(fileWriter->GetPossibleFileExtensionsAsString().c_str()); - QMessageBox::critical(NULL,"ERROR",message); - return; + return false; } } //Write only if a valid name was set if(qFileName.isEmpty() == false) { fileWriter->SetFileName( qFileName.toLocal8Bit().constData() ); fileWriter->DoWrite( data ); } + + return true; } diff --git a/Modules/QmitkExt/QmitkApplicationBase/QmitkIOUtil.h b/Modules/QmitkExt/QmitkApplicationBase/QmitkIOUtil.h index 20a514b071..4e3955c928 100644 --- a/Modules/QmitkExt/QmitkApplicationBase/QmitkIOUtil.h +++ b/Modules/QmitkExt/QmitkApplicationBase/QmitkIOUtil.h @@ -1,105 +1,106 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _QmitkIOUtil__h_ #define _QmitkIOUtil__h_ #include "QmitkExtExports.h" // std #include // mitk includes #include #include #include #include #include #include //Qt #include #include namespace mitk { class QmitkExt_EXPORT QmitkIOUtil { /** * @brief QmitkIOUtil This is a static helper method to save any files with Qt dialogs. * Methods of opening files with dialogs are currently implemented in QmitkFileOpenAction.h. */ public: /** * @brief SaveBaseDataWithDialog Convenience method to save any data with a Qt dialog. * @param data BaseData holding the data you wish to save. * @param fileName The file name where to save the data (including path and extension). * @param parent An optional QWidget as parent. If no parent is supplied, the QFileDialog can occur anywhere on the screen. */ static void SaveBaseDataWithDialog(BaseData *data, std::string fileName, QWidget* parent = NULL); /** * @brief SaveSurfaceWithDialog Convenience method to save a surface with a Qt dialog. * @param surface The surface to save. * @param fileName The file name where to save the data (including path and extension). * @param parent An optional QWidget as parent. If no parent is supplied, the QFileDialog can occur anywhere on the screen. */ static void SaveSurfaceWithDialog(mitk::Surface::Pointer surface, std::string fileName = "", QWidget* parent = NULL); /** * @brief SaveImageWithDialog Convenience method to save an image with a Qt dialog. * @param image The image to save. * @param fileName The file name where to save the data (including path and extension). * @param parent An optional QWidget as parent. If no parent is supplied, the QFileDialog can occur anywhere on the screen. */ static void SaveImageWithDialog(mitk::Image::Pointer image, std::string fileName = "", QWidget* parent = NULL); /** * @brief SavePointSetWithDialog Convenience method to save a pointset with a Qt dialog. * @param pointset The pointset to save. * @param fileName The file name where to save the data (including path and extension). * @param parent An optional QWidget as parent. If no parent is supplied, the QFileDialog can occur anywhere on the screen. */ static void SavePointSetWithDialog(mitk::PointSet::Pointer pointset, std::string fileName = "", QWidget* parent = NULL); protected: /** * @brief GetFileNameWithQDialog Opens a QDialog and returns the filename. * @param caption Caption for the QDialog. * @param defaultFilename Default filename (e.g. "NewImage.nrrd" for images). * @param filter Filters the data according to data types (e.g. *.nrrd; *.png; etc. for images). * @param selectedFilter Default selected filter for the data. * @return The file name as QString. */ static QString GetFileNameWithQDialog(QString caption, QString defaultFilename, QString filter, QString* selectedFilter = 0, QWidget* parent = NULL); /** * @brief SaveToFileWriter Internal helper method to save data with writer's which have been supplied by extensions (e.g. TensorImage etc.). * @param fileWriter The writer supplied by an extension. * @param data The data to save in a specific format. * @param aFileName The filename. * @param propFileName Proposed file name? + * @return false if writing attempt failed, true otherwise */ - static void SaveToFileWriter(mitk::FileWriterWithInformation::Pointer fileWriter, mitk::BaseData::Pointer data, const std::string fileName); + static bool SaveToFileWriter(mitk::FileWriterWithInformation::Pointer fileWriter, mitk::BaseData::Pointer data, const std::string fileName); }; } //end namespace mitk #endif // _QmitkIOUtil__h_