Compare commits

...

79 Commits

Author SHA1 Message Date
7ed44c839e New snapshot 2015-10-23 11:36:36 -05:00
503c65692d FFix for creating favourites timelines 2015-10-23 11:33:56 -05:00
f76b86b24d A sound bugfix 2015-10-23 11:29:59 -05:00
1f96e71b63 workaround for duplicated tweets 2015-10-23 11:28:54 -05:00
Jose Manuel Delicado
adf062f654 Now com cache is stored in the config folder, so program files folder keeps untouched on installed copies. Updated contributors in application.py, fixed spelling in some comments in main.py 2015-10-18 12:19:43 +02:00
70b5f25cf0 New snapshot 2015-10-15 08:55:54 -05:00
2b65b89afb Disabled translation service 2015-10-15 08:54:30 -05:00
44e8ed6456 Removed send errors in some functions 2015-10-14 20:38:42 -05:00
792655e299 Improved stream reconnection 2015-10-14 17:30:41 -05:00
0f56d8cdd4 Quoted tweets again 2015-10-14 17:07:57 -05:00
6c47dd2fa9 Some fixes for URL Player 2015-10-14 17:07:30 -05:00
Jose Manuel Delicado
49073bc151 Added new packages to readme.md. Now setup.py adds wx localization files to the binary version. 2015-10-04 18:15:09 +02:00
Jose Manuel Delicado
336acd9860 updated translations 2015-10-03 13:25:23 +02:00
4daeeb7beb Disable some things before snapshot 2015-10-03 05:12:22 -05:00
408ff50404 New snapshot 2015-10-03 04:55:02 -05:00
148c5176c6 Reverted quoted tweets support 2015-10-03 04:34:43 -05:00
bdb9de863f A fw bugfixes 2015-10-02 15:52:08 -05:00
ce1f8b2cc3 New snapshot 2015-09-29 09:39:47 -05:00
5933323beb Updated translation templates 2015-09-29 09:38:39 -05:00
22b1b0a149 Added posibility for search a term in trending topics 2015-09-29 09:37:04 -05:00
e71afeb10f View other user's lists is implemented 2015-09-29 09:22:19 -05:00
98f026156d Fixed search in application menu 2015-09-29 08:42:04 -05:00
cbee57aa30 Quoted tweets support in buffers 2015-09-29 08:38:05 -05:00
fd9e4dc05d New snapshot 2015-09-23 10:01:43 -05:00
6022cecad1 Added japanese, croatian and serbian 2015-09-23 10:01:22 -05:00
89e39e2168 Double tweets should be ignored in streams 2015-09-23 10:01:00 -05:00
a69bf99c1a If there is no locale for language, use English in arrow 2015-09-23 10:00:14 -05:00
d34ef81324 Updated locales 2015-09-23 09:59:34 -05:00
a3c050195a Twishort retweets are displayed as espected 2015-09-17 09:00:30 -05:00
3623eafacd handle_longtweets is enabled by default 2015-09-17 08:59:59 -05:00
Sukil Etxenike
2bd3f0a1d1 Updated docs with contributors 2015-09-06 23:09:14 +02:00
f1f828522e Translation templates updated 2015-09-05 11:46:34 -05:00
51e4898346 Add shorcuts to the audio upload dialogue 2015-09-05 11:42:47 -05:00
c4478198b6 NEw snapshot 2015-08-31 11:18:10 -05:00
f468924b85 Merge branch 'next-gen' of https://github.com/manuelcortez/TWBlue into next-gen 2015-08-31 11:03:54 -05:00
158b48e4d5 Add and remove user to list are implemented in GUI 2015-08-31 10:08:34 -05:00
756a58e443 New timeline sound is played again 2015-08-31 08:42:28 -05:00
85ce5b0791 Trending topics now have their names at startup 2015-08-31 08:15:37 -05:00
Jose Manuel Delicado
e534d1cd20 Updated readme. 2015-08-28 11:47:54 +02:00
2d35304ef0 New snapshot 2015-08-27 08:13:01 -05:00
4f0e6d758b Restores buffer positions at startup using cached database 2015-08-25 13:37:31 -05:00
bd4aa89c2b Added text_focus() in some actions to the tweet dialogue 2015-08-24 10:00:34 -05:00
b046360293 Added right click menu in buffers 2015-08-24 09:54:15 -05:00
6971fb3999 Bugfix in retweet with comment 2015-08-21 09:55:05 -05:00
7b840f29c4 Keystroke editor can execute the actions directly 2015-08-21 09:51:01 -05:00
71fed7300b IF there are no tweets or favs, the timeline is not created 2015-08-21 09:12:54 -05:00
57315c3b6e open_timeline() cleaned 2015-08-21 08:57:15 -05:00
3d3abc90e1 Expanded URL are displayed in the view tweet dialogue 2015-08-20 17:57:06 -05:00
de7882e4cf Logout session improvements 2015-08-20 17:32:27 -05:00
jmdaweb
10190d61c0 Fixed windows dependencies submodule. Please, don't forget to run git submodule update before sending a commit or pull request. 2015-08-19 13:38:10 +02:00
bb6fa7cb46 logout() now removes database for the session 2015-08-19 05:28:56 -05:00
80cb70c9a6 Merge branch 'next-gen' of https://github.com/manuelcortez/TWBlue into next-gen 2015-08-18 08:05:21 -05:00
77d51aa51a New snapshot 2015-08-18 08:04:58 -05:00
jmdaweb
ebb4e22d02 Updated Windows dependencies. Now wx buttons and messages should be localized. 2015-08-16 15:42:17 +02:00
4344a0df0c Get full text for dm buffers 2015-08-12 17:21:00 -05:00
34ad0c5e47 Reconnecting streams every 5 mins 2015-08-12 16:43:23 -05:00
704ade560a Increasing character limit for direct messages 2015-08-12 15:57:29 -05:00
a4892cf847 TWBlue does not change the current session in invisible interface 2015-08-11 08:58:11 -05:00
e59661775a Updated translations 2015-08-10 09:49:16 -05:00
53a9f04155 New snapshot 2015-08-10 09:28:47 -05:00
100f483a86 List with special characters are handled properly 2015-08-10 09:26:07 -05:00
bad468560a Saving unicode keys as string objects in cache database 2015-08-10 09:24:46 -05:00
eb0cf62a54 A better way to save keymaps 2015-08-10 09:21:51 -05:00
a016932ac7 Timelines fix 2015-08-08 09:42:55 -05:00
1706414171 Timelines order improvements 2015-08-07 16:44:33 -05:00
5f963aa66b Modified windows 10 keymap 2015-08-07 14:05:22 -05:00
25578e4fc6 Fixed #59 2015-08-07 09:05:59 -05:00
faec92ce6c Stream connection improvements 2015-08-06 13:54:26 -05:00
313e725ff2 Autocompletion now works in the actions dialogue 2015-08-06 13:16:55 -05:00
3f82a51ef9 Added a new contributor 2015-08-06 12:07:30 -05:00
d26ab9b910 Fixed bug when opening multiple timelines 2015-08-06 12:03:40 -05:00
aa42e056c0 Updated translation templates 2015-08-04 13:40:16 -05:00
fa6592ed1a Fixed a string 2015-08-04 13:39:57 -05:00
11b06accbb Merge pull request #61 from codeofdusk/stringcleanup
String Cleanup
2015-08-04 13:27:50 -05:00
Sukil Etxenike
915eb5802f Fixed Basque locale 2015-08-02 00:04:04 +02:00
Bill Dengler
4e943c7bee String cleanup. 2015-07-30 14:15:26 -04:00
Bill Dengler
692d75562e String cleanup. 2015-07-30 14:03:52 -04:00
4cce6d4318 Bugfixes 2015-07-30 11:19:20 -05:00
e55e15466d Fixed some bugs 2015-07-30 09:06:56 -05:00
87 changed files with 22522 additions and 21162 deletions

View File

