Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWalter Bender <walter@sugarlabs.org>2014-01-13 21:07:03 (GMT)
committer Walter Bender <walter@sugarlabs.org>2014-01-13 21:07:03 (GMT)
commit75b8e9fc31c23cab96590dd614b3498d88b85f1b (patch)
treef347c52c57e398cc7c5bbefe572e98a3df0b0e8a
parent90c21ad97df88f84862f4176f747cbe1e0baf480 (diff)
parentec47e8a14c7a12351d510c3feb0b1e37b9d6b90a (diff)
merging icon selection alert
-rw-r--r--Notebook.py93
-rw-r--r--icons/pippy-import_py.svg88
-rw-r--r--icons/pippy-save_library.svg70
-rw-r--r--pippy_app.py282
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)
-