Compare commits

...

20 Commits

Author SHA1 Message Date
93dc3ad646 New snapshot 2015-11-03 10:13:09 -06:00
8e67ed025c Changed favourites for likes 2015-11-03 10:07:06 -06:00
fa1b8bfde3 Added more keystrokes to the invisible interface 2015-11-03 09:02:19 -06:00
7dfe2cbb5c Lists should work 2015-11-03 05:56:57 -06:00
880c421f3e added check for updates to the invisible interface 2015-11-03 05:25:03 -06:00
e1b8d49af5 manage_stream_errors will only delete the stream objects 2015-11-03 04:42:38 -06:00
e1d14b8c27 Now conversation buffers are removed properly 2015-11-03 04:41:01 -06:00
594b0cd546 Translator is working properly again 2015-11-03 04:40:05 -06:00
fe9f724673 Updated accessible_output2. Add mac and a better linux support 2015-11-03 04:38:59 -06:00
6a4a3cc94e Cache com saved in data directory. Translation service restored 2015-10-31 20:57:21 -06:00
Jose Manuel Delicado
af41dcfc4e com.py: use config_path instead of data_path. Paths.py: some strings weren't appended as unicode 2015-10-24 23:01:23 +02:00
31611d8429 Merge branch 'next-gen' of https://github.com/manuelcortez/TWBlue into next-gen 2015-10-23 11:37:43 -05:00
7ed44c839e New snapshot 2015-10-23 11:36:36 -05:00
503c65692d FFix for creating favourites timelines 2015-10-23 11:33:56 -05:00
f76b86b24d A sound bugfix 2015-10-23 11:29:59 -05:00
1f96e71b63 workaround for duplicated tweets 2015-10-23 11:28:54 -05:00
Jose Manuel Delicado
cc249fe1a7 Added japanese, croatian and serbian (latin) languages to the installer 2015-10-19 12:47:52 +02:00
Jose Manuel Delicado
268bd35f3a Updated windows dependencies. Remember to run git submodule update before submiting new commits 2015-10-19 10:52:05 +02:00
Jose Manuel Delicado
0307c0abe3 Fixed com cache error 2015-10-18 22:18:43 +02:00
Jose Manuel Delicado
adf062f654 Now com cache is stored in the config folder, so program files folder keeps untouched on installed copies. Updated contributors in application.py, fixed spelling in some comments in main.py 2015-10-18 12:19:43 +02:00
51 changed files with 548 additions and 1403 deletions

View File

@@ -45,6 +45,9 @@ var StartMenuFolder
!insertmacro MUI_LANGUAGE "Galician" !insertmacro MUI_LANGUAGE "Galician"
!insertmacro MUI_LANGUAGE "Catalan" !insertmacro MUI_LANGUAGE "Catalan"
!insertmacro MUI_LANGUAGE "Basque" !insertmacro MUI_LANGUAGE "Basque"
!insertmacro MUI_LANGUAGE "Croatian"
!insertmacro MUI_LANGUAGE "Japanese"
!insertmacro MUI_LANGUAGE "SerbianLatin"
!insertmacro MUI_RESERVEFILE_LANGDLL !insertmacro MUI_RESERVEFILE_LANGDLL
Section Section
SetShellVarContext All SetShellVarContext All

View File

@@ -1,19 +1,23 @@
from __future__ import absolute_import
import ctypes import ctypes
import os import os
import types import types
from platform_utils import paths from platform_utils import paths
def load_library(libname): def load_library(libname, cdll=False):
if paths.is_frozen(): if paths.is_frozen():
libfile = os.path.join(paths.embedded_data_path(), 'accessible_output2', 'lib', libname) libfile = os.path.join(paths.embedded_data_path(), 'accessible_output2', 'lib', libname)
else: else:
libfile = os.path.join(paths.module_path(), 'lib', libname) 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(): def get_output_classes():
import outputs from . import outputs
module_type = types.ModuleType 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) return sorted(classes, key=lambda c: c.priority)
def find_datafiles(): def find_datafiles():

View File

@@ -1,16 +1,20 @@
from __future__ import absolute_import
import platform import platform
if platform.system() == 'Windows': if platform.system() == 'Windows':
import nvda from . import nvda
import jaws from . import jaws
import sapi5 from . import sapi5
import window_eyes from . import window_eyes
import system_access from . import system_access
import dolphin from . import dolphin
import pc_talker from . import pc_talker
#import sapi4 #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

View File

@@ -1,24 +1,17 @@
import platform from __future__ import absolute_import
import accessible_output2 import accessible_output2
from base import Output, OutputError from .base import Output, OutputError
class Auto(Output): class Auto(Output):
def __init__(self): def __init__(self):
if platform.system() == "Darwin": output_classes = accessible_output2.get_output_classes()
import voiceover self.outputs = []
self.outputs = [voiceover.VoiceOver()] for output in output_classes:
elif platform.system() == "Linux": try:
import speechDispatcher self.outputs.append(output())
self.outputs = [speechDispatcher.SpeechDispatcher()] except OutputError:
elif platform.system() == "Windows": 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): def get_first_available_output(self):
for output in self.outputs: for output in self.outputs:
@@ -40,3 +33,8 @@ class Auto(Output):
output = self.get_first_available_output() output = self.get_first_available_output()
if output: if output:
output.speak(*args, **kwargs) output.speak(*args, **kwargs)
def is_system_output(self):
output = self.get_first_available_output()
if output:
return output.is_system_output()

View File

@@ -5,27 +5,43 @@ class OutputError(Exception):
pass pass
class Output(object): class Output(object):
name = "Unnamed Output" #The name of this output name = "Unnamed Output"
lib32 = None #name of 32-bit lib lib32 = None
lib64 = None #name of 64-bit lib lib64 = None
priority = 100 #Where to sort in the list of available outputs for automaticly speaking argtypes = {}
cdll = False
priority = 100
system_output = False
def __init__(self): def __init__(self):
is_32bit = platform.architecture()[0] == "32bit" self.is_32bit = platform.architecture()[0] == "32bit"
if self.lib32 and is_32bit: if self.lib32 and self.is_32bit:
self.lib = load_library(self.lib32) self.lib = load_library(self.lib32, cdll=self.cdll)
elif self.lib64: 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): def output(self, text, **options):
output = False output = False
if hasattr(self, 'speak') and callable(self.speak): if self.speak(text, **options):
self.speak(text, **options)
output = True output = True
if hasattr(self, 'braille') and callable(self.braille): if self.braille(text, **options):
self.braille(text, **options)
output = True output = True
if not output: if not output:
raise RuntimeError("Output %r does not have any method defined to output" % self) 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

View File

