def window_grab_and_map(window, mask): """Returns a list of devices that have a grab or an empty list if something failed. If somethings failed the window will be hidden. """ device = Gtk.get_current_event_device() event_time = Gtk.get_current_event_time() if not device: return [] # On wayland we need to grab before mapping and on X11 and everywhere else # we can grab after we are mapped if not is_wayland(): window.show() else: window.realize() Gtk.device_grab_add(window, device, True) status = device.grab( window.get_window(), Gdk.GrabOwnership.WINDOW, True, mask, None, event_time) if status != Gdk.GrabStatus.SUCCESS: Gtk.device_grab_remove(window, device) window.hide() return [] associated_device = device.get_associated_device() if associated_device is None: if is_wayland(): window.show() return [device] Gtk.device_grab_add(window, associated_device, True) status = associated_device.grab( window.get_window(), Gdk.GrabOwnership.WINDOW, True, mask, None, event_time) if status != Gdk.GrabStatus.SUCCESS: Gtk.device_grab_remove(window, associated_device) Gtk.device_grab_remove(window, device) device.ungrab(event_time) window.hide() return [] if is_wayland(): window.show() return [device, associated_device]
def __event(self, event): if not self.__view: return True # hack: present the main window on key press if event.type == Gdk.EventType.BUTTON_PRESS: # hack: present is overridden to present all windows. # bypass to only select one if not is_wayland(): # present duplicates windows in weston Gtk.Window.present(get_top_parent(self.__view)) type_ = event.type real_event = None if type_ == Gdk.EventType.BUTTON_PRESS: real_event = event.button elif type_ == Gdk.EventType.BUTTON_RELEASE: real_event = event.button elif type_ == Gdk.EventType.MOTION_NOTIFY: real_event = event.motion if real_event: real_event.x += self.__dx real_event.y += self.__dy # modifying event.window is a necessary evil, made okay because # nobody else should tie to any TreeViewHints events ever. event.any.window = self.__view.get_bin_window() event.put() return True
def __calculate_screen_width(self, parent): if qltk.is_wayland(): # no screen size with wayland, the parent window is # the next best thing.. width, height = parent.get_size() width = int(width / 1.1) height = int(height / 1.1) return (width, height) else: win = parent.get_window() if win: if qltk.gtk_version[:2] >= (3, 22): disp = Gdk.Display.get_default() mon = disp.get_monitor_at_window(win) rect = mon.get_geometry() else: # The result should be the same as above, just using # deprecated methods instead screen = Gdk.Screen.get_default() mon_num = screen.get_monitor_at_window(win) rect = screen.get_monitor_geometry(mon_num) width = int(rect.width / 1.8) height = int(rect.height / 1.8) return (width, height) width = int(Gdk.Screen.width() / 1.8) height = int(Gdk.Screen.height() / 1.8) return (width, height)
def __calculate_screen_width(self, parent, scale=0.5): if qltk.is_wayland(): # no screen size with wayland, the parent window is # the next best thing.. width, height = parent.get_size() width = int(width / 1.1) height = int(height / 1.1) return (width, height) else: win = parent.get_window() if win: if qltk.gtk_version[:2] >= (3, 22): disp = Gdk.Display.get_default() mon = disp.get_monitor_at_window(win) rect = mon.get_geometry() else: # The result should be the same as above, just using # deprecated methods instead screen = Gdk.Screen.get_default() mon_num = screen.get_monitor_at_window(win) rect = screen.get_monitor_geometry(mon_num) width = int(rect.width * scale) height = int(rect.height * scale) return (width, height) width = int(Gdk.Screen.width() * scale) height = int(Gdk.Screen.height() * scale) return (width, height)
def __event(self, event): if not self.__view: return True # hack: present the main window on key press if event.type == Gdk.EventType.BUTTON_PRESS: # hack: present is overridden to present all windows. # bypass to only select one if not is_wayland(): # present duplicates windows in weston Gtk.Window.present(get_top_parent(self.__view)) def translate_enter_leave_event(event): # enter/leave events have different x/y values as motion events # so it makes sense to push them to the underlying view as # additional motion events. # Warning: this may result in motion events outside of the # view window.. ? new_event = Gdk.Event.new(Gdk.EventType.MOTION_NOTIFY) struct = new_event.motion for attr in ["x", "y", "x_root", "y_root", "time", "window", "state", "send_event"]: setattr(struct, attr, getattr(event.crossing, attr)) device = Gtk.get_current_event_device() if device is not None: struct.set_device(device) return new_event # FIXME: We should translate motion events on the tooltip # to crossing events for the underlying view. # (I think, no tested) Currently the hover scrollbar stays visible # if the mouse leaves the view through the tooltip without the # knowledge of the view. type_ = event.type real_event = None if type_ == Gdk.EventType.BUTTON_PRESS: real_event = event.button elif type_ == Gdk.EventType.BUTTON_RELEASE: real_event = event.button elif type_ == Gdk.EventType.MOTION_NOTIFY: real_event = event.motion elif type_ == Gdk.EventType.ENTER_NOTIFY: event = translate_enter_leave_event(event) real_event = event.motion elif type_ == Gdk.EventType.LEAVE_NOTIFY: event = translate_enter_leave_event(event) real_event = event.motion if real_event: real_event.x += self.__dx real_event.y += self.__dy # modifying event.window is a necessary evil, made okay because # nobody else should tie to any TreeViewHints events ever. event.any.window = self.__view.get_bin_window() Gtk.main_do_event(event) return True
def get_indicator_impl(): """Returns a BaseIndicator implementation depending on the environ""" try: from .appindicator import AppIndicator except ImportError: # no indicator, fall back return SystemTray if is_unity() or is_wayland() or is_plasma(): return AppIndicator return SystemTray
def __event(self, event): if not self.__view: return True # hack: present the main window on key press if event.type == Gdk.EventType.BUTTON_PRESS: # hack: present is overridden to present all windows. # bypass to only select one if not is_wayland(): # present duplicates windows in weston Gtk.Window.present(get_top_parent(self.__view)) def translate_enter_leave_event(event): # enter/leave events have different x/y values as motion events # so it makes sense to push them to the underlying view as # additional motion events. # Warning: this may result in motion events outside of the # view window.. ? new_event = Gdk.Event() new_event.type = Gdk.EventType.MOTION_NOTIFY struct = new_event.motion for attr in ["x", "y", "x_root", "y_root", "time", "window", "state", "send_event"]: setattr(struct, attr, getattr(event.crossing, attr)) struct.device = Gtk.get_current_event_device() return new_event type_ = event.type real_event = None if type_ == Gdk.EventType.BUTTON_PRESS: real_event = event.button elif type_ == Gdk.EventType.BUTTON_RELEASE: real_event = event.button elif type_ == Gdk.EventType.MOTION_NOTIFY: real_event = event.motion elif type_ == Gdk.EventType.ENTER_NOTIFY: event = translate_enter_leave_event(event) real_event = event.motion elif type_ == Gdk.EventType.LEAVE_NOTIFY: event = translate_enter_leave_event(event) real_event = event.motion if real_event: real_event.x += self.__dx real_event.y += self.__dy # modifying event.window is a necessary evil, made okay because # nobody else should tie to any TreeViewHints events ever. event.any.window = self.__view.get_bin_window() Gtk.main_do_event(event) return True
def __init__(self, *args, **kwargs): self._header_bar = None dialog = kwargs.pop("dialog", True) super().__init__(*args, **kwargs) type(self).windows.append(self) if dialog: # Modal is the only way to center the window on the parent # with wayland atm if is_wayland(): self.set_modal(True) self.set_type_hint(Gdk.WindowTypeHint.DIALOG) self.set_destroy_with_parent(True) self.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) connect_obj(self, 'destroy', type(self).windows.remove, self) self.connect('key-press-event', self._on_key_press)
def __init__(self, title, fileobj, parent): super(BigCenteredImage, self).__init__(type=Gtk.WindowType.POPUP) self.set_type_hint(Gdk.WindowTypeHint.TOOLTIP) assert parent parent = qltk.get_top_parent(parent) self.set_transient_for(parent) if qltk.is_wayland(): # no screen size with wayland, the parent window is # the next best thing.. width, height = parent.get_size() width = int(width / 1.1) height = int(height / 1.1) else: width = int(Gdk.Screen.width() / 1.8) height = int(Gdk.Screen.height() / 1.8) self.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) scale_factor = self.get_scale_factor() pixbuf = None try: pixbuf = pixbuf_from_file(fileobj, (width, height), scale_factor) except GLib.GError: pass # failed to load, abort if not pixbuf: self.destroy() return image = Gtk.Image() image.set_from_surface(get_surface_for_pixbuf(self, pixbuf)) event_box = Gtk.EventBox() event_box.add(image) frame = Gtk.Frame() frame.set_shadow_type(Gtk.ShadowType.OUT) frame.add(event_box) self.add(frame) event_box.connect('button-press-event', self.__destroy) event_box.connect('key-press-event', self.__destroy) self.get_child().show_all()
def __init__(self, title, fileobj, parent): super(BigCenteredImage, self).__init__(type=Gtk.WindowType.POPUP) self.set_type_hint(Gdk.WindowTypeHint.TOOLTIP) assert parent parent = qltk.get_top_parent(parent) self.set_transient_for(parent) if qltk.is_wayland(): # no screen size with wayland, the parent window is # the next best thing.. width, height = parent.get_size() width = int(width / 1.1) height = int(height / 1.1) else: width = int(Gdk.Screen.width() / 1.75) height = int(Gdk.Screen.height() / 1.75) self.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) scale_factor = get_scale_factor(self) pixbuf = None try: pixbuf = pixbuf_from_file(fileobj, (width, height), scale_factor) except GLib.GError: pass # failed to load, abort if not pixbuf: self.destroy() return image = Gtk.Image() set_image_from_pbosf(image, get_pbosf_for_pixbuf(self, pixbuf)) event_box = Gtk.EventBox() event_box.add(image) frame = Gtk.Frame() frame.set_shadow_type(Gtk.ShadowType.OUT) frame.add(event_box) self.add(frame) event_box.connect('button-press-event', self.__destroy) event_box.connect('key-press-event', self.__destroy) self.get_child().show_all()
def get_indicator_impl(): """Returns a BaseIndicator implementation depending on the environ""" use_app_indicator = (is_unity() or is_wayland() or is_kde()) print_d("use app indicator: %s" % use_app_indicator) if not use_app_indicator: return SystemTray else: try: from .appindicator import AppIndicator except ImportError: print_w("importing app indicator failed") print_exc() # no indicator, fall back return SystemTray else: return AppIndicator
def __popup_position(self, menu, *args): path, col = self.get_cursor() # get a rectangle describing the cell render area (assume 3 px pad) rect = self.get_cell_area(path, col) padding = 3 rect.x += padding rect.width = max(rect.width - padding * 2, 0) rect.y += padding rect.height = max(rect.height - padding * 2, 0) x, y = self.get_window().get_origin()[1:] x, y = self.convert_bin_window_to_widget_coords(x + rect.x, y + rect.y) menu.realize() ma = menu.get_allocation() menu_y = rect.height + y if self.get_direction() == Gtk.TextDirection.LTR: menu_x = x else: menu_x = x - ma.width + rect.width # on X11/win32 we can use the screen size if not is_wayland(): # fit menu to screen, aligned per text direction screen = self.get_screen() screen_width = screen.get_width() screen_height = screen.get_height() # show above row if no space below and enough above if menu_y + ma.height > screen_height and y - ma.height > 0: menu_y = y - ma.height # make sure it's not outside of the screen if self.get_direction() == Gtk.TextDirection.LTR: menu_x = max(0, min(menu_x, screen_width - ma.width)) else: menu_x = min(max(0, menu_x), screen_width) return (menu_x, menu_y, True) # x, y, move_within_screen
def __motion(self, view, event): label = self.__label clabel = self.__clabel # trigger over row area, not column headers if event.window is not view.get_bin_window(): self.__undisplay() return False # hide if any modifier is active if event.get_state() & Gtk.accelerator_get_default_mod_mask(): self.__undisplay() return False # get the cell at the mouse position x, y = map(int, [event.x, event.y]) try: path, col, cellx, celly = view.get_path_at_pos(x, y) except TypeError: # no hints where no rows exist self.__undisplay() return False col_area = view.get_cell_area(path, col) # make sure we are on the same level if x < col_area.x: self.__undisplay() return False # hide for partial hidden rows at the bottom if y > view.get_visible_rect().height: self.__undisplay() return False # get the renderer at the mouse position and get the xpos/width renderers = col.get_cells() pos = sorted(zip(map(col.cell_get_position, renderers), renderers)) pos = filter(lambda ((x, w), r): x < cellx, pos) if not pos: self.__undisplay() return False (render_offset, render_width), renderer = pos[-1] if self.__current_renderer == renderer and self.__current_path == path: return False # only ellipsized text renderers if not isinstance(renderer, Gtk.CellRendererText): self.__undisplay() return False ellipsize = renderer.get_property('ellipsize') if ellipsize == Pango.EllipsizeMode.END: expand_left = False elif ellipsize == Pango.EllipsizeMode.MIDDLE: # depending on where the cursor is expand_left = x > col_area.x + render_offset + render_width / 2 elif ellipsize == Pango.EllipsizeMode.START: expand_left = True else: self.__undisplay() return False # don't display if the renderer is in editing mode if renderer.props.editing: self.__undisplay() return False # set the cell renderer attributes for the active cell model = view.get_model() col.cell_set_cell_data(model, model.get_iter(path), False, False) # the markup attribute is write only, so the markup text needs # to be saved on the python side, so we can copy it to the label markup = getattr(renderer, "markup", None) if markup is None: text = renderer.get_property('text') set_text = lambda l: l.set_text(text) else: # markup can also be column index if isinstance(markup, int): markup = model[path][markup] set_text = lambda l: l.set_markup(markup) # Use the renderer padding as label padding so the text offset matches render_xpad = renderer.get_property("xpad") label.set_padding(render_xpad, 0) set_text(clabel) clabel.set_padding(render_xpad, 0) label_width = clabel.get_layout().get_pixel_size()[0] label_width += clabel.get_layout_offsets()[0] or 0 # layout offset includes the left padding, so add one more label_width += render_xpad # CellRenderer width is too large if it's the last one in a column. # Use cell_area width as a maximum and limit render_width. max_width = col_area.width if render_width + render_offset > max_width: render_width = max_width - render_offset # don't display if it doesn't need expansion if label_width < render_width: self.__undisplay() return False dummy, ox, oy = view.get_window().get_origin() # save for adjusting passthrough events self.__dx, self.__dy = col_area.x + render_offset, col_area.y if expand_left: # shift to the left # FIXME: ellipsize start produces a space at the end depending # on the text. I don't know how to compute it.. self.__dx -= (label_width - render_width) # final window coordinates/size x = ox + self.__dx y = oy + self.__dy x, y = view.convert_bin_window_to_widget_coords(x, y) w = label_width h = col_area.height if not is_wayland(): # clip if it's bigger than the screen screen_border = 5 # leave some space if not expand_left: space_right = Gdk.Screen.width() - x - w - screen_border if space_right < 0: w += space_right label.set_ellipsize(Pango.EllipsizeMode.END) else: label.set_ellipsize(Pango.EllipsizeMode.NONE) else: space_left = x - screen_border if space_left < 0: x -= space_left self.__dx -= space_left w += space_left label.set_ellipsize(Pango.EllipsizeMode.START) else: label.set_ellipsize(Pango.EllipsizeMode.NONE) else: label.set_ellipsize(Pango.EllipsizeMode.NONE) # Don't show if the resulting tooltip would be smaller # than the visible area (if not all is on the display) if w < render_width: self.__undisplay() return False self.__view = view self.__current_renderer = renderer self.__edit_id = renderer.connect('editing-started', self.__undisplay) self.__current_path = path self.__current_col = col if self.__hide_id: GLib.source_remove(self.__hide_id) self.__hide_id = None self.set_transient_for(get_top_parent(view)) set_text(label) self.set_size_request(w, h) window = self.get_window() if self.get_visible() and window: window.move_resize(x, y, w, h) else: self.move(x, y) self.resize(w, h) self.show() return False
def __motion(self, view, event): label = self.__label clabel = self.__clabel # trigger over row area, not column headers if event.window is not view.get_bin_window(): self.__undisplay() return False x, y = map(int, [event.x, event.y]) # For gtk3.16 overlay scrollbars: if our event x coordinate # is contained in the scrollbar, hide the tooltip. Unlike other # hiding events we don't want to send a leave event to the scrolled # window so the overlay scrollbar does't hide and can be interacted # with. parent = view.get_parent() # We only need to check if the tooltip is there since events # on the scrollbars don't get forwarded to us anyway. if self.__view and parent and isinstance(parent, Gtk.ScrolledWindow): vscrollbar = parent.get_vscrollbar() res = vscrollbar.translate_coordinates(view, 0, 0) if res is not None: x_offset = res[0] vbar_width = vscrollbar.get_allocation().width if x_offset <= x <= x_offset + vbar_width: self.__undisplay(send_leave=False) return False # hide if any modifier is active. mask = Gtk.accelerator_get_default_mod_mask() mask = Gdk.Keymap.get_default().map_virtual_modifiers(mask)[1] if event.get_state() & mask: self.__undisplay() return False # get the cell at the mouse position try: path, col, cellx, celly = view.get_path_at_pos(x, y) except TypeError: # no hints where no rows exist self.__undisplay() return False col_area = view.get_cell_area(path, col) # make sure we are on the same level if x < col_area.x: self.__undisplay() return False # hide for partial hidden rows at the bottom if y > view.get_visible_rect().height: self.__undisplay() return False # get the renderer at the mouse position and get the xpos/width renderers = col.get_cells() pos = sorted(zip(map(col.cell_get_position, renderers), renderers)) pos = list(filter(lambda p: p[0][0] < cellx, pos)) if not pos: self.__undisplay() return False (render_offset, render_width), renderer = pos[-1] if self.__current_renderer == renderer and self.__current_path == path: return False # only ellipsized text renderers if not isinstance(renderer, Gtk.CellRendererText): self.__undisplay() return False ellipsize = renderer.get_property('ellipsize') if ellipsize == Pango.EllipsizeMode.END: expand_left = False elif ellipsize == Pango.EllipsizeMode.MIDDLE: # depending on where the cursor is expand_left = x > col_area.x + render_offset + render_width / 2 elif ellipsize == Pango.EllipsizeMode.START: expand_left = True else: self.__undisplay() return False # don't display if the renderer is in editing mode if renderer.props.editing: self.__undisplay() return False # set the cell renderer attributes for the active cell model = view.get_model() col.cell_set_cell_data(model, model.get_iter(path), False, False) # the markup attribute is write only, so the markup text needs # to be saved on the python side, so we can copy it to the label markup = getattr(renderer, "markup", None) if markup is None: text = renderer.get_property('text') set_text = lambda l: l.set_text(text) else: # markup can also be column index if isinstance(markup, int): markup = model[path][markup] set_text = lambda l: l.set_markup(markup) # Use the renderer padding as label padding so the text offset matches render_xpad = renderer.get_property("xpad") # the renderer xpad is not enough for the tooltip, especially with # rounded corners the label gets nearly clipped. MIN_HINT_X_PAD = 4 if render_xpad < MIN_HINT_X_PAD: extra_xpad = MIN_HINT_X_PAD - render_xpad else: extra_xpad = 0 label.set_padding(render_xpad + extra_xpad, 0) set_text(clabel) clabel.set_padding(render_xpad, 0) label_width = clabel.get_layout().get_pixel_size()[0] label_width += clabel.get_layout_offsets()[0] or 0 # layout offset includes the left padding, so add one more label_width += render_xpad # CellRenderer width is too large if it's the last one in a column. # Use cell_area width as a maximum and limit render_width. max_width = col_area.width if render_width + render_offset > max_width: render_width = max_width - render_offset # don't display if it doesn't need expansion if label_width < render_width: self.__undisplay() return False dummy, ox, oy = view.get_window().get_origin() bg_area = view.get_background_area(path, None) # save for adjusting passthrough events self.__dx, self.__dy = col_area.x + render_offset, bg_area.y self.__dx -= extra_xpad if expand_left: # shift to the left # FIXME: ellipsize start produces a space at the end depending # on the text. I don't know how to compute it.. self.__dx -= (label_width - render_width) # final window coordinates/size x = ox + self.__dx y = oy + self.__dy x, y = view.convert_bin_window_to_widget_coords(x, y) w = label_width + extra_xpad * 2 h = bg_area.height if not is_wayland(): # clip if it's bigger than the monitor mon_border = 5 # leave some space screen = Gdk.Screen.get_default() if not expand_left: monitor_idx = screen.get_monitor_at_point(x, y) mon = screen.get_monitor_geometry(monitor_idx) space_right = mon.x + mon.width - x - w - mon_border if space_right < 0: w += space_right label.set_ellipsize(Pango.EllipsizeMode.END) else: label.set_ellipsize(Pango.EllipsizeMode.NONE) else: monitor_idx = screen.get_monitor_at_point(x + w, y) mon = screen.get_monitor_geometry(monitor_idx) space_left = x - mon.x - mon_border if space_left < 0: x -= space_left self.__dx -= space_left w += space_left label.set_ellipsize(Pango.EllipsizeMode.START) else: label.set_ellipsize(Pango.EllipsizeMode.NONE) else: label.set_ellipsize(Pango.EllipsizeMode.NONE) # Don't show if the resulting tooltip would be smaller # than the visible area (if not all is on the display) if w < render_width: self.__undisplay() return False self.__view = view self.__current_renderer = renderer self.__edit_id = renderer.connect('editing-started', self.__undisplay) self.__current_path = path self.__current_col = col if self.__hide_id: GLib.source_remove(self.__hide_id) self.__hide_id = None self.set_transient_for(get_top_parent(view)) set_text(label) self.set_size_request(w, h) window = self.get_window() if self.get_visible() and window: window.move_resize(x, y, w, h) else: self.move(x, y) self.resize(w, h) self.show() return False
def __restore_window_state(self): if not is_wayland(): self.__restore_state() self.__restore_position() self.__restore_size()
def __init__(self, title, fileobj, parent): super(BigCenteredImage, self).__init__(type=Gtk.WindowType.POPUP) self.set_type_hint(Gdk.WindowTypeHint.TOOLTIP) assert parent parent = qltk.get_top_parent(parent) self.set_transient_for(parent) if qltk.is_wayland(): # no screen size with wayland, the parent window is # the next best thing.. width, height = parent.get_size() width = int(width / 1.1) height = int(height / 1.1) else: win = parent.get_window() if win: if qltk.gtk_version[:2] >= (3, 22): disp = Gdk.Display.get_default() mon = disp.get_monitor_at_window(win) rect = mon.get_geometry() else: # The result should be the same as above, just using # deprecated methods instead screen = Gdk.Screen.get_default() mon_num = screen.get_monitor_at_window(win) rect = screen.get_monitor_geometry(mon_num) width = int(rect.width / 1.8) height = int(rect.height / 1.8) else: width = int(Gdk.Screen.width() / 1.8) height = int(Gdk.Screen.height() / 1.8) self.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) scale_factor = self.get_scale_factor() pixbuf = None try: pixbuf = pixbuf_from_file(fileobj, (width, height), scale_factor) except GLib.GError: pass # failed to load, abort if not pixbuf: self.destroy() return image = Gtk.Image() image.set_from_surface(get_surface_for_pixbuf(self, pixbuf)) event_box = Gtk.EventBox() event_box.add(image) frame = Gtk.Frame() frame.set_shadow_type(Gtk.ShadowType.OUT) frame.add(event_box) self.add(frame) event_box.connect('button-press-event', self.__destroy) event_box.connect('key-press-event', self.__destroy) self.get_child().show_all()
from gi.repository import Gtk, Gdk from tests import TestCase, skipIf from quodlibet.qltk.getstring import GetStringDialog from quodlibet.qltk import is_wayland class _ClipboadTestClass(GetStringDialog): _OK = True def _verify_clipboard(self, text): if self._OK: return text @skipIf(is_wayland(), "blocks under wayland for some reason") class TGetStringDialog(TestCase): def setUp(self): parent = Gtk.Window() self.gsd1 = GetStringDialog(parent, "title", "enter a string") self.gsd2 = _ClipboadTestClass(parent, "title", "enter a string") def test_getstring(self): ret = self.gsd1.run(text="foobar", test=True) self.failUnlessEqual(ret, "foobar") def test_tooltip(self): foo = GetStringDialog(Gtk.Window(), "title", "", tooltip="foo bar") self.failUnlessEqual(foo._val.get_tooltip_text(), "foo bar") def test_clipboard(self):
def test_none(self): self.failUnlessRaises(ValueError, self.Kind, []) def test_some(self): self.some.set_active(2) self.failUnlessEqual(self.some.tag, "foobar") def test_all(self): tags = list(USER_TAGS) tags.sort() for i, value in enumerate(tags): self.all.set_active(i) self.failUnlessEqual(self.all.tag, value) @skipIf(is_wayland(), "crashes..") class TTagsComboBox(TagsCombo): from quodlibet.qltk.tagscombobox import TagsComboBox as Kind Kind @skipIf(is_wayland(), "crashes..") class TTagsComboBoxEntry(TagsCombo): from quodlibet.qltk.tagscombobox import TagsComboBoxEntry as Kind Kind def test_custom(self): self.all.get_child().set_text("a new tag") self.failUnlessEqual(self.all.tag, "a new tag")