Table of Contents
- Code conventions
- Application core (shared library)
- GUI application
- Console application (CLI)
- New release routine
This page describes aspects of SQLiteStudio core application development. Learning this will also help you with developing plugins.
switch-case with all cases explicit
switch-case for enums will list all cases (all enum values) explicitly. This is not a waste of time - it helps maintaining the code, because when you add new enum, the compiler will warn you that you didn't handle that enum value yet in such places.
For "switch-casing" enums, list all cases explicitly, don't use
Application core (shared library)
Core application is enclosed in the
coreSQLiteStudio shared library (*.dll/*.so/*.dylib). It's used by all clients (console, GUI), while it's independent from the actual interface implementation. It does not depend on QtGui or any other GUI library. It's linked with QtCore, QtXml and QtNetwork.
The SQLiteStudio singleton is a entry point for all services in the application (well, those enclosed in the core, not the ones from GUI or CLI). It can be accessed with a singleton method:
qDebug() << SQLiteStudio::getInstance()->getVersionString();
or easier, with a macro:
qDebug() << SQLITESTUDIO->getVersionString();
You will rarely use configuration manager explicitly. Instead you should use configuration containers created with model-view binding, namely CFG_CORE, CFG_UI and CFG_CLI. Nevertheless, sometimes you will want to manage SQL queries history, or add new functionality to the configuration manager, so here's how it works.
Registering new plugin type
Registering built-in plugin
SQLiteStudio provides a very handy binding automation which connects data model with UI forms. It's used widely in the ConfigDialog, but also in several plugin-related dialogs. It allows plugins to be developed without GUI dependency, but yet having the UI forms when used from GUI.
This subject is quite extensive and was moved to a separate page: Model-view binding.
Binding UI form (widgets) to the configuration container
See the Model-view binding section above.
Using SQLiteStudio's shortcuts binding solution makes any defined action shortcuts automatically available in the configuration dialog, including saving modified values into configuration file.
See Shortcuts binding for more details.
Dynamically loadable UI forms
Adding action to menu and toolbars
Plugins can create their own
QAction and may need it to be added to SQLiteStudio's main menu, or to some toolbars.
Adding to main menu
This is easy. Just use one of:
MAINWINDOW->getDatabaseMenu() MAINWINDOW->getStructureMenu() MAINWINDOW->getViewMenu() MAINWINDOW->getToolsMenu()
...to access particular menus. To access the menu bar (for example to add new menu) use:
Adding to toolbars
In case of the main window there is always only one instance of it, so you can handle it in a similar way as for menus:
TOOLBAR_MAIN is the value of
ToolBar enum defined in the
MainWindow. This way you can query all toolbars placed in the main window.
MDI window toolbars
This is a little more complicated in case of MDI windows, such as
TableWindow, etc. You need to "register" and "deregister" actions for particular class and toolbar. This is possible thanks to the
ExtActionContainer class, which is inherited by all SQLiteStudio widgets that have toolbar inside.
For example we will add and then remove action from the
ExtActionPrototype* action = new ExtActionPrototype(QIcon(":/icons/icon.png"), tr("Action title"), this); ExtActionContainer::insertActionBefore<EditorWindow>(action, EditorWindow::EXEC_QUERY, EditorWindow::TOOLBAR_MAIN); // Now remove: ExtActionContainer::removeAction<EditorWindow>(action, EditorWindow::TOOLBAR_MAIN);
The ExtActionPrototype is a special prototype for QAction that can be copied as QAction and inserted to different action containers (and this actually what's being done by the ExtActionContainer), while each action calls back the ExtActionPrototype when triggered. This ways the ExtActionPrototype knows which action (from which container) called it and so it emits signal with information which container exactly requested the action. See list of signals emitted by ExtActionPrototype below to learn more.
Adding action this way causes action to be added to all currently existing
EditorWindow instances and also to every
EditorWindow that will be open by the user in future.
This is important that when adding/removing action with ExtActionContainer methods you use toolbar enums from the same class that you specify as a template parameter to insertAction/removeAction, otherwise action might be added to wrong toolbar, or even worse - application can crash.
Some classes (and the
EditorWindow is an example of it) have those static methods overloaded, so they don't require template parameter,
ToolBar enums are explicitly declared, instead of implict cast to integer. This makes above calls more human friendly and protects you from making a mistake with wrong toolbar type or wrong action type used (as in the warning above), because compiler will check those types:
ExtActionPrototype* action = new ExtActionPrototype(QIcon(":/icons/icon.png"), tr("Action title"), this); EditorWindow::insertActionBefore(action, EditorWindow::EXEC_QUERY, EditorWindow::TOOLBAR_MAIN); // Now remove: EditorWindow::removeAction(action, EditorWindow::TOOLBAR_MAIN);
Other classes that have such overloaded methods are:
ExtActionContainer classes you will have to use generic template methods from the
ExtActionPrototype emits several useful signals. The most important is
triggered(ExtActionContainer*,int), which tells you, that the action was triggered from given action container and given toolbar (toolbar integer represents enum value of the toolbar that the action was added to - use
ExtActionContainer::getToolBar(int) to get
ExtActionPrototype signals will tell you when the action prototype is copied and inserted into
ExtActionContainer, or when it's removed from the container. Arguments of those signals include the individual copy of
QAction being added/removed from the container. You can use those signals to - for example - dynamically update action status (enabled or not), according to some changed in the action container.
Console application (CLI)
New release routine
- Check unit tests.
- Update translations (lupdate, translate, lrelease)
- Compile on all 3 platforms.
- Upload new app packages.
- Upload update repositories.
- Update Changelog on homepage.
- Post release news at homepage
- Post release news at social media