@@ -1,19 +1,25 @@
from __future__ import absolute_import
import os import os
import ctypes
from base import Output from .base import Output
class Dolphin (Output): class Dolphin (Output):
"""Supports dolphin products.""" """Supports dolphin products."""
name = 'Dolphin' name = 'Dolphin'
lib32 = 'dolapi.dll' 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): def speak(self, text, interrupt=0):
if interrupt: if interrupt:
self.silence() self.silence()
#If we don't call this, the API won't let us speak. #If we don't call this, the API won't let us speak.
if self.is_active(): 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): def silence(self):
self.lib.DolAccess_Action(141) self.lib.DolAccess_Action(141)

View 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

View File

@@ -1,8 +1,9 @@
from __future__ import absolute_import
import win32gui import win32gui
from libloader.com import load_com from libloader.com import load_com
import pywintypes import pywintypes
from base import Output, OutputError from .base import Output, OutputError
class Jaws (Output): class Jaws (Output):
"""Output supporting the Jaws for Windows screen reader.""" """Output supporting the Jaws for Windows screen reader."""

View File

@@ -1,15 +1,21 @@
from __future__ import absolute_import
import os import os
import platform import platform
import ctypes
from platform_utils import paths from platform_utils import paths
from libloader import load_library from libloader import load_library
from base import Output from .base import Output
class NVDA(Output): class NVDA(Output):
"""Supports The NVDA screen reader""" """Supports The NVDA screen reader"""
name = "NVDA" name = "NVDA"
lib32 = 'nvdaControllerClient32.dll' lib32 = 'nvdaControllerClient32.dll'
lib64 = 'nvdaControllerClient64.dll' lib64 = 'nvdaControllerClient64.dll'
argtypes = {
'nvdaController_brailleMessage': (ctypes.c_wchar_p,),
'nvdaController_speakText': (ctypes.c_wchar_p,),
}
def is_active(self): def is_active(self):
try: try:
@@ -18,12 +24,12 @@ class NVDA(Output):
return False return False
def braille(self, text, **options): def braille(self, text, **options):
self.lib.nvdaController_brailleMessage(unicode(text)) self.lib.nvdaController_brailleMessage(text)
def speak(self, text, interrupt=False): def speak(self, text, interrupt=False):
if interrupt: if interrupt:
self.silence() self.silence()
self.lib.nvdaController_speakText(unicode(text)) self.lib.nvdaController_speakText(text)
def silence(self): def silence(self):
self.lib.nvdaController_cancelSpeech() self.lib.nvdaController_cancelSpeech()

View File

@@ -1,14 +1,19 @@
from __future__ import absolute_import
import ctypes import ctypes
from base import Output from .base import Output
class PCTalker(Output): class PCTalker(Output):
lib32 = 'pctkusr.dll' lib32 = 'pctkusr.dll'
lib64 = 'pctkusr64.dll' lib64 = 'pctkusr64.dll'
cdll = True
argtypes = {
'PCTKPRead': (ctypes.c_char_p, ctypes.c_int, ctypes.c_int)
}
def speak(self, text, interrupt=False): def speak(self, text, interrupt=False):
if interrupt: if interrupt:
self.silence() self.silence()
self.lib.PCTKPRead(text.encode('cp932', 'replace')) self.lib.PCTKPRead(text.encode('cp932', 'replace'), 0, 1)
def silence(self): def silence(self):
self.lib.PCTKVReset() self.lib.PCTKVReset()

View File

@@ -1,5 +1,7 @@
from __future__ import absolute_import
from builtins import range
from libloader.com import load_com from libloader.com import load_com
from base import Output from .base import Output
import logging import logging
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@@ -1,12 +1,19 @@
# -*- coding: utf-8 -*- from __future__ import absolute_import
import config
from collections import OrderedDict from collections import OrderedDict
from libloader.com import load_com from libloader.com import load_com
from base import Output, OutputError from .base import Output, OutputError
import pywintypes import pywintypes
import logging import logging
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
SVSFDefault = 0
SVSFlagsAsync = 1
SVSFPurgeBeforeSpeak = 2
SVSFIsFilename = 4
SVSFIsXML = 8
SVSFIsNotXML = 16
SVSFPersistXML = 32
class SAPI5(Output): class SAPI5(Output):
has_volume = True has_volume = True
has_rate = True has_rate = True
@@ -19,9 +26,9 @@ class SAPI5(Output):
max_volume = 100 max_volume = 100
name = "sapi5" name = "sapi5"
priority = 101 priority = 101
system_output = True
def __init__(self): def __init__(self):
if config.app["app-settings"]["voice_enabled"] == False: raise OutputError
try: try:
self.object = load_com("SAPI.SPVoice") self.object = load_com("SAPI.SPVoice")
self._voices = self._available_voices() self._voices = self._available_voices()
@@ -36,14 +43,14 @@ class SAPI5(Output):
return _voices return _voices
def list_voices(self): def list_voices(self):
return self.available_voices.keys() return list(self._voices.keys())
def get_voice(self): def get_voice(self):
return self.object.Voice.GetDescription() return self.object.Voice.GetDescription()
def set_voice(self, value): def set_voice(self, value):
log.debug("Setting SAPI5 voice to \"%s\"" % 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 # For some reason SAPI5 does not reset audio after changing the voice
# By setting the audio device after changing voices seems to fix this # By setting the audio device after changing voices seems to fix this
# This was noted from information at: # This was noted from information at:
@@ -75,10 +82,10 @@ class SAPI5(Output):
self.silence() self.silence()
# We need to do the pitch in XML here # We need to do the pitch in XML here
textOutput = "<pitch absmiddle=\"%d\">%s</pitch>" % (round(self._pitch), text.replace("<", "&lt;")) textOutput = "<pitch absmiddle=\"%d\">%s</pitch>" % (round(self._pitch), text.replace("<", "&lt;"))
self.object.Speak(textOutput, 1|8) self.object.Speak(textOutput, SVSFlagsAsync | SVSFIsXML)
def silence(self): def silence(self):
self.object.Speak("", 3) self.object.Speak("", SVSFlagsAsync | SVSFPurgeBeforeSpeak)
def is_active(self): def is_active(self):
if self.object: if self.object:

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -1 +0,0 @@
SPD_SPAWN_CMD = "/usr/bin/speech-dispatcher"

View File

@@ -1,18 +1,24 @@
from base import Output from __future__ import absolute_import
import ctypes
from .base import Output
class SystemAccess (Output): class SystemAccess (Output):
"""Supports System Access and System Access Mobile""" """Supports System Access and System Access Mobile"""
name = "System Access" name = "System Access"
lib32 = 'saapi32.dll' lib32 = 'saapi32.dll'
argtypes = {
'SA_BrlShowTextW': (ctypes.c_wchar_p,),
'SA_SayW': (ctypes.c_wchar_p,),
}
priority = 99 priority = 99
def braille(self, text, **options): def braille(self, text, **options):
self.lib.SA_BrlShowTextW(unicode(text)) self.lib.SA_BrlShowTextW(text)
def speak(self, text, interrupt=False): def speak(self, text, interrupt=False):
if self.is_active(): if self.is_active():
self.dll.SA_SayW(unicode(text)) self.dll.SA_SayW(str(text))
def is_active(self): def is_active(self):
try: try:

View File

@@ -1,23 +1 @@
from base import Output, OutputError from __future__ import absolute_import
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

View File

@@ -1,6 +1,7 @@
from __future__ import absolute_import
import win32gui import win32gui
from libloader.com import load_com from libloader.com import load_com
from base import Output, OutputError from .base import Output, OutputError
import pywintypes import pywintypes
class WindowEyes (Output): class WindowEyes (Output):

View File

@@ -5,11 +5,11 @@ if snapshot == False:
version = "0.80" version = "0.80"
update_url = 'http://twblue.es/updates/twblue_ngen.json' update_url = 'http://twblue.es/updates/twblue_ngen.json'
else: else:
version = "10.92" version = "10.95"
update_url = 'http://twblue.es/updates/snapshots_ngen.json' 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" 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.") 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"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)"] 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" url = u"http://twblue.es"

