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
53LoadWidget::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
381
382 return this->exec();
383}
384
386int 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
440int 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
498bool 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 = QFileInfo(selectedFiles()[0]);
523 // Test if directory exists
524 return QDir(firstEntered.dir()).exists();
525}
526
527void 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
544void LoadWidget::slotSetPluginForExtension(QString _extension, int _pluginId ){
545 pluginForExtension_[ _extension ] = _pluginId;
546}
547
548
std::vector< int > IdList
Standard Type for id Lists used for scripting.
Definition: DataTypes.hh:181
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
bool dataType(DataType _type) const
Definition: BaseObject.cc:219
Predefined datatypes.
Definition: DataTypes.hh:83
int showLoad()
show Widget for loading Files
Definition: loadWidget.cc:370
int showSave(int _id, QString _filename)
show Widget for saving Files
Definition: loadWidget.cc:386
void loadFile()
find suitable plugin for loading current file
Definition: loadWidget.cc:185
void slotSetLoadFilters()
adjust load-filters to current datatype
Definition: loadWidget.cc:87
~LoadWidget()
Destructor.
Definition: loadWidget.cc:81
QCheckBox * optionsBox_
checkbox for option displaying
Definition: loadWidget.hh:98
bool dirExists()
returns true, if the directory of the specified filename (user input via widget) exists
Definition: loadWidget.cc:520
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
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.