{"id":14982643,"url":"https://github.com/carlonluca/lqtutils","last_synced_at":"2025-04-10T02:26:21.256Z","repository":{"id":67318955,"uuid":"267307637","full_name":"carlonluca/lqtutils","owner":"carlonluca","description":"Basic Qt tools to speed up writing Qt app for Windows/MacOS/Linux/Android/iOS.","archived":false,"fork":false,"pushed_at":"2024-10-13T00:00:48.000Z","size":1322,"stargazers_count":58,"open_issues_count":1,"forks_count":14,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-10-13T01:21:02.014Z","etag":null,"topics":["qml","qobject","qt","qt5","qt6","utils"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/carlonluca.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-05-27T12:01:11.000Z","updated_at":"2024-10-13T00:00:51.000Z","dependencies_parsed_at":"2023-12-01T23:30:22.520Z","dependency_job_id":"365beeed-1d81-48cc-865e-cd2490de8191","html_url":"https://github.com/carlonluca/lqtutils","commit_stats":{"total_commits":233,"total_committers":2,"mean_commits":116.5,"dds":0.01716738197424894,"last_synced_commit":"22f2c9b736a41a19a73bcccb5e9fd707acb87cc3"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carlonluca%2Flqtutils","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carlonluca%2Flqtutils/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carlonluca%2Flqtutils/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carlonluca%2Flqtutils/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/carlonluca","download_url":"https://codeload.github.com/carlonluca/lqtutils/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248143701,"owners_count":21054825,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["qml","qobject","qt","qt5","qt6","utils"],"created_at":"2024-09-24T14:05:47.901Z","updated_at":"2025-04-10T02:26:21.226Z","avatar_url":"https://github.com/carlonluca.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# LQtUtils\nThis is a module containing a few tools that I typically use in Qt apps. Using this module in your app is simple: add a submodule to your git repo and include the headers. Most of the code is in independent headers, so you don't need to build anything separately.\nA couple of headers need the related source file to be compiled explicitly; in that case I typically add this project as a submodule and link to my main project file.\n\nMore articles related to these topics: https://bugfreeblog.duckdns.org/tag/lqtutils.\n\n## Index\n\n- [How to Include](#how-to-include)\n- [Synthesize Qt properties in a short way (lqtutils_prop.h)](#synthesize-qt-props)\n- [Synthesize Qt enums and quickly expose to QML (lqtutils_enum.h)](#synthesize-qt-enums)\n- [Synthesize Qt settings with support for signals (lqtutils_settings.h)](#synthesize-qt-settings)\n- [Cache values and init automatically](#cache-values)\n- [Threading tools](#threading)\n- [Auto execute actions when exiting a scope (lqtutils_autoexec.h)](#autoexec)\n- [Measuring rate](#measure-rate)\n- [Measuring framerate](#measure-framerate)\n- [Showing Local Notifications](#local-notifications)\n- [Single shot timer for QML (lqtutils_ui.h)](#singleshot-qml)\n- [Getting safe areas on mobile](#safe-areas)\n- [Measure Performance (lqtutils_perf.h)](#measure-performance)\n- [Blocking Queue for qt (lqtutils_bqueue.h)](#blocking-queue)\n- [Download a File with Progress Notifications (lqtutils_net.h)](#download-file)\n- [FontAwesome in QML](#fontawesome)\n- [Compute total and available RAM (lqtutils_system.h) [Linux only]](#available-ram)\n\n\u003ca id=\"how-to-include\"\u003e\u003c/a\u003e\n## How to Include\n\nTo include in a qmake app:\n\n```\ninclude(lqtutils/lqtutils.pri)\n```\n\nTo include in a cmake app in Qt6:\n\n```\nadd_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/deps/lqtutils)\ntarget_link_libraries(yourproj lqtutilsplugin)\n```\n\nNOTE: the name of the library to link is `lqtutilsplugin`, not just `lqtutils`.\n\nTo include in a cmake app in Qt5:\n\n```\ninclude(${CMAKE_CURRENT_SOURCE_DIR}/deps/lqtutils/CMakeLists_qt5.txt)\ntarget_link_libraries(LQtUtilsTest PRIVATE lqtutils)\n```\n\n\u003ca id=\"synthesize-qt-props\"\u003e\u003c/a\u003e\n## Synthesize Qt properties in a short way (lqtutils_prop.h)\n**For more info: https://bugfreeblog.duckdns.org/2020/05/synthesize-qt-properties.html.**\n\nContains a few useful macros to synthesize Qt props. For instance:\n```c++\nclass Fraction : public QObject\n{\n    Q_OBJECT\n    L_RW_PROP(double, numerator, setNumerator, 5)\n    L_RW_PROP(double, denominator, setDenominator, 9)\npublic:\n    Fraction(QObject* parent = nullptr) : QObject(parent) {}\n};\n```\ninstead of:\n```c++\nclass Fraction : public QObject\n{\n    Q_OBJECT\n    Q_PROPERTY(double numerator READ numerator WRITE setNumerator NOTIFY numeratorChanged)\n    Q_PROPERTY(double denominator READ denominator WRITE setDenominator NOTIFY denominatorChanged)\npublic:\n    Fraction(QObject* parent = nullptr) :\n        QObject(parent),\n        m_numerator(5),\n        m_denominator(9)\n        {}\n\n    double numerator() const {\n        return m_numerator;\n    }\n\n    double denominator() const {\n        return m_denominator;\n    }\n\npublic slots:\n    void setNumerator(double numerator) {\n        if (m_numerator == numerator)\n            return;\n        m_numerator = numerator;\n        emit numeratorChanged(numerator);\n    }\n\n    void setDenominator(double denominator) {\n        if (m_denominator == denominator)\n            return;\n        m_denominator = denominator;\n        emit denominatorChanged(denominator);\n    }\n\nsignals:\n    void numeratorChanged(double numerator);\n    void denominatorChanged(double denominator);\n\nprivate:\n    double m_numerator;\n    double m_denominator;\n};\n```\nWhen the QObject subclass is not supposed to have a particular behavior, the two macros L_BEGIN_CLASS and L_END_CLASS can speed up the declaration even more:\n```c++\nL_BEGIN_CLASS(Fraction)\nL_RW_PROP(double, numerator, setNumerator, 5)\nL_RW_PROP(double, denominator, setDenominator, 9)\nL_END_CLASS\n```\nThe L_RW_PROP and L_RO_PROP macros are overloaded, and can therefore be used with three or four params. The last param is used if you want to init the prop to some specific value automatically.\n\nThis makes the usage of Qt properties more synthetic and speeds up the development. It is very useful when many properties are needed to expose data to QML.\n\n### References\n\nIf you need to be able to modify the property itself from C++ instead of resetting it, you can use the *_REF alternatives of L_RW_PROP and L_RO_PROP. In that case, getter methods return a reference to the type in C++.\n\n### Signals With or Without Parameters\n\nBy default, signals are generated with the value passed in the argument. If you prefer signals without params, you can define LQTUTILS_OMIT_ARG_FROM_SIGNAL **before** including the header.\n\n### Autosetter\n\nIt is also possible to omit the name of the setter in the declaration. This results in the auto-generation of a setter with the name \"set_\u003cproperty name\u003e\". To obtain this behavior, simply use the variants of the above macros with the suffix \"_AS\". This should work for all property types: ro, rw, ref and all gadget props.\n\n### Custom Setter\n\nIt is possible to generate a property without its setter implementation. The setter con be implemented with a slot explicitly by writing a method named \"set_\u003cpropname\u003e\" returning void. An example can be found [here](lqtutils/tst_lqtutils.cpp#L52).\n\n### Complete List of Available Macros\n\nFor QObjects:\n\n    L_RW_PROP(type, name, setter)\n    L_RW_PROP(type, name, setter, default)\n    L_RW_PROP_AS(type, name)\n    L_RW_PROP_AS(type, name, default)\n    L_RW_PROP_CS(type, name)\n    L_RW_PROP_CS(type, name, default)\n    L_RW_PROP_REF(type, name, setter)\n    L_RW_PROP_REF(type, name, setter, default)\n    L_RW_PROP_REF_AS(type, name)\n    L_RW_PROP_REF_AS(type, name, default)\n    L_RW_PROP_REF_CS(type, name)\n    L_RW_PROP_REF_CS(type, name, default)\n    L_RO_PROP(type, name, setter)\n    L_RO_PROP(type, name, setter, default)\n    L_RO_PROP_AS(type, name)\n    L_RO_PROP_AS(type, name, default)\n    L_RO_PROP_CS(type, name)\n    L_RO_PROP_CS(type, name, default)\n    L_RO_PROP_REF(type, name, setter)\n    L_RO_PROP_REF(type, name, setter, default)\n    L_RO_PROP_REF_AS(type, name)\n    L_RO_PROP_REF_AS(type, name, default)\n    L_RO_PROP_REF_CS(type, name)\n    L_RO_PROP_REF_CS(type, name, default)\n    L_BEGIN_CLASS(name)\n    L_END_CLASS\n\nFor gadgets:\n\n    L_RW_GPROP(type, name, setter)\n    L_RW_GPROP(type, name, setter, default)\n    L_RW_GPROP_AS(type, name)\n    L_RW_GPROP_AS(type, name, default)\n    L_RW_GPROP_CS(type, name)\n    L_RW_GPROP_CS(type, name, default)\n    L_RO_GPROP(type, name, setter)\n    L_RO_GPROP(type, name, setter, default)\n    L_RO_GPROP_AS(type, name)\n    L_RO_GPROP_AS(type, name, default)\n    L_RO_GPROP_CS(type, name)\n    L_RO_GPROP_CS(type, name, default)\n    L_BEGIN_GADGET(name)\n    L_END_GADGET\n\n\u003ca id=\"synthesize-qt-settings\"\u003e\u003c/a\u003e\n## Synthesize Qt settings with support for signals (lqtutils_settings.h)\n**For more info: https://bugfreeblog.duckdns.org/2023/01/lqtutils-settings.html.**\n\nContains a few tools that can be used to speed up writing simple settings to a file. Settings will still use QSettings and are therefore fully compatible. The macros are simply shortcuts to synthetise code. I only used this for creating ini files, but should work for other formats. An example:\n```c++\nL_DECLARE_SETTINGS(LSettingsTest, new QSettings(\"settings.ini\", QSettings::IniFormat))\nL_DEFINE_VALUE(QString, string1, QString(\"string1\"))\nL_DEFINE_VALUE(QSize, size, QSize(100, 100))\nL_DEFINE_VALUE(double, temperature, -1)\nL_DEFINE_VALUE(QByteArray, image, QByteArray())\nL_END_CLASS\n\nL_DECLARE_SETTINGS(LSettingsTestSec1, new QSettings(\"settings.ini\", QSettings::IniFormat), \"SECTION_1\")\nL_DEFINE_VALUE(QString, string2, QString(\"string2\"))\nL_END_CLASS\n```\nThis will provide an interface to a \"strong type\" settings file containing a string, a QSize value, a double, a jpg image and another string, in a specific section of the ini file. Each class is reentrant like QSettings and can be instantiated in multiple threads.\nEach class also provides a unique notifier: the notifier can be used to receive notifications when any thread in the code changes the settings, and can also be used in bindings in QML code. For an example, refer to LQtUtilsQuick:\n```c++\nWindow {\n    visible: true\n    x: settings.appX\n    y: settings.appY\n    width: settings.appWidth\n    height: settings.appHeight\n    title: qsTr(\"Hello World\")\n\n    Connections {\n        target: settings\n        onAppWidthChanged:\n            console.log(\"App width saved:\", settings.appWidth)\n        onAppHeightChanged:\n            console.log(\"App width saved:\", settings.appHeight)\n    }\n\n    Binding { target: settings; property: \"appWidth\"; value: width }\n    Binding { target: settings; property: \"appHeight\"; value: height }\n    Binding { target: settings; property: \"appX\"; value: x }\n    Binding { target: settings; property: \"appY\"; value: y }\n}\n```\n\n\u003ca id=\"synthesize-qt-enums\"\u003e\u003c/a\u003e\n## synthesize Qt enums and quickly expose to QML (lqtutils_enum.h)\n**For more info: https://bugfreeblog.duckdns.org/2020/06/synthesizing-qt-settings.html.**\n\nContains a macro to define a enum and register it with the meta-object system. This enum can then be exposed to the QML. To create the enum simply do:\n```c++\nL_DECLARE_ENUM(MyEnum,\n               Value1 = 1,\n               Value2,\n               Value3)\n```\nThis enum is exposed using a namespace without subclassing QObject. Register with the QML engine with:\n```c++\nMyEnum::registerEnum(\"com.luke\", 1, 0);\n```\n\n\u003ca id=\"cache-values\"\u003e\u003c/a\u003e\n## Cache values and init automatically\n```lqt::CacheValue``` caches values of any type in a hash and calls the provided lambda if the value was never initialized. This is useful when writing settings classes and you want to read only once.\n\n\u003ca id=\"threading\"\u003e\u003c/a\u003e\n## Threading tools (lqtutils_threading.h)\n```lqt::RecursiveMutex``` is a simple QMutex subclass defaulting to recursive mode.\n\n```INVOKE_AWAIT_ASYNC``` is a wrapper around QMetaObject::invokeMethod that allows to execute a slot or lambda in the thread of an obj, synchronously awaiting for the result. E.g.:\n```c++\nQThread* t = new QThread;\nt-\u003estart();\nQObject* obj = new QObject;\nobj-\u003emoveToThread(t);\nINVOKE_AWAIT_ASYNC(obj, [\u0026i, currentThread, t] {\n    i++;\n    QCOMPARE(t, QThread::currentThread());\n    QVERIFY(QThread::currentThread() != currentThread);\n    QCOMPARE(i, 11);\n});\nQCOMPARE(i, 11);\n```\n\n```lqt_run_in_thread``` runs a lambda in a specific QThread asynchronously.\n\n\u003ca id=\"autoexec\"\u003e\u003c/a\u003e\n## Auto execute actions when exiting a scope (lqtutils_autoexec.h)\nA class that can be used to execute a lambda whenever the current scope ends, e.g.:\n```c++\nint i = 9;\n{\n    lqt::AutoExec autoexec([\u0026] {\n        i++;\n    });\n    QCOMPARE(i, 9);\n}\nQCOMPARE(i, 10);\n```\n\n```lqt::SharedAutoExec```: a class that can create copiable autoexec objects. Useful to implement locks with a function being executed when the lock is released.\n\n\u003ca id=\"measure-rate\"\u003e\u003c/a\u003e\n## Measuring rate (lqtutils_freq.h)\n\n```lqt::FreqMeter``` is a class that allows to measure the rate of any sampling activity. For example the refresh rate (see lqtutils_ui.h) or the rate of some kind of processing.\n\n\u003ca id=\"measure-framerate\"\u003e\u003c/a\u003e\n## Measuring frame rate in QML (lqtutils_ui.h)\n\n**For more info: https://bugfreeblog.duckdns.org/2021/09/measure-framerate-qt.html.**\n\n```lqt::FrameRateMonitor``` is a class that can be used to measure the current frame rate of a QQuickWindow. The class monitors the frequency of frame swaps and provides a property with a value reporting the frame rate during the last second.\n\n\u003ca id=\"local-notifications\"\u003e\u003c/a\u003e\n## Showing Local Notifications\n\nThe `lqt::SystemNotification` and the `lqt::AndroidSystemNotification` objects can be used to show a local notification on Linux, Android, Windows, iOS and MacOS.\n\nExample:\n\n```c++\n#ifdef Q_OS_ANDROID\n    lqt::AndroidSystemNotification notification;\n    notification.set_icon(QImage(\":/qt/qml/FlashbackPrism/assets/icon_96.png\"));\n    notification.set_activityClass(QSL(\"org.qtproject.qt.android.bindings.QtActivity\"));\n#else\n    lqt::SystemNotification notification;\n#endif\n    notification.set_appName(qApp-\u003eapplicationName());\n    notification.set_title(tr(\"Flashbacks available\"));\n    notification.set_message(tr(\"You have %1 memories taken in %2 years for today. Have a look!\").arg(photos).arg(years));\n    notification.set_openApp(true);\n    notification.send();\n```\n\n\u003ca id=\"singleshot-qml\"\u003e\u003c/a\u003e\n## Single shot timer for QML (lqtutils_ui.h)\n\n```c++\nlqt::QmlUtils::singleShot(int msec, QJSValue callback)\n```\n\nUseful to defer an action of a specified amount of milleseconds in QML, without having to create a timer. Example:\n\n```QML\nlqtUtils.singleShot(5000, () =\u003e console.log(\"Hello!\"))\n```\n\nremember to expose lqt::QmlUtils to QML with:\n\n```c++\nengine.rootContext()-\u003esetContextProperty(\"lqtUtils\", new lqt::QmlUtils(qApp));\n```\n\n\u003ca id=\"safe-areas\"\u003e\u003c/a\u003e\n## Getting safe areas on mobile (lqtutils_ui.h)\n\n**For more info: https://bugfreeblog.duckdns.org/2023/01/qt-qml-cutouts.html.**\n\nBoth iOS and Android smartphones may include cutouts and you may want to know where it is safe to draw your QML UI. These four methods are useful to get the safe area both on iOS and Android (on Desktop the methods are still defined and simply return 0).\n\n```c++\nQ_INVOKABLE static double safeAreaBottomInset();\nQ_INVOKABLE static double safeAreaTopInset();\nQ_INVOKABLE static double safeAreaRightInset();\nQ_INVOKABLE static double safeAreaLeftInset();\n```\n\nNote that the methods return a value in logical pixels, so device pixel ratio is already taken into account.\n\nThis is an example of a demo app where some elements extends under the cutouts, while the interactive area does not.\n\n\u003cimg src=\"docs/cutouts.webp\" width=\"20%\"\u003e\u003c/img\u003e\n\n### How to Use\n\nTo use it, simply instantiate it when you need it like this:\n\n```c++\nQQuickView view;\nLQTFrameRateMonitor* monitor = new lqt::FrameRateMonitor(\u0026view);\n```\n\nexpose it to QML if you need it:\n\n```c++\nview.engine()-\u003erootContext()-\u003esetContextProperty(\"fpsmonitor\", monitor);\n```\n\nand use it in QML (or in C++ if you prefer):\n\n```js\nText { text: qsTr(\"fps: \") + fpsmonitor.freq }\n```\n\nIf there have been no updates to the scene, Qt will not redraw it and you will end up with a measurement of ~1fps. If you want to measure how many frames *can* be drawn per second, you can enable automatic frame update triggers via the helper\n\n```c++\nlqt::enableAutoFrameUpdates(view);\n```\n\nwhich causes the window to request an update on every frame swap (that is on every vsync in most cases).\n\n### Details\n\nThe frame rate is provided in a notifiable property of the ```lqt::FrameRateMonitor``` class:\n\n```c++\nL_RO_PROP_AS(int, freq, 0)\n```\n\nNote that this property is defined using the prop macros provided by this library. The property is recomputed when each frame is swapped or after a second. The overhead of the component should be minimal.\n\n\u003ca id=\"measure-performance\"\u003e\u003c/a\u003e\n## Measure Performance (lqtutils_perf.h)\n\n```measure_time``` is a shortcut to quickly measure a procedure provided in a lambda for benchmarking it. The macro ```L_MEASURE_TIME``` can be used to be able to enable/disable the measurement through ```L_ENABLE_BENCHMARKS``` at project level reducing overhead to zero.\n\n### How to Use\n\nThis is an exmaple:\n\n```c++\nmeasure_time([\u0026] {\n    const uchar* rgba = ...\n    for (int x = 0; x \u003c width; x++) {\n        for (int y = 0; y \u003c height; y++) {\n            [process pixel]\n        }\n    }\n}, [] (qint64 time) {\n    qWarning() \u003c\u003c \"Image processed in:\" \u003c\u003c time;\n});\n```\n\n\u003ca id=\"blocking-queue\"\u003e\u003c/a\u003e\n## Blocking Queue for qt (lqtutils_bqueue.h)\n\nThis header contains a simple blocking queue. It allows blocking/nonblocking insertions with timeout, blocking/nonblocking removal and a safe processing of the queue. This is an example of the producer/consumer pattern:\n\n```c++\nstruct LQTTestProducer : public QThread\n{\n    LQTTestProducer(LQTBlockingQueue\u003cint\u003e* queue) : QThread(), m_queue(queue) {}\n    void run() override {\n        static int i = 0;\n        while (!isInterruptionRequested()) {\n            QThread::msleep(10);\n            m_queue-\u003eenqueue(i++);\n            QVERIFY(m_queue-\u003esize() \u003c= 10);\n        }\n    }\n    void requestDispose() {\n        requestInterruption();\n        m_queue-\u003erequestDispose();\n    }\n\nprivate:\n    LQTBlockingQueue\u003cint\u003e* m_queue;\n};\n\nstruct LQTTestConsumer : public QThread\n{\n    LQTTestConsumer(LQTBlockingQueue\u003cint\u003e* queue) : QThread(), m_queue(queue) {}\n    void run() override {\n        static int i = 0;\n        while (!isInterruptionRequested()) {\n            QThread::msleep(15);\n            std::optional\u003cint\u003e ret = m_queue-\u003edequeue();\n            if (!ret)\n                return;\n            QVERIFY(*ret == i++);\n            QVERIFY(lqt_in_range(m_queue-\u003esize(), 0, 11));\n        }\n    }\n    void requestDispose() {\n        requestInterruption();\n        m_queue-\u003erequestDispose();\n    }\n\nprivate:\n    LQTBlockingQueue\u003cint\u003e* m_queue;\n};\n\n[...]\n\nlqt::BlockingQueue\u003cint\u003e queue(10, QSL(\"display_name\"));\nLQTTestConsumer consumer(\u0026queue);\nLQTTestProducer producer(\u0026queue);\nconsumer.start();\nproducer.start();\n\nQEventLoop loop;\nQTimer::singleShot(30*1000, this, [\u0026] { loop.quit(); });\nloop.exec();\n\nproducer.requestDispose();\nproducer.wait();\nconsumer.requestDispose();\nconsumer.wait();\n```\n\n\u003ca id=\"download-file\"\u003e\u003c/a\u003e\n## Download a File with Progress Notifications (lqtutils_net.h)\n\nThe class ```lqt::Downloader``` can be used to download a URL to a file in a background thread. Example:\n\n```c++\nQScopedPointer\u003clqt::Downloader\u003e downloader(new lqt::Downloader(url, filePath));\ndownloader-\u003edownload();\nconnect(downloader.data(), \u0026lqt::Downloader::downloadProgress, this, [\u0026downloader] (qint64 progress, qint64 total) {\n    qDebug() \u003c\u003c \"Downloading:\" \u003c\u003c progress \u003c\u003c \"/\" \u003c\u003c total \u003c\u003c downloader-\u003estate();\n});\nconnect(downloader.data(), \u0026lqt::Downloader::stateChanged, this, [\u0026loop, \u0026downloader] {\n    if (downloader-\u003estate() == lqt::DownloaderState::S_DONE)\n        // Done\n});\n```\n\n## lqtutils_data.h\n\nHash of a file:\n\n```c++\nQByteArray lqt::hash(const QString \u0026fileName,\n                     QCryptographicHash::Algorithm algo = QCryptographicHash::Md5)\n```\n\nWrites a random file of the specified size:\n\n```c++\nbool lqt::random_file(const QString\u0026 fileName, qint64 size)\n```\n\n\u003ca id=\"fontawesome\"\u003e\u003c/a\u003e\n## FontAwesome in QML (lqtutils_fa.h)\n\n**For more info: https://bugfreeblog.duckdns.org/2023/05/fontawesome-qml-lqtutils.html.**\n\nThis header includes a function to load FontAwesome fonts and QML items to render the fonts in QML. To include FontAwesome in Qt6 add the support to your cmake file when including the project:\n\n```cmake\nset(ENABLE_FONT_AWESOME true)\nadd_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lqtutils)\n```\n\nthen init FontAwesome in your main function:\n\n```c++\nlqt::embed_font_awesome(view.engine()-\u003erootContext());\n```\n\nNow types and fonts are loaded. To use it in QML:\n\n```qml\nimport \"qrc:/lqtutils/fontawesome\"\n\n[...]\n\nLQTFontAwesomeFreeSolid {\n    width: 16\n    height: 16\n    iconUtf8: \"\\uf013\"\n}\n```\n\nto ensure the plugin is linked, add these two lines to your main.cpp:\n\n```c++\n#include \u003cQtQml/QQmlExtensionPlugin\u003e\nQ_IMPORT_QML_PLUGIN(lqtutilsPlugin)\n```\n\nNote that the size is mandatory. The available types are: `LQTFontAwesomeFreeSolid`, `LQTFontAwesomeFreeRegular` and `LQTFontAwesomeBrandsRegular`. The init function also set the context properties: `fontAwesomeBrandsRegular`, `fontAwesomeFreeRegular` and `fontAwesomeFreeSolid`. These are QFont instances available in QML.\n\n\u003ca id=\"available-ram\"\u003e\u003c/a\u003e\n## Compute total and available RAM (lqtutils_system.h) [Linux only]\n\n**For more info: https://bugfreeblog.duckdns.org/2024/01/computing-total-and-free-ram-in-linux-with-qt.html.**\n\nThis header includes a function to compute the total available RAM and the RAM potentially allocatable.\n\n```c++\nstd::optional\u003clqt::MemData\u003e mem = lqt::read_mem_data();\nif (!mem)\n    return;\nqInfo() \u003c\u003c \"Total:\" \u003c\u003c mem-\u003etotalMemBytes;\nqInfo() \u003c\u003c \"Free :\" \u003c\u003c mem-\u003efreeMemBytes;\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcarlonluca%2Flqtutils","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcarlonluca%2Flqtutils","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcarlonluca%2Flqtutils/lists"}