ソースを参照

implement search in explorer table

Olivier Massot 4 年 前
コミット
7063fb8060
8 ファイル変更832 行追加806 行削除
  1. 81 4
      ui/qt/main.ui
  2. 51 23
      ui/qt/main_ui.py
  3. 2 0
      ui/qt/rsc.qrc
  4. BIN
      ui/qt/rsc/filter.png
  5. BIN
      ui/qt/rsc/search.png
  6. 626 778
      ui/qt/rsc_rc.py
  7. 64 1
      ui/qt/widgets/explorertable.py
  8. 8 0
      ui/window.py

+ 81 - 4
ui/qt/main.ui

@@ -96,7 +96,7 @@
         <item>
          <widget class="QStackedWidget" name="stack">
           <property name="currentIndex">
-           <number>2</number>
+           <number>0</number>
           </property>
           <widget class="QWidget" name="page_1">
            <layout class="QHBoxLayout" name="horizontalLayout_2">
@@ -174,7 +174,7 @@
                    <bool>true</bool>
                   </attribute>
                   <attribute name="verticalHeaderVisible">
-                   <bool>false</bool>
+                   <bool>true</bool>
                   </attribute>
                   <column>
                    <property name="text">
@@ -201,7 +201,6 @@
                   <property name="frameShadow">
                    <enum>QFrame::Raised</enum>
                   </property>
-                  <layout class="QHBoxLayout" name="horizontalLayout_20"/>
                  </widget>
                 </item>
                </layout>
@@ -330,6 +329,78 @@
                   </item>
                  </layout>
                 </item>
+                <item>
+                 <layout class="QHBoxLayout" name="horizontalLayout_21">
+                  <item>
+                   <widget class="QToolButton" name="explorerBtnSearch">
+                    <property name="minimumSize">
+                     <size>
+                      <width>28</width>
+                      <height>28</height>
+                     </size>
+                    </property>
+                    <property name="maximumSize">
+                     <size>
+                      <width>28</width>
+                      <height>28</height>
+                     </size>
+                    </property>
+                    <property name="text">
+                     <string>...</string>
+                    </property>
+                    <property name="icon">
+                     <iconset resource="rsc.qrc">
+                      <normaloff>:/img/rsc/search.png</normaloff>:/img/rsc/search.png</iconset>
+                    </property>
+                   </widget>
+                  </item>
+                  <item>
+                   <widget class="QLineEdit" name="explorerLineSearch">
+                    <property name="minimumSize">
+                     <size>
+                      <width>0</width>
+                      <height>28</height>
+                     </size>
+                    </property>
+                    <property name="maximumSize">
+                     <size>
+                      <width>16777215</width>
+                      <height>28</height>
+                     </size>
+                    </property>
+                    <property name="placeholderText">
+                     <string>Rechercher un morceau...</string>
+                    </property>
+                    <property name="clearButtonEnabled">
+                     <bool>true</bool>
+                    </property>
+                   </widget>
+                  </item>
+                  <item>
+                   <widget class="QToolButton" name="explorerBtnFilter">
+                    <property name="minimumSize">
+                     <size>
+                      <width>28</width>
+                      <height>28</height>
+                     </size>
+                    </property>
+                    <property name="maximumSize">
+                     <size>
+                      <width>28</width>
+                      <height>28</height>
+                     </size>
+                    </property>
+                    <property name="text">
+                     <string>...</string>
+                    </property>
+                    <property name="icon">
+                     <iconset resource="rsc.qrc">
+                      <normaloff>:/img/rsc/filter.png</normaloff>:/img/rsc/filter.png</iconset>
+                    </property>
+                   </widget>
+                  </item>
+                 </layout>
+                </item>
                 <item>
                  <widget class="ExplorerTable" name="explorerTable">
                   <property name="minimumSize">
@@ -464,6 +535,9 @@
                         </item>
                         <item>
                          <widget class="QToolButton" name="explorerTrackEdit">
+                          <property name="enabled">
+                           <bool>false</bool>
+                          </property>
                           <property name="minimumSize">
                            <size>
                             <width>28</width>
@@ -690,6 +764,9 @@
                           <height>120</height>
                          </size>
                         </property>
