spec.md 11 KB

Spec: Qt-based GUI Implementation

Overview

Specification for migrating the application from tkinter to PySide6 to resolve macOS rendering issues and provide a modern, cross-platform GUI framework.

ADDED Requirements

Requirement: PySide6 Framework Integration

ID: qt-gui-001

The application MUST use PySide6 (Qt 6 for Python) as the GUI framework, replacing tkinter entirely. The framework SHALL be version 6.6.0 or higher.

Scenario: PySide6 is installed and importable

Given the application is deployed on a system When the Python interpreter attempts to import PySide6 modules Then the import MUST succeed without errors And the version SHALL be 6.6.0 or higher And all required Qt modules SHALL be available (QtWidgets, QtCore, QtGui)

Scenario: No tkinter dependencies remain

Given the migrated application code When analyzing all imports Then no tkinter or ttk imports SHALL exist And no tk.* or ttk.* class references SHALL exist And all GUI code SHALL use PySide6.Qt* classes

Requirement: LoginDialog Cross-Platform Visibility

ID: qt-gui-002

The login dialog MUST be fully visible and functional on macOS, Windows, and Linux platforms. All UI elements SHALL render with native platform appearance.

Scenario: LoginDialog renders correctly on macOS

Given the application is launched on macOS When the LoginDialog is displayed Then all UI elements SHALL be visible (title, labels, input fields, checkboxes, button) And the dialog SHALL have a white background And the dialog SHALL use macOS native window decorations And all text SHALL be readable with proper contrast And input fields SHALL accept keyboard input And the cursor SHALL be visible in focused input fields

Scenario: LoginDialog renders correctly on Windows

Given the application is launched on Windows When the LoginDialog is displayed Then all UI elements SHALL be visible And the dialog SHALL use Windows native window decorations And the styling SHALL match Windows UI guidelines And high-DPI displays SHALL scale correctly

Scenario: LoginDialog authentication functionality preserved

Given the LoginDialog is displayed with valid database configuration When the user enters valid credentials and clicks "登录" Then the database authentication SHALL execute And on success, the dialog SHALL return QDialog.Accepted And the authenticated username and password hash SHALL be accessible And on failure, an error message SHALL display in the dialog

Requirement: ImageGeneratorWindow Functional Parity

ID: qt-gui-003

The main application window MUST preserve all functionality from the tkinter version while using Qt widgets and layouts.

Scenario: All features from tkinter version are available

Given the Qt-based ImageGeneratorWindow Then reference image upload SHALL work And image preview thumbnails SHALL display And prompt text input SHALL work And prompt favorites (save/load/delete) SHALL work And aspect ratio selection SHALL work And image size selection SHALL work And image generation SHALL work via Gemini API And generated image preview SHALL display And image download SHALL work And configuration save/load SHALL work

Scenario: Reference images can be uploaded and displayed

Given the ImageGeneratorWindow is displayed When the user clicks "+ 添加图片" Then a QFileDialog SHALL open for image selection When the user selects one or more image files Then each image SHALL appear as a 100x100 thumbnail And each thumbnail SHALL have a delete button And the image count label SHALL update And clicking delete SHALL remove the thumbnail

Scenario: Image generation works asynchronously

Given the user has entered a prompt When the user clicks "生成图片" Then image generation SHALL execute in a QThread (not main thread) And the UI SHALL remain responsive during generation And a status message SHALL indicate generation is in progress And on completion, the generated image SHALL display in the preview area And the "下载图片" button SHALL become enabled And on error, an error message SHALL display

Requirement: Qt Layout System Usage

ID: qt-gui-004

All UI layouts MUST use Qt's layout system (QVBoxLayout, QHBoxLayout, QFormLayout, QGridLayout) rather than absolute positioning. This ensures responsive, cross-platform compatibility.

Scenario: LoginDialog uses Qt layouts

Given the LoginDialog implementation Then the main structure SHALL use QVBoxLayout And username/password fields SHALL use QFormLayout And checkboxes SHALL use QHBoxLayout And no absolute positioning (setGeometry) SHALL be used And the dialog SHALL resize gracefully

Scenario: ImageGeneratorWindow uses Qt layouts

Given the ImageGeneratorWindow implementation Then the central widget SHALL use QVBoxLayout as main layout And content sections SHALL use appropriate nested layouts And the window SHALL be resizable And widgets SHALL expand/contract appropriately when resized

Requirement: Qt Styling with QSS

ID: qt-gui-005

The application MUST use Qt Style Sheets (QSS) for consistent, maintainable styling across all UI components.

Scenario: Consistent color scheme applied via QSS

