mirror of
https://github.com/fergalmoran/picard.git
synced 2026-03-01 02:54:01 +00:00
Introduce SortableCheckboxListWidget
- it is a QGridLayout, with re-orderable checkboxes using small up/down arrows
This commit is contained in:
139
picard/ui/sortablecheckboxlist.py
Normal file
139
picard/ui/sortablecheckboxlist.py
Normal file
@@ -0,0 +1,139 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Picard, the next-generation MusicBrainz tagger
|
||||
# Copyright (C) 2015 Laurent Monin
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
import sys
|
||||
from functools import partial
|
||||
from PyQt4 import QtGui, QtCore
|
||||
from PyQt4.QtCore import pyqtSignal
|
||||
|
||||
|
||||
class SortableCheckboxListWidget(QtGui.QWidget):
|
||||
_CHECKBOX_POS = 0
|
||||
_BUTTON_UP = 1
|
||||
_BUTTON_DOWN = 2
|
||||
|
||||
__no_emit = False
|
||||
changed = pyqtSignal(list)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super(SortableCheckboxListWidget, self).__init__(parent)
|
||||
layout = QtGui.QGridLayout()
|
||||
layout.setHorizontalSpacing(5)
|
||||
layout.setVerticalSpacing(2)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
self.setLayout(layout)
|
||||
self.__items = []
|
||||
|
||||
def addItems(self, items):
|
||||
for item in items:
|
||||
self.addItem(item)
|
||||
|
||||
def setSignals(self, row):
|
||||
layout = self.layout()
|
||||
checkbox = layout.itemAtPosition(row, self._CHECKBOX_POS).widget()
|
||||
up = layout.itemAtPosition(row, self._BUTTON_UP).widget()
|
||||
down = layout.itemAtPosition(row, self._BUTTON_DOWN).widget()
|
||||
checkbox.stateChanged.connect(partial(self.checkbox_toggled, row))
|
||||
up.clicked.connect(partial(self.move_button_clicked, row, up=True))
|
||||
down.clicked.connect(partial(self.move_button_clicked, row, up=False))
|
||||
|
||||
def moveItem(self, from_row, to_row):
|
||||
to_row = to_row % len(self.__items)
|
||||
self.__items[to_row], self.__items[from_row] = \
|
||||
self.__items[from_row], self.__items[to_row]
|
||||
self.updateRow(to_row)
|
||||
self.updateRow(from_row)
|
||||
self._emit_changed()
|
||||
|
||||
def checkbox_toggled(self, row, state):
|
||||
self.__items[row].setChecked(state == QtCore.Qt.Checked)
|
||||
self._emit_changed()
|
||||
|
||||
def move_button_clicked(self, row, up):
|
||||
if up:
|
||||
to = row - 1
|
||||
else:
|
||||
to = row + 1
|
||||
self.moveItem(row, to)
|
||||
|
||||
def updateRow(self, row):
|
||||
self.__no_emit = True
|
||||
item = self.__items[row]
|
||||
layout = self.layout()
|
||||
checkbox = layout.itemAtPosition(row, self._CHECKBOX_POS).widget()
|
||||
checkbox.setText(item.text)
|
||||
checkbox.setChecked(item.checked)
|
||||
self.__no_emit = False
|
||||
|
||||
def addItem(self, item):
|
||||
self.__items.append(item)
|
||||
row = len(self.__items) - 1
|
||||
layout = self.layout()
|
||||
layout.addWidget(QtGui.QCheckBox(), row, self._CHECKBOX_POS)
|
||||
self.updateRow(row)
|
||||
up_button = QtGui.QToolButton()
|
||||
up_button.setArrowType(QtCore.Qt.UpArrow)
|
||||
up_button.setMaximumSize(QtCore.QSize(16, 16))
|
||||
down_button = QtGui.QToolButton()
|
||||
down_button.setArrowType(QtCore.Qt.DownArrow)
|
||||
down_button.setMaximumSize(QtCore.QSize(16, 16))
|
||||
layout.addWidget(up_button, row, self._BUTTON_UP)
|
||||
layout.addWidget(down_button, row, self._BUTTON_DOWN)
|
||||
self.setSignals(row)
|
||||
|
||||
def _emit_changed(self):
|
||||
if not self.__no_emit:
|
||||
self.changed.emit(self.__items)
|
||||
|
||||
|
||||
class SortableCheckboxListItem(object):
|
||||
|
||||
def __init__(self, text=u'', checked=False, data=None):
|
||||
self._checked = checked
|
||||
self._text = text
|
||||
self._data = data
|
||||
|
||||
@property
|
||||
def text(self):
|
||||
return self._text
|
||||
|
||||
def setText(self, text):
|
||||
self._text = text
|
||||
|
||||
@property
|
||||
def checked(self):
|
||||
return self._checked
|
||||
|
||||
def setChecked(self, state):
|
||||
self._checked = state
|
||||
|
||||
@property
|
||||
def data(self):
|
||||
return self._data
|
||||
|
||||
def setData(self, data):
|
||||
self._data = data
|
||||
|
||||
def __repr__(self):
|
||||
params = []
|
||||
params.append('text=' + repr(self.text))
|
||||
params.append('checked=' + repr(self.checked))
|
||||
if self.data is not None:
|
||||
params.append('data=' + repr(self.data))
|
||||
return "%s(%s)" % (self.__class__.__name__, ", ".join(params))
|
||||
Reference in New Issue
Block a user