v0.9.23
This commit is contained in:
@@ -14,7 +14,7 @@ Classes:
|
|||||||
MainWindow: The main application window containing the thumbnail grid and docks.
|
MainWindow: The main application window containing the thumbnail grid and docks.
|
||||||
"""
|
"""
|
||||||
__appname__ = "BagheeraView"
|
__appname__ = "BagheeraView"
|
||||||
__version__ = "0.9.22"
|
__version__ = "0.9.23"
|
||||||
__author__ = "Ignacio Serantes"
|
__author__ = "Ignacio Serantes"
|
||||||
__email__ = "kde@aynoa.net"
|
__email__ = "kde@aynoa.net"
|
||||||
__license__ = "LGPL"
|
__license__ = "LGPL"
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ if FORCE_X11:
|
|||||||
# --- CONFIGURATION ---
|
# --- CONFIGURATION ---
|
||||||
PROG_NAME = "Bagheera Image Viewer"
|
PROG_NAME = "Bagheera Image Viewer"
|
||||||
PROG_ID = "bagheeraview"
|
PROG_ID = "bagheeraview"
|
||||||
PROG_VERSION = "0.9.22"
|
PROG_VERSION = "0.9.23"
|
||||||
PROG_AUTHOR = "Ignacio Serantes"
|
PROG_AUTHOR = "Ignacio Serantes"
|
||||||
|
|
||||||
# --- CACHE SETTINGS ---
|
# --- CACHE SETTINGS ---
|
||||||
@@ -852,6 +852,7 @@ _UI_TEXTS = {
|
|||||||
"PROPERTIES_TABLE_HEADER": ["Property", "Value"],
|
"PROPERTIES_TABLE_HEADER": ["Property", "Value"],
|
||||||
"PROPERTIES_ADD_ATTR": "Add Attribute",
|
"PROPERTIES_ADD_ATTR": "Add Attribute",
|
||||||
"PROPERTIES_ADD_ATTR_NAME": "Attribute Name (e.g. user.comment):",
|
"PROPERTIES_ADD_ATTR_NAME": "Attribute Name (e.g. user.comment):",
|
||||||
|
"PROPERTIES_DELETE_ALL": "Delete All",
|
||||||
"PROPERTIES_ADD_ATTR_VALUE": "Value for {}:",
|
"PROPERTIES_ADD_ATTR_VALUE": "Value for {}:",
|
||||||
"PROPERTIES_ERROR_SET_ATTR": "Failed to set xattr: {}",
|
"PROPERTIES_ERROR_SET_ATTR": "Failed to set xattr: {}",
|
||||||
"PROPERTIES_ERROR_ADD_ATTR": "Failed to add xattr: {}",
|
"PROPERTIES_ERROR_ADD_ATTR": "Failed to add xattr: {}",
|
||||||
@@ -1403,6 +1404,7 @@ _UI_TEXTS = {
|
|||||||
"PROPERTIES_TABLE_HEADER": ["Propiedad", "Valor"],
|
"PROPERTIES_TABLE_HEADER": ["Propiedad", "Valor"],
|
||||||
"PROPERTIES_ADD_ATTR": "Añadir Atributo",
|
"PROPERTIES_ADD_ATTR": "Añadir Atributo",
|
||||||
"PROPERTIES_ADD_ATTR_NAME": "Nombre del Atributo (ej. user.comment):",
|
"PROPERTIES_ADD_ATTR_NAME": "Nombre del Atributo (ej. user.comment):",
|
||||||
|
"PROPERTIES_DELETE_ALL": "Borrar Todo",
|
||||||
"PROPERTIES_ADD_ATTR_VALUE": "Valor para {}:",
|
"PROPERTIES_ADD_ATTR_VALUE": "Valor para {}:",
|
||||||
"PROPERTIES_ERROR_SET_ATTR": "Fallo al establecer xattr: {}",
|
"PROPERTIES_ERROR_SET_ATTR": "Fallo al establecer xattr: {}",
|
||||||
"PROPERTIES_ERROR_ADD_ATTR": "Fallo al añadir xattr: {}",
|
"PROPERTIES_ERROR_ADD_ATTR": "Fallo al añadir xattr: {}",
|
||||||
@@ -1954,6 +1956,7 @@ _UI_TEXTS = {
|
|||||||
"PROPERTIES_TABLE_HEADER": ["Propiedade", "Valor"],
|
"PROPERTIES_TABLE_HEADER": ["Propiedade", "Valor"],
|
||||||
"PROPERTIES_ADD_ATTR": "Engadir Atributo",
|
"PROPERTIES_ADD_ATTR": "Engadir Atributo",
|
||||||
"PROPERTIES_ADD_ATTR_NAME": "Nome do Atributo (ex. user.comment):",
|
"PROPERTIES_ADD_ATTR_NAME": "Nome do Atributo (ex. user.comment):",
|
||||||
|
"PROPERTIES_DELETE_ALL": "Borrar Todo",
|
||||||
"PROPERTIES_ADD_ATTR_VALUE": "Valor para {}:",
|
"PROPERTIES_ADD_ATTR_VALUE": "Valor para {}:",
|
||||||
"PROPERTIES_ERROR_SET_ATTR": "Fallo ao establecer xattr: {}",
|
"PROPERTIES_ERROR_SET_ATTR": "Fallo ao establecer xattr: {}",
|
||||||
"PROPERTIES_ERROR_ADD_ATTR": "Fallo ao engadir xattr: {}",
|
"PROPERTIES_ERROR_ADD_ATTR": "Fallo ao engadir xattr: {}",
|
||||||
|
|||||||
@@ -3331,7 +3331,7 @@ class ImageViewer(QWidget):
|
|||||||
# Speed 1 (slowest) requires a full 120 delta.
|
# Speed 1 (slowest) requires a full 120 delta.
|
||||||
# Speed 10 (fastest) requires 120/10 = 12 delta.
|
# Speed 10 (fastest) requires 120/10 = 12 delta.
|
||||||
# Still too fast so speed / 2.
|
# Still too fast so speed / 2.
|
||||||
threshold = 120 / speed / 2
|
threshold = 120 / speed * 2
|
||||||
|
|
||||||
self._wheel_scroll_accumulator += event.angleDelta().y()
|
self._wheel_scroll_accumulator += event.angleDelta().y()
|
||||||
|
|
||||||
|
|||||||
@@ -121,6 +121,43 @@ class MetadataManager:
|
|||||||
|
|
||||||
return all_metadata
|
return all_metadata
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def write_metadata(path, metadata_dict):
|
||||||
|
"""
|
||||||
|
Writes EXIF, IPTC, and XMP metadata back to a file.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
path (str): The path to the image file.
|
||||||
|
metadata_dict (dict): A dictionary of metadata keys and values.
|
||||||
|
"""
|
||||||
|
if not HAVE_EXIV2:
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
image = exiv2.ImageFactory.open(path)
|
||||||
|
image.readMetadata()
|
||||||
|
|
||||||
|
exif = image.exifData()
|
||||||
|
iptc = image.iptcData()
|
||||||
|
xmp = image.xmpData()
|
||||||
|
|
||||||
|
for key, value in metadata_dict.items():
|
||||||
|
try:
|
||||||
|
if key.startswith("Exif."):
|
||||||
|
exif[key] = str(value)
|
||||||
|
elif key.startswith("Iptc."):
|
||||||
|
iptc[key] = str(value)
|
||||||
|
elif key.startswith("Xmp."):
|
||||||
|
xmp[key] = str(value)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error setting metadata key {key}: {e}")
|
||||||
|
|
||||||
|
image.writeMetadata()
|
||||||
|
notify_baloo(path)
|
||||||
|
mark_app_modified(path)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error writing metadata for {path}: {e}")
|
||||||
|
|
||||||
|
|
||||||
class XattrManager:
|
class XattrManager:
|
||||||
"""A manager class to handle reading and writing extended attributes (xattrs)."""
|
"""A manager class to handle reading and writing extended attributes (xattrs)."""
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ Classes:
|
|||||||
from PySide6.QtWidgets import (
|
from PySide6.QtWidgets import (
|
||||||
QWidget, QLabel, QVBoxLayout, QMessageBox, QMenu, QInputDialog,
|
QWidget, QLabel, QVBoxLayout, QMessageBox, QMenu, QInputDialog,
|
||||||
QDialog, QTableWidget, QTableWidgetItem, QHeaderView, QTabWidget,
|
QDialog, QTableWidget, QTableWidgetItem, QHeaderView, QTabWidget,
|
||||||
QFormLayout, QDialogButtonBox, QApplication
|
QFormLayout, QDialogButtonBox, QApplication, QToolBar, QAbstractItemView
|
||||||
)
|
)
|
||||||
from PySide6.QtGui import (
|
from PySide6.QtGui import (
|
||||||
QImageReader, QIcon, QColor
|
QImageReader, QIcon, QColor
|
||||||
@@ -76,6 +76,8 @@ class PropertiesDialog(QDialog):
|
|||||||
self.setWindowTitle(UITexts.PROPERTIES_TITLE)
|
self.setWindowTitle(UITexts.PROPERTIES_TITLE)
|
||||||
self._initial_tags = initial_tags if initial_tags is not None else []
|
self._initial_tags = initial_tags if initial_tags is not None else []
|
||||||
self._initial_rating = initial_rating
|
self._initial_rating = initial_rating
|
||||||
|
self.original_xattrs = {}
|
||||||
|
self.original_exif = {}
|
||||||
self.loader = None
|
self.loader = None
|
||||||
self.resize(400, 500)
|
self.resize(400, 500)
|
||||||
self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint)
|
self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint)
|
||||||
@@ -136,6 +138,11 @@ class PropertiesDialog(QDialog):
|
|||||||
meta_widget = QWidget()
|
meta_widget = QWidget()
|
||||||
meta_layout = QVBoxLayout(meta_widget)
|
meta_layout = QVBoxLayout(meta_widget)
|
||||||
|
|
||||||
|
self.meta_toolbar = QToolBar()
|
||||||
|
self._setup_table_toolbar(self.meta_toolbar, self.on_add_meta, self.on_delete_meta,
|
||||||
|
self.on_delete_all_meta, self.on_save_meta, self.on_cancel_meta)
|
||||||
|
meta_layout.addWidget(self.meta_toolbar)
|
||||||
|
|
||||||
self.table = QTableWidget()
|
self.table = QTableWidget()
|
||||||
self.table.setColumnCount(2)
|
self.table.setColumnCount(2)
|
||||||
self.table.setHorizontalHeaderLabels(UITexts.PROPERTIES_TABLE_HEADER)
|
self.table.setHorizontalHeaderLabels(UITexts.PROPERTIES_TABLE_HEADER)
|
||||||
@@ -145,12 +152,12 @@ class PropertiesDialog(QDialog):
|
|||||||
self.table.setColumnWidth(0, self.width() * 0.4)
|
self.table.setColumnWidth(0, self.width() * 0.4)
|
||||||
self.table.verticalHeader().setVisible(False)
|
self.table.verticalHeader().setVisible(False)
|
||||||
self.table.setAlternatingRowColors(True)
|
self.table.setAlternatingRowColors(True)
|
||||||
self.table.setEditTriggers(QTableWidget.DoubleClicked |
|
self.table.setEditTriggers(QAbstractItemView.DoubleClicked |
|
||||||
QTableWidget.EditKeyPressed |
|
QAbstractItemView.EditKeyPressed |
|
||||||
QTableWidget.SelectedClicked)
|
QAbstractItemView.AnyKeyPressed)
|
||||||
self.table.setSelectionBehavior(QTableWidget.SelectRows)
|
self.table.setSelectionBehavior(QTableWidget.SelectRows)
|
||||||
|
self.table.setSelectionMode(QAbstractItemView.ExtendedSelection)
|
||||||
|
|
||||||
self.table.itemChanged.connect(self.on_item_changed)
|
|
||||||
self.table.setContextMenuPolicy(Qt.CustomContextMenu)
|
self.table.setContextMenuPolicy(Qt.CustomContextMenu)
|
||||||
self.table.customContextMenuRequested.connect(self.show_context_menu)
|
self.table.customContextMenuRequested.connect(self.show_context_menu)
|
||||||
|
|
||||||
@@ -164,6 +171,11 @@ class PropertiesDialog(QDialog):
|
|||||||
exif_widget = QWidget()
|
exif_widget = QWidget()
|
||||||
exif_layout = QVBoxLayout(exif_widget)
|
exif_layout = QVBoxLayout(exif_widget)
|
||||||
|
|
||||||
|
self.exif_toolbar = QToolBar()
|
||||||
|
self._setup_table_toolbar(self.exif_toolbar, self.on_add_exif, self.on_delete_exif,
|
||||||
|
self.on_delete_all_exif, self.on_save_exif, self.on_cancel_exif)
|
||||||
|
exif_layout.addWidget(self.exif_toolbar)
|
||||||
|
|
||||||
self.exif_table = QTableWidget()
|
self.exif_table = QTableWidget()
|
||||||
# This table will display EXIF/XMP/IPTC data.
|
# This table will display EXIF/XMP/IPTC data.
|
||||||
# Reading this data involves opening the file with exiv2, which is a disk read.
|
# Reading this data involves opening the file with exiv2, which is a disk read.
|
||||||
@@ -180,8 +192,11 @@ class PropertiesDialog(QDialog):
|
|||||||
1, QHeaderView.ResizeToContents)
|
1, QHeaderView.ResizeToContents)
|
||||||
self.exif_table.verticalHeader().setVisible(False)
|
self.exif_table.verticalHeader().setVisible(False)
|
||||||
self.exif_table.setAlternatingRowColors(True)
|
self.exif_table.setAlternatingRowColors(True)
|
||||||
self.exif_table.setEditTriggers(QTableWidget.NoEditTriggers)
|
self.exif_table.setEditTriggers(QAbstractItemView.DoubleClicked |
|
||||||
|
QAbstractItemView.EditKeyPressed |
|
||||||
|
QAbstractItemView.AnyKeyPressed)
|
||||||
self.exif_table.setSelectionBehavior(QTableWidget.SelectRows)
|
self.exif_table.setSelectionBehavior(QTableWidget.SelectRows)
|
||||||
|
self.exif_table.setSelectionMode(QAbstractItemView.ExtendedSelection)
|
||||||
self.exif_table.setContextMenuPolicy(Qt.CustomContextMenu)
|
self.exif_table.setContextMenuPolicy(Qt.CustomContextMenu)
|
||||||
# This is a disk read.
|
# This is a disk read.
|
||||||
self.exif_table.customContextMenuRequested.connect(self.show_exif_context_menu)
|
self.exif_table.customContextMenuRequested.connect(self.show_exif_context_menu)
|
||||||
@@ -204,6 +219,87 @@ class PropertiesDialog(QDialog):
|
|||||||
# Start background loading
|
# Start background loading
|
||||||
self.reload_metadata()
|
self.reload_metadata()
|
||||||
|
|
||||||
|
def _setup_table_toolbar(self, toolbar, add_slot, del_slot, del_all_slot, save_slot, cancel_slot):
|
||||||
|
"""Helper to populate toolbars with buttons."""
|
||||||
|
toolbar.addAction(QIcon.fromTheme("list-add"), UITexts.CREATE, add_slot)
|
||||||
|
toolbar.addAction(QIcon.fromTheme("list-remove"), UITexts.DELETE, del_slot)
|
||||||
|
toolbar.addAction(QIcon.fromTheme("edit-clear-all"), UITexts.PROPERTIES_DELETE_ALL, del_all_slot)
|
||||||
|
toolbar.addSeparator()
|
||||||
|
toolbar.addAction(QIcon.fromTheme("document-save"), UITexts.SAVE, save_slot)
|
||||||
|
toolbar.addAction(QIcon.fromTheme("edit-undo"), UITexts.CANCEL, cancel_slot)
|
||||||
|
|
||||||
|
def on_add_meta(self):
|
||||||
|
key, ok = QInputDialog.getText(self, UITexts.PROPERTIES_ADD_ATTR, UITexts.PROPERTIES_ADD_ATTR_NAME)
|
||||||
|
if ok and key:
|
||||||
|
row = self.table.rowCount()
|
||||||
|
self.table.insertRow(row)
|
||||||
|
self.table.setItem(row, 0, QTableWidgetItem(key))
|
||||||
|
v_item = QTableWidgetItem("")
|
||||||
|
self.table.setItem(row, 1, v_item)
|
||||||
|
self.table.setCurrentItem(v_item)
|
||||||
|
self.table.editItem(v_item)
|
||||||
|
|
||||||
|
def on_delete_meta(self):
|
||||||
|
rows = sorted(set(index.row() for index in self.table.selectedIndexes()), reverse=True)
|
||||||
|
for row in rows:
|
||||||
|
self.table.removeRow(row)
|
||||||
|
|
||||||
|
def on_delete_all_meta(self):
|
||||||
|
self.table.setRowCount(0)
|
||||||
|
|
||||||
|
def on_save_meta(self):
|
||||||
|
new_attrs = {}
|
||||||
|
for r in range(self.table.rowCount()):
|
||||||
|
k_item, v_item = self.table.item(r, 0), self.table.item(r, 1)
|
||||||
|
if k_item and v_item:
|
||||||
|
new_attrs[k_item.text()] = v_item.text()
|
||||||
|
try:
|
||||||
|
for k in self.original_xattrs:
|
||||||
|
if k not in new_attrs:
|
||||||
|
XattrManager.set_attribute(self.path, k, None)
|
||||||
|
for k, v in new_attrs.items():
|
||||||
|
XattrManager.set_attribute(self.path, k, v)
|
||||||
|
self.reload_metadata()
|
||||||
|
except Exception as e:
|
||||||
|
QMessageBox.warning(self, UITexts.ERROR, f"Error: {e}")
|
||||||
|
|
||||||
|
def on_cancel_meta(self):
|
||||||
|
self.update_metadata_table(self.original_xattrs)
|
||||||
|
|
||||||
|
def on_add_exif(self):
|
||||||
|
key, ok = QInputDialog.getText(self, UITexts.PROPERTIES_ADD_ATTR, UITexts.PROPERTIES_ADD_ATTR_NAME)
|
||||||
|
if ok and key:
|
||||||
|
row = self.exif_table.rowCount()
|
||||||
|
self.exif_table.insertRow(row)
|
||||||
|
self.exif_table.setItem(row, 0, QTableWidgetItem(key))
|
||||||
|
v_item = QTableWidgetItem("")
|
||||||
|
self.exif_table.setItem(row, 1, v_item)
|
||||||
|
self.exif_table.setCurrentItem(v_item)
|
||||||
|
self.exif_table.editItem(v_item)
|
||||||
|
|
||||||
|
def on_delete_exif(self):
|
||||||
|
rows = sorted(set(index.row() for index in self.exif_table.selectedIndexes()), reverse=True)
|
||||||
|
for row in rows:
|
||||||
|
self.exif_table.removeRow(row)
|
||||||
|
|
||||||
|
def on_delete_all_exif(self):
|
||||||
|
self.exif_table.setRowCount(0)
|
||||||
|
|
||||||
|
def on_save_exif(self):
|
||||||
|
new_exif = {}
|
||||||
|
for r in range(self.exif_table.rowCount()):
|
||||||
|
k_item, v_item = self.exif_table.item(r, 0), self.exif_table.item(r, 1)
|
||||||
|
if k_item and v_item:
|
||||||
|
new_exif[k_item.text()] = v_item.text()
|
||||||
|
try:
|
||||||
|
MetadataManager.write_metadata(self.path, new_exif)
|
||||||
|
self.reload_metadata()
|
||||||
|
except Exception as e:
|
||||||
|
QMessageBox.warning(self, UITexts.ERROR, f"Error: {e}")
|
||||||
|
|
||||||
|
def on_cancel_exif(self):
|
||||||
|
self.update_exif_table(self.original_exif)
|
||||||
|
|
||||||
def done(self, r):
|
def done(self, r):
|
||||||
if self.loader and self.loader.isRunning():
|
if self.loader and self.loader.isRunning():
|
||||||
self.loader.stop()
|
self.loader.stop()
|
||||||
@@ -232,6 +328,7 @@ class PropertiesDialog(QDialog):
|
|||||||
# Combine preloaded and newly read xattrs
|
# Combine preloaded and newly read xattrs
|
||||||
all_xattrs = preloaded_xattrs.copy()
|
all_xattrs = preloaded_xattrs.copy()
|
||||||
if not initial_only and disk_xattrs:
|
if not initial_only and disk_xattrs:
|
||||||
|
self.original_xattrs = disk_xattrs.copy()
|
||||||
# Disk data takes precedence or adds to it
|
# Disk data takes precedence or adds to it
|
||||||
all_xattrs.update(disk_xattrs)
|
all_xattrs.update(disk_xattrs)
|
||||||
|
|
||||||
@@ -242,9 +339,9 @@ class PropertiesDialog(QDialog):
|
|||||||
for key, val in all_xattrs.items():
|
for key, val in all_xattrs.items():
|
||||||
# QImageReader.textKeys() is not used here as it's not xattr.
|
# QImageReader.textKeys() is not used here as it's not xattr.
|
||||||
k_item = QTableWidgetItem(key)
|
k_item = QTableWidgetItem(key)
|
||||||
k_item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
|
k_item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable)
|
||||||
v_item = QTableWidgetItem(val)
|
v_item = QTableWidgetItem(val)
|
||||||
v_item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
|
v_item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable)
|
||||||
self.table.setItem(row, 0, k_item)
|
self.table.setItem(row, 0, k_item)
|
||||||
self.table.setItem(row, 1, v_item)
|
self.table.setItem(row, 1, v_item)
|
||||||
row += 1
|
row += 1
|
||||||
@@ -303,6 +400,7 @@ class PropertiesDialog(QDialog):
|
|||||||
self.exif_table.blockSignals(False)
|
self.exif_table.blockSignals(False)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
self.original_exif = exif_data.copy()
|
||||||
self.exif_table.setRowCount(len(exif_data))
|
self.exif_table.setRowCount(len(exif_data))
|
||||||
error_color = QColor("red")
|
error_color = QColor("red")
|
||||||
error_text_lower = UITexts.ERROR.lower()
|
error_text_lower = UITexts.ERROR.lower()
|
||||||
@@ -310,9 +408,9 @@ class PropertiesDialog(QDialog):
|
|||||||
|
|
||||||
for row, (key, value) in enumerate(sorted(exif_data.items())):
|
for row, (key, value) in enumerate(sorted(exif_data.items())):
|
||||||
k_item = QTableWidgetItem(str(key))
|
k_item = QTableWidgetItem(str(key))
|
||||||
k_item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
|
k_item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable)
|
||||||
v_item = QTableWidgetItem(str(value))
|
v_item = QTableWidgetItem(str(value))
|
||||||
v_item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
|
v_item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable)
|
||||||
|
|
||||||
key_str_lower = str(key).lower()
|
key_str_lower = str(key).lower()
|
||||||
val_str_lower = str(value).lower()
|
val_str_lower = str(value).lower()
|
||||||
@@ -328,25 +426,6 @@ class PropertiesDialog(QDialog):
|
|||||||
|
|
||||||
self.exif_table.blockSignals(False)
|
self.exif_table.blockSignals(False)
|
||||||
|
|
||||||
def on_item_changed(self, item):
|
|
||||||
"""
|
|
||||||
Slot that triggers when an item in the metadata table is changed.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
item (QTableWidgetItem): The item that was changed.
|
|
||||||
"""
|
|
||||||
if item.column() == 1:
|
|
||||||
key = self.table.item(item.row(), 0).text()
|
|
||||||
val = item.text()
|
|
||||||
# Treat empty or whitespace-only values as removal to match previous
|
|
||||||
# behavior
|
|
||||||
val_to_set = val if val.strip() else None
|
|
||||||
try:
|
|
||||||
XattrManager.set_attribute(self.path, key, val_to_set)
|
|
||||||
except Exception as e:
|
|
||||||
QMessageBox.warning(self, UITexts.ERROR,
|
|
||||||
UITexts.PROPERTIES_ERROR_SET_ATTR.format(e))
|
|
||||||
|
|
||||||
def show_context_menu(self, pos):
|
def show_context_menu(self, pos):
|
||||||
"""
|
"""
|
||||||
Displays a context menu in the metadata table.
|
Displays a context menu in the metadata table.
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "bagheeraview"
|
name = "bagheeraview"
|
||||||
version = "0.9.22"
|
version = "0.9.23"
|
||||||
authors = [
|
authors = [
|
||||||
{ name = "Ignacio Serantes" }
|
{ name = "Ignacio Serantes" }
|
||||||
]
|
]
|
||||||
|
|||||||
2
setup.py
2
setup.py
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="bagheeraview",
|
name="bagheeraview",
|
||||||
version="0.9.22",
|
version="0.9.23",
|
||||||
author="Ignacio Serantes",
|
author="Ignacio Serantes",
|
||||||
description="Bagheera Image Viewer - An image viewer for KDE with Baloo in mind",
|
description="Bagheera Image Viewer - An image viewer for KDE with Baloo in mind",
|
||||||
long_description="A fast image viewer built with PySide6, featuring search and "
|
long_description="A fast image viewer built with PySide6, featuring search and "
|
||||||
|
|||||||
Reference in New Issue
Block a user