View File

@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import time
import platform import platform
if platform.system() == "Windows": if platform.system() == "Windows":
import wx import wx
@@ -42,6 +43,7 @@ class bufferController(object):
self.account = "" self.account = ""
self.needs_init = True self.needs_init = True
self.invisible = False # False if the buffer will be ignored on the invisible interface. self.invisible = False # False if the buffer will be ignored on the invisible interface.
self.execution_time = 0
def clear_list(self): pass def clear_list(self): pass
@@ -271,15 +273,19 @@ class baseBufferController(bufferController):
return (tweet, tweetsList) return (tweet, tweetsList)
def start_stream(self): def start_stream(self):
log.debug("Starting stream for buffer %s, account %s and type %s" % (self.name, self.account, self.type)) # starts stream every 3 minutes.
log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs)) current_time = time.time()
val = self.session.call_paged(self.function, *self.args, **self.kwargs) if self.execution_time == 0 or current_time-self.execution_time >= 180:
number_of_items = self.session.order_buffer(self.name, val) self.execution_time = current_time
log.debug("Number of items retrieved: %d" % (number_of_items,)) log.debug("Starting stream for buffer %s, account %s and type %s" % (self.name, self.account, self.type))
self.put_items_on_list(number_of_items) log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs))
if self.sound == None: return val = self.session.call_paged(self.function, *self.args, **self.kwargs)
if number_of_items > 0 and self.name != "sent_tweets" and self.name != "sent_direct_messages": number_of_items = self.session.order_buffer(self.name, val)
self.session.sound.play(self.sound) 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): def get_more_items(self):
elements = [] elements = []
@@ -531,7 +537,7 @@ class baseBufferController(bufferController):
# @_tweets_exist # @_tweets_exist
def audio(self, url='', *args, **kwargs): def audio(self, url='', *args, **kwargs):
if hasattr(sound.URLPlayer,'stream'): if hasattr(sound.URLPlayer,'stream') and sound.URLPlayer.stream.is_playing == True:
return sound.URLPlayer.stop_audio(delete=True) return sound.URLPlayer.stop_audio(delete=True)
tweet = self.get_tweet() tweet = self.get_tweet()
if tweet == None: return if tweet == None: return
@@ -739,12 +745,14 @@ class peopleBufferController(baseBufferController):
if hasattr(message.message, "destroy"): message.message.destroy() if hasattr(message.message, "destroy"): message.message.destroy()
def start_stream(self): def start_stream(self):
log.debug("Starting stream for %s buffer, %s account" % (self.name, self.account,)) # starts stream every 3 minutes.
log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs)) current_time = time.time()
val = self.session.get_cursored_stream(self.name, self.function, *self.args, **self.kwargs) if self.execution_time == 0 or current_time-self.execution_time >= 180:
# self.session.order_cursored_buffer(self.name, self.session.db[self.name]) self.execution_time = current_time
# log.debug("Number of items retrieved: %d" % (val,)) log.debug("Starting stream for %s buffer, %s account" % (self.name, self.account,))
self.put_items_on_list(val) 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): def get_more_items(self):
try: try:
@@ -834,17 +842,21 @@ class peopleBufferController(baseBufferController):
class searchBufferController(baseBufferController): class searchBufferController(baseBufferController):
def start_stream(self): def start_stream(self):
log.debug("Starting stream for %s buffer, %s account and %s type" % (self.name, self.account, self.type)) # starts stream every 3 minutes.
log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs)) current_time = time.time()
log.debug("Function: %s" % (self.function,)) 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: # try:
val = self.session.search(self.name, *self.args, **self.kwargs) val = self.session.search(self.name, *self.args, **self.kwargs)
# except: # except:
# return None # return None
num = self.session.order_buffer(self.name, val) num = self.session.order_buffer(self.name, val)
self.put_items_on_list(num) self.put_items_on_list(num)
if num > 0: if num > 0:
self.session.sound.play("search_updated.ogg") self.session.sound.play("search_updated.ogg")
def remove_buffer(self): def remove_buffer(self):
dlg = commonMessageDialogs.remove_buffer() dlg = commonMessageDialogs.remove_buffer()
@@ -868,18 +880,22 @@ class searchPeopleBufferController(peopleBufferController):
self.function = function self.function = function
def start_stream(self): def start_stream(self):
log.debug("starting stream for %s buffer, %s account and %s type" % (self.name, self.account, self.type)) # starts stream every 3 minutes.
log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs)) current_time = time.time()
log.debug("Function: %s" % (self.function,)) 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: # try:
val = self.session.call_paged(self.function, *self.args, **self.kwargs) val = self.session.call_paged(self.function, *self.args, **self.kwargs)
# except: # except:
# return # return
number_of_items = self.session.order_cursored_buffer(self.name, val) number_of_items = self.session.order_cursored_buffer(self.name, val)
log.debug("Number of items retrieved: %d" % (number_of_items,)) log.debug("Number of items retrieved: %d" % (number_of_items,))
self.put_items_on_list(number_of_items) self.put_items_on_list(number_of_items)
if number_of_items > 0: if number_of_items > 0:
self.session.sound.play("search_updated.ogg") self.session.sound.play("search_updated.ogg")
def remove_buffer(self): def remove_buffer(self):
dlg = commonMessageDialogs.remove_buffer() dlg = commonMessageDialogs.remove_buffer()
@@ -911,15 +927,19 @@ class trendsBufferController(bufferController):
self.reply = self.search_topic self.reply = self.search_topic
def start_stream(self): def start_stream(self):
try: # starts stream every 3 minutes.
data = self.session.call_paged("get_place_trends", id=self.trendsFor) current_time = time.time()
except: if self.execution_time == 0 or current_time-self.execution_time >= 180:
return self.execution_time = current_time
if not hasattr(self, "name_"): try:
self.name_ = data[0]["locations"][0]["name"] data = self.session.call_paged("get_place_trends", id=self.trendsFor)
self.trends = data[0]["trends"] except:
self.put_items_on_the_list() return
self.session.sound.play(self.sound) 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): def put_items_on_the_list(self):
selected_item = self.buffer.list.get_selected() selected_item = self.buffer.list.get_selected()
@@ -1004,30 +1024,42 @@ class trendsBufferController(bufferController):
class conversationBufferController(searchBufferController): class conversationBufferController(searchBufferController):
def start_stream(self, start=False): def start_stream(self, start=False):
if start == True: # starts stream every 3 minutes.
self.statuses = [] current_time = time.time()
self.ids = [] if self.execution_time == 0 or current_time-self.execution_time >= 180:
self.statuses.append(self.tweet) self.execution_time = current_time
self.ids.append(self.tweet["id"]) if start == True:
tweet = self.tweet self.statuses = []
while tweet["in_reply_to_status_id"] != None: self.ids = []
tweet = self.session.twitter.twitter.show_status(id=tweet["in_reply_to_status_id"]) self.statuses.append(self.tweet)
self.statuses.insert(0, tweet) self.ids.append(self.tweet["id"])
self.ids.append(tweet["id"]) tweet = self.tweet
if tweet["in_reply_to_status_id"] == None: while tweet["in_reply_to_status_id"] != None:
self.kwargs["since_id"] = tweet["id"] tweet = self.session.twitter.twitter.show_status(id=tweet["in_reply_to_status_id"])
self.ids.append(tweet["id"]) self.statuses.insert(0, tweet)
val2 = self.session.search(self.name, *self.args, **self.kwargs) self.ids.append(tweet["id"])
for i in val2: if tweet["in_reply_to_status_id"] == None:
if i["in_reply_to_status_id"] in self.ids: self.kwargs["since_id"] = tweet["id"]
self.statuses.append(i) self.ids.append(tweet["id"])
self.ids.append(i["id"]) val2 = self.session.search(self.name, *self.args, **self.kwargs)
tweet = i for i in val2:
number_of_items = self.session.order_buffer(self.name, self.statuses) if i["in_reply_to_status_id"] in self.ids:
log.debug("Number of items retrieved: %d" % (number_of_items,)) self.statuses.append(i)
self.put_items_on_list(number_of_items) self.ids.append(i["id"])
if number_of_items > 0: tweet = i
self.session.sound.play("search_updated.ogg") 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): class pocketBufferController(baseBufferController):
def __init__(self, parent, name, sessionObject, account, sound=None, function=None, bufferType=None, *args, **kwargs): def __init__(self, parent, name, sessionObject, account, sound=None, function=None, bufferType=None, *args, **kwargs):

