Преглед изворни кода

fix tags table, add meta editor

Olivier Massot пре 4 година
родитељ
комит
eac12cc528

+ 3 - 3
core/repositories.py

@@ -94,12 +94,12 @@ class TrackRepository(Repository):
         return self.session.query(Track).group_by(Track.artist).all()
 
     def get_albums_by_artist(self, artist):
-        return self.session.query(Track).where(Track.artist == artist).group_by(Track.album).all()
+        return self.session.query(Track).filter(Track.artist == artist).group_by(Track.album).all()
 
     def get_by_artist_and_album(self, artist, album):
         return self.session.query(Track)\
-            .where(Track.artist == artist)\
-            .where(Track.album == album)\
+            .filter(Track.artist == artist)\
+            .filter(Track.album == album)\
             .group_by(Track.album)\
             .all()
 

+ 3 - 2
main.py

@@ -59,13 +59,14 @@ main_window.show()
 try:
     r = app.exec_()
 finally:
+    indexer.stop()
     try:
         settings = main_window.currentSettings()
         with open(SETTING_PATH, 'w') as f:
             yaml.dump(settings, f)
     finally:
-        indexer.stop()
         db.close()
 
-
 logger.info("-- Closed --")
+sys.exit(r)
+

+ 54 - 0
ui/qt/dlg_meta_editor.py

@@ -0,0 +1,54 @@
+import os
+
+from PyQt5 import QtWidgets
+from PyQt5.QtGui import QIntValidator
+from path import Path
+
+from core.repositories import TrackRepository
+from ui.qt.dlg_meta_editor_ui import Ui_dlgMetaEditor
+
+
+class DlgMetaEditor(QtWidgets.QDialog):
+    def __init__(self, parent=None, track=None):
+        super().__init__(parent)
+        self.track = track
+        self.createWidgets()
+
+    def createWidgets(self):
+        self.ui = Ui_dlgMetaEditor()
+        self.ui.setupUi(self)
+
+        self.ui.lineTitle.setText(self.track.title or "")
+        self.ui.lineArtist.setText(self.track.artist or "")
+        self.ui.lineAlbum.setText(self.track.album or "")
+        self.ui.lineTrackNum.setText(str(self.track.track_num) or "")
+
+        self.ui.lineTrackNum.setValidator(QIntValidator())
+
+        self.ui.lblPath.setText(self.track.path)
+
+        self.ui.btnOpenTrackFolder.clicked.connect(self.openTrackFolder)
+
+        self.ui.btnSave.clicked.connect(self.ok)
+        self.ui.btnCancel.clicked.connect(self.cancel)
+
+    def openTrackFolder(self):
+        folder = Path(self.track.path)
+        os.startfile(folder)
+
+    @classmethod
+    def edit(cls, parent, track=None):
+        dlg = cls(parent, track)
+        return dlg.exec_()
+
+    def ok(self):
+        track_repo = TrackRepository()
+        self.track.title = self.ui.lineTitle.text() or None
+        self.track.artist = self.ui.lineArtist.text() or None
+        self.track.album = self.ui.lineAlbum.text() or None
+        self.track.track_num = int(self.ui.lineTrackNum.text()) or None
+        track_repo.commit()
+        self.done(1)
+
+    def cancel(self):
+        self.done(0)

+ 230 - 0
ui/qt/dlg_meta_editor.ui

