Much improved search now working

This commit is contained in:
Keith Edmunds 2022-08-14 22:19:15 +01:00
parent b7c0fa94dd
commit ebdb0d0a82
4 changed files with 255 additions and 195 deletions

View File

@ -16,7 +16,7 @@ from PyQt5.QtWidgets import (
QFileDialog, QFileDialog,
QInputDialog, QInputDialog,
QLabel, QLabel,
# QLineEdit, QLineEdit,
QListWidgetItem, QListWidgetItem,
QMainWindow, QMainWindow,
# QMessageBox, # QMessageBox,
@ -77,9 +77,9 @@ class Window(QMainWindow, Ui_MainWindow):
self.set_main_window_size() self.set_main_window_size()
self.lblSumPlaytime = QLabel("") self.lblSumPlaytime = QLabel("")
self.statusbar.addPermanentWidget(self.lblSumPlaytime) self.statusbar.addPermanentWidget(self.lblSumPlaytime)
# self.txtSearch = QLineEdit() self.txtSearch = QLineEdit()
# self.statusbar.addWidget(self.txtSearch) self.statusbar.addWidget(self.txtSearch)
# self.txtSearch.setHidden(True) self.txtSearch.setHidden(True)
self.hide_played_tracks = False self.hide_played_tracks = False
self.visible_playlist_tab: Callable[[], PlaylistTab] = \ self.visible_playlist_tab: Callable[[], PlaylistTab] = \
@ -101,8 +101,12 @@ class Window(QMainWindow, Ui_MainWindow):
def clear_selection(self) -> None: def clear_selection(self) -> None:
""" Clear selected row""" """ Clear selected row"""
# Unselect any selected rows
if self.visible_playlist_tab(): if self.visible_playlist_tab():
self.visible_playlist_tab().clear_selection() self.visible_playlist_tab().clear_selection()
# Clear the search bar
self.search_playlist_clear()
def closeEvent(self, event: QEvent) -> None: def closeEvent(self, event: QEvent) -> None:
"""Handle attempt to close main window""" """Handle attempt to close main window"""
@ -148,6 +152,10 @@ class Window(QMainWindow, Ui_MainWindow):
event.accept() event.accept()
def connect_signals_slots(self) -> None: def connect_signals_slots(self) -> None:
self.actionFind_next.triggered.connect(
lambda: self.tabPlaylist.currentWidget().search_next())
self.actionFind_previous.triggered.connect(
lambda: self.tabPlaylist.currentWidget().search_previous())
self.actionInsertSectionHeader.triggered.connect(self.insert_header) self.actionInsertSectionHeader.triggered.connect(self.insert_header)
self.action_Clear_selection.triggered.connect(self.clear_selection) self.action_Clear_selection.triggered.connect(self.clear_selection)
self.actionClosePlaylist.triggered.connect(self.close_playlist_tab) self.actionClosePlaylist.triggered.connect(self.close_playlist_tab)
@ -162,7 +170,7 @@ class Window(QMainWindow, Ui_MainWindow):
self.actionNewPlaylist.triggered.connect(self.create_playlist) self.actionNewPlaylist.triggered.connect(self.create_playlist)
self.actionOpenPlaylist.triggered.connect(self.open_playlist) self.actionOpenPlaylist.triggered.connect(self.open_playlist)
self.actionPlay_next.triggered.connect(self.play_next) self.actionPlay_next.triggered.connect(self.play_next)
# self.actionSearch.triggered.connect(self.search_playlist) self.actionSearch.triggered.connect(self.search_playlist)
self.actionInsertTrack.triggered.connect(self.insert_track) self.actionInsertTrack.triggered.connect(self.insert_track)
self.actionSelect_next_track.triggered.connect(self.select_next_row) self.actionSelect_next_track.triggered.connect(self.select_next_row)
# self.actionSelect_played_tracks.triggered.connect(self.select_played) # self.actionSelect_played_tracks.triggered.connect(self.select_played)
@ -179,9 +187,8 @@ class Window(QMainWindow, Ui_MainWindow):
self.btnFade.clicked.connect(self.fade) self.btnFade.clicked.connect(self.fade)
self.btnStop.clicked.connect(self.stop) self.btnStop.clicked.connect(self.stop)
self.tabPlaylist.tabCloseRequested.connect(self.close_tab) self.tabPlaylist.tabCloseRequested.connect(self.close_tab)
# self.txtSearch.returnPressed.connect(self.search_playlist_return) self.txtSearch.returnPressed.connect(self.search_playlist_return)
# self.txtSearch.textChanged.connect(self.search_playlist_update)
#
self.timer.timeout.connect(self.tick) self.timer.timeout.connect(self.tick)
def close_playlist_tab(self) -> None: def close_playlist_tab(self) -> None:
@ -623,25 +630,34 @@ class Window(QMainWindow, Ui_MainWindow):
with Session() as session: with Session() as session:
dlg = DbDialog(self, session) dlg = DbDialog(self, session)
dlg.exec() dlg.exec()
#
# def search_playlist(self): def search_playlist(self) -> None:
# """Show text box to search playlist""" """Show text box to search playlist"""
#
# self.disable_play_next_controls() # Disable play controls so that 'return' in search box doesn't
# self.txtSearch.setHidden(False) # play next track
# self.txtSearch.setFocus() self.disable_play_next_controls()
# self.txtSearch.setHidden(False)
# def search_playlist_return(self): self.txtSearch.setFocus()
# """Close off search box when return pressed"""
# def search_playlist_clear(self) -> None:
# self.txtSearch.setText("") """Tidy up and reset search bar"""
# self.txtSearch.setHidden(True)
# self.enable_play_next_controls() # Clear the search text
# self.visible_playlist_tab().set_filter("") self.visible_playlist_tab().search("")
# # Clean up search bar
self.txtSearch.setText("")
self.txtSearch.setHidden(True)
def search_playlist_return(self) -> None:
"""Initiate search when return pressed"""
self.visible_playlist_tab().search(self.txtSearch.text())
self.enable_play_next_controls()
# def search_playlist_update(self): # def search_playlist_update(self):
# """Update search when search string changes""" # """Update search when search string changes"""
#
# self.visible_playlist_tab().set_filter(self.txtSearch.text()) # self.visible_playlist_tab().set_filter(self.txtSearch.text())
def open_playlist(self): def open_playlist(self):

View File

@ -146,7 +146,7 @@ class PlaylistTab(QTableWidget):
self.itemSelectionChanged.connect(self._select_event) self.itemSelectionChanged.connect(self._select_event)
self.row_filter: Optional[str] = None self.search_text: str = ""
self.edit_cell_type = None self.edit_cell_type = None
self.selecting_in_progress = False self.selecting_in_progress = False
# Connect signals # Connect signals
@ -775,78 +775,109 @@ class PlaylistTab(QTableWidget):
session.commit() session.commit()
PlaylistRows.delete_higher_rows(session, self.playlist_id, row) PlaylistRows.delete_higher_rows(session, self.playlist_id, row)
# def save_playlist(self, session) -> None: def search(self, text: str) -> None:
# """ """Set search text and find first match"""
# Save playlist to database.
# self.search_text = text
# For notes: check the database entry is correct and update it if if not text:
# necessary. Playlists:Note is one:many, so each note may only appear # Search string has been reset
# in one playlist. return
# self.search_next()
# For tracks: erase the playlist tracks and recreate. This is much
# simpler than trying to implement any Playlists:Tracks many:many def search_next(self) -> None:
# changes. """
# """ Select next row containg self.search_string. Start from
# top selected row if there is one, else from top.
# playlist = Playlists.get_by_id(session, self.playlist_id)
# Wrap at last row.
# # Notes first """
# # Create dictionaries indexed by note_id
# playlist_notes: Dict[int, Notes] = {} if not self.search_text:
# database_notes: Dict[int, Notes] = {} return
# notes_rows: List[int] = self._get_notes_rows()
# selected_row = self._get_selected_row()
# # PlaylistTab if selected_row and selected_row < self.rowCount() - 1:
# for row in notes_rows: starting_row = selected_row + 1
# note: Notes = self._get_row_notes_object(row, session) else:
# session.add(note) starting_row = 0
# playlist_notes[note.id] = note
# if row != note.row: wrapped = False
# log.debug(f"Updating: {playlist.name=}, {row=}, {note.row=}") match_row = None
# note.update(session=session, row=row) row = starting_row
# needle = self.search_text.lower()
# # Database while True:
# for note in playlist.notes: # Check for match in title, artist or notes
# database_notes[note.id] = note title = self._get_row_title(row)
# if title and needle in title.lower():
# # We don't need to check for notes to add to the database as match_row = row
# # they can't exist in the playlist without being in the database break
# # and pointing at this playlist. artist = self._get_row_title(row)
# if artist and needle in artist.lower():
# # Notes to remove from database match_row = row
# for note_id in set(database_notes.keys()) - set(playlist_notes.keys()): break
# log.debug( note = self._get_row_note(row)
# "_save_playlist(): " if note and needle in note.lower():
# f"Delete {note_id=} from {self=} in database" match_row = row
# ) break
# database_notes[note_id].delete_note(session) row += 1
# if wrapped and row >= starting_row:
# # Note rows to update in playlist database break
# for note_id in set(playlist_notes.keys()) & set(database_notes.keys()): if row >= self.rowCount():
# if playlist_notes[note_id].row != database_notes[note_id].row: row = 0
# log.debug( wrapped = True
# f"_save_playlist(): Update notes row in database "
# f"from {database_notes[note_id]=} " if match_row:
# f"to {playlist_notes[note_id]=}" self.selectRow(row)
# )
# database_notes[note_id].update( def search_previous(self) -> None:
# session, row=playlist_notes[note_id].row) """
# Select previous row containg self.search_string. Start from
# # Tracks top selected row if there is one, else from top.
# # Remove all tracks from this playlist
# playlist.remove_all_tracks(session) Wrap at last row.
# # Iterate on-screen playlist and add tracks back in """
# for row in range(self.rowCount()):
# if row in notes_rows: if not self.search_text:
# continue return
# track_id: int = self.item(
# row, FIXUP.COL_USERDATA).data(self.CONTENT_OBJECT) selected_row = self._get_selected_row()
# playlist.add_track(session, track_id, row) if selected_row and selected_row > 0:
# session.commit() starting_row = selected_row - 1
else:
starting_row = self.rowCount() - 1
wrapped = False
match_row = None
row = starting_row
needle = self.search_text.lower()
while True:
# Check for match in title, artist or notes
title = self._get_row_title(row)
if title and needle in title.lower():
match_row = row
break
artist = self._get_row_title(row)
if artist and needle in artist.lower():
match_row = row
break
note = self._get_row_note(row)
if note and needle in note.lower():
match_row = row
break
row -= 1
if wrapped and row <= starting_row:
break
if row < 0:
row = self.rowCount() - 1
wrapped = True
if match_row:
self.selectRow(row)
def select_next_row(self) -> None: def select_next_row(self) -> None:
""" """
Select next or first row. Don't select section headers. Select next or first row. Don't select section headers.
Wrap at last row. Wrap at last row.
""" """
@ -938,13 +969,12 @@ class PlaylistTab(QTableWidget):
# finally: # finally:
# self.selecting_in_progress = False # self.selecting_in_progress = False
# self._select_event() # self._select_event()
#
# def set_filter(self, text: Optional[str]) -> None: def set_searchtext(self, text: Optional[str]) -> None:
# """Filter rows to only show those containing text""" """Set the search text and find first match"""
#
# self.row_filter = text self.search_text = text
# with Session() as session: self._find_next_match()
# self.update_display(session)
def set_selected_as_next(self) -> None: def set_selected_as_next(self) -> None:
"""Sets the select track as next to play""" """Sets the select track as next to play"""
@ -980,10 +1010,6 @@ class PlaylistTab(QTableWidget):
] ]
unreadable: List[int] = self._get_unreadable_track_rows() unreadable: List[int] = self._get_unreadable_track_rows()
if self.row_filter:
filter_text = self.row_filter.lower()
else:
filter_text = None
next_start_time = None next_start_time = None
section_start_plr = None section_start_plr = None
section_time = 0 section_time = 0
@ -1023,22 +1049,6 @@ class PlaylistTab(QTableWidget):
if section_start_plr is not None: if section_start_plr is not None:
section_time += track.duration section_time += track.duration
# If filtering, only show matching tracks
if filter_text:
try:
if (track.title
and filter_text not in track.title.lower()
and track.artist
and filter_text not in track.artist.lower()):
self.hideRow(row)
continue
else:
self.showRow(row)
except TypeError:
print(f"TypeError: {track=}")
else:
self.showRow(row)
# Colour any note # Colour any note
if note_text: if note_text:
(self.item(row, columns['row_notes'].idx) (self.item(row, columns['row_notes'].idx)
@ -1119,14 +1129,6 @@ class PlaylistTab(QTableWidget):
continue continue
# No track associated, so this row is a section header # No track associated, so this row is a section header
if filter_text:
if filter_text not in note_text.lower():
self.hideRow(row)
continue
else:
self.showRow(row)
else:
self.showRow(row)
# Does the note have a start time? # Does the note have a start time?
row_time = self._get_note_text_time(note_text) row_time = self._get_note_text_time(note_text)
if row_time: if row_time:
@ -1264,11 +1266,18 @@ class PlaylistTab(QTableWidget):
return (index.row() + 1 if self._is_below(event.pos(), index) return (index.row() + 1 if self._is_below(event.pos(), index)
else index.row()) else index.row())
# def _get_notes_rows(self) -> List[int]: def _find_next_match(self) -> None:
# """Return rows marked as notes, or None""" """
# Find next match of search_text. Start at first highlighted row
# return self._meta_search(RowMeta.NOTE, one=False) if there is one, else from top of playlist.
# """
start_row = self._get_selected_row()
if start_row is None:
start_row = 0
def _find_next_track_row(self, session: Session, def _find_next_track_row(self, session: Session,
starting_row: int = None) -> Optional[int]: starting_row: int = None) -> Optional[int]:
@ -1340,6 +1349,16 @@ class PlaylistTab(QTableWidget):
return playlistrow_id return playlistrow_id
def _get_row_artist(self, row: int) -> Optional[str]:
"""Return artist on this row or None if none"""
track_id = self._get_row_track_id(row)
if not track_id:
return None
item_artist = self.item(row, columns['artist'].idx)
return item_artist.text()
def _get_row_duration(self, row: int) -> int: def _get_row_duration(self, row: int) -> int:
"""Return duration associated with this row""" """Return duration associated with this row"""
@ -1350,46 +1369,15 @@ class PlaylistTab(QTableWidget):
else: else:
return 0 return 0
def _get_row_track_id(self, row: int) -> int: def _get_row_note(self, row: int) -> Optional[str]:
"""Return the track_id associated with this row or None""" """Return note on this row or None if none"""
track_id = (self.item(row, columns['userdata'].idx) track_id = self._get_row_track_id(row)
.data(self.ROW_TRACK_ID)) if track_id:
item_note = self.item(row, columns['row_notes'].idx)
return track_id else:
item_note = self.item(row, 1)
# return item_note.text()
# def _get_row_end_time(self, row) -> Optional[datetime]:
# """
# Return row end time as string
# """
#
# try:
# if self.item(row, FIXUP.COL_END_TIME):
# return datetime.strptime(self.item(
# row, FIXUP.COL_END_TIME).text(),
# Config.NOTE_TIME_FORMAT
# )
# else:
# return None
# except ValueError:
# return None
#
# def _get_row_notes_object(self, row: int, session: Session) \
# -> Optional[Notes]:
# """Return note associated with this row"""
#
# note_id = self.item(row, FIXUP.COL_USERDATA).data(self.CONTENT_OBJECT)
# note = Notes.get_by_id(session, note_id)
# return note
#
# def _get_unplayed_track_rows(self) -> Optional[List[int]]:
# """Return rows marked as unplayed, or None"""
#
# unplayed_rows: Set[int] = set(self._meta_notset(RowMeta.PLAYED))
# notes_rows: Set[int] = set(self._get_notes_rows())
#
# return list(unplayed_rows - notes_rows)
def _get_row_start_time(self, row: int) -> Optional[datetime]: def _get_row_start_time(self, row: int) -> Optional[datetime]:
try: try:
@ -1403,6 +1391,35 @@ class PlaylistTab(QTableWidget):
except ValueError: except ValueError:
return None return None
def _get_row_title(self, row: int) -> Optional[str]:
"""Return title on this row or None if none"""
track_id = self._get_row_track_id(row)
if not track_id:
return None
item_title = self.item(row, columns['title'].idx)
return item_title.text()
def _get_row_track_id(self, row: int) -> int:
"""Return the track_id associated with this row or None"""
try:
track_id = (self.item(row, columns['userdata'].idx)
.data(self.ROW_TRACK_ID))
except AttributeError:
return None
return track_id
# def _get_unplayed_track_rows(self) -> Optional[List[int]]:
# """Return rows marked as unplayed, or None"""
#
# unplayed_rows: Set[int] = set(self._meta_notset(RowMeta.PLAYED))
# notes_rows: Set[int] = set(self._get_notes_rows())
#
# return list(unplayed_rows - notes_rows)
def _get_selected_row(self) -> Optional[int]: def _get_selected_row(self) -> Optional[int]:
"""Return row number of first selected row, or None if none selected""" """Return row number of first selected row, or None if none selected"""
@ -1410,19 +1427,6 @@ class PlaylistTab(QTableWidget):
return None return None
else: else:
return self.selectionModel().selectedRows()[0].row() return self.selectionModel().selectedRows()[0].row()
#
# def _get_row_track_object(self, row: int, session: Session) \
# -> Optional[Tracks]:
# """Return track associated with this row"""
#
# track_id = self.item(row, FIXUP.COL_USERDATA).data(self.CONTENT_OBJECT)
# track = Tracks.get_by_id(session, track_id)
# return track
#
# def _get_track_rows(self) -> List[int]:
# """Return rows marked as tracks, or None"""
#
# return self._meta_notset(RowMeta.NOTE)
def _get_unreadable_track_rows(self) -> List[int]: def _get_unreadable_track_rows(self) -> List[int]:
"""Return rows marked as unreadable, or None""" """Return rows marked as unreadable, or None"""

View File

@ -784,17 +784,26 @@ border: 1px solid rgb(85, 87, 83);</string>
<addaction name="actionInsertTrack"/> <addaction name="actionInsertTrack"/>
<addaction name="actionRemove"/> <addaction name="actionRemove"/>
<addaction name="actionImport"/> <addaction name="actionImport"/>
<addaction name="separator"/>
<addaction name="actionSetNext"/> <addaction name="actionSetNext"/>
<addaction name="action_Clear_selection"/> <addaction name="action_Clear_selection"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionEnable_controls"/>
</widget>
<widget class="QMenu" name="menuSearc_h">
<property name="title">
<string>Searc&amp;h</string>
</property>
<addaction name="actionSearch"/> <addaction name="actionSearch"/>
<addaction name="actionFind_next"/>
<addaction name="actionFind_previous"/>
<addaction name="separator"/>
<addaction name="actionSelect_next_track"/> <addaction name="actionSelect_next_track"/>
<addaction name="actionSelect_previous_track"/> <addaction name="actionSelect_previous_track"/>
<addaction name="separator"/>
<addaction name="actionEnable_controls"/>
</widget> </widget>
<addaction name="menuFile"/> <addaction name="menuFile"/>
<addaction name="menuPlaylist"/> <addaction name="menuPlaylist"/>
<addaction name="menuSearc_h"/>
</widget> </widget>
<widget class="QStatusBar" name="statusbar"> <widget class="QStatusBar" name="statusbar">
<property name="enabled"> <property name="enabled">
@ -1043,6 +1052,22 @@ border: 1px solid rgb(85, 87, 83);</string>
<string>&amp;Remove track</string> <string>&amp;Remove track</string>
</property> </property>
</action> </action>
<action name="actionFind_next">
<property name="text">
<string>Find next</string>
</property>
<property name="shortcut">
<string>N</string>
</property>
</action>
<action name="actionFind_previous">
<property name="text">
<string>Find previous</string>
</property>
<property name="shortcut">
<string>P</string>
</property>
</action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>

View File

@ -350,6 +350,8 @@ class Ui_MainWindow(object):
self.menuFile.setObjectName("menuFile") self.menuFile.setObjectName("menuFile")
self.menuPlaylist = QtWidgets.QMenu(self.menubar) self.menuPlaylist = QtWidgets.QMenu(self.menubar)
self.menuPlaylist.setObjectName("menuPlaylist") self.menuPlaylist.setObjectName("menuPlaylist")
self.menuSearc_h = QtWidgets.QMenu(self.menubar)
self.menuSearc_h.setObjectName("menuSearc_h")
MainWindow.setMenuBar(self.menubar) MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setEnabled(True) self.statusbar.setEnabled(True)
@ -444,6 +446,10 @@ class Ui_MainWindow(object):
self.actionInsertSectionHeader.setObjectName("actionInsertSectionHeader") self.actionInsertSectionHeader.setObjectName("actionInsertSectionHeader")
self.actionRemove = QtWidgets.QAction(MainWindow) self.actionRemove = QtWidgets.QAction(MainWindow)
self.actionRemove.setObjectName("actionRemove") self.actionRemove.setObjectName("actionRemove")
self.actionFind_next = QtWidgets.QAction(MainWindow)
self.actionFind_next.setObjectName("actionFind_next")
self.actionFind_previous = QtWidgets.QAction(MainWindow)
self.actionFind_previous.setObjectName("actionFind_previous")
self.menuFile.addAction(self.actionNewPlaylist) self.menuFile.addAction(self.actionNewPlaylist)
self.menuFile.addAction(self.actionOpenPlaylist) self.menuFile.addAction(self.actionOpenPlaylist)
self.menuFile.addAction(self.actionClosePlaylist) self.menuFile.addAction(self.actionClosePlaylist)
@ -468,16 +474,20 @@ class Ui_MainWindow(object):
self.menuPlaylist.addAction(self.actionInsertTrack) self.menuPlaylist.addAction(self.actionInsertTrack)
self.menuPlaylist.addAction(self.actionRemove) self.menuPlaylist.addAction(self.actionRemove)
self.menuPlaylist.addAction(self.actionImport) self.menuPlaylist.addAction(self.actionImport)
self.menuPlaylist.addSeparator()
self.menuPlaylist.addAction(self.actionSetNext) self.menuPlaylist.addAction(self.actionSetNext)
self.menuPlaylist.addAction(self.action_Clear_selection) self.menuPlaylist.addAction(self.action_Clear_selection)
self.menuPlaylist.addSeparator() self.menuPlaylist.addSeparator()
self.menuPlaylist.addAction(self.actionSearch)
self.menuPlaylist.addAction(self.actionSelect_next_track)
self.menuPlaylist.addAction(self.actionSelect_previous_track)
self.menuPlaylist.addSeparator()
self.menuPlaylist.addAction(self.actionEnable_controls) self.menuPlaylist.addAction(self.actionEnable_controls)
self.menuSearc_h.addAction(self.actionSearch)
self.menuSearc_h.addAction(self.actionFind_next)
self.menuSearc_h.addAction(self.actionFind_previous)
self.menuSearc_h.addSeparator()
self.menuSearc_h.addAction(self.actionSelect_next_track)
self.menuSearc_h.addAction(self.actionSelect_previous_track)
self.menubar.addAction(self.menuFile.menuAction()) self.menubar.addAction(self.menuFile.menuAction())
self.menubar.addAction(self.menuPlaylist.menuAction()) self.menubar.addAction(self.menuPlaylist.menuAction())
self.menubar.addAction(self.menuSearc_h.menuAction())
self.retranslateUi(MainWindow) self.retranslateUi(MainWindow)
self.tabPlaylist.setCurrentIndex(-1) self.tabPlaylist.setCurrentIndex(-1)
@ -514,6 +524,7 @@ class Ui_MainWindow(object):
self.btnHidePlayed.setText(_translate("MainWindow", "Hide played")) self.btnHidePlayed.setText(_translate("MainWindow", "Hide played"))
self.menuFile.setTitle(_translate("MainWindow", "P&laylists")) self.menuFile.setTitle(_translate("MainWindow", "P&laylists"))
self.menuPlaylist.setTitle(_translate("MainWindow", "Sho&wtime")) self.menuPlaylist.setTitle(_translate("MainWindow", "Sho&wtime"))
self.menuSearc_h.setTitle(_translate("MainWindow", "Searc&h"))
self.actionPlay_next.setText(_translate("MainWindow", "&Play next")) self.actionPlay_next.setText(_translate("MainWindow", "&Play next"))
self.actionPlay_next.setShortcut(_translate("MainWindow", "Return")) self.actionPlay_next.setShortcut(_translate("MainWindow", "Return"))
self.actionSkipToNext.setText(_translate("MainWindow", "Skip to &next")) self.actionSkipToNext.setText(_translate("MainWindow", "Skip to &next"))
@ -560,5 +571,9 @@ class Ui_MainWindow(object):
self.actionInsertSectionHeader.setText(_translate("MainWindow", "Insert &section header...")) self.actionInsertSectionHeader.setText(_translate("MainWindow", "Insert &section header..."))
self.actionInsertSectionHeader.setShortcut(_translate("MainWindow", "Ctrl+H")) self.actionInsertSectionHeader.setShortcut(_translate("MainWindow", "Ctrl+H"))
self.actionRemove.setText(_translate("MainWindow", "&Remove track")) self.actionRemove.setText(_translate("MainWindow", "&Remove track"))
self.actionFind_next.setText(_translate("MainWindow", "Find next"))
self.actionFind_next.setShortcut(_translate("MainWindow", "N"))
self.actionFind_previous.setText(_translate("MainWindow", "Find previous"))
self.actionFind_previous.setShortcut(_translate("MainWindow", "P"))
from infotabs import InfoTabs from infotabs import InfoTabs
import icons_rc import icons_rc