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  setConfirmOverwrite(false);
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 ext = 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(ext)).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_[ ext ] = j;
269  }
270 
271  //emit load signal
272  if ( pluginForExtension_.find( ext ) != pluginForExtension_.end() ){
273  emit load(filename, pluginForExtension_[ ext ]);
274  loadableFiles.push_back(filename);
275  pluginIds.push_back(pluginForExtension_[ext]);
276  }
277  }
278  emit loadFiles(loadableFiles, pluginIds);
279 }
280 
283  //get selection
284  QStringList files = selectedFiles();
285 
286  if ( files.size() != 1 ) {
287  std::cerr << "Error: zero or multiple save files selected!" << std::endl;
288  return;
289  }
290 
291  QString filename = files[0];
292 
293  if (QFileInfo(filename).completeSuffix().isEmpty()) {
294 
295  int s = selectedNameFilter().indexOf("*")+1;
296  int e = selectedNameFilter().indexOf(" ", s);
297  int e2 = selectedNameFilter().indexOf(")", s);
298  if (e == -1 || e2 < e) e = e2;
299 
300  QString ext = selectedNameFilter().mid(s,e-s);
301  filename += ext;
302  }
303 
304  QFile f(filename);
305  QFileInfo fi(filename);
306 
307  //find plugin that can handle the current extension
308  pluginForExtension_.clear();
309 
310  for (uint t=0; t < supportedTypes_.size(); t++){
311 
312  QString filters = supportedTypes_[t].saveFilters;
313 
314  // Take only part inside brackets
315  filters = filters.section("(",1).section(")",0,0);
316 
317  QStringList separateFilters = filters.split(" ");
318 
319  bool found = false;
320 
321  for ( int filterId = 0 ; filterId < separateFilters.size(); ++filterId ) {
322 
323  if (separateFilters[filterId].endsWith(fi.suffix(),Qt::CaseInsensitive)){
324  pluginForExtension_[ fi.suffix() ] = t;
325  found = true;
326  }
327 
328  }
329 
330  if ( found )
331  break;
332 
333  }
334 
335  // display options for all dataTypes
336  if ( !optionsBox_->isChecked() ){
337 
338  FileOptionsDialog options(supportedTypes_,QStringList(fi.suffix()), loadMode_);
339 
340  connect(&options, SIGNAL(setPluginForExtension(QString,int)), this, SLOT(slotSetPluginForExtension(QString,int)) );
341 
342  if ( !options.exec() )
343  return;
344  }
345 
346  if (f.exists()){ //check for extension
347  int ret = QMessageBox::warning(this, tr("File exists"),tr("This file already exists.\n"
348  "Do you want to overwrite the file?"),QMessageBox::Yes|QMessageBox::No,QMessageBox::No);
349  if (ret == QMessageBox::No)
350  return; //abort if users doesn't want to overwrite
351  }
352 
353  const std::map< QString, int >::iterator saving_plugin =
354  pluginForExtension_.find( fi.suffix() );
355  if ( saving_plugin != pluginForExtension_.end() ){
356  if (ids_.size() == 1)
357  emit save(ids_[0],filename, saving_plugin->second);
358  else
359  emit save(ids_ ,filename, saving_plugin->second);
360  }
361 
362  OpenFlipperSettings().setValue("Core/CurrentDir", fi.absolutePath() );
363 }
364 
367  setAcceptMode ( QFileDialog::AcceptOpen );
368  setWindowTitle(tr("Load Object"));
369  loadMode_ = true;
370 
371  setFileMode(QFileDialog::ExistingFiles);
372 
373  // Set directory to last Directory used for Opening Files
374  setDirectory(OpenFlipperSettings().value("Core/CurrentDir").toString() );
375 
376  slotSetLoadFilters();
377 
378  return this->exec();
379 }
380 
382 int LoadWidget::showSave(int _id, QString _filename){
383  setAcceptMode ( QFileDialog::AcceptSave );
384  setFileMode( QFileDialog::AnyFile );
385  setWindowTitle(tr("Save Object"));
386  loadMode_ = false;
387 
388  ids_.clear();
389  ids_.push_back(_id);
390 
391  //set dataType
392  BaseObjectData* object;
393  PluginFunctions::getObject(_id,object);
394 
395  //check if we can save this dataType
396  bool typeFound = false;
397 
398  for (int i=0; i < (int)supportedTypes_.size(); i++)
399  if ( object->dataType( supportedTypes_[i].type ) )
400  typeFound = true;
401 
402 
403  if (!typeFound){
404  std::cerr << "No suitable plugin for saving this dataType." << std::endl;
405  return QDialog::Rejected;
406  }
407 
408  slotSetSaveFilters( object->dataType() );
409 
410  //display correct path/name
411  QFileInfo fi(_filename);
412  QFile file(_filename);
413 
414  setDirectory(OpenFlipperSettings().value("Core/CurrentDir").toString() );
415  selectFile ( fi.fileName() );
416 
417  //try to select the best fitting name filter
418  for (int i=0; i < nameFilters().count(); i++){
419  int s = nameFilters()[i].indexOf("*")+2;
420  int e = nameFilters()[i].indexOf(" ", s);
421  int e2 = nameFilters()[i].indexOf(")", s);
422  if (e == -1 || e2 < e) e = e2;
423 
424  QString ext = nameFilters()[i].mid(s,e-s);
425 
426  if (ext == fi.completeSuffix()){
427  selectNameFilter(nameFilters()[i]);
428  break;
429  }
430  }
431 
432  return this->exec();
433 }
434 
436 int LoadWidget::showSave(IdList _ids, QString _filename){
437  setAcceptMode ( QFileDialog::AcceptSave );
438  setFileMode( QFileDialog::AnyFile );
439  setWindowTitle(tr("Save Objects"));
440  loadMode_ = false;
441 
442  ids_ = _ids;
443 
444  DataType types = 0;
445 
446  for (uint i=0; i < _ids.size(); i++){
447 
448  BaseObjectData* object;
449  PluginFunctions::getObject(_ids[i], object);
450 
451  types |= object->dataType();
452  }
453 
454  //check if we can save this dataType
455  bool typeFound = false;
456 
457  for (int i=0; i < (int)supportedTypes_.size(); i++)
458  if ( supportedTypes_[i].type.contains(types) )
459  typeFound = true;
460 
461 
462  if (!typeFound){
463  std::cerr << "No suitable plugin for saving this dataType." << std::endl;
464  return QDialog::Rejected;
465  }
466 
467  slotSetSaveFilters( types );
468 
469  //display correct path/name
470  QFileInfo fi(_filename);
471  QFile file(_filename);
472 
473  setDirectory(OpenFlipperSettings().value("Core/CurrentDir").toString() );
474  selectFile ( fi.fileName() );
475 
476  //try to select the best fitting name filter
477  for (int i=0; i < nameFilters().count(); i++){
478  int s = nameFilters()[i].indexOf("*")+2;
479  int e = nameFilters()[i].indexOf(" ", s);
480  int e2 = nameFilters()[i].indexOf(")", s);
481  if (e == -1 || e2 < e) e = e2;
482 
483  QString ext = nameFilters()[i].mid(s,e-s);
484 
485  if (ext == fi.completeSuffix()){
486  selectNameFilter(nameFilters()[i]);
487  break;
488  }
489  }
490 
491  return this->exec();
492 }
493 
494 bool LoadWidget::validFilename() {
495 
496  // Only proceed if selected file is REALLY a file
497  // Consider two cases:
498  // Case 1: Filename is neither a valid file nor a directory -> continue and wait for valid file
499  // Case 2: Entered filename is a directory -> Change to directory and wait for valid file
500  QString firstEntered = selectedFiles()[0];
501 
502  // Test if directory exists
503  QDir testdir(firstEntered);
504  if(testdir.exists()) {
505  setDirectory(testdir);
506  return false;
507  }
508 
509  // Test if file exists
510  QFile file(firstEntered);
511  if(!file.exists()) return false;
512 
513  return true;
514 }
515 
517 {
518  QFileInfo firstEntered = selectedFiles()[0];
519  // Test if directory exists
520  return QDir(firstEntered.dir()).exists();
521 }
522 
523 void LoadWidget::accept() {
524 
525  if( (!loadMode_) || validFilename() ) {
526 
527  if ( loadMode_ )
528  loadFile();
529  else
530  {
531  if (!dirExists()) //if dir does not exist, don't accept
532  return;
533  saveFile();
534  }
535 
536  QFileDialog::accept();
537  }
538 }
539 
540 void LoadWidget::slotSetPluginForExtension(QString _extension, int _pluginId ){
541  pluginForExtension_[ _extension ] = _pluginId;
542 }
543 
544 
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
void slotSetLoadFilters()
adjust load-filters to current datatype
Definition: loadWidget.cc:87
int showSave(int _id, QString _filename)
show Widget for saving Files
Definition: loadWidget.cc:382
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...
int showLoad()
show Widget for loading Files
Definition: loadWidget.cc:366
bool dataType(DataType _type) const
Definition: BaseObject.cc:221
void loadFile()
find suitable plugin for loading current file
Definition: loadWidget.cc:185
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.
void saveFile()
find suitable plugin for saving current file
Definition: loadWidget.cc:282
std::vector< int > IdList
Standard Type for id Lists used for scripting.
Definition: DataTypes.hh:179
bool dirExists()
returns true, if the directory of the specified filename (user input via widget) exists ...
Definition: loadWidget.cc:516
void slotSetSaveFilters(DataType _type)
adjust save-filters to current datatype
Definition: loadWidget.cc:133
Predefined datatypes.
Definition: DataTypes.hh:83
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
~LoadWidget()
Destructor.
Definition: loadWidget.cc:81