@@ -0,0 +1,230 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>dlgMetaEditor</class>
+ <widget class="QDialog" name="dlgMetaEditor">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>270</height>
+   </rect>
+  </property>
+  <property name="minimumSize">
+   <size>
+    <width>400</width>
+    <height>270</height>
+   </size>
+  </property>
+  <property name="maximumSize">
+   <size>
+    <width>800</width>
+    <height>270</height>
+   </size>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+  <layout class="QHBoxLayout" name="horizontalLayout">
+   <item>
+    <layout class="QVBoxLayout" name="verticalLayout">
+     <property name="spacing">
+      <number>10</number>
+     </property>
+     <item>
+      <widget class="QLabel" name="label">
+       <property name="font">
+        <font>
+         <pointsize>11</pointsize>
+         <weight>75</weight>
+         <bold>true</bold>
+        </font>
+       </property>
+       <property name="text">
+        <string>Editer les informations de la piste</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <layout class="QFormLayout" name="formLayout">
+       <property name="horizontalSpacing">
+        <number>17</number>
+       </property>
+       <property name="leftMargin">
+        <number>6</number>
+       </property>
+       <property name="rightMargin">
+        <number>6</number>
+       </property>
+       <item row="0" column="0">
+        <widget class="QLabel" name="label_2">
+         <property name="text">
+          <string>Titre</string>
+         </property>
+        </widget>
+       </item>
+       <item row="0" column="1">
+        <widget class="QLineEdit" name="lineTitle"/>
+       </item>
+       <item row="1" column="0">
+        <widget class="QLabel" name="label_3">
+         <property name="text">
+          <string>Artiste</string>
+         </property>
+        </widget>
+       </item>
+       <item row="2" column="0">
+        <widget class="QLabel" name="label_4">
+         <property name="text">
+          <string>Album</string>
+         </property>
+        </widget>
+       </item>
+       <item row="1" column="1">
+        <widget class="QLineEdit" name="lineArtist"/>
+       </item>
+       <item row="2" column="1">
+        <widget class="QLineEdit" name="lineAlbum"/>
+       </item>
+       <item row="3" column="0">
+        <widget class="QLabel" name="label_5">
+         <property name="text">
+          <string>Piste n°</string>
+         </property>
+        </widget>
+       </item>
+       <item row="3" column="1">
+        <widget class="QLineEdit" name="lineTrackNum"/>
+       </item>
+      </layout>
+     </item>
+     <item>
+      <layout class="QHBoxLayout" name="horizontalLayout_3">
+       <item>
+        <widget class="QLabel" name="label_6">
+         <property name="minimumSize">
+          <size>
+           <width>21</width>
+           <height>21</height>
+          </size>
+         </property>
+         <property name="maximumSize">
+          <size>
+           <width>21</width>
+           <height>21</height>
+          </size>
+         </property>
+         <property name="text">
+          <string/>
+         </property>
+         <property name="pixmap">
+          <pixmap resource="rsc.qrc">:/img/rsc/audio-file.png</pixmap>
+         </property>
+         <property name="scaledContents">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QLabel" name="lblPath">
+         <property name="text">
+          <string>...</string>
+         </property>
+         <property name="wordWrap">
+          <bool>true</bool>
+         </property>
+         <property name="textInteractionFlags">
+          <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QToolButton" name="btnOpenTrackFolder">
+         <property name="text">
+          <string>...</string>
+         </property>
+         <property name="icon">
+          <iconset resource="rsc.qrc">
+           <normaloff>:/img/rsc/folder.png</normaloff>:/img/rsc/folder.png</iconset>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+     <item>
+      <spacer name="verticalSpacer">
+       <property name="orientation">
+        <enum>Qt::Vertical</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>20</width>
+         <height>40</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <layout class="QHBoxLayout" name="horizontalLayout_2">
+       <item>
+        <widget class="QPushButton" name="btnCancel">
+         <property name="minimumSize">
+          <size>
+           <width>120</width>
+           <height>28</height>
+          </size>
+         </property>
+         <property name="maximumSize">
+          <size>
+           <width>120</width>
+           <height>28</height>
+          </size>
+         </property>
+         <property name="text">
+          <string>Annuler</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <spacer name="horizontalSpacer">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>40</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item>
+        <widget class="QPushButton" name="btnSave">
+         <property name="minimumSize">
+          <size>
+           <width>140</width>
+           <height>28</height>
+          </size>
+         </property>
+         <property name="maximumSize">
+          <size>
+           <width>140</width>
+           <height>28</height>
+          </size>
+         </property>
+         <property name="text">
+          <string>Enregistrer</string>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <resources>
+  <include location="rsc.qrc"/>
+ </resources>
+ <connections/>
+</ui>

+ 118 - 0
ui/qt/dlg_meta_editor_ui.py

