Created
August 27, 2014 03:49
-
-
Save oglops/c7e3988da49e462f2c30 to your computer and use it in GitHub Desktop.
fix dragging selection and checkbox toggling
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from PyQt4 import QtGui, QtCore | |
from PyQt4.QtCore import Qt, QString | |
import sys | |
import os | |
class ThumbListWidget(QtGui.QListWidget): | |
_rows_to_del = [] | |
def __init__(self, type, parent=None): | |
super(ThumbListWidget, self).__init__(parent) | |
self.setIconSize(QtCore.QSize(124, 124)) | |
self.setDragDropMode(QtGui.QAbstractItemView.DragDrop) | |
self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) | |
self.setAcceptDrops(True) | |
self._dropping = False | |
self.setSelectionRectVisible(True) | |
self.connect(self, QtCore.SIGNAL("dropped"), self.items_dropped) | |
def dragEnterEvent(self, event): | |
if event.mimeData().hasUrls(): | |
event.accept() | |
else: | |
super(ThumbListWidget, self).dragEnterEvent(event) | |
def dragMoveEvent(self, event): | |
if event.mimeData().hasUrls(): | |
event.setDropAction(QtCore.Qt.CopyAction) | |
event.accept() | |
else: | |
super(ThumbListWidget, self).dragMoveEvent(event) | |
def dropEvent(self, event): | |
if event.mimeData().hasUrls(): | |
event.setDropAction(QtCore.Qt.CopyAction) | |
event.accept() | |
links = [] | |
for url in event.mimeData().urls(): | |
links.append(str(url.toLocalFile())) | |
self.emit(QtCore.SIGNAL("dropped"), links) | |
else: | |
if event.source() is self: | |
event.setDropAction(QtCore.Qt.MoveAction) | |
else: | |
event.setDropAction(QtCore.Qt.CopyAction) | |
self._dropping = True | |
super(ThumbListWidget, self).dropEvent(event) | |
self._dropping = False | |
def rowsInserted(self, parent, start, end): | |
if self._dropping: | |
self.emit(QtCore.SIGNAL("dropped"), (start, end)) | |
super(ThumbListWidget, self).rowsInserted(parent, start, end) | |
def dataChanged(self, start, end): | |
if self._dropping: | |
for row in range(start.row(), end.row() + 1): | |
index = self.indexFromItem(self.item(row)) | |
shot = index.data().toString() | |
# print len(self.findItems(shot, Qt.MatchExactly)) | |
if len(self.findItems(shot, Qt.MatchExactly)) > 1: | |
self._rows_to_del.append(row) | |
self._rows_to_del.reverse() | |
for row in self._rows_to_del: | |
self.takeItem(row) | |
self._rows_to_del = [] | |
def items_dropped(self, arg): | |
start, end = arg | |
print range(start, end + 1) | |
for row in range(start, end + 1): | |
item = self.item(row) | |
item.setFlags(item.flags() | Qt.ItemIsUserCheckable) | |
item.setCheckState(Qt.Checked) | |
def keyPressEvent(self, event): | |
if event.key() == Qt.Key_Space: | |
if self.selectedItems(): | |
new_state = Qt.Unchecked if self.selectedItems()[0].checkState() else Qt.Checked | |
for item in self.selectedItems(): | |
if item.flags() & Qt.ItemIsUserCheckable: | |
# print 'set new state:', new_state | |
item.setCheckState(new_state) | |
self.viewport().update() | |
elif event.key() == Qt.Key_Delete: | |
for item in self.selectedItems(): | |
self.takeItem(self.row(item)) | |
def mousePressEvent(self, event): | |
# check if clicked within previously selected area | |
self._drag = False | |
selectedItems = self.selectedItems() | |
if selectedItems: | |
for sel_item in selectedItems: | |
if self.visualItemRect(sel_item).contains(event.pos()): | |
self._drag = True | |
break | |
self.mousePressPos = (event.pos()) | |
QtGui.QListWidget.mousePressEvent(self, event) | |
def mouseReleaseEvent(self, event): | |
item = self.selectedCheckStateItem(event.pos()) | |
if item: | |
selectedItems = self.selectedItems() | |
new_state = Qt.Unchecked if item.checkState() == Qt.Checked else Qt.Checked | |
self.setSelectedCheckStates(new_state, item) | |
# QtGui.QApplication.processEvents() | |
self.viewport().update() | |
QtGui.QListWidget.mouseReleaseEvent(self, event) | |
if item: | |
for sel_item in selectedItems: | |
sel_item.setSelected(True) | |
def setSelectedCheckStates(self, state, click_item): | |
for item in self.selectedItems(): | |
if item is not click_item: | |
item.setCheckState(state) | |
def selectedCheckStateItem(self, pos): | |
item = self.itemAt(pos) | |
if item: | |
opt = QtGui.QStyleOptionButton() | |
opt.rect = self.visualItemRect(item) | |
rect = self.style().subElementRect(QtGui.QStyle.SE_ViewItemCheckIndicator, opt) | |
if item in self.selectedItems() and rect.contains(pos): | |
return item | |
return 0 | |
def mouseMoveEvent(self, event): | |
if (event.pos() - self.mousePressPos).manhattanLength() > QtGui.QApplication.startDragDistance(): | |
item = self.itemAt(event.pos()) | |
if item and not self._drag: | |
rect = self.visualItemRect(item) | |
self.setState(QtGui.QAbstractItemView.DragSelectingState) | |
QtGui.QListWidget.mouseMoveEvent(self, event) | |
class Dialog_01(QtGui.QMainWindow): | |
def __init__(self): | |
super(QtGui.QMainWindow, self).__init__() | |
self.listItems = {} | |
myQWidget = QtGui.QWidget() | |
myBoxLayout = QtGui.QVBoxLayout() | |
myQWidget.setLayout(myBoxLayout) | |
self.setCentralWidget(myQWidget) | |
self.listWidgetA = ThumbListWidget(self) | |
for i in range(12): | |
QtGui.QListWidgetItem('Item ' + str(i), self.listWidgetA) | |
all_items = self.listWidgetA.findItems(QString('*'), Qt.MatchWrap | Qt.MatchWildcard) | |
for item in all_items: | |
item.setFlags(item.flags() & ~Qt.ItemIsUserCheckable) | |
myBoxLayout.addWidget(self.listWidgetA) | |
self.listWidgetB = ThumbListWidget(self) | |
self.listWidgetA.setAcceptDrops(False) | |
myBoxLayout.addWidget(self.listWidgetB) | |
if __name__ == '__main__': | |
app = QtGui.QApplication(sys.argv) | |
dialog_1 = Dialog_01() | |
dialog_1.show() | |
dialog_1.resize(480, 320) | |
sys.exit(app.exec_()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment