1 /*
2  * Copyright (c) 2013-2020 Meltytech, LLC
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "settings.h"
19 #include <QLocale>
20 #include <QStandardPaths>
21 #include <QFile>
22 #include <QDir>
23 #include <Logger.h>
24 
25 static const QString APP_DATA_DIR_KEY("appdatadir");
26 static const QString SHOTCUT_INI_FILENAME("/shotcut.ini");
27 static QScopedPointer<ShotcutSettings> instance;
28 static QString appDataForSession;
29 static const int kMaximumTrackHeight = 125;
30 
singleton()31 ShotcutSettings &ShotcutSettings::singleton()
32 {
33     if (!instance) {
34         if (appDataForSession.isEmpty()) {
35             instance.reset(new ShotcutSettings);
36             if (instance->settings.value(APP_DATA_DIR_KEY).isValid()
37                 && QFile::exists(instance->settings.value(APP_DATA_DIR_KEY).toString() + SHOTCUT_INI_FILENAME) )
38                 instance.reset(new ShotcutSettings(instance->settings.value(APP_DATA_DIR_KEY).toString()));
39         } else {
40             instance.reset(new ShotcutSettings(appDataForSession));
41         }
42     }
43     return *instance;
44 }
45 
ShotcutSettings(const QString & appDataLocation)46 ShotcutSettings::ShotcutSettings(const QString& appDataLocation)
47     : QObject()
48     , settings(appDataLocation + SHOTCUT_INI_FILENAME, QSettings::IniFormat)
49     , m_appDataLocation(appDataLocation)
50 {
51 }
52 
log()53 void ShotcutSettings::log()
54 {
55     LOG_DEBUG() << "language" << language();
56     LOG_DEBUG() << "deinterlacer" << playerDeinterlacer();
57     LOG_DEBUG() << "external monitor" << playerExternal();
58     LOG_DEBUG() << "GPU processing" << playerGPU();
59     LOG_DEBUG() << "interpolation" << playerInterpolation();
60     LOG_DEBUG() << "video mode" << playerProfile();
61     LOG_DEBUG() << "realtime" << playerRealtime();
62     LOG_DEBUG() << "audio channels" << playerAudioChannels();
63 #ifdef Q_OS_WIN
64     LOG_DEBUG() << "display method" << drawMethod();
65 #endif
66 }
67 
language() const68 QString ShotcutSettings::language() const
69 {
70     QString language = settings.value("language", QLocale().name()).toString();
71     if (language == "en")
72         language = "en_US";
73     return language;
74 }
75 
setLanguage(const QString & s)76 void ShotcutSettings::setLanguage(const QString& s)
77 {
78     settings.setValue("language", s);
79 }
80 
imageDuration() const81 double ShotcutSettings::imageDuration() const
82 {
83     return settings.value("imageDuration", 4.0).toDouble();
84 }
85 
setImageDuration(double d)86 void ShotcutSettings::setImageDuration(double d)
87 {
88     settings.setValue("imageDuration", d);
89 }
90 
openPath() const91 QString ShotcutSettings::openPath() const
92 {
93     return settings.value("openPath", QStandardPaths::standardLocations(QStandardPaths::MoviesLocation)).toString();
94 }
95 
setOpenPath(const QString & s)96 void ShotcutSettings::setOpenPath(const QString& s)
97 {
98     settings.setValue("openPath", s);
99     emit savePathChanged();
100 }
101 
savePath() const102 QString ShotcutSettings::savePath() const
103 {
104     return settings.value("savePath", QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation)).toString();
105 }
106 
setSavePath(const QString & s)107 void ShotcutSettings::setSavePath(const QString& s)
108 {
109     settings.setValue("savePath", s);
110     emit savePathChanged();
111 }
112 
recent() const113 QStringList ShotcutSettings::recent() const
114 {
115     return settings.value("recent").toStringList();
116 }
117 
setRecent(const QStringList & ls)118 void ShotcutSettings::setRecent(const QStringList& ls)
119 {
120     if (ls.isEmpty())
121         settings.remove("recent");
122     else if (!clearRecent())
123         settings.setValue("recent", ls);
124 }
125 
theme() const126 QString ShotcutSettings::theme() const
127 {
128     return settings.value("theme", "dark").toString();
129 }
130 
setTheme(const QString & s)131 void ShotcutSettings::setTheme(const QString& s)
132 {
133     settings.setValue("theme", s);
134 }
135 
showTitleBars() const136 bool ShotcutSettings::showTitleBars() const
137 {
138     return settings.value("titleBars", true).toBool();
139 }
140 
setShowTitleBars(bool b)141 void ShotcutSettings::setShowTitleBars(bool b)
142 {
143     settings.setValue("titleBars", b);
144 }
145 
showToolBar() const146 bool ShotcutSettings::showToolBar() const
147 {
148     return settings.value("toolBar", true).toBool();
149 }
150 
setShowToolBar(bool b)151 void ShotcutSettings::setShowToolBar(bool b)
152 {
153     settings.setValue("toolBar", b);
154 }
155 
textUnderIcons() const156 bool ShotcutSettings::textUnderIcons() const
157 {
158     return settings.value("textUnderIcons", true).toBool();
159 }
160 
setTextUnderIcons(bool b)161 void ShotcutSettings::setTextUnderIcons(bool b)
162 {
163     settings.setValue("textUnderIcons", b);
164 }
165 
smallIcons() const166 bool ShotcutSettings::smallIcons() const
167 {
168     return settings.value("smallIcons", false).toBool();
169 }
170 
setSmallIcons(bool b)171 void ShotcutSettings::setSmallIcons(bool b)
172 {
173     settings.setValue("smallIcons", b);
174     emit smallIconsChanged();
175 }
176 
windowGeometry() const177 QByteArray ShotcutSettings::windowGeometry() const
178 {
179     return settings.value("geometry").toByteArray();
180 }
181 
setWindowGeometry(const QByteArray & a)182 void ShotcutSettings::setWindowGeometry(const QByteArray& a)
183 {
184     settings.setValue("geometry", a);
185 }
186 
windowGeometryDefault() const187 QByteArray ShotcutSettings::windowGeometryDefault() const
188 {
189     return settings.value("geometryDefault").toByteArray();
190 }
191 
setWindowGeometryDefault(const QByteArray & a)192 void ShotcutSettings::setWindowGeometryDefault(const QByteArray& a)
193 {
194     settings.setValue("geometryDefault", a);
195 }
196 
windowState() const197 QByteArray ShotcutSettings::windowState() const
198 {
199     return settings.value("windowState").toByteArray();
200 }
201 
setWindowState(const QByteArray & a)202 void ShotcutSettings::setWindowState(const QByteArray& a)
203 {
204     settings.setValue("windowState", a);
205 }
206 
windowStateDefault() const207 QByteArray ShotcutSettings::windowStateDefault() const
208 {
209     return settings.value("windowStateDefault").toByteArray();
210 }
211 
setWindowStateDefault(const QByteArray & a)212 void ShotcutSettings::setWindowStateDefault(const QByteArray& a)
213 {
214     settings.setValue("windowStateDefault", a);
215 }
216 
viewMode() const217 QString ShotcutSettings::viewMode() const
218 {
219     return settings.value("playlist/viewMode").toString();
220 }
221 
setViewMode(const QString & viewMode)222 void ShotcutSettings::setViewMode(const QString& viewMode)
223 {
224     settings.setValue("playlist/viewMode", viewMode);
225     emit viewModeChanged();
226 }
227 
encodePath() const228 QString ShotcutSettings::encodePath() const
229 {
230     return settings.value("encode/path", QStandardPaths::standardLocations(QStandardPaths::MoviesLocation)).toString();
231 }
232 
setEncodePath(const QString & s)233 void ShotcutSettings::setEncodePath(const QString& s)
234 {
235     settings.setValue("encode/path", s);
236 }
237 
encodeFreeSpaceCheck() const238 bool ShotcutSettings::encodeFreeSpaceCheck() const
239 {
240     return settings.value("encode/freeSpaceCheck", true).toBool();
241 }
242 
setEncodeFreeSpaceCheck(bool b)243 void ShotcutSettings::setEncodeFreeSpaceCheck(bool b)
244 {
245     settings.setValue("encode/freeSpaceCheck", b);
246 }
247 
encodeUseHardware() const248 bool ShotcutSettings::encodeUseHardware() const
249 {
250     return settings.value("encode/useHardware").toBool();
251 }
252 
setEncodeUseHardware(bool b)253 void ShotcutSettings::setEncodeUseHardware(bool b)
254 {
255     settings.setValue("encode/useHardware", b);
256 }
257 
encodeHardware() const258 QStringList ShotcutSettings::encodeHardware() const
259 {
260     return settings.value("encode/hardware").toStringList();
261 }
262 
setEncodeHardware(const QStringList & ls)263 void ShotcutSettings::setEncodeHardware(const QStringList& ls)
264 {
265     if (ls.isEmpty())
266         settings.remove("encode/hardware");
267     else
268         settings.setValue("encode/hardware", ls);
269 }
270 
encodeAdvanced() const271 bool ShotcutSettings::encodeAdvanced() const
272 {
273     return settings.value("encode/advanced", false).toBool();
274 }
275 
setEncodeAdvanced(bool b)276 void ShotcutSettings::setEncodeAdvanced(bool b)
277 {
278     settings.setValue("encode/advanced", b);
279 }
280 
showConvertClipDialog() const281 bool ShotcutSettings::showConvertClipDialog() const
282 {
283     return settings.value("showConvertClipDialog", true).toBool();
284 }
285 
setShowConvertClipDialog(bool b)286 void ShotcutSettings::setShowConvertClipDialog(bool b)
287 {
288     settings.setValue("showConvertClipDialog", b);
289 }
290 
encodeParallelProcessing() const291 bool ShotcutSettings::encodeParallelProcessing() const
292 {
293     return settings.value("encode/parallelProcessing", false).toBool();
294 }
295 
setEncodeParallelProcessing(bool b)296 void ShotcutSettings::setEncodeParallelProcessing(bool b)
297 {
298     settings.setValue("encode/parallelProcessing", b);
299 }
300 
playerAudioChannels() const301 int ShotcutSettings::playerAudioChannels() const
302 {
303     return settings.value("player/audioChannels", 2).toInt();
304 }
305 
setPlayerAudioChannels(int i)306 void ShotcutSettings::setPlayerAudioChannels(int i)
307 {
308     settings.setValue("player/audioChannels", i);
309     emit playerAudioChannelsChanged(i);
310 }
311 
playerDeinterlacer() const312 QString ShotcutSettings::playerDeinterlacer() const
313 {
314     QString result = settings.value("player/deinterlacer", "onefield").toString();
315     //XXX workaround yadif crashing with mlt_transition
316     if (result == "yadif" || result == "yadif-nospatial")
317         result = "onefield";
318     return result;
319 }
320 
setPlayerDeinterlacer(const QString & s)321 void ShotcutSettings::setPlayerDeinterlacer(const QString& s)
322 {
323     settings.setValue("player/deinterlacer", s);
324 }
325 
playerExternal() const326 QString ShotcutSettings::playerExternal() const
327 {
328     auto result = settings.value("player/external", "").toString();
329     // "sdi" is no longer supported DVEO VidPort
330     return result == "sdi"? "" : result;
331 }
332 
setPlayerExternal(const QString & s)333 void ShotcutSettings::setPlayerExternal(const QString& s)
334 {
335     settings.setValue("player/external", s);
336 }
337 
playerGamma() const338 QString ShotcutSettings::playerGamma() const
339 {
340     return settings.value("player/gamma", "bt709").toString();
341 }
342 
setPlayerGamma(const QString & s)343 void ShotcutSettings::setPlayerGamma(const QString& s)
344 {
345     settings.setValue("player/gamma", s);
346 }
347 
setPlayerGPU(bool b)348 void ShotcutSettings::setPlayerGPU(bool b)
349 {
350     settings.setValue("player/gpu", b);
351     emit playerGpuChanged();
352 }
353 
playerJACK() const354 bool ShotcutSettings::playerJACK() const
355 {
356     return settings.value("player/jack", false).toBool();
357 }
358 
playerInterpolation() const359 QString ShotcutSettings::playerInterpolation() const
360 {
361     return settings.value("player/interpolation", "bilinear").toString();
362 }
363 
setPlayerInterpolation(const QString & s)364 void ShotcutSettings::setPlayerInterpolation(const QString& s)
365 {
366     settings.setValue("player/interpolation", s);
367 }
368 
playerGPU() const369 bool ShotcutSettings::playerGPU() const
370 {
371     return settings.value("player/gpu", false).toBool();
372 }
373 
playerWarnGPU() const374 bool ShotcutSettings::playerWarnGPU() const
375 {
376     return settings.value("player/warnGPU", false).toBool();
377 }
378 
setPlayerJACK(bool b)379 void ShotcutSettings::setPlayerJACK(bool b)
380 {
381     settings.setValue("player/jack", b);
382 }
383 
playerKeyerMode() const384 int ShotcutSettings::playerKeyerMode() const
385 {
386     return settings.value("player/keyer", 0).toInt();
387 }
388 
setPlayerKeyerMode(int i)389 void ShotcutSettings::setPlayerKeyerMode(int i)
390 {
391     settings.setValue("player/keyer", i);
392 }
393 
playerMuted() const394 bool ShotcutSettings::playerMuted() const
395 {
396     return settings.value("player/muted", false).toBool();
397 }
398 
setPlayerMuted(bool b)399 void ShotcutSettings::setPlayerMuted(bool b)
400 {
401     settings.setValue("player/muted", b);
402 }
403 
playerProfile() const404 QString ShotcutSettings::playerProfile() const
405 {
406     return settings.value("player/profile", "").toString();
407 }
408 
setPlayerProfile(const QString & s)409 void ShotcutSettings::setPlayerProfile(const QString& s)
410 {
411     settings.setValue("player/profile", s);
412 }
413 
playerProgressive() const414 bool ShotcutSettings::playerProgressive() const
415 {
416     return settings.value("player/progressive", true).toBool();
417 }
418 
setPlayerProgressive(bool b)419 void ShotcutSettings::setPlayerProgressive(bool b)
420 {
421     settings.setValue("player/progressive", b);
422 }
423 
playerRealtime() const424 bool ShotcutSettings::playerRealtime() const
425 {
426     return settings.value("player/realtime", true).toBool();
427 }
428 
setPlayerRealtime(bool b)429 void ShotcutSettings::setPlayerRealtime(bool b)
430 {
431     settings.setValue("player/realtime", b);
432 }
433 
playerScrubAudio() const434 bool ShotcutSettings::playerScrubAudio() const
435 {
436     return settings.value("player/scrubAudio", true).toBool();
437 }
438 
setPlayerScrubAudio(bool b)439 void ShotcutSettings::setPlayerScrubAudio(bool b)
440 {
441     settings.setValue("player/scrubAudio", b);
442 }
443 
playerVolume() const444 int ShotcutSettings::playerVolume() const
445 {
446     return settings.value("player/volume", 88).toInt();
447 }
448 
setPlayerVolume(int i)449 void ShotcutSettings::setPlayerVolume(int i)
450 {
451     settings.setValue("player/volume", i);
452 }
453 
playerZoom() const454 float ShotcutSettings::playerZoom() const
455 {
456     return settings.value("player/zoom", 0.0f).toFloat();
457 }
458 
setPlayerZoom(float f)459 void ShotcutSettings::setPlayerZoom(float f)
460 {
461     settings.setValue("player/zoom", f);
462 }
463 
playerPreviewScale() const464 int ShotcutSettings::playerPreviewScale() const
465 {
466     return settings.value("player/previewScale", 0).toInt();
467 }
468 
setPlayerPreviewScale(int i)469 void ShotcutSettings::setPlayerPreviewScale(int i)
470 {
471     settings.setValue("player/previewScale", i);
472 }
473 
playerVideoDelayMs() const474 int ShotcutSettings::playerVideoDelayMs() const
475 {
476     return settings.value("player/videoDelayMs", 0).toInt();
477 }
478 
setPlayerVideoDelayMs(int i)479 void ShotcutSettings::setPlayerVideoDelayMs(int i)
480 {
481     settings.setValue("player/videoDelayMs", i);
482 }
483 
playlistThumbnails() const484 QString ShotcutSettings::playlistThumbnails() const
485 {
486     return settings.value("playlist/thumbnails", "small").toString();
487 }
488 
setPlaylistThumbnails(const QString & s)489 void ShotcutSettings::setPlaylistThumbnails(const QString& s)
490 {
491     settings.setValue("playlist/thumbnails", s);
492     emit playlistThumbnailsChanged();
493 }
494 
playlistAutoplay() const495 bool ShotcutSettings::playlistAutoplay() const
496 {
497     return settings.value("playlist/autoplay", true).toBool();
498 }
499 
setPlaylistAutoplay(bool b)500 void ShotcutSettings::setPlaylistAutoplay(bool b)
501 {
502     settings.setValue("playlist/autoplay", b);
503 }
504 
timelineDragScrub() const505 bool ShotcutSettings::timelineDragScrub() const
506 {
507     return settings.value("timeline/dragScrub", false).toBool();
508 }
509 
setTimelineDragScrub(bool b)510 void ShotcutSettings::setTimelineDragScrub(bool b)
511 {
512     settings.setValue("timeline/dragScrub", b);
513     emit timelineDragScrubChanged();
514 }
515 
timelineShowWaveforms() const516 bool ShotcutSettings::timelineShowWaveforms() const
517 {
518     return settings.value("timeline/waveforms", true).toBool();
519 }
520 
setTimelineShowWaveforms(bool b)521 void ShotcutSettings::setTimelineShowWaveforms(bool b)
522 {
523     settings.setValue("timeline/waveforms", b);
524     emit timelineShowWaveformsChanged();
525 }
526 
timelineShowThumbnails() const527 bool ShotcutSettings::timelineShowThumbnails() const
528 {
529     return settings.value("timeline/thumbnails", true).toBool();
530 }
531 
setTimelineShowThumbnails(bool b)532 void ShotcutSettings::setTimelineShowThumbnails(bool b)
533 {
534     settings.setValue("timeline/thumbnails", b);
535     emit timelineShowThumbnailsChanged();
536 }
537 
timelineRipple() const538 bool ShotcutSettings::timelineRipple() const
539 {
540     return settings.value("timeline/ripple", false).toBool();
541 }
542 
setTimelineRipple(bool b)543 void ShotcutSettings::setTimelineRipple(bool b)
544 {
545     settings.setValue("timeline/ripple", b);
546     emit timelineRippleChanged();
547 }
548 
timelineRippleAllTracks() const549 bool ShotcutSettings::timelineRippleAllTracks() const
550 {
551     return settings.value("timeline/rippleAllTracks", false).toBool();
552 }
553 
setTimelineRippleAllTracks(bool b)554 void ShotcutSettings::setTimelineRippleAllTracks(bool b)
555 {
556     settings.setValue("timeline/rippleAllTracks", b);
557     emit timelineRippleAllTracksChanged();
558 }
559 
timelineSnap() const560 bool ShotcutSettings::timelineSnap() const
561 {
562     return settings.value("timeline/snap", true).toBool();
563 }
564 
setTimelineSnap(bool b)565 void ShotcutSettings::setTimelineSnap(bool b)
566 {
567     settings.setValue("timeline/snap", b);
568     emit timelineSnapChanged();
569 }
570 
timelineCenterPlayhead() const571 bool ShotcutSettings::timelineCenterPlayhead() const
572 {
573     return settings.value("timeline/centerPlayhead", false).toBool();
574 }
575 
setTimelineCenterPlayhead(bool b)576 void ShotcutSettings::setTimelineCenterPlayhead(bool b)
577 {
578     settings.setValue("timeline/centerPlayhead", b);
579     emit timelineCenterPlayheadChanged();
580 }
581 
timelineTrackHeight() const582 int ShotcutSettings::timelineTrackHeight() const
583 {
584     return qMin(settings.value("timeline/trackHeight", 50).toInt(), kMaximumTrackHeight);
585 }
586 
setTimelineTrackHeight(int n)587 void ShotcutSettings::setTimelineTrackHeight(int n)
588 {
589     settings.setValue("timeline/trackHeight", qMin(n, kMaximumTrackHeight));
590 }
591 
timelineScrollZoom() const592 bool ShotcutSettings::timelineScrollZoom() const
593 {
594     return settings.value("timeline/scrollZoom", true).toBool();
595 }
596 
setTimelineScrollZoom(bool b)597 void ShotcutSettings::setTimelineScrollZoom(bool b)
598 {
599     settings.setValue("timeline/scrollZoom", b);
600     emit timelineScrollZoomChanged();
601 }
602 
timelineFramebufferWaveform() const603 bool ShotcutSettings::timelineFramebufferWaveform() const
604 {
605     return settings.value("timeline/framebufferWaveform", true).toBool();
606 }
607 
setTimelineFramebufferWaveform(bool b)608 void ShotcutSettings::setTimelineFramebufferWaveform(bool b)
609 {
610     settings.setValue("timeline/framebufferWaveform", b);
611     emit timelineFramebufferWaveformChanged();
612 }
613 
filterFavorite(const QString & filterName)614 QString ShotcutSettings::filterFavorite(const QString& filterName)
615 {
616     return settings.value("filter/favorite/" + filterName, "").toString();
617 }
setFilterFavorite(const QString & filterName,const QString & value)618 void ShotcutSettings::setFilterFavorite(const QString& filterName, const QString& value)
619 {
620     settings.setValue("filter/favorite/" + filterName, value);
621 }
622 
audioInDuration() const623 double ShotcutSettings::audioInDuration() const
624 {
625     return settings.value("filter/audioInDuration", 1.0).toDouble();
626 }
627 
setAudioInDuration(double d)628 void ShotcutSettings::setAudioInDuration(double d)
629 {
630     settings.setValue("filter/audioInDuration", d);
631     emit audioInDurationChanged();
632 }
633 
audioOutDuration() const634 double ShotcutSettings::audioOutDuration() const
635 {
636     return settings.value("filter/audioOutDuration", 1.0).toDouble();
637 }
638 
setAudioOutDuration(double d)639 void ShotcutSettings::setAudioOutDuration(double d)
640 {
641     settings.setValue("filter/audioOutDuration", d);
642     emit audioOutDurationChanged();
643 }
644 
645 
videoInDuration() const646 double ShotcutSettings::videoInDuration() const
647 {
648     return settings.value("filter/videoInDuration", 1.0).toDouble();
649 }
650 
setVideoInDuration(double d)651 void ShotcutSettings::setVideoInDuration(double d)
652 {
653     settings.setValue("filter/videoInDuration", d);
654     emit videoInDurationChanged();
655 }
656 
videoOutDuration() const657 double ShotcutSettings::videoOutDuration() const
658 {
659     return settings.value("filter/videoOutDuration", 1.0).toDouble();
660 }
661 
setVideoOutDuration(double d)662 void ShotcutSettings::setVideoOutDuration(double d)
663 {
664     settings.setValue("filter/videoOutDuration", d);
665     emit videoOutDurationChanged();
666 }
667 
askOutputFilter() const668 bool ShotcutSettings::askOutputFilter() const
669 {
670     return settings.value("filter/askOutput", true).toBool();
671 }
672 
setAskOutputFilter(bool b)673 void ShotcutSettings::setAskOutputFilter(bool b)
674 {
675     settings.setValue("filter/askOutput", b);
676     emit askOutputFilterChanged();
677 }
678 
loudnessScopeShowMeter(const QString & meter) const679 bool ShotcutSettings::loudnessScopeShowMeter(const QString& meter) const
680 {
681     return settings.value("scope/loudness/" + meter, true).toBool();
682 }
683 
setLoudnessScopeShowMeter(const QString & meter,bool b)684 void ShotcutSettings::setLoudnessScopeShowMeter(const QString& meter, bool b)
685 {
686     settings.setValue("scope/loudness/" + meter, b);
687 }
688 
drawMethod() const689 int ShotcutSettings::drawMethod() const
690 {
691 #ifdef Q_OS_WIN
692     return settings.value("opengl", Qt::AA_UseOpenGLES).toInt();
693 #else
694     return settings.value("opengl", Qt::AA_UseDesktopOpenGL).toInt();
695 #endif
696 }
697 
setDrawMethod(int i)698 void ShotcutSettings::setDrawMethod(int i)
699 {
700     settings.setValue("opengl", i);
701 }
702 
noUpgrade() const703 bool ShotcutSettings::noUpgrade() const
704 {
705     return settings.value("noupgrade", false).toBool();
706 }
707 
setNoUpgrade(bool value)708 void ShotcutSettings::setNoUpgrade(bool value)
709 {
710     settings.setValue("noupgrade", value);
711 }
712 
checkUpgradeAutomatic()713 bool ShotcutSettings::checkUpgradeAutomatic()
714 {
715     return settings.value("checkUpgradeAutomatic", false).toBool();
716 }
717 
setCheckUpgradeAutomatic(bool b)718 void ShotcutSettings::setCheckUpgradeAutomatic(bool b)
719 {
720     settings.setValue("checkUpgradeAutomatic", b);
721 }
722 
askUpgradeAutomatic()723 bool ShotcutSettings::askUpgradeAutomatic()
724 {
725     return settings.value("askUpgradeAutmatic", true).toBool();
726 }
727 
setAskUpgradeAutomatic(bool b)728 void ShotcutSettings::setAskUpgradeAutomatic(bool b)
729 {
730     settings.setValue("askUpgradeAutmatic", b);
731 }
732 
sync()733 void ShotcutSettings::sync()
734 {
735     settings.sync();
736 }
737 
appDataLocation() const738 QString ShotcutSettings::appDataLocation() const
739 {
740     if (!m_appDataLocation.isEmpty())
741         return m_appDataLocation;
742     else
743         return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation);
744 }
745 
setAppDataForSession(const QString & location)746 void ShotcutSettings::setAppDataForSession(const QString& location)
747 {
748     // This is intended to be called when using a command line option
749     // to set the AppData location.
750     appDataForSession = location;
751     if (instance)
752         instance.reset(new ShotcutSettings(location));
753 }
754 
setAppDataLocally(const QString & location)755 void ShotcutSettings::setAppDataLocally(const QString& location)
756 {
757     // This is intended to be called when using a GUI action to set the
758     // the new AppData location.
759 
760     // Copy the existing settings if they exist.
761     if (!QFile::exists(location + SHOTCUT_INI_FILENAME)) {
762         QSettings newSettings(location + SHOTCUT_INI_FILENAME, QSettings::IniFormat);
763         foreach (const QString& key, settings.allKeys())
764             newSettings.setValue(key, settings.value(key));
765         newSettings.sync();
766     }
767 
768     // Set the new location.
769     QSettings localSettings;
770     localSettings.setValue(APP_DATA_DIR_KEY, location);
771     localSettings.sync();
772 }
773 
layouts() const774 QStringList ShotcutSettings::layouts() const
775 {
776     QStringList result;
777     for (const auto& s : settings.value("layout/layouts").toStringList()) {
778         if (!s.startsWith("__"))
779             result << s;
780     }
781     return result;
782 }
783 
setLayout(const QString & name,const QByteArray & geometry,const QByteArray & state)784 bool ShotcutSettings::setLayout(const QString& name, const QByteArray& geometry, const QByteArray& state)
785 {
786     bool isNew = false;
787     QStringList layouts = Settings.layouts();
788     if (layouts.indexOf(name) == -1) {
789         isNew = true;
790         layouts.append(name);
791         settings.setValue("layout/layouts", layouts);
792     }
793     settings.setValue(QString("layout/%1_%2").arg(name).arg("geometry"), geometry);
794     settings.setValue(QString("layout/%1_%2").arg(name).arg("state"), state);
795     return isNew;
796 }
797 
layoutGeometry(const QString & name)798 QByteArray ShotcutSettings::layoutGeometry(const QString& name)
799 {
800     QString key = QString("layout/%1_geometry").arg(name);
801     return settings.value(key).toByteArray();
802 }
803 
layoutState(const QString & name)804 QByteArray ShotcutSettings::layoutState(const QString& name)
805 {
806     QString key = QString("layout/%1_state").arg(name);
807     return settings.value(key).toByteArray();
808 }
809 
removeLayout(const QString & name)810 bool ShotcutSettings::removeLayout(const QString& name)
811 {
812     QStringList list = layouts();
813     int index = list.indexOf(name);
814     if (index > -1) {
815         list.removeAt(index);
816         if (list.isEmpty())
817             settings.remove("layout/layouts");
818         else
819             settings.setValue("layout/layouts", list);
820         settings.remove(QString("layout/%1_%2").arg(name).arg("geometry"));
821         settings.remove(QString("layout/%1_%2").arg(name).arg("state"));
822         return true;
823     }
824     return false;
825 }
826 
layoutMode() const827 int ShotcutSettings::layoutMode() const
828 {
829     return settings.value("layout/mode", -1).toInt();
830 }
831 
setLayoutMode(int mode)832 void ShotcutSettings::setLayoutMode(int mode)
833 {
834     settings.setValue("layout/mode", mode);
835 }
836 
clearRecent() const837 bool ShotcutSettings::clearRecent() const
838 {
839     return settings.value("clearRecent", false).toBool();
840 }
841 
setClearRecent(bool b)842 void ShotcutSettings::setClearRecent(bool b)
843 {
844     settings.setValue("clearRecent", b);
845 }
846 
projectsFolder() const847 QString ShotcutSettings::projectsFolder() const
848 {
849     return settings.value("projectsFolder", QStandardPaths::standardLocations(QStandardPaths::MoviesLocation)).toString();
850 }
851 
setProjectsFolder(const QString & path)852 void ShotcutSettings::setProjectsFolder(const QString &path)
853 {
854     settings.setValue("projectsFolder", path);
855 }
856 
proxyEnabled() const857 bool ShotcutSettings::proxyEnabled() const
858 {
859     return settings.value("proxy/enabled", false).toBool();
860 }
861 
setProxyEnabled(bool b)862 void ShotcutSettings::setProxyEnabled(bool b)
863 {
864     settings.setValue("proxy/enabled", b);
865 }
866 
proxyFolder() const867 QString ShotcutSettings::proxyFolder() const
868 {
869     QDir dir(appDataLocation());
870     const char* subfolder = "proxies";
871     if (!dir.cd(subfolder)) {
872         if (dir.mkdir(subfolder))
873             dir.cd(subfolder);
874     }
875     return settings.value("proxy/folder", dir.path()).toString();
876 }
877 
setProxyFolder(const QString & path)878 void ShotcutSettings::setProxyFolder(const QString& path)
879 {
880     settings.setValue("proxy/folder", path);
881 }
882 
proxyUseProjectFolder() const883 bool ShotcutSettings::proxyUseProjectFolder() const
884 {
885     return settings.value("proxy/useProjectFolder", true).toBool();
886 }
887 
setProxyUseProjectFolder(bool b)888 void ShotcutSettings::setProxyUseProjectFolder(bool b)
889 {
890     settings.setValue("proxy/useProjectFolder", b);
891 }
892 
proxyUseHardware() const893 bool ShotcutSettings::proxyUseHardware() const
894 {
895     return settings.value("proxy/useHardware", false).toBool();
896 }
897 
setProxyUseHardware(bool b)898 void ShotcutSettings::setProxyUseHardware(bool b)
899 {
900     settings.setValue("proxy/useHardware", b);
901 }
902 
undoLimit() const903 int ShotcutSettings::undoLimit() const
904 {
905     return settings.value("undoLimit", 1000).toInt();
906 }
907