qleany 1.7.2

Architecture generator for Rust and C++/Qt applications.
import { VerticalBox, HorizontalBox, ProgressIndicator, ScrollView } from "std-widgets.slint";
import { HomeTab } from "tabs/HomeTab.slint";
import { ProjectTab } from "tabs/ProjectTab.slint";
import { EntitiesTab } from "tabs/EntitiesTab.slint";
import { FeaturesTab } from "tabs/FeaturesTab.slint";
import { UserInterfaceTab } from "tabs/UserInterfaceTab.slint";
import { GenerateTab } from "tabs/GenerateTab.slint";
import { ConfirmationDialog } from "components/confirmation_dialog.slint";
import { NewManifestWizard } from "components/new_manifest_wizard.slint";
import { DemoWizard } from "components/demo_wizard.slint";
import { StyledButton } from "components/misc.slint";
import { CheckWidget } from "components/check_widget.slint";

// Import and export globals for Rust access
import { ManifestCommands, UndoRedoCommands, GenerateCommands, ProjectTabState, EntitiesTabState, FeaturesTabState, UserInterfaceTabState, AppState, CheckState, CommonTools, NewManifestWizardState, DemoWizardState } from "globals.slint";
export { ManifestCommands, UndoRedoCommands, GenerateCommands, ProjectTabState, EntitiesTabState, FeaturesTabState, UserInterfaceTabState, AppState, CheckState, CommonTools, NewManifestWizardState, DemoWizardState }

// Custom NavItem component for sidebar navigation
component NavItem inherits Rectangle {
    in property <bool> active: false;
    in property <string> label;
    in property <image> icon;
    in property <bool> enable: true;
    callback clicked();

    height: 48px;
    background: active ? #228be6 : transparent;
    border-radius: 8px;

    HorizontalLayout {
        padding: 12px;
        spacing: 12px;

        Image {
            source: icon;
            width: 24px;
            height: 24px;
            colorize: active ? #ffffff : enable? #495057 : #adb5bd;
        }

        Text {
            text: label;
            color: active ? #ffffff :  enable? #495057 : #adb5bd;
            font-size: 14px;
            vertical-alignment: center;
        }
    }

    TouchArea {
        clicked => { root.clicked(); }
        enabled: enable;
    }
}

