explorertable.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  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. self.trackSelected.emit(None)
  51. def update_tracks(self, tracks):
  52. # for track in tracks:
  53. # pass
  54. self.populate()
  55. def selected_track(self):
  56. track_id = self.selectionModel().selection().indexes()[2].data(2)
  57. if not track_id:
  58. return None
  59. return TrackRepository().get_by_id(int(track_id))
  60. def selectionChanged(self, selected, _):
  61. try:
  62. track_id = selected.indexes()[2].data(2)
  63. except IndexError:
  64. return
  65. if track_id:
  66. track = TrackRepository().get_by_id(int(track_id))
  67. else:
  68. track = None
  69. self.trackSelected.emit(track)
  70. def _itemDoubleClicked(self, item, _):
  71. track_id = item.data(2, 0)
  72. if track_id:
  73. track = TrackRepository().get_by_id(int(track_id))
  74. self.trackDoubleClicked.emit(track)
  75. @staticmethod
  76. def _norm_search(s):
  77. return s.lower().replace("é", "e").replace("è", "e").replace("ê", "e").replace("ë", "e").replace("ç", "c")\
  78. .replace("à", "a").replace("ö", "o").replace("ü", "u").replace("'", " ")
  79. def filterBySearchText(self, searchText):
  80. searchText = self._norm_search(searchText)
  81. self.setUpdatesEnabled(False)
  82. iterator = QTreeWidgetItemIterator(self)
  83. while True:
  84. item = iterator.value()
  85. if item is not None:
  86. if not item.data(2, 0):
  87. # not a track
  88. item.setHidden(True)
  89. iterator += 1
  90. continue
  91. track_item = item
  92. parent_item = item.parent()
  93. grand_parent_item = parent_item.parent() if parent_item else None
  94. keys = [track_item.text(1)]
  95. if parent_item:
  96. keys.append(parent_item.text(1))
  97. if grand_parent_item:
  98. keys.append(grand_parent_item.text(1))
  99. s = self._norm_search(" ".join(keys))
  100. hide = searchText not in s
  101. track_item.setHidden(hide)
  102. iterator += 1
  103. else:
  104. break
  105. iterator = QTreeWidgetItemIterator(self)
  106. while True:
  107. item = iterator.value()
  108. if item is not None:
  109. if not item.data(2, 0) or item.isHidden():
  110. # not a track or hidden
  111. iterator += 1
  112. continue
  113. if item.parent():
  114. item.parent().setHidden(False)
  115. if item.parent() and item.parent().parent():
  116. item.parent().parent().setHidden(False)
  117. iterator += 1
  118. else:
  119. break
  120. if searchText:
  121. self.expandAll()
  122. self.setUpdatesEnabled(True)