+                        <property name="cursor" stdset="0">
+                         <cursorShape>IBeamCursor</cursorShape>
+                        </property>
                         <property name="autoFormatting">
                          <set>QTextEdit::AutoAll</set>
                         </property>
@@ -943,7 +1020,7 @@
                    <bool>true</bool>
                   </attribute>
                   <attribute name="verticalHeaderVisible">
-                   <bool>true</bool>
+                   <bool>false</bool>
                   </attribute>
                   <column>
                    <property name="text">

+ 51 - 23
ui/qt/main_ui.py

@@ -96,14 +96,12 @@ class Ui_mainWindow(object):
         self.sessionPlaylist.setHorizontalHeaderItem(2, item)
         self.sessionPlaylist.horizontalHeader().setVisible(False)
         self.sessionPlaylist.horizontalHeader().setStretchLastSection(True)
-        self.sessionPlaylist.verticalHeader().setVisible(False)
+        self.sessionPlaylist.verticalHeader().setVisible(True)
         self.horizontalLayout_14.addWidget(self.sessionPlaylist)
         self.frameNotes = FrameNotes(self.page_1)
         self.frameNotes.setFrameShape(QtWidgets.QFrame.StyledPanel)
         self.frameNotes.setFrameShadow(QtWidgets.QFrame.Raised)
         self.frameNotes.setObjectName("frameNotes")
-        self.horizontalLayout_20 = QtWidgets.QHBoxLayout(self.frameNotes)
-        self.horizontalLayout_20.setObjectName("horizontalLayout_20")
         self.horizontalLayout_14.addWidget(self.frameNotes)
         self.horizontalLayout_14.setStretch(0, 1)
         self.horizontalLayout_14.setStretch(1, 1)
@@ -161,6 +159,31 @@ class Ui_mainWindow(object):
         self.btnExplorerRefresh.setObjectName("btnExplorerRefresh")
         self.horizontalLayout_12.addWidget(self.btnExplorerRefresh)
         self.verticalLayout_8.addLayout(self.horizontalLayout_12)
