1
2
3 // TnzCore includes
4 #include "tstream.h"
5 #include "tsystem.h"
6
7 // ToonzLib includes
8 #include "toonz/toonzscene.h"
9 #include "toonz/sceneproperties.h"
10 #include "toonz/txshleveltypes.h"
11 #include "toonz/txshsimplelevel.h"
12 #include "toonz/levelproperties.h"
13 #include "toonz/cleanupparameters.h"
14 #include "toonz/tcleanupper.h"
15
16 #include "toonz/tscenehandle.h"
17 #include "toonz/txsheethandle.h"
18 #include "toonz/txshlevelhandle.h"
19 #include "toonz/tcolumnhandle.h"
20 #include "toonz/tframehandle.h"
21 #include "toonz/tpalettehandle.h"
22 #include "toonz/palettecontroller.h"
23 #include "toonz/tproject.h"
24
25 // ToonzQt includes
26 #include "toonzqt/gutil.h"
27 #include "toonzqt/dvdialog.h"
28 #include "toonzqt/tselectionhandle.h"
29
30 // Toonz includes
31 #include "tapp.h"
32 #include "filebrowserpopup.h"
33
34 // Qt includes
35 #include <QMetaType>
36 #include <QApplication>
37
38 #include "cleanupsettingsmodel.h"
39
40 //**********************************************************************
41 // Local classes
42 //**********************************************************************
43
44 namespace {
45
46 //==================================================================
47 // IOSettingsPopup
48 //==================================================================
49
50 class IOSettingsPopup : public FileBrowserPopup {
51 public:
IOSettingsPopup(const QString & title)52 IOSettingsPopup(const QString &title) : FileBrowserPopup(title) {
53 setModal(true);
54 addFilterType("cln");
55 }
56
setPath(const TFilePath & levelPath)57 void setPath(const TFilePath &levelPath) {
58 TFilePath folderPath(levelPath);
59 if (!folderPath.isEmpty())
60 folderPath = folderPath.getParentDir();
61 else {
62 TProject *currentProject =
63 TProjectManager::instance()->getCurrentProject().getPointer();
64 if (currentProject)
65 folderPath =
66 currentProject->decode(currentProject->getFolder(TProject::Inputs));
67 }
68
69 setFolder(folderPath);
70 setFilename(levelPath.withoutParentDir());
71 }
72 };
73
74 //==================================================================
75 // SaveSettingsPopup
76 //==================================================================
77
78 class SaveSettingsPopup final : public IOSettingsPopup {
79 public:
SaveSettingsPopup()80 SaveSettingsPopup() : IOSettingsPopup(QObject::tr("Save Cleanup Settings")) {
81 // addFilterType("tif");
82 // addFilterType("tga");
83 // addFilterType("png");
84
85 setOkText(QObject::tr("Save"));
86 }
87
execute()88 bool execute() override {
89 if (m_selectedPaths.empty()) return false;
90
91 TFilePath savePath(*m_selectedPaths.begin());
92 if (savePath.isEmpty()) return false;
93
94 savePath = savePath.withNoFrame().withType("cln"); // Just to be sure
95 if (TFileStatus(savePath).doesExist()) {
96 int ret = DVGui::MsgBox(
97 QObject::tr("The cleanup settings file for the %1 level already "
98 "exists.\n Do you want to overwrite it?")
99 .arg(toQString(savePath.withoutParentDir())),
100 QObject::tr("Overwrite"), QObject::tr("Don't Overwrite"), 0);
101
102 if (ret == 2) return false;
103 }
104
105 CleanupSettingsModel::instance()->saveSettings(savePath);
106 return true;
107 }
108 };
109
110 //==================================================================
111 // LoadSettingsPopup
112 //==================================================================
113
114 class LoadSettingsPopup final : public IOSettingsPopup {
115 public:
LoadSettingsPopup()116 LoadSettingsPopup() : IOSettingsPopup(QObject::tr("Load Cleanup Settings")) {
117 setOkText(QObject::tr("Load"));
118 }
119
execute()120 bool execute() override {
121 if (m_selectedPaths.empty()) return false;
122
123 const TFilePath &loadPath = *m_selectedPaths.begin();
124 if (loadPath.isEmpty()) return false;
125
126 if (!TSystem::doesExistFileOrLevel(loadPath)) {
127 DVGui::error(QObject::tr("%1 does not exist.").arg(toQString(loadPath)));
128 return false;
129 }
130
131 CleanupSettingsModel::instance()->loadSettings(loadPath);
132 return true;
133 }
134 };
135
136 } // namespace
137
138 //******************************************************************************
139 // CleanupSettingsModel implementation
140 //******************************************************************************
141
CleanupSettingsModel()142 CleanupSettingsModel::CleanupSettingsModel()
143 : m_listenersCount(0)
144 , m_previewersCount(0)
145 , m_cameraTestsCount(0)
146 , m_allowedActions(FULLPROCESS)
147 , m_action(NONE)
148 , m_c(-1)
149 , m_sl(0) {
150 CleanupParameters *currentParams = getCurrentParameters();
151
152 // Don't clone the palette. Palette changes are tracked through
153 // palette handle signals.
154 m_backupParams.assign(currentParams, false);
155
156 TSceneHandle *sceneHandle = TApp::instance()->getCurrentScene();
157
158 bool ret = true;
159 ret = ret &&
160 connect(sceneHandle, SIGNAL(sceneSwitched()), SLOT(onSceneSwitched()));
161 assert(ret);
162
163 onSceneSwitched();
164 }
165
166 //-----------------------------------------------------------------------
167
~CleanupSettingsModel()168 CleanupSettingsModel::~CleanupSettingsModel() {}
169
170 //-----------------------------------------------------------------------
171
instance()172 CleanupSettingsModel *CleanupSettingsModel::instance() {
173 static CleanupSettingsModel theInstance;
174 return &theInstance;
175 }
176
177 //-----------------------------------------------------------------------
178
getCurrentParameters()179 CleanupParameters *CleanupSettingsModel::getCurrentParameters() {
180 ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
181 return scene ? scene->getProperties()->getCleanupParameters() : 0;
182 }
183
184 //-----------------------------------------------------------------------
185
getCleanupFrame(TXshSimpleLevel * & sl,TFrameId & fid)186 void CleanupSettingsModel::getCleanupFrame(TXshSimpleLevel *&sl,
187 TFrameId &fid) {
188 TApp *app = TApp::instance();
189
190 int r = app->getCurrentFrame()->getFrame();
191 int c = app->getCurrentColumn()->getColumnIndex();
192
193 TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
194 assert(xsh);
195
196 const TXshCell &cell = xsh->getCell(r, c);
197
198 fid = cell.getFrameId();
199 sl = cell.isEmpty() ? 0 : cell.getSimpleLevel();
200 }
201
202 //-----------------------------------------------------------------------
203
attach(int objectFlag,bool doPreview)204 void CleanupSettingsModel::attach(int objectFlag, bool doPreview) {
205 if ((objectFlag & LISTENER) && (m_listenersCount++ <= 0)) connectSignals();
206
207 bool doRebuild = false;
208
209 if ((objectFlag & PREVIEWER) && (m_previewersCount++ <= 0)) doRebuild = true;
210
211 if ((objectFlag & CAMERATEST) && (m_cameraTestsCount++ <= 0))
212 doRebuild = true;
213
214 if (doRebuild && doPreview) rebuildPreview();
215 }
216
217 //-----------------------------------------------------------------------
218
detach(int objectFlag)219 void CleanupSettingsModel::detach(int objectFlag) {
220 if ((objectFlag & LISTENER) && (--m_listenersCount <= 0)) disconnectSignals();
221
222 if ((objectFlag & PREVIEWER) && (--m_previewersCount <= 0)) {
223 m_previewTransformed = TRasterImageP();
224 m_transform = TAffine();
225 }
226
227 if ((objectFlag & CAMERATEST) && (--m_cameraTestsCount <= 0))
228 m_cameraTestTransformed = TRasterImageP();
229
230 assert(m_listenersCount >= 0);
231 assert(m_previewersCount >= 0);
232 assert(m_cameraTestsCount >= 0);
233 }
234
235 //-----------------------------------------------------------------------
236
connectSignals()237 void CleanupSettingsModel::connectSignals() {
238 TApp *app = TApp::instance();
239
240 TFrameHandle *frameHandle = app->getCurrentFrame();
241 TColumnHandle *columnHandle = app->getCurrentColumn();
242 TPaletteHandle *paletteHandle =
243 app->getPaletteController()->getCurrentCleanupPalette();
244
245 // The following are queued. This is best to prevent double-updates and
246 // selection issues with cln cancels.
247 bool ret = true;
248
249 ret = ret && connect(frameHandle, SIGNAL(frameSwitched()),
250 SLOT(onCellChanged()), Qt::QueuedConnection);
251 ret = ret && connect(columnHandle, SIGNAL(columnIndexSwitched()),
252 SLOT(onCellChanged()), Qt::QueuedConnection);
253 ret = ret && connect(paletteHandle, SIGNAL(colorStyleChanged(bool)),
254 SLOT(onPaletteChanged()), Qt::QueuedConnection);
255 ret = ret && connect(paletteHandle, SIGNAL(paletteChanged()),
256 SLOT(onPaletteChanged()), Qt::QueuedConnection);
257
258 assert(ret);
259
260 QMetaObject::invokeMethod(this, "onCellChanged", Qt::QueuedConnection);
261 }
262
263 //-----------------------------------------------------------------------
264
disconnectSignals()265 void CleanupSettingsModel::disconnectSignals() {
266 TApp *app = TApp::instance();
267
268 TFrameHandle *frameHandle = app->getCurrentFrame();
269 TColumnHandle *columnHandle = app->getCurrentColumn();
270 TPaletteHandle *paletteHandle =
271 app->getPaletteController()->getCurrentCleanupPalette();
272
273 bool ret = true;
274
275 ret = ret && frameHandle->disconnect(this);
276 ret = ret && columnHandle->disconnect(this);
277 ret = ret && paletteHandle->disconnect(this);
278
279 assert(ret);
280 }
281
282 //-----------------------------------------------------------------------
283
setCommitMask(CommitMask allowedProcessing)284 void CleanupSettingsModel::setCommitMask(CommitMask allowedProcessing) {
285 m_allowedActions = allowedProcessing;
286 commitChanges();
287 }
288
289 //-----------------------------------------------------------------------
290
commitChanges()291 void CleanupSettingsModel::commitChanges() {
292 CleanupParameters *currentParams = getCurrentParameters();
293
294 int action = NONE;
295
296 // Analyze param changes
297 {
298 // Check for simple changes
299 if (currentParams->m_path != m_backupParams.m_path) action = INTERFACE;
300
301 // Check post-processing-related changes
302 if (currentParams->m_transparencyCheckEnabled !=
303 m_backupParams.m_transparencyCheckEnabled ||
304 currentParams->m_noAntialias != m_backupParams.m_noAntialias ||
305 currentParams->m_postAntialias != m_backupParams.m_postAntialias ||
306 currentParams->m_despeckling != m_backupParams.m_despeckling ||
307 currentParams->m_aaValue != m_backupParams.m_aaValue)
308
309 action = POSTPROCESS;
310
311 // Check for full preview rebuilds
312 if (currentParams->m_lineProcessingMode !=
313 m_backupParams.m_lineProcessingMode ||
314 currentParams->m_autocenterType != m_backupParams.m_autocenterType ||
315 currentParams->m_autoAdjustMode != m_backupParams.m_autoAdjustMode ||
316 currentParams->m_camera.getRes() != m_backupParams.m_camera.getRes() ||
317 currentParams->m_camera.getSize() !=
318 m_backupParams.m_camera.getSize() ||
319 currentParams->m_rotate != m_backupParams.m_rotate ||
320 currentParams->m_flipx != m_backupParams.m_flipx ||
321 currentParams->m_flipy != m_backupParams.m_flipy ||
322 currentParams->m_offx != m_backupParams.m_offx ||
323 currentParams->m_offy != m_backupParams.m_offy ||
324 currentParams->m_sharpness != m_backupParams.m_sharpness ||
325 currentParams->m_closestField != m_backupParams.m_closestField)
326
327 action = FULLPROCESS;
328
329 if (currentParams->m_autocenterType != CleanupTypes::AUTOCENTER_NONE) {
330 // Check Autocenter changes
331 if (!(currentParams->getFdgInfo() == m_backupParams.getFdgInfo()) ||
332 currentParams->m_pegSide != m_backupParams.m_pegSide)
333
334 action = FULLPROCESS;
335 }
336 }
337
338 commitChanges(action);
339 }
340
341 //-----------------------------------------------------------------------
342
commitChanges(int action)343 void CleanupSettingsModel::commitChanges(int action) {
344 CleanupParameters *currentParams = getCurrentParameters();
345
346 if (action > NONE) {
347 m_backupParams.assign(currentParams, false);
348
349 currentParams->setDirtyFlag(true);
350
351 // Deal with scene stuff
352 if (m_clnPath.isEmpty()) {
353 TApp::instance()->getCurrentScene()->setDirtyFlag(
354 true); // This should be moved outside... sadly not supported at the
355 // moment...
356 CleanupParameters::GlobalParameters.assign(
357 currentParams); // The global settings are being changed
358 }
359 }
360
361 // Perform actions
362 int maxAction =
363 std::max(action, m_action); // Add previuosly required actions
364 action = std::min(maxAction,
365 m_allowedActions); // But only up to the allowed action
366 m_action = (action == maxAction)
367 ? NONE
368 : maxAction; // Then, update the previously required action
369
370 if (action >= FULLPROCESS) rebuildPreview();
371
372 if (action >= INTERFACE) emit modelChanged(action == POSTPROCESS);
373 }
374
375 //-----------------------------------------------------------------------
376
rebuildPreview()377 void CleanupSettingsModel::rebuildPreview() {
378 // If no previewer is active, do nothing
379 if (m_previewersCount <= 0 && m_cameraTestsCount <= 0) return;
380
381 // Reset data
382 m_original = m_previewTransformed = m_cameraTestTransformed = TRasterImageP();
383 m_transform = TAffine();
384
385 // Retrieve frame to cleanup
386 TXshSimpleLevel *sl;
387 TFrameId fid;
388 getCleanupFrame(sl, fid);
389
390 if (sl) {
391 // Inform that we're beginning a long computation
392 QApplication::setOverrideCursor(Qt::WaitCursor);
393
394 // Perform the preview
395 processFrame(sl, fid);
396
397 QApplication::restoreOverrideCursor();
398 }
399
400 emit previewDataChanged();
401 }
402
403 //-----------------------------------------------------------------------
404
processFrame(TXshSimpleLevel * sl,TFrameId fid)405 void CleanupSettingsModel::processFrame(TXshSimpleLevel *sl, TFrameId fid) {
406 assert(sl);
407
408 TRasterImageP imageToCleanup = sl->getFrameToCleanup(fid);
409 if (!imageToCleanup) return;
410
411 // Store the original image
412 m_original = imageToCleanup;
413
414 // Retrieve cleanup params
415 CleanupParameters *params = getCurrentParameters();
416 TCleanupper *cl = TCleanupper::instance();
417
418 bool doProcessing =
419 (params->m_lineProcessingMode != lpNone) && (m_previewersCount > 0);
420 bool doCameraTest = (m_cameraTestsCount > 0);
421
422 // Retrieve new image dpi
423 TPointD dpi;
424 imageToCleanup->getDpi(dpi.x, dpi.y);
425 if (dpi.x == 0 && dpi.y == 0) dpi = sl->getProperties()->getDpi();
426 cl->setSourceDpi(dpi);
427
428 // Perform primary cleanup processing
429 if (doProcessing) {
430 // Warning: the process() call below will put imageToCleanup = 0.
431 CleanupPreprocessedImage *cpi =
432 cl->process(imageToCleanup, true, m_previewTransformed, false, true,
433 true, &m_transform);
434 delete cpi;
435 }
436
437 // Perform camera test processing
438 if (doCameraTest) {
439 m_cameraTestTransformed = m_original;
440 if (params->m_autocenterType != CleanupTypes::AUTOCENTER_NONE ||
441 params->m_rotate != 0 || params->m_flipx || params->m_flipy) {
442 bool autocentered;
443 m_cameraTestTransformed =
444 cl->autocenterOnly(m_original.getPointer(), true, autocentered);
445
446 if (params->m_autocenterType != CleanupTypes::AUTOCENTER_NONE &&
447 !autocentered)
448 DVGui::warning(
449 QObject::tr("The autocentering failed on the current drawing."));
450 }
451 }
452 }
453
454 //-----------------------------------------------------------------------
455
onSceneSwitched()456 void CleanupSettingsModel::onSceneSwitched() {
457 // When the scene switches, current parameters are reverted the scene's
458 // originals.
459 // So, since we store originals in CleanupParameters::GlobalParameters, we
460 // copy them there.
461 CleanupParameters *params = getCurrentParameters();
462 CleanupParameters::GlobalParameters.assign(params);
463
464 // The cleanupper always uses current cleanup parameters. It has to be
465 // specified somewhere,
466 // so let's do it once here.
467 TCleanupper::instance()->setParameters(params);
468
469 // Finally, send notifications, deal with backups, etc.
470 restoreGlobalSettings();
471 }
472
473 //-----------------------------------------------------------------------
474
onCellChanged()475 void CleanupSettingsModel::onCellChanged() {
476 // Process events. This slot wants to be invoked when no other slot/event
477 // is pending. This is best since current selection may change inside.
478 QCoreApplication::processEvents();
479
480 TApp *app = TApp::instance();
481
482 // Update xsheet position
483 int oldC = m_c;
484 m_c = app->getCurrentColumn()->getColumnIndex();
485
486 // Retrieve new cleanup image reference (not updated yet)
487 TXshSimpleLevel *sl;
488 TFrameId fid;
489
490 /*---
491 * カラムを上から走査して、最初にLevelの入っているセルのLevelパスを取ってくる
492 * ---*/
493 TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
494 if (xsh->getFrameCount() == 0) return;
495
496 for (int f = 0; f < xsh->getFrameCount(); f++) {
497 TXshCell cell = xsh->getCell(f, m_c);
498 sl = cell.getSimpleLevel();
499 if (sl) {
500 fid = cell.getFrameId();
501 break;
502 }
503 }
504
505 // Deal with cln switches
506 bool rebuiltPreview = false;
507
508 if (sl != m_sl) {
509 // Build new cln path
510 const TFilePath &clnPath = getClnPath(sl);
511
512 // If there is a switch in cln paths
513 if (m_clnPath != clnPath) {
514 // In case, save the old cln
515 if (!m_clnPath.isEmpty() && TFileStatus(m_clnPath).doesExist()) {
516 if (!saveSettingsIfNeeded()) {
517 // Unselect current selection, and return to the old cell
518 app->getCurrentSelection()->setSelection(0);
519 app->getCurrentColumn()->setColumnIndex(oldC);
520 m_c = oldC;
521 return;
522 }
523 }
524
525 // Load the new cleanup settings, if any
526 if (loadSettings(
527 clnPath)) // modelChanged() emitted here, plust preview rebuild
528 {
529 m_clnPath = clnPath;
530 rebuiltPreview = true;
531 } else if (!m_clnPath.isEmpty()) {
532 // Otherwise, in case there was an old cln, reload global settings
533 restoreGlobalSettings(); // modelChanged() emitted here
534 rebuiltPreview = true;
535 }
536 }
537 }
538
539 m_sl = sl, m_fid = fid;
540
541 if ((m_previewersCount > 0 || m_cameraTestsCount > 0) && !rebuiltPreview)
542 rebuildPreview();
543
544 emit imageSwitched();
545 }
546
547 //-----------------------------------------------------------------------
548
onPaletteChanged()549 void CleanupSettingsModel::onPaletteChanged() { commitChanges(POSTPROCESS); }
550
551 //-----------------------------------------------------------------------
552
saveSettingsIfNeeded()553 bool CleanupSettingsModel::saveSettingsIfNeeded() {
554 CleanupParameters *params = getCurrentParameters();
555
556 if (params->getDirtyFlag() && !m_clnPath.isEmpty() &&
557 TFileStatus(m_clnPath).doesExist()) {
558 QString question(
559 QObject::tr("The cleanup settings for the current level have been "
560 "modified...\n\nDo you want to save your changes?"));
561
562 int ret = DVGui::MsgBox(question, QObject::tr("Save"),
563 QObject::tr("Discard"), QObject::tr("Cancel"), 0);
564 if (ret == 1) {
565 // WARNING: This is legacy behavior, but is it really needed? I think
566 // there should be no further
567 // request of user interaction - why invoking the popup to choose the save
568 // path?
569 promptSave();
570 } else if (ret == 3)
571 return false;
572 }
573
574 return true;
575 }
576
577 //-----------------------------------------------------------------------------
578
restoreGlobalSettings()579 void CleanupSettingsModel::restoreGlobalSettings() {
580 CleanupParameters *currentParams = getCurrentParameters();
581 currentParams->assign(&CleanupParameters::GlobalParameters);
582
583 // Make sure that the current cleanup palette is set to currentParams' palette
584 TApp::instance()
585 ->getPaletteController()
586 ->getCurrentCleanupPalette()
587 ->setPalette(currentParams->m_cleanupPalette.getPointer());
588
589 m_clnPath = TFilePath();
590 m_backupParams.assign(currentParams, false);
591
592 if (m_previewersCount > 0 || m_cameraTestsCount > 0) rebuildPreview();
593
594 emit modelChanged(false);
595 emit clnLoaded();
596 }
597
598 //-----------------------------------------------------------------------------
599
saveSettings(CleanupParameters * params,const TFilePath & clnPath)600 void CleanupSettingsModel::saveSettings(CleanupParameters *params,
601 const TFilePath &clnPath) {
602 if (clnPath.isEmpty() || !params) return;
603
604 TOStream os(clnPath);
605
606 os.openChild("version");
607 os << 1 << 19;
608 os.closeChild();
609
610 params->saveData(os);
611 params->setDirtyFlag(false);
612 }
613
614 //-----------------------------------------------------------------------------
615
saveSettings(const TFilePath & clnPath)616 void CleanupSettingsModel::saveSettings(const TFilePath &clnPath) {
617 saveSettings(getCurrentParameters(), clnPath);
618
619 // Saving current settings should put the model in the same situation we
620 // have after a model is loaded (ie see loadSettings(clnPath))
621 m_clnPath = clnPath;
622
623 emit clnLoaded();
624 }
625
626 //-----------------------------------------------------------------------------
627
loadSettings(CleanupParameters * params,const TFilePath & clnPath)628 bool CleanupSettingsModel::loadSettings(CleanupParameters *params,
629 const TFilePath &clnPath) {
630 assert(params);
631 if (clnPath.isEmpty() || !TSystem::doesExistFileOrLevel(clnPath))
632 return false;
633
634 TIStream *is = new TIStream(clnPath);
635
636 CleanupParameters defaultParameters;
637 params->assign(&defaultParameters);
638
639 std::string tagName;
640 is->matchTag(tagName);
641 if (tagName == "version") {
642 int minor, major;
643 *is >> major >> minor;
644
645 is->matchEndTag();
646 is->setVersion(VersionNumber(major, minor));
647 } else {
648 delete is;
649 is = new TIStream(clnPath);
650 }
651
652 params->loadData(*is, false);
653 delete is;
654
655 return true;
656 }
657
658 //-----------------------------------------------------------------------------
659
loadSettings(const TFilePath & clnPath)660 bool CleanupSettingsModel::loadSettings(const TFilePath &clnPath) {
661 CleanupParameters *cp = getCurrentParameters();
662 if (!loadSettings(cp, clnPath)) return false;
663
664 // The same as restoreGlobalSettings()
665 TApp::instance()
666 ->getPaletteController()
667 ->getCurrentCleanupPalette()
668 ->setPalette(cp->m_cleanupPalette.getPointer());
669
670 /*---
671 * LoadSettingsPopupからこの関数が呼ばれたとき、ロードしたパラメータをGlobal設定に格納する---*/
672 if (m_clnPath.isEmpty()) {
673 TApp::instance()->getCurrentScene()->setDirtyFlag(
674 true); // This should be moved outside... sadly not supported at the
675 // moment...
676 CleanupParameters::GlobalParameters.assign(
677 cp); // The global settings are being changed
678 }
679
680 m_backupParams.assign(cp, false);
681
682 if (m_previewersCount > 0 || m_cameraTestsCount > 0) rebuildPreview();
683
684 emit modelChanged(false);
685 emit clnLoaded();
686
687 return true;
688 }
689
690 //-----------------------------------------------------------------------------
691
promptSave()692 void CleanupSettingsModel::promptSave() {
693 static SaveSettingsPopup *savePopup = 0;
694 if (!savePopup) savePopup = new SaveSettingsPopup;
695
696 savePopup->setPath(getClnPath(m_sl));
697 savePopup->exec();
698 }
699
700 //-----------------------------------------------------------------------------
701
promptLoad()702 void CleanupSettingsModel::promptLoad() {
703 static LoadSettingsPopup *loadPopup = 0;
704 if (!loadPopup) loadPopup = new LoadSettingsPopup;
705
706 loadPopup->setPath(getClnPath(m_sl));
707 loadPopup->exec();
708 }
709
710 //-----------------------------------------------------------------------------
711
getClnPath(TXshSimpleLevel * sl)712 TFilePath CleanupSettingsModel::getClnPath(TXshSimpleLevel *sl) {
713 if (!sl) return TFilePath();
714
715 TFilePath clnPath(sl->getScannedPath());
716 if (clnPath == TFilePath()) clnPath = sl->getPath();
717
718 ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
719 return scene->decodeFilePath(clnPath).withNoFrame().withType("cln");
720 }
721
722 //-----------------------------------------------------------------------------
723
getInputPath(TXshSimpleLevel * sl)724 TFilePath CleanupSettingsModel::getInputPath(TXshSimpleLevel *sl) {
725 const TFilePath &scannedPath = sl->getScannedPath();
726 return scannedPath.isEmpty() ? sl->getPath() : scannedPath;
727 }
728
729 //-----------------------------------------------------------------------------
730
getOutputPath(TXshSimpleLevel * sl,const CleanupParameters * params)731 TFilePath CleanupSettingsModel::getOutputPath(TXshSimpleLevel *sl,
732 const CleanupParameters *params) {
733 const TFilePath &inPath = getInputPath(sl); // Used just to get level name
734
735 if (inPath.isEmpty() || !params) return TFilePath();
736
737 bool lineProcessing = (params->m_lineProcessingMode != lpNone);
738 ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
739
740 // Check if the cleaned up level already exists
741 const TFilePath &outDir = params->getPath(scene);
742
743 return lineProcessing ? (outDir + inPath.getWideName()).withType("tlv")
744 : (outDir + inPath.getLevelNameW()).withType("tif");
745 }
746