Compare commits

..

109 Commits

Author SHA1 Message Date
437f01ac78 Merge branch 'master' of https://github.com/manuelcortez/twblue 2015-01-13 08:51:41 -06:00
fd6c7fa2d7 Changes for the 0.51 version 2015-01-13 08:51:03 -06:00
jmdaweb
b373e716c7 pa.c format: appinfo.ini: fixed package version. 2015-01-12 21:15:40 +01:00
cc00c513c3 Merge branch 'master' of https://github.com/manuelcortez/twblue 2015-01-12 11:22:33 -06:00
jmdaweb
0a0fe58715 readme.md: fixed duplicated package name. 2015-01-12 17:12:54 +01:00
e831098bd2 Merge branch 'master' of https://github.com/manuelcortez/twblue 2015-01-12 10:02:39 -06:00
jmdaweb
05d62456ee Installer: updated website. Application.py: changed version to 0.51. Main.py: redirect stdout and stderr to log files located in temp folder. 2015-01-12 16:54:19 +01:00
d2e6221432 Commit for 0.51 release 2015-01-12 09:25:07 -06:00
jmdaweb
d31a3e5bb7 Installer script: updated to version 0.51, updated website, added german translation. Added the portableApps template used to package TWBlue in portableApps.com format 2015-01-08 16:12:37 +01:00
e3b0a3d731 Fix for the last commit 2015-01-08 08:11:33 -06:00
3a6849cf0b the Webdomain for TWBlue has been changed 2015-01-08 08:09:20 -06:00
6832a4a93e Merge branch 'master' of https://github.com/manuelcortez/twblue 2015-01-01 21:08:36 -06:00
jmdaweb
bda1ddce47 updated readme file 2014-12-30 22:56:31 +01:00
b106b3a0f2 updated readme 2014-12-29 14:27:34 -06:00
813ad2fc1e Merge branch 'master' of https://github.com/manuelcortez/twblue 2014-12-29 13:53:26 -06:00
4bcd8d8b4e Updated readme; a few bugfixes; german translation is added 2014-12-29 13:52:50 -06:00
jmdaweb
4ef7c6c5f1 Updated pyenchant to version 1.6.6 in windows dependencies submodule 2014-12-26 20:10:58 +01:00
b6c9edafcf Merge branch 'master' of https://github.com/manuelcortez/twblue 2014-12-24 12:07:32 -06:00
73be8400b0 a few bugfixes in date representations. Fix for #14 2014-12-24 12:06:28 -06:00
jmdaweb
5fdbb578c4 removed setuptools from windows dependencies submodule 2014-12-24 10:51:27 +01:00
jmdaweb
540bf5d312 updated windows dependencies with the new python 2.7.9 2014-12-20 00:20:07 +01:00
375cdd2528 0.50 Release changes. Last commit for this year. 2014-12-18 00:59:18 -06:00
jmdaweb
836675bfa1 New sound for trending topics, updated contributors in application.py 2014-12-16 22:12:29 +01:00
jmdaweb
2b3c7601f2 Merge branch 'master' of https://github.com/manuelcortez/TWBlue 2014-12-15 18:10:55 +01:00
eb2c315abb Bugfixes for lists buffers and autocomplete 2014-12-15 09:53:13 -06:00
e12f440cf2 Build_installer fixes 2014-12-14 19:07:18 -06:00
jmdaweb
57dc271fb0 Merge branch 'master' of https://github.com/manuelcortez/TWBlue 2014-12-12 19:33:37 +01:00
193cafcc9d A bash script to create TWBlue installer versions has been added 2014-12-12 12:21:59 -06:00
jmdaweb
e7b6c39f76 Merge branch 'master' of https://github.com/manuelcortez/TWBlue 2014-12-12 11:26:19 +01:00
7df2441442 Fixes for the Snapshot6 compilation process 2014-12-11 15:37:53 -06:00
jmdaweb
aa687450f6 Merge branch 'master' of https://github.com/manuelcortez/TWBlue 2014-12-11 21:52:01 +01:00
6e0ae38d4e Code changes for Snapshot 6 2014-12-11 12:21:37 -06:00
jmdaweb
fa8c9f639c Merge branch 'master' of https://github.com/manuelcortez/TWBlue 2014-12-11 17:26:02 +01:00
9502cef251 Final additions for TWBlue 0.50. TWBlue's source code has been frozen 2014-12-11 10:03:02 -06:00
jmdaweb
982dd78f81 Merge branch 'master' of https://github.com/manuelcortez/TWBlue 2014-12-11 16:26:30 +01:00
jmdaweb
4b98f27968 Now TWBlue.exe.log shouldn't be created, so admin rights aren't required the first time in the installed version. 2014-12-11 16:25:22 +01:00
jmdaweb
ecb0fa8f2b Merge branch 'master' of https://github.com/manuelcortez/TWBlue 2014-12-10 20:04:17 +01:00
ef2ff9dbfc This tries to fix the bug related to stdout and stderr for TWBlue installed 2014-12-10 12:44:11 -06:00
jmdaweb
1fe94642a2 Merge branch 'master' of https://github.com/manuelcortez/TWBlue 2014-12-10 18:33:18 +01:00
b232a0b0ad Ignoring clients improvements: adding clients from the action users dialog does always work, no matters the buffer the client is added 2014-12-10 11:19:38 -06:00
2ce59cf208 Autocompletion improvements. Adding/removing users manually is now possible. 2014-12-09 17:56:43 -06:00
jmdaweb
ceb8266828 Merge branch 'master' of https://github.com/manuelcortez/TWBlue 2014-12-09 17:10:44 +01:00
jmdaweb
21970f2c94 installer: now two radio buttons are displayed in the license page. 2014-12-09 17:10:03 +01:00
14965f73d3 Invisible shorcuts no blocks itself when passes through the events buffer 2014-12-09 08:26:33 -06:00
jmdaweb
267b454fc6 Merge branch 'master' of https://github.com/manuelcortez/TWBlue 2014-12-09 10:36:30 +01:00
c3dc00c241 Mantis support is back on TWBlue 2014-12-08 22:06:44 -06:00
jmdaweb
9fb67f01ae Merge branch 'master' of https://github.com/manuelcortez/TWBlue 2014-12-08 20:49:05 +01:00
6d1cd0b1fc The mention all button works as espected when someone replies to a retweet 2014-12-08 13:38:27 -06:00
a7ef572d05 Now, TWBlue does not block the system when any session is closed or turned off 2014-12-08 12:46:29 -06:00
403784b77a The switcher module does not close the app when it is cancelled. 2014-12-08 10:17:07 -06:00
d032a6d8f7 Use invisible interface's keyboard shorcuts even if the window is displayed 2014-12-08 09:44:02 -06:00
jmdaweb
231d43ab22 Merge branch 'master' of https://github.com/manuelcortez/TWBlue 2014-12-08 00:32:46 +01:00
5e3bcfc82e Mentions are detected even if username's capitalization is incorrect 2014-12-07 13:24:56 -06:00
8e92d97260 Trending topic buffers are removed from configuration 2014-12-07 12:22:19 -06:00
bb1ffa9ff1 Merge branch 'master' of https://github.com/manuelcortez/twblue 2014-12-07 09:31:46 -06:00
104bc4ec8c Changes for Snapshot 5 release 2014-12-07 09:31:39 -06:00
jmdaweb
6ae555fe72 Merge branch 'master' of https://github.com/manuelcortez/TWBlue 2014-12-06 20:18:10 +01:00
jmdaweb
dd51516c30 Improved installer script. In the finish page, it shows a checkbox to run TW Blue, and a button to go to the website. Modified installer version to 0.50 2014-12-06 20:17:21 +01:00
jmdaweb
4e18bb0721 Merge branch 'master' of https://github.com/manuelcortez/TWBlue 2014-12-06 00:09:11 +01:00
jmdaweb
0492e65aa0 Merge branch 'master' of github.com:manuelcortez/TWBlue 2014-12-06 00:08:43 +01:00
jmdaweb
a5fb59d7a7 fixed submodule 2014-12-06 00:08:09 +01:00
f2fab29cb7 Trending topics improvements 2014-12-05 17:05:29 -06:00
jmdaweb
f36accf89b Merge branch 'master' of https://github.com/manuelcortez/TWBlue 2014-12-06 00:01:21 +01:00
a13536233e Improvements on autocomplete, now it updates its database at startup 2014-12-05 16:23:54 -06:00
bc2d448464 Updated translations 2014-12-05 12:21:40 -06:00
60ec9ab215 Date is displayed properly in the GUI 2014-12-05 11:31:58 -06:00
20b5fc079b onFocus will play the ogg file instead the mp3 2014-12-05 11:25:29 -06:00
80e231b689 Merge branch 'master' of https://github.com/manuelcortez/twblue 2014-12-05 11:21:27 -06:00
7137d437bd Basic tt support, fixed some English mistakes reported by @sukiletxe 2014-12-05 11:20:55 -06:00
jmdaweb
a07b3c1829 Merge branch 'master' of https://github.com/manuelcortez/TWBlue 2014-12-02 23:36:47 +01:00
jmdaweb
c062c10542 Converted the geo sound to ogg format 2014-12-02 23:35:37 +01:00
jmdaweb
0e7c070bd4 Merge branch 'master' of https://github.com/manuelcortez/TWBlue 2014-12-02 22:18:45 +01:00
jmdaweb
9f35d079b1 Updated windows-dependencies submodule with the new pycurl 2014-12-02 22:18:11 +01:00
jmdaweb
a3fca4d2a0 Merge branch 'master' of https://github.com/manuelcortez/TWBlue 2014-12-02 21:27:00 +01:00
ada6f1fb0d Fixing some issues with tweets and retweets 2014-12-02 11:40:39 -06:00
79124810b0 Reverse geocode is now in TWBlue. Ctrl+win+g and CTRL+Shift+Win+G and in the tweet menu on the menu bar 2014-12-01 17:19:03 -06:00
fee7254d55 Configuration for autocompletion users 2014-12-01 15:21:25 -06:00
jmdaweb
c12902d011 Merge branch 'master' of https://github.com/manuelcortez/TWBlue 2014-12-01 13:14:36 +01:00
2f7eb12104 There is a context menu on buffers. When the applications key or the right mouse button is pressed that menu is displayed. It only works for the GUI 2014-12-01 05:55:25 -06:00
855cefeb8d Now the session manager does not appear ramdonly 2014-11-30 22:35:48 -06:00
e649b883c6 gendoc script has been deletedo so it isn't necessary 2014-11-30 17:43:00 -06:00
jmdaweb
1a61f2d790 Merge branch 'master' of https://github.com/manuelcortez/TWBlue 2014-11-30 22:26:33 +01:00
jmdaweb
6abfba317a updated windows dependencies submodule 2014-11-30 22:25:50 +01:00
jmdaweb
18ce92daab Merge branch 'master' of https://github.com/manuelcortez/TWBlue 2014-11-30 11:19:03 +01:00
jmdaweb
84f729f42b Now setup.py shouldn't include an unnecesary mfc90.dll in x64 builds 2014-11-30 11:17:26 +01:00
jmdaweb
4e7666cf52 Merge branch 'master' of https://github.com/manuelcortez/TWBlue 2014-11-30 00:42:56 +01:00
88e0fbb531 Updated readmes 2014-11-29 11:29:22 -06:00
af32b3ceb6 Merge branch 'master' of github.com:manuelcortez/TWBlue 2014-11-29 11:09:39 -06:00
94dc083650 Windows-dependencies fix 2014-11-29 11:09:33 -06:00
acb3cce1d6 Changes on snapshot 4; audio uploader fixes 2014-11-29 11:07:06 -06:00
jmdaweb
2b3e1099f6 Merge branch 'master' of https://github.com/manuelcortez/TWBlue 2014-11-27 22:05:21 +01:00
jmdaweb
60507e8f6b Pressing enter, spacebar or mouse left click should show window if it's not visible 2014-11-27 17:31:10 +01:00
jmdaweb
75bfc17bb1 Merge branch 'master' of github.com:manuelcortez/TWBlue 2014-11-27 17:19:08 +01:00
acb8c5acd3 TWBlue starts automatically if there is only an account 2014-11-27 07:18:05 -06:00
jmdaweb
5bcf04fc94 Merge branch 'master' of github.com:manuelcortez/TWBlue 2014-11-27 10:12:54 +01:00
0f2fbc775a Switch account is now possible from the application menu 2014-11-26 17:26:53 -06:00
1b684cd12c The session manager has a remove account button 2014-11-26 16:38:46 -06:00
9d64901791 Session manager deletes invalid sessions; plays audio from any URL when the tweet has more than one 2014-11-26 13:45:24 -06:00
18f7cb6c96 Replies will not show on list buffers 2014-11-26 11:52:36 -06:00
7f673fb9de Show more information about tweets on the ViewTweets dialog 2014-11-26 05:43:13 -06:00
jmdaweb
f6f542fbec Merge branch 'master' of https://github.com/manuelcortez/TWBlue 2014-11-25 23:09:33 +01:00
jmdaweb
a211e2e5e4 Merge branch 'master' of github.com:manuelcortez/TWBlue 2014-11-25 22:49:12 +01:00
3ec8ac31a5 Autocompletion for users has been implemented 2014-11-25 12:30:00 -06:00
jmdaweb
dacbb19586 added the windows dependencies as a git submodule, so the users can get them only if they plan to build a binary version 2014-11-25 14:44:59 +01:00
jmdaweb
55691cca20 Fixed setup.py, now it takes the correct bootstrap.exe in x64 builds 2014-11-24 17:26:35 +01:00
0104b97df0 Merge branch 'master' of github.com:manuelcortez/TWBlue 2014-11-21 11:39:35 -06:00
aa58e61e5e TWBlue shows followers and friends in realtime again 2014-11-21 11:37:41 -06:00
jmdaweb
fae204f3c2 updated windows build instructions 2014-11-19 16:07:55 +01:00
d8149a4c96 TWBlue has access to the direct messages on all accounts 2014-11-14 16:05:34 -06:00
333 changed files with 42602 additions and 57869 deletions