export component App inherits Window {
    title: AppState.manifest_is_open ? (AppState.manifest_path == "" ? "Qleany - new manifest without path" : "Qleany - " + AppState.manifest_path) : "Qleany";
    min-width: 1400px;
    min-height: 800px;


    // All state and callbacks are now in globals (AppState, ManifestCommands, etc.)
    // See globals.slint for the complete list

    Rectangle {
        background: #f8f9fa;

        VerticalLayout {
            // Header Bar
            Rectangle {
                height: 60px;
                background: #ffffff;
                drop-shadow-blur: 4px;
                drop-shadow-color: #00000020;
                drop-shadow-offset-y: 2px;

                HorizontalLayout {
                    padding: 16px;
                    spacing: 12px;

                    Text {
                        text: "Qleany";
                        font-size: 24px;
                        font-weight: 700;
                        vertical-alignment: center;
                        color: #212529;
                    }

                    // Undo button
                    StyledButton {
                        text: "↩";
                        enabled: AppState.manifest_is_open;
                        clicked => { UndoRedoCommands.undo(); }
                        visible: false;
                    }

                    // Redo button
                    StyledButton {
                        text: "↪";
                        enabled: AppState.manifest_is_open;
                        clicked => { UndoRedoCommands.redo(); }
                        visible: false;
                    }

                    // Save button
                    StyledButton {
                        text: "Save Manifest";
                        enabled: AppState.manifest_is_open && !AppState.manifest_is_saved && !AppState.is_loading;
                        clicked => {
                            if (AppState.manifest_path == "") {
                                ManifestCommands.save_manifest_as();
                            } else {
                                ManifestCommands.save_manifest();
                            }
                        }
                        primary: true;
                    }

                    // Spacer
                    Rectangle { horizontal-stretch: 1; }
                }
            }

            // Main content area with sidebar
            HorizontalLayout {
                // Left Sidebar Navigation
                Rectangle {
                    width: 140px;
                    background: #f8f9fa;

                    VerticalLayout {
                        padding: 4px;
                        spacing: 4px;
                        alignment: start;

                        NavItem {
                            label: "Home";
                            icon: @image-url("icons/home.svg");
                            active: AppState.current_tab == 0;
                            clicked => {
                                if (AppState.current_tab == 5) { GenerateCommands.cancel_fill_code(); }
                                AppState.current_tab = 0;
                            }
                        }

                        NavItem {
                            label: "Project";
                            icon: @image-url("icons/tag.svg");
                            active: AppState.current_tab == 1 && AppState.manifest_is_open;
                            enable: AppState.manifest_is_open;
                            clicked => {
                                if (AppState.current_tab == 5) { GenerateCommands.cancel_fill_code(); }
                                AppState.current_tab = 1;
                            }
                        }

                        NavItem {
                            label: "Entities";
                            icon: @image-url("icons/entities.svg");
                            active: AppState.current_tab == 2 && AppState.manifest_is_open;
                            enable: AppState.manifest_is_open;
                            clicked => {
                                if (AppState.current_tab == 5) { GenerateCommands.cancel_fill_code(); }
                                AppState.current_tab = 2;
                            }
                        }

                        NavItem {
                            label: "Features";
                            icon: @image-url("icons/features.svg");
                            active: AppState.current_tab == 3 && AppState.manifest_is_open;
                            enable: AppState.manifest_is_open;
                            clicked => {
                                if (AppState.current_tab == 5) { GenerateCommands.cancel_fill_code(); }
                                AppState.current_tab = 3;
                            }
                        }

                        NavItem {
                            label: "User Interface";
                            icon: @image-url("icons/user_interface.svg");
                            active: AppState.current_tab == 4 && AppState.manifest_is_open;
                            enable: AppState.manifest_is_open;
                            clicked => {
                                if (AppState.current_tab == 5) { GenerateCommands.cancel_fill_code(); }
                                AppState.current_tab = 4;
                            }
                        }

                        NavItem {
                            label: "Generate";
                            icon: @image-url("icons/factory.svg");
                            active: AppState.current_tab == 5 && AppState.manifest_is_open;
                            enable: AppState.manifest_is_open && CheckState.check-status != "critical";
                            clicked => {
                                AppState.current_tab = 5;
                                AppState.refresh_generate_tab();
                            }
                        }

                        // Spacer
                        Rectangle { vertical-stretch: 1; }
                    }
                }

                // Main Content Area
                Rectangle {
                    background: #ffffff;
                    border-radius: 8px;

                    // Tab components now use globals directly for state and callbacks
                    if AppState.current_tab == 0 : HomeTab { }

                    if AppState.current_tab == 1 && AppState.manifest_is_open : ProjectTab { }

                    if AppState.current_tab == 2 && AppState.manifest_is_open  : EntitiesTab { }

                    if AppState.current_tab == 3 && AppState.manifest_is_open : FeaturesTab { }

                    if AppState.current_tab == 4 && AppState.manifest_is_open : UserInterfaceTab { }

                    if AppState.current_tab == 5 && AppState.manifest_is_open && CheckState.check-status != "critical" : GenerateTab { }
                }
            }

            // Status bar at the bottom
            Rectangle {
                height: AppState.error_message != "" || AppState.success_message_visible ? 32px : 0px;
                background: AppState.error_message != "" ? #ffc9c9 : (AppState.success_message_visible ? #d3f9d8 : #ffffff);
                animate height { duration: 200ms; }
                
                HorizontalLayout {
                    padding-left: 16px;
                    padding-right: 16px;
                    alignment: start;
                    
                    if AppState.error_message != "" : Text {
                        text: AppState.error_message;
                        color: #c92a2a;
                        font-size: 14px;
                        vertical-alignment: center;
                    }

                    if AppState.error_message == "" && AppState.success_message_visible : Text {
                        text: AppState.success_message;
                        color: #2b8a3e;
                        font-size: 14px;
                        vertical-alignment: center;
                    }
                }
            }
        }

        // Check widget overlay (FAB + side panel)
        CheckWidget {
            x: 0px;
            y: 0px;
            width: parent.width;
            height: parent.height;
        }

        // Global loading overlay
        if AppState.is_loading : Rectangle {
            background: #00000040;
            x: 0px;
            y: 0px;
            width: parent.width;
            height: parent.height;

            ProgressIndicator {
                width: 48px;
                height: 48px;
                x: (parent.width - self.width) / 2;
                y: (parent.height - self.height) / 2;
                indeterminate: true;
            }
        }

        // New manifest wizard dialog
        if NewManifestWizardState.visible : NewManifestWizard {
            width: parent.width;
            height: parent.height;
            cancelled => {
                NewManifestWizardState.visible = false;
                NewManifestWizardState.step = 0;
            }
            confirmed => {
                NewManifestWizardState.visible = false;
                NewManifestWizardState.step = 0;
                ManifestCommands.create_wizard_confirmed();
            }
        }

        // Demo wizard dialog
        if DemoWizardState.visible : DemoWizard {
            width: parent.width;
            height: parent.height;
            cancelled => {
                DemoWizardState.visible = false;
                DemoWizardState.step = 0;
                DemoWizardState.completed = false;
                DemoWizardState.error_message = "";
            }
        }

        // Confirmation dialog for unsaved changes
        if AppState.confirm_dialog_visible : ConfirmationDialog {
            width: parent.width;
            height: parent.height;
            message: AppState.confirm_dialog_message;
            accepted => {
                // Execute the pending action based on confirm_dialog_pending_action value
                if (AppState.confirm_dialog_pending_action == "new") {
                    ManifestCommands.new_manifest();
                } else if (AppState.confirm_dialog_pending_action == "open") {
                    ManifestCommands.open_manifest();
                } else if (AppState.confirm_dialog_pending_action == "close") {
                    ManifestCommands.close_manifest();
                } else if (AppState.confirm_dialog_pending_action == "exit") {
                    AppState.force_exit = true;
                    ManifestCommands.exit_app();
                } else if (AppState.confirm_dialog_pending_action == "open_qleany") {
                    ManifestCommands.open_qleany_manifest();
                }
                // Reset and close the dialog
                AppState.confirm_dialog_pending_action = "none";
                AppState.confirm_dialog_message = "";
                AppState.confirm_dialog_visible = false;
            }
            rejected => {
                // Just close the dialog without executing the action
                AppState.confirm_dialog_pending_action = "none";
                AppState.confirm_dialog_message = "";
                AppState.confirm_dialog_visible = false;
            }
        }
    }
}