Drag and drop fix
This commit is contained in:
parent
4bf2513f31
commit
415a3d64e8
@ -907,21 +907,22 @@ class UnifiedViewModel(QAbstractItemModel):
|
|||||||
stream = QDataStream(encoded_data, QIODevice.OpenModeFlag.WriteOnly)
|
stream = QDataStream(encoded_data, QIODevice.OpenModeFlag.WriteOnly)
|
||||||
|
|
||||||
# Store QPersistentModelIndex for robustness
|
# Store QPersistentModelIndex for robustness
|
||||||
persistent_indices = []
|
# Collect file paths of dragged FileRule items
|
||||||
|
file_paths = []
|
||||||
for index in indexes:
|
for index in indexes:
|
||||||
if index.isValid() and index.column() == 0:
|
if index.isValid() and index.column() == 0:
|
||||||
item = index.internalPointer()
|
item = index.internalPointer()
|
||||||
if isinstance(item, FileRule):
|
if isinstance(item, FileRule):
|
||||||
persistent_indices.append(QPersistentModelIndex(index))
|
file_paths.append(item.file_path)
|
||||||
log.debug(f"mimeData: Added persistent index for file: {Path(item.file_path).name}")
|
log.debug(f"mimeData: Added file path for file: {Path(item.file_path).name}")
|
||||||
|
|
||||||
# Write the number of items first, then each persistent index
|
# Write the number of items first, then each file path string
|
||||||
stream.writeInt32(len(persistent_indices)) # Use writeInt32 for potentially more items
|
stream.writeInt32(len(file_paths)) # Use writeInt32 for potentially more items
|
||||||
for p_index in persistent_indices:
|
for file_path in file_paths:
|
||||||
stream.writeQPersistentModelIndex(p_index)
|
stream.writeQString(file_path) # Use writeQString for strings
|
||||||
|
|
||||||
mime_data.setData(self.MIME_TYPE, encoded_data)
|
mime_data.setData(self.MIME_TYPE, encoded_data)
|
||||||
log.debug(f"mimeData: Encoded {len(persistent_indices)} FileRule persistent indices.")
|
log.debug(f"mimeData: Encoded {len(file_paths)} FileRule file paths.")
|
||||||
return mime_data
|
return mime_data
|
||||||
|
|
||||||
def canDropMimeData(self, data: QMimeData, action: Qt.DropAction, row: int, column: int, parent: QModelIndex) -> bool:
|
def canDropMimeData(self, data: QMimeData, action: Qt.DropAction, row: int, column: int, parent: QModelIndex) -> bool:
|
||||||
@ -956,48 +957,68 @@ class UnifiedViewModel(QAbstractItemModel):
|
|||||||
encoded_data = data.data(self.MIME_TYPE)
|
encoded_data = data.data(self.MIME_TYPE)
|
||||||
stream = QDataStream(encoded_data, QIODevice.OpenModeFlag.ReadOnly)
|
stream = QDataStream(encoded_data, QIODevice.OpenModeFlag.ReadOnly)
|
||||||
|
|
||||||
# Read QPersistentModelIndex objects
|
# Read file paths from the stream
|
||||||
persistent_indices = []
|
dragged_file_paths = []
|
||||||
num_items = stream.readInt32()
|
num_items = stream.readInt32()
|
||||||
log.debug(f"dropMimeData: Decoding {num_items} persistent indices.")
|
log.debug(f"dropMimeData: Decoding {num_items} file paths.")
|
||||||
for _ in range(num_items):
|
for _ in range(num_items):
|
||||||
p_index = stream.readQPersistentModelIndex()
|
dragged_file_paths.append(stream.readQString()) # Use readQString for strings
|
||||||
if p_index.isValid():
|
|
||||||
persistent_indices.append(p_index)
|
log.debug(f"dropMimeData: Decoded {len(dragged_file_paths)} file paths. Target Asset: '{target_asset_item.asset_name}'")
|
||||||
|
|
||||||
|
if not dragged_file_paths:
|
||||||
|
log.warning("dropMimeData: No file path information decoded.")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Find the current FileRule objects and their indices based on file paths
|
||||||
|
dragged_items_with_indices = []
|
||||||
|
for file_path in dragged_file_paths:
|
||||||
|
found_item = None
|
||||||
|
found_index = QModelIndex()
|
||||||
|
# Iterate through the model to find the FileRule object by file_path
|
||||||
|
for sr_row, source_rule in enumerate(self._source_rules):
|
||||||
|
for ar_row, asset_rule in enumerate(source_rule.assets):
|
||||||
|
for fr_row, file_rule in enumerate(asset_rule.files):
|
||||||
|
if file_rule.file_path == file_path:
|
||||||
|
found_item = file_rule
|
||||||
|
# Get the current index for this item
|
||||||
|
parent_asset_index = self.index(ar_row, 0, self.createIndex(sr_row, 0, source_rule))
|
||||||
|
if parent_asset_index.isValid():
|
||||||
|
found_index = self.index(fr_row, 0, parent_asset_index)
|
||||||
|
if found_index.isValid():
|
||||||
|
dragged_items_with_indices.append((found_item, found_index))
|
||||||
|
log.debug(f"dropMimeData: Found item and index for file: {Path(file_path).name}")
|
||||||
else:
|
else:
|
||||||
log.warning("dropMimeData: Decoded invalid persistent index. Skipping.")
|
log.warning(f"dropMimeData: Could not get valid index for found file item: {Path(file_path).name}")
|
||||||
|
else:
|
||||||
|
log.warning(f"dropMimeData: Could not get valid parent asset index for found file item: {Path(file_path).name}")
|
||||||
|
break # Found the file rule, move to the next dragged file path
|
||||||
|
if found_item: break # Found the file rule, move to the next dragged file path
|
||||||
|
if found_item: break # Found the file rule, move to the next dragged file path
|
||||||
|
|
||||||
log.debug(f"dropMimeData: Decoded {len(persistent_indices)} valid persistent indices. Target Asset: '{target_asset_item.asset_name}'")
|
if not found_item:
|
||||||
|
log.warning(f"dropMimeData: Could not find FileRule item for path: {file_path}. Skipping.")
|
||||||
|
|
||||||
if not persistent_indices:
|
|
||||||
log.warning("dropMimeData: No valid persistent index information decoded.")
|
if not dragged_items_with_indices:
|
||||||
|
log.warning("dropMimeData: No valid FileRule items found in the model for the dragged paths.")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Keep track of original parents that might become empty
|
# Keep track of original parents that might become empty
|
||||||
original_parents_to_check = set()
|
original_parents_to_check = set()
|
||||||
moved_files_new_indices = {}
|
moved_files_new_indices = {}
|
||||||
|
|
||||||
# Process moves using the persistent indices
|
# Process moves using the retrieved items and their current indices
|
||||||
for p_source_index in persistent_indices:
|
for file_item, source_file_index in dragged_items_with_indices:
|
||||||
# Convert persistent index back to a model index
|
|
||||||
source_file_index = QModelIndex(p_source_index)
|
|
||||||
|
|
||||||
if not source_file_index.isValid():
|
|
||||||
log.warning(f"dropMimeData: Persistent index is no longer valid. Skipping item.")
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Get the file item
|
|
||||||
file_item = source_file_index.internalPointer()
|
|
||||||
if not isinstance(file_item, FileRule):
|
|
||||||
log.error(f"dropMimeData: Index points to non-FileRule item after conversion. Skipping.")
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Track original parent for cleanup using the parent back-reference
|
# Track original parent for cleanup using the parent back-reference
|
||||||
old_parent_asset = getattr(file_item, 'parent_asset', None)
|
old_parent_asset = getattr(file_item, 'parent_asset', None)
|
||||||
if old_parent_asset and isinstance(old_parent_asset, AssetRule):
|
if old_parent_asset and isinstance(old_parent_asset, AssetRule):
|
||||||
original_parents_to_check.add(old_parent_asset)
|
source_rule = getattr(old_parent_asset, 'parent_source', None)
|
||||||
|
if source_rule:
|
||||||
|
# Store a hashable representation (tuple of identifiers)
|
||||||
|
original_parents_to_check.add((source_rule.input_path, old_parent_asset.asset_name))
|
||||||
else:
|
else:
|
||||||
log.warning(f"dropMimeData: File '{Path(file_item.file_path).name}' has no valid parent asset reference for cleanup tracking.")
|
log.warning(f"dropMimeData: Original parent asset '{old_parent_asset.asset_name}' has no parent source reference for cleanup tracking.")
|
||||||
|
|
||||||
|
|
||||||
# Perform the move using the model's method and the valid source_file_index
|
# Perform the move using the model's method and the valid source_file_index
|
||||||
@ -1009,16 +1030,25 @@ class UnifiedViewModel(QAbstractItemModel):
|
|||||||
if file_item.target_asset_name_override != target_asset_item.asset_name:
|
if file_item.target_asset_name_override != target_asset_item.asset_name:
|
||||||
log.debug(f" Updating target override for '{Path(file_item.file_path).name}' to '{target_asset_item.asset_name}'")
|
log.debug(f" Updating target override for '{Path(file_item.file_path).name}' to '{target_asset_item.asset_name}'")
|
||||||
file_item.target_asset_name_override = target_asset_item.asset_name
|
file_item.target_asset_name_override = target_asset_item.asset_name
|
||||||
# Need the *new* index of the moved file to emit dataChanged
|
# Need the *new* index of the moved file to emit dataChanged AND the override changed signal
|
||||||
try:
|
try:
|
||||||
# Find the new row of the file item within the target parent's list
|
# Find the new row of the file item within the target parent's list
|
||||||
new_row = target_asset_item.files.index(file_item)
|
new_row = target_asset_item.files.index(file_item)
|
||||||
# Create the index for the target asset column
|
# Create the index for the target asset column (for dataChanged)
|
||||||
new_file_index_target_col = self.index(new_row, self.COL_TARGET_ASSET, parent)
|
new_file_index_target_col = self.index(new_row, self.COL_TARGET_ASSET, parent)
|
||||||
if new_file_index_target_col.isValid():
|
if new_file_index_target_col.isValid():
|
||||||
moved_files_new_indices[file_item.file_path] = new_file_index_target_col
|
moved_files_new_indices[file_item.file_path] = new_file_index_target_col
|
||||||
else:
|
else:
|
||||||
log.warning(f" Could not get valid *new* index for target column of moved file: {Path(file_item.file_path).name}")
|
log.warning(f" Could not get valid *new* index for target column of moved file: {Path(file_item.file_path).name}")
|
||||||
|
|
||||||
|
# Emit the targetAssetOverrideChanged signal for the handler
|
||||||
|
new_file_index_col_0 = self.index(new_row, 0, parent) # Index for column 0
|
||||||
|
if new_file_index_col_0.isValid():
|
||||||
|
self.targetAssetOverrideChanged.emit(file_item, target_asset_item.asset_name, new_file_index_col_0)
|
||||||
|
log.debug(f" Emitted targetAssetOverrideChanged for '{Path(file_item.file_path).name}'")
|
||||||
|
else:
|
||||||
|
log.warning(f" Could not get valid *new* index for column 0 of moved file to emit signal: {Path(file_item.file_path).name}")
|
||||||
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
log.error(f" Could not find moved file '{Path(file_item.file_path).name}' in target parent's list after move.")
|
log.error(f" Could not find moved file '{Path(file_item.file_path).name}' in target parent's list after move.")
|
||||||
|
|
||||||
@ -1034,30 +1064,43 @@ class UnifiedViewModel(QAbstractItemModel):
|
|||||||
self.dataChanged.emit(new_index, new_index, [Qt.DisplayRole, Qt.EditRole])
|
self.dataChanged.emit(new_index, new_index, [Qt.DisplayRole, Qt.EditRole])
|
||||||
|
|
||||||
# --- Cleanup: Remove any original parent AssetRules that are now empty ---
|
# --- Cleanup: Remove any original parent AssetRules that are now empty ---
|
||||||
log.debug(f"dropMimeData: Checking original parents for cleanup: {[asset.asset_name for asset in original_parents_to_check]}")
|
log.debug(f"dropMimeData: Checking original parents for cleanup: {[f'{path}/{name}' for path, name in original_parents_to_check]}")
|
||||||
# Convert set to list to iterate and allow removal from the model
|
# Convert set to list to iterate
|
||||||
for asset_rule_to_check in list(original_parents_to_check):
|
for source_path, asset_name_to_check in list(original_parents_to_check):
|
||||||
|
found_asset_rule_to_check = None
|
||||||
|
# Find the AssetRule object based on source_path and asset_name
|
||||||
|
for source_rule in self._source_rules:
|
||||||
|
if source_rule.input_path == source_path:
|
||||||
|
for asset_rule in source_rule.assets:
|
||||||
|
if asset_rule.asset_name == asset_name_to_check:
|
||||||
|
found_asset_rule_to_check = asset_rule
|
||||||
|
break
|
||||||
|
if found_asset_rule_to_check: break
|
||||||
|
|
||||||
|
if found_asset_rule_to_check:
|
||||||
try:
|
try:
|
||||||
# Re-check if the asset is still in the model and is now empty
|
# Re-check if the asset is still in the model and is now empty
|
||||||
# Use parent back-reference to find the source rule
|
# Use parent back-reference to find the source rule (should be the same as source_rule found above)
|
||||||
source_rule = getattr(asset_rule_to_check, 'parent_source', None)
|
source_rule = getattr(found_asset_rule_to_check, 'parent_source', None)
|
||||||
if source_rule:
|
if source_rule:
|
||||||
# Check if the asset rule is still in its parent's list
|
# Check if the asset rule is still in its parent's list
|
||||||
if asset_rule_to_check in source_rule.assets:
|
if found_asset_rule_to_check in source_rule.assets:
|
||||||
if not asset_rule_to_check.files and asset_rule_to_check is not target_asset_item:
|
if not found_asset_rule_to_check.files and found_asset_rule_to_check is not target_asset_item:
|
||||||
log.info(f"dropMimeData: Attempting cleanup of now empty original parent: '{asset_rule_to_check.asset_name}'")
|
log.info(f"dropMimeData: Attempting cleanup of now empty original parent: '{found_asset_rule_to_check.asset_name}'")
|
||||||
if not self.removeAssetRule(asset_rule_to_check):
|
if not self.removeAssetRule(found_asset_rule_to_check):
|
||||||
log.warning(f"dropMimeData: Failed to remove empty original parent '{asset_rule_to_check.asset_name}'.")
|
log.warning(f"dropMimeData: Failed to remove empty original parent '{found_asset_rule_to_check.asset_name}'.")
|
||||||
elif asset_rule_to_check.files:
|
elif found_asset_rule_to_check.files:
|
||||||
log.debug(f"dropMimeData: Original parent '{asset_rule_to_check.asset_name}' is not empty after moves. Skipping cleanup.")
|
log.debug(f"dropMimeData: Original parent '{found_asset_rule_to_check.asset_name}' is not empty after moves. Skipping cleanup.")
|
||||||
# If it's the target asset, we don't remove it
|
# If it's the target asset, we don't remove it
|
||||||
else:
|
else:
|
||||||
log.warning(f"dropMimeData: Cleanup check failed. Original parent asset '{asset_rule_to_check.asset_name}' not found in its source rule's list.")
|
log.warning(f"dropMimeData: Cleanup check failed. Original parent asset '{found_asset_rule_to_check.asset_name}' not found in its source rule's list.")
|
||||||
else:
|
else:
|
||||||
log.warning(f"dropMimeData: Cleanup check failed. Original parent asset '{asset_rule_to_check.asset_name}' has no parent source reference.")
|
log.warning(f"dropMimeData: Cleanup check failed. Original parent asset '{found_asset_rule_to_check.asset_name}' has no parent source reference.")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.exception(f"dropMimeData: Error during cleanup check for parent '{asset_rule_to_check.asset_name}': {e}")
|
log.exception(f"dropMimeData: Error during cleanup check for parent '{found_asset_rule_to_check.asset_name}': {e}")
|
||||||
|
else:
|
||||||
|
log.warning(f"dropMimeData: Could not find original parent asset '{asset_name_to_check}' for cleanup.")
|
||||||
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
Loading…
x
Reference in New Issue
Block a user