WIP V3: ready for testing
This commit is contained in:
parent
00d7258afd
commit
4eabf4a02a
@ -868,7 +868,7 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
dlg = TrackSelectDialog(
|
dlg = TrackSelectDialog(
|
||||||
session=session,
|
session=session,
|
||||||
new_row_number=self.active_tab().selected_model_row_number(),
|
new_row_number=self.active_tab().selected_model_row_number(),
|
||||||
model=self.active_model()
|
model=self.active_model(),
|
||||||
)
|
)
|
||||||
dlg.exec()
|
dlg.exec()
|
||||||
|
|
||||||
@ -1067,12 +1067,6 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
# Clear next track
|
# Clear next track
|
||||||
self.clear_next()
|
self.clear_next()
|
||||||
|
|
||||||
# Set current track playlist_tab colour
|
|
||||||
# TODO Reimplement without reference to self.current_track.playlist_tab
|
|
||||||
# current_tab = self.current_track.playlist_tab
|
|
||||||
# if current_tab:
|
|
||||||
# self.set_tab_colour(current_tab, QColor(Config.COLOUR_CURRENT_TAB))
|
|
||||||
|
|
||||||
# Restore volume if -3dB active
|
# Restore volume if -3dB active
|
||||||
if self.btnDrop3db.isChecked():
|
if self.btnDrop3db.isChecked():
|
||||||
self.btnDrop3db.setChecked(False)
|
self.btnDrop3db.setChecked(False)
|
||||||
@ -1422,85 +1416,6 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
# Enable controls
|
# Enable controls
|
||||||
self.enable_play_next_controls()
|
self.enable_play_next_controls()
|
||||||
|
|
||||||
def set_next_plr_id(
|
|
||||||
self, next_plr_id: Optional[int], playlist_tab: PlaylistTab
|
|
||||||
) -> None:
|
|
||||||
"""
|
|
||||||
Set passed plr_id as next track to play, or clear next track if None
|
|
||||||
|
|
||||||
Actions required:
|
|
||||||
- Update playing_track
|
|
||||||
- Tell playlist tabs to update their 'next track' highlighting
|
|
||||||
- Update headers
|
|
||||||
- Set playlist tab colours
|
|
||||||
- Populate ‘info’ tabs
|
|
||||||
"""
|
|
||||||
|
|
||||||
return
|
|
||||||
# with Session() as session:
|
|
||||||
# # Update self.next_track PlaylistTrack structure
|
|
||||||
# self.next_track = NextTrack()
|
|
||||||
# if next_plr_id:
|
|
||||||
# next_plr = session.get(PlaylistRows, next_plr_id)
|
|
||||||
# if next_plr:
|
|
||||||
# self.next_track.set_plr(session, next_plr)
|
|
||||||
# self.signals.set_next_track_signal.emit(next_plr.playlist_id)
|
|
||||||
|
|
||||||
# # Update headers
|
|
||||||
# self.update_headers()
|
|
||||||
|
|
||||||
# TODO: reimlement
|
|
||||||
# # Set playlist tab colours
|
|
||||||
# self._set_next_track_playlist_tab_colours(old_next_track)
|
|
||||||
|
|
||||||
# if next_plr_id:
|
|
||||||
# # Populate 'info' tabs with Wikipedia info, but queue it
|
|
||||||
# # because it isn't quick
|
|
||||||
# if self.next_track.title:
|
|
||||||
# QTimer.singleShot(
|
|
||||||
# 0,
|
|
||||||
# lambda: self.tabInfolist.open_in_wikipedia(
|
|
||||||
# self.next_track.title
|
|
||||||
# ),
|
|
||||||
# )
|
|
||||||
|
|
||||||
def _set_next_track_playlist_tab_colours(
|
|
||||||
self, old_next_track: Optional[PlaylistTrack]
|
|
||||||
) -> None:
|
|
||||||
"""
|
|
||||||
Set playlist tab colour for next track. self.next_track needs
|
|
||||||
to be set before calling.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# If the original next playlist tab isn't the same as the
|
|
||||||
# new one or the current track, it needs its colour reset.
|
|
||||||
return
|
|
||||||
# TODO Reimplement
|
|
||||||
# if (
|
|
||||||
# old_next_track
|
|
||||||
# and old_next_track.playlist_tab
|
|
||||||
# and old_next_track.playlist_tab
|
|
||||||
# not in [self.next_track.playlist_tab, self.current_track.playlist_tab]
|
|
||||||
# ):
|
|
||||||
# self.set_tab_colour(
|
|
||||||
# old_next_track.playlist_tab, QColor(Config.COLOUR_NORMAL_TAB)
|
|
||||||
# )
|
|
||||||
# # If the new next playlist tab isn't the same as the
|
|
||||||
# # old one or the current track, it needs its colour set.
|
|
||||||
# if old_next_track:
|
|
||||||
# old_tab = old_next_track.playlist_tab
|
|
||||||
# else:
|
|
||||||
# old_tab = None
|
|
||||||
# if (
|
|
||||||
# self.next_track
|
|
||||||
# and self.next_track.playlist_tab
|
|
||||||
# and self.next_track.playlist_tab
|
|
||||||
# not in [old_tab, self.current_track.playlist_tab]
|
|
||||||
# ):
|
|
||||||
# self.set_tab_colour(
|
|
||||||
# self.next_track.playlist_tab, QColor(Config.COLOUR_NEXT_TAB)
|
|
||||||
# )
|
|
||||||
|
|
||||||
def tick_10ms(self) -> None:
|
def tick_10ms(self) -> None:
|
||||||
"""
|
"""
|
||||||
Called every 10ms
|
Called every 10ms
|
||||||
|
|||||||
@ -5,7 +5,7 @@ from datetime import datetime, timedelta
|
|||||||
from enum import auto, Enum
|
from enum import auto, Enum
|
||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
from typing import cast, List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
from PyQt6.QtCore import (
|
from PyQt6.QtCore import (
|
||||||
QAbstractTableModel,
|
QAbstractTableModel,
|
||||||
@ -144,10 +144,7 @@ class PlaylistModel(QAbstractTableModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def add_track_to_header(
|
def add_track_to_header(
|
||||||
self,
|
self, row_number: int, track_id: int, note: Optional[str] = None
|
||||||
row_number: int,
|
|
||||||
track_id: int,
|
|
||||||
note: Optional[str] = None
|
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Add track to existing header row
|
Add track to existing header row
|
||||||
@ -1423,12 +1420,16 @@ class PlaylistProxyModel(QSortFilterProxyModel):
|
|||||||
def move_track_add_note(
|
def move_track_add_note(
|
||||||
self, new_row_number: int, existing_prd: PlaylistRowData, note: str
|
self, new_row_number: int, existing_prd: PlaylistRowData, note: str
|
||||||
) -> None:
|
) -> None:
|
||||||
return self.playlist_model.move_track_add_note(new_row_number, existing_prd, note)
|
return self.playlist_model.move_track_add_note(
|
||||||
|
new_row_number, existing_prd, note
|
||||||
|
)
|
||||||
|
|
||||||
def move_track_to_header(
|
def move_track_to_header(
|
||||||
self, header_row_number: int, existing_prd: PlaylistRowData, note: Optional[str]
|
self, header_row_number: int, existing_prd: PlaylistRowData, note: Optional[str]
|
||||||
) -> None:
|
) -> None:
|
||||||
return self.playlist_model.move_track_to_header(header_row_number, existing_prd)
|
return self.playlist_model.move_track_to_header(
|
||||||
|
header_row_number, existing_prd, note
|
||||||
|
)
|
||||||
|
|
||||||
def open_in_audacity(self, row_number: int) -> None:
|
def open_in_audacity(self, row_number: int) -> None:
|
||||||
return self.playlist_model.open_in_audacity(row_number)
|
return self.playlist_model.open_in_audacity(row_number)
|
||||||
|
|||||||
370
app/playlists.py
370
app/playlists.py
@ -1,8 +1,3 @@
|
|||||||
import subprocess
|
|
||||||
|
|
||||||
import obsws_python as obs # type: ignore
|
|
||||||
|
|
||||||
from datetime import datetime, timedelta
|
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
from typing import Callable, cast, List, Optional, TYPE_CHECKING
|
from typing import Callable, cast, List, Optional, TYPE_CHECKING
|
||||||
|
|
||||||
@ -11,11 +6,9 @@ from PyQt6.QtCore import (
|
|||||||
QModelIndex,
|
QModelIndex,
|
||||||
QObject,
|
QObject,
|
||||||
QItemSelection,
|
QItemSelection,
|
||||||
QItemSelectionModel,
|
|
||||||
Qt,
|
Qt,
|
||||||
# QTimer,
|
|
||||||
)
|
)
|
||||||
from PyQt6.QtGui import QAction, QDropEvent, QKeyEvent
|
from PyQt6.QtGui import QAction, QKeyEvent
|
||||||
from PyQt6.QtWidgets import (
|
from PyQt6.QtWidgets import (
|
||||||
QAbstractItemDelegate,
|
QAbstractItemDelegate,
|
||||||
QAbstractItemView,
|
QAbstractItemView,
|
||||||
@ -34,29 +27,21 @@ from PyQt6.QtWidgets import (
|
|||||||
QStyleOption,
|
QStyleOption,
|
||||||
)
|
)
|
||||||
|
|
||||||
from dbconfig import Session, scoped_session
|
from dbconfig import Session
|
||||||
from dialogs import TrackSelectDialog
|
from dialogs import TrackSelectDialog
|
||||||
from classes import MusicMusterSignals, track_sequence
|
from classes import MusicMusterSignals, track_sequence
|
||||||
from config import Config
|
from config import Config
|
||||||
from helpers import (
|
from helpers import (
|
||||||
ask_yes_no,
|
ask_yes_no,
|
||||||
file_is_unreadable,
|
|
||||||
get_relative_date,
|
|
||||||
ms_to_mmss,
|
ms_to_mmss,
|
||||||
open_in_audacity,
|
|
||||||
send_mail,
|
|
||||||
set_track_metadata,
|
|
||||||
show_warning,
|
show_warning,
|
||||||
)
|
)
|
||||||
from log import log
|
from models import Settings
|
||||||
from models import PlaylistRows, Settings, Tracks, NoteColours
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from musicmuster import Window
|
from musicmuster import Window
|
||||||
from playlistmodel import PlaylistModel, PlaylistProxyModel
|
from playlistmodel import PlaylistModel, PlaylistProxyModel
|
||||||
|
|
||||||
# HEADER_NOTES_COLUMN = 2
|
|
||||||
|
|
||||||
|
|
||||||
class EscapeDelegate(QStyledItemDelegate):
|
class EscapeDelegate(QStyledItemDelegate):
|
||||||
"""
|
"""
|
||||||
@ -180,7 +165,6 @@ class PlaylistTab(QTableView):
|
|||||||
self.proxy_model = PlaylistProxyModel(self.playlist_model)
|
self.proxy_model = PlaylistProxyModel(self.playlist_model)
|
||||||
self.setItemDelegate(EscapeDelegate(self, self.playlist_model))
|
self.setItemDelegate(EscapeDelegate(self, self.playlist_model))
|
||||||
self.setAlternatingRowColors(True)
|
self.setAlternatingRowColors(True)
|
||||||
# self.setEditTriggers(QAbstractItemView.EditTrigger.DoubleClicked)
|
|
||||||
self.setVerticalScrollMode(QAbstractItemView.ScrollMode.ScrollPerPixel)
|
self.setVerticalScrollMode(QAbstractItemView.ScrollMode.ScrollPerPixel)
|
||||||
self.setDragDropMode(QAbstractItemView.DragDropMode.InternalMove)
|
self.setDragDropMode(QAbstractItemView.DragDropMode.InternalMove)
|
||||||
self.setDragDropOverwriteMode(False)
|
self.setDragDropOverwriteMode(False)
|
||||||
@ -205,13 +189,9 @@ class PlaylistTab(QTableView):
|
|||||||
self.signals = MusicMusterSignals()
|
self.signals = MusicMusterSignals()
|
||||||
self.signals.span_cells_signal.connect(self._span_cells)
|
self.signals.span_cells_signal.connect(self._span_cells)
|
||||||
|
|
||||||
# Call self.eventFilter() for events
|
|
||||||
# self.installEventFilter(self)
|
|
||||||
|
|
||||||
# Initialise miscellaneous instance variables
|
# Initialise miscellaneous instance variables
|
||||||
self.search_text: str = ""
|
self.search_text: str = ""
|
||||||
self.sort_undo: List[int] = []
|
self.sort_undo: List[int] = []
|
||||||
# self.edit_cell_type: Optional[int]
|
|
||||||
|
|
||||||
# Selection model
|
# Selection model
|
||||||
self.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection)
|
self.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection)
|
||||||
@ -358,7 +338,7 @@ class PlaylistTab(QTableView):
|
|||||||
return self.proxy_model.mapToSource(selected_index).row()
|
return self.proxy_model.mapToSource(selected_index).row()
|
||||||
return selected_index.row()
|
return selected_index.row()
|
||||||
|
|
||||||
def selected_model_row_numbers(self) -> Optional[List[int]]:
|
def selected_model_row_numbers(self) -> List[int]:
|
||||||
"""
|
"""
|
||||||
Return a list of model row numbers corresponding to the selected rows or
|
Return a list of model row numbers corresponding to the selected rows or
|
||||||
an empty list.
|
an empty list.
|
||||||
@ -366,7 +346,7 @@ class PlaylistTab(QTableView):
|
|||||||
|
|
||||||
selected_indexes = self._selected_row_indexes()
|
selected_indexes = self._selected_row_indexes()
|
||||||
if selected_indexes is None:
|
if selected_indexes is None:
|
||||||
return None
|
return []
|
||||||
if hasattr(self.proxy_model, "mapToSource"):
|
if hasattr(self.proxy_model, "mapToSource"):
|
||||||
return [self.proxy_model.mapToSource(a).row() for a in selected_indexes]
|
return [self.proxy_model.mapToSource(a).row() for a in selected_indexes]
|
||||||
return [a.row() for a in selected_indexes]
|
return [a.row() for a in selected_indexes]
|
||||||
@ -407,137 +387,6 @@ class PlaylistTab(QTableView):
|
|||||||
return ""
|
return ""
|
||||||
return self.playlist_model.get_row_track_path(model_row_number)
|
return self.playlist_model.get_row_track_path(model_row_number)
|
||||||
|
|
||||||
# def lookup_row_in_songfacts(self) -> None:
|
|
||||||
# """
|
|
||||||
# If there is a selected row and it is a track row,
|
|
||||||
# look up its title in songfacts.
|
|
||||||
|
|
||||||
# If multiple rows are selected, only consider the first one.
|
|
||||||
|
|
||||||
# Otherwise return.
|
|
||||||
# """
|
|
||||||
|
|
||||||
# self._look_up_row(website="songfacts")
|
|
||||||
|
|
||||||
# def lookup_row_in_wikipedia(self) -> None:
|
|
||||||
# """
|
|
||||||
# If there is a selected row and it is a track row,
|
|
||||||
# look up its title in wikipedia.
|
|
||||||
|
|
||||||
# If multiple rows are selected, only consider the first one.
|
|
||||||
|
|
||||||
# Otherwise return.
|
|
||||||
# """
|
|
||||||
|
|
||||||
# self._look_up_row(website="wikipedia")
|
|
||||||
|
|
||||||
# def scroll_current_to_top(self) -> None:
|
|
||||||
# """Scroll currently-playing row to top"""
|
|
||||||
|
|
||||||
# current_row = track_sequence.now.plr_rownum
|
|
||||||
# if current_row is not None:
|
|
||||||
# self._scroll_to_top(current_row)
|
|
||||||
|
|
||||||
# def scroll_next_to_top(self) -> None:
|
|
||||||
# """Scroll nextly-playing row to top"""
|
|
||||||
|
|
||||||
# next_row = track_sequence.now.plr_rownum
|
|
||||||
# if next_row is not None:
|
|
||||||
# self._scroll_to_top(next_row)
|
|
||||||
|
|
||||||
def set_search(self, text: str) -> None:
|
|
||||||
"""Set search text and find first match"""
|
|
||||||
|
|
||||||
self.search_text = text
|
|
||||||
if not text:
|
|
||||||
# Search string has been reset
|
|
||||||
return
|
|
||||||
self._search(next=True)
|
|
||||||
|
|
||||||
# def search_next(self) -> None:
|
|
||||||
# """
|
|
||||||
# Select next row containg self.search_string.
|
|
||||||
# """
|
|
||||||
|
|
||||||
# self._search(next=True)
|
|
||||||
|
|
||||||
# def search_previous(self) -> None:
|
|
||||||
# """
|
|
||||||
# Select previous row containg self.search_string.
|
|
||||||
# """
|
|
||||||
|
|
||||||
# self._search(next=False)
|
|
||||||
|
|
||||||
# def select_next_row(self) -> None:
|
|
||||||
# """
|
|
||||||
# Select next or first row. Don't select section headers.
|
|
||||||
|
|
||||||
# Wrap at last row.
|
|
||||||
# """
|
|
||||||
|
|
||||||
# selected_rows = self._get_selected_rows()
|
|
||||||
# # we will only handle zero or one selected rows
|
|
||||||
# if len(selected_rows) > 1:
|
|
||||||
# return
|
|
||||||
# # select first row if none selected
|
|
||||||
# if len(selected_rows) == 0:
|
|
||||||
# row_number = 0
|
|
||||||
# else:
|
|
||||||
# row_number = selected_rows[0] + 1
|
|
||||||
# if row_number >= self.rowCount():
|
|
||||||
# row_number = 0
|
|
||||||
|
|
||||||
# # Don't select section headers
|
|
||||||
# wrapped = False
|
|
||||||
# track_id = self._get_row_track_id(row_number)
|
|
||||||
# while not track_id:
|
|
||||||
# row_number += 1
|
|
||||||
# if row_number >= self.rowCount():
|
|
||||||
# if wrapped:
|
|
||||||
# # we're already wrapped once, so there are no
|
|
||||||
# # non-headers
|
|
||||||
# return
|
|
||||||
# row_number = 0
|
|
||||||
# wrapped = True
|
|
||||||
# track_id = self._get_row_track_id(row_number)
|
|
||||||
|
|
||||||
# self.selectRow(row_number)
|
|
||||||
|
|
||||||
# def select_previous_row(self) -> None:
|
|
||||||
# """
|
|
||||||
# Select previous or last track. Don't select section headers.
|
|
||||||
# Wrap at first row.
|
|
||||||
# """
|
|
||||||
|
|
||||||
# selected_rows = self._get_selected_rows()
|
|
||||||
# # we will only handle zero or one selected rows
|
|
||||||
# if len(selected_rows) > 1:
|
|
||||||
# return
|
|
||||||
# # select last row if none selected
|
|
||||||
# last_row = self.rowCount() - 1
|
|
||||||
# if len(selected_rows) == 0:
|
|
||||||
# row_number = last_row
|
|
||||||
# else:
|
|
||||||
# row_number = selected_rows[0] - 1
|
|
||||||
# if row_number < 0:
|
|
||||||
# row_number = last_row
|
|
||||||
|
|
||||||
# # Don't select section headers
|
|
||||||
# wrapped = False
|
|
||||||
# track_id = self._get_row_track_id(row_number)
|
|
||||||
# while not track_id:
|
|
||||||
# row_number -= 1
|
|
||||||
# if row_number < 0:
|
|
||||||
# if wrapped:
|
|
||||||
# # we're already wrapped once, so there are no
|
|
||||||
# # non-notes
|
|
||||||
# return
|
|
||||||
# row_number = last_row
|
|
||||||
# wrapped = True
|
|
||||||
# track_id = self._get_row_track_id(row_number)
|
|
||||||
|
|
||||||
# self.selectRow(row_number)
|
|
||||||
|
|
||||||
def set_row_as_next_track(self) -> None:
|
def set_row_as_next_track(self) -> None:
|
||||||
"""
|
"""
|
||||||
Set selected row as next track
|
Set selected row as next track
|
||||||
@ -660,22 +509,12 @@ class PlaylistTab(QTableView):
|
|||||||
if track_row:
|
if track_row:
|
||||||
self._add_context_menu("Info", lambda: self._info_row(model_row_number))
|
self._add_context_menu("Info", lambda: self._info_row(model_row_number))
|
||||||
|
|
||||||
# Track path TODO
|
# Track path
|
||||||
if track_row:
|
if track_row:
|
||||||
self._add_context_menu(
|
self._add_context_menu(
|
||||||
"Copy track path", lambda: self._copy_path(model_row_number)
|
"Copy track path", lambda: self._copy_path(model_row_number)
|
||||||
)
|
)
|
||||||
|
|
||||||
def _calculate_end_time(
|
|
||||||
self, start: Optional[datetime], duration: int
|
|
||||||
) -> Optional[datetime]:
|
|
||||||
"""Return datetime 'duration' ms after 'start'"""
|
|
||||||
|
|
||||||
if start is None:
|
|
||||||
return None
|
|
||||||
|
|
||||||
return start + timedelta(milliseconds=duration)
|
|
||||||
|
|
||||||
def _column_resize(self, column_number: int, _old: int, _new: int) -> None:
|
def _column_resize(self, column_number: int, _old: int, _new: int) -> None:
|
||||||
"""
|
"""
|
||||||
Called when column width changes. Save new width to database.
|
Called when column width changes. Save new width to database.
|
||||||
@ -776,132 +615,18 @@ class PlaylistTab(QTableView):
|
|||||||
info.setDefaultButton(QMessageBox.StandardButton.Cancel)
|
info.setDefaultButton(QMessageBox.StandardButton.Cancel)
|
||||||
info.exec()
|
info.exec()
|
||||||
|
|
||||||
def _look_up_row(self, website: str) -> None:
|
|
||||||
"""
|
|
||||||
If there is a selected row and it is a track row,
|
|
||||||
look up its title in the passed website
|
|
||||||
|
|
||||||
If multiple rows are selected, only consider the first one.
|
|
||||||
|
|
||||||
Otherwise return.
|
|
||||||
"""
|
|
||||||
|
|
||||||
print("playlists_v3:_look_up_row()")
|
|
||||||
return
|
|
||||||
# selected_row = self._get_selected_row()
|
|
||||||
# if not selected_row:
|
|
||||||
# return
|
|
||||||
|
|
||||||
# if not self._get_row_track_id(selected_row):
|
|
||||||
# return
|
|
||||||
|
|
||||||
# title = self._get_row_title(selected_row)
|
|
||||||
|
|
||||||
# if website == "wikipedia":
|
|
||||||
# QTimer.singleShot(
|
|
||||||
# 0, lambda: self.musicmuster.tabInfolist.open_in_wikipedia(title)
|
|
||||||
# )
|
|
||||||
# elif website == "songfacts":
|
|
||||||
# QTimer.singleShot(
|
|
||||||
# 0, lambda: self.musicmuster.tabInfolist.open_in_songfacts(title)
|
|
||||||
# )
|
|
||||||
# else:
|
|
||||||
# return
|
|
||||||
|
|
||||||
def _mark_as_unplayed(self, row_numbers: List[int]) -> None:
|
def _mark_as_unplayed(self, row_numbers: List[int]) -> None:
|
||||||
"""Rescan track"""
|
"""Rescan track"""
|
||||||
|
|
||||||
self.playlist_model.mark_unplayed(row_numbers)
|
self.playlist_model.mark_unplayed(row_numbers)
|
||||||
self.clear_selection()
|
self.clear_selection()
|
||||||
|
|
||||||
def _obs_change_scene(self, current_row: int) -> None:
|
|
||||||
"""
|
|
||||||
Try to change OBS scene to the name passed
|
|
||||||
"""
|
|
||||||
|
|
||||||
check_row = current_row
|
|
||||||
while True:
|
|
||||||
# If we have a note and it has a scene change command,
|
|
||||||
# execute it
|
|
||||||
note_text = self._get_row_note(check_row)
|
|
||||||
if note_text:
|
|
||||||
match_obj = scene_change_re.search(note_text)
|
|
||||||
if match_obj:
|
|
||||||
scene_name = match_obj.group(1)
|
|
||||||
if scene_name:
|
|
||||||
try:
|
|
||||||
cl = obs.ReqClient(
|
|
||||||
host=Config.OBS_HOST,
|
|
||||||
port=Config.OBS_PORT,
|
|
||||||
password=Config.OBS_PASSWORD,
|
|
||||||
)
|
|
||||||
except ConnectionRefusedError:
|
|
||||||
log.error("OBS connection refused")
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
cl.set_current_program_scene(scene_name)
|
|
||||||
log.info(f"OBS scene changed to '{scene_name}'")
|
|
||||||
return
|
|
||||||
except obs.error.OBSSDKError as e:
|
|
||||||
log.error(f"OBS SDK error ({e})")
|
|
||||||
return
|
|
||||||
# After current track row, only check header rows and stop
|
|
||||||
# at first non-header row
|
|
||||||
check_row -= 1
|
|
||||||
if check_row < 0:
|
|
||||||
break
|
|
||||||
if self._get_row_track_id(check_row):
|
|
||||||
break
|
|
||||||
|
|
||||||
def _rescan(self, row_number: int) -> None:
|
def _rescan(self, row_number: int) -> None:
|
||||||
"""Rescan track"""
|
"""Rescan track"""
|
||||||
|
|
||||||
self.playlist_model.rescan_track(row_number)
|
self.playlist_model.rescan_track(row_number)
|
||||||
self.clear_selection()
|
self.clear_selection()
|
||||||
|
|
||||||
# def _reset_next(self, old_plrid: int, new_plrid: int) -> None:
|
|
||||||
# """
|
|
||||||
# Called when set_next_track_signal signal received.
|
|
||||||
|
|
||||||
# Actions required:
|
|
||||||
# - If old_plrid points to this playlist:
|
|
||||||
# - Remove existing next track
|
|
||||||
# - If new_plrid points to this playlist:
|
|
||||||
# - Set track as next
|
|
||||||
# - Display row as next track
|
|
||||||
# - Update start/stop times
|
|
||||||
# """
|
|
||||||
|
|
||||||
# with Session() as session:
|
|
||||||
# # Get plrs
|
|
||||||
# old_plr = new_plr = None
|
|
||||||
# if old_plrid:
|
|
||||||
# old_plr = session.get(PlaylistRows, old_plrid)
|
|
||||||
|
|
||||||
# # Unmark next track
|
|
||||||
# if old_plr and old_plr.playlist_id == self.playlist_id:
|
|
||||||
# self._set_row_colour_default(old_plr.plr_rownum)
|
|
||||||
|
|
||||||
# # Mark next track
|
|
||||||
# if new_plrid:
|
|
||||||
# new_plr = session.get(PlaylistRows, new_plrid)
|
|
||||||
# if not new_plr:
|
|
||||||
# log.error(f"_reset_next({new_plrid=}): plr not found")
|
|
||||||
# return
|
|
||||||
# if new_plr.playlist_id == self.playlist_id:
|
|
||||||
# self._set_row_colour_next(new_plr.plr_rownum)
|
|
||||||
|
|
||||||
# # Update start/stop times
|
|
||||||
# self._update_start_end_times(session)
|
|
||||||
|
|
||||||
# self.clear_selection()
|
|
||||||
|
|
||||||
def _run_subprocess(self, args):
|
|
||||||
"""Run args in subprocess"""
|
|
||||||
|
|
||||||
subprocess.call(args)
|
|
||||||
|
|
||||||
def scroll_to_top(self, row_number: int) -> None:
|
def scroll_to_top(self, row_number: int) -> None:
|
||||||
"""
|
"""
|
||||||
Scroll to put passed row_number Config.SCROLL_TOP_MARGIN from the
|
Scroll to put passed row_number Config.SCROLL_TOP_MARGIN from the
|
||||||
@ -914,65 +639,6 @@ class PlaylistTab(QTableView):
|
|||||||
row_index = self.proxy_model.index(row_number, 0)
|
row_index = self.proxy_model.index(row_number, 0)
|
||||||
self.scrollTo(row_index, QAbstractItemView.ScrollHint.PositionAtTop)
|
self.scrollTo(row_index, QAbstractItemView.ScrollHint.PositionAtTop)
|
||||||
|
|
||||||
# def _search(self, next: bool = True) -> None:
|
|
||||||
# """
|
|
||||||
# Select next/previous row containg self.search_string. Start from
|
|
||||||
# top selected row if there is one, else from top.
|
|
||||||
|
|
||||||
# Wrap at last/first row.
|
|
||||||
# """
|
|
||||||
|
|
||||||
# if not self.search_text:
|
|
||||||
# return
|
|
||||||
|
|
||||||
# selected_row = self._get_selected_row()
|
|
||||||
# if next:
|
|
||||||
# if selected_row is not None and selected_row < self.rowCount() - 1:
|
|
||||||
# starting_row = selected_row + 1
|
|
||||||
# else:
|
|
||||||
# starting_row = 0
|
|
||||||
# else:
|
|
||||||
# if selected_row is not None and selected_row > 0:
|
|
||||||
# starting_row = selected_row - 1
|
|
||||||
# else:
|
|
||||||
# starting_row = self.rowCount() - 1
|
|
||||||
|
|
||||||
# wrapped = False
|
|
||||||
# match_row = None
|
|
||||||
# row_number = starting_row
|
|
||||||
# needle = self.search_text.lower()
|
|
||||||
# while True:
|
|
||||||
# # Check for match in title, artist or notes
|
|
||||||
# title = self._get_row_title(row_number)
|
|
||||||
# if title and needle in title.lower():
|
|
||||||
# match_row = row_number
|
|
||||||
# break
|
|
||||||
# artist = self._get_row_artist(row_number)
|
|
||||||
# if artist and needle in artist.lower():
|
|
||||||
# match_row = row_number
|
|
||||||
# break
|
|
||||||
# note = self._get_row_note(row_number)
|
|
||||||
# if note and needle in note.lower():
|
|
||||||
# match_row = row_number
|
|
||||||
# break
|
|
||||||
# if next:
|
|
||||||
# row_number += 1
|
|
||||||
# if wrapped and row_number >= starting_row:
|
|
||||||
# break
|
|
||||||
# if row_number >= self.rowCount():
|
|
||||||
# row_number = 0
|
|
||||||
# wrapped = True
|
|
||||||
# else:
|
|
||||||
# row_number -= 1
|
|
||||||
# if wrapped and row_number <= starting_row:
|
|
||||||
# break
|
|
||||||
# if row_number < 0:
|
|
||||||
# row_number = self.rowCount() - 1
|
|
||||||
# wrapped = True
|
|
||||||
|
|
||||||
# if match_row is not None:
|
|
||||||
# self.selectRow(row_number)
|
|
||||||
|
|
||||||
def select_duplicate_rows(self) -> None:
|
def select_duplicate_rows(self) -> None:
|
||||||
"""
|
"""
|
||||||
Select the last of any rows with duplicate tracks in current playlist.
|
Select the last of any rows with duplicate tracks in current playlist.
|
||||||
@ -1036,30 +702,6 @@ class PlaylistTab(QTableView):
|
|||||||
else:
|
else:
|
||||||
self.setColumnWidth(column_number, Config.DEFAULT_COLUMN_WIDTH)
|
self.setColumnWidth(column_number, Config.DEFAULT_COLUMN_WIDTH)
|
||||||
|
|
||||||
# def _set_row_note_colour(self, session: scoped_session, row_number: int) -> None:
|
|
||||||
# """
|
|
||||||
# Set row note colour
|
|
||||||
# """
|
|
||||||
|
|
||||||
# # Sanity check: this should be a track row and thus have a
|
|
||||||
# # track associated
|
|
||||||
# if not self._get_row_track_id(row_number):
|
|
||||||
# if os.environ["MM_ENV"] == "PRODUCTION":
|
|
||||||
# send_mail(
|
|
||||||
# Config.ERRORS_TO,
|
|
||||||
# Config.ERRORS_FROM,
|
|
||||||
# "playlists:_set_row_note_colour() on header row",
|
|
||||||
# stackprinter.format(),
|
|
||||||
# )
|
|
||||||
# # stackprinter.show(add_summary=True, style="darkbg")
|
|
||||||
# print(f"playists:_set_row_note_colour() called on track row ({row_number=}")
|
|
||||||
# return
|
|
||||||
|
|
||||||
# # Set colour
|
|
||||||
# note_text = self._get_row_note(row_number)
|
|
||||||
# note_colour = NoteColours.get_colour(session, note_text)
|
|
||||||
# self._set_cell_colour(row_number, ROW_NOTES, note_colour)
|
|
||||||
|
|
||||||
def _span_cells(self, row: int, column: int, rowSpan: int, columnSpan: int) -> None:
|
def _span_cells(self, row: int, column: int, rowSpan: int, columnSpan: int) -> None:
|
||||||
"""
|
"""
|
||||||
Implement spanning of cells, initiated by signal
|
Implement spanning of cells, initiated by signal
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user