1 /*
2  * Copyright (C) Pedram Pourang (aka Tsu Jan) 2014-2019 <tsujan2000@gmail.com>
3  *
4  * FeatherPad is free software: you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * FeatherPad is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12  * See the GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program.  If not, see <http://www.gnu.org/licenses/>.
16  *
17  * @license GPL-3.0+ <https://spdx.org/licenses/GPL-3.0+.html>
18  */
19 
20 #ifndef CONFIG_H
21 #define CONFIG_H
22 
23 #include <QSettings>
24 #include <QSize>
25 #include <QPoint>
26 #include <QFont>
27 #include <QColor>
28 
29 namespace FeatherPad {
30 
31 // Prevent redundant writings! (Why does QSettings write to the config file when no setting is changed?)
32 class Settings : public QSettings
33 {
34     Q_OBJECT
35 public:
36     Settings (const QString &organization, const QString &application = QString(), QObject *parent = nullptr)
QSettings(organization,application,parent)37              : QSettings (organization, application, parent) {}
38     Settings (const QString &fileName, QSettings::Format format, QObject *parent = nullptr)
QSettings(fileName,format,parent)39              : QSettings (fileName, format, parent) {}
40 
setValue(const QString & key,const QVariant & v)41     void setValue (const QString &key, const QVariant &v) {
42         if (value (key) == v)
43             return;
44         QSettings::setValue (key, v);
45     }
46 };
47 
48 class Config {
49 public:
50     Config();
51     ~Config();
52 
53     void readConfig();
54     void readShortcuts();
55     void writeConfig();
56 
getRemSize()57     bool getRemSize() const {
58         return remSize_;
59     }
setRemSize(bool rem)60     void setRemSize (bool rem) {
61         remSize_ = rem;
62     }
63 
getRemPos()64     bool getRemPos() const {
65         return remPos_;
66     }
setRemPos(bool rem)67     void setRemPos (bool rem) {
68         remPos_ = rem;
69     }
70 
getRemSplitterPos()71     bool getRemSplitterPos() const {
72         return remSplitterPos_;
73     }
setRemSplitterPos(bool rem)74     void setRemSplitterPos (bool rem) {
75         remSplitterPos_ = rem;
76     }
77 
getIsMaxed()78     bool getIsMaxed() const {
79         return isMaxed_;
80     }
setIsMaxed(bool isMaxed)81     void setIsMaxed (bool isMaxed) {
82         isMaxed_ = isMaxed;
83     }
84 
getIsFull()85     bool getIsFull() const {
86         return isFull_;
87     }
setIsFull(bool isFull)88     void setIsFull (bool isFull) {
89         isFull_ = isFull;
90     }
91 
getDarkColScheme()92     bool getDarkColScheme() const {
93         return darkColScheme_;
94     }
setDarkColScheme(bool dark)95     void setDarkColScheme (bool dark) {
96         darkColScheme_ = dark;
97     }
98 
getThickCursor()99     bool getThickCursor() const {
100         return thickCursor_;
101     }
setThickCursor(bool thick)102     void setThickCursor (bool thick) {
103         thickCursor_ = thick;
104     }
105 
getLightBgColorValue()106     int getLightBgColorValue() const {
107         return lightBgColorValue_;
108     }
setLightBgColorValue(int lightness)109     void setLightBgColorValue (int lightness) {
110         lightBgColorValue_ = lightness;
111     }
112 
getDarkBgColorValue()113     int getDarkBgColorValue() const {
114         return darkBgColorValue_;
115     }
setDarkBgColorValue(int darkness)116     void setDarkBgColorValue (int darkness) {
117         darkBgColorValue_ = darkness;
118     }
119 
getDateFormat()120     QString getDateFormat() const {
121         return dateFormat_;
122     }
setDateFormat(const QString & format)123     void setDateFormat (const QString &format) {
124         dateFormat_ = format;
125     }
126 
getTextTabSize()127     int getTextTabSize() const {
128         return textTabSize_;
129     }
setTextTabSize(int textTab)130     void setTextTabSize (int textTab) {
131         textTabSize_ = textTab;
132     }
133 
getRecentFilesNumber()134     int getRecentFilesNumber() const {
135         return recentFilesNumber_;
136     }
setRecentFilesNumber(int number)137     void setRecentFilesNumber (int number) {
138         recentFilesNumber_ = number;
139     }
getCurRecentFilesNumber()140     int getCurRecentFilesNumber() const {
141         return curRecentFilesNumber_;
142     }
143 
getTabWrapAround()144     bool getTabWrapAround() const {
145         return tabWrapAround_;
146     }
setTabWrapAround(bool wrap)147     void setTabWrapAround (bool wrap) {
148         tabWrapAround_ = wrap;
149     }
150 
getHideSingleTab()151     bool getHideSingleTab() const {
152         return hideSingleTab_;
153     }
setHideSingleTab(bool hide)154     void setHideSingleTab (bool hide) {
155         hideSingleTab_ = hide;
156     }
157 
getWinSize()158     QSize getWinSize() const {
159         return winSize_;
160     }
setWinSize(const QSize & s)161     void setWinSize (const QSize &s) {
162         winSize_ = s;
163     }
164 
getPrefSize()165     QSize getPrefSize() const {
166         return prefSize_;
167     }
setPrefSize(const QSize & s)168     void setPrefSize (const QSize &s) {
169         prefSize_ = s;
170     }
171 
getStartSize()172     QSize getStartSize() const {
173         return startSize_;
174     }
setStartSize(const QSize & s)175     void setStartSize (const QSize &s) {
176         startSize_ = s;
177     }
178 
getWinPos()179     QPoint getWinPos() const {
180         return winPos_;
181     }
setWinPos(const QPoint & p)182     void setWinPos (const QPoint &p) {
183         winPos_ = p;
184     }
185 
getSplitterPos()186     int getSplitterPos() const {
187         return splitterPos_;
188     }
setSplitterPos(int pos)189     void setSplitterPos (int pos) {
190         splitterPos_ = pos;
191     }
192 
getNoToolbar()193     bool getNoToolbar() const {
194         return noToolbar_;
195     }
setNoToolbar(bool noTB)196     void setNoToolbar (bool noTB) {
197         noToolbar_ = noTB;
198     }
199 
getNoMenubar()200     bool getNoMenubar() const {
201         return noMenubar_;
202     }
setNoMenubar(bool noMB)203     void setNoMenubar (bool noMB) {
204         noMenubar_ = noMB;
205     }
206 
getHideSearchbar()207     bool getHideSearchbar() const {
208         return hideSearchbar_;
209     }
setHideSearchbar(bool hide)210     void setHideSearchbar (bool hide) {
211         hideSearchbar_ = hide;
212     }
213 
getShowStatusbar()214     bool getShowStatusbar() const {
215         return showStatusbar_;
216     }
setShowStatusbar(bool show)217     void setShowStatusbar (bool show) {
218         showStatusbar_ = show;
219     }
220 
getShowCursorPos()221     bool getShowCursorPos() const {
222         return showCursorPos_;
223     }
setShowCursorPos(bool show)224     void setShowCursorPos (bool show) {
225         showCursorPos_ = show;
226     }
227 
getShowLangSelector()228     bool getShowLangSelector() const {
229         return showLangSelector_;
230     }
setShowLangSelector(bool show)231     void setShowLangSelector (bool show) {
232         showLangSelector_ = show;
233     }
234 
getSidePaneMode()235     bool getSidePaneMode() const {
236         return sidePaneMode_;
237     }
setSidePaneMode(bool sidePane)238     void setSidePaneMode (bool sidePane) {
239         sidePaneMode_ = sidePane;
240     }
241 
getTabPosition()242     int getTabPosition() const {
243         return tabPosition_;
244     }
setTabPosition(int pos)245     void setTabPosition (int pos) {
246         tabPosition_ = pos;
247     }
248 
getFont()249     QFont getFont() const {
250         return font_;
251     }
setFont(const QFont & font)252     void setFont (const QFont &font) {
253         font_ = font;
254     }
255     void resetFont();
256 
getRemFont()257     bool getRemFont() const {
258         return remFont_;
259     }
setRemFont(bool rem)260     void setRemFont (bool rem) {
261         remFont_ = rem;
262     }
263 
getWrapByDefault()264     bool getWrapByDefault() const {
265         return wrapByDefault_;
266     }
setWrapByDefault(bool wrap)267     void setWrapByDefault (bool wrap) {
268         wrapByDefault_ = wrap;
269     }
270 
getIndentByDefault()271     bool getIndentByDefault() const {
272         return indentByDefault_;
273     }
setIndentByDefault(bool indent)274     void setIndentByDefault (bool indent) {
275         indentByDefault_ = indent;
276     }
277 
getAutoReplace()278     bool getAutoReplace() const {
279         return autoReplace_;
280     }
setAutoReplace(bool autoR)281     void setAutoReplace (bool autoR) {
282         autoReplace_ = autoR;
283     }
284 
getAutoBracket()285     bool getAutoBracket() const {
286         return autoBracket_;
287     }
setAutoBracket(bool autoB)288     void setAutoBracket (bool autoB) {
289         autoBracket_ = autoB;
290     }
291 
getLineByDefault()292     bool getLineByDefault() const {
293         return lineByDefault_;
294     }
setLineByDefault(bool line)295     void setLineByDefault (bool line) {
296         lineByDefault_ = line;
297     }
298 
getSyntaxByDefault()299     bool getSyntaxByDefault() const {
300         return syntaxByDefault_;
301     }
setSyntaxByDefault(bool syntax)302     void setSyntaxByDefault (bool syntax) {
303         syntaxByDefault_ = syntax;
304     }
305 
getShowWhiteSpace()306     bool getShowWhiteSpace() const {
307         return showWhiteSpace_;
308     }
setShowWhiteSpace(bool show)309     void setShowWhiteSpace (bool show) {
310         showWhiteSpace_ = show;
311     }
312 
getShowEndings()313     bool getShowEndings() const {
314         return showEndings_;
315     }
setShowEndings(bool show)316     void setShowEndings (bool show) {
317         showEndings_ = show;
318     }
319 
getVLineDistance()320     int getVLineDistance() const {
321         return vLineDistance_;
322     }
setVLineDistance(int distance)323     void setVLineDistance (int distance) {
324         vLineDistance_ = distance;
325     }
326 
getMaxSHSize()327     int getMaxSHSize() const {
328         return maxSHSize_;
329     }
setMaxSHSize(int max)330     void setMaxSHSize (int max) {
331         maxSHSize_ = max;
332     }
333 
getSkipNonText()334     bool getSkipNonText() const {
335         return skipNonText_;
336     }
setSkipNonText(bool skip)337     void setSkipNonText (bool skip) {
338         skipNonText_ = skip;
339     }
340 /*************************/
getExecuteScripts()341     bool getExecuteScripts() const {
342         return executeScripts_;
343     }
setExecuteScripts(bool execute)344     void setExecuteScripts (bool execute) {
345         executeScripts_ = execute;
346     }
getExecuteCommand()347     QString getExecuteCommand() const {
348         return executeCommand_;
349     }
setExecuteCommand(const QString & command)350     void setExecuteCommand (const QString& command) {
351         executeCommand_ = command;
352     }
353 /*************************/
getAppendEmptyLine()354     bool getAppendEmptyLine() const {
355         return appendEmptyLine_;
356     }
setAppendEmptyLine(bool append)357     void setAppendEmptyLine (bool append) {
358         appendEmptyLine_ = append;
359     }
360 
getRemoveTrailingSpaces()361     bool getRemoveTrailingSpaces() const {
362         return removeTrailingSpaces_;
363     }
setRemoveTrailingSpaces(bool remove)364     void setRemoveTrailingSpaces (bool remove) {
365         removeTrailingSpaces_ = remove;
366     }
367 
getOpenInWindows()368     bool getOpenInWindows() const {
369         return openInWindows_;
370     }
setOpenInWindows(bool windows)371     void setOpenInWindows (bool windows) {
372         openInWindows_ = windows;
373     }
374 
getNativeDialog()375     bool getNativeDialog() const {
376         return nativeDialog_;
377     }
setNativeDialog(bool native)378     void setNativeDialog (bool native) {
379         nativeDialog_ = native;
380     }
381 /*************************/
getRecentOpened()382     bool getRecentOpened() const {
383         return recentOpened_;
384     }
setRecentOpened(bool opened)385     void setRecentOpened (bool opened) {
386         recentOpened_ = opened;
387     }
388 
getRecentFiles()389     QStringList getRecentFiles() const {
390         return recentFiles_;
391     }
clearRecentFiles()392     void clearRecentFiles() {
393         recentFiles_ = QStringList();
394     }
395     void addRecentFile (const QString &file);
396 /*************************/
customShortcutActions()397     QHash<QString, QString> customShortcutActions() const {
398         return actions_;
399     }
setActionShortcut(const QString & action,const QString & shortcut)400     void setActionShortcut (const QString &action, const QString &shortcut) {
401         actions_.insert (action, shortcut);
402     }
removeShortcut(const QString & action)403     void removeShortcut (const QString &action) {
404         actions_.remove (action);
405         removedActions_ << action;
406     }
407 
hasReservedShortcuts()408     bool hasReservedShortcuts() const {
409         return (!reservedShortcuts_.isEmpty());
410     }
reservedShortcuts()411     QStringList reservedShortcuts() const {
412         return reservedShortcuts_;
413     }
setReservedShortcuts(const QStringList & s)414     void setReservedShortcuts (const QStringList &s) {
415         reservedShortcuts_ = s;
416     }
417 /*************************/
getInertialScrolling()418     bool getInertialScrolling() const {
419         return inertialScrolling_;
420     }
setInertialScrolling(bool inertial)421     void setInertialScrolling (bool inertial) {
422         inertialScrolling_ = inertial;
423     }
424 /*************************/
savedCursorPos()425     QHash<QString, QVariant> savedCursorPos() {
426         readCursorPos();
427         return cursorPos_;
428     }
saveCursorPos(const QString & name,int pos)429     void saveCursorPos (const QString& name, int pos) {
430         readCursorPos();
431         if (removedCursorPos_.contains (name))
432             removedCursorPos_.removeOne (name);
433         else
434             cursorPos_.insert (name, pos);
435     }
removeCursorPos(const QString & name)436     void removeCursorPos (const QString& name) {
437         readCursorPos();
438         cursorPos_.remove (name);
439         removedCursorPos_ << name;
440     }
removeAllCursorPos()441     void removeAllCursorPos() {
442         readCursorPos();
443         removedCursorPos_.append (cursorPos_.keys());
444         cursorPos_.clear();
445     }
446 /*************************/
getSaveLastFilesList()447     bool getSaveLastFilesList() const {
448         return saveLastFilesList_;
449     }
setSaveLastFilesList(bool saveList)450     void setSaveLastFilesList (bool saveList) {
451         saveLastFilesList_ = saveList;
452     }
453 
454     QStringList getLastFiles(); // may be called only at session start and sets lasFilesCursorPos_
getLastFilesCursorPos()455     QHash<QString, QVariant> getLastFilesCursorPos() const { // is called only after getLastFiles()
456         return lasFilesCursorPos_;
457     }
setLastFileCursorPos(const QHash<QString,QVariant> & curPos)458     void setLastFileCursorPos (const QHash<QString, QVariant>& curPos) {
459         lasFilesCursorPos_ = curPos;
460     }
461 /*************************/
getAutoSave()462     bool getAutoSave() const {
463         return autoSave_;
464     }
setAutoSave(bool as)465     void setAutoSave (bool as) {
466         autoSave_ = as;
467     }
getAutoSaveInterval()468     int getAutoSaveInterval() const {
469         return autoSaveInterval_;
470     }
setAutoSaveInterval(int i)471     void setAutoSaveInterval (int i) {
472         autoSaveInterval_ = i;
473     }
474 /*************************/
getSaveUnmodified()475     bool getSaveUnmodified() const {
476         return saveUnmodified_;
477     }
setSaveUnmodified(bool save)478     void setSaveUnmodified (bool save) {
479         saveUnmodified_ = save;
480     }
481 /*************************/
getSelectionHighlighting()482     bool getSelectionHighlighting() const {
483         return selectionHighlighting_;
484     }
setSelectionHighlighting(bool enable)485     void setSelectionHighlighting (bool enable) {
486         selectionHighlighting_ = enable;
487     }
488 /*************************/
getPastePaths()489     bool getPastePaths() const {
490         return pastePaths_;
491     }
setPastePaths(bool pastPaths)492     void setPastePaths (bool pastPaths) {
493         pastePaths_ = pastPaths;
494     }
495 /*************************/
getCloseWithLastTab()496     bool getCloseWithLastTab() const {
497         return closeWithLastTab_;
498     }
setCloseWithLastTab(bool close)499     void setCloseWithLastTab (bool close) {
500         closeWithLastTab_ = close;
501     }
502 /*************************/
getSharedSearchHistory()503     bool getSharedSearchHistory() const {
504         return sharedSearchHistory_;
505     }
setSharedSearchHistory(bool share)506     void setSharedSearchHistory (bool share) {
507         sharedSearchHistory_ = share;
508     }
509 /*************************/
getDisableMenubarAccel()510     bool getDisableMenubarAccel() const {
511         return disableMenubarAccel_;
512     }
setDisableMenubarAccel(bool disable)513     void setDisableMenubarAccel (bool disable) {
514         disableMenubarAccel_ = disable;
515     }
516 /*************************/
getDictPath()517     QString getDictPath() const {
518         return dictPath_;
519     }
setDictPath(const QString & dictPath)520     void setDictPath (const QString& dictPath) {
521         dictPath_ = dictPath;
522     }
523 
getSpellCheckFromStart()524     bool getSpellCheckFromStart() const {
525         return spellCheckFromStart_;
526     }
setSpellCheckFromStart(bool fromStart)527     void setSpellCheckFromStart (bool fromStart) {
528         spellCheckFromStart_ = fromStart;
529     }
530 /*************************/
lightSyntaxColors()531     QHash<QString, QColor> lightSyntaxColors() const {
532         return defaultLightSyntaxColors_;
533     }
darkSyntaxColors()534     QHash<QString, QColor> darkSyntaxColors() const {
535         return defaultDarkSyntaxColors_;
536     }
537 
customSyntaxColors()538     QHash<QString, QColor> customSyntaxColors() const {
539         return customSyntaxColors_;
540     }
setCustomSyntaxColors(const QHash<QString,QColor> & colors)541     void setCustomSyntaxColors (const QHash<QString, QColor>& colors) {
542         customSyntaxColors_ = colors;
543     }
544 
getDefaultWhiteSpaceValue()545     int getDefaultWhiteSpaceValue() const {
546         return darkColScheme_ ? 95 : 180;
547     }
getMinWhiteSpaceValue()548     int getMinWhiteSpaceValue() const {
549         return darkColScheme_ ? 50 : 130;
550     }
getMaxWhiteSpaceValue()551     int getMaxWhiteSpaceValue() const {
552         return darkColScheme_ ? 140 : 230;
553     }
getWhiteSpaceValue()554     int getWhiteSpaceValue() const {
555         return whiteSpaceValue_;
556     }
557     void setWhiteSpaceValue (int value);
558 
getCurLineHighlight()559     int getCurLineHighlight() const {
560         return curLineHighlight_;
561     }
getMinCurLineHighlight()562     int getMinCurLineHighlight() const {
563         return darkColScheme_ ? 0 : 210;
564     }
getMaxCurLineHighlight()565     int getMaxCurLineHighlight() const {
566         return darkColScheme_ ? 70 : 255;
567     }
568     void setCurLineHighlight (int value);
569 
570     void readSyntaxColors();
571 
572 private:
573     QString validatedShortcut (const QVariant v, bool *isValid);
574     void readCursorPos();
575     void writeCursorPos();
576     void setDfaultSyntaxColors();
577     void writeSyntaxColors();
578 
579     bool remSize_, remPos_, remSplitterPos_,
580          noToolbar_, noMenubar_,
581          hideSearchbar_,
582          showStatusbar_, showCursorPos_, showLangSelector_,
583          sidePaneMode_,
584          remFont_, wrapByDefault_, indentByDefault_, autoReplace_, autoBracket_, lineByDefault_,
585          syntaxByDefault_, showWhiteSpace_, showEndings_,
586          isMaxed_, isFull_,
587          darkColScheme_,
588          thickCursor_,
589          tabWrapAround_, hideSingleTab_,
590          executeScripts_,
591          appendEmptyLine_,
592          removeTrailingSpaces_,
593          openInWindows_,
594          nativeDialog_,
595          inertialScrolling_,
596          autoSave_,
597          skipNonText_,
598          saveUnmodified_,
599          selectionHighlighting_,
600          pastePaths_,
601          closeWithLastTab_,
602          sharedSearchHistory_,
603          disableMenubarAccel_;
604     int vLineDistance_,
605         tabPosition_,
606         maxSHSize_,
607         lightBgColorValue_, darkBgColorValue_,
608         recentFilesNumber_,
609         curRecentFilesNumber_, // the start value of recentFilesNumber_ -- fixed during a session
610         autoSaveInterval_,
611         textTabSize_;
612     QString dateFormat_;
613     QSize winSize_, startSize_, prefSize_;
614     QPoint winPos_;
615     int splitterPos_;
616     QFont font_;
617     QString executeCommand_;
618     bool recentOpened_;
619     QStringList recentFiles_;
620     bool saveLastFilesList_;
621     QHash<QString, QString> actions_;
622     QStringList removedActions_, reservedShortcuts_;
623 
624     QHash<QString, QVariant> cursorPos_;
625     QStringList removedCursorPos_; // used only internally for the clean-up
626     bool cursorPosRetrieved_; // used only internally for reading once
627 
628     QHash<QString, QVariant> lasFilesCursorPos_;
629 
630     QString dictPath_;
631     bool spellCheckFromStart_;
632 
633     QHash<QString, QColor> defaultLightSyntaxColors_, defaultDarkSyntaxColors_, customSyntaxColors_;
634     int whiteSpaceValue_, curLineHighlight_;
635 };
636 
637 }
638 
639 #endif // CONFIG_H
640