mirror of
https://github.com/MCV-Software/TWBlue.git
synced 2025-08-26 01:49:22 +00:00
Compare commits
159 Commits
Author | SHA1 | Date | |
---|---|---|---|
97afc379e8 | |||
7f401ba789 | |||
ff22ae5653 | |||
02d94fcea0 | |||
df2015f360 | |||
64a14c831b | |||
fbbe7852c2 | |||
9dfccd2bd0 | |||
969a75e9f3 | |||
a59ba5ef78 | |||
3ebfdbc48b | |||
8db14a95c1 | |||
1b9062d86f | |||
4b60a79e49 | |||
002e1ccb55 | |||
0bcdf88290 | |||
0612c653b8 | |||
![]() |
c5dadb063a | ||
35d6010298 | |||
40a63d9e16 | |||
5712dd735b | |||
2c75ea5005 | |||
e35f37fcc2 | |||
71358ea74d | |||
b8f822830f | |||
74e4fe6357 | |||
77bee64421 | |||
c761230566 | |||
49505fabcd | |||
4ad01d7833 | |||
ab1a13f886 | |||
![]() |
44c25e54f8 | ||
cdabd6f055 | |||
60144a6b08 | |||
382acf7c8c | |||
![]() |
03ba59028f | ||
![]() |
50125fc55a | ||
39e1fb017c | |||
2aaa4eced3 | |||
![]() |
6d2eac5b1c | ||
![]() |
40040d1b17 | ||
2a791d43bf | |||
b10aeb046d | |||
7d6e230fd9 | |||
9346bba7a0 | |||
30f739c42e | |||
eb0679cb96 | |||
45deae3402 | |||
5b0b26799d | |||
ee234b80a7 | |||
0065af2aef | |||
9c086cfa0f | |||
2f263a23b7 | |||
9cb6eafbbc | |||
cba7c39a0e | |||
e2e8b84e6a | |||
eca0c0dbbd | |||
36cc3f9365 | |||
63d7cbe7c4 | |||
ae57cc3404 | |||
23df8f8a7f | |||
2f278b7f3c | |||
9444939c35 | |||
6688dc1163 | |||
6a7300b35f | |||
c95a2feb5e | |||
8042d28b13 | |||
890359f8c7 | |||
91955e80d2 | |||
6c1c66226d | |||
1a76913aac | |||
f85af2cbd2 | |||
351f700927 | |||
![]() |
abdde4c1f0 | ||
![]() |
4899285eca | ||
![]() |
fb3e6b537c | ||
![]() |
22d1cc9ce9 | ||
304d91e8b7 | |||
cf650052e4 | |||
![]() |
10055788e4 | ||
![]() |
a67f3f037e | ||
![]() |
4d736c00fc | ||
![]() |
29b8a645db | ||
![]() |
2459a499ce | ||
28f4e3a534 | |||
e2931e96eb | |||
![]() |
fbcba39e69 | ||
![]() |
b59d262dca | ||
![]() |
7f4a13231f | ||
![]() |
4ab5af2ae9 | ||
![]() |
4c4eaf4012 | ||
![]() |
b03198a39f | ||
![]() |
06dc26e962 | ||
![]() |
bcc8f5968e | ||
![]() |
4c144d2f7e | ||
747290e16a | |||
![]() |
64b6d4df74 | ||
![]() |
22d48cb5d9 | ||
![]() |
fea01c44ca | ||
b80a342f92 | |||
60a13d974c | |||
4c9000839d | |||
b3c24c6734 | |||
a2a8cc5b79 | |||
da7a208c1f | |||
979a3d3e99 | |||
1f11ea7aa0 | |||
8bdc933bce | |||
999cbba464 | |||
7457521398 | |||
366b61134e | |||
52154ac271 | |||
cdc285e362 | |||
4643301764 | |||
f546543e9b | |||
85fe94ec0c | |||
db13c96baa | |||
33b6000b41 | |||
a261365682 | |||
4064582583 | |||
fc0da0bdbb | |||
76c678d4ba | |||
3db8b7b021 | |||
fa49637d0e | |||
65ec231349 | |||
93705bf534 | |||
29a905199d | |||
8569d9b0a0 | |||
1e1f2b089f | |||
78cc6e6784 | |||
a37f339fea | |||
d0cc12ef5c | |||
bcd51d6259 | |||
7ceb806af2 | |||
![]() |
8f35fc0ec0 | ||
![]() |
3f79fab8e5 | ||
![]() |
53dee8cb81 | ||
56103466fa | |||
13f5df3a48 | |||
a89cc35d40 | |||
276cd4b4dd | |||
c509433b2c | |||
7292b36137 | |||
![]() |
0111c8aae1 | ||
eefe5e6200 | |||
492f1d8aa5 | |||
ac20ced5fa | |||
866cd53328 | |||
f523e3e81e | |||
bdd7d617c3 | |||
a0bc5f6cb3 | |||
3f238635f2 | |||
c300476ad2 | |||
6a2e00c467 | |||
4fa983a314 | |||
ed5b66d033 | |||
bec45c37c1 | |||
ad42c09fef | |||
084fa1894c |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -20,3 +20,4 @@ release-snapshot/
|
|||||||
src/com_cache/
|
src/com_cache/
|
||||||
doc/strings.py
|
doc/strings.py
|
||||||
doc/changelog.py
|
doc/changelog.py
|
||||||
|
env/
|
42
README.md
42
README.md
@@ -24,45 +24,37 @@ This document describes how to run tw blue from source and how to build a binary
|
|||||||
### Required dependencies.
|
### Required dependencies.
|
||||||
|
|
||||||
Although most dependencies can be found in the windows-dependencies directory, we provide links to their official websites. If you are cloning with git, don't forget to initialize and update the submodules to get the windows-dependencies folder. You can use these two commands to perform this task from git bash:
|
Although most dependencies can be found in the windows-dependencies directory, we provide links to their official websites. If you are cloning with git, don't forget to initialize and update the submodules to get the windows-dependencies folder. You can use these two commands to perform this task from git bash:
|
||||||
|
```
|
||||||
git submodule init
|
git submodule init
|
||||||
git submodule update
|
git submodule update
|
||||||
|
```
|
||||||
All the dependencies provided in this folder are prebuilt. If you want to build them from source, you will need Microsoft visual Studio 2008.
|
|
||||||
|
|
||||||
#### Dependencies packaged in windows installers
|
#### Dependencies packaged in windows installers
|
||||||
|
|
||||||
* [Python,](http://python.org) version 2.7.16
|
* [Python,](https://python.org) version 3.8.7
|
||||||
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.
|
If you want to build both x86 and x64 binaries, you can install python x86 to C:\python38 and python x64 to C:\python38x64, 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
|
|
||||||
|
|
||||||
The windows installers are available only in the windows-dependencies folder.
|
|
||||||
|
|
||||||
To build a binary version:
|
|
||||||
|
|
||||||
* [Py2exe](http://www.sourceforge.net/projects/py2exe/) for Python 2.7, version 0.6.9
|
|
||||||
|
|
||||||
#### Dependencies that must be installed using pip
|
#### Dependencies that must be installed using pip
|
||||||
|
|
||||||
Python installs a tool called Pip that allows to install packages in a simple way. You can find it in the python scripts directory. To install packages using Pip, you have to navigate to the scripts directory using a command prompt, for example:
|
Python installs a tool called Pip that allows to install packages in a simple way. You can find it in the python scripts directory. To install packages using Pip, you have to navigate to the scripts directory using a command prompt, for example:
|
||||||
|
|
||||||
cd C:\python27x64\scripts
|
`cd C:\python37x64\scripts`
|
||||||
|
|
||||||
You can also add the scripts folder to your path environment variable or choose the corresponding option when installing Python.
|
You can also add the scripts folder to your path environment variable or choose the corresponding option when installing Python.
|
||||||
Note: pip and setuptools are included in the Python installer since version 2.7.9.
|
Note: pip and setuptools are included in the Python installer since version 2.7.9.
|
||||||
|
|
||||||
Pip is able to install packages listed in a special text file, called the requirements file. To install all remaining dependencies, perform the following command:
|
Pip is able to install packages listed in a special text file, called the requirements file. To install all remaining dependencies, perform the following command:
|
||||||
|
|
||||||
pip install -r requirements.txt
|
`pip install -r requirements.txt`
|
||||||
|
|
||||||
Note that if you perform the command from the path where Pip is located, you need to specify the path to your Tw Blue root folder where the requirements file is located, for example:
|
Note that if you perform the command from the path where Pip is located, you need to specify the path to your Tw Blue root folder where the requirements file is located, for example:
|
||||||
|
|
||||||
pip install -r D:\repos\TwBlue\requirements.txt
|
`pip install -r D:\repos\TwBlue\requirements.txt`
|
||||||
|
|
||||||
Pip will automatically get the additional libraries that the listed packages need to work properly.
|
Pip will automatically get the additional libraries that the listed packages need to work properly.
|
||||||
If you need to update your dependencies, perform the following command:
|
If you need to update your dependencies, perform the following command:
|
||||||
|
|
||||||
pip install --upgrade -r requirements.txt
|
`pip install --upgrade -r requirements.txt`
|
||||||
|
|
||||||
#### Other dependencies
|
#### Other dependencies
|
||||||
|
|
||||||
@@ -71,7 +63,7 @@ These dependencies are located in the windows-dependencies directory. You don't
|
|||||||
* Bootstrap 1.2.1: included in dependencies directory.
|
* Bootstrap 1.2.1: included in dependencies directory.
|
||||||
This dependency has been built using pure basic 4.61. Its source can be found at http://hg.q-continuum.net/updater
|
This dependency has been built using pure basic 4.61. Its source can be found at http://hg.q-continuum.net/updater
|
||||||
* [oggenc2.exe,](http://www.rarewares.org/ogg-oggenc.php) version 2.87
|
* [oggenc2.exe,](http://www.rarewares.org/ogg-oggenc.php) version 2.87
|
||||||
* Microsoft Visual c++ 2008 redistributable dlls.
|
* Microsoft Visual c++ 2019 redistributable dlls.
|
||||||
* VLC plugins and DLL libraries.
|
* VLC plugins and DLL libraries.
|
||||||
|
|
||||||
#### Dependencies required to build the installer
|
#### Dependencies required to build the installer
|
||||||
@@ -94,7 +86,7 @@ In order to add the support for spell checking in more languages than english yo
|
|||||||
|
|
||||||
Now that you have installed all these packages, you can run TW Blue from source using a command prompt. Navigate to the repo's `src` directory, and type the following command:
|
Now that you have installed all these packages, you can run TW Blue from source using a command prompt. Navigate to the repo's `src` directory, and type the following command:
|
||||||
|
|
||||||
python main.py
|
`python main.py`
|
||||||
|
|
||||||
If necessary, change the first part of the command to reflect the location of your python executable. You can run TW Blue using python x86 and x64.
|
If necessary, change the first part of the command to reflect the location of your python executable. You can run TW Blue using python x86 and x64.
|
||||||
|
|
||||||
@@ -102,8 +94,8 @@ Now that you have installed all these packages, you can run TW Blue from source
|
|||||||
|
|
||||||
To generate the documentation in html format, navigate to the doc folder inside this repo. After that, run these commands:
|
To generate the documentation in html format, navigate to the doc folder inside this repo. After that, run these commands:
|
||||||
|
|
||||||
python document_importer.py
|
`python document_importer.py`
|
||||||
python generator.py
|
`python generator.py`
|
||||||
|
|
||||||
The documentation will be generated, placing each language in a separate folder in the doc directory. Move these folders (for example `de`, `en`, `es`, `fr`, `it`, ...) to `src/documentation`, creating the directory if necessary.
|
The documentation will be generated, placing each language in a separate folder in the doc directory. Move these folders (for example `de`, `en`, `es`, `fr`, `it`, ...) to `src/documentation`, creating the directory if necessary.
|
||||||
Also, copy the `license.txt` file located in the root of the repo to the documentation folder.
|
Also, copy the `license.txt` file located in the root of the repo to the documentation folder.
|
||||||
@@ -114,7 +106,7 @@ A binary version doesn't need python and the other dependencies to run, it's the
|
|||||||
|
|
||||||
To build it, run the following command from the src folder:
|
To build it, run the following command from the src folder:
|
||||||
|
|
||||||
python setup.py py2exe
|
`python setup.py build`
|
||||||
|
|
||||||
You will find the binaries in the dist directory.
|
You will find the binaries in the dist directory.
|
||||||
|
|
||||||
@@ -122,9 +114,9 @@ To build it, run the following command from the src folder:
|
|||||||
|
|
||||||
If you want to install TWBlue on your computer, you must create the installer first. Follow these steps:
|
If you want to install TWBlue on your computer, you must create the installer first. Follow these steps:
|
||||||
|
|
||||||
* Navigate to the src directory, and create a binary version for x86: C:\python27\python setup.py py2exe
|
* Navigate to the src directory, and create a binary version for x86: C:\python37\python setup.py build
|
||||||
* Move the dist directory to the scripts folder in this repo, and rename it to twblue
|
* Move the dist directory to the scripts folder in this repo, and rename it to twblue
|
||||||
* Repeat these steps with Python for x64: C:\python27x64\python setup.py py2exe
|
* Repeat these steps with Python for x64: C:\python37x64\python setup.py build
|
||||||
* Move the new dist directory to the scripts folder, and rename it to twblue64
|
* Move the new dist directory to the scripts folder, and rename it to twblue64
|
||||||
* Go to the scripts folder, right click on the twblue.nsi file, and choose compyle unicode NSIS script
|
* Go to the scripts folder, right click on the twblue.nsi file, and choose compyle unicode NSIS script
|
||||||
* This may take a while. After the process, you will find the installer in the scripts folder
|
* This may take a while. After the process, you will find the installer in the scripts folder
|
||||||
@@ -137,9 +129,9 @@ Run the gen_pot.bat file, located in the tools directory. Your python installati
|
|||||||
|
|
||||||
If you want to have TWBlue on your PortableApps.com platform, follow these steps:
|
If you want to have TWBlue on your PortableApps.com platform, follow these steps:
|
||||||
|
|
||||||
* Navigate to the src directory, and create a binary version for x86: C:\python27\python setup.py py2exe
|
* Navigate to the src directory, and create a binary version for x86: C:\python37\python setup.py build
|
||||||
* Move the dist directory to the misc\pa.c format\app folder in this repo, and rename it to twblue
|
* Move the dist directory to the misc\pa.c format\app folder in this repo, and rename it to twblue
|
||||||
* Repeat these steps with Python for x64: C:\python27x64\python setup.py py2exe
|
* Repeat these steps with Python for x64: C:\python37x64\python setup.py build
|
||||||
* Move the new dist directory to the misc\pa.c format\app folder, and rename it to twblue64
|
* Move the new dist directory to the misc\pa.c format\app folder, and rename it to twblue64
|
||||||
* Run the PortableApps.com Launcher Generator, and follow the wizard. Choose the pa.c format folder and continue to generate the launcher. If the wizard is completed, you will see a file named TWBlue portable.exe inside the pa.c format folder.
|
* Run the PortableApps.com Launcher Generator, and follow the wizard. Choose the pa.c format folder and continue to generate the launcher. If the wizard is completed, you will see a file named TWBlue portable.exe inside the pa.c format folder.
|
||||||
* Run the PortableApps.com Installer, and follow the wizard. As in the above step, choose the pa.c format folder. When it completes, you will see a file named TWBluePortable_x.y.paf.exe inside the misc folder, where x.y is the version number.
|
* Run the PortableApps.com Installer, and follow the wizard. As in the above step, choose the pa.c format folder. When it completes, you will see a file named TWBluePortable_x.y.paf.exe inside the misc folder, where x.y is the version number.
|
||||||
|
@@ -10,8 +10,8 @@ environment:
|
|||||||
matrix:
|
matrix:
|
||||||
|
|
||||||
# List of python versions we want to work with.
|
# List of python versions we want to work with.
|
||||||
- PYTHON: "C:\\Python37"
|
- PYTHON: "C:\\Python38"
|
||||||
PYTHON_VERSION: "3.7.x" # currently 2.7.9
|
PYTHON_VERSION: "3.8.x" # currently 2.7.9
|
||||||
PYTHON_ARCH: "32"
|
PYTHON_ARCH: "32"
|
||||||
|
|
||||||
# perhaps we may enable this one in future?
|
# perhaps we may enable this one in future?
|
||||||
|
@@ -39,4 +39,5 @@ florian Ionașcu
|
|||||||
Christian Leo Mameli
|
Christian Leo Mameli
|
||||||
Natalia Hedlund (Наталья Хедлунд)
|
Natalia Hedlund (Наталья Хедлунд)
|
||||||
Valeria (Валерия)
|
Valeria (Валерия)
|
||||||
Corentin Bacqué-Cazenave
|
Oreonan
|
||||||
|
Artem Plaksin (maniyax)
|
||||||
|
@@ -2,7 +2,30 @@
|
|||||||
|
|
||||||
## changes in this version
|
## 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])
|
* Added support for Twitter audio and videos: Tweets which contains audio or videos will be detected as audio items, and you can playback those with the regular command to play audios. ([#384,](https://github.com/manuelcortez/TWBlue/pull/384))
|
||||||
|
* We just implemented some changes in the way TWBlue handles tweets in order to reduce its RAM memory usage [#380](https://github.com/manuelcortez/TWBlue/pull/380):
|
||||||
|
* We reduced the tweets size by storing only the tweet fields we currently use. This should reduce tweet's size in memory for every object up to 75%.
|
||||||
|
* When using the cache database to store your tweets, there is a new setting present in the account settings dialog, in the general tab. This setting allows you to control whether TWBlue will load the whole database into memory (which is the current behaviour) or not.
|
||||||
|
* Loading the whole database into memory has the advantage of being extremely fast to access any element (for example when moving through tweets in a buffer), but it requires more memory as the tweet buffers grow up. This should, however, use less memory than before thanks to the optimizations performed in tweet objects. If you have a machine with enough memory, this should be a good option for your case.
|
||||||
|
* If you uncheck this setting, TWBlue will read the whole database from disk. This is significantly slower, but the advantage of this setting is that it will consume almost no extra memory, no matter how big is the tweets dataset. Be ware, though, that TWBlue might start to feel slower when accessing elements (for example when reading tweets) as the buffers grow up. This setting is suggested for computers with low memory or for those people not wanting to keep a really big amount of tweets stored.
|
||||||
|
* Changed the label in the direct message's text control so it will indicate that the user needs to write the text there, without referring to any username in particular. ([#366,](https://github.com/manuelcortez/TWBlue/issues/366))
|
||||||
|
* TWBlue will take Shift+F10 again as the contextual menu key in the list of items in a buffer. This stopped working after we have migrated to WX 4.1. ([#353,](https://github.com/manuelcortez/TWBlue/issues/353))
|
||||||
|
* TWBlue should render correctly retweets of quoted tweets. ([#365,](https://github.com/manuelcortez/TWBlue/issues/365))
|
||||||
|
* Fixed an error that was causing TWBlue to be unable to output to screen readers at times. ([#369,](https://github.com/manuelcortez/TWBlue/issues/369))
|
||||||
|
* Fixed autocomplete users feature. ([#367,](https://github.com/manuelcortez/TWBlue/issues/367))
|
||||||
|
* 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) [#272,](https://github.com/manuelcortez/TWBlue/issues/272))
|
||||||
|
* TWBlue has been migrated completely to Python 3 (currently, the software builds with Python 3.8).
|
||||||
|
* TWBlue should be restarted gracefully. Before, the application was alerting users of not being closed properly every time the application restarted by itself.
|
||||||
|
* If TWBlue attemps to load an account with invalid tokens (this happens when reactivating a previously deactivated account, or when access to the ap is revoqued), TWBlue will inform the user about this error and will skip the account. Before, the app was unable to start due to a critical error. ([#328,](https://github.com/manuelcortez/TWBlue/issues/328))
|
||||||
|
* When sending a direct message, the title of the window will change appropiately when the recipient is edited. ([#276,](https://github.com/manuelcortez/TWBlue/issues/276))
|
||||||
|
* URL'S in user profiles are expanded automatically. ([#275,](https://github.com/manuelcortez/TWBlue/issues/275))
|
||||||
|
* TWBlue now uses [Tweepy,](https://github.com/tweepy/tweepy) to connect with Twitter. We have adopted this change in order to support Twitter'S API V 2 in the very near future. ([#333,](https://github.com/manuelcortez/TWBlue/issues/337) [#347](https://github.com/manuelcortez/TWBlue/pull/347))
|
||||||
|
* TWBlue can upload images in Tweets and replies again. ([#240,](https://github.com/manuelcortez/TWBlue/issues/240))
|
||||||
|
* Fixed the way we use to count characters in Twitter. The new methods in TWBlue take into account special characters and URLS as documented in Twitter. ([#199,](https://github.com/manuelcortez/TWBlue/issues/199) [#315](https://github.com/manuelcortez/TWBlue/issues/315))
|
||||||
|
* Proxy support now works as expected.
|
||||||
|
* Changed translation service from yandex.translate to Google Translator. ([#355,](https://github.com/manuelcortez/TWBlue/issues/355))
|
||||||
|
* Improved method to load direct messages in the buffers. Now it should be faster due to less calls to Twitter API performed from the client.
|
||||||
|
* And more. ([#352,](https://github.com/manuelcortez/TWBlue/issues/352))
|
||||||
|
|
||||||
## Changes in version 0.95
|
## Changes in version 0.95
|
||||||
|
|
||||||
|
@@ -16,9 +16,9 @@ def prepare_documentation_in_file(fileSource, fileDest):
|
|||||||
if "\n" == i:
|
if "\n" == i:
|
||||||
newvar = "\"\","
|
newvar = "\"\","
|
||||||
elif "\n" == i[-1]:
|
elif "\n" == i[-1]:
|
||||||
newvar = "_(u\"\"\"%s\"\"\"),\n" % (i[:-1])
|
newvar = "\"\"\"%s\"\"\",\n" % (i[:-1])
|
||||||
else:
|
else:
|
||||||
newvar = "_(u\"\"\"%s\"\"\"),\n" % (i)
|
newvar = "\"\"\"%s\"\"\",\n" % (i)
|
||||||
f2.write(newvar)
|
f2.write(newvar)
|
||||||
f1.close()
|
f1.close()
|
||||||
f2.write("]")
|
f2.write("]")
|
||||||
|
@@ -8,28 +8,27 @@ import shutil
|
|||||||
from codecs import open as _open
|
from codecs import open as _open
|
||||||
from importlib import reload
|
from importlib import reload
|
||||||
|
|
||||||
def change_language(name, language):
|
def get_translation_function(name, language):
|
||||||
global _
|
if language == "en":
|
||||||
os.environ["lang"] = language
|
return gettext.NullTranslations()
|
||||||
_ = gettext.install(name, os.path.join(paths.app_path(), "locales"))
|
translation_function = gettext.translation(name, os.path.join(paths.app_path(), "locales"), languages=[language])
|
||||||
|
return translation_function
|
||||||
|
|
||||||
# the list of supported language codes of TW Blue
|
# the list of supported language codes of TW Blue
|
||||||
languages = ["en", "es", "fr", "de", "it", "gl", "ja", "ru", "ro", "eu", "ca", "da"]
|
languages = ["en", "es", "fr", "de", "it", "gl", "ja", "ru", "ro", "eu", "ca", "da", "sr"]
|
||||||
|
|
||||||
def generate_document(language, document_type="documentation"):
|
def generate_document(language, document_type="documentation"):
|
||||||
if document_type == "documentation":
|
if document_type == "documentation":
|
||||||
translation_file = "twblue-documentation"
|
translation_file = "twblue-documentation"
|
||||||
change_language(translation_file, language)
|
translation_function = get_translation_function(translation_file, language)
|
||||||
reload(strings)
|
markdown_file = markdown.markdown("\n".join([translation_function.gettext(s[:-1]) if s != "\n" else s for s in strings.documentation[1:]]), extensions=["markdown.extensions.toc"])
|
||||||
markdown_file = markdown.markdown("\n".join(strings.documentation[1:]), extensions=["markdown.extensions.toc"])
|
title = translation_function.gettext(strings.documentation[0][:-1])
|
||||||
title = strings.documentation[0]
|
|
||||||
filename = "manual.html"
|
filename = "manual.html"
|
||||||
elif document_type == "changelog":
|
elif document_type == "changelog":
|
||||||
translation_file = "twblue-changelog"
|
translation_file = "twblue-changelog"
|
||||||
change_language(translation_file, language)
|
translation_function = get_translation_function(translation_file, language)
|
||||||
reload(changelog)
|
markdown_file = markdown.markdown("\n".join([translation_function.gettext(s[:-1]) if s != "\n" else s for s in changelog.documentation[1:]]), extensions=["markdown.extensions.toc"])
|
||||||
markdown_file = markdown.markdown("\n".join(changelog.documentation[1:]), extensions=["markdown.extensions.toc"])
|
title = translation_function.gettext(changelog.documentation[0][:-1])
|
||||||
title = changelog.documentation[0]
|
|
||||||
filename = "changelog.html"
|
filename = "changelog.html"
|
||||||
first_html_block = """<!doctype html>
|
first_html_block = """<!doctype html>
|
||||||
<html lang="%s">
|
<html lang="%s">
|
||||||
@@ -56,11 +55,13 @@ def create_documentation():
|
|||||||
shutil.copy(os.path.join("..", "license.txt"), os.path.join("documentation", "license.txt"))
|
shutil.copy(os.path.join("..", "license.txt"), os.path.join("documentation", "license.txt"))
|
||||||
for i in languages:
|
for i in languages:
|
||||||
print("Creating documentation for: %s" % (i,))
|
print("Creating documentation for: %s" % (i,))
|
||||||
generate_document(i)
|
try:
|
||||||
generate_document(i, "changelog")
|
generate_document(i)
|
||||||
|
generate_document(i, "changelog")
|
||||||
|
except:
|
||||||
|
continue
|
||||||
print("Done")
|
print("Done")
|
||||||
|
|
||||||
change_language("twblue-documentation", "en")
|
|
||||||
import strings
|
import strings
|
||||||
import changelog
|
import changelog
|
||||||
create_documentation()
|
create_documentation()
|
BIN
doc/locales/sr/lc_messages/twblue-changelog.mo
Normal file
BIN
doc/locales/sr/lc_messages/twblue-changelog.mo
Normal file
Binary file not shown.
1309
doc/locales/sr/lc_messages/twblue-changelog.po
Normal file
1309
doc/locales/sr/lc_messages/twblue-changelog.po
Normal file
File diff suppressed because it is too large
Load Diff
BIN
doc/locales/sr/lc_messages/twblue-documentation.mo
Normal file
BIN
doc/locales/sr/lc_messages/twblue-documentation.mo
Normal file
Binary file not shown.
1885
doc/locales/sr/lc_messages/twblue-documentation.po
Normal file
1885
doc/locales/sr/lc_messages/twblue-documentation.po
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
|||||||
wxpython==4.0.3
|
wxpython
|
||||||
|
wheel
|
||||||
six
|
six
|
||||||
configobj
|
configobj
|
||||||
markdown
|
markdown
|
||||||
@@ -15,8 +16,10 @@ futures
|
|||||||
winpaths
|
winpaths
|
||||||
PySocks
|
PySocks
|
||||||
win_inet_pton
|
win_inet_pton
|
||||||
yandex.translate
|
# Install the latest RC of this lib
|
||||||
idna
|
# see https://github.com/ssut/py-googletrans/issues/234
|
||||||
|
googletrans==4.0.0-rc1
|
||||||
|
idna<3,>=2.5
|
||||||
chardet
|
chardet
|
||||||
urllib3
|
urllib3
|
||||||
youtube-dl
|
youtube-dl
|
||||||
@@ -25,8 +28,11 @@ pypiwin32
|
|||||||
certifi
|
certifi
|
||||||
backports.functools_lru_cache
|
backports.functools_lru_cache
|
||||||
cx_freeze
|
cx_freeze
|
||||||
git+https://github.com/manuelcortez/twython
|
tweepy
|
||||||
git+https://github.com/manuelcortez/libloader
|
twitter-text-parser
|
||||||
git+https://github.com/manuelcortez/platform_utils
|
pyenchant
|
||||||
git+https://github.com/manuelcortez/accessible_output2
|
sqlitedict
|
||||||
git+https://github.com/jmdaweb/sound_lib
|
git+https://github.com/accessibleapps/libloader
|
||||||
|
git+https://github.com/accessibleapps/platform_utils
|
||||||
|
git+https://github.com/accessibleapps/accessible_output2
|
||||||
|
git+https://github.com/accessibleapps/sound_lib
|
@@ -12,6 +12,7 @@ reverse_timelines = boolean(default=False)
|
|||||||
announce_stream_status = boolean(default=True)
|
announce_stream_status = boolean(default=True)
|
||||||
retweet_mode = string(default="ask")
|
retweet_mode = string(default="ask")
|
||||||
persist_size = integer(default=0)
|
persist_size = integer(default=0)
|
||||||
|
load_cache_in_memory=boolean(default=True)
|
||||||
show_screen_names = boolean(default=False)
|
show_screen_names = boolean(default=False)
|
||||||
buffer_order = list(default=list('home','mentions', 'dm', 'sent_dm', 'sent_tweets','favorites','followers','friends','blocks','muted','events'))
|
buffer_order = list(default=list('home','mentions', 'dm', 'sent_dm', 'sent_tweets','favorites','followers','friends','blocks','muted','events'))
|
||||||
|
|
||||||
|
@@ -24,8 +24,8 @@ mention_all = boolean(default=False)
|
|||||||
no_streaming = boolean(default=False)
|
no_streaming = boolean(default=False)
|
||||||
|
|
||||||
[proxy]
|
[proxy]
|
||||||
type = string(default="Direct connection")
|
type = integer(default=0)
|
||||||
server = string(default="")
|
server = string(default="")
|
||||||
port = string(default="")
|
port = integer(default=8080)
|
||||||
user = string(default="")
|
user = string(default="")
|
||||||
password = string(default="")
|
password = string(default="")
|
@@ -5,18 +5,18 @@ name = 'TWBlue'
|
|||||||
short_name='twblue'
|
short_name='twblue'
|
||||||
snapshot = True
|
snapshot = True
|
||||||
if snapshot == False:
|
if snapshot == False:
|
||||||
version = "0.95"
|
version = "0.95"
|
||||||
update_url = 'https://twblue.es/updates/stable.php'
|
update_url = 'https://twblue.es/updates/stable.php'
|
||||||
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/stable.json'
|
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/stable.json'
|
||||||
else:
|
else:
|
||||||
version = "1"
|
version = "6"
|
||||||
update_url = 'https://twblue.es/updates/snapshot.php'
|
update_url = 'https://twblue.es/updates/snapshot.php'
|
||||||
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/snapshots.json'
|
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/snapshots.json'
|
||||||
authors = ["Manuel Cortéz", "José Manuel Delicado"]
|
authors = ["Manuel Cortéz", "José Manuel Delicado"]
|
||||||
authorEmail = "manuel@manuelcortez.net"
|
authorEmail = "manuel@manuelcortez.net"
|
||||||
copyright = "Copyright (C) 2013-2018, Manuel cortéz."
|
copyright = "Copyright (C) 2013-2021, 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."
|
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)"]
|
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)", "Oreonan (Français)", "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"
|
url = u"https://twblue.es"
|
||||||
report_bugs_url = "https://github.com/manuelcortez/twblue/issues"
|
report_bugs_url = "https://github.com/manuelcortez/twblue/issues"
|
||||||
supported_languages = []
|
supported_languages = []
|
@@ -2,22 +2,22 @@ from __future__ import unicode_literals
|
|||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
def matches_url(url):
|
def matches_url(url):
|
||||||
def url_setter(func):
|
def url_setter(func):
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
def internal_url_setter(*args, **kwargs):
|
def internal_url_setter(*args, **kwargs):
|
||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
internal_url_setter.url = url
|
internal_url_setter.url = url
|
||||||
return internal_url_setter
|
return internal_url_setter
|
||||||
return url_setter
|
return url_setter
|
||||||
|
|
||||||
def find_url_transformer(url):
|
def find_url_transformer(url):
|
||||||
from audio_services import services
|
from audio_services import services
|
||||||
funcs = []
|
funcs = []
|
||||||
for i in dir(services):
|
for i in dir(services):
|
||||||
possible = getattr(services, i)
|
possible = getattr(services, i)
|
||||||
if callable(possible) and hasattr(possible, 'url'):
|
if callable(possible) and hasattr(possible, 'url'):
|
||||||
funcs.append(possible)
|
funcs.append(possible)
|
||||||
for f in funcs:
|
for f in funcs:
|
||||||
if url.lower().startswith(f.url.lower()):
|
if url.lower().startswith(f.url.lower()):
|
||||||
return f
|
return f
|
||||||
return services.convert_generic_audio
|
return services.convert_generic_audio
|
||||||
|
@@ -1,43 +1,41 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from audio_services import matches_url
|
from audio_services import matches_url
|
||||||
import youtube_utils
|
|
||||||
import requests
|
import requests
|
||||||
|
from . import youtube_utils
|
||||||
|
|
||||||
|
|
||||||
@matches_url('https://audioboom.com')
|
@matches_url('https://audioboom.com')
|
||||||
def convert_audioboom(url):
|
def convert_audioboom(url):
|
||||||
if "audioboom.com" not in url.lower():
|
if "audioboom.com" not in url.lower():
|
||||||
raise TypeError('%r is not a valid URL' % url)
|
raise TypeError('%r is not a valid URL' % url)
|
||||||
audio_id = url.split('.com/')[-1]
|
audio_id = url.split('.com/')[-1]
|
||||||
return 'https://audioboom.com/%s.mp3' % audio_id
|
return 'https://audioboom.com/%s.mp3' % audio_id
|
||||||
|
|
||||||
@matches_url ('https://soundcloud.com/')
|
@matches_url ('https://soundcloud.com/')
|
||||||
def convert_soundcloud (url):
|
def convert_soundcloud (url):
|
||||||
client_id = "df8113ca95c157b6c9731f54b105b473"
|
client_id = "df8113ca95c157b6c9731f54b105b473"
|
||||||
with requests.get('http://api.soundcloud.com/resolve.json', client_id=client_id, url=url) as permalink:
|
with requests.get('http://api.soundcloud.com/resolve.json', client_id=client_id, url=url) as permalink:
|
||||||
if permalink.status_code==404:
|
if permalink.status_code==404:
|
||||||
raise TypeError('%r is not a valid URL' % permalink.url)
|
raise TypeError('%r is not a valid URL' % permalink.url)
|
||||||
else:
|
else:
|
||||||
resolved_url = permalink.url
|
resolved_url = permalink.url
|
||||||
with requests.get(resolved_url) as track_url:
|
with requests.get(resolved_url) as track_url:
|
||||||
track_data = track_url.json()
|
track_data = track_url.json()
|
||||||
|
|
||||||
if track_data ['streamable']:
|
if track_data ['streamable']:
|
||||||
return track_data ['stream_url'] + "?client_id=%s" %client_id
|
return track_data ['stream_url'] + "?client_id=%s" %client_id
|
||||||
else:
|
else:
|
||||||
raise TypeError('%r is not streamable' % url)
|
raise TypeError('%r is not streamable' % url)
|
||||||
|
|
||||||
@matches_url ('https://www.youtube.com/watch')
|
@matches_url ('https://www.youtube.com/watch')
|
||||||
def convert_youtube_long (url):
|
def convert_youtube_long (url):
|
||||||
return youtube_utils.get_video_url(url)
|
return youtube_utils.get_video_url(url)
|
||||||
|
|
||||||
@matches_url ('http://anyaudio.net/listen')
|
@matches_url ('http://anyaudio.net/listen')
|
||||||
def convert_anyaudio(url):
|
def convert_anyaudio(url):
|
||||||
values = url.split("audio=")
|
values = url.split("audio=")
|
||||||
if len(values) != 2:
|
if len(values) != 2:
|
||||||
raise TypeError('%r is not streamable' % url)
|
raise TypeError('%r is not streamable' % url)
|
||||||
return "http://anyaudio.net/audiodownload?audio=%s" % (values[1],)
|
return "http://anyaudio.net/audiodownload?audio=%s" % (values[1],)
|
||||||
|
|
||||||
def convert_generic_audio(url):
|
def convert_generic_audio(url):
|
||||||
return url
|
return url
|
||||||
|
@@ -3,11 +3,11 @@ from __future__ import unicode_literals
|
|||||||
import youtube_dl
|
import youtube_dl
|
||||||
|
|
||||||
def get_video_url(url):
|
def get_video_url(url):
|
||||||
ydl = youtube_dl.YoutubeDL({'quiet': True, 'format': 'bestaudio/best', 'outtmpl': u'%(id)s%(ext)s'})
|
ydl = youtube_dl.YoutubeDL({'quiet': True, 'format': 'bestaudio/best', 'outtmpl': u'%(id)s%(ext)s'})
|
||||||
with ydl:
|
with ydl:
|
||||||
result = ydl.extract_info(url, download=False)
|
result = ydl.extract_info(url, download=False)
|
||||||
if 'entries' in result:
|
if 'entries' in result:
|
||||||
video = result['entries'][0]
|
video = result['entries'][0]
|
||||||
else:
|
else:
|
||||||
video = result
|
video = result
|
||||||
return video["formats"][0]["url"]
|
return video["formats"][0]["url"]
|
||||||
|
@@ -9,20 +9,20 @@ log = logging.getLogger("config")
|
|||||||
|
|
||||||
MAINFILE = "twblue.conf"
|
MAINFILE = "twblue.conf"
|
||||||
MAINSPEC = "app-configuration.defaults"
|
MAINSPEC = "app-configuration.defaults"
|
||||||
proxyTypes=[u"http", u"https", u"socks4", u"socks5"]
|
proxyTypes = ["system", "http", "socks4", "socks4a", "socks5", "socks5h"]
|
||||||
app = None
|
app = None
|
||||||
keymap=None
|
keymap=None
|
||||||
changed_keymap = False
|
changed_keymap = False
|
||||||
|
|
||||||
def setup ():
|
def setup ():
|
||||||
global app
|
global app
|
||||||
log.debug("Loading global app settings...")
|
log.debug("Loading global app settings...")
|
||||||
app = config_utils.load_config(os.path.join(paths.config_path(), MAINFILE), os.path.join(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...")
|
log.debug("Loading keymap...")
|
||||||
global keymap
|
global keymap
|
||||||
if float(platform.version()[:2]) >= 10 and app["app-settings"]["load_keymap"] == "default.keymap":
|
if float(platform.version()[:2]) >= 10 and app["app-settings"]["load_keymap"] == "default.keymap":
|
||||||
app["app-settings"]["load_keymap"] = "Windows 10.keymap"
|
app["app-settings"]["load_keymap"] = "Windows 10.keymap"
|
||||||
app.write()
|
app.write()
|
||||||
global changed_keymap
|
global changed_keymap
|
||||||
changed_keymap = True
|
changed_keymap = True
|
||||||
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)
|
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)
|
||||||
|
@@ -9,69 +9,69 @@ log = getLogger("config_utils")
|
|||||||
class ConfigLoadError(Exception): pass
|
class ConfigLoadError(Exception): pass
|
||||||
|
|
||||||
def load_config(config_path, configspec_path=None, copy=True, *args, **kwargs):
|
def load_config(config_path, configspec_path=None, copy=True, *args, **kwargs):
|
||||||
spec = ConfigObj(configspec_path, encoding='UTF8', list_values=False, _inspec=True)
|
spec = ConfigObj(configspec_path, encoding='UTF8', list_values=False, _inspec=True)
|
||||||
try:
|
try:
|
||||||
config = ConfigObj(infile=config_path, configspec=spec, create_empty=True, encoding='UTF8', *args, **kwargs)
|
config = ConfigObj(infile=config_path, configspec=spec, create_empty=True, encoding='UTF8', *args, **kwargs)
|
||||||
except ParseError:
|
except ParseError:
|
||||||
raise ConfigLoadError("Unable to load %r" % config_path)
|
raise ConfigLoadError("Unable to load %r" % config_path)
|
||||||
validator = Validator()
|
validator = Validator()
|
||||||
validated = config.validate(validator, preserve_errors=False, copy=copy)
|
validated = config.validate(validator, preserve_errors=False, copy=copy)
|
||||||
if validated == True:
|
if validated == True:
|
||||||
config.write()
|
config.write()
|
||||||
return config
|
return config
|
||||||
else:
|
else:
|
||||||
log.exception("Error in config file: {0}".format(validated,))
|
log.exception("Error in config file: {0}".format(validated,))
|
||||||
|
|
||||||
def is_blank(arg):
|
def is_blank(arg):
|
||||||
"Check if a line is blank."
|
"Check if a line is blank."
|
||||||
for c in arg:
|
for c in arg:
|
||||||
if c not in string.whitespace:
|
if c not in string.whitespace:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def get_keys(path):
|
def get_keys(path):
|
||||||
"Gets the keys of a configobj config file."
|
"Gets the keys of a configobj config file."
|
||||||
res=[]
|
res=[]
|
||||||
fin=open(path)
|
fin=open(path)
|
||||||
for line in fin:
|
for line in fin:
|
||||||
if not is_blank(line):
|
if not is_blank(line):
|
||||||
res.append(line[0:line.find('=')].strip())
|
res.append(line[0:line.find('=')].strip())
|
||||||
fin.close()
|
fin.close()
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def hist(keys):
|
def hist(keys):
|
||||||
"Generates a histogram of an iterable."
|
"Generates a histogram of an iterable."
|
||||||
res={}
|
res={}
|
||||||
for k in keys:
|
for k in keys:
|
||||||
res[k]=res.setdefault(k,0)+1
|
res[k]=res.setdefault(k,0)+1
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def find_problems(hist):
|
def find_problems(hist):
|
||||||
"Takes a histogram and returns a list of items occurring more than once."
|
"Takes a histogram and returns a list of items occurring more than once."
|
||||||
res=[]
|
res=[]
|
||||||
for k,v in hist.items():
|
for k,v in hist.items():
|
||||||
if v>1:
|
if v>1:
|
||||||
res.append(k)
|
res.append(k)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def clean_config(path):
|
def clean_config(path):
|
||||||
"Cleans a config file. If duplicate values are found, delete all of them and just use the default."
|
"Cleans a config file. If duplicate values are found, delete all of them and just use the default."
|
||||||
orig=[]
|
orig=[]
|
||||||
cleaned=[]
|
cleaned=[]
|
||||||
fin=open(path)
|
fin=open(path)
|
||||||
for line in fin:
|
for line in fin:
|
||||||
orig.append(line)
|
orig.append(line)
|
||||||
fin.close()
|
fin.close()
|
||||||
for p in find_problems(hist(get_keys(path))):
|
for p in find_problems(hist(get_keys(path))):
|
||||||
for o in orig:
|
for o in orig:
|
||||||
o.strip()
|
o.strip()
|
||||||
if p not in o:
|
if p not in o:
|
||||||
cleaned.append(o)
|
cleaned.append(o)
|
||||||
if len(cleaned) != 0:
|
if len(cleaned) != 0:
|
||||||
cam=open(path,'w')
|
cam=open(path,'w')
|
||||||
for c in cleaned:
|
for c in cleaned:
|
||||||
cam.write(c)
|
cam.write(c)
|
||||||
cam.close()
|
cam.close()
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
@@ -8,33 +8,33 @@ from wxUI.dialogs import attach as gui
|
|||||||
log = logging.getLogger("controller.attach")
|
log = logging.getLogger("controller.attach")
|
||||||
|
|
||||||
class attach(object):
|
class attach(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.attachments = list()
|
self.attachments = list()
|
||||||
self.dialog = gui.attachDialog()
|
self.dialog = gui.attachDialog()
|
||||||
widgetUtils.connect_event(self.dialog.photo, widgetUtils.BUTTON_PRESSED, self.upload_image)
|
widgetUtils.connect_event(self.dialog.photo, widgetUtils.BUTTON_PRESSED, self.upload_image)
|
||||||
widgetUtils.connect_event(self.dialog.remove, widgetUtils.BUTTON_PRESSED, self.remove_attachment)
|
widgetUtils.connect_event(self.dialog.remove, widgetUtils.BUTTON_PRESSED, self.remove_attachment)
|
||||||
self.dialog.get_response()
|
self.dialog.get_response()
|
||||||
log.debug("Attachments controller started.")
|
log.debug("Attachments controller started.")
|
||||||
|
|
||||||
def upload_image(self, *args, **kwargs):
|
def upload_image(self, *args, **kwargs):
|
||||||
image, description = self.dialog.get_image()
|
image, description = self.dialog.get_image()
|
||||||
if image != None:
|
if image != None:
|
||||||
imageInfo = {"type": "photo", "file": image, "description": description}
|
imageInfo = {"type": "photo", "file": image, "description": description}
|
||||||
log.debug("Image data to upload: %r" % (imageInfo,))
|
log.debug("Image data to upload: %r" % (imageInfo,))
|
||||||
self.attachments.append(imageInfo)
|
self.attachments.append(imageInfo)
|
||||||
info = [_(u"Photo"), description]
|
info = [_(u"Photo"), description]
|
||||||
self.dialog.attachments.insert_item(False, *info)
|
self.dialog.attachments.insert_item(False, *info)
|
||||||
self.dialog.remove.Enable(True)
|
self.dialog.remove.Enable(True)
|
||||||
|
|
||||||
def remove_attachment(self, *args, **kwargs):
|
def remove_attachment(self, *args, **kwargs):
|
||||||
current_item = self.dialog.attachments.get_selected()
|
current_item = self.dialog.attachments.get_selected()
|
||||||
log.debug("Removing item %d" % (current_item,))
|
log.debug("Removing item %d" % (current_item,))
|
||||||
if current_item == -1: current_item = 0
|
if current_item == -1: current_item = 0
|
||||||
self.attachments.pop(current_item)
|
self.attachments.pop(current_item)
|
||||||
self.dialog.attachments.remove_item(current_item)
|
self.dialog.attachments.remove_item(current_item)
|
||||||
self.check_remove_status()
|
self.check_remove_status()
|
||||||
log.debug("Removed")
|
log.debug("Removed")
|
||||||
|
|
||||||
def check_remove_status(self):
|
def check_remove_status(self):
|
||||||
if len(self.attachments) == 0 and self.dialog.attachments.get_count() == 0:
|
if len(self.attachments) == 0 and self.dialog.attachments.get_count() == 0:
|
||||||
self.dialog.remove.Enable(False)
|
self.dialog.remove.Enable(False)
|
||||||
|
@@ -14,190 +14,196 @@ from wxUI import buffers
|
|||||||
log = logging.getLogger("controller.buffers.baseBuffers")
|
log = logging.getLogger("controller.buffers.baseBuffers")
|
||||||
|
|
||||||
def _items_exist(function):
|
def _items_exist(function):
|
||||||
""" A decorator to execute a function only if the selected buffer contains at least one item."""
|
""" A decorator to execute a function only if the selected buffer contains at least one item."""
|
||||||
def function_(self, *args, **kwargs):
|
def function_(self, *args, **kwargs):
|
||||||
if self.buffer.list.get_count() > 0:
|
if self.buffer.list.get_count() > 0:
|
||||||
function(self, *args, **kwargs)
|
function(self, *args, **kwargs)
|
||||||
return function_
|
return function_
|
||||||
|
|
||||||
class buffer(object):
|
class buffer(object):
|
||||||
""" A basic buffer object. This should be the base class for all other derived buffers."""
|
""" A basic buffer object. This should be the base class for all other derived buffers."""
|
||||||
|
|
||||||
def __init__(self, parent=None, function=None, session=None, *args, **kwargs):
|
def __init__(self, parent=None, function=None, session=None, *args, **kwargs):
|
||||||
"""Inits the main controller for this buffer:
|
"""Inits the main controller for this buffer:
|
||||||
@ parent wx.Treebook object: Container where we will put this buffer.
|
@ parent wx.Treebook object: Container where we will put this buffer.
|
||||||
@ function str or None: function to be called periodically and update items on this buffer.
|
@ function str or None: function to be called periodically and update items on this buffer.
|
||||||
@ session sessionmanager.session object or None: Session handler for settings, database and data access.
|
@ session sessionmanager.session object or None: Session handler for settings, database and data access.
|
||||||
"""
|
"""
|
||||||
super(buffer, self).__init__()
|
super(buffer, self).__init__()
|
||||||
self.function = function
|
self.function = function
|
||||||
# Compose_function will be used to render an object on this buffer. Normally, signature is as follows:
|
# Compose_function will be used to render an object on this buffer. Normally, signature is as follows:
|
||||||
# compose_function(item, db, relative_times, show_screen_names=False, session=None)
|
# compose_function(item, db, relative_times, show_screen_names=False, session=None)
|
||||||
# Read more about compose functions in twitter/compose.py.
|
# Read more about compose functions in twitter/compose.py.
|
||||||
self.compose_function = None
|
self.compose_function = None
|
||||||
self.args = args
|
self.args = args
|
||||||
self.kwargs = kwargs
|
self.kwargs = kwargs
|
||||||
# This will be used as a reference to the wx.Panel object wich stores the buffer GUI.
|
# This will be used as a reference to the wx.Panel object wich stores the buffer GUI.
|
||||||
self.buffer = None
|
self.buffer = None
|
||||||
# This should countains the account associated to this buffer.
|
# This should countains the account associated to this buffer.
|
||||||
self.account = ""
|
self.account = ""
|
||||||
# This controls whether the start_stream function should be called when starting the program.
|
# This controls whether the start_stream function should be called when starting the program.
|
||||||
self.needs_init = True
|
self.needs_init = True
|
||||||
# if this is set to False, the buffer will be ignored on the invisible interface.
|
# if this is set to False, the buffer will be ignored on the invisible interface.
|
||||||
self.invisible = False
|
self.invisible = False
|
||||||
# Control variable, used to track time of execution for calls to start_stream.
|
# Control variable, used to track time of execution for calls to start_stream.
|
||||||
self.execution_time = 0
|
self.execution_time = 0
|
||||||
|
|
||||||
def clear_list(self):
|
def clear_list(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def get_event(self, ev):
|
def get_event(self, ev):
|
||||||
""" Catch key presses in the WX interface and generate the corresponding event names."""
|
""" Catch key presses in the WX interface and generate the corresponding event names."""
|
||||||
if ev.GetKeyCode() == wx.WXK_RETURN and ev.ControlDown(): event = "audio"
|
if ev.GetKeyCode() == wx.WXK_RETURN and ev.ControlDown(): event = "audio"
|
||||||
elif ev.GetKeyCode() == wx.WXK_RETURN: event = "url"
|
elif ev.GetKeyCode() == wx.WXK_RETURN: event = "url"
|
||||||
elif ev.GetKeyCode() == wx.WXK_F5: event = "volume_down"
|
elif ev.GetKeyCode() == wx.WXK_F5: event = "volume_down"
|
||||||
elif ev.GetKeyCode() == wx.WXK_F6: event = "volume_up"
|
elif ev.GetKeyCode() == wx.WXK_F6: event = "volume_up"
|
||||||
elif ev.GetKeyCode() == wx.WXK_DELETE and ev.ShiftDown(): event = "clear_list"
|
elif ev.GetKeyCode() == wx.WXK_DELETE and ev.ShiftDown(): event = "clear_list"
|
||||||
elif ev.GetKeyCode() == wx.WXK_DELETE: event = "destroy_status"
|
elif ev.GetKeyCode() == wx.WXK_DELETE: event = "destroy_status"
|
||||||
else:
|
# Raise a Special event when pressed Shift+F10 because Wx==4.1.x does not seems to trigger this by itself.
|
||||||
event = None
|
# See https://github.com/manuelcortez/TWBlue/issues/353
|
||||||
ev.Skip()
|
elif ev.GetKeyCode() == wx.WXK_F10 and ev.ShiftDown(): event = "show_menu"
|
||||||
if event != None:
|
else:
|
||||||
try:
|
event = None
|
||||||
getattr(self, event)()
|
ev.Skip()
|
||||||
except AttributeError:
|
if event != None:
|
||||||
pass
|
try:
|
||||||
|
### ToDo: Remove after WX fixes issue #353 in the widgets.
|
||||||
|
if event == "show_menu":
|
||||||
|
return self.show_menu(widgetUtils.MENU, pos=self.buffer.list.list.GetPosition())
|
||||||
|
getattr(self, event)()
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
def volume_down(self):
|
def volume_down(self):
|
||||||
""" Decreases volume by 5%"""
|
""" Decreases volume by 5%"""
|
||||||
if self.session.settings["sound"]["volume"] > 0.0:
|
if self.session.settings["sound"]["volume"] > 0.0:
|
||||||
if self.session.settings["sound"]["volume"] <= 0.05:
|
if self.session.settings["sound"]["volume"] <= 0.05:
|
||||||
self.session.settings["sound"]["volume"] = 0.0
|
self.session.settings["sound"]["volume"] = 0.0
|
||||||
else:
|
else:
|
||||||
self.session.settings["sound"]["volume"] -=0.05
|
self.session.settings["sound"]["volume"] -=0.05
|
||||||
sound.URLPlayer.player.audio_set_volume(int(self.session.settings["sound"]["volume"]*100.0))
|
sound.URLPlayer.player.audio_set_volume(int(self.session.settings["sound"]["volume"]*100.0))
|
||||||
self.session.sound.play("volume_changed.ogg")
|
self.session.sound.play("volume_changed.ogg")
|
||||||
self.session.settings.write()
|
self.session.settings.write()
|
||||||
|
|
||||||
def volume_up(self):
|
def volume_up(self):
|
||||||
""" Increases volume by 5%."""
|
""" Increases volume by 5%."""
|
||||||
if self.session.settings["sound"]["volume"] < 1.0:
|
if self.session.settings["sound"]["volume"] < 1.0:
|
||||||
if self.session.settings["sound"]["volume"] >= 0.95:
|
if self.session.settings["sound"]["volume"] >= 0.95:
|
||||||
self.session.settings["sound"]["volume"] = 1.0
|
self.session.settings["sound"]["volume"] = 1.0
|
||||||
else:
|
else:
|
||||||
self.session.settings["sound"]["volume"] +=0.05
|
self.session.settings["sound"]["volume"] +=0.05
|
||||||
sound.URLPlayer.player.audio_set_volume(int(self.session.settings["sound"]["volume"]*100))
|
sound.URLPlayer.player.audio_set_volume(int(self.session.settings["sound"]["volume"]*100))
|
||||||
self.session.sound.play("volume_changed.ogg")
|
self.session.sound.play("volume_changed.ogg")
|
||||||
self.session.settings.write()
|
self.session.settings.write()
|
||||||
|
|
||||||
def start_stream(self, mandatory=False, play_sound=True):
|
def start_stream(self, mandatory=False, play_sound=True):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def get_more_items(self):
|
def get_more_items(self):
|
||||||
output.speak(_(u"This action is not supported for this buffer"), True)
|
output.speak(_(u"This action is not supported for this buffer"), True)
|
||||||
|
|
||||||
def put_items_on_list(self, items):
|
def put_items_on_list(self, items):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def remove_buffer(self):
|
def remove_buffer(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def remove_item(self, item):
|
def remove_item(self, item):
|
||||||
f = self.buffer.list.get_selected()
|
f = self.buffer.list.get_selected()
|
||||||
self.buffer.list.remove_item(item)
|
self.buffer.list.remove_item(item)
|
||||||
self.buffer.list.select_item(f)
|
self.buffer.list.select_item(f)
|
||||||
|
|
||||||
def bind_events(self):
|
def bind_events(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def get_object(self):
|
def get_object(self):
|
||||||
return self.buffer
|
return self.buffer
|
||||||
|
|
||||||
def get_message(self):
|
def get_message(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def set_list_position(self, reversed=False):
|
def set_list_position(self, reversed=False):
|
||||||
if reversed == False:
|
if reversed == False:
|
||||||
self.buffer.list.select_item(-1)
|
self.buffer.list.select_item(-1)
|
||||||
else:
|
else:
|
||||||
self.buffer.list.select_item(0)
|
self.buffer.list.select_item(0)
|
||||||
|
|
||||||
def reply(self):
|
def reply(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def send_message(self):
|
def send_message(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def share_item(self):
|
def share_item(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def destroy_status(self):
|
def destroy_status(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def post_status(self, *args, **kwargs):
|
def post_status(self, *args, **kwargs):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def save_positions(self):
|
def save_positions(self):
|
||||||
try:
|
try:
|
||||||
self.session.db[self.name+"_pos"]=self.buffer.list.get_selected()
|
self.session.db[self.name+"_pos"]=self.buffer.list.get_selected()
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class accountPanel(buffer):
|
class accountPanel(buffer):
|
||||||
def __init__(self, parent, name, account, account_id):
|
def __init__(self, parent, name, account, account_id):
|
||||||
super(accountPanel, self).__init__(parent, None, name)
|
super(accountPanel, self).__init__(parent, None, name)
|
||||||
log.debug("Initializing buffer %s, account %s" % (name, account,))
|
log.debug("Initializing buffer %s, account %s" % (name, account,))
|
||||||
self.buffer = buffers.accountPanel(parent, name)
|
self.buffer = buffers.accountPanel(parent, name)
|
||||||
self.type = self.buffer.type
|
self.type = self.buffer.type
|
||||||
self.compose_function = None
|
self.compose_function = None
|
||||||
self.session = None
|
self.session = None
|
||||||
self.needs_init = False
|
self.needs_init = False
|
||||||
self.account = account
|
self.account = account
|
||||||
self.buffer.account = account
|
self.buffer.account = account
|
||||||
self.name = name
|
self.name = name
|
||||||
self.account_id = account_id
|
self.account_id = account_id
|
||||||
|
|
||||||
def setup_account(self):
|
def setup_account(self):
|
||||||
widgetUtils.connect_event(self.buffer, widgetUtils.CHECKBOX, self.autostart, menuitem=self.buffer.autostart_account)
|
widgetUtils.connect_event(self.buffer, widgetUtils.CHECKBOX, self.autostart, menuitem=self.buffer.autostart_account)
|
||||||
if self.account_id in config.app["sessions"]["ignored_sessions"]:
|
if self.account_id in config.app["sessions"]["ignored_sessions"]:
|
||||||
self.buffer.change_autostart(False)
|
self.buffer.change_autostart(False)
|
||||||
else:
|
else:
|
||||||
self.buffer.change_autostart(True)
|
self.buffer.change_autostart(True)
|
||||||
if not hasattr(self, "logged"):
|
if not hasattr(self, "logged"):
|
||||||
self.buffer.change_login(login=False)
|
self.buffer.change_login(login=False)
|
||||||
widgetUtils.connect_event(self.buffer.login, widgetUtils.BUTTON_PRESSED, self.logout)
|
widgetUtils.connect_event(self.buffer.login, widgetUtils.BUTTON_PRESSED, self.logout)
|
||||||
else:
|
else:
|
||||||
self.buffer.change_login(login=True)
|
self.buffer.change_login(login=True)
|
||||||
widgetUtils.connect_event(self.buffer.login, widgetUtils.BUTTON_PRESSED, self.login)
|
widgetUtils.connect_event(self.buffer.login, widgetUtils.BUTTON_PRESSED, self.login)
|
||||||
|
|
||||||
def login(self, *args, **kwargs):
|
def login(self, *args, **kwargs):
|
||||||
del self.logged
|
del self.logged
|
||||||
self.setup_account()
|
self.setup_account()
|
||||||
pub.sendMessage("login", session_id=self.account_id)
|
pub.sendMessage("login", session_id=self.account_id)
|
||||||
|
|
||||||
def logout(self, *args, **kwargs):
|
def logout(self, *args, **kwargs):
|
||||||
self.logged = False
|
self.logged = False
|
||||||
self.setup_account()
|
self.setup_account()
|
||||||
pub.sendMessage("logout", session_id=self.account_id)
|
pub.sendMessage("logout", session_id=self.account_id)
|
||||||
|
|
||||||
def autostart(self, *args, **kwargs):
|
def autostart(self, *args, **kwargs):
|
||||||
if self.account_id in config.app["sessions"]["ignored_sessions"]:
|
if self.account_id in config.app["sessions"]["ignored_sessions"]:
|
||||||
self.buffer.change_autostart(True)
|
self.buffer.change_autostart(True)
|
||||||
config.app["sessions"]["ignored_sessions"].remove(self.account_id)
|
config.app["sessions"]["ignored_sessions"].remove(self.account_id)
|
||||||
else:
|
else:
|
||||||
self.buffer.change_autostart(False)
|
self.buffer.change_autostart(False)
|
||||||
config.app["sessions"]["ignored_sessions"].append(self.account_id)
|
config.app["sessions"]["ignored_sessions"].append(self.account_id)
|
||||||
config.app.write()
|
config.app.write()
|
||||||
|
|
||||||
class emptyPanel(buffer):
|
class emptyPanel(buffer):
|
||||||
def __init__(self, parent, name, account):
|
def __init__(self, parent, name, account):
|
||||||
super(emptyPanel, self).__init__(parent=parent)
|
super(emptyPanel, self).__init__(parent=parent)
|
||||||
log.debug("Initializing buffer %s, account %s" % (name, account,))
|
log.debug("Initializing buffer %s, account %s" % (name, account,))
|
||||||
self.buffer = buffers.emptyPanel(parent, name)
|
self.buffer = buffers.emptyPanel(parent, name)
|
||||||
self.type = self.buffer.type
|
self.type = self.buffer.type
|
||||||
self.compose_function = None
|
self.compose_function = None
|
||||||
self.account = account
|
self.account = account
|
||||||
self.buffer.account = account
|
self.buffer.account = account
|
||||||
self.name = name
|
self.name = name
|
||||||
self.session = None
|
self.session = None
|
||||||
self.needs_init = True
|
self.needs_init = True
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -8,71 +8,71 @@ from wxUI.dialogs import filterDialogs
|
|||||||
from wxUI import commonMessageDialogs
|
from wxUI import commonMessageDialogs
|
||||||
|
|
||||||
class filter(object):
|
class filter(object):
|
||||||
def __init__(self, buffer, filter_title=None, if_word_exists=None, in_lang=None, regexp=None, word=None, in_buffer=None):
|
def __init__(self, buffer, filter_title=None, if_word_exists=None, in_lang=None, regexp=None, word=None, in_buffer=None):
|
||||||
self.buffer = buffer
|
self.buffer = buffer
|
||||||
self.dialog = filterDialogs.filterDialog(languages=[i["name"] for i in application.supported_languages])
|
self.dialog = filterDialogs.filterDialog(languages=[i["name"] for i in application.supported_languages])
|
||||||
if self.dialog.get_response() == widgetUtils.OK:
|
if self.dialog.get_response() == widgetUtils.OK:
|
||||||
title = self.dialog.get("title")
|
title = self.dialog.get("title")
|
||||||
contains = self.dialog.get("contains")
|
contains = self.dialog.get("contains")
|
||||||
term = self.dialog.get("term")
|
term = self.dialog.get("term")
|
||||||
regexp = self.dialog.get("regexp")
|
regexp = self.dialog.get("regexp")
|
||||||
allow_rts = self.dialog.get("allow_rts")
|
allow_rts = self.dialog.get("allow_rts")
|
||||||
allow_quotes = self.dialog.get("allow_quotes")
|
allow_quotes = self.dialog.get("allow_quotes")
|
||||||
allow_replies = self.dialog.get("allow_replies")
|
allow_replies = self.dialog.get("allow_replies")
|
||||||
load_language = self.dialog.get("load_language")
|
load_language = self.dialog.get("load_language")
|
||||||
ignore_language = self.dialog.get("ignore_language")
|
ignore_language = self.dialog.get("ignore_language")
|
||||||
lang_option = None
|
lang_option = None
|
||||||
if ignore_language:
|
if ignore_language:
|
||||||
lang_option = False
|
lang_option = False
|
||||||
elif load_language:
|
elif load_language:
|
||||||
lang_option = True
|
lang_option = True
|
||||||
langs = self.dialog.get_selected_langs()
|
langs = self.dialog.get_selected_langs()
|
||||||
langcodes = []
|
langcodes = []
|
||||||
for i in application.supported_languages:
|
for i in application.supported_languages:
|
||||||
if i["name"] in langs:
|
if i["name"] in langs:
|
||||||
langcodes.append(i["code"])
|
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)
|
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 title in self.buffer.session.settings["filters"]:
|
if title in self.buffer.session.settings["filters"]:
|
||||||
return commonMessageDialogs.existing_filter()
|
return commonMessageDialogs.existing_filter()
|
||||||
self.buffer.session.settings["filters"][title] = d
|
self.buffer.session.settings["filters"][title] = d
|
||||||
self.buffer.session.settings.write()
|
self.buffer.session.settings.write()
|
||||||
|
|
||||||
class filterManager(object):
|
class filterManager(object):
|
||||||
|
|
||||||
def __init__(self, session):
|
def __init__(self, session):
|
||||||
self.session = session
|
self.session = session
|
||||||
self.dialog = filterDialogs.filterManagerDialog()
|
self.dialog = filterDialogs.filterManagerDialog()
|
||||||
self.insert_filters(self.session.settings["filters"])
|
self.insert_filters(self.session.settings["filters"])
|
||||||
if self.dialog.filters.get_count() == 0:
|
if self.dialog.filters.get_count() == 0:
|
||||||
self.dialog.edit.Enable(False)
|
self.dialog.edit.Enable(False)
|
||||||
self.dialog.delete.Enable(False)
|
self.dialog.delete.Enable(False)
|
||||||
else:
|
else:
|
||||||
widgetUtils.connect_event(self.dialog.edit, widgetUtils.BUTTON_PRESSED, self.edit_filter)
|
widgetUtils.connect_event(self.dialog.edit, widgetUtils.BUTTON_PRESSED, self.edit_filter)
|
||||||
widgetUtils.connect_event(self.dialog.delete, widgetUtils.BUTTON_PRESSED, self.delete_filter)
|
widgetUtils.connect_event(self.dialog.delete, widgetUtils.BUTTON_PRESSED, self.delete_filter)
|
||||||
response = self.dialog.get_response()
|
response = self.dialog.get_response()
|
||||||
|
|
||||||
def insert_filters(self, filters):
|
def insert_filters(self, filters):
|
||||||
self.dialog.filters.clear()
|
self.dialog.filters.clear()
|
||||||
for f in list(filters.keys()):
|
for f in list(filters.keys()):
|
||||||
filterName = f
|
filterName = f
|
||||||
buffer = filters[f]["in_buffer"]
|
buffer = filters[f]["in_buffer"]
|
||||||
if filters[f]["if_word_exists"] == "True" and filters[f]["word"] != "":
|
if filters[f]["if_word_exists"] == "True" and filters[f]["word"] != "":
|
||||||
filter_by_word = "True"
|
filter_by_word = "True"
|
||||||
else:
|
else:
|
||||||
filter_by_word = "False"
|
filter_by_word = "False"
|
||||||
filter_by_lang = ""
|
filter_by_lang = ""
|
||||||
if filters[f]["in_lang"] != "None":
|
if filters[f]["in_lang"] != "None":
|
||||||
filter_by_lang = "True"
|
filter_by_lang = "True"
|
||||||
b = [f, buffer, filter_by_word, filter_by_lang]
|
b = [f, buffer, filter_by_word, filter_by_lang]
|
||||||
self.dialog.filters.insert_item(False, *b)
|
self.dialog.filters.insert_item(False, *b)
|
||||||
|
|
||||||
def edit_filter(self, *args, **kwargs):
|
def edit_filter(self, *args, **kwargs):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def delete_filter(self, *args, **kwargs):
|
def delete_filter(self, *args, **kwargs):
|
||||||
filter_title = self.dialog.filters.get_text_column(self.dialog.filters.get_selected(), 0)
|
filter_title = self.dialog.filters.get_text_column(self.dialog.filters.get_selected(), 0)
|
||||||
response = commonMessageDialogs.delete_filter()
|
response = commonMessageDialogs.delete_filter()
|
||||||
if response == widgetUtils.YES:
|
if response == widgetUtils.YES:
|
||||||
self.session.settings["filters"].pop(filter_title)
|
self.session.settings["filters"].pop(filter_title)
|
||||||
self.session.settings.write()
|
self.session.settings.write()
|
||||||
self.insert_filters(self.session.settings["filters"])
|
self.insert_filters(self.session.settings["filters"])
|
||||||
|
@@ -1,108 +1,110 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
|
||||||
from builtins import object
|
|
||||||
import widgetUtils
|
import widgetUtils
|
||||||
import output
|
import output
|
||||||
|
import logging
|
||||||
from wxUI.dialogs import lists
|
from wxUI.dialogs import lists
|
||||||
from twython import TwythonError
|
from tweepy.error import TweepError
|
||||||
from sessions.twitter import compose, utils
|
from sessions.twitter import compose, utils
|
||||||
from pubsub import pub
|
from pubsub import pub
|
||||||
|
|
||||||
|
log = logging.getLogger("controller.listsController")
|
||||||
|
|
||||||
class listsController(object):
|
class listsController(object):
|
||||||
def __init__(self, session, user=None):
|
def __init__(self, session, user=None):
|
||||||
super(listsController, self).__init__()
|
super(listsController, self).__init__()
|
||||||
self.session = session
|
self.session = session
|
||||||
if user == None:
|
if user == None:
|
||||||
self.dialog = lists.listViewer()
|
self.dialog = lists.listViewer()
|
||||||
self.dialog.populate_list(self.get_all_lists())
|
self.dialog.populate_list(self.get_all_lists())
|
||||||
widgetUtils.connect_event(self.dialog.createBtn, widgetUtils.BUTTON_PRESSED, self.create_list)
|
widgetUtils.connect_event(self.dialog.createBtn, widgetUtils.BUTTON_PRESSED, self.create_list)
|
||||||
widgetUtils.connect_event(self.dialog.editBtn, widgetUtils.BUTTON_PRESSED, self.edit_list)
|
widgetUtils.connect_event(self.dialog.editBtn, widgetUtils.BUTTON_PRESSED, self.edit_list)
|
||||||
widgetUtils.connect_event(self.dialog.deleteBtn, widgetUtils.BUTTON_PRESSED, self.remove_list)
|
widgetUtils.connect_event(self.dialog.deleteBtn, widgetUtils.BUTTON_PRESSED, self.remove_list)
|
||||||
widgetUtils.connect_event(self.dialog.view, widgetUtils.BUTTON_PRESSED, self.open_list_as_buffer)
|
widgetUtils.connect_event(self.dialog.view, widgetUtils.BUTTON_PRESSED, self.open_list_as_buffer)
|
||||||
widgetUtils.connect_event(self.dialog.deleteBtn, widgetUtils.BUTTON_PRESSED, self.remove_list)
|
widgetUtils.connect_event(self.dialog.deleteBtn, widgetUtils.BUTTON_PRESSED, self.remove_list)
|
||||||
else:
|
else:
|
||||||
self.dialog = lists.userListViewer(user)
|
self.dialog = lists.userListViewer(user)
|
||||||
self.dialog.populate_list(self.get_user_lists(user))
|
self.dialog.populate_list(self.get_user_lists(user))
|
||||||
widgetUtils.connect_event(self.dialog.createBtn, widgetUtils.BUTTON_PRESSED, self.subscribe)
|
widgetUtils.connect_event(self.dialog.createBtn, widgetUtils.BUTTON_PRESSED, self.subscribe)
|
||||||
widgetUtils.connect_event(self.dialog.deleteBtn, widgetUtils.BUTTON_PRESSED, self.unsubscribe)
|
widgetUtils.connect_event(self.dialog.deleteBtn, widgetUtils.BUTTON_PRESSED, self.unsubscribe)
|
||||||
self.dialog.get_response()
|
self.dialog.get_response()
|
||||||
|
|
||||||
def get_all_lists(self):
|
def get_all_lists(self):
|
||||||
return [compose.compose_list(item) for item in self.session.db["lists"]]
|
return [compose.compose_list(item) for item in self.session.db["lists"]]
|
||||||
|
|
||||||
def get_user_lists(self, user):
|
def get_user_lists(self, user):
|
||||||
self.lists = self.session.twitter.show_lists(reverse=True, screen_name=user)
|
self.lists = self.session.twitter.lists_all(reverse=True, screen_name=user)
|
||||||
return [compose.compose_list(item) for item in self.lists]
|
return [compose.compose_list(item) for item in self.lists]
|
||||||
|
|
||||||
def create_list(self, *args, **kwargs):
|
def create_list(self, *args, **kwargs):
|
||||||
dialog = lists.createListDialog()
|
dialog = lists.createListDialog()
|
||||||
if dialog.get_response() == widgetUtils.OK:
|
if dialog.get_response() == widgetUtils.OK:
|
||||||
name = dialog.get("name")
|
name = dialog.get("name")
|
||||||
description = dialog.get("description")
|
description = dialog.get("description")
|
||||||
p = dialog.get("public")
|
p = dialog.get("public")
|
||||||
if p == True:
|
if p == True:
|
||||||
mode = "public"
|
mode = "public"
|
||||||
else:
|
else:
|
||||||
mode = "private"
|
mode = "private"
|
||||||
try:
|
try:
|
||||||
new_list = self.session.twitter.create_list(name=name, description=description, mode=mode)
|
new_list = self.session.twitter.create_list(name=name, description=description, mode=mode)
|
||||||
self.session.db["lists"].append(new_list)
|
self.session.db["lists"].append(new_list)
|
||||||
self.dialog.lista.insert_item(False, *compose.compose_list(new_list))
|
self.dialog.lista.insert_item(False, *compose.compose_list(new_list))
|
||||||
except TwythonError as e:
|
except TweepError as e:
|
||||||
output.speak("error %s: %s" % (e.status_code, e.msg))
|
output.speak("error %s: %s" % (e.api_code, e.reason))
|
||||||
dialog.destroy()
|
log.exception("error %s: %s" % (e.api_code, e.reason))
|
||||||
|
dialog.destroy()
|
||||||
|
|
||||||
def edit_list(self, *args, **kwargs):
|
def edit_list(self, *args, **kwargs):
|
||||||
if self.dialog.lista.get_count() == 0: return
|
if self.dialog.lista.get_count() == 0: return
|
||||||
list = self.session.db["lists"][self.dialog.get_item()]
|
list = self.session.db["lists"][self.dialog.get_item()]
|
||||||
dialog = lists.editListDialog(list)
|
dialog = lists.editListDialog(list)
|
||||||
if dialog.get_response() == widgetUtils.OK:
|
if dialog.get_response() == widgetUtils.OK:
|
||||||
name = dialog.get("name")
|
name = dialog.get("name")
|
||||||
description = dialog.get("description")
|
description = dialog.get("description")
|
||||||
p = dialog.get("public")
|
p = dialog.get("public")
|
||||||
if p == True:
|
if p == True:
|
||||||
mode = "public"
|
mode = "public"
|
||||||
else:
|
else:
|
||||||
mode = "private"
|
mode = "private"
|
||||||
try:
|
try:
|
||||||
self.session.twitter.update_list(list_id=list["id"], name=name, description=description, mode=mode)
|
self.session.twitter.update_list(list_id=list.id, name=name, description=description, mode=mode)
|
||||||
self.session.get_lists()
|
self.session.get_lists()
|
||||||
self.dialog.populate_list(self.get_all_lists(), True)
|
self.dialog.populate_list(self.get_all_lists(), True)
|
||||||
except TwythonError as e:
|
except TweepError as e:
|
||||||
output.speak("error %s: %s" % (e.error_code, e.msg))
|
output.speak("error %s: %s" % (e.api_code, e.reason))
|
||||||
dialog.destroy()
|
dialog.destroy()
|
||||||
|
|
||||||
def remove_list(self, *args, **kwargs):
|
def remove_list(self, *args, **kwargs):
|
||||||
if self.dialog.lista.get_count() == 0: return
|
if self.dialog.lista.get_count() == 0: return
|
||||||
list = self.session.db["lists"][self.dialog.get_item()]["id"]
|
list = self.session.db["lists"][self.dialog.get_item()].id
|
||||||
if lists.remove_list() == widgetUtils.YES:
|
if lists.remove_list() == widgetUtils.YES:
|
||||||
try:
|
try:
|
||||||
self.session.twitter.delete_list(list_id=list)
|
self.session.twitter.destroy_list(list_id=list)
|
||||||
self.session.db["lists"].pop(self.dialog.get_item())
|
self.session.db["lists"].pop(self.dialog.get_item())
|
||||||
self.dialog.lista.remove_item(self.dialog.get_item())
|
self.dialog.lista.remove_item(self.dialog.get_item())
|
||||||
except TwythonError as e:
|
except TweepError as e:
|
||||||
output.speak("error %s: %s" % (e.error_code, e.msg))
|
output.speak("error %s: %s" % (e.api_code, e.reason))
|
||||||
|
|
||||||
def open_list_as_buffer(self, *args, **kwargs):
|
def open_list_as_buffer(self, *args, **kwargs):
|
||||||
if self.dialog.lista.get_count() == 0: return
|
if self.dialog.lista.get_count() == 0: return
|
||||||
list = self.session.db["lists"][self.dialog.get_item()]
|
list = self.session.db["lists"][self.dialog.get_item()]
|
||||||
pub.sendMessage("create-new-buffer", buffer="list", account=self.session.db["user_name"], create=list["name"])
|
pub.sendMessage("create-new-buffer", buffer="list", account=self.session.db["user_name"], create=list.name)
|
||||||
|
|
||||||
def subscribe(self, *args, **kwargs):
|
def subscribe(self, *args, **kwargs):
|
||||||
if self.dialog.lista.get_count() == 0: return
|
if self.dialog.lista.get_count() == 0: return
|
||||||
list_id = self.lists[self.dialog.get_item()]["id"]
|
list_id = self.lists[self.dialog.get_item()].id
|
||||||
try:
|
try:
|
||||||
list = self.session.twitter.subscribe_to_list(list_id=list_id)
|
list = self.session.twitter.subscribe_list(list_id=list_id)
|
||||||
item = utils.find_item(list["id"], self.session.db["lists"])
|
item = utils.find_item(list.id, self.session.db["lists"])
|
||||||
self.session.db["lists"].append(list)
|
self.session.db["lists"].append(list)
|
||||||
except TwythonError as e:
|
except TweepError as e:
|
||||||
output.speak("error %s: %s" % (e.status_code, e.msg))
|
output.speak("error %s: %s" % (e.api_code, e.reason))
|
||||||
|
|
||||||
def unsubscribe(self, *args, **kwargs):
|
def unsubscribe(self, *args, **kwargs):
|
||||||
if self.dialog.lista.get_count() == 0: return
|
if self.dialog.lista.get_count() == 0: return
|
||||||
list_id = self.lists[self.dialog.get_item()]["id"]
|
list_id = self.lists[self.dialog.get_item()].id
|
||||||
try:
|
try:
|
||||||
list = self.session.twitter.unsubscribe_from_list(list_id=list_id)
|
list = self.session.twitter.unsubscribe_list(list_id=list_id)
|
||||||
self.session.db["lists"].remove(list)
|
self.session.db["lists"].remove(list)
|
||||||
except TwythonError as e:
|
except TweepError as e:
|
||||||
output.speak("error %s: %s" % (e.status_code, e.msg))
|
output.speak("error %s: %s" % (e.api_code, e.reason))
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- 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 re
|
||||||
import platform
|
import platform
|
||||||
from . import attach
|
|
||||||
import arrow
|
import arrow
|
||||||
import languageHandler
|
import languageHandler
|
||||||
system = platform.system()
|
system = platform.system()
|
||||||
@@ -16,271 +10,283 @@ import url_shortener
|
|||||||
import sound
|
import sound
|
||||||
import config
|
import config
|
||||||
from pubsub import pub
|
from pubsub import pub
|
||||||
|
from twitter_text import parse_tweet
|
||||||
if system == "Windows":
|
if system == "Windows":
|
||||||
from wxUI.dialogs import message, urlList
|
from wxUI.dialogs import message, urlList
|
||||||
from wxUI import commonMessageDialogs
|
from wxUI import commonMessageDialogs
|
||||||
|
from extra import translator, SpellChecker, autocompletionUsers
|
||||||
from extra import translator, SpellChecker, autocompletionUsers
|
from extra.AudioUploader import audioUploader
|
||||||
from extra.AudioUploader import audioUploader
|
|
||||||
elif system == "Linux":
|
elif system == "Linux":
|
||||||
from gtkUI.dialogs import message
|
from gtkUI.dialogs import message
|
||||||
from sessions.twitter import utils
|
from sessions.twitter import utils
|
||||||
|
from . import attach
|
||||||
|
|
||||||
class basicTweet(object):
|
class basicTweet(object):
|
||||||
""" This class handles the tweet main features. Other classes should derive from this class."""
|
""" This class handles the tweet main features. Other classes should derive from this class."""
|
||||||
def __init__(self, session, title, caption, text, messageType="tweet", max=280, *args, **kwargs):
|
def __init__(self, session, title, caption, text, messageType="tweet", max=280, *args, **kwargs):
|
||||||
super(basicTweet, self).__init__()
|
super(basicTweet, self).__init__()
|
||||||
self.max = max
|
self.max = max
|
||||||
self.title = title
|
self.title = title
|
||||||
self.session = session
|
self.session = session
|
||||||
self.message = getattr(message, messageType)(title, caption, text, *args, **kwargs)
|
self.message = getattr(message, messageType)(title, caption, text, *args, **kwargs)
|
||||||
widgetUtils.connect_event(self.message.spellcheck, widgetUtils.BUTTON_PRESSED, self.spellcheck)
|
widgetUtils.connect_event(self.message.spellcheck, widgetUtils.BUTTON_PRESSED, self.spellcheck)
|
||||||
widgetUtils.connect_event(self.message.attach, widgetUtils.BUTTON_PRESSED, self.attach)
|
widgetUtils.connect_event(self.message.attach, widgetUtils.BUTTON_PRESSED, self.attach)
|
||||||
widgetUtils.connect_event(self.message.text, widgetUtils.ENTERED_TEXT, self.text_processor)
|
widgetUtils.connect_event(self.message.text, widgetUtils.ENTERED_TEXT, self.text_processor)
|
||||||
widgetUtils.connect_event(self.message.shortenButton, widgetUtils.BUTTON_PRESSED, self.shorten)
|
widgetUtils.connect_event(self.message.shortenButton, widgetUtils.BUTTON_PRESSED, self.shorten)
|
||||||
widgetUtils.connect_event(self.message.unshortenButton, widgetUtils.BUTTON_PRESSED, self.unshorten)
|
widgetUtils.connect_event(self.message.unshortenButton, widgetUtils.BUTTON_PRESSED, self.unshorten)
|
||||||
widgetUtils.connect_event(self.message.translateButton, widgetUtils.BUTTON_PRESSED, self.translate)
|
widgetUtils.connect_event(self.message.translateButton, widgetUtils.BUTTON_PRESSED, self.translate)
|
||||||
if hasattr(self.message, "long_tweet"):
|
if hasattr(self.message, "long_tweet"):
|
||||||
widgetUtils.connect_event(self.message.long_tweet, widgetUtils.CHECKBOX, self.text_processor)
|
widgetUtils.connect_event(self.message.long_tweet, widgetUtils.CHECKBOX, self.text_processor)
|
||||||
if config.app["app-settings"]["remember_mention_and_longtweet"]:
|
if config.app["app-settings"]["remember_mention_and_longtweet"]:
|
||||||
self.message.long_tweet.SetValue(config.app["app-settings"]["longtweet"])
|
self.message.long_tweet.SetValue(config.app["app-settings"]["longtweet"])
|
||||||
self.attachments = []
|
self.attachments = []
|
||||||
|
|
||||||
def translate(self, event=None):
|
def translate(self, event=None):
|
||||||
dlg = translator.gui.translateDialog()
|
dlg = translator.gui.translateDialog()
|
||||||
if dlg.get_response() == widgetUtils.OK:
|
if dlg.get_response() == widgetUtils.OK:
|
||||||
text_to_translate = self.message.get_text()
|
text_to_translate = self.message.get_text()
|
||||||
dest = [x[0] for x in translator.translator.available_languages()][dlg.get("dest_lang")]
|
language_dict = translator.translator.available_languages()
|
||||||
msg = translator.translator.translate(text=text_to_translate, target=dest)
|
for k in language_dict:
|
||||||
self.message.set_text(msg)
|
if language_dict[k] == dlg.dest_lang.GetStringSelection():
|
||||||
self.text_processor()
|
dst = k
|
||||||
self.message.text_focus()
|
msg = translator.translator.translate(text=text_to_translate, target=dst)
|
||||||
output.speak(_(u"Translated"))
|
self.message.set_text(msg)
|
||||||
else:
|
self.text_processor()
|
||||||
return
|
self.message.text_focus()
|
||||||
|
output.speak(_(u"Translated"))
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
def shorten(self, event=None):
|
def shorten(self, event=None):
|
||||||
urls = utils.find_urls_in_text(self.message.get_text())
|
urls = utils.find_urls_in_text(self.message.get_text())
|
||||||
if len(urls) == 0:
|
if len(urls) == 0:
|
||||||
output.speak(_(u"There's no URL to be shortened"))
|
output.speak(_(u"There's no URL to be shortened"))
|
||||||
self.message.text_focus()
|
self.message.text_focus()
|
||||||
elif len(urls) == 1:
|
elif len(urls) == 1:
|
||||||
self.message.set_text(self.message.get_text().replace(urls[0], url_shortener.shorten(urls[0])))
|
self.message.set_text(self.message.get_text().replace(urls[0], url_shortener.shorten(urls[0])))
|
||||||
output.speak(_(u"URL shortened"))
|
output.speak(_(u"URL shortened"))
|
||||||
self.text_processor()
|
self.text_processor()
|
||||||
self.message.text_focus()
|
self.message.text_focus()
|
||||||
elif len(urls) > 1:
|
elif len(urls) > 1:
|
||||||
list_urls = urlList.urlList()
|
list_urls = urlList.urlList()
|
||||||
list_urls.populate_list(urls)
|
list_urls.populate_list(urls)
|
||||||
if list_urls.get_response() == widgetUtils.OK:
|
if list_urls.get_response() == widgetUtils.OK:
|
||||||
self.message.set_text(self.message.get_text().replace(urls[list_urls.get_item()], url_shortener.shorten(list_urls.get_string())))
|
self.message.set_text(self.message.get_text().replace(urls[list_urls.get_item()], url_shortener.shorten(list_urls.get_string())))
|
||||||
output.speak(_(u"URL shortened"))
|
output.speak(_(u"URL shortened"))
|
||||||
self.text_processor()
|
self.text_processor()
|
||||||
self.message.text_focus()
|
self.message.text_focus()
|
||||||
|
|
||||||
def unshorten(self, event=None):
|
def unshorten(self, event=None):
|
||||||
urls = utils.find_urls_in_text(self.message.get_text())
|
urls = utils.find_urls_in_text(self.message.get_text())
|
||||||
if len(urls) == 0:
|
if len(urls) == 0:
|
||||||
output.speak(_(u"There's no URL to be expanded"))
|
output.speak(_(u"There's no URL to be expanded"))
|
||||||
self.message.text_focus()
|
self.message.text_focus()
|
||||||
elif len(urls) == 1:
|
elif len(urls) == 1:
|
||||||
self.message.set_text(self.message.get_text().replace(urls[0], url_shortener.unshorten(urls[0])))
|
self.message.set_text(self.message.get_text().replace(urls[0], url_shortener.unshorten(urls[0])))
|
||||||
output.speak(_(u"URL expanded"))
|
output.speak(_(u"URL expanded"))
|
||||||
self.text_processor()
|
self.text_processor()
|
||||||
self.message.text_focus()
|
self.message.text_focus()
|
||||||
elif len(urls) > 1:
|
elif len(urls) > 1:
|
||||||
list_urls = urlList.urlList()
|
list_urls = urlList.urlList()
|
||||||
list_urls.populate_list(urls)
|
list_urls.populate_list(urls)
|
||||||
if list_urls.get_response() == widgetUtils.OK:
|
if list_urls.get_response() == widgetUtils.OK:
|
||||||
self.message.set_text(self.message.get_text().replace(urls[list_urls.get_item()], url_shortener.unshorten(list_urls.get_string())))
|
self.message.set_text(self.message.get_text().replace(urls[list_urls.get_item()], url_shortener.unshorten(list_urls.get_string())))
|
||||||
output.speak(_(u"URL expanded"))
|
output.speak(_(u"URL expanded"))
|
||||||
self.text_processor()
|
self.text_processor()
|
||||||
self.message.text_focus()
|
self.message.text_focus()
|
||||||
|
|
||||||
def text_processor(self, *args, **kwargs):
|
def text_processor(self, *args, **kwargs):
|
||||||
if len(self.message.get_text()) > 1:
|
if len(self.message.get_text()) > 1:
|
||||||
self.message.enable_button("shortenButton")
|
self.message.enable_button("shortenButton")
|
||||||
self.message.enable_button("unshortenButton")
|
self.message.enable_button("unshortenButton")
|
||||||
else:
|
else:
|
||||||
self.message.disable_button("shortenButton")
|
self.message.disable_button("shortenButton")
|
||||||
self.message.disable_button("unshortenButton")
|
self.message.disable_button("unshortenButton")
|
||||||
if self.message.get("long_tweet") == False:
|
if self.message.get("long_tweet") == False:
|
||||||
self.message.set_title(_(u"%s - %s of %d characters") % (self.title, len(self.message.get_text()), self.max))
|
text = self.message.get_text()
|
||||||
if len(self.message.get_text()) > self.max:
|
results = parse_tweet(text)
|
||||||
self.session.sound.play("max_length.ogg")
|
self.message.set_title(_(u"%s - %s of %d characters") % (self.title, results.weightedLength, self.max))
|
||||||
else:
|
if results.weightedLength > self.max:
|
||||||
self.message.set_title(_(u"%s - %s characters") % (self.title, len(self.message.get_text())))
|
self.session.sound.play("max_length.ogg")
|
||||||
|
else:
|
||||||
|
self.message.set_title(_(u"%s - %s characters") % (self.title, len(self.message.get_text())))
|
||||||
|
|
||||||
def spellcheck(self, event=None):
|
def spellcheck(self, event=None):
|
||||||
text = self.message.get_text()
|
text = self.message.get_text()
|
||||||
checker = SpellChecker.spellchecker.spellChecker(text, "")
|
checker = SpellChecker.spellchecker.spellChecker(text, "")
|
||||||
if hasattr(checker, "fixed_text"):
|
if hasattr(checker, "fixed_text"):
|
||||||
self.message.set_text(checker.fixed_text)
|
self.message.set_text(checker.fixed_text)
|
||||||
self.text_processor()
|
self.text_processor()
|
||||||
self.message.text_focus()
|
self.message.text_focus()
|
||||||
|
|
||||||
def attach(self, *args, **kwargs):
|
def attach(self, *args, **kwargs):
|
||||||
def completed_callback(dlg):
|
def completed_callback(dlg):
|
||||||
url = dlg.uploaderFunction.get_url()
|
url = dlg.uploaderFunction.get_url()
|
||||||
pub.unsubscribe(dlg.uploaderDialog.update, "uploading")
|
pub.unsubscribe(dlg.uploaderDialog.update, "uploading")
|
||||||
dlg.uploaderDialog.destroy()
|
dlg.uploaderDialog.destroy()
|
||||||
if "sndup.net/" in url:
|
if "sndup.net/" in url:
|
||||||
self.message.set_text(self.message.get_text()+url+" #audio")
|
self.message.set_text(self.message.get_text()+url+" #audio")
|
||||||
self.text_processor()
|
self.text_processor()
|
||||||
else:
|
else:
|
||||||
commonMessageDialogs.common_error(url)
|
commonMessageDialogs.common_error(url)
|
||||||
|
|
||||||
dlg.cleanup()
|
dlg.cleanup()
|
||||||
dlg = audioUploader.audioUploader(self.session.settings, completed_callback)
|
dlg = audioUploader.audioUploader(self.session.settings, completed_callback)
|
||||||
self.message.text_focus()
|
self.message.text_focus()
|
||||||
|
|
||||||
class tweet(basicTweet):
|
class tweet(basicTweet):
|
||||||
def __init__(self, session, title, caption, text, max=280, messageType="tweet", *args, **kwargs):
|
def __init__(self, session, title, caption, text, max=280, messageType="tweet", *args, **kwargs):
|
||||||
super(tweet, self).__init__(session, title, caption, text, messageType, max, *args, **kwargs)
|
super(tweet, self).__init__(session, title, caption, text, messageType, max, *args, **kwargs)
|
||||||
self.image = None
|
self.image = None
|
||||||
widgetUtils.connect_event(self.message.upload_image, widgetUtils.BUTTON_PRESSED, self.upload_image)
|
widgetUtils.connect_event(self.message.upload_image, widgetUtils.BUTTON_PRESSED, self.upload_image)
|
||||||
widgetUtils.connect_event(self.message.autocompletionButton, widgetUtils.BUTTON_PRESSED, self.autocomplete_users)
|
widgetUtils.connect_event(self.message.autocompletionButton, widgetUtils.BUTTON_PRESSED, self.autocomplete_users)
|
||||||
self.text_processor()
|
self.text_processor()
|
||||||
|
|
||||||
def upload_image(self, *args, **kwargs):
|
def upload_image(self, *args, **kwargs):
|
||||||
a = attach.attach()
|
a = attach.attach()
|
||||||
if len(a.attachments) != 0:
|
if len(a.attachments) != 0:
|
||||||
self.attachments = a.attachments
|
self.attachments = a.attachments
|
||||||
|
|
||||||
def autocomplete_users(self, *args, **kwargs):
|
def autocomplete_users(self, *args, **kwargs):
|
||||||
c = autocompletionUsers.completion.autocompletionUsers(self.message, self.session.session_id)
|
c = autocompletionUsers.completion.autocompletionUsers(self.message, self.session.session_id)
|
||||||
c.show_menu()
|
c.show_menu()
|
||||||
|
|
||||||
class reply(tweet):
|
class reply(tweet):
|
||||||
def __init__(self, session, title, caption, text, users=[], ids=[]):
|
def __init__(self, session, title, caption, text, users=[], ids=[]):
|
||||||
super(reply, self).__init__(session, title, caption, text, messageType="reply", users=users)
|
super(reply, self).__init__(session, title, caption, text, messageType="reply", users=users)
|
||||||
self.ids = ids
|
self.ids = ids
|
||||||
self.users = users
|
self.users = users
|
||||||
if len(users) > 0:
|
if len(users) > 0:
|
||||||
widgetUtils.connect_event(self.message.mentionAll, widgetUtils.CHECKBOX, self.mention_all)
|
widgetUtils.connect_event(self.message.mentionAll, widgetUtils.CHECKBOX, self.mention_all)
|
||||||
self.message.enable_button("mentionAll")
|
self.message.enable_button("mentionAll")
|
||||||
if config.app["app-settings"]["remember_mention_and_longtweet"]:
|
if config.app["app-settings"]["remember_mention_and_longtweet"]:
|
||||||
self.message.mentionAll.SetValue(config.app["app-settings"]["mention_all"])
|
self.message.mentionAll.SetValue(config.app["app-settings"]["mention_all"])
|
||||||
self.mention_all()
|
self.mention_all()
|
||||||
self.message.set_cursor_at_end()
|
self.message.set_cursor_at_end()
|
||||||
self.text_processor()
|
self.text_processor()
|
||||||
|
|
||||||
def mention_all(self, *args, **kwargs):
|
def mention_all(self, *args, **kwargs):
|
||||||
if self.message.mentionAll.GetValue() == True:
|
if self.message.mentionAll.GetValue() == True:
|
||||||
for i in self.message.checkboxes:
|
for i in self.message.checkboxes:
|
||||||
i.SetValue(True)
|
i.SetValue(True)
|
||||||
i.Hide()
|
i.Hide()
|
||||||
else:
|
else:
|
||||||
for i in self.message.checkboxes:
|
for i in self.message.checkboxes:
|
||||||
i.SetValue(False)
|
i.SetValue(False)
|
||||||
i.Show()
|
i.Show()
|
||||||
|
|
||||||
def get_ids(self):
|
def get_ids(self):
|
||||||
excluded_ids = ""
|
excluded_ids = ""
|
||||||
for i in range(0, len(self.message.checkboxes)):
|
for i in range(0, len(self.message.checkboxes)):
|
||||||
if self.message.checkboxes[i].GetValue() == False:
|
if self.message.checkboxes[i].GetValue() == False:
|
||||||
excluded_ids = excluded_ids + "{0},".format(self.ids[i],)
|
excluded_ids = excluded_ids + "{0},".format(self.ids[i],)
|
||||||
return excluded_ids
|
return excluded_ids
|
||||||
|
|
||||||
def get_people(self):
|
def get_people(self):
|
||||||
people = ""
|
people = ""
|
||||||
for i in range(0, len(self.message.checkboxes)):
|
for i in range(0, len(self.message.checkboxes)):
|
||||||
if self.message.checkboxes[i].GetValue() == True:
|
if self.message.checkboxes[i].GetValue() == True:
|
||||||
people = people + "{0} ".format(self.message.checkboxes[i].GetLabel(),)
|
people = people + "{0} ".format(self.message.checkboxes[i].GetLabel(),)
|
||||||
return people
|
return people
|
||||||
|
|
||||||
class dm(basicTweet):
|
class dm(basicTweet):
|
||||||
def __init__(self, session, title, caption, text):
|
def __init__(self, session, title, caption, text):
|
||||||
super(dm, self).__init__(session, title, caption, text, messageType="dm", max=10000)
|
super(dm, self).__init__(session, title, caption, text, messageType="dm", max=10000)
|
||||||
widgetUtils.connect_event(self.message.autocompletionButton, widgetUtils.BUTTON_PRESSED, self.autocomplete_users)
|
widgetUtils.connect_event(self.message.autocompletionButton, widgetUtils.BUTTON_PRESSED, self.autocomplete_users)
|
||||||
self.text_processor()
|
self.text_processor()
|
||||||
|
widgetUtils.connect_event(self.message.cb, widgetUtils.ENTERED_TEXT, self.user_changed)
|
||||||
|
|
||||||
def autocomplete_users(self, *args, **kwargs):
|
def user_changed(self, *args, **kwargs):
|
||||||
c = autocompletionUsers.completion.autocompletionUsers(self.message, self.session.session_id)
|
self.title = _("Direct message to %s") % (self.message.get_user())
|
||||||
c.show_menu("dm")
|
self.text_processor()
|
||||||
|
|
||||||
|
def autocomplete_users(self, *args, **kwargs):
|
||||||
|
c = autocompletionUsers.completion.autocompletionUsers(self.message, self.session.session_id)
|
||||||
|
c.show_menu("dm")
|
||||||
|
|
||||||
class viewTweet(basicTweet):
|
class viewTweet(basicTweet):
|
||||||
def __init__(self, tweet, tweetList, is_tweet=True, utc_offset=0, date=""):
|
def __init__(self, tweet, tweetList, is_tweet=True, utc_offset=0, date=""):
|
||||||
""" This represents a tweet displayer. However it could be used for showing something wich is not a tweet, like a direct message or an event.
|
""" This represents a tweet displayer. However it could be used for showing something wich is not a tweet, like a direct message or an event.
|
||||||
param tweet: A dictionary that represents a full tweet or a string for non-tweets.
|
param tweet: A dictionary that represents a full tweet or a string for non-tweets.
|
||||||
param tweetList: If is_tweet is set to True, this could be a list of quoted tweets.
|
param tweetList: If is_tweet is set to True, this could be a list of quoted tweets.
|
||||||
param is_tweet: True or false, depending wether the passed object is a tweet or not."""
|
param is_tweet: True or false, depending wether the passed object is a tweet or not."""
|
||||||
if is_tweet == True:
|
if is_tweet == True:
|
||||||
self.title = _(u"Tweet")
|
self.title = _(u"Tweet")
|
||||||
image_description = []
|
image_description = []
|
||||||
text = ""
|
text = ""
|
||||||
for i in range(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.
|
# tweets with message keys are longer tweets, the message value is the full messaje taken from twishort.
|
||||||
if "message" in tweetList[i] and tweetList[i]["is_quote_status"] == False:
|
if hasattr(tweetList[i], "message") and tweetList[i].is_quote_status == False:
|
||||||
value = "message"
|
value = "message"
|
||||||
else:
|
else:
|
||||||
value = "full_text"
|
value = "full_text"
|
||||||
if "retweeted_status" in tweetList[i] and tweetList[i]["is_quote_status"] == False:
|
if hasattr(tweetList[i], "retweeted_status") and tweetList[i].is_quote_status == False:
|
||||||
if ("message" in tweetList[i]) == False:
|
if not hasattr(tweetList[i], "message"):
|
||||||
text = text + "rt @%s: %s\n" % (tweetList[i]["retweeted_status"]["user"]["screen_name"], tweetList[i]["retweeted_status"]["full_text"])
|
text = text + "rt @%s: %s\n" % (tweetList[i].retweeted_status.user.screen_name, tweetList[i].retweeted_status.full_text)
|
||||||
else:
|
else:
|
||||||
text = text + "rt @%s: %s\n" % (tweetList[i]["retweeted_status"]["user"]["screen_name"], tweetList[i][value])
|
text = text + "rt @%s: %s\n" % (tweetList[i].retweeted_status.user.screen_name, getattr(tweetList[i], value))
|
||||||
else:
|
else:
|
||||||
text = text + " @%s: %s\n" % (tweetList[i]["user"]["screen_name"], tweetList[i][value])
|
text = text + " @%s: %s\n" % (tweetList[i].user.screen_name, getattr(tweetList[i], value))
|
||||||
# tweets with extended_entities could include image descriptions.
|
# tweets with extended_entities could include image descriptions.
|
||||||
if "extended_entities" in tweetList[i] and "media" in tweetList[i]["extended_entities"]:
|
if hasattr(tweetList[i], "extended_entities") and "media" in tweetList[i].extended_entities:
|
||||||
for z in tweetList[i]["extended_entities"]["media"]:
|
for z in tweetList[i].extended_entities["media"]:
|
||||||
if "ext_alt_text" in z 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"])
|
image_description.append(z["ext_alt_text"])
|
||||||
if "retweeted_status" in tweetList[i] and "extended_entities" in tweetList[i]["retweeted_status"] and "media" in tweetList[i]["retweeted_status"]["extended_entities"]:
|
if hasattr(tweetList[i], "retweeted_status") and hasattr(tweetList[i].retweeted_status, "extended_entities") and "media" in tweetList[i].retweeted_status["extended_entities"]:
|
||||||
for z in tweetList[i]["retweeted_status"]["extended_entities"]["media"]:
|
for z in tweetList[i].retweeted_status.extended_entities["media"]:
|
||||||
if "ext_alt_text" in z 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"])
|
image_description.append(z["ext_alt_text"])
|
||||||
# set rt and likes counters.
|
# set rt and likes counters.
|
||||||
rt_count = str(tweet["retweet_count"])
|
rt_count = str(tweet.retweet_count)
|
||||||
favs_count = str(tweet["favorite_count"])
|
favs_count = str(tweet.favorite_count)
|
||||||
# Gets the client from where this tweet was made.
|
# Gets the client from where this tweet was made.
|
||||||
source = re.sub(r"(?s)<.*?>", "", tweet["source"])
|
source = tweet.source
|
||||||
original_date = arrow.get(tweet["created_at"], "ddd MMM DD H:m:s Z YYYY", locale="en")
|
original_date = arrow.get(tweet.created_at, locale="en")
|
||||||
date = original_date.shift(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 text == "":
|
||||||
if "message" in tweet:
|
if hasattr(tweet, "message"):
|
||||||
value = "message"
|
value = "message"
|
||||||
else:
|
else:
|
||||||
value = "full_text"
|
value = "full_text"
|
||||||
if "retweeted_status" in tweet:
|
if hasattr(tweet, "retweeted_status"):
|
||||||
if ("message" in tweet) == False:
|
if not hasattr(tweet, "message"):
|
||||||
text = "rt @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], tweet["retweeted_status"]["full_text"])
|
text = "rt @%s: %s" % (tweet.retweeted_status.user.screen_name, tweet.retweeted_status.full_text)
|
||||||
else:
|
else:
|
||||||
text = "rt @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], tweet[value])
|
text = "rt @%s: %s" % (tweet.retweeted_status.user.screen_name, getattr(tweet, value))
|
||||||
else:
|
else:
|
||||||
text = tweet[value]
|
text = getattr(tweet, value)
|
||||||
text = self.clear_text(text)
|
text = self.clear_text(text)
|
||||||
if "extended_entities" in tweet and "media" in tweet["extended_entities"]:
|
if hasattr(tweet, "extended_entities") and "media" in tweet.extended_entities:
|
||||||
for z in tweet["extended_entities"]["media"]:
|
for z in tweet.extended_entities["media"]:
|
||||||
if "ext_alt_text" in z 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"])
|
image_description.append(z["ext_alt_text"])
|
||||||
if "retweeted_status" in tweet and "extended_entities" in tweet["retweeted_status"] and "media" in tweet["retweeted_status"]["extended_entities"]:
|
if hasattr(tweet, "retweeted_status") and hasattr(tweet.retweeted_status, "extended_entities") and "media" in tweet.retweeted_status.extended_entities:
|
||||||
for z in tweet["retweeted_status"]["extended_entities"]["media"]:
|
for z in tweet.retweeted_status.extended_entities["media"]:
|
||||||
if "ext_alt_text" in z 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"])
|
image_description.append(z["ext_alt_text"])
|
||||||
self.message = message.viewTweet(text, rt_count, favs_count, source, date)
|
self.message = message.viewTweet(text, rt_count, favs_count, source, date)
|
||||||
self.message.set_title(len(text))
|
results = parse_tweet(text)
|
||||||
[self.message.set_image_description(i) for i in image_description]
|
self.message.set_title(results.weightedLength)
|
||||||
else:
|
[self.message.set_image_description(i) for i in image_description]
|
||||||
self.title = _(u"View item")
|
else:
|
||||||
text = tweet
|
self.title = _(u"View item")
|
||||||
self.message = message.viewNonTweet(text, date)
|
text = tweet
|
||||||
widgetUtils.connect_event(self.message.spellcheck, widgetUtils.BUTTON_PRESSED, self.spellcheck)
|
self.message = message.viewNonTweet(text, date)
|
||||||
widgetUtils.connect_event(self.message.translateButton, widgetUtils.BUTTON_PRESSED, self.translate)
|
widgetUtils.connect_event(self.message.spellcheck, widgetUtils.BUTTON_PRESSED, self.spellcheck)
|
||||||
if self.contain_urls() == True:
|
widgetUtils.connect_event(self.message.translateButton, widgetUtils.BUTTON_PRESSED, self.translate)
|
||||||
self.message.enable_button("unshortenButton")
|
if self.contain_urls() == True:
|
||||||
widgetUtils.connect_event(self.message.unshortenButton, widgetUtils.BUTTON_PRESSED, self.unshorten)
|
self.message.enable_button("unshortenButton")
|
||||||
self.message.get_response()
|
widgetUtils.connect_event(self.message.unshortenButton, widgetUtils.BUTTON_PRESSED, self.unshorten)
|
||||||
|
self.message.get_response()
|
||||||
|
|
||||||
def contain_urls(self):
|
def contain_urls(self):
|
||||||
if len(utils.find_urls_in_text(self.message.get_text())) > 0:
|
if len(utils.find_urls_in_text(self.message.get_text())) > 0:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def clear_text(self, text):
|
def clear_text(self, text):
|
||||||
urls = utils.find_urls_in_text(text)
|
urls = utils.find_urls_in_text(text)
|
||||||
for i in urls:
|
for i in urls:
|
||||||
if "https://twitter.com/" in i:
|
if "https://twitter.com/" in i:
|
||||||
text = text.replace(i, "\n")
|
text = text.replace(i, "\n")
|
||||||
return text
|
return text
|
||||||
|
@@ -1,7 +1,4 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
|
||||||
from builtins import str
|
|
||||||
from builtins import object
|
|
||||||
import os
|
import os
|
||||||
import webbrowser
|
import webbrowser
|
||||||
import sound_lib
|
import sound_lib
|
||||||
@@ -24,202 +21,206 @@ from collections import OrderedDict
|
|||||||
from mysc import autostart as autostart_windows
|
from mysc import autostart as autostart_windows
|
||||||
|
|
||||||
class globalSettingsController(object):
|
class globalSettingsController(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(globalSettingsController, self).__init__()
|
super(globalSettingsController, self).__init__()
|
||||||
self.dialog = configuration.configurationDialog()
|
self.dialog = configuration.configurationDialog()
|
||||||
self.create_config()
|
self.create_config()
|
||||||
self.needs_restart = False
|
self.needs_restart = False
|
||||||
self.is_started = True
|
self.is_started = True
|
||||||
|
|
||||||
def make_kmmap(self):
|
def make_kmmap(self):
|
||||||
res={}
|
res={}
|
||||||
for i in os.listdir(os.path.join(paths.app_path(), 'keymaps')):
|
for i in os.listdir(os.path.join(paths.app_path(), 'keymaps')):
|
||||||
if ".keymap" not in i:
|
if ".keymap" not in i:
|
||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
res[i[:-7]] =i
|
res[i[:-7]] =i
|
||||||
except:
|
except:
|
||||||
log.exception("Exception while loading keymap " + i)
|
log.exception("Exception while loading keymap " + i)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def create_config(self):
|
def create_config(self):
|
||||||
self.kmmap=self.make_kmmap()
|
self.kmmap=self.make_kmmap()
|
||||||
self.langs = languageHandler.getAvailableLanguages()
|
self.langs = languageHandler.getAvailableLanguages()
|
||||||
langs = []
|
langs = []
|
||||||
[langs.append(i[1]) for i in self.langs]
|
[langs.append(i[1]) for i in self.langs]
|
||||||
self.codes = []
|
self.codes = []
|
||||||
[self.codes.append(i[0]) for i in self.langs]
|
[self.codes.append(i[0]) for i in self.langs]
|
||||||
id = self.codes.index(config.app["app-settings"]["language"])
|
id = self.codes.index(config.app["app-settings"]["language"])
|
||||||
self.kmfriendlies=[]
|
self.kmfriendlies=[]
|
||||||
self.kmnames=[]
|
self.kmnames=[]
|
||||||
for k,v in list(self.kmmap.items()):
|
for k,v in list(self.kmmap.items()):
|
||||||
self.kmfriendlies.append(k)
|
self.kmfriendlies.append(k)
|
||||||
self.kmnames.append(v)
|
self.kmnames.append(v)
|
||||||
self.kmid=self.kmnames.index(config.app['app-settings']['load_keymap'])
|
self.kmid=self.kmnames.index(config.app['app-settings']['load_keymap'])
|
||||||
self.dialog.create_general(langs,self.kmfriendlies)
|
self.dialog.create_general(langs,self.kmfriendlies)
|
||||||
self.dialog.general.language.SetSelection(id)
|
self.dialog.general.language.SetSelection(id)
|
||||||
self.dialog.general.km.SetSelection(self.kmid)
|
self.dialog.general.km.SetSelection(self.kmid)
|
||||||
if paths.mode == "installed":
|
if paths.mode == "installed":
|
||||||
self.dialog.set_value("general", "autostart", config.app["app-settings"]["autostart"])
|
self.dialog.set_value("general", "autostart", config.app["app-settings"]["autostart"])
|
||||||
else:
|
else:
|
||||||
self.dialog.general.autostart.Enable(False)
|
self.dialog.general.autostart.Enable(False)
|
||||||
self.dialog.set_value("general", "ask_at_exit", config.app["app-settings"]["ask_at_exit"])
|
self.dialog.set_value("general", "ask_at_exit", config.app["app-settings"]["ask_at_exit"])
|
||||||
self.dialog.set_value("general", "no_streaming", config.app["app-settings"]["no_streaming"])
|
self.dialog.set_value("general", "no_streaming", config.app["app-settings"]["no_streaming"])
|
||||||
self.dialog.set_value("general", "play_ready_sound", config.app["app-settings"]["play_ready_sound"])
|
self.dialog.set_value("general", "play_ready_sound", config.app["app-settings"]["play_ready_sound"])
|
||||||
self.dialog.set_value("general", "speak_ready_msg", config.app["app-settings"]["speak_ready_msg"])
|
self.dialog.set_value("general", "speak_ready_msg", config.app["app-settings"]["speak_ready_msg"])
|
||||||
self.dialog.set_value("general", "handle_longtweets", config.app["app-settings"]["handle_longtweets"])
|
self.dialog.set_value("general", "handle_longtweets", config.app["app-settings"]["handle_longtweets"])
|
||||||
self.dialog.set_value("general", "use_invisible_shorcuts", config.app["app-settings"]["use_invisible_keyboard_shorcuts"])
|
self.dialog.set_value("general", "use_invisible_shorcuts", config.app["app-settings"]["use_invisible_keyboard_shorcuts"])
|
||||||
self.dialog.set_value("general", "disable_sapi5", config.app["app-settings"]["voice_enabled"])
|
self.dialog.set_value("general", "disable_sapi5", config.app["app-settings"]["voice_enabled"])
|
||||||
self.dialog.set_value("general", "hide_gui", config.app["app-settings"]["hide_gui"])
|
self.dialog.set_value("general", "hide_gui", config.app["app-settings"]["hide_gui"])
|
||||||
self.dialog.set_value("general", "update_period", config.app["app-settings"]["update_period"])
|
self.dialog.set_value("general", "update_period", config.app["app-settings"]["update_period"])
|
||||||
self.dialog.set_value("general", "check_for_updates", config.app["app-settings"]["check_for_updates"])
|
self.dialog.set_value("general", "check_for_updates", config.app["app-settings"]["check_for_updates"])
|
||||||
self.dialog.set_value("general", "remember_mention_and_longtweet", config.app["app-settings"]["remember_mention_and_longtweet"])
|
self.dialog.set_value("general", "remember_mention_and_longtweet", config.app["app-settings"]["remember_mention_and_longtweet"])
|
||||||
proxyTypes=config.proxyTypes
|
proxyTypes = [_("System default"), _("HTTP"), _("SOCKS v4"), _("SOCKS v4 with DNS support"), _("SOCKS v5"), _("SOCKS v5 with DNS support")]
|
||||||
self.dialog.create_proxy([_(u"Direct connection")]+proxyTypes)
|
self.dialog.create_proxy(proxyTypes)
|
||||||
if config.app["proxy"]["type"] not in proxyTypes:
|
try:
|
||||||
self.dialog.proxy.type.SetSelection(0)
|
self.dialog.proxy.type.SetSelection(config.app["proxy"]["type"])
|
||||||
else:
|
except:
|
||||||
self.dialog.proxy.type.SetSelection(proxyTypes.index(config.app["proxy"]["type"])+1)
|
self.dialog.proxy.type.SetSelection(0)
|
||||||
self.dialog.set_value("proxy", "server", config.app["proxy"]["server"])
|
self.dialog.set_value("proxy", "server", config.app["proxy"]["server"])
|
||||||
self.dialog.set_value("proxy", "port", config.app["proxy"]["port"])
|
self.dialog.set_value("proxy", "port", config.app["proxy"]["port"])
|
||||||
self.dialog.set_value("proxy", "user", config.app["proxy"]["user"])
|
self.dialog.set_value("proxy", "user", config.app["proxy"]["user"])
|
||||||
self.dialog.set_value("proxy", "password", config.app["proxy"]["password"])
|
self.dialog.set_value("proxy", "password", config.app["proxy"]["password"])
|
||||||
|
|
||||||
self.dialog.realize()
|
self.dialog.realize()
|
||||||
self.response = self.dialog.get_response()
|
self.response = self.dialog.get_response()
|
||||||
|
|
||||||
def save_configuration(self):
|
def save_configuration(self):
|
||||||
if self.codes[self.dialog.general.language.GetSelection()] != config.app["app-settings"]["language"]:
|
if self.codes[self.dialog.general.language.GetSelection()] != config.app["app-settings"]["language"]:
|
||||||
config.app["app-settings"]["language"] = self.codes[self.dialog.general.language.GetSelection()]
|
config.app["app-settings"]["language"] = self.codes[self.dialog.general.language.GetSelection()]
|
||||||
languageHandler.setLanguage(config.app["app-settings"]["language"])
|
languageHandler.setLanguage(config.app["app-settings"]["language"])
|
||||||
self.needs_restart = True
|
self.needs_restart = True
|
||||||
if self.kmnames[self.dialog.general.km.GetSelection()] != config.app["app-settings"]["load_keymap"]:
|
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()]
|
config.app["app-settings"]["load_keymap"] =self.kmnames[self.dialog.general.km.GetSelection()]
|
||||||
kmFile = open(os.path.join(paths.config_path(), "keymap.keymap"), "w")
|
kmFile = open(os.path.join(paths.config_path(), "keymap.keymap"), "w")
|
||||||
kmFile.close()
|
kmFile.close()
|
||||||
self.needs_restart = True
|
self.needs_restart = True
|
||||||
if config.app["app-settings"]["autostart"] != self.dialog.get_value("general", "autostart") and paths.mode == "installed":
|
if config.app["app-settings"]["autostart"] != self.dialog.get_value("general", "autostart") and paths.mode == "installed":
|
||||||
config.app["app-settings"]["autostart"] = self.dialog.get_value("general", "autostart")
|
config.app["app-settings"]["autostart"] = self.dialog.get_value("general", "autostart")
|
||||||
autostart_windows.setAutoStart(application.name, enable=self.dialog.get_value("general", "autostart"))
|
autostart_windows.setAutoStart(application.name, enable=self.dialog.get_value("general", "autostart"))
|
||||||
if config.app["app-settings"]["use_invisible_keyboard_shorcuts"] != self.dialog.get_value("general", "use_invisible_shorcuts"):
|
if config.app["app-settings"]["use_invisible_keyboard_shorcuts"] != self.dialog.get_value("general", "use_invisible_shorcuts"):
|
||||||
config.app["app-settings"]["use_invisible_keyboard_shorcuts"] = self.dialog.get_value("general", "use_invisible_shorcuts")
|
config.app["app-settings"]["use_invisible_keyboard_shorcuts"] = self.dialog.get_value("general", "use_invisible_shorcuts")
|
||||||
pub.sendMessage("invisible-shorcuts-changed", registered=self.dialog.get_value("general", "use_invisible_shorcuts"))
|
pub.sendMessage("invisible-shorcuts-changed", registered=self.dialog.get_value("general", "use_invisible_shorcuts"))
|
||||||
if config.app["app-settings"]["no_streaming"] != self.dialog.get_value("general", "no_streaming"):
|
if config.app["app-settings"]["no_streaming"] != self.dialog.get_value("general", "no_streaming"):
|
||||||
config.app["app-settings"]["no_streaming"] = self.dialog.get_value("general", "no_streaming")
|
config.app["app-settings"]["no_streaming"] = self.dialog.get_value("general", "no_streaming")
|
||||||
self.needs_restart = True
|
self.needs_restart = True
|
||||||
if config.app["app-settings"]["update_period"] != self.dialog.get_value("general", "update_period"):
|
if config.app["app-settings"]["update_period"] != self.dialog.get_value("general", "update_period"):
|
||||||
config.app["app-settings"]["update_period"] = self.dialog.get_value("general", "update_period")
|
config.app["app-settings"]["update_period"] = self.dialog.get_value("general", "update_period")
|
||||||
self.needs_restart = True
|
self.needs_restart = True
|
||||||
config.app["app-settings"]["voice_enabled"] = self.dialog.get_value("general", "disable_sapi5")
|
config.app["app-settings"]["voice_enabled"] = self.dialog.get_value("general", "disable_sapi5")
|
||||||
config.app["app-settings"]["hide_gui"] = self.dialog.get_value("general", "hide_gui")
|
config.app["app-settings"]["hide_gui"] = self.dialog.get_value("general", "hide_gui")
|
||||||
config.app["app-settings"]["ask_at_exit"] = self.dialog.get_value("general", "ask_at_exit")
|
config.app["app-settings"]["ask_at_exit"] = self.dialog.get_value("general", "ask_at_exit")
|
||||||
config.app["app-settings"]["handle_longtweets"] = self.dialog.get_value("general", "handle_longtweets")
|
config.app["app-settings"]["handle_longtweets"] = self.dialog.get_value("general", "handle_longtweets")
|
||||||
config.app["app-settings"]["play_ready_sound"] = self.dialog.get_value("general", "play_ready_sound")
|
config.app["app-settings"]["play_ready_sound"] = self.dialog.get_value("general", "play_ready_sound")
|
||||||
config.app["app-settings"]["speak_ready_msg"] = self.dialog.get_value("general", "speak_ready_msg")
|
config.app["app-settings"]["speak_ready_msg"] = self.dialog.get_value("general", "speak_ready_msg")
|
||||||
config.app["app-settings"]["check_for_updates"] = self.dialog.get_value("general", "check_for_updates")
|
config.app["app-settings"]["check_for_updates"] = self.dialog.get_value("general", "check_for_updates")
|
||||||
config.app["app-settings"]["remember_mention_and_longtweet"] = self.dialog.get_value("general", "remember_mention_and_longtweet")
|
config.app["app-settings"]["remember_mention_and_longtweet"] = self.dialog.get_value("general", "remember_mention_and_longtweet")
|
||||||
if config.app["proxy"]["type"]!=self.dialog.get_value("proxy", "type") or config.app["proxy"]["server"] != self.dialog.get_value("proxy", "server") or config.app["proxy"]["port"] != self.dialog.get_value("proxy", "port") or config.app["proxy"]["user"] != self.dialog.get_value("proxy", "user") or config.app["proxy"]["password"] != self.dialog.get_value("proxy", "password"):
|
if config.app["proxy"]["type"]!=self.dialog.get_value("proxy", "type") or config.app["proxy"]["server"] != self.dialog.get_value("proxy", "server") or config.app["proxy"]["port"] != self.dialog.get_value("proxy", "port") or config.app["proxy"]["user"] != self.dialog.get_value("proxy", "user") or config.app["proxy"]["password"] != self.dialog.get_value("proxy", "password"):
|
||||||
if self.is_started == True:
|
if self.is_started == True:
|
||||||
self.needs_restart = True
|
self.needs_restart = True
|
||||||
config.app["proxy"]["type"]=self.dialog.get_value("proxy", "type")
|
config.app["proxy"]["type"] = self.dialog.proxy.type.Selection
|
||||||
config.app["proxy"]["server"] = self.dialog.get_value("proxy", "server")
|
config.app["proxy"]["server"] = self.dialog.get_value("proxy", "server")
|
||||||
config.app["proxy"]["port"] = self.dialog.get_value("proxy", "port")
|
config.app["proxy"]["port"] = self.dialog.get_value("proxy", "port")
|
||||||
config.app["proxy"]["user"] = self.dialog.get_value("proxy", "user")
|
config.app["proxy"]["user"] = self.dialog.get_value("proxy", "user")
|
||||||
config.app["proxy"]["password"] = self.dialog.get_value("proxy", "password")
|
config.app["proxy"]["password"] = self.dialog.get_value("proxy", "password")
|
||||||
config.app.write()
|
config.app.write()
|
||||||
|
|
||||||
class accountSettingsController(globalSettingsController):
|
class accountSettingsController(globalSettingsController):
|
||||||
def __init__(self, buffer, window):
|
def __init__(self, buffer, window):
|
||||||
self.user = buffer.session.db["user_name"]
|
self.user = buffer.session.db["user_name"]
|
||||||
self.buffer = buffer
|
self.buffer = buffer
|
||||||
self.window = window
|
self.window = window
|
||||||
self.config = buffer.session.settings
|
self.config = buffer.session.settings
|
||||||
super(accountSettingsController, self).__init__()
|
super(accountSettingsController, self).__init__()
|
||||||
|
|
||||||
def create_config(self):
|
def create_config(self):
|
||||||
self.dialog.create_general_account()
|
self.dialog.create_general_account()
|
||||||
widgetUtils.connect_event(self.dialog.general.au, widgetUtils.BUTTON_PRESSED, self.manage_autocomplete)
|
widgetUtils.connect_event(self.dialog.general.au, widgetUtils.BUTTON_PRESSED, self.manage_autocomplete)
|
||||||
self.dialog.set_value("general", "relative_time", self.config["general"]["relative_times"])
|
self.dialog.set_value("general", "relative_time", self.config["general"]["relative_times"])
|
||||||
self.dialog.set_value("general", "show_screen_names", self.config["general"]["show_screen_names"])
|
self.dialog.set_value("general", "show_screen_names", self.config["general"]["show_screen_names"])
|
||||||
self.dialog.set_value("general", "itemsPerApiCall", self.config["general"]["max_tweets_per_call"])
|
self.dialog.set_value("general", "itemsPerApiCall", self.config["general"]["max_tweets_per_call"])
|
||||||
self.dialog.set_value("general", "reverse_timelines", self.config["general"]["reverse_timelines"])
|
self.dialog.set_value("general", "reverse_timelines", self.config["general"]["reverse_timelines"])
|
||||||
rt = self.config["general"]["retweet_mode"]
|
rt = self.config["general"]["retweet_mode"]
|
||||||
if rt == "ask":
|
if rt == "ask":
|
||||||
self.dialog.set_value("general", "retweet_mode", _(u"Ask"))
|
self.dialog.set_value("general", "retweet_mode", _(u"Ask"))
|
||||||
elif rt == "direct":
|
elif rt == "direct":
|
||||||
self.dialog.set_value("general", "retweet_mode", _(u"Retweet without comments"))
|
self.dialog.set_value("general", "retweet_mode", _(u"Retweet without comments"))
|
||||||
else:
|
else:
|
||||||
self.dialog.set_value("general", "retweet_mode", _(u"Retweet with comments"))
|
self.dialog.set_value("general", "retweet_mode", _(u"Retweet with comments"))
|
||||||
self.dialog.set_value("general", "persist_size", str(self.config["general"]["persist_size"]))
|
self.dialog.set_value("general", "persist_size", str(self.config["general"]["persist_size"]))
|
||||||
self.dialog.create_reporting()
|
self.dialog.set_value("general", "load_cache_in_memory", self.config["general"]["load_cache_in_memory"])
|
||||||
self.dialog.set_value("reporting", "speech_reporting", self.config["reporting"]["speech_reporting"])
|
self.dialog.create_reporting()
|
||||||
self.dialog.set_value("reporting", "braille_reporting", self.config["reporting"]["braille_reporting"])
|
self.dialog.set_value("reporting", "speech_reporting", self.config["reporting"]["speech_reporting"])
|
||||||
self.dialog.create_other_buffers()
|
self.dialog.set_value("reporting", "braille_reporting", self.config["reporting"]["braille_reporting"])
|
||||||
buffer_values = self.get_buffers_list()
|
self.dialog.create_other_buffers()
|
||||||
self.dialog.buffers.insert_buffers(buffer_values)
|
buffer_values = self.get_buffers_list()
|
||||||
self.dialog.buffers.connect_hook_func(self.toggle_buffer_active)
|
self.dialog.buffers.insert_buffers(buffer_values)
|
||||||
widgetUtils.connect_event(self.dialog.buffers.toggle_state, widgetUtils.BUTTON_PRESSED, self.toggle_state)
|
self.dialog.buffers.connect_hook_func(self.toggle_buffer_active)
|
||||||
widgetUtils.connect_event(self.dialog.buffers.up, widgetUtils.BUTTON_PRESSED, self.dialog.buffers.move_up)
|
widgetUtils.connect_event(self.dialog.buffers.toggle_state, widgetUtils.BUTTON_PRESSED, self.toggle_state)
|
||||||
widgetUtils.connect_event(self.dialog.buffers.down, widgetUtils.BUTTON_PRESSED, self.dialog.buffers.move_down)
|
widgetUtils.connect_event(self.dialog.buffers.up, widgetUtils.BUTTON_PRESSED, self.dialog.buffers.move_up)
|
||||||
|
widgetUtils.connect_event(self.dialog.buffers.down, widgetUtils.BUTTON_PRESSED, self.dialog.buffers.move_down)
|
||||||
|
|
||||||
|
|
||||||
self.dialog.create_ignored_clients(self.config["twitter"]["ignored_clients"])
|
self.dialog.create_ignored_clients(self.config["twitter"]["ignored_clients"])
|
||||||
widgetUtils.connect_event(self.dialog.ignored_clients.add, widgetUtils.BUTTON_PRESSED, self.add_ignored_client)
|
widgetUtils.connect_event(self.dialog.ignored_clients.add, widgetUtils.BUTTON_PRESSED, self.add_ignored_client)
|
||||||
widgetUtils.connect_event(self.dialog.ignored_clients.remove, widgetUtils.BUTTON_PRESSED, self.remove_ignored_client)
|
widgetUtils.connect_event(self.dialog.ignored_clients.remove, widgetUtils.BUTTON_PRESSED, self.remove_ignored_client)
|
||||||
self.input_devices = sound_lib.input.Input.get_device_names()
|
self.input_devices = sound_lib.input.Input.get_device_names()
|
||||||
self.output_devices = sound_lib.output.Output.get_device_names()
|
self.output_devices = sound_lib.output.Output.get_device_names()
|
||||||
self.soundpacks = []
|
self.soundpacks = []
|
||||||
[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.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.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", "volumeCtrl", self.config["sound"]["volume"]*100)
|
||||||
self.dialog.set_value("sound", "input", self.config["sound"]["input_device"])
|
self.dialog.set_value("sound", "input", self.config["sound"]["input_device"])
|
||||||
self.dialog.set_value("sound", "output", self.config["sound"]["output_device"])
|
self.dialog.set_value("sound", "output", self.config["sound"]["output_device"])
|
||||||
self.dialog.set_value("sound", "session_mute", self.config["sound"]["session_mute"])
|
self.dialog.set_value("sound", "session_mute", self.config["sound"]["session_mute"])
|
||||||
self.dialog.set_value("sound", "soundpack", self.config["sound"]["current_soundpack"])
|
self.dialog.set_value("sound", "soundpack", self.config["sound"]["current_soundpack"])
|
||||||
self.dialog.set_value("sound", "indicate_audio", self.config["sound"]["indicate_audio"])
|
self.dialog.set_value("sound", "indicate_audio", self.config["sound"]["indicate_audio"])
|
||||||
self.dialog.set_value("sound", "indicate_geo", self.config["sound"]["indicate_geo"])
|
self.dialog.set_value("sound", "indicate_geo", self.config["sound"]["indicate_geo"])
|
||||||
self.dialog.set_value("sound", "indicate_img", self.config["sound"]["indicate_img"])
|
self.dialog.set_value("sound", "indicate_img", self.config["sound"]["indicate_img"])
|
||||||
self.dialog.create_extras(OCRSpace.translatable_langs)
|
self.dialog.create_extras(OCRSpace.translatable_langs)
|
||||||
self.dialog.set_value("extras", "sndup_apiKey", self.config["sound"]["sndup_api_key"])
|
self.dialog.set_value("extras", "sndup_apiKey", self.config["sound"]["sndup_api_key"])
|
||||||
language_index = OCRSpace.OcrLangs.index(self.config["mysc"]["ocr_language"])
|
language_index = OCRSpace.OcrLangs.index(self.config["mysc"]["ocr_language"])
|
||||||
self.dialog.extras.ocr_lang.SetSelection(language_index)
|
self.dialog.extras.ocr_lang.SetSelection(language_index)
|
||||||
self.dialog.realize()
|
self.dialog.realize()
|
||||||
self.dialog.set_title(_(u"Account settings for %s") % (self.user,))
|
self.dialog.set_title(_(u"Account settings for %s") % (self.user,))
|
||||||
self.response = self.dialog.get_response()
|
self.response = self.dialog.get_response()
|
||||||
|
|
||||||
def save_configuration(self):
|
def save_configuration(self):
|
||||||
if self.config["general"]["relative_times"] != self.dialog.get_value("general", "relative_time"):
|
if self.config["general"]["relative_times"] != self.dialog.get_value("general", "relative_time"):
|
||||||
self.needs_restart = True
|
self.needs_restart = True
|
||||||
self.config["general"]["relative_times"] = self.dialog.get_value("general", "relative_time")
|
self.config["general"]["relative_times"] = self.dialog.get_value("general", "relative_time")
|
||||||
self.config["general"]["show_screen_names"] = self.dialog.get_value("general", "show_screen_names")
|
self.config["general"]["show_screen_names"] = self.dialog.get_value("general", "show_screen_names")
|
||||||
self.config["general"]["max_tweets_per_call"] = self.dialog.get_value("general", "itemsPerApiCall")
|
self.config["general"]["max_tweets_per_call"] = self.dialog.get_value("general", "itemsPerApiCall")
|
||||||
if self.config["general"]["persist_size"] != self.dialog.get_value("general", "persist_size"):
|
if self.config["general"]["load_cache_in_memory"] != self.dialog.get_value("general", "load_cache_in_memory"):
|
||||||
if self.dialog.get_value("general", "persist_size") == '':
|
self.config["general"]["load_cache_in_memory"] = self.dialog.get_value("general", "load_cache_in_memory")
|
||||||
self.config["general"]["persist_size"] =-1
|
self.needs_restart = True
|
||||||
else:
|
if self.config["general"]["persist_size"] != self.dialog.get_value("general", "persist_size"):
|
||||||
try:
|
if self.dialog.get_value("general", "persist_size") == '':
|
||||||
self.config["general"]["persist_size"] = int(self.dialog.get_value("general", "persist_size"))
|
self.config["general"]["persist_size"] =-1
|
||||||
except ValueError:
|
else:
|
||||||
output.speak("Invalid cache size, setting to default.",True)
|
try:
|
||||||
self.config["general"]["persist_size"] =1764
|
self.config["general"]["persist_size"] = int(self.dialog.get_value("general", "persist_size"))
|
||||||
|
except ValueError:
|
||||||
|
output.speak("Invalid cache size, setting to default.",True)
|
||||||
|
self.config["general"]["persist_size"] =1764
|
||||||
|
|
||||||
if self.config["general"]["reverse_timelines"] != self.dialog.get_value("general", "reverse_timelines"):
|
if self.config["general"]["reverse_timelines"] != self.dialog.get_value("general", "reverse_timelines"):
|
||||||
self.needs_restart = True
|
self.needs_restart = True
|
||||||
self.config["general"]["reverse_timelines"] = self.dialog.get_value("general", "reverse_timelines")
|
self.config["general"]["reverse_timelines"] = self.dialog.get_value("general", "reverse_timelines")
|
||||||
rt = self.dialog.get_value("general", "retweet_mode")
|
rt = self.dialog.get_value("general", "retweet_mode")
|
||||||
if rt == _(u"Ask"):
|
if rt == _(u"Ask"):
|
||||||
self.config["general"]["retweet_mode"] = "ask"
|
self.config["general"]["retweet_mode"] = "ask"
|
||||||
elif rt == _(u"Retweet without comments"):
|
elif rt == _(u"Retweet without comments"):
|
||||||
self.config["general"]["retweet_mode"] = "direct"
|
self.config["general"]["retweet_mode"] = "direct"
|
||||||
else:
|
else:
|
||||||
self.config["general"]["retweet_mode"] = "comment"
|
self.config["general"]["retweet_mode"] = "comment"
|
||||||
buffers_list = self.dialog.buffers.get_list()
|
buffers_list = self.dialog.buffers.get_list()
|
||||||
if buffers_list != self.config["general"]["buffer_order"]:
|
if buffers_list != self.config["general"]["buffer_order"]:
|
||||||
self.needs_restart = True
|
self.needs_restart = True
|
||||||
self.config["general"]["buffer_order"] = buffers_list
|
self.config["general"]["buffer_order"] = buffers_list
|
||||||
self.config["reporting"]["speech_reporting"] = self.dialog.get_value("reporting", "speech_reporting")
|
self.config["reporting"]["speech_reporting"] = self.dialog.get_value("reporting", "speech_reporting")
|
||||||
self.config["reporting"]["braille_reporting"] = self.dialog.get_value("reporting", "braille_reporting")
|
self.config["reporting"]["braille_reporting"] = self.dialog.get_value("reporting", "braille_reporting")
|
||||||
self.config["mysc"]["ocr_language"] = OCRSpace.OcrLangs[self.dialog.extras.ocr_lang.GetSelection()]
|
self.config["mysc"]["ocr_language"] = OCRSpace.OcrLangs[self.dialog.extras.ocr_lang.GetSelection()]
|
||||||
# if self.config["other_buffers"]["show_followers"] != self.dialog.get_value("buffers", "followers"):
|
# if self.config["other_buffers"]["show_followers"] != self.dialog.get_value("buffers", "followers"):
|
||||||
# self.config["other_buffers"]["show_followers"] = self.dialog.get_value("buffers", "followers")
|
# self.config["other_buffers"]["show_followers"] = self.dialog.get_value("buffers", "followers")
|
||||||
# pub.sendMessage("create-new-buffer", buffer="followers", account=self.user, create=self.config["other_buffers"]["show_followers"])
|
# pub.sendMessage("create-new-buffer", buffer="followers", account=self.user, create=self.config["other_buffers"]["show_followers"])
|
||||||
@@ -238,75 +239,75 @@ class accountSettingsController(globalSettingsController):
|
|||||||
# if self.config["other_buffers"]["show_events"] != self.dialog.get_value("buffers", "events"):
|
# if self.config["other_buffers"]["show_events"] != self.dialog.get_value("buffers", "events"):
|
||||||
# self.config["other_buffers"]["show_events"] = self.dialog.get_value("buffers", "events")
|
# self.config["other_buffers"]["show_events"] = self.dialog.get_value("buffers", "events")
|
||||||
# pub.sendMessage("create-new-buffer", buffer="events", account=self.user, create=self.config["other_buffers"]["show_events"])
|
# pub.sendMessage("create-new-buffer", buffer="events", account=self.user, create=self.config["other_buffers"]["show_events"])
|
||||||
if self.config["sound"]["input_device"] != self.dialog.sound.get("input"):
|
if self.config["sound"]["input_device"] != self.dialog.sound.get("input"):
|
||||||
self.config["sound"]["input_device"] = self.dialog.sound.get("input")
|
self.config["sound"]["input_device"] = self.dialog.sound.get("input")
|
||||||
try:
|
try:
|
||||||
self.buffer.session.sound.input.set_device(self.buffer.session.sound.input.find_device_by_name(self.config["sound"]["input_device"]))
|
self.buffer.session.sound.input.set_device(self.buffer.session.sound.input.find_device_by_name(self.config["sound"]["input_device"]))
|
||||||
except:
|
except:
|
||||||
self.config["sound"]["input_device"] = "default"
|
self.config["sound"]["input_device"] = "default"
|
||||||
if self.config["sound"]["output_device"] != self.dialog.sound.get("output"):
|
if self.config["sound"]["output_device"] != self.dialog.sound.get("output"):
|
||||||
self.config["sound"]["output_device"] = self.dialog.sound.get("output")
|
self.config["sound"]["output_device"] = self.dialog.sound.get("output")
|
||||||
try:
|
try:
|
||||||
self.buffer.session.sound.output.set_device(self.buffer.session.sound.output.find_device_by_name(self.config["sound"]["output_device"]))
|
self.buffer.session.sound.output.set_device(self.buffer.session.sound.output.find_device_by_name(self.config["sound"]["output_device"]))
|
||||||
except:
|
except:
|
||||||
self.config["sound"]["output_device"] = "default"
|
self.config["sound"]["output_device"] = "default"
|
||||||
self.config["sound"]["volume"] = self.dialog.get_value("sound", "volumeCtrl")/100.0
|
self.config["sound"]["volume"] = self.dialog.get_value("sound", "volumeCtrl")/100.0
|
||||||
self.config["sound"]["session_mute"] = self.dialog.get_value("sound", "session_mute")
|
self.config["sound"]["session_mute"] = self.dialog.get_value("sound", "session_mute")
|
||||||
self.config["sound"]["current_soundpack"] = self.dialog.sound.get("soundpack")
|
self.config["sound"]["current_soundpack"] = self.dialog.sound.get("soundpack")
|
||||||
self.config["sound"]["indicate_audio"] = self.dialog.get_value("sound", "indicate_audio")
|
self.config["sound"]["indicate_audio"] = self.dialog.get_value("sound", "indicate_audio")
|
||||||
self.config["sound"]["indicate_geo"] = self.dialog.get_value("sound", "indicate_geo")
|
self.config["sound"]["indicate_geo"] = self.dialog.get_value("sound", "indicate_geo")
|
||||||
self.config["sound"]["indicate_img"] = self.dialog.get_value("sound", "indicate_img")
|
self.config["sound"]["indicate_img"] = self.dialog.get_value("sound", "indicate_img")
|
||||||
self.config["sound"]["sndup_api_key"] = self.dialog.get_value("extras", "sndup_apiKey")
|
self.config["sound"]["sndup_api_key"] = self.dialog.get_value("extras", "sndup_apiKey")
|
||||||
self.buffer.session.sound.config = self.config["sound"]
|
self.buffer.session.sound.config = self.config["sound"]
|
||||||
self.buffer.session.sound.check_soundpack()
|
self.buffer.session.sound.check_soundpack()
|
||||||
self.config.write()
|
self.config.write()
|
||||||
|
|
||||||
def toggle_state(self,*args,**kwargs):
|
def toggle_state(self,*args,**kwargs):
|
||||||
return self.dialog.buffers.change_selected_item()
|
return self.dialog.buffers.change_selected_item()
|
||||||
|
|
||||||
def manage_autocomplete(self, *args, **kwargs):
|
def manage_autocomplete(self, *args, **kwargs):
|
||||||
configuration = settings.autocompletionSettings(self.buffer.session.settings, self.buffer, self.window)
|
configuration = settings.autocompletionSettings(self.buffer.session.settings, self.buffer, self.window)
|
||||||
|
|
||||||
def add_ignored_client(self, *args, **kwargs):
|
def add_ignored_client(self, *args, **kwargs):
|
||||||
client = commonMessageDialogs.get_ignored_client()
|
client = commonMessageDialogs.get_ignored_client()
|
||||||
if client == None: return
|
if client == None: return
|
||||||
if client not in self.config["twitter"]["ignored_clients"]:
|
if client not in self.config["twitter"]["ignored_clients"]:
|
||||||
self.config["twitter"]["ignored_clients"].append(client)
|
self.config["twitter"]["ignored_clients"].append(client)
|
||||||
self.dialog.ignored_clients.append(client)
|
self.dialog.ignored_clients.append(client)
|
||||||
|
|
||||||
def remove_ignored_client(self, *args, **kwargs):
|
def remove_ignored_client(self, *args, **kwargs):
|
||||||
if self.dialog.ignored_clients.get_clients() == 0: return
|
if self.dialog.ignored_clients.get_clients() == 0: return
|
||||||
id = self.dialog.ignored_clients.get_client_id()
|
id = self.dialog.ignored_clients.get_client_id()
|
||||||
self.config["twitter"]["ignored_clients"].pop(id)
|
self.config["twitter"]["ignored_clients"].pop(id)
|
||||||
self.dialog.ignored_clients.remove_(id)
|
self.dialog.ignored_clients.remove_(id)
|
||||||
|
|
||||||
def get_buffers_list(self):
|
def get_buffers_list(self):
|
||||||
all_buffers=OrderedDict()
|
all_buffers=OrderedDict()
|
||||||
all_buffers['home']=_(u"Home")
|
all_buffers['home']=_(u"Home")
|
||||||
all_buffers['mentions']=_(u"Mentions")
|
all_buffers['mentions']=_(u"Mentions")
|
||||||
all_buffers['dm']=_(u"Direct Messages")
|
all_buffers['dm']=_(u"Direct Messages")
|
||||||
all_buffers['sent_dm']=_(u"Sent direct messages")
|
all_buffers['sent_dm']=_(u"Sent direct messages")
|
||||||
all_buffers['sent_tweets']=_(u"Sent tweets")
|
all_buffers['sent_tweets']=_(u"Sent tweets")
|
||||||
all_buffers['favorites']=_(u"Likes")
|
all_buffers['favorites']=_(u"Likes")
|
||||||
all_buffers['followers']=_(u"Followers")
|
all_buffers['followers']=_(u"Followers")
|
||||||
all_buffers['friends']=_(u"Friends")
|
all_buffers['friends']=_(u"Friends")
|
||||||
all_buffers['blocks']=_(u"Blocked users")
|
all_buffers['blocks']=_(u"Blocked users")
|
||||||
all_buffers['muted']=_(u"Muted users")
|
all_buffers['muted']=_(u"Muted users")
|
||||||
list_buffers = []
|
list_buffers = []
|
||||||
hidden_buffers=[]
|
hidden_buffers=[]
|
||||||
all_buffers_keys = list(all_buffers.keys())
|
all_buffers_keys = list(all_buffers.keys())
|
||||||
# Check buffers shown first.
|
# Check buffers shown first.
|
||||||
for i in self.config["general"]["buffer_order"]:
|
for i in self.config["general"]["buffer_order"]:
|
||||||
if i in all_buffers_keys:
|
if i in all_buffers_keys:
|
||||||
list_buffers.append((i, all_buffers[i], True))
|
list_buffers.append((i, all_buffers[i], True))
|
||||||
# This second pass will retrieve all hidden buffers.
|
# This second pass will retrieve all hidden buffers.
|
||||||
for i in all_buffers_keys:
|
for i in all_buffers_keys:
|
||||||
if i not in self.config["general"]["buffer_order"]:
|
if i not in self.config["general"]["buffer_order"]:
|
||||||
hidden_buffers.append((i, all_buffers[i], False))
|
hidden_buffers.append((i, all_buffers[i], False))
|
||||||
list_buffers.extend(hidden_buffers)
|
list_buffers.extend(hidden_buffers)
|
||||||
return list_buffers
|
return list_buffers
|
||||||
|
|
||||||
def toggle_buffer_active(self, ev):
|
def toggle_buffer_active(self, ev):
|
||||||
change = self.dialog.buffers.get_event(ev)
|
change = self.dialog.buffers.get_event(ev)
|
||||||
if change == True:
|
if change == True:
|
||||||
self.dialog.buffers.change_selected_item()
|
self.dialog.buffers.change_selected_item()
|
||||||
|
@@ -1,47 +1,45 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
|
||||||
from builtins import object
|
|
||||||
from wxUI.dialogs import trends
|
from wxUI.dialogs import trends
|
||||||
import widgetUtils
|
import widgetUtils
|
||||||
|
|
||||||
class trendingTopicsController(object):
|
class trendingTopicsController(object):
|
||||||
def __init__(self, session):
|
def __init__(self, session):
|
||||||
super(trendingTopicsController, self).__init__()
|
super(trendingTopicsController, self).__init__()
|
||||||
self.countries = {}
|
self.countries = {}
|
||||||
self.cities = {}
|
self.cities = {}
|
||||||
self.dialog = trends.trendingTopicsDialog()
|
self.dialog = trends.trendingTopicsDialog()
|
||||||
self.information = session.twitter.get_available_trends()
|
self.information = session.twitter.trends_available()
|
||||||
self.split_information()
|
self.split_information()
|
||||||
widgetUtils.connect_event(self.dialog.country, widgetUtils.RADIOBUTTON, self.get_places)
|
widgetUtils.connect_event(self.dialog.country, widgetUtils.RADIOBUTTON, self.get_places)
|
||||||
widgetUtils.connect_event(self.dialog.city, widgetUtils.RADIOBUTTON, self.get_places)
|
widgetUtils.connect_event(self.dialog.city, widgetUtils.RADIOBUTTON, self.get_places)
|
||||||
self.get_places()
|
self.get_places()
|
||||||
|
|
||||||
def split_information(self):
|
def split_information(self):
|
||||||
for i in self.information:
|
for i in self.information:
|
||||||
if i["placeType"]["name"] == "Country":
|
if i["placeType"]["name"] == "Country":
|
||||||
self.countries[i["name"]] = i["woeid"]
|
self.countries[i["name"]] = i["woeid"]
|
||||||
else:
|
else:
|
||||||
self.cities[i["name"]] = i["woeid"]
|
self.cities[i["name"]] = i["woeid"]
|
||||||
|
|
||||||
def get_places(self, event=None):
|
def get_places(self, event=None):
|
||||||
values = []
|
values = []
|
||||||
if self.dialog.get_active() == "country":
|
if self.dialog.get_active() == "country":
|
||||||
for i in self.information:
|
for i in self.information:
|
||||||
if i["placeType"]["name"] == "Country":
|
if i["placeType"]["name"] == "Country":
|
||||||
values.append(i["name"])
|
values.append(i["name"])
|
||||||
elif self.dialog.get_active() == "city":
|
elif self.dialog.get_active() == "city":
|
||||||
for i in self.information:
|
for i in self.information:
|
||||||
if i["placeType"]["name"] != "Country":
|
if i["placeType"]["name"] != "Country":
|
||||||
values.append(i["name"])
|
values.append(i["name"])
|
||||||
self.dialog.set(values)
|
self.dialog.set(values)
|
||||||
|
|
||||||
def get_woeid(self):
|
def get_woeid(self):
|
||||||
selected = self.dialog.get_item()
|
selected = self.dialog.get_item()
|
||||||
if self.dialog.get_active() == "country":
|
if self.dialog.get_active() == "country":
|
||||||
woeid = self.countries[selected]
|
woeid = self.countries[selected]
|
||||||
else:
|
else:
|
||||||
woeid = self.cities[selected]
|
woeid = self.cities[selected]
|
||||||
return woeid
|
return woeid
|
||||||
|
|
||||||
def get_string(self):
|
def get_string(self):
|
||||||
return self.dialog.get_item()
|
return self.dialog.get_item()
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
|
||||||
from builtins import object
|
|
||||||
import wx
|
import wx
|
||||||
import webbrowser
|
import webbrowser
|
||||||
import widgetUtils
|
import widgetUtils
|
||||||
@@ -8,121 +6,123 @@ import output
|
|||||||
from wxUI.dialogs import update_profile, show_user
|
from wxUI.dialogs import update_profile, show_user
|
||||||
import logging
|
import logging
|
||||||
log = logging.getLogger("controller.user")
|
log = logging.getLogger("controller.user")
|
||||||
from twython import TwythonError
|
from tweepy.error import TweepError
|
||||||
|
from sessions.twitter import utils
|
||||||
|
|
||||||
class profileController(object):
|
class profileController(object):
|
||||||
def __init__(self, session, user=None):
|
def __init__(self, session, user=None):
|
||||||
super(profileController, self).__init__()
|
super(profileController, self).__init__()
|
||||||
self.file = None
|
self.file = None
|
||||||
self.session = session
|
self.session = session
|
||||||
self.user = user
|
self.user = user
|
||||||
if user == None:
|
if user == None:
|
||||||
self.get_data(screen_name=self.session.db["user_name"])
|
self.get_data(screen_name=self.session.db["user_name"])
|
||||||
self.dialog = update_profile.updateProfileDialog()
|
self.dialog = update_profile.updateProfileDialog()
|
||||||
self.fill_profile_fields()
|
self.fill_profile_fields()
|
||||||
self.uploaded = False
|
self.uploaded = False
|
||||||
widgetUtils.connect_event(self.dialog.upload_image, widgetUtils.BUTTON_PRESSED, self.upload_image)
|
widgetUtils.connect_event(self.dialog.upload_image, widgetUtils.BUTTON_PRESSED, self.upload_image)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
self.get_data(screen_name=self.user)
|
self.get_data(screen_name=self.user)
|
||||||
except TwythonError as err:
|
except TweepError as err:
|
||||||
if err.error_code == 404:
|
if err.api_code == 50:
|
||||||
wx.MessageDialog(None, _(u"That user does not exist"), _(u"Error"), wx.ICON_ERROR).ShowModal()
|
wx.MessageDialog(None, _(u"That user does not exist"), _(u"Error"), wx.ICON_ERROR).ShowModal()
|
||||||
if err.error_code == 403:
|
if err.api_code == 403:
|
||||||
wx.MessageDialog(None, _(u"User has been suspended"), _(u"Error"), wx.ICON_ERROR).ShowModal()
|
wx.MessageDialog(None, _(u"User has been suspended"), _(u"Error"), wx.ICON_ERROR).ShowModal()
|
||||||
log.error("error %d: %s" % (err.error_code, err.msg))
|
log.error("error %d: %s" % (err.api_code, err.reason))
|
||||||
return
|
return
|
||||||
self.dialog = show_user.showUserProfile()
|
self.dialog = show_user.showUserProfile()
|
||||||
string = self.get_user_info()
|
string = self.get_user_info()
|
||||||
self.dialog.set("text", string)
|
self.dialog.set("text", string)
|
||||||
self.dialog.set_title(_(u"Information for %s") % (self.data["screen_name"]))
|
self.dialog.set_title(_(u"Information for %s") % (self.data.screen_name))
|
||||||
if self.data["url"] != None:
|
if self.data.url != None:
|
||||||
self.dialog.enable_url()
|
self.dialog.enable_url()
|
||||||
widgetUtils.connect_event(self.dialog.url, widgetUtils.BUTTON_PRESSED, self.visit_url)
|
widgetUtils.connect_event(self.dialog.url, widgetUtils.BUTTON_PRESSED, self.visit_url)
|
||||||
if self.dialog.get_response() == widgetUtils.OK and self.user == None:
|
if self.dialog.get_response() == widgetUtils.OK and self.user == None:
|
||||||
self.do_update()
|
self.do_update()
|
||||||
|
|
||||||
def get_data(self, screen_name):
|
def get_data(self, screen_name):
|
||||||
self.data = self.session.twitter.show_user(screen_name=screen_name)
|
self.data = self.session.twitter.get_user(screen_name=screen_name)
|
||||||
if screen_name != self.session.db["user_name"]:
|
if screen_name != self.session.db["user_name"]:
|
||||||
self.friendship_status = self.session.twitter.show_friendship(source_screen_name=self.session.db["user_name"], target_screen_name=screen_name)
|
self.friendship_status = self.session.twitter.show_friendship(source_screen_name=self.session.db["user_name"], target_screen_name=screen_name)
|
||||||
|
|
||||||
def fill_profile_fields(self):
|
def fill_profile_fields(self):
|
||||||
self.dialog.set_name(self.data["name"])
|
self.dialog.set_name(self.data.name)
|
||||||
if self.data["url"] != None:
|
if self.data.url != None:
|
||||||
self.dialog.set_url(self.data["url"])
|
self.dialog.set_url(self.data.url)
|
||||||
if len(self.data["location"]) > 0:
|
if len(self.data.location) > 0:
|
||||||
self.dialog.set_location(self.data["location"])
|
self.dialog.set_location(self.data.location)
|
||||||
if len(self.data["description"]) > 0:
|
if len(self.data.description) > 0:
|
||||||
self.dialog.set_description(self.data["description"])
|
self.dialog.set_description(self.data.description)
|
||||||
|
|
||||||
def get_image(self):
|
def get_image(self):
|
||||||
file = self.dialog.upload_picture()
|
file = self.dialog.upload_picture()
|
||||||
if file != None:
|
if file != None:
|
||||||
self.file = open(file, "rb")
|
self.file = open(file, "rb")
|
||||||
self.uploaded = True
|
self.uploaded = True
|
||||||
self.dialog.change_upload_button(self.uploaded)
|
self.dialog.change_upload_button(self.uploaded)
|
||||||
|
|
||||||
def discard_image(self):
|
def discard_image(self):
|
||||||
self.file = None
|
self.file = None
|
||||||
output.speak(_(u"Discarded"))
|
output.speak(_(u"Discarded"))
|
||||||
self.uploaded = False
|
self.uploaded = False
|
||||||
self.dialog.change_upload_button(self.uploaded)
|
self.dialog.change_upload_button(self.uploaded)
|
||||||
|
|
||||||
def upload_image(self, *args, **kwargs):
|
def upload_image(self, *args, **kwargs):
|
||||||
if self.uploaded == False:
|
if self.uploaded == False:
|
||||||
self.get_image()
|
self.get_image()
|
||||||
elif self.uploaded == True:
|
elif self.uploaded == True:
|
||||||
self.discard_image()
|
self.discard_image()
|
||||||
|
|
||||||
def do_update(self):
|
def do_update(self):
|
||||||
if self.user != None: return
|
if self.user != None: return
|
||||||
name = self.dialog.get("name")
|
name = self.dialog.get("name")
|
||||||
description = self.dialog.get("description")
|
description = self.dialog.get("description")
|
||||||
location = self.dialog.get("location")
|
location = self.dialog.get("location")
|
||||||
url = self.dialog.get("url")
|
url = self.dialog.get("url")
|
||||||
if self.file != None:
|
if self.file != None:
|
||||||
try:
|
try:
|
||||||
self.session.twitter.update_profile_image(image=self.file)
|
self.session.twitter.update_profile_image(image=self.file)
|
||||||
except TwythonError as e:
|
except TweepError as e:
|
||||||
output.speak(u"Error %s. %s" % (e.error_code, e.msg))
|
output.speak(u"Error %s. %s" % (e.api_code, e.reason))
|
||||||
try:
|
try:
|
||||||
self.session.twitter.update_profile(name=name, description=description, location=location, url=url)
|
self.session.twitter.update_profile(name=name, description=description, location=location, url=url)
|
||||||
except TwythonError as e:
|
except TweepError as e:
|
||||||
output.speak(u"Error %s. %s" % (e.error_code, e.msg))
|
output.speak(u"Error %s. %s" % (e.api_code, e.reason))
|
||||||
|
|
||||||
def get_user_info(self):
|
def get_user_info(self):
|
||||||
|
string = u""
|
||||||
|
string = string + _(u"Username: @%s\n") % (self.data.screen_name)
|
||||||
|
string = string + _(u"Name: %s\n") % (self.data.name)
|
||||||
|
if self.data.location != "":
|
||||||
|
string = string + _(u"Location: %s\n") % (self.data.location)
|
||||||
|
if self.data.url != None:
|
||||||
|
string = string+ _(u"URL: %s\n") % (self.data.entities["url"]["urls"][0]["expanded_url"])
|
||||||
|
if self.data.description != "":
|
||||||
|
if self.data.entities.get("description") != None and self.data.entities["description"].get("urls"):
|
||||||
|
self.data.description = utils.expand_urls(self.data.description, self.data.entities["description"])
|
||||||
|
string = string+ _(u"Bio: %s\n") % (self.data.description)
|
||||||
|
if self.data.protected == True: protected = _(u"Yes")
|
||||||
|
else: protected = _(u"No")
|
||||||
|
string = string+ _(u"Protected: %s\n") % (protected)
|
||||||
|
if hasattr(self, "friendship_status"):
|
||||||
|
relation = False
|
||||||
|
friendship = "Relationship: "
|
||||||
|
if self.friendship_status[0].following:
|
||||||
|
friendship += _(u"You follow {0}. ").format(self.data.name,)
|
||||||
|
relation = True
|
||||||
|
if self.friendship_status[1].following:
|
||||||
|
friendship += _(u"{0} is following you.").format(self.data.name,)
|
||||||
|
relation = True
|
||||||
|
if relation == True:
|
||||||
|
string = string+friendship+"\n"
|
||||||
|
string = string+_(u"Followers: %s\n Friends: %s\n") % (self.data.followers_count, self.data.friends_count)
|
||||||
|
if self.data.verified == True: verified = _(u"Yes")
|
||||||
|
else: verified = _(u"No")
|
||||||
|
string = string+ _(u"Verified: %s\n") % (verified)
|
||||||
|
string = string+ _(u"Tweets: %s\n") % (self.data.statuses_count)
|
||||||
|
string = string+ _(u"Likes: %s") % (self.data.favourites_count)
|
||||||
|
return string
|
||||||
|
|
||||||
string = u""
|
def visit_url(self, *args, **kwargs):
|
||||||
string = string + _(u"Username: @%s\n") % (self.data["screen_name"])
|
webbrowser.open_new_tab(self.data.url)
|
||||||
string = string + _(u"Name: %s\n") % (self.data["name"])
|
|
||||||
if self.data["location"] != "":
|
|
||||||
string = string + _(u"Location: %s\n") % (self.data["location"])
|
|
||||||
if self.data["url"] != None:
|
|
||||||
string = string+ _(u"URL: %s\n") % (self.data["url"])
|
|
||||||
if self.data["description"] != "":
|
|
||||||
string = string+ _(u"Bio: %s\n") % (self.data["description"])
|
|
||||||
if self.data["protected"] == True: protected = _(u"Yes")
|
|
||||||
else: protected = _(u"No")
|
|
||||||
string = string+ _(u"Protected: %s\n") % (protected)
|
|
||||||
if hasattr(self, "friendship_status"):
|
|
||||||
relation = False
|
|
||||||
friendship = "Relationship: "
|
|
||||||
if self.friendship_status["relationship"]["target"]["followed_by"]:
|
|
||||||
friendship += _(u"You follow {0}. ").format(self.data["name"],)
|
|
||||||
relation = True
|
|
||||||
if self.friendship_status["relationship"]["target"]["following"]:
|
|
||||||
friendship += _(u"{0} is following you.").format(self.data["name"],)
|
|
||||||
relation = True
|
|
||||||
if relation == True:
|
|
||||||
string = string+friendship+"\n"
|
|
||||||
string = string+_(u"Followers: %s\n Friends: %s\n") % (self.data["followers_count"], self.data["friends_count"])
|
|
||||||
if self.data["verified"] == True: verified = _(u"Yes")
|
|
||||||
else: verified = _(u"No")
|
|
||||||
string = string+ _(u"Verified: %s\n") % (verified)
|
|
||||||
string = string+ _(u"Tweets: %s\n") % (self.data["statuses_count"])
|
|
||||||
string = string+ _(u"Likes: %s") % (self.data["favourites_count"])
|
|
||||||
return string
|
|
||||||
|
|
||||||
def visit_url(self, *args, **kwargs):
|
|
||||||
webbrowser.open_new_tab(self.data["url"])
|
|
||||||
|
@@ -1,82 +1,79 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
|
||||||
from builtins import object
|
|
||||||
import re
|
|
||||||
import widgetUtils
|
import widgetUtils
|
||||||
import output
|
import output
|
||||||
from wxUI.dialogs import userActions
|
from wxUI.dialogs import userActions
|
||||||
from pubsub import pub
|
from pubsub import pub
|
||||||
from twython import TwythonError
|
from tweepy.error import TweepError
|
||||||
from extra import autocompletionUsers
|
from extra import autocompletionUsers
|
||||||
|
|
||||||
class userActionsController(object):
|
class userActionsController(object):
|
||||||
def __init__(self, buffer, users=[], default="follow"):
|
def __init__(self, buffer, users=[], default="follow"):
|
||||||
super(userActionsController, self).__init__()
|
super(userActionsController, self).__init__()
|
||||||
self.buffer = buffer
|
self.buffer = buffer
|
||||||
self.session = buffer.session
|
self.session = buffer.session
|
||||||
self.dialog = userActions.UserActionsDialog(users, default)
|
self.dialog = userActions.UserActionsDialog(users, default)
|
||||||
widgetUtils.connect_event(self.dialog.autocompletion, widgetUtils.BUTTON_PRESSED, self.autocomplete_users)
|
widgetUtils.connect_event(self.dialog.autocompletion, widgetUtils.BUTTON_PRESSED, self.autocomplete_users)
|
||||||
if self.dialog.get_response() == widgetUtils.OK:
|
if self.dialog.get_response() == widgetUtils.OK:
|
||||||
self.process_action()
|
self.process_action()
|
||||||
|
|
||||||
def autocomplete_users(self, *args, **kwargs):
|
def autocomplete_users(self, *args, **kwargs):
|
||||||
c = autocompletionUsers.completion.autocompletionUsers(self.dialog, self.session.session_id)
|
c = autocompletionUsers.completion.autocompletionUsers(self.dialog, self.session.session_id)
|
||||||
c.show_menu("dm")
|
c.show_menu("dm")
|
||||||
|
|
||||||
def process_action(self):
|
def process_action(self):
|
||||||
action = self.dialog.get_action()
|
action = self.dialog.get_action()
|
||||||
user = self.dialog.get_user()
|
user = self.dialog.get_user()
|
||||||
if user == "": return
|
if user == "": return
|
||||||
getattr(self, action)(user)
|
getattr(self, action)(user)
|
||||||
|
|
||||||
def follow(self, user):
|
def follow(self, user):
|
||||||
try:
|
try:
|
||||||
self.session.twitter.create_friendship(screen_name=user )
|
self.session.twitter.create_friendship(screen_name=user )
|
||||||
except TwythonError as err:
|
except TweepError as err:
|
||||||
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
|
output.speak("Error %s: %s" % (err.api_code, err.reason), True)
|
||||||
|
|
||||||
def unfollow(self, user):
|
def unfollow(self, user):
|
||||||
try:
|
try:
|
||||||
id = self.session.twitter.destroy_friendship(screen_name=user )
|
id = self.session.twitter.destroy_friendship(screen_name=user )
|
||||||
except TwythonError as err:
|
except TweepError as err:
|
||||||
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
|
output.speak("Error %s: %s" % (err.api_code, err.reason), True)
|
||||||
|
|
||||||
def mute(self, user):
|
def mute(self, user):
|
||||||
try:
|
try:
|
||||||
id = self.session.twitter.create_mute(screen_name=user )
|
id = self.session.twitter.create_mute(screen_name=user )
|
||||||
except TwythonError as err:
|
except TweepError as err:
|
||||||
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
|
output.speak("Error %s: %s" % (err.api_code, err.reason), True)
|
||||||
|
|
||||||
def unmute(self, user):
|
def unmute(self, user):
|
||||||
try:
|
try:
|
||||||
id = self.session.twitter.destroy_mute(screen_name=user )
|
id = self.session.twitter.destroy_mute(screen_name=user )
|
||||||
except TwythonError as err:
|
except TweepError as err:
|
||||||
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
|
output.speak("Error %s: %s" % (err.api_code, err.reason), True)
|
||||||
|
|
||||||
def report(self, user):
|
def report(self, user):
|
||||||
try:
|
try:
|
||||||
id = self.session.twitter.report_spam(screen_name=user )
|
id = self.session.twitter.report_spam(screen_name=user )
|
||||||
except TwythonError as err:
|
except TweepError as err:
|
||||||
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
|
output.speak("Error %s: %s" % (err.api_code, err.reason), True)
|
||||||
|
|
||||||
def block(self, user):
|
def block(self, user):
|
||||||
try:
|
try:
|
||||||
id = self.session.twitter.create_block(screen_name=user )
|
id = self.session.twitter.create_block(screen_name=user )
|
||||||
except TwythonError as err:
|
except TweepError as err:
|
||||||
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
|
output.speak("Error %s: %s" % (err.api_code, err.reason), True)
|
||||||
|
|
||||||
def unblock(self, user):
|
def unblock(self, user):
|
||||||
try:
|
try:
|
||||||
id = self.session.twitter.destroy_block(screen_name=user )
|
id = self.session.twitter.destroy_block(screen_name=user )
|
||||||
except TwythonError as err:
|
except TweepError as err:
|
||||||
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
|
output.speak("Error %s: %s" % (err.api_code, err.reason), True)
|
||||||
|
|
||||||
def ignore_client(self, user):
|
def ignore_client(self, user):
|
||||||
tweet = self.buffer.get_right_tweet()
|
tweet = self.buffer.get_right_tweet()
|
||||||
if "sender" in tweet:
|
if hasattr(tweet, "sender"):
|
||||||
output.speak(_(u"You can't ignore direct messages"))
|
output.speak(_(u"You can't ignore direct messages"))
|
||||||
return
|
return
|
||||||
client = re.sub(r"(?s)<.*?>", "", tweet["source"])
|
client = tweet.source
|
||||||
if client not in self.session.settings["twitter"]["ignored_clients"]:
|
if client not in self.session.settings["twitter"]["ignored_clients"]:
|
||||||
self.session.settings["twitter"]["ignored_clients"].append(client)
|
self.session.settings["twitter"]["ignored_clients"].append(client)
|
||||||
self.session.settings.write()
|
self.session.settings.write()
|
||||||
|
@@ -37,146 +37,146 @@ import logging
|
|||||||
log = logging.getLogger("extra.AudioUploader.audioUploader")
|
log = logging.getLogger("extra.AudioUploader.audioUploader")
|
||||||
|
|
||||||
class audioUploader(object):
|
class audioUploader(object):
|
||||||
def __init__(self, configFile, completed_callback):
|
def __init__(self, configFile, completed_callback):
|
||||||
self.config = configFile
|
self.config = configFile
|
||||||
super(audioUploader, self).__init__()
|
super(audioUploader, self).__init__()
|
||||||
self.dialog = wx_ui.audioDialog(services=self.get_available_services())
|
self.dialog = wx_ui.audioDialog(services=self.get_available_services())
|
||||||
self.file = None
|
self.file = None
|
||||||
self.recorded = False
|
self.recorded = False
|
||||||
self.recording = None
|
self.recording = None
|
||||||
self.playing = None
|
self.playing = None
|
||||||
widgetUtils.connect_event(self.dialog.play, widgetUtils.BUTTON_PRESSED, self.on_play)
|
widgetUtils.connect_event(self.dialog.play, widgetUtils.BUTTON_PRESSED, self.on_play)
|
||||||
widgetUtils.connect_event(self.dialog.pause, widgetUtils.BUTTON_PRESSED, self.on_pause)
|
widgetUtils.connect_event(self.dialog.pause, widgetUtils.BUTTON_PRESSED, self.on_pause)
|
||||||
widgetUtils.connect_event(self.dialog.record, widgetUtils.BUTTON_PRESSED, self.on_record)
|
widgetUtils.connect_event(self.dialog.record, widgetUtils.BUTTON_PRESSED, self.on_record)
|
||||||
widgetUtils.connect_event(self.dialog.attach_exists, widgetUtils.BUTTON_PRESSED, self.on_attach_exists)
|
widgetUtils.connect_event(self.dialog.attach_exists, widgetUtils.BUTTON_PRESSED, self.on_attach_exists)
|
||||||
widgetUtils.connect_event(self.dialog.discard, widgetUtils.BUTTON_PRESSED, self.on_discard)
|
widgetUtils.connect_event(self.dialog.discard, widgetUtils.BUTTON_PRESSED, self.on_discard)
|
||||||
if self.dialog.get_response() == widgetUtils.OK:
|
if self.dialog.get_response() == widgetUtils.OK:
|
||||||
self.postprocess()
|
self.postprocess()
|
||||||
log.debug("Uploading file %s to %s..." % (self.file, self.dialog.get("services")))
|
log.debug("Uploading file %s to %s..." % (self.file, self.dialog.get("services")))
|
||||||
self.uploaderDialog = wx_transfer_dialogs.UploadDialog(self.file)
|
self.uploaderDialog = wx_transfer_dialogs.UploadDialog(self.file)
|
||||||
output.speak(_(u"Attaching..."))
|
output.speak(_(u"Attaching..."))
|
||||||
if self.dialog.get("services") == "SNDUp":
|
if self.dialog.get("services") == "SNDUp":
|
||||||
base_url = "https://sndup.net/post.php"
|
base_url = "https://sndup.net/post.php"
|
||||||
if len(self.config["sound"]["sndup_api_key"]) > 0:
|
if len(self.config["sound"]["sndup_api_key"]) > 0:
|
||||||
url = base_url + '?apikey=' + self.config['sound']['sndup_api_key']
|
url = base_url + '?apikey=' + self.config['sound']['sndup_api_key']
|
||||||
else:
|
else:
|
||||||
url = base_url
|
url = base_url
|
||||||
self.uploaderFunction = transfer.Upload(obj=self, field='file', url=url, filename=self.file, completed_callback=completed_callback)
|
self.uploaderFunction = transfer.Upload(obj=self, field='file', url=url, filename=self.file, completed_callback=completed_callback)
|
||||||
pub.subscribe(self.uploaderDialog.update, "uploading")
|
pub.subscribe(self.uploaderDialog.update, "uploading")
|
||||||
self.uploaderDialog.get_response(self.uploaderFunction.perform_threaded)
|
self.uploaderDialog.get_response(self.uploaderFunction.perform_threaded)
|
||||||
|
|
||||||
def get_available_services(self):
|
def get_available_services(self):
|
||||||
services = []
|
services = []
|
||||||
services.append("SNDUp")
|
services.append("SNDUp")
|
||||||
return services
|
return services
|
||||||
|
|
||||||
def on_pause(self, *args, **kwargs):
|
def on_pause(self, *args, **kwargs):
|
||||||
if self.dialog.get("pause") == _(u"Pause"):
|
if self.dialog.get("pause") == _(u"Pause"):
|
||||||
self.recording.pause()
|
self.recording.pause()
|
||||||
self.dialog.set("pause", _(u"&Resume"))
|
self.dialog.set("pause", _(u"&Resume"))
|
||||||
elif self.dialog.get("pause") == _(u"Resume"):
|
elif self.dialog.get("pause") == _(u"Resume"):
|
||||||
self.recording.play()
|
self.recording.play()
|
||||||
self.dialog.set("pause", _(U"&Pause"))
|
self.dialog.set("pause", _(U"&Pause"))
|
||||||
|
|
||||||
def on_record(self, *args, **kwargs):
|
def on_record(self, *args, **kwargs):
|
||||||
if self.recording != None:
|
if self.recording != None:
|
||||||
self.stop_recording()
|
self.stop_recording()
|
||||||
self.dialog.disable_control("pause")
|
self.dialog.disable_control("pause")
|
||||||
else:
|
else:
|
||||||
self.start_recording()
|
self.start_recording()
|
||||||
self.dialog.enable_control("pause")
|
self.dialog.enable_control("pause")
|
||||||
|
|
||||||
def start_recording(self):
|
def start_recording(self):
|
||||||
self.dialog.disable_control("attach_exists")
|
self.dialog.disable_control("attach_exists")
|
||||||
self.file = tempfile.mktemp(suffix='.wav')
|
self.file = tempfile.mktemp(suffix='.wav')
|
||||||
self.recording = sound.recording(self.file)
|
self.recording = sound.recording(self.file)
|
||||||
self.recording.play()
|
self.recording.play()
|
||||||
self.dialog.set("record", _(u"&Stop"))
|
self.dialog.set("record", _(u"&Stop"))
|
||||||
output.speak(_(u"Recording"))
|
output.speak(_(u"Recording"))
|
||||||
|
|
||||||
def stop_recording(self):
|
def stop_recording(self):
|
||||||
self.recording.stop()
|
self.recording.stop()
|
||||||
self.recording.free()
|
self.recording.free()
|
||||||
output.speak(_(u"Stopped"))
|
output.speak(_(u"Stopped"))
|
||||||
self.recorded = True
|
self.recorded = True
|
||||||
self.dialog.set("record", _(u"&Record"))
|
self.dialog.set("record", _(u"&Record"))
|
||||||
self.file_attached()
|
self.file_attached()
|
||||||
|
|
||||||
def file_attached(self):
|
def file_attached(self):
|
||||||
self.dialog.set("pause", _(u"&Pause"))
|
self.dialog.set("pause", _(u"&Pause"))
|
||||||
self.dialog.disable_control("record")
|
self.dialog.disable_control("record")
|
||||||
self.dialog.enable_control("play")
|
self.dialog.enable_control("play")
|
||||||
self.dialog.enable_control("discard")
|
self.dialog.enable_control("discard")
|
||||||
self.dialog.disable_control("attach_exists")
|
self.dialog.disable_control("attach_exists")
|
||||||
self.dialog.enable_control("attach")
|
self.dialog.enable_control("attach")
|
||||||
self.dialog.play.SetFocus()
|
self.dialog.play.SetFocus()
|
||||||
|
|
||||||
def on_discard(self, *args, **kwargs):
|
def on_discard(self, *args, **kwargs):
|
||||||
if self.playing:
|
if self.playing:
|
||||||
self._stop()
|
self._stop()
|
||||||
if self.recording != None:
|
if self.recording != None:
|
||||||
self.cleanup()
|
self.cleanup()
|
||||||
self.dialog.disable_control("attach")
|
self.dialog.disable_control("attach")
|
||||||
self.dialog.disable_control("play")
|
self.dialog.disable_control("play")
|
||||||
self.file = None
|
self.file = None
|
||||||
self.dialog.enable_control("record")
|
self.dialog.enable_control("record")
|
||||||
self.dialog.enable_control("attach_exists")
|
self.dialog.enable_control("attach_exists")
|
||||||
self.dialog.record.SetFocus()
|
self.dialog.record.SetFocus()
|
||||||
self.dialog.disable_control("discard")
|
self.dialog.disable_control("discard")
|
||||||
self.recording = None
|
self.recording = None
|
||||||
output.speak(_(u"Discarded"))
|
output.speak(_(u"Discarded"))
|
||||||
|
|
||||||
def on_play(self, *args, **kwargs):
|
def on_play(self, *args, **kwargs):
|
||||||
if not self.playing:
|
if not self.playing:
|
||||||
call_threaded(self._play)
|
call_threaded(self._play)
|
||||||
else:
|
else:
|
||||||
self._stop()
|
self._stop()
|
||||||
|
|
||||||
def _play(self):
|
def _play(self):
|
||||||
output.speak(_(u"Playing..."))
|
output.speak(_(u"Playing..."))
|
||||||
# try:
|
# try:
|
||||||
self.playing = sound_lib.stream.FileStream(file=str(self.file), flags=sound_lib.stream.BASS_UNICODE)
|
self.playing = sound_lib.stream.FileStream(file=str(self.file), flags=sound_lib.stream.BASS_UNICODE)
|
||||||
self.playing.play()
|
self.playing.play()
|
||||||
self.dialog.set("play", _(u"&Stop"))
|
self.dialog.set("play", _(u"&Stop"))
|
||||||
try:
|
try:
|
||||||
while self.playing.is_playing:
|
while self.playing.is_playing:
|
||||||
pass
|
pass
|
||||||
self.dialog.set("play", _(u"&Play"))
|
self.dialog.set("play", _(u"&Play"))
|
||||||
self.playing.free()
|
self.playing.free()
|
||||||
self.playing = None
|
self.playing = None
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _stop(self):
|
def _stop(self):
|
||||||
output.speak(_(u"Stopped"))
|
output.speak(_(u"Stopped"))
|
||||||
self.playing.stop()
|
self.playing.stop()
|
||||||
self.playing.free()
|
self.playing.free()
|
||||||
self.dialog.set("play", _(u"&Play"))
|
self.dialog.set("play", _(u"&Play"))
|
||||||
self.playing = None
|
self.playing = None
|
||||||
|
|
||||||
def postprocess(self):
|
def postprocess(self):
|
||||||
if self.file.lower().endswith('.wav'):
|
if self.file.lower().endswith('.wav'):
|
||||||
output.speak(_(u"Recoding audio..."))
|
output.speak(_(u"Recoding audio..."))
|
||||||
sound.recode_audio(self.file)
|
sound.recode_audio(self.file)
|
||||||
self.wav_file = self.file
|
self.wav_file = self.file
|
||||||
self.file = '%s.ogg' % self.file[:-4]
|
self.file = '%s.ogg' % self.file[:-4]
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
if self.playing and self.playing.is_playing:
|
if self.playing and self.playing.is_playing:
|
||||||
self.playing.stop()
|
self.playing.stop()
|
||||||
if self.recording != None:
|
if self.recording != None:
|
||||||
if self.recording.is_playing:
|
if self.recording.is_playing:
|
||||||
self.recording.stop()
|
self.recording.stop()
|
||||||
try:
|
try:
|
||||||
self.recording.free()
|
self.recording.free()
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
os.remove(self.file)
|
os.remove(self.file)
|
||||||
if hasattr(self, 'wav_file'):
|
if hasattr(self, 'wav_file'):
|
||||||
os.remove(self.wav_file)
|
os.remove(self.wav_file)
|
||||||
|
|
||||||
def on_attach_exists(self, *args, **kwargs):
|
def on_attach_exists(self, *args, **kwargs):
|
||||||
self.file = self.dialog.get_file()
|
self.file = self.dialog.get_file()
|
||||||
if self.file != False:
|
if self.file != False:
|
||||||
self.file_attached()
|
self.file_attached()
|
||||||
|
|
||||||
|
@@ -15,74 +15,74 @@ from requests_toolbelt.multipart.encoder import MultipartEncoder, MultipartEncod
|
|||||||
import requests
|
import requests
|
||||||
import os
|
import os
|
||||||
class Upload(object):
|
class Upload(object):
|
||||||
def __init__(self, field=None, obj=None, url=None, filename=None, follow_location=True, completed_callback=None, verbose=False, *args, **kwargs):
|
def __init__(self, field=None, obj=None, url=None, filename=None, follow_location=True, completed_callback=None, verbose=False, *args, **kwargs):
|
||||||
super(Upload, self).__init__(*args, **kwargs)
|
super(Upload, self).__init__(*args, **kwargs)
|
||||||
self.url=url
|
self.url=url
|
||||||
self.filename=filename
|
self.filename=filename
|
||||||
log.debug("Uploading audio to %s, filename %s" % (url, filename))
|
log.debug("Uploading audio to %s, filename %s" % (url, filename))
|
||||||
self.start_time = None
|
self.start_time = None
|
||||||
self.completed_callback = completed_callback
|
self.completed_callback = completed_callback
|
||||||
self.background_thread = None
|
self.background_thread = None
|
||||||
self.transfer_rate = 0
|
self.transfer_rate = 0
|
||||||
self.local_filename=os.path.basename(self.filename)
|
self.local_filename=os.path.basename(self.filename)
|
||||||
if isinstance(self.local_filename, str):
|
if isinstance(self.local_filename, str):
|
||||||
self.local_filename=self.local_filename.encode(sys.getfilesystemencoding())
|
self.local_filename=self.local_filename.encode(sys.getfilesystemencoding())
|
||||||
self.fin=open(self.filename, 'rb')
|
self.fin=open(self.filename, 'rb')
|
||||||
self.m = MultipartEncoder(fields={field:(self.local_filename, self.fin, "application/octet-stream")})
|
self.m = MultipartEncoder(fields={field:(self.local_filename, self.fin, "application/octet-stream")})
|
||||||
self.monitor = MultipartEncoderMonitor(self.m, self.progress_callback)
|
self.monitor = MultipartEncoderMonitor(self.m, self.progress_callback)
|
||||||
self.response=None
|
self.response=None
|
||||||
self.obj=obj
|
self.obj=obj
|
||||||
self.follow_location=follow_location
|
self.follow_location=follow_location
|
||||||
#the verbose parameter is deprecated and will be removed soon
|
#the verbose parameter is deprecated and will be removed soon
|
||||||
|
|
||||||
def elapsed_time(self):
|
def elapsed_time(self):
|
||||||
if not self.start_time:
|
if not self.start_time:
|
||||||
return 0
|
return 0
|
||||||
return time.time() - self.start_time
|
return time.time() - self.start_time
|
||||||
|
|
||||||
def progress_callback(self, monitor):
|
def progress_callback(self, monitor):
|
||||||
progress = {}
|
progress = {}
|
||||||
progress["total"] = monitor.len
|
progress["total"] = monitor.len
|
||||||
progress["current"] = monitor.bytes_read
|
progress["current"] = monitor.bytes_read
|
||||||
if progress["current"] == 0:
|
if progress["current"] == 0:
|
||||||
progress["percent"] = 0
|
progress["percent"] = 0
|
||||||
self.transfer_rate = 0
|
self.transfer_rate = 0
|
||||||
else:
|
else:
|
||||||
progress["percent"] = int((float(progress["current"]) / progress["total"]) * 100)
|
progress["percent"] = int((float(progress["current"]) / progress["total"]) * 100)
|
||||||
self.transfer_rate = old_div(progress["current"], self.elapsed_time())
|
self.transfer_rate = old_div(progress["current"], self.elapsed_time())
|
||||||
progress["speed"] = '%s/s' % convert_bytes(self.transfer_rate)
|
progress["speed"] = '%s/s' % convert_bytes(self.transfer_rate)
|
||||||
if self.transfer_rate:
|
if self.transfer_rate:
|
||||||
progress["eta"] = old_div((progress["total"] - progress["current"]), self.transfer_rate)
|
progress["eta"] = old_div((progress["total"] - progress["current"]), self.transfer_rate)
|
||||||
else:
|
else:
|
||||||
progress["eta"] = 0
|
progress["eta"] = 0
|
||||||
pub.sendMessage("uploading", data=progress)
|
pub.sendMessage("uploading", data=progress)
|
||||||
|
|
||||||
def perform_transfer(self):
|
def perform_transfer(self):
|
||||||
log.debug("starting upload...")
|
log.debug("starting upload...")
|
||||||
self.start_time = time.time()
|
self.start_time = time.time()
|
||||||
self.response=requests.post(url=self.url, data=self.monitor, headers={"Content-Type":self.m.content_type}, allow_redirects=self.follow_location, stream=True)
|
self.response=requests.post(url=self.url, data=self.monitor, headers={"Content-Type":self.m.content_type}, allow_redirects=self.follow_location, stream=True)
|
||||||
log.debug("Upload finished.")
|
log.debug("Upload finished.")
|
||||||
self.complete_transfer()
|
self.complete_transfer()
|
||||||
|
|
||||||
def perform_threaded(self, *args, **kwargs):
|
def perform_threaded(self, *args, **kwargs):
|
||||||
self.background_thread = threading.Thread(target=self.perform_transfer)
|
self.background_thread = threading.Thread(target=self.perform_transfer)
|
||||||
self.background_thread.daemon = True
|
self.background_thread.daemon = True
|
||||||
self.background_thread.start()
|
self.background_thread.start()
|
||||||
|
|
||||||
def complete_transfer(self):
|
def complete_transfer(self):
|
||||||
if callable(self.completed_callback):
|
if callable(self.completed_callback):
|
||||||
self.completed_callback(self.obj)
|
self.completed_callback(self.obj)
|
||||||
if hasattr(self,'fin') and callable(self.fin.close):
|
if hasattr(self,'fin') and callable(self.fin.close):
|
||||||
self.fin.close()
|
self.fin.close()
|
||||||
|
|
||||||
def get_url(self):
|
def get_url(self):
|
||||||
try:
|
try:
|
||||||
data = self.response.json()
|
data = self.response.json()
|
||||||
except:
|
except:
|
||||||
return _("Error in file upload: {0}").format(self.data.content,)
|
return _("Error in file upload: {0}").format(self.data.content,)
|
||||||
if "url" in data and data["url"] != "0":
|
if "url" in data and data["url"] != "0":
|
||||||
return data["url"]
|
return data["url"]
|
||||||
elif "error" in data and data["error"] != "0":
|
elif "error" in data and data["error"] != "0":
|
||||||
return data["error"]
|
return data["error"]
|
||||||
else:
|
else:
|
||||||
return _("Error in file upload: {0}").format(self.data.content,)
|
return _("Error in file upload: {0}").format(self.data.content,)
|
||||||
|
@@ -3,42 +3,42 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from builtins import str
|
from builtins import str
|
||||||
def convert_bytes(n):
|
def convert_bytes(n):
|
||||||
K, M, G, T, P = 1 << 10, 1 << 20, 1 << 30, 1 << 40, 1 << 50
|
K, M, G, T, P = 1 << 10, 1 << 20, 1 << 30, 1 << 40, 1 << 50
|
||||||
if n >= P:
|
if n >= P:
|
||||||
return '%.2fPb' % (float(n) / T)
|
return '%.2fPb' % (float(n) / T)
|
||||||
elif n >= T:
|
elif n >= T:
|
||||||
return '%.2fTb' % (float(n) / T)
|
return '%.2fTb' % (float(n) / T)
|
||||||
elif n >= G:
|
elif n >= G:
|
||||||
return '%.2fGb' % (float(n) / G)
|
return '%.2fGb' % (float(n) / G)
|
||||||
elif n >= M:
|
elif n >= M:
|
||||||
return '%.2fMb' % (float(n) / M)
|
return '%.2fMb' % (float(n) / M)
|
||||||
elif n >= K:
|
elif n >= K:
|
||||||
return '%.2fKb' % (float(n) / K)
|
return '%.2fKb' % (float(n) / K)
|
||||||
else:
|
else:
|
||||||
return '%d' % n
|
return '%d' % n
|
||||||
|
|
||||||
def seconds_to_string(seconds, precision=0):
|
def seconds_to_string(seconds, precision=0):
|
||||||
day = seconds // 86400
|
day = seconds // 86400
|
||||||
hour = seconds // 3600
|
hour = seconds // 3600
|
||||||
min = (seconds // 60) % 60
|
min = (seconds // 60) % 60
|
||||||
sec = seconds - (hour * 3600) - (min * 60)
|
sec = seconds - (hour * 3600) - (min * 60)
|
||||||
sec_spec = "." + str(precision) + "f"
|
sec_spec = "." + str(precision) + "f"
|
||||||
sec_string = sec.__format__(sec_spec)
|
sec_string = sec.__format__(sec_spec)
|
||||||
string = ""
|
string = ""
|
||||||
if day == 1:
|
if day == 1:
|
||||||
string += _(u"%d day, ") % day
|
string += _(u"%d day, ") % day
|
||||||
elif day >= 2:
|
elif day >= 2:
|
||||||
string += _(u"%d days, ") % day
|
string += _(u"%d days, ") % day
|
||||||
if (hour == 1):
|
if (hour == 1):
|
||||||
string += _(u"%d hour, ") % hour
|
string += _(u"%d hour, ") % hour
|
||||||
elif (hour >= 2):
|
elif (hour >= 2):
|
||||||
string += _("%d hours, ") % hour
|
string += _("%d hours, ") % hour
|
||||||
if (min == 1):
|
if (min == 1):
|
||||||
string += _(u"%d minute, ") % min
|
string += _(u"%d minute, ") % min
|
||||||
elif (min >= 2):
|
elif (min >= 2):
|
||||||
string += _(u"%d minutes, ") % min
|
string += _(u"%d minutes, ") % min
|
||||||
if sec >= 0 and sec <= 2:
|
if sec >= 0 and sec <= 2:
|
||||||
string += _(u"%s second") % sec_string
|
string += _(u"%s second") % sec_string
|
||||||
else:
|
else:
|
||||||
string += _(u"%s seconds") % sec_string
|
string += _(u"%s seconds") % sec_string
|
||||||
return string
|
return string
|
||||||
|
@@ -7,57 +7,57 @@ import widgetUtils
|
|||||||
|
|
||||||
class UploadDialog(widgetUtils.BaseDialog):
|
class UploadDialog(widgetUtils.BaseDialog):
|
||||||
|
|
||||||
def __init__(self, filename, *args, **kwargs):
|
def __init__(self, filename, *args, **kwargs):
|
||||||
super(UploadDialog, self).__init__(parent=None, id=wx.ID_ANY, *args, **kwargs)
|
super(UploadDialog, self).__init__(parent=None, id=wx.ID_ANY, *args, **kwargs)
|
||||||
self.pane = wx.Panel(self)
|
self.pane = wx.Panel(self)
|
||||||
self.progress_bar = wx.Gauge(parent=self.pane)
|
self.progress_bar = wx.Gauge(parent=self.pane)
|
||||||
fileBox = wx.BoxSizer(wx.HORIZONTAL)
|
fileBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
fileLabel = wx.StaticText(self.pane, -1, _(u"File"))
|
fileLabel = wx.StaticText(self.pane, -1, _(u"File"))
|
||||||
self.file = wx.TextCtrl(self.pane, -1, value=filename, style=wx.TE_READONLY|wx.TE_MULTILINE, size=(200, 100))
|
self.file = wx.TextCtrl(self.pane, -1, value=filename, style=wx.TE_READONLY|wx.TE_MULTILINE, size=(200, 100))
|
||||||
self.file.SetFocus()
|
self.file.SetFocus()
|
||||||
fileBox.Add(fileLabel)
|
fileBox.Add(fileLabel)
|
||||||
fileBox.Add(self.file)
|
fileBox.Add(self.file)
|
||||||
currentAmountBox = wx.BoxSizer(wx.HORIZONTAL)
|
currentAmountBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
current_amount_label = wx.StaticText(self.pane, -1, _(u"Transferred"))
|
current_amount_label = wx.StaticText(self.pane, -1, _(u"Transferred"))
|
||||||
self.current_amount = wx.TextCtrl(self.pane, -1, value='0', style=wx.TE_READONLY|wx.TE_MULTILINE)
|
self.current_amount = wx.TextCtrl(self.pane, -1, value='0', style=wx.TE_READONLY|wx.TE_MULTILINE)
|
||||||
currentAmountBox.Add(current_amount_label)
|
currentAmountBox.Add(current_amount_label)
|
||||||
currentAmountBox.Add(self.current_amount)
|
currentAmountBox.Add(self.current_amount)
|
||||||
totalSizeBox = wx.BoxSizer(wx.HORIZONTAL)
|
totalSizeBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
total_size_label = wx.StaticText(self.pane, -1, _(u"Total file size"))
|
total_size_label = wx.StaticText(self.pane, -1, _(u"Total file size"))
|
||||||
self.total_size = wx.TextCtrl(self.pane, -1, value='0', style=wx.TE_READONLY|wx.TE_MULTILINE)
|
self.total_size = wx.TextCtrl(self.pane, -1, value='0', style=wx.TE_READONLY|wx.TE_MULTILINE)
|
||||||
totalSizeBox.Add(total_size_label)
|
totalSizeBox.Add(total_size_label)
|
||||||
totalSizeBox.Add(self.total_size)
|
totalSizeBox.Add(self.total_size)
|
||||||
speedBox = wx.BoxSizer(wx.HORIZONTAL)
|
speedBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
speedLabel = wx.StaticText(self.pane, -1, _(u"Transfer rate"))
|
speedLabel = wx.StaticText(self.pane, -1, _(u"Transfer rate"))
|
||||||
self.speed = wx.TextCtrl(self.pane, -1, style=wx.TE_READONLY|wx.TE_MULTILINE, value="0 Kb/s")
|
self.speed = wx.TextCtrl(self.pane, -1, style=wx.TE_READONLY|wx.TE_MULTILINE, value="0 Kb/s")
|
||||||
speedBox.Add(speedLabel)
|
speedBox.Add(speedLabel)
|
||||||
speedBox.Add(self.speed)
|
speedBox.Add(self.speed)
|
||||||
etaBox = wx.BoxSizer(wx.HORIZONTAL)
|
etaBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
etaLabel = wx.StaticText(self.pane, -1, _(u"Time left"))
|
etaLabel = wx.StaticText(self.pane, -1, _(u"Time left"))
|
||||||
self.eta = wx.TextCtrl(self.pane, -1, style=wx.TE_READONLY|wx.TE_MULTILINE, value="Unknown", size=(200, 100))
|
self.eta = wx.TextCtrl(self.pane, -1, style=wx.TE_READONLY|wx.TE_MULTILINE, value="Unknown", size=(200, 100))
|
||||||
etaBox.Add(etaLabel)
|
etaBox.Add(etaLabel)
|
||||||
etaBox.Add(self.eta)
|
etaBox.Add(self.eta)
|
||||||
self.create_buttons()
|
self.create_buttons()
|
||||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||||
sizer.Add(fileBox)
|
sizer.Add(fileBox)
|
||||||
sizer.Add(currentAmountBox)
|
sizer.Add(currentAmountBox)
|
||||||
sizer.Add(totalSizeBox)
|
sizer.Add(totalSizeBox)
|
||||||
sizer.Add(speedBox)
|
sizer.Add(speedBox)
|
||||||
sizer.Add(etaBox)
|
sizer.Add(etaBox)
|
||||||
sizer.Add(self.progress_bar)
|
sizer.Add(self.progress_bar)
|
||||||
self.pane.SetSizerAndFit(sizer)
|
self.pane.SetSizerAndFit(sizer)
|
||||||
|
|
||||||
def update(self, data):
|
def update(self, data):
|
||||||
wx.CallAfter(self.progress_bar.SetValue, data["percent"])
|
wx.CallAfter(self.progress_bar.SetValue, data["percent"])
|
||||||
wx.CallAfter(self.current_amount.SetValue, '%s (%d%%)' % (convert_bytes(data["current"]), data["percent"]))
|
wx.CallAfter(self.current_amount.SetValue, '%s (%d%%)' % (convert_bytes(data["current"]), data["percent"]))
|
||||||
wx.CallAfter(self.total_size.SetValue, convert_bytes(data["total"]))
|
wx.CallAfter(self.total_size.SetValue, convert_bytes(data["total"]))
|
||||||
wx.CallAfter(self.speed.SetValue, data["speed"])
|
wx.CallAfter(self.speed.SetValue, data["speed"])
|
||||||
if data["eta"]:
|
if data["eta"]:
|
||||||
wx.CallAfter(self.eta.SetValue, seconds_to_string(data["eta"]))
|
wx.CallAfter(self.eta.SetValue, seconds_to_string(data["eta"]))
|
||||||
|
|
||||||
def create_buttons(self):
|
def create_buttons(self):
|
||||||
self.cancel_button = wx.Button(parent=self.pane, id=wx.ID_CANCEL)
|
self.cancel_button = wx.Button(parent=self.pane, id=wx.ID_CANCEL)
|
||||||
|
|
||||||
def get_response(self, fn):
|
def get_response(self, fn):
|
||||||
wx.CallAfter(fn, 0.01)
|
wx.CallAfter(fn, 0.01)
|
||||||
self.ShowModal()
|
self.ShowModal()
|
||||||
|
@@ -24,56 +24,56 @@ import logging
|
|||||||
log = logging.getLogger("extra.AudioUploader.wx_UI")
|
log = logging.getLogger("extra.AudioUploader.wx_UI")
|
||||||
|
|
||||||
class audioDialog(widgetUtils.BaseDialog):
|
class audioDialog(widgetUtils.BaseDialog):
|
||||||
def __init__(self, services):
|
def __init__(self, services):
|
||||||
log.debug("creating audio dialog.")
|
log.debug("creating audio dialog.")
|
||||||
super(audioDialog, self).__init__(None, -1, _(u"Attach audio"))
|
super(audioDialog, self).__init__(None, -1, _(u"Attach audio"))
|
||||||
panel = wx.Panel(self)
|
panel = wx.Panel(self)
|
||||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||||
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
|
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
btnSizer2 = wx.BoxSizer(wx.HORIZONTAL)
|
btnSizer2 = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
|
|
||||||
self.play = wx.Button(panel, -1, _(u"&Play"))
|
self.play = wx.Button(panel, -1, _(u"&Play"))
|
||||||
self.play.Disable()
|
self.play.Disable()
|
||||||
self.pause = wx.Button(panel, -1, _(u"&Pause"))
|
self.pause = wx.Button(panel, -1, _(u"&Pause"))
|
||||||
self.pause.Disable()
|
self.pause.Disable()
|
||||||
self.record = wx.Button(panel, -1, _(u"&Record"))
|
self.record = wx.Button(panel, -1, _(u"&Record"))
|
||||||
self.record.SetFocus()
|
self.record.SetFocus()
|
||||||
self.attach_exists = wx.Button(panel, -1, _(u"&Add an existing file"))
|
self.attach_exists = wx.Button(panel, -1, _(u"&Add an existing file"))
|
||||||
self.discard = wx.Button(panel, -1, _(u"&Discard"))
|
self.discard = wx.Button(panel, -1, _(u"&Discard"))
|
||||||
self.discard.Disable()
|
self.discard.Disable()
|
||||||
label = wx.StaticText(panel, -1, _(u"Upload to"))
|
label = wx.StaticText(panel, -1, _(u"Upload to"))
|
||||||
self.services = wx.ComboBox(panel, -1, choices=services, value=services[0], style=wx.CB_READONLY)
|
self.services = wx.ComboBox(panel, -1, choices=services, value=services[0], style=wx.CB_READONLY)
|
||||||
servicesBox = wx.BoxSizer(wx.HORIZONTAL)
|
servicesBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
servicesBox.Add(label, 0, wx.ALL, 5)
|
servicesBox.Add(label, 0, wx.ALL, 5)
|
||||||
servicesBox.Add(self.services, 0, wx.ALL, 5)
|
servicesBox.Add(self.services, 0, wx.ALL, 5)
|
||||||
self.attach = wx.Button(panel, wx.ID_OK, _(u"Attach"))
|
self.attach = wx.Button(panel, wx.ID_OK, _(u"Attach"))
|
||||||
self.attach.Disable()
|
self.attach.Disable()
|
||||||
cancel = wx.Button(panel, wx.ID_CANCEL, _(u"&Cancel"))
|
cancel = wx.Button(panel, wx.ID_CANCEL, _(u"&Cancel"))
|
||||||
btnSizer.Add(self.play, 0, wx.ALL, 5)
|
btnSizer.Add(self.play, 0, wx.ALL, 5)
|
||||||
btnSizer.Add(self.pause, 0, wx.ALL, 5)
|
btnSizer.Add(self.pause, 0, wx.ALL, 5)
|
||||||
btnSizer.Add(self.record, 0, wx.ALL, 5)
|
btnSizer.Add(self.record, 0, wx.ALL, 5)
|
||||||
btnSizer2.Add(self.attach_exists, 0, wx.ALL, 5)
|
btnSizer2.Add(self.attach_exists, 0, wx.ALL, 5)
|
||||||
btnSizer2.Add(self.discard, 0, wx.ALL, 5)
|
btnSizer2.Add(self.discard, 0, wx.ALL, 5)
|
||||||
btnSizer2.Add(self.attach, 0, wx.ALL, 5)
|
btnSizer2.Add(self.attach, 0, wx.ALL, 5)
|
||||||
btnSizer2.Add(cancel, 0, wx.ALL, 5)
|
btnSizer2.Add(cancel, 0, wx.ALL, 5)
|
||||||
sizer.Add(servicesBox, 0, wx.ALL, 5)
|
sizer.Add(servicesBox, 0, wx.ALL, 5)
|
||||||
sizer.Add(btnSizer, 0, wx.ALL, 5)
|
sizer.Add(btnSizer, 0, wx.ALL, 5)
|
||||||
sizer.Add(btnSizer2, 0, wx.ALL, 5)
|
sizer.Add(btnSizer2, 0, wx.ALL, 5)
|
||||||
panel.SetSizer(sizer)
|
panel.SetSizer(sizer)
|
||||||
self.SetClientSize(sizer.CalcMin())
|
self.SetClientSize(sizer.CalcMin())
|
||||||
|
|
||||||
def enable_control(self, control):
|
def enable_control(self, control):
|
||||||
log.debug("Enabling control %s" % (control,))
|
log.debug("Enabling control %s" % (control,))
|
||||||
if hasattr(self, control):
|
if hasattr(self, control):
|
||||||
getattr(self, control).Enable()
|
getattr(self, control).Enable()
|
||||||
|
|
||||||
def disable_control(self, control):
|
def disable_control(self, control):
|
||||||
log.debug("Disabling control %s" % (control,))
|
log.debug("Disabling control %s" % (control,))
|
||||||
if hasattr(self, control):
|
if hasattr(self, control):
|
||||||
getattr(self, control).Disable()
|
getattr(self, control).Disable()
|
||||||
|
|
||||||
def get_file(self):
|
def get_file(self):
|
||||||
openFileDialog = wx.FileDialog(self, _(u"Select the audio file to be uploaded"), "", "", _("Audio Files (*.mp3, *.ogg, *.wav)|*.mp3; *.ogg; *.wav"), wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)
|
openFileDialog = wx.FileDialog(self, _(u"Select the audio file to be uploaded"), "", "", _("Audio Files (*.mp3, *.ogg, *.wav)|*.mp3; *.ogg; *.wav"), wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)
|
||||||
if openFileDialog.ShowModal() == wx.ID_CANCEL:
|
if openFileDialog.ShowModal() == wx.ID_CANCEL:
|
||||||
return False
|
return False
|
||||||
return openFileDialog.GetPath()
|
return openFileDialog.GetPath()
|
||||||
|
@@ -4,23 +4,23 @@ from gi.repository import Gtk
|
|||||||
import widgetUtils
|
import widgetUtils
|
||||||
|
|
||||||
class soundsTutorialDialog(Gtk.Dialog):
|
class soundsTutorialDialog(Gtk.Dialog):
|
||||||
def __init__(self, actions):
|
def __init__(self, actions):
|
||||||
super(soundsTutorialDialog, self).__init__("Sounds tutorial", None, 0, (Gtk.STOCK_CANCEL, widgetUtils.CANCEL))
|
super(soundsTutorialDialog, self).__init__("Sounds tutorial", None, 0, (Gtk.STOCK_CANCEL, widgetUtils.CANCEL))
|
||||||
box = self.get_content_area()
|
box = self.get_content_area()
|
||||||
label = Gtk.Label("Press enter for listen the sound")
|
label = Gtk.Label("Press enter for listen the sound")
|
||||||
self.list = widgetUtils.list("Action")
|
self.list = widgetUtils.list("Action")
|
||||||
self.populate_actions(actions)
|
self.populate_actions(actions)
|
||||||
lBox = Gtk.Box(spacing=6)
|
lBox = Gtk.Box(spacing=6)
|
||||||
lBox.add(label)
|
lBox.add(label)
|
||||||
lBox.add(self.list.list)
|
lBox.add(self.list.list)
|
||||||
box.add(lBox)
|
box.add(lBox)
|
||||||
self.play = Gtk.Button("Play")
|
self.play = Gtk.Button("Play")
|
||||||
box.add(self.play)
|
box.add(self.play)
|
||||||
self.show_all()
|
self.show_all()
|
||||||
|
|
||||||
def populate_actions(self, actions):
|
def populate_actions(self, actions):
|
||||||
for i in actions:
|
for i in actions:
|
||||||
self.list.insert_item(i)
|
self.list.insert_item(i)
|
||||||
|
|
||||||
def get_selected(self):
|
def get_selected(self):
|
||||||
return self.list.get_selected()
|
return self.list.get_selected()
|
||||||
|
@@ -10,28 +10,28 @@ import logging
|
|||||||
log = logging.getLogger("extra.SoundsTutorial.soundsTutorial")
|
log = logging.getLogger("extra.SoundsTutorial.soundsTutorial")
|
||||||
from . import soundsTutorial_constants
|
from . import soundsTutorial_constants
|
||||||
if platform.system() == "Windows":
|
if platform.system() == "Windows":
|
||||||
from . import wx_ui as UI
|
from . import wx_ui as UI
|
||||||
elif platform.system() == "Linux":
|
elif platform.system() == "Linux":
|
||||||
from . import gtk_ui as UI
|
from . import gtk_ui as UI
|
||||||
|
|
||||||
class soundsTutorial(object):
|
class soundsTutorial(object):
|
||||||
def __init__(self, sessionObject):
|
def __init__(self, sessionObject):
|
||||||
log.debug("Creating sounds tutorial object...")
|
log.debug("Creating sounds tutorial object...")
|
||||||
super(soundsTutorial, self).__init__()
|
super(soundsTutorial, self).__init__()
|
||||||
self.session = sessionObject
|
self.session = sessionObject
|
||||||
self.actions = []
|
self.actions = []
|
||||||
log.debug("Loading actions for sounds tutorial...")
|
log.debug("Loading actions for sounds tutorial...")
|
||||||
[self.actions.append(i[1]) for i in soundsTutorial_constants.actions]
|
[self.actions.append(i[1]) for i in soundsTutorial_constants.actions]
|
||||||
self.files = []
|
self.files = []
|
||||||
log.debug("Searching sound files...")
|
log.debug("Searching sound files...")
|
||||||
[self.files.append(i[0]) for i in soundsTutorial_constants.actions]
|
[self.files.append(i[0]) for i in soundsTutorial_constants.actions]
|
||||||
log.debug("Creating dialog...")
|
log.debug("Creating dialog...")
|
||||||
self.dialog = UI.soundsTutorialDialog(self.actions)
|
self.dialog = UI.soundsTutorialDialog(self.actions)
|
||||||
widgetUtils.connect_event(self.dialog.play, widgetUtils.BUTTON_PRESSED, self.on_play)
|
widgetUtils.connect_event(self.dialog.play, widgetUtils.BUTTON_PRESSED, self.on_play)
|
||||||
self.dialog.get_response()
|
self.dialog.get_response()
|
||||||
|
|
||||||
def on_play(self, *args, **kwargs):
|
def on_play(self, *args, **kwargs):
|
||||||
try:
|
try:
|
||||||
self.session.sound.play(self.files[self.dialog.get_selection()]+".ogg")
|
self.session.sound.play(self.files[self.dialog.get_selection()]+".ogg")
|
||||||
except:
|
except:
|
||||||
log.exception("Error playing the %s sound" % (self.files[self.dialog.items.GetSelection()],))
|
log.exception("Error playing the %s sound" % (self.files[self.dialog.items.GetSelection()],))
|
||||||
|
@@ -5,27 +5,27 @@ from __future__ import unicode_literals
|
|||||||
from . import reverse_sort
|
from . import reverse_sort
|
||||||
import application
|
import application
|
||||||
actions = reverse_sort.reverse_sort([ ("audio", _(u"Audio tweet.")),
|
actions = reverse_sort.reverse_sort([ ("audio", _(u"Audio tweet.")),
|
||||||
("create_timeline", _(u"User timeline buffer created.")),
|
("create_timeline", _(u"User timeline buffer created.")),
|
||||||
("delete_timeline", _(u"Buffer destroied.")),
|
("delete_timeline", _(u"Buffer destroied.")),
|
||||||
("dm_received", _(u"Direct message received.")),
|
("dm_received", _(u"Direct message received.")),
|
||||||
("dm_sent", _(u"Direct message sent.")),
|
("dm_sent", _(u"Direct message sent.")),
|
||||||
("error", _(u"Error.")),
|
("error", _(u"Error.")),
|
||||||
("favourite", _(u"Tweet liked.")),
|
("favourite", _(u"Tweet liked.")),
|
||||||
("favourites_timeline_updated", _(u"Likes buffer updated.")),
|
("favourites_timeline_updated", _(u"Likes buffer updated.")),
|
||||||
("geo", _(u"Geotweet.")),
|
("geo", _(u"Geotweet.")),
|
||||||
("image", _("Tweet contains one or more images")),
|
("image", _("Tweet contains one or more images")),
|
||||||
("limit", _(u"Boundary reached.")),
|
("limit", _(u"Boundary reached.")),
|
||||||
("list_tweet", _(u"List updated.")),
|
("list_tweet", _(u"List updated.")),
|
||||||
("max_length", _(u"Too many characters.")),
|
("max_length", _(u"Too many characters.")),
|
||||||
("mention_received", _(u"Mention received.")),
|
("mention_received", _(u"Mention received.")),
|
||||||
("new_event", _(u"New event.")),
|
("new_event", _(u"New event.")),
|
||||||
("ready", _(u"{0} is ready.").format(application.name,)),
|
("ready", _(u"{0} is ready.").format(application.name,)),
|
||||||
("reply_send", _(u"Mention sent.")),
|
("reply_send", _(u"Mention sent.")),
|
||||||
("retweet_send", _(u"Tweet retweeted.")),
|
("retweet_send", _(u"Tweet retweeted.")),
|
||||||
("search_updated", _(u"Search buffer updated.")),
|
("search_updated", _(u"Search buffer updated.")),
|
||||||
("tweet_received", _(u"Tweet received.")),
|
("tweet_received", _(u"Tweet received.")),
|
||||||
("tweet_send", _(u"Tweet sent.")),
|
("tweet_send", _(u"Tweet sent.")),
|
||||||
("trends_updated", _(u"Trending topics buffer updated.")),
|
("trends_updated", _(u"Trending topics buffer updated.")),
|
||||||
("tweet_timeline", _(u"New tweet in user timeline buffer.")),
|
("tweet_timeline", _(u"New tweet in user timeline buffer.")),
|
||||||
("update_followers", _(u"New follower.")),
|
("update_followers", _(u"New follower.")),
|
||||||
("volume_changed", _(u"Volume changed."))])
|
("volume_changed", _(u"Volume changed."))])
|
||||||
|
@@ -4,27 +4,27 @@ import wx
|
|||||||
import widgetUtils
|
import widgetUtils
|
||||||
|
|
||||||
class soundsTutorialDialog(widgetUtils.BaseDialog):
|
class soundsTutorialDialog(widgetUtils.BaseDialog):
|
||||||
def __init__(self, actions):
|
def __init__(self, actions):
|
||||||
super(soundsTutorialDialog, self).__init__(None, -1)
|
super(soundsTutorialDialog, self).__init__(None, -1)
|
||||||
self.SetTitle(_(u"Sounds tutorial"))
|
self.SetTitle(_(u"Sounds tutorial"))
|
||||||
panel = wx.Panel(self)
|
panel = wx.Panel(self)
|
||||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||||
label = wx.StaticText(panel, -1, _(u"Press enter to listen to the sound for the selected event"))
|
label = wx.StaticText(panel, -1, _(u"Press enter to listen to the sound for the selected event"))
|
||||||
self.items = wx.ListBox(panel, 1, choices=actions, style=wx.LB_SINGLE)
|
self.items = wx.ListBox(panel, 1, choices=actions, style=wx.LB_SINGLE)
|
||||||
self.items.SetSelection(0)
|
self.items.SetSelection(0)
|
||||||
listBox = wx.BoxSizer(wx.HORIZONTAL)
|
listBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
listBox.Add(label)
|
listBox.Add(label)
|
||||||
listBox.Add(self.items)
|
listBox.Add(self.items)
|
||||||
self.play = wx.Button(panel, 1, (u"Play"))
|
self.play = wx.Button(panel, 1, (u"Play"))
|
||||||
self.play.SetDefault()
|
self.play.SetDefault()
|
||||||
close = wx.Button(panel, wx.ID_CANCEL)
|
close = wx.Button(panel, wx.ID_CANCEL)
|
||||||
btnBox = wx.BoxSizer(wx.HORIZONTAL)
|
btnBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
btnBox.Add(self.play)
|
btnBox.Add(self.play)
|
||||||
btnBox.Add(close)
|
btnBox.Add(close)
|
||||||
sizer.Add(listBox)
|
sizer.Add(listBox)
|
||||||
sizer.Add(btnBox)
|
sizer.Add(btnBox)
|
||||||
panel.SetSizer(sizer)
|
panel.SetSizer(sizer)
|
||||||
self.SetClientSize(sizer.CalcMin())
|
self.SetClientSize(sizer.CalcMin())
|
||||||
|
|
||||||
def get_selection(self):
|
def get_selection(self):
|
||||||
return self.items.GetSelection()
|
return self.items.GetSelection()
|
||||||
|
@@ -3,4 +3,4 @@ from __future__ import unicode_literals
|
|||||||
from . import spellchecker
|
from . import spellchecker
|
||||||
import platform
|
import platform
|
||||||
if platform.system() == "Windows":
|
if platform.system() == "Windows":
|
||||||
from .wx_ui import *
|
from .wx_ui import *
|
||||||
|
@@ -19,69 +19,69 @@ from enchant import tokenize
|
|||||||
log = logging.getLogger("extra.SpellChecker.spellChecker")
|
log = logging.getLogger("extra.SpellChecker.spellChecker")
|
||||||
|
|
||||||
class spellChecker(object):
|
class spellChecker(object):
|
||||||
def __init__(self, text, dictionary):
|
def __init__(self, text, dictionary):
|
||||||
super(spellChecker, self).__init__()
|
super(spellChecker, self).__init__()
|
||||||
# Set Dictionary path if not set in a previous call to this method.
|
# Set Dictionary path if not set in a previous call to this method.
|
||||||
# Dictionary path will be located in user config, see https://github.com/manuelcortez/twblue/issues/208
|
# Dictionary path will be located in user config, see https://github.com/manuelcortez/twblue/issues/208
|
||||||
# dict_path = enchant.get_param("enchant.myspell.dictionary.path")
|
# dict_path = enchant.get_param("enchant.myspell.dictionary.path")
|
||||||
# if dict_path == None:
|
# if dict_path == None:
|
||||||
# enchant.set_param("enchant.myspell.dictionary.path", os.path.join(paths.config_path(), "dicts"))
|
# enchant.set_param("enchant.myspell.dictionary.path", os.path.join(paths.config_path(), "dicts"))
|
||||||
# log.debug("Dictionary path set to %s" % (os.path.join(paths.config_path(), "dicts"),))
|
# log.debug("Dictionary path set to %s" % (os.path.join(paths.config_path(), "dicts"),))
|
||||||
log.debug("Creating the SpellChecker object. Dictionary: %s" % (dictionary,))
|
log.debug("Creating the SpellChecker object. Dictionary: %s" % (dictionary,))
|
||||||
self.active = True
|
self.active = True
|
||||||
try:
|
try:
|
||||||
if config.app["app-settings"]["language"] == "system":
|
if config.app["app-settings"]["language"] == "system":
|
||||||
log.debug("Using the system language")
|
log.debug("Using the system language")
|
||||||
self.dict = enchant.DictWithPWL(languageHandler.curLang[:2], os.path.join(paths.config_path(), "wordlist.dict"))
|
self.dict = enchant.DictWithPWL(languageHandler.curLang[:2], os.path.join(paths.config_path(), "wordlist.dict"))
|
||||||
else:
|
else:
|
||||||
log.debug("Using language: %s" % (languageHandler.getLanguage(),))
|
log.debug("Using language: %s" % (languageHandler.getLanguage(),))
|
||||||
self.dict = enchant.DictWithPWL(languageHandler.getLanguage()[:2], os.path.join(paths.config_path(), "wordlist.dict"))
|
self.dict = enchant.DictWithPWL(languageHandler.getLanguage()[:2], os.path.join(paths.config_path(), "wordlist.dict"))
|
||||||
except DictNotFoundError:
|
except DictNotFoundError:
|
||||||
log.exception("Dictionary for language %s not found." % (dictionary,))
|
log.exception("Dictionary for language %s not found." % (dictionary,))
|
||||||
wx_ui.dict_not_found_error()
|
wx_ui.dict_not_found_error()
|
||||||
self.active = False
|
self.active = False
|
||||||
self.checker = SpellChecker(self.dict, filters=[twitterFilter.TwitterFilter, tokenize.EmailFilter, tokenize.URLFilter])
|
self.checker = SpellChecker(self.dict, filters=[twitterFilter.TwitterFilter, tokenize.EmailFilter, tokenize.URLFilter])
|
||||||
self.checker.set_text(text)
|
self.checker.set_text(text)
|
||||||
if self.active == True:
|
if self.active == True:
|
||||||
log.debug("Creating dialog...")
|
log.debug("Creating dialog...")
|
||||||
self.dialog = wx_ui.spellCheckerDialog()
|
self.dialog = wx_ui.spellCheckerDialog()
|
||||||
widgetUtils.connect_event(self.dialog.ignore, widgetUtils.BUTTON_PRESSED, self.ignore)
|
widgetUtils.connect_event(self.dialog.ignore, widgetUtils.BUTTON_PRESSED, self.ignore)
|
||||||
widgetUtils.connect_event(self.dialog.ignoreAll, widgetUtils.BUTTON_PRESSED, self.ignoreAll)
|
widgetUtils.connect_event(self.dialog.ignoreAll, widgetUtils.BUTTON_PRESSED, self.ignoreAll)
|
||||||
widgetUtils.connect_event(self.dialog.replace, widgetUtils.BUTTON_PRESSED, self.replace)
|
widgetUtils.connect_event(self.dialog.replace, widgetUtils.BUTTON_PRESSED, self.replace)
|
||||||
widgetUtils.connect_event(self.dialog.replaceAll, widgetUtils.BUTTON_PRESSED, self.replaceAll)
|
widgetUtils.connect_event(self.dialog.replaceAll, widgetUtils.BUTTON_PRESSED, self.replaceAll)
|
||||||
widgetUtils.connect_event(self.dialog.add, widgetUtils.BUTTON_PRESSED, self.add)
|
widgetUtils.connect_event(self.dialog.add, widgetUtils.BUTTON_PRESSED, self.add)
|
||||||
self.check()
|
self.check()
|
||||||
self.dialog.get_response()
|
self.dialog.get_response()
|
||||||
self.fixed_text = self.checker.get_text()
|
self.fixed_text = self.checker.get_text()
|
||||||
|
|
||||||
def check(self):
|
def check(self):
|
||||||
try:
|
try:
|
||||||
next(self.checker)
|
next(self.checker)
|
||||||
textToSay = _(u"Misspelled word: %s") % (self.checker.word,)
|
textToSay = _(u"Misspelled word: %s") % (self.checker.word,)
|
||||||
context = u"... %s %s %s" % (self.checker.leading_context(10), self.checker.word, self.checker.trailing_context(10))
|
context = u"... %s %s %s" % (self.checker.leading_context(10), self.checker.word, self.checker.trailing_context(10))
|
||||||
self.dialog.set_title(textToSay)
|
self.dialog.set_title(textToSay)
|
||||||
output.speak(textToSay)
|
output.speak(textToSay)
|
||||||
self.dialog.set_word_and_suggestions(word=self.checker.word, context=context, suggestions=self.checker.suggest())
|
self.dialog.set_word_and_suggestions(word=self.checker.word, context=context, suggestions=self.checker.suggest())
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
log.debug("Process finished.")
|
log.debug("Process finished.")
|
||||||
wx_ui.finished()
|
wx_ui.finished()
|
||||||
self.dialog.Destroy()
|
self.dialog.Destroy()
|
||||||
|
|
||||||
def ignore(self, ev):
|
def ignore(self, ev):
|
||||||
self.check()
|
self.check()
|
||||||
|
|
||||||
def ignoreAll(self, ev):
|
def ignoreAll(self, ev):
|
||||||
self.checker.ignore_always(word=self.checker.word)
|
self.checker.ignore_always(word=self.checker.word)
|
||||||
self.check()
|
self.check()
|
||||||
|
|
||||||
def replace(self, ev):
|
def replace(self, ev):
|
||||||
self.checker.replace(self.dialog.get_selected_suggestion())
|
self.checker.replace(self.dialog.get_selected_suggestion())
|
||||||
self.check()
|
self.check()
|
||||||
|
|
||||||
def replaceAll(self, ev):
|
def replaceAll(self, ev):
|
||||||
self.checker.replace_always(self.dialog.get_selected_suggestion())
|
self.checker.replace_always(self.dialog.get_selected_suggestion())
|
||||||
self.check()
|
self.check()
|
||||||
|
|
||||||
def add(self, ev):
|
def add(self, ev):
|
||||||
self.checker.add()
|
self.checker.add()
|
||||||
self.check()
|
self.check()
|
||||||
|
@@ -21,63 +21,63 @@ import wx
|
|||||||
import application
|
import application
|
||||||
|
|
||||||
class spellCheckerDialog(wx.Dialog):
|
class spellCheckerDialog(wx.Dialog):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(spellCheckerDialog, self).__init__(None, 1)
|
super(spellCheckerDialog, self).__init__(None, 1)
|
||||||
panel = wx.Panel(self)
|
panel = wx.Panel(self)
|
||||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||||
word = wx.StaticText(panel, -1, _(u"Misspelled word"))
|
word = wx.StaticText(panel, -1, _(u"Misspelled word"))
|
||||||
self.word = wx.TextCtrl(panel, -1)
|
self.word = wx.TextCtrl(panel, -1)
|
||||||
wordBox = wx.BoxSizer(wx.HORIZONTAL)
|
wordBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
wordBox.Add(word, 0, wx.ALL, 5)
|
wordBox.Add(word, 0, wx.ALL, 5)
|
||||||
wordBox.Add(self.word, 0, wx.ALL, 5)
|
wordBox.Add(self.word, 0, wx.ALL, 5)
|
||||||
context = wx.StaticText(panel, -1, _(u"Context"))
|
context = wx.StaticText(panel, -1, _(u"Context"))
|
||||||
self.context = wx.TextCtrl(panel, -1)
|
self.context = wx.TextCtrl(panel, -1)
|
||||||
contextBox = wx.BoxSizer(wx.HORIZONTAL)
|
contextBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
contextBox.Add(context, 0, wx.ALL, 5)
|
contextBox.Add(context, 0, wx.ALL, 5)
|
||||||
contextBox.Add(self.context, 0, wx.ALL, 5)
|
contextBox.Add(self.context, 0, wx.ALL, 5)
|
||||||
suggest = wx.StaticText(panel, -1, _(u"Suggestions"))
|
suggest = wx.StaticText(panel, -1, _(u"Suggestions"))
|
||||||
self.suggestions = wx.ListBox(panel, -1, choices=[], style=wx.LB_SINGLE)
|
self.suggestions = wx.ListBox(panel, -1, choices=[], style=wx.LB_SINGLE)
|
||||||
suggestionsBox = wx.BoxSizer(wx.HORIZONTAL)
|
suggestionsBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
suggestionsBox.Add(suggest, 0, wx.ALL, 5)
|
suggestionsBox.Add(suggest, 0, wx.ALL, 5)
|
||||||
suggestionsBox.Add(self.suggestions, 0, wx.ALL, 5)
|
suggestionsBox.Add(self.suggestions, 0, wx.ALL, 5)
|
||||||
self.ignore = wx.Button(panel, -1, _(u"&Ignore"))
|
self.ignore = wx.Button(panel, -1, _(u"&Ignore"))
|
||||||
self.ignoreAll = wx.Button(panel, -1, _(u"I&gnore all"))
|
self.ignoreAll = wx.Button(panel, -1, _(u"I&gnore all"))
|
||||||
self.replace = wx.Button(panel, -1, _(u"&Replace"))
|
self.replace = wx.Button(panel, -1, _(u"&Replace"))
|
||||||
self.replaceAll = wx.Button(panel, -1, _(u"R&eplace all"))
|
self.replaceAll = wx.Button(panel, -1, _(u"R&eplace all"))
|
||||||
self.add = wx.Button(panel, -1, _(u"&Add to personal dictionary"))
|
self.add = wx.Button(panel, -1, _(u"&Add to personal dictionary"))
|
||||||
close = wx.Button(panel, wx.ID_CANCEL)
|
close = wx.Button(panel, wx.ID_CANCEL)
|
||||||
btnBox = wx.BoxSizer(wx.HORIZONTAL)
|
btnBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
btnBox.Add(self.ignore, 0, wx.ALL, 5)
|
btnBox.Add(self.ignore, 0, wx.ALL, 5)
|
||||||
btnBox.Add(self.ignoreAll, 0, wx.ALL, 5)
|
btnBox.Add(self.ignoreAll, 0, wx.ALL, 5)
|
||||||
btnBox.Add(self.replace, 0, wx.ALL, 5)
|
btnBox.Add(self.replace, 0, wx.ALL, 5)
|
||||||
btnBox.Add(self.replaceAll, 0, wx.ALL, 5)
|
btnBox.Add(self.replaceAll, 0, wx.ALL, 5)
|
||||||
btnBox.Add(self.add, 0, wx.ALL, 5)
|
btnBox.Add(self.add, 0, wx.ALL, 5)
|
||||||
btnBox.Add(close, 0, wx.ALL, 5)
|
btnBox.Add(close, 0, wx.ALL, 5)
|
||||||
sizer.Add(wordBox, 0, wx.ALL, 5)
|
sizer.Add(wordBox, 0, wx.ALL, 5)
|
||||||
sizer.Add(contextBox, 0, wx.ALL, 5)
|
sizer.Add(contextBox, 0, wx.ALL, 5)
|
||||||
sizer.Add(suggestionsBox, 0, wx.ALL, 5)
|
sizer.Add(suggestionsBox, 0, wx.ALL, 5)
|
||||||
sizer.Add(btnBox, 0, wx.ALL, 5)
|
sizer.Add(btnBox, 0, wx.ALL, 5)
|
||||||
panel.SetSizer(sizer)
|
panel.SetSizer(sizer)
|
||||||
self.SetClientSize(sizer.CalcMin())
|
self.SetClientSize(sizer.CalcMin())
|
||||||
|
|
||||||
|
|
||||||
def get_response(self):
|
def get_response(self):
|
||||||
return self.ShowModal()
|
return self.ShowModal()
|
||||||
|
|
||||||
def set_title(self, title):
|
def set_title(self, title):
|
||||||
return self.SetTitle(title)
|
return self.SetTitle(title)
|
||||||
|
|
||||||
def set_word_and_suggestions(self, word, context, suggestions):
|
def set_word_and_suggestions(self, word, context, suggestions):
|
||||||
self.word.SetValue(word)
|
self.word.SetValue(word)
|
||||||
self.context.ChangeValue(context)
|
self.context.ChangeValue(context)
|
||||||
self.suggestions.Set(suggestions)
|
self.suggestions.Set(suggestions)
|
||||||
self.suggestions.SetFocus()
|
self.suggestions.SetFocus()
|
||||||
|
|
||||||
def get_selected_suggestion(self):
|
def get_selected_suggestion(self):
|
||||||
return self.suggestions.GetStringSelection()
|
return self.suggestions.GetStringSelection()
|
||||||
|
|
||||||
def dict_not_found_error():
|
def dict_not_found_error():
|
||||||
wx.MessageDialog(None, _(u"An error has occurred. There are no dictionaries available for the selected language in {0}").format(application.name,), _(u"Error"), wx.ICON_ERROR).ShowModal()
|
wx.MessageDialog(None, _(u"An error has occurred. There are no dictionaries available for the selected language in {0}").format(application.name,), _(u"Error"), wx.ICON_ERROR).ShowModal()
|
||||||
|
|
||||||
def finished():
|
def finished():
|
||||||
wx.MessageDialog(None, _(u"Spell check complete."), application.name, style=wx.OK).ShowModal()
|
wx.MessageDialog(None, _(u"Spell check complete."), application.name, style=wx.OK).ShowModal()
|
||||||
|
@@ -1,50 +1,47 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
from builtins import object
|
|
||||||
import output
|
import output
|
||||||
from . import storage
|
from . import storage
|
||||||
from . import wx_menu
|
from . import wx_menu
|
||||||
|
|
||||||
class autocompletionUsers(object):
|
class autocompletionUsers(object):
|
||||||
def __init__(self, window, session_id):
|
def __init__(self, window, session_id):
|
||||||
super(autocompletionUsers, self).__init__()
|
super(autocompletionUsers, self).__init__()
|
||||||
self.window = window
|
self.window = window
|
||||||
self.db = storage.storage(session_id)
|
self.db = storage.storage(session_id)
|
||||||
|
|
||||||
def show_menu(self, mode="tweet"):
|
def show_menu(self, mode="tweet"):
|
||||||
position = self.window.get_position()
|
position = self.window.get_position()
|
||||||
if mode == "tweet":
|
if mode == "tweet":
|
||||||
text = self.window.get_text()
|
text = self.window.get_text()
|
||||||
text = text[:position]
|
text = text[:position]
|
||||||
try:
|
try:
|
||||||
pattern = text.split()[-1]
|
pattern = text.split()[-1]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
output.speak(_(u"You have to start writing"))
|
output.speak(_(u"You have to start writing"))
|
||||||
return
|
return
|
||||||
if pattern.startswith("@") == True:
|
if pattern.startswith("@") == True:
|
||||||
menu = wx_menu.menu(self.window.text, pattern[1:], mode=mode)
|
menu = wx_menu.menu(self.window.text, pattern[1:], mode=mode)
|
||||||
users = self.db.get_users(pattern[1:])
|
users = self.db.get_users(pattern[1:])
|
||||||
if len(users) > 0:
|
if len(users) > 0:
|
||||||
menu.append_options(users)
|
menu.append_options(users)
|
||||||
self.window.popup_menu(menu)
|
self.window.popup_menu(menu)
|
||||||
menu.destroy()
|
menu.destroy()
|
||||||
else:
|
else:
|
||||||
output.speak(_(u"There are no results in your users database"))
|
output.speak(_(u"There are no results in your users database"))
|
||||||
else:
|
else:
|
||||||
output.speak(_(u"Autocompletion only works for users."))
|
output.speak(_(u"Autocompletion only works for users."))
|
||||||
elif mode == "dm":
|
elif mode == "dm":
|
||||||
text = self.window.get_user()
|
text = self.window.get_user()
|
||||||
try:
|
try:
|
||||||
pattern = text.split()[-1]
|
pattern = text.split()[-1]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
output.speak(_(u"You have to start writing"))
|
output.speak(_(u"You have to start writing"))
|
||||||
return
|
return
|
||||||
menu = wx_menu.menu(self.window.cb, pattern, mode=mode)
|
menu = wx_menu.menu(self.window.cb, pattern, mode=mode)
|
||||||
users = self.db.get_users(pattern)
|
users = self.db.get_users(pattern)
|
||||||
if len(users) > 0:
|
if len(users) > 0:
|
||||||
menu.append_options(users)
|
menu.append_options(users)
|
||||||
self.window.popup_menu(menu)
|
self.window.popup_menu(menu)
|
||||||
menu.destroy()
|
menu.destroy()
|
||||||
else:
|
else:
|
||||||
output.speak(_(u"There are no results in your users database"))
|
output.speak(_(u"There are no results in your users database"))
|
||||||
|
@@ -1,47 +1,42 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from builtins import object
|
|
||||||
from . import storage
|
|
||||||
import widgetUtils
|
import widgetUtils
|
||||||
from . import wx_manage
|
from . import storage, wx_manage
|
||||||
from wxUI import commonMessageDialogs
|
from wxUI import commonMessageDialogs
|
||||||
|
|
||||||
class autocompletionManage(object):
|
class autocompletionManage(object):
|
||||||
def __init__(self, session):
|
def __init__(self, session):
|
||||||
super(autocompletionManage, self).__init__()
|
super(autocompletionManage, self).__init__()
|
||||||
self.session = session
|
self.session = session
|
||||||
self.dialog = wx_manage.autocompletionManageDialog()
|
self.dialog = wx_manage.autocompletionManageDialog()
|
||||||
self.database = storage.storage(self.session.session_id)
|
self.database = storage.storage(self.session.session_id)
|
||||||
self.users = self.database.get_all_users()
|
self.users = self.database.get_all_users()
|
||||||
self.dialog.put_users(self.users)
|
self.dialog.put_users(self.users)
|
||||||
widgetUtils.connect_event(self.dialog.add, widgetUtils.BUTTON_PRESSED, self.add_user)
|
widgetUtils.connect_event(self.dialog.add, widgetUtils.BUTTON_PRESSED, self.add_user)
|
||||||
widgetUtils.connect_event(self.dialog.remove, widgetUtils.BUTTON_PRESSED, self.remove_user)
|
widgetUtils.connect_event(self.dialog.remove, widgetUtils.BUTTON_PRESSED, self.remove_user)
|
||||||
self.dialog.get_response()
|
self.dialog.get_response()
|
||||||
|
|
||||||
def update_list(self):
|
def update_list(self):
|
||||||
item = self.dialog.users.get_selected()
|
item = self.dialog.users.get_selected()
|
||||||
self.dialog.users.clear()
|
self.dialog.users.clear()
|
||||||
self.users = self.database.get_all_users()
|
self.users = self.database.get_all_users()
|
||||||
self.dialog.put_users(self.users)
|
self.dialog.put_users(self.users)
|
||||||
self.dialog.users.select_item(item)
|
self.dialog.users.select_item(item)
|
||||||
|
|
||||||
def add_user(self, *args, **kwargs):
|
def add_user(self, *args, **kwargs):
|
||||||
usr = self.dialog.get_user()
|
usr = self.dialog.get_user()
|
||||||
if usr == False:
|
if usr == False:
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
data = self.session.twitter.twitter.show_user(screen_name=usr)
|
data = self.session.twitter.twitter.get_user(screen_name=usr)
|
||||||
except:
|
except:
|
||||||
self.dialog.show_invalid_user_error()
|
self.dialog.show_invalid_user_error()
|
||||||
return
|
return
|
||||||
self.database.set_user(data["screen_name"], data["name"], 0)
|
self.database.set_user(data.screen_name, data.name, 0)
|
||||||
self.update_list()
|
self.update_list()
|
||||||
|
|
||||||
def remove_user(self, ev):
|
def remove_user(self, ev):
|
||||||
if commonMessageDialogs.delete_user_from_db() == widgetUtils.YES:
|
if commonMessageDialogs.delete_user_from_db() == widgetUtils.YES:
|
||||||
item = self.dialog.users.get_selected()
|
item = self.dialog.users.get_selected()
|
||||||
user = self.users[item]
|
user = self.users[item]
|
||||||
self.database.remove_user(user[0])
|
self.database.remove_user(user[0])
|
||||||
self.update_list()
|
self.update_list()
|
||||||
|
@@ -1,63 +1,59 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from builtins import object
|
|
||||||
from . import storage
|
|
||||||
import widgetUtils
|
import widgetUtils
|
||||||
|
import output
|
||||||
from . import wx_settings
|
from . import wx_settings
|
||||||
from . import manage
|
from . import manage
|
||||||
import output
|
from . import storage
|
||||||
from mysc.thread_utils import call_threaded
|
from mysc.thread_utils import call_threaded
|
||||||
|
|
||||||
class autocompletionSettings(object):
|
class autocompletionSettings(object):
|
||||||
def __init__(self, config, buffer, window):
|
def __init__(self, config, buffer, window):
|
||||||
super(autocompletionSettings, self).__init__()
|
super(autocompletionSettings, self).__init__()
|
||||||
self.config = config
|
self.config = config
|
||||||
self.buffer = buffer
|
self.buffer = buffer
|
||||||
self.window = window
|
self.window = window
|
||||||
self.dialog = wx_settings.autocompletionSettingsDialog()
|
self.dialog = wx_settings.autocompletionSettingsDialog()
|
||||||
self.dialog.set("friends_buffer", self.config["mysc"]["save_friends_in_autocompletion_db"])
|
self.dialog.set("friends_buffer", self.config["mysc"]["save_friends_in_autocompletion_db"])
|
||||||
self.dialog.set("followers_buffer", self.config["mysc"]["save_followers_in_autocompletion_db"])
|
self.dialog.set("followers_buffer", self.config["mysc"]["save_followers_in_autocompletion_db"])
|
||||||
widgetUtils.connect_event(self.dialog.viewList, widgetUtils.BUTTON_PRESSED, self.view_list)
|
widgetUtils.connect_event(self.dialog.viewList, widgetUtils.BUTTON_PRESSED, self.view_list)
|
||||||
if self.dialog.get_response() == widgetUtils.OK:
|
if self.dialog.get_response() == widgetUtils.OK:
|
||||||
call_threaded(self.add_users_to_database)
|
call_threaded(self.add_users_to_database)
|
||||||
|
|
||||||
def add_users_to_database(self):
|
def add_users_to_database(self):
|
||||||
self.config["mysc"]["save_friends_in_autocompletion_db"] = self.dialog.get("friends_buffer")
|
self.config["mysc"]["save_friends_in_autocompletion_db"] = self.dialog.get("friends_buffer")
|
||||||
self.config["mysc"]["save_followers_in_autocompletion_db"] = self.dialog.get("followers_buffer")
|
self.config["mysc"]["save_followers_in_autocompletion_db"] = self.dialog.get("followers_buffer")
|
||||||
output.speak(_(u"Updating database... You can close this window now. A message will tell you when the process finishes."))
|
output.speak(_(u"Updating database... You can close this window now. A message will tell you when the process finishes."))
|
||||||
database = storage.storage(self.buffer.session.session_id)
|
database = storage.storage(self.buffer.session.session_id)
|
||||||
if self.dialog.get("followers_buffer") == True:
|
if self.dialog.get("followers_buffer") == True:
|
||||||
buffer = self.window.search_buffer("followers", self.config["twitter"]["user_name"])
|
buffer = self.window.search_buffer("followers", self.config["twitter"]["user_name"])
|
||||||
for i in buffer.session.db[buffer.name]["items"]:
|
for i in buffer.session.db[buffer.name]:
|
||||||
database.set_user(i["screen_name"], i["name"], 1)
|
database.set_user(i.screen_name, i.name, 1)
|
||||||
else:
|
else:
|
||||||
database.remove_by_buffer(1)
|
database.remove_by_buffer(1)
|
||||||
if self.dialog.get("friends_buffer") == True:
|
if self.dialog.get("friends_buffer") == True:
|
||||||
buffer = self.window.search_buffer("friends", self.config["twitter"]["user_name"])
|
buffer = self.window.search_buffer("friends", self.config["twitter"]["user_name"])
|
||||||
for i in buffer.session.db[buffer.name]["items"]:
|
for i in buffer.session.db[buffer.name]:
|
||||||
database.set_user(i["screen_name"], i["name"], 2)
|
database.set_user(i.screen_name, i.name, 2)
|
||||||
else:
|
else:
|
||||||
database.remove_by_buffer(2)
|
database.remove_by_buffer(2)
|
||||||
wx_settings.show_success_dialog()
|
wx_settings.show_success_dialog()
|
||||||
self.dialog.destroy()
|
self.dialog.destroy()
|
||||||
|
|
||||||
def view_list(self, ev):
|
def view_list(self, ev):
|
||||||
q = manage.autocompletionManage(self.buffer.session)
|
q = manage.autocompletionManage(self.buffer.session)
|
||||||
|
|
||||||
|
|
||||||
def execute_at_startup(window, buffer, config):
|
def execute_at_startup(window, buffer, config):
|
||||||
database = storage.storage(buffer.session.session_id)
|
database = storage.storage(buffer.session.session_id)
|
||||||
if config["mysc"]["save_followers_in_autocompletion_db"] == True and config["other_buffers"]["show_followers"] == True:
|
if config["mysc"]["save_followers_in_autocompletion_db"] == True and config["other_buffers"]["show_followers"] == True:
|
||||||
buffer = window.search_buffer("followers", config["twitter"]["user_name"])
|
buffer = window.search_buffer("followers", config["twitter"]["user_name"])
|
||||||
for i in buffer.session.db[buffer.name]:
|
for i in buffer.session.db[buffer.name]:
|
||||||
database.set_user(i["screen_name"], i["name"], 1)
|
database.set_user(i.screen_name, i.name, 1)
|
||||||
else:
|
else:
|
||||||
database.remove_by_buffer(1)
|
database.remove_by_buffer(1)
|
||||||
if config["mysc"]["save_friends_in_autocompletion_db"] == True and config["other_buffers"]["show_friends"] == True:
|
if config["mysc"]["save_friends_in_autocompletion_db"] == True and config["other_buffers"]["show_friends"] == True:
|
||||||
buffer = window.search_buffer("friends", config["twitter"]["user_name"])
|
buffer = window.search_buffer("friends", config["twitter"]["user_name"])
|
||||||
for i in buffer.session.db[buffer.name]:
|
for i in buffer.session.db[buffer.name]:
|
||||||
database.set_user(i["screen_name"], i["name"], 2)
|
database.set_user(i.screen_name, i.name, 2)
|
||||||
else:
|
else:
|
||||||
database.remove_by_buffer(2)
|
database.remove_by_buffer(2)
|
||||||
|
@@ -1,54 +1,52 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
import os, sqlite3, paths
|
||||||
from builtins import object
|
|
||||||
import sqlite3, paths
|
|
||||||
|
|
||||||
class storage(object):
|
class storage(object):
|
||||||
def __init__(self, session_id):
|
def __init__(self, session_id):
|
||||||
self.connection = sqlite3.connect(paths.config_path("%s/autocompletionUsers.dat" % (session_id)))
|
self.connection = sqlite3.connect(os.path.join(paths.config_path(), "%s/autocompletionUsers.dat" % (session_id)))
|
||||||
self.cursor = self.connection.cursor()
|
self.cursor = self.connection.cursor()
|
||||||
if self.table_exist("users") == False:
|
if self.table_exist("users") == False:
|
||||||
self.create_table()
|
self.create_table()
|
||||||
|
|
||||||
def table_exist(self, table):
|
def table_exist(self, table):
|
||||||
ask = self.cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='%s'" % (table))
|
ask = self.cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='%s'" % (table))
|
||||||
answer = ask.fetchone()
|
answer = ask.fetchone()
|
||||||
if answer == None:
|
if answer == None:
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def get_all_users(self):
|
def get_all_users(self):
|
||||||
self.cursor.execute("""select * from users""")
|
self.cursor.execute("""select * from users""")
|
||||||
return self.cursor.fetchall()
|
return self.cursor.fetchall()
|
||||||
|
|
||||||
def get_users(self, term):
|
def get_users(self, term):
|
||||||
self.cursor.execute("""SELECT * FROM users WHERE user LIKE ?""", ('{}%'.format(term),))
|
self.cursor.execute("""SELECT * FROM users WHERE user LIKE ?""", ('{}%'.format(term),))
|
||||||
return self.cursor.fetchall()
|
return self.cursor.fetchall()
|
||||||
|
|
||||||
def set_user(self, screen_name, user_name, from_a_buffer):
|
def set_user(self, screen_name, user_name, from_a_buffer):
|
||||||
self.cursor.execute("""insert or ignore into users values(?, ?, ?)""", (screen_name, user_name, from_a_buffer))
|
self.cursor.execute("""insert or ignore into users values(?, ?, ?)""", (screen_name, user_name, from_a_buffer))
|
||||||
self.connection.commit()
|
self.connection.commit()
|
||||||
|
|
||||||
def remove_user(self, user):
|
def remove_user(self, user):
|
||||||
self.cursor.execute("""DELETE FROM users WHERE user = ?""", (user,))
|
self.cursor.execute("""DELETE FROM users WHERE user = ?""", (user,))
|
||||||
self.connection.commit()
|
self.connection.commit()
|
||||||
return self.cursor.fetchone()
|
return self.cursor.fetchone()
|
||||||
|
|
||||||
def remove_by_buffer(self, bufferType):
|
def remove_by_buffer(self, bufferType):
|
||||||
""" Removes all users saved on a buffer. BufferType is 0 for no buffer, 1 for friends and 2 for followers"""
|
""" Removes all users saved on a buffer. BufferType is 0 for no buffer, 1 for friends and 2 for followers"""
|
||||||
self.cursor.execute("""DELETE FROM users WHERE from_a_buffer = ?""", (bufferType,))
|
self.cursor.execute("""DELETE FROM users WHERE from_a_buffer = ?""", (bufferType,))
|
||||||
self.connection.commit()
|
self.connection.commit()
|
||||||
return self.cursor.fetchone()
|
return self.cursor.fetchone()
|
||||||
|
|
||||||
def create_table(self):
|
def create_table(self):
|
||||||
self.cursor.execute("""
|
self.cursor.execute("""
|
||||||
create table users(
|
create table users(
|
||||||
user TEXT UNIQUE,
|
user TEXT UNIQUE,
|
||||||
name TEXT,
|
name TEXT,
|
||||||
from_a_buffer INTEGER
|
from_a_buffer INTEGER
|
||||||
)""")
|
)""")
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
self.cursor.close()
|
self.cursor.close()
|
||||||
self.connection.close()
|
self.connection.close()
|
||||||
|
@@ -1,44 +1,44 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
|
||||||
import wx
|
import wx
|
||||||
import widgetUtils
|
import widgetUtils
|
||||||
from multiplatform_widgets import widgets
|
from multiplatform_widgets import widgets
|
||||||
import application
|
import application
|
||||||
|
|
||||||
class autocompletionManageDialog(widgetUtils.BaseDialog):
|
class autocompletionManageDialog(widgetUtils.BaseDialog):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(autocompletionManageDialog, self).__init__(parent=None, id=-1, title=_(u"Manage Autocompletion database"))
|
super(autocompletionManageDialog, self).__init__(parent=None, id=-1, title=_(u"Manage Autocompletion database"))
|
||||||
panel = wx.Panel(self)
|
panel = wx.Panel(self)
|
||||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||||
label = wx.StaticText(panel, -1, _(u"Editing {0} users database").format(application.name,))
|
label = wx.StaticText(panel, -1, _(u"Editing {0} users database").format(application.name,))
|
||||||
self.users = widgets.list(panel, _(u"Username"), _(u"Name"), style=wx.LC_REPORT)
|
self.users = widgets.list(panel, _(u"Username"), _(u"Name"), style=wx.LC_REPORT)
|
||||||
sizer.Add(label, 0, wx.ALL, 5)
|
sizer.Add(label, 0, wx.ALL, 5)
|
||||||
sizer.Add(self.users.list, 0, wx.ALL, 5)
|
sizer.Add(self.users.list, 0, wx.ALL, 5)
|
||||||
self.add = wx.Button(panel, -1, _(u"Add user"))
|
self.add = wx.Button(panel, -1, _(u"Add user"))
|
||||||
self.remove = wx.Button(panel, -1, _(u"Remove user"))
|
self.remove = wx.Button(panel, -1, _(u"Remove user"))
|
||||||
optionsBox = wx.BoxSizer(wx.HORIZONTAL)
|
optionsBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
optionsBox.Add(self.add, 0, wx.ALL, 5)
|
optionsBox.Add(self.add, 0, wx.ALL, 5)
|
||||||
optionsBox.Add(self.remove, 0, wx.ALL, 5)
|
optionsBox.Add(self.remove, 0, wx.ALL, 5)
|
||||||
sizer.Add(optionsBox, 0, wx.ALL, 5)
|
sizer.Add(optionsBox, 0, wx.ALL, 5)
|
||||||
ok = wx.Button(panel, wx.ID_OK)
|
ok = wx.Button(panel, wx.ID_OK)
|
||||||
cancel = wx.Button(panel, wx.ID_CANCEL)
|
cancel = wx.Button(panel, wx.ID_CANCEL)
|
||||||
sizerBtn = wx.BoxSizer(wx.HORIZONTAL)
|
sizerBtn = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
sizerBtn.Add(ok, 0, wx.ALL, 5)
|
sizerBtn.Add(ok, 0, wx.ALL, 5)
|
||||||
sizer.Add(cancel, 0, wx.ALL, 5)
|
sizer.Add(cancel, 0, wx.ALL, 5)
|
||||||
sizer.Add(sizerBtn, 0, wx.ALL, 5)
|
sizer.Add(sizerBtn, 0, wx.ALL, 5)
|
||||||
panel.SetSizer(sizer)
|
panel.SetSizer(sizer)
|
||||||
self.SetClientSize(sizer.CalcMin())
|
self.SetClientSize(sizer.CalcMin())
|
||||||
|
|
||||||
def put_users(self, users):
|
def put_users(self, users):
|
||||||
for i in users:
|
for i in users:
|
||||||
j = [i[0], i[1]]
|
j = [i[0], i[1]]
|
||||||
self.users.insert_item(False, *j)
|
self.users.insert_item(False, *j)
|
||||||
|
|
||||||
def get_user(self):
|
def get_user(self):
|
||||||
usr = False
|
usr = False
|
||||||
userDlg = wx.TextEntryDialog(None, _(u"Twitter username"), _(u"Add user to database"))
|
userDlg = wx.TextEntryDialog(None, _(u"Twitter username"), _(u"Add user to database"))
|
||||||
if userDlg.ShowModal() == wx.ID_OK:
|
if userDlg.ShowModal() == wx.ID_OK:
|
||||||
usr = userDlg.GetValue()
|
usr = userDlg.GetValue()
|
||||||
return usr
|
return usr
|
||||||
|
|
||||||
def show_invalid_user_error(self):
|
def show_invalid_user_error(self):
|
||||||
wx.MessageDialog(None, _(u"The user does not exist"), _(u"Error!"), wx.ICON_ERROR).ShowModal()
|
wx.MessageDialog(None, _(u"The user does not exist"), _(u"Error!"), wx.ICON_ERROR).ShowModal()
|
||||||
|
@@ -1,26 +1,25 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
|
||||||
import wx
|
import wx
|
||||||
|
|
||||||
class menu(wx.Menu):
|
class menu(wx.Menu):
|
||||||
def __init__(self, window, pattern, mode):
|
def __init__(self, window, pattern, mode):
|
||||||
super(menu, self).__init__()
|
super(menu, self).__init__()
|
||||||
self.window = window
|
self.window = window
|
||||||
self.pattern = pattern
|
self.pattern = pattern
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
|
|
||||||
def append_options(self, options):
|
def append_options(self, options):
|
||||||
for i in options:
|
for i in options:
|
||||||
item = wx.MenuItem(self, wx.ID_ANY, "%s (@%s)" % (i[1], i[0]))
|
item = wx.MenuItem(self, wx.ID_ANY, "%s (@%s)" % (i[1], i[0]))
|
||||||
self.AppendItem(item)
|
self.AppendItem(item)
|
||||||
self.Bind(wx.EVT_MENU, lambda evt, temp=i[0]: self.select_text(evt, temp), item)
|
self.Bind(wx.EVT_MENU, lambda evt, temp=i[0]: self.select_text(evt, temp), item)
|
||||||
|
|
||||||
def select_text(self, ev, text):
|
def select_text(self, ev, text):
|
||||||
if self.mode == "tweet":
|
if self.mode == "tweet":
|
||||||
self.window.ChangeValue(self.window.GetValue().replace("@"+self.pattern, "@"+text+" "))
|
self.window.ChangeValue(self.window.GetValue().replace("@"+self.pattern, "@"+text+" "))
|
||||||
elif self.mode == "dm":
|
elif self.mode == "dm":
|
||||||
self.window.SetValue(self.window.GetValue().replace(self.pattern, text))
|
self.window.SetValue(self.window.GetValue().replace(self.pattern, text))
|
||||||
self.window.SetInsertionPointEnd()
|
self.window.SetInsertionPointEnd()
|
||||||
|
|
||||||
def destroy(self):
|
def destroy(self):
|
||||||
self.Destroy()
|
self.Destroy()
|
||||||
|
@@ -1,28 +1,27 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
|
||||||
import wx
|
import wx
|
||||||
import widgetUtils
|
import widgetUtils
|
||||||
import application
|
import application
|
||||||
|
|
||||||
class autocompletionSettingsDialog(widgetUtils.BaseDialog):
|
class autocompletionSettingsDialog(widgetUtils.BaseDialog):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(autocompletionSettingsDialog, self).__init__(parent=None, id=-1, title=_(u"Autocomplete users' settings"))
|
super(autocompletionSettingsDialog, self).__init__(parent=None, id=-1, title=_(u"Autocomplete users' settings"))
|
||||||
panel = wx.Panel(self)
|
panel = wx.Panel(self)
|
||||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||||
self.followers_buffer = wx.CheckBox(panel, -1, _(u"Add users from followers buffer"))
|
self.followers_buffer = wx.CheckBox(panel, -1, _(u"Add users from followers buffer"))
|
||||||
self.friends_buffer = wx.CheckBox(panel, -1, _(u"Add users from friends buffer"))
|
self.friends_buffer = wx.CheckBox(panel, -1, _(u"Add users from friends buffer"))
|
||||||
sizer.Add(self.followers_buffer, 0, wx.ALL, 5)
|
sizer.Add(self.followers_buffer, 0, wx.ALL, 5)
|
||||||
sizer.Add(self.friends_buffer, 0, wx.ALL, 5)
|
sizer.Add(self.friends_buffer, 0, wx.ALL, 5)
|
||||||
self.viewList = wx.Button(panel, -1, _(u"Manage database..."))
|
self.viewList = wx.Button(panel, -1, _(u"Manage database..."))
|
||||||
sizer.Add(self.viewList, 0, wx.ALL, 5)
|
sizer.Add(self.viewList, 0, wx.ALL, 5)
|
||||||
ok = wx.Button(panel, wx.ID_OK)
|
ok = wx.Button(panel, wx.ID_OK)
|
||||||
cancel = wx.Button(panel, wx.ID_CANCEL)
|
cancel = wx.Button(panel, wx.ID_CANCEL)
|
||||||
sizerBtn = wx.BoxSizer(wx.HORIZONTAL)
|
sizerBtn = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
sizerBtn.Add(ok, 0, wx.ALL, 5)
|
sizerBtn.Add(ok, 0, wx.ALL, 5)
|
||||||
sizer.Add(cancel, 0, wx.ALL, 5)
|
sizer.Add(cancel, 0, wx.ALL, 5)
|
||||||
sizer.Add(sizerBtn, 0, wx.ALL, 5)
|
sizer.Add(sizerBtn, 0, wx.ALL, 5)
|
||||||
panel.SetSizer(sizer)
|
panel.SetSizer(sizer)
|
||||||
self.SetClientSize(sizer.CalcMin())
|
self.SetClientSize(sizer.CalcMin())
|
||||||
|
|
||||||
def show_success_dialog():
|
def show_success_dialog():
|
||||||
wx.MessageDialog(None, _(u"{0}'s database of users has been updated.").format(application.name,), _(u"Done"), wx.OK).ShowModal()
|
wx.MessageDialog(None, _(u"{0}'s database of users has been updated.").format(application.name,), _(u"Done"), wx.OK).ShowModal()
|
||||||
|
@@ -9,37 +9,37 @@ short_langs = ["", "da", "du", "en", "fi", "fr", "de", "hu", "ko", "it", "ja", "
|
|||||||
OcrLangs = ["", "dan", "dut", "eng", "fin", "fre", "ger", "hun", "kor", "ita", "jpn", "pol", "por", "rus", "spa", "tur"]
|
OcrLangs = ["", "dan", "dut", "eng", "fin", "fre", "ger", "hun", "kor", "ita", "jpn", "pol", "por", "rus", "spa", "tur"]
|
||||||
|
|
||||||
class APIError(Exception):
|
class APIError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class OCRSpaceAPI(object):
|
class OCRSpaceAPI(object):
|
||||||
|
|
||||||
def __init__(self, key="4e72ae996f88957", url='https://api.ocr.space/parse/image'):
|
def __init__(self, key="4e72ae996f88957", url='https://api.ocr.space/parse/image'):
|
||||||
self.key = key
|
self.key = key
|
||||||
self.url = url
|
self.url = url
|
||||||
|
|
||||||
def OCR_URL(self, url, overlay=False, lang=None):
|
def OCR_URL(self, url, overlay=False, lang=None):
|
||||||
payload = {
|
payload = {
|
||||||
'url': url,
|
'url': url,
|
||||||
'isOverlayRequired': overlay,
|
'isOverlayRequired': overlay,
|
||||||
'apikey': self.key,
|
'apikey': self.key,
|
||||||
}
|
}
|
||||||
if lang != None:
|
if lang != None:
|
||||||
payload.update(language=lang)
|
payload.update(language=lang)
|
||||||
r = requests.post(self.url, data=payload)
|
r = requests.post(self.url, data=payload)
|
||||||
result = r.json()['ParsedResults'][0]
|
result = r.json()['ParsedResults'][0]
|
||||||
if result['ErrorMessage']:
|
if result['ErrorMessage']:
|
||||||
raise APIError(result['ErrorMessage'])
|
raise APIError(result['ErrorMessage'])
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def OCR_file(self, fileobj, overlay=False):
|
def OCR_file(self, fileobj, overlay=False):
|
||||||
payload = {
|
payload = {
|
||||||
'isOverlayRequired': overlay,
|
'isOverlayRequired': overlay,
|
||||||
'apikey': self.key,
|
'apikey': self.key,
|
||||||
'lang': 'es',
|
'lang': 'es',
|
||||||
}
|
}
|
||||||
r = requests.post(self.url, data=payload, files={'file': fileobj})
|
r = requests.post(self.url, data=payload, files={'file': fileobj})
|
||||||
results = r.json()['ParsedResults']
|
results = r.json()['ParsedResults']
|
||||||
if results[0]['ErrorMessage']:
|
if results[0]['ErrorMessage']:
|
||||||
raise APIError(results[0]['ErrorMessage'])
|
raise APIError(results[0]['ErrorMessage'])
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
@@ -4,5 +4,5 @@ from __future__ import unicode_literals
|
|||||||
from . import translator
|
from . import translator
|
||||||
import platform
|
import platform
|
||||||
if platform.system() == "Windows":
|
if platform.system() == "Windows":
|
||||||
from . import wx_ui as gui
|
from . import wx_ui as gui
|
||||||
|
|
@@ -1,115 +1,116 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
import logging
|
||||||
from builtins import zip
|
from googletrans import Translator, LANGUAGES
|
||||||
from yandex_translate import YandexTranslate
|
|
||||||
|
log = logging.getLogger("extras.translator")
|
||||||
|
|
||||||
|
# create a single translator instance
|
||||||
|
# see https://github.com/ssut/py-googletrans/issues/234
|
||||||
|
t = None
|
||||||
|
|
||||||
def translate(text="", target="en"):
|
def translate(text="", target="en"):
|
||||||
t = YandexTranslate("trnsl.1.1.20161012T134532Z.d01b9c75fc39aa74.7d1be75a5166a80583eeb020e10f584168da6bf7")
|
global t
|
||||||
vars = dict(text=text, lang=target)
|
log.debug("Received translation request for language %s, text=%s" % (target, text))
|
||||||
return t.translate(**vars)["text"][0]
|
if t == None:
|
||||||
|
t = Translator()
|
||||||
|
vars = dict(text=text, dest=target)
|
||||||
|
return t.translate(**vars).text
|
||||||
|
|
||||||
supported_langs = None
|
supported_langs = None
|
||||||
d = None
|
|
||||||
languages = {
|
languages = {
|
||||||
"af": _(u"Afrikaans"),
|
"af": _(u"Afrikaans"),
|
||||||
"sq": _(u"Albanian"),
|
"sq": _(u"Albanian"),
|
||||||
"am": _(u"Amharic"),
|
"am": _(u"Amharic"),
|
||||||
"ar": _(u"Arabic"),
|
"ar": _(u"Arabic"),
|
||||||
"hy": _(u"Armenian"),
|
"hy": _(u"Armenian"),
|
||||||
"az": _(u"Azerbaijani"),
|
"az": _(u"Azerbaijani"),
|
||||||
"eu": _(u"Basque"),
|
"eu": _(u"Basque"),
|
||||||
"be": _(u"Belarusian"),
|
"be": _(u"Belarusian"),
|
||||||
"bn": _(u"Bengali"),
|
"bn": _(u"Bengali"),
|
||||||
"bh": _(u"Bihari"),
|
"bh": _(u"Bihari"),
|
||||||
"bg": _(u"Bulgarian"),
|
"bg": _(u"Bulgarian"),
|
||||||
"my": _(u"Burmese"),
|
"my": _(u"Burmese"),
|
||||||
"ca": _(u"Catalan"),
|
"ca": _(u"Catalan"),
|
||||||
"chr": _(u"Cherokee"),
|
"chr": _(u"Cherokee"),
|
||||||
"zh": _(u"Chinese"),
|
"zh": _(u"Chinese"),
|
||||||
"zh-CN": _(u"Chinese_simplified"),
|
"zh-CN": _(u"Chinese_simplified"),
|
||||||
"zh-TW": _(u"Chinese_traditional"),
|
"zh-TW": _(u"Chinese_traditional"),
|
||||||
"hr": _(u"Croatian"),
|
"hr": _(u"Croatian"),
|
||||||
"cs": _(u"Czech"),
|
"cs": _(u"Czech"),
|
||||||
"da": _(u"Danish"),
|
"da": _(u"Danish"),
|
||||||
"dv": _(u"Dhivehi"),
|
"dv": _(u"Dhivehi"),
|
||||||
"nl": _(u"Dutch"),
|
"nl": _(u"Dutch"),
|
||||||
"en": _(u"English"),
|
"en": _(u"English"),
|
||||||
"eo": _(u"Esperanto"),
|
"eo": _(u"Esperanto"),
|
||||||
"et": _(u"Estonian"),
|
"et": _(u"Estonian"),
|
||||||
"tl": _(u"Filipino"),
|
"tl": _(u"Filipino"),
|
||||||
"fi": _(u"Finnish"),
|
"fi": _(u"Finnish"),
|
||||||
"fr": _(u"French"),
|
"fr": _(u"French"),
|
||||||
"gl": _(u"Galician"),
|
"gl": _(u"Galician"),
|
||||||
"ka": _(u"Georgian"),
|
"ka": _(u"Georgian"),
|
||||||
"de": _(u"German"),
|
"de": _(u"German"),
|
||||||
"el": _(u"Greek"),
|
"el": _(u"Greek"),
|
||||||
"gn": _(u"Guarani"),
|
"gn": _(u"Guarani"),
|
||||||
"gu": _(u"Gujarati"),
|
"gu": _(u"Gujarati"),
|
||||||
"iw": _(u"Hebrew"),
|
"iw": _(u"Hebrew"),
|
||||||
"hi": _(u"Hindi"),
|
"hi": _(u"Hindi"),
|
||||||
"hu": _(u"Hungarian"),
|
"hu": _(u"Hungarian"),
|
||||||
"is": _(u"Icelandic"),
|
"is": _(u"Icelandic"),
|
||||||
"id": _(u"Indonesian"),
|
"id": _(u"Indonesian"),
|
||||||
"iu": _(u"Inuktitut"),
|
"iu": _(u"Inuktitut"),
|
||||||
"ga": _(u"Irish"),
|
"ga": _(u"Irish"),
|
||||||
"it": _(u"Italian"),
|
"it": _(u"Italian"),
|
||||||
"ja": _(u"Japanese"),
|
"ja": _(u"Japanese"),
|
||||||
"kn": _(u"Kannada"),
|
"kn": _(u"Kannada"),
|
||||||
"kk": _(u"Kazakh"),
|
"kk": _(u"Kazakh"),
|
||||||
"km": _(u"Khmer"),
|
"km": _(u"Khmer"),
|
||||||
"ko": _(u"Korean"),
|
"ko": _(u"Korean"),
|
||||||
"ku": _(u"Kurdish"),
|
"ku": _(u"Kurdish"),
|
||||||
"ky": _(u"Kyrgyz"),
|
"ky": _(u"Kyrgyz"),
|
||||||
"lo": _(u"Laothian"),
|
"lo": _(u"Laothian"),
|
||||||
"lv": _(u"Latvian"),
|
"lv": _(u"Latvian"),
|
||||||
"lt": _(u"Lithuanian"),
|
"lt": _(u"Lithuanian"),
|
||||||
"mk": _(u"Macedonian"),
|
"mk": _(u"Macedonian"),
|
||||||
"ms": _(u"Malay"),
|
"ms": _(u"Malay"),
|
||||||
"ml": _(u"Malayalam"),
|
"ml": _(u"Malayalam"),
|
||||||
"mt": _(u"Maltese"),
|
"mt": _(u"Maltese"),
|
||||||
"mr": _(u"Marathi"),
|
"mr": _(u"Marathi"),
|
||||||
"mn": _(u"Mongolian"),
|
"mn": _(u"Mongolian"),
|
||||||
"ne": _(u"Nepali"),
|
"ne": _(u"Nepali"),
|
||||||
"no": _(u"Norwegian"),
|
"no": _(u"Norwegian"),
|
||||||
"or": _(u"Oriya"),
|
"or": _(u"Oriya"),
|
||||||
"ps": _(u"Pashto"),
|
"ps": _(u"Pashto"),
|
||||||
"fa": _(u"Persian"),
|
"fa": _(u"Persian"),
|
||||||
"pl": _(u"Polish"),
|
"pl": _(u"Polish"),
|
||||||
"pt": _(u"Portuguese"),
|
"pt": _(u"Portuguese"),
|
||||||
"pa": _(u"Punjabi"),
|
"pa": _(u"Punjabi"),
|
||||||
"ro": _(u"Romanian"),
|
"ro": _(u"Romanian"),
|
||||||
"ru": _(u"Russian"),
|
"ru": _(u"Russian"),
|
||||||
"sa": _(u"Sanskrit"),
|
"sa": _(u"Sanskrit"),
|
||||||
"sr": _(u"Serbian"),
|
"sr": _(u"Serbian"),
|
||||||
"sd": _(u"Sindhi"),
|
"sd": _(u"Sindhi"),
|
||||||
"si": _(u"Sinhalese"),
|
"si": _(u"Sinhalese"),
|
||||||
"sk": _(u"Slovak"),
|
"sk": _(u"Slovak"),
|
||||||
"sl": _(u"Slovenian"),
|
"sl": _(u"Slovenian"),
|
||||||
"es": _(u"Spanish"),
|
"es": _(u"Spanish"),
|
||||||
"sw": _(u"Swahili"),
|
"sw": _(u"Swahili"),
|
||||||
"sv": _(u"Swedish"),
|
"sv": _(u"Swedish"),
|
||||||
"tg": _(u"Tajik"),
|
"tg": _(u"Tajik"),
|
||||||
"ta": _(u"Tamil"),
|
"ta": _(u"Tamil"),
|
||||||
"tl": _(u"Tagalog"),
|
"tl": _(u"Tagalog"),
|
||||||
"te": _(u"Telugu"),
|
"te": _(u"Telugu"),
|
||||||
"th": _(u"Thai"),
|
"th": _(u"Thai"),
|
||||||
"bo": _(u"Tibetan"),
|
"bo": _(u"Tibetan"),
|
||||||
"tr": _(u"Turkish"),
|
"tr": _(u"Turkish"),
|
||||||
"uk": _(u"Ukrainian"),
|
"uk": _(u"Ukrainian"),
|
||||||
"ur": _(u"Urdu"),
|
"ur": _(u"Urdu"),
|
||||||
"uz": _(u"Uzbek"),
|
"uz": _(u"Uzbek"),
|
||||||
"ug": _(u"Uighur"),
|
"ug": _(u"Uighur"),
|
||||||
"vi": _(u"Vietnamese"),
|
"vi": _(u"Vietnamese"),
|
||||||
"cy": _(u"Welsh"),
|
"cy": _(u"Welsh"),
|
||||||
"yi": _(u"Yiddish")
|
"yi": _(u"Yiddish")
|
||||||
}
|
}
|
||||||
|
|
||||||
def available_languages():
|
def available_languages():
|
||||||
global supported_langs, d
|
return dict(sorted(languages.items(), key=lambda x: x[1]))
|
||||||
if supported_langs == None and d == None:
|
|
||||||
t = YandexTranslate("trnsl.1.1.20161012T134532Z.d01b9c75fc39aa74.7d1be75a5166a80583eeb020e10f584168da6bf7")
|
|
||||||
supported_langs = t.langs
|
|
||||||
d = []
|
|
||||||
for i in supported_langs:
|
|
||||||
d.append(languages[i])
|
|
||||||
return sorted(zip(supported_langs, d))
|
|
||||||
|
@@ -16,46 +16,30 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
############################################################
|
############################################################
|
||||||
from __future__ import absolute_import
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
############################################################
|
|
||||||
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 2 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
############################################################
|
|
||||||
from . import translator
|
from . import translator
|
||||||
import wx
|
import wx
|
||||||
from wxUI.dialogs import baseDialog
|
from wxUI.dialogs import baseDialog
|
||||||
|
|
||||||
class translateDialog(baseDialog.BaseWXDialog):
|
class translateDialog(baseDialog.BaseWXDialog):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(translateDialog, self).__init__(None, -1, title=_(u"Translate message"))
|
languages = []
|
||||||
panel = wx.Panel(self)
|
language_dict = translator.available_languages()
|
||||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
for k in language_dict:
|
||||||
staticDest = wx.StaticText(panel, -1, _(u"Target language"))
|
languages.append(language_dict[k])
|
||||||
self.dest_lang = wx.ComboBox(panel, -1, choices=[x[1] for x in translator.available_languages()], style = wx.CB_READONLY)
|
super(translateDialog, self).__init__(None, -1, title=_(u"Translate message"))
|
||||||
self.dest_lang.SetFocus()
|
panel = wx.Panel(self)
|
||||||
self.dest_lang.SetSelection(0)
|
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||||
listSizer = wx.BoxSizer(wx.HORIZONTAL)
|
staticDest = wx.StaticText(panel, -1, _(u"Target language"))
|
||||||
listSizer.Add(staticDest)
|
self.dest_lang = wx.ComboBox(panel, -1, choices=languages, style = wx.CB_READONLY)
|
||||||
listSizer.Add(self.dest_lang)
|
self.dest_lang.SetFocus()
|
||||||
ok = wx.Button(panel, wx.ID_OK)
|
self.dest_lang.SetSelection(0)
|
||||||
ok.SetDefault()
|
listSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
cancel = wx.Button(panel, wx.ID_CANCEL)
|
listSizer.Add(staticDest)
|
||||||
self.SetEscapeId(wx.ID_CANCEL)
|
listSizer.Add(self.dest_lang)
|
||||||
|
ok = wx.Button(panel, wx.ID_OK)
|
||||||
|
ok.SetDefault()
|
||||||
|
cancel = wx.Button(panel, wx.ID_CANCEL)
|
||||||
|
self.SetEscapeId(wx.ID_CANCEL)
|
||||||
|
|
||||||
def get(self, control):
|
def get(self, control):
|
||||||
return getattr(self, control).GetSelection()
|
return getattr(self, control).GetSelection()
|
||||||
|
@@ -9,11 +9,11 @@ from . import fix_urllib3_warnings # Avoiding some SSL warnings related to Twyth
|
|||||||
from . import fix_win32com
|
from . import fix_win32com
|
||||||
#from . import fix_requests #fix cacert.pem location for TWBlue binary copies
|
#from . import fix_requests #fix cacert.pem location for TWBlue binary copies
|
||||||
def setup():
|
def setup():
|
||||||
fix_arrow.fix()
|
fix_arrow.fix()
|
||||||
if hasattr(sys, "frozen"):
|
if hasattr(sys, "frozen"):
|
||||||
fix_libloader.fix()
|
fix_libloader.fix()
|
||||||
fix_win32com.fix()
|
fix_win32com.fix()
|
||||||
# fix_requests.fix()
|
# fix_requests.fix()
|
||||||
# else:
|
# else:
|
||||||
# fix_requests.fix(False)
|
# fix_requests.fix(False)
|
||||||
fix_urllib3_warnings.fix()
|
fix_urllib3_warnings.fix()
|
||||||
|
@@ -1,95 +1,49 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
|
||||||
from arrow import locales
|
from arrow import locales
|
||||||
from arrow.locales import Locale
|
from arrow.locales import Locale
|
||||||
|
|
||||||
def fix():
|
def fix():
|
||||||
# insert a modified function so if there is no language available in arrow, returns English locale.
|
# insert a modified function so if there is no language available in arrow, returns English locale.
|
||||||
locales.get_locale = get_locale
|
locales.get_locale = get_locale
|
||||||
|
|
||||||
def get_locale(name):
|
def get_locale(name):
|
||||||
locale_cls = locales._locales.get(name.lower())
|
locale_cls = locales._locale_map.get(name.lower())
|
||||||
if locale_cls is None:
|
if locale_cls is None:
|
||||||
name = name[:2]
|
name = name[:2]
|
||||||
locale_cls = locales._locales.get(name.lower())
|
locale_cls = locales._locale_map.get(name.lower())
|
||||||
if locale_cls == None:
|
if locale_cls == None:
|
||||||
return locales.EnglishLocale()
|
return locales.EnglishLocale()
|
||||||
return locale_cls()
|
return locale_cls()
|
||||||
|
|
||||||
class CatalaLocale(Locale):
|
class GalicianLocale(object):
|
||||||
names = ['ca', 'ca_es', 'ca_ca']
|
names = ['gl', 'gl_es', 'gl_gl']
|
||||||
past = 'Fa {0}'
|
past = 'Hai {0}'
|
||||||
future = '{0}' # I don't know what's the right phrase in catala for the future.
|
future = 'En {0}'
|
||||||
|
and_word = "e"
|
||||||
|
|
||||||
timeframes = {
|
timeframes = {
|
||||||
'now': 'Ara mateix',
|
'now': 'Agora',
|
||||||
'seconds': 'segons',
|
"second": "un segundo",
|
||||||
'minute': '1 minut',
|
'seconds': '{0} segundos',
|
||||||
'minutes': '{0} minuts',
|
'minute': 'un minuto',
|
||||||
'hour': 'una hora',
|
'minutes': '{0} minutos',
|
||||||
'hours': '{0} hores',
|
'hour': 'unha hora',
|
||||||
'day': 'un dia',
|
'hours': '{0} horas',
|
||||||
'days': '{0} dies',
|
'day': 'un día',
|
||||||
'month': 'un mes',
|
'days': '{0} días',
|
||||||
'months': '{0} messos',
|
"week": "unha semana",
|
||||||
'year': 'un any',
|
"weeks": "{0} semanas",
|
||||||
'years': '{0} anys',
|
'month': 'un mes',
|
||||||
}
|
'months': '{0} meses',
|
||||||
|
'year': 'un ano',
|
||||||
|
'years': '{0} anos',
|
||||||
|
}
|
||||||
|
|
||||||
month_names = ['', 'Jener', 'Febrer', 'Març', 'Abril', 'Maig', 'Juny', 'Juliol', 'Agost', 'Setembre', 'Octubre', 'Novembre', 'Decembre']
|
meridians = {"am": "am", "pm": "pm", "AM": "AM", "PM": "PM"}
|
||||||
month_abbreviations = ['', 'Jener', 'Febrer', 'Març', 'Abril', 'Maig', 'Juny', 'Juliol', 'Agost', 'Setembre', 'Octubre', 'Novembre', 'Decembre']
|
|
||||||
day_names = ['', 'Dilluns', 'Dimars', 'Dimecres', 'Dijous', 'Divendres', 'Disabte', 'Diumenge']
|
|
||||||
day_abbreviations = ['', 'Dilluns', 'Dimars', 'Dimecres', 'Dijous', 'Divendres', 'Disabte', 'Diumenge']
|
|
||||||
|
|
||||||
class GalicianLocale(Locale):
|
month_names = ['', 'xaneiro', 'febreiro', 'marzo', 'abril', 'maio', 'xuño', 'xullo', 'agosto', 'setembro', 'outubro', 'novembro', 'decembro']
|
||||||
names = ['gl', 'gl_es', 'gl_gl']
|
month_abbreviations = ['', 'xan', 'feb', 'mar', 'abr', 'mai', 'xun', 'xul', 'ago', 'set', 'out', 'nov', 'dec']
|
||||||
past = 'Fai {0}'
|
day_names = ['', 'luns', 'martes', 'mércores', 'xoves', 'venres', 'sábado', 'domingo']
|
||||||
future = 'En {0}'
|
day_abbreviations = ['', 'lun', 'mar', 'mer', 'xov', 'ven', 'sab', 'dom']
|
||||||
|
ordinal_day_re = r"((?P<value>[1-3]?[0-9](?=[ºª]))[ºª])"
|
||||||
timeframes = {
|
|
||||||
'now': 'Agora mesmo',
|
|
||||||
'seconds': 'segundos',
|
|
||||||
'minute': 'un minuto',
|
|
||||||
'minutes': '{0} minutos',
|
|
||||||
'hour': 'una hora',
|
|
||||||
'hours': '{0} horas',
|
|
||||||
'day': 'un día',
|
|
||||||
'days': '{0} días',
|
|
||||||
'month': 'un mes',
|
|
||||||
'months': '{0} meses',
|
|
||||||
'year': 'un ano',
|
|
||||||
'years': '{0} anos',
|
|
||||||
}
|
|
||||||
|
|
||||||
month_names = ['', 'Xaneiro', 'Febreiro', 'Marzo', 'Abril', 'Maio', 'Xuño', 'Xullo', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Decembro']
|
|
||||||
month_abbreviations = ['', 'Xan', 'Feb', 'Mar', 'Abr', 'Mai', 'Xun', 'Xul', 'Ago', 'Set', 'Out', 'Nov', 'Dec']
|
|
||||||
day_names = ['', 'Luns', 'Martes', 'Mércores', 'Xoves', 'Venres', 'Sábado', 'Domingo']
|
|
||||||
day_abbreviations = ['', 'Lun', 'Mar', 'Mer', 'xov', 'Ven' 'Sab', 'Dom']
|
|
||||||
|
|
||||||
class BasqueLocale(Locale):
|
|
||||||
names = ['eu', 'eu_es', 'eu_eu']
|
|
||||||
past = 'duela {0}'
|
|
||||||
future = '{0} igarota'
|
|
||||||
|
|
||||||
timeframes = {
|
|
||||||
'now': 'Orain',
|
|
||||||
# 'second': 'segundu bat',
|
|
||||||
'seconds': 'segundu batzuk', # without specifying a number.
|
|
||||||
#'seconds': '{0} segundu', # specifying a number
|
|
||||||
'minute': 'minutu bat',
|
|
||||||
'minutes': '{0} minutu',
|
|
||||||
'hour': 'ordu bat',
|
|
||||||
'hours': '{0} ordu',
|
|
||||||
'day': 'egun bat',
|
|
||||||
'days': '{0} egun',
|
|
||||||
'month': 'hilabete bat',
|
|
||||||
'months': '{0} hilabete',
|
|
||||||
'year': 'urte bat',
|
|
||||||
'years': '{0} urte',
|
|
||||||
}
|
|
||||||
|
|
||||||
month_names = ['', 'Urtarrilak', 'Otsailak', 'Martxoak', 'Apirilak', 'Maiatzak', 'Ekainak', 'Uztailak', 'Abuztuak', 'Irailak', 'Urriak', 'Azaroak', 'Abenduak']
|
|
||||||
month_abbreviations = ['', 'urt', 'ots', 'mar', 'api', 'mai', 'eka', 'uzt', 'abu', 'ira', 'urr', 'aza', 'abe']
|
|
||||||
day_names = ['', 'Asteleehna', 'Asteartea', 'Asteazkena', 'Osteguna', 'Ostirala', 'Larunbata', 'Igandea']
|
|
||||||
day_abbreviations = ['', 'al', 'ar', 'az', 'og', 'ol', 'lr', 'ig']
|
|
||||||
|
|
||||||
|
@@ -16,27 +16,27 @@ log = logging.getLogger("fixes.fix_libloader")
|
|||||||
fixed=False
|
fixed=False
|
||||||
|
|
||||||
def patched_getmodule(modname):
|
def patched_getmodule(modname):
|
||||||
mod=__import__(modname)
|
mod=__import__(modname)
|
||||||
return sys.modules[modname]
|
return sys.modules[modname]
|
||||||
|
|
||||||
def load_com(*names):
|
def load_com(*names):
|
||||||
global fixed
|
global fixed
|
||||||
if fixed==False:
|
if fixed==False:
|
||||||
gencache._GetModule=patched_getmodule
|
gencache._GetModule=patched_getmodule
|
||||||
com.prepare_gencache()
|
com.prepare_gencache()
|
||||||
fixed=True
|
fixed=True
|
||||||
result = None
|
result = None
|
||||||
for name in names:
|
for name in names:
|
||||||
try:
|
try:
|
||||||
result = gencache.EnsureDispatch(name)
|
result = gencache.EnsureDispatch(name)
|
||||||
break
|
break
|
||||||
except com_error:
|
except com_error:
|
||||||
continue
|
continue
|
||||||
if result is None:
|
if result is None:
|
||||||
raise com_error("Unable to load any of the provided com objects.")
|
raise com_error("Unable to load any of the provided com objects.")
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def fix():
|
def fix():
|
||||||
log.debug("Applying fix for Libloader...")
|
log.debug("Applying fix for Libloader...")
|
||||||
com.load_com = load_com
|
com.load_com = load_com
|
||||||
log.debug("Load_com has been mapped correctly.")
|
log.debug("Load_com has been mapped correctly.")
|
||||||
|
@@ -7,6 +7,6 @@ import logging
|
|||||||
log = logging.getLogger("fixes.fix_requests")
|
log = logging.getLogger("fixes.fix_requests")
|
||||||
|
|
||||||
def fix():
|
def fix():
|
||||||
log.debug("Applying fix for requests...")
|
log.debug("Applying fix for requests...")
|
||||||
os.environ["REQUESTS_CA_BUNDLE"] = os.path.join(paths.app_path(), "certifi", "cacert.pem")#.encode(paths.fsencoding)
|
os.environ["REQUESTS_CA_BUNDLE"] = os.path.join(paths.app_path(), "certifi", "cacert.pem")#.encode(paths.fsencoding)
|
||||||
# log.debug("Changed CA path to %s" % (os.environ["REQUESTS_CA_BUNDLE"]))#.decode(paths.fsencoding)))
|
# log.debug("Changed CA path to %s" % (os.environ["REQUESTS_CA_BUNDLE"]))#.decode(paths.fsencoding)))
|
@@ -8,8 +8,8 @@ import six
|
|||||||
import urllib.request, urllib.parse, urllib.error
|
import urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
def fix():
|
def fix():
|
||||||
urllib3.disable_warnings()
|
urllib3.disable_warnings()
|
||||||
fields.format_header_param=patched_format_header_param
|
fields.format_header_param=patched_format_header_param
|
||||||
|
|
||||||
def patched_format_header_param(name, value):
|
def patched_format_header_param(name, value):
|
||||||
if not any(ch in value for ch in '"\\\r\n'):
|
if not any(ch in value for ch in '"\\\r\n'):
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import win32com.client
|
import win32com.client
|
||||||
def fix():
|
def fix():
|
||||||
if win32com.client.gencache.is_readonly == True:
|
if win32com.client.gencache.is_readonly == True:
|
||||||
win32com.client.gencache.is_readonly = False
|
win32com.client.gencache.is_readonly = False
|
||||||
win32com.client.gencache.Rebuild()
|
win32com.client.gencache.Rebuild()
|
||||||
|
@@ -27,40 +27,40 @@ from suds.client import Client
|
|||||||
import constants
|
import constants
|
||||||
|
|
||||||
class reportBug(object):
|
class reportBug(object):
|
||||||
def __init__(self, user_name):
|
def __init__(self, user_name):
|
||||||
self.user_name = user_name
|
self.user_name = user_name
|
||||||
self.categories = [_(u"General")]
|
self.categories = [_(u"General")]
|
||||||
self.reproducibilities = [_(u"always"), _(u"sometimes"), _(u"random"), _(u"have not tried"), _(u"unable to duplicate")]
|
self.reproducibilities = [_(u"always"), _(u"sometimes"), _(u"random"), _(u"have not tried"), _(u"unable to duplicate")]
|
||||||
self.severities = [_(u"block"), _(u"crash"), _(u"major"), _(u"minor"), _(u"tweak"), _(u"text"), _(u"trivial"), _(u"feature")]
|
self.severities = [_(u"block"), _(u"crash"), _(u"major"), _(u"minor"), _(u"tweak"), _(u"text"), _(u"trivial"), _(u"feature")]
|
||||||
self.dialog = wx_ui.reportBugDialog(self.categories, self.reproducibilities, self.severities)
|
self.dialog = wx_ui.reportBugDialog(self.categories, self.reproducibilities, self.severities)
|
||||||
widgetUtils.connect_event(self.dialog.ok, widgetUtils.BUTTON_PRESSED, self.send)
|
widgetUtils.connect_event(self.dialog.ok, widgetUtils.BUTTON_PRESSED, self.send)
|
||||||
self.dialog.get_response()
|
self.dialog.get_response()
|
||||||
|
|
||||||
def send(self, *args, **kwargs):
|
def send(self, *args, **kwargs):
|
||||||
if self.dialog.get("summary") == "" or self.dialog.get("description") == "":
|
if self.dialog.get("summary") == "" or self.dialog.get("description") == "":
|
||||||
self.dialog.no_filled()
|
self.dialog.no_filled()
|
||||||
return
|
return
|
||||||
if self.dialog.get("agree") == False:
|
if self.dialog.get("agree") == False:
|
||||||
self.dialog.no_checkbox()
|
self.dialog.no_checkbox()
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
client = Client(application.report_bugs_url)
|
client = Client(application.report_bugs_url)
|
||||||
issue = client.factory.create('IssueData')
|
issue = client.factory.create('IssueData')
|
||||||
issue.project.name = application.name
|
issue.project.name = application.name
|
||||||
issue.project.id = 0
|
issue.project.id = 0
|
||||||
issue.summary = self.dialog.get("summary"),
|
issue.summary = self.dialog.get("summary"),
|
||||||
issue.description = "Reported by @%s on version %s (snapshot = %s)\n\n" % (self.user_name, application.version, application.snapshot) + self.dialog.get("description")
|
issue.description = "Reported by @%s on version %s (snapshot = %s)\n\n" % (self.user_name, application.version, application.snapshot) + self.dialog.get("description")
|
||||||
# to do: Create getters for category, severity and reproducibility in wx_UI.
|
# to do: Create getters for category, severity and reproducibility in wx_UI.
|
||||||
issue.category = constants.categories[self.dialog.category.GetSelection()]
|
issue.category = constants.categories[self.dialog.category.GetSelection()]
|
||||||
issue.reproducibility.name = constants.reproducibilities[self.dialog.reproducibility.GetSelection()]
|
issue.reproducibility.name = constants.reproducibilities[self.dialog.reproducibility.GetSelection()]
|
||||||
issue.severity.name = constants.severities[self.dialog.severity.GetSelection()]
|
issue.severity.name = constants.severities[self.dialog.severity.GetSelection()]
|
||||||
issue.priority.name = "normal"
|
issue.priority.name = "normal"
|
||||||
issue.view_state.name = "public"
|
issue.view_state.name = "public"
|
||||||
issue.resolution.name = "open"
|
issue.resolution.name = "open"
|
||||||
issue.projection.name = "none"
|
issue.projection.name = "none"
|
||||||
issue.eta.name = "eta"
|
issue.eta.name = "eta"
|
||||||
issue.status.name = "new"
|
issue.status.name = "new"
|
||||||
id = client.service.mc_issue_add(keys.keyring.get("bts_user"), keys.keyring.get("bts_password"), issue)
|
id = client.service.mc_issue_add(keys.keyring.get("bts_user"), keys.keyring.get("bts_password"), issue)
|
||||||
self.dialog.success(id)
|
self.dialog.success(id)
|
||||||
except:
|
except:
|
||||||
self.dialog.error()
|
self.dialog.error()
|
||||||
|
@@ -21,75 +21,75 @@ import wx
|
|||||||
import widgetUtils
|
import widgetUtils
|
||||||
import application
|
import application
|
||||||
class reportBugDialog(widgetUtils.BaseDialog):
|
class reportBugDialog(widgetUtils.BaseDialog):
|
||||||
def __init__(self, categories, reproducibilities, severities):
|
def __init__(self, categories, reproducibilities, severities):
|
||||||
super(reportBugDialog, self).__init__(parent=None, id=wx.NewId())
|
super(reportBugDialog, self).__init__(parent=None, id=wx.NewId())
|
||||||
self.SetTitle(_(u"Report an error"))
|
self.SetTitle(_(u"Report an error"))
|
||||||
panel = wx.Panel(self)
|
panel = wx.Panel(self)
|
||||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||||
categoryLabel = wx.StaticText(panel, -1, _(u"Select a category"), size=wx.DefaultSize)
|
categoryLabel = wx.StaticText(panel, -1, _(u"Select a category"), size=wx.DefaultSize)
|
||||||
self.category = wx.ComboBox(panel, -1, choices=categories, style=wx.CB_READONLY)
|
self.category = wx.ComboBox(panel, -1, choices=categories, style=wx.CB_READONLY)
|
||||||
self.category.SetSelection(0)
|
self.category.SetSelection(0)
|
||||||
categoryB = wx.BoxSizer(wx.HORIZONTAL)
|
categoryB = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
categoryB.Add(categoryLabel, 0, wx.ALL, 5)
|
categoryB.Add(categoryLabel, 0, wx.ALL, 5)
|
||||||
categoryB.Add(self.category, 0, wx.ALL, 5)
|
categoryB.Add(self.category, 0, wx.ALL, 5)
|
||||||
self.category.SetFocus()
|
self.category.SetFocus()
|
||||||
sizer.Add(categoryB, 0, wx.ALL, 5)
|
sizer.Add(categoryB, 0, wx.ALL, 5)
|
||||||
summaryLabel = wx.StaticText(panel, -1, _(u"Briefly describe what happened. You will be able to thoroughly explain it later"), size=wx.DefaultSize)
|
summaryLabel = wx.StaticText(panel, -1, _(u"Briefly describe what happened. You will be able to thoroughly explain it later"), size=wx.DefaultSize)
|
||||||
self.summary = wx.TextCtrl(panel, -1)
|
self.summary = wx.TextCtrl(panel, -1)
|
||||||
dc = wx.WindowDC(self.summary)
|
dc = wx.WindowDC(self.summary)
|
||||||
dc.SetFont(self.summary.GetFont())
|
dc.SetFont(self.summary.GetFont())
|
||||||
self.summary.SetSize(dc.GetTextExtent("a"*80))
|
self.summary.SetSize(dc.GetTextExtent("a"*80))
|
||||||
summaryB = wx.BoxSizer(wx.HORIZONTAL)
|
summaryB = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
summaryB.Add(summaryLabel, 0, wx.ALL, 5)
|
summaryB.Add(summaryLabel, 0, wx.ALL, 5)
|
||||||
summaryB.Add(self.summary, 0, wx.ALL, 5)
|
summaryB.Add(self.summary, 0, wx.ALL, 5)
|
||||||
sizer.Add(summaryB, 0, wx.ALL, 5)
|
sizer.Add(summaryB, 0, wx.ALL, 5)
|
||||||
descriptionLabel = wx.StaticText(panel, -1, _(u"Here, you can describe the bug in detail"), size=wx.DefaultSize)
|
descriptionLabel = wx.StaticText(panel, -1, _(u"Here, you can describe the bug in detail"), size=wx.DefaultSize)
|
||||||
self.description = wx.TextCtrl(panel, -1, style=wx.TE_MULTILINE)
|
self.description = wx.TextCtrl(panel, -1, style=wx.TE_MULTILINE)
|
||||||
dc = wx.WindowDC(self.description)
|
dc = wx.WindowDC(self.description)
|
||||||
dc.SetFont(self.description.GetFont())
|
dc.SetFont(self.description.GetFont())
|
||||||
(x, y, z) = dc.GetMultiLineTextExtent("0"*2000)
|
(x, y, z) = dc.GetMultiLineTextExtent("0"*2000)
|
||||||
self.description.SetSize((x, y))
|
self.description.SetSize((x, y))
|
||||||
descBox = wx.BoxSizer(wx.HORIZONTAL)
|
descBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
descBox.Add(descriptionLabel, 0, wx.ALL, 5)
|
descBox.Add(descriptionLabel, 0, wx.ALL, 5)
|
||||||
descBox.Add(self.description, 0, wx.ALL, 5)
|
descBox.Add(self.description, 0, wx.ALL, 5)
|
||||||
sizer.Add(descBox, 0, wx.ALL, 5)
|
sizer.Add(descBox, 0, wx.ALL, 5)
|
||||||
reproducibilityLabel = wx.StaticText(panel, -1, _(u"how often does this bug happen?"), size=wx.DefaultSize)
|
reproducibilityLabel = wx.StaticText(panel, -1, _(u"how often does this bug happen?"), size=wx.DefaultSize)
|
||||||
self.reproducibility = wx.ComboBox(panel, -1, choices=reproducibilities, style=wx.CB_READONLY)
|
self.reproducibility = wx.ComboBox(panel, -1, choices=reproducibilities, style=wx.CB_READONLY)
|
||||||
self.reproducibility.SetSelection(3)
|
self.reproducibility.SetSelection(3)
|
||||||
reprB = wx.BoxSizer(wx.HORIZONTAL)
|
reprB = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
reprB.Add(reproducibilityLabel, 0, wx.ALL, 5)
|
reprB.Add(reproducibilityLabel, 0, wx.ALL, 5)
|
||||||
reprB.Add(self.reproducibility, 0, wx.ALL, 5)
|
reprB.Add(self.reproducibility, 0, wx.ALL, 5)
|
||||||
sizer.Add(reprB, 0, wx.ALL, 5)
|
sizer.Add(reprB, 0, wx.ALL, 5)
|
||||||
severityLabel = wx.StaticText(panel, -1, _(u"Select the importance that you think this bug has"))
|
severityLabel = wx.StaticText(panel, -1, _(u"Select the importance that you think this bug has"))
|
||||||
self.severity = wx.ComboBox(panel, -1, choices=severities, style=wx.CB_READONLY)
|
self.severity = wx.ComboBox(panel, -1, choices=severities, style=wx.CB_READONLY)
|
||||||
self.severity.SetSelection(3)
|
self.severity.SetSelection(3)
|
||||||
severityB = wx.BoxSizer(wx.HORIZONTAL)
|
severityB = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
severityB.Add(severityLabel, 0, wx.ALL, 5)
|
severityB.Add(severityLabel, 0, wx.ALL, 5)
|
||||||
severityB.Add(self.severity, 0, wx.ALL, 5)
|
severityB.Add(self.severity, 0, wx.ALL, 5)
|
||||||
sizer.Add(severityB, 0, wx.ALL, 5)
|
sizer.Add(severityB, 0, wx.ALL, 5)
|
||||||
self.agree = wx.CheckBox(panel, -1, _(u"I know that the {0} bug system will get my Twitter username to contact me and fix the bug quickly").format(application.name,))
|
self.agree = wx.CheckBox(panel, -1, _(u"I know that the {0} bug system will get my Twitter username to contact me and fix the bug quickly").format(application.name,))
|
||||||
self.agree.SetValue(False)
|
self.agree.SetValue(False)
|
||||||
sizer.Add(self.agree, 0, wx.ALL, 5)
|
sizer.Add(self.agree, 0, wx.ALL, 5)
|
||||||
self.ok = wx.Button(panel, wx.ID_OK, _(u"Send report"))
|
self.ok = wx.Button(panel, wx.ID_OK, _(u"Send report"))
|
||||||
self.ok.SetDefault()
|
self.ok.SetDefault()
|
||||||
cancel = wx.Button(panel, wx.ID_CANCEL, _(u"Cancel"))
|
cancel = wx.Button(panel, wx.ID_CANCEL, _(u"Cancel"))
|
||||||
btnBox = wx.BoxSizer(wx.HORIZONTAL)
|
btnBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
btnBox.Add(self.ok, 0, wx.ALL, 5)
|
btnBox.Add(self.ok, 0, wx.ALL, 5)
|
||||||
btnBox.Add(cancel, 0, wx.ALL, 5)
|
btnBox.Add(cancel, 0, wx.ALL, 5)
|
||||||
sizer.Add(btnBox, 0, wx.ALL, 5)
|
sizer.Add(btnBox, 0, wx.ALL, 5)
|
||||||
panel.SetSizer(sizer)
|
panel.SetSizer(sizer)
|
||||||
self.SetClientSize(sizer.CalcMin())
|
self.SetClientSize(sizer.CalcMin())
|
||||||
|
|
||||||
def no_filled(self):
|
def no_filled(self):
|
||||||
wx.MessageDialog(self, _(u"You must fill out both fields"), _(u"Error"), wx.OK|wx.ICON_ERROR).ShowModal()
|
wx.MessageDialog(self, _(u"You must fill out both fields"), _(u"Error"), wx.OK|wx.ICON_ERROR).ShowModal()
|
||||||
|
|
||||||
def no_checkbox(self):
|
def no_checkbox(self):
|
||||||
wx.MessageDialog(self, _(u"You need to mark the checkbox to provide us your twitter username to contact you if it is necessary."), _(u"Error"), wx.ICON_ERROR).ShowModal()
|
wx.MessageDialog(self, _(u"You need to mark the checkbox to provide us your twitter username to contact you if it is necessary."), _(u"Error"), wx.ICON_ERROR).ShowModal()
|
||||||
|
|
||||||
def success(self, id):
|
def success(self, id):
|
||||||
wx.MessageDialog(self, _(u"Thanks for reporting this bug! In future versions, you may be able to find it in the changes list. You've reported the bug number %i") % (id), _(u"reported"), wx.OK).ShowModal()
|
wx.MessageDialog(self, _(u"Thanks for reporting this bug! In future versions, you may be able to find it in the changes list. You've reported the bug number %i") % (id), _(u"reported"), wx.OK).ShowModal()
|
||||||
self.EndModal(wx.ID_OK)
|
self.EndModal(wx.ID_OK)
|
||||||
|
|
||||||
def error(self):
|
def error(self):
|
||||||
wx.MessageDialog(self, _(u"Something unexpected occurred while trying to report the bug. Please, try again later"), _(u"Error while reporting"), wx.ICON_ERROR|wx.OK).ShowModal()
|
wx.MessageDialog(self, _(u"Something unexpected occurred while trying to report the bug. Please, try again later"), _(u"Error while reporting"), wx.ICON_ERROR|wx.OK).ShowModal()
|
||||||
self.EndModal(wx.ID_CANCEL)
|
self.EndModal(wx.ID_CANCEL)
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
import platform
|
import platform
|
||||||
if platform.system() == 'Linux':
|
if platform.system() == 'Linux':
|
||||||
from .linux import LinuxKeyboardHandler as GlobalKeyboardHandler
|
from .linux import LinuxKeyboardHandler as GlobalKeyboardHandler
|
||||||
else:
|
else:
|
||||||
from .wx_handler import WXKeyboardHandler as GlobalKeyboardHandler
|
from .wx_handler import WXKeyboardHandler as GlobalKeyboardHandler
|
||||||
#elif platform.system() == 'Darwin':
|
#elif platform.system() == 'Darwin':
|
||||||
#from osx import OSXKeyboardHandler as GlobalKeyboardHandler
|
#from osx import OSXKeyboardHandler as GlobalKeyboardHandler
|
||||||
|
@@ -1,127 +1,127 @@
|
|||||||
keys = {
|
keys = {
|
||||||
'accept': 30,
|
'accept': 30,
|
||||||
'add': 107,
|
'add': 107,
|
||||||
'apps': 93,
|
'apps': 93,
|
||||||
'attn': 246,
|
'attn': 246,
|
||||||
'back': 8,
|
'back': 8,
|
||||||
'browser_back': 166,
|
'browser_back': 166,
|
||||||
'browser_forward': 167,
|
'browser_forward': 167,
|
||||||
'cancel': 3,
|
'cancel': 3,
|
||||||
'capital': 20,
|
'capital': 20,
|
||||||
'clear': 12,
|
'clear': 12,
|
||||||
'control': 17,
|
'control': 17,
|
||||||
'convert': 28,
|
'convert': 28,
|
||||||
'crsel': 247,
|
'crsel': 247,
|
||||||
'decimal': 110,
|
'decimal': 110,
|
||||||
'delete': 46,
|
'delete': 46,
|
||||||
'divide': 111,
|
'divide': 111,
|
||||||
'down': 40,
|
'down': 40,
|
||||||
'end': 35,
|
'end': 35,
|
||||||
'ereof': 249,
|
'ereof': 249,
|
||||||
'escape': 27,
|
'escape': 27,
|
||||||
'execute': 43,
|
'execute': 43,
|
||||||
'exsel': 248,
|
'exsel': 248,
|
||||||
'f1': 112,
|
'f1': 112,
|
||||||
'f10': 121,
|
'f10': 121,
|
||||||
'f11': 122,
|
'f11': 122,
|
||||||
'f12': 123,
|
'f12': 123,
|
||||||
'f13': 124,
|
'f13': 124,
|
||||||
'f14': 125,
|
'f14': 125,
|
||||||
'f15': 126,
|
'f15': 126,
|
||||||
'f16': 127,
|
'f16': 127,
|
||||||
'f17': 128,
|
'f17': 128,
|
||||||
'f18': 129,
|
'f18': 129,
|
||||||
'f19': 130,
|
'f19': 130,
|
||||||
'f2': 113,
|
'f2': 113,
|
||||||
'f20': 131,
|
'f20': 131,
|
||||||
'f21': 132,
|
'f21': 132,
|
||||||
'f22': 133,
|
'f22': 133,
|
||||||
'f23': 134,
|
'f23': 134,
|
||||||
'f24': 135,
|
'f24': 135,
|
||||||
'f3': 114,
|
'f3': 114,
|
||||||
'f4': 115,
|
'f4': 115,
|
||||||
'f5': 116,
|
'f5': 116,
|
||||||
'f6': 117,
|
'f6': 117,
|
||||||
'f7': 118,
|
'f7': 118,
|
||||||
'f8': 119,
|
'f8': 119,
|
||||||
'f9': 120,
|
'f9': 120,
|
||||||
'final': 24,
|
'final': 24,
|
||||||
'hangeul': 21,
|
'hangeul': 21,
|
||||||
'hangul': 21,
|
'hangul': 21,
|
||||||
'hanja': 25,
|
'hanja': 25,
|
||||||
'help': 47,
|
'help': 47,
|
||||||
'home': 36,
|
'home': 36,
|
||||||
'insert': 45,
|
'insert': 45,
|
||||||
'junja': 23,
|
'junja': 23,
|
||||||
'kana': 21,
|
'kana': 21,
|
||||||
'kanji': 25,
|
'kanji': 25,
|
||||||
'lbutton': 1,
|
'lbutton': 1,
|
||||||
'lcontrol': 162,
|
'lcontrol': 162,
|
||||||
'left': 37,
|
'left': 37,
|
||||||
'lmenu': 164,
|
'lmenu': 164,
|
||||||
'lshift': 160,
|
'lshift': 160,
|
||||||
'lwin': 91,
|
'lwin': 91,
|
||||||
'mbutton': 4,
|
'mbutton': 4,
|
||||||
'media_next_track': 176,
|
'media_next_track': 176,
|
||||||
'media_play_pause': 179,
|
'media_play_pause': 179,
|
||||||
'media_prev_track': 177,
|
'media_prev_track': 177,
|
||||||
'menu': 18,
|
'menu': 18,
|
||||||
'modechange': 31,
|
'modechange': 31,
|
||||||
'multiply': 106,
|
'multiply': 106,
|
||||||
'next': 34,
|
'next': 34,
|
||||||
'noname': 252,
|
'noname': 252,
|
||||||
'nonconvert': 29,
|
'nonconvert': 29,
|
||||||
'numlock': 144,
|
'numlock': 144,
|
||||||
'numpad0': 96,
|
'numpad0': 96,
|
||||||
'numpad1': 97,
|
'numpad1': 97,
|
||||||
'numpad2': 98,
|
'numpad2': 98,
|
||||||
'numpad3': 99,
|
'numpad3': 99,
|
||||||
'numpad4': 100,
|
'numpad4': 100,
|
||||||
'numpad5': 101,
|
'numpad5': 101,
|
||||||
'numpad6': 102,
|
'numpad6': 102,
|
||||||
'numpad7': 103,
|
'numpad7': 103,
|
||||||
'numpad8': 104,
|
'numpad8': 104,
|
||||||
'numpad9': 105,
|
'numpad9': 105,
|
||||||
'oem_clear': 254,
|
'oem_clear': 254,
|
||||||
'pa1': 253,
|
'pa1': 253,
|
||||||
'pagedown': 34,
|
'pagedown': 34,
|
||||||
'pageup': 33,
|
'pageup': 33,
|
||||||
'pause': 19,
|
'pause': 19,
|
||||||
'play': 250,
|
'play': 250,
|
||||||
'print': 42,
|
'print': 42,
|
||||||
'prior': 33,
|
'prior': 33,
|
||||||
'processkey': 229,
|
'processkey': 229,
|
||||||
'rbutton': 2,
|
'rbutton': 2,
|
||||||
'rcontrol': 163,
|
'rcontrol': 163,
|
||||||
'return': 13,
|
'return': 13,
|
||||||
'right': 39,
|
'right': 39,
|
||||||
'rmenu': 165,
|
'rmenu': 165,
|
||||||
'rshift': 161,
|
'rshift': 161,
|
||||||
'rwin': 92,
|
'rwin': 92,
|
||||||
'scroll': 145,
|
'scroll': 145,
|
||||||
'select': 41,
|
'select': 41,
|
||||||
'separator': 108,
|
'separator': 108,
|
||||||
'shift': 16,
|
'shift': 16,
|
||||||
'snapshot': 44,
|
'snapshot': 44,
|
||||||
'space': 32,
|
'space': 32,
|
||||||
'subtract': 109,
|
'subtract': 109,
|
||||||
'tab': 9,
|
'tab': 9,
|
||||||
'up': 38,
|
'up': 38,
|
||||||
'volume_down': 174,
|
'volume_down': 174,
|
||||||
'volume_mute': 173,
|
'volume_mute': 173,
|
||||||
'volume_up': 175,
|
'volume_up': 175,
|
||||||
'xbutton1': 5,
|
'xbutton1': 5,
|
||||||
'xbutton2': 6,
|
'xbutton2': 6,
|
||||||
'zoom': 251,
|
'zoom': 251,
|
||||||
'/': 191,
|
'/': 191,
|
||||||
';': 218,
|
';': 218,
|
||||||
'[': 219,
|
'[': 219,
|
||||||
'\\': 220,
|
'\\': 220,
|
||||||
']': 221,
|
']': 221,
|
||||||
'\'': 222,
|
'\'': 222,
|
||||||
'=': 187,
|
'=': 187,
|
||||||
'-': 189,
|
'-': 189,
|
||||||
';': 186,
|
';': 186,
|
||||||
}
|
}
|
||||||
|
|
||||||
modifiers = {'alt': 1, 'control': 2, 'shift': 4, 'win': 8}
|
modifiers = {'alt': 1, 'control': 2, 'shift': 4, 'win': 8}
|
||||||
|
@@ -3,56 +3,56 @@ import threading
|
|||||||
import thread
|
import thread
|
||||||
import pyatspi
|
import pyatspi
|
||||||
def parse(s):
|
def parse(s):
|
||||||
"""parse a string like control+f into (modifier, key).
|
"""parse a string like control+f into (modifier, key).
|
||||||
Unknown modifiers will return ValueError."""
|
Unknown modifiers will return ValueError."""
|
||||||
m = 0
|
m = 0
|
||||||
lst = s.split('+')
|
lst = s.split('+')
|
||||||
if not len(lst): return (0, s)
|
if not len(lst): return (0, s)
|
||||||
#Are these right?
|
#Are these right?
|
||||||
d = {
|
d = {
|
||||||
"shift": 1<<pyatspi.MODIFIER_SHIFT,
|
"shift": 1<<pyatspi.MODIFIER_SHIFT,
|
||||||
"control": 1<<pyatspi.MODIFIER_CONTROL,
|
"control": 1<<pyatspi.MODIFIER_CONTROL,
|
||||||
"alt": 1<<pyatspi.MODIFIER_ALT,
|
"alt": 1<<pyatspi.MODIFIER_ALT,
|
||||||
"win":1<<pyatspi.MODIFIER_META3,
|
"win":1<<pyatspi.MODIFIER_META3,
|
||||||
}
|
}
|
||||||
for item in lst:
|
for item in lst:
|
||||||
if item in d:
|
if item in d:
|
||||||
m|=d[item]
|
m|=d[item]
|
||||||
lst.remove(item)
|
lst.remove(item)
|
||||||
#end if
|
#end if
|
||||||
if len(lst) > 1: #more than one key, parse error
|
if len(lst) > 1: #more than one key, parse error
|
||||||
raise ValueError, 'unknown modifier %s' % lst[0]
|
raise ValueError, 'unknown modifier %s' % lst[0]
|
||||||
return (m, lst[0].lower())
|
return (m, lst[0].lower())
|
||||||
class AtspiThread(threading.Thread):
|
class AtspiThread(threading.Thread):
|
||||||
def run(self):
|
def run(self):
|
||||||
pyatspi.Registry.registerKeystrokeListener(handler, kind=(pyatspi.KEY_PRESSED_EVENT,),
|
pyatspi.Registry.registerKeystrokeListener(handler, kind=(pyatspi.KEY_PRESSED_EVENT,),
|
||||||
mask=pyatspi.allModifiers())
|
mask=pyatspi.allModifiers())
|
||||||
pyatspi.Registry.start()
|
pyatspi.Registry.start()
|
||||||
#the keys we registered
|
#the keys we registered
|
||||||
keys = {}
|
keys = {}
|
||||||
def handler(e):
|
def handler(e):
|
||||||
m,k = e.modifiers,e.event_string.lower()
|
m,k = e.modifiers,e.event_string.lower()
|
||||||
#not sure why we can't catch control+f. Try to fix it.
|
#not sure why we can't catch control+f. Try to fix it.
|
||||||
if (not e.is_text) and e.id >= 97 <= 126:
|
if (not e.is_text) and e.id >= 97 <= 126:
|
||||||
k = chr(e.id)
|
k = chr(e.id)
|
||||||
if (m,k) not in keys: return False
|
if (m,k) not in keys: return False
|
||||||
thread.start_new(keys[(m,k)], ())
|
thread.start_new(keys[(m,k)], ())
|
||||||
return True #don't pass it on
|
return True #don't pass it on
|
||||||
class LinuxKeyboardHandler(KeyboardHandler):
|
class LinuxKeyboardHandler(KeyboardHandler):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
KeyboardHandler.__init__(self, *args, **kwargs)
|
KeyboardHandler.__init__(self, *args, **kwargs)
|
||||||
t = AtspiThread()
|
t = AtspiThread()
|
||||||
t.start()
|
t.start()
|
||||||
def register_key(self, key, function):
|
def register_key(self, key, function):
|
||||||
"""key will be a string, such as control+shift+f.
|
"""key will be a string, such as control+shift+f.
|
||||||
We need to convert that, using parse_key,
|
We need to convert that, using parse_key,
|
||||||
into modifier and key to put into our dictionary."""
|
into modifier and key to put into our dictionary."""
|
||||||
#register key so we know if we have it on event receive.
|
#register key so we know if we have it on event receive.
|
||||||
t = parse(key)
|
t = parse(key)
|
||||||
keys[t] = function
|
keys[t] = function
|
||||||
#if we got this far, the key is valid.
|
#if we got this far, the key is valid.
|
||||||
KeyboardHandler.register_key(self, key, function)
|
KeyboardHandler.register_key(self, key, function)
|
||||||
|
|
||||||
def unregister_key (self, key, function):
|
def unregister_key (self, key, function):
|
||||||
KeyboardHandler.unregister_key(self, key, function)
|
KeyboardHandler.unregister_key(self, key, function)
|
||||||
del keys[parse(key)]
|
del keys[parse(key)]
|
||||||
|
@@ -5,84 +5,84 @@ class KeyboardHandlerError (Exception): pass
|
|||||||
|
|
||||||
class KeyboardHandler(object):
|
class KeyboardHandler(object):
|
||||||
|
|
||||||
def __init__(self, repeat_rate=0.0, *args, **kwargs):
|
def __init__(self, repeat_rate=0.0, *args, **kwargs):
|
||||||
self.repeat_rate = repeat_rate #How long between accepting the same keystroke?
|
self.repeat_rate = repeat_rate #How long between accepting the same keystroke?
|
||||||
self._last_key = None
|
self._last_key = None
|
||||||
self._last_keypress_time = 0
|
self._last_keypress_time = 0
|
||||||
super(KeyboardHandler, self).__init__(*args, **kwargs)
|
super(KeyboardHandler, self).__init__(*args, **kwargs)
|
||||||
self.active_keys = {}
|
self.active_keys = {}
|
||||||
if not hasattr(self, 'replacement_mods'):
|
if not hasattr(self, 'replacement_mods'):
|
||||||
self.replacement_mods = {}
|
self.replacement_mods = {}
|
||||||
if not hasattr(self, 'replacement_keys'):
|
if not hasattr(self, 'replacement_keys'):
|
||||||
self.replacement_keys = {}
|
self.replacement_keys = {}
|
||||||
|
|
||||||
def register_key (self, key, function):
|
def register_key (self, key, function):
|
||||||
if key in self.active_keys:
|
if key in self.active_keys:
|
||||||
raise KeyboardHandlerError("Key %s is already registered to a function" % key)
|
raise KeyboardHandlerError("Key %s is already registered to a function" % key)
|
||||||
if not callable(function):
|
if not callable(function):
|
||||||
raise TypeError("Must provide a callable to be invoked upon keypress")
|
raise TypeError("Must provide a callable to be invoked upon keypress")
|
||||||
self.active_keys[key] = function
|
self.active_keys[key] = function
|
||||||
|
|
||||||
def unregister_key (self, key, function):
|
def unregister_key (self, key, function):
|
||||||
try:
|
try:
|
||||||
if self.active_keys[key] != function:
|
if self.active_keys[key] != function:
|
||||||
raise KeyboardHandlerError("key %s is not registered to that function" % key)
|
raise KeyboardHandlerError("key %s is not registered to that function" % key)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise KeyboardHandlerError("Key %s not currently registered" % key)
|
raise KeyboardHandlerError("Key %s not currently registered" % key)
|
||||||
del(self.active_keys[key])
|
del(self.active_keys[key])
|
||||||
|
|
||||||
def unregister_all_keys(self):
|
def unregister_all_keys(self):
|
||||||
for key in list(self.active_keys):
|
for key in list(self.active_keys):
|
||||||
self.unregister_key(key, self.active_keys[key])
|
self.unregister_key(key, self.active_keys[key])
|
||||||
|
|
||||||
def handle_key (self, key):
|
def handle_key (self, key):
|
||||||
if self.repeat_rate and key == self._last_key and time.time() - self._last_keypress_time < self.repeat_rate:
|
if self.repeat_rate and key == self._last_key and time.time() - self._last_keypress_time < self.repeat_rate:
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
function = self.active_keys[key]
|
function = self.active_keys[key]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return
|
return
|
||||||
self._last_key = key
|
self._last_key = key
|
||||||
self._last_keypress_time = time.time()
|
self._last_keypress_time = time.time()
|
||||||
return function()
|
return function()
|
||||||
|
|
||||||
def register_keys(self, keys):
|
def register_keys(self, keys):
|
||||||
"""Given a mapping of keystrokes to functions, registers all keystrokes"""
|
"""Given a mapping of keystrokes to functions, registers all keystrokes"""
|
||||||
for k in keys:
|
for k in keys:
|
||||||
self.register_key(k, keys[k])
|
self.register_key(k, keys[k])
|
||||||
|
|
||||||
def unregister_keys(self, keys):
|
def unregister_keys(self, keys):
|
||||||
"""Given a mapping of keys to their functions, unregisters all provided keys."""
|
"""Given a mapping of keys to their functions, unregisters all provided keys."""
|
||||||
for k in keys:
|
for k in keys:
|
||||||
self.unregister_key(k, keys[k])
|
self.unregister_key(k, keys[k])
|
||||||
|
|
||||||
def standardize_key(self, key):
|
def standardize_key(self, key):
|
||||||
"""Takes a keystroke and places it in a standard case and order in a list."""
|
"""Takes a keystroke and places it in a standard case and order in a list."""
|
||||||
working = key.split('+')
|
working = key.split('+')
|
||||||
working = [i.lower() for i in working]
|
working = [i.lower() for i in working]
|
||||||
answer = []
|
answer = []
|
||||||
if "control" in working:
|
if "control" in working:
|
||||||
answer.append("control")
|
answer.append("control")
|
||||||
if "win" in working:
|
if "win" in working:
|
||||||
answer.append("win")
|
answer.append("win")
|
||||||
if "alt" in working:
|
if "alt" in working:
|
||||||
answer.append("alt")
|
answer.append("alt")
|
||||||
if "shift" in working:
|
if "shift" in working:
|
||||||
answer.append("shift")
|
answer.append("shift")
|
||||||
if working[-1] not in answer:
|
if working[-1] not in answer:
|
||||||
answer.append(working[-1])
|
answer.append(working[-1])
|
||||||
return answer
|
return answer
|
||||||
|
|
||||||
def standardize_keymap(self, keymap):
|
def standardize_keymap(self, keymap):
|
||||||
"""Given a keymap, returns the keymap standardized."""
|
"""Given a keymap, returns the keymap standardized."""
|
||||||
full = {}
|
full = {}
|
||||||
for i in keymap:
|
for i in keymap:
|
||||||
answer = ""
|
answer = ""
|
||||||
new = self.standardize_key(keymap[i])
|
new = self.standardize_key(keymap[i])
|
||||||
for (c, j) in enumerate(new):
|
for (c, j) in enumerate(new):
|
||||||
if c < len(new)-1:
|
if c < len(new)-1:
|
||||||
answer = "%s%s+" % (answer, j)
|
answer = "%s%s+" % (answer, j)
|
||||||
else:
|
else:
|
||||||
answer = "%s%s" % (answer, j)
|
answer = "%s%s" % (answer, j)
|
||||||
full[i] = answer
|
full[i] = answer
|
||||||
return full
|
return full
|
||||||
|
@@ -12,45 +12,45 @@ kEventHotKeyReleasedSubtype = 9
|
|||||||
|
|
||||||
class OSXKeyboardHandler(KeyboardHandler):
|
class OSXKeyboardHandler(KeyboardHandler):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(OSXKeyboardHandler, self).__init__()
|
super(OSXKeyboardHandler, self).__init__()
|
||||||
self.replacement_keys = dict()
|
self.replacement_keys = dict()
|
||||||
self.app = KeyboardCapturingNSApplication.alloc().init()
|
self.app = KeyboardCapturingNSApplication.alloc().init()
|
||||||
self._event_thread = Thread(target=AppHelper.runEventLoop)
|
self._event_thread = Thread(target=AppHelper.runEventLoop)
|
||||||
self._event_thread.start()
|
self._event_thread.start()
|
||||||
|
|
||||||
def register_key (self, key, function):
|
def register_key (self, key, function):
|
||||||
super(OSXKeyboardHandler, self).register_key(key, function)
|
super(OSXKeyboardHandler, self).register_key(key, function)
|
||||||
k, m = self.parse_key(key)
|
k, m = self.parse_key(key)
|
||||||
key_id = RegisterEventHotKey(k, m, (0, 0), GetApplicationEventTarget(), 0)
|
key_id = RegisterEventHotKey(k, m, (0, 0), GetApplicationEventTarget(), 0)
|
||||||
self.key_ids[key] = key_id
|
self.key_ids[key] = key_id
|
||||||
|
|
||||||
def unregister_key (self, key, function):
|
def unregister_key (self, key, function):
|
||||||
super(OSXKeyboardHandler, self).unregister_key(key, function)
|
super(OSXKeyboardHandler, self).unregister_key(key, function)
|
||||||
key_id = self.key_ids[key]
|
key_id = self.key_ids[key]
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def parse_key (self, key):
|
def parse_key (self, key):
|
||||||
key=key.split("+")
|
key=key.split("+")
|
||||||
#replacements
|
#replacements
|
||||||
#Modifier keys:
|
#Modifier keys:
|
||||||
for index, item in enumerate(key[0:-1]):
|
for index, item in enumerate(key[0:-1]):
|
||||||
if self.replacement_mods.has_key(item):
|
if self.replacement_mods.has_key(item):
|
||||||
key[index] = self.replacement_mods[item]
|
key[index] = self.replacement_mods[item]
|
||||||
if self.replacement_keys.has_key(key[-1]):
|
if self.replacement_keys.has_key(key[-1]):
|
||||||
key[-1] = self.replacement_keys[key[-1]]
|
key[-1] = self.replacement_keys[key[-1]]
|
||||||
elif len(key[-1])==1:
|
elif len(key[-1])==1:
|
||||||
key[-1] = ord(str(key[-1]))-36
|
key[-1] = ord(str(key[-1]))-36
|
||||||
mods = 0
|
mods = 0
|
||||||
for i in key[:-1]:
|
for i in key[:-1]:
|
||||||
mods = mods|i
|
mods = mods|i
|
||||||
return [key[-1], mods]
|
return [key[-1], mods]
|
||||||
|
|
||||||
class KeyboardCapturingNSApplication(NSApplication):
|
class KeyboardCapturingNSApplication(NSApplication):
|
||||||
|
|
||||||
def sendEvent_(self, theEvent):
|
def sendEvent_(self, theEvent):
|
||||||
if theEvent.type() == NSSystemDefined and theEvent.subtype() == kEventHotKeyPressedSubtype:
|
if theEvent.type() == NSSystemDefined and theEvent.subtype() == kEventHotKeyPressedSubtype:
|
||||||
self.activateIgnoringOtherApps_(True)
|
self.activateIgnoringOtherApps_(True)
|
||||||
NSRunAlertPanel(u'Hot Key Pressed', u'Hot Key Pressed', None, None, None)
|
NSRunAlertPanel(u'Hot Key Pressed', u'Hot Key Pressed', None, None, None)
|
||||||
super(NSApplication, self).sendEvent_(theEvent)
|
super(NSApplication, self).sendEvent_(theEvent)
|
||||||
|
|
||||||
|
@@ -5,36 +5,36 @@ from main import KeyboardHandler
|
|||||||
|
|
||||||
class WindowsKeyboardHandler(KeyboardHandler):
|
class WindowsKeyboardHandler(KeyboardHandler):
|
||||||
|
|
||||||
def __init__ (self, *args, **kwargs):
|
def __init__ (self, *args, **kwargs):
|
||||||
super(WindowsKeyboardHandler, self).__init__(*args, **kwargs)
|
super(WindowsKeyboardHandler, self).__init__(*args, **kwargs)
|
||||||
#Setup the replacement dictionaries.
|
#Setup the replacement dictionaries.
|
||||||
for i in dir(win32con):
|
for i in dir(win32con):
|
||||||
if i.startswith("VK_"):
|
if i.startswith("VK_"):
|
||||||
key = i[3:].lower()
|
key = i[3:].lower()
|
||||||
self.replacement_keys[key] = getattr(win32con, i)
|
self.replacement_keys[key] = getattr(win32con, i)
|
||||||
elif i.startswith("MOD_"):
|
elif i.startswith("MOD_"):
|
||||||
key = i[4:].lower()
|
key = i[4:].lower()
|
||||||
self.replacement_mods[key] = getattr(win32con, i)
|
self.replacement_mods[key] = getattr(win32con, i)
|
||||||
self.replacement_keys .update(dict(pageup=win32con.VK_PRIOR, pagedown=win32con.VK_NEXT))
|
self.replacement_keys .update(dict(pageup=win32con.VK_PRIOR, pagedown=win32con.VK_NEXT))
|
||||||
|
|
||||||
def parse_key (self, keystroke, separator="+"):
|
def parse_key (self, keystroke, separator="+"):
|
||||||
keystroke = str(keystroke) #We don't want unicode
|
keystroke = str(keystroke) #We don't want unicode
|
||||||
keystroke = [self.keycode_from_key(i) for i in keystroke.split(separator)]
|
keystroke = [self.keycode_from_key(i) for i in keystroke.split(separator)]
|
||||||
mods = 0
|
mods = 0
|
||||||
for i in keystroke[:-1]:
|
for i in keystroke[:-1]:
|
||||||
mods = mods | i #or everything together
|
mods = mods | i #or everything together
|
||||||
return (mods, keystroke[-1])
|
return (mods, keystroke[-1])
|
||||||
|
|
||||||
def keycode_from_key(self, key):
|
def keycode_from_key(self, key):
|
||||||
if key in self.replacement_mods:
|
if key in self.replacement_mods:
|
||||||
return self.replacement_mods[key]
|
return self.replacement_mods[key]
|
||||||
if key in self.replacement_keys:
|
if key in self.replacement_keys:
|
||||||
return self.replacement_keys[key]
|
return self.replacement_keys[key]
|
||||||
if len(key) == 1:
|
if len(key) == 1:
|
||||||
return win32api.VkKeyScanEx(key, win32api.GetKeyboardLayout())
|
return win32api.VkKeyScanEx(key, win32api.GetKeyboardLayout())
|
||||||
|
|
||||||
def is_key_pressed(self, key):
|
def is_key_pressed(self, key):
|
||||||
"""Returns if the given key was pressed. Requires an active message loop or will simply give if the key was pressed recently."""
|
"""Returns if the given key was pressed. Requires an active message loop or will simply give if the key was pressed recently."""
|
||||||
key = self.keycode_from_key(key)
|
key = self.keycode_from_key(key)
|
||||||
return win32api.GetAsyncKeyState(key)
|
return win32api.GetAsyncKeyState(key)
|
||||||
|
|
||||||
|
@@ -10,121 +10,121 @@ from . import key_constants
|
|||||||
__all__ = ['WXKeyboardHandler', 'WXControlKeyboardHandler']
|
__all__ = ['WXKeyboardHandler', 'WXControlKeyboardHandler']
|
||||||
|
|
||||||
def call_after(func):
|
def call_after(func):
|
||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
wx.CallAfter(func, *args, **kwargs)
|
wx.CallAfter(func, *args, **kwargs)
|
||||||
functools.update_wrapper(wrapper, func)
|
functools.update_wrapper(wrapper, func)
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
class BaseWXKeyboardHandler(KeyboardHandler):
|
class BaseWXKeyboardHandler(KeyboardHandler):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(BaseWXKeyboardHandler, self).__init__(*args, **kwargs)
|
super(BaseWXKeyboardHandler, self).__init__(*args, **kwargs)
|
||||||
#Setup the replacement dictionaries.
|
#Setup the replacement dictionaries.
|
||||||
for i in dir(wx):
|
for i in dir(wx):
|
||||||
if i.startswith('WXK_'):
|
if i.startswith('WXK_'):
|
||||||
key = i[4:].lower()
|
key = i[4:].lower()
|
||||||
self.replacement_keys[key] = getattr(wx, i)
|
self.replacement_keys[key] = getattr(wx, i)
|
||||||
elif i.startswith('MOD_'):
|
elif i.startswith('MOD_'):
|
||||||
key = i[4:].lower()
|
key = i[4:].lower()
|
||||||
self.replacement_mods[key] = getattr(wx, i)
|
self.replacement_mods[key] = getattr(wx, i)
|
||||||
|
|
||||||
def parse_key (self, keystroke, separator="+"):
|
def parse_key (self, keystroke, separator="+"):
|
||||||
keystroke = [self.keycode_from_key(i) for i in keystroke.split(separator)]
|
keystroke = [self.keycode_from_key(i) for i in keystroke.split(separator)]
|
||||||
mods = 0
|
mods = 0
|
||||||
for i in keystroke[:-1]:
|
for i in keystroke[:-1]:
|
||||||
mods = mods | i #or everything together
|
mods = mods | i #or everything together
|
||||||
return (mods, keystroke[-1])
|
return (mods, keystroke[-1])
|
||||||
|
|
||||||
def keycode_from_key(self, key):
|
def keycode_from_key(self, key):
|
||||||
result = None
|
result = None
|
||||||
if key in self.replacement_mods:
|
if key in self.replacement_mods:
|
||||||
result = self.replacement_mods[key]
|
result = self.replacement_mods[key]
|
||||||
elif key in self.replacement_keys:
|
elif key in self.replacement_keys:
|
||||||
result = self.replacement_keys[key]
|
result = self.replacement_keys[key]
|
||||||
if result >= 277:
|
if result >= 277:
|
||||||
result -= 277
|
result -= 277
|
||||||
elif len(key) == 1:
|
elif len(key) == 1:
|
||||||
result = ord(key.upper())
|
result = ord(key.upper())
|
||||||
if result is None:
|
if result is None:
|
||||||
raise KeyboardHandlerError("Could not translate key %r into a valid keycode." % key)
|
raise KeyboardHandlerError("Could not translate key %r into a valid keycode." % key)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class WXKeyboardHandler(BaseWXKeyboardHandler):
|
class WXKeyboardHandler(BaseWXKeyboardHandler):
|
||||||
|
|
||||||
def __init__ (self, parent, *args, **kwargs):
|
def __init__ (self, parent, *args, **kwargs):
|
||||||
super(WXKeyboardHandler, self).__init__(*args, **kwargs)
|
super(WXKeyboardHandler, self).__init__(*args, **kwargs)
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
self.key_ids = {}
|
self.key_ids = {}
|
||||||
self.replacement_keys = key_constants.keys
|
self.replacement_keys = key_constants.keys
|
||||||
self.replacement_mods = key_constants.modifiers
|
self.replacement_mods = key_constants.modifiers
|
||||||
|
|
||||||
@call_after
|
@call_after
|
||||||
def register_key(self, key, function):
|
def register_key(self, key, function):
|
||||||
super(WXKeyboardHandler, self).register_key(key, function)
|
super(WXKeyboardHandler, self).register_key(key, function)
|
||||||
key_id = wx.NewId()
|
key_id = wx.NewId()
|
||||||
parsed = self.parse_key(key)
|
parsed = self.parse_key(key)
|
||||||
res = self.parent.RegisterHotKey(key_id, *parsed)
|
res = self.parent.RegisterHotKey(key_id, *parsed)
|
||||||
if not res:
|
if not res:
|
||||||
logger.warn("Failed to register hotkey: %s for function %r", key, function)
|
logger.warn("Failed to register hotkey: %s for function %r", key, function)
|
||||||
self.parent.Bind(wx.EVT_HOTKEY, lambda evt: self.process_key(evt, key_id), id=key_id)
|
self.parent.Bind(wx.EVT_HOTKEY, lambda evt: self.process_key(evt, key_id), id=key_id)
|
||||||
self.key_ids[key] = key_id
|
self.key_ids[key] = key_id
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def parse_key (self, keystroke, separator="+"):
|
def parse_key (self, keystroke, separator="+"):
|
||||||
keystroke = str(keystroke) #We don't want unicode
|
keystroke = str(keystroke) #We don't want unicode
|
||||||
keystroke = [self.keycode_from_key(i) for i in keystroke.split(separator)]
|
keystroke = [self.keycode_from_key(i) for i in keystroke.split(separator)]
|
||||||
mods = 0
|
mods = 0
|
||||||
for i in keystroke[:-1]:
|
for i in keystroke[:-1]:
|
||||||
mods = mods | i #or everything together
|
mods = mods | i #or everything together
|
||||||
return (mods, keystroke[-1])
|
return (mods, keystroke[-1])
|
||||||
|
|
||||||
@call_after
|
@call_after
|
||||||
def unregister_key (self, key, function):
|
def unregister_key (self, key, function):
|
||||||
super(WXKeyboardHandler, self).unregister_key(key, function)
|
super(WXKeyboardHandler, self).unregister_key(key, function)
|
||||||
if key not in self.key_ids:
|
if key not in self.key_ids:
|
||||||
return #there's nothing we can do.
|
return #there's nothing we can do.
|
||||||
key_id = self.key_ids[key]
|
key_id = self.key_ids[key]
|
||||||
self.parent.UnregisterHotKey(key_id)
|
self.parent.UnregisterHotKey(key_id)
|
||||||
self.parent.Unbind( wx.EVT_HOTKEY, id=key_id)
|
self.parent.Unbind( wx.EVT_HOTKEY, id=key_id)
|
||||||
self.key_ids.pop(key)
|
self.key_ids.pop(key)
|
||||||
|
|
||||||
def process_key (self, evt, id):
|
def process_key (self, evt, id):
|
||||||
evt.Skip()
|
evt.Skip()
|
||||||
key_ids = self.key_ids.keys()
|
key_ids = self.key_ids.keys()
|
||||||
for i in key_ids:
|
for i in key_ids:
|
||||||
if self.key_ids.get(i) == id:
|
if self.key_ids.get(i) == id:
|
||||||
self.handle_key(i)
|
self.handle_key(i)
|
||||||
|
|
||||||
class WXControlKeyboardHandler(wx.StaticText, KeyboardHandler):
|
class WXControlKeyboardHandler(wx.StaticText, KeyboardHandler):
|
||||||
|
|
||||||
def __init__(self, parent=None, *a, **k):
|
def __init__(self, parent=None, *a, **k):
|
||||||
wx.StaticText.__init__(self, parent=parent)
|
wx.StaticText.__init__(self, parent=parent)
|
||||||
KeyboardHandler.__init__(self, *a, **k)
|
KeyboardHandler.__init__(self, *a, **k)
|
||||||
self.wx_replacements = {}
|
self.wx_replacements = {}
|
||||||
for i in [d for d in dir(wx) if d.startswith('WXK_')]:
|
for i in [d for d in dir(wx) if d.startswith('WXK_')]:
|
||||||
self.wx_replacements[getattr(wx, i)] = i[4:].lower()
|
self.wx_replacements[getattr(wx, i)] = i[4:].lower()
|
||||||
self.Bind(wx.EVT_KEY_DOWN, self.process_key, self)
|
self.Bind(wx.EVT_KEY_DOWN, self.process_key, self)
|
||||||
self.SetFocus()
|
self.SetFocus()
|
||||||
|
|
||||||
def process_key(self, evt):
|
def process_key(self, evt):
|
||||||
keycode = evt.GetKeyCode()
|
keycode = evt.GetKeyCode()
|
||||||
keyname = self.wx_replacements.get(keycode, None)
|
keyname = self.wx_replacements.get(keycode, None)
|
||||||
modifiers = ""
|
modifiers = ""
|
||||||
replacements = ( (evt.ControlDown(), 'control+'),
|
replacements = ( (evt.ControlDown(), 'control+'),
|
||||||
(evt.AltDown(), 'alt+'),
|
(evt.AltDown(), 'alt+'),
|
||||||
(evt.ShiftDown(), 'shift+'),
|
(evt.ShiftDown(), 'shift+'),
|
||||||
(evt.MetaDown(), 'win+')
|
(evt.MetaDown(), 'win+')
|
||||||
)
|
)
|
||||||
for mod, ch in (replacements):
|
for mod, ch in (replacements):
|
||||||
if mod:
|
if mod:
|
||||||
modifiers += ch
|
modifiers += ch
|
||||||
if keyname is None:
|
if keyname is None:
|
||||||
if 27 < keycode < 256:
|
if 27 < keycode < 256:
|
||||||
keyname = chr(keycode).lower()
|
keyname = chr(keycode).lower()
|
||||||
else:
|
else:
|
||||||
keyname = "(%s)unknown" % keycode
|
keyname = "(%s)unknown" % keycode
|
||||||
key = modifiers + keyname
|
key = modifiers + keyname
|
||||||
self.handle_key(key)
|
self.handle_key(key)
|
||||||
|
@@ -14,9 +14,9 @@ import paths
|
|||||||
# lib = load_library("snapshot_api_keys64", x64_path=paths.app_path("keys/lib"))
|
# lib = load_library("snapshot_api_keys64", x64_path=paths.app_path("keys/lib"))
|
||||||
#else:
|
#else:
|
||||||
if platform.architecture()[0][:2] == "32":
|
if platform.architecture()[0][:2] == "32":
|
||||||
lib = load_library("stable_api_keys32", x86_path=os.path.join(paths.app_path(), "keys", "lib"))
|
lib = load_library("stable_api_keys32", x86_path=os.path.join(paths.app_path(), "keys", "lib"))
|
||||||
else:
|
else:
|
||||||
lib = load_library("stable_api_keys64", x64_path=os.path.join(paths.app_path(), "keys", "lib"))
|
lib = load_library("stable_api_keys64", x64_path=os.path.join(paths.app_path(), "keys", "lib"))
|
||||||
|
|
||||||
# import linuxKeys
|
# import linuxKeys
|
||||||
# lib = linuxKeys
|
# lib = linuxKeys
|
||||||
@@ -24,20 +24,20 @@ else:
|
|||||||
keyring = None
|
keyring = None
|
||||||
|
|
||||||
def setup():
|
def setup():
|
||||||
global keyring
|
global keyring
|
||||||
if keyring == None:
|
if keyring == None:
|
||||||
keyring = Keyring()
|
keyring = Keyring()
|
||||||
|
|
||||||
class Keyring(object):
|
class Keyring(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(Keyring, self).__init__()
|
super(Keyring, self).__init__()
|
||||||
|
|
||||||
def _call_method(self, function):
|
def _call_method(self, function):
|
||||||
result = getattr(lib, function)
|
result = getattr(lib, function)
|
||||||
result = c_char_p(result.__call__())
|
result = c_char_p(result.__call__())
|
||||||
return result.value
|
return result.value
|
||||||
|
|
||||||
def get(self, func):
|
def get(self, func):
|
||||||
if hasattr(application,func+"_override"):
|
if hasattr(application,func+"_override"):
|
||||||
return getattr(application,func+'_override')
|
return getattr(application,func+'_override')
|
||||||
return getattr(self, "_call_method")("get_"+func)
|
return getattr(self, "_call_method")("get_"+func)
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
def get_api_key():
|
def get_api_key():
|
||||||
return "8pDLbyOW3saYnvSZ4uLFg\0"
|
return "8pDLbyOW3saYnvSZ4uLFg\0"
|
||||||
|
|
||||||
def get_api_secret():
|
def get_api_secret():
|
||||||
return "YsgdrzY9B4yyYvYsyee78rKI3GshjHpenVS9LnFJXY\0";
|
return "YsgdrzY9B4yyYvYsyee78rKI3GshjHpenVS9LnFJXY\0";
|
||||||
|
|
||||||
#char *get_dropbox_api_key(){
|
#char *get_dropbox_api_key(){
|
||||||
#return "key\0";
|
#return "key\0";
|
||||||
|
@@ -1,60 +1,60 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
actions = {
|
actions = {
|
||||||
"up": _(u"Go up in the current buffer"),
|
"up": _(u"Go up in the current buffer"),
|
||||||
"down": _(u"Go down in the current buffer"),
|
"down": _(u"Go down in the current buffer"),
|
||||||
"left": _(u"Go to the previous buffer"),
|
"left": _(u"Go to the previous buffer"),
|
||||||
"right": _(u"Go to the next buffer"),
|
"right": _(u"Go to the next buffer"),
|
||||||
"next_account": _(u"Focus the next session"),
|
"next_account": _(u"Focus the next session"),
|
||||||
"previous_account": _(u"Focus the previous session"),
|
"previous_account": _(u"Focus the previous session"),
|
||||||
"show_hide": _(u"Show or hide the GUI"),
|
"show_hide": _(u"Show or hide the GUI"),
|
||||||
"post_tweet": _(u"New tweet"),
|
"post_tweet": _(u"New tweet"),
|
||||||
"post_reply": _(u"Reply"),
|
"post_reply": _(u"Reply"),
|
||||||
"post_retweet": _(u"Retweet"),
|
"post_retweet": _(u"Retweet"),
|
||||||
"send_dm": _(u"Send direct message"),
|
"send_dm": _(u"Send direct message"),
|
||||||
"add_to_favourites": _(u"Like a tweet"),
|
"add_to_favourites": _(u"Like a tweet"),
|
||||||
"toggle_like": _(u"Like/unlike a tweet"),
|
"toggle_like": _(u"Like/unlike a tweet"),
|
||||||
"remove_from_favourites": _(u"Unlike a tweet"),
|
"remove_from_favourites": _(u"Unlike a tweet"),
|
||||||
"follow": _(u"Open the user actions dialogue"),
|
"follow": _(u"Open the user actions dialogue"),
|
||||||
"user_details": _(u"See user details"),
|
"user_details": _(u"See user details"),
|
||||||
"view_item": _(u"Show tweet"),
|
"view_item": _(u"Show tweet"),
|
||||||
"exit": _(u"Quit"),
|
"exit": _(u"Quit"),
|
||||||
"open_timeline": _(u"Open user timeline"),
|
"open_timeline": _(u"Open user timeline"),
|
||||||
"remove_buffer": _(u"Destroy buffer"),
|
"remove_buffer": _(u"Destroy buffer"),
|
||||||
"interact": _(u"Interact with the currently focused tweet."),
|
"interact": _(u"Interact with the currently focused tweet."),
|
||||||
"url": _(u"Open URL"),
|
"url": _(u"Open URL"),
|
||||||
"open_in_browser": _(u"View in Twitter"),
|
"open_in_browser": _(u"View in Twitter"),
|
||||||
"volume_up": _(u"Increase volume by 5%"),
|
"volume_up": _(u"Increase volume by 5%"),
|
||||||
"volume_down": _(u"Decrease volume by 5%"),
|
"volume_down": _(u"Decrease volume by 5%"),
|
||||||
"go_home": _(u"Jump to the first element of a buffer"),
|
"go_home": _(u"Jump to the first element of a buffer"),
|
||||||
"go_end": _(u"Jump to the last element of the current buffer"),
|
"go_end": _(u"Jump to the last element of the current buffer"),
|
||||||
"go_page_up": _(u"Jump 20 elements up in the current buffer"),
|
"go_page_up": _(u"Jump 20 elements up in the current buffer"),
|
||||||
"go_page_down": _(u"Jump 20 elements down in the current buffer"),
|
"go_page_down": _(u"Jump 20 elements down in the current buffer"),
|
||||||
"update_profile": _(u"Edit profile"),
|
"update_profile": _(u"Edit profile"),
|
||||||
"delete": _(u"Delete a tweet or direct message"),
|
"delete": _(u"Delete a tweet or direct message"),
|
||||||
"clear_buffer": _(u"Empty the current buffer"),
|
"clear_buffer": _(u"Empty the current buffer"),
|
||||||
"repeat_item": _(u"Repeat last item"),
|
"repeat_item": _(u"Repeat last item"),
|
||||||
"copy_to_clipboard": _(u"Copy to clipboard"),
|
"copy_to_clipboard": _(u"Copy to clipboard"),
|
||||||
"add_to_list": _(u"Add to list"),
|
"add_to_list": _(u"Add to list"),
|
||||||
"remove_from_list": _(u"Remove from list"),
|
"remove_from_list": _(u"Remove from list"),
|
||||||
"toggle_buffer_mute": _(u"Mute/unmute the active buffer"),
|
"toggle_buffer_mute": _(u"Mute/unmute the active buffer"),
|
||||||
"toggle_session_mute": _(u"Mute/unmute the current session"),
|
"toggle_session_mute": _(u"Mute/unmute the current session"),
|
||||||
"toggle_autoread": _(u"toggle the automatic reading of incoming tweets in the active buffer"),
|
"toggle_autoread": _(u"toggle the automatic reading of incoming tweets in the active buffer"),
|
||||||
"search": _(u"Search on twitter"),
|
"search": _(u"Search on twitter"),
|
||||||
"find": _(u"Find a string in the currently focused buffer"),
|
"find": _(u"Find a string in the currently focused buffer"),
|
||||||
"edit_keystrokes": _(u"Show the keystroke editor"),
|
"edit_keystrokes": _(u"Show the keystroke editor"),
|
||||||
"view_user_lists": _(u"Show lists for a specified user"),
|
"view_user_lists": _(u"Show lists for a specified user"),
|
||||||
"get_more_items": _(u"load previous items"),
|
"get_more_items": _(u"load previous items"),
|
||||||
"reverse_geocode": _(u"Get geolocation"),
|
"reverse_geocode": _(u"Get geolocation"),
|
||||||
"view_reverse_geocode": _(u"Display the tweet's geolocation in a dialog"),
|
"view_reverse_geocode": _(u"Display the tweet's geolocation in a dialog"),
|
||||||
"get_trending_topics": _(u"Create a trending topics buffer"),
|
"get_trending_topics": _(u"Create a trending topics buffer"),
|
||||||
"open_conversation": _(u"View conversation"),
|
"open_conversation": _(u"View conversation"),
|
||||||
"check_for_updates": _(u"Check and download updates"),
|
"check_for_updates": _(u"Check and download updates"),
|
||||||
"lists_manager": _(u"Opens the list manager, which allows you to create, edit, delete and open lists in buffers."),
|
"lists_manager": _(u"Opens the list manager, which allows you to create, edit, delete and open lists in buffers."),
|
||||||
"configuration": _(u"Opens the global settings dialogue"),
|
"configuration": _(u"Opens the global settings dialogue"),
|
||||||
"list_manager": _(u"Opens the list manager"),
|
"list_manager": _(u"Opens the list manager"),
|
||||||
"accountConfiguration": _(u"Opens the account settings dialogue"),
|
"accountConfiguration": _(u"Opens the account settings dialogue"),
|
||||||
"audio": _(u"Try to play an audio file"),
|
"audio": _(u"Try to play an audio file"),
|
||||||
"update_buffer": _(u"Updates the buffer and retrieves possible lost items there."),
|
"update_buffer": _(u"Updates the buffer and retrieves possible lost items there."),
|
||||||
"ocr_image": _(u"Extracts the text from a picture and displays the result in a dialog."),
|
"ocr_image": _(u"Extracts the text from a picture and displays the result in a dialog."),
|
||||||
}
|
}
|
@@ -9,53 +9,53 @@ from . import constants
|
|||||||
from pubsub import pub
|
from pubsub import pub
|
||||||
|
|
||||||
class KeystrokeEditor(object):
|
class KeystrokeEditor(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(KeystrokeEditor, self).__init__()
|
super(KeystrokeEditor, self).__init__()
|
||||||
self.changed = False # Change it if the keyboard shorcuts are reassigned.
|
self.changed = False # Change it if the keyboard shorcuts are reassigned.
|
||||||
self.dialog = wx_ui.keystrokeEditorDialog()
|
self.dialog = wx_ui.keystrokeEditorDialog()
|
||||||
self.map = config.keymap["keymap"]
|
self.map = config.keymap["keymap"]
|
||||||
# we need to copy the keymap before modify it, for unregistering the old keystrokes if is needed.
|
# we need to copy the keymap before modify it, for unregistering the old keystrokes if is needed.
|
||||||
self.hold_map = self.map.copy()
|
self.hold_map = self.map.copy()
|
||||||
self.dialog.put_keystrokes(constants.actions, self.map)
|
self.dialog.put_keystrokes(constants.actions, self.map)
|
||||||
widgetUtils.connect_event(self.dialog.edit, widgetUtils.BUTTON_PRESSED, self.edit_keystroke)
|
widgetUtils.connect_event(self.dialog.edit, widgetUtils.BUTTON_PRESSED, self.edit_keystroke)
|
||||||
widgetUtils.connect_event(self.dialog.execute, widgetUtils.BUTTON_PRESSED, self.execute_action)
|
widgetUtils.connect_event(self.dialog.execute, widgetUtils.BUTTON_PRESSED, self.execute_action)
|
||||||
self.dialog.get_response()
|
self.dialog.get_response()
|
||||||
|
|
||||||
def edit_keystroke(self, *args, **kwargs):
|
def edit_keystroke(self, *args, **kwargs):
|
||||||
action = self.dialog.actions[self.dialog.get_action()]
|
action = self.dialog.actions[self.dialog.get_action()]
|
||||||
edit_dialog = wx_ui.editKeystrokeDialog()
|
edit_dialog = wx_ui.editKeystrokeDialog()
|
||||||
self.set_keystroke(self.map[action], edit_dialog)
|
self.set_keystroke(self.map[action], edit_dialog)
|
||||||
answer = edit_dialog.get_response()
|
answer = edit_dialog.get_response()
|
||||||
if answer == widgetUtils.OK:
|
if answer == widgetUtils.OK:
|
||||||
new_keystroke = self.get_edited_keystroke(edit_dialog)
|
new_keystroke = self.get_edited_keystroke(edit_dialog)
|
||||||
if new_keystroke != self.map[action]:
|
if new_keystroke != self.map[action]:
|
||||||
self.changed = True
|
self.changed = True
|
||||||
self.map[action] = new_keystroke
|
self.map[action] = new_keystroke
|
||||||
self.dialog.put_keystrokes(constants.actions, self.map)
|
self.dialog.put_keystrokes(constants.actions, self.map)
|
||||||
|
|
||||||
def set_keystroke(self, keystroke, dialog):
|
def set_keystroke(self, keystroke, dialog):
|
||||||
for i in keystroke.split("+"):
|
for i in keystroke.split("+"):
|
||||||
if hasattr(dialog, i):
|
if hasattr(dialog, i):
|
||||||
dialog.set(i, True)
|
dialog.set(i, True)
|
||||||
dialog.set("key", keystroke.split("+")[-1])
|
dialog.set("key", keystroke.split("+")[-1])
|
||||||
|
|
||||||
def get_edited_keystroke(self, dialog):
|
def get_edited_keystroke(self, dialog):
|
||||||
keys = []
|
keys = []
|
||||||
if dialog.get("control") == True:
|
if dialog.get("control") == True:
|
||||||
keys.append("control")
|
keys.append("control")
|
||||||
if dialog.get("win") == True:
|
if dialog.get("win") == True:
|
||||||
keys.append("win")
|
keys.append("win")
|
||||||
if dialog.get("alt") == True:
|
if dialog.get("alt") == True:
|
||||||
keys.append("alt")
|
keys.append("alt")
|
||||||
if dialog.get("shift") == True:
|
if dialog.get("shift") == True:
|
||||||
keys.append("shift")
|
keys.append("shift")
|
||||||
if dialog.get("key") != "":
|
if dialog.get("key") != "":
|
||||||
keys.append(dialog.get("key"))
|
keys.append(dialog.get("key"))
|
||||||
else:
|
else:
|
||||||
wx_ui.no_key()
|
wx_ui.no_key()
|
||||||
return
|
return
|
||||||
return "+".join(keys)
|
return "+".join(keys)
|
||||||
|
|
||||||
def execute_action(self, *args, **kwargs):
|
def execute_action(self, *args, **kwargs):
|
||||||
action = self.dialog.actions[self.dialog.get_action()]
|
action = self.dialog.actions[self.dialog.get_action()]
|
||||||
pub.sendMessage("execute-action", action=action)
|
pub.sendMessage("execute-action", action=action)
|
||||||
|
@@ -5,78 +5,78 @@ from multiplatform_widgets import widgets
|
|||||||
from wxUI.dialogs import baseDialog
|
from wxUI.dialogs import baseDialog
|
||||||
|
|
||||||
class keystrokeEditorDialog(baseDialog.BaseWXDialog):
|
class keystrokeEditorDialog(baseDialog.BaseWXDialog):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(keystrokeEditorDialog, self).__init__(parent=None, id=-1, title=_(u"Keystroke editor"))
|
super(keystrokeEditorDialog, self).__init__(parent=None, id=-1, title=_(u"Keystroke editor"))
|
||||||
panel = wx.Panel(self)
|
panel = wx.Panel(self)
|
||||||
self.actions = []
|
self.actions = []
|
||||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||||
keysText = wx.StaticText(panel, -1, _(u"Select a keystroke to edit"))
|
keysText = wx.StaticText(panel, -1, _(u"Select a keystroke to edit"))
|
||||||
self.keys = widgets.list(self, _(u"Action"), _(u"Keystroke"), style=wx.LC_REPORT|wx.LC_SINGLE_SEL, size=(400, 450))
|
self.keys = widgets.list(self, _(u"Action"), _(u"Keystroke"), style=wx.LC_REPORT|wx.LC_SINGLE_SEL, size=(400, 450))
|
||||||
self.keys.list.SetFocus()
|
self.keys.list.SetFocus()
|
||||||
firstSizer = wx.BoxSizer(wx.HORIZONTAL)
|
firstSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
firstSizer.Add(keysText, 0, wx.ALL, 5)
|
firstSizer.Add(keysText, 0, wx.ALL, 5)
|
||||||
firstSizer.Add(self.keys.list, 0, wx.ALL, 5)
|
firstSizer.Add(self.keys.list, 0, wx.ALL, 5)
|
||||||
self.edit = wx.Button(panel, -1, _(u"Edit"))
|
self.edit = wx.Button(panel, -1, _(u"Edit"))
|
||||||
self.edit.SetDefault()
|
self.edit.SetDefault()
|
||||||
self.execute = wx.Button(panel, -1, _(u"Execute action"))
|
self.execute = wx.Button(panel, -1, _(u"Execute action"))
|
||||||
close = wx.Button(panel, wx.ID_CANCEL, _(u"Close"))
|
close = wx.Button(panel, wx.ID_CANCEL, _(u"Close"))
|
||||||
secondSizer = wx.BoxSizer(wx.HORIZONTAL)
|
secondSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
secondSizer.Add(self.edit, 0, wx.ALL, 5)
|
secondSizer.Add(self.edit, 0, wx.ALL, 5)
|
||||||
secondSizer.Add(self.execute, 0, wx.ALL, 5)
|
secondSizer.Add(self.execute, 0, wx.ALL, 5)
|
||||||
secondSizer.Add(close, 0, wx.ALL, 5)
|
secondSizer.Add(close, 0, wx.ALL, 5)
|
||||||
sizer.Add(firstSizer, 0, wx.ALL, 5)
|
sizer.Add(firstSizer, 0, wx.ALL, 5)
|
||||||
sizer.Add(secondSizer, 0, wx.ALL, 5)
|
sizer.Add(secondSizer, 0, wx.ALL, 5)
|
||||||
panel.SetSizer(sizer)
|
panel.SetSizer(sizer)
|
||||||
self.SetClientSize(sizer.CalcMin())
|
self.SetClientSize(sizer.CalcMin())
|
||||||
|
|
||||||
def put_keystrokes(self, actions, keystrokes):
|
def put_keystrokes(self, actions, keystrokes):
|
||||||
selection = self.keys.get_selected()
|
selection = self.keys.get_selected()
|
||||||
self.keys.clear()
|
self.keys.clear()
|
||||||
for i in keystrokes:
|
for i in keystrokes:
|
||||||
if (i in actions) == False:
|
if (i in actions) == False:
|
||||||
continue
|
continue
|
||||||
action = actions[i]
|
action = actions[i]
|
||||||
self.actions.append(i)
|
self.actions.append(i)
|
||||||
keystroke = keystrokes[i]
|
keystroke = keystrokes[i]
|
||||||
self.keys.insert_item(False, *[action, keystroke])
|
self.keys.insert_item(False, *[action, keystroke])
|
||||||
self.keys.select_item(selection)
|
self.keys.select_item(selection)
|
||||||
|
|
||||||
def get_action(self):
|
def get_action(self):
|
||||||
return self.keys.get_selected()
|
return self.keys.get_selected()
|
||||||
|
|
||||||
class editKeystrokeDialog(baseDialog.BaseWXDialog):
|
class editKeystrokeDialog(baseDialog.BaseWXDialog):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(editKeystrokeDialog, self).__init__(parent=None, id=-1, title=_(u"Editing keystroke"))
|
super(editKeystrokeDialog, self).__init__(parent=None, id=-1, title=_(u"Editing keystroke"))
|
||||||
panel = wx.Panel(self)
|
panel = wx.Panel(self)
|
||||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||||
self.control = wx.CheckBox(panel, -1, _(u"Control"))
|
self.control = wx.CheckBox(panel, -1, _(u"Control"))
|
||||||
self.alt = wx.CheckBox(panel, -1, _(u"Alt"))
|
self.alt = wx.CheckBox(panel, -1, _(u"Alt"))
|
||||||
self.shift = wx.CheckBox(panel, -1, _(u"Shift"))
|
self.shift = wx.CheckBox(panel, -1, _(u"Shift"))
|
||||||
self.win = wx.CheckBox(panel, -1, _(u"Windows"))
|
self.win = wx.CheckBox(panel, -1, _(u"Windows"))
|
||||||
sizer1 = wx.BoxSizer(wx.HORIZONTAL)
|
sizer1 = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
sizer1.Add(self.control)
|
sizer1.Add(self.control)
|
||||||
sizer1.Add(self.alt)
|
sizer1.Add(self.alt)
|
||||||
sizer1.Add(self.shift)
|
sizer1.Add(self.shift)
|
||||||
sizer1.Add(self.win)
|
sizer1.Add(self.win)
|
||||||
charLabel = wx.StaticText(panel, -1, _(u"Key"))
|
charLabel = wx.StaticText(panel, -1, _(u"Key"))
|
||||||
self.key = wx.TextCtrl(panel, -1)
|
self.key = wx.TextCtrl(panel, -1)
|
||||||
sizer2 = wx.BoxSizer(wx.HORIZONTAL)
|
sizer2 = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
sizer2.Add(charLabel)
|
sizer2.Add(charLabel)
|
||||||
sizer2.Add(self.key)
|
sizer2.Add(self.key)
|
||||||
ok = wx.Button(panel, wx.ID_OK, _(u"OK"))
|
ok = wx.Button(panel, wx.ID_OK, _(u"OK"))
|
||||||
ok.SetDefault()
|
ok.SetDefault()
|
||||||
cancel = wx.Button(panel, wx.ID_CANCEL)
|
cancel = wx.Button(panel, wx.ID_CANCEL)
|
||||||
sizer3 = wx.BoxSizer(wx.HORIZONTAL)
|
sizer3 = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
sizer3.Add(ok)
|
sizer3.Add(ok)
|
||||||
sizer3.Add(cancel)
|
sizer3.Add(cancel)
|
||||||
sizer.Add(sizer1)
|
sizer.Add(sizer1)
|
||||||
sizer.Add(sizer2)
|
sizer.Add(sizer2)
|
||||||
sizer.Add(sizer3)
|
sizer.Add(sizer3)
|
||||||
panel.SetSizerAndFit(sizer)
|
panel.SetSizerAndFit(sizer)
|
||||||
|
|
||||||
|
|
||||||
def no_win_message():
|
def no_win_message():
|
||||||
return wx.MessageDialog(None, _(u"You need to use the Windows key"), _(u"Invalid keystroke"), wx.OK|wx.ICON_ERROR).ShowModal()
|
return wx.MessageDialog(None, _(u"You need to use the Windows key"), _(u"Invalid keystroke"), wx.OK|wx.ICON_ERROR).ShowModal()
|
||||||
|
|
||||||
def no_key():
|
def no_key():
|
||||||
return wx.MessageDialog(None, _(u"You must provide a character for the keystroke"), _(u"Invalid keystroke"), wx.ICON_ERROR).ShowModal()
|
return wx.MessageDialog(None, _(u"You must provide a character for the keystroke"), _(u"Invalid keystroke"), wx.ICON_ERROR).ShowModal()
|
||||||
|
@@ -20,195 +20,195 @@ LOCALE_SLANGDISPLAYNAME=0x6f
|
|||||||
curLang="en"
|
curLang="en"
|
||||||
|
|
||||||
def localeNameToWindowsLCID(localeName):
|
def localeNameToWindowsLCID(localeName):
|
||||||
"""Retreave the Windows locale identifier (LCID) for the given locale name
|
"""Retreave the Windows locale identifier (LCID) for the given locale name
|
||||||
@param localeName: a string of 2letterLanguage_2letterCountry or or just 2letterLanguage
|
@param localeName: a string of 2letterLanguage_2letterCountry or or just 2letterLanguage
|
||||||
@type localeName: string
|
@type localeName: string
|
||||||
@returns: a Windows LCID
|
@returns: a Windows LCID
|
||||||
@rtype: integer
|
@rtype: integer
|
||||||
"""
|
"""
|
||||||
#Windows Vista is able to convert locale names to LCIDs
|
#Windows Vista is able to convert locale names to LCIDs
|
||||||
func_LocaleNameToLCID=getattr(ctypes.windll.kernel32,'LocaleNameToLCID',None)
|
func_LocaleNameToLCID=getattr(ctypes.windll.kernel32,'LocaleNameToLCID',None)
|
||||||
if func_LocaleNameToLCID is not None:
|
if func_LocaleNameToLCID is not None:
|
||||||
localeName=localeName.replace('_','-')
|
localeName=localeName.replace('_','-')
|
||||||
LCID=func_LocaleNameToLCID(str(localeName),0)
|
LCID=func_LocaleNameToLCID(str(localeName),0)
|
||||||
else: #Windows doesn't have this functionality, manually search Python's windows_locale dictionary for the LCID
|
else: #Windows doesn't have this functionality, manually search Python's windows_locale dictionary for the LCID
|
||||||
localeName=locale.normalize(localeName)
|
localeName=locale.normalize(localeName)
|
||||||
if '.' in localeName:
|
if '.' in localeName:
|
||||||
localeName=localeName.split('.')[0]
|
localeName=localeName.split('.')[0]
|
||||||
LCList=[x[0] for x in locale.windows_locale.items() if x[1]==localeName]
|
LCList=[x[0] for x in locale.windows_locale.items() if x[1]==localeName]
|
||||||
if len(LCList)>0:
|
if len(LCList)>0:
|
||||||
LCID=LCList[0]
|
LCID=LCList[0]
|
||||||
else:
|
else:
|
||||||
LCID=0
|
LCID=0
|
||||||
return LCID
|
return LCID
|
||||||
|
|
||||||
def getLanguageDescription(language):
|
def getLanguageDescription(language):
|
||||||
"""Finds out the description (localized full name) of a given local name"""
|
"""Finds out the description (localized full name) of a given local name"""
|
||||||
desc=None
|
desc=None
|
||||||
if platform.system() == "Windows":
|
if platform.system() == "Windows":
|
||||||
LCID=localeNameToWindowsLCID(language)
|
LCID=localeNameToWindowsLCID(language)
|
||||||
if LCID!=0:
|
if LCID!=0:
|
||||||
buf=ctypes.create_unicode_buffer(1024)
|
buf=ctypes.create_unicode_buffer(1024)
|
||||||
if '_' not in language:
|
if '_' not in language:
|
||||||
res=ctypes.windll.kernel32.GetLocaleInfoW(LCID,LOCALE_SLANGDISPLAYNAME,buf,1024)
|
res=ctypes.windll.kernel32.GetLocaleInfoW(LCID,LOCALE_SLANGDISPLAYNAME,buf,1024)
|
||||||
else:
|
else:
|
||||||
res=0
|
res=0
|
||||||
if res==0:
|
if res==0:
|
||||||
res=ctypes.windll.kernel32.GetLocaleInfoW(LCID,LOCALE_SLANGUAGE,buf,1024)
|
res=ctypes.windll.kernel32.GetLocaleInfoW(LCID,LOCALE_SLANGUAGE,buf,1024)
|
||||||
desc=buf.value
|
desc=buf.value
|
||||||
elif platform.system() == "Linux" or not desc:
|
elif platform.system() == "Linux" or not desc:
|
||||||
desc={
|
desc={
|
||||||
"am":pgettext("languageName","Amharic"),
|
"am":pgettext("languageName","Amharic"),
|
||||||
"an":pgettext("languageName","Aragonese"),
|
"an":pgettext("languageName","Aragonese"),
|
||||||
"es":pgettext("languageName","Spanish"),
|
"es":pgettext("languageName","Spanish"),
|
||||||
"pt":pgettext("languageName","Portuguese"),
|
"pt":pgettext("languageName","Portuguese"),
|
||||||
"ru":pgettext("languageName","Russian"),
|
"ru":pgettext("languageName","Russian"),
|
||||||
"it":pgettext("languageName","italian"),
|
"it":pgettext("languageName","italian"),
|
||||||
"tr":pgettext("languageName","Turkey"),
|
"tr":pgettext("languageName","Turkey"),
|
||||||
"gl":pgettext("languageName","Galician"),
|
"gl":pgettext("languageName","Galician"),
|
||||||
"ca":pgettext("languageName","Catala"),
|
"ca":pgettext("languageName","Catala"),
|
||||||
"eu":pgettext("languageName","Vasque"),
|
"eu":pgettext("languageName","Vasque"),
|
||||||
"pl":pgettext("languageName","polish"),
|
"pl":pgettext("languageName","polish"),
|
||||||
"ar":pgettext("languageName","Arabic"),
|
"ar":pgettext("languageName","Arabic"),
|
||||||
"ne":pgettext("languageName","Nepali"),
|
"ne":pgettext("languageName","Nepali"),
|
||||||
"sr":pgettext("languageName","Serbian (Latin)"),
|
"sr":pgettext("languageName","Serbian (Latin)"),
|
||||||
"ja":pgettext("languageName","Japanese"),
|
"ja":pgettext("languageName","Japanese"),
|
||||||
}.get(language,None)
|
}.get(language,None)
|
||||||
return desc
|
return desc
|
||||||
|
|
||||||
def getAvailableLanguages():
|
def getAvailableLanguages():
|
||||||
"""generates a list of locale names, plus their full localized language and country names.
|
"""generates a list of locale names, plus their full localized language and country names.
|
||||||
@rtype: list of tuples
|
@rtype: list of tuples
|
||||||
"""
|
"""
|
||||||
#Make a list of all the locales found in NVDA's locale dir
|
#Make a list of all the locales found in NVDA's locale dir
|
||||||
l=[x for x in os.listdir(paths.locale_path()) if not x.startswith('.')]
|
l=[x for x in os.listdir(paths.locale_path()) if not x.startswith('.')]
|
||||||
l=[x for x in l if os.path.isfile(os.path.join(paths.locale_path(), '%s/LC_MESSAGES/%s.po' % (x, application.short_name)))]
|
l=[x for x in l if os.path.isfile(os.path.join(paths.locale_path(), '%s/LC_MESSAGES/%s.po' % (x, application.short_name)))]
|
||||||
#Make sure that en (english) is in the list as it may not have any locale files, but is default
|
#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:
|
if 'en' not in l:
|
||||||
l.append('en')
|
l.append('en')
|
||||||
l.sort()
|
l.sort()
|
||||||
#For each locale, ask Windows for its human readable display name
|
#For each locale, ask Windows for its human readable display name
|
||||||
d=[]
|
d=[]
|
||||||
for i in l:
|
for i in l:
|
||||||
desc=getLanguageDescription(i)
|
desc=getLanguageDescription(i)
|
||||||
label="%s, %s"%(desc,i) if desc else i
|
label="%s, %s"%(desc,i) if desc else i
|
||||||
d.append(label)
|
d.append(label)
|
||||||
#include a 'user default, windows' language, which just represents the default language for this user account
|
#include a 'user default, windows' language, which just represents the default language for this user account
|
||||||
l.append("system")
|
l.append("system")
|
||||||
# Translators: the label for the Windows default NVDA interface language.
|
# Translators: the label for the Windows default NVDA interface language.
|
||||||
d.append(_("User default"))
|
d.append(_("User default"))
|
||||||
#return a zipped up version of both the lists (a list with tuples of locale,label)
|
#return a zipped up version of both the lists (a list with tuples of locale,label)
|
||||||
return list(zip(l,d))
|
return list(zip(l,d))
|
||||||
|
|
||||||
def makePgettext(translations):
|
def makePgettext(translations):
|
||||||
"""Obtaina pgettext function for use with a gettext translations instance.
|
"""Obtaina pgettext function for use with a gettext translations instance.
|
||||||
pgettext is used to support message contexts,
|
pgettext is used to support message contexts,
|
||||||
but Python 2.7's gettext module doesn't support this,
|
but Python 2.7's gettext module doesn't support this,
|
||||||
so NVDA must provide its own implementation.
|
so NVDA must provide its own implementation.
|
||||||
"""
|
"""
|
||||||
if isinstance(translations, gettext.GNUTranslations):
|
if isinstance(translations, gettext.GNUTranslations):
|
||||||
def pgettext(context, message):
|
def pgettext(context, message):
|
||||||
message = str(message)
|
message = str(message)
|
||||||
try:
|
try:
|
||||||
# Look up the message with its context.
|
# Look up the message with its context.
|
||||||
return translations._catalog["%s\x04%s" % (context, message)]
|
return translations._catalog["%s\x04%s" % (context, message)]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return message
|
return message
|
||||||
else:
|
else:
|
||||||
def pgettext(context, message):
|
def pgettext(context, message):
|
||||||
return str(message)
|
return str(message)
|
||||||
return pgettext
|
return pgettext
|
||||||
|
|
||||||
def setLanguage(lang):
|
def setLanguage(lang):
|
||||||
system = platform.system()
|
system = platform.system()
|
||||||
global curLang
|
global curLang
|
||||||
try:
|
try:
|
||||||
if lang=="system":
|
if lang=="system":
|
||||||
if system == "Windows":
|
if system == "Windows":
|
||||||
windowsLCID=ctypes.windll.kernel32.GetUserDefaultUILanguage()
|
windowsLCID=ctypes.windll.kernel32.GetUserDefaultUILanguage()
|
||||||
localeName=locale.windows_locale[windowsLCID]
|
localeName=locale.windows_locale[windowsLCID]
|
||||||
elif system == "Darwin":
|
elif system == "Darwin":
|
||||||
import Foundation
|
import Foundation
|
||||||
localeName = Foundation.NSLocale.currentLocale().identifier()
|
localeName = Foundation.NSLocale.currentLocale().identifier()
|
||||||
elif system == "Linux":
|
elif system == "Linux":
|
||||||
localeName = locale.getdefaultlocale()[0]
|
localeName = locale.getdefaultlocale()[0]
|
||||||
trans=gettext.translation(application.short_name, localedir=paths.locale_path(), languages=[localeName])
|
trans=gettext.translation(application.short_name, localedir=paths.locale_path(), languages=[localeName])
|
||||||
curLang=localeName
|
curLang=localeName
|
||||||
# else:
|
# else:
|
||||||
# localeName=locale.getdefaultlocale()[0]
|
# localeName=locale.getdefaultlocale()[0]
|
||||||
# trans=gettext.translation('twblue', localedir=paths.locale_path(), languages=[localeName])
|
# trans=gettext.translation('twblue', localedir=paths.locale_path(), languages=[localeName])
|
||||||
# curLang=localeName
|
# curLang=localeName
|
||||||
|
|
||||||
else:
|
else:
|
||||||
trans=gettext.translation(application.short_name, localedir=paths.locale_path(), languages=[lang])
|
trans=gettext.translation(application.short_name, localedir=paths.locale_path(), languages=[lang])
|
||||||
curLang=lang
|
curLang=lang
|
||||||
localeChanged=False
|
localeChanged=False
|
||||||
#Try setting Python's locale to lang
|
#Try setting Python's locale to lang
|
||||||
# try:
|
# try:
|
||||||
if system == "Windows":
|
if system == "Windows":
|
||||||
locale.setlocale(locale.LC_ALL, langToWindowsLocale(lang))
|
locale.setlocale(locale.LC_ALL, langToWindowsLocale(lang))
|
||||||
localeChanged=True
|
localeChanged=True
|
||||||
else:
|
else:
|
||||||
locale.setlocale(locale.LC_ALL, lang)
|
locale.setlocale(locale.LC_ALL, lang)
|
||||||
localeChanged=True
|
localeChanged=True
|
||||||
# except:
|
# except:
|
||||||
# pass
|
# pass
|
||||||
if not localeChanged and '_' in lang:
|
if not localeChanged and '_' in lang:
|
||||||
#Python couldn'tsupport the language_country locale, just try language.
|
#Python couldn'tsupport the language_country locale, just try language.
|
||||||
try:
|
try:
|
||||||
locale.setlocale(locale.LC_ALL, lang.split('_')[0])
|
locale.setlocale(locale.LC_ALL, lang.split('_')[0])
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
#Set the windows locale for this thread (NVDA core) to this locale.
|
#Set the windows locale for this thread (NVDA core) to this locale.
|
||||||
if system == "Windows":
|
if system == "Windows":
|
||||||
LCID=localeNameToWindowsLCID(lang)
|
LCID=localeNameToWindowsLCID(lang)
|
||||||
ctypes.windll.kernel32.SetThreadLocale(LCID)
|
ctypes.windll.kernel32.SetThreadLocale(LCID)
|
||||||
except IOError:
|
except IOError:
|
||||||
trans=gettext.translation(application.short_name, fallback=True)
|
trans=gettext.translation(application.short_name, fallback=True)
|
||||||
curLang="en"
|
curLang="en"
|
||||||
if sys.version[0] == "3":
|
if sys.version[0] == "3":
|
||||||
trans.install()
|
trans.install()
|
||||||
else:
|
else:
|
||||||
trans.install(unicode=True)
|
trans.install(unicode=True)
|
||||||
# Install our pgettext function.
|
# Install our pgettext function.
|
||||||
# __builtin__.__dict__["pgettext"] = makePgettext(trans)
|
# __builtin__.__dict__["pgettext"] = makePgettext(trans)
|
||||||
|
|
||||||
def getLanguage():
|
def getLanguage():
|
||||||
return curLang
|
return curLang
|
||||||
|
|
||||||
def normalizeLanguage(lang):
|
def normalizeLanguage(lang):
|
||||||
"""
|
"""
|
||||||
Normalizes a language-dialect string in to a standard form we can deal with.
|
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.
|
Converts any dash to underline, and makes sure that language is lowercase and dialect is upercase.
|
||||||
"""
|
"""
|
||||||
lang=lang.replace('-','_')
|
lang=lang.replace('-','_')
|
||||||
ld=lang.split('_')
|
ld=lang.split('_')
|
||||||
ld[0]=ld[0].lower()
|
ld[0]=ld[0].lower()
|
||||||
#Filter out meta languages such as x-western
|
#Filter out meta languages such as x-western
|
||||||
if ld[0]=='x':
|
if ld[0]=='x':
|
||||||
return None
|
return None
|
||||||
if len(ld)>=2:
|
if len(ld)>=2:
|
||||||
ld[1]=ld[1].upper()
|
ld[1]=ld[1].upper()
|
||||||
return "_".join(ld)
|
return "_".join(ld)
|
||||||
|
|
||||||
def langToWindowsLocale(lang):
|
def langToWindowsLocale(lang):
|
||||||
languages = {"en": "eng",
|
languages = {"en": "eng",
|
||||||
"ar": "ara",
|
"ar": "ara",
|
||||||
"ca": "cat",
|
"ca": "cat",
|
||||||
"de": "deu",
|
"de": "deu",
|
||||||
"es": "esp",
|
"es": "esp",
|
||||||
"fi": "fin",
|
"fi": "fin",
|
||||||
"fr": "fre_FRA",
|
"fr": "fre_FRA",
|
||||||
"gl": "glc",
|
"gl": "glc",
|
||||||
"eu": "euq",
|
"eu": "euq",
|
||||||
"hu": "hun",
|
"hu": "hun",
|
||||||
"hr": "hrv",
|
"hr": "hrv",
|
||||||
"it": "ita",
|
"it": "ita",
|
||||||
"ja": "jpn",
|
"ja": "jpn",
|
||||||
"pl": "plk",
|
"pl": "plk",
|
||||||
"pt": "ptb",
|
"pt": "ptb",
|
||||||
"ru": "rus",
|
"ru": "rus",
|
||||||
"tr": "trk",
|
"tr": "trk",
|
||||||
"sr": "eng",
|
"sr": "eng",
|
||||||
}
|
}
|
||||||
return languages[lang]
|
return languages[lang]
|
||||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -2,14 +2,14 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: TW Blue 0.94\n"
|
"Project-Id-Version: TW Blue 0.94\n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estándar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34+Hora estándar romance\n"
|
||||||
"PO-Revision-Date: 2019-07-22 16:16+0200\n"
|
"PO-Revision-Date: 2020-06-04 21:19+0200\n"
|
||||||
"Last-Translator: Corentin BACQUÉ-CAZENAVE <corentin@progaccess33.net>\n"
|
"Last-Translator: Corentin BACQUÉ-CAZENAVE <corentin@progaccess33.net>\n"
|
||||||
"Language-Team: Corentin BACQUÉ-CAZENAVE <corentin@progaccess.net>\n"
|
"Language-Team: Oreonan <corentin@progaccess.net>\n"
|
||||||
"Language: fr\n"
|
"Language: fr\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Generator: Poedit 2.2.3\n"
|
"X-Generator: Poedit 2.3.1\n"
|
||||||
"X-Poedit-KeywordsList: _;gettext;gettext_noop\n"
|
"X-Poedit-KeywordsList: _;gettext;gettext_noop\n"
|
||||||
"X-Poedit-Basepath: .\n"
|
"X-Poedit-Basepath: .\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
@@ -262,7 +262,7 @@ msgstr "Listes"
|
|||||||
#: ../src\controller\mainController.py:378
|
#: ../src\controller\mainController.py:378
|
||||||
#: ../src\controller\mainController.py:1399
|
#: ../src\controller\mainController.py:1399
|
||||||
msgid "List for {}"
|
msgid "List for {}"
|
||||||
msgstr "Liste de {}"
|
msgstr "Liste {}"
|
||||||
|
|
||||||
#: ../src\controller\mainController.py:381
|
#: ../src\controller\mainController.py:381
|
||||||
msgid "Searches"
|
msgid "Searches"
|
||||||
@@ -1988,7 +1988,7 @@ msgstr "Téléchargement de la nouvelle version en cours..."
|
|||||||
|
|
||||||
#: ../src\update\wxUpdater.py:28
|
#: ../src\update\wxUpdater.py:28
|
||||||
msgid "Updating... %s of %s"
|
msgid "Updating... %s of %s"
|
||||||
msgstr "Mise à jour en cours... %s de %s"
|
msgstr "Mise à jour en cours... %s sur %s"
|
||||||
|
|
||||||
#: ../src\update\wxUpdater.py:31
|
#: ../src\update\wxUpdater.py:31
|
||||||
msgid "Done!"
|
msgid "Done!"
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -6,15 +6,15 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: TW Blue 0.85\n"
|
"Project-Id-Version: TW Blue 0.85\n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
||||||
"PO-Revision-Date: 2018-08-15 09:47+0400\n"
|
"PO-Revision-Date: 2020-10-23 14:30+0300\n"
|
||||||
"Last-Translator: Manuel Cortez <manuel@manuelcortez.net>\n"
|
"Last-Translator: Artem Plaksin <admin@maniyax.ru>\n"
|
||||||
"Language-Team: Alexander Jaszyn <a.jaszyn@ya.ru>\n"
|
"Language-Team: Alexander Jaszyn <a.jaszyn@ya.ru>\n"
|
||||||
"Language: ru\n"
|
"Language: ru\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Generated-By: pygettext.py 1.5\n"
|
"Generated-By: pygettext.py 1.5\n"
|
||||||
"X-Generator: Poedit 1.5.7\n"
|
"X-Generator: Poedit 1.8.8\n"
|
||||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
|
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
|
||||||
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||||
"X-Poedit-SourceCharset: UTF-8\n"
|
"X-Poedit-SourceCharset: UTF-8\n"
|
||||||
@@ -84,24 +84,22 @@ msgid "Muted users"
|
|||||||
msgstr "Отключенные пользователи"
|
msgstr "Отключенные пользователи"
|
||||||
|
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:75
|
#: ../src\controller\buffers\twitterBuffers.py:75
|
||||||
#, fuzzy
|
|
||||||
msgid "{username}'s timeline"
|
msgid "{username}'s timeline"
|
||||||
msgstr "Открыть ленту пользователя"
|
msgstr "Лента твитов {username}"
|
||||||
|
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:77
|
#: ../src\controller\buffers\twitterBuffers.py:77
|
||||||
msgid "{username}'s likes"
|
msgid "{username}'s likes"
|
||||||
msgstr ""
|
msgstr "Понравившееся {username}"
|
||||||
|
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:79
|
#: ../src\controller\buffers\twitterBuffers.py:79
|
||||||
msgid "{username}'s followers"
|
msgid "{username}'s followers"
|
||||||
msgstr ""
|
msgstr "Читающие {username}"
|
||||||
|
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:81
|
#: ../src\controller\buffers\twitterBuffers.py:81
|
||||||
msgid "{username}'s friends"
|
msgid "{username}'s friends"
|
||||||
msgstr ""
|
msgstr "Список читаемых {username}"
|
||||||
|
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:83
|
#: ../src\controller\buffers\twitterBuffers.py:83
|
||||||
#, fuzzy
|
|
||||||
msgid "Unknown buffer"
|
msgid "Unknown buffer"
|
||||||
msgstr "Неизвестно"
|
msgstr "Неизвестно"
|
||||||
|
|
||||||
@@ -119,14 +117,12 @@ msgid "Write the tweet here"
|
|||||||
msgstr "Напишите текст твита здесь"
|
msgstr "Напишите текст твита здесь"
|
||||||
|
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:194
|
#: ../src\controller\buffers\twitterBuffers.py:194
|
||||||
#, fuzzy
|
|
||||||
msgid "New tweet in {0}"
|
msgid "New tweet in {0}"
|
||||||
msgstr "Новый твит"
|
msgstr "Новый твит в {0}"
|
||||||
|
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:197
|
#: ../src\controller\buffers\twitterBuffers.py:197
|
||||||
#, fuzzy
|
|
||||||
msgid "{0} new tweets in {1}."
|
msgid "{0} new tweets in {1}."
|
||||||
msgstr "Пользователь @{0} процитировал ваш твит: {1}"
|
msgstr "@{0} процитировал ваш твит: {1}"
|
||||||
|
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:232
|
#: ../src\controller\buffers\twitterBuffers.py:232
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:676
|
#: ../src\controller\buffers\twitterBuffers.py:676
|
||||||
@@ -182,7 +178,7 @@ msgstr "Профиль"
|
|||||||
#: ../src\controller\buffers\twitterBuffers.py:634
|
#: ../src\controller\buffers\twitterBuffers.py:634
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:987
|
#: ../src\controller\buffers\twitterBuffers.py:987
|
||||||
msgid "Opening item in web browser..."
|
msgid "Opening item in web browser..."
|
||||||
msgstr ""
|
msgstr "Открыть в браузере"
|
||||||
|
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:688
|
#: ../src\controller\buffers\twitterBuffers.py:688
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:855
|
#: ../src\controller\buffers\twitterBuffers.py:855
|
||||||
@@ -196,12 +192,10 @@ msgid "Mention"
|
|||||||
msgstr "Упомянуть"
|
msgstr "Упомянуть"
|
||||||
|
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:728
|
#: ../src\controller\buffers\twitterBuffers.py:728
|
||||||
#, fuzzy
|
|
||||||
msgid "{0} new direct messages."
|
msgid "{0} new direct messages."
|
||||||
msgstr "Новое личное сообщение"
|
msgstr "Новое личное сообщение"
|
||||||
|
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:731
|
#: ../src\controller\buffers\twitterBuffers.py:731
|
||||||
#, fuzzy
|
|
||||||
msgid "This action is not supported in the buffer yet."
|
msgid "This action is not supported in the buffer yet."
|
||||||
msgstr "Это действие не поддерживается в данном буфере"
|
msgstr "Это действие не поддерживается в данном буфере"
|
||||||
|
|
||||||
@@ -210,6 +204,8 @@ msgid ""
|
|||||||
"Getting more items cannot be done in this buffer. Use the direct messages "
|
"Getting more items cannot be done in this buffer. Use the direct messages "
|
||||||
"buffer instead."
|
"buffer instead."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Невозможно получить больше элементов в данном буфере, используйте буфер "
|
||||||
|
"личных сообщений вместо этого."
|
||||||
|
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:983
|
#: ../src\controller\buffers\twitterBuffers.py:983
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
@@ -379,12 +375,11 @@ msgstr "Список уже открыт"
|
|||||||
|
|
||||||
#: ../src\controller\mainController.py:1423
|
#: ../src\controller\mainController.py:1423
|
||||||
#: ../src\controller\mainController.py:1439
|
#: ../src\controller\mainController.py:1439
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"An error happened while trying to connect to the server. Please try later."
|
"An error happened while trying to connect to the server. Please try later."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Что-то неожиданное произошло при попытке сообщить об ошибке. Пожалуйста, "
|
"При попытке подключиться к серверу произошла ошибка. Пожалуйста, попробуйте "
|
||||||
"повторите попытку позже"
|
"позже."
|
||||||
|
|
||||||
#: ../src\controller\mainController.py:1475
|
#: ../src\controller\mainController.py:1475
|
||||||
msgid "The auto-reading of new tweets is enabled for this buffer"
|
msgid "The auto-reading of new tweets is enabled for this buffer"
|
||||||
@@ -874,19 +869,19 @@ msgstr "Игнорировать"
|
|||||||
|
|
||||||
#: ../src\extra\SpellChecker\wx_ui.py:43
|
#: ../src\extra\SpellChecker\wx_ui.py:43
|
||||||
msgid "I&gnore all"
|
msgid "I&gnore all"
|
||||||
msgstr "Игнорировать все"
|
msgstr "&Игнорировать все"
|
||||||
|
|
||||||
#: ../src\extra\SpellChecker\wx_ui.py:44
|
#: ../src\extra\SpellChecker\wx_ui.py:44
|
||||||
msgid "&Replace"
|
msgid "&Replace"
|
||||||
msgstr "Заменить"
|
msgstr "&Заменить"
|
||||||
|
|
||||||
#: ../src\extra\SpellChecker\wx_ui.py:45
|
#: ../src\extra\SpellChecker\wx_ui.py:45
|
||||||
msgid "R&eplace all"
|
msgid "R&eplace all"
|
||||||
msgstr "Заменить все"
|
msgstr "З&аменить все"
|
||||||
|
|
||||||
#: ../src\extra\SpellChecker\wx_ui.py:46
|
#: ../src\extra\SpellChecker\wx_ui.py:46
|
||||||
msgid "&Add to personal dictionary"
|
msgid "&Add to personal dictionary"
|
||||||
msgstr "Добавить в личный словарь"
|
msgstr "&Добавить в личный словарь"
|
||||||
|
|
||||||
#: ../src\extra\SpellChecker\wx_ui.py:79
|
#: ../src\extra\SpellChecker\wx_ui.py:79
|
||||||
msgid ""
|
msgid ""
|
||||||
@@ -1587,9 +1582,8 @@ msgid "Open URL"
|
|||||||
msgstr "Открыть ссылку"
|
msgstr "Открыть ссылку"
|
||||||
|
|
||||||
#: ../src\keystrokeEditor\constants.py:25
|
#: ../src\keystrokeEditor\constants.py:25
|
||||||
#, fuzzy
|
|
||||||
msgid "View in Twitter"
|
msgid "View in Twitter"
|
||||||
msgstr "Поиск в твиттере"
|
msgstr "Посмотреть в Твиттере"
|
||||||
|
|
||||||
#: ../src\keystrokeEditor\constants.py:26
|
#: ../src\keystrokeEditor\constants.py:26
|
||||||
msgid "Increase volume by 5%"
|
msgid "Increase volume by 5%"
|
||||||
@@ -1693,7 +1687,7 @@ msgstr "Просмотр беседы"
|
|||||||
|
|
||||||
#: ../src\keystrokeEditor\constants.py:51
|
#: ../src\keystrokeEditor\constants.py:51
|
||||||
msgid "Check and download updates"
|
msgid "Check and download updates"
|
||||||
msgstr "Проверить на наличие обновлений"
|
msgstr "Проверить наличие обновлений"
|
||||||
|
|
||||||
#: ../src\keystrokeEditor\constants.py:52
|
#: ../src\keystrokeEditor\constants.py:52
|
||||||
msgid ""
|
msgid ""
|
||||||
@@ -1816,6 +1810,9 @@ msgid ""
|
|||||||
"If you're sure that {0} isn't running, try deleting the file at {1}. If "
|
"If you're sure that {0} isn't running, try deleting the file at {1}. If "
|
||||||
"you're unsure of how to do this, contact the {0} developers."
|
"you're unsure of how to do this, contact the {0} developers."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"{0} уже запущен. Закройте другой экземпляр, прежде чем запускать этот. Если "
|
||||||
|
"вы уверены, что {0} не активен, попробуйте удалить файл по адресу {1}. Если "
|
||||||
|
"вы не знаете, как это сделать, обратитесь к разработчикам {0}."
|
||||||
|
|
||||||
#: ../src\sessionmanager\wxUI.py:8
|
#: ../src\sessionmanager\wxUI.py:8
|
||||||
msgid "Session manager"
|
msgid "Session manager"
|
||||||
@@ -1920,9 +1917,8 @@ msgid "public"
|
|||||||
msgstr "Публичный"
|
msgstr "Публичный"
|
||||||
|
|
||||||
#: ../src\sessions\twitter\session.py:169
|
#: ../src\sessions\twitter\session.py:169
|
||||||
#, fuzzy
|
|
||||||
msgid "There are no more items to retrieve in this buffer."
|
msgid "There are no more items to retrieve in this buffer."
|
||||||
msgstr "Координаты отсутствуют"
|
msgstr "В этом буфере больше нет элементов для извлечения."
|
||||||
|
|
||||||
#: ../src\sessions\twitter\session.py:215
|
#: ../src\sessions\twitter\session.py:215
|
||||||
msgid "%s failed. Reason: %s"
|
msgid "%s failed. Reason: %s"
|
||||||
@@ -2048,7 +2044,7 @@ msgstr "Тренды"
|
|||||||
|
|
||||||
#: ../src\wxUI\buffers\trends.py:18
|
#: ../src\wxUI\buffers\trends.py:18
|
||||||
msgid "Tweet about this trend"
|
msgid "Tweet about this trend"
|
||||||
msgstr "Tweet о тренде"
|
msgstr "Твитнуть о тренде"
|
||||||
|
|
||||||
#: ../src\wxUI\buffers\trends.py:19 ../src\wxUI\menus.py:96
|
#: ../src\wxUI\buffers\trends.py:19 ../src\wxUI\menus.py:96
|
||||||
msgid "Search topic"
|
msgid "Search topic"
|
||||||
@@ -2265,6 +2261,8 @@ msgid ""
|
|||||||
"{0} quit unexpectedly the last time it was run. If the problem persists, "
|
"{0} quit unexpectedly the last time it was run. If the problem persists, "
|
||||||
"please report it to the {0} developers."
|
"please report it to the {0} developers."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"{0} неожиданно закончил свою работу при последнем запуске. Если проблема не "
|
||||||
|
"устранена, пожалуйста, сообщите об этом разработчикам {0}."
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\attach.py:9
|
#: ../src\wxUI\dialogs\attach.py:9
|
||||||
msgid "Add an attachment"
|
msgid "Add an attachment"
|
||||||
@@ -2362,6 +2360,7 @@ msgstr "Использование удлинителя твитов (может
|
|||||||
#: ../src\wxUI\dialogs\configuration.py:48
|
#: ../src\wxUI\dialogs\configuration.py:48
|
||||||
msgid "Remember state for mention all and long tweet"
|
msgid "Remember state for mention all and long tweet"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Запоминать состояние для упоминаний всех пользователей и длинных твитов"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\configuration.py:51
|
#: ../src\wxUI\dialogs\configuration.py:51
|
||||||
msgid "Keymap"
|
msgid "Keymap"
|
||||||
@@ -2413,7 +2412,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: ../src\wxUI\dialogs\configuration.py:116
|
#: ../src\wxUI\dialogs\configuration.py:116
|
||||||
msgid "Retweet mode"
|
msgid "Retweet mode"
|
||||||
msgstr "Стиль ретвита"
|
msgstr "Режим ретвита"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\configuration.py:122
|
#: ../src\wxUI\dialogs\configuration.py:122
|
||||||
msgid "Show screen names instead of full names"
|
msgid "Show screen names instead of full names"
|
||||||
@@ -2429,11 +2428,11 @@ msgstr ""
|
|||||||
|
|
||||||
#: ../src\wxUI\dialogs\configuration.py:134
|
#: ../src\wxUI\dialogs\configuration.py:134
|
||||||
msgid "Enable automatic speech feedback"
|
msgid "Enable automatic speech feedback"
|
||||||
msgstr ""
|
msgstr "Включить автоматический речевой вывод"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\configuration.py:136
|
#: ../src\wxUI\dialogs\configuration.py:136
|
||||||
msgid "Enable automatic Braille feedback"
|
msgid "Enable automatic Braille feedback"
|
||||||
msgstr ""
|
msgstr "Включить автоматический брайлевский вывод"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\configuration.py:144
|
#: ../src\wxUI\dialogs\configuration.py:144
|
||||||
msgid "Status"
|
msgid "Status"
|
||||||
@@ -2515,7 +2514,7 @@ msgstr "Устройство записи"
|
|||||||
|
|
||||||
#: ../src\wxUI\dialogs\configuration.py:299
|
#: ../src\wxUI\dialogs\configuration.py:299
|
||||||
msgid "Sound pack"
|
msgid "Sound pack"
|
||||||
msgstr "Пакет звуков"
|
msgstr "Звуковая схема"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\configuration.py:305
|
#: ../src\wxUI\dialogs\configuration.py:305
|
||||||
msgid "Indicate audio tweets with sound"
|
msgid "Indicate audio tweets with sound"
|
||||||
@@ -2539,7 +2538,7 @@ msgstr "API ключ SndUp"
|
|||||||
|
|
||||||
#: ../src\wxUI\dialogs\configuration.py:353
|
#: ../src\wxUI\dialogs\configuration.py:353
|
||||||
msgid "{0} preferences"
|
msgid "{0} preferences"
|
||||||
msgstr "Настройки {0}"
|
msgstr "Параметры {0}"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\configuration.py:364
|
#: ../src\wxUI\dialogs\configuration.py:364
|
||||||
msgid "Proxy"
|
msgid "Proxy"
|
||||||
@@ -2819,9 +2818,8 @@ msgid "Source: "
|
|||||||
msgstr "Клиент"
|
msgstr "Клиент"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\message.py:342 ../src\wxUI\dialogs\message.py:420
|
#: ../src\wxUI\dialogs\message.py:342 ../src\wxUI\dialogs\message.py:420
|
||||||
#, fuzzy
|
|
||||||
msgid "Date: "
|
msgid "Date: "
|
||||||
msgstr "Дата"
|
msgstr "Дата: "
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\message.py:405
|
#: ../src\wxUI\dialogs\message.py:405
|
||||||
msgid "View"
|
msgid "View"
|
||||||
@@ -2890,7 +2888,7 @@ msgstr "Детали"
|
|||||||
|
|
||||||
#: ../src\wxUI\dialogs\show_user.py:16
|
#: ../src\wxUI\dialogs\show_user.py:16
|
||||||
msgid "&Go to URL"
|
msgid "&Go to URL"
|
||||||
msgstr "Перейти по ссылке"
|
msgstr "&Перейти по ссылке"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\trends.py:12
|
#: ../src\wxUI\dialogs\trends.py:12
|
||||||
msgid "View trending topics"
|
msgid "View trending topics"
|
||||||
@@ -3031,12 +3029,11 @@ msgstr "н&е нравится"
|
|||||||
|
|
||||||
#: ../src\wxUI\menus.py:15 ../src\wxUI\menus.py:35 ../src\wxUI\menus.py:51
|
#: ../src\wxUI\menus.py:15 ../src\wxUI\menus.py:35 ../src\wxUI\menus.py:51
|
||||||
msgid "&Open URL"
|
msgid "&Open URL"
|
||||||
msgstr "Открыть ссылку"
|
msgstr "&Открыть ссылку"
|
||||||
|
|
||||||
#: ../src\wxUI\menus.py:17 ../src\wxUI\menus.py:53 ../src\wxUI\menus.py:86
|
#: ../src\wxUI\menus.py:17 ../src\wxUI\menus.py:53 ../src\wxUI\menus.py:86
|
||||||
#, fuzzy
|
|
||||||
msgid "&Open in Twitter"
|
msgid "&Open in Twitter"
|
||||||
msgstr "Поиск в твиттере"
|
msgstr "Открыть в &Твиттере"
|
||||||
|
|
||||||
#: ../src\wxUI\menus.py:19 ../src\wxUI\menus.py:37 ../src\wxUI\menus.py:55
|
#: ../src\wxUI\menus.py:19 ../src\wxUI\menus.py:37 ../src\wxUI\menus.py:55
|
||||||
msgid "&Play audio"
|
msgid "&Play audio"
|
||||||
@@ -3246,7 +3243,7 @@ msgstr "Сайт {0}"
|
|||||||
|
|
||||||
#: ../src\wxUI\view.py:77
|
#: ../src\wxUI\view.py:77
|
||||||
msgid "Get soundpacks for TWBlue"
|
msgid "Get soundpacks for TWBlue"
|
||||||
msgstr ""
|
msgstr "Получить звуковые схемы для TWBlue"
|
||||||
|
|
||||||
#: ../src\wxUI\view.py:78
|
#: ../src\wxUI\view.py:78
|
||||||
msgid "About &{0}"
|
msgid "About &{0}"
|
||||||
|
Binary file not shown.
@@ -5,16 +5,16 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: TwBlue 0.80\n"
|
"Project-Id-Version: TwBlue 0.80\n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34+Hora estándar romance\n"
|
||||||
"PO-Revision-Date: 2018-08-07 13:46-0500\n"
|
"PO-Revision-Date: 2021-06-25 18:32+0100\n"
|
||||||
"Last-Translator: Manuel Cortez <manuel@manuelcortez.net>\n"
|
"Last-Translator: Nikola Jović <wwenikola123@gmail.com>\n"
|
||||||
"Language-Team: Aleksandar Đurić <agasoft@gmail.com>\n"
|
"Language-Team: Aleksandar Đurić <agasoft@gmail.com>\n"
|
||||||
"Language: sr_RS@latin\n"
|
"Language: sr_RS@latin\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Generated-By: pygettext.py 1.5\n"
|
"Generated-By: pygettext.py 1.5\n"
|
||||||
"X-Generator: Poedit 2.0.1\n"
|
"X-Generator: Poedit 1.6.10\n"
|
||||||
"X-Poedit-Bookmarks: -1,442,-1,-1,-1,-1,-1,-1,-1,-1\n"
|
"X-Poedit-Bookmarks: -1,442,-1,-1,-1,-1,-1,-1,-1,-1\n"
|
||||||
"X-Poedit-SourceCharset: UTF-8\n"
|
"X-Poedit-SourceCharset: UTF-8\n"
|
||||||
|
|
||||||
@@ -82,26 +82,24 @@ msgid "Muted users"
|
|||||||
msgstr "Utišani korisnici"
|
msgstr "Utišani korisnici"
|
||||||
|
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:75
|
#: ../src\controller\buffers\twitterBuffers.py:75
|
||||||
#, fuzzy
|
|
||||||
msgid "{username}'s timeline"
|
msgid "{username}'s timeline"
|
||||||
msgstr "Otvori korisničku vremensku crtu"
|
msgstr "Vremenska linija korisnika {username}"
|
||||||
|
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:77
|
#: ../src\controller\buffers\twitterBuffers.py:77
|
||||||
msgid "{username}'s likes"
|
msgid "{username}'s likes"
|
||||||
msgstr ""
|
msgstr "Sviđanja korisnika {username}"
|
||||||
|
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:79
|
#: ../src\controller\buffers\twitterBuffers.py:79
|
||||||
msgid "{username}'s followers"
|
msgid "{username}'s followers"
|
||||||
msgstr ""
|
msgstr "Pratioci korisnika {username}"
|
||||||
|
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:81
|
#: ../src\controller\buffers\twitterBuffers.py:81
|
||||||
msgid "{username}'s friends"
|
msgid "{username}'s friends"
|
||||||
msgstr ""
|
msgstr "Prijatelji korisnika {username}"
|
||||||
|
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:83
|
#: ../src\controller\buffers\twitterBuffers.py:83
|
||||||
#, fuzzy
|
|
||||||
msgid "Unknown buffer"
|
msgid "Unknown buffer"
|
||||||
msgstr "Nepoznato"
|
msgstr "Nepoznat kanal"
|
||||||
|
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:86
|
#: ../src\controller\buffers\twitterBuffers.py:86
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:1242
|
#: ../src\controller\buffers\twitterBuffers.py:1242
|
||||||
@@ -117,14 +115,12 @@ msgid "Write the tweet here"
|
|||||||
msgstr "Otkucajte tvit ovde:"
|
msgstr "Otkucajte tvit ovde:"
|
||||||
|
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:194
|
#: ../src\controller\buffers\twitterBuffers.py:194
|
||||||
#, fuzzy
|
|
||||||
msgid "New tweet in {0}"
|
msgid "New tweet in {0}"
|
||||||
msgstr "Novi tvit"
|
msgstr "Novi tvit u kanalu {0}"
|
||||||
|
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:197
|
#: ../src\controller\buffers\twitterBuffers.py:197
|
||||||
#, fuzzy
|
|
||||||
msgid "{0} new tweets in {1}."
|
msgid "{0} new tweets in {1}."
|
||||||
msgstr "@{0} citira vaš tvit: {1}"
|
msgstr "{0} novih tvitova u kanalu {1}."
|
||||||
|
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:232
|
#: ../src\controller\buffers\twitterBuffers.py:232
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:676
|
#: ../src\controller\buffers\twitterBuffers.py:676
|
||||||
@@ -180,7 +176,7 @@ msgstr "Podaci o korisniku"
|
|||||||
#: ../src\controller\buffers\twitterBuffers.py:634
|
#: ../src\controller\buffers\twitterBuffers.py:634
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:987
|
#: ../src\controller\buffers\twitterBuffers.py:987
|
||||||
msgid "Opening item in web browser..."
|
msgid "Opening item in web browser..."
|
||||||
msgstr ""
|
msgstr "Otvaram stavku u Web pretraživaču..."
|
||||||
|
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:688
|
#: ../src\controller\buffers\twitterBuffers.py:688
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:855
|
#: ../src\controller\buffers\twitterBuffers.py:855
|
||||||
@@ -194,30 +190,28 @@ msgid "Mention"
|
|||||||
msgstr "Spomeni"
|
msgstr "Spomeni"
|
||||||
|
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:728
|
#: ../src\controller\buffers\twitterBuffers.py:728
|
||||||
#, fuzzy
|
|
||||||
msgid "{0} new direct messages."
|
msgid "{0} new direct messages."
|
||||||
msgstr "Nova direktna poruka"
|
msgstr "{0} novih direktnih poruka."
|
||||||
|
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:731
|
#: ../src\controller\buffers\twitterBuffers.py:731
|
||||||
#, fuzzy
|
|
||||||
msgid "This action is not supported in the buffer yet."
|
msgid "This action is not supported in the buffer yet."
|
||||||
msgstr "Ova radnja nije podržana na ovom kanalu"
|
msgstr "Ova radnja još uvek nije podržana na ovom kanalu."
|
||||||
|
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:741
|
#: ../src\controller\buffers\twitterBuffers.py:741
|
||||||
msgid ""
|
msgid ""
|
||||||
"Getting more items cannot be done in this buffer. Use the direct messages "
|
"Getting more items cannot be done in this buffer. Use the direct messages "
|
||||||
"buffer instead."
|
"buffer instead."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Nemoguće preuzeti dodatne stavke za ovaj kanal. Umesto toga, koristite kanal "
|
||||||
|
"direktne poruke."
|
||||||
|
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:983
|
#: ../src\controller\buffers\twitterBuffers.py:983
|
||||||
#, fuzzy
|
|
||||||
msgid "{0} new followers."
|
msgid "{0} new followers."
|
||||||
msgstr "Novi pratilac."
|
msgstr "{0} novih pratilaca."
|
||||||
|
|
||||||
#: ../src\controller\buffers\twitterBuffers.py:1266
|
#: ../src\controller\buffers\twitterBuffers.py:1266
|
||||||
#, fuzzy
|
|
||||||
msgid "This action is not supported in the buffer, yet."
|
msgid "This action is not supported in the buffer, yet."
|
||||||
msgstr "Ova radnja nije podržana na ovom kanalu"
|
msgstr "Ova radnja još uvek nije podržana na ovom kanalu"
|
||||||
|
|
||||||
#: ../src\controller\mainController.py:273
|
#: ../src\controller\mainController.py:273
|
||||||
msgid "Ready"
|
msgid "Ready"
|
||||||
@@ -308,9 +302,8 @@ msgid "{0} not found."
|
|||||||
msgstr "{0} nije pronađen."
|
msgstr "{0} nije pronađen."
|
||||||
|
|
||||||
#: ../src\controller\mainController.py:482
|
#: ../src\controller\mainController.py:482
|
||||||
#, fuzzy
|
|
||||||
msgid "Filters cannot be applied on this buffer"
|
msgid "Filters cannot be applied on this buffer"
|
||||||
msgstr "Ova radnja nije podržana na ovom kanalu"
|
msgstr "Filteri se ne mogu primeniti na ovaj kanal"
|
||||||
|
|
||||||
#: ../src\controller\mainController.py:535
|
#: ../src\controller\mainController.py:535
|
||||||
#: ../src\controller\mainController.py:552
|
#: ../src\controller\mainController.py:552
|
||||||
@@ -319,9 +312,8 @@ msgid "Select the user"
|
|||||||
msgstr "Izaberite korisnika"
|
msgstr "Izaberite korisnika"
|
||||||
|
|
||||||
#: ../src\controller\mainController.py:809 ../src\controller\messages.py:236
|
#: ../src\controller\mainController.py:809 ../src\controller\messages.py:236
|
||||||
#, fuzzy
|
|
||||||
msgid "MMM D, YYYY. H:m"
|
msgid "MMM D, YYYY. H:m"
|
||||||
msgstr "dddd, MMMM D, YYYY H:m:s"
|
msgstr "MMM D, YYYY. H:m"
|
||||||
|
|
||||||
#: ../src\controller\mainController.py:934
|
#: ../src\controller\mainController.py:934
|
||||||
msgid "Conversation with {0}"
|
msgid "Conversation with {0}"
|
||||||
@@ -379,12 +371,11 @@ msgstr "Ova lista je već otvorena"
|
|||||||
|
|
||||||
#: ../src\controller\mainController.py:1423
|
#: ../src\controller\mainController.py:1423
|
||||||
#: ../src\controller\mainController.py:1439
|
#: ../src\controller\mainController.py:1439
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"An error happened while trying to connect to the server. Please try later."
|
"An error happened while trying to connect to the server. Please try later."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Dogodilo se nešto neočekivano prilikom prijavljivanja greške. Molimo vas da "
|
"Došlo je do greške pri pokušaju povezivanja na server. Molimo pokušajte "
|
||||||
"pokušate kasnije."
|
"kasnije."
|
||||||
|
|
||||||
#: ../src\controller\mainController.py:1475
|
#: ../src\controller\mainController.py:1475
|
||||||
msgid "The auto-reading of new tweets is enabled for this buffer"
|
msgid "The auto-reading of new tweets is enabled for this buffer"
|
||||||
@@ -475,9 +466,8 @@ msgid "%s - %s characters"
|
|||||||
msgstr "%s - %s znakova"
|
msgstr "%s - %s znakova"
|
||||||
|
|
||||||
#: ../src\controller\messages.py:262
|
#: ../src\controller\messages.py:262
|
||||||
#, fuzzy
|
|
||||||
msgid "View item"
|
msgid "View item"
|
||||||
msgstr "Vidi liste"
|
msgstr "Prikaži stavku"
|
||||||
|
|
||||||
#: ../src\controller\settings.py:75
|
#: ../src\controller\settings.py:75
|
||||||
msgid "Direct connection"
|
msgid "Direct connection"
|
||||||
@@ -533,7 +523,8 @@ msgstr "Korisnik je suspendovan."
|
|||||||
msgid "Information for %s"
|
msgid "Information for %s"
|
||||||
msgstr "Informacija za %s"
|
msgstr "Informacija za %s"
|
||||||
|
|
||||||
#: ../src\controller\user.py:66 ../src\extra\AudioUploader\audioUploader.py:124
|
#: ../src\controller\user.py:66
|
||||||
|
#: ../src\extra\AudioUploader\audioUploader.py:124
|
||||||
msgid "Discarded"
|
msgid "Discarded"
|
||||||
msgstr "Odbačeno"
|
msgstr "Odbačeno"
|
||||||
|
|
||||||
@@ -658,9 +649,8 @@ msgstr "Snimam zvučni zapis..."
|
|||||||
|
|
||||||
#: ../src\extra\AudioUploader\transfer.py:78
|
#: ../src\extra\AudioUploader\transfer.py:78
|
||||||
#: ../src\extra\AudioUploader\transfer.py:84
|
#: ../src\extra\AudioUploader\transfer.py:84
|
||||||
#, fuzzy
|
|
||||||
msgid "Error in file upload: {0}"
|
msgid "Error in file upload: {0}"
|
||||||
msgstr "Kod greške {0}"
|
msgstr "Greška u otpremanju datoteke: {0}"
|
||||||
|
|
||||||
#: ../src\extra\AudioUploader\utils.py:27 ../src\update\utils.py:27
|
#: ../src\extra\AudioUploader\utils.py:27 ../src\update\utils.py:27
|
||||||
msgid "%d day, "
|
msgid "%d day, "
|
||||||
@@ -871,28 +861,24 @@ msgid "Suggestions"
|
|||||||
msgstr "Predlozi"
|
msgstr "Predlozi"
|
||||||
|
|
||||||
#: ../src\extra\SpellChecker\wx_ui.py:42
|
#: ../src\extra\SpellChecker\wx_ui.py:42
|
||||||
#, fuzzy
|
|
||||||
msgid "&Ignore"
|
msgid "&Ignore"
|
||||||
msgstr "Zamenari."
|
msgstr "&Zanemari"
|
||||||
|
|
||||||
#: ../src\extra\SpellChecker\wx_ui.py:43
|
#: ../src\extra\SpellChecker\wx_ui.py:43
|
||||||
#, fuzzy
|
|
||||||
msgid "I&gnore all"
|
msgid "I&gnore all"
|
||||||
msgstr "Zanemari sve"
|
msgstr "Z&anemai sve"
|
||||||
|
|
||||||
#: ../src\extra\SpellChecker\wx_ui.py:44
|
#: ../src\extra\SpellChecker\wx_ui.py:44
|
||||||
#, fuzzy
|
|
||||||
msgid "&Replace"
|
msgid "&Replace"
|
||||||
msgstr "Zameni"
|
msgstr "&Zameni"
|
||||||
|
|
||||||
#: ../src\extra\SpellChecker\wx_ui.py:45
|
#: ../src\extra\SpellChecker\wx_ui.py:45
|
||||||
#, fuzzy
|
|
||||||
msgid "R&eplace all"
|
msgid "R&eplace all"
|
||||||
msgstr "Zameni sve"
|
msgstr "Zam&eni sve"
|
||||||
|
|
||||||
#: ../src\extra\SpellChecker\wx_ui.py:46
|
#: ../src\extra\SpellChecker\wx_ui.py:46
|
||||||
msgid "&Add to personal dictionary"
|
msgid "&Add to personal dictionary"
|
||||||
msgstr ""
|
msgstr "&Dodaj u lični rečnik"
|
||||||
|
|
||||||
#: ../src\extra\SpellChecker\wx_ui.py:79
|
#: ../src\extra\SpellChecker\wx_ui.py:79
|
||||||
msgid ""
|
msgid ""
|
||||||
@@ -1553,9 +1539,8 @@ msgid "Like a tweet"
|
|||||||
msgstr "Označi tvit sa sviđa mi se"
|
msgstr "Označi tvit sa sviđa mi se"
|
||||||
|
|
||||||
#: ../src\keystrokeEditor\constants.py:15
|
#: ../src\keystrokeEditor\constants.py:15
|
||||||
#, fuzzy
|
|
||||||
msgid "Like/unlike a tweet"
|
msgid "Like/unlike a tweet"
|
||||||
msgstr "Označi tvit sa ne sviđa mi se"
|
msgstr "Označi da ti se tvit sviđa / ne sviđa"
|
||||||
|
|
||||||
#: ../src\keystrokeEditor\constants.py:16
|
#: ../src\keystrokeEditor\constants.py:16
|
||||||
msgid "Unlike a tweet"
|
msgid "Unlike a tweet"
|
||||||
@@ -1594,9 +1579,8 @@ msgid "Open URL"
|
|||||||
msgstr "Otvori vezu"
|
msgstr "Otvori vezu"
|
||||||
|
|
||||||
#: ../src\keystrokeEditor\constants.py:25
|
#: ../src\keystrokeEditor\constants.py:25
|
||||||
#, fuzzy
|
|
||||||
msgid "View in Twitter"
|
msgid "View in Twitter"
|
||||||
msgstr "Pretraži ttwitter"
|
msgstr "Prikaži na Twitteru"
|
||||||
|
|
||||||
#: ../src\keystrokeEditor\constants.py:26
|
#: ../src\keystrokeEditor\constants.py:26
|
||||||
msgid "Increase volume by 5%"
|
msgid "Increase volume by 5%"
|
||||||
@@ -1715,9 +1699,8 @@ msgid "Opens the global settings dialogue"
|
|||||||
msgstr "Otvara dijalog globalnih podešavanja"
|
msgstr "Otvara dijalog globalnih podešavanja"
|
||||||
|
|
||||||
#: ../src\keystrokeEditor\constants.py:54
|
#: ../src\keystrokeEditor\constants.py:54
|
||||||
#, fuzzy
|
|
||||||
msgid "Opens the list manager"
|
msgid "Opens the list manager"
|
||||||
msgstr "Upravljanje listama"
|
msgstr "Otvara upravljanje listama"
|
||||||
|
|
||||||
#: ../src\keystrokeEditor\constants.py:55
|
#: ../src\keystrokeEditor\constants.py:55
|
||||||
msgid "Opens the account settings dialogue"
|
msgid "Opens the account settings dialogue"
|
||||||
@@ -1821,6 +1804,10 @@ msgid ""
|
|||||||
"If you're sure that {0} isn't running, try deleting the file at {1}. If "
|
"If you're sure that {0} isn't running, try deleting the file at {1}. If "
|
||||||
"you're unsure of how to do this, contact the {0} developers."
|
"you're unsure of how to do this, contact the {0} developers."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"{0} je već pokrenut. Zatvorite druge pokrenute prozore aplikacije pre "
|
||||||
|
"pokretanja ovog. Ako ste sigurni da {0} nije pokrenut, pokušajte da obrišete "
|
||||||
|
"datoteku koja se nalazi na {1}. Ako niste sigurni kako ovo da uradite, "
|
||||||
|
"kontaktirajte {0} programere."
|
||||||
|
|
||||||
#: ../src\sessionmanager\wxUI.py:8
|
#: ../src\sessionmanager\wxUI.py:8
|
||||||
msgid "Session manager"
|
msgid "Session manager"
|
||||||
@@ -1926,9 +1913,8 @@ msgid "public"
|
|||||||
msgstr "Javno"
|
msgstr "Javno"
|
||||||
|
|
||||||
#: ../src\sessions\twitter\session.py:169
|
#: ../src\sessions\twitter\session.py:169
|
||||||
#, fuzzy
|
|
||||||
msgid "There are no more items to retrieve in this buffer."
|
msgid "There are no more items to retrieve in this buffer."
|
||||||
msgstr "Nema koordinata u ovom tvitu."
|
msgstr "Nema više stavki koje se mogu preuzeti u ovom kanalu."
|
||||||
|
|
||||||
#: ../src\sessions\twitter\session.py:215
|
#: ../src\sessions\twitter\session.py:215
|
||||||
msgid "%s failed. Reason: %s"
|
msgid "%s failed. Reason: %s"
|
||||||
@@ -1951,13 +1937,12 @@ msgid "Error code {0}"
|
|||||||
msgstr "Kod greške {0}"
|
msgstr "Kod greške {0}"
|
||||||
|
|
||||||
#: ../src\sessions\twitter\wxUI.py:6
|
#: ../src\sessions\twitter\wxUI.py:6
|
||||||
#, fuzzy
|
|
||||||
msgid "Authorising account..."
|
msgid "Authorising account..."
|
||||||
msgstr "Autorizovan nalog %d"
|
msgstr "Autorizacija naloga..."
|
||||||
|
|
||||||
#: ../src\sessions\twitter\wxUI.py:9
|
#: ../src\sessions\twitter\wxUI.py:9
|
||||||
msgid "Enter your PIN code here"
|
msgid "Enter your PIN code here"
|
||||||
msgstr ""
|
msgstr "Ovde upišite vaš PIN kod"
|
||||||
|
|
||||||
#: ../src\sound.py:159
|
#: ../src\sound.py:159
|
||||||
msgid "Stopped."
|
msgid "Stopped."
|
||||||
@@ -2266,19 +2251,20 @@ msgstr ""
|
|||||||
"suspendovan sa tvitera."
|
"suspendovan sa tvitera."
|
||||||
|
|
||||||
#: ../src\wxUI\commonMessageDialogs.py:85
|
#: ../src\wxUI\commonMessageDialogs.py:85
|
||||||
#, fuzzy
|
|
||||||
msgid "Do you really want to delete this filter?"
|
msgid "Do you really want to delete this filter?"
|
||||||
msgstr "Želite li zaista da izbrišete ovu listu?"
|
msgstr "Da li zaista želite da izbrišete ovaj filter?"
|
||||||
|
|
||||||
#: ../src\wxUI\commonMessageDialogs.py:88
|
#: ../src\wxUI\commonMessageDialogs.py:88
|
||||||
msgid "This filter already exists. Please use a different title"
|
msgid "This filter already exists. Please use a different title"
|
||||||
msgstr ""
|
msgstr "Ovaj filter već postoji. Molimo koristite drugi naziv"
|
||||||
|
|
||||||
#: ../src\wxUI\commonMessageDialogs.py:94
|
#: ../src\wxUI\commonMessageDialogs.py:94
|
||||||
msgid ""
|
msgid ""
|
||||||
"{0} quit unexpectedly the last time it was run. If the problem persists, "
|
"{0} quit unexpectedly the last time it was run. If the problem persists, "
|
||||||
"please report it to the {0} developers."
|
"please report it to the {0} developers."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"{0} je neočekivano zatvoren pri poslednjem pokretanju. Ako se problem "
|
||||||
|
"nastavi, molimo prijavite ga{0} programerima."
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\attach.py:9
|
#: ../src\wxUI\dialogs\attach.py:9
|
||||||
msgid "Add an attachment"
|
msgid "Add an attachment"
|
||||||
@@ -2343,11 +2329,11 @@ msgstr "Pitaj pre zatvaranja {0}"
|
|||||||
|
|
||||||
#: ../src\wxUI\dialogs\configuration.py:27
|
#: ../src\wxUI\dialogs\configuration.py:27
|
||||||
msgid "Disable Streaming functions"
|
msgid "Disable Streaming functions"
|
||||||
msgstr ""
|
msgstr "Onemogući streaming funkcije"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\configuration.py:30
|
#: ../src\wxUI\dialogs\configuration.py:30
|
||||||
msgid "Buffer update interval, in minutes"
|
msgid "Buffer update interval, in minutes"
|
||||||
msgstr ""
|
msgstr "Interval ažuriranja kanala, u minutima"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\configuration.py:36
|
#: ../src\wxUI\dialogs\configuration.py:36
|
||||||
msgid "Play a sound when {0} launches"
|
msgid "Play a sound when {0} launches"
|
||||||
@@ -2378,7 +2364,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: ../src\wxUI\dialogs\configuration.py:48
|
#: ../src\wxUI\dialogs\configuration.py:48
|
||||||
msgid "Remember state for mention all and long tweet"
|
msgid "Remember state for mention all and long tweet"
|
||||||
msgstr ""
|
msgstr "Pamti stanje opcija spomeni sve i dug tvit"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\configuration.py:51
|
#: ../src\wxUI\dialogs\configuration.py:51
|
||||||
msgid "Keymap"
|
msgid "Keymap"
|
||||||
@@ -2446,11 +2432,11 @@ msgstr ""
|
|||||||
|
|
||||||
#: ../src\wxUI\dialogs\configuration.py:134
|
#: ../src\wxUI\dialogs\configuration.py:134
|
||||||
msgid "Enable automatic speech feedback"
|
msgid "Enable automatic speech feedback"
|
||||||
msgstr ""
|
msgstr "Omogući automatske govorne povratne informacije"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\configuration.py:136
|
#: ../src\wxUI\dialogs\configuration.py:136
|
||||||
msgid "Enable automatic Braille feedback"
|
msgid "Enable automatic Braille feedback"
|
||||||
msgstr ""
|
msgstr "Omogući automatske povratne informacije na brajevom redu"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\configuration.py:144
|
#: ../src\wxUI\dialogs\configuration.py:144
|
||||||
msgid "Status"
|
msgid "Status"
|
||||||
@@ -2564,7 +2550,7 @@ msgstr "Proksi"
|
|||||||
|
|
||||||
#: ../src\wxUI\dialogs\configuration.py:373
|
#: ../src\wxUI\dialogs\configuration.py:373
|
||||||
msgid "Feedback"
|
msgid "Feedback"
|
||||||
msgstr ""
|
msgstr "Povratne informacije"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\configuration.py:377
|
#: ../src\wxUI\dialogs\configuration.py:377
|
||||||
msgid "Buffers"
|
msgid "Buffers"
|
||||||
@@ -2583,81 +2569,74 @@ msgid "Save"
|
|||||||
msgstr "Sačuvaj"
|
msgstr "Sačuvaj"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\filterDialogs.py:15
|
#: ../src\wxUI\dialogs\filterDialogs.py:15
|
||||||
#, fuzzy
|
|
||||||
msgid "Create a filter for this buffer"
|
msgid "Create a filter for this buffer"
|
||||||
msgstr "Stvori kanal trenutnih tema u trendu"
|
msgstr "Napravi filter za ovaj kanal"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\filterDialogs.py:16
|
#: ../src\wxUI\dialogs\filterDialogs.py:16
|
||||||
msgid "Filter title"
|
msgid "Filter title"
|
||||||
msgstr ""
|
msgstr "Naziv filtera"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\filterDialogs.py:25
|
#: ../src\wxUI\dialogs\filterDialogs.py:25
|
||||||
#: ../src\wxUI\dialogs\filterDialogs.py:125
|
#: ../src\wxUI\dialogs\filterDialogs.py:125
|
||||||
msgid "Filter by word"
|
msgid "Filter by word"
|
||||||
msgstr ""
|
msgstr "Filtriraj na osnovu reči"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\filterDialogs.py:26
|
#: ../src\wxUI\dialogs\filterDialogs.py:26
|
||||||
msgid "Ignore tweets wich contain the following word"
|
msgid "Ignore tweets wich contain the following word"
|
||||||
msgstr ""
|
msgstr "Zanemari tvitove koji sadrže sledeću reč"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\filterDialogs.py:27
|
#: ../src\wxUI\dialogs\filterDialogs.py:27
|
||||||
#, fuzzy
|
|
||||||
msgid "Ignore tweets without the following word"
|
msgid "Ignore tweets without the following word"
|
||||||
msgstr "Zanemari tvitove iz ovog klijenta"
|
msgstr "Zanemari tvitove bez sledeće reči"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\filterDialogs.py:32
|
#: ../src\wxUI\dialogs\filterDialogs.py:32
|
||||||
msgid "word"
|
msgid "word"
|
||||||
msgstr ""
|
msgstr "Reč"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\filterDialogs.py:37
|
#: ../src\wxUI\dialogs\filterDialogs.py:37
|
||||||
#, fuzzy
|
|
||||||
msgid "Allow retweets"
|
msgid "Allow retweets"
|
||||||
msgstr "Prikaži tvit"
|
msgstr "Dozvoli retvitove"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\filterDialogs.py:38
|
#: ../src\wxUI\dialogs\filterDialogs.py:38
|
||||||
msgid "Allow quoted tweets"
|
msgid "Allow quoted tweets"
|
||||||
msgstr ""
|
msgstr "Dozvoli citirane tvitove"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\filterDialogs.py:39
|
#: ../src\wxUI\dialogs\filterDialogs.py:39
|
||||||
#, fuzzy
|
|
||||||
msgid "Allow replies"
|
msgid "Allow replies"
|
||||||
msgstr "Vremenska linija pratilaca"
|
msgstr "Dozvoli odgovore"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\filterDialogs.py:47
|
#: ../src\wxUI\dialogs\filterDialogs.py:47
|
||||||
msgid "Use this term as a regular expression"
|
msgid "Use this term as a regular expression"
|
||||||
msgstr ""
|
msgstr "Koristi ovaj termin kao regulara nizraz"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\filterDialogs.py:49
|
#: ../src\wxUI\dialogs\filterDialogs.py:49
|
||||||
#: ../src\wxUI\dialogs\filterDialogs.py:125
|
#: ../src\wxUI\dialogs\filterDialogs.py:125
|
||||||
#, fuzzy
|
|
||||||
msgid "Filter by language"
|
msgid "Filter by language"
|
||||||
msgstr "Izvorni jezik"
|
msgstr "Filtriraj na osnovu jezika"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\filterDialogs.py:50
|
#: ../src\wxUI\dialogs\filterDialogs.py:50
|
||||||
msgid "Load tweets in the following languages"
|
msgid "Load tweets in the following languages"
|
||||||
msgstr ""
|
msgstr "Učitaj tvitove na sledećim jezicima"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\filterDialogs.py:51
|
#: ../src\wxUI\dialogs\filterDialogs.py:51
|
||||||
msgid "Ignore tweets in the following languages"
|
msgid "Ignore tweets in the following languages"
|
||||||
msgstr ""
|
msgstr "Zanemari tvitove na sledećim jezicima"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\filterDialogs.py:52
|
#: ../src\wxUI\dialogs\filterDialogs.py:52
|
||||||
msgid "Don't filter by language"
|
msgid "Don't filter by language"
|
||||||
msgstr ""
|
msgstr "Ne filtriraj na osnovu jezika"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\filterDialogs.py:63
|
#: ../src\wxUI\dialogs\filterDialogs.py:63
|
||||||
#, fuzzy
|
|
||||||
msgid "Supported languages"
|
msgid "Supported languages"
|
||||||
msgstr "Izvorni jezik"
|
msgstr "Podržani jezici"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\filterDialogs.py:68
|
#: ../src\wxUI\dialogs\filterDialogs.py:68
|
||||||
msgid "Add selected language to filter"
|
msgid "Add selected language to filter"
|
||||||
msgstr ""
|
msgstr "Dodaj izabrani jezik u filter"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\filterDialogs.py:72
|
#: ../src\wxUI\dialogs\filterDialogs.py:72
|
||||||
#, fuzzy
|
|
||||||
msgid "Selected languages"
|
msgid "Selected languages"
|
||||||
msgstr "Izvorni jezik"
|
msgstr "Izabrani jezici"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\filterDialogs.py:74
|
#: ../src\wxUI\dialogs\filterDialogs.py:74
|
||||||
#: ../src\wxUI\dialogs\filterDialogs.py:132 ../src\wxUI\dialogs\lists.py:20
|
#: ../src\wxUI\dialogs\filterDialogs.py:132 ../src\wxUI\dialogs\lists.py:20
|
||||||
@@ -2666,17 +2645,16 @@ msgid "Remove"
|
|||||||
msgstr "Ukloni"
|
msgstr "Ukloni"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\filterDialogs.py:122
|
#: ../src\wxUI\dialogs\filterDialogs.py:122
|
||||||
#, fuzzy
|
|
||||||
msgid "Manage filters"
|
msgid "Manage filters"
|
||||||
msgstr "Upravljaj nalozima"
|
msgstr "Upravljanje filterima"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\filterDialogs.py:124
|
#: ../src\wxUI\dialogs\filterDialogs.py:124
|
||||||
msgid "Filters"
|
msgid "Filters"
|
||||||
msgstr ""
|
msgstr "Filteri"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\filterDialogs.py:125
|
#: ../src\wxUI\dialogs\filterDialogs.py:125
|
||||||
msgid "Filter"
|
msgid "Filter"
|
||||||
msgstr ""
|
msgstr "Filter"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\find.py:12
|
#: ../src\wxUI\dialogs\find.py:12
|
||||||
msgid "Find in current buffer"
|
msgid "Find in current buffer"
|
||||||
@@ -2844,9 +2822,8 @@ msgid "Source: "
|
|||||||
msgstr "Izvor:"
|
msgstr "Izvor:"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\message.py:342 ../src\wxUI\dialogs\message.py:420
|
#: ../src\wxUI\dialogs\message.py:342 ../src\wxUI\dialogs\message.py:420
|
||||||
#, fuzzy
|
|
||||||
msgid "Date: "
|
msgid "Date: "
|
||||||
msgstr "Datum"
|
msgstr "Datum:"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\message.py:405
|
#: ../src\wxUI\dialogs\message.py:405
|
||||||
msgid "View"
|
msgid "View"
|
||||||
@@ -2942,9 +2919,8 @@ msgid "Update your profile"
|
|||||||
msgstr "Ažurirajte vaš profil"
|
msgstr "Ažurirajte vaš profil"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\update_profile.py:11
|
#: ../src\wxUI\dialogs\update_profile.py:11
|
||||||
#, fuzzy
|
|
||||||
msgid "&Name (50 characters maximum)"
|
msgid "&Name (50 characters maximum)"
|
||||||
msgstr "Ime, najviše 20 znakova"
|
msgstr "&Ime(najviše 50 znakova)"
|
||||||
|
|
||||||
#: ../src\wxUI\dialogs\update_profile.py:22
|
#: ../src\wxUI\dialogs\update_profile.py:22
|
||||||
msgid "&Website"
|
msgid "&Website"
|
||||||
@@ -3060,9 +3036,8 @@ msgid "&Open URL"
|
|||||||
msgstr "otvori vezu"
|
msgstr "otvori vezu"
|
||||||
|
|
||||||
#: ../src\wxUI\menus.py:17 ../src\wxUI\menus.py:53 ../src\wxUI\menus.py:86
|
#: ../src\wxUI\menus.py:17 ../src\wxUI\menus.py:53 ../src\wxUI\menus.py:86
|
||||||
#, fuzzy
|
|
||||||
msgid "&Open in Twitter"
|
msgid "&Open in Twitter"
|
||||||
msgstr "Pretraži ttwitter"
|
msgstr "&Otvori na Twitteru"
|
||||||
|
|
||||||
#: ../src\wxUI\menus.py:19 ../src\wxUI\menus.py:37 ../src\wxUI\menus.py:55
|
#: ../src\wxUI\menus.py:19 ../src\wxUI\menus.py:37 ../src\wxUI\menus.py:55
|
||||||
msgid "&Play audio"
|
msgid "&Play audio"
|
||||||
@@ -3215,14 +3190,12 @@ msgid "New &trending topics buffer..."
|
|||||||
msgstr "Novi kanal sa temama u trendu"
|
msgstr "Novi kanal sa temama u trendu"
|
||||||
|
|
||||||
#: ../src\wxUI\view.py:54
|
#: ../src\wxUI\view.py:54
|
||||||
#, fuzzy
|
|
||||||
msgid "Create a &filter"
|
msgid "Create a &filter"
|
||||||
msgstr "Stvori novu listu"
|
msgstr "Napravi &filter"
|
||||||
|
|
||||||
#: ../src\wxUI\view.py:55
|
#: ../src\wxUI\view.py:55
|
||||||
#, fuzzy
|
|
||||||
msgid "&Manage filters"
|
msgid "&Manage filters"
|
||||||
msgstr "Upravljaj nalozima"
|
msgstr "&Upravljanje filterima"
|
||||||
|
|
||||||
#: ../src\wxUI\view.py:56
|
#: ../src\wxUI\view.py:56
|
||||||
msgid "Find a string in the currently focused buffer..."
|
msgid "Find a string in the currently focused buffer..."
|
||||||
@@ -3274,7 +3247,7 @@ msgstr "{0} &website"
|
|||||||
|
|
||||||
#: ../src\wxUI\view.py:77
|
#: ../src\wxUI\view.py:77
|
||||||
msgid "Get soundpacks for TWBlue"
|
msgid "Get soundpacks for TWBlue"
|
||||||
msgstr ""
|
msgstr "Nabavi zvučne pakete za TW Blue"
|
||||||
|
|
||||||
#: ../src\wxUI\view.py:78
|
#: ../src\wxUI\view.py:78
|
||||||
msgid "About &{0}"
|
msgid "About &{0}"
|
||||||
|
@@ -37,9 +37,9 @@ error_handler.setLevel(logging.ERROR)
|
|||||||
logger.addHandler(error_handler)
|
logger.addHandler(error_handler)
|
||||||
|
|
||||||
def handle_exception(exc_type, exc_value, exc_traceback):
|
def handle_exception(exc_type, exc_value, exc_traceback):
|
||||||
if issubclass(exc_type, KeyboardInterrupt):
|
if issubclass(exc_type, KeyboardInterrupt):
|
||||||
sys.__excepthook__(exc_type, exc_value, exc_traceback)
|
sys.__excepthook__(exc_type, exc_value, exc_traceback)
|
||||||
return
|
return
|
||||||
logger.error("Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback))
|
logger.error("Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback))
|
||||||
|
|
||||||
sys.excepthook = handle_exception
|
sys.excepthook = handle_exception
|
||||||
|
195
src/main.py
195
src/main.py
@@ -7,19 +7,19 @@ from win32com.client import GetObject
|
|||||||
|
|
||||||
system = platform.system()
|
system = platform.system()
|
||||||
if system == "Windows":
|
if system == "Windows":
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
#redirect the original stdout and stderr
|
#redirect the original stdout and stderr
|
||||||
stdout=sys.stdout
|
stdout=sys.stdout
|
||||||
stderr=sys.stderr
|
stderr=sys.stderr
|
||||||
sys.stdout = open(os.path.join(os.getenv("temp"), "stdout.log"), "w")
|
sys.stdout = open(os.path.join(os.getenv("temp"), "stdout.log"), "w")
|
||||||
sys.stderr = open(os.path.join(os.getenv("temp"), "stderr.log"), "w")
|
sys.stderr = open(os.path.join(os.getenv("temp"), "stderr.log"), "w")
|
||||||
import languageHandler
|
import languageHandler
|
||||||
import paths
|
import paths
|
||||||
#check if TWBlue is installed (Windows only)
|
#check if TWBlue is installed (Windows only)
|
||||||
# ToDo: Remove this soon as this is done already when importing the paths module.
|
# ToDo: Remove this soon as this is done already when importing the paths module.
|
||||||
if os.path.exists(os.path.join(paths.app_path(), "Uninstall.exe")):
|
if os.path.exists(os.path.join(paths.app_path(), "Uninstall.exe")):
|
||||||
paths.mode="installed"
|
paths.mode="installed"
|
||||||
import commandline
|
import commandline
|
||||||
import config
|
import config
|
||||||
import output
|
import output
|
||||||
@@ -32,101 +32,114 @@ import widgetUtils
|
|||||||
import webbrowser
|
import webbrowser
|
||||||
from wxUI import commonMessageDialogs
|
from wxUI import commonMessageDialogs
|
||||||
if system == "Windows":
|
if system == "Windows":
|
||||||
from logger import logger
|
from logger import logger
|
||||||
from update import updater
|
from update import updater
|
||||||
stdout_temp=sys.stdout
|
stdout_temp=sys.stdout
|
||||||
stderr_temp=sys.stderr
|
stderr_temp=sys.stderr
|
||||||
#if it's a binary version
|
#if it's a binary version
|
||||||
if hasattr(sys, 'frozen'):
|
if hasattr(sys, 'frozen'):
|
||||||
sys.stderr = open(os.path.join(paths.logs_path(), "stderr.log"), 'w')
|
sys.stderr = open(os.path.join(paths.logs_path(), "stderr.log"), 'w')
|
||||||
sys.stdout = open(os.path.join(paths.logs_path(), "stdout.log"), 'w')
|
sys.stdout = open(os.path.join(paths.logs_path(), "stdout.log"), 'w')
|
||||||
else:
|
else:
|
||||||
sys.stdout=stdout
|
sys.stdout=stdout
|
||||||
sys.stderr=stderr
|
sys.stderr=stderr
|
||||||
# We are running from source, let's prepare vlc module for that situation
|
# We are running from source, let's prepare vlc module for that situation
|
||||||
if system=="Windows":
|
if system=="Windows":
|
||||||
arch="x86"
|
arch="x86"
|
||||||
if platform.architecture()[0][:2] == "64":
|
if platform.architecture()[0][:2] == "64":
|
||||||
arch="x64"
|
arch="x64"
|
||||||
os.environ['PYTHON_VLC_MODULE_PATH']=os.path.abspath(os.path.join(paths.app_path(), "..", "windows-dependencies", arch))
|
os.environ['PYTHON_VLC_MODULE_PATH']=os.path.abspath(os.path.join(paths.app_path(), "..", "windows-dependencies", arch))
|
||||||
os.environ['PYTHON_VLC_LIB_PATH']=os.path.abspath(os.path.join(paths.app_path(), "..", "windows-dependencies", arch, "libvlc.dll"))
|
os.environ['PYTHON_VLC_LIB_PATH']=os.path.abspath(os.path.join(paths.app_path(), "..", "windows-dependencies", arch, "libvlc.dll"))
|
||||||
#the final log files have been opened succesfully, let's close the temporary files
|
#the final log files have been opened succesfully, let's close the temporary files
|
||||||
stdout_temp.close()
|
stdout_temp.close()
|
||||||
stderr_temp.close()
|
stderr_temp.close()
|
||||||
#finally, remove the temporary files. TW Blue doesn't need them anymore, and we will get more free space on the harddrive
|
#finally, remove the temporary files. TW Blue doesn't need them anymore, and we will get more free space on the harddrive
|
||||||
os.remove(stdout_temp.name)
|
os.remove(stdout_temp.name)
|
||||||
os.remove(stderr_temp.name)
|
os.remove(stderr_temp.name)
|
||||||
import sound
|
import sound
|
||||||
if system == "Linux":
|
if system == "Linux":
|
||||||
from gi.repository import Gdk, GObject, GLib
|
from gi.repository import Gdk, GObject, GLib
|
||||||
|
|
||||||
log = logging.getLogger("main")
|
log = logging.getLogger("main")
|
||||||
|
|
||||||
def setup():
|
def setup():
|
||||||
log.debug("Starting " + application.name + " %s" % (application.version,))
|
log.debug("Starting " + application.name + " %s" % (application.version,))
|
||||||
config.setup()
|
config.setup()
|
||||||
log.debug("Using %s %s" % (platform.system(), platform.architecture()[0]))
|
proxy_setup()
|
||||||
log.debug("Application path is %s" % (paths.app_path(),))
|
log.debug("Using %s %s" % (platform.system(), platform.architecture()[0]))
|
||||||
log.debug("config path is %s" % (paths.config_path(),))
|
log.debug("Application path is %s" % (paths.app_path(),))
|
||||||
sound.setup()
|
log.debug("config path is %s" % (paths.config_path(),))
|
||||||
languageHandler.setLanguage(config.app["app-settings"]["language"])
|
sound.setup()
|
||||||
fixes.setup()
|
languageHandler.setLanguage(config.app["app-settings"]["language"])
|
||||||
output.setup()
|
fixes.setup()
|
||||||
keys.setup()
|
output.setup()
|
||||||
from controller import settings
|
keys.setup()
|
||||||
from controller import mainController
|
from controller import settings
|
||||||
from sessionmanager import sessionManager
|
from controller import mainController
|
||||||
app = widgetUtils.mainLoopObject()
|
from sessionmanager import sessionManager
|
||||||
if system == "Windows":
|
app = widgetUtils.mainLoopObject()
|
||||||
if config.app["app-settings"]["donation_dialog_displayed"] == False:
|
check_pid()
|
||||||
donation()
|
if system == "Windows":
|
||||||
if config.app['app-settings']['check_for_updates']:
|
if config.app["app-settings"]["donation_dialog_displayed"] == False:
|
||||||
updater.do_update()
|
donation()
|
||||||
sm = sessionManager.sessionManagerController()
|
if config.app['app-settings']['check_for_updates']:
|
||||||
sm.fill_list()
|
updater.do_update()
|
||||||
if len(sm.sessions) == 0: sm.show()
|
sm = sessionManager.sessionManagerController()
|
||||||
else:
|
sm.fill_list()
|
||||||
sm.do_ok()
|
if len(sm.sessions) == 0: sm.show()
|
||||||
if hasattr(sm.view, "destroy"):
|
else:
|
||||||
sm.view.destroy()
|
sm.do_ok()
|
||||||
del sm
|
if hasattr(sm.view, "destroy"):
|
||||||
check_pid()
|
sm.view.destroy()
|
||||||
r = mainController.Controller()
|
del sm
|
||||||
r.view.show()
|
r = mainController.Controller()
|
||||||
r.do_work()
|
r.view.show()
|
||||||
r.check_invisible_at_startup()
|
r.do_work()
|
||||||
if system == "Windows":
|
r.check_invisible_at_startup()
|
||||||
call_threaded(r.start)
|
if system == "Windows":
|
||||||
elif system == "Linux":
|
call_threaded(r.start)
|
||||||
GLib.idle_add(r.start)
|
elif system == "Linux":
|
||||||
app.run()
|
GLib.idle_add(r.start)
|
||||||
|
app.run()
|
||||||
|
|
||||||
|
def proxy_setup():
|
||||||
|
if config.app["proxy"]["server"] != "" and config.app["proxy"]["type"] > 0:
|
||||||
|
log.debug("Loading proxy settings")
|
||||||
|
proxy_url = config.app["proxy"]["server"] + ":" + str(config.app["proxy"]["port"])
|
||||||
|
if config.app["proxy"]["user"] != "" and config.app["proxy"]["password"] != "":
|
||||||
|
proxy_url = config.app["proxy"]["user"] + ":" + config.app["proxy"]["password"] + "@" + proxy_url
|
||||||
|
elif config.app["proxy"]["user"] != "" and config.proxyTypes[config.app["proxy"]["type"]] in ["socks4", "socks4a"]:
|
||||||
|
proxy_url = config.app["proxy"]["user"] + "@" + proxy_url
|
||||||
|
proxy_url = config.proxyTypes[config.app["proxy"]["type"]] + "://" + proxy_url
|
||||||
|
os.environ["HTTP_PROXY"] = proxy_url
|
||||||
|
os.environ["HTTPS_PROXY"] = proxy_url
|
||||||
|
|
||||||
def donation():
|
def donation():
|
||||||
dlg = commonMessageDialogs.donation()
|
dlg = commonMessageDialogs.donation()
|
||||||
if dlg == widgetUtils.YES:
|
if dlg == widgetUtils.YES:
|
||||||
webbrowser.open_new_tab(_("https://twblue.es/donate"))
|
webbrowser.open_new_tab(_("https://twblue.es/donate"))
|
||||||
config.app["app-settings"]["donation_dialog_displayed"] = True
|
config.app["app-settings"]["donation_dialog_displayed"] = True
|
||||||
|
|
||||||
def is_running(pid):
|
def is_running(pid):
|
||||||
"Check if the process with ID pid is running. Adapted from https://stackoverflow.com/a/568589"
|
"Check if the process with ID pid is running. Adapted from https://stackoverflow.com/a/568589"
|
||||||
WMI = GetObject('winmgmts:')
|
WMI = GetObject('winmgmts:')
|
||||||
processes = WMI.InstancesOf('Win32_Process')
|
processes = WMI.InstancesOf('Win32_Process')
|
||||||
return [process.Properties_('ProcessID').Value for process in processes if process.Properties_('ProcessID').Value == pid]
|
return [process.Properties_('ProcessID').Value for process in processes if process.Properties_('ProcessID').Value == pid]
|
||||||
|
|
||||||
def check_pid():
|
def check_pid():
|
||||||
"Insures that only one copy of the application is running at a time."
|
"Insures that only one copy of the application is running at a time."
|
||||||
pidpath = os.path.join(os.getenv("temp"), "{}.pid".format(application.name))
|
pidpath = os.path.join(os.getenv("temp"), "{}.pid".format(application.name))
|
||||||
if os.path.exists(pidpath):
|
if os.path.exists(pidpath):
|
||||||
with open(pidpath) as fin:
|
with open(pidpath) as fin:
|
||||||
pid = int(fin.read())
|
pid = int(fin.read())
|
||||||
if is_running(pid):
|
if is_running(pid):
|
||||||
# Display warning dialog
|
# Display warning dialog
|
||||||
commonMessageDialogs.common_error(_(u"{0} is already running. Close the other instance before starting this one. If you're sure that {0} isn't running, try deleting the file at {1}. If you're unsure of how to do this, contact the {0} developers.").format(application.name, pidpath))
|
commonMessageDialogs.common_error(_(u"{0} is already running. Close the other instance before starting this one. If you're sure that {0} isn't running, try deleting the file at {1}. If you're unsure of how to do this, contact the {0} developers.").format(application.name, pidpath))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
else:
|
else:
|
||||||
commonMessageDialogs.dead_pid()
|
commonMessageDialogs.dead_pid()
|
||||||
# Write the new PID
|
# Write the new PID
|
||||||
with open(pidpath,"w") as cam:
|
with open(pidpath,"w") as cam:
|
||||||
cam.write(str(os.getpid()))
|
cam.write(str(os.getpid()))
|
||||||
|
|
||||||
setup()
|
setup()
|
||||||
|
@@ -8,85 +8,85 @@ import logging
|
|||||||
log = logging.getLogger("multiplatform_widgets.widgets")
|
log = logging.getLogger("multiplatform_widgets.widgets")
|
||||||
|
|
||||||
class list(object):
|
class list(object):
|
||||||
def __init__(self, parent, *columns, **listArguments):
|
def __init__(self, parent, *columns, **listArguments):
|
||||||
self.system = platform.system()
|
self.system = platform.system()
|
||||||
self.columns = columns
|
self.columns = columns
|
||||||
self.listArguments = listArguments
|
self.listArguments = listArguments
|
||||||
log.debug("Creating list: Columns: %s, arguments: %s" % (self.columns, self.listArguments))
|
log.debug("Creating list: Columns: %s, arguments: %s" % (self.columns, self.listArguments))
|
||||||
self.create_list(parent)
|
self.create_list(parent)
|
||||||
# self.set_size()
|
# self.set_size()
|
||||||
|
|
||||||
def set_windows_size(self, column, characters_max):
|
def set_windows_size(self, column, characters_max):
|
||||||
# it = wx.ListItem()
|
# it = wx.ListItem()
|
||||||
# dc = wx.WindowDC(self.list)
|
# dc = wx.WindowDC(self.list)
|
||||||
# dc.SetFont(it.GetFont())
|
# dc.SetFont(it.GetFont())
|
||||||
# (x, y) = dc.GetTextExtent("r"*characters_max)
|
# (x, y) = dc.GetTextExtent("r"*characters_max)
|
||||||
self.list.SetColumnWidth(column, characters_max*2)
|
self.list.SetColumnWidth(column, characters_max*2)
|
||||||
|
|
||||||
def set_size(self):
|
def set_size(self):
|
||||||
self.list.SetSize((self.list.GetBestSize()[0], 728))
|
self.list.SetSize((self.list.GetBestSize()[0], 728))
|
||||||
# self.list.SetSize((1439, 1000))
|
# self.list.SetSize((1439, 1000))
|
||||||
|
|
||||||
def create_list(self, parent):
|
def create_list(self, parent):
|
||||||
if self.system == "Windows":
|
if self.system == "Windows":
|
||||||
self.list = wx.ListCtrl(parent, -1, **self.listArguments)
|
self.list = wx.ListCtrl(parent, -1, **self.listArguments)
|
||||||
for i in range(0, len(self.columns)):
|
for i in range(0, len(self.columns)):
|
||||||
self.list.InsertColumn(i, u"%s" % (self.columns[i]))
|
self.list.InsertColumn(i, u"%s" % (self.columns[i]))
|
||||||
else:
|
else:
|
||||||
self.list = wx.ListBox(parent, -1, choices=[])
|
self.list = wx.ListBox(parent, -1, choices=[])
|
||||||
|
|
||||||
def insert_item(self, reversed, *item):
|
def insert_item(self, reversed, *item):
|
||||||
""" Inserts an item on the list, depending on the OS."""
|
""" Inserts an item on the list, depending on the OS."""
|
||||||
if self.system == "Windows":
|
if self.system == "Windows":
|
||||||
if reversed == False: items = self.list.GetItemCount()
|
if reversed == False: items = self.list.GetItemCount()
|
||||||
else: items = 0
|
else: items = 0
|
||||||
self.list.InsertItem(items, item[0])
|
self.list.InsertItem(items, item[0])
|
||||||
for i in range(1, len(self.columns)):
|
for i in range(1, len(self.columns)):
|
||||||
self.list.SetItem(items, i, item[i])
|
self.list.SetItem(items, i, item[i])
|
||||||
else:
|
else:
|
||||||
self.list.Append(" ".join(item))
|
self.list.Append(" ".join(item))
|
||||||
|
|
||||||
def remove_item(self, pos):
|
def remove_item(self, pos):
|
||||||
""" Deletes an item from the list."""
|
""" Deletes an item from the list."""
|
||||||
if self.system == "Windows":
|
if self.system == "Windows":
|
||||||
if pos > 0: self.list.Focus(pos-1)
|
if pos > 0: self.list.Focus(pos-1)
|
||||||
self.list.DeleteItem(pos)
|
self.list.DeleteItem(pos)
|
||||||
else:
|
else:
|
||||||
if pos > 0: self.list.SetSelection(pos-1)
|
if pos > 0: self.list.SetSelection(pos-1)
|
||||||
self.list.Delete(pos)
|
self.list.Delete(pos)
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
if self.system == "Windows":
|
if self.system == "Windows":
|
||||||
self.list.DeleteAllItems()
|
self.list.DeleteAllItems()
|
||||||
else:
|
else:
|
||||||
self.list.Clear()
|
self.list.Clear()
|
||||||
|
|
||||||
def get_selected(self):
|
def get_selected(self):
|
||||||
if self.system == "Windows":
|
if self.system == "Windows":
|
||||||
return self.list.GetFocusedItem()
|
return self.list.GetFocusedItem()
|
||||||
else:
|
else:
|
||||||
return self.list.GetSelection()
|
return self.list.GetSelection()
|
||||||
|
|
||||||
def select_item(self, pos):
|
def select_item(self, pos):
|
||||||
if self.system == "Windows":
|
if self.system == "Windows":
|
||||||
self.list.Focus(pos)
|
self.list.Focus(pos)
|
||||||
else:
|
else:
|
||||||
self.list.SetSelection(pos)
|
self.list.SetSelection(pos)
|
||||||
|
|
||||||
def get_count(self):
|
def get_count(self):
|
||||||
if self.system == "Windows":
|
if self.system == "Windows":
|
||||||
selected = self.list.GetItemCount()
|
selected = self.list.GetItemCount()
|
||||||
else:
|
else:
|
||||||
selected = self.list.GetCount()
|
selected = self.list.GetCount()
|
||||||
if selected == -1:
|
if selected == -1:
|
||||||
return 0
|
return 0
|
||||||
else:
|
else:
|
||||||
return selected
|
return selected
|
||||||
|
|
||||||
def get_text_column(self, indexId, column):
|
def get_text_column(self, indexId, column):
|
||||||
item = self.list.GetItem(indexId, column)
|
item = self.list.GetItem(indexId, column)
|
||||||
return item.GetText()
|
return item.GetText()
|
||||||
|
|
||||||
def set_text_column(self, indexId, column, text):
|
def set_text_column(self, indexId, column, text):
|
||||||
item = self.list.SetStringItem(indexId, column, text)
|
item = self.list.SetStringItem(indexId, column, text)
|
||||||
return item
|
return item
|
||||||
|
@@ -10,35 +10,35 @@ from platform_utils import paths
|
|||||||
RUN_REGKEY = r"SOFTWARE\Microsoft\Windows\CurrentVersion\Run"
|
RUN_REGKEY = r"SOFTWARE\Microsoft\Windows\CurrentVersion\Run"
|
||||||
|
|
||||||
def is_installed(app_subkey):
|
def is_installed(app_subkey):
|
||||||
"""Checks if the currently running copy is installed or portable variant. Requires the name of the application subkey found under the uninstall section in Windows registry."""
|
"""Checks if the currently running copy is installed or portable variant. Requires the name of the application subkey found under the uninstall section in Windows registry."""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s" % app_subkey)
|
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s" % app_subkey)
|
||||||
inst_dir = winreg.QueryValueEx(key,"InstallLocation")[0]
|
inst_dir = winreg.QueryValueEx(key,"InstallLocation")[0]
|
||||||
except WindowsError:
|
except WindowsError:
|
||||||
return False
|
return False
|
||||||
winreg.CloseKey(key)
|
winreg.CloseKey(key)
|
||||||
try:
|
try:
|
||||||
return os.stat(inst_dir) == os.stat(paths.app_path())
|
return os.stat(inst_dir) == os.stat(paths.app_path())
|
||||||
except WindowsError:
|
except WindowsError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def getAutoStart(app_name):
|
def getAutoStart(app_name):
|
||||||
"""Queries if the automatic startup should be set for the application or not, depending on it's current state."""
|
"""Queries if the automatic startup should be set for the application or not, depending on it's current state."""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, RUN_REGKEY)
|
key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, RUN_REGKEY)
|
||||||
val = winreg.QueryValueEx(key, str(app_name))[0]
|
val = winreg.QueryValueEx(key, str(app_name))[0]
|
||||||
return os.stat(val) == os.stat(sys.argv[0])
|
return os.stat(val) == os.stat(sys.argv[0])
|
||||||
except (WindowsError, OSError):
|
except (WindowsError, OSError):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def setAutoStart(app_name, enable=True):
|
def setAutoStart(app_name, enable=True):
|
||||||
"""Configures automatic startup for the application, if the enable argument is set to True. If set to False, deletes the application AutoStart value."""
|
"""Configures automatic startup for the application, if the enable argument is set to True. If set to False, deletes the application AutoStart value."""
|
||||||
if getAutoStart(app_name) == enable:
|
if getAutoStart(app_name) == enable:
|
||||||
return
|
return
|
||||||
key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, RUN_REGKEY, 0, winreg.KEY_WRITE)
|
key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, RUN_REGKEY, 0, winreg.KEY_WRITE)
|
||||||
if enable:
|
if enable:
|
||||||
winreg.SetValueEx(key, str(app_name), None, winreg.REG_SZ, paths.get_executable())
|
winreg.SetValueEx(key, str(app_name), None, winreg.REG_SZ, paths.get_executable())
|
||||||
else:
|
else:
|
||||||
winreg.DeleteValue(key, str(app_name))
|
winreg.DeleteValue(key, str(app_name))
|
||||||
|
@@ -5,14 +5,14 @@ import logging
|
|||||||
log = logging.getLogger("mysc.localization")
|
log = logging.getLogger("mysc.localization")
|
||||||
|
|
||||||
def get(rootFolder):
|
def get(rootFolder):
|
||||||
log.debug("Getting documentation folder. RootFolder: %s" % (rootFolder,))
|
log.debug("Getting documentation folder. RootFolder: %s" % (rootFolder,))
|
||||||
defaultLocale = languageHandler.curLang
|
defaultLocale = languageHandler.curLang
|
||||||
if len(defaultLocale) > 2:
|
if len(defaultLocale) > 2:
|
||||||
defaultLocale = defaultLocale[:2]
|
defaultLocale = defaultLocale[:2]
|
||||||
log.debug("Locale: %s" % (defaultLocale,))
|
log.debug("Locale: %s" % (defaultLocale,))
|
||||||
if os.path.exists(rootFolder+"/"+defaultLocale):
|
if os.path.exists(rootFolder+"/"+defaultLocale):
|
||||||
return defaultLocale
|
return defaultLocale
|
||||||
else:
|
else:
|
||||||
log.debug("The folder does not exist, using the English folder...")
|
log.debug("The folder does not exist, using the English folder...")
|
||||||
return "en"
|
return "en"
|
||||||
|
|
||||||
|
@@ -4,34 +4,34 @@ import logging
|
|||||||
log = logging.getLogger("mysc.repeating_timer")
|
log = logging.getLogger("mysc.repeating_timer")
|
||||||
|
|
||||||
class RepeatingTimer(threading.Thread):
|
class RepeatingTimer(threading.Thread):
|
||||||
"""Call a function after a specified number of seconds, it will then repeat again after the specified number of seconds
|
"""Call a function after a specified number of seconds, it will then repeat again after the specified number of seconds
|
||||||
Note: If the function provided takes time to execute, this time is NOT taken from the next wait period
|
Note: If the function provided takes time to execute, this time is NOT taken from the next wait period
|
||||||
|
|
||||||
t = RepeatingTimer(30.0, f, args=[], kwargs={})
|
t = RepeatingTimer(30.0, f, args=[], kwargs={})
|
||||||
t.start()
|
t.start()
|
||||||
t.cancel() # stop the timer's actions
|
t.cancel() # stop the timer's actions
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, interval, function, daemon=True, *args, **kwargs):
|
def __init__(self, interval, function, daemon=True, *args, **kwargs):
|
||||||
threading.Thread.__init__(self)
|
threading.Thread.__init__(self)
|
||||||
self.daemon = daemon
|
self.daemon = daemon
|
||||||
self.interval = float(interval)
|
self.interval = float(interval)
|
||||||
self.function = function
|
self.function = function
|
||||||
self.args = args
|
self.args = args
|
||||||
self.kwargs = kwargs
|
self.kwargs = kwargs
|
||||||
self.finished = threading.Event()
|
self.finished = threading.Event()
|
||||||
|
|
||||||
def cancel(self):
|
def cancel(self):
|
||||||
"""Stop the timer if it hasn't finished yet"""
|
"""Stop the timer if it hasn't finished yet"""
|
||||||
log.debug("Stopping repeater for %s" % (self.function,))
|
log.debug("Stopping repeater for %s" % (self.function,))
|
||||||
self.finished.set()
|
self.finished.set()
|
||||||
stop = cancel
|
stop = cancel
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
while not self.finished.is_set():
|
while not self.finished.is_set():
|
||||||
self.finished.wait(self.interval)
|
self.finished.wait(self.interval)
|
||||||
if not self.finished.is_set(): #In case someone has canceled while waiting
|
if not self.finished.is_set(): #In case someone has canceled while waiting
|
||||||
try:
|
try:
|
||||||
self.function(*self.args, **self.kwargs)
|
self.function(*self.args, **self.kwargs)
|
||||||
except:
|
except:
|
||||||
log.exception("Execution failed. Function: %r args: %r and kwargs: %r" % (self.function, self.args, self.kwargs))
|
log.exception("Execution failed. Function: %r args: %r and kwargs: %r" % (self.function, self.args, self.kwargs))
|
||||||
|
@@ -1,12 +1,16 @@
|
|||||||
# -*- coding: cp1252
|
# -*- coding: cp1252
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import sys, os
|
import sys, os
|
||||||
|
import application
|
||||||
|
|
||||||
def restart_program():
|
def restart_program():
|
||||||
""" Function that restarts the application if is executed."""
|
""" Function that restarts the application if is executed."""
|
||||||
args = sys.argv[:]
|
args = sys.argv[:]
|
||||||
if not hasattr(sys, "frozen"):
|
if not hasattr(sys, "frozen"):
|
||||||
args.insert(0, sys.executable)
|
args.insert(0, sys.executable)
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
args = ['"%s"' % arg for arg in args]
|
args = ['"%s"' % arg for arg in args]
|
||||||
os.execv(sys.executable, args)
|
pidpath = os.path.join(os.getenv("temp"), "{}.pid".format(application.name))
|
||||||
|
if os.path.exists(pidpath):
|
||||||
|
os.remove(pidpath)
|
||||||
|
os.execv(sys.executable, args)
|
||||||
|
@@ -1,39 +1,19 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
|
||||||
from future import standard_library
|
|
||||||
standard_library.install_aliases()
|
|
||||||
import logging
|
import logging
|
||||||
log = logging.getLogger("mysc.thread_utils")
|
log = logging.getLogger("mysc.thread_utils")
|
||||||
import threading
|
import threading
|
||||||
import wx
|
import wx
|
||||||
from pubsub import pub
|
from pubsub import pub
|
||||||
from twython import TwythonRateLimitError
|
|
||||||
|
|
||||||
def call_threaded(func, *args, **kwargs):
|
def call_threaded(func, *args, **kwargs):
|
||||||
#Call the given function in a daemonized thread and return the thread.
|
#Call the given function in a daemonized thread and return the thread.
|
||||||
def new_func(*a, **k):
|
def new_func(*a, **k):
|
||||||
try:
|
try:
|
||||||
func(*a, **k)
|
func(*a, **k)
|
||||||
except TwythonRateLimitError:
|
except:
|
||||||
pass
|
log.exception("Thread %d with function %r, args of %r, and kwargs of %r failed to run." % (threading.current_thread().ident, func, a, k))
|
||||||
except:
|
|
||||||
log.exception("Thread %d with function %r, args of %r, and kwargs of %r failed to run." % (threading.current_thread().ident, func, a, k))
|
|
||||||
# pass
|
# pass
|
||||||
thread = threading.Thread(target=new_func, args=args, kwargs=kwargs)
|
thread = threading.Thread(target=new_func, args=args, kwargs=kwargs)
|
||||||
thread.daemon = True
|
thread.daemon = True
|
||||||
thread.start()
|
thread.start()
|
||||||
return thread
|
return thread
|
||||||
|
|
||||||
def stream_threaded(func, *args, **kwargs):
|
|
||||||
def new_func(*a, **k):
|
|
||||||
try:
|
|
||||||
func(**k)
|
|
||||||
except Exception as msg:
|
|
||||||
log.error("Error in stream with args: %r" % (a,))
|
|
||||||
log.error(msg.message)
|
|
||||||
pub.sendMessage("stream-error", session=a[0])
|
|
||||||
|
|
||||||
thread = threading.Thread(target=new_func, args=args, kwargs=kwargs)
|
|
||||||
thread.daemon = True
|
|
||||||
thread.start()
|
|
||||||
return thread
|
|
||||||
|
@@ -8,16 +8,16 @@ import platform
|
|||||||
notify = None
|
notify = None
|
||||||
|
|
||||||
def setup():
|
def setup():
|
||||||
global notify
|
global notify
|
||||||
if platform.system() == "Windows":
|
if platform.system() == "Windows":
|
||||||
from . import windows
|
from . import windows
|
||||||
notify = windows.notification()
|
notify = windows.notification()
|
||||||
elif platform.system() == "Linux":
|
elif platform.system() == "Linux":
|
||||||
from . import linux
|
from . import linux
|
||||||
notify = linux.notification()
|
notify = linux.notification()
|
||||||
|
|
||||||
def send(title, text):
|
def send(title, text):
|
||||||
global notify
|
global notify
|
||||||
if not notify or notify is None:
|
if not notify or notify is None:
|
||||||
setup()
|
setup()
|
||||||
notify.notify(title, text)
|
notify.notify(title, text)
|
||||||
|
@@ -5,23 +5,23 @@ import dbus
|
|||||||
import application
|
import application
|
||||||
|
|
||||||
class notifications(object):
|
class notifications(object):
|
||||||
"""Supports notifications on Linux.
|
"""Supports notifications on Linux.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(notifications, self).__init__()
|
super(notifications, self).__init__()
|
||||||
self.item = "org.freedesktop.Notifications"
|
self.item = "org.freedesktop.Notifications"
|
||||||
self.path = "/org/freedesktop/Notifications"
|
self.path = "/org/freedesktop/Notifications"
|
||||||
self.interface = "org.freedesktop.Notifications"
|
self.interface = "org.freedesktop.Notifications"
|
||||||
self.app_name = application.name
|
self.app_name = application.name
|
||||||
self.id_num_to_replace = 0
|
self.id_num_to_replace = 0
|
||||||
self.icon = "/usr/share/icons/Tango/32x32/status/sunny.png"
|
self.icon = "/usr/share/icons/Tango/32x32/status/sunny.png"
|
||||||
|
|
||||||
def notify(self, title="", text=""):
|
def notify(self, title="", text=""):
|
||||||
actions_list = ''
|
actions_list = ''
|
||||||
hint = ''
|
hint = ''
|
||||||
time = 5000 # Use seconds x 1000
|
time = 5000 # Use seconds x 1000
|
||||||
bus = dbus.SessionBus()
|
bus = dbus.SessionBus()
|
||||||
notif = bus.get_object(self.item, self.path)
|
notif = bus.get_object(self.item, self.path)
|
||||||
notify = dbus.Interface(notif, self.interface)
|
notify = dbus.Interface(notif, self.interface)
|
||||||
notify.Notify(self.app_name, self.id_num_to_replace, self.icon, title, text, actions_list, hint, time)
|
notify.Notify(self.app_name, self.id_num_to_replace, self.icon, title, text, actions_list, hint, time)
|
||||||
|
@@ -5,5 +5,5 @@ import wx
|
|||||||
|
|
||||||
class notification(object):
|
class notification(object):
|
||||||
|
|
||||||
def notify(self, title, text):
|
def notify(self, title, text):
|
||||||
wx.NotificationMessage(title, text).Show()
|
wx.NotificationMessage(title, text).Show()
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user