saveSettings.cc 17 KB
Newer Older
1
/*===========================================================================*\
Jan Möbius's avatar
Jan Möbius committed
2 3
*                                                                            *
*                              OpenFlipper                                   *
Martin Schultz's avatar
Martin Schultz committed
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
 *           Copyright (c) 2001-2015, RWTH-Aachen University                 *
 *           Department of Computer Graphics and Multimedia                  *
 *                          All rights reserved.                             *
 *                            www.openflipper.org                            *
 *                                                                           *
 *---------------------------------------------------------------------------*
 * This file is part of OpenFlipper.                                         *
 *---------------------------------------------------------------------------*
 *                                                                           *
 * Redistribution and use in source and binary forms, with or without        *
 * modification, are permitted provided that the following conditions        *
 * are met:                                                                  *
 *                                                                           *
 * 1. Redistributions of source code must retain the above copyright notice, *
 *    this list of conditions and the following disclaimer.                  *
 *                                                                           *
 * 2. Redistributions in binary form must reproduce the above copyright      *
 *    notice, this list of conditions and the following disclaimer in the    *
 *    documentation and/or other materials provided with the distribution.   *
 *                                                                           *
 * 3. Neither the name of the copyright holder nor the names of its          *
 *    contributors may be used to endorse or promote products derived from   *
 *    this software without specific prior written permission.               *
 *                                                                           *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS       *
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A           *
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  *
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,       *
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR        *
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    *
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING      *
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS        *
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.              *
Jan Möbius's avatar
Jan Möbius committed
39
*                                                                            *
40 41 42
\*===========================================================================*/

/*===========================================================================*\
Jan Möbius's avatar
Jan Möbius committed
43 44 45 46 47
*                                                                            *
*   $Revision$                                                       *
*   $LastChangedBy$                                                *
*   $Date$                     *
*                                                                            *
48
\*===========================================================================*/
49 50 51 52


#include "Core.hh"

53 54
#include <ObjectTypes/Light/Light.hh>

