Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Francis <francis@sugarlabs.org>2013-01-03 12:05:48 (GMT)
committer Daniel Francis <francis@sugarlabs.org>2013-01-03 12:05:48 (GMT)
commit617dc31a24435bb44df4f019d14a4d3df04e5b76 (patch)
treebb2626f7519f725941d090bb54ef28734c72dcea
parent578e555f7fee57bb941b88ac0bc39c7262ac8dd2 (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.py52
-rw-r--r--activitygtk2.py71
-rw-r--r--activitygtk3.py81
-rw-r--r--[-rwxr-xr-x]application.py230
-rwxr-xr-xapplicationgtk2.py258
-rwxr-xr-xapplicationgtk3.py291
-rw-r--r--desktop/sweetener.py30
m---------desktop/sweetenergtk20
m---------desktop/sweetenergtk30
-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.py10
-rwxr-xr-xsetup.py2
-rw-r--r--style.css21
-rw-r--r--sugar/sweetener.py29
m---------sugar/sweetenergtk20
m---------sugar/sweetenergtk30
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')
diff --git a/info.py b/info.py
index b01899a..9181636 100644
--- a/info.py
+++ b/info.py
@@ -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'
diff --git a/setup.py b/setup.py
index 530f97c..c60f4d0 100755
--- a/setup.py
+++ b/setup.py
@@ -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