@@ -0,0 +1,118 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'dlg_meta_editor.ui'
+#
+# Created by: PyQt5 UI code generator 5.15.2
+#
+# WARNING: Any manual changes made to this file will be lost when pyuic5 is
+# run again.  Do not edit this file unless you know what you are doing.
+
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+
+
+class Ui_dlgMetaEditor(object):
+    def setupUi(self, dlgMetaEditor):
+        dlgMetaEditor.setObjectName("dlgMetaEditor")
+        dlgMetaEditor.resize(400, 270)
+        dlgMetaEditor.setMinimumSize(QtCore.QSize(400, 270))
+        dlgMetaEditor.setMaximumSize(QtCore.QSize(800, 270))
+        self.horizontalLayout = QtWidgets.QHBoxLayout(dlgMetaEditor)
+        self.horizontalLayout.setObjectName("horizontalLayout")
+        self.verticalLayout = QtWidgets.QVBoxLayout()
+        self.verticalLayout.setSpacing(10)
+        self.verticalLayout.setObjectName("verticalLayout")
+        self.label = QtWidgets.QLabel(dlgMetaEditor)
+        font = QtGui.QFont()
+        font.setPointSize(11)
+        font.setBold(True)
+        font.setWeight(75)
+        self.label.setFont(font)
+        self.label.setObjectName("label")
+        self.verticalLayout.addWidget(self.label)
+        self.formLayout = QtWidgets.QFormLayout()
+        self.formLayout.setContentsMargins(6, -1, 6, -1)
+        self.formLayout.setHorizontalSpacing(17)
+        self.formLayout.setObjectName("formLayout")
+        self.label_2 = QtWidgets.QLabel(dlgMetaEditor)
+        self.label_2.setObjectName("label_2")
+        self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label_2)
+        self.lineTitle = QtWidgets.QLineEdit(dlgMetaEditor)
+        self.lineTitle.setObjectName("lineTitle")
+        self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.lineTitle)
+        self.label_3 = QtWidgets.QLabel(dlgMetaEditor)
+        self.label_3.setObjectName("label_3")
+        self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label_3)
+        self.label_4 = QtWidgets.QLabel(dlgMetaEditor)
+        self.label_4.setObjectName("label_4")
+        self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.label_4)
+        self.lineArtist = QtWidgets.QLineEdit(dlgMetaEditor)
+        self.lineArtist.setObjectName("lineArtist")
+        self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.lineArtist)
+        self.lineAlbum = QtWidgets.QLineEdit(dlgMetaEditor)
+        self.lineAlbum.setObjectName("lineAlbum")
+        self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.lineAlbum)
+        self.label_5 = QtWidgets.QLabel(dlgMetaEditor)
+        self.label_5.setObjectName("label_5")
+        self.formLayout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.label_5)
+        self.lineTrackNum = QtWidgets.QLineEdit(dlgMetaEditor)
+        self.lineTrackNum.setObjectName("lineTrackNum")
+        self.formLayout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.lineTrackNum)
+        self.verticalLayout.addLayout(self.formLayout)
+        self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
+        self.horizontalLayout_3.setObjectName("horizontalLayout_3")
+        self.label_6 = QtWidgets.QLabel(dlgMetaEditor)
+        self.label_6.setMinimumSize(QtCore.QSize(21, 21))
+        self.label_6.setMaximumSize(QtCore.QSize(21, 21))
+        self.label_6.setText("")
+        self.label_6.setPixmap(QtGui.QPixmap(":/img/rsc/audio-file.png"))
+        self.label_6.setScaledContents(True)
+        self.label_6.setObjectName("label_6")
+        self.horizontalLayout_3.addWidget(self.label_6)
+        self.lblPath = QtWidgets.QLabel(dlgMetaEditor)
+        self.lblPath.setWordWrap(True)
+        self.lblPath.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByMouse)
+        self.lblPath.setObjectName("lblPath")
+        self.horizontalLayout_3.addWidget(self.lblPath)
+        self.btnOpenTrackFolder = QtWidgets.QToolButton(dlgMetaEditor)
+        icon = QtGui.QIcon()
+        icon.addPixmap(QtGui.QPixmap(":/img/rsc/folder.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnOpenTrackFolder.setIcon(icon)
+        self.btnOpenTrackFolder.setObjectName("btnOpenTrackFolder")
+        self.horizontalLayout_3.addWidget(self.btnOpenTrackFolder)
+        self.verticalLayout.addLayout(self.horizontalLayout_3)
+        spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+        self.verticalLayout.addItem(spacerItem)
+        self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
+        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
+        self.btnCancel = QtWidgets.QPushButton(dlgMetaEditor)
+        self.btnCancel.setMinimumSize(QtCore.QSize(120, 28))
+        self.btnCancel.setMaximumSize(QtCore.QSize(120, 28))
+        self.btnCancel.setObjectName("btnCancel")
+        self.horizontalLayout_2.addWidget(self.btnCancel)
+        spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+        self.horizontalLayout_2.addItem(spacerItem1)
+        self.btnSave = QtWidgets.QPushButton(dlgMetaEditor)
+        self.btnSave.setMinimumSize(QtCore.QSize(140, 28))
+        self.btnSave.setMaximumSize(QtCore.QSize(140, 28))
+        self.btnSave.setObjectName("btnSave")
+        self.horizontalLayout_2.addWidget(self.btnSave)
+        self.verticalLayout.addLayout(self.horizontalLayout_2)
+        self.horizontalLayout.addLayout(self.verticalLayout)
+
+        self.retranslateUi(dlgMetaEditor)
+        QtCore.QMetaObject.connectSlotsByName(dlgMetaEditor)
+
+    def retranslateUi(self, dlgMetaEditor):
+        _translate = QtCore.QCoreApplication.translate
+        dlgMetaEditor.setWindowTitle(_translate("dlgMetaEditor", "Dialog"))
+        self.label.setText(_translate("dlgMetaEditor", "Editer les informations de la piste"))
+        self.label_2.setText(_translate("dlgMetaEditor", "Titre"))
+        self.label_3.setText(_translate("dlgMetaEditor", "Artiste"))
+        self.label_4.setText(_translate("dlgMetaEditor", "Album"))
+        self.label_5.setText(_translate("dlgMetaEditor", "Piste n°"))
+        self.lblPath.setText(_translate("dlgMetaEditor", "..."))
+        self.btnOpenTrackFolder.setText(_translate("dlgMetaEditor", "..."))
+        self.btnCancel.setText(_translate("dlgMetaEditor", "Annuler"))
+        self.btnSave.setText(_translate("dlgMetaEditor", "Enregistrer"))
+from . import rsc_rc

+ 0 - 2
ui/qt/dlg_tag_editor.py

@@ -1,6 +1,4 @@
 from PyQt5 import QtWidgets
-from PyQt5.QtWidgets import QMessageBox
-
 from ui.qt.dlg_tag_editor_ui import Ui_DlgTagEditor
 
 

+ 1 - 0
ui/qt/gen.cmd

@@ -3,5 +3,6 @@ pyuic5 main.ui -o main_ui.py --from-imports
 pyuic5 dlg_select_playlist.ui -o dlg_select_playlist_ui.py --from-imports
 pyuic5 dlg_playlist.ui -o dlg_playlist_ui.py --from-imports
 pyuic5 dlg_tag_editor.ui -o dlg_tag_editor_ui.py --from-imports
+pyuic5 dlg_meta_editor.ui -o dlg_meta_editor_ui.py --from-imports
 pyuic5 widgets/frame_notes.ui -o widgets/frame_notes_ui.py --import-from=..
 pyuic5 widgets/vlcframe.ui -o widgets/vlcframe_ui.py --import-from=..

+ 10 - 13
ui/qt/main.ui

@@ -541,7 +541,7 @@
                         <item>
                          <widget class="QToolButton" name="explorerTrackEdit">
                           <property name="enabled">
-                           <bool>false</bool>
+                           <bool>true</bool>
                           </property>
                           <property name="minimumSize">
                            <size>
@@ -743,6 +743,9 @@
                         </item>
                         <item>
                          <widget class="QLineEdit" name="lineSearchTags">
+                          <property name="enabled">
+                           <bool>false</bool>
+                          </property>
                           <property name="minimumSize">
                            <size>
                             <width>0</width>
@@ -765,6 +768,9 @@
                         </item>
                         <item>
                          <widget class="QToolButton" name="btnEditTags">
+                          <property name="enabled">
+                           <bool>false</bool>
+                          </property>
                           <property name="minimumSize">
                            <size>
                             <width>28</width>
@@ -823,6 +829,9 @@
                         <attribute name="horizontalHeaderVisible">
                          <bool>false</bool>
                         </attribute>
+                        <attribute name="horizontalHeaderShowSortIndicator" stdset="0">
+                         <bool>true</bool>
+                        </attribute>
                         <attribute name="horizontalHeaderStretchLastSection">
                          <bool>true</bool>
                         </attribute>
@@ -1308,24 +1317,12 @@
                   <height>192</height>
                  </size>
                 </property>
-                <property name="horizontalScrollBarPolicy">
-                 <enum>Qt::ScrollBarAsNeeded</enum>
-                </property>
                 <property name="selectionMode">
                  <enum>QAbstractItemView::SingleSelection</enum>
                 </property>
                 <property name="selectionBehavior">
                  <enum>QAbstractItemView::SelectRows</enum>
                 </property>
-                <property name="showGrid">
-                 <bool>false</bool>
-                </property>
-                <property name="gridStyle">
-                 <enum>Qt::NoPen</enum>
-                </property>
-                <property name="cornerButtonEnabled">
-                 <bool>false</bool>
-                </property>
                 <attribute name="horizontalHeaderVisible">
                  <bool>false</bool>
                 </attribute>

+ 4 - 5
ui/qt/main_ui.py

@@ -237,7 +237,7 @@ 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.setEnabled(True)
         self.explorerTrackEdit.setMinimumSize(QtCore.QSize(28, 28))
         self.explorerTrackEdit.setMaximumSize(QtCore.QSize(28, 28))
         self.explorerTrackEdit.setText("")
@@ -315,12 +315,14 @@ class Ui_mainWindow(object):
         self.label_12.setObjectName("label_12")
         self.horizontalLayout_19.addWidget(self.label_12)
         self.lineSearchTags = QtWidgets.QLineEdit(self.page_6)
+        self.lineSearchTags.setEnabled(False)
         self.lineSearchTags.setMinimumSize(QtCore.QSize(0, 25))
         self.lineSearchTags.setMaximumSize(QtCore.QSize(100, 16777215))
         self.lineSearchTags.setClearButtonEnabled(True)
         self.lineSearchTags.setObjectName("lineSearchTags")
         self.horizontalLayout_19.addWidget(self.lineSearchTags)
         self.btnEditTags = QtWidgets.QToolButton(self.page_6)
+        self.btnEditTags.setEnabled(False)
         self.btnEditTags.setMinimumSize(QtCore.QSize(28, 28))
         self.btnEditTags.setMaximumSize(QtCore.QSize(28, 28))
         self.btnEditTags.setIcon(icon5)
@@ -347,6 +349,7 @@ class Ui_mainWindow(object):
         item = QtWidgets.QTableWidgetItem()
         self.explorerTrackTagsTable.setHorizontalHeaderItem(2, item)
         self.explorerTrackTagsTable.horizontalHeader().setVisible(False)
+        self.explorerTrackTagsTable.horizontalHeader().setSortIndicatorShown(True)
         self.explorerTrackTagsTable.horizontalHeader().setStretchLastSection(True)
         self.explorerTrackTagsTable.verticalHeader().setVisible(False)
         self.verticalLayout_9.addWidget(self.explorerTrackTagsTable)
@@ -542,12 +545,8 @@ class Ui_mainWindow(object):
         self.settingsTagsTableWidget = TagsTable(self.page_5)
         self.settingsTagsTableWidget.setMinimumSize(QtCore.QSize(0, 192))
         self.settingsTagsTableWidget.setMaximumSize(QtCore.QSize(16777215, 192))
-        self.settingsTagsTableWidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
         self.settingsTagsTableWidget.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
         self.settingsTagsTableWidget.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
-        self.settingsTagsTableWidget.setShowGrid(False)
-        self.settingsTagsTableWidget.setGridStyle(QtCore.Qt.NoPen)
-        self.settingsTagsTableWidget.setCornerButtonEnabled(False)
         self.settingsTagsTableWidget.setObjectName("settingsTagsTableWidget")
         self.settingsTagsTableWidget.setColumnCount(3)
         self.settingsTagsTableWidget.setRowCount(0)

+ 1 - 0
ui/qt/rsc.qrc

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

BIN
ui/qt/rsc/audio-file.png


Разлика између датотеке није приказан због своје велике величине
+ 357 - 771
ui/qt/rsc_rc.py


+ 25 - 10
ui/qt/widgets/tags_table.py

@@ -1,20 +1,25 @@
-from PyQt5.QtCore import pyqtSignal
+from PyQt5.QtCore import pyqtSignal, Qt
 from PyQt5.QtWidgets import QTableWidget, QTableWidgetItem, QCheckBox, QTableWidgetSelectionRange, QMessageBox
 
+from core.logging_ import Logger
 from core.models import Tag
 from core.repositories import TagRepository
 
+logger = Logger.get()
+
 
 class TagsTable(QTableWidget):
     contentChanged = pyqtSignal()
-    selectionChanged = pyqtSignal()
+    tagChecked = pyqtSignal(int)
+    tagUnchecked = pyqtSignal(int)
 
-    def __init__(self, parent=None):
+    def __init__(self, parent=None, selectable=True):
         super().__init__(parent)
+        self.selectable = selectable
 
         self.cellChanged.connect(self.tagChanged)
 
-    def populate(self, track=None, selectable=True):
+    def populate(self, track=None):
         self.setColumnHidden(0, True)
         self.setColumnWidth(1, 45)
 
@@ -25,12 +30,12 @@ class TagsTable(QTableWidget):
 
         tag_repo = TagRepository()
         tags = tag_repo.get_all()
-
         checked = []
-        if track is not None:
-            checked = [t.id for t in tag_repo.get_by_track_id(track.id)]
 
-        if not selectable:
+        if self.selectable:
+            if track is not None:
+                checked = [t.id for t in tag_repo.get_by_track_id(track.id)]
+        else:
             self.setColumnHidden(1, True)
 
         i = 0
@@ -41,11 +46,12 @@ class TagsTable(QTableWidget):
             item.setData(0, tag.id)
             self.setItem(i, 0, item)
 
-            if selectable:
+            if self.selectable:
                 checkBox = QCheckBox()
                 if tag.id in checked:
                     checkBox.setChecked(True)
-                checkBox.stateChanged.connect(self.selectionChanged.emit)
+                checkBox.tag_id = tag.id
+                checkBox.stateChanged.connect(self.tagStateChanged)
                 self.setCellWidget(i, 1, checkBox)
 
             self.setItem(i, 2, QTableWidgetItem(tag.label))
@@ -98,7 +104,16 @@ class TagsTable(QTableWidget):
         tag_repo.commit()
         self.contentChanged.emit()
 
+    def tagStateChanged(self, state):
+        checkBox = self.sender()
+        if state == Qt.Unchecked:
+            self.tagUnchecked.emit(checkBox.tag_id)
+        else:
+            self.tagChecked.emit(checkBox.tag_id)
+
     def selectedTags(self):
+        if not self.selectable:
+            raise RuntimeError("TagsTable is not selectable")
         selected = []
         for i in range(self.rowCount()):
             checked = self.cellWidget(i, 1).isChecked()

+ 40 - 26
ui/window.py

@@ -14,6 +14,7 @@ from core.logging_ import Logger
 from core.models import MusicFolder, TrackTag
 from core.repositories import MusicFolderRepository, TrackRepository, SessionTrackRepository, SessionRepository, \
     TrackTagRepository
+from ui.qt.dlg_meta_editor import DlgMetaEditor
 from ui.qt.dlg_playlist import DlgPlaylist
 from ui.qt.dlg_select_playlist import DlgSelectPlaylist
 from ui.qt.dlg_tag_editor import DlgTagEditor
@@ -77,8 +78,11 @@ class MainWindow(QMainWindow):
         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.explorerTrackEdit.clicked.connect(self.showMetaEditor)
+
         # self.ui.btnEditTags.clicked.connect(self.showTagsEditor)
-        self.ui.explorerTrackTagsTable.selectionChanged.connect(self.updateTrackTags)
+        self.ui.explorerTrackTagsTable.tagChecked.connect(self.addTrackTags)
+        self.ui.explorerTrackTagsTable.tagUnchecked.connect(self.removeTrackTags)
 
         self.ui.explorerTrackMetaStack.setCurrentIndex(0)
         self.ui.explorerTrackNotepad.textChanged.connect(self.explorerTrackNotesChanged)
@@ -100,8 +104,8 @@ class MainWindow(QMainWindow):
 
         self.ui.tagsTableAddButton.clicked.connect(self.addTag)
         self.ui.tableTagsRemoveButton.clicked.connect(self.removeTag)
-        self.ui.settingsTagsTableWidget.populate(selectable=False)
-
+        self.ui.settingsTagsTableWidget.selectable = False
+        self.ui.settingsTagsTableWidget.populate()
         self.ui.settingsTagsTableWidget.contentChanged.connect(self.ui.explorerTrackTagsTable.populate)
 
         # vlc frame
@@ -148,12 +152,8 @@ class MainWindow(QMainWindow):
         self.selected_track = track
 
         # track infos
-        self.ui.explorerLblTrackTitle.setText(track.title)
-        self.ui.explorerLblTrackArtist.setText(track.artist)
-        self.ui.explorerLblTrackAlbum.setText(track.album)
-        self.ui.explorerLblTrackNumber.setText(
-            str(track.track_num if track.track_num is not None else "")
-        )
+        self.update_meta()
+
         self.ui.explorerTrackNotepad.textChanged.disconnect(self.explorerTrackNotesChanged)
         self.ui.explorerTrackNotepad.setHtml(track.note)
         self.ui.explorerTrackNotepad.textChanged.connect(self.explorerTrackNotesChanged)
@@ -175,6 +175,22 @@ class MainWindow(QMainWindow):
         self.ui.explorerPlaylist.viewport().repaint()
         self.ui.sessionPlaylist.viewport().repaint()
 
+    def update_meta(self):
+        if self.selected_track:
+            title, artist, album, track_num = self.selected_track.title, \
+                                              self.selected_track.artist, \
+                                              self.selected_track.album, \
+                                              self.selected_track.track_num
+        else:
+            title, artist, album, track_num = "", "", "", ""
+
+        self.ui.explorerLblTrackTitle.setText(title)
+        self.ui.explorerLblTrackArtist.setText(artist)
+        self.ui.explorerLblTrackAlbum.setText(album)
+        self.ui.explorerLblTrackNumber.setText(
+            str(track_num if track_num is not None else "")
+        )
+
     def populate_music_folders_table(self):
         music_folders = MusicFolderRepository().get_all()
         self.ui.settingsMusicFoldersTable.setRowCount(0)
@@ -211,6 +227,13 @@ class MainWindow(QMainWindow):
         self.ui.vlcFrame.load_track(track)
         self.ui.vlcFrame.play()
 
+    def showMetaEditor(self):
+        if not self.selected_track:
+            return
+        r = DlgMetaEditor.edit(self, self.selected_track)
+        if r:
+            self.update_meta()
+
     def add_music_folder(self):
         path = QFileDialog.getExistingDirectory(self, "Sélectionnez le dossier à ajouter")
         if not path:
@@ -318,25 +341,17 @@ class MainWindow(QMainWindow):
     #     if tags:
     #         print(tags)
 
-    def updateTrackTags(self):
+    def addTrackTags(self, tag_id):
         track_id = self.selected_track.id
-
-        new_tags = self.ui.explorerTrackTagsTable.selectedTags()
-
         track_tag_repo = TrackTagRepository()
+        tt = TrackTag(track_id=track_id, tag_id=tag_id)
+        track_tag_repo.create(tt)
+        track_tag_repo.commit()
 
-        current_track_tags = [tt.tag_id for tt in track_tag_repo.get_by("track_id", track_id)]
-
-        added = [t for t in new_tags if t not in current_track_tags]
-        removed = [t for t in current_track_tags if t not in new_tags]
-
-        for tag_id in added:
-            tt = TrackTag(track_id=track_id, tag_id=tag_id)
-            track_tag_repo.create(tt)
-
-        for tag_id in removed:
-            track_tag_repo.query().where(TrackTag.track_id == track_id).where(TrackTag.tag_id == tag_id).delete()
-
+    def removeTrackTags(self, tag_id):
+        track_id = self.selected_track.id
+        track_tag_repo = TrackTagRepository()
+        track_tag_repo.query().filter(TrackTag.track_id == track_id).filter(TrackTag.tag_id == tag_id).delete()
         track_tag_repo.commit()
 
     def sessionNotesChanged(self):
@@ -344,7 +359,6 @@ class MainWindow(QMainWindow):
             return
         notes = self.ui.frameNotes.ui.sessionNotes.toHtml()
         session_repo = SessionRepository()
-        # session = session_repo.get_by_id(self.selected_playlist.id)
         self.selected_playlist.notes = notes
         session_repo.commit()
 

Неке датотеке нису приказане због велике количине промена