View File

@@ -307,7 +307,7 @@ class Controller(object):
favourites = buffersController.baseBufferController(self.view.nb, "get_favorites", "favourites", session, session.db["user_name"]) favourites = buffersController.baseBufferController(self.view.nb, "get_favorites", "favourites", session, session.db["user_name"])
self.buffers.append(favourites) 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': elif i == 'followers':
followers = buffersController.peopleBufferController(self.view.nb, "get_followers_list", "followers", session, session.db["user_name"], screen_name=session.db["user_name"]) 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) self.buffers.append(followers)
@@ -337,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"])) 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"]) favs_timelines = buffersController.emptyPanel(self.view.nb, "favs_timelines", session.db["user_name"])
self.buffers.append(favs_timelines) 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"]: 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) 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.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 = RepeatingTimer(300, tl.start_stream)
tl.timer.start() tl.timer.start()
lists = buffersController.emptyPanel(self.view.nb, "lists", session.db["user_name"]) lists = buffersController.emptyPanel(self.view.nb, "lists", session.db["user_name"])
@@ -779,14 +779,14 @@ class Controller(object):
if usr["favourites_count"] == 0: if usr["favourites_count"] == 0:
commonMessageDialogs.no_favs() commonMessageDialogs.no_favs()
return return
if dlg.get_user() in buffer.session.settings["other_buffers"]["favourites_timelines"]: if dlg.get_user() in buff.session.settings["other_buffers"]["favourites_timelines"]:
commonMessageDialogs.timeline_exist() commonMessageDialogs.timeline_exist()
return return
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()) 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"]) pos=self.view.search("favs_timelines", buff.session.db["user_name"])
self.insert_buffer(tl, pos+1) self.insert_buffer(tl, pos+1)
# self.buffers.insert(pos+1, tl) # 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.start_stream()
tl.timer = RepeatingTimer(300, tl.start_stream) tl.timer = RepeatingTimer(300, tl.start_stream)
tl.timer.start() tl.timer.start()
@@ -1226,7 +1226,7 @@ class Controller(object):
def manage_item_in_list(self, data, user, where): def manage_item_in_list(self, data, user, where):
buffer = self.search_buffer("%s" % (where,), user) buffer = self.search_buffer("%s" % (where,), user)
if buffer == None: return 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"]: if "%s" % (where,) not in buffer.session.settings["other_buffers"]["muted_buffers"]:
self.notify(buffer.session, play_sound=play_sound) self.notify(buffer.session, play_sound=play_sound)
output.speak(_(u"One tweet from %s") % (data["user"]["name"])) output.speak(_(u"One tweet from %s") % (data["user"]["name"]))
@@ -1248,16 +1248,20 @@ class Controller(object):
log.error(" Restarting %s session streams. It will be destroyed" % (session,)) log.error(" Restarting %s session streams. It will be destroyed" % (session,))
s = session_.sessions[session] s = session_.sessions[session]
try: try:
if hasattr(s, "main_stream"): del s.main_stream if hasattr(s, "main_stream"):
self.main_stream.disconnect()
log.error("main stream disconnected")
del s.main_stream
self.timelinesStream.disconnect()
del s.timelinesStream del s.timelinesStream
s.counter = 0 s.counter = 0
s.reconnection_function_active = False s.reconnection_function_active = False
except AttributeError: except AttributeError:
log.error("Error deleting some thing") log.error("Error deleting some thing")
for i in self.buffers: # for i in self.buffers:
if i.invisible == True and i.session.session_id == s.session_id and i.type != "people": # if i.invisible == True and i.session.session_id == s.session_id and i.type != "people":
i.start_stream() # i.start_stream()
s.listen_stream_error() # s.listen_stream_error()
def check_connection(self): def check_connection(self):
for i in session_.sessions: for i in session_.sessions:
@@ -1270,7 +1274,7 @@ class Controller(object):
if buffer == "favourites": if buffer == "favourites":
favourites = buffersController.baseBufferController(self.view.nb, "get_favorites", "favourites", buff.session, buff.session.db["user_name"]) favourites = buffersController.baseBufferController(self.view.nb, "get_favorites", "favourites", buff.session, buff.session.db["user_name"])
self.buffers.append(favourites) 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() favourites.start_stream()
if buffer == "followers": 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"]) followers = buffersController.peopleBufferController(self.view.nb, "get_followers_list", "followers", buff.session, buff.session.db["user_name"], screen_name=buff.session.db["user_name"])

View File

