Merge pull request #1034 from phw/PICARD-1060-fix-collection-menu-layout

PICARD-1060: Fix collections menu not looking and behaving like a normal menu
This commit is contained in:
Philipp Wolfer
2018-11-15 11:57:05 +01:00
committed by GitHub

View File

@@ -2,6 +2,7 @@
#
# Picard, the next-generation MusicBrainz tagger
# Copyright (C) 2013 Michael Wiencek
# Copyright (C) 2018 Philipp Wolfer
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@@ -21,6 +22,7 @@ import locale
from PyQt5 import (
QtCore,
QtGui,
QtWidgets,
)
@@ -35,18 +37,24 @@ class CollectionMenu(QtWidgets.QMenu):
def __init__(self, albums, *args):
super().__init__(*args)
self.ids = set(a.id for a in albums)
self._ignore_update = False
self.update_collections()
def update_collections(self):
self._ignore_update = True
self.clear()
self.actions = []
for id_, collection in sorted(user_collections.items(),
key=lambda k_v:
(locale.strxfrm(str(k_v[1])), k_v[0])):
action = QtWidgets.QWidgetAction(self)
action.setDefaultWidget(CollectionCheckBox(self, collection))
action.setDefaultWidget(CollectionMenuItem(self, collection))
self.addAction(action)
self.actions.append(action)
self._ignore_update = False
self.addSeparator()
self.refresh_action = self.addAction(_("Refresh List"))
self.hovered.connect(self.update_highlight)
def refresh_list(self):
self.refresh_action.setEnabled(False)
@@ -57,13 +65,81 @@ class CollectionMenu(QtWidgets.QMenu):
if self.actionAt(event.pos()) == self.refresh_action and self.refresh_action.isEnabled():
self.refresh_list()
def update_highlight(self, action):
if self._ignore_update:
return
for a in self.actions:
a.defaultWidget().set_active(a == action)
def update_active_action_for_widget(self, widget):
if self._ignore_update:
return
for action in self.actions:
action_widget = action.defaultWidget()
is_active = action_widget == widget
if is_active:
self._ignore_hover = True
self.setActiveAction(action)
self._ignore_hover = False
action_widget.set_active(is_active)
class CollectionMenuItem(QtWidgets.QWidget):
def __init__(self, menu, collection):
super().__init__()
self.menu = menu
self.active = False
self._setup_layout(menu, collection)
self._setup_colors()
def _setup_layout(self, menu, collection):
layout = QtWidgets.QVBoxLayout(self)
style = self.style()
layout.setContentsMargins(
style.pixelMetric(QtWidgets.QStyle.PM_LayoutLeftMargin),
style.pixelMetric(QtWidgets.QStyle.PM_FocusFrameVMargin),
style.pixelMetric(QtWidgets.QStyle.PM_LayoutRightMargin),
style.pixelMetric(QtWidgets.QStyle.PM_FocusFrameVMargin))
self.checkbox = CollectionCheckBox(self, menu, collection)
layout.addWidget(self.checkbox)
def _setup_colors(self):
palette = self.palette()
self.text_color = palette.text().color()
self.highlight_color = palette.highlightedText().color()
def set_active(self, active):
self.active = active
palette = self.palette()
textcolor = self.highlight_color if active else self.text_color
palette.setColor(QtGui.QPalette.WindowText, textcolor)
self.checkbox.setPalette(palette)
def enterEvent(self, e):
self.menu.update_active_action_for_widget(self)
def leaveEvent(self, e):
self.set_active(False)
def paintEvent(self, e):
painter = QtWidgets.QStylePainter(self)
option = QtWidgets.QStyleOptionMenuItem()
option.initFrom(self)
option.state = QtWidgets.QStyle.State_None
if self.isEnabled():
option.state |= QtWidgets.QStyle.State_Enabled
if self.active:
option.state |= QtWidgets.QStyle.State_Selected
painter.drawControl(QtWidgets.QStyle.CE_MenuItem, option)
class CollectionCheckBox(QtWidgets.QCheckBox):
def __init__(self, menu, collection):
def __init__(self, parent, menu, collection):
self.menu = menu
self.collection = collection
super().__init__(self.label())
super().__init__(self.label(), parent)
releases = collection.releases & menu.ids
if len(releases) == len(menu.ids):