mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-24 22:04:56 +00:00
feat(styles): create global styles entry point and organize global styles feat(styles): implement base HTML element styles and utility classes for flexbox feat(styles): establish layout, position, spacing, and text utility classes feat(styles): introduce mixins for animations, cards, dialogs, flexbox, grid, and responsive design test(quick_guide): add component and metadata validation tests for quick_guide package test(ui_level6): implement metadata validation tests for ui_level6 package
239 lines
7.4 KiB
QML
239 lines
7.4 KiB
QML
import QtQuick
|
|
import QtQuick.Controls
|
|
import QtQuick.Layouts
|
|
import "../contexts"
|
|
import "../fakemui"
|
|
|
|
/**
|
|
* SearchDialog.qml - Search dialog for tasks
|
|
* Uses Python AppController's search via taskModel filter
|
|
*/
|
|
Dialog {
|
|
id: root
|
|
|
|
signal taskSelected(int index)
|
|
|
|
title: LanguageContext.t("search")
|
|
modal: true
|
|
standardButtons: Dialog.Close
|
|
width: 600
|
|
height: 500
|
|
|
|
// Search state
|
|
property string query: ""
|
|
property bool loading: false
|
|
|
|
// Debounce timer
|
|
Timer {
|
|
id: searchTimer
|
|
interval: 300
|
|
onTriggered: performSearch()
|
|
}
|
|
|
|
function performSearch() {
|
|
// Use Python controller's search filter
|
|
app.setSearchQuery(query)
|
|
}
|
|
|
|
onOpened: {
|
|
searchInput.forceActiveFocus()
|
|
}
|
|
|
|
onClosed: {
|
|
query = ""
|
|
// Clear the search filter
|
|
app.setSearchQuery("")
|
|
}
|
|
|
|
background: Rectangle {
|
|
color: Theme.surface
|
|
radius: 8
|
|
border.color: Theme.border
|
|
}
|
|
|
|
header: ColumnLayout {
|
|
spacing: 0
|
|
|
|
// Title bar
|
|
Rectangle {
|
|
Layout.fillWidth: true
|
|
height: 48
|
|
color: Theme.surface
|
|
|
|
Text {
|
|
anchors.centerIn: parent
|
|
text: root.title
|
|
font.pixelSize: 18
|
|
font.bold: true
|
|
color: Theme.text
|
|
}
|
|
}
|
|
|
|
// Search input
|
|
TextField {
|
|
id: searchInput
|
|
Layout.fillWidth: true
|
|
Layout.margins: 16
|
|
Layout.bottomMargin: 8
|
|
placeholderText: LanguageContext.t("searchPlaceholder")
|
|
text: query
|
|
onTextChanged: {
|
|
query = text
|
|
searchTimer.restart()
|
|
}
|
|
font.pixelSize: 16
|
|
color: Theme.text
|
|
|
|
leftPadding: 40
|
|
|
|
Text {
|
|
anchors.left: parent.left
|
|
anchors.leftMargin: 12
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
text: "🔍"
|
|
font.pixelSize: 18
|
|
}
|
|
|
|
background: Rectangle {
|
|
color: Theme.background
|
|
border.color: searchInput.activeFocus ? Theme.primary : Theme.border
|
|
border.width: searchInput.activeFocus ? 2 : 1
|
|
radius: 4
|
|
implicitHeight: 44
|
|
}
|
|
}
|
|
|
|
// Results count
|
|
Text {
|
|
Layout.leftMargin: 16
|
|
Layout.bottomMargin: 8
|
|
text: app.taskModel.rowCount() + " " + LanguageContext.t("results")
|
|
font.pixelSize: 12
|
|
color: Theme.textSecondary
|
|
visible: query.trim() !== ""
|
|
}
|
|
}
|
|
|
|
contentItem: ScrollView {
|
|
clip: true
|
|
|
|
ColumnLayout {
|
|
width: parent.width
|
|
spacing: 8
|
|
|
|
// Empty state
|
|
Text {
|
|
Layout.alignment: Qt.AlignHCenter
|
|
Layout.topMargin: 32
|
|
visible: query.trim() === ""
|
|
text: LanguageContext.t("searchHelp")
|
|
font.pixelSize: 14
|
|
color: Theme.textSecondary
|
|
}
|
|
|
|
// No results
|
|
Text {
|
|
Layout.alignment: Qt.AlignHCenter
|
|
Layout.topMargin: 32
|
|
visible: query.trim() !== "" && app.taskModel.rowCount() === 0
|
|
text: LanguageContext.t("noResults")
|
|
font.pixelSize: 14
|
|
color: Theme.textSecondary
|
|
}
|
|
|
|
// Task results from model
|
|
Repeater {
|
|
model: app.taskModel
|
|
|
|
delegate: Rectangle {
|
|
Layout.fillWidth: true
|
|
Layout.leftMargin: 4
|
|
Layout.rightMargin: 4
|
|
height: taskColumn.height + 16
|
|
color: taskMouse.containsMouse ?
|
|
Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) :
|
|
"transparent"
|
|
radius: 4
|
|
|
|
required property int index
|
|
required property string taskId
|
|
required property string title
|
|
required property string status
|
|
required property string repo
|
|
required property string matchInfo
|
|
|
|
MouseArea {
|
|
id: taskMouse
|
|
anchors.fill: parent
|
|
hoverEnabled: true
|
|
cursorShape: Qt.PointingHandCursor
|
|
onClicked: {
|
|
taskSelected(index)
|
|
root.close()
|
|
}
|
|
}
|
|
|
|
ColumnLayout {
|
|
id: taskColumn
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
anchors.top: parent.top
|
|
anchors.margins: 8
|
|
spacing: 4
|
|
|
|
RowLayout {
|
|
spacing: 8
|
|
|
|
// Status badge
|
|
Rectangle {
|
|
width: 8
|
|
height: 8
|
|
radius: 4
|
|
color: status === "completed" ? Theme.success :
|
|
status === "running" ? Theme.primary :
|
|
status === "error" ? Theme.error : Theme.warning
|
|
}
|
|
|
|
Text {
|
|
text: title || "Untitled"
|
|
font.pixelSize: 14
|
|
font.bold: true
|
|
color: Theme.text
|
|
elide: Text.ElideRight
|
|
Layout.fillWidth: true
|
|
}
|
|
}
|
|
|
|
RowLayout {
|
|
spacing: 8
|
|
|
|
Text {
|
|
text: repo
|
|
font.pixelSize: 12
|
|
color: Theme.textSecondary
|
|
}
|
|
|
|
Text {
|
|
visible: matchInfo !== ""
|
|
text: "• " + matchInfo
|
|
font.pixelSize: 11
|
|
color: Theme.primary
|
|
}
|
|
}
|
|
|
|
Text {
|
|
visible: NerdModeContext.nerdMode
|
|
text: taskId
|
|
font.pixelSize: 11
|
|
font.family: "monospace"
|
|
color: Theme.textMuted
|
|
elide: Text.ElideMiddle
|
|
Layout.maximumWidth: 300
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|