/usr/share/pyshared/quodlibet/qltk/window.py is in exfalso 3.0.2-3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | # Copyright 2012 Christoph Reiter
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation
from gi.repository import Gtk, GObject, Gdk
from quodlibet import config
from quodlibet.qltk import get_top_parent
class Window(Gtk.Window):
"""Base window class the keeps track of all window instances.
All active instances can be accessed through Window.instances.
By defining dialog=True as a kwarg binds Escape to close, otherwise
^W will close the window.
"""
instances = []
__gsignals__ = {
"close-accel": (GObject.SIGNAL_RUN_LAST | GObject.SIGNAL_ACTION,
GObject.TYPE_NONE, ())
}
def __init__(self, *args, **kwargs):
dialog = kwargs.pop("dialog", True)
super(Window, self).__init__(*args, **kwargs)
type(self).instances.append(self)
self.__accels = Gtk.AccelGroup()
if dialog:
self.set_type_hint(Gdk.WindowTypeHint.DIALOG)
self.set_destroy_with_parent(True)
self.set_position(Gtk.WindowPosition.CENTER_ON_PARENT)
self.add_accel_group(self.__accels)
if not dialog:
self.add_accelerator('close-accel', self.__accels,
ord('w'), Gdk.ModifierType.CONTROL_MASK, 0)
else:
esc, mod = Gtk.accelerator_parse("Escape")
self.add_accelerator('close-accel', self.__accels, esc, mod, 0)
self.connect_object('destroy', type(self).instances.remove, self)
def set_transient_for(self, parent):
"""Set a parent for the window.
In case parent=None, fall back to the main window.
"""
is_toplevel = parent and parent.props.type == Gtk.WindowType.TOPLEVEL
if parent is None or not is_toplevel:
if parent:
print_w("Not a toplevel window set for: %r" % self)
from quodlibet import app
parent = app.window
super(Window, self).set_transient_for(parent)
def do_close_accel(self):
#Do not close the window if we edit a Gtk.CellRendererText.
#Focus the treeview instead.
if isinstance(self.get_focus(), Gtk.Entry) and \
isinstance(self.get_focus().get_parent(), Gtk.TreeView):
self.get_focus().get_parent().grab_focus()
return
if not self.emit('delete-event', Gdk.Event.new(Gdk.EventType.DELETE)):
self.destroy()
class PersistentWindowMixin(object):
"""A mixin for saving/restoring window size/position/maximized state"""
def enable_window_tracking(self, config_prefix, size_suffix=""):
"""Enable tracking/saving of changes and restore size/pos/maximized
config_prefix -- prefix for the config key
(prefix_size, prefix_position, prefix_maximized)
size_suffix -- optional suffix for saving the size. For cases where the
window has multiple states with different content sizes.
(example: edit tags with one song or multiple)
"""
self.__state = 0
self.__name = config_prefix
self.__size_suffix = size_suffix
self.connect('configure-event', self.__save_size)
self.connect('window-state-event', self.__window_state_changed)
self.connect('map', self.__map)
self.__restore_window_state()
def __map(self, *args):
# Some WMs (metacity..) tend to forget the position randomly
self.__restore_window_state()
def __restore_window_state(self):
self.__restore_size()
self.__restore_state()
self.__restore_position()
def __conf(self, name):
if name == "size":
name += "_" + self.__size_suffix
return "%s_%s" % (self.__name, name)
def __restore_state(self):
print_d("Restore state")
if config.getint("memory", self.__conf("maximized"), 0):
self.maximize()
else:
self.unmaximize()
def __restore_position(self):
print_d("Restore position")
pos = config.get('memory', self.__conf("position"), "-1 -1")
x, y = map(int, pos.split())
if x >= 0 and y >= 0:
self.move(x, y)
def __restore_size(self):
print_d("Restore size")
value = config.get('memory', self.__conf("size"), "-1 -1")
x, y = map(int, value.split())
screen = self.get_screen()
x = min(x, screen.get_width())
y = min(y, screen.get_height())
if x >= 0 and y >= 0:
self.resize(x, y)
def __save_size(self, window, event):
if self.__state & Gdk.WindowState.MAXIMIZED:
return
value = "%d %d" % (event.width, event.height)
config.set("memory", self.__conf("size"), value)
if self.get_property("visible"):
pos_value = '%s %s' % self.get_position()
config.set('memory', self.__conf("position"), pos_value)
def __window_state_changed(self, window, event):
self.__state = event.new_window_state
if self.__state & Gdk.WindowState.WITHDRAWN:
return
maximized = int(self.__state & Gdk.WindowState.MAXIMIZED)
config.set("memory", self.__conf("maximized"), maximized)
class UniqueWindow(Window):
"""A wrapper for the window class to get a one instance per class window.
The is_not_unique method will return True if the window
is already there."""
__window = None
def __new__(klass, *args, **kwargs):
window = klass.__window
if window is None:
return super(UniqueWindow, klass).__new__(klass, *args, **kwargs)
#Look for widgets in the args, if there is one and it has
#a new top level window, reparent and reposition the window.
widgets = filter(lambda x: isinstance(x, Gtk.Widget), args)
if widgets:
parent = window.get_transient_for()
new_parent = get_top_parent(widgets[0])
if parent and new_parent and parent is not new_parent:
window.set_transient_for(new_parent)
window.hide()
window.show()
window.present()
return window
@classmethod
def is_not_unique(klass):
if klass.__window:
return True
def __init__(self, *args, **kwargs):
if type(self).__window:
return
else:
type(self).__window = self
super(UniqueWindow, self).__init__(*args, **kwargs)
self.connect_object('destroy', self.__destroy, self)
def __destroy(self, *args):
type(self).__window = None
|