Developer Documentation

saveSettings.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 #include "Core.hh"
46
47 //#include <ObjectTypes/Light/Light.hh>
48
49 #include <OpenFlipper/common/FileTypes.hh>
50
51
53 void Core::saveSettings(){
54
55 // ========================================================================================
56 // generate the saveSettings-Dialog
57 // ========================================================================================
58
59 QFileDialog fileDialog( coreWidget_,
60 tr("Save Settings"),
61 OpenFlipperSettings().value("Core/CurrentDir").toString(),
62 tr("INI files (*.ini);;OBJ files (*.obj )") );
63
64 fileDialog.setOption (QFileDialog::DontUseNativeDialog, true);
65 fileDialog.setAcceptMode ( QFileDialog::AcceptSave );
66 fileDialog.setFileMode ( QFileDialog::AnyFile );
67
68 QGridLayout *layout = (QGridLayout*)fileDialog.layout();
69
70 QGroupBox* optionsBox = new QGroupBox( &fileDialog ) ;
71 optionsBox->setSizePolicy( QSizePolicy ( QSizePolicy::Expanding , QSizePolicy::Preferred ) );
72 optionsBox->setTitle(tr("Options"));
73 layout->addWidget( optionsBox, layout->rowCount() , 0 , 1,layout->columnCount() );
74
75 QCheckBox *saveProgramSettings = new QCheckBox(optionsBox);
76 saveProgramSettings->setText(tr("Save program settings"));
77 saveProgramSettings->setToolTip(tr("Save all current program settings to the file ( This will include view settings, colors,...) "));
78 saveProgramSettings->setCheckState( Qt::Unchecked );
79
80 QCheckBox *savePluginSettings = new QCheckBox(optionsBox);
81 savePluginSettings->setText(tr("Save per Plugin Settings"));
82 savePluginSettings->setToolTip(tr("Plugins should add their current global settings to the file"));
83 savePluginSettings->setCheckState( Qt::Checked );
84
85 QCheckBox *saveObjectInfo = new QCheckBox(optionsBox);
86 saveObjectInfo->setText(tr("Save open object information to the file"));
87 saveObjectInfo->setToolTip(tr("Save all open Objects and add them to the settings file ( they will be loaded if opening the settings file"));
88 saveObjectInfo->setCheckState( Qt::Checked );
89
90 QCheckBox *saveAllBox = new QCheckBox(optionsBox);
91 saveAllBox->setText(tr("Save everything to same folder"));
92 saveAllBox->setToolTip(tr("Save all open files to the same folder as the ini file"));
93 saveAllBox->setCheckState( Qt::Checked );
94
95 QCheckBox *askOverwrite = new QCheckBox(optionsBox);
96 askOverwrite->setText(tr("Ask before overwriting files"));
97 askOverwrite->setToolTip(tr("If a file exists you will get asked what to do"));
98 askOverwrite->setCheckState( Qt::Checked );
99
100 QCheckBox *targetOnly = new QCheckBox(optionsBox);
101 targetOnly->setText(tr("Save only target objects"));
102 targetOnly->setToolTip(tr("Only objects with target flag will be handled"));
103 targetOnly->setCheckState( Qt::Unchecked );
104
105 QBoxLayout* frameLayout = new QBoxLayout(QBoxLayout::TopToBottom,optionsBox);
106 frameLayout->addWidget( saveProgramSettings , 0 , 0);
107 frameLayout->addWidget( savePluginSettings , 1 , 0);
108 frameLayout->addWidget( saveObjectInfo , 2 , 0);
109 frameLayout->addWidget( saveAllBox , 3 , 0);
110 frameLayout->addWidget( askOverwrite , 4 , 0);
111 frameLayout->addWidget( targetOnly , 5 , 0);
112 frameLayout->addStretch();
113
114 fileDialog.resize(550 ,600);
115
116 // ========================================================================================
117 // show the saveSettings-Dialog and get the target file
118 // ========================================================================================
119 QStringList fileNames;
120 if (fileDialog.exec()) {
121 fileNames = fileDialog.selectedFiles();
122 } else {
123 return;
124 }
125
126 if ( fileNames.size() > 1 ) {
127 std::cerr << "Too many save filenames selected" << std::endl;
128 return;
129 }
130
131 QString complete_name = fileNames[0];
132
133 //check the extension if its a known one
134 if ( !complete_name.endsWith(".ini", Qt::CaseInsensitive) && !complete_name.endsWith(".obj", Qt::CaseInsensitive) ){
135
136 // If its unknown, get the type from the currently selected filter and add this extension to the filename
137 if ( fileDialog.selectedNameFilter().contains(tr("INI files (*.ini)")) )
138 complete_name += ".ini";
139 else
140 complete_name += ".obj";
141
142 }
143
144 bool is_saveObjectInfo = saveObjectInfo->isChecked();
145 bool is_targetOnly = targetOnly->isChecked();
146 bool is_saveAll = saveAllBox->isChecked();
147 bool is_askOverwrite = askOverwrite->isChecked();
148 bool is_saveProgramSettings = saveProgramSettings->isChecked();
149 bool is_savePluginSettings = savePluginSettings->isChecked();
150
151 saveSettings(complete_name, is_saveObjectInfo, is_targetOnly, is_saveAll, is_askOverwrite, is_saveProgramSettings, is_savePluginSettings);
152 }
153
154 void Core::saveSettings(QString complete_name, bool is_saveObjectInfo, bool is_targetOnly, bool is_saveAll,
155 bool is_askOverwrite, bool is_saveProgramSettings, bool is_savePluginSettings){
156 // Get the chosen directory and remember it.
157 QFileInfo fileInfo(complete_name);
158 OpenFlipperSettings().setValue("Core/CurrentDir", fileInfo.absolutePath() );
159
160 // ========================================================================================
161 // update status information
162 // ========================================================================================
163 OpenFlipper::Options::savingSettings(true);
164
165 if ( OpenFlipper::Options::gui() ) {
166 coreWidget_->statusMessage( tr("Saving Settings to ") + complete_name + " ...");
167 coreWidget_->setStatus(ApplicationStatus::BLOCKED );
168 }
169
170 // ========================================================================================
171 // Save the objects itself
172 // ========================================================================================
173 // Depending on the checkbox iterate over all objects or only the selected ones.
174
175 // Memorize saved files new file names
176 std::map<int,QString> savedFiles;
177
178 if ( is_saveObjectInfo ) {
179
180 PluginFunctions::IteratorRestriction restriction;
181 if ( is_targetOnly )
182 restriction = PluginFunctions::TARGET_OBJECTS;
183 else
184 restriction = PluginFunctions::ALL_OBJECTS;
185
186 // Store saved file's original names (in order to get number of duplicates)
187 std::multiset<QString> originalFiles;
188
189 // Store default extensions per type
190 std::map<DataType,QString> defaultExtensions;
191 // get the supported extensions for when no extension is given
192 QMultiMap<DataType,QString> allFilters; // type -> supported extension
193 const std::vector<fileTypes>& types = supportedTypes();
194 for (int i=0; i < (int)types.size(); i++) {
195 QString filters = types[i].saveFilters;
196
197 // only take the actual extensions
198 filters = filters.section("(",1).section(")",0,0);
199 if (filters.trimmed() == "")
200 continue;
201
202 QStringList separateFilters = filters.split(" ");
203 bool found = false;
204 for ( int filterId = 0 ; filterId < separateFilters.size(); ++filterId ) {
205 if (separateFilters[filterId].trimmed() == "")
206 continue;
207
208 found = true;
209 allFilters.insert(types[i].type,separateFilters[filterId]);
210 }
211
212 if (!found)
213 allFilters.insert(types[i].type,filters);
214 }
215
216 // create a dialog to set extensions if none are given once
217 QDialog extensionDialog(coreWidget_, Qt::Dialog);
218 QGridLayout extensionLayout;
219 const QString extensionCheckBoxPrefixString = "Apply extension to all Objects without preset extensions with DataType: ";
220 QCheckBox extensionCheckBox;
221 QComboBox extensionComboBox;
222 QDialogButtonBox extensionButtons(QDialogButtonBox::Ok);
223 QDialogButtonBox::connect(&extensionButtons, SIGNAL(accepted()), &extensionDialog, SLOT(accept()));
224 //extensionComboBox.addItems(allFilters);
225 extensionLayout.addWidget(&extensionComboBox);
226 extensionLayout.addWidget(&extensionCheckBox);
227 extensionLayout.addWidget(&extensionButtons);
228 extensionDialog.setLayout(&extensionLayout);
229
230 //Iterate over opened objects and save them
231 for ( PluginFunctions::ObjectIterator o_it(restriction);
232 o_it != PluginFunctions::objectsEnd(); ++o_it)
233 {
234 QString filename;
235
236 if ( is_saveAll )
237 {
238 // Use path of settings file for all objects
239 filename = fileInfo.absolutePath() + OpenFlipper::Options::dirSeparator() + o_it->name();
240 }
241 else
242 {
243 // Use objects own path if it has one. Otherwise also use path of settings file
244 filename = o_it->path() + OpenFlipper::Options::dirSeparator() + o_it->name();
245
246 // handle the case that the object was created in current session and not loaded from disk
247 if (o_it->path() == ".") {
248 filename = fileInfo.absolutePath() + OpenFlipper::Options::dirSeparator() + o_it->name();
249 std::cerr << "newpath : " << fileInfo.absolutePath().toStdString() << std::endl;
250 std::cerr << "name : " << o_it->name().toStdString() << std::endl;
251 }
252 }
253
254 // enforce that all files end with obj extension if its an obj-settings file
255 if ( complete_name.endsWith("obj") )
256 {
257 if (!filename.endsWith("obj"))
258 {
259 // remove old extension
260 int pos = filename.lastIndexOf(".");
261 filename.remove(pos+1, filename.length() - pos);
262 // add obj extension
263 filename += "obj";
264 }
265 }
266
267 /* @Todo: This is broken when Light source Object type is not available!
268 // Don't save default light source objects
269 LightObject* light = 0;
270 PluginFunctions::getObject( o_it->id(), light );
271 if(light != 0) {
272 if(light->defaultLight()) continue;
273 }
274
275 */
276
277 // Store original file name
278 originalFiles.insert(filename);
279
280 // If a file with the same name already has been saved,
281 // rename it.
282 size_t c = originalFiles.count(filename);
283 if(c > 1) {
284 QFileInfo finfo(filename);
285 filename = finfo.absolutePath() + OpenFlipper::Options::dirSeparator();
286 filename += finfo.baseName() + QString("_%1").arg(c-1) + ".";
287 filename += finfo.completeSuffix();
288 }
289
290 // check if the name of the object specifies already the extension
291 bool extInName = false;
292 for (QMultiMap<DataType,QString>::const_iterator e_it = allFilters.begin(); e_it != allFilters.end(); ++e_it)
293 {
294 // suffix is the same as one extension and
295 extInName = e_it.key().contains(o_it->dataType()) && e_it.value() == QString("*.")+QFileInfo(filename).suffix();
296 if (extInName)
297 break;
298 }
299
300 if (!extInName)
301 {
302 // search for the default data type
303 std::map<DataType,QString>::const_iterator defaultExtIt = defaultExtensions.find(o_it->dataType());
304 bool useDefault = defaultExtIt != defaultExtensions.end();
305 QString extension = (useDefault) ? defaultExtIt->second : "";
306
307 // if no default extension for the datatype was given, request one
308 if (!useDefault)
309 {
310 // present only those filters, which support the type
311 QStringList supportedFilters;
312 for (QMultiMap<DataType,QString>::const_iterator it = allFilters.begin(); it != allFilters.end() ; ++it)
313 {
314 if (it.key().contains(o_it->dataType()))
315 supportedFilters.append(it.value());
316 }
317
318 extensionComboBox.clear();
319 extensionComboBox.addItems(supportedFilters);
320 extensionDialog.setWindowTitle("Please specify a file extension for " + o_it->name());
321 extensionCheckBox.setText(extensionCheckBoxPrefixString + typeName(o_it->dataType()));
322 extensionDialog.move(coreWidget_->width()/2 - extensionDialog.width(),
323 coreWidget_->height()/2 - extensionDialog.height());
324
325 if (extensionDialog.exec() && !supportedFilters.isEmpty())
326 {
327 extension = extensionComboBox.currentText();
328 extension = QFileInfo(extension).suffix();
329 filename += "." + extension;
330 if (extensionCheckBox.isChecked())
331 defaultExtensions[o_it->dataType()] = extension;
332
333 } else
334 {
335 emit log(LOGERR, tr("Unabel to save %1. No extension specified.").arg(o_it->name()));
336 continue;
337 }
338 } else
339 {
340 filename += "." + extension;
341 }
342 }
343
344
345 // decide whether to use saveObject or saveObjectTo
346 if ( !QFile(filename).exists() || !is_askOverwrite )
347 saveObject( o_it->id(), filename);
348 else
349 saveObjectTo(o_it->id(), filename);
350
351 // Store saved file's name
352 savedFiles.insert(std::pair<int,QString>(o_it->id(),filename));
353
354 }
355 }
356
357
358 // ========================================================================================
359 // Finally save all Settings
360 // ========================================================================================
361 if ( complete_name.endsWith("obj") ) {
362
363 //write to obj
364 writeObjFile(complete_name, is_saveAll, is_targetOnly, savedFiles);
365
366 } else {
367 // write to ini
368 writeIniFile( complete_name,
369 is_saveAll,
370 is_targetOnly,
371 is_saveProgramSettings,
372 is_savePluginSettings,
373 is_saveObjectInfo,
374 savedFiles);
375 }
376
377 // update status
378 OpenFlipper::Options::savingSettings(false);
379
380 if ( OpenFlipper::Options::gui() ) {
381 coreWidget_->statusMessage( tr("Saving Settings to ") + complete_name + tr(" ... Done"), 4000);
382 coreWidget_->setStatus(ApplicationStatus::READY );
383 }
384
385 //add to recent files
386 if ( OpenFlipper::Options::gui() )
387 coreWidget_->addRecent( complete_name, DATA_UNKNOWN );
388
389 }
OpenFlipperSettings
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
Definition: GlobalOptions.cc:1038
Core::saveSettings
void saveSettings()
Save current status to a settings file. Solicit file name through dialog.
Definition: saveSettings.cc:53
ApplicationStatus::READY
Status is ready (green light)
Definition: StatusbarInterface.hh:65
ApplicationStatus::BLOCKED
Status is processing and blocked system will not allow interaction (red light)
Definition: StatusbarInterface.hh:67
typeName
DLLEXPORT QString typeName(DataType _id)
Get the name of a type with given id.
Definition: Types.cc:154
Core::writeIniFile
void writeIniFile(QString _filename, bool _relativePaths, bool _targetOnly, bool _saveSystemSettings, bool _savePluginSettings, bool _saveObjectInfo, std::map< int, QString > &_fileMapping)
Write current status to ini file (Application and File Options)
Definition: ParseIni.cc:540
CoreWidget::addRecent
void addRecent(QString _filename, DataType _type)
Add a recent file and update menu.
Definition: CoreWidget.cc:860
Core.hh
OpenFlipperQSettings::setValue
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...
Definition: OpenFlipperQSettings.cc:61
PluginFunctions::TARGET_OBJECTS
const QStringList TARGET_OBJECTS("target")
Iterable object range.
PluginFunctions::IteratorRestriction
QStringList IteratorRestriction
Iterable object range.
Definition: PluginFunctions.hh:428
Core::log
void log(Logtype _type, QString _message)
Logg with OUT,WARN or ERR as type.
Core::coreWidget_
CoreWidget * coreWidget_
The main applications widget ( only created in gui mode )
Definition: Core.hh:1596
PluginFunctions::ALL_OBJECTS
const QStringList ALL_OBJECTS
Iterable object range.
Definition: PluginFunctions.hh:430
LOGERR
Definition: LoggingInterface.hh:96
Core::saveObjectTo
bool saveObjectTo(int _id, QString _filename)
Definition: saveFunctions.cc:211
DATA_UNKNOWN
const DataType DATA_UNKNOWN(0)
None of the other Objects.
PluginFunctions::ObjectIterator
Core Data Iterator.
Definition: PluginFunctions.hh:441
PluginFunctions::objectsEnd
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
Definition: PluginFunctionsIterator.cc:177
FileTypes.hh
Core::writeObjFile
void writeObjFile(QString _filename, bool _relativePaths, bool _targetOnly, std::map< int, QString > &_fileMapping)
Write current status to obj file (Application and File Options)
Definition: ParseObj.cc:65
Core::saveObject
bool saveObject(int _id, QString _filename)
Save an object.
Definition: saveFunctions.cc:65