diff options
author | Tony Anderson <tony_anderson@usa.net> | 2009-08-20 05:57:36 (GMT) |
---|---|---|
committer | Tony Anderson <tony_anderson@usa.net> | 2009-08-20 05:57:36 (GMT) |
commit | fc18bb8c4b5262e1a6a1b4483f4855c227b3912b (patch) | |
tree | f26bceb1093fdc0f314ec3808ba26bff5f3b9956 | |
parent | cc347df7be9fa906f8f9f431257edf8c48fdb626 (diff) |
further developlent
-rw-r--r-- | datamanager.py | 384 | ||||
-rwxr-xr-x | icons/btncancel.png | bin | 0 -> 3684 bytes | |||
-rwxr-xr-x | icons/btngo.png | bin | 0 -> 1141 bytes |
3 files changed, 310 insertions, 74 deletions
diff --git a/datamanager.py b/datamanager.py index e6daf25..548b262 100644 --- a/datamanager.py +++ b/datamanager.py @@ -21,12 +21,15 @@ from sugar.activity import activity from sugar.datastore import datastore from sugar.graphics.toolbutton import ToolButton +from sugar.graphics.alert import Alert from sugar.graphics.menuitem import MenuItem import os, sys import subprocess import gtk from path import path +from datetime import datetime +from time import strftime import urllib2 from BeautifulSoup import BeautifulSoup @@ -35,24 +38,32 @@ ACTIVITYPATH = path(activity.get_bundle_path()) DATAPATH = path(activity.get_activity_root()) / "data" WORKPATH = DATAPATH / 'work' KEYPATH = ACTIVITYPATH / '.ssh' -STOREPATH = path("/library/Datastore/") -COMMONSPATH = path("/library/Commons/") +STOREPATH = path("/library/Datastore") +COMMONSPATH = path("/library/Commons") +LOCALPATH = path("/home/olpc/.sugar/default/datastore/store") +DATEFORMAT = "%Y-%m-%d %H:%M:%S" -SERIALNUMBER = '/ofw/serial-number' USAGETOOLBAR = 1 class DataManager(activity.Activity): def __init__(self, handle): + print 'activity started' + global SERIALNUMBER activity.Activity.__init__(self, handle) - print 'activity initialized' self.set_title("Datamanager") f = open('/ofw/serial-number', 'r') t = f.read() - self.xoserial = t[:11] + f.close() + SERIALNUMBER = t[:11] + print 'serial-number', SERIALNUMBER subprocess.call("mkdir -p " + WORKPATH, shell=True) + #set up alert + #self.alert = Alert() + #self.alert.props.title='Updating Datastore' + #self.alert.props.msg='Please be patient - updating store' #Create the usage toolbar - self.usageTB = UsageToolbar(self.xoserial) + self.usageTB = UsageToolbar(self) #Create the standard activity toolbox toolbox = activity.ActivityToolbox(self) toolbox.add_toolbar("Usage", self.usageTB) @@ -60,18 +71,154 @@ class DataManager(activity.Activity): self.set_toolbox(toolbox) toolbox.show() self.viewer = Listview() - self.child.pack_start(self.viewer, True, True, 0) - treeView = self.viewer.get_treeView() - treeView.set_model(self.viewer.create_model(self.usageTB, self.xoserial)) + #treeView = self.viewer.get_treeView() + #treeView.set_model(self.viewer.create_model(self.usageTB)) + #set up main screen + self.main_screen = gtk.VBox() + #self.main_screen.pack_start(self.alert, False, False, 0) + self.main_screen.pack_start(self.viewer, True, True, 0) + self.set_canvas(self.main_screen) + print 'canvas set' self.show_all() + self.viewer.set_label('canvas set') + #self.alert.hide() + + def start_cb(self, widget): + treeView = self.viewer.get_treeView() + treeView.set_model(self.viewer.create_model(self.usageTB)) + + def close_cb(self, widget): + #debug switch to cancel uploads + #return True + global SERIALNUMBER + global store + global online + action_request = 5 + status = 4 + if not online: + return True + self.viewer.set_label('closing - online') + self.logger('') + self.logger('can_close_online') + print 'can_close online' + #now the real work begins + #self.alert.show() + self.logger('showing alert') + remove_list = [] + 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': + row[action_request] = -1 + if row[status] == 'Red': + row[action_request] = +1 + if row[action_request] < 0: + remove_list.append(row[0]) + if row[action_request] == 1: + #upload it + self.viewer.set_label('reviewing status: ' + row[0] + ' upload') + self.logger('upload' + row[0] + '.metadata') + mname = row[0] + '.metadata' + fname = row[0] + src = LOCALPATH / mname + pfx = SERIALNUMBER + '@schoolserver:' + dst = STOREPATH / SERIALNUMBER + cmd = 'scp ' + src + ' ' + pfx + dst + print 'metadata upload', cmd + self.logger('call scp') + subprocess.call(cmd, shell=True) + self.logger('metadata uploaded') + src = LOCALPATH / fname + cmd = 'scp ' + src + ' ' + pfx + dst + if src.exists(): + print 'file upload', cmd + subprocess.call(cmd, shell=True) + self.logger('file uploaded') + else: + print 'src path does not exist', src + if row[action_request] > 1 and row[status] == "light green": + #download from schoolserver + self.viewer.set_label('reviewing status: ' + row[0] + ' download') + self.logger('download ' + row[0] ) + 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) + self.logger('metadata downloaded') + src = STOREPATH / SERIALNUMBER / fname + cmd = 'scp ' + pfx + src + ' ' + dst + subprocess.call(cmd, shell=True) + self.logger('file downloaded') + if row[action_request] > 1 and row[status] == "cyan": + #download from Commons + self.viewer.set_label('reviewing status: ' + row[0] + ' download') + self.logger('download from Commons: ' + row[0]) + #if mime_type is activity - install it + mname = row[0] + '.metadata' + fname = row[0] + dst = LOCALPATH + pfx = SERIALNUMBER + '@schoolserver:' + src = COMMONSPATH / SERIALNUMBER / mname + cmd = 'scp ' + pfx + src + ' ' + dst + print 'metadata download', cmd + subprocess.call(cmd, shell=True) + src = COMMONSPATH / SERIALNUMBER / fname + cmd = 'scp ' + pfx + src + ' ' + dst + subprocess.call(cmd, shell=True) + #now remove + self.logger('now remove') + try: + ds_objects,num_objects = datastore.find(dict()) + except: + print 'datastore.find failed', sys.exc_info()[0] + num_objects = 0 + #self.logger(str(num_objects) + ', ' + str(len(remove_list))) + self.logger('datastore.find complete') + print 'remove_list', len(remove_list), remove_list + for i in xrange(0, num_objects, 1): + ds_objects[i].destroy() + obj = ds_objects[i].object_id + self.viewer.set_label('checking files ' + obj) + if str(obj) in remove_list: + datastore.delete(obj) + self.logger(obj + ' deleted') + txt = 'deleted ' + obj + self.viewer.set_label('checking files ' + obj + ' deleted') + #self.remove_alert(self.alert) + self.logger('done') + self.viewer.set_label('done') + return + + def logger(self, log): + l = '' + logpth = path('/tmp/log') + if logpth.exists(): + f = open(logpth,'r') + l = f.read() + f.close() + l = l + log + '\n' + if len(log) == 0: + l = '' + f = open(logpth, 'w') + f.write(l) + f.close() # based on PyGTK tutorial by jan bodnar, zetcode.com, February 2009 class Listview(gtk.VBox): def __init__(self): + global online print 'Listview init' gtk.VBox.__init__(self) self.connect("destroy", gtk.main_quit) self.online = False + online = False sw = gtk.ScrolledWindow() sw.set_shadow_type(gtk.SHADOW_ETCHED_IN) sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) @@ -98,49 +245,103 @@ class Listview(gtk.VBox): def get_treeView(self): return self.treeView - def create_model(self, tb, xoserial): + def set_label(self, txt): + self.label.set_text(txt) + + def create_model(self, tb): global online + global store + global SERIALNUMBER + action_request = 5 + status = 4 #object is object_id, str = title, str = mime_type or activity, - #str is color of col 1, str is source color of col 0 - store = gtk.ListStore(object, str, str, str, str) + #str is color of col 1 (status), str is source color of col 0 (source) + store = gtk.ListStore(object, str, str, str, str, int) #let's display objects from the schoolserver #temp for testing url = "http://schoolserver/Commons/" - response = urllib2.urlopen(url) + try: + response = urllib2.urlopen(url) + except: + response = None if response: self.online = True - self.addentries(store, response, "Blue", xoserial) - url = "http://schoolserver/Datastore/" + xoserial - response = urllib2.urlopen(url) + online = True + self.addentries(store, response, "cyan") + url = "http://schoolserver/Datastore/" + SERIALNUMBER + try: + response = urllib2.urlopen(url) + except: + response = None if response: - print 'response' self.online = True - self.addentries(store, response, "Green", xoserial) + online = True + self.addentries(store, response, "light green") if self.online: print 'online' else: tb.item2.remove(tb.fuelguage2) tb.lbl2.set_text("not connected") #objects from the local datastore - results, count = datastore.find(dict()) - print 'number of datastore items', count - for f in results: - obj = datastore.get(f.object_id) - f.destroy() - if len(obj.get_file_path()) > 0: - color1 = "Red" - color2 = "Green" - else: - color1 = "White" - color2 = "Green" - itm = obj.metadata['mime_type'] - if len(itm) <= 0: - itm = obj.metadata['activity'] - store.append([obj, obj.metadata['title'], obj.metadata['mime_type'], color1, color2 ]) + #new strategy - get directly - not through datastore + #we want to compare items in store with items in LOCALPATH + #if there is a match - set status + storelist = [] + for row in store: + storelist.append(row[0]) + fn = row[0] + '.metadata' + pth = LOCALPATH / fn + if pth.exists(): + if row[status] == 'cyan': + row[status] = 'Blue' + else: + row[status] = 'Green' + for f in LOCALPATH.files(): + #is this file already on the schoolserver? + if f.namebase not in storelist and f.ext == '.metadata': + m = open(f, 'r') + metadata = eval(m.read()) + m.close() + obj = f.namebase + try: + title = metadata['title'] + except: + try: + title = metadata['title:text'] + except: + title = 'not given' + try: + mime_type = metadata['mime_type'] + except: + mime_type = '' + if len(mime_type) <= 0: + try: + mime_type = metadata['activity'] + except: + mime_type = 'not given' + try: + mtime = metadata['mtime'] + except: + mtime = "" + #tm = datetime.fromtimestamp(mtime) + #date = tm.strftime(DATEFORMAT) + temp = mtime.replace('T',' ') + pos = mtime.find('.') + date = temp[:pos] + fpath = LOCALPATH / obj + if fpath.exists(): + color = 'Red' + else: + color = 'White' + store.append([obj, title, mime_type, date, color, 0]) + store.set_sort_column_id(3, gtk.SORT_DESCENDING) print 'return store' return store - def addentries(self, store, response, color, xoserial): + def addentries(self, store, response, source): + global SERIALNUMBER + print 'addentries:', SERIALNUMBER, source + treeView = self.get_treeView() soup = BeautifulSoup(response) entry_candidates = soup.findAll('a') for entry in entry_candidates: @@ -148,57 +349,67 @@ class Listview(gtk.VBox): pos = t.find('metadata') if pos > 0: pos2 = t.find('href=') - print color, t[pos2+6:pos+8] obj = t[pos2+6:pos-1] fn = t[pos2+6:pos+8] - if color == "green": + if source == "blue": pth = COMMONSPATH / fn else: - pth = STOREPATH / xoserial / fn - cmd = "sftp " + xoserial + "@schoolserver: " + pth - print 'get metadata:', cmd - subprocess.call(cmd, shell=True, cwd=WORKPATH) + pth = STOREPATH / SERIALNUMBER / fn + cmd = "scp " + SERIALNUMBER + "@schoolserver:" + pth + cmd = cmd + " " + WORKPATH + subprocess.call(cmd, shell=True) pth = WORKPATH / fn f = open(pth, 'r') t = f.read() f.close() - metadata = dict(t) - title = metadata['title'] - activity = metadata['activity'] + subprocess.call("rm -rf pth", shell=True) + metadata = eval(t) + try: + title = metadata['title'] + except: + try: + title = metadata['title:text'] + except: + title = '' mime_type = metadata['mime_type'] - store.append([obj, title, mime_type, color, color]) - print 'new row', store[len(store) - 1] + mtime = metadata['mtime'].replace('T',' ') + pos = mtime.find('.') + date = mtime[:pos] + store.append([obj, title, mime_type, date, source, 0]) + treeView.set_model(store) def create_columns(self, treeView): + status = 4 rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Title", rendererText, text=1) - column.add_attribute(rendererText, "cell-background", 3) - column.set_sort_column_id(0) + column.add_attribute(rendererText, "cell-background", status) + column.set_sort_column_id(1) treeView.append_column(column) rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Mime_type", rendererText, text=2) - column.set_sort_column_id(1) + column.set_sort_column_id(2) + treeView.append_column(column) + + rendererText = gtk.CellRendererText() + column = gtk.TreeViewColumn("Date", rendererText, text=3) + column.set_sort_column_id(3) treeView.append_column(column) def on_activated(self, widget, row, col): + #what we really want to do + #is define a request to upload/remove/download an entry + print 'on_activated', widget, row, col model = widget.get_model() - model[row][3] = "cyan" obj = model[row][0] - pth = obj.get_file_path() - print 'pth', pth - if len(pth) > 0: - f = open(pth,'r') - text = f.read() - f.close() - tpllist = [] - metakeys = obj.metadata.keys() - for metakey in metakeys: - metavalue = obj.metadata[metakey] - tpllist.append((metakey, metavalue)) - metadata = dict(tpllist) + fn = obj + '.metadata' + pth = LOCALPATH / fn + print 'on_activated:', pth + f = open(pth,'r') + metadata = eval(f.read()) + f.close() tstr = "" for k, v in metadata.iteritems(): @@ -208,14 +419,15 @@ class Listview(gtk.VBox): except: tstr = tstr + k + ':' + "" + '\n' self.label.set_text(tstr) + print 'on_activated', tstr class UsageToolbar(gtk.Toolbar): - def __init__(self, xoserial): - + def __init__(self, activity): + global SERIALNUMBER gtk.Toolbar.__init__(self) - self.lbl1 = gtk.Label("XO") + self.lbl1 = gtk.Label("XO ") self.lbl1.show() self.item0 = gtk.ToolItem() self.item0.add(self.lbl1) @@ -223,14 +435,28 @@ class UsageToolbar(gtk.Toolbar): self.fuelguage1 = gtk.ProgressBar(adjustment=None) style = self.fuelguage1.get_style().copy() - style.bg[gtk.STATE_NORMAL] = gtk.gdk.color_parse('Blue') + style.bg[gtk.STATE_NORMAL] = gtk.gdk.color_parse('White') style.bg[gtk.STATE_PRELIGHT] = gtk.gdk.color_parse('Red') self.fuelguage1.set_style(style) - cmd = 'df -h /home/olpc/.sugar/default/datastore' + cmd = 'du -h /home/olpc/.sugar/default/datastore > /tmp/rslt' #need way to return stdout to get rslt - #subprocess.call(cmd, shell=True) - rslt = 0.69 - self.fuelguage1.set_fraction(rslt) + subprocess.call(cmd, shell=True) + f = open('/tmp/rslt','r') + storesize = f.read() + f.close() + print 'du datastore', len(storesize), storesize + cmd = 'df -h > /tmp/rslt1' + subprocess.call(cmd, shell=True) + f = open('/tmp/rslt1', 'r') + t = f.read() + f.close() + print 'df', len(t), t + totalsize = t.split('\n') + t1 = totalsize[1] + pos = t1.find('%') + rslt = t1[pos-4:pos].strip() + print 'rslt', float(rslt) * .01 + self.fuelguage1.set_fraction(float(rslt) * .01) self.fuelguage1.set_orientation(gtk.PROGRESS_LEFT_TO_RIGHT) self.fuelguage1.show() self.item1 = gtk.ToolItem() @@ -241,7 +467,7 @@ class UsageToolbar(gtk.Toolbar): self.spacer.set_expand(True) self.insert(self.spacer, -1) - self.lbl2 = gtk.Label("schoolserver") + self.lbl2 = gtk.Label("Schoolserver ") self.lbl2.show() self.item3 = gtk.ToolItem() self.item3.add(self.lbl2) @@ -249,17 +475,27 @@ class UsageToolbar(gtk.Toolbar): self.fuelguage2 = gtk.ProgressBar(adjustment=None) style = self.fuelguage2.get_style().copy() - style.bg[gtk.STATE_NORMAL] = gtk.gdk.color_parse('Green') + style.bg[gtk.STATE_NORMAL] = gtk.gdk.color_parse('White') style.bg[gtk.STATE_PRELIGHT] = gtk.gdk.color_parse('Red') self.fuelguage2.set_style(style) #need a way to know if schoolserver not online #need a way to return rslt from stdout - cmd = "ssh -i " + KEYPATH + xoserial + "@schoolserver " - cmd = cmd + "du -h /library/datastore/" + xoserial + cmd = "ssh -i " + KEYPATH + SERIALNUMBER + "@schoolserver " + cmd = cmd + "du -h /library/datastore/" + SERIALNUMBER #subprocess.call(cmd, shell=True) - rslt = 0.01 + rslt = 0.1 self.fuelguage2.set_fraction(rslt) self.fuelguage2.set_orientation(gtk.PROGRESS_LEFT_TO_RIGHT) self.item2 = gtk.ToolItem() self.item2.add(self.fuelguage2) self.insert(self.item2, -1) + + self.startbtn = ToolButton('btngo') + self.startbtn.connect('clicked', activity.start_cb) + self.startbtn.show() + self.insert(self.startbtn, -1) + + self.closebtn = ToolButton("btncancel") + self.closebtn.connect('clicked', activity.close_cb) + self.closebtn.show() + self.insert(self.closebtn, -1) diff --git a/icons/btncancel.png b/icons/btncancel.png Binary files differnew file mode 100755 index 0000000..fb13ad5 --- /dev/null +++ b/icons/btncancel.png diff --git a/icons/btngo.png b/icons/btngo.png Binary files differnew file mode 100755 index 0000000..b67609b --- /dev/null +++ b/icons/btngo.png |