+        self.horizontalLayout_21 = QtWidgets.QHBoxLayout()
+        self.horizontalLayout_21.setObjectName("horizontalLayout_21")
+        self.explorerBtnSearch = QtWidgets.QToolButton(self.page_3)
+        self.explorerBtnSearch.setMinimumSize(QtCore.QSize(28, 28))
+        self.explorerBtnSearch.setMaximumSize(QtCore.QSize(28, 28))
+        icon3 = QtGui.QIcon()
+        icon3.addPixmap(QtGui.QPixmap(":/img/rsc/search.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.explorerBtnSearch.setIcon(icon3)
+        self.explorerBtnSearch.setObjectName("explorerBtnSearch")
+        self.horizontalLayout_21.addWidget(self.explorerBtnSearch)
+        self.explorerLineSearch = QtWidgets.QLineEdit(self.page_3)
+        self.explorerLineSearch.setMinimumSize(QtCore.QSize(0, 28))
+        self.explorerLineSearch.setMaximumSize(QtCore.QSize(16777215, 28))
+        self.explorerLineSearch.setClearButtonEnabled(True)
+        self.explorerLineSearch.setObjectName("explorerLineSearch")
+        self.horizontalLayout_21.addWidget(self.explorerLineSearch)
+        self.explorerBtnFilter = QtWidgets.QToolButton(self.page_3)
+        self.explorerBtnFilter.setMinimumSize(QtCore.QSize(28, 28))
+        self.explorerBtnFilter.setMaximumSize(QtCore.QSize(28, 28))
+        icon4 = QtGui.QIcon()
+        icon4.addPixmap(QtGui.QPixmap(":/img/rsc/filter.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.explorerBtnFilter.setIcon(icon4)
+        self.explorerBtnFilter.setObjectName("explorerBtnFilter")
+        self.horizontalLayout_21.addWidget(self.explorerBtnFilter)
+        self.verticalLayout_8.addLayout(self.horizontalLayout_21)
         self.explorerTable = ExplorerTable(self.page_3)
         self.explorerTable.setMinimumSize(QtCore.QSize(320, 0))
         self.explorerTable.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
@@ -211,12 +234,13 @@ class Ui_mainWindow(object):
         self.label_11.setObjectName("label_11")
         self.horizontalLayout_13.addWidget(self.label_11)
         self.explorerTrackEdit = QtWidgets.QToolButton(self.page_6)
+        self.explorerTrackEdit.setEnabled(False)
         self.explorerTrackEdit.setMinimumSize(QtCore.QSize(28, 28))
         self.explorerTrackEdit.setMaximumSize(QtCore.QSize(28, 28))
         self.explorerTrackEdit.setText("")
-        icon3 = QtGui.QIcon()
-        icon3.addPixmap(QtGui.QPixmap(":/img/rsc/edit.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
-        self.explorerTrackEdit.setIcon(icon3)
+        icon5 = QtGui.QIcon()
+        icon5.addPixmap(QtGui.QPixmap(":/img/rsc/edit.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.explorerTrackEdit.setIcon(icon5)
         self.explorerTrackEdit.setObjectName("explorerTrackEdit")
         self.horizontalLayout_13.addWidget(self.explorerTrackEdit)
         self.verticalLayout_9.addLayout(self.horizontalLayout_13)
@@ -290,6 +314,7 @@ class Ui_mainWindow(object):
         self.verticalLayout_9.addWidget(self.label_10)
         self.explorerTrackNotepad = QtWidgets.QTextEdit(self.page_6)
         self.explorerTrackNotepad.setMinimumSize(QtCore.QSize(218, 120))
+        self.explorerTrackNotepad.viewport().setProperty("cursor", QtGui.QCursor(QtCore.Qt.IBeamCursor))
         self.explorerTrackNotepad.setAutoFormatting(QtWidgets.QTextEdit.AutoAll)
         self.explorerTrackNotepad.setUndoRedoEnabled(True)
         self.explorerTrackNotepad.setReadOnly(False)
@@ -311,26 +336,26 @@ class Ui_mainWindow(object):
         self.explorerTrackPlay = QtWidgets.QPushButton(self.page_3)
         self.explorerTrackPlay.setEnabled(False)
         self.explorerTrackPlay.setMinimumSize(QtCore.QSize(220, 0))
-        icon4 = QtGui.QIcon()
-        icon4.addPixmap(QtGui.QPixmap(":/img/rsc/play.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
-        self.explorerTrackPlay.setIcon(icon4)
+        icon6 = QtGui.QIcon()
+        icon6.addPixmap(QtGui.QPixmap(":/img/rsc/play.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.explorerTrackPlay.setIcon(icon6)
         self.explorerTrackPlay.setIconSize(QtCore.QSize(12, 12))
         self.explorerTrackPlay.setObjectName("explorerTrackPlay")
         self.verticalLayout_5.addWidget(self.explorerTrackPlay)
         self.explorerAddToPlaylist = QtWidgets.QPushButton(self.page_3)
         self.explorerAddToPlaylist.setEnabled(False)
         self.explorerAddToPlaylist.setMinimumSize(QtCore.QSize(220, 0))
-        icon5 = QtGui.QIcon()
-        icon5.addPixmap(QtGui.QPixmap(":/img/rsc/double-right-arrows-symbol.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
-        self.explorerAddToPlaylist.setIcon(icon5)
+        icon7 = QtGui.QIcon()
+        icon7.addPixmap(QtGui.QPixmap(":/img/rsc/double-right-arrows-symbol.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.explorerAddToPlaylist.setIcon(icon7)
         self.explorerAddToPlaylist.setObjectName("explorerAddToPlaylist")
         self.verticalLayout_5.addWidget(self.explorerAddToPlaylist)
         self.explorerRemoveFromPlaylist = QtWidgets.QPushButton(self.page_3)
         self.explorerRemoveFromPlaylist.setEnabled(False)
         self.explorerRemoveFromPlaylist.setMinimumSize(QtCore.QSize(220, 0))
-        icon6 = QtGui.QIcon()
-        icon6.addPixmap(QtGui.QPixmap(":/img/rsc/double-left-arrows-symbol.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
-        self.explorerRemoveFromPlaylist.setIcon(icon6)
+        icon8 = QtGui.QIcon()
+        icon8.addPixmap(QtGui.QPixmap(":/img/rsc/double-left-arrows-symbol.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.explorerRemoveFromPlaylist.setIcon(icon8)
         self.explorerRemoveFromPlaylist.setObjectName("explorerRemoveFromPlaylist")
         self.verticalLayout_5.addWidget(self.explorerRemoveFromPlaylist)
         spacerItem4 = QtWidgets.QSpacerItem(20, 30, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
@@ -382,7 +407,7 @@ class Ui_mainWindow(object):
         self.explorerPlaylist.setHorizontalHeaderItem(2, item)
         self.explorerPlaylist.horizontalHeader().setVisible(False)
         self.explorerPlaylist.horizontalHeader().setStretchLastSection(True)
-        self.explorerPlaylist.verticalHeader().setVisible(True)
+        self.explorerPlaylist.verticalHeader().setVisible(False)
         self.verticalLayout_12.addWidget(self.explorerPlaylist)
         self.horizontalLayout_6.addLayout(self.verticalLayout_12)
         self.horizontalLayout_6.setStretch(0, 1)
@@ -439,18 +464,18 @@ class Ui_mainWindow(object):
         self.horizontalLayout_7.setObjectName("horizontalLayout_7")
         self.musicFoldersRemoveButton = QtWidgets.QPushButton(self.page_5)
         self.musicFoldersRemoveButton.setMinimumSize(QtCore.QSize(0, 32))
-        icon7 = QtGui.QIcon()
-        icon7.addPixmap(QtGui.QPixmap(":/img/rsc/delete.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
-        self.musicFoldersRemoveButton.setIcon(icon7)
+        icon9 = QtGui.QIcon()
+        icon9.addPixmap(QtGui.QPixmap(":/img/rsc/delete.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.musicFoldersRemoveButton.setIcon(icon9)
         self.musicFoldersRemoveButton.setObjectName("musicFoldersRemoveButton")
         self.horizontalLayout_7.addWidget(self.musicFoldersRemoveButton)
         spacerItem5 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
         self.horizontalLayout_7.addItem(spacerItem5)
         self.musicFoldersAddButton = QtWidgets.QPushButton(self.page_5)
         self.musicFoldersAddButton.setMinimumSize(QtCore.QSize(128, 32))
-        icon8 = QtGui.QIcon()
-        icon8.addPixmap(QtGui.QPixmap(":/img/rsc/plus.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
-        self.musicFoldersAddButton.setIcon(icon8)
+        icon10 = QtGui.QIcon()
+        icon10.addPixmap(QtGui.QPixmap(":/img/rsc/plus.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.musicFoldersAddButton.setIcon(icon10)
         self.musicFoldersAddButton.setObjectName("musicFoldersAddButton")
         self.horizontalLayout_7.addWidget(self.musicFoldersAddButton)
         self.verticalLayout_6.addLayout(self.horizontalLayout_7)
@@ -482,7 +507,7 @@ class Ui_mainWindow(object):
 
         self.retranslateUi(mainWindow)
         self.menu.setCurrentRow(-1)
-        self.stack.setCurrentIndex(2)
+        self.stack.setCurrentIndex(0)
         self.explorerTrackMetaStack.setCurrentIndex(1)
         QtCore.QMetaObject.connectSlotsByName(mainWindow)
 
@@ -500,6 +525,9 @@ class Ui_mainWindow(object):
         self.btnSessionStart.setText(_translate("mainWindow", "Lancer la séance"))
         self.label_3.setText(_translate("mainWindow", "Mes musiques"))
         self.btnExplorerRefresh.setToolTip(_translate("mainWindow", "Rafraichir la liste"))
+        self.explorerBtnSearch.setText(_translate("mainWindow", "..."))
+        self.explorerLineSearch.setPlaceholderText(_translate("mainWindow", "Rechercher un morceau..."))
+        self.explorerBtnFilter.setText(_translate("mainWindow", "..."))
         self.explorerTable.headerItem().setText(1, _translate("mainWindow", "2"))
         self.label_2.setText(_translate("mainWindow", "Sélectionnez une piste"))
         self.label_11.setText(_translate("mainWindow", "Informations sur la piste"))

+ 2 - 0
ui/qt/rsc.qrc

@@ -1,5 +1,7 @@
 <RCC>
   <qresource prefix="/img">
+    <file>rsc/filter.png</file>
+    <file>rsc/search.png</file>
     <file>rsc/undo-arrow.png</file>
     <file>rsc/redo-arrow.png</file>
     <file>rsc/underline.png</file>

BIN
ui/qt/rsc/filter.png


BIN
ui/qt/rsc/search.png


ファイルの差分が大きいため隠しています
+ 626 - 778
ui/qt/rsc_rc.py


+ 64 - 1
ui/qt/widgets/explorertable.py

@@ -1,6 +1,6 @@
 from PyQt5.QtCore import pyqtSlot, pyqtSignal
 from PyQt5.QtGui import QIcon
-from PyQt5.QtWidgets import QTreeWidget, QTreeWidgetItem
+from PyQt5.QtWidgets import QTreeWidget, QTreeWidgetItem, QTreeWidgetItemIterator
 
 from core import db
 from core.logging_ import Logger
@@ -80,3 +80,66 @@ class ExplorerTable(QTreeWidget):
         if track_id:
             track = TrackRepository().get_by_id(int(track_id))
             self.trackDoubleClicked.emit(track)
+
+    @staticmethod
+    def _norm_search(s):
+        return s.lower().replace("é", "e").replace("è", "e").replace("ê", "e").replace("ë", "e").replace("ç", "c")\
+                .replace("à", "a").replace("ö", "o").replace("ü", "u").replace("'", " ")
+
+    def filterBySearchText(self, searchText):
+        searchText = self._norm_search(searchText)
+
+        self.setUpdatesEnabled(False)
+
+        iterator = QTreeWidgetItemIterator(self)
+        while True:
+            item = iterator.value()
+            if item is not None:
+
+                if not item.data(2, 0):
+                    # not a track
+                    item.setHidden(True)
+                    iterator += 1
+                    continue
+
+                track_item = item
+                parent_item = item.parent()
+                grand_parent_item = parent_item.parent() if parent_item else None
+
+                keys = [track_item.text(1)]
+                if parent_item:
+                    keys.append(parent_item.text(1))
+                if grand_parent_item:
+                    keys.append(grand_parent_item.text(1))
+
+                s = self._norm_search(" ".join(keys))
+                hide = searchText not in s
+
+                track_item.setHidden(hide)
+
+                iterator += 1
+            else:
+                break
+
+        iterator = QTreeWidgetItemIterator(self)
+        while True:
+            item = iterator.value()
+            if item is not None:
+                if not item.data(2, 0) or item.isHidden():
+                    # not a track or hidden
+                    iterator += 1
+                    continue
+
+                if item.parent():
+                    item.parent().setHidden(False)
+                if item.parent() and item.parent().parent():
+                    item.parent().parent().setHidden(False)
+
+                iterator += 1
+            else:
+                break
+
+        if searchText:
+            self.expandAll()
+
+        self.setUpdatesEnabled(True)

+ 8 - 0
ui/window.py

@@ -71,6 +71,10 @@ class MainWindow(QMainWindow):
         self.ui.explorerTable.trackSelected.connect(self.newTrackSelected)
         self.ui.explorerTable.trackDoubleClicked.connect(self.play_track)
         self.ui.btnExplorerRefresh.clicked.connect(self.refresh_explorer_tree)
+        self.ui.explorerLineSearch.editingFinished.connect(self.explorerSearchChanged)
+        self.ui.explorerLineSearch.textChanged.connect(lambda s: (s or self.explorerSearchChanged())) # when search bar is cleared
+        self.ui.explorerBtnSearch.clicked.connect(self.explorerSearchChanged)
+
         self.ui.explorerTrackMetaStack.setCurrentIndex(0)
         self.ui.explorerTrackNotepad.textChanged.connect(self.explorerTrackNotesChanged)
         self.ui.explorerTrackPlay.clicked.connect(self.explorerPlaySelected)
@@ -297,6 +301,10 @@ class MainWindow(QMainWindow):
         self.selected_track.note = note
         track_repo.commit()
 
+    def explorerSearchChanged(self):
+        searchText = self.ui.explorerLineSearch.text()
+        self.ui.explorerTable.filterBySearchText(searchText)
+
     def currentSettings(self):
         volume = self.ui.vlcFrame.volume
         playlist_id = self.selected_playlist.id if self.selected_playlist else None

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません