Codebase list sugar-read-activity / upstream/121
New upstream version 121 Jonas Smedegaard 5 years ago
24 changed file(s) with 1023 addition(s) and 550 deletion(s). Raw diff Collapse all Expand all
0 [flake8]
1
2 # E402 module level import not at top of file
3 # gi.require_version() is required before later imports
4
5 ignore = E402
0 GNU LIBRARY GENERAL PUBLIC LICENSE
1 Version 2, June 1991
2
3 Copyright (C) 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 [This is the first released version of the library GPL. It is
9 numbered 2 because it goes with version 2 of the ordinary GPL.]
10
11 Preamble
12
13 The licenses for most software are designed to take away your
14 freedom to share and change it. By contrast, the GNU General Public
15 Licenses are intended to guarantee your freedom to share and change
16 free software--to make sure the software is free for all its users.
17
18 This license, the Library General Public License, applies to some
19 specially designated Free Software Foundation software, and to any
20 other libraries whose authors decide to use it. You can use it for
21 your libraries, too.
22
23 When we speak of free software, we are referring to freedom, not
24 price. Our General Public Licenses are designed to make sure that you
25 have the freedom to distribute copies of free software (and charge for
26 this service if you wish), that you receive source code or can get it
27 if you want it, that you can change the software or use pieces of it
28 in new free programs; and that you know you can do these things.
29
30 To protect your rights, we need to make restrictions that forbid
31 anyone to deny you these rights or to ask you to surrender the rights.
32 These restrictions translate to certain responsibilities for you if
33 you distribute copies of the library, or if you modify it.
34
35 For example, if you distribute copies of the library, whether gratis
36 or for a fee, you must give the recipients all the rights that we gave
37 you. You must make sure that they, too, receive or can get the source
38 code. If you link a program with the library, you must provide
39 complete object files to the recipients so that they can relink them
40 with the library, after making changes to the library and recompiling
41 it. And you must show them these terms so they know their rights.
42
43 Our method of protecting your rights has two steps: (1) copyright
44 the library, and (2) offer you this license which gives you legal
45 permission to copy, distribute and/or modify the library.
46
47 Also, for each distributor's protection, we want to make certain
48 that everyone understands that there is no warranty for this free
49 library. If the library is modified by someone else and passed on, we
50 want its recipients to know that what they have is not the original
51 version, so that any problems introduced by others will not reflect on
52 the original authors' reputations.
53
54 Finally, any free program is threatened constantly by software
55 patents. We wish to avoid the danger that companies distributing free
56 software will individually obtain patent licenses, thus in effect
57 transforming the program into proprietary software. To prevent this,
58 we have made it clear that any patent must be licensed for everyone's
59 free use or not licensed at all.
60
61 Most GNU software, including some libraries, is covered by the ordinary
62 GNU General Public License, which was designed for utility programs. This
63 license, the GNU Library General Public License, applies to certain
64 designated libraries. This license is quite different from the ordinary
65 one; be sure to read it in full, and don't assume that anything in it is
66 the same as in the ordinary license.
67
68 The reason we have a separate public license for some libraries is that
69 they blur the distinction we usually make between modifying or adding to a
70 program and simply using it. Linking a program with a library, without
71 changing the library, is in some sense simply using the library, and is
72 analogous to running a utility program or application program. However, in
73 a textual and legal sense, the linked executable is a combined work, a
74 derivative of the original library, and the ordinary General Public License
75 treats it as such.
76
77 Because of this blurred distinction, using the ordinary General
78 Public License for libraries did not effectively promote software
79 sharing, because most developers did not use the libraries. We
80 concluded that weaker conditions might promote sharing better.
81
82 However, unrestricted linking of non-free programs would deprive the
83 users of those programs of all benefit from the free status of the
84 libraries themselves. This Library General Public License is intended to
85 permit developers of non-free programs to use free libraries, while
86 preserving your freedom as a user of such programs to change the free
87 libraries that are incorporated in them. (We have not seen how to achieve
88 this as regards changes in header files, but we have achieved it as regards
89 changes in the actual functions of the Library.) The hope is that this
90 will lead to faster development of free libraries.
91
92 The precise terms and conditions for copying, distribution and
93 modification follow. Pay close attention to the difference between a
94 "work based on the library" and a "work that uses the library". The
95 former contains code derived from the library, while the latter only
96 works together with the library.
97
98 Note that it is possible for a library to be covered by the ordinary
99 General Public License rather than by this special one.
100
101 GNU LIBRARY GENERAL PUBLIC LICENSE
102 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
103
104 0. This License Agreement applies to any software library which
105 contains a notice placed by the copyright holder or other authorized
106 party saying it may be distributed under the terms of this Library
107 General Public License (also called "this License"). Each licensee is
108 addressed as "you".
109
110 A "library" means a collection of software functions and/or data
111 prepared so as to be conveniently linked with application programs
112 (which use some of those functions and data) to form executables.
113
114 The "Library", below, refers to any such software library or work
115 which has been distributed under these terms. A "work based on the
116 Library" means either the Library or any derivative work under
117 copyright law: that is to say, a work containing the Library or a
118 portion of it, either verbatim or with modifications and/or translated
119 straightforwardly into another language. (Hereinafter, translation is
120 included without limitation in the term "modification".)
121
122 "Source code" for a work means the preferred form of the work for
123 making modifications to it. For a library, complete source code means
124 all the source code for all modules it contains, plus any associated
125 interface definition files, plus the scripts used to control compilation
126 and installation of the library.
127
128 Activities other than copying, distribution and modification are not
129 covered by this License; they are outside its scope. The act of
130 running a program using the Library is not restricted, and output from
131 such a program is covered only if its contents constitute a work based
132 on the Library (independent of the use of the Library in a tool for
133 writing it). Whether that is true depends on what the Library does
134 and what the program that uses the Library does.
135
136 1. You may copy and distribute verbatim copies of the Library's
137 complete source code as you receive it, in any medium, provided that
138 you conspicuously and appropriately publish on each copy an
139 appropriate copyright notice and disclaimer of warranty; keep intact
140 all the notices that refer to this License and to the absence of any
141 warranty; and distribute a copy of this License along with the
142 Library.
143
144 You may charge a fee for the physical act of transferring a copy,
145 and you may at your option offer warranty protection in exchange for a
146 fee.
147
148 2. You may modify your copy or copies of the Library or any portion
149 of it, thus forming a work based on the Library, and copy and
150 distribute such modifications or work under the terms of Section 1
151 above, provided that you also meet all of these conditions:
152
153 a) The modified work must itself be a software library.
154
155 b) You must cause the files modified to carry prominent notices
156 stating that you changed the files and the date of any change.
157
158 c) You must cause the whole of the work to be licensed at no
159 charge to all third parties under the terms of this License.
160
161 d) If a facility in the modified Library refers to a function or a
162 table of data to be supplied by an application program that uses
163 the facility, other than as an argument passed when the facility
164 is invoked, then you must make a good faith effort to ensure that,
165 in the event an application does not supply such function or
166 table, the facility still operates, and performs whatever part of
167 its purpose remains meaningful.
168
169 (For example, a function in a library to compute square roots has
170 a purpose that is entirely well-defined independent of the
171 application. Therefore, Subsection 2d requires that any
172 application-supplied function or table used by this function must
173 be optional: if the application does not supply it, the square
174 root function must still compute square roots.)
175
176 These requirements apply to the modified work as a whole. If
177 identifiable sections of that work are not derived from the Library,
178 and can be reasonably considered independent and separate works in
179 themselves, then this License, and its terms, do not apply to those
180 sections when you distribute them as separate works. But when you
181 distribute the same sections as part of a whole which is a work based
182 on the Library, the distribution of the whole must be on the terms of
183 this License, whose permissions for other licensees extend to the
184 entire whole, and thus to each and every part regardless of who wrote
185 it.
186
187 Thus, it is not the intent of this section to claim rights or contest
188 your rights to work written entirely by you; rather, the intent is to
189 exercise the right to control the distribution of derivative or
190 collective works based on the Library.
191
192 In addition, mere aggregation of another work not based on the Library
193 with the Library (or with a work based on the Library) on a volume of
194 a storage or distribution medium does not bring the other work under
195 the scope of this License.
196
197 3. You may opt to apply the terms of the ordinary GNU General Public
198 License instead of this License to a given copy of the Library. To do
199 this, you must alter all the notices that refer to this License, so
200 that they refer to the ordinary GNU General Public License, version 2,
201 instead of to this License. (If a newer version than version 2 of the
202 ordinary GNU General Public License has appeared, then you can specify
203 that version instead if you wish.) Do not make any other change in
204 these notices.
205
206 Once this change is made in a given copy, it is irreversible for
207 that copy, so the ordinary GNU General Public License applies to all
208 subsequent copies and derivative works made from that copy.
209
210 This option is useful when you wish to copy part of the code of
211 the Library into a program that is not a library.
212
213 4. You may copy and distribute the Library (or a portion or
214 derivative of it, under Section 2) in object code or executable form
215 under the terms of Sections 1 and 2 above provided that you accompany
216 it with the complete corresponding machine-readable source code, which
217 must be distributed under the terms of Sections 1 and 2 above on a
218 medium customarily used for software interchange.
219
220 If distribution of object code is made by offering access to copy
221 from a designated place, then offering equivalent access to copy the
222 source code from the same place satisfies the requirement to
223 distribute the source code, even though third parties are not
224 compelled to copy the source along with the object code.
225
226 5. A program that contains no derivative of any portion of the
227 Library, but is designed to work with the Library by being compiled or
228 linked with it, is called a "work that uses the Library". Such a
229 work, in isolation, is not a derivative work of the Library, and
230 therefore falls outside the scope of this License.
231
232 However, linking a "work that uses the Library" with the Library
233 creates an executable that is a derivative of the Library (because it
234 contains portions of the Library), rather than a "work that uses the
235 library". The executable is therefore covered by this License.
236 Section 6 states terms for distribution of such executables.
237
238 When a "work that uses the Library" uses material from a header file
239 that is part of the Library, the object code for the work may be a
240 derivative work of the Library even though the source code is not.
241 Whether this is true is especially significant if the work can be
242 linked without the Library, or if the work is itself a library. The
243 threshold for this to be true is not precisely defined by law.
244
245 If such an object file uses only numerical parameters, data
246 structure layouts and accessors, and small macros and small inline
247 functions (ten lines or less in length), then the use of the object
248 file is unrestricted, regardless of whether it is legally a derivative
249 work. (Executables containing this object code plus portions of the
250 Library will still fall under Section 6.)
251
252 Otherwise, if the work is a derivative of the Library, you may
253 distribute the object code for the work under the terms of Section 6.
254 Any executables containing that work also fall under Section 6,
255 whether or not they are linked directly with the Library itself.
256
257 6. As an exception to the Sections above, you may also compile or
258 link a "work that uses the Library" with the Library to produce a
259 work containing portions of the Library, and distribute that work
260 under terms of your choice, provided that the terms permit
261 modification of the work for the customer's own use and reverse
262 engineering for debugging such modifications.
263
264 You must give prominent notice with each copy of the work that the
265 Library is used in it and that the Library and its use are covered by
266 this License. You must supply a copy of this License. If the work
267 during execution displays copyright notices, you must include the
268 copyright notice for the Library among them, as well as a reference
269 directing the user to the copy of this License. Also, you must do one
270 of these things:
271
272 a) Accompany the work with the complete corresponding
273 machine-readable source code for the Library including whatever
274 changes were used in the work (which must be distributed under
275 Sections 1 and 2 above); and, if the work is an executable linked
276 with the Library, with the complete machine-readable "work that
277 uses the Library", as object code and/or source code, so that the
278 user can modify the Library and then relink to produce a modified
279 executable containing the modified Library. (It is understood
280 that the user who changes the contents of definitions files in the
281 Library will not necessarily be able to recompile the application
282 to use the modified definitions.)
283
284 b) Accompany the work with a written offer, valid for at
285 least three years, to give the same user the materials
286 specified in Subsection 6a, above, for a charge no more
287 than the cost of performing this distribution.
288
289 c) If distribution of the work is made by offering access to copy
290 from a designated place, offer equivalent access to copy the above
291 specified materials from the same place.
292
293 d) Verify that the user has already received a copy of these
294 materials or that you have already sent this user a copy.
295
296 For an executable, the required form of the "work that uses the
297 Library" must include any data and utility programs needed for
298 reproducing the executable from it. However, as a special exception,
299 the source code distributed need not include anything that is normally
300 distributed (in either source or binary form) with the major
301 components (compiler, kernel, and so on) of the operating system on
302 which the executable runs, unless that component itself accompanies
303 the executable.
304
305 It may happen that this requirement contradicts the license
306 restrictions of other proprietary libraries that do not normally
307 accompany the operating system. Such a contradiction means you cannot
308 use both them and the Library together in an executable that you
309 distribute.
310
311 7. You may place library facilities that are a work based on the
312 Library side-by-side in a single library together with other library
313 facilities not covered by this License, and distribute such a combined
314 library, provided that the separate distribution of the work based on
315 the Library and of the other library facilities is otherwise
316 permitted, and provided that you do these two things:
317
318 a) Accompany the combined library with a copy of the same work
319 based on the Library, uncombined with any other library
320 facilities. This must be distributed under the terms of the
321 Sections above.
322
323 b) Give prominent notice with the combined library of the fact
324 that part of it is a work based on the Library, and explaining
325 where to find the accompanying uncombined form of the same work.
326
327 8. You may not copy, modify, sublicense, link with, or distribute
328 the Library except as expressly provided under this License. Any
329 attempt otherwise to copy, modify, sublicense, link with, or
330 distribute the Library is void, and will automatically terminate your
331 rights under this License. However, parties who have received copies,
332 or rights, from you under this License will not have their licenses
333 terminated so long as such parties remain in full compliance.
334
335 9. You are not required to accept this License, since you have not
336 signed it. However, nothing else grants you permission to modify or
337 distribute the Library or its derivative works. These actions are
338 prohibited by law if you do not accept this License. Therefore, by
339 modifying or distributing the Library (or any work based on the
340 Library), you indicate your acceptance of this License to do so, and
341 all its terms and conditions for copying, distributing or modifying
342 the Library or works based on it.
343
344 10. Each time you redistribute the Library (or any work based on the
345 Library), the recipient automatically receives a license from the
346 original licensor to copy, distribute, link with or modify the Library
347 subject to these terms and conditions. You may not impose any further
348 restrictions on the recipients' exercise of the rights granted herein.
349 You are not responsible for enforcing compliance by third parties to
350 this License.
351
352 11. If, as a consequence of a court judgment or allegation of patent
353 infringement or for any other reason (not limited to patent issues),
354 conditions are imposed on you (whether by court order, agreement or
355 otherwise) that contradict the conditions of this License, they do not
356 excuse you from the conditions of this License. If you cannot
357 distribute so as to satisfy simultaneously your obligations under this
358 License and any other pertinent obligations, then as a consequence you
359 may not distribute the Library at all. For example, if a patent
360 license would not permit royalty-free redistribution of the Library by
361 all those who receive copies directly or indirectly through you, then
362 the only way you could satisfy both it and this License would be to
363 refrain entirely from distribution of the Library.
364
365 If any portion of this section is held invalid or unenforceable under any
366 particular circumstance, the balance of the section is intended to apply,
367 and the section as a whole is intended to apply in other circumstances.
368
369 It is not the purpose of this section to induce you to infringe any
370 patents or other property right claims or to contest validity of any
371 such claims; this section has the sole purpose of protecting the
372 integrity of the free software distribution system which is
373 implemented by public license practices. Many people have made
374 generous contributions to the wide range of software distributed
375 through that system in reliance on consistent application of that
376 system; it is up to the author/donor to decide if he or she is willing
377 to distribute software through any other system and a licensee cannot
378 impose that choice.
379
380 This section is intended to make thoroughly clear what is believed to
381 be a consequence of the rest of this License.
382
383 12. If the distribution and/or use of the Library is restricted in
384 certain countries either by patents or by copyrighted interfaces, the
385 original copyright holder who places the Library under this License may add
386 an explicit geographical distribution limitation excluding those countries,
387 so that distribution is permitted only in or among countries not thus
388 excluded. In such case, this License incorporates the limitation as if
389 written in the body of this License.
390
391 13. The Free Software Foundation may publish revised and/or new
392 versions of the Library General Public License from time to time.
393 Such new versions will be similar in spirit to the present version,
394 but may differ in detail to address new problems or concerns.
395
396 Each version is given a distinguishing version number. If the Library
397 specifies a version number of this License which applies to it and
398 "any later version", you have the option of following the terms and
399 conditions either of that version or of any later version published by
400 the Free Software Foundation. If the Library does not specify a
401 license version number, you may choose any version ever published by
402 the Free Software Foundation.
403
404 14. If you wish to incorporate parts of the Library into other free
405 programs whose distribution conditions are incompatible with these,
406 write to the author to ask for permission. For software which is
407 copyrighted by the Free Software Foundation, write to the Free
408 Software Foundation; we sometimes make exceptions for this. Our
409 decision will be guided by the two goals of preserving the free status
410 of all derivatives of our free software and of promoting the sharing
411 and reuse of software generally.
412
413 NO WARRANTY
414
415 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
416 WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
417 EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
418 OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
419 KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
420 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
421 PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
422 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
423 THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
424
425 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
426 WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
427 AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
428 FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
429 CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
430 LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
431 RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
432 FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
433 SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
434 DAMAGES.
435
436 END OF TERMS AND CONDITIONS
437
438 How to Apply These Terms to Your New Libraries
439
440 If you develop a new library, and you want it to be of the greatest
441 possible use to the public, we recommend making it free software that
442 everyone can redistribute and change. You can do so by permitting
443 redistribution under these terms (or, alternatively, under the terms of the
444 ordinary General Public License).
445
446 To apply these terms, attach the following notices to the library. It is
447 safest to attach them to the start of each source file to most effectively
448 convey the exclusion of warranty; and each file should have at least the
449 "copyright" line and a pointer to where the full notice is found.
450
451 <one line to give the library's name and a brief idea of what it does.>
452 Copyright (C) <year> <name of author>
453
454 This library is free software; you can redistribute it and/or
455 modify it under the terms of the GNU Library General Public
456 License as published by the Free Software Foundation; either
457 version 2 of the License, or (at your option) any later version.
458
459 This library is distributed in the hope that it will be useful,
460 but WITHOUT ANY WARRANTY; without even the implied warranty of
461 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
462 Library General Public License for more details.
463
464 You should have received a copy of the GNU Library General Public
465 License along with this library; if not, write to the Free Software
466 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
467
468 Also add information on how to contact you by electronic and paper mail.
469
470 You should also get your employer (if you work as a programmer) or your
471 school, if any, to sign a "copyright disclaimer" for the library, if
472 necessary. Here is a sample; alter the names:
473
474 Yoyodyne, Inc., hereby disclaims all copyright interest in the
475 library `Frob' (a library for tweaking knobs) written by James Random Hacker.
476
477 <signature of Ty Coon>, 1 April 1990
478 Ty Coon, President of Vice
479
480 That's all there is to it!
0 121
1
2 * Add README.md (Rudra Sadhu),
3 * Flake8 fixes (Rahul Bothra),
4 * Update metadata (Rahul Bothra),
5 * Add metedata, license copies and screenshot (Vipul Gupta),
6 * Port from GObject to GLib (James Cameron),
7 * Move PyGObject API version check to main program (James Cameron),
8 * Port to TelepathyGLib (James Cameron),
9 * Remove some log warnings and errors (James Cameron),
10 * Port to sugar3.speech (James Cameron).
11
12 120
13
14 * Fix use of Gst.Message.structure (James Cameron),
15 * Port from GConf (James Cameron),
16 * New translations (Chris Leonard et al).
17
018 119
119
220 * New translations (Chris Leonard, et al)
0 What is this?
1 =============
2
3 Read activity allows the laptop to act as a book reader. It has a simple interface, and will view many kinds of text and image-based book-like materials.
4
5 How to use?
6 ===========
7
8 Read is part of the Sugar desktop. Please refer to;
9
10 * [How to Get Sugar on sugarlabs.org](https://sugarlabs.org/),
11 * [How to use Sugar](https://help.sugarlabs.org/),
12 * [How to use Read](https://help.sugarlabs.org/read.html)
22 bundle_id = org.laptop.sugar.ReadActivity
33 icon = activity-read
44 exec = sugar-activity readactivity.ReadActivity
5 activity_version = 119
5 activity_version = 121
66 mime_types = application/pdf;image/vnd.djvu;image/x.djvu;image/tiff;text/plain;application/zip;application/x-cbz
7 license = GPLv2+
7 max_participants = 10
8 license = GPLv2+;LGPLv2+
89 summary = Use this activity when you are ready to read! Remember to flip your computer around to feel like you are really holding a book!
9 categories = language documents media system
10 repository = https://github.com/sugarlabs/read-activity.git
11 max_participants = 10
10 tags = Language;Documents;Media;System
11 url = https://help.sugarlabs.org/en/read.html
12 repository = https://github.com/sugarlabs/read-activity
0 import logging
1
2 import gi
3 gi.require_version('Gtk', '3.0')
4
50 from gi.repository import Gtk
61
72 from sugar3.graphics import style
1919 import cairo
2020 import math
2121
22 from gi.repository import GLib
2223 from gi.repository import Gtk
2324 from gi.repository import Gdk
2425 from gi.repository import GdkPixbuf
9192 __gproperties__ = {
9293 "hscroll-policy": (Gtk.ScrollablePolicy, "hscroll-policy",
9394 "hscroll-policy", Gtk.ScrollablePolicy.MINIMUM,
94 GObject.PARAM_READWRITE),
95 GObject.ParamFlags.READWRITE),
9596 "hadjustment": (Gtk.Adjustment, "hadjustment", "hadjustment",
96 GObject.PARAM_READWRITE),
97 GObject.ParamFlags.READWRITE),
9798 "vscroll-policy": (Gtk.ScrollablePolicy, "hscroll-policy",
9899 "hscroll-policy", Gtk.ScrollablePolicy.MINIMUM,
99 GObject.PARAM_READWRITE),
100 GObject.ParamFlags.READWRITE),
100101 "vadjustment": (Gtk.Adjustment, "hadjustment", "hadjustment",
101 GObject.PARAM_READWRITE),
102 GObject.ParamFlags.READWRITE),
102103 }
103104
104105 __gsignals__ = {
221222 # be set to False. This is to perform a faster drawing while
222223 # scrolling.
223224 if self._scrolling_hid is not None:
224 GObject.source_remove(self._scrolling_hid)
225 self._scrolling_hid = GObject.timeout_add(200,
226 self._stop_scrolling)
225 GLib.source_remove(self._scrolling_hid)
226 self._scrolling_hid = GLib.timeout_add(200,
227 self._stop_scrolling)
227228
228229 def __hadj_value_changed_cb(self, adj):
229230 alloc = self.get_allocation()
1010 # Lesser General Public License for more details.
1111 #
1212 # You should have received a copy of the GNU Lesser General Public
13 # License along with this library; if not, write to the
14 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15 # Boston, MA 02111-1307, USA.
13 # License along with this library; if not, write to the Free Software
14 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
15 # MA 02110-1301 USA
1616
1717 from gi.repository import Gtk
1818 from gi.repository import Gdk
77 msgstr ""
88 "Project-Id-Version: PACKAGE VERSION\n"
99 "Report-Msgid-Bugs-To: \n"
10 "POT-Creation-Date: 2017-08-12 13:27+1000\n"
10 "POT-Creation-Date: 2018-04-02 15:53+1000\n"
1111 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
1212 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313 "Language-Team: LANGUAGE <LL@li.org>\n"
214214 msgid "Hide Tray"
215215 msgstr ""
216216
217 #: speechtoolbar.py:57
217 #: speechtoolbar.py:55
218218 msgid "Play / Pause"
219219 msgstr ""
220220
221 #: speechtoolbar.py:65
221 #: speechtoolbar.py:63
222222 msgid "Stop"
223223 msgstr ""
1414 "Project-Id-Version: PACKAGE VERSION\n"
1515 "Report-Msgid-Bugs-To: \n"
1616 "POT-Creation-Date: 2017-03-24 17:39+1100\n"
17 "PO-Revision-Date: 2013-09-07 14:30+0200\n"
18 "Last-Translator: Aputsiaq Niels <aj@isit.gl>\n"
17 "PO-Revision-Date: 2017-11-03 09:26+0000\n"
18 "Last-Translator: dark159123 <r.j.hansen@protonmail.com>\n"
1919 "Language-Team: LANGUAGE <LL@li.org>\n"
2020 "Language: da\n"
2121 "MIME-Version: 1.0\n"
2222 "Content-Type: text/plain; charset=UTF-8\n"
2323 "Content-Transfer-Encoding: 8bit\n"
2424 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
25 "X-Generator: Pootle 2.0.5\n"
25 "X-Generator: Pootle 2.5.1.1\n"
26 "X-POOTLE-MTIME: 1509701219.000000\n"
2627
2728 #: activity/activity.info:2
2829 msgid "Read"
5051
5152 #: readdialog.py:147
5253 msgid "<b>Author</b>:"
53 msgstr ""
54 msgstr "<b>Forfatter</b>:"
5455
5556 #: readdialog.py:163
5657 msgid "<b>Details</b>:"
127128 #: readactivity.py:1032 readactivity.py:1227
128129 #, python-format
129130 msgid "%s (Page %d)"
130 msgstr ""
131 msgstr "%s (Side %d)"
131132
132133 #: readtoolbar.py:61
133134 msgid "Previous"
226227
227228 #: comicadapter.py:69
228229 msgid "Can not read Comic Book Archive"
229 msgstr ""
230 msgstr "Kan ikke læse Tegneserie Arkivet"
230231
231232 #: comicadapter.py:70
232233 msgid "No readable images were found"
233 msgstr ""
234 msgstr "Ingen læsbare billeder blev fundet"
234235
235236 #, python-format
236237 #~ msgid "Page %d"
0 # SOME DESCRIPTIVE TITLE.
1 # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
2 # This file is distributed under the same license as the PACKAGE package.
3 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
4 msgid ""
5 msgstr ""
6 "Project-Id-Version: PACKAGE VERSION\n"
7 "Report-Msgid-Bugs-To: \n"
8 "POT-Creation-Date: 2017-03-24 17:39+1100\n"
9 "PO-Revision-Date: 2017-12-15 18:48+0000\n"
10 "Last-Translator: Berend <berendy@gmail.com>\n"
11 "Language-Team: LANGUAGE <LL@li.org>\n"
12 "Language: fy\n"
13 "MIME-Version: 1.0\n"
14 "Content-Type: text/plain; charset=UTF-8\n"
15 "Content-Transfer-Encoding: 8bit\n"
16 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
17 "X-Generator: Pootle 2.5.1.1\n"
18 "X-POOTLE-MTIME: 1513363716.000000\n"
19
20 #: activity/activity.info:2
21 msgid "Read"
22 msgstr "Lêze"
23
24 #: activity/activity.info:3
25 msgid ""
26 "Use this activity when you are ready to read! Remember to flip your computer "
27 "around to feel like you are really holding a book!"
28 msgstr ""
29 "Brûk dizze aktiviteit ast klear bist om te lêzen! Tink derom om dyn "
30 "kompjûter sa no en dan om te slaan om it gefoel fan it fêsthâlden fan in "
31 "echt boek te behâlden!"
32
33 #: readdialog.py:52
34 msgid "Cancel"
35 msgstr "Ofbrekke"
36
37 #: readdialog.py:58
38 msgid "Ok"
39 msgstr "Okee"
40
41 #: readdialog.py:120
42 msgid "<b>Title</b>:"
43 msgstr "<b>Titel</b>:"
44
45 #: readdialog.py:147
46 msgid "<b>Author</b>:"
47 msgstr "<b>Skriuwer</b>:"
48
49 #: readdialog.py:163
50 msgid "<b>Details</b>:"
51 msgstr "<b>Details</b>:"
52
53 #: evinceadapter.py:92
54 msgid "URL from Read"
55 msgstr "URL-adres fan lêzen"
56
57 #: speechtoolbar.py:57
58 msgid "Play / Pause"
59 msgstr "Ofspylje / Skoftsje"
60
61 #: speechtoolbar.py:65
62 msgid "Stop"
63 msgstr "Ophâlde"
64
65 #: readactivity.py:379
66 msgid "Please wait"
67 msgstr "In amerijke"
68
69 #: readactivity.py:380
70 msgid "Starting connection..."
71 msgstr "Ferbining opbouwe..."
72
73 #: readactivity.py:388
74 msgid "No book"
75 msgstr "Gjin boek"
76
77 #: readactivity.py:388
78 msgid "Choose something to read"
79 msgstr "Kies wat om te lêzen"
80
81 #: readactivity.py:393
82 msgid "Back"
83 msgstr "Tebek"
84
85 #: readactivity.py:397
86 msgid "Previous page"
87 msgstr "Foarige side"
88
89 #: readactivity.py:399
90 msgid "Previous bookmark"
91 msgstr "Foarige blêdwizer"
92
93 #: readactivity.py:411
94 msgid "Forward"
95 msgstr "Folgjende"
96
97 #: readactivity.py:415
98 msgid "Next page"
99 msgstr "Folgjende side"
100
101 #: readactivity.py:417
102 msgid "Next bookmark"
103 msgstr "Folgjende blêdwizer"
104
105 #: readactivity.py:468
106 msgid "Index"
107 msgstr "Yndeks"
108
109 #: readactivity.py:564
110 msgid "Delete bookmark"
111 msgstr "Blêdwizer wiskje"
112
113 #: readactivity.py:565
114 msgid "All the information related with this bookmark will be lost"
115 msgstr "Alle ynformaasje by dizze blêdwizer sil ferlern gean"
116
117 #: readactivity.py:954
118 msgid "Receiving book..."
119 msgstr "Untfang boek..."
120
121 #: readactivity.py:1032 readactivity.py:1227
122 #, python-format
123 msgid "%s (Page %d)"
124 msgstr "%s (Side %d)"
125
126 #: readtoolbar.py:61
127 msgid "Previous"
128 msgstr "Foarige"
129
130 #: readtoolbar.py:68
131 msgid "Next"
132 msgstr "Folgjende"
133
134 #: readtoolbar.py:79
135 msgid "Highlight"
136 msgstr "Markearje"
137
138 #: readtoolbar.py:160
139 msgid "Find first"
140 msgstr "Folgjende side"
141
142 #: readtoolbar.py:166
143 msgid "Find previous"
144 msgstr "Foarige sykje"
145
146 #: readtoolbar.py:168
147 msgid "Find next"
148 msgstr "Folgjende sykje"
149
150 #: readtoolbar.py:188
151 msgid "Table of contents"
152 msgstr "Ynhâldsopjefte"
153
154 #: readtoolbar.py:197
155 msgid "Zoom out"
156 msgstr "Zoom út"
157
158 #: readtoolbar.py:203
159 msgid "Zoom in"
160 msgstr "Zoom yn"
161
162 #: readtoolbar.py:209
163 msgid "Zoom to width"
164 msgstr "Zoom neffens breedte"
165
166 #: readtoolbar.py:215
167 msgid "Zoom to fit"
168 msgstr "Zoom nei hiele side"
169
170 #: readtoolbar.py:221
171 msgid "Actual size"
172 msgstr "Wiere grutte"
173
174 #: readtoolbar.py:232
175 msgid "Fullscreen"
176 msgstr "Folslein skerm"
177
178 #: readtoolbar.py:252
179 msgid "Rotate left"
180 msgstr "Links rotearje"
181
182 #: readtoolbar.py:258
183 msgid "Rotate right"
184 msgstr "Rjochts rotearje"
185
186 #: readtoolbar.py:324
187 msgid "Show Tray"
188 msgstr "Plato sjen litte"
189
190 #: readtoolbar.py:326
191 msgid "Hide Tray"
192 msgstr "Plato ferbergje"
193
194 #: linkbutton.py:133
195 msgid "Go to Bookmark"
196 msgstr "Gean nei blêdwizer"
197
198 #: linkbutton.py:139
199 msgid "Remove"
200 msgstr "Wiskje"
201
202 #: bookmarkview.py:107
203 #, python-format
204 msgid "Bookmark added by %(user)s %(time)s"
205 msgstr "Blêdwizer taheakke troch %(user)s %(time)s"
206
207 #: bookmarkview.py:143 bookmarkview.py:192
208 msgid "Add notes for bookmark: "
209 msgstr "Notysjes foar blêdwizer taheakje: "
210
211 #: bookmarkview.py:188
212 #, python-format
213 msgid "%s's bookmark"
214 msgstr "%s's blêdwizer"
215
216 #: bookmarkview.py:189
217 #, python-format
218 msgid "Bookmark for page %d"
219 msgstr "Blêdwizer foar side %d"
220
221 #: comicadapter.py:69
222 msgid "Can not read Comic Book Archive"
223 msgstr "Kin it stripboek argyf net lêze"
224
225 #: comicadapter.py:70
226 msgid "No readable images were found"
227 msgstr "Gjin te lêzen ôfbyldings binne fûn"
66 "Project-Id-Version: PACKAGE VERSION\n"
77 "Report-Msgid-Bugs-To: \n"
88 "POT-Creation-Date: 2017-03-24 17:39+1100\n"
9 "PO-Revision-Date: 2017-06-10 11:29+0000\n"
10 "Last-Translator: belkacem77 <belkacem77@gmail.com>\n"
9 "PO-Revision-Date: 2017-12-06 14:53+0000\n"
10 "Last-Translator: hociben <hociben@gmail.com>\n"
1111 "Language-Team: LANGUAGE <LL@li.org>\n"
1212 "Language: kab\n"
1313 "MIME-Version: 1.0\n"
1515 "Content-Transfer-Encoding: 8bit\n"
1616 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
1717 "X-Generator: Pootle 2.5.1.1\n"
18 "X-POOTLE-MTIME: 1497094194.000000\n"
18 "X-POOTLE-MTIME: 1512572038.000000\n"
1919
2020 #: activity/activity.info:2
2121 msgid "Read"
8787
8888 #: readactivity.py:399
8989 msgid "Previous bookmark"
90 msgstr ""
90 msgstr "Ticreḍt n deffir"
9191
9292 #: readactivity.py:411
9393 msgid "Forward"
94 msgstr ""
94 msgstr "Ɣer zdat"
9595
9696 #: readactivity.py:415
9797 msgid "Next page"
98 msgstr ""
98 msgstr "Asebter ɣer zdat"
9999
100100 #: readactivity.py:417
101101 msgid "Next bookmark"
102 msgstr ""
102 msgstr "Ticreḍt n zdat"
103103
104104 #: readactivity.py:468
105105 msgid "Index"
107107
108108 #: readactivity.py:564
109109 msgid "Delete bookmark"
110 msgstr ""
110 msgstr "Kkes ticreḍt"
111111
112112 #: readactivity.py:565
113113 msgid "All the information related with this bookmark will be lost"
114 msgstr ""
114 msgstr "Talɣut akk yerzan ticreḍt-agi ad truḥ"
115115
116116 #: readactivity.py:954
117117 msgid "Receiving book..."
120120 #: readactivity.py:1032 readactivity.py:1227
121121 #, python-format
122122 msgid "%s (Page %d)"
123 msgstr ""
123 msgstr "%s (Asebter %d)"
124124
125125 #: readtoolbar.py:61
126126 msgid "Previous"
127 msgstr ""
127 msgstr "Send"
128128
129129 #: readtoolbar.py:68
130130 msgid "Next"
131 msgstr ""
131 msgstr "Seld"
132132
133133 #: readtoolbar.py:79
134134 msgid "Highlight"
135 msgstr ""
135 msgstr "Asebrureq"
136136
137137 #: readtoolbar.py:160
138138 msgid "Find first"
139 msgstr ""
139 msgstr "Af-d d amezwaru"
140140
141141 #: readtoolbar.py:166
142142 msgid "Find previous"
148148
149149 #: readtoolbar.py:188
150150 msgid "Table of contents"
151 msgstr ""
151 msgstr "Agbur"
152152
153153 #: readtoolbar.py:197
154154 msgid "Zoom out"
192192
193193 #: linkbutton.py:133
194194 msgid "Go to Bookmark"
195 msgstr ""
195 msgstr "Ddu ɣer ticreḍt "
196196
197197 #: linkbutton.py:139
198198 msgid "Remove"
199 msgstr ""
199 msgstr "Kkes"
200200
201201 #: bookmarkview.py:107
202202 #, python-format
1414 "Project-Id-Version: PACKAGE VERSION\n"
1515 "Report-Msgid-Bugs-To: \n"
1616 "POT-Creation-Date: 2017-03-24 17:39+1100\n"
17 "PO-Revision-Date: 2017-04-17 06:15+0000\n"
18 "Last-Translator: Chris <cjl@sugarlabs.org>\n"
17 "PO-Revision-Date: 2017-10-14 08:59+0000\n"
18 "Last-Translator: yuray <yuray@komyakino.ru>\n"
1919 "Language-Team: LANGUAGE <LL@li.org>\n"
2020 "Language: ru\n"
2121 "MIME-Version: 1.0\n"
2424 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
2525 "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
2626 "X-Generator: Pootle 2.5.1.1\n"
27 "X-POOTLE-MTIME: 1492409727.000000\n"
27 "X-POOTLE-MTIME: 1507971582.000000\n"
2828
2929 #: activity/activity.info:2
3030 msgid "Read"
5252
5353 #: readdialog.py:147
5454 msgid "<b>Author</b>:"
55 msgstr ""
55 msgstr "<b>Автор</b>:"
5656
5757 #: readdialog.py:163
5858 msgid "<b>Details</b>:"
7272
7373 #: readactivity.py:379
7474 msgid "Please wait"
75 msgstr ""
75 msgstr "Подождите"
7676
7777 #: readactivity.py:380
7878 msgid "Starting connection..."
79 msgstr ""
79 msgstr "Начинается подключение…"
8080
8181 #: readactivity.py:388
8282 msgid "No book"
124124
125125 #: readactivity.py:954
126126 msgid "Receiving book..."
127 msgstr ""
127 msgstr "Получение книги…"
128128
129129 #: readactivity.py:1032 readactivity.py:1227
130130 #, python-format
131131 msgid "%s (Page %d)"
132 msgstr ""
132 msgstr "%s (страница %d)"
133133
134134 #: readtoolbar.py:61
135135 msgid "Previous"
185185
186186 #: readtoolbar.py:252
187187 msgid "Rotate left"
188 msgstr ""
188 msgstr "Повернуть влево"
189189
190190 #: readtoolbar.py:258
191191 msgid "Rotate right"
192 msgstr ""
192 msgstr "Повернуть вправо"
193193
194194 #: readtoolbar.py:324
195195 msgid "Show Tray"
228228
229229 #: comicadapter.py:69
230230 msgid "Can not read Comic Book Archive"
231 msgstr ""
231 msgstr "Невозможно прочитать архив книги комиксов"
232232
233233 #: comicadapter.py:70
234234 msgid "No readable images were found"
235 msgstr ""
235 msgstr "Доступные для чтения изображения не найдены"
236236
237237 #, python-format
238238 #~ msgid "Page %d"
1414 "Project-Id-Version: PACKAGE VERSION\n"
1515 "Report-Msgid-Bugs-To: \n"
1616 "POT-Creation-Date: 2017-03-24 17:39+1100\n"
17 "PO-Revision-Date: 2009-08-25 15:36-0400\n"
18 "Last-Translator: Chris Leonard <cjl@laptop.org>\n"
17 "PO-Revision-Date: 2017-11-03 12:45+0000\n"
18 "Last-Translator: jana <jpastyrova@gmail.com>\n"
1919 "Language-Team: LANGUAGE <LL@li.org>\n"
2020 "Language: sk\n"
2121 "MIME-Version: 1.0\n"
2222 "Content-Type: text/plain; charset=UTF-8\n"
2323 "Content-Transfer-Encoding: 8bit\n"
24 "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2 ;\n"
25 "X-Generator: Pootle 1.2.1\n"
24 "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
25 "X-Generator: Pootle 2.5.1.1\n"
26 "X-POOTLE-MTIME: 1509713154.000000\n"
2627
2728 #: activity/activity.info:2
2829 msgid "Read"
3334 "Use this activity when you are ready to read! Remember to flip your computer "
3435 "around to feel like you are really holding a book!"
3536 msgstr ""
37 "Táto činnosť je určená na čítanie! Nezabudnite obrátiť počítač tak aby sme "
38 "mali pocit, že držíte skutočnú knihu. "
3639
3740 #: readdialog.py:52
3841 msgid "Cancel"
4447
4548 #: readdialog.py:120
4649 msgid "<b>Title</b>:"
47 msgstr ""
50 msgstr "<b>Názov</b>:"
4851
4952 #: readdialog.py:147
5053 msgid "<b>Author</b>:"
51 msgstr ""
54 msgstr "<b>Autor</b>:"
5255
5356 #: readdialog.py:163
5457 msgid "<b>Details</b>:"
55 msgstr ""
58 msgstr "<b>Detaily</b>:"
5659
5760 #: evinceadapter.py:92
5861 msgid "URL from Read"
59 msgstr ""
62 msgstr "URL z Read"
6063
6164 #: speechtoolbar.py:57
6265 msgid "Play / Pause"
63 msgstr ""
66 msgstr "Prehrať/Zastaviť"
6467
6568 #: speechtoolbar.py:65
6669 msgid "Stop"
67 msgstr ""
70 msgstr "Zastaviť"
6871
6972 #: readactivity.py:379
7073 msgid "Please wait"
71 msgstr ""
74 msgstr "Prosím čakajte"
7275
7376 #: readactivity.py:380
7477 msgid "Starting connection..."
75 msgstr ""
78 msgstr "Pripájanie......"
7679
7780 #: readactivity.py:388
7881 msgid "No book"
79 msgstr ""
82 msgstr "Žiadna kniha"
8083
8184 #: readactivity.py:388
8285 msgid "Choose something to read"
83 msgstr ""
86 msgstr "Vyberte si niečo na čítanie"
8487
8588 #: readactivity.py:393
8689 msgid "Back"
8790 msgstr "Späť"
8891
8992 #: readactivity.py:397
90 #, fuzzy
9193 msgid "Previous page"
92 msgstr "Predchádzajúci strana"
94 msgstr "Predchádzajúca strana"
9395
9496 #: readactivity.py:399
9597 msgid "Previous bookmark"
96 msgstr ""
98 msgstr "Predchádzajúca záložka"
9799
98100 #: readactivity.py:411
99101 msgid "Forward"
100102 msgstr "Dopredu"
101103
102104 #: readactivity.py:415
103 #, fuzzy
104105 msgid "Next page"
105 msgstr "Ďaľší strana"
106 msgstr "Ďalšia strana"
106107
107108 #: readactivity.py:417
108109 msgid "Next bookmark"
109 msgstr ""
110 msgstr "Ďalšia záložka"
110111
111112 #: readactivity.py:468
112113 msgid "Index"
113 msgstr ""
114 msgstr "Zoznam"
114115
115116 #: readactivity.py:564
116117 msgid "Delete bookmark"
117 msgstr ""
118 msgstr "Vymazať záložky"
118119
119120 #: readactivity.py:565
120121 msgid "All the information related with this bookmark will be lost"
121 msgstr ""
122 msgstr "Všetky informácie súvisiace s touto záložkou budú vymazané"
122123
123124 #: readactivity.py:954
124125 msgid "Receiving book..."
125 msgstr ""
126 msgstr "Prijímanie knihy...."
126127
127128 #: readactivity.py:1032 readactivity.py:1227
128129 #, python-format
129130 msgid "%s (Page %d)"
130 msgstr ""
131 msgstr "%s (Strana %d)"
131132
132133 #: readtoolbar.py:61
133134 msgid "Previous"
139140
140141 #: readtoolbar.py:79
141142 msgid "Highlight"
142 msgstr ""
143 msgstr "Zvýraznenie"
143144
144145 #: readtoolbar.py:160
145146 msgid "Find first"
150151 msgstr "Nájsť predchádzajúci"
151152
152153 #: readtoolbar.py:168
153 #, fuzzy
154154 msgid "Find next"
155155 msgstr "Hľadať ďalej"
156156
157157 #: readtoolbar.py:188
158158 msgid "Table of contents"
159 msgstr ""
159 msgstr "Zoznam obsahov"
160160
161161 #: readtoolbar.py:197
162162 msgid "Zoom out"
168168
169169 #: readtoolbar.py:209
170170 msgid "Zoom to width"
171 msgstr ""
171 msgstr "Priblíženie na šírku"
172172
173173 #: readtoolbar.py:215
174174 msgid "Zoom to fit"
175 msgstr ""
175 msgstr "Priblíženie na presnosť"
176176
177177 #: readtoolbar.py:221
178178 msgid "Actual size"
180180
181181 #: readtoolbar.py:232
182182 msgid "Fullscreen"
183 msgstr ""
183 msgstr "Plná obrazovka"
184184
185185 #: readtoolbar.py:252
186186 msgid "Rotate left"
187 msgstr ""
187 msgstr "Otočiť doľava"
188188
189189 #: readtoolbar.py:258
190190 msgid "Rotate right"
191 msgstr ""
191 msgstr "Otočiť doprava"
192192
193193 #: readtoolbar.py:324
194194 msgid "Show Tray"
195 msgstr ""
195 msgstr "Ukázať lištu"
196196
197197 #: readtoolbar.py:326
198198 msgid "Hide Tray"
199 msgstr ""
199 msgstr "Skryť lištu"
200200
201201 #: linkbutton.py:133
202202 msgid "Go to Bookmark"
203 msgstr ""
203 msgstr "Choďte na záložku"
204204
205205 #: linkbutton.py:139
206206 msgid "Remove"
207 msgstr ""
207 msgstr "Odstrániť"
208208
209209 #: bookmarkview.py:107
210210 #, python-format
211211 msgid "Bookmark added by %(user)s %(time)s"
212 msgstr ""
212 msgstr "Pridaná záložka od %(užívateľ)ia %(čas)"
213213
214214 #: bookmarkview.py:143 bookmarkview.py:192
215215 msgid "Add notes for bookmark: "
216 msgstr ""
216 msgstr "Pridajte poznámky k záložke"
217217
218218 #: bookmarkview.py:188
219219 #, python-format
220220 msgid "%s's bookmark"
221 msgstr ""
221 msgstr "%ove/ ina záložka"
222222
223223 #: bookmarkview.py:189
224224 #, python-format
225225 msgid "Bookmark for page %d"
226 msgstr ""
226 msgstr "Záložka pre stránku %d"
227227
228228 #: comicadapter.py:69
229229 msgid "Can not read Comic Book Archive"
230 msgstr ""
230 msgstr "Comic Book Archív je nedostupný"
231231
232232 #: comicadapter.py:70
233233 msgid "No readable images were found"
234 msgstr ""
234 msgstr "Boli nájdené nečitateľné položky"
235235
236236 #~ msgid "%"
237237 #~ msgstr "%"
1414 "Project-Id-Version: PACKAGE VERSION\n"
1515 "Report-Msgid-Bugs-To: \n"
1616 "POT-Creation-Date: 2017-03-24 17:39+1100\n"
17 "PO-Revision-Date: 2011-12-18 22:47+0200\n"
18 "Last-Translator: Chris <cjl@laptop.org>\n"
17 "PO-Revision-Date: 2017-12-03 16:41+0000\n"
18 "Last-Translator: Martin <miles@filmsi.net>\n"
1919 "Language-Team: LANGUAGE <LL@li.org>\n"
2020 "Language: sl\n"
2121 "MIME-Version: 1.0\n"
2323 "Content-Transfer-Encoding: 8bit\n"
2424 "Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || "
2525 "n%100==4 ? 2 : 3);\n"
26 "X-Generator: Pootle 2.0.5\n"
26 "X-Generator: Pootle 2.5.1.1\n"
27 "X-POOTLE-MTIME: 1512319274.000000\n"
2728
2829 #: activity/activity.info:2
2930 msgid "Read"
3435 "Use this activity when you are ready to read! Remember to flip your computer "
3536 "around to feel like you are really holding a book!"
3637 msgstr ""
38 "Uporabi to dejavnost, ko želiš brati! Ne pozabiti obrniti računalnika "
39 "pokonci, da dobiš občutek, da v roki držiš knjigo!"
3740
3841 #: readdialog.py:52
3942 msgid "Cancel"
4952
5053 #: readdialog.py:147
5154 msgid "<b>Author</b>:"
52 msgstr ""
55 msgstr "<b>Avtor</b>:"
5356
5457 #: readdialog.py:163
5558 msgid "<b>Details</b>:"
5760
5861 #: evinceadapter.py:92
5962 msgid "URL from Read"
60 msgstr ""
63 msgstr "URL iz Beri"
6164
6265 #: speechtoolbar.py:57
6366 msgid "Play / Pause"
6568
6669 #: speechtoolbar.py:65
6770 msgid "Stop"
68 msgstr ""
71 msgstr "Ustavi"
6972
7073 #: readactivity.py:379
7174 msgid "Please wait"
72 msgstr ""
75 msgstr "Počakaj malo"
7376
7477 #: readactivity.py:380
7578 msgid "Starting connection..."
76 msgstr ""
79 msgstr "Povezava se vzpostavlja ..."
7780
7881 #: readactivity.py:388
7982 msgid "No book"
80 msgstr ""
83 msgstr "Ni knjige"
8184
8285 #: readactivity.py:388
8386 msgid "Choose something to read"
84 msgstr ""
87 msgstr "Izberi nekaj za branje"
8588
8689 #: readactivity.py:393
8790 msgid "Back"
109112
110113 #: readactivity.py:468
111114 msgid "Index"
112 msgstr ""
115 msgstr "Kazalo"
113116
114117 #: readactivity.py:564
115118 msgid "Delete bookmark"
116 msgstr ""
119 msgstr "Izbriši zaznamek"
117120
118121 #: readactivity.py:565
119122 msgid "All the information related with this bookmark will be lost"
120 msgstr ""
123 msgstr "Vsi podatki o tem zaznamku bodo izgubljeni"
121124
122125 #: readactivity.py:954
123126 msgid "Receiving book..."
124 msgstr ""
127 msgstr "Prejemanje knjige ..."
125128
126129 #: readactivity.py:1032 readactivity.py:1227
127130 #, python-format
128131 msgid "%s (Page %d)"
129 msgstr ""
132 msgstr "%s (stran %d)"
130133
131134 #: readtoolbar.py:61
132135 msgid "Previous"
154157
155158 #: readtoolbar.py:188
156159 msgid "Table of contents"
157 msgstr ""
160 msgstr "Kazalo vsebine"
158161
159162 #: readtoolbar.py:197
160163 msgid "Zoom out"
182185
183186 #: readtoolbar.py:252
184187 msgid "Rotate left"
185 msgstr ""
188 msgstr "Zasukaj levo"
186189
187190 #: readtoolbar.py:258
188191 msgid "Rotate right"
189 msgstr ""
192 msgstr "Zasukaj desno"
190193
191194 #: readtoolbar.py:324
192195 msgid "Show Tray"
193 msgstr ""
196 msgstr "Pokaži pladenj"
194197
195198 #: readtoolbar.py:326
196199 msgid "Hide Tray"
197 msgstr ""
200 msgstr "Skrij pladenj"
198201
199202 #: linkbutton.py:133
200203 msgid "Go to Bookmark"
201 msgstr ""
204 msgstr "Pojdi na zaznamek"
202205
203206 #: linkbutton.py:139
204207 msgid "Remove"
205 msgstr ""
208 msgstr "Odstrani"
206209
207210 #: bookmarkview.py:107
208211 #, python-format
225228
226229 #: comicadapter.py:69
227230 msgid "Can not read Comic Book Archive"
228 msgstr ""
231 msgstr "Ni mogoče brati iz Comic Book Archive"
229232
230233 #: comicadapter.py:70
231234 msgid "No readable images were found"
232 msgstr ""
235 msgstr "Nobenih berljivih slik ni mogoče najti"
233236
234237 #, python-format
235238 #~ msgid "Page %(current)i of %(total_pages)i"
1414 "Project-Id-Version: PACKAGE VERSION\n"
1515 "Report-Msgid-Bugs-To: \n"
1616 "POT-Creation-Date: 2017-03-24 17:39+1100\n"
17 "PO-Revision-Date: 2017-04-17 05:32+0000\n"
18 "Last-Translator: Chris <cjl@sugarlabs.org>\n"
17 "PO-Revision-Date: 2018-02-03 21:13+0000\n"
18 "Last-Translator: Besnik_b <besnik@programeshqip.org>\n"
1919 "Language-Team: LANGUAGE <LL@li.org>\n"
2020 "Language: sq\n"
2121 "MIME-Version: 1.0\n"
2323 "Content-Transfer-Encoding: 8bit\n"
2424 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
2525 "X-Generator: Pootle 2.5.1.1\n"
26 "X-POOTLE-MTIME: 1492407135.000000\n"
26 "X-POOTLE-MTIME: 1517692424.000000\n"
2727
2828 #: activity/activity.info:2
2929 msgid "Read"
5252
5353 #: readdialog.py:147
5454 msgid "<b>Author</b>:"
55 msgstr ""
55 msgstr "<b>Autor</b>:"
5656
5757 #: readdialog.py:163
5858 msgid "<b>Details</b>:"
7272
7373 #: readactivity.py:379
7474 msgid "Please wait"
75 msgstr ""
75 msgstr "Ju lutemi, pritni"
7676
7777 #: readactivity.py:380
7878 msgid "Starting connection..."
79 msgstr ""
79 msgstr "Po fillohet lidhja…"
8080
8181 #: readactivity.py:388
8282 msgid "No book"
124124
125125 #: readactivity.py:954
126126 msgid "Receiving book..."
127 msgstr ""
127 msgstr "Po merret libër…"
128128
129129 #: readactivity.py:1032 readactivity.py:1227
130130 #, python-format
131131 msgid "%s (Page %d)"
132 msgstr ""
132 msgstr "%s (Faqja %d)"
133133
134134 #: readtoolbar.py:61
135135 msgid "Previous"
157157
158158 #: readtoolbar.py:188
159159 msgid "Table of contents"
160 msgstr "Tabelë e lëndës"
160 msgstr "Pasqyrë e lëndës"
161161
162162 #: readtoolbar.py:197
163163 msgid "Zoom out"
185185
186186 #: readtoolbar.py:252
187187 msgid "Rotate left"
188 msgstr ""
188 msgstr "Rrotulloje majtas"
189189
190190 #: readtoolbar.py:258
191191 msgid "Rotate right"
192 msgstr ""
192 msgstr "Rrotulloje djathtas"
193193
194194 #: readtoolbar.py:324
195195 msgid "Show Tray"
228228
229229 #: comicadapter.py:69
230230 msgid "Can not read Comic Book Archive"
231 msgstr ""
231 msgstr "S’lexohet dot te Comic Book Archive"
232232
233233 #: comicadapter.py:70
234234 msgid "No readable images were found"
235 msgstr ""
235 msgstr "S’u gjetën figura të lexueshme"
236236
237237 #, python-format
238238 #~ msgid "Page %d"
2626 import cairo
2727 import json
2828
29 import emptypanel
30
3129 import dbus
30
31 import gi
32 gi.require_version('Gtk', '3.0')
33 gi.require_version('Gst', '1.0')
34 gi.require_version('TelepathyGLib', '0.12')
35
36 from gi.repository import GLib
3237 from gi.repository import GObject
3338 from gi.repository import Gtk
3439 from gi.repository import Gdk
3540 from gi.repository import Gio
41 from gi.repository import TelepathyGLib
3642
3743 GObject.threads_init()
38
39 import telepathy
4044
4145 from sugar3.activity import activity
4246 from sugar3.graphics.toolbutton import ToolButton
4852 from sugar3.activity.widgets import ActivityToolbarButton
4953 from sugar3.activity.widgets import StopButton
5054 from sugar3.graphics.tray import HTray
55 from sugar3.graphics.menuitem import MenuItem
5156 from sugar3 import network
5257 from sugar3 import mime
5358 from sugar3 import profile
6166
6267 from sugar3.graphics import style
6368
69 import emptypanel
6470 from readtoolbar import EditToolbar
6571 from readtoolbar import ViewToolbar
6672 from bookmarkview import BookmarkView
6773 from readdb import BookmarkManager
68 from sugar3.graphics.menuitem import MenuItem
6974 from linkbutton import LinkButton
75 from speechtoolbar import SpeechToolbar
7076
7177 _HARDWARE_MANAGER_INTERFACE = 'org.laptop.HardwareManager'
7278 _HARDWARE_MANAGER_SERVICE = 'org.laptop.HardwareManager'
504510
505511 def __toogle_tray_cb(self, button, visible):
506512 if visible:
507 logging.error('Show tray')
513 logging.debug('Show tray')
508514 self.tray.show()
509515 else:
510 logging.error('Hide tray')
516 logging.debug('Hide tray')
511517 self.tray.hide()
512518
513519 def __num_page_entry_insert_text_cb(self, entry, text, length, position):
684690 if self.props.active:
685691 # Now active, start initial suspend timeout
686692 if self._idle_timer > 0:
687 GObject.source_remove(self._idle_timer)
688 self._idle_timer = GObject.timeout_add_seconds(15,
689 self._suspend_cb)
693 GLib.source_remove(self._idle_timer)
694 self._idle_timer = GLib.timeout_add_seconds(15,
695 self._suspend_cb)
690696 self._sleep_inhibit = False
691697 else:
692698 # Now inactive
704710 def _user_action_cb(self, widget):
705711 """Set a timer for going back to ebook mode idle sleep."""
706712 if self._idle_timer > 0:
707 GObject.source_remove(self._idle_timer)
708 self._idle_timer = GObject.timeout_add_seconds(5, self._suspend_cb)
713 GLib.source_remove(self._idle_timer)
714 self._idle_timer = GLib.timeout_add_seconds(5, self._suspend_cb)
709715
710716 def _suspend_cb(self):
711717 """Go into ebook mode idle sleep."""
730736 self._load_document('file://' + tempfile)
731737
732738 # FIXME: This should obviously be fixed properly
733 GObject.timeout_add_seconds(
739 GLib.timeout_add_seconds(
734740 1, self.__view_toolbar_needs_update_size_cb, None)
735741
736742 def write_file(self, file_path):
840846 self._progress_alert = None
841847
842848 # download the metadata
843 GObject.idle_add(self._download_metadata, tube_id, tube_ip, tube_port)
849 GLib.idle_add(self._download_metadata, tube_id, tube_ip, tube_port)
844850
845851 def _download_metadata_result_cb(self, getter, tempfile, suggested_name,
846852 tube_id):
850856 os.remove(tempfile)
851857
852858 # load the object from the datastore to update the file path
853 GObject.idle_add(self._open_downloaded_file, shared_metadata)
859 GLib.idle_add(self._open_downloaded_file, shared_metadata)
854860
855861 def _open_downloaded_file(self, shared_metadata):
856862 self._jobject = datastore.get(self._jobject.object_id)
881887 if self._progress_alert is not None:
882888 self.remove_alert(self._progress_alert)
883889 self._progress_alert = None
884 GObject.idle_add(self._get_document)
890 GLib.idle_add(self._get_document)
885891
886892 def _get_connection_params(self, tube_id):
887893 # return ip and port to download a file
888894 chan = self.shared_activity.telepathy_tubes_chan
889 iface = chan[telepathy.CHANNEL_TYPE_TUBES]
895 iface = chan[TelepathyGLib.IFACE_CHANNEL_TYPE_TUBES]
890896 addr = iface.AcceptStreamTube(
891897 tube_id,
892 telepathy.SOCKET_ADDRESS_TYPE_IPV4,
893 telepathy.SOCKET_ACCESS_CONTROL_LOCALHOST, 0,
898 TelepathyGLib.SocketAddressType.IPV4,
899 TelepathyGLib.SocketAccessControl.LOCALHOST, 0,
894900 utf8_strings=True)
895901 _logger.debug('Accepted stream tube: listening address is %r', addr)
896902 # SOCKET_ADDRESS_TYPE_IPV4 is defined to have addresses of type '(sq)'
939945
940946 # Avoid trying to download the document multiple times at once
941947 self._want_document = False
942 GObject.idle_add(self._download_document, tube_id)
948 GLib.idle_add(self._download_document, tube_id)
943949 return False
944950
945951 def _joined_cb(self, also_self):
951957 if self._progress_alert is not None:
952958 self._progress_alert.props.msg = _('Receiving book...')
953959
954 GObject.idle_add(self._get_document)
960 GLib.idle_add(self._get_document)
955961
956962 def _load_document(self, filepath):
957963 """Load the specified document and set up the UI.
10191025 page = bookmark.page_no
10201026 thumb = self._bookmarkmanager.get_bookmark_preview(page)
10211027 if thumb is None:
1022 logging.error('Preview NOT FOUND')
1028 logging.debug('Preview NOT FOUND')
10231029 thumb = self._get_screenshot()
10241030 # The database is zero based
10251031 num_page = int(page) + 1
10601066 if self._view.can_highlight():
10611067 self._highlight.show()
10621068 if self._view.can_do_text_to_speech():
1063 import speech
1064 from speechtoolbar import SpeechToolbar
1065 if speech.supported:
1066 self.speech_toolbar = SpeechToolbar(self)
1067 self.speech_toolbar_button.set_page(self.speech_toolbar)
1068 self.speech_toolbar_button.show()
1069 self.speech_toolbar = SpeechToolbar(self)
1070 self.speech_toolbar_button.set_page(self.speech_toolbar)
1071 self.speech_toolbar_button.show()
10691072
10701073 def _share_document(self):
10711074 """Share the document."""
10801083
10811084 # Make a tube for it
10821085 chan = self.shared_activity.telepathy_tubes_chan
1083 iface = chan[telepathy.CHANNEL_TYPE_TUBES]
1086 iface = chan[TelepathyGLib.IFACE_CHANNEL_TYPE_TUBES]
10841087 self._fileserver_tube_id = iface.OfferStreamTube(
10851088 READ_STREAM_SERVICE,
10861089 {},
1087 telepathy.SOCKET_ADDRESS_TYPE_IPV4,
1090 TelepathyGLib.SocketAddressType.IPV4,
10881091 ('127.0.0.1', dbus.UInt16(self.port)),
1089 telepathy.SOCKET_ACCESS_CONTROL_LOCALHOST, 0)
1092 TelepathyGLib.SocketAccessControl.LOCALHOST, 0)
10901093
10911094 def create_metadata_file(self):
10921095 # store the metadata in a json file
10971100 for key in self.metadata.keys():
10981101 if key not in ['preview', 'cover_image']:
10991102 shared_metadata[str(key)] = self.metadata[key]
1100 logging.error('save metadata in %s', metadata_file_path)
1103 logging.debug('save metadata in %s', metadata_file_path)
11011104 with open(metadata_file_path, 'w') as json_file:
11021105 json.dump(shared_metadata, json_file)
11031106 return metadata_file_path
11061109 """Watch for new tubes."""
11071110 tubes_chan = self.shared_activity.telepathy_tubes_chan
11081111
1109 tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal(
1112 tubes_chan[TelepathyGLib.IFACE_CHANNEL_TYPE_TUBES].connect_to_signal(
11101113 'NewTube', self._new_tube_cb)
1111 tubes_chan[telepathy.CHANNEL_TYPE_TUBES].ListTubes(
1114 tubes_chan[TelepathyGLib.IFACE_CHANNEL_TYPE_TUBES].ListTubes(
11121115 reply_handler=self._list_tubes_reply_cb,
11131116 error_handler=self._list_tubes_error_cb)
11141117
11231126 self.unused_download_tubes.add(tube_id)
11241127 # if no download is in progress, let's fetch the document
11251128 if self._want_document:
1126 GObject.idle_add(self._get_document)
1129 GLib.idle_add(self._get_document)
11271130
11281131 def _list_tubes_reply_cb(self, tubes):
11291132 """Callback when new tubes are available."""
12171220 self.fullscreen()
12181221
12191222 def _added_bookmark_cb(self, bookmarkmanager, page, title):
1220 logging.error('Bookmark added page %d', page)
1223 logging.debug('Bookmark added page %d', page)
12211224 title = _('%s (Page %d)') % (title, page)
12221225 color = profile.get_color().to_string()
12231226 owner = profile.get_nick_name()
12261229 bookmarkmanager.add_bookmark_preview(page - 1, thumb)
12271230
12281231 def _removed_bookmark_cb(self, bookmarkmanager, page):
1229 logging.error('Bookmark removed page %d', page)
1232 logging.debug('Bookmark removed page %d', page)
12301233 # remove button from tray
12311234 for button in self.tray.get_children():
12321235 if button.page == page:
12541257 # but we don't have a event yet, Evince model have a event
12551258 # we need check the differnt backends and implement
12561259 # in all the backends.
1257 GObject.timeout_add_seconds(2, self._update_preview, button, page)
1260 GLib.timeout_add_seconds(2, self._update_preview, button, page)
12581261
12591262 def _update_preview(self, button, page):
12601263 thumb = self._get_screenshot()
3636 dbpath = os.path.join(dbdir, 'read_v1.db')
3737 olddbpath = os.path.join(dbdir, 'read.db')
3838
39 srcpath = os.path.join(os.environ['SUGAR_BUNDLE_PATH'], 'read_v1.db')
40
4139 # Situation 0: Db is existent
4240 if os.path.exists(dbpath):
4341 return dbpath
119117
120118 self._bookmarks = []
121119 self._populate_bookmarks()
122 self._highlights = {0: []}
120 self._highlights = {0: []}
123121 self._populate_highlights()
124122
125123 self._user = profile.get_nick_name()
125125 self._search_entry_changed = True
126126 self._update_find_buttons()
127127
128 # GObject.timeout_add(500, self._search_entry_timeout_cb)
128 # GLib.timeout_add(500, self._search_entry_timeout_cb)
129129 #
130130 # def _search_entry_timeout_cb(self):
131131 # self._clear_find_job()
+0
-45
speech.py less more
0 # Copyright (C) 2008, 2009 James D. Simmons
1 # Copyright (C) 2009 Aleksey S. Lim
2 #
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
12 #
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software
15 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16
17 import logging
18
19 _logger = logging.getLogger('read-activity')
20
21 supported = True
22
23 try:
24 from gi.repository import Gst
25 Gst.init(None)
26 Gst.ElementFactory.make('espeak', None)
27 from speech_gst import *
28 _logger.error('use gst-plugins-espeak')
29 except Exception, e:
30 _logger.error('disable gst-plugins-espeak: %s' % e)
31 try:
32 from speech_dispatcher import *
33 _logger.error('use speech-dispatcher')
34 except Exception, e:
35 supported = False
36 _logger.error('disable speech: %s' % e)
37
38 voice = 'default'
39 pitch = 0
40 rate = 0
41
42 highlight_cb = None
43 end_text_cb = None
44 reset_cb = None
+0
-124
speech_dispatcher.py less more
0 # Copyright (C) 2008 James D. Simmons
1 #
2 # This program is free software; you can redistribute it and/or modify
3 # it under the terms of the GNU General Public License as published by
4 # the Free Software Foundation; either version 2 of the License, or
5 # (at your option) any later version.
6 #
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
11 #
12 # You should have received a copy of the GNU General Public License
13 # along with this program; if not, write to the Free Software
14 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
15
16 from gi.repository import Gdk
17 import time
18 import threading
19 import speechd
20 import logging
21
22 import speech
23
24 _logger = logging.getLogger('read-etexts-activity')
25
26 done = True
27
28
29 def voices():
30 try:
31 client = speechd.SSIPClient('readetextstest')
32 voices = client.list_synthesis_voices()
33 client.close()
34 return voices
35 except Exception, e:
36 _logger.warning('speech dispatcher not started: %s' % e)
37 return []
38
39
40 def say(words):
41 try:
42 client = speechd.SSIPClient('readetextstest')
43 client.set_rate(int(speech.rate))
44 client.set_pitch(int(speech.pitch))
45 client.set_language(speech.voice[1])
46 client.speak(words)
47 client.close()
48 except Exception, e:
49 _logger.warning('speech dispatcher not running: %s' % e)
50
51
52 def is_stopped():
53 return done
54
55
56 def pause():
57 pass
58
59
60 def stop():
61 global done
62 done = True
63
64
65 def play(words):
66 global thread
67 thread = EspeakThread(words)
68 thread.start()
69
70
71 class EspeakThread(threading.Thread):
72
73 def __init__(self, words):
74 threading.Thread.__init__(self)
75 self.words = words
76
77 def run(self):
78 "This is the code that is executed when the start() method is called"
79 self.client = None
80 try:
81 self.client = speechd.SSIPClient('readetexts')
82 self.client._conn.send_command('SET', speechd.Scope.SELF,
83 'SSML_MODE', "ON")
84 if speech.voice:
85 self.client.set_language(speech.voice[1])
86 self.client.set_rate(speech.rate)
87 self.client.set_pitch(speech.pitch)
88 self.client.speak(self.words, self.next_word_cb,
89 (speechd.CallbackType.INDEX_MARK,
90 speechd.CallbackType.END))
91 global done
92 done = False
93 while not done:
94 time.sleep(0.1)
95 self.cancel()
96 self.client.close()
97 except Exception, e:
98 _logger.warning('speech-dispatcher client not created: %s' % e)
99
100 def cancel(self):
101 if self.client:
102 try:
103 self.client.cancel()
104 except Exception, e:
105 _logger.warning('speech dispatcher cancel failed: %s' % e)
106
107 def next_word_cb(self, type, **kargs):
108 if type == speechd.CallbackType.INDEX_MARK:
109 mark = kargs['index_mark']
110 word_count = int(mark)
111 Gdk.threads_enter()
112 speech.highlight_cb(word_count)
113 Gdk.threads_leave()
114 elif type == speechd.CallbackType.END:
115 Gdk.threads_enter()
116 if speech.reset_cb is not None:
117 speech.reset_cb()
118 if speech.reset_buttons_cb is not None:
119 speech.reset_buttons_cb()
120
121 Gdk.threads_leave()
122 global done
123 done = True
+0
-104
speech_gst.py less more
0 # Copyright (C) 2009 Aleksey S. Lim
1 #
2 # This program is free software; you can redistribute it and/or modify
3 # it under the terms of the GNU General Public License as published by
4 # the Free Software Foundation; either version 2 of the License, or
5 # (at your option) any later version.
6 #
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
11 #
12 # You should have received a copy of the GNU General Public License
13 # along with this program; if not, write to the Free Software
14 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
15
16 from gi.repository import Gst
17 import logging
18
19 import speech
20
21 _logger = logging.getLogger('read-activity')
22
23
24 def get_all_voices():
25 all_voices = {}
26 for voice in Gst.ElementFactory.make('espeak', None).props.voices:
27 name, language, dialect = voice
28 if dialect != 'none':
29 all_voices[language + '_' + dialect] = name
30 else:
31 all_voices[language] = name
32 return all_voices
33
34
35 def _message_cb(bus, message, pipe):
36 if message.type == Gst.MessageType.EOS:
37 pipe.set_state(Gst.State.NULL)
38 if speech.end_text_cb is not None:
39 speech.end_text_cb()
40 if message.type == Gst.MessageType.ERROR:
41 pipe.set_state(Gst.State.NULL)
42 if pipe is play_speaker[1]:
43 speech.reset_cb()
44 elif message.type == Gst.MessageType.ELEMENT and \
45 message.structure.get_name() == 'espeak-mark':
46 mark = message.structure['mark']
47 speech.highlight_cb(int(mark))
48
49
50 def _create_pipe():
51 pipe = Gst.parse_launch('espeak name=espeak ! autoaudiosink')
52 source = pipe.get_by_name('espeak')
53
54 bus = pipe.get_bus()
55 bus.add_signal_watch()
56 bus.connect('message', _message_cb, pipe)
57
58 return (source, pipe)
59
60
61 def _speech(speaker, words):
62 speaker[0].props.pitch = speech.pitch
63 speaker[0].props.rate = speech.rate
64 speaker[0].props.voice = speech.voice[1]
65 speaker[0].props.text = words
66 speaker[1].set_state(Gst.State.NULL)
67 speaker[1].set_state(Gst.State.PLAYING)
68
69
70 info_speaker = _create_pipe()
71 play_speaker = _create_pipe()
72 play_speaker[0].props.track = 2
73
74
75 def voices():
76 return info_speaker[0].props.voices
77
78
79 def say(words):
80 _speech(info_speaker, words)
81
82
83 def play(words):
84 _speech(play_speaker, words)
85
86
87 def pause():
88 play_speaker[1].set_state(Gst.State.PAUSED)
89
90
91 def continue_play():
92 play_speaker[1].set_state(Gst.State.PLAYING)
93
94
95 def is_stopped():
96 for i in play_speaker[1].get_state():
97 if isinstance(i, Gst.State) and i == Gst.State.NULL:
98 return True
99 return False
100
101
102 def stop():
103 play_speaker[1].set_state(Gst.State.NULL)
1818 from gettext import gettext as _
1919
2020 from gi.repository import Gtk
21 from gi.repository import GConf
2221
2322 from sugar3.graphics.toolbutton import ToolButton
2423 from sugar3.graphics.toggletoolbutton import ToggleToolButton
2524 from sugar3.graphics.combobox import ComboBox
2625 from sugar3.graphics.toolcombobox import ToolComboBox
27
28 import speech
26 from sugar3.speech import SpeechManager
2927
3028
3129 class SpeechToolbar(Gtk.Toolbar):
3331 def __init__(self, activity):
3432 Gtk.Toolbar.__init__(self)
3533 self._activity = activity
36 if not speech.supported:
37 return
38 self.is_paused = False
34 self._speech = SpeechManager()
35 self._is_paused = False
3936
40 self._cnf_client = GConf.Client.get_default()
4137 self.load_speech_parameters()
4238
43 self.sorted_voices = [i for i in speech.voices()]
44 self.sorted_voices.sort(self.compare_voices)
45 default = 0
46 for voice in self.sorted_voices:
47 if voice[0] == speech.voice[0]:
48 break
49 default = default + 1
39 self._voices = self._speech.get_all_voices() # a dictionary
40
41 locale = os.environ.get('LANG', '')
42 language_location = locale.split('.', 1)[0].lower()
43 language = language_location.split('_')[0]
44 # if the language is es but not es_es default to es_la (latin voice)
45 if language == 'es' and language_location != 'es_es':
46 language_location = 'es_la'
47
48 self._voice = 'en_us'
49 if language_location in self._voices:
50 self._voice = language_location
51 elif language in self._voices:
52 self._voice = language
53
54 voice_names = []
55 for language, name in self._voices.iteritems():
56 voice_names.append((language, name))
57 voice_names.sort(self._compare_voice)
5058
5159 # Play button
52 self.play_btn = ToggleToolButton('media-playback-start')
53 self.play_btn.show()
54 self.play_btn.connect('toggled', self.play_cb)
55 self.insert(self.play_btn, -1)
56 self.play_btn.set_tooltip(_('Play / Pause'))
60 self._play_button = ToggleToolButton('media-playback-start')
61 self._play_button.show()
62 self._play_button.connect('toggled', self._play_toggled_cb)
63 self.insert(self._play_button, -1)
64 self._play_button.set_tooltip(_('Play / Pause'))
5765
5866 # Stop button
59 self.stop_btn = ToolButton('media-playback-stop')
60 self.stop_btn.show()
61 self.stop_btn.connect('clicked', self.stop_cb)
62 self.stop_btn.set_sensitive(False)
63 self.insert(self.stop_btn, -1)
64 self.stop_btn.set_tooltip(_('Stop'))
67 self._stop_button = ToolButton('media-playback-stop')
68 self._stop_button.show()
69 self._stop_button.connect('clicked', self._stop_clicked_cb)
70 self._stop_button.set_sensitive(False)
71 self.insert(self._stop_button, -1)
72 self._stop_button.set_tooltip(_('Stop'))
6573
66 self.voice_combo = ComboBox()
67 for voice in self.sorted_voices:
68 self.voice_combo.append_item(voice, voice[0])
69 self.voice_combo.set_active(default)
74 # Language list
75 combo = ComboBox()
76 which = 0
77 for pair in voice_names:
78 language, name = pair
79 combo.append_item(language, name)
80 if language == self._voice:
81 combo.set_active(which)
82 which += 1
7083
71 self.voice_combo.connect('changed', self.voice_changed_cb)
72 combotool = ToolComboBox(self.voice_combo)
84 combo.connect('changed', self._voice_changed_cb)
85 combotool = ToolComboBox(combo)
7386 self.insert(combotool, -1)
7487 combotool.show()
75 speech.reset_buttons_cb = self.reset_buttons_cb
7688
77 def compare_voices(self, a, b):
78 if a[0].lower() == b[0].lower():
89 self._speech.connect('stop', self._reset_buttons_cb)
90
91 def _compare_voice(self, a, b):
92 if a[1].lower() == b[1].lower():
7993 return 0
80 if a[0] .lower() < b[0].lower():
94 if a[1].lower() < b[1].lower():
8195 return -1
82 if a[0] .lower() > b[0].lower():
96 if a[1].lower() > b[1].lower():
8397 return 1
8498
85 def voice_changed_cb(self, combo):
86 speech.voice = combo.props.value
87 speech.say(speech.voice[0])
99 def _voice_changed_cb(self, combo):
100 self._voice = combo.props.value
101 self._speech.say_text(self._voices[self._voice])
88102 self.save_speech_parameters()
89103
90104 def load_speech_parameters(self):
95109 f = open(data_file_name, 'r')
96110 try:
97111 speech_parameters = json.load(f)
98 speech.voice = speech_parameters['voice']
112 self._voice = speech_parameters['voice']
99113 finally:
100114 f.close()
101115
102 self._cnf_client.add_dir('/desktop/sugar/speech',
103 GConf.ClientPreloadType.PRELOAD_NONE)
104 speech.pitch = self._cnf_client.get_int('/desktop/sugar/speech/pitch')
105 speech.rate = self._cnf_client.get_int('/desktop/sugar/speech/rate')
106 self._cnf_client.notify_add('/desktop/sugar/speech/pitch',
107 self.__conf_changed_cb, None)
108 self._cnf_client.notify_add('/desktop/sugar/speech/rate',
109 self.__conf_changed_cb, None)
110
111 def __conf_changed_cb(self, client, connection_id, entry, args):
112 key = entry.get_key()
113 value = client.get_int(key)
114 if key == '/desktop/sugar/speech/pitch':
115 speech.pitch = value
116 if key == '/desktop/sugar/speech/rate':
117 speech.rate = value
118
119116 def save_speech_parameters(self):
120117 speech_parameters = {}
121 speech_parameters['voice'] = speech.voice
118 speech_parameters['voice'] = self._voice
122119 data_path = os.path.join(self._activity.get_activity_root(), 'data')
123120 data_file_name = os.path.join(data_path, 'speech_params.json')
124121 f = open(data_file_name, 'w')
127124 finally:
128125 f.close()
129126
130 def reset_buttons_cb(self):
131 self.play_btn.set_icon_name('media-playback-start')
132 self.stop_btn.set_sensitive(False)
133 self.is_paused = False
127 def _reset_buttons_cb(self, widget=None):
128 self._play_button.set_icon_name('media-playback-start')
129 self._stop_button.set_sensitive(False)
130 self._is_paused = False
134131
135 def play_cb(self, widget):
136 self.stop_btn.set_sensitive(True)
132 def _play_toggled_cb(self, widget):
133 self._stop_button.set_sensitive(True)
137134 if widget.get_active():
138 self.play_btn.set_icon_name('media-playback-pause')
139 if not self.is_paused:
140 speech.play(self._activity._view.get_marked_words())
135 self._play_button.set_icon_name('media-playback-pause')
136 if not self._is_paused:
137 self._speech.say_text(
138 self._activity._view.get_marked_words(),
139 lang_code=self._voice)
141140 else:
142 speech.continue_play()
141 self._speech.restart()
143142 else:
144 self.play_btn.set_icon_name('media-playback-start')
145 self.is_paused = True
146 speech.pause()
143 self._play_button.set_icon_name('media-playback-start')
144 self._is_paused = True
145 self._speech.pause()
147146
148 def stop_cb(self, widget):
149 self.stop_btn.set_sensitive(False)
150 self.play_btn.set_icon_name('media-playback-start')
151 self.play_btn.set_active(False)
152 self.is_paused = False
153 speech.stop()
147 def _stop_clicked_cb(self, widget):
148 self._stop_button.set_sensitive(False)
149 self._play_button.set_icon_name('media-playback-start')
150 self._play_button.set_active(False)
151 self._is_paused = False
152 self._speech.stop()
88
99 from sugar3 import mime
1010 from sugar3.graphics import style
11
12 import speech
1311
1412 PAGE_SIZE = 38
1513
9694 self.spoken_word_tag = self.textview.get_buffer().create_tag()
9795 self.spoken_word_tag.set_property('weight', Pango.Weight.BOLD)
9896 self.normal_tag = self.textview.get_buffer().create_tag()
99 self.normal_tag.set_property('weight', Pango.Weight.NORMAL)
97 self.normal_tag.set_property('weight', Pango.Weight.NORMAL)
10098
10199 def load_document(self, file_path):
102100
103101 file_name = file_path.replace('file://', '')
104102 mimetype = mime.get_for_file(file_path)
105103 if mimetype == 'application/zip':
106 logging.error('opening zip file')
104 logging.debug('opening zip file')
107105 self.zf = zipfile.ZipFile(file_path.replace('file://', ''), 'r')
108106 self.book_files = self.zf.namelist()
109107 extract_path = os.path.join(self._activity.get_activity_root(),
113111 self.zf.extract(book_file, extract_path)
114112 file_name = os.path.join(extract_path, book_file)
115113
116 logging.error('opening file_name %s' % file_name)
114 logging.debug('opening file_name %s' % file_name)
117115 self._etext_file = open(file_name, 'r')
118116
119117 self.page_index = [0]
135133 self._scrollbar.set_range(1.0, self._pagecount - 1.0)
136134 self._scrollbar.set_increments(1.0, 1.0)
137135
138 speech.highlight_cb = self.highlight_next_word
139 speech.reset_cb = self.reset_text_to_speech
136 # TODO: if ever sugar3.speech has word signals
137 # call self.highlight_next_word on each word
138 # call self.reset_text_to_speech at end
140139
141140 def _show_page(self, page_number):
142141 position = self.page_index[page_number]
149148 break
150149 else:
151150 line = _clean_text(line)
152 label_text = label_text + unicode(line, "iso-8859-1")
151 label_text = label_text + unicode(line, "iso-8859-1")
153152 line_increment = (len(line) / 80) + 1
154153 linecount = linecount + line_increment
155154 textbuffer = self.textview.get_buffer()
195194 self._current_page = int(value)
196195 self.emit('page-changed', old_page, self._current_page)
197196 else:
198 print 'Warning: unknown scrolltype %s with value %f' \
199 % (str(scrolltype), value)
197 print('Warning: unknown scrolltype %s with value %f'
198 % (str(scrolltype), value))
200199
201200 # FIXME: This should not be needed here
202201 self._scrollbar.set_value(self._current_page)
280279 marked_up_text = '<speak> '
281280 while i < len(self.word_tuples):
282281 word_tuple = self.word_tuples[i]
283 marked_up_text = marked_up_text + '<mark name="' + str(i) + '"/>' \
284 + word_tuple[2]
282 marked_up_text = marked_up_text + \
283 ' <mark name="' + str(i) + '"/>' + word_tuple[2]
285284 i = i + 1
286285 print marked_up_text
287286 return marked_up_text + '</speak>'
294293 j = 0
295294 word_begin = 0
296295 word_end = 0
297 ignore_chars = [' ', '\n', u'\r', '_', '[', '{', ']', '}', '|',
298 '<', '>', '*', '+', '/', '\\']
296 ignore_chars = [' ', '\n', u'\r', '_', '[', '{', ']', '}', '|',
297 '<', '>', '*', '+', '/', '\\']
299298 ignore_set = set(ignore_chars)
300299 self.word_tuples = []
301300 len_page_text = len(page_text)
313312 self.word_tuples.append(word_tuple)
314313 i = i + 1
315314
316 def highlight_next_word(self, word_count):
315 def highlight_next_word(self, word_count):
317316 if word_count < len(self.word_tuples):
318317 word_tuple = self.word_tuples[word_count]
319318 textbuffer = self.textview.get_buffer()
320319 iterStart = textbuffer.get_iter_at_offset(word_tuple[0])
321320 iterEnd = textbuffer.get_iter_at_offset(word_tuple[1])
322321 bounds = textbuffer.get_bounds()
323 textbuffer.apply_tag(self.normal_tag, bounds[0], iterStart)
322 textbuffer.apply_tag(self.normal_tag, bounds[0], iterStart)
324323 textbuffer.apply_tag(self.spoken_word_tag, iterStart, iterEnd)
325324 v_adjustment = self._sw.get_vadjustment()
326325 max_pos = v_adjustment.get_upper() - v_adjustment.get_page_size()
338337 self.metadata = activity.metadata
339338 if 'Read_zoom' in self.metadata:
340339 try:
341 logging.error('Loading zoom %s', self.metadata['Read_zoom'])
340 logging.debug('Loading zoom %s', self.metadata['Read_zoom'])
342341 self.set_zoom(float(self.metadata['Read_zoom']))
343342 except:
344343 pass
435434 def get_has_selection(self):
436435 return self._has_selection
437436
438 def find_set_highlight_search(self, True):
437 def find_set_highlight_search(self, boolean):
439438 pass
440439
441440 def setup_find_job(self, text, _find_updated_cb):
621620
622621 return False
623622
624 def _allindices(self, line, search, listindex=None, offset=0):
623 def _allindices(self, line, search, listindex=None, offset=0):
625624 if listindex is None:
626625 listindex = []
627626 if (line.find(search) == -1):