Compare commits
109 Commits
snapshot9.
...
v0.51
Author | SHA1 | Date | |
---|---|---|---|
437f01ac78 | |||
fd6c7fa2d7 | |||
![]() |
b373e716c7 | ||
cc00c513c3 | |||
![]() |
0a0fe58715 | ||
e831098bd2 | |||
![]() |
05d62456ee | ||
d2e6221432 | |||
![]() |
d31a3e5bb7 | ||
e3b0a3d731 | |||
3a6849cf0b | |||
6832a4a93e | |||
![]() |
bda1ddce47 | ||
b106b3a0f2 | |||
813ad2fc1e | |||
4bcd8d8b4e | |||
![]() |
4ef7c6c5f1 | ||
b6c9edafcf | |||
73be8400b0 | |||
![]() |
5fdbb578c4 | ||
![]() |
540bf5d312 | ||
375cdd2528 | |||
![]() |
836675bfa1 | ||
![]() |
2b3c7601f2 | ||
eb2c315abb | |||
e12f440cf2 | |||
![]() |
57dc271fb0 | ||
193cafcc9d | |||
![]() |
e7b6c39f76 | ||
7df2441442 | |||
![]() |
aa687450f6 | ||
6e0ae38d4e | |||
![]() |
fa8c9f639c | ||
9502cef251 | |||
![]() |
982dd78f81 | ||
![]() |
4b98f27968 | ||
![]() |
ecb0fa8f2b | ||
ef2ff9dbfc | |||
![]() |
1fe94642a2 | ||
b232a0b0ad | |||
2ce59cf208 | |||
![]() |
ceb8266828 | ||
![]() |
21970f2c94 | ||
14965f73d3 | |||
![]() |
267b454fc6 | ||
c3dc00c241 | |||
![]() |
9fb67f01ae | ||
6d1cd0b1fc | |||
a7ef572d05 | |||
403784b77a | |||
d032a6d8f7 | |||
![]() |
231d43ab22 | ||
5e3bcfc82e | |||
8e92d97260 | |||
bb1ffa9ff1 | |||
104bc4ec8c | |||
![]() |
6ae555fe72 | ||
![]() |
dd51516c30 | ||
![]() |
4e18bb0721 | ||
![]() |
0492e65aa0 | ||
![]() |
a5fb59d7a7 | ||
f2fab29cb7 | |||
![]() |
f36accf89b | ||
a13536233e | |||
bc2d448464 | |||
60ec9ab215 | |||
20b5fc079b | |||
80e231b689 | |||
7137d437bd | |||
![]() |
a07b3c1829 | ||
![]() |
c062c10542 | ||
![]() |
0e7c070bd4 | ||
![]() |
9f35d079b1 | ||
![]() |
a3fca4d2a0 | ||
ada6f1fb0d | |||
79124810b0 | |||
fee7254d55 | |||
![]() |
c12902d011 | ||
2f7eb12104 | |||
855cefeb8d | |||
e649b883c6 | |||
![]() |
1a61f2d790 | ||
![]() |
6abfba317a | ||
![]() |
18ce92daab | ||
![]() |
84f729f42b | ||
![]() |
4e7666cf52 | ||
88e0fbb531 | |||
af32b3ceb6 | |||
94dc083650 | |||
acb3cce1d6 | |||
![]() |
2b3e1099f6 | ||
![]() |
60507e8f6b | ||
![]() |
75bfc17bb1 | ||
acb8c5acd3 | |||
![]() |
5bcf04fc94 | ||
0f2fbc775a | |||
1b684cd12c | |||
9d64901791 | |||
18f7cb6c96 | |||
7f673fb9de | |||
![]() |
f6f542fbec | ||
![]() |
a211e2e5e4 | ||
3ec8ac31a5 | |||
![]() |
dacbb19586 | ||
![]() |
55691cca20 | ||
0104b97df0 | |||
aa58e61e5e | |||
![]() |
fae204f3c2 | ||
d8149a4c96 |
8
.gitignore
vendored
@@ -3,17 +3,11 @@
|
||||
src/build/
|
||||
src/dist/
|
||||
src/config/
|
||||
src/config1/
|
||||
src/config2/
|
||||
src/config3/
|
||||
src/dropbox/
|
||||
src/logs/
|
||||
src/documentation/
|
||||
src/sounds/iOs
|
||||
src/oggenc2.exe
|
||||
src/bootstrap.exe
|
||||
src/Microsoft.VC90.CRT
|
||||
src/Microsoft.VC90.MFC
|
||||
src/launcher.bat
|
||||
src/sounds/iOs
|
||||
release-snapshot/
|
||||
src/launcher.bat
|
23
README.md
@@ -1,10 +1,9 @@
|
||||
TWBlue -
|
||||
TWBlue
|
||||
======
|
||||
|
||||
Copyright (C) 2015. [Technow S.L.](https://www.technow.es)
|
||||
TWBlue, an accessible, open source and multiplatform twitter application.
|
||||
|
||||
TW Blue is an app designed to use Twitter simply and efficiently while using minimal system resources.
|
||||
With this app you’ll have access to twitter features such as:
|
||||
TW Blue is an app designed to use Twitter in a simple and fast way and avoiding, as far as possible, the consumtion of excessive resources of the machine where it’s running. With this app you’ll have access to twitter features such as:
|
||||
|
||||
* Create, reply to, retweet and delete tweets,
|
||||
* Add and remove tweets from favourites,
|
||||
@@ -12,11 +11,11 @@ With this app you’ll have access to twitter features such as:
|
||||
* See your friends and followers,
|
||||
* Follow, unfollow, block and report users as spam,
|
||||
* Open a user’s timeline, which will allow you to get that user’s tweets separately,
|
||||
* Open URLs when attached to a tweet or direct message,
|
||||
* Play audio tweets
|
||||
* Open URL addresses when attached to a tweet or direct message,
|
||||
* Play various file and URL types which contain audio
|
||||
* and more!
|
||||
|
||||
See [TWBlue's webpage](http://twblue.es) for more details.
|
||||
See the [TWBlue's webpage](http://twblue.com.mx) for more details.
|
||||
|
||||
## Using TWBlue from sources
|
||||
|
||||
@@ -60,7 +59,6 @@ setuptools install a script, called easy_install. You can find it in the python
|
||||
|
||||
The -z switch unzips the package, instead of installing it compressed. If you add the --upgrade switch, you can upgrade a package to its latest version. The following packages need to be installed:
|
||||
|
||||
* pypubsub
|
||||
* dropbox
|
||||
* configobj
|
||||
* requests-oauthlib
|
||||
@@ -68,7 +66,6 @@ setuptools install a script, called easy_install. You can find it in the python
|
||||
* pygeocoder
|
||||
* suds
|
||||
* arrow
|
||||
* goslate
|
||||
* markdown
|
||||
|
||||
easy_install will automatically get the additional libraries that these packages need to work properly.
|
||||
@@ -88,15 +85,15 @@ This dependency has been built using pure basic 4.61. Its source can be found at
|
||||
|
||||
### Running TW Blue from source
|
||||
|
||||
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 src directory into the repo, and type the following command:
|
||||
|
||||
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 necesary, change the first part of the command to reflect where is your python executable. You can run TW Blue using python x86 and x64
|
||||
|
||||
### Building a binary version
|
||||
|
||||
A binary version doesn't need python and the other dependencies to run, it's the same version that you will find on the TW Blue website if you download the zip files.
|
||||
A binary version doesn't need python and the other dependencies to run, it's the same version that you will find in TW Blue website if you download the zip files.
|
||||
|
||||
To build it, run the following command from the src folder:
|
||||
|
||||
@@ -106,4 +103,4 @@ To build it, run the following command from the src folder:
|
||||
|
||||
### How to generate a translation template
|
||||
|
||||
Run the gen_pot.bat file, located in the tools directory. Your python installation must be in your path environment variable. The pot file will appear in the tools directory.
|
||||
You must run the gen_pot.bat file, located in the tools directory. Your python installation should be in your path environment variable. The pot file will appear in the tools directory too.
|
@@ -1,5 +1,4 @@
|
||||
Manuel E. Cortéz
|
||||
Bill Dengler
|
||||
Johana Hidrobo
|
||||
Marcelo Sosa
|
||||
Isabel del Castillo
|
||||
|
@@ -1,7 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
name = 'TWBlue'
|
||||
snapshot = False
|
||||
if snapshot == False:
|
||||
version = "0.80"
|
||||
else:
|
||||
version = "7"
|
247
doc/strings.py
@@ -13,7 +13,7 @@ documentation.append(_(u"""
|
||||
documentation.append(_(u"""## Warning!"""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""You're reading documentation produced for a program still in development. The object of this manual is to explain some details of the operation of the program. Bear in mind that as the software is in the process of active development, parts of this document may change in the near future, so it is advisable to keep an eye on it from time to time to avoid missing too much out."""))
|
||||
documentation.append(_(u"""You're reading documentation produced for a program still in development. The object of this manual is explaining some details of the operation of the program. Bear in mind that as the software is in the process of active development, parts of this document may change in the near future, so it is advisable to keep an eye on it from time to time to avoid missing too much out."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""If you want to see what has changed from the previous version, [read the list of updates here.](changes.html)"""))
|
||||
@@ -48,36 +48,38 @@ documentation.append(_(u"""
|
||||
documentation.append(_(u"""First off, it's necessary to authorise the program so it can access your Twitter account and act on your behalf. The authorisation process is quite simple, and the program never gets data such as your username and password. In order to authorise the application, you just need to run the main executable file, called TWBlue.exe (on some computers it may appear simply as TWBlue)."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""Whether this is the first time you open TWBlue or you don't have any session, you will see the session manager. This dialog allows you to authorise as many accounts as you wish. If you press the "new account" button a dialog will tell you that your default browser will be opened in order to authorise the application. Press "yes" so the process may start."""))
|
||||
#$documentation.append(_(u"""When executed, if you have not previously configured the program, it will show a dialogue box where it tells you'll be taken to Twitter in order to authorise the application as soon as you press OK. To begin the authorisation process, press the only available button on the box."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""Your default browser will open on the Twitter page to request authorisation. Enter your user name and password if you're not already logged in, look for the authorise button, and press it."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""Once you've authorised your twitter account, Twitter will redirect you to a web page which will notify you that TWBlue has been authorised successfully. Now you are able to close that window and come back to the session manager. You will see on the session list a new item temporally called "Authorised account x" -where x is a number. The session name will change once you open that session."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""To start running TWBlue, press the Ok button in the session manager dialog. By default, TWBlue starts all the configured sessions, however, you can change this behavior."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
#$documentation.append(_(u"""Read the instructions you will get if the process is successful. In summary, you will be given a numeric code with several digits you must paste on an edit field open by the application on another window."""))
|
||||
#$documentation.append(_(u"""
|
||||
#$"""))
|
||||
#$documentation.append(_(u"""Paste the verification code, and press the enter key. """))
|
||||
#$documentation.append(_(u"""
|
||||
#$"""))
|
||||
### Add here the instructions on how to deal with the session manager.
|
||||
documentation.append(_(u"""If all went well, the application will start playing sounds, indicating your data are being updated."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""When the process is finished, the program will play another sound, and the screen reader will say "ready"."""))
|
||||
documentation.append(_(u"""When the process is finished,the program will play another sound, and the screen reader will say "ready"."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""## The program's interface"""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""The easiest way to describe the graphical user interface of TWBlue is saying that the application has a window which contains a menu bar with five menus (application, tweet, user, buffer and help); one tree view, one list of items and, mostly in every case, three buttons: Tweet, retweet and reply. The actions that are available for every item will be described later."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""In the tree view are inserted buffers which are lists to manage the processed data. When you configure a new session on TWBlue and start it, your account is the root of the tree view. Inside of it many buffers are created. Each one of them may contain some of the items which TWBlue works with: Tweets, direct messages, users, trends or events. According to the buffer you were, you will be able to make different actions with these items."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""The following is a description for every kind of TWBlue's buffer and the kind of items they work with."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
### Add the new GUI description here
|
||||
#$documentation.append(_(u"""The easiest way to describe the graphical interface of the application is a window with a menu bar with five menus (application, tweet, user, buffer and help), a list with several elements, and, in most cases, three buttons: tweet, retweet and reply. The actions available for each element are described below."""))
|
||||
#$documentation.append(_(u"""
|
||||
#$"""))
|
||||
#$documentation.append(_(u"""Elements on the lists may be tweets, direct messages or users. TW Blue creates different tabs for each list, which can be sent tweets, main timeline tweets, favourites, or direct messages, and each tab contains a single type of tweet. These tabs are called lists or buffers."""))
|
||||
#$documentation.append(_(u"""
|
||||
#$"""))
|
||||
#$documentation.append(_(u"""To switch from list to list press control-tab to go forward, and control-shift-tab to go back. Screen readers will announce the list that gains the focus at all times. These are the basic lists of TW Blue, which are configured by default."""))
|
||||
#$documentation.append(_(u"""
|
||||
#$"""))
|
||||
documentation.append(_(u"""* Home: it shows all the tweets on the main timeline. These are the tweets by users you follow."""))
|
||||
documentation.append(_(u"""* Mentions: if a user, whether you follow them or not, mentions you on Twitter, you will find it on this list."""))
|
||||
documentation.append(_(u"""* Direct messages: here go the private direct messages you exchange with users you follow and who follow you back. This list only shows received messages."""))
|
||||
@@ -90,22 +92,27 @@ documentation.append(_(u"""* Events: An event is anything that happens on Twitte
|
||||
documentation.append(_(u"""* Lists: A list is similar to a temporary timeline, except that you can configure it to contain tweets from multiple users."""))
|
||||
documentation.append(_(u"""* Search: A search buffer contains the results of a search operation."""))
|
||||
documentation.append(_(u"""* User favorites: You can have TW Blue create a buffer containing tweets favorited by a particular user."""))
|
||||
documentation.append(_(u"""* Trending Topics: a trend buffer shows the top ten most used terms in a geographical region. This region may be a country or a city. Trends are updated every five minutes."""))
|
||||
### add here the trending buffers description.
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""If there's a URL on a tweet, TW Blue will try to open it when you press enter on it. If there are several, it will show you a list with all of them so you choose the one you want. If you're on the followers or friends buffer, the enter key will show you additional information about them."""))
|
||||
#$documentation.append(_(u"""Note: In this version of TW Blue, you will be able to see up to (or around) 400 friends and followers in their respective buffers. In the next version, we will provide a solution for those who have more to be able to see them."""))
|
||||
#$documentation.append(_(u"""
|
||||
#$"""))
|
||||
#$documentation.append(_(u"""Bear in mind the default configuration only allows getting the last 200 tweets for the home,, mentions, direct messages, and user timeline lists. You can change this on the setup dialogue. For the sent list, the last 200 tweets and the last 200 sent direct messages will be retrieved. Future versions will allow changing this parameter."""))
|
||||
#$documentation.append(_(u"""
|
||||
#$"""))
|
||||
documentation.append(_(u"""If there's a URL on a tweet TW Blue will try to open it when you press enter on it. If there are several, it will show you a list with all of them so you choose the one you want. If you're on the followers or friends buffer, the enter key will show you additional information on them."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""If you press control-enter, TW Blue will try to play the audio from the focused tweet, as long as it has a URL. If it has the #audio hashtag, you will hear a sound when it is selected, letting you know you can try to play it. However, a tweet can be missing the hashtag and TW Blue will still be able to play it so long as it contains a URL with audio."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""You will also hear a sound when you see any tweet containing geographical information. You can see someone's location by selecting the option "view address" from the tweet menu on the menu bar."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
### Add information about the GEO location in tweets.
|
||||
documentation.append(_(u"""## Controls"""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""Beginning with the 0.36 version, there's support for an interface which does not require a visible window. It can be activated by pressing control-m, or choosing hide window from the application menu. This interface is entirely driven through shortcut keys. These shortcuts are different from those used to drive the graphical interface. By default, you can't use the invisible interface shortcuts on the GUI. It has been made this way to keep compatibility with applications like TheQube and Chicken nugget which may use the same shortcuts. If you wish to have available the invisible interface shortcuts even if you are using the GUI, activate this option on the General tab of the preferences dialogue. This section describes both the graphical and the invisible interface."""))
|
||||
### add more information about using invisible shorcuts in the GUI mode in the next variable.
|
||||
documentation.append(_(u"""Beginning with the 0.36 version, there's support for an interface which does not require a visible window. It can be activated by pressing control-m, or choosing hide window from the application menu. This interface is entirely driven through shortcut keys. These shortcuts are different from those used to drive the graphical interface. This section describes both the graphical and the invisible interface."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""### The graphical user interface (GUI)"""))
|
||||
@@ -117,7 +124,8 @@ documentation.append(_(u"""
|
||||
documentation.append(_(u"""#### Buttons on the application"""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""* Tweet: this button opens up a dialogue box to write your tweet. The message must not exceed 140 characters. If you write past this limit, a sound will play to warn you. You may use the shorten and expand URL buttons to comply with the character limit. You can translate your message, upload a picture, check spelling or attach audio by selecting one of the available buttons in the dialogue. Press enter to send the tweet. If all goes well, you'll hear a sound confirming it. Otherwise, the screen reader will say an error message in English describing the problem."""))
|
||||
### Add information on spell correction, translate, attach images and audio.
|
||||
documentation.append(_(u"""* Tweet: this button opens up a dialogue box to write your tweet. The message must not exceed 140 characters. If you write past this limit, a sound will play to warn you. You may use the shorten and expand URL buttons to comply with the character limit. Press enter to send the tweet. If all goes well, you'll hear a sound confirming it. Otherwise, the screen reader will say an error message in English describing the problem."""))
|
||||
documentation.append(_(u"""* Retweet: this button retweets the message you're reading. After you press it, you'll be asked if you want to add a comment or simply send it as written."""))
|
||||
documentation.append(_(u"""* Reply: when you're viewing a tweet, you can reply to the user who sent it by pressing this button. A dialogue will open up like the one for tweeting, but with the name of the user already filled in (for example @user) so you only need to write your message. If there are more users mentioned on the tweet, you can press shift-tab and press the mention all users button. When you're on the friends or followers lists, the button will be called mention instead."""))
|
||||
documentation.append(_(u"""* Direct message: exactly like sending a tweet, but it's a private message which can only be read by the user you send it to. Press shift-tab to see the recipient. If there were other users mentioned on the tweet you were reading, you can arrow up or down to choose which one to send it to, or write the username yourself without the at sign."""))
|
||||
@@ -135,77 +143,206 @@ documentation.append(_(u"""
|
||||
documentation.append(_(u"""##### Application menu"""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""* Session manager: Opens a window with all the sessions configured in TWBlue, where you can add new sessions or delete the ones you've already created."""))
|
||||
documentation.append(_(u"""* Update profile: opens a dialogue box where you can update your information on Twitter: name, location, URL and bio. If you have already set this up the fields will be prefilled with the existing information. Also, you can upload a photo to your profile."""))
|
||||
documentation.append(_(u"""* Hide window: turns off the Graphical User Interface. Read the section on the invisible interface for further details."""))
|
||||
documentation.append(_(u"""* Search: shows a dialog where you can search for tweets or users on Twitter."""))
|
||||
documentation.append(_(u"""* View trending topics: It opens a buffer to get the trending topics of a country or a city. You'll be able to select from a dialog if you wish to get countries' trends or cities' trends and choose one from the selected list. The trending topics buffer will be created once pressing "ok" on this dialog. Remember this kind of buffer will be updated every five minutes."""))
|
||||
documentation.append(_(u"""* Lists Manager: This dialog allows you to manage your Twitter lists. In order to use them, you must first create them. Here, you can view, edit, create, delete or, optionally, open them in buffers similar to temporary timelines."""))
|
||||
documentation.append(_(u"""* Sounds tutorial: Opens a dialog where you can familiarize yourself with the different sounds of the program."""))
|
||||
documentation.append(_(u"""* Edit keystrokes: It opens a dialog where you can see and re edit the invisible interface shortcuts."""))
|
||||
### Add description for the global settings and accounts settings options.
|
||||
documentation.append(_(u"""* Quit: asks whether you want to exit the program. If the answer is yes, it shuts the application down. If you wish TWBlue not to ask you for confirmation before exiting, uncheck the checkbox from the preferences dialogue."""))
|
||||
documentation.append(_(u"""* Sound tutorial: Opens a dialog where you can familiarize yourself with the different sounds of the program."""))
|
||||
documentation.append(_(u"""* Preferences: opens up a preference dialogue box from which you can control some of the program settings. The options need no explanation."""))
|
||||
documentation.append(_(u"""* Quit: asks whether you want to exit the program. If the answer is yes, it shuts the application down."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""##### Tweet menu"""))
|
||||
documentation.append(_(u"""##### Tweet menu {#tweet}"""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""* You will first find the items to tweet, reply and retweet, which are equivalent to the buttons with the same name."""))
|
||||
documentation.append(_(u"""* Mark as favourite: marks the tweet you're viewing as a favourite."""))
|
||||
documentation.append(_(u"""* Remove tweet from favourites: removes the tweet from your favourites, but not from Twitter."""))
|
||||
documentation.append(_(u"""* Show tweet: opens up a dialogue box where you can read the tweet, direct message, friend or follower under focus. You can read the text with the arrow keys. It's the same dialogue box used to write tweets on."""))
|
||||
documentation.append(_(u"""* View address: If the selected tweet has geographical information, TWBlue may display a dialog where you can read the tweet address. This address is got by sending the geographical coordinates of the tweet to Google maps."""))
|
||||
### Add description for view conversation feature
|
||||
documentation.append(_(u"""* Show tweet: opens up a dialogue box where you can read the tweet, direct message, friend or follower under focus. You can read the text with the cursors. It's the same dialogue box used to write tweets on."""))
|
||||
documentation.append(_(u"""* Delete: permanently removes the tweet or direct message you're on from Twitter and from your lists. Bear in mind that Twitter only allows you to delete tweets you have posted yourself."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""##### User menu"""))
|
||||
documentation.append(_(u"""##### User menu {#user}"""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""The available actions you can choose are described below:"""))
|
||||
documentation.append(_(u"""Bear in mind the four topmost items on this menu open up the same dialogue box. This box has an edit field where you can choose the user you want to act on, by using up and down arrows or by writing the text in yourself. Afterwards you will find a group with four radio buttons to follow, unfollow, report as spam and block. If you choose the follow menu item, the radio button on the dialogue box will be set to follow, and the same applies to unfollow, report as spam and block. Press OK to try to carry out the action. If it doesn't succeed, you'll hear the error message in English."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""The remaining items on the menu are described below:"""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""* Follow: Follows a user. This means you'll see his/her tweets on your main timeline, and if he/she also follows you, you'll be able to interchange direct messages."""))
|
||||
documentation.append(_(u"""* Unfollow: Stops following a user, which causes you not being able to see his/her tweets on your main timeline neither interchanging direct messages."""))
|
||||
documentation.append(_(u"""* Mute: While muting someone, TWBlue won't show you nor his/her tweets on your main timeline; neither you'll see that person's mentions. But you both will be able to interchange direct messages. The muted user is not informed of this action."""))
|
||||
documentation.append(_(u"""* Unmute: It turns the way TWBlue treats this user to its normal way. You will see his/her tweets and mentions again."""))
|
||||
documentation.append(_(u"""* Report as spam: It suggests twitter this user is performing prohibited practices on the social network."""))
|
||||
documentation.append(_(u"""* Block: Blocks a user. This forces the user to unfollow you ."""))
|
||||
documentation.append(_(u"""* Unblock: Stops blocking a user.""")
|
||||
documentation.append(_(u"""* Direct message: same action as the button."""))
|
||||
documentation.append(_(u"""* Add to List: In order to see someone's tweets in one or more of your lists, you must add them first. This option will open a dialog where you can select the user you wish to add. Next, you will be asked to select the list you wish to add them to. Afterwards, the list will contain a new member and their tweets will show up there."""))
|
||||
### add description for remove from list and view lists.
|
||||
documentation.append(_(u"""* View user profile: opens up a dialogue box to choose the user whose profile you want to browse."""))
|
||||
documentation.append(_(u"""* Timeline: Lets you open a user's timeline by choosing the user in a dialog box. It is created when you press enter. If you try it with a user that has no tweets, the program will fail. If you try creating an already existing timeline the program will warn you and will not create it again."""))
|
||||
documentation.append(_(u"""* Timeline: opens up a dialogue box to choose whose user you want a timeline for. Create it by pressing enter. If you try it with a user that has no tweets, the program will fail. If you try creating an already existing timeline the program will warn you and will not create it again."""))
|
||||
documentation.append(_(u"""* View favourites: Opens a buffer where you can see what tweets have been favorited by a particular user."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""##### Buffer menu"""))
|
||||
documentation.append(_(u"""##### Buffer menu{#buffer}"""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
### add description for load previous items.
|
||||
documentation.append(_(u"""* Mute buffer: Mutes notifications of a particular buffer so you will not hear when new tweets arrive."""))
|
||||
documentation.append(_(u"""* autoread tweets for this buffer: When enabled, the screen reader or SAPI 5 (if enabled) will read the text of incoming tweets. Please note that this could get rather chatty if there are a lot of incoming tweets."""))
|
||||
documentation.append(_(u"""* Clear buffer: Deletes all items from the buffer."""))
|
||||
documentation.append(_(u"""* Remove buffer: dismiss the list you're on."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""##### Help menu"""))
|
||||
documentation.append(_(u"""##### Help menu {#help}"""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""* Documentation: opens up this file, where you can read some useful program concepts."""))
|
||||
documentation.append(_(u"""* What's new in this version?: opens up a document with the list of changes from the current version down to the first."""))
|
||||
documentation.append(_(u"""* Check for updates: every time you open the program it automatically checks for new versions. If there is any, it will ask you if you want to download it. If you accept, it will do so, after which it will install it and ask you to let it restart itself, which it does automatically. This item checks for new updates without having to restart the application."""))
|
||||
documentation.append(_(u"""* Report a bug: opens up a dialogue box to report a bug by filling a couple of fields. Pressing enter will send the report. If the operation doesn't succeed the program will show a warning."""))
|
||||
documentation.append(_(u"""* TW Blue's website: visit our [home page](http://twblue.es) where you can find all relevant information and downloads for TW Blue and become a part of the community."""))
|
||||
documentation.append(_(u"""* Check for updates: every time you open the program it automatically checks for new versions. If there are, it will ask you if you want to download it. If you accept, it will do so, after which it will install it and ask you to let it restart itself, which it does automatically. This item checks for new updates without having to restart the application."""))
|
||||
documentation.append(_(u"""* TW Blue's website: visit our [home page](http://twblue.com.mx) where you can find all relevant information and downloads for TW Blue and become a part of the community."""))
|
||||
documentation.append(_(u"""* Report a bug: opens up a dialogue box to report a bug by filling a couple of fields: the title and a short description of what happened. Pressing enter will send the report. If the operation doesn't succeed the program will show a warning."""))
|
||||
documentation.append(_(u"""* About TW Blue: shows the credits of the program."""))
|
||||
documentation.append(_(u"""...
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""## Contact"""))
|
||||
documentation.append(_(u"""### Invisible interface {#invisible_interface}"""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""If you press control-m, or if you choose hide window from the application menu, you will activate an interface that cannot be used in the usual way, because it is invisible."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""Every action on the invisible interface is done through keyboard shortcuts, even browsing lists. Eventually you may open dialogue boxes and these will be visible, but not the application's main window. Read the section on invisible interface shortcuts to know which ones you can use for the time being."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""### Keyboard shortcuts for the graphical interface {#shortcuts}"""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""Instead of using the buttons and menus, most actions can be carried out by pressing a key combination. The ones available at present are described below:"""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""* Enter: open a URL. If there are more than one you will get a list that will allow you to choose the one you want. On the friends or followers lists it will show details on the selected item."""))
|
||||
documentation.append(_(u"""* Control-enter: attempt to play audio from URL."""))
|
||||
documentation.append(_(u"""* F5: decrease sounds volume. It affects the program sounds as well as audio played from the program."""))
|
||||
documentation.append(_(u"""* F6: increase application sounds volume."""))
|
||||
documentation.append(_(u"""* Control-n: open new tweet dialogue."""))
|
||||
documentation.append(_(u"""* Control-m: hide window."""))
|
||||
documentation.append(_(u"""* Control-q: quit."""))
|
||||
documentation.append(_(u"""* Control-r: open reply tweet dialogue."""))
|
||||
documentation.append(_(u"""* Control-shift-r: Retweet."""))
|
||||
documentation.append(_(u"""* Control-d: send direct message."""))
|
||||
documentation.append(_(u"""* Control-f: mark as favourite."""))
|
||||
documentation.append(_(u"""* Control-shift-f: remove from favourites."""))
|
||||
documentation.append(_(u"""* Control-shift-v: view tweet."""))
|
||||
documentation.append(_(u"""* Control-s: follow a user."""))
|
||||
documentation.append(_(u"""* Control-shift-s: unfollow a user."""))
|
||||
documentation.append(_(u"""* Control-k: block a user."""))
|
||||
documentation.append(_(u"""* Control-shift-k: report as spam."""))
|
||||
documentation.append(_(u"""* Control-i: open user's timeline."""))
|
||||
documentation.append(_(u"""* Control-shift-i: remove timeline."""))
|
||||
documentation.append(_(u"""* Control-p: edit profile."""))
|
||||
documentation.append(_(u"""* Delete: remove tweet or direct message."""))
|
||||
documentation.append(_(u"""* Shift-delete: empty the buffer removing all the elements. This doesn't remove them from Twitter itself."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""### Keyboard shortcuts for the invisible interface {#invisible_shortcuts}"""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""These are the shortcuts you may use from the invisible interface. Bear in mind that when the graphical user interface is shown you may not use these. By "win" the left windows key is intended."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""* Control+win+up arrow: go up on the current list."""))
|
||||
documentation.append(_(u"""* Control+win+down arrow: go down on the current list."""))
|
||||
documentation.append(_(u"""* Control+win+left arrow: go to the previous tab."""))
|
||||
documentation.append(_(u"""* Control+win+right arrow: go to the next tab."""))
|
||||
documentation.append(_(u"""* Control+win+home: go to the first element on the list."""))
|
||||
documentation.append(_(u"""* Control+win+end: go to the last element on the list."""))
|
||||
documentation.append(_(u"""* Control+win+page down: move 20 elements down on the current list."""))
|
||||
documentation.append(_(u"""* Control+win+page up: move 20 elements up on the current list."""))
|
||||
documentation.append(_(u"""* Control+win+alt+up arrow: increase volume by 5%."""))
|
||||
documentation.append(_(u"""* control+win+alt+down arrow: decrease volume by 5%."""))
|
||||
documentation.append(_(u"""* Control+win+enter: open URL on the current tweet, or further information for a friend or follower."""))
|
||||
documentation.append(_(u"""* control+win+alt+enter: attempt to play audio."""))
|
||||
documentation.append(_(u"""* control+win+m: show the graphical interface, turning the invisible one off."""))
|
||||
documentation.append(_(u"""* Control+win+n: new tweet."""))
|
||||
documentation.append(_(u"""* Control+win+r: reply to tweet."""))
|
||||
documentation.append(_(u"""* Control+win+shift-r: retweet."""))
|
||||
documentation.append(_(u"""* Control+win+d: send direct message."""))
|
||||
documentation.append(_(u"""* Control+win+delete: remove a tweet or direct message."""))
|
||||
documentation.append(_(u"""* Control+win+shift+delete: empty the buffer removing all the elements. This doesn't remove them from Twitter itself."""))
|
||||
documentation.append(_(u"""* Win+alt+f: mark as favourite."""))
|
||||
documentation.append(_(u"""* Win+alt+shift+f: remove from favourites."""))
|
||||
documentation.append(_(u"""* Control+win+s: follow a user."""))
|
||||
documentation.append(_(u"""* Control+win+shift+s: unfollow a user."""))
|
||||
documentation.append(_(u"""* Control+win+alt+n: see user details."""))
|
||||
documentation.append(_(u"""* Control+win+v: show tweet on an edit box."""))
|
||||
documentation.append(_(u"""* Control+win+i: open user timeline."""))
|
||||
documentation.append(_(u"""* Control+win+shift+i: remove user timeline."""))
|
||||
documentation.append(_(u"""* Alt+win+p: edit profile."""))
|
||||
documentation.append(_(u"""* Control+win+c: Copy to clipboard."""))
|
||||
documentation.append(_(u"""* Control+win+space: Listen the current message."""))
|
||||
documentation.append(_(u"""* Control+win+a: Add to list."""))
|
||||
documentation.append(_(u"""* Control+win+shift+a: Remove from list."""))
|
||||
documentation.append(_(u"""* Control+Win+Shift+M: Mutes/unmutes the active buffer."""))
|
||||
documentation.append(_(u"""* Control+Win+E: toggles the automatic reading of incoming tweets in the active buffer."""))
|
||||
documentation.append(_(u"""* Control+Win+Shift+Up arrow: move up one tweet in the conversation."""))
|
||||
documentation.append(_(u"""* Control+Win+Shift+Down arrow: move down one tweet in the conversation."""))
|
||||
documentation.append(_(u"""* Win+Alt+M: Globally mute/unmute TW Blue."""))
|
||||
documentation.append(_(u"""* control+win+minus: Search on twitter."""))
|
||||
documentation.append(_(u"""* Control+win+f4: quit."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""## Lists {#lists}"""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""One of the most useful features of Twitter is the ability to create lists. Lists allow you to group users whose tweets you wish to see together instead of viewing their individual buffers. A common example of this would be if you follow multiple tech news accounts; it would be more convenient to have, for example, a "Tech News" list in which you can see tweets from these similar accounts together. A temporary buffer, such as what is created when you are viewing an individual person's timeline, is created and you can add/remove people from the list."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""In TW Blue, we have begun working on this feature little by little. It is still experimental but is in working condition. Below, we will explain how to configure lists."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""* First, you will need to open the lists manager which can be found under the application menu."""))
|
||||
documentation.append(_(u"""* In the lists manager, you will first see the lists you have created followed by those which you are a member. If you see no lists, it means that you have not created any and that you are not a part of any list."""))
|
||||
documentation.append(_(u"""* You will then see a group of buttons: Create a New List, Edit, Remove and Open in Buffer. Perhaps the last one is a bit less self-explanatory: it will open the list in a buffer similar to when opening someone's timeline. """))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""Once you have created a new list, the next step will be to add users to it. If you were to open it in a buffer right now, it would be empty and no tweets would show up in it. To add users, follow these steps:"""))
|
||||
documentation.append(_(u"""* While browsing your tweets, find a tweet from the user which you wish to add to a list. Next, press ctrl+win+A or select "Add to List" from the User menu."""))
|
||||
documentation.append(_(u"""* A dialog will then appear asking for the user which you wish to add. The name of the user whose tweet you just selected should already be in the box. Simply confirm that it is correct and press the "OK" button."""))
|
||||
documentation.append(_(u"""* Another dialog will appear showing all of your lists. Arrow to the one you want and press the "Add" button."""))
|
||||
documentation.append(_(u"""* To remove a user from a list, repeat the same process but press ctrl+win+shift+A and, from the dialog that appears, choose the list from which you wish to remove the selected user."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""## Reporting bugs from the web {#reporting}"""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""Note: if you're running the program you can also report a bug from it, by using the help menu item. This process only allows for two edit fields and takes care of the rest. These steps are described for those who can't run the program, don't have it opened at a given moment, or simply want to report from the web instead of using the integrated bug reporting system."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""All things under the sun (yes, this includes computer programs) are very far from being perfect, so often you may find unforeseen bugs in the application. But as our intent is to always improve you're free (what's more, it would be great if you did) to report the bugs you find on the program so they can be reviewed and eventually fixed"""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""In order to open the bug tracker's web, [follow this link](http://twblue.com.mx/errores/bug_report_page.php) It's a website with a form where you must fill several fields. Only three of them are really required (those marked with a star), but the more you can fill the better."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""Here are the different form fields and what you must enter on each. Remember only fields mark witha star are required:"""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""* Category: this field allows to choose what category to assign the bug to. You can choose general, if it's a program error, or documentation, if you have found a mistake in this manual or the changes list. This is a required field."""))
|
||||
documentation.append(_(u"""* Reproducibility: here you must indicate how easy or hard it is to reproduce the bug. Available options are unknown, not reproducible, not attempted (by default), random, sometimes, or always. Depending on whether you can reproduce the error or not, you should choose the one closest to your situation. If you're making a feature request, this field is irrelevant."""))
|
||||
documentation.append(_(u"""* Severity: here you choose how much it affects the program. Available options are functionality (choose this for a feature request), trivial, text, setting, minor, major, failure, or crash. Note the options go in increasing order. Choose the one which fits the situation best. If you're not sure which to choose you can leave it as it is."""))
|
||||
documentation.append(_(u"""* Priority: choose according to the importance of the bug or feature requested. Available options are none, low, normal, high, urgent, and immediate."""))
|
||||
documentation.append(_(u"""* Choose profile: here you can choose between 32 or 64 bit architecture and OS (Windows 7 for now). If they don't fit, you can fill the edit fields below with your specific information."""))
|
||||
documentation.append(_(u"""* Product version: choose the version of the program you're running in order to find out when the error was introduced. This field will contain a sorted list of the available versions. Although it's not required, it would help a lot in quickly finding the bug."""))
|
||||
documentation.append(_(u"""* Summary: a title for the bug, explaining in a few words what the problem is. It's a required text field."""))
|
||||
documentation.append(_(u"""* Description: this required field asks you to describe in more detail what happened to the program."""))
|
||||
documentation.append(_(u"""* Steps to reproduce: this field is used if you know how to cause the error. It's not required, but it would help a lot knowing how the program gets to the error in order to track it down."""))
|
||||
documentation.append(_(u"""* Additional information: if you have a comment or note to add, it can go here. It's not required."""))
|
||||
documentation.append(_(u"""* File attachment: you can attach the TW Blue.exe.log generated due to the bug. It is not required."""))
|
||||
documentation.append(_(u"""* Visibility: choose if you want the bug to be publically visible or private. By default it's public, and it's recommended to keep it that way."""))
|
||||
documentation.append(_(u"""* Send report: press the button to send the report and have it looked into."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""Many thanks for your participation in reporting bugs and trying out new functionality."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""## Contact {#contact}"""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""If what's explained in this document is not enough, if you want to collaborate in some other way, or if you simply want to get in touch with the application developer, follow the Twitter account [@tw_blue2](https://twitter.com/tw_blue2) or [@manuelcortez00.](https://twitter.com/manuelcortez00) You can also visit [our website](http://twblue.com.mx)"""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""---"""))
|
||||
documentation.append(_(u"""Copyright © 2013-2015. Manuel Cortéz"""))
|
||||
documentation.append(_(u"""Copyright © 2013-2014. Manuel Cortéz"""))
|
||||
|
@@ -1,23 +0,0 @@
|
||||
#include "api_keys.h"
|
||||
char *get_api_key(){
|
||||
return "key\0";
|
||||
}
|
||||
char *get_api_secret(){
|
||||
return "secret_key\0";
|
||||
}
|
||||
char *get_dropbox_api_key(){
|
||||
return "key\0";
|
||||
}
|
||||
char *get_dropbox_api_secret(){
|
||||
return "secret_key\0";
|
||||
}
|
||||
char *get_twishort_api_key(){
|
||||
return "key\0";
|
||||
}
|
||||
char *get_bts_user(){
|
||||
return "user\0";
|
||||
}
|
||||
char *get_bts_password(){
|
||||
return "pass\0";
|
||||
}
|
||||
|
@@ -1,12 +0,0 @@
|
||||
#ifndef _API_KEYS_H
|
||||
#define API_KEYS_H
|
||||
|
||||
char *get_api_key();
|
||||
char *get_api_secret();
|
||||
char *get_dropbox_api_key();
|
||||
char *get_dropbox_api_secret();
|
||||
char *get_twishort_api_key();
|
||||
char *get_bts_user();
|
||||
char *get_bts_password();
|
||||
|
||||
#endif
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 182 KiB After Width: | Height: | Size: 182 KiB |
Before Width: | Height: | Size: 379 B After Width: | Height: | Size: 379 B |
Before Width: | Height: | Size: 103 B After Width: | Height: | Size: 103 B |
Before Width: | Height: | Size: 119 B After Width: | Height: | Size: 119 B |
@@ -20,8 +20,8 @@ CommercialUse=true
|
||||
EULAVersion=2
|
||||
|
||||
[Version]
|
||||
PackageVersion=0.80.0.0
|
||||
DisplayVersion=0.80
|
||||
PackageVersion=0.51.0.0
|
||||
DisplayVersion=0.51
|
||||
|
||||
[Control]
|
||||
Icons=1
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 168 B After Width: | Height: | Size: 168 B |
Before Width: | Height: | Size: 269 B After Width: | Height: | Size: 269 B |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
@@ -1,89 +1,89 @@
|
||||
!include "MUI2.nsh"
|
||||
!include "LogicLib.nsh"
|
||||
!include "x64.nsh"
|
||||
CRCCheck on
|
||||
XPStyle on
|
||||
Name "TWBlue"
|
||||
OutFile "TWBlue_setup.exe"
|
||||
InstallDir "$PROGRAMFILES\twblue"
|
||||
InstallDirRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "InstallLocation"
|
||||
RequestExecutionLevel admin
|
||||
SetCompress auto
|
||||
SetCompressor /solid lzma
|
||||
SetDatablockOptimize on
|
||||
VIAddVersionKey ProductName "TWBlue"
|
||||
VIAddVersionKey LegalCopyright "Copyright 2015 Manuel Cortéz."
|
||||
VIAddVersionKey ProductVersion "0.80"
|
||||
VIAddVersionKey FileVersion "0.80"
|
||||
VIProductVersion "0.80.0.0"
|
||||
!insertmacro MUI_PAGE_WELCOME
|
||||
!define MUI_LICENSEPAGE_RADIOBUTTONS
|
||||
!insertmacro MUI_PAGE_LICENSE "license.txt"
|
||||
!insertmacro MUI_PAGE_DIRECTORY
|
||||
var StartMenuFolder
|
||||
!insertmacro MUI_PAGE_STARTMENU startmenu $StartMenuFolder
|
||||
!insertmacro MUI_PAGE_INSTFILES
|
||||
!define MUI_FINISHPAGE_LINK "Visit TWBlue website"
|
||||
!define MUI_FINISHPAGE_LINK_LOCATION "http://twblue.es"
|
||||
!define MUI_FINISHPAGE_RUN "$INSTDIR\TWBlue.exe"
|
||||
!define MUI_FINISHPAGE_RUN_PARAMETERS "-i"
|
||||
!insertmacro MUI_PAGE_FINISH
|
||||
!insertmacro MUI_UNPAGE_CONFIRM
|
||||
!insertmacro MUI_UNPAGE_INSTFILES
|
||||
!insertmacro MUI_LANGUAGE "English"
|
||||
!insertmacro MUI_LANGUAGE "French"
|
||||
!insertmacro MUI_LANGUAGE "Spanish"
|
||||
!insertmacro MUI_LANGUAGE "Italian"
|
||||
!insertmacro MUI_LANGUAGE "Finnish"
|
||||
!insertmacro MUI_LANGUAGE "Russian"
|
||||
!insertmacro MUI_LANGUAGE "PortugueseBR"
|
||||
!insertmacro MUI_LANGUAGE "Polish"
|
||||
!insertmacro MUI_LANGUAGE "German"
|
||||
!insertmacro MUI_LANGUAGE "Hungarian"
|
||||
!insertmacro MUI_LANGUAGE "Turkish"
|
||||
!insertmacro MUI_LANGUAGE "Arabic"
|
||||
!insertmacro MUI_LANGUAGE "Galician"
|
||||
!insertmacro MUI_LANGUAGE "Catalan"
|
||||
!insertmacro MUI_LANGUAGE "Basque"
|
||||
!insertmacro MUI_RESERVEFILE_LANGDLL
|
||||
Section
|
||||
SetShellVarContext All
|
||||
SetOutPath "$INSTDIR"
|
||||
${If} ${RunningX64}
|
||||
File /r TWBlue64\*
|
||||
${Else}
|
||||
File /r TWBlue\*
|
||||
${EndIf}
|
||||
CreateShortCut "$DESKTOP\TWBlue.lnk" "$INSTDIR\TWBlue.exe" "-i"
|
||||
!insertmacro MUI_STARTMENU_WRITE_BEGIN startmenu
|
||||
CreateDirectory "$SMPROGRAMS\$StartMenuFolder"
|
||||
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\TWBlue.lnk" "$INSTDIR\TWBlue.exe" "-i"
|
||||
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\TWBlue on the web.lnk" "http://twblue.es"
|
||||
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
|
||||
!insertmacro MUI_STARTMENU_WRITE_END
|
||||
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "DisplayName" "TWBlue"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "UninstallString" '"$INSTDIR\uninstall.exe"'
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall" "InstallLocation" $INSTDIR
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall" "Publisher" "Manuel Cortéz"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "DisplayVersion" "0.80"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "URLInfoAbout" "http://twblue.es"
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "VersionMajor" 0
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "VersionMinor" 80
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "NoModify" 1
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "NoRepair" 1
|
||||
SectionEnd
|
||||
Section "Uninstall"
|
||||
SetShellVarContext All
|
||||
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue"
|
||||
RMDir /r /REBOOTOK $INSTDIR
|
||||
Delete "$DESKTOP\TWBlue.lnk"
|
||||
!insertmacro MUI_STARTMENU_GETFOLDER startmenu $StartMenuFolder
|
||||
RMDir /r "$SMPROGRAMS\$StartMenuFolder"
|
||||
SectionEnd
|
||||
Function .onInit
|
||||
${If} ${RunningX64}
|
||||
StrCpy $instdir "$programfiles64\twblue"
|
||||
${EndIf}
|
||||
!insertmacro MUI_LANGDLL_DISPLAY
|
||||
FunctionEnd
|
||||
!include "MUI2.nsh"
|
||||
!include "LogicLib.nsh"
|
||||
!include "x64.nsh"
|
||||
CRCCheck on
|
||||
XPStyle on
|
||||
Name "TW Blue"
|
||||
OutFile "TWBlue_setup.exe"
|
||||
InstallDir "$PROGRAMFILES\twblue"
|
||||
InstallDirRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "InstallLocation"
|
||||
RequestExecutionLevel admin
|
||||
SetCompress auto
|
||||
SetCompressor /solid lzma
|
||||
SetDatablockOptimize on
|
||||
VIAddVersionKey ProductName "TW Blue"
|
||||
VIAddVersionKey LegalCopyright "Copyright 2014 Manuel Cortez."
|
||||
VIAddVersionKey ProductVersion "0.51"
|
||||
VIAddVersionKey FileVersion "0.51"
|
||||
VIProductVersion "0.51.0.0"
|
||||
!insertmacro MUI_PAGE_WELCOME
|
||||
!define MUI_LICENSEPAGE_RADIOBUTTONS
|
||||
!insertmacro MUI_PAGE_LICENSE "license.txt"
|
||||
!insertmacro MUI_PAGE_DIRECTORY
|
||||
var StartMenuFolder
|
||||
!insertmacro MUI_PAGE_STARTMENU startmenu $StartMenuFolder
|
||||
!insertmacro MUI_PAGE_INSTFILES
|
||||
!define MUI_FINISHPAGE_LINK "Visit TW Blue website"
|
||||
!define MUI_FINISHPAGE_LINK_LOCATION "http://twblue.es"
|
||||
!define MUI_FINISHPAGE_RUN "$INSTDIR\TWBlue.exe"
|
||||
!define MUI_FINISHPAGE_RUN_PARAMETERS "-i"
|
||||
!insertmacro MUI_PAGE_FINISH
|
||||
!insertmacro MUI_UNPAGE_CONFIRM
|
||||
!insertmacro MUI_UNPAGE_INSTFILES
|
||||
!insertmacro MUI_LANGUAGE "English"
|
||||
!insertmacro MUI_LANGUAGE "French"
|
||||
!insertmacro MUI_LANGUAGE "Spanish"
|
||||
!insertmacro MUI_LANGUAGE "Italian"
|
||||
!insertmacro MUI_LANGUAGE "Finnish"
|
||||
!insertmacro MUI_LANGUAGE "Russian"
|
||||
!insertmacro MUI_LANGUAGE "PortugueseBR"
|
||||
!insertmacro MUI_LANGUAGE "Polish"
|
||||
!insertmacro MUI_LANGUAGE "German"
|
||||
!insertmacro MUI_LANGUAGE "Hungarian"
|
||||
!insertmacro MUI_LANGUAGE "Turkish"
|
||||
!insertmacro MUI_LANGUAGE "Arabic"
|
||||
!insertmacro MUI_LANGUAGE "Galician"
|
||||
!insertmacro MUI_LANGUAGE "Catalan"
|
||||
!insertmacro MUI_LANGUAGE "Basque"
|
||||
!insertmacro MUI_RESERVEFILE_LANGDLL
|
||||
Section
|
||||
SetShellVarContext All
|
||||
SetOutPath "$INSTDIR"
|
||||
${If} ${RunningX64}
|
||||
File /r TWBlue64\*
|
||||
${Else}
|
||||
File /r TWBlue\*
|
||||
${EndIf}
|
||||
CreateShortCut "$DESKTOP\TW Blue.lnk" "$INSTDIR\TWBlue.exe" "-i"
|
||||
!insertmacro MUI_STARTMENU_WRITE_BEGIN startmenu
|
||||
CreateDirectory "$SMPROGRAMS\$StartMenuFolder"
|
||||
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\TW Blue.lnk" "$INSTDIR\TWBlue.exe" "-i"
|
||||
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\TW Blue on the web.lnk" "http://twblue.es"
|
||||
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
|
||||
!insertmacro MUI_STARTMENU_WRITE_END
|
||||
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "DisplayName" "TW Blue"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "UninstallString" '"$INSTDIR\uninstall.exe"'
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall" "InstallLocation" $INSTDIR
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall" "Publisher" "Manuel Cortez"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "DisplayVersion" "0.51"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "URLInfoAbout" "http://twblue.es"
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "VersionMajor" 0
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "VersionMinor" 51
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "NoModify" 1
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "NoRepair" 1
|
||||
SectionEnd
|
||||
Section "Uninstall"
|
||||
SetShellVarContext All
|
||||
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue"
|
||||
RMDir /r /REBOOTOK $INSTDIR
|
||||
Delete "$DESKTOP\TW Blue.lnk"
|
||||
!insertmacro MUI_STARTMENU_GETFOLDER startmenu $StartMenuFolder
|
||||
RMDir /r "$SMPROGRAMS\$StartMenuFolder"
|
||||
SectionEnd
|
||||
Function .onInit
|
||||
${If} ${RunningX64}
|
||||
StrCpy $instdir "$programfiles64\twblue"
|
||||
${EndIf}
|
||||
!insertmacro MUI_LANGDLL_DISPLAY
|
||||
FunctionEnd
|
||||
|
@@ -5,32 +5,40 @@ user_name = string(default="")
|
||||
ignored_clients = list(default=list())
|
||||
|
||||
[general]
|
||||
language = string(default="system")
|
||||
relative_times = boolean(default=True)
|
||||
hide_gui = boolean(default=False)
|
||||
voice_enabled = boolean(default=False)
|
||||
max_api_calls = integer(default=1)
|
||||
max_tweets_per_call = integer(default=100)
|
||||
reverse_timelines = boolean(default=False)
|
||||
time_to_check_streams = integer(default=30)
|
||||
announce_stream_status = boolean(default=True)
|
||||
retweet_mode = string(default="ask")
|
||||
persist_size = integer(default=0)
|
||||
buffer_order = list(default=list('home','mentions','dm','sent_dm','sent_tweets','favorites','followers','friends','blocks','muted','events'))
|
||||
ask_at_exit = boolean(default=True)
|
||||
use_invisible_keyboard_shorcuts = boolean(default=False)
|
||||
|
||||
[sound]
|
||||
volume = float(default=1.0)
|
||||
input_device = string(default="Default")
|
||||
output_device = string(default="Default")
|
||||
session_mute = boolean(default=False)
|
||||
current_soundpack = string(default="default")
|
||||
global_mute = boolean(default=False)
|
||||
sndup_api_key = string(default="")
|
||||
|
||||
[other_buffers]
|
||||
show_friends = boolean(default=True)
|
||||
show_followers = boolean(default=True)
|
||||
show_favourites = boolean(default=True)
|
||||
show_events = boolean(default=True)
|
||||
show_blocks = boolean(default=False)
|
||||
show_muted_users = boolean(default=False)
|
||||
timelines = list(default=list())
|
||||
tweet_searches = list(default=list())
|
||||
lists = list(default=list())
|
||||
favourites_timelines = list(default=list())
|
||||
trending_topic_buffers = list(default=list())
|
||||
muted_buffers = list(default=list())
|
||||
autoread_buffers = list(default=list(mentions, direct_messages, events))
|
||||
autoread_buffers = list(default=list())
|
||||
|
||||
[mysc]
|
||||
spelling_language = string(default="")
|
||||
@@ -40,3 +48,48 @@ save_friends_in_autocompletion_db = boolean(default=False)
|
||||
[services]
|
||||
dropbox_token=string(default="")
|
||||
|
||||
[keymap]
|
||||
up = string(default="control+win+up")
|
||||
down = string(default="control+win+down")
|
||||
left = string(default="control+win+left")
|
||||
right = string(default="control+win+right")
|
||||
conversation_up = string(default="control+win+shift+up")
|
||||
conversation_down = string(default="control+win+shift+down")
|
||||
show_hide = string(default="control+win+m")
|
||||
compose = string(default="control+win+n")
|
||||
reply = string(default="control+win+r")
|
||||
retweet = string(default="control+win+shift+r")
|
||||
dm = string(default="control+win+d")
|
||||
fav = string(default="alt+win+f")
|
||||
unfav = string(default="alt+shift+win+f")
|
||||
action = string(default="control+win+s")
|
||||
details = string(default="control+win+alt+n")
|
||||
view = string(default="control+win+v")
|
||||
close = string(default="control+win+f4")
|
||||
open_timeline = string(default="control+win+i")
|
||||
delete_buffer = string(default="control+win+shift+i")
|
||||
url = string(default="control+win+return")
|
||||
audio = string(default="control+win+alt+return")
|
||||
volume_up = string(default="control+win+alt+up")
|
||||
volume_down = string(default="control+win+alt+down")
|
||||
go_home = string(default="control+win+home")
|
||||
go_end = string(default="control+win+end")
|
||||
go_page_up = string(default="control+win+pageup")
|
||||
go_page_down = string(default="control+win+pagedown")
|
||||
update_profile = string(default="alt+win+p")
|
||||
delete = string(default="control+win+delete")
|
||||
clear_list = string(default="control+win+shift+delete")
|
||||
repeat_item = string(default="control+win+space")
|
||||
copy_to_clipboard = string(default="control+win+c")
|
||||
add_to_list = string(default="control+win+a")
|
||||
remove_from_list = string(default="control+win+shift+a")
|
||||
toggle_mute = string(default="control+win+shift+m")
|
||||
toggle_global_mute = string(default="alt+win+m")
|
||||
toggle_autoread = string(default="control+win+e")
|
||||
search = string(default="control+win+-")
|
||||
edit_keystrokes = string(default="control+win+k")
|
||||
view_user_lists = string(default="control+win+l")
|
||||
get_more_items = string(default="alt+win+pageup")
|
||||
reverse_geocode = string(default="control+win+g")
|
||||
view_reverse_geocode = string(default="control+win+shift+g")
|
||||
get_trending_topics = string(default="control+win+t")
|
@@ -21,7 +21,7 @@ class SAPI5(Output):
|
||||
priority = 101
|
||||
|
||||
def __init__(self):
|
||||
if config.app["app-settings"]["voice_enabled"] == False: raise OutputError
|
||||
if config.main["general"]["voice_enabled"] == False: raise OutputError
|
||||
try:
|
||||
self.object = load_com("SAPI.SPVoice")
|
||||
self._voices = self._available_voices()
|
||||
|
@@ -1,9 +1,9 @@
|
||||
from base import Output, OutputError
|
||||
import atexit
|
||||
import application
|
||||
|
||||
class SpeechDispatcher(Output):
|
||||
"""Supports speech dispatcher on Linux.
|
||||
Note that this module will use the configuration of speech dispatcher, the user will need to configure the voice, language, punctuation and rate before using this module.
|
||||
Note that it will take the configuration from the speech dispatcher, the user will need configure voice, language, punctuation and rate before use this module.
|
||||
"""
|
||||
name = 'SpeechDispatcher'
|
||||
|
||||
@@ -11,7 +11,7 @@ class SpeechDispatcher(Output):
|
||||
super(SpeechDispatcher, self).__init__(*args, **kwargs)
|
||||
try:
|
||||
import speechd
|
||||
self.spd = speechd.SSIPClient(application.name)
|
||||
self.spd = speechd.SSIPClient("TWBlue")
|
||||
except ImportError:
|
||||
raise OutputError
|
||||
atexit.register(self.on_exit_event)
|
||||
|
@@ -1,21 +0,0 @@
|
||||
[sessions]
|
||||
current_session = string(default="")
|
||||
sessions = list(default=list())
|
||||
ignored_sessions = list(default=list())
|
||||
|
||||
[app-settings]
|
||||
language = string(default="system")
|
||||
hide_gui = boolean(default=False)
|
||||
voice_enabled = boolean(default=False)
|
||||
ask_at_exit = boolean(default=True)
|
||||
use_invisible_keyboard_shorcuts = boolean(default=True)
|
||||
play_ready_sound = boolean(default=True)
|
||||
speak_ready_msg = boolean(default=True)
|
||||
log_level = string(default="error")
|
||||
load_keymap = string(default="default.keymap")
|
||||
|
||||
[proxy]
|
||||
server = string(default="")
|
||||
port = string(default="")
|
||||
user = string(default="")
|
||||
password = string(default="")
|
@@ -1,16 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
name = 'TWBlue'
|
||||
snapshot = True
|
||||
snapshot = False
|
||||
if snapshot == False:
|
||||
version = "0.80"
|
||||
update_url = 'http://twblue.es/updates/twblue_ngen.json'
|
||||
version = "0.51"
|
||||
update_url = 'http://twblue.es/updates/tw_blue.json'
|
||||
else:
|
||||
version = "9.4"
|
||||
update_url = 'http://twblue.es/updates/snapshots_ngen.json'
|
||||
author = u"Manuel Cortéz, Bill Dengler"
|
||||
version = "7"
|
||||
update_url = 'http://twblue.es/updates/snapshots.json'
|
||||
author = u"Manuel Cortéz"
|
||||
authorEmail = "manuel@manuelcortez.net"
|
||||
copyright = u"Copyright (C) 2015, Technow S.L. \nCopyright (C) 2015, Bill Dengler\nCopyright (C) 2013-2015, Manuel cortéz."
|
||||
description = unicode(name+" is an app designed to use Twitter simply and efficiently while using minimal system resources. This app provides access to most Twitter features.")
|
||||
translators = [u"Bryner Villalobos, Bill Dengler (English)", u"Mohammed Al Shara (Arabic)", u"Joan Rabat, Juan Carlos Rivilla (Catalan)", u"Manuel cortéz (Spanish)", u"Sukil Etxenike Arizaleta (Basque)", u"Jani Kinnunen (finnish)", u"Rémy Ruiz (French)", u"Alba Quinteiro (Galician)", u"Steffen Schultz (German)", u"Robert Osztolykan (Hungarian)", u"Paweł Masarczyk (Polish)", u"Odenilton Júnior Santos (Portuguese)", u"Alexander Jaszyn (Russian)", u"Burak (Turkish)"]
|
||||
copyright = u"copyright (C) 2013-2015, Manuel cortéz"
|
||||
description = u"TW Blue is an app designed to use Twitter in a simple and fast way and avoiding, as far as possible, the consumtion of excessive resources of the machine where it’s running. With this app you’ll have access to most twitter features."
|
||||
translators = [u"Bryner Villalobos (English)", u"Mohammed Al Shara (Arabic)", u"Joan Rabat, Juan Carlos Rivilla (Catalan)", u"Manuel cortéz (Spanish)", u"Sukil Etxenike Arizaleta (Basque)", u"Jani Kinnunen (finnish)", u"Rémy Ruiz (French)", u"Alba Quinteiro (Galician)", u"Steffen Schultz (German)", u"Robert Osztolykan (Hungarian)", u"Paweł Masarczyk (Polish)", u"Odenilton Júnior Santos (Portuguese)", u"Alexander Jaszyn (Russian)", u"Burak (Turkish)"]
|
||||
url = u"http://twblue.es"
|
||||
report_bugs_url = "http://twblue.es/bugs/api/soap/mantisconnect.php?wsdl"
|
||||
report_bugs_url = "http://twblue.es/bugs/api/soap/mantisconnect.php?wsdl"
|
||||
|
||||
# Tokens
|
||||
app_key = '8pDLbyOW3saYnvSZ4uLFg'
|
||||
app_secret = 'YsgdrzY9B4yyYvYsyee78rKI3GshjHpenVS9LnFJXY'
|
@@ -10,6 +10,14 @@ def convert_audioboom(url):
|
||||
audio_id = url.split('.com/')[-1]
|
||||
return 'https://audioboom.com/%s.mp3' % audio_id
|
||||
|
||||
@matches_url('http://q-audio.net')
|
||||
def convert_q_audio(url):
|
||||
result = re.match("^https?://q-audio.net/(i|d|download)/(?P<audio_id>[a-z0-9]+/?)$", url, re.I)
|
||||
if not result or result.group("audio_id") is None:
|
||||
raise TypeError('%r is not a valid URL' % url)
|
||||
audio_id = result.group("audio_id")
|
||||
return 'http://q-audio.net/download/%s' % audio_id
|
||||
|
||||
@matches_url ('http://soundcloud.com/')
|
||||
def convert_soundcloud (url):
|
||||
client_id = "df8113ca95c157b6c9731f54b105b473"
|
||||
|
@@ -1,18 +1,16 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import argparse
|
||||
import paths
|
||||
import logging
|
||||
import application
|
||||
log = logging.getLogger("commandlineLauncher")
|
||||
|
||||
parser = argparse.ArgumentParser(description=application.name+" command line launcher")
|
||||
parser = argparse.ArgumentParser(description="TW Blue command line launcher")
|
||||
group = parser.add_mutually_exclusive_group()
|
||||
group.add_argument("-p", "--portable", help="Use " + application.name + " as a portable application.", action="store_true", default=True)
|
||||
group.add_argument("-i", "--installed", help="Use " + application.name + " as an installed application. Config files will be saved in the user data directory", action="store_true")
|
||||
parser.add_argument("-d", "--data-directory", action="store", dest="directory", help="Specifies the directory where " + application.name + " saves userdata.")
|
||||
group.add_argument("-p", "--portable", help="Use TW Blue as a portable aplication", action="store_true", default=True)
|
||||
group.add_argument("-i", "--installed", help="Use TW Blue as an installed application. Config files will be saved on the user data directory", action="store_true")
|
||||
parser.add_argument("-d", "--data-directory", action="store", dest="directory", help="Specifies the directory where TW Blue saves the data files")
|
||||
args = parser.parse_args()
|
||||
log.debug("Starting " + application.name + " with the following arguments: installed = %s, portable = %s and directory = %s" % (args.installed, args.portable, args.directory))
|
||||
if args.installed == True: paths.mode = "installed"
|
||||
if args.installed == True:
|
||||
paths.mode = "installed"
|
||||
elif args.portable == True:
|
||||
paths.mode = "portable"
|
||||
if args.directory != None: paths.directory = args.directory
|
||||
|
||||
|
@@ -1,19 +1,16 @@
|
||||
# -*- coding: cp1252 -*-
|
||||
import config_utils
|
||||
from config_utils import Configuration, ConfigurationResetException
|
||||
import paths
|
||||
import logging
|
||||
|
||||
log = logging.getLogger("config")
|
||||
MAINFILE = "session.conf"
|
||||
MAINSPEC = "Conf.defaults"
|
||||
|
||||
MAINFILE = "twblue.conf"
|
||||
MAINSPEC = "app-configuration.defaults"
|
||||
main = None
|
||||
|
||||
app = None
|
||||
keymap=None
|
||||
def setup ():
|
||||
global app
|
||||
log.debug("Loading global app settings...")
|
||||
app = config_utils.load_config(paths.config_path(MAINFILE), paths.app_path(MAINSPEC))
|
||||
log.debug("Loading keymap...")
|
||||
global keymap
|
||||
keymap = config_utils.load_config(paths.app_path("keymaps/"+app['app-settings']['load_keymap']), paths.app_path('keymaps/base.template'))
|
||||
global main
|
||||
try:
|
||||
main = Configuration(paths.config_path(MAINFILE), paths.app_path(MAINSPEC))
|
||||
except ConfigurationResetException:
|
||||
pass
|
||||
# return main
|
@@ -1,73 +1,50 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from UserDict import UserDict
|
||||
from configobj import ConfigObj, ParseError
|
||||
from validate import Validator, ValidateError
|
||||
from validate import Validator, VdtValueError
|
||||
import os
|
||||
import string
|
||||
class ConfigLoadError(Exception): pass
|
||||
|
||||
def load_config(config_path, configspec_path=None, *args, **kwargs):
|
||||
if os.path.exists(config_path):
|
||||
clean_config(config_path)
|
||||
spec = ConfigObj(configspec_path, encoding='UTF8', list_values=False, _inspec=True)
|
||||
try:
|
||||
config = ConfigObj(infile=config_path, configspec=spec, create_empty=True, encoding='UTF8', *args, **kwargs)
|
||||
except ParseError:
|
||||
raise ConfigLoadError("Unable to load %r" % config_path)
|
||||
validator = Validator()
|
||||
validated = config.validate(validator, copy=True)
|
||||
if validated == True:
|
||||
config.write()
|
||||
return config
|
||||
"""We're using the configobj python package
|
||||
from http://www.voidspace.org.uk/python/configobj.html """
|
||||
|
||||
def is_blank(arg):
|
||||
"Check if a line is blank."
|
||||
for c in arg:
|
||||
if c not in string.whitespace:
|
||||
return False
|
||||
return True
|
||||
def get_keys(path):
|
||||
"Gets the keys of a configobj config file."
|
||||
res=[]
|
||||
fin=open(path)
|
||||
for line in fin:
|
||||
if not is_blank(line):
|
||||
res.append(line[0:line.find('=')].strip())
|
||||
fin.close()
|
||||
return res
|
||||
class ConfigurationResetException(Exception):
|
||||
pass
|
||||
|
||||
def hist(keys):
|
||||
"Generates a histogram of an iterable."
|
||||
res={}
|
||||
for k in keys:
|
||||
res[k]=res.setdefault(k,0)+1
|
||||
return res
|
||||
|
||||
def find_problems(hist):
|
||||
"Takes a histogram and returns a list of items occurring more than once."
|
||||
res=[]
|
||||
for k,v in hist.items():
|
||||
if v>1:
|
||||
res.append(k)
|
||||
return res
|
||||
class Configuration (UserDict):
|
||||
|
||||
def clean_config(path):
|
||||
"Cleans a config file. If duplicate values are found, delete all of them and just use the default."
|
||||
orig=[]
|
||||
cleaned=[]
|
||||
fin=open(path)
|
||||
for line in fin:
|
||||
orig.append(line)
|
||||
fin.close()
|
||||
for p in find_problems(hist(get_keys(path))):
|
||||
for o in orig:
|
||||
o.strip()
|
||||
if p not in o:
|
||||
cleaned.append(o)
|
||||
if len(cleaned) != 0:
|
||||
cam=open(path,'w')
|
||||
for c in cleaned:
|
||||
cam.write(c)
|
||||
cam.close()
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
def __init__ (self, file=None, spec=None, *args, **kwargs):
|
||||
self.file = file
|
||||
self.spec = spec
|
||||
self.validator = Validator()
|
||||
self.setup_config(file=file, spec=spec)
|
||||
self.validated = self.config.validate(self.validator, copy=True)
|
||||
if self.validated:
|
||||
self.write()
|
||||
UserDict.__init__(self, self.config)
|
||||
|
||||
def setup_config (self, file, spec):
|
||||
#The default way -- load from a file
|
||||
spec = ConfigObj(spec, list_values=False, encoding="utf-8")
|
||||
try:
|
||||
self.config = ConfigObj(infile=file, configspec=spec, create_empty=True, stringify=True, encoding="utf-8")
|
||||
except ParseError:
|
||||
os.remove(file)
|
||||
self.config = ConfigObj(infile=file, configspec=spec, create_empty=True, stringify=True)
|
||||
raise ConfigurationResetException
|
||||
def __getitem__ (self, *args, **kwargs):
|
||||
return dict(self.config).__getitem__(*args, **kwargs)
|
||||
|
||||
def __setitem__ (self, *args, **kwargs):
|
||||
self.config.__setitem__(*args, **kwargs)
|
||||
UserDict.__setitem__(self, *args, **kwargs)
|
||||
|
||||
def write (self):
|
||||
if hasattr(self.config, 'write'):
|
||||
self.config.write()
|
||||
|
||||
class SessionConfiguration (Configuration):
|
||||
def setup_config (self, file, spec):
|
||||
#No infile required.
|
||||
spec = ConfigObj(spec, list_values=False)
|
||||
self.config = ConfigObj(configspec=spec, stringify=True)
|
||||
|
@@ -1,863 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import platform
|
||||
if platform.system() == "Windows":
|
||||
import wx
|
||||
from wxUI import buffers, dialogs, commonMessageDialogs
|
||||
import user
|
||||
elif platform.system() == "Linux":
|
||||
from gi.repository import Gtk
|
||||
from gtkUI import buffers, dialogs, commonMessageDialogs
|
||||
import messages
|
||||
import widgetUtils
|
||||
import arrow
|
||||
import webbrowser
|
||||
import output
|
||||
import config
|
||||
import sound
|
||||
import languageHandler
|
||||
import logging
|
||||
from twitter import compose, utils
|
||||
from mysc.thread_utils import call_threaded
|
||||
from twython import TwythonError
|
||||
from pubsub import pub
|
||||
from long_tweets import twishort, tweets
|
||||
|
||||
log = logging.getLogger("controller.buffers")
|
||||
|
||||
def _tweets_exist(function):
|
||||
""" A decorator to execute a function only if the selected buffer contains at least one item."""
|
||||
def function_(self, *args, **kwargs):
|
||||
if self.buffer.list.get_count() > 0:
|
||||
function(self, *args, **kwargs)
|
||||
return function_
|
||||
|
||||
class bufferController(object):
|
||||
def __init__(self, parent=None, function=None, session=None, *args, **kwargs):
|
||||
super(bufferController, self).__init__()
|
||||
self.function = function
|
||||
self.compose_function = None
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
self.buffer = None
|
||||
self.account = ""
|
||||
self.needs_init = True
|
||||
self.invisible = False # False if the buffer will be ignored on the invisible interface.
|
||||
|
||||
def clear_list(self): pass
|
||||
|
||||
|
||||
def get_event(self, ev):
|
||||
if ev.GetKeyCode() == wx.WXK_RETURN and ev.ControlDown(): event = "url"
|
||||
elif ev.GetKeyCode() == wx.WXK_RETURN: event = "interact"
|
||||
elif ev.GetKeyCode() == wx.WXK_F5: event = "volume_down"
|
||||
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: event = "destroy_status"
|
||||
else:
|
||||
event = None
|
||||
ev.Skip()
|
||||
if event != None:
|
||||
try:
|
||||
getattr(self, event)()
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def volume_down(self):
|
||||
if self.session.settings["sound"]["volume"] > 0.0:
|
||||
if self.session.settings["sound"]["volume"] <= 0.05:
|
||||
self.session.settings["sound"]["volume"] = 0.0
|
||||
else:
|
||||
self.session.settings["sound"]["volume"] -=0.05
|
||||
if hasattr(sound.URLPlayer, "stream"):
|
||||
sound.URLPlayer.stream.volume = self.session.settings["sound"]["volume"]
|
||||
self.session.sound.play("volume_changed.ogg")
|
||||
|
||||
def volume_up(self):
|
||||
if self.session.settings["sound"]["volume"] < 1.0:
|
||||
if self.session.settings["sound"]["volume"] >= 0.95:
|
||||
self.session.settings["sound"]["volume"] = 1.0
|
||||
else:
|
||||
self.session.settings["sound"]["volume"] +=0.05
|
||||
if hasattr(sound.URLPlayer, "stream"):
|
||||
sound.URLPlayer.stream.volume = self.session.settings["sound"]["volume"]
|
||||
self.session.sound.play("volume_changed.ogg")
|
||||
|
||||
def interact(self):
|
||||
if hasattr(sound.URLPlayer,'stream'):
|
||||
return sound.URLPlayer.stop_audio(delete=True)
|
||||
tweet = self.get_tweet()
|
||||
url=None
|
||||
urls = utils.find_urls(tweet)
|
||||
if len(urls) == 1:
|
||||
url=urls[0]
|
||||
elif len(urls) > 1:
|
||||
urls_list = dialogs.urlList.urlList()
|
||||
urls_list.populate_list(urls)
|
||||
if urls_list.get_response() == widgetUtils.OK:
|
||||
url=urls_list.get_string()
|
||||
if hasattr(urls_list, "destroy"): urls_list.destroy()
|
||||
if url != None:
|
||||
output.speak(_(u"Opening media..."), True)
|
||||
if sound.URLPlayer.is_playable(url=url, play=True, volume=self.session.settings["sound"]["volume"]) == False:
|
||||
return webbrowser.open_new_tab(url)
|
||||
# else:
|
||||
# output.speak(_(u"Not actionable."), True)
|
||||
# self.session.sound.play("error.ogg")
|
||||
|
||||
def start_stream(self):
|
||||
pass
|
||||
|
||||
def get_more_items(self):
|
||||
output.speak(_(u"This action is not supported for this buffer"), True)
|
||||
|
||||
def put_items_on_list(self, items):
|
||||
pass
|
||||
|
||||
def remove_buffer(self):
|
||||
return False
|
||||
|
||||
def remove_item(self, item):
|
||||
self.buffer.list.remove_item(item)
|
||||
|
||||
def bind_events(self):
|
||||
pass
|
||||
|
||||
def get_object(self):
|
||||
return self.buffer
|
||||
|
||||
def get_message(self):
|
||||
pass
|
||||
|
||||
def set_list_position(self, reversed=False):
|
||||
if reversed == False:
|
||||
self.buffer.list.select_item(-1)
|
||||
else:
|
||||
self.buffer.list.select_item(0)
|
||||
|
||||
def reply(self):
|
||||
pass
|
||||
|
||||
def direct_message(self):
|
||||
pass
|
||||
|
||||
def retweet(self):
|
||||
pass
|
||||
|
||||
def destroy_status(self):
|
||||
pass
|
||||
|
||||
def post_tweet(self, *args, **kwargs):
|
||||
title = _(u"Tweet")
|
||||
caption = _(u"Write the tweet here")
|
||||
tweet = messages.tweet(self.session, title, caption, "")
|
||||
if tweet.message.get_response() == widgetUtils.OK:
|
||||
text = tweet.message.get_text()
|
||||
if tweet.image == None:
|
||||
call_threaded(self.session.api_call, call_name="update_status", status=text)
|
||||
else:
|
||||
call_threaded(self.session.api_call, call_name="update_status_with_media", status=text, media=tweet.image)
|
||||
if hasattr(tweet.message, "destroy"): tweet.message.destroy()
|
||||
|
||||
class accountPanel(bufferController):
|
||||
def __init__(self, parent, name, account, account_id):
|
||||
super(accountPanel, self).__init__(parent, None, name)
|
||||
log.debug("Initializing buffer %s, account %s" % (name, account,))
|
||||
self.buffer = buffers.accountPanel(parent, name)
|
||||
self.type = self.buffer.type
|
||||
self.compose_function = None
|
||||
self.session = None
|
||||
self.needs_init = False
|
||||
self.account = account
|
||||
self.buffer.account = account
|
||||
self.name = name
|
||||
self.account_id = account_id
|
||||
|
||||
def setup_account(self):
|
||||
widgetUtils.connect_event(self.buffer, widgetUtils.CHECKBOX, self.autostart, menuitem=self.buffer.autostart_account)
|
||||
if self.account_id in config.app["sessions"]["ignored_sessions"]:
|
||||
self.buffer.change_autostart(False)
|
||||
else:
|
||||
self.buffer.change_autostart(True)
|
||||
if not hasattr(self, "logged"):
|
||||
self.buffer.change_login(login=False)
|
||||
widgetUtils.connect_event(self.buffer.login, widgetUtils.BUTTON_PRESSED, self.logout)
|
||||
else:
|
||||
self.buffer.change_login(login=True)
|
||||
widgetUtils.connect_event(self.buffer.login, widgetUtils.BUTTON_PRESSED, self.login)
|
||||
|
||||
def login(self, *args, **kwargs):
|
||||
del self.logged
|
||||
self.setup_account()
|
||||
pub.sendMessage("login", session_id=self.account_id)
|
||||
|
||||
def logout(self, *args, **kwargs):
|
||||
self.logged = False
|
||||
self.setup_account()
|
||||
pub.sendMessage("logout", session_id=self.account_id)
|
||||
|
||||
def autostart(self, *args, **kwargs):
|
||||
if self.account_id in config.app["sessions"]["ignored_sessions"]:
|
||||
self.buffer.change_autostart(True)
|
||||
config.app["sessions"]["ignored_sessions"].remove(self.account_id)
|
||||
else:
|
||||
self.buffer.change_autostart(False)
|
||||
config.app["sessions"]["ignored_sessions"].append(self.account_id)
|
||||
|
||||
class emptyPanel(bufferController):
|
||||
def __init__(self, parent, name, account):
|
||||
super(emptyPanel, self).__init__(parent, None, name)
|
||||
log.debug("Initializing buffer %s, account %s" % (name, account,))
|
||||
self.buffer = buffers.emptyPanel(parent, name)
|
||||
self.type = self.buffer.type
|
||||
self.compose_function = None
|
||||
self.account = account
|
||||
self.buffer.account = account
|
||||
self.name = name
|
||||
self.session = None
|
||||
self.needs_init = True
|
||||
|
||||
class baseBufferController(bufferController):
|
||||
def __init__(self, parent, function, name, sessionObject, account, sound=None, bufferType=None, *args, **kwargs):
|
||||
super(baseBufferController, self).__init__(parent, function, *args, **kwargs)
|
||||
log.debug("Initializing buffer %s, account %s" % (name, account,))
|
||||
if bufferType != None:
|
||||
self.buffer = getattr(buffers, bufferType)(parent, name)
|
||||
else:
|
||||
self.buffer = buffers.basePanel(parent, name)
|
||||
self.invisible = True
|
||||
self.name = name
|
||||
self.type = self.buffer.type
|
||||
self.session = sessionObject
|
||||
self.compose_function = compose.compose_tweet
|
||||
log.debug("Compose_function: %s" % (self.compose_function,))
|
||||
self.account = account
|
||||
self.buffer.account = account
|
||||
self.bind_events()
|
||||
self.sound = sound
|
||||
|
||||
def get_formatted_message(self):
|
||||
if self.type == "dm" or self.name == "sent_tweets" or self.name == "sent_direct_messages": return self.compose_function(self.get_right_tweet(), self.session.db, self.session.settings["general"]["relative_times"])[1]
|
||||
return self.get_message()
|
||||
|
||||
def get_message(self):
|
||||
return " ".join(self.compose_function(self.get_right_tweet(), self.session.db, self.session.settings["general"]["relative_times"]))
|
||||
|
||||
def get_full_tweet(self):
|
||||
tweet = self.get_right_tweet()
|
||||
tweetsList = []
|
||||
tweet_id = tweet["id"]
|
||||
uri = None
|
||||
if tweet.has_key("long_uri"):
|
||||
uri = tweet["long_uri"]
|
||||
tweet = self.session.twitter.twitter.show_status(id=tweet_id)
|
||||
if uri != None:
|
||||
tweet["text"] = twishort.get_full_text(uri)
|
||||
l = tweets.is_long(tweet)
|
||||
while l != False:
|
||||
tweetsList.append(tweet)
|
||||
id = tweets.get_id(l)
|
||||
tweet = self.session.twitter.twitter.show_status(id=id)
|
||||
l = tweets.is_long(tweet)
|
||||
if l == False:
|
||||
tweetsList.append(tweet)
|
||||
return (tweet, tweetsList)
|
||||
|
||||
def start_stream(self):
|
||||
log.debug("Starting stream for buffer %s, account %s and type %s" % (self.name, self.account, self.type))
|
||||
log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs))
|
||||
val = self.session.call_paged(self.function, *self.args, **self.kwargs)
|
||||
number_of_items = self.session.order_buffer(self.name, val)
|
||||
log.debug("Number of items retrieved: %d" % (number_of_items,))
|
||||
self.put_items_on_list(number_of_items)
|
||||
if self.sound == None: return
|
||||
if number_of_items > 0 and self.name != "sent_tweets" and self.name != "sent_direct_messages":
|
||||
self.session.sound.play(self.sound)
|
||||
|
||||
def get_more_items(self):
|
||||
elements = []
|
||||
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||
last_id = self.session.db[self.name][0]["id"]
|
||||
else:
|
||||
last_id = self.session.db[self.name][-1]["id"]
|
||||
try:
|
||||
items = self.session.get_more_items(self.function, count=self.session.settings["general"]["max_tweets_per_call"], max_id=last_id, *self.args, **self.kwargs)
|
||||
except TwythonError as e:
|
||||
output.speak(e.message, True)
|
||||
for i in items:
|
||||
if utils.is_allowed(i, self.session.settings["twitter"]["ignored_clients"]) == True:
|
||||
elements.append(i)
|
||||
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||
self.session.db[self.name].insert(0, i)
|
||||
else:
|
||||
self.session.db[self.name].append(i)
|
||||
selection = self.buffer.list.get_selected()
|
||||
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||
for i in elements:
|
||||
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"])
|
||||
self.buffer.list.insert_item(True, *tweet)
|
||||
else:
|
||||
for i in items:
|
||||
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"])
|
||||
self.buffer.list.insert_item(False, *tweet)
|
||||
# self.buffer.list.select_item(selection+elements)
|
||||
# else:
|
||||
self.buffer.list.select_item(selection)
|
||||
output.speak(_(u"%s items retrieved") % (str(len(elements))), True)
|
||||
|
||||
def remove_buffer(self):
|
||||
if "-timeline" in self.name:
|
||||
dlg = commonMessageDialogs.remove_buffer()
|
||||
if dlg == widgetUtils.YES:
|
||||
if self.name[:-9] in self.session.settings["other_buffers"]["timelines"]:
|
||||
self.session.settings["other_buffers"]["timelines"].remove(self.name[:-9])
|
||||
return True
|
||||
elif dlg == widgetUtils.NO:
|
||||
return False
|
||||
elif "favorite" in self.name:
|
||||
dlg = commonMessageDialogs.remove_buffer()
|
||||
if dlg == widgetUtils.YES:
|
||||
if self.name[:-9] in self.session.settings["other_buffers"]["favourites_timelines"]:
|
||||
self.session.settings["other_buffers"]["favourites_timelines"].remove(self.name[:-9])
|
||||
return True
|
||||
elif dlg == widgetUtils.NO:
|
||||
return False
|
||||
else:
|
||||
output.speak(_(u"This buffer is not a timeline; it can't be deleted."), True)
|
||||
return False
|
||||
|
||||
def put_items_on_list(self, number_of_items):
|
||||
log.debug("The list contains %d items " % (self.buffer.list.get_count(),))
|
||||
log.debug("Putting %d items on the list" % (number_of_items,))
|
||||
if self.buffer.list.get_count() == 0:
|
||||
for i in self.session.db[self.name]:
|
||||
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"])
|
||||
self.buffer.list.insert_item(False, *tweet)
|
||||
self.buffer.set_position(self.session.settings["general"]["reverse_timelines"])
|
||||
elif self.buffer.list.get_count() > 0:
|
||||
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||
for i in self.session.db[self.name][:number_of_items]:
|
||||
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"])
|
||||
self.buffer.list.insert_item(False, *tweet)
|
||||
else:
|
||||
for i in self.session.db[self.name][0:number_of_items]:
|
||||
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"])
|
||||
self.buffer.list.insert_item(True, *tweet)
|
||||
log.debug("Now the list contains %d items " % (self.buffer.list.get_count(),))
|
||||
|
||||
def add_new_item(self, item):
|
||||
tweet = self.compose_function(item, self.session.db, self.session.settings["general"]["relative_times"])
|
||||
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||
self.buffer.list.insert_item(False, *tweet)
|
||||
else:
|
||||
self.buffer.list.insert_item(True, *tweet)
|
||||
if self.name in self.session.settings["other_buffers"]["autoread_buffers"] and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and self.session.settings["sound"]["session_mute"] == False:
|
||||
output.speak(" ".join(tweet[:2]))
|
||||
#Improve performance on Windows
|
||||
if platform.system() == "Windows":
|
||||
call_threaded(utils.is_audio,item)
|
||||
|
||||
def bind_events(self):
|
||||
log.debug("Binding events...")
|
||||
self.buffer.set_focus_function(self.onFocus)
|
||||
widgetUtils.connect_event(self.buffer.list.list, widgetUtils.KEYPRESS, self.get_event)
|
||||
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.post_tweet, self.buffer.tweet)
|
||||
# if self.type == "baseBuffer":
|
||||
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.retweet, self.buffer.retweet)
|
||||
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.direct_message, self.buffer.dm)
|
||||
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.reply, self.buffer.reply)
|
||||
|
||||
def get_tweet(self):
|
||||
if self.session.db[self.name][self.buffer.list.get_selected()].has_key("retweeted_status"):
|
||||
tweet = self.session.db[self.name][self.buffer.list.get_selected()]["retweeted_status"]
|
||||
else:
|
||||
tweet = self.session.db[self.name][self.buffer.list.get_selected()]
|
||||
return tweet
|
||||
|
||||
def get_right_tweet(self):
|
||||
tweet = self.session.db[self.name][self.buffer.list.get_selected()]
|
||||
return tweet
|
||||
|
||||
@_tweets_exist
|
||||
def reply(self, *args, **kwargs):
|
||||
tweet = self.get_right_tweet()
|
||||
screen_name = tweet["user"]["screen_name"]
|
||||
id = tweet["id"]
|
||||
users = utils.get_all_mentioned(tweet, self.session.db)
|
||||
message = messages.reply(self.session, _(u"Reply"), _(u"Reply to %s") % (screen_name,), "@%s " % (screen_name,), users)
|
||||
if message.message.get_response() == widgetUtils.OK:
|
||||
if message.image == None:
|
||||
call_threaded(self.session.api_call, call_name="update_status", _sound="reply_send.ogg", in_reply_to_status_id=id, status=message.message.get_text())
|
||||
else:
|
||||
call_threaded(self.session.api_call, call_name="update_status_with_media", _sound="reply_send.ogg", in_reply_to_status_id=id, status=message.message.get_text(), media=message.file)
|
||||
if hasattr(message.message, "destroy"): message.message.destroy()
|
||||
|
||||
@_tweets_exist
|
||||
def direct_message(self, *args, **kwargs):
|
||||
tweet = self.get_right_tweet()
|
||||
if self.type == "dm":
|
||||
screen_name = tweet["sender"]["screen_name"]
|
||||
users = utils.get_all_users(tweet, self.session.db)
|
||||
elif self.type == "people":
|
||||
screen_name = tweet["screen_name"]
|
||||
users = [screen_name]
|
||||
else:
|
||||
screen_name = tweet["user"]["screen_name"]
|
||||
users = utils.get_all_users(tweet, self.session.db)
|
||||
dm = messages.dm(self.session, _(u"Direct message to %s") % (screen_name,), _(u"New direct message"), users)
|
||||
if dm.message.get_response() == widgetUtils.OK:
|
||||
call_threaded(self.session.api_call, call_name="send_direct_message", text=dm.message.get_text(), screen_name=dm.message.get("cb"))
|
||||
if hasattr(dm.message, "destroy"): dm.message.destroy()
|
||||
|
||||
@_tweets_exist
|
||||
def retweet(self, *args, **kwargs):
|
||||
tweet = self.get_right_tweet()
|
||||
id = tweet["id"]
|
||||
if self.session.settings["general"]["retweet_mode"] == "ask":
|
||||
answer = commonMessageDialogs.retweet_question(self.buffer)
|
||||
if answer == widgetUtils.YES:
|
||||
self._retweet_with_comment(tweet, id)
|
||||
elif answer == widgetUtils.NO:
|
||||
self._direct_retweet(id)
|
||||
elif self.session.settings["general"]["retweet_mode"] == "direct":
|
||||
self._direct_retweet(id)
|
||||
else:
|
||||
self._retweet_with_comment(tweet, id)
|
||||
|
||||
def _retweet_with_comment(self, tweet, id, comment=''):
|
||||
retweet = messages.tweet(self.session, _(u"Retweet"), _(u"Add your comment to the tweet"), u"“@%s: %s ”" % (tweet["user"]["screen_name"], tweet["text"]), max=116-len("@%s " % (tweet["user"]["screen_name"],)), messageType="retweet")
|
||||
if comment != '':
|
||||
retweet.message.set_text(comment)
|
||||
if retweet.message.get_response() == widgetUtils.OK:
|
||||
text = retweet.message.get_text()
|
||||
comments=text
|
||||
if len(text+ u"“@%s: %s ”" % (tweet["user"]["screen_name"], tweet["text"])) < 140:
|
||||
text = text+u"“@%s: %s ”" % (tweet["user"]["screen_name"], tweet["text"])
|
||||
else:
|
||||
answer = commonMessageDialogs.retweet_as_link(self.buffer)
|
||||
if answer == widgetUtils.YES:
|
||||
text = text+" @{2} https://twitter.com/{0}/status/{1}".format(tweet["user"]["screen_name"], id, tweet["user"]["screen_name"])
|
||||
else:
|
||||
return self._retweet_with_comment(tweet, id, comment=comments)
|
||||
if retweet.image == None:
|
||||
call_threaded(self.session.api_call, call_name="update_status", _sound="retweet_send.ogg", status=text, in_reply_to_status_id=id)
|
||||
else:
|
||||
call_threaded(self.session.api_call, call_name="update_status", _sound="retweet_send.ogg", status=text, media=retweet.image)
|
||||
if hasattr(retweet.message, "destroy"): retweet.message.destroy()
|
||||
|
||||
def _direct_retweet(self, id):
|
||||
call_threaded(self.session.api_call, call_name="retweet", _sound="retweet_send.ogg", id=id)
|
||||
|
||||
def onFocus(self, *args, **kwargs):
|
||||
tweet = self.get_tweet()
|
||||
if platform.system() == "Windows" and self.session.settings["general"]["relative_times"] == True:
|
||||
# fix this:
|
||||
original_date = arrow.get(self.session.db[self.name][self.buffer.list.get_selected()]["created_at"], "ddd MMM D H:m:s Z YYYY", locale="en")
|
||||
ts = original_date.humanize(locale=languageHandler.getLanguage())
|
||||
self.buffer.list.list.SetStringItem(self.buffer.list.get_selected(), 2, ts)
|
||||
if utils.is_audio(tweet):
|
||||
self.session.sound.play("audio.ogg")
|
||||
if utils.is_geocoded(tweet):
|
||||
self.session.sound.play("geo.ogg")
|
||||
self.session.db[str(self.name+"_pos")]=self.buffer.list.get_selected()
|
||||
|
||||
@_tweets_exist
|
||||
def audio(self,url=''):
|
||||
if hasattr(sound.URLPlayer,'stream'):
|
||||
return sound.URLPlayer.stop_audio(delete=True)
|
||||
tweet = self.get_tweet()
|
||||
if tweet == None: return
|
||||
urls = utils.find_urls(tweet)
|
||||
if len(urls) == 1:
|
||||
url=urls[0]
|
||||
elif len(urls) > 1:
|
||||
urls_list = dialogs.urlList.urlList()
|
||||
urls_list.populate_list(urls)
|
||||
if urls_list.get_response() == widgetUtils.OK:
|
||||
url=urls_list.get_string()
|
||||
if hasattr(urls_list, "destroy"): urls_list.destroy()
|
||||
if url != '':
|
||||
try:
|
||||
sound.URLPlayer.play(url, self.session.settings["sound"]["volume"])
|
||||
except:
|
||||
log.error("Exception while executing audio method.")
|
||||
|
||||
@_tweets_exist
|
||||
def url(self,url='',announce=True):
|
||||
if url == '':
|
||||
tweet = self.get_tweet()
|
||||
urls = utils.find_urls(tweet)
|
||||
if len(urls) == 1:
|
||||
url=urls[0]
|
||||
elif len(urls) > 1:
|
||||
urls_list = dialogs.urlList.urlList()
|
||||
urls_list.populate_list(urls)
|
||||
if urls_list.get_response() == widgetUtils.OK:
|
||||
url=urls_list.get_string()
|
||||
if hasattr(urls_list, "destroy"): urls_list.destroy()
|
||||
if url != '':
|
||||
if announce:
|
||||
output.speak(_(u"Opening URL..."), True)
|
||||
webbrowser.open_new_tab(url)
|
||||
|
||||
def clear_list(self):
|
||||
dlg = commonMessageDialogs.clear_list()
|
||||
if dlg == widgetUtils.YES:
|
||||
self.session.db[self.name] = []
|
||||
self.buffer.list.clear()
|
||||
|
||||
@_tweets_exist
|
||||
def destroy_status(self, *args, **kwargs):
|
||||
index = self.buffer.list.get_selected()
|
||||
if self.type == "events" or self.type == "people" or self.type == "empty" or self.type == "account": return
|
||||
answer = commonMessageDialogs.delete_tweet_dialog(None)
|
||||
if answer == widgetUtils.YES:
|
||||
try:
|
||||
if self.name == "direct_messages" or self.name == "sent_direct_messages":
|
||||
self.session.twitter.twitter.destroy_direct_message(id=self.get_right_tweet()["id"])
|
||||
else:
|
||||
self.session.twitter.twitter.destroy_status(id=self.get_right_tweet()["id"])
|
||||
self.session.db[self.name].pop(index)
|
||||
self.buffer.list.remove_item(index)
|
||||
# if index > 0:
|
||||
except TwythonError:
|
||||
self.session.sound.play("error")
|
||||
|
||||
@_tweets_exist
|
||||
def user_details(self):
|
||||
tweet = self.get_right_tweet()
|
||||
if self.type == "dm":
|
||||
users = utils.get_all_users(tweet, self.session.db)
|
||||
elif self.type == "people":
|
||||
users = [tweet["screen_name"]]
|
||||
else:
|
||||
users = utils.get_all_users(tweet, self.session.db)
|
||||
dlg = dialogs.utils.selectUserDialog(title=_(u"User details"), users=users)
|
||||
if dlg.get_response() == widgetUtils.OK:
|
||||
user.profileController(session=self.session, user=dlg.get_user())
|
||||
if hasattr(dlg, "destroy"): dlg.destroy()
|
||||
|
||||
class listBufferController(baseBufferController):
|
||||
def __init__(self, parent, function, name, sessionObject, account, sound=None, bufferType=None, list_id=None, *args, **kwargs):
|
||||
super(listBufferController, self).__init__(parent, function, name, sessionObject, account, sound=None, bufferType=None, *args, **kwargs)
|
||||
self.users = []
|
||||
self.list_id = list_id
|
||||
self.kwargs["list_id"] = list_id
|
||||
|
||||
def start_stream(self):
|
||||
self.get_user_ids()
|
||||
super(listBufferController, self).start_stream()
|
||||
|
||||
def get_user_ids(self):
|
||||
self.users = []
|
||||
next_cursor = -1
|
||||
while(next_cursor):
|
||||
users = self.session.twitter.twitter.get_list_members(list_id=self.list_id, cursor=next_cursor, include_entities=False, skip_status=True)
|
||||
for i in users['users']:
|
||||
self.users.append(i["id"])
|
||||
next_cursor = users["next_cursor"]
|
||||
|
||||
def remove_buffer(self):
|
||||
dlg = commonMessageDialogs.remove_buffer()
|
||||
if dlg == widgetUtils.YES:
|
||||
if self.name[:-5] in self.session.settings["other_buffers"]["lists"]:
|
||||
self.session.settings["other_buffers"]["lists"].remove(self.name[:-5])
|
||||
return True
|
||||
elif dlg == widgetUtils.NO:
|
||||
return False
|
||||
|
||||
class eventsBufferController(bufferController):
|
||||
def __init__(self, parent, name, session, account, *args, **kwargs):
|
||||
super(eventsBufferController, self).__init__(parent, *args, **kwargs)
|
||||
log.debug("Initializing buffer %s, account %s" % (name, account,))
|
||||
self.invisible = True
|
||||
self.buffer = buffers.eventsPanel(parent, name)
|
||||
self.name = name
|
||||
self.account = account
|
||||
self.buffer.account = self.account
|
||||
self.compose_function = compose.compose_event
|
||||
self.session = session
|
||||
self.type = self.buffer.type
|
||||
self.get_formatted_message = self.get_message
|
||||
|
||||
def get_message(self):
|
||||
if self.buffer.list.get_count() == 0: return _(u"Empty")
|
||||
# fix this:
|
||||
return "%s. %s" % (self.buffer.list.list.GetItemText(self.buffer.list.get_selected()), self.buffer.list.list.GetItemText(self.buffer.list.get_selected(), 1))
|
||||
|
||||
def add_new_item(self, item):
|
||||
tweet = self.compose_function(item, self.session.db["user_name"])
|
||||
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||
self.buffer.list.insert_item(False, *tweet)
|
||||
else:
|
||||
self.buffer.list.insert_item(True, *tweet)
|
||||
if self.name in self.session.settings["other_buffers"]["autoread_buffers"] and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and self.session.settings["sound"]["session_mute"] == False:
|
||||
output.speak(" ".join(tweet))
|
||||
if self.buffer.list.get_count() == 1:
|
||||
self.buffer.list.select_item(0)
|
||||
|
||||
def clear_list(self):
|
||||
dlg = commonMessageDialogs.clear_list()
|
||||
if dlg == widgetUtils.YES:
|
||||
self.buffer.list.clear()
|
||||
|
||||
class peopleBufferController(baseBufferController):
|
||||
def __init__(self, parent, function, name, sessionObject, account, bufferType=None, *args, **kwargs):
|
||||
super(peopleBufferController, self).__init__(parent, function, name, sessionObject, account, bufferType="peoplePanel")
|
||||
log.debug("Initializing buffer %s, account %s" % (name, account,))
|
||||
self.compose_function = compose.compose_followers_list
|
||||
log.debug("Compose_function: %s" % (self.compose_function,))
|
||||
self.get_tweet = self.get_right_tweet
|
||||
self.url = self.interact
|
||||
|
||||
def remove_buffer(self):
|
||||
return False
|
||||
|
||||
def onFocus(self, ev):
|
||||
pass
|
||||
|
||||
def get_message(self):
|
||||
return " ".join(self.compose_function(self.get_tweet(), self.session.db, self.session.settings["general"]["relative_times"]))
|
||||
|
||||
def delete_item(self): pass
|
||||
|
||||
@_tweets_exist
|
||||
def reply(self, *args, **kwargs):
|
||||
tweet = self.get_right_tweet()
|
||||
screen_name = tweet["screen_name"]
|
||||
message = messages.reply(self.session, _(u"Mention"), _(u"Mention to %s") % (screen_name,), "@%s " % (screen_name,), [screen_name,])
|
||||
if message.message.get_response() == widgetUtils.OK:
|
||||
if message.image == None:
|
||||
call_threaded(self.session.api_call, call_name="update_status", _sound="reply_send.ogg", status=message.message.get_text())
|
||||
else:
|
||||
call_threaded(self.session.api_call, call_name="update_status_with_media", _sound="reply_send.ogg", status=message.message.get_text(), media=message.file)
|
||||
if hasattr(message.message, "destroy"): message.message.destroy()
|
||||
|
||||
def start_stream(self):
|
||||
log.debug("Starting stream for %s buffer, %s account" % (self.name, self.account,))
|
||||
log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs))
|
||||
val = self.session.get_cursored_stream(self.name, self.function, *self.args, **self.kwargs)
|
||||
# self.session.order_cursored_buffer(self.name, self.session.db[self.name])
|
||||
# log.debug("Number of items retrieved: %d" % (val,))
|
||||
self.put_items_on_list(val)
|
||||
|
||||
def get_more_items(self):
|
||||
try:
|
||||
items = self.session.get_more_items(self.function, users=True, name=self.name, count=self.session.settings["general"]["max_tweets_per_call"], cursor=self.session.db[self.name]["cursor"])
|
||||
except TwythonError as e:
|
||||
output.speak(e.message, True)
|
||||
return
|
||||
for i in items:
|
||||
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||
self.session.db[self.name]["items"].insert(0, i)
|
||||
else:
|
||||
self.session.db[self.name]["items"].append(i)
|
||||
selected = self.buffer.list.get_selected()
|
||||
# self.put_items_on_list(len(items))
|
||||
if self.session.settings["general"]["reverse_timelines"] == True:
|
||||
for i in items:
|
||||
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"])
|
||||
self.buffer.list.insert_item(True, *tweet)
|
||||
self.buffer.list.select_item(selected)
|
||||
else:
|
||||
for i in items:
|
||||
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"])
|
||||
self.buffer.list.insert_item(True, *tweet)
|
||||
# self.buffer.list.select_item(selection)
|
||||
# else:
|
||||
# self.buffer.list.select_item(selection-elements)
|
||||
output.speak(_(u"%s items retrieved") % (len(items)), True)
|
||||
|
||||
def put_items_on_list(self, number_of_items):
|
||||
log.debug("The list contains %d items" % (self.buffer.list.get_count(),))
|
||||
# log.debug("Putting %d items on the list..." % (number_of_items,))
|
||||
if self.buffer.list.get_count() == 0:
|
||||
for i in self.session.db[self.name]["items"]:
|
||||
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"])
|
||||
self.buffer.list.insert_item(False, *tweet)
|
||||
self.buffer.set_position(self.session.settings["general"]["reverse_timelines"])
|
||||
# self.buffer.set_list_position()
|
||||
elif self.buffer.list.get_count() > 0:
|
||||
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||
for i in self.session.db[self.name]["items"][:number_of_items]:
|
||||
tweet = self.compose_function(i, self.session.db)
|
||||
self.buffer.list.insert_item(False, *tweet)
|
||||
else:
|
||||
for i in self.session.db[self.name]["items"][0:number_of_items]:
|
||||
tweet = self.compose_function(i, self.session.db)
|
||||
self.buffer.list.insert_item(True, *tweet)
|
||||
log.debug("now the list contains %d items" % (self.buffer.list.get_count(),))
|
||||
|
||||
def get_right_tweet(self):
|
||||
tweet = self.session.db[self.name]["items"][self.buffer.list.get_selected()]
|
||||
return tweet
|
||||
|
||||
def add_new_item(self, item):
|
||||
tweet = self.compose_function(item, self.session.db, self.session.settings["general"]["relative_times"])
|
||||
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||
self.buffer.list.insert_item(False, *tweet)
|
||||
else:
|
||||
self.buffer.list.insert_item(True, *tweet)
|
||||
if self.name in self.session.settings["other_buffers"]["autoread_buffers"] and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and self.session.settings["sound"]["session_mute"] == False:
|
||||
output.speak(" ".join(tweet))
|
||||
|
||||
def clear_list(self):
|
||||
dlg = commonMessageDialogs.clear_list()
|
||||
if dlg == widgetUtils.YES:
|
||||
self.session.db[self.name]["items"] = []
|
||||
self.session.db[self.name]["cursor"] = -1
|
||||
self.buffer.list.clear()
|
||||
|
||||
def interact(self):
|
||||
user.profileController(self.session, user=self.get_right_tweet()["screen_name"])
|
||||
|
||||
class searchBufferController(baseBufferController):
|
||||
def start_stream(self):
|
||||
log.debug("Starting stream for %s buffer, %s account and %s type" % (self.name, self.account, self.type))
|
||||
log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs))
|
||||
log.debug("Function: %s" % (self.function,))
|
||||
# try:
|
||||
val = self.session.search(self.name, *self.args, **self.kwargs)
|
||||
# except:
|
||||
# return None
|
||||
num = self.session.order_buffer(self.name, val)
|
||||
self.put_items_on_list(num)
|
||||
if num > 0:
|
||||
self.session.sound.play("search_updated.ogg")
|
||||
|
||||
def remove_buffer(self):
|
||||
dlg = commonMessageDialogs.remove_buffer()
|
||||
if dlg == widgetUtils.YES:
|
||||
if self.name[:-11] in self.session.settings["other_buffers"]["tweet_searches"]:
|
||||
self.session.settings["other_buffers"]["tweet_searches"].remove(self.name[:-11])
|
||||
self.timer.cancel()
|
||||
return True
|
||||
elif dlg == widgetUtils.NO:
|
||||
return False
|
||||
|
||||
class searchPeopleBufferController(peopleBufferController):
|
||||
|
||||
def __init__(self, parent, function, name, sessionObject, account, bufferType="peoplePanel", *args, **kwargs):
|
||||
super(searchPeopleBufferController, self).__init__(parent, function, name, sessionObject, account, bufferType="peoplePanel", *args, **kwargs)
|
||||
log.debug("Initializing buffer %s, account %s" % (name, account,))
|
||||
# self.compose_function = compose.compose_followers_list
|
||||
log.debug("Compose_function: %s" % (self.compose_function,))
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
self.function = function
|
||||
|
||||
def start_stream(self):
|
||||
log.debug("starting stream for %s buffer, %s account and %s type" % (self.name, self.account, self.type))
|
||||
log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs))
|
||||
log.debug("Function: %s" % (self.function,))
|
||||
# try:
|
||||
val = self.session.call_paged(self.function, *self.args, **self.kwargs)
|
||||
# except:
|
||||
# return
|
||||
number_of_items = self.session.order_cursored_buffer(self.name, val)
|
||||
log.debug("Number of items retrieved: %d" % (number_of_items,))
|
||||
self.put_items_on_list(number_of_items)
|
||||
if number_of_items > 0:
|
||||
self.session.sound.play("search_updated.ogg")
|
||||
|
||||
def remove_buffer(self):
|
||||
dlg = commonMessageDialogs.remove_buffer()
|
||||
if dlg == widgetUtils.YES:
|
||||
if self.name[:-11] in self.session.settings["other_buffers"]["tweet_searches"]:
|
||||
self.session.settings["other_buffers"]["tweet_searches"].remove(self.name[:-11])
|
||||
self.timer.cancel()
|
||||
return True
|
||||
elif dlg == widgetUtils.NO:
|
||||
return False
|
||||
|
||||
class trendsBufferController(bufferController):
|
||||
def __init__(self, parent, name, session, account, trendsFor, *args, **kwargs):
|
||||
super(trendsBufferController, self).__init__(parent=parent, session=session)
|
||||
self.trendsFor = trendsFor
|
||||
self.session = session
|
||||
self.account = account
|
||||
self.invisible = True
|
||||
self.buffer = buffers.trendsPanel(parent, name)
|
||||
self.buffer.account = account
|
||||
self.type = self.buffer.type
|
||||
self.bind_events()
|
||||
self.sound = "trends_updated.ogg"
|
||||
self.trends = []
|
||||
self.name = name
|
||||
self.buffer.name = name
|
||||
self.compose_function = self.compose_function_
|
||||
self.get_formatted_message = self.get_message
|
||||
|
||||
def start_stream(self):
|
||||
try:
|
||||
data = self.session.call_paged("get_place_trends", id=self.trendsFor)
|
||||
except:
|
||||
return
|
||||
if not hasattr(self, "name_"):
|
||||
self.name_ = data[0]["locations"][0]["name"]
|
||||
self.trends = data[0]["trends"]
|
||||
self.put_items_on_the_list()
|
||||
self.session.sound.play(self.sound)
|
||||
|
||||
def put_items_on_the_list(self):
|
||||
selected_item = self.buffer.list.get_selected()
|
||||
self.buffer.list.clear()
|
||||
for i in self.trends:
|
||||
tweet = self.compose_function(i)
|
||||
self.buffer.list.insert_item(False, *tweet)
|
||||
self.buffer.set_position(self.session.settings["general"]["reverse_timelines"])
|
||||
|
||||
def compose_function_(self, trend):
|
||||
return [trend["name"]]
|
||||
|
||||
def bind_events(self):
|
||||
log.debug("Binding events...")
|
||||
self.buffer.list.list.Bind(wx.EVT_CHAR_HOOK, self.get_event)
|
||||
# widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.post_tweet, self.buffer.tweet)
|
||||
# widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.retweet, self.buffer.retweet)
|
||||
# widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.direct_message, self.buffer.dm)
|
||||
# widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.reply, self.buffer.reply)
|
||||
|
||||
def get_message(self):
|
||||
return self.compose_function(self.trends[self.buffer.list.get_selected()])[0]
|
||||
|
||||
def remove_buffer(self):
|
||||
dlg = commonMessageDialogs.remove_buffer()
|
||||
if dlg == widgetUtils.YES:
|
||||
if self.name[:-3] in self.session.settings["other_buffers"]["trending_topic_buffers"]:
|
||||
self.session.settings["other_buffers"]["trending_topic_buffers"].remove(self.name[:-3])
|
||||
self.timer.cancel()
|
||||
return True
|
||||
elif dlg == widgetUtils.NO:
|
||||
return False
|
||||
|
||||
def interact(self, *args, **kwargs):
|
||||
self.searchfunction(value=self.get_message())
|
||||
|
||||
class conversationBufferController(searchBufferController):
|
||||
|
||||
def start_stream(self, start=False):
|
||||
if start == True:
|
||||
self.statuses = []
|
||||
self.ids = []
|
||||
self.statuses.append(self.tweet)
|
||||
self.ids.append(self.tweet["id"])
|
||||
tweet = self.tweet
|
||||
while tweet["in_reply_to_status_id"] != None:
|
||||
tweet = self.session.twitter.twitter.show_status(id=tweet["in_reply_to_status_id"])
|
||||
self.statuses.insert(0, tweet)
|
||||
self.ids.append(tweet["id"])
|
||||
if tweet["in_reply_to_status_id"] == None:
|
||||
self.kwargs["since_id"] = tweet["id"]
|
||||
self.ids.append(tweet["id"])
|
||||
val2 = self.session.search(self.name, *self.args, **self.kwargs)
|
||||
for i in val2:
|
||||
if i["in_reply_to_status_id"] in self.ids:
|
||||
self.statuses.append(i)
|
||||
self.ids.append(i["id"])
|
||||
tweet = i
|
||||
number_of_items = self.session.order_buffer(self.name, self.statuses)
|
||||
log.debug("Number of items retrieved: %d" % (number_of_items,))
|
||||
self.put_items_on_list(number_of_items)
|
||||
if number_of_items > 0:
|
||||
self.session.sound.play("search_updated.ogg")
|
||||
|
@@ -1,76 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import widgetUtils
|
||||
import output
|
||||
from wxUI.dialogs import lists
|
||||
from twython import TwythonError
|
||||
from twitter import compose, utils
|
||||
from pubsub import pub
|
||||
|
||||
class listsController(object):
|
||||
def __init__(self, session, user=None):
|
||||
super(listsController, self).__init__()
|
||||
self.session = session
|
||||
if user == None:
|
||||
self.dialog = lists.listViewer()
|
||||
self.dialog.populate_list(self.get_all_lists())
|
||||
widgetUtils.connect_event(self.dialog.createBtn, widgetUtils.BUTTON_PRESSED, self.create_list)
|
||||
widgetUtils.connect_event(self.dialog.editBtn, widgetUtils.BUTTON_PRESSED, self.edit_list)
|
||||
widgetUtils.connect_event(self.dialog.view, widgetUtils.BUTTON_PRESSED, self.open_list_as_buffer)
|
||||
self.dialog.get_response()
|
||||
|
||||
def get_all_lists(self):
|
||||
return [compose.compose_list(item) for item in self.session.db["lists"]]
|
||||
|
||||
def create_list(self, *args, **kwargs):
|
||||
dialog = lists.createListDialog()
|
||||
if dialog.get_response() == widgetUtils.OK:
|
||||
name = dialog.get("name")
|
||||
description = dialog.get("description")
|
||||
p = dialog.get("public")
|
||||
if public == True:
|
||||
mode = "public"
|
||||
else:
|
||||
mode = "private"
|
||||
try:
|
||||
new_list = self.session.twitter.twitter.create_list(name=name, description=description, mode=mode)
|
||||
self.session.db["lists"].append(new_list)
|
||||
self.dialog.lista.insert_item(False, *compose.compose_list(new_list))
|
||||
except TwythonError as e:
|
||||
output.speak("error %s: %s" % (e.status_code, e.msg))
|
||||
dialog.destroy()
|
||||
|
||||
def edit_list(self, *args, **kwargs):
|
||||
if self.dialog.lista.get_count() == 0: return
|
||||
list = self.session.db["lists"][self.dialog.get_item()]
|
||||
dialog = lists.editListDialog(list)
|
||||
if dialog.get_response() == widgetUtils.OK:
|
||||
name = dialog.get("name")
|
||||
description = dialog.get("description")
|
||||
p = dialog.get("public")
|
||||
if p == True:
|
||||
mode = "public"
|
||||
else:
|
||||
mode = "private"
|
||||
try:
|
||||
self.session.twitter.twitter.update_list(list_id=list["id"], name=name, description=description, mode=mode)
|
||||
self.session.get_lists()
|
||||
self.dialog.populate_list(self.get_all_lists(), True)
|
||||
except TwythonError as e:
|
||||
output.speak("error %s: %s" % (e.error_code, e.msg))
|
||||
dialog.destroy()
|
||||
|
||||
def remove_list(self, *args, **kwargs):
|
||||
if self.dialog.lista.get_count() == 0: return
|
||||
list = self.session.db["lists"][self.dialog.get_item()]["id"]
|
||||
if lists.remove_list() == widgetUtils.YES:
|
||||
try:
|
||||
self.session.twitter.twitter.delete_list(list_id=list)
|
||||
self.session.db["lists"].pop(self.dialog.get_item())
|
||||
self.dialog.lista.remove_item(self.dialog.get_item())
|
||||
except TwythonError as e:
|
||||
output.speak("error %s: %s" % (e.error_code, e.msg))
|
||||
|
||||
def open_list_as_buffer(self, *args, **kwargs):
|
||||
if self.dialog.lista.get_count() == 0: return
|
||||
list = self.session.db["lists"][self.dialog.get_item()]
|
||||
pub.sendMessage("create-new-buffer", buffer="list", account=self.session.db["user_name"], create=list["slug"])
|
@@ -1,186 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import platform
|
||||
system = platform.system()
|
||||
import widgetUtils
|
||||
import output
|
||||
import url_shortener
|
||||
import sound
|
||||
from pubsub import pub
|
||||
if system == "Windows":
|
||||
from wxUI.dialogs import message, urlList
|
||||
from extra import translator, SpellChecker, autocompletionUsers
|
||||
from extra.AudioUploader import audioUploader
|
||||
elif system == "Linux":
|
||||
from gtkUI.dialogs import message
|
||||
from twitter import utils
|
||||
|
||||
class basicTweet(object):
|
||||
""" This class handles the tweet main features. Other classes should derive from this class."""
|
||||
def __init__(self, session, title, caption, text, messageType="tweet", max=140):
|
||||
super(basicTweet, self).__init__()
|
||||
self.max = max
|
||||
self.title = title
|
||||
self.session = session
|
||||
self.message = getattr(message, messageType)(title, caption, text)
|
||||
widgetUtils.connect_event(self.message.spellcheck, widgetUtils.BUTTON_PRESSED, self.spellcheck)
|
||||
widgetUtils.connect_event(self.message.attach, widgetUtils.BUTTON_PRESSED, self.attach)
|
||||
# if system == "Windows":
|
||||
widgetUtils.connect_event(self.message.text, widgetUtils.ENTERED_TEXT, self.text_processor)
|
||||
self.text_processor()
|
||||
widgetUtils.connect_event(self.message.shortenButton, widgetUtils.BUTTON_PRESSED, self.shorten)
|
||||
widgetUtils.connect_event(self.message.unshortenButton, widgetUtils.BUTTON_PRESSED, self.unshorten)
|
||||
widgetUtils.connect_event(self.message.translateButton, widgetUtils.BUTTON_PRESSED, self.translate)
|
||||
|
||||
def translate(self, event=None):
|
||||
dlg = translator.gui.translateDialog()
|
||||
if dlg.get_response() == widgetUtils.OK:
|
||||
text_to_translate = self.message.get_text().encode("utf-8")
|
||||
source = [x[0] for x in translator.translator.available_languages()][dlg.get("source_lang")]
|
||||
dest = [x[0] for x in translator.translator.available_languages()][dlg.get("dest_lang")]
|
||||
msg = translator.translator.translate(text_to_translate, source, dest)
|
||||
self.message.set_text(msg)
|
||||
self.message.text_focus()
|
||||
output.speak(_(u"Translated"))
|
||||
else:
|
||||
return
|
||||
|
||||
def shorten(self, event=None):
|
||||
urls = utils.find_urls_in_text(self.message.get_text())
|
||||
if len(urls) == 0:
|
||||
output.speak(_(u"There's no URL to be shortened"))
|
||||
self.message.text_focus()
|
||||
elif len(urls) == 1:
|
||||
self.message.set_text(self.message.get_text().replace(urls[0], url_shortener.shorten(urls[0])))
|
||||
output.speak(_(u"URL shortened"))
|
||||
self.message.text_focus()
|
||||
elif len(urls) > 1:
|
||||
list_urls = urlList.urlList()
|
||||
list_urls.populate_list(urls)
|
||||
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())))
|
||||
output.speak(_(u"URL shortened"))
|
||||
self.message.text_focus()
|
||||
|
||||
def unshorten(self, event=None):
|
||||
urls = utils.find_urls_in_text(self.message.get_text())
|
||||
if len(urls) == 0:
|
||||
output.speak(_(u"There's no URL to be expanded"))
|
||||
self.message.text_focus()
|
||||
elif len(urls) == 1:
|
||||
self.message.set_text(self.message.get_text().replace(urls[0], url_shortener.unshorten(urls[0])))
|
||||
output.speak(_(u"URL expanded"))
|
||||
self.message.text_focus()
|
||||
elif len(urls) > 1:
|
||||
list_urls = urlList.urlList()
|
||||
list_urls.populate_list(urls)
|
||||
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())))
|
||||
output.speak(_(u"URL expanded"))
|
||||
self.message.text_focus()
|
||||
|
||||
def text_processor(self, *args, **kwargs):
|
||||
self.message.set_title(_(u"%s - %s of %d characters") % (self.title, len(self.message.get_text()), self.max))
|
||||
if len(self.message.get_text()) > 1:
|
||||
self.message.enable_button("shortenButton")
|
||||
self.message.enable_button("unshortenButton")
|
||||
else:
|
||||
self.message.disable_button("shortenButton")
|
||||
self.message.disable_button("unshortenButton")
|
||||
if len(self.message.get_text()) > self.max:
|
||||
self.session.sound.play("max_length.ogg")
|
||||
|
||||
def spellcheck(self, event=None):
|
||||
text = self.message.get_text()
|
||||
checker = SpellChecker.spellchecker.spellChecker(text, "")
|
||||
if hasattr(checker, "fixed_text"):
|
||||
self.message.set_text(checker.fixed_text)
|
||||
|
||||
def attach(self, *args, **kwargs):
|
||||
def completed_callback():
|
||||
url = dlg.uploaderFunction.get_url()
|
||||
pub.unsubscribe(dlg.uploaderDialog.update, "uploading")
|
||||
dlg.uploaderDialog.destroy()
|
||||
if url != 0:
|
||||
self.message.set_text(self.message.get_text()+url+" #audio")
|
||||
else:
|
||||
output.speak(_(u"Unable to upload the audio"))
|
||||
dlg.cleanup()
|
||||
dlg = audioUploader.audioUploader(self.session.settings, completed_callback)
|
||||
|
||||
class tweet(basicTweet):
|
||||
def __init__(self, session, title, caption, text, messageType="tweet", max=140):
|
||||
super(tweet, self).__init__(session, title, caption, text, messageType, max)
|
||||
self.image = None
|
||||
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)
|
||||
|
||||
def upload_image(self, *args, **kwargs):
|
||||
if self.message.get("upload_image") == _(u"Discard image"):
|
||||
del self.image
|
||||
self.image = None
|
||||
output.speak(_(u"Discarded"))
|
||||
self.message.set("upload_image", _(u"Upload a picture"))
|
||||
else:
|
||||
self.image = self.message.get_image()
|
||||
if self.image != None:
|
||||
self.message.set("upload_image", _(u"Discard image"))
|
||||
|
||||
def autocomplete_users(self, *args, **kwargs):
|
||||
c = autocompletionUsers.completion.autocompletionUsers(self.message, self.session.session_id)
|
||||
c.show_menu()
|
||||
|
||||
class reply(tweet):
|
||||
def __init__(self, session, title, caption, text, users=None):
|
||||
super(reply, self).__init__(session, title, caption, text, messageType="reply")
|
||||
self.users = users
|
||||
if self.users != None and len(self.users) > 1:
|
||||
widgetUtils.connect_event(self.message.mentionAll, widgetUtils.BUTTON_PRESSED, self.mention_all)
|
||||
self.message.enable_button("mentionAll")
|
||||
self.message.set_cursor_at_end()
|
||||
|
||||
def mention_all(self, *args, **kwargs):
|
||||
self.message.set_text(self.message.get_text()+self.users)
|
||||
self.message.set_cursor_at_end()
|
||||
self.message.text_focus()
|
||||
|
||||
class dm(basicTweet):
|
||||
def __init__(self, session, title, caption, text):
|
||||
super(dm, self).__init__(session, title, caption, text, messageType="dm")
|
||||
widgetUtils.connect_event(self.message.autocompletionButton, widgetUtils.BUTTON_PRESSED, self.autocomplete_users)
|
||||
|
||||
def autocomplete_users(self, *args, **kwargs):
|
||||
c = autocompletionUsers.completion.autocompletionUsers(self.message, self.session.session_id)
|
||||
c.show_menu("dm")
|
||||
|
||||
class viewTweet(basicTweet):
|
||||
def __init__(self, tweet, tweetList, is_tweet=True):
|
||||
if is_tweet == True:
|
||||
text = ""
|
||||
for i in xrange(0, len(tweetList)):
|
||||
if tweetList[i].has_key("retweeted_status"):
|
||||
text = text + "rt @%s: %s\n\n" % (tweetList[i]["retweeted_status"]["user"]["screen_name"], tweetList[i]["retweeted_status"]["text"])
|
||||
else:
|
||||
text = text + "@%s: %s\n\n" % (tweetList[i]["user"]["screen_name"], tweetList[i]["text"])
|
||||
rt_count = str(tweet["retweet_count"])
|
||||
favs_count = str(tweet["favorite_count"])
|
||||
if text == "":
|
||||
if tweet.has_key("retweeted_status"):
|
||||
text = "rt @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], tweet["retweeted_status"]["text"])
|
||||
else:
|
||||
text = tweet["text"]
|
||||
self.message = message.viewTweet(text, rt_count, favs_count)
|
||||
self.message.set_title(len(text))
|
||||
else:
|
||||
text = tweet
|
||||
self.message = message.viewNonTweet(text)
|
||||
widgetUtils.connect_event(self.message.spellcheck, widgetUtils.BUTTON_PRESSED, self.spellcheck)
|
||||
widgetUtils.connect_event(self.message.translateButton, widgetUtils.BUTTON_PRESSED, self.translate)
|
||||
if self.contain_urls() == True:
|
||||
self.message.enable_button("unshortenButton")
|
||||
widgetUtils.connect_event(self.message.unshortenButton, widgetUtils.BUTTON_PRESSED, self.unshorten)
|
||||
self.message.get_response()
|
||||
|
||||
def contain_urls(self):
|
||||
if len(utils.find_urls_in_text(self.message.get_text())) > 0:
|
||||
return True
|
||||
return False
|
@@ -1,281 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
import webbrowser
|
||||
import sound_lib
|
||||
import paths
|
||||
import widgetUtils
|
||||
import config
|
||||
import languageHandler
|
||||
import output
|
||||
import application
|
||||
from wxUI.dialogs import configuration
|
||||
from wxUI import commonMessageDialogs
|
||||
from extra.autocompletionUsers import settings
|
||||
from extra.AudioUploader import dropbox_transfer
|
||||
from pubsub import pub
|
||||
import logging
|
||||
import config_utils
|
||||
log = logging.getLogger("Settings")
|
||||
|
||||
class globalSettingsController(object):
|
||||
def __init__(self):
|
||||
super(globalSettingsController, self).__init__()
|
||||
self.dialog = configuration.configurationDialog()
|
||||
self.create_config()
|
||||
self.needs_restart = False
|
||||
self.is_started = True
|
||||
|
||||
def make_kmmap(self):
|
||||
res={}
|
||||
for i in os.listdir(paths.app_path('keymaps')):
|
||||
if ".keymap" not in i:
|
||||
continue
|
||||
try:
|
||||
res[config_utils.load_config(paths.app_path('keymaps/'+i))['info']['name']]=i
|
||||
except:
|
||||
log.exception("Exception while loading keymap " + i)
|
||||
return res
|
||||
|
||||
def create_config(self):
|
||||
self.kmmap=self.make_kmmap()
|
||||
self.langs = languageHandler.getAvailableLanguages()
|
||||
langs = []
|
||||
[langs.append(i[1]) for i in self.langs]
|
||||
self.codes = []
|
||||
[self.codes.append(i[0]) for i in self.langs]
|
||||
id = self.codes.index(config.app["app-settings"]["language"])
|
||||
self.kmfriendlies=[]
|
||||
self.kmnames=[]
|
||||
for k,v in self.kmmap.items():
|
||||
self.kmfriendlies.append(k)
|
||||
self.kmnames.append(v)
|
||||
self.kmid=self.kmnames.index(config.app['app-settings']['load_keymap'])
|
||||
self.dialog.create_general(langs,self.kmfriendlies)
|
||||
self.dialog.general.language.SetSelection(id)
|
||||
self.dialog.general.km.SetSelection(self.kmid)
|
||||
self.dialog.set_value("general", "ask_at_exit", config.app["app-settings"]["ask_at_exit"])
|
||||
|
||||
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", "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", "hide_gui", config.app["app-settings"]["hide_gui"])
|
||||
self.dialog.create_proxy()
|
||||
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", "user", config.app["proxy"]["user"])
|
||||
self.dialog.set_value("proxy", "password", config.app["proxy"]["password"])
|
||||
self.dialog.realize()
|
||||
self.response = self.dialog.get_response()
|
||||
|
||||
def save_configuration(self):
|
||||
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()]
|
||||
languageHandler.setLanguage(config.app["app-settings"]["language"])
|
||||
self.needs_restart = True
|
||||
if self.kmnames[self.dialog.general.km.GetSelection()] != config.app["app-settings"]["load_keymap"]:
|
||||
config.app["app-settings"]["load_keymap"] =self.kmnames[self.dialog.general.km.GetSelection()]
|
||||
self.needs_restart = True
|
||||
|
||||
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")
|
||||
pub.sendMessage("invisible-shorcuts-changed", registered=self.dialog.get_value("general", "use_invisible_shorcuts"))
|
||||
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"]["ask_at_exit"] = self.dialog.get_value("general", "ask_at_exit")
|
||||
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")
|
||||
if 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:
|
||||
self.needs_restart = True
|
||||
config.app["proxy"]["server"] = self.dialog.get_value("proxy", "server")
|
||||
config.app["proxy"]["port"] = self.dialog.get_value("proxy", "port")
|
||||
config.app["proxy"]["user"] = self.dialog.get_value("proxy", "user")
|
||||
config.app["proxy"]["password"] = self.dialog.get_value("proxy", "password")
|
||||
config.app.write()
|
||||
|
||||
class accountSettingsController(globalSettingsController):
|
||||
def __init__(self, buffer, window):
|
||||
self.user = buffer.session.db["user_name"]
|
||||
self.buffer = buffer
|
||||
self.window = window
|
||||
self.config = buffer.session.settings
|
||||
super(accountSettingsController, self).__init__()
|
||||
|
||||
def create_config(self):
|
||||
self.dialog.create_general_account()
|
||||
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", "apiCalls", self.config["general"]["max_api_calls"])
|
||||
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"])
|
||||
rt = self.config["general"]["retweet_mode"]
|
||||
if rt == "ask":
|
||||
self.dialog.set_value("general", "retweet_mode", _(u"Ask"))
|
||||
elif rt == "direct":
|
||||
self.dialog.set_value("general", "retweet_mode", _(u"Retweet without comments"))
|
||||
else:
|
||||
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.create_other_buffers()
|
||||
buffer_values = self.get_buffers_list()
|
||||
self.dialog.buffers.insert_buffers(buffer_values)
|
||||
self.dialog.buffers.connect_hook_func(self.toggle_buffer_active)
|
||||
widgetUtils.connect_event(self.dialog.buffers.toggle_state, widgetUtils.BUTTON_PRESSED, self.toggle_state)
|
||||
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"])
|
||||
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)
|
||||
self.input_devices = sound_lib.input.Input.get_device_names()
|
||||
self.output_devices = sound_lib.output.Output.get_device_names()
|
||||
self.soundpacks = []
|
||||
[self.soundpacks.append(i) for i in os.listdir(paths.sound_path()) if os.path.isdir(paths.sound_path(i)) == True ]
|
||||
self.dialog.create_sound(self.input_devices, self.output_devices, self.soundpacks)
|
||||
self.dialog.set_value("sound", "volumeCtrl", self.config["sound"]["volume"]*100)
|
||||
self.dialog.set_value("sound", "input", self.config["sound"]["input_device"])
|
||||
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", "soundpack", self.config["sound"]["current_soundpack"])
|
||||
self.dialog.create_audio_services()
|
||||
if self.config["services"]["dropbox_token"] == "":
|
||||
self.dialog.services.set_dropbox(False)
|
||||
else:
|
||||
self.dialog.services.set_dropbox(True)
|
||||
widgetUtils.connect_event(self.dialog.services.dropbox, widgetUtils.BUTTON_PRESSED, self.manage_dropbox)
|
||||
self.dialog.set_value("services", "apiKey", self.config["sound"]["sndup_api_key"])
|
||||
self.dialog.realize()
|
||||
self.dialog.set_title(_(u"Account settings for %s") % (self.user,))
|
||||
self.response = self.dialog.get_response()
|
||||
|
||||
def save_configuration(self):
|
||||
if self.config["general"]["relative_times"] != self.dialog.get_value("general", "relative_time"):
|
||||
self.needs_restart = True
|
||||
self.config["general"]["relative_times"] = self.dialog.get_value("general", "relative_time")
|
||||
self.config["general"]["max_api_calls"] = self.dialog.get_value("general", "apiCalls")
|
||||
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.dialog.get_value("general", "persist_size") == '':
|
||||
self.config["general"]["persist_size"] =-1
|
||||
else:
|
||||
try:
|
||||
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"):
|
||||
self.needs_restart = True
|
||||
self.config["general"]["reverse_timelines"] = self.dialog.get_value("general", "reverse_timelines")
|
||||
rt = self.dialog.get_value("general", "retweet_mode")
|
||||
if rt == _(u"Ask"):
|
||||
self.config["general"]["retweet_mode"] = "ask"
|
||||
elif rt == _(u"Retweet without comments"):
|
||||
self.config["general"]["retweet_mode"] = "direct"
|
||||
else:
|
||||
self.config["general"]["retweet_mode"] = "comment"
|
||||
buffers_list = self.dialog.buffers.get_list()
|
||||
if set(self.config["general"]["buffer_order"]) != set(buffers_list) or buffers_list != self.config["general"]["buffer_order"]:
|
||||
self.needs_restart = True
|
||||
self.config["general"]["buffer_order"] = buffers_list
|
||||
|
||||
# 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")
|
||||
# pub.sendMessage("create-new-buffer", buffer="followers", account=self.user, create=self.config["other_buffers"]["show_followers"])
|
||||
# if self.config["other_buffers"]["show_friends"] != self.dialog.get_value("buffers", "friends"):
|
||||
# self.config["other_buffers"]["show_friends"] = self.dialog.get_value("buffers", "friends")
|
||||
# pub.sendMessage("create-new-buffer", buffer="friends", account=self.user, create=self.config["other_buffers"]["show_friends"])
|
||||
# if self.config["other_buffers"]["show_favourites"] != self.dialog.get_value("buffers", "favs"):
|
||||
# self.config["other_buffers"]["show_favourites"] = self.dialog.get_value("buffers", "favs")
|
||||
# pub.sendMessage("create-new-buffer", buffer="favourites", account=self.user, create=self.config["other_buffers"]["show_favourites"])
|
||||
# if self.config["other_buffers"]["show_blocks"] != self.dialog.get_value("buffers", "blocks"):
|
||||
# self.config["other_buffers"]["show_blocks"] = self.dialog.get_value("buffers", "blocks")
|
||||
# pub.sendMessage("create-new-buffer", buffer="blocked", account=self.user, create=self.config["other_buffers"]["show_blocks"])
|
||||
# if self.config["other_buffers"]["show_muted_users"] != self.dialog.get_value("buffers", "mutes"):
|
||||
# self.config["other_buffers"]["show_muted_users"] = self.dialog.get_value("buffers", "mutes")
|
||||
# pub.sendMessage("create-new-buffer", buffer="muted", account=self.user, create=self.config["other_buffers"]["show_muted_users"])
|
||||
# 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")
|
||||
# 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"):
|
||||
self.config["sound"]["input_device"] = self.dialog.sound.get("input")
|
||||
try:
|
||||
self.buffer.session.sound.input.set_device(self.buffer.session.sound.input.find_device_by_name(self.config["sound"]["input_device"]))
|
||||
except:
|
||||
self.config["sound"]["input_device"] = "default"
|
||||
if self.config["sound"]["output_device"] != self.dialog.sound.get("output"):
|
||||
self.config["sound"]["output_device"] = self.dialog.sound.get("output")
|
||||
try:
|
||||
self.buffer.session.sound.output.set_device(self.buffer.session.sound.output.find_device_by_name(self.config["sound"]["output_device"]))
|
||||
except:
|
||||
self.config["sound"]["output_device"] = "default"
|
||||
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"]["current_soundpack"] = self.dialog.sound.get("soundpack")
|
||||
self.buffer.session.sound.config = self.config["sound"]
|
||||
self.buffer.session.sound.check_soundpack()
|
||||
self.config["sound"]["sndup_api_key"] = self.dialog.get_value("services", "apiKey")
|
||||
|
||||
def toggle_state(self,*args,**kwargs):
|
||||
return self.dialog.buffers.change_selected_item()
|
||||
|
||||
def manage_autocomplete(self, *args, **kwargs):
|
||||
configuration = settings.autocompletionSettings(self.buffer.session.settings, self.buffer, self.window)
|
||||
|
||||
def add_ignored_client(self, *args, **kwargs):
|
||||
client = commonMessageDialogs.get_ignored_client()
|
||||
if client == None: return
|
||||
if client not in self.config["twitter"]["ignored_clients"]:
|
||||
self.config["twitter"]["ignored_clients"].append(client)
|
||||
self.dialog.ignored_clients.append(client)
|
||||
|
||||
def remove_ignored_client(self, *args, **kwargs):
|
||||
if self.dialog.ignored_clients.get_clients() == 0: return
|
||||
id = self.dialog.ignored_clients.get_client_id()
|
||||
self.config["twitter"]["ignored_clients"].pop(id)
|
||||
self.dialog.ignored_clients.remove_(id)
|
||||
|
||||
def manage_dropbox(self, *args, **kwargs):
|
||||
if self.dialog.services.get_dropbox() == _(u"Link your Dropbox account"):
|
||||
self.connect_dropbox()
|
||||
else:
|
||||
self.disconnect_dropbox()
|
||||
|
||||
def connect_dropbox(self):
|
||||
auth = dropbox_transfer.dropboxLogin(self.config)
|
||||
url = auth.get_url()
|
||||
self.dialog.services.show_dialog()
|
||||
webbrowser.open(url)
|
||||
resp = self.dialog.services.get_response()
|
||||
if resp == "":
|
||||
self.dialog.services.set_dropbox(False)
|
||||
else:
|
||||
try:
|
||||
auth.authorise(resp)
|
||||
self.dialog.services.set_dropbox()
|
||||
except:
|
||||
self.dialog.services.show_error()
|
||||
self.dialog.services.set_dropbox(False)
|
||||
|
||||
def disconnect_dropbox(self):
|
||||
self.config["services"]["dropbox_token"] = ""
|
||||
self.dialog.services.set_dropbox(False)
|
||||
|
||||
def get_buffers_list(self):
|
||||
all_buffers = ['home','mentions','dm','sent_dm','sent_tweets','favorites','followers','friends','blocks','muted','events']
|
||||
list_buffers = []
|
||||
hidden_buffers=[]
|
||||
for i in all_buffers:
|
||||
if i in self.config["general"]["buffer_order"]:
|
||||
list_buffers.append((i, True))
|
||||
else:
|
||||
hidden_buffers.append((i, False))
|
||||
list_buffers.extend(hidden_buffers)
|
||||
return list_buffers
|
||||
|
||||
def toggle_buffer_active(self, ev):
|
||||
change = self.dialog.buffers.get_event(ev)
|
||||
if change == True:
|
||||
self.dialog.buffers.change_selected_item()
|
@@ -1,45 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from wxUI.dialogs import trends
|
||||
import widgetUtils
|
||||
|
||||
class trendingTopicsController(object):
|
||||
def __init__(self, session):
|
||||
super(trendingTopicsController, self).__init__()
|
||||
self.countries = {}
|
||||
self.cities = {}
|
||||
self.dialog = trends.trendingTopicsDialog()
|
||||
self.information = session.twitter.twitter.get_available_trends()
|
||||
self.split_information()
|
||||
widgetUtils.connect_event(self.dialog.country, widgetUtils.RADIOBUTTON, self.get_places)
|
||||
widgetUtils.connect_event(self.dialog.city, widgetUtils.RADIOBUTTON, self.get_places)
|
||||
self.get_places()
|
||||
|
||||
def split_information(self):
|
||||
for i in self.information:
|
||||
if i["placeType"]["name"] == "Country":
|
||||
self.countries[i["name"]] = i["woeid"]
|
||||
else:
|
||||
self.cities[i["name"]] = i["woeid"]
|
||||
|
||||
def get_places(self, event=None):
|
||||
values = []
|
||||
if self.dialog.get_active() == "country":
|
||||
for i in self.information:
|
||||
if i["placeType"]["name"] == "Country":
|
||||
values.append(i["name"])
|
||||
elif self.dialog.get_active() == "city":
|
||||
for i in self.information:
|
||||
if i["placeType"]["name"] != "Country":
|
||||
values.append(i["name"])
|
||||
self.dialog.set(values)
|
||||
|
||||
def get_woeid(self):
|
||||
selected = self.dialog.get_item()
|
||||
if self.dialog.get_active() == "country":
|
||||
woeid = self.countries[selected]
|
||||
else:
|
||||
woeid = self.cities[selected]
|
||||
return woeid
|
||||
|
||||
def get_string(self):
|
||||
return self.dialog.get_item()
|
@@ -1,102 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import webbrowser
|
||||
import widgetUtils
|
||||
import output
|
||||
from wxUI.dialogs import update_profile, show_user
|
||||
from twython import TwythonError
|
||||
|
||||
class profileController(object):
|
||||
def __init__(self, session, user=None):
|
||||
super(profileController, self).__init__()
|
||||
self.file = None
|
||||
self.session = session
|
||||
self.user = user
|
||||
if user == None:
|
||||
self.dialog = update_profile.updateProfileDialog()
|
||||
self.get_data(screen_name=self.session.db["user_name"])
|
||||
self.fill_profile_fields()
|
||||
self.uploaded = False
|
||||
widgetUtils.connect_event(self.dialog.upload_image, widgetUtils.BUTTON_PRESSED, self.upload_image)
|
||||
else:
|
||||
self.dialog = show_user.showUserProfile()
|
||||
self.get_data(screen_name=self.user)
|
||||
string = self.get_user_info()
|
||||
self.dialog.set("text", string)
|
||||
self.dialog.set_title(_(u"Information for %s") % (self.data["screen_name"]))
|
||||
if self.data["url"] != None:
|
||||
self.dialog.enable_url()
|
||||
widgetUtils.connect_event(self.dialog.url, widgetUtils.BUTTON_PRESSED, self.visit_url)
|
||||
if self.dialog.get_response() == widgetUtils.OK and self.user == None:
|
||||
self.do_update()
|
||||
|
||||
def get_data(self, screen_name):
|
||||
self.data = self.session.twitter.twitter.show_user(screen_name=screen_name)
|
||||
|
||||
def fill_profile_fields(self):
|
||||
self.dialog.set_name(self.data["name"])
|
||||
if self.data["url"] != None:
|
||||
self.dialog.set_url(self.data["url"])
|
||||
if len(self.data["location"]) > 0:
|
||||
self.dialog.set_location(self.data["location"])
|
||||
if len(self.data["description"]) > 0:
|
||||
self.dialog.set_description(self.data["description"])
|
||||
|
||||
def get_image(self):
|
||||
file = self.dialog.upload_picture()
|
||||
if file != None:
|
||||
self.file = open(file, "rb")
|
||||
self.uploaded = True
|
||||
self.dialog.change_upload_button(self.uploaded)
|
||||
|
||||
def discard_image(self):
|
||||
self.file = None
|
||||
output.speak(_(u"Discarded"))
|
||||
self.uploaded = False
|
||||
self.dialog.change_upload_button(self.uploaded)
|
||||
|
||||
def upload_image(self, *args, **kwargs):
|
||||
if self.uploaded == False:
|
||||
self.get_image()
|
||||
elif self.uploaded == True:
|
||||
self.discard_image()
|
||||
|
||||
def do_update(self):
|
||||
if self.user != None: return
|
||||
name = self.dialog.get("name")
|
||||
description = self.dialog.get("description")
|
||||
location = self.dialog.get("location")
|
||||
url = self.dialog.get("url")
|
||||
if self.file != None:
|
||||
try:
|
||||
self.session.twitter.twitter.update_profile_image(image=self.file)
|
||||
except TwythonError as e:
|
||||
output.speak(u"Error %s. %s" % (e.error_code, e.msg))
|
||||
try:
|
||||
self.session.twitter.twitter.update_profile(name=name, description=description, location=location, url=url)
|
||||
except TwythonError as e:
|
||||
output.speak(u"Error %s. %s" % (e.error_code, e.msg))
|
||||
|
||||
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["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)
|
||||
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"Favourites: %s") % (self.data["favourites_count"])
|
||||
return string
|
||||
|
||||
def visit_url(self, *args, **kwargs):
|
||||
webbrowser.open_new_tab(self.data["url"])
|
@@ -1,73 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from wxUI.dialogs import userActions
|
||||
from pubsub import pub
|
||||
import re
|
||||
import widgetUtils
|
||||
import output
|
||||
from twython import TwythonError
|
||||
|
||||
class userActionsController(object):
|
||||
def __init__(self, buffer, users=[], default="follow"):
|
||||
super(userActionsController, self).__init__()
|
||||
self.buffer = buffer
|
||||
self.session = buffer.session
|
||||
self.dialog = userActions.UserActionsDialog(users, default)
|
||||
if self.dialog.get_response() == widgetUtils.OK:
|
||||
self.process_action()
|
||||
|
||||
def process_action(self):
|
||||
action = self.dialog.get_action()
|
||||
user = self.dialog.get_user()
|
||||
if user == "": return
|
||||
getattr(self, action)(user)
|
||||
|
||||
def follow(self, user):
|
||||
try:
|
||||
self.session.twitter.twitter.create_friendship(screen_name=user )
|
||||
except TwythonError as err:
|
||||
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
|
||||
|
||||
def unfollow(self, user):
|
||||
try:
|
||||
id = self.session.twitter.twitter.destroy_friendship(screen_name=user )
|
||||
except TwythonError as err:
|
||||
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
|
||||
|
||||
def mute(self, user):
|
||||
try:
|
||||
id = self.session.twitter.twitter.create_mute(screen_name=user )
|
||||
except TwythonError as err:
|
||||
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
|
||||
|
||||
def unmute(self, user):
|
||||
try:
|
||||
id = self.session.twitter.twitter.destroy_mute(screen_name=user )
|
||||
except TwythonError as err:
|
||||
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
|
||||
|
||||
def report(self, user):
|
||||
try:
|
||||
id = self.session.twitter.twitter.report_spam(screen_name=user )
|
||||
except TwythonError as err:
|
||||
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
|
||||
|
||||
def block(self, user):
|
||||
try:
|
||||
id = self.session.twitter.twitter.create_block(screen_name=user )
|
||||
except TwythonError as err:
|
||||
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
|
||||
|
||||
def unblock(self, user):
|
||||
try:
|
||||
id = self.session.twitter.twitter.destroy_block(screen_name=user )
|
||||
except TwythonError as err:
|
||||
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
|
||||
|
||||
def ignore_client(self, user):
|
||||
tweet = self.buffer.get_right_tweet()
|
||||
if tweet.has_key("sender"):
|
||||
output.speak(_(u"You can't ignore direct messages"))
|
||||
return
|
||||
client = re.sub(r"(?s)<.*?>", "", tweet["source"])
|
||||
if client not in self.session.settings["twitter"]["ignored_clients"]:
|
||||
self.session.settings["twitter"]["ignored_clients"].append(client)
|
5
src/db.py
Normal file
@@ -0,0 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
""" Handles storage from a durus database """
|
||||
class db(object):
|
||||
def __init__(self):
|
||||
self.settings = {}
|
@@ -0,0 +1,3 @@
|
||||
import gui, transfer, transfer_dialogs, platform
|
||||
if platform.system() != "Darwin":
|
||||
import dropbox
|
@@ -1,189 +0,0 @@
|
||||
# -*- 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/>.
|
||||
#
|
||||
############################################################
|
||||
import widgetUtils
|
||||
import wx_ui
|
||||
import wx_transfer_dialogs
|
||||
import dropbox_transfer, transfer
|
||||
import output
|
||||
import tempfile
|
||||
import sound
|
||||
import os
|
||||
import config
|
||||
from pubsub import pub
|
||||
from mysc.thread_utils import call_threaded
|
||||
import sound_lib
|
||||
import logging
|
||||
|
||||
log = logging.getLogger("extra.AudioUploader.audioUploader")
|
||||
class audioUploader(object):
|
||||
def __init__(self, configFile, completed_callback):
|
||||
self.config = configFile
|
||||
super(audioUploader, self).__init__()
|
||||
self.dialog = wx_ui.audioDialog(services=self.get_available_services())
|
||||
self.file = None
|
||||
self.recorded = False
|
||||
self.recording = None
|
||||
self.playing = None
|
||||
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.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.discard, widgetUtils.BUTTON_PRESSED, self.on_discard)
|
||||
if self.dialog.get_response() == widgetUtils.OK:
|
||||
self.postprocess()
|
||||
log.debug("Uploading file %s to %s..." % (self.file, self.dialog.get("services")))
|
||||
self.uploaderDialog = wx_transfer_dialogs.UploadDialog(self.file)
|
||||
output.speak(_(u"Attaching..."))
|
||||
if self.dialog.get("services") == "Dropbox":
|
||||
self.uploaderFunction = dropbox_transfer.dropboxUploader(filename=self.file, completed_callback=completed_callback, config=self.config)
|
||||
elif self.dialog.get("services") == "SNDUp":
|
||||
base_url = "http://sndup.net/post.php"
|
||||
if len(self.config["sound"]["sndup_api_key"]) > 0:
|
||||
url = base_url + '?apikey=' + self.config['sound']['sndup_api_key']
|
||||
else:
|
||||
url = base_url
|
||||
self.uploaderFunction = transfer.Upload(field='file', url=url, filename=self.file, completed_callback=completed_callback)
|
||||
elif self.dialog.get("services") == "TwUp":
|
||||
url = "http://api.twup.me/post.json"
|
||||
self.uploaderFunction = transfer.Upload(field='file', url=url, filename=self.file, completed_callback=completed_callback)
|
||||
pub.subscribe(self.uploaderDialog.update, "uploading")
|
||||
self.uploaderDialog.get_response()
|
||||
self.uploaderFunction.perform_threaded()
|
||||
|
||||
def get_available_services(self):
|
||||
services = []
|
||||
services.append("TwUp")
|
||||
if self.config["services"]["dropbox_token"] != "":
|
||||
services.append("Dropbox")
|
||||
services.append("SNDUp")
|
||||
return services
|
||||
|
||||
def on_pause(self, *args, **kwargs):
|
||||
if self.dialog.get("pause") == _(u"Pause"):
|
||||
self.recording.pause()
|
||||
self.dialog.set("pause", _(u"Resume"))
|
||||
elif self.dialog.get("pause") == _(u"Resume"):
|
||||
self.recording.play()
|
||||
self.dialog.set("pause", _(U"Pause"))
|
||||
|
||||
def on_record(self, *args, **kwargs):
|
||||
if self.recording != None:
|
||||
self.stop_recording()
|
||||
self.dialog.disable_control("pause")
|
||||
else:
|
||||
self.start_recording()
|
||||
self.dialog.enable_control("pause")
|
||||
|
||||
def start_recording(self):
|
||||
self.dialog.disable_control("attach_exists")
|
||||
self.file = tempfile.mktemp(suffix='.wav')
|
||||
self.recording = sound.recording(self.file)
|
||||
self.recording.play()
|
||||
self.dialog.set("record", _(u"Stop"))
|
||||
output.speak(_(u"Recording"))
|
||||
|
||||
def stop_recording(self):
|
||||
self.recording.stop()
|
||||
self.recording.free()
|
||||
output.speak(_(u"Stopped"))
|
||||
self.recorded = True
|
||||
self.dialog.set("record", _(u"Record"))
|
||||
self.file_attached()
|
||||
|
||||
def file_attached(self):
|
||||
self.dialog.set("pause", _(u"Pause"))
|
||||
self.dialog.disable_control("record")
|
||||
self.dialog.enable_control("play")
|
||||
self.dialog.enable_control("discard")
|
||||
self.dialog.disable_control("attach_exists")
|
||||
self.dialog.enable_control("attach")
|
||||
self.dialog.play.SetFocus()
|
||||
|
||||
def on_discard(self, *args, **kwargs):
|
||||
if self.playing:
|
||||
self._stop()
|
||||
if self.recording != None:
|
||||
self.dialog.disable_control("attach")
|
||||
self.dialog.disable_control("play")
|
||||
self.file = None
|
||||
self.dialog.enable_control("record")
|
||||
self.dialog.enable_control("attach_exists")
|
||||
self.dialog.record.SetFocus()
|
||||
self.dialog.disable_control("discard")
|
||||
self.recording = None
|
||||
output.speak(_(u"Discarded"))
|
||||
|
||||
def on_play(self, *args, **kwargs):
|
||||
if not self.playing:
|
||||
call_threaded(self._play)
|
||||
else:
|
||||
self._stop()
|
||||
|
||||
def _play(self):
|
||||
output.speak(_(u"Playing..."))
|
||||
# try:
|
||||
self.playing = sound_lib.stream.FileStream(file=unicode(self.file), flags=sound_lib.stream.BASS_UNICODE)
|
||||
self.playing.play()
|
||||
self.dialog.set("play", _(u"Stop"))
|
||||
try:
|
||||
while self.playing.is_playing:
|
||||
pass
|
||||
self.dialog.set("play", _(u"Play"))
|
||||
self.playing.free()
|
||||
self.playing = None
|
||||
except:
|
||||
pass
|
||||
|
||||
def _stop(self):
|
||||
output.speak(_(u"Stopped"))
|
||||
self.playing.stop()
|
||||
self.playing.free()
|
||||
self.dialog.set("play", _(u"Play"))
|
||||
self.playing = None
|
||||
|
||||
def postprocess(self):
|
||||
if self.file.lower().endswith('.wav'):
|
||||
output.speak(_(u"Recoding audio..."))
|
||||
sound.recode_audio(self.file)
|
||||
self.wav_file = self.file
|
||||
self.file = '%s.ogg' % self.file[:-4]
|
||||
|
||||
def cleanup(self):
|
||||
if self.playing and self.playing.is_playing:
|
||||
self.playing.stop()
|
||||
if self.recording != None:
|
||||
if self.recording.is_playing:
|
||||
self.recording.stop()
|
||||
try:
|
||||
self.recording.free()
|
||||
except:
|
||||
pass
|
||||
os.remove(self.file)
|
||||
if hasattr(self, 'wav_file'):
|
||||
os.remove(self.wav_file)
|
||||
del(self.wav_file)
|
||||
if hasattr(self, 'wav_file') and os.path.exists(self.file):
|
||||
os.remove(self.file)
|
||||
|
||||
|
||||
def on_attach_exists(self, *args, **kwargs):
|
||||
self.file = self.dialog.get_file()
|
||||
if self.file != False:
|
||||
self.file_attached()
|
||||
|
@@ -3,16 +3,14 @@ import threading
|
||||
import time
|
||||
import os
|
||||
import exceptions
|
||||
import wx
|
||||
import dropbox
|
||||
import logging
|
||||
import application
|
||||
from keys import keyring
|
||||
import config
|
||||
from mysc import event
|
||||
from utils import *
|
||||
from dropbox.rest import ErrorResponse
|
||||
from StringIO import StringIO
|
||||
from pubsub import pub
|
||||
|
||||
log = logging.getLogger("extra.AudioUploader.dropbox_transfer")
|
||||
class UnauthorisedError(exceptions.Exception):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(UnauthorisedError, self).__init__(*args, **kwargs)
|
||||
@@ -41,33 +39,29 @@ class newChunkedUploader(dropbox.client.ChunkedUploader):
|
||||
self.offset = reply['offset']
|
||||
|
||||
class dropboxLogin(object):
|
||||
def __init__(self, config):
|
||||
log.debug("Trying to login in Dropbox...")
|
||||
def __init__(self):
|
||||
self.logged = False
|
||||
self.config = config
|
||||
self.app_key = "c8ikm0gexqvovol"
|
||||
self.app_secret = "gvvi6fzfecooast"
|
||||
|
||||
def get_url(self):
|
||||
log.debug("Getting autorisation URL...")
|
||||
self.flow = dropbox.client.DropboxOAuth2FlowNoRedirect(keyring.get("dropbox_api_key"), keyring.get("dropbox_api_secret"))
|
||||
self.flow = dropbox.client.DropboxOAuth2FlowNoRedirect(self.app_key, self.app_secret)
|
||||
return self.flow.start()
|
||||
|
||||
def authorise(self, code):
|
||||
log.debug("Authorising " + application.name + " to Dropbox...")
|
||||
access_token, user_id = self.flow.finish(code)
|
||||
log.debug("Saving tokens...")
|
||||
self.config["services"]["dropbox_token"] = access_token
|
||||
config.main["services"]["dropbox_token"] = access_token
|
||||
self.logged = True
|
||||
|
||||
class dropboxUploader(object):
|
||||
def __init__(self, config, filename, completed_callback, short_url=False):
|
||||
if config["services"]["dropbox_token"] != "":
|
||||
log.debug("logging in Dropbox...")
|
||||
self.client = dropbox.client.DropboxClient(config["services"]["dropbox_token"])
|
||||
def __init__(self, filename, completed_callback, wxDialog, short_url=False):
|
||||
if config.main["services"]["dropbox_token"] != "":
|
||||
self.client = dropbox.client.DropboxClient(config.main["services"]["dropbox_token"])
|
||||
else:
|
||||
log.error("Dropbox is not authorised for this session.")
|
||||
raise UnauthorisedError("You need to authorise " + application.name)
|
||||
raise UnauthorisedError("You need authorise TWBlue")
|
||||
self.filename = filename
|
||||
self.short_url = short_url
|
||||
self.wxDialog = wxDialog
|
||||
self.file = open(self.filename, "rb")
|
||||
self.file_size = os.path.getsize(self.filename)
|
||||
self.uploader = newChunkedUploader(client=self.client, file_obj=self.file, length=self.file_size, callback=self.process)
|
||||
@@ -76,7 +70,6 @@ class dropboxUploader(object):
|
||||
self.background_thread = None
|
||||
self.current = 0
|
||||
self.transfer_rate = 0
|
||||
log.debug("File Size: %d " % (self.file_size,))
|
||||
|
||||
def elapsed_time(self):
|
||||
if not self.start_time:
|
||||
@@ -84,7 +77,6 @@ class dropboxUploader(object):
|
||||
return time.time() - self.start_time
|
||||
|
||||
def perform_transfer(self):
|
||||
log.debug("Starting transfer...")
|
||||
self.start_time = time.time()
|
||||
while self.uploader.offset < self.file_size:
|
||||
self.uploader.upload_chunked(self.file_size/100)
|
||||
@@ -102,7 +94,9 @@ class dropboxUploader(object):
|
||||
progress["eta"] = (progress["total"] - progress["current"]) / self.transfer_rate
|
||||
else:
|
||||
progress["eta"] = 0
|
||||
pub.sendMessage("uploading", data=progress)
|
||||
info = event.event(event.EVT_OBJECT, 1)
|
||||
info.SetItem(progress)
|
||||
wx.PostEvent(self.wxDialog, info)
|
||||
|
||||
def perform_threaded(self):
|
||||
self.background_thread = threading.Thread(target=self.perform_transfer)
|
||||
@@ -110,12 +104,10 @@ class dropboxUploader(object):
|
||||
self.background_thread.start()
|
||||
|
||||
def transfer_completed(self):
|
||||
log.debug("Transfer completed")
|
||||
self.uploader.finish(os.path.basename(self.filename))
|
||||
if callable(self.completed_callback):
|
||||
self.completed_callback()
|
||||
|
||||
def get_url(self):
|
||||
original = "%s" % (self.client.media(os.path.basename(self.filename))["url"])
|
||||
return original
|
||||
# .replace("dl=0", "dl=1")
|
||||
original = "%s" % (self.client.share(os.path.basename(self.filename), False)["url"])
|
||||
return original.replace("dl=0", "dl=1")
|
191
src/extra/AudioUploader/gui.py
Normal file
@@ -0,0 +1,191 @@
|
||||
# -*- 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/>.
|
||||
#
|
||||
############################################################
|
||||
import wx
|
||||
import output
|
||||
import tempfile
|
||||
import sound
|
||||
import os
|
||||
import config
|
||||
from mysc.thread_utils import call_threaded
|
||||
import sound_lib
|
||||
|
||||
class audioDialog(wx.Dialog):
|
||||
def __init__(self, parent):
|
||||
self.parent = parent
|
||||
wx.Dialog.__init__(self, None, -1, _(u"Attach audio"))
|
||||
self.file = None
|
||||
self.recorded = False
|
||||
self.recording = None
|
||||
self.playing = None
|
||||
panel = wx.Panel(self)
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
self.play = wx.Button(panel, -1, _(u"Play"))
|
||||
self.play.Bind(wx.EVT_BUTTON, self.onPlay)
|
||||
self.play.Disable()
|
||||
self.pause = wx.Button(panel, -1, _(u"Pause"))
|
||||
self.pause.Bind(wx.EVT_BUTTON, self.onPause)
|
||||
self.pause.Disable()
|
||||
self.record = wx.Button(panel, -1, _(u"Record"))
|
||||
self.record.Bind(wx.EVT_BUTTON, self.onRecord)
|
||||
self.record.SetFocus()
|
||||
self.attach_exists = wx.Button(panel, -1, _(u"Add an existing file"))
|
||||
self.attach_exists.Bind(wx.EVT_BUTTON, self.onAttach)
|
||||
self.discard = wx.Button(panel, -1, _(u"Discard"))
|
||||
self.discard.Bind(wx.EVT_BUTTON, self.onDiscard)
|
||||
self.discard.Disable()
|
||||
label = wx.StaticText(panel, -1, _(u"Upload to"))
|
||||
self.services = wx.ComboBox(panel, -1, choices=self.get_available_services(), value=self.get_available_services()[0], style=wx.CB_READONLY)
|
||||
servicesBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
servicesBox.Add(label)
|
||||
servicesBox.Add(self.services)
|
||||
self.attach = wx.Button(panel, wx.ID_OK, _(u"Attach"))
|
||||
self.attach.Disable()
|
||||
cancel = wx.Button(panel, wx.ID_CANCEL, _(u"Cancel"))
|
||||
sizer.Add(self.play)
|
||||
sizer.Add(self.pause)
|
||||
sizer.Add(self.record)
|
||||
sizer.Add(self.attach_exists)
|
||||
sizer.Add(self.discard)
|
||||
sizer.Add(self.attach)
|
||||
|
||||
def get_available_services(self):
|
||||
services = []
|
||||
if config.main["services"]["dropbox_token"] != "":
|
||||
services.append("Dropbox")
|
||||
services.append("TwUp")
|
||||
services.append("SNDUp")
|
||||
return services
|
||||
|
||||
def onPause(self, ev):
|
||||
if self.pause.GetLabel() == _(u"Pause"):
|
||||
self.recording.pause()
|
||||
self.pause.SetLabel(_(u"Resume"))
|
||||
elif self.pause.GetLabel() == _(u"Resume"):
|
||||
self.recording.play()
|
||||
self.pause.SetLabel(_(U"Pause"))
|
||||
|
||||
def onRecord(self, ev):
|
||||
if self.recording != None:
|
||||
self.stop_recording()
|
||||
self.pause.Disable()
|
||||
else:
|
||||
self.start_recording()
|
||||
self.pause.Enable()
|
||||
|
||||
def start_recording(self):
|
||||
self.attach_exists.Disable()
|
||||
self.file = tempfile.mktemp(suffix='.wav')
|
||||
self.recording = sound.recording(self.file)
|
||||
self.recording.play()
|
||||
self.record.SetLabel(_(u"Stop recording"))
|
||||
output.speak(_(u"Recording"))
|
||||
|
||||
def stop_recording(self):
|
||||
self.recording.stop()
|
||||
self.recording.free()
|
||||
output.speak(_(u"Stopped"))
|
||||
self.recorded = True
|
||||
self.record.SetLabel(_(u"Record"))
|
||||
self.file_attached()
|
||||
|
||||
def file_attached(self):
|
||||
self.pause.SetLabel(_(u"Pause"))
|
||||
self.record.Disable()
|
||||
self.play.Enable()
|
||||
self.discard.Enable()
|
||||
self.attach_exists.Disable()
|
||||
self.attach.Enable()
|
||||
self.play.SetFocus()
|
||||
|
||||
def onDiscard(self, evt):
|
||||
evt.Skip()
|
||||
if self.playing:
|
||||
self._stop()
|
||||
if self.recording != None:
|
||||
self.attach.Disable()
|
||||
self.play.Disable()
|
||||
self.file = None
|
||||
self.record.Enable()
|
||||
self.attach_exists.Enable()
|
||||
self.record.SetFocus()
|
||||
self.discard.Disable()
|
||||
self.recording = None
|
||||
output.speak(_(u"Discarded"))
|
||||
|
||||
def onPlay(self, evt):
|
||||
evt.Skip()
|
||||
if not self.playing:
|
||||
call_threaded(self._play)
|
||||
else:
|
||||
self._stop()
|
||||
|
||||
def _play(self):
|
||||
output.speak(_(u"Playing..."))
|
||||
# try:
|
||||
self.playing = sound_lib.stream.FileStream(file=unicode(self.file), flags=sound_lib.stream.BASS_UNICODE)
|
||||
self.playing.play()
|
||||
self.play.SetLabel(_(u"Stop"))
|
||||
try:
|
||||
while self.playing.is_playing:
|
||||
pass
|
||||
self.play.SetLabel(_(u"Play"))
|
||||
self.playing.free()
|
||||
self.playing = None
|
||||
except:
|
||||
pass
|
||||
|
||||
def _stop(self):
|
||||
output.speak(_(u"Stopped"))
|
||||
self.playing.stop()
|
||||
self.playing.free()
|
||||
self.play.SetLabel(_(u"Play"))
|
||||
self.playing = None
|
||||
|
||||
def postprocess(self):
|
||||
if self.file.lower().endswith('.wav'):
|
||||
output.speak(_(u"Recoding audio..."))
|
||||
sound.recode_audio(self.file)
|
||||
self.wav_file = self.file
|
||||
self.file = '%s.ogg' % self.file[:-4]
|
||||
|
||||
def cleanup(self):
|
||||
if self.playing and self.playing.is_playing:
|
||||
self.playing.stop()
|
||||
if self.recording != None:
|
||||
if self.recording.is_playing:
|
||||
self.recording.stop()
|
||||
try:
|
||||
self.recording.free()
|
||||
except:
|
||||
pass
|
||||
os.remove(self.file)
|
||||
if hasattr(self, 'wav_file'):
|
||||
os.remove(self.wav_file)
|
||||
del(self.wav_file)
|
||||
if hasattr(self, 'wav_file') and os.path.exists(self.file):
|
||||
os.remove(self.file)
|
||||
|
||||
|
||||
def onAttach(self, ev):
|
||||
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:
|
||||
return
|
||||
self.file = openFileDialog.GetPath()
|
||||
self.file_attached()
|
||||
ev.Skip()
|
@@ -4,17 +4,17 @@ import sys
|
||||
import threading
|
||||
import time
|
||||
import json
|
||||
import logging
|
||||
import wx
|
||||
from mysc import event
|
||||
from utils import *
|
||||
from pubsub import pub
|
||||
|
||||
log = logging.getLogger("extra.AudioUploader.transfer")
|
||||
#__all__ = ['TransferDialog', 'DownloadDialog', 'UploadDialog']
|
||||
|
||||
class Transfer(object):
|
||||
|
||||
def __init__(self, url=None, filename=None, follow_location=True, completed_callback=None, verbose=False, *args, **kwargs):
|
||||
def __init__(self, url=None, filename=None, follow_location=True, completed_callback=None, verbose=False, wxDialog=None, *args, **kwargs):
|
||||
self.url = url
|
||||
self.filename = filename
|
||||
log.debug("Uploading audio to %s, filename %s" % (url, filename))
|
||||
self.curl = pycurl.Curl()
|
||||
self.start_time = None
|
||||
self.completed_callback = completed_callback
|
||||
@@ -26,6 +26,7 @@ class Transfer(object):
|
||||
self.curl.setopt(self.curl.HTTP_VERSION, self.curl.CURL_HTTP_VERSION_1_0)
|
||||
self.curl.setopt(self.curl.FOLLOWLOCATION, int(follow_location))
|
||||
self.curl.setopt(self.curl.VERBOSE, int(verbose))
|
||||
self.wxDialog = wxDialog
|
||||
super(Transfer, self).__init__(*args, **kwargs)
|
||||
|
||||
def elapsed_time(self):
|
||||
@@ -51,15 +52,15 @@ class Transfer(object):
|
||||
progress["eta"] = (progress["total"] - progress["current"]) / self.transfer_rate
|
||||
else:
|
||||
progress["eta"] = 0
|
||||
pub.sendMessage("uploading", data=progress)
|
||||
info = event.event(event.EVT_OBJECT, 1)
|
||||
info.SetItem(progress)
|
||||
wx.PostEvent(self.wxDialog, info)
|
||||
|
||||
def perform_transfer(self):
|
||||
log.debug("starting upload...")
|
||||
self.start_time = time.time()
|
||||
self.curl.perform()
|
||||
self.curl.close()
|
||||
log.debug("Upload finished.")
|
||||
self.complete_transfer()
|
||||
wx.CallAfter(self.complete_transfer)
|
||||
|
||||
def perform_threaded(self):
|
||||
self.background_thread = threading.Thread(target=self.perform_transfer)
|
||||
|
@@ -1,12 +1,14 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import wx
|
||||
from mysc import event
|
||||
from utils import *
|
||||
import widgetUtils
|
||||
|
||||
class TransferDialog(widgetUtils.BaseDialog):
|
||||
__all__ = ['TransferDialog', 'DownloadDialog', 'UploadDialog']
|
||||
|
||||
class TransferDialog(wx.Dialog):
|
||||
|
||||
def __init__(self, filename, *args, **kwargs):
|
||||
super(TransferDialog, self).__init__(parent=None, id=wx.NewId(), *args, **kwargs)
|
||||
super(TransferDialog, self).__init__(*args, **kwargs)
|
||||
self.pane = wx.Panel(self)
|
||||
self.progress_bar = wx.Gauge(parent=self.pane)
|
||||
fileBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
@@ -35,7 +37,7 @@ class TransferDialog(widgetUtils.BaseDialog):
|
||||
self.eta = wx.TextCtrl(self.pane, -1, style=wx.TE_READONLY|wx.TE_MULTILINE, value="Unknown", size=(200, 100))
|
||||
etaBox.Add(etaLabel)
|
||||
etaBox.Add(self.eta)
|
||||
self.create_buttons()
|
||||
# self.create_buttons()
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
sizer.Add(fileBox)
|
||||
sizer.Add(currentAmountBox)
|
||||
@@ -44,8 +46,10 @@ class TransferDialog(widgetUtils.BaseDialog):
|
||||
sizer.Add(etaBox)
|
||||
sizer.Add(self.progress_bar)
|
||||
self.pane.SetSizerAndFit(sizer)
|
||||
self.Bind(event.MyEVT_OBJECT, self.update)
|
||||
|
||||
def update(self, data):
|
||||
def update(self, ev):
|
||||
data = ev.GetItem()
|
||||
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.total_size.SetValue, convert_bytes(data["total"]))
|
||||
@@ -55,12 +59,7 @@ class TransferDialog(widgetUtils.BaseDialog):
|
||||
|
||||
def create_buttons(self):
|
||||
self.cancel_button = wx.Button(parent=self.pane, id=wx.ID_CANCEL)
|
||||
|
||||
def get_response(self):
|
||||
self.Show()
|
||||
|
||||
def destroy(self):
|
||||
self.Destroy()
|
||||
self.cancel_button.Bind(wx.EVT_BUTTON, self.on_cancel)
|
||||
|
||||
class UploadDialog(TransferDialog):
|
||||
|
@@ -1,78 +0,0 @@
|
||||
# -*- 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/>.
|
||||
#
|
||||
############################################################
|
||||
import wx
|
||||
import widgetUtils
|
||||
import output
|
||||
import logging
|
||||
log = logging.getLogger("extra.AudioUploader.wx_UI")
|
||||
|
||||
class audioDialog(widgetUtils.BaseDialog):
|
||||
def __init__(self, services):
|
||||
log.debug("creating audio dialog.")
|
||||
super(audioDialog, self).__init__(None, -1, _(u"Attach audio"))
|
||||
panel = wx.Panel(self)
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
btnSizer2 = wx.BoxSizer(wx.HORIZONTAL)
|
||||
|
||||
self.play = wx.Button(panel, -1, _(u"Play"))
|
||||
self.play.Disable()
|
||||
self.pause = wx.Button(panel, -1, _(u"Pause"))
|
||||
self.pause.Disable()
|
||||
self.record = wx.Button(panel, -1, _(u"Record"))
|
||||
self.record.SetFocus()
|
||||
self.attach_exists = wx.Button(panel, -1, _(u"Add an existing file"))
|
||||
self.discard = wx.Button(panel, -1, _(u"Discard"))
|
||||
self.discard.Disable()
|
||||
label = wx.StaticText(panel, -1, _(u"Upload to"))
|
||||
self.services = wx.ComboBox(panel, -1, choices=services, value=services[0], style=wx.CB_READONLY)
|
||||
servicesBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
servicesBox.Add(label, 0, wx.ALL, 5)
|
||||
servicesBox.Add(self.services, 0, wx.ALL, 5)
|
||||
self.attach = wx.Button(panel, wx.ID_OK, _(u"Attach"))
|
||||
self.attach.Disable()
|
||||
cancel = wx.Button(panel, wx.ID_CANCEL, _(u"Cancel"))
|
||||
btnSizer.Add(self.play, 0, wx.ALL, 5)
|
||||
btnSizer.Add(self.pause, 0, wx.ALL, 5)
|
||||
btnSizer.Add(self.record, 0, wx.ALL, 5)
|
||||
btnSizer2.Add(self.attach_exists, 0, wx.ALL, 5)
|
||||
btnSizer2.Add(self.discard, 0, wx.ALL, 5)
|
||||
btnSizer2.Add(self.attach, 0, wx.ALL, 5)
|
||||
btnSizer2.Add(cancel, 0, wx.ALL, 5)
|
||||
sizer.Add(servicesBox, 0, wx.ALL, 5)
|
||||
sizer.Add(btnSizer, 0, wx.ALL, 5)
|
||||
sizer.Add(btnSizer2, 0, wx.ALL, 5)
|
||||
panel.SetSizer(sizer)
|
||||
self.SetClientSize(sizer.CalcMin())
|
||||
|
||||
def enable_control(self, control):
|
||||
log.debug("Enabling control %s" % (control,))
|
||||
if hasattr(self, control):
|
||||
getattr(self, control).Enable()
|
||||
|
||||
def disable_control(self, control):
|
||||
log.debug("Disabling control %s" % (control,))
|
||||
if hasattr(self, control):
|
||||
getattr(self, control).Disable()
|
||||
|
||||
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)
|
||||
if openFileDialog.ShowModal() == wx.ID_CANCEL:
|
||||
return False
|
||||
return openFileDialog.GetPath()
|
@@ -1 +1 @@
|
||||
from soundsTutorial import soundsTutorial
|
||||
import gui
|
@@ -1,25 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from gi.repository import Gtk
|
||||
import widgetUtils
|
||||
|
||||
class soundsTutorialDialog(Gtk.Dialog):
|
||||
def __init__(self, actions):
|
||||
super(soundsTutorialDialog, self).__init__("Sounds tutorial", None, 0, (Gtk.STOCK_CANCEL, widgetUtils.CANCEL))
|
||||
box = self.get_content_area()
|
||||
label = Gtk.Label("Press enter for listen the sound")
|
||||
self.list = widgetUtils.list("Action")
|
||||
self.populate_actions(actions)
|
||||
lBox = Gtk.Box(spacing=6)
|
||||
lBox.add(label)
|
||||
lBox.add(self.list.list)
|
||||
box.add(lBox)
|
||||
self.play = Gtk.Button("Play")
|
||||
box.add(self.play)
|
||||
self.show_all()
|
||||
|
||||
def populate_actions(self, actions):
|
||||
for i in actions:
|
||||
self.list.insert_item(i)
|
||||
|
||||
def get_selected(self):
|
||||
return self.list.get_selected()
|
61
src/extra/SoundsTutorial/gui.py
Normal file
@@ -0,0 +1,61 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import wx
|
||||
import config
|
||||
import os
|
||||
import paths
|
||||
import sound
|
||||
|
||||
class soundsTutorial(wx.Dialog):
|
||||
def __init__(self):
|
||||
self.actions = [
|
||||
_(u"The tweet may contain a playable audio"),
|
||||
_(u"A timeline has been created"),
|
||||
_(u"A timeline has been deleted"),
|
||||
_(u"You've received a direct message"),
|
||||
_(u"You've sent a direct message"),
|
||||
_(u"A bug has happened"),
|
||||
_(u"You've added a tweet to your favourites"),
|
||||
_(u"Someone's favourites have been updated"),
|
||||
_(u"The tweet has coordinates to determine its location"),
|
||||
_(u"There are no more tweets to read"),
|
||||
_(u"A list has a new tweet"),
|
||||
_(u"You can't add any more characters on the tweet"),
|
||||
_(u"You've been mentioned "),
|
||||
_(u"A new event has happened"),
|
||||
_(u"TW Blue is ready "),
|
||||
_(u"You've replied"),
|
||||
_(u"You've retweeted"),
|
||||
_(u"A search has been updated"),
|
||||
_(u"the buffer for trending topics has been updated"),
|
||||
_(u"There's a new tweet in the main buffer"),
|
||||
_(u"You've sent a tweet"),
|
||||
_(u"There's a new tweet in a timeline"),
|
||||
_(u"You have a new follower"),
|
||||
_(u"You've turned the volume up or down")]
|
||||
self.files = os.listdir(paths.sound_path("default"))
|
||||
super(soundsTutorial, self).__init__(None, -1)
|
||||
if len(self.actions) > len(self.files):
|
||||
wx.MessageDialog(None, _(u"It seems as though the currently used sound pack needs an update. %i fails are still be required to use this function. Make sure to obtain the needed lacking sounds or to contact with the sound pack developer.") % (len(self.actions) - len(self.files)), _(u"Error"), wx.ICON_ERROR).ShowModal()
|
||||
self.Destroy()
|
||||
self.SetTitle(_(u"Sounds tutorial"))
|
||||
panel = wx.Panel(self)
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
label = wx.StaticText(panel, -1, _(u"Press enter to listen to the sound for the selected event"))
|
||||
self.items = wx.ListBox(panel, 1, choices=self.actions, style=wx.LB_SINGLE)
|
||||
self.items.SetSelection(0)
|
||||
listBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
listBox.Add(label)
|
||||
listBox.Add(self.items)
|
||||
play = wx.Button(panel, 1, (u"Play"))
|
||||
play.SetDefault()
|
||||
self.Bind(wx.EVT_BUTTON, self.onPlay, play)
|
||||
close = wx.Button(panel, wx.ID_CANCEL)
|
||||
btnBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
btnBox.Add(play)
|
||||
btnBox.Add(close)
|
||||
sizer.Add(listBox)
|
||||
sizer.Add(btnBox)
|
||||
panel.SetSizer(sizer)
|
||||
|
||||
def onPlay(self, ev):
|
||||
sound.player.play(self.files[self.items.GetSelection()])
|
@@ -1,11 +0,0 @@
|
||||
#Reverse sort, by Bill Dengler <codeofdusk@gmail.com> for use in TWBlue http://twblue.es
|
||||
def invert_tuples(t):
|
||||
"Invert a list of tuples, so that the 0th element becomes the -1th, and the -1th becomes the 0th."
|
||||
res=[]
|
||||
for i in t:
|
||||
res.append(i[::-1])
|
||||
return res
|
||||
|
||||
def reverse_sort(t):
|
||||
"Sorts a list of tuples/lists by their last elements, not their first."
|
||||
return invert_tuples(sorted(invert_tuples(t)))
|
@@ -1,34 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import platform
|
||||
import widgetUtils
|
||||
import os
|
||||
import paths
|
||||
import logging
|
||||
log = logging.getLogger("extra.SoundsTutorial.soundsTutorial")
|
||||
import soundsTutorial_constants
|
||||
if platform.system() == "Windows":
|
||||
import wx_ui as UI
|
||||
elif platform.system() == "Linux":
|
||||
import gtk_ui as UI
|
||||
|
||||
class soundsTutorial(object):
|
||||
def __init__(self, sessionObject):
|
||||
log.debug("Creating sounds tutorial object...")
|
||||
super(soundsTutorial, self).__init__()
|
||||
self.session = sessionObject
|
||||
self.actions = []
|
||||
log.debug("Loading actions for sounds tutorial...")
|
||||
[self.actions.append(i[1]) for i in soundsTutorial_constants.actions]
|
||||
self.files = []
|
||||
log.debug("Searching sound files...")
|
||||
[self.files.append(i[0]) for i in soundsTutorial_constants.actions]
|
||||
log.debug("Creating dialog...")
|
||||
self.dialog = UI.soundsTutorialDialog(self.actions)
|
||||
widgetUtils.connect_event(self.dialog.play, widgetUtils.BUTTON_PRESSED, self.on_play)
|
||||
self.dialog.get_response()
|
||||
|
||||
def on_play(self, *args, **kwargs):
|
||||
try:
|
||||
self.session.sound.play(self.files[self.dialog.get_selection()]+".ogg")
|
||||
except:
|
||||
log.exception("Error playing the %s sound" % (self.files[self.dialog.items.GetSelection()],))
|
@@ -1,27 +0,0 @@
|
||||
#-*- coding: utf-8 -*-
|
||||
import reverse_sort
|
||||
import application
|
||||
actions = reverse_sort.reverse_sort([ ("audio", _(u"Audio tweet.")),
|
||||
("create_timeline", _(u"User timeline buffer created.")),
|
||||
("delete_timeline", _(u"Buffer destroied.")),
|
||||
("dm_received", _(u"Direct message received.")),
|
||||
("dm_sent", _(u"Direct message sent.")),
|
||||
("error", _(u"Error.")),
|
||||
("favourite", _(u"Tweet favorited.")),
|
||||
("favourites_timeline_updated", _(u"Favourites buffer updated.")),
|
||||
("geo", _(u"Geotweet.")),
|
||||
("limit", _(u"Boundary reached.")),
|
||||
("list_tweet", _(u"List updated.")),
|
||||
("max_length", _(u"Too many characters.")),
|
||||
("mention_received", _(u"Mention received.")),
|
||||
("new_event", _(u"New event.")),
|
||||
("ready", _(unicode(application.name+" is ready."))),
|
||||
("reply_send", _(u"Mention sent.")),
|
||||
("retweet_send", _(u"Tweet retweeted.")),
|
||||
("search_updated", _(u"Search buffer updated.")),
|
||||
("tweet_received", _(u"Tweet received.")),
|
||||
("tweet_send", _(u"Tweet sent.")),
|
||||
("trends_updated", _(u"Trending topics buffer updated.")),
|
||||
("tweet_timeline", _(u"New tweet in user timeline buffer.")),
|
||||
("update_followers", _(u"New follower.")),
|
||||
("volume_changed", _(u"Volume changed."))])
|
@@ -1,29 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import wx
|
||||
import widgetUtils
|
||||
|
||||
class soundsTutorialDialog(widgetUtils.BaseDialog):
|
||||
def __init__(self, actions):
|
||||
super(soundsTutorialDialog, self).__init__(None, -1)
|
||||
self.SetTitle(_(u"Sounds tutorial"))
|
||||
panel = wx.Panel(self)
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
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.SetSelection(0)
|
||||
listBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
listBox.Add(label)
|
||||
listBox.Add(self.items)
|
||||
self.play = wx.Button(panel, 1, (u"Play"))
|
||||
self.play.SetDefault()
|
||||
close = wx.Button(panel, wx.ID_CANCEL)
|
||||
btnBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
btnBox.Add(self.play)
|
||||
btnBox.Add(close)
|
||||
sizer.Add(listBox)
|
||||
sizer.Add(btnBox)
|
||||
panel.SetSizer(sizer)
|
||||
self.SetClientSize(sizer.CalcMin())
|
||||
|
||||
def get_selection(self):
|
||||
return self.items.GetSelection()
|
@@ -1,4 +0,0 @@
|
||||
import spellchecker
|
||||
import platform
|
||||
if platform.system() == "Windows":
|
||||
from wx_ui import *
|
105
src/extra/SpellChecker/gui.py
Normal file
@@ -0,0 +1,105 @@
|
||||
# -*- 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/>.
|
||||
#
|
||||
############################################################
|
||||
import wx
|
||||
import output
|
||||
import config
|
||||
import languageHandler
|
||||
from enchant.checker import SpellChecker
|
||||
from enchant.errors import DictNotFoundError
|
||||
|
||||
class spellCheckerDialog(wx.Dialog):
|
||||
def __init__(self, text, dictionary):
|
||||
super(spellCheckerDialog, self).__init__(None, 1)
|
||||
try:
|
||||
if config.main["general"]["language"] == "system": self.checker = SpellChecker()
|
||||
else: self.checker = SpellChecker(languageHandler.getLanguage())
|
||||
self.checker.set_text(text)
|
||||
except DictNotFoundError:
|
||||
wx.MessageDialog(None, _(u"A bug has happened. There are no dictionaries available for the selected language in TW Blue"), _(u"Error"), wx.ICON_ERROR).ShowModal()
|
||||
self.Destroy()
|
||||
panel = wx.Panel(self)
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
word = wx.StaticText(panel, -1, _(u"Mis-spelled word"))
|
||||
self.word = wx.TextCtrl(panel, -1)
|
||||
wordBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
wordBox.Add(word)
|
||||
wordBox.Add(self.word)
|
||||
context = wx.StaticText(panel, -1, _(u"Context"))
|
||||
self.context = wx.TextCtrl(panel, -1)
|
||||
contextBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
contextBox.Add(context)
|
||||
contextBox.Add(self.context)
|
||||
suggest = wx.StaticText(panel, -1, _(u"Suggestions"))
|
||||
self.suggestions = wx.ListBox(panel, -1, choices=[], style=wx.LB_SINGLE)
|
||||
suggestionsBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
suggestionsBox.Add(suggest)
|
||||
suggestionsBox.Add(self.suggestions)
|
||||
ignore = wx.Button(panel, -1, _(u"Ignore"))
|
||||
self.Bind(wx.EVT_BUTTON, self.onIgnore, ignore)
|
||||
ignoreAll = wx.Button(panel, -1, _(u"Ignore all"))
|
||||
self.Bind(wx.EVT_BUTTON, self.onIgnoreAll, ignoreAll)
|
||||
replace = wx.Button(panel, -1, _(u"Replace"))
|
||||
self.Bind(wx.EVT_BUTTON, self.onReplace, replace)
|
||||
replaceAll = wx.Button(panel, -1, _(u"Replace all"))
|
||||
self.Bind(wx.EVT_BUTTON, self.onReplaceAll, replaceAll)
|
||||
close = wx.Button(panel, wx.ID_CANCEL)
|
||||
btnBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
btnBox.Add(ignore)
|
||||
btnBox.Add(ignoreAll)
|
||||
btnBox.Add(replace)
|
||||
btnBox.Add(replaceAll)
|
||||
btnBox.Add(close)
|
||||
sizer.Add(wordBox)
|
||||
sizer.Add(contextBox)
|
||||
sizer.Add(suggestionsBox)
|
||||
sizer.Add(btnBox)
|
||||
panel.SetSizerAndFit(sizer)
|
||||
self.check()
|
||||
|
||||
def check(self):
|
||||
try:
|
||||
self.checker.next()
|
||||
textToSay = _(u"Mis-spelled word: %s") % (self.checker.word,)
|
||||
context = u"... %s %s %s" % (self.checker.leading_context(10), self.checker.word, self.checker.trailing_context(10))
|
||||
self.SetTitle(textToSay)
|
||||
output.speak(textToSay)
|
||||
self.word.SetValue(self.checker.word)
|
||||
self.context.ChangeValue(context)
|
||||
self.suggestions.Set(self.checker.suggest())
|
||||
self.suggestions.SetFocus()
|
||||
except StopIteration:
|
||||
wx.MessageDialog(self, _(u"The spelling review has finished."), _("Finished"), style=wx.OK).ShowModal()
|
||||
self.EndModal(wx.ID_OK)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def onIgnore(self, ev):
|
||||
self.check()
|
||||
|
||||
def onIgnoreAll(self, ev):
|
||||
self.checker.ignore_always(word=self.checker.word)
|
||||
self.check()
|
||||
|
||||
def onReplace(self, ev):
|
||||
self.checker.replace(self.suggestions.GetStringSelection())
|
||||
self.check()
|
||||
|
||||
def onReplaceAll(self, ev):
|
||||
self.checker.replace_always(self.suggestions.GetStringSelection())
|
||||
self.check()
|
@@ -1,70 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import logging
|
||||
log = logging.getLogger("extra.SpellChecker.spellChecker")
|
||||
import wx_ui
|
||||
import widgetUtils
|
||||
import output
|
||||
import config
|
||||
import languageHandler
|
||||
from enchant.checker import SpellChecker
|
||||
from enchant.errors import DictNotFoundError
|
||||
from enchant import tokenize
|
||||
import twitterFilter
|
||||
|
||||
class spellChecker(object):
|
||||
def __init__(self, text, dictionary):
|
||||
super(spellChecker, self).__init__()
|
||||
log.debug("Creating the SpellChecker object. Dictionary: %s" % (dictionary,))
|
||||
self.active = True
|
||||
try:
|
||||
if config.app["app-settings"]["language"] == "system":
|
||||
log.debug("Using the system language")
|
||||
self.checker = SpellChecker(filters=[twitterFilter.TwitterFilter, tokenize.EmailFilter, tokenize.URLFilter])
|
||||
else:
|
||||
log.debug("Using language: %s" % (languageHandler.getLanguage(),))
|
||||
self.checker = SpellChecker(languageHandler.getLanguage(), filters=[twitterFilter.TwitterFilter, tokenize.EmailFilter, tokenize.URLFilter])
|
||||
self.checker.set_text(text)
|
||||
except DictNotFoundError:
|
||||
log.exception("Dictionary for language %s not found." % (dictionary,))
|
||||
wx_ui.dict_not_found_error()
|
||||
self.active = False
|
||||
if self.active == True:
|
||||
log.debug("Creating dialog...")
|
||||
self.dialog = wx_ui.spellCheckerDialog()
|
||||
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.replace, widgetUtils.BUTTON_PRESSED, self.replace)
|
||||
widgetUtils.connect_event(self.dialog.replaceAll, widgetUtils.BUTTON_PRESSED, self.replaceAll)
|
||||
self.check()
|
||||
self.dialog.get_response()
|
||||
self.fixed_text = self.checker.get_text()
|
||||
|
||||
def check(self):
|
||||
try:
|
||||
self.checker.next()
|
||||
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))
|
||||
self.dialog.set_title(textToSay)
|
||||
output.speak(textToSay)
|
||||
self.dialog.set_word_and_suggestions(word=self.checker.word, context=context, suggestions=self.checker.suggest())
|
||||
except StopIteration:
|
||||
log.debug("Process finished.")
|
||||
wx_ui.finished()
|
||||
self.dialog.Destroy()
|
||||
# except AttributeError:
|
||||
# pass
|
||||
|
||||
def ignore(self, ev):
|
||||
self.check()
|
||||
|
||||
def ignoreAll(self, ev):
|
||||
self.checker.ignore_always(word=self.checker.word)
|
||||
self.check()
|
||||
|
||||
def replace(self, ev):
|
||||
self.checker.replace(self.dialog.get_selected_suggestion())
|
||||
self.check()
|
||||
|
||||
def replaceAll(self, ev):
|
||||
self.checker.replace_always(self.dialog.get_selected_suggestion())
|
||||
self.check()
|
@@ -1,15 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import re
|
||||
from enchant.tokenize import Filter
|
||||
|
||||
class TwitterFilter(Filter):
|
||||
"""Filter skipping over twitter usernames and hashtags.
|
||||
This filter skips any words matching the following regular expression:
|
||||
^[#@](\S){1, }$
|
||||
That is, any words that resemble users and hashtags.
|
||||
"""
|
||||
_pattern = re.compile(r"^[#@](\S){1,}$")
|
||||
def _skip(self,word):
|
||||
if self._pattern.match(word):
|
||||
return True
|
||||
return False
|
@@ -1,79 +0,0 @@
|
||||
# -*- 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/>.
|
||||
#
|
||||
############################################################
|
||||
import wx
|
||||
import application
|
||||
class spellCheckerDialog(wx.Dialog):
|
||||
def __init__(self):
|
||||
super(spellCheckerDialog, self).__init__(None, 1)
|
||||
panel = wx.Panel(self)
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
word = wx.StaticText(panel, -1, _(u"Misspelled word"))
|
||||
self.word = wx.TextCtrl(panel, -1)
|
||||
wordBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
wordBox.Add(word, 0, wx.ALL, 5)
|
||||
wordBox.Add(self.word, 0, wx.ALL, 5)
|
||||
context = wx.StaticText(panel, -1, _(u"Context"))
|
||||
self.context = wx.TextCtrl(panel, -1)
|
||||
contextBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
contextBox.Add(context, 0, wx.ALL, 5)
|
||||
contextBox.Add(self.context, 0, wx.ALL, 5)
|
||||
suggest = wx.StaticText(panel, -1, _(u"Suggestions"))
|
||||
self.suggestions = wx.ListBox(panel, -1, choices=[], style=wx.LB_SINGLE)
|
||||
suggestionsBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
suggestionsBox.Add(suggest, 0, wx.ALL, 5)
|
||||
suggestionsBox.Add(self.suggestions, 0, wx.ALL, 5)
|
||||
self.ignore = wx.Button(panel, -1, _(u"Ignore"))
|
||||
self.ignoreAll = wx.Button(panel, -1, _(u"Ignore all"))
|
||||
self.replace = wx.Button(panel, -1, _(u"Replace"))
|
||||
self.replaceAll = wx.Button(panel, -1, _(u"Replace all"))
|
||||
close = wx.Button(panel, wx.ID_CANCEL)
|
||||
btnBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
btnBox.Add(self.ignore, 0, wx.ALL, 5)
|
||||
btnBox.Add(self.ignoreAll, 0, wx.ALL, 5)
|
||||
btnBox.Add(self.replace, 0, wx.ALL, 5)
|
||||
btnBox.Add(self.replaceAll, 0, wx.ALL, 5)
|
||||
btnBox.Add(close, 0, wx.ALL, 5)
|
||||
sizer.Add(wordBox, 0, wx.ALL, 5)
|
||||
sizer.Add(contextBox, 0, wx.ALL, 5)
|
||||
sizer.Add(suggestionsBox, 0, wx.ALL, 5)
|
||||
sizer.Add(btnBox, 0, wx.ALL, 5)
|
||||
panel.SetSizer(sizer)
|
||||
self.SetClientSize(sizer.CalcMin())
|
||||
|
||||
|
||||
def get_response(self):
|
||||
return self.ShowModal()
|
||||
|
||||
def set_title(self, title):
|
||||
return self.SetTitle(title)
|
||||
|
||||
def set_word_and_suggestions(self, word, context, suggestions):
|
||||
self.word.SetValue(word)
|
||||
self.context.ChangeValue(context)
|
||||
self.suggestions.Set(suggestions)
|
||||
self.suggestions.SetFocus()
|
||||
|
||||
def get_selected_suggestion(self):
|
||||
return self.suggestions.GetStringSelection()
|
||||
|
||||
def dict_not_found_error():
|
||||
wx.MessageDialog(None, _(u"An error has occurred. There are no dictionaries available for the selected language in " + application.name), _(u"Error"), wx.ICON_ERROR).ShowModal()
|
||||
|
||||
def finished():
|
||||
wx.MessageDialog(None, _(u"Spell check complete."), _(application.name), style=wx.OK).ShowModal()
|
@@ -1,2 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import completion, settings
|
@@ -1,47 +1,31 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import output
|
||||
import storage
|
||||
import output
|
||||
import wx_menu
|
||||
|
||||
class autocompletionUsers(object):
|
||||
def __init__(self, window, session_id):
|
||||
def __init__(self, window):
|
||||
super(autocompletionUsers, self).__init__()
|
||||
self.window = window
|
||||
self.db = storage.storage(session_id)
|
||||
|
||||
def show_menu(self, mode="tweet"):
|
||||
position = self.window.get_position()
|
||||
if mode == "tweet":
|
||||
text = self.window.get_text()
|
||||
text = text[:position]
|
||||
try:
|
||||
pattern = text.split()[-1]
|
||||
except IndexError:
|
||||
output.speak(_(u"You have to start writing"))
|
||||
return
|
||||
if pattern.startswith("@") == True:
|
||||
menu = wx_menu.menu(self.window.text, pattern[1:], mode=mode)
|
||||
users = self.db.get_users(pattern[1:])
|
||||
if len(users) > 0:
|
||||
menu.append_options(users)
|
||||
self.window.popup_menu(menu)
|
||||
menu.destroy()
|
||||
else:
|
||||
output.speak(_(u"There are no results in your users database"))
|
||||
else:
|
||||
output.speak(_(u"Autocompletion only works for users."))
|
||||
elif mode == "dm":
|
||||
text = self.window.get_user()
|
||||
try:
|
||||
pattern = text.split()[-1]
|
||||
except IndexError:
|
||||
output.speak(_(u"You have to start writing"))
|
||||
return
|
||||
menu = wx_menu.menu(self.window.cb, pattern, mode=mode)
|
||||
users = self.db.get_users(pattern)
|
||||
def show_menu(self):
|
||||
position = self.window.text.GetInsertionPoint()
|
||||
text = self.window.text.GetValue()
|
||||
text = text[:position]
|
||||
try:
|
||||
pattern = text.split()[-1]
|
||||
except IndexError:
|
||||
output.speak(_(u"You have to start writing"))
|
||||
return
|
||||
if pattern.startswith("@") == True:
|
||||
db = storage.storage()
|
||||
menu = wx_menu.menu(self.window.text, pattern[1:])
|
||||
users = db.get_users(pattern[1:])
|
||||
if len(users) > 0:
|
||||
menu.append_options(users)
|
||||
self.window.popup_menu(menu)
|
||||
menu.destroy()
|
||||
self.window.PopupMenu(menu, self.window.text.GetPosition())
|
||||
menu.Destroy()
|
||||
else:
|
||||
output.speak(_(u"There are no results in your users database"))
|
||||
output.speak(_(u"There are not results in your users database"))
|
||||
else:
|
||||
output.speak(_(u"Autocompletion only works for users."))
|
@@ -1,20 +1,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import storage
|
||||
import widgetUtils
|
||||
import wx
|
||||
import wx_manage
|
||||
from wxUI import commonMessageDialogs
|
||||
|
||||
class autocompletionManage(object):
|
||||
def __init__(self, session):
|
||||
def __init__(self, window):
|
||||
super(autocompletionManage, self).__init__()
|
||||
self.session = session
|
||||
self.window = window
|
||||
self.dialog = wx_manage.autocompletionManageDialog()
|
||||
self.database = storage.storage(self.session.session_id)
|
||||
self.database = storage.storage()
|
||||
self.users = self.database.get_all_users()
|
||||
self.dialog.put_users(self.users)
|
||||
widgetUtils.connect_event(self.dialog.add, widgetUtils.BUTTON_PRESSED, self.add_user)
|
||||
widgetUtils.connect_event(self.dialog.remove, widgetUtils.BUTTON_PRESSED, self.remove_user)
|
||||
self.dialog.get_response()
|
||||
self.dialog.add.Bind(wx.EVT_BUTTON, self.add_user)
|
||||
self.dialog.remove.Bind(wx.EVT_BUTTON, self.remove_user)
|
||||
self.dialog.ShowModal()
|
||||
|
||||
def update_list(self):
|
||||
item = self.dialog.users.get_selected()
|
||||
@@ -23,12 +22,12 @@ class autocompletionManage(object):
|
||||
self.dialog.put_users(self.users)
|
||||
self.dialog.users.select_item(item)
|
||||
|
||||
def add_user(self, *args, **kwargs):
|
||||
def add_user(self, event=None):
|
||||
usr = self.dialog.get_user()
|
||||
if usr == False:
|
||||
return
|
||||
try:
|
||||
data = self.session.twitter.twitter.show_user(screen_name=usr)
|
||||
data = self.window.twitter.twitter.show_user(screen_name=usr)
|
||||
except:
|
||||
self.dialog.show_invalid_user_error()
|
||||
return
|
||||
@@ -36,7 +35,8 @@ class autocompletionManage(object):
|
||||
self.update_list()
|
||||
|
||||
def remove_user(self, ev):
|
||||
if commonMessageDialogs.delete_user_from_db() == widgetUtils.YES:
|
||||
ask = wx.MessageDialog(None, _(u"Are you sure you want to delete this user from the database? This user will not appear on the autocomplete results anymore."), _(u"Confirm"), wx.YES_NO|wx.ICON_QUESTION)
|
||||
if ask.ShowModal() == wx.ID_YES:
|
||||
item = self.dialog.users.get_selected()
|
||||
user = self.users[item]
|
||||
self.database.remove_user(user[0])
|
||||
|
@@ -1,59 +1,58 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import storage
|
||||
import widgetUtils
|
||||
import wx
|
||||
import config
|
||||
import wx_settings
|
||||
import manage
|
||||
import output
|
||||
from mysc.thread_utils import call_threaded
|
||||
|
||||
class autocompletionSettings(object):
|
||||
def __init__(self, config, buffer, window):
|
||||
def __init__(self, window):
|
||||
super(autocompletionSettings, self).__init__()
|
||||
self.config = config
|
||||
self.buffer = buffer
|
||||
self.window = window
|
||||
self.dialog = wx_settings.autocompletionSettingsDialog()
|
||||
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"])
|
||||
widgetUtils.connect_event(self.dialog.viewList, widgetUtils.BUTTON_PRESSED, self.view_list)
|
||||
if self.dialog.get_response() == widgetUtils.OK:
|
||||
self.dialog.friends_buffer.SetValue(config.main["mysc"]["save_friends_in_autocompletion_db"])
|
||||
self.dialog.followers_buffer.SetValue(config.main["mysc"]["save_followers_in_autocompletion_db"])
|
||||
self.dialog.viewList.Bind(wx.EVT_BUTTON, self.view_list)
|
||||
if self.dialog.ShowModal() == wx.ID_OK:
|
||||
call_threaded(self.add_users_to_database)
|
||||
|
||||
def add_users_to_database(self):
|
||||
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")
|
||||
config.main["mysc"]["save_friends_in_autocompletion_db"] = self.dialog.friends_buffer.GetValue()
|
||||
config.main["mysc"]["save_followers_in_autocompletion_db"] = self.dialog.friends_buffer.GetValue()
|
||||
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)
|
||||
if self.dialog.get("followers_buffer") == True:
|
||||
buffer = self.window.search_buffer("followers", self.config["twitter"]["user_name"])
|
||||
for i in buffer.session.db[buffer.name]["items"]:
|
||||
database = storage.storage()
|
||||
if self.dialog.followers_buffer.GetValue() == True:
|
||||
buffer = self.window.search_buffer("people", "followers")
|
||||
for i in buffer.db.settings[buffer.name_buffer]:
|
||||
database.set_user(i["screen_name"], i["name"], 1)
|
||||
else:
|
||||
database.remove_by_buffer(1)
|
||||
if self.dialog.get("friends_buffer") == True:
|
||||
buffer = self.window.search_buffer("friends", self.config["twitter"]["user_name"])
|
||||
for i in buffer.session.db[buffer.name]["items"]:
|
||||
if self.dialog.friends_buffer.GetValue() == True:
|
||||
buffer = self.window.search_buffer("people", "friends")
|
||||
for i in buffer.db.settings[buffer.name_buffer]:
|
||||
database.set_user(i["screen_name"], i["name"], 2)
|
||||
else:
|
||||
database.remove_by_buffer(2)
|
||||
wx_settings.show_success_dialog()
|
||||
self.dialog.destroy()
|
||||
self.dialog.Destroy()
|
||||
|
||||
def view_list(self, ev):
|
||||
q = manage.autocompletionManage(self.buffer.session)
|
||||
q = manage.autocompletionManage(self.window)
|
||||
|
||||
|
||||
def execute_at_startup(window, buffer, config):
|
||||
database = storage.storage(buffer.session.session_id)
|
||||
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"])
|
||||
for i in buffer.session.db[buffer.name]:
|
||||
def execute_at_startup(window):
|
||||
database = storage.storage()
|
||||
if config.main["mysc"]["save_followers_in_autocompletion_db"] == True and config.main["other_buffers"]["show_followers"] == True:
|
||||
buffer = window.search_buffer("people", "followers")
|
||||
for i in buffer.db.settings[buffer.name_buffer]:
|
||||
database.set_user(i["screen_name"], i["name"], 1)
|
||||
else:
|
||||
database.remove_by_buffer(1)
|
||||
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"])
|
||||
for i in buffer.session.db[buffer.name]:
|
||||
if config.main["mysc"]["save_friends_in_autocompletion_db"] == True and config.main["other_buffers"]["show_friends"] == True:
|
||||
buffer = window.search_buffer("people", "friends")
|
||||
for i in buffer.db.settings[buffer.name_buffer]:
|
||||
database.set_user(i["screen_name"], i["name"], 2)
|
||||
else:
|
||||
database.remove_by_buffer(2)
|
@@ -1,9 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import sqlite3, paths
|
||||
from sessionmanager import manager
|
||||
|
||||
class storage(object):
|
||||
def __init__(self, session_id):
|
||||
self.connection = sqlite3.connect(paths.config_path("%s/autocompletionUsers.dat" % (session_id)))
|
||||
def __init__(self):
|
||||
self.connection = sqlite3.connect(paths.config_path("%s/autocompletionUsers.dat" % (manager.manager.get_current_session())))
|
||||
self.cursor = self.connection.cursor()
|
||||
if self.table_exist("users") == False:
|
||||
self.create_table()
|
||||
|
@@ -1,14 +1,13 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import wx
|
||||
import widgetUtils
|
||||
from multiplatform_widgets import widgets
|
||||
import application
|
||||
class autocompletionManageDialog(widgetUtils.BaseDialog):
|
||||
|
||||
class autocompletionManageDialog(wx.Dialog):
|
||||
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 Autocomplete users’ database"))
|
||||
panel = wx.Panel(self)
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
label = wx.StaticText(panel, -1, _(u"Editing " + application.name + " users database"))
|
||||
label = wx.StaticText(panel, -1, _(u"Editing TWBlue users database"))
|
||||
self.users = widgets.list(panel, _(u"Username"), _(u"Name"), style=wx.LC_REPORT)
|
||||
sizer.Add(label, 0, wx.ALL, 5)
|
||||
sizer.Add(self.users.list, 0, wx.ALL, 5)
|
||||
|
@@ -2,11 +2,10 @@
|
||||
import wx
|
||||
|
||||
class menu(wx.Menu):
|
||||
def __init__(self, window, pattern, mode):
|
||||
def __init__(self, window, pattern):
|
||||
super(menu, self).__init__()
|
||||
self.window = window
|
||||
self.pattern = pattern
|
||||
self.mode = mode
|
||||
|
||||
def append_options(self, options):
|
||||
for i in options:
|
||||
@@ -15,11 +14,5 @@ class menu(wx.Menu):
|
||||
self.Bind(wx.EVT_MENU, lambda evt, temp=i[0]: self.select_text(evt, temp), item)
|
||||
|
||||
def select_text(self, ev, text):
|
||||
if self.mode == "tweet":
|
||||
self.window.ChangeValue(self.window.GetValue().replace("@"+self.pattern, "@"+text+" "))
|
||||
elif self.mode == "dm":
|
||||
self.window.SetValue(self.window.GetValue().replace(self.pattern, text))
|
||||
self.window.SetInsertionPointEnd()
|
||||
|
||||
def destroy(self):
|
||||
self.Destroy()
|
||||
self.window.ChangeValue(self.window.GetValue().replace(self.pattern, text+" "))
|
||||
self.window.SetInsertionPointEnd()
|
@@ -1,9 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import wx
|
||||
import widgetUtils
|
||||
import application
|
||||
|
||||
class autocompletionSettingsDialog(widgetUtils.BaseDialog):
|
||||
class autocompletionSettingsDialog(wx.Dialog):
|
||||
def __init__(self):
|
||||
super(autocompletionSettingsDialog, self).__init__(parent=None, id=-1, title=_(u"Autocomplete users’ settings"))
|
||||
panel = wx.Panel(self)
|
||||
@@ -12,7 +10,7 @@ class autocompletionSettingsDialog(widgetUtils.BaseDialog):
|
||||
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.friends_buffer, 0, wx.ALL, 5)
|
||||
self.viewList = wx.Button(panel, -1, _(u"Manage database..."))
|
||||
self.viewList = wx.Button(panel, -1, _(u"See the users list"))
|
||||
sizer.Add(self.viewList, 0, wx.ALL, 5)
|
||||
ok = wx.Button(panel, wx.ID_OK)
|
||||
cancel = wx.Button(panel, wx.ID_CANCEL)
|
||||
@@ -24,4 +22,4 @@ class autocompletionSettingsDialog(widgetUtils.BaseDialog):
|
||||
self.SetClientSize(sizer.CalcMin())
|
||||
|
||||
def show_success_dialog():
|
||||
wx.MessageDialog(None, _(uapplication.name+"'s database of users has been updated."), _(u"Done"), wx.OK).ShowModal()
|
||||
wx.MessageDialog(None, _(u"TWBlue's database of users has been updated."), _(u"Done"), wx.OK).ShowModal()
|
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import translator
|
||||
import platform
|
||||
if platform.system() == "Windows":
|
||||
import wx_ui as gui
|
||||
|
||||
from translator import *
|
||||
import gui
|
@@ -16,13 +16,12 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
############################################################
|
||||
import translator
|
||||
import wx
|
||||
from wxUI.dialogs import baseDialog
|
||||
import translator
|
||||
|
||||
class translateDialog(baseDialog.BaseWXDialog):
|
||||
class translateDialog(wx.Dialog):
|
||||
def __init__(self):
|
||||
super(translateDialog, self).__init__(None, -1, title=_(u"Translate message"))
|
||||
wx.Dialog.__init__(self, None, -1, title=_(u"Translate message"))
|
||||
panel = wx.Panel(self)
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
staticSource = wx.StaticText(panel, -1, _(u"Source language"))
|
||||
@@ -41,5 +40,5 @@ class translateDialog(baseDialog.BaseWXDialog):
|
||||
cancel = wx.Button(panel, wx.ID_CANCEL)
|
||||
self.SetEscapeId(wx.ID_CANCEL)
|
||||
|
||||
def get(self, control):
|
||||
return getattr(self, control).GetSelection()
|
||||
def onOk(self, ev):
|
||||
self.EndModal(wx.ID_OK)
|
@@ -1,9 +1,53 @@
|
||||
#!/usr/bin/env python
|
||||
import goslate
|
||||
# -*- coding: utf-8 -*-
|
||||
import re
|
||||
try:
|
||||
import urllib2 as request
|
||||
from urllib import quote
|
||||
except:
|
||||
from urllib import request
|
||||
from urllib.parse import quote
|
||||
|
||||
def translate(text, source_lang, target_lang):
|
||||
gs = goslate.Goslate()
|
||||
return gs.translate(text, target_lang, source_lang)
|
||||
class Translator:
|
||||
string_pattern = r"\"(([^\"\\]|\\.)*)\""
|
||||
match_string =re.compile(
|
||||
r"\,?\["
|
||||
+ string_pattern + r"\,"
|
||||
+ string_pattern + r"\,"
|
||||
+ string_pattern + r"\,"
|
||||
+ string_pattern
|
||||
+r"\]")
|
||||
|
||||
def __init__(self):
|
||||
self.from_lang = ""
|
||||
self.to_lang = ""
|
||||
|
||||
def translate(self, source):
|
||||
json5 = self._get_json5_from_google(source)
|
||||
return self._unescape(self._get_translation_from_json5(json5))
|
||||
|
||||
def _get_translation_from_json5(self, content):
|
||||
result = ""
|
||||
pos = 2
|
||||
while True:
|
||||
m = self.match_string.match(content, pos)
|
||||
if not m:
|
||||
break
|
||||
result += m.group(1)
|
||||
pos = m.end()
|
||||
return result
|
||||
|
||||
def _get_json5_from_google(self, source):
|
||||
escaped_source = quote(source, '')
|
||||
headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.168 Safari/535.19'}
|
||||
req = request.Request(
|
||||
url="http://translate.google.com/translate_a/t?client=t&ie=UTF-8&oe=UTF-8"
|
||||
+"&sl=%s&tl=%s&text=%s" % (self.from_lang, self.to_lang, escaped_source)
|
||||
, headers = headers)
|
||||
r = request.urlopen(req)
|
||||
return r.read().decode('utf-8')
|
||||
|
||||
def _unescape(self, text):
|
||||
return re.sub(r"\\.?", lambda x:eval('"%s"'%x.group(0)), text)
|
||||
|
||||
languages = {
|
||||
"af": _(u"Afrikaans"),
|
||||
|
@@ -1,6 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
""" This module contains some bugfixes for packages used in TWBlue."""
|
||||
import fix_arrow # A few new locales for Three languages in arrow.
|
||||
|
||||
def setup():
|
||||
fix_arrow.fix()
|
@@ -1,91 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from arrow import locales
|
||||
from arrow.locales import Locale
|
||||
|
||||
def fix():
|
||||
''' This function adds the Catala, Basque and galician locales to the list of locales supported in Arrow.
|
||||
it also fixes capitalizations in names from turkish and arabian locales.
|
||||
see https://github.com/crsmithdev/arrow/pull/207 for following the pull request.'''
|
||||
locales.CatalaLocale = CatalaLocale
|
||||
locales.GalicianLocale = GalicianLocale
|
||||
locales.BasqueLocale = BasqueLocale
|
||||
locales.TurkishLocale.names[-1] = "tr_tr"
|
||||
locales.ArabicLocale.names[-1] = "ar_eg"
|
||||
# We need to reassign the locales list for updating the list with our new contents.
|
||||
locales._locales = locales._map_locales()
|
||||
|
||||
class CatalaLocale(Locale):
|
||||
names = ['ca', 'ca_ca']
|
||||
past = 'Fa {0}'
|
||||
future = '{0}' # I don't know what's the right phrase in catala for the future.
|
||||
|
||||
timeframes = {
|
||||
'now': 'Ara mateix',
|
||||
'seconds': 'segons',
|
||||
'minute': '1 minut',
|
||||
'minutes': '{0} minuts',
|
||||
'hour': 'una hora',
|
||||
'hours': '{0} hores',
|
||||
'day': 'un dia',
|
||||
'days': '{0} dies',
|
||||
'month': 'un mes',
|
||||
'months': '{0} messos',
|
||||
'year': 'un any',
|
||||
'years': '{0} anys',
|
||||
}
|
||||
|
||||
month_names = ['', 'Jener', 'Febrer', 'Març', 'Abril', 'Maig', 'Juny', 'Juliol', 'Agost', 'Setembre', 'Octubre', 'Novembre', 'Decembre']
|
||||
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):
|
||||
names = ['gl', 'gl_gl']
|
||||
past = 'Fai {0}'
|
||||
future = '{0}' # I don't know what's the right phrase in Galician for the future.
|
||||
|
||||
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_eu']
|
||||
past = 'duela {0}'
|
||||
future = '{0}' # I don't know what's the right phrase in Basque for the future.
|
||||
|
||||
timeframes = {
|
||||
'now': 'Orain',
|
||||
'seconds': 'segundu',
|
||||
'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']
|
||||
|
@@ -1,11 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
""" This is the GTK view module for TWBlue.
|
||||
As of April 3 2015, there are the things that have been implemented:
|
||||
* the main view (partially implemented)
|
||||
* All buffers.
|
||||
* Three of the most common message dialogs.
|
||||
* Dialogs for tweet, reply, retweet, send a direct message and view a tweet.
|
||||
|
||||
And we need to implement:
|
||||
* All the other dialogs.
|
||||
"""
|
@@ -1,11 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from base import basePanel
|
||||
from dm import dmPanel
|
||||
from events import eventsPanel
|
||||
from favourites import favsPanel
|
||||
from lists import listPanel
|
||||
from panels import accountPanel, emptyPanel
|
||||
from people import peoplePanel
|
||||
from trends import trendsPanel
|
||||
from tweet_searches import searchPanel
|
||||
from user_searches import searchUsersPanel
|
@@ -1,35 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import widgetUtils
|
||||
from gi.repository import Gtk
|
||||
|
||||
class basePanel(Gtk.VBox):
|
||||
|
||||
def create_list(self):
|
||||
self.list = widgetUtils.list(_(u"User"), _(u"Text"), _(u"Date"), _(u"Client"))
|
||||
|
||||
def __init__(self, parent, name):
|
||||
super(basePanel, self).__init__(spacing=6)
|
||||
self.name = name
|
||||
self.type = "baseBuffer"
|
||||
self.create_list()
|
||||
self.tweet = Gtk.Button(_(u"Tweet"))
|
||||
self.retweet = Gtk.Button(_(u"Retweet"))
|
||||
self.reply = Gtk.Button(_(u"Reply"))
|
||||
self.dm = Gtk.Button(_(u"Direct message"))
|
||||
btnSizer = Gtk.Box(spacing=6)
|
||||
btnSizer.add(self.tweet)
|
||||
btnSizer.add(self.retweet)
|
||||
btnSizer.add(self.reply)
|
||||
btnSizer.add(self.dm)
|
||||
self.add(self.list.list)
|
||||
self.add(btnSizer)
|
||||
|
||||
def set_position(self, reversed=False):
|
||||
if reversed == False:
|
||||
self.list.select_item(self.list.get_count()-1)
|
||||
else:
|
||||
self.list.select_item(0)
|
||||
|
||||
def set_focus_function(self, f):
|
||||
tree_selection = self.list.list.get_selection()
|
||||
tree_selection.connect("changed", f)
|
@@ -1,14 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from gi.repository import Gtk
|
||||
import widgetUtils
|
||||
from base import basePanel
|
||||
|
||||
class dmPanel(basePanel):
|
||||
def __init__(self, parent, name):
|
||||
""" Class to DM'S. Reply and retweet buttons are not showed and they have your delete method for dm's."""
|
||||
super(dmPanel, self).__init__(parent, name)
|
||||
self.retweet.hide()
|
||||
self.retweet.set_no_show_all(True)
|
||||
self.reply.hide()
|
||||
self.reply.set_no_show_all(True)
|
||||
self.type = "dm"
|
@@ -1,25 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import widgetUtils
|
||||
from gi.repository import Gtk
|
||||
|
||||
class eventsPanel(Gtk.VBox):
|
||||
""" Buffer to show events. Different than tweets or people."""
|
||||
|
||||
def __init__(self, parent, name):
|
||||
self.type = "event"
|
||||
super(eventsPanel, self).__init__(spacing=6)
|
||||
self.name = name
|
||||
self.list = widgetUtils.list(_(u"Date"), _(u"Event"))
|
||||
self.add(self.list.list)
|
||||
self.tweet = Gtk.Button(_(u"Tweet"))
|
||||
self.delete_event = Gtk.Button(_(u"Remove event"))
|
||||
btnBox = Gtk.Box(spacing=6)
|
||||
btnBox.add(self.tweet)
|
||||
btnBox.add(self.delete_event)
|
||||
self.add(btnBox)
|
||||
|
||||
def set_position(self, reversed=False):
|
||||
if reversed == False:
|
||||
self.list.select_item(self.list.get_count()-1)
|
||||
else:
|
||||
self.list.select_item(0)
|
@@ -1,8 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from gi.repository import Gtk
|
||||
from base import basePanel
|
||||
|
||||
class favsPanel(basePanel):
|
||||
def __init__(self, parent, name):
|
||||
super(favsPanel, self).__init__(parent, name)
|
||||
self.type = "favourites_timeline"
|
@@ -1,9 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from gi.repository import Gtk
|
||||
from base import basePanel
|
||||
|
||||
class listPanel(basePanel):
|
||||
def __init__(self, parent, name):
|
||||
super(listPanel, self).__init__(parent, name)
|
||||
self.type = "list"
|
||||
self.users = []
|
@@ -1,34 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from gi.repository import Gtk
|
||||
import widgetUtils
|
||||
|
||||
class accountPanel(Gtk.VBox):
|
||||
def __init__(self, parent, name=None):
|
||||
super(accountPanel, self).__init__(spacing=5)
|
||||
self.name = name
|
||||
self.type = "account"
|
||||
self.login = Gtk.Button(_(u"Login"))
|
||||
self.add(self.login)
|
||||
self.autostart_account = Gtk.ToggleButton(_(u"Log in automatically"))
|
||||
self.add(self.autostart_account)
|
||||
|
||||
def change_login(self, login=True):
|
||||
if login == True:
|
||||
self.login.set_label(_(u"Login"))
|
||||
else:
|
||||
self.login.set_label(_(u"Logout"))
|
||||
|
||||
def change_autostart(self, autostart=True):
|
||||
self.autostart_account.set_active(autostart)
|
||||
|
||||
def get_autostart(self):
|
||||
print "actived"
|
||||
print self.autostart_account.get_active()
|
||||
return self.autostart_account.get_active()
|
||||
|
||||
class emptyPanel(Gtk.VBox):
|
||||
def __init__(self, parent, name):
|
||||
super(emptyPanel, self).__init__(spacing=6)
|
||||
self.name = name
|
||||
self.type = "account"
|
||||
|
@@ -1,17 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from gi.repository import Gtk
|
||||
import widgetUtils
|
||||
from base import basePanel
|
||||
|
||||
class peoplePanel(basePanel):
|
||||
""" Buffer used to show people."""
|
||||
|
||||
def create_list(self):
|
||||
self.list = widgetUtils.list(_(u"User"))
|
||||
|
||||
def __init__(self, parent, name):
|
||||
super(peoplePanel, self).__init__(parent, name)
|
||||
self.type = "people"
|
||||
self.reply.set_label(_(u"Mention"))
|
||||
self.retweet.hide()
|
||||
self.retweet.set_no_show_all(True)
|
@@ -1,26 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from gi.repository import Gtk
|
||||
import widgetUtils
|
||||
|
||||
class trendsPanel(Gtk.VBox):
|
||||
def create_list(self):
|
||||
""" Returns the list for put the tweets here."""
|
||||
self.list = widgetUtils.list(_(u"Trending topic"))
|
||||
|
||||
def __init__(self, parent, name):
|
||||
super(trendsPanel, self).__init__(spacing=6)
|
||||
self.type = "trends"
|
||||
self.create_list()
|
||||
self.tweet = Gtk.Button(_(u"Tweet"))
|
||||
self.tweetTrendBtn = Gtk.Button(_(u"Tweet about this trend"))
|
||||
btnSizer = Gtk.Box(spacing=3)
|
||||
btnSizer.add(self.tweet)
|
||||
btnSizer.add(self.tweetTrendBtn)
|
||||
self.add(btnSizer)
|
||||
self.Add(self.list.list)
|
||||
|
||||
def set_position(self, reversed=False):
|
||||
if reversed == False:
|
||||
self.list.select_item(self.list.get_count()-1)
|
||||
else:
|
||||
self.list.select_item(0)
|
@@ -1,8 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from gi.repository import Gtk
|
||||
from base import basePanel
|
||||
|
||||
class searchPanel(basePanel):
|
||||
def __init__(self, parent, name):
|
||||
super(searchPanel, self).__init__(parent, name)
|
||||
self.type = "search"
|
@@ -1,14 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from gi.repository import Gtk
|
||||
from tweet_searches import searchPanel
|
||||
import widgetUtils
|
||||
|
||||
class searchUsersPanel(searchPanel):
|
||||
def create_list(self):
|
||||
""" Returns the list for put the tweets here."""
|
||||
self.list = widgetUtils.list(_(u"User"))
|
||||
|
||||
def __init__(self, parent, name):
|
||||
self.create_list()
|
||||
super(searchUsersPanel, self).__init__(parent, name)
|
||||
self.type = "user_searches"
|
@@ -1,64 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from gi.repository import Gtk
|
||||
import application
|
||||
def retweet_as_link(parent):
|
||||
dialog = Gtk.MessageDialog(None, 0, Gtk.MessageType.QUESTION, Gtk.ButtonsType.YES_NO, unicode(application.name))
|
||||
dialog.format_secondary_text(_(u"This retweet is over 140 characters. Would you like to post it as a mention to the poster with your comments and a link to the original tweet?"))
|
||||
answer = dialog.run()
|
||||
dialog.destroy()
|
||||
return answer
|
||||
|
||||
def retweet_question(parent):
|
||||
dialog = Gtk.MessageDialog(None, 0, Gtk.MessageType.QUESTION, Gtk.ButtonsType.YES_NO, _(u"Retweet"))
|
||||
dialog.format_secondary_text(_(u"Would you like to add a comment to this tweet?"))
|
||||
answer = dialog.run()
|
||||
dialog.destroy()
|
||||
return answer
|
||||
|
||||
def delete_tweet_dialog(parent):
|
||||
dialog = Gtk.MessageDialog(None, 0, Gtk.MessageType.QUESTION, Gtk.ButtonsType.YES_NO, _(u"Delete"))
|
||||
dialog.format_secondary_text(_(u"Do you really want to delete this message? It will be deleted from Twitter as well."))
|
||||
answer = dialog.run()
|
||||
dialog.destroy()
|
||||
return answer
|
||||
|
||||
def exit_dialog(parent):
|
||||
dialog = Gtk.MessageDialog(parent, 0, Gtk.MessageType.QUESTION, Gtk.ButtonsType.YES_NO, _(u"Exit"))
|
||||
dialog.format_secondary_text(_(u"Do you really want to close " + application.name + "?"))
|
||||
answer = dialog.run()
|
||||
dialog.destroy()
|
||||
return answer
|
||||
|
||||
def needs_restart():
|
||||
wx.MessageDialog(None, _(unicode(application.name+" must be restarted to save these changes. Press OK to restart now.")), _("Restart " + application.name), wx.OK).ShowModal()
|
||||
|
||||
def delete_user_from_db():
|
||||
return wx.MessageDialog(None, _(u"Are you sure you want to delete this user from the database? This user will not appear on the autocomplete results anymore."), _(u"Confirm"), wx.YES_NO|wx.ICON_QUESTION).ShowModal()
|
||||
|
||||
def get_ignored_client():
|
||||
entry = wx.TextEntryDialog(None, _(u"Enter the name of the client here"), _(u"Add a new ignored client"))
|
||||
if entry.ShowModal() == wx.ID_OK:
|
||||
return entry.GetValue()
|
||||
return None
|
||||
|
||||
def clear_list():
|
||||
dlg = wx.MessageDialog(None, _(u"Do you really want to empty this buffer? It's items will be removed from the list but not from Twitter"), _(u"Empty buffer"), wx.ICON_QUESTION|wx.YES_NO)
|
||||
return dlg.ShowModal()
|
||||
|
||||
def remove_buffer():
|
||||
return wx.MessageDialog(None, _(u"Do you really want to delete this timeline?"), _(u"Attention"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal()
|
||||
|
||||
def user_not_exist():
|
||||
return wx.MessageDialog(None, _(u"The user does not exist"), _(u"Error"), wx.ICON_ERROR).ShowModal()
|
||||
|
||||
def timeline_exist():
|
||||
return wx.MessageDialog(None, _(u"There's currently a timeline for this user. You are not able to open another"), _(u"Existing timeline"), wx.ICON_ERROR).ShowModal()
|
||||
|
||||
def no_tweets():
|
||||
return wx.MessageDialog(None, _(u"This user has no tweets. You can't open a timeline for this user"), _(u"Error!"), wx.ICON_ERROR).ShowModal()
|
||||
|
||||
def protected_user():
|
||||
return wx.MessageDialog(None, _(u"This is a protected Twitter user. It means you can not open a timeline using the Streaming API. The user's tweets will not update due to a twitter policy. Do you want to continue?"), _(u"Warning"), wx.ICON_WARNING|wx.YES_NO).ShowModal()
|
||||
|
||||
def no_following():
|
||||
return wx.MessageDialog(None, _(u"This is a protected user account, you need follow to this user for viewing your tweets or favourites."), _(u"Error"), wx.ICON_ERROR).ShowModal()
|
@@ -1 +0,0 @@
|
||||
#import trends, configuration, lists, message, search, show_user, update_profile, urlList, userSelection, utils
|
@@ -1,228 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import baseDialog
|
||||
import wx
|
||||
import logging as original_logger
|
||||
import application
|
||||
class general(wx.Panel, baseDialog.BaseWXDialog):
|
||||
def __init__(self, parent, languages):
|
||||
super(general, self).__init__(parent)
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
language = wx.StaticText(self, -1, _(u"Language"))
|
||||
self.language = wx.ListBox(self, -1, choices=languages)
|
||||
self.language.SetSize(self.language.GetBestSize())
|
||||
langBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
langBox.Add(language, 0, wx.ALL, 5)
|
||||
langBox.Add(self.language, 0, wx.ALL, 5)
|
||||
sizer.Add(langBox, 0, wx.ALL, 5)
|
||||
self.ask_at_exit = wx.CheckBox(self, -1, _(U"ask before exiting " + application.name))
|
||||
sizer.Add(self.ask_at_exit, 0, wx.ALL, 5)
|
||||
self.use_invisible_shorcuts = wx.CheckBox(self, -1, _(u"Use invisible interface's keyboard shortcuts while GUI is visible"))
|
||||
sizer.Add(self.use_invisible_shorcuts, 0, wx.ALL, 5)
|
||||
self.disable_sapi5 = wx.CheckBox(self, -1, _(u"Activate Sapi5 when any other screen reader is not being run"))
|
||||
sizer.Add(self.disable_sapi5, 0, wx.ALL, 5)
|
||||
self.hide_gui = wx.CheckBox(self, -1, _(u"Hide GUI on launch"))
|
||||
sizer.Add(self.hide_gui, 0, wx.ALL, 5)
|
||||
self.SetSizer(sizer)
|
||||
|
||||
class generalAccount(wx.Panel, baseDialog.BaseWXDialog):
|
||||
def __init__(self, parent):
|
||||
super(generalAccount, self).__init__(parent)
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
self.au = wx.Button(self, wx.NewId(), _(u"Set the autocomplete function"))
|
||||
sizer.Add(self.au, 0, wx.ALL, 5)
|
||||
self.relative_time = wx.CheckBox(self, wx.NewId(), _(U"Relative times"))
|
||||
sizer.Add(self.relative_time, 0, wx.ALL, 5)
|
||||
apiCallsBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
apiCallsBox.Add(wx.StaticText(self, -1, _(u"API calls when the stream is started (One API call equals to 200 tweetts, two API calls equals 400 tweets, etc):")), 0, wx.ALL, 5)
|
||||
self.apiCalls = wx.SpinCtrl(self, wx.NewId())
|
||||
self.apiCalls.SetRange(1, 10)
|
||||
self.apiCalls.SetSize(self.apiCalls.GetBestSize())
|
||||
apiCallsBox.Add(self.apiCalls, 0, wx.ALL, 5)
|
||||
sizer.Add(apiCallsBox, 0, wx.ALL, 5)
|
||||
tweetsPerCallBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
tweetsPerCallBox.Add(wx.StaticText(self, -1, _(u"Items on each API call")), 0, wx.ALL, 5)
|
||||
self.itemsPerApiCall = wx.SpinCtrl(self, wx.NewId())
|
||||
self.itemsPerApiCall.SetRange(0, 200)
|
||||
self.itemsPerApiCall.SetSize(self.itemsPerApiCall.GetBestSize())
|
||||
tweetsPerCallBox.Add(self.itemsPerApiCall, 0, wx.ALL, 5)
|
||||
sizer.Add(tweetsPerCallBox, 0, wx.ALL, 5)
|
||||
self.reverse_timelines = wx.CheckBox(self, wx.NewId(), _(u"Inverted buffers: The newest tweets will be shown at the beginning of the lists while the oldest at the end"))
|
||||
sizer.Add(self.reverse_timelines, 0, wx.ALL, 5)
|
||||
self.SetSizer(sizer)
|
||||
|
||||
class other_buffers(wx.Panel):
|
||||
def __init__(self, parent):
|
||||
super(other_buffers, self).__init__(parent)
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
self.SetSizer(sizer)
|
||||
|
||||
class ignoredClients(wx.Panel):
|
||||
def __init__(self, parent, choices):
|
||||
super(ignoredClients, self).__init__(parent=parent)
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
label = wx.StaticText(self, -1, _(u"Ignored clients"))
|
||||
self.clients = wx.ListBox(self, -1, choices=choices)
|
||||
self.clients.SetSize(self.clients.GetBestSize())
|
||||
clientsBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
clientsBox.Add(label, 0, wx.ALL, 5)
|
||||
clientsBox.Add(self.clients, 0, wx.ALL, 5)
|
||||
self.add = wx.Button(self, -1, _(u"Add client"))
|
||||
self.remove = wx.Button(self, -1, _(u"Remove client"))
|
||||
btnBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
btnBox.Add(self.add, 0, wx.ALL, 5)
|
||||
btnBox.Add(self.remove, 0, wx.ALL, 5)
|
||||
sizer.Add(clientsBox, 0, wx.ALL, 5)
|
||||
sizer.Add(btnBox, 0, wx.ALL, 5)
|
||||
self.SetSizer(sizer)
|
||||
|
||||
def append(self, client):
|
||||
self.clients.Append(client)
|
||||
|
||||
def get_clients(self):
|
||||
return self.clients.GetCount()
|
||||
|
||||
def get_client_id(self):
|
||||
return self.clients.GetSelection()
|
||||
|
||||
def remove_(self, id):
|
||||
self.clients.Delete(id)
|
||||
|
||||
class sound(wx.Panel):
|
||||
def __init__(self, parent, input_devices, output_devices, soundpacks):
|
||||
wx.Panel.__init__(self, parent)
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
volume = wx.StaticText(self, -1, _(u"Volume"))
|
||||
self.volumeCtrl = wx.Slider(self)
|
||||
self.volumeCtrl.SetRange(0, 100)
|
||||
self.volumeCtrl.SetSize(self.volumeCtrl.GetBestSize())
|
||||
volumeBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
volumeBox.Add(volume, 0, wx.ALL, 5)
|
||||
volumeBox.Add(self.volumeCtrl, 0, wx.ALL, 5)
|
||||
sizer.Add(volumeBox, 0, wx.ALL, 5)
|
||||
self.session_mute = wx.CheckBox(self, -1, _(u"Session mute"))
|
||||
sizer.Add(self.session_mute, 0, wx.ALL, 5)
|
||||
output_label = wx.StaticText(self, -1, _(u"Output device"))
|
||||
self.output = wx.ComboBox(self, -1, choices=output_devices, style=wx.CB_READONLY)
|
||||
self.output.SetSize(self.output.GetBestSize())
|
||||
outputBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
outputBox.Add(output_label, 0, wx.ALL, 5)
|
||||
outputBox.Add(self.output, 0, wx.ALL, 5)
|
||||
sizer.Add(outputBox, 0, wx.ALL, 5)
|
||||
input_label = wx.StaticText(self, -1, _(u"Input device"))
|
||||
self.input = wx.ComboBox(self, -1, choices=input_devices, style=wx.CB_READONLY)
|
||||
self.input.SetSize(self.input.GetBestSize())
|
||||
inputBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
inputBox.Add(input_label, 0, wx.ALL, 5)
|
||||
inputBox.Add(self.input, 0, wx.ALL, 5)
|
||||
sizer.Add(inputBox, 0, wx.ALL, 5)
|
||||
soundBox = wx.BoxSizer(wx.VERTICAL)
|
||||
soundpack_label = wx.StaticText(self, -1, _(u"Sound pack"))
|
||||
self.soundpack = wx.ComboBox(self, -1, choices=soundpacks, style=wx.CB_READONLY)
|
||||
self.soundpack.SetSize(self.soundpack.GetBestSize())
|
||||
soundBox.Add(soundpack_label, 0, wx.ALL, 5)
|
||||
soundBox.Add(self.soundpack, 0, wx.ALL, 5)
|
||||
sizer.Add(soundBox, 0, wx.ALL, 5)
|
||||
self.SetSizer(sizer)
|
||||
|
||||
def get(self, control):
|
||||
return getattr(self, control).GetStringSelection()
|
||||
|
||||
class audioServicesPanel(wx.Panel):
|
||||
def __init__(self, parent):
|
||||
super(audioServicesPanel, self).__init__(parent)
|
||||
mainSizer = wx.BoxSizer(wx.VERTICAL)
|
||||
apiKeyLabel = wx.StaticText(self, -1, _(u"If you've got a SndUp account, enter your API Key here. Whether the API Key is wrong, the App will fail to upload anything to the server. Whether there's no API Key here, then the audio files will be uploaded anonimously"))
|
||||
self.apiKey = wx.TextCtrl(self, -1)
|
||||
dc = wx.WindowDC(self.apiKey)
|
||||
dc.SetFont(self.apiKey.GetFont())
|
||||
self.apiKey.SetSize(dc.GetTextExtent("0"*100))
|
||||
apiKeyBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
apiKeyBox.Add(apiKeyLabel, 0, wx.ALL, 5)
|
||||
apiKeyBox.Add(self.apiKey, 0, wx.ALL, 5)
|
||||
mainSizer.Add(apiKeyBox, 0, wx.ALL, 5)
|
||||
first_sizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
self.dropbox = wx.Button(self, -1)
|
||||
first_sizer.Add(self.dropbox, 0, wx.ALL, 5)
|
||||
mainSizer.Add(first_sizer, 0, wx.ALL, 5)
|
||||
self.SetSizer(mainSizer)
|
||||
|
||||
def set_dropbox(self, active=True):
|
||||
if active == True:
|
||||
self.dropbox.SetLabel(_(u"Unlink your Dropbox account"))
|
||||
else:
|
||||
self.dropbox.SetLabel(_(u"Link your Dropbox account"))
|
||||
|
||||
def show_dialog(self):
|
||||
wx.MessageDialog(self, _(u"The authorization request will be opened in your browser. Copy the code from Dropbox and paste it into the text box which will appear. You only need to do this once."), _(u"Authorization"), wx.OK).ShowModal()
|
||||
|
||||
def get_response(self):
|
||||
dlg = wx.TextEntryDialog(self, _(u"Enter the code here."), _(u"Verification code"))
|
||||
if dlg.ShowModal() == wx.ID_CANCEL:
|
||||
return False
|
||||
return dlg.GetValue()
|
||||
|
||||
def show_error(self):
|
||||
wx.MessageDialog(self, _(u"Error during authorisation. Try again later."), _(u"Error!"), wx.ICON_ERROR).ShowModal()
|
||||
|
||||
def get_dropbox(self):
|
||||
return self.dropbox.GetLabel()
|
||||
|
||||
class configurationDialog(baseDialog.BaseWXDialog):
|
||||
|
||||
def set_title(self, title):
|
||||
self.SetTitle(title)
|
||||
|
||||
def __init__(self):
|
||||
super(configurationDialog, self).__init__(None, -1)
|
||||
self.panel = wx.Panel(self)
|
||||
self.SetTitle(_(u"TW Blue preferences"))
|
||||
self.sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
self.notebook = wx.Notebook(self.panel)
|
||||
|
||||
def create_general(self, languageList):
|
||||
self.general = general(self.notebook, languageList)
|
||||
self.notebook.AddPage(self.general, _(u"General"))
|
||||
self.general.SetFocus()
|
||||
|
||||
def create_general_account(self):
|
||||
self.general = generalAccount(self.notebook)
|
||||
self.notebook.AddPage(self.general, _(u"General"))
|
||||
self.general.SetFocus()
|
||||
|
||||
def create_other_buffers(self):
|
||||
self.buffers = other_buffers(self.notebook)
|
||||
self.notebook.AddPage(self.buffers, _(u"Show other buffers"))
|
||||
|
||||
def create_ignored_clients(self, ignored_clients_list):
|
||||
self.ignored_clients = ignoredClients(self.notebook, ignored_clients_list)
|
||||
self.notebook.AddPage(self.ignored_clients, _(u"Ignored clients"))
|
||||
|
||||
def create_sound(self, output_devices, input_devices, soundpacks):
|
||||
self.sound = sound(self.notebook, output_devices, input_devices, soundpacks)
|
||||
self.notebook.AddPage(self.sound, _(u"Sound"))
|
||||
def create_audio_services(self):
|
||||
self.services = audioServicesPanel(self.notebook)
|
||||
self.notebook.AddPage(self.services, _(u"Audio Services"))
|
||||
|
||||
def realize(self):
|
||||
self.sizer.Add(self.notebook, 0, wx.ALL, 5)
|
||||
ok_cancel_box = wx.BoxSizer(wx.HORIZONTAL)
|
||||
ok = wx.Button(self.panel, wx.ID_OK, _(u"Save"))
|
||||
ok.SetDefault()
|
||||
cancel = wx.Button(self.panel, wx.ID_CANCEL, _(u"Close"))
|
||||
self.SetEscapeId(cancel.GetId())
|
||||
ok_cancel_box.Add(ok, 0, wx.ALL, 5)
|
||||
ok_cancel_box.Add(cancel, 0, wx.ALL, 5)
|
||||
self.sizer.Add(ok_cancel_box, 0, wx.ALL, 5)
|
||||
self.panel.SetSizer(self.sizer)
|
||||
self.SetClientSize(self.sizer.CalcMin())
|
||||
|
||||
def get_value(self, panel, key):
|
||||
p = getattr(self, panel)
|
||||
return getattr(p, key).GetValue()
|
||||
|
||||
def set_value(self, panel, key, value):
|
||||
p = getattr(self, panel)
|
||||
control = getattr(p, key)
|
||||
getattr(control, "SetValue")(value)
|
||||
|
@@ -1,123 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import wx
|
||||
from multiplatform_widgets import widgets
|
||||
|
||||
class listViewer(wx.Dialog):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(listViewer, self).__init__(parent=None, *args, **kwargs)
|
||||
self.SetTitle(_(u"Lists manager"))
|
||||
panel = wx.Panel(self)
|
||||
label = wx.StaticText(panel, -1, _(u"Lists"))
|
||||
self.lista = widgets.list(panel, _(u"List"), _(u"Description"), _(u"Owner"), _(u"Members"), _(u"mode"), size=(800, 800), style=wx.LC_REPORT|wx.LC_SINGLE_SEL)
|
||||
self.lista.list.SetFocus()
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
sizer.Add(label)
|
||||
sizer.Add(self.lista.list)
|
||||
self.createBtn = wx.Button(panel, wx.NewId(), _(u"Create a new list"))
|
||||
self.editBtn = wx.Button(panel, -1, _(u"Edit"))
|
||||
self.deleteBtn = wx.Button(panel, -1, _(u"Remove"))
|
||||
self.view = wx.Button(panel, -1, _(u"Open in buffer"))
|
||||
# self.members = wx.Button(panel, -1, _(u"View members"))
|
||||
# self.members.Disable()
|
||||
# self.subscriptors = wx.Button(panel, -1, _(u"View subscribers"))
|
||||
# self.subscriptors.Disable()
|
||||
# self.get_linkBtn = wx.Button(panel, -1, _(u"Get link for the list"))
|
||||
# self.get_linkBtn.Bind(wx.EVT_BUTTON, self.onGetLink)
|
||||
self.cancelBtn = wx.Button(panel, wx.ID_CANCEL)
|
||||
btnSizer = wx.BoxSizer()
|
||||
btnSizer.Add(self.createBtn)
|
||||
btnSizer.Add(self.editBtn)
|
||||
btnSizer.Add(self.cancelBtn)
|
||||
panel.SetSizer(sizer)
|
||||
|
||||
def populate_list(self, lists):
|
||||
for item in lists:
|
||||
self.lista.insert_item(False, *item)
|
||||
|
||||
def get_item(self):
|
||||
return self.lista.get_selected()
|
||||
|
||||
class userListViewer(listViewer):
|
||||
def __init__(self, username, *args, **kwargs):
|
||||
self.username = username
|
||||
super(userListViewer, self).__init__(*args, **kwargs)
|
||||
self.SetTitle(_(u"Viewing lists for %s") % (self.username))
|
||||
self.createBtn.SetLabel(_(u"Subscribe"))
|
||||
self.deleteBtn.SetLabel(_(u"Unsubscribe"))
|
||||
self.editBtn.Disable()
|
||||
self.view.Disable()
|
||||
|
||||
class createListDialog(wx.Dialog):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(createListDialog, self).__init__(*args, **kwargs)
|
||||
self.SetTitle(_(u"Create a new list"))
|
||||
panel = wx.Panel(self)
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
name = wx.StaticText(panel, -1, _(u"Name (20 characters maximun)"))
|
||||
self.name = wx.TextCtrl(panel, -1)
|
||||
nameSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
nameSizer.Add(name)
|
||||
nameSizer.Add(self.name)
|
||||
description = wx.StaticText(panel, -1, _(u"Description"))
|
||||
self.description = wx.TextCtrl(panel, -1)
|
||||
descriptionSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
descriptionSizer.Add(description)
|
||||
descriptionSizer.Add(self.description)
|
||||
mode = wx.StaticText(panel, -1, _(u"Mode"))
|
||||
self.public = wx.RadioButton(panel, -1, _(u"Public"), style=wx.RB_GROUP)
|
||||
self.private = wx.RadioButton(panel, -1, _(u"Private"))
|
||||
modeBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
modeBox.Add(mode)
|
||||
modeBox.Add(self.public)
|
||||
modeBox.Add(self.private)
|
||||
ok = wx.Button(panel, wx.ID_OK)
|
||||
ok.SetDefault()
|
||||
cancel = wx.Button(panel, wx.ID_CANCEL)
|
||||
btnBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
btnBox.Add(ok)
|
||||
btnBox.Add(cancel)
|
||||
sizer.Add(nameSizer)
|
||||
sizer.Add(descriptionSizer)
|
||||
sizer.Add(modeBox)
|
||||
sizer.Add(btnBox)
|
||||
|
||||
def get(self, field):
|
||||
return getattr(self, field).GetValue()
|
||||
|
||||
class editListDialog(createListDialog):
|
||||
|
||||
def __init__(self, list, *args, **kwargs):
|
||||
super(editListDialog, self).__init__(*args, **kwargs)
|
||||
self.SetTitle(_(u"Editing the list %s") % (list["name"]))
|
||||
self.name.ChangeValue(list["name"])
|
||||
self.description.ChangeValue(list["description"])
|
||||
if list["mode"] == "public":
|
||||
self.public.SetValue(True)
|
||||
else:
|
||||
self.private.SetValue(True)
|
||||
|
||||
class addUserListDialog(listViewer):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(addUserListDialog, self).__init__(*args, **kwargs)
|
||||
self.SetTitle(_(u"Select a list to add the user"))
|
||||
self.createBtn.SetLabel(_(u"Add"))
|
||||
self.createBtn.SetDefault()
|
||||
self.editBtn.Disable()
|
||||
self.view.Disable()
|
||||
# self.subscriptors.Disable()
|
||||
# self.members.Disable()
|
||||
self.deleteBtn.Disable()
|
||||
|
||||
class removeUserListDialog(listViewer):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(removeUserListDialog, self).__init__(*args, **kwargs)
|
||||
self.SetTitle(_(u"Select a list to remove the user"))
|
||||
self.createBtn.SetLabel(_(u"Remove"))
|
||||
self.createBtn.SetDefault()
|
||||
self.editBtn.Disable()
|
||||
self.view.Disable()
|
||||
# self.subscriptors.Disable()
|
||||
# self.members.Disable()
|
||||
self.deleteBtn.Disable()
|
@@ -1,275 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from gi.repository import Gtk
|
||||
import widgetUtils
|
||||
|
||||
class textLimited(widgetUtils.baseDialog):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(textLimited, self).__init__(buttons=(Gtk.STOCK_OK, widgetUtils.OK, Gtk.STOCK_CANCEL, widgetUtils.CANCEL), *args, **kwargs)
|
||||
|
||||
def createTextArea(self, message="", text=""):
|
||||
self.label = Gtk.Label(message)
|
||||
self.set_title(message, titleWindow=True)
|
||||
self.text = Gtk.Entry()
|
||||
self.text.set_max_length(140)
|
||||
self.text.set_text(text)
|
||||
self.text.set_placeholder_text(message)
|
||||
self.set_title(str(len(text)))
|
||||
self.textBox = Gtk.Box(spacing=10)
|
||||
self.textBox.add(self.label)
|
||||
self.textBox.add(self.text)
|
||||
|
||||
def get(self, control):
|
||||
if control == "upload_image":
|
||||
return self.upload_image.get_label()
|
||||
elif control == "cb":
|
||||
return self.cb.get_active_text()
|
||||
|
||||
def set(self, control, val):
|
||||
if control == "upload_image":
|
||||
self.upload_image.set_label(val)
|
||||
elif control == "cb":
|
||||
self.cb.set_active_text(val)
|
||||
|
||||
def text_focus(self):
|
||||
self.text.grab_focus()
|
||||
|
||||
def get_text(self):
|
||||
return self.text.get_text()
|
||||
|
||||
def set_text(self, text):
|
||||
self.text.set_text(text)
|
||||
|
||||
def set_title(self, new_title, titleWindow=False):
|
||||
if titleWindow == False:
|
||||
self.text.set_placeholder_text(new_title)
|
||||
else:
|
||||
super(textLimited, self).set_title(new_title)
|
||||
# self.set_title(new_title)
|
||||
|
||||
def enable_button(self, buttonName):
|
||||
if getattr(self, buttonName):
|
||||
return getattr(self, buttonName).show()
|
||||
|
||||
def disable_button(self, buttonName):
|
||||
if getattr(self, buttonName):
|
||||
return getattr(self, buttonName).hide()
|
||||
|
||||
def set_cursor_at_end(self):
|
||||
self.text.set_position(-1)
|
||||
|
||||
def set_cursor_at_position(self, position):
|
||||
self.text.set_position()
|
||||
|
||||
def get_position(self):
|
||||
return self.text.get_position()
|
||||
|
||||
class tweet(textLimited):
|
||||
def createControls(self, title, message, text):
|
||||
self.createTextArea(message, text)
|
||||
self.box.add(self.textBox)
|
||||
self.upload_image = Gtk.Button(_(u"Upload image..."))
|
||||
self.spellcheck = Gtk.Button(_("Check spelling..."))
|
||||
self.attach = Gtk.Button(_(u"Attach audio..."))
|
||||
self.shortenButton = Gtk.Button(_(u"Shorten URL"))
|
||||
self.unshortenButton = Gtk.Button(_(u"Expand URL"))
|
||||
self.shortenButton.hide()
|
||||
self.shortenButton.set_no_show_all(True)
|
||||
self.unshortenButton.hide()
|
||||
self.unshortenButton.set_no_show_all(True)
|
||||
self.translateButton = Gtk.Button(_(u"Translate..."))
|
||||
self.autocompletionButton = Gtk.Button(_(u"&Autocomplete users"))
|
||||
self.buttonsBox1 = Gtk.Box(spacing=6)
|
||||
self.buttonsBox1.add(self.upload_image)
|
||||
self.buttonsBox1.add(self.spellcheck)
|
||||
self.buttonsBox1.add(self.attach)
|
||||
self.box.add(self.buttonsBox1)
|
||||
self.buttonsBox2 = Gtk.Box(spacing=6)
|
||||
self.buttonsBox2.add(self.shortenButton)
|
||||
self.buttonsBox2.add(self.unshortenButton)
|
||||
self.buttonsBox2.add(self.translateButton)
|
||||
self.box.add(self.buttonsBox2)
|
||||
|
||||
def __init__(self, title, message, text):
|
||||
super(tweet, self).__init__()
|
||||
self.createControls(message, title, text)
|
||||
self.show_all()
|
||||
|
||||
def get_image(self):
|
||||
dialog = Gtk.FileChooserDialog(_(u"Select the picture to be uploaded"), self, Gtk.FileChooserAction.OPEN, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
|
||||
filter_jpg = Gtk.FileFilter()
|
||||
filter_jpg.set_name(_(u"JPG images"))
|
||||
filter_jpg.add_mime_type("image/jpeg")
|
||||
dialog.add_filter(filter_jpg)
|
||||
filter_gif = Gtk.FileFilter()
|
||||
filter_gif.set_name(_(u"GIF images"))
|
||||
filter_gif.add_mime_type("image/gif")
|
||||
dialog.add_filter(filter_gif)
|
||||
filter_png = Gtk.FileFilter()
|
||||
filter_png.set_name(_(u"PNG Images"))
|
||||
filter_png.add_mime_type("image/png")
|
||||
dialog.add_filter(filter_png)
|
||||
answer = dialog.run()
|
||||
if answer == widgetUtils.OK:
|
||||
image = dialog.get_filename()
|
||||
dialog.destroy()
|
||||
return open(image, "rb")
|
||||
else:
|
||||
dialog.destroy()
|
||||
return None
|
||||
|
||||
class dm(textLimited):
|
||||
def createControls(self, title, message, users):
|
||||
label = Gtk.Label(_(u"Recipient"))
|
||||
self.cb = Gtk.ComboBoxText.new_with_entry()
|
||||
self.cb.set_entry_text_column(0)
|
||||
for user in users:
|
||||
self.cb.append_text(user)
|
||||
self.cb.get_child().set_placeholder_text(_(u"Recipient"))
|
||||
self.cb.get_child().set_text(users[0])
|
||||
self.autocompletionButton = Gtk.Button(_(u"&Autocomplete users"))
|
||||
self.createTextArea(message, text="")
|
||||
userBox = Gtk.Box(spacing=8)
|
||||
userBox.add(label)
|
||||
userBox.add(self.cb)
|
||||
userBox.add(self.autocompletionButton)
|
||||
self.box.add(userBox)
|
||||
# self.mainBox.Add(self.cb, 0, wx.ALL, 5)
|
||||
self.box.add(self.textBox)
|
||||
self.spellcheck = Gtk.Button(_("Spelling correction"))
|
||||
self.attach = Gtk.Button(_(u"Attach audio"))
|
||||
self.shortenButton = Gtk.Button(_(u"Shorten URL"))
|
||||
self.unshortenButton = Gtk.Button(_(u"Expand URL"))
|
||||
self.shortenButton.hide()
|
||||
self.shortenButton.set_no_show_all(True)
|
||||
self.unshortenButton.hide()
|
||||
self.unshortenButton.set_no_show_all(True)
|
||||
self.translateButton = Gtk.Button(_(u"Translate message"))
|
||||
self.buttonsBox = Gtk.Box(spacing=6)
|
||||
self.buttonsBox.add(self.spellcheck)
|
||||
self.buttonsBox.add(self.attach)
|
||||
self.box.add(self.buttonsBox)
|
||||
self.buttonsBox1 = Gtk.Box(spacing=6)
|
||||
self.buttonsBox1.add(self.shortenButton)
|
||||
self.buttonsBox1.add(self.unshortenButton)
|
||||
self.buttonsBox1.add(self.translateButton)
|
||||
self.box.add(self.buttonsBox1)
|
||||
self.text.grab_focus()
|
||||
|
||||
def __init__(self, title, message, users):
|
||||
super(dm, self).__init__()
|
||||
self.createControls(message, title, users)
|
||||
# self.onTimer(wx.EVT_CHAR_HOOK)
|
||||
self.show_all()
|
||||
|
||||
def get_user(self):
|
||||
return self.cb.get_text()
|
||||
|
||||
def set_user(self, user):
|
||||
return self.cb.set_value()
|
||||
|
||||
class reply(tweet):
|
||||
def __init__(self, title, message, text):
|
||||
super(reply, self).__init__(message, title, text)
|
||||
self.text.set_position(-1)
|
||||
self.mentionAll = Gtk.Button(_(u"Men&tion to all"))
|
||||
self.mentionAll.set_no_show_all(True)
|
||||
self.mentionAll.hide()
|
||||
self.buttonsBox1.add(self.mentionAll)
|
||||
|
||||
class viewTweet(widgetUtils.baseDialog):
|
||||
def set_title(self, lenght):
|
||||
pass
|
||||
self.set_title(_(u"Tweet - %i characters ") % (lenght,))
|
||||
|
||||
def __init__(self, text, rt_count, favs_count):
|
||||
super(viewTweet, self).__init__(buttons=(Gtk.STOCK_OK, widgetUtils.OK, Gtk.STOCK_CANCEL, widgetUtils.CANCEL))
|
||||
label = Gtk.Label(_(u"Tweet"))
|
||||
self.text = Gtk.TextView()
|
||||
self.textBuffer = self.text.get_buffer()
|
||||
self.textBuffer.set_text(text)
|
||||
self.text.set_editable(False)
|
||||
# self.textBuffer.set_placeholder_text(message)
|
||||
textBox = Gtk.Box(spacing=6)
|
||||
textBox.add(label)
|
||||
textBox.add(self.text)
|
||||
self.box.add(textBox)
|
||||
rtCountLabel = Gtk.Label(_(u"Retweets: "))
|
||||
rtCount = Gtk.Entry()
|
||||
rtCount.set_text(rt_count)
|
||||
rtCount.set_editable(False)
|
||||
rtBox = Gtk.Box(spacing=2)
|
||||
rtBox.add(rtCountLabel)
|
||||
rtBox.add(rtCount)
|
||||
favsCountLabel = Gtk.Label(_(u"Favourites: "))
|
||||
favsCount = Gtk.Entry()
|
||||
favsCount.set_text(favs_count)
|
||||
favsCount.set_editable(False)
|
||||
favsBox = Gtk.Box(spacing=2)
|
||||
favsBox.add(favsCountLabel)
|
||||
favsBox.add(favsCount)
|
||||
infoBox = Gtk.Box(spacing=4)
|
||||
infoBox.add(rtBox)
|
||||
infoBox.add(favsBox)
|
||||
self.box.add(infoBox)
|
||||
self.spellcheck = Gtk.Button(_("Spelling correction"))
|
||||
self.unshortenButton = Gtk.Button(_(u"Expand URL"))
|
||||
self.unshortenButton.hide()
|
||||
self.unshortenButton.set_no_show_all(True)
|
||||
self.translateButton = Gtk.Button(_(u"Translate message"))
|
||||
buttonsBox = Gtk.Box(spacing=6)
|
||||
buttonsBox.add(self.spellcheck)
|
||||
buttonsBox.add(self.unshortenButton)
|
||||
buttonsBox.add(self.translateButton)
|
||||
self.box.add(buttonsBox)
|
||||
self.show_all()
|
||||
|
||||
def set_text(self, text):
|
||||
self.textBuffer.set_text(text)
|
||||
|
||||
def get_text(self):
|
||||
return self.textBuffer.get_text(self.textBuffer.get_start_iter(), self.textBuffer.get_end_iter(), False)
|
||||
|
||||
def text_focus(self):
|
||||
self.text.grab_focus()
|
||||
|
||||
def enable_button(self, buttonName):
|
||||
if getattr(self, buttonName):
|
||||
return getattr(self, buttonName).show()
|
||||
|
||||
class viewNonTweet(widgetUtils.baseDialog):
|
||||
|
||||
def __init__(self, text):
|
||||
super(viewNonTweet, self).__init__(buttons=(Gtk.STOCK_OK, widgetUtils.OK, Gtk.STOCK_CANCEL, widgetUtils.CANCEL))
|
||||
self.set_title(_(u"View"))
|
||||
label = Gtk.Label(_(u"Item"))
|
||||
self.text = Gtk.TextView()
|
||||
self.text.set_editable(False)
|
||||
self.text.get_buffer().set_text(text)
|
||||
textBox = Gtk.Box(spacing=5)
|
||||
textBox.add(label)
|
||||
textBox.add(self.text)
|
||||
self.box.Add(textBox)
|
||||
self.spellcheck = Gtk.Button(_("Spelling correction"))
|
||||
self.unshortenButton = Gtk.Button(_(u"Expand URL"))
|
||||
self.unshortenButton.hide()
|
||||
self.unshortenButton.set_no_show_all(True)
|
||||
self.translateButton = Gtk.Button(_(u"Translate message"))
|
||||
buttonsBox = Gtk.Box(spacing=6)
|
||||
buttonsBox.add(self.spellcheck)
|
||||
buttonsBox.add(self.unshortenButton)
|
||||
buttonsBox.add(self.translateButton)
|
||||
self.box.Add(buttonsBox)
|
||||
self.show_all()
|
||||
|
||||
def set_text(self, text):
|
||||
self.text.get_buffer().set_text()
|
||||
|
||||
def get_text(self):
|
||||
return self.text.get_buffer().get_text()
|
||||
|
||||
def text_focus(self):
|
||||
self.text.grab_focus()
|
||||
|
||||
def enable_button(self, buttonName):
|
||||
if getattr(self, buttonName):
|
||||
return getattr(self, buttonName).show()
|
@@ -1,32 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import baseDialog
|
||||
import wx
|
||||
|
||||
class searchDialog(baseDialog.BaseWXDialog):
|
||||
def __init__(self, value=""):
|
||||
super(searchDialog, self).__init__(None, -1)
|
||||
panel = wx.Panel(self)
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
self.SetTitle(_(u"Search on Twitter"))
|
||||
label = wx.StaticText(panel, -1, _(u"Search"))
|
||||
self.term = wx.TextCtrl(panel, -1, value)
|
||||
dc = wx.WindowDC(self.term)
|
||||
dc.SetFont(self.term.GetFont())
|
||||
self.term.SetSize(dc.GetTextExtent("0"*40))
|
||||
sizer.Add(label, 0, wx.ALL, 5)
|
||||
sizer.Add(self.term, 0, wx.ALL, 5)
|
||||
self.tweets = wx.RadioButton(panel, -1, _(u"Tweets"), style=wx.RB_GROUP)
|
||||
self.users = wx.RadioButton(panel, -1, _(u"Users"))
|
||||
radioSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
radioSizer.Add(self.tweets, 0, wx.ALL, 5)
|
||||
radioSizer.Add(self.users, 0, wx.ALL, 5)
|
||||
sizer.Add(radioSizer, 0, wx.ALL, 5)
|
||||
ok = wx.Button(panel, wx.ID_OK, _(u"OK"))
|
||||
ok.SetDefault()
|
||||
cancel = wx.Button(panel, wx.ID_CANCEL, _(u"Close"))
|
||||
btnsizer = wx.BoxSizer()
|
||||
btnsizer.Add(ok, 0, wx.ALL, 5)
|
||||
btnsizer.Add(cancel, 0, wx.ALL, 5)
|
||||
sizer.Add(btnsizer, 0, wx.ALL, 5)
|
||||
panel.SetSizer(sizer)
|
||||
self.SetClientSize(sizer.CalcMin())
|
@@ -1,26 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import wx
|
||||
import baseDialog
|
||||
|
||||
class showUserProfile(baseDialog.BaseWXDialog):
|
||||
def __init__(self):
|
||||
super(showUserProfile, self).__init__(parent=None, id=wx.NewId())
|
||||
panel = wx.Panel(self)
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
static = wx.StaticText(panel, -1, _(u"Details"))
|
||||
sizer.Add(static, 0, wx.ALL, 5)
|
||||
self.text = wx.TextCtrl(panel, -1, style=wx.TE_MULTILINE|wx.TE_READONLY, size=(350, 250))
|
||||
self.text.SetFocus()
|
||||
sizer.Add(self.text, 0, wx.ALL|wx.EXPAND, 5)
|
||||
self.url = wx.Button(panel, -1, _(u"Go to URL"), size=wx.DefaultSize)
|
||||
self.url.Disable()
|
||||
close = wx.Button(panel, wx.ID_CANCEL, _(u"Close"))
|
||||
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
btnSizer.Add(self.url, 0, wx.ALL, 5)
|
||||
btnSizer.Add(close, 0, wx.ALL, 5)
|
||||
sizer.Add(btnSizer, 0, wx.ALL, 5)
|
||||
panel.SetSizer(sizer)
|
||||
self.SetClientSize(sizer.CalcMin())
|
||||
|
||||
def enable_url(self, enabled=True):
|
||||
self.url.Enable(enabled)
|
@@ -1,46 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import baseDialog
|
||||
import wx
|
||||
|
||||
class trendingTopicsDialog(baseDialog.BaseWXDialog):
|
||||
def __init__(self):
|
||||
super(trendingTopicsDialog, self).__init__(None, -1)
|
||||
panel = wx.Panel(self)
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
self.SetTitle(_(u"View trending topics"))
|
||||
label = wx.StaticText(panel, -1, _(u"Trending topics by"))
|
||||
sizer.Add(label, 0, wx.ALL, 5)
|
||||
self.country = wx.RadioButton(panel, -1, _(u"Country"), style=wx.RB_GROUP)
|
||||
self.city = wx.RadioButton(panel, -1, _(u"City"))
|
||||
radioSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
radioSizer.Add(label, 0, wx.ALL, 5)
|
||||
radioSizer.Add(self.country, 0, wx.ALL, 5)
|
||||
radioSizer.Add(self.city, 0, wx.ALL, 5)
|
||||
sizer.Add(radioSizer, 0, wx.ALL, 5)
|
||||
label = wx.StaticText(panel, -1, _(u"Location"))
|
||||
self.location = wx.ListBox(panel, -1, choices=[], style=wx.CB_READONLY)
|
||||
locationBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
locationBox.Add(label, 0, wx.ALL, 5)
|
||||
locationBox.Add(self.location, 0, wx.ALL, 5)
|
||||
sizer.Add(locationBox, 0, wx.ALL, 5)
|
||||
ok = wx.Button(panel, wx.ID_OK, _(u"OK"))
|
||||
ok.SetDefault()
|
||||
cancel = wx.Button(panel, wx.ID_CANCEL, _(u"Close"))
|
||||
btnsizer = wx.BoxSizer()
|
||||
btnsizer.Add(ok, 0, wx.ALL, 5)
|
||||
btnsizer.Add(cancel, 0, wx.ALL, 5)
|
||||
sizer.Add(btnsizer, 0, wx.ALL, 5)
|
||||
panel.SetSizer(sizer)
|
||||
self.SetClientSize(sizer.CalcMin())
|
||||
|
||||
def get_active(self):
|
||||
if self.country.GetValue() == True:
|
||||
return "country"
|
||||
else:
|
||||
return "city"
|
||||
|
||||
def get_item(self):
|
||||
return self.location.GetStringSelection()
|
||||
|
||||
def set(self, values):
|
||||
self.location.Set(values)
|
@@ -1,98 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import wx
|
||||
import baseDialog
|
||||
|
||||
class updateProfileDialog(baseDialog.BaseWXDialog):
|
||||
def __init__(self):
|
||||
super(updateProfileDialog, self).__init__(parent=None, id=-1)
|
||||
self.SetTitle(_(u"Update your profile"))
|
||||
panel = wx.Panel(self)
|
||||
labelName = wx.StaticText(panel, -1, _(u"Name (20 characters maximum)"))
|
||||
self.name = wx.TextCtrl(panel, -1)
|
||||
self.name.SetFocus()
|
||||
dc = wx.WindowDC(self.name)
|
||||
dc.SetFont(self.name.GetFont())
|
||||
self.name.SetSize(dc.GetTextExtent("0"*20))
|
||||
labelLocation = wx.StaticText(panel, -1, _(u"Location"))
|
||||
self.location = wx.TextCtrl(panel, -1)
|
||||
dc = wx.WindowDC(self.location)
|
||||
dc.SetFont(self.location.GetFont())
|
||||
self.location.SetSize(dc.GetTextExtent("0"*35))
|
||||
labelUrl = wx.StaticText(panel, -1, _(u"Website"))
|
||||
self.url = wx.TextCtrl(panel, -1)
|
||||
dc = wx.WindowDC(self.url)
|
||||
dc.SetFont(self.url.GetFont())
|
||||
self.url.SetSize(dc.GetTextExtent("0"*22))
|
||||
labelDescription = wx.StaticText(panel, -1, _(u"Bio (160 characters maximum)"))
|
||||
self.description = wx.TextCtrl(panel, -1, size=(400, 400))
|
||||
dc = wx.WindowDC(self.description)
|
||||
dc.SetFont(self.description.GetFont())
|
||||
self.description.SetSize(dc.GetTextExtent("0"*160))
|
||||
self.image = None
|
||||
self.upload_image = wx.Button(panel, -1, _(u"Upload a picture"))
|
||||
self.ok = wx.Button(panel, wx.ID_OK, _(u"Update profile"))
|
||||
self.ok.SetDefault()
|
||||
close = wx.Button(panel, wx.ID_CANCEL, _("Close"))
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
nameBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
nameBox.Add(labelName, 0, wx.ALL, 5)
|
||||
nameBox.Add(self.name, 0, wx.ALL, 5)
|
||||
sizer.Add(nameBox, 0, wx.ALL, 5)
|
||||
locationBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
locationBox.Add(labelLocation, 0, wx.ALL, 5)
|
||||
locationBox.Add(self.location, 0, wx.ALL, 5)
|
||||
sizer.Add(locationBox, 0, wx.ALL, 5)
|
||||
urlBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
urlBox.Add(labelUrl, 0, wx.ALL, 5)
|
||||
urlBox.Add(self.url, 0, wx.ALL, 5)
|
||||
sizer.Add(urlBox, 0, wx.ALL, 5)
|
||||
descriptionBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
descriptionBox.Add(labelDescription, 0, wx.ALL, 5)
|
||||
descriptionBox.Add(self.description, 0, wx.ALL, 5)
|
||||
sizer.Add(descriptionBox, 0, wx.ALL, 5)
|
||||
sizer.Add(self.upload_image, 5, wx.CENTER, 5)
|
||||
btnBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
btnBox.Add(self.ok, 0, wx.ALL, 5)
|
||||
btnBox.Add(close, 0, wx.ALL, 5)
|
||||
sizer.Add(btnBox, 0, wx.ALL, 5)
|
||||
panel.SetSizer(sizer)
|
||||
self.SetClientSize(sizer.CalcMin())
|
||||
|
||||
def set_name(self, name):
|
||||
self.set("name", name)
|
||||
|
||||
def set_description(self, description):
|
||||
self.set("description", description)
|
||||
|
||||
def set_location(self, location):
|
||||
self.set("location", location)
|
||||
|
||||
def set_url(self, url):
|
||||
self.set("url", url)
|
||||
|
||||
def change_upload_button(self, uploaded=False):
|
||||
if uploaded == False:
|
||||
self.upload_image.SetLabel(_(u"Upload a picture"))
|
||||
else:
|
||||
self.upload_image.SetLabel(_(u"Discard image"))
|
||||
|
||||
def upload_picture(self):
|
||||
openFileDialog = wx.FileDialog(self, _(u"Select the picture to be uploaded"), "", "", _("Image files (*.png, *.jpg, *.gif)|*.png; *.jpg; *.gif"), wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)
|
||||
if openFileDialog.ShowModal() == wx.ID_CANCEL:
|
||||
return None
|
||||
return openFileDialog.GetPath()
|
||||
|
||||
def hide_upload_button(self, hide):
|
||||
self.upload_image.Enable(hide)
|
||||
|
||||
def set_readonly(self):
|
||||
self.name.style = wx.TE_READONLY
|
||||
self.name.Refresh()
|
||||
self.description.style = wx.TE_READONLY
|
||||
self.description.Refresh()
|
||||
self.location.style = wx.TE_READONLY
|
||||
self.location.Refresh()
|
||||
self.url.style = wx.TE_READONLY
|
||||
self.url.Refresh()
|
||||
self.hide_upload_button(False)
|
||||
self.ok.Enable(False)
|
@@ -1,35 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import wx
|
||||
|
||||
class urlList(wx.Dialog):
|
||||
def __init__(self):
|
||||
super(urlList, self).__init__(parent=None, title=_(u"Select an URL"))
|
||||
panel = wx.Panel(self)
|
||||
self.lista = wx.ListBox(panel, -1)
|
||||
self.lista.SetFocus()
|
||||
self.lista.SetSize(self.lista.GetBestSize())
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
sizer.Add(self.lista, 0, wx.ALL, 5)
|
||||
goBtn = wx.Button(panel, wx.ID_OK)
|
||||
goBtn.SetDefault()
|
||||
cancelBtn = wx.Button(panel, wx.ID_CANCEL)
|
||||
btnSizer = wx.BoxSizer()
|
||||
btnSizer.Add(goBtn, 0, wx.ALL, 5)
|
||||
btnSizer.Add(cancelBtn, 0, wx.ALL, 5)
|
||||
sizer.Add(btnSizer, 0, wx.ALL, 5)
|
||||
panel.SetSizer(sizer)
|
||||
self.SetClientSize(sizer.CalcMin())
|
||||
|
||||
def populate_list(self, urls):
|
||||
for i in urls:
|
||||
self.lista.Append(i)
|
||||
self.lista.SetSelection(0)
|
||||
|
||||
def get_string(self):
|
||||
return self.lista.GetStringSelection()
|
||||
|
||||
def get_item(self):
|
||||
return self.lista.GetSelection()
|
||||
|
||||
def get_response(self):
|
||||
return self.ShowModal()
|