You are on page 1of 16

h t t p : / / s e e t a .

i n

Page 1



SocialCalc on Sugar Collaboration over the Mesh Network




h t t p : / / s e e t a . i n

Page 2

Revision Date Authors Descritpion

1.0 October 25, 2009 Vijit Singh Basic Documentation
prepared after
discussion with
Manusheel Gupta
























h t t p : / / s e e t a . i n

Page 3




SOCIALCALC ON SUGAR

INTRODUCTION:

SocialCalc is a spreadsheet activity developed in JavaScript for functioning on
the Sugar environment, OLPCs software paradigm. The Javascript code was initially
coded by Dan Bricklin of Software Garden Inc., for Socialtext Inc. The OLPC part of
the project has been coordinated by Manusheel Gupta, Managing Director of SEETA
(Software for Education, Entertainment and Training Activities), Vijit Singh, Software
Engineer, Products and Services at SEETA, and K.S. Preeti, undergraduate student
from Netaji Subhas Institute of Technology, University of Delhi with guidance from
Walter Bender, Oversight Board Member at Sugar Labs. The XOCom library, which is
used to communicate between Python based Sugar environment and JavaScript based
SocialCalc was developed by Luke Closs from Socialtext Inc. The pie, line and bar
chart tools have been recently developed by Nicholas Doiron, an engineering student
from Carnegie Mellon University, U.S.A. Collaboration over the mesh network has
been developed by Vijit Singh under the guidance of Manusheel Gupta.


FEATURES AND DESIGN GOALS:

The main idea of the Spreadsheet activity for the XO is to include features that
would enable children to make easy use of the typical features of Spreadsheet activities
such as Organization, Tabulation, Graphing and simple Calculations. The main features
of this spreadsheet activity are:



h t t p : / / s e e t a . i n

Page 4
1. Tabulation: The main screen of the SocialCalc showcases the tabulation
features of this activity. It enables the user to enter data in table format, edit the
data using the various edit features such as Cut, Copy, Paste, Fill columns,
Format Painter, Cell mergers, Allignment of texts, Selection of borders, et al.
This gives the user immense independence in choosing the look for the table
data.


2. Organisation: The tabular matter can be organised in several forms. The calls
can be formatted according to borders, colors, alignment, etc. The format of the
data can be of various types such as numbers, text (preceded by a "'" if
necessary to distinguish it from numbers), dates (e.g., "1/2/3"), dollars
("$1,234.50"), time ("3:45"), numbers with fractions ("1 1/2"), and "true",
"false", and "#N/A". A value's type determines its displayed format if there is no
explicit numeric format set for a cell. The program supports a wide variety of
formats (including other currencies) through its custom format functionality.
The activity also facilitates sorting of numeric data. Comments to increase ease
of understanding of data, Names to access data in different modalities,
Clipboard function to load and save data are some of the other features which
make the activity useful.

3. Graphing: In any data related activity, analysis of data holds a very significant
place. Graphs are a very useful and visual way of analysis of numeric data.
SocialCalc supports graphic features. Any number of data can be selected and
represented in the form of Histograms.

4. Calculations: Various mathematical calculations and modifications are possible
on the cell data. A complete list of functions supported has been documented in
the Appendix.

5. Collaboration: Sharing and multi-user editing over the network.


h t t p : / / s e e t a . i n

Page 5
Section I

Brief Overview-

1) SocialCalc before collaboration- Porting SocialCalc on the XO laptop-

Socialcalc which is written initially in JavaScript and and html have been
ported on the xo laptops/ sugar using the Mozilla XPCOM APIs (For details
refer Appendix).
Xocom which is a library for DHTML applications over the XO laptops have
been made over the top of these XPCOM APIs in order to achieve this porting.
In order to display the html page over the xo, mozillas gecko rendering
engine has been used.
In brief the following things have been made to port SocialCalc over the Xo
laptops (file wise description)-
SocialCalcActivity.py- This file contains the basic activity structure of
the Sugar activities. It also contains the code for initializing the gecko
rendering engine.
import hulahop
hulahop.startup(os.path.join(env.get_profile_path(), 'gecko'))
XoCom.py- This is python code of the XoCom library. It is
responsible for the transfer of data from the python part ( Xo part) to
the javascript part (socialcalc part) and vica-versa. Besides, it also
initializes the first url to be shown by the gecko engine and also
initiates some other variables required for proper data transfer.
Xocom.js- This file is the javascript counterpart of the XoCom.py and
is written to receive of data from the python part ( Xo part) to the
javascript part (socialcalc part) and vica-versa. Not just that, as the file
has been written over the jQuery library of javascript, in
synchronization of the socialcalc code, it is also responsible for
handling various mouse and keyboard events.
Some changes have also been made in the html file in order to
integrate graphing tools in the SocialCalc on sugar application.