@@ -39,7 +39,7 @@ If you want to build both x86 and x64 binaries, you can install python x86 to C:
* [Pycurl](http://pycurl.sourceforge.net) 7.19.5.1 for Python 2.7: [32-bit downloads,](https://pypi.python.org/pypi/pycurl/7.19.5.1) [64-bit downloads](http://www.lfd.uci.edu/~gohlke/pythonlibs/)
Note: the x64 version is in wheel format instead of executable installer, so you have to install it using pip. For example: C:\python27x64\scripts\pip install pycurl-7.19.5.1-cp27-none-win_amd64.whl
* [PyEnchant,](http://pythonhosted.org/pyenchant/) version 1.6.6.
x64 version has been built by TW Blue developers, so you only will find it in windows-dependencies folder
x64 version has been built by TWBlue developers, so you only will find it in windows-dependencies folder
The windows installers are available only in the windows-dependencies folder
@@ -71,8 +71,11 @@ setuptools install a script, called easy_install. You can find it in the python
* arrow
* goslate
* markdown
* pocket
easy_install will automatically get the additional libraries that these packages need to work properly.
Run the following command to quickly install and upgrade all packages and their dependencies:
easy_install -Z --upgrade six configobj goslate markdown future pocket suds requests oauthlib requests-oauthlib pypubsub pygeocoder arrow python-dateutil futures
#### Other dependencies
@@ -95,9 +98,16 @@ Now that you have installed all these packages, you can run TW Blue from source
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
### Generating the documentation
To generate the documentation in html format, navigate to the doc folder inside this repo. After that, run this command:
python generator.py
The documentation will be generated, placing each language in a separate folder in the doc directory. Move these folders (for example de, en, es, fr, it, ...) to src/documentation, creating the directory if necesary.
Also, copy the license.txt located in the root of the repo to the documentation folder.
### 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 on the TW Blue website if you download the zip files or the snapshot versions.
To build it, run the following command from the src folder:
@@ -105,6 +115,17 @@ To build it, run the following command from the src folder:
You will find the binaries in the dist directory.
### Building an installer
If you want to install TWBlue in your computer, you must create the installer first. Follow these steps:
* Navigate to the src directory, and create a binary version for x86: C:\python27\python setup.py py2exe
* Move the dist directory to the scripts folder in this repo, and rename it to twblue
* Repeat these steps with Python for x64: C:\python27x64\python setup.py py2exe
* Move the new dist directory to the scripts folder, and rename it to twblue64
* Go to the scripts folder, right click on the twblue.nsi file, and choose compyle unicode NSIS script
* This may take a while. After the process, you will find the installer in the scripts 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.

View File

@@ -34,3 +34,4 @@ Holly Scott-Gardner
Anibal Hernández
Sussan Leiva
Brian Hartgen
PEDRO REINA COLOBON

View File

@@ -163,7 +163,7 @@ documentation.append(_(u"""* Lists Manager: This dialogue box allows you to mana
documentation.append(_(u"""* Edit keystrokes: this opens a dialogue where you can see and edit the shortcuts used in the invisible interface."""))
documentation.append(_(u"""* Account settings: Opens a dialogue box which lets you customize settings for the current account."""))
documentation.append(_(u"""* Global settings: Opens a dialogue which lets you configure settings for the entire application."""))
documentation.append(_(u"""* Quit: asks whether you want to exit the program. If the answer is yes, it closes the application. If you do not want to be asked for confirmation before exiting, uncheck the checkbox from the global settings dialogue box."""))
documentation.append(_(u"""* Exit: asks whether you want to exit the program. If the answer is yes, it closes the application. If you do not want to be asked for confirmation before exiting, uncheck the checkbox from the global settings dialogue box."""))
documentation.append(_(u"""
"""))
documentation.append(_(u"""##### Tweet menu"""))
@@ -405,19 +405,21 @@ documentation.append(_(u"""We would also like to thank the translators of TWBlue
documentation.append(_(u"""
"""))
documentation.append(_(u"""* English: [Bryner Villalobos](https://twitter.com/Bry_StarkCR) and [Bill Dengler](https://twitter.com/codeofdusk)."""))
documentation.append(_(u"""* Arabic: Mohammed Al Shara."""))
documentation.append(_(u"""* Arabic: [Mohammed Al Shara](https://twitter.com/mohammed0204)."""))
documentation.append(_(u"""* Catalan: [Joan Rabat](https://twitter.com/joanrabat) and Juan Carlos Rivilla."""))
documentation.append(_(u"""* Spanish: [Manuel Cortéz](https://twitter.com/manuelcortez00)."""))
documentation.append(_(u"""* Basque: [Sukil Etxenike](https://twitter.com/sukil2011)."""))
documentation.append(_(u"""* Finnish: Jani Kinnunen."""))
documentation.append(_(u"""* French: Rémi Ruiz."""))
documentation.append(_(u"""* Finnish: [Jani Kinnunen](https://twitter.com/jani_kinnunen)."""))
documentation.append(_(u"""* French: [Rémi Ruiz](https://twitter.com/blindhelp38)."""))
documentation.append(_(u"""* Galician: [Alba Kinteiro](https://twitter.com/albasmileforeve)."""))
documentation.append(_(u"""* German: Steffen Schultz."""))
documentation.append(_(u"""* German: [Steffen Schultz](https://twitter.com/schulle4u)."""))
documentation.append(_(u"""* Croatian: [Zvonimir Stanečić](https://twitter.com/zvonimirek222)."""))
documentation.append(_(u"""* Hungarian: Robert Osztolykan."""))
documentation.append(_(u"""* Italian: [Christian Leo Mameli](https://twitter.com/llajta2012)."""))
documentation.append(_(u"""* Polish: Pawel Masarczyk."""))
documentation.append(_(u"""* Portuguese: Odenilton Júnior Santos."""))
documentation.append(_(u"""* Russian: Alexander Jaszyn."""))
documentation.append(_(u"""* Turkish: Burak."""))
documentation.append(_(u"""* Russian: [Александр Яшин](https://twitter.com/radovest)."""))
documentation.append(_(u"""* Turkish: [Burak Yüksek](https://twitter.com/burakyuksek)."""))
documentation.append(_(u"""
"""))
documentation.append(_(u"""Many thanks also to the people who worked on the documentation. Initially, [Manuel Cortez](https://twitter.com/manuelcortez00) did the documentation in Spanish, and translated to English by [Bryner Villalobos](https://twitter.com/Bry_StarkCR), [Robert Spangler](https://twitter.com/glasscity1837), [Sussan Rey](https://twitter.com/sussanrey17), [Anibal Hernandez](https://twitter.com/anibalmetal), and [Holly Scott-Gardner](https://twitter.com/holly1994). It was updated by [Sukil Etxenike](https://twitter.com/sukil2011), with some valuable corrections by [Brian Hartgen](https://twitter.com/brianhartgen) and [Bill Dengler](https://twitter.com/codeofdusk)."""))

View File

@@ -8,7 +8,7 @@ language = string(default="system")
hide_gui = boolean(default=False)
voice_enabled = boolean(default=False)
ask_at_exit = boolean(default=True)
handle_longtweets = boolean(default=False)
handle_longtweets = boolean(default=True)
use_invisible_keyboard_shorcuts = boolean(default=True)
play_ready_sound = boolean(default=True)
speak_ready_msg = boolean(default=True)

View File

@@ -5,12 +5,12 @@ if snapshot == False:
version = "0.80"
update_url = 'http://twblue.es/updates/twblue_ngen.json'
else:
version = "9.10"
version = "10.93"
update_url = 'http://twblue.es/updates/snapshots_ngen.json'
author = u"Manuel Cortéz, Bill Dengler"
author = u"Manuel Cortéz"
authorEmail = "manuel@manuelcortez.net"
copyright = u"Copyright (C) 2015, Technow S.L. \nCopyright (C) 2015, Bill Dengler\nCopyright (C) 2013-2015, Manuel cortéz."
copyright = u"Copyright (C) 2015, Technow S.L. \nCopyright (C) 2013-2015, Manuel cortéz."
description = unicode(name+" is an app designed to use Twitter simply and efficiently while using minimal system resources. This app provides access to most Twitter features.")
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)"]
translators = [u"Bryner Villalobos, Bill Dengler (English)", u"Mohammed Al Shara (Arabic)", u"Joan Rabat, Juan Carlos Rivilla (Catalan)", u"Manuel cortéz (Spanish)", u"Sukil Etxenike Arizaleta (Basque)", u"Jani Kinnunen (finnish)", u"Rémy Ruiz (French)", u"Juan Buño (Galician)", u"Steffen Schultz (German)", u"Robert Osztolykan (Hungarian)", u"Paweł Masarczyk (Polish)", u"Odenilton Júnior Santos (Portuguese)", u"Alexander Jaszyn (Russian)", u"Burak (Turkish)"]
url = u"http://twblue.es"
report_bugs_url = "http://twblue.es/bugs/api/soap/mantisconnect.php?wsdl"

View File

@@ -16,4 +16,4 @@ def setup ():
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'))
keymap = config_utils.load_config(paths.config_path("keymap.keymap"), paths.app_path("keymaps/"+app['app-settings']['load_keymap']))

View File

@@ -2,7 +2,7 @@
import platform
if platform.system() == "Windows":
import wx
from wxUI import buffers, dialogs, commonMessageDialogs
from wxUI import buffers, dialogs, commonMessageDialogs, menus
import user
elif platform.system() == "Linux":
from gi.repository import Gtk
@@ -142,6 +142,13 @@ class bufferController(object):
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()
def save_positions(self):
try:
self.session.db[self.name+"_pos"]=self.buffer.list.get_selected()
except AttributeError:
pass
class accountPanel(bufferController):
def __init__(self, parent, name, account, account_id):
super(accountPanel, self).__init__(parent, None, name)
@@ -224,7 +231,8 @@ class baseBufferController(bufferController):
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"]))
tweet = self.get_right_tweet()
return " ".join(self.compose_function(tweet, self.session.db, self.session.settings["general"]["relative_times"]))
def get_full_tweet(self):
tweet = self.get_right_tweet()
@@ -235,6 +243,10 @@ class baseBufferController(bufferController):
uri = tweet["long_uri"]
try:
tweet = self.session.twitter.twitter.show_status(id=tweet_id)
urls = utils.find_urls_in_text(tweet["text"])
for url in range(0, len(urls)):
try: tweet["text"] = tweet["text"].replace(urls[url], tweet["entities"]["urls"][url]["expanded_url"])
except IndexError: pass
except TwythonError as e:
utils.twitter_error(e)
return
@@ -246,6 +258,10 @@ class baseBufferController(bufferController):
id = tweets.get_id(l)
try:
tweet = self.session.twitter.twitter.show_status(id=id)
urls = utils.find_urls_in_text(tweet["text"])
for url in range(0, len(urls)):
try: tweet["text"] = tweet["text"].replace(urls[url], tweet["entities"]["urls"][url]["expanded_url"])
except IndexError: pass
except TwythonError as e:
utils.twitter_error(e)
return
@@ -345,8 +361,8 @@ class baseBufferController(bufferController):
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)
# if platform.system() == "Windows":
# call_threaded(utils.is_audio,item)
def bind_events(self):
log.debug("Binding events...")
@@ -357,6 +373,61 @@ class baseBufferController(bufferController):
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)
# Replace for the correct way in other platforms.
widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_ITEM_RIGHT_CLICK, self.show_menu)
widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_KEY_DOWN, self.show_menu_by_key)
def show_menu(self, ev, pos=0, *args, **kwargs):
if self.buffer.list.get_count() == 0: return
if self.name == "sent_tweets" or self.name == "sent_direct_messages":
menu = menus.sentPanelMenu()
elif self.name == "direct_messages":
menu = menus.dmPanelMenu()
widgetUtils.connect_event(menu, widgetUtils.MENU, self.direct_message, menuitem=menu.reply)
widgetUtils.connect_event(menu, widgetUtils.MENU, self.user_actions, menuitem=menu.userActions)
else:
menu = menus.basePanelMenu()
widgetUtils.connect_event(menu, widgetUtils.MENU, self.reply, menuitem=menu.reply)
widgetUtils.connect_event(menu, widgetUtils.MENU, self.user_actions, menuitem=menu.userActions)
widgetUtils.connect_event(menu, widgetUtils.MENU, self.retweet, menuitem=menu.retweet)
widgetUtils.connect_event(menu, widgetUtils.MENU, self.fav, menuitem=menu.fav)
widgetUtils.connect_event(menu, widgetUtils.MENU, self.unfav, menuitem=menu.unfav)
widgetUtils.connect_event(menu, widgetUtils.MENU, self.url_, menuitem=menu.openUrl)
widgetUtils.connect_event(menu, widgetUtils.MENU, self.audio, menuitem=menu.play)
widgetUtils.connect_event(menu, widgetUtils.MENU, self.view, menuitem=menu.view)
widgetUtils.connect_event(menu, widgetUtils.MENU, self.copy, menuitem=menu.copy)
widgetUtils.connect_event(menu, widgetUtils.MENU, self.destroy_status, menuitem=menu.remove)
if pos != 0:
self.buffer.PopupMenu(menu, pos)
else:
self.buffer.PopupMenu(menu, ev.GetPosition())
def view(self, *args, **kwargs):
pub.sendMessage("execute-action", action="view_item")
def copy(self, *args, **kwargs):
pub.sendMessage("execute-action", action="copy_to_clipboard")
def user_actions(self, *args, **kwargs):
pub.sendMessage("execute-action", action="follow")
def fav(self, *args, **kwargs):
pub.sendMessage("execute-action", action="add_to_favourites")
def unfav(self, *args, **kwargs):
pub.sendMessage("execute-action", action="remove_from_favourites")
def delete_item_(self, *args, **kwargs):
pub.sendMessage("execute-action", action="delete_item")
def url_(self, *args, **kwargs):
self.url()
def show_menu_by_key(self, ev):
if self.buffer.list.get_count() == 0:
return
if ev.GetKeyCode() == wx.WXK_WINDOWS_MENU:
self.show_menu(widgetUtils.MENU, pos=self.buffer.list.list.GetPosition())
def get_tweet(self):
if self.session.db[self.name][self.buffer.list.get_selected()].has_key("retweeted_status"):
@@ -375,7 +446,7 @@ class baseBufferController(bufferController):
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, twishort_enabled=self.session.settings["mysc"]["twishort_enabled"])
message = messages.reply(self.session, _(u"Reply"), _(u"Reply to %s") % (screen_name,), "@%s " % (screen_name,), twishort_enabled=self.session.settings["mysc"]["twishort_enabled"], users=users)
if message.message.get_response() == widgetUtils.OK:
self.session.settings["mysc"]["twishort_enabled"] = message.message.long_tweet.GetValue()
text = message.message.get_text()
@@ -423,11 +494,10 @@ class baseBufferController(bufferController):
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", twishort_enabled=self.session.settings["mysc"]["twishort_enabled"])
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, messageType="retweet", twishort_enabled=self.session.settings["mysc"]["twishort_enabled"])
if comment != '':
retweet.message.set_text(comment)
if retweet.message.get_response() == widgetUtils.OK:
self.session.settings["mysc"]["twishort_enabled"] = retweet.message.long_tweet.GetValue()
text = retweet.message.get_text()
comments=text
if len(text+ u"“@%s: %s" % (tweet["user"]["screen_name"], tweet["text"])) < 140:
@@ -458,10 +528,9 @@ class baseBufferController(bufferController):
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=''):
# @_tweets_exist
def audio(self, url='', *args, **kwargs):
if hasattr(sound.URLPlayer,'stream'):
return sound.URLPlayer.stop_audio(delete=True)
tweet = self.get_tweet()
@@ -481,8 +550,8 @@ class baseBufferController(bufferController):
except:
log.error("Exception while executing audio method.")
@_tweets_exist
def url(self,url='',announce=True):
# @_tweets_exist
def url(self, url='', announce=True, *args, **kwargs):
if url == '':
tweet = self.get_tweet()
urls = utils.find_urls(tweet)
@@ -536,6 +605,26 @@ class baseBufferController(bufferController):
user.profileController(session=self.session, user=dlg.get_user())
if hasattr(dlg, "destroy"): dlg.destroy()
def get_quoted_tweet(self, tweet):
# try:
quoted_tweet = self.session.twitter.twitter.show_status(id=tweet["id"])
urls = utils.find_urls_in_text(quoted_tweet["text"])
for url in range(0, len(urls)):
try: quoted_tweet["text"] = quoted_tweet["text"].replace(urls[url], quoted_tweet["entities"]["urls"][url]["expanded_url"])
except IndexError: pass
# except TwythonError as e:
# utils.twitter_error(e)
# return
l = tweets.is_long(quoted_tweet)
id = tweets.get_id(l)
# try:
original_tweet = self.session.twitter.twitter.show_status(id=id)
urls = utils.find_urls_in_text(original_tweet["text"])
for url in range(0, len(urls)):
try: original_tweet["text"] = original_tweet["text"].replace(urls[url], original_tweet["entities"]["urls"][url]["expanded_url"])
except IndexError: pass
return compose.compose_quoted_tweet(quoted_tweet, original_tweet, self.session.db, self.session.settings["general"]["relative_times"])
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)
@@ -600,6 +689,23 @@ class eventsBufferController(bufferController):
if dlg == widgetUtils.YES:
self.buffer.list.clear()
def show_menu(self, ev, pos=0, *args, **kwargs):
if self.buffer.list.get_count() == 0: return
menu = menus.eventsPanelMenu()
widgetUtils.connect_event(menu, widgetUtils.MENU, self.view, menuitem=menu.view)
widgetUtils.connect_event(menu, widgetUtils.MENU, self.copy, menuitem=menu.copy)
widgetUtils.connect_event(menu, widgetUtils.MENU, self.destroy_status, menuitem=menu.remove)
if pos != 0:
self.buffer.PopupMenu(menu, pos)
else:
self.buffer.PopupMenu(menu, ev.GetPosition())
def view(self, *args, **kwargs):
pub.sendMessage("execute-action", action="view_item")
def copy(self, *args, **kwargs):
pub.sendMessage("execute-action", action="copy_to_clipboard")
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")
@@ -710,6 +816,22 @@ class peopleBufferController(baseBufferController):
def interact(self):
user.profileController(self.session, user=self.get_right_tweet()["screen_name"])
def show_menu(self, ev, pos=0, *args, **kwargs):
menu = menus.peoplePanelMenu()
widgetUtils.connect_event(menu, widgetUtils.MENU, self.direct_message, menuitem=menu.reply)
widgetUtils.connect_event(menu, widgetUtils.MENU, self.user_actions, menuitem=menu.userActions)
widgetUtils.connect_event(menu, widgetUtils.MENU, self.details, menuitem=menu.details)
# widgetUtils.connect_event(menu, widgetUtils.MENU, self.lists, menuitem=menu.lists)
widgetUtils.connect_event(menu, widgetUtils.MENU, self.view, menuitem=menu.view)
widgetUtils.connect_event(menu, widgetUtils.MENU, self.copy, menuitem=menu.copy)
if pos != 0:
self.buffer.PopupMenu(menu, pos)
else:
self.buffer.PopupMenu(menu, ev.GetPosition())
def details(self, *args, **kwargs):
pub.sendMessage("execute-action", action="user_details")
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))
@@ -786,6 +908,7 @@ class trendsBufferController(bufferController):
self.buffer.name = name
self.compose_function = self.compose_function_
self.get_formatted_message = self.get_message
self.reply = self.search_topic
def start_stream(self):
try:
@@ -812,10 +935,11 @@ class trendsBufferController(bufferController):
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)
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.tweet_about_this_trend, self.buffer.tweetTrendBtn)
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.post_tweet, self.buffer.tweet)
widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_ITEM_RIGHT_CLICK, self.show_menu)
widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_KEY_DOWN, self.show_menu_by_key)
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.search_topic, self.buffer.search_topic)
def get_message(self):
return self.compose_function(self.trends[self.buffer.list.get_selected()])[0]
@@ -830,8 +954,52 @@ class trendsBufferController(bufferController):
elif dlg == widgetUtils.NO:
return False
def interact(self, *args, **kwargs):
self.searchfunction(value=self.get_message())
def search_topic(self, *args, **kwargs):
topic = self.trends[self.buffer.list.get_selected()]["name"]
pub.sendMessage("search", term=topic)
def show_menu(self, ev, pos=0, *args, **kwargs):
menu = menus.trendsPanelMenu()
widgetUtils.connect_event(menu, widgetUtils.MENU, self.search_topic, menuitem=menu.search_topic)
widgetUtils.connect_event(menu, widgetUtils.MENU, self.tweet_about_this_trend, menuitem=menu.tweetThisTrend)
widgetUtils.connect_event(menu, widgetUtils.MENU, self.view, menuitem=menu.view)
widgetUtils.connect_event(menu, widgetUtils.MENU, self.copy, menuitem=menu.copy)
if pos != 0:
self.buffer.PopupMenu(menu, pos)
else:
self.buffer.PopupMenu(menu, ev.GetPosition())
def view(self, *args, **kwargs):
pub.sendMessage("execute-action", action="view_item")
def copy(self, *args, **kwargs):
pub.sendMessage("execute-action", action="copy_to_clipboard")
def tweet_about_this_trend(self, *args, **kwargs):
if self.buffer.list.get_count() == 0: return
title = _(u"Tweet")
caption = _(u"Write the tweet here")
tweet = messages.tweet(self.session, title, caption, self.get_message()+ " ", twishort_enabled=self.session.settings["mysc"]["twishort_enabled"])
tweet.message.set_cursor_at_end()
if tweet.message.get_response() == widgetUtils.OK:
self.session.settings["mysc"]["twishort_enabled"] = tweet.message.long_tweet.GetValue()
text = tweet.message.get_text()
if len(text) > 140 and tweet.message.get("long_tweet") == True:
if tweet.image == None:
text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text)
else:
text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text, 1)
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()
def show_menu_by_key(self, ev):
if self.buffer.list.get_count() == 0:
return
if ev.GetKeyCode() == wx.WXK_WINDOWS_MENU:
self.show_menu(widgetUtils.MENU, pos=self.buffer.list.list.GetPosition())
class conversationBufferController(searchBufferController):

