[Sugar-devel] [PATCH] adding copy submenu to viewsource

Walter Bender walter at sugarlabs.org
Mon Jun 6 14:26:04 EDT 2011


From: Walter Bender <walter.bender at gmail.com>

---
 src/jarabe/view/Makefile.am     |    1 +
 src/jarabe/view/custombundle.py |  169 +++++++++++++++++++++++++++++++++++++++
 src/jarabe/view/viewsource.py   |   37 +++++++--
 3 files changed, 200 insertions(+), 7 deletions(-)
 create mode 100644 src/jarabe/view/custombundle.py

diff --git a/src/jarabe/view/Makefile.am b/src/jarabe/view/Makefile.am
index 1abea6d..b38b382 100644
--- a/src/jarabe/view/Makefile.am
+++ b/src/jarabe/view/Makefile.am
@@ -3,6 +3,7 @@ sugar_PYTHON =				\
 	__init__.py			\
 	buddyicon.py			\
 	buddymenu.py			\
+	custombundle.py			\
 	keyhandler.py			\
 	launcher.py			\
 	palettes.py			\
diff --git a/src/jarabe/view/custombundle.py b/src/jarabe/view/custombundle.py
new file mode 100644
index 0000000..e61a030
--- /dev/null
+++ b/src/jarabe/view/custombundle.py
@@ -0,0 +1,169 @@
+# Copyright (C) 2011 Walter Bender
+#
+# 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 2 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 St, Fifth Floor, Boston, MA  02110-1301  USA
+
+import os
+import subprocess
+import gtk
+
+import logging
+_logger = logging.getLogger('ViewSource')
+
+CUSTOMICON = 'customize.svg'
+RESCALE = '  <g transform="matrix(0.73,0,0,0.73,7.57,7.96)">\n'
+
+
+def customize_bundle(home_activities, new_bundle_name):
+    ''' Modify bundle_id in new activity.info file. '''
+    fd_old = open(os.path.join(home_activities, new_bundle_name,
+			       'activity', 'activity.info'), 'r')
+    fd_new = open(os.path.join(home_activities, new_bundle_name,
+			       'activity', 'new_activity.info'), 'w')
+    for line in fd_old:
+        tokens = line.split('=')
+	if tokens[0].rstrip() == 'bundle_id':
+            new_bundle_id = tokens[1].strip() + '_my_copy'
+	    fd_new.write('%s = %s\n' % (tokens[0].rstrip(), new_bundle_id))
+	elif tokens[0].rstrip() == 'icon':
+            old_icon_name = tokens[1].strip()
+	    new_icon_name = 'My' + old_icon_name
+	    fd_new.write('%s = %s\n' % (tokens[0].rstrip(), new_icon_name))
+	else:
+            fd_new.write(line)
+    fd_old.close
+    fd_new.close
+    command_line = ['mv', os.path.join(home_activities, new_bundle_name,
+				       'activity', 'new_activity.info'),
+		    os.path.join(home_activities, new_bundle_name,
+				 'activity', 'activity.info')]
+    _logger.debug(subprocess.call(command_line))
+
+    _custom_icon(home_activities, new_bundle_name, old_icon_name,
+		 new_icon_name)
+
+
+def _custom_icon(home_activities, new_bundle_name, old_icon_name,
+                 new_icon_name):
+    ''' Modify new activity icon by overlaying custom icon. '''
+
+    # First, find customize.svg, which will be used as an overlay.
+    for path in gtk.icon_theme_get_default().get_search_path():
+        if os.path.exists(os.path.join(path, 'sugar', 'scalable', 'actions',
+                                       CUSTOMICON)):
+            break
+        else:
+            path = None
+        
+    if path == None:
+        _logger.debug('customize.svg not found')
+        command_line = ['mv', os.path.join(home_activities, new_bundle_name,
+                                           'activity', old_icon_name + '.svg'),
+                        os.path.join(home_activities, new_bundle_name,
+                                     'activity', new_icon_name + '.svg')]
+        _logger.debug(subprocess.call(command_line))
+        return
+
+    # Extract custom_svg, i.e., the 'payload' from the svg file.
+    fd_custom = open(os.path.join(path, 'sugar', 'scalable', 'actions',
+                                CUSTOMICON), 'r')
+
+    custom_svg = ''
+    found_begin_svg_tag = False
+    found_close_tag = False
+    found_end_svg_tag = False
+
+    for line in fd_custom:
+        if not found_begin_svg_tag:
+            if line.count('<svg') > 0:
+                found_begin_svg_tag = True
+                partials = line.split('<svg')
+                found_close_tag, temp_string = _find_and_split(
+                    partials[1], '>', '', None)
+            else:
+                pass
+        elif not found_close_tag:
+            found_close_tag, temp_string = _find_and_split(
+                line, '>', '', None)
+            temp_string = ''
+        elif not found_end_svg_tag:
+            custom_svg += temp_string
+            found_end_svg_tag, temp_string = _find_and_split(
+                line, '</svg>', '', None)
+        else:
+            custom += line
+    fd_custom.close
+ 
+    # Next, modify the old icon by shrinking it and applying the overlay.
+    fd_old = open(os.path.join(home_activities, new_bundle_name, 'activity',
+                             old_icon_name + '.svg'), 'r')
+    fd_new = open(os.path.join(home_activities, new_bundle_name, 'activity',
+                             new_icon_name + '.svg'), 'w')
+
+    found_begin_svg_tag = False
+    found_close_tag = False
+    found_end_svg_tag = False
+
+    for line in fd_old:
+        if not found_begin_svg_tag:
+            if line.count('<svg') > 0:
+                found_begin_svg_tag = True
+                partials = line.split('<svg')
+                fd_new.write(partials[0] + '<svg\n')
+                found_close_tag = _find_and_split(partials[1], '>',
+                                                       RESCALE, fd_new)
+            else:
+                fd_new.write(line)
+        elif not found_close_tag:
+            found_close_tag = _find_and_split(line, '>', RESCALE, fd_new)
+        elif not found_end_svg_tag:
+            found_end_svg_tag = _find_and_split(
+                line, '</svg>', '  </g>\n' + custom_svg, fd_new,
+                insert_before=True)
+        else:
+            fd_new.write(line)
+    fd_old.close
+    fd_new.close
+
+
+def _find_and_split(line, token, insert, fd, insert_before=False):
+    ''' If token is found in line, split line, add insert, and write;
+    else just write. '''
+
+    tmp_string = ''
+
+    if line.count(token) > 0:
+        partials = line.split(token)
+        if insert_before:
+            tmp_string += insert
+            tmp_string += partials[0] + token + '\n'
+        else:
+            tmp_string += partials[0] + token + '\n'
+            tmp_string += insert
+        tmp_string += partials[1]
+        if len(partials) > 2:
+            for i, part in enumerate(partials):
+                if i > 1:
+                    tmp_string += partials[i] + token
+        if fd is None:
+            return True, tmp_string
+        else:
+            fd.write(tmp_string)
+            return True
+    else:
+        if fd is None:
+            return False, line
+        else:
+            fd.write(line)
+            return False
diff --git a/src/jarabe/view/viewsource.py b/src/jarabe/view/viewsource.py
index a9f6e12..5b9293a 100644
--- a/src/jarabe/view/viewsource.py
+++ b/src/jarabe/view/viewsource.py
@@ -16,6 +16,7 @@
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 import os
+import subprocess
 import logging
 from gettext import gettext as _
 
