29 #include <QFileDialog> 30 #include <QMessageBox> 35 #include <itksys/SystemTools.hxx> 39 struct QmitkIOUtil::Impl
41 struct ReaderOptionsDialogFunctor :
public ReaderOptionsFunctorBase
43 bool operator()(LoadInfo &loadInfo)
const override 46 if (dialog.exec() == QDialog::Accepted)
48 return !dialog.ReuseOptions();
52 loadInfo.m_Cancel =
true;
58 struct WriterOptionsDialogFunctor :
public WriterOptionsFunctorBase
60 bool operator()(SaveInfo &saveInfo)
const override 63 if (dialog.exec() == QDialog::Accepted)
65 return !dialog.ReuseOptions();
69 saveInfo.m_Cancel =
true;
76 static QString s_InvalidFilenameCharacters;
83 static bool IsIllegalFilename(
const QString &fullFilename)
85 QFileInfo fi(fullFilename);
86 auto filename = fi.fileName();
88 for (
const auto &ch : s_InvalidFilenameCharacters)
90 if (filename.contains(ch))
96 if (filename.startsWith(
' ' || filename.endsWith(
' ')))
106 #if defined(_WIN32) || defined(_WIN64) 107 QString QmitkIOUtil::Impl::s_InvalidFilenameCharacters =
"<>:\"/\\|?*";
109 QString QmitkIOUtil::Impl::s_InvalidFilenameCharacters =
"/";
112 struct MimeTypeComparison :
public std::unary_function<mitk::MimeType, bool>
114 MimeTypeComparison(
const std::string &mimeTypeName) : m_Name(mimeTypeName) {}
116 const std::string m_Name;
124 std::vector<std::string> categories = mimeTypeProvider->
GetCategories();
125 for (std::vector<std::string>::iterator cat = categories.begin(); cat != categories.end(); ++cat)
127 QSet<QString> filterExtensions;
129 for (std::vector<mitk::MimeType>::iterator mt = mimeTypes.begin(); mt != mimeTypes.end(); ++mt)
131 std::vector<std::string> extensions = mt->GetExtensions();
132 for (std::vector<std::string>::iterator ext = extensions.begin(); ext != extensions.end(); ++ext)
134 filterExtensions << QString::fromStdString(*ext);
138 QString filter = QString::fromStdString(*cat) +
" (";
139 foreach (
const QString &extension, filterExtensions)
141 filter +=
"*." + extension +
" ";
143 filter = filter.replace(filter.size() - 1, 1,
')');
144 filters +=
";;" + filter;
146 filters.prepend(
"All (*)");
152 std::vector<LoadInfo> loadInfos;
153 foreach (
const QString &file, paths)
155 loadInfos.push_back(
LoadInfo(file.toLocal8Bit().constData()));
158 Impl::ReaderOptionsDialogFunctor optionsCallback;
159 std::string errMsg =
Load(loadInfos,
nullptr,
nullptr, &optionsCallback);
162 QMessageBox::warning(parent,
"Error reading files", QString::fromStdString(errMsg));
166 QList<mitk::BaseData::Pointer> qResult;
167 for (std::vector<LoadInfo>::const_iterator iter = loadInfos.begin(), iterEnd = loadInfos.end(); iter != iterEnd;
170 for (
const auto &elem : iter->m_Output)
182 std::vector<LoadInfo> loadInfos;
183 foreach (
const QString &file, paths)
185 loadInfos.push_back(
LoadInfo(file.toLocal8Bit().constData()));
188 mitk::DataStorage::SetOfObjects::Pointer nodeResult = mitk::DataStorage::SetOfObjects::New();
189 Impl::ReaderOptionsDialogFunctor optionsCallback;
190 std::string errMsg =
Load(loadInfos, nodeResult, &storage, &optionsCallback);
193 QMessageBox::warning(parent,
"Error reading files", QString::fromStdString(errMsg));
202 return Load(paths, parent);
211 return Load(paths, storage, parent);
215 const QString &defaultBaseName,
216 const QString &defaultPath,
218 bool setPathProperty)
220 std::vector<const mitk::BaseData *> dataVector;
221 dataVector.push_back(data);
222 QStringList defaultBaseNames;
223 defaultBaseNames.push_back(defaultBaseName);
224 return Save(dataVector, defaultBaseNames, defaultPath, parent, setPathProperty).back();
228 const QStringList &defaultBaseNames,
229 const QString &defaultPath,
231 bool setPathProperty)
233 QStringList fileNames;
234 QString currentPath = defaultPath;
236 std::vector<SaveInfo> saveInfos;
239 for (std::vector<const mitk::BaseData *>::const_iterator dataIter = data.begin(), dataIterEnd = data.end();
240 dataIter != dataIterEnd;
241 ++dataIter, ++counter)
248 if (filters.
Size() < 2)
250 QMessageBox::warning(
252 "Saving not possible",
253 QString(
"No writer available for type \"%1\"").arg(QString::fromStdString((*dataIter)->GetNameOfClass())));
258 QString filterString = filters.
ToString();
260 QString fileName = currentPath;
261 QString dialogTitle =
"Save " + QString::fromStdString((*dataIter)->GetNameOfClass());
262 if (counter < defaultBaseNames.size())
264 dialogTitle +=
" \"" + defaultBaseNames[counter] +
"\"";
265 fileName += QDir::separator() + defaultBaseNames[counter];
279 QString nextName = QFileDialog::getSaveFileName(parent, dialogTitle, fileName, filterString, &selectedFilter);
281 if (Impl::IsIllegalFilename(nextName))
283 QMessageBox::warning(
285 "Saving not possible",
286 QString(
"File \"%2\" contains invalid characters.\n\nPlease avoid any of \"%1\"")
287 .arg(Impl::s_InvalidFilenameCharacters.split(
"", QString::SkipEmptyParts).join(
" "))
292 if (nextName.isEmpty())
300 std::string stdFileName = fileName.toLocal8Bit().constData();
301 QFileInfo fileInfo(fileName);
302 currentPath = fileInfo.absolutePath();
303 QString suffix = fileInfo.completeSuffix();
307 if (fileInfo.exists() && !fileInfo.isFile())
309 QMessageBox::warning(parent,
"Saving not possible", QString(
"The path \"%1\" is not a file").arg(fileName));
316 std::vector<mitk::MimeType> filterMimeTypes = filters.
GetMimeTypes();
317 for (std::vector<mitk::MimeType>::const_iterator mimeTypeIter = filterMimeTypes.begin(),
318 mimeTypeIterEnd = filterMimeTypes.end();
319 mimeTypeIter != mimeTypeIterEnd;
322 if (mimeTypeIter->MatchesExtension(stdFileName))
324 selectedMimeType = *mimeTypeIter;
329 if (!selectedMimeType.
IsValid())
340 if (!fileInfo.exists())
344 if (suffix.isEmpty())
352 selectedMimeType = filterMimeType;
355 if (selectedMimeType.
IsValid())
357 suffix = QString::fromStdString(selectedMimeType.
GetExtensions().front());
358 fileName +=
"." + suffix;
359 stdFileName = fileName.toLocal8Bit().constData();
362 fileInfo = QFileInfo(fileName);
363 if (fileInfo.exists())
365 if (!fileInfo.isFile())
367 QMessageBox::warning(
368 parent,
"Saving not possible", QString(
"The path \"%1\" is not a file").arg(fileName));
371 if (QMessageBox::question(
374 QString(
"A file named \"%1\" already exists. Do you want to replace it?").arg(fileName)) ==
384 if (!selectedMimeType.
IsValid())
387 QMessageBox::warning(
388 parent,
"Saving not possible", QString(
"No mime-type available which can handle \"%1\".").arg(fileName));
392 if (!QFileInfo(fileInfo.absolutePath()).isWritable())
394 QMessageBox::warning(parent,
"Saving not possible", QString(
"The path \"%1\" is not writable").arg(fileName));
398 fileNames.push_back(fileName);
399 saveInfo.
m_Path = stdFileName;
403 saveInfos.push_back(saveInfo);
406 if (!saveInfos.empty())
408 Impl::WriterOptionsDialogFunctor optionsCallback;
409 std::string errMsg =
Save(saveInfos, &optionsCallback, setPathProperty);
412 QMessageBox::warning(parent,
"Error writing files", QString::fromStdString(errMsg));
422 Save(data, fileName);
427 Save(surface, fileName);
432 Save(image, fileName);
437 Save(pointset, fileName);
440 struct QmitkIOUtil::SaveFilter::Impl
445 m_MimeTypes.push_back(ALL_MIMETYPE());
446 m_FilterStrings.push_back(
"All (*.*)");
452 for (std::vector<mitk::MimeType>::const_reverse_iterator iter = mimeTypes.rbegin(), iterEnd = mimeTypes.rend();
456 QList<QString> filterExtensions;
458 std::vector<std::string> extensions = mimeType.
GetExtensions();
459 for (
auto &extension : extensions)
461 filterExtensions << QString::fromStdString(extension);
463 if (m_DefaultExtension.isEmpty())
465 m_DefaultExtension = QString::fromStdString(extensions.front());
468 QString filter = QString::fromStdString(mimeType.
GetComment()) +
" (";
469 foreach (
const QString &extension, filterExtensions)
471 filter +=
"*." + extension +
" ";
473 filter = filter.replace(filter.size() - 1, 1,
')');
474 m_MimeTypes.push_back(mimeType);
475 m_FilterStrings.push_back(filter);
480 std::vector<mitk::MimeType> m_MimeTypes;
481 QStringList m_FilterStrings;
482 QString m_DefaultExtension;
501 d.reset(
new Impl(*other.d));
507 return d->m_MimeTypes;
512 std::vector<mitk::MimeType>::const_iterator iter =
513 std::find_if(d->m_MimeTypes.begin(), d->m_MimeTypes.end(), MimeTypeComparison(mimeType));
514 if (iter == d->m_MimeTypes.end())
518 int index =
static_cast<int>(iter - d->m_MimeTypes.begin());
519 if (index < 0 || index >= d->m_FilterStrings.size())
523 return d->m_FilterStrings[index];
528 int index = d->m_FilterStrings.indexOf(filter);
533 return d->m_MimeTypes[index];
538 if (d->m_FilterStrings.size() > 1)
540 return d->m_FilterStrings.at(1);
542 else if (d->m_FilterStrings.size() > 0)
544 return d->m_FilterStrings.front();
551 return d->m_DefaultExtension;
556 if (d->m_MimeTypes.size() > 1)
558 return d->m_MimeTypes.at(1);
560 else if (d->m_MimeTypes.size() > 0)
562 return d->m_MimeTypes.front();
569 return d->m_FilterStrings.join(
";;");
574 return d->m_FilterStrings.size();
579 return d->m_FilterStrings.isEmpty();
584 return std::find_if(d->m_MimeTypes.begin(), d->m_MimeTypes.end(), MimeTypeComparison(mimeType)) !=
585 d->m_MimeTypes.end();
Data management class that handles 'was created by' relations.
FileWriterSelector m_WriterSelector
Contains a set of IFileWriter objects.
static IMimeTypeProvider * GetMimeTypeProvider(us::ModuleContext *context=us::GetModuleContext())
Get an IMimeTypeProvider instance.
Base of all data objects.
static void SaveBaseDataWithDialog(mitk::BaseData *data, std::string fileName, QWidget *parent=nullptr)
SaveBaseDataWithDialog Convenience method to save any data with a Qt dialog.
static void SaveImageWithDialog(mitk::Image::Pointer image, std::string fileName="", QWidget *parent=nullptr)
SaveImageWithDialog Convenience method to save an image with a Qt dialog.
static mitk::MimeType ALL_MIMETYPE()
bool Select(const std::string &mimeType)
bool ContainsMimeType(const std::string &mimeType)
std::string GetName() const
std::vector< std::string > GetExtensions() const
std::vector< MimeType > GetMimeTypes() const
static void SaveSurfaceWithDialog(mitk::Surface::Pointer surface, std::string fileName="", QWidget *parent=nullptr)
SaveSurfaceWithDialog Convenience method to save a surface with a Qt dialog.
QString GetDefaultExtension() const
The CustomMimeType class represents a custom mime-type which may be registered as a service object...
MimeType m_MimeType
The selected mime-type, used to restrict results from FileWriterSelector.
mitk::MimeType GetDefaultMimeType() const
static QString GetFileOpenFilterString()
GetFilterString.
mitk::MimeType GetMimeTypeForFilter(const QString &filter) const
virtual std::vector< MimeType > GetMimeTypesForCategory(const std::string &category) const =0
QString GetFilterForMimeType(const std::string &mimeType) const
virtual std::vector< std::string > GetCategories() const =0
Get a sorted and unique list of mime-type categories.
static void SavePointSetWithDialog(mitk::PointSet::Pointer pointset, std::string fileName="", QWidget *parent=nullptr)
SavePointSetWithDialog Convenience method to save a pointset with a Qt dialog.
mitk::Image::Pointer image
SaveFilter & operator=(const SaveFilter &other)
The MimeType class represens a registered mime-type. It is an immutable wrapper for mitk::CustomMimeT...
SaveFilter(const SaveFilter &other)
QString GetDefaultFilter() const
static QString Save(const mitk::BaseData *data, const QString &defaultBaseName, const QString &defaultPath=QString(), QWidget *parent=nullptr, bool setPathProperty=false)
std::vector< mitk::MimeType > GetMimeTypes() const
std::string m_Path
The path to write the BaseData object to.
A RAII helper class for core service objects.
static QList< mitk::BaseData::Pointer > Load(const QStringList &paths, QWidget *parent=nullptr)
Loads the specified files.
std::string GetComment() const