PEP8 white space and long line fixes
This commit is contained in:
@@ -54,8 +54,10 @@ import math
|
||||
from sugar.graphics import style
|
||||
from sugar.graphics.icon import Icon
|
||||
|
||||
|
||||
_ = lambda msg: gettext.dgettext('sugar-toolkit', msg)
|
||||
|
||||
|
||||
class Alert(gtk.EventBox):
|
||||
"""
|
||||
UI interface for Alerts
|
||||
@@ -78,18 +80,14 @@ class Alert(gtk.EventBox):
|
||||
__gtype_name__ = 'SugarAlert'
|
||||
|
||||
__gsignals__ = {
|
||||
'response': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([object]))
|
||||
}
|
||||
'response': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([object])),
|
||||
}
|
||||
|
||||
__gproperties__ = {
|
||||
'title' : (str, None, None, None,
|
||||
gobject.PARAM_READWRITE),
|
||||
'msg' : (str, None, None, None,
|
||||
gobject.PARAM_READWRITE),
|
||||
'icon' : (object, None, None,
|
||||
gobject.PARAM_WRITABLE)
|
||||
}
|
||||
'title': (str, None, None, None, gobject.PARAM_READWRITE),
|
||||
'msg': (str, None, None, None, gobject.PARAM_READWRITE),
|
||||
'icon': (object, None, None, gobject.PARAM_WRITABLE),
|
||||
}
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
|
||||
|
||||
@@ -24,12 +24,13 @@ import time
|
||||
import gobject
|
||||
|
||||
EASE_OUT_EXPO = 0
|
||||
EASE_IN_EXPO = 1
|
||||
EASE_IN_EXPO = 1
|
||||
|
||||
|
||||
class Animator(gobject.GObject):
|
||||
|
||||
__gsignals__ = {
|
||||
'completed': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([])),
|
||||
'completed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
|
||||
}
|
||||
|
||||
def __init__(self, duration, fps=20, easing=EASE_OUT_EXPO):
|
||||
@@ -111,7 +112,9 @@ class Animator(gobject.GObject):
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
class Animation(object):
|
||||
|
||||
def __init__(self, start, end):
|
||||
self.start = start
|
||||
self.end = end
|
||||
|
||||
@@ -20,7 +20,9 @@ import hippo
|
||||
|
||||
from sugar.graphics import style
|
||||
|
||||
|
||||
class CanvasTextView(hippo.CanvasWidget):
|
||||
|
||||
def __init__(self, text, **kwargs):
|
||||
hippo.CanvasWidget.__init__(self, **kwargs)
|
||||
self.text_view_widget = gtk.TextView()
|
||||
|
||||
@@ -26,12 +26,15 @@ from sugar.graphics import style
|
||||
from sugar.graphics.icon import Icon
|
||||
from sugar.graphics.palette import Palette, ToolInvoker, WidgetInvoker
|
||||
|
||||
|
||||
_ = lambda msg: gettext.dgettext('sugar-toolkit', msg)
|
||||
|
||||
|
||||
def get_svg_color_string(color):
|
||||
return '#%.2X%.2X%.2X' % (color.red / 257, color.green / 257,
|
||||
color.blue / 257)
|
||||
|
||||
|
||||
class _ColorButton(gtk.Button):
|
||||
"""This is a ColorButton for Sugar. It is similar to the gtk.ColorButton,
|
||||
but does not have any alpha support.
|
||||
@@ -42,8 +45,8 @@ class _ColorButton(gtk.Button):
|
||||
"""
|
||||
|
||||
__gtype_name__ = 'SugarColorButton'
|
||||
__gsignals__ = { 'color-set' : (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
tuple())}
|
||||
__gsignals__ = {'color-set': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
tuple())}
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self._title = _('Choose a color')
|
||||
@@ -78,7 +81,7 @@ class _ColorButton(gtk.Button):
|
||||
if self._has_palette and self._has_invoker:
|
||||
self._invoker = WidgetInvoker(self)
|
||||
# FIXME: This is a hack.
|
||||
self._invoker.has_rectangle_gap = lambda : False
|
||||
self._invoker.has_rectangle_gap = lambda: False
|
||||
self._invoker.palette = self._palette
|
||||
|
||||
def create_palette(self):
|
||||
@@ -86,7 +89,8 @@ class _ColorButton(gtk.Button):
|
||||
self._palette = _ColorPalette(color=self._color,
|
||||
primary_text=self._title)
|
||||
self._palette.connect('color-set', self.__palette_color_set_cb)
|
||||
self._palette.connect('notify::color', self.__palette_color_changed)
|
||||
self._palette.connect('notify::color', self.
|
||||
__palette_color_changed)
|
||||
|
||||
return self._palette
|
||||
|
||||
@@ -192,8 +196,8 @@ class _ColorButton(gtk.Button):
|
||||
getter=_get_accept_drag,
|
||||
setter=_set_accept_drag)
|
||||
|
||||
# Drag and Drop
|
||||
def __drag_begin_cb(self, widget, context):
|
||||
# Drag and Drop
|
||||
pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8,
|
||||
style.SMALL_ICON_SIZE,
|
||||
style.SMALL_ICON_SIZE)
|
||||
@@ -235,10 +239,11 @@ class _ColorPalette(Palette):
|
||||
_BLUE = 2
|
||||
|
||||
__gtype_name__ = 'SugarColorPalette'
|
||||
|
||||
# The color-set signal is emitted when the user is finished selecting
|
||||
# a color.
|
||||
__gsignals__ = { 'color-set' : (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
tuple())}
|
||||
__gsignals__ = {'color-set': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
tuple())}
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self._color = gtk.gdk.Color(0, 0, 0)
|
||||
@@ -300,8 +305,6 @@ class _ColorPalette(Palette):
|
||||
|
||||
return scale
|
||||
|
||||
|
||||
|
||||
def _build_swatches(self):
|
||||
for child in self._swatch_tray.get_children():
|
||||
child.destroy()
|
||||
@@ -384,7 +387,6 @@ class _ColorPalette(Palette):
|
||||
color = gobject.property(type=object, getter=get_color, setter=set_color)
|
||||
|
||||
|
||||
|
||||
def _add_accelerator(tool_button):
|
||||
if not tool_button.props.accelerator or not tool_button.get_toplevel() or \
|
||||
not tool_button.child:
|
||||
@@ -403,20 +405,24 @@ def _add_accelerator(tool_button):
|
||||
tool_button.child.add_accelerator('clicked', accel_group, keyval, mask,
|
||||
gtk.ACCEL_LOCKED | gtk.ACCEL_VISIBLE)
|
||||
|
||||
|
||||
def _hierarchy_changed_cb(tool_button, previous_toplevel):
|
||||
_add_accelerator(tool_button)
|
||||
|
||||
|
||||
def setup_accelerator(tool_button):
|
||||
_add_accelerator(tool_button)
|
||||
tool_button.connect('hierarchy-changed', _hierarchy_changed_cb)
|
||||
|
||||
# This not ideal. It would be better to subclass gtk.ToolButton, however
|
||||
# the python bindings do not seem to be powerfull enough for that.
|
||||
# (As we need to change a variable in the class structure.)
|
||||
|
||||
class ColorToolButton(gtk.ToolItem):
|
||||
# This not ideal. It would be better to subclass gtk.ToolButton, however
|
||||
# the python bindings do not seem to be powerfull enough for that.
|
||||
# (As we need to change a variable in the class structure.)
|
||||
|
||||
__gtype_name__ = 'SugarColorToolButton'
|
||||
__gsignals__ = { 'color-set' : (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
tuple())}
|
||||
__gsignals__ = {'color-set': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
tuple())}
|
||||
|
||||
def __init__(self, icon_name='color-preview', **kwargs):
|
||||
self._accelerator = None
|
||||
@@ -528,4 +534,3 @@ class ColorToolButton(gtk.ToolItem):
|
||||
|
||||
def __color_set_cb(self, widget):
|
||||
self.emit('color-set')
|
||||
|
||||
|
||||
@@ -22,7 +22,9 @@ STABLE.
|
||||
import gobject
|
||||
import gtk
|
||||
|
||||
|
||||
class ComboBox(gtk.ComboBox):
|
||||
|
||||
__gtype_name__ = 'SugarComboBox'
|
||||
|
||||
def __init__(self):
|
||||
|
||||
@@ -22,7 +22,9 @@ STABLE.
|
||||
import gtk
|
||||
import hippo
|
||||
|
||||
|
||||
class CanvasEntry(hippo.CanvasEntry):
|
||||
|
||||
def set_background(self, color_spec):
|
||||
"""
|
||||
Parameters
|
||||
|
||||
@@ -33,9 +33,12 @@ import cairo
|
||||
from sugar.graphics.xocolor import XoColor
|
||||
from sugar.util import LRU
|
||||
|
||||
|
||||
_BADGE_SIZE = 0.45
|
||||
|
||||
|
||||
class _SVGLoader(object):
|
||||
|
||||
def __init__(self):
|
||||
self._cache = LRU(50)
|
||||
|
||||
@@ -61,20 +64,26 @@ class _SVGLoader(object):
|
||||
import rsvg # XXX this is very slow! why?
|
||||
return rsvg.Handle(data=icon)
|
||||
|
||||
|
||||
class _IconInfo(object):
|
||||
|
||||
def __init__(self):
|
||||
self.file_name = None
|
||||
self.attach_x = 0
|
||||
self.attach_y = 0
|
||||
|
||||
|
||||
class _BadgeInfo(object):
|
||||
|
||||
def __init__(self):
|
||||
self.attach_x = 0
|
||||
self.attach_y = 0
|
||||
self.size = 0
|
||||
self.icon_padding = 0
|
||||
|
||||
|
||||
class _IconBuffer(object):
|
||||
|
||||
_surface_cache = LRU(50)
|
||||
_loader = _SVGLoader()
|
||||
|
||||
@@ -219,7 +228,7 @@ class _IconBuffer(object):
|
||||
self.stroke_color = None
|
||||
self.fill_color = None
|
||||
|
||||
def _get_insensitive_pixbuf (self, pixbuf, widget):
|
||||
def _get_insensitive_pixbuf(self, pixbuf, widget):
|
||||
if not (widget and widget.style):
|
||||
return pixbuf
|
||||
|
||||
@@ -309,7 +318,9 @@ class _IconBuffer(object):
|
||||
|
||||
xo_color = property(_get_xo_color, _set_xo_color)
|
||||
|
||||
|
||||
class Icon(gtk.Image):
|
||||
|
||||
__gtype_name__ = 'SugarIcon'
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@@ -510,7 +521,9 @@ class Icon(gtk.Image):
|
||||
badge_name = gobject.property(
|
||||
type=str, getter=get_badge_name, setter=set_badge_name)
|
||||
|
||||
|
||||
class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
|
||||
|
||||
__gtype_name__ = 'CanvasIcon'
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@@ -932,11 +945,13 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
|
||||
|
||||
palette = property(get_palette, set_palette)
|
||||
|
||||
|
||||
class CellRendererIcon(gtk.GenericCellRenderer):
|
||||
|
||||
__gtype_name__ = 'SugarCellRendererIcon'
|
||||
|
||||
__gsignals__ = {
|
||||
'clicked': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, [object])
|
||||
'clicked': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, [object]),
|
||||
}
|
||||
|
||||
def __init__(self, tree_view):
|
||||
@@ -1073,8 +1088,8 @@ class CellRendererIcon(gtk.GenericCellRenderer):
|
||||
|
||||
return False
|
||||
|
||||
def on_render(self, window, widget, background_area, cell_area, expose_area,
|
||||
flags):
|
||||
def on_render(self, window, widget, background_area, cell_area,
|
||||
expose_area, flags):
|
||||
has_prelit_colors = None not in [self._prelit_fill_color,
|
||||
self._prelit_stroke_color]
|
||||
if flags & gtk.CELL_RENDERER_PRELIT and has_prelit_colors and \
|
||||
@@ -1100,6 +1115,7 @@ class CellRendererIcon(gtk.GenericCellRenderer):
|
||||
cr.rectangle(expose_area)
|
||||
cr.paint()
|
||||
|
||||
|
||||
def get_icon_state(base_name, perc, step=5):
|
||||
strength = round(perc / step) * step
|
||||
icon_theme = gtk.icon_theme_get_default()
|
||||
@@ -1111,6 +1127,7 @@ def get_icon_state(base_name, perc, step=5):
|
||||
|
||||
strength = strength + step
|
||||
|
||||
|
||||
def get_icon_file_name(icon_name):
|
||||
icon_theme = gtk.icon_theme_get_default()
|
||||
info = icon_theme.lookup_icon(icon_name, gtk.ICON_SIZE_LARGE_TOOLBAR, 0)
|
||||
@@ -1119,4 +1136,3 @@ def get_icon_file_name(icon_name):
|
||||
filename = info.get_filename()
|
||||
del info
|
||||
return filename
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ from sugar.graphics.icon import _SVGLoader
|
||||
ICON_ENTRY_PRIMARY = _sugarext.ICON_ENTRY_PRIMARY
|
||||
ICON_ENTRY_SECONDARY = _sugarext.ICON_ENTRY_SECONDARY
|
||||
|
||||
|
||||
class IconEntry(_sugarext.IconEntry):
|
||||
|
||||
def __init__(self):
|
||||
@@ -103,4 +104,3 @@ class IconEntry(_sugarext.IconEntry):
|
||||
self.hide_clear_button()
|
||||
else:
|
||||
self.show_clear_button()
|
||||
|
||||
|
||||
@@ -27,7 +27,9 @@ import gtk
|
||||
|
||||
from sugar.graphics.icon import Icon
|
||||
|
||||
|
||||
class MenuItem(gtk.ImageMenuItem):
|
||||
|
||||
def __init__(self, text_label=None, icon_name=None, text_maxlen=60,
|
||||
xo_color=None, file_name=None):
|
||||
gobject.GObject.__init__(self)
|
||||
@@ -91,4 +93,3 @@ class MenuItem(gtk.ImageMenuItem):
|
||||
|
||||
accelerator = gobject.property(type=str, setter=set_accelerator,
|
||||
getter=get_accelerator)
|
||||
|
||||
|
||||
@@ -27,13 +27,14 @@ STABLE.
|
||||
import gtk
|
||||
import gobject
|
||||
|
||||
|
||||
class Notebook(gtk.Notebook):
|
||||
|
||||
__gtype_name__ = 'SugarNotebook'
|
||||
|
||||
__gproperties__ = {
|
||||
'can-close-tabs': (bool, None, None, False,
|
||||
gobject.PARAM_READWRITE |
|
||||
gobject.PARAM_CONSTRUCT_ONLY)
|
||||
gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT_ONLY),
|
||||
}
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
|
||||
@@ -27,11 +27,14 @@ import dbus
|
||||
|
||||
from sugar.datastore import datastore
|
||||
|
||||
|
||||
J_DBUS_SERVICE = 'org.laptop.Journal'
|
||||
J_DBUS_INTERFACE = 'org.laptop.Journal'
|
||||
J_DBUS_PATH = '/org/laptop/Journal'
|
||||
|
||||
|
||||
class ObjectChooser(object):
|
||||
|
||||
def __init__(self, title=None, parent=None, flags=None, buttons=None,
|
||||
what_filter=None):
|
||||
# For backwards compatibility:
|
||||
@@ -127,4 +130,3 @@ class ObjectChooser(object):
|
||||
# Journal service disappeared from the bus
|
||||
self._response_code = gtk.RESPONSE_CANCEL
|
||||
self._cleanup()
|
||||
|
||||
|
||||
@@ -39,16 +39,18 @@ from sugar import _sugarext
|
||||
from sugar.graphics.palettewindow import MouseSpeedDetector, Invoker, \
|
||||
WidgetInvoker, CanvasInvoker, ToolInvoker, CellRendererInvoker
|
||||
|
||||
|
||||
class Palette(PaletteWindow):
|
||||
PRIMARY = 0
|
||||
SECONDARY = 1
|
||||
|
||||
__gtype_name__ = 'SugarPalette'
|
||||
|
||||
# DEPRECATED: label is passed with the primary-text property, accel_path
|
||||
# is set via the invoker property, and menu_after_content is not used
|
||||
def __init__(self, label=None, accel_path=None, menu_after_content=False,
|
||||
text_maxlen=60, **kwargs):
|
||||
# DEPRECATED: label is passed with the primary-text property,
|
||||
# accel_path is set via the invoker property, and menu_after_content
|
||||
# is not used
|
||||
|
||||
self._primary_text = None
|
||||
self._secondary_text = None
|
||||
@@ -238,10 +240,9 @@ class Palette(PaletteWindow):
|
||||
def get_secondary_text(self):
|
||||
return self._secondary_text
|
||||
|
||||
secondary_text = gobject.property(type=str, getter=get_secondary_text,
|
||||
setter=set_secondary_text)
|
||||
|
||||
secondary_text = gobject.property(type=str,
|
||||
getter=get_secondary_text,
|
||||
setter=set_secondary_text)
|
||||
def _show_icon(self):
|
||||
self._label_alignment.set_padding(0, 0, 0, style.DEFAULT_SPACING)
|
||||
self._icon_box.show()
|
||||
@@ -362,7 +363,9 @@ class Palette(PaletteWindow):
|
||||
|
||||
self._palette_state = state
|
||||
|
||||
|
||||
class PaletteActionBar(gtk.HButtonBox):
|
||||
|
||||
def add_action(self, label, icon_name=None):
|
||||
button = gtk.Button(label)
|
||||
|
||||
@@ -374,11 +377,13 @@ class PaletteActionBar(gtk.HButtonBox):
|
||||
self.pack_start(button)
|
||||
button.show()
|
||||
|
||||
|
||||
class _Menu(_sugarext.Menu):
|
||||
|
||||
__gtype_name__ = 'SugarPaletteMenu'
|
||||
|
||||
__gsignals__ = {
|
||||
'item-inserted': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([]))
|
||||
'item-inserted': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
|
||||
}
|
||||
|
||||
def __init__(self, palette):
|
||||
@@ -410,7 +415,9 @@ class _Menu(_sugarext.Menu):
|
||||
def do_deactivate(self):
|
||||
self._palette.hide()
|
||||
|
||||
|
||||
class _SecondaryAnimation(animator.Animation):
|
||||
|
||||
def __init__(self, palette):
|
||||
animator.Animation.__init__(self, 0.0, 1.0)
|
||||
self._palette = palette
|
||||
@@ -418,4 +425,3 @@ class _SecondaryAnimation(animator.Animation):
|
||||
def next_frame(self, current):
|
||||
if current == 1.0:
|
||||
self._palette.set_palette_state(Palette.SECONDARY)
|
||||
|
||||
|
||||
@@ -21,8 +21,10 @@ STABLE.
|
||||
|
||||
import gobject
|
||||
|
||||
|
||||
_groups = {}
|
||||
|
||||
|
||||
def get_group(group_id):
|
||||
if _groups.has_key(group_id):
|
||||
group = _groups[group_id]
|
||||
@@ -32,13 +34,14 @@ def get_group(group_id):
|
||||
|
||||
return group
|
||||
|
||||
|
||||
class Group(gobject.GObject):
|
||||
|
||||
__gsignals__ = {
|
||||
'popup' : (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([])),
|
||||
'popdown' : (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([]))
|
||||
'popup': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
|
||||
'popdown': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
gobject.GObject.__init__(self)
|
||||
self._up = False
|
||||
|
||||
@@ -31,8 +31,9 @@ from sugar.graphics import palettegroup
|
||||
from sugar.graphics import animator
|
||||
from sugar.graphics import style
|
||||
|
||||
# Helper function to find the gap position and size of widget a
|
||||
|
||||
def _calculate_gap(a, b):
|
||||
"""Helper function to find the gap position and size of widget a"""
|
||||
# Test for each side if the palette and invoker are
|
||||
# adjacent to each other.
|
||||
gap = True
|
||||
@@ -63,6 +64,7 @@ def _calculate_gap(a, b):
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
class MouseSpeedDetector(gobject.GObject):
|
||||
|
||||
__gsignals__ = {
|
||||
@@ -125,17 +127,15 @@ class MouseSpeedDetector(gobject.GObject):
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class PaletteWindow(gtk.Window):
|
||||
|
||||
__gtype_name__ = 'SugarPaletteWindow'
|
||||
|
||||
__gsignals__ = {
|
||||
'popup' : (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([])),
|
||||
'popdown' : (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([])),
|
||||
'activate' : (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ([]))
|
||||
'popup': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
|
||||
'popdown': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
|
||||
'activate': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
|
||||
}
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@@ -401,7 +401,9 @@ class PaletteWindow(gtk.Window):
|
||||
|
||||
palette_state = property(get_palette_state)
|
||||
|
||||
|
||||
class _PopupAnimation(animator.Animation):
|
||||
|
||||
def __init__(self, palette):
|
||||
animator.Animation.__init__(self, 0.0, 1.0)
|
||||
self._palette = palette
|
||||
@@ -410,7 +412,9 @@ class _PopupAnimation(animator.Animation):
|
||||
if current == 1.0:
|
||||
self._palette.show()
|
||||
|
||||
|
||||
class _PopdownAnimation(animator.Animation):
|
||||
|
||||
def __init__(self, palette):
|
||||
animator.Animation.__init__(self, 0.0, 1.0)
|
||||
self._palette = palette
|
||||
@@ -419,27 +423,25 @@ class _PopdownAnimation(animator.Animation):
|
||||
if current == 1.0:
|
||||
self._palette.hide()
|
||||
|
||||
|
||||
class Invoker(gobject.GObject):
|
||||
|
||||
__gtype_name__ = 'SugarPaletteInvoker'
|
||||
|
||||
__gsignals__ = {
|
||||
'mouse-enter': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
|
||||
'mouse-leave': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
|
||||
'right-click': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
|
||||
'focus-out': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([]))
|
||||
'focus-out': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
|
||||
}
|
||||
|
||||
ANCHORED = 0
|
||||
AT_CURSOR = 1
|
||||
|
||||
BOTTOM = [(0.0, 0.0, 0.0, 1.0),
|
||||
(-1.0, 0.0, 1.0, 1.0)]
|
||||
RIGHT = [(0.0, 0.0, 1.0, 0.0),
|
||||
(0.0, -1.0, 1.0, 1.0)]
|
||||
TOP = [(0.0, -1.0, 0.0, 0.0),
|
||||
(-1.0, -1.0, 1.0, 0.0)]
|
||||
LEFT = [(-1.0, 0.0, 0.0, 0.0),
|
||||
(-1.0, -1.0, 0.0, 1.0)]
|
||||
BOTTOM = [(0.0, 0.0, 0.0, 1.0), (-1.0, 0.0, 1.0, 1.0)]
|
||||
RIGHT = [(0.0, 0.0, 1.0, 0.0), (0.0, -1.0, 1.0, 1.0)]
|
||||
TOP = [(0.0, -1.0, 0.0, 0.0), (-1.0, -1.0, 1.0, 0.0)]
|
||||
LEFT = [(-1.0, 0.0, 0.0, 0.0), (-1.0, -1.0, 0.0, 1.0)]
|
||||
|
||||
def __init__(self):
|
||||
gobject.GObject.__init__(self)
|
||||
@@ -531,8 +533,9 @@ class Invoker(gobject.GObject):
|
||||
alignment = self.get_alignment(palette_dim)
|
||||
rect = self._get_position_for_alignment(alignment, palette_dim)
|
||||
|
||||
# In case our efforts to find an optimum place inside the screen failed,
|
||||
# just make sure the palette fits inside the screen if at all possible.
|
||||
# In case our efforts to find an optimum place inside the screen
|
||||
# failed, just make sure the palette fits inside the screen if at all
|
||||
# possible.
|
||||
rect.x = max(0, rect.x)
|
||||
rect.y = max(0, rect.y)
|
||||
|
||||
@@ -642,7 +645,9 @@ class Invoker(gobject.GObject):
|
||||
palette = gobject.property(
|
||||
type=object, setter=set_palette, getter=get_palette)
|
||||
|
||||
|
||||
class WidgetInvoker(Invoker):
|
||||
|
||||
def __init__(self, parent=None, widget=None):
|
||||
Invoker.__init__(self)
|
||||
|
||||
@@ -663,11 +668,11 @@ class WidgetInvoker(Invoker):
|
||||
self.notify('widget')
|
||||
|
||||
self._enter_hid = self._widget.connect('enter-notify-event',
|
||||
self.__enter_notify_event_cb)
|
||||
self.__enter_notify_event_cb)
|
||||
self._leave_hid = self._widget.connect('leave-notify-event',
|
||||
self.__leave_notify_event_cb)
|
||||
self.__leave_notify_event_cb)
|
||||
self._release_hid = self._widget.connect('button-release-event',
|
||||
self.__button_release_event_cb)
|
||||
self.__button_release_event_cb)
|
||||
|
||||
self.attach(parent)
|
||||
|
||||
@@ -750,7 +755,9 @@ class WidgetInvoker(Invoker):
|
||||
return self._widget
|
||||
widget = gobject.property(type=object, getter=_get_widget, setter=None)
|
||||
|
||||
|
||||
class CanvasInvoker(Invoker):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
Invoker.__init__(self)
|
||||
|
||||
@@ -806,7 +813,9 @@ class CanvasInvoker(Invoker):
|
||||
def get_toplevel(self):
|
||||
return hippo.get_canvas_for_item(self._item).get_toplevel()
|
||||
|
||||
|
||||
class ToolInvoker(WidgetInvoker):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
WidgetInvoker.__init__(self)
|
||||
|
||||
@@ -826,7 +835,9 @@ class ToolInvoker(WidgetInvoker):
|
||||
else:
|
||||
return self.LEFT + self.RIGHT
|
||||
|
||||
|
||||
class CellRendererInvoker(Invoker):
|
||||
|
||||
def __init__(self):
|
||||
Invoker.__init__(self)
|
||||
|
||||
@@ -910,14 +921,16 @@ class CellRendererInvoker(Invoker):
|
||||
self.notify_mouse_leave()
|
||||
|
||||
def __button_release_event_cb(self, widget, event):
|
||||
if event.button == 1 and self._point_in_cell_renderer(event.x, event.y):
|
||||
if event.button == 1 and self._point_in_cell_renderer(event.x,
|
||||
event.y):
|
||||
tree_view = self._tree_view
|
||||
path, column_, x_, y_ = tree_view.get_path_at_pos(int(event.x),
|
||||
int(event.y))
|
||||
self._cell_renderer.emit('clicked', path)
|
||||
# So the treeview receives it and knows a drag isn't going on
|
||||
return False
|
||||
if event.button == 3 and self._point_in_cell_renderer(event.x, event.y):
|
||||
if event.button == 3 and self._point_in_cell_renderer(event.x,
|
||||
event.y):
|
||||
self.notify_right_click()
|
||||
return True
|
||||
else:
|
||||
@@ -951,4 +964,3 @@ class CellRendererInvoker(Invoker):
|
||||
|
||||
def get_default_position(self):
|
||||
return self.AT_CURSOR
|
||||
|
||||
|
||||
@@ -21,7 +21,10 @@ STABLE.
|
||||
|
||||
import gtk
|
||||
|
||||
|
||||
class Panel(gtk.VBox):
|
||||
|
||||
__gtype_name__ = 'SugarPanel'
|
||||
|
||||
def __init__(self):
|
||||
gtk.VBox.__init__(self)
|
||||
|
||||
@@ -20,7 +20,9 @@ import gtk
|
||||
from sugar.graphics.toolbutton import ToolButton
|
||||
from sugar.graphics.palette import Palette
|
||||
|
||||
|
||||
class RadioMenuButton(ToolButton):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
ToolButton.__init__(self, **kwargs)
|
||||
self.selected_button = None
|
||||
@@ -44,7 +46,9 @@ class RadioMenuButton(ToolButton):
|
||||
else:
|
||||
self.palette.popup(immediate=True, state=Palette.SECONDARY)
|
||||
|
||||
|
||||
class RadioToolsButton(RadioMenuButton):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
RadioMenuButton.__init__(self, **kwargs)
|
||||
|
||||
@@ -53,7 +57,9 @@ class RadioToolsButton(RadioMenuButton):
|
||||
return
|
||||
self.selected_button.emit('clicked')
|
||||
|
||||
|
||||
class RadioPalette(Palette):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
Palette.__init__(self, **kwargs)
|
||||
|
||||
|
||||
@@ -27,11 +27,13 @@ from sugar.graphics.icon import Icon
|
||||
from sugar.graphics.palette import Palette, ToolInvoker
|
||||
from sugar.graphics import toolbutton
|
||||
|
||||
|
||||
class RadioToolButton(gtk.RadioToolButton):
|
||||
"""
|
||||
An implementation of a "push" button.
|
||||
|
||||
"""
|
||||
|
||||
__gtype_name__ = 'SugarRadioToolButton'
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@@ -76,7 +78,8 @@ class RadioToolButton(gtk.RadioToolButton):
|
||||
def get_tooltip(self):
|
||||
return self._tooltip
|
||||
|
||||
tooltip = gobject.property(type=str, setter=set_tooltip, getter=get_tooltip)
|
||||
tooltip = gobject.property(type=str, setter=set_tooltip,
|
||||
getter=get_tooltip)
|
||||
|
||||
def set_accelerator(self, accelerator):
|
||||
"""
|
||||
@@ -177,4 +180,3 @@ class RadioToolButton(gtk.RadioToolButton):
|
||||
allocation.width, allocation.height)
|
||||
|
||||
gtk.RadioToolButton.do_expose_event(self, event)
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import hippo
|
||||
|
||||
from sugar.graphics import style
|
||||
|
||||
|
||||
class CanvasRoundBox(hippo.CanvasBox, hippo.CanvasItem):
|
||||
__gtype_name__ = 'SugarRoundBox'
|
||||
|
||||
|
||||
@@ -28,9 +28,11 @@ import logging
|
||||
import gtk
|
||||
import pango
|
||||
|
||||
|
||||
FOCUS_LINE_WIDTH = 2
|
||||
_TAB_CURVATURE = 1
|
||||
|
||||
|
||||
def _compute_zoom_factor():
|
||||
if os.environ.has_key('SUGAR_SCALING'):
|
||||
try:
|
||||
@@ -41,7 +43,9 @@ def _compute_zoom_factor():
|
||||
|
||||
return 1.0
|
||||
|
||||
|
||||
class Font(object):
|
||||
|
||||
def __init__(self, desc):
|
||||
self._desc = desc
|
||||
|
||||
@@ -51,7 +55,9 @@ class Font(object):
|
||||
def get_pango_desc(self):
|
||||
return pango.FontDescription(self._desc)
|
||||
|
||||
|
||||
class Color(object):
|
||||
|
||||
def __init__(self, color, alpha=1.0):
|
||||
self._r, self._g, self._b = self._html_to_rgb(color)
|
||||
self._a = alpha
|
||||
@@ -91,9 +97,11 @@ class Color(object):
|
||||
else:
|
||||
return self.get_html()
|
||||
|
||||
|
||||
def zoom(units):
|
||||
return int(ZOOM_FACTOR * units)
|
||||
|
||||
|
||||
ZOOM_FACTOR = _compute_zoom_factor()
|
||||
|
||||
DEFAULT_SPACING = zoom(15)
|
||||
|
||||
@@ -25,7 +25,9 @@ import gtk
|
||||
from sugar.graphics.icon import Icon
|
||||
from sugar.graphics.palette import Palette, ToolInvoker
|
||||
|
||||
|
||||
class ToggleToolButton(gtk.ToggleToolButton):
|
||||
|
||||
__gtype_name__ = "SugarToggleToolButton"
|
||||
|
||||
def __init__(self, named_icon=None):
|
||||
|
||||
@@ -24,7 +24,9 @@ from sugar.graphics.palette import PaletteWindow, ToolInvoker
|
||||
from sugar.graphics.toolbutton import ToolButton
|
||||
from sugar.graphics import palettegroup
|
||||
|
||||
|
||||
class ToolbarButton(ToolButton):
|
||||
|
||||
def __init__(self, page=None, **kwargs):
|
||||
ToolButton.__init__(self, **kwargs)
|
||||
|
||||
@@ -132,7 +134,9 @@ class ToolbarButton(ToolButton):
|
||||
gtk.ToolButton.do_expose_event(self, event)
|
||||
_paint_arrow(self, event, gtk.ARROW_UP)
|
||||
|
||||
|
||||
class ToolbarBox(gtk.VBox):
|
||||
|
||||
def __init__(self, padding=style.TOOLBOX_HORIZONTAL_PADDING):
|
||||
gtk.VBox.__init__(self)
|
||||
self.expanded_button = None
|
||||
@@ -177,7 +181,9 @@ class ToolbarBox(gtk.VBox):
|
||||
self.toolbar.parent.parent.modify_bg(state, color)
|
||||
self.toolbar.modify_bg(state, color)
|
||||
|
||||
|
||||
class _ToolbarPalette(PaletteWindow):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
PaletteWindow.__init__(self, **kwargs)
|
||||
self.toolbar_box = None
|
||||
@@ -232,7 +238,9 @@ class _ToolbarPalette(PaletteWindow):
|
||||
if self._focus == 0:
|
||||
self.popdown(immediate=True)
|
||||
|
||||
|
||||
class _Box(gtk.EventBox):
|
||||
|
||||
def __init__(self):
|
||||
gtk.EventBox.__init__(self)
|
||||
self.connect('expose-event', self.do_expose_event)
|
||||
@@ -251,6 +259,7 @@ class _Box(gtk.EventBox):
|
||||
alloc.width - style.FOCUS_LINE_WIDTH * 2,
|
||||
style.FOCUS_LINE_WIDTH)
|
||||
|
||||
|
||||
def _setup_page(page_widget, color, hpad):
|
||||
vpad = style.FOCUS_LINE_WIDTH
|
||||
page_widget.child.set_padding(vpad, vpad, hpad, hpad)
|
||||
@@ -264,6 +273,7 @@ def _setup_page(page_widget, color, hpad):
|
||||
page_widget.modify_bg(gtk.STATE_NORMAL, color)
|
||||
page_widget.modify_bg(gtk.STATE_PRELIGHT, color)
|
||||
|
||||
|
||||
def _embody_page(box_class, widget):
|
||||
widget.show()
|
||||
alignment = gtk.Alignment(0.0, 0.0, 1.0, 1.0)
|
||||
@@ -275,6 +285,7 @@ def _embody_page(box_class, widget):
|
||||
box.show()
|
||||
return box
|
||||
|
||||
|
||||
def _paint_arrow(widget, event, arrow_type):
|
||||
alloc = widget.allocation
|
||||
x = alloc.x + alloc.width / 2 - style.TOOLBAR_ARROW_SIZE / 2
|
||||
|
||||
@@ -25,13 +25,14 @@ import hippo
|
||||
|
||||
from sugar.graphics import style
|
||||
|
||||
|
||||
class Toolbox(gtk.VBox):
|
||||
|
||||
__gtype_name__ = 'SugarToolbox'
|
||||
|
||||
__gsignals__ = {
|
||||
'current-toolbar-changed': (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE,
|
||||
([int]))
|
||||
gobject.TYPE_NONE, ([int])),
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
@@ -98,4 +99,3 @@ class Toolbox(gtk.VBox):
|
||||
return self._notebook.get_current_page()
|
||||
|
||||
current_toolbar = property(get_current_toolbar, set_current_toolbar)
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import gobject
|
||||
from sugar.graphics.icon import Icon
|
||||
from sugar.graphics.palette import Palette, ToolInvoker
|
||||
|
||||
|
||||
def _add_accelerator(tool_button):
|
||||
if not tool_button.props.accelerator or not tool_button.get_toplevel() or \
|
||||
not tool_button.child:
|
||||
@@ -46,14 +47,18 @@ def _add_accelerator(tool_button):
|
||||
tool_button.child.add_accelerator('clicked', accel_group, keyval, mask,
|
||||
gtk.ACCEL_LOCKED | gtk.ACCEL_VISIBLE)
|
||||
|
||||
|
||||
def _hierarchy_changed_cb(tool_button, previous_toplevel):
|
||||
_add_accelerator(tool_button)
|
||||
|
||||
|
||||
def setup_accelerator(tool_button):
|
||||
_add_accelerator(tool_button)
|
||||
tool_button.connect('hierarchy-changed', _hierarchy_changed_cb)
|
||||
|
||||
|
||||
class ToolButton(gtk.ToolButton):
|
||||
|
||||
__gtype_name__ = "SugarToolButton"
|
||||
|
||||
def __init__(self, icon_name=None, **kwargs):
|
||||
@@ -97,7 +102,8 @@ class ToolButton(gtk.ToolButton):
|
||||
def get_tooltip(self):
|
||||
return self._tooltip
|
||||
|
||||
tooltip = gobject.property(type=str, setter=set_tooltip, getter=get_tooltip)
|
||||
tooltip = gobject.property(type=str, setter=set_tooltip,
|
||||
getter=get_tooltip)
|
||||
|
||||
def set_accelerator(self, accelerator):
|
||||
self._accelerator = accelerator
|
||||
|
||||
@@ -25,10 +25,11 @@ import gobject
|
||||
from sugar.graphics.combobox import ComboBox
|
||||
from sugar.graphics import style
|
||||
|
||||
|
||||
class ToolComboBox(gtk.ToolItem):
|
||||
|
||||
__gproperties__ = {
|
||||
'label-text' : (str, None, None, None,
|
||||
gobject.PARAM_WRITABLE),
|
||||
'label-text': (str, None, None, None, gobject.PARAM_WRITABLE),
|
||||
}
|
||||
|
||||
def __init__(self, combo=None, **kwargs):
|
||||
|
||||
+25
-18
@@ -27,17 +27,17 @@ from sugar.graphics.palette import ToolInvoker
|
||||
from sugar.graphics.toolbutton import ToolButton
|
||||
from sugar.graphics.icon import Icon
|
||||
|
||||
|
||||
_PREVIOUS_PAGE = 0
|
||||
_NEXT_PAGE = 1
|
||||
|
||||
|
||||
class _TrayViewport(gtk.Viewport):
|
||||
|
||||
__gproperties__ = {
|
||||
'scrollable' : (bool, None, None, False,
|
||||
gobject.PARAM_READABLE),
|
||||
'can-scroll-prev' : (bool, None, None, False,
|
||||
gobject.PARAM_READABLE),
|
||||
'can-scroll-next' : (bool, None, None, False,
|
||||
gobject.PARAM_READABLE),
|
||||
'scrollable': (bool, None, None, False, gobject.PARAM_READABLE),
|
||||
'can-scroll-prev': (bool, None, None, False, gobject.PARAM_READABLE),
|
||||
'can-scroll-next': (bool, None, None, False, gobject.PARAM_READABLE),
|
||||
}
|
||||
|
||||
def __init__(self, orientation):
|
||||
@@ -161,6 +161,7 @@ class _TrayViewport(gtk.Viewport):
|
||||
|
||||
|
||||
class _TrayScrollButton(ToolButton):
|
||||
|
||||
def __init__(self, icon_name, scroll_direction):
|
||||
ToolButton.__init__(self)
|
||||
self._viewport = None
|
||||
@@ -194,7 +195,6 @@ class _TrayScrollButton(ToolButton):
|
||||
self._viewport_can_scroll_dir_changed_cb)
|
||||
self.set_sensitive(self._viewport.props.can_scroll_next)
|
||||
|
||||
|
||||
def _viewport_scrollable_changed_cb(self, viewport, pspec):
|
||||
self.props.visible = self._viewport.props.scrollable
|
||||
|
||||
@@ -211,19 +211,21 @@ class _TrayScrollButton(ToolButton):
|
||||
|
||||
viewport = property(fset=set_viewport)
|
||||
|
||||
|
||||
ALIGN_TO_START = 0
|
||||
ALIGN_TO_END = 1
|
||||
|
||||
|
||||
class HTray(gtk.HBox):
|
||||
|
||||
__gtype_name__ = 'SugarHTray'
|
||||
|
||||
__gproperties__ = {
|
||||
'align' : (int, None, None, 0, 1, ALIGN_TO_START,
|
||||
gobject.PARAM_READWRITE |
|
||||
gobject.PARAM_CONSTRUCT_ONLY),
|
||||
'drag-active' : (bool, None, None, False,
|
||||
gobject.PARAM_READWRITE)
|
||||
'align': (int, None, None, 0, 1, ALIGN_TO_START,
|
||||
gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT_ONLY),
|
||||
'drag-active': (bool, None, None, False, gobject.PARAM_READWRITE),
|
||||
}
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self._drag_active = False
|
||||
self.align = ALIGN_TO_START
|
||||
@@ -299,15 +301,15 @@ class HTray(gtk.HBox):
|
||||
def scroll_to_item(self, item):
|
||||
self._viewport.scroll_to_item(item)
|
||||
|
||||
|
||||
class VTray(gtk.VBox):
|
||||
|
||||
__gtype_name__ = 'SugarVTray'
|
||||
|
||||
__gproperties__ = {
|
||||
'align' : (int, None, None, 0, 1, ALIGN_TO_START,
|
||||
gobject.PARAM_READWRITE |
|
||||
gobject.PARAM_CONSTRUCT_ONLY),
|
||||
'drag-active' : (bool, None, None, False,
|
||||
gobject.PARAM_READWRITE)
|
||||
'align': (int, None, None, 0, 1, ALIGN_TO_START,
|
||||
gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT_ONLY),
|
||||
'drag-active': (bool, None, None, False, gobject.PARAM_READWRITE),
|
||||
}
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@@ -385,11 +387,15 @@ class VTray(gtk.VBox):
|
||||
def scroll_to_item(self, item):
|
||||
self._viewport.scroll_to_item(item)
|
||||
|
||||
|
||||
class TrayButton(ToolButton):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
ToolButton.__init__(self, **kwargs)
|
||||
|
||||
|
||||
class _IconWidget(gtk.EventBox):
|
||||
|
||||
__gtype_name__ = "SugarTrayIconWidget"
|
||||
|
||||
def __init__(self, icon_name=None, xo_color=None):
|
||||
@@ -413,7 +419,9 @@ class _IconWidget(gtk.EventBox):
|
||||
def get_icon(self):
|
||||
return self._icon
|
||||
|
||||
|
||||
class TrayIcon(gtk.ToolItem):
|
||||
|
||||
__gtype_name__ = "SugarTrayIcon"
|
||||
|
||||
def __init__(self, icon_name=None, xo_color=None):
|
||||
@@ -458,4 +466,3 @@ class TrayIcon(gtk.ToolItem):
|
||||
def get_icon(self):
|
||||
return self._icon_widget.get_icon()
|
||||
icon = property(get_icon, None)
|
||||
|
||||
|
||||
@@ -26,8 +26,10 @@ import warnings
|
||||
|
||||
from sugar.graphics.icon import Icon
|
||||
|
||||
|
||||
_UNFULLSCREEN_BUTTON_VISIBILITY_TIMEOUT = 2
|
||||
|
||||
|
||||
class UnfullscreenButton(gtk.Window):
|
||||
|
||||
def __init__(self):
|
||||
@@ -77,7 +79,9 @@ class UnfullscreenButton(gtk.Window):
|
||||
def _screen_size_changed_cb(self, screen):
|
||||
self._reposition()
|
||||
|
||||
|
||||
class Window(gtk.Window):
|
||||
|
||||
def __init__(self, **args):
|
||||
self._enable_fullscreen_mode = True
|
||||
|
||||
@@ -263,8 +267,7 @@ class Window(gtk.Window):
|
||||
return self._enable_fullscreen_mode
|
||||
|
||||
enable_fullscreen_mode = gobject.property(type=object,
|
||||
setter=set_enable_fullscreen_mode,
|
||||
getter=get_enable_fullscreen_mode)
|
||||
setter=set_enable_fullscreen_mode, getter=get_enable_fullscreen_mode)
|
||||
|
||||
# DEPRECATED
|
||||
|
||||
|
||||
@@ -204,6 +204,7 @@ colors = [
|
||||
['#BCCDFF', '#AC32FF'], \
|
||||
]
|
||||
|
||||
|
||||
def _parse_string(color_string):
|
||||
if color_string == 'white':
|
||||
return ['#ffffff', '#414141']
|
||||
@@ -216,10 +217,13 @@ def _parse_string(color_string):
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def is_valid(color_string):
|
||||
return (_parse_string(color_string) != None)
|
||||
|
||||
|
||||
class XoColor:
|
||||
|
||||
def __init__(self, color_string=None):
|
||||
if color_string == None or not is_valid(color_string):
|
||||
n = int(random.random() * (len(colors) - 1))
|
||||
@@ -242,6 +246,7 @@ class XoColor:
|
||||
def to_string(self):
|
||||
return '%s,%s' % (self.stroke, self.fill)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
import re
|
||||
|
||||
Reference in New Issue
Block a user