Initial commit of ISC QtQuick application scaffold, including main application logic in , QML components for UI in directory, project metadata in , and runtime dependencies in . Added README for setup instructions and project structure overview.
This commit is contained in:
@@ -0,0 +1,151 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import ISC
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: root
|
||||||
|
anchors.fill: parent
|
||||||
|
color: Theme.pageBackground
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
// Primary navigation shown in the left rail.
|
||||||
|
property var sideActions: ["DETECT WAFER", "READ MEMORY", "OPEN CSV IN EXCEL", "ERASE MEMORY", "IMPORT DATA", "STORED DATA"]
|
||||||
|
|
||||||
|
// Footer tabs drive the active workspace section.
|
||||||
|
property var bottomTabs: ["Status", "Graph", "Data", "Wafer Map", "Compare", "Split", "Settings", "About"]
|
||||||
|
|
||||||
|
property int selectedTabIndex: 0
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
// Left control rail.
|
||||||
|
Rectangle {
|
||||||
|
id: sideRail
|
||||||
|
Layout.preferredWidth: Theme.sideRailWidth
|
||||||
|
Layout.fillHeight: true
|
||||||
|
color: Theme.sideRailBackground
|
||||||
|
border.color: Theme.workspaceBorder
|
||||||
|
border.width: 1
|
||||||
|
|
||||||
|
readonly property int actionCount: root.sideActions.length
|
||||||
|
readonly property real computedButtonHeight: Math.min(Theme.sideButtonHeight, (height - (Theme.panelPadding * 2) - (Theme.sideRailSpacing * Math.max(0, actionCount - 1))) / Math.max(1, actionCount))
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Theme.panelPadding
|
||||||
|
spacing: Theme.sideRailSpacing
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: root.sideActions
|
||||||
|
|
||||||
|
Button {
|
||||||
|
id: control
|
||||||
|
text: modelData
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: Math.max(Theme.sideButtonMinHeight, sideRail.computedButtonHeight)
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
color: control.down ? Theme.buttonPressed : Theme.cardBackground
|
||||||
|
border.color: Theme.cardBorder
|
||||||
|
border.width: 1
|
||||||
|
radius: 4
|
||||||
|
}
|
||||||
|
|
||||||
|
contentItem: Text {
|
||||||
|
text: control.text
|
||||||
|
color: Theme.headingColor
|
||||||
|
font.bold: true
|
||||||
|
font.pixelSize: 18
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main workspace and footer navigation.
|
||||||
|
Rectangle {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
color: Theme.workspaceBackground
|
||||||
|
border.color: Theme.workspaceBorder
|
||||||
|
border.width: 1
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Theme.mainAreaPadding
|
||||||
|
spacing: Theme.rightPaneGap
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.minimumHeight: 220
|
||||||
|
color: Theme.responseBackground
|
||||||
|
border.color: Theme.responseBorder
|
||||||
|
border.width: 1
|
||||||
|
radius: 8
|
||||||
|
|
||||||
|
Label {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: "Main content area"
|
||||||
|
color: Theme.bodyColor
|
||||||
|
font.pixelSize: 20
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep the tab strip evenly distributed across the footer.
|
||||||
|
Rectangle {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: Theme.tabBarHeight + (Theme.tabBarPadding * 2)
|
||||||
|
color: Theme.tabBarBackground
|
||||||
|
border.color: Theme.workspaceBorder
|
||||||
|
border.width: 1
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Theme.tabBarPadding
|
||||||
|
spacing: Theme.tabSpacing
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: root.bottomTabs
|
||||||
|
|
||||||
|
Button {
|
||||||
|
id: botTabBtn
|
||||||
|
property bool isActive: index === root.selectedTabIndex
|
||||||
|
|
||||||
|
text: modelData
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: Theme.tabBarHeight
|
||||||
|
Layout.minimumWidth: Theme.tabButtonMinWidth
|
||||||
|
onClicked: root.selectedTabIndex = index
|
||||||
|
hoverEnabled: true
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
color: botTabBtn.isActive ? Theme.tabActiveBackground : (botTabBtn.hovered ? Theme.tabHoverBackground : Theme.tabBackground)
|
||||||
|
border.color: Theme.tabBorder
|
||||||
|
border.width: 1
|
||||||
|
radius: Theme.tabRadius
|
||||||
|
}
|
||||||
|
|
||||||
|
contentItem: Text {
|
||||||
|
text: botTabBtn.text
|
||||||
|
color: botTabBtn.isActive ? Theme.tabActiveText : Theme.tabText
|
||||||
|
font.pixelSize: Theme.tabFontSize
|
||||||
|
font.bold: botTabBtn.isActive
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import QtQuick.Window
|
||||||
|
import ISC
|
||||||
|
|
||||||
|
// ===== App Window Shell =====
|
||||||
|
Window {
|
||||||
|
// ===== Window Dimensions =====
|
||||||
|
width: 1400
|
||||||
|
height: 820
|
||||||
|
minimumWidth: 1100
|
||||||
|
minimumHeight: 700
|
||||||
|
visible: true
|
||||||
|
title: qsTr("ISenseCloud")
|
||||||
|
|
||||||
|
// Keep the window file very small.
|
||||||
|
// Styling and layout now live in HomePage.qml.
|
||||||
|
// ===== Root Page Mount =====
|
||||||
|
HomePage {
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
# ===== ISC Tabs Module =====
|
||||||
|
module ISC.Tabs
|
||||||
|
|
||||||
|
# ===== Tab Components =====
|
||||||
|
SettingsTab 1.0 SettingsTab.qml
|
||||||
|
|
||||||
|
# ===== Local Python Helpers =====
|
||||||
|
local_settings 1.0 local_settings.py
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
pragma Singleton
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
// ===== Shared Theme Tokens =====
|
||||||
|
QtObject {
|
||||||
|
// ===== Theme Mode =====
|
||||||
|
// Toggle this to preview the same shell in light mode.
|
||||||
|
property bool isDarkMode: true
|
||||||
|
|
||||||
|
// ===== Surface Colors =====
|
||||||
|
// Core application surfaces.
|
||||||
|
readonly property color pageBackground: isDarkMode ? "#11161c" : "#eef4f7"
|
||||||
|
readonly property color cardBackground: isDarkMode ? "#1b232d" : "#ffffff"
|
||||||
|
readonly property color workspaceBackground: isDarkMode ? "#121923" : "#ffffff"
|
||||||
|
readonly property color sideRailBackground: isDarkMode ? "#18202a" : "#f5f7fa"
|
||||||
|
readonly property color responseBackground: isDarkMode ? "#18212a" : "#f9fbfc"
|
||||||
|
|
||||||
|
// Shared border and text colors.
|
||||||
|
readonly property color cardBorder: isDarkMode ? "#334155" : "#cbd5e1"
|
||||||
|
readonly property color workspaceBorder: isDarkMode ? "#334155" : "#d7dde5"
|
||||||
|
readonly property color responseBorder: isDarkMode ? "#334155" : "#d5e0e8"
|
||||||
|
|
||||||
|
readonly property color headingColor: isDarkMode ? "#e5eef7" : "#12324a"
|
||||||
|
readonly property color bodyColor: isDarkMode ? "#afbdca" : "#415a6b"
|
||||||
|
readonly property color buttonPressed: isDarkMode ? "#214d60" : "#17576c"
|
||||||
|
readonly property color statusSuccessColor: isDarkMode ? "#7cd67e" : "#1f7a33"
|
||||||
|
readonly property color statusErrorColor: isDarkMode ? "#ff8a80" : "#c62828"
|
||||||
|
readonly property color statusWarningColor: isDarkMode ? "#f3c677" : "#9a6700"
|
||||||
|
|
||||||
|
// ===== Side Rail Sizing =====
|
||||||
|
readonly property int sideRailWidth: 190
|
||||||
|
readonly property int sideRailSpacing: 14
|
||||||
|
readonly property int sideButtonHeight: 146
|
||||||
|
readonly property int sideButtonMinHeight: 88
|
||||||
|
readonly property int panelPadding: 12
|
||||||
|
|
||||||
|
// ===== Main Panel Spacing =====
|
||||||
|
// Main content spacing.
|
||||||
|
readonly property int mainAreaPadding: 10
|
||||||
|
readonly property int rightPaneGap: 6
|
||||||
|
readonly property int tabBarHeight: 34
|
||||||
|
readonly property int settingsPanelMaxWidth: 760
|
||||||
|
readonly property int settingsOuterMargin: 40
|
||||||
|
readonly property int settingsSectionSpacing: 20
|
||||||
|
readonly property int settingsRowSpacing: 16
|
||||||
|
readonly property int settingsGridSpacing: 12
|
||||||
|
readonly property int settingsButtonHeight: 40
|
||||||
|
readonly property int settingsActionWidth: 200
|
||||||
|
readonly property int settingsFieldMinWidth: 160
|
||||||
|
|
||||||
|
// ===== Footer Tab Theme =====
|
||||||
|
// Bottom tab styling.
|
||||||
|
readonly property color tabBarBackground: isDarkMode ? "#161d26" : "#f2f2f2"
|
||||||
|
readonly property color tabBackground: isDarkMode ? "#202833" : "#ececec"
|
||||||
|
readonly property color tabActiveBackground: isDarkMode ? "#2a3440" : "#ffffff"
|
||||||
|
readonly property color tabHoverBackground: isDarkMode ? "#263140" : "#f7f7f7"
|
||||||
|
readonly property color tabBorder: isDarkMode ? "#3a4758" : "#cfcfcf"
|
||||||
|
readonly property color tabText: isDarkMode ? "#c6d0da" : "#222222"
|
||||||
|
readonly property color tabActiveText: isDarkMode ? "#ffffff" : "#111111"
|
||||||
|
|
||||||
|
readonly property int tabButtonMinWidth: 80
|
||||||
|
readonly property int tabHorizontalPadding: 14
|
||||||
|
readonly property int tabBarPadding: 6
|
||||||
|
readonly property int tabSpacing: 2
|
||||||
|
readonly property int tabRadius: 2
|
||||||
|
readonly property int tabFontSize: 12
|
||||||
|
|
||||||
|
// ===== Form Control Theme =====
|
||||||
|
readonly property color inputBackground: isDarkMode ? "#202833" : "#ffffff"
|
||||||
|
readonly property color inputBorder: isDarkMode ? "#4a596d" : "#cfcfcf"
|
||||||
|
readonly property color buttonBackground: isDarkMode ? "#202833" : "#ffffff"
|
||||||
|
readonly property color buttonText: isDarkMode ? "#e5eef7" : "#111111"
|
||||||
|
readonly property color checkboxText: isDarkMode ? "#d6dfeb" : "#111111"
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# ===== ISC QML Module =====
|
||||||
|
module ISC
|
||||||
|
|
||||||
|
# ===== Root Components =====
|
||||||
|
Main 1.0 Main.qml
|
||||||
|
HomePage 1.0 HomePage.qml
|
||||||
|
|
||||||
|
# ===== Singleton Theme =====
|
||||||
|
singleton Theme 1.0 Theme.qml
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
# ISC QtQuick App
|
||||||
|
|
||||||
|
Small PySide6 + Qt Quick application scaffold for the `ISenseCloud` desktop UI shell.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Python 3.10+ (tested with Python 3.14 in this workspace)
|
||||||
|
- macOS, Linux, or Windows with GUI support
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
From the project root:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -m venv .venv
|
||||||
|
source .venv/bin/activate
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
## Run
|
||||||
|
|
||||||
|
```bash
|
||||||
|
source .venv/bin/activate
|
||||||
|
python main.py
|
||||||
|
```
|
||||||
|
|
||||||
|
This launches the Qt window and loads the `ISC` QML module from `ISC/Main.qml`.
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
- `main.py`: PySide6 bootstrap; creates the Qt app and loads QML module `ISC/Main`.
|
||||||
|
- `ISC/Main.qml`: top-level window definition.
|
||||||
|
- `ISC/HomePage.qml`: main UI layout (left action rail, workspace panel, footer tabs).
|
||||||
|
- `ISC/Theme.qml`: shared theme constants and dark/light mode tokens.
|
||||||
|
- `ISC/qmldir`: QML module registration.
|
||||||
|
|
||||||
|
## Window Configuration
|
||||||
|
|
||||||
|
Window dimensions and constraints are defined in `ISC/Main.qml`:
|
||||||
|
|
||||||
|
- **Default size**: 1400 × 820 pixels
|
||||||
|
- **Minimum size**: 1100 × 700 pixels
|
||||||
|
- **Title bar**: "ISenseCloud"
|
||||||
|
|
||||||
|
To adjust the window, edit the `Window` block in `ISC/Main.qml`:
|
||||||
|
|
||||||
|
```qml
|
||||||
|
Window {
|
||||||
|
width: 1400
|
||||||
|
height: 820
|
||||||
|
minimumWidth: 1100
|
||||||
|
minimumHeight: 700
|
||||||
|
visible: true
|
||||||
|
title: qsTr("ISenseCloud")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Customization
|
||||||
|
|
||||||
|
- Toggle dark/light mode in `ISC/Theme.qml` via `isDarkMode`.
|
||||||
|
- Update sidebar and footer labels in `ISC/HomePage.qml` through `sideActions` and `bottomTabs`.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
- If the app does not start, verify the venv is active and dependencies are installed:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
source .venv/bin/activate
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
- If no window appears, ensure you are running in a desktop session with GUI access.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
# ===== Backend Package Marker =====
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from PySide6.QtGui import QGuiApplication
|
||||||
|
from PySide6.QtQml import QQmlApplicationEngine
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# Minimal Qt bootstrap: load the ISC QML module and exit if it fails.
|
||||||
|
app = QGuiApplication(sys.argv)
|
||||||
|
engine = QQmlApplicationEngine()
|
||||||
|
engine.addImportPath(Path(__file__).parent)
|
||||||
|
engine.loadFromModule("ISC", "Main")
|
||||||
|
|
||||||
|
if not engine.rootObjects():
|
||||||
|
sys.exit(-1)
|
||||||
|
|
||||||
|
sys.exit(app.exec())
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# ===== Project Metadata =====
|
||||||
|
[project]
|
||||||
|
name = "PySide QtQuick Project"
|
||||||
|
|
||||||
|
# ===== PySide Build Inputs =====
|
||||||
|
[tool.pyside6-project]
|
||||||
|
files = ["ISC/HomePage.qml", "ISC/Main.qml", "ISC/Theme.qml", "ISC/Tabs/SettingsTab.qml", "ISC/Tabs/qmldir", "ISC/qmldir", "main.py", "backend/local_settings.py", "backend/local_settings_model.py"]
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
# ===== Runtime Dependencies =====
|
||||||
|
PySide6
|
||||||
Reference in New Issue
Block a user