Developer Documentation
loadWidget.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41 
42 
43 
44 
45 
46 
47 #include "loadWidget.hh"
48 
49 #include "FileOptionsDialog.hh"
50 
51 #include <QFileInfo>
52 
53 LoadWidget::LoadWidget(std::vector<fileTypes>& _supportedTypes , QWidget *parent)
54  : QFileDialog(parent),
55  loadMode_(true),
56  supportedTypes_(_supportedTypes)
57 {
58  setOption (QFileDialog::DontUseNativeDialog, true);
59 
60  // Get our layout
61  QGridLayout *gridLayout = (QGridLayout*)layout();
62 
63  //supported Types
64  optionsBox_ = new QCheckBox(tr("use defaults"), this);
65  optionsBox_->setChecked( OpenFlipperSettings().value("Core/File/UseLoadDefaults",false).toBool() );
66 
67  // add the options box to the bottom
68  gridLayout->addWidget( optionsBox_, gridLayout->rowCount() , 1 );
69 
70  // Add a very nice label for it
71  QLabel* typeLabel = new QLabel(tr("Options:") , this);
72  gridLayout->addWidget( typeLabel, gridLayout->rowCount() -1 , 0 );
73 
74  //overwrite dialog shouldn't be handled by the qfiledialog
75  setOption(DontConfirmOverwrite, true);
76 
77  setDirectory( OpenFlipperSettings().value("Core/CurrentDir").toString() );
78 }
79 
82 {
83 
84 }
85 
88 
89  QStringList allFilters;
90 
91  //TODO All files filter
92 
93  for (int i=0; i < (int)supportedTypes_.size(); i++){
94  QStringList filters = supportedTypes_[i].loadFilters.split(";;");
95  for (int f=filters.size()-1; f >= 0; f--){
96  if (filters[f].trimmed() == "") { filters.removeAt(f); continue; }
97  if (filters[f].contains( tr("All files") ) ) filters.removeAt(f);
98  }
99 
100  allFilters.append( filters );
101  }
102 
103  allFilters.removeDuplicates();
104  allFilters.sort();
105 
106  QStringList allExt;
107 
108  //get all possible extensions
109  for (int i=0; i < allFilters.size(); i++){
110  QString ext = allFilters[i].section("(",1).section(")",0,0);
111  allExt.append( ext.split(" ") );
112  }
113 
114  for (int f=allExt.size()-1; f >= 0; f--)
115  if (allExt[f].trimmed() == "") allExt.removeAt(f);
116 
117  allExt.removeDuplicates();
118  allExt.sort();
119 
120  QString allFiles = tr("All Files (");
121 
122  for (int i=0; i < allExt.size(); i++)
123  allFiles += " " + allExt[i];
124 
125  allFiles += " )";
126 
127  allFilters.push_front(allFiles);
128 
129  setNameFilters(allFilters);
130 }
131 
134 
135  QStringList allFilters;
136 
137  bool multipleFiles = (ids_.size() > 1);
138 
139  for (int i=0; i < (int)supportedTypes_.size(); i++)
140  if ( supportedTypes_[i].type.contains(_type) ){
141 
142  if ( multipleFiles && !supportedTypes_[i].saveMultipleObjects)
143  continue;
144 
145  QStringList filters = supportedTypes_[i].saveFilters.split(";;");
146  for (int f=filters.size()-1; f >= 0; f--){
147  if (filters[f].trimmed() == "") { filters.removeAt(f); continue; }
148  if (filters[f].contains( tr("All files") ) ) filters.removeAt(f);
149  }
150 
151  allFilters.append( filters );
152  }
153 
154  allFilters.removeDuplicates();
155  allFilters.sort();
156 
157  QStringList allExt;
158 
159  //get all possible extensions
160  for (int i=0; i < allFilters.size(); i++){
161  QString ext = allFilters[i].section("(",1).section(")",0,0);
162  allExt.append( ext.split(" ") );
163  }
164 
165  for (int f=allExt.size()-1; f >= 0; f--)
166  if (allExt[f].trimmed() == "") allExt.removeAt(f);
167 
168  allExt.removeDuplicates();
169  allExt.sort();
170 
171  QString allFiles = tr("All Files (");
172 
173  for (int i=0; i < allExt.size(); i++)
174  allFiles += " " + allExt[i];
175 
176  allFiles += " )";
177 
178  allFilters.push_front(allFiles);
179 
180  setNameFilters(allFilters);
181 }
182 
183 
186 
187  //get selection
188  QStringList files = selectedFiles();
189 
190  //get all extensions
191  QStringList ext;
192 
193  for (int i=0; i < files.size(); i++)
194  ext.push_back( QFileInfo(files[i]).suffix() );
195 
196 
197  //find plugins that can handle the current extensions
198  pluginForExtension_.clear();
199 
200  for (int i=0; i < ext.size(); i++){
201 
202  for (uint t=0; t < supportedTypes_.size(); t++){
203 
204  QString filters = supportedTypes_[t].loadFilters;
205 
206  // Take only part inside brackets
207  filters = filters.section("(",1).section(")",0,0);
208 
209  QStringList separateFilters = filters.split(" ");
210 
211  bool found = false;
212 
213  for ( int filterId = 0 ; filterId < separateFilters.size(); ++filterId ) {
214 
215  if (separateFilters[filterId].endsWith("*." + ext[i],Qt::CaseInsensitive)){
216  pluginForExtension_[ ext[i] ] = t;
217  found = true;
218  }
219 
220  }
221 
222  if ( found )
223  break;
224 
225  }
226  }
227 
228  // display options for all dataTypes
229  if ( !optionsBox_->isChecked() ){
230 
231  FileOptionsDialog options(supportedTypes_,ext, loadMode_);
232 
233  connect(&options, SIGNAL(setPluginForExtension(QString,int)), this, SLOT(slotSetPluginForExtension(QString,int)) );
234 
235  if ( !options.exec() )
236  return;
237  }
238 
239 
240  //load the selected files
241  QStringList loadableFiles;
242  IdList pluginIds;
243  for (int i=0; i < files.size(); i++){
244 
245  QFileInfo fi(files[i]);
246  QString filename = fi.absoluteFilePath();
247  OpenFlipperSettings().setValue("Core/CurrentDir", fi.absolutePath());
248  QFile file(filename);
249 
250  if (fi.isDir() || !file.exists()) continue; //do nothing if its a not a valid file
251  QString ext1 = fi.suffix();
252 
253  // if the default options should be used find the default plugin
254  if (optionsBox_->isChecked()) {
255  QString pluginName = OpenFlipperSettings().value(QString("Core/File/DefaultLoader/").append(ext1)).toString();
256 
257  // find the id of the plugin
258  bool found = false;
259  unsigned int j;
260  for (j = 0; j < supportedTypes_.size(); ++j) {
261  if (supportedTypes_[j].name == pluginName) {
262  found = true;
263  break;
264  }
265  }
266 
267  if (found)
268  pluginForExtension_[ ext1 ] = j;
269  }
270 
271  hide();
272 
273  //emit load signal
274  if ( pluginForExtension_.find( ext1 ) != pluginForExtension_.end() ){
275  emit load(filename, pluginForExtension_[ ext1 ]);
276  loadableFiles.push_back(filename);
277  pluginIds.push_back(pluginForExtension_[ext1]);
278  }
279  }
280  emit loadFiles(loadableFiles, pluginIds);
281 }
282 
285  //get selection
286  QStringList files = selectedFiles();
287 
288  if ( files.size() != 1 ) {
289  std::cerr << "Error: zero or multiple save files selected!" << std::endl;
290  return;
291  }
292 
293  QString filename = files[0];
294 
295  if (QFileInfo(filename).completeSuffix().isEmpty()) {
296 
297  int s = selectedNameFilter().indexOf("*")+1;
298  int e = selectedNameFilter().indexOf(" ", s);
299  int e2 = selectedNameFilter().indexOf(")", s);
300  if (e == -1 || e2 < e) e = e2;
301 
302  QString ext = selectedNameFilter().mid(s,e-s);
303  filename += ext;
304  }
305 
306  QFile f(filename);
307  QFileInfo fi(filename);
308 
309  //find plugin that can handle the current extension
310  pluginForExtension_.clear();
311 
312  for (uint t=0; t < supportedTypes_.size(); t++){
313 
314  QString filters = supportedTypes_[t].saveFilters;
315 
316  // Take only part inside brackets
317  filters = filters.section("(",1).section(")",0,0);
318 
319  QStringList separateFilters = filters.split(" ");
320 
321  bool found = false;
322 
323  for ( int filterId = 0 ; filterId < separateFilters.size(); ++filterId ) {
324 
325  if (separateFilters[filterId].endsWith(fi.suffix(),Qt::CaseInsensitive)){
326  pluginForExtension_[ fi.suffix() ] = t;
327  found = true;
328  }
329 
330  }
331 
332  if ( found )
333  break;
334 
335  }
336 
337  // display options for all dataTypes
338  if ( !optionsBox_->isChecked() ){
339 
340  FileOptionsDialog options(supportedTypes_,QStringList(fi.suffix()), loadMode_);
341 
342  connect(&options, SIGNAL(setPluginForExtension(QString,int)), this, SLOT(slotSetPluginForExtension(QString,int)) );
343 
344  if ( !options.exec() )
345  return;
346  }
347 
348  if (f.exists()){ //check for extension
349  int ret = QMessageBox::warning(this, tr("File exists"),tr("This file already exists.\n"
350  "Do you want to overwrite the file?"),QMessageBox::Yes|QMessageBox::No,QMessageBox::No);
351  if (ret == QMessageBox::No)
352  return; //abort if users doesn't want to overwrite
353  }
354 
355  hide();
356 
357  const std::map< QString, int >::iterator saving_plugin =
358  pluginForExtension_.find( fi.suffix() );
359  if ( saving_plugin != pluginForExtension_.end() ){
360  if (ids_.size() == 1)
361  emit save(ids_[0],filename, saving_plugin->second);
362  else
363  emit save(ids_ ,filename, saving_plugin->second);
364  }
365 
366  OpenFlipperSettings().setValue("Core/CurrentDir", fi.absolutePath() );
367 }
368 
371  setAcceptMode ( QFileDialog::AcceptOpen );
372  setWindowTitle(tr("Load Object"));
373  loadMode_ = true;
374 
375  setFileMode(QFileDialog::ExistingFiles);
376 
377  // Set directory to last Directory used for Opening Files
378  setDirectory(OpenFlipperSettings().value("Core/CurrentDir").toString() );
379 
380  slotSetLoadFilters();
381 
382  return this->exec();
383 }
384 
386 int LoadWidget::showSave(int _id, QString _filename){
387  setAcceptMode ( QFileDialog::AcceptSave );
388  setFileMode( QFileDialog::AnyFile );
389  setWindowTitle(tr("Save Object"));
390  loadMode_ = false;
391 
392  ids_.clear();
393  ids_.push_back(_id);
394 
395  //set dataType
396  BaseObjectData* object;
397  PluginFunctions::getObject(_id,object);
398 
399  //check if we can save this dataType
400  bool typeFound = false;
401 
402  for (int i=0; i < (int)supportedTypes_.size(); i++)
403  if ( object->dataType( supportedTypes_[i].type ) )
404  typeFound = true;
405 
406 
407  if (!typeFound){
408  std::cerr << "No suitable plugin for saving this dataType." << std::endl;
409  return QDialog::Rejected;
410  }
411 
412  slotSetSaveFilters( object->dataType() );
413 
414  //display correct path/name
415  QFileInfo fi(_filename);
416  QFile file(_filename);
417 
418  setDirectory(OpenFlipperSettings().value("Core/CurrentDir").toString() );
419  selectFile ( fi.fileName() );
420 
421  //try to select the best fitting name filter
422  for (int i=0; i < nameFilters().count(); i++){
423  int s = nameFilters()[i].indexOf("*")+2;
424  int e = nameFilters()[i].indexOf(" ", s);
425  int e2 = nameFilters()[i].indexOf(")", s);
426  if (e == -1 || e2 < e) e = e2;
427 
428  QString ext = nameFilters()[i].mid(s,e-s);
429 
430  if (ext == fi.completeSuffix()){
431  selectNameFilter(nameFilters()[i]);
432  break;
433  }
434  }
435 
436  return this->exec();
437 }
438 
440 int LoadWidget::showSave(IdList _ids, QString _filename){
441  setAcceptMode ( QFileDialog::AcceptSave );
442  setFileMode( QFileDialog::AnyFile );
443  setWindowTitle(tr("Save Objects"));
444  loadMode_ = false;
445 
446  ids_ = _ids;
447 
448  DataType types = 0;
449 
450  for (uint i=0; i < _ids.size(); i++){
451 
452  BaseObjectData* object;
453  PluginFunctions::getObject(_ids[i], object);
454 
455  types |= object->dataType();
456  }
457 
458  //check if we can save this dataType
459  bool typeFound = false;
460 
461  for (int i=0; i < (int)supportedTypes_.size(); i++)
462  if ( supportedTypes_[i].type.contains(types) )
463  typeFound = true;
464 
465 
466  if (!typeFound){
467  std::cerr << "No suitable plugin for saving this dataType." << std::endl;
468  return QDialog::Rejected;
469  }
470 
471  slotSetSaveFilters( types );
472 
473  //display correct path/name
474  QFileInfo fi(_filename);
475  QFile file(_filename);
476 
477  setDirectory(OpenFlipperSettings().value("Core/CurrentDir").toString() );
478  selectFile ( fi.fileName() );
479 
480  //try to select the best fitting name filter
481  for (int i=0; i < nameFilters().count(); i++){
482  int s = nameFilters()[i].indexOf("*")+2;
483  int e = nameFilters()[i].indexOf(" ", s);
484  int e2 = nameFilters()[i].indexOf(")", s);
485  if (e == -1 || e2 < e) e = e2;
486 
487  QString ext = nameFilters()[i].mid(s,e-s);
488 
489  if (ext == fi.completeSuffix()){
490  selectNameFilter(nameFilters()[i]);
491  break;
492  }
493  }
494 
495  return this->exec();
496 }
497 
498 bool LoadWidget::validFilename() {
499 
500  // Only proceed if selected file is REALLY a file
501  // Consider two cases:
502  // Case 1: Filename is neither a valid file nor a directory -> continue and wait for valid file
503  // Case 2: Entered filename is a directory -> Change to directory and wait for valid file
504  QString firstEntered = selectedFiles()[0];
505 
506  // Test if directory exists
507  QDir testdir(firstEntered);
508  if(testdir.exists()) {
509  setDirectory(testdir);
510  return false;
511  }
512 
513  // Test if file exists
514  QFile file(firstEntered);
515  if(!file.exists()) return false;
516 
517  return true;
518 }
519 
521 {
522  QFileInfo firstEntered = selectedFiles()[0];
523  // Test if directory exists
524  return QDir(firstEntered.dir()).exists();
525 }
526 
527 void LoadWidget::accept() {
528 
529  if( (!loadMode_) || validFilename() ) {
530 
531  if ( loadMode_ )
532  loadFile();
533  else
534  {
535  if (!dirExists()) //if dir does not exist, don't accept
536  return;
537  saveFile();
538  }
539 
540  QFileDialog::accept();
541  }
542 }
543 
544 void LoadWidget::slotSetPluginForExtension(QString _extension, int _pluginId ){
545  pluginForExtension_[ _extension ] = _pluginId;
546 }
547 
548 
int showLoad()
show Widget for loading Files
Definition: loadWidget.cc:370
~LoadWidget()
Destructor.
Definition: loadWidget.cc:81
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.
Predefined datatypes.
Definition: DataTypes.hh:83
bool dataType(DataType _type) const
Definition: BaseObject.cc:221
std::vector< int > IdList
Standard Type for id Lists used for scripting.
Definition: DataTypes.hh:181
void slotSetSaveFilters(DataType _type)
adjust save-filters to current datatype
Definition: loadWidget.cc:133
void saveFile()
find suitable plugin for saving current file
Definition: loadWidget.cc:284
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
int showSave(int _id, QString _filename)
show Widget for saving Files
Definition: loadWidget.cc:386
void slotSetLoadFilters()
adjust load-filters to current datatype
Definition: loadWidget.cc:87
void loadFile()
find suitable plugin for loading current file
Definition: loadWidget.cc:185
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
bool dirExists()
returns true, if the directory of the specified filename (user input via widget) exists ...
Definition: loadWidget.cc:520