1 /* Copyright (C) 2021 J.F.Dockes
2  *
3  * License: GPL 2.1
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2.1 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this program; if not, write to the
17  * Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 #ifndef _SCBASE_H_INCLUDED_
21 #define _SCBASE_H_INCLUDED_
22 
23 #include <QString>
24 #include <QKeySequence>
25 #include <QStringList>
26 #include <QObject>
27 
28 /** Shortcuts storage classe. Singleton.
29  *
30  * Manage settings storage for key sequences shortcuts.
31  * Each shortcut is defined by 4 strings:
32  *  - Context  (e.g. "Main Window").
33  *  - Description (e.g. "Move focus to search entry").
34  *  - Current value, possibly changed by user, e.g. "Ctrl+l".
35  *  - Default value.
36  *
37  * The customised values are read from the stored settings by the SCBase
38  * constructor.
39  * The entries with default values are created from the init() method
40  * of each class responsible for a context (e.g. RclMain, SnippetsW),
41  * or from a static method for classes which are not instantiated when
42  * the program starts up.
43  *
44  * Macros are provided for actually creating the shortcuts in the
45  * init() routines, or for just creating the default entries (for use
46  * in the preferences screen).
47  */
48 class SCBase : public QObject {
49     Q_OBJECT;
50 public:
51     ~SCBase();
52 
53     /* Return a reference to the instantiated singleton */
54     static SCBase& scBase();
55 
56     /** Get the current keysequence for the shortcut. If the entry was not
57      * created from the settings, create it with the default
58      * sequence. This is called from the context classes and returns
59      * either the default or the customised sequence. */
60     QKeySequence get(const QString& id, const QString& context,
61                      const QString& description, const QString& defkeyseq);
62 
63     /** Set a customised value for the designated shortcut. Called
64      * from the preference code. */
65     void set(const QString& id, const QString& context,
66              const QString& description, const QString& keyseq);
67 
68     /** Return a list of all shortcuts. This is used to create the
69      *  preferences table. Each entry in the list is a string
70      *  tuple: id, context, description, value, default */
71     QStringList getAll();
72 
73     /** Return a list of all shortcuts, with only default values (no settings).
74      * Used for resetting the defaults, especially if a lang changed
75      * has messed up the keys */
76     QStringList getAllDefaults();
77 
78     /** Store the customised values to the settings storage. Called
79      * from the preferences accept() method. */
80     void store();
81 
82     class Internal;
83 
84 signals:
85 
86     /** Preference change has been accepted and client classes should
87      * update their shortcuts */
88     void shortcutsChanged();
89 
90 private:
91     Internal *m{nullptr};
92     SCBase();
93 };
94 
95 /** This can be used in the client class init method, to actually
96  * create and connect the shortcuts. */
97 #define SETSHORTCUT(OBJ, ID, CTXT, DESCR, SEQ, FLD, SLTFUNC)            \
98     do {                                                                \
99         QKeySequence ks = SCBase::scBase().get(ID, CTXT, DESCR, SEQ);   \
100         if (!ks.isEmpty()) {                                            \
101             delete FLD;                                                 \
102             FLD = new QShortcut(ks, OBJ, SLOT(SLTFUNC()));              \
103         }                                                               \
104     } while (false);
105 
106 /** This can be used from a static method, to be called by the program
107  * initialisation, for classes which are not instantiated at startup,
108  * and so that the shortcuts are available for the preferences
109  * customisation screen. Same param list as SETSHORTCUT to make it
110  * easy to duplicate a list of ones into the other, even if some
111  * parameters are not used here. */
112 #define LISTSHORTCUT(OBJ, ID, CTXT, DESCR, SEQ, FLD, SLTFUNC)       \
113     do {                                                            \
114         SCBase::scBase().get(ID, CTXT, DESCR, SEQ);                 \
115     } while (false);
116 
117 
118 #endif /* _SCBASE_H_INCLUDED_ */
119