55 56 57
/// Save Settings (slot is called from CoreWidget's File-Menu)
void Core::saveSettings(){

Jan Möbius's avatar
Jan Möbius committed
58
  // ========================================================================================
59
  // generate the saveSettings-Dialog
Jan Möbius's avatar
Jan Möbius committed
60
  // ========================================================================================
61 62 63

  QFileDialog fileDialog( coreWidget_,
                          tr("Save Settings"),
64
                          OpenFlipperSettings().value("Core/CurrentDir").toString(),
65 66
                          tr("INI files (*.ini);;OBJ files (*.obj )") );

67
  fileDialog.setOption (QFileDialog::DontUseNativeDialog, true);
68 69
  fileDialog.setAcceptMode ( QFileDialog::AcceptSave );
  fileDialog.setFileMode ( QFileDialog::AnyFile );
70

71 72 73 74
  QGridLayout *layout = (QGridLayout*)fileDialog.layout();

  QGroupBox* optionsBox = new QGroupBox( &fileDialog ) ;
  optionsBox->setSizePolicy( QSizePolicy ( QSizePolicy::Expanding , QSizePolicy::Preferred ) );
75
  optionsBox->setTitle(tr("Options"));
76 77
  layout->addWidget( optionsBox, layout->rowCount() , 0 , 1,layout->columnCount() );

Jan Möbius's avatar
Jan Möbius committed
78
  QCheckBox *saveProgramSettings = new QCheckBox(optionsBox);
79 80
  saveProgramSettings->setText(tr("Save program settings"));
  saveProgramSettings->setToolTip(tr("Save all current program settings to the file ( This will include view settings, colors,...) "));
Jan Möbius's avatar
Jan Möbius committed
81 82
  saveProgramSettings->setCheckState( Qt::Unchecked );

83
  QCheckBox *savePluginSettings = new QCheckBox(optionsBox);
84 85
  savePluginSettings->setText(tr("Save per Plugin Settings"));
  savePluginSettings->setToolTip(tr("Plugins should add their current global settings to the file"));
86 87 88
  savePluginSettings->setCheckState( Qt::Checked );

  QCheckBox *saveObjectInfo = new QCheckBox(optionsBox);
89 90
  saveObjectInfo->setText(tr("Save open object information to the file"));
  saveObjectInfo->setToolTip(tr("Save all open Objects and add them to the settings file ( they will be loaded if opening the settings file"));
91 92
  saveObjectInfo->setCheckState( Qt::Checked );

93
  QCheckBox *saveAllBox = new QCheckBox(optionsBox);
94 95
  saveAllBox->setText(tr("Save everything to same folder"));
  saveAllBox->setToolTip(tr("Save all open files to the same folder as the ini file"));
96 97 98
  saveAllBox->setCheckState( Qt::Checked );

  QCheckBox *askOverwrite = new QCheckBox(optionsBox);
99 100
  askOverwrite->setText(tr("Ask before overwriting files"));
  askOverwrite->setToolTip(tr("If a file exists you will get asked what to do"));
101 102 103
  askOverwrite->setCheckState( Qt::Checked );

  QCheckBox *targetOnly = new QCheckBox(optionsBox);
104 105
  targetOnly->setText(tr("Save only target objects"));
  targetOnly->setToolTip(tr("Only objects with target flag will be handled"));
106 107 108
  targetOnly->setCheckState( Qt::Unchecked );

  QBoxLayout* frameLayout = new QBoxLayout(QBoxLayout::TopToBottom,optionsBox);
109 110 111 112 113 114
  frameLayout->addWidget( saveProgramSettings , 0 , 0);
  frameLayout->addWidget( savePluginSettings  , 1 , 0);
  frameLayout->addWidget( saveObjectInfo      , 2 , 0);
  frameLayout->addWidget( saveAllBox          , 3 , 0);
  frameLayout->addWidget( askOverwrite        , 4 , 0);
  frameLayout->addWidget( targetOnly          , 5 , 0);
115 116
  frameLayout->addStretch();

Jan Möbius's avatar
Jan Möbius committed
117
  fileDialog.resize(550 ,600);
118

Jan Möbius's avatar
Jan Möbius committed
119 120 121
  // ========================================================================================
  // show the saveSettings-Dialog and get the target file
  // ========================================================================================
122 123 124 125 126 127 128 129 130 131 132 133
  QStringList fileNames;
  if (fileDialog.exec()) {
    fileNames = fileDialog.selectedFiles();
  } else {
    return;
  }

  if ( fileNames.size() > 1 ) {
    std::cerr << "Too many save filenames selected" << std::endl;
    return;
  }

134
  QString complete_name = fileNames[0];
135

Jan Möbius's avatar
Jan Möbius committed
136
  //check the extension if its a known one
137
  if ( !complete_name.endsWith(".ini", Qt::CaseInsensitive) && !complete_name.endsWith(".obj", Qt::CaseInsensitive) ){
Jan Möbius's avatar
Jan Möbius committed
138 139

    // If its unknown, get the type from the currently selected filter and add this extension to the filename
140
    if ( fileDialog.selectedNameFilter().contains(tr("INI files (*.ini)")) )
141 142 143
      complete_name += ".ini";
    else
      complete_name += ".obj";
Jan Möbius's avatar
Jan Möbius committed
144

145 146
  }

147 148 149 150 151 152 153 154 155 156 157 158
  bool is_saveObjectInfo = saveObjectInfo->isChecked();
  bool is_targetOnly = targetOnly->isChecked();
  bool is_saveAll = saveAllBox->isChecked();
  bool is_askOverwrite = askOverwrite->isChecked();
  bool is_saveProgramSettings = saveProgramSettings->isChecked();
  bool is_savePluginSettings = savePluginSettings->isChecked();

  saveSettings(complete_name, is_saveObjectInfo, is_targetOnly, is_saveAll, is_askOverwrite, is_saveProgramSettings, is_savePluginSettings);
}

