diff options
author | Daniel Francis <francis@sugarlabs.org> | 2013-01-03 12:05:48 (GMT) |
---|---|---|
committer | Daniel Francis <francis@sugarlabs.org> | 2013-01-03 12:05:48 (GMT) |
commit | 617dc31a24435bb44df4f019d14a4d3df04e5b76 (patch) | |
tree | bb2626f7519f725941d090bb54ef28734c72dcea | |
parent | 578e555f7fee57bb941b88ac0bc39c7262ac8dd2 (diff) |
Port to Gtk3 allowing to run a Gtk2 version on old systems
Signed-off-by: Daniel Francis <francis@sugarlabs.org>
-rw-r--r-- | activity.py | 52 | ||||
-rw-r--r-- | activitygtk2.py | 71 | ||||
-rw-r--r-- | activitygtk3.py | 81 | ||||
-rw-r--r--[-rwxr-xr-x] | application.py | 230 | ||||
-rwxr-xr-x | applicationgtk2.py | 258 | ||||
-rwxr-xr-x | applicationgtk3.py | 291 | ||||
-rw-r--r-- | desktop/sweetener.py | 30 | ||||
m--------- | desktop/sweetenergtk2 | 0 | ||||
m--------- | desktop/sweetenergtk3 | 0 | ||||
-rw-r--r-- | gtk2modules/canvas.py (copied from canvas.py) | 9 | ||||
-rw-r--r-- | gtk2modules/functions.py (copied from functions.py) | 13 | ||||
-rw-r--r-- | gtk2modules/graph.py (copied from graph.py) | 0 | ||||
-rw-r--r-- | gtk2modules/options.py (copied from options.py) | 75 | ||||
-rw-r--r-- | gtk3modules/canvas.py (renamed from canvas.py) | 37 | ||||
-rw-r--r-- | gtk3modules/functions.py (renamed from functions.py) | 55 | ||||
-rw-r--r-- | gtk3modules/graph.py (renamed from graph.py) | 99 | ||||
-rw-r--r-- | gtk3modules/options.py (renamed from options.py) | 197 | ||||
-rw-r--r-- | info.py | 10 | ||||
-rwxr-xr-x | setup.py | 2 | ||||
-rw-r--r-- | style.css | 21 | ||||
-rw-r--r-- | sugar/sweetener.py | 29 | ||||
m--------- | sugar/sweetenergtk2 | 0 | ||||
m--------- | sugar/sweetenergtk3 | 0 |
23 files changed, 1042 insertions, 518 deletions
diff --git a/activity.py b/activity.py index 032f223..d1be2f2 100644 --- a/activity.py +++ b/activity.py @@ -15,20 +15,10 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. -import tempfile +import sys import os os.environ['PROGRAMRUNNING'] = 'SUGAR' os.environ['INFO_L10N'] = '1' -import logging -logging.basicConfig(level=logging.DEBUG) -import info -logger = logging.getLogger(info.lower_name) -from gettext import gettext as _ - -import gtk - -from sugar.datastore import datastore -from sugar.activity import activity try: import sweetener @@ -37,40 +27,8 @@ except ImportError: sys.path.append(os.path.abspath('./sugar')) import sweetener -os.environ['DATA_DIR'] = os.path.abspath('./data') - -from options import Options -from canvas import Canvas - - -class Activity(activity.Activity): - def __init__(self, handle): - activity.Activity.__init__(self, handle) - self.options = Options(self) - self.options.show() - self.set_toolbar_box(self.options) - self.canvas = Canvas(self.options, self) - self.canvas.show() - self.set_canvas(self.canvas) - self.canvas.new() - - def export(self, widget, data): - jobject = datastore.create() - jobject.metadata['title'] = self.metadata['title'] - mime_type = data[1] - jobject.metadata['mime_type'] = mime_type - file_path = tempfile.mktemp() - self.canvas.exports[mime_type](file_path) - jobject.set_file_path(file_path) - datastore.write(jobject) - - def read_file(self, path): - return self.canvas.read_file(path) - - def write_file(self, path): - return self.canvas.write_file(path) +if sweetener.GTK == 2: + from activitygtk2 import Activity - def unfullscreen(self): - # The following line is an adition for Graph Plotter - self.canvas._resize_queue = self.canvas.previous_size - activity.Activity.unfullscreen(self) +else: + from activitygtk3 import Activity diff --git a/activitygtk2.py b/activitygtk2.py new file mode 100644 index 0000000..3a1eeee --- /dev/null +++ b/activitygtk2.py @@ -0,0 +1,71 @@ +# Copyright (C) 2012 S. Daniel Francis <francis@sugarlabs.org> +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. + +import tempfile +import os +import sys +sys.path.append(os.path.abspath('./gtk2modules')) +sys.path.append(os.path.abspath('./sweetenergtk2')) + +import logging +logging.basicConfig(level=logging.DEBUG) +import info +logger = logging.getLogger(info.lower_name) +from gettext import gettext as _ + +import gtk + +from sugar.datastore import datastore +from sugar.activity import activity + +os.environ['DATA_DIR'] = os.path.abspath('./data') + +from options import Options +from canvas import Canvas + + +class Activity(activity.Activity): + def __init__(self, handle): + activity.Activity.__init__(self, handle) + self.options = Options(self) + self.options.show() + self.set_toolbar_box(self.options) + self.canvas = Canvas(self.options, self) + self.canvas.show() + self.set_canvas(self.canvas) + self.canvas.new() + + def export(self, widget, data): + jobject = datastore.create() + jobject.metadata['title'] = self.metadata['title'] + mime_type = data[1] + jobject.metadata['mime_type'] = mime_type + file_path = tempfile.mktemp() + self.canvas.exports[mime_type](file_path) + jobject.set_file_path(file_path) + datastore.write(jobject) + + def read_file(self, path): + return self.canvas.read_file(path) + + def write_file(self, path): + return self.canvas.write_file(path) + + def unfullscreen(self): + # The following line is an adition for Graph Plotter + self.canvas._resize_queue = self.canvas.previous_size + activity.Activity.unfullscreen(self) diff --git a/activitygtk3.py b/activitygtk3.py new file mode 100644 index 0000000..cf4dfe9 --- /dev/null +++ b/activitygtk3.py @@ -0,0 +1,81 @@ +# Copyright (C) 2012 S. Daniel Francis <francis@sugarlabs.org> +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. + +import tempfile +import sys +import os +sys.path.append(os.path.abspath('./gtk3modules')) +sys.path.append(os.path.abspath('./sweetenergtk3')) + +import logging +logging.basicConfig(level=logging.DEBUG) +import info +logger = logging.getLogger(info.lower_name) +from gettext import gettext as _ + +from gi.repository import Gtk +from gi.repository import Gdk + +screen = Gdk.Screen.get_default() +cssprovider = Gtk.CssProvider.get_default() +cssprovider.load_from_path(os.path.join(os.environ['SUGAR_BUNDLE_PATH'], 'style.css')) +context = Gtk.StyleContext() +context.add_provider_for_screen( + screen, + cssprovider, + Gtk.STYLE_PROVIDER_PRIORITY_USER) + +from sugar3.datastore import datastore +from sugar3.activity import activity + +os.environ['DATA_DIR'] = os.path.abspath('./data') + +from options import Options +from canvas import Canvas + + +class Activity(activity.Activity): + def __init__(self, handle): + activity.Activity.__init__(self, handle) + self.options = Options(self) + self.options.show() + self.set_toolbar_box(self.options) + self.canvas = Canvas(self.options, self) + self.canvas.show() + self.set_canvas(self.canvas) + self.canvas.new() + + def export(self, widget, data): + jobject = datastore.create() + jobject.metadata['title'] = self.metadata['title'] + mime_type = data[1] + jobject.metadata['mime_type'] = mime_type + file_path = tempfile.mktemp() + self.canvas.exports[mime_type](file_path) + jobject.set_file_path(file_path) + datastore.write(jobject) + + def read_file(self, path): + return self.canvas.read_file(path) + + def write_file(self, path): + return self.canvas.write_file(path) + + def unfullscreen(self): + # The following line is an adition for Graph Plotter + self.canvas._resize_queue = self.canvas.previous_size + activity.Activity.unfullscreen(self) diff --git a/application.py b/application.py index 7d3faf0..af221ba 100755..100644 --- a/application.py +++ b/application.py @@ -18,8 +18,6 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. -# This file is modified for Graph Plotter - import os import logging logging.basicConfig(level=logging.DEBUG) @@ -27,230 +25,13 @@ import glib import info logger = logging.getLogger(info.lower_name) appname = info.name -# Some desktops like Gnome3-Shell show the Glib Prgname -glib.set_prgname(appname) -glib.set_application_name(appname) -import gtk -from options import Options -from canvas import Canvas -try: - from sweetener.alerts import Alert -except: - pass +import sweetener -this_dir = os.path.split('__file__')[:-1] -if len(this_dir) == 1 and this_dir[0] == '': - this_dir = os.path.abspath('./') +if sweetener.GTK == 2: + from applicationgtk2 import Application else: - this_dir = os.path.join(this_dir) -os.chdir(this_dir) - -from gettext import gettext as _ - -if 'programabspath' in os.environ['DATADIR']: - datadir = os.environ['DATADIR'].replace('programabspath', - this_dir) -else: - datadir = os.environ['DATADIR'] - -if os.environ['ICONDIR'] != 'SYSTEM': - logger.debug(this_dir) - icondir = os.environ['ICONDIR'].replace('programabspath', - this_dir) - icon_theme = gtk.icon_theme_get_for_screen(gtk.gdk.screen_get_default()) - icon_theme.append_search_path(icondir) - - -class UnfullscreenButton(gtk.Window): - - def __init__(self): - gtk.Window.__init__(self) - - self.set_decorated(False) - self.set_resizable(False) - self.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) - - self.set_border_width(0) - - self.props.accept_focus = False - - #Setup estimate of width, height - w, h = gtk.icon_size_lookup(gtk.ICON_SIZE_LARGE_TOOLBAR) - self._width = w - self._height = h - - self.connect('size-request', self._size_request_cb) - - screen = self.get_screen() - screen.connect('size-changed', self._screen_size_changed_cb) - - self._button = gtk.Button(stock=gtk.STOCK_LEAVE_FULLSCREEN) - self._button.set_relief(gtk.RELIEF_NONE) - self._button.show() - self.add(self._button) - - def connect_button_press(self, cb): - self._button.connect('button-press-event', cb) - - def _reposition(self): - x = gtk.gdk.screen_width() - self._width - self.move(x, 0) - - def _size_request_cb(self, widget, req): - self._width = req.width - self._height = req.height - self._reposition() - - def _screen_size_changed_cb(self, screen): - self._reposition() - - -class Application(gtk.Window): - def __init__(self): - gtk.Window.__init__(self) - self.save_type = info.io_mode - self.started = False - self.file_path = None - if info.file_filter_name: - self.filter = gtk.FileFilter() - self.filter.set_name(info.file_filter_name) - if info.file_filter_mime: - self.filter.add_mime_type(info.file_filter_mime) - for i in info.file_filter_patterns: - self.filter.add_pattern(i) - self.accel_group = gtk.AccelGroup() - self.add_accel_group(self.accel_group) - self.set_title(appname) - logger.debug(info.lower_name) - self.set_icon(gtk.gdk.pixbuf_new_from_file(os.path.join(datadir, - 'appicon.svg'))) - self.connect('delete-event', lambda w, e: self.stop()) - self.maximize() - self._vbox = gtk.VBox() - self.options = Options(self) - self.options.show() - self._vbox.pack_start(self.options, False, True, 0) - self.canvas = Canvas(self.options, self) - self.canvas.show() - self._vbox.pack_start(self.canvas, True, True, 0) - self.add(self._vbox) - self._vbox.show() - - self._is_fullscreen = False - self.set_events(gtk.gdk.ALL_EVENTS_MASK) - self.connect('motion-notify-event', self.motion_cb) - self.canvas.connect('expose-event', self.expose_event) - - def expose_event(self, widget, event): - #logger.debug('Exposing') - if not self.started: - if self.file_path is not None: - self.canvas.read_file(self.file_path) - self.set_title(os.path.abspath('%s - %s' % (self.file_path, - appname))) - else: - self.new() - self.started = True - - def motion_cb(self, widget, event): - if self._is_fullscreen: - x, y, state = self.get_window().get_pointer() - width, height = self.get_size() - button_width, button_height = self._unfullscreen_button.get_size() - if x >= width - button_width or y <= button_height: - self._unfullscreen_button.show() - else: - self._unfullscreen_button.hide() - - def add_alert(self, alert): - alert.run() - - def fullscreen(self): - self.options.hide() - self._is_fullscreen = True - self._unfullscreen_button = UnfullscreenButton() - self._unfullscreen_button.set_transient_for(self) - self._unfullscreen_button.connect_button_press( - lambda w, e: self.unfullscreen()) - self._unfullscreen_button.show() - gtk.Window.fullscreen(self) - - def unfullscreen(self): - self.options.show() - self._is_fullscreen = False - self._unfullscreen_button.destroy() - # The following line is an adition for Graph Plotter - self.canvas._resize_queue = self.canvas.previous_size - # Part of the sweetener code - gtk.Window.unfullscreen(self) - - def export(self, widget, data): - format_name = data[3] - filter_mime = data[2] - mime_type = data[1] - filechooser = gtk.FileChooserDialog(_("Export..."), self, - gtk.FILE_CHOOSER_ACTION_SAVE, - (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, - gtk.STOCK_OK, gtk.RESPONSE_OK)) - file_filter = gtk.FileFilter() - file_filter.set_name(format_name) - file_filter.add_mime_type(filter_mime) - filechooser.add_filter(file_filter) - filechooser.set_do_overwrite_confirmation(True) - filechooser.run() - file_path = filechooser.get_filename() - filechooser.destroy() - self.canvas.exports[mime_type](file_path) - - def new(self): - self.file_path = None - self.canvas.new() - self.set_title(appname) - - def stop(self): - if info.io_mode == info.CONFIG: - self.file_path = os.path.join(os.environ['HOME'], - '.' + info.lower_name) - self.save() - gtk.main_quit() - - def open(self): - filechooser = gtk.FileChooserDialog(_('Open...'), self, - gtk.FILE_CHOOSER_ACTION_OPEN, - (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, - gtk.STOCK_OPEN, gtk.RESPONSE_OK)) - filechooser.add_filter(self.filter) - response = filechooser.run() - self.file_path = filechooser.get_filename() - filechooser.destroy() - if response == gtk.RESPONSE_OK: - logger.debug('Read file %s' % self.file_path) - self.canvas.read_file(self.file_path) - self.set_title('%s - %s' % (self.file_path, appname)) - - def save(self): - if self.file_path is None: - self.save_as() - else: - logger.debug('Write file %s' % self.file_path) - self.canvas.write_file(self.file_path) - - def save_as(self): - filechooser = gtk.FileChooserDialog(_('Save...'), self, - gtk.FILE_CHOOSER_ACTION_SAVE, - (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, - gtk.STOCK_OK, gtk.RESPONSE_OK)) - filechooser.add_filter(self.filter) - filechooser.set_do_overwrite_confirmation(True) - response = filechooser.run() - self.file_path = filechooser.get_filename() - filechooser.destroy() - if response == gtk.RESPONSE_OK: - logger.debug('Save file as %s' % self.file_path) - self.canvas.write_file(self.file_path) - self.set_title('%s - %s' % (self.file_path, appname)) - + from applicationgtk3 import Application if __name__ == '__main__': logger.debug('Initializing %s' % info.name) @@ -275,7 +56,6 @@ if __name__ == '__main__': file_path = None window = Application() window.file_path = file_path - window.show() - gtk.main() + window.start() logger.debug('Closing %s' % info.name) exit() diff --git a/applicationgtk2.py b/applicationgtk2.py new file mode 100755 index 0000000..64ecc27 --- /dev/null +++ b/applicationgtk2.py @@ -0,0 +1,258 @@ +# Copyright (C) 2012-2013 S. Daniel Francis <francis@sugarlabs.org> +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. + +# This file is modified for Graph Plotter + +import logging +logger = logging.getLogger('application') + +import os +import sys +import info +appname = info.name +import sweetener + +sys.path.append(os.path.abspath('./gtk2modules')) +sys.path.append(os.path.abspath('./sweetenergtk2')) + +logger.debug('gtk2 application loading') + +from options import Options +from canvas import Canvas + +try: + from sweetener.alerts import Alert +except: + pass + +this_dir = os.path.split('__file__')[:-1] +if len(this_dir) == 1 and this_dir[0] == '': + this_dir = os.path.abspath('./') +else: + this_dir = os.path.join(this_dir) +os.chdir(this_dir) + +from gettext import gettext as _ + +if 'programabspath' in os.environ['DATADIR']: + datadir = os.environ['DATADIR'].replace('programabspath', + this_dir) +else: + datadir = os.environ['DATADIR'] + +import gtk + +if os.environ['ICONDIR'] != 'SYSTEM': + logger.debug(this_dir) + icondir = os.environ['ICONDIR'].replace('programabspath', + this_dir) + icon_theme = gtk.icon_theme_get_for_screen(gtk.gdk.screen_get_default()) + icon_theme.append_search_path(icondir) + + +class UnfullscreenButton(gtk.Window): + + def __init__(self): + gtk.Window.__init__(self) + + self.set_decorated(False) + self.set_resizable(False) + self.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) + + self.set_border_width(0) + + self.props.accept_focus = False + + #Setup estimate of width, height + w, h = gtk.icon_size_lookup(gtk.ICON_SIZE_LARGE_TOOLBAR) + self._width = w + self._height = h + + self.connect('size-request', self._size_request_cb) + + screen = self.get_screen() + screen.connect('size-changed', self._screen_size_changed_cb) + + self._button = gtk.Button(stock=gtk.STOCK_LEAVE_FULLSCREEN) + self._button.set_relief(gtk.RELIEF_NONE) + self._button.show() + self.add(self._button) + + def connect_button_press(self, cb): + self._button.connect('button-press-event', cb) + + def _reposition(self): + x = gtk.gdk.screen_width() - self._width + self.move(x, 0) + + def _size_request_cb(self, widget, req): + self._width = req.width + self._height = req.height + self._reposition() + + def _screen_size_changed_cb(self, screen): + self._reposition() + + +class Application(gtk.Window): + def __init__(self): + gtk.Window.__init__(self) + self.save_type = info.io_mode + self.started = False + self.file_path = None + if info.file_filter_name: + self.filter = gtk.FileFilter() + self.filter.set_name(info.file_filter_name) + if info.file_filter_mime: + self.filter.add_mime_type(info.file_filter_mime) + for i in info.file_filter_patterns: + self.filter.add_pattern(i) + self.accel_group = gtk.AccelGroup() + self.add_accel_group(self.accel_group) + self.set_title(appname) + logger.debug(info.lower_name) + self.set_icon(gtk.gdk.pixbuf_new_from_file(os.path.join(datadir, + 'appicon.svg'))) + self.connect('delete-event', lambda w, e: self.stop()) + self.maximize() + self._vbox = gtk.VBox() + self.options = Options(self) + self.options.show() + self._vbox.pack_start(self.options, False, True, 0) + self.canvas = Canvas(self.options, self) + self.canvas.show() + self._vbox.pack_start(self.canvas, True, True, 0) + self.add(self._vbox) + self._vbox.show() + + self._is_fullscreen = False + self.set_events(gtk.gdk.ALL_EVENTS_MASK) + self.connect('motion-notify-event', self.motion_cb) + self.canvas.connect('expose-event', self.expose_event) + + def expose_event(self, widget, event): + #logger.debug('Exposing') + if not self.started: + if self.file_path is not None: + self.canvas.read_file(self.file_path) + self.set_title(os.path.abspath('%s - %s' % (self.file_path, + appname))) + else: + self.new() + self.started = True + + def motion_cb(self, widget, event): + if self._is_fullscreen: + x, y, state = self.get_window().get_pointer() + width, height = self.get_size() + button_width, button_height = self._unfullscreen_button.get_size() + if x >= width - button_width or y <= button_height: + self._unfullscreen_button.show() + else: + self._unfullscreen_button.hide() + + def add_alert(self, alert): + alert.run() + + def fullscreen(self): + self.options.hide() + self._is_fullscreen = True + self._unfullscreen_button = UnfullscreenButton() + self._unfullscreen_button.set_transient_for(self) + self._unfullscreen_button.connect_button_press( + lambda w, e: self.unfullscreen()) + self._unfullscreen_button.show() + gtk.Window.fullscreen(self) + + def unfullscreen(self): + self.options.show() + self._is_fullscreen = False + self._unfullscreen_button.destroy() + # The following line is an adition for Graph Plotter + self.canvas._resize_queue = self.canvas.previous_size + # Part of the sweetener code + gtk.Window.unfullscreen(self) + + def export(self, widget, data): + format_name = data[3] + filter_mime = data[2] + mime_type = data[1] + filechooser = gtk.FileChooserDialog(_("Export..."), self, + gtk.FILE_CHOOSER_ACTION_SAVE, + (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, + gtk.STOCK_OK, gtk.RESPONSE_OK)) + file_filter = gtk.FileFilter() + file_filter.set_name(format_name) + file_filter.add_mime_type(filter_mime) + filechooser.add_filter(file_filter) + filechooser.set_do_overwrite_confirmation(True) + filechooser.run() + file_path = filechooser.get_filename() + filechooser.destroy() + self.canvas.exports[mime_type](file_path) + + def new(self): + self.file_path = None + self.canvas.new() + self.set_title(appname) + + def stop(self): + if info.io_mode == info.CONFIG: + self.file_path = os.path.join(os.environ['HOME'], + '.' + info.lower_name) + self.save() + gtk.main_quit() + + def open(self): + filechooser = gtk.FileChooserDialog(_('Open...'), self, + gtk.FILE_CHOOSER_ACTION_OPEN, + (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, + gtk.STOCK_OPEN, gtk.RESPONSE_OK)) + filechooser.add_filter(self.filter) + response = filechooser.run() + self.file_path = filechooser.get_filename() + filechooser.destroy() + if response == gtk.RESPONSE_OK: + logger.debug('Read file %s' % self.file_path) + self.canvas.read_file(self.file_path) + self.set_title('%s - %s' % (self.file_path, appname)) + + def save(self): + if self.file_path is None: + self.save_as() + else: + logger.debug('Write file %s' % self.file_path) + self.canvas.write_file(self.file_path) + + def save_as(self): + filechooser = gtk.FileChooserDialog(_('Save...'), self, + gtk.FILE_CHOOSER_ACTION_SAVE, + (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, + gtk.STOCK_OK, gtk.RESPONSE_OK)) + filechooser.add_filter(self.filter) + filechooser.set_do_overwrite_confirmation(True) + response = filechooser.run() + self.file_path = filechooser.get_filename() + filechooser.destroy() + if response == gtk.RESPONSE_OK: + logger.debug('Save file as %s' % self.file_path) + self.canvas.write_file(self.file_path) + self.set_title('%s - %s' % (self.file_path, appname)) + + def start(self): + self.show() + gtk.main() diff --git a/applicationgtk3.py b/applicationgtk3.py new file mode 100755 index 0000000..d371559 --- /dev/null +++ b/applicationgtk3.py @@ -0,0 +1,291 @@ +# Copyright (C) 2012-2013 S. Daniel Francis <francis@sugarlabs.org> +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. + +# This file is modified for Graph Plotter + + +import logging +logger = logging.getLogger('application') + +import os +import sys +import info +appname = info.name + +import sweetener + +sys.path.append(os.path.abspath('./gtk3modules')) +sys.path.append(os.path.abspath('./sweetenergtk3')) + +logger.debug('gtk3 application loading') + +from gi.repository import GObject +from gi.repository import Gtk +from gi.repository import Gdk +from gi.repository import GdkPixbuf + +from options import Options +from canvas import Canvas +try: + from sweetener.alerts import Alert +except: + pass + +this_dir = os.path.split('__file__')[:-1] +if len(this_dir) == 1 and this_dir[0] == '': + this_dir = os.path.abspath('./') +else: + this_dir = os.path.join(this_dir) +os.chdir(this_dir) + +from gettext import gettext as _ + +if 'programabspath' in os.environ['DATADIR']: + datadir = os.environ['DATADIR'].replace('programabspath', + this_dir) +else: + datadir = os.environ['DATADIR'] + +if os.environ['ICONDIR'] != 'SYSTEM': + logger.debug(this_dir) + icondir = os.environ['ICONDIR'].replace('programabspath', + this_dir) + icon_theme = Gtk.IconTheme.get_for_screen(Gdk.Screen.get_default()) + icon_theme.append_search_path(icondir) + + +class UnfullscreenButton(Gtk.Window): + + def __init__(self): + GObject.GObject.__init__(self) + + self.set_decorated(False) + self.set_resizable(False) + self.set_type_hint(Gdk.WindowTypeHint.DIALOG) + + self.set_border_width(0) + + self.props.accept_focus = False + + #Setup estimate of width, height + valid, w, h = Gtk.icon_size_lookup(Gtk.IconSize.LARGE_TOOLBAR) + self._width = w + self._height = h + + screen = self.get_screen() + screen.connect('size-changed', self._screen_size_changed_cb) + + self._button = Gtk.Button(stock=Gtk.STOCK_LEAVE_FULLSCREEN) + self._button.set_relief(Gtk.ReliefStyle.NONE) + self._button.show() + self.add(self._button) + + def connect_button_press(self, cb): + self._button.connect('button-press-event', cb) + + def _reposition(self): + x = Gdk.Screen.width() - self._width + self.move(x, 0) + + def do_get_preferred_width(self): + minimum, natural = Gtk.Window.do_get_preferred_width(self) + self._width = minimum + self._reposition() + return minimum, natural + + def _screen_size_changed_cb(self, screen): + self._reposition() + + +class Application(Gtk.Window): + def __init__(self): + GObject.GObject.__init__(self) + self.set_size_request(800, 600) + self.save_type = info.io_mode + self.started = False + self.file_path = None + if info.file_filter_name: + self.filter = Gtk.FileFilter() + self.filter.set_name(info.file_filter_name) + if info.file_filter_mime: + self.filter.add_mime_type(info.file_filter_mime) + for i in info.file_filter_patterns: + self.filter.add_pattern(i) + self.accel_group = Gtk.AccelGroup() + self.add_accel_group(self.accel_group) + self.set_title(appname) + logger.debug(info.lower_name) + self.set_icon(GdkPixbuf.Pixbuf.new_from_file(os.path.join(datadir, + 'appicon.svg'))) + self.connect('delete-event', lambda w, e: self.stop()) + self.maximize() + self._vbox = Gtk.VBox() + self.options = Options(self) + self.options.show() + self._vbox.pack_start(self.options, False, True, 0) + self.canvas = Canvas(self.options, self) + self.canvas.show() + self._vbox.pack_start(self.canvas, True, True, 0) + self.add(self._vbox) + self._vbox.show() + + self._is_fullscreen = False + self.set_events(Gdk.EventMask.ALL_EVENTS_MASK) + self.connect('motion-notify-event', self.motion_cb) + + def do_draw(self, extra): + Gtk.Window.do_draw(self, extra) + #logger.debug('Exposing') + if not self.started: + if self.file_path is not None: + self.canvas.read_file(self.file_path) + self.set_title(os.path.abspath('%s - %s' % (self.file_path, + appname))) + else: + self.new() + self.started = True + + def motion_cb(self, widget, event): + if self._is_fullscreen: + state, x, y, mask = self.get_window().get_pointer() + width, height = self.get_size() + button_width, button_height = self._unfullscreen_button.get_size() + if x >= width - button_width or y <= button_height: + self._unfullscreen_button.show() + else: + self._unfullscreen_button.hide() + + def add_alert(self, alert): + alert.run() + + def fullscreen(self): + self.options.hide() + self._is_fullscreen = True + self._unfullscreen_button = UnfullscreenButton() + self._unfullscreen_button.set_transient_for(self) + self._unfullscreen_button.connect_button_press( + lambda w, e: self.unfullscreen()) + self._unfullscreen_button.show() + Gtk.Window.fullscreen(self) + + def unfullscreen(self): + self.options.show() + self._is_fullscreen = False + self._unfullscreen_button.destroy() + # The following line is an adition for Graph Plotter + self.canvas._resize_queue = self.canvas.previous_size + # Part of the sweetener code + Gtk.Window.unfullscreen(self) + + def export(self, widget, data): + format_name = data[3] + filter_mime = data[2] + mime_type = data[1] + filechooser = Gtk.FileChooserDialog(_("Export..."), self, + Gtk.FileChooserAction.SAVE, + (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, + Gtk.STOCK_OK, Gtk.ResponseType.OK)) + file_filter = Gtk.FileFilter() + file_filter.set_name(format_name) + file_filter.add_mime_type(filter_mime) + filechooser.add_filter(file_filter) + filechooser.set_do_overwrite_confirmation(True) + filechooser.run() + file_path = filechooser.get_filename() + filechooser.destroy() + self.canvas.exports[mime_type](file_path) + + def new(self): + self.file_path = None + self.canvas.new() + self.set_title(appname) + + def stop(self): + if info.io_mode == info.CONFIG: + self.file_path = os.path.join(os.environ['HOME'], + '.' + info.lower_name) + self.save() + Gtk.main_quit() + + def open(self): + filechooser = Gtk.FileChooserDialog(_('Open...'), self, + Gtk.FileChooserAction.OPEN, + (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, + Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) + filechooser.add_filter(self.filter) + response = filechooser.run() + self.file_path = filechooser.get_filename() + filechooser.destroy() + if response == Gtk.ResponseType.OK: + logger.debug('Read file %s' % self.file_path) + self.canvas.read_file(self.file_path) + self.set_title('%s - %s' % (self.file_path, appname)) + + def save(self): + if self.file_path is None: + self.save_as() + else: + logger.debug('Write file %s' % self.file_path) + self.canvas.write_file(self.file_path) + + def save_as(self): + filechooser = Gtk.FileChooserDialog(_('Save...'), self, + Gtk.FileChooserAction.SAVE, + (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, + Gtk.STOCK_OK, Gtk.ResponseType.OK)) + filechooser.add_filter(self.filter) + filechooser.set_do_overwrite_confirmation(True) + response = filechooser.run() + self.file_path = filechooser.get_filename() + filechooser.destroy() + if response == Gtk.ResponseType.OK: + logger.debug('Save file as %s' % self.file_path) + self.canvas.write_file(self.file_path) + self.set_title('%s - %s' % (self.file_path, appname)) + + def start(self): + self.show() + Gtk.main() + + +if __name__ == '__main__': + logger.debug('Initializing %s' % info.name) + import sys + if info.io_mode == info.DOCUMENT: + if len(sys.argv) > 1: + logger.debug('Open from args %s' % sys.argv[1]) + if os.path.exists(sys.argv[1]): + file_path = sys.argv[1] + logger.debug('Found file') + else: + file_path = None + logger.error('Could not find file') + else: + file_path = None + logger.debug('Create new file') + else: + if os.path.exists(os.path.join(os.environ['HOME'], + '.' + info.lower_name)): + file_path = os.path.join(os.environ['HOME'], '.' + info.lower_name) + else: + file_path = None + window = Application() + window.file_path = file_path + window.show() + Gtk.main() + logger.debug('Closing %s' % info.name) + exit() diff --git a/desktop/sweetener.py b/desktop/sweetener.py new file mode 100644 index 0000000..753d459 --- /dev/null +++ b/desktop/sweetener.py @@ -0,0 +1,30 @@ +# Copyright (C) 2013 S. Daniel Francis <francis@sugarlabs.org> +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. + + +# from sweetenergtk2 import * +# GTK = 2 + +# Use False and import Gtk2 by uncommenting the lines. +if True: + try: + from gi.repository import Gtk + from sweetenergtk3 import * + GTK = 3 + except ImportError: + from sweetenergtk2 import * + GTK = 2 diff --git a/desktop/sweetenergtk2 b/desktop/sweetenergtk2 -Subproject 1265546eda5b8ba30a5e430c50ad08f15b31c69 +Subproject 6d27a917415ecae9659620c94a34605322d44be diff --git a/desktop/sweetenergtk3 b/desktop/sweetenergtk3 -Subproject cb6082321b3c54eb1fc69900f68d4827bf061ee +Subproject 2c0cc402828a112ec67ac6301a783b8d42ab4c2 diff --git a/canvas.py b/gtk2modules/canvas.py index 818445a..fd52259 100644 --- a/canvas.py +++ b/gtk2modules/canvas.py @@ -1,7 +1,4 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# Copyright 2012 S. Daniel Francis <francis@sugarlabs.org> +# Copyright 2012-2013 S. Daniel Francis <francis@sugarlabs.org> # # 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 @@ -26,7 +23,7 @@ import gtk from math import * from sweetener import profile -from sweetener.colors import color2string +from sweetener import colors import expressions from graph import Graph @@ -58,7 +55,7 @@ class Canvas(gtk.HPaned): _list = [] for i in self.functions_list.get_list(): - _list.append([color2string(i[0]), i[2]]) + _list.append([colors.color2string(i[0]), i[2]]) graph_props = {'list': _list, 'xmin': self.graph.xmin, diff --git a/functions.py b/gtk2modules/functions.py index d0368b3..db6bb11 100644 --- a/functions.py +++ b/gtk2modules/functions.py @@ -1,7 +1,7 @@ """ This is a Gtk TreeView to list and modify the plotted functions """ -# Copyright (C) 2012 S. Daniel Francis <francis@sugarlabs.org> +# Copyright (C) 2012-2013 S. Daniel Francis <francis@sugarlabs.org> # # 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 @@ -23,9 +23,8 @@ logger = logging.getLogger('functions') import gobject import gtk -from sweetener.colors import color2string -from sweetener.colors import XoColor -from sweetener.icon import CellRendererIcon +from sweetener import colors +from sweetener import icon import expressions @@ -45,7 +44,7 @@ class FunctionsList(gtk.TreeView): self.model = gtk.ListStore(object, str, str, str, bool) self.set_model(self.model) column = gtk.TreeViewColumn() - color_renderer = CellRendererIcon(self) + color_renderer = icon.CellRendererIcon(self) width, height = gtk.icon_size_lookup(gtk.ICON_SIZE_SMALL_TOOLBAR) color_renderer.set_fixed_size(int(width * 1.5), int(height * 1.5)) # int(style.SMALL_ICON_SIZE * 4), -1) @@ -93,7 +92,7 @@ class FunctionsList(gtk.TreeView): def set_current_line_color(self, color): if not self.updating_color: rows = self.selection.get_selected_rows() - self.model[rows[1][0]][0] = XoColor(color + "," + color) + self.model[rows[1][0]][0] = colors.XoColor(color + "," + color) def update_color(self, info): path = info[0] @@ -124,7 +123,7 @@ class FunctionsList(gtk.TreeView): def append_function(self, color, expression='sin(x)'): self.selection.select_iter(self.model.append([ - XoColor(color2string(color) + "," + color2string(color)), + colors.XoColor(colors.color2string(color) + "," + colors.color2string(color)), "f%d(x) = " % (len(self.model) + 1), expression, None, True])) def remove_function(self): diff --git a/graph.py b/gtk2modules/graph.py index 6cb4c26..6cb4c26 100644 --- a/graph.py +++ b/gtk2modules/graph.py diff --git a/options.py b/gtk2modules/options.py index 96a75d5..722092d 100644 --- a/options.py +++ b/gtk2modules/options.py @@ -25,25 +25,26 @@ from gettext import gettext as _ import gobject import gtk +import sweetener +logger.debug(sweetener) +logger.debug(dir(sweetener)) from sweetener import stock -from sweetener.itembox import ItemBox -from sweetener.basic_options import BasicOptions -from sweetener.itemgroup import ItemGroup -from sweetener.itemgroup import SubGroup -from sweetener.itemgroup import GhostGroup -from sweetener.item import Item -from sweetener.toggleitem import ToggleItem -from sweetener.radioitem import RadioItem -from sweetener.settingsitem import SettingsItem -from sweetener.shortcontentitem import ShortContentItem -from sweetener.settingsradioitem import SettingsRadioItem -from sweetener.coloritem import ColorItem -from sweetener.help import Help +from sweetener import itembox +from sweetener import basic_options +from sweetener import itemgroup +from sweetener import item +from sweetener import toggleitem +from sweetener import radioitem +from sweetener import settingsitem +from sweetener import shortcontentitem +from sweetener import settingsradioitem +from sweetener import coloritem +from sweetener import helper -#from helpbutton import HelpButton +#from helpbutton import helper.HelpButton -class ViewOptions(ItemGroup): +class ViewOptions(itemgroup.ItemGroup): __gsignals__ = {'zoom-in': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, tuple()), @@ -79,17 +80,17 @@ class ViewOptions(ItemGroup): (gobject.TYPE_BOOLEAN,))} def __init__(self, box): - ItemGroup.__init__(self, box, _('_View'), 'toolbar-view') + itemgroup.ItemGroup.__init__(self, box, _('_View'), 'toolbar-view') self.setup_scale_style() stock.register('graph-plotter-show-grid', _('Show _grid'), '<Ctrl>G', 'insert-table') - show_grid = ToggleItem(True, 'graph-plotter-show-grid') + show_grid = toggleitem.ToggleItem(True, 'graph-plotter-show-grid') show_grid.connect('toggled', lambda w, active: self.emit('show-grid', active)) self.append_item(show_grid) stock.register('graph-plotter-connect-points', _('Connect _points'), '<Ctrl>I', 'connect-points') - connect_points_option = ToggleItem(True, + connect_points_option = toggleitem.ToggleItem(True, 'graph-plotter-connect-points') connect_points_option.connect('toggled', lambda w, active: self.emit('connect-points', active)) @@ -97,26 +98,26 @@ class ViewOptions(ItemGroup): self.append_separator() self.setup_zoom() self.append_separator() - fullscreen_option = Item(gtk.STOCK_FULLSCREEN) + fullscreen_option = item.Item(gtk.STOCK_FULLSCREEN) fullscreen_option.connect('activate', lambda w: self.emit('fullscreen')) self.append_item(fullscreen_option) def setup_zoom(self): - zoom_in_item = Item(gtk.STOCK_ZOOM_IN) + zoom_in_item = item.Item(gtk.STOCK_ZOOM_IN) zoom_in_item.connect('activate', lambda w: self.emit('zoom-in')) self.append_item(zoom_in_item) - zoom_out_item = Item(gtk.STOCK_ZOOM_OUT) + zoom_out_item = item.Item(gtk.STOCK_ZOOM_OUT) zoom_out_item.connect('activate', lambda w: self.emit('zoom-out')) self.append_item(zoom_out_item) - zoom_reset_item = Item(gtk.STOCK_ZOOM_100) + zoom_reset_item = item.Item(gtk.STOCK_ZOOM_100) zoom_reset_item.connect('activate', lambda w: self.emit('zoom-reset')) self.append_item(zoom_reset_item) def setup_scale_range(self, subgroup): stock.register('graph-plotter-scale-range', _('R_ange'), '<Ctrl>N', 'cell-size') - self.scale_range = SettingsItem(self.activity, + self.scale_range = settingsitem.SettingsItem(self.activity, 'graph-plotter-scale-range', True) self.scale_range.tooltip = _('Scale range') self.scale_range.connect('closed', lambda w: self.emit('scale-range')) @@ -174,18 +175,18 @@ class ViewOptions(ItemGroup): return self.x_scale_entry.get_text(), self.y_scale_entry.get_text() def setup_scale_style(self): - subgroup = SubGroup(self, _('_Scale')) + subgroup = itemgroup.SubGroup(self, _('_Scale')) self.setup_scale_range(subgroup) stock.register('graph-plotter-decimal', _('_Decimal'), '<Ctrl>D', 'decimal') - self.decimal_option = RadioItem(None, stock_id='graph-plotter-decimal') + self.decimal_option = radioitem.RadioItem(None, stock_id='graph-plotter-decimal') self.decimal_option.tooltip = _('Decimal scale') self.decimal_option.connect('toggled', lambda w, a: self.emit('decimal-scale')) subgroup.append_item(self.decimal_option) stock.register('graph-plotter-radians', _('_Radian'), '<Ctrl>I', 'radian') - self.radians_option = RadioItem(self.decimal_option, False, + self.radians_option = radioitem.RadioItem(self.decimal_option, False, 'graph-plotter-radians') self.radians_option.tooltip = _('Radian scale') self.radians_option.connect('toggled', @@ -193,7 +194,7 @@ class ViewOptions(ItemGroup): subgroup.append_item(self.radians_option) stock.register('graph-plotter-custom', _('_Custom'), '<Ctrl>T', 'custom') - self.custom_option = SettingsRadioItem(self.decimal_option, False, + self.custom_option = settingsradioitem.SettingsRadioItem(self.decimal_option, False, self.activity, 'graph-plotter-custom') self.custom_option.set_stock_id('graph-plotter-custom') @@ -237,7 +238,7 @@ class ViewOptions(ItemGroup): return scale_table -class Options(ItemBox): +class Options(itembox.ItemBox): __gsignals__ = {'append-function': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_INT, tuple()), @@ -255,28 +256,28 @@ class Options(ItemBox): (gobject.TYPE_STRING,))} def __init__(self, activity): - ItemBox.__init__(self, activity) + itembox.ItemBox.__init__(self, activity) self.activity = activity - self.basic = BasicOptions(activity, self, + self.basic = basic_options.BasicOptions(activity, self, [(_('_image'), 'image/x-generic', 'image/*', _('Images'))]) #activity_button.page.share.hide() self.view = ViewOptions(self) - self.ghost = GhostGroup(self, _('F_unction')) - add_function = Item(gtk.STOCK_ADD, True) + self.ghost = itemgroup.GhostGroup(self, _('F_unction')) + add_function = item.Item(gtk.STOCK_ADD, True) add_function.tooltip = _('Append a new function') add_function.connect('activate', self._append_function_cb) self.ghost.append_item(add_function) - self.remove_function = Item(gtk.STOCK_REMOVE, True) + self.remove_function = item.Item(gtk.STOCK_REMOVE, True) self.remove_function.tooltip = _('Remove the selected function') self.remove_function.connect('activate', self._remove_function_cb) self.ghost.append_item(self.remove_function) self.remove_function.sensitive = False - self.color_item = ColorItem(activity, True) + self.color_item = coloritem.ColorItem(activity, True) self.color_item.tooltip = _('Plot color') self.color_item.connect('updated', lambda w, color: self.emit('color-updated', @@ -284,7 +285,7 @@ class Options(ItemBox): self.ghost.append_item(self.color_item) # self.setup_help_button() -# separator = gtk.SeparatorToolItem() +# separator = gtk.SeparatorToolitem.Item() # separator.show() # separator.set_expand(True) # separator.set_draw(False) @@ -301,7 +302,7 @@ class Options(ItemBox): hbox.pack_start(evaluate_label, False, False, 0) hbox.pack_start(self.evaluate_entry, True, True, 0) hbox.show() - evaluate_entry_item = ShortContentItem(activity, + evaluate_entry_item = shortcontentitem.ShortContentItem(activity, 'graph-plotter-evaluate', True) evaluate_entry_item.separator = self.ghost.append_separator(True) stock.register('graph-plotter-evaluate', _('_Evaluate'), @@ -309,7 +310,7 @@ class Options(ItemBox): evaluate_entry_item.set_stock_id('graph-plotter-evaluate') evaluate_entry_item.content = hbox self.ghost.append_item(evaluate_entry_item) - self.help = Help(self) + self.help = helper.Help(self) def _append_function_cb(self, widget): number = self.emit('append-function') diff --git a/canvas.py b/gtk3modules/canvas.py index 818445a..bd9afcc 100644 --- a/canvas.py +++ b/gtk3modules/canvas.py @@ -22,11 +22,13 @@ import logging logger = logging.getLogger('canvas') import json -import gtk +from gi.repository import Gtk +from gi.repository import Gdk +from gi.repository import GObject from math import * from sweetener import profile -from sweetener.colors import color2string +from sweetener import colors import expressions from graph import Graph @@ -44,10 +46,10 @@ y_min = '-3.0' y_scale = '1.0' -class Canvas(gtk.HPaned): +class Canvas(Gtk.HPaned): #def write_file(self, file_path): #x, y, w, h = self.graph.get_allocation() - #pix_buffer = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, w, h) + #pix_buffer = GdkPixbuf.Pixbuf(GdkPixbuf.Colorspace.RGB, False, 8, w, h) #pix_buffer.get_from_drawable(self.graph.pix_map, #self.graph.pix_map.get_colormap(), #0, 0, 0, 0, w, h) @@ -58,7 +60,7 @@ class Canvas(gtk.HPaned): _list = [] for i in self.functions_list.get_list(): - _list.append([color2string(i[0]), i[2]]) + _list.append([colors.color2string(i[0]), i[2]]) graph_props = {'list': _list, 'xmin': self.graph.xmin, @@ -78,7 +80,7 @@ class Canvas(gtk.HPaned): graph_props = json.load(jfile) self.functions_list.model.clear() for i in graph_props['list']: - self.functions_list.append_function(gtk.gdk.color_parse(i[0]), + self.functions_list.append_function(Gdk.color_parse(i[0]), i[1]) self.update_graph(None, self.functions_list.get_list()) except Exception, err: @@ -87,7 +89,7 @@ class Canvas(gtk.HPaned): jfile.close() def __init__(self, toolbar_box, activity): - gtk.HPaned.__init__(self) + GObject.GObject.__init__(self) self.activity = activity self.x_max = x_max self.x_min = x_min @@ -141,24 +143,24 @@ class Canvas(gtk.HPaned): self.functions_list.connect('function-selected', self._update_color_selection) self.functions_list.show() - functions_box = gtk.VBox() - function_entry = gtk.Entry() + functions_box = Gtk.VBox() + function_entry = Gtk.Entry() function_entry.show() function_entry.connect('activate', self._new_function_cb) functions_box.pack_start(function_entry, False, True, 0) - functions_window = gtk.ScrolledWindow() + functions_window = Gtk.ScrolledWindow() functions_window.add(self.functions_list) - functions_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + functions_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) functions_window.set_hadjustment(self.functions_list.get_hadjustment()) functions_window.set_vadjustment(self.functions_list.get_vadjustment()) functions_window.show() functions_box.pack_start(functions_window, True, True, 0) - hbox = gtk.HBox() - self.xlabel = gtk.Label() + hbox = Gtk.HBox() + self.xlabel = Gtk.Label() self.xlabel.set_alignment(0.5, 0.5) self.xlabel.show() hbox.pack_start(self.xlabel, True, True, 0) - self.ylabel = gtk.Label() + self.ylabel = Gtk.Label() self.ylabel.set_alignment(0.5, 0.5) self.ylabel.show() hbox.pack_start(self.ylabel, True, True, 0) @@ -174,7 +176,6 @@ class Canvas(gtk.HPaned): self.toolbar_box.view.y_scale_entry.set_text(self.y_scale) self.pack2(self.graph) self.graph.show() - self.connect('expose-event', self._paned_expose_event_cb) def new(self): self.functions_list.model.clear() @@ -233,9 +234,11 @@ class Canvas(gtk.HPaned): self.graph.set_ymax(ymax) self.update_graph(None, self.functions_list.get_list()) - def _paned_expose_event_cb(self, widget, event): + def do_draw(self, extra): + Gtk.Paned.do_draw(self, extra) #logger.debug('Paned expose') - x, y, w, h = self.get_allocation() + alloc = self.get_allocation() + x, y, w, h = alloc.x, alloc.y, alloc.width, alloc.height if self._resize_queue == None: if self.w != w or self.h != h: self._resize_queue = self._resize_constant diff --git a/functions.py b/gtk3modules/functions.py index d0368b3..a9e2aa9 100644 --- a/functions.py +++ b/gtk3modules/functions.py @@ -20,33 +20,33 @@ This is a Gtk TreeView to list and modify the plotted functions import logging logger = logging.getLogger('functions') -import gobject -import gtk +from gi.repository import GObject +from gi.repository import Gtk +from gi.repository import Gdk -from sweetener.colors import color2string -from sweetener.colors import XoColor -from sweetener.icon import CellRendererIcon +from sweetener import colors +from sweetener import icon import expressions -class FunctionsList(gtk.TreeView): - __gsignals__ = {'list-updated': (gobject.SIGNAL_RUN_LAST, - gobject.TYPE_NONE, - (gobject.TYPE_PYOBJECT,)), - 'function-selected': (gobject.SIGNAL_RUN_LAST, - gobject.TYPE_NONE, - (gobject.TYPE_PYOBJECT,))} +class FunctionsList(Gtk.TreeView): + __gsignals__ = {'list-updated': (GObject.SignalFlags.RUN_LAST, + None, + (GObject.TYPE_PYOBJECT,)), + 'function-selected': (GObject.SignalFlags.RUN_LAST, + None, + (GObject.TYPE_PYOBJECT,))} def __init__(self): - gtk.TreeView.__init__(self) + GObject.GObject.__init__(self) self.set_rules_hint(True) self.grab_focus() - self.model = gtk.ListStore(object, str, str, str, bool) + self.model = Gtk.ListStore(object, str, str, str, bool) self.set_model(self.model) - column = gtk.TreeViewColumn() - color_renderer = CellRendererIcon(self) - width, height = gtk.icon_size_lookup(gtk.ICON_SIZE_SMALL_TOOLBAR) + column = Gtk.TreeViewColumn() + color_renderer = icon.CellRendererIcon(self) + valid, width, height = Gtk.icon_size_lookup(Gtk.IconSize.SMALL_TOOLBAR) color_renderer.set_fixed_size(int(width * 1.5), int(height * 1.5)) # int(style.SMALL_ICON_SIZE * 4), -1) color_renderer.set_size(int(height * 1.5)) @@ -57,27 +57,27 @@ class FunctionsList(gtk.TreeView): color_renderer.props.prelit_fill_color = "#FFFFFF" column.pack_start(color_renderer, False) column.add_attribute(color_renderer, 'xo-color', 0) - name_renderer = gtk.CellRendererText() + name_renderer = Gtk.CellRendererText() column.pack_start(name_renderer, False) column.add_attribute(name_renderer, 'text', 1) - text_renderer = gtk.CellRendererText() + text_renderer = Gtk.CellRendererText() text_renderer.set_property('editable', True) text_renderer.connect('edited', self._function_changed) column.pack_start(text_renderer, True) column.add_attribute(text_renderer, 'text', 2) self.set_headers_visible(False) self.append_column(column) - self.evaluating_column = gtk.TreeViewColumn() - y_renderer = gtk.CellRendererText() + self.evaluating_column = Gtk.TreeViewColumn() + y_renderer = Gtk.CellRendererText() y_renderer.set_property('text', ' = ') self.evaluating_column.pack_start(y_renderer, False) - evaluation_cell = gtk.CellRendererText() + evaluation_cell = Gtk.CellRendererText() self.evaluating_column.pack_start(evaluation_cell, False) self.evaluating_column.add_attribute(evaluation_cell, 'text', 3) self.append_column(self.evaluating_column) self.evaluating_column.set_visible(False) self.selection = self.get_selection() - self.selection.set_select_function(self.update_color) + self.selection.set_select_function(self.update_color, None) self.updating_color = False def evaluate(self, safe_dict): @@ -93,10 +93,9 @@ class FunctionsList(gtk.TreeView): def set_current_line_color(self, color): if not self.updating_color: rows = self.selection.get_selected_rows() - self.model[rows[1][0]][0] = XoColor(color + "," + color) + self.model[rows[1][0]][0] = colors.XoColor(color + "," + color) - def update_color(self, info): - path = info[0] + def update_color(self, selection, model, path, selected, data): for i in self.model: i[-1] = False color = self.model[path][0] @@ -109,7 +108,7 @@ class FunctionsList(gtk.TreeView): def get_list(self): funcs = [] for func in self.model: - row = [gtk.gdk.color_parse(func[0].get_fill_color()), + row = [Gdk.color_parse(func[0].get_fill_color()), func[1], func[2], func[-1]] funcs.append(row) # logger.debug(str(funcs)) @@ -124,7 +123,7 @@ class FunctionsList(gtk.TreeView): def append_function(self, color, expression='sin(x)'): self.selection.select_iter(self.model.append([ - XoColor(color2string(color) + "," + color2string(color)), + colors.XoColor(colors.color2string(color) + "," + colors.color2string(color)), "f%d(x) = " % (len(self.model) + 1), expression, None, True])) def remove_function(self): diff --git a/graph.py b/gtk3modules/graph.py index 6cb4c26..c707668 100644 --- a/graph.py +++ b/gtk3modules/graph.py @@ -1,7 +1,4 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# Copyright 2012 S. Daniel Francis <francis@sugarlabs.org> +# Copyright 2012-2013 S. Daniel Francis <francis@sugarlabs.org> # # 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 @@ -25,9 +22,10 @@ from math import * fac = lambda n: [1, 0][n > 0] or fac(n - 1) * n from numpy import sinc -import gobject -import gtk -import pango +from gi.repository import GObject +from gi.repository import Gtk +from gi.repository import Gdk +from gi.repository import Pango import cairo import expressions @@ -78,14 +76,14 @@ def marks(min_val, max_val, minor=1): a_mark += interval -class Graph(gtk.DrawingArea): - __gsignals__ = {'repopulate-parameter-entries': (gobject.SIGNAL_RUN_LAST, - gobject.TYPE_NONE, +class Graph(Gtk.DrawingArea): + __gsignals__ = {'repopulate-parameter-entries': (GObject.SignalFlags.RUN_LAST, + None, tuple()), - 'update-x-y': (gobject.SIGNAL_RUN_LAST, - gobject.TYPE_NONE, - (gobject.TYPE_FLOAT, - gobject.TYPE_FLOAT))} + 'update-x-y': (GObject.SignalFlags.RUN_LAST, + None, + (GObject.TYPE_FLOAT, + GObject.TYPE_FLOAT))} safe_dict = safe_list = {'acos': acos, 'asin': asin, @@ -135,7 +133,7 @@ class Graph(gtk.DrawingArea): _move_from = None def __init__(self): - gtk.DrawingArea.__init__(self) + GObject.GObject.__init__(self) self.connect_points = True #add any needed builtins back in. self.safe_dict['abs'] = abs @@ -147,16 +145,16 @@ class Graph(gtk.DrawingArea): self.y = None self.prev_y = [None, None, None] self.selection = [[None, None], [None, None]] - self.set_events(gtk.gdk.ALL_EVENTS_MASK) + self.set_events(Gdk.EventMask.ALL_EVENTS_MASK) self.scale_style = SCALE_TYPE_DEC self.follow_function = False -# self.set_flags(gtk.CAN_FOCUS) -# self.add_events(gtk.gdk.BUTTON_PRESS_MASK) -# self.add_events(gtk.gdk.KEY_PRESS) +# self.set_flags(Gtk.CAN_FOCUS) +# self.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) +# self.add_events(Gdk.KEY_PRESS) # self.grab_focus() # self.connect('key_press_event', self._key_press_event) # self.connect('key_release_event', self._key_relase_event) - self.connect('expose_event', self._expose_event_cb) + self.connect('draw', self._draw_cb) self.connect('configure_event', self._configure_event_cb) self.connect('button_press_event', self._button_press_event_cb) self.connect('button_release_event', self._button_release_event_cb) @@ -218,23 +216,27 @@ class Graph(gtk.DrawingArea): self.selection[1][0], self.selection[1][1] = None, None self.follow_function = not self.follow_function - # End of selection def _button_release_event_cb(self, widget, event): if event.x != None and event.y != None\ and self.selection[0][0] != None: if event.button == 1 and\ - event.x != self.selection[0][0] and\ - event.y != self.selection[0][1]: + int(event.x) != self.selection[0][0] and\ + int(event.y) != self.selection[0][1]: + logger.debug('from x: %d y: %d to x: %d y: %d' % + (self.selection[0][0], self.selection[0][1], event.x, event.y)) xmi = min(self.graph_x(self.selection[0][0]), - self.graph_x(event.x)) + self.graph_x(event.x)) ymi = min(self.graph_y(self.selection[0][1]), - self.graph_y(event.y)) + self.graph_y(event.y)) xma = max(self.graph_x(self.selection[0][0]), - self.graph_x(event.x)) + self.graph_x(event.x)) yma = max(self.graph_y(self.selection[0][1]), - self.graph_y(event.y)) + self.graph_y(event.y)) self.xmin, self.ymin, self.xmax, self.ymax = xmi, ymi, xma, yma + # Cancel the follow function self.follow_function = not self.follow_function + else: + logger.debug(event.button) self.selection = [[None, None], [None, None]] self._move_from = None self.queue_draw() @@ -243,7 +245,7 @@ class Graph(gtk.DrawingArea): # Draw rectangle during mouse movement def _motion_notify_event_cb(self, widget, event): - x, y, state = self.get_window().get_pointer() + state, x, y, mask = self.get_window().get_pointer() self.pointer = [x, y] graph_x = self.graph_x(x) if self.scale_style == SCALE_TYPE_RAD: @@ -273,31 +275,31 @@ class Graph(gtk.DrawingArea): if self.shift: if self._move_from != None: #logger.debug(str(self._move_from)) - self.get_window().set_cursor(gtk.gdk.Cursor(gtk.gdk.FLEUR)) + self.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.FLEUR)) else: - self.get_window().set_cursor(gtk.gdk.Cursor(gtk.gdk.LEFT_PTR)) + self.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.LEFT_PTR)) elif self.selection[0][0] != None: if self.selection[0][0] < self.selection[1][0]: if self.selection[0][1] < self.selection[1][1]: self.get_window().set_cursor( - gtk.gdk.Cursor(gtk.gdk.BOTTOM_RIGHT_CORNER)) + Gdk.Cursor.new(Gdk.CursorType.BOTTOM_RIGHT_CORNER)) else: self.get_window().set_cursor( - gtk.gdk.Cursor(gtk.gdk.TOP_RIGHT_CORNER)) + Gdk.Cursor.new(Gdk.CursorType.TOP_RIGHT_CORNER)) else: if self.selection[0][1] < self.selection[1][1]: self.get_window().set_cursor( - gtk.gdk.Cursor(gtk.gdk.BOTTOM_LEFT_CORNER)) + Gdk.Cursor.new(Gdk.CursorType.BOTTOM_LEFT_CORNER)) else: self.get_window().set_cursor( - gtk.gdk.Cursor(gtk.gdk.TOP_LEFT_CORNER)) + Gdk.Cursor.new(Gdk.CursorType.TOP_LEFT_CORNER)) else: - self.get_window().set_cursor(gtk.gdk.Cursor(gtk.gdk.CROSS)) + self.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.CROSS)) def draw_selection_rectangle(self): if self.selection[0][0] != None: #gc = self.drawing_area.get_style().black_gc - #gc.set_function(gtk.gdk.INVERT) + #gc.set_function(Gdk.INVERT) if self.selection[1][0] != None: x0 = min(self.selection[1][0], self.selection[0][0]) y0 = min(self.selection[1][1], self.selection[0][1]) @@ -350,7 +352,9 @@ class Graph(gtk.DrawingArea): self.context.set_line_width(0.5) self.context.move_to(x, 0) self.context.line_to(x, self.canvas_height) + logger.debug(self.follow_function) if self.follow_function: + for i in self.functions: if i[-1]: expression = expressions.convert(i[0]) @@ -471,10 +475,10 @@ class Graph(gtk.DrawingArea): self.context.line_to(int(round(self.canvas_x(i))), center_y_pix + 5) - self.layout.set_text(label) + self.layout.set_text(label, -1) extents = self.layout.get_pixel_extents()[1] if (numbers_y_pos < 0): - adjust = extents[3] + adjust = 0 # extents.height else: adjust = 0 self.context.move_to(int(round(self.canvas_x(i))), @@ -499,10 +503,10 @@ class Graph(gtk.DrawingArea): self.context.line_to(center_x_pix + 5, int(round(self.canvas_y(i)))) - self.layout.set_text(label) + self.layout.set_text(label, -1) extents = self.layout.get_pixel_extents()[1] if (numbers_x_pos < 0): - adjust = extents[2] + adjust = extents.width else: adjust = 0 self.context.move_to(center_x_pix + numbers_x_pos - adjust, @@ -619,24 +623,23 @@ class Graph(gtk.DrawingArea): self.yscale = eval(yscale, {'__builtins__': {}}, self.safe_dict) def _configure_event_cb(self, widget, event): - x, y, w, h = widget.get_allocation() + alloc = widget.get_allocation() self.context = widget.get_window().cairo_create() # make colors self.gc = dict() - self.layout = pango.Layout(widget.create_pango_context()) - self.canvas_width = w - self.canvas_height = h + self.layout = Pango.Layout(widget.create_pango_context()) + self.canvas_width = alloc.width + self.canvas_height = alloc.height self.queue_draw() return True - def _expose_event_cb(self, widget, event): - x, y, w, h = event.area + def _draw_cb(self, widget, context): + alloc = widget.get_allocation() window = widget.get_window() self.draw_cursor() - context = window.cairo_create() self.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, - w, h) + alloc.width, alloc.height) self.context = cairo.Context(self.surface) context.set_source_surface(self.surface, 0, 0) self.draw_queue() diff --git a/options.py b/gtk3modules/options.py index 96a75d5..3f133ac 100644 --- a/options.py +++ b/gtk3modules/options.py @@ -1,7 +1,4 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# Copyright 2012 S. Daniel Francis <francis@sugarlabs.org> +# Copyright 2012-2013 S. Daniel Francis <francis@sugarlabs.org> # # 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 @@ -22,74 +19,70 @@ import logging logger = logging.getLogger('options') from gettext import gettext as _ -import gobject -import gtk +from gi.repository import GObject +from gi.repository import Gtk from sweetener import stock -from sweetener.itembox import ItemBox -from sweetener.basic_options import BasicOptions -from sweetener.itemgroup import ItemGroup -from sweetener.itemgroup import SubGroup -from sweetener.itemgroup import GhostGroup -from sweetener.item import Item -from sweetener.toggleitem import ToggleItem -from sweetener.radioitem import RadioItem -from sweetener.settingsitem import SettingsItem -from sweetener.shortcontentitem import ShortContentItem -from sweetener.settingsradioitem import SettingsRadioItem -from sweetener.coloritem import ColorItem -from sweetener.help import Help - -#from helpbutton import HelpButton +from sweetener import itembox +from sweetener import basic_options +from sweetener import itemgroup +from sweetener import item +from sweetener import toggleitem +from sweetener import radioitem +from sweetener import settingsitem +from sweetener import shortcontentitem +from sweetener import settingsradioitem +from sweetener import coloritem +from sweetener import helper -class ViewOptions(ItemGroup): - __gsignals__ = {'zoom-in': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, +class ViewOptions(itemgroup.ItemGroup): + __gsignals__ = {'zoom-in': (GObject.SignalFlags.RUN_FIRST, + None, tuple()), - 'zoom-out': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, + 'zoom-out': (GObject.SignalFlags.RUN_FIRST, + None, tuple()), - 'zoom-reset': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, + 'zoom-reset': (GObject.SignalFlags.RUN_FIRST, + None, tuple()), - 'scale-range': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, + 'scale-range': (GObject.SignalFlags.RUN_FIRST, + None, tuple()), - 'fullscreen': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, + 'fullscreen': (GObject.SignalFlags.RUN_FIRST, + None, tuple()), - 'connect-points': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_BOOLEAN,)), - 'decimal-scale': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, + 'connect-points': (GObject.SignalFlags.RUN_FIRST, + None, + (GObject.TYPE_BOOLEAN,)), + 'decimal-scale': (GObject.SignalFlags.RUN_FIRST, + None, tuple()), - 'radian-scale': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, + 'radian-scale': (GObject.SignalFlags.RUN_FIRST, + None, tuple()), - 'custom-scale': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, + 'custom-scale': (GObject.SignalFlags.RUN_FIRST, + None, tuple()), - 'scale': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, + 'scale': (GObject.SignalFlags.RUN_FIRST, + None, tuple()), - 'show-grid': (gobject.SIGNAL_RUN_LAST, - gobject.TYPE_NONE, - (gobject.TYPE_BOOLEAN,))} + 'show-grid': (GObject.SignalFlags.RUN_LAST, + None, + (GObject.TYPE_BOOLEAN,))} def __init__(self, box): - ItemGroup.__init__(self, box, _('_View'), 'toolbar-view') + itemgroup.ItemGroup.__init__(self, box, _('_View'), 'toolbar-view') self.setup_scale_style() stock.register('graph-plotter-show-grid', _('Show _grid'), '<Ctrl>G', 'insert-table') - show_grid = ToggleItem(True, 'graph-plotter-show-grid') + show_grid = toggleitem.ToggleItem(True, 'graph-plotter-show-grid') show_grid.connect('toggled', lambda w, active: self.emit('show-grid', active)) self.append_item(show_grid) stock.register('graph-plotter-connect-points', _('Connect _points'), '<Ctrl>I', 'connect-points') - connect_points_option = ToggleItem(True, + connect_points_option = toggleitem.ToggleItem(True, 'graph-plotter-connect-points') connect_points_option.connect('toggled', lambda w, active: self.emit('connect-points', active)) @@ -97,43 +90,43 @@ class ViewOptions(ItemGroup): self.append_separator() self.setup_zoom() self.append_separator() - fullscreen_option = Item(gtk.STOCK_FULLSCREEN) + fullscreen_option = item.Item(Gtk.STOCK_FULLSCREEN) fullscreen_option.connect('activate', lambda w: self.emit('fullscreen')) self.append_item(fullscreen_option) def setup_zoom(self): - zoom_in_item = Item(gtk.STOCK_ZOOM_IN) + zoom_in_item = item.Item(Gtk.STOCK_ZOOM_IN) zoom_in_item.connect('activate', lambda w: self.emit('zoom-in')) self.append_item(zoom_in_item) - zoom_out_item = Item(gtk.STOCK_ZOOM_OUT) + zoom_out_item = item.Item(Gtk.STOCK_ZOOM_OUT) zoom_out_item.connect('activate', lambda w: self.emit('zoom-out')) self.append_item(zoom_out_item) - zoom_reset_item = Item(gtk.STOCK_ZOOM_100) + zoom_reset_item = item.Item(Gtk.STOCK_ZOOM_100) zoom_reset_item.connect('activate', lambda w: self.emit('zoom-reset')) self.append_item(zoom_reset_item) def setup_scale_range(self, subgroup): stock.register('graph-plotter-scale-range', _('R_ange'), '<Ctrl>N', 'cell-size') - self.scale_range = SettingsItem(self.activity, + self.scale_range = settingsitem.SettingsItem(self.activity, 'graph-plotter-scale-range', True) self.scale_range.tooltip = _('Scale range') self.scale_range.connect('closed', lambda w: self.emit('scale-range')) - scale_range_table = gtk.Table(4, 2, False) - x_min_label = gtk.Label(_('X min') + ' =') - x_min_label.set_justify(gtk.JUSTIFY_RIGHT) - self.x_min_entry = gtk.Entry() + scale_range_table = Gtk.Table(4, 2, False) + x_min_label = Gtk.Label(label=_('X min') + ' =') + x_min_label.set_justify(Gtk.Justification.RIGHT) + self.x_min_entry = Gtk.Entry() self.x_min_entry.set_size_request(90, -1) self.x_min_entry.set_alignment(0) self.x_min_entry.connect('activate', lambda w: self.emit('scale-range')) scale_range_table.attach(x_min_label, 0, 1, 0, 1, xpadding=5) scale_range_table.attach(self.x_min_entry, 1, 2, 0, 1) - x_max_label = gtk.Label(_('X max') + ' =') - x_max_label.set_justify(gtk.JUSTIFY_RIGHT) - self.x_max_entry = gtk.Entry() + x_max_label = Gtk.Label(label=_('X max') + ' =') + x_max_label.set_justify(Gtk.Justification.RIGHT) + self.x_max_entry = Gtk.Entry() self.x_max_entry.set_size_request(90, -1) self.x_max_entry.set_alignment(0) self.x_max_entry.connect('activate', @@ -141,18 +134,18 @@ class ViewOptions(ItemGroup): scale_range_table.attach(x_max_label, 0, 1, 2, 3, xpadding=5) scale_range_table.attach(self.x_max_entry, 1, 2, 2, 3) - y_min_label = gtk.Label(_('Y min') + ' =') - y_min_label.set_justify(gtk.JUSTIFY_RIGHT) - self.y_min_entry = gtk.Entry() + y_min_label = Gtk.Label(label=_('Y min') + ' =') + y_min_label.set_justify(Gtk.Justification.RIGHT) + self.y_min_entry = Gtk.Entry() self.y_min_entry.set_size_request(90, -1) self.y_min_entry.set_alignment(0) self.y_min_entry.connect('activate', lambda w: self.emit('scale-range')) scale_range_table.attach(y_min_label, 2, 3, 0, 1, xpadding=5) scale_range_table.attach(self.y_min_entry, 3, 4, 0, 1) - y_max_label = gtk.Label(_('Y max') + ' =') - y_max_label.set_justify(gtk.JUSTIFY_RIGHT) - self.y_max_entry = gtk.Entry() + y_max_label = Gtk.Label(label=_('Y max') + ' =') + y_max_label.set_justify(Gtk.Justification.RIGHT) + self.y_max_entry = Gtk.Entry() self.y_max_entry.set_size_request(90, -1) self.y_max_entry.set_alignment(0) self.y_max_entry.connect('activate', @@ -174,18 +167,18 @@ class ViewOptions(ItemGroup): return self.x_scale_entry.get_text(), self.y_scale_entry.get_text() def setup_scale_style(self): - subgroup = SubGroup(self, _('_Scale')) + subgroup = itemgroup.SubGroup(self, _('_Scale')) self.setup_scale_range(subgroup) stock.register('graph-plotter-decimal', _('_Decimal'), '<Ctrl>D', 'decimal') - self.decimal_option = RadioItem(None, stock_id='graph-plotter-decimal') + self.decimal_option = radioitem.RadioItem(None, stock_id='graph-plotter-decimal') self.decimal_option.tooltip = _('Decimal scale') self.decimal_option.connect('toggled', lambda w, a: self.emit('decimal-scale')) subgroup.append_item(self.decimal_option) stock.register('graph-plotter-radians', _('_Radian'), '<Ctrl>I', 'radian') - self.radians_option = RadioItem(self.decimal_option, False, + self.radians_option = radioitem.RadioItem(self.decimal_option, False, 'graph-plotter-radians') self.radians_option.tooltip = _('Radian scale') self.radians_option.connect('toggled', @@ -193,7 +186,7 @@ class ViewOptions(ItemGroup): subgroup.append_item(self.radians_option) stock.register('graph-plotter-custom', _('_Custom'), '<Ctrl>T', 'custom') - self.custom_option = SettingsRadioItem(self.decimal_option, False, + self.custom_option = settingsradioitem.SettingsRadioItem(self.decimal_option, False, self.activity, 'graph-plotter-custom') self.custom_option.set_stock_id('graph-plotter-custom') @@ -216,18 +209,18 @@ class ViewOptions(ItemGroup): # self.toolbar.insert(custom_item, -1) def setup_scale_palette(self): - scale_table = gtk.Table(2, 2, False) - self.x_scale_entry = gtk.Entry() + scale_table = Gtk.Table(2, 2, False) + self.x_scale_entry = Gtk.Entry() self.x_scale_entry.connect('activate', lambda w: self.emit('scale')) self.x_scale_entry.set_size_request(90, -1) - self.y_scale_entry = gtk.Entry() + self.y_scale_entry = Gtk.Entry() self.y_scale_entry.connect('activate', lambda w: self.emit('scale')) self.y_scale_entry.set_size_request(90, -1) - x_scale_label = gtk.Label(_('X scale')) + x_scale_label = Gtk.Label(label=_('X scale')) x_scale_label.set_alignment(0, .5) - y_scale_label = gtk.Label(_('Y scale')) + y_scale_label = Gtk.Label(label=_('Y scale')) y_scale_label.set_alignment(0, .5) scale_table.attach(x_scale_label, 0, 1, 0, 1, xpadding=5) scale_table.attach(self.x_scale_entry, 1, 2, 0, 1) @@ -237,46 +230,46 @@ class ViewOptions(ItemGroup): return scale_table -class Options(ItemBox): - __gsignals__ = {'append-function': (gobject.SIGNAL_RUN_LAST, - gobject.TYPE_INT, +class Options(itembox.ItemBox): + __gsignals__ = {'append-function': (GObject.SignalFlags.RUN_LAST, + GObject.TYPE_INT, tuple()), - 'remove-function': (gobject.SIGNAL_RUN_LAST, - gobject.TYPE_INT, + 'remove-function': (GObject.SignalFlags.RUN_LAST, + GObject.TYPE_INT, tuple()), - 'color-updated': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_PYOBJECT,)), - 'evaluate': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING,)), - 'save-png': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_STRING,))} + 'color-updated': (GObject.SignalFlags.RUN_FIRST, + None, + (GObject.TYPE_PYOBJECT,)), + 'evaluate': (GObject.SignalFlags.RUN_FIRST, + None, + (GObject.TYPE_STRING,)), + 'save-png': (GObject.SignalFlags.RUN_FIRST, + None, + (GObject.TYPE_STRING,))} def __init__(self, activity): - ItemBox.__init__(self, activity) + itembox.ItemBox.__init__(self, activity) self.activity = activity - self.basic = BasicOptions(activity, self, + self.basic = basic_options.BasicOptions(activity, self, [(_('_image'), 'image/x-generic', 'image/*', _('Images'))]) #activity_button.page.share.hide() self.view = ViewOptions(self) - self.ghost = GhostGroup(self, _('F_unction')) - add_function = Item(gtk.STOCK_ADD, True) + self.ghost = itemgroup.GhostGroup(self, _('F_unction')) + add_function = item.Item(Gtk.STOCK_ADD, True) add_function.tooltip = _('Append a new function') add_function.connect('activate', self._append_function_cb) self.ghost.append_item(add_function) - self.remove_function = Item(gtk.STOCK_REMOVE, True) + self.remove_function = item.Item(Gtk.STOCK_REMOVE, True) self.remove_function.tooltip = _('Remove the selected function') self.remove_function.connect('activate', self._remove_function_cb) self.ghost.append_item(self.remove_function) self.remove_function.sensitive = False - self.color_item = ColorItem(activity, True) + self.color_item = coloritem.ColorItem(activity, True) self.color_item.tooltip = _('Plot color') self.color_item.connect('updated', lambda w, color: self.emit('color-updated', @@ -284,24 +277,24 @@ class Options(ItemBox): self.ghost.append_item(self.color_item) # self.setup_help_button() -# separator = gtk.SeparatorToolItem() +# separator = Gtk.SeparatorToolitem.Item() # separator.show() # separator.set_expand(True) # separator.set_draw(False) # self.toolbar.insert(separator, -1) - evaluate_label = gtk.Label('x = ') + evaluate_label = Gtk.Label(label='x = ') evaluate_label.show() - self.evaluate_entry = gtk.Entry() + self.evaluate_entry = Gtk.Entry() self.evaluate_entry.set_size_request(150, -1) self.evaluate_entry.connect('changed', lambda w: self.emit('evaluate', w.get_text())) self.evaluate_entry.show() - hbox = gtk.HBox() + hbox = Gtk.HBox() hbox.pack_start(evaluate_label, False, False, 0) hbox.pack_start(self.evaluate_entry, True, True, 0) hbox.show() - evaluate_entry_item = ShortContentItem(activity, + evaluate_entry_item = shortcontentitem.ShortContentItem(activity, 'graph-plotter-evaluate', True) evaluate_entry_item.separator = self.ghost.append_separator(True) stock.register('graph-plotter-evaluate', _('_Evaluate'), @@ -309,7 +302,7 @@ class Options(ItemBox): evaluate_entry_item.set_stock_id('graph-plotter-evaluate') evaluate_entry_item.content = hbox self.ghost.append_item(evaluate_entry_item) - self.help = Help(self) + self.help = helper.Help(self) def _append_function_cb(self, widget): number = self.emit('append-function') @@ -17,6 +17,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. + service_name = 'org.sugarlabs.GraphPlotter' import os @@ -29,12 +30,21 @@ if int(os.environ['INFO_L10N']): gettext.textdomain(service_name) _ = gettext.gettext +import sweetener +if sweetener.GTK == 3: + from gi.repository import GLib +else: + import glib as GLib DOCUMENT = 0 CONFIG = 1 io_mode = DOCUMENT name = _('Graph Plotter') + +GLib.set_prgname(name) +GLib.set_application_name(name) + generic_name = _('Mathematical Function Plotter') lower_name = 'graph-plotter' copyright = 'Copyright © 2012 Daniel Francis' @@ -16,6 +16,6 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -from sugar.activity import bundlebuilder +from sugar3.activity import bundlebuilder bundlebuilder.start() diff --git a/style.css b/style.css new file mode 100644 index 0000000..65cd12a --- /dev/null +++ b/style.css @@ -0,0 +1,21 @@ +.toolbar SugarRadioToolButton *, +SugarPaletteWindowWidget SugarRadioToolButton *, +SugarPaletteWindowWidget GtkToolButton .button { + background-color: transparent; + border-radius: 0px; + padding: 0px; +} + + +.toolbar SugarRadioToolButton *:active, +SugarPaletteWindowWidget SugarRadioToolButton *:active { + background-color: #808080; + border-radius: 10px; +} + +/* +.scale { + -GtkScale-slider-length: 30; + -GtkRange-slider-width: 30; +} +*/
\ No newline at end of file diff --git a/sugar/sweetener.py b/sugar/sweetener.py new file mode 100644 index 0000000..3189627 --- /dev/null +++ b/sugar/sweetener.py @@ -0,0 +1,29 @@ +# Copyright (C) 2013 S. Daniel Francis <francis@sugarlabs.org> +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. + +# GTK = 2 +# from sweetenergtk2 import * + +# Use False and import Gtk2 by uncommenting the lines. +if True: + try: + import sugar3 + GTK = 3 + from sweetenergtk3 import * + except ImportError: + GTK = 2 + from sweetenergtk2 import * diff --git a/sugar/sweetenergtk2 b/sugar/sweetenergtk2 -Subproject 9c5b89b28c94b7ec0a99f61c8b6e0df1b033fcb +Subproject 3ee30e1a171d48b3c8ff2eeac5e12ad4528490a diff --git a/sugar/sweetenergtk3 b/sugar/sweetenergtk3 -Subproject 13886fdb54b1fc392110cac0e075e2a7411332c +Subproject 2cf30f7665d8b3c0a1fe977b248d7ff07e9f398 |