Utilize new toolbars
Aleksey Lim
14 years ago
30 | 30 | import telepathy |
31 | 31 | import telepathy.client |
32 | 32 | |
33 | from sugar.activity.activity import Activity, ActivityToolbox, EditToolbar | |
33 | from sugar.graphics.toolcombobox import ToolComboBox | |
34 | from sugar.graphics.toolbar import ToolbarButton, Toolbar | |
35 | from sugar.activity import activity | |
34 | 36 | from sugar.presence import presenceservice |
35 | 37 | from sugar.graphics import style |
36 | 38 | |
37 | 39 | from abiword import Canvas |
38 | 40 | import toolbar |
39 | from toolbar import WriteActivityToolbarExtension, WriteEditToolbar, TextToolbar, ImageToolbar, TableToolbar, FormatToolbar, ViewToolbar | |
41 | import widgets | |
40 | 42 | from sugar.activity.activity import get_bundle_path |
41 | 43 | |
42 | 44 | logger = logging.getLogger('write-activity') |
43 | 45 | |
44 | class AbiWordActivity (Activity): | |
46 | class AbiWordActivity (activity.Activity): | |
45 | 47 | |
46 | 48 | def __init__ (self, handle): |
47 | Activity.__init__ (self, handle) | |
48 | ||
49 | # abiword uses the current directory for all its file dialogs | |
49 | activity.Activity.__init__ (self, handle) | |
50 | ||
51 | # abiword uses the current directory for all its file dialogs | |
50 | 52 | os.chdir(os.path.expanduser('~')) |
51 | 53 | |
52 | 54 | # create our main abiword canvas |
53 | 55 | self.abiword_canvas = Canvas() |
54 | self.abiword_canvas.connect('text-selected', self._selection_cb) | |
55 | self.abiword_canvas.connect('image-selected', self._selection_cb) | |
56 | self.abiword_canvas.connect('selection-cleared', self._selection_cleared_cb) | |
57 | ||
58 | # create our toolbars | |
59 | toolbox = ActivityToolbox(self) | |
60 | self.set_toolbox(toolbox) | |
61 | toolbox.show() | |
62 | ||
63 | activity_toolbar_ext = WriteActivityToolbarExtension(self, toolbox, self.abiword_canvas) | |
64 | ||
65 | text_toolbar = TextToolbar(toolbox, self.abiword_canvas) | |
66 | ||
67 | self._edit_toolbar = WriteEditToolbar(toolbox, self.abiword_canvas, text_toolbar) | |
68 | toolbox.add_toolbar(_('Edit'), self._edit_toolbar) | |
69 | self._edit_toolbar.show() | |
70 | ||
71 | toolbox.add_toolbar(_('Text'), text_toolbar) | |
72 | text_toolbar.show() | |
73 | ||
74 | image_toolbar = ImageToolbar(toolbox, self.abiword_canvas, self) | |
75 | toolbox.add_toolbar(_('Image'), image_toolbar) | |
76 | image_toolbar.show() | |
77 | ||
78 | table_toolbar = TableToolbar(toolbox, self.abiword_canvas) | |
79 | toolbox.add_toolbar(_('Table'), table_toolbar) | |
80 | table_toolbar.show() | |
81 | ||
82 | format_toolbar = FormatToolbar(toolbox, self.abiword_canvas) | |
83 | toolbox.add_toolbar(_('Format'), format_toolbar) | |
84 | format_toolbar.show() | |
85 | ||
86 | view_toolbar = ViewToolbar(self.abiword_canvas) | |
87 | toolbox.add_toolbar(_('View'), view_toolbar) | |
88 | view_toolbar.show() | |
89 | ||
90 | # the text toolbar should be our default toolbar | |
91 | toolbox.set_current_toolbar(toolbar.TOOLBAR_TEXT) | |
56 | ||
57 | main_toolbar = Toolbar() | |
58 | ||
59 | main_toolbar.top.insert(activity.toolbar(self), 0) | |
60 | ||
61 | main_toolbar.top.insert( | |
62 | ToolComboBox(widgets.FontCombo(self.abiword_canvas)), -1) | |
63 | main_toolbar.top.insert( | |
64 | ToolComboBox(widgets.FontSizeCombo(self.abiword_canvas)), -1) | |
65 | ||
66 | text_toolbar = ToolbarButton( | |
67 | page=toolbar.TextToolbar(self.abiword_canvas), | |
68 | icon_name='text-bar') | |
69 | main_toolbar.top.insert(text_toolbar, -1) | |
70 | ||
71 | main_toolbar.top.insert(activity.separator(), -1) | |
72 | ||
73 | undo = activity.undo_button(sensitive=False) | |
74 | undo.connect('clicked', lambda button: self.abiword_canvas.undo()) | |
75 | self.abiword_canvas.connect("can-undo", lambda abi, can_undo: | |
76 | undo.set_sensitive(can_undo)) | |
77 | main_toolbar.top.insert(undo, -1) | |
78 | ||
79 | redo = activity.redo_button(sensitive=False) | |
80 | redo.connect('clicked', lambda button: self.abiword_canvas.redo()) | |
81 | self.abiword_canvas.connect("can-redo", lambda abi, can_redo: | |
82 | redo.set_sensitive(can_redo)) | |
83 | main_toolbar.top.insert(redo, -1) | |
84 | ||
85 | copy = activity.copy_button() | |
86 | copy.connect('clicked', lambda button: self.abiword_canvas.copy()) | |
87 | main_toolbar.top.insert(copy, -1) | |
88 | ||
89 | paste = activity.paste_button() | |
90 | paste.connect('clicked', lambda button: self.abiword_canvas.paste()) | |
91 | main_toolbar.top.insert(paste, -1) | |
92 | ||
93 | self.abiword_canvas.connect('text-selected', lambda abi, b: | |
94 | copy.set_sensitive(True)) | |
95 | self.abiword_canvas.connect('image-selected', lambda abi, b: | |
96 | copy.set_sensitive(True)) | |
97 | self.abiword_canvas.connect('selection-cleared', lambda abi, b: | |
98 | copy.set_sensitive(False)) | |
99 | ||
100 | main_toolbar.top.insert(activity.separator(), -1) | |
101 | ||
102 | insert_toolbar = ToolbarButton( | |
103 | page=toolbar.InsertToolbar(self.abiword_canvas), | |
104 | icon_name='transfer-from') | |
105 | main_toolbar.top.insert(insert_toolbar, -1) | |
106 | ||
107 | search_toolbar = ToolbarButton( | |
108 | page=toolbar.SearchToolbar(self.abiword_canvas, main_toolbar), | |
109 | icon_name='search-bar') | |
110 | main_toolbar.top.insert(search_toolbar, -1) | |
111 | ||
112 | view_toolbar = ToolbarButton( | |
113 | page=toolbar.ViewToolbar(self.abiword_canvas), | |
114 | icon_name='view-bar') | |
115 | main_toolbar.top.insert(view_toolbar, -1) | |
116 | ||
117 | main_toolbar.top.insert(activity.expander(), -1) | |
118 | main_toolbar.top.insert(activity.stop_button(self), -1) | |
119 | ||
120 | main_toolbar.show_all() | |
121 | self.set_toolbox(main_toolbar) | |
92 | 122 | |
93 | 123 | self.set_canvas(self.abiword_canvas) |
94 | self.abiword_canvas.connect_after('map-event', self._map_event_cb) | |
124 | #self.abiword_canvas.connect_after('map-event', self._map_event_cb) | |
95 | 125 | self.abiword_canvas.show() |
96 | 126 | |
97 | 127 | def _map_event_cb(self, event, activity): |
98 | 128 | logger.debug('_map_event_cb') |
99 | ||
129 | ||
100 | 130 | # set custom keybindings for Write |
101 | 131 | logger.debug("Loading keybindings") |
102 | 132 | keybindings_file = os.path.join( get_bundle_path(), "keybindings.xml" ) |
140 | 170 | |
141 | 171 | def get_preview(self): |
142 | 172 | if not hasattr(self.abiword_canvas, 'render_page_to_image'): |
143 | return Activity.get_preview(self) | |
173 | return activity.Activity.get_preview(self) | |
144 | 174 | |
145 | 175 | pixbuf = self.abiword_canvas.render_page_to_image(1) |
146 | 176 | pixbuf = pixbuf.scale_simple(style.zoom(300), style.zoom(225), |
348 | 378 | |
349 | 379 | self.metadata['fulltext'] = self.abiword_canvas.get_content(extension_or_mimetype=".txt")[:3000] |
350 | 380 | self.abiword_canvas.save('file://' + file_path, actual_mimetype, ''); |
351 | ||
352 | def _selection_cb(self, abi, b): | |
353 | self._edit_toolbar.copy.set_sensitive(True) | |
354 | ||
355 | def _selection_cleared_cb(self, abi, b): | |
356 | self._edit_toolbar.copy.set_sensitive(False) |
0 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
1 | <svg | |
2 | xmlns:dc="http://purl.org/dc/elements/1.1/" | |
3 | xmlns:cc="http://creativecommons.org/ns#" | |
4 | xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |
5 | xmlns:svg="http://www.w3.org/2000/svg" | |
6 | xmlns="http://www.w3.org/2000/svg" | |
7 | xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | |
8 | xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | |
9 | enable-background="new 0 0 55 54.696" | |
10 | height="54.696px" | |
11 | version="1.1" | |
12 | viewBox="0 0 55 54.696" | |
13 | width="55px" | |
14 | x="0px" | |
15 | xml:space="preserve" | |
16 | y="0px" | |
17 | id="svg2" | |
18 | sodipodi:version="0.32" | |
19 | inkscape:version="0.46" | |
20 | sodipodi:docname="list-bullet.svg" | |
21 | inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata | |
22 | id="metadata16"><rdf:RDF><cc:Work | |
23 | rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type | |
24 | rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs | |
25 | id="defs14"><inkscape:perspective | |
26 | sodipodi:type="inkscape:persp3d" | |
27 | inkscape:vp_x="0 : 27.348 : 1" | |
28 | inkscape:vp_y="0 : 1000 : 0" | |
29 | inkscape:vp_z="55 : 27.348 : 1" | |
30 | inkscape:persp3d-origin="27.5 : 18.232 : 1" | |
31 | id="perspective18" /></defs><sodipodi:namedview | |
32 | inkscape:window-height="655" | |
33 | inkscape:window-width="1278" | |
34 | inkscape:pageshadow="2" | |
35 | inkscape:pageopacity="0.40392157" | |
36 | guidetolerance="10.0" | |
37 | gridtolerance="10.0" | |
38 | objecttolerance="10.0" | |
39 | borderopacity="1.0" | |
40 | bordercolor="#666666" | |
41 | pagecolor="#909090" | |
42 | id="base" | |
43 | showgrid="false" | |
44 | inkscape:zoom="8.4101215" | |
45 | inkscape:cx="6.6917394" | |
46 | inkscape:cy="27.348" | |
47 | inkscape:window-x="0" | |
48 | inkscape:window-y="16" | |
49 | inkscape:current-layer="svg2" /><g | |
50 | display="block" | |
51 | id="format-justify-fill" | |
52 | transform="translate(7.4268516,0)" | |
53 | style="display:block"> | |
54 | <line | |
55 | display="inline" | |
56 | x1="11.737" | |
57 | x2="42.737" | |
58 | y1="14.47" | |
59 | y2="14.47" | |
60 | id="line5" | |
61 | style="fill:#4c4d4f;stroke:#ffffff;stroke-width:3.5;display:inline" /> | |
62 | <line | |
63 | display="inline" | |
64 | x1="11.737" | |
65 | x2="42.737" | |
66 | y1="23.056" | |
67 | y2="23.056" | |
68 | id="line7" | |
69 | style="fill:#4c4d4f;stroke:#ffffff;stroke-width:3.5;display:inline" /> | |
70 | <line | |
71 | display="inline" | |
72 | x1="11.737" | |
73 | x2="42.737" | |
74 | y1="31.641001" | |
75 | y2="31.641001" | |
76 | id="line9" | |
77 | style="fill:#4c4d4f;stroke:#ffffff;stroke-width:3.5;display:inline" /> | |
78 | <line | |
79 | display="inline" | |
80 | x1="11.737" | |
81 | x2="42.737" | |
82 | y1="40.227001" | |
83 | y2="40.227001" | |
84 | id="line11" | |
85 | style="fill:#4c4d4f;stroke:#ffffff;stroke-width:3.5;display:inline" /> | |
86 | </g><path | |
87 | sodipodi:type="arc" | |
88 | style="fill:#f5f5f5;fill-opacity:0.96078431;fill-rule:evenodd;stroke:#f5f5f5;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.96078431" | |
89 | id="path2383" | |
90 | sodipodi:cx="-26.694027" | |
91 | sodipodi:cy="23.126896" | |
92 | sodipodi:rx="2.7942522" | |
93 | sodipodi:ry="2.7942522" | |
94 | d="M -23.899775,23.126896 A 2.7942522,2.7942522 0 1 1 -29.488279,23.126896 A 2.7942522,2.7942522 0 1 1 -23.899775,23.126896 z" | |
95 | transform="matrix(0.87874,0,0,0.8787401,31.083695,-2.2657739)" /></svg>⏎ |
0 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
1 | <svg | |
2 | xmlns:dc="http://purl.org/dc/elements/1.1/" | |
3 | xmlns:cc="http://creativecommons.org/ns#" | |
4 | xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |
5 | xmlns:svg="http://www.w3.org/2000/svg" | |
6 | xmlns="http://www.w3.org/2000/svg" | |
7 | xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | |
8 | xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | |
9 | enable-background="new 0 0 55 54.696" | |
10 | height="54.696px" | |
11 | version="1.1" | |
12 | viewBox="0 0 55 54.696" | |
13 | width="55px" | |
14 | x="0px" | |
15 | xml:space="preserve" | |
16 | y="0px" | |
17 | id="svg2" | |
18 | sodipodi:version="0.32" | |
19 | inkscape:version="0.46" | |
20 | sodipodi:docname="list-dashed.svg" | |
21 | inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata | |
22 | id="metadata16"><rdf:RDF><cc:Work | |
23 | rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type | |
24 | rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs | |
25 | id="defs14"><inkscape:perspective | |
26 | sodipodi:type="inkscape:persp3d" | |
27 | inkscape:vp_x="0 : 27.348 : 1" | |
28 | inkscape:vp_y="0 : 1000 : 0" | |
29 | inkscape:vp_z="55 : 27.348 : 1" | |
30 | inkscape:persp3d-origin="27.5 : 18.232 : 1" | |
31 | id="perspective18" /> | |
32 | ||
33 | ||
34 | ||
35 | ||
36 | </defs><sodipodi:namedview | |
37 | inkscape:window-height="655" | |
38 | inkscape:window-width="1278" | |
39 | inkscape:pageshadow="2" | |
40 | inkscape:pageopacity="0.40392157" | |
41 | guidetolerance="10.0" | |
42 | gridtolerance="10.0" | |
43 | objecttolerance="10.0" | |
44 | borderopacity="1.0" | |
45 | bordercolor="#666666" | |
46 | pagecolor="#909090" | |
47 | id="base" | |
48 | showgrid="false" | |
49 | inkscape:zoom="8.4101215" | |
50 | inkscape:cx="6.6917394" | |
51 | inkscape:cy="27.348" | |
52 | inkscape:window-x="0" | |
53 | inkscape:window-y="32" | |
54 | inkscape:current-layer="svg2" /><g | |
55 | id="g3212"><line | |
56 | display="inline" | |
57 | x1="19.163853" | |
58 | x2="50.163853" | |
59 | y1="14.47" | |
60 | y2="14.47" | |
61 | id="line5" | |
62 | style="fill:#4c4d4f;stroke:#ffffff;stroke-width:3.5;display:inline" /><line | |
63 | display="inline" | |
64 | x1="19.163853" | |
65 | x2="50.163853" | |
66 | y1="23.056" | |
67 | y2="23.056" | |
68 | id="line7" | |
69 | style="fill:#4c4d4f;stroke:#ffffff;stroke-width:3.5;display:inline" /><line | |
70 | display="inline" | |
71 | x1="19.163853" | |
72 | x2="50.163853" | |
73 | y1="31.641001" | |
74 | y2="31.641001" | |
75 | id="line9" | |
76 | style="fill:#4c4d4f;stroke:#ffffff;stroke-width:3.5;display:inline" /><line | |
77 | display="inline" | |
78 | x1="19.163853" | |
79 | x2="50.163853" | |
80 | y1="40.227001" | |
81 | y2="40.227001" | |
82 | id="line11" | |
83 | style="fill:#4c4d4f;stroke:#ffffff;stroke-width:3.5;display:inline" /></g><line | |
84 | style="fill:#4c4d4f;stroke:#ffffff;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;display:inline" | |
85 | id="line3210" | |
86 | y2="18.90579" | |
87 | y1="18.90579" | |
88 | x2="13.115018" | |
89 | x1="3.0559719" | |
90 | display="inline" /></svg>⏎ |
0 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
1 | <svg | |
2 | xmlns:dc="http://purl.org/dc/elements/1.1/" | |
3 | xmlns:cc="http://creativecommons.org/ns#" | |
4 | xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |
5 | xmlns:svg="http://www.w3.org/2000/svg" | |
6 | xmlns="http://www.w3.org/2000/svg" | |
7 | xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | |
8 | xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | |
9 | enable-background="new 0 0 55 54.696" | |
10 | height="54.696px" | |
11 | version="1.1" | |
12 | viewBox="0 0 55 54.696" | |
13 | width="55px" | |
14 | x="0px" | |
15 | xml:space="preserve" | |
16 | y="0px" | |
17 | id="svg2" | |
18 | sodipodi:version="0.32" | |
19 | inkscape:version="0.46" | |
20 | sodipodi:docname="list-lower-case.svg" | |
21 | inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata | |
22 | id="metadata16"><rdf:RDF><cc:Work | |
23 | rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type | |
24 | rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs | |
25 | id="defs14"><inkscape:perspective | |
26 | sodipodi:type="inkscape:persp3d" | |
27 | inkscape:vp_x="0 : 27.348 : 1" | |
28 | inkscape:vp_y="0 : 1000 : 0" | |
29 | inkscape:vp_z="55 : 27.348 : 1" | |
30 | inkscape:persp3d-origin="27.5 : 18.232 : 1" | |
31 | id="perspective18" /></defs><sodipodi:namedview | |
32 | inkscape:window-height="655" | |
33 | inkscape:window-width="1278" | |
34 | inkscape:pageshadow="2" | |
35 | inkscape:pageopacity="0.40392157" | |
36 | guidetolerance="10.0" | |
37 | gridtolerance="10.0" | |
38 | objecttolerance="10.0" | |
39 | borderopacity="1.0" | |
40 | bordercolor="#666666" | |
41 | pagecolor="#909090" | |
42 | id="base" | |
43 | showgrid="false" | |
44 | inkscape:zoom="8.4101215" | |
45 | inkscape:cx="27.5" | |
46 | inkscape:cy="27.348" | |
47 | inkscape:window-x="0" | |
48 | inkscape:window-y="48" | |
49 | inkscape:current-layer="svg2" /><g | |
50 | display="block" | |
51 | id="format-justify-fill" | |
52 | transform="translate(7.4268516,0)" | |
53 | style="display:block"> | |
54 | <line | |
55 | display="inline" | |
56 | x1="11.737" | |
57 | x2="42.737" | |
58 | y1="14.47" | |
59 | y2="14.47" | |
60 | id="line5" | |
61 | style="fill:#4c4d4f;stroke:#ffffff;stroke-width:3.5;display:inline" /> | |
62 | <line | |
63 | display="inline" | |
64 | x1="11.737" | |
65 | x2="42.737" | |
66 | y1="23.056" | |
67 | y2="23.056" | |
68 | id="line7" | |
69 | style="fill:#4c4d4f;stroke:#ffffff;stroke-width:3.5;display:inline" /> | |
70 | <line | |
71 | display="inline" | |
72 | x1="11.737" | |
73 | x2="42.737" | |
74 | y1="31.641001" | |
75 | y2="31.641001" | |
76 | id="line9" | |
77 | style="fill:#4c4d4f;stroke:#ffffff;stroke-width:3.5;display:inline" /> | |
78 | <line | |
79 | display="inline" | |
80 | x1="11.737" | |
81 | x2="42.737" | |
82 | y1="40.227001" | |
83 | y2="40.227001" | |
84 | id="line11" | |
85 | style="fill:#4c4d4f;stroke:#ffffff;stroke-width:3.5;display:inline" /> | |
86 | </g><text | |
87 | xml:space="preserve" | |
88 | style="font-size:18px;font-style:normal;font-weight:bold;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold" | |
89 | x="2.615895" | |
90 | y="23.543058" | |
91 | id="text3778"><tspan | |
92 | sodipodi:role="line" | |
93 | id="tspan3780" | |
94 | x="2.615895" | |
95 | y="23.543058">a</tspan></text> | |
96 | </svg>⏎ |
0 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
1 | <svg | |
2 | xmlns:dc="http://purl.org/dc/elements/1.1/" | |
3 | xmlns:cc="http://creativecommons.org/ns#" | |
4 | xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |
5 | xmlns:svg="http://www.w3.org/2000/svg" | |
6 | xmlns="http://www.w3.org/2000/svg" | |
7 | xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | |
8 | xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | |
9 | enable-background="new 0 0 55 54.696" | |
10 | height="54.696px" | |
11 | version="1.1" | |
12 | viewBox="0 0 55 54.696" | |
13 | width="55px" | |
14 | x="0px" | |
15 | xml:space="preserve" | |
16 | y="0px" | |
17 | id="svg2" | |
18 | sodipodi:version="0.32" | |
19 | inkscape:version="0.46" | |
20 | sodipodi:docname="list-none.svg" | |
21 | inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata | |
22 | id="metadata16"><rdf:RDF><cc:Work | |
23 | rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type | |
24 | rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs | |
25 | id="defs14"><inkscape:perspective | |
26 | sodipodi:type="inkscape:persp3d" | |
27 | inkscape:vp_x="0 : 27.348 : 1" | |
28 | inkscape:vp_y="0 : 1000 : 0" | |
29 | inkscape:vp_z="55 : 27.348 : 1" | |
30 | inkscape:persp3d-origin="27.5 : 18.232 : 1" | |
31 | id="perspective18" /> | |
32 | ||
33 | ||
34 | ||
35 | ||
36 | </defs><sodipodi:namedview | |
37 | inkscape:window-height="719" | |
38 | inkscape:window-width="1278" | |
39 | inkscape:pageshadow="2" | |
40 | inkscape:pageopacity="0.40392157" | |
41 | guidetolerance="10.0" | |
42 | gridtolerance="10.0" | |
43 | objecttolerance="10.0" | |
44 | borderopacity="1.0" | |
45 | bordercolor="#666666" | |
46 | pagecolor="#909090" | |
47 | id="base" | |
48 | showgrid="false" | |
49 | inkscape:zoom="8.4101215" | |
50 | inkscape:cx="24.745584" | |
51 | inkscape:cy="27.348" | |
52 | inkscape:window-x="0" | |
53 | inkscape:window-y="16" | |
54 | inkscape:current-layer="svg2" /><g | |
55 | id="g3162"><line | |
56 | display="inline" | |
57 | x1="5.3933511" | |
58 | x2="49.428024" | |
59 | y1="14.47" | |
60 | y2="14.47" | |
61 | id="line5" | |
62 | style="fill:#4c4d4f;stroke:#ffffff;stroke-width:3.50000005;display:inline;stroke-miterlimit:4;stroke-dasharray:none" /><line | |
63 | display="inline" | |
64 | x1="5.3933511" | |
65 | x2="49.428024" | |
66 | y1="23.056" | |
67 | y2="23.056" | |
68 | id="line7" | |
69 | style="fill:#4c4d4f;stroke:#ffffff;stroke-width:3.50000005;display:inline;stroke-miterlimit:4;stroke-dasharray:none" /><line | |
70 | display="inline" | |
71 | x1="5.3933511" | |
72 | x2="49.428024" | |
73 | y1="31.641001" | |
74 | y2="31.641001" | |
75 | id="line9" | |
76 | style="fill:#4c4d4f;stroke:#ffffff;stroke-width:3.50000005;display:inline;stroke-miterlimit:4;stroke-dasharray:none" /><line | |
77 | display="inline" | |
78 | x1="5.3933511" | |
79 | x2="49.428024" | |
80 | y1="40.227001" | |
81 | y2="40.227001" | |
82 | id="line11" | |
83 | style="fill:#4c4d4f;stroke:#ffffff;stroke-width:3.50000005;display:inline;stroke-miterlimit:4;stroke-dasharray:none" /></g></svg>⏎ |
0 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
1 | <svg | |
2 | xmlns:dc="http://purl.org/dc/elements/1.1/" | |
3 | xmlns:cc="http://creativecommons.org/ns#" | |
4 | xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |
5 | xmlns:svg="http://www.w3.org/2000/svg" | |
6 | xmlns="http://www.w3.org/2000/svg" | |
7 | xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | |
8 | xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | |
9 | enable-background="new 0 0 55 54.696" | |
10 | height="54.696px" | |
11 | version="1.1" | |
12 | viewBox="0 0 55 54.696" | |
13 | width="55px" | |
14 | x="0px" | |
15 | xml:space="preserve" | |
16 | y="0px" | |
17 | id="svg2" | |
18 | sodipodi:version="0.32" | |
19 | inkscape:version="0.46" | |
20 | sodipodi:docname="list-numbered.svg" | |
21 | inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata | |
22 | id="metadata16"><rdf:RDF><cc:Work | |
23 | rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type | |
24 | rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs | |
25 | id="defs14"><inkscape:perspective | |
26 | sodipodi:type="inkscape:persp3d" | |
27 | inkscape:vp_x="0 : 27.348 : 1" | |
28 | inkscape:vp_y="0 : 1000 : 0" | |
29 | inkscape:vp_z="55 : 27.348 : 1" | |
30 | inkscape:persp3d-origin="27.5 : 18.232 : 1" | |
31 | id="perspective18" /></defs><sodipodi:namedview | |
32 | inkscape:window-height="655" | |
33 | inkscape:window-width="1278" | |
34 | inkscape:pageshadow="2" | |
35 | inkscape:pageopacity="0.40392157" | |
36 | guidetolerance="10.0" | |
37 | gridtolerance="10.0" | |
38 | objecttolerance="10.0" | |
39 | borderopacity="1.0" | |
40 | bordercolor="#666666" | |
41 | pagecolor="#909090" | |
42 | id="base" | |
43 | showgrid="false" | |
44 | inkscape:zoom="8.4101215" | |
45 | inkscape:cx="27.5" | |
46 | inkscape:cy="27.348" | |
47 | inkscape:window-x="0" | |
48 | inkscape:window-y="64" | |
49 | inkscape:current-layer="svg2" /><g | |
50 | display="block" | |
51 | id="format-justify-fill" | |
52 | transform="translate(7.4268516,0)" | |
53 | style="display:block"> | |
54 | <line | |
55 | display="inline" | |
56 | x1="11.737" | |
57 | x2="42.737" | |
58 | y1="14.47" | |
59 | y2="14.47" | |
60 | id="line5" | |
61 | style="fill:#4c4d4f;stroke:#ffffff;stroke-width:3.5;display:inline" /> | |
62 | <line | |
63 | display="inline" | |
64 | x1="11.737" | |
65 | x2="42.737" | |
66 | y1="23.056" | |
67 | y2="23.056" | |
68 | id="line7" | |
69 | style="fill:#4c4d4f;stroke:#ffffff;stroke-width:3.5;display:inline" /> | |
70 | <line | |
71 | display="inline" | |
72 | x1="11.737" | |
73 | x2="42.737" | |
74 | y1="31.641001" | |
75 | y2="31.641001" | |
76 | id="line9" | |
77 | style="fill:#4c4d4f;stroke:#ffffff;stroke-width:3.5;display:inline" /> | |
78 | <line | |
79 | display="inline" | |
80 | x1="11.737" | |
81 | x2="42.737" | |
82 | y1="40.227001" | |
83 | y2="40.227001" | |
84 | id="line11" | |
85 | style="fill:#4c4d4f;stroke:#ffffff;stroke-width:3.5;display:inline" /> | |
86 | </g><text | |
87 | xml:space="preserve" | |
88 | style="font-size:16px;font-style:normal;font-weight:bold;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold" | |
89 | x="1.7835652" | |
90 | y="24.969913" | |
91 | id="text3845"><tspan | |
92 | sodipodi:role="line" | |
93 | id="tspan3847" | |
94 | x="1.7835652" | |
95 | y="24.969913">1</tspan></text> | |
96 | </svg>⏎ |
0 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
1 | <svg | |
2 | xmlns:dc="http://purl.org/dc/elements/1.1/" | |
3 | xmlns:cc="http://creativecommons.org/ns#" | |
4 | xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |
5 | xmlns:svg="http://www.w3.org/2000/svg" | |
6 | xmlns="http://www.w3.org/2000/svg" | |
7 | xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | |
8 | xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | |
9 | enable-background="new 0 0 55 54.696" | |
10 | height="54.696px" | |
11 | version="1.1" | |
12 | viewBox="0 0 55 54.696" | |
13 | width="55px" | |
14 | x="0px" | |
15 | xml:space="preserve" | |
16 | y="0px" | |
17 | id="svg2" | |
18 | sodipodi:version="0.32" | |
19 | inkscape:version="0.46" | |
20 | sodipodi:docname="list-upper-case.svg" | |
21 | inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata | |
22 | id="metadata16"><rdf:RDF><cc:Work | |
23 | rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type | |
24 | rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs | |
25 | id="defs14"><inkscape:perspective | |
26 | sodipodi:type="inkscape:persp3d" | |
27 | inkscape:vp_x="0 : 27.348 : 1" | |
28 | inkscape:vp_y="0 : 1000 : 0" | |
29 | inkscape:vp_z="55 : 27.348 : 1" | |
30 | inkscape:persp3d-origin="27.5 : 18.232 : 1" | |
31 | id="perspective18" /></defs><sodipodi:namedview | |
32 | inkscape:window-height="655" | |
33 | inkscape:window-width="1278" | |
34 | inkscape:pageshadow="2" | |
35 | inkscape:pageopacity="0.40392157" | |
36 | guidetolerance="10.0" | |
37 | gridtolerance="10.0" | |
38 | objecttolerance="10.0" | |
39 | borderopacity="1.0" | |
40 | bordercolor="#666666" | |
41 | pagecolor="#909090" | |
42 | id="base" | |
43 | showgrid="false" | |
44 | inkscape:zoom="8.4101215" | |
45 | inkscape:cx="27.5" | |
46 | inkscape:cy="27.348" | |
47 | inkscape:window-x="0" | |
48 | inkscape:window-y="80" | |
49 | inkscape:current-layer="svg2" /><g | |
50 | display="block" | |
51 | id="format-justify-fill" | |
52 | transform="translate(7.4268516,0)" | |
53 | style="display:block"> | |
54 | <line | |
55 | display="inline" | |
56 | x1="11.737" | |
57 | x2="42.737" | |
58 | y1="14.47" | |
59 | y2="14.47" | |
60 | id="line5" | |
61 | style="fill:#4c4d4f;stroke:#ffffff;stroke-width:3.5;display:inline" /> | |
62 | <line | |
63 | display="inline" | |
64 | x1="11.737" | |
65 | x2="42.737" | |
66 | y1="23.056" | |
67 | y2="23.056" | |
68 | id="line7" | |
69 | style="fill:#4c4d4f;stroke:#ffffff;stroke-width:3.5;display:inline" /> | |
70 | <line | |
71 | display="inline" | |
72 | x1="11.737" | |
73 | x2="42.737" | |
74 | y1="31.641001" | |
75 | y2="31.641001" | |
76 | id="line9" | |
77 | style="fill:#4c4d4f;stroke:#ffffff;stroke-width:3.5;display:inline" /> | |
78 | <line | |
79 | display="inline" | |
80 | x1="11.737" | |
81 | x2="42.737" | |
82 | y1="40.227001" | |
83 | y2="40.227001" | |
84 | id="line11" | |
85 | style="fill:#4c4d4f;stroke:#ffffff;stroke-width:3.5;display:inline" /> | |
86 | </g><text | |
87 | xml:space="preserve" | |
88 | style="font-size:16px;font-style:normal;font-weight:bold;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold" | |
89 | x="2.2591829" | |
90 | y="24.494293" | |
91 | id="text3912"><tspan | |
92 | sodipodi:role="line" | |
93 | id="tspan3914" | |
94 | x="2.2591829" | |
95 | y="24.494293">A</tspan></text> | |
96 | </svg>⏎ |
0 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
1 | <!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 14948) --> | |
2 | <svg | |
3 | xmlns:dc="http://purl.org/dc/elements/1.1/" | |
4 | xmlns:cc="http://creativecommons.org/ns#" | |
5 | xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |
6 | xmlns:svg="http://www.w3.org/2000/svg" | |
7 | xmlns="http://www.w3.org/2000/svg" | |
8 | xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | |
9 | xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | |
10 | version="1.0" | |
11 | id="Layer_1" | |
12 | x="0px" | |
13 | y="0px" | |
14 | width="22.16" | |
15 | height="22.156" | |
16 | viewBox="0 0 22.156 22.156" | |
17 | enable-background="new 0 0 22.156 22.156" | |
18 | xml:space="preserve" | |
19 | sodipodi:version="0.32" | |
20 | inkscape:version="0.46" | |
21 | sodipodi:docname="white-search.svg" | |
22 | inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata | |
23 | id="metadata12"><rdf:RDF><cc:Work | |
24 | rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type | |
25 | rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs | |
26 | id="defs10"><inkscape:perspective | |
27 | sodipodi:type="inkscape:persp3d" | |
28 | inkscape:vp_x="0 : 11.078 : 1" | |
29 | inkscape:vp_y="0 : 1000 : 0" | |
30 | inkscape:vp_z="22.156 : 11.078 : 1" | |
31 | inkscape:persp3d-origin="11.078 : 7.3853334 : 1" | |
32 | id="perspective14" /></defs><sodipodi:namedview | |
33 | inkscape:window-height="719" | |
34 | inkscape:window-width="1278" | |
35 | inkscape:pageshadow="2" | |
36 | inkscape:pageopacity="0.90196078" | |
37 | guidetolerance="10.0" | |
38 | gridtolerance="10.0" | |
39 | objecttolerance="10.0" | |
40 | borderopacity="1.0" | |
41 | bordercolor="#666666" | |
42 | pagecolor="#a1a1a1" | |
43 | id="base" | |
44 | showgrid="false" | |
45 | inkscape:zoom="41.704278" | |
46 | inkscape:cx="17.054208" | |
47 | inkscape:cy="9.0460986" | |
48 | inkscape:window-x="0" | |
49 | inkscape:window-y="16" | |
50 | inkscape:current-layer="g3" | |
51 | borderlayer="false" | |
52 | showborder="true" | |
53 | inkscape:showpageshadow="true" /> | |
54 | <g | |
55 | id="g3"> | |
56 | ||
57 | <rect | |
58 | style="opacity:1;fill:#ffffff;fill-opacity:0.9;fill-rule:nonzero;stroke:#3f3f3f;stroke-width:0.99999964;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.9" | |
59 | id="rect3245" | |
60 | width="3.1647084" | |
61 | height="7.8021984" | |
62 | x="-1.8735586" | |
63 | y="20.465549" | |
64 | transform="matrix(0.6999914,-0.7141512,0.7141512,0.6999914,0,0)" /><path | |
65 | d="M 2.7712159,9.5270226 C 2.7712159,13.233154 5.7738562,16.23849 9.480886,16.23849 C 13.183424,16.23849 16.188759,13.233154 16.188759,9.5270226 C 16.188759,5.8226881 13.183424,2.8191494 9.480886,2.8191494 C 5.7738562,2.8191494 2.7712159,5.8226881 2.7712159,9.5270226 z" | |
66 | id="path5" | |
67 | style="fill:none;stroke:#ffffff;stroke-width:3.14459634000000010;stroke-opacity:0.89999998" /> | |
68 | <path | |
69 | sodipodi:type="arc" | |
70 | style="opacity:1;fill:#ffffff;fill-opacity:0;fill-rule:nonzero;stroke:#3f3f3f;stroke-width:0.37737417000000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.89999998" | |
71 | id="path3758" | |
72 | sodipodi:cx="-5.7568049" | |
73 | sodipodi:cy="10.262735" | |
74 | sodipodi:rx="3.2130997" | |
75 | sodipodi:ry="2.8774025" | |
76 | d="M -2.5437052,10.262735 A 3.2130997,2.8774025 0 1 1 -8.9699047,10.262735 A 3.2130997,2.8774025 0 1 1 -2.5437052,10.262735 z" | |
77 | transform="matrix(2.5076449,0,0,2.8002036,23.987204,-19.204298)" /><path | |
78 | sodipodi:type="arc" | |
79 | style="opacity:1;fill:#ffffff;fill-opacity:0;fill-rule:nonzero;stroke:#3f3f3f;stroke-width:0.6316339;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.90000000000000002" | |
80 | id="path3760" | |
81 | sodipodi:cx="-5.7568049" | |
82 | sodipodi:cy="10.262735" | |
83 | sodipodi:rx="3.2130997" | |
84 | sodipodi:ry="2.8774025" | |
85 | d="M -2.5437052,10.262735 A 3.2130997,2.8774025 0 1 1 -8.9699047,10.262735 A 3.2130997,2.8774025 0 1 1 -2.5437052,10.262735 z" | |
86 | transform="matrix(1.4982103,0,0,1.6730016,18.022419,-7.6261876)" /><path | |
87 | sodipodi:type="arc" | |
88 | style="opacity:1;fill:#ffffff;fill-opacity:0;fill-rule:nonzero;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.9" | |
89 | id="path2385" | |
90 | sodipodi:cx="-18.08168" | |
91 | sodipodi:cy="9.3755369" | |
92 | sodipodi:rx="1.9182684" | |
93 | sodipodi:ry="1.7024633" | |
94 | d="M -16.163412,9.3755369 A 1.9182684,1.7024633 0 0 1 -17.387355,10.962566" | |
95 | sodipodi:start="0" | |
96 | sodipodi:end="1.2004329" | |
97 | sodipodi:open="true" /><path | |
98 | style="fill:none;fill-rule:evenodd;stroke:#f5f5f5;stroke-width:2.15084887px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.96078431" | |
99 | d="M 14.456402,14.583424 L 16.158553,16.233575" | |
100 | id="path3163" | |
101 | inkscape:connector-type="polyline" /></g> | |
102 | </svg>⏎ |
0 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
1 | <svg | |
2 | xmlns:dc="http://purl.org/dc/elements/1.1/" | |
3 | xmlns:cc="http://creativecommons.org/ns#" | |
4 | xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |
5 | xmlns:svg="http://www.w3.org/2000/svg" | |
6 | xmlns="http://www.w3.org/2000/svg" | |
7 | xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | |
8 | xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | |
9 | enable-background="new 0 0 55 54.696" | |
10 | height="54.696px" | |
11 | version="1.1" | |
12 | viewBox="0 0 55 54.696" | |
13 | width="55px" | |
14 | x="0px" | |
15 | xml:space="preserve" | |
16 | y="0px" | |
17 | id="svg2" | |
18 | sodipodi:version="0.32" | |
19 | inkscape:version="0.46" | |
20 | sodipodi:docname="text-bar.svg" | |
21 | inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata | |
22 | id="metadata22"><rdf:RDF><cc:Work | |
23 | rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type | |
24 | rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs | |
25 | id="defs20"><inkscape:perspective | |
26 | sodipodi:type="inkscape:persp3d" | |
27 | inkscape:vp_x="0 : 27.348 : 1" | |
28 | inkscape:vp_y="0 : 1000 : 0" | |
29 | inkscape:vp_z="55 : 27.348 : 1" | |
30 | inkscape:persp3d-origin="27.5 : 18.232 : 1" | |
31 | id="perspective24" /> | |
32 | ||
33 | ||
34 | ||
35 | ||
36 | </defs><sodipodi:namedview | |
37 | inkscape:window-height="719" | |
38 | inkscape:window-width="1278" | |
39 | inkscape:pageshadow="2" | |
40 | inkscape:pageopacity="0.96078431" | |
41 | guidetolerance="10.0" | |
42 | gridtolerance="10.0" | |
43 | objecttolerance="10.0" | |
44 | borderopacity="1.0" | |
45 | bordercolor="#666666" | |
46 | pagecolor="#767676" | |
47 | id="base" | |
48 | showgrid="false" | |
49 | inkscape:zoom="8.4101215" | |
50 | inkscape:cx="27.5" | |
51 | inkscape:cy="27.348" | |
52 | inkscape:window-x="0" | |
53 | inkscape:window-y="16" | |
54 | inkscape:current-layer="svg2" /><g | |
55 | id="g7" | |
56 | transform="matrix(1.3315067,0,0,1.3315067,-22.643371,-8.8784595)"> | |
57 | <g | |
58 | id="g9"> | |
59 | <path | |
60 | d="M 25.263,12.435 L 49.919,12.435 L 49.919,15.997 L 39.575,15.997 L 39.575,41.59 L 35.606,41.59 L 35.606,15.996 L 25.263,15.996 L 25.263,12.435 z" | |
61 | id="path11" | |
62 | style="fill:#ffffff" /> | |
63 | </g> | |
64 | </g></svg>⏎ |
0 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
1 | <!-- Created with Inkscape (http://www.inkscape.org/) --> | |
2 | <svg | |
3 | xmlns:dc="http://purl.org/dc/elements/1.1/" | |
4 | xmlns:cc="http://creativecommons.org/ns#" | |
5 | xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |
6 | xmlns:svg="http://www.w3.org/2000/svg" | |
7 | xmlns="http://www.w3.org/2000/svg" | |
8 | xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | |
9 | xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | |
10 | width="42" | |
11 | height="42" | |
12 | id="svg2" | |
13 | sodipodi:version="0.32" | |
14 | inkscape:version="0.46" | |
15 | version="1.0" | |
16 | sodipodi:docbase="/home/msgodoi/olpc/workspace/Memorize.activity/images" | |
17 | sodipodi:docname="view.svg" | |
18 | inkscape:output_extension="org.inkscape.output.svg.inkscape"> | |
19 | <defs | |
20 | id="defs4"> | |
21 | <inkscape:perspective | |
22 | sodipodi:type="inkscape:persp3d" | |
23 | inkscape:vp_x="0 : 21 : 1" | |
24 | inkscape:vp_y="0 : 1000 : 0" | |
25 | inkscape:vp_z="42 : 21 : 1" | |
26 | inkscape:persp3d-origin="21 : 14 : 1" | |
27 | id="perspective15" /> | |
28 | </defs> | |
29 | <sodipodi:namedview | |
30 | id="base" | |
31 | pagecolor="#ffffff" | |
32 | bordercolor="#666666" | |
33 | borderopacity="1.0" | |
34 | gridtolerance="10000" | |
35 | guidetolerance="10" | |
36 | objecttolerance="10" | |
37 | inkscape:pageopacity="0.0" | |
38 | inkscape:pageshadow="2" | |
39 | inkscape:zoom="11.313708" | |
40 | inkscape:cx="8.5837325" | |
41 | inkscape:cy="21" | |
42 | inkscape:document-units="px" | |
43 | inkscape:current-layer="layer1" | |
44 | width="42px" | |
45 | height="42px" | |
46 | inkscape:window-width="1278" | |
47 | inkscape:window-height="719" | |
48 | inkscape:window-x="0" | |
49 | inkscape:window-y="16" | |
50 | showgrid="false" /> | |
51 | <metadata | |
52 | id="metadata7"> | |
53 | <rdf:RDF> | |
54 | <cc:Work | |
55 | rdf:about=""> | |
56 | <dc:format>image/svg+xml</dc:format> | |
57 | <dc:type | |
58 | rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | |
59 | </cc:Work> | |
60 | </rdf:RDF> | |
61 | </metadata> | |
62 | <g | |
63 | inkscape:label="Layer 1" | |
64 | inkscape:groupmode="layer" | |
65 | id="layer1"> | |
66 | <g | |
67 | id="g3164" | |
68 | transform="translate(0.4419419,0.3535535)"> | |
69 | <path | |
70 | style="fill:#ffffff;fill-opacity:1;stroke:#404040;stroke-width:2.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;overflow:visible" | |
71 | id="path9" | |
72 | d="M 20.673867,9.8120817 C 10.544487,9.8120817 2.1236741,19.900784 2.1236741,19.900784 C 2.1236741,19.900784 10.544487,30.030166 20.673867,30.030166 C 30.803249,30.030166 39.22406,19.860104 39.22406,19.860104 C 39.22406,19.860104 30.803249,9.8120817 20.673867,9.8120817 z M 20.673867,27.019828 C 16.768563,27.019828 13.554823,23.846769 13.554823,19.900784 C 13.554823,15.99548 16.727884,12.781739 20.673867,12.781739 C 24.579169,12.781739 27.79291,15.954799 27.79291,19.900784 C 27.79291,23.846769 24.619851,27.019828 20.673867,27.019828 z" | |
73 | class="st0" /> | |
74 | <circle | |
75 | style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1.00508869;stroke-opacity:1;overflow:visible" | |
76 | sodipodi:ry="7.9000001" | |
77 | sodipodi:rx="7.9000001" | |
78 | sodipodi:cy="25.4" | |
79 | sodipodi:cx="46.299999" | |
80 | id="circle2386" | |
81 | r="7.9000001" | |
82 | cy="25.4" | |
83 | cx="46.299999" | |
84 | class="st0" | |
85 | transform="matrix(1.192052,-3.4298789e-3,4.2357937e-3,1.0633869,-34.174785,-6.9925058)" /> | |
86 | </g> | |
87 | <circle | |
88 | transform="matrix(0.8617299,0,0,0.8617299,-18.746536,-1.4676242)" | |
89 | class="st0" | |
90 | cx="46.299999" | |
91 | cy="25.4" | |
92 | r="7.9000001" | |
93 | id="circle2362" | |
94 | sodipodi:cx="46.299999" | |
95 | sodipodi:cy="25.4" | |
96 | sodipodi:rx="7.9000001" | |
97 | sodipodi:ry="7.9000001" | |
98 | style="fill:#404040;fill-opacity:1;stroke:#404040;stroke-width:0.44639024;stroke-opacity:1;overflow:visible" /> | |
99 | <circle | |
100 | transform="matrix(0.4165405,0,0,0.4165405,1.8602249,9.8155409)" | |
101 | class="st0" | |
102 | cx="46.299999" | |
103 | cy="25.4" | |
104 | r="7.9000001" | |
105 | id="circle11" | |
106 | sodipodi:cx="46.299999" | |
107 | sodipodi:cy="25.4" | |
108 | sodipodi:rx="7.9000001" | |
109 | sodipodi:ry="7.9000001" | |
110 | style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1.00508869;stroke-opacity:1;overflow:visible" /> | |
111 | </g> | |
112 | </svg> |
0 | GNU GENERAL PUBLIC LICENSE | |
1 | Version 2, June 1991 | |
2 | ||
3 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. | |
4 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
5 | Everyone is permitted to copy and distribute verbatim copies | |
6 | of this license document, but changing it is not allowed. | |
7 | ||
8 | Preamble | |
9 | ||
10 | The licenses for most software are designed to take away your | |
11 | freedom to share and change it. By contrast, the GNU General Public | |
12 | License is intended to guarantee your freedom to share and change free | |
13 | software--to make sure the software is free for all its users. This | |
14 | General Public License applies to most of the Free Software | |
15 | Foundation's software and to any other program whose authors commit to | |
16 | using it. (Some other Free Software Foundation software is covered by | |
17 | the GNU Library General Public License instead.) You can apply it to | |
18 | your programs, too. | |
19 | ||
20 | When we speak of free software, we are referring to freedom, not | |
21 | price. Our General Public Licenses are designed to make sure that you | |
22 | have the freedom to distribute copies of free software (and charge for | |
23 | this service if you wish), that you receive source code or can get it | |
24 | if you want it, that you can change the software or use pieces of it | |
25 | in new free programs; and that you know you can do these things. | |
26 | ||
27 | To protect your rights, we need to make restrictions that forbid | |
28 | anyone to deny you these rights or to ask you to surrender the rights. | |
29 | These restrictions translate to certain responsibilities for you if you | |
30 | distribute copies of the software, or if you modify it. | |
31 | ||
32 | For example, if you distribute copies of such a program, whether | |
33 | gratis or for a fee, you must give the recipients all the rights that | |
34 | you have. You must make sure that they, too, receive or can get the | |
35 | source code. And you must show them these terms so they know their | |
36 | rights. | |
37 | ||
38 | We protect your rights with two steps: (1) copyright the software, and | |
39 | (2) offer you this license which gives you legal permission to copy, | |
40 | distribute and/or modify the software. | |
41 | ||
42 | Also, for each author's protection and ours, we want to make certain | |
43 | that everyone understands that there is no warranty for this free | |
44 | software. If the software is modified by someone else and passed on, we | |
45 | want its recipients to know that what they have is not the original, so | |
46 | that any problems introduced by others will not reflect on the original | |
47 | authors' reputations. | |
48 | ||
49 | Finally, any free program is threatened constantly by software | |
50 | patents. We wish to avoid the danger that redistributors of a free | |
51 | program will individually obtain patent licenses, in effect making the | |
52 | program proprietary. To prevent this, we have made it clear that any | |
53 | patent must be licensed for everyone's free use or not licensed at all. | |
54 | ||
55 | The precise terms and conditions for copying, distribution and | |
56 | modification follow. | |
57 | ||
58 | GNU GENERAL PUBLIC LICENSE | |
59 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | |
60 | ||
61 | 0. This License applies to any program or other work which contains | |
62 | a notice placed by the copyright holder saying it may be distributed | |
63 | under the terms of this General Public License. The "Program", below, | |
64 | refers to any such program or work, and a "work based on the Program" | |
65 | means either the Program or any derivative work under copyright law: | |
66 | that is to say, a work containing the Program or a portion of it, | |
67 | either verbatim or with modifications and/or translated into another | |
68 | language. (Hereinafter, translation is included without limitation in | |
69 | the term "modification".) Each licensee is addressed as "you". | |
70 | ||
71 | Activities other than copying, distribution and modification are not | |
72 | covered by this License; they are outside its scope. The act of | |
73 | running the Program is not restricted, and the output from the Program | |
74 | is covered only if its contents constitute a work based on the | |
75 | Program (independent of having been made by running the Program). | |
76 | Whether that is true depends on what the Program does. | |
77 | ||
78 | 1. You may copy and distribute verbatim copies of the Program's | |
79 | source code as you receive it, in any medium, provided that you | |
80 | conspicuously and appropriately publish on each copy an appropriate | |
81 | copyright notice and disclaimer of warranty; keep intact all the | |
82 | notices that refer to this License and to the absence of any warranty; | |
83 | and give any other recipients of the Program a copy of this License | |
84 | along with the Program. | |
85 | ||
86 | You may charge a fee for the physical act of transferring a copy, and | |
87 | you may at your option offer warranty protection in exchange for a fee. | |
88 | ||
89 | 2. You may modify your copy or copies of the Program or any portion | |
90 | of it, thus forming a work based on the Program, and copy and | |
91 | distribute such modifications or work under the terms of Section 1 | |
92 | above, provided that you also meet all of these conditions: | |
93 | ||
94 | a) You must cause the modified files to carry prominent notices | |
95 | stating that you changed the files and the date of any change. | |
96 | ||
97 | b) You must cause any work that you distribute or publish, that in | |
98 | whole or in part contains or is derived from the Program or any | |
99 | part thereof, to be licensed as a whole at no charge to all third | |
100 | parties under the terms of this License. | |
101 | ||
102 | c) If the modified program normally reads commands interactively | |
103 | when run, you must cause it, when started running for such | |
104 | interactive use in the most ordinary way, to print or display an | |
105 | announcement including an appropriate copyright notice and a | |
106 | notice that there is no warranty (or else, saying that you provide | |
107 | a warranty) and that users may redistribute the program under | |
108 | these conditions, and telling the user how to view a copy of this | |
109 | License. (Exception: if the Program itself is interactive but | |
110 | does not normally print such an announcement, your work based on | |
111 | the Program is not required to print an announcement.) | |
112 | ||
113 | These requirements apply to the modified work as a whole. If | |
114 | identifiable sections of that work are not derived from the Program, | |
115 | and can be reasonably considered independent and separate works in | |
116 | themselves, then this License, and its terms, do not apply to those | |
117 | sections when you distribute them as separate works. But when you | |
118 | distribute the same sections as part of a whole which is a work based | |
119 | on the Program, the distribution of the whole must be on the terms of | |
120 | this License, whose permissions for other licensees extend to the | |
121 | entire whole, and thus to each and every part regardless of who wrote it. | |
122 | ||
123 | Thus, it is not the intent of this section to claim rights or contest | |
124 | your rights to work written entirely by you; rather, the intent is to | |
125 | exercise the right to control the distribution of derivative or | |
126 | collective works based on the Program. | |
127 | ||
128 | In addition, mere aggregation of another work not based on the Program | |
129 | with the Program (or with a work based on the Program) on a volume of | |
130 | a storage or distribution medium does not bring the other work under | |
131 | the scope of this License. | |
132 | ||
133 | 3. You may copy and distribute the Program (or a work based on it, | |
134 | under Section 2) in object code or executable form under the terms of | |
135 | Sections 1 and 2 above provided that you also do one of the following: | |
136 | ||
137 | a) Accompany it with the complete corresponding machine-readable | |
138 | source code, which must be distributed under the terms of Sections | |
139 | 1 and 2 above on a medium customarily used for software interchange; or, | |
140 | ||
141 | b) Accompany it with a written offer, valid for at least three | |
142 | years, to give any third party, for a charge no more than your | |
143 | cost of physically performing source distribution, a complete | |
144 | machine-readable copy of the corresponding source code, to be | |
145 | distributed under the terms of Sections 1 and 2 above on a medium | |
146 | customarily used for software interchange; or, | |
147 | ||
148 | c) Accompany it with the information you received as to the offer | |
149 | to distribute corresponding source code. (This alternative is | |
150 | allowed only for noncommercial distribution and only if you | |
151 | received the program in object code or executable form with such | |
152 | an offer, in accord with Subsection b above.) | |
153 | ||
154 | The source code for a work means the preferred form of the work for | |
155 | making modifications to it. For an executable work, complete source | |
156 | code means all the source code for all modules it contains, plus any | |
157 | associated interface definition files, plus the scripts used to | |
158 | control compilation and installation of the executable. However, as a | |
159 | special exception, the source code distributed need not include | |
160 | anything that is normally distributed (in either source or binary | |
161 | form) with the major components (compiler, kernel, and so on) of the | |
162 | operating system on which the executable runs, unless that component | |
163 | itself accompanies the executable. | |
164 | ||
165 | If distribution of executable or object code is made by offering | |
166 | access to copy from a designated place, then offering equivalent | |
167 | access to copy the source code from the same place counts as | |
168 | distribution of the source code, even though third parties are not | |
169 | compelled to copy the source along with the object code. | |
170 | ||
171 | 4. You may not copy, modify, sublicense, or distribute the Program | |
172 | except as expressly provided under this License. Any attempt | |
173 | otherwise to copy, modify, sublicense or distribute the Program is | |
174 | void, and will automatically terminate your rights under this License. | |
175 | However, parties who have received copies, or rights, from you under | |
176 | this License will not have their licenses terminated so long as such | |
177 | parties remain in full compliance. | |
178 | ||
179 | 5. You are not required to accept this License, since you have not | |
180 | signed it. However, nothing else grants you permission to modify or | |
181 | distribute the Program or its derivative works. These actions are | |
182 | prohibited by law if you do not accept this License. Therefore, by | |
183 | modifying or distributing the Program (or any work based on the | |
184 | Program), you indicate your acceptance of this License to do so, and | |
185 | all its terms and conditions for copying, distributing or modifying | |
186 | the Program or works based on it. | |
187 | ||
188 | 6. Each time you redistribute the Program (or any work based on the | |
189 | Program), the recipient automatically receives a license from the | |
190 | original licensor to copy, distribute or modify the Program subject to | |
191 | these terms and conditions. You may not impose any further | |
192 | restrictions on the recipients' exercise of the rights granted herein. | |
193 | You are not responsible for enforcing compliance by third parties to | |
194 | this License. | |
195 | ||
196 | 7. If, as a consequence of a court judgment or allegation of patent | |
197 | infringement or for any other reason (not limited to patent issues), | |
198 | conditions are imposed on you (whether by court order, agreement or | |
199 | otherwise) that contradict the conditions of this License, they do not | |
200 | excuse you from the conditions of this License. If you cannot | |
201 | distribute so as to satisfy simultaneously your obligations under this | |
202 | License and any other pertinent obligations, then as a consequence you | |
203 | may not distribute the Program at all. For example, if a patent | |
204 | license would not permit royalty-free redistribution of the Program by | |
205 | all those who receive copies directly or indirectly through you, then | |
206 | the only way you could satisfy both it and this License would be to | |
207 | refrain entirely from distribution of the Program. | |
208 | ||
209 | If any portion of this section is held invalid or unenforceable under | |
210 | any particular circumstance, the balance of the section is intended to | |
211 | apply and the section as a whole is intended to apply in other | |
212 | circumstances. | |
213 | ||
214 | It is not the purpose of this section to induce you to infringe any | |
215 | patents or other property right claims or to contest validity of any | |
216 | such claims; this section has the sole purpose of protecting the | |
217 | integrity of the free software distribution system, which is | |
218 | implemented by public license practices. Many people have made | |
219 | generous contributions to the wide range of software distributed | |
220 | through that system in reliance on consistent application of that | |
221 | system; it is up to the author/donor to decide if he or she is willing | |
222 | to distribute software through any other system and a licensee cannot | |
223 | impose that choice. | |
224 | ||
225 | This section is intended to make thoroughly clear what is believed to | |
226 | be a consequence of the rest of this License. | |
227 | ||
228 | 8. If the distribution and/or use of the Program is restricted in | |
229 | certain countries either by patents or by copyrighted interfaces, the | |
230 | original copyright holder who places the Program under this License | |
231 | may add an explicit geographical distribution limitation excluding | |
232 | those countries, so that distribution is permitted only in or among | |
233 | countries not thus excluded. In such case, this License incorporates | |
234 | the limitation as if written in the body of this License. | |
235 | ||
236 | 9. The Free Software Foundation may publish revised and/or new versions | |
237 | of the General Public License from time to time. Such new versions will | |
238 | be similar in spirit to the present version, but may differ in detail to | |
239 | address new problems or concerns. | |
240 | ||
241 | Each version is given a distinguishing version number. If the Program | |
242 | specifies a version number of this License which applies to it and "any | |
243 | later version", you have the option of following the terms and conditions | |
244 | either of that version or of any later version published by the Free | |
245 | Software Foundation. If the Program does not specify a version number of | |
246 | this License, you may choose any version ever published by the Free Software | |
247 | Foundation. | |
248 | ||
249 | 10. If you wish to incorporate parts of the Program into other free | |
250 | programs whose distribution conditions are different, write to the author | |
251 | to ask for permission. For software which is copyrighted by the Free | |
252 | Software Foundation, write to the Free Software Foundation; we sometimes | |
253 | make exceptions for this. Our decision will be guided by the two goals | |
254 | of preserving the free status of all derivatives of our free software and | |
255 | of promoting the sharing and reuse of software generally. | |
256 | ||
257 | NO WARRANTY | |
258 | ||
259 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY | |
260 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN | |
261 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES | |
262 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED | |
263 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
264 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS | |
265 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE | |
266 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, | |
267 | REPAIR OR CORRECTION. | |
268 | ||
269 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING | |
270 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR | |
271 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, | |
272 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING | |
273 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED | |
274 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY | |
275 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER | |
276 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE | |
277 | POSSIBILITY OF SUCH DAMAGES. | |
278 | ||
279 | END OF TERMS AND CONDITIONS | |
280 | ||
281 | How to Apply These Terms to Your New Programs | |
282 | ||
283 | If you develop a new program, and you want it to be of the greatest | |
284 | possible use to the public, the best way to achieve this is to make it | |
285 | free software which everyone can redistribute and change under these terms. | |
286 | ||
287 | To do so, attach the following notices to the program. It is safest | |
288 | to attach them to the start of each source file to most effectively | |
289 | convey the exclusion of warranty; and each file should have at least | |
290 | the "copyright" line and a pointer to where the full notice is found. | |
291 | ||
292 | <one line to give the program's name and a brief idea of what it does.> | |
293 | Copyright (C) <year> <name of author> | |
294 | ||
295 | This program is free software; you can redistribute it and/or modify | |
296 | it under the terms of the GNU General Public License as published by | |
297 | the Free Software Foundation; either version 2 of the License, or | |
298 | (at your option) any later version. | |
299 | ||
300 | This program is distributed in the hope that it will be useful, | |
301 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
302 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
303 | GNU General Public License for more details. | |
304 | ||
305 | You should have received a copy of the GNU General Public License | |
306 | along with this program; if not, write to the Free Software | |
307 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
308 | ||
309 | ||
310 | Also add information on how to contact you by electronic and paper mail. | |
311 | ||
312 | If the program is interactive, make it output a short notice like this | |
313 | when it starts in an interactive mode: | |
314 | ||
315 | Gnomovision version 69, Copyright (C) year name of author | |
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. | |
317 | This is free software, and you are welcome to redistribute it | |
318 | under certain conditions; type `show c' for details. | |
319 | ||
320 | The hypothetical commands `show w' and `show c' should show the appropriate | |
321 | parts of the General Public License. Of course, the commands you use may | |
322 | be called something other than `show w' and `show c'; they could even be | |
323 | mouse-clicks or menu items--whatever suits your program. | |
324 | ||
325 | You should also get your employer (if you work as a programmer) or your | |
326 | school, if any, to sign a "copyright disclaimer" for the program, if | |
327 | necessary. Here is a sample; alter the names: | |
328 | ||
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program | |
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. | |
331 | ||
332 | <signature of Ty Coon>, 1 April 1989 | |
333 | Ty Coon, President of Vice | |
334 | ||
335 | This General Public License does not permit incorporating your program into | |
336 | proprietary programs. If your program is a subroutine library, you may | |
337 | consider it more useful to permit linking proprietary applications with the | |
338 | library. If this is what you want to do, use the GNU Library General | |
339 | Public License instead of this License. |
0 | About | |
1 | ----- | |
2 | ||
3 | A set of sugar components/libraries/etc to simplify writing activities. | |
4 | ||
5 | Cornerstone purposes for this project: | |
6 | * Total backwards compatibility for sugar-port API | |
7 | * Run on all sugar platforms beginning from 0.82 | |
8 | ||
9 | In most cases sugar-port could be embedded to activity's directory tree. | |
10 | There is no need to include the whole sugar-port project only top level | |
11 | files/directories you are using directly - sugar-port's top level entities | |
12 | don't import each other. | |
13 | ||
14 | Get it | |
15 | ------ | |
16 | ||
17 | http://wiki.sugarlabs.org/go/Development_Team/sugar-port |
0 | # This program is free software; you can redistribute it and/or modify | |
1 | # it under the terms of the GNU General Public License as published by | |
2 | # the Free Software Foundation; either version 2 of the License, or | |
3 | # (at your option) any later version. | |
4 | # | |
5 | # This program is distributed in the hope that it will be useful, | |
6 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
7 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
8 | # GNU General Public License for more details. | |
9 | # | |
10 | # You should have received a copy of the GNU General Public License | |
11 | # along with this program; if not, write to the Free Software | |
12 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
13 | ||
14 | """Object chooser method""" | |
15 | ||
16 | import gtk | |
17 | import logging | |
18 | ||
19 | from sugar import mime | |
20 | from sugar.graphics.objectchooser import ObjectChooser | |
21 | ||
22 | TEXT = hasattr(mime, 'GENERIC_TYPE_TEXT') and mime.GENERIC_TYPE_TEXT or None | |
23 | IMAGE = hasattr(mime, 'GENERIC_TYPE_IMAGE') and mime.GENERIC_TYPE_IMAGE or None | |
24 | AUDIO = hasattr(mime, 'GENERIC_TYPE_AUDIO') and mime.GENERIC_TYPE_AUDIO or None | |
25 | VIDEO = hasattr(mime, 'GENERIC_TYPE_VIDEO') and mime.GENERIC_TYPE_VIDEO or None | |
26 | LINK = hasattr(mime, 'GENERIC_TYPE_LINK') and mime.GENERIC_TYPE_LINK or None | |
27 | ||
28 | def pick(cb=None, default=None, parent=None, what=None): | |
29 | """ | |
30 | Opens object chooser. | |
31 | ||
32 | Method returns: | |
33 | ||
34 | * cb(jobject), if object was choosen and cb is not None | |
35 | * jobject, if object was choosen and cb is None | |
36 | * default, otherwise | |
37 | ||
38 | NOTE: 'what' makes sense only for sugar >= 0.84 | |
39 | """ | |
40 | what = what and {'what_filter': what} or {} | |
41 | chooser = ObjectChooser(parent=parent, **what) | |
42 | ||
43 | jobject = None | |
44 | out = None | |
45 | ||
46 | try: | |
47 | if chooser.run() == gtk.RESPONSE_ACCEPT: | |
48 | jobject = chooser.get_selected_object() | |
49 | logging.debug('ObjectChooser: %r' % jobject) | |
50 | ||
51 | if jobject and jobject.file_path: | |
52 | if cb: | |
53 | out = cb(jobject) | |
54 | else: | |
55 | out = jobject | |
56 | finally: | |
57 | if jobject and id(jobject) != id(out): | |
58 | jobject.destroy() | |
59 | chooser.destroy() | |
60 | del chooser | |
61 | ||
62 | if out: | |
63 | return out | |
64 | else: | |
65 | return default |
14 | 14 | # You should have received a copy of the GNU General Public License |
15 | 15 | # along with this program; if not, write to the Free Software |
16 | 16 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
17 | ||
17 | 18 | from gettext import gettext as _ |
18 | 19 | import logging |
19 | 20 | import os |
20 | 21 | import time |
22 | import dbus | |
21 | 23 | |
22 | 24 | import abiword |
23 | 25 | import gtk |
24 | 26 | |
27 | from sugar.graphics.radiopalette import RadioMenuButton | |
25 | 28 | from sugar.graphics.icon import Icon |
26 | 29 | from sugar.graphics.toolbutton import ToolButton |
27 | 30 | from sugar.graphics.toggletoolbutton import ToggleToolButton |
28 | from sugar.graphics.combobox import ComboBox | |
29 | 31 | from sugar.graphics.colorbutton import ColorToolButton |
30 | 32 | from sugar.graphics.toolcombobox import ToolComboBox |
31 | 33 | from sugar.graphics.objectchooser import ObjectChooser |
32 | 34 | from sugar.graphics import iconentry |
33 | from sugar.activity.activity import ActivityToolbar | |
34 | from sugar.activity.activity import EditToolbar | |
35 | from sugar.activity import activity | |
35 | 36 | from sugar.graphics.menuitem import MenuItem |
37 | from sugar.graphics.palette import Palette | |
36 | 38 | from sugar.datastore import datastore |
37 | 39 | from sugar import mime |
40 | from port import chooser | |
38 | 41 | import sugar.profile |
39 | 42 | |
40 | import dbus | |
43 | import widgets | |
41 | 44 | |
42 | 45 | logger = logging.getLogger('write-activity') |
43 | ||
44 | #ick | |
45 | TOOLBAR_ACTIVITY = 0 | |
46 | TOOLBAR_EDIT = 1 | |
47 | TOOLBAR_TEXT = 2 | |
48 | TOOLBAR_IMAGE = 3 | |
49 | TOOLBAR_TABLE = 4 | |
50 | TOOLBAR_VIEW = 5 | |
51 | 46 | |
52 | 47 | class WriteActivityToolbarExtension: |
53 | 48 | |
107 | 102 | fileObject.destroy() |
108 | 103 | del fileObject |
109 | 104 | |
110 | class WriteEditToolbar(EditToolbar): | |
111 | ||
112 | def __init__(self, toolbox, abiword_canvas, text_toolbar): | |
113 | ||
114 | EditToolbar.__init__(self) | |
115 | ||
116 | self._toolbox = toolbox | |
105 | class SearchToolbar(gtk.Toolbar): | |
106 | ||
107 | def __init__(self, abiword_canvas, text_toolbar): | |
108 | ||
109 | gtk.Toolbar.__init__(self) | |
110 | ||
117 | 111 | self._abiword_canvas = abiword_canvas |
118 | 112 | self._text_toolbar = text_toolbar |
119 | ||
120 | # connect existing buttons | |
121 | self.undo.set_sensitive(False) | |
122 | self.redo.set_sensitive(False) | |
123 | self.undo.connect('clicked', self._undo_cb) | |
124 | self.redo.connect('clicked', self._redo_cb) | |
125 | self.copy.connect('clicked', self._copy_cb) | |
126 | self.paste.connect('clicked', self._paste_cb) | |
127 | self._abiword_canvas.connect("can-undo", self._can_undo_cb) | |
128 | self._abiword_canvas.connect("can-redo", self._can_redo_cb) | |
129 | ||
130 | # make expanded non-drawn visible separator to make the search stuff right-align | |
131 | separator = gtk.SeparatorToolItem() | |
132 | separator.props.draw = False | |
133 | separator.set_expand(True) | |
134 | self.insert(separator, -1) | |
135 | separator.show() | |
136 | 113 | |
137 | 114 | # setup the search options |
138 | 115 | self._search_entry = iconentry.IconEntry() |
163 | 140 | self._findprev.set_sensitive(False) |
164 | 141 | self._findnext.set_sensitive(False) |
165 | 142 | |
166 | def _undo_cb(self, button): | |
167 | self._abiword_canvas.undo() | |
168 | ||
169 | def _redo_cb(self, button): | |
170 | self._abiword_canvas.redo() | |
171 | ||
172 | def _copy_cb(self, button): | |
173 | self._abiword_canvas.copy() | |
174 | ||
175 | def _paste_cb(self, button): | |
176 | self._abiword_canvas.paste() | |
177 | ||
178 | def _can_undo_cb(self, canvas, can_undo): | |
179 | self.undo.set_sensitive(can_undo) | |
180 | ||
181 | def _can_redo_cb(self, canvas, can_redo): | |
182 | self.redo.set_sensitive(can_redo) | |
183 | ||
184 | 143 | def _search_entry_activated_cb(self, entry): |
185 | 144 | logger.debug('_search_entry_activated_cb') |
186 | 145 | if not self._search_entry.props.text: |
187 | 146 | return |
188 | 147 | |
189 | 148 | # find the next entry |
190 | id = self._text_toolbar.get_text_selected_handler(); | |
191 | self._abiword_canvas.handler_block(id) | |
192 | 149 | self._abiword_canvas.find_next(False) |
193 | self._abiword_canvas.handler_unblock(id) | |
194 | 150 | |
195 | 151 | def _search_entry_changed_cb(self, entry): |
196 | logger.debug('_search_entry_changed_cb search for \'%s\'', self._search_entry.props.text) | |
197 | ||
152 | logger.debug('_search_entry_changed_cb search for \'%s\'', | |
153 | self._search_entry.props.text) | |
154 | ||
198 | 155 | if not self._search_entry.props.text: |
199 | 156 | self._search_entry.activate() |
200 | 157 | # set the button contexts |
209 | 166 | self._findnext.set_sensitive(True) |
210 | 167 | |
211 | 168 | # immediately start seaching |
212 | id = self._text_toolbar.get_text_selected_handler(); | |
213 | self._abiword_canvas.handler_block(id) | |
214 | 169 | self._abiword_canvas.find_next(True) |
215 | self._abiword_canvas.handler_unblock(id) | |
216 | 170 | |
217 | 171 | def _findprev_cb(self, button): |
218 | 172 | logger.debug('_findprev_cb') |
219 | 173 | if self._search_entry.props.text: |
220 | id = self._text_toolbar.get_text_selected_handler(); | |
221 | self._abiword_canvas.handler_block(id) | |
222 | 174 | self._abiword_canvas.find_prev() |
223 | self._abiword_canvas.handler_unblock(id) | |
224 | 175 | else: |
225 | 176 | logger.debug('nothing to search for!') |
226 | 177 | |
227 | 178 | def _findnext_cb(self, button): |
228 | 179 | logger.debug('_findnext_cb') |
229 | 180 | if self._search_entry.props.text: |
230 | id = self._text_toolbar.get_text_selected_handler(); | |
231 | self._abiword_canvas.handler_block(id) | |
232 | 181 | self._abiword_canvas.find_next(False) |
233 | self._abiword_canvas.handler_unblock(id) | |
234 | 182 | else: |
235 | 183 | logger.debug('nothing to search for!') |
236 | 184 | |
245 | 193 | self.insert(tool_item, -1) |
246 | 194 | tool_item.show() |
247 | 195 | |
248 | class TextToolbar(gtk.Toolbar): | |
249 | _ACTION_ALIGNMENT_LEFT = 0 | |
250 | _ACTION_ALIGNMENT_CENTER = 1 | |
251 | _ACTION_ALIGNMENT_RIGHT = 2 | |
252 | _ACTION_ALIGNMENT_JUSTIFY = 3 | |
253 | ||
254 | def __init__(self, toolbox, abiword_canvas): | |
255 | self._colorseldlg = None | |
256 | ||
196 | class InsertToolbar(gtk.Toolbar): | |
197 | def __init__(self, abiword_canvas): | |
257 | 198 | gtk.Toolbar.__init__(self) |
258 | 199 | |
259 | self._toolbox = toolbox | |
260 | self._abiword_canvas = abiword_canvas | |
261 | ||
262 | self._bold = ToggleToolButton('format-text-bold') | |
263 | self._bold.set_tooltip(_('Bold')) | |
264 | self._bold_id = self._bold.connect('clicked', self._bold_cb) | |
265 | self._abiword_canvas.connect('bold', self._isBold_cb) | |
266 | self.insert(self._bold, -1) | |
267 | self._bold.show() | |
268 | ||
269 | self._italic = ToggleToolButton('format-text-italic') | |
270 | self._italic.set_tooltip(_('Italic')) | |
271 | self._italic_id = self._italic.connect('clicked', self._italic_cb) | |
272 | self._abiword_canvas.connect('italic', self._isItalic_cb) | |
273 | self.insert(self._italic, -1) | |
274 | self._italic.show() | |
275 | ||
276 | self._underline = ToggleToolButton('format-text-underline') | |
277 | self._underline.set_tooltip(_('Underline')) | |
278 | self._underline_id = self._underline.connect('clicked', self._underline_cb) | |
279 | self._abiword_canvas.connect('underline', self._isUnderline_cb) | |
280 | self.insert(self._underline, -1) | |
281 | self._underline.show() | |
282 | ||
283 | self._text_color = ColorToolButton() | |
284 | self._text_color_id = self._text_color.connect('color-set', self._text_color_cb) | |
285 | tool_item = gtk.ToolItem() | |
286 | tool_item.add(self._text_color) | |
287 | self.insert(tool_item, -1) | |
288 | tool_item.show_all() | |
289 | ||
290 | separator = gtk.SeparatorToolItem() | |
291 | separator.set_draw(True) | |
292 | separator.show() | |
293 | self.insert(separator, -1) | |
294 | ||
295 | self._font_size_icon = Icon(icon_name="format-text-size", icon_size=gtk.ICON_SIZE_LARGE_TOOLBAR) | |
296 | tool_item = gtk.ToolItem() | |
297 | tool_item.add(self._font_size_icon) | |
298 | self.insert(tool_item, -1) | |
299 | tool_item.show_all() | |
300 | ||
301 | self._font_size_combo = ComboBox() | |
302 | self._font_sizes = ['8', '9', '10', '11', '12', '14', '16', '20', '22', '24', '26', '28', '36', '48', '72'] | |
303 | self._font_size_changed_id = self._font_size_combo.connect('changed', self._font_size_changed_cb) | |
304 | for i, s in enumerate(self._font_sizes): | |
305 | self._font_size_combo.append_item(i, s, None) | |
306 | if s == '12': | |
307 | self._font_size_combo.set_active(i) | |
308 | tool_item = ToolComboBox(self._font_size_combo) | |
309 | self.insert(tool_item, -1); | |
310 | tool_item.show() | |
311 | ||
312 | self._has_custom_fonts = False | |
313 | ||
314 | self._font_combo = ComboBox() | |
315 | self._fonts = sorted(self._abiword_canvas.get_font_names()) | |
316 | self._fonts_changed_id = self._font_combo.connect('changed', self._font_changed_cb) | |
317 | for i, f in enumerate(self._fonts): | |
318 | self._font_combo.append_item(i, f, None) | |
319 | if f == 'Times New Roman': | |
320 | self._font_combo.set_active(i) | |
321 | tool_item = ToolComboBox(self._font_combo) | |
322 | self.insert(tool_item, -1); | |
323 | tool_item.show() | |
324 | ||
325 | separator = gtk.SeparatorToolItem() | |
326 | separator.set_draw(True) | |
327 | self.insert(separator, -1) | |
328 | separator.show() | |
329 | ||
330 | self._alignment = ComboBox() | |
331 | self._alignment.append_item(self._ACTION_ALIGNMENT_LEFT, None, | |
332 | 'format-justify-left') | |
333 | self._alignment.append_item(self._ACTION_ALIGNMENT_CENTER, None, | |
334 | 'format-justify-center') | |
335 | self._alignment.append_item(self._ACTION_ALIGNMENT_RIGHT, None, | |
336 | 'format-justify-right') | |
337 | self._alignment.append_item(self._ACTION_ALIGNMENT_JUSTIFY, None, | |
338 | 'format-justify-fill') | |
339 | self._alignment_changed_id = \ | |
340 | self._alignment.connect('changed', self._alignment_changed_cb) | |
341 | tool_item = ToolComboBox(self._alignment) | |
342 | self.insert(tool_item, -1); | |
343 | tool_item.show() | |
344 | ||
345 | self._abiword_canvas.connect('color', self._color_cb) | |
346 | ||
347 | self._abiword_canvas.connect('font-size', self._font_size_cb) | |
348 | self._abiword_canvas.connect('font-family', self._font_family_cb) | |
349 | ||
350 | self._abiword_canvas.connect('left-align', self._isLeftAlign_cb) | |
351 | self._abiword_canvas.connect('center-align', self._isCenterAlign_cb) | |
352 | self._abiword_canvas.connect('right-align', self._isRightAlign_cb) | |
353 | self._abiword_canvas.connect('justify-align', self._isJustifyAlign_cb) | |
354 | ||
355 | self._text_selected_handler = self._abiword_canvas.connect('text-selected', self._text_selected_cb) | |
356 | ||
357 | def get_text_selected_handler(self): | |
358 | return self._text_selected_handler | |
359 | ||
360 | def _add_widget(self, widget, expand=False): | |
361 | tool_item = gtk.ToolItem() | |
362 | tool_item.set_expand(expand) | |
363 | ||
364 | tool_item.add(widget) | |
365 | widget.show() | |
366 | ||
367 | self.insert(tool_item, -1) | |
368 | tool_item.show() | |
369 | ||
370 | def setToggleButtonState(self,button,b,id): | |
371 | button.handler_block(id) | |
372 | button.set_active(b) | |
373 | button.handler_unblock(id) | |
374 | ||
375 | def _bold_cb(self, button): | |
376 | self._abiword_canvas.toggle_bold() | |
377 | ||
378 | def _isBold_cb(self, abi, b): | |
379 | self.setToggleButtonState(self._bold,b,self._bold_id) | |
380 | ||
381 | def _italic_cb(self, button): | |
382 | self._abiword_canvas.toggle_italic() | |
383 | ||
384 | def _isItalic_cb(self, abi, b): | |
385 | self.setToggleButtonState(self._italic, b, self._italic_id) | |
386 | ||
387 | def _underline_cb(self, button): | |
388 | self._abiword_canvas.toggle_underline() | |
389 | ||
390 | def _isUnderline_cb(self, abi, b): | |
391 | self.setToggleButtonState(self._underline, b, self._underline_id) | |
392 | ||
393 | def _color_cb(self, abi, r, g, b): | |
394 | self._text_color.set_color(gtk.gdk.Color(r * 256, g * 256, b * 256)) | |
395 | ||
396 | def _text_color_cb(self, button): | |
397 | newcolor = self._text_color.get_color() | |
398 | self._abiword_canvas.set_text_color(int(newcolor.red / 256.0), | |
399 | int(newcolor.green / 256.0), | |
400 | int(newcolor.blue / 256.0)) | |
401 | ||
402 | def _font_size_cb(self, abi, size): | |
403 | for i, s in enumerate(self._font_sizes): | |
404 | if int(s) == int(size): | |
405 | self._font_size_combo.handler_block(self._font_size_changed_id) | |
406 | self._font_size_combo.set_active(i) | |
407 | self._font_size_combo.handler_unblock(self._font_size_changed_id) | |
408 | break; | |
409 | ||
410 | def _font_size_changed_cb(self, combobox): | |
411 | if self._font_size_combo.get_active() != -1: | |
412 | logger.debug('Setting font size: %d', int(self._font_sizes[self._font_size_combo.get_active()])) | |
413 | self._abiword_canvas.set_font_size(self._font_sizes[self._font_size_combo.get_active()]) | |
414 | ||
415 | def _font_family_cb(self, abi, font_family): | |
416 | font_index = -1 | |
417 | ||
418 | # search for the font name in our font list | |
419 | for i, f in enumerate(self._fonts): | |
420 | if f == font_family: | |
421 | font_index = i | |
422 | break; | |
423 | ||
424 | # if we don't know this font yet, then add it (temporary) to the list | |
425 | if font_index == -1: | |
426 | logger.debug('Font not found in font list: %s', font_family) | |
427 | if not self._has_custom_fonts: | |
428 | # add a separator to seperate the non-available fonts from | |
429 | # the available ones | |
430 | self._fonts.append('') # ugly | |
431 | self._font_combo.append_separator() | |
432 | self._has_custom_fonts = True | |
433 | # add the new font | |
434 | self._fonts.append(font_family) | |
435 | self._font_combo.append_item(0, font_family, None) | |
436 | # see how many fonts we have now, so we can select the last one | |
437 | model = self._font_combo.get_model() | |
438 | num_children = model.iter_n_children(None) | |
439 | logger.debug('Number of fonts in the list: %d', num_children) | |
440 | font_index = num_children-1 | |
441 | ||
442 | # activate the found font | |
443 | if (font_index > -1): | |
444 | self._font_combo.handler_block(self._fonts_changed_id) | |
445 | self._font_combo.set_active(font_index) | |
446 | self._font_combo.handler_unblock(self._fonts_changed_id) | |
447 | ||
448 | def _font_changed_cb(self, combobox): | |
449 | if self._font_combo.get_active() != -1: | |
450 | logger.debug('Setting font name: %s', self._fonts[self._font_combo.get_active()]) | |
451 | self._abiword_canvas.set_font_name(self._fonts[self._font_combo.get_active()]) | |
452 | ||
453 | def _alignment_changed_cb(self, combobox): | |
454 | if self._alignment.get_active() == self._ACTION_ALIGNMENT_LEFT: | |
455 | self._abiword_canvas.align_left() | |
456 | elif self._alignment.get_active() == self._ACTION_ALIGNMENT_CENTER: | |
457 | self._abiword_canvas.align_center() | |
458 | elif self._alignment.get_active() == self._ACTION_ALIGNMENT_RIGHT: | |
459 | self._abiword_canvas.align_right() | |
460 | elif self._alignment.get_active() == self._ACTION_ALIGNMENT_JUSTIFY: | |
461 | self._abiword_canvas.align_justify() | |
462 | else: | |
463 | raise ValueError, 'Unknown option in alignment combobox.' | |
464 | ||
465 | def _update_alignment_icon(self, index): | |
466 | self._alignment.handler_block(self._alignment_changed_id) | |
467 | try: | |
468 | self._alignment.set_active(index) | |
469 | finally: | |
470 | self._alignment.handler_unblock(self._alignment_changed_id) | |
471 | ||
472 | def _isLeftAlign_cb(self, abi, b): | |
473 | if b: | |
474 | self._update_alignment_icon(self._ACTION_ALIGNMENT_LEFT) | |
475 | ||
476 | def _isCenterAlign_cb(self, abi, b): | |
477 | if b: | |
478 | self._update_alignment_icon(self._ACTION_ALIGNMENT_CENTER) | |
479 | ||
480 | def _isRightAlign_cb(self, abi, b): | |
481 | if b: | |
482 | self._update_alignment_icon(self._ACTION_ALIGNMENT_RIGHT) | |
483 | ||
484 | def _isJustifyAlign_cb(self, abi, b): | |
485 | if b: | |
486 | self._update_alignment_icon(self._ACTION_ALIGNMENT_JUSTIFY) | |
487 | ||
488 | def _text_selected_cb(self, abi, b): | |
489 | if b: | |
490 | self._toolbox.set_current_toolbar(TOOLBAR_TEXT) | |
491 | self._abiword_canvas.grab_focus() # hack: bad toolbox, bad! | |
492 | ||
493 | class ImageToolbar(gtk.Toolbar): | |
494 | def __init__(self, toolbox, abiword_canvas, parent): | |
495 | gtk.Toolbar.__init__(self) | |
496 | ||
497 | self._toolbox = toolbox | |
498 | self._abiword_canvas = abiword_canvas | |
499 | self._parent = parent | |
500 | ||
501 | self._image = ToolButton('insert-image') | |
502 | self._image.set_tooltip(_('Insert Image')) | |
503 | self._image_id = self._image.connect('clicked', self._image_cb) | |
504 | self.insert(self._image, -1) | |
505 | self._image.show() | |
506 | ||
507 | self._abiword_canvas.connect('image-selected', self._image_selected_cb) | |
508 | ||
509 | def _image_cb(self, button): | |
510 | chooser = ObjectChooser(_('Choose image'), self._parent, | |
511 | gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, | |
512 | what_filter=mime.GENERIC_TYPE_IMAGE) | |
513 | try: | |
514 | result = chooser.run() | |
515 | if result == gtk.RESPONSE_ACCEPT: | |
516 | logging.debug('ObjectChooser: %r' % chooser.get_selected_object()) | |
517 | jobject = chooser.get_selected_object() | |
518 | if jobject and jobject.file_path: | |
519 | self._abiword_canvas.insert_image(jobject.file_path, True) | |
520 | finally: | |
521 | chooser.destroy() | |
522 | del chooser | |
523 | ||
524 | def _image_selected_cb(self, abi, b): | |
525 | if b: | |
526 | self._toolbox.set_current_toolbar(TOOLBAR_IMAGE) | |
527 | self._abiword_canvas.grab_focus() # hack: bad toolbox, bad! | |
528 | ||
529 | class TableToolbar(gtk.Toolbar): | |
530 | def __init__(self, toolbox, abiword_canvas): | |
531 | gtk.Toolbar.__init__(self) | |
532 | ||
533 | self._toolbox = toolbox | |
534 | 200 | self._abiword_canvas = abiword_canvas |
535 | 201 | |
536 | 202 | self._table = abiword.TableCreator() |
537 | 203 | self._table.set_labels(_('Table'), _('Cancel')) |
538 | 204 | self._table_id = self._table.connect('selected', self._table_cb) |
539 | self._table.show() | |
540 | 205 | tool_item = gtk.ToolItem() |
541 | 206 | tool_item.add(self._table) |
542 | 207 | self.insert(tool_item, -1) |
546 | 211 | self._table_rows_after.set_tooltip(_('Insert Row')) |
547 | 212 | self._table_rows_after_id = self._table_rows_after.connect('clicked', self._table_rows_after_cb) |
548 | 213 | self.insert(self._table_rows_after, -1) |
549 | self._table_rows_after.show() | |
550 | 214 | |
551 | 215 | self._table_delete_rows = ToolButton('row-remove') |
552 | 216 | self._table_delete_rows.set_tooltip(_('Delete Row')) |
553 | 217 | self._table_delete_rows_id = self._table_delete_rows.connect('clicked', self._table_delete_rows_cb) |
554 | 218 | self.insert(self._table_delete_rows, -1) |
555 | self._table_delete_rows.show() | |
556 | 219 | |
557 | 220 | self._table_cols_after = ToolButton('column-insert') |
558 | 221 | self._table_cols_after.set_tooltip(_('Insert Column')) |
559 | 222 | self._table_cols_after_id = self._table_cols_after.connect('clicked', self._table_cols_after_cb) |
560 | 223 | self.insert(self._table_cols_after, -1) |
561 | self._table_cols_after.show() | |
562 | 224 | |
563 | 225 | self._table_delete_cols = ToolButton('column-remove') |
564 | 226 | self._table_delete_cols.set_tooltip(_('Delete Column')) |
565 | 227 | self._table_delete_cols_id = self._table_delete_cols.connect('clicked', self._table_delete_cols_cb) |
566 | 228 | self.insert(self._table_delete_cols, -1) |
567 | self._table_delete_cols.show() | |
229 | ||
230 | separator = gtk.SeparatorToolItem() | |
231 | self.insert(separator, -1) | |
232 | ||
233 | image = ToolButton('insert-image') | |
234 | image.set_tooltip(_('Insert Image')) | |
235 | self._image_id = image.connect('clicked', self._image_cb) | |
236 | self.insert(image, -1) | |
237 | ||
238 | self.show_all() | |
568 | 239 | |
569 | 240 | self._abiword_canvas.connect('table-state', self._isTable_cb) |
241 | #self._abiword_canvas.connect('image-selected', self._image_selected_cb) | |
242 | ||
243 | def _image_cb(self, button): | |
244 | def cb(object): | |
245 | logging.debug('ObjectChooser: %r' % object) | |
246 | self._abiword_canvas.insert_image(object.file_path, True) | |
247 | chooser.pick(what=chooser.IMAGE, cb=cb) | |
570 | 248 | |
571 | 249 | def _table_cb(self, abi, rows, cols): |
572 | 250 | self._abiword_canvas.insert_table(rows,cols) |
588 | 266 | self._table_delete_rows.set_sensitive(b) |
589 | 267 | self._table_cols_after.set_sensitive(b) |
590 | 268 | self._table_delete_cols.set_sensitive(b) |
591 | if b: | |
592 | self._toolbox.set_current_toolbar(TOOLBAR_TABLE) | |
593 | self._abiword_canvas.grab_focus() # hack: bad toolbox, bad! | |
594 | ||
595 | class FormatToolbar(gtk.Toolbar): | |
596 | def __init__(self, toolbox, abiword_canvas): | |
597 | gtk.Toolbar.__init__(self) | |
598 | ||
599 | self._toolbox = toolbox | |
600 | self._abiword_canvas = abiword_canvas | |
601 | ||
602 | style_label = gtk.Label(_("Style: ")) | |
603 | style_label.show() | |
604 | tool_item_style_label = gtk.ToolItem() | |
605 | tool_item_style_label.add(style_label) | |
606 | self.insert(tool_item_style_label, -1) | |
607 | tool_item_style_label.show() | |
608 | ||
609 | self._has_custom_styles = False | |
610 | ||
611 | self._style_combo = ComboBox() | |
612 | self._styles = [['Heading 1',_('Heading 1')], | |
613 | ['Heading 2',_('Heading 2')], | |
614 | ['Heading 3',_('Heading 3')], | |
615 | ['Heading 4',_('Heading 4')], | |
616 | ['Bullet List',_('Bullet List')], | |
617 | ['Dashed List',_('Dashed List')], | |
618 | ['Numbered List',_('Numbered List')], | |
619 | ['Lower Case List',_('Lower Case List')], | |
620 | ['Upper Case List',_('Upper Case List')], | |
621 | ['Block Text',_('Block Text')], | |
622 | ['Normal',_('Normal')], | |
623 | ['Plain Text',_('Plain Text')]] | |
624 | self._style_changed_id = self._style_combo.connect('changed', self._style_changed_cb) | |
625 | for i, s in enumerate(self._styles): | |
626 | self._style_combo.append_item(i, s[1], None) | |
627 | if s[0] == 'Normal': | |
628 | self._style_combo.set_active(i) | |
629 | tool_item = ToolComboBox(self._style_combo) | |
630 | self.insert(tool_item, -1); | |
631 | tool_item.show() | |
632 | ||
633 | self._abiword_canvas.connect('style-name', self._style_cb) | |
634 | ||
635 | def _style_cb(self, abi, style_name): | |
636 | style_index = -1 | |
637 | for i, s in enumerate(self._styles): | |
638 | if s[0] == style_name: | |
639 | style_index = i | |
640 | break; | |
641 | ||
642 | # if we don't know this style yet, then add it (temporary) to the list | |
643 | if style_index == -1: | |
644 | logger.debug('Style not found in style list: %s', style_name) | |
645 | if not self._has_custom_styles: | |
646 | # add a separator to seperate the non-available styles from | |
647 | # the available ones | |
648 | self._styles.append(['','']) # ugly | |
649 | self._style_combo.append_separator() | |
650 | self._has_custom_styles = True | |
651 | # add the new style | |
652 | self._styles.append([style_name, style_name]) | |
653 | self._style_combo.append_item(0, style_name, None) | |
654 | # see how many styles we have now, so we can select the last one | |
655 | model = self._style_combo.get_model() | |
656 | num_children = model.iter_n_children(None) | |
657 | logger.debug('Number of styles in the list: %d', num_children) | |
658 | style_index = num_children-1 | |
659 | ||
660 | if style_index > -1: | |
661 | self._style_combo.handler_block(self._style_changed_id) | |
662 | self._style_combo.set_active(style_index) | |
663 | self._style_combo.handler_unblock(self._style_changed_id) | |
664 | ||
665 | def _style_changed_cb(self, combobox): | |
666 | if self._style_combo.get_active() != -1: | |
667 | logger.debug('Setting style name: %s', self._styles[self._style_combo.get_active()][0]) | |
668 | self._abiword_canvas.set_style(self._styles[self._style_combo.get_active()][0]) | |
669 | 269 | |
670 | 270 | class ViewToolbar(gtk.Toolbar): |
671 | 271 | def __init__(self, abiword_canvas): |
740 | 340 | def set_zoom_percentage(self, zoom): |
741 | 341 | self._zoom_percentage = zoom |
742 | 342 | self._abiword_canvas.set_zoom_percentage(self._zoom_percentage) |
743 | ||
343 | ||
744 | 344 | def _zoom_cb(self, canvas, zoom): |
745 | 345 | self._zoom_spin.handler_block(self._zoom_spin_id) |
746 | 346 | try: |
781 | 381 | finally: |
782 | 382 | self._page_spin.handler_unblock(self._page_spin_id) |
783 | 383 | |
384 | class TextToolbar(gtk.Toolbar): | |
385 | def __init__(self, abiword_canvas): | |
386 | gtk.Toolbar.__init__(self) | |
387 | ||
388 | self._abiword_canvas = abiword_canvas | |
389 | ||
390 | self.insert(ToolComboBox(widgets.StyleCombo(abiword_canvas)), -1) | |
391 | self.insert(activity.separator(), -1) | |
392 | ||
393 | bold = ToggleToolButton('format-text-bold') | |
394 | bold.set_tooltip(_('Bold')) | |
395 | bold_id = bold.connect('clicked', lambda sender: | |
396 | abiword_canvas.toggle_bold()) | |
397 | self._abiword_canvas.connect('bold', lambda abi, b: | |
398 | self.setToggleButtonState(bold, b, bold_id)) | |
399 | self.insert(bold, -1) | |
400 | ||
401 | italic = ToggleToolButton('format-text-italic') | |
402 | italic.set_tooltip(_('Italic')) | |
403 | italic_id = italic.connect('clicked', lambda sender: | |
404 | abiword_canvas.toggle_italic()) | |
405 | self._abiword_canvas.connect('italic', lambda abi, b: | |
406 | self.setToggleButtonState(italic, b, italic_id)) | |
407 | self.insert(italic, -1) | |
408 | ||
409 | underline = ToggleToolButton('format-text-underline') | |
410 | underline.set_tooltip(_('Underline')) | |
411 | underline_id = underline.connect('clicked', lambda sender: | |
412 | abiword_canvas.toggle_underline()) | |
413 | self._abiword_canvas.connect('underline', lambda abi, b: | |
414 | self.setToggleButtonState(underline, b, underline_id)) | |
415 | self.insert(underline, -1) | |
416 | ||
417 | self.insert(activity.separator(), -1) | |
418 | ||
419 | alignment = RadioMenuButton(palette=widgets.Alignment(abiword_canvas)) | |
420 | self.insert(alignment, -1) | |
421 | ||
422 | lists = RadioMenuButton(palette=widgets.Lists(abiword_canvas)) | |
423 | self.insert(lists, -1) | |
424 | ||
425 | self.insert(activity.separator(), -1) | |
426 | ||
427 | color = ColorToolButton() | |
428 | color.connect('color-set', self._text_color_cb) | |
429 | tool_item = gtk.ToolItem() | |
430 | tool_item.add(color) | |
431 | self.insert(tool_item, -1) | |
432 | self._abiword_canvas.connect('color', lambda abi, r, g, b: | |
433 | color.set_color(gtk.gdk.Color(r * 256, g * 256, b * 256))) | |
434 | ||
435 | self.show_all() | |
436 | ||
437 | def setToggleButtonState(self,button,b,id): | |
438 | button.handler_block(id) | |
439 | button.set_active(b) | |
440 | button.handler_unblock(id) | |
441 | ||
442 | def _text_color_cb(self, button): | |
443 | newcolor = button.get_color() | |
444 | self._abiword_canvas.set_text_color(int(newcolor.red / 256.0), | |
445 | int(newcolor.green / 256.0), | |
446 | int(newcolor.blue / 256.0)) | |
447 |
0 | # This program is free software; you can redistribute it and/or modify | |
1 | # it under the terms of the GNU General Public License as published by | |
2 | # the Free Software Foundation; either version 2 of the License, or | |
3 | # (at your option) any later version. | |
4 | # | |
5 | # This program is distributed in the hope that it will be useful, | |
6 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
7 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
8 | # GNU General Public License for more details. | |
9 | # | |
10 | # You should have received a copy of the GNU General Public License | |
11 | # along with this program; if not, write to the Free Software | |
12 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
13 | ||
14 | import gtk | |
15 | from gettext import gettext as _ | |
16 | ||
17 | import logging | |
18 | logger = logging.getLogger('write-activity') | |
19 | ||
20 | from sugar.graphics.radiotoolbutton import RadioToolButton | |
21 | from sugar.graphics.combobox import ComboBox | |
22 | from sugar.graphics.palette import Palette | |
23 | from sugar.graphics.radiopalette import RadioPalette | |
24 | ||
25 | class FontCombo(ComboBox): | |
26 | def __init__(self, abi): | |
27 | ComboBox.__init__(self) | |
28 | ||
29 | self._has_custom_fonts = False | |
30 | self._fonts = sorted(abi.get_font_names()) | |
31 | self._fonts_changed_id = self.connect('changed', self._font_changed_cb, | |
32 | abi) | |
33 | ||
34 | for i, f in enumerate(self._fonts): | |
35 | self.append_item(i, f, None) | |
36 | if f == 'Times New Roman': | |
37 | self.set_active(i) | |
38 | ||
39 | abi.connect('font-family', self._font_family_cb) | |
40 | ||
41 | def _font_changed_cb(self, combobox, abi): | |
42 | if self.get_active() != -1: | |
43 | logger.debug('Setting font: %s', self._fonts[self.get_active()]) | |
44 | abi.set_font_name(self._fonts[self.get_active()]) | |
45 | ||
46 | def _font_family_cb(self, abi, font_family): | |
47 | font_index = -1 | |
48 | ||
49 | # search for the font name in our font list | |
50 | for i, f in enumerate(self._fonts): | |
51 | if f == font_family: | |
52 | font_index = i | |
53 | break; | |
54 | ||
55 | # if we don't know this font yet, then add it (temporary) to the list | |
56 | if font_index == -1: | |
57 | logger.debug('Font not found in font list: %s', font_family) | |
58 | if not self._has_custom_fonts: | |
59 | # add a separator to seperate the non-available fonts from | |
60 | # the available ones | |
61 | self._fonts.append('') # ugly | |
62 | self.append_separator() | |
63 | self._has_custom_fonts = True | |
64 | # add the new font | |
65 | self._fonts.append(font_family) | |
66 | self.append_item(0, font_family, None) | |
67 | # see how many fonts we have now, so we can select the last one | |
68 | model = self.get_model() | |
69 | num_children = model.iter_n_children(None) | |
70 | logger.debug('Number of fonts in the list: %d', num_children) | |
71 | font_index = num_children-1 | |
72 | ||
73 | # activate the found font | |
74 | if (font_index > -1): | |
75 | self.handler_block(self._fonts_changed_id) | |
76 | self.set_active(font_index) | |
77 | self.handler_unblock(self._fonts_changed_id) | |
78 | ||
79 | class FontSizeCombo(ComboBox): | |
80 | def __init__(self, abi): | |
81 | ComboBox.__init__(self) | |
82 | ||
83 | self._font_sizes = ['8', '9', '10', '11', '12', '14', '16', '20', \ | |
84 | '22', '24', '26', '28', '36', '48', '72'] | |
85 | self._changed_id = self.connect('changed', self._font_size_changed_cb, | |
86 | abi) | |
87 | ||
88 | for i, s in enumerate(self._font_sizes): | |
89 | self.append_item(i, s, None) | |
90 | if s == '12': | |
91 | self.set_active(i) | |
92 | ||
93 | abi.connect('font-size', self._font_size_cb) | |
94 | ||
95 | def _font_size_changed_cb(self, combobox, abi): | |
96 | if self.get_active() != -1: | |
97 | logger.debug('Setting font size: %d', | |
98 | int(self._font_sizes[self.get_active()])) | |
99 | abi.set_font_size(self._font_sizes[self.get_active()]) | |
100 | ||
101 | def _font_size_cb(self, abi, size): | |
102 | for i, s in enumerate(self._font_sizes): | |
103 | if int(s) == int(size): | |
104 | self.handler_block(self._changed_id) | |
105 | self.set_active(i) | |
106 | self.handler_unblock(self._changed_id) | |
107 | break; | |
108 | ||
109 | class StyleCombo(ComboBox): | |
110 | def __init__(self, abi): | |
111 | ComboBox.__init__(self) | |
112 | ||
113 | self._styles = [ ['Heading 1', _('Heading 1')], | |
114 | ['Heading 2', _('Heading 2')], | |
115 | ['Heading 3', _('Heading 3')], | |
116 | ['Heading 4', _('Heading 4')], | |
117 | ['Bullet List', _('Bullet List')], | |
118 | ['Dashed List', _('Dashed List')], | |
119 | ['Numbered List', _('Numbered List')], | |
120 | ['Lower Case List', _('Lower Case List')], | |
121 | ['Upper Case List', _('Upper Case List')], | |
122 | ['Block Text', _('Block Text')], | |
123 | ['Normal', _('Normal')], | |
124 | ['Plain Text', _('Plain Text')] ] | |
125 | ||
126 | self._has_custom_styles = False | |
127 | self._style_changed_id = self.connect('changed', self._style_changed_cb, | |
128 | abi) | |
129 | ||
130 | for i, s in enumerate(self._styles): | |
131 | self.append_item(i, s[1], None) | |
132 | if s[0] == 'Normal': | |
133 | self.set_active(i) | |
134 | ||
135 | abi.connect('style-name', self._style_cb) | |
136 | ||
137 | def _style_changed_cb(self, combobox, abi): | |
138 | if self.get_active() != -1: | |
139 | logger.debug('Set style: %s', self._styles[self.get_active()][0]) | |
140 | abi.set_style(self._styles[self.get_active()][0]) | |
141 | ||
142 | def _style_cb(self, abi, style_name): | |
143 | if style_name is None or style_name == 'None': | |
144 | style_name = 'Normal' | |
145 | ||
146 | style_index = -1 | |
147 | for i, s in enumerate(self._styles): | |
148 | if s[0] == style_name: | |
149 | style_index = i | |
150 | break; | |
151 | ||
152 | # if we don't know this style yet, then add it (temporary) to the list | |
153 | if style_index == -1: | |
154 | logger.debug('Style not found in style list: %s', style_name) | |
155 | ||
156 | if not self._has_custom_styles: | |
157 | # add a separator to seperate the non-available styles from | |
158 | # the available ones | |
159 | self._styles.append(['','']) # ugly | |
160 | self.append_separator() | |
161 | self._has_custom_styles = True | |
162 | ||
163 | # add the new style | |
164 | self._styles.append([style_name, style_name]) | |
165 | self.append_item(0, style_name, None) | |
166 | ||
167 | # see how many styles we have now, so we can select the last one | |
168 | model = self.get_model() | |
169 | num_children = model.iter_n_children(None) | |
170 | logger.debug('Number of styles in the list: %d', num_children) | |
171 | style_index = num_children-1 | |
172 | ||
173 | if style_index > -1: | |
174 | self.handler_block(self._style_changed_id) | |
175 | self.set_active(style_index) | |
176 | self.handler_unblock(self._style_changed_id) | |
177 | ||
178 | class AbiPalette(RadioPalette): | |
179 | def __init__(self, abi): | |
180 | RadioPalette.__init__(self) | |
181 | self.abi = abi | |
182 | ||
183 | def append(self, icon_name, tooltip, clicked_cb, abi_signal, abi_cb): | |
184 | button = RadioPalette.append(self, | |
185 | icon_name=icon_name, | |
186 | tooltip=tooltip, | |
187 | toggled_cb=lambda: clicked_cb()) | |
188 | ||
189 | def cb(abi, prop): | |
190 | if abi_cb(abi, prop): | |
191 | button.set_active(True) | |
192 | self.abi.connect(abi_signal, cb) | |
193 | ||
194 | class Alignment(AbiPalette): | |
195 | def __init__(self, abi): | |
196 | AbiPalette.__init__(self, abi) | |
197 | ||
198 | self.append('format-justify-left', _('Left justify'), | |
199 | lambda: abi.align_left(), 'left-align', lambda abi, b: b) | |
200 | ||
201 | self.append('format-justify-center', _('Center justify'), | |
202 | lambda: abi.align_center(), 'center-align', lambda abi, b: b) | |
203 | ||
204 | self.append('format-justify-right', _('Right justify'), | |
205 | lambda: abi.align_right(), 'right-align', lambda abi, b: b) | |
206 | ||
207 | self.append('format-justify-fill', _('Fill justify'), | |
208 | lambda: abi.align_justify(), 'justify-align', lambda abi, b: b) | |
209 | ||
210 | class Lists(AbiPalette): | |
211 | def __init__(self, abi): | |
212 | AbiPalette.__init__(self, abi) | |
213 | ||
214 | self.append('list-none', _('Normal'), | |
215 | lambda: abi.set_style('Normal'), | |
216 | 'style-name', lambda abi, style: | |
217 | style not in ['Bullet List', | |
218 | 'Dashed List', | |
219 | 'Numbered List', | |
220 | 'Lower Case List', | |
221 | 'Upper Case List']) | |
222 | ||
223 | self.append('list-bullet', _('Bullet List'), | |
224 | lambda: abi.set_style('Bullet List'), | |
225 | 'style-name', lambda abi, style: style == 'Bullet List') | |
226 | ||
227 | self.append('list-dashed', _('Dashed List'), | |
228 | lambda: abi.set_style('Dashed List'), | |
229 | 'style-name', lambda abi, style: style == 'Dashed List') | |
230 | ||
231 | self.append('list-numbered', _('Numbered List'), | |
232 | lambda: abi.set_style('Numbered List'), | |
233 | 'style-name', lambda abi, style: style == 'Numbered List') | |
234 | ||
235 | self.append('list-lower-case', _('Lower Case List'), | |
236 | lambda: abi.set_style('Lower Case List'), | |
237 | 'style-name', lambda abi, style: style == 'Lower Case List') | |
238 | ||
239 | self.append('list-upper-case', _('Upper Case List'), | |
240 | lambda: abi.set_style('Upper Case List'), | |
241 | 'style-name', lambda abi, style: style == 'Upper Case List') |