V3.4.0 — Panneau fusion, macros CLI, bouton config client Vision
- Panneau de fusion PDF avec dialog dedié : - Liste des fichiers avec drag & drop pour reordonner - Boutons Ajouter/Retirer/Monter/Descendre - Pre-rempli avec le fichier courant - Support --macro en ligne de commande - register_windows.bat : ajout dynamique des macros au menu contextuel - Vision : bouton "Configurer le client" dans le modal licence (ouvre le gros modal client avec SFTP, fonctions, tunnel, etc.) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
105
app/dialogs/merge_dialog.py
Normal file
105
app/dialogs/merge_dialog.py
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
"""Dialogue Fusion de PDF avec reordonnement drag & drop."""
|
||||||
|
|
||||||
|
from PyQt6.QtWidgets import (QDialog, QVBoxLayout, QHBoxLayout, QLabel,
|
||||||
|
QListWidget, QListWidgetItem, QAbstractItemView,
|
||||||
|
QPushButton, QDialogButtonBox, QFileDialog)
|
||||||
|
from PyQt6.QtCore import Qt, QSize
|
||||||
|
|
||||||
|
|
||||||
|
class MergeDialog(QDialog):
|
||||||
|
def __init__(self, initial_files=None, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.setWindowTitle("Fusionner des PDF")
|
||||||
|
self.setMinimumSize(500, 400)
|
||||||
|
self._files = list(initial_files or [])
|
||||||
|
self._setup_ui()
|
||||||
|
self._refresh_list()
|
||||||
|
|
||||||
|
def _setup_ui(self):
|
||||||
|
layout = QVBoxLayout(self)
|
||||||
|
|
||||||
|
layout.addWidget(QLabel("Glissez les fichiers pour reordonner. Cliquez Ajouter pour en ajouter."))
|
||||||
|
|
||||||
|
self._list = QListWidget()
|
||||||
|
self._list.setDragDropMode(QAbstractItemView.DragDropMode.InternalMove)
|
||||||
|
self._list.setDefaultDropAction(Qt.DropAction.MoveAction)
|
||||||
|
self._list.setStyleSheet("""
|
||||||
|
QListWidget { background: #fff; border: 1px solid #d0d0d0; border-radius: 6px; padding: 4px; }
|
||||||
|
QListWidget::item { padding: 8px; border-bottom: 1px solid #eee; }
|
||||||
|
QListWidget::item:selected { background: #e0f4ff; color: #006fa6; }
|
||||||
|
""")
|
||||||
|
layout.addWidget(self._list)
|
||||||
|
|
||||||
|
btn_layout = QHBoxLayout()
|
||||||
|
btn_add = QPushButton("Ajouter des PDF...")
|
||||||
|
btn_add.clicked.connect(self._add_files)
|
||||||
|
btn_layout.addWidget(btn_add)
|
||||||
|
|
||||||
|
btn_remove = QPushButton("Retirer")
|
||||||
|
btn_remove.clicked.connect(self._remove_file)
|
||||||
|
btn_layout.addWidget(btn_remove)
|
||||||
|
|
||||||
|
btn_up = QPushButton("Monter")
|
||||||
|
btn_up.clicked.connect(self._move_up)
|
||||||
|
btn_layout.addWidget(btn_up)
|
||||||
|
|
||||||
|
btn_down = QPushButton("Descendre")
|
||||||
|
btn_down.clicked.connect(self._move_down)
|
||||||
|
btn_layout.addWidget(btn_down)
|
||||||
|
|
||||||
|
layout.addLayout(btn_layout)
|
||||||
|
|
||||||
|
self._count_label = QLabel("")
|
||||||
|
layout.addWidget(self._count_label)
|
||||||
|
|
||||||
|
buttons = QDialogButtonBox(
|
||||||
|
QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
|
||||||
|
)
|
||||||
|
buttons.accepted.connect(self.accept)
|
||||||
|
buttons.rejected.connect(self.reject)
|
||||||
|
layout.addWidget(buttons)
|
||||||
|
|
||||||
|
def _refresh_list(self):
|
||||||
|
self._list.clear()
|
||||||
|
for i, path in enumerate(self._files):
|
||||||
|
import os
|
||||||
|
name = os.path.basename(path)
|
||||||
|
item = QListWidgetItem(f"{i+1}. {name}")
|
||||||
|
item.setData(Qt.ItemDataRole.UserRole, path)
|
||||||
|
item.setToolTip(path)
|
||||||
|
self._list.addItem(item)
|
||||||
|
self._count_label.setText(f"{len(self._files)} fichier(s)")
|
||||||
|
|
||||||
|
def _add_files(self):
|
||||||
|
paths, _ = QFileDialog.getOpenFileNames(self, "Ajouter des PDF", "", "PDF (*.pdf)")
|
||||||
|
if paths:
|
||||||
|
self._files.extend(paths)
|
||||||
|
self._refresh_list()
|
||||||
|
|
||||||
|
def _remove_file(self):
|
||||||
|
row = self._list.currentRow()
|
||||||
|
if row >= 0:
|
||||||
|
self._files.pop(row)
|
||||||
|
self._refresh_list()
|
||||||
|
|
||||||
|
def _move_up(self):
|
||||||
|
row = self._list.currentRow()
|
||||||
|
if row > 0:
|
||||||
|
self._files[row], self._files[row-1] = self._files[row-1], self._files[row]
|
||||||
|
self._refresh_list()
|
||||||
|
self._list.setCurrentRow(row - 1)
|
||||||
|
|
||||||
|
def _move_down(self):
|
||||||
|
row = self._list.currentRow()
|
||||||
|
if 0 <= row < len(self._files) - 1:
|
||||||
|
self._files[row], self._files[row+1] = self._files[row+1], self._files[row]
|
||||||
|
self._refresh_list()
|
||||||
|
self._list.setCurrentRow(row + 1)
|
||||||
|
|
||||||
|
def get_files(self):
|
||||||
|
# Relire l'ordre depuis la liste (drag & drop peut avoir change)
|
||||||
|
files = []
|
||||||
|
for i in range(self._list.count()):
|
||||||
|
item = self._list.item(i)
|
||||||
|
files.append(item.data(Qt.ItemDataRole.UserRole))
|
||||||
|
return files
|
||||||
@@ -1108,22 +1108,26 @@ class MainWindow(QMainWindow):
|
|||||||
QMessageBox.critical(self, "Erreur", str(e))
|
QMessageBox.critical(self, "Erreur", str(e))
|
||||||
|
|
||||||
def _do_merge(self):
|
def _do_merge(self):
|
||||||
paths, _ = QFileDialog.getOpenFileNames(self, "Selectionner les PDF a fusionner", "", "PDF (*.pdf)")
|
from app.dialogs.merge_dialog import MergeDialog
|
||||||
if not paths or len(paths) < 2:
|
# Pre-remplir avec le fichier courant si ouvert
|
||||||
if paths and len(paths) == 1:
|
initial = [self._current_file] if self._current_file else []
|
||||||
|
dlg = MergeDialog(initial_files=initial, parent=self)
|
||||||
|
if dlg.exec():
|
||||||
|
files = dlg.get_files()
|
||||||
|
if len(files) < 2:
|
||||||
QMessageBox.information(self, "Fusion", "Selectionnez au moins 2 fichiers PDF.")
|
QMessageBox.information(self, "Fusion", "Selectionnez au moins 2 fichiers PDF.")
|
||||||
return
|
return
|
||||||
from pypdf import PdfWriter
|
from pypdf import PdfWriter
|
||||||
self._show_progress()
|
self._show_progress()
|
||||||
try:
|
try:
|
||||||
writer = PdfWriter()
|
writer = PdfWriter()
|
||||||
for path in paths:
|
for path in files:
|
||||||
writer.append(path)
|
writer.append(path)
|
||||||
output = self._make_temp()
|
output = self._make_temp()
|
||||||
with open(output, "wb") as f:
|
with open(output, "wb") as f:
|
||||||
writer.write(f)
|
writer.write(f)
|
||||||
self._show_result(output)
|
self._show_result(output)
|
||||||
self._status_label.setText(f"Fusion de {len(paths)} fichiers terminee")
|
self._status_label.setText(f"Fusion de {len(files)} fichiers terminee")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._hide_progress()
|
self._hide_progress()
|
||||||
QMessageBox.critical(self, "Erreur", str(e))
|
QMessageBox.critical(self, "Erreur", str(e))
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ REPO = "jules/copydev-imposing-tool"
|
|||||||
BRANCH = "master"
|
BRANCH = "master"
|
||||||
|
|
||||||
# Version actuelle (incrementee a chaque release)
|
# Version actuelle (incrementee a chaque release)
|
||||||
VERSION = "3.3.1"
|
VERSION = "3.4.0"
|
||||||
|
|
||||||
|
|
||||||
def get_remote_version():
|
def get_remote_version():
|
||||||
|
|||||||
10
main.py
10
main.py
@@ -210,12 +210,16 @@ def main():
|
|||||||
# Gestion des arguments
|
# Gestion des arguments
|
||||||
args = sys.argv[1:]
|
args = sys.argv[1:]
|
||||||
action = None
|
action = None
|
||||||
|
macro_name = None
|
||||||
files_to_open = []
|
files_to_open = []
|
||||||
i = 0
|
i = 0
|
||||||
while i < len(args):
|
while i < len(args):
|
||||||
if args[i] == "--action" and i + 1 < len(args):
|
if args[i] == "--action" and i + 1 < len(args):
|
||||||
action = args[i + 1]
|
action = args[i + 1]
|
||||||
i += 2
|
i += 2
|
||||||
|
elif args[i] == "--macro" and i + 1 < len(args):
|
||||||
|
macro_name = args[i + 1]
|
||||||
|
i += 2
|
||||||
elif args[i].lower().endswith('.pdf') and os.path.exists(args[i]):
|
elif args[i].lower().endswith('.pdf') and os.path.exists(args[i]):
|
||||||
files_to_open.append(args[i])
|
files_to_open.append(args[i])
|
||||||
i += 1
|
i += 1
|
||||||
@@ -265,6 +269,12 @@ def main():
|
|||||||
QMessageBox.critical(window, "Erreur", str(e))
|
QMessageBox.critical(window, "Erreur", str(e))
|
||||||
QTimer.singleShot(500, run_cli_action)
|
QTimer.singleShot(500, run_cli_action)
|
||||||
|
|
||||||
|
# Macro en ligne de commande
|
||||||
|
if macro_name and files_to_open:
|
||||||
|
def run_cli_macro():
|
||||||
|
window._run_macro(macro_name)
|
||||||
|
QTimer.singleShot(500, run_cli_macro)
|
||||||
|
|
||||||
window.show()
|
window.show()
|
||||||
splash.close()
|
splash.close()
|
||||||
sys.exit(app.exec())
|
sys.exit(app.exec())
|
||||||
|
|||||||
@@ -80,6 +80,20 @@ reg add "HKCU\Software\Classes\SystemFileAssociations\.pdf\shell\CopyDevImpose\s
|
|||||||
reg add "HKCU\Software\Classes\SystemFileAssociations\.pdf\shell\CopyDevImpose\shell\unbooklet" /ve /d "Delivretiser" /f >nul 2>&1
|
reg add "HKCU\Software\Classes\SystemFileAssociations\.pdf\shell\CopyDevImpose\shell\unbooklet" /ve /d "Delivretiser" /f >nul 2>&1
|
||||||
reg add "HKCU\Software\Classes\SystemFileAssociations\.pdf\shell\CopyDevImpose\shell\unbooklet\command" /ve /d "\"%EXE_PATH%\" --action unbooklet \"%%1\"" /f >nul 2>&1
|
reg add "HKCU\Software\Classes\SystemFileAssociations\.pdf\shell\CopyDevImpose\shell\unbooklet\command" /ve /d "\"%EXE_PATH%\" --action unbooklet \"%%1\"" /f >nul 2>&1
|
||||||
|
|
||||||
|
:: Ajouter les macros enregistrees
|
||||||
|
if exist "%~dp0.presets.json" (
|
||||||
|
echo Ajout des macros...
|
||||||
|
for /f "tokens=1 delims=:" %%m in ('findstr /r "\"[^\"]*\":" "%~dp0.presets.json" ^| findstr /v "{" ^| findstr /v "action" ^| findstr /v "settings"') do (
|
||||||
|
set "MACRO=%%~m"
|
||||||
|
set "MACRO=!MACRO: =!"
|
||||||
|
set "MACRO=!MACRO:"=!"
|
||||||
|
if not "!MACRO!"=="" (
|
||||||
|
reg add "HKCU\Software\Classes\SystemFileAssociations\.pdf\shell\CopyDevImpose\shell\macro_!MACRO!" /ve /d "Macro: !MACRO!" /f >nul 2>&1
|
||||||
|
reg add "HKCU\Software\Classes\SystemFileAssociations\.pdf\shell\CopyDevImpose\shell\macro_!MACRO!\command" /ve /d "\"%EXE_PATH%\" --macro \"!MACRO!\" \"%%1\"" /f >nul 2>&1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
echo [OK] Menu contextuel ajoute
|
echo [OK] Menu contextuel ajoute
|
||||||
echo (clic droit sur PDF > CopyDev Impose > ...)
|
echo (clic droit sur PDF > CopyDev Impose > ...)
|
||||||
goto :EOF
|
goto :EOF
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
3.3.1
|
3.4.0
|
||||||
|
|||||||
Reference in New Issue
Block a user