Given the application windows and dialogs Then all styling SHALL use QSS (not programmatic setFont/setColor) And the color scheme SHALL match the original design:

  • Background: #ffffff (white)
  • Accent: #007AFF (blue)
  • Hover: #0051D5 (darker blue)
  • Text: #1d1d1f (dark gray)
  • Secondary text: #666666 (medium gray)
  • Input background: #fafafa (light gray)
  • Error text: #ff3b30 (red) And fonts SHALL use "Segoe UI" or system default And the stylesheet SHALL be centralized for easy modification

Scenario: Buttons have hover states

Given any QPushButton in the application When the user hovers over the button Then the button background color SHALL change to the hover color And the cursor SHALL change to a pointing hand

Requirement: Asynchronous Operations with QThread

ID: qt-gui-006

All long-running operations (API calls, file I/O, database queries) MUST execute in QThread instances to prevent UI freezing.

Scenario: Image generation runs in background thread

Given the user initiates image generation When the generation process starts Then a QThread worker SHALL be created and started And the main thread (UI) SHALL remain responsive And the user SHALL be able to interact with other UI elements And the worker SHALL communicate via Qt signals (finished, error, progress) And UI updates SHALL occur in response to signals

Scenario: Database authentication runs asynchronously

Given the user clicks the login button When database authentication begins Then the operation SHOULD execute in a separate thread (optional for quick operations) Or the UI SHALL show a loading indicator during authentication And the UI SHALL not freeze

Requirement: Configuration Compatibility

ID: qt-gui-007

The Qt-based application MUST read and write configuration files in the same format as the tkinter version, ensuring seamless transition.

Scenario: Existing config.json is read correctly

Given a config.json file from the tkinter version exists When the Qt application loads Then the config SHALL be read successfully And api_key SHALL be loaded And saved_prompts SHALL be loaded And db_config SHALL be loaded And last_user and saved_password_hash SHALL be loaded

Scenario: Config changes are saved correctly

Given the user makes changes (adds favorite prompt, checks remember me, etc.) When the application saves configuration Then the config.json file SHALL be updated And the JSON structure SHALL match the tkinter version's format And the file SHALL be readable by the tkinter version (backwards compatible)

Requirement: Native File Dialogs

ID: qt-gui-008

The application MUST use Qt's native file dialogs (QFileDialog) which provide platform-specific file selection interfaces.

Scenario: Image upload uses native file dialog

Given the user clicks "+ 添加图片" When QFileDialog.getOpenFileNames is called Then the system's native file picker SHALL appear And on macOS, it SHALL use the macOS file picker UI And on Windows, it SHALL use the Windows file picker UI And the dialog SHALL filter to show image files (png, jpg, jpeg, gif, bmp)

Scenario: Image save uses native save dialog

Given the user clicks "下载图片" When QFileDialog.getSaveFileName is called Then the system's native save dialog SHALL appear And the default filename SHALL be timestamp-based (YYYYMMDDHHMMSS.png) And the user can choose the save location and filename

Requirement: Error Handling and User Feedback

ID: qt-gui-009

The application MUST provide clear error messages and user feedback using Qt's message box and status display mechanisms.

Scenario: Error messages display in QMessageBox

Given an error occurs (API failure, file I/O error, etc.) When the error is encountered Then a QMessageBox SHALL display with the error details And the message box SHALL be modal (blocks interaction until dismissed) And the message SHALL be in Chinese (matching original UI) And the severity SHALL be appropriate (Critical, Warning, Information)

Scenario: Status updates display in status label

Given operations are in progress When status changes (generating image, uploading, saving, etc.) Then the status QLabel SHALL update with the current status And the status text SHALL include an indicator (● symbol) And the color SHALL indicate status (blue=in progress, green=success, red=error)

MODIFIED Requirements

Requirement: Database Authentication Implementation

ID: qt-gui-010

Database authentication MUST function identically to the tkinter version, with the same SQL queries, password hashing, and result handling, but using Qt widgets for UI.

Scenario: Authentication logic unchanged

Given the DatabaseManager class from the tkinter version Then the class SHOULD remain unchanged (works with Qt) And the hash_password function SHOULD remain unchanged And the SQL queries SHOULD remain identical And only the UI response (show dialog, update labels) SHALL use Qt widgets

REMOVED Requirements

Requirement: tkinter Framework Usage

ID: tkinter-001 (REMOVED)

The application no longer uses tkinter. All tkinter-based requirements are superseded by Qt requirements above.

Cross-References

  • qt-gui-002 depends on qt-gui-001 (Qt must be installed first)
  • qt-gui-003 depends on qt-gui-006 (async operations required for features)
  • qt-gui-005 supports qt-gui-002 and qt-gui-003 (styling makes UI visible and polished)
  • qt-gui-007 ensures qt-gui-010 works (config needed for auth)