def get_picture(self, jobject_id): """return picture surface from journal, given jobject_id""" try: ds_obj = datastore.get(jobject_id) except Exception, e: print ("get filename from id error: %s" % e) return None
def update_entry(self): needs_update = False if self.selected_journal_entry is None: return object_id = self.selected_journal_entry.object_id jobject = datastore.get(object_id) old_title = jobject.metadata.get('title', None) if old_title != self.title_entry.props.text: jobject.metadata['title'] = self.title_entry.props.text jobject.metadata['title_set_by_user'] = '******' self.update_log_entries += '\n' + _('Entry title changed to %s') % self.title_entry.props.text needs_update = True old_tags = jobject.metadata.get('tags', None) new_tags = self.tags_textview.props.buffer.props.text if old_tags != new_tags: jobject.metadata['tags'] = new_tags self.update_log_entries += '\n' + _('Entry %s tags updated.') % self.title_entry.props.text needs_update = True old_description = jobject.metadata.get('description', None) new_description = self.description_textview.props.buffer.props.text if old_description != new_description: jobject.metadata['description'] = new_description self.update_log_entries += '\n' + _('Entry %s description updated.') % self.title_entry.props.text needs_update = True if needs_update: datastore.write(jobject, update_mtime=False, reply_handler=self.datastore_write_cb, error_handler=self.datastore_write_error_cb) self.btn_save.props.sensitive = False
def selection_journal_cb(self, selection): self.btn_delete.props.sensitive = True tv = selection.get_tree_view() model = tv.get_model() sel = selection.get_selected() if sel: model, iter = sel jobject = model.get_value(iter,COLUMN_JOBJECT) jobject = datastore.get(jobject.object_id) self.selected_journal_entry = jobject self.set_form_fields(jobject) if jobject.metadata['mime_type'] .startswith('image/') \ and jobject.metadata['mime_type'] != 'image/vnd.djvu': self.btn_resize.show() self.resize_width_entry.show() filename = jobject.get_file_path() im = pygame.image.load(filename) image_width, image_height = im.get_size() self.dimension_label.set_text(str(image_width) + "x" + str(image_height)) self.dimension_label.show() else: self.btn_resize.hide() self.resize_width_entry.hide() self.dimension_label.hide() self.selected_path = model.get_path(iter)
def imgbrowse(): global imgs #set up pageview to show images in image #imgs is a list of tuples: (fn, src)) imgs = [] #get paths to images in image folder d = IMAGEPATH print 'imgbrowse: ', len(d.files()), len(d.files('*.png')) for f in d.files('*.png'): imgs.append((f.name, f, 's')) for f in d.files('*.jpg'): imgs.append((f.name, f, 's')) #get objects from the local datastore print 'imgbrowse: get objects from the local datastore' ds_objects, num_objects = datastore.find( {'mime_type': ['image/png', 'image/jpeg', 'image/svg']}) print 'imgbrowse: ', num_objects for f in ds_objects: obj = datastore.get(f.object_id) pth = path(obj.get_file_path()) print 'imgbrowse: ', obj.get_file_path() imgs.append((pth.name, obj, 'd')) f.destroy() print 'imgbrowse: call pageview' vw.pageview(imgs, setnewimg, "images")
def __init__(self, object_id=None, file_name=None, default_color=None): self._logger = logging.getLogger("bundle.BundleActivity") self._logger.setLevel(logging.DEBUG) # Show ALL messages self.owner_icon_color = default_color activityRegistry = ActivityRegistry() if object_id: self.object_id = object_id jobject = datastore.get(object_id) if jobject: try: self.mime_type = jobject.metadata["mime_type"] self.title = jobject.metadata["title"] self.activity = jobject.metadata["activity"] activity_info = activityRegistry.get_activity(self.activity) if activity_info: self.icon_path = activity_info.icon if jobject.metadata.has_key("icon-color"): self._logger.debug("The key icon-color exists: %s", jobject.metadata.has_key("icon-color")) self.icon_color = jobject.metadata["icon-color"] self.mtime = jobject.metadata["mtime"] except Exception, e: self._logger.error("key errors in there:", str(e)) jobject.destroy()
def create_preview(self, object_id): jobject = datastore.get(object_id) if jobject.metadata.has_key('preview'): preview = jobject.metadata['preview'] if preview is None or preview == '' or preview == 'None': if jobject.metadata['mime_type'].startswith('image/'): filename = jobject.get_file_path() self.show_image(filename) return if jobject.metadata['mime_type'] == 'application/x-cbz': filename = jobject.get_file_path() fname = self.extract_image(filename) self.show_image(fname) os.remove(fname) return if jobject.metadata.has_key('preview') and \ len(jobject.metadata['preview']) > 4: if jobject.metadata['preview'][1:4] == 'PNG': preview_data = jobject.metadata['preview'] else: import base64 preview_data = base64.b64decode(jobject.metadata['preview']) loader = gtk.gdk.PixbufLoader() loader.write(preview_data) scaled_buf = loader.get_pixbuf() loader.close() self.image.set_from_pixbuf(scaled_buf) self.image.show() else: self.image.clear() self.image.show()
def clipbrowse(): global clips #set up pageview to show audio clips in sound (and later the journal) #clips is a list of tuples: (src, fn) clips = [] #get paths to sound clips in sound folder d = SOUNDPATH print 'clipbrowse: ', len(d.files()), len(d.files('*.ogg')) for f in d.files('*.ogg'): clips.append((f.name, f, 's')) print 'clipbrowse: ', f.name #get objects from the local datastore print 'clipbrowse: get objects from the local datastore' ds_objects, num_objects = datastore.find( {'mime_type': ['application/ogg', 'audio/ogg', 'audio/mp3']}) print 'clipbrowse: ', num_objects for f in ds_objects: obj = datastore.get(f.object_id) pth = path(obj.get_file_path()) if len(pth) > 0: clips.append((pth.name, obj, 'd')) print 'clipbrowse:', pth.name f.destroy() print 'clipbrowse: call pageview' pv.pageview(clips, setnewclip, "audio clips")
def delete_entry(self, widget): treeView = self.viewer.get_treeView() treeselection = treeView.get_selection() model, selection = treeselection.get_selected() row = model[selection] ds_object = datastore.get(row[0]) ds_object.destroy() datastore.delete(ds_object.object_id) model.remove(selection)
def getMediaFromDatastore(id): mediaObject = None try: mediaObject = datastore.get(id) finally: if (mediaObject == None): return None return mediaObject
def _datastore_updated_cb(self, uid): logging.debug("_datastore_updated_cb: %r" % uid) if uid in self._dict: jobject = datastore.get(uid) index = self._array.index(self._dict[uid]) self._array[index].destroy() self._array[index] = jobject self._dict[uid] = jobject self.emit("modified")
def _datastore_updated_cb(self, uid): logging.debug('_datastore_updated_cb: %r' % uid) if uid in self._dict: jobject = datastore.get(uid) index = self._array.index(self._dict[uid]) self._array[index].destroy() self._array[index] = jobject self._dict[uid] = jobject self.emit('modified')
def _datastore_updated_cb(self, uid): logging.debug('_datastore_updated_cb: %r' % uid) if self._dict.has_key(uid): jobject = datastore.get(uid) index = self._array.index(self._dict[uid]) self._array[index].destroy() self._array[index] = jobject self._dict[uid] = jobject self.emit('modified')
def datastore_created_cb(self, uid): new_jobject = datastore.get(uid) iter = self.ls_journal.append() title = new_jobject.metadata['title'] self.ls_journal.set(iter, COLUMN_TITLE, title) mime = new_jobject.metadata['mime_type'] self.ls_journal.set(iter, COLUMN_MIME, mime) self.ls_journal.set(iter, COLUMN_JOBJECT, new_jobject) size = self.get_size(new_jobject) / 1024 self.ls_journal.set(iter, COLUMN_SIZE, size)
def _save_descriptions_cb(self, button=None): ''' Find the object in the datastore and write out the changes to the decriptions. ''' for s in self.slides: if not s.owner: continue jobject = datastore.get(s.uid) jobject.metadata['description'] = s.desc datastore.write(jobject, update_mtime=False, reply_handler=self.datastore_write_cb, error_handler=self.datastore_write_error_cb)
def selection_journal_cb(self, selection): self.btn_delete.props.sensitive = True tv = selection.get_tree_view() model = tv.get_model() sel = selection.get_selected() if sel: model, iter = sel jobject = model.get_value(iter, COLUMN_JOBJECT) jobject = datastore.get(jobject.object_id) self.selected_journal_entry = jobject self.set_form_fields(jobject) self.selected_path = model.get_path(iter)
def getMediaFromDatastore(recd): if not recd.datastoreId: return None if recd.datastoreOb: #already have the object return recd.datastoreOb mediaObject = None try: mediaObject = datastore.get(recd.datastoreId) finally: return mediaObject
def on_activated(self, widget, row, col): model = widget.get_model() print 'row', model[row][0], model[row][1], model[row][2], model[row][3] title = model[row][1] mime_type = model[row][2] timestamp = model[row][3] object = datastore.get(model[row][0]) fn = object.file_path print 'object filename', path(fn).exists(), fn self.deck.addSlide(fn) self.deck.reload() object.destroy() self.activity.set_screen(0)
def on_activated(self, widget, row, col): print 'cpxo on_activated' model = widget.get_model() print 'row', model[row][0], model[row][1], model[row][2] title = model[row][1] timestamp = model[row][2] object = datastore.get(model[row][0]) fn = object.file_path print 'object filename', path(fn).exists(), fn #open slideshow, set Navigation toolbar current self.activity.read_file(fn) for object in ds_objects: object.destroy() self.activity.set_screen(0)
def on_activated(self, widget, row, col): print "cpxo on_activated" model = widget.get_model() print "row", model[row][0], model[row][1], model[row][2] title = model[row][1] timestamp = model[row][2] object = datastore.get(model[row][0]) fn = object.file_path print "object filename", path(fn).exists(), fn # open slideshow, set Navigation toolbar current self.activity.read_file(fn) for object in ds_objects: object.destroy() self.activity.set_screen(0)
def getMediaFromDatastore( recd ): if (recd.datastoreId == None): return None if (recd.datastoreOb != None): #already have the object return recd.datastoreOb mediaObject = None try: mediaObject = datastore.get( recd.datastoreId ) finally: if (mediaObject == None): return None return mediaObject
def datastore_updated_cb(self, uid): new_jobject = datastore.get(uid) iter = self.ls_journal.get_iter_first() for row in self.ls_journal: jobject = row[COLUMN_JOBJECT] if jobject.object_id == uid: title = jobject.metadata['title'] self.ls_journal.set(iter, COLUMN_TITLE, title) mime = jobject.metadata['mime_type'] self.ls_journal.set(iter, COLUMN_MIME, mime) size = self.get_size(jobject) / 1024 self.ls_journal.set(iter, COLUMN_SIZE, size) iter = self.ls_journal.iter_next(iter) object_id = self.selected_journal_entry.object_id if object_id == uid: self.set_form_fields(new_jobject)
def _add_label(string): if isinstance(string, str) and string[0:8] in ['#smedia_', '#saudio_', '#svideo_', '#sdescr_']: string = string[8:] if HAS_DATASTORE: dsobject = datastore.get(string[8:]) if 'title' in dsobject.metadata: string = dsobject.metadata['title'] else: string = str(string) if string[0:2] == '#s': string = string[2:] string = '"' + string if string.count(' ') > 0: return 'label sentence %s\n' % (string.replace(' ', ' "')) else: return 'label %s' % (string.replace(' ', '_'))
def datastore_deleted_cb(self, uid): self.load_journal_table() object_id = self.selected_journal_entry.object_id try: jobject = datastore.get(object_id) except: if not self.selected_path is None: self.selection_journal.select_path(self.selected_path) else: self.title_entry.set_text('') description_textbuffer = self.description_textview.get_buffer() description_textbuffer.set_text('') tags_textbuffer = self.tags_textview.get_buffer() tags_textbuffer.set_text('') self.btn_save.props.sensitive = False self.btn_delete.props.sensitive = False self.image.clear() self.image.show()
def _add_label(string): if type(string) == str and string[0:8] in [ '#smedia_', '#saudio_', '#svideo_', '#sdescr_' ]: string = string[8:] if HAS_DATASTORE: dsobject = datastore.get(string[8:]) if 'title' in dsobject.metadata: string = dsobject.metadata['title'] else: string = str(string) if string[0:2] == '#s': string = string[2:] string = '"' + string if string.count(' ') > 0: return 'label sentence %s\r' % (string.replace(' ', ' "')) else: return 'label %s' % (string.replace(' ', '_'))
def get_temp_files(self): self._logger.debug("get_temp_files called") for (item) in self.myBundle.objList: if item.status == self.myBundle.notInZip: self._logger.debug("Getting file for object = %s", item.object_id) jobject = datastore.get(item.object_id) filename = jobject.file_path self._logger.debug("Copying file %s", filename) ext = os.path.splitext(filename)[1] self._logger.debug("File extension = %s", ext) f, temp_file = tempfile.mkstemp(ext, prefix= jobject.metadata['title']+"_HASH", dir = self.scratchDir) # the changes to the line above should preserve and uniquify our filenames ~J #Might be more sensible to use the file name, but I think this'll work............... self._logger.debug("Copying %s", jobject.metadata['title']) if (os.path.exists(filename)): shutil.copy(filename, temp_file) self._logger.debug("Copying DONE"); self.myBundle.tempFileList.append((temp_file, jobject.metadata['title'])) else: self._logger.debug("Item %s does not have a file associated", jobject.metadata['title']) jobject.destroy() # this segment right here handles modified archives # basically modification is also handled when we click "Pack" (after adding new items) # just that here we unpack the existing files in the archive to put them in a new archive # file. Files flagged with the "to_delete" flag are not extracted if (self.myBundle.status == self.myBundle.packed): self._logger.debug("Attempting to re-pack the archive") # extract all the files that are not flagged as "TO DELETE" for (item) in self.myBundle.objList: self._logger.debug("Found item with title %s and to_delete %s", item.title, item.to_delete) if ((item.status == self.myBundle.inZip) and (item.to_delete == False)): try: f, temp_file = tempfile.mkstemp(item.ext, prefix= item.title+"_HASH", dir = self.scratchDir) del f; f = open(temp_file, 'wb') f.write(self.myBundle.extractOne(item)) f.close() self.myBundle.tempFileList.append((temp_file, " ")) except Exception, e: self._logger.error("EXCEPTION: %s", str(e))
def update_entry(self): needs_update = False needs_reload = False if self.selected_journal_entry is None: return object_id = self.selected_journal_entry.object_id jobject = datastore.get(object_id) old_title = jobject.metadata.get('title', None) if old_title != self.title_entry.props.text: jobject.metadata['title'] = self.title_entry.props.text jobject.metadata['title_set_by_user'] = '******' needs_update = True needs_reload = True old_tags = jobject.metadata.get('tags', None) new_tags = self.tags_textview.props.buffer.props.text if old_tags != new_tags: jobject.metadata['tags'] = new_tags needs_update = True old_description = jobject.metadata.get('description', None) new_description = self.description_textview.props.buffer.props.text if old_description != new_description: jobject.metadata['description'] = new_description needs_update = True if needs_update: datastore.write(jobject, update_mtime=False, reply_handler=self.datastore_write_cb, error_handler=self.datastore_write_error_cb) if needs_reload: self.load_journal_table() self.btn_save.props.sensitive = False
def get_filename_from_jobject_id(self, id): try: ds_obj = datastore.get(id) except Exception,e: _logger.debug('get filename from id error: %s'%e) return None
def write_file(self, file_path): global SERIALNUMBER global store global online global quitflag f = open(file_path, 'w') f.write('this is a dummy file') f.close() if quitflag: return else: quitflag = True action_request = 5 status = 4 today = strftime(DATEFORMAT)[:10] if online: self.viewer.set_label('closing - online') print 'can_close online' #now the real work begins remove_list = [] wcount = 0 acount = 0 for row in store: self.viewer.set_label('reviewing status: ' + row[0]) #action_request = 0: no action #action_request = +2: download #action_request = +1: upload #action_request = -1: remove if row[status] == 'White': print 'today', today, 'mtime', row[3] if row[3].find(today) < 0: row[action_request] = -1 wcount += 1 if row[status] == 'Red': row[action_request] = +1 if row[action_request] < 0: acount += 1 remove_list.append(row[0]) if online: if row[action_request] == 1 and row[status] == 'Red': #upload it self.viewer.set_label('reviewing status: ' + row[0] + ' upload') mname = row[0] + '.metadata' fname = row[0] srcm = LOCALPATH / mname srcf = LOCALPATH / fname if srcm.exists() and srcf.exists(): pfx = SERIALNUMBER + '@schoolserver:' dst = STOREPATH / SERIALNUMBER cmd = 'scp ' + srcm + ' ' + pfx + dst print 'metadata upload', cmd subprocess.call(cmd, shell=True) cmd = 'scp ' + srcf + ' ' + pfx + dst print 'file upload', cmd subprocess.call(cmd, shell=True) else: print 'upload request but no document', row[1], srcf if row[action_request] > 1 and row[status] == "Green": #download from schoolserver self.viewer.set_label('reviewing status: ' + row[0] + ' download') mname = row[0] + '.metadata' fname = row[0] dst = LOCALPATH pfx = SERIALNUMBER + '@schoolserver:' src = STOREPATH / SERIALNUMBER / mname cmd = 'scp ' + pfx + src + ' ' + dst print 'metadata download', cmd subprocess.call(cmd, shell=True) src = STOREPATH / SERIALNUMBER / fname cmd = 'scp ' + pfx + src + ' ' + dst print 'file download', cmd subprocess.call(cmd, shell=True) if row[action_request] > 1 and row[status] == "cyan": #download from Commons self.viewer.set_label('reviewing status: ' + row[0] + ' download') #if mime_type is activity - install it mname = row[0] + '.metadata' fname = row[0] dst = LOCALPATH pfx = SERIALNUMBER + '@schoolserver:' src = COMMONSPATH / mname cmd = 'scp ' + pfx + src + ' ' + dst print 'metadata download', cmd subprocess.call(cmd, shell=True) src = COMMONSPATH / fname cmd = 'scp ' + pfx + src + ' ' + dst print 'file download', cmd subprocess.call(cmd, shell=True) if row[action_request] == 1 and row[status] == 'cyan': #upload entry to Commons self.viewer.set_label('reviewing status: ' + row[0] + ' upload') #if mime_type is activity - install it mname = row[0] + '.metadata' fname = row[0] dst = COMMONSPATH / mname pfx = SERIALNUMBER + '@schoolserver:' src = LOCALPATH / mname cmd = 'scp ' + src + ' ' + pfx + dst print 'metadata upload', cmd subprocess.call(cmd, shell=True) src = LOCALPATH / fname cmd = 'scp ' + src + ' ' + pfx + dst print 'file upload', cmd subprocess.call(cmd, shell=True) #now remove self.viewer.set_label('removing files ...') print 'removing:' , len(remove_list) print 'white entries:', wcount print 'appended:', acount count = 0 for obj in remove_list: ds_object = datastore.get(obj) if ds_object: ds_object.destroy() datastore.delete(ds_object.object_id) count += 1 else: print 'obj not found', obj txt = 'done ' + str(count) + ' files deleted' self.viewer.set_label(txt) print txt
def update_metadata(self,jobject_id,**kwargs): try: ds_obj = datastore.get(jobject_id) except Exception,e: _logger.debug('update metadata error: %s'%e) return None
def __init__(self, handle, create_jobject=True): """Initialise the Activity handle -- sugar.activity.activityhandle.ActivityHandle instance providing the activity id and access to the presence service which *may* provide sharing for this application create_jobject -- boolean define if it should create a journal object if we are not resuming Side effects: Sets the gdk screen DPI setting (resolution) to the Sugar screen resolution. Connects our "destroy" message to our _destroy_cb method. Creates a base gtk.Window within this window. Creates an ActivityService (self._bus) servicing this application. Usage: If your Activity implements __init__(), it should call the base class __init()__ before doing Activity specific things. """ Window.__init__(self) # process titles will only show 15 characters # but they get truncated anyway so if more characters # are supported in the future we will get a better view # of the processes proc_title = "%s <%s>" % (get_bundle_name(), handle.activity_id) util.set_proc_title(proc_title) self.connect('realize', self.__realize_cb) self.connect('delete-event', self.__delete_event_cb) self._active = False self._activity_id = handle.activity_id self._pservice = presenceservice.get_instance() self.shared_activity = None self._share_id = None self._join_id = None self._updating_jobject = False self._closing = False self._quit_requested = False self._deleting = False self._max_participants = 0 self._invites_queue = [] self._jobject = None self._read_file_called = False self._session = _get_session() self._session.register(self) self._session.connect('quit-requested', self.__session_quit_requested_cb) self._session.connect('quit', self.__session_quit_cb) accel_group = gtk.AccelGroup() self.set_data('sugar-accel-group', accel_group) self.add_accel_group(accel_group) self._bus = ActivityService(self) self._owns_file = False share_scope = SCOPE_PRIVATE if handle.object_id: self._jobject = datastore.get(handle.object_id) self.set_title(self._jobject.metadata['title']) if self._jobject.metadata.has_key('share-scope'): share_scope = self._jobject.metadata['share-scope'] # handle activity share/join mesh_instance = self._pservice.get_activity(self._activity_id, warn_if_none=False) logging.debug("*** Act %s, mesh instance %r, scope %s", self._activity_id, mesh_instance, share_scope) if mesh_instance is not None: # There's already an instance on the mesh, join it logging.debug("*** Act %s joining existing mesh instance %r", self._activity_id, mesh_instance) self.shared_activity = mesh_instance self.shared_activity.connect('notify::private', self.__privacy_changed_cb) self._join_id = self.shared_activity.connect("joined", self.__joined_cb) if not self.shared_activity.props.joined: self.shared_activity.join() else: self.__joined_cb(self.shared_activity, True, None) elif share_scope != SCOPE_PRIVATE: logging.debug("*** Act %s no existing mesh instance, but used to " \ "be shared, will share" % self._activity_id) # no existing mesh instance, but activity used to be shared, so # restart the share if share_scope == SCOPE_INVITE_ONLY: self.share(private=True) elif share_scope == SCOPE_NEIGHBORHOOD: self.share(private=False) else: logging.debug("Unknown share scope %r" % share_scope) if handle.object_id is None and create_jobject: logging.debug('Creating a jobject.') self._jobject = datastore.create() title = _('%s Activity') % get_bundle_name() self._jobject.metadata['title'] = title self.set_title(self._jobject.metadata['title']) self._jobject.metadata['title_set_by_user'] = '******' self._jobject.metadata['activity'] = self.get_bundle_id() self._jobject.metadata['activity_id'] = self.get_id() self._jobject.metadata['keep'] = '0' self._jobject.metadata['preview'] = '' self._jobject.metadata['share-scope'] = SCOPE_PRIVATE if self.shared_activity is not None: icon_color = self.shared_activity.props.color else: client = gconf.client_get_default() icon_color = client.get_string('/desktop/sugar/user/color') self._jobject.metadata['icon-color'] = icon_color self._jobject.file_path = '' # Cannot call datastore.write async for creates: # https://dev.laptop.org/ticket/3071 datastore.write(self._jobject)
def __init__(self, handle, create_jobject=True): """Initialise the Activity handle -- sugar.activity.activityhandle.ActivityHandle instance providing the activity id and access to the presence service which *may* provide sharing for this application create_jobject -- boolean define if it should create a journal object if we are not resuming Side effects: Sets the gdk screen DPI setting (resolution) to the Sugar screen resolution. Connects our "destroy" message to our _destroy_cb method. Creates a base gtk.Window within this window. Creates an ActivityService (self._bus) servicing this application. Usage: If your Activity implements __init__(), it should call the base class __init()__ before doing Activity specific things. """ # Stuff that needs to be done early icons_path = os.path.join(get_bundle_path(), 'icons') gtk.icon_theme_get_default().append_search_path(icons_path) sugar_theme = 'sugar-72' if 'SUGAR_SCALING' in os.environ: if os.environ['SUGAR_SCALING'] == '100': sugar_theme = 'sugar-100' # This code can be removed when we grow an xsettings daemon (the GTK+ # init routines will then automatically figure out the font settings) settings = gtk.settings_get_default() settings.set_property('gtk-font-name', '%s %f' % (style.FONT_FACE, style.FONT_SIZE)) settings.set_property('gtk-theme-name', sugar_theme) settings.set_property('gtk-icon-theme-name', 'sugar') settings.set_property( 'gtk-icon-sizes', 'gtk-large-toolbar=%s,%s' % (style.STANDARD_ICON_SIZE, style.STANDARD_ICON_SIZE)) Window.__init__(self) if 'SUGAR_ACTIVITY_ROOT' in os.environ: # If this activity runs inside Sugar, we want it to take all the # screen. Would be better if it was the shell to do this, but we # haven't found yet a good way to do it there. See #1263. self.connect('window-state-event', self.__window_state_event_cb) screen = gtk.gdk.screen_get_default() screen.connect('size-changed', self.__screen_size_changed_cb) self._adapt_window_to_screen() # process titles will only show 15 characters # but they get truncated anyway so if more characters # are supported in the future we will get a better view # of the processes proc_title = '%s <%s>' % (get_bundle_name(), handle.activity_id) util.set_proc_title(proc_title) self.connect('realize', self.__realize_cb) self.connect('delete-event', self.__delete_event_cb) self._active = False self._activity_id = handle.activity_id self.shared_activity = None self._join_id = None self._updating_jobject = False self._closing = False self._quit_requested = False self._deleting = False self._max_participants = 0 self._invites_queue = [] self._jobject = None self._read_file_called = False self._session = _get_session() self._session.register(self) self._session.connect('quit-requested', self.__session_quit_requested_cb) self._session.connect('quit', self.__session_quit_cb) accel_group = gtk.AccelGroup() self.set_data('sugar-accel-group', accel_group) self.add_accel_group(accel_group) self._bus = ActivityService(self) self._owns_file = False share_scope = SCOPE_PRIVATE if handle.object_id: self._jobject = datastore.get(handle.object_id) if 'share-scope' in self._jobject.metadata: share_scope = self._jobject.metadata['share-scope'] if 'launch-times' in self._jobject.metadata: self._jobject.metadata['launch-times'] += ', %d' % \ int(time.time()) else: self._jobject.metadata['launch-times'] = \ str(int(time.time())) self.shared_activity = None self._join_id = None if handle.object_id is None and create_jobject: logging.debug('Creating a jobject.') self._jobject = self._initialize_journal_object() if handle.invited: wait_loop = gobject.MainLoop() self._client_handler = _ClientHandler( self.get_bundle_id(), partial(self.__got_channel_cb, wait_loop)) # FIXME: The current API requires that self.shared_activity is set # before exiting from __init__, so we wait until we have got the # shared activity. http://bugs.sugarlabs.org/ticket/2168 wait_loop.run() else: pservice = presenceservice.get_instance() mesh_instance = pservice.get_activity(self._activity_id, warn_if_none=False) self._set_up_sharing(mesh_instance, share_scope) if not create_jobject: self.set_title(get_bundle_name()) return if self.shared_activity is not None: self._jobject.metadata['title'] = self.shared_activity.props.name self._jobject.metadata['icon-color'] = \ self.shared_activity.props.color else: self._jobject.metadata.connect('updated', self.__jobject_updated_cb) self.set_title(self._jobject.metadata['title']) bundle = get_bundle_instance(get_bundle_path()) self.set_icon_from_file(bundle.get_icon())
def get(uid): return datastore.get(uid)
def get_selected_object(self): if self._object_id is None: return None else: return datastore.get(self._object_id)
def __init__(self, handle): #handle object contains command line inputs to this activity self.handle = handle _logger.debug('Activity id:%s.Object id: %s. uri:%s' % (handle.activity_id, handle.object_id, handle.uri)) self.passed_in_ds_object = None if handle.object_id and handle.object_id != '': self.passed_in_ds_object = datastore.get(handle.object_id) if self.passed_in_ds_object: d = self.passed_in_ds_object.metadata #log_dict(d,'initial datastore metadata ==>:') else: ds_object = self.get_new_dsobject() if hasattr(ds_object, 'get_object_id'): handle.object_id = ds_object.get_object_id() else: handle.object_id = ds_object.object_id _logger.debug( 'no initial datastore object id passed in via handle') #Save a global poiinter so remote procedure calls can communicate with pydebug global pydebug_instance pydebug_instance = self start_clock = time.clock() #init variables self.make_paths() self.save_icon_clicked = False self.source_directory = None self.data_file = None self.help = None self.help_x11 = None self.dirty = False self.sock = None #self.last_filename = None self.debug_dict = {} self.activity_dict = {} self.manifest_treeview = None #set up to recognize an re-display of playpen #self.set_title(_('PyDebug Activity')) self.ds = None #datastore pointer self._logger = _logger self.traceback = 'Context' self.abandon_changes = False self.delete_after_load = None self.find_window = None self.icon_outline = 'icon_square' self.icon_window = None self.last_icon_file = None self.activity_data_changed = False self.icon_basename = None #sugar 0.82 has a different way of getting colors and dies during init unless the following self.profile = profile.get_profile() self.profile.color = XoColor() #get the persistent data across all debug sessions and start using it self.get_config() #give the server a chance to get started so terminal can connect to it self.non_blocking_server() #glib.idle_add(self.non_blocking_server) """ if self.request_new_jobject and self.debug_dict.get('jobject_id','') != '': self.request_new_jobject = False #keep on using the same journal entry if self.debug_dict.get('jobject_id','') != '': handle.object_id = self.debug_dict.get('jobject_id','') """ # init the Classes we are subclassing _logger.debug('about to init superclass activity. Elapsed time: %f'%\ (time.clock()-start_clock)) Activity.__init__(self, handle, create_jobject=False) """ if self.request_new_jobject: #check to see if the object was created if self._jobject: self.debug_dict['jobject_id'] = str(self._jobject.object_id) else: _logger.debug('failed to create jobject in Activity.__init__') """ self.connect('realize', self.realize_cb) self.accelerator = gtk.AccelGroup() self.add_accel_group(self.accelerator) #set up the PANES for the different functions of the debugger _logger.debug('about to set up Menu panes. Elapsed time: %f' % (time.clock() - start_clock)) self.panes = {} PANES = ['TERMINAL', 'EDITOR', 'PROJECT', 'HELP'] for i in range(len(PANES)): self.panes[PANES[i]] = i #toolbox needs to be available during init of modules self.toolbox = pytoolbar.ActivityToolbox(self) self.toolbox.connect_after('current_toolbar_changed', self._toolbar_changed_cb) self.toolbox.set_current_toolbar(self.panes['TERMINAL']) ######################################################################################### #init the sub functions TerminalGui.__init__(self, self, self.toolbox) EditorGui.__init__(self, self) ProjectGui.__init__(self, self) self.help = Help(self) self.util = Utilities(self) ######################################################################################### #if first time run on this machine, set up home directory if not os.path.isfile(os.path.join(self.debugger_home, '.bashrc')): self.setup_home_directory() # setup the search options self.s_opts = SearchOptions( where=S_WHERE.file, use_regex=False, ignore_caps=True, replace_all=False, #defaults to avoid creating #a new SearchOptions object for normal searches #should never be changed, just make a copy like: #SearchOptions(self.s_opts, forward=False) forward=True, stay=False) self.safe_to_replace = False #get the sugar version (major, minor, micro, release) = self._activity.util.sugar_version() _logger.debug('sugar version major:%s minor:%s micro:%s release:%s' % (major, minor, micro, release)) if not minor: minor = 70 self.sugar_minor = minor ######################################################################################### _logger.debug( 'All app objects created. about to set up Display . Elapsed time: %f' % (time.clock() - start_clock)) self.canvas_list = [] self.canvas_list.append(self._get_terminal_canvas()) self.canvas_list.append(self._get_edit_canvas()) self.canvas_list.append(self._get_project_canvas()) self.canvas_list.append(self._get_help_canvas()) nb = gtk.Notebook() nb.show() nb.set_show_tabs(False) for c in self.canvas_list: nb.append_page(c) self.pydebug_notebook = nb #the following call to the activity code puts our notebook under the stock toolbar self.set_canvas(nb) helpbar = self.help.get_help_toolbar() self.toolbox.add_toolbar(_('Edit'), self.get_editbar()) self.toolbox.add_toolbar(_('Project'), self.get_projectbar()) self.toolbox.add_toolbar(_('Help'), self.help.get_help_toolbar()) self.set_toolbox(self.toolbox) self.toolbox.show() #set which PANE is visible initially self.set_visible_canvas(self.panes['PROJECT']) self.set_toolbar(self.panes['PROJECT']) _logger.debug('about to setup_project_page. Elapsed time: %f' % (time.clock() - start_clock)) self.setup_project_page() _logger.debug( 'about Returned from setup_project_page. Elapsed time: %f' % (time.clock() - start_clock)) #get the journal datastore information and resume previous activity #self.metadata = self.ds if self.passed_in_ds_object and self.passed_in_ds_object.get_file_path( ): ds_file = self.passed_in_ds_object.get_file_path() else: ds_file = '' _logger.debug('about to call read routine Elapsed time: %f' % (time.clock() - start_clock)) self.read_file(ds_file) _logger.debug('about (end of init) Elapsed time: %f' % (time.clock() - start_clock))
def datastore_updated_cb(self, uid): self.load_journal_table() object_id = self.selected_journal_entry.object_id jobject = datastore.get(object_id) self.set_form_fields(jobject)
def __init__(self, handle, create_jobject=True): """Initialise the Activity handle -- sugar.activity.activityhandle.ActivityHandle instance providing the activity id and access to the presence service which *may* provide sharing for this application create_jobject -- boolean define if it should create a journal object if we are not resuming Side effects: Sets the gdk screen DPI setting (resolution) to the Sugar screen resolution. Connects our "destroy" message to our _destroy_cb method. Creates a base gtk.Window within this window. Creates an ActivityService (self._bus) servicing this application. Usage: If your Activity implements __init__(), it should call the base class __init()__ before doing Activity specific things. """ # Stuff that needs to be done early icons_path = os.path.join(get_bundle_path(), 'icons') gtk.icon_theme_get_default().append_search_path(icons_path) sugar_theme = 'sugar-72' if 'SUGAR_SCALING' in os.environ: if os.environ['SUGAR_SCALING'] == '100': sugar_theme = 'sugar-100' # This code can be removed when we grow an xsettings daemon (the GTK+ # init routines will then automatically figure out the font settings) settings = gtk.settings_get_default() settings.set_property('gtk-font-name', '%s %f' % (style.FONT_FACE, style.FONT_SIZE)) settings.set_property('gtk-theme-name', sugar_theme) settings.set_property('gtk-icon-theme-name', 'sugar') settings.set_property('gtk-icon-sizes', 'gtk-large-toolbar=%s,%s' % (style.STANDARD_ICON_SIZE, style.STANDARD_ICON_SIZE)) Window.__init__(self) if 'SUGAR_ACTIVITY_ROOT' in os.environ: # If this activity runs inside Sugar, we want it to take all the # screen. Would be better if it was the shell to do this, but we # haven't found yet a good way to do it there. See #1263. self.connect('window-state-event', self.__window_state_event_cb) screen = gtk.gdk.screen_get_default() screen.connect('size-changed', self.__screen_size_changed_cb) self._adapt_window_to_screen() # process titles will only show 15 characters # but they get truncated anyway so if more characters # are supported in the future we will get a better view # of the processes proc_title = '%s <%s>' % (get_bundle_name(), handle.activity_id) util.set_proc_title(proc_title) self.connect('realize', self.__realize_cb) self.connect('delete-event', self.__delete_event_cb) self._active = False self._activity_id = handle.activity_id self.shared_activity = None self._join_id = None self._updating_jobject = False self._closing = False self._quit_requested = False self._deleting = False self._max_participants = 0 self._invites_queue = [] self._jobject = None self._read_file_called = False self._session = _get_session() self._session.register(self) self._session.connect('quit-requested', self.__session_quit_requested_cb) self._session.connect('quit', self.__session_quit_cb) accel_group = gtk.AccelGroup() self.set_data('sugar-accel-group', accel_group) self.add_accel_group(accel_group) self._bus = ActivityService(self) self._owns_file = False share_scope = SCOPE_PRIVATE if handle.object_id: self._jobject = datastore.get(handle.object_id) if 'share-scope' in self._jobject.metadata: share_scope = self._jobject.metadata['share-scope'] if 'launch-times' in self._jobject.metadata: self._jobject.metadata['launch-times'] += ', %d' % \ int(time.time()) else: self._jobject.metadata['launch-times'] = \ str(int(time.time())) self.shared_activity = None self._join_id = None if handle.object_id is None and create_jobject: logging.debug('Creating a jobject.') self._jobject = self._initialize_journal_object() if handle.invited: wait_loop = gobject.MainLoop() self._client_handler = _ClientHandler( self.get_bundle_id(), partial(self.__got_channel_cb, wait_loop)) # FIXME: The current API requires that self.shared_activity is set # before exiting from __init__, so we wait until we have got the # shared activity. http://bugs.sugarlabs.org/ticket/2168 wait_loop.run() else: pservice = presenceservice.get_instance() mesh_instance = pservice.get_activity(self._activity_id, warn_if_none=False) self._set_up_sharing(mesh_instance, share_scope) if not create_jobject: self.set_title(get_bundle_name()) return if self.shared_activity is not None: self._jobject.metadata['title'] = self.shared_activity.props.name self._jobject.metadata['icon-color'] = \ self.shared_activity.props.color else: self._jobject.metadata.connect('updated', self.__jobject_updated_cb) self.set_title(self._jobject.metadata['title']) bundle = get_bundle_instance(get_bundle_path()) self.set_icon_from_file(bundle.get_icon())
def _prim_add_food(self, name, media, calories, protein, carbohydrates, fiber, fat): # Add a new food item to the palette palette = make_palette('food', colors=["#FFFFFF", "#A0A0A0"], help_string=_('Palette of foods')) # We need to convert the media into two svgs, one for the # palette and one for the block. filepath = None if media is not None and os.path.exists(media.value): filepath = media.value elif self.tw.running_sugar: # datastore object from sugar.datastore import datastore try: dsobject = datastore.get(media.value) except: debug_output("Couldn't find dsobject %s" % (media.value), self.tw.running_sugar) if dsobject is not None: filepath = dsobject.file_path if filepath is None: self.tw.showlabel('nojournal', filepath) return pixbuf = None try: pixbufsmall = gtk.gdk.pixbuf_new_from_file_at_size( filepath, 40, 40) pixbufoff = gtk.gdk.pixbuf_new_from_file_at_size(filepath, 40, 40) except: self.tw.showlabel('nojournal', filepath) debug_output("Couldn't open food image %s" % (filepath), self.tw.running_sugar) return def _draw_pixbuf(cr, pixbuf, x, y, w, h): # Build a gtk.gdk.CairoContext from a cairo.Context to access # the set_source_pixbuf attribute. cc = gtk.gdk.CairoContext(cr) cc.save() # center the rotation on the center of the image cc.translate(x + w / 2., y + h / 2.) cc.translate(-x - w / 2., -y - h / 2.) cc.set_source_pixbuf(pixbuf, x, y) cc.rectangle(x, y, w, h) cc.fill() cc.restore() if self.tw.running_sugar: path = os.path.join(get_path(self.tw.activity, 'instance'), 'output.svg') else: path = TMP_SVG_PATH svg_surface = cairo.SVGSurface(path, 40, 40) cr_svg = cairo.Context(svg_surface) _draw_pixbuf(cr_svg, pixbufsmall, 0, 0, 40, 40) cr_svg.show_page() svg_surface.flush() svg_surface.finish() destination = os.path.join(self.tw.path, 'plugins', 'food', 'images', name.encode('ascii') + 'small.svg') check_output(['mv', path, destination], 'problem moving %s to %s' % (path, destination)) pixbufsmall = gtk.gdk.pixbuf_new_from_file_at_size(destination, 40, 40) self.tw.media_shapes[name.encode('ascii') + 'small'] = pixbufsmall svg_surface = cairo.SVGSurface(path, 40, 40) cr_svg = cairo.Context(svg_surface) _draw_pixbuf(cr_svg, pixbufoff, 0, 0, 40, 40) cr_svg.show_page() svg_surface.flush() svg_surface.finish() destination = os.path.join(self.tw.path, 'plugins', 'food', 'images', name.encode('ascii') + 'off.svg') check_output(['mv', path, destination], 'problem moving %s to %s' % (path, destination)) # Now that we have the images, we can make the new block self._make_polynominal(palette, name.encode('ascii'), name, [calories, protein, carbohydrates, fiber, fat], expand=(15, 15)) pixbufoff = gtk.gdk.pixbuf_new_from_file_at_size(destination, 40, 40) self.tw.media_shapes[name.encode('ascii') + 'off'] = pixbufoff # Show the new block self.tw.show_toolbar_palette(palette_name_to_index('food'), regenerate=True) # Finally, we need to save new food item to a database so it # loads next time. food = name.encode('ascii') self.food_dictionary[food] = {} self.food_dictionary[food]['name'] = name self.food_dictionary[food]['calories'] = calories self.food_dictionary[food]['protein'] = protein self.food_dictionary[food]['carbohydrates'] = carbohydrates self.food_dictionary[food]['fiber'] = fiber self.food_dictionary[food]['fat'] = fat path = os.path.join(self.tw.path, 'plugins', 'food', 'food.db') data_to_file(self.food_dictionary, path) return
def get_filename_from_jobject_id(self, id): try: ds_obj = datastore.get(id) except Exception, e: _logger.debug('get filename from id error: %s' % e) return None
def update_metadata(self, jobject_id, **kwargs): try: ds_obj = datastore.get(jobject_id) except Exception, e: _logger.debug('update metadata error: %s' % e) return None
filepath = os.path.join(self.get_activity_root(), 'instance', file_name) self._logger.debug("Saving to %s", archive_name); #shutil.copy(archive_name, filepath) try: os.chmod(archive_name, 0744) self._logger.debug("Trying to put %s in journal", archive_name) self._jobject.file_path = archive_name datastore.write(self._jobject, transfer_ownership=True) self._logger.debug("Written to datastore"); except Exception, e: self._logger.error("Write to datastore failed: %s", str(e)) #self.myBundle.myGUI.list.append( # ["This guy caused a general exception mess", str(e)]) # Sanity check - see if the object can be retrieved from the datastore jobject = datastore.get(self._jobject.object_id) self._logger.debug("Successfully retrieved archive info from data store") self._logger.debug("mime_type: %s file_path: %s", jobject.metadata['mime_type'], jobject.file_path) self.myBundle.objList = [] self.myGUI.list.clear() #f, tmp = tempfile.mkstemp() self.read_file(jobject.get_file_path()) jobject.destroy() def read_file(self, file_path): self._logger.debug("read_file found mime_type %s for file_path %s", self.metadata['mime_type'], file_path); # mime_type "application/x-zebra" indicates that the archive was # not packed before the activity was suspended or terminated, so # the file information is just a list of objects that had been
def save_html(self, tw, embed_flag=True): """ Either save the canvas and code or pictures to HTML """ if embed_flag: HTML_GLUE['img'] = ('<img width="400" height="300" alt=' + \ '"Image" src="data:image/png;base64,\n', '"/>\n') HTML_GLUE['img2'] = ('<img alt="Image" src="data:image/png;' + \ 'base64,\n', '"/>\n') """ If there are saved_pictures, put them into a .html; otherwise, save a screendump and the turtle project code. """ htmlcode = '' if len(tw.saved_pictures) > 0: # saved_picture list is a collection of tuples of either the # image_file or the containing dsobject and an SVG flag for i, (image, svg_flag) in enumerate(tw.saved_pictures): htmlcode += HTML_GLUE['slide'][0] + str(i) htmlcode += HTML_GLUE['slide'][1] + \ HTML_GLUE['div'][0] + \ HTML_GLUE['h1'][0] if tw.running_sugar: from sugar.datastore import datastore dobject = datastore.get(image) # dsobject.object_id image_file = dobject.file_path else: image_file = image if embed_flag: f = open(image_file, 'r') imgdata = f.read() f.close() if svg_flag: tmp = imgdata else: imgdata = image_to_base64( image_file, get_path(tw.activity, 'instance')) tmp = HTML_GLUE['img2'][0] tmp += imgdata tmp += HTML_GLUE['img2'][1] else: if svg_flag: f = open(image_file, 'r') imgdata = f.read() f.close() tmp = imgdata else: tmp = HTML_GLUE['img3'][0] tmp += image_file tmp += HTML_GLUE['img3'][1] htmlcode += tmp + \ HTML_GLUE['h1'][1] + \ HTML_GLUE['div'][1] else: if embed_flag: tmp_file = os.path.join(get_path(tw.activity, 'instance'), 'tmpfile.png') save_picture(self.tw.canvas, tmp_file) imgdata = image_to_base64(tmp_file, get_path(tw.activity, 'instance')) else: imgdata = os.path.join(self.tw.load_save_folder, 'image') self.tw.save_as_image(imgdata) htmlcode += (HTML_GLUE['img'][0] + imgdata + \ HTML_GLUE['img'][1]) htmlcode += HTML_GLUE['div'][0] htmlcode += escape( data_to_string(tw.assemble_data_to_save(False, True))) htmlcode += HTML_GLUE['div'][1] if tw.running_sugar: title = _('Turtle Art') + ' ' + tw.activity.metadata['title'] else: title = _('Turtle Art') header = HTML_GLUE['doctype'] + \ HTML_GLUE['html'][0] style = HTML_GLUE['style'][0] + \ HTML_GLUE['style'][1] if len(tw.saved_pictures) > 0: if tw.saved_pictures[0][1]: header = HTML_GLUE['html_svg'][0] style = COMMENT return header + \ HTML_GLUE['head'][0] + \ HTML_GLUE['meta'] + \ HTML_GLUE['title'][0] + \ title + \ HTML_GLUE['title'][1] + \ style + \ HTML_GLUE['head'][1] + \ HTML_GLUE['body'][0] + \ htmlcode + \ HTML_GLUE['body'][1] + \ HTML_GLUE['html'][1]
def save_logo(tw): """ Set up the Turtle Art color palette and color processing. """ color_processing = "\ to tasetpalette :i :r :g :b :myshade \r\ make \"s ((:myshade - 50) / 50) \r\ ifelse lessp :s 0 [ \r\ make \"s (1 + (:s *0.8)) \r\ make \"r (:r * :s) \r\ make \"g (:g * :s) \r\ make \"b (:b * :s) \r\ ] [ \ make \"s (:s * 0.9) \r\ make \"r (:r + ((99-:r) * :s)) \r\ make \"g (:g + ((99-:g) * :s)) \r\ make \"b (:b + ((99-:b) * :s)) \r\ ] \ setpalette :i (list :r :g :b) \r\ end \r\ \ to rgb :myi :mycolors :myshade \r\ make \"myr first :mycolors \r\ make \"mycolors butfirst :mycolors \r\ make \"myg first :mycolors \r\ make \"mycolors butfirst :mycolors \r\ make \"myb first :mycolors \r\ make \"mycolors butfirst :mycolors \r\ tasetpalette :myi :myr :myg :myb :myshade \r\ output :mycolors \r\ end \r\ \ to processcolor :mycolors :myshade \r\ if emptyp :mycolors [stop] \r\ make \"i :i + 1 \r\ processcolor (rgb :i :mycolors :myshade) :myshade \r\ end \r\ \ to tasetshade :shade \r\ make \"myshade modulo :shade 200 \r\ if greaterp :myshade 99 [make \"myshade (199-:myshade)] \r\ make \"i 7 \r\ make \"mycolors :colors \r\ processcolor :mycolors :myshade \r\ end \r\ \ to tasetpencolor :c \r\ make \"color (modulo (round :c) 100) \r\ setpencolor :color + 8 \r\ end \r\ \ make \"colors [ \ 99 0 0 99 5 0 99 10 0 99 15 0 99 20 0 \ 99 25 0 99 30 0 99 35 0 99 40 0 99 45 0 \ 99 50 0 99 55 0 99 60 0 99 65 0 99 70 0 \ 99 75 0 99 80 0 99 85 0 99 90 0 99 95 0 \ 99 99 0 90 99 0 80 99 0 70 99 0 60 99 0 \ 50 99 0 40 99 0 30 99 0 20 99 0 10 99 0 \ 0 99 0 0 99 5 0 99 10 0 99 15 0 99 20 \ 0 99 25 0 99 30 0 99 35 0 99 40 0 99 45 \ 0 99 50 0 99 55 0 99 60 0 99 65 0 99 70 \ 0 99 75 0 99 80 0 99 85 0 99 90 0 99 95 \ 0 99 99 0 95 99 0 90 99 0 85 99 0 80 99 \ 0 75 99 0 70 99 0 65 99 0 60 99 0 55 99 \ 0 50 99 0 45 99 0 40 99 0 35 99 0 30 99 \ 0 25 99 0 20 99 0 15 99 0 10 99 0 5 99 \ 0 0 99 5 0 99 10 0 99 15 0 99 20 0 99 \ 25 0 99 30 0 99 35 0 99 40 0 99 45 0 99 \ 50 0 99 55 0 99 60 0 99 65 0 99 70 0 99 \ 75 0 99 80 0 99 85 0 99 90 0 99 95 0 99 \ 99 0 99 99 0 90 99 0 80 99 0 70 99 0 60 \ 99 0 50 99 0 40 99 0 30 99 0 20 99 0 10] \r\ make \"shade 50 \r\ tasetshade :shade \r" bs = tw.just_blocks() code = "" stack_count = 0 show = 0 # These flags are used to trigger the prepending of additional procedures. random = False fillscreen = False setcolor = False setxy = False setxy2 = False pensize = False setpensize = False arc = False heap = False write = False minus = False division = False image = False """ Walk through the code, substituting UCB Logo for Turtle Art primitives. """ for b in bs: this_stack = "" data = walk_stack(tw, b) # We need to catch several special cases: stacks, random, etc. stack = False namedstack = False namedbox = False refstack = False refbox = False myvar = "" for d in data: if type(d) == type((1, 2)): (d, b) = d if type(d) is float: if namedbox: myvar += str(d) myvar += " " elif write: this_stack += "labelsize " this_stack += str(d) write = False else: this_stack += str(d) elif show == 2: # Use title for Journal objects if d[0:8] == '#smedia_': try: dsobject = datastore.get(d[8:]) this_stack += dsobject.metadata['title'] dsobject.destroy() except: this_stack += str(d) else: this_stack += str(d) show = 0 else: # Translate some Turtle Art primitives into UCB Logo if namedstack: this_stack += "to " this_stack += d[2:].replace(' ', '_') this_stack += "\r" stack = True namedstack = False elif namedbox: if d[0:2] == "#s": this_stack += "make \"" this_stack += d[2:].replace(' ', '_') this_stack += " " this_stack += myvar namedbox = False myvar = "" else: myvar += d elif refstack: this_stack += d[2:].replace(' ', '_') this_stack += " " refstack = False elif refbox: this_stack += ":" this_stack += d[2:].replace(' ', '_') refbox = False elif d == "stack": refstack = True elif d == "box": refbox = True elif d == "storeinbox": namedbox = True elif d == "storeinbox1": this_stack += "make \"box1" elif d == "box1": this_stack += ":box1" elif d == "storeinbox2": this_stack += "make \"box2" elif d == "box2": this_stack += ":box2" elif d == "shade": this_stack += ":shade" elif d == "setshade": setcolor = True this_stack += "tasetshade" elif d == "color": this_stack += "pencolor" elif d == "nop": this_stack += " " elif d == "start": this_stack += "to start\r" stack = True elif d == "nop1": this_stack += "to stack1\r" stack = True elif d == "nop2": this_stack += "to stack2\r" stack = True elif d == "nop3": namedstack = True elif d == "stopstack": this_stack += "stop" elif d == "clean": this_stack += "clearscreen" elif d == "setxy": setxy = True this_stack += "tasetxypenup" elif d == "setxy2": setxy2 = True this_stack += "tasetxy" elif d == "color": this_stack += ":color" elif d == "plus": this_stack += "sum" elif d == "setcolor": setcolor = True this_stack += "tasetpencolor" elif d == "fillscreen": fillscreen = True setcolor = True this_stack += "tasetbackground" elif d == "random": random = True this_stack += "tarandom" elif d == "pensize": pensize = True this_stack += "tapensize" elif d == "setpensize": setpensize = True this_stack += "tasetpensize" elif d == "arc": arc = True this_stack += "taarc" elif d == "pop": heap = True this_stack += "tapop" elif d == "push": heap = True this_stack += "tapush" elif d == "heap": heap = True this_stack += "taprintheap" elif d == "emptyheap": heap = True this_stack += "taclearheap" elif d == "kbinput": this_stack += "make \"keyboard readchar" elif d == "keyboard": this_stack += ":keyboard" elif d == 'insertimage': image = True elif image: # Skip this arg image = 2 elif image == 2: # Skip this arg image = False elif d[0:2] == "#s": # output single characters as a string if len(d[2:]): this_stack += "\"" this_stack += d[2:] # make a sentence out of everything else else: this_stack += "sentence " this_stack += d[2:].replace("\s", " \"") this_stack += "\r" elif d == "write": this_stack += "label" write = True elif d == 'show' or d == 'showaligned': this_stack += "label" show = 1 elif d == "minus2": this_stack += "taminus" minus = True elif d == "division": this_stack += "quotient" elif d == "lpos": this_stack += str(-tw.canvas.width / (tw.coord_scale * 2)) elif d == "rpos": this_stack += str(tw.canvas.width / (tw.coord_scale * 2)) elif d == "bpos": this_stack += str(-tw.canvas.height / (tw.coord_scale * 2)) elif d == "tpos": this_stack += str(tw.canvas.height / (tw.coord_scale * 2)) elif d in IGNORE: this_stack += ' ' elif show == 1 and d[0:2] == "#s": this_stack += d[2:] # We don't handle depreciated 'template' blocks else: this_stack += d this_stack += " " if stack: stack = False # if it is not a stack, we need to add a "to ta#" label elif len(data) > 0: this_stack = "to ta" + str(stack_count) + "\r" + this_stack stack_count += 1 if len(data) > 0: code += this_stack code += "\rend\r" # We need to define some additional procedures. if minus: # Logo minus only takes one argument. code = "to taminus :y :x\routput sum :x minus :y\rend\r" + code if random: # to avoid negative numbers code = "to tarandom :min :max\r" + \ "output (random (:max - :min)) + :min\rend\r" + code if fillscreen: # Set shade than background color code = "to tasetbackground :color :shade\r" + \ "tasetshade :shade\rsetbackground :color\rend\r" + code if setcolor: # Load the Turtle Art color palette. code = color_processing + code if setpensize: # Set int of pensize code = "to tasetpensize :a\rsetpensize round :a\rend\r" + code if pensize: # Return only the first argument. code = "to tapensize\routput first round pensize\rend\r" + code if setxy2: # Swap and round arguments code = "to tasetxy :x :y\rsetxy :x :y\rend\r" + code if setxy: # Swap and round arguments and add pen up/down code = "to tasetxy :x :y\rpenup\rsetxy :x :y\rpendown\rend\r" + code if arc: # Turtle Art 'arc' needs to be redefined. c = (2 * math.pi)/360 code = "to taarc :a :r\rrepeat round :a [right 1 forward (" + \ str(c) + " * :r)]\rend\r" + code if heap: # Add psuedo 'push' and 'pop' code = "to tapush :foo\rmake \"taheap fput :foo :taheap\rend\r" + \ "to tapop\rif emptyp :taheap [stop]\rmake \"tmp first :taheap\r" + \ "make \"taheap butfirst :taheap\routput :tmp\rend\r" + \ "to taclearheap\rmake \"taheap []\rend\r" + \ "to taprintheap \rprint :taheap\rend\r" + \ "make \"taheap []\r" + code code = "window\r" + code return code