Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
84361afe5c | |||
|
22a18a2069 | ||
|
943af1a316 | ||
|
94ebd86d35 | ||
|
4daa42e883 | ||
|
106bd53a55 |
@ -8,10 +8,12 @@ A GUI for basic tasks of package management using apt:
|
|||||||
* Check for and list all available upgrades
|
* Check for and list all available upgrades
|
||||||
* Download and install all available upgrades
|
* Download and install all available upgrades
|
||||||
|
|
||||||
|
![Screenshot](doc/screenshot.png "Screenshot: Updating the Package Cache")
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
apt install python3-gi
|
sudo apt install python3-gi
|
||||||
```
|
```
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
@ -60,9 +60,8 @@ class UpdateWindow(Gtk.ApplicationWindow):
|
|||||||
self.buffer.set_text("")
|
self.buffer.set_text("")
|
||||||
|
|
||||||
def scroll_to_bottom(self):
|
def scroll_to_bottom(self):
|
||||||
adj = self.scrolledwindow.get_vadjustment()
|
self.buffer.get_end_iter()
|
||||||
adj.set_value(adj.get_upper())
|
self.text_view.scroll_to_mark(self.text_mark_end, 0, False, 0, 0)
|
||||||
self.scrolledwindow.set_vadjustment(adj)
|
|
||||||
|
|
||||||
def level_to_color(self, level):
|
def level_to_color(self, level):
|
||||||
if level == "INFO":
|
if level == "INFO":
|
||||||
@ -72,47 +71,76 @@ class UpdateWindow(Gtk.ApplicationWindow):
|
|||||||
else:
|
else:
|
||||||
return "grey"
|
return "grey"
|
||||||
|
|
||||||
def prepend_mesg(self, level, text):
|
|
||||||
self.prepend(text)
|
|
||||||
self.prepend_color(level + ": ", self.level_to_color(level))
|
|
||||||
|
|
||||||
def append_mesg(self, level, text):
|
def append_mesg(self, level, text):
|
||||||
self.append_color(level + ": ", self.level_to_color(level))
|
self.append_color(
|
||||||
|
level + ": ",
|
||||||
|
self.level_to_color(level)
|
||||||
|
)
|
||||||
self.append(text)
|
self.append(text)
|
||||||
|
|
||||||
def prepend_markup(self, markup):
|
|
||||||
self.insert_markup(markup, self.buffer.get_start_iter())
|
|
||||||
|
|
||||||
def append_markup(self, markup):
|
def append_markup(self, markup):
|
||||||
self.insert_markup(markup, self.buffer.get_end_iter())
|
self.insert_markup(
|
||||||
|
markup,
|
||||||
|
self.buffer.get_end_iter()
|
||||||
|
)
|
||||||
|
|
||||||
def insert_markup(self, markup, iter):
|
def insert_markup(self, markup, iter):
|
||||||
self.buffer.insert_markup(iter, markup, -1)
|
self.buffer.insert_markup(iter, markup, -1)
|
||||||
|
|
||||||
def prepend_color(self, text, color):
|
|
||||||
self.insert_color(text, color, self.buffer.get_start_iter())
|
|
||||||
|
|
||||||
def append_color(self, text, color):
|
def append_color(self, text, color):
|
||||||
self.insert_color(text, color, self.buffer.get_end_iter())
|
self.insert_color(
|
||||||
|
text,
|
||||||
|
color,
|
||||||
|
self.buffer.get_end_iter()
|
||||||
|
)
|
||||||
|
|
||||||
def insert_color(self, text, color, iter):
|
def insert_color(self, text, color, iter):
|
||||||
self.buffer.insert_markup(
|
self.buffer.insert_markup(
|
||||||
iter,
|
iter,
|
||||||
"<span color=\"%s\">%s</span>" % (color, html.escape(text)),
|
"<span color=\"%s\">%s</span>" % (
|
||||||
|
color,
|
||||||
|
html.escape(text)),
|
||||||
-1)
|
-1)
|
||||||
|
|
||||||
def prepend(self, text):
|
|
||||||
self.insert(text, self.buffer.get_start_iter())
|
|
||||||
|
|
||||||
def append(self, text):
|
def append(self, text):
|
||||||
self.insert(text, self.buffer.get_end_iter())
|
self.insert(
|
||||||
|
text,
|
||||||
|
self.buffer.get_end_iter()
|
||||||
|
)
|
||||||
self.scroll_to_bottom()
|
self.scroll_to_bottom()
|
||||||
|
|
||||||
def insert(self, text, iter):
|
def insert(self, text, iter):
|
||||||
self.buffer.insert(iter, text + "\n")
|
self.buffer.insert(iter, text + "\n")
|
||||||
|
|
||||||
def execute(self, args, ignore_stderr=False, output_msg=None,
|
def run_thread(self, args, env, prefix=None):
|
||||||
empty_msg=None, env={}, clear=True):
|
if self.thread is None:
|
||||||
|
do_run = True
|
||||||
|
elif not self.thread.is_alive():
|
||||||
|
do_run = True
|
||||||
|
else:
|
||||||
|
do_run = False
|
||||||
|
|
||||||
|
if do_run:
|
||||||
|
self.thread = threading.Thread(
|
||||||
|
target=self.run,
|
||||||
|
args=(args, env, prefix,))
|
||||||
|
|
||||||
|
self.thread.start()
|
||||||
|
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def execute(
|
||||||
|
self,
|
||||||
|
args,
|
||||||
|
ignore_stderr=False,
|
||||||
|
output_msg=None,
|
||||||
|
empty_msg=None,
|
||||||
|
prefix=None,
|
||||||
|
env={},
|
||||||
|
clear=True
|
||||||
|
):
|
||||||
self.lock()
|
self.lock()
|
||||||
|
|
||||||
if clear:
|
if clear:
|
||||||
@ -123,15 +151,24 @@ class UpdateWindow(Gtk.ApplicationWindow):
|
|||||||
self.ignore_stderr = ignore_stderr
|
self.ignore_stderr = ignore_stderr
|
||||||
self.stdout = ''
|
self.stdout = ''
|
||||||
self.stderr = ''
|
self.stderr = ''
|
||||||
self.prepend_mesg(
|
self.append_mesg(
|
||||||
"INFO",
|
"INFO",
|
||||||
"Running command \"%s\" ..." % " ".join(args))
|
"Running command \"%s\" ..." % " ".join(args))
|
||||||
thread = threading.Thread(target=self.run, args=(args, env,))
|
|
||||||
thread.start()
|
|
||||||
|
|
||||||
def run(self, args, env={}):
|
GLib.timeout_add(
|
||||||
|
250,
|
||||||
|
self.run_thread,
|
||||||
|
args,
|
||||||
|
env,
|
||||||
|
prefix
|
||||||
|
)
|
||||||
|
|
||||||
|
def run(self, args, env={}, prefix=None):
|
||||||
p = subprocess.Popen(
|
p = subprocess.Popen(
|
||||||
args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False,
|
args,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
shell=False,
|
||||||
env=dict(os.environ, **env))
|
env=dict(os.environ, **env))
|
||||||
|
|
||||||
sel = selectors.DefaultSelector()
|
sel = selectors.DefaultSelector()
|
||||||
@ -145,7 +182,10 @@ class UpdateWindow(Gtk.ApplicationWindow):
|
|||||||
|
|
||||||
if data:
|
if data:
|
||||||
if key.fileobj is p.stdout:
|
if key.fileobj is p.stdout:
|
||||||
self.stdout_queue.put(data)
|
if prefix is None:
|
||||||
|
self.stdout_queue.put(data)
|
||||||
|
else:
|
||||||
|
self.stdout_queue.put(prefix + " " + data)
|
||||||
else:
|
else:
|
||||||
self.stderr_queue.put(data)
|
self.stderr_queue.put(data)
|
||||||
|
|
||||||
@ -176,16 +216,15 @@ class UpdateWindow(Gtk.ApplicationWindow):
|
|||||||
env=env,
|
env=env,
|
||||||
empty_msg="No package upgrades were performed.")
|
empty_msg="No package upgrades were performed.")
|
||||||
|
|
||||||
def on_upgrade(self, *args):
|
|
||||||
self.upgrade()
|
|
||||||
|
|
||||||
def update(self, clear=True):
|
def update(self, clear=True):
|
||||||
args = ['/usr/bin/apt-get', '-y', 'update']
|
args = ['/usr/bin/apt-get', '-y', 'update']
|
||||||
env = {'DEBIAN_FRONTEND': 'noninteractive'}
|
env = {'DEBIAN_FRONTEND': 'noninteractive'}
|
||||||
self.execute(args, env=env, clear=clear)
|
self.execute(
|
||||||
|
args,
|
||||||
def on_update(self, *args):
|
env=env,
|
||||||
self.update()
|
clear=clear,
|
||||||
|
output_msg="The package cache was refreshed."
|
||||||
|
)
|
||||||
|
|
||||||
def list(self, clear=True):
|
def list(self, clear=True):
|
||||||
args = ['/usr/bin/apt', '-qq', 'list', '--upgradable']
|
args = ['/usr/bin/apt', '-qq', 'list', '--upgradable']
|
||||||
@ -193,8 +232,16 @@ class UpdateWindow(Gtk.ApplicationWindow):
|
|||||||
args,
|
args,
|
||||||
ignore_stderr=True,
|
ignore_stderr=True,
|
||||||
clear=clear,
|
clear=clear,
|
||||||
output_msg="Found the following package upgrades:",
|
prefix="UPDATE",
|
||||||
empty_msg="Currently there are no available package upgrades.")
|
output_msg="Done listing available upgrades.",
|
||||||
|
empty_msg="No package upgrades found."
|
||||||
|
)
|
||||||
|
|
||||||
|
def on_update(self, *args):
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def on_upgrade(self, *args):
|
||||||
|
self.upgrade()
|
||||||
|
|
||||||
def on_list(self, *args):
|
def on_list(self, *args):
|
||||||
self.list()
|
self.list()
|
||||||
@ -202,27 +249,39 @@ class UpdateWindow(Gtk.ApplicationWindow):
|
|||||||
def on_quit(self, *args):
|
def on_quit(self, *args):
|
||||||
self.application.quit()
|
self.application.quit()
|
||||||
|
|
||||||
|
def process_exit(self, exit_code, empty_msg=None, output_msg=None):
|
||||||
|
self.thread.join()
|
||||||
|
|
||||||
|
if exit_code != 0:
|
||||||
|
self.append_mesg(
|
||||||
|
"ERROR",
|
||||||
|
"Command exited with code %d" % exit_code
|
||||||
|
)
|
||||||
|
elif self.stdout == '' and self.empty_msg is not None:
|
||||||
|
self.append_mesg("INFO", self.empty_msg)
|
||||||
|
elif self.stdout != '' and self.output_msg is not None:
|
||||||
|
self.append_mesg("INFO", self.output_msg)
|
||||||
|
|
||||||
|
self.unlock()
|
||||||
|
|
||||||
def update_buffer(self):
|
def update_buffer(self):
|
||||||
try:
|
try:
|
||||||
text = self.stdout_queue.get(block=False)
|
text = self.stdout_queue.get(block=False)
|
||||||
match = re.fullmatch(r'EXIT (\d+)', text)
|
match = re.fullmatch(r'(EXIT|UPDATE) (.*)', text)
|
||||||
|
|
||||||
if match is None:
|
if match is None:
|
||||||
self.stdout += text
|
self.stdout += text
|
||||||
self.append_mesg("STDOUT", text)
|
self.append_mesg("STDOUT", text)
|
||||||
|
elif match.group(1) == 'EXIT':
|
||||||
|
exit_code = int(match.group(2))
|
||||||
|
self.process_exit(exit_code)
|
||||||
|
elif match.group(1) == 'UPDATE':
|
||||||
|
text = match.group(2)
|
||||||
|
self.stdout += text
|
||||||
|
self.append_mesg("UPDATE", text)
|
||||||
else:
|
else:
|
||||||
exit_code = int(match.group(1))
|
self.stdout += text
|
||||||
|
self.append_mesg("UPDATE", text)
|
||||||
if exit_code != 0:
|
|
||||||
self.append_mesg(
|
|
||||||
"ERROR",
|
|
||||||
"Command exited with code %d" % exit_code)
|
|
||||||
elif self.stdout == '' and self.empty_msg is not None:
|
|
||||||
self.append_mesg("INFO", self.empty_msg)
|
|
||||||
elif self.stdout != '' and self.output_msg is not None:
|
|
||||||
self.append_mesg("INFO", self.empty_msg)
|
|
||||||
|
|
||||||
self.unlock()
|
|
||||||
|
|
||||||
except queue.Empty:
|
except queue.Empty:
|
||||||
pass
|
pass
|
||||||
@ -240,20 +299,31 @@ class UpdateWindow(Gtk.ApplicationWindow):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def __init__(self, application):
|
def __init__(self, application):
|
||||||
super(UpdateWindow, self).__init__(
|
super(
|
||||||
|
UpdateWindow,
|
||||||
|
self
|
||||||
|
).__init__(
|
||||||
application=application,
|
application=application,
|
||||||
title="Simple APT Update")
|
title="Simple APT Update"
|
||||||
|
)
|
||||||
|
|
||||||
self.application = application
|
self.application = application
|
||||||
|
self.thread = None
|
||||||
self.stdout_queue = queue.Queue()
|
self.stdout_queue = queue.Queue()
|
||||||
self.stderr_queue = queue.Queue()
|
self.stderr_queue = queue.Queue()
|
||||||
GLib.timeout_add(100, self.update_buffer)
|
|
||||||
self.init_ui()
|
self.init_ui()
|
||||||
|
|
||||||
|
GLib.timeout_add(100, self.update_buffer)
|
||||||
|
|
||||||
def init_ui(self):
|
def init_ui(self):
|
||||||
self.set_border_width(10)
|
self.set_border_width(10)
|
||||||
self.set_default_size(630, 390)
|
self.set_default_size(630, 390)
|
||||||
|
|
||||||
hbox = Gtk.Box(spacing=6, orientation=Gtk.Orientation.VERTICAL)
|
hbox = Gtk.Box(
|
||||||
|
spacing=6,
|
||||||
|
orientation=Gtk.Orientation.VERTICAL
|
||||||
|
)
|
||||||
self.add(hbox)
|
self.add(hbox)
|
||||||
|
|
||||||
grid = Gtk.Grid()
|
grid = Gtk.Grid()
|
||||||
@ -272,9 +342,12 @@ class UpdateWindow(Gtk.ApplicationWindow):
|
|||||||
grid.attach(self.list_button, 1, 0, 1, 1)
|
grid.attach(self.list_button, 1, 0, 1, 1)
|
||||||
|
|
||||||
self.upgrade_button = Gtk.Button.new_from_icon_name(
|
self.upgrade_button = Gtk.Button.new_from_icon_name(
|
||||||
"gtk-apply", Gtk.IconSize.BUTTON)
|
"gtk-apply",
|
||||||
|
Gtk.IconSize.BUTTON
|
||||||
|
)
|
||||||
self.upgrade_button.set_tooltip_text(
|
self.upgrade_button.set_tooltip_text(
|
||||||
"Download and install all available upgrades")
|
"Download and install all available upgrades"
|
||||||
|
)
|
||||||
self.upgrade_button.connect("clicked", self.on_upgrade)
|
self.upgrade_button.connect("clicked", self.on_upgrade)
|
||||||
grid.attach(self.upgrade_button, 2, 0, 1, 1)
|
grid.attach(self.upgrade_button, 2, 0, 1, 1)
|
||||||
|
|
||||||
@ -283,7 +356,9 @@ class UpdateWindow(Gtk.ApplicationWindow):
|
|||||||
grid.attach(self.spinner, 3, 0, 1, 1)
|
grid.attach(self.spinner, 3, 0, 1, 1)
|
||||||
|
|
||||||
self.quit_button = Gtk.Button.new_from_icon_name(
|
self.quit_button = Gtk.Button.new_from_icon_name(
|
||||||
"exit", Gtk.IconSize.BUTTON)
|
"exit",
|
||||||
|
Gtk.IconSize.BUTTON
|
||||||
|
)
|
||||||
self.quit_button.set_tooltip_text("Exit the program")
|
self.quit_button.set_tooltip_text("Exit the program")
|
||||||
self.quit_button.set_halign(Gtk.Align.END)
|
self.quit_button.set_halign(Gtk.Align.END)
|
||||||
self.quit_button.connect("clicked", self.on_quit)
|
self.quit_button.connect("clicked", self.on_quit)
|
||||||
@ -296,24 +371,32 @@ class UpdateWindow(Gtk.ApplicationWindow):
|
|||||||
self.scrolledwindow.set_max_content_height(300)
|
self.scrolledwindow.set_max_content_height(300)
|
||||||
self.buffer = Gtk.TextBuffer()
|
self.buffer = Gtk.TextBuffer()
|
||||||
|
|
||||||
text_view = Gtk.TextView(buffer=self.buffer)
|
self.text_view = Gtk.TextView(buffer=self.buffer)
|
||||||
text_view.set_editable(False)
|
self.text_view.set_editable(False)
|
||||||
text_view.set_monospace(True)
|
self.text_view.set_monospace(True)
|
||||||
text_view.set_cursor_visible(False)
|
self.text_view.set_cursor_visible(False)
|
||||||
|
|
||||||
self.scrolledwindow.add(text_view)
|
text_buffer = self.text_view.get_buffer()
|
||||||
|
iter = text_buffer.get_end_iter()
|
||||||
|
self.text_mark_end = text_buffer.create_mark("", iter, False)
|
||||||
|
|
||||||
|
self.scrolledwindow.add(self.text_view)
|
||||||
hbox.pack_start(self.scrolledwindow, True, True, 0)
|
hbox.pack_start(self.scrolledwindow, True, True, 0)
|
||||||
|
|
||||||
|
|
||||||
class SimpleAptUpdate(Gtk.Application):
|
class SimpleAptUpdate(Gtk.Application):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__(application_id='de.linuxfoo.SimpleAptUpdate',
|
super(
|
||||||
flags=Gio.ApplicationFlags.FLAGS_NONE)
|
SimpleAptUpdate,
|
||||||
self.connect('activate', self.on_activate)
|
self
|
||||||
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
).__init__(
|
||||||
|
application_id='de.linuxfoo.SimpleAptUpdate',
|
||||||
|
flags=Gio.ApplicationFlags.FLAGS_NONE
|
||||||
|
)
|
||||||
|
|
||||||
def do_command_line(self, cmdline):
|
self.connect('activate', self.on_activate)
|
||||||
pass
|
|
||||||
|
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
||||||
|
|
||||||
def on_activate(self, application):
|
def on_activate(self, application):
|
||||||
self.window = UpdateWindow(application)
|
self.window = UpdateWindow(application)
|
||||||
@ -321,7 +404,10 @@ class SimpleAptUpdate(Gtk.Application):
|
|||||||
action = Gio.SimpleAction.new("quit", None)
|
action = Gio.SimpleAction.new("quit", None)
|
||||||
action.connect("activate", self.window.on_quit)
|
action.connect("activate", self.window.on_quit)
|
||||||
self.add_action(action)
|
self.add_action(action)
|
||||||
self.set_accels_for_action('app.quit', ['<Primary>q', '<Primary>w'])
|
self.set_accels_for_action(
|
||||||
|
'app.quit',
|
||||||
|
['<Primary>q', '<Primary>w']
|
||||||
|
)
|
||||||
|
|
||||||
action = Gio.SimpleAction.new("update", None)
|
action = Gio.SimpleAction.new("update", None)
|
||||||
action.connect("activate", self.window.on_update)
|
action.connect("activate", self.window.on_update)
|
||||||
@ -340,7 +426,6 @@ class SimpleAptUpdate(Gtk.Application):
|
|||||||
|
|
||||||
self.window.present()
|
self.window.present()
|
||||||
self.window.show_all()
|
self.window.show_all()
|
||||||
self.window.update()
|
|
||||||
self.window.list(clear=False)
|
self.window.list(clear=False)
|
||||||
|
|
||||||
|
|
||||||
@ -355,3 +440,5 @@ def main():
|
|||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
# vim:fenc=utf-8:et:ts=4:sw=4
|
||||||
|
BIN
doc/screenshot.png
Normal file
BIN
doc/screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 33 KiB |
@ -7,19 +7,14 @@
|
|||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="31.72216mm"
|
width="31.72216mm"
|
||||||
height="36.307823mm"
|
height="36.307823mm"
|
||||||
viewBox="0 0 31.72216 36.307823"
|
viewBox="0 0 31.72216 36.307823"
|
||||||
version="1.1"
|
version="1.1"
|
||||||
id="svg8"
|
id="svg8">
|
||||||
inkscape:version="1.0.2 (e86c870879, 2021-01-15)"
|
|
||||||
sodipodi:docname="simple-apt-update.svg">
|
|
||||||
<defs
|
<defs
|
||||||
id="defs2">
|
id="defs2">
|
||||||
<linearGradient
|
<linearGradient
|
||||||
inkscape:collect="always"
|
|
||||||
id="linearGradient4117">
|
id="linearGradient4117">
|
||||||
<stop
|
<stop
|
||||||
style="stop-color:#000000;stop-opacity:1;"
|
style="stop-color:#000000;stop-opacity:1;"
|
||||||
@ -55,7 +50,6 @@
|
|||||||
id="stop4093" />
|
id="stop4093" />
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
<linearGradient
|
<linearGradient
|
||||||
inkscape:collect="always"
|
|
||||||
id="linearGradient1878"
|
id="linearGradient1878"
|
||||||
osb:paint="gradient">
|
osb:paint="gradient">
|
||||||
<stop
|
<stop
|
||||||
@ -72,24 +66,14 @@
|
|||||||
id="Arrow2Lend"
|
id="Arrow2Lend"
|
||||||
refX="0"
|
refX="0"
|
||||||
refY="0"
|
refY="0"
|
||||||
orient="auto"
|
orient="auto">
|
||||||
inkscape:stockid="Arrow2Lend"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
<path
|
||||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
||||||
id="path892" />
|
id="path892" />
|
||||||
</marker>
|
</marker>
|
||||||
<inkscape:perspective
|
|
||||||
sodipodi:type="inkscape:persp3d"
|
|
||||||
inkscape:vp_x="177.41502 : 38.534923 : 1"
|
|
||||||
inkscape:vp_y="57.01026 : -606.09557 : 0"
|
|
||||||
inkscape:vp_z="-849.50931 : -58.059119 : 1"
|
|
||||||
inkscape:persp3d-origin="-338.86915 : 20.239614 : 1"
|
|
||||||
id="perspective833" />
|
|
||||||
<linearGradient
|
<linearGradient
|
||||||
inkscape:collect="always"
|
|
||||||
xlink:href="#linearGradient4095"
|
xlink:href="#linearGradient4095"
|
||||||
id="linearGradient4087"
|
id="linearGradient4087"
|
||||||
x1="41.938935"
|
x1="41.938935"
|
||||||
@ -98,7 +82,6 @@
|
|||||||
y2="60.562257"
|
y2="60.562257"
|
||||||
gradientUnits="userSpaceOnUse" />
|
gradientUnits="userSpaceOnUse" />
|
||||||
<linearGradient
|
<linearGradient
|
||||||
inkscape:collect="always"
|
|
||||||
xlink:href="#linearGradient4095"
|
xlink:href="#linearGradient4095"
|
||||||
id="linearGradient4089"
|
id="linearGradient4089"
|
||||||
x1="22.932867"
|
x1="22.932867"
|
||||||
@ -107,7 +90,6 @@
|
|||||||
y2="48.843493"
|
y2="48.843493"
|
||||||
gradientUnits="userSpaceOnUse" />
|
gradientUnits="userSpaceOnUse" />
|
||||||
<linearGradient
|
<linearGradient
|
||||||
inkscape:collect="always"
|
|
||||||
xlink:href="#linearGradient4095"
|
xlink:href="#linearGradient4095"
|
||||||
id="linearGradient4097"
|
id="linearGradient4097"
|
||||||
gradientUnits="userSpaceOnUse"
|
gradientUnits="userSpaceOnUse"
|
||||||
@ -116,7 +98,6 @@
|
|||||||
x2="51.607597"
|
x2="51.607597"
|
||||||
y2="48.390368" />
|
y2="48.390368" />
|
||||||
<linearGradient
|
<linearGradient
|
||||||
inkscape:collect="always"
|
|
||||||
xlink:href="#linearGradient4117"
|
xlink:href="#linearGradient4117"
|
||||||
id="linearGradient4121"
|
id="linearGradient4121"
|
||||||
x1="22.932867"
|
x1="22.932867"
|
||||||
@ -125,7 +106,6 @@
|
|||||||
y2="48.843493"
|
y2="48.843493"
|
||||||
gradientUnits="userSpaceOnUse" />
|
gradientUnits="userSpaceOnUse" />
|
||||||
<linearGradient
|
<linearGradient
|
||||||
inkscape:collect="always"
|
|
||||||
xlink:href="#linearGradient4117"
|
xlink:href="#linearGradient4117"
|
||||||
id="linearGradient4123"
|
id="linearGradient4123"
|
||||||
x1="19.885436"
|
x1="19.885436"
|
||||||
@ -134,29 +114,6 @@
|
|||||||
y2="48.390368"
|
y2="48.390368"
|
||||||
gradientUnits="userSpaceOnUse" />
|
gradientUnits="userSpaceOnUse" />
|
||||||
</defs>
|
</defs>
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="3.959798"
|
|
||||||
inkscape:cx="81.30198"
|
|
||||||
inkscape:cy="102.74857"
|
|
||||||
inkscape:document-units="mm"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
inkscape:document-rotation="0"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:window-width="1885"
|
|
||||||
inkscape:window-height="1236"
|
|
||||||
inkscape:window-x="2101"
|
|
||||||
inkscape:window-y="111"
|
|
||||||
inkscape:window-maximized="0"
|
|
||||||
fit-margin-top="0"
|
|
||||||
fit-margin-left="0"
|
|
||||||
fit-margin-right="0"
|
|
||||||
fit-margin-bottom="0" />
|
|
||||||
<metadata
|
<metadata
|
||||||
id="metadata5">
|
id="metadata5">
|
||||||
<rdf:RDF>
|
<rdf:RDF>
|
||||||
@ -170,8 +127,6 @@
|
|||||||
</rdf:RDF>
|
</rdf:RDF>
|
||||||
</metadata>
|
</metadata>
|
||||||
<g
|
<g
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
id="layer1"
|
||||||
transform="translate(-19.885436,-34.013894)">
|
transform="translate(-19.885436,-34.013894)">
|
||||||
<rect
|
<rect
|
||||||
@ -181,18 +136,14 @@
|
|||||||
height="27.752951"
|
height="27.752951"
|
||||||
x="20.385435"
|
x="20.385435"
|
||||||
y="34.513893"
|
y="34.513893"
|
||||||
ry="2.9184699"
|
ry="2.9184699" />
|
||||||
inkscape:transform-center-x="13.051673"
|
|
||||||
inkscape:transform-center-y="11.996269" />
|
|
||||||
<path
|
<path
|
||||||
style="fill:url(#linearGradient4121);stroke:url(#linearGradient4089);stroke-width:3.765;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1"
|
style="fill:url(#linearGradient4121);stroke:url(#linearGradient4089);stroke-width:3.765;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1"
|
||||||
d="m 24.815338,34.950563 c 0.145105,26.252732 17.704313,25.913942 17.704313,25.913942"
|
d="m 24.815338,34.950563 c 0.145105,26.252732 17.704313,25.913942 17.704313,25.913942"
|
||||||
id="path1321"
|
id="path1321" />
|
||||||
sodipodi:nodetypes="cc" />
|
|
||||||
<path
|
<path
|
||||||
style="fill:#bebebe;fill-opacity:1;stroke:url(#linearGradient4087);stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
style="fill:#bebebe;fill-opacity:1;stroke:url(#linearGradient4087);stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
d="m 42.10017,59.891406 -0.02493,-8.714785 8.491092,10.446869 -8.494225,8.380984 z"
|
d="m 42.10017,59.891406 -0.02493,-8.714785 8.491092,10.446869 -8.494225,8.380984 z"
|
||||||
id="path1869"
|
id="path1869" />
|
||||||
sodipodi:nodetypes="ccccc" />
|
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 4.6 KiB |
Loading…
Reference in New Issue
Block a user