/usr/share/cyclograph/gtk3/glal.py is in cyclograph-gtk3 1.7.1-1.
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 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 | #!/usr/bin/env python
# -*- coding: utf-8 -*-
#gtk3.glal.py
"""This module provides a graphic library abstraction layer for Cyclograph"""
# Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013 Federico Brega, Pierluigi Villani
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
import math
from gi.repository import Gtk, GObject, Gdk
import cairo
import gui
GObject.threads_init()
def initapp():
return Gtk.main()
def bind(cgfunc, menuopt):
"""Connect gui menu option with cg function"""
return menuopt.connect("activate", cgfunc)
def bind_close(cg_exit, gui):
"""Connect gui close event with cg exit function"""
gui.cg_exit = cg_exit
bind(gui.exit, gui.menu_item_exit)
def ToolbarBind(fun, button):
"""Connect gui toolbar button with cg function"""
return button.connect("clicked", fun)
def OptionCheck(guiopt, option):
"""Set a gui menu option to selected/unselected """
guiopt.set_active(option)
def enable_saving(gui, bool_val):
"""Enable or disable saving options according to bool_val"""
gui.menu_item_save.set_sensitive(bool_val)
gui.menu_item_save_as.set_sensitive(bool_val)
gui.action_add.set_sensitive(bool_val)
gui.action_edit.set_sensitive(bool_val)
gui.action_delete.set_sensitive(bool_val)
gui.action_plot.set_sensitive(bool_val)
gui.action_map.set_sensitive(bool_val)
gui.action_properties.set_sensitive(bool_val)
def addstatusbartext(maingui, text):
"""Add text to main gui status bar"""
maingui.addstatusbartext(text)
maingui.sbtimer.start()
def signalbug(event=None):
"""Open webpage to signal bugs"""
bugUrl = 'http://sourceforge.net/project/memberlist.php?group_id=227295'
#Looks like gtk hasn't any function to launch an external browser,
#the best we can do is use python webbrowser
import webbrowser
webbrowser.open(bugUrl, new=True, autoraise=True)
class Message():
""" Gtk3 message"""
def __init__(self):
class Messenger(GObject.GObject):
__gsignals__ = {
str("UPDATE_TAB"): (GObject.SignalFlags.ACTION, None,
(int, int, )),
str("SLOPE_ADD"): (GObject.SignalFlags.ACTION, None,
(int, int, )),
str("SLOPE_DEL"): (GObject.SignalFlags.ACTION, None,
(int, int, )),
}
self.gobj = Messenger()
def send(self, message, slope_number, row_num):
""" Send message"""
self.gobj.emit(message, slope_number, row_num)
def subscribe(self, function, emitter, message):
""" Subscribe message"""
self.handler = function
emitter.gobj.connect(message, self._reformat_handler_param)
def _reformat_handler_param(self, emitter, arg1, arg2):
self.handler(arg1, arg2)
class Notebook:
"""Gtk3 notebook"""
def __init__(self, notebook, fun_close):
self.notebook = notebook
self.fun_close = fun_close
self.notebook.set_scrollable(True)
def Page(self):
"""Creates page"""
return gui.Page(self.notebook)
def set_page_label(self, page_num, text):
"""Set page label text"""
lab = self.notebook.get_tab_label(self.get_page(page_num))
lab.label.set_text(text)
def add_page(self, page, title):
"""Add page to the notebook"""
box = gui.tab_label(page, title)
page.button_close = box.closebtn
page.button_close.connect("clicked", self.fun_close, page)
self.notebook.append_page(page, box)
self.notebook.show_all()
nbpages = self.notebook.get_n_pages()
self.notebook.set_current_page(nbpages-1)
def remove_page(self, page_num):
"""Remove page from the notebook"""
self.notebook.remove_page(page_num)
def getselpagnum(self):
"""Return current selected page"""
return self.notebook.get_current_page()
def setselpagnum(self, page_num):
"""Set current selected page"""
self.notebook.set_current_page(page_num)
def get_page(self, page_num):
"""Return page at page_num"""
return self.notebook.get_nth_page(page_num)
def get_pagenum(self, argument):
"""Return page_num from page passed as argument"""
return self.notebook.page_num(argument[1])
class DeviceContext():
"""Device Context Gtk3 class wrapper"""
def _convcolor(self, color):
""" Convert color"""
col = color
if isinstance(color, basestring):
if color.startswith("rgb"):
col = [(int(component)<<8)/65535.0 for component in color[4:-1].split(',')]
elif color == "white":
col = [1, 1, 1]
else:
col = [0, 0, 0]
return col
def init_draw_surf(self, widget, width, height):
"""Initialize device context"""
self.size_x = width
self.size_y = height
self.devc = widget
self.FONT_TYP = {
"light" : cairo.FONT_WEIGHT_NORMAL,
"normal" : cairo.FONT_WEIGHT_NORMAL,
"bold" : cairo.FONT_WEIGHT_BOLD,
}
#pen color
self.pcolor = [0, 0, 0]
#brush color
self.bcolor = [0, 0, 0]
def shear(self, shear):
""" device shear"""
matrix = cairo.Matrix(yx = shear)
self.devc.set_matrix(matrix)
def getsize(self):
"""Return device context dimensions"""
return (self.size_x, self.size_y)
def gradfill(self, rect, startcolor, endcolor):
"""Fill context with gradient"""
(startx, starty) = (rect[0], rect[1])
scolor = self._convcolor(startcolor)
ecolor = self._convcolor(endcolor)
lg1 = cairo.LinearGradient(0, 160.0, 0, self.size_y)
lg1.add_color_stop_rgb(0, *scolor)
lg1.add_color_stop_rgb(1, *ecolor)
self.devc.rectangle(startx, starty, self.size_x, self.size_y)
self.devc.set_source(lg1)
self.devc.fill()
def setpen(self, color, size):
"""Set pen color and size"""
self.devc.set_line_width(size)
self.pcolor = self._convcolor(color)
def setfont(self, font):
"""Set font"""
try:
self.devc.select_font_face(font['des'], cairo.FONT_SLANT_NORMAL,
self.FONT_TYP[font['typ']])
self.devc.set_font_size(font['dim'])
except Exception:
pass
def drawtext(self, text, pos_x, pos_y):
"""Draw text"""
self.devc.set_source_rgb(*self.pcolor)
self.devc.move_to(pos_x, pos_y+12)
self.devc.show_text(text)
def gettextwidth(self, text):
""" Return text length"""
return int(self.devc.text_extents(text)[2])
def gettextheight(self, text):
""" Return text height"""
return int(self.devc.text_extents(text)[3])
def drawline(self, pos_x0, pos_y0, pos_x1, pos_y1):
"""Draw line"""
self.devc.set_source_rgb(*self.pcolor)
self.devc.move_to(pos_x0, pos_y0)
self.devc.line_to(pos_x1, pos_y1)
self.devc.stroke()
def setlineargradientbrush(self, colorlist, startp, endp):
""" Get a linear gradient from startp to endp, using colors in colorlist.
The elments of colorlist are tuple in the format (color, realtive position)."""
grad = cairo.LinearGradient(startp[0], startp[1], endp[0], endp[1])
for color in colorlist:
grad.add_color_stop_rgb(color[1], *self._convcolor(color[0]))
self.pattern = grad
def setbrush(self, color):
"""Set brush color"""
self.pattern = cairo.SolidPattern(*self._convcolor(color))
def drawrectangle(self, pos_x0, pos_y0, width, height):
"""Draw rectangle"""
self.devc.set_source_rgb(0, 0, 0)
self.devc.rectangle(pos_x0, pos_y0, width, height)
self.devc.stroke_preserve()
self.devc.set_source(self.pattern)
self.devc.fill()
def drawrotatedtext(self, text, pos_x, pos_y, angle):
"""Draw rotated text"""
self.devc.save()
self.devc.translate(pos_x, pos_y)
self.devc.rotate(-math.radians(angle))
self.drawtext(text, 0, 0)
self.devc.restore()
def drawpolygon(self, sequence):
"""Draw polygon"""
self.devc.set_source_rgb(0, 0, 0)
self.devc.move_to(*sequence[0])
for point in sequence:
self.devc.line_to(*point)
self.devc.close_path()
self.devc.stroke_preserve()
self.devc.set_source(self.pattern)
self.devc.fill()
def startpath(self, point):
""" Start a path in the specified point,"""
(pointx, pointy) = point
self.devc.set_source_rgb(0, 0, 0)
self.devc.move_to(pointx, pointy)
return None
def drawpathlineto(self, path, point):
""" Draw a straight line from the last point to the given point."""
(pointx, pointy) = point
self.devc.line_to(pointx, pointy)
def drawpathcubicto(self, path, controlpoints):
""" Draw a cubic BeziƩr from the last point using the given list of
three control points."""
points = []
for pnt in controlpoints:
points.append(pnt[0])
points.append(pnt[1])
self.devc.curve_to(*points)
def endpath(self, path):
""" Show the path."""
self.devc.set_source_rgb(0, 0, 0)
self.devc.stroke_preserve()
self.devc.set_source(self.pattern)
self.devc.fill()
def end_draw(self):
"""End drawing not used for gtk gui"""
pass
class Image():
"""Gtk3 image class wrapper"""
def __init__(self, size_x, size_y, plotfnct):
(self.size_x, self.size_y) = (size_x, size_y)
self.plotfnct = plotfnct
self.image = cairo.ImageSurface(cairo.FORMAT_RGB24,
self.size_x, self.size_y)
def plot(self, settings):
"""Plot image"""
dcwrpp = DeviceContext()
dcwrpp.init_draw_surf(cairo.Context(self.image),
self.size_x, self.size_y)
self.plotfnct(settings, dcwrpp)
def savetofile(self, path, format):
"""Save slope to image"""
if format.lower() == 'png':
self.image.write_to_png(path)
if format.lower() == 'bmp':
width, height = self.image.get_width(), self.image.get_height()
pixbuf = Gdk.pixbuf_get_from_surface(self.image, 0, 0, width, height)
pixbuf.savev(path, "bmp", [], [])
if format.lower() == 'jpg':
width, height = self.image.get_width(), self.image.get_height()
pixbuf = Gdk.pixbuf_get_from_surface(self.image, 0, 0, width, height)
pixbuf.savev(path, "jpeg", ["quality"], ["100"])
class Pdf():
"""Gtk3 pdf class wrapper"""
def __init__(self, filepath):
width, height = 793, 1122
self.dy = 90
self.dx = 300
self.y_incr = 30
self.surface = cairo.PDFSurface(filepath, width, height)
self.context = cairo.Context(self.surface)
# white background
self.context.set_source_rgb(1, 1, 1)
self.context.rectangle(0, 0, width, height)
self.context.fill()
self.context.select_font_face("Arial")
self.context.set_font_size(18)
def plot_image(self, settings, size_x, size_y, plotfnct):
"""Plot image"""
image = cairo.SVGSurface(None, size_x, size_y)
dcwrpp = DeviceContext()
dcwrpp.init_draw_surf(cairo.Context(image), size_x, size_y)
plotfnct(settings, dcwrpp)
self.context.set_source_surface(image, 0, 0)
self.context.paint()
self.dy += size_y
def addtext(self, text):
self.dy += self.y_incr
self.context.set_source_rgb(0, 0, 0)
self.context.move_to(self.dx, self.dy)
self.context.show_text(text)
def addtitle(self, text):
self.dy += self.y_incr
self.context.set_source_rgb(0, 0, 0.4)
self.context.move_to(self.dx-50, self.dy)
self.context.show_text(text+":")
def save(self):
"""Save slope to pdf"""
self.context.show_page()
self.surface.finish()
class ProgressDialog():
"""Gtk3 Progress dialog"""
def __init__(self):
self.pdialog = gui.ProgressDialog(_("Downloading altitudes"),
_("Please wait, Cycograph is downloading altitudes."), 1000.0)
def update(self, value):
"""Update the progress shown and return if user want to abort."""
return self.pdialog.update(value)
def destroy(self):
"""Destroy dialog"""
self.pdialog.destroy()
class Timer():
"""Gtk3 timer"""
def __init__(self, period, callback):
self.timer = 0
self.callback = callback
self.period = period
def start(self):
"""Start timer"""
self.timer = GObject.timeout_add(self.period, self.callback)
def stop(self):
"""Stop timer"""
GObject.source_remove(self.timer)
self.timer = 0
# vim:sw=4:softtabstop=4:expandtab
|