explorertable.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. from PyQt5.QtCore import pyqtSlot, pyqtSignal
  2. from PyQt5.QtGui import QIcon
  3. from PyQt5.QtWidgets import QTreeWidget, QTreeWidgetItem, QTreeWidgetItemIterator
  4. from core import db
  5. from core.logging_ import Logger
  6. from core.repositories import TrackRepository
  7. logger = Logger.get()
  8. class ExplorerTable(QTreeWidget):
  9. trackSelected = pyqtSignal(object)
  10. trackDoubleClicked = pyqtSignal(object)
  11. def __init__(self, parent):
  12. super(QTreeWidget, self).__init__(parent)
  13. self.setColumnCount(3)
  14. self.setColumnWidth(0, 54)
  15. self.hideColumn(2)
  16. self.itemDoubleClicked.connect(self._itemDoubleClicked)
  17. def populate(self):
  18. session = db.Session()
  19. track_repo = TrackRepository(session)
  20. self.clear()
  21. artist_folders = {}
  22. album_folders = {}
  23. tracks = track_repo.get_all()
  24. self.setUpdatesEnabled(False)
  25. for track in tracks:
  26. if track.artist and track.artist not in artist_folders:
  27. item = QTreeWidgetItem(self)
  28. item.setIcon(0, QIcon(":/img/rsc/artist.png"))
  29. item.setText(1, track.artist)
  30. artist_folders[track.artist] = item
  31. for track in tracks:
  32. # list albums with artists
  33. if track.artist and track.album and (track.artist, track.album) not in album_folders:
  34. item = QTreeWidgetItem(artist_folders[track.artist])
  35. item.setIcon(0, QIcon(":/img/rsc/album.png"))
  36. item.setText(1, track.album)
  37. album_folders[(track.artist, track.album)] = item
  38. for track in tracks:
  39. if track.artist and track.album:
  40. parent = album_folders[(track.artist, track.album)]
  41. elif track.artist:
  42. parent = artist_folders[track.artist]
  43. else:
  44. parent = self
  45. item = QTreeWidgetItem(parent)
  46. item.setIcon(0, QIcon(":/img/rsc/music.png"))
  47. item.setText(1, track.title)
  48. item.setData(2, 0, track.id)
  49. self.setUpdatesEnabled(True)
  50. def selected_track(self):
  51. track_id = self.selectionModel().selection().indexes()[2].data(2)
  52. if not track_id:
  53. return None
  54. return TrackRepository().get_by_id(int(track_id))
  55. def selectionChanged(self, selected, _):
  56. track_id = selected.indexes()[2].data(2)
  57. if track_id:
  58. track = TrackRepository().get_by_id(int(track_id))
  59. else:
  60. track = None
  61. self.trackSelected.emit(track)
  62. def _itemDoubleClicked(self, item, _):
  63. track_id = item.data(2, 0)
  64. if track_id:
  65. track = TrackRepository().get_by_id(int(track_id))
  66. self.trackDoubleClicked.emit(track)
  67. @staticmethod
  68. def _norm_search(s):
  69. return s.lower().replace("é", "e").replace("è", "e").replace("ê", "e").replace("ë", "e").replace("ç", "c")\
  70. .replace("à", "a").replace("ö", "o").replace("ü", "u").replace("'", " ")
  71. def filterBySearchText(self, searchText):
  72. searchText = self._norm_search(searchText)
  73. self.setUpdatesEnabled(False)
  74. iterator = QTreeWidgetItemIterator(self)
  75. while True:
  76. item = iterator.value()
  77. if item is not None:
  78. if not item.data(2, 0):
  79. # not a track
  80. item.setHidden(True)
  81. iterator += 1
  82. continue
  83. track_item = item
  84. parent_item = item.parent()
  85. grand_parent_item = parent_item.parent() if parent_item else None
  86. keys = [track_item.text(1)]
  87. if parent_item:
  88. keys.append(parent_item.text(1))
  89. if grand_parent_item:
  90. keys.append(grand_parent_item.text(1))
  91. s = self._norm_search(" ".join(keys))
  92. hide = searchText not in s
  93. track_item.setHidden(hide)
  94. iterator += 1
  95. else:
  96. break
  97. iterator = QTreeWidgetItemIterator(self)
  98. while True:
  99. item = iterator.value()
  100. if item is not None:
  101. if not item.data(2, 0) or item.isHidden():
  102. # not a track or hidden
  103. iterator += 1
  104. continue
  105. if item.parent():
  106. item.parent().setHidden(False)
  107. if item.parent() and item.parent().parent():
  108. item.parent().parent().setHidden(False)
  109. iterator += 1
  110. else:
  111. break
  112. if searchText:
  113. self.expandAll()
  114. self.setUpdatesEnabled(True)