diff options
author | Walter Bender <walter@sugarlabs.org> | 2014-01-13 21:07:03 (GMT) |
---|---|---|
committer | Walter Bender <walter@sugarlabs.org> | 2014-01-13 21:07:03 (GMT) |
commit | 75b8e9fc31c23cab96590dd614b3498d88b85f1b (patch) | |
tree | f347c52c57e398cc7c5bbefe572e98a3df0b0e8a | |
parent | 90c21ad97df88f84862f4176f747cbe1e0baf480 (diff) | |
parent | ec47e8a14c7a12351d510c3feb0b1e37b9d6b90a (diff) |
merging icon selection alert
-rw-r--r-- | Notebook.py | 93 | ||||
-rw-r--r-- | icons/pippy-import_py.svg | 88 | ||||
-rw-r--r-- | icons/pippy-save_library.svg | 70 | ||||
-rw-r--r-- | pippy_app.py | 282 |
4 files changed, 496 insertions, 37 deletions
diff --git a/Notebook.py b/Notebook.py index 3deb3a1..23b0be3 100644 --- a/Notebook.py +++ b/Notebook.py @@ -23,15 +23,28 @@ class TabLabel(Gtk.HBox): ([GObject.TYPE_PYOBJECT])), } - def __init__(self, child, label): + def __init__(self, child, label, tabs): GObject.GObject.__init__(self) self.child = child - self._label = Gtk.Label(label=label) + self.label_text = label + self.tabs = tabs + + self.label_box = Gtk.EventBox() + self._label = Gtk.Label(label=self.label_text) self._label.set_alignment(0, 0.5) - self.pack_start(self._label, True, True, 5) self._label.show() + self.label_box.add(self._label) + self.label_box.connect("button-press-event", self._label_clicked) + self.label_box.show_all() + self.pack_start(self.label_box, True, True, 5) + + self.label_entry = Gtk.Entry() + self.label_entry.connect("activate", self._label_entry_cb) + self.label_entry.connect("focus-out-event", self._label_entry_cb) + self.pack_start(self.label_entry, True, True, 0) + button = ToolButton("close-tab") button.connect('clicked', self.__button_clicked_cb) self.pack_start(button, False, True, 0) @@ -41,6 +54,9 @@ class TabLabel(Gtk.HBox): def set_text(self, title): self._label.set_text(title) + def get_text(self): + return self._label.get_text() + def update_size(self, size): self.set_size_request(size, -1) @@ -53,6 +69,21 @@ class TabLabel(Gtk.HBox): def __button_clicked_cb(self, button): self.emit('tab-close', self.child) + def _label_clicked(self, eventbox, data): + if self.tabs.page_num(self.child) is not self.tabs.get_current_page(): + self.child.grab_focus() + else: + self.label_entry.set_text(self.label_text) + eventbox.hide() + self.label_entry.grab_focus() + self.label_entry.show() + + def _label_entry_cb(self, entry, focus=None): + self.label_text = self.label_entry.get_text() + self.label_box.show_all() + self.label_entry.hide() + self._label.set_text(self.label_text) + """ AddNotebook @@ -85,10 +116,9 @@ class SourceNotebook(AddNotebook): def __init__(self, activity): AddNotebook.__init__(self) self.activity = activity + self.set_scrollable(True) - self.add_tab() - - def add_tab(self, label=None): + def add_tab(self, label=None, buffer_text=None): # Set text_buffer text_buffer = GtkSource.Buffer() @@ -109,6 +139,9 @@ class SourceNotebook(AddNotebook): else: text_buffer.set_highlight_syntax(True) + if buffer_text: + text_buffer.set_text(buffer_text) + # Set up SourceView text_view = GtkSource.View() text_view.set_buffer(text_buffer) @@ -129,12 +162,13 @@ class SourceNotebook(AddNotebook): Gtk.PolicyType.AUTOMATIC) codesw.add(text_view) - tabdex = self.get_n_pages() + tabdex = self.get_n_pages() + 1 if label: - tablabel = TabLabel(codesw, label) + tablabel = TabLabel(codesw, label, self) else: tablabel = TabLabel(codesw, - _("New Source File %d" % tabdex)) + _("New Source File %d" % tabdex), + self) tablabel.connect("tab-close", self._tab_closed_cb) codesw.show_all() index = self.append_page(codesw, @@ -151,6 +185,43 @@ class SourceNotebook(AddNotebook): text_view = tab[0] return text_view + def _purify_file(self, label): + import unicodedata + + if not label.endswith(".py"): + label = label + ".py" + + label = label.replace(" ", "_") + if isinstance(label, unicode): + label = \ + unicodedata.normalize('NFKD', label).encode('ascii', 'ignore') + + return label + + def get_all_data(self): + # Returns all the names of files and the buffer contents too. + names = [] + contents = [] + for i in range(0, self.get_n_pages()): + child = self.get_nth_page(i) + text_buffer = child.get_children()[0].get_buffer() + text = text_buffer.get_text(*text_buffer.get_bounds(), + include_hidden_chars=True) + contents.append(text) + + label = self._purify_file(self.get_tab_label(child).get_text()) + + names.append(label) + + return (names, contents) + + def get_current_file_name(self): + child = self.get_nth_page(self.get_current_page()) + label = self.get_tab_label(child).get_text() + label = self._purify_file(label) + + return label + def child_exited_cb(self, *args): """Called whenever a child exits. If there's a handler, runadd it.""" h, self.activity._child_exited_handler = \ @@ -161,3 +232,7 @@ class SourceNotebook(AddNotebook): def _tab_closed_cb(self, notebook, child): index = self.page_num(child) self.remove_page(index) + try: + del self.activity.session_data[index] + except IndexError: + pass diff --git a/icons/pippy-import_py.svg b/icons/pippy-import_py.svg new file mode 100644 index 0000000..e373d06 --- /dev/null +++ b/icons/pippy-import_py.svg @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="55" + height="55" + viewBox="0 0 55 55" + id="svg2" + xml:space="preserve"><metadata + id="metadata3296"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs + id="defs3294" /><g + transform="translate(-0.81330855,-0.30499076)" + id="g3830"><g + transform="matrix(0.55205508,0,0,0.55205508,75.618464,18.235971)" + id="g4382"><g + transform="translate(-80.093659,12.220029)" + id="g4308" + style="fill:none;stroke:#ffffff;stroke-opacity:1"> + <g + id="g4310" + style="fill:none;stroke:#ffffff;stroke-opacity:1"> + <path + d="m 6.736,49.002 h 24.52 c 2.225,0 3.439,-1.447 3.439,-3.441 v -27.28 c 0,-1.73 -1.732,-3.441 -3.439,-3.441 h -4.389" + id="path4312" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + </g> + </g><g + transform="translate(-80.093659,12.220029)" + id="g4314" + style="fill:none;stroke:#ffffff;stroke-opacity:1"> + <g + id="g4316" + style="fill:none;stroke:#ffffff;stroke-opacity:1"> + <path + d="m 26.867,38.592 c 0,1.836 -1.345,3.201 -3.441,4.047 L 6.736,49.002 V 14.84 l 16.69,-8.599 c 2.228,-0.394 3.441,0.84 3.441,2.834 v 29.517 z" + id="path4318" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + </g> + </g><path + d="m -70.669659,54.827029 c 0,0 -1.351,-0.543 -2.702,-0.543 -1.351,0 -2.703,0.543 -2.703,0.543" + id="path4320" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><path + d="m -70.669659,44.226029 c 0,0 -1.239,-0.543 -2.815,-0.543 -1.577,0 -2.59,0.543 -2.59,0.543" + id="path4322" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><path + d="m -70.669659,33.898029 c 0,0 -1.125,-0.544 -2.927,-0.544 -1.802,0 -2.478,0.544 -2.478,0.544" + id="path4324" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><line + id="line4326" + y2="23.725029" + y1="58.753029" + x2="-66.884659" + x1="-66.884659" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /></g><g + transform="matrix(-0.00197591,-0.99999804,0.99999804,-0.00197591,9.1500435,88.143185)" + id="g4770"><g + transform="translate(34.0803,-1006.42)" + id="g4772"><polyline + id="polyline4774" + points="51.562,15.306 41.17,16.188 42.053,5.794" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round" + transform="matrix(-0.469241,0.469241,-0.469241,-0.469241,66.2906,1019.03)" /><path + d="m 39.363241,1033.1291 -0.05636,9.9115 -8.750608,0.067" + id="path4776" + style="fill:none;stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g></g></g><g + transform="translate(-11.224307,-12.034777)" + id="g4709" + style="fill:none;stroke:#ffffff"><path + d="m 28.090497,40.381834 c 3.974667,-0.06221 9.878139,-1.753708 9.878139,-6.911631 0,-5.73755 -4.497322,-6.751378 -6.645938,-7.265877 -2.341015,-0.560569 -4.551388,-0.765446 -4.645545,-1.7177 -0.161426,-1.632578 0.768742,-2.268447 2.619566,-2.268447 0,0 4.402457,2.26367 8.142826,0.457274 1.05398,-0.509016 2.942197,-2.884533 2.942197,-4.523303 0,-1.639388 -6.094837,-3.533985 -7.944332,-3.533985 -1.850824,0 -3.424821,2.377206 -3.424821,2.377206 -3.700318,0 -7.401302,3.278776 -7.401302,6.557553 0,3.278158 3.417627,6.165937 7.653709,6.85261 1.962616,0.318142 3.729994,1.076753 3.3563,3.065286 -0.303435,1.614661 -1.696316,2.770905 -5.258386,2.736319 -2.749295,-0.02669 -6.417645,0.138525 -8.840139,-1.714654 -1.314772,-1.005784 -1.146531,-3.578075 -1.146531,-3.578075 0,0 -3.4034,0.162415 -2.757976,3.376412 0.965274,4.806741 6.251099,6.204027 13.472233,6.091012 z" + id="path2474-6" + style="fill:none;stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><path + d="M 37.438881,22.676071 C 35.697593,22.498722 33.050146,21.440194 32.481887,19.572788" + id="path2476-1" + style="fill:none;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><circle + cx="35.805" + cy="10.96" + r="1.676" + transform="matrix(0.3489205,0,0,0.32478716,20.448838,13.620467)" + id="circle2478-8" + style="fill:none;stroke:#ffffff;stroke-width:3.42034841;stroke-miterlimit:4;stroke-dasharray:none" /></g></svg>
\ No newline at end of file diff --git a/icons/pippy-save_library.svg b/icons/pippy-save_library.svg new file mode 100644 index 0000000..a814340 --- /dev/null +++ b/icons/pippy-save_library.svg @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="55" + height="55" + viewBox="0 0 55 55" + id="svg2" + xml:space="preserve"><metadata + id="metadata3172"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs + id="defs3170" /><g + transform="translate(4.4279661,-8.8559322)" + id="g3830"><g + transform="matrix(1,0,0,-1,-36.795472,60.940333)" + id="g4770"><g + transform="translate(34.0803,-1006.42)" + id="g4772"><polyline + id="polyline4774" + points="51.562,15.306 41.17,16.188 42.053,5.794" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round" + transform="matrix(-0.469241,0.469241,-0.469241,-0.469241,66.2906,1019.03)" /><path + d="m 39.363241,1033.1291 -0.05636,9.9115 -8.750608,0.067" + id="path4776" + style="fill:none;stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g></g><rect + width="22.489407" + height="18.430876" + x="24.120762" + y="42.415253" + id="rect3176" + style="fill:none;stroke:#ffffff;stroke-width:0.77346295;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><rect + width="22.489407" + height="6.2923727" + x="24.120762" + y="48.241524" + id="rect3178" + style="fill:none;stroke:#ffffff;stroke-width:0.81820756;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g><g + transform="translate(-11.834288,-11.628123)" + id="g4709" + style="fill:none;stroke:#ffffff"><path + d="m 28.090497,40.381834 c 3.974667,-0.06221 9.878139,-1.753708 9.878139,-6.911631 0,-5.73755 -4.497322,-6.751378 -6.645938,-7.265877 -2.341015,-0.560569 -4.551388,-0.765446 -4.645545,-1.7177 -0.161426,-1.632578 0.768742,-2.268447 2.619566,-2.268447 0,0 4.402457,2.26367 8.142826,0.457274 1.05398,-0.509016 2.942197,-2.884533 2.942197,-4.523303 0,-1.639388 -6.094837,-3.533985 -7.944332,-3.533985 -1.850824,0 -3.424821,2.377206 -3.424821,2.377206 -3.700318,0 -7.401302,3.278776 -7.401302,6.557553 0,3.278158 3.417627,6.165937 7.653709,6.85261 1.962616,0.318142 3.729994,1.076753 3.3563,3.065286 -0.303435,1.614661 -1.696316,2.770905 -5.258386,2.736319 -2.749295,-0.02669 -6.417645,0.138525 -8.840139,-1.714654 -1.314772,-1.005784 -1.146531,-3.578075 -1.146531,-3.578075 0,0 -3.4034,0.162415 -2.757976,3.376412 0.965274,4.806741 6.251099,6.204027 13.472233,6.091012 z" + id="path2474-6" + style="fill:none;stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><path + d="M 37.438881,22.676071 C 35.697593,22.498722 33.050146,21.440194 32.481887,19.572788" + id="path2476-1" + style="fill:none;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><circle + cx="35.805" + cy="10.96" + r="1.676" + transform="matrix(0.3489205,0,0,0.32478716,20.448838,13.620467)" + id="circle2478-8" + style="fill:none;stroke:#ffffff;stroke-width:3.42034841;stroke-miterlimit:4;stroke-dasharray:none" /></g><path + d="m 40.317798,36.647247 a 0.46610171,0.52436441 0 1 1 -0.932204,0 0.46610171,0.52436441 0 1 1 0.932204,0 z" + id="path3948" + style="fill:none;stroke:#ffffff;stroke-width:0.77346295;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><path + d="m 40.317798,36.647247 a 0.46610171,0.52436441 0 1 1 -0.932204,0 0.46610171,0.52436441 0 1 1 0.932204,0 z" + transform="translate(0.11652389,6.2341086)" + id="path3948-9" + style="fill:none;stroke:#ffffff;stroke-width:0.77346295;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><path + d="m 40.317798,36.647247 a 0.46610171,0.52436441 0 1 1 -0.932204,0 0.46610171,0.52436441 0 1 1 0.932204,0 z" + transform="translate(0.34957558,12.176905)" + id="path3948-3" + style="fill:none;stroke:#ffffff;stroke-width:0.77346295;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></svg>
\ No newline at end of file diff --git a/pippy_app.py b/pippy_app.py index 0616cac..49ee793 100644 --- a/pippy_app.py +++ b/pippy_app.py @@ -25,6 +25,8 @@ import os import subprocess from random import uniform import locale +import json +import sys import dbus from dbus.mainloop.glib import DBusGMainLoop @@ -43,6 +45,7 @@ from port.style import font_zoom from signal import SIGTERM from gettext import gettext as _ +from sugar3.datastore import datastore from sugar3.activity.widgets import EditToolbar from sugar3.activity.widgets import StopButton from sugar3.activity.activity import get_bundle_path @@ -52,6 +55,7 @@ from sugar3.graphics.alert import Alert from sugar3.graphics.icon import Icon from sugar3.graphics import style from sugar3.graphics.toggletoolbutton import ToggleToolButton +from sugar3.graphics.objectchooser import ObjectChooser from jarabe.view.customizebundle import generate_unique_id @@ -83,13 +87,29 @@ groupthink_mimetype = 'pickle/groupthink-pippy' from Notebook import SourceNotebook +DISUTILS_SETUP_SCRIPT = """#!/usr/bin/python +# -*- coding: utf-8 -*- +from distutils.core import setup +setup(name='{modulename}', + version='1.0', + py_modules=[ + {filenames} + ], + ) +""" # This is .format()'ed with the list of the file names. + class PippyActivity(ViewSourceActivity, groupthink.sugar_tools.GroupActivity): """Pippy Activity as specified in activity.info""" def early_setup(self): - global text_buffer from gi.repository import GtkSource - text_buffer = GtkSource.Buffer() + self.initial_text_buffer = GtkSource.Buffer() + self.loaded_from_journal = False + self.py_file = False + self.loaded_session = [] + self.session_data = [] + + sys.path.append(os.path.join(self.get_activity_root(), "Library")) def initialize_display(self): self._logger = logging.getLogger('pippy-activity') @@ -102,6 +122,18 @@ class PippyActivity(ViewSourceActivity, groupthink.sugar_tools.GroupActivity): separator.show() activity_toolbar.insert(separator, -1) + import_py_button = ToolButton("pippy-import_py") + import_py_button.set_tooltip(_("Import Python File")) + import_py_button.connect("clicked", self._import_py_cb) + import_py_button.show() + activity_toolbar.insert(import_py_button, -1) + + save_as_library = ToolButton("pippy-save_library") + save_as_library.set_tooltip(_("Save this file as a library")) + save_as_library.connect("clicked", self._save_as_library) + save_as_library.show() + activity_toolbar.insert(save_as_library, -1) + export_doc_button = ToolButton('pippy-export_doc') export_doc_button.set_tooltip(_("Export as Pippy Document")) export_doc_button.connect('clicked', self._export_document_cb) @@ -120,6 +152,12 @@ class PippyActivity(ViewSourceActivity, groupthink.sugar_tools.GroupActivity): create_bundle_button.show() activity_toolbar.insert(create_bundle_button, -1) + export_disutils = ToolButton("pippy-create_bundle") + export_disutils.set_tooltip(_("Export as disutils package")) + export_disutils.connect("clicked", self.__export_disutils_cb) + export_disutils.show() + activity_toolbar.insert(export_disutils, -1) + self._edit_toolbar = EditToolbar() edit_toolbar_button = ToolbarButton() @@ -259,6 +297,15 @@ class PippyActivity(ViewSourceActivity, groupthink.sugar_tools.GroupActivity): self.source_tabs = SourceNotebook(self) self.source_tabs.connect("tab-added", self._add_source_cb) + if self.loaded_from_journal and self.py_file: + self.source_tabs.add_tab( + self.initial_title, + self.initial_text_buffer) + elif self.loaded_session: + for name, content in self.loaded_session: + self.source_tabs.add_tab(name, content) + else: + self.source_tabs.add_tab() vpane.add1(self.source_tabs) @@ -387,18 +434,16 @@ class PippyActivity(ViewSourceActivity, groupthink.sugar_tools.GroupActivity): self._reset_vte() self.source_tabs.get_text_view().grab_focus() - def _write_text_buffer(self, filename): - text_buffer = self.source_tabs.get_text_buffer() - start, end = text_buffer.get_bounds() - text = text_buffer.get_text(start, end, True) - - with open(filename, 'w') as f: - # write utf-8 coding prefix if there's not already one - if re.match(r'coding[:=]\s*([-\w.]+)', - '\n'.join(text.splitlines()[:2])) is None: - f.write(PYTHON_PREFIX) - for line in text: - f.write(line) + def _write_all_buffers(self, tmp_dir): + data = self.source_tabs.get_all_data() + zipdata = zip(data[0], data[1]) + for name, content in zipdata: + with open(os.path.join(tmp_dir, name), 'w') as f: + # write utf-8 coding prefix if there's not already one + if re.match(r'coding[:=]\s*([-\w.]+)', + '\n'.join(content.splitlines()[:2])) is None: + f.write(PYTHON_PREFIX) + f.write(content) def _reset_vte(self): self._vte.grab_focus() @@ -434,8 +479,13 @@ class PippyActivity(ViewSourceActivity, groupthink.sugar_tools.GroupActivity): self.outbox.show_all() self.toggle_output.set_active(True) - pippy_app_name = '%s/tmp/pippy_app.py' % self.get_activity_root() - self._write_text_buffer(pippy_app_name) + pippy_tmp_dir = '%s/tmp/' % self.get_activity_root() + self._write_all_buffers(pippy_tmp_dir) + + current_file = os.path.join( + pippy_tmp_dir, + self.source_tabs.get_current_file_name()) + # write activity.py here too, to support pippy-based activities. copy2('%s/activity.py' % get_bundle_path(), '%s/tmp/activity.py' % self.get_activity_root()) @@ -443,7 +493,7 @@ class PippyActivity(ViewSourceActivity, groupthink.sugar_tools.GroupActivity): self._pid = self._vte.fork_command_full( Vte.PtyFlags.DEFAULT, get_bundle_path(), - ["/bin/sh", "-c", "python %s; sleep 1" % pippy_app_name, + ["/bin/sh", "-c", "python %s; sleep 1" % current_file, "PYTHONPATH=%s/library:%s" % (get_bundle_path(), os.getenv("PYTHONPATH", ""))], ["PYTHONPATH=%s/library:%s" % (get_bundle_path(), @@ -459,9 +509,67 @@ class PippyActivity(ViewSourceActivity, groupthink.sugar_tools.GroupActivity): except: pass # process must already be dead. + def _save_as_library(self, button): + import unicodedata + library_dir = os.path.join(get_bundle_path(), "library") + file_name = self.source_tabs.get_current_file_name() + text_buffer = self.source_tabs.get_text_buffer() + content = text_buffer.get_text( + *text_buffer.get_bounds(), + include_hidden_chars=True) + + if not os.path.isdir(library_dir): + os.mkdir(library_dir) + + with open(os.path.join(library_dir, file_name), "w") as f: + f.write(content) + success = True + + if success: + alert = NotifyAlert(5) + alert.props.title = _('Python File added to Library') + IMPORT_MESSAGE = _('The file you selected has been added' + ' to the library. Use "import {importname}"' + ' to import the library for using.') + alert.props.msg = IMPORT_MESSAGE.format(importname=file_name[:-3]) + alert.connect('response', self.remove_alert_cb) + self.add_alert(alert) + def _export_document_cb(self, __): self.copy() + def remove_alert_cb(self, alert, response_id): + self.remove_alert(alert) + + def _import_py_cb(self, button): + chooser = ObjectChooser() + result = chooser.run() + if result is Gtk.ResponseType.ACCEPT: + dsitem = chooser.get_selected_object() + if dsitem.metadata['mime_type'] != "text/x-python": + alert = NotifyAlert(5) + alert.props.title = _('Error importing Python file') + alert.props.msg = _('The file you selected is not a ' + 'Python file.') + alert.connect('response', self.remove_alert_cb) + self.add_alert(alert) + elif dsitem.object_id in self.session_data: + alert = NotifyAlert(5) + alert.props.title = _('Error importing Python file') + alert.props.msg = _('The file you selected is already ' + 'open') + alert.connect('response', self.remove_alert_cb) + self.add_alert(alert) + else: + name = dsitem.metadata['title'] + file_path = dsitem.get_file_path() + content = open(file_path, "r").read() + + self.source_tabs.add_tab(name, content) + self.session_data.append(dsitem.object_id) + + chooser.destroy() + def _create_bundle_cb(self, __): from shutil import rmtree from tempfile import mkdtemp @@ -486,6 +594,19 @@ class PippyActivity(ViewSourceActivity, groupthink.sugar_tools.GroupActivity): alert_icon.props.title = _('Activity icon') alert_icon.props.msg = _('Please select an activity icon.') + self.stopbutton_cb(None) # try stopping old code first. + self._reset_vte() + self.outbox.show_all() + self._vte.feed(_("Creating activity bundle...")) + self._vte.feed("\r\n") + TMPDIR = 'instance' + app_temp = mkdtemp('.activity', 'Pippy', + os.path.join(self.get_activity_root(), TMPDIR)) + sourcefile = os.path.join(app_temp, 'xyzzy.py') + # invoke ourself to build the activity bundle. + self._logger.debug('writing out source file: %s' % sourcefile) +>>>>>>> ec47e8a14c7a12351d510c3feb0b1e37b9d6b90a + def internal_callback(window=None, event=None): icon = "%s/activity/activity-default.svg" % (get_bundle_path()) if window: @@ -534,6 +655,74 @@ class PippyActivity(ViewSourceActivity, groupthink.sugar_tools.GroupActivity): alert_icon.connect('response', alert_response) self.add_alert(alert_icon) + def _write_text_buffer(self, filename): + text_buffer = self.source_tabs.get_text_buffer() + start, end = text_buffer.get_bounds() + text = text_buffer.get_text(start, end, True) + + with open(filename, 'w') as f: + # write utf-8 coding prefix if there's not already one + if re.match(r'coding[:=]\s*([-\w.]+)', + '\n'.join(text.splitlines()[:2])) is None: + f.write(PYTHON_PREFIX) + for line in text: + f.write(line) + + def __export_disutils_cb(self, button): + app_temp = os.path.join(self.get_activity_root(), "instance") + data = self.source_tabs.get_all_data() + for filename, content in zip(data[0], data[1]): + fileobj = open(os.path.join(app_temp, filename), "w") + fileobj.write(content) + fileobj.close() + + filenames = ",".join([("'"+name[:-3]+"'") for name in data[0]]) + + title = self.metadata['title'] + if title is _('Pippy Activity'): + from sugar3.graphics.alert import Alert + from sugar3.graphics.icon import Icon + alert = Alert() + alert.props.title = _('Save as disutils package error') + alert.props.msg = _('Please give your activity a meaningful' + 'name before attempting to save it ' + 'as an disutils package.') + ok_icon = Icon(icon_name='dialog-ok') + alert.add_button(Gtk.ResponseType.OK, _('Ok'), ok_icon) + alert.connect('response', self.dismiss_alert_cb) + self.add_alert(alert) + return + + setup_script = DISUTILS_SETUP_SCRIPT.format(modulename=title, + filenames=filenames) + setupfile = open(os.path.join(app_temp, "setup.py"), "w") + setupfile.write(setup_script) + setupfile.close() + + os.chdir(app_temp) + + output = subprocess.check_output( + [ + "/usr/bin/python", + os.path.join(app_temp, "setup.py"), + "sdist", "-v" + ]) + + # hand off to journal + os.chmod(app_temp, 0777) + jobject = datastore.create() + metadata = { + 'title': '%s disutils bundle' % title, + 'title_set_by_user': '1', + 'mime_type': 'application/x-gzip', + } + for k, v in metadata.items(): + # the dict.update method is missing =( + jobject.metadata[k] = v + tarname = "dist/{modulename}-1.0.tar.gz".format(modulename=title) + jobject.file_path = os.path.join(app_temp, tarname) + datastore.write(jobject) + def _export_example_cb(self, __): # get the name of this pippy program. title = self.metadata['title'] @@ -579,7 +768,6 @@ Do you want to overwrite it?') """Called when we're done building a bundle for a source file.""" from sugar3 import profile from shutil import rmtree - from sugar3.datastore import datastore try: # find the .xo file: were we successful? bundle_file = [f for f in os.listdir(app_temp) @@ -639,11 +827,41 @@ Do you want to overwrite it?') def save_to_journal(self, file_path, cloudstring): _file = open(file_path, 'w') if not self.shared_activity: - self.metadata['mime_type'] = 'text/x-python' - global text_buffer - start, end = text_buffer.get_bounds() - text = text_buffer.get_text(start, end, True) - _file.write(text) + data = self.source_tabs.get_all_data() + zipped_data = zip(data[0], data[1]) + sessionlist = [] + app_temp = os.path.join(self.get_activity_root(), "instance") + tmpfile = os.path.join(app_temp, + "pippy-tempfile-storing.py") + for zipdata, dsid in map(None, zipped_data, self.session_data): + name, content = zipdata + + if dsid is not None: + dsitem = datastore.get(dsid) + __file = open(tmpfile, "w") + __file.write(content) + __file.close() + dsitem.set_file_path(tmpfile) + dsitem.metadata['title'] = name + datastore.write(dsitem) + else: + dsobject = datastore.create() + dsobject.metadata['mime_type'] = 'text/x-python' + dsobject.metadata['title'] = name + __file = open(tmpfile, "w") + __file.write(content) + __file.close() + dsobject.set_file_path(tmpfile) + datastore.write(dsobject) + dsitem = None + + if dsitem is not None: + sessionlist.append([name, dsitem.object_id]) + else: + sessionlist.append([name, dsobject.object_id]) + + self.metadata['mime_type'] = 'application/json' + _file.write(json.dumps(sessionlist)) else: self.metadata['mime_type'] = groupthink_mimetype _file.write(cloudstring) @@ -654,9 +872,19 @@ Do you want to overwrite it?') # discard the '#!/usr/bin/python' and 'coding: utf-8' lines, # if present text = re.sub(r'^' + re.escape(PYTHON_PREFIX), '', text) - global text_buffer - text_buffer.set_text(text) - text_buffer.set_modified(False) + + self.initial_text_buffer = text + self.initial_title = self.metadata['title'] + self.loaded_from_journal = self.py_file = True + + elif self.metadata['mime_type'] == "application/json": + data = json.loads(open(file_path).read()) + for name, dsid in data: + dsitem = datastore.get(dsid) + content = open(dsitem.get_file_path()).read() + self.loaded_session.append([name, content]) + self.session_data.append(dsitem.object_id) + elif self.metadata['mime_type'] == groupthink_mimetype: return open(file_path).read() @@ -757,7 +985,6 @@ def main(): from tempfile import mkdtemp from shutil import copytree, copy2, rmtree from sugar3.activity import bundlebuilder - import sys parser = OptionParser(usage='%prog [options] [title] [sourcefile] [icon]') parser.add_option('-d', '--dir', dest='dir', default='.', metavar='DIR', @@ -877,4 +1104,3 @@ if __name__ == '__main__': main() print(_("done!")) sys.exit(0) - |