explorertable.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. from PyQt5.QtCore import 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. from core.utils import norm_search
  8. logger = Logger.get()
  9. class ExplorerTable(QTreeWidget):
  10. trackSelected = pyqtSignal(object)
  11. trackDoubleClicked = pyqtSignal(object)
  12. def __init__(self, parent):
  13. super(QTreeWidget, self).__init__(parent)
  14. self.setColumnCount(3)
  15. self.setColumnWidth(0, 54)
  16. self.hideColumn(2)
  17. self.itemDoubleClicked.connect(self._itemDoubleClicked)
  18. def populate(self):
  19. session = db.Session()
  20. track_repo = TrackRepository(session)
  21. self.clear()
  22. artist_folders = {}
  23. album_folders = {}
  24. tracks = track_repo.get_all()
  25. self.setUpdatesEnabled(False)
  26. for track in tracks:
  27. if track.artist and track.artist not in artist_folders:
  28. item = QTreeWidgetItem(self)
  29. item.setIcon(0, QIcon(":/img/rsc/artist.png"))
  30. item.setText(1, track.artist)
  31. artist_folders[track.artist] = item
  32. for track in tracks:
  33. # list albums with artists
  34. if track.artist and track.album and (track.artist, track.album) not in album_folders:
  35. item = QTreeWidgetItem(artist_folders[track.artist])
  36. item.setIcon(0, QIcon(":/img/rsc/album.png"))
  37. item.setText(1, track.album)
  38. album_folders[(track.artist, track.album)] = item
  39. for track in tracks:
  40. if track.artist and track.album:
  41. parent = album_folders[(track.artist, track.album)]
  42. elif track.artist:
  43. parent = artist_folders[track.artist]
  44. else:
  45. parent = self
  46. item = QTreeWidgetItem(parent)
  47. item.setIcon(0, QIcon(":/img/rsc/music.png"))
  48. item.setText(1, track.title)
  49. item.setData(2, 0, track.id)
  50. self.setUpdatesEnabled(True)
  51. self.trackSelected.emit(None)
  52. def update_tracks(self, tracks):
  53. # for track in tracks:
  54. # pass
  55. self.populate()
  56. def selected_track(self):
  57. track_id = self.selectionModel().selection().indexes()[2].data(2)
  58. if not track_id:
  59. return None
  60. return TrackRepository().get_by_id(int(track_id))
  61. def selectionChanged(self, selected, _):
  62. try:
  63. track_id = selected.indexes()[2].data(2)
  64. except IndexError:
  65. return
  66. if track_id:
  67. track = TrackRepository().get_by_id(int(track_id))
  68. else:
  69. track = None
  70. self.trackSelected.emit(track)
  71. def _itemDoubleClicked(self, item, _):
  72. track_id = item.data(2, 0)
  73. if track_id:
  74. track = TrackRepository().get_by_id(int(track_id))
  75. self.trackDoubleClicked.emit(track)
  76. def filterBySearchText(self, searchText):
  77. searchText = norm_search(searchText)
  78. self.setUpdatesEnabled(False)
  79. iterator = QTreeWidgetItemIterator(self)
  80. while True:
  81. item = iterator.value()
  82. if item is not None:
  83. if not item.data(2, 0):
  84. # not a track
  85. item.setHidden(True)
  86. iterator += 1
  87. continue
  88. track_item = item
  89. parent_item = item.parent()
  90. grand_parent_item = parent_item.parent() if parent_item else None
  91. keys = [track_item.text(1)]
  92. if parent_item:
  93. keys.append(parent_item.text(1))
  94. if grand_parent_item:
  95. keys.append(grand_parent_item.text(1))
  96. s = norm_search(" ".join(keys))
  97. hide = searchText not in s
  98. track_item.setHidden(hide)
  99. iterator += 1
  100. else:
  101. break
  102. iterator = QTreeWidgetItemIterator(self)
  103. while True:
  104. item = iterator.value()
  105. if item is not None:
  106. if not item.data(2, 0) or item.isHidden():
  107. # not a track or hidden
  108. iterator += 1
  109. continue
  110. if item.parent():
  111. item.parent().setHidden(False)
  112. if item.parent() and item.parent().parent():
  113. item.parent().parent().setHidden(False)
  114. iterator += 1
  115. else:
  116. break
  117. if searchText:
  118. self.expandAll()
  119. else:
  120. self.collapseAll()
  121. self.setUpdatesEnabled(True)
  122. def filterByTagId(self, tag_id):
  123. track_ids = []
  124. if tag_id:
  125. track_repo = TrackRepository()
  126. track_ids = [t.id for t in track_repo.get_by_tag_id(tag_id)]
  127. self.setUpdatesEnabled(False)
  128. iterator = QTreeWidgetItemIterator(self)
  129. while True:
  130. item = iterator.value()
  131. if item is not None:
  132. if not item.data(2, 0):
  133. # not a track
  134. item.setHidden(True)
  135. iterator += 1
  136. continue
  137. hide = tag_id and item.data(2, 0) not in track_ids
  138. item.setHidden(hide)
  139. iterator += 1
  140. else:
  141. break
  142. iterator = QTreeWidgetItemIterator(self)
  143. while True:
  144. item = iterator.value()
  145. if item is not None:
  146. if not item.data(2, 0) or item.isHidden():
  147. # not a track or hidden
  148. iterator += 1
  149. continue
  150. if item.parent():
  151. item.parent().setHidden(False)
  152. if item.parent() and item.parent().parent():
  153. item.parent().parent().setHidden(False)
  154. iterator += 1
  155. else:
  156. break
  157. if tag_id:
  158. self.expandAll()
  159. else:
  160. self.collapseAll()
  161. self.setUpdatesEnabled(True)