@@ -38,7 +38,7 @@ class basicTweet(object):
text_to_translate = self.message.get_text().encode("utf-8") text_to_translate = self.message.get_text().encode("utf-8")
source = [x[0] for x in translator.translator.available_languages()][dlg.get("source_lang")] 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")] 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.set_text(msg)
self.message.text_focus() self.message.text_focus()
output.speak(_(u"Translated")) output.speak(_(u"Translated"))
@@ -168,9 +168,9 @@ class viewTweet(basicTweet):
text = "" text = ""
for i in xrange(0, len(tweetList)): for i in xrange(0, len(tweetList)):
if tweetList[i].has_key("retweeted_status"): 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: 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"]) rt_count = str(tweet["retweet_count"])
favs_count = str(tweet["favorite_count"]) favs_count = str(tweet["favorite_count"])
if text == "": if text == "":
@@ -178,6 +178,7 @@ class viewTweet(basicTweet):
text = "rt @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], tweet["retweeted_status"]["text"]) text = "rt @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], tweet["retweeted_status"]["text"])
else: else:
text = tweet["text"] text = tweet["text"]
text = self.clear_text(text)
self.message = message.viewTweet(text, rt_count, favs_count) self.message = message.viewTweet(text, rt_count, favs_count)
self.message.set_title(len(text)) self.message.set_title(len(text))
else: else:
@@ -194,3 +195,10 @@ class viewTweet(basicTweet):
if len(utils.find_urls_in_text(self.message.get_text())) > 0: if len(utils.find_urls_in_text(self.message.get_text())) > 0:
return True return True
return False 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

View File

@@ -95,7 +95,7 @@ class profileController(object):
else: verified = _(u"No") else: verified = _(u"No")
string = string+ _(u"Verified: %s\n") % (verified) string = string+ _(u"Verified: %s\n") % (verified)
string = string+ _(u"Tweets: %s\n") % (self.data["statuses_count"]) 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 return string
def visit_url(self, *args, **kwargs): def visit_url(self, *args, **kwargs):

View File