h t t p : / / s e e t a . i n

Page 6
2) SocialCalc after collaboration

In this section, I am just describing the basic overview about the changes which I have
made in the code in order to achieve collaboration, a much detailed technical
description will be given in the next section. Here are the basic points
Firstly, I created a basic infrastructure which is required by all the sugar
activities to achieve collaboration. These changes were made in the python
part of the code and functions and classes were added so that the data can
reach from one xo laptop to another.
We have used dbus-tubes and telepathy framework in order to achieve
collaboration. This is the most relied system used by sugar activities to
achieve collaboration.
Next, I made changes in the python part of the Xocom library. I enhanced it by
creating a basic infrastructure so that we can not only call functions and send
data from python to the javascript part but we can easily call functions and
send parameters from javascript part to the python part.
In the javascript part of the xocom library , I made equivalent changes so that
javascript part can notify the python part that it needs to send data over the
mesh and some change has been made in the spreadsheet.
Many new XPCOM interfaces and methods were added to achieve the same.
The enhancement of the XOCOM library have not only helped in the
collaboration but it has also made the code robust enough to add many new
features like localization and interoperability.
Besides, the code can also be used as a model to design other javascript and
DHTML applications for the xo laptops.
Besides, I have also made changes in the javascript portion of the original
socialcalc code at certain places which I will explain in detail in the next
section.












h t t p : / / s e e t a . i n

Page 7
Section II

Technical Description-

After pondering a lot about how to explain the changes I have made, I think the best
way would be to explain the changes file-wise. I will take the files one by one and the
then explain the changes I have made and would also paste the relevant code from the
file so that the reader gets well-acquainted with the code as well by the time this
document is finished. So, here goes we into the details-
PYTHON FILES-
1) SocialCalcActivity.py-
Firstly, I defined the some global variables which are required for the basic
collaboration of a sugar activity.
SERVICE = "com.socialtext.SocialCalcActivity"
IFACE = SERVICE
PATH = "/com/socialtext/SocialCalcActivity"
Then, some local variables were also defined in the main class.
self.hellotube = None # Shared session #REQUIRED
self.initiating = False
self.pservice = presenceservice.get_instance()
owner = self.pservice.get_owner()
self.owner = owner
self.connect('shared', self._shared_cb)
self.connect('joined', self._joined_cb)
Now, functions were added in the main socialcalc class which actually creates
the dbus-tube and are also responsible for sharing them over the mesh
network. Here are the added functions.
def _shared_cb(self, activity):
def _sharing_setup(self):
def _list_tubes_reply_cb(self, tubes):
def _list_tubes_error_cb(self, e):
def _joined_cb(self, activity):
def _new_tube_cb(self, id, initiator, type, service, params, state):
def _buddy_joined_cb (self, activity, buddy):
def _buddy_left_cb (self, activity, buddy):
def _get_buddy(self, cs_handle):
Now, a new class was added in order to achieve the transfer of data over the
mesh network. It is this class whose methods are called in by the other python
modules in order to send and receive data via mesh network. This class in turn
calls the functions as described above to transfer the data.
class TextSync(ExportedGObject):


h t t p : / / s e e t a . i n

Page 8
The functions added in the class are-
def __init__(self, tube, is_initiator, get_buddy , read_shared,
write_shared,xocom):
def participant_change_cb(self, added, removed):
@signal(dbus_interface=IFACE, signature='')
def Hello(self):
This is the signal function which sent over basic signals over the mesh.
@method(dbus_interface=IFACE, in_signature='s',
out_signature='')
def World(self, text):
This is the world method which initializes variables on the joining xo
from the already present xo.
def add_hello_handler(self):
def hello_cb(self, sender=None):
def sendtext_cb(self, text, sender=None):
This is the handler to receive sent text.
@signal(dbus_interface=IFACE, signature='as')
def SendText(self, text):
This is the signal which actually transfers data over the dbus-tubes.
Changes in the definitions of the signals and methods were made in
order to achieve collaboration. These changes were different from
other XO activities and required proper understanding of the dbus and
telepathy framework.
I also added 2 read and write functions which were based on the basic sugar
read and write functions, however, they were used to transfer data only when
some change was made in the spreadsheet, in order to transfer that change to
other xos as well.
def write_shared(self):
def read_shared(self,content):
Another function to take control functioning of the above functions was added.
def control_sending_text(self,array='', topic='', str=''):













h t t p : / / s e e t a . i n

