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:
Laurent Monin
2018-03-03 15:50:40 +01:00
parent 5d4f4c82e8
commit b7d8ce91fd
12 changed files with 79 additions and 164 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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()

View File

@@ -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()

View File

@@ -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)

View File

@@ -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"]

View File

@@ -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):

View File

@@ -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()

View File

@@ -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())
]

View File

@@ -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())
]

View File

@@ -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())
]

View File

@@ -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()