@@ -7,8 +7,8 @@ actions = reverse_sort.reverse_sort([ ("audio", _(u"Audio tweet.")),
("dm_received", _(u"Direct message received.")), ("dm_received", _(u"Direct message received.")),
("dm_sent", _(u"Direct message sent.")), ("dm_sent", _(u"Direct message sent.")),
("error", _(u"Error.")), ("error", _(u"Error.")),
("favourite", _(u"Tweet favourited.")), ("favourite", _(u"Tweet liked.")),
("favourites_timeline_updated", _(u"Favourites buffer updated.")), ("favourites_timeline_updated", _(u"Likes buffer updated.")),
("geo", _(u"Geotweet.")), ("geo", _(u"Geotweet.")),
("limit", _(u"Boundary reached.")), ("limit", _(u"Boundary reached.")),
("list_tweet", _(u"List updated.")), ("list_tweet", _(u"List updated.")),

View File

@@ -1,9 +1,153 @@
#!/usr/bin/env python # encoding: utf-8
import goslate #
# 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): import os
gs = goslate.Goslate() import re
return gs.translate(text, target_lang, source_lang) 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 = { languages = {
"af": _(u"Afrikaans"), "af": _(u"Afrikaans"),

View File

@@ -1,5 +1,4 @@
import win32com.client import win32com.client
def fix(): def fix():
if win32com.client.gencache.is_readonly == True: if win32com.client.gencache.is_readonly == True:
win32com.client.gencache.is_readonly = False win32com.client.gencache.is_readonly = False

View File

@@ -28,3 +28,7 @@ repeat_item = string(default="control+win+space")
copy_to_clipboard = string(default="control+win+shift+c") copy_to_clipboard = string(default="control+win+shift+c")
search = string(default="control+win+/") search = string(default="control+win+/")
find = string(default="control+win+shift+/") 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")

View File

@@ -47,3 +47,7 @@ view_user_lists = string(default="win+alt+shift+l")
reverse_geocode = string(default="control+win+g") reverse_geocode = string(default="control+win+g")
view_reverse_geocode = string(default="control+win+shift+g") view_reverse_geocode = string(default="control+win+shift+g")
get_trending_topics = string(default="control+win+shift+t") 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")

View File

@@ -49,3 +49,7 @@ get_more_items = string(default="alt+win+pageup")
reverse_geocode = string(default="alt+win+g") reverse_geocode = string(default="alt+win+g")
view_reverse_geocode = string(default="alt+win+shift+g") view_reverse_geocode = string(default="alt+win+shift+g")
get_trending_topics = string(default="alt+win+t") 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")

View File

@@ -50,3 +50,7 @@ get_more_items = string(default="alt+win+pageup")
reverse_geocode = string(default="control+win+g") reverse_geocode = string(default="control+win+g")
view_reverse_geocode = string(default="control+win+shift+g") view_reverse_geocode = string(default="control+win+shift+g")
get_trending_topics = string(default="control+win+t") 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")

View File

@@ -50,3 +50,7 @@ reverse_geocode = string(default="control+win+g")
view_reverse_geocode = string(default="control+win+shift+g") view_reverse_geocode = string(default="control+win+shift+g")
get_trending_topics = string(default="control+win+t") get_trending_topics = string(default="control+win+t")
find = string(default="control+win+{") 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")

View File

@@ -11,8 +11,8 @@ actions = {
"post_reply": _(u"Reply"), "post_reply": _(u"Reply"),
"post_retweet": _(u"Retweet"), "post_retweet": _(u"Retweet"),
"send_dm": _(u"Send direct message"), "send_dm": _(u"Send direct message"),
"add_to_favourites": _(u"Mark as favourite"), "add_to_favourites": _(u"Like a tweet"),
"remove_from_favourites": _(u"Remove from favourites"), "remove_from_favourites": _(u"Unlike a tweet"),
"follow": _(u"Open the user actions dialogue"), "follow": _(u"Open the user actions dialogue"),
"user_details": _(u"See user details"), "user_details": _(u"See user details"),
"view_item": _(u"Show tweet"), "view_item": _(u"Show tweet"),
@@ -46,4 +46,8 @@ actions = {
"view_reverse_geocode": _(u"Display the tweet's geolocation in a dialog"), "view_reverse_geocode": _(u"Display the tweet's geolocation in a dialog"),
"get_trending_topics": _(u"Create a trending topics buffer"), "get_trending_topics": _(u"Create a trending topics buffer"),
"open_conversation": _(u"View conversation"), "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"),
} }

View File

@@ -1,13 +1,26 @@
from pywintypes import com_error 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 from win32com.client import gencache
fixed=False
def prepare_gencache(): def prepare_gencache():
gencache.is_readonly = False gencache.is_readonly = False
gencache.GetGeneratePath() gencache.GetGeneratePath()
def patched_getmodule(modname):
mod=__import__(modname)
return sys.modules[modname]
def load_com(*names): def load_com(*names):
global fixed
if fixed==False:
gencache._GetModule=patched_getmodule
fixed=True
result = None result = None
for name in names: for name in names:
try: try:

View File

@@ -23,7 +23,7 @@ import application
import keys import keys
from mysc.thread_utils import call_threaded from mysc.thread_utils import call_threaded
import fixes 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 widgetUtils
import webbrowser import webbrowser
from wxUI import commonMessageDialogs from wxUI import commonMessageDialogs
@@ -53,13 +53,13 @@ log = logging.getLogger("main")
def setup(): def setup():
log.debug("Starting " + application.name + " %s" % (application.version,)) log.debug("Starting " + application.name + " %s" % (application.version,))
config.setup() config.setup()
fixes.setup()
log.debug("Using %s %s" % (platform.system(), platform.architecture()[0])) log.debug("Using %s %s" % (platform.system(), platform.architecture()[0]))
log.debug("Application path is %s" % (paths.app_path(),)) log.debug("Application path is %s" % (paths.app_path(),))
log.debug("config path is %s" % (paths.config_path(),)) log.debug("config path is %s" % (paths.config_path(),))
sound.setup() sound.setup()
output.setup() output.setup()
languageHandler.setLanguage(config.app["app-settings"]["language"]) languageHandler.setLanguage(config.app["app-settings"]["language"])
fixes.setup()
keys.setup() keys.setup()
from controller import mainController from controller import mainController
from sessionmanager import sessionManager from sessionmanager import sessionManager

View File

@@ -29,7 +29,7 @@ def config_path():
if directory != None: path = os.path.join(directory, "config") if directory != None: path = os.path.join(directory, "config")
elif directory == None: path = app_path(u"config") elif directory == None: path = app_path(u"config")
elif mode == "installed": elif mode == "installed":
path = data_path("config") path = data_path(u"config")
if not os.path.exists(path): if not os.path.exists(path):
log.debug("%s path does not exist, creating..." % (path,)) log.debug("%s path does not exist, creating..." % (path,))
os.mkdir(path) os.mkdir(path)
@@ -42,7 +42,7 @@ def logs_path():
if directory != None: path = os.path.join(directory, "logs") if directory != None: path = os.path.join(directory, "logs")
elif directory == None: path = app_path(u"logs") elif directory == None: path = app_path(u"logs")
elif mode == "installed": elif mode == "installed":
path = data_path("logs") path = data_path(u"logs")
if not os.path.exists(path): if not os.path.exists(path):
log.debug("%s path does not exist, creating..." % (path,)) log.debug("%s path does not exist, creating..." % (path,))
os.mkdir(path) os.mkdir(path)

View File

@@ -322,10 +322,12 @@ class Session(object):
for z in i.users: for z in i.users:
ids += str(z) + ", " ids += str(z) + ", "
if ids != "": if ids != "":
# print ids
stream_threaded(self.timelinesStream.statuses.filter, self.session_id, follow=ids) stream_threaded(self.timelinesStream.statuses.filter, self.session_id, follow=ids)
def add_friends(self): def add_friends(self):
try: try:
# print "setting friends"
self.timelinesStream.set_friends(self.main_stream.friends) self.timelinesStream.set_friends(self.main_stream.friends)
except AttributeError: except AttributeError:
pass pass
@@ -348,7 +350,7 @@ class Session(object):
self.logged = False self.logged = False
self.twitter = twitter.twitter.twitter() self.twitter = twitter.twitter.twitter()
self.login(False) self.login(False)
pub.sendMessage("streamError", session=self.session_id) # pub.sendMessage("streamError", session=self.session_id)
if self.reconnection_function_active == True: return if self.reconnection_function_active == True: return
self.reconnection_function_active = True self.reconnection_function_active = True
if not hasattr(self, "main_stream"): if not hasattr(self, "main_stream"):

View File

@@ -139,8 +139,8 @@ class URLStream(object):
log.debug("Stopped audio stream.") log.debug("Stopped audio stream.")
except: except:
log.exception("Exception while stopping stream.") log.exception("Exception while stopping stream.")
# if delete: if delete:
# del self.stream del self.stream
log.debug("Deleted audio stream.") log.debug("Deleted audio stream.")
return True return True
else: else:

View File

@@ -37,7 +37,7 @@ class timelinesStreamer(TwythonStreamer):
try: try:
data_ = self.session.check_quoted_status(data) data_ = self.session.check_quoted_status(data)
data = data_ data = data_
except: except AttributeError:
pass pass
if self.session.settings["general"]["reverse_timelines"] == False: self.session.db["%s-timeline" % (i,)].append(data) 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) else: self.session.db["%s-timeline" % (i,)].insert(0, data)
@@ -46,15 +46,15 @@ class timelinesStreamer(TwythonStreamer):
try: try:
i.users.index(data["user"]["id"]) i.users.index(data["user"]["id"])
usr = data["in_reply_to_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) data = self.session.check_quoted_status(data)
if self.session.settings["general"]["reverse_timelines"] == False: self.session.db["%s" % (i.name,)].append(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) 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) pub.sendMessage("item-in-list", data=data, user=self.session.db["user_name"], where=i.name)
elif usr == None: elif usr == None:
if self.session.settings["general"]["reverse_timelines"] == False: self.session.db["%s" % (i.name,)].append(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) 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) pub.sendMessage("item-in-list", data=data, user=self.session.db["user_name"], where=i.name)
except ValueError: except ValueError:
pass pass

View File

@@ -36,7 +36,7 @@ class streamer(TwythonStreamer):
if self.session.db.has_key(place): if self.session.db.has_key(place):
if utils.find_item(data["id"], self.session.db[place]) != None: if utils.find_item(data["id"], self.session.db[place]) != None:
log.error("duplicated tweet. Ignoring it...") log.error("duplicated tweet. Ignoring it...")
return return False
try: try:
data_ = self.session.check_quoted_status(data) data_ = self.session.check_quoted_status(data)
data = data_ data = data_
@@ -47,6 +47,7 @@ class streamer(TwythonStreamer):
else: else:
self.session.db[place].insert(0, data) self.session.db[place].insert(0, data)
utils.is_audio(data) utils.is_audio(data)
return True
def block_user(self, data): def block_user(self, data):
id = data["target"]["id"] id = data["target"]["id"]
@@ -64,30 +65,36 @@ class streamer(TwythonStreamer):
def check_send(self, data): def check_send(self, data):
if self.session.db["user_name"] == data["user"]["screen_name"]: if self.session.db["user_name"] == data["user"]["screen_name"]:
self.put_data("sent_tweets", data) d = self.put_data("sent_tweets", data)
pub.sendMessage("sent-tweet", data=data, user=self.get_user()) if d != False:
pub.sendMessage("sent-tweet", data=data, user=self.get_user())
def check_favs(self, data): def check_favs(self, data):
if data["source"]["screen_name"] == self.session.db["user_name"]: if data["source"]["screen_name"] == self.session.db["user_name"]:
self.put_data("favourites", data["target_object"]) d = self.put_data("favourites", data["target_object"])
pub.sendMessage("favourite", data=data["target_object"], user=self.get_user()) if d != False:
pub.sendMessage("favourite", data=data["target_object"], user=self.get_user())
def check_mentions(self, data): def check_mentions(self, data):
if "@%s" % (self.session.db["user_name"]) in data["text"]: if "@%s" % (self.session.db["user_name"]) in data["text"]:
self.put_data("mentions", data) d = self.put_data("mentions", data)
pub.sendMessage("mention", data=data, user=self.get_user()) if d != False:
pub.sendMessage("mention", data=data, user=self.get_user())
def set_quoted_tweet(self, data): def set_quoted_tweet(self, data):
self.put_data("mentions", data) d = self.put_data("mentions", data)
pub.sendMessage("mention", data=data, user=self.get_user()) if d != False:
pub.sendMessage("mention", data=data, user=self.get_user())
def process_dm(self, data): def process_dm(self, data):
if self.session.db["user_name"] == data["direct_message"]["sender"]["screen_name"]: if self.session.db["user_name"] == data["direct_message"]["sender"]["screen_name"]:
self.put_data("sent_direct_messages", data["direct_message"]) d = self.put_data("sent_direct_messages", data["direct_message"])
pub.sendMessage("sent-dm", data=data["direct_message"], user=self.get_user()) if d != False:
pub.sendMessage("sent-dm", data=data["direct_message"], user=self.get_user())
else: else:
self.put_data("direct_messages", data["direct_message"]) d = self.put_data("direct_messages", data["direct_message"])
pub.sendMessage("direct-message", data=data["direct_message"], user=self.get_user()) if d != False:
pub.sendMessage("direct-message", data=data["direct_message"], user=self.get_user())
def check_follower(self, data): def check_follower(self, data):
if data["target"]["screen_name"] == self.session.db["user_name"]: if data["target"]["screen_name"] == self.session.db["user_name"]:
@@ -129,8 +136,9 @@ class streamer(TwythonStreamer):
self.check_mentions(data) self.check_mentions(data)
self.check_send(data) self.check_send(data)
if data["user"]["id"] in self.friends or data["user"]["screen_name"] == self.session.db["user_name"]: if data["user"]["id"] in self.friends or data["user"]["screen_name"] == self.session.db["user_name"]:
self.put_data("home_timeline", data) d = self.put_data("home_timeline", data)
pub.sendMessage("item-in-home", data=data, user=self.get_user()) if d != False:
pub.sendMessage("item-in-home", data=data, user=self.get_user())
elif data.has_key("event"): elif data.has_key("event"):
if "favorite" == data["event"] and "favorites" in self.session.settings["general"]["buffer_order"]: if "favorite" == data["event"] and "favorites" in self.session.settings["general"]["buffer_order"]:
self.check_favs(data) self.check_favs(data)

View File

@@ -123,12 +123,12 @@ def compose_event(data, username):
event = _(u"You've unfollowed %s (@%s)") % (data["target"]["name"], data["target"]["screen_name"]) event = _(u"You've unfollowed %s (@%s)") % (data["target"]["name"], data["target"]["screen_name"])
elif data["event"] == "favorite": elif data["event"] == "favorite":
if data["source"]["screen_name"] == username: 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: 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": 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"]) 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 removed from favourites: %s") % (data["source"]["name"], data["source"]["screen_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": elif data["event"] == "list_created":
event = _(u"You've created the list %s") % (data["target_object"]["name"]) event = _(u"You've created the list %s") % (data["target_object"]["name"])
elif data["event"] == "list_destroyed": elif data["event"] == "list_destroyed":

