labelDialog.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. from qtpy import PYQT5
  2. from qtpy import QtCore
  3. from qtpy import QtGui
  4. from qtpy import QtWidgets
  5. from .lib import labelValidator
  6. from .lib import newIcon
  7. # TODO(unknown):
  8. # - Calculate optimal position so as not to go out of screen area.
  9. class LabelQLineEdit(QtWidgets.QLineEdit):
  10. def setListWidget(self, list_widget):
  11. self.list_widget = list_widget
  12. def keyPressEvent(self, e):
  13. if e.key() in [QtCore.Qt.Key_Up, QtCore.Qt.Key_Down]:
  14. self.list_widget.keyPressEvent(e)
  15. else:
  16. super(LabelQLineEdit, self).keyPressEvent(e)
  17. class LabelDialog(QtWidgets.QDialog):
  18. def __init__(self, text="Enter object label", parent=None, labels=None,
  19. sort_labels=True):
  20. super(LabelDialog, self).__init__(parent)
  21. self.edit = LabelQLineEdit()
  22. self.edit.setPlaceholderText(text)
  23. self.edit.setValidator(labelValidator())
  24. self.edit.editingFinished.connect(self.postProcess)
  25. layout = QtWidgets.QVBoxLayout()
  26. layout.addWidget(self.edit)
  27. # buttons
  28. self.buttonBox = bb = QtWidgets.QDialogButtonBox(
  29. QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel,
  30. QtCore.Qt.Horizontal,
  31. self,
  32. )
  33. bb.button(bb.Ok).setIcon(newIcon('done'))
  34. bb.button(bb.Cancel).setIcon(newIcon('undo'))
  35. bb.accepted.connect(self.validate)
  36. bb.rejected.connect(self.reject)
  37. layout.addWidget(bb)
  38. # label_list
  39. self.labelList = QtWidgets.QListWidget()
  40. self._sort_labels = sort_labels
  41. if labels:
  42. self.labelList.addItems(labels)
  43. if self._sort_labels:
  44. self.labelList.sortItems()
  45. else:
  46. self.labelList.setDragDropMode(
  47. QtGui.QAbstractItemView.InternalMove)
  48. self.labelList.currentItemChanged.connect(self.labelSelected)
  49. self.edit.setListWidget(self.labelList)
  50. layout.addWidget(self.labelList)
  51. self.setLayout(layout)
  52. # completion
  53. completer = QtWidgets.QCompleter()
  54. completer.setCompletionMode(QtWidgets.QCompleter.InlineCompletion)
  55. completer.setModel(self.labelList.model())
  56. self.edit.setCompleter(completer)
  57. def addLabelHistory(self, label):
  58. if self.labelList.findItems(label, QtCore.Qt.MatchExactly):
  59. return
  60. self.labelList.addItem(label)
  61. if self._sort_labels:
  62. self.labelList.sortItems()
  63. def labelSelected(self, item):
  64. self.edit.setText(item.text())
  65. def validate(self):
  66. if PYQT5:
  67. if self.edit.text().strip():
  68. self.accept()
  69. else:
  70. if self.edit.text().trimmed():
  71. self.accept()
  72. def postProcess(self):
  73. if PYQT5:
  74. self.edit.setText(self.edit.text().strip())
  75. else:
  76. self.edit.setText(self.edit.text().trimmed())
  77. def popUp(self, text=None, move=True):
  78. # if text is None, the previous label in self.edit is kept
  79. if text is None:
  80. text = self.edit.text()
  81. self.edit.setText(text)
  82. self.edit.setSelection(0, len(text))
  83. items = self.labelList.findItems(text, QtCore.Qt.MatchFixedString)
  84. if items:
  85. assert len(items) == 1
  86. self.labelList.setCurrentItem(items[0])
  87. row = self.labelList.row(items[0])
  88. self.edit.completer().setCurrentRow(row)
  89. self.edit.setFocus(QtCore.Qt.PopupFocusReason)
  90. if move:
  91. self.move(QtGui.QCursor.pos())
  92. return self.edit.text() if self.exec_() else None