View File

@@ -15,19 +15,30 @@ class listsController(object):
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.deleteBtn, widgetUtils.BUTTON_PRESSED, self.remove_list)
widgetUtils.connect_event(self.dialog.view, widgetUtils.BUTTON_PRESSED, self.open_list_as_buffer)
widgetUtils.connect_event(self.dialog.deleteBtn, widgetUtils.BUTTON_PRESSED, self.remove_list)
else:
self.dialog = lists.userListViewer(user)
self.dialog.populate_list(self.get_user_lists(user))
widgetUtils.connect_event(self.dialog.createBtn, widgetUtils.BUTTON_PRESSED, self.subscribe)
widgetUtils.connect_event(self.dialog.deleteBtn, widgetUtils.BUTTON_PRESSED, self.unsubscribe)
self.dialog.get_response()
def get_all_lists(self):
return [compose.compose_list(item) for item in self.session.db["lists"]]
def get_user_lists(self, user):
self.lists = self.session.twitter.twitter.show_lists(reverse=True, screen_name=user)
return [compose.compose_list(item) for item in self.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:
if p == True:
mode = "public"
else:
mode = "private"
@@ -73,4 +84,23 @@ class listsController(object):
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"])
pub.sendMessage("create-new-buffer", buffer="list", account=self.session.db["user_name"], create=list["name"])
def subscribe(self, *args, **kwargs):
if self.dialog.lista.get_count() == 0: return
list_id = self.lists[self.dialog.get_item()]["id"]
try:
list = self.session.twitter.twitter.subscribe_to_list(list_id=list_id)
item = utils.find_item(list["id"], self.session.db["lists"])
self.session.db["lists"].append(list)
except TwythonError as e:
output.speak("error %s: %s" % (e.status_code, e.msg))
def unsubscribe(self, *args, **kwargs):
if self.dialog.lista.get_count() == 0: return
list_id = self.lists[self.dialog.get_item()]["id"]
try:
list = self.session.twitter.twitter.unsubscribe_from_list(list_id=list_id)
self.session.db["lists"].remove(list)
except TwythonError as e:
output.speak("error %s: %s" % (e.status_code, e.msg))

View File

@@ -90,12 +90,14 @@ class Controller(object):
""" Gets the last valid buffer for an account.
account str: A twitter username.
The last valid buffer is the last buffer that contains a session object assigned."""
# results = self.get_buffers_for_account(account)
results = self.get_buffers_for_account(account)
return self.view.search(results[-1].name, results[-1].account)
def get_buffers_for_account(self, account):
results = []
[results.append(i) for i in self.buffers if i.account == account and i.invisible == True]
buffers = self.view.get_buffers()
[results.append(self.search_buffer(i.name, i.account)) for i in buffers if i.account == account and (i.type != "account")]
return results
def bind_stream_events(self):
@@ -126,7 +128,8 @@ class Controller(object):
pub.subscribe(self.manage_stream_errors, "stream-error")
pub.subscribe(self.create_new_buffer, "create-new-buffer")
pub.subscribe(self.restart_streams, "restart-streams")
pub.subscribe(self.execute_action, "execute-action")
pub.subscribe(self.search_topic, "search")
if system == "Windows":
pub.subscribe(self.invisible_shorcuts_changed, "invisible-shorcuts-changed")
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.show_hide, menuitem=self.view.show_hide)
@@ -154,7 +157,9 @@ class Controller(object):
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.delete, self.view.delete)
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.follow, menuitem=self.view.follow)
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.send_dm, self.view.dm)
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.view_user_lists, menuitem=self.view.viewLists)
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.get_more_items, menuitem=self.view.load_previous_items)
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.view_user_lists, menuitem=self.view.viewLists)
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.clear_buffer, menuitem=self.view.clear)
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.remove_buffer, self.view.deleteTl)
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.check_for_updates, self.view.check_for_updates)
@@ -172,6 +177,8 @@ class Controller(object):
widgetUtils.connect_event(self.view.nb, widgetUtils.NOTEBOOK_PAGE_CHANGED, self.buffer_changed)
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.report_error, self.view.reportError)
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.view_documentation, self.view.doc)
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.add_to_list, self.view.addToList)
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.remove_from_list, self.view.removeFromList)
def set_systray_icon(self):
self.systrayIcon = sysTrayIcon.SysTrayIcon()
@@ -233,7 +240,6 @@ class Controller(object):
self.create_ignored_session_buffer(session_.sessions[i])
continue
self.create_buffers(session_.sessions[i])
self.set_buffer_positions(session_.sessions[i])
# Connection checker executed each minute.
self.checker_function = RepeatingTimer(60, self.check_connection)
@@ -244,6 +250,7 @@ class Controller(object):
for i in session_.sessions:
if session_.sessions[i].is_logged == False: continue
self.start_buffers(session_.sessions[i])
self.set_buffer_positions(session_.sessions[i])
if config.app["app-settings"]["play_ready_sound"] == True:
session_.sessions[session_.sessions.keys()[0]].sound.play("ready.ogg")
if config.app["app-settings"]["speak_ready_msg"] == True:
@@ -261,6 +268,7 @@ class Controller(object):
for i in session_.sessions:
if session_.sessions[i].session_id == session_id: session = session_.sessions[i]
session.login()
session.db = dict()
self.create_buffers(session, False)
self.start_buffers(session)
@@ -284,11 +292,11 @@ class Controller(object):
self.buffers.append(mentions)
self.view.insert_buffer(mentions.buffer, name=_(u"Mentions"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
elif i == 'dm':
dm = buffersController.baseBufferController(self.view.nb, "get_direct_messages", "direct_messages", session, session.db["user_name"], bufferType="dmPanel", sound="dm_received.ogg")
dm = buffersController.baseBufferController(self.view.nb, "get_direct_messages", "direct_messages", session, session.db["user_name"], bufferType="dmPanel", sound="dm_received.ogg", full_text=True)
self.buffers.append(dm)
self.view.insert_buffer(dm.buffer, name=_(u"Direct messages"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
elif i == 'sent_dm':
sent_dm = buffersController.baseBufferController(self.view.nb, "get_sent_messages", "sent_direct_messages", session, session.db["user_name"], bufferType="dmPanel")
sent_dm = buffersController.baseBufferController(self.view.nb, "get_sent_messages", "sent_direct_messages", session, session.db["user_name"], bufferType="dmPanel", full_text=True)
self.buffers.append(sent_dm)
self.view.insert_buffer(sent_dm.buffer, name=_(u"Sent direct messages"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
elif i == 'sent_tweets':
@@ -358,40 +366,27 @@ class Controller(object):
buffer.start_stream()
buffer.searchfunction = self.search
self.buffers.append(buffer)
self.view.insert_buffer(buffer.buffer, name=_(u"Trending topics for %s") % (buffer.name_), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
buffer.timer = RepeatingTimer(300, buffer.start_stream)
buffer.timer.start()
self.view.insert_buffer(buffer.buffer, name=_(u"Trending topics for %s") % (buffer.name_), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
def set_buffer_positions(self,session):
"Sets positions for buffers if values exist in the database."
for i in self.buffers:
if str(i.name+"_pos") in session.db and hasattr(i.buffer,'list'):
if i.account == session.db["user_name"] and session.db.has_key(i.name+"_pos") and hasattr(i.buffer,'list'):
i.buffer.list.select_item(session.db[str(i.name+"_pos")])
def logout_account(self, session_id):
for i in session_.sessions:
if session_.sessions[i].session_id == session_id: session = session_.sessions[i]
user = session.db["user_name"]
self.destroy_buffer("home_timeline", user)
self.destroy_buffer("mentions", user)
self.destroy_buffer("direct_messages", user)
self.destroy_buffer("sent_direct_messages", user)
self.destroy_buffer("sent_tweets", user)
self.destroy_buffer("favourites", user)
self.destroy_buffer("followers", user)
self.destroy_buffer("friends", user)
self.destroy_buffer("blocked", user)
self.destroy_buffer("muted", user)
self.destroy_buffer("events", user)
self.destroy_buffer("timelines", user)
for i in session.settings["other_buffers"]["timelines"]:
self.destroy_buffer("%s-timeline" % (i,), user)
self.destroy_buffer("favs_timelines", user)
self.destroy_buffer("searches", user)
for i in session.settings["other_buffers"]["tweet_searches"]:
self.destroy_buffer("%s-searchterm" % (i,), user)
for i in session.settings["other_buffers"]["trending_topic_buffers"]:
self.destroy_buffer("%s_tt" % (i,), user)
delete_buffers = []
for i in self.buffers:
if i.account == user and i.name != user:
delete_buffers.append(i.name)
for i in delete_buffers:
self.destroy_buffer(i, user)
session.db = None
def destroy_buffer(self, buffer_name, account):
buffer = self.search_buffer(buffer_name, account)
@@ -402,7 +397,10 @@ class Controller(object):
self.buffers.remove(buffer)
del buffer
def search(self, value="", *args, **kwargs):
def search_topic(self, term):
self.search(value=term)
def search(self, event=None, value="", *args, **kwargs):
""" Searches words or users in twitter. This creates a new buffer containing the search results."""
log.debug("Creating a new search...")
dlg = dialogs.search.searchDialog(value)
@@ -476,8 +474,20 @@ class Controller(object):
buffer = self.get_best_buffer()
SoundsTutorial.soundsTutorial(buffer.session)
def view_user_lists(self, users):
pass
def view_user_lists(self, *args, **kwargs):
buff = self.get_best_buffer()
if not hasattr(buff, "get_right_tweet"): return
tweet = buff.get_right_tweet()
if buff.type != "people":
users = utils.get_all_users(tweet, buff.session.db)
else:
users = [tweet["screen_name"]]
dlg = dialogs.utils.selectUserDialog(_(u"Select the user"), users)
if dlg.get_response() == widgetUtils.OK:
user = dlg.get_user()
else:
return
l = listsController.listsController(buff.session, user=user)
def add_to_list(self, *args, **kwargs):
buff = self.get_best_buffer()
@@ -506,8 +516,32 @@ class Controller(object):
except TwythonError as e:
output.speak("error %s: %s" % (e.error_code, e.msg))
def remove_from_list(self, user):
pass
def remove_from_list(self, *args, **kwargs):
buff = self.get_best_buffer()
if not hasattr(buff, "get_right_tweet"): return
tweet = buff.get_right_tweet()
if buff.type != "people":
users = utils.get_all_users(tweet, buff.session.db)
else:
users = [tweet["screen_name"]]
dlg = dialogs.utils.selectUserDialog(_(u"Select the user"), users)
if dlg.get_response() == widgetUtils.OK:
user = dlg.get_user()
else:
return
dlg = dialogs.lists.removeUserListDialog()
dlg.populate_list([compose.compose_list(item) for item in buff.session.db["lists"]])
if dlg.get_response() == widgetUtils.OK:
try:
list = buff.session.twitter.twitter.delete_list_member(list_id=buff.session.db["lists"][dlg.get_item()]["id"], screen_name=user)
older_list = utils.find_item(buff.session.db["lists"][dlg.get_item()]["id"], buff.session.db["lists"])
listBuffer = self.search_buffer("%s-list" % (buff.session.db["lists"][dlg.get_item()]["name"].lower()), buff.session.db["user_name"])
if listBuffer != None: listBuffer.get_user_ids()
buff.session.db["lists"].pop(older_list)
buff.session.db["lists"].append(list)
if listBuffer != None: pub.sendMessage("restart-streams", streams=["timelinesStream"], session=buff.session)
except TwythonError as e:
output.speak("error %s: %s" % (e.error_code, e.msg))
def list_manager(self, *args, **kwargs):
s = self.get_best_buffer().session
@@ -559,6 +593,7 @@ class Controller(object):
self.exit_()
def exit_(self, *args, **kwargs):
for i in self.buffers: i.save_positions()
log.debug("Exiting...")
log.debug("Saving global configuration...")
config.app.write()
@@ -716,8 +751,7 @@ class Controller(object):
users = [tweet["screen_name"]]
dlg = dialogs.userSelection.selectUserDialog(users=users, default=default)
if dlg.get_response() == widgetUtils.OK:
buffer = self.get_best_buffer()
usr = utils.if_user_exists(buffer.session.twitter.twitter, dlg.get_user())
usr = utils.if_user_exists(buff.session.twitter.twitter, dlg.get_user())
if usr != None:
if usr["protected"] == True:
if usr["following"] == False:
@@ -726,32 +760,38 @@ class Controller(object):
answer = commonMessageDialogs.protected_user()
if answer == widgetUtils.NO: return
if dlg.get_action() == "tweets":
if dlg.get_user() in buffer.session.settings["other_buffers"]["timelines"]:
if usr["statuses_count"] == 0:
commonMessageDialogs.no_tweets()
return
if dlg.get_user() in buff.session.settings["other_buffers"]["timelines"]:
commonMessageDialogs.timeline_exist()
return
tl = buffersController.baseBufferController(self.view.nb, "get_user_timeline", "%s-timeline" % (dlg.get_user(),), buffer.session, buffer.session.db["user_name"], bufferType=None, screen_name=dlg.get_user())
tl = buffersController.baseBufferController(self.view.nb, "get_user_timeline", "%s-timeline" % (dlg.get_user(),), buff.session, buff.session.db["user_name"], bufferType=None, screen_name=dlg.get_user())
tl.start_stream()
pos=self.view.search("timelines", buffer.session.db["user_name"])
self.insert_buffer(tl, pos)
pos=self.view.search("timelines", buff.session.db["user_name"])
self.insert_buffer(tl, pos+1)
# self.buffers.insert(pos+1, tl)
self.view.insert_buffer(tl.buffer, name=_(u"Timeline for {}").format(dlg.get_user()), pos=pos)
buffer.session.settings["other_buffers"]["timelines"].append(dlg.get_user())
pub.sendMessage("restart-streams", streams=["timelinesStream"], session=buffer.session)
buffer.session.sound.play("create_timeline.ogg")
buff.session.settings["other_buffers"]["timelines"].append(dlg.get_user())
pub.sendMessage("restart-streams", streams=["timelinesStream"], session=buff.session)
buff.session.sound.play("create_timeline.ogg")
else:
if dlg.get_user() in buffer.session.settings["other_buffers"]["favourites_timelines"]:
if usr["favourites_count"] == 0:
commonMessageDialogs.no_favs()
return
if dlg.get_user() in buff.session.settings["other_buffers"]["favourites_timelines"]:
commonMessageDialogs.timeline_exist()
return
tl = buffersController.baseBufferController(self.view.nb, "get_favorites", "%s-favorite" % (dlg.get_user(),), buffer.session, buffer.session.db["user_name"], bufferType=None, screen_name=dlg.get_user())
pos=self.view.search("favs_timelines", buffer.session.db["user_name"])
self.insert_buffer(tl, pos)
tl = buffersController.baseBufferController(self.view.nb, "get_favorites", "%s-favorite" % (dlg.get_user(),), buff.session, buff.session.db["user_name"], bufferType=None, screen_name=dlg.get_user())
pos=self.view.search("favs_timelines", buff.session.db["user_name"])
self.insert_buffer(tl, pos+1)
# self.buffers.insert(pos+1, tl)
self.view.insert_buffer(buffer=tl.buffer, name=_(u"Favourites timeline for {}").format(dlg.get_user()), pos=pos)
tl.start_stream()
tl.timer = RepeatingTimer(300, tl.start_stream)
tl.timer.start()
buffer.session.settings["other_buffers"]["favourites_timelines"].append(dlg.get_user())
buffer.session.sound.play("create_timeline.ogg")
buff.session.settings["other_buffers"]["favourites_timelines"].append(dlg.get_user())
buff.session.sound.play("create_timeline.ogg")
else:
commonMessageDialogs.user_not_exist()
@@ -923,13 +963,11 @@ class Controller(object):
def left(self, *args, **kwargs):
buff = self.view.get_current_buffer_pos()
# print buff
buffer = self.get_current_buffer()
if not hasattr(buffer.buffer, "list"):
output.speak(_(u"No session is currently in focus. Focus a session with the next or previous session shortcut."), True)
return
if buff == self.get_first_buffer(buffer.account) or buff == 0:
print "This is the last buffer"
self.view.change_buffer(self.get_last_buffer(buffer.account))
else:
self.view.change_buffer(buff-1)
@@ -1186,6 +1224,7 @@ class Controller(object):
buffer.add_new_item(data)
def manage_item_in_list(self, data, user, where):
print "I'm activated!"
buffer = self.search_buffer("%s" % (where,), user)
if buffer == None: return
play_sound = "tweet_timeline.ogg"
@@ -1202,9 +1241,23 @@ class Controller(object):
log.debug("Starting the streaming endpoint")
session.start_streaming()
def set_positions(self):
for i in session_.sessions:
self.set_buffer_positions(i)
def manage_stream_errors(self, session):
log.error("An error ocurred with the stream for the %s session. It will be destroyed" % (session,))
log.error(" Restarting %s session streams. It will be destroyed" % (session,))
s = session_.sessions[session]
try:
if hasattr(s, "main_stream"): del s.main_stream
del s.timelinesStream
s.counter = 0
s.reconnection_function_active = False
except AttributeError:
log.error("Error deleting some thing")
for i in self.buffers:
if i.invisible == True and i.session.session_id == s.session_id and i.type != "people":
i.start_stream()
s.listen_stream_error()
def check_connection(self):
@@ -1252,7 +1305,8 @@ class Controller(object):
return
tl = buffersController.listBufferController(self.view.nb, "get_list_statuses", create+"-list", buff.session, buff.session.db["user_name"], bufferType=None, list_id=utils.find_list(create, buff.session.db["lists"]))
buff.session.lists.append(tl)
self.buffers.append(tl)
pos=self.view.search("lists", buff.session.db["user_name"])
self.insert_buffer(tl, pos)
self.view.insert_buffer(tl.buffer, name=_(u"List for {}").format(create), pos=self.view.search("lists", buff.session.db["user_name"]))
tl.start_stream()
buff.session.settings["other_buffers"]["lists"].append(create)
@@ -1337,31 +1391,7 @@ class Controller(object):
os.chdir("../../")
def insert_buffer(self, buffer, position):
# print ref_buf.name, ref_buf.account
# if ref_buf.account != buffer.account or ref_buf.type == "account" or type(ref_buf) == buffers.emptyPanel:
buffers = self.get_buffers_for_account(buffer.account)
ref_buf = self.buffers[position+1]
empty = True
for i in buffers[position+1:]:
if i.type == "account" or i.invisible == False:
empty = True
else:
empty = False
if empty == True:
self.buffers.append(buffer)
# print "account"
else:
self.buffers.insert(position+1, buffer)
# for i in self.buffers:
# print i.name, i.account
def __del__(self):
config.app.write()
def change_buffer(self, bufferPosition):
buff = self.buffers[bufferPosition]
newPos = self.view.search(buff.name, buff.account)
self.view.change_buffer(newPos)
self.buffers.insert(position, buffer)
def copy_to_clipboard(self, *args, **kwargs):
output.copy(self.get_current_buffer().get_message())
@@ -1369,3 +1399,10 @@ class Controller(object):
def repeat_item(self, *args, **kwargs):
output.speak(self.get_current_buffer().get_message())
def execute_action(self, action):
if hasattr(self, action):
getattr(self, action)()
def __del__(self):
config.app.write()

View File

@@ -25,6 +25,7 @@ class basicTweet(object):
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":
# if messageType != "dm":
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)
@@ -97,6 +98,7 @@ class basicTweet(object):
checker = SpellChecker.spellchecker.spellChecker(text, "")
if hasattr(checker, "fixed_text"):
self.message.set_text(checker.fixed_text)
self.message.text_focus()
def attach(self, *args, **kwargs):
def completed_callback():
@@ -109,6 +111,7 @@ class basicTweet(object):
output.speak(_(u"Unable to upload the audio"))
dlg.cleanup()
dlg = audioUploader.audioUploader(self.session.settings, completed_callback)
self.message.text_focus()
class tweet(basicTweet):
def __init__(self, session, title, caption, text, twishort_enabled, messageType="tweet", max=140):
@@ -117,7 +120,8 @@ class tweet(basicTweet):
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)
if twishort_enabled == False:
self.message.long_tweet.SetValue(False)
try: self.message.long_tweet.SetValue(False)
except AttributeError: pass
def upload_image(self, *args, **kwargs):
if self.message.get("upload_image") == _(u"Discard image"):
@@ -129,14 +133,15 @@ class tweet(basicTweet):
self.image = self.message.get_image()
if self.image != None:
self.message.set("upload_image", _(u"Discard image"))
self.message.text_focus()
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")
def __init__(self, session, title, caption, text, twishort_enabled, users=None):
super(reply, self).__init__(session, title, caption, text, twishort_enabled, 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)
@@ -150,7 +155,7 @@ class reply(tweet):
class dm(basicTweet):
def __init__(self, session, title, caption, text):
super(dm, self).__init__(session, title, caption, text, messageType="dm")
super(dm, self).__init__(session, title, caption, text, messageType="dm", max=10000)
widgetUtils.connect_event(self.message.autocompletionButton, widgetUtils.BUTTON_PRESSED, self.autocomplete_users)
def autocomplete_users(self, *args, **kwargs):

View File

@@ -34,7 +34,7 @@ class globalSettingsController(object):
if ".keymap" not in i:
continue
try:
res[config_utils.load_config(paths.app_path('keymaps/'+i))['info']['name']]=i
res[i[:-7]] =i
except:
log.exception("Exception while loading keymap " + i)
return res
@@ -79,6 +79,8 @@ class globalSettingsController(object):
self.needs_restart = True
if self.kmnames[self.dialog.general.km.GetSelection()] != config.app["app-settings"]["load_keymap"]:
config.app["app-settings"]["load_keymap"] =self.kmnames[self.dialog.general.km.GetSelection()]
kmFile = open(paths.config_path("keymap.keymap"), "w")
kmFile.close()
self.needs_restart = True
if config.app["app-settings"]["use_invisible_keyboard_shorcuts"] != self.dialog.get_value("general", "use_invisible_shorcuts"):

View File

@@ -1,10 +1,11 @@
# -*- coding: utf-8 -*-
from wxUI.dialogs import userActions
from pubsub import pub
import re
import widgetUtils
import output
from wxUI.dialogs import userActions
from pubsub import pub
from twython import TwythonError
from extra import autocompletionUsers
class userActionsController(object):
def __init__(self, buffer, users=[], default="follow"):
@@ -12,9 +13,14 @@ class userActionsController(object):
self.buffer = buffer
self.session = buffer.session
self.dialog = userActions.UserActionsDialog(users, default)
widgetUtils.connect_event(self.dialog.autocompletion, widgetUtils.BUTTON_PRESSED, self.autocomplete_users)
if self.dialog.get_response() == widgetUtils.OK:
self.process_action()
def autocomplete_users(self, *args, **kwargs):
c = autocompletionUsers.completion.autocompletionUsers(self.dialog, self.session.session_id)
c.show_menu("dm")
def process_action(self):
action = self.dialog.get_action()
user = self.dialog.get_user()

View File

@@ -74,10 +74,10 @@ class audioUploader(object):
def on_pause(self, *args, **kwargs):
if self.dialog.get("pause") == _(u"Pause"):
self.recording.pause()
self.dialog.set("pause", _(u"Resume"))
self.dialog.set("pause", _(u"&Resume"))
elif self.dialog.get("pause") == _(u"Resume"):
self.recording.play()
self.dialog.set("pause", _(U"Pause"))
self.dialog.set("pause", _(U"&Pause"))
def on_record(self, *args, **kwargs):
if self.recording != None:
@@ -92,7 +92,7 @@ class audioUploader(object):
self.file = tempfile.mktemp(suffix='.wav')
self.recording = sound.recording(self.file)
self.recording.play()
self.dialog.set("record", _(u"Stop"))
self.dialog.set("record", _(u"&Stop"))
output.speak(_(u"Recording"))
def stop_recording(self):
@@ -100,11 +100,11 @@ class audioUploader(object):
self.recording.free()
output.speak(_(u"Stopped"))
self.recorded = True
self.dialog.set("record", _(u"Record"))
self.dialog.set("record", _(u"&Record"))
self.file_attached()
def file_attached(self):
self.dialog.set("pause", _(u"Pause"))
self.dialog.set("pause", _(u"&Pause"))
self.dialog.disable_control("record")
self.dialog.enable_control("play")
self.dialog.enable_control("discard")
@@ -137,11 +137,11 @@ class audioUploader(object):
# 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"))
self.dialog.set("play", _(u"&Stop"))
try:
while self.playing.is_playing:
pass
self.dialog.set("play", _(u"Play"))
self.dialog.set("play", _(u"&Play"))
self.playing.free()
self.playing = None
except:
@@ -151,7 +151,7 @@ class audioUploader(object):
output.speak(_(u"Stopped"))
self.playing.stop()
self.playing.free()
self.dialog.set("play", _(u"Play"))
self.dialog.set("play", _(u"&Play"))
self.playing = None
def postprocess(self):

View File

@@ -31,14 +31,14 @@ class audioDialog(widgetUtils.BaseDialog):
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
btnSizer2 = wx.BoxSizer(wx.HORIZONTAL)
self.play = wx.Button(panel, -1, _(u"Play"))
self.play = wx.Button(panel, -1, _(u"&Play"))
self.play.Disable()
self.pause = wx.Button(panel, -1, _(u"Pause"))
self.pause = wx.Button(panel, -1, _(u"&Pause"))
self.pause.Disable()
self.record = wx.Button(panel, -1, _(u"Record"))
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.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)
@@ -47,7 +47,7 @@ class audioDialog(widgetUtils.BaseDialog):
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"))
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)

View File

@@ -11,9 +11,17 @@ def fix():
locales.BasqueLocale = BasqueLocale
locales.TurkishLocale.names[-1] = "tr_tr"
locales.ArabicLocale.names[-1] = "ar_eg"
# insert a modified function so if there is no language available in arrow, returns English locale.
locales.get_locale = get_locale
# We need to reassign the locales list for updating the list with our new contents.
locales._locales = locales._map_locales()
def get_locale(name):
locale_cls = locales._locales.get(name.lower())
if locale_cls is None:
return locales.EnglishLocale()
return locale_cls()
class CatalaLocale(Locale):
names = ['ca', 'ca_ca']
past = 'Fa {0}'
@@ -67,11 +75,13 @@ class GalicianLocale(Locale):
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.
future = '{0} igarota'
timeframes = {
'now': 'Orain',
'seconds': 'segundu',
# 'second': 'segundu bat',
'seconds': 'segundu batzuk', # without specifying a number.
#'seconds': '{0} segundu', # specifying a number
'minute': 'minutu bat',
'minutes': '{0} minutu',
'hour': 'ordu bat',

View File

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

View File

@@ -0,0 +1,30 @@
[info]
name = string(default="Chicken Nugget")
desc = string(default="Remaps TWBlue shortcuts to their equivalents in Christopher Toth's Chicken Nugget Twitter client.")
author = string(default="Bill Dengler <codeofdusk@gmail.com>")
[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")
open_conversation = string(default="control+win+c")
show_hide = string(default="control+win+w")
post_tweet = string(default="control+win+t")
post_reply = string(default="control+win+r")
post_retweet = string(default="control+win+shift+t")
send_dm = string(default="control+win+d")
user_details = string(default="control+win+shift+u")
exit = string(default="control+win+q")
open_timeline = string(default="control+win+u")
remove_buffer = string(default="control+win+backspace")
audio = string(default="control+win+return")
url = string(default="control+win+b")
go_home = string(default="control+win+home")
go_end = string(default="control+win+end")
delete = string(default="control+win+delete")
clear_buffer = string(default="control+win+shift+delete")
repeat_item = string(default="control+win+space")
copy_to_clipboard = string(default="control+win+shift+c")
search = string(default="control+win+/")
find = string(default="control+win+shift+/")

View File

@@ -1,30 +0,0 @@
[info]
name = Chicken Nugget
desc = Remaps TWBlue shortcuts to their equivalents in Christopher Toth's Chicken Nugget Twitter client.
author = Bill Dengler <codeofdusk@gmail.com>
[keymap]
up = control+win+up
down = control+win+down
left = control+win+left
right = control+win+right
open_conversation = control+win+c
show_hide = control+win+w
post_tweet = control+win+t
post_reply = control+win+r
post_retweet = control+win+shift+t
send_dm = control+win+d
user_details = control+win+shift+u
exit = control+win+q
open_timeline = control+win+u
remove_buffer = control+win+backspace
audio = control+win+return
secondary_interact = control+win+b
go_home = control+win+home
go_end = control+win+end
delete = control+win+delete
clear_buffer = control+win+shift+delete
repeat_item = control+win+space
copy_to_clipboard = control+win+shift+c
search = control+win+/
find = control+win+shift+/

View File

@@ -1,48 +1,49 @@
[info]
name = Qwitter
desc = A keymap which emulates Qwitter as closely as possible.
author = Bill Dengler <codeofdusk@gmail.com>
name = string(default="Qwitter")
desc = string(default="A keymap which emulates Qwitter as closely as possible.")
author = string(default="Bill Dengler <codeofdusk@gmail.com>")
[keymap]
up = control+win+up
down = control+win+down
left = control+win+left
right = control+win+right
next_account = control+win+shift+right
previous_account = control+win+shift+left
show_hide = control+win+w
post_tweet = control+win+n
post_reply = control+win+r
post_retweet = control+win+shift+r
send_dm = control+win+d
add_to_favourites = alt+win+f
remove_from_favourites = alt+shift+win+f
follow = control+win+l
user_details = control+win+shift+;
view_item = control+win+v
exit = control+win+f4
open_timeline = control+win+i
remove_buffer = "control+win+'"
audio = control+win+return
volume_up = control+win+alt+up
volume_down = control+win+alt+down
go_home = control+win+home
go_end = control+win+end
go_page_up = control+win+pageup
go_page_down = control+win+pagedown
update_profile = control+win+shift+p
delete = control+win+delete
clear_buffer = control+win+shift+delete
repeat_item = control+win+space
copy_to_clipboard = control+win+shift+c
add_to_list = control+win+alt+l
remove_from_list = control+win+alt+shift+l
toggle_buffer_mute = control+win+alt+m
toggle_session_mute = control+win+m
search = control+win+/
find = control+win+shift+/
edit_keystrokes = control+win+k
view_user_lists = win+alt+shift+l
reverse_geocode = control+win+g
view_reverse_geocode = control+win+shift+g
get_trending_topics = control+win+shift+t
up = string(default="control+win+up")
down = string(default="control+win+down")
left = string(default="control+win+left")
right = string(default="control+win+right")
next_account = string(default="control+win+shift+right")
previous_account = string(default="control+win+shift+left")
show_hide = string(default="control+win+w")
post_tweet = string(default="control+win+n")
post_reply = string(default="control+win+r")
post_retweet = string(default="control+win+shift+r")
send_dm = string(default="control+win+d")
add_to_favourites = string(default="alt+win+f")
remove_from_favourites = string(default="alt+shift+win+f")
follow = string(default="control+win+l")
user_details = string(default="control+win+shift+;")
view_item = string(default="control+win+v")
exit = string(default="control+win+f4")
open_timeline = string(default="control+win+i")
remove_buffer = '''string(default="control+win+'")'''
url = string(default="control+win+return")
audio = string(default="control+win+shift+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="control+win+shift+p")
delete = string(default="control+win+delete")
clear_buffer = string(default="control+win+shift+delete")
repeat_item = string(default="control+win+space")
copy_to_clipboard = string(default="control+win+shift+c")
add_to_list = string(default="control+win+alt+l")
remove_from_list = string(default="control+win+alt+shift+l")
toggle_buffer_mute = string(default="control+win+alt+m")
toggle_session_mute = string(default="control+win+m")
search = string(default="control+win+/")
find = string(default="control+win+shift+/")
edit_keystrokes = string(default="control+win+k")
view_user_lists = string(default="win+alt+shift+l")
reverse_geocode = string(default="control+win+g")
view_reverse_geocode = string(default="control+win+shift+g")
get_trending_topics = string(default="control+win+shift+t")

View File

@@ -1,52 +0,0 @@
[info]
name = Windows 10 (experimental)
desc = A keymap with remapped modifiers for Windows 10 compatibility.
author = Bill Dengler <codeofdusk@gmail.com>
[keymap]
up = alt+win+up
down = alt+win+down
left = alt+win+left
right = alt+win+right
next_account = alt+win+shift+right
previous_account = alt+win+shift+left
open_conversation = alt+win+c
show_hide = alt+win+w
post_tweet = alt+win+n
post_reply = alt+win+r
post_retweet = alt+win+shift+r
send_dm = alt+win+d
add_to_favourites = alt+win+f
remove_from_favourites = alt+shift+win+f
follow = alt+win+s
user_details = alt+win+shift+n
view_item = alt+win+v
exit = alt+win+f4
open_timeline = alt+win+i
remove_buffer = alt+win+shift+i
audio = alt+win+return
secondary_interact = alt+shift+win+return
volume_up = alt+win+shift+up
go_home = alt+win+home
volume_down = alt+win+shift+down
go_end = alt+win+end
go_page_up = alt+win+pageup
go_page_down = alt+win+pagedown
update_profile = alt+win+p
delete = alt+win+delete
clear_buffer = alt+win+shift+delete
repeat_item = alt+win+space
copy_to_clipboard = alt+win+shift+c
add_to_list = alt+win+a
remove_from_list = alt+win+shift+a
toggle_buffer_mute = alt+win+shift+m
toggle_session_mute = alt+win+m
toggle_autoread = alt+win+e
search = alt+win+-
edit_keystrokes = alt+win+k
view_user_lists = alt+win+l
get_more_items = alt+win+pageup
reverse_geocode = alt+win+g
view_reverse_geocode = alt+win+shift+g
get_trending_topics = alt+win+t

View File

@@ -0,0 +1,51 @@
[info]
name = string(default="Windows 10")
desc = string(default="A keymap with remapped modifiers for Windows 10 compatibility.")
author = string(default="Bill Dengler <codeofdusk@gmail.com>")
[keymap]
up = string(default="alt+win+up")
down = string(default="alt+win+down")
left = string(default="alt+win+left")
right = string(default="alt+win+right")
next_account = string(default="alt+win+shift+right")
previous_account = string(default="alt+win+shift+left")
open_conversation = string(default="alt+win+c")
show_hide = string(default="alt+win+w")
post_tweet = string(default="alt+win+n")
post_reply = string(default="control+win+r")
post_retweet = string(default="alt+win+shift+r")
send_dm = string(default="alt+win+d")
add_to_favourites = string(default="alt+win+f")
remove_from_favourites = string(default="alt+shift+win+f")
follow = string(default="alt+win+s")
user_details = string(default="alt+win+shift+n")
view_item = string(default="alt+win+v")
exit = string(default="alt+win+f4")
open_timeline = string(default="alt+win+i")
remove_buffer = string(default="alt+win+shift+i")
url = string(default="alt+win+return")
audio = string(default="alt+shift+win+return")
volume_up = string(default="alt+win+shift+up")
go_home = string(default="alt+win+home")
volume_down = string(default="alt+win+shift+down")
go_end = string(default="alt+win+end")
go_page_up = string(default="alt+win+pageup")
go_page_down = string(default="alt+win+pagedown")
update_profile = string(default="alt+win+p")
delete = string(default="alt+win+delete")
clear_buffer = string(default="alt+win+shift+delete")
repeat_item = string(default="alt+win+space")
copy_to_clipboard = string(default="alt+win+shift+c")
add_to_list = string(default="alt+win+a")
remove_from_list = string(default="alt+win+shift+a")
toggle_buffer_mute = string(default="alt+win+shift+m")
toggle_session_mute = string(default="alt+win+m")
toggle_autoread = string(default="alt+win+e")
search = string(default="alt+win+-")
edit_keystrokes = string(default="alt+win+k")
view_user_lists = string(default="alt+win+l")
get_more_items = string(default="alt+win+pageup")
reverse_geocode = string(default="alt+win+g")
view_reverse_geocode = string(default="alt+win+shift+g")
get_trending_topics = string(default="alt+win+t")

View File

@@ -1,54 +1,52 @@
[info]
name = Default
desc = TWBlue's default keymap.
author = Bill Dengler <codeofdusk@gmail.com>
name = string(default="Default")
desc = string(default="TWBlue's default keymap.")
author = string(default="Bill Dengler <codeofdusk@gmail.com>")
[keymap]
up = control+win+up
down = control+win+down
left = control+win+left
right = control+win+right
next_account = control+win+shift+right
previous_account = control+win+shift+left
open_conversation = control+win+c
show_hide = control+win+m
post_tweet = control+win+n
post_reply = control+win+r
post_retweet = control+win+shift+r
send_dm = control+win+d
add_to_favourites = alt+win+f
remove_from_favourites = alt+shift+win+f
follow = control+win+s
user_details = control+win+alt+n
view_item = control+win+v
exit = control+win+f4
open_timeline = control+win+i
remove_buffer = control+win+shift+i
audio = control+alt+win+return
url = control+win+return
volume_up = control+win+alt+up
volume_down = control+win+alt+down
go_home = control+win+home
go_end = control+win+end
go_page_up = control+win+pageup
go_page_down = control+win+pagedown
update_profile = alt+win+p
delete = control+win+delete
clear_buffer = control+win+shift+delete
repeat_item = control+win+space
copy_to_clipboard = control+win+shift+c
add_to_list = control+win+a
remove_from_list = control+win+shift+a
toggle_buffer_mute = control+win+shift+m
toggle_session_mute = alt+win+m
toggle_autoread = control+win+e
search = control+win+-
edit_keystrokes = control+win+k
view_user_lists = control+win+l
get_more_items = alt+win+pageup
reverse_geocode = control+win+g
view_reverse_geocode = control+win+shift+g
get_trending_topics = control+win+t
find = control+win+{
secondary_interact = control+win+alt+return
interact = control+win+return
up = string(default="control+win+up")
down = string(default="control+win+down")
left = string(default="control+win+left")
right = string(default="control+win+right")
next_account = string(default="control+win+shift+right")
previous_account = string(default="control+win+shift+left")
open_conversation = string(default="control+win+c")
show_hide = string(default="control+win+m")
post_tweet = string(default="control+win+n")
post_reply = string(default="control+win+r")
post_retweet = string(default="control+win+shift+r")
send_dm = string(default="control+win+d")
add_to_favourites = string(default="alt+win+f")
remove_from_favourites = string(default="alt+shift+win+f")
follow = string(default="control+win+s")
user_details = string(default="control+win+alt+n")
view_item = string(default="control+win+v")
exit = string(default="control+win+f4")
open_timeline = string(default="control+win+i")
remove_buffer = string(default="control+win+shift+i")
audio = string(default="control+alt+win+return")
url = string(default="control+win+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_buffer = string(default="control+win+shift+delete")
repeat_item = string(default="control+win+space")
copy_to_clipboard = string(default="control+win+shift+c")
add_to_list = string(default="control+win+a")
remove_from_list = string(default="control+win+shift+a")
toggle_buffer_mute = string(default="control+win+shift+m")
toggle_session_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")
find = string(default="control+win+{")

View File

@@ -3,6 +3,7 @@ import widgetUtils
import config
import wx_ui
import constants
from pubsub import pub
class KeystrokeEditor(object):
def __init__(self):
@@ -14,6 +15,7 @@ class KeystrokeEditor(object):
self.hold_map = self.map.copy()
self.dialog.put_keystrokes(constants.actions, self.map)
widgetUtils.connect_event(self.dialog.edit, widgetUtils.BUTTON_PRESSED, self.edit_keystroke)
widgetUtils.connect_event(self.dialog.execute, widgetUtils.BUTTON_PRESSED, self.execute_action)
self.dialog.get_response()
def edit_keystroke(self, *args, **kwargs):
@@ -52,3 +54,7 @@ class KeystrokeEditor(object):
wx_ui.no_key()
return
return "+".join(keys)
def execute_action(self, *args, **kwargs):
action = self.dialog.actions[self.dialog.get_action()]
pub.sendMessage("execute-action", action=action)

View File

@@ -13,18 +13,20 @@ class keystrokeEditorDialog(baseDialog.BaseWXDialog):
self.keys = widgets.list(self, _(u"Action"), _(u"Keystroke"), style=wx.LC_REPORT|wx.LC_SINGLE_SEL, size=(400, 450))
self.keys.list.SetFocus()
firstSizer = wx.BoxSizer(wx.HORIZONTAL)
firstSizer.Add(keysText)
firstSizer.Add(self.keys.list)
firstSizer.Add(keysText, 0, wx.ALL, 5)
firstSizer.Add(self.keys.list, 0, wx.ALL, 5)
self.edit = wx.Button(panel, -1, _(u"Edit"))
self.edit.SetDefault()
self.execute = wx.Button(panel, -1, _(u"Execute action"))
close = wx.Button(panel, wx.ID_CANCEL, _(u"Close"))
secondSizer = wx.BoxSizer(wx.HORIZONTAL)
secondSizer.Add(self.edit)
secondSizer.Add(close)
sizer.Add(firstSizer)
sizer.Add(secondSizer)
panel.SetSizerAndFit(sizer)
secondSizer.Add(self.edit, 0, wx.ALL, 5)
secondSizer.Add(self.execute, 0, wx.ALL, 5)
secondSizer.Add(close, 0, wx.ALL, 5)
sizer.Add(firstSizer, 0, wx.ALL, 5)
sizer.Add(secondSizer, 0, wx.ALL, 5)
panel.SetSizer(sizer)
self.SetClientSize(sizer.CalcMin())
def put_keystrokes(self, actions, keystrokes):
for i in keystrokes:

View File

@@ -69,6 +69,7 @@ def getLanguageDescription(language):
"ar":pgettext("languageName","Arabic"),
"ne":pgettext("languageName","Nepali"),
"sr":pgettext("languageName","Serbian (Latin)"),
"ja":pgettext("languageName","Japanese"),
}.get(language,None)
return desc
@@ -195,10 +196,13 @@ def langToWindowsLocale(lang):
"gl": "glc",
"eu": "euq",
"hu": "hun",
"hr": "hrv",
"it": "ita",
"ja": "jpn",
"pl": "plk",
"pt": "ptb",
"ru": "rus",
"tr": "trk"
"tr": "trk",
"sr": "eng",
}
return languages[lang]

View File

@@ -1,4 +1,7 @@
from pywintypes import com_error
import win32com
import paths
win32com.__gen_path__=paths.data_path("com_cache")
from win32com.client import gencache
def prepare_gencache():

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -16,6 +16,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################
from twitter import utils
def get_id(url):
return url.split("/")[-1]
@@ -26,3 +27,9 @@ def is_long(tweet):
if "twitter.com" in tweet["entities"]["urls"][url]["expanded_url"]:
long = get_id(tweet["entities"]["urls"][url]["expanded_url"])
return long
def clear_url(tweet):
urls = utils.find_urls_in_text(tweet["text"])
try: tweet["message"] = tweet["message"].replace(urls[-1], "")
except IndexError: pass
return tweet

View File

@@ -23,7 +23,7 @@ import application
import keys
from mysc.thread_utils import call_threaded
import fixes
#extra variables to control the temporal stdout and stderr, while the final files are opened. We understand that some errors could happen while all outputs are closed, so let's try to avoid it.
#extra variables to control the temporary stdout and stderr, while the final files are opened. We understand that some errors could happen while all outputs are closed, so let's try to avoid it.
import widgetUtils
import webbrowser
from wxUI import commonMessageDialogs
@@ -53,13 +53,13 @@ log = logging.getLogger("main")
def setup():
log.debug("Starting " + application.name + " %s" % (application.version,))
config.setup()
fixes.setup()
log.debug("Using %s %s" % (platform.system(), platform.architecture()[0]))
log.debug("Application path is %s" % (paths.app_path(),))
log.debug("config path is %s" % (paths.config_path(),))
sound.setup()
output.setup()
languageHandler.setLanguage(config.app["app-settings"]["language"])
fixes.setup()
keys.setup()
from controller import mainController
from sessionmanager import sessionManager
@@ -89,7 +89,7 @@ def setup():
def donation():
dlg = commonMessageDialogs.donation()
if dlg == widgetUtils.YES:
webbrowser.open_new_tab("http://twblue.es/donate")
webbrowser.open_new_tab("http://twblue.es/?q=donate")
config.app["app-settings"]["donation_dialog_displayed"] = True
setup()

View File

@@ -27,7 +27,9 @@ def stream_threaded(func, *args, **kwargs):
try:
func(**k)
except:
pub.sendMessage("streamError", session=a[0])
log.error("Error in stream with args: %r" % (a,))
pub.sendMessage("stream-error", session=a[0])
thread = threading.Thread(target=new_func, args=args, kwargs=kwargs)
thread.daemon = True
thread.start()

View File

@@ -9,7 +9,7 @@ import output
import time
import sound
import logging
from twitter import utils
from twitter import utils, compose
from twython import TwythonError, TwythonRateLimitError, TwythonAuthError
import config_utils
import shelve
@@ -18,6 +18,7 @@ import os
from mysc.thread_utils import stream_threaded
from pubsub import pub
log = logging.getLogger("sessionmanager.session")
from long_tweets import tweets
sessions = {}
@@ -60,7 +61,9 @@ class Session(object):
if self.db.has_key(name) == False:
self.db[name] = []
for i in data:
if utils.find_item(i["id"], self.db[name]) == None:
if utils.find_item(i["id"], self.db[name]) == None and utils.is_allowed(i, self.settings["twitter"]["ignored_clients"]) == True:
try: i = self.check_quoted_status(i)
except: pass
if self.settings["general"]["reverse_timelines"] == False: self.db[name].append(i)
else: self.db[name].insert(0, i)
num = num+1
@@ -119,7 +122,8 @@ class Session(object):
# self.settings = None
def init_sound(self):
self.sound = sound.soundSystem(self.settings["sound"])
try: self.sound = sound.soundSystem(self.settings["sound"])
except: pass
@_require_configuration
def login(self, verify_credentials=True):
@@ -318,10 +322,12 @@ class Session(object):
for z in i.users:
ids += str(z) + ", "
if ids != "":
# print ids
stream_threaded(self.timelinesStream.statuses.filter, self.session_id, follow=ids)
def add_friends(self):
try:
# print "setting friends"
self.timelinesStream.set_friends(self.main_stream.friends)
except AttributeError:
pass
@@ -344,6 +350,7 @@ class Session(object):
self.logged = False
self.twitter = twitter.twitter.twitter()
self.login(False)
# pub.sendMessage("streamError", session=self.session_id)
if self.reconnection_function_active == True: return
self.reconnection_function_active = True
if not hasattr(self, "main_stream"):
@@ -381,10 +388,11 @@ class Session(object):
if type(key) != str and type(key) != unicode:
output.speak("Uh oh, while shelving the database, a key of type " + str(type(key)) + " has been found. It will be converted to type str, but this will cause all sorts of problems on deshelve. Please bring this to the attention of the " + application.name + " developers immediately. More information about the error will be written to the error log.",True)
log.error("Uh oh, " + str(key) + " is of type " + str(type(key)) + "!")
# Convert unicode objects to UTF-8 strings before shelve these objects.
if type(value) == list and self.settings["general"]["persist_size"] != -1 and len(value) > self.settings["general"]["persist_size"]:
shelf[str(key)]=value[self.settings["general"]["persist_size"]:]
shelf[str(key.encode("utf-8"))]=value[self.settings["general"]["persist_size"]:]
else:
shelf[str(key)]=value
shelf[str(key.encode("utf-8"))]=value
shelf.close()
except:
output.speak("An exception occurred while shelving the " + application.name + " database. It will be deleted and rebuilt automatically. If this error persists, send the error log to the " + application.name + " developers.",True)
@@ -401,7 +409,7 @@ class Session(object):
try:
shelf=shelve.open(paths.config_path(shelfname),'c')
for key,value in shelf.items():
self.db[unicode(key)]=value
self.db[key]=value
shelf.close()
except:
output.speak("An exception occurred while deshelving the " + application.name + " database. It will be deleted and rebuilt automatically. If this error persists, send the error log to the " + application.name + " developers.",True)
@@ -410,3 +418,28 @@ class Session(object):
os.remove(shelfname)
except:
pass
def check_quoted_status(self, tweet):
status = tweets.is_long(tweet)
if status != False:
tweet["quoted"] = 1
tweet = self.get_quoted_tweet(tweet)
return tweet
def get_quoted_tweet(self, tweet):
quoted_tweet = self.twitter.twitter.show_status(id=tweet["id"])
urls = utils.find_urls_in_text(quoted_tweet["text"])
for url in range(0, len(urls)):
try: quoted_tweet["text"] = quoted_tweet["text"].replace(urls[url], quoted_tweet["entities"]["urls"][url]["expanded_url"])
except IndexError: pass
l = tweets.is_long(quoted_tweet)
id = tweets.get_id(l)
try: original_tweet = self.twitter.twitter.show_status(id=id)
except: return quoted_tweet
urls = utils.find_urls_in_text(original_tweet["text"])
for url in range(0, len(urls)):
try: original_tweet["text"] = original_tweet["text"].replace(urls[url], original_tweet["entities"]["urls"][url]["expanded_url"])
except IndexError: pass
return compose.compose_quoted_tweet(quoted_tweet, original_tweet)

View File

@@ -25,6 +25,7 @@ import gettext
import application
import platform
from glob import glob
import wx
def get_architecture_files():
if platform.architecture()[0][:2] == "32":
@@ -48,7 +49,7 @@ def get_data():
("accessible_output2/lib", glob("accessible_output2/lib/*.dll")),
("keys/lib", glob("keys/lib/*.dll")),
("keymaps", glob("keymaps/*.keymap")),
]+get_sounds()+get_locales()+get_documentation()+sound_lib.find_datafiles()+accessible_output2.find_datafiles()+enchant.utils.win32_data_files()+get_architecture_files()
]+get_sounds()+get_locales()+get_documentation()+sound_lib.find_datafiles()+accessible_output2.find_datafiles()+enchant.utils.win32_data_files()+get_architecture_files()+wx_files()
def get_documentation ():
answer = []
@@ -79,6 +80,24 @@ def get_locales():
answer.append(new)
return answer
def wx_files():
wxDir=wx.__path__[0]
localeMoFiles=set()
for f in glob("locales/*/LC_MESSAGES"):
g=f.replace("locales", "locale")
wxMoFile=os.path.join(wxDir,g,"wxstd.mo")
if os.path.isfile(wxMoFile):
localeMoFiles.add((f,(wxMoFile,)))
lang=os.path.split(os.path.split(f)[0])[1]
if '_' in lang:
lang=lang.split('_')[0]
f=os.path.join('locale',lang,'lc_messages')
g=f.replace("locale", "locales")
wxMoFile=os.path.join(wxDir,f,"wxstd.mo")
if os.path.isfile(wxMoFile):
localeMoFiles.add((g,(wxMoFile,)))
return list(localeMoFiles)
if __name__ == '__main__':
setup(
name = application.name,
@@ -92,7 +111,7 @@ options = {
'py2exe': {
'optimize':2,
'packages': ["pubsub", "pubsub.core", "pubsub.core.kwargs", "dbhash"],
'dll_excludes': ["MPR.dll", "api-ms-win-core-apiquery-l1-1-0.dll", "api-ms-win-core-console-l1-1-0.dll", "api-ms-win-core-delayload-l1-1-1.dll", "api-ms-win-core-errorhandling-l1-1-1.dll", "api-ms-win-core-file-l1-2-0.dll", "api-ms-win-core-handle-l1-1-0.dll", "api-ms-win-core-heap-obsolete-l1-1-0.dll", "api-ms-win-core-libraryloader-l1-1-1.dll", "api-ms-win-core-localization-l1-2-0.dll", "api-ms-win-core-processenvironment-l1-2-0.dll", "api-ms-win-core-processthreads-l1-1-1.dll", "api-ms-win-core-profile-l1-1-0.dll", "api-ms-win-core-registry-l1-1-0.dll", "api-ms-win-core-synch-l1-2-0.dll", "api-ms-win-core-sysinfo-l1-2-0.dll", "api-ms-win-security-base-l1-2-0.dll", "api-ms-win-core-heap-l1-2-0.dll", "api-ms-win-core-interlocked-l1-2-0.dll", "api-ms-win-core-localization-obsolete-l1-1-0.dll", "api-ms-win-core-string-l1-1-0.dll", "api-ms-win-core-string-obsolete-l1-1-0.dll", "WLDAP32.dll", "MSVCP90.dll"],
'dll_excludes': ["MPR.dll", "api-ms-win-core-apiquery-l1-1-0.dll", "api-ms-win-core-console-l1-1-0.dll", "api-ms-win-core-delayload-l1-1-1.dll", "api-ms-win-core-errorhandling-l1-1-1.dll", "api-ms-win-core-file-l1-2-0.dll", "api-ms-win-core-handle-l1-1-0.dll", "api-ms-win-core-heap-obsolete-l1-1-0.dll", "api-ms-win-core-libraryloader-l1-1-1.dll", "api-ms-win-core-localization-l1-2-0.dll", "api-ms-win-core-processenvironment-l1-2-0.dll", "api-ms-win-core-processthreads-l1-1-1.dll", "api-ms-win-core-profile-l1-1-0.dll", "api-ms-win-core-registry-l1-1-0.dll", "api-ms-win-core-synch-l1-2-0.dll", "api-ms-win-core-sysinfo-l1-2-0.dll", "api-ms-win-security-base-l1-2-0.dll", "api-ms-win-core-heap-l1-2-0.dll", "api-ms-win-core-interlocked-l1-2-0.dll", "api-ms-win-core-localization-obsolete-l1-1-0.dll", "api-ms-win-core-string-l1-1-0.dll", "api-ms-win-core-string-obsolete-l1-1-0.dll", "WLDAP32.dll", "MSVCP90.dll", "CRYPT32.dll", "mfc90.dll"],
'skip_archive': True
},
},

View File

@@ -129,24 +129,7 @@ class URLStream(object):
self.stream.volume = float(volume)
self.stream.play()
log.debug("played")
call_threaded(self.delete_when_done)
def is_playable(self, url,play=False,volume=1.0):
try:
log.debug("Checking URL playability...")
self.prepare(url)
if self.prepared == True:
stream=sound_lib.stream.URLStream(url=self.url)
if play:
return self.play(stream=stream,volume=volume,announce=False)
return True
except:
return False
def delete_when_done(self):
while hasattr(self,'stream') and self.stream.is_playing:
pass
del self.stream
# call_threaded(self.delete_when_done)
def stop_audio(self,delete=False):
if hasattr(self, "stream"):
@@ -156,8 +139,8 @@ class URLStream(object):
log.debug("Stopped audio stream.")
except:
log.exception("Exception while stopping stream.")
# if delete:
# del self.stream
if delete:
del self.stream
log.debug("Deleted audio stream.")
return True
else:

View File

@@ -21,31 +21,44 @@ class timelinesStreamer(TwythonStreamer):
self.lists = self.session.lists
def on_error(self, status_code, data):
log.debug("%s: %s" % (status_code, data))
log.error("error in stream: %s: %s" % (status_code, data))
# pub.sendMessage("stream-error", session=self.session.session_id)
def on_timeout(self, *args, **kwargs):
log.debug("Twitter timeout Error")
pub.sendMessage("stream-error")
log.error("Twitter timeout Error")
# pub.sendMessage("stream-error", session=self.session.session_id)
def check_tls(self, data):
for i in self.session.settings["other_buffers"]["timelines"]:
if data["user"]["screen_name"] == i:
if utils.find_item(data["id"], self.session.db["%s-timeline" % (i,)]) != None:
log.error("duplicated tweet. Ignoring it...")
return
try:
data_ = self.session.check_quoted_status(data)
data = data_
except AttributeError:
pass
if self.session.settings["general"]["reverse_timelines"] == False: self.session.db["%s-timeline" % (i,)].append(data)
else: self.session.db["%s-timeline" % (i,)].insert(0, data)
pub.sendMessage("item-in-timeline", data= data, user= self.session.db["user_name"], who= i)
# return
for i in self.session.lists:
try:
i.users.index(data["user"]["id"])
# print "Index in the list for the specified user: %d" % (i.users.index(data["user"]["id"]),)
usr = data["in_reply_to_user_id"]
if (usr != None and usr in self.friends) or data.has_key("retweeted_status"):
if (usr != None or usr in self.friends) or data.has_key("retweeted_status"):
data = self.session.check_quoted_status(data)
# print data
if self.session.settings["general"]["reverse_timelines"] == False: self.session.db["%s" % (i.name,)].append(data)
else: self.session.db["%s" % (i,)].insert(0, data)
pub.sendMessage("item-in-list", data= data, user= self.session.db["user_name"], where= i.name)
pub.sendMessage("item-in-list", data=data, user=self.session.db["user_name"], where=i.name)
elif usr == None:
if self.session.settings["general"]["reverse_timelines"] == False: self.session.db["%s" % (i.name,)].append(data)
else: self.session.db["%s" % (i,)].insert(0, data)
pub.sendMessage("item-in-list", data= data, user= self.session.db["user_name"], where= i.name)
except ValueError:
pub.sendMessage("item-in-list", data=data, user=self.session.db["user_name"], where=i.name)
except NameError:
pass
def set_friends(self, friends):

View File

@@ -22,22 +22,33 @@ class streamer(TwythonStreamer):
# self.blocked_users = []
def on_timeout(self, *args, **kwargs):
log.debug("Twitter timeout Error")
pub.sendMessage("stream-error")
log.error("Twitter timeout Error")
# pub.sendMessage("stream-error", session=self.session.session_id)
def on_error(self, status_code, data):
log.debug("Error %s: %s" % (status_code, data))
log.error("Error %s: %s" % (status_code, data))
# pub.sendMessage("stream-error", session=self.session.session_id)
def get_user(self):
return self.session.db["user_name"]
def put_data(self, place, data):
if self.session.db.has_key(place):
if utils.find_item(data["id"], self.session.db[place]) != None:
log.error("duplicated tweet. Ignoring it...")
return False
try:
data_ = self.session.check_quoted_status(data)
data = data_
except:
pass
if self.session.settings["general"]["reverse_timelines"] == False:
self.session.db[place].append(data)
else:
self.session.db[place].insert(0, data)
utils.is_audio(data)
return True
def block_user(self, data):
id = data["target"]["id"]
if id in self.friends:
@@ -54,30 +65,36 @@ class streamer(TwythonStreamer):
def check_send(self, data):
if self.session.db["user_name"] == data["user"]["screen_name"]:
self.put_data("sent_tweets", data)
pub.sendMessage("sent-tweet", data=data, user=self.get_user())
d = self.put_data("sent_tweets", data)
if d != False:
pub.sendMessage("sent-tweet", data=data, user=self.get_user())
def check_favs(self, data):
if data["source"]["screen_name"] == self.session.db["user_name"]:
self.put_data("favourites", data["target_object"])
pub.sendMessage("favourite", data=data["target_object"], user=self.get_user())
d = self.put_data("favourites", data["target_object"])
if d != False:
pub.sendMessage("favourite", data=data["target_object"], user=self.get_user())
def check_mentions(self, data):
if "@%s" % (self.session.db["user_name"]) in data["text"]:
self.put_data("mentions", data)
pub.sendMessage("mention", data=data, user=self.get_user())
d = self.put_data("mentions", data)
if d != False:
pub.sendMessage("mention", data=data, user=self.get_user())
def set_quoted_tweet(self, data):
self.put_data("mentions", data)
pub.sendMessage("mention", data=data, user=self.get_user())
d = self.put_data("mentions", data)
if d != False:
pub.sendMessage("mention", data=data, user=self.get_user())
def process_dm(self, data):
if self.session.db["user_name"] == data["direct_message"]["sender"]["screen_name"]:
self.put_data("sent_direct_messages", data["direct_message"])
pub.sendMessage("sent-dm", data=data["direct_message"], user=self.get_user())
d = self.put_data("sent_direct_messages", data["direct_message"])
if d != False:
pub.sendMessage("sent-dm", data=data["direct_message"], user=self.get_user())
else:
self.put_data("direct_messages", data["direct_message"])
pub.sendMessage("direct-message", data=data["direct_message"], user=self.get_user())
d = self.put_data("direct_messages", data["direct_message"])
if d != False:
pub.sendMessage("direct-message", data=data["direct_message"], user=self.get_user())
def check_follower(self, data):
if data["target"]["screen_name"] == self.session.db["user_name"]:
@@ -119,8 +136,9 @@ class streamer(TwythonStreamer):
self.check_mentions(data)
self.check_send(data)
if data["user"]["id"] in self.friends or data["user"]["screen_name"] == self.session.db["user_name"]:
self.put_data("home_timeline", data)
pub.sendMessage("item-in-home", data=data, user=self.get_user())
d = self.put_data("home_timeline", data)
if d != False:
pub.sendMessage("item-in-home", data=data, user=self.get_user())
elif data.has_key("event"):
if "favorite" == data["event"] and "favorites" in self.session.settings["general"]["buffer_order"]:
self.check_favs(data)

View File

@@ -10,7 +10,7 @@ import languageHandler
import arrow
import logging
import config
from long_tweets import twishort
from long_tweets import twishort, tweets
log = logging.getLogger("compose")
def StripChars(s):
@@ -60,11 +60,33 @@ def compose_tweet(tweet, db, relative_times):
try:
oldtext=text
text=twishort.get_full_text(tweet['long_uri'])
try: text = "rt @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], StripChars(text))
except KeyError: pass
except:
text=oldtext
if tweet.has_key("message"):
text = tweet["message"]
return [user+", ", text, ts+", ", source]
tweet["text"] = text
return [user+", ", tweet["text"], ts+", ", source]
def compose_quoted_tweet(quoted_tweet, original_tweet):
""" It receives a tweet and returns a list with the user, text for the tweet or message, date and the client where user is."""
text = StripChars(quoted_tweet["text"])
quoting_user = quoted_tweet["user"]["name"]
source = re.sub(r"(?s)<.*?>", "", quoted_tweet["source"])
try: text = "rt @%s: %s" % (quoted_tweet["retweeted_status"]["user"]["screen_name"], StripChars(quoted_tweet["retweeted_status"]["text"]))
except KeyError: text = "%s" % (StripChars(quoted_tweet["text"]))
if text[-1] in chars: text=text+"."
original_user = original_tweet["user"]["screen_name"]
original_text = StripChars(original_tweet["text"])
try: original_text = "rt @%s: %s" % (original_tweet["retweeted_status"]["user"]["screen_name"], StripChars(original_tweet["retweeted_status"]["text"]))
except KeyError: original_text = "%s" % (StripChars(original_tweet["text"]))
quoted_tweet["message"] = _(u"{0}. Quoted tweet from @{1}: {2}").format( quoted_tweet["text"], original_user, original_text)
quoted_tweet = tweets.clear_url(quoted_tweet)
return quoted_tweet
def compose_followers_list(tweet, db, relative_times=True):
if system == "Windows":
original_date = arrow.get(tweet["created_at"], "ddd MMM D H:m:s Z YYYY", locale="en")

View File

@@ -53,5 +53,3 @@ class twitter(object):
settings["twitter"]["user_secret"] = user_secret
settings.write()
def __init__(self):
log.error(certs.where())

View File

@@ -32,7 +32,7 @@ def find_item(id, listItem):
def find_list(name, lists):
for i in range(0, len(lists)):
if lists[i]["slug"] == name: return lists[i]["id"]
if lists[i]["name"] == name: return lists[i]["id"]
def find_previous_reply(id, listItem):
for i in range(0, len(listItem)):

View File

@@ -23,8 +23,8 @@ def perform_update(endpoint, current_version, app_name='', password=None, update
if not available_update:
logger.debug("No update available")
return False
available_version = available_update['current_version']
if not str(available_version) > str(current_version) or platform.system()+platform.architecture()[0][:2] not in available_update['downloads']:
available_version = float(available_update['current_version'])
if not float(available_version) > float(current_version) or platform.system()+platform.architecture()[0][:2] not in available_update['downloads']:
logger.debug("No update for this architecture")
return False
available_description = available_update.get('description', None)
@@ -122,4 +122,4 @@ def call_callback(callback, *args, **kwargs):
def donation():
dlg = commonMessageDialogs.donation()
if dlg == widgetUtils.YES:
webbrowser.open_new_tab("http://twblue.es/donate")
webbrowser.open_new_tab("http://twblue.es/?q=donate")

View File

@@ -1,4 +1,7 @@
import wx
import paths
import languageHandler
import sys
toolkit = "wx"
@@ -108,6 +111,15 @@ class mainLoopObject(wx.App):
def __init__(self):
self.app = wx.App()
self.lc = wx.Locale()
lang=languageHandler.getLanguage()
wxLang=self.lc.FindLanguageInfo(lang)
if not wxLang and '_' in lang:
wxLang=self.lc.FindLanguageInfo(lang.split('_')[0])
if hasattr(sys,'frozen'):
self.lc.AddCatalogLookupPathPrefix(paths.app_path("locales"))
if wxLang:
self.lc.Init(wxLang.Language)
def run(self):
self.app.MainLoop()

View File

@@ -16,9 +16,11 @@ class trendsPanel(wx.Panel):
self.create_list()
self.tweet = wx.Button(self, -1, _(u"Tweet"))
self.tweetTrendBtn = wx.Button(self, -1, _(u"Tweet about this trend"))
self.search_topic = wx.Button(self, -1, _(u"Search topic"))
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
btnSizer.Add(self.tweet, 0, wx.ALL, 5)
btnSizer.Add(self.tweetTrendBtn, 0, wx.ALL, 5)
btnSizer.Add(self.search_topic, 0, wx.ALL, 5)
self.sizer.Add(btnSizer, 0, wx.ALL, 5)
self.sizer.Add(self.list.list, 0, wx.ALL, 5)
self.SetSizer(self.sizer)

View File

@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
import wx
import application
def retweet_as_link(parent):
return wx.MessageDialog(parent, _(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?"), application.name, wx.YES_NO|wx.ICON_QUESTION).ShowModal()
@@ -8,7 +9,7 @@ def retweet_question(parent):
return wx.MessageDialog(parent, _(u"Would you like to add a comment to this tweet?"), _("Retweet"), wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION).ShowModal()
def delete_tweet_dialog(parent):
return wx.MessageDialog(parent, _(u"Do you really want to delete this message? It will be deleted from Twitter as well."), _(u"Delete"), wx.ICON_QUESTION|wx.YES_NO).ShowModal()
return wx.MessageDialog(parent, _(u"Do you really want to delete this tweet? It will be deleted from Twitter as well."), _(u"Delete"), wx.ICON_QUESTION|wx.YES_NO).ShowModal()
def exit_dialog(parent):
dlg = wx.MessageDialog(parent, _(u"Do you really want to close {0}?").format(application.name,), _(u"Exit"), wx.YES_NO|wx.ICON_QUESTION)
@@ -18,10 +19,10 @@ def needs_restart():
wx.MessageDialog(None, _(u" {0} must be restarted for these changes to take effect.").format(application.name,), _("Restart {0} ").format(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()
return wx.MessageDialog(None, _(u"Are you sure you want to delete this user from the database? This user will not appear in 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"))
entry = wx.TextEntryDialog(None, _(u"Enter the name of the client : "), _(u"Add client"))
if entry.ShowModal() == wx.ID_OK:
return entry.GetValue()
return None
@@ -31,23 +32,29 @@ def clear_list():
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()
return wx.MessageDialog(None, _(u"Do you really want to destroy this buffer?"), _(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()
return wx.MessageDialog(None, _(u"That 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()
return wx.MessageDialog(None, _(u"A timeline for this user already exists. You can't 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()
return wx.MessageDialog(None, _(u"This user has no tweets, so you can't open a timeline for them."), _(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()
return wx.MessageDialog(None, _(u"This is a protected Twitter user, which means you can't open a timeline using the Streaming API. The user's tweets will not update due to a twitter policy. Do you want to continue?"), _(u"Warning"), wx.ICON_WARNING|wx.YES_NO).ShowModal()
def no_following():
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()
return wx.MessageDialog(None, _(u"This is a protected user account, you need to follow this user to view their tweets or favorites."), _(u"Error"), wx.ICON_ERROR).ShowModal()
def donation():
dlg = wx.MessageDialog(None, _(u"If you like this application, we need your help to keep it operational. Help us donating to the project. This will let us pay the server, the domain on the Internet and some other things to ensure that TWBlue will keep developing. Your donation will let us continue writing features for TWBlue, and these features to be free. Would you like to donate now?"), _(u"We need your help"), wx.ICON_QUESTION|wx.YES_NO)
dlg = wx.MessageDialog(None, _(u"If you like {0} we need your help to keep it going. Help us by donating to the project. This will help us pay for the server, the domain and some other things to ensure that {0} will be actively maintained. Your donation will give us the means to continue the development of {0}, and to keep {0} free. Would you like to donate now?").format(application.name), _(u"We need your help"), wx.ICON_QUESTION|wx.YES_NO)
return dlg.ShowModal()
def no_tweets():
return wx.MessageDialog(None, _(u"This user has no tweets. {0} can't create a timeline.").format(application.name), _(u"Error"), wx.ICON_ERROR).ShowModal()
def no_favs():
return wx.MessageDialog(None, _(u"This user has no favorited tweets. {0} can't create a timeline.").format(application.name), _(u"Error"), wx.ICON_ERROR).ShowModal()

View File

@@ -123,6 +123,7 @@ class removeUserListDialog(listViewer):
self.SetTitle(_(u"Select a list to remove the user"))
self.createBtn.SetLabel(_(u"Remove"))
self.createBtn.SetDefault()
self.createBtn.SetId(wx.ID_OK)
self.editBtn.Disable()
self.view.Disable()
# self.subscriptors.Disable()

View File

@@ -78,6 +78,7 @@ class tweet(textLimited):
self.shortenButton.Disable()
self.unshortenButton.Disable()
self.translateButton = wx.Button(self.panel, -1, _(u"Translate..."), size=wx.DefaultSize)
self.translateButton.Enable(False)
self.autocompletionButton = wx.Button(self.panel, -1, _(u"&Autocomplete users"))
self.okButton = wx.Button(self.panel, wx.ID_OK, _(u"Send"), size=wx.DefaultSize)
self.okButton.SetDefault()
@@ -138,6 +139,7 @@ class retweet(tweet):
self.shortenButton.Disable()
self.unshortenButton.Disable()
self.translateButton = wx.Button(self.panel, -1, _(u"Translate message"), size=wx.DefaultSize)
self.translateButton.Enable(False)
self.autocompletionButton = wx.Button(self.panel, -1, _(u"&Autocomplete users"))
self.okButton = wx.Button(self.panel, wx.ID_OK, _(u"Send"), size=wx.DefaultSize)
self.okButton.SetDefault()
@@ -199,6 +201,7 @@ class dm(textLimited):
self.shortenButton.Disable()
self.unshortenButton.Disable()
self.translateButton = wx.Button(self.panel, -1, _(u"Translate message"), size=wx.DefaultSize)
self.translateButton.Enable(False)
self.okButton = wx.Button(self.panel, wx.ID_OK, _(u"Send"), size=wx.DefaultSize)
self.okButton.SetDefault()
cancelButton = wx.Button(self.panel, wx.ID_CANCEL, _(u"Close"), size=wx.DefaultSize)
@@ -216,6 +219,7 @@ class dm(textLimited):
self.buttonsBox3.Add(cancelButton, 0, wx.ALL, 5)
self.mainBox.Add(self.buttonsBox3, 0, wx.ALL, 5)
self.panel.SetSizer(self.mainBox)
# self.SetClientSize(self.mainBox.CalcMin())
def __init__(self, title, message, users):
super(dm, self).__init__()
@@ -277,6 +281,7 @@ class viewTweet(widgetUtils.BaseDialog):
self.unshortenButton = wx.Button(panel, -1, _(u"Expand URL"), size=wx.DefaultSize)
self.unshortenButton.Disable()
self.translateButton = wx.Button(panel, -1, _(u"Translate message"), size=wx.DefaultSize)
self.translateButton.Enable(False)
cancelButton = wx.Button(panel, wx.ID_CANCEL, _(u"Close"), size=wx.DefaultSize)
cancelButton.SetDefault()
buttonsBox = wx.BoxSizer(wx.HORIZONTAL)
@@ -332,6 +337,7 @@ class viewNonTweet(widgetUtils.BaseDialog):
self.unshortenButton = wx.Button(panel, -1, _(u"Expand URL"), size=wx.DefaultSize)
self.unshortenButton.Disable()
self.translateButton = wx.Button(panel, -1, _(u"Translate message"), size=wx.DefaultSize)
self.translateButton.Enable(False)
cancelButton = wx.Button(panel, wx.ID_CANCEL, _(u"Close"), size=wx.DefaultSize)
cancelButton.SetDefault()
buttonsBox = wx.BoxSizer(wx.HORIZONTAL)

View File

@@ -10,8 +10,10 @@ class UserActionsDialog(wx.Dialog):
userLabel = wx.StaticText(panel, -1, _(u"User"))
self.cb = wx.ComboBox(panel, -1, choices=users, value=users[0])
self.cb.SetFocus()
self.autocompletion = wx.Button(panel, -1, _(u"&Autocomplete users"))
userSizer.Add(userLabel, 0, wx.ALL, 5)
userSizer.Add(self.cb, 0, wx.ALL, 5)
userSizer.Add(self.autocompletion, 0, wx.ALL, 5)
actionSizer = wx.BoxSizer(wx.VERTICAL)
label2 = wx.StaticText(panel, -1, _(u"Action"))
self.follow = wx.RadioButton(panel, -1, _(u"Follow"), style=wx.RB_GROUP)
@@ -79,3 +81,9 @@ class UserActionsDialog(wx.Dialog):
def get_user(self):
return self.cb.GetValue()
def get_position(self):
return self.cb.GetPosition()
def popup_menu(self, menu):
self.PopupMenu(menu, self.cb.GetPosition())

View File

@@ -10,8 +10,10 @@ class selectUserDialog(wx.Dialog):
userLabel = wx.StaticText(panel, -1, _(u"User"))
self.cb = wx.ComboBox(panel, -1, choices=users, value=users[0])
self.cb.SetFocus()
self.autocompletion = wx.Button(panel, -1, _(u"&Autocomplete users"))
userSizer.Add(userLabel, 0, wx.ALL, 5)
userSizer.Add(self.cb, 0, wx.ALL, 5)
userSizer.Add(self.autocompletion, 0, wx.ALL, 5)
actionSizer = wx.BoxSizer(wx.VERTICAL)
label2 = wx.StaticText(panel, -1, _(u"Buffer type"))
self.tweets = wx.RadioButton(panel, -1, _(u"Tweets"), style=wx.RB_GROUP)
@@ -49,3 +51,9 @@ class selectUserDialog(wx.Dialog):
def get_user(self):
return self.cb.GetValue()
def get_position(self):
return self.cb.GetPosition()
def popup_menu(self, menu):
self.PopupMenu(menu, self.cb.GetPosition())

View File

@@ -26,8 +26,10 @@ class selectUserDialog(baseDialog.BaseWXDialog):
userSizer = wx.BoxSizer()
self.cb = wx.ComboBox(panel, -1, choices=users, value=users[0], size=wx.DefaultSize)
self.cb.SetFocus()
self.autocompletion = wx.Button(panel, -1, _(u"&Autocomplete users"))
userSizer.Add(wx.StaticText(panel, -1, _(u"User")), 0, wx.ALL, 5)
userSizer.Add(self.cb)
userSizer.Add(self.cb, 0, wx.ALL, 5)
userSizer.Add(self.autocompletion, 0, wx.ALL, 5)
sizer = wx.BoxSizer(wx.VERTICAL)
ok = wx.Button(panel, wx.ID_OK, _(u"OK"))
ok.SetDefault()

97
src/wxUI/menus.py Normal file
View File

@@ -0,0 +1,97 @@
# -*- coding: utf-8 -*-
import wx
class basePanelMenu(wx.Menu):
def __init__(self):
super(basePanelMenu, self).__init__()
self.retweet = wx.MenuItem(self, wx.NewId(), _(u"&Retweet"))
self.AppendItem(self.retweet)
self.reply = wx.MenuItem(self, wx.NewId(), _(u"Re&ply"))
self.AppendItem(self.reply)
self.fav = wx.MenuItem(self, wx.NewId(), _(u"Add to &favourites"))
self.AppendItem(self.fav)
self.unfav = wx.MenuItem(self, wx.NewId(), _(u"Remove from favo&urites"))
self.AppendItem(self.unfav)
self.openUrl = wx.MenuItem(self, wx.NewId(), _(u"&Open URL"))
self.AppendItem(self.openUrl)
self.play = wx.MenuItem(self, wx.NewId(), _(u"&Play audio"))
self.AppendItem(self.play)
self.view = wx.MenuItem(self, wx.NewId(), _(u"&Show tweet"))
self.AppendItem(self.view)
self.copy = wx.MenuItem(self, wx.NewId(), _(u"&Copy to clipboard"))
self.AppendItem(self.copy)
self.remove = wx.MenuItem(self, wx.NewId(), _(u"&Delete"))
self.AppendItem(self.remove)
self.userActions = wx.MenuItem(self, wx.NewId(), _(u"&User actions..."))
self.AppendItem(self.userActions)
class dmPanelMenu(wx.Menu):
def __init__(self):
super(dmPanelMenu, self).__init__()
self.reply = wx.MenuItem(self, wx.NewId(), _(u"Re&ply"))
self.AppendItem(self.reply)
self.openUrl = wx.MenuItem(self, wx.NewId(), _(u"&Open URL"))
self.AppendItem(self.openUrl)
self.play = wx.MenuItem(self, wx.NewId(), _(u"&Play audio"))
self.AppendItem(self.play)
self.view = wx.MenuItem(self, wx.NewId(), _(u"&Show direct message"))
self.AppendItem(self.view)
self.copy = wx.MenuItem(self, wx.NewId(), _(u"&Copy to clipboard"))
self.AppendItem(self.copy)
self.remove = wx.MenuItem(self, wx.NewId(), _(u"&Delete"))
self.AppendItem(self.remove)
self.userActions = wx.MenuItem(self, wx.NewId(), _(u"&User actions..."))
self.AppendItem(self.userActions)
class sentPanelMenu(wx.Menu):
def __init__(self):
super(sentPanelMenu, self).__init__()
self.openUrl = wx.MenuItem(self, wx.NewId(), _(u"&Open URL"))
self.AppendItem(self.openUrl)
self.play = wx.MenuItem(self, wx.NewId(), _(u"&Play audio"))
self.AppendItem(self.play)
self.view = wx.MenuItem(self, wx.NewId(), _(u"&Show tweet"))
self.AppendItem(self.view)
self.copy = wx.MenuItem(self, wx.NewId(), _(u"&Copy to clipboard"))
self.AppendItem(self.copy)
self.remove = wx.MenuItem(self, wx.NewId(), _(u"&Delete"))
self.AppendItem(self.remove)
class eventsPanelMenu(wx.Menu):
def __init__(self):
super(eventsPanelMenu, self).__init__()
self.view = wx.MenuItem(self, wx.NewId(), _(u"&Show event"))
self.AppendItem(self.view)
self.copy = wx.MenuItem(self, wx.NewId(), _(u"&Copy to clipboard"))
self.AppendItem(self.copy)
self.remove = wx.MenuItem(self, wx.NewId(), _(u"&Delete"))
self.AppendItem(self.remove)
class peoplePanelMenu(wx.Menu):
def __init__(self):
super(peoplePanelMenu, self).__init__()
self.reply = wx.MenuItem(self, wx.NewId(), _(u"Direct &message"))
self.AppendItem(self.reply)
self.lists = wx.MenuItem(self, wx.NewId(), _(u"&View lists"))
self.AppendItem(self.lists)
self.lists.Enable(False)
self.details = wx.MenuItem(self, wx.NewId(), _(u"Show user &profile"))
self.AppendItem(self.details)
self.view = wx.MenuItem(self, wx.NewId(), _(u"&Show user"))
self.AppendItem(self.view)
self.copy = wx.MenuItem(self, wx.NewId(), _(u"&Copy to clipboard"))
self.AppendItem(self.copy)
self.userActions = wx.MenuItem(self, wx.NewId(), _(u"&User actions..."))
self.AppendItem(self.userActions)
class trendsPanelMenu(wx.Menu):
def __init__(self):
super(trendsPanelMenu, self).__init__()
self.search_topic = wx.MenuItem(self, wx.NewId(), _(u"Search topic"))
self.AppendItem(self.search_topic)
self.tweetThisTrend = wx.MenuItem(self, wx.NewId(), _(u"&Tweet about this trend"))
self.AppendItem(self.tweetThisTrend)
self.view = wx.MenuItem(self, wx.NewId(), _(u"&Show item"))
self.AppendItem(self.view)
self.copy = wx.MenuItem(self, wx.NewId(), _(u"&Copy to clipboard"))
self.AppendItem(self.copy)

View File

@@ -41,9 +41,7 @@ class mainFrame(wx.Frame):
self.dm = user.Append(wx.NewId(), _(u"Direct me&ssage"))
self.addToList = user.Append(wx.NewId(), _(u"&Add to list"))
self.removeFromList = user.Append(wx.NewId(), _(u"R&emove from list"))
self.removeFromList.Enable(False)
self.viewLists = user.Append(wx.NewId(), _(u"&View lists"))
self.viewLists.Enable(False)
self.details = user.Append(wx.NewId(), _(u"Show user &profile"))
self.favs = user.Append(wx.NewId(), _(u"V&iew favourites"))
@@ -126,6 +124,8 @@ class mainFrame(wx.Frame):
self.SetClientSize(self.sizer.CalcMin())
# print self.GetSize()
def get_buffers(self):
return [self.nb.GetPage(i) for i in range(0, self.nb.GetPageCount())]
def search(self, name_, account):
for i in range(0, self.nb.GetPageCount()):

View File

@@ -5,7 +5,7 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2015-07-03 17:23+Hora de verano central (M<>xico)\n"
"POT-Creation-Date: 2015-09-29 09:37+Hora de verano central (M<>xico)\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -51,7 +51,7 @@ msgstr ""
#: ../doc\strings.py:378 ../doc\strings.py:381 ../doc\strings.py:384
#: ../doc\strings.py:387 ../doc\strings.py:390 ../doc\strings.py:393
#: ../doc\strings.py:396 ../doc\strings.py:399 ../doc\strings.py:402
#: ../doc\strings.py:405 ../doc\strings.py:421 ../doc\strings.py:424
#: ../doc\strings.py:405 ../doc\strings.py:423 ../doc\strings.py:426
msgid ""
"\n"
msgstr ""
@@ -361,7 +361,7 @@ msgid "* Global settings: Opens a dialogue which lets you configure settings for
msgstr ""
#: ../doc\strings.py:166
msgid "* Quit: asks whether you want to exit the program. If the answer is yes, it closes the application. If you do not want to be asked for confirmation before exiting, uncheck the checkbox from the global settings dialogue box."
msgid "* Exit: asks whether you want to exit the program. If the answer is yes, it closes the application. If you do not want to be asked for confirmation before exiting, uncheck the checkbox from the global settings dialogue box."
msgstr ""
#: ../doc\strings.py:169
@@ -973,7 +973,7 @@ msgid "* English: [Bryner Villalobos](https://twitter.com/Bry_StarkCR) and [Bill
msgstr ""
#: ../doc\strings.py:408
msgid "* Arabic: Mohammed Al Shara."
msgid "* Arabic: [Mohammed Al Shara](https://twitter.com/mohammed0204)."
msgstr ""
#: ../doc\strings.py:409
@@ -989,11 +989,11 @@ msgid "* Basque: [Sukil Etxenike](https://twitter.com/sukil2011)."
msgstr ""
#: ../doc\strings.py:412
msgid "* Finnish: Jani Kinnunen."
msgid "* Finnish: [Jani Kinnunen](https://twitter.com/jani_kinnunen)."
msgstr ""
#: ../doc\strings.py:413
msgid "* French: R\303\251mi Ruiz."
msgid "* French: [R\303\251mi Ruiz](https://twitter.com/blindhelp38)."
msgstr ""
#: ../doc\strings.py:414
@@ -1001,38 +1001,46 @@ msgid "* Galician: [Alba Kinteiro](https://twitter.com/albasmileforeve)."
msgstr ""
#: ../doc\strings.py:415
msgid "* German: Steffen Schultz."
msgid "* German: [Steffen Schultz](https://twitter.com/schulle4u)."
msgstr ""
#: ../doc\strings.py:416
msgid "* Hungarian: Robert Osztolykan."
msgid "* Croatian: [Zvonimir Stane\304\215i\304\207](https://twitter.com/zvonimirek222)."
msgstr ""
#: ../doc\strings.py:417
msgid "* Polish: Pawel Masarczyk."
msgid "* Hungarian: Robert Osztolykan."
msgstr ""
#: ../doc\strings.py:418
msgid "* Portuguese: Odenilton J\303\272nior Santos."
msgid "* Italian: [Christian Leo Mameli](https://twitter.com/llajta2012)."
msgstr ""
#: ../doc\strings.py:419
msgid "* Russian: Alexander Jaszyn."
msgid "* Polish: Pawel Masarczyk."
msgstr ""
#: ../doc\strings.py:420
msgid "* Turkish: Burak."
msgid "* Portuguese: Odenilton J\303\272nior Santos."
msgstr ""
#: ../doc\strings.py:423
#: ../doc\strings.py:421
msgid "* Russian: [\320\220\320\273\320\265\320\272\321\201\320\260\320\275\320\264\321\200 \320\257\321\210\320\270\320\275](https://twitter.com/radovest)."
msgstr ""
#: ../doc\strings.py:422
msgid "* Turkish: [Burak Y\303\274ksek](https://twitter.com/burakyuksek)."
msgstr ""
#: ../doc\strings.py:425
msgid "Many thanks also to the people who worked on the documentation. Initially, [Manuel Cortez](https://twitter.com/manuelcortez00) did the documentation in Spanish, and translated to English by [Bryner Villalobos](https://twitter.com/Bry_StarkCR), [Robert Spangler](https://twitter.com/glasscity1837), [Sussan Rey](https://twitter.com/sussanrey17), [Anibal Hernandez](https://twitter.com/anibalmetal), and [Holly Scott-Gardner](https://twitter.com/holly1994). It was updated by [Sukil Etxenike](https://twitter.com/sukil2011), with some valuable corrections by [Brian Hartgen](https://twitter.com/brianhartgen) and [Bill Dengler](https://twitter.com/codeofdusk)."
msgstr ""
#: ../doc\strings.py:426
#: ../doc\strings.py:428
msgid "---"
msgstr ""
#: ../doc\strings.py:427
#: ../doc\strings.py:429
msgid "Copyright \302\251 2013-2015. Manuel Cort\303\251z"
msgstr ""

File diff suppressed because it is too large Load Diff