### Install QuickFlux Manually (without qpm) Source: https://github.com/benlau/quickflux/blob/master/README.md Instructions for installing QuickFlux by manually including the project files in your source tree. It involves adding a .pri file to your project and importing the library in QML. ```makefile include(quickflux/quickflux.pri) # Modify path as needed import QuickFlux 1.0 ``` -------------------------------- ### Install QuickFlux with qpm Package Manager Source: https://github.com/benlau/quickflux/blob/master/README.md This snippet shows how to install the QuickFlux library using the qpm package manager, including adding the include path to your project file and importing the library in QML. ```bash $qpm install com.github.benlau.quickflux include(vendor/vendor.pri) import QuickFlux 1.0 ``` -------------------------------- ### CMake Project Setup and Dependencies Source: https://github.com/benlau/quickflux/blob/master/examples/todo/CMakeLists.txt Configures the CMake build for the 'todo' project, specifying minimum version, project name, and enabling verbose build output. It finds and requires necessary Qt5 modules (Qml, Gui, Core, Quick). ```cmake cmake_minimum_required(VERSION 3.1.0) project(todo) set(CMAKE_VERBOSE_MAKEFILE ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) find_package(Qt5Qml CONFIG REQUIRED) find_package(Qt5Gui CONFIG REQUIRED) find_package(Qt5Core CONFIG REQUIRED) find_package(Qt5Quick CONFIG REQUIRED) ``` -------------------------------- ### Structure Main Application Window in QML Source: https://github.com/benlau/quickflux/blob/master/examples/todo/README.md The main QML file sets up the primary window for the application, arranging components like Header, TodoList, and Footer within a `ColumnLayout`. This demonstrates the principle of breaking down the UI into smaller, manageable pieces and achieving a loosely coupled design by avoiding direct signal propagation between these components. ```qml Window { width: 480 height: 640 visible: true ColumnLayout { anchors.fill: parent anchors.leftMargin: 16 anchors.rightMargin: 16 Header { Layout.fillWidth: true Layout.fillHeight: false } TodoList { Layout.fillWidth: true Layout.fillHeight: true } Footer { Layout.fillWidth: true Layout.fillHeight: false } } } ``` -------------------------------- ### Create Actions with AppActions in QML Source: https://github.com/benlau/quickflux/blob/master/examples/todo/README.md AppActions acts as an action creator, a helper component to create and dispatch actions through the central dispatcher. It depends only on AppDispatcher and has no knowledge of the data model or its consumers. Actions are dispatched via the `dispatch()` function. ```qml // Example usage within a QML file (assuming AppActions is imported and available) // AppActions.addTask("Buy groceries"); // AppActions.setTaskDone(taskId, true); // AppActions.setShowCompletedTasks(false); ``` -------------------------------- ### Source Files and External Project Integration Source: https://github.com/benlau/quickflux/blob/master/examples/todo/CMakeLists.txt Defines the source files for the 'todo' executable and integrates 'QuickFlux' as an external project using `ExternalProject_Add`. This allows the project to fetch, build, and install QuickFlux dependencies. ```cmake set(todo_SRCS main.cpp qml.qrc ) include(ExternalProject) ExternalProject_Add(QuickFlux PREFIX "${PROJECT_BINARY_DIR}/QuickFlux-build" SOURCE_DIR "${PROJECT_SOURCE_DIR}/../.." CMAKE_ARGS "-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}" "-DCMAKE_INSTALL_PREFIX=${PROJECT_BINARY_DIR}/QuickFlux" "-DCMAKE_INSTALL_LIBDIR=${PROJECT_BINARY_DIR}/QuickFlux/lib" "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}" ) ``` -------------------------------- ### Define Action Types in QML Source: https://github.com/benlau/quickflux/blob/master/examples/todo/README.md Defines a constant table (singleton component) for storing all available action types used in the application. This helps in centralizing action names and avoiding naming conflicts. It relies on Quickflux's KeyTable for key-value storage. ```qml pragma Singleton import QtQuick 2.0 import QuickFlux 1.0 KeyTable { // KeyTable is an object with properties equal to its key name property string addTask; property string setTaskDone; property string setShowCompletedTasks; } ``` -------------------------------- ### Create Application RootStore Singleton in QML Source: https://context7.com/benlau/quickflux/llms.txt Implements a singleton RootStore that binds to AppDispatcher and aggregates child stores. Provides direct data binding examples for ListView and UI controls accessing MainStore. Serves as single source of truth for application state with automatic action propagation to child stores. ```qml // stores/RootStore.qml import QtQuick 2.0 import QuickFlux 1.1 Store { id: rootStore // Bind to AppDispatcher to receive all actions bindSource: AppDispatcher // Child stores automatically receive dispatched actions property alias todo: todoStore TodoStore { id: todoStore } property alias userPrefs: userPrefsStore UserPrefsStore { id: userPrefsStore } property alias ui: uiStore UIStore { id: uiStore } } // stores/MainStore.qml (singleton wrapper) pragma Singleton import QtQuick 2.0 import QuickFlux 1.1 RootStore { bindSource: AppDispatcher } // Usage in views - direct data binding import "../stores" ListView { model: MainStore.todo.model delegate: ItemDelegate { text: model.title checkState: model.done ? Qt.Checked : Qt.Unchecked onClicked: { AppActions.setTaskDone(model.uid, !model.done); } } } Text { text: "Total tasks: " + MainStore.todo.model.count } CheckBox { checked: MainStore.userPrefs.showCompleted text: "Show completed tasks" onCheckedChanged: { AppActions.setShowCompleted(checked); } } ``` -------------------------------- ### Manage State with UserPrefsStore in QML Source: https://github.com/benlau/quickflux/blob/master/examples/todo/README.md UserPrefsStore is a QML component that extends Quickflux's `Store` to manage application data and state. It defines properties like `showCompletedTasks` and uses a `Filter` to react to specific action types (`ActionTypes.setShowCompletedTasks`) dispatched by the central dispatcher, updating its state accordingly. ```qml import QtQuick 2.0 import QuickFlux 1.1 import "../actions" Store { property bool showCompletedTasks: false Filter { // Views do not write to showCompeletedTasks directly. // It asks AppActions.setShowCompletedTasks() to do so. type: ActionTypes.setShowCompletedTasks onDispatched: { showCompletedTasks = message.value; } } } ``` -------------------------------- ### Dispatch Actions from UI Events in QML Source: https://github.com/benlau/quickflux/blob/master/examples/todo/README.md This QML snippet shows how to handle UI events, such as a checkbox changing its state, by dispatching actions through `AppActions`. Instead of directly manipulating state or querying other components, the UI 'tells' the system what action to perform (e.g., `setTaskDone`), adhering to the 'Tell, Don't Ask' design principle for better traceability and testability. ```qml // Example within a QML component like Header.qml or TodoItem.qml // Assuming 'uid' and 'checked' are available properties or variables onCheckedChanged: { AppActions.setTaskDone(uid,checked); } ``` -------------------------------- ### Hydrate Store State Source: https://github.com/benlau/quickflux/wiki/Roadmap Example of using Hydrate to serialize and deserialize store states. This functionality enables taking snapshots of store data and restoring them, useful for UI state management and testing different application states. ```JavaScript var snapshot = Hydrate.dehydrate(MainStore); // Convert the data field of MainStore into a JSON object ... Hydrate.rehydrate(MainStore, snapshot1); // ... Hydrate.rehydrate(MainStore, snapshot2); ``` -------------------------------- ### QML Middleware for Navigation and Logging Source: https://context7.com/benlau/quickflux/llms.txt Defines QML middleware components for intercepting actions. NavigationMiddleware handles navigation actions by interacting with a StackView, while LoggerMiddleware logs all dispatched actions. These examples demonstrate how to filter and process actions before they are passed to stores or the next middleware in the chain. ```qml // middlewares/NavigationMiddleware.qml import QtQuick 2.0 import QuickFlux 1.1 Middleware { filterFunctionEnabled: true property var stack // Set from main.qml function dispatch(type, message) { // Intercept navigation actions if (type === ActionTypes.navigateTo) { stack.push(message.item, message.properties); return; // Stop propagation } if (type === ActionTypes.navigateBack) { stack.pop(); return; } // Pass through to next middleware/stores next(type, message); } } ``` ```qml // middlewares/LoggerMiddleware.qml Middleware { filterFunctionEnabled: true function dispatch(type, message) { console.log("[Action]", type, JSON.stringify(message)); next(type, message); // Always pass through for logging } } ``` ```qml // main.qml - Apply middleware to ActionCreator import QtQuick 2.0 import QuickFlux 1.1 import "actions" import "middlewares" ApplicationWindow { StackView { id: stackView } MiddlewareList { applyTarget: AppActions LoggerMiddleware { } NavigationMiddleware { stack: stackView } DialogMiddleware { } } } ``` -------------------------------- ### QML ActionCreator - Signal-based Action Dispatching Source: https://context7.com/benlau/quickflux/llms.txt Implements a clean API for triggering actions using QML's ActionCreator. Signals defined in an ActionCreator component are automatically converted into dispatcher actions. The signal name becomes the action type, and its parameters become the action's message properties. The example demonstrates how to define signals and use them in UI components to dispatch actions. ```qml // actions/AppActions.qml pragma Singleton import QtQuick 2.0 import QuickFlux 1.1 ActionCreator { // Signals automatically become dispatcher actions // Signal name becomes action type // Parameters become message properties signal addTask(string title) signal setTaskDone(var uid, bool done) signal deleteTask(var uid) signal updateTaskTitle(var uid, string newTitle) signal setFilter(string filterType) } // Usage in views/components import "../actions" Button { text: "Add Task" onClicked: { // Call signal - automatically dispatches action AppActions.addTask("New task from button"); } } TextField { id: taskInput onAccepted: { AppActions.addTask(taskInput.text); taskInput.text = ""; } } CheckBox { checked: model.done onCheckedChanged: { AppActions.setTaskDone(model.uid, checked); } } ``` -------------------------------- ### QML ActionTypes - Type-Safe Action Constants Source: https://context7.com/benlau/quickflux/llms.txt Defines type-safe action constants using QML's KeyTable component. Each property declared in ActionTypes.qml automatically becomes a string constant representing the action type. This promotes consistency and reduces errors when dispatching or listening to actions. The example shows how to import and use these constants in other QML files. ```qml // actions/ActionTypes.qml pragma Singleton import QtQuick 2.0 import QuickFlux 1.0 KeyTable { // Each property is auto-initialized with its name as the value property string addTask // value: "addTask" property string setTaskDone // value: "setTaskDone" property string deleteTask // value: "deleteTask" property string setShowCompleted // value: "setShowCompleted" } // Usage in other files import "actions" Filter { type: ActionTypes.addTask // "addTask" onDispatched: { console.log("Action type:", type); } } ``` -------------------------------- ### CMake Configuration for Quickflux Middleware Source: https://github.com/benlau/quickflux/blob/master/examples/middleware/CMakeLists.txt Sets up the build environment for the Quickflux middleware. It defines the minimum CMake version, project name, includes Qt5 Core, and adds resource files. It also configures the executable and links necessary libraries. ```cmake cmake_minimum_required(VERSION 3.8.2) project(middleware) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) find_package(Qt5Core REQUIRED) include_directories(${Qt5Qml_INCLUDE_DIRS}) include_directories(${Qt5Gui_INCLUDE_DIRS}) #include("${CMAKE_CURRENT_SOURCE_DIR}/../../CMakeLists.txt") # Generate rules for building source files from the resources qt5_add_resources(QRCS qml.qrc) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../ ${CMAKE_CURRENT_BINARY_DIR}/quickflux) message(STATUS "test" ${quickflux_SOURCES}) # Tell CMake to create the middleware executable add_executable(middleware main.cpp ${QRCS} quickflux) #target_link_libraries(middleware ${CMAKE_CURRENT_BINARY_DIR}/quickflux/libquickflux.a) link_directories(quickflux) target_link_libraries(middleware quickflux) qt5_use_modules(middleware Qml Gui) ``` -------------------------------- ### C++ Integration with AppDispatcher Source: https://context7.com/benlau/quickflux/llms.txt Demonstrates how to integrate the AppDispatcher singleton into C++ applications. It shows how to obtain the dispatcher instance, dispatch actions with QVariantMap messages, and listen for dispatched actions using QObject::connect. This allows for seamless communication between C++ backend logic and QML frontend components. ```cpp #include QQmlApplicationEngine engine; QFAppDispatcher* dispatcher = QFAppDispatcher::instance(&engine); // Dispatch action from C++ QVariantMap message; message["title"] = "New Task"; message["priority"] = 1; dispatcher->dispatch("addTask", QJSValue::fromVariant(message)); // Listen to actions from C++ QObject::connect(dispatcher, &QFDispatcher::dispatched, [](QString type, QJSValue message) { if (type == "addTask") { qDebug() << "Task added:" << message.property("title").toString(); } } ); ``` -------------------------------- ### Linking Libraries and Executable Creation Source: https://github.com/benlau/quickflux/blob/master/examples/todo/CMakeLists.txt Sets include and link directories for the QuickFlux library and defines the 'todo' executable. It adds dependencies on the QuickFlux external project and links against both QuickFlux (debug/optimized versions) and Qt5 libraries. ```cmake link_directories("${PROJECT_BINARY_DIR}/QuickFlux/lib") include_directories("${PROJECT_BINARY_DIR}/QuickFlux/include/quickflux") add_executable(todo WIN32 ${todo_SRCS}) add_dependencies(todo QuickFlux) target_link_libraries(todo debug quickfluxd optimized quickflux) target_link_libraries(todo Qt5::Qml Qt5::Gui Qt5::Core Qt5::Quick) ``` -------------------------------- ### Configure Single Singleton Store Source: https://github.com/benlau/quickflux/wiki/Roadmap Shows how to set up a single singleton Store with property aliases for child stores. This pattern provides direct access to specific store components while maintaining the hierarchical structure. ```QML Store { id: rootStore property alias photoAlbum: photoAlbum PhotoAlbumStore { id: photoAlbum } property alias navigationStore: navigation NavigationStore { id: navigation } } ``` -------------------------------- ### Configure Multiple Singleton Stores Source: https://github.com/benlau/quickflux/wiki/Roadmap Demonstrates how to configure a Store component that manages multiple singleton stores. This approach allows grouping related stores under a single parent store component for better organization. ```QML Store { id: bridge stores: [ PhotoAlbumStore, NavigationStore ] } ``` -------------------------------- ### Implement Todo App Main UI in QML Source: https://context7.com/benlau/quickflux/llms.txt This QML code defines the main application window for a Todo app, featuring task input, list view, and footer controls. It demonstrates unidirectional data flow using QuickFlux with middleware chain for logging and validation. Dependencies include QtQuick, QuickFlux, and custom stores/actions/middlewares. ```qml // main.qml import QtQuick 2.12 import QtQuick.Controls 2.12 import QuickFlux 1.1 import "stores" import "actions" import "middlewares" ApplicationWindow { visible: true width: 640 height: 480 title: "Todo App" // Middleware chain MiddlewareList { applyTarget: AppActions LoggerMiddleware { } ValidationMiddleware { } } // Main content ColumnLayout { anchors.fill: parent anchors.margins: 10 // Add task input RowLayout { TextField { id: taskInput Layout.fillWidth: true placeholderText: "Enter new task" onAccepted: { if (text.trim()) { AppActions.addTask(text.trim()); text = ""; } } } Button { text: "Add" onClicked: taskInput.accepted() } } // Task list ListView { Layout.fillWidth: true Layout.fillHeight: true // Direct binding to store model: MainStore.todo.model delegate: ItemDelegate { width: parent.width contentItem: RowLayout { CheckBox { id: checkbox checked: model.done onCheckedChanged: { AppActions.setTaskDone(model.uid, checked); } } Text { Layout.fillWidth: true text: model.title font.strikeout: model.done } Button { text: "×" onClicked: { AppActions.deleteTask(model.uid); } } } } } // Footer controls RowLayout { CheckBox { checked: MainStore.userPrefs.showCompleted text: "Show completed" onCheckedChanged: { AppActions.setShowCompleted(checked); } } Text { Layout.fillWidth: true text: "Total: " + MainStore.todo.model.count } } } // Initialize app Component.onCompleted: { AppActions.startApp(); } } ``` -------------------------------- ### QML AppScript for Manual Login Workflow Source: https://context7.com/benlau/quickflux/llms.txt Demonstrates a QML AppScript for handling a login process. It listens for login success or failure actions, navigates to the home view upon success, or displays an error dialog upon failure. The script also includes a condition to exit if the login is cancelled, ensuring proper workflow management. ```qml // Alternative: Manual script execution AppScript { id: loginScript autoExit: true script: { once(ActionTypes.loginSuccess, function(message) { console.log("Login successful:", message.username); AppActions.navigateTo(homeView); }); once(ActionTypes.loginFailure, function(message) { console.log("Login failed:", message.error); errorDialog.show(message.error); exit(1); }); once(ActionTypes.cancelLogin, exit.bind(this, 0)); } Component.onCompleted: { // Run manually with custom message run({ source: "manual" }); } } ``` -------------------------------- ### QML AppScript for Asynchronous Image Picking Workflow Source: https://context7.com/benlau/quickflux/llms.txt Implements an asynchronous workflow using AppScript for picking an image. It opens a file dialog, waits for user selection, navigates to a preview, and adds the selected photo to a store. The script ensures automatic callback cleanup and guaranteed execution order, exiting when the workflow is complete or cancelled. ```qml // scripts/ImagePickerScript.qml import QtQuick 2.0 import QuickFlux 1.0 import QtQuick.Dialogs 1.0 import "../actions" import "../stores" Item { FileDialog { id: dialog title: "Pick Image" nameFilters: ["Image files (*.jpg *.png)"] } Component { id: imagePreview ImagePreview { } } AppScript { // Trigger: Run when this action is dispatched runWhen: ActionTypes.askToPickPhoto // Cleanup: Auto-terminate and cleanup callbacks when finished autoExit: true script: { // Step 1: Open file dialog dialog.open(); // Step 2: Wait for file selection once(dialog.onAccepted, function() { // Navigate to preview with selected file AppActions.navigateTo(imagePreview, { source: dialog.fileUrl }); }).then(ActionTypes.pickPhoto, function(message) { // Step 3: User confirmed - add to store PhotoStore.add(String(message.url)); AppActions.navigateBack(); }); // Exit conditions - cleanup all callbacks once(dialog.onRejected, exit.bind(this, 0)); once(ActionTypes.navigateBack, exit.bind(this, 0)); once(ActionTypes.cancelPicker, exit.bind(this, 0)); } onStarted: { console.log("Image picker workflow started"); } onFinished: { console.log("Image picker workflow finished:", returnCode); } } } ``` -------------------------------- ### Integrate QuickFlux with CMake Source: https://github.com/benlau/quickflux/blob/master/README.md This code demonstrates how to add QuickFlux as an external project in CMake, configuring build paths, linking libraries, and including necessary headers. It also highlights the need to call `registerQuickFluxQmlTypes()`. ```cmake include(ExternalProject) ExternalProject_Add(QuickFlux PREFIX "${PROJECT_BINARY_DIR}/QuickFlux-build" GIT_REPOSITORY "https://github.com/benlau/quickflux.git" CMAKE_ARGS "-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}" "-DCMAKE_INSTALL_PREFIX=${PROJECT_BINARY_DIR}/QuickFlux" "-DCMAKE_INSTALL_LIBDIR=${PROJECT_BINARY_DIR}/QuickFlux/lib" "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}" ) link_directories("${PROJECT_BINARY_DIR}/QuickFlux/lib") include_directories("${PROJECT_BINARY_DIR}/QuickFlux/include/quickflux") ... add_dependencies( QuickFlux) target_link_libraries( debug quickfluxd optimized quickflux) # Ensure to call registerQuickFluxQmlTypes(); in your C++ code. ``` -------------------------------- ### AppListener: Dispatcher Event Listener with Filtering (QML) Source: https://context7.com/benlau/quickflux/llms.txt AppListener is a Quickflux component for listening to dispatcher messages, offering filtering and dependency management capabilities. It's ideal when the standard Store/Filter pattern is not suitable. It supports single or multiple filters, defining execution order with `waitFor`, and dynamic callback registration at runtime. Dependencies include QuickFlux. ```qml import QtQuick 2.0 import QuickFlux 1.1 import "../actions" Item { // Single filter AppListener { filter: ActionTypes.showNotification onDispatched: { notificationPopup.show(message.text, message.duration); } } // Multiple filters with waitFor AppListener { id: analyticsListener filters: [ ActionTypes.addTask, ActionTypes.deleteTask, ActionTypes.setTaskDone ] onDispatched: { analytics.trackEvent(type, message); } } // Listener with dependency AppListener { // Wait for analyticsListener to process first waitFor: [analyticsListener.listenerId] filter: ActionTypes.addTask onDispatched: { // This executes after analyticsListener console.log("Task added, analytics tracked"); } } // Dynamic callback registration AppListener { id: dynamicListener Component.onCompleted: { // Register callback at runtime on(ActionTypes.customEvent, function(message) { console.log("Custom event:", message); }); // Register another callback on(ActionTypes.anotherEvent, function(message) { console.log("Another event:", message); }); } } } ``` -------------------------------- ### Create Singleton QtObject with signals in QML Source: https://github.com/benlau/quickflux/blob/master/README.md Defines a QML singleton object containing openItem and removeItem signals. It can be imported across the application to dispatch actions via the QuickFlux dispatcher. No external dependencies beyond QtQuick 2.2 are required. ```QML import QtQuick 2.2 pragma Singleton QtObject { signal openItem(string id); signal removeItem(string id); } ``` -------------------------------- ### Create User Preferences Store in QML Source: https://context7.com/benlau/quickflux/llms.txt This QML store manages user preferences like showing completed tasks. It uses QuickFlux Store and Filter to handle actions for updating preferences. No external dependencies beyond QuickFlux and custom actions. ```qml // stores/UserPrefsStore.qml import QuickFlux 1.1 import "../actions" Store { property bool showCompleted: true Filter { type: ActionTypes.setShowCompleted onDispatched: { showCompleted = message.value; } } } ``` -------------------------------- ### Match Actions with QuickFlux Filter Components Source: https://context7.com/benlau/quickflux/llms.txt Demonstrates declarative action filtering by type using QuickFlux Filter component. Shows single type matching and multiple type handling with conditional logic. Updates store properties based on dispatched actions and provides access to matched action type in callback. ```qml // Multiple filter types Store { property bool showCompleted: true property string currentFilter: "all" Filter { type: ActionTypes.setShowCompleted onDispatched: { showCompleted = message.value; } } Filter { types: [ ActionTypes.showAllTasks, ActionTypes.showActiveTasks, ActionTypes.showCompletedTasks ] onDispatched: { // type contains the matched action type if (type === ActionTypes.showAllTasks) { currentFilter = "all"; } else if (type === ActionTypes.showActiveTasks) { currentFilter = "active"; } else if (type === ActionTypes.showCompletedTasks) { currentFilter = "completed"; } } } } ``` -------------------------------- ### Implement Logger Middleware in QML Source: https://context7.com/benlau/quickflux/llms.txt This middleware logs all dispatched actions with timestamps for debugging. It extends QuickFlux Middleware and calls next() to continue the action chain. No inputs or outputs; it operates passively on the dispatch flow. ```qml // middlewares/LoggerMiddleware.qml import QuickFlux 1.1 Middleware { filterFunctionEnabled: true function dispatch(type, message) { var timestamp = new Date().toISOString(); console.log("[" + timestamp + "]", type, JSON.stringify(message)); next(type, message); } } ``` -------------------------------- ### Implement Todo Data Store with QML QuickFlux Source: https://context7.com/benlau/quickflux/llms.txt Creates a hierarchical data store using QuickFlux Store component with ListModel. Handles addTask, setTaskDone, and deleteTask actions through Filter components. Automatically increments UIDs and updates todo model state based on messages from AppDispatcher. ```qml // stores/TodoStore.qml import QtQuick 2.0 import QuickFlux 1.1 import "../actions" Store { property alias model: todoModel property int nextUid: 1 ListModel { id: todoModel // Initial data ListElement { uid: 0 title: "First Task" done: false } } // Filter listens for specific action types Filter { type: ActionTypes.addTask onDispatched: { // message contains signal parameters todoModel.append({ uid: nextUid++, title: message.title, done: false }); } } Filter { type: ActionTypes.setTaskDone onDispatched: { for (var i = 0; i < todoModel.count; i++) { if (todoModel.get(i).uid === message.uid) { todoModel.setProperty(i, "done", message.done); break; } } } } Filter { type: ActionTypes.deleteTask onDispatched: { for (var i = 0; i < todoModel.count; i++) { if (todoModel.get(i).uid === message.uid) { todoModel.remove(i); break; } } } } } ``` -------------------------------- ### Hydrate: Serialize and Deserialize Store State (QML) Source: https://context7.com/benlau/quickflux/llms.txt The Hydrate utility in Quickflux allows for serializing (dehydrate) and deserializing (rehydrate) Store components to and from JSON. This is useful for persisting application state or for testing purposes. It integrates with Qt's Settings for saving state and handles auto-saving on application exit and auto-restoring on startup. Dependencies include QuickFlux and Qt.labs.settings. ```qml import QtQuick 2.0 import QuickFlux 1.1 import Qt.labs.settings 1.0 import "../stores" Item { // Save application state Button { text: "Save State" onClicked: { // Dehydrate extracts all properties from store var snapshot = Hydrate.dehydrate(MainStore); // Save to localStorage/settings settings.stateSnapshot = JSON.stringify(snapshot); console.log("State saved:", JSON.stringify(snapshot, null, 2)); } } // Restore application state Button { text: "Restore State" onClicked: { try { var snapshot = JSON.parse(settings.stateSnapshot); // Rehydrate loads properties into store Hydrate.rehydrate(MainStore, snapshot); console.log("State restored"); } catch(e) { console.error("Failed to restore state:", e); } } } // Reset to default state Button { text: "Reset State" onClicked: { var defaultState = { todo: { model: [], nextUid: 0 }, userPrefs: { showCompleted: true, filterType: "all" } }; Hydrate.rehydrate(MainStore, defaultState); } } Settings { id: settings property string stateSnapshot: "" } // Auto-save on application exit Connections { target: Qt.application onAboutToQuit: { var snapshot = Hydrate.dehydrate(MainStore); settings.stateSnapshot = JSON.stringify(snapshot); } } // Auto-restore on startup Component.onCompleted: { if (settings.stateSnapshot) { try { var snapshot = JSON.parse(settings.stateSnapshot); Hydrate.rehydrate(MainStore, snapshot); } catch(e) { console.error("Failed to restore previous state:", e); } } } } ``` -------------------------------- ### Create Validation Middleware in QML Source: https://context7.com/benlau/quickflux/llms.txt This middleware validates actions before dispatching, blocking invalid ones like adding tasks without titles. It uses QuickFlux Middleware and checks action types. Limitations: Only validates addTask; does not handle other actions. ```qml // middlewares/ValidationMiddleware.qml import QuickFlux 1.1 import "../actions" Middleware { filterFunctionEnabled: true function dispatch(type, message) { if (type === ActionTypes.addTask) { if (!message.title || message.title.trim() === "") { console.error("Validation failed: Task title cannot be empty"); return; // Block action } } next(type, message); } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.