void Core::saveSettings(QString complete_name, bool is_saveObjectInfo, bool is_targetOnly, bool is_saveAll,
                        bool is_askOverwrite, bool is_saveProgramSettings, bool is_savePluginSettings){
Jan Möbius's avatar
Jan Möbius committed
159
  // Get the chosen directory and remember it.
160 161
  QFileInfo fileInfo(complete_name);
  OpenFlipperSettings().setValue("Core/CurrentDir", fileInfo.absolutePath() );
162

Jan Möbius's avatar
Jan Möbius committed
163 164 165
  // ========================================================================================
  // update status information
  // ========================================================================================
166 167 168
  OpenFlipper::Options::savingSettings(true);

  if ( OpenFlipper::Options::gui() ) {
169
    coreWidget_->statusMessage( tr("Saving Settings to ") + complete_name + " ...");
170 171 172
    coreWidget_->setStatus(ApplicationStatus::BLOCKED );
  }

Jan Möbius's avatar
Jan Möbius committed
173 174 175 176
  // ========================================================================================
  // Save the objects itself
  // ========================================================================================
  // Depending on the checkbox iterate over all objects or only the selected ones.
177

178 179 180
  // Memorize saved files new file names
  std::map<int,QString> savedFiles;

181
  if ( is_saveObjectInfo ) {
182

183
    PluginFunctions::IteratorRestriction restriction;
184
    if ( is_targetOnly )
185
      restriction = PluginFunctions::TARGET_OBJECTS;
186
    else
187 188
      restriction = PluginFunctions::ALL_OBJECTS;

189 190 191
    // Store saved file's original names (in order to get number of duplicates)
    std::multiset<QString> originalFiles;

192 193
    // Store default extensions per type
    std::map<DataType,QString> defaultExtensions;
194
    // get the supported extensions for when no extension is given
195 196
    QMultiMap<DataType,QString> allFilters; // type -> supported extension
    const std::vector<fileTypes>& types = supportedTypes();
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
    for (int i=0; i < (int)types.size(); i++) {
      QString filters = types[i].saveFilters;

      // only take the actual extensions
      filters = filters.section("(",1).section(")",0,0);
      if (filters.trimmed() == "")
        continue;

      QStringList separateFilters = filters.split(" ");
      bool found = false;
      for ( int filterId = 0 ; filterId < separateFilters.size(); ++filterId ) {
        if (separateFilters[filterId].trimmed() == "")
          continue;

        found = true;
212
        allFilters.insert(types[i].type,separateFilters[filterId]);
213 214 215
      }

      if (!found)
216
        allFilters.insert(types[i].type,filters);
217 218 219 220 221
    }

    // create a dialog to set extensions if none are given once
    QDialog extensionDialog(coreWidget_, Qt::Dialog);
    QGridLayout extensionLayout;
222 223
    const QString extensionCheckBoxPrefixString = "Apply extension to all Objects without preset extensions with DataType: ";
    QCheckBox extensionCheckBox;
224 225 226
    QComboBox extensionComboBox;
    QDialogButtonBox extensionButtons(QDialogButtonBox::Ok);
    QDialogButtonBox::connect(&extensionButtons, SIGNAL(accepted()), &extensionDialog, SLOT(accept()));
227
    //extensionComboBox.addItems(allFilters);
228 229 230 231 232
    extensionLayout.addWidget(&extensionComboBox);
    extensionLayout.addWidget(&extensionCheckBox);
    extensionLayout.addWidget(&extensionButtons);
    extensionDialog.setLayout(&extensionLayout);

233 234
    //Iterate over opened objects and save them
    for ( PluginFunctions::ObjectIterator o_it(restriction);
Jan Möbius's avatar
 
Jan Möbius committed
235
                                          o_it != PluginFunctions::objectsEnd(); ++o_it)
236
    {
237
      QString filename;
238

239
      if ( is_saveAll )
240 241
      {
        // Use path of settings file for all objects
242
        filename = fileInfo.absolutePath() + OpenFlipper::Options::dirSeparator() + o_it->name();
243
      }
244 245 246 247 248 249 250
      else
      {
        // Use objects own path if it has one. Otherwise also use path of settings file
        filename = o_it->path() + OpenFlipper::Options::dirSeparator() + o_it->name();

        // handle the case that the object was created in current session and not loaded from disk
        if (o_it->path() == ".") {
251 252
          filename = fileInfo.absolutePath() + OpenFlipper::Options::dirSeparator() + o_it->name();
          std::cerr << "newpath : " << fileInfo.absolutePath().toStdString() << std::endl;
253 254 255
          std::cerr << "name  : " << o_it->name().toStdString() << std::endl;
        }
      }
256

257 258
      // enforce that all files end with obj extension if its an obj-settings file
      if ( complete_name.endsWith("obj") )
259
      {
260 261 262 263 264 265 266 267
        if (!filename.endsWith("obj"))
        {
          // remove old extension
          int pos = filename.lastIndexOf(".");
          filename.remove(pos+1, filename.length() - pos);
          // add obj extension
          filename += "obj";
        }
268
      }
269 270 271 272 273 274 275
      
      // Don't save default light source objects
      LightObject* light = 0;
      PluginFunctions::getObject( o_it->id(), light );
      if(light != 0) {
          if(light->defaultLight()) continue;
      }
276

277 278 279 280 281
      // Store original file name
      originalFiles.insert(filename);

      // If a file with the same name already has been saved,
      // rename it.
282
      size_t c = originalFiles.count(filename);
283 284 285
      if(c > 1) {
          QFileInfo finfo(filename);
          filename = finfo.absolutePath() + OpenFlipper::Options::dirSeparator();
286
          filename += finfo.baseName() + QString("_%1").arg(c-1) + ".";
287 288 289
          filename += finfo.completeSuffix();
      }

290 291 292 293 294 295 296 297 298
      // check if the name of the object specifies already the extension
      bool extInName = false;
      for (QMultiMap<DataType,QString>::const_iterator e_it = allFilters.begin(); e_it != allFilters.end(); ++e_it)
      {
        // suffix is the same as one extension and
        extInName = e_it.key().contains(o_it->dataType()) && e_it.value() == QString("*.")+QFileInfo(filename).suffix();
        if (extInName)
          break;
      }
299

300 301 302 303 304 305
      if (!extInName)
      {
        // search for the default data type
        std::map<DataType,QString>::const_iterator defaultExtIt = defaultExtensions.find(o_it->dataType());
        bool useDefault = defaultExtIt != defaultExtensions.end();
        QString extension = (useDefault) ? defaultExtIt->second : "";
306

307 308 309 310 311 312 313 314 315 316
        // if no default extension for the datatype was given, request one
        if (!useDefault)
        {
          // present only those filters, which support the type
          QStringList supportedFilters;
          for (QMultiMap<DataType,QString>::const_iterator it = allFilters.begin(); it != allFilters.end() ; ++it)
          {
            if (it.key().contains(o_it->dataType()))
              supportedFilters.append(it.value());
          }
317

318 319
          extensionComboBox.clear();
          extensionComboBox.addItems(supportedFilters);
320
          extensionDialog.setWindowTitle("Please specify a file extension for " + o_it->name());
321 322 323
          extensionCheckBox.setText(extensionCheckBoxPrefixString + typeName(o_it->dataType()));
          extensionDialog.move(coreWidget_->width()/2 - extensionDialog.width(),
                        coreWidget_->height()/2 - extensionDialog.height());
324

325 326
          if (extensionDialog.exec() && !supportedFilters.isEmpty())
          {
327 328 329
            extension = extensionComboBox.currentText();
            extension = QFileInfo(extension).suffix();
            filename += "." + extension;
330 331 332 333 334
            if (extensionCheckBox.isChecked())
              defaultExtensions[o_it->dataType()] = extension;

          } else
          {
335 336
            emit log(LOGERR, tr("Unabel to save %1. No extension specified.").arg(o_it->name()));
            continue;
337
          }
338 339
        } else
        {
340
          filename += "." + extension;
341 342
        }
      }
343

344

345
      // decide whether to use saveObject or saveObjectTo
346
      if ( !QFile(filename).exists() || !is_askOverwrite )
347 348 349
        saveObject( o_it->id(), filename);
      else
        saveObjectTo(o_it->id(), filename);
350

351 352 353
      // Store saved file's name
      savedFiles.insert(std::pair<int,QString>(o_it->id(),filename));

354
    }
355 356 357
  }


Jan Möbius's avatar
Jan Möbius committed
358 359 360
  // ========================================================================================
  // Finally save all Settings
  // ========================================================================================
361
  if ( complete_name.endsWith("obj") ) {
Jan Möbius's avatar
Jan Möbius committed
362

363
    //write to obj
364
    writeObjFile(complete_name, is_saveAll, is_targetOnly, savedFiles);
Jan Möbius's avatar
Jan Möbius committed
365

366 367 368 369 370 371 372 373 374
  } else {
      // write to ini
      writeIniFile( complete_name,
                    is_saveAll,
                    is_targetOnly,
                    is_saveProgramSettings,
                    is_savePluginSettings,
                    is_saveObjectInfo,
                    savedFiles);
375 376
  }

Jan Möbius's avatar
Jan Möbius committed
377
  // update status
378 379 380
  OpenFlipper::Options::savingSettings(false);

  if ( OpenFlipper::Options::gui() ) {
381
    coreWidget_->statusMessage( tr("Saving Settings to ") + complete_name + tr(" ... Done"), 4000);
382 383 384 385 386
    coreWidget_->setStatus(ApplicationStatus::READY );
  }

  //add to recent files
  if ( OpenFlipper::Options::gui() )
387
    coreWidget_->addRecent( complete_name, DATA_UNKNOWN );
388 389

}