explorertable.py 4.8 KB

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