Page 9
2) XOCom.py-
A new class was added in the file. The purpose of this class to set an observer
in the python part of the code so that the javascript part can notify the python
part whenever some change has been made in the javascript part, so that the
python part can transfer this change to the other xos collaborated with the
application. In this way the synchronization b/w the spreadsheets on different
xos are maintained.
The class been made on the nsIObserverClass interface of the XPCOM library.
The name of this kind of signal was given as "xo-message2".
The code for the class is as follows-
class Observer():
_com_interfaces_ = components.interfaces.nsIObserver
def __init__(self,control_sending_text):
print 'just initiating'
self.control_sending_text=control_sending_text
self.content_observe=''
def observe(self, service, topic, extra):
print 'getting the signal in the python part'
if topic=="xo-message2": #it is for the execute command type'
service = service.QueryInterface(components.interfaces.nsIMutableArray)
if service.length:
iter = service.enumerate()
result = iter.getNext()
result = result.QueryInterface(components.interfaces.nsISupportsString)
self.content_observe=result.toString()
print 'the content in observer of xocom is ', self.content_observe
saveundostring=iter.getNext()
saveundostring=saveundostring.QueryInterface(components.interfaces.nsISupportsString)
saveundostring=saveundostring.toString()
sendingArray=['execute',self.content_observe,saveundostring]
self.control_sending_text(array=sendingArray,str='execute')
Another subroutine was added in the file to share data over the browser. It was
based on the Mozilla APIs and Mozilla XPCOM data types were used in the
process. Here is the code-
def send_to_browser_shared(self,command):
if command[0]=='execute':
array =
components.classes["@mozilla.org/array;1"].createInstance(components.interfaces.nsIMutable
Array)
str = components.classes["@mozilla.org/supports-
string;1"].createInstance(components.interfaces.nsISupportsString)
str.data = command[1]
array.appendElement(str, False)
str2 = components.classes["@mozilla.org/supports-
string;1"].createInstance(components.interfaces.nsISupportsString)
str2.data = command[2]
array.appendElement(str2, False)

observerService = components.classes["@mozilla.org/observer-service;1"]


h t t p : / / s e e t a . i n

Page 10
ob_serv = observerService.getService(components.interfaces.nsIObserverService);
if not array.length:
print 'no need of sending anywhere , array is empty'
ob_serv.notifyObservers(array, "xo-message", 'execute');
Another function to set the observer was also added. Here is the code-
def set_observer(self):
#try:
print 'enter: set_observer'
observerService = components.classes["@mozilla.org/observer-service;1"]
ob_serv = observerService.getService(components.interfaces.nsIObserverService);
observer=Observer(self.control_sending_text)
ob_serv.addObserver(observer,"xo-message2",False);
print 'exit: set_observer'



Javascript FILES-
1) xocom.js-
This file is made on the top of the jQuery library. It is also responsible for
handling various mouse and keyboard events besides creating the inter-
connection b/w the python and the javascript part.
New variables were defined in the XO structure-
errorMessage: 'everything is fine till now',
flagShared:false, //To check that the activity is shared or not, its value will be changed
to true by the check string sent by the xocom.py
callbacks: { },
Changes were made in the main observe function of the XO structure to
facilitate data reading and conversion to and from the data types of the
XPCOM and the javascript. Here is the revised code-
observe: function(req_obj,topic,command) {
now = new Date().getTime()
XO.set_status("(" + now + ") Handling " + command)
try {
// We need access to use the XPCom functions below
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect")
req_obj = req_obj.QueryInterface(Components.interfaces.nsIMutableArray)
if (req_obj.length){XO.errorMessage=XO.errorMessage+'..........the length of req_obj
is 0';}

//would be unwrapping the array thing here only if it is not related to the sharing
command, else will handle in the called function itself
var handle_sharing=false;
if (command=='execute')
{
XO.errorMessage=XO.errorMessage+' \n calling the command from observer'
return_value = XO.callbacks[command](req_obj) || ''
handle_sharing=true;
XO.errorMessage=XO.errorMessage+' \n returned successfully in the observer
after the call'
}



h t t p : / / s e e t a . i n

Page 11
if (handle_sharing==false)
{
// Unwrap the XPCom objects to get at the data passed to us

var command_arg = undefined
if (req_obj.length) {
var iter = req_obj.enumerate()
xp_arg = iter.getNext()
xp_arg = xp_arg.QueryInterface(Components.interfaces.nsISupportsString)
command_arg = xp_arg.toString()
}


// Execute the registered callback method
return_value = XO.callbacks[command](command_arg) || ''


// Wrap the return value back into the XPCom object
var result = Components.classes["@mozilla.org/supports-string;1"].createInstance(
Components.interfaces.nsISupportsString)
result.data = return_value
req_obj.clear()
req_obj.appendElement(result, false)
XO.set_status("(" + now + ") Handled " + command + ": (" + return_value + ")")
}
}
//end of if for handle sharing

catch (err) {
XO.errorMessage='here lies the problem'+err;
alert('here lies the problem'+err)
}
}
Changes were made in some other parts of the code in order to register the
functions with the callback mechanism and also to add the observer function.
The revised code is as follows-
XO.register('check',function(){XO.flagShared=true;}) //changed the value of the shared
flag


try {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var observerService = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
observerService.addObserver(XO.observer, 'xo-message', false);
}
catch(err) { //NOTE: This part should be removed from here as there is no element named
as xo-status, it has been taken from the OnePageWiki portion
// Wait a bit to show this error, so the page has time to load up.
setTimeout( function() {
jQuery('#xo-status', 'JS Error: ' + err);
}, 1000)
}



h t t p : / / s e e t a . i n

Page 12

3) socialcalc-3.js-

The major changes in this file were made in the ScheduleSheetCommands
function. The purpose of this function is to schedule when a certain sheet
command should be sent for execution. As, when a change is made in a
spreadsheet the string to apply that change always first comes to the
ScheduleSheetCommands function, so we have revised this code, so that
whenever the activity is collaborated, then this string should also be sent to the
python part, which sent it to other xos over the mesh network.
Here is the revised code of the function-
SocialCalc.ScheduleSheetCommands = function(sheet, cmdstr, saveundo,
notSendOverMesh) {

if (notSendOverMesh!=true)
{ if (window.XO.flagShared==true) //it checks whether the activity is shared till now or
not
{
if (saveundo==true) //to transfer the saveundo thing to the other xo
{var saveundostring='true'}
else {var saveundostring='false'}

netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var observerService = Components.classes["@mozilla.org/observer-
service;1"].getService(Components.interfaces.nsIObserverService);
array =
Components.classes["@mozilla.org/array;1"].createInstance(Components.interfaces.nsIM
utableArray)
var str = Components.classes["@mozilla.org/supports-
string;1"].createInstance(Components.interfaces.nsISupportsString)
str.data = cmdstr
array.appendElement(str, false)
var str2 = Components.classes["@mozilla.org/supports-
string;1"].createInstance(Components.interfaces.nsISupportsString)
str2.data = saveundostring
array.appendElement(str2, false)
observerService.notifyObservers(array,'xo-message2',saveundostring); //this
saveundostring is not req to be sent here, any array can be sent

}//end of smaller if
}//end of if

if (notSendOverMesh==true)
{
window.XO.errorMessage=window.XO.errorMessage+' reaching in the schedule
command thing'
}//end of if

try {
var sci = SocialCalc.SheetCommandInfo;

sci.sheetobj = sheet;


h t t p : / / s e e t a . i n

Page 13
sci.parseobj = new SocialCalc.Parse(cmdstr);
sci.saveundo = saveundo;

if (sci.sheetobj.statuscallback) { // notify others if requested
sheet.statuscallback(sci, "cmdstart", "", sci.sheetobj.statuscallbackparams);
}

if (sci.saveundo) {
sci.sheetobj.changes.PushChange(""); // add a step to undo stack
}

sci.timerobj = window.setTimeout(SocialCalc.SheetCommandsTimerRoutine,
sci.firsttimerdelay);
if (notSendOverMesh==true)
{

//window.XO.errorMessage=window.XO.errorMessage+' successfully executing the
command'
}//end of if
}
catch(err)
{window.XO.errorMessage=window.XO.errorMessage+' error is in schedule
command'+err}

}
Hence, a change was also made where the function was actually declared in
the file-
try {SocialCalc.Sheet.prototype.ScheduleSheetCommands = function(cmd, saveundo,
notSendOverMesh) {try {return SocialCalc.ScheduleSheetCommands(this, cmd,
saveundo,notSendOverMesh);}catch(err){window.XO.errorMessage='here lies the
problem'+err;alert('here lies the problem'+err);}}; }//end of try
catch(err)
{alert('here lies the problem'+err)}



3) socialcalcspreadsheetcontrol.js-
A new function was registered with the callback mechanism in order to get the
latest instance of the schedule spreadsheet command for the purpose of
receiving the execute command. This was a tricky part and led quite some
time in debugging. Here is the code-
window.XO.register('execute',function(array){
try
{

netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect")
//array = array.QueryInterface(Components.interfaces.nsIMutableArray)
window.XO.errorMessage=window.XO.errorMessage+'\nreached
successfully in the register fn of execute'
if (array.length) {
window.XO.errorMessage=window.XO.errorMessage+'..........reaching
inside the array.length';


h t t p : / / s e e t a . i n

Page 14
var iter = array.enumerate()
var xp_arg1 = iter.getNext()
xp_arg1 =
xp_arg1.QueryInterface(Components.interfaces.nsISupportsString)
xp_arg1= xp_arg1.toString()
var xp_arg2 = iter.getNext()
xp_arg2 =
xp_arg2.QueryInterface(Components.interfaces.nsISupportsString)
xp_arg2= xp_arg2.toString()
//in order to call the current context schedulesheetcommand

window.XO.errorMessage=window.XO.errorMessage+'\ncalling the
currentspreadsheet.schedulesheetcommand fn'

SocialCalc.CurrentSpreadsheetControlObject.context.sheetobj.ScheduleSheetCommands(x
p_arg1,xp_arg2,true)

window.XO.errorMessage=window.XO.errorMessage+'\nreturned after calling the
currentspreadsheet.schedulesheetcommand fn'


}//end of if(array.length)

else {window.XO.errorMessage=window.XO.errorMessage+'..........array
is empty';}

}//end of try


catch(err)
{window.XO.errorMessage='here lies the problem'+err;//alert('here lies
the problem'+err);

}//end of catch

})//end of window.XO.register


HTML FILES-
1.index.html-
A few changes were made initially in this part however, to make the working
simpler these changes were transferred to the javascript part only. However,
some changes will be required in this file while collaborating the graphing
framework.








h t t p : / / s e e t a . i n

Page 15
Section III

Appendix-
1. Xpcom- XPCOM (Cross Platform Component Object Model) is a cross
platform component model from Mozilla. It is similar to CORBA and Microsoft
COM. It has multiple language bindings and IDL descriptions so programmers can
plug their custom functionality into the framework and connect it with other
components. XPCOM is one of the main things that makes the Mozilla application
environment an actual framework. It is a development environment that provides the
following features for the cross-platform software developer:
Component management
File abstraction
Object message passing
Memory management
This component object model makes virtually all of the functionality of Gecko
available as a series of components, or reusable cross-platform libraries, that can be
accessed from the web browser or scripted from any Mozilla application.
The flexibility to reuse the XPCOM components from the Gecko library and develop
new components that run on different platforms facilitates rapid application
development and results in an application that is more productive and easier to
maintain

My Description Of Xpcom: xpcom is a cross platform component model designed
by mozilla.
Application End: now by using the various components of xpcom model we can
access the different functions provided by the gecko engine. So xpcom helps an
application written in any language to use any functionality of gecko by using the
various components of the xpcom libraries. These applications have to use a special
layer of xpcom (xpconnect for javascript or pyxpcom for python) to interact with
xpcom; these layers reflect the library interfaces of xpcom into the corresponding
language of the application.
Understand It Like This- Xpcom Is like internationalization which creates a base for
using the functionality of gecko by applications in various languages. And xpconnect
or pyxpcom or others are like the localized layers of xpcom designed to interact with
applications in their localized languages.
Developer End: Xpcom helps a developer as we can write new components (other
than that of gecko) in any of the languages like c, c++, python for which bindings (


h t t p : / / s e e t a . i n

Page 16
support) is provided by xpcom. Now applications written in any other languages can
access these components. So it helps in making our written components language-
independent.

2. Pyxpcom: PyXPCOM allows for communication between Python and
XPCOM, such that a Python application can access XPCOM objects, and XPCOM
can access any Python class that implements an XPCOM interface. With PyXPCOM,
a developer can talk to XPCOM or embed Gecko from a Python application.
PyXPCOM is similar to JavaXPCOM (Java-XPCOM bridge) or XPConnect
(JavaScript-XPCOM bridge).
Python classes and interfaces: Mozilla defines many external interfaces available to
embeddors and component developers. PyXPCOM provides access to these interfaces
as Python interfaces. PyXPCOM also contains several classes that provide access to
functions for initializing and shutting down XPCOM and Gecko from Python, as well
as some XPCOM helper functions.

3. Xocom: XOCom is a library for running DHTML activities in the sugar
development environment.
It uses the embedded gecko browser engine (via Hulahop) to render the page, and the
Mozilla XPCom interface to communicate between the python activity and the
javascript backend.













Contact Note For getting involved in the development of SocialCalc, or on any
questions related to it, please e-mail at socialcalc<dot>sugar<at>seeta<dot>in.
For posting a feature request/bug, please use http://testtrack.seeta.in.
Looking forward to your feedback.

You might also like