Files
metabuilder/qml/core/App.qml
johndoe6345789 6e394d7846 style(qt6): 80-char margin enforced — 737 violations → 29 remaining
191 files reformatted across views, components, widgets, hybrid, contexts.
New components: CCreateSchemaDialog, CAddFieldDialog, CAdminContentPanel.
JS helpers: connBadgeStatus/Text, adminStats, exampleLabels, onLevelClicked.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 15:48:39 +00:00

502 lines
18 KiB
QML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import "components"
import "contexts"
import "fakemui"
/**
* App.qml - Main application component
* Mirrors React's App.jsx with drawer navigation and view management
*/
ApplicationWindow {
id: appWindow
visible: true
width: 1280
height: 800
minimumWidth: 800
minimumHeight: 600
title: "Codex Runner"
color: Theme.background
// Initialize Responsive singleton with this window
Component.onCompleted: {
Responsive.targetWindow = appWindow
app.statusMessage.connect(onStatusMessage)
}
// Current view state
property string currentView: "tasks"
property int selectedTaskIndex: -1
property bool searchOpen: false
// Drawer width - responsive!
readonly property int drawerWidth: Responsive.isMobile
? 0 : (Responsive.isTablet ? 200 : 240)
function onStatusMessage(msg) {
// Could show a snackbar/toast here
// Status messages handled via UI feedback
}
// Keyboard shortcut: Cmd/Ctrl+K for search
Shortcut {
sequence: StandardKey.Find
onActivated: searchOpen = true
}
Shortcut {
sequence: "Ctrl+K"
onActivated: searchOpen = true
}
// Navigation
function navigateTo(view) {
currentView = view
selectedTaskIndex = -1
}
function selectTask(index) {
selectedTaskIndex = index
currentView = "taskDetail"
// Load the task detail via Python controller
app.loadTaskDetail(index)
}
// Layout: Drawer + Main Content
RowLayout {
anchors.fill: parent
spacing: 0
// Sidebar / Drawer
Rectangle {
id: drawer
Layout.preferredWidth: drawerWidth
Layout.fillHeight: true
color: Theme.paper
ColumnLayout {
anchors.fill: parent
spacing: 0
// Header
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 64
color: "transparent"
Text {
anchors.centerIn: parent
text: "Codex Runner"
font.pixelSize: 18
font.bold: true
color: Theme.primary
}
}
// Divider
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 1
color:
Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.12)
}
// Navigation Items
ListView {
Layout.fillWidth: true
Layout.preferredHeight: contentHeight
interactive: false
model: ListModel {
ListElement { viewId: "tasks"; emoji: "☰"
labelKey: "tasks" }
ListElement { viewId: "newPrompt"; emoji: ""
labelKey: "newTask" }
}
delegate: ItemDelegate {
width: parent.width
height: 48
highlighted: currentView === viewId
contentItem: RowLayout {
spacing: 16
Text {
text: emoji
font.pixelSize: 20
color: Theme.text
Layout.leftMargin: 16
}
Text {
text: LanguageContext.t(labelKey)
font.pixelSize: 14
color: Theme.text
}
}
background: Rectangle {
color: highlighted ? Qt.rgba(Theme.primary.r,
Theme.primary.g, Theme.primary.b, 0.12)
: (hovered ? Qt.rgba(Theme.text.r,
Theme.text.g, Theme.text.b,
0.04) : "transparent")
}
onClicked: navigateTo(viewId)
}
}
// Divider
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 1
color:
Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.12)
}
// Secondary Navigation
ListView {
Layout.fillWidth: true
Layout.preferredHeight: contentHeight
interactive: false
model: ListModel {
ListElement { viewId: "user"; emoji: "👤"
labelKey: "profile" }
ListElement { viewId: "docs"; emoji: "📖"
labelKey: "documentation" }
}
delegate: ItemDelegate {
width: parent.width
height: 48
highlighted: currentView === viewId
contentItem: RowLayout {
spacing: 16
Text {
text: emoji
font.pixelSize: 20
color: Theme.text
Layout.leftMargin: 16
}
Text {
text: LanguageContext.t(labelKey)
font.pixelSize: 14
color: Theme.text
}
}
background: Rectangle {
color: highlighted ? Qt.rgba(Theme.primary.r,
Theme.primary.g, Theme.primary.b, 0.12)
: (hovered ? Qt.rgba(Theme.text.r,
Theme.text.g, Theme.text.b,
0.04) : "transparent")
}
onClicked: navigateTo(viewId)
}
}
// Divider
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 1
color:
Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.12)
}
// Settings Section
Item {
Layout.fillWidth: true
Layout.preferredHeight: 48
RowLayout {
anchors.fill: parent
anchors.leftMargin: 16
anchors.rightMargin: 16
Text {
text: "💻"
font.pixelSize: 16
}
Text {
text: LanguageContext.t("nerdMode")
font.pixelSize: 14
color: Theme.text
Layout.fillWidth: true
}
Switch {
checked: NerdModeContext.nerdMode
onToggled: NerdModeContext.setNerdMode(checked)
}
}
}
// Theme selector
ItemDelegate {
Layout.fillWidth: true
height: 48
contentItem: RowLayout {
spacing: 16
Text {
text: "🎨"
font.pixelSize: 16
Layout.leftMargin: 16
}
Text {
text: LanguageContext.t(
"theme") + ": " + Theme.current.name
font.pixelSize: 14
color: Theme.text
}
}
onClicked: themeMenu.open()
Menu {
id: themeMenu
Repeater {
model: Theme.themeKeys
MenuItem {
text: Theme.themes[modelData].name
checkable: true
checked: Theme.themeName === modelData
onTriggered: Theme.setTheme(modelData)
indicator: Rectangle {
implicitWidth: 12
implicitHeight: 12
x: 6
y: parent.height / 2 - 6
radius: 6
color: Theme.themes[modelData].primary
}
}
}
}
}
// Language selector
ItemDelegate {
Layout.fillWidth: true
height: 48
contentItem: RowLayout {
spacing: 16
Text {
text: "🌐"
font.pixelSize: 16
Layout.leftMargin: 16
}
Text {
text:
LanguageContext.t("language")
+ ": "
+ LanguageContext.languages[
LanguageContext.language
].flag
font.pixelSize: 14
color: Theme.text
}
}
onClicked: languageMenu.open()
Menu {
id: languageMenu
Repeater {
model: LanguageContext.languageKeys
MenuItem {
text:
LanguageContext.languages[
modelData
].flag + " "
+ LanguageContext.languages[
modelData
].name
checkable: true
checked: LanguageContext.language === modelData
onTriggered: LanguageContext.setLanguage(
modelData)
}
}
}
}
// Spacer
Item { Layout.fillHeight: true }
// User chip at bottom - shows connection status
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 48
Layout.margins: 16
color:
Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.08)
radius: 24
RowLayout {
anchors.centerIn: parent
spacing: 8
Text {
text: "🔌"
font.pixelSize: 16
}
Text {
text: "Python API"
font.pixelSize: 12
color: Theme.text
}
}
}
}
}
// Main Content Area
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
color: Theme.background
ColumnLayout {
anchors.fill: parent
spacing: 0
// App Bar
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 64
color: Theme.paper
RowLayout {
anchors.fill: parent
anchors.leftMargin: 16
anchors.rightMargin: 16
Text {
text: {
switch(currentView) {
case "tasks":
return LanguageContext.t("tasks")
case "taskDetail":
return LanguageContext.t("taskDetail")
case "newPrompt":
return LanguageContext.t("newTask")
case "user":
return LanguageContext.t("profile")
case "docs": return LanguageContext.t(
"documentation")
default: return ""
}
}
font.pixelSize: 20
font.bold: true
color: Theme.text
}
Item { Layout.fillWidth: true }
// Search button
CIconButton {
icon: "🔍"
tooltip: LanguageContext.t("search") + " (⌘K)"
onClicked: searchOpen = true
}
// Docs button
CIconButton {
icon: "📖"
tooltip: LanguageContext.t("documentation")
onClicked: navigateTo("docs")
}
// Refresh button
CIconButton {
icon: "🔄"
tooltip: "Refresh"
onClicked: app.loadTasks()
}
}
}
// Content
StackLayout {
Layout.fillWidth: true
Layout.fillHeight: true
currentIndex: {
switch(currentView) {
case "tasks": return 0
case "taskDetail": return 1
case "newPrompt": return 2
case "user": return 3
case "docs": return 4
default: return 0
}
}
// Tasks View
TaskList {
onTaskSelected: function(index) { selectTask(index) }
}
// Task Detail View
TaskDetail {
taskIndex: selectedTaskIndex
onBack: navigateTo("tasks")
}
// New Prompt View
NewPrompt {
onSuccess: navigateTo("tasks")
}
// User Info View
UserInfo {}
// Documentation View
Documentation {}
}
}
}
}
// Search Dialog
SearchDialog {
id: searchDialog
visible: searchOpen
onRejected: searchOpen = false
onTaskSelected: function(index) {
searchOpen = false
selectTask(index)
}
}
// Ajax Queue Widget (fixed position, bottom right)
AjaxQueueWidget {
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.margins: 16
}
}