generated from LouisMazin/PythonApplicationTemplate
fix some issues
This commit is contained in:
parent
a9dfbee1a8
commit
2d89c95a23
@ -18,7 +18,7 @@ os_name = config.get("app_os", sys.platform)
|
||||
app_name = config.get("app_name", "Application")
|
||||
|
||||
# --- Construct dynamic name ---
|
||||
name = f"{app_name}-{os_name}-{arch}-v{version}"
|
||||
name = f"{app_name}"
|
||||
|
||||
# --- Optional icon path ---
|
||||
icon = getenv("ICON_PATH", "")
|
||||
|
||||
@ -32,7 +32,7 @@ class DragDropFrame(QFrame):
|
||||
urls = event.mimeData().urls()
|
||||
if urls and self.parent_window:
|
||||
file_path = urls[0].toLocalFile()
|
||||
self.parent_window.set_dicom_from_files(file_path)
|
||||
self.parent_window.find_dicoms_from_files(file_path)
|
||||
|
||||
def getDragIndicator(self) -> QLabel:
|
||||
drag_indicator = QLabel(self)
|
||||
|
||||
@ -128,6 +128,11 @@ class ExportWindow(QWidget):
|
||||
# disable automatic stretch and fit col 1 to its contents
|
||||
tree.header().setStretchLastSection(False)
|
||||
tree.header().setSectionResizeMode(1, QHeaderView.ResizeMode.ResizeToContents)
|
||||
|
||||
# Install event filter to handle clicks on items
|
||||
tree.viewport().installEventFilter(self)
|
||||
self._current_tree = tree # Store reference for event filter
|
||||
|
||||
popup.layout().addWidget(tree)
|
||||
|
||||
for dicom, sub_dicoms in dicom_list:
|
||||
@ -188,8 +193,9 @@ class ExportWindow(QWidget):
|
||||
self.show_color_dialog(item, btn, cols))
|
||||
tree.setItemWidget(child_item, 1, color_button)
|
||||
|
||||
# single connection to handle both directions
|
||||
# Connect signals - itemChanged handles all checkbox state changes
|
||||
tree.itemChanged.connect(self.on_item_changed)
|
||||
|
||||
tree.resizeColumnToContents(0) # Resize first column to fit content
|
||||
tree.setColumnWidth(0, max(200, tree.columnWidth(0))) # Ensure minimum 200px for first column
|
||||
tree.setColumnWidth(1, 20) # Exact width for button
|
||||
@ -203,16 +209,53 @@ class ExportWindow(QWidget):
|
||||
|
||||
popup.exec()
|
||||
|
||||
def toggle_child_items(self, item):
|
||||
if item.childCount() > 0: # Check if the item has children
|
||||
for i in range(item.childCount()):
|
||||
child = item.child(i)
|
||||
child.setCheckState(0, item.checkState(0)) # Set child state to match parent state
|
||||
# Clean up reference
|
||||
self._current_tree = None
|
||||
|
||||
def eventFilter(self, source, event):
|
||||
# Handle tree widget clicks
|
||||
if hasattr(self, '_current_tree') and self._current_tree and source == self._current_tree.viewport():
|
||||
if event.type() == QEvent.Type.MouseButtonPress and event.button() == Qt.MouseButton.LeftButton:
|
||||
pos = event.pos()
|
||||
item = self._current_tree.itemAt(pos)
|
||||
|
||||
if item:
|
||||
# Get the column that was clicked
|
||||
column = self._current_tree.header().logicalIndexAt(pos.x())
|
||||
if column == 0: # Only on first column
|
||||
# Get the visual rect for the item
|
||||
visual_rect = self._current_tree.visualItemRect(item)
|
||||
|
||||
# Calculate the indentation and branch indicator area
|
||||
# The branch indicator (arrow) is typically in the first ~20 pixels
|
||||
indent = self._current_tree.indentation()
|
||||
item_depth = 0
|
||||
parent = item.parent()
|
||||
while parent:
|
||||
item_depth += 1
|
||||
parent = parent.parent()
|
||||
|
||||
# Calculate where the branch indicator starts
|
||||
branch_start = item_depth * indent
|
||||
branch_end = branch_start + indent
|
||||
|
||||
# If click is NOT in the branch indicator area, toggle checkbox
|
||||
if pos.x() < branch_start or pos.x() > branch_end:
|
||||
current_state = item.checkState(0)
|
||||
new_state = Qt.CheckState.Unchecked if current_state == Qt.CheckState.Checked else Qt.CheckState.Checked
|
||||
item.setCheckState(0, new_state)
|
||||
return True # Event handled
|
||||
|
||||
# Handle combobox wheel events
|
||||
if isinstance(source, QComboBox) and event.type() == QEvent.Type.Wheel:
|
||||
return True
|
||||
|
||||
return super().eventFilter(source, event)
|
||||
|
||||
def show_color_dialog(self, item, button, colors):
|
||||
dialog = QDialog(self)
|
||||
dialog.setWindowFlags(Qt.WindowType.Popup)
|
||||
dialog.setFixedSize(200, 40) # Increased height for labels
|
||||
dialog.setFixedSize(200, 20) # Reduced height since no labels
|
||||
|
||||
# Position dialog to the left of the button
|
||||
button_pos = button.mapToGlobal(button.rect().topLeft())
|
||||
@ -238,12 +281,6 @@ class ExportWindow(QWidget):
|
||||
color_btn.clicked.connect(lambda _, c=color: self.select_color(item, button, c, dialog))
|
||||
layout.addWidget(color_btn, 0, i)
|
||||
|
||||
# Add label below button
|
||||
label = QLabel(ExportCategory.get_name(color)[:3]) # First 3 letters
|
||||
label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
label.setStyleSheet("font-size: 8px; color: black;")
|
||||
layout.addWidget(label, 1, i)
|
||||
|
||||
dialog.exec()
|
||||
|
||||
def select_color(self, item, button, color, dialog):
|
||||
@ -338,8 +375,43 @@ class ExportWindow(QWidget):
|
||||
self.alert_manager.show_error("export_error")
|
||||
|
||||
def eventFilter(self, source, event):
|
||||
# Handle tree widget clicks
|
||||
if hasattr(self, '_current_tree') and self._current_tree and source == self._current_tree.viewport():
|
||||
if event.type() == QEvent.Type.MouseButtonPress and event.button() == Qt.MouseButton.LeftButton:
|
||||
pos = event.pos()
|
||||
item = self._current_tree.itemAt(pos)
|
||||
|
||||
if item:
|
||||
# Get the column that was clicked
|
||||
column = self._current_tree.header().logicalIndexAt(pos.x())
|
||||
if column == 0: # Only on first column
|
||||
# Get the visual rect for the item
|
||||
visual_rect = self._current_tree.visualItemRect(item)
|
||||
|
||||
# Calculate the indentation and branch indicator area
|
||||
# The branch indicator (arrow) is typically in the first ~20 pixels
|
||||
indent = self._current_tree.indentation()
|
||||
item_depth = 0
|
||||
parent = item.parent()
|
||||
while parent:
|
||||
item_depth += 1
|
||||
parent = parent.parent()
|
||||
|
||||
# Calculate where the branch indicator starts
|
||||
branch_start = item_depth * indent
|
||||
branch_end = branch_start + indent
|
||||
|
||||
# If click is NOT in the branch indicator area, toggle checkbox
|
||||
if pos.x() < branch_start or pos.x() > branch_end:
|
||||
current_state = item.checkState(0)
|
||||
new_state = Qt.CheckState.Unchecked if current_state == Qt.CheckState.Checked else Qt.CheckState.Checked
|
||||
item.setCheckState(0, new_state)
|
||||
return True # Event handled
|
||||
|
||||
# Handle combobox wheel events
|
||||
if isinstance(source, QComboBox) and event.type() == QEvent.Type.Wheel:
|
||||
return True
|
||||
|
||||
return super().eventFilter(source, event)
|
||||
|
||||
def on_item_changed(self, item, column):
|
||||
|
||||
@ -4,6 +4,7 @@ setlocal enabledelayedexpansion
|
||||
REM === PATH SETUP ===
|
||||
set PARENT_DIR=%~dp0..
|
||||
set CONFIG_FILE=%PARENT_DIR%\config.json
|
||||
set ICON_FILE=%PARENT_DIR%\data\assets\icon.png
|
||||
set ENV_FILE=%PARENT_DIR%\.env
|
||||
|
||||
REM Check if .env file exists
|
||||
@ -24,8 +25,10 @@ REM === Extract python path from .env file ===
|
||||
for /f "usebackq tokens=2 delims==" %%i in (`findstr "PYTHON_PATH" "%ENV_FILE%"`) do set SYSTEM_PYTHON=%%i
|
||||
|
||||
set VENV_PATH=%PARENT_DIR%\WINenv_%ARCHITECTURE%
|
||||
set EXE_NAME=%APP_NAME%-Windows-%ARCHITECTURE%
|
||||
set EXE_NAME=%APP_NAME%.exe
|
||||
set PYTHON_IN_VENV=%VENV_PATH%\Scripts\python.exe
|
||||
set BUILD_DIR=%PARENT_DIR%\build
|
||||
set ZIP_FILE=%BUILD_DIR%\%APP_NAME%.zip
|
||||
|
||||
REM === Verify Python existence ===
|
||||
if not exist "%SYSTEM_PYTHON%" (
|
||||
@ -45,12 +48,44 @@ if not exist "%VENV_PATH%\Scripts\activate.bat" (
|
||||
|
||||
REM === Run PyInstaller ===
|
||||
"%PYTHON_IN_VENV%" -m PyInstaller ^
|
||||
--distpath "%PARENT_DIR%\build" ^
|
||||
--workpath "%PARENT_DIR%\build\dist" ^
|
||||
--distpath "%BUILD_DIR%" ^
|
||||
--workpath "%BUILD_DIR%\dist" ^
|
||||
--clean ^
|
||||
"%PARENT_DIR%\BUILD.spec"
|
||||
|
||||
REM === Clean build cache ===
|
||||
rmdir /s /q "%PARENT_DIR%\build\dist"
|
||||
rmdir /s /q "%BUILD_DIR%\dist"
|
||||
|
||||
REM === Create ZIP ===
|
||||
echo [INFO] Creating ZIP archive...
|
||||
|
||||
set TEMP_ZIP_DIR=%BUILD_DIR%\temp_zip
|
||||
|
||||
REM Remove old temp dir if exists
|
||||
if exist "%TEMP_ZIP_DIR%" rmdir /s /q "%TEMP_ZIP_DIR%"
|
||||
mkdir "%TEMP_ZIP_DIR%"
|
||||
|
||||
REM Copy compiled app - tout le contenu du build sauf les ZIP existants
|
||||
move /Y "%BUILD_DIR%\%EXE_NAME%" "%TEMP_ZIP_DIR%\"
|
||||
|
||||
REM Copy config.json
|
||||
copy "%CONFIG_FILE%" "%TEMP_ZIP_DIR%\" /Y
|
||||
|
||||
REM Copy icon.png
|
||||
copy "%ICON_FILE%" "%TEMP_ZIP_DIR%\" /Y
|
||||
|
||||
REM Copy data/lang
|
||||
xcopy /E /I /Y "%PARENT_DIR%\data\lang" "%TEMP_ZIP_DIR%\lang"
|
||||
|
||||
REM Remove old ZIP if exists
|
||||
if exist "%ZIP_FILE%" del "%ZIP_FILE%"
|
||||
|
||||
REM Create ZIP
|
||||
powershell -NoProfile -Command "Add-Type -AssemblyName 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::CreateFromDirectory('%TEMP_ZIP_DIR%', '%ZIP_FILE%')"
|
||||
|
||||
REM Remove temp folder
|
||||
rmdir /s /q "%TEMP_ZIP_DIR%"
|
||||
|
||||
echo [INFO] ZIP created at: %ZIP_FILE%
|
||||
|
||||
endlocal
|
||||
|
||||
@ -1,59 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# === PATH SETUP ===
|
||||
PARENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
CONFIG_FILE="$PARENT_DIR/config.json"
|
||||
ENV_FILE="$PARENT_DIR/.env"
|
||||
|
||||
# --- Check .env file ---
|
||||
if [[ ! -f "$ENV_FILE" ]]; then
|
||||
echo "[ERROR] .env file not found. Please copy .env.example to .env and configure it."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Check jq availability ---
|
||||
if ! command -v jq &>/dev/null; then
|
||||
echo "[ERROR] 'jq' is required. Install it with: brew install jq"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Extract values from config.json ---
|
||||
ICON_PATH=$(jq -r '.icon_path' "$CONFIG_FILE")
|
||||
APP_NAME=$(jq -r '.app_name' "$CONFIG_FILE")
|
||||
ARCHITECTURE=$(jq -r '.architecture' "$CONFIG_FILE")
|
||||
|
||||
# --- Extract PYTHON_PATH from .env ---
|
||||
SYSTEM_PYTHON=$(grep -E "^PYTHON_PATH=" "$ENV_FILE" | cut -d '=' -f2)
|
||||
|
||||
VENV_PATH="$PARENT_DIR/MACenv_$ARCHITECTURE"
|
||||
EXE_NAME="${APP_NAME}-MacOS-${ARCHITECTURE}"
|
||||
PYTHON_IN_VENV="$VENV_PATH/bin/python"
|
||||
|
||||
# --- Verify Python existence ---
|
||||
if [[ ! -x "$SYSTEM_PYTHON" ]]; then
|
||||
echo "[ERROR] Python not found at: $SYSTEM_PYTHON"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Check if virtual environment exists ---
|
||||
if [[ ! -f "$VENV_PATH/bin/activate" ]]; then
|
||||
echo "[INFO] Virtual environment not found. Creating..."
|
||||
"$SYSTEM_PYTHON" -m venv "$VENV_PATH"
|
||||
"$PYTHON_IN_VENV" -m pip install --upgrade pip
|
||||
"$PYTHON_IN_VENV" -m pip install -r "$PARENT_DIR/requirements.txt"
|
||||
else
|
||||
echo "[INFO] Virtual environment found."
|
||||
fi
|
||||
|
||||
# --- Run PyInstaller ---
|
||||
"$PYTHON_IN_VENV" -m PyInstaller \
|
||||
--distpath "$PARENT_DIR/build" \
|
||||
--workpath "$PARENT_DIR/build/dist" \
|
||||
--clean \
|
||||
"$PARENT_DIR/BUILD.spec"
|
||||
|
||||
# --- Clean build cache ---
|
||||
rm -rf "$PARENT_DIR/build/dist"
|
||||
|
||||
echo "[INFO] Build complete: $EXE_NAME"
|
||||
@ -1,59 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Root paths
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
CONFIG_FILE="$ROOT_DIR/config.json"
|
||||
REQUIREMENTS="$ROOT_DIR/requirements.txt"
|
||||
ENV_FILE="$ROOT_DIR/.env"
|
||||
|
||||
# Check if .env exists
|
||||
if [[ ! -f "$ENV_FILE" ]]; then
|
||||
echo "[ERROR] .env file not found. Please copy .env.example to .env and configure it."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Extract architecture from config.json (requires jq)
|
||||
if ! command -v jq &>/dev/null; then
|
||||
echo "[ERROR] 'jq' is required. Install it with: brew install jq"
|
||||
exit 1
|
||||
fi
|
||||
ARCHITECTURE=$(jq -r '.architecture' "$CONFIG_FILE")
|
||||
|
||||
# Extract python path from .env
|
||||
PYTHON_EXEC=$(grep -E "^PYTHON_PATH=" "$ENV_FILE" | cut -d '=' -f2)
|
||||
|
||||
# Construct venv path
|
||||
ENV_NAME="MACenv_$ARCHITECTURE"
|
||||
ENV_PATH="$ROOT_DIR/$ENV_NAME"
|
||||
|
||||
# Check python executable
|
||||
if [[ ! -x "$PYTHON_EXEC" ]]; then
|
||||
echo "[ERROR] Python not found at: $PYTHON_EXEC"
|
||||
echo "Please check your .env or installation path."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Show info
|
||||
echo "[INFO] Configuration:"
|
||||
echo " Python: $PYTHON_EXEC"
|
||||
echo " Env: $ENV_NAME"
|
||||
|
||||
# Create virtual env if missing
|
||||
if [[ ! -d "$ENV_PATH/bin" ]]; then
|
||||
echo "[INFO] Virtual environment not found, creating..."
|
||||
"$PYTHON_EXEC" -m venv "$ENV_PATH"
|
||||
echo "[INFO] Installing dependencies..."
|
||||
"$ENV_PATH/bin/python" -m pip install --upgrade pip
|
||||
"$ENV_PATH/bin/pip" install -r "$REQUIREMENTS"
|
||||
else
|
||||
echo "[INFO] Virtual environment found."
|
||||
fi
|
||||
|
||||
# Activate and launch VS Code
|
||||
echo "[INFO] Launching VS Code..."
|
||||
# shellcheck source=/dev/null
|
||||
source "$ENV_PATH/bin/activate"
|
||||
open -a "Visual Studio Code" "$ROOT_DIR"
|
||||
|
||||
exit 0
|
||||
Loading…
x
Reference in New Issue
Block a user