8
.gitignore vendored
View File

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

View File

@@ -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 youll 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 its running. With this app youll 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 youll have access to twitter features such as:
* See your friends and followers,
* Follow, unfollow, block and report users as spam,
* Open a users timeline, which will allow you to get that users 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.

View File

@@ -1,5 +1,4 @@
Manuel E. Cortéz
Bill Dengler
Johana Hidrobo
Marcelo Sosa
Isabel del Castillo

View File

@@ -1,7 +0,0 @@
# -*- coding: utf-8 -*-
name = 'TWBlue'
snapshot = False
if snapshot == False:
version = "0.80"
else:
version = "7"

View File

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

View File

@@ -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";
}

View File

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

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

Before

Width:  |  Height:  |  Size: 182 KiB

After

Width:  |  Height:  |  Size: 182 KiB

View File

Before

Width:  |  Height:  |  Size: 379 B

After

Width:  |  Height:  |  Size: 379 B

View File

Before

Width:  |  Height:  |  Size: 103 B

After

Width:  |  Height:  |  Size: 103 B

View File

Before

Width:  |  Height:  |  Size: 119 B

After

Width:  |  Height:  |  Size: 119 B

View File

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

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 168 B

After

Width:  |  Height:  |  Size: 168 B

View File

Before

Width:  |  Height:  |  Size: 269 B

After

Width:  |  Height:  |  Size: 269 B

View File

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

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

View File

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

View File

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

View File

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

View File

@@ -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="")

View File

@@ -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 its running. With this app youll 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'

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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"])

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@@ -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"])

View File

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

@@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
""" Handles storage from a durus database """
class db(object):
def __init__(self):
self.settings = {}

View File

@@ -0,0 +1,3 @@
import gui, transfer, transfer_dialogs, platform
if platform.system() != "Darwin":
import dropbox

View File

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

View File

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

View 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()

View File

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

View File

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

View File

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

View File

@@ -1 +1 @@
from soundsTutorial import soundsTutorial
import gui

View File

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

View 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()])

View File

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

View File

@@ -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()],))

View File

@@ -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."))])

View File

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

View File

@@ -1,4 +0,0 @@
import spellchecker
import platform
if platform.system() == "Windows":
from wx_ui import *

View 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()

View File

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

View File

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

View File

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

View File

@@ -1,2 +1 @@
# -*- coding: utf-8 -*-
import completion, settings

View File

@@ -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."))

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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"),

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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 = []

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1 +0,0 @@
#import trends, configuration, lists, message, search, show_user, update_profile, urlList, userSelection, utils

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

Some files were not shown because too many files have changed in this diff Show More