View File

@@ -47,7 +47,7 @@ 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() 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(): 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(): 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) 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)

View File

@@ -78,7 +78,6 @@ class tweet(textLimited):
self.shortenButton.Disable() self.shortenButton.Disable()
self.unshortenButton.Disable() self.unshortenButton.Disable()
self.translateButton = wx.Button(self.panel, -1, _(u"Translate..."), size=wx.DefaultSize) self.translateButton = wx.Button(self.panel, -1, _(u"Translate..."), size=wx.DefaultSize)
self.translateButton.Enable(False)
self.autocompletionButton = wx.Button(self.panel, -1, _(u"&Autocomplete users")) self.autocompletionButton = wx.Button(self.panel, -1, _(u"&Autocomplete users"))
self.okButton = wx.Button(self.panel, wx.ID_OK, _(u"Send"), size=wx.DefaultSize) self.okButton = wx.Button(self.panel, wx.ID_OK, _(u"Send"), size=wx.DefaultSize)
self.okButton.SetDefault() self.okButton.SetDefault()
@@ -139,7 +138,6 @@ class retweet(tweet):
self.shortenButton.Disable() self.shortenButton.Disable()
self.unshortenButton.Disable() self.unshortenButton.Disable()
self.translateButton = wx.Button(self.panel, -1, _(u"Translate message"), size=wx.DefaultSize) self.translateButton = wx.Button(self.panel, -1, _(u"Translate message"), size=wx.DefaultSize)
self.translateButton.Enable(False)
self.autocompletionButton = wx.Button(self.panel, -1, _(u"&Autocomplete users")) self.autocompletionButton = wx.Button(self.panel, -1, _(u"&Autocomplete users"))
self.okButton = wx.Button(self.panel, wx.ID_OK, _(u"Send"), size=wx.DefaultSize) self.okButton = wx.Button(self.panel, wx.ID_OK, _(u"Send"), size=wx.DefaultSize)
self.okButton.SetDefault() self.okButton.SetDefault()
@@ -201,7 +199,6 @@ class dm(textLimited):
self.shortenButton.Disable() self.shortenButton.Disable()
self.unshortenButton.Disable() self.unshortenButton.Disable()
self.translateButton = wx.Button(self.panel, -1, _(u"Translate message"), size=wx.DefaultSize) self.translateButton = wx.Button(self.panel, -1, _(u"Translate message"), size=wx.DefaultSize)
self.translateButton.Enable(False)
self.okButton = wx.Button(self.panel, wx.ID_OK, _(u"Send"), size=wx.DefaultSize) self.okButton = wx.Button(self.panel, wx.ID_OK, _(u"Send"), size=wx.DefaultSize)
self.okButton.SetDefault() self.okButton.SetDefault()
cancelButton = wx.Button(self.panel, wx.ID_CANCEL, _(u"Close"), size=wx.DefaultSize) cancelButton = wx.Button(self.panel, wx.ID_CANCEL, _(u"Close"), size=wx.DefaultSize)
@@ -268,7 +265,7 @@ class viewTweet(widgetUtils.BaseDialog):
rtBox = wx.BoxSizer(wx.HORIZONTAL) rtBox = wx.BoxSizer(wx.HORIZONTAL)
rtBox.Add(rtCountLabel, 0, wx.ALL, 5) rtBox.Add(rtCountLabel, 0, wx.ALL, 5)
rtBox.Add(rtCount, 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) favsCount = wx.TextCtrl(panel, -1, favs_count, size=wx.DefaultSize, style=wx.TE_READONLY|wx.TE_MULTILINE)
favsBox = wx.BoxSizer(wx.HORIZONTAL) favsBox = wx.BoxSizer(wx.HORIZONTAL)
favsBox.Add(favsCountLabel, 0, wx.ALL, 5) favsBox.Add(favsCountLabel, 0, wx.ALL, 5)
@@ -281,7 +278,6 @@ class viewTweet(widgetUtils.BaseDialog):
self.unshortenButton = wx.Button(panel, -1, _(u"Expand URL"), size=wx.DefaultSize) self.unshortenButton = wx.Button(panel, -1, _(u"Expand URL"), size=wx.DefaultSize)
self.unshortenButton.Disable() self.unshortenButton.Disable()
self.translateButton = wx.Button(panel, -1, _(u"Translate message"), size=wx.DefaultSize) self.translateButton = wx.Button(panel, -1, _(u"Translate message"), size=wx.DefaultSize)
self.translateButton.Enable(False)
cancelButton = wx.Button(panel, wx.ID_CANCEL, _(u"Close"), size=wx.DefaultSize) cancelButton = wx.Button(panel, wx.ID_CANCEL, _(u"Close"), size=wx.DefaultSize)
cancelButton.SetDefault() cancelButton.SetDefault()
buttonsBox = wx.BoxSizer(wx.HORIZONTAL) buttonsBox = wx.BoxSizer(wx.HORIZONTAL)
@@ -337,7 +333,6 @@ class viewNonTweet(widgetUtils.BaseDialog):
self.unshortenButton = wx.Button(panel, -1, _(u"Expand URL"), size=wx.DefaultSize) self.unshortenButton = wx.Button(panel, -1, _(u"Expand URL"), size=wx.DefaultSize)
self.unshortenButton.Disable() self.unshortenButton.Disable()
self.translateButton = wx.Button(panel, -1, _(u"Translate message"), size=wx.DefaultSize) self.translateButton = wx.Button(panel, -1, _(u"Translate message"), size=wx.DefaultSize)
self.translateButton.Enable(False)
cancelButton = wx.Button(panel, wx.ID_CANCEL, _(u"Close"), size=wx.DefaultSize) cancelButton = wx.Button(panel, wx.ID_CANCEL, _(u"Close"), size=wx.DefaultSize)
cancelButton.SetDefault() cancelButton.SetDefault()
buttonsBox = wx.BoxSizer(wx.HORIZONTAL) buttonsBox = wx.BoxSizer(wx.HORIZONTAL)

