cmake repository for laserdock library with WiFi Cube Support
Windows (msvc2019 x86)
macOS (clang)
android
Linux
- Download Qt Online installer from https://www.qt.io/download-qt-installer
- Run installer and install Qt for mac/windows (the latest version is recommended, library was tested with Qt 6.7)
- Check Qt Creator Preferences -> Kits -> Kits page for any warnings
- If you need Android build ensure that page Preferences -> SDKs is filled
- Open root CMakeLists.txt.
- Setup build dirs and create them manually. Qt Creator won't do it until you check the corresponding checkbox in Preferences -> Kits -> Cmake. However this checkbox can create unnecessary dirs if you decide to change build dir later.
- Build & run
-
mkdir build && cd build
-
cmake -G "Visual Studio 16 2019" -A Win32 -DQTDIR="C:\dev\Qt\5.15.2\msvc2019" ..
or
cmake -G "Visual Studio 16 2019" -A x64 -DQTDIR="C:\dev\Qt\5.15.2\msvc2019_64" ..
- cmake -- build .
(or run .sln file)
Code style helps to read and edit project easier to all of us. It is not strict policy but more like general recommendations.
Do not use exceptions.
Do not use tabs symbols in code. You can setup your IDE to save tabs as spaces (1 tab is 4 spaces).
Try to declare float variables with f suffix in new code - 1.0f or 1.f instead of 1.0 or 1
Try to avoid copy-paste.
Try to use std containers instead of Qt containers if it is possible. STD containers are more 'clear' than Qt. In some cases you have no choice and should use Qt container (if you want to use QStringList as Q_PROPERTY for example).
Recommended class field prefix is m_*, but try to keep the same style if some class has other prefix.
We often use _* as prefix. It is a bit dangerous however.
С++ has some restrictions for underscore prefix usage by standard. _* is reserved to use in global namespace.
In ANY namespace standard reserves _*_ (2 underscores prefix) and _A* (underscore + any capital letter) for compiler internal usage so you should never use them.
Try to give significant names to variables and functions and avoid short names (except some obvious one like x,y, etc).
Common prefix for all classes/structs is ld*. If some class is strictly connected to one mini-app, you can use app name as second prefix - ldTunes*, ldClock*, but app name can be changed later and we should be careful with it. Many classes are started with ldVisualizer* by historical reason but not related to Visualizer app.
I used *WindowLogic classes before but it is better to avoid them and use plain good-structured objects in QML directly. QQmlHelpers library has some very useful macros for properties.
Recommended class member order: public, public slots, signals, protected slots, protected, private slots, private. In each section order is: enum, static functions, constructor, functions, fields. Static fields should be avoided generally.
From common to local:
<C++ std module>
<Qt Module with explicit submodule>
<Windows/mac/linux specific>
<3rdparty library>
<ldCore/../..>
"LaserdocVisualizer/../.."
"Subfolder/ldClass.h"
Try to sort includes in each include subgroup in alphabetical order.
Class forward declarations are preferred to Include directives.
in .cpp file the first inlcude should be current ".h" file
When it is possible try to use C++11 syntax for with iterators, e.g for(const ldClass &myClass : myClasses) instead of index-based for. It helps to avoid unnecessary variable for index in most cases and easier to read. If you need index than use old-style for for sure. An try to avoid index names like i, j, k.
Pass all classes/strucs in functions by const reference and try to use const reference whenever it is possible for huge data. If some function doesn't change class field and shouldn't do it in future by design mark it as const.
enum class syntax from C++11 is preferrable instead of old-style enum. However old-style enum is good to use as flag with Q_FLAG. The advantage of enum class that you should explicitly cast it to int using ldEnumHelper::asInteger and that you shouldn't worry about namespace - you always should use ClassName::EnumName::EnumValue syntax and can't have issues with ClassName::EnumValue. For any enum try to avoid if-else long trees and use switch(){} instead.
In new code use C++11 nullptr keyword. It's better than NULL or 0 because you can't compare 'nullptr' with int type, only with pointer.
Use C++11 style of variable initialization if it is possible - in *.h file. If something is initialized from constructor then initialize it in constructor declaration. And initialize field in constructor itself if you don't have other options. Also we should try to avoid classes with fields without default values, we use them quite often now but it looks weird because you can't rely on default constructor.
Use auto keyword only for iterators and lambdas.
Try to avoid using keywords delete / free and any manul memory operations. Prefer to use std::unique_ptr, std::shared_ptr or Qt parent-based object system.
Need to be discussed. Currently we have mess with QString and std::string, char* sometimes.
char* should be avoided in modern C++ code generally. There is no any reason to use it for your code. Use it only when you need to pass it somewhere to 3rdparty library and there is no choice.
QString is faster, has more functions and easier to use. So it is recommended string.
The only reason not to use it is if you don't want to restrict your class to Qt library and std::string is enough for you. In this cases std::string looks ok since you can always convert it to/from QString with one line. Sometimes we have mess as the result with many convertions and it looks ugly so try to use one string in the scope.
QFileInfo::completeSuffix and QFileInfo::baseName shouldn't be used in general because they don't work as you can expect it if filename has other "." symbols. They can be used only for internal data even in theory and should never be used for any file with a custom name. QFileInfo::suffix and QFileInfo::completeBaseName are ok.