mirror of
https://github.com/fergalmoran/picard.git
synced 2026-02-24 16:43:59 +00:00
Introduce and use PreserveGeometry class and drop a lot useless code
It also adds save/restore geometry to: - password dialog - info dialogs (fix PICARD-1093) - tags from filenames dialog - edit tags dialog Each geometry is saved as "geometry_<class_name>" persist option (ByteArray())
This commit is contained in:
@@ -19,10 +19,39 @@
|
||||
|
||||
|
||||
import uuid
|
||||
from picard import config
|
||||
from PyQt5 import QtCore, QtWidgets
|
||||
from picard.util import restore_method
|
||||
|
||||
|
||||
class PicardDialog(QtWidgets.QDialog):
|
||||
class PreserveGeometry:
|
||||
|
||||
defaultsize = None
|
||||
autorestore = True
|
||||
|
||||
def __init__(self):
|
||||
config.Option("persist", self.opt_name(), QtCore.QByteArray())
|
||||
if self.autorestore:
|
||||
self.restore_geometry()
|
||||
if getattr(self, 'finished', None):
|
||||
self.finished.connect(self.save_geometry)
|
||||
|
||||
def opt_name(self):
|
||||
return 'geometry_' + self.__class__.__name__
|
||||
|
||||
@restore_method
|
||||
def restore_geometry(self):
|
||||
geometry = config.persist[self.opt_name()]
|
||||
if not geometry.isNull():
|
||||
self.restoreGeometry(geometry)
|
||||
elif self.defaultsize:
|
||||
self.resize(self.defaultsize)
|
||||
|
||||
def save_geometry(self):
|
||||
config.persist[self.opt_name()] = self.saveGeometry()
|
||||
|
||||
|
||||
class PicardDialog(QtWidgets.QDialog, PreserveGeometry):
|
||||
|
||||
flags = QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint
|
||||
|
||||
|
||||
@@ -31,11 +31,12 @@ from picard.util import restore_method
|
||||
|
||||
|
||||
class CDLookupDialog(PicardDialog):
|
||||
dialog_window_size = "cdlookupdialog_window_size"
|
||||
|
||||
defaultsize = QtCore.QSize(720, 360)
|
||||
autorestore = False
|
||||
dialog_header_state = "cdlookupdialog_header_state"
|
||||
|
||||
options = [
|
||||
config.Option("persist", dialog_window_size, QtCore.QSize(720, 360)),
|
||||
config.Option("persist", dialog_header_state, QtCore.QByteArray())
|
||||
]
|
||||
|
||||
@@ -49,7 +50,6 @@ class CDLookupDialog(PicardDialog):
|
||||
self.ui.release_list.setAlternatingRowColors(True)
|
||||
self.ui.release_list.setHeaderLabels([_("Album"), _("Artist"), _("Date"), _("Country"),
|
||||
_("Labels"), _("Catalog #s"), _("Barcode")])
|
||||
self.restore_state()
|
||||
if self.releases:
|
||||
def myjoin(l):
|
||||
return "\n".join(l)
|
||||
@@ -75,48 +75,31 @@ class CDLookupDialog(PicardDialog):
|
||||
self.ui.release_list.sortByColumn(3, QtCore.Qt.AscendingOrder)
|
||||
self.ui.release_list.sortByColumn(2, QtCore.Qt.DescendingOrder)
|
||||
self.ui.lookup_button.clicked.connect(self.lookup)
|
||||
self.restore_geometry()
|
||||
self.restore_header_state()
|
||||
|
||||
def save_and_accept(self):
|
||||
self.save_state()
|
||||
QtWidgets.QDialog.accept(self)
|
||||
self.finished.connect(self.save_header_state)
|
||||
|
||||
def accept(self):
|
||||
release_id = self.ui.release_list.currentItem().data(0, QtCore.Qt.UserRole)
|
||||
self.tagger.load_album(release_id, discid=self.disc.id)
|
||||
self.save_and_accept()
|
||||
super().accept()
|
||||
|
||||
def lookup(self):
|
||||
lookup = self.tagger.get_file_lookup()
|
||||
lookup.disc_lookup(self.disc.submission_url)
|
||||
self.save_and_accept()
|
||||
|
||||
def reject(self):
|
||||
self.save_state()
|
||||
QtWidgets.QDialog.reject(self)
|
||||
|
||||
@restore_method
|
||||
def restore_state(self):
|
||||
size = config.persist[self.dialog_window_size]
|
||||
if size:
|
||||
self.resize(size)
|
||||
log.debug("restore_state: %s" % self.dialog_window_size)
|
||||
super().accept()
|
||||
|
||||
@restore_method
|
||||
def restore_header_state(self):
|
||||
header = self.ui.release_list.header()
|
||||
state = config.persist[self.dialog_header_state]
|
||||
if state:
|
||||
header.restoreState(state)
|
||||
log.debug("restore_state: %s" % self.dialog_header_state)
|
||||
|
||||
def save_state(self):
|
||||
if self.ui.release_list:
|
||||
self.save_header_state()
|
||||
log.debug("save_state: %s" % self.dialog_window_size)
|
||||
config.persist[self.dialog_window_size] = self.size()
|
||||
header = self.ui.release_list.header()
|
||||
state = config.persist[self.dialog_header_state]
|
||||
if state:
|
||||
header.restoreState(state)
|
||||
log.debug("restore_state: %s" % self.dialog_header_state)
|
||||
|
||||
def save_header_state(self):
|
||||
state = self.ui.release_list.header().saveState()
|
||||
config.persist[self.dialog_header_state] = state
|
||||
log.debug("save_state: %s" % self.dialog_header_state)
|
||||
if self.ui.release_list:
|
||||
state = self.ui.release_list.header().saveState()
|
||||
config.persist[self.dialog_header_state] = state
|
||||
log.debug("save_state: %s" % self.dialog_header_state)
|
||||
|
||||
@@ -25,6 +25,9 @@ from picard.ui.ui_edittagdialog import Ui_EditTagDialog
|
||||
|
||||
class EditTagDialog(PicardDialog):
|
||||
|
||||
defaultsize = None
|
||||
autorestore = False
|
||||
|
||||
def __init__(self, window, tag):
|
||||
super().__init__(window)
|
||||
self.ui = Ui_EditTagDialog()
|
||||
@@ -55,6 +58,7 @@ class EditTagDialog(PicardDialog):
|
||||
self.ui.remove_value.clicked.connect(self.remove_value)
|
||||
self.value_list.itemChanged.connect(self.value_edited)
|
||||
self.value_list.itemSelectionChanged.connect(self.value_selection_changed)
|
||||
self.restore_geometry()
|
||||
|
||||
def edit_value(self):
|
||||
item = self.value_list.currentItem()
|
||||
@@ -175,4 +179,4 @@ class EditTagDialog(PicardDialog):
|
||||
obj.update()
|
||||
self.window.ignore_selection_changes = False
|
||||
self.window.update_selection()
|
||||
QtWidgets.QDialog.accept(self)
|
||||
super().accept()
|
||||
|
||||
@@ -97,6 +97,9 @@ class ArtworkTable(QtWidgets.QTableWidget):
|
||||
|
||||
class InfoDialog(PicardDialog):
|
||||
|
||||
defaultsize = QtCore.QSize(665, 436)
|
||||
autorestore = False
|
||||
|
||||
def __init__(self, obj, parent=None):
|
||||
super().__init__(parent)
|
||||
self.obj = obj
|
||||
@@ -131,14 +134,13 @@ class InfoDialog(PicardDialog):
|
||||
self.ui.artwork_table = ArtworkTable(self.display_existing_artwork)
|
||||
self.ui.artwork_table.setObjectName("artwork_table")
|
||||
self.ui.vboxlayout1.addWidget(self.ui.artwork_table)
|
||||
if self.display_existing_artwork:
|
||||
self.resize(665, 436)
|
||||
self.setTabOrder(self.ui.tabWidget, self.ui.artwork_table)
|
||||
self.setTabOrder(self.ui.artwork_table, self.ui.buttonBox)
|
||||
|
||||
self.setWindowTitle(_("Info"))
|
||||
self.artwork_table = self.ui.artwork_table
|
||||
self._display_tabs()
|
||||
self.restore_geometry()
|
||||
|
||||
def _display_tabs(self):
|
||||
self._display_info_tab()
|
||||
|
||||
@@ -26,15 +26,14 @@ from functools import partial
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
from picard import config, log
|
||||
from picard.ui import PicardDialog
|
||||
from picard.util import restore_method
|
||||
|
||||
|
||||
class LogViewDialog(PicardDialog):
|
||||
defaultsize = QtCore.QSize(570, 400)
|
||||
|
||||
def __init__(self, title, w, h, parent=None):
|
||||
def __init__(self, title, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setWindowFlags(QtCore.Qt.Window)
|
||||
self.resize(w, h)
|
||||
self.setWindowTitle(title)
|
||||
self.doc = QtGui.QTextDocument()
|
||||
self.textCursor = QtGui.QTextCursor(self.doc)
|
||||
@@ -44,26 +43,8 @@ class LogViewDialog(PicardDialog):
|
||||
self.setLayout(self.vbox)
|
||||
self.vbox.addWidget(self.browser)
|
||||
|
||||
def saveWindowState(self, position, size):
|
||||
pos = self.pos()
|
||||
if not pos.isNull():
|
||||
config.persist[position] = pos
|
||||
config.persist[size] = self.size()
|
||||
|
||||
@restore_method
|
||||
def restoreWindowState(self, position, size):
|
||||
pos = config.persist[position]
|
||||
if pos.x() > 0 and pos.y() > 0:
|
||||
self.move(pos)
|
||||
self.resize(config.persist[size])
|
||||
|
||||
def closeEvent(self, event):
|
||||
return super().closeEvent(event)
|
||||
|
||||
|
||||
class LogViewCommon(LogViewDialog):
|
||||
WIDTH = 570
|
||||
HEIGHT = 400
|
||||
|
||||
def __init__(self, log_tail, *args, **kwargs):
|
||||
self.displaying = False
|
||||
@@ -144,17 +125,12 @@ class VerbosityMenu(QtWidgets.QMenu):
|
||||
class LogView(LogViewCommon):
|
||||
|
||||
options = [
|
||||
config.Option("persist", "logview_position", QtCore.QPoint()),
|
||||
config.Option("persist", "logview_size", QtCore.QSize(
|
||||
LogViewCommon.WIDTH, LogViewCommon.HEIGHT)),
|
||||
config.IntOption("setting", "log_verbosity", log.VERBOSITY_DEFAULT),
|
||||
]
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(log.main_tail, _("Log"), w=self.WIDTH,
|
||||
h=self.HEIGHT, parent=parent)
|
||||
super().__init__(log.main_tail, _("Log"), parent=parent)
|
||||
self.verbosity = config.setting['log_verbosity']
|
||||
self.restoreWindowState("logview_position", "logview_size")
|
||||
|
||||
self._setup_formats()
|
||||
self.hl_text = ''
|
||||
@@ -301,10 +277,6 @@ class LogView(LogViewCommon):
|
||||
self.verbosity = level
|
||||
self.verbosity_menu.set_verbosity(self.verbosity)
|
||||
|
||||
def closeEvent(self, event):
|
||||
self.saveWindowState("logview_position", "logview_size")
|
||||
super().closeEvent(event)
|
||||
|
||||
def _verbosity_changed(self, level):
|
||||
if level != self.verbosity:
|
||||
config.setting['log_verbosity'] = level
|
||||
@@ -314,17 +286,6 @@ class LogView(LogViewCommon):
|
||||
|
||||
|
||||
class HistoryView(LogViewCommon):
|
||||
options = [
|
||||
config.Option("persist", "historyview_position", QtCore.QPoint()),
|
||||
config.Option("persist", "historyview_size", QtCore.QSize(LogViewCommon.WIDTH,
|
||||
LogViewCommon.HEIGHT)),
|
||||
]
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(log.history_tail, _("Activity History"), w=self.WIDTH,
|
||||
h=self.HEIGHT, parent=parent)
|
||||
self.restoreWindowState("historyview_position", "historyview_size")
|
||||
|
||||
def closeEvent(self, event):
|
||||
self.saveWindowState("historyview_position", "historyview_size")
|
||||
super().closeEvent(event)
|
||||
super().__init__(log.history_tail, _("Activity History"), parent=parent)
|
||||
|
||||
@@ -29,6 +29,7 @@ from picard.cluster import Cluster
|
||||
from picard.file import File
|
||||
from picard.track import Track
|
||||
from picard.formats import supported_formats
|
||||
from picard.ui import PreserveGeometry
|
||||
from picard.ui.coverartbox import CoverArtBox
|
||||
from picard.ui.itemviews import MainPanel
|
||||
from picard.ui.metadatabox import MetadataBox
|
||||
@@ -58,14 +59,14 @@ def register_ui_init(function):
|
||||
ui_init.register(function.__module__, function)
|
||||
|
||||
|
||||
class MainWindow(QtWidgets.QMainWindow):
|
||||
class MainWindow(QtWidgets.QMainWindow, PreserveGeometry):
|
||||
|
||||
defaultsize = QtCore.QSize(780, 560)
|
||||
autorestore = False
|
||||
selection_updated = QtCore.pyqtSignal(object)
|
||||
|
||||
options = [
|
||||
config.Option("persist", "window_state", QtCore.QByteArray()),
|
||||
config.Option("persist", "window_position", QtCore.QPoint()),
|
||||
config.Option("persist", "window_size", QtCore.QSize(780, 560)),
|
||||
config.Option("persist", "bottom_splitter_state", QtCore.QByteArray()),
|
||||
config.BoolOption("persist", "window_maximized", False),
|
||||
config.BoolOption("persist", "view_cover_art", True),
|
||||
@@ -183,16 +184,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
def saveWindowState(self):
|
||||
config.persist["window_state"] = self.saveState()
|
||||
isMaximized = int(self.windowState()) & QtCore.Qt.WindowMaximized != 0
|
||||
if isMaximized:
|
||||
# FIXME: this doesn't include the window frame
|
||||
geom = self.normalGeometry()
|
||||
config.persist["window_position"] = geom.topLeft()
|
||||
config.persist["window_size"] = geom.size()
|
||||
else:
|
||||
pos = self.pos()
|
||||
if not pos.isNull():
|
||||
config.persist["window_position"] = pos
|
||||
config.persist["window_size"] = self.size()
|
||||
self.save_geometry()
|
||||
config.persist["window_maximized"] = isMaximized
|
||||
config.persist["view_cover_art"] = self.show_cover_art_action.isChecked()
|
||||
config.persist["view_toolbar"] = self.show_toolbar_action.isChecked()
|
||||
@@ -205,16 +197,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
@restore_method
|
||||
def restoreWindowState(self):
|
||||
self.restoreState(config.persist["window_state"])
|
||||
pos = config.persist["window_position"]
|
||||
size = config.persist["window_size"]
|
||||
self._desktopgeo = self.tagger.desktop().screenGeometry()
|
||||
if (pos.x() > 0 and pos.y() > 0
|
||||
and pos.x() + size.width() < self._desktopgeo.width()
|
||||
and pos.y() + size.height() < self._desktopgeo.height()):
|
||||
self.move(pos)
|
||||
if size.width() <= 0 or size.height() <= 0:
|
||||
size = QtCore.QSize(780, 560)
|
||||
self.resize(size)
|
||||
self.restore_geometry()
|
||||
if config.persist["window_maximized"]:
|
||||
self.setWindowState(QtCore.Qt.WindowMaximized)
|
||||
bottom_splitter_state = config.persist["bottom_splitter_state"]
|
||||
|
||||
@@ -47,9 +47,10 @@ from picard.ui.options import (
|
||||
|
||||
class OptionsDialog(PicardDialog):
|
||||
|
||||
defaultsize = QtCore.QSize(560, 400)
|
||||
autorestore = False
|
||||
|
||||
options = [
|
||||
config.Option("persist", "options_position", QtCore.QPoint()),
|
||||
config.Option("persist", "options_size", QtCore.QSize(560, 400)),
|
||||
config.Option("persist", "options_splitter", QtCore.QByteArray()),
|
||||
]
|
||||
|
||||
@@ -119,6 +120,7 @@ class OptionsDialog(PicardDialog):
|
||||
self.ui.pages_tree.itemSelectionChanged.connect(self.switch_page)
|
||||
|
||||
self.restoreWindowState()
|
||||
self.finished.connect(self.saveWindowState)
|
||||
|
||||
for page in self.pages:
|
||||
page.load()
|
||||
@@ -143,26 +145,14 @@ class OptionsDialog(PicardDialog):
|
||||
return
|
||||
for page in self.pages:
|
||||
page.save()
|
||||
self.saveWindowState()
|
||||
QtWidgets.QDialog.accept(self)
|
||||
|
||||
def closeEvent(self, event):
|
||||
self.saveWindowState()
|
||||
event.accept()
|
||||
super().accept()
|
||||
|
||||
def saveWindowState(self):
|
||||
pos = self.pos()
|
||||
if not pos.isNull():
|
||||
config.persist["options_position"] = pos
|
||||
config.persist["options_size"] = self.size()
|
||||
config.persist["options_splitter"] = self.ui.splitter.saveState()
|
||||
|
||||
@restore_method
|
||||
def restoreWindowState(self):
|
||||
pos = config.persist["options_position"]
|
||||
if pos.x() > 0 and pos.y() > 0:
|
||||
self.move(pos)
|
||||
self.resize(config.persist["options_size"])
|
||||
self.restore_geometry()
|
||||
self.ui.splitter.restoreState(config.persist["options_splitter"])
|
||||
|
||||
def restore_all_defaults(self):
|
||||
|
||||
@@ -158,6 +158,8 @@ def to_seconds(timestr):
|
||||
|
||||
class SearchDialog(PicardDialog):
|
||||
|
||||
defaultsize = QtCore.QSize(720, 360)
|
||||
autorestore = False
|
||||
scrolled = pyqtSignal()
|
||||
|
||||
def __init__(self, parent, accept_button_title, show_search=True):
|
||||
@@ -172,6 +174,7 @@ class SearchDialog(PicardDialog):
|
||||
# matching label as values
|
||||
self.columns = None
|
||||
self.sorting_enabled = True
|
||||
self.finished.connect(self.save_state)
|
||||
|
||||
@property
|
||||
def columns(self):
|
||||
@@ -340,21 +343,13 @@ class SearchDialog(PicardDialog):
|
||||
idx = self.table.selectionModel().selectedRows()[0]
|
||||
row = self.table.itemFromIndex(idx).data(QtCore.Qt.UserRole)
|
||||
self.accept_event(row)
|
||||
self.save_state()
|
||||
QtWidgets.QDialog.accept(self)
|
||||
|
||||
def reject(self):
|
||||
self.save_state()
|
||||
QtWidgets.QDialog.reject(self)
|
||||
super().accept()
|
||||
|
||||
@restore_method
|
||||
def restore_state(self):
|
||||
size = config.persist[self.dialog_window_size]
|
||||
if size:
|
||||
self.resize(size)
|
||||
self.restore_geometry()
|
||||
if self.show_search:
|
||||
self.search_box.restore_checkbox_state()
|
||||
log.debug("restore_state: %s" % self.dialog_window_size)
|
||||
|
||||
@restore_method
|
||||
def restore_table_header_state(self):
|
||||
@@ -368,8 +363,6 @@ class SearchDialog(PicardDialog):
|
||||
def save_state(self):
|
||||
if self.table:
|
||||
self.save_table_header_state()
|
||||
config.persist[self.dialog_window_size] = self.size()
|
||||
log.debug("save_state: %s" % self.dialog_window_size)
|
||||
|
||||
def save_table_header_state(self):
|
||||
state = self.table.horizontalHeader().saveState()
|
||||
|
||||
@@ -117,11 +117,9 @@ class CoverCell:
|
||||
|
||||
class AlbumSearchDialog(SearchDialog):
|
||||
|
||||
dialog_window_size = "albumsearchdialog_window_size"
|
||||
dialog_header_state = "albumsearchdialog_header_state"
|
||||
|
||||
options = [
|
||||
config.Option("persist", dialog_window_size, QtCore.QSize(720, 360)),
|
||||
config.Option("persist", dialog_header_state, QtCore.QByteArray())
|
||||
]
|
||||
|
||||
|
||||
@@ -28,11 +28,9 @@ from picard.ui.searchdialog import SearchDialog, Retry, BY_NUMBER
|
||||
|
||||
class ArtistSearchDialog(SearchDialog):
|
||||
|
||||
dialog_window_size = "artistsearchdialog_window_size"
|
||||
dialog_header_state = "artistsearchdialog_header_state"
|
||||
|
||||
options = [
|
||||
config.Option("persist", dialog_window_size, QtCore.QSize(720, 360)),
|
||||
config.Option("persist", dialog_header_state, QtCore.QByteArray())
|
||||
]
|
||||
|
||||
|
||||
@@ -37,11 +37,9 @@ from picard.ui.searchdialog import SearchDialog, Retry, BY_DURATION, BY_NUMBER
|
||||
|
||||
class TrackSearchDialog(SearchDialog):
|
||||
|
||||
dialog_window_size = "tracksearchdialog_window_size"
|
||||
dialog_header_state = "tracksearchdialog_header_state"
|
||||
|
||||
options = [
|
||||
config.Option("persist", dialog_window_size, QtCore.QSize(720, 360)),
|
||||
config.Option("persist", dialog_header_state, QtCore.QByteArray())
|
||||
]
|
||||
|
||||
|
||||
@@ -24,16 +24,15 @@ from picard import config
|
||||
from picard.ui.util import StandardButton
|
||||
from picard.ui import PicardDialog
|
||||
from picard.ui.ui_tagsfromfilenames import Ui_TagsFromFileNamesDialog
|
||||
from picard.util import restore_method
|
||||
from picard.util.tags import display_tag_name
|
||||
|
||||
|
||||
class TagsFromFileNamesDialog(PicardDialog):
|
||||
|
||||
defaultsize = QtCore.QSize(560, 400)
|
||||
|
||||
options = [
|
||||
config.TextOption("persist", "tags_from_filenames_format", ""),
|
||||
config.Option("persist", "tags_from_filenames_position", QtCore.QPoint()),
|
||||
config.Option("persist", "tags_from_filenames_size", QtCore.QSize(560, 400)),
|
||||
]
|
||||
|
||||
def __init__(self, files, parent=None):
|
||||
@@ -64,7 +63,6 @@ class TagsFromFileNamesDialog(PicardDialog):
|
||||
self.ui.buttonbox.rejected.connect(self.reject)
|
||||
self.ui.preview.clicked.connect(self.preview)
|
||||
self.ui.files.setHeaderLabels([_("File Name")])
|
||||
self.restoreWindowState()
|
||||
self.files = files
|
||||
self.items = []
|
||||
for file in files:
|
||||
@@ -127,26 +125,4 @@ class TagsFromFileNamesDialog(PicardDialog):
|
||||
file.metadata[name] = value
|
||||
file.update()
|
||||
config.persist["tags_from_filenames_format"] = self.ui.format.currentText()
|
||||
self.saveWindowState()
|
||||
QtWidgets.QDialog.accept(self)
|
||||
|
||||
def reject(self):
|
||||
self.saveWindowState()
|
||||
QtWidgets.QDialog.reject(self)
|
||||
|
||||
def closeEvent(self, event):
|
||||
self.saveWindowState()
|
||||
event.accept()
|
||||
|
||||
def saveWindowState(self):
|
||||
pos = self.pos()
|
||||
if not pos.isNull():
|
||||
config.persist["tags_from_filenames_position"] = pos
|
||||
config.persist["tags_from_filenames_size"] = self.size()
|
||||
|
||||
@restore_method
|
||||
def restoreWindowState(self):
|
||||
pos = config.persist["tags_from_filenames_position"]
|
||||
if pos.x() > 0 and pos.y() > 0:
|
||||
self.move(pos)
|
||||
self.resize(config.persist["tags_from_filenames_size"])
|
||||
super().accept()
|
||||
|
||||
Reference in New Issue
Block a user