-
-
Notifications
You must be signed in to change notification settings - Fork 601
Developers_manual
- 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.
Almost every 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 default
keyword.
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.
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.
The main configuration objects (CFG_CORE, CFG_UI and CFG_CLI) are defined using this framework.
This subject is quite extensive and was moved to a separate page: Model-view binding.
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.
Plugins can create their own QAction
and may need it to be added to SQLiteStudio's main menu, or to some toolbars.
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:
MAINWINDOW->menuBar()
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:
MAINWINDOW->getToolBar(MainWindow::TOOLBAR_MAIN)
The TOOLBAR_MAIN
is the value of ToolBar
enum defined in the MainWindow
. This way you can query all toolbars placed in the main window.
This is a little more complicated in case of MDI windows, such as EditorWindow
, 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 EditorWindow
:
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, Action
and 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:
DataView
TableWindow
ViewWindow
For other ExtActionContainer
classes you will have to use generic template methods from the ExtActionPrototype
itself.
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 QToolBar*
.)
Other 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.
- 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