1
0
mirror of https://github.com/ciromattia/kcc synced 2026-05-19 22:11:59 +00:00

Add bulk volume editing with rich tooltip

* Add checkbox next to Volume field for enabling bulk volume editing (only in bulk mode)

* Support single number (5), range (1-10), or comma list (1, 3, 5) input formats

* Sort files alphabetically before volume assignment

* Validate that volume count matches file count

* Add rich HTML tooltip explaining the feature
This commit is contained in:
jaroslawjanas
2025-12-03 15:38:29 +01:00
parent abd1adb22f
commit a50db2e5ed

View File

@@ -22,7 +22,7 @@ import itertools
from pathlib import Path
from PySide6.QtCore import (QSize, QUrl, Qt, Signal, QIODeviceBase, QEvent, QThread, QSettings)
from PySide6.QtGui import (QColor, QIcon, QPixmap, QDesktopServices)
from PySide6.QtWidgets import (QApplication, QLabel, QListWidgetItem, QMainWindow, QSystemTrayIcon, QFileDialog, QMessageBox, QDialog)
from PySide6.QtWidgets import (QApplication, QLabel, QListWidgetItem, QMainWindow, QSystemTrayIcon, QFileDialog, QMessageBox, QDialog, QCheckBox)
from PySide6.QtNetwork import (QLocalSocket, QLocalServer)
import os
@@ -1422,6 +1422,9 @@ class KCCGUI_MetaEditor(KCC_ui_editor.Ui_editorDialog):
self.files = files if isinstance(files, list) else [files]
self.bulkMode = len(self.files) > 1
# Sort files by name for consistent volume assignment
self.files.sort()
if self.bulkMode:
firstFile = self.files[0]
self.parser = metadata.MetadataParser(firstFile)
@@ -1429,6 +1432,10 @@ class KCCGUI_MetaEditor(KCC_ui_editor.Ui_editorDialog):
self.okButton.setEnabled(True)
self.statusLabel.setText(f'Editing {len(self.files)} files.')
# Show bulk volume checkbox
self.bulkVolumeCheck.setVisible(True)
self.bulkVolumeCheck.setChecked(False)
for field in (self.volumeLine, self.numberLine, self.titleLine):
field.setEnabled(False)
field.setText('')
@@ -1447,6 +1454,9 @@ class KCCGUI_MetaEditor(KCC_ui_editor.Ui_editorDialog):
file = self.files[0]
self.parser = metadata.MetadataParser(file)
# Hide bulk volume checkbox in single file mode
self.bulkVolumeCheck.setVisible(False)
for field in (self.volumeLine, self.numberLine, self.titleLine, self.seriesLine,
self.writerLine, self.pencillerLine, self.inkerLine, self.coloristLine):
field.setEnabled(True)
@@ -1486,7 +1496,16 @@ class KCCGUI_MetaEditor(KCC_ui_editor.Ui_editorDialog):
if tmpData:
bulkData[fieldName] = tmpData
if not bulkData:
# Handle bulk volume editing
volumes = None
if self.bulkVolumeCheck.isChecked():
volumeText = self.volumeLine.text()
volumes, error = self.parseVolumeInput(volumeText, len(self.files))
if error:
self.statusLabel.setText(error)
return
if not bulkData and volumes is None:
self.statusLabel.setText('No changes to apply.')
return
@@ -1506,6 +1525,9 @@ class KCCGUI_MetaEditor(KCC_ui_editor.Ui_editorDialog):
continue
for key, value in bulkData.items():
parser.data[key] = value
# Set volume if bulk volume editing is enabled
if volumes is not None:
parser.data['Volume'] = str(volumes[i - 1])
parser.saveXML()
except Exception as err:
errors.append(f'{os.path.basename(file)}: {str(err)}')
@@ -1548,6 +1570,60 @@ class KCCGUI_MetaEditor(KCC_ui_editor.Ui_editorDialog):
def cleanData(self, s):
return escape(s.strip())
def parseVolumeInput(self, text, fileCount):
"""Parse volume input and return list of volume numbers.
Supports: single number (5), range (5-10), comma list (1,3,5)
Returns (volumes_list, error_message) tuple.
"""
text = text.strip()
if not text:
return None, None
volumes = []
# Check if it's a range (e.g., "5-10")
if '-' in text and ',' not in text:
parts = text.split('-')
if len(parts) == 2:
try:
start = int(parts[0].strip())
end = int(parts[1].strip())
if start <= end:
volumes = list(range(start, end + 1))
else:
return None, 'Invalid range: start > end'
except ValueError:
return None, 'Invalid range format'
# Check if it's a comma-separated list (e.g., "1,3,5")
elif ',' in text:
try:
volumes = [int(v.strip()) for v in text.split(',') if v.strip()]
except ValueError:
return None, 'Invalid list format'
# Single number - generate sequence starting from that number
else:
try:
start = int(text)
volumes = list(range(start, start + fileCount))
except ValueError:
return None, 'Invalid number'
# Validate count
if volumes and len(volumes) != fileCount:
return None, f'Volume count ({len(volumes)}) ≠ file count ({fileCount})'
return volumes, None
def toggleBulkVolume(self, checked):
"""Toggle volume field enabled state based on checkbox."""
self.volumeLine.setEnabled(checked)
if checked:
self.volumeLine.setText('')
self.volumeLine.setPlaceholderText('e.g., 5 or 1-10 or 1,3,5')
else:
self.volumeLine.setText('')
self.volumeLine.setPlaceholderText('(multiple files)')
def __init__(self):
self.ui = QDialog()
self.parser = None
@@ -1555,6 +1631,26 @@ class KCCGUI_MetaEditor(KCC_ui_editor.Ui_editorDialog):
self.bulkMode = False
self.setupUi(self.ui)
self.ui.setWindowFlags(self.ui.windowFlags() & ~Qt.WindowType.WindowContextHelpButtonHint)
# Create bulk volume editing widgets
self.bulkVolumeCheck = QCheckBox()
self.bulkVolumeCheck.setToolTip(
'<b>Bulk Volume Editing</b><br>'
'Check this box to assign volume numbers to multiple files.<br><br>'
'<b>Input formats:</b><br>'
'<code>5</code> → sequence starting from 5 (5, 6, 7...)<br>'
'<code>1-10</code> → range from 1 to 10<br>'
'<code>1, 3, 5</code> → specific values<br><br>'
'<i>Note: Files are sorted alphabetically before assignment.</i>'
)
self.bulkVolumeCheck.stateChanged.connect(self.toggleBulkVolume)
# Add widget to the grid layout at row 1 (Volume row), column 2
self.gridLayout.addWidget(self.bulkVolumeCheck, 1, 2, 1, 1)
# Hide by default (only shown in bulk mode)
self.bulkVolumeCheck.setVisible(False)
self.okButton.clicked.connect(self.saveData)
self.cancelButton.clicked.connect(self.ui.close)
if sys.platform.startswith('linux'):