mirror of
https://github.com/MCV-Software/TWBlue.git
synced 2025-08-25 09:29:22 +00:00
Compare commits
93 Commits
snapshot11
...
snapshot1
Author | SHA1 | Date | |
---|---|---|---|
7e9d5359f1 | |||
86b8a2ab0f | |||
b8043f2c4a | |||
![]() |
eff11f18c5 | ||
eca8b1ec46 | |||
59bd2842c4 | |||
92564d4075 | |||
9d59ee9d8d | |||
b845e751aa | |||
246a10535c | |||
977c521d7c | |||
0e3ba0b89e | |||
18d75e0564 | |||
482f95ba55 | |||
c70b900c96 | |||
75877661a2 | |||
1828b14790 | |||
35582650dc | |||
9500703408 | |||
ba48a817f2 | |||
b06f28d3e6 | |||
838e0c7b12 | |||
08b34138e0 | |||
073ccbf6c7 | |||
a58187e5f7 | |||
6af39c6a2f | |||
d97733fb1a | |||
80212fc61f | |||
fe60ac8f67 | |||
b6d5c9be63 | |||
e5a40288af | |||
bafb56651c | |||
29290b1468 | |||
316a539a11 | |||
6320f0d93c | |||
6e12d70cd9 | |||
bca6861bcb | |||
![]() |
60074919f6 | ||
![]() |
7f9e5e181a | ||
0f2662e52d | |||
![]() |
5930470023 | ||
![]() |
56930a8921 | ||
![]() |
991f46e923 | ||
![]() |
2ec47ad1e2 | ||
ae81dd94a5 | |||
dcc4f4c782 | |||
c65d149590 | |||
2620348573 | |||
![]() |
ba1bcd550d | ||
![]() |
0dd082079e | ||
![]() |
7928cf5f24 | ||
![]() |
1333ebf859 | ||
![]() |
ec3779147f | ||
ebd8e42154 | |||
a4f20872b0 | |||
ef689d04fc | |||
![]() |
d441536f01 | ||
f976beb751 | |||
bed6142fa1 | |||
4c34099751 | |||
![]() |
e0db808dce | ||
![]() |
c500e8f513 | ||
![]() |
7f86da1123 | ||
aa4ebfff29 | |||
![]() |
ae4deb412f | ||
![]() |
6eb27b655a | ||
![]() |
fe72fe97b5 | ||
c82ef1855c | |||
fd43865105 | |||
cf095ba13b | |||
092c5312cb | |||
fc21b43475 | |||
3fce3c58e2 | |||
207315937a | |||
61d9180b2e | |||
89985cf6bd | |||
cc4568b968 | |||
d7132ecaf6 | |||
720e0e6c24 | |||
9763d8b26c | |||
f512267b6d | |||
241de0264d | |||
5c7bce1258 | |||
e24543be12 | |||
422c780d0c | |||
![]() |
96a592a4f9 | ||
d4bf33ca6d | |||
e5b33160e0 | |||
c8d83ed9e7 | |||
16b2e16614 | |||
221d1d413b | |||
4391e3d3de | |||
c5e9e97c84 |
@@ -31,7 +31,7 @@ Although most dependencies can be found in the windows-dependencies directory, w
|
||||
|
||||
#### Dependencies packaged in windows installers
|
||||
|
||||
* [Python,](http://python.org) version 2.7.15
|
||||
* [Python,](http://python.org) version 2.7.16
|
||||
If you want to build both x86 and x64 binaries, you can install python x86 to C:\python27 and python x64 to C:\python27x64, for example.
|
||||
* [PyEnchant,](http://pythonhosted.org/pyenchant/) version 1.6.6.
|
||||
x64 version has been built by TWBlue developers, so you only will find it in windows-dependencies folder
|
||||
@@ -76,13 +76,13 @@ This dependency has been built using pure basic 4.61. Its source can be found at
|
||||
|
||||
#### Dependencies required to build the installer
|
||||
|
||||
* [NSIS,](http://nsis.sourceforge.net/) version 3.03
|
||||
* [NSIS,](http://nsis.sourceforge.net/) version 3.04
|
||||
|
||||
#### Dependencies required to build the portableApps.com format archive
|
||||
|
||||
* [NSIS Portable,](http://portableapps.com/apps/development/nsis_portable) version 3.03
|
||||
* [PortableApps.com Launcher,](http://portableapps.com/apps/development/portableapps.com_launcher) version 2.2.1
|
||||
* [PortableApps.com Installer,](http://portableapps.com/apps/development/portableapps.com_installer) version 3.5.8
|
||||
* [PortableApps.com Installer,](http://portableapps.com/apps/development/portableapps.com_installer) version 3.5.11
|
||||
|
||||
Important! Install these 3 apps into the same folder, otherwise you won't be able to build the pa.c version. For example: D:\portableApps\NSISPortable, D:\PortableApps\PortableApps.com installer, ...
|
||||
|
||||
|
21
appveyor.yml
21
appveyor.yml
@@ -10,13 +10,13 @@ environment:
|
||||
matrix:
|
||||
|
||||
# List of python versions we want to work with.
|
||||
- PYTHON: "C:\\Python27"
|
||||
PYTHON_VERSION: "2.7.x" # currently 2.7.9
|
||||
- PYTHON: "C:\\Python37"
|
||||
PYTHON_VERSION: "3.7.x" # currently 2.7.9
|
||||
PYTHON_ARCH: "32"
|
||||
|
||||
# perhaps we may enable this one in future?
|
||||
# - PYTHON: "C:\\Python27-x64"
|
||||
# PYTHON_VERSION: "2.7.x" # currently 2.7.9
|
||||
# - PYTHON: "C:\\Python37-x64"
|
||||
# PYTHON_VERSION: "3.7.x" # currently 2.7.9
|
||||
# PYTHON_ARCH: "64"
|
||||
|
||||
# This is important so we will retrieve everything in submodules as opposed to default method.
|
||||
@@ -37,10 +37,11 @@ install:
|
||||
https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | `
|
||||
Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { `
|
||||
throw "There are newer queued builds for this pull request, failing early." }
|
||||
- ECHO "Filesystem root:"
|
||||
- ps: "ls \"C:/\""
|
||||
# - ECHO "Filesystem root:"
|
||||
# - ps: "ls \"C:/\""
|
||||
|
||||
# Check that we have the expected version and architecture for Python
|
||||
- "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
|
||||
- "python --version"
|
||||
- "python -c \"import struct; print(struct.calcsize('P') * 8)\""
|
||||
|
||||
@@ -53,7 +54,7 @@ install:
|
||||
# pip will build them from source using the MSVC compiler matching the
|
||||
# target Python version and architecture
|
||||
- "%CMD_IN_ENV% pip install -r requirements.txt"
|
||||
- "%CMD_IN_ENV% pip install pyenchant py2exe_py2"
|
||||
- "%CMD_IN_ENV% pip install pyenchant"
|
||||
|
||||
build_script:
|
||||
# Build documentation at first, so setup.py won't fail when copying everything.
|
||||
@@ -64,10 +65,10 @@ build_script:
|
||||
- "cd ..\\src"
|
||||
- "%CMD_IN_ENV% python ..\\doc\\generator.py"
|
||||
# Build distributable files.
|
||||
- "%CMD_IN_ENV% python setup.py py2exe"
|
||||
- "%CMD_IN_ENV% python setup.py build"
|
||||
- "cd dist"
|
||||
# Zip it all.
|
||||
- cmd: 7z a ..\..\snapshot.zip *
|
||||
- cmd: 7z a ..\..\snapshot_python3.zip *
|
||||
|
||||
artifacts:
|
||||
- path: snapshot.zip
|
||||
@@ -80,4 +81,4 @@ deploy:
|
||||
username: twblue
|
||||
password:
|
||||
secure: ml/xB8YEoZ7DmjzDr+KSNw==
|
||||
# folder: '//pubs'
|
||||
folder: 'web/pubs'
|
@@ -38,4 +38,5 @@ Burak Yüksek
|
||||
florian Ionașcu
|
||||
Christian Leo Mameli
|
||||
Natalia Hedlund (Наталья Хедлунд)
|
||||
Valeria (Валерия)
|
||||
Valeria (Валерия)
|
||||
Corentin Bacqué-Cazenave
|
@@ -1,18 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
name = 'TWBlue'
|
||||
snapshot = False
|
||||
if snapshot == False:
|
||||
version = "0.94"
|
||||
update_url = 'http://twblue.es/updates/twblue_ngen.json'
|
||||
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/stable.json'
|
||||
else:
|
||||
version = "10.99"
|
||||
update_url = 'http://twblue.es/updates/snapshots_ngen.json'
|
||||
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/snapshots.json'
|
||||
author = u"Manuel Cortéz"
|
||||
authorEmail = "manuel@manuelcortez.net"
|
||||
copyright = u"Copyright (C) 2013-2016, 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"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"
|
@@ -2,6 +2,18 @@
|
||||
|
||||
## changes in this version
|
||||
|
||||
* Fixed error when displaying an URL at the end of a line, when the tweet or direct message contained multiple lines. Now the URL should be displayed correctly. ((#305,)[https://github.com/manuelcortez/TWBlue/issues/305])
|
||||
|
||||
## Changes in version 0.95
|
||||
|
||||
* TWBlue can open a Tweet or user directly in Twitter. There is a new option in the context menu for people and tweet buffers, and also, the shortcut control+win+alt+Enter will open the focused item in Twitter.
|
||||
* Some keystrokes were remapped in the Windows 10 Keymap:
|
||||
* Read location of a tweet: Ctrl+Win+G. ([#177](https://github.com/manuelcortez/TWBlue/pull/177))
|
||||
* Open global settings dialogue: Ctrl+Win+Alt+O.
|
||||
* Mute/unmute current session: Control + Windows + Alt + M.
|
||||
* Fixed an error that was preventing TWBlue to load the direct messages buffer if an user who sent a message has been deleted.
|
||||
* Added support for playing audios posted in [AnyAudio.net](http://anyaudio.net) directly from TWBlue. Thanks to [Sam Tupy](http://www.samtupy.com/)
|
||||
* Custom buffer ordering will not be reset every time the application restarts after an account setting has been modified.
|
||||
* When adding or removing an user from a list, it is possible to press enter in the focused list instead of having to search for the "add" or "delete" button.
|
||||
* Quoted and long tweets are displayed properly in the sent tweets buffer after being send. ([#253](https://github.com/manuelcortez/TWBlue/issues/253))
|
||||
* Fixed an issue that was making the list manager keystroke unable to be shown in the keystroke editor. Now the keystroke is listed properly. ([#260](https://github.com/manuelcortez/TWBlue/issues/260))
|
||||
@@ -14,7 +26,6 @@
|
||||
* There is a new soundpack, called FreakyBlue (Thanks to [Andre Louis](https://twitter.com/FreakyFwoof)) as a new option in TWBlue. This pack can be the default in the next stable, so users can take a look and share their opinion in snapshot versions. ([#247](https://github.com/manuelcortez/TWBlue/issues/247))
|
||||
* There is a new option in the help menu that allows you to visit the soundpacks section in the TWBlue website. ([#247](https://github.com/manuelcortez/TWBlue/issues/247))
|
||||
* When reading location of a geotagged tweet, it will be translated for users of other languages. ([#251](https://github.com/manuelcortez/TWBlue/pull/251))
|
||||
* In the Windows 10 Keymap, the action to read location of a tweet has been remapped to Ctrl+Win+G. ([#177](https://github.com/manuelcortez/TWBlue/pull/177))
|
||||
* When there are no more items to retrieve in direct messages and people buffers, a message will announce it.
|
||||
* Fixed an issue reported by some users that was making them unable to load more items in their direct messages.
|
||||
* It is possible to add a tweet to the likes buffer from the menu bar again.
|
||||
|
@@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from codecs import open
|
||||
""" This script converts the hold documentation (saved in markdown files) in a python file with a list of strings to translate it using gettext."""
|
||||
|
||||
def prepare_documentation_in_file(fileSource, fileDest):
|
||||
@@ -6,8 +7,8 @@ def prepare_documentation_in_file(fileSource, fileDest):
|
||||
@fileSource str: A markdown(.md) file.
|
||||
@fileDest str: A file where this will put the new strings"""
|
||||
|
||||
f1 = open(fileSource, "r")
|
||||
f2 = open(fileDest, "w")
|
||||
f1 = open(fileSource, "r", encoding="utf-8")
|
||||
f2 = open(fileDest, "w", encoding="utf-8")
|
||||
lns = f1.readlines()
|
||||
f2.write("# -*- coding: utf-8 -*-\n")
|
||||
f2.write("documentation = [\n")
|
||||
|
@@ -1,29 +1,32 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import markdown
|
||||
import gettext
|
||||
import os
|
||||
import locale
|
||||
import paths
|
||||
import markdown
|
||||
import shutil
|
||||
from codecs import open as _open
|
||||
import languageHandler
|
||||
languageHandler.setLanguage("en")
|
||||
import strings
|
||||
import changelog
|
||||
from importlib import reload
|
||||
|
||||
def change_language(name, language):
|
||||
global _
|
||||
os.environ["lang"] = language
|
||||
_ = gettext.install(name, os.path.join(paths.app_path(), "locales"))
|
||||
|
||||
# the list of supported language codes of TW Blue
|
||||
languages = ["en", "es", "fr", "de", "it", "gl", "ja", "ru", "ro", "eu", "ca", "da"]
|
||||
#"eu", "ar", "ca", "es", "fi", "fr", "gl", "hu", "it", "pl", "pt", "ru", "tr"]
|
||||
|
||||
def generate_document(language, document_type="documentation"):
|
||||
reload(languageHandler)
|
||||
if document_type == "documentation":
|
||||
translation_file = "twblue-documentation"
|
||||
languageHandler.setLanguage(language, translation_file)
|
||||
change_language(translation_file, language)
|
||||
reload(strings)
|
||||
markdown_file = markdown.markdown("\n".join(strings.documentation[1:]), extensions=["markdown.extensions.toc"])
|
||||
title = strings.documentation[0]
|
||||
filename = "manual.html"
|
||||
elif document_type == "changelog":
|
||||
translation_file = "twblue-changelog"
|
||||
languageHandler.setLanguage(language, translation_file)
|
||||
change_language(translation_file, language)
|
||||
reload(changelog)
|
||||
markdown_file = markdown.markdown("\n".join(changelog.documentation[1:]), extensions=["markdown.extensions.toc"])
|
||||
title = changelog.documentation[0]
|
||||
@@ -57,4 +60,7 @@ def create_documentation():
|
||||
generate_document(i, "changelog")
|
||||
print("Done")
|
||||
|
||||
change_language("twblue-documentation", "en")
|
||||
import strings
|
||||
import changelog
|
||||
create_documentation()
|
@@ -1,176 +0,0 @@
|
||||
import __builtin__
|
||||
import os
|
||||
import sys
|
||||
import ctypes
|
||||
import locale
|
||||
import gettext
|
||||
#import paths
|
||||
import platform
|
||||
|
||||
# A fix for the mac locales
|
||||
if platform.system() != 'Windows':
|
||||
if locale.getlocale()[0] is None:
|
||||
locale.setlocale(locale.LC_ALL, 'en_US')
|
||||
|
||||
#a few Windows locale constants
|
||||
LOCALE_SLANGUAGE=0x2
|
||||
LOCALE_SLANGDISPLAYNAME=0x6f
|
||||
|
||||
curLang="en"
|
||||
|
||||
def localeNameToWindowsLCID(localeName):
|
||||
"""Retreave the Windows locale identifier (LCID) for the given locale name
|
||||
@param localeName: a string of 2letterLanguage_2letterCountry or or just 2letterLanguage
|
||||
@type localeName: string
|
||||
@returns: a Windows LCID
|
||||
@rtype: integer
|
||||
"""
|
||||
#Windows Vista is able to convert locale names to LCIDs
|
||||
func_LocaleNameToLCID=getattr(ctypes.windll.kernel32,'LocaleNameToLCID',None)
|
||||
if func_LocaleNameToLCID is not None:
|
||||
localeName=localeName.replace('_','-')
|
||||
LCID=func_LocaleNameToLCID(unicode(localeName),0)
|
||||
else: #Windows doesn't have this functionality, manually search Python's windows_locale dictionary for the LCID
|
||||
localeName=locale.normalize(localeName)
|
||||
if '.' in localeName:
|
||||
localeName=localeName.split('.')[0]
|
||||
LCList=[x[0] for x in locale.windows_locale.iteritems() if x[1]==localeName]
|
||||
if len(LCList)>0:
|
||||
LCID=LCList[0]
|
||||
else:
|
||||
LCID=0
|
||||
return LCID
|
||||
|
||||
def getLanguageDescription(language):
|
||||
"""Finds out the description (localized full name) of a given local name"""
|
||||
desc=None
|
||||
if platform.system() == "Windows":
|
||||
LCID=localeNameToWindowsLCID(language)
|
||||
if LCID!=0:
|
||||
buf=ctypes.create_unicode_buffer(1024)
|
||||
if '_' not in language:
|
||||
res=ctypes.windll.kernel32.GetLocaleInfoW(LCID,LOCALE_SLANGDISPLAYNAME,buf,1024)
|
||||
else:
|
||||
res=0
|
||||
if res==0:
|
||||
res=ctypes.windll.kernel32.GetLocaleInfoW(LCID,LOCALE_SLANGUAGE,buf,1024)
|
||||
desc=buf.value
|
||||
elif platform.system() == "Linux" or not desc:
|
||||
desc={
|
||||
"am":pgettext("languageName","Amharic"),
|
||||
"an":pgettext("languageName","Aragonese"),
|
||||
"es":pgettext("languageName","Spanish"),
|
||||
"pt":pgettext("languageName","Portuguese"),
|
||||
"ru":pgettext("languageName","Russian"),
|
||||
"it":pgettext("languageName","italian"),
|
||||
"tr":pgettext("languageName","Turkey"),
|
||||
"gl":pgettext("languageName","Galician"),
|
||||
"ca":pgettext("languageName","Catala"),
|
||||
"eu":pgettext("languageName","Vasque"),
|
||||
"pl":pgettext("languageName","polish"),
|
||||
"ar":pgettext("languageName","Arabic"),
|
||||
"ne":pgettext("languageName","Nepali"),
|
||||
"sr":pgettext("languageName","Serbian (Latin)"),
|
||||
}.get(language,None)
|
||||
return desc
|
||||
|
||||
def getAvailableLanguages():
|
||||
"""generates a list of locale names, plus their full localized language and country names.
|
||||
@rtype: list of tuples
|
||||
"""
|
||||
#Make a list of all the locales found in NVDA's locale dir
|
||||
l=[x for x in os.listdir("locales") if not x.startswith('.')]
|
||||
l=[x for x in l if os.path.isfile('locales/%s/LC_MESSAGES/twblue-documentation.mo' % x)]
|
||||
#Make sure that en (english) is in the list as it may not have any locale files, but is default
|
||||
if 'en' not in l:
|
||||
l.append('en')
|
||||
l.sort()
|
||||
#For each locale, ask Windows for its human readable display name
|
||||
d=[]
|
||||
for i in l:
|
||||
desc=getLanguageDescription(i)
|
||||
label="%s, %s"%(desc,i) if desc else i
|
||||
d.append(label)
|
||||
#include a 'user default, windows' language, which just represents the default language for this user account
|
||||
l.append("system")
|
||||
# Translators: the label for the Windows default NVDA interface language.
|
||||
d.append(_("User default"))
|
||||
#return a zipped up version of both the lists (a list with tuples of locale,label)
|
||||
return zip(l,d)
|
||||
|
||||
def makePgettext(translations):
|
||||
"""Obtaina pgettext function for use with a gettext translations instance.
|
||||
pgettext is used to support message contexts,
|
||||
but Python 2.7's gettext module doesn't support this,
|
||||
so NVDA must provide its own implementation.
|
||||
"""
|
||||
if isinstance(translations, gettext.GNUTranslations):
|
||||
def pgettext(context, message):
|
||||
message = unicode(message)
|
||||
try:
|
||||
# Look up the message with its context.
|
||||
return translations._catalog[u"%s\x04%s" % (context, message)]
|
||||
except KeyError:
|
||||
return message
|
||||
else:
|
||||
def pgettext(context, message):
|
||||
return unicode(message)
|
||||
return pgettext
|
||||
|
||||
def setLanguage(lang, translation_file="twblue-documentation"):
|
||||
system = platform.system()
|
||||
global curLang
|
||||
try:
|
||||
if lang=="system":
|
||||
if system == "Windows":
|
||||
windowsLCID=ctypes.windll.kernel32.GetUserDefaultUILanguage()
|
||||
localeName=locale.windows_locale[windowsLCID]
|
||||
else:
|
||||
localeName=locale.getlocale()[0]
|
||||
trans=gettext.translation(translation_file, localedir="locales", languages=[localeName])
|
||||
curLang=localeName
|
||||
else:
|
||||
trans=gettext.translation(translation_file, localedir="locales", languages=[lang])
|
||||
curLang=lang
|
||||
localeChanged=False
|
||||
#Try setting Python's locale to lang
|
||||
try:
|
||||
locale.setlocale(locale.LC_ALL, lang)
|
||||
localeChanged=True
|
||||
except:
|
||||
pass
|
||||
if not localeChanged and '_' in lang:
|
||||
#Python couldn'tsupport the language_country locale, just try language.
|
||||
try:
|
||||
locale.setlocale(locale.LC_ALL, lang.split('_')[0])
|
||||
except:
|
||||
pass
|
||||
#Set the windows locale for this thread (NVDA core) to this locale.
|
||||
if system == "Windows":
|
||||
LCID=localeNameToWindowsLCID(lang)
|
||||
ctypes.windll.kernel32.SetThreadLocale(LCID)
|
||||
except IOError:
|
||||
trans=gettext.translation(translation_file,fallback=True)
|
||||
curLang="en"
|
||||
trans.install(unicode=True)
|
||||
# Install our pgettext function.
|
||||
__builtin__.__dict__["pgettext"] = makePgettext(trans)
|
||||
|
||||
def getLanguage():
|
||||
return curLang
|
||||
|
||||
def normalizeLanguage(lang):
|
||||
"""
|
||||
Normalizes a language-dialect string in to a standard form we can deal with.
|
||||
Converts any dash to underline, and makes sure that language is lowercase and dialect is upercase.
|
||||
"""
|
||||
lang=lang.replace('-','_')
|
||||
ld=lang.split('_')
|
||||
ld[0]=ld[0].lower()
|
||||
#Filter out meta languages such as x-western
|
||||
if ld[0]=='x':
|
||||
return None
|
||||
if len(ld)>=2:
|
||||
ld[1]=ld[1].upper()
|
||||
return "_".join(ld)
|
||||
|
BIN
doc/locales/ar/lc_messages/twblue-changelog.mo
Normal file
BIN
doc/locales/ar/lc_messages/twblue-changelog.mo
Normal file
Binary file not shown.
1014
doc/locales/ar/lc_messages/twblue-changelog.po
Normal file
1014
doc/locales/ar/lc_messages/twblue-changelog.po
Normal file
File diff suppressed because it is too large
Load Diff
BIN
doc/locales/ar/lc_messages/twblue-documentation.mo
Normal file
BIN
doc/locales/ar/lc_messages/twblue-documentation.mo
Normal file
Binary file not shown.
1604
doc/locales/ar/lc_messages/twblue-documentation.po
Normal file
1604
doc/locales/ar/lc_messages/twblue-documentation.po
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: TW Blue documentation 0.89\n"
|
||||
"POT-Creation-Date: 2018-08-07 13:19+Hora de verano central (Mexico)\n"
|
||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
||||
"PO-Revision-Date: 2017-03-25 15:15+0100\n"
|
||||
"Last-Translator: Joan Rabat <joanrabat@hotmail.com>\n"
|
||||
"Language-Team: Francisco Torres Gallego <frantorresgallego@gmail.com>\n"
|
||||
|
Binary file not shown.
@@ -5,16 +5,16 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"POT-Creation-Date: 2018-08-07 13:19+Hora de verano central (Mexico)\n"
|
||||
"PO-Revision-Date: 2017-12-11 09:17-0600\n"
|
||||
"Last-Translator: \n"
|
||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
||||
"PO-Revision-Date: 2018-11-17 10:25+0100\n"
|
||||
"Last-Translator: Nicolai Svendsen <chojiro1990@gmail.com>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: da\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
"X-Generator: Poedit 2.0.2\n"
|
||||
"X-Generator: Poedit 2.2\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: ../doc/strings.py:3
|
||||
@@ -110,7 +110,6 @@ msgid "## Usage"
|
||||
msgstr "## Brug"
|
||||
|
||||
#: ../doc/strings.py:21
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Twitter is a social networking or micro-blogging tool which allows you to "
|
||||
"compose short status updates of your activities in 280 characters or less. "
|
||||
@@ -120,7 +119,7 @@ msgid ""
|
||||
"anyone to access them."
|
||||
msgstr ""
|
||||
"Twitter er et socialt netværk eller mikro-blogging-værktøj, der giver dig "
|
||||
"mulighed for at skrive korte statusopdateringer om dine aktiviteter i 140 "
|
||||
"mulighed for at skrive korte statusopdateringer om dine aktiviteter på 280 "
|
||||
"tegn eller mindre. Twitter er en måde for venner, familie og kollegaer til "
|
||||
"at kommunikere og holde kontakten gennem udveksling af hurtige, hyppige "
|
||||
"meddelelser. Du kan begrænse levering af opdateringer til dem i din cirkel "
|
||||
@@ -170,7 +169,7 @@ msgstr ""
|
||||
|
||||
#: ../doc/strings.py:25
|
||||
msgid "### Authorising the application"
|
||||
msgstr "### Tillad applikationen"
|
||||
msgstr "### Godkend applikationen"
|
||||
|
||||
#: ../doc/strings.py:26
|
||||
msgid ""
|
||||
@@ -222,8 +221,8 @@ msgid ""
|
||||
"Enter your username and password into the appropriate edit fields if you're "
|
||||
"not already logged in, select the authorise button, and press it."
|
||||
msgstr ""
|
||||
"Standardbrowseren åbnes på Twitter-siden for at anmode om tilladelse. "
|
||||
"Indtast dit Brugernavn og adgangskode i de passende redigeringsfelterne hvis "
|
||||
"Standardbrowseren åbnes på Twitter-siden for at anmode om godkendelse. "
|
||||
"Indtast dit Brugernavn og adgangskode i de passende redigeringsfelter, hvis "
|
||||
"du ikke allerede er logget ind. Vælg så knappen Godkend, og tryk den."
|
||||
|
||||
#: ../doc/strings.py:29
|
||||
@@ -266,7 +265,7 @@ msgid ""
|
||||
"sound, and the screen reader will say \"ready\" (this behaviour can be "
|
||||
"configured)."
|
||||
msgstr ""
|
||||
"Når processen er afsluttet, vil programmet afspilles en anden lyd som "
|
||||
"Når processen er afsluttet, vil programmet afspille en anden lyd som "
|
||||
"standard og skærmlæseren vil sige “Klar” (denne adfærd kan blive "
|
||||
"konfigureret)."
|
||||
|
||||
@@ -352,7 +351,7 @@ msgstr "* Sendte tweets: Denne viser alle tweets sendt fra din konto."
|
||||
|
||||
#: ../doc/strings.py:43
|
||||
msgid "* Likes: here you will see all the tweets you have liked."
|
||||
msgstr "* Synes godt om: Her vil du se alle de tweets, du har synes godt om."
|
||||
msgstr "* Synes godt om: Her vil du se alle de tweets, du synes godt om."
|
||||
|
||||
#: ../doc/strings.py:44
|
||||
msgid ""
|
||||
@@ -422,7 +421,7 @@ msgid ""
|
||||
"geographical region. This region may be a country or a city. Trends are "
|
||||
"updated every five minutes."
|
||||
msgstr ""
|
||||
"* Trending emner: Denne buffer viser top ti mest anvendte udtryk i et "
|
||||
"* Trending emner: Denne buffer viser top ti mest anvendte ord i et "
|
||||
"geografisk område. Dette område kan være et land eller en by. Trends "
|
||||
"opdateres hvert femte minut."
|
||||
|
||||
@@ -494,8 +493,8 @@ msgid ""
|
||||
"* a menu bar accomodating six menus (application, tweet, user, buffer, "
|
||||
"audio and help);"
|
||||
msgstr ""
|
||||
"* en menu bar der består af seks menuer (Applikation, tweet, bruger, buffer, "
|
||||
"lyd og hjælp);"
|
||||
"* en menulinje der består af seks menuer (Applikation, tweet, bruger, "
|
||||
"buffer, lyd og hjælp);"
|
||||
|
||||
#: ../doc/strings.py:59
|
||||
msgid "* One tree view,"
|
||||
@@ -533,7 +532,6 @@ msgid "#### Buttons in the application"
|
||||
msgstr "### Knapper i programmet"
|
||||
|
||||
#: ../doc/strings.py:65
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"* Tweet: this button opens up a dialogue box to write your tweet. Normal "
|
||||
"tweets must not exceed 280 characters. However you can press the long tweet "
|
||||
@@ -550,7 +548,7 @@ msgid ""
|
||||
"message in English describing the problem."
|
||||
msgstr ""
|
||||
"* Tweet: Denne knap åbner en dialogboks hvor du kan skrive dit tweet. "
|
||||
"Normale tweets må ikke overstige 140 tegn. Du kan dog markere checkboksen "
|
||||
"Normale tweets må ikke overstige 280 tegn. Du kan dog markere checkboksen "
|
||||
"“Lang tweet”, og dit tweet vil blive sendt gennem Twishort, som tillader dig "
|
||||
"at skrive længere tweets (10000 tegn). Hvis du skriver og overstiger denne "
|
||||
"grænse, afspilles en lyd for at advare dig. Bemærk at antallet af indtastede "
|
||||
@@ -1762,14 +1760,12 @@ msgid "## Credits"
|
||||
msgstr "## Krediteringer"
|
||||
|
||||
#: ../doc/strings.py:238
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"TWBlue is developed and maintained by [Manuel Cortéz](https://twitter.com/"
|
||||
"manuelcortez00) and [José Manuel Delicado](https://twitter.com/jmdaweb)."
|
||||
msgstr ""
|
||||
"TWBlue er udviklet og vedligeholdt af [Manuel Cort\\303\\251z](https://"
|
||||
"twitter.com/manuelcortez00) og [Jos\\303\\251 Manuel Delicado](https://"
|
||||
"twitter.com/jmdaweb)."
|
||||
"TWBlue et udviklet og vedligeholdt af [Manuel Cortéz](https://twitter.com/"
|
||||
"manuelcortez00) and [José Manuel Delicado](https://twitter.com/jmdaweb)."
|
||||
|
||||
#: ../doc/strings.py:239
|
||||
msgid ""
|
||||
@@ -1796,31 +1792,24 @@ msgid "* Catalan: [Francisco Torres](https://twitter.com/ftgalleg)"
|
||||
msgstr "* Catalansk: [Francisco Torres](https://twitter.com/ftgalleg)"
|
||||
|
||||
#: ../doc/strings.py:243
|
||||
#, fuzzy
|
||||
msgid "* Croatian: [Zvonimir Stanečić](https://twitter.com/zvonimirek222)."
|
||||
msgstr ""
|
||||
"* Kroatisk: [Zvonimir Stane\\304\\215i\\304\\207](https://twitter.com/"
|
||||
"zvonimirek222)."
|
||||
msgstr "* Kroatisk: [Zvonimir Stanečić](https://twitter.com/zvonimirek222)."
|
||||
|
||||
#: ../doc/strings.py:244
|
||||
#, fuzzy
|
||||
msgid "* English: [Manuel Cortéz](https://twitter.com/manuelcortez00)."
|
||||
msgstr ""
|
||||
"* Engelsk: [Manuel Cort\\303\\251z](https://twitter.com/manuelcortez00)."
|
||||
msgstr "* Engelsk: [Manuel Cortéz](https://twitter.com/manuelcortez00)."
|
||||
|
||||
#: ../doc/strings.py:245
|
||||
msgid "* Finnish: [Jani Kinnunen](https://twitter.com/jani_kinnunen)."
|
||||
msgstr "* Finsk: [Jani Kinnunen](https://twitter.com/jani_kinnunen)."
|
||||
|
||||
#: ../doc/strings.py:246
|
||||
#, fuzzy
|
||||
msgid "* French: [Rémy Ruiz](https://twitter.com/blindhelp38)."
|
||||
msgstr "* Fransk: [R\\303\\251my Ruiz](https://twitter.com/blindhelp38)."
|
||||
msgstr "* Fransk: [Rémy Ruiz](https://twitter.com/blindhelp38)."
|
||||
|
||||
#: ../doc/strings.py:247
|
||||
#, fuzzy
|
||||
msgid "* Galician: [Juan Buño](https://twitter.com/Quetzatl_)."
|
||||
msgstr "* Galicisk: [Juan Bu\\303\\261o](https://twitter.com/Quetzatl_)."
|
||||
msgstr "* Galicisk: [Juan Buño](https://twitter.com/Quetzatl_)."
|
||||
|
||||
#: ../doc/strings.py:248
|
||||
msgid "* German: [Steffen Schultz](https://twitter.com/schulle4u)."
|
||||
@@ -1843,44 +1832,37 @@ msgid "* Polish: [Pawel Masarczyk.](https://twitter.com/Piciok)"
|
||||
msgstr "* Polsk: [Pawel Masarczyk.](https://twitter.com/Piciok)"
|
||||
|
||||
#: ../doc/strings.py:253
|
||||
#, fuzzy
|
||||
msgid "* Portuguese: [Odenilton Júnior Santos.](https://twitter.com/romaleif)"
|
||||
msgstr ""
|
||||
"* Portugisisk: [Odenilton J\\303\\272nior Santos.](https://twitter.com/"
|
||||
"romaleif)"
|
||||
"* Portugisisk: [Odenilton Júnior Santos.](https://twitter.com/romaleif)"
|
||||
|
||||
#: ../doc/strings.py:254
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"* Romanian: [Florian Ionașcu](https://twitter.com/florianionascu7) and "
|
||||
"[Nicușor Untilă](https://twitter.com/dj_storm2001)"
|
||||
msgstr ""
|
||||
"* Rumænsk: [Florian Iona\\310\\231cu](https://twitter.com/florianionascu7) "
|
||||
"og [Nicu\\310\\231or Until\\304\\203](https://twitter.com/dj_storm2001)"
|
||||
"* Rumænsk: [Florian Ionașcu](https://twitter.com/florianionascu7) and "
|
||||
"[Nicușor Untilă](https://twitter.com/dj_storm2001)"
|
||||
|
||||
#: ../doc/strings.py:255
|
||||
msgid ""
|
||||
"* Russian: [Наталья Хедлунд](https://twitter.com/Lifestar_n) and [Валерия "
|
||||
"Кузнецова](https://twitter.com/ValeriaK305)."
|
||||
msgstr ""
|
||||
"* Russisk: [Наталья Хедлунд](https://twitter.com/Lifestar_n) and [Валерия "
|
||||
"Кузнецова](https://twitter.com/ValeriaK305)."
|
||||
|
||||
#: ../doc/strings.py:256
|
||||
#, fuzzy
|
||||
msgid "* Serbian: [Aleksandar Đurić](https://twitter.com/sokodtreshnje)"
|
||||
msgstr ""
|
||||
"* Serbisk: [Aleksandar \\304\\220uri\\304\\207](https://twitter.com/"
|
||||
"sokodtreshnje)"
|
||||
msgstr "* Serbisk: [Aleksandar Đurić](https://twitter.com/sokodtreshnje)"
|
||||
|
||||
#: ../doc/strings.py:257
|
||||
#, fuzzy
|
||||
msgid "* Spanish: [Manuel Cortéz](https://twitter.com/manuelcortez00)."
|
||||
msgstr ""
|
||||
"* Spansk: [Manuel Cort\\303\\251z](https://twitter.com/manuelcortez00)."
|
||||
msgstr "* Spansk: [Manuel Cortéz](https://twitter.com/manuelcortez00)."
|
||||
|
||||
#: ../doc/strings.py:258
|
||||
#, fuzzy
|
||||
msgid "* Turkish: [Burak Yüksek](https://twitter.com/burakyuksek)."
|
||||
msgstr "* Tyrkisk: [Burak Y\\303\\274ksek](https://twitter.com/burakyuksek)."
|
||||
msgstr "* Tyrkisk: [Burak Yüksek](https://twitter.com/burakyuksek)."
|
||||
|
||||
#: ../doc/strings.py:259
|
||||
msgid ""
|
||||
@@ -1910,9 +1892,8 @@ msgid "------------------------------------------------------------------------"
|
||||
msgstr "————————————————————————————————————"
|
||||
|
||||
#: ../doc/strings.py:261
|
||||
#, fuzzy
|
||||
msgid "Copyright © 2013-2017. Manuel Cortéz"
|
||||
msgstr "Copyright \\302\\251 2013-2017. Manuel Cort\\303\\251z"
|
||||
msgstr "Copyright © 2013-2017. Manuel Cortéz"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "* Russian: "
|
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: TWBlue Documentation\n"
|
||||
"POT-Creation-Date: 2018-08-07 13:19+Hora de verano central (Mexico)\n"
|
||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
||||
"PO-Revision-Date: 2018-08-08 11:01+0200\n"
|
||||
"Last-Translator: Steffen Schultz <schulle3o@yahoo.de>\n"
|
||||
"Language-Team: Steffen Schultz <schulle3o@yahoo.de>\n"
|
||||
|
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
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: TW Blue documentation 0.46\n"
|
||||
"POT-Creation-Date: 2018-08-07 13:19+Hora de verano central (Mexico)\n"
|
||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
||||
"PO-Revision-Date: 2015-11-27 08:33-0600\n"
|
||||
"Last-Translator: Manuel Cortéz <manuel@manuelcortez.net>\n"
|
||||
"Language-Team: Sukil Echenique <sukiletxe@yahoo.es>\n"
|
||||
|
1014
doc/locales/fi/lc_messages/twblue-changelog.po
Normal file
1014
doc/locales/fi/lc_messages/twblue-changelog.po
Normal file
File diff suppressed because it is too large
Load Diff
2485
doc/locales/fi/lc_messages/twblue-documentation.po
Normal file
2485
doc/locales/fi/lc_messages/twblue-documentation.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
@@ -5,7 +5,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: TW Blue documentation 0.88\n"
|
||||
"POT-Creation-Date: 2018-08-07 13:19+Hora de verano central (Mexico)\n"
|
||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
||||
"PO-Revision-Date: 2018-08-11 12:25+0200\n"
|
||||
"Last-Translator: Rémy Ruiz <remyruiz@gmail.com>\n"
|
||||
"Language-Team: Rémy Ruiz <remyruiz@gmail.com>\n"
|
||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: tw blue documentation 0.46\n"
|
||||
"POT-Creation-Date: 2018-08-07 13:19+Hora de verano central (Mexico)\n"
|
||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
||||
"PO-Revision-Date: 2018-08-08 11:34+0100\n"
|
||||
"Last-Translator: Juan C. Buño <oprisniki@gmail.com>\n"
|
||||
"Language-Team: Alba Quinteiro <alba_080695@hotmail.com>\n"
|
||||
|
BIN
doc/locales/hu/lc_messages/twblue-changelog.mo
Normal file
BIN
doc/locales/hu/lc_messages/twblue-changelog.mo
Normal file
Binary file not shown.
1014
doc/locales/hu/lc_messages/twblue-changelog.po
Normal file
1014
doc/locales/hu/lc_messages/twblue-changelog.po
Normal file
File diff suppressed because it is too large
Load Diff
BIN
doc/locales/hu/lc_messages/twblue-documentation.mo
Normal file
BIN
doc/locales/hu/lc_messages/twblue-documentation.mo
Normal file
Binary file not shown.
1463
doc/locales/hu/lc_messages/twblue-documentation.po
Normal file
1463
doc/locales/hu/lc_messages/twblue-documentation.po
Normal file
File diff suppressed because it is too large
Load Diff
BIN
doc/locales/it/lc_messages/twblue-changelog.mo
Normal file
BIN
doc/locales/it/lc_messages/twblue-changelog.mo
Normal file
Binary file not shown.
1014
doc/locales/it/lc_messages/twblue-changelog.po
Normal file
1014
doc/locales/it/lc_messages/twblue-changelog.po
Normal file
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: TW Blue documentation 0.46\n"
|
||||
"POT-Creation-Date: 2018-08-07 13:19+Hora de verano central (Mexico)\n"
|
||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
||||
"PO-Revision-Date: 2018-08-09 11:51+0100\n"
|
||||
"Last-Translator: Chris Leo Mameli <llajta2012@gmail.com>\n"
|
||||
"Language-Team: \n"
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"POT-Creation-Date: 2018-08-07 13:19+Hora de verano central (Mexico)\n"
|
||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
||||
"PO-Revision-Date: 2018-08-08 19:09+0900\n"
|
||||
"Last-Translator: Masamitsu Misono <misono@nvsupport.org>\n"
|
||||
"Language-Team: NVDA Help Desk <nvdahelp@center-aikoh.net>\n"
|
||||
|
BIN
doc/locales/pl/lc_messages/twblue-changelog.mo
Normal file
BIN
doc/locales/pl/lc_messages/twblue-changelog.mo
Normal file
Binary file not shown.
1090
doc/locales/pl/lc_messages/twblue-changelog.po
Normal file
1090
doc/locales/pl/lc_messages/twblue-changelog.po
Normal file
File diff suppressed because it is too large
Load Diff
BIN
doc/locales/pl/lc_messages/twblue-documentation.mo
Normal file
BIN
doc/locales/pl/lc_messages/twblue-documentation.mo
Normal file
Binary file not shown.
1477
doc/locales/pl/lc_messages/twblue-documentation.po
Normal file
1477
doc/locales/pl/lc_messages/twblue-documentation.po
Normal file
File diff suppressed because it is too large
Load Diff
BIN
doc/locales/pt/lc_messages/twblue-changelog.mo
Normal file
BIN
doc/locales/pt/lc_messages/twblue-changelog.mo
Normal file
Binary file not shown.
1014
doc/locales/pt/lc_messages/twblue-changelog.po
Normal file
1014
doc/locales/pt/lc_messages/twblue-changelog.po
Normal file
File diff suppressed because it is too large
Load Diff
BIN
doc/locales/pt/lc_messages/twblue-documentation.mo
Normal file
BIN
doc/locales/pt/lc_messages/twblue-documentation.mo
Normal file
Binary file not shown.
1478
doc/locales/pt/lc_messages/twblue-documentation.po
Normal file
1478
doc/locales/pt/lc_messages/twblue-documentation.po
Normal file
File diff suppressed because it is too large
Load Diff
285
doc/locales/pt/manual.md
Normal file
285
doc/locales/pt/manual.md
Normal file
@@ -0,0 +1,285 @@
|
||||
% Documentação do TW Blue 0.42
|
||||
|
||||
# Versão 0.42 (alpha)
|
||||
|
||||
# ¡Perigro!
|
||||
|
||||
Você está lendo um documento gerado para uma aplicação em fase de desenvolvimento. A intenção deste manual é esclarecer alguns detalhes sobre o funcionamento do programa. Note-se que sendo desenvolvido ativamente, o software pode mudar um pouco em relação a esta documentação num futuro próximo. Por isso é aconselhável dar uma olhada de vez em quando para não se perder muito.
|
||||
|
||||
Si quieres ver lo que ha cambiado con respecto a la versión anterior, [lee la lista de novedades aquí.](changes.html)
|
||||
|
||||
# TW Blue
|
||||
|
||||
TW Blue é um aplicativo para utilizar o Twitter de forma simples e rápida, além de evitar tanto quanto possível consumir demasiados recursos do computador. Com ele é possível realizar ações do Twitter, tais como:
|
||||
|
||||
* Crear, responder, reenviar y eliminar Tuits,
|
||||
* Marcar como favorito, eliminar de tus favoritos un tuit,
|
||||
* Enviar y eliminar mensajes directos,
|
||||
* Ver tus amigos y seguidores,
|
||||
* Seguir, dejar de seguir, reportar como spam y bloquear a un usuario,
|
||||
* Abrir una línea temporal para un usuario, lo que permite obtener todos los Tuits de ese usuario únicamente,
|
||||
* Abrir direcciones URL cuando vayan en un tuit o mensaje directo,
|
||||
* Reproducir varios tipos de archivos o direcciones que contengan audio.
|
||||
* Y más.
|
||||
|
||||
# Tabla de contenidos
|
||||
|
||||
Para poder utilizar una aplicación como TW Blue que te permita gestionar una cuenta de Twitter, primero tienes que estar registrado en esta red social. Esta documentación no tiene como objetivo explicar el procedimiento para hacerlo. Partiremos desde el punto que tienes una cuenta con su respectivo nombre de usuario y contraseña. La documentación cubrirá estas secciones.
|
||||
|
||||
* [Autorizar la aplicación](#autorizar)
|
||||
* [La interfaz del programa](#interfaz)
|
||||
* [Controles](#controles)
|
||||
* [La interfaz gráfica (GUI)](#gui)
|
||||
* [Botones de la aplicación](#botones)
|
||||
* [Menús](#menus)
|
||||
* [Menú aplicación](#app)
|
||||
* [Menú Tuit](#tuit)
|
||||
* [Menú Usuario](#usuario)
|
||||
* [Menú buffer](#buffer)
|
||||
* [Menú ayuda](#ayuda)
|
||||
* [La interfaz No Visible](#interfaz_no_visible)
|
||||
* [Atajos de Teclado para la Interfaz Gráfica](#atajos)
|
||||
* [Atajos de Teclado para la Interfaz no Visible](#atajos_invisibles)
|
||||
* [Listas](#listas)
|
||||
* [Reportando Errores desde la web](#reportar)
|
||||
* [Contacto](#contacto)
|
||||
|
||||
## Autorizando la aplicación {#autorizar}
|
||||
|
||||
Antes de nada, lo primero que se necesita es autorizar al programa para que este pueda acceder a tu cuenta de Twitter, y desde ella realizar lo que le pidas. El proceso de autorización es bastante sencillo, y en ningún momento el programa podrá tener acceso a tus datos como usuario y contraseña. Para autorizar la aplicación, solo tienes que abrir el archivo principal del programa, llamado TW Blue.exe (en algunos PC, solo se muestra como TW Blue).
|
||||
|
||||
Al hacerlo, si no has configurado ninguna vez el programa, se mostrará un cuadro de diálogo donde te informa que serás llevado a Twitter para autorizar la aplicación una vez pulses sobre "aceptar". Para empezar con el proceso de autorización presiona sobre el único botón de ese diálogo.
|
||||
|
||||
A continuación, tu navegador predeterminado se abrirá con la página de Twitter solicitándote autorizar la aplicación. Escribe, si no estás autenticado ya, tu nombre de usuario y contraseña, luego busca el botón autorizar, y presiónalo.
|
||||
|
||||
De la página a la que serás redirigido (si el proceso ha tenido éxito), busca las instrucciones que te proporciona Twitter. En resumen, te dará un código numérico de varios dígitos que deberás pegar en un cuadro de texto que la aplicación ha abierto en otra ventana.
|
||||
|
||||
Pega el código de verificación, y pulsa la tecla Intro.
|
||||
|
||||
Si todo ha salido bien, la aplicación empezará a reproducir un grupo de sonidos en señal que se están actualizando tus datos.
|
||||
|
||||
Cuando termine, el programa reproducirá otro sonido, y el lector de pantalla dirá "listo".
|
||||
|
||||
## La interfaz del programa {#interfaz}
|
||||
|
||||
La forma más simple de describir la interfaz gráfica de la aplicación es la de una ventana con una barra de menú con cinco menús (aplicación, tuit, usuario, buffer y ayuda); una lista de varios elementos y en la mayoría de los casos tres botones. Tuit, retuit y responder. Las acciones para cada uno de estos elementos serán descritas más adelante.
|
||||
|
||||
Los elementos que hay en las listas pueden ser Tuits, mensajes directos o usuarios. TW Blue crea diferentes pestañas para cada lista, pues estos elementos pueden ser Tuits enviados, Tuits recividos en la línea principal, favoritos, o mensajes directos, y cada pestaña tiene un solo tipo de Tuit. Estas pestañas se llaman listas o buffers.
|
||||
|
||||
Para cambiar entre las listas se hace presionando Control+Tab si se desea avanzar, y Control+Shift+Tab para retroceder. En todo momento los lectores de pantalla anunciarán la lista hacia la que se cambie el foco de la aplicación. Aquí están las listas básicas de TW Blue, que aparecen si se usa la configuración por defecto.
|
||||
|
||||
* Principal: Aquí van todos los Tuits que se muestran en la línea principal. Estos son los Tuits de los usuarios a los que sigues.
|
||||
* Menciones: Si un usuario (lo sigas o no) te menciona en Twitter, lo verás en esta lista.
|
||||
* Mensajes directos: Aquí están los mensajes directos (privados) que intercambias con los usuarios que sigues y te siguen. Esta lista solo muestra los mensajes recividos.
|
||||
* Enviados: En esta lista se muestran todos los Tuits y mensajes directos que se han enviado desde tu cuenta.
|
||||
* Favoritos: Aquí verás los Tuits que has marcado como favoritos.
|
||||
* Seguidores: Cuando los usuarios sigan tu cuenta, podrás verlos en esta lista, junto con un poco de información de la cuenta.
|
||||
* Amigos: Igual que la lista anterior, pero estos usuarios son a los que tú sigues.
|
||||
* Eventos: Un evento en TW Blue es "algo" que pase en Twitter. En la línea de eventos, podrás ver registrados los eventos más comunes (p. Ej. Te han comenzado a seguir, han marcado o removido un tweet tuyo de los favoritos, te has suscrito a una lista). Son como pequeñas notificaciones que envía Twitter y TW Blue organiza para que no te pierdas lo que ha pasado con tu cuenta.
|
||||
* Línea temporal de un usuario: Estas son listas que tú deberás crear. Es una lista que contiene únicamente los Tuits de un usuario. Se usan si algún día necesitas o quieres ver los Tuits que ha realizado solo una persona y no deseas buscar por todo tu timeline. Puedes crear tantas como usuarios necesites.
|
||||
* Lista: Una lista es parecida a una línea temporal, pero compuesta por los tweets de cada usuario que forme parte de ella. De momento las listas son una característica experimental de TW Blue. Si experimentas problemas con ellas, por favor escríbenos para contárnoslo.
|
||||
* Búsqueda: Un buffer de búsqueda contiene los resultados de una búsqueda hecha en TW Blue. Las búsquedas pueden ser por tuits, en cuyo caso buscas un término en los tuits relevantes de Twitter, o por usuarios, donde los resultados son nombres de usuario de Twitter.
|
||||
* Favoritos de un usuario: Es posible pedirle a TW Blue que te muestre los tuits que un usuario ha marcado como favoritos.
|
||||
|
||||
Nota: Únicamente para esta versión de TW Blue, los amigos y seguidores actualizarán hasta 400, o cerca a los 400. En la próxima versión proporcionaremos un método para ver los amigos y seguidores sin exponerse tanto a los errores causados por el uso de la API de Twitter, muy frecuente entre personas con más de 600 amigos o seguidores.
|
||||
|
||||
Ten en cuenta que por defecto la configuración solo permite obtener los 200 últimos Tuits para las listas principal, menciones, mensajes directos y líneas temporales. Esto puedes cambiarlo desde el diálogo de configuración. Para los enviados se obtendrán los últimos 200 Tuits y 200 mensajes directos. En versiones futuras se permitirá ajustar este parámetro.
|
||||
|
||||
Si hay una dirección URL en algún tuit, TW Blue intentará abrirla cuando presiones Intro sobre ella. Si hay más de una, te mostrará una lista con todas para que selecciones la que quieras abrir. Si estás en el cuadro de diálogo de los amigos o seguidores, la tecla intro te mostrará detalles del mismo.
|
||||
|
||||
Si pulsas Control+Intro, TW Blue intentará reproducir el audio que tenga el tuit sobre el que está el foco del sistema, siempre que tenga una URL. Si el tuit lleva la etiqueta #audio, un sonido al pasar por él te alertará que es un audio y puedes intentar reproducirlo. No obstante, también puede que no esté etiquetado y que TW Blue pueda reproducirlo, siempre que lleve a una dirección URL donde exista audio.
|
||||
|
||||
## Controles {#controles}
|
||||
|
||||
A partir de la versión 0.36, existe soporte para una interfaz que no requiere de una ventana visible. Esta puede ser activada pulsando Control+m, o seleccionando desde el menú aplicación la opción "Esconder ventana". Esta interfaz se maneja completamente con atajos de teclado. Estos atajos son diferentes a los que se utilizan para la interfaz gráfica. Cada una de ellas podrá utilizar solo los atajos que le correspondan, lo que quiere decir que no se permitirá utilizar los atajos de la interfaz no visible si se tiene activada la interfaz gráfica. En esta sección se detallará tanto la interfaz gráfica como la no visible.
|
||||
|
||||
### Interfaz gráfica (GUI) {#gui}
|
||||
|
||||
Aquí una lista dividida en dos partes. Por un lado, los botones que encontrarás si presionas Tab o Shift+Tab en la interfaz del programa, y por otro, los diferentes elementos que hay en la barra de menú.
|
||||
|
||||
#### Botones de la aplicación {#botones}
|
||||
|
||||
* Twit: Este botón abre el diálogo para escribir un tuit. El mensaje solo debe tener 140 caracteres. Al escribir el caracter número 141, un sonido será reproducido para indicarte que te has pasado del límite permitido por Twitter. Puedes querer acortar o desacortar una URL si la incluye tu tuit a fin de ganar más espacio donde escribir, para eso están los botones con esos nombres. Pulsa Intro para enviar el tuit. Si todo sale bien, el mensaje se enviará y tú escucharás un sonido que te lo confirme, si no, el lector de pantalla te responderá con un error en inglés, que indica por qué no se ha podido enviar el mensaje.
|
||||
* Retuit: Este botón se encarga de reenviar el tuit sobre el que estás leyendo. Al presionarlo se te preguntará si deseas añadirle un comentario al tuit original (citándolo) o simplemente enviarlo como se ha escrito sin añadir nada más.
|
||||
* Responder: Cuando estés visualizando un Tuit, puedes responderle al usuario que lo escribió pulsando sobre este botón. Se abrirá el mismo diálogo de Tuit, pero con el nombre del usuario (por ejemplo @usuario) en el, para que solo escribas el mensaje que quieres responderle. Si en el tuit hay más de un usuario mencionado, pulsa Shift+Tab y pulsa el botón "Mencionar a todos los usuarios". Cuando estés en la lista de amigos o seguidores, este botón se llamará mencionar.
|
||||
* mensaje directo: Exactamente igual que enviar un Tuit, pero es un mensaje privado que solo podrá ver el usuario al que se lo envías. Pulsa Shift+Tab para ver el destinatario de tu mensaje. Si en el Tuit donde estabas para enviar el mensaje había más de un usuario mencionado, puedes navegar con las flechas de arriba y abajo para seleccionar otro, o escribir tú mismo el usuario (sin el signo de arroba).
|
||||
|
||||
Ten en cuenta que los botones aparecerán según las acciones que se puedan hacer en la lista donde estés. Por ejemplo, en la línea principal, menciones, enviados, favoritos y las líneas temporales de los usuarios podrás ver los cuatro botones; mientras que en la lista de mensajes directos solo estará disponible el botón de "Mensaje Directo" y "tuit", y en las listas de amigos y seguidores, se verá el botón para "Twit" y el de "Mensaje directo" junto a "mencionar".
|
||||
|
||||
#### Menús {#menus}
|
||||
|
||||
En la parte superior de la ventana del programa podrás encontrar una barra de menú que hace las mismas cosas, y algunas cuantas más. A la barra de menú se accede presionando la tecla ALT, y cuenta en este momento con cuatro menús para diferentes acciones: Aplicación, Tuit, usuario y Ayuda. En esta sección se describen las acciones para cada uno de ellos.
|
||||
|
||||
##### Menú aplicación {#app}
|
||||
|
||||
* Actualizar Perfil: Abre un diálogo desde donde se podrá actualizar parte de tu información en Twitter. Nombre, ubicación, dirección URL y descripción. Si ya tienes alguno de estos campos actualmente en el perfil se llenarán automáticamente con lo que tiene tu configuración de Twitter. También podrás subir una foto a tu perfil.
|
||||
* Esconder Ventana: Desactiva la interfaz gráfica. Lee el apartado sobre la interfaz no visible para más detalles sobre este comportamiento.
|
||||
* Búsqueda: Muestra un cuadro de diálogo desde donde puedes buscar por tuits o por usuarios en twitter.
|
||||
* Gestor de listas: Para poder utilizar las listas de Twitter, primero necesitarás crearlas. Este diálogo permite ver tus listas, editarlas, crearlas, borrarlas y, opcionalmente, verlas en buffers tal como lo harías con las líneas temporales.
|
||||
* Tutorial de sonidos: Abre un diálogo donde verás una lista de los sonidos de TW blue, para que puedas aprenderlos y no te cueste trabajo familiarizarte con TW Blue.
|
||||
* Preferencias: Abre un diálogo de configuración desde donde se pueden controlar algunos aspectos del programa. Las opciones no necesitan de explicación.
|
||||
* Salir: pregunta si quieres salir o no del programa. Si la respuesta es que sí, cierra la aplicación.
|
||||
|
||||
##### Menú Tuit {#tuit}
|
||||
|
||||
* Las primeras opciones del menú son Twit, responder y retuit, que corresponden a los botones del mismo nombre.
|
||||
* Marcar como favorito: Marca el tuit que estés viendo como favorito.
|
||||
* Quitar tuit de favoritos: Elimina el tuit de tus favoritos. Esto no significa que se borra de Twitter, solo deja de estar en tu lista de favoritos.
|
||||
* Ver Tuit: Abre un diálogo donde puedes ver el Tuit, mensaje directo, amigo o seguidor sobre el que esté el foco de la aplicación. Puedes leer el texto con los cursores. El diálogo es el mismo que el que se usa para escribir un Tuit.
|
||||
* Eliminar: Elimina el Tuit o mensaje directo sobre el que estés, borrándolo definitivamente de Twitter y qitándolo de tus listas. Ten en cuenta que en el caso de los Tuits, Twitter solo permite borrar los que tú mismo has escrito.
|
||||
|
||||
##### Menú usuario {#usuario}
|
||||
|
||||
Ten en cuenta que las primeras seis opciones de este menú abren un mismo diálogo. Este diálogo tiene un cuadro de edición donde puedes seleccionar el usuario sobre el que deseas actuar, bien con los cursores arriba y abajo o escribiendo tú mismo el nombre. Después, hay un grupo de botones de radio para seguir, dejar de seguir, silenciar, des-silenciar, reportar como Spam y bloquear. Si seleccionas desde el menú la opción seguir, el botón del cuadro de diálogo estará marcado con esa opción, así como sucederá respectivamente con dejar de seguir, reportar como Spam y bloquear. Pulsa el botón Aceptar para que el programa trate de hacer lo que le pides. Si no se ha podido, escucharás el error en inglés.
|
||||
|
||||
A continuación se describen las opciones restantes para este menú:
|
||||
|
||||
* Mensaje Directo: La misma acción que el botón.
|
||||
* Añadir a lista: Para que puedas ver los tweets de un usuario en tus listas, primero hay que añadirlo. Esta opción abrirá un diálogo desde donde puedes seleccionar al usuario que deseas añadir, para después abrir otra ventana donde puedes seleccionar la lista a la cual añadir a ese usuario. Una vez hecho esto, la lista contendrá un nuevo usuario y podrás ver sus tweets.
|
||||
* Ver Perfil del usuario: Abre un diálogo desde donde te permite seleccionar el usuario al que quieres ver el perfil.
|
||||
* Línea temporal: Abre un diálogo desde donde puedes seleccionar el usuario para el que se creará la línea temporal. Al presionar intro, se creará. Si se hace una línea temporal de un usuario que no tenga Tuits, el programa fallará. Si se crea una línea que ya existe el programa te avisará y no permitirá crearla de nuevo.
|
||||
* Ver favoritos: Abre un buffer para seguir los favoritos que marca el usuario seleccionado.
|
||||
|
||||
##### Menú Buffer {#buffer}
|
||||
|
||||
* Silenciar: Silencia completamente el buffer, con lo que no escucharás sonido alguno cuando nuevos elementos aparezcan.
|
||||
* Leer automáticamente tuits para este buffer: Esta opción activa o desactiva la lectura automática de tuits. Si está activada, el lector de pantalla o la voz Sapi5 (si está activada una) leerá automáticamente los nuevos tuits conforme estos vayan llegando al buffer.
|
||||
* Limpiar Buffer: Vacía los elementos de este buffer.
|
||||
* Eliminar buffer: Borra la lista sobre la que te encuentras actualmente.
|
||||
|
||||
##### Menú Ayuda {#ayuda}
|
||||
|
||||
* Documentación: Abre este archivo, donde puedes leer algunos conceptos interesantes del programa.
|
||||
* ¿Qué hay de nuevo en esta versión?: Abre un documento con la lista de cambios desde la versión actual, hasta la primera en existencia.
|
||||
* Buscar actualizaciones: Cada que se abre el programa él mismo busca automáticamente si hay una nueva versión. Si lo hay, te preguntará si quieres descargarla; si aceptas, TW Blue descargará la actualización, la instalará y te pedirá reiniciarla (algo que hace automáticamente). Esta opción comprueba si hay actualizaciones sin tener que reiniciar la aplicación.
|
||||
* Sitio web de TW Blue. Ve a nuestra [página principal](http://twblue.com.mx) donde podrás encontrar toda la información y descargas relativas a TW Blue, así como participar de la comunidad.
|
||||
* Reportar un error: Lanza un diálogo desde donde puedes reportar un error solo llenando un par de campos. El título y una pequeña descripción de lo que pasó. Al pulsar en "enviar" el error se reportará. Si no se ha podido el programa te mostrará un mensaje informándolo.
|
||||
* Sobre TW Blue: Muestra información de créditos del programa.
|
||||
|
||||
### Interfaz no visible {#interfaz_no_visible}
|
||||
|
||||
Si presionas Control+M, o si desde el menú aplicación seleccionas esconder ventana, estarás activando una interfaz a la que no se podrá acceder por la manera convencional, porque no se ve.
|
||||
|
||||
En la interfaz no visible todo lo que hagas será mediante atajos de teclado, incluso para recorrer las listas. Eventualmente se abrirán diálogos y estos sí serán visibles, pero la ventana principal de la aplicación no. Ve a la sección de atajos de teclado de la interfaz no visible para saber cuales puedes usar de momento.
|
||||
|
||||
### Atajos de teclado para la Interfaz Gráfica {#atajos}
|
||||
|
||||
Además de los botones y menús, la mayoría de las acciones pueden hacerse presionando una combinación de teclado. Aquí están las existentes en este momento:
|
||||
|
||||
* Intro: Abrir una dirección URL. Si hay más de una podrás ver una lista que te permitirá seleccionar la que quieras. Si estás en la lista de amigos o seguidores, mostrará detalles del seleccionado.
|
||||
* Control+Intro: Intenta reproducir un audio si en el Tuit hay una dirección URL.
|
||||
* F5: Baja un 5% el volumen de los sonidos. Esto afecta a los sonidos que reproduce el programa y al audio que puedas escuchar a través de él.
|
||||
* F6: Sube un 5% el volumen de los sonidos de la aplicación.
|
||||
* Control+N: Abre el diálogo para escribir un nuevo Tuit.
|
||||
* Control+M: Oculta la ventana.
|
||||
* Control+Q: Sale de la aplicación.
|
||||
* Control+R: Abre el diálogo para responder.
|
||||
* Control+Shift+R: Equivalente a la acción Retuit.
|
||||
* Control+D: Enviar mensaje directo.
|
||||
* Control+F: Marcar como favorito.
|
||||
* Control+Shift+F: Quitar de favoritos.
|
||||
* Control+Shift+V: Ver Tuit.
|
||||
* Control+S: Seguir a un usuario.
|
||||
* Control+Shift+S: Dejar de seguir a un usuario.
|
||||
* Control+K: Bloquear a un usuario.
|
||||
* Control+Shift+K: Reportar como Spam.
|
||||
* Control+I: Abrir línea temporal a un usuario.
|
||||
* Control+Shift+I: Eliminar línea temporal.
|
||||
* Control+p: Editar tu perfil.
|
||||
* Suprimir: Eliminar tuit o mensaje directo.
|
||||
* Shift+suprimir: vacía el buffer, quitando todos los elementos hasta ese entonces. Esto ocurre sin borrar nada de Twitter.
|
||||
|
||||
### Atajos de teclado para la Interfaz no Visible {#atajos_invisibles}
|
||||
|
||||
Estos son los atajos de teclado que puedes usar desde la interfaz no visible. Ten en cuenta que cuando la vista de la interfaz gráfica esté activada ninguno de ellos podrá usarse. Al decir "windows", nos estamos refiriendo a la tecla de Windows izquierda.
|
||||
|
||||
* Control+Windows+Flecha Arriba: Va arriba en la lista actual.
|
||||
* Control+Windows+Flecha abajo: Va hacia abajo en la lista actual.
|
||||
* Control+Windows+Izquierda: Se desplaza a la pestaña de la izquierda.
|
||||
* Control+Windows+Derecha: Se desplaza hacia la pestaña de la derecha.
|
||||
* Control+Windows+Inicio: Ir al primer elemento de la lista.
|
||||
* Control+Windows+Fin: Ir al final de la lista.
|
||||
* Control+Windows+Avance de página: Ir 20 elementos hacia abajo en la lista actual.
|
||||
* Control+Windows+Retroceso de página: ir 20 elementos hacia arriba en la lista actual.
|
||||
* Control+Windows+Alt+Flecha Arriba: Subir volumen un 5%.
|
||||
* Control+Windows+Alt+Flecha Abajo: Bajar volumen un 5%.
|
||||
* Control+Windows+Intro: Abrir URL en el tuit, o ver detalles del usuario si estás en la lista de amigos o seguidores.
|
||||
* Control+Windows+Alt+Intro: Intentar reproducir un audio.
|
||||
* Control+Windows+M: Muestra la interfaz gráfica, desactivando la no visible.
|
||||
* Control+Windows+N: Hacer un nuevo Tuit.
|
||||
* Control+Windows+R: Responder a un tuit.
|
||||
* Control+Windows+Shift+R: Hacer un retuit.
|
||||
* Control+Windows+D: Enviar un mensaje directo.
|
||||
* Control+Windows+Suprimir: Eliminar un tuit o mensaje directo.
|
||||
* control+win+Shift+suprimir: vacía el buffer, quitando todos los elementos hasta ese entonces. Esto ocurre sin borrar nada de Twitter.
|
||||
* Windows+Alt+F: Marcar como favorito.
|
||||
* Windows+Alt+Shift+F: Quitar de favoritos.
|
||||
* Control+Windows+S: Seguir a un usuario.
|
||||
* Control+Windows+Shift+S: Dejar de seguir a alguien.
|
||||
* Control+Windows+Alt+N: Ver detalles de un usuario,
|
||||
* Control+Windows+V: Ver tuit en un cuadro de texto.
|
||||
* Control+Windows+I: Abrir línea temporal.
|
||||
* Control+Windows+Shift+I: Eliminar línea temporal de un usuario.
|
||||
* Alt+Windows+P: Editar tu perfil.
|
||||
* Control+win+espacio: ver tweet actual.
|
||||
* Control+win+c: Copiar tweet al portapapeles.
|
||||
* Control+windows+a: Añadir a un usuario a la lista.
|
||||
* Control+shift+windows+a: qitar de la lista.
|
||||
* Control+Windows+Shift+Flecha arriba: Ir un tuit hacia arriba en la conversación.
|
||||
* Control+Windows+Flecha Abajo: Ir un tuit hacia abajo en la conversación.
|
||||
* Control+Windows+Shift+M: Activar o desactivar el sonido para el buffer actual.
|
||||
* Windows+Alt+M: Activar o desactivar el silencio global de TW Blue.
|
||||
* Control+Windows+E: Activar o desactivar la lectura automática de los tuits en el buffer actual.
|
||||
* Control+windows+Guion: buscar en Twitter.
|
||||
* Control+Windows+F4: Cerrar el programa.
|
||||
|
||||
## Listas {#listas}
|
||||
|
||||
Una de las características más interesantes de Twitter son las listas, ya que son una manera de mantenerse actualizado sin tener que leer los tweets de todos los usuarios a los que sigues. Con una lista de Twitter solo verás los tweets de sus miembros (la gente que está dentro de la lista). Es parecido a una línea temporal, pero para muchos más usuarios.
|
||||
|
||||
En TW blue hemos empezado a dar soporte para esta característica. De momento vamos poco a poco, pero ya es posible usar esta función. Te presentamos los pasos que hay que dar para poder tener una lista abierta en TW Blue.
|
||||
|
||||
* Primero necesitarás ir al gestor de listas, ubicado bajo el menú aplicación.
|
||||
* en el gestor de listas podrás ver todas las listas a las que estás unido, empezando por las que tú has creado. Si no ves ninguna lista en este diálogo, significa que no has creado ni te has unido a ninguna lista. Está bien.
|
||||
* Verás un grupo de botones que se explican por sí solos: Crear nueva lista, editar, eliminar, abrir en buffer (este quizá es el menos claro, se refiere a abrir un nuevo buffer para que TW Blue actualice los tweets de la lista, como cuando pasa con las líneas temporales).
|
||||
|
||||
Una vez que hayas creado una nueva lista, no deberías abrirla en buffer. Al menos no de inmediato, porque en este momento no tiene miembro alguno y eso significa que cuando se carguen los tweets para empezar a actualizarla no verás nada. Es recomendable primero añadir a gente a la lista, tal como sigue:
|
||||
|
||||
* Cuando hayas cerrado el gestor de listas y estés navegando por entre los tweets de los usuarios, busca el usuario al que quieres añadir a la lista.
|
||||
* Una vez encontrado, presiona el atajo Ctrl+Win+A o ve al menú usuario y selecciona la opción "Añadir a lista".
|
||||
* Lo siguiente que verás es un diálogo que te permitirá seleccionar el usuario, asegúrate que el que está como predeterminado es el que deseas, o cámbialo si es necesario, y presiona Aceptar.
|
||||
* Ahora verás otro diálogo, pero aquí están todas tus listas. Selecciona una (simplemente lleva el cursor hacia ella), y presiona el botón añadir.
|
||||
* Para qitar a un usuario de una lista repite el mismo proceso, pero presiona Control+Win+Shift+A o selecciona la opción "Quitar de lista", y en el diálogo de las listas presiona sobre el botón "remover".
|
||||
|
||||
## Reportando Errores Desde la Web {#reportar}
|
||||
|
||||
Nota: Si estás usando el programa también puedes reportar un error desde el mismo, usando para ello la opción del menú ayuda. Este proceso solo te pide llenar dos cuadros de edición, y se encarga del resto. Estos pasos están escritos para quienes no pueden abrir el programa, no lo tienen en uso en este momento o sencillamente quieran reportar desde la web en lugar del sistema integrado de reporte de errores.
|
||||
|
||||
Las cosas en este mundo (sí, incluidos los programas informáticos) están muy lejos de ser perfectas, con lo que a menudo te encontrarás con errores no previstos en la aplicación. Pero como la intención es siempre mejorar, eres libre (es más, sería genial que lo hicieras) de reportar los errores que vayas encontrando del programa para que se puedan revisar y eventualmente corregir.
|
||||
|
||||
Para entrar a la web de reporte de incidencias, sigue [Este enlace.](http://twblue.com.mx/errores/bug_report_page.php) Es una web con un formulario donde tienes que llenar varios campos. Solo tres de ellos son realmente obligatorios (los que tienen marcado un asterisco), pero entre más campos puedas llenar, será mejor.
|
||||
|
||||
Aquí están los diferentes campos del formulario y lo que deberías introducir en cada uno de ellos. Recuerda que son obligatorios solamente los campos marcados con un asterisco (*):
|
||||
|
||||
* Categoría: Este cuadro combinado permite seleccionar a qué categoría asignar el error. Puede ser a la categoría General, si es un error del programa, o a documentación, si has encontrado un error en este archivo o en la lista de cambios. Este campo es obligatorio.
|
||||
* Reproducibilidad: Aquí deberías indicar qué tan fácil o no es de reproducir el error. Las opciones disponibles son Desconocido, No reproducible, No se ha intentado (por defecto), aleatorio, a veces o siempre. Dependiendo de si se puede reproducir el error o no, deberías indicar lo que se parezca más a tu caso. Si estás solicitando una nueva funcionalidad, no importa este cuadro combinado.
|
||||
* Severidad: Aquí se selecciona que tanto afecta esto al programa. Las opciones disponibles son funcionalidad (selecciona esto para solicitar una nueva funcionalidad), Trivial, Texto, Ajuste, Menor, Mayor, fallo o bloqueo. Nota que las opciones aumentan de nivel. Selecciona lo que más creas. Si no estás seguro de que seleccionar puedes dejarlo como está.
|
||||
* Prioridad: En este cuadro se selecciona la opción de acuerdo con la importancia del error o funcionalidad solicitada. Las opciones disponibles son Ninguna, baja, normal, alta, hurgente e inmediata.
|
||||
* Seleccionar Perfil: Aquí puedes escojer entre la configuración de arquitectura (32 o 64 bits), y el sistema operativo (Windows siete de momento). Si no, puedes llenar los tres cuadros de edición que están en la siguiente tabla con tus datos en específico.
|
||||
* Versión del producto: Selecciona la versión del programa que estás utilizando para poder averiguar donde se ha generado el error. Este cuadro combinado tendrá la lista de las versiones en orden. Si bien no es obligatorio, ayudaría mucho a resolver más rápidamente el error.
|
||||
* Resumen: Un título para el error, que explique en pocas palabras qué ocurre. Es un cuadro de texto obligatorio.
|
||||
* Descripción: Este campo también obligatorio, te pide que describas con más detalles qué fue lo que ha ocurrido con el programa.
|
||||
* Pasos para reproducir: Este campo de texto te sirve si sabes como hacer que la aplicación genere el error. Esto no es obligatorio, pero ayudaría mucho conocer como hacer que el programa tenga este error para rastrearlo mejor.
|
||||
* Información adicional: Si tienes un comentario o nota que añadir, aquí puede ir. No es obligatorio.
|
||||
* Subir archivo: Puedes subir aquí el archivo TW Blue.exe.log que se creó con el error que el programa tuvo. No es obligatorio.
|
||||
* Visibilidad: Selecciona si quieres que el error sea público o privado. Por defecto es público, y es recomendable que así continúe.
|
||||
* Enviar reporte. Presiona aquí para publicar el error y que este sea atendido.
|
||||
|
||||
Muchas gracias por participar reportando errores y probando las funciones nuevas.
|
||||
|
||||
## Contacto {#contacto}
|
||||
|
||||
Si lo que se expone en este documento no es suficiente, si deseas colaborar de alguna otra forma o si simplemente deseas mantenerte en contacto con quien hace esta aplicación, sigue a la cuenta [@tw_blue2](https://twitter.com/tw_blue2) o a [@manuelcortez00.](https://twitter.com/manuelcortez00) También puedes visitar nuestro [Sitio web](http://twblue.com.mx)
|
||||
|
||||
---
|
||||
Copyright © 2013-2014. Manuel Cortéz.
|
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: twblue-documentation 0.46\n"
|
||||
"POT-Creation-Date: 2018-08-07 13:19+Hora de verano central (Mexico)\n"
|
||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
||||
"PO-Revision-Date: 2018-08-08 10:32+0300\n"
|
||||
"Last-Translator: Florian Ionașcu <florianionascu@hotmail.com>\n"
|
||||
"Language-Team: Spanish <manuel@manuelcortez.net>\n"
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: TW Blue documentation 0.46\n"
|
||||
"POT-Creation-Date: 2018-08-07 13:19+Hora de verano central (Mexico)\n"
|
||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
||||
"PO-Revision-Date: 2018-08-14 21:44+0400\n"
|
||||
"Last-Translator: Valeria <luciana.lu3a@gmail.com>\n"
|
||||
"Language-Team: \n"
|
||||
|
BIN
doc/locales/tr/lc_messages/twblue-changelog.mo
Normal file
BIN
doc/locales/tr/lc_messages/twblue-changelog.mo
Normal file
Binary file not shown.
1109
doc/locales/tr/lc_messages/twblue-changelog.po
Normal file
1109
doc/locales/tr/lc_messages/twblue-changelog.po
Normal file
File diff suppressed because it is too large
Load Diff
BIN
doc/locales/tr/lc_messages/twblue-documentation.mo
Normal file
BIN
doc/locales/tr/lc_messages/twblue-documentation.mo
Normal file
Binary file not shown.
1611
doc/locales/tr/lc_messages/twblue-documentation.po
Normal file
1611
doc/locales/tr/lc_messages/twblue-documentation.po
Normal file
File diff suppressed because it is too large
Load Diff
67
doc/paths.py
Normal file
67
doc/paths.py
Normal file
@@ -0,0 +1,67 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import sys
|
||||
import platform
|
||||
import os
|
||||
import glob
|
||||
from platform_utils import paths as paths_
|
||||
|
||||
mode = "portable"
|
||||
directory = None
|
||||
fsencoding = sys.getfilesystemencoding()
|
||||
|
||||
if len(glob.glob("Uninstall.exe")) > 0: # installed copy
|
||||
mode= "installed"
|
||||
|
||||
def app_path():
|
||||
return paths_.app_path()
|
||||
|
||||
def config_path():
|
||||
global mode, directory
|
||||
if mode == "portable":
|
||||
if directory != None: path = os.path.join(directory, "config")
|
||||
elif directory == None: path = os.path.join(app_path(), "config")
|
||||
elif mode == "installed":
|
||||
path = os.path.join(data_path(), "config")
|
||||
if not os.path.exists(path):
|
||||
# log.debug("%s path does not exist, creating..." % (path,))
|
||||
os.mkdir(path)
|
||||
return path
|
||||
|
||||
def logs_path():
|
||||
global mode, directory
|
||||
if mode == "portable":
|
||||
if directory != None: path = os.path.join(directory, "logs")
|
||||
elif directory == None: path = os.path.join(app_path(), "logs")
|
||||
elif mode == "installed":
|
||||
path = os.path.join(data_path(), "logs")
|
||||
if not os.path.exists(path):
|
||||
# log.debug("%s path does not exist, creating..." % (path,))
|
||||
os.mkdir(path)
|
||||
return path
|
||||
|
||||
def data_path(app_name='socializer'):
|
||||
if platform.system() == "Windows":
|
||||
data_path = os.path.join(os.getenv("AppData"), app_name)
|
||||
else:
|
||||
data_path = os.path.join(os.environ['HOME'], ".%s" % app_name)
|
||||
if not os.path.exists(data_path):
|
||||
os.mkdir(data_path)
|
||||
return data_path
|
||||
|
||||
def locale_path():
|
||||
return os.path.join(app_path(), "locales")
|
||||
|
||||
def sound_path():
|
||||
return os.path.join(app_path(), "sounds")
|
||||
|
||||
def com_path():
|
||||
global mode, directory
|
||||
if mode == "portable":
|
||||
if directory != None: path = os.path.join(directory, "com_cache")
|
||||
elif directory == None: path = os.path.join(app_path(), "com_cache")
|
||||
elif mode == "installed":
|
||||
path = os.path.join(data_path(), "com_cache")
|
||||
if not os.path.exists(path):
|
||||
# log.debug("%s path does not exist, creating..." % (path,))
|
||||
os.mkdir(path)
|
||||
return path
|
@@ -20,8 +20,8 @@ CommercialUse=true
|
||||
EULAVersion=2
|
||||
|
||||
[Version]
|
||||
PackageVersion=0.94.0.0
|
||||
DisplayVersion=0.94
|
||||
PackageVersion=0.95.0.0
|
||||
DisplayVersion=0.95
|
||||
|
||||
[Control]
|
||||
Icons=1
|
||||
|
@@ -1,4 +1,4 @@
|
||||
wxpython
|
||||
wxpython==4.0.3
|
||||
six
|
||||
configobj
|
||||
markdown
|
||||
@@ -7,7 +7,7 @@ requests
|
||||
oauthlib
|
||||
requests-oauthlib
|
||||
requests-toolbelt
|
||||
pypubsub==3.3.0
|
||||
pypubsub
|
||||
pygeocoder
|
||||
arrow
|
||||
python-dateutil
|
||||
@@ -21,6 +21,12 @@ chardet
|
||||
urllib3
|
||||
youtube-dl
|
||||
python-vlc
|
||||
pywin32
|
||||
pypiwin32
|
||||
certifi
|
||||
backports.functools_lru_cache
|
||||
cx_freeze
|
||||
git+https://github.com/manuelcortez/twython
|
||||
git+https://github.com/manuelcortez/libloader
|
||||
git+https://github.com/manuelcortez/platform_utils
|
||||
git+https://github.com/manuelcortez/accessible_output2
|
||||
git+https://github.com/jmdaweb/sound_lib
|
@@ -15,10 +15,10 @@ SetCompressor /solid lzma
|
||||
SetDatablockOptimize on
|
||||
VIAddVersionKey ProductName "TWBlue"
|
||||
VIAddVersionKey LegalCopyright "Copyright 2018 Manuel Cortéz."
|
||||
VIAddVersionKey ProductVersion "0.94"
|
||||
VIAddVersionKey FileVersion "0.94"
|
||||
VIProductVersion "0.94.0.0"
|
||||
VIFileVersion "0.94.0.0"
|
||||
VIAddVersionKey ProductVersion "0.95"
|
||||
VIAddVersionKey FileVersion "0.95"
|
||||
VIProductVersion "0.95.0.0"
|
||||
VIFileVersion "0.95.0.0"
|
||||
!insertmacro MUI_PAGE_WELCOME
|
||||
!define MUI_LICENSEPAGE_RADIOBUTTONS
|
||||
!insertmacro MUI_PAGE_LICENSE "license.txt"
|
||||
@@ -72,10 +72,10 @@ WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "D
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "UninstallString" '"$INSTDIR\uninstall.exe"'
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall" "InstallLocation" $INSTDIR
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall" "Publisher" "Manuel Cortéz"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "DisplayVersion" "0.94"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "DisplayVersion" "0.95"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "URLInfoAbout" "http://twblue.es"
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "VersionMajor" 0
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "VersionMinor" 94
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "VersionMinor" 95
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "NoModify" 1
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "NoRepair" 1
|
||||
SectionEnd
|
||||
|
@@ -1,33 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
import ctypes
|
||||
import os
|
||||
import types
|
||||
from platform_utils import paths
|
||||
|
||||
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)
|
||||
if cdll:
|
||||
return ctypes.cdll[libfile]
|
||||
else:
|
||||
return ctypes.windll[libfile]
|
||||
|
||||
def get_output_classes():
|
||||
from . import outputs
|
||||
module_type = types.ModuleType
|
||||
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():
|
||||
import os
|
||||
import platform
|
||||
from glob import glob
|
||||
import accessible_output2
|
||||
if platform.system() != 'Windows':
|
||||
return []
|
||||
path = os.path.join(accessible_output2.__path__[0], 'lib', '*.dll')
|
||||
results = glob(path)
|
||||
dest_dir = os.path.join('accessible_output2', 'lib')
|
||||
return [(dest_dir, results)]
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,20 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
import platform
|
||||
if platform.system() == 'Windows':
|
||||
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
|
||||
|
||||
if platform.system() == 'Darwin':
|
||||
from . import voiceover
|
||||
from . import say
|
||||
|
||||
if platform.system() == 'Linux':
|
||||
from . import e_speak
|
||||
|
||||
from . import auto
|
@@ -1,42 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
import accessible_output2
|
||||
from .base import Output, OutputError
|
||||
|
||||
class Auto(Output):
|
||||
|
||||
def __init__(self):
|
||||
output_classes = accessible_output2.get_output_classes()
|
||||
self.outputs = []
|
||||
for output in output_classes:
|
||||
try:
|
||||
a=output()
|
||||
self.outputs.append(a)
|
||||
except:
|
||||
pass
|
||||
|
||||
def get_first_available_output(self):
|
||||
for output in self.outputs:
|
||||
if output.is_active():
|
||||
return output
|
||||
return None
|
||||
|
||||
def speak(self, *args, **kwargs):
|
||||
output = self.get_first_available_output()
|
||||
if output:
|
||||
output.speak(*args, **kwargs)
|
||||
|
||||
def braille(self, *args, **kwargs):
|
||||
output = self.get_first_available_output()
|
||||
if output:
|
||||
output.braille(*args, **kwargs)
|
||||
|
||||
def output(self, *args, **kwargs):
|
||||
output = self.get_first_available_output()
|
||||
if output:
|
||||
output.speak(*args, **kwargs)
|
||||
output.braille(*args, **kwargs)
|
||||
|
||||
def is_system_output(self):
|
||||
output = self.get_first_available_output()
|
||||
if output:
|
||||
return output.is_system_output()
|
@@ -1,47 +0,0 @@
|
||||
from accessible_output2 import load_library
|
||||
import platform
|
||||
|
||||
class OutputError(Exception):
|
||||
pass
|
||||
|
||||
class Output(object):
|
||||
name = "Unnamed Output"
|
||||
lib32 = None
|
||||
lib64 = None
|
||||
argtypes = {}
|
||||
cdll = False
|
||||
priority = 100
|
||||
system_output = False
|
||||
|
||||
def __init__(self):
|
||||
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, 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 self.speak(text, **options):
|
||||
output = True
|
||||
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, *args, **options):
|
||||
return False
|
@@ -1,33 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
import os
|
||||
import ctypes
|
||||
|
||||
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(text, (len(text)*2)+2, 1)
|
||||
|
||||
def silence(self):
|
||||
self.lib.DolAccess_Action(141)
|
||||
|
||||
def is_active(self):
|
||||
try:
|
||||
return self.lib.DolAccess_GetSystem() in (1, 4, 8)
|
||||
except:
|
||||
return False
|
||||
|
||||
output_class = Dolphin
|
@@ -1,31 +0,0 @@
|
||||
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,34 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
import win32gui
|
||||
from libloader.com import load_com
|
||||
import pywintypes
|
||||
|
||||
from .base import Output, OutputError
|
||||
|
||||
class Jaws (Output):
|
||||
"""Output supporting the Jaws for Windows screen reader."""
|
||||
|
||||
name = 'jaws'
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super (Jaws, self).__init__(*args, **kwargs)
|
||||
try:
|
||||
self.object = load_com("FreedomSci.JawsApi", "jfwapi")
|
||||
except pywintypes.com_error:
|
||||
raise OutputError
|
||||
|
||||
def braille(self, text, **options):
|
||||
# HACK: replace " with ', Jaws doesn't seem to understand escaping them with \
|
||||
text = text.replace('"', "'")
|
||||
self.object.RunFunction("BrailleString(\"%s\")" % text)
|
||||
|
||||
def speak(self, text, interrupt=False):
|
||||
self.object.SayString(' %s' % text, interrupt)
|
||||
|
||||
def is_active(self):
|
||||
try:
|
||||
return self.object.SayString('',0) == True or win32gui.FindWindow("JFWUI2", "JAWS") != 0
|
||||
except:
|
||||
return False
|
||||
|
||||
output_class = Jaws
|
@@ -1,37 +0,0 @@
|
||||
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
|
||||
|
||||
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:
|
||||
return self.lib.nvdaController_testIfRunning() == 0
|
||||
except:
|
||||
return False
|
||||
|
||||
def braille(self, text, **options):
|
||||
self.lib.nvdaController_brailleMessage(text)
|
||||
|
||||
def speak(self, text, interrupt=False):
|
||||
if interrupt:
|
||||
self.silence()
|
||||
self.lib.nvdaController_speakText(text)
|
||||
|
||||
def silence(self):
|
||||
self.lib.nvdaController_cancelSpeech()
|
||||
|
||||
output_class = NVDA
|
@@ -1,24 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
import ctypes
|
||||
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'), 0, 1)
|
||||
|
||||
def silence(self):
|
||||
self.lib.PCTKVReset()
|
||||
|
||||
def is_active(self):
|
||||
return self.lib.PCTKStatus() != 0
|
||||
|
||||
output_class = PCTalker
|
@@ -1,143 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
from builtins import range
|
||||
from libloader.com import load_com
|
||||
from .base import Output
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
class Sapi4(Output):
|
||||
|
||||
name = 'sapi4'
|
||||
priority = 102
|
||||
|
||||
def __init__(self):
|
||||
sapi4 = load_com("{EEE78591-FE22-11D0-8BEF-0060081841DE}")
|
||||
self._voiceNo = sapi4.Find(0)
|
||||
sapi4.Select(self._voiceNo)
|
||||
sapi4.Speak(" ")
|
||||
self.__object = sapi4
|
||||
self._voice_list = self._available_voices()
|
||||
|
||||
def _set_capabilities(self):
|
||||
sapi4 = self.__object
|
||||
try:
|
||||
sapi4.Pitch = sapi4.Pitch
|
||||
self._min_pitch = sapi4.MinPitch
|
||||
self._max_pitch = sapi4.MaxPitch
|
||||
self._has_pitch = True
|
||||
except:
|
||||
self._min_pitch = 0
|
||||
self._max_pitch = 0
|
||||
self._has_pitch = False
|
||||
try:
|
||||
sapi4.Speed = sapi4.Speed
|
||||
self._min_rate = sapi4.MinSpeed
|
||||
self._max_rate = sapi4.MaxSpeed
|
||||
self._has_rate = True
|
||||
except:
|
||||
self._min_rate = 0
|
||||
self._max_rate = 0
|
||||
self._has_rate = False
|
||||
try:
|
||||
sapi4.VolumeLeft = sapi4.VolumeLeft
|
||||
self._min_volume = sapi4.MinVolumeLeft
|
||||
self._max_volume = sapi4.MaxVolumeLeft
|
||||
self._has_volume = True
|
||||
except:
|
||||
self._min_volume = 0
|
||||
self._max_volume = 0
|
||||
self._has_volume = False
|
||||
|
||||
def _available_voices(self):
|
||||
voice_list = []
|
||||
for voice_no in range(1, self.__object.CountEngines):
|
||||
voice_list.append(self.__object.ModeName(voice_no))
|
||||
return voice_list
|
||||
|
||||
@property
|
||||
def available_voices(self):
|
||||
return self._voice_list
|
||||
|
||||
def list_voices(self):
|
||||
return self.available_voices
|
||||
|
||||
def get_voice(self):
|
||||
return self.__object.ModeName(self._voice_no)
|
||||
|
||||
def set_voice(self, value):
|
||||
self._voice_no = self.list_voices().index(value) + 1
|
||||
self.__object.Select(self._voice_no)
|
||||
self.silence()
|
||||
self.__object.Speak(" ")
|
||||
self._set_capabilities()
|
||||
|
||||
def get_pitch(self):
|
||||
if self.has_pitch:
|
||||
return self.__object.Pitch
|
||||
|
||||
def set_pitch(self, value):
|
||||
if self.has_pitch:
|
||||
self.__object.Pitch = value
|
||||
|
||||
def get_rate(self):
|
||||
if self.has_rate:
|
||||
return self.__object.Speed
|
||||
|
||||
def set_rate(self, value):
|
||||
if self.has_rate:
|
||||
self.__object.Speed = value
|
||||
|
||||
def get_volume(self):
|
||||
if self.has_volume:
|
||||
return self.__object.VolumeLeft
|
||||
|
||||
def set_volume(self, value):
|
||||
if self.has_volume:
|
||||
self.__object.VolumeLeft = value
|
||||
|
||||
@property
|
||||
def has_pitch(self):
|
||||
return self._has_pitch
|
||||
|
||||
@property
|
||||
def has_rate(self):
|
||||
return self._has_rate
|
||||
|
||||
@property
|
||||
def has_volume(self):
|
||||
return self._has_volume
|
||||
|
||||
@property
|
||||
def min_pitch(self):
|
||||
return self._min_pitch
|
||||
|
||||
@property
|
||||
def max_pitch(self):
|
||||
return self._max_pitch
|
||||
|
||||
@property
|
||||
def min_rate(self):
|
||||
return self._min_rate
|
||||
|
||||
@property
|
||||
def max_rate(self):
|
||||
return self._max_rate
|
||||
|
||||
@property
|
||||
def min_volume(self):
|
||||
return self._min_volume
|
||||
|
||||
@property
|
||||
def max_volume(self):
|
||||
return self._max_volume
|
||||
|
||||
def speak(self, text, interrupt=False):
|
||||
if interrupt:
|
||||
self.silence()
|
||||
self.__object.Speak(text)
|
||||
|
||||
def silence(self):
|
||||
self.__object.AudioReset()
|
||||
|
||||
output_class = Sapi4
|
@@ -1,95 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
from collections import OrderedDict
|
||||
from libloader.com import load_com
|
||||
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
|
||||
has_pitch = True
|
||||
min_pitch = -10
|
||||
max_pitch = 10
|
||||
min_rate = -10
|
||||
max_rate = 10
|
||||
min_volume = 0
|
||||
max_volume = 100
|
||||
name = "sapi5"
|
||||
priority = 101
|
||||
system_output = True
|
||||
|
||||
def __init__(self):
|
||||
try:
|
||||
self.object = load_com("SAPI.SPVoice")
|
||||
self._voices = self._available_voices()
|
||||
except pywintypes.com_error:
|
||||
raise OutputError
|
||||
self._pitch = 0
|
||||
|
||||
def _available_voices(self):
|
||||
_voices = OrderedDict()
|
||||
for v in self.object.GetVoices():
|
||||
_voices[v.GetDescription()] = v
|
||||
return _voices
|
||||
|
||||
def list_voices(self):
|
||||
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._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:
|
||||
# http://lists.nvaccess.org/pipermail/nvda-dev/2011-November/022464.html
|
||||
self.object.AudioOutput = self.object.AudioOutput
|
||||
|
||||
def get_pitch(self):
|
||||
return self._pitch
|
||||
|
||||
def set_pitch(self, value):
|
||||
log.debug("Setting pitch to %d" % value)
|
||||
self._pitch = value
|
||||
|
||||
def get_rate(self):
|
||||
return self.object.Rate
|
||||
|
||||
def set_rate(self, value):
|
||||
log.debug("Setting rate to %d" % value)
|
||||
self.object.Rate = value
|
||||
|
||||
def get_volume(self):
|
||||
return self.object.Volume
|
||||
|
||||
def set_volume(self, value):
|
||||
self.object.Volume = value
|
||||
|
||||
def speak(self, text, interrupt=False):
|
||||
if interrupt:
|
||||
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, SVSFlagsAsync | SVSFIsXML)
|
||||
|
||||
def silence(self):
|
||||
self.object.Speak("", SVSFlagsAsync | SVSFPurgeBeforeSpeak)
|
||||
|
||||
def is_active(self):
|
||||
if self.object:
|
||||
return True
|
||||
return False
|
||||
|
||||
output_class = SAPI5
|
@@ -1,21 +0,0 @@
|
||||
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 __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(text)
|
||||
|
||||
def speak(self, text, interrupt=False):
|
||||
if self.is_active():
|
||||
self.dll.SA_SayW(str(text))
|
||||
|
||||
def is_active(self):
|
||||
try:
|
||||
return self.dll.SA_IsRunning()
|
||||
except:
|
||||
return False
|
||||
|
||||
output_class = SystemAccess
|
@@ -1 +0,0 @@
|
||||
from __future__ import absolute_import
|
@@ -1,33 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
import win32gui
|
||||
from libloader.com import load_com
|
||||
from .base import Output, OutputError
|
||||
import pywintypes
|
||||
|
||||
class WindowEyes (Output):
|
||||
"""Speech output supporting the WindowEyes screen reader"""
|
||||
|
||||
name = 'Window-Eyes'
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(WindowEyes, self).__init__(*args, **kwargs)
|
||||
try:
|
||||
self.object = load_com("gwspeak.speak")
|
||||
except pywintypes.com_error:
|
||||
raise OutputError
|
||||
|
||||
def speak(self, text, interrupt=0):
|
||||
if interrupt:
|
||||
self.silence()
|
||||
self.object.SpeakString(text)
|
||||
|
||||
def silence (self):
|
||||
self.object.Silence()
|
||||
|
||||
def is_active(self):
|
||||
try:
|
||||
return win32gui.FindWindow("GWMExternalControl", "External Control") != 0
|
||||
except:
|
||||
return False
|
||||
|
||||
output_class = WindowEyes
|
@@ -2,20 +2,21 @@
|
||||
import datetime
|
||||
|
||||
name = 'TWBlue'
|
||||
short_name='twblue'
|
||||
snapshot = True
|
||||
if snapshot == False:
|
||||
version = "0.94"
|
||||
version = "0.95"
|
||||
update_url = 'https://twblue.es/updates/stable.php'
|
||||
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/stable.json'
|
||||
else:
|
||||
version = "11"
|
||||
version = "1"
|
||||
update_url = 'https://twblue.es/updates/snapshot.php'
|
||||
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/snapshots.json'
|
||||
authors = [u"Manuel Cortéz", u"José Manuel Delicado"]
|
||||
authors = ["Manuel Cortéz", "José Manuel Delicado"]
|
||||
authorEmail = "manuel@manuelcortez.net"
|
||||
copyright = u"Copyright (C) 2013-2018, 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"Manuel Cortéz (English)", u"Mohammed Al Shara, Hatoun Felemban (Arabic)", u"Francisco Torres (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"Zvonimir Stanečić (Croatian)", u"Robert Osztolykan (Hungarian)", u"Christian Leo Mameli (Italian)", u"Riku (Japanese)", u"Paweł Masarczyk (Polish)", u"Odenilton Júnior Santos (Portuguese)", u"Florian Ionașcu, Nicușor Untilă (Romanian)", u"Natalia Hedlund, Valeria Kuznetsova (Russian)", u"Aleksandar Đurić (Serbian)", u"Burak Yüksek (Turkish)"]
|
||||
copyright = "Copyright (C) 2013-2018, Manuel cortéz."
|
||||
description = 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 = ["Manuel Cortéz (English)", "Mohammed Al Shara, Hatoun Felemban (Arabic)", "Francisco Torres (Catalan)", "Manuel cortéz (Spanish)", "Sukil Etxenike Arizaleta (Basque)", "Jani Kinnunen (finnish)", "Rémy Ruiz (French)", "Juan Buño (Galician)", "Steffen Schultz (German)", "Zvonimir Stanečić (Croatian)", "Robert Osztolykan (Hungarian)", "Christian Leo Mameli (Italian)", "Riku (Japanese)", "Paweł Masarczyk (Polish)", "Odenilton Júnior Santos (Portuguese)", "Florian Ionașcu, Nicușor Untilă (Romanian)", "Natalia Hedlund, Valeria Kuznetsova (Russian)", "Aleksandar Đurić (Serbian)", "Burak Yüksek (Turkish)"]
|
||||
url = u"https://twblue.es"
|
||||
report_bugs_url = "https://github.com/manuelcortez/twblue/issues"
|
||||
supported_languages = []
|
@@ -1,3 +1,4 @@
|
||||
from __future__ import unicode_literals
|
||||
from functools import wraps
|
||||
|
||||
def matches_url(url):
|
||||
|
@@ -1,8 +1,9 @@
|
||||
from __future__ import unicode_literals
|
||||
from audio_services import matches_url
|
||||
import json
|
||||
import re
|
||||
import urllib
|
||||
import youtube_utils
|
||||
import requests
|
||||
|
||||
|
||||
|
||||
@matches_url('https://audioboom.com')
|
||||
def convert_audioboom(url):
|
||||
@@ -14,16 +15,14 @@ def convert_audioboom(url):
|
||||
@matches_url ('https://soundcloud.com/')
|
||||
def convert_soundcloud (url):
|
||||
client_id = "df8113ca95c157b6c9731f54b105b473"
|
||||
permalink = urllib.urlopen ('http://api.soundcloud.com/resolve.json?client_id=%s&url=%s' %(client_id, url))
|
||||
if permalink.getcode () == 404:
|
||||
permalink.close ()
|
||||
raise TypeError('%r is not a valid URL' % url)
|
||||
else:
|
||||
resolved_url = permalink.geturl ()
|
||||
permalink.close ()
|
||||
track_url = urllib.urlopen (resolved_url)
|
||||
track_data = json.loads (track_url.read ())
|
||||
track_url.close ()
|
||||
with requests.get('http://api.soundcloud.com/resolve.json', client_id=client_id, url=url) as permalink:
|
||||
if permalink.status_code==404:
|
||||
raise TypeError('%r is not a valid URL' % permalink.url)
|
||||
else:
|
||||
resolved_url = permalink.url
|
||||
with requests.get(resolved_url) as track_url:
|
||||
track_data = track_url.json()
|
||||
|
||||
if track_data ['streamable']:
|
||||
return track_data ['stream_url'] + "?client_id=%s" %client_id
|
||||
else:
|
||||
@@ -33,5 +32,12 @@ def convert_soundcloud (url):
|
||||
def convert_youtube_long (url):
|
||||
return youtube_utils.get_video_url(url)
|
||||
|
||||
@matches_url ('http://anyaudio.net/listen')
|
||||
def convert_anyaudio(url):
|
||||
values = url.split("audio=")
|
||||
if len(values) != 2:
|
||||
raise TypeError('%r is not streamable' % url)
|
||||
return "http://anyaudio.net/audiodownload?audio=%s" % (values[1],)
|
||||
|
||||
def convert_generic_audio(url):
|
||||
return url
|
||||
|
@@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
import youtube_dl
|
||||
|
||||
def get_video_url(url):
|
||||
@@ -9,4 +10,4 @@ def get_video_url(url):
|
||||
video = result['entries'][0]
|
||||
else:
|
||||
video = result
|
||||
return video["url"]
|
||||
return video["formats"][0]["url"]
|
@@ -1,4 +1,5 @@
|
||||
# -*- coding: cp1252 -*-
|
||||
import os
|
||||
import config_utils
|
||||
import paths
|
||||
import logging
|
||||
@@ -16,7 +17,7 @@ changed_keymap = False
|
||||
def setup ():
|
||||
global app
|
||||
log.debug("Loading global app settings...")
|
||||
app = config_utils.load_config(paths.config_path(MAINFILE), paths.app_path(MAINSPEC))
|
||||
app = config_utils.load_config(os.path.join(paths.config_path(), MAINFILE), os.path.join(paths.app_path(), MAINSPEC))
|
||||
log.debug("Loading keymap...")
|
||||
global keymap
|
||||
if float(platform.version()[:2]) >= 10 and app["app-settings"]["load_keymap"] == "default.keymap":
|
||||
@@ -24,4 +25,4 @@ def setup ():
|
||||
app.write()
|
||||
global changed_keymap
|
||||
changed_keymap = True
|
||||
keymap = config_utils.load_config(paths.config_path("keymap.keymap"), paths.app_path("keymaps/"+app['app-settings']['load_keymap']), copy=False)
|
||||
keymap = config_utils.load_config(os.path.join(paths.config_path(), "keymap.keymap"), os.path.join(paths.app_path(), "keymaps/"+app['app-settings']['load_keymap']), copy=False)
|
||||
|
@@ -1,4 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
from builtins import object
|
||||
import os
|
||||
import widgetUtils
|
||||
import logging
|
||||
|
@@ -4,4 +4,5 @@
|
||||
Currently, the package contains the following modules:
|
||||
* baseBuffers: Define a set of functions and structure to be expected in all buffers. New buffers should inherit its classes from one of the classes present here.
|
||||
* twitterBuffers: All other code, specific to Twitter.
|
||||
"""
|
||||
"""
|
||||
from __future__ import unicode_literals
|
@@ -1,5 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
""" Common logic to all buffers in TWBlue."""
|
||||
from __future__ import unicode_literals
|
||||
from builtins import object
|
||||
import logging
|
||||
import wx
|
||||
import output
|
||||
|
@@ -1,4 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
from builtins import str
|
||||
from builtins import range
|
||||
import time
|
||||
import platform
|
||||
if platform.system() == "Windows":
|
||||
@@ -17,7 +20,7 @@ import config
|
||||
import sound
|
||||
import languageHandler
|
||||
import logging
|
||||
import youtube_utils
|
||||
from audio_services import youtube_utils
|
||||
from controller.buffers import baseBuffers
|
||||
from sessions.twitter import compose, utils
|
||||
from mysc.thread_utils import call_threaded
|
||||
@@ -67,7 +70,7 @@ class baseBufferController(baseBuffers.buffer):
|
||||
""" Get buffer name from a set of different techniques."""
|
||||
# firstly let's take the easier buffers.
|
||||
basic_buffers = dict(home_timeline=_(u"Home"), mentions=_(u"Mentions"), direct_messages=_(u"Direct messages"), sent_direct_messages=_(u"Sent direct messages"), sent_tweets=_(u"Sent tweets"), favourites=_(u"Likes"), followers=_(u"Followers"), friends=_(u"Friends"), blocked=_(u"Blocked users"), muted=_(u"Muted users"))
|
||||
if self.name in basic_buffers.keys():
|
||||
if self.name in list(basic_buffers.keys()):
|
||||
return basic_buffers[self.name]
|
||||
# Check user timelines
|
||||
elif hasattr(self, "username"):
|
||||
@@ -128,7 +131,7 @@ class baseBufferController(baseBuffers.buffer):
|
||||
tweetsList = []
|
||||
tweet_id = tweet["id"]
|
||||
message = None
|
||||
if tweet.has_key("message"):
|
||||
if "message" in tweet:
|
||||
message = tweet["message"]
|
||||
try:
|
||||
tweet = self.session.twitter.show_status(id=tweet_id, include_ext_alt_text=True, tweet_mode="extended")
|
||||
@@ -241,7 +244,7 @@ class baseBufferController(baseBuffers.buffer):
|
||||
if self.name[:-9] in self.session.settings["other_buffers"]["timelines"]:
|
||||
self.session.settings["other_buffers"]["timelines"].remove(self.name[:-9])
|
||||
self.session.settings.write()
|
||||
if self.session.db.has_key(self.name):
|
||||
if self.name in self.session.db:
|
||||
self.session.db.pop(self.name)
|
||||
return True
|
||||
elif dlg == widgetUtils.NO:
|
||||
@@ -254,7 +257,7 @@ class baseBufferController(baseBuffers.buffer):
|
||||
if dlg == widgetUtils.YES:
|
||||
if self.name[:-9] in self.session.settings["other_buffers"]["favourites_timelines"]:
|
||||
self.session.settings["other_buffers"]["favourites_timelines"].remove(self.name[:-9])
|
||||
if self.session.db.has_key(self.name):
|
||||
if self.name in self.session.db:
|
||||
self.session.db.pop(self.name)
|
||||
self.session.settings.write()
|
||||
return True
|
||||
@@ -266,7 +269,7 @@ class baseBufferController(baseBuffers.buffer):
|
||||
|
||||
def remove_tweet(self, id):
|
||||
if type(self.session.db[self.name]) == dict: return
|
||||
for i in xrange(0, len(self.session.db[self.name])):
|
||||
for i in range(0, len(self.session.db[self.name])):
|
||||
if self.session.db[self.name][i]["id"] == id:
|
||||
self.session.db[self.name].pop(i)
|
||||
self.remove_item(i)
|
||||
@@ -344,6 +347,8 @@ class baseBufferController(baseBuffers.buffer):
|
||||
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 hasattr(menu, "openInBrowser"):
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.open_in_browser, menuitem=menu.openInBrowser)
|
||||
if pos != 0:
|
||||
self.buffer.PopupMenu(menu, pos)
|
||||
else:
|
||||
@@ -377,7 +382,7 @@ class baseBufferController(baseBuffers.buffer):
|
||||
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"):
|
||||
if "retweeted_status" in self.session.db[self.name][self.buffer.list.get_selected()]:
|
||||
tweet = self.session.db[self.name][self.buffer.list.get_selected()]["retweeted_status"]
|
||||
else:
|
||||
tweet = self.session.db[self.name][self.buffer.list.get_selected()]
|
||||
@@ -392,7 +397,7 @@ class baseBufferController(baseBuffers.buffer):
|
||||
tweet = self.get_right_tweet()
|
||||
screen_name = tweet["user"]["screen_name"]
|
||||
id = tweet["id"]
|
||||
twishort_enabled = tweet.has_key("twishort")
|
||||
twishort_enabled = "twishort" in tweet
|
||||
users = utils.get_all_mentioned(tweet, self.session.db, field="screen_name")
|
||||
ids = utils.get_all_mentioned(tweet, self.session.db, field="id_str")
|
||||
# Build the window title
|
||||
@@ -489,9 +494,9 @@ class baseBufferController(baseBuffers.buffer):
|
||||
|
||||
def _retweet_with_comment(self, tweet, id, comment=''):
|
||||
# If quoting a retweet, let's quote the original tweet instead the retweet.
|
||||
if tweet.has_key("retweeted_status"):
|
||||
if "retweeted_status" in tweet:
|
||||
tweet = tweet["retweeted_status"]
|
||||
if tweet.has_key("full_text"):
|
||||
if "full_text" in tweet:
|
||||
comments = tweet["full_text"]
|
||||
else:
|
||||
comments = tweet["text"]
|
||||
@@ -627,6 +632,12 @@ class baseBufferController(baseBuffers.buffer):
|
||||
except IndexError: pass
|
||||
return compose.compose_quoted_tweet(quoted_tweet, original_tweet, self.session.db, self.session.settings["general"]["relative_times"])
|
||||
|
||||
def open_in_browser(self, *args, **kwargs):
|
||||
tweet = self.get_tweet()
|
||||
output.speak(_(u"Opening item in web browser..."))
|
||||
url = "https://twitter.com/{screen_name}/status/{tweet_id}".format(screen_name=tweet["user"]["screen_name"], tweet_id=tweet["id"])
|
||||
webbrowser.open(url)
|
||||
|
||||
class directMessagesController(baseBufferController):
|
||||
|
||||
def get_more_items(self):
|
||||
@@ -694,7 +705,7 @@ class directMessagesController(baseBufferController):
|
||||
tweet = self.get_tweet()
|
||||
if platform.system() == "Windows" and self.session.settings["general"]["relative_times"] == True:
|
||||
# fix this:
|
||||
original_date = arrow.get(tweet["created_timestamp"][:-3])
|
||||
original_date = arrow.get(int(tweet["created_timestamp"][:-3]))
|
||||
ts = original_date.humanize(locale=languageHandler.getLanguage())
|
||||
self.buffer.list.list.SetItem(self.buffer.list.get_selected(), 2, ts)
|
||||
if self.session.settings['sound']['indicate_audio'] and utils.is_audio(tweet):
|
||||
@@ -719,11 +730,14 @@ class directMessagesController(baseBufferController):
|
||||
elif number_of_items > 1 and 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(_(u"{0} new direct messages.").format(number_of_items,))
|
||||
|
||||
def open_in_browser(self, *args, **kwargs):
|
||||
output.speak(_(u"This action is not supported in the buffer yet."))
|
||||
|
||||
class sentDirectMessagesController(directMessagesController):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(sentDirectMessagesController, self).__init__(*args, **kwargs)
|
||||
if self.session.db.has_key("sent_direct_messages") == False:
|
||||
if ("sent_direct_messages" in self.session.db) == False:
|
||||
self.session.db["sent_direct_messages"] = {"items": []}
|
||||
|
||||
def get_more_items(self):
|
||||
@@ -770,7 +784,7 @@ class listBufferController(baseBufferController):
|
||||
if dlg == widgetUtils.YES:
|
||||
if self.name[:-5] in self.session.settings["other_buffers"]["lists"]:
|
||||
self.session.settings["other_buffers"]["lists"].remove(self.name[:-5])
|
||||
if self.session.db.has_key(self.name):
|
||||
if self.name in self.session.db:
|
||||
self.session.db.pop(self.name)
|
||||
self.session.settings.write()
|
||||
return True
|
||||
@@ -805,7 +819,7 @@ class peopleBufferController(baseBufferController):
|
||||
if dlg == widgetUtils.YES:
|
||||
if self.name[:-10] in self.session.settings["other_buffers"]["followers_timelines"]:
|
||||
self.session.settings["other_buffers"]["followers_timelines"].remove(self.name[:-10])
|
||||
if self.session.db.has_key(self.name):
|
||||
if self.name in self.session.db:
|
||||
self.session.db.pop(self.name)
|
||||
self.session.settings.write()
|
||||
return True
|
||||
@@ -819,7 +833,7 @@ class peopleBufferController(baseBufferController):
|
||||
if dlg == widgetUtils.YES:
|
||||
if self.name[:-8] in self.session.settings["other_buffers"]["friends_timelines"]:
|
||||
self.session.settings["other_buffers"]["friends_timelines"].remove(self.name[:-8])
|
||||
if self.session.db.has_key(self.name):
|
||||
if self.name in self.session.db:
|
||||
self.session.db.pop(self.name)
|
||||
self.session.settings.write()
|
||||
return True
|
||||
@@ -951,6 +965,8 @@ class peopleBufferController(baseBufferController):
|
||||
# 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 hasattr(menu, "openInBrowser"):
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.open_in_browser, menuitem=menu.openInBrowser)
|
||||
if pos != 0:
|
||||
self.buffer.PopupMenu(menu, pos)
|
||||
else:
|
||||
@@ -969,6 +985,12 @@ class peopleBufferController(baseBufferController):
|
||||
elif number_of_items > 1 and 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(_(u"{0} new followers.").format(number_of_items))
|
||||
|
||||
def open_in_browser(self, *args, **kwargs):
|
||||
tweet = self.get_tweet()
|
||||
output.speak(_(u"Opening item in web browser..."))
|
||||
url = "https://twitter.com/{screen_name}".format(screen_name=tweet["screen_name"])
|
||||
webbrowser.open(url)
|
||||
|
||||
class searchBufferController(baseBufferController):
|
||||
def start_stream(self, mandatory=False, play_sound=True, avoid_autoreading=False):
|
||||
# starts stream every 3 minutes.
|
||||
@@ -1000,7 +1022,7 @@ class searchBufferController(baseBufferController):
|
||||
if self.name[:-11] in self.session.settings["other_buffers"]["tweet_searches"]:
|
||||
self.session.settings["other_buffers"]["tweet_searches"].remove(self.name[:-11])
|
||||
self.session.settings.write()
|
||||
if self.session.db.has_key(self.name):
|
||||
if self.name in self.session.db:
|
||||
self.session.db.pop(self.name)
|
||||
return True
|
||||
elif dlg == widgetUtils.NO:
|
||||
@@ -1051,7 +1073,7 @@ class searchPeopleBufferController(peopleBufferController):
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
self.function = function
|
||||
if self.kwargs.has_key("page") == False:
|
||||
if ("page" in self.kwargs) == False:
|
||||
self.kwargs["page"] = 1
|
||||
|
||||
def start_stream(self, mandatory=False, play_sound=True, avoid_autoreading=True):
|
||||
@@ -1115,7 +1137,7 @@ class searchPeopleBufferController(peopleBufferController):
|
||||
if self.name[:-11] in self.session.settings["other_buffers"]["tweet_searches"]:
|
||||
self.session.settings["other_buffers"]["tweet_searches"].remove(self.name[:-11])
|
||||
self.session.settings.write()
|
||||
if self.session.db.has_key(self.name):
|
||||
if self.name in self.session.db:
|
||||
self.session.db.pop(self.name)
|
||||
return True
|
||||
elif dlg == widgetUtils.NO:
|
||||
@@ -1188,7 +1210,7 @@ class trendsBufferController(baseBuffers.buffer):
|
||||
if self.name[:-3] in self.session.settings["other_buffers"]["trending_topic_buffers"]:
|
||||
self.session.settings["other_buffers"]["trending_topic_buffers"].remove(self.name[:-3])
|
||||
self.session.settings.write()
|
||||
if self.session.db.has_key(self.name):
|
||||
if self.name in self.session.db:
|
||||
self.session.db.pop(self.name)
|
||||
return True
|
||||
elif dlg == widgetUtils.NO:
|
||||
@@ -1243,6 +1265,9 @@ class trendsBufferController(baseBuffers.buffer):
|
||||
if ev.GetKeyCode() == wx.WXK_WINDOWS_MENU:
|
||||
self.show_menu(widgetUtils.MENU, pos=self.buffer.list.list.GetPosition())
|
||||
|
||||
def open_in_browser(self, *args, **kwargs):
|
||||
output.speak(_(u"This action is not supported in the buffer, yet."))
|
||||
|
||||
class conversationBufferController(searchBufferController):
|
||||
|
||||
def start_stream(self, start=False, mandatory=False, play_sound=True, avoid_autoreading=False):
|
||||
@@ -1288,7 +1313,7 @@ class conversationBufferController(searchBufferController):
|
||||
else:
|
||||
dlg = widgetUtils.YES
|
||||
if dlg == widgetUtils.YES:
|
||||
if self.session.db.has_key(self.name):
|
||||
if self.name in self.session.db:
|
||||
self.session.db.pop(self.name)
|
||||
return True
|
||||
elif dlg == widgetUtils.NO:
|
||||
|
@@ -1,4 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
from builtins import object
|
||||
import time
|
||||
import widgetUtils
|
||||
import application
|
||||
@@ -30,7 +32,7 @@ class filter(object):
|
||||
if i["name"] in langs:
|
||||
langcodes.append(i["code"])
|
||||
d = dict(in_buffer=self.buffer.name, word=term, regexp=regexp, in_lang=lang_option, languages=langcodes, if_word_exists=contains, allow_rts=allow_rts, allow_quotes=allow_quotes, allow_replies=allow_replies)
|
||||
if self.buffer.session.settings["filters"].has_key(title):
|
||||
if title in self.buffer.session.settings["filters"]:
|
||||
return commonMessageDialogs.existing_filter()
|
||||
self.buffer.session.settings["filters"][title] = d
|
||||
self.buffer.session.settings.write()
|
||||
@@ -51,7 +53,7 @@ class filterManager(object):
|
||||
|
||||
def insert_filters(self, filters):
|
||||
self.dialog.filters.clear()
|
||||
for f in filters.keys():
|
||||
for f in list(filters.keys()):
|
||||
filterName = f
|
||||
buffer = filters[f]["in_buffer"]
|
||||
if filters[f]["if_word_exists"] == "True" and filters[f]["word"] != "":
|
||||
|
@@ -1,4 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
from builtins import object
|
||||
import widgetUtils
|
||||
import output
|
||||
from wxUI.dialogs import lists
|
||||
|
@@ -1,22 +1,26 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
from builtins import str
|
||||
from builtins import range
|
||||
from builtins import object
|
||||
import platform
|
||||
system = platform.system()
|
||||
import application
|
||||
import requests
|
||||
import youtube_utils
|
||||
from audio_services import youtube_utils
|
||||
import arrow
|
||||
if system == "Windows":
|
||||
from update import updater
|
||||
from wxUI import (view, dialogs, commonMessageDialogs, sysTrayIcon)
|
||||
import settings
|
||||
from . import settings
|
||||
from extra import SoundsTutorial, ocr
|
||||
import keystrokeEditor
|
||||
from keyboard_handler.wx_handler import WXKeyboardHandler
|
||||
import userActionsController
|
||||
import trendingTopics
|
||||
import user
|
||||
import listsController
|
||||
import filterController
|
||||
from . import userActionsController
|
||||
from . import trendingTopics
|
||||
from . import user
|
||||
from . import listsController
|
||||
from . import filterController
|
||||
# from issueReporter import issueReporter
|
||||
elif system == "Linux":
|
||||
from gtkUI import (view, commonMessageDialogs)
|
||||
@@ -24,7 +28,7 @@ from sessions.twitter import utils, compose
|
||||
from sessionmanager import manager, sessionManager
|
||||
|
||||
from controller.buffers import baseBuffers, twitterBuffers
|
||||
import messages
|
||||
from . import messages
|
||||
import sessions
|
||||
from sessions.twitter import session as session_
|
||||
from pubsub import pub
|
||||
@@ -267,7 +271,7 @@ class Controller(object):
|
||||
self.start_buffers(sessions.sessions[i])
|
||||
self.set_buffer_positions(sessions.sessions[i])
|
||||
if config.app["app-settings"]["play_ready_sound"] == True:
|
||||
sessions.sessions[sessions.sessions.keys()[0]].sound.play("ready.ogg")
|
||||
sessions.sessions[list(sessions.sessions.keys())[0]].sound.play("ready.ogg")
|
||||
if config.app["app-settings"]["speak_ready_msg"] == True:
|
||||
output.speak(_(u"Ready"))
|
||||
self.started = True
|
||||
@@ -392,7 +396,7 @@ class Controller(object):
|
||||
def set_buffer_positions(self, session):
|
||||
"Sets positions for buffers if values exist in the database."
|
||||
for i in self.buffers:
|
||||
if i.account == session.db["user_name"] and session.db.has_key(i.name+"_pos") and hasattr(i.buffer,'list'):
|
||||
if i.account == session.db["user_name"] and i.name+"_pos" in session.db and hasattr(i.buffer,'list'):
|
||||
i.buffer.list.select_item(session.db[str(i.name+"_pos")])
|
||||
|
||||
def logout_account(self, session_id):
|
||||
@@ -464,7 +468,7 @@ class Controller(object):
|
||||
output.speak(_(u"Empty buffer."), True)
|
||||
return
|
||||
start = page.buffer.list.get_selected()
|
||||
for i in xrange(start, count):
|
||||
for i in range(start, count):
|
||||
if string.lower() in page.buffer.list.get_text_column(i, 1).lower():
|
||||
page.buffer.list.select_item(i)
|
||||
return output.speak(page.get_message(), True)
|
||||
@@ -655,6 +659,9 @@ class Controller(object):
|
||||
sessions.sessions[item].shelve()
|
||||
if system == "Windows":
|
||||
self.systrayIcon.RemoveIcon()
|
||||
pidpath = os.path.join(os.getenv("temp"), "{}.pid".format(application.name))
|
||||
if os.path.exists(pidpath):
|
||||
os.remove(pidpath)
|
||||
widgetUtils.exit_application()
|
||||
|
||||
def follow(self, *args, **kwargs):
|
||||
@@ -801,13 +808,18 @@ class Controller(object):
|
||||
elif buffer.type == "dm":
|
||||
non_tweet = buffer.get_formatted_message()
|
||||
item = buffer.get_right_tweet()
|
||||
original_date = arrow.get(item["created_timestamp"][:-3])
|
||||
date = original_date.replace(seconds=buffer.session.db["utc_offset"]).format(_(u"MMM D, YYYY. H:m"), locale=languageHandler.getLanguage())
|
||||
original_date = arrow.get(int(item["created_timestamp"][:-3]))
|
||||
date = original_date.shift(seconds=buffer.session.db["utc_offset"]).format(_(u"MMM D, YYYY. H:m"), locale=languageHandler.getLanguage())
|
||||
msg = messages.viewTweet(non_tweet, [], False, date=date)
|
||||
else:
|
||||
non_tweet = buffer.get_formatted_message()
|
||||
msg = messages.viewTweet(non_tweet, [], False)
|
||||
|
||||
def open_in_browser(self, *args, **kwargs):
|
||||
buffer = self.get_current_buffer()
|
||||
if hasattr(buffer, "open_in_browser"):
|
||||
buffer.open_in_browser()
|
||||
|
||||
def open_favs_timeline(self, *args, **kwargs):
|
||||
self.open_timeline(default="favourites")
|
||||
|
||||
@@ -960,8 +972,8 @@ class Controller(object):
|
||||
x = tweet["coordinates"]["coordinates"][0]
|
||||
y = tweet["coordinates"]["coordinates"][1]
|
||||
address = geocoder.reverse_geocode(y, x, language = languageHandler.curLang)
|
||||
if event == None: output.speak(address[0].__str__().decode("utf-8"))
|
||||
else: self.view.show_address(address[0].__str__().decode("utf-8"))
|
||||
if event == None: output.speak(address[0].__str__())
|
||||
else: self.view.show_address(address[0].__str__())
|
||||
else:
|
||||
output.speak(_(u"There are no coordinates in this tweet"))
|
||||
except GeocoderError:
|
||||
@@ -1563,18 +1575,25 @@ class Controller(object):
|
||||
output.speak(_(u"Invalid buffer"))
|
||||
return
|
||||
tweet = buffer.get_tweet()
|
||||
if tweet.has_key("entities") == False or tweet["entities"].has_key("media") == False:
|
||||
output.speak(_(u"This tweet doesn't contain images"))
|
||||
return
|
||||
if len(tweet["entities"]["media"]) > 1:
|
||||
image_list = [_(u"Picture {0}").format(i,) for i in xrange(0, len(tweet["entities"]["media"]))]
|
||||
media_list = []
|
||||
if ("entities" in tweet) and ("media" in tweet["entities"]):
|
||||
[media_list.append(i) for i in tweet["entities"]["media"] if i not in media_list]
|
||||
elif "retweeted_status" in tweet and "media" in tweet["retweeted_status"]["entities"]:
|
||||
[media_list.append(i) for i in tweet["retweeted_status"]["entities"]["media"] if i not in media_list]
|
||||
elif "quoted_status" in tweet and "media" in tweet["quoted_status"]["entities"]:
|
||||
[media_list.append(i) for i in tweet["quoted_status"]["entities"]["media"] if i not in media_list]
|
||||
if len(media_list) > 1:
|
||||
image_list = [_(u"Picture {0}").format(i,) for i in range(0, len(media_list))]
|
||||
dialog = dialogs.urlList.urlList(title=_(u"Select the picture"))
|
||||
if dialog.get_response() == widgetUtils.OK:
|
||||
img = tweet["entities"]["media"][dialog.get_item()]
|
||||
img = media_list[dialog.get_item()]
|
||||
else:
|
||||
return
|
||||
elif len(media_list) == 1:
|
||||
img = media_list[0]
|
||||
else:
|
||||
img = tweet["entities"]["media"][0]
|
||||
output.speak(_(u"Invalid buffer"))
|
||||
return
|
||||
if buffer.session.settings["mysc"]["ocr_language"] != "":
|
||||
ocr_lang = buffer.session.settings["mysc"]["ocr_language"]
|
||||
else:
|
||||
|
@@ -1,7 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import absolute_import
|
||||
from __future__ import unicode_literals
|
||||
from builtins import str
|
||||
from builtins import range
|
||||
from builtins import object
|
||||
import re
|
||||
import platform
|
||||
import attach
|
||||
from . import attach
|
||||
import arrow
|
||||
import languageHandler
|
||||
system = platform.system()
|
||||
@@ -172,14 +177,14 @@ class reply(tweet):
|
||||
|
||||
def get_ids(self):
|
||||
excluded_ids = ""
|
||||
for i in xrange(0, len(self.message.checkboxes)):
|
||||
for i in range(0, len(self.message.checkboxes)):
|
||||
if self.message.checkboxes[i].GetValue() == False:
|
||||
excluded_ids = excluded_ids + "{0},".format(self.ids[i],)
|
||||
return excluded_ids
|
||||
|
||||
def get_people(self):
|
||||
people = ""
|
||||
for i in xrange(0, len(self.message.checkboxes)):
|
||||
for i in range(0, len(self.message.checkboxes)):
|
||||
if self.message.checkboxes[i].GetValue() == True:
|
||||
people = people + "{0} ".format(self.message.checkboxes[i].GetLabel(),)
|
||||
return people
|
||||
@@ -204,57 +209,57 @@ class viewTweet(basicTweet):
|
||||
self.title = _(u"Tweet")
|
||||
image_description = []
|
||||
text = ""
|
||||
for i in xrange(0, len(tweetList)):
|
||||
for i in range(0, len(tweetList)):
|
||||
# tweets with message keys are longer tweets, the message value is the full messaje taken from twishort.
|
||||
if tweetList[i].has_key("message") and tweetList[i]["is_quote_status"] == False:
|
||||
if "message" in tweetList[i] and tweetList[i]["is_quote_status"] == False:
|
||||
value = "message"
|
||||
else:
|
||||
value = "full_text"
|
||||
if tweetList[i].has_key("retweeted_status") and tweetList[i]["is_quote_status"] == False:
|
||||
if tweetList[i].has_key("message") == False:
|
||||
if "retweeted_status" in tweetList[i] and tweetList[i]["is_quote_status"] == False:
|
||||
if ("message" in tweetList[i]) == False:
|
||||
text = text + "rt @%s: %s\n" % (tweetList[i]["retweeted_status"]["user"]["screen_name"], tweetList[i]["retweeted_status"]["full_text"])
|
||||
else:
|
||||
text = text + "rt @%s: %s\n" % (tweetList[i]["retweeted_status"]["user"]["screen_name"], tweetList[i][value])
|
||||
else:
|
||||
text = text + " @%s: %s\n" % (tweetList[i]["user"]["screen_name"], tweetList[i][value])
|
||||
# tweets with extended_entities could include image descriptions.
|
||||
if tweetList[i].has_key("extended_entities") and tweetList[i]["extended_entities"].has_key("media"):
|
||||
if "extended_entities" in tweetList[i] and "media" in tweetList[i]["extended_entities"]:
|
||||
for z in tweetList[i]["extended_entities"]["media"]:
|
||||
if z.has_key("ext_alt_text") and z["ext_alt_text"] != None:
|
||||
if "ext_alt_text" in z and z["ext_alt_text"] != None:
|
||||
image_description.append(z["ext_alt_text"])
|
||||
if tweetList[i].has_key("retweeted_status") and tweetList[i]["retweeted_status"].has_key("extended_entities") and tweetList[i]["retweeted_status"]["extended_entities"].has_key("media"):
|
||||
if "retweeted_status" in tweetList[i] and "extended_entities" in tweetList[i]["retweeted_status"] and "media" in tweetList[i]["retweeted_status"]["extended_entities"]:
|
||||
for z in tweetList[i]["retweeted_status"]["extended_entities"]["media"]:
|
||||
if z.has_key("ext_alt_text") and z["ext_alt_text"] != None:
|
||||
if "ext_alt_text" in z and z["ext_alt_text"] != None:
|
||||
image_description.append(z["ext_alt_text"])
|
||||
# set rt and likes counters.
|
||||
rt_count = str(tweet["retweet_count"])
|
||||
favs_count = str(tweet["favorite_count"])
|
||||
# Gets the client from where this tweet was made.
|
||||
source = str(re.sub(r"(?s)<.*?>", "", tweet["source"].encode("utf-8")))
|
||||
source = re.sub(r"(?s)<.*?>", "", tweet["source"])
|
||||
original_date = arrow.get(tweet["created_at"], "ddd MMM DD H:m:s Z YYYY", locale="en")
|
||||
date = original_date.replace(seconds=utc_offset).format(_(u"MMM D, YYYY. H:m"), locale=languageHandler.getLanguage())
|
||||
date = original_date.shift(seconds=utc_offset).format(_(u"MMM D, YYYY. H:m"), locale=languageHandler.getLanguage())
|
||||
if text == "":
|
||||
if tweet.has_key("message"):
|
||||
if "message" in tweet:
|
||||
value = "message"
|
||||
else:
|
||||
value = "full_text"
|
||||
if tweet.has_key("retweeted_status"):
|
||||
if tweet.has_key("message") == False:
|
||||
if "retweeted_status" in tweet:
|
||||
if ("message" in tweet) == False:
|
||||
text = "rt @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], tweet["retweeted_status"]["full_text"])
|
||||
else:
|
||||
text = "rt @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], tweet[value])
|
||||
else:
|
||||
text = tweet[value]
|
||||
text = self.clear_text(text)
|
||||
if tweet.has_key("extended_entities") and tweet["extended_entities"].has_key("media"):
|
||||
if "extended_entities" in tweet and "media" in tweet["extended_entities"]:
|
||||
for z in tweet["extended_entities"]["media"]:
|
||||
if z.has_key("ext_alt_text") and z["ext_alt_text"] != None:
|
||||
if "ext_alt_text" in z and z["ext_alt_text"] != None:
|
||||
image_description.append(z["ext_alt_text"])
|
||||
if tweet.has_key("retweeted_status") and tweet["retweeted_status"].has_key("extended_entities") and tweet["retweeted_status"]["extended_entities"].has_key("media"):
|
||||
if "retweeted_status" in tweet and "extended_entities" in tweet["retweeted_status"] and "media" in tweet["retweeted_status"]["extended_entities"]:
|
||||
for z in tweet["retweeted_status"]["extended_entities"]["media"]:
|
||||
if z.has_key("ext_alt_text") and z["ext_alt_text"] != None:
|
||||
if "ext_alt_text" in z and z["ext_alt_text"] != None:
|
||||
image_description.append(z["ext_alt_text"])
|
||||
self.message = message.viewTweet(text, rt_count, favs_count, source.decode("utf-8"), date)
|
||||
self.message = message.viewTweet(text, rt_count, favs_count, source, date)
|
||||
self.message.set_title(len(text))
|
||||
[self.message.set_image_description(i) for i in image_description]
|
||||
else:
|
||||
|
@@ -1,4 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
from builtins import str
|
||||
from builtins import object
|
||||
import os
|
||||
import webbrowser
|
||||
import sound_lib
|
||||
@@ -18,7 +21,7 @@ import config_utils
|
||||
log = logging.getLogger("Settings")
|
||||
import keys
|
||||
from collections import OrderedDict
|
||||
from platform_utils.autostart import windows as autostart_windows
|
||||
from mysc import autostart as autostart_windows
|
||||
|
||||
class globalSettingsController(object):
|
||||
def __init__(self):
|
||||
@@ -30,7 +33,7 @@ class globalSettingsController(object):
|
||||
|
||||
def make_kmmap(self):
|
||||
res={}
|
||||
for i in os.listdir(paths.app_path('keymaps')):
|
||||
for i in os.listdir(os.path.join(paths.app_path(), 'keymaps')):
|
||||
if ".keymap" not in i:
|
||||
continue
|
||||
try:
|
||||
@@ -49,7 +52,7 @@ class globalSettingsController(object):
|
||||
id = self.codes.index(config.app["app-settings"]["language"])
|
||||
self.kmfriendlies=[]
|
||||
self.kmnames=[]
|
||||
for k,v in self.kmmap.items():
|
||||
for k,v in list(self.kmmap.items()):
|
||||
self.kmfriendlies.append(k)
|
||||
self.kmnames.append(v)
|
||||
self.kmid=self.kmnames.index(config.app['app-settings']['load_keymap'])
|
||||
@@ -92,7 +95,7 @@ class globalSettingsController(object):
|
||||
self.needs_restart = True
|
||||
if self.kmnames[self.dialog.general.km.GetSelection()] != config.app["app-settings"]["load_keymap"]:
|
||||
config.app["app-settings"]["load_keymap"] =self.kmnames[self.dialog.general.km.GetSelection()]
|
||||
kmFile = open(paths.config_path("keymap.keymap"), "w")
|
||||
kmFile = open(os.path.join(paths.config_path(), "keymap.keymap"), "w")
|
||||
kmFile.close()
|
||||
self.needs_restart = True
|
||||
if config.app["app-settings"]["autostart"] != self.dialog.get_value("general", "autostart") and paths.mode == "installed":
|
||||
@@ -166,7 +169,7 @@ class accountSettingsController(globalSettingsController):
|
||||
self.input_devices = sound_lib.input.Input.get_device_names()
|
||||
self.output_devices = sound_lib.output.Output.get_device_names()
|
||||
self.soundpacks = []
|
||||
[self.soundpacks.append(i) for i in os.listdir(paths.sound_path()) if os.path.isdir(paths.sound_path(i)) == True ]
|
||||
[self.soundpacks.append(i) for i in os.listdir(paths.sound_path()) if os.path.isdir(os.path.join(paths.sound_path(), i)) == True ]
|
||||
self.dialog.create_sound(self.input_devices, self.output_devices, self.soundpacks)
|
||||
self.dialog.set_value("sound", "volumeCtrl", self.config["sound"]["volume"]*100)
|
||||
self.dialog.set_value("sound", "input", self.config["sound"]["input_device"])
|
||||
@@ -211,7 +214,7 @@ class accountSettingsController(globalSettingsController):
|
||||
else:
|
||||
self.config["general"]["retweet_mode"] = "comment"
|
||||
buffers_list = self.dialog.buffers.get_list()
|
||||
if set(self.config["general"]["buffer_order"]) != set(buffers_list) or buffers_list != self.config["general"]["buffer_order"]:
|
||||
if buffers_list != self.config["general"]["buffer_order"]:
|
||||
self.needs_restart = True
|
||||
self.config["general"]["buffer_order"] = buffers_list
|
||||
self.config["reporting"]["speech_reporting"] = self.dialog.get_value("reporting", "speech_reporting")
|
||||
@@ -291,10 +294,14 @@ class accountSettingsController(globalSettingsController):
|
||||
all_buffers['muted']=_(u"Muted users")
|
||||
list_buffers = []
|
||||
hidden_buffers=[]
|
||||
for i in all_buffers.keys():
|
||||
if i in self.config["general"]["buffer_order"]:
|
||||
all_buffers_keys = list(all_buffers.keys())
|
||||
# Check buffers shown first.
|
||||
for i in self.config["general"]["buffer_order"]:
|
||||
if i in all_buffers_keys:
|
||||
list_buffers.append((i, all_buffers[i], True))
|
||||
else:
|
||||
# This second pass will retrieve all hidden buffers.
|
||||
for i in all_buffers_keys:
|
||||
if i not in self.config["general"]["buffer_order"]:
|
||||
hidden_buffers.append((i, all_buffers[i], False))
|
||||
list_buffers.extend(hidden_buffers)
|
||||
return list_buffers
|
||||
|
@@ -1,4 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
from builtins import object
|
||||
from wxUI.dialogs import trends
|
||||
import widgetUtils
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user