From c139215603c2a76fd05e3220ed8d0343d547e3b0 Mon Sep 17 00:00:00 2001 From: Keith Edmunds Date: Sat, 22 Jun 2024 21:52:08 +0100 Subject: [PATCH] Improve drag and drop targetting --- app/playlists.py | 16 ++++++- archive/dragdrop.py | 101 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+), 2 deletions(-) create mode 100755 archive/dragdrop.py diff --git a/app/playlists.py b/app/playlists.py index 8f49172..d77a1ac 100644 --- a/app/playlists.py +++ b/app/playlists.py @@ -271,8 +271,20 @@ class PlaylistTab(QTableView): from_rows = self.selected_model_row_numbers() to_index = self.indexAt(event.position().toPoint()) - to_model_row = self.proxy_model.mapToSource(to_index).row() - log.info(f"PlaylistTab.dropEvent(): {from_rows=}, {to_index=}, {to_model_row=}") + if ( + self.dropIndicatorPosition() + == QAbstractItemView.DropIndicatorPosition.BelowItem + ): + internal_id = to_index.internalId() + proxy_index = self.proxy_model.createIndex( + to_index.row() + 1, to_index.column(), internal_id + ) + else: + proxy_index = to_index + to_model_row = self.proxy_model.mapToSource(proxy_index).row() + log.info( + f"PlaylistTab.dropEvent(): {from_rows=}, {proxy_index=}, {to_model_row=}" + ) if ( 0 <= min(from_rows) <= self.source_model.rowCount() diff --git a/archive/dragdrop.py b/archive/dragdrop.py new file mode 100755 index 0000000..ce00b48 --- /dev/null +++ b/archive/dragdrop.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 + +# https://stackoverflow.com/questions/26227885/drag-and-drop-rows-within-qtablewidget + +import sys + +from PyQt6.QtWidgets import ( + QTableWidget, + QAbstractItemView, + QTableWidgetItem, + QWidget, + QHBoxLayout, + QApplication, +) +from PyQt6.QtCore import Qt + + +class TableWidgetDragRows(QTableWidget): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + self.setDragEnabled(True) + self.setAcceptDrops(True) + self.viewport().setAcceptDrops(True) + self.setDragDropOverwriteMode(False) + self.setDropIndicatorShown(True) + + self.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection) + self.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows) + self.setDragDropMode(QAbstractItemView.DragDropMode.InternalMove) + self.DropIndicatorPosition(QAbstractItemView.DropIndicatorPosition.BelowItem) + + def dropEvent(self, event): + if event.source() == self: + rows = set([mi.row() for mi in self.selectedIndexes()]) + targetRow = self.indexAt(event.position().toPoint()).row() + if self.dropIndicatorPosition() == QAbstractItemView.DropIndicatorPosition.BelowItem: + targetRow += 1 + rows.discard(targetRow) + rows = sorted(rows) + if not rows: + return + if targetRow == -1: + targetRow = self.rowCount() + for _ in range(len(rows)): + self.insertRow(targetRow) + rowMapping = dict() # Src row to target row. + for idx, row in enumerate(rows): + if row < targetRow: + rowMapping[row] = targetRow + idx + else: + rowMapping[row + len(rows)] = targetRow + idx + colCount = self.columnCount() + for srcRow, tgtRow in sorted(rowMapping.items()): + for col in range(0, colCount): + self.setItem(tgtRow, col, self.takeItem(srcRow, col)) + for row in reversed(sorted(rowMapping.keys())): + self.removeRow(row) + event.accept() + return + + +class Window(QWidget): + def __init__(self): + super(Window, self).__init__() + + layout = QHBoxLayout() + self.setLayout(layout) + + self.table_widget = TableWidgetDragRows() + layout.addWidget(self.table_widget) + + # setup table widget + self.table_widget.setColumnCount(2) + self.table_widget.setHorizontalHeaderLabels(["Type", "Name"]) + + items = [ + ("Red", "Toyota"), + ("Blue", "RV"), + ("Green", "Beetle"), + ("Silver", "Chevy"), + ("Black", "BMW"), + ] + self.table_widget.setRowCount(len(items)) + for i, (color, model) in enumerate(items): + item_flags = Qt.ItemFlag.ItemIsSelectable | Qt.ItemFlag.ItemIsDragEnabled + colour_item = QTableWidgetItem(color) + colour_item.setFlags(item_flags) + model_item = QTableWidgetItem(model) + model_item.setFlags(item_flags) + self.table_widget.setItem(i, 0, QTableWidgetItem(color)) + self.table_widget.setItem(i, 1, QTableWidgetItem(model)) + + self.resize(400, 400) + self.show() + + +if __name__ == "__main__": + app = QApplication(sys.argv) + window = Window() + sys.exit(app.exec())