tasks.md 10.7 KB

Tasks: Migrate from tkinter to PySide6

Pre-Migration Tasks

  1. Install PySide6 dependency

    • Add PySide6>=6.6.0 to requirements (if exists) or install directly
    • Run pip install PySide6
    • Validation: python -c "from PySide6.QtWidgets import QApplication; print('OK')"
  2. Backup current implementation

    • Create git commit of current tkinter version
    • Tag as before-qt-migration for easy rollback
    • Validation: git log --oneline -1 shows commit

Phase 1: LoginDialog Migration (Priority: Critical)

  1. Create LoginDialog class structure

    • Import PySide6 modules (QDialog, QVBoxLayout, QFormLayout, etc.)
    • Define LoginDialog class inheriting from QDialog
    • Move init parameters from LoginWindow
    • Validation: Class instantiates without errors
  2. Implement LoginDialog UI layout

    • Create QVBoxLayout as main layout
    • Add title QLabel
    • Create QFormLayout for username/password fields
    • Add QLineEdit widgets for username and password
    • Set password field to QLineEdit.Password mode
    • Validation: Dialog shows with all fields visible
  3. Add checkbox row to LoginDialog

    • Create QHBoxLayout for checkboxes
    • Add "记住用户名" QCheckBox
    • Add "记住密码" QCheckBox
    • Set initial checked states from parameters
    • Validation: Checkboxes appear and can be toggled
  4. Add login button and error label

    • Create QPushButton with text "登录"
    • Connect to on_login slot
    • Add QLabel for error messages (initially hidden)
    • Validation: Button appears and is clickable
  5. Apply LoginDialog styling

    • Create QSS stylesheet for dialog
    • Style title, labels, input fields, button
    • Match colors from original design (#ffffff, #007AFF, #fafafa, etc.)
    • Validation: Dialog matches design mockup
  6. Implement password placeholder handling

    • Check if saved_password_hash exists
    • If yes, set placeholder text "••••••••" with gray color
    • Bind textChanged signal to clear placeholder
    • Validation: Placeholder shows and clears on typing
  7. Implement authentication logic

    • Move database connection code to on_login method
    • Use pymysql exactly as in tkinter version
    • Handle success: set result variables, accept dialog
    • Handle failure: show error in error_label
    • Validation: Login succeeds with valid credentials, fails with invalid
  8. Implement dialog return values

    • Store success, authenticated_user, password_hash as instance variables
    • Provide getter methods or properties
    • Return QDialog.Accepted on success, QDialog.Rejected on cancel
    • Validation: Calling code can access all return values
  9. Test LoginDialog on macOS

    • Run application and verify dialog appears
    • Verify all UI elements are visible (title, labels, inputs, button, checkboxes)
    • Test typing in username field
    • Test typing in password field (should be masked)
    • Test login with valid credentials
    • Test login with invalid credentials (should show error)
    • Validation: ALL UI elements visible, login flow works

Phase 2: ImageGeneratorWindow Migration (Priority: High)

  1. Create ImageGeneratorWindow class structure

    • Define class inheriting from QMainWindow
    • Move instance variables from ImageGeneratorApp
    • Call load_config() in init
    • Validation: Class instantiates, config loads
  2. Create central widget and main layout

    • Create QWidget as central widget
    • Create QVBoxLayout as main layout
    • Set central widget with setCentralWidget()
    • Validation: Window shows with empty layout
  3. Implement reference images section

    • Create QGroupBox titled "参考图片"
    • Add horizontal layout with "添加图片" button and count label
    • Create QScrollArea for horizontal image preview
    • Implement upload_images() method using QFileDialog
    • Validation: Can upload images, preview appears
  4. Implement image preview thumbnails

    • For each uploaded image, create QLabel with scaled QPixmap
    • Add delete button overlay or adjacent to each thumbnail
    • Arrange horizontally in scroll area
    • Implement delete_image() method
    • Validation: Thumbnails appear, delete works
  5. Implement prompt section

    • Create QGroupBox titled "提示词"
    • Add toolbar with favorite button, combo box, delete button
    • Add QTextEdit for prompt input
    • Set default text
    • Validation: Section appears with all controls
  6. Implement prompt favorites management

    • Implement toggle_favorite() method
    • Implement load_saved_prompt() slot for combo selection
    • Implement delete_saved_prompt() method
    • Update QComboBox when saved_prompts changes
    • Validation: Can save, load, delete prompts
  7. Implement settings section

    • Create QGroupBox titled "生成设置"
    • Add QLabel + QComboBox for aspect ratio
    • Add QLabel + QComboBox for image size
    • Set options and default values
    • Validation: Settings section appears with dropdowns
  8. Implement action buttons section

    • Create QHBoxLayout for buttons
    • Add "生成图片" QPushButton
    • Add "下载图片" QPushButton (initially disabled)
    • Add status QLabel
    • Validation: Buttons appear with correct states
  9. Implement preview section

    • Create QGroupBox titled "预览"
    • Add QLabel for image display
    • Set placeholder text when no image
    • Enable double-click to open system viewer
    • Validation: Preview area appears with placeholder
  10. Apply ImageGeneratorWindow styling

    • Create comprehensive QSS stylesheet
    • Style all sections, buttons, inputs
    • Match original color scheme
    • Validation: Window matches design, looks polished
  11. Create ImageGenerationWorker thread

    • Define class inheriting from QThread
    • Add signals: finished(bytes), error(str), progress(str)
    • Move image generation logic to run() method
    • Use same Gemini API calls as tkinter version
    • Validation: Thread instantiates, signals defined
  12. Implement async image generation

    • Create generate_image_async() method
    • Instantiate ImageGenerationWorker
    • Connect signals to slots (finished → display_image, error → show_error)
    • Start worker thread
    • Disable generate button during generation
    • Validation: Image generation works without freezing UI
  13. Implement image display

    • In on_image_generated slot, receive image bytes
    • Create QPixmap from bytes
    • Scale to fit preview area
    • Display in preview QLabel
    • Enable download button
    • Validation: Generated image displays correctly
  14. Implement image download

    • Use QFileDialog.getSaveFileName for save path
    • Write image bytes to selected file
    • Show success QMessageBox
    • Validation: Can save generated images
  15. Implement open in system viewer

    • Handle double-click on preview QLabel
    • Write temp file and open with QDesktopServices
    • Validation: Double-click opens image in system viewer
  16. Implement config save/load

    • load_config() method (same logic as tkinter)
    • save_config() method (same logic as tkinter)
    • Handle API key, saved_prompts, db_config, last_user, password_hash
    • Validation: Config persists across app restarts

Phase 3: Main Application Integration

  1. Create main() function

    • Create QApplication instance
    • Show LoginDialog with exec()
    • If accepted, create and show ImageGeneratorWindow
    • Run app.exec()
    • Handle dialog rejection (exit gracefully)
    • Validation: Application flow works end-to-end
  2. Update if name == "main" block

    • Call main() function
    • Keep database config loading logic
    • Validation: Can run as standalone script
  3. Remove old tkinter code

    • Delete or comment out old LoginWindow class
    • Delete or comment out old ImageGeneratorApp class
    • Remove tkinter imports if no longer needed
    • Keep utility functions (hash_password, DatabaseManager)
    • Validation: No unused code remains

Phase 4: Testing & Polish (Priority: Medium)

  1. macOS comprehensive testing

    • Launch application
    • LoginDialog: all elements visible
    • LoginDialog: authentication works
    • Main window: all sections visible
    • Upload reference images
    • Enter prompt
    • Generate image
    • Download image
    • Save/load favorites
    • Config persistence
    • Validation: All features work on macOS
  2. Windows comprehensive testing

    • Launch application
    • Verify native Windows look
    • Test all features (same as macOS checklist)
    • Check high-DPI scaling
    • Validation: All features work on Windows
  3. Cross-platform consistency check

    • Compare screenshots from macOS and Windows
    • Verify consistent layout and sizing
    • Check font rendering
    • Validation: UI looks good on both platforms
  4. Performance testing

    • Test with 10+ reference images
    • Test with long prompts
    • Test rapid UI interactions
    • Check memory usage
    • Validation: No lag, no memory leaks
  5. Error handling testing

    • Test with invalid API key
    • Test with no network connection
    • Test with corrupted image files
    • Test with invalid database credentials
    • Validation: Graceful error messages, no crashes
  6. UI polish and refinements

    • Adjust spacing and padding if needed
    • Fine-tune button sizes
    • Improve loading indicators
    • Add tooltips to buttons
    • Validation: UI feels polished and professional
  7. Documentation updates

    • Update README with PySide6 dependency
    • Document installation steps
    • Note Qt-specific features
    • Validation: Documentation is accurate

Dependencies

  • Tasks 1-2: Must complete before any migration work
  • Tasks 3-11: LoginDialog (can work independently)
  • Tasks 12-27: ImageGeneratorWindow (depends on LoginDialog being tested)
  • Tasks 28-30: Integration (depends on both windows complete)
  • Tasks 31-37: Testing and polish (depends on integration complete)

Estimated Time

  • Phase 1 (LoginDialog): 2-3 hours
  • Phase 2 (ImageGeneratorWindow): 4-6 hours
  • Phase 3 (Integration): 1 hour
  • Phase 4 (Testing & Polish): 1-2 hours
  • Total: 8-12 hours

Notes

  • Focus on getting LoginDialog working first to validate Qt works on macOS
  • Keep DatabaseManager and hash_password unchanged (they work fine)
  • Preserve all existing functionality - no feature removals
  • Use QSS for styling consistently
  • Use QThread for all async operations
  • Test frequently on macOS to catch issues early