mirror of
https://github.com/MCV-Software/TWBlue.git
synced 2025-08-25 09:29:22 +00:00
Compare commits
74 Commits
snapshot10
...
snapshot10
Author | SHA1 | Date | |
---|---|---|---|
93dc3ad646 | |||
8e67ed025c | |||
fa1b8bfde3 | |||
7dfe2cbb5c | |||
880c421f3e | |||
e1b8d49af5 | |||
e1d14b8c27 | |||
594b0cd546 | |||
fe9f724673 | |||
6a4a3cc94e | |||
![]() |
af41dcfc4e | ||
31611d8429 | |||
7ed44c839e | |||
503c65692d | |||
f76b86b24d | |||
1f96e71b63 | |||
![]() |
cc249fe1a7 | ||
![]() |
268bd35f3a | ||
![]() |
0307c0abe3 | ||
![]() |
adf062f654 | ||
70b5f25cf0 | |||
2b65b89afb | |||
44e8ed6456 | |||
792655e299 | |||
0f56d8cdd4 | |||
6c47dd2fa9 | |||
![]() |
49073bc151 | ||
![]() |
336acd9860 | ||
4daeeb7beb | |||
408ff50404 | |||
148c5176c6 | |||
bdb9de863f | |||
ce1f8b2cc3 | |||
5933323beb | |||
22b1b0a149 | |||
e71afeb10f | |||
98f026156d | |||
cbee57aa30 | |||
fd9e4dc05d | |||
6022cecad1 | |||
89e39e2168 | |||
a69bf99c1a | |||
d34ef81324 | |||
a3c050195a | |||
3623eafacd | |||
![]() |
2bd3f0a1d1 | ||
f1f828522e | |||
51e4898346 | |||
c4478198b6 | |||
f468924b85 | |||
158b48e4d5 | |||
756a58e443 | |||
85ce5b0791 | |||
![]() |
e534d1cd20 | ||
2d35304ef0 | |||
4f0e6d758b | |||
bd4aa89c2b | |||
b046360293 | |||
6971fb3999 | |||
7b840f29c4 | |||
71fed7300b | |||
57315c3b6e | |||
3d3abc90e1 | |||
de7882e4cf | |||
![]() |
10190d61c0 | ||
bb6fa7cb46 | |||
80cb70c9a6 | |||
77d51aa51a | |||
![]() |
ebb4e22d02 | ||
4344a0df0c | |||
34ad0c5e47 | |||
704ade560a | |||
a4892cf847 | |||
e59661775a |
25
README.md
25
README.md
@@ -39,7 +39,7 @@ If you want to build both x86 and x64 binaries, you can install python x86 to C:
|
||||
* [Pycurl](http://pycurl.sourceforge.net) 7.19.5.1 for Python 2.7: [32-bit downloads,](https://pypi.python.org/pypi/pycurl/7.19.5.1) [64-bit downloads](http://www.lfd.uci.edu/~gohlke/pythonlibs/)
|
||||
Note: the x64 version is in wheel format instead of executable installer, so you have to install it using pip. For example: C:\python27x64\scripts\pip install pycurl-7.19.5.1-cp27-none-win_amd64.whl
|
||||
* [PyEnchant,](http://pythonhosted.org/pyenchant/) version 1.6.6.
|
||||
x64 version has been built by TW Blue developers, so you only will find it in windows-dependencies folder
|
||||
x64 version has been built by TWBlue developers, so you only will find it in windows-dependencies folder
|
||||
|
||||
The windows installers are available only in the windows-dependencies folder
|
||||
|
||||
@@ -71,8 +71,11 @@ setuptools install a script, called easy_install. You can find it in the python
|
||||
* arrow
|
||||
* goslate
|
||||
* markdown
|
||||
* pocket
|
||||
|
||||
easy_install will automatically get the additional libraries that these packages need to work properly.
|
||||
Run the following command to quickly install and upgrade all packages and their dependencies:
|
||||
easy_install -Z --upgrade six configobj goslate markdown future pocket suds requests oauthlib requests-oauthlib pypubsub pygeocoder arrow python-dateutil futures
|
||||
|
||||
#### Other dependencies
|
||||
|
||||
@@ -95,9 +98,16 @@ Now that you have installed all these packages, you can run TW Blue from source
|
||||
|
||||
If necessary, change the first part of the command to reflect the location of your python executable. You can run TW Blue using python x86 and x64
|
||||
|
||||
### Generating the documentation
|
||||
|
||||
To generate the documentation in html format, navigate to the doc folder inside this repo. After that, run this command:
|
||||
python generator.py
|
||||
The documentation will be generated, placing each language in a separate folder in the doc directory. Move these folders (for example de, en, es, fr, it, ...) to src/documentation, creating the directory if necesary.
|
||||
Also, copy the license.txt located in the root of the repo to the documentation folder.
|
||||
|
||||
### Building a binary version
|
||||
|
||||
A binary version doesn't need python and the other dependencies to run, it's the same version that you will find on the TW Blue website if you download the zip files.
|
||||
A binary version doesn't need python and the other dependencies to run, it's the same version that you will find on the TW Blue website if you download the zip files or the snapshot versions.
|
||||
|
||||
To build it, run the following command from the src folder:
|
||||
|
||||
@@ -105,6 +115,17 @@ To build it, run the following command from the src folder:
|
||||
|
||||
You will find the binaries in the dist directory.
|
||||
|
||||
### Building an installer
|
||||
|
||||
If you want to install TWBlue in your computer, you must create the installer first. Follow these steps:
|
||||
|
||||
* Navigate to the src directory, and create a binary version for x86: C:\python27\python setup.py py2exe
|
||||
* Move the dist directory to the scripts folder in this repo, and rename it to twblue
|
||||
* Repeat these steps with Python for x64: C:\python27x64\python setup.py py2exe
|
||||
* Move the new dist directory to the scripts folder, and rename it to twblue64
|
||||
* Go to the scripts folder, right click on the twblue.nsi file, and choose compyle unicode NSIS script
|
||||
* This may take a while. After the process, you will find the installer in the scripts folder
|
||||
|
||||
### How to generate a translation template
|
||||
|
||||
Run the gen_pot.bat file, located in the tools directory. Your python installation must be in your path environment variable. The pot file will appear in the tools directory.
|
||||
|
@@ -405,19 +405,21 @@ documentation.append(_(u"""We would also like to thank the translators of TWBlue
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""* English: [Bryner Villalobos](https://twitter.com/Bry_StarkCR) and [Bill Dengler](https://twitter.com/codeofdusk)."""))
|
||||
documentation.append(_(u"""* Arabic: Mohammed Al Shara."""))
|
||||
documentation.append(_(u"""* Arabic: [Mohammed Al Shara](https://twitter.com/mohammed0204)."""))
|
||||
documentation.append(_(u"""* Catalan: [Joan Rabat](https://twitter.com/joanrabat) and Juan Carlos Rivilla."""))
|
||||
documentation.append(_(u"""* Spanish: [Manuel Cortéz](https://twitter.com/manuelcortez00)."""))
|
||||
documentation.append(_(u"""* Basque: [Sukil Etxenike](https://twitter.com/sukil2011)."""))
|
||||
documentation.append(_(u"""* Finnish: Jani Kinnunen."""))
|
||||
documentation.append(_(u"""* French: Rémi Ruiz."""))
|
||||
documentation.append(_(u"""* Finnish: [Jani Kinnunen](https://twitter.com/jani_kinnunen)."""))
|
||||
documentation.append(_(u"""* French: [Rémi Ruiz](https://twitter.com/blindhelp38)."""))
|
||||
documentation.append(_(u"""* Galician: [Alba Kinteiro](https://twitter.com/albasmileforeve)."""))
|
||||
documentation.append(_(u"""* German: Steffen Schultz."""))
|
||||
documentation.append(_(u"""* German: [Steffen Schultz](https://twitter.com/schulle4u)."""))
|
||||
documentation.append(_(u"""* Croatian: [Zvonimir Stanečić](https://twitter.com/zvonimirek222)."""))
|
||||
documentation.append(_(u"""* Hungarian: Robert Osztolykan."""))
|
||||
documentation.append(_(u"""* Italian: [Christian Leo Mameli](https://twitter.com/llajta2012)."""))
|
||||
documentation.append(_(u"""* Polish: Pawel Masarczyk."""))
|
||||
documentation.append(_(u"""* Portuguese: Odenilton Júnior Santos."""))
|
||||
documentation.append(_(u"""* Russian: Alexander Jaszyn."""))
|
||||
documentation.append(_(u"""* Turkish: Burak."""))
|
||||
documentation.append(_(u"""* Russian: [Александр Яшин](https://twitter.com/radovest)."""))
|
||||
documentation.append(_(u"""* Turkish: [Burak Yüksek](https://twitter.com/burakyuksek)."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""Many thanks also to the people who worked on the documentation. Initially, [Manuel Cortez](https://twitter.com/manuelcortez00) did the documentation in Spanish, and translated to English by [Bryner Villalobos](https://twitter.com/Bry_StarkCR), [Robert Spangler](https://twitter.com/glasscity1837), [Sussan Rey](https://twitter.com/sussanrey17), [Anibal Hernandez](https://twitter.com/anibalmetal), and [Holly Scott-Gardner](https://twitter.com/holly1994). It was updated by [Sukil Etxenike](https://twitter.com/sukil2011), with some valuable corrections by [Brian Hartgen](https://twitter.com/brianhartgen) and [Bill Dengler](https://twitter.com/codeofdusk)."""))
|
||||
|
@@ -45,6 +45,9 @@ var StartMenuFolder
|
||||
!insertmacro MUI_LANGUAGE "Galician"
|
||||
!insertmacro MUI_LANGUAGE "Catalan"
|
||||
!insertmacro MUI_LANGUAGE "Basque"
|
||||
!insertmacro MUI_LANGUAGE "Croatian"
|
||||
!insertmacro MUI_LANGUAGE "Japanese"
|
||||
!insertmacro MUI_LANGUAGE "SerbianLatin"
|
||||
!insertmacro MUI_RESERVEFILE_LANGDLL
|
||||
Section
|
||||
SetShellVarContext All
|
||||
|
@@ -1,19 +1,23 @@
|
||||
from __future__ import absolute_import
|
||||
import ctypes
|
||||
import os
|
||||
import types
|
||||
from platform_utils import paths
|
||||
|
||||
def load_library(libname):
|
||||
def load_library(libname, cdll=False):
|
||||
if paths.is_frozen():
|
||||
libfile = os.path.join(paths.embedded_data_path(), 'accessible_output2', 'lib', libname)
|
||||
else:
|
||||
libfile = os.path.join(paths.module_path(), 'lib', libname)
|
||||
return ctypes.windll[libfile]
|
||||
if cdll:
|
||||
return ctypes.cdll[libfile]
|
||||
else:
|
||||
return ctypes.windll[libfile]
|
||||
|
||||
def get_output_classes():
|
||||
import outputs
|
||||
from . import outputs
|
||||
module_type = types.ModuleType
|
||||
classes = [m.output_class for m in outputs.__dict__.itervalues() if type(m) == module_type and hasattr(m, 'output_class')]
|
||||
classes = [m.output_class for m in outputs.__dict__.values() if type(m) == module_type and hasattr(m, 'output_class')]
|
||||
return sorted(classes, key=lambda c: c.priority)
|
||||
|
||||
def find_datafiles():
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,16 +1,20 @@
|
||||
from __future__ import absolute_import
|
||||
import platform
|
||||
if platform.system() == 'Windows':
|
||||
import nvda
|
||||
import jaws
|
||||
import sapi5
|
||||
import window_eyes
|
||||
import system_access
|
||||
import dolphin
|
||||
import pc_talker
|
||||
from . import nvda
|
||||
from . import jaws
|
||||
from . import sapi5
|
||||
from . import window_eyes
|
||||
from . import system_access
|
||||
from . import dolphin
|
||||
from . import pc_talker
|
||||
#import sapi4
|
||||
elif platform.system() == "Darwin":
|
||||
import voiceover
|
||||
elif platform.system() == "Linux":
|
||||
import speechDispatcher
|
||||
|
||||
import auto
|
||||
if platform.system() == 'Darwin':
|
||||
from . import voiceover
|
||||
from . import say
|
||||
|
||||
if platform.system() == 'Linux':
|
||||
from . import e_speak
|
||||
|
||||
from . import auto
|
||||
|
@@ -1,24 +1,17 @@
|
||||
import platform
|
||||
from __future__ import absolute_import
|
||||
import accessible_output2
|
||||
from base import Output, OutputError
|
||||
from .base import Output, OutputError
|
||||
|
||||
class Auto(Output):
|
||||
|
||||
def __init__(self):
|
||||
if platform.system() == "Darwin":
|
||||
import voiceover
|
||||
self.outputs = [voiceover.VoiceOver()]
|
||||
elif platform.system() == "Linux":
|
||||
import speechDispatcher
|
||||
self.outputs = [speechDispatcher.SpeechDispatcher()]
|
||||
elif platform.system() == "Windows":
|
||||
output_classes = accessible_output2.get_output_classes()
|
||||
self.outputs = []
|
||||
for output in output_classes:
|
||||
try:
|
||||
self.outputs.append(output())
|
||||
except OutputError:
|
||||
pass
|
||||
output_classes = accessible_output2.get_output_classes()
|
||||
self.outputs = []
|
||||
for output in output_classes:
|
||||
try:
|
||||
self.outputs.append(output())
|
||||
except OutputError:
|
||||
pass
|
||||
|
||||
def get_first_available_output(self):
|
||||
for output in self.outputs:
|
||||
@@ -40,3 +33,8 @@ class Auto(Output):
|
||||
output = self.get_first_available_output()
|
||||
if output:
|
||||
output.speak(*args, **kwargs)
|
||||
|
||||
def is_system_output(self):
|
||||
output = self.get_first_available_output()
|
||||
if output:
|
||||
return output.is_system_output()
|
||||
|
@@ -5,27 +5,43 @@ class OutputError(Exception):
|
||||
pass
|
||||
|
||||
class Output(object):
|
||||
name = "Unnamed Output" #The name of this output
|
||||
lib32 = None #name of 32-bit lib
|
||||
lib64 = None #name of 64-bit lib
|
||||
priority = 100 #Where to sort in the list of available outputs for automaticly speaking
|
||||
name = "Unnamed Output"
|
||||
lib32 = None
|
||||
lib64 = None
|
||||
argtypes = {}
|
||||
cdll = False
|
||||
priority = 100
|
||||
system_output = False
|
||||
|
||||
def __init__(self):
|
||||
is_32bit = platform.architecture()[0] == "32bit"
|
||||
if self.lib32 and is_32bit:
|
||||
self.lib = load_library(self.lib32)
|
||||
self.is_32bit = platform.architecture()[0] == "32bit"
|
||||
if self.lib32 and self.is_32bit:
|
||||
self.lib = load_library(self.lib32, cdll=self.cdll)
|
||||
elif self.lib64:
|
||||
self.lib = load_library(self.lib64)
|
||||
self.lib = load_library(self.lib64, cdll=self.cdll)
|
||||
else:
|
||||
self.lib = None
|
||||
if self.lib is not None:
|
||||
for func in self.argtypes:
|
||||
try:
|
||||
getattr(self.lib, func).argtypes = self.argtypes[func]
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def output(self, text, **options):
|
||||
output = False
|
||||
if hasattr(self, 'speak') and callable(self.speak):
|
||||
self.speak(text, **options)
|
||||
if self.speak(text, **options):
|
||||
output = True
|
||||
if hasattr(self, 'braille') and callable(self.braille):
|
||||
self.braille(text, **options)
|
||||
if self.braille(text, **options):
|
||||
output = True
|
||||
if not output:
|
||||
raise RuntimeError("Output %r does not have any method defined to output" % self)
|
||||
|
||||
def is_system_output(self):
|
||||
return self.system_output
|
||||
|
||||
def speak(self, **optiont):
|
||||
return False
|
||||
|
||||
def braille(self, **options):
|
||||
return False
|
||||
|
@@ -1,19 +1,25 @@
|
||||
from __future__ import absolute_import
|
||||
import os
|
||||
import ctypes
|
||||
|
||||
from base import Output
|
||||
from .base import Output
|
||||
|
||||
class Dolphin (Output):
|
||||
"""Supports dolphin products."""
|
||||
|
||||
name = 'Dolphin'
|
||||
lib32 = 'dolapi.dll'
|
||||
argtypes = {
|
||||
'DolAccess_Command': (ctypes.c_wchar_p, ctypes.c_int, ctypes.c_int),
|
||||
'DolAccess_Action': (ctypes.c_int,),
|
||||
}
|
||||
|
||||
def speak(self, text, interrupt=0):
|
||||
if interrupt:
|
||||
self.silence()
|
||||
#If we don't call this, the API won't let us speak.
|
||||
if self.is_active():
|
||||
self.lib.DolAccess_Command(unicode(text), (len(text)*2)+2, 1)
|
||||
self.lib.DolAccess_Command(text, (len(text)*2)+2, 1)
|
||||
|
||||
def silence(self):
|
||||
self.lib.DolAccess_Action(141)
|
||||
|
31
src/accessible_output2/outputs/e_speak.py
Normal file
31
src/accessible_output2/outputs/e_speak.py
Normal file
@@ -0,0 +1,31 @@
|
||||
from __future__ import absolute_import
|
||||
from .base import Output
|
||||
|
||||
try:
|
||||
import espeak.core
|
||||
except:
|
||||
raise RuntimeError("Cannot find espeak.core. Please install python-espeak")
|
||||
|
||||
class ESpeak(Output):
|
||||
"""Speech output supporting ESpeak on Linux
|
||||
Note this requires python-espeak to be installed
|
||||
This can be done on Debian distros by using apt-get install python-espeak
|
||||
Or through this tarball: https://launchpad.net/python-espeak
|
||||
"""
|
||||
name = "Linux ESpeak"
|
||||
|
||||
def is_active(self):
|
||||
try:
|
||||
import espeak.core
|
||||
except:
|
||||
return False
|
||||
return True
|
||||
|
||||
def speak(self, text, interrupt = 0):
|
||||
if interrupt:
|
||||
self.silence()
|
||||
espeak.core.synth(text)
|
||||
def silence(self):
|
||||
espeak.core.cancel()
|
||||
|
||||
output_class = ESpeak
|
@@ -1,8 +1,9 @@
|
||||
from __future__ import absolute_import
|
||||
import win32gui
|
||||
from libloader.com import load_com
|
||||
import pywintypes
|
||||
|
||||
from base import Output, OutputError
|
||||
from .base import Output, OutputError
|
||||
|
||||
class Jaws (Output):
|
||||
"""Output supporting the Jaws for Windows screen reader."""
|
||||
|
@@ -1,15 +1,21 @@
|
||||
from __future__ import absolute_import
|
||||
import os
|
||||
import platform
|
||||
import ctypes
|
||||
|
||||
from platform_utils import paths
|
||||
from libloader import load_library
|
||||
from base import Output
|
||||
from .base import Output
|
||||
|
||||
class NVDA(Output):
|
||||
"""Supports The NVDA screen reader"""
|
||||
name = "NVDA"
|
||||
lib32 = 'nvdaControllerClient32.dll'
|
||||
lib64 = 'nvdaControllerClient64.dll'
|
||||
argtypes = {
|
||||
'nvdaController_brailleMessage': (ctypes.c_wchar_p,),
|
||||
'nvdaController_speakText': (ctypes.c_wchar_p,),
|
||||
}
|
||||
|
||||
def is_active(self):
|
||||
try:
|
||||
@@ -18,12 +24,12 @@ class NVDA(Output):
|
||||
return False
|
||||
|
||||
def braille(self, text, **options):
|
||||
self.lib.nvdaController_brailleMessage(unicode(text))
|
||||
self.lib.nvdaController_brailleMessage(text)
|
||||
|
||||
def speak(self, text, interrupt=False):
|
||||
if interrupt:
|
||||
self.silence()
|
||||
self.lib.nvdaController_speakText(unicode(text))
|
||||
self.lib.nvdaController_speakText(text)
|
||||
|
||||
def silence(self):
|
||||
self.lib.nvdaController_cancelSpeech()
|
||||
|
@@ -1,14 +1,19 @@
|
||||
from __future__ import absolute_import
|
||||
import ctypes
|
||||
from base import Output
|
||||
from .base import Output
|
||||
|
||||
class PCTalker(Output):
|
||||
lib32 = 'pctkusr.dll'
|
||||
lib64 = 'pctkusr64.dll'
|
||||
cdll = True
|
||||
argtypes = {
|
||||
'PCTKPRead': (ctypes.c_char_p, ctypes.c_int, ctypes.c_int)
|
||||
}
|
||||
|
||||
def speak(self, text, interrupt=False):
|
||||
if interrupt:
|
||||
self.silence()
|
||||
self.lib.PCTKPRead(text.encode('cp932', 'replace'))
|
||||
self.lib.PCTKPRead(text.encode('cp932', 'replace'), 0, 1)
|
||||
|
||||
def silence(self):
|
||||
self.lib.PCTKVReset()
|
||||
|
@@ -1,5 +1,7 @@
|
||||
from __future__ import absolute_import
|
||||
from builtins import range
|
||||
from libloader.com import load_com
|
||||
from base import Output
|
||||
from .base import Output
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
@@ -1,12 +1,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import config
|
||||
from __future__ import absolute_import
|
||||
from collections import OrderedDict
|
||||
from libloader.com import load_com
|
||||
from base import Output, OutputError
|
||||
from .base import Output, OutputError
|
||||
import pywintypes
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
SVSFDefault = 0
|
||||
SVSFlagsAsync = 1
|
||||
SVSFPurgeBeforeSpeak = 2
|
||||
SVSFIsFilename = 4
|
||||
SVSFIsXML = 8
|
||||
SVSFIsNotXML = 16
|
||||
SVSFPersistXML = 32
|
||||
|
||||
class SAPI5(Output):
|
||||
has_volume = True
|
||||
has_rate = True
|
||||
@@ -19,9 +26,9 @@ class SAPI5(Output):
|
||||
max_volume = 100
|
||||
name = "sapi5"
|
||||
priority = 101
|
||||
system_output = True
|
||||
|
||||
def __init__(self):
|
||||
if config.app["app-settings"]["voice_enabled"] == False: raise OutputError
|
||||
try:
|
||||
self.object = load_com("SAPI.SPVoice")
|
||||
self._voices = self._available_voices()
|
||||
@@ -36,14 +43,14 @@ class SAPI5(Output):
|
||||
return _voices
|
||||
|
||||
def list_voices(self):
|
||||
return self.available_voices.keys()
|
||||
return list(self._voices.keys())
|
||||
|
||||
def get_voice(self):
|
||||
return self.object.Voice.GetDescription()
|
||||
|
||||
def set_voice(self, value):
|
||||
log.debug("Setting SAPI5 voice to \"%s\"" % value)
|
||||
self.object.Voice = self.available_voices[value]
|
||||
self.object.Voice = self._voices[value]
|
||||
# For some reason SAPI5 does not reset audio after changing the voice
|
||||
# By setting the audio device after changing voices seems to fix this
|
||||
# This was noted from information at:
|
||||
@@ -75,10 +82,10 @@ class SAPI5(Output):
|
||||
self.silence()
|
||||
# We need to do the pitch in XML here
|
||||
textOutput = "<pitch absmiddle=\"%d\">%s</pitch>" % (round(self._pitch), text.replace("<", "<"))
|
||||
self.object.Speak(textOutput, 1|8)
|
||||
self.object.Speak(textOutput, SVSFlagsAsync | SVSFIsXML)
|
||||
|
||||
def silence(self):
|
||||
self.object.Speak("", 3)
|
||||
self.object.Speak("", SVSFlagsAsync | SVSFPurgeBeforeSpeak)
|
||||
|
||||
def is_active(self):
|
||||
if self.object:
|
||||
|
21
src/accessible_output2/outputs/say.py
Normal file
21
src/accessible_output2/outputs/say.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from __future__ import absolute_import
|
||||
import os
|
||||
from .base import Output
|
||||
|
||||
class AppleSay(Output):
|
||||
"""Speech output supporting the Apple Say subsystem."""
|
||||
name = 'Apple Say'
|
||||
def __init__(self, voice = 'Alex', rate = '300'):
|
||||
self.voice = voice
|
||||
self.rate = rate
|
||||
super(AppleSay, self).__init__()
|
||||
def is_active(self):
|
||||
return not os.system('which say')
|
||||
def speak(self, text, interrupt = 0):
|
||||
if interrupt:
|
||||
self.silence()
|
||||
os.system('say -v %s -r %s "%s" &' % (self.voice, self.rate, text))
|
||||
def silence(self):
|
||||
os.system('killall say')
|
||||
|
||||
output_class = AppleSay
|
@@ -1,29 +0,0 @@
|
||||
from base import Output, OutputError
|
||||
import atexit
|
||||
import application
|
||||
class SpeechDispatcher(Output):
|
||||
"""Supports speech dispatcher on Linux.
|
||||
Note that this module will use the configuration of speech dispatcher, the user will need to configure the voice, language, punctuation and rate before using this module.
|
||||
"""
|
||||
name = 'SpeechDispatcher'
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(SpeechDispatcher, self).__init__(*args, **kwargs)
|
||||
try:
|
||||
import speechd
|
||||
self.spd = speechd.SSIPClient(application.name)
|
||||
except ImportError:
|
||||
raise OutputError
|
||||
atexit.register(self.on_exit_event)
|
||||
|
||||
def speak(self, text, interupt=False):
|
||||
if interupt == True:
|
||||
self.spd.cancel()
|
||||
self.spd.speak(text)
|
||||
|
||||
def is_active(self):
|
||||
return True
|
||||
|
||||
def on_exit_event(self):
|
||||
self.spd.close()
|
||||
del self.spd
|
@@ -1,18 +0,0 @@
|
||||
# Copyright (C) 2001, 2002 Brailcom, o.p.s.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
from .client import *
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
SPD_SPAWN_CMD = "/usr/bin/speech-dispatcher"
|
@@ -1,18 +1,24 @@
|
||||
from base import Output
|
||||
from __future__ import absolute_import
|
||||
import ctypes
|
||||
from .base import Output
|
||||
|
||||
class SystemAccess (Output):
|
||||
"""Supports System Access and System Access Mobile"""
|
||||
|
||||
name = "System Access"
|
||||
lib32 = 'saapi32.dll'
|
||||
argtypes = {
|
||||
'SA_BrlShowTextW': (ctypes.c_wchar_p,),
|
||||
'SA_SayW': (ctypes.c_wchar_p,),
|
||||
}
|
||||
priority = 99
|
||||
|
||||
def braille(self, text, **options):
|
||||
self.lib.SA_BrlShowTextW(unicode(text))
|
||||
self.lib.SA_BrlShowTextW(text)
|
||||
|
||||
def speak(self, text, interrupt=False):
|
||||
if self.is_active():
|
||||
self.dll.SA_SayW(unicode(text))
|
||||
self.dll.SA_SayW(str(text))
|
||||
|
||||
def is_active(self):
|
||||
try:
|
||||
|
@@ -1,23 +1 @@
|
||||
from base import Output, OutputError
|
||||
|
||||
class VoiceOver (Output):
|
||||
"""Supports the VoiceOver screenreader on the Mac.
|
||||
|
||||
Note that this will also output as a message to the braille display if VoiceOver is used with braille.
|
||||
Calling this module could cause VoiceOver to be started.
|
||||
"""
|
||||
name = 'VoiceOver'
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(VoiceOver, self).__init__(*args, **kwargs)
|
||||
try:
|
||||
from appscript import app
|
||||
self.app = app('VoiceOver')
|
||||
except ImportError:
|
||||
raise OutputError
|
||||
|
||||
def speak(self, text, interupt=False):
|
||||
self.app.output(text)
|
||||
|
||||
def is_active(self):
|
||||
return True
|
||||
from __future__ import absolute_import
|
@@ -1,6 +1,7 @@
|
||||
from __future__ import absolute_import
|
||||
import win32gui
|
||||
from libloader.com import load_com
|
||||
from base import Output, OutputError
|
||||
from .base import Output, OutputError
|
||||
import pywintypes
|
||||
|
||||
class WindowEyes (Output):
|
||||
|
@@ -8,7 +8,7 @@ language = string(default="system")
|
||||
hide_gui = boolean(default=False)
|
||||
voice_enabled = boolean(default=False)
|
||||
ask_at_exit = boolean(default=True)
|
||||
handle_longtweets = boolean(default=False)
|
||||
handle_longtweets = boolean(default=True)
|
||||
use_invisible_keyboard_shorcuts = boolean(default=True)
|
||||
play_ready_sound = boolean(default=True)
|
||||
speak_ready_msg = boolean(default=True)
|
||||
|
@@ -5,12 +5,12 @@ if snapshot == False:
|
||||
version = "0.80"
|
||||
update_url = 'http://twblue.es/updates/twblue_ngen.json'
|
||||
else:
|
||||
version = "10.2"
|
||||
version = "10.95"
|
||||
update_url = 'http://twblue.es/updates/snapshots_ngen.json'
|
||||
author = u"Manuel Cortéz, Bill Dengler"
|
||||
author = u"Manuel Cortéz"
|
||||
authorEmail = "manuel@manuelcortez.net"
|
||||
copyright = u"Copyright (C) 2015, Technow S.L. \nCopyright (C) 2015, Bill Dengler\nCopyright (C) 2013-2015, Manuel cortéz."
|
||||
copyright = u"Copyright (C) 2015, Technow S.L. \nCopyright (C) 2013-2015, Manuel cortéz."
|
||||
description = unicode(name+" is an app designed to use Twitter simply and efficiently while using minimal system resources. This app provides access to most Twitter features.")
|
||||
translators = [u"Bryner Villalobos, Bill Dengler (English)", u"Mohammed Al Shara (Arabic)", u"Joan Rabat, Juan Carlos Rivilla (Catalan)", u"Manuel cortéz (Spanish)", u"Sukil Etxenike Arizaleta (Basque)", u"Jani Kinnunen (finnish)", u"Rémy Ruiz (French)", u"Alba Quinteiro (Galician)", u"Steffen Schultz (German)", u"Robert Osztolykan (Hungarian)", u"Paweł Masarczyk (Polish)", u"Odenilton Júnior Santos (Portuguese)", u"Alexander Jaszyn (Russian)", u"Burak (Turkish)"]
|
||||
translators = [u"Bryner Villalobos, Bill Dengler (English)", u"Mohammed Al Shara (Arabic)", u"Joan Rabat, Juan Carlos Rivilla (Catalan)", u"Manuel cortéz (Spanish)", u"Sukil Etxenike Arizaleta (Basque)", u"Jani Kinnunen (finnish)", u"Rémy Ruiz (French)", u"Juan Buño (Galician)", u"Steffen Schultz (German)", u"Robert Osztolykan (Hungarian)", u"Paweł Masarczyk (Polish)", u"Odenilton Júnior Santos (Portuguese)", u"Alexander Jaszyn (Russian)", u"Burak (Turkish)"]
|
||||
url = u"http://twblue.es"
|
||||
report_bugs_url = "http://twblue.es/bugs/api/soap/mantisconnect.php?wsdl"
|
@@ -1,8 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import time
|
||||
import platform
|
||||
if platform.system() == "Windows":
|
||||
import wx
|
||||
from wxUI import buffers, dialogs, commonMessageDialogs
|
||||
from wxUI import buffers, dialogs, commonMessageDialogs, menus
|
||||
import user
|
||||
elif platform.system() == "Linux":
|
||||
from gi.repository import Gtk
|
||||
@@ -42,6 +43,7 @@ class bufferController(object):
|
||||
self.account = ""
|
||||
self.needs_init = True
|
||||
self.invisible = False # False if the buffer will be ignored on the invisible interface.
|
||||
self.execution_time = 0
|
||||
|
||||
def clear_list(self): pass
|
||||
|
||||
@@ -142,6 +144,13 @@ class bufferController(object):
|
||||
call_threaded(self.session.api_call, call_name="update_status_with_media", status=text, media=tweet.image)
|
||||
if hasattr(tweet.message, "destroy"): tweet.message.destroy()
|
||||
|
||||
def save_positions(self):
|
||||
try:
|
||||
self.session.db[self.name+"_pos"]=self.buffer.list.get_selected()
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
|
||||
class accountPanel(bufferController):
|
||||
def __init__(self, parent, name, account, account_id):
|
||||
super(accountPanel, self).__init__(parent, None, name)
|
||||
@@ -224,7 +233,8 @@ class baseBufferController(bufferController):
|
||||
return self.get_message()
|
||||
|
||||
def get_message(self):
|
||||
return " ".join(self.compose_function(self.get_right_tweet(), self.session.db, self.session.settings["general"]["relative_times"]))
|
||||
tweet = self.get_right_tweet()
|
||||
return " ".join(self.compose_function(tweet, self.session.db, self.session.settings["general"]["relative_times"]))
|
||||
|
||||
def get_full_tweet(self):
|
||||
tweet = self.get_right_tweet()
|
||||
@@ -235,6 +245,10 @@ class baseBufferController(bufferController):
|
||||
uri = tweet["long_uri"]
|
||||
try:
|
||||
tweet = self.session.twitter.twitter.show_status(id=tweet_id)
|
||||
urls = utils.find_urls_in_text(tweet["text"])
|
||||
for url in range(0, len(urls)):
|
||||
try: tweet["text"] = tweet["text"].replace(urls[url], tweet["entities"]["urls"][url]["expanded_url"])
|
||||
except IndexError: pass
|
||||
except TwythonError as e:
|
||||
utils.twitter_error(e)
|
||||
return
|
||||
@@ -246,6 +260,10 @@ class baseBufferController(bufferController):
|
||||
id = tweets.get_id(l)
|
||||
try:
|
||||
tweet = self.session.twitter.twitter.show_status(id=id)
|
||||
urls = utils.find_urls_in_text(tweet["text"])
|
||||
for url in range(0, len(urls)):
|
||||
try: tweet["text"] = tweet["text"].replace(urls[url], tweet["entities"]["urls"][url]["expanded_url"])
|
||||
except IndexError: pass
|
||||
except TwythonError as e:
|
||||
utils.twitter_error(e)
|
||||
return
|
||||
@@ -255,15 +273,19 @@ class baseBufferController(bufferController):
|
||||
return (tweet, tweetsList)
|
||||
|
||||
def start_stream(self):
|
||||
log.debug("Starting stream for buffer %s, account %s and type %s" % (self.name, self.account, self.type))
|
||||
log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs))
|
||||
val = self.session.call_paged(self.function, *self.args, **self.kwargs)
|
||||
number_of_items = self.session.order_buffer(self.name, val)
|
||||
log.debug("Number of items retrieved: %d" % (number_of_items,))
|
||||
self.put_items_on_list(number_of_items)
|
||||
if self.sound == None: return
|
||||
if number_of_items > 0 and self.name != "sent_tweets" and self.name != "sent_direct_messages":
|
||||
self.session.sound.play(self.sound)
|
||||
# starts stream every 3 minutes.
|
||||
current_time = time.time()
|
||||
if self.execution_time == 0 or current_time-self.execution_time >= 180:
|
||||
self.execution_time = current_time
|
||||
log.debug("Starting stream for buffer %s, account %s and type %s" % (self.name, self.account, self.type))
|
||||
log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs))
|
||||
val = self.session.call_paged(self.function, *self.args, **self.kwargs)
|
||||
number_of_items = self.session.order_buffer(self.name, val)
|
||||
log.debug("Number of items retrieved: %d" % (number_of_items,))
|
||||
self.put_items_on_list(number_of_items)
|
||||
if self.sound == None: return
|
||||
if number_of_items > 0 and self.name != "sent_tweets" and self.name != "sent_direct_messages":
|
||||
self.session.sound.play(self.sound)
|
||||
|
||||
def get_more_items(self):
|
||||
elements = []
|
||||
@@ -345,8 +367,8 @@ class baseBufferController(bufferController):
|
||||
if self.name in self.session.settings["other_buffers"]["autoread_buffers"] and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and self.session.settings["sound"]["session_mute"] == False:
|
||||
output.speak(" ".join(tweet[:2]))
|
||||
#Improve performance on Windows
|
||||
if platform.system() == "Windows":
|
||||
call_threaded(utils.is_audio,item)
|
||||
# if platform.system() == "Windows":
|
||||
# call_threaded(utils.is_audio,item)
|
||||
|
||||
def bind_events(self):
|
||||
log.debug("Binding events...")
|
||||
@@ -357,6 +379,61 @@ class baseBufferController(bufferController):
|
||||
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.retweet, self.buffer.retweet)
|
||||
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.direct_message, self.buffer.dm)
|
||||
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.reply, self.buffer.reply)
|
||||
# Replace for the correct way in other platforms.
|
||||
widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_ITEM_RIGHT_CLICK, self.show_menu)
|
||||
widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_KEY_DOWN, self.show_menu_by_key)
|
||||
|
||||
def show_menu(self, ev, pos=0, *args, **kwargs):
|
||||
if self.buffer.list.get_count() == 0: return
|
||||
if self.name == "sent_tweets" or self.name == "sent_direct_messages":
|
||||
menu = menus.sentPanelMenu()
|
||||
elif self.name == "direct_messages":
|
||||
menu = menus.dmPanelMenu()
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.direct_message, menuitem=menu.reply)
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.user_actions, menuitem=menu.userActions)
|
||||
else:
|
||||
menu = menus.basePanelMenu()
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.reply, menuitem=menu.reply)
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.user_actions, menuitem=menu.userActions)
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.retweet, menuitem=menu.retweet)
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.fav, menuitem=menu.fav)
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.unfav, menuitem=menu.unfav)
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.url_, menuitem=menu.openUrl)
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.audio, menuitem=menu.play)
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.view, menuitem=menu.view)
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.copy, menuitem=menu.copy)
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.destroy_status, menuitem=menu.remove)
|
||||
if pos != 0:
|
||||
self.buffer.PopupMenu(menu, pos)
|
||||
else:
|
||||
self.buffer.PopupMenu(menu, ev.GetPosition())
|
||||
|
||||
def view(self, *args, **kwargs):
|
||||
pub.sendMessage("execute-action", action="view_item")
|
||||
|
||||
def copy(self, *args, **kwargs):
|
||||
pub.sendMessage("execute-action", action="copy_to_clipboard")
|
||||
|
||||
def user_actions(self, *args, **kwargs):
|
||||
pub.sendMessage("execute-action", action="follow")
|
||||
|
||||
def fav(self, *args, **kwargs):
|
||||
pub.sendMessage("execute-action", action="add_to_favourites")
|
||||
|
||||
def unfav(self, *args, **kwargs):
|
||||
pub.sendMessage("execute-action", action="remove_from_favourites")
|
||||
|
||||
def delete_item_(self, *args, **kwargs):
|
||||
pub.sendMessage("execute-action", action="delete_item")
|
||||
|
||||
def url_(self, *args, **kwargs):
|
||||
self.url()
|
||||
|
||||
def show_menu_by_key(self, ev):
|
||||
if self.buffer.list.get_count() == 0:
|
||||
return
|
||||
if ev.GetKeyCode() == wx.WXK_WINDOWS_MENU:
|
||||
self.show_menu(widgetUtils.MENU, pos=self.buffer.list.list.GetPosition())
|
||||
|
||||
def get_tweet(self):
|
||||
if self.session.db[self.name][self.buffer.list.get_selected()].has_key("retweeted_status"):
|
||||
@@ -423,7 +500,7 @@ class baseBufferController(bufferController):
|
||||
self._retweet_with_comment(tweet, id)
|
||||
|
||||
def _retweet_with_comment(self, tweet, id, comment=''):
|
||||
retweet = messages.tweet(self.session, _(u"Retweet"), _(u"Add your comment to the tweet"), u"“@%s: %s ”" % (tweet["user"]["screen_name"], tweet["text"]), max=116-len("@%s " % (tweet["user"]["screen_name"],)), messageType="retweet", twishort_enabled=self.session.settings["mysc"]["twishort_enabled"])
|
||||
retweet = messages.tweet(self.session, _(u"Retweet"), _(u"Add your comment to the tweet"), u"“@%s: %s ”" % (tweet["user"]["screen_name"], tweet["text"]), max=116, messageType="retweet", twishort_enabled=self.session.settings["mysc"]["twishort_enabled"])
|
||||
if comment != '':
|
||||
retweet.message.set_text(comment)
|
||||
if retweet.message.get_response() == widgetUtils.OK:
|
||||
@@ -457,11 +534,10 @@ class baseBufferController(bufferController):
|
||||
self.session.sound.play("audio.ogg")
|
||||
if utils.is_geocoded(tweet):
|
||||
self.session.sound.play("geo.ogg")
|
||||
self.session.db[self.name+"_pos"]=self.buffer.list.get_selected()
|
||||
|
||||
@_tweets_exist
|
||||
def audio(self,url=''):
|
||||
if hasattr(sound.URLPlayer,'stream'):
|
||||
# @_tweets_exist
|
||||
def audio(self, url='', *args, **kwargs):
|
||||
if hasattr(sound.URLPlayer,'stream') and sound.URLPlayer.stream.is_playing == True:
|
||||
return sound.URLPlayer.stop_audio(delete=True)
|
||||
tweet = self.get_tweet()
|
||||
if tweet == None: return
|
||||
@@ -480,8 +556,8 @@ class baseBufferController(bufferController):
|
||||
except:
|
||||
log.error("Exception while executing audio method.")
|
||||
|
||||
@_tweets_exist
|
||||
def url(self,url='',announce=True):
|
||||
# @_tweets_exist
|
||||
def url(self, url='', announce=True, *args, **kwargs):
|
||||
if url == '':
|
||||
tweet = self.get_tweet()
|
||||
urls = utils.find_urls(tweet)
|
||||
@@ -535,6 +611,26 @@ class baseBufferController(bufferController):
|
||||
user.profileController(session=self.session, user=dlg.get_user())
|
||||
if hasattr(dlg, "destroy"): dlg.destroy()
|
||||
|
||||
def get_quoted_tweet(self, tweet):
|
||||
# try:
|
||||
quoted_tweet = self.session.twitter.twitter.show_status(id=tweet["id"])
|
||||
urls = utils.find_urls_in_text(quoted_tweet["text"])
|
||||
for url in range(0, len(urls)):
|
||||
try: quoted_tweet["text"] = quoted_tweet["text"].replace(urls[url], quoted_tweet["entities"]["urls"][url]["expanded_url"])
|
||||
except IndexError: pass
|
||||
# except TwythonError as e:
|
||||
# utils.twitter_error(e)
|
||||
# return
|
||||
l = tweets.is_long(quoted_tweet)
|
||||
id = tweets.get_id(l)
|
||||
# try:
|
||||
original_tweet = self.session.twitter.twitter.show_status(id=id)
|
||||
urls = utils.find_urls_in_text(original_tweet["text"])
|
||||
for url in range(0, len(urls)):
|
||||
try: original_tweet["text"] = original_tweet["text"].replace(urls[url], original_tweet["entities"]["urls"][url]["expanded_url"])
|
||||
except IndexError: pass
|
||||
return compose.compose_quoted_tweet(quoted_tweet, original_tweet, self.session.db, self.session.settings["general"]["relative_times"])
|
||||
|
||||
class listBufferController(baseBufferController):
|
||||
def __init__(self, parent, function, name, sessionObject, account, sound=None, bufferType=None, list_id=None, *args, **kwargs):
|
||||
super(listBufferController, self).__init__(parent, function, name, sessionObject, account, sound=None, bufferType=None, *args, **kwargs)
|
||||
@@ -599,6 +695,23 @@ class eventsBufferController(bufferController):
|
||||
if dlg == widgetUtils.YES:
|
||||
self.buffer.list.clear()
|
||||
|
||||
def show_menu(self, ev, pos=0, *args, **kwargs):
|
||||
if self.buffer.list.get_count() == 0: return
|
||||
menu = menus.eventsPanelMenu()
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.view, menuitem=menu.view)
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.copy, menuitem=menu.copy)
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.destroy_status, menuitem=menu.remove)
|
||||
if pos != 0:
|
||||
self.buffer.PopupMenu(menu, pos)
|
||||
else:
|
||||
self.buffer.PopupMenu(menu, ev.GetPosition())
|
||||
|
||||
def view(self, *args, **kwargs):
|
||||
pub.sendMessage("execute-action", action="view_item")
|
||||
|
||||
def copy(self, *args, **kwargs):
|
||||
pub.sendMessage("execute-action", action="copy_to_clipboard")
|
||||
|
||||
class peopleBufferController(baseBufferController):
|
||||
def __init__(self, parent, function, name, sessionObject, account, bufferType=None, *args, **kwargs):
|
||||
super(peopleBufferController, self).__init__(parent, function, name, sessionObject, account, bufferType="peoplePanel")
|
||||
@@ -632,12 +745,14 @@ class peopleBufferController(baseBufferController):
|
||||
if hasattr(message.message, "destroy"): message.message.destroy()
|
||||
|
||||
def start_stream(self):
|
||||
log.debug("Starting stream for %s buffer, %s account" % (self.name, self.account,))
|
||||
log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs))
|
||||
val = self.session.get_cursored_stream(self.name, self.function, *self.args, **self.kwargs)
|
||||
# self.session.order_cursored_buffer(self.name, self.session.db[self.name])
|
||||
# log.debug("Number of items retrieved: %d" % (val,))
|
||||
self.put_items_on_list(val)
|
||||
# starts stream every 3 minutes.
|
||||
current_time = time.time()
|
||||
if self.execution_time == 0 or current_time-self.execution_time >= 180:
|
||||
self.execution_time = current_time
|
||||
log.debug("Starting stream for %s buffer, %s account" % (self.name, self.account,))
|
||||
log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs))
|
||||
val = self.session.get_cursored_stream(self.name, self.function, *self.args, **self.kwargs)
|
||||
self.put_items_on_list(val)
|
||||
|
||||
def get_more_items(self):
|
||||
try:
|
||||
@@ -709,19 +824,39 @@ class peopleBufferController(baseBufferController):
|
||||
def interact(self):
|
||||
user.profileController(self.session, user=self.get_right_tweet()["screen_name"])
|
||||
|
||||
def show_menu(self, ev, pos=0, *args, **kwargs):
|
||||
menu = menus.peoplePanelMenu()
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.direct_message, menuitem=menu.reply)
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.user_actions, menuitem=menu.userActions)
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.details, menuitem=menu.details)
|
||||
# widgetUtils.connect_event(menu, widgetUtils.MENU, self.lists, menuitem=menu.lists)
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.view, menuitem=menu.view)
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.copy, menuitem=menu.copy)
|
||||
if pos != 0:
|
||||
self.buffer.PopupMenu(menu, pos)
|
||||
else:
|
||||
self.buffer.PopupMenu(menu, ev.GetPosition())
|
||||
|
||||
def details(self, *args, **kwargs):
|
||||
pub.sendMessage("execute-action", action="user_details")
|
||||
|
||||
class searchBufferController(baseBufferController):
|
||||
def start_stream(self):
|
||||
log.debug("Starting stream for %s buffer, %s account and %s type" % (self.name, self.account, self.type))
|
||||
log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs))
|
||||
log.debug("Function: %s" % (self.function,))
|
||||
# starts stream every 3 minutes.
|
||||
current_time = time.time()
|
||||
if self.execution_time == 0 or current_time-self.execution_time >= 180:
|
||||
self.execution_time = current_time
|
||||
log.debug("Starting stream for %s buffer, %s account and %s type" % (self.name, self.account, self.type))
|
||||
log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs))
|
||||
log.debug("Function: %s" % (self.function,))
|
||||
# try:
|
||||
val = self.session.search(self.name, *self.args, **self.kwargs)
|
||||
val = self.session.search(self.name, *self.args, **self.kwargs)
|
||||
# except:
|
||||
# return None
|
||||
num = self.session.order_buffer(self.name, val)
|
||||
self.put_items_on_list(num)
|
||||
if num > 0:
|
||||
self.session.sound.play("search_updated.ogg")
|
||||
num = self.session.order_buffer(self.name, val)
|
||||
self.put_items_on_list(num)
|
||||
if num > 0:
|
||||
self.session.sound.play("search_updated.ogg")
|
||||
|
||||
def remove_buffer(self):
|
||||
dlg = commonMessageDialogs.remove_buffer()
|
||||
@@ -745,18 +880,22 @@ class searchPeopleBufferController(peopleBufferController):
|
||||
self.function = function
|
||||
|
||||
def start_stream(self):
|
||||
log.debug("starting stream for %s buffer, %s account and %s type" % (self.name, self.account, self.type))
|
||||
log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs))
|
||||
log.debug("Function: %s" % (self.function,))
|
||||
# starts stream every 3 minutes.
|
||||
current_time = time.time()
|
||||
if self.execution_time == 0 or current_time-self.execution_time >= 180:
|
||||
self.execution_time = current_time
|
||||
log.debug("starting stream for %s buffer, %s account and %s type" % (self.name, self.account, self.type))
|
||||
log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs))
|
||||
log.debug("Function: %s" % (self.function,))
|
||||
# try:
|
||||
val = self.session.call_paged(self.function, *self.args, **self.kwargs)
|
||||
val = self.session.call_paged(self.function, *self.args, **self.kwargs)
|
||||
# except:
|
||||
# return
|
||||
number_of_items = self.session.order_cursored_buffer(self.name, val)
|
||||
log.debug("Number of items retrieved: %d" % (number_of_items,))
|
||||
self.put_items_on_list(number_of_items)
|
||||
if number_of_items > 0:
|
||||
self.session.sound.play("search_updated.ogg")
|
||||
number_of_items = self.session.order_cursored_buffer(self.name, val)
|
||||
log.debug("Number of items retrieved: %d" % (number_of_items,))
|
||||
self.put_items_on_list(number_of_items)
|
||||
if number_of_items > 0:
|
||||
self.session.sound.play("search_updated.ogg")
|
||||
|
||||
def remove_buffer(self):
|
||||
dlg = commonMessageDialogs.remove_buffer()
|
||||
@@ -785,17 +924,22 @@ class trendsBufferController(bufferController):
|
||||
self.buffer.name = name
|
||||
self.compose_function = self.compose_function_
|
||||
self.get_formatted_message = self.get_message
|
||||
self.reply = self.search_topic
|
||||
|
||||
def start_stream(self):
|
||||
try:
|
||||
data = self.session.call_paged("get_place_trends", id=self.trendsFor)
|
||||
except:
|
||||
return
|
||||
if not hasattr(self, "name_"):
|
||||
self.name_ = data[0]["locations"][0]["name"]
|
||||
self.trends = data[0]["trends"]
|
||||
self.put_items_on_the_list()
|
||||
self.session.sound.play(self.sound)
|
||||
# starts stream every 3 minutes.
|
||||
current_time = time.time()
|
||||
if self.execution_time == 0 or current_time-self.execution_time >= 180:
|
||||
self.execution_time = current_time
|
||||
try:
|
||||
data = self.session.call_paged("get_place_trends", id=self.trendsFor)
|
||||
except:
|
||||
return
|
||||
if not hasattr(self, "name_"):
|
||||
self.name_ = data[0]["locations"][0]["name"]
|
||||
self.trends = data[0]["trends"]
|
||||
self.put_items_on_the_list()
|
||||
self.session.sound.play(self.sound)
|
||||
|
||||
def put_items_on_the_list(self):
|
||||
selected_item = self.buffer.list.get_selected()
|
||||
@@ -811,10 +955,11 @@ class trendsBufferController(bufferController):
|
||||
def bind_events(self):
|
||||
log.debug("Binding events...")
|
||||
self.buffer.list.list.Bind(wx.EVT_CHAR_HOOK, self.get_event)
|
||||
# widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.post_tweet, self.buffer.tweet)
|
||||
# widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.retweet, self.buffer.retweet)
|
||||
# widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.direct_message, self.buffer.dm)
|
||||
# widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.reply, self.buffer.reply)
|
||||
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.tweet_about_this_trend, self.buffer.tweetTrendBtn)
|
||||
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.post_tweet, self.buffer.tweet)
|
||||
widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_ITEM_RIGHT_CLICK, self.show_menu)
|
||||
widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_KEY_DOWN, self.show_menu_by_key)
|
||||
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.search_topic, self.buffer.search_topic)
|
||||
|
||||
def get_message(self):
|
||||
return self.compose_function(self.trends[self.buffer.list.get_selected()])[0]
|
||||
@@ -829,36 +974,92 @@ class trendsBufferController(bufferController):
|
||||
elif dlg == widgetUtils.NO:
|
||||
return False
|
||||
|
||||
def interact(self, *args, **kwargs):
|
||||
self.searchfunction(value=self.get_message())
|
||||
def search_topic(self, *args, **kwargs):
|
||||
topic = self.trends[self.buffer.list.get_selected()]["name"]
|
||||
pub.sendMessage("search", term=topic)
|
||||
|
||||
def show_menu(self, ev, pos=0, *args, **kwargs):
|
||||
menu = menus.trendsPanelMenu()
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.search_topic, menuitem=menu.search_topic)
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.tweet_about_this_trend, menuitem=menu.tweetThisTrend)
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.view, menuitem=menu.view)
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.copy, menuitem=menu.copy)
|
||||
if pos != 0:
|
||||
self.buffer.PopupMenu(menu, pos)
|
||||
else:
|
||||
self.buffer.PopupMenu(menu, ev.GetPosition())
|
||||
|
||||
def view(self, *args, **kwargs):
|
||||
pub.sendMessage("execute-action", action="view_item")
|
||||
|
||||
def copy(self, *args, **kwargs):
|
||||
pub.sendMessage("execute-action", action="copy_to_clipboard")
|
||||
|
||||
def tweet_about_this_trend(self, *args, **kwargs):
|
||||
if self.buffer.list.get_count() == 0: return
|
||||
title = _(u"Tweet")
|
||||
caption = _(u"Write the tweet here")
|
||||
tweet = messages.tweet(self.session, title, caption, self.get_message()+ " ", twishort_enabled=self.session.settings["mysc"]["twishort_enabled"])
|
||||
tweet.message.set_cursor_at_end()
|
||||
if tweet.message.get_response() == widgetUtils.OK:
|
||||
self.session.settings["mysc"]["twishort_enabled"] = tweet.message.long_tweet.GetValue()
|
||||
text = tweet.message.get_text()
|
||||
if len(text) > 140 and tweet.message.get("long_tweet") == True:
|
||||
if tweet.image == None:
|
||||
text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text)
|
||||
else:
|
||||
text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text, 1)
|
||||
if tweet.image == None:
|
||||
call_threaded(self.session.api_call, call_name="update_status", status=text)
|
||||
else:
|
||||
call_threaded(self.session.api_call, call_name="update_status_with_media", status=text, media=tweet.image)
|
||||
if hasattr(tweet.message, "destroy"): tweet.message.destroy()
|
||||
|
||||
def show_menu_by_key(self, ev):
|
||||
if self.buffer.list.get_count() == 0:
|
||||
return
|
||||
if ev.GetKeyCode() == wx.WXK_WINDOWS_MENU:
|
||||
self.show_menu(widgetUtils.MENU, pos=self.buffer.list.list.GetPosition())
|
||||
|
||||
class conversationBufferController(searchBufferController):
|
||||
|
||||
def start_stream(self, start=False):
|
||||
if start == True:
|
||||
self.statuses = []
|
||||
self.ids = []
|
||||
self.statuses.append(self.tweet)
|
||||
self.ids.append(self.tweet["id"])
|
||||
tweet = self.tweet
|
||||
while tweet["in_reply_to_status_id"] != None:
|
||||
tweet = self.session.twitter.twitter.show_status(id=tweet["in_reply_to_status_id"])
|
||||
self.statuses.insert(0, tweet)
|
||||
self.ids.append(tweet["id"])
|
||||
if tweet["in_reply_to_status_id"] == None:
|
||||
self.kwargs["since_id"] = tweet["id"]
|
||||
self.ids.append(tweet["id"])
|
||||
val2 = self.session.search(self.name, *self.args, **self.kwargs)
|
||||
for i in val2:
|
||||
if i["in_reply_to_status_id"] in self.ids:
|
||||
self.statuses.append(i)
|
||||
self.ids.append(i["id"])
|
||||
tweet = i
|
||||
number_of_items = self.session.order_buffer(self.name, self.statuses)
|
||||
log.debug("Number of items retrieved: %d" % (number_of_items,))
|
||||
self.put_items_on_list(number_of_items)
|
||||
if number_of_items > 0:
|
||||
self.session.sound.play("search_updated.ogg")
|
||||
# starts stream every 3 minutes.
|
||||
current_time = time.time()
|
||||
if self.execution_time == 0 or current_time-self.execution_time >= 180:
|
||||
self.execution_time = current_time
|
||||
if start == True:
|
||||
self.statuses = []
|
||||
self.ids = []
|
||||
self.statuses.append(self.tweet)
|
||||
self.ids.append(self.tweet["id"])
|
||||
tweet = self.tweet
|
||||
while tweet["in_reply_to_status_id"] != None:
|
||||
tweet = self.session.twitter.twitter.show_status(id=tweet["in_reply_to_status_id"])
|
||||
self.statuses.insert(0, tweet)
|
||||
self.ids.append(tweet["id"])
|
||||
if tweet["in_reply_to_status_id"] == None:
|
||||
self.kwargs["since_id"] = tweet["id"]
|
||||
self.ids.append(tweet["id"])
|
||||
val2 = self.session.search(self.name, *self.args, **self.kwargs)
|
||||
for i in val2:
|
||||
if i["in_reply_to_status_id"] in self.ids:
|
||||
self.statuses.append(i)
|
||||
self.ids.append(i["id"])
|
||||
tweet = i
|
||||
number_of_items = self.session.order_buffer(self.name, self.statuses)
|
||||
log.debug("Number of items retrieved: %d" % (number_of_items,))
|
||||
self.put_items_on_list(number_of_items)
|
||||
if number_of_items > 0:
|
||||
self.session.sound.play("search_updated.ogg")
|
||||
|
||||
def remove_buffer(self):
|
||||
dlg = commonMessageDialogs.remove_buffer()
|
||||
if dlg == widgetUtils.YES:
|
||||
self.timer.cancel()
|
||||
return True
|
||||
elif dlg == WidgetUtils.NO:
|
||||
return False
|
||||
|
||||
class pocketBufferController(baseBufferController):
|
||||
def __init__(self, parent, name, sessionObject, account, sound=None, function=None, bufferType=None, *args, **kwargs):
|
||||
|
@@ -15,12 +15,23 @@ class listsController(object):
|
||||
self.dialog.populate_list(self.get_all_lists())
|
||||
widgetUtils.connect_event(self.dialog.createBtn, widgetUtils.BUTTON_PRESSED, self.create_list)
|
||||
widgetUtils.connect_event(self.dialog.editBtn, widgetUtils.BUTTON_PRESSED, self.edit_list)
|
||||
widgetUtils.connect_event(self.dialog.deleteBtn, widgetUtils.BUTTON_PRESSED, self.remove_list)
|
||||
widgetUtils.connect_event(self.dialog.view, widgetUtils.BUTTON_PRESSED, self.open_list_as_buffer)
|
||||
widgetUtils.connect_event(self.dialog.deleteBtn, widgetUtils.BUTTON_PRESSED, self.remove_list)
|
||||
else:
|
||||
self.dialog = lists.userListViewer(user)
|
||||
self.dialog.populate_list(self.get_user_lists(user))
|
||||
widgetUtils.connect_event(self.dialog.createBtn, widgetUtils.BUTTON_PRESSED, self.subscribe)
|
||||
widgetUtils.connect_event(self.dialog.deleteBtn, widgetUtils.BUTTON_PRESSED, self.unsubscribe)
|
||||
self.dialog.get_response()
|
||||
|
||||
def get_all_lists(self):
|
||||
return [compose.compose_list(item) for item in self.session.db["lists"]]
|
||||
|
||||
def get_user_lists(self, user):
|
||||
self.lists = self.session.twitter.twitter.show_lists(reverse=True, screen_name=user)
|
||||
return [compose.compose_list(item) for item in self.lists]
|
||||
|
||||
def create_list(self, *args, **kwargs):
|
||||
dialog = lists.createListDialog()
|
||||
if dialog.get_response() == widgetUtils.OK:
|
||||
@@ -73,4 +84,23 @@ class listsController(object):
|
||||
def open_list_as_buffer(self, *args, **kwargs):
|
||||
if self.dialog.lista.get_count() == 0: return
|
||||
list = self.session.db["lists"][self.dialog.get_item()]
|
||||
pub.sendMessage("create-new-buffer", buffer="list", account=self.session.db["user_name"], create=list["name"])
|
||||
pub.sendMessage("create-new-buffer", buffer="list", account=self.session.db["user_name"], create=list["name"])
|
||||
|
||||
def subscribe(self, *args, **kwargs):
|
||||
if self.dialog.lista.get_count() == 0: return
|
||||
list_id = self.lists[self.dialog.get_item()]["id"]
|
||||
try:
|
||||
list = self.session.twitter.twitter.subscribe_to_list(list_id=list_id)
|
||||
item = utils.find_item(list["id"], self.session.db["lists"])
|
||||
self.session.db["lists"].append(list)
|
||||
except TwythonError as e:
|
||||
output.speak("error %s: %s" % (e.status_code, e.msg))
|
||||
|
||||
def unsubscribe(self, *args, **kwargs):
|
||||
if self.dialog.lista.get_count() == 0: return
|
||||
list_id = self.lists[self.dialog.get_item()]["id"]
|
||||
try:
|
||||
list = self.session.twitter.twitter.unsubscribe_from_list(list_id=list_id)
|
||||
self.session.db["lists"].remove(list)
|
||||
except TwythonError as e:
|
||||
output.speak("error %s: %s" % (e.status_code, e.msg))
|
||||
|
@@ -97,7 +97,7 @@ class Controller(object):
|
||||
def get_buffers_for_account(self, account):
|
||||
results = []
|
||||
buffers = self.view.get_buffers()
|
||||
[results.append(self.search_buffer(i.name, i.account)) for i in buffers if i.account == account]
|
||||
[results.append(self.search_buffer(i.name, i.account)) for i in buffers if i.account == account and (i.type != "account")]
|
||||
return results
|
||||
|
||||
def bind_stream_events(self):
|
||||
@@ -128,7 +128,8 @@ class Controller(object):
|
||||
pub.subscribe(self.manage_stream_errors, "stream-error")
|
||||
pub.subscribe(self.create_new_buffer, "create-new-buffer")
|
||||
pub.subscribe(self.restart_streams, "restart-streams")
|
||||
|
||||
pub.subscribe(self.execute_action, "execute-action")
|
||||
pub.subscribe(self.search_topic, "search")
|
||||
if system == "Windows":
|
||||
pub.subscribe(self.invisible_shorcuts_changed, "invisible-shorcuts-changed")
|
||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.show_hide, menuitem=self.view.show_hide)
|
||||
@@ -156,7 +157,9 @@ class Controller(object):
|
||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.delete, self.view.delete)
|
||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.follow, menuitem=self.view.follow)
|
||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.send_dm, self.view.dm)
|
||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.view_user_lists, menuitem=self.view.viewLists)
|
||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.get_more_items, menuitem=self.view.load_previous_items)
|
||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.view_user_lists, menuitem=self.view.viewLists)
|
||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.clear_buffer, menuitem=self.view.clear)
|
||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.remove_buffer, self.view.deleteTl)
|
||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.check_for_updates, self.view.check_for_updates)
|
||||
@@ -174,6 +177,8 @@ class Controller(object):
|
||||
widgetUtils.connect_event(self.view.nb, widgetUtils.NOTEBOOK_PAGE_CHANGED, self.buffer_changed)
|
||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.report_error, self.view.reportError)
|
||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.view_documentation, self.view.doc)
|
||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.add_to_list, self.view.addToList)
|
||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.remove_from_list, self.view.removeFromList)
|
||||
|
||||
def set_systray_icon(self):
|
||||
self.systrayIcon = sysTrayIcon.SysTrayIcon()
|
||||
@@ -235,7 +240,6 @@ class Controller(object):
|
||||
self.create_ignored_session_buffer(session_.sessions[i])
|
||||
continue
|
||||
self.create_buffers(session_.sessions[i])
|
||||
self.set_buffer_positions(session_.sessions[i])
|
||||
|
||||
# Connection checker executed each minute.
|
||||
self.checker_function = RepeatingTimer(60, self.check_connection)
|
||||
@@ -246,6 +250,7 @@ class Controller(object):
|
||||
for i in session_.sessions:
|
||||
if session_.sessions[i].is_logged == False: continue
|
||||
self.start_buffers(session_.sessions[i])
|
||||
self.set_buffer_positions(session_.sessions[i])
|
||||
if config.app["app-settings"]["play_ready_sound"] == True:
|
||||
session_.sessions[session_.sessions.keys()[0]].sound.play("ready.ogg")
|
||||
if config.app["app-settings"]["speak_ready_msg"] == True:
|
||||
@@ -263,6 +268,7 @@ class Controller(object):
|
||||
for i in session_.sessions:
|
||||
if session_.sessions[i].session_id == session_id: session = session_.sessions[i]
|
||||
session.login()
|
||||
session.db = dict()
|
||||
self.create_buffers(session, False)
|
||||
self.start_buffers(session)
|
||||
|
||||
@@ -286,11 +292,11 @@ class Controller(object):
|
||||
self.buffers.append(mentions)
|
||||
self.view.insert_buffer(mentions.buffer, name=_(u"Mentions"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
|
||||
elif i == 'dm':
|
||||
dm = buffersController.baseBufferController(self.view.nb, "get_direct_messages", "direct_messages", session, session.db["user_name"], bufferType="dmPanel", sound="dm_received.ogg")
|
||||
dm = buffersController.baseBufferController(self.view.nb, "get_direct_messages", "direct_messages", session, session.db["user_name"], bufferType="dmPanel", sound="dm_received.ogg", full_text=True)
|
||||
self.buffers.append(dm)
|
||||
self.view.insert_buffer(dm.buffer, name=_(u"Direct messages"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
|
||||
elif i == 'sent_dm':
|
||||
sent_dm = buffersController.baseBufferController(self.view.nb, "get_sent_messages", "sent_direct_messages", session, session.db["user_name"], bufferType="dmPanel")
|
||||
sent_dm = buffersController.baseBufferController(self.view.nb, "get_sent_messages", "sent_direct_messages", session, session.db["user_name"], bufferType="dmPanel", full_text=True)
|
||||
self.buffers.append(sent_dm)
|
||||
self.view.insert_buffer(sent_dm.buffer, name=_(u"Sent direct messages"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
|
||||
elif i == 'sent_tweets':
|
||||
@@ -301,7 +307,7 @@ class Controller(object):
|
||||
favourites = buffersController.baseBufferController(self.view.nb, "get_favorites", "favourites", session, session.db["user_name"])
|
||||
self.buffers.append(favourites)
|
||||
|
||||
self.view.insert_buffer(favourites.buffer, name=_(u"Favourites"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
|
||||
self.view.insert_buffer(favourites.buffer, name=_(u"Likes"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
|
||||
elif i == 'followers':
|
||||
followers = buffersController.peopleBufferController(self.view.nb, "get_followers_list", "followers", session, session.db["user_name"], screen_name=session.db["user_name"])
|
||||
self.buffers.append(followers)
|
||||
@@ -331,11 +337,11 @@ class Controller(object):
|
||||
self.view.insert_buffer(tl.buffer, name=_(u"Timeline for {}").format(i,), pos=self.view.search("timelines", session.db["user_name"]))
|
||||
favs_timelines = buffersController.emptyPanel(self.view.nb, "favs_timelines", session.db["user_name"])
|
||||
self.buffers.append(favs_timelines)
|
||||
self.view.insert_buffer(favs_timelines.buffer , name=_(u"Favourites timelines"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
|
||||
self.view.insert_buffer(favs_timelines.buffer , name=_(u"Likes timelines"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
|
||||
for i in session.settings["other_buffers"]["favourites_timelines"]:
|
||||
tl = buffersController.baseBufferController(self.view.nb, "get_favorites", "%s-favorite" % (i,), session, session.db["user_name"], bufferType=None, screen_name=i)
|
||||
self.buffers.append(tl)
|
||||
self.view.insert_buffer(tl.buffer, name=_(u"Favourites timeline for {}").format(i,), pos=self.view.search("favs_timelines", session.db["user_name"]))
|
||||
self.view.insert_buffer(tl.buffer, name=_(u"Likes for {}").format(i,), pos=self.view.search("favs_timelines", session.db["user_name"]))
|
||||
tl.timer = RepeatingTimer(300, tl.start_stream)
|
||||
tl.timer.start()
|
||||
lists = buffersController.emptyPanel(self.view.nb, "lists", session.db["user_name"])
|
||||
@@ -360,41 +366,28 @@ class Controller(object):
|
||||
buffer.start_stream()
|
||||
buffer.searchfunction = self.search
|
||||
self.buffers.append(buffer)
|
||||
self.view.insert_buffer(buffer.buffer, name=_(u"Trending topics for %s") % (buffer.name_), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
|
||||
buffer.timer = RepeatingTimer(300, buffer.start_stream)
|
||||
buffer.timer.start()
|
||||
self.view.insert_buffer(buffer.buffer, name=_(u"Trending topics for %s") % (buffer.name_), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
|
||||
|
||||
def set_buffer_positions(self,session):
|
||||
"Sets positions for buffers if values exist in the database."
|
||||
for i in self.buffers:
|
||||
if i.name+"_pos" in session.db and hasattr(i.buffer,'list'):
|
||||
if i.account == session.db["user_name"] and session.db.has_key(i.name+"_pos") and hasattr(i.buffer,'list'):
|
||||
i.buffer.list.select_item(session.db[str(i.name+"_pos")])
|
||||
|
||||
def logout_account(self, session_id):
|
||||
for i in session_.sessions:
|
||||
if session_.sessions[i].session_id == session_id: session = session_.sessions[i]
|
||||
user = session.db["user_name"]
|
||||
self.destroy_buffer("home_timeline", user)
|
||||
self.destroy_buffer("mentions", user)
|
||||
self.destroy_buffer("direct_messages", user)
|
||||
self.destroy_buffer("sent_direct_messages", user)
|
||||
self.destroy_buffer("sent_tweets", user)
|
||||
self.destroy_buffer("favourites", user)
|
||||
self.destroy_buffer("followers", user)
|
||||
self.destroy_buffer("friends", user)
|
||||
self.destroy_buffer("blocked", user)
|
||||
self.destroy_buffer("muted", user)
|
||||
self.destroy_buffer("events", user)
|
||||
self.destroy_buffer("timelines", user)
|
||||
for i in session.settings["other_buffers"]["timelines"]:
|
||||
self.destroy_buffer("%s-timeline" % (i,), user)
|
||||
self.destroy_buffer("favs_timelines", user)
|
||||
self.destroy_buffer("searches", user)
|
||||
for i in session.settings["other_buffers"]["tweet_searches"]:
|
||||
self.destroy_buffer("%s-searchterm" % (i,), user)
|
||||
for i in session.settings["other_buffers"]["trending_topic_buffers"]:
|
||||
self.destroy_buffer("%s_tt" % (i,), user)
|
||||
|
||||
delete_buffers = []
|
||||
for i in self.buffers:
|
||||
if i.account == user and i.name != user:
|
||||
delete_buffers.append(i.name)
|
||||
for i in delete_buffers:
|
||||
self.destroy_buffer(i, user)
|
||||
session.db = None
|
||||
|
||||
def destroy_buffer(self, buffer_name, account):
|
||||
buffer = self.search_buffer(buffer_name, account)
|
||||
if buffer == None: return
|
||||
@@ -404,7 +397,10 @@ class Controller(object):
|
||||
self.buffers.remove(buffer)
|
||||
del buffer
|
||||
|
||||
def search(self, value="", *args, **kwargs):
|
||||
def search_topic(self, term):
|
||||
self.search(value=term)
|
||||
|
||||
def search(self, event=None, value="", *args, **kwargs):
|
||||
""" Searches words or users in twitter. This creates a new buffer containing the search results."""
|
||||
log.debug("Creating a new search...")
|
||||
dlg = dialogs.search.searchDialog(value)
|
||||
@@ -478,8 +474,20 @@ class Controller(object):
|
||||
buffer = self.get_best_buffer()
|
||||
SoundsTutorial.soundsTutorial(buffer.session)
|
||||
|
||||
def view_user_lists(self, users):
|
||||
pass
|
||||
def view_user_lists(self, *args, **kwargs):
|
||||
buff = self.get_best_buffer()
|
||||
if not hasattr(buff, "get_right_tweet"): return
|
||||
tweet = buff.get_right_tweet()
|
||||
if buff.type != "people":
|
||||
users = utils.get_all_users(tweet, buff.session.db)
|
||||
else:
|
||||
users = [tweet["screen_name"]]
|
||||
dlg = dialogs.utils.selectUserDialog(_(u"Select the user"), users)
|
||||
if dlg.get_response() == widgetUtils.OK:
|
||||
user = dlg.get_user()
|
||||
else:
|
||||
return
|
||||
l = listsController.listsController(buff.session, user=user)
|
||||
|
||||
def add_to_list(self, *args, **kwargs):
|
||||
buff = self.get_best_buffer()
|
||||
@@ -508,8 +516,32 @@ class Controller(object):
|
||||
except TwythonError as e:
|
||||
output.speak("error %s: %s" % (e.error_code, e.msg))
|
||||
|
||||
def remove_from_list(self, user):
|
||||
pass
|
||||
def remove_from_list(self, *args, **kwargs):
|
||||
buff = self.get_best_buffer()
|
||||
if not hasattr(buff, "get_right_tweet"): return
|
||||
tweet = buff.get_right_tweet()
|
||||
if buff.type != "people":
|
||||
users = utils.get_all_users(tweet, buff.session.db)
|
||||
else:
|
||||
users = [tweet["screen_name"]]
|
||||
dlg = dialogs.utils.selectUserDialog(_(u"Select the user"), users)
|
||||
if dlg.get_response() == widgetUtils.OK:
|
||||
user = dlg.get_user()
|
||||
else:
|
||||
return
|
||||
dlg = dialogs.lists.removeUserListDialog()
|
||||
dlg.populate_list([compose.compose_list(item) for item in buff.session.db["lists"]])
|
||||
if dlg.get_response() == widgetUtils.OK:
|
||||
try:
|
||||
list = buff.session.twitter.twitter.delete_list_member(list_id=buff.session.db["lists"][dlg.get_item()]["id"], screen_name=user)
|
||||
older_list = utils.find_item(buff.session.db["lists"][dlg.get_item()]["id"], buff.session.db["lists"])
|
||||
listBuffer = self.search_buffer("%s-list" % (buff.session.db["lists"][dlg.get_item()]["name"].lower()), buff.session.db["user_name"])
|
||||
if listBuffer != None: listBuffer.get_user_ids()
|
||||
buff.session.db["lists"].pop(older_list)
|
||||
buff.session.db["lists"].append(list)
|
||||
if listBuffer != None: pub.sendMessage("restart-streams", streams=["timelinesStream"], session=buff.session)
|
||||
except TwythonError as e:
|
||||
output.speak("error %s: %s" % (e.error_code, e.msg))
|
||||
|
||||
def list_manager(self, *args, **kwargs):
|
||||
s = self.get_best_buffer().session
|
||||
@@ -561,6 +593,7 @@ class Controller(object):
|
||||
self.exit_()
|
||||
|
||||
def exit_(self, *args, **kwargs):
|
||||
for i in self.buffers: i.save_positions()
|
||||
log.debug("Exiting...")
|
||||
log.debug("Saving global configuration...")
|
||||
config.app.write()
|
||||
@@ -718,8 +751,7 @@ class Controller(object):
|
||||
users = [tweet["screen_name"]]
|
||||
dlg = dialogs.userSelection.selectUserDialog(users=users, default=default)
|
||||
if dlg.get_response() == widgetUtils.OK:
|
||||
buffer = self.get_best_buffer()
|
||||
usr = utils.if_user_exists(buffer.session.twitter.twitter, dlg.get_user())
|
||||
usr = utils.if_user_exists(buff.session.twitter.twitter, dlg.get_user())
|
||||
if usr != None:
|
||||
if usr["protected"] == True:
|
||||
if usr["following"] == False:
|
||||
@@ -728,32 +760,38 @@ class Controller(object):
|
||||
answer = commonMessageDialogs.protected_user()
|
||||
if answer == widgetUtils.NO: return
|
||||
if dlg.get_action() == "tweets":
|
||||
if dlg.get_user() in buffer.session.settings["other_buffers"]["timelines"]:
|
||||
if usr["statuses_count"] == 0:
|
||||
commonMessageDialogs.no_tweets()
|
||||
return
|
||||
if dlg.get_user() in buff.session.settings["other_buffers"]["timelines"]:
|
||||
commonMessageDialogs.timeline_exist()
|
||||
return
|
||||
tl = buffersController.baseBufferController(self.view.nb, "get_user_timeline", "%s-timeline" % (dlg.get_user(),), buffer.session, buffer.session.db["user_name"], bufferType=None, screen_name=dlg.get_user())
|
||||
tl = buffersController.baseBufferController(self.view.nb, "get_user_timeline", "%s-timeline" % (dlg.get_user(),), buff.session, buff.session.db["user_name"], bufferType=None, screen_name=dlg.get_user())
|
||||
tl.start_stream()
|
||||
pos=self.view.search("timelines", buffer.session.db["user_name"])
|
||||
pos=self.view.search("timelines", buff.session.db["user_name"])
|
||||
self.insert_buffer(tl, pos+1)
|
||||
# self.buffers.insert(pos+1, tl)
|
||||
self.view.insert_buffer(tl.buffer, name=_(u"Timeline for {}").format(dlg.get_user()), pos=pos)
|
||||
buffer.session.settings["other_buffers"]["timelines"].append(dlg.get_user())
|
||||
pub.sendMessage("restart-streams", streams=["timelinesStream"], session=buffer.session)
|
||||
buffer.session.sound.play("create_timeline.ogg")
|
||||
buff.session.settings["other_buffers"]["timelines"].append(dlg.get_user())
|
||||
pub.sendMessage("restart-streams", streams=["timelinesStream"], session=buff.session)
|
||||
buff.session.sound.play("create_timeline.ogg")
|
||||
else:
|
||||
if dlg.get_user() in buffer.session.settings["other_buffers"]["favourites_timelines"]:
|
||||
if usr["favourites_count"] == 0:
|
||||
commonMessageDialogs.no_favs()
|
||||
return
|
||||
if dlg.get_user() in buff.session.settings["other_buffers"]["favourites_timelines"]:
|
||||
commonMessageDialogs.timeline_exist()
|
||||
return
|
||||
tl = buffersController.baseBufferController(self.view.nb, "get_favorites", "%s-favorite" % (dlg.get_user(),), buffer.session, buffer.session.db["user_name"], bufferType=None, screen_name=dlg.get_user())
|
||||
pos=self.view.search("favs_timelines", buffer.session.db["user_name"])
|
||||
tl = buffersController.baseBufferController(self.view.nb, "get_favorites", "%s-favorite" % (dlg.get_user(),), buff.session, buff.session.db["user_name"], bufferType=None, screen_name=dlg.get_user())
|
||||
pos=self.view.search("favs_timelines", buff.session.db["user_name"])
|
||||
self.insert_buffer(tl, pos+1)
|
||||
# self.buffers.insert(pos+1, tl)
|
||||
self.view.insert_buffer(buffer=tl.buffer, name=_(u"Favourites timeline for {}").format(dlg.get_user()), pos=pos)
|
||||
self.view.insert_buffer(buffer=tl.buffer, name=_(u"Likes for {}").format(dlg.get_user()), pos=pos)
|
||||
tl.start_stream()
|
||||
tl.timer = RepeatingTimer(300, tl.start_stream)
|
||||
tl.timer.start()
|
||||
buffer.session.settings["other_buffers"]["favourites_timelines"].append(dlg.get_user())
|
||||
buffer.session.sound.play("create_timeline.ogg")
|
||||
buff.session.settings["other_buffers"]["favourites_timelines"].append(dlg.get_user())
|
||||
buff.session.sound.play("create_timeline.ogg")
|
||||
else:
|
||||
commonMessageDialogs.user_not_exist()
|
||||
|
||||
@@ -1188,7 +1226,7 @@ class Controller(object):
|
||||
def manage_item_in_list(self, data, user, where):
|
||||
buffer = self.search_buffer("%s" % (where,), user)
|
||||
if buffer == None: return
|
||||
play_sound = "tweet_timeline.ogg"
|
||||
play_sound = "list_tweet.ogg"
|
||||
if "%s" % (where,) not in buffer.session.settings["other_buffers"]["muted_buffers"]:
|
||||
self.notify(buffer.session, play_sound=play_sound)
|
||||
output.speak(_(u"One tweet from %s") % (data["user"]["name"]))
|
||||
@@ -1202,13 +1240,28 @@ class Controller(object):
|
||||
log.debug("Starting the streaming endpoint")
|
||||
session.start_streaming()
|
||||
|
||||
def set_positions(self):
|
||||
for i in session_.sessions:
|
||||
self.set_buffer_positions(i)
|
||||
|
||||
def manage_stream_errors(self, session):
|
||||
log.error("An error ocurred with the stream for the %s session. It will be destroyed" % (session,))
|
||||
log.error(" Restarting %s session streams. It will be destroyed" % (session,))
|
||||
s = session_.sessions[session]
|
||||
for i in self.buffers:
|
||||
if i.invisible == True and i.session.session_id == s.session_id:
|
||||
i.start_stream()
|
||||
s.listen_stream_error()
|
||||
try:
|
||||
if hasattr(s, "main_stream"):
|
||||
self.main_stream.disconnect()
|
||||
log.error("main stream disconnected")
|
||||
del s.main_stream
|
||||
self.timelinesStream.disconnect()
|
||||
del s.timelinesStream
|
||||
s.counter = 0
|
||||
s.reconnection_function_active = False
|
||||
except AttributeError:
|
||||
log.error("Error deleting some thing")
|
||||
# for i in self.buffers:
|
||||
# if i.invisible == True and i.session.session_id == s.session_id and i.type != "people":
|
||||
# i.start_stream()
|
||||
# s.listen_stream_error()
|
||||
|
||||
def check_connection(self):
|
||||
for i in session_.sessions:
|
||||
@@ -1221,7 +1274,7 @@ class Controller(object):
|
||||
if buffer == "favourites":
|
||||
favourites = buffersController.baseBufferController(self.view.nb, "get_favorites", "favourites", buff.session, buff.session.db["user_name"])
|
||||
self.buffers.append(favourites)
|
||||
self.view.insert_buffer(favourites.buffer, name=_(u"Favourites"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"]))
|
||||
self.view.insert_buffer(favourites.buffer, name=_(u"Likes"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"]))
|
||||
favourites.start_stream()
|
||||
if buffer == "followers":
|
||||
followers = buffersController.peopleBufferController(self.view.nb, "get_followers_list", "followers", buff.session, buff.session.db["user_name"], screen_name=buff.session.db["user_name"])
|
||||
@@ -1350,5 +1403,9 @@ class Controller(object):
|
||||
def repeat_item(self, *args, **kwargs):
|
||||
output.speak(self.get_current_buffer().get_message())
|
||||
|
||||
def execute_action(self, action):
|
||||
if hasattr(self, action):
|
||||
getattr(self, action)()
|
||||
|
||||
def __del__(self):
|
||||
config.app.write()
|
@@ -25,6 +25,7 @@ class basicTweet(object):
|
||||
widgetUtils.connect_event(self.message.spellcheck, widgetUtils.BUTTON_PRESSED, self.spellcheck)
|
||||
widgetUtils.connect_event(self.message.attach, widgetUtils.BUTTON_PRESSED, self.attach)
|
||||
# if system == "Windows":
|
||||
# if messageType != "dm":
|
||||
widgetUtils.connect_event(self.message.text, widgetUtils.ENTERED_TEXT, self.text_processor)
|
||||
self.text_processor()
|
||||
widgetUtils.connect_event(self.message.shortenButton, widgetUtils.BUTTON_PRESSED, self.shorten)
|
||||
@@ -37,7 +38,7 @@ class basicTweet(object):
|
||||
text_to_translate = self.message.get_text().encode("utf-8")
|
||||
source = [x[0] for x in translator.translator.available_languages()][dlg.get("source_lang")]
|
||||
dest = [x[0] for x in translator.translator.available_languages()][dlg.get("dest_lang")]
|
||||
msg = translator.translator.translate(text_to_translate, source, dest)
|
||||
msg = translator.translator.translate(text=text_to_translate, source=source, target=dest)
|
||||
self.message.set_text(msg)
|
||||
self.message.text_focus()
|
||||
output.speak(_(u"Translated"))
|
||||
@@ -97,6 +98,7 @@ class basicTweet(object):
|
||||
checker = SpellChecker.spellchecker.spellChecker(text, "")
|
||||
if hasattr(checker, "fixed_text"):
|
||||
self.message.set_text(checker.fixed_text)
|
||||
self.message.text_focus()
|
||||
|
||||
def attach(self, *args, **kwargs):
|
||||
def completed_callback():
|
||||
@@ -109,6 +111,7 @@ class basicTweet(object):
|
||||
output.speak(_(u"Unable to upload the audio"))
|
||||
dlg.cleanup()
|
||||
dlg = audioUploader.audioUploader(self.session.settings, completed_callback)
|
||||
self.message.text_focus()
|
||||
|
||||
class tweet(basicTweet):
|
||||
def __init__(self, session, title, caption, text, twishort_enabled, messageType="tweet", max=140):
|
||||
@@ -130,6 +133,7 @@ class tweet(basicTweet):
|
||||
self.image = self.message.get_image()
|
||||
if self.image != None:
|
||||
self.message.set("upload_image", _(u"Discard image"))
|
||||
self.message.text_focus()
|
||||
|
||||
def autocomplete_users(self, *args, **kwargs):
|
||||
c = autocompletionUsers.completion.autocompletionUsers(self.message, self.session.session_id)
|
||||
@@ -151,7 +155,7 @@ class reply(tweet):
|
||||
|
||||
class dm(basicTweet):
|
||||
def __init__(self, session, title, caption, text):
|
||||
super(dm, self).__init__(session, title, caption, text, messageType="dm")
|
||||
super(dm, self).__init__(session, title, caption, text, messageType="dm", max=10000)
|
||||
widgetUtils.connect_event(self.message.autocompletionButton, widgetUtils.BUTTON_PRESSED, self.autocomplete_users)
|
||||
|
||||
def autocomplete_users(self, *args, **kwargs):
|
||||
@@ -164,9 +168,9 @@ class viewTweet(basicTweet):
|
||||
text = ""
|
||||
for i in xrange(0, len(tweetList)):
|
||||
if tweetList[i].has_key("retweeted_status"):
|
||||
text = text + "rt @%s: %s\n\n" % (tweetList[i]["retweeted_status"]["user"]["screen_name"], tweetList[i]["retweeted_status"]["text"])
|
||||
text = text + "rt @%s: %s\n" % (tweetList[i]["retweeted_status"]["user"]["screen_name"], tweetList[i]["retweeted_status"]["text"])
|
||||
else:
|
||||
text = text + "@%s: %s\n\n" % (tweetList[i]["user"]["screen_name"], tweetList[i]["text"])
|
||||
text = text + "@%s: %s\n" % (tweetList[i]["user"]["screen_name"], tweetList[i]["text"])
|
||||
rt_count = str(tweet["retweet_count"])
|
||||
favs_count = str(tweet["favorite_count"])
|
||||
if text == "":
|
||||
@@ -174,6 +178,7 @@ class viewTweet(basicTweet):
|
||||
text = "rt @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], tweet["retweeted_status"]["text"])
|
||||
else:
|
||||
text = tweet["text"]
|
||||
text = self.clear_text(text)
|
||||
self.message = message.viewTweet(text, rt_count, favs_count)
|
||||
self.message.set_title(len(text))
|
||||
else:
|
||||
@@ -190,3 +195,10 @@ class viewTweet(basicTweet):
|
||||
if len(utils.find_urls_in_text(self.message.get_text())) > 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
def clear_text(self, text):
|
||||
urls = utils.find_urls_in_text(text)
|
||||
for i in urls:
|
||||
if "https://twitter.com/" in i:
|
||||
text = text.replace(i, "")
|
||||
return text
|
||||
|
@@ -95,7 +95,7 @@ class profileController(object):
|
||||
else: verified = _(u"No")
|
||||
string = string+ _(u"Verified: %s\n") % (verified)
|
||||
string = string+ _(u"Tweets: %s\n") % (self.data["statuses_count"])
|
||||
string = string+ _(u"Favourites: %s") % (self.data["favourites_count"])
|
||||
string = string+ _(u"Likes: %s") % (self.data["favourites_count"])
|
||||
return string
|
||||
|
||||
def visit_url(self, *args, **kwargs):
|
||||
|
@@ -74,10 +74,10 @@ class audioUploader(object):
|
||||
def on_pause(self, *args, **kwargs):
|
||||
if self.dialog.get("pause") == _(u"Pause"):
|
||||
self.recording.pause()
|
||||
self.dialog.set("pause", _(u"Resume"))
|
||||
self.dialog.set("pause", _(u"&Resume"))
|
||||
elif self.dialog.get("pause") == _(u"Resume"):
|
||||
self.recording.play()
|
||||
self.dialog.set("pause", _(U"Pause"))
|
||||
self.dialog.set("pause", _(U"&Pause"))
|
||||
|
||||
def on_record(self, *args, **kwargs):
|
||||
if self.recording != None:
|
||||
@@ -92,7 +92,7 @@ class audioUploader(object):
|
||||
self.file = tempfile.mktemp(suffix='.wav')
|
||||
self.recording = sound.recording(self.file)
|
||||
self.recording.play()
|
||||
self.dialog.set("record", _(u"Stop"))
|
||||
self.dialog.set("record", _(u"&Stop"))
|
||||
output.speak(_(u"Recording"))
|
||||
|
||||
def stop_recording(self):
|
||||
@@ -100,11 +100,11 @@ class audioUploader(object):
|
||||
self.recording.free()
|
||||
output.speak(_(u"Stopped"))
|
||||
self.recorded = True
|
||||
self.dialog.set("record", _(u"Record"))
|
||||
self.dialog.set("record", _(u"&Record"))
|
||||
self.file_attached()
|
||||
|
||||
def file_attached(self):
|
||||
self.dialog.set("pause", _(u"Pause"))
|
||||
self.dialog.set("pause", _(u"&Pause"))
|
||||
self.dialog.disable_control("record")
|
||||
self.dialog.enable_control("play")
|
||||
self.dialog.enable_control("discard")
|
||||
@@ -137,11 +137,11 @@ class audioUploader(object):
|
||||
# try:
|
||||
self.playing = sound_lib.stream.FileStream(file=unicode(self.file), flags=sound_lib.stream.BASS_UNICODE)
|
||||
self.playing.play()
|
||||
self.dialog.set("play", _(u"Stop"))
|
||||
self.dialog.set("play", _(u"&Stop"))
|
||||
try:
|
||||
while self.playing.is_playing:
|
||||
pass
|
||||
self.dialog.set("play", _(u"Play"))
|
||||
self.dialog.set("play", _(u"&Play"))
|
||||
self.playing.free()
|
||||
self.playing = None
|
||||
except:
|
||||
@@ -151,7 +151,7 @@ class audioUploader(object):
|
||||
output.speak(_(u"Stopped"))
|
||||
self.playing.stop()
|
||||
self.playing.free()
|
||||
self.dialog.set("play", _(u"Play"))
|
||||
self.dialog.set("play", _(u"&Play"))
|
||||
self.playing = None
|
||||
|
||||
def postprocess(self):
|
||||
|
@@ -31,14 +31,14 @@ class audioDialog(widgetUtils.BaseDialog):
|
||||
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
btnSizer2 = wx.BoxSizer(wx.HORIZONTAL)
|
||||
|
||||
self.play = wx.Button(panel, -1, _(u"Play"))
|
||||
self.play = wx.Button(panel, -1, _(u"&Play"))
|
||||
self.play.Disable()
|
||||
self.pause = wx.Button(panel, -1, _(u"Pause"))
|
||||
self.pause = wx.Button(panel, -1, _(u"&Pause"))
|
||||
self.pause.Disable()
|
||||
self.record = wx.Button(panel, -1, _(u"Record"))
|
||||
self.record = wx.Button(panel, -1, _(u"&Record"))
|
||||
self.record.SetFocus()
|
||||
self.attach_exists = wx.Button(panel, -1, _(u"Add an existing file"))
|
||||
self.discard = wx.Button(panel, -1, _(u"Discard"))
|
||||
self.attach_exists = wx.Button(panel, -1, _(u"&Add an existing file"))
|
||||
self.discard = wx.Button(panel, -1, _(u"&Discard"))
|
||||
self.discard.Disable()
|
||||
label = wx.StaticText(panel, -1, _(u"Upload to"))
|
||||
self.services = wx.ComboBox(panel, -1, choices=services, value=services[0], style=wx.CB_READONLY)
|
||||
@@ -47,7 +47,7 @@ class audioDialog(widgetUtils.BaseDialog):
|
||||
servicesBox.Add(self.services, 0, wx.ALL, 5)
|
||||
self.attach = wx.Button(panel, wx.ID_OK, _(u"Attach"))
|
||||
self.attach.Disable()
|
||||
cancel = wx.Button(panel, wx.ID_CANCEL, _(u"Cancel"))
|
||||
cancel = wx.Button(panel, wx.ID_CANCEL, _(u"&Cancel"))
|
||||
btnSizer.Add(self.play, 0, wx.ALL, 5)
|
||||
btnSizer.Add(self.pause, 0, wx.ALL, 5)
|
||||
btnSizer.Add(self.record, 0, wx.ALL, 5)
|
||||
|
@@ -7,8 +7,8 @@ actions = reverse_sort.reverse_sort([ ("audio", _(u"Audio tweet.")),
|
||||
("dm_received", _(u"Direct message received.")),
|
||||
("dm_sent", _(u"Direct message sent.")),
|
||||
("error", _(u"Error.")),
|
||||
("favourite", _(u"Tweet favourited.")),
|
||||
("favourites_timeline_updated", _(u"Favourites buffer updated.")),
|
||||
("favourite", _(u"Tweet liked.")),
|
||||
("favourites_timeline_updated", _(u"Likes buffer updated.")),
|
||||
("geo", _(u"Geotweet.")),
|
||||
("limit", _(u"Boundary reached.")),
|
||||
("list_tweet", _(u"List updated.")),
|
||||
|
@@ -1,9 +1,153 @@
|
||||
#!/usr/bin/env python
|
||||
import goslate
|
||||
# encoding: utf-8
|
||||
#
|
||||
# Copyright (C) 2013 Mesar Hameed <mhameed@src.gnome.org>
|
||||
# This file is covered by the GNU General Public License.
|
||||
|
||||
def translate(text, source_lang, target_lang):
|
||||
gs = goslate.Goslate()
|
||||
return gs.translate(text, target_lang, source_lang)
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import threading
|
||||
from time import sleep
|
||||
from random import randint
|
||||
import logging
|
||||
log = logging.getLogger("translator")
|
||||
import urllib2
|
||||
|
||||
# Each group has to be a class of possible breaking points for the writing script.
|
||||
# Usually this is the major syntax marks, such as:
|
||||
# full stop, comma, exclaim, question, etc.
|
||||
arabicBreaks = u'[،؛؟]'
|
||||
# Thanks to Talori in the NVDA irc room:
|
||||
# U+3000 to U+303F, U+FE10 to U+FE1F, U+FE30 to U+FE6F, U+FF01 to U+FF60
|
||||
chineseBreaks = u'[ -〿︐-︰-!-⦆]'
|
||||
latinBreaks = r'[.,!?;:\n]'
|
||||
splitReg = re.compile(u"{arabic}|{chinese}|{latin}".format(arabic=arabicBreaks, chinese=chineseBreaks, latin=latinBreaks))
|
||||
|
||||
def translate(text, source="auto", target="en"):
|
||||
if source == "": source = "auto"
|
||||
t = Translator(lang_from=source, lang_to=target, text=text)
|
||||
t.start()
|
||||
while t.isAlive():
|
||||
sleep(0.1)
|
||||
t.join()
|
||||
return t.translation
|
||||
|
||||
def splitChunks(text, chunksize):
|
||||
pos = 0
|
||||
potentialPos = 0
|
||||
for splitMark in splitReg.finditer(text):
|
||||
if (splitMark.start() - pos +1) < chunksize:
|
||||
potentialPos = splitMark.start()
|
||||
continue
|
||||
else:
|
||||
yield text[pos:potentialPos+1]
|
||||
pos = potentialPos + 1
|
||||
potentialPos = splitMark.start()
|
||||
yield text[pos:]
|
||||
|
||||
class Translator(threading.Thread):
|
||||
|
||||
def __init__(self, lang_from, lang_to, text, lang_swap=None, chunksize=350, *args, **kwargs):
|
||||
super(Translator, self).__init__(*args, **kwargs)
|
||||
self._stop = threading.Event()
|
||||
self.text = text
|
||||
self.chunksize = chunksize
|
||||
self.lang_to = lang_to
|
||||
self.lang_from = lang_from
|
||||
self.lang_swap = lang_swap
|
||||
self.translation = ''
|
||||
self.lang_translated = ''
|
||||
self.firstChunk = True
|
||||
|
||||
def stop(self):
|
||||
self._stop.set()
|
||||
|
||||
def run(self):
|
||||
for chunk in splitChunks(self.text, self.chunksize):
|
||||
# Make sure we don't send requests to google too often.
|
||||
# Try to simulate a human.
|
||||
if not self.firstChunk:
|
||||
sleep(randint(1, 10))
|
||||
req = self.buildRequest(chunk, self.lang_from, self.lang_to)
|
||||
try:
|
||||
response = urllib2.urlopen(req)
|
||||
translation, lang_translated = self.parseData(response)
|
||||
if self.firstChunk and self.lang_from == "auto" and lang_translated == self.lang_to and self.lang_swap is not None:
|
||||
self.lang_to = self.lang_swap
|
||||
self.firstChunk = False
|
||||
req = self.buildRequest(chunk.encode('utf-8'), self.lang_from, self.lang_to)
|
||||
response = urllib2.urlopen(req)
|
||||
translation, lang_translated = self.parseData(response)
|
||||
except Exception as e:
|
||||
log.exception("Can not translate text '%s'" %chunk)
|
||||
# We have probably been blocked, so stop trying to translate.
|
||||
raise e
|
||||
self.translation += translation
|
||||
# some adjustment, better to do on full text
|
||||
self.translation = self.fixNewlines(self.translation)
|
||||
self.lang_translated = lang_translated
|
||||
|
||||
def buildRequest(self, text, lang_from, lang_to):
|
||||
"""Build POST request which will be sent to Google."""
|
||||
urlTemplate = 'http://translate.google.com/translate_a/single?client=t&sl={lang_from}&tl={lang_to}&ie=utf-8&oe=utf-8&dt=t&dt=bd&tk='
|
||||
url = urlTemplate.format(lang_from=lang_from, lang_to=lang_to)
|
||||
header = {'User-agent': 'Mozilla/5.0', 'Content-Type': 'application/x-www-form-urlencoded'}
|
||||
data = 'text=%s' %urllib2.quote(text)
|
||||
req = urllib2.Request(url, data, header)
|
||||
return req
|
||||
|
||||
def parseData(self, response):
|
||||
"""Parse unstructured response."""
|
||||
data = response.readlines()[0]
|
||||
# get segments with couples ["translation","original text"]
|
||||
l1, l2 = data.split(']],', 1)
|
||||
translation = l1[3:]
|
||||
if l2.startswith('[[\"'):
|
||||
# get list of synonyms
|
||||
syn = l2[l2.find(',[')+1:l2.find(']')].split(',')
|
||||
temp = ', '.join([x.replace('\"', '') for x in syn])
|
||||
else:
|
||||
# get a list with each couple as item
|
||||
sentences = translation.split('],[')
|
||||
temp = ''
|
||||
# get translation, removing first char (quote symbol)
|
||||
for item in sentences:
|
||||
item = item.split('\",\"', 1)[0][1:]
|
||||
# join all translations
|
||||
temp = ' '.join([temp, item])
|
||||
translation = temp.decode('string-escape').decode('utf-8')
|
||||
translation = self.fixPunctuation(translation)
|
||||
# get the language of original text
|
||||
tempLang = data.partition(']],,\"')[2]
|
||||
lang = tempLang[:tempLang.find('\"')]
|
||||
if lang == '':
|
||||
lang = _("unavailable")
|
||||
return translation, lang
|
||||
|
||||
def fixPunctuation(self, translation):
|
||||
"""Clean text from space before punctuation symbol."""
|
||||
# list of potentially positions of spaces to remove
|
||||
spacePos = []
|
||||
for puncMark in splitReg.finditer(translation):
|
||||
spacePos.append(puncMark.start()-1)
|
||||
if len(spacePos) == 0:
|
||||
return translation
|
||||
fixedTranslation = ''
|
||||
for n in xrange(0,len(translation)):
|
||||
temp = translation[n]
|
||||
if n in spacePos and temp == ' ':
|
||||
continue
|
||||
else:
|
||||
fixedTranslation += temp
|
||||
return fixedTranslation
|
||||
|
||||
def fixNewlines(self, translation):
|
||||
"""Adjust newlines and (subsequent or double) spaces."""
|
||||
fixes = [('\r\n ', '\r\n'), ('\n ', '\r\n'), (' ', ' ')]
|
||||
for fix in fixes:
|
||||
translation = translation.replace(fix[0], fix[1])
|
||||
# first char is a space, so...
|
||||
return translation[1:]
|
||||
|
||||
languages = {
|
||||
"af": _(u"Afrikaans"),
|
||||
|
@@ -11,9 +11,17 @@ def fix():
|
||||
locales.BasqueLocale = BasqueLocale
|
||||
locales.TurkishLocale.names[-1] = "tr_tr"
|
||||
locales.ArabicLocale.names[-1] = "ar_eg"
|
||||
# insert a modified function so if there is no language available in arrow, returns English locale.
|
||||
locales.get_locale = get_locale
|
||||
# We need to reassign the locales list for updating the list with our new contents.
|
||||
locales._locales = locales._map_locales()
|
||||
|
||||
def get_locale(name):
|
||||
locale_cls = locales._locales.get(name.lower())
|
||||
if locale_cls is None:
|
||||
return locales.EnglishLocale()
|
||||
return locale_cls()
|
||||
|
||||
class CatalaLocale(Locale):
|
||||
names = ['ca', 'ca_ca']
|
||||
past = 'Fa {0}'
|
||||
|
@@ -1,6 +1,4 @@
|
||||
import win32com.client
|
||||
|
||||
|
||||
def fix():
|
||||
if win32com.client.gencache.is_readonly == True:
|
||||
win32com.client.gencache.is_readonly = False
|
||||
|
@@ -28,3 +28,7 @@ repeat_item = string(default="control+win+space")
|
||||
copy_to_clipboard = string(default="control+win+shift+c")
|
||||
search = string(default="control+win+/")
|
||||
find = string(default="control+win+shift+/")
|
||||
check_for_updates = string(default="alt+win+u)
|
||||
list_manager = string(default="control+win+shift+l")
|
||||
configuration = string(default="control+win+o")
|
||||
accountConfiguration = string(default="control+win+shift+o")
|
@@ -47,3 +47,7 @@ view_user_lists = string(default="win+alt+shift+l")
|
||||
reverse_geocode = string(default="control+win+g")
|
||||
view_reverse_geocode = string(default="control+win+shift+g")
|
||||
get_trending_topics = string(default="control+win+shift+t")
|
||||
check_for_updates = string(default="control+win+u")
|
||||
list_manager = string(default="control+win+shift+l")
|
||||
configuration = string(default="control+win+o")
|
||||
accountConfiguration = string(default="control+win+shift+o")
|
@@ -49,3 +49,7 @@ get_more_items = string(default="alt+win+pageup")
|
||||
reverse_geocode = string(default="alt+win+g")
|
||||
view_reverse_geocode = string(default="alt+win+shift+g")
|
||||
get_trending_topics = string(default="alt+win+t")
|
||||
check_for_updates = string(default="alt+win+u")
|
||||
list_manager = string(default="alt+win+shift+l")
|
||||
configuration = string(default="control+win+o")
|
||||
accountConfiguration = string(default="control+win+shift+o")
|
@@ -50,3 +50,7 @@ get_more_items = string(default="alt+win+pageup")
|
||||
reverse_geocode = string(default="control+win+g")
|
||||
view_reverse_geocode = string(default="control+win+shift+g")
|
||||
get_trending_topics = string(default="control+win+t")
|
||||
check_for_updates = string(default="control+win+u")
|
||||
list_manager = string(default="control+win+shift+l")
|
||||
configuration = string(default="control+win+o")
|
||||
accountConfiguration = string(default="control+win+shift+o")
|
@@ -50,3 +50,7 @@ reverse_geocode = string(default="control+win+g")
|
||||
view_reverse_geocode = string(default="control+win+shift+g")
|
||||
get_trending_topics = string(default="control+win+t")
|
||||
find = string(default="control+win+{")
|
||||
check_for_updates = string(default="control+win+u")
|
||||
list_manager = string(default="control+win+shift+l")
|
||||
configuration = string(default="control+win+o")
|
||||
accountConfiguration = string(default="control+win+shift+o")
|
@@ -11,8 +11,8 @@ actions = {
|
||||
"post_reply": _(u"Reply"),
|
||||
"post_retweet": _(u"Retweet"),
|
||||
"send_dm": _(u"Send direct message"),
|
||||
"add_to_favourites": _(u"Mark as favourite"),
|
||||
"remove_from_favourites": _(u"Remove from favourites"),
|
||||
"add_to_favourites": _(u"Like a tweet"),
|
||||
"remove_from_favourites": _(u"Unlike a tweet"),
|
||||
"follow": _(u"Open the user actions dialogue"),
|
||||
"user_details": _(u"See user details"),
|
||||
"view_item": _(u"Show tweet"),
|
||||
@@ -46,4 +46,8 @@ actions = {
|
||||
"view_reverse_geocode": _(u"Display the tweet's geolocation in a dialog"),
|
||||
"get_trending_topics": _(u"Create a trending topics buffer"),
|
||||
"open_conversation": _(u"View conversation"),
|
||||
"check_for_updates": _(u"Check and download updates"),
|
||||
"lists_manager": _(u"Opens the list manager, which allows you to create, edit, delete and open lists in buffers."),
|
||||
"configuration": _(u"Opens the global settings dialogue"),
|
||||
"accountConfiguration": _(u"Opens the account settings dialogue"),
|
||||
}
|
@@ -3,6 +3,7 @@ import widgetUtils
|
||||
import config
|
||||
import wx_ui
|
||||
import constants
|
||||
from pubsub import pub
|
||||
|
||||
class KeystrokeEditor(object):
|
||||
def __init__(self):
|
||||
@@ -14,6 +15,7 @@ class KeystrokeEditor(object):
|
||||
self.hold_map = self.map.copy()
|
||||
self.dialog.put_keystrokes(constants.actions, self.map)
|
||||
widgetUtils.connect_event(self.dialog.edit, widgetUtils.BUTTON_PRESSED, self.edit_keystroke)
|
||||
widgetUtils.connect_event(self.dialog.execute, widgetUtils.BUTTON_PRESSED, self.execute_action)
|
||||
self.dialog.get_response()
|
||||
|
||||
def edit_keystroke(self, *args, **kwargs):
|
||||
@@ -52,3 +54,7 @@ class KeystrokeEditor(object):
|
||||
wx_ui.no_key()
|
||||
return
|
||||
return "+".join(keys)
|
||||
|
||||
def execute_action(self, *args, **kwargs):
|
||||
action = self.dialog.actions[self.dialog.get_action()]
|
||||
pub.sendMessage("execute-action", action=action)
|
@@ -13,18 +13,20 @@ class keystrokeEditorDialog(baseDialog.BaseWXDialog):
|
||||
self.keys = widgets.list(self, _(u"Action"), _(u"Keystroke"), style=wx.LC_REPORT|wx.LC_SINGLE_SEL, size=(400, 450))
|
||||
self.keys.list.SetFocus()
|
||||
firstSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
firstSizer.Add(keysText)
|
||||
firstSizer.Add(self.keys.list)
|
||||
firstSizer.Add(keysText, 0, wx.ALL, 5)
|
||||
firstSizer.Add(self.keys.list, 0, wx.ALL, 5)
|
||||
self.edit = wx.Button(panel, -1, _(u"Edit"))
|
||||
self.edit.SetDefault()
|
||||
|
||||
self.execute = wx.Button(panel, -1, _(u"Execute action"))
|
||||
close = wx.Button(panel, wx.ID_CANCEL, _(u"Close"))
|
||||
secondSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
secondSizer.Add(self.edit)
|
||||
secondSizer.Add(close)
|
||||
sizer.Add(firstSizer)
|
||||
sizer.Add(secondSizer)
|
||||
panel.SetSizerAndFit(sizer)
|
||||
secondSizer.Add(self.edit, 0, wx.ALL, 5)
|
||||
secondSizer.Add(self.execute, 0, wx.ALL, 5)
|
||||
secondSizer.Add(close, 0, wx.ALL, 5)
|
||||
sizer.Add(firstSizer, 0, wx.ALL, 5)
|
||||
sizer.Add(secondSizer, 0, wx.ALL, 5)
|
||||
panel.SetSizer(sizer)
|
||||
self.SetClientSize(sizer.CalcMin())
|
||||
|
||||
def put_keystrokes(self, actions, keystrokes):
|
||||
for i in keystrokes:
|
||||
|
@@ -69,6 +69,7 @@ def getLanguageDescription(language):
|
||||
"ar":pgettext("languageName","Arabic"),
|
||||
"ne":pgettext("languageName","Nepali"),
|
||||
"sr":pgettext("languageName","Serbian (Latin)"),
|
||||
"ja":pgettext("languageName","Japanese"),
|
||||
}.get(language,None)
|
||||
return desc
|
||||
|
||||
@@ -195,10 +196,13 @@ def langToWindowsLocale(lang):
|
||||
"gl": "glc",
|
||||
"eu": "euq",
|
||||
"hu": "hun",
|
||||
"hr": "hrv",
|
||||
"it": "ita",
|
||||
"ja": "jpn",
|
||||
"pl": "plk",
|
||||
"pt": "ptb",
|
||||
"ru": "rus",
|
||||
"tr": "trk"
|
||||
"tr": "trk",
|
||||
"sr": "eng",
|
||||
}
|
||||
return languages[lang]
|
||||
|
@@ -1,13 +1,26 @@
|
||||
from pywintypes import com_error
|
||||
import win32com
|
||||
import paths
|
||||
win32com.__gen_path__=paths.data_path(u"com_cache")
|
||||
import sys
|
||||
import os
|
||||
sys.path.append(os.path.join(win32com.__gen_path__, "."))
|
||||
from win32com.client import gencache
|
||||
fixed=False
|
||||
|
||||
def prepare_gencache():
|
||||
gencache.is_readonly = False
|
||||
gencache.GetGeneratePath()
|
||||
|
||||
|
||||
def patched_getmodule(modname):
|
||||
mod=__import__(modname)
|
||||
return sys.modules[modname]
|
||||
|
||||
def load_com(*names):
|
||||
global fixed
|
||||
if fixed==False:
|
||||
gencache._GetModule=patched_getmodule
|
||||
fixed=True
|
||||
result = None
|
||||
for name in names:
|
||||
try:
|
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
src/locales/RS/LC_MESSAGES/twblue.mo
Normal file
BIN
src/locales/RS/LC_MESSAGES/twblue.mo
Normal file
Binary file not shown.
2823
src/locales/RS/LC_MESSAGES/twblue.po
Normal file
2823
src/locales/RS/LC_MESSAGES/twblue.po
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
src/locales/ja/lc_messages/twblue.mo
Normal file
BIN
src/locales/ja/lc_messages/twblue.mo
Normal file
Binary file not shown.
2828
src/locales/ja/lc_messages/twblue.po
Normal file
2828
src/locales/ja/lc_messages/twblue.po
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
src/locales/sr/LC_MESSAGES/twblue.mo
Normal file
BIN
src/locales/sr/LC_MESSAGES/twblue.mo
Normal file
Binary file not shown.
2821
src/locales/sr/LC_MESSAGES/twblue.po
Normal file
2821
src/locales/sr/LC_MESSAGES/twblue.po
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -16,6 +16,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
############################################################
|
||||
from twitter import utils
|
||||
|
||||
def get_id(url):
|
||||
return url.split("/")[-1]
|
||||
@@ -25,4 +26,10 @@ def is_long(tweet):
|
||||
for url in range(0, len(tweet["entities"]["urls"])):
|
||||
if "twitter.com" in tweet["entities"]["urls"][url]["expanded_url"]:
|
||||
long = get_id(tweet["entities"]["urls"][url]["expanded_url"])
|
||||
return long
|
||||
return long
|
||||
|
||||
def clear_url(tweet):
|
||||
urls = utils.find_urls_in_text(tweet["text"])
|
||||
try: tweet["message"] = tweet["message"].replace(urls[-1], "")
|
||||
except IndexError: pass
|
||||
return tweet
|
@@ -23,7 +23,7 @@ import application
|
||||
import keys
|
||||
from mysc.thread_utils import call_threaded
|
||||
import fixes
|
||||
#extra variables to control the temporal stdout and stderr, while the final files are opened. We understand that some errors could happen while all outputs are closed, so let's try to avoid it.
|
||||
#extra variables to control the temporary stdout and stderr, while the final files are opened. We understand that some errors could happen while all outputs are closed, so let's try to avoid it.
|
||||
import widgetUtils
|
||||
import webbrowser
|
||||
from wxUI import commonMessageDialogs
|
||||
@@ -53,13 +53,13 @@ log = logging.getLogger("main")
|
||||
def setup():
|
||||
log.debug("Starting " + application.name + " %s" % (application.version,))
|
||||
config.setup()
|
||||
fixes.setup()
|
||||
log.debug("Using %s %s" % (platform.system(), platform.architecture()[0]))
|
||||
log.debug("Application path is %s" % (paths.app_path(),))
|
||||
log.debug("config path is %s" % (paths.config_path(),))
|
||||
sound.setup()
|
||||
output.setup()
|
||||
languageHandler.setLanguage(config.app["app-settings"]["language"])
|
||||
fixes.setup()
|
||||
keys.setup()
|
||||
from controller import mainController
|
||||
from sessionmanager import sessionManager
|
||||
|
@@ -27,7 +27,9 @@ def stream_threaded(func, *args, **kwargs):
|
||||
try:
|
||||
func(**k)
|
||||
except:
|
||||
pub.sendMessage("streamError", session=a[0])
|
||||
log.error("Error in stream with args: %r" % (a,))
|
||||
pub.sendMessage("stream-error", session=a[0])
|
||||
|
||||
thread = threading.Thread(target=new_func, args=args, kwargs=kwargs)
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
|
@@ -29,7 +29,7 @@ def config_path():
|
||||
if directory != None: path = os.path.join(directory, "config")
|
||||
elif directory == None: path = app_path(u"config")
|
||||
elif mode == "installed":
|
||||
path = data_path("config")
|
||||
path = data_path(u"config")
|
||||
if not os.path.exists(path):
|
||||
log.debug("%s path does not exist, creating..." % (path,))
|
||||
os.mkdir(path)
|
||||
@@ -42,7 +42,7 @@ def logs_path():
|
||||
if directory != None: path = os.path.join(directory, "logs")
|
||||
elif directory == None: path = app_path(u"logs")
|
||||
elif mode == "installed":
|
||||
path = data_path("logs")
|
||||
path = data_path(u"logs")
|
||||
if not os.path.exists(path):
|
||||
log.debug("%s path does not exist, creating..." % (path,))
|
||||
os.mkdir(path)
|
||||
|
@@ -9,7 +9,7 @@ import output
|
||||
import time
|
||||
import sound
|
||||
import logging
|
||||
from twitter import utils
|
||||
from twitter import utils, compose
|
||||
from twython import TwythonError, TwythonRateLimitError, TwythonAuthError
|
||||
import config_utils
|
||||
import shelve
|
||||
@@ -18,6 +18,7 @@ import os
|
||||
from mysc.thread_utils import stream_threaded
|
||||
from pubsub import pub
|
||||
log = logging.getLogger("sessionmanager.session")
|
||||
from long_tweets import tweets
|
||||
|
||||
sessions = {}
|
||||
|
||||
@@ -61,6 +62,8 @@ class Session(object):
|
||||
self.db[name] = []
|
||||
for i in data:
|
||||
if utils.find_item(i["id"], self.db[name]) == None and utils.is_allowed(i, self.settings["twitter"]["ignored_clients"]) == True:
|
||||
try: i = self.check_quoted_status(i)
|
||||
except: pass
|
||||
if self.settings["general"]["reverse_timelines"] == False: self.db[name].append(i)
|
||||
else: self.db[name].insert(0, i)
|
||||
num = num+1
|
||||
@@ -119,7 +122,8 @@ class Session(object):
|
||||
# self.settings = None
|
||||
|
||||
def init_sound(self):
|
||||
self.sound = sound.soundSystem(self.settings["sound"])
|
||||
try: self.sound = sound.soundSystem(self.settings["sound"])
|
||||
except: pass
|
||||
|
||||
@_require_configuration
|
||||
def login(self, verify_credentials=True):
|
||||
@@ -318,10 +322,12 @@ class Session(object):
|
||||
for z in i.users:
|
||||
ids += str(z) + ", "
|
||||
if ids != "":
|
||||
# print ids
|
||||
stream_threaded(self.timelinesStream.statuses.filter, self.session_id, follow=ids)
|
||||
|
||||
def add_friends(self):
|
||||
try:
|
||||
# print "setting friends"
|
||||
self.timelinesStream.set_friends(self.main_stream.friends)
|
||||
except AttributeError:
|
||||
pass
|
||||
@@ -344,6 +350,7 @@ class Session(object):
|
||||
self.logged = False
|
||||
self.twitter = twitter.twitter.twitter()
|
||||
self.login(False)
|
||||
# pub.sendMessage("streamError", session=self.session_id)
|
||||
if self.reconnection_function_active == True: return
|
||||
self.reconnection_function_active = True
|
||||
if not hasattr(self, "main_stream"):
|
||||
@@ -411,3 +418,28 @@ class Session(object):
|
||||
os.remove(shelfname)
|
||||
except:
|
||||
pass
|
||||
|
||||
def check_quoted_status(self, tweet):
|
||||
status = tweets.is_long(tweet)
|
||||
if status != False:
|
||||
tweet["quoted"] = 1
|
||||
tweet = self.get_quoted_tweet(tweet)
|
||||
return tweet
|
||||
|
||||
|
||||
def get_quoted_tweet(self, tweet):
|
||||
quoted_tweet = self.twitter.twitter.show_status(id=tweet["id"])
|
||||
urls = utils.find_urls_in_text(quoted_tweet["text"])
|
||||
for url in range(0, len(urls)):
|
||||
try: quoted_tweet["text"] = quoted_tweet["text"].replace(urls[url], quoted_tweet["entities"]["urls"][url]["expanded_url"])
|
||||
except IndexError: pass
|
||||
l = tweets.is_long(quoted_tweet)
|
||||
id = tweets.get_id(l)
|
||||
try: original_tweet = self.twitter.twitter.show_status(id=id)
|
||||
except: return quoted_tweet
|
||||
urls = utils.find_urls_in_text(original_tweet["text"])
|
||||
for url in range(0, len(urls)):
|
||||
try: original_tweet["text"] = original_tweet["text"].replace(urls[url], original_tweet["entities"]["urls"][url]["expanded_url"])
|
||||
except IndexError: pass
|
||||
return compose.compose_quoted_tweet(quoted_tweet, original_tweet)
|
||||
|
||||
|
23
src/setup.py
23
src/setup.py
@@ -25,6 +25,7 @@ import gettext
|
||||
import application
|
||||
import platform
|
||||
from glob import glob
|
||||
import wx
|
||||
|
||||
def get_architecture_files():
|
||||
if platform.architecture()[0][:2] == "32":
|
||||
@@ -48,7 +49,7 @@ def get_data():
|
||||
("accessible_output2/lib", glob("accessible_output2/lib/*.dll")),
|
||||
("keys/lib", glob("keys/lib/*.dll")),
|
||||
("keymaps", glob("keymaps/*.keymap")),
|
||||
]+get_sounds()+get_locales()+get_documentation()+sound_lib.find_datafiles()+accessible_output2.find_datafiles()+enchant.utils.win32_data_files()+get_architecture_files()
|
||||
]+get_sounds()+get_locales()+get_documentation()+sound_lib.find_datafiles()+accessible_output2.find_datafiles()+enchant.utils.win32_data_files()+get_architecture_files()+wx_files()
|
||||
|
||||
def get_documentation ():
|
||||
answer = []
|
||||
@@ -79,6 +80,24 @@ def get_locales():
|
||||
answer.append(new)
|
||||
return answer
|
||||
|
||||
def wx_files():
|
||||
wxDir=wx.__path__[0]
|
||||
localeMoFiles=set()
|
||||
for f in glob("locales/*/LC_MESSAGES"):
|
||||
g=f.replace("locales", "locale")
|
||||
wxMoFile=os.path.join(wxDir,g,"wxstd.mo")
|
||||
if os.path.isfile(wxMoFile):
|
||||
localeMoFiles.add((f,(wxMoFile,)))
|
||||
lang=os.path.split(os.path.split(f)[0])[1]
|
||||
if '_' in lang:
|
||||
lang=lang.split('_')[0]
|
||||
f=os.path.join('locale',lang,'lc_messages')
|
||||
g=f.replace("locale", "locales")
|
||||
wxMoFile=os.path.join(wxDir,f,"wxstd.mo")
|
||||
if os.path.isfile(wxMoFile):
|
||||
localeMoFiles.add((g,(wxMoFile,)))
|
||||
return list(localeMoFiles)
|
||||
|
||||
if __name__ == '__main__':
|
||||
setup(
|
||||
name = application.name,
|
||||
@@ -92,7 +111,7 @@ options = {
|
||||
'py2exe': {
|
||||
'optimize':2,
|
||||
'packages': ["pubsub", "pubsub.core", "pubsub.core.kwargs", "dbhash"],
|
||||
'dll_excludes': ["MPR.dll", "api-ms-win-core-apiquery-l1-1-0.dll", "api-ms-win-core-console-l1-1-0.dll", "api-ms-win-core-delayload-l1-1-1.dll", "api-ms-win-core-errorhandling-l1-1-1.dll", "api-ms-win-core-file-l1-2-0.dll", "api-ms-win-core-handle-l1-1-0.dll", "api-ms-win-core-heap-obsolete-l1-1-0.dll", "api-ms-win-core-libraryloader-l1-1-1.dll", "api-ms-win-core-localization-l1-2-0.dll", "api-ms-win-core-processenvironment-l1-2-0.dll", "api-ms-win-core-processthreads-l1-1-1.dll", "api-ms-win-core-profile-l1-1-0.dll", "api-ms-win-core-registry-l1-1-0.dll", "api-ms-win-core-synch-l1-2-0.dll", "api-ms-win-core-sysinfo-l1-2-0.dll", "api-ms-win-security-base-l1-2-0.dll", "api-ms-win-core-heap-l1-2-0.dll", "api-ms-win-core-interlocked-l1-2-0.dll", "api-ms-win-core-localization-obsolete-l1-1-0.dll", "api-ms-win-core-string-l1-1-0.dll", "api-ms-win-core-string-obsolete-l1-1-0.dll", "WLDAP32.dll", "MSVCP90.dll"],
|
||||
'dll_excludes': ["MPR.dll", "api-ms-win-core-apiquery-l1-1-0.dll", "api-ms-win-core-console-l1-1-0.dll", "api-ms-win-core-delayload-l1-1-1.dll", "api-ms-win-core-errorhandling-l1-1-1.dll", "api-ms-win-core-file-l1-2-0.dll", "api-ms-win-core-handle-l1-1-0.dll", "api-ms-win-core-heap-obsolete-l1-1-0.dll", "api-ms-win-core-libraryloader-l1-1-1.dll", "api-ms-win-core-localization-l1-2-0.dll", "api-ms-win-core-processenvironment-l1-2-0.dll", "api-ms-win-core-processthreads-l1-1-1.dll", "api-ms-win-core-profile-l1-1-0.dll", "api-ms-win-core-registry-l1-1-0.dll", "api-ms-win-core-synch-l1-2-0.dll", "api-ms-win-core-sysinfo-l1-2-0.dll", "api-ms-win-security-base-l1-2-0.dll", "api-ms-win-core-heap-l1-2-0.dll", "api-ms-win-core-interlocked-l1-2-0.dll", "api-ms-win-core-localization-obsolete-l1-1-0.dll", "api-ms-win-core-string-l1-1-0.dll", "api-ms-win-core-string-obsolete-l1-1-0.dll", "WLDAP32.dll", "MSVCP90.dll", "CRYPT32.dll", "mfc90.dll"],
|
||||
'skip_archive': True
|
||||
},
|
||||
},
|
||||
|
23
src/sound.py
23
src/sound.py
@@ -129,24 +129,7 @@ class URLStream(object):
|
||||
self.stream.volume = float(volume)
|
||||
self.stream.play()
|
||||
log.debug("played")
|
||||
call_threaded(self.delete_when_done)
|
||||
|
||||
def is_playable(self, url,play=False,volume=1.0):
|
||||
try:
|
||||
log.debug("Checking URL playability...")
|
||||
self.prepare(url)
|
||||
if self.prepared == True:
|
||||
stream=sound_lib.stream.URLStream(url=self.url)
|
||||
if play:
|
||||
return self.play(stream=stream,volume=volume,announce=False)
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
def delete_when_done(self):
|
||||
while hasattr(self,'stream') and self.stream.is_playing:
|
||||
pass
|
||||
del self.stream
|
||||
# call_threaded(self.delete_when_done)
|
||||
|
||||
def stop_audio(self,delete=False):
|
||||
if hasattr(self, "stream"):
|
||||
@@ -156,8 +139,8 @@ class URLStream(object):
|
||||
log.debug("Stopped audio stream.")
|
||||
except:
|
||||
log.exception("Exception while stopping stream.")
|
||||
# if delete:
|
||||
# del self.stream
|
||||
if delete:
|
||||
del self.stream
|
||||
log.debug("Deleted audio stream.")
|
||||
return True
|
||||
else:
|
||||
|
@@ -21,15 +21,24 @@ class timelinesStreamer(TwythonStreamer):
|
||||
self.lists = self.session.lists
|
||||
|
||||
def on_error(self, status_code, data):
|
||||
log.debug("%s: %s" % (status_code, data))
|
||||
log.error("error in stream: %s: %s" % (status_code, data))
|
||||
# pub.sendMessage("stream-error", session=self.session.session_id)
|
||||
|
||||
def on_timeout(self, *args, **kwargs):
|
||||
log.debug("Twitter timeout Error")
|
||||
pub.sendMessage("stream-error")
|
||||
log.error("Twitter timeout Error")
|
||||
# pub.sendMessage("stream-error", session=self.session.session_id)
|
||||
|
||||
def check_tls(self, data):
|
||||
for i in self.session.settings["other_buffers"]["timelines"]:
|
||||
if data["user"]["screen_name"] == i:
|
||||
if utils.find_item(data["id"], self.session.db["%s-timeline" % (i,)]) != None:
|
||||
log.error("duplicated tweet. Ignoring it...")
|
||||
return
|
||||
try:
|
||||
data_ = self.session.check_quoted_status(data)
|
||||
data = data_
|
||||
except AttributeError:
|
||||
pass
|
||||
if self.session.settings["general"]["reverse_timelines"] == False: self.session.db["%s-timeline" % (i,)].append(data)
|
||||
else: self.session.db["%s-timeline" % (i,)].insert(0, data)
|
||||
pub.sendMessage("item-in-timeline", data= data, user= self.session.db["user_name"], who= i)
|
||||
@@ -37,14 +46,15 @@ class timelinesStreamer(TwythonStreamer):
|
||||
try:
|
||||
i.users.index(data["user"]["id"])
|
||||
usr = data["in_reply_to_user_id"]
|
||||
if (usr != None and usr in self.friends) or data.has_key("retweeted_status"):
|
||||
if (usr != None or usr in self.friends) or data.has_key("retweeted_status"):
|
||||
data = self.session.check_quoted_status(data)
|
||||
if self.session.settings["general"]["reverse_timelines"] == False: self.session.db["%s" % (i.name,)].append(data)
|
||||
else: self.session.db["%s" % (i,)].insert(0, data)
|
||||
pub.sendMessage("item-in-list", data= data, user= self.session.db["user_name"], where= i.name)
|
||||
else: self.session.db["%s" % (i.name,)].insert(0, data)
|
||||
pub.sendMessage("item-in-list", data=data, user=self.session.db["user_name"], where=i.name)
|
||||
elif usr == None:
|
||||
if self.session.settings["general"]["reverse_timelines"] == False: self.session.db["%s" % (i.name,)].append(data)
|
||||
else: self.session.db["%s" % (i,)].insert(0, data)
|
||||
pub.sendMessage("item-in-list", data= data, user= self.session.db["user_name"], where= i.name)
|
||||
else: self.session.db["%s" % (i.name,)].insert(0, data)
|
||||
pub.sendMessage("item-in-list", data=data, user=self.session.db["user_name"], where=i.name)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
|
@@ -22,22 +22,33 @@ class streamer(TwythonStreamer):
|
||||
# self.blocked_users = []
|
||||
|
||||
def on_timeout(self, *args, **kwargs):
|
||||
log.debug("Twitter timeout Error")
|
||||
pub.sendMessage("stream-error")
|
||||
log.error("Twitter timeout Error")
|
||||
# pub.sendMessage("stream-error", session=self.session.session_id)
|
||||
|
||||
def on_error(self, status_code, data):
|
||||
log.debug("Error %s: %s" % (status_code, data))
|
||||
log.error("Error %s: %s" % (status_code, data))
|
||||
# pub.sendMessage("stream-error", session=self.session.session_id)
|
||||
|
||||
def get_user(self):
|
||||
return self.session.db["user_name"]
|
||||
|
||||
def put_data(self, place, data):
|
||||
if self.session.db.has_key(place):
|
||||
if utils.find_item(data["id"], self.session.db[place]) != None:
|
||||
log.error("duplicated tweet. Ignoring it...")
|
||||
return False
|
||||
try:
|
||||
data_ = self.session.check_quoted_status(data)
|
||||
data = data_
|
||||
except:
|
||||
pass
|
||||
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||
self.session.db[place].append(data)
|
||||
else:
|
||||
self.session.db[place].insert(0, data)
|
||||
utils.is_audio(data)
|
||||
return True
|
||||
|
||||
def block_user(self, data):
|
||||
id = data["target"]["id"]
|
||||
if id in self.friends:
|
||||
@@ -54,30 +65,36 @@ class streamer(TwythonStreamer):
|
||||
|
||||
def check_send(self, data):
|
||||
if self.session.db["user_name"] == data["user"]["screen_name"]:
|
||||
self.put_data("sent_tweets", data)
|
||||
pub.sendMessage("sent-tweet", data=data, user=self.get_user())
|
||||
d = self.put_data("sent_tweets", data)
|
||||
if d != False:
|
||||
pub.sendMessage("sent-tweet", data=data, user=self.get_user())
|
||||
|
||||
def check_favs(self, data):
|
||||
if data["source"]["screen_name"] == self.session.db["user_name"]:
|
||||
self.put_data("favourites", data["target_object"])
|
||||
pub.sendMessage("favourite", data=data["target_object"], user=self.get_user())
|
||||
d = self.put_data("favourites", data["target_object"])
|
||||
if d != False:
|
||||
pub.sendMessage("favourite", data=data["target_object"], user=self.get_user())
|
||||
|
||||
def check_mentions(self, data):
|
||||
if "@%s" % (self.session.db["user_name"]) in data["text"]:
|
||||
self.put_data("mentions", data)
|
||||
pub.sendMessage("mention", data=data, user=self.get_user())
|
||||
d = self.put_data("mentions", data)
|
||||
if d != False:
|
||||
pub.sendMessage("mention", data=data, user=self.get_user())
|
||||
|
||||
def set_quoted_tweet(self, data):
|
||||
self.put_data("mentions", data)
|
||||
pub.sendMessage("mention", data=data, user=self.get_user())
|
||||
d = self.put_data("mentions", data)
|
||||
if d != False:
|
||||
pub.sendMessage("mention", data=data, user=self.get_user())
|
||||
|
||||
def process_dm(self, data):
|
||||
if self.session.db["user_name"] == data["direct_message"]["sender"]["screen_name"]:
|
||||
self.put_data("sent_direct_messages", data["direct_message"])
|
||||
pub.sendMessage("sent-dm", data=data["direct_message"], user=self.get_user())
|
||||
d = self.put_data("sent_direct_messages", data["direct_message"])
|
||||
if d != False:
|
||||
pub.sendMessage("sent-dm", data=data["direct_message"], user=self.get_user())
|
||||
else:
|
||||
self.put_data("direct_messages", data["direct_message"])
|
||||
pub.sendMessage("direct-message", data=data["direct_message"], user=self.get_user())
|
||||
d = self.put_data("direct_messages", data["direct_message"])
|
||||
if d != False:
|
||||
pub.sendMessage("direct-message", data=data["direct_message"], user=self.get_user())
|
||||
|
||||
def check_follower(self, data):
|
||||
if data["target"]["screen_name"] == self.session.db["user_name"]:
|
||||
@@ -119,8 +136,9 @@ class streamer(TwythonStreamer):
|
||||
self.check_mentions(data)
|
||||
self.check_send(data)
|
||||
if data["user"]["id"] in self.friends or data["user"]["screen_name"] == self.session.db["user_name"]:
|
||||
self.put_data("home_timeline", data)
|
||||
pub.sendMessage("item-in-home", data=data, user=self.get_user())
|
||||
d = self.put_data("home_timeline", data)
|
||||
if d != False:
|
||||
pub.sendMessage("item-in-home", data=data, user=self.get_user())
|
||||
elif data.has_key("event"):
|
||||
if "favorite" == data["event"] and "favorites" in self.session.settings["general"]["buffer_order"]:
|
||||
self.check_favs(data)
|
||||
|
@@ -10,7 +10,7 @@ import languageHandler
|
||||
import arrow
|
||||
import logging
|
||||
import config
|
||||
from long_tweets import twishort
|
||||
from long_tweets import twishort, tweets
|
||||
log = logging.getLogger("compose")
|
||||
|
||||
def StripChars(s):
|
||||
@@ -60,11 +60,33 @@ def compose_tweet(tweet, db, relative_times):
|
||||
try:
|
||||
oldtext=text
|
||||
text=twishort.get_full_text(tweet['long_uri'])
|
||||
try: text = "rt @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], StripChars(text))
|
||||
except KeyError: pass
|
||||
except:
|
||||
text=oldtext
|
||||
if tweet.has_key("message"):
|
||||
text = tweet["message"]
|
||||
return [user+", ", text, ts+", ", source]
|
||||
|
||||
tweet["text"] = text
|
||||
return [user+", ", tweet["text"], ts+", ", source]
|
||||
|
||||
def compose_quoted_tweet(quoted_tweet, original_tweet):
|
||||
""" It receives a tweet and returns a list with the user, text for the tweet or message, date and the client where user is."""
|
||||
text = StripChars(quoted_tweet["text"])
|
||||
quoting_user = quoted_tweet["user"]["name"]
|
||||
source = re.sub(r"(?s)<.*?>", "", quoted_tweet["source"])
|
||||
try: text = "rt @%s: %s" % (quoted_tweet["retweeted_status"]["user"]["screen_name"], StripChars(quoted_tweet["retweeted_status"]["text"]))
|
||||
except KeyError: text = "%s" % (StripChars(quoted_tweet["text"]))
|
||||
if text[-1] in chars: text=text+"."
|
||||
original_user = original_tweet["user"]["screen_name"]
|
||||
original_text = StripChars(original_tweet["text"])
|
||||
try: original_text = "rt @%s: %s" % (original_tweet["retweeted_status"]["user"]["screen_name"], StripChars(original_tweet["retweeted_status"]["text"]))
|
||||
except KeyError: original_text = "%s" % (StripChars(original_tweet["text"]))
|
||||
quoted_tweet["message"] = _(u"{0}. Quoted tweet from @{1}: {2}").format( quoted_tweet["text"], original_user, original_text)
|
||||
quoted_tweet = tweets.clear_url(quoted_tweet)
|
||||
return quoted_tweet
|
||||
|
||||
def compose_followers_list(tweet, db, relative_times=True):
|
||||
if system == "Windows":
|
||||
original_date = arrow.get(tweet["created_at"], "ddd MMM D H:m:s Z YYYY", locale="en")
|
||||
@@ -101,12 +123,12 @@ def compose_event(data, username):
|
||||
event = _(u"You've unfollowed %s (@%s)") % (data["target"]["name"], data["target"]["screen_name"])
|
||||
elif data["event"] == "favorite":
|
||||
if data["source"]["screen_name"] == username:
|
||||
event = _(u"You've added to favourites: %s, %s") % (data["target"]["name"], data["target_object"]["text"])
|
||||
event = _(u"You've liked: %s, %s") % (data["target"]["name"], data["target_object"]["text"])
|
||||
else:
|
||||
event = _(u"%s(@%s) has marked as favourite: %s") % (data["source"]["name"], data["source"]["screen_name"], data["target_object"]["text"])
|
||||
event = _(u"%s(@%s) has liked: %s") % (data["source"]["name"], data["source"]["screen_name"], data["target_object"]["text"])
|
||||
elif data["event"] == "unfavorite":
|
||||
if data["source"]["screen_name"] == username: event = _(u"You've removed from favourites: %s, %s") % (data["target"]["name"], data["target_object"]["text"])
|
||||
else: event = _(u"%s(@%s) has removed from favourites: %s") % (data["source"]["name"], data["source"]["screen_name"], data["target_object"]["text"])
|
||||
if data["source"]["screen_name"] == username: event = _(u"You've unliked: %s, %s") % (data["target"]["name"], data["target_object"]["text"])
|
||||
else: event = _(u"%s(@%s) has unliked: %s") % (data["source"]["name"], data["source"]["screen_name"], data["target_object"]["text"])
|
||||
elif data["event"] == "list_created":
|
||||
event = _(u"You've created the list %s") % (data["target_object"]["name"])
|
||||
elif data["event"] == "list_destroyed":
|
||||
|
@@ -53,5 +53,3 @@ class twitter(object):
|
||||
settings["twitter"]["user_secret"] = user_secret
|
||||
settings.write()
|
||||
|
||||
def __init__(self):
|
||||
log.error(certs.where())
|
@@ -1,4 +1,7 @@
|
||||
import wx
|
||||
import paths
|
||||
import languageHandler
|
||||
import sys
|
||||
|
||||
toolkit = "wx"
|
||||
|
||||
@@ -108,6 +111,15 @@ class mainLoopObject(wx.App):
|
||||
|
||||
def __init__(self):
|
||||
self.app = wx.App()
|
||||
self.lc = wx.Locale()
|
||||
lang=languageHandler.getLanguage()
|
||||
wxLang=self.lc.FindLanguageInfo(lang)
|
||||
if not wxLang and '_' in lang:
|
||||
wxLang=self.lc.FindLanguageInfo(lang.split('_')[0])
|
||||
if hasattr(sys,'frozen'):
|
||||
self.lc.AddCatalogLookupPathPrefix(paths.app_path("locales"))
|
||||
if wxLang:
|
||||
self.lc.Init(wxLang.Language)
|
||||
|
||||
def run(self):
|
||||
self.app.MainLoop()
|
||||
|
@@ -16,9 +16,11 @@ class trendsPanel(wx.Panel):
|
||||
self.create_list()
|
||||
self.tweet = wx.Button(self, -1, _(u"Tweet"))
|
||||
self.tweetTrendBtn = wx.Button(self, -1, _(u"Tweet about this trend"))
|
||||
self.search_topic = wx.Button(self, -1, _(u"Search topic"))
|
||||
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
btnSizer.Add(self.tweet, 0, wx.ALL, 5)
|
||||
btnSizer.Add(self.tweetTrendBtn, 0, wx.ALL, 5)
|
||||
btnSizer.Add(self.search_topic, 0, wx.ALL, 5)
|
||||
self.sizer.Add(btnSizer, 0, wx.ALL, 5)
|
||||
self.sizer.Add(self.list.list, 0, wx.ALL, 5)
|
||||
self.SetSizer(self.sizer)
|
||||
|
@@ -47,8 +47,14 @@ def protected_user():
|
||||
return wx.MessageDialog(None, _(u"This is a protected Twitter user, which means you can't open a timeline using the Streaming API. The user's tweets will not update due to a twitter policy. Do you want to continue?"), _(u"Warning"), wx.ICON_WARNING|wx.YES_NO).ShowModal()
|
||||
|
||||
def no_following():
|
||||
return wx.MessageDialog(None, _(u"This is a protected user account, you need to follow this user to view their tweets or favorites."), _(u"Error"), wx.ICON_ERROR).ShowModal()
|
||||
return wx.MessageDialog(None, _(u"This is a protected user account, you need to follow this user to view their tweets or likes."), _(u"Error"), wx.ICON_ERROR).ShowModal()
|
||||
|
||||
def donation():
|
||||
dlg = wx.MessageDialog(None, _(u"If you like {0} we need your help to keep it going. Help us by donating to the project. This will help us pay for the server, the domain and some other things to ensure that {0} will be actively maintained. Your donation will give us the means to continue the development of {0}, and to keep {0} free. Would you like to donate now?").format(application.name), _(u"We need your help"), wx.ICON_QUESTION|wx.YES_NO)
|
||||
return dlg.ShowModal()
|
||||
|
||||
def no_tweets():
|
||||
return wx.MessageDialog(None, _(u"This user has no tweets. {0} can't create a timeline.").format(application.name), _(u"Error"), wx.ICON_ERROR).ShowModal()
|
||||
|
||||
def no_favs():
|
||||
return wx.MessageDialog(None, _(u"This user has no favorited tweets. {0} can't create a timeline.").format(application.name), _(u"Error"), wx.ICON_ERROR).ShowModal()
|
||||
|
@@ -123,6 +123,7 @@ class removeUserListDialog(listViewer):
|
||||
self.SetTitle(_(u"Select a list to remove the user"))
|
||||
self.createBtn.SetLabel(_(u"Remove"))
|
||||
self.createBtn.SetDefault()
|
||||
self.createBtn.SetId(wx.ID_OK)
|
||||
self.editBtn.Disable()
|
||||
self.view.Disable()
|
||||
# self.subscriptors.Disable()
|
||||
|
@@ -216,7 +216,8 @@ class dm(textLimited):
|
||||
self.buttonsBox3.Add(cancelButton, 0, wx.ALL, 5)
|
||||
self.mainBox.Add(self.buttonsBox3, 0, wx.ALL, 5)
|
||||
self.panel.SetSizer(self.mainBox)
|
||||
|
||||
# self.SetClientSize(self.mainBox.CalcMin())
|
||||
|
||||
def __init__(self, title, message, users):
|
||||
super(dm, self).__init__()
|
||||
self.createControls(message, title, users)
|
||||
@@ -264,7 +265,7 @@ class viewTweet(widgetUtils.BaseDialog):
|
||||
rtBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
rtBox.Add(rtCountLabel, 0, wx.ALL, 5)
|
||||
rtBox.Add(rtCount, 0, wx.ALL, 5)
|
||||
favsCountLabel = wx.StaticText(panel, -1, _(u"Favourites: "))
|
||||
favsCountLabel = wx.StaticText(panel, -1, _(u"Likes: "))
|
||||
favsCount = wx.TextCtrl(panel, -1, favs_count, size=wx.DefaultSize, style=wx.TE_READONLY|wx.TE_MULTILINE)
|
||||
favsBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
favsBox.Add(favsCountLabel, 0, wx.ALL, 5)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user