@@ -36,6 +37,7 @@ from sugar.bundle.activitybundle import ActivityBundle
 from sugar.datastore import datastore
 from sugar import mime
 
+from custombundle import customize_bundle
 
 _SOURCE_FONT = pango.FontDescription('Monospace %d' % style.FONT_SIZE)
 
@@ -133,7 +135,7 @@ class ViewSource(gtk.Window):
         command = activity_bundle.get_command()
         if len(command.split(' ')) > 1:
             name = command.split(' ')[1].split('.')[-1]
-            tmp_path = command.split(' ')[1].replace('.', '/')
+            tmppath = command.split(' ')[1].replace('.', '/')
             file_name = tmppath[0:-(len(name) + 1)] + '.py'
             path = os.path.join(activity_bundle.get_path(), file_name)
             self._selected_file = path
@@ -201,7 +203,7 @@ class ViewSource(gtk.Window):
 class DocumentButton(RadioToolButton):
     __gtype_name__ = 'SugarDocumentButton'
 
-    def __init__(self, file_name, document_path, title):
+    def __init__(self, file_name, document_path, title, bundle=False):
         RadioToolButton.__init__(self)
 
         self._document_path = document_path
@@ -218,15 +220,35 @@ class DocumentButton(RadioToolButton):
         self.set_icon_widget(icon)
         icon.show()
 
-        menu_item = MenuItem(_('Keep'))
-        icon = Icon(icon_name='document-save', icon_size=gtk.ICON_SIZE_MENU,
-                    xo_color=XoColor(self._color))
+        if bundle:
+            menu_item = MenuItem(_('Copy'))
+            icon = Icon(icon_name='edit-copy', icon_size=gtk.ICON_SIZE_MENU,
+                        xo_color=XoColor(self._color))
+            menu_item.connect('activate', self.__copy_to_home_cb)
+        else:
+            menu_item = MenuItem(_('Keep'))
+            icon = Icon(icon_name='document-save', icon_size=gtk.ICON_SIZE_MENU,
+                        xo_color=XoColor(self._color))
+            menu_item.connect('activate', self.__keep_in_journal_cb)
+
         menu_item.set_image(icon)
 
-        menu_item.connect('activate', self.__keep_in_journal_cb)
         self.props.palette.menu.append(menu_item)
         menu_item.show()
 
+    def __copy_to_home_cb(self, menu_item):
+        ''' Make a local copy of the activity bundle in
+        $HOME/Activities as MyActivity and change the bundle_id to
+        bundle_id_my_copy'''
+        # TODO: Check to see if MyActivity already exisits
+        home_activities = os.path.join(os.environ['HOME'], 'Activities')
+        new_bundle_name = 'My' + self._document_path.split('/')[-1]
+        command_line = ['cp', '-r', self._document_path,
+                        os.path.join(home_activities, new_bundle_name)]
+        _logger.debug(subprocess.call(command_line))
+
+        customize_bundle(home_activities, new_bundle_name)
+
     def __keep_in_journal_cb(self, menu_item):
         mime_type = mime.get_from_file_name(self._document_path)
         if mime_type == 'application/octet-stream':
@@ -283,7 +305,8 @@ class Toolbar(gtk.Toolbar):
             self._add_separator()
 
         if bundle_path is not None and os.path.exists(bundle_path):
-            activity_button = RadioToolButton()
+            activity_button = DocumentButton(file_name, bundle_path, title,
+                                             bundle=True)
             icon = Icon(file=file_name,
                         icon_size=gtk.ICON_SIZE_LARGE_TOOLBAR,
                         fill_color=style.COLOR_TRANSPARENT.get_svg(),
-- 
1.7.4.4



More information about the Sugar-devel mailing list