View File

@@ -17,7 +17,7 @@ class selectUserDialog(wx.Dialog):
actionSizer = wx.BoxSizer(wx.VERTICAL) actionSizer = wx.BoxSizer(wx.VERTICAL)
label2 = wx.StaticText(panel, -1, _(u"Buffer type")) label2 = wx.StaticText(panel, -1, _(u"Buffer type"))
self.tweets = wx.RadioButton(panel, -1, _(u"Tweets"), style=wx.RB_GROUP) self.tweets = wx.RadioButton(panel, -1, _(u"Tweets"), style=wx.RB_GROUP)
self.favourites = wx.RadioButton(panel, -1, _(u"Favourites")) self.favourites = wx.RadioButton(panel, -1, _(u"Likes"))
self.setup_default(default) self.setup_default(default)
hSizer = wx.BoxSizer(wx.HORIZONTAL) hSizer = wx.BoxSizer(wx.HORIZONTAL)
hSizer.Add(label2, 0, wx.ALL, 5) hSizer.Add(label2, 0, wx.ALL, 5)

View File

@@ -8,9 +8,9 @@ class basePanelMenu(wx.Menu):
self.AppendItem(self.retweet) self.AppendItem(self.retweet)
self.reply = wx.MenuItem(self, wx.NewId(), _(u"Re&ply")) self.reply = wx.MenuItem(self, wx.NewId(), _(u"Re&ply"))
self.AppendItem(self.reply) self.AppendItem(self.reply)
self.fav = wx.MenuItem(self, wx.NewId(), _(u"Add to &favourites")) self.fav = wx.MenuItem(self, wx.NewId(), _(u"&Like"))
self.AppendItem(self.fav) self.AppendItem(self.fav)
self.unfav = wx.MenuItem(self, wx.NewId(), _(u"Remove from favo&urites")) self.unfav = wx.MenuItem(self, wx.NewId(), _(u"&Unlike"))
self.AppendItem(self.unfav) self.AppendItem(self.unfav)
self.openUrl = wx.MenuItem(self, wx.NewId(), _(u"&Open URL")) self.openUrl = wx.MenuItem(self, wx.NewId(), _(u"&Open URL"))
self.AppendItem(self.openUrl) self.AppendItem(self.openUrl)

View File

@@ -27,8 +27,8 @@ class mainFrame(wx.Frame):
self.compose = tweet.Append(wx.NewId(), _(u"&Tweet")) self.compose = tweet.Append(wx.NewId(), _(u"&Tweet"))
self.reply = tweet.Append(wx.NewId(), _(u"Re&ply")) self.reply = tweet.Append(wx.NewId(), _(u"Re&ply"))
self.retweet = tweet.Append(wx.NewId(), _(u"&Retweet")) self.retweet = tweet.Append(wx.NewId(), _(u"&Retweet"))
self.fav = tweet.Append(wx.NewId(), _(u"Add to &favourites")) self.fav = tweet.Append(wx.NewId(), _(u"&Like"))
self.unfav = tweet.Append(wx.NewId(), _(u"Remove from favo&urites")) self.unfav = tweet.Append(wx.NewId(), _(u"&Unlike"))
self.view = tweet.Append(wx.NewId(), _(u"&Show tweet")) self.view = tweet.Append(wx.NewId(), _(u"&Show tweet"))
self.view_coordinates = tweet.Append(wx.NewId(), _(u"View &address")) self.view_coordinates = tweet.Append(wx.NewId(), _(u"View &address"))
self.view_conversation = tweet.Append(wx.NewId(), _(u"View conversa&tion")) self.view_conversation = tweet.Append(wx.NewId(), _(u"View conversa&tion"))
@@ -43,7 +43,7 @@ class mainFrame(wx.Frame):
self.removeFromList = user.Append(wx.NewId(), _(u"R&emove from list")) self.removeFromList = user.Append(wx.NewId(), _(u"R&emove from list"))
self.viewLists = user.Append(wx.NewId(), _(u"&View lists")) self.viewLists = user.Append(wx.NewId(), _(u"&View lists"))
self.details = user.Append(wx.NewId(), _(u"Show user &profile")) self.details = user.Append(wx.NewId(), _(u"Show user &profile"))
self.favs = user.Append(wx.NewId(), _(u"V&iew favourites")) self.favs = user.Append(wx.NewId(), _(u"V&iew likes"))
# buffer menu # buffer menu
buffer = wx.Menu() buffer = wx.Menu()