The next generation branch has been added

This commit is contained in:
Manuel Cortez 2014-11-12 20:41:29 -06:00
parent 75f494fc5a
commit f54d9394b7
96 changed files with 2629 additions and 4517 deletions

View File

@ -5,23 +5,14 @@ user_name = string(default="")
ignored_clients = list(default=list())
[general]
language = string(default="system")
relative_times = boolean(default=True)
hide_gui = boolean(default=False)
voice_enabled = boolean(default=False)
max_api_calls = integer(default=1)
max_tweets_per_call = integer(default=100)
reverse_timelines = boolean(default=False)
time_to_check_streams = integer(default=30)
announce_stream_status = boolean(default=True)
ask_at_exit = boolean(default=True)
[sound]
volume = float(default=1.0)
input_device = string(default="Default")
output_device = string(default="Default")
current_soundpack = string(default="default")
global_mute = boolean(default=False)
sndup_api_key = string(default="")
[other_buffers]
@ -44,45 +35,3 @@ spelling_language = string(default="")
[services]
dropbox_token=string(default="")
[keymap]
up = string(default="control+win+up")
down = string(default="control+win+down")
left = string(default="control+win+left")
right = string(default="control+win+right")
conversation_up = string(default="control+win+shift+up")
conversation_down = string(default="control+win+shift+down")
show_hide = string(default="control+win+m")
compose = string(default="control+win+n")
reply = string(default="control+win+r")
retweet = string(default="control+win+shift+r")
dm = string(default="control+win+d")
fav = string(default="alt+win+f")
unfav = string(default="alt+shift+win+f")
action = string(default="control+win+s")
details = string(default="control+win+alt+n")
view = string(default="control+win+v")
close = string(default="control+win+f4")
open_timeline = string(default="control+win+i")
delete_buffer = string(default="control+win+shift+i")
url = string(default="control+win+return")
audio = string(default="control+win+alt+return")
volume_up = string(default="control+win+alt+up")
volume_down = string(default="control+win+alt+down")
go_home = string(default="control+win+home")
go_end = string(default="control+win+end")
go_page_up = string(default="control+win+pageup")
go_page_down = string(default="control+win+pagedown")
update_profile = string(default="alt+win+p")
delete = string(default="control+win+delete")
clear_list = string(default="control+win+shift+delete")
repeat_item = string(default="control+win+space")
copy_to_clipboard = string(default="control+win+c")
add_to_list = string(default="control+win+a")
remove_from_list = string(default="control+win+shift+a")
toggle_mute = string(default="control+win+shift+m")
toggle_global_mute = string(default="alt+win+m")
toggle_autoread = string(default="control+win+e")
search = string(default="control+win+-")
edit_keystrokes = string(default="control+win+k")
view_user_lists = string(default="control+win+l")
get_more_items = string(default="alt+win+pageup")

View File

@ -21,7 +21,7 @@ class SAPI5(Output):
priority = 101
def __init__(self):
if config.main["general"]["voice_enabled"] == False: raise OutputError
if config.app["app-settings"]["voice_enabled"] == False: raise OutputError
try:
self.object = load_com("SAPI.SPVoice")
self._voices = self._available_voices()

View File

@ -0,0 +1,56 @@
[sessions]
current_session = string(default="")
sessions = list(default=list())
[app-settings]
language = string(default="system")
hide_gui = boolean(default=False)
voice_enabled = boolean(default=False)
volume = float(default=1.0)
input_device = string(default="Default")
output_device = string(default="Default")
global_mute = boolean(default=False)
current_soundpack = string(default="default")
[keymap]
up = string(default="control+win+up")
down = string(default="control+win+down")
left = string(default="control+win+left")
right = string(default="control+win+right")
conversation_up = string(default="control+win+shift+up")
conversation_down = string(default="control+win+shift+down")
show_hide = string(default="control+win+m")
compose = string(default="control+win+n")
reply = string(default="control+win+r")
retweet = string(default="control+win+shift+r")
dm = string(default="control+win+d")
fav = string(default="alt+win+f")
unfav = string(default="alt+shift+win+f")
action = string(default="control+win+s")
details = string(default="control+win+alt+n")
view = string(default="control+win+v")
close = string(default="control+win+f4")
open_timeline = string(default="control+win+i")
delete_buffer = string(default="control+win+shift+i")
url = string(default="control+win+return")
audio = string(default="control+win+alt+return")
volume_up = string(default="control+win+alt+up")
volume_down = string(default="control+win+alt+down")
go_home = string(default="control+win+home")
go_end = string(default="control+win+end")
go_page_up = string(default="control+win+pageup")
go_page_down = string(default="control+win+pagedown")
update_profile = string(default="alt+win+p")
delete = string(default="control+win+delete")
clear_list = string(default="control+win+shift+delete")
repeat_item = string(default="control+win+space")
copy_to_clipboard = string(default="control+win+c")
add_to_list = string(default="control+win+a")
remove_from_list = string(default="control+win+shift+a")
toggle_mute = string(default="control+win+shift+m")
toggle_global_mute = string(default="alt+win+m")
toggle_autoread = string(default="control+win+e")
search = string(default="control+win+-")
edit_keystrokes = string(default="control+win+k")
view_user_lists = string(default="control+win+l")
get_more_items = string(default="alt+win+pageup")

View File

@ -2,7 +2,7 @@
name = 'TW Blue'
snapshot = False
if snapshot == False:
version = "0.48"
version = "0.47"
update_url = 'http://twblue.com.mx/updates/tw_blue.json'
else:
version = "4"
@ -13,7 +13,7 @@ copyright = u"copyright (C) 2013-2014, Manuel cortéz"
description = u"TW Blue is an app designed to use Twitter in a simple and fast way and avoiding, as far as possible, the consumtion of excessive resources of the machine where its running. With this app youll have access to most twitter features."
translators = [u"Bryner Villalobos (English)", u"Mohammed Al Shara (Arabic)", u"Salva Doménech, Juan Carlos Rivilla(Catalan)", u"Manuel cortéz(Spanish)", u"Sukil Etxenike Arizaleta(Basque)", u"Jani Kinnunen(finnish)", u"Javier Currás, José Manuel Delicado, Alba Quinteiro(Galician)", 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.com.mx"
#report_bugs_url = "http://twblue.com.mx/errores/api/soap/mantisconnect.php?wsdl"
report_bugs_url = "http://twblue.com.mx/errores/api/soap/mantisconnect.php?wsdl"
# Tokens
app_key = '8pDLbyOW3saYnvSZ4uLFg'

View File

@ -10,14 +10,6 @@ def convert_audioboom(url):
audio_id = url.split('.com/')[-1]
return 'https://audioboom.com/%s.mp3' % audio_id
@matches_url('http://q-audio.net')
def convert_q_audio(url):
result = re.match("^https?://q-audio.net/(i|d|download)/(?P<audio_id>[a-z0-9]+/?)$", url, re.I)
if not result or result.group("audio_id") is None:
raise TypeError('%r is not a valid URL' % url)
audio_id = result.group("audio_id")
return 'http://q-audio.net/download/%s' % audio_id
@matches_url ('http://soundcloud.com/')
def convert_soundcloud (url):
client_id = "df8113ca95c157b6c9731f54b105b473"

View File

@ -2,15 +2,14 @@
from config_utils import Configuration, ConfigurationResetException
import paths
MAINFILE = "session.conf"
MAINSPEC = "Conf.defaults"
MAINFILE = "twblue.conf"
MAINSPEC = "app-configuration.defaults"
main = None
app = None
def setup ():
global main
global app
try:
main = Configuration(paths.config_path(MAINFILE), paths.app_path(MAINSPEC))
app = Configuration(paths.config_path(MAINFILE), paths.app_path(MAINSPEC))
except ConfigurationResetException:
pass
# return main

View File

@ -1,3 +1 @@
# -*- coding: utf-8 -*-
import main, dialogs

View File

@ -0,0 +1,279 @@
# -*- coding: utf-8 -*-
import wx
import widgetUtils
import datetime
import webbrowser
import output
import config
import sound
from twitter import compose, prettydate, utils
from wxUI import buffers, dialogs
class bufferController(object):
def __init__(self, parent=None, function=None, session=None, *args, **kwargs):
super(bufferController, self).__init__()
self.function = function
self.compose_function = None
self.args = args
self.kwargs = kwargs
self.buffer = None
self.account = ""
def get_event(self, ev):
if ev.GetKeyCode() == wx.WXK_RETURN and ev.ControlDown(): event = "audio"
elif ev.GetKeyCode() == wx.WXK_RETURN: event = "url"
elif ev.GetKeyCode() == wx.WXK_F5: event = "volume_down"
elif ev.GetKeyCode() == wx.WXK_F6: event = "volume_up"
elif ev.GetKeyCode() == wx.WXK_DELETE and ev.ShiftDown(): event = "clear_list"
elif ev.GetKeyCode() == wx.WXK_DELETE: event = "delete_item"
else:
event = None
ev.Skip()
if event != None:
# try:
getattr(self, event)()
# except AttributeError:
#pass
def volume_down(self):
if config.app["app-settings"]["volume"] > 0.0:
if config.app["app-settings"]["volume"] <= 0.05:
config.app["app-settings"]["volume"] = 0.0
else:
config.app["app-settings"]["volume"] -=0.05
if hasattr(sound.URLStream, "stream"):
sound.URLStream.stream.volume = config.app["app-settings"]["volume"]
sound.player.play("volume_changed.ogg")
def volume_up(self):
if config.app["app-settings"]["volume"] < 1.0:
if config.app["app-settings"]["volume"] >= 0.95:
config.app["app-settings"]["volume"] = 1.0
else:
config.app["app-settings"]["volume"] +=0.05
if hasattr(sound.URLStream, "stream"):
sound.URLStream.stream.volume = config.app["app-settings"]["volume"]
sound.player.play("volume_changed.ogg")
def start_stream(self):
pass
def put_items_on_list(self, items):
pass
def remove_buffer(self):
pass
def remove_item(self, item):
self.buffer.list.remove_item(item)
def bind_events(self):
pass
def get_object(self):
return self.buffer
def set_list_position(self, reversed=False):
if reversed == False:
self.buffer.list.select_item(-1)
else:
self.buffer.list.select_item(0)
class accountPanel(bufferController):
def __init__(self, parent, name, account):
super(accountPanel, self).__init__(parent, None, name)
self.buffer = buffers.accountPanel(parent, name)
self.type = self.buffer.type
self.compose_function = None
self.id = self.buffer.GetId()
self.account = account
self.buffer.account = account
self.name = name
class emptyPanel(bufferController):
def __init__(self, parent, name, account):
super(emptyPanel, self).__init__(parent, None, name)
self.buffer = buffers.emptyPanel(parent, name)
self.type = self.buffer.type
self.compose_function = None
self.id = self.buffer.GetId()
self.account = account
self.buffer.account = account
self.name = name
class baseBufferController(bufferController):
def __init__(self, parent, function, name, sessionObject, account, bufferType=None, *args, **kwargs):
super(baseBufferController, self).__init__(parent, function, *args, **kwargs)
if bufferType != None:
self.buffer = getattr(buffers, bufferType)(parent, name)
else:
self.buffer = buffers.basePanel(parent, name)
self.name = name
self.type = self.buffer.type
self.id = self.buffer.GetId()
self.session = sessionObject
self.compose_function = compose.compose_tweet
self.account = account
self.buffer.account = account
self.bind_events()
def start_stream(self):
val = self.session.call_paged(self.function, *self.args, **self.kwargs)
number_of_items = self.session.order_buffer(self.name, val)
self.put_items_on_list(number_of_items)
def put_items_on_list(self, number_of_items):
if self.buffer.list.get_count() == 0:
for i in self.session.db[self.name]:
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"])
self.buffer.list.insert_item(False, *tweet)
# self.buffer.set_list_position()
elif self.buffer.list.get_count() > 0:
if self.session.settings["general"]["reverse_timelines"] == False:
for i in self.session.db[self.name][:number_of_items]:
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"])
self.buffer.list.insert_item(False, *tweet)
else:
for i in self.session.db[self.name][0:number_of_items]:
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"])
self.buffer.list.insert_item(True, *tweet)
def add_new_item(self, item):
tweet = self.compose_function(item, self.session.db, self.session.settings["general"]["relative_times"])
if self.session.settings["general"]["reverse_timelines"] == False:
self.buffer.list.insert_item(False, *tweet)
else:
self.buffer.list.insert_item(True, *tweet)
def bind_events(self):
self.buffer.list.list.Bind(wx.EVT_LIST_ITEM_FOCUSED, self.onFocus)
self.buffer.list.list.Bind(wx.EVT_CHAR_HOOK, self.get_event)
def get_tweet(self):
if self.session.db[self.name][self.buffer.list.get_selected()].has_key("retweeted_status"):
tweet = self.session.db[self.name][self.buffer.list.get_selected()]["retweeted_status"]
else:
tweet = self.session.db[self.name][self.buffer.list.get_selected()]
return tweet
def onFocus(self, ev):
tweet = self.get_tweet()
if self.session.settings["general"]["relative_times"] == True:
original_date = datetime.datetime.strptime(self.session.db[self.name][self.buffer.list.get_selected()]["created_at"], "%a %b %d %H:%M:%S +0000 %Y")
ts = prettydate(original_date)
self.buffer.list.list.SetStringItem(self.buffer.list.get_selected(), 2, ts)
if utils.is_audio(tweet):
sound.player.play("audio.ogg")
def audio(self):
tweet = self.get_tweet()
urls = utils.find_urls(tweet)
if len(urls) == 1:
sound.URLPlayer.play(urls[0])
else:
urls_list = dialogs.urlList.urlList()
urls_list.populate_list(urls)
if urls_list.get_response() == widgetUtils.OK:
sound.URLPlayer.play(urls_list.get_string())
def url(self):
tweet = self.get_tweet()
urls = utils.find_urls(tweet)
if len(urls) == 1:
output.speak(_(u"Opening URL..."))
webbrowser.open_new_tab(urls[0])
elif len(urls) > 1:
urls_list = dialogs.urlList.urlList()
urls_list.populate_list(urls)
if urls_list.get_response() == widgetUtils.OK:
output.speak(_(u"Opening URL..."))
webbrowser.open_new_tab(urls_list.get_string())
def clear_list(self):
dlg = wx.MessageDialog(None, _(u"Do you really want to empty this buffer? It's tweets will be removed from the list but not from Twitter"), _(u"Empty buffer"), wx.ICON_QUESTION|wx.YES_NO)
if dlg.ShowModal() == widgetUtils.YES:
self.session.db[self.name] = []
self.buffer.list.clear()
dlg.Destroy()
def delete_item(self):
dlg = wx.MessageDialog(None, _(u"Do you really want to delete this message?"), _(u"Delete"), wx.ICON_QUESTION|wx.YES_NO)
if dlg.ShowModal() == widgetUtils.YES:
index = self.buffer.list.get_selected()
try:
self.session.twitter.twitter.destroy_status(id=self.session.db[self.name][index]["id"])
self.session.db[self.name].pop(index)
self.buffer.list.remove_item(index)
if index > 0:
self.buffer.list.select_item(index-1)
except:
sound.player.play("error.ogg")
class eventsBufferController(bufferController):
def __init__(self, parent, name, session, account, *args, **kwargs):
super(eventsBufferController, self).__init__(parent, *args, **kwargs)
self.buffer = buffers.eventsPanel(parent, name)
self.name = name
self.account = account
self.id = self.buffer.GetId()
self.compose_function = compose.compose_event
self.session = session
def add_new_item(self, item):
tweet = self.compose_function(item, self.session.db["user_name"])
if self.session.settings["general"]["reverse_timelines"] == False:
self.buffer.list.insert_item(False, *tweet)
else:
self.buffer.list.insert_item(True, *tweet)
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")
self.compose_function = compose.compose_followers_list
def onFocus(self, ev):
pass
def delete_item(self): pass
def start_stream(self):
val = self.session.get_cursored_stream(self.name, self.function, *self.args, **self.kwargs)
# self.session.order_cursored_buffer(self.name, self.session.db[self.name])
self.put_items_on_list(val)
def put_items_on_list(self, number_of_items):
if self.buffer.list.get_count() == 0:
for i in self.session.db[self.name]["items"]:
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"])
self.buffer.list.insert_item(False, *tweet)
# self.buffer.set_list_position()
elif self.buffer.list.get_count() > 0:
if self.session.settings["general"]["reverse_timelines"] == False:
for i in self.session.db[self.name]["items"][:number_of_items]:
tweet = self.compose_function(i, self.session.db)
self.buffers.list.insert_item(False, *tweet)
else:
for i in self.session.db[self.name]["items"][0:number_of_items]:
tweet = self.compose_function(i, self.session.db)
self.buffer.list.insert_item(True, *tweet)
class searchBufferController(baseBufferController):
def start_stream(self):
val = getattr(self.session.twitter.twitter, self.function)(*self.args, **self.kwargs)
number_of_items = self.session.order_buffer(self.name, val["statuses"])
self.put_items_on_list(number_of_items)
if number_of_items > 0:
sound.player.play("search_updated.ogg")
class searchPeopleBufferController(searchBufferController):
def __init__(self, parent, function, name, sessionObject, account, bufferType="peoplePanel", *args, **kwargs):
super(searchPeopleBufferController, self).__init__(parent, function, name, sessionObject, account, bufferType="peoplePanel", *args, **kwargs)
self.compose_function = compose.compose_followers_list
def start_stream(self):
val = getattr(self.session.twitter.twitter, self.function)(*self.args, **self.kwargs)
number_of_items = self.session.order_buffer(self.name, val)
self.put_items_on_list(number_of_items)
if number_of_items > 0:
sound.player.play("search_updated.ogg")

View File

@ -0,0 +1,349 @@
# -*- coding: utf-8 -*-
from wxUI import (view, dialogs)
import buffersController
from sessionmanager import session
from pubsub import pub
import sound
import output
from mysc.thread_utils import call_threaded
from mysc.repeating_timer import RepeatingTimer
import config
import widgetUtils
import platform
if platform.system() == "Windows":
import keystrokeEditor
class Controller(object):
""" Main Controller for TWBlue. It manages the main window and sessions."""
def search_buffer(self, name_, user):
""" Searches a buffer.
name_ str: The name for the buffer
user str: The account for the buffer.
for example you may want to search the home_timeline buffer for the tw_blue2 user.
returns buffersController.buffer object with the result if there is one."""
for i in self.buffers:
if i.name == name_ and i.account == user: return i
def get_best_buffer(self):
# Gets the parent buffer to know what account is doing an action
view_buffer = self.view.get_current_buffer()
# If the account has no session attached, we will need to search the home_timeline for that account to use its session.
if view_buffer.type == "account" or view_buffer.type == "empty":
buffer = self.search_buffer("home_timeline", view_buffer.account)
else:
buffer = self.search_buffer(view_buffer.name, view_buffer.account)
return buffer
def bind_stream_events(self):
pub.subscribe(self.manage_home_timelines, "item-in-home")
pub.subscribe(self.manage_mentions, "mention")
pub.subscribe(self.manage_direct_messages, "direct-message")
pub.subscribe(self.manage_sent_dm, "sent-dm")
pub.subscribe(self.manage_sent_tweets, "sent-tweet")
pub.subscribe(self.manage_events, "event")
pub.subscribe(self.manage_followers, "follower")
pub.subscribe(self.manage_friend, "friend")
pub.subscribe(self.manage_unfollowing, "unfollowing")
pub.subscribe(self.manage_favourite, "favourite")
pub.subscribe(self.manage_unfavourite, "unfavourite")
pub.subscribe(self.manage_blocked_user, "blocked-user")
pub.subscribe(self.manage_unblocked_user, "unblocked-user")
pub.subscribe(self.manage_item_in_timeline, "item-in-timeline")
widgetUtils.connect_event(self.view, widgetUtils.CLOSE_EVENT, self.exit)
def bind_other_events(self):
pub.subscribe(self.editing_keystroke, "editing_keystroke")
def __init__(self):
super(Controller, self).__init__()
self.view = view.mainFrame(self)
self.buffers = []
self.view.prepare()
self.bind_stream_events()
self.bind_other_events()
self.do_work()
def do_work(self):
for i in session.sessions:
self.create_buffers(session.sessions[i])
sound.player.play("tweet_timeline.ogg")
def create_buffers(self, session):
session.get_user_info()
account = buffersController.accountPanel(self.view.nb, session.db["user_name"], session.db["user_name"])
self.buffers.append(account)
self.view.add_buffer(account.buffer , name=session.db["user_name"])
home = buffersController.baseBufferController(self.view.nb, "get_home_timeline", "home_timeline", session, session.db["user_name"])
self.buffers.append(home)
home.start_stream()
self.view.insert_buffer(home.buffer, name=_(u"Home"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
mentions = buffersController.baseBufferController(self.view.nb, "get_mentions_timeline", "mentions", session, session.db["user_name"])
self.buffers.append(mentions)
mentions.start_stream()
self.view.insert_buffer(mentions.buffer, name=_(u"Mentions"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
sound.player.play("mention_received.ogg")
dm = buffersController.baseBufferController(self.view.nb, "get_direct_messages", "direct_messages", session, session.db["user_name"], bufferType="dmPanel")
self.buffers.append(dm)
dm.start_stream()
self.view.insert_buffer(dm.buffer, name=_(u"Direct messages"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
sound.player.play("dm_received.ogg")
sent_dm = buffersController.baseBufferController(self.view.nb, "get_sent_messages", "sent_direct_messages", session, session.db["user_name"], bufferType="dmPanel")
self.buffers.append(sent_dm)
sent_dm.start_stream()
self.view.insert_buffer(sent_dm.buffer, name=_(u"Sent direct messages"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
sent_tweets = buffersController.baseBufferController(self.view.nb, "get_user_timeline", "sent_tweets", session, session.db["user_name"], bufferType="dmPanel", screen_name=session.db["user_name"])
self.buffers.append(sent_tweets)
sent_tweets.start_stream()
self.view.insert_buffer(sent_tweets.buffer, name=_(u"Sent tweets"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
if session.settings["other_buffers"]["show_favourites"] == True:
favourites = buffersController.baseBufferController(self.view.nb, "get_favorites", "favourites", session, session.db["user_name"])
self.buffers.append(favourites)
favourites.start_stream()
self.view.insert_buffer(favourites.buffer, name=_(u"Favourites"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
if session.settings["other_buffers"]["show_followers"] == True:
followers = buffersController.peopleBufferController(self.view.nb, "get_followers_list", "followers", session, session.db["user_name"], screen_name=session.db["user_name"])
self.buffers.append(followers)
followers.start_stream()
self.view.insert_buffer(followers.buffer, name=_(u"Followers"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
if session.settings["other_buffers"]["show_friends"] == True:
friends = buffersController.peopleBufferController(self.view.nb, "get_friends_list", "friends", session, session.db["user_name"], screen_name=session.db["user_name"])
self.buffers.append(friends)
friends.start_stream()
self.view.insert_buffer(friends.buffer, name=_(u"Friends"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
if session.settings["other_buffers"]["show_blocks"] == True:
blocks = buffersController.peopleBufferController(self.view.nb, "list_blocks", "blocked", session, session.db["user_name"])
self.buffers.append(blocks)
blocks.start_stream()
self.view.insert_buffer(blocks.buffer, name=_(u"Blocked users"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
if session.settings["other_buffers"]["show_muted_users"] == True:
muted = buffersController.peopleBufferController(self.view.nb, "get_muted_users_list", "muted", session, session.db["user_name"])
self.buffers.append(muted)
muted.start_stream()
self.view.insert_buffer(muted.buffer, name=_(u"Muted users"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
if session.settings["other_buffers"]["show_events"] == True:
events = buffersController.eventsBufferController(self.view.nb, "events", session, session.db["user_name"], bufferType="dmPanel", screen_name=session.db["user_name"])
self.buffers.append(events)
self.view.insert_buffer(events.buffer, name=_(u"Events"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
timelines = buffersController.emptyPanel(self.view.nb, "timelines", session.db["user_name"])
self.buffers.append(timelines)
self.view.insert_buffer(timelines.buffer , name=_(u"Timelines"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
for i in session.settings["other_buffers"]["timelines"]:
tl = buffersController.baseBufferController(self.view.nb, "get_user_timeline", "%s-timeline" % (i,), session, session.db["user_name"], bufferType=None, screen_name=i)
self.buffers.append(tl)
tl.start_stream()
self.view.insert_buffer(tl.buffer, name=_(u"Timeline for {}".format(i)), pos=self.view.search("timelines", session.db["user_name"]))
searches = buffersController.emptyPanel(self.view.nb, "searches", session.db["user_name"])
self.buffers.append(searches)
self.view.insert_buffer(searches.buffer , name=_(u"Searches"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
for i in session.settings["other_buffers"]["tweet_searches"]:
tl = buffersController.searchBufferController(self.view.nb, "search", "%s-searchterm" % (i,), session, session.db["user_name"], bufferType="searchPanel", q=i)
self.buffers.append(tl)
tl.start_stream()
self.view.insert_buffer(tl.buffer, name=_(u"Search for {}".format(i)), pos=self.view.search("searches", session.db["user_name"]))
tl.timer = RepeatingTimer(180, tl.start_stream)
tl.timer.start()
session.start_streaming()
def search(self, event=None):
dlg = dialogs.search.searchDialog()
if dlg.get_response() == widgetUtils.OK:
term = dlg.get("term")
buffer = self.get_best_buffer()
if dlg.get("tweets") == True:
if term not in buffer.session.settings["other_buffers"]["tweet_searches"]:
buffer.session.settings["other_buffers"]["tweet_searches"].append(term)
search = buffersController.searchBufferController(self.view.nb, "search", "%s-searchterm" % (term,), buffer.session, buffer.session.db["user_name"], bufferType="searchPanel", q=term)
else:
return
elif dlg.get("users") == True:
search = buffersController.searchPeopleBufferController(self.view.nb, "search_users", "%s-searchUser" % (term,), buffer.session, buffer.session.db["user_name"], bufferType=None, q=term)
self.buffers.append(search)
search.start_stream()
self.view.insert_buffer(search.buffer, name=_(u"Search for {}".format(term)), pos=self.view.search("searches", buffer.session.db["user_name"]))
search.timer = RepeatingTimer(180, search.start_stream)
search.timer.start()
dlg.Destroy()
def edit_keystrokes(self, event=None):
dlg = keystrokeEditor.keystrokeEditor()
dlg.put_keystrokes(**config.app["keymap"])
dlg.ShowModal()
dlg.Destroy()
def view_user_lists(self, users):
pass
def add_to_list(self, user):
pass
def remove_from_list(self, user):
pass
def lists_manager(self):
pass
def configuration(self):
pass
def update_profile(self):
pass
def show_document(self, document):
pass
def report_error(self):
pass
def check_for_updates(self, show_msg=True):
pass
def show_details_for_user(self, user):
pass
def delete(self):
pass
def exit(self, event=None):
for item in session.sessions:
session.sessions[item].settings.write()
session.sessions[item].main_stream.disconnect()
session.sessions[item].timelinesStream.disconnect()
sound.player.cleaner.cancel()
widgetUtils.exit_application()
def action(self, do_action):
pass
def post_tweet(self):
pass
def post_reply(self):
pass
def send_dm(self, user):
pass
def post_retweet(self):
pass
def viewTweet(self):
pass
def add_to_favourites(self):
pass
def remove_from_favourites(self):
pass
def open_timeline(self, user, timeline_tipe):
pass
def remove_buffer(self):
pass
def show_hide(self):
pass
def toggle_global_mute(self):
pass
def toggle_mute(self):
pass
def toggle_autoread(self):
pass
def go_conversation(self, orientation):
pass
def notify(self, play_sound=None, message=None, notification=False):
if play_sound != None:
sound.player.play(play_sound)
if message != None:
output.speak(message)
def manage_home_timelines(self, data, user):
buffer = self.search_buffer("home_timeline", user)
play_sound = "tweet_received.ogg"
buffer.add_new_item(data)
self.notify(play_sound=play_sound)
def manage_mentions(self, data, user):
buffer = self.search_buffer("mentions", user)
play_sound = "mention_received.ogg"
buffer.add_new_item(data)
message = _(u"New mention")
self.notify(play_sound=play_sound, message=message)
def manage_direct_messages(self, data, user):
buffer = self.search_buffer("direct_messages", user)
play_sound = "dm_received.ogg"
buffer.add_new_item(data)
message = _(u"New direct message")
self.notify(play_sound=play_sound, message=message)
def manage_sent_dm(self, data, user):
buffer = self.search_buffer("sent_direct_messages", user)
play_sound = "dm_sent.ogg"
buffer.add_new_item(data)
self.notify(play_sound=play_sound)
def manage_sent_tweets(self, data, user):
buffer = self.search_buffer("sent_tweets", user)
play_sound = "tweet_send.ogg"
buffer.add_new_item(data)
self.notify(play_sound=play_sound)
def manage_events(self, data, user):
buffer = self.search_buffer("events", user)
play_sound = "new_event.ogg"
buffer.add_new_item(data)
self.notify(play_sound=play_sound)
def manage_followers(self, data, user):
buffer = self.search_buffer("followers", user)
play_sound = "update_followers.ogg"
buffer.add_new_item(data)
self.notify(play_sound=play_sound)
def manage_friend(self, data, user):
buffer = self.search_buffer("friends", user)
buffer.add_new_item(data)
def manage_unfollowing(self, item, user):
buffer = self.search_buffer("friends", user)
play_sound = "new_event.ogg"
buffer.remove_item(item)
def manage_favourite(self, data, user):
buffer = self.search_buffer("favourites", user)
play_sound = "favourite.ogg"
buffer.add_new_item(data)
self.notify(play_sound=play_sound)
def manage_unfavourite(self, item, user):
buffer = self.search_buffer("favourites", user)
buffer.remove_item(item)
def manage_blocked_user(self, data, user):
buffer = self.search_buffer("blocked", user)
buffer.add_new_item(data)
def manage_unblocked_user(self, item, user):
buffer = self.search_buffer("blocked", user)
buffer.remove_item(item)
def manage_item_in_timeline(self, data, user, who):
buffer = self.search_buffer("%i-timeline" % (who,), user)
play_sound = "tweet_timeline.ogg"
buffer.add_new_item(data)
self.notify(play_sound=play_sound)
def editing_keystroke(self, action, parentDialog):
print "i've pressed"
def __del__(self):
config.app.write()

View File

@ -0,0 +1,9 @@
# -*- coding: utf-8 -*-
import widgetUtils
from wxUI.dialogs import message
class tweet(object):
def __init__(self, session):
super(tweet, self).__init__()
self.message = message.tweet(_(u"Write the tweet here"), _(u"tweet - 0 characters"), "")

View File

@ -68,7 +68,6 @@ class audioDialog(wx.Dialog):
services = []
if config.main["services"]["dropbox_token"] != "":
services.append("Dropbox")
services.append("TwUp")
services.append("SNDUp")
return services

View File

@ -0,0 +1,105 @@
# -*- coding: utf-8 -*-
############################################################
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################
import wx
import output
import config
import languageHandler
from enchant.checker import SpellChecker
from enchant.errors import DictNotFoundError
class spellCheckerDialog(wx.Dialog):
def __init__(self, text, dictionary):
super(spellCheckerDialog, self).__init__(None, 1)
try:
if config.main["general"]["language"] == "system": self.checker = SpellChecker()
else: self.checker = SpellChecker(languageHandler.getLanguage())
self.checker.set_text(text)
except DictNotFoundError:
wx.MessageDialog(None, _(u"A bug has happened. There are no dictionaries available for the selected language in TW Blue"), _(u"Error"), wx.ICON_ERROR).ShowModal()
self.Destroy()
panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
word = wx.StaticText(panel, -1, _(u"Mis-spelled word"))
self.word = wx.TextCtrl(panel, -1)
wordBox = wx.BoxSizer(wx.HORIZONTAL)
wordBox.Add(word)
wordBox.Add(self.word)
context = wx.StaticText(panel, -1, _(u"Context"))
self.context = wx.TextCtrl(panel, -1)
contextBox = wx.BoxSizer(wx.HORIZONTAL)
contextBox.Add(context)
contextBox.Add(self.context)
suggest = wx.StaticText(panel, -1, _(u"Suggestions"))
self.suggestions = wx.ListBox(panel, -1, choices=[], style=wx.LB_SINGLE)
suggestionsBox = wx.BoxSizer(wx.HORIZONTAL)
suggestionsBox.Add(suggest)
suggestionsBox.Add(self.suggestions)
ignore = wx.Button(panel, -1, _(u"Ignore"))
self.Bind(wx.EVT_BUTTON, self.onIgnore, ignore)
ignoreAll = wx.Button(panel, -1, _(u"Ignore all"))
self.Bind(wx.EVT_BUTTON, self.onIgnoreAll, ignoreAll)
replace = wx.Button(panel, -1, _(u"Replace"))
self.Bind(wx.EVT_BUTTON, self.onReplace, replace)
replaceAll = wx.Button(panel, -1, _(u"Replace all"))
self.Bind(wx.EVT_BUTTON, self.onReplaceAll, replaceAll)
close = wx.Button(panel, wx.ID_CANCEL)
btnBox = wx.BoxSizer(wx.HORIZONTAL)
btnBox.Add(ignore)
btnBox.Add(ignoreAll)
btnBox.Add(replace)
btnBox.Add(replaceAll)
btnBox.Add(close)
sizer.Add(wordBox)
sizer.Add(contextBox)
sizer.Add(suggestionsBox)
sizer.Add(btnBox)
panel.SetSizerAndFit(sizer)
self.check()
def check(self):
try:
self.checker.next()
textToSay = _(u"Mis-spelled word: %s") % (self.checker.word,)
context = u"... %s %s %s" % (self.checker.leading_context(10), self.checker.word, self.checker.trailing_context(10))
self.SetTitle(textToSay)
output.speak(textToSay)
self.word.SetValue(self.checker.word)
self.context.ChangeValue(context)
self.suggestions.Set(self.checker.suggest())
self.suggestions.SetFocus()
except StopIteration:
wx.MessageDialog(self, _(u"The spelling review has finished."), _("Finished"), style=wx.OK).ShowModal()
self.EndModal(wx.ID_OK)
except AttributeError:
pass
def onIgnore(self, ev):
self.check()
def onIgnoreAll(self, ev):
self.checker.ignore_always(word=self.checker.word)
self.check()
def onReplace(self, ev):
self.checker.replace(self.suggestions.GetStringSelection())
self.check()
def onReplaceAll(self, ev):
self.checker.replace_always(self.suggestions.GetStringSelection())
self.check()

View File

@ -1,3 +1 @@
# -*- coding: utf-8 -*-
from translator import *
import gui

View File

@ -17,11 +17,11 @@
#
############################################################
import wx
import translator
from wxUI.dialogs import baseDialog
class translateDialog(wx.Dialog):
class translateDialog(baseDialog.BaseDialog):
def __init__(self):
wx.Dialog.__init__(self, None, -1, title=_(u"Translate message"))
super(translateDialog, self).__init__(None, -1, title=_(u"Translate message"))
panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
staticSource = wx.StaticText(panel, -1, _(u"Source language"))
@ -38,7 +38,4 @@ class translateDialog(wx.Dialog):
ok = wx.Button(panel, wx.ID_OK)
ok.SetDefault()
cancel = wx.Button(panel, wx.ID_CANCEL)
self.SetEscapeId(wx.ID_CANCEL)
def onOk(self, ev):
self.EndModal(wx.ID_OK)
self.SetEscapeId(wx.ID_CANCEL)

View File

@ -1,10 +0,0 @@
# -*- coding: utf-8 -*-
from panels import accountPanel, emptyPanel
from base import *
from dm import *
from events import *
from favourites import *
from lists import *
from people import *
from tweet_searches import *
from user_searches import *

View File

@ -1,364 +0,0 @@
# -*- coding: utf-8 -*-
############################################################
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################
import wx
import gui.dialogs
import twitter
import webbrowser
import config
import sound
import url_shortener
import logging as original_logger
import output
import platform
import datetime
from twitter import prettydate
from multiplatform_widgets import widgets
from mysc import event
from mysc.thread_utils import call_threaded
from twython import TwythonError
log = original_logger.getLogger("buffers.base")
class basePanel(wx.Panel):
def bind_events(self):
self.Bind(event.MyEVT_OBJECT, self.update)
self.Bind(event.MyEVT_DELETED, self.Remove)
self.list.list.Bind(wx.EVT_CHAR_HOOK, self.interact)
if self.system == "Windows":
self.list.list.Bind(wx.EVT_LIST_ITEM_FOCUSED, self.onFocus)
else:
self.list.list.Bind(wx.EVT_LISTBOX, self.onFocus)
def get_message(self, dialog=False):
if dialog == False: return " ".join(self.compose_function(self.db.settings[self.name_buffer][self.list.get_selected()], self.db))
else:
list = self.compose_function(self.db.settings[self.name_buffer][self.list.get_selected()], self.db)
return " ".join(list[1:-2])
def create_list(self):
self.list = widgets.list(self, _(u"User"), _(u"Text"), _(u"Date"), _(u"Client"), style=wx.LC_REPORT|wx.LC_SINGLE_SEL|wx.LC_VRULES)
if self.system == "Windows":
self.list.set_windows_size(0, 30)
self.list.set_windows_size(1, 160)
self.list.set_windows_size(2, 55)
self.list.set_windows_size(3, 42)
self.list.set_size()
def __init__(self, parent, window, name_buffer, function=None, argumento=None, sound="", timeline=False):
if timeline == False:
self.type = "buffer"
elif timeline == True:
self.type = "timeline"
self.db = window.db
self.twitter = window.twitter
self.name_buffer = name_buffer
self.function = function
self.argumento = argumento
self.sound = sound
self.parent = window
self.compose_function = twitter.compose.compose_tweet
self.system = platform.system()
wx.Panel.__init__(self, parent)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.create_list()
self.btn = wx.Button(self, -1, _(u"Tweet"))
self.btn.Bind(wx.EVT_BUTTON, self.post_status)
self.retweetBtn = wx.Button(self, -1, _(u"Retweet"))
self.retweetBtn.Bind(wx.EVT_BUTTON, self.onRetweet)
self.responseBtn = wx.Button(self, -1, _(u"Reply"))
self.responseBtn.Bind(wx.EVT_BUTTON, self.onResponse)
self.dmBtn = wx.Button(self, -1, _(u"Direct message"))
self.dmBtn.Bind(wx.EVT_BUTTON, self.onDm)
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
btnSizer.Add(self.btn, 0, wx.ALL, 5)
btnSizer.Add(self.retweetBtn, 0, wx.ALL, 5)
btnSizer.Add(self.responseBtn, 0, wx.ALL, 5)
btnSizer.Add(self.dmBtn, 0, wx.ALL, 5)
self.sizer.Add(btnSizer, 0, wx.ALL, 5)
self.sizer.Add(self.list.list, 0, wx.ALL, 5)
self.bind_events()
self.SetSizer(self.sizer)
def remove_buffer(self):
if self.type == "timeline":
dlg = wx.MessageDialog(self, _(u"Do you really want to delete this timeline?"), _(u"Attention"), style=wx.ICON_QUESTION|wx.YES_NO)
if dlg.ShowModal() == wx.ID_YES:
names = config.main["other_buffers"]["timelines"]
user = self.name_buffer
log.info(u"Deleting %s's timeline" % user)
if user in names:
names.remove(user)
self.db.settings.pop(user)
pos = self.db.settings["buffers"].index(user)
self.db.settings["buffers"].remove(user)
return pos
elif self.type == "buffer":
output.speak(_(u"This buffer is not a timeline; it can't be deleted."))
return None
def remove_invalid_buffer(self):
if self.type == "timeline":
names = config.main["other_buffers"]["timelines"]
user = self.name_buffer
log.info(u"Deleting %s's timeline" % user)
if user in names:
names.remove(user)
self.db.settings.pop(user)
pos = self.db.settings["buffers"].index(user)
self.db.settings["buffers"].remove(user)
return pos
def Remove(self, ev):
# try:
self.list.remove_item(ev.GetItem())
# except:
# log.error(u"Cannot delete the %s item from list " % str(ev.GetItem()))
def destroy_status(self, ev):
index = self.list.get_selected()
try:
self.twitter.twitter.destroy_status(id=self.db.settings[self.name_buffer][index]["id"])
self.db.settings[self.name_buffer].pop(index)
self.list.remove_item(index)
if index > 0:
self.list.select_item(index-1)
except:
sound.player.play("error.ogg")
def onFocus(self, ev):
if self.db.settings[self.name_buffer][self.list.get_selected()].has_key("retweeted_status"): tweet = self.db.settings[self.name_buffer][self.list.get_selected()]["retweeted_status"]
else: tweet = self.db.settings[self.name_buffer][self.list.get_selected()]
if config.main["general"]["relative_times"] == True:
# On windows we need only put the new date on the column, but under linux and mac it isn't possible.
if self.system == "Windows":
original_date = datetime.datetime.strptime(tweet["created_at"], "%a %b %d %H:%M:%S +0000 %Y")
date = original_date-datetime.timedelta(seconds=-self.db.settings["utc_offset"])
ts = prettydate(original_date)
self.list.list.SetStringItem(self.list.get_selected(), 2, ts)
else:
self.list.list.SetString(self.list.get_selected(), " ".join(self.compose_function(self.db.settings[self.name_buffer][self.list.get_selected()], self.db)))
if twitter.utils.is_audio(tweet):
sound.player.play("audio.ogg", False)
def start_streams(self):
if self.name_buffer == "sent":
num = twitter.starting.start_sent(self.db, self.twitter, self.name_buffer, self.function, param=self.argumento)
else:
# try:
if self.argumento != None:
num = twitter.starting.start_stream(self.db, self.twitter, self.name_buffer, self.function, param=self.argumento)
else:
num = twitter.starting.start_stream(self.db, self.twitter, self.name_buffer, self.function)
# except TwythonError:
# raise TwythonError
# self.parent.delete_invalid_timeline()
if self.sound != "" and num > 0 and self.name_buffer != "home_timeline" and self.name_buffer != "sent": sound.player.play(self.sound)
return num
def get_more_items(self):
if config.main["general"]["reverse_timelines"] == False:
last_id = self.db.settings[self.name_buffer][0]["id"]
else:
last_id = self.db.settings[self.name_buffer][-1]["id"]
try:
items = twitter.starting.get_more_items(self.function, self.twitter, count=config.main["general"]["max_tweets_per_call"], max_id=last_id, screen_name=self.argumento)
except TwythonError as e:
output.speak(e.message)
for i in items:
if config.main["general"]["reverse_timelines"] == False:
self.db.settings[self.name_buffer].insert(0, i)
else:
self.db.settings[self.name_buffer].append(i)
if config.main["general"]["reverse_timelines"] == False:
for i in items:
tweet = self.compose_function(i, self.db)
self.list.insert_item(True, *tweet)
else:
for i in items:
tweet = self.compose_function(i, self.db)
self.list.insert_item(False, *tweet)
output.speak(_(u"%s items retrieved") % (len(items)))
def put_items(self, num):
if self.list.get_count() == 0:
for i in self.db.settings[self.name_buffer]:
tweet = self.compose_function(i, self.db)
self.list.insert_item(False, *tweet)
self.set_list_position()
elif self.list.get_count() > 0:
if config.main["general"]["reverse_timelines"] == False:
for i in self.db.settings[self.name_buffer][:num]:
tweet = self.compose_function(i, self.db)
self.list.insert_item(False, *tweet)
else:
for i in self.db.settings[self.name_buffer][0:num]:
tweet = self.compose_function(i, self.db)
self.list.insert_item(True, *tweet)
def onDm(self, ev):
if self.name_buffer == "sent": return
if self.name_buffer == "direct_messages":
self.onResponse(ev)
else:
user = self.db.settings[self.name_buffer][self.list.get_selected()]["user"]["screen_name"]
dlg = gui.dialogs.message.dm(_("Direct message to %s") % (user,), _(u"New direct message"), "", self)
if dlg.ShowModal() == wx.ID_OK:
call_threaded(self.twitter.api_call, call_name="send_direct_message", _sound="dm_sent.ogg", text=dlg.text.GetValue(), screen_name=dlg.cb.GetValue())
# dlg.Destroy()
if ev != None:
self.list.list.SetFocus()
def post_status(self, ev=None):
text = gui.dialogs.message.tweet(_(u"Write the tweet here"), _(u"Tweet"), "", self)
if text.ShowModal() == wx.ID_OK:
if text.image == None:
call_threaded(self.twitter.api_call, call_name="update_status", _sound="tweet_send.ogg", status=text.text.GetValue())
else:
call_threaded(self.twitter.api_call, call_name="update_status_with_media", _sound="tweet_send.ogg", status=text.text.GetValue(), media=text.file)
# text.Destroy()
if ev != None: self.list.list.SetFocus()
def onRetweet(self, ev):
if self.name_buffer != "direct_messages":
id=self.db.settings[self.name_buffer][self.list.get_selected()]["id"]
ask = wx.MessageDialog(self.parent, _(u"Would you like to add a comment to this tweet?"), _("Retweet"), wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION)
response = ask.ShowModal()
if response == wx.ID_YES:
dlg = gui.dialogs.message.retweet(_(u"Add your comment to the tweet"), _(u"Retweet"), u"“@%s: %s" % (self.db.settings[self.name_buffer][self.list.get_selected()]["user"]["screen_name"], self.db.settings[self.name_buffer][self.list.get_selected()]["text"]), self)
if dlg.ShowModal() == wx.ID_OK:
if dlg.image == None:
call_threaded(self.twitter.api_call, call_name="update_status", _sound="retweet_send.ogg", status=dlg.text.GetValue(), in_reply_to_status_id=dlg.in_reply_to)
else:
call_threaded(self.twitter.call_api, call_name="update_status_with_media", _sound="retweet_send.ogg", status=dlg.text.GetValue(), in_reply_to_status_id=text.in_reply_to, media=dlg.file)
# dlg.Destroy()
if ev != None:
self.list.list.SetFocus()
elif response == wx.ID_NO:
call_threaded(self.twitter.api_call, call_name="retweet", _sound="retweet_send.ogg", id=id)
if ev != None: self.list.list.SetFocus()
ask.Destroy()
def onResponse(self, ev):
if self.name_buffer == "sent": return
dlg = gui.dialogs.message.reply(_(u"Reply to %s") % (self.db.settings[self.name_buffer][self.list.get_selected()]["user"]["screen_name"]), _(u"Reply"), u"@%s " % (self.db.settings[self.name_buffer][self.list.get_selected()]["user"]["screen_name"]), self)
if dlg.ShowModal() == wx.ID_OK:
if dlg.image == None:
call_threaded(self.twitter.api_call, call_name="update_status", _sound="reply_send.ogg", in_reply_to_status_id=dlg.in_reply_to, status=dlg.text.GetValue())
else:
call_threaded(self.twitter.api_call, call_name="update_status_with_media", _sound="reply_send.ogg", in_reply_to_status_id=dlg.in_reply_to, status=dlg.text.GetValue(), media=dlg.file)
# dlg.Destroy()
if ev != None: self.list.list.SetFocus()
def update(self, ev):
data = ev.GetItem()
announce = ev.GetAnnounce()
if config.main["general"]["reverse_timelines"] == False: self.db.settings[self.name_buffer].append(data)
else: self.db.settings[self.name_buffer].insert(0, data)
tweet = self.compose_function(data, self.db)
self.list.insert_item(config.main["general"]["reverse_timelines"], *tweet)
if self.name_buffer not in config.main["other_buffers"]["muted_buffers"]:
if self.sound != "": sound.player.play(self.sound)
if announce != "": output.speak(announce)
if self.name_buffer in config.main["other_buffers"]["autoread_buffers"]:
output.speak(" ".join(tweet[:2]))
def interact(self, ev):
try:
if self.db.settings[self.name_buffer][self.list.get_selected()].has_key("retweeted_status"): tweet = self.db.settings[self.name_buffer][self.list.get_selected()]["retweeted_status"]
else: tweet = self.db.settings[self.name_buffer][self.list.get_selected()]
urls = twitter.utils.find_urls_in_text(tweet["text"])
except:
urls = []
if type(ev) is str: event = ev
else:
if ev.GetKeyCode() == wx.WXK_RETURN and ev.ControlDown(): event = "audio"
elif ev.GetKeyCode() == wx.WXK_RETURN: event = "url"
elif ev.GetKeyCode() == wx.WXK_F5: event = "volume_down"
elif ev.GetKeyCode() == wx.WXK_F6: event = "volume_up"
elif ev.GetKeyCode() == wx.WXK_DELETE and ev.ShiftDown(): event = "clear_list"
elif ev.GetKeyCode() == wx.WXK_DELETE: event = "delete_item"
else:
ev.Skip()
return
if event == "audio" and len(urls) > 0:
self.streamer(urls[0])
elif event == "url":
if len(urls) == 0: return
elif len(urls) == 1:
output.speak(_(u"Opening URL..."), True)
webbrowser.open(urls[0])
elif len(urls) > 1:
gui.dialogs.urlList.urlList(urls).ShowModal()
elif event == "volume_down":
if config.main["sound"]["volume"] > 0.05:
config.main["sound"]["volume"] = config.main["sound"]["volume"]-0.05
sound.player.play("volume_changed.ogg", False)
if hasattr(self.parent, "audioStream"):
self.parent.audioStream.stream.volume = config.main["sound"]["volume"]
elif event == "volume_up":
if config.main["sound"]["volume"] < 0.95:
config.main["sound"]["volume"] = config.main["sound"]["volume"]+0.05
sound.player.play("volume_changed.ogg", False)
if hasattr(self.parent, "audioStream"):
self.parent.audioStream.stream.volume = config.main["sound"]["volume"]
elif event == "clear_list" and self.list.get_count() > 0:
dlg = wx.MessageDialog(self, _(u"Do you really want to empty this buffer? It's tweets will be removed from the list but not from Twitter"), _(u"Empty buffer"), wx.ICON_QUESTION|wx.YES_NO)
if dlg.ShowModal() == wx.ID_YES:
self.db.settings[self.name_buffer] = []
self.list.clear()
elif event == "delete_item":
dlg = wx.MessageDialog(self, _(u"Do you really want to delete this message?"), _(u"Delete"), wx.ICON_QUESTION|wx.YES_NO)
if dlg.ShowModal() == wx.ID_YES:
self.destroy_status(wx.EVT_MENU)
else:
return
try:
ev.Skip()
except:
pass
def streamer(self, url):
if hasattr(self.parent, "audioStream"):
if self.parent.audioStream.stream.is_active() == 0:
output.speak(_(u"Playing..."))
self.parent.audioStream = sound.urlStream(url)
try:
self.parent.audioStream.prepare()
self.parent.audioStream.play()
except:
del self.parent.audioStream
output.speak(_(u"Unable to play audio."))
else:
output.speak(_(u"Audio stopped."))
self.parent.audioStream.stream.stop()
else:
output.speak(_(u"Playing..."))
self.parent.audioStream = sound.urlStream(url)
try:
self.parent.audioStream.prepare()
self.parent.audioStream.play()
except:
output.speak(_(u"Unable to play audio."))
del self.parent.audioStream
def set_list_position(self):
if config.main["general"]["reverse_timelines"] == False:
self.list.select_item(len(self.db.settings[self.name_buffer])-1)
else:
self.list.select_item(0)

View File

@ -1,48 +0,0 @@
# -*- coding: utf-8 -*-
############################################################
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################
import wx
import sound
import gui.dialogs
import logging as original_logger
from base import basePanel
from mysc.thread_utils import call_threaded
log = original_logger.getLogger("buffers.base")
class dmPanel(basePanel):
def __init__(self, parent, window, name_buffer, function, argumento=None, sound=""):
""" Class to DM'S. Reply and retweet buttons are not showed and they have your delete method for dm's."""
super(dmPanel, self).__init__(parent, window, name_buffer, function, argumento=argumento, sound=sound)
self.retweetBtn.Disable()
self.responseBtn.Disable()
def destroy_status(self, ev):
index = self.list.get_selected()
try:
self.twitter.twitter.destroy_direct_message(id=self.db.settings[self.name_buffer][index]["id"])
self.db.settings[self.name_buffer].pop(index)
self.remove_item(index)
except:
sound.player.play("error.ogg")
def onResponse(self, ev):
dlg = gui.dialogs.message.dm(_("Direct message to %s") % (self.db.settings[self.name_buffer][self.list.get_selected()]["sender"]["screen_name"]), _(u"New direct message"), "", self)
if dlg.ShowModal() == wx.ID_OK:
call_threaded(self.twitter.api_call, call_name="send_direct_message", _sound="dm_sent.ogg", text=dlg.text.GetValue(), screen_name=dlg.cb.GetValue())
if ev != None:
self.list.list.SetFocus()

View File

@ -1,134 +0,0 @@
# -*- coding: utf-8 -*-
############################################################
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################
import wx
import sound
import config
import platform
import gui.dialogs
import output
import logging as original_logger
from multiplatform_widgets import widgets
from mysc import event
from mysc.thread_utils import call_threaded
log = original_logger.getLogger("buffers.base")
class eventsPanel(wx.Panel):
""" Buffer to show events. Different than tweets or people."""
def get_more_items(self):
output.speak(_(u"This action is not supported for this buffer"))
def bind_events(self):
self.Bind(event.MyEVT_OBJECT, self.update)
def put_items(self, items):
pass
def get_selected_text(self):
if self.list.get_count() == 0: return _(u"Empty")
if self.system == "Windows":
return "%s. %s" % (self.list.list.GetItemText(self.list.get_selected()), self.list.list.GetItemText(self.list.get_selected(), 1))
else:
return self.list.list.GetStringSelection()
def get_message(self, dialog=False):
return self.get_selected_text()
def __init__(self, parent, window, sound=""):
self.type = "event"
self.system = platform.system()
self.name_buffer = "events"
self.parent = window
self.sound = "new_event.ogg"
wx.Panel.__init__(self, parent)
sizer = wx.BoxSizer()
self.list = widgets.list(self, _(u"Date"), _(u"Event"), size=(600,600), style=wx.LC_REPORT|wx.LC_SINGLE_SEL|wx.LC_VRULES)
self.tweet = wx.Button(self, -1, _(u"Tweet"))
self.tweet.Bind(wx.EVT_BUTTON, self.post_status)
self.delete_event = wx.Button(self, -1, _(u"Remove event"))
self.delete_event.Bind(wx.EVT_BUTTON, self.on_delete_event)
self.bind_events()
def on_delete_event(self, ev):
self.list.remove_item(self.get_selected())
def remove_buffer(self):
return None
def start_streams(self):
return 0
def post_status(self, ev=None):
text = gui.dialogs.message.tweet(_(u"Write the tweet here"), _(u"Tweet"), "", self.parent)
if text.ShowModal() == wx.ID_OK:
if text.image == None:
call_threaded(self.parent.twitter.api_call, call_name="update_status", _sound="tweet_send.ogg", status=text.text.GetValue())
else:
call_threaded(self.parent.twitter.api_call, call_name="update_status_with_media", _sound="tweet_send.ogg", status=text.text.GetValue(), media=text.file)
# text.Destroy()
if ev != None: self.list.list.SetFocus()
def update(self, ev):
tweet = ev.GetItem()
announce = ev.GetAnnounce()
self.list.insert_item(config.main["general"]["reverse_timelines"], *tweet)
if self.list.get_count() == 1:
self.list.select_item(0)
if self.name_buffer not in config.main["other_buffers"]["muted_buffers"]:
if self.sound != "": sound.player.play(self.sound)
# if announce != "": output.speak(announce)
if self.name_buffer in config.main["other_buffers"]["autoread_buffers"]:
output.speak(" ".join(tweet))
def interact(self, ev):
if type(ev) is str: event = ev
else:
if ev.GetKeyCode() == wx.WXK_F5: event = "volume_down"
elif ev.GetKeyCode() == wx.WXK_F6: event = "volume_up"
elif ev.GetKeyCode() == wx.WXK_DELETE and ev.ShiftDown(): event = "clear_list"
elif ev.GetKeyCode() == wx.WXK_DELETE: event = "delete_item"
else:
ev.Skip()
return
if event == "volume_down":
if config.main["sound"]["volume"] > 0.05:
config.main["sound"]["volume"] = config.main["sound"]["volume"]-0.05
sound.player.play("volume_changed.ogg", False)
if hasattr(self.parent, "audioStream"):
self.parent.audioStream.stream.volume = config.main["sound"]["volume"]
elif event == "volume_up":
if config.main["sound"]["volume"] < 0.95:
config.main["sound"]["volume"] = config.main["sound"]["volume"]+0.05
sound.player.play("volume_changed.ogg", False)
if hasattr(self.parent, "audioStream"):
self.parent.audioStream.stream.volume = config.main["sound"]["volume"]
elif event == "clear_list" and self.get_count() > 0:
dlg = wx.MessageDialog(self, _(u"Do you really want to empty this buffer? It's tweets will be removed from the list but not from Twitter"), _(u"Empty buffer"), wx.ICON_QUESTION|wx.YES_NO)
if dlg.ShowModal() == wx.ID_YES:
self.list.clear()
elif event == "delete_item":
dlg = wx.MessageDialog(self, _(u"Do you really want to delete this message?"), _(u"Delete"), wx.ICON_QUESTION|wx.YES_NO)
if dlg.ShowModal() == wx.ID_YES:
self.list.remove_item(self.list.get_selected())
else:
return
try:
ev.Skip()
except:
pass

View File

@ -1,62 +0,0 @@
# -*- coding: utf-8 -*-
############################################################
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################
import wx
import twitter
import config
import sound
import logging as original_logger
from base import basePanel
log = original_logger.getLogger("buffers.base")
class favsPanel(basePanel):
def __init__(self, parent, window, name_buffer, argumento=None, sound=""):
super(favsPanel, self).__init__(parent, window, name_buffer, function="", argumento=argumento, sound=sound)
self.type = "favourites_timeline"
def start_streams(self):
num = twitter.starting.get_favourites_timeline(self.db, self.twitter, self.name_buffer, param=self.argumento, count=200)
if self.sound != "" and num > 0:
sound.player.play(self.sound)
if self.list.get_count() > 0: self.put_items(num)
return num
return num
def remove_buffer(self):
dlg = wx.MessageDialog(self, _(u"Do you really want to delete this favourites timeline?"), _(u"Attention"), style=wx.ICON_QUESTION|wx.YES_NO)
if dlg.ShowModal() == wx.ID_YES:
names = config.main["other_buffers"]["favourites_timelines"]
user = self.argumento
log.info(u"Deleting %s's timeline" % user)
if user in names:
names.remove(user)
self.db.settings.pop(self.name_buffer)
pos = self.db.settings["buffers"].index(self.name_buffer)
self.db.settings["buffers"].remove(self.name_buffer)
return pos
def remove_invalid_buffer(self):
names = config.main["other_buffers"]["favourites_timelines"]
user = self.name_buffer[:-5]
log.info(u"Deleting %s's timeline" % user)
if user in names:
names.remove(user)
self.db.settings.pop(self.name_buffer)
pos = self.db.settings["buffers"].index(self.name_buffer)
self.db.settings["buffers"].remove(self.name_buffer)
return pos

View File

@ -1,68 +0,0 @@
# -*- coding: utf-8 -*-
############################################################
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################
import wx
import sound
import config
import twitter
import gui.dialogs
import logging as original_logger
from base import basePanel
from mysc.thread_utils import call_threaded
log = original_logger.getLogger("buffers.base")
class listPanel(basePanel):
def __init__(self, parent, window, name_buffer, argumento="", sound=""):
super(listPanel, self).__init__(parent, window, name_buffer, argumento=argumento, sound=sound)
self.type = "list"
self.users = []
self.sound = "list_tweet.ogg"
def start_streams(self):
self.retrieve_ids()
num = twitter.starting.start_list(self.db, self.twitter, self.name_buffer, list_id=self.argumento)
return num
def retrieve_ids(self):
self.users = twitter.starting.get_users_list(self.twitter, self.argumento)
def remove_buffer(self):
if self.type == "list":
dlg = wx.MessageDialog(self, _(u"Do you really want to delete this list?"), _(u"Attention"), style=wx.ICON_QUESTION|wx.YES_NO)
if dlg.ShowModal() == wx.ID_YES:
names = config.main["other_buffers"]["lists"]
user = self.name_buffer[:-5]
log.info(u"Deleting %s's list" % user)
if user in names:
names.remove(user)
self.db.settings.pop(self.name_buffer)
pos = self.db.settings["buffers"].index(self.name_buffer)
self.db.settings["buffers"].remove(self.name_buffer)
return pos
def remove_invalid_buffer(self):
if self.type == "list":
names = config.main["other_buffers"]["lists"]
user = self.name_buffer[:-5]
log.info(u"Deleting %s's list" % user)
if user in names:
names.remove(user)
self.db.settings.pop(self.name_buffer)
pos = self.db.settings["buffers"].index(self.name_buffer)
self.db.settings["buffers"].remove(self.name_buffer)
return pos

View File

@ -1,142 +0,0 @@
# -*- coding: utf-8 -*-
############################################################
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################
import wx
import sound
import config
import twitter
import gui.dialogs
import logging as original_logger
import output
from multiplatform_widgets import widgets
from mysc import event
from base import basePanel
from mysc.thread_utils import call_threaded
from twython import TwythonError
log = original_logger.getLogger("buffers.base")
class peoplePanel(basePanel):
""" Buffer used to show people."""
def bind_events(self):
self.Bind(event.MyEVT_OBJECT, self.update)
self.Bind(event.MyEVT_DELETED, self.Remove)
self.list.list.Bind(wx.EVT_CHAR_HOOK, self.interact)
def create_list(self):
self.list = widgets.list(self, _(u"User"), style=wx.LC_REPORT|wx.LC_SINGLE_SEL, size=(800, 800))
def __init__(self, parent, window, name_buffer, function, argumento=None, sound="", timeline=False):
self.type = "people"
super(peoplePanel, self).__init__(parent, window, name_buffer, function, argumento=argumento, sound=sound)
self.responseBtn.SetLabel(_(u"Mention"))
self.retweetBtn.Disable()
self.compose_function = twitter.compose.compose_followers_list
def onDm(self, ev):
if self.name_buffer == "sent": return
if self.name_buffer == "direct_messages":
self.onResponse(ev)
else:
user = self.db.settings[self.name_buffer][self.list.get_selected()]["screen_name"]
dlg = gui.dialogs.message.dm(_("Direct message to %s") % (user,), _(u"New direct message"), "", self)
if dlg.ShowModal() == wx.ID_OK:
call_threaded(self.twitter.api_call, call_name="send_direct_message", _sound="dm_sent.ogg", text=dlg.text.GetValue(), screen_name=dlg.cb.GetValue())
# dlg.Destroy()
if ev != None:
self.list.list.SetFocus()
def onResponse(self, ev):
dlg = gui.dialogs.message.reply(_(u"Mention to %s") % (self.db.settings[self.name_buffer][self.list.get_selected()]["screen_name"]), _(u"Mention"), u"@%s " % (self.db.settings[self.name_buffer][self.list.get_selected()]["screen_name"]), self)
if dlg.ShowModal() == wx.ID_OK:
if dlg.image == None:
call_threaded(self.twitter.api_call, call_name="update_status", _sound="reply_send.ogg", in_reply_to_status_id=dlg.in_reply_to, status=dlg.text.GetValue())
else:
call_threaded(self.twitter.api_call, call_name="update_status_with_media", _sound="reply_send.ogg", in_reply_to_status_id=dlg.in_reply_to, status=dlg.text.GetValue(), media=dlg.file)
# dlg.Destroy()
if ev != None: self.list.list.SetFocus()
def Remove(self, ev):
try:
index = self.list.get_selected()
self.list.remove_item(ev.GetItem())
except:
log.error("Unable to delete element %s from the list %s" % (str(ev.GetItem(), self.name_buffer)))
def start_streams(self):
num = twitter.starting.start_followers(self.db, self.twitter, self.name_buffer, self.function, param=self.argumento)
# sound.player.play(self.sound)
return num
def put_items(self, num):
if self.list.get_count() > 0:
self.list.clear()
for i in self.db.settings[self.name_buffer]:
f = self.compose_function(i, self.db)
self.list.insert_item(False, *f)
self.set_list_position()
def get_more_items(self):
if self.name_buffer == "followers": cursor = twitter.starting.followers_cursor
elif self.name_buffer == "friends": cursor = twitter.starting.friends_cursor
try:
items = twitter.starting.get_more_items(self.function, self.twitter, users=True, name=self.name_buffer, count=config.main["general"]["max_tweets_per_call"], cursor=cursor)
except TwythonError as e:
output.speak(e.message)
return
for i in items:
if config.main["general"]["reverse_timelines"] == False:
self.db.settings[self.name_buffer].insert(0, i)
else:
self.db.settings[self.name_buffer].append(i)
if config.main["general"]["reverse_timelines"] == False:
for i in items:
tweet = self.compose_function(i, self.db)
self.list.insert_item(True, *tweet)
else:
for i in items:
tweet = self.compose_function(i, self.db)
self.list.insert_item(False, *tweet)
output.speak(_(u"%s items retrieved") % (len(items)))
def interact(self, ev):
if type(ev) is str: event = ev
else:
if ev.GetKeyCode() == wx.WXK_RETURN:
event = "url"
elif ev.GetKeyCode() == wx.WXK_F5:
event = "volume_down"
elif ev.GetKeyCode() == wx.WXK_F6:
event = "volume_down"
else:
ev.Skip()
return
if event == "url":
gui.dialogs.show_user.showUserProfile(self.parent.twitter, self.db.settings[self.name_buffer][self.list.get_selected()]["screen_name"]).ShowModal()
elif event == "volume_down":
if config.main["sound"]["volume"] > 0.05:
config.main["sound"]["volume"] = config.main["sound"]["volume"]-0.05
sound.player.play("volume_changed.ogg")
elif event == "volume_up":
if config.main["sound"]["volume"] < 0.95:
config.main["sound"]["volume"] = config.main["sound"]["volume"]+0.05
sound.player.play("volume_changed.ogg")
if type(ev) is not str: ev.Skip()
def remove_buffer(self):
pos = None
return pos

View File

@ -1,51 +0,0 @@
# -*- coding: utf-8 -*-
############################################################
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################
import wx
import sound
import config
import twitter
import gui.dialogs
import logging as original_logger
from base import basePanel
log = original_logger.getLogger("buffers.base")
class trendPanel(basePanel):
def __init__(self, parent, window, name_buffer, *args, **kwargs):
super(searchPanel, self).__init__(parent, window, name_buffer, sound)
self.type = "trend"
self.args = kwargs
def start_streams(self):
num = twitter.starting.search(self.db, self.twitter, self.name_buffer, **self.args)
if num > 0: sound.player.play("search_updated.ogg")
self.put_items(num)
return num
def remove_buffer(self):
dlg = wx.MessageDialog(self, _(u"Do you really want to delete this search term?"), _(u"Attention"), style=wx.ICON_QUESTION|wx.YES_NO)
if dlg.ShowModal() == wx.ID_YES:
names = config.main["other_buffers"]["tweet_searches"]
user = self.name_buffer[:-7]
log.info(u"Deleting %s's search term" % user)
if user in names:
names.remove(user)
self.db.settings.pop(self.name_buffer)
pos = self.db.settings["buffers"].index(self.name_buffer)
self.db.settings["buffers"].remove(self.name_buffer)
return pos

View File

@ -1,58 +0,0 @@
# -*- coding: utf-8 -*-
############################################################
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################
import wx
import sound
import config
import twitter
import gui.dialogs
import output
import logging as original_logger
from base import basePanel
log = original_logger.getLogger("buffers.base")
class searchPanel(basePanel):
def __init__(self, parent, window, name_buffer, *args, **kwargs):
super(searchPanel, self).__init__(parent, window, name_buffer, sound)
self.type = "search"
self.args = kwargs
def load_search(self):
num = self.start_streams()
self.put_items(num)
def start_streams(self):
num = twitter.starting.search(self.db, self.twitter, self.name_buffer, **self.args)
if num > 0: sound.player.play("search_updated.ogg")
return num
def remove_buffer(self):
dlg = wx.MessageDialog(self, _(u"Do you really want to delete this search term?"), _(u"Attention"), style=wx.ICON_QUESTION|wx.YES_NO)
if dlg.ShowModal() == wx.ID_YES:
names = config.main["other_buffers"]["tweet_searches"]
user = self.name_buffer[:-7]
log.info(u"Deleting %s's search term" % user)
if user in names:
names.remove(user)
self.db.settings.pop(self.name_buffer)
pos = self.db.settings["buffers"].index(self.name_buffer)
self.db.settings["buffers"].remove(self.name_buffer)
return pos
def get_more_items(self):
output.speak(_(u"This action is not supported for this buffer"))

View File

@ -1,64 +0,0 @@
# -*- coding: utf-8 -*-
############################################################
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################
import wx
import twitter
import logging as original_logger
import sound
from people import peoplePanel
from mysc import event
from multiplatform_widgets import widgets
log = original_logger.getLogger("buffers.base")
class searchUsersPanel(peoplePanel):
def create_list(self):
""" Returns the list for put the tweets here."""
self.list = widgets.list(self, _(u"User"), style=wx.LC_REPORT|wx.LC_SINGLE_SEL, size=(800, 800))
# def bind_events(self):
# self.Bind(event.MyEVT_OBJECT, self.update)
# self.list.list.Bind(wx.EVT_CHAR_HOOK, self.interact)
def __init__(self, parent, window, name_buffer, *args, **kwargs):
super(searchUsersPanel, self).__init__(parent, window, name_buffer, function=None)
self.compose_function = twitter.compose.compose_followers_list
self.create_list()
self.args = args
self.kwargs = kwargs
self.type = "timeline"
def start_streams(self):
num = twitter.starting.search_users(self.db, self.twitter, self.name_buffer, **self.kwargs)
if num > 0: sound.player.play("search_updated.ogg")
# self.put_items(num)
return num
def load_search(self):
num = self.start_streams()
self.put_items(num)
def remove_buffer(self):
dlg = wx.MessageDialog(self, _(u"Do you really want to delete this search term?"), _(u"Attention"), style=wx.ICON_QUESTION|wx.YES_NO)
if dlg.ShowModal() == wx.ID_YES:
self.db.settings.pop(self.name_buffer)
pos = self.db.settings["buffers"].index(self.name_buffer)
self.db.settings["buffers"].remove(self.name_buffer)
return pos
def get_more_items(self):
output.speak(_(u"This action is not supported for this buffer"))

View File

@ -1 +0,0 @@
import message, urlList, follow, utils, show_user, update_profile, configuration, lists, search

View File

@ -1,424 +0,0 @@
# -*- coding: utf-8 -*-
############################################################
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################
import wx
import config
#import gui
from gui import buffers
import sound as snd
import sound_lib
import languageHandler
import logging as original_logger
import os
import webbrowser
import paths
import platform
from mysc import restart
log = original_logger.getLogger("configuration")
system = platform.system()
class general(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
sizer = wx.BoxSizer(wx.VERTICAL)
language = wx.StaticText(self, -1, _(u"Language"))
self.langs = languageHandler.getAvailableLanguages()
langs = []
[langs.append(i[1]) for i in self.langs]
self.codes = []
[self.codes.append(i[0]) for i in self.langs]
self.language = wx.ListBox(self, -1, choices=langs)
id = self.codes.index(config.main["general"]["language"])
self.language.SetSelection(id)
self.language.SetSize(self.language.GetBestSize())
langBox = wx.BoxSizer(wx.HORIZONTAL)
langBox.Add(language, 0, wx.ALL, 5)
langBox.Add(self.language, 0, wx.ALL, 5)
sizer.Add(langBox, 0, wx.ALL, 5)
self.ask_at_exit = wx.CheckBox(self, -1, _(U"ask before exiting TwBlue?"))
self.ask_at_exit.SetValue(config.main["general"]["ask_at_exit"])
sizer.Add(self.ask_at_exit, 0, wx.ALL, 5)
self.relative_time = wx.CheckBox(self, -1, _(U"Relative times"))
self.relative_time.SetValue(config.main["general"]["relative_times"])
sizer.Add(self.relative_time, 0, wx.ALL, 5)
if platform.system() == "Windows":
self.disable_sapi5 = wx.CheckBox(self, -1, _(u"Activate Sapi5 when any other screen reader is not being run"))
self.disable_sapi5.SetValue(config.main["general"]["voice_enabled"])
sizer.Add(self.disable_sapi5, 0, wx.ALL, 5)
self.show_gui = wx.CheckBox(self, -1, _(u"Activate the auto-start of the invisible interface"))
self.show_gui.SetValue(config.main["general"]["hide_gui"])
sizer.Add(self.show_gui, 0, wx.ALL, 5)
apiCallsBox = wx.BoxSizer(wx.HORIZONTAL)
apiCallsBox.Add(wx.StaticText(self, -1, _(u"API calls when the stream is started (One API call equals to 200 tweetts, two API calls equals 400 tweets, etc):")), 0, wx.ALL, 5)
self.apiCalls = wx.SpinCtrl(self, -1)
self.apiCalls.SetRange(1, 10)
self.apiCalls.SetValue(config.main["general"]["max_api_calls"])
self.apiCalls.SetSize(self.apiCalls.GetBestSize())
apiCallsBox.Add(self.apiCalls, 0, wx.ALL, 5)
sizer.Add(apiCallsBox, 0, wx.ALL, 5)
tweetsPerCallBox = wx.BoxSizer(wx.HORIZONTAL)
tweetsPerCallBox.Add(wx.StaticText(self, -1, _(u"Items on each API call")), 0, wx.ALL, 5)
self.itemsPerApiCall = wx.SpinCtrl(self, -1)
self.itemsPerApiCall.SetRange(0, 200)
self.itemsPerApiCall.SetValue(config.main["general"]["max_tweets_per_call"])
self.itemsPerApiCall.SetSize(self.itemsPerApiCall.GetBestSize())
tweetsPerCallBox.Add(self.itemsPerApiCall, 0, wx.ALL, 5)
sizer.Add(tweetsPerCallBox, 0, wx.ALL, 5)
self.reverse_timelines = wx.CheckBox(self, -1, _(u"Inverted buffers: The newest tweets will be shown at the beginning of the lists while the oldest at the end"))
self.reverse_timelines.SetValue(config.main["general"]["reverse_timelines"])
sizer.Add(self.reverse_timelines, 0, wx.ALL, 5)
self.SetSizer(sizer)
class other_buffers(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
sizer = wx.BoxSizer(wx.VERTICAL)
self.followers_value = config.main["other_buffers"]["show_followers"]
self.friends_value = config.main["other_buffers"]["show_friends"]
self.favs_value = config.main["other_buffers"]["show_favourites"]
self.events_value = config.main["other_buffers"]["show_events"]
self.blocks_value = config.main["other_buffers"]["show_blocks"]
self.mutes_value = config.main["other_buffers"]["show_muted_users"]
self.followers = wx.CheckBox(self, -1, _(u"Show followers"))
self.followers.SetValue(config.main["other_buffers"]["show_followers"])
sizer.Add(self.followers, 0, wx.ALL, 5)
self.friends = wx.CheckBox(self, -1, _(u"Show friends"))
self.friends.SetValue(config.main["other_buffers"]["show_friends"])
sizer.Add(self.friends, 0, wx.ALL, 5)
self.favs = wx.CheckBox(self, -1, _(u"Show favourites"))
self.favs.SetValue(config.main["other_buffers"]["show_favourites"])
sizer.Add(self.favs, 0, wx.ALL, 5)
self.blocks = wx.CheckBox(self, -1, _(u"Show blocked users"))
self.blocks.SetValue(config.main["other_buffers"]["show_blocks"])
sizer.Add(self.blocks, 0, wx.ALL, 5)
self.mutes = wx.CheckBox(self, -1, _(u"Show muted users"))
self.mutes.SetValue(config.main["other_buffers"]["show_muted_users"])
sizer.Add(self.mutes, 0, wx.ALL, 5)
self.events = wx.CheckBox(self, -1, _(u"Show events"))
self.events.SetValue(config.main["other_buffers"]["show_events"])
sizer.Add(self.events, 0, wx.ALL, 5)
self.SetSizer(sizer)
class ignoredClients(wx.Panel):
def __init__(self, parent):
super(ignoredClients, self).__init__(parent=parent)
sizer = wx.BoxSizer(wx.VERTICAL)
choices = config.main["twitter"]["ignored_clients"]
label = wx.StaticText(self, -1, _(u"Ignored clients"))
self.clients = wx.ListBox(self, -1, choices=choices)
self.clients.SetSize(self.clients.GetBestSize())
clientsBox = wx.BoxSizer(wx.HORIZONTAL)
clientsBox.Add(label, 0, wx.ALL, 5)
clientsBox.Add(self.clients, 0, wx.ALL, 5)
add = wx.Button(self, -1, _(u"Add client"))
remove = wx.Button(self, -1, _(u"Remove client"))
self.Bind(wx.EVT_BUTTON, self.add, add)
self.Bind(wx.EVT_BUTTON, self.remove, remove)
btnBox = wx.BoxSizer(wx.HORIZONTAL)
btnBox.Add(add, 0, wx.ALL, 5)
btnBox.Add(remove, 0, wx.ALL, 5)
sizer.Add(clientsBox, 0, wx.ALL, 5)
sizer.Add(btnBox, 0, wx.ALL, 5)
self.SetSizer(sizer)
def add(self, ev):
entry = wx.TextEntryDialog(self, _(u"Enter the name of the client here"), _(u"Add a new ignored client"))
if entry.ShowModal() == wx.ID_OK:
client = entry.GetValue()
if client not in config.main["twitter"]["ignored_clients"]:
config.main["twitter"]["ignored_clients"].append(client)
self.clients.Append(client)
def remove(self, ev):
if self.clients.GetCount() == 0: return
id = self.clients.GetSelection()
config.main["twitter"]["ignored_clients"].pop(id)
self.clients.Delete(id)
class sound(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
sizer = wx.BoxSizer(wx.VERTICAL)
volume = wx.StaticText(self, -1, _(u"Volume"))
self.volumeCtrl = wx.Slider(self)
self.volumeCtrl.SetRange(0, 100)
self.volumeCtrl.SetValue(config.main["sound"]["volume"]*100)
self.volumeCtrl.SetSize(self.volumeCtrl.GetBestSize())
volumeBox = wx.BoxSizer(wx.HORIZONTAL)
volumeBox.Add(volume, 0, wx.ALL, 5)
volumeBox.Add(self.volumeCtrl, 0, wx.ALL, 5)
sizer.Add(volumeBox, 0, wx.ALL, 5)
self.global_mute = wx.CheckBox(self, -1, _(u"Global mute"))
self.global_mute.SetValue(config.main["sound"]["global_mute"])
sizer.Add(self.global_mute, 0, wx.ALL, 5)
self.output_devices = sound_lib.output.Output.get_device_names()
output_label = wx.StaticText(self, -1, _(u"Output device"))
self.output = wx.ComboBox(self, -1, choices=self.output_devices, style=wx.CB_READONLY)
self.output.SetValue(config.main["sound"]["output_device"])
self.output.SetSize(self.output.GetBestSize())
outputBox = wx.BoxSizer(wx.HORIZONTAL)
outputBox.Add(output_label, 0, wx.ALL, 5)
outputBox.Add(self.output, 0, wx.ALL, 5)
sizer.Add(outputBox, 0, wx.ALL, 5)
self.input_devices = sound_lib.input.Input.get_device_names()
input_label = wx.StaticText(self, -1, _(u"Input device"))
self.input = wx.ComboBox(self, -1, choices=self.input_devices, style=wx.CB_READONLY)
self.input.SetValue(config.main["sound"]["input_device"])
self.input.SetSize(self.input.GetBestSize())
inputBox = wx.BoxSizer(wx.HORIZONTAL)
inputBox.Add(input_label, 0, wx.ALL, 5)
inputBox.Add(self.input, 0, wx.ALL, 5)
sizer.Add(inputBox, 0, wx.ALL, 5)
soundBox = wx.BoxSizer(wx.VERTICAL)
self.soundpacks = []
[self.soundpacks.append(i) for i in os.listdir(paths.sound_path()) if os.path.isdir(paths.sound_path(i)) == True ]
soundpack_label = wx.StaticText(self, -1, _(u"Sound pack"))
self.soundpack = wx.ComboBox(self, -1, choices=self.soundpacks, style=wx.CB_READONLY)
self.soundpack.SetValue(config.main["sound"]["current_soundpack"])
self.soundpack.SetSize(self.soundpack.GetBestSize())
soundBox.Add(soundpack_label, 0, wx.ALL, 5)
soundBox.Add(self.soundpack, 0, wx.ALL, 5)
sizer.Add(soundBox, 0, wx.ALL, 5)
self.SetSizer(sizer)
class audioServicesPanel(wx.Panel):
def __init__(self, parent):
super(audioServicesPanel, self).__init__(parent)
mainSizer = wx.BoxSizer(wx.VERTICAL)
apiKeyLabel = wx.StaticText(self, -1, _(u"If you've got a SndUp account, enter your API Key here. Whether the API Key is wrong, the App will fail to upload anything to the server. Whether there's no API Key here, then the audio files will be uploaded anonimously"))
self.apiKey = wx.TextCtrl(self, -1)
self.apiKey.SetValue(config.main["sound"]["sndup_api_key"])
dc = wx.WindowDC(self.apiKey)
dc.SetFont(self.apiKey.GetFont())
self.apiKey.SetSize(dc.GetTextExtent("0"*100))
apiKeyBox = wx.BoxSizer(wx.HORIZONTAL)
apiKeyBox.Add(apiKeyLabel, 0, wx.ALL, 5)
apiKeyBox.Add(self.apiKey, 0, wx.ALL, 5)
mainSizer.Add(apiKeyBox, 0, wx.ALL, 5)
first_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.dropbox = wx.Button(self, -1)
if len(config.main["services"]["dropbox_token"]) > 0:
self.dropbox.SetLabel(_(u"Unlink your Dropbox account"))
else:
self.dropbox.SetLabel(_(u"Link your Dropbox account"))
self.dropbox.Bind(wx.EVT_BUTTON, self.onLink_unlink)
first_sizer.Add(self.dropbox, 0, wx.ALL, 5)
mainSizer.Add(first_sizer, 0, wx.ALL, 5)
self.SetSizer(mainSizer)
def setup_dropbox(self):
from extra.AudioUploader import dropbox_transfer
auth = dropbox_transfer.dropboxLogin()
url = auth.get_url()
wx.MessageDialog(self, _(u"The authorisation request will be shown on your browser. Copy the code tat Dropbox will provide and, in the text box that will appear on TW Blue, paste it. This code is necessary to continue. You only need to do it once."), _(u"Authorisation"), wx.OK).ShowModal()
webbrowser.open(url)
dlg = wx.TextEntryDialog(self, _(u"Enter the code here."), _(u"Verification code"))
if dlg.ShowModal() == wx.ID_CANCEL:
return False
resp = dlg.GetValue()
if resp == "":
self.dropbox.SetLabel(_(u"Link your Dropbox account"))
return False
else:
try:
auth.authorise(resp)
self.dropbox.SetLabel(_(u"Unlink your Dropbox account"))
except:
wx.MessageDialog(self, _(u"Error during authorisation. Try again later."), _(u"Error!"), wx.ICON_ERROR).ShowModal()
self.dropbox.SetLabel(_(u"Link your Dropbox account"))
return False
def onLink_unlink(self, ev):
if self.dropbox.GetLabel() == _(u"Link your Dropbox account"):
self.setup_dropbox()
else:
self.disconnect_dropbox()
def disconnect_dropbox(self):
config.main["services"]["dropbox_token"] = ""
self.dropbox.SetLabel(_(u"Link your Dropbox account"))
class configurationDialog(wx.Dialog):
def __init__(self, parent):
self.parent = parent
wx.Dialog.__init__(self, None, -1)
panel = wx.Panel(self)
self.SetTitle(_(u"TW Blue preferences"))
sizer = wx.BoxSizer(wx.VERTICAL)
notebook = wx.Notebook(panel)
self.general = general(notebook)
notebook.AddPage(self.general, _(u"General"))
self.general.SetFocus()
self.buffers = other_buffers(notebook)
notebook.AddPage(self.buffers, _(u"Show other buffers"))
self.ignored_clients = ignoredClients(notebook)
notebook.AddPage(self.ignored_clients, _(u"Ignored clients"))
self.sound = sound(notebook)
notebook.AddPage(self.sound, _(u"Sound"))
self.services = audioServicesPanel(notebook)
notebook.AddPage(self.services, _(u"Audio Services"))
sizer.Add(notebook, 0, wx.ALL, 5)
ok_cancel_box = wx.BoxSizer(wx.HORIZONTAL)
ok = wx.Button(panel, wx.ID_OK, _(u"Save"))
ok.Bind(wx.EVT_BUTTON, self.onSave)
ok.SetDefault()
cancel = wx.Button(panel, wx.ID_CANCEL, _(u"Close"))
self.SetEscapeId(cancel.GetId())
ok_cancel_box.Add(ok, 0, wx.ALL, 5)
ok_cancel_box.Add(cancel, 0, wx.ALL, 5)
sizer.Add(ok_cancel_box, 0, wx.ALL, 5)
panel.SetSizer(sizer)
self.SetClientSize(sizer.CalcMin())
def check_followers_change(self):
if self.buffers.followers.GetValue() != self.buffers.followers_value:
if self.buffers.followers.GetValue() == True:
log.debug("Creating followers list...")
followers = buffers.peoplePanel(self.parent.nb, self.parent, "followers", self.parent.twitter.twitter.get_followers_list, argumento=self.parent.db.settings["user_name"])
self.parent.nb.InsertSubPage(self.parent.db.settings["buffers"].index(self.parent.db.settings["user_name"]), followers, _(u"Followers"))
num = followers.start_streams()
followers.put_items(num)
self.parent.db.settings["buffers"].append("followers")
elif self.buffers.followers.GetValue() == False:
self.parent.nb.DeletePage(self.parent.db.settings["buffers"].index("followers"))
self.parent.db.settings.pop("followers")
self.parent.db.settings["buffers"].remove("followers")
def check_friends_change(self):
if self.buffers.friends.GetValue() != self.buffers.friends_value:
if self.buffers.friends.GetValue() == True:
log.debug("Creating friends list...")
friends = buffers.peoplePanel(self.parent.nb, self.parent, "friends", self.parent.twitter.twitter.get_friends_list, argumento=self.parent.db.settings["user_name"])
self.parent.nb.InsertSubPage(self.parent.db.settings["buffers"].index(self.parent.db.settings["user_name"]), friends, _(u"friends"))
num = friends.start_streams()
friends.put_items(num)
self.parent.db.settings["buffers"].append("friends")
elif self.buffers.friends.GetValue() == False:
self.parent.nb.DeletePage(self.parent.db.settings["buffers"].index("friends"))
self.parent.db.settings.pop("friends")
self.parent.db.settings["buffers"].remove("friends")
def check_favs_change(self):
if self.buffers.favs.GetValue() != self.buffers.favs_value:
if self.buffers.favs.GetValue() == True:
log.debug("Creating favorites...")
favs = buffers.basePanel(self.parent.nb, self.parent, "favs", self.parent.twitter.twitter.get_favorites)
self.parent.nb.InsertSubPage(self.parent.db.settings["buffers"].index(self.parent.db.settings["user_name"]), favs, _(u"Favorites"))
num = favs.start_streams()
favs.put_items(num)
self.parent.db.settings["buffers"].append("favs")
elif self.buffers.favs.GetValue() == False:
self.parent.nb.DeletePage(self.parent.db.settings["buffers"].index("favs"))
self.parent.db.settings.pop("favs")
self.parent.db.settings["buffers"].remove("favs")
def check_events_change(self):
if self.buffers.events.GetValue() != self.buffers.events_value:
if self.buffers.events.GetValue() == True:
log.debug("Creating events...")
events = buffers.eventsPanel(self.parent.nb, self.parent)
self.parent.nb.InsertSubPage(self.parent.db.settings["buffers"].index(self.parent.db.settings["user_name"]), events, _(u"Events"))
self.parent.db.settings["buffers"].append("events")
elif self.buffers.events.GetValue() == False:
self.parent.nb.DeletePage(self.parent.db.settings["buffers"].index("events"))
self.parent.db.settings["buffers"].remove("events")
def check_blocks_change(self):
if self.buffers.blocks.GetValue() != self.buffers.blocks_value:
if self.buffers.blocks.GetValue() == True:
log.debug("Creating blocked users list...")
blocks = buffers.peoplePanel(self.parent.nb, self.parent, "blocks", self.parent.twitter.twitter.list_blocks)
self.parent.nb.InsertSubPage(self.parent.db.settings["buffers"].index(self.parent.db.settings["user_name"]), blocks, _(u"Blocked users"))
num = blocks.start_streams()
blocks.put_items(num)
self.parent.db.settings["buffers"].append("blocks")
elif self.buffers.blocks.GetValue() == False:
self.parent.nb.DeletePage(self.parent.db.settings["buffers"].index("blocks"))
self.parent.db.settings.pop("blocks")
self.parent.db.settings["buffers"].remove("blocks")
def check_mutes_change(self):
if self.buffers.mutes.GetValue() != self.buffers.mutes_value:
if self.buffers.mutes.GetValue() == True:
log.debug("Creating muted users list...")
mutes = buffers.peoplePanel(self.parent.nb, self.parent, "muteds", self.parent.twitter.twitter.get_muted_users_list)
self.parent.nb.InsertSubPage(self.parent.db.settings["buffers"].index(self.parent.db.settings["user_name"]), mutes, _(u"Muted users"))
num = mutes.start_streams()
mutes.put_items(num)
self.parent.db.settings["buffers"].append("muteds")
elif self.buffers.mutes.GetValue() == False:
self.parent.nb.DeletePage(self.parent.db.settings["buffers"].index("muteds"))
self.parent.db.settings.pop("muteds")
self.parent.db.settings["buffers"].remove("muteds")
def onSave(self, ev):
need_restart = False
# Check general settings
if config.main["general"]["language"] != self.general.langs[self.general.language.GetSelection()][0]:
if self.general.langs[self.general.language.GetSelection()][0] in self.general.codes: config.main["general"]["language"] = self.general.langs[self.general.language.GetSelection()][0]
languageHandler.setLanguage(config.main["general"]["language"])
need_restart = True
if platform.system() == "Windows":
config.main["general"]["voice_enabled"] = self.general.disable_sapi5.GetValue()
config.main["general"]["ask_at_exit"] = self.general.ask_at_exit.GetValue()
config.main["general"]["hide_gui"] = self.general.show_gui.GetValue()
config.main["general"]["max_api_calls"] = self.general.apiCalls.GetValue()
config.main["general"]["max_tweets_per_call"] = self.general.itemsPerApiCall.GetValue()
if config.main["general"]["relative_times"] != self.general.relative_time.GetValue():
config.main["general"]["relative_times"] = self.general.relative_time.GetValue()
need_restart = True
if config.main["general"]["reverse_timelines"] != self.general.reverse_timelines.GetValue():
config.main["general"]["reverse_timelines"] = self.general.reverse_timelines.GetValue()
need_restart = True
## Check buffers settings
config.main["other_buffers"]["show_followers"] = self.buffers.followers.GetValue()
self.check_followers_change()
config.main["other_buffers"]["show_friends"] = self.buffers.friends.GetValue()
self.check_friends_change()
config.main["other_buffers"]["show_favourites"] = self.buffers.favs.GetValue()
self.check_favs_change()
config.main["other_buffers"]["show_events"] = self.buffers.events.GetValue()
self.check_events_change()
config.main["other_buffers"]["show_blocks"] = self.buffers.blocks.GetValue()
self.check_blocks_change()
config.main["other_buffers"]["show_muted_users"] = self.buffers.mutes.GetValue()
self.check_mutes_change()
## Check sound settings
config.main["sound"]["volume"] = self.sound.volumeCtrl.GetValue()/100.0
config.main["sound"]["global_mute"] = self.sound.global_mute.GetValue()
if system == "Windows":
config.main["sound"]["output_device"] = self.sound.output.GetStringSelection()
config.main["sound"]["input_device"] = self.sound.input.GetValue()
try:
snd.player.input.set_device(snd.player.input.find_device_by_name(config.main["sound"]["input_device"]))
snd.player.output.set_device(snd.player.output.find_device_by_name(config.main["sound"]["output_device"]))
except:
config.main["sound"]["output_device"] = "Default"
config.main["sound"]["input_device"] = "Default"
config.main["sound"]["sndup_api_key"] = self.services.apiKey.GetValue()
config.main["sound"]["current_soundpack"] = self.sound.soundpack.GetStringSelection()
snd.player.check_soundpack()
if need_restart == True:
config.main.write()
wx.MessageDialog(None, _(u"The application requires to be restarted to save these changes. Press OK to do it now."), _("Restart TW Blue"), wx.OK).ShowModal()
restart.restart_program()
config.main.write()
self.EndModal(wx.ID_OK)

View File

@ -1,151 +0,0 @@
# -*- coding: utf-8 -*-
############################################################
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################
import wx
import config
from mysc import event
import twitter
from twitter import utils
from twython import TwythonError
import output
class follow(wx.Dialog):
def __init__(self, parent, default="follow"):
self.parent = parent
wx.Dialog.__init__(self, None, -1)
panel = wx.Panel(self)
userSizer = wx.BoxSizer()
self.SetTitle(_(u"Action"))
if self.parent.name_buffer == "followers" or self.parent.name_buffer == "friends":
list = [self.parent.db.settings[self.parent.name_buffer][self.parent.list.get_selected()]["screen_name"]]
else:
try: list =twitter.utils.get_all_users(self.parent.db.settings[self.parent.name_buffer][self.parent.list.get_selected()], self.parent.db)
except KeyError: list = [self.parent.db.settings[self.parent.name_buffer][self.parent.list.get_selected()]["screen_name"]]
self.cb = wx.ComboBox(panel, -1, choices=list, value=list[0])
self.cb.SetFocus()
userSizer.Add(self.cb)
actionSizer = wx.BoxSizer(wx.VERTICAL)
label2 = wx.StaticText(panel, -1, _(u"Action"))
self.follow = wx.RadioButton(panel, -1, _(u"Follow"), style=wx.RB_GROUP)
self.unfollow = wx.RadioButton(panel, -1, _(u"Unfollow"))
self.mute = wx.RadioButton(panel, -1, _(u"Mute"))
self.unmute = wx.RadioButton(panel, -1, _(u"Unmute"))
self.block = wx.RadioButton(panel, -1, _(u"Block"))
self.unblock = wx.RadioButton(panel, -1, _(u"Unblock"))
self.reportSpam = wx.RadioButton(panel, -1, _(u"Report as spam"))
self.setup_default(default)
actionSizer.Add(label2)
actionSizer.Add(self.follow)
actionSizer.Add(self.unfollow)
actionSizer.Add(self.mute)
actionSizer.Add(self.unmute)
actionSizer.Add(self.block)
actionSizer.Add(self.unblock)
actionSizer.Add(self.reportSpam)
sizer = wx.BoxSizer(wx.VERTICAL)
ok = wx.Button(panel, wx.ID_OK, _(u"OK"))
ok.Bind(wx.EVT_BUTTON, self.onok)
ok.SetDefault()
cancel = wx.Button(panel, wx.ID_CANCEL, _(u"Close"))
btnsizer = wx.BoxSizer()
btnsizer.Add(ok)
btnsizer.Add(cancel)
sizer.Add(userSizer)
sizer.Add(actionSizer)
sizer.Add(btnsizer)
panel.SetSizer(sizer)
self.Bind(wx.EVT_CHAR_HOOK, self.onEscape, self.cb)
def onEscape(self, ev):
if ev.GetKeyCode() == wx.WXK_RETURN:
self.onok(wx.EVT_BUTTON)
ev.Skip()
def onok(self, ev):
if self.follow.GetValue() == True:
try:
self.parent.twitter.twitter.create_friendship(screen_name=self.cb.GetValue())
self.Destroy()
except TwythonError as err:
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
elif self.unfollow.GetValue() == True:
try:
id = self.parent.twitter.twitter.destroy_friendship(screen_name=self.cb.GetValue())
self.Destroy()
except TwythonError as err:
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
elif self.mute.GetValue() == True:
try:
id = self.parent.twitter.twitter.create_mute(screen_name=self.cb.GetValue())
if config.main["other_buffers"]["show_muted_users"] == True:
tweet_event = event.event(event.EVT_OBJECT, 1)
tweet_event.SetItem(id)
wx.PostEvent(self.parent.parent.nb.GetPage(self.parent.db.settings["buffers"].index("muteds")), tweet_event)
self.parent.db.settings["muted_users"].append(id["id"])
self.Destroy()
output.speak(_(u"You've muted to %s") % (id["screen_name"]))
except TwythonError as err:
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
elif self.unmute.GetValue() == True:
try:
id = self.parent.twitter.twitter.destroy_mute(screen_name=self.cb.GetValue())
if config.main["other_buffers"]["show_muted_users"] == True:
item = utils.find_item(id, self.parent.db.settings["muteds"])
if item > 0:
deleted_event = event.event(event.EVT_DELETED, 1)
deleted_event.SetItem(item)
wx.PostEvent(self.parent.parent.nb.GetPage(self.parent.db.settings["buffers"].index("muteds")), deleted_event)
if id["id"] in self.parent.db.settings["muted_users"]: self.parent.db.settings["muted_users"].remove(id["id"])
self.Destroy()
output.speak(_(u"You've unmuted to %s") % (id["screen_name"]))
except TwythonError as err:
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
elif self.reportSpam.GetValue() == True:
try:
self.parent.twitter.twitter.report_spam(screen_name=self.cb.GetValue())
self.Destroy()
except TwythonError as err:
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
elif self.block.GetValue() == True:
try:
self.parent.twitter.twitter.create_block(screen_name=self.cb.GetValue())
self.Destroy()
except TwythonError as err:
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
elif self.unblock.GetValue() == True:
try:
self.parent.twitter.twitter.destroy_block(screen_name=self.cb.GetValue())
self.Destroy()
except TwythonError as err:
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
def setup_default(self, default):
if default == "follow":
self.follow.SetValue(True)
elif default == "unfollow":
self.unfollow.SetValue(True)
elif default == "mute":
self.mute.SetValue(True)
elif default == "unmute":
self.unmute.SetValue(True)
elif default == "report":
self.reportSpam.SetValue(True)
elif default == "block":
self.block.SetValue(True)
elif default == "unblock":
self.unblock.SetValue(True)

View File

@ -1,244 +0,0 @@
# -*- coding: utf-8 -*-
############################################################
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################
import wx
import platform
import output
import config
import gui
from multiplatform_widgets import widgets
from twython import TwythonError
from twitter import compose, utils
class listViewer(wx.Dialog):
def __init__(self, parent):
self.twitter = parent.twitter
self.db = parent.db
self.nb = parent.nb
self.parent = parent
wx.Dialog.__init__(self, None)
self.SetTitle(_(u"Lists manager"))
panel = wx.Panel(self)
label = wx.StaticText(panel, -1, _(u"Lists"))
self.lista = widgets.list(panel, _(u"List"), _(u"Description"), _(u"Owner"), _(u"Members"), _(u"mode"), size=(800, 800), style=wx.LC_REPORT|wx.LC_SINGLE_SEL)
self.lista.list.SetFocus()
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(label)
sizer.Add(self.lista.list)
self.createBtn = wx.Button(panel, wx.NewId(), _(u"Create a new list"))
self.createBtn.Bind(wx.EVT_BUTTON, self.onGo)
self.editBtn = wx.Button(panel, -1, _(u"Edit"))
self.Bind(wx.EVT_BUTTON, self.onEdit, self.editBtn)
self.deleteBtn = wx.Button(panel, -1, _(u"Remove"))
self.Bind(wx.EVT_BUTTON, self.onDelete, self.deleteBtn)
self.view = wx.Button(panel, -1, _(u"Open in buffer"))
self.Bind(wx.EVT_BUTTON, self.onView, self.view)
# self.members = wx.Button(panel, -1, _(u"View members"))
# self.members.Disable()
# self.subscriptors = wx.Button(panel, -1, _(u"View subscribers"))
# self.subscriptors.Disable()
# self.get_linkBtn = wx.Button(panel, -1, _(u"Get link for the list"))
# self.get_linkBtn.Bind(wx.EVT_BUTTON, self.onGetLink)
self.cancelBtn = wx.Button(panel, wx.ID_CANCEL)
btnSizer = wx.BoxSizer()
btnSizer.Add(self.createBtn)
btnSizer.Add(self.editBtn)
btnSizer.Add(self.cancelBtn)
panel.SetSizer(sizer)
self.populate_list()
self.lista.select_item(0)
def onGo(self, ev):
ev.Skip()
dlg = createListDialog()
if dlg.ShowModal() == wx.ID_OK:
name = dlg.name.GetValue()
description = dlg.description.GetValue()
if dlg.public.GetValue() == True: mode = "public"
else: mode = "private"
try:
new_list = self.twitter.twitter.create_list(name=name, description=description, mode=mode)
self.db.settings["lists"].append(new_list)
self.lista.insert_item(False, *compose.compose_list(new_list))
except TwythonError as e:
output.speak("error %s: %s" % (e.status_code, e.msg))
else:
return
dlg.Destroy()
def onEdit(self, ev):
ev.Skip()
if self.lista.get_count() == 0: return
list = self.db.settings["lists"][self.lista.get_selected()]
dlg = editListDialog(list)
if dlg.ShowModal() == wx.ID_OK:
name = dlg.name.GetValue()
description = dlg.description.GetValue()
if dlg.public.GetValue() == True: mode = "public"
else: mode = "private"
try:
self.twitter.twitter.update_list(list_id=self.lists[self.get_selected()]["id"], name=name, description=description, mode=mode)
except TwythonError as e:
output.speak("error %s: %s" % (e.error_code, e.msg))
else:
return
dlg.Destroy()
def onDelete(self, ev):
ev.Skip()
if self.lista.get_count() == 0: return
list = self.db.settings["lists"][self.lista.get_selected()]["id"]
dlg = wx.MessageDialog(self, _("Do you really want to delete this list?"), _("Delete"), wx.YES_NO)
if dlg.ShowModal() == wx.ID_YES:
try:
self.twitter.twitter.delete_list(list_id=list)
self.db.settings["lists"].pop(self.lista.get_selected())
self.remove_item(self.lista.get_selected())
except TwythonError as e:
output.speak("error %s: %s" % (e.error_code, e.msg))
dlg.Destroy()
def onView(self, ev):
ev.Skip()
if self.lista.get_count() == 0: return
list_id = self.db.settings["lists"][self.lista.get_selected()]["id"]
list_updated = self.twitter.twitter.get_specific_list(list_id=list_id)
self.db.settings["lists"][self.lista.get_selected()] = list_updated
if list_updated["slug"] not in config.main["other_buffers"]["lists"]:
config.main["other_buffers"]["lists"].append(list_updated["slug"])
output.speak(_(u"List opened"))
else:
output.speak(_(u"This list is arready opened."))
return
listUI = gui.buffers.lists.listPanel(self.nb, self.parent, list_updated["slug"]+"-list", argumento=utils.find_list(list_updated["slug"], self.db.settings["lists"]))
self.nb.AddPage(listUI, _(u"List for %s") % (list_updated["slug"],))
self.db.settings["buffers"].append(list_updated["slug"]+"-list")
num = listUI.start_streams()
listUI.put_items(num)
listUI.sound = "tweet_timeline.wav"
self.parent.stream2.disconnect()
del self.parent.stream2
self.parent.get_tls()
def populate_list(self):
for i in self.db.settings["lists"]:
item = compose.compose_list(i)
self.lista.insert_item(False, *item)
class userListViewer(listViewer):
def __init__(self, parent, username):
self.username = username
super(userListViewer, self).__init__(parent)
self.SetTitle(_(u"Viewing lists for %s") % (self.username))
self.createBtn.SetLabel(_(u"Subscribe"))
self.deleteBtn.SetLabel(_(u"Unsubscribe"))
self.editBtn.Disable()
self.view.Disable()
def populate_list(self):
self.lists = self.twitter.twitter.show_owned_lists(screen_name=self.username, count=200)["lists"]
for i in self.lists:
item = compose.compose_list(i)
self.lista.insert_item(False, *item)
def onGo(self, ev):
list_id = self.lists[self.lista.get_selected()]["id"]
try:
list = self.twitter.twitter.subscribe_to_list(list_id=list_id)
item = utils.find_item(list["id"], self.db.settings["lists"])
self.db.settings["lists"].append(list)
except TwythonError as e:
output.speak("error %s: %s" % (e.status_code, e.msg))
class createListDialog(wx.Dialog):
def __init__(self):
wx.Dialog.__init__(self, None, size=(450, 400))
self.SetTitle(_(u"Create a new list"))
panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
name = wx.StaticText(panel, -1, _(u"Name (20 characters maximun)"))
self.name = wx.TextCtrl(panel, -1)
nameSizer = wx.BoxSizer(wx.HORIZONTAL)
nameSizer.Add(name)
nameSizer.Add(self.name)
description = wx.StaticText(panel, -1, _(u"Description"))
self.description = wx.TextCtrl(panel, -1)
descriptionSizer = wx.BoxSizer(wx.HORIZONTAL)
descriptionSizer.Add(description)
descriptionSizer.Add(self.description)
mode = wx.StaticText(panel, -1, _(u"Mode"))
self.public = wx.RadioButton(panel, -1, _(u"Public"), style=wx.RB_GROUP)
self.private = wx.RadioButton(panel, -1, _(u"Private"))
modeBox = wx.BoxSizer(wx.HORIZONTAL)
modeBox.Add(mode)
modeBox.Add(self.public)
modeBox.Add(self.private)
ok = wx.Button(panel, wx.ID_OK)
ok.SetDefault()
cancel = wx.Button(panel, wx.ID_CANCEL)
btnBox = wx.BoxSizer(wx.HORIZONTAL)
btnBox.Add(ok)
btnBox.Add(cancel)
sizer.Add(nameSizer)
sizer.Add(descriptionSizer)
sizer.Add(modeBox)
sizer.Add(btnBox)
class editListDialog(createListDialog):
def __init__(self, list):
createListDialog.__init__(self)
self.SetTitle(_(u"Editing the list %s") % (list["name"]))
self.name.ChangeValue(list["name"])
self.description.ChangeValue(list["description"])
if list["mode"] == "public":
self.public.SetValue(True)
else:
self.private.SetValue(True)
class addUserListDialog(listViewer):
def __init__(self, parent):
listViewer.__init__(self, parent)
self.SetTitle(_(u"Select a list to add the user"))
self.createBtn.SetLabel(_(u"Add"))
self.createBtn.SetDefault()
self.editBtn.Disable()
self.view.Disable()
# self.subscriptors.Disable()
# self.members.Disable()
self.deleteBtn.Disable()
def onGo(self, ev):
self.EndModal(wx.ID_OK)
class removeUserListDialog(listViewer):
def __init__(self, parent):
listViewer.__init__(self, parent)
self.SetTitle(_(u"Select a list to remove the user"))
self.createBtn.SetLabel(_(u"Remove"))
self.createBtn.SetDefault()
self.editBtn.Disable()
self.view.Disable()
# self.subscriptors.Disable()
# self.members.Disable()
self.deleteBtn.Disable()
def onGo(self, ev):
self.EndModal(wx.ID_OK)

View File

@ -1,419 +0,0 @@
# -*- coding: utf-8 -*-
############################################################
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################
import wx
import twitter
import config
import output
import sound
import urlList
import url_shortener
import json
from mysc.thread_utils import call_threaded
from mysc.repeating_timer import RepeatingTimer
from twython import TwythonError
from extra import translator, AudioUploader
import platform
from extra.AudioUploader import transfer
if platform.system() != "Darwin":
from extra.AudioUploader import dropbox_transfer
from extra.SpellChecker import gui as spellCheckerGUI
class textLimited(wx.Dialog):
def __init__(self, message, title, text, parent):
wx.Dialog.__init__(self, parent)
self.twitter = parent.twitter
self.parent = parent
self.title = title
self.SetTitle(_(u"%s - %s of 140 characters") % (self.title, str(len(text))))
self.panel = wx.Panel(self)
def createTextArea(self, message, text):
self.label = wx.StaticText(self.panel, -1, message)
self.text = wx.TextCtrl(self.panel, -1, text)
font = self.text.GetFont()
dc = wx.WindowDC(self.text)
dc.SetFont(font)
x, y = dc.GetTextExtent("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
self.text.SetSize((x, y))
self.text.SetFocus()
if platform.system() != "Darwin":
self.text.Bind(wx.EVT_TEXT, self.onTimer)
self.textBox = wx.BoxSizer(wx.HORIZONTAL)
self.textBox.Add(self.label, 0, wx.ALL, 5)
self.textBox.Add(self.text, 0, wx.ALL, 5)
def onCheck(self, ev):
if platform.system() == "Darwin":
return
text = self.text.GetValue()
dlg = spellCheckerGUI.spellCheckerDialog(text, "")
if dlg.ShowModal() == wx.ID_OK:
self.text.ChangeValue(dlg.checker.get_text())
dlg.Destroy()
def onAttach(self, ev):
ev.Skip()
self.recording = AudioUploader.gui.audioDialog(self.parent)
if self.recording.ShowModal() != wx.ID_OK:
self.recording.cleanup()
return
self.recording.postprocess()
output.speak(_(u"Attaching..."))
self.uploaderDialog = AudioUploader.transfer_dialogs.UploadDialog(parent=self.parent, title=_(u"Uploading..."), filename=self.recording.file)
if self.recording.services.GetValue() == "Dropbox" and platform.system() != "Darwin":
self.uploader = dropbox_transfer.dropboxUploader(filename=self.recording.file, completed_callback=self.upload_completed, wxDialog=self.uploaderDialog)
elif self.recording.services.GetValue() == "SNDUp":
base_url = 'http://sndup.net/post.php'
if len(config.main["sound"]["sndup_api_key"]) > 0:
url = base_url + '?apikey=' + config.main['sound']['sndup_api_key']
else:
url = base_url
self.uploader = transfer.Upload(field='file', url=url, filename=self.recording.file, completed_callback=self.upload_completed, wxDialog=self.uploaderDialog)
elif self.recording.services.GetValue() == "TwUp":
url = 'http://api.twup.me/post.json'
self.uploader = transfer.Upload(field='file', url=url, filename=self.recording.file, completed_callback=self.upload_completed, wxDialog=self.uploaderDialog)
self.uploaderDialog.Show()
self.uploader.perform_threaded()
def upload_completed(self):
url = self.uploader.get_url()
self.uploaderDialog.Destroy()
if url != 0:
self.text.SetValue(self.text.GetValue()+url+" #audio")
else:
output.speak(_(u"Unable to upload the audio"))
def onTranslate(self, ev):
dlg = translator.gui.translateDialog()
selection = dlg.ShowModal()
if selection != wx.ID_CANCEL:
text_to_translate = self.text.GetValue().encode("utf-8")
source = [x[0] for x in translator.available_languages()][dlg.source_lang.GetSelection()]
dest = [x[0] for x in translator.available_languages()][dlg.dest_lang.GetSelection()]
t = translator.translator.Translator()
t.from_lang = source
t.to_lang = dest
msg = t.translate(text_to_translate)
self.text.ChangeValue(msg)
output.speak(_(u"Translated"))
self.text.SetFocus()
else:
return
dlg.Destroy()
def onSelect(self, ev):
self.text.SelectAll()
def onShorten(self, ev):
urls = twitter.utils.find_urls_in_text(self.text.GetValue())
if len(urls) == 0:
output.speak(_(u"There's no URL to be shortened"))
elif len(urls) == 1:
self.text.SetValue(self.text.GetValue().replace(urls[0], url_shortener.shorten(urls[0])))
output.speak(_(u"URL shortened"))
elif len(urls) > 1:
urlList.shorten(urls, self).ShowModal()
self.text.SetFocus()
def onUnshorten(self, ev):
urls = twitter.utils.find_urls_in_text(self.text.GetValue())
if len(urls) == 0:
output.speak(_(u"There's no URL to be expanded"))
elif len(urls) == 1:
self.text.SetValue(self.text.GetValue().replace(urls[0], url_shortener.unshorten(urls[0])))
output.speak(_(u"URL expanded"))
elif len(urls) > 1:
urlList.unshorten(urls, self).ShowModal()
self.text.SetFocus()
def onTimer(self, ev):
self.SetTitle(_(u"%s - %s of 140 characters") % (self.title, str(len(self.text.GetValue()))))
if len(self.text.GetValue()) > 1:
self.shortenButton.Enable()
self.unshortenButton.Enable()
else:
self.shortenButton.Disable()
self.unshortenButton.Disable()
if len(self.text.GetValue()) > 140:
sound.player.play("max_length.ogg")
self.okButton.Disable()
elif len(self.text.GetValue()) <= 140:
self.okButton.Enable()
def onCancel(self, ev):
self.Destroy()
class tweet(textLimited):
def createControls(self, message, title, text):
self.mainBox = wx.BoxSizer(wx.VERTICAL)
self.createTextArea(message, text)
self.mainBox.Add(self.textBox, 0, wx.ALL, 5)
self.upload_image = wx.Button(self.panel, -1, _(u"Upload a picture"), size=wx.DefaultSize)
self.upload_image.Bind(wx.EVT_BUTTON, self.onUpload_image)
if platform.system() != "Darwin":
self.spellcheck = wx.Button(self.panel, -1, _("Spelling correction"), size=wx.DefaultSize)
self.spellcheck.Bind(wx.EVT_BUTTON, self.onCheck)
self.attach = wx.Button(self.panel, -1, _(u"Attach audio"), size=wx.DefaultSize)
self.attach.Bind(wx.EVT_BUTTON, self.onAttach)
self.shortenButton = wx.Button(self.panel, -1, _(u"Shorten URL"), size=wx.DefaultSize)
self.shortenButton.Bind(wx.EVT_BUTTON, self.onShorten)
self.unshortenButton = wx.Button(self.panel, -1, _(u"Expand URL"), size=wx.DefaultSize)
self.unshortenButton.Bind(wx.EVT_BUTTON, self.onUnshorten)
self.shortenButton.Disable()
self.unshortenButton.Disable()
self.translateButton = wx.Button(self.panel, -1, _(u"Translate message"), size=wx.DefaultSize)
self.translateButton.Bind(wx.EVT_BUTTON, self.onTranslate)
self.okButton = wx.Button(self.panel, wx.ID_OK, _(u"Send"), size=wx.DefaultSize)
self.okButton.Bind(wx.EVT_BUTTON, self.onSend)
self.okButton.SetDefault()
cancelButton = wx.Button(self.panel, wx.ID_CANCEL, _(u"Close"), size=wx.DefaultSize)
cancelButton.Bind(wx.EVT_BUTTON, self.onCancel)
self.buttonsBox1 = wx.BoxSizer(wx.HORIZONTAL)
self.buttonsBox1.Add(self.upload_image, 0, wx.ALL, 5)
if platform.system() != "Darwin":
self.buttonsBox1.Add(self.spellcheck, 0, wx.ALL, 5)
self.buttonsBox1.Add(self.attach, 0, wx.ALL, 5)
self.mainBox.Add(self.buttonsBox1, 0, wx.ALL, 5)
self.buttonsBox2 = wx.BoxSizer(wx.HORIZONTAL)
self.buttonsBox2.Add(self.shortenButton, 0, wx.ALL, 5)
self.buttonsBox2.Add(self.unshortenButton, 0, wx.ALL, 5)
self.buttonsBox2.Add(self.translateButton, 0, wx.ALL, 5)
self.mainBox.Add(self.buttonsBox2, 0, wx.ALL, 5)
self.ok_cancelSizer = wx.BoxSizer(wx.HORIZONTAL)
self.ok_cancelSizer.Add(self.okButton, 0, wx.ALL, 5)
self.ok_cancelSizer.Add(cancelButton, 0, wx.ALL, 5)
self.mainBox.Add(self.ok_cancelSizer)
selectId = wx.NewId()
self.Bind(wx.EVT_MENU, self.onSelect, id=selectId)
self.accel_tbl = wx.AcceleratorTable([
(wx.ACCEL_CTRL, ord('A'), selectId),
])
self.SetAcceleratorTable(self.accel_tbl)
self.panel.SetSizer(self.mainBox)
def __init__(self, message, title, text, parent):
super(tweet, self).__init__(message, title, text, parent)
self.image = None
self.createControls(message, title, text)
self.onTimer(wx.EVT_CHAR_HOOK)
self.SetClientSize(self.mainBox.CalcMin())
def onUpload_image(self, ev):
if self.upload_image.GetLabel() == _(u"Discard image"):
self.image = None
del self.file
output.speak(_(u"Discarded"))
self.upload_image.SetLabel(_(u"Upload a picture"))
else:
openFileDialog = wx.FileDialog(self, _(u"Select the picture to be uploaded"), "", "", _("Image files (*.png, *.jpg, *.gif)|*.png; *.jpg; *.gif"), wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)
if openFileDialog.ShowModal() == wx.ID_CANCEL:
return
self.file = open(openFileDialog.GetPath(), "rb")
self.image = True
self.upload_image.SetLabel(_(u"Discard image"))
ev.Skip()
def onSend(self, ev):
self.EndModal(wx.ID_OK)
class retweet(tweet):
def __init__(self, message, title, text, parent):
super(retweet, self).__init__(message, title, text, parent)
# self.createControls(message, title, text)
self.in_reply_to = parent.db.settings[parent.name_buffer][parent.list.get_selected()]["id"]
self.text.SetInsertionPoint(0)
def onSend(self, ev):
self.EndModal(wx.ID_OK)
class dm(textLimited):
def createControls(self, message, title, text):
self.mainBox = wx.BoxSizer(wx.VERTICAL)
if self.parent.name_buffer == "followers" or self.parent.name_buffer == "friends":
list = [self.parent.db.settings[self.parent.name_buffer][self.parent.list.get_selected()]["screen_name"]]
else:
list =twitter.utils.get_all_users(self.parent.db.settings[self.parent.name_buffer][self.parent.list.get_selected()], self.parent.db)
label = wx.StaticText(self.panel, -1, _(u"Recipient"))
self.cb = wx.ComboBox(self.panel, -1, choices=list, value=list[0], size=wx.DefaultSize)
self.createTextArea(message, text)
self.mainBox.Add(self.cb, 0, wx.ALL, 5)
self.mainBox.Add(self.textBox, 0, wx.ALL, 5)
if platform.system() != "Darwin":
self.spellcheck = wx.Button(self.panel, -1, _("Spelling correction"), size=wx.DefaultSize)
self.spellcheck.Bind(wx.EVT_BUTTON, self.onCheck)
self.attach = wx.Button(self.panel, -1, _(u"Attach audio"), size=wx.DefaultSize)
self.attach.Bind(wx.EVT_BUTTON, self.onAttach)
self.shortenButton = wx.Button(self.panel, -1, _(u"Shorten URL"), size=wx.DefaultSize)
self.shortenButton.Bind(wx.EVT_BUTTON, self.onShorten)
self.unshortenButton = wx.Button(self.panel, -1, _(u"Expand URL"), size=wx.DefaultSize)
self.unshortenButton.Bind(wx.EVT_BUTTON, self.onUnshorten)
self.shortenButton.Disable()
self.unshortenButton.Disable()
self.translateButton = wx.Button(self.panel, -1, _(u"Translate message"), size=wx.DefaultSize)
self.translateButton.Bind(wx.EVT_BUTTON, self.onTranslate)
self.okButton = wx.Button(self.panel, wx.ID_OK, _(u"Send"), size=wx.DefaultSize)
self.okButton.Bind(wx.EVT_BUTTON, self.onSend)
self.okButton.SetDefault()
cancelButton = wx.Button(self.panel, wx.ID_CANCEL, _(u"Close"), size=wx.DefaultSize)
cancelButton.Bind(wx.EVT_BUTTON, self.onCancel)
self.buttonsBox = wx.BoxSizer(wx.HORIZONTAL)
if platform.system() != "Darwin":
self.buttonsBox.Add(self.spellcheck, 0, wx.ALL, 5)
self.buttonsBox.Add(self.attach, 0, wx.ALL, 5)
self.mainBox.Add(self.buttonsBox, 0, wx.ALL, 5)
self.buttonsBox1 = wx.BoxSizer(wx.HORIZONTAL)
self.buttonsBox1.Add(self.shortenButton, 0, wx.ALL, 5)
self.buttonsBox1.Add(self.unshortenButton, 0, wx.ALL, 5)
self.buttonsBox1.Add(self.translateButton, 0, wx.ALL, 5)
self.mainBox.Add(self.buttonsBox1, 0, wx.ALL, 5)
self.buttonsBox3 = wx.BoxSizer(wx.HORIZONTAL)
self.buttonsBox3.Add(self.okButton, 0, wx.ALL, 5)
self.buttonsBox3.Add(cancelButton, 0, wx.ALL, 5)
self.mainBox.Add(self.buttonsBox3, 0, wx.ALL, 5)
self.panel.SetSizer(self.mainBox)
def __init__(self, message, title, text, parent):
super(dm, self).__init__(message, title, text, parent)
self.parent = parent
self.image = None
self.createControls(message, title, text)
self.onTimer(wx.EVT_CHAR_HOOK)
self.SetClientSize(self.mainBox.CalcMin())
def onSend(self, ev):
self.EndModal(wx.ID_OK)
class reply(tweet):
def __init__(self, message, title, text, parent):
super(reply, self).__init__(message, title, text, parent)
self.in_reply_to = parent.db.settings[parent.name_buffer][parent.list.get_selected()]["id"]
self.text.SetInsertionPoint(len(self.text.GetValue()))
self.mentionAll = wx.Button(self, -1, _(u"Mention to all"), size=wx.DefaultSize)
self.mentionAll.Disable()
self.mentionAll.Bind(wx.EVT_BUTTON, self.mentionAllUsers)
self.buttonsBox1.Add(self.mentionAll, 0, wx.ALL, 5)
self.buttonsBox1.Layout()
self.mainBox.Layout()
self.check_if_users()
self.SetClientSize(self.mainBox.CalcMin())
def check_if_users(self):
try:
if len(self.parent.db.settings[self.parent.name_buffer][self.parent.list.get_selected()]["entities"]["user_mentions"]) > 0:
self.mentionAll.Enable()
except KeyError:
pass
def mentionAllUsers(self, ev):
self.text.SetValue(self.text.GetValue()+twitter.utils.get_all_mentioned(self.parent.db.settings[self.parent.name_buffer][self.parent.list.get_selected()], self.parent.db))
self.text.SetInsertionPoint(len(self.text.GetValue()))
self.text.SetFocus()
def onSend(self, ev):
self.EndModal(wx.ID_OK)
class viewTweet(wx.Dialog):
def __init__(self, tweet):
super(viewTweet, self).__init__(None, size=(850,850))
self.SetTitle(_(u"Tweet - %i characters ") % (len(tweet)))
panel = wx.Panel(self)
label = wx.StaticText(panel, -1, _(u"Tweet"))
self.text = wx.TextCtrl(panel, -1, tweet, style=wx.TE_READONLY|wx.TE_MULTILINE, size=(250, 180))
dc = wx.WindowDC(self.text)
dc.SetFont(self.text.GetFont())
(x, y, z) = dc.GetMultiLineTextExtent("0"*140)
self.text.SetSize((x, y))
self.text.SetFocus()
textBox = wx.BoxSizer(wx.HORIZONTAL)
textBox.Add(label, 0, wx.ALL, 5)
textBox.Add(self.text, 1, wx.EXPAND, 5)
mainBox = wx.BoxSizer(wx.VERTICAL)
mainBox.Add(textBox, 0, wx.ALL, 5)
if platform.system() != "Darwin":
spellcheck = wx.Button(panel, -1, _("Spelling correction"), size=wx.DefaultSize)
spellcheck.Bind(wx.EVT_BUTTON, self.onCheck)
self.unshortenButton = wx.Button(panel, -1, _(u"Expand URL"), size=wx.DefaultSize)
self.unshortenButton.Bind(wx.EVT_BUTTON, self.onUnshorten)
self.unshortenButton.Disable()
translateButton = wx.Button(panel, -1, _(u"Translate message"), size=wx.DefaultSize)
translateButton.Bind(wx.EVT_BUTTON, self.onTranslate)
cancelButton = wx.Button(panel, wx.ID_CANCEL, _(u"Close"), size=wx.DefaultSize)
cancelButton.SetDefault()
buttonsBox = wx.BoxSizer(wx.HORIZONTAL)
if platform.system() != "Darwin":
buttonsBox.Add(spellcheck, 0, wx.ALL, 5)
buttonsBox.Add(self.unshortenButton, 0, wx.ALL, 5)
buttonsBox.Add(translateButton, 0, wx.ALL, 5)
buttonsBox.Add(cancelButton, 0, wx.ALL, 5)
mainBox.Add(buttonsBox, 0, wx.ALL, 5)
selectId = wx.NewId()
self.Bind(wx.EVT_MENU, self.onSelect, id=selectId)
self.accel_tbl = wx.AcceleratorTable([
(wx.ACCEL_CTRL, ord('A'), selectId),
])
self.SetAcceleratorTable(self.accel_tbl)
panel.SetSizer(mainBox)
self.check_urls()
self.SetClientSize(mainBox.CalcMin())
def check_urls(self):
if len(twitter.utils.find_urls_in_text(self.text.GetValue())) > 0:
self.unshortenButton.Enable()
def onCheck(self, ev):
if platform.system() != "Darwin": return
text = self.text.GetValue()
dlg = spellCheckerGUI.spellCheckerDialog(text, "")
if dlg.ShowModal() == wx.ID_OK:
self.text.ChangeValue(dlg.checker.get_text())
dlg.Destroy()
def onTranslate(self, ev):
dlg = translator.gui.translateDialog()
selection = dlg.ShowModal()
if selection != wx.ID_CANCEL:
text_to_translate = self.text.GetValue().encode("utf-8")
source = [x[0] for x in translator.available_languages()][dlg.source_lang.GetSelection()]
dest = [x[0] for x in translator.available_languages()][dlg.dest_lang.GetSelection()]
t = translator.translator.Translator()
t.from_lang = source
t.to_lang = dest
msg = t.translate(text_to_translate)
self.text.ChangeValue(msg)
output.speak(_(u"Translated"))
self.text.SetFocus()
else:
return
dlg.Destroy()
def onSelect(self, ev):
self.text.SelectAll()
def onUnshorten(self, ev):
urls = twitter.utils.find_urls_in_text(self.text.GetValue())
if len(urls) == 0:
output.speak(_(u"There's no URL to be expanded"))
elif len(urls) == 1:
self.text.SetValue(self.text.GetValue().replace(urls[0], url_shortener.unshorten(urls[0])))
output.speak(_(u"URL expanded"))
elif len(urls) > 1:
urlList.unshorten(urls, self).ShowModal()
self.text.SetFocus()

View File

@ -1,83 +0,0 @@
# -*- coding: utf-8 -*-
############################################################
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################
import wx, twitter, config, gui.dialogs, sound, webbrowser
class showUserProfile(wx.Dialog):
def __init__(self, twitter, screen_name):
self.twitter = twitter
self.screen_name = screen_name
wx.Dialog.__init__(self, None, -1)
self.SetTitle(_(u"Information for %s") % (screen_name))
panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
self.get_data()
static = wx.StaticText(panel, -1, _(u"Details"))
sizer.Add(static, 0, wx.ALL, 5)
text = wx.TextCtrl(panel, -1, style=wx.TE_MULTILINE|wx.TE_READONLY)
# dc = wx.WindowDC(text)
# dc.SetFont(text.GetFont())
# (x, y, z) = dc.GetMultiLineTextExtent("0"*10000)
# text.SetSize((x, y))
text.SetFocus()
sizer.Add(text, 0, wx.ALL|wx.EXPAND, 5)
self.url = wx.Button(panel, -1, _(u"Go to URL"), size=wx.DefaultSize)
self.url.Bind(wx.EVT_BUTTON, self.onUrl)
self.url.Disable()
close = wx.Button(panel, wx.ID_CANCEL, _(u"Close"))
close.Bind(wx.EVT_BUTTON, self.onClose)
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
btnSizer.Add(self.url, 0, wx.ALL, 5)
btnSizer.Add(close, 0, wx.ALL, 5)
sizer.Add(btnSizer, 0, wx.ALL, 5)
text.ChangeValue(self.compose_string())
text.SetSize(text.GetBestSize())
panel.SetSizer(sizer)
self.SetClientSize(sizer.CalcMin())
def onUrl(self, ev):
webbrowser.open(self.data["url"])
def onClose(self, ev):
self.Destroy()
def get_data(self):
try:
self.data = self.twitter.twitter.show_user(screen_name=self.screen_name)
except:
wx.MessageDialog(self, _(u"This user does not exist on Twitter"), _(u"Error"), wx.ICON_ERROR).ShowModal()
self.EndModal()
def compose_string(self):
string = u""
string = string + _(u"Username: @%s\n") % (self.data["screen_name"])
string = string + _(u"Name: %s\n") % (self.data["name"])
if self.data["location"] != "":
string = string + _(u"Location: %s\n") % (self.data["location"])
if self.data["url"] != None:
string = string+ _(u"URL: %s\n") % (self.data["url"])
self.url.Enable()
if self.data["description"] != "":
string = string+ _(u"Bio: %s\n") % (self.data["description"])
if self.data["protected"] == True: protected = _(u"Yes")
else: protected = _(u"No")
string = string+ _(u"Protected: %s\n") % (protected)
string = string+_(u"Followers: %s\n Friends: %s\n") % (self.data["followers_count"], self.data["friends_count"])
string = string+ _(u"Tweets: %s\n") % (self.data["statuses_count"])
string = string+ _(u"Favourites: %s") % (self.data["favourites_count"])
return string

View File

@ -1,48 +0,0 @@
# -*- coding: utf-8 -*-
############################################################
# Copyright (c) 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################
import wx
class trendingTopicsDialog(wx.Dialog):
def __init__(self):
super(searchDialog, self).__init__(None, -1)
panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
self.SetTitle(_(u"Search on Twitter"))
label = wx.StaticText(panel, -1, _(u"Search"))
self.term = wx.TextCtrl(panel, -1,)
dc = wx.WindowDC(self.term)
dc.SetFont(self.term.GetFont())
self.term.SetSize(dc.GetTextExtent("0"*40))
sizer.Add(label, 0, wx.ALL, 5)
sizer.Add(self.term, 0, wx.ALL, 5)
self.tweets = wx.RadioButton(panel, -1, _(u"Tweets"), style=wx.RB_GROUP)
self.users = wx.RadioButton(panel, -1, _(u"Users"))
radioSizer = wx.BoxSizer(wx.HORIZONTAL)
radioSizer.Add(self.tweets, 0, wx.ALL, 5)
radioSizer.Add(self.users, 0, wx.ALL, 5)
sizer.Add(radioSizer, 0, wx.ALL, 5)
ok = wx.Button(panel, wx.ID_OK, _(u"OK"))
ok.SetDefault()
cancel = wx.Button(panel, wx.ID_CANCEL, _(u"Close"))
btnsizer = wx.BoxSizer()
btnsizer.Add(ok, 0, wx.ALL, 5)
btnsizer.Add(cancel, 0, wx.ALL, 5)
sizer.Add(btnsizer, 0, wx.ALL, 5)
panel.SetSizer(sizer)
self.SetClientSize(sizer.CalcMin())

View File

@ -1,71 +0,0 @@
# -*- coding: utf-8 -*-
############################################################
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################
import wx
import webbrowser
import url_shortener
class urlList(wx.Dialog):
def __init__(self, urls):
self.urls = urls
super(urlList, self).__init__(parent=None, title=_(u"Select an URL"))
panel = wx.Panel(self)
# label = wx.StaticText(panel, -1, _(u"Select a URL"))
self.lista = wx.ListBox(panel, -1)
self.lista.SetFocus()
self.populate_list()
self.lista.SetSelection(0)
self.lista.SetSize(self.lista.GetBestSize())
sizer = wx.BoxSizer(wx.VERTICAL)
# sizer.Add(label, 0, wx.ALL, 5)
sizer.Add(self.lista, 0, wx.ALL, 5)
goBtn = wx.Button(panel, wx.ID_OK)
goBtn.SetDefault()
goBtn.Bind(wx.EVT_BUTTON, self.onGo)
cancelBtn = wx.Button(panel, wx.ID_CANCEL)
btnSizer = wx.BoxSizer()
btnSizer.Add(goBtn, 0, wx.ALL, 5)
btnSizer.Add(cancelBtn, 0, wx.ALL, 5)
sizer.Add(btnSizer, 0, wx.ALL, 5)
panel.SetSizer(sizer)
self.SetClientSize(sizer.CalcMin())
def onGo(self, ev):
webbrowser.open(self.lista.GetStringSelection())
self.Destroy()
def populate_list(self):
for i in self.urls:
self.lista.Append(i)
class shorten(urlList):
def __init__(self, urls, parent):
urlList.__init__(self, urls)
self.parent = parent
def onGo(self, ev):
self.parent.text.SetValue(self.parent.text.GetValue().replace(self.lista.GetStringSelection(), url_shortener.shorten(self.lista.GetStringSelection())))
self.Destroy()
class unshorten(shorten):
def __init__(self, urls, parent):
shorten.__init__(self, urls, parent)
def onGo(self, ev):
self.parent.text.SetValue(self.parent.text.GetValue().replace(self.lista.GetStringSelection(), url_shortener.unshorten(self.lista.GetStringSelection())))
self.Destroy()

View File

@ -1,49 +0,0 @@
# -*- coding: utf-8 -*-
############################################################
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################
import wx, twitter, gui.dialogs, sound, config
from mysc.repeating_timer import RepeatingTimer
class selectUserDialog(wx.Dialog):
def __init__(self, parent, title):
self.parent = parent
wx.Dialog.__init__(self, None, -1)
panel = wx.Panel(self)
userSizer = wx.BoxSizer()
self.SetTitle(title)
if self.parent.nb.GetCurrentPage().name_buffer == "followers" or self.parent.nb.GetCurrentPage().name_buffer == "friends":
list = [self.parent.db.settings[self.parent.nb.GetCurrentPage().name_buffer][self.parent.nb.GetCurrentPage().list.get_selected()]["screen_name"]]
else:
try: list =twitter.utils.get_all_users(self.parent.db.settings[self.parent.nb.GetCurrentPage().name_buffer][self.parent.nb.GetCurrentPage().list.get_selected()], self.parent.db)
except KeyError: list = [self.parent.db.settings[self.parent.nb.GetCurrentPage().name_buffer][self.parent.nb.GetCurrentPage().list.get_selected()]["screen_name"]]
self.cb = wx.ComboBox(panel, -1, choices=list, value=list[0], size=wx.DefaultSize)
self.cb.SetFocus()
userSizer.Add(wx.StaticText(panel, -1, _(u"User")), 0, wx.ALL, 5)
userSizer.Add(self.cb)
sizer = wx.BoxSizer(wx.VERTICAL)
ok = wx.Button(panel, wx.ID_OK, _(u"OK"))
ok.SetDefault()
# ok.Bind(wx.EVT_BUTTON, self.onok)
cancel = wx.Button(panel, wx.ID_CANCEL, _(u"Close"))
btnsizer = wx.BoxSizer()
btnsizer.Add(ok, 0, wx.ALL, 5)
btnsizer.Add(cancel, 0, wx.ALL, 5)
sizer.Add(userSizer, 0, wx.ALL, 5)
sizer.Add(btnsizer, 0, wx.ALL, 5)
panel.SetSizer(sizer)
self.SetClientSize(sizer.CalcMin())

View File

@ -1,965 +0,0 @@
# -*- coding: utf-8 -*-
############################################################
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################
import wx
import dialogs
import buffers
import config
import twitter
import db
import webbrowser
import sound
import updater
import application
import os
import logging as original_logger
import output
import platform
import urllib2
import sysTrayIcon
import languageHandler
from sessionmanager import manager
from mysc import event
from mysc.thread_utils import call_threaded
from twython import TwythonError
from urllib2 import URLError
from mysc.repeating_timer import RepeatingTimer
from mysc import localization
if platform.system() == "Windows" or platform.system() == "Linux":
from keyboard_handler.wx_handler import WXKeyboardHandler
from extra import SoundsTutorial
from keystrokeEditor import gui as keystrokeEditorGUI
log = original_logger.getLogger("gui.main")
class mainFrame(wx.Frame):
""" Main class of the Frame. This is the Main Window."""
### MENU
def makeMenus(self):
""" Creates, bind and returns the menu bar for the application. Also in this function, the accel table is created."""
menuBar = wx.MenuBar()
# Application menu
app = wx.Menu()
updateProfile = app.Append(wx.NewId(), _(u"&Update profile"))
self.Bind(wx.EVT_MENU, self.update_profile, updateProfile)
show_hide = app.Append(wx.NewId(), _(u"&Hide window"))
self.Bind(wx.EVT_MENU, self.show_hide, show_hide)
search = app.Append(wx.NewId(), _(u"&Search"))
self.Bind(wx.EVT_MENU, self.search, search)
lists = app.Append(wx.NewId(), _(u"&Lists manager"))
self.Bind(wx.EVT_MENU, self.list_manager, lists)
sounds_tutorial = app.Append(wx.NewId(), _(u"Sounds &tutorial"))
self.Bind(wx.EVT_MENU, self.learn_sounds, sounds_tutorial)
keystroke_editor = app.Append(wx.NewId(), _(u"&Edit keystrokes"))
self.Bind(wx.EVT_MENU, self.edit_keystrokes, keystroke_editor)
prefs = app.Append(wx.ID_PREFERENCES, _(u"&Preferences"))
self.Bind(wx.EVT_MENU, self.preferences, prefs)
close = app.Append(wx.ID_EXIT, _(u"E&xit"))
self.Bind(wx.EVT_MENU, self.close, close)
# Tweet menu
tweet = wx.Menu()
compose = tweet.Append(wx.NewId(), _(u"&Tweet"))
self.Bind(wx.EVT_MENU, self.compose, compose)
response = tweet.Append(wx.NewId(), _(u"Re&ply"))
self.Bind(wx.EVT_MENU, self.reply, response)
retweet = tweet.Append(wx.NewId(), _(u"&Retweet"))
self.Bind(wx.EVT_MENU, self.retweet, retweet)
fav = tweet.Append(wx.NewId(), _(u"Add to &favourites"))
self.Bind(wx.EVT_MENU, self.fav, fav)
unfav = tweet.Append(wx.NewId(), _(u"Remove from favo&urites"))
self.Bind(wx.EVT_MENU, self.unfav, unfav)
view = tweet.Append(wx.NewId(), _(u"&Show tweet"))
self.Bind(wx.EVT_MENU, self.view, view)
delete = tweet.Append(wx.NewId(), _(u"&Delete"))
self.Bind(wx.EVT_MENU, self.delete, delete)
# User menu
user = wx.Menu()
follow = user.Append(wx.NewId(), _(u"&Follow"))
self.Bind(wx.EVT_MENU, self.onFollow, follow)
unfollow = user.Append(wx.NewId(), _(u"&Unfollow"))
self.Bind(wx.EVT_MENU, self.onUnfollow, unfollow)
mute = user.Append(wx.NewId(), _(u"&Mute"))
self.Bind(wx.EVT_MENU, self.onMute, mute)
unmute = user.Append(wx.NewId(), _(u"U&nmute"))
self.Bind(wx.EVT_MENU, self.onUnmute, unmute)
report = user.Append(wx.NewId(), _(u"&Report as spam"))
self.Bind(wx.EVT_MENU, self.onReport, report)
block = user.Append(wx.NewId(), _(u"&Block"))
self.Bind(wx.EVT_MENU, self.onBlock, block)
unblock = user.Append(wx.NewId(), _(u"Unb&lock"))
self.Bind(wx.EVT_MENU, self.onUnblock, unblock)
dm = user.Append(wx.NewId(), _(u"Direct me&ssage"))
self.Bind(wx.EVT_MENU, self.dm, dm)
addToList = user.Append(wx.NewId(), _(u"&Add to list"))
self.Bind(wx.EVT_MENU, self.add_to_list, addToList)
removeFromList = user.Append(wx.NewId(), _(u"R&emove from list"))
self.Bind(wx.EVT_MENU, self.remove_from_list, removeFromList)
viewLists = user.Append(wx.NewId(), _(u"&View lists"))
self.Bind(wx.EVT_MENU, self.view_user_lists, viewLists)
details = user.Append(wx.NewId(), _(u"Show user &profile"))
self.Bind(wx.EVT_MENU, self.details, details)
timeline = user.Append(wx.NewId(), _(u"&Timeline"))
self.Bind(wx.EVT_MENU, self.open_timeline, timeline)
favs = user.Append(wx.NewId(), _(u"V&iew favourites"))
self.Bind(wx.EVT_MENU, self.favs_timeline, favs)
# buffer menu
buffer = wx.Menu()
load_previous_items = buffer.Append(wx.NewId(), _(u"&Load previous items"))
self.Bind(wx.EVT_MENU, self.get_more_items, load_previous_items)
mute = buffer.Append(wx.NewId(), _(u"&Mute"))
self.Bind(wx.EVT_MENU, self.toggle_mute, mute)
autoread = buffer.Append(wx.NewId(), _(u"&Autoread tweets for this buffer"))
self.Bind(wx.EVT_MENU, self.toggle_autoread, autoread)
clear = buffer.Append(wx.NewId(), _(u"&Clear buffer"))
self.Bind(wx.EVT_MENU, self.clear_list, clear)
deleteTl = buffer.Append(wx.NewId(), _(u"&Remove buffer"))
self.Bind(wx.EVT_MENU, self.delete_buffer, deleteTl)
# Help Menu
help = wx.Menu()
doc = help.Append(-1, _(u"&Documentation"))
self.Bind(wx.EVT_MENU, self.onManual, doc)
changelog = help.Append(wx.NewId(), _(u"&What's new in this version?"))
self.Bind(wx.EVT_MENU, self.onChangelog, changelog)
check_for_updates = help.Append(wx.NewId(), _(u"&Check for updates"))
self.Bind(wx.EVT_MENU, self.onCheckForUpdates, check_for_updates)
reportError = help.Append(wx.NewId(), _(u"&Report an error"))
self.Bind(wx.EVT_MENU, self.onReportBug, reportError)
visit_website = help.Append(-1, _(u"TW Blue &website"))
self.Bind(wx.EVT_MENU, self.onVisit_website, visit_website)
about = help.Append(-1, _(u"About &TW Blue"))
self.Bind(wx.EVT_MENU, self.onAbout, about)
# Add all to the menu Bar
menuBar.Append(app, _(u"&Application"))
menuBar.Append(tweet, _(u"&Tweet"))
menuBar.Append(user, _(u"&User"))
menuBar.Append(buffer, _(u"&Buffer"))
menuBar.Append(help, _(u"&Help"))
downID = wx.NewId()
upID = wx.NewId()
leftID = wx.NewId()
rightID = wx.NewId()
if platform.system() == "Darwin":
self.Bind(wx.EVT_MENU, self.down, id=downID)
self.Bind(wx.EVT_MENU, self.up, id=upID)
self.Bind(wx.EVT_MENU, self.left, id=leftID)
self.Bind(wx.EVT_MENU, self.right, id=rightID)
# Creates the acceleration table.
self.accel_tbl = wx.AcceleratorTable([
(wx.ACCEL_CTRL, ord('N'), compose.GetId()),
(wx.ACCEL_CTRL, ord('R'), response.GetId()),
(wx.ACCEL_CTRL|wx.ACCEL_SHIFT, ord('R'), retweet.GetId()),
(wx.ACCEL_CTRL, ord('F'), fav.GetId()),
(wx.ACCEL_CTRL|wx.ACCEL_SHIFT, ord('F'), unfav.GetId()),
(wx.ACCEL_CTRL|wx.ACCEL_SHIFT, ord('V'), view.GetId()),
(wx.ACCEL_CTRL, ord('D'), dm.GetId()),
(wx.ACCEL_CTRL, ord('Q'), close.GetId()),
(wx.ACCEL_CTRL, ord('S'), follow.GetId()),
(wx.ACCEL_CTRL|wx.ACCEL_SHIFT, ord('S'), unfollow.GetId()),
(wx.ACCEL_CTRL, ord('K'), block.GetId()),
(wx.ACCEL_CTRL|wx.ACCEL_SHIFT, ord('K'), report.GetId()),
(wx.ACCEL_CTRL, ord('I'), timeline.GetId()),
(wx.ACCEL_CTRL|wx.ACCEL_SHIFT, ord('I'), deleteTl.GetId()),
(wx.ACCEL_CTRL, ord('M'), show_hide.GetId()),
(wx.ACCEL_CTRL, ord('P'), updateProfile.GetId()),
(wx.ACCEL_CTRL, wx.WXK_DOWN, downID),
(wx.ACCEL_CTRL, wx.WXK_UP, upID),
(wx.ACCEL_CTRL, wx.WXK_LEFT, leftID),
(wx.ACCEL_CTRL, wx.WXK_RIGHT, rightID),
])
self.SetAcceleratorTable(self.accel_tbl)
return menuBar
### MAIN
def __init__(self, authorised=True, user_key=None, user_secret=None):
""" Main function of this class."""
if authorised == False:
self.user_key = user_key
self.user_secret = user_secret
else:
self.user_key = self.user_secret = None
log.debug("Loading temporal database...")
self.db = db.db()
# Gets the twitter object for future calls to the twitter Rest API.
log.debug("Getting Twitter's Rest API...")
self.twitter = twitter.twitter.twitter()
super(mainFrame, self).__init__(None, -1, "TW Blue", size=(1600, 1600))
self.Bind(wx.EVT_QUERY_END_SESSION, self.exit)
self.Bind(wx.EVT_END_SESSION, self.exit)
log.debug(u"Creating the system tray icon... ")
sysTray=sysTrayIcon.SysTrayIcon(self)
panel = wx.Panel(self)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.SetTitle("TW Blue")
try:
updater.update_manager.check_for_update()
except:
pass
self.SetMenuBar(self.makeMenus())
self.setup_twitter(panel)
def logging_in_twblue(self, panel):
log.debug("Retrieving username...")
twitter.starting.start_user_info(config=self.db, twitter=self.twitter)
config.main["twitter"]["user_name"] = self.db.settings["user_name"]
self.SetTitle(u"@%s. - TW Blue" % (self.db.settings["user_name"]))
self.nb = wx.Treebook(panel, -1)
self.Bind(wx.EVT_CLOSE, self.close)
self.nb.Bind(wx.EVT_TREEBOOK_PAGE_CHANGED, self.onPageChanged)
# Gets the tabs for home, mentions, send and direct messages.
log.debug("Creating buffers...")
self.db.settings["buffers"] = []
account = buffers.accountPanel(self.nb)
self.nb.AddPage(account, self.db.settings["user_name"])
self.db.settings["buffers"].append(self.db.settings["user_name"])
account_index = self.db.settings["buffers"].index(self.db.settings["user_name"])
home = buffers.basePanel(self.nb, self, "home_timeline", self.twitter.twitter.get_home_timeline, sound="tweet_received.ogg")
self.nb.InsertSubPage(account_index, home, _(u"Home"))
self.db.settings["buffers"].append("home_timeline")
self.nb.SetSelection(1)
self.nb.GetPage(1).list.list.SetFocus()
mentionsP = buffers.basePanel(self.nb, self, "mentions", self.twitter.twitter.get_mentions_timeline, sound="mention_received.ogg")
self.nb.InsertSubPage(account_index, mentionsP, _("Mentions"))
self.db.settings["buffers"].append("mentions")
dms = buffers.dmPanel(self.nb, self, "direct_messages", self.twitter.twitter.get_direct_messages, sound="dm_received.ogg")
self.nb.InsertSubPage(account_index, dms, _(u"Direct messages"))
self.db.settings["buffers"].append("direct_messages")
sent = buffers.basePanel(self.nb, self, "sent", self.twitter.twitter.get_user_timeline, argumento=self.db.settings["user_name"])
self.nb.InsertSubPage(account_index, sent, _(u"Sent"))
self.db.settings["buffers"].append("sent")
# If the user has enabled favs from config.
if config.main["other_buffers"]["show_favourites"] == True:
log.debug("Getting Favorited tweets...")
favs = buffers.basePanel(self.nb, self, "favs", self.twitter.twitter.get_favorites)
self.nb.InsertSubPage(account_index, favs, _(u"Favourites"))
self.db.settings["buffers"].append("favs")
# If followers are enabled from config.
if config.main["other_buffers"]["show_followers"] == True:
log.debug("Getting followers...")
followers = buffers.peoplePanel(self.nb, self, "followers", self.twitter.twitter.get_followers_list, argumento=self.db.settings["user_name"], sound="update_followers.ogg")
self.nb.InsertSubPage(account_index, followers, _(u"Followers"))
self.db.settings["buffers"].append("followers")
# Same here but for friends.
if config.main["other_buffers"]["show_friends"] == True:
log.debug("Getting friends...")
friends = buffers.peoplePanel(self.nb, self, "friends", self.twitter.twitter.get_friends_list, argumento=self.db.settings["user_name"])
self.nb.InsertSubPage(account_index, friends, _(u"Friends"))
self.db.settings["buffers"].append("friends")
if config.main["other_buffers"]["show_blocks"] == True:
blocked = buffers.peoplePanel(self.nb, self, "blocks", self.twitter.twitter.list_blocks)
self.nb.InsertSubPage(account_index, blocked, _(u"Blocked users"))
self.db.settings["buffers"].append("blocks")
if config.main["other_buffers"]["show_muted_users"] == True:
muteds = buffers.peoplePanel(self.nb, self, "muteds", self.twitter.twitter.get_muted_users_list)
self.nb.InsertSubPage(account_index, muteds, _(u"Muted users"))
self.db.settings["buffers"].append("muteds")
if config.main["other_buffers"]["show_events"] == True:
evt = buffers.eventsPanel(self.nb, self, sound="new_event.ogg")
self.nb.InsertSubPage(account_index, evt, _(u"Events"))
self.db.settings["buffers"].append("events")
searches = buffers.emptyPanel(self.nb)
self.nb.InsertSubPage(account_index, searches, _(u"Searches"))
self.db.settings["buffers"].append("searches")
for i in config.main["other_buffers"]["tweet_searches"]:
self.nb.InsertSubPage(self.db.settings["buffers"].index("searches"), buffers.searchPanel(self.nb, self, "%s-search" % (i,), q=i, count=100), _(u"Search for %s" % (i,)))
self.db.settings["buffers"].append("%s-search" % (i,))
timelines = buffers.emptyPanel(self.nb)
self.nb.InsertSubPage(account_index, timelines, _(u"Timelines"))
self.db.settings["buffers"].append("timelines")
for i in config.main["other_buffers"]["timelines"]:
self.nb.InsertSubPage(self.db.settings["buffers"].index("timelines"), buffers.basePanel(self.nb, self, i, self.twitter.twitter.get_user_timeline, argumento=i, timeline=True, sound="tweet_timeline.ogg"), _(u"Timeline for %s") % i)
self.db.settings["buffers"].append(i)
lists = buffers.emptyPanel(self.nb)
self.nb.InsertSubPage(account_index, lists, _(u"Lists"))
self.db.settings["buffers"].append("lists")
for i in config.main["other_buffers"]["lists"]:
self.nb.InsertSubPage(self.db.settings["buffers"].index("lists"), buffers.listPanel(self.nb, self, i+"-list", argumento=twitter.utils.find_list(i, self.db.settings["lists"])), _(u"List for %s") % i)
self.db.settings["buffers"].append(i+"-list")
## favourites timelines
favs_timelines = buffers.emptyPanel(self.nb)
self.nb.InsertSubPage(account_index, favs_timelines, _(U"Favourites timelines"))
self.db.settings["buffers"].append("favourites_timelines")
for i in config.main["other_buffers"]["favourites_timelines"]:
self.nb.InsertSubPage(self.db.settings["buffers"].index("favourites_timelines"), buffers.favsPanel(self.nb, self, i+"favs", argumento=i, sound="favourites_timeline_updated.ogg"), _(u"Favourites for %s") % i,)
self.db.settings["buffers"].append(i+"favs")
self.fav_stream = RepeatingTimer(180, self.get_fav_buffers)
self.fav_stream.start()
self.sizer.Add(self.nb, 0, wx.ALL, 5)
panel.SetSizer(self.sizer)
self.SetClientSize(self.sizer.CalcMin())
self.Bind(event.MyEVT_STARTED, self.onInit)
self.Bind(event.EVT_RESULT, self.onMemberAdded)
call_threaded(self.init, run_streams=True)
def init(self, run_streams=False):
""" Calls the start_stream function for each stream tab."""
deleted = 0
for i in range(0, self.nb.GetPageCount()):
if self.nb.GetPage(i).type == "account" or self.nb.GetPage(i).type == "empty": continue
if i == self.nb.GetPageCount() and deleted > 0:
i = i-1
deleted = deleted-1
log.debug("Starting stream for %s..." % self.nb.GetPage(i).name_buffer)
info_event = event.infoEvent(event.EVT_STARTED, 1)
try:
if self.nb.GetPage(i).type == "search":
self.nb.GetPage(i).timer = RepeatingTimer(180, self.nb.GetPage(i).load_search)
self.nb.GetPage(i).timer.start()
num = self.nb.GetPage(i).start_streams()
info_event.SetItem(i, num)
wx.PostEvent(self, info_event)
except TwythonError as e:
continue
except UnicodeDecodeError: # This happens when there is a bad internet connection
continue
output.speak(_(u"Ready"))
if run_streams == True:
self.get_home()
self.get_tls()
self.check_streams = RepeatingTimer(config.main["general"]["time_to_check_streams"], self.check_stream_up)
self.check_streams.start()
# If all it's done, then play a nice sound saying that all it's OK.
sound.player.play("ready.ogg")
def remove_list(self, id):
for i in range(0, self.nb.GetPageCount()):
if self.nb.GetPage(i).type == "list":
if self.nb.GetPage(i).argumento == id:
pos = self.nb.GetCurrentPage().remove_invalid_buffer()
if pos != None:
self.nb.DeletePage(pos)
self.onMemberAdded()
def onMemberAdded(self, ev):
self.stream2.disconnect()
del self.stream2
self.get_tls()
def get_fav_buffers(self):
for i in config.main["other_buffers"]["favourites_timelines"]:
num = self.nb.GetPage(self.db.settings["buffers"].index(i+"favs")).start_streams()
if num > 0: output.speak(_(u"%s favourites from %s") % (nun, i))
def setup_twitter(self, panel):
""" Setting up the connection for twitter, or authenticate if the config file has valid credentials."""
try:
self.twitter.login(self.user_key, self.user_secret)
self.logging_in_twblue(panel)
log.info("Authorized in Twitter.")
del self.user_key; del self.user_secret
except:
dlg1 = wx.MessageDialog(panel, _(u"Connection error. Try again later."), _(u"Error!"), wx.ICON_ERROR)
dlg1.ShowModal()
self.Close(True)
def get_home(self):
""" Gets the home stream, that manages home timeline, mentions, direct messages and sent."""
try:
self.stream = twitter.buffers.stream.streamer(application.app_key, application.app_secret, config.main["twitter"]["user_key"], config.main["twitter"]["user_secret"], parent=self)
call_threaded(self.stream.user)
except:
self.stream.disconnect()
def start_lists(self):
for i in range(0, self.nb.GetPageCount()):
if self.nb.GetPage(i).type == "list": self.nb.GetPage(i).retrieve_ids()
def get_tls(self):
""" Setting the stream for individual user timelines."""
# try:
self.stream2 = twitter.buffers.indibidual.streamer(application.app_key, application.app_secret, config.main["twitter"]["user_key"], config.main["twitter"]["user_secret"], parent=self)
# The self.ids contains all IDS for the follow argument of the stream.
ids = ""
# If we have more than 0 items on a list, then.
for i in config.main["other_buffers"]["timelines"]:
ids = ids+self.db.settings[i][0]["user"]["id_str"]+", "
for i in range(0, self.nb.GetPageCount()):
if self.nb.GetPage(i).type == "list":
for z in self.nb.GetPage(i).users:
ids+= str(z)+", "
if ids != "":
# try:
call_threaded(self.stream2.statuses.filter, follow=ids)
# except:
# pass
# except:
# self.stream2.disconnect()
def check_stream_up(self):
try:
urllib2.urlopen("http://74.125.228.231", timeout=5)
except urllib2.URLError:
if self.stream.connected == True: self.stream.disconnect()
if hasattr(self, "stream2") and self.stream2.connected: self.stream2.disconnect()
if config.main["general"]["announce_stream_status"] == True: output.speak(_(u"Streams disconnected. TW Blue will try to reconnect in a minute."))
return
if self.stream.connected == False:
del self.stream
if config.main["general"]["announce_stream_status"] == True: output.speak(_(u"Reconnecting streams..."))
call_threaded(self.init)
self.get_home()
if hasattr(self, "stream2") and self.stream2.connected == False:
log.debug("Trying reconnects the timelines stream...")
del self.stream2
self.get_tls()
### Events
def edit_keystrokes(self, ev=None):
if hasattr(self, "keyboard_handler"):
dlg = keystrokeEditorGUI.keystrokeEditor(parent=self, keyboard_handler=self.keyboard_handler)
else:
dlg = keystrokeEditorGUI.keystrokeEditor(parent=self)
dlg.ShowModal()
dlg.Destroy()
def search(self, ev=None):
dlg = dialogs.search.searchDialog()
if dlg.ShowModal() == wx.ID_OK:
term = dlg.term.GetValue()
if dlg.tweets.GetValue() == True:
search =buffers.searchPanel(self.nb, self, "%s-search" % (term,), q=term, count=100)
self.nb.InsertSubPage(self.db.settings["buffers"].index("searches"), search, _(u"search for %s") % (term,))
self.db.settings["buffers"].append("%s-search" % (term,))
config.main["other_buffers"]["tweet_searches"].append(term)
elif dlg.users.GetValue() == True:
search =buffers.searchUsersPanel(self.nb, self, "%s_search" % (term,), q=term, count=20)
self.nb.InsertSubPage(self.db.settings["buffers"].index("searches"), search, _(u"search users for %s") % (term,))
self.db.settings["buffers"].append("%s_search" % (term,))
timer = RepeatingTimer(180, search.load_search)
timer.start()
num = search.start_streams()
search.put_items(num)
dlg.Destroy()
def learn_sounds(self, ev):
SoundsTutorial.gui.soundsTutorial().ShowModal()
def view_user_lists(self, ev=None):
userDlg = dialogs.utils.selectUserDialog(parent=self, title=_(u"Select the user"))
if userDlg.ShowModal() == wx.ID_OK:
user = userDlg.cb.GetValue()
else:
return
dlg = dialogs.lists.userListViewer(self, user)
dlg.ShowModal()
userDlg.Destroy()
dlg.Destroy()
def add_to_list(self, ev=None):
userDlg = dialogs.utils.selectUserDialog(parent=self, title=_(u"Select the user"))
if userDlg.ShowModal() == wx.ID_OK:
user = userDlg.cb.GetValue()
else:
return
dlg = dialogs.lists.addUserListDialog(self)
if dlg.ShowModal() == wx.ID_OK:
try:
list = self.twitter.twitter.add_list_member(list_id=self.db.settings["lists"][dlg.lista.get_selected()]["id"], screen_name=user)
older_list = twitter.utils.find_item(self.db.settings["lists"][dlg.lista.get_selected()]["id"], self.db.settings["lists"])
if list["mode"] == "private":
self.db.settings["lists"].pop(older_list)
self.db.settings["lists"].append(list)
except TwythonError as e:
output.speak("error %s: %s" % (e.error_code, e.msg))
userDlg.Destroy()
dlg.Destroy()
def remove_from_list(self, ev=None):
userDlg = dialogs.utils.selectUserDialog(parent=self, title=_(u"Select the user"))
if userDlg.ShowModal() == wx.ID_OK:
user = userDlg.cb.GetValue()
else:
return
dlg = dialogs.lists.removeUserListDialog(self)
if dlg.ShowModal() == wx.ID_OK:
try:
list = self.twitter.twitter.delete_list_member(list_id=self.db.settings["lists"][dlg.get_selected()]["id"], screen_name=user)
older_list = twitter.utils.find_item(self.db.settings["lists"][dlg.get_selected()]["id"], self.db.settings["lists"])
if list["mode"] == "private":
self.db.settings["lists"].pop(older_list)
self.db.settings["lists"].append(list)
except TwythonError as e:
output.speak("error %s: %s" % (e.error_code, e.msg))
userDlg.Destroy()
dlg.Destroy()
def list_manager(self, ev):
dlg = dialogs.lists.listViewer(self)
dlg.ShowModal()
self.stream2.disconnect()
del self.stream2
self.get_tls()
dlg.Destroy()
def onInit(self, ev):
if self.nb.GetPage(ev.GetItem()[0]).type != "search" or self.nb.GetPage(ev.GetItem()[0]).type != "favourites_timeline": self.nb.GetPage(ev.GetItem()[0]).put_items(ev.GetItem()[1])
def preferences(self, ev=None):
dlg = dialogs.configuration.configurationDialog(self)
dlg.ShowModal()
dlg.Destroy()
def update_profile(self, ev=None):
dialogs.update_profile.updateProfile(self).ShowModal()
def onManual(self, ev):
lang = localization.get("documentation")
os.chdir("documentation/%s" % (lang,))
webbrowser.open("manual.html")
os.chdir("../../")
def onChangelog(self, ev):
lang = localization.get("documentation")
os.chdir("documentation/%s" % (lang,))
webbrowser.open("changes.html")
os.chdir("../../")
def onVisit_website(self, ev):
webbrowser.open("http://twblue.com.mx")
def onReportBug(self, ev):
webbrowser.open("https://github.com/manuelcortez/TWBlue/issues")
# issueReporterGUI.reportBug(self.db.settings["user_name"]).ShowModal()
def onCheckForUpdates(self, ev):
updater.update_manager.check_for_update(msg=True)
def details(self, ev=None):
""" This function shows details for the selected user."""
dlg = dialogs.utils.selectUserDialog(parent=self, title=_(u"User details"))
if dlg.ShowModal() == wx.ID_OK:
dialogs.show_user.showUserProfile(self.twitter, dlg.cb.GetValue()).ShowModal()
dlg.Destroy()
def delete(self, ev=None):
""" Deleting a tweet or direct message."""
if self.nb.GetCurrentPage().name_buffer != "followers" and self.nb.GetCurrentPage() != "friends" and self.nb.GetCurrentPage().name_buffer != "events":
dlg = wx.MessageDialog(self, _(u"Do you really want to delete this message? It will be eliminated from Twitter as well."), _(u"Delete"), wx.ICON_QUESTION|wx.YES_NO)
if dlg.ShowModal() == wx.ID_YES:
self.nb.GetCurrentPage().destroy_status(wx.EVT_MENU)
else:
return
def onPageChanged(self, ev):
""" Announces the new title for the tab."""
if platform.system() == "Darwin":
output.speak(self.nb.GetPageText(self.nb.GetSelection())+",", True)
def skip_blank_pages(self, forward=True):
if self.nb.GetCurrentPage().type == "account" or self.nb.GetCurrentPage().type == "empty" and (self.showing == False or platform.system() == "Darwin"):
self.nb.AdvanceSelection(forward)
def close(self, ev=None):
if config.main["general"]["ask_at_exit"] == True:
dlg = wx.MessageDialog(self, _(u"Do you really want to close TW Blue?"), _(u"Exit"), wx.YES_NO|wx.ICON_QUESTION)
if dlg.ShowModal() == wx.ID_YES:
self.exit()
dlg.Destroy()
else:
output.speak(_(u"Exiting..."))
self.exit()
def exit(self, event=None):
config.main.write()
log.debug("Exiting...")
try:
self.check_streams.cancel()
except AttributeError:
pass
sound.player.cleaner.cancel()
try:
self.stream.disconnect()
log.debug("Stream disconnected.")
except:
pass
try:
self.stream2.disconnect()
log.debug(u"Timelines stream disconnected.")
except:
pass
wx.GetApp().ExitMainLoop()
def onFollow(self, ev=None):
""" Opens the follow dialog."""
dialogs.follow.follow(self.nb.GetCurrentPage(), "follow").ShowModal()
def onUnfollow(self, ev=None):
""" Opens the unfollow dialog."""
dialogs.follow.follow(self.nb.GetCurrentPage(), "unfollow").ShowModal()
def onMute(self, ev=None):
""" Opens the unfollow dialog."""
dialogs.follow.follow(self.nb.GetCurrentPage(), "mute").ShowModal()
def onUnmute(self, ev=None):
""" Opens the unfollow dialog."""
dialogs.follow.follow(self.nb.GetCurrentPage(), "unmute").ShowModal()
def onReport(self, ev=None):
""" Opens the report dialog, to report as spam to the specified user."""
dialogs.follow.follow(self.nb.GetCurrentPage(), "report").ShowModal()
def onBlock(self, ev=None):
""" Opens the "block" dialog, to block the user that you want."""
dialogs.follow.follow(self.nb.GetCurrentPage(), "block").ShowModal()
def onUnblock(self, ev=None):
""" Opens the "block" dialog, to block the user that you want."""
dialogs.follow.follow(self.nb.GetCurrentPage(), "unblock").ShowModal()
def action(self, ev=None):
dialogs.follow.follow(self.nb.GetCurrentPage()).ShowModal()
def compose(self, ev=None):
""" Opens the new tweet dialog."""
self.nb.GetCurrentPage().post_status(ev)
def reply(self, ev=None):
""" Opens the response dialog."""
self.nb.GetCurrentPage().onResponse(ev)
def dm(self, ev=None):
""" Opens the DM Dialog."""
# The direct_messages buffer has a method to post a diret messages while the other tabs does has not it.
if self.nb.GetCurrentPage().name_buffer == "direct_messages":
self.nb.GetCurrentPage().onResponse(ev)
elif self.nb.GetCurrentPage().name_buffer == "events": return
else:
# dialogs.message.dm(_(u"Direct message to %s ") % (self.db.settings[self.nb.GetCurrentPage().name_buffer][self.nb.GetCurrentPage().get_selected()]["user"]["screen_name"]), "", "", self.nb.GetCurrentPage()).ShowModal()
self.nb.GetCurrentPage().onDm(ev)
def retweet(self, ev=None):
if self.nb.GetCurrentPage().name_buffer != "direct_messages" and self.nb.GetCurrentPage().name_buffer != "followers" and self.nb.GetCurrentPage().name_buffer != "friends" and self.nb.GetCurrentPage().name_buffer != "events":
self.nb.GetCurrentPage().onRetweet(ev)
def view(self, ev=None):
tweet = self.nb.GetCurrentPage().get_message(dialog=True)
dialogs.message.viewTweet(tweet).ShowModal()
def fav(self, ev=None):
if self.nb.GetCurrentPage().name_buffer != "direct_messages" and self.nb.GetCurrentPage().name_buffer != "followers" and self.nb.GetCurrentPage().name_buffer != "friends":
try:
self.twitter.twitter.create_favorite(id=self.db.settings[self.nb.GetCurrentPage().name_buffer][self.nb.GetCurrentPage().list.get_selected()]["id"])
sound.player.play("favourite.ogg")
except TwythonError as e:
output.speak(_(u"Error while adding to favourites."), True)
sound.player.play("error.ogg")
def unfav(self, ev=None):
if self.nb.GetCurrentPage().name_buffer != "direct_messages" and self.nb.GetCurrentPage().name_buffer != "followers" and self.nb.GetCurrentPage().name_buffer != "friends":
try:
self.twitter.twitter.destroy_favorite(id=self.db.settings[self.nb.GetCurrentPage().name_buffer][self.nb.GetCurrentPage().list.get_selected()]["id"])
except TwythonError as e:
output.speak(_(u"Error while removing from favourites."), True)
sound.player.play("error.ogg")
def open_timeline(self, ev=None):
dlg = dialogs.utils.selectUserDialog(self, _(u"Individual timeline"))
if dlg.ShowModal() == wx.ID_OK:
user = twitter.utils.if_user_exists(self.twitter.twitter, dlg.cb.GetValue())
if user == None:
wx.MessageDialog(None, _(u"The user does not exist"), _(u"Error"), wx.ICON_ERROR).ShowModal()
dlg.Destroy()
return
if user not in config.main["other_buffers"]["timelines"]:
config.main["other_buffers"]["timelines"].append(user)
else:
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()
dlg.Destroy()
return
sound.player.play("create_timeline.ogg")
st = buffers.basePanel(self.nb, self, user, self.twitter.twitter.get_user_timeline, argumento=user, sound="ready.ogg", timeline=True)
num = st.start_streams()
self.db.settings["buffers"].append(user)
if num == 0:
wx.MessageDialog(None, _(u"This user has no tweets. You can't open a timeline for this user"), _(u"Error!"), wx.ICON_ERROR).ShowModal()
self.db.settings.pop(user)
# self.nb.DeletePage(self.db.settings["buffers"].index(user))
self.db.settings["buffers"].remove(user)
else:
self.nb.InsertSubPage(self.db.settings["buffers"].index("timelines"), st, _(u"Timeline for %s") % (user))
st.put_items(num)
st.sound = "tweet_timeline.ogg"
self.stream2.disconnect()
del self.stream2
self.get_tls()
dlg.Destroy()
def favs_timeline(self, ev=None):
dlg = dialogs.utils.selectUserDialog(self, _(u"List of favourites"))
if dlg.ShowModal() == wx.ID_OK:
user = twitter.utils.if_user_exists(self.twitter.twitter, dlg.cb.GetValue())
if user == None:
wx.MessageDialog(None, _(u"The user does not exist"), _(u"Error"), wx.ICON_ERROR).ShowModal()
dlg.Destroy()
return
if user not in config.main["other_buffers"]["favourites_timelines"]:
config.main["other_buffers"]["favourites_timelines"].append(user)
else:
wx.MessageDialog(None, _(u"There's already a list of favourites for this user. You can't create another."), _(u"Existing list"), wx.ICON_ERROR).ShowModal()
dlg.Destroy()
return
sound.player.play("create_timeline.ogg")
st = buffers.favsPanel(self.nb, self, user+"-favs", argumento=user, sound="favourites_timeline_updated.ogg")
self.nb.InsertSubPage(self.db.settings["buffers"].index("favourites_timelines"), st, _(u"Favourites for %s") % (user))
num = st.start_streams()
self.db.settings["buffers"].append(user+"-favs")
if num == 0:
wx.MessageDialog(None, _(u"This user has no favourites. You can't create a list of favourites for this user."), _(u"Error!"), wx.ICON_ERROR).ShowModal()
self.db.settings.pop(user+"-favs")
self.nb.DeletePage(self.db.settings["buffers"].index(user+"-favs"))
self.db.settings["buffers"].remove(user+"-favs")
st.put_items(num)
dlg.Destroy()
def onAbout(self, ev=None):
info = wx.AboutDialogInfo()
info.SetName(application.name)
info.SetVersion(application.version)
info.SetDescription(application.description)
info.SetCopyright(application.copyright)
info.SetTranslators(application.translators)
# info.SetLicence(application.licence)
info.AddDeveloper(application.author)
wx.AboutBox(info)
def delete_buffer(self, ev=None):
pos = self.nb.GetCurrentPage().remove_buffer()
if pos != None:
self.stream2.disconnect()
del self.stream2
self.nb.DeletePage(self.nb.GetSelection())
sound.player.play("delete_timeline.ogg")
self.get_tls()
def delete_invalid_timeline(self):
pos = self.nb.GetCurrentPage().remove_invalid_buffer()
if pos != None:
self.nb.DeletePage(self.nb.GetSelection())
### Hidden Window
def left(self, event=None):
num = self.nb.GetSelection()
if num == 0:
self.nb.ChangeSelection(self.nb.GetPageCount()-1)
else:
self.nb.SetSelection(num-1)
while self.nb.GetCurrentPage().type == "account" or self.nb.GetCurrentPage().type == "empty": self.skip_blank_pages(False)
try:
msg = _(u"%s, %s of %s") % (self.nb.GetPageText(self.nb.GetSelection()), self.nb.GetCurrentPage().list.get_selected()+1, self.nb.GetCurrentPage().list.get_count())
except:
msg = _(u"%s. Empty") % (self.nb.GetPageText(self.nb.GetSelection()))
output.speak(msg, 1)
def right(self, event=None):
num = self.nb.GetSelection()
if num+1 == self.nb.GetPageCount():
self.nb.SetSelection(0)
else:
self.nb.SetSelection(num+1)
while self.nb.GetCurrentPage().type == "account" or self.nb.GetCurrentPage().type == "empty": self.skip_blank_pages(True)
try:
msg = _(u"%s, %s of %s") % (self.nb.GetPageText(self.nb.GetSelection()), self.nb.GetCurrentPage().list.get_selected()+1, self.nb.GetCurrentPage().list.get_count())
except:
msg = _(u"%s. Empty") % (self.nb.GetPageText(self.nb.GetSelection()))
output.speak(msg, 1)
def show_hide(self, ev=None):
# if platform.system() == "Linux" or platform.system() == "Darwin": return
keymap = {}
for i in config.main["keymap"]:
if hasattr(self, i):
keymap[config.main["keymap"][i]] = getattr(self, i)
if self.showing == True:
self.keyboard_handler = WXKeyboardHandler(self)
self.keyboard_handler.register_keys(keymap)
self.Hide()
self.showing = False
else:
self.keyboard_handler.unregister_keys(keymap)
del self.keyboard_handler
self.Show()
self.showing = True
def toggle_global_mute(self, event=None):
if config.main["sound"]["global_mute"] == False:
config.main["sound"]["global_mute"] = True
output.speak(_(u"Global mute on"))
elif config.main["sound"]["global_mute"] == True:
config.main["sound"]["global_mute"] = False
output.speak(_(u"Global mute off"))
def toggle_mute(self, event=None):
buffer = self.nb.GetCurrentPage().name_buffer
if buffer not in config.main["other_buffers"]["muted_buffers"]:
config.main["other_buffers"]["muted_buffers"].append(buffer)
output.speak(_(u"Buffer mute on"))
elif buffer in config.main["other_buffers"]["muted_buffers"]:
config.main["other_buffers"]["muted_buffers"].remove(buffer)
output.speak(_(u"Buffer mute off"))
def toggle_autoread(self, event=None):
buffer = self.nb.GetCurrentPage().name_buffer
if buffer not in config.main["other_buffers"]["autoread_buffers"]:
config.main["other_buffers"]["autoread_buffers"].append(buffer)
output.speak(_(u"The auto-reading of new tweets is enabled for this buffer"))
elif buffer in config.main["other_buffers"]["autoread_buffers"]:
config.main["other_buffers"]["autoread_buffers"].remove(buffer)
output.speak(_(u"The auto-reading of new tweets is disabled for this buffer"))
def repeat_item(self):
output.speak(self.nb.GetCurrentPage().get_message(), 1)
def copy_to_clipboard(self, event=None):
output.Copy(self.nb.GetCurrentPage().get_message())
output.speak(_(u"Copied"))
def clear_list(self, event=None):
self.nb.GetCurrentPage().interact("clear_list")
def conversation_up(self, evt=None):
if config.main["general"]["reverse_timelines"] == True and evt == None:
self.conversation_down("down")
return
id = self.db.settings[self.nb.GetCurrentPage().name_buffer][self.nb.GetCurrentPage().list.get_selected()]["in_reply_to_status_id_str"]
pos = twitter.utils.find_previous_reply(id, self.db.settings["home_timeline"])
if pos != None:
self.nb.ChangeSelection(1)
self.nb.GetCurrentPage().list.select_item(pos)
msg = _(u"%s") % (self.nb.GetCurrentPage().get_message())
output.speak(msg)
def conversation_down(self, evt=None):
if config.main["general"]["reverse_timelines"] == True and evt == None:
self.conversation_up("up")
return
id = self.db.settings[self.nb.GetCurrentPage().name_buffer][self.nb.GetCurrentPage().list.get_selected()]["id_str"]
# pos = twitter.utils.find_next_reply(id, self.db.settings["home_timeline"])
pos = twitter.utils.find_next_reply(id, self.db.settings["home_timeline"])
if pos != None:
self.nb.ChangeSelection(1)
self.nb.GetCurrentPage().list.select_item(pos)
msg = _(u"%s") % (self.nb.GetCurrentPage().get_message())
output.speak(msg)
def go_home(self):
self.nb.GetCurrentPage().list.select_item(0)
try:
output.speak(self.nb.GetCurrentPage().get_message(), 1)
except:
pass
def go_end(self):
self.nb.GetCurrentPage().list.select_item(self.nb.GetCurrentPage().list.get_count()-1)
try:
output.speak(self.nb.GetCurrentPage().get_message(), 1)
except:
pass
def go_page_up(self):
if self.nb.GetCurrentPage().list.get_selected <= 20:
index = 0
else:
index = self.nb.GetCurrentPage().list.get_selected() - 20
self.nb.GetCurrentPage().list.select_item(index)
try:
output.speak(self.nb.GetCurrentPage().get_message(), 1)
except:
pass
def go_page_down(self):
if self.nb.GetCurrentPage().list.get_selected() >= self.nb.GetCurrentPage().list.get_count() - 20:
index = self.nb.GetCurrentPage().list.get_count()-1
else:
index = self.nb.GetCurrentPage().list.get_selected() + 20
self.nb.GetCurrentPage().list.select_item(index)
try:
output.speak(self.nb.GetCurrentPage().get_message(), 1)
except:
pass
def volume_up(self):
self.nb.GetCurrentPage().interact("volume_up")
def volume_down(self):
self.nb.GetCurrentPage().interact("volume_down")
def url(self):
self.nb.GetCurrentPage().interact("url")
def audio(self):
self.nb.GetCurrentPage().interact("audio")
def up(self, event=None):
pos = self.nb.GetCurrentPage().list.get_selected()
index = self.nb.GetCurrentPage().list.get_selected()-1
try:
self.nb.GetCurrentPage().list.select_item(index)
except:
pass
if pos == self.nb.GetCurrentPage().list.get_selected():
sound.player.play("limit.ogg", False)
try:
output.speak(self.nb.GetCurrentPage().get_message(), 1)
except:
pass
def down(self, event=None):
index = self.nb.GetCurrentPage().list.get_selected()+1
pos = self.nb.GetCurrentPage().list.get_selected()
try:
self.nb.GetCurrentPage().list.select_item(index)
except:
pass
if pos == self.nb.GetCurrentPage().list.get_selected():
sound.player.play("limit.ogg", False)
try:
output.speak(self.nb.GetCurrentPage().get_message(), 1)
except:
pass
def get_more_items(self, event=None):
self.nb.GetCurrentPage().get_more_items()
def search_buffer(self, buffer_type=None, name_buffer=None):
page = None
for i in range(0, self.nb.GetPageCount()):
page = self.nb.GetPage(i)
if page.type != buffer_type:
continue
if page.name_buffer == name_buffer:
return page
return page
### Close App
def Destroy(self):
self.sysTray.Destroy()
super(mainFrame, self).Destroy()

View File

View File

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
############################################################
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################
categories = ["General"]
reproducibilities = ["always", "sometimes", "random", "have not tried", "unable to duplicate"]
severities = ["block", "crash", "major", "minor", "tweak", "text", "trivial", "feature"]

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
############################################################
# Copyright (c) 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -16,22 +16,17 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################
import wx
from multiplatform_widgets import widgets
import paths
import os
class accountPanel(wx.Panel):
def __init__(self, parent):
super(accountPanel, self).__init__(parent=parent)
self.type = "account"
sizer = wx.BoxSizer(wx.VERTICAL)
self.list = widgets.list(self, _(u"Announce"))
sizer.Add(self.list.list, 0, wx.ALL, 5)
self.SetSizer(sizer)
def get_logs_files():
files = {}
for i in os.listdir(paths.logs_path()):
if i == "debug.log": continue
f = open(paths.logs_path(i), "r")
files[i] = f.readlines()
f.close()
try: os.remove(paths.logs_path("tracebacks.log"))
except: pass
return files
class emptyPanel(accountPanel):
def __init__(self, parent):
super(emptyPanel, self).__init__(parent=parent)
self.type = "empty"
def get_more_items(self):
output.speak(_(u"This action is not supported for this buffer"))

124
src/issueReporter/gui.py Normal file
View File

@ -0,0 +1,124 @@
# -*- coding: utf-8 -*-
############################################################
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################
import wx
import application
from suds.client import Client
import constants
class reportBug(wx.Dialog):
def __init__(self, user_name):
self.user = "informador"
self.user_name = user_name
self.password = "contrasena"
self.url = application.report_bugs_url
self.categories = [_(u"General")]
self.reproducibilities = [_(u"always"), _(u"sometimes"), _(u"random"), _(u"have not tried"), _(u"unable to duplicate")]
self.severities = [_(u"block"), _(u"crash"), _(u"major"), _(u"minor"), _(u"tweak"), _(u"text"), _(u"trivial"), _(u"feature")]
wx.Dialog.__init__(self, None, -1)
self.SetTitle(_(u"Report an error"))
panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
categoryLabel = wx.StaticText(panel, -1, _(u"Select a category"), size=wx.DefaultSize)
self.category = wx.ComboBox(panel, -1, choices=self.categories, style=wx.CB_READONLY)
self.category.SetSize(self.category.GetBestSize())
self.category.SetSelection(0)
categoryB = wx.BoxSizer(wx.HORIZONTAL)
categoryB.Add(categoryLabel, 0, wx.ALL, 5)
categoryB.Add(self.category, 0, wx.ALL, 5)
self.category.SetFocus()
sizer.Add(categoryB, 0, wx.ALL, 5)
summaryLabel = wx.StaticText(panel, -1, _(u"Briefly describe what happened. You will be able to thoroughly explain it later"), size=wx.DefaultSize)
self.summary = wx.TextCtrl(panel, -1)
dc = wx.WindowDC(self.summary)
dc.SetFont(self.summary.GetFont())
self.summary.SetSize(dc.GetTextExtent("a"*80))
# self.summary.SetFocus()
summaryB = wx.BoxSizer(wx.HORIZONTAL)
summaryB.Add(summaryLabel, 0, wx.ALL, 5)
summaryB.Add(self.summary, 0, wx.ALL, 5)
sizer.Add(summaryB, 0, wx.ALL, 5)
descriptionLabel = wx.StaticText(panel, -1, _(u"Here, you can describe the bug in detail"), size=wx.DefaultSize)
self.description = wx.TextCtrl(panel, -1, style=wx.TE_MULTILINE)
dc = wx.WindowDC(self.description)
dc.SetFont(self.description.GetFont())
(x, y, z) = dc.GetMultiLineTextExtent("0"*2000)
self.description.SetSize((x, y))
descBox = wx.BoxSizer(wx.HORIZONTAL)
descBox.Add(descriptionLabel, 0, wx.ALL, 5)
descBox.Add(self.description, 0, wx.ALL, 5)
sizer.Add(descBox, 0, wx.ALL, 5)
reproducibilityLabel = wx.StaticText(panel, -1, _(u"how often does this bug happen?"), size=wx.DefaultSize)
self.reproducibility = wx.ComboBox(panel, -1, choices=self.reproducibilities, style=wx.CB_READONLY)
self.reproducibility.SetSelection(3)
self.reproducibility.SetSize(self.reproducibility.GetBestSize())
reprB = wx.BoxSizer(wx.HORIZONTAL)
reprB.Add(reproducibilityLabel, 0, wx.ALL, 5)
reprB.Add(self.reproducibility, 0, wx.ALL, 5)
sizer.Add(reprB, 0, wx.ALL, 5)
severityLabel = wx.StaticText(panel, -1, _(u"Select the importance that you think this bug has"))
self.severity = wx.ComboBox(panel, -1, choices=self.severities, style=wx.CB_READONLY)
self.severity.SetSize(self.severity.GetBestSize())
self.severity.SetSelection(3)
severityB = wx.BoxSizer(wx.HORIZONTAL)
severityB.Add(severityLabel, 0, wx.ALL, 5)
severityB.Add(self.severity, 0, wx.ALL, 5)
sizer.Add(severityB, 0, wx.ALL, 5)
self.agree = wx.CheckBox(panel, -1, _(u"I know that the TW Blue bug system will get my Twitter username to contact me and fix the bug quickly"))
self.agree.SetValue(False)
sizer.Add(self.agree, 0, wx.ALL, 5)
ok = wx.Button(panel, wx.ID_OK, _(u"Send report"))
ok.Bind(wx.EVT_BUTTON, self.onSend)
ok.SetDefault()
cancel = wx.Button(panel, wx.ID_CANCEL, _(u"Cancel"))
btnBox = wx.BoxSizer(wx.HORIZONTAL)
btnBox.Add(ok, 0, wx.ALL, 5)
btnBox.Add(cancel, 0, wx.ALL, 5)
sizer.Add(btnBox, 0, wx.ALL, 5)
panel.SetSizer(sizer)
self.SetClientSize(sizer.CalcMin())
def onSend(self, ev):
if self.summary.GetValue() == "" or self.description.GetValue() == "":
wx.MessageDialog(self, _(u"You must fill out both fields"), _(u"Error"), wx.OK|wx.ICON_ERROR).ShowModal()
return
if self.agree.GetValue() == False:
wx.MessageDialog(self, _(u"You need to mark the checkbox to provide us your twitter username to contact to you if is necessary."), _(u"Error"), wx.ICON_ERROR).ShowModal()
return
try:
client = Client(self.url)
issue = client.factory.create('IssueData')
issue.project.name = "TW Blue"
issue.project.id = 0
issue.summary = self.summary.GetValue(),
issue.description = "Reported by @%s\n\n" % (self.user_name) + self.description.GetValue()
issue.category = constants.categories[self.category.GetSelection()]
issue.reproducibility.name = constants.reproducibilities[self.reproducibility.GetSelection()]
issue.severity.name = constants.severities[self.severity.GetSelection()]
issue.priority.name = "normal"
issue.view_state.name = "public"
issue.resolution.name = "open"
issue.projection.name = "none"
issue.eta.name = "eta"
issue.status.name = "new"
id = client.service.mc_issue_add(self.user, self.password, issue)
wx.MessageDialog(self, _(u"Thanks for reporting this bug! In future versions, you may be able to find it in the changes list. You've reported the bug number %i") % (id), _(u"reported"), wx.OK).ShowModal()
self.EndModal(wx.ID_OK)
except:
wx.MessageDialog(self, _(u"Something unexpected occurred while trying to report the bug. Please, try again later"), _(u"Error while reporting"), wx.ICON_ERROR|wx.OK).ShowModal()
self.EndModal(wx.ID_CANCEL)

View File

@ -0,0 +1,3 @@
import platform
if platform.system() == "Windows":
from wxUI import *

View File

@ -41,5 +41,5 @@ actions = {
"search": _(u"Search on twitter"),
"edit_keystrokes": _(u"Shows the keystroke editor"),
"view_user_lists": _(u"Show lists for a specified user"),
"get_more_items": _(u"loads previous items to any buffer"),
"get_more_items": _(u"Loads more items for the current buffer"),
}

View File

@ -4,13 +4,12 @@ import wx
import constants
from multiplatform_widgets import widgets
from constants import actions
from pubsub import pub
class keystrokeEditor(wx.Dialog):
def __init__(self, parent=None, keyboard_handler=None):
super(keystrokeEditor, self).__init__(parent=parent, id=-1, title=_(u"Keystroke editor"))
def __init__(self):
super(keystrokeEditor, self).__init__(parent=None, id=-1, title=_(u"Keystroke editor"))
panel = wx.Panel(self)
self.parent = parent
self.keyboard_handler = keyboard_handler or None
self.actions = []
sizer = wx.BoxSizer(wx.VERTICAL)
keysText = wx.StaticText(panel, -1, _(u"Select a keystroke to edit"))
@ -30,27 +29,20 @@ class keystrokeEditor(wx.Dialog):
sizer.Add(firstSizer)
sizer.Add(secondSizer)
panel.SetSizerAndFit(sizer)
self.put_keystrokes()
def put_keystrokes(self):
for i in config.main["keymap"]:
def put_keystrokes(self, **keystrokes):
for i in keystrokes:
action = actions[i]
self.actions.append(i)
keystroke = config.main["keymap"][i]
keystroke = keystrokes[i]
self.keys.insert_item(False, *[action, keystroke])
def edit(self, ev):
action = self.actions[self.keys.get_selected()]
dlg = editKeystroke(self.parent, action, config.main["keymap"][action], self.keyboard_handler)
if dlg.ShowModal() == wx.ID_OK:
pos = self.keys.get_selected()
self.keys.clear()
self.put_keystrokes()
self.keys.select_item(pos)
# dlg.Destroy()
pub.sendMessage("editing_keystroke", action=action, parentDialog=self)
class editKeystroke(wx.Dialog):
def __init__(self, parent, action, keystroke, keyboard_handler):
def __init__(self, action, keystroke, keyboard_handler):
super(editKeystroke, self).__init__(parent=None, id=-1, title=_(u"Editing keystroke"))
self.parent = parent
self.keyboard_handler = keyboard_handler

Binary file not shown.

View File

@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: TW Blue 0.48\n"
"POT-Creation-Date: 2014-11-08 16:42+Hora estándar central (México)\n"
"PO-Revision-Date: 2014-11-08 23:50+0100\n"
"Last-Translator: José Manuel Delicado Alcolea <jmdaweb@hotmail.com>\n"
"PO-Revision-Date: 2014-11-11 19:16+0200\n"
"Last-Translator: Jani Kinnunen <jani.kinnunen@wippies.fi>\n"
"Language-Team: Jani Kinnunen <jani.kinnunen@wippies.fi>\n"
"Language: fi\n"
"MIME-Version: 1.0\n"
@ -750,9 +750,8 @@ msgstr "Yksityisviesti käyttäjälle %s"
#: ../src\gui\buffers\base.py:220 ../src\gui\buffers\dm.py:44
#: ../src\gui\buffers\people.py:56
#, fuzzy
msgid "New direct message"
msgstr "Yksityisviesti"
msgstr "Uusi yksityisviesti"
#: ../src\gui\buffers\base.py:228 ../src\gui\buffers\events.py:78
msgid "Write the tweet here"
@ -838,9 +837,8 @@ msgid "Mention"
msgstr "Mainitse"
#: ../src\gui\buffers\people.py:64
#, fuzzy
msgid "Mention to %s"
msgstr "Mainitse kaikille"
msgstr "Maininta käyttäjälle %s"
#: ../src\gui\buffers\trends.py:41 ../src\gui\buffers\tweet_searches.py:45
#: ../src\gui\buffers\user_searches.py:56
@ -853,7 +851,7 @@ msgstr "Kieli"
#: ../src\gui\dialogs\configuration.py:53
msgid "ask before exiting TwBlue?"
msgstr ""
msgstr "Kysy vahvistus ennen sulkemista"
#: ../src\gui\dialogs\configuration.py:56
msgid "Relative times"
@ -1222,9 +1220,8 @@ msgid "Select a list to remove the user"
msgstr "Valitse lista, jolta käyttäjä poistetaan"
#: ../src\gui\dialogs\message.py:43 ../src\gui\dialogs\message.py:146
#, fuzzy
msgid "%s - %s of 140 characters"
msgstr "Twiitti - %i merkkiä"
msgstr "%s - %s / 140 merkkiä"
#: ../src\gui\dialogs\message.py:77
msgid "Attaching..."
@ -1534,7 +1531,7 @@ msgstr "&Näytä suosikit"
#: ../src\gui\main.py:126
msgid "&Load previous items"
msgstr ""
msgstr "&Lataa edelliset kohteet"
#: ../src\gui\main.py:130
msgid "&Autoread tweets for this buffer"
@ -1641,9 +1638,8 @@ msgid "%s favourites from %s"
msgstr "%s suosikkia käyttäjältä %s"
#: ../src\gui\main.py:378
#, fuzzy
msgid "Connection error. Try again later."
msgstr "Valtuutuksessa tapahtui virhe. Yritä myöhemmin uudelleen."
msgstr "Yhteysvirhe. Yritä myöhemmin uudelleen."
#: ../src\gui\main.py:421
msgid "Streams disconnected. TW Blue will try to reconnect in a minute."
@ -1687,9 +1683,8 @@ msgid "Exit"
msgstr "Lopeta"
#: ../src\gui\main.py:587
#, fuzzy
msgid "Exiting..."
msgstr "Lisätään liitettä..."
msgstr "Suljetaan..."
#: ../src\gui\main.py:673
msgid "Error while adding to favourites."
@ -1960,7 +1955,7 @@ msgstr "Näytä valitun käyttäjän listat"
#: ../src\keystrokeEditor\constants.py:44
msgid "loads previous items to any buffer"
msgstr ""
msgstr "Lataa edelliset kohteet mihin tahansa puskuriin"
#: ../src\keystrokeEditor\gui.py:10
msgid "Keystroke editor"

Binary file not shown.

View File

@ -2,14 +2,14 @@ msgid ""
msgstr ""
"Project-Id-Version: TW Blue 0.48\n"
"POT-Creation-Date: 2014-11-08 16:42+Hora estándar central (México)\n"
"PO-Revision-Date: 2014-11-08 23:51+0100\n"
"Last-Translator: José Manuel Delicado Alcolea <jmdaweb@hotmail.com>\n"
"PO-Revision-Date: 2014-11-11 15:45+0100\n"
"Last-Translator: Rémy Ruiz <remyruiz@gmail.com>\n"
"Language-Team: Rémy Ruiz <remyruiz@gmail.com>\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.6.10\n"
"X-Generator: Poedit 1.6.8\n"
"X-Poedit-KeywordsList: _;gettext;gettext_noop\n"
"X-Poedit-Basepath: .\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@ -752,9 +752,8 @@ msgstr "Message direct à %s"
#: ../src\gui\buffers\base.py:220 ../src\gui\buffers\dm.py:44
#: ../src\gui\buffers\people.py:56
#, fuzzy
msgid "New direct message"
msgstr "Un message direct"
msgstr "Nouveau message direct"
#: ../src\gui\buffers\base.py:228 ../src\gui\buffers\events.py:78
msgid "Write the tweet here"
@ -854,7 +853,7 @@ msgstr "Langue"
#: ../src\gui\dialogs\configuration.py:53
msgid "ask before exiting TwBlue?"
msgstr ""
msgstr "demander avant de sortir de TwBlue ?"
#: ../src\gui\dialogs\configuration.py:56
msgid "Relative times"
@ -1227,9 +1226,8 @@ msgid "Select a list to remove the user"
msgstr "Sélectionnez une liste pour supprimer l'utilisateur"
#: ../src\gui\dialogs\message.py:43 ../src\gui\dialogs\message.py:146
#, fuzzy
msgid "%s - %s of 140 characters"
msgstr "Tweet - %i caractères"
msgstr "%s - %s de 140 caractères"
#: ../src\gui\dialogs\message.py:77
msgid "Attaching..."
@ -1539,7 +1537,7 @@ msgstr "V&oir favoris"
#: ../src\gui\main.py:126
msgid "&Load previous items"
msgstr ""
msgstr "&Charger les éléments précédents"
#: ../src\gui\main.py:130
msgid "&Autoread tweets for this buffer"
@ -1646,9 +1644,8 @@ msgid "%s favourites from %s"
msgstr "%s favoris de %s"
#: ../src\gui\main.py:378
#, fuzzy
msgid "Connection error. Try again later."
msgstr "Erreur pendant l'autorisation. Réessayez plus tard."
msgstr "Erreur pendant la connexion. Réessayez plus tard."
#: ../src\gui\main.py:421
msgid "Streams disconnected. TW Blue will try to reconnect in a minute."
@ -1691,9 +1688,8 @@ msgid "Exit"
msgstr "Sortir"
#: ../src\gui\main.py:587
#, fuzzy
msgid "Exiting..."
msgstr "Ajout en cours..."
msgstr "Sortie en cours..."
#: ../src\gui\main.py:673
msgid "Error while adding to favourites."
@ -1972,7 +1968,7 @@ msgstr "Afficher les listes d'un utilisateur spécifié"
#: ../src\keystrokeEditor\constants.py:44
msgid "loads previous items to any buffer"
msgstr ""
msgstr "chargez les éléments précédents à n'importe quel tampon"
#: ../src\keystrokeEditor\gui.py:10
msgid "Keystroke editor"

Binary file not shown.

View File

@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: TW Blue 0.48\n"
"POT-Creation-Date: 2014-11-08 16:42+Hora estándar central (México)\n"
"PO-Revision-Date: 2014-11-08 23:52+0100\n"
"Last-Translator: José Manuel Delicado Alcolea <jmdaweb@hotmail.com>\n"
"PO-Revision-Date: 2014-11-12 12:03+0100\n"
"Last-Translator: Chris Leo Mameli <llajta2012@gmail.com>\n"
"Language-Team: Manuel Cortez <info@twblue.com.mx>\n"
"Language: it\n"
"MIME-Version: 1.0\n"
@ -13,7 +13,7 @@ msgstr ""
"X-Poedit-Basepath: .\n"
"X-Poedit-SourceCharset: UTF-8\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 1.6.10\n"
"X-Generator: Poedit 1.6.3\n"
#: ../src\extra\AudioUploader\gui.py:31 ../src\gui\dialogs\message.py:173
#: ../src\gui\dialogs\message.py:261
@ -752,9 +752,8 @@ msgstr "Messaggio diretto a %s"
#: ../src\gui\buffers\base.py:220 ../src\gui\buffers\dm.py:44
#: ../src\gui\buffers\people.py:56
#, fuzzy
msgid "New direct message"
msgstr "Un messaggio diretto"
msgstr "Nuovo messaggio diretto"
#: ../src\gui\buffers\base.py:228 ../src\gui\buffers\events.py:78
msgid "Write the tweet here"
@ -854,11 +853,11 @@ msgstr "Lingua"
#: ../src\gui\dialogs\configuration.py:53
msgid "ask before exiting TwBlue?"
msgstr ""
msgstr "Richiedere conferma prima di uscire da TwBlue?"
#: ../src\gui\dialogs\configuration.py:56
msgid "Relative times"
msgstr "Relative times"
msgstr "Mostra tempo di ricezione trascorso"
#: ../src\gui\dialogs\configuration.py:60
msgid "Activate Sapi5 when any other screen reader is not being run"
@ -885,8 +884,8 @@ msgid ""
"Inverted buffers: The newest tweets will be shown at the beginning of the "
"lists while the oldest at the end"
msgstr ""
"Elenco invertito: I più nuovi tweets verranno mostrate all'inizio delle "
"liste, mentre il più antico alla fine"
"Inverti elenco: I nuovi tweets verranno mostrate in cima all'elenco, i "
"precedenti alla fine"
#: ../src\gui\dialogs\configuration.py:97
msgid "Show followers"
@ -1224,9 +1223,8 @@ msgid "Select a list to remove the user"
msgstr "Seleziona una lista per rimuovere l'utente"
#: ../src\gui\dialogs\message.py:43 ../src\gui\dialogs\message.py:146
#, fuzzy
msgid "%s - %s of 140 characters"
msgstr "Tweet -% i caratteri "
msgstr "%s - %s di 140 caratteri"
#: ../src\gui\dialogs\message.py:77
msgid "Attaching..."
@ -1440,7 +1438,7 @@ msgstr "&Tutorial dei suoni"
#: ../src\gui\main.py:69
msgid "&Edit keystrokes"
msgstr "&Modifica"
msgstr "&Modifica comandi"
#: ../src\gui\main.py:71
msgid "&Preferences"
@ -1536,7 +1534,7 @@ msgstr "Visualizza &preferiti"
#: ../src\gui\main.py:126
msgid "&Load previous items"
msgstr ""
msgstr "&Carica le voci precedenti"
#: ../src\gui\main.py:130
msgid "&Autoread tweets for this buffer"
@ -1643,9 +1641,8 @@ msgid "%s favourites from %s"
msgstr "%s preferiti da %s"
#: ../src\gui\main.py:378
#, fuzzy
msgid "Connection error. Try again later."
msgstr "Errore durante l'autorizzazione. Riprovare più tardi."
msgstr "Errore durante la connessione. Riprovare più tardi."
#: ../src\gui\main.py:421
msgid "Streams disconnected. TW Blue will try to reconnect in a minute."
@ -1688,9 +1685,8 @@ msgid "Exit"
msgstr "Esci"
#: ../src\gui\main.py:587
#, fuzzy
msgid "Exiting..."
msgstr "Allegando..."
msgstr "Chiusura in corso..."
#: ../src\gui\main.py:673
msgid "Error while adding to favourites."
@ -1850,7 +1846,7 @@ msgstr "Rimuovi dai favoriti"
#: ../src\keystrokeEditor\constants.py:17
msgid "Open the actions dialogue"
msgstr "Open the actions dialogue"
msgstr "Apre una finestra per selezionare un'azione"
#: ../src\keystrokeEditor\constants.py:18
msgid "See user details"
@ -1924,7 +1920,7 @@ msgstr "Ascolta il messaggio corrente"
#: ../src\keystrokeEditor\constants.py:35
msgid "Copy to clipboard"
msgstr "Copiato negli appunti"
msgstr "Copia negli appunti"
#: ../src\keystrokeEditor\constants.py:36
msgid "Add to list"
@ -1936,7 +1932,7 @@ msgstr "Rimuovi dalla lista"
#: ../src\keystrokeEditor\constants.py:38
msgid "Mutes/unmutes the active buffer"
msgstr "Mutes/unmutes the active buffer"
msgstr "Mutes/unmutes il buffer corrente"
#: ../src\keystrokeEditor\constants.py:39
msgid "Globally mute/unmute TW Blue"
@ -1962,7 +1958,7 @@ msgstr "Mostra le liste di un utente"
#: ../src\keystrokeEditor\constants.py:44
msgid "loads previous items to any buffer"
msgstr ""
msgstr "Carica voci precedenti per tutti i buffer"
#: ../src\keystrokeEditor\gui.py:10
msgid "Keystroke editor"
@ -1970,7 +1966,7 @@ msgstr "Modifica comando"
#: ../src\keystrokeEditor\gui.py:16
msgid "Select a keystroke to edit"
msgstr "Select a keystroke to edit"
msgstr "Seleziona il comando da modificare:"
#: ../src\keystrokeEditor\gui.py:17
msgid "Keystroke"
@ -1978,11 +1974,11 @@ msgstr "Comando"
#: ../src\keystrokeEditor\gui.py:54
msgid "Editing keystroke"
msgstr "Editing keystroke"
msgstr "Modifica comando"
#: ../src\keystrokeEditor\gui.py:61
msgid "Control"
msgstr "Comandi"
msgstr "Control"
#: ../src\keystrokeEditor\gui.py:62
msgid "Alt"

View File

@ -1,81 +1,29 @@
# -*- coding: utf-8 -*-
""" TW Blue
A twitter accessible, easy of use and cross platform application."""
############################################################
# Copyright(C)2013-2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################
import languageHandler
import wx
ssmg = None
import gui
import paths
import config
import commandline
import platform
if platform.system() == "Windows":
from logger import logger as logging
if platform.system() == "Darwin":
import osx_prepare
osx_prepare.setup()
from sessionmanager import manager
from sessionmanager import gui as smGUI
manager.setup()
import sys
import config
import sound
import output
if hasattr(sys, 'frozen'):
sys.stderr = open(paths.logs_path("stderr.log"), 'w')
sys.stdout = open(paths.logs_path("stdout.log"), 'w')
class app(wx.App):
def __init__(self, *args, **kwargs):
super(app, self).__init__(*args, **kwargs)
if platform.system() != "Darwin":
self.start()
else:
self.mac()
def mac(self):
self.hold_frame = wx.Frame(title="None", parent=None)
self.hold_frame.Show()
wx.CallLater(10, self.start)
def start(self):
ssmg = smGUI.sessionManagerWindow()
if ssmg.ShowModal() == wx.ID_OK:
frame = gui.main.mainFrame()
frame.Show()
frame.showing = True
if config.main != None and config.main["general"]["hide_gui"] == True and platform.system() == "Windows":
frame.show_hide()
frame.Hide()
self.SetTopWindow(frame)
if hasattr(self, "frame"): self.hold_frame.Hide()
# If the user press on cancel.
else:
self.Exit()
ap = app()
### I should uncomment this
#if platform.system() != "Windows":
# local = wx.Locale(wx.LANGUAGE_DEFAULT)
# local.AddCatalogLookupPathPrefix(paths.locale_path())
# local.AddCatalog("twblue")
#ap = app(redirect=True, useBestVisual=True, filename=paths.logs_path('tracebacks.log'))
#wx.CallLater(10, start)
ap.MainLoop()
def setup():
config.setup()
sound.setup()
output.setup()
languageHandler.setLanguage(config.app["app-settings"]["language"])
from controller import mainController
from sessionmanager import sessionManager
app = wx.App()
sm = sessionManager.sessionManagerController()
sm.fill_list()
if len(sm.sessions) == 0: sm.show()
else:
sm.do_ok()
del sm
r = mainController.Controller()
r.view.Show()
sound.player.play("ready.ogg")
app.MainLoop()
setup()

View File

@ -1,41 +0,0 @@
# -- coding: utf-8 -*-
from wx.lib.newevent import NewEvent
import wx
EVT_DELETED = wx.NewEventType()
MyEVT_DELETED = wx.PyEventBinder(EVT_DELETED, 1)
EVT_STARTED = wx.NewEventType()
MyEVT_STARTED = wx.PyEventBinder(EVT_STARTED, 1)
EVT_OBJECT = wx.NewEventType()
MyEVT_OBJECT = wx.PyEventBinder(EVT_OBJECT, 1)
ResultEvent, EVT_RESULT = NewEvent()
#DeletedEvent, EVT_DELETED = NewEvent()
class event(wx.PyCommandEvent):
def __init__(self, evtType, id):
self.text = ""
wx.PyCommandEvent.__init__(self, evtType, id)
def SetItem(self, item):
self.item = item
def GetItem(self):
return self.item
def SetAnnounce(self, text ):
self.text = text
def GetAnnounce(self):
try: return self.text
except: pass
class infoEvent(event):
def __init__(self, evtType, id):
event.__init__(self, evtType, id)
def SetItem(self, page, items):
self.page = page
self.items = items
def GetItem(self):
return [self.page, self.items]

View File

@ -1,38 +0,0 @@
import platform
import os
import sys
from functools import wraps
def merge_paths(func):
@wraps(func)
def merge_paths_wrapper(*a):
return unicode(os.path.join(func(), *a))
return merge_paths_wrapper
@merge_paths
def app_path():
if hasattr(sys, "frozen"):
from win32api import GetModuleFileName #We should only be here if using py2exe hence windows
app_path = os.path.dirname(GetModuleFileName(0))
else:
app_path = os.path.normpath(os.path.dirname(__file__))
return app_path
@merge_paths
def config_path():
path = app_path(u"config")
if not os.path.exists(path):
os.mkdir(path)
return path
@merge_paths
def data_path(app_name='Blu JM'):
# if platform.system() == "Windows":
# import shlobj
# data_path = os.path.join(shlobj.SHGetFolderPath(0, shlobj.CSIDL_APPDATA), app_name)
# else:
data_path = os.path.join(os.environ['HOME'], ".%s" % app_name)
if not os.path.exists(data_path):
os.mkdir(data_path)
return data_path

View File

@ -27,8 +27,8 @@ class RepeatingTimer(threading.Thread):
while not self.finished.is_set():
self.finished.wait(self.interval)
if not self.finished.is_set(): #In case someone has canceled while waiting
try:
self.function(*self.args, **self.kwargs)
except:
pass
# try:
self.function(*self.args, **self.kwargs)
# except:
# pass
# logging.exception("Execution failed. Function: %r args: %r and kwargs: %r" % (self.function, self.args, self.kwargs))

View File

@ -1 +1,9 @@
# -*- coding: cp1252 -*-
# -*- coding: utf-8 -*-
""" Module to manage sessions. It can create and configure all sessions.
Contents of this package:
wxUI: The graphical user interface written in WX Python (for windows). The view.
session_exceptions: Some useful exceptions when there is an error.
manager: Handles multiple sessions, setting the configuration files and check if the session is valid. Part of the model.
session: Creates a twitter session for an user. The other part of the model.
"""

View File

@ -1,101 +0,0 @@
# -*- coding: utf-8 -*-
import time
import wx
import manager
import session_exceptions
import paths
import config
import sound
import languageHandler
import output
import os
import twitter
import webbrowser
from multiplatform_widgets import widgets
from config_utils import Configuration
class sessionManagerWindow(wx.Dialog):
def __init__(self):
super(sessionManagerWindow, self).__init__(parent=None, title=_(u"Session manager"), size=wx.DefaultSize)
# panelSizer = wx.BoxSizer(wx.VERTICAL)
panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
label = wx.StaticText(panel, -1, _(u"Select a twitter account to start TW Blue"), size=wx.DefaultSize)
listSizer = wx.BoxSizer(wx.HORIZONTAL)
self.list = widgets.list(panel, _(u"Account"), style=wx.LC_SINGLE_SEL|wx.LC_REPORT)
self.fill_list()
listSizer.Add(label, 0, wx.ALL, 5)
listSizer.Add(self.list.list, 0, wx.ALL, 5)
sizer.Add(listSizer, 0, wx.ALL, 5)
new = wx.Button(panel, -1, _(u"New account"), size=wx.DefaultSize)
new.Bind(wx.EVT_BUTTON, self.new_account)
ok = wx.Button(panel, wx.ID_OK, size=wx.DefaultSize)
ok.SetDefault()
ok.Bind(wx.EVT_BUTTON, self.ok)
cancel = wx.Button(panel, wx.ID_CANCEL, size=wx.DefaultSize)
buttons = wx.BoxSizer(wx.HORIZONTAL)
buttons.Add(new, 0, wx.ALL, 5)
buttons.Add(ok, 0, wx.ALL, 5)
buttons.Add(cancel, 0, wx.ALL, 5)
sizer.Add(buttons, 0, wx.ALL, 5)
panel.SetSizer(sizer)
# sizer.Layout()
# self.Fit()
# self.SetSize(panel.GetBestSize())
# panelSizer.Add(panel)
# self.SetSizerAndFit(sizer)
# sizer.Layout()
min = sizer.CalcMin()
self.SetClientSize(min)
def fill_list(self):
self.sessions = []
for i in os.listdir(paths.config_path()):
if os.path.isdir(paths.config_path(i)):
strconfig = "%s/session.conf" % (paths.config_path(i))
config_test = Configuration(strconfig)
name = config_test["twitter"]["user_name"]
if name != "" and config_test["twitter"]["user_key"] != "" and config_test["twitter"]["user_secret"] != "":
self.list.insert_item(False, name)
self.sessions.append(i)
if self.list.get_count() > 0:
self.list.select_item(0)
self.list.list.SetSize(self.list.list.GetBestSize())
def ok(self, ev):
if self.list.get_count() == 0:
wx.MessageDialog(None, _(u"You need to configure an account."), _(u"Account Error"), wx.ICON_ERROR).ShowModal()
return
current_session = self.sessions[self.list.get_selected()]
manager.manager.set_current_session(current_session)
config.MAINFILE = "%s/session.conf" % (manager.manager.get_current_session())
config.setup()
lang=config.main['general']['language']
languageHandler.setLanguage(lang)
sound.setup()
output.setup()
# else:
# self.name = current_session
self.EndModal(wx.ID_OK)
def new_account(self, ev):
twitter_object = twitter.twitter.twitter()
dlg = wx.MessageDialog(self, _(u"The request for the required Twitter authorization to continue will be opened on your browser. You only need to do it once. Would you like to autorhise a new account now?"), _(u"Authorisation"), wx.YES_NO)
if dlg.ShowModal() == wx.ID_NO:
return
else:
location = (str(time.time())[:12])
manager.manager.add_session(location)
config.MAINFILE = "%s/session.conf" % (location,)
config.setup()
try:
twitter_object.authorise()
except:
wx.MessageDialog(None, _(u"Your access token is invalid or the authorisation has failed. Please try again."), _(u"Invalid user token"), wx.ICON_ERROR).ShowModal()
return
total = self.list.get_count()
name = _(u"Authorised account %d") % (total+1)
self.list.insert_item(False, name)
if self.list.get_count() == 1:
self.list.select_item(0)
self.sessions.append(location)

View File

@ -1,5 +1,6 @@
# -*- coding: cp1252 -*-
from config_utils import Configuration, ConfigurationResetException
#from config_utils import Configuration, ConfigurationResetException
import config
import paths
import os
import session_exceptions
@ -10,17 +11,17 @@ def setup():
manager = sessionManager()
class sessionManager(object):
def __init__(self):
FILE = "sessions.conf"
SPEC = "sessions.defaults"
try:
self.main = Configuration(paths.config_path(FILE), paths.app_path(SPEC))
except ConfigurationResetException:
pass
# def __init__(self):
# FILE = "sessions.conf"
# SPEC = "app-configuration.defaults"
# try:
# self.main = Configuration(paths.config_path(FILE), paths.app_path(SPEC))
# except ConfigurationResetException:
# pass
def get_current_session(self):
if self.is_valid(self.main["sessions"]["current_session"]):
return self.main["sessions"]["current_session"]
if self.is_valid(config.app["sessions"]["current_session"]):
return config.app["sessions"]["current_session"]
else:
return False
@ -28,16 +29,16 @@ class sessionManager(object):
path = paths.config_path(id)
if not os.path.exists(path):
os.mkdir(path)
self.main["sessions"]["sessions"].append(id)
config.app["sessions"]["sessions"].append(id)
def set_current_session(self, sessionID):
self.main["sessions"]["current_session"] = sessionID
self.main.write()
config.app["sessions"]["current_session"] = sessionID
config.app.write()
def is_valid(self, id):
if not os.path.exists(paths.config_path(id)):
raise session_exceptions.NonExistentSessionError("That session does not exist.")
self.main["sessions"]["current_session"] = ""
config.app["sessions"]["current_session"] = ""
return False
else:
return True

View File

@ -0,0 +1,269 @@
# -*- coding: utf-8 -*-
""" The main session object. Here are the twitter functions to interact with the "model" of TWBlue."""
import twitter
import application
import db
import session_exceptions as Exceptions
import paths
import output
import time
import sound
from twitter import utils
from twython import TwythonError, TwythonRateLimitError, TwythonAuthError
from config_utils import Configuration, ConfigurationResetException
from mysc.thread_utils import call_threaded
sessions = {}
class Session(object):
""" A session object where we will save configuration, the twitter object and a local storage for saving the items retrieved through the Twitter API methods"""
# Decorators.
def _require_login(fn):
""" Decorator for checking if the user is logged (a twitter object has credentials) on twitter.
Some functions may need this to avoid make unneeded twitter API calls."""
def f(self, *args, **kwargs):
if self.logged == True:
fn(self, *args, **kwargs)
else:
raise Exceptions.NotLoggedSessionError("You are not logged yet.")
return f
def _require_configuration(fn):
""" Check if the user has a configured session."""
def f(self, *args, **kwargs):
if self.settings != None:
fn(self, *args, **kwargs)
else:
raise Exceptions.NotConfiguredSessionError("Not configured.")
return f
def order_buffer(self, name, data):
""" Put the new items on the local database.
name str: The name for the buffer stored in the dictionary.
data list: A list with tweets.
returns the number of items that has been added in this execution"""
num = 0
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 self.settings["general"]["reverse_timelines"] == False: self.db[name].append(i)
else: self.db[name].insert(0, i)
num = num+1
return num
def order_cursored_buffer(self, name, data):
""" Put the new items on the local database. Useful for cursored buffers (followers, friends, users of a list and searches)
name str: The name for the buffer stored in the dictionary.
data list: A list with items and some information about cursors.
returns the number of items that has been added in this execution"""
num = 0
if self.db.has_key(name) == False:
self.db[name] = {}
self.db[name]["items"] = []
# if len(self.db[name]["items"]) > 0:
for i in data:
if utils.find_item(i["id"], self.db[name]["items"]) == None:
if self.settings["general"]["reverse_timelines"] == False: self.db[name]["items"].append(i)
else: self.db[name]["items"].insert(0, i)
num = num+1
return num
def __init__(self, session_id):
""" session_id (str): The name of the folder inside the config directory where the session is located."""
super(Session, self).__init__()
self.session_id = session_id
self.logged = False
self.settings = None
self.twitter = twitter.twitter.twitter()
self.db = {}
def get_configuration(self):
""" Gets settings for a session."""
file_ = "%s/session.conf" % (self.session_id,)
try:
self.settings = Configuration(paths.config_path(file_), paths.app_path("Conf.defaults"))
except:
self.settings = None
@_require_configuration
def login(self):
""" Login into twitter using credentials from settings.
if the user account isn't authorised, it needs to call self.authorise() before login."""
if self.settings["twitter"]["user_key"] != None and self.settings["twitter"]["user_secret"] != None:
self.twitter.login(self.settings["twitter"]["user_key"], self.settings["twitter"]["user_secret"])
self.logged = True
else:
self.logged = False
raise Exceptions.RequireCredentialsSessionError
@_require_configuration
def authorise(self):
""" Authorises a Twitter account. This function needs to be called for each new session, after of self.get_configuration() and before of self.login()"""
if self.logged == True:
raise Exceptions.AlreadyAuthorisedError("The authorisation process is not needed at this time.")
else:
self.twitter.authorise(self.settings)
def api_call(self, call_name, action="", _sound=None, report_success=False, report_failure=True, preexec_message="", *args, **kwargs):
""" Make a call to the Twitter API. If there is a connectionError or another exception not related to Twitter, It will call to the method at least 25 times, waiting a while between calls. Useful for post methods.
If twitter returns an error, it will not call anymore the method.
call_name str: The method to call
action str: The thing what you are doing on twitter, it will be reported to the user if report_success is set to True.
for example "following @tw_blue2" will be reported as "following @tw_blue2 succeeded".
_sound str: a sound to play if the call is executed properly.
report_success and report_failure bool: These are self explanatory. True or false. It's all.
preexec_message str: A message to speak to the user while the call is doing the work, example: "try to follow to x user"."""
finished = False
tries = 0
if preexec_message:
output.speak(preexec_message, True)
while finished==False and tries < 25:
try:
val = getattr(self.twitter.twitter, call_name)(*args, **kwargs)
finished = True
except TwythonError as e:
output.speak(e.message)
if report_failure and hasattr(e, 'message'):
output.speak(_("%s failed. Reason: %s") % (action, e.message))
finished = True
except:
tries = tries + 1
time.sleep(5)
if report_success:
output.speak(_("%s succeeded.") % action)
if _sound != None: sound.player.play(_sound)
@_require_login
def get_favourites_timeline(self, name, *args, **kwargs):
""" Gets favourites for the authenticated user or a friend or follower or somewhat.
name str: Name for store all in the database."""
tl = self.call_paged(self.twitter.twitter.get_favorites, *args, **kwargs)
return self.order_buffer(name, tl)
def call_paged(self, update_function, *args, **kwargs):
""" Makes a call to the Twitter API methods several times. Useful for get methods.
this function is needed for retrieving more than 200 items.
update_function str: The function to call. This function must be child of self.twitter.twitter
return a list with all items retrieved."""
max = int(self.settings["general"]["max_api_calls"])-1
results = []
data = getattr(self.twitter.twitter, update_function)(count=self.settings["general"]["max_tweets_per_call"], *args, **kwargs)
results.extend(data)
for i in range(0, max):
if i == 0: max_id = results[-1]["id"]
else: max_id = results[0]["id"]
data = update_function(max_id=max_id, count=self.settings["general"]["max_tweets_per_call"], *args, **kwargs)
results.extend(data)
results.reverse()
return results
@_require_login
def get_user_info(self):
""" Retrieves some information required by TWBlue for setup."""
f = self.twitter.twitter.get_account_settings()
sn = f["screen_name"]
self.db["user_name"] = sn
self.db["user_id"] = self.twitter.twitter.show_user(screen_name=sn)["id_str"]
try:
self.db["utc_offset"] = f["time_zone"]["utc_offset"]
except KeyError:
self.db["utc_offset"] = -time.timezone
self.get_lists()
self.get_muted_users()
self.settings.write()
@_require_login
def get_lists(self):
""" Gets the lists that the user is suscribed."""
self.db["lists"] = self.twitter.twitter.show_lists(reverse=True)
@_require_login
def get_muted_users(self):
""" Gets muted users (oh really?)."""
self.db["muted_users"] = self.twitter.twitter.get_muted_users_ids()["ids"]
@_require_login
def get_stream(self, name, function, *args, **kwargs):
""" Retrieves the items for a regular stream.
name str: Name to save items on the database.
function str: A function to get the items."""
last_id = -1
if self.db.has_key(name):
try:
if self.db[name][0]["id"] > self.db[name][-1]["id"]:
last_id = self.db[name][0]["id"]
else:
last_id = self.db[name][-1]["id"]
except IndexError:
pass
tl = self.call_paged(function, sinze_id=last_id, *args, **kwargs)
self.order_buffer(name, tl)
@_require_login
def get_cursored_stream(self, name, function, items="users", *args, **kwargs):
""" Gets items for API calls that requires using cursors to paginate the results.
name str: Name to save it in the database.
function str: Function that provides the items.
items: When the function returns the list with results, items will tell how the order function should be look.
for example get_followers_list returns a list and users are under list["users"], here the items should be point to "users"."""
items_ = []
try:
if self.db[name].has_key("next_cursor"):
next_cursor = self.db[name]["next_cursor"]
else:
next_cursor = -1
except KeyError:
next_cursor = -1
tl = getattr(self.twitter.twitter, function)(cursor=next_cursor, count=self.settings["general"]["max_tweets_per_call"], *args, **kwargs)
tl[items].reverse()
num = self.order_cursored_buffer(name, tl[items])
self.db[name]["next_cursor"] = tl["next_cursor"]
return num
def start_streaming(self):
""" Start the streaming for sending tweets in realtime."""
self.main_stream = twitter.buffers.stream.streamer(application.app_key, application.app_secret, self.settings["twitter"]["user_key"], self.settings["twitter"]["user_secret"], self)
call_threaded(self.main_stream.user)
self.timelinesStream = twitter.buffers.indibidual.timelinesStreamer(application.app_key, application.app_secret, self.settings["twitter"]["user_key"], self.settings["twitter"]["user_secret"], session=self)
ids = ""
for i in self.settings["other_buffers"]["timelines"]:
ids = ids + "%s, " % (self.db[i+"-timeline"][0]["user"]["id_str"])
# if ids != "":
call_threaded(self.timelinesStream.statuses.filter, follow=ids)

View File

@ -0,0 +1,52 @@
# -*- coding: utf-8 -*-
import wx
import wxUI as view
import paths
import time
import os
import session
import manager
from config_utils import Configuration
class sessionManagerController(object):
def __init__(self):
super(sessionManagerController, self).__init__()
manager.setup()
def fill_list(self):
sessionsList = []
self.sessions = []
for i in os.listdir(paths.config_path()):
if os.path.isdir(paths.config_path(i)):
strconfig = "%s/session.conf" % (paths.config_path(i))
config_test = Configuration(strconfig)
name = config_test["twitter"]["user_name"]
if name != "" and config_test["twitter"]["user_key"] != "" and config_test["twitter"]["user_secret"] != "":
sessionsList.append(name)
self.sessions.append(i)
if hasattr(self, "view"): self.view.fill_list(sessionsList)
def show(self):
self.view = view.sessionManagerWindow(self)
if self.view.ShowModal() == wx.ID_CANCEL:
self.view.Destroy()
def do_ok(self):
for i in self.sessions:
s = session.Session(i)
s.get_configuration()
s.login()
session.sessions[i] = s
def manage_new_account(self):
location = (str(time.time())[:6])
s = session.Session(location)
manager.manager.add_session(location)
s.get_configuration()
try:
s.authorise()
self.sessions.append(location)
self.view.add_new_session_to_list()
except:
self.view.show_unauthorised_error()
return

View File

@ -3,3 +3,7 @@ import exceptions
class InvalidSessionError(exceptions.Exception): pass
class NonExistentSessionError(exceptions.Exception): pass
class NotLoggedSessionError(exceptions.BaseException): pass
class NotConfiguredSessionError(exceptions.BaseException): pass
class RequireCredentialsSessionError(exceptions.BaseException): pass
class AlreadyAuthorisedError(exceptions.BaseException): pass

View File

@ -0,0 +1,60 @@
# -*- coding: utf-8 -*-
import wx
from multiplatform_widgets import widgets
class sessionManagerWindow(wx.Dialog):
def __init__(self, controller):
super(sessionManagerWindow, self).__init__(parent=None, title="Session manager", size=wx.DefaultSize)
self.controller = controller
panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
label = wx.StaticText(panel, -1, u"Select a twitter account to start TW Blue", size=wx.DefaultSize)
listSizer = wx.BoxSizer(wx.HORIZONTAL)
self.list = widgets.list(panel, u"Account", style=wx.LC_SINGLE_SEL|wx.LC_REPORT)
listSizer.Add(label, 0, wx.ALL, 5)
listSizer.Add(self.list.list, 0, wx.ALL, 5)
sizer.Add(listSizer, 0, wx.ALL, 5)
new = wx.Button(panel, -1, u"New account", size=wx.DefaultSize)
new.Bind(wx.EVT_BUTTON, self.new_account)
ok = wx.Button(panel, wx.ID_OK, size=wx.DefaultSize)
ok.SetDefault()
ok.Bind(wx.EVT_BUTTON, self.ok)
cancel = wx.Button(panel, wx.ID_CANCEL, size=wx.DefaultSize)
buttons = wx.BoxSizer(wx.HORIZONTAL)
buttons.Add(new, 0, wx.ALL, 5)
buttons.Add(ok, 0, wx.ALL, 5)
buttons.Add(cancel, 0, wx.ALL, 5)
sizer.Add(buttons, 0, wx.ALL, 5)
panel.SetSizer(sizer)
min = sizer.CalcMin()
self.SetClientSize(min)
def fill_list(self, sessionsList):
for i in sessionsList:
self.list.insert_item(False, i)
if self.list.get_count() > 0:
self.list.select_item(0)
self.list.list.SetSize(self.list.list.GetBestSize())
def ok(self, ev):
if self.list.get_count() == 0:
wx.MessageDialog(None, _(u"You need to configure an account."), _(u"Account Error"), wx.ICON_ERROR).ShowModal()
return
self.controller.do_ok()
self.EndModal(wx.ID_OK)
def new_account(self, ev):
dlg = wx.MessageDialog(self, _(u"The request for the required Twitter authorization to continue will be opened on your browser. You only need to do it once. Would you like to autorhise a new account now?"), _(u"Authorisation"), wx.YES_NO)
if dlg.ShowModal() == wx.ID_NO:
return
else:
self.controller.manage_new_account()
def add_new_session_to_list(self):
total = self.list.get_count()
name = _(u"Authorised account %d") % (total+1)
self.list.insert_item(False, name)
if self.list.get_count() == 1:
self.list.select_item(0)
def show_unauthorised_error(self):
wx.MessageDialog(None, _(u"Your access token is invalid or the authorisation has failed. Please try again."), _(u"Invalid user token"), wx.ICON_ERROR).ShowModal()

View File

@ -1,3 +0,0 @@
[sessions]
current_session = string(default="")
sessions = list(default=list())

View File

@ -1,22 +1,4 @@
# -*- coding: utf-8 -*-
""" Sound utilities."""
############################################################
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################
import sys
import url_shortener
import audio_services
@ -28,15 +10,18 @@ import paths
import sound_lib
import subprocess
import platform
import output
system = platform.system()
from mysc.repeating_timer import RepeatingTimer
player = None
player = URLPlayer = None
def setup():
global player
global player, URLPlayer
if not player:
player = soundSystem()
if not URLPlayer:
URLPlayer = URLStream()
def recode_audio(filename, quality=4.5):
global system
@ -55,8 +40,8 @@ class soundSystem(object):
def check_soundpack(self):
""" Checks if the folder where live the current soundpack exists."""
self.soundpack_OK = False
if os.path.exists(paths.sound_path(config.main["sound"]["current_soundpack"])):
self.path = paths.sound_path(config.main["sound"]["current_soundpack"])
if os.path.exists(paths.sound_path(config.app["app-settings"]["current_soundpack"])):
self.path = paths.sound_path(config.app["app-settings"]["current_soundpack"])
self.soundpack_OK = True
elif os.path.exists(paths.sound_path("default")):
self.path = paths.sound_path("default")
@ -71,11 +56,11 @@ class soundSystem(object):
self.input = sound_lib.input.Input()
# Try to use the selected device from the configuration. It can fail if the machine does not has a mic.
try:
self.output.set_device(self.output.find_device_by_name(config.main["sound"]["output_device"]))
self.input.set_device(self.input.find_device_by_name(config.main["sound"]["input_device"]))
self.output.set_device(self.output.find_device_by_name(config.app["app-settings"]["output_device"]))
self.input.set_device(self.input.find_device_by_name(config.app["app-settings"]["input_device"]))
except:
config.main["sound"]["output_device"] = "Default"
config.main["sound"]["input_device"] = "Default"
config.app["app-settings"]["output_device"] = "Default"
config.app["app-settings"]["input_device"] = "Default"
self.files = []
self.cleaner = RepeatingTimer(60, self.clear_list)
@ -84,42 +69,49 @@ class soundSystem(object):
def clear_list(self):
log.debug("Cleaning sounds... Total sounds found: %i" % len(self.files))
if self.files == []: return
for i in xrange(0, len(self.files)):
if self.files[i].is_playing == False:
self.files[i].free()
self.files.pop(i)
if len(self.files) == 0: return
try:
for i in range(0, len(self.files)):
if self.files[i].is_playing == False:
self.files[i].free()
self.files.pop(i)
except IndexError:
pass
log.debug("Files used now: %i" % len(self.files))
def play(self, sound, argument=False):
if self.soundpack_OK == False: return
if config.main["sound"]["global_mute"] == True: return
if config.app["app-settings"]["global_mute"] == True: return
sound_object = sound_lib.stream.FileStream(file="%s/%s" % (self.path, sound))
sound_object.volume = float(config.main["sound"]["volume"])
sound_object.volume = float(config.app["app-settings"]["volume"])
self.files.append(sound_object)
sound_object.play()
class urlStream(object):
def __init__(self, url):
self.url = url
log.debug(u"URL: %s" % url)
class URLStream(object):
def __init__(self):
self.url = None
self.prepared = False
def prepare(self):
def prepare(self, url):
self.prepared = False
url = url_shortener.unshorten(self.url)
log.debug("url desacortada: "+str(url))
if url != None:
self.url = url
transformer = audio_services.find_url_transformer(self.url)
self.url = transformer(self.url)
log.debug(u"Url transformada: %s" % self.url)
prepare = True
self.url = url_shortener.unshorten(url)
if self.url != None:
transformer = audio_services.find_url_transformer(self.url)
self.url = transformer(self.url)
self.prepared = True
def play(self):
self.stream = sound_lib.stream.URLStream(url=self.url)
self.stream.volume = float(config.main["sound"]["volume"])
self.stream.play()
def play(self, url):
if hasattr(self, "stream") and self.stream.is_playing:
output.speak(_(u"Stopped"))
self.stream.stop()
del self.stream
else:
output.speak(_(u"Playing..."))
self.prepare(url)
if self.prepared == True:
self.stream = sound_lib.stream.URLStream(url=self.url)
self.stream.volume = float(config.app["app-settings"]["volume"])
self.stream.play()
@staticmethod
def delete_old_tempfiles():

View File

@ -1,2 +1,2 @@
import buffers, utils, compose, starting, twitter
import buffers, utils, compose, twitter
from compose import prettydate

View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
import BaseHTTPServer
from urlparse import urlparse, parse_qs
logged = False
verifier = None
class handler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(self):
global logged
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
logged = True
params = parse_qs(urlparse(self.path).query)
global verifier
verifier = params.get('oauth_verifier', [None])[0]
self.wfile.write("You have successfully logged in to Twitter with TW Blue. "
"You can close this window now.")

View File

@ -1,46 +1,35 @@
# -*- coding: utf-8 -*-
from twitter import compose
from twython import TwythonStreamer
import sound
from mysc import event
import wx
import config
import output
from pubsub import pub
import logging as original_logger
log = original_logger.getLogger("MainStream")
class streamer(TwythonStreamer):
def __init__(self, app_key, app_secret, oauth_token, oauth_token_secret, timeout=300, retry_count=None, retry_in=10, client_args=None, handlers=None, chunk_size=1, parent=None):
self.db = parent.db
self.parent = parent
TwythonStreamer.__init__(self, app_key, app_secret, oauth_token, oauth_token_secret, timeout=60, retry_count=None, retry_in=180, client_args=None, handlers=None, chunk_size=1)
class timelinesStreamer(TwythonStreamer):
def __init__(self, app_key, app_secret, oauth_token, oauth_token_secret, timeout=300, retry_count=None, retry_in=10, client_args=None, handlers=None, chunk_size=1, session=None):
self.session = session
super(timelinesStreamer, self).__init__(app_key, app_secret, oauth_token, oauth_token_secret, timeout=60, retry_count=None, retry_in=180, client_args=None, handlers=None, chunk_size=1)
def on_error(self, status_code, data):
log.debug("%s: %s" % (status_code, data))
def check_tls(self, data):
for i in config.main["other_buffers"]["timelines"]:
for i in self.session.settings["other_buffers"]["timelines"]:
if data["user"]["screen_name"] == i:
tweet_event = event.event(event.EVT_OBJECT, 1)
tweet_event.SetItem(data)
announce = _(u"One tweet from %s") % (data["user"]["name"])
tweet_event.SetAnnounce(announce)
wx.PostEvent(self.parent.search_buffer(buffer_type="timeline", name_buffer=data["user"]["screen_name"]), tweet_event)
for i in range(0, self.parent.nb.GetPageCount()):
if self.parent.nb.GetPage(i).type == "list":
try:
self.parent.nb.GetPage(i).users.index(data["user"]["id"])
tweet_event = event.event(event.EVT_OBJECT, 1)
tweet_event.SetItem(data)
announce = _(u"One tweet from %s in the list %s") % (data["user"]["name"], self.parent.nb.GetPage(i).name_buffer[:-5])
tweet_event.SetAnnounce(announce)
wx.PostEvent(self.parent.nb.GetPage(i), tweet_event)
except ValueError:
pass
pub.sendMessage("item-in-timeline", data= data, user= self.session.db["user_name"], who= i)
def on_success(self, data):
# try:
if "text" in data:
self.check_tls(data)
# except:
# pass
class listsStreamer(timelinesStreamer):
def on_success(self, data):
try:
if data.has_key("text"):
self.check_tls(data)
if "text" in data:
pub.sendMessage("item-in-list", **{"data": data, "user": self.session.db["user_name"]})
except:
pass

View File

@ -1,104 +1,89 @@
# -*- coding: utf-8 -*-
from twitter import compose, utils
from twitter import utils
from twython import TwythonStreamer
import sound
from mysc import event
import wx
import config
from pubsub import pub
import logging as original_logger
log = original_logger.getLogger("MainStream")
import output
class streamer(TwythonStreamer):
def __init__(self, app_key, app_secret, oauth_token, oauth_token_secret, timeout=300, retry_count=None, retry_in=10, client_args=None, handlers=None, chunk_size=1, parent=None):
self.db = parent.db
self.parent = parent
TwythonStreamer.__init__(self, app_key, app_secret, oauth_token, oauth_token_secret, timeout=480, retry_count=0, retry_in=60, client_args=None, handlers=None, chunk_size=1)
self.muted_users = self.db.settings["muted_users"]
def __init__(self, app_key, app_secret, oauth_token, oauth_token_secret, sessionObject, *args, **kwargs):
super(streamer, self).__init__(app_key, app_secret, oauth_token, oauth_token_secret, *args, **kwargs)
self.session = sessionObject
self.muted_users = self.session.db["muted_users"]
# self.blocked_users = []
def on_error(self, status_code, data):
log.debug("Error %s: %s" % (status_code, data))
def get_user(self):
return self.session.db["user_name"]
def put_data(self, place, data):
if self.session.db.has_key(place):
if self.session.settings["general"]["reverse_timelines"] == False:
self.session.db[place].append(data)
else:
self.session.db[place].insert(0, data)
def block_user(self, data):
id = data["target"]["id"]
if id in self.friends:
self.friends.remove(id)
if config.main["other_buffers"]["show_blocks"] == True:
tweet_event = event.event(event.EVT_OBJECT, 1)
tweet_event.SetItem(data["target"])
wx.PostEvent(self.parent.search_buffer("people", "blocks"), tweet_event)
if self.session.settings["other_buffers"]["show_blocks"] == True:
self.session.db["blocked"]["items"].append(data["target"])
pub.sendMessage("blocked-user", data=data["target"], user=self.get_user())
def unblock(self, data):
if config.main["other_buffers"]["show_blocks"] == True:
item = utils.find_item(data["target"]["id"], self.db.settings["blocks"])
self.db.settings["blocks"].pop(item)
deleted_event = event.event(event.EVT_DELETED, 1)
deleted_event.SetItem(item)
wx.PostEvent(self.parent.search_buffer("people", "blocks"), deleted_event)
wx.PostEvent(self.parent, event.ResultEvent())
if self.session.settings["other_buffers"]["show_blocks"] == True:
item = utils.find_item(data["target"]["id"], self.session.db["blocked"]["items"])
self.session.db["blocked"]["items"].pop(item)
pub.sendMessage("unblocked-user", item=item, user=self.get_user())
def check_send(self, data):
if self.db.settings["user_name"] == data["user"]["screen_name"]:
tweet_event = event.event(event.EVT_OBJECT, 1)
tweet_event.SetItem(data)
wx.PostEvent(self.parent.search_buffer("buffer", "sent"), tweet_event)
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())
def check_favs(self, data):
if data["source"]["screen_name"] == self.db.settings["user_name"]:
tweet_event = event.event(event.EVT_OBJECT, 1)
tweet_event.SetItem(data["target_object"])
wx.PostEvent(self.parent.search_buffer("buffer", "favs"), tweet_event)
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())
def check_mentions(self, data):
if "@%s" % (self.db.settings["user_name"]) in data["text"]:
tweet_event = event.event(event.EVT_OBJECT, 1)
tweet_event.SetItem(data)
text = _(u"One mention from %s ") % (data["user"]["name"])
tweet_event.SetAnnounce(text)
wx.PostEvent(self.parent.search_buffer("buffer", "mentions"), tweet_event)
if "@%s" % (self.session.db["user_name"]) in data["text"]:
self.put_data("mentions", data)
pub.sendMessage("mention", data=data, user=self.get_user())
def process_dm(self, data):
if self.db.settings["user_name"] == data["direct_message"]["sender"]["screen_name"]:
tweet_event = event.event(event.EVT_OBJECT, 1)
tweet_event.SetItem(data["direct_message"])
wx.PostEvent(self.parent.search_buffer("buffer", "sent"), tweet_event)
if self.db.settings["user_name"] != data["direct_message"]["sender"]["screen_name"]:
tweet_event = event.event(event.EVT_OBJECT, 1)
tweet_event.SetItem(data["direct_message"])
text = _(u"One direct message")
tweet_event.SetAnnounce(text)
wx.PostEvent(self.parent.search_buffer("buffer", "direct_messages"), tweet_event)
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())
else:
self.put_data("direct_messages", data["direct_message"])
pub.sendMessage("direct-message", data=data["direct_message"], user=self.get_user())
def check_follower(self, data):
if data["target"]["screen_name"] == self.db.settings["user_name"]:
if config.main["other_buffers"]["show_followers"] == True:
tweet_event = event.event(event.EVT_OBJECT, 1)
tweet_event.SetItem(data["source"])
wx.PostEvent(self.parent.search_buffer("people", "followers"), tweet_event)
elif data["source"]["screen_name"] == self.db.settings["user_name"] and config.main["other_buffers"]["show_friends"] == True:
tweet_event = event.event(event.EVT_OBJECT, 1)
tweet_event.SetItem(data["target"])
wx.PostEvent(self.parent.search_buffer("people", "friends"), tweet_event)
if data["target"]["screen_name"] == self.session.db["user_name"]:
self.session.db["followers"]["items"].append(data["source"])
pub.sendMessage("follower", data=data["source"], user = self.get_user())
else:
self.session.db["friends"]["items"].append(data["target"])
pub.sendMessage("friend", data=data["target"], user=self.get_user())
###
def remove_fav(self, data):
if self.db.settings["user_name"] == data["source"]["screen_name"]:
self.db.settings.update()
item = utils.find_item(data["target_object"]["id"], self.db.settings["favs"])
self.db.settings["favs"].pop(item)
deleted_event = event.event(event.EVT_DELETED, 1)
deleted_event.SetItem(item)
wx.PostEvent(self.parent.search_buffer("buffer", "favs"), deleted_event)
if self.session.db["user_name"] == data["source"]["screen_name"]:
item = utils.find_item(data["target_object"]["id"], self.session.db["favourites"])
print item
self.session.db["favourites"].pop(item)
pub.sendMessage("unfavourite", item=item, user=self.get_user())
def remove_friend(self, data):
if config.main["other_buffers"]["show_friends"] == True:
item = utils.find_item(data["target"]["id"], self.db.settings["friends"])
if self.session.settings["other_buffers"]["show_friends"] == True:
item = utils.find_item(data["target"]["id"], self.session.db["friends"]["items"])
if item > 0:
deleted_event = event.event(event.EVT_DELETED, 1)
deleted_event.SetItem(item)
self.friends.pop(item)
self.db.settings["friends"].pop(item)
wx.PostEvent(self.parent.search_buffer("people", "friends"), deleted_event)
self.friends["items"].pop(item)
pub.sendMessage("unfollowing", item=item, user=self.get_user())
def on_success(self, data):
try:
@ -106,64 +91,46 @@ class streamer(TwythonStreamer):
self.process_dm(data)
elif "friends" in data:
self.friends = data["friends"]
elif "text" in data and utils.is_allowed(data) == True:
elif "text" in data:
if data["user"]["id"] in self.muted_users: return
self.check_mentions(data)
self.check_send(data)
if data["user"]["id"] in self.friends or data["user"]["screen_name"] == self.db.settings["user_name"]:
tweet_event = event.event(event.EVT_OBJECT, 1)
tweet_event.SetItem(data)
wx.PostEvent(self.parent.search_buffer("buffer", "home_timeline"), tweet_event)
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())
elif data.has_key("event"):
if "favorite" == data["event"] and config.main["other_buffers"]["show_favourites"] == True:
if "favorite" == data["event"] and self.session.settings["other_buffers"]["show_favourites"] == True:
self.check_favs(data)
elif "unfavorite" == data["event"] and config.main["other_buffers"]["show_favourites"] == True:
elif "unfavorite" == data["event"] and self.session.settings["other_buffers"]["show_favourites"] == True:
self.remove_fav(data)
elif "follow" == data["event"] and config.main["other_buffers"]["show_followers"] == True:
elif "follow" == data["event"] and self.session.settings["other_buffers"]["show_followers"] == True:
self.check_follower(data)
elif "unfollow" == data["event"] and config.main["other_buffers"]["show_followers"] == True:
elif "unfollow" == data["event"] and self.session.settings["other_buffers"]["show_followers"] == True:
self.remove_friend(data)
elif "block" == data["event"]:
self.block_user(data)
elif "unblock" in data["event"]:
elif "unblock" == data["event"]:
self.unblock(data)
elif "list_created" == data["event"]:
item = utils.find_item(data["target_object"]["id"], self.db.settings["lists"])
if item != None: self.db.settings["lists"].append(data["target_object"])
item = utils.find_item(data["target_object"]["id"], self.session.db["lists"])
if item != None: self.session.db["lists"].append(data["target_object"])
elif "list_destroyed" == data["event"]:
item = utils.find_item(data["target_object"]["id"], self.db.settings["lists"])
if item != None: self.db.settings["lists"].pop(item)
item = utils.find_item(data["target_object"]["id"], self.session.db["lists"])
if item != None: self.session.db["lists"].pop(item)
self.parent.remove_list(data["target_object"]["id"])
elif "list_member_added" == data["event"] and data["source"]["screen_name"] == self.db.settings["user_name"]:
if len(config.main["other_buffers"]["lists"]) > 0:
for i in range(0, self.parent.nb.GetPageCount()):
if self.parent.nb.GetPage(i).type == "list":
if str(data["target_object"]["id"]) == str(self.parent.nb.GetPage(i).argumento):
self.parent.nb.GetPage(i).users.append(data["target"]["id"])
wx.PostEvent(self.parent, event.ResultEvent())
elif "list_member_added" == data["event"] and data["target"]["screen_name"] == self.db.settings["user_name"]:
self.db.settings["lists"].append(data["target_object"])
elif "list_member_removed" == data["event"] and data["source"]["screen_name"] == self.db.settings["user_name"]:
if len(config.main["other_buffers"]["lists"]) > 0:
for i in range(0, self.parent.nb.GetPageCount()):
if self.parent.nb.GetPage(i).type == "list":
if str(data["target_object"]["id"]) == str(self.parent.nb.GetPage(i).argumento):
self.parent.nb.GetPage(i).users.remove(data["target"]["id"])
wx.PostEvent(self.parent, event.ResultEvent())
elif "list_member_removed" == data["event"] and data["target"] == self.db.settings["user_name"]:
elif "list_member_added" == data["event"] and data["source"]["screen_name"] == self.get_user():
pub.sendMessage("new-list-member-added", **{"id":str(data["target"]["id"]), "list":data["target_object"], "user":self.get_user()})
elif "list_member_added" == data["event"] and data["target"]["screen_name"] == self.get_user():
self.session.db["lists"].append(data["target_object"])
elif "list_member_removed" == data["event"] and data["source"]["screen_name"] == self.get_user():
pub.sendMessage("list-member-deleted", **{"id":str(data["target"]["id"]), "list":data["target_object"], "user":self.get_user()})
elif "list_member_removed" == data["event"] and data["target"] == self.get_user():
id = data["target_object"]["id"]
list = utils.find_item(id, self.db.settings["lists"])
if list != None: self.db.settings["lists"].pop(list)
self.parent.remove_list(data["target_object"]["id"])
if config.main["other_buffers"]["show_events"] == True:
evento = compose.compose_event(data, self.db.settings["user_name"])
tweet_event = event.event(event.EVT_OBJECT, 1)
tweet_event.SetItem(evento)
text = evento[1]
tweet_event.SetAnnounce(text)
# deleted_event = event.event(event.EVT_DELETED, 1)
# deleted_event.SetItem(evento)
wx.PostEvent(self.parent.search_buffer("event", "events"), tweet_event)
list = utils.find_item(id, self.session.db["lists"])
if list != None: self.session.db["lists"].pop(list)
pub.sendMessage("list-deleted", **{"item":list, "user":self.get_user()})
if self.session.settings["other_buffers"]["show_events"] == True:
pub.sendMessage("event", data= data, user= self.get_user())
# self.sound.play("new_event.ogg")
except:
except KeyboardInterrupt:
pass

View File

@ -6,11 +6,6 @@ import datetime
import time
import output
import gettext, paths, locale, gettext_windows
import config, languageHandler
if config.main != None:
languageHandler.setLanguage(config.main["general"]["language"])
else:
languageHandler.setLanguage("system")
import platform
system = platform.system()
@ -133,14 +128,14 @@ def translate_short(string):
chars = "abcdefghijklmnopqrstuvwxyz"
def compose_tweet(tweet, db):
def compose_tweet(tweet, db, relative_times):
""" It receives a tweet and returns a list with the user, text for the tweet or message, date and the client where user is."""
# original_date = datetime.datetime.strptime(translate_short(tweet["created_at"]).encode("utf-8"), "%a %b %d %H:%M:%S +0000 %Y")
original_date = datetime.datetime.strptime(tweet["created_at"], "%a %b %d %H:%M:%S +0000 %Y")
# else:
# original_date = datetime.datetime.strptime(tweet["created_at"], '%a %b %d %H:%M:%S +0000 %Y')
date = original_date-datetime.timedelta(seconds=-db.settings["utc_offset"])
if config.main["general"]["relative_times"] == True:
date = original_date-datetime.timedelta(seconds=-db["utc_offset"])
if relative_times == True:
ts = prettydate(original_date)
else:
# ts = translate(datetime.datetime.strftime(date, _("%A, %B %d, %Y at %I:%M:%S %p".encode("utf-8"))).decode("utf-8"))
@ -149,7 +144,7 @@ def compose_tweet(tweet, db):
text = StripChars(tweet["text"])
if tweet.has_key("sender"):
source = "DM"
if db.settings["user_name"] == tweet["sender"]["screen_name"]: user = _(u"Dm to %s ") % (tweet["recipient"]["name"],)
if db["user_name"] == tweet["sender"]["screen_name"]: user = _(u"Dm to %s ") % (tweet["recipient"]["name"],)
else: user = tweet["sender"]["name"]
elif tweet.has_key("user"):
user = tweet["user"]["name"]
@ -162,13 +157,13 @@ def compose_tweet(tweet, db):
try: text = text.replace(urls[url], tweet["entities"]["urls"][url]["expanded_url"])
except IndexError: pass
tweet["text"] = text
return [user+", ", tweet["text"], ts+", ", source]
return [user+", ", text, ts+", ", source]
def compose_followers_list(tweet, db):
def compose_followers_list(tweet, db, relative_time=True):
# original_date = datetime.datetime.strptime(translate_short(tweet["created_at"]).encode("utf-8"), '%a %b %d %H:%M:%S +0000 %Y')
original_date = datetime.datetime.strptime(tweet["created_at"], '%a %b %d %H:%M:%S +0000 %Y')
date = original_date-datetime.timedelta(seconds=-db.settings["utc_offset"])
if config.main["general"]["relative_times"] == True:
date = original_date-datetime.timedelta(seconds=-db["utc_offset"])
if relative_time == True:
ts = prettydate(original_date)
else:
ts = translate(datetime.datetime.strftime(date, _(u"%A, %B %d, %Y at %I:%M:%S %p")))
@ -177,8 +172,8 @@ def compose_followers_list(tweet, db):
if len(tweet["status"]) > 4:
# original_date2 = datetime.datetime.strptime(translate_short(tweet["status"]["created_at"]).encode("utf-8"), '%a %b %d %H:%M:%S +0000 %Y')
original_date2 = datetime.datetime.strptime(tweet["status"]["created_at"], '%a %b %d %H:%M:%S +0000 %Y')
date2 = original_date2-datetime.timedelta(seconds=-db.settings["utc_offset"])
if config.main["general"]["relative_times"]:
date2 = original_date2-datetime.timedelta(seconds=-db["utc_offset"])
if relative_time == True:
ts2 = prettydate(original_date2)
else:
ts2 = translate(datetime.datetime.strftime(date2, _(u"%A, %B %d, %Y at %I:%M:%S %p")))

View File

@ -1,259 +0,0 @@
# -*- config: utf-8 -*-
from twython import Twython, TwythonError
import config
#import sound
import time
import utils
friends_cursor = followers_cursor = None
def get_more_items(update_function, twitter_object, users=False, name=None, *args, **kwargs):
results = []
data = update_function(*args, **kwargs)
if users == True:
global friends_cursor, followers_cursor
if name == "friends":
friends_cursor = data["next_cursor"]
elif name == "followers":
followers_cursor = data["next_cursor"]
for i in data["users"]: results.append(i)
else:
results.extend(data[1:])
return results
def call_paged(update_function, twitter_object, *args, **kwargs):
max = int(config.main["general"]["max_api_calls"])-1
results = []
data = update_function(*args, **kwargs)
results.extend(data)
for i in range(0, max):
if i == 0: max_id = results[-1]["id"]
else: max_id = results[0]["id"]
data = update_function(max_id=max_id, *args, **kwargs)
results.extend(data)
results.reverse()
return results
def start_user_info(config, twitter):
f = twitter.twitter.get_account_settings()
sn = f["screen_name"]
config.settings["user_name"] = sn
config.settings["user_id"] = twitter.twitter.show_user(screen_name=sn)["id_str"]
try:
config.settings["utc_offset"] = f["time_zone"]["utc_offset"]
except KeyError:
config.settings["utc_offset"] = -time.timezone
get_lists(config, twitter)
get_muted_users(config, twitter)
def get_lists(config, twitter):
config.settings["lists"] = twitter.twitter.show_lists(reverse=True)
def get_muted_users(config, twitter):
config.settings["muted_users"] = twitter.twitter.get_muted_users_ids()["ids"]
def start_stream(db, twitter, name, function, param=None):
num = 0
if db.settings.has_key(name):
try:
if db.settings[name][0]["id"] > db.settings[name][-1]["id"]:
last_id = db.settings[name][0]["id"]
else:
last_id = db.settings[name][-1]["id"]
except IndexError:
pass
if param != None:
tl = call_paged(function, twitter, sinze_id=last_id, screen_name=param, count=config.main["general"]["max_tweets_per_call"])
else:
tl = call_paged(function, twitter, sinze_id=last_id, count=config.main["general"]["max_tweets_per_call"])
else:
if param != None:
tl = call_paged(function, twitter, screen_name=param, count=config.main["general"]["max_tweets_per_call"])
else:
tl = call_paged(function, twitter, count=config.main["general"]["max_tweets_per_call"])
db.settings[name] = []
last_id = 0
if len(db.settings[name]) > 0:
for i in tl:
if int(i["id"]) > int(last_id):
if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i)
else: db.settings[name].insert(0, i)
num = num+1
elif len(db.settings[name]) == 0:
for i in tl:
if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i)
else: db.settings[name].insert(0, i)
num = num+1
# db.settings.update()
return num
def start_followers(db, twitter, name, function, param=None):
global friends_cursor, followers_cursor
num = 0
db.settings[name] = []
# next_cursor = -1
# while(next_cursor):
tl = function(screen_name=param, count=config.main["general"]["max_tweets_per_call"])
for i in tl['users']:
if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i)
else: db.settings[name].insert(0, i)
num = num+1
# next_cursor = tl["next_cursor"]
db.settings[name].reverse()
# if config.main["streams"]["reverse_timelines"] == True: db.settings[name].reverse()
if name == "followers": followers_cursor = tl["next_cursor"]
elif name == "friends": friends_cursor = tl["next_cursor"]
return num
def get_users_list(twitter, list_id):
answers = []
next_cursor = -1
while(next_cursor):
users = twitter.twitter.get_list_members(list_id=list_id, cursor=next_cursor, include_entities=False, skip_status=True)
for i in users['users']:
answers.append(i["id"])
next_cursor = users["next_cursor"]
return answers
def update_stream(config, twitter, name, function, param=None, sndFile=""):
num = 0
sounded = False
tl = function(sinze_id=config.settings[name][-1]["id"], screen_name=param, count=config.main["general"]["max_tweets_per_call"])
tl.reverse()
for i in tl:
if i["id"] > config.settings[name][-1]["id"]:
config.settings[name].append(i)
sounded = True
num = num+1
if sounded == True:
sound.play(sndFile)
return num
def start_sent(db, twitter, name, function, param=None):
num = 0
if db.settings.has_key(name):
try:
if db.settings[name][0]["id"] > db.settings[name][-1]["id"]:
last_id = db.settings[name][0]["id"]
else:
last_id = db.settings[name][-1]["id"]
except IndexError:
return 0
if param != None:
tl = function(sinze_id=last_id, screen_name=param, count=config.main["general"]["max_tweets_per_call"])
tl2 = twitter.twitter.get_sent_messages(sinze_id=last_id, count=config.main["general"]["max_tweets_per_call"])
else:
tl = function(sinze_id=last_id, count=config.main["general"]["max_tweets_per_call"])
tl2 = twitter.twitter.get_sent_messages(sinze_id=last_id, count=config.main["general"]["max_tweets_per_call"])
else:
if param != None:
tl = function(screen_name=param, count=config.main["general"]["max_tweets_per_call"])
tl2 = twitter.twitter.get_sent_messages(count=config.main["general"]["max_tweets_per_call"])
else:
tl = function(count=config.main["general"]["max_tweets_per_call"])
tl2 = twitter.twitter.get_sent_messages(sinze_id=last_id, count=config.main["general"]["max_tweets_per_call"])
db.settings[name] = []
last_id = 0
tl.extend(tl2)
# tl.reverse()
tl.sort(key=lambda tup: tup["id"])
if len(db.settings[name]) > 0:
for i in tl:
# print last_id, i["id"]
if int(i["id"]) > int(last_id):
if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i)
else: db.settings[name].insert(0, i)
num = num+1
elif len(db.settings[name]) == 0:
for i in tl:
if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i)
else: db.settings[name].insert(0, i)
num = num+1
return num
def start_list(db, twitter, name, list_id):
num = 0
if db.settings.has_key(name):
try:
if db.settings[name][0]["id"] > db.settings[name][-1]["id"]:
last_id = db.settings[name][0]["id"]
else:
last_id = db.settings[name][-1]["id"]
except IndexError:
pass
tl = twitter.twitter.get_list_statuses(list_id=list_id, count=200)
else:
tl = twitter.twitter.get_list_statuses(list_id=list_id, count=200)
tl.reverse()
db.settings[name] = []
last_id = 0
if len(db.settings[name]) > 0:
for i in tl:
if int(i["id"]) > int(last_id):
if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i)
else: db.settings[name].insert(0, i)
num = num+1
elif len(db.settings[name]) == 0:
for i in tl:
if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i)
else: db.settings[name].insert(0, i)
num = num+1
db.settings.update()
return num
def search(db, twitter, name, *args, **kwargs):
num = 0
if db.settings.has_key(name) == False:
db.settings[name] = []
tl = twitter.twitter.search(*args, **kwargs)
tl["statuses"].reverse()
if len(db.settings[name]) > 0:
for i in tl["statuses"]:
if utils.find_item(i["id"], db.settings[name]) == None:
if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i)
else: db.settings[name].insert(0, i)
num = num+1
elif len(db.settings[name]) == 0:
for i in tl["statuses"]:
if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i)
else: db.settings[name].insert(0, i)
num = num+1
return num
def search_users(db, twitter, name, *args, **kwargs):
num = 0
if db.settings.has_key(name) == False:
db.settings[name] = []
tl = twitter.twitter.search_users(*args, **kwargs)
tl.reverse()
if len(db.settings[name]) > 0:
for i in tl:
if utils.find_item(i["id"], db.settings[name]) == None:
if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i)
else: db.settings[name].insert(0, i)
num = num+1
elif len(db.settings[name]) == 0:
for i in tl:
if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i)
else: db.settings[name].insert(0, i)
num = num+1
return num
def get_favourites_timeline(db, twitter, name, param, *args, **kwargs):
num = 0
if db.settings.has_key(name) == False:
db.settings[name] = []
tl = twitter.twitter.get_favorites(screen_name=param, *args, **kwargs)
tl.reverse()
if len(db.settings[name]) > 0:
for i in tl:
if utils.find_item(i["id"], db.settings[name]) == None:
if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i)
else: db.settings[name].insert(0, i)
num = num+1
elif len(db.settings[name]) == 0:
for i in tl:
if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i)
else: db.settings[name].insert(0, i)
num = num+1
return num

View File

@ -1,83 +1,29 @@
# -*- coding: utf-8 -*-
import BaseHTTPServer
import webbrowser
from urlparse import urlparse, parse_qs
from twython import Twython, TwythonError
import config
import application
import output
import sound
import time
logged = False
verifier = None
class handler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(self):
global logged
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
logged = True
params = parse_qs(urlparse(self.path).query)
global verifier
verifier = params.get('oauth_verifier', [None])[0]
self.wfile.write("You have successfully logged in to Twitter with TW Blue. "
"You can close this window now.")
import authorisationHandler
class twitter(object):
def login(self, user_key=None, user_secret=None):
if user_key != None and user_secret != None:
self.twitter = Twython(application.app_key, application.app_secret, user_key, user_secret)
elif config.main != None:
self.twitter = Twython(application.app_key, application.app_secret, config.main["twitter"]["user_key"], config.main["twitter"]["user_secret"])
else:
self.twitter = Twython(application.app_key, application.app_secret, self.final_step['oauth_token'], self.final_step['oauth_token_secret'])
def login(self, user_key, user_secret):
self.twitter = Twython(application.app_key, application.app_secret, user_key, user_secret)
self.credentials = self.twitter.verify_credentials()
def authorise(self):
httpd = BaseHTTPServer.HTTPServer(('127.0.0.1', 8080), handler)
def authorise(self, settings):
httpd = BaseHTTPServer.HTTPServer(('127.0.0.1', 8080), authorisationHandler.handler)
twitter = Twython(application.app_key, application.app_secret)
auth = twitter.get_authentication_tokens("http://127.0.0.1:8080")
webbrowser.open_new_tab(auth['auth_url'])
global logged, verifier
while logged == False:
# global logged, verifier
while authorisationHandler.logged == False:
httpd.handle_request()
self.twitter = Twython(application.app_key, application.app_secret, auth['oauth_token'], auth['oauth_token_secret'])
final = self.twitter.get_authorized_tokens(verifier)
self.save_configuration(final["oauth_token"], final["oauth_token_secret"])
final = self.twitter.get_authorized_tokens(authorisationHandler.verifier)
self.save_configuration(settings, final["oauth_token"], final["oauth_token_secret"])
def save_configuration(self, user_key=None, user_secret=None):
if user_key != None and user_secret != None:
config.main["twitter"]["user_key"] = user_key
config.main["twitter"]["user_secret"] = user_secret
else:
config.main['twitter']['user_key'] = self.final_step['oauth_token']
config.main['twitter']['user_secret'] = self.final_step['oauth_token_secret']
config.main.write()
def api_call(self, call_name, action="", _sound=None, report_success=False, report_failure=True, preexec_message="", *args, **kwargs):
finished = False
tries = 0
if preexec_message:
output.speak(preexec_message, True)
while finished==False and tries < 25:
try:
val = getattr(self.twitter, call_name)(*args, **kwargs)
finished = True
except TwythonError as e:
# if hasattr(e, 'reason') and e.reason.startswith("Failed to send request"):
output.speak(e.message)
if report_failure and hasattr(e, 'message'):
output.speak(_("%s failed. Reason: %s") % (action, e.message))
finished = True
except:
tries = tries + 1
time.sleep(5)
# raise e
if report_success:
output.speak(_("%s succeeded.") % action)
if _sound != None: sound.player.play(_sound)
# return val
def save_configuration(self, settings, user_key, user_secret):
settings["twitter"]["user_key"] = user_key
settings["twitter"]["user_secret"] = user_secret
settings.write()

View File

@ -9,8 +9,6 @@ __version__ = 0.1
__doc__ = "Find urls in tweets and #audio hashtag."
url_re = re.compile(r"(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'\".,<>?«»“”‘’]))")
#"(?:\w+://|www\.)[^ ,.?!#%=+][^ ]*")
#bad_chars = '\'\\.,[](){}:;"'
url_re2 = re.compile("(?:\w+://|www\.)[^ ,.?!#%=+][^ ]*")
bad_chars = '\'\\.,[](){}:;"'
@ -20,13 +18,6 @@ def find_urls_in_text(text):
def find_urls (tweet):
urls = []
# for i in tweet["entities"]["urls"]:
# unshortened = url_shortener.unshorten(i["expanded_url"])
# if unshortened == None:
# urls.append(i["expanded_url"])
# else:
# urls.append(unshortened)
# return urls
return [s[0] for s in url_re.findall(tweet["text"])]
def find_item(id, listItem):
@ -44,9 +35,6 @@ def find_previous_reply(id, listItem):
return None
def find_next_reply(id, listItem):
# r = range(0, len(listItem))
# r.reverse()
# for i in r:
for i in range(0, len(listItem)):
if listItem[i]["in_reply_to_status_id_str"] == str(id): return i
return None

View File

@ -124,7 +124,6 @@ class TwythonStreamer(object):
except requests.exceptions.Timeout:
self.on_timeout()
else:
# self.connected = False
if response.status_code != 200:
self.on_error(response.status_code, response.content)

View File

@ -0,0 +1,3 @@
import platform
if platform.system() == "Windows":
from wxUtils import *

View File

@ -0,0 +1,17 @@
import wx
# Code responses for WX dialogs.
OK = wx.ID_OK
CANCEL = wx.ID_CANCEL
CLOSE = wx.ID_CLOSE
YES = wx.ID_YES
NO = wx.ID_NO
#events
CLOSE_EVENT = wx.EVT_CLOSE
def exit_application():
wx.GetApp().ExitMainLoop()
def connect_event(parent, event, func):
return getattr(parent, "Bind")(event, func)

1
src/wxUI/__init__.py Normal file
View File

@ -0,0 +1 @@
# -*- coding: utf-8 -*-

View File

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
from base import basePanel
from dm import dmPanel
from events import eventsPanel
from favourites import favsPanel
from lists import listPanel
from panels import accountPanel, emptyPanel
from people import peoplePanel
from tweet_searches import searchPanel
from user_searches import searchUsersPanel

32
src/wxUI/buffers/base.py Normal file
View File

@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
import wx
from multiplatform_widgets import widgets
class basePanel(wx.Panel):
def create_list(self):
self.list = widgets.list(self, _(u"User"), _(u"Text"), _(u"Date"), _(u"Client"), style=wx.LC_REPORT|wx.LC_SINGLE_SEL|wx.LC_VRULES)
self.list.set_windows_size(0, 30)
self.list.set_windows_size(1, 160)
self.list.set_windows_size(2, 55)
self.list.set_windows_size(3, 42)
self.list.set_size()
def __init__(self, parent, name):
super(basePanel, self).__init__(parent)
self.name = name
self.type = "baseBuffer"
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.create_list()
self.btn = wx.Button(self, -1, _(u"Tweet"))
self.retweetBtn = wx.Button(self, -1, _(u"Retweet"))
self.responseBtn = wx.Button(self, -1, _(u"Reply"))
self.dmBtn = wx.Button(self, -1, _(u"Direct message"))
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
btnSizer.Add(self.btn, 0, wx.ALL, 5)
btnSizer.Add(self.retweetBtn, 0, wx.ALL, 5)
btnSizer.Add(self.responseBtn, 0, wx.ALL, 5)
btnSizer.Add(self.dmBtn, 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)

11
src/wxUI/buffers/dm.py Normal file
View File

@ -0,0 +1,11 @@
# -*- coding: utf-8 -*-
import wx
from base import basePanel
class dmPanel(basePanel):
def __init__(self, parent, name):
""" Class to DM'S. Reply and retweet buttons are not showed and they have your delete method for dm's."""
super(dmPanel, self).__init__(parent, name)
self.retweetBtn.Disable()
self.responseBtn.Disable()
self.type = "dm"

View File

@ -0,0 +1,15 @@
# -*- coding: utf-8 -*-
import wx
from multiplatform_widgets import widgets
class eventsPanel(wx.Panel):
""" Buffer to show events. Different than tweets or people."""
def __init__(self, parent, name):
self.type = "event"
super(eventsPanel, self).__init__(parent)
self.name = name
sizer = wx.BoxSizer()
self.list = widgets.list(self, _(u"Date"), _(u"Event"), size=(600,600), style=wx.LC_REPORT|wx.LC_SINGLE_SEL|wx.LC_VRULES)
self.tweet = wx.Button(self, -1, _(u"Tweet"))
self.delete_event = wx.Button(self, -1, _(u"Remove event"))

View File

@ -0,0 +1,8 @@
# -*- coding: utf-8 -*-
import wx
from base import basePanel
class favsPanel(basePanel):
def __init__(self, parent, name):
super(favsPanel, self).__init__(parent, name)
self.type = "favourites_timeline"

View File

@ -0,0 +1,9 @@
# -*- coding: utf-8 -*-
import wx
from base import basePanel
class listPanel(basePanel):
def __init__(self, parent, name):
super(listPanel, self).__init__(parent, name)
self.type = "list"
self.users = []

View File

@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
import wx
from multiplatform_widgets import widgets
class accountPanel(wx.Panel):
def __init__(self, parent, name=None):
super(accountPanel, self).__init__(parent=parent)
self.name = name
self.type = "account"
sizer = wx.BoxSizer(wx.VERTICAL)
self.list = widgets.list(self, _(u"Announce"))
sizer.Add(self.list.list, 0, wx.ALL, 5)
self.SetSizer(sizer)
class emptyPanel(accountPanel):
def __init__(self, parent, name):
super(emptyPanel, self).__init__(parent=parent, name=name)
self.type = "empty"

View File

@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
import wx
from multiplatform_widgets import widgets
from base import basePanel
class peoplePanel(basePanel):
""" Buffer used to show people."""
def create_list(self):
self.list = widgets.list(self, _(u"User"), style=wx.LC_REPORT|wx.LC_SINGLE_SEL, size=(800, 800))
def __init__(self, parent, name):
super(peoplePanel, self).__init__(parent, name)
self.type = "people"
self.responseBtn.SetLabel(_(u"Mention"))
self.retweetBtn.Disable()

View File

@ -0,0 +1,8 @@
# -*- coding: utf-8 -*-
import wx
from base import basePanel
class searchPanel(basePanel):
def __init__(self, parent, name):
super(searchPanel, self).__init__(parent, name)
self.type = "search"

View File

@ -0,0 +1,14 @@
# -*- coding: utf-8 -*-
import wx
from tweet_searches import searchPanel
from multiplatform_widgets import widgets
class searchUsersPanel(searchPanel):
def create_list(self):
""" Returns the list for put the tweets here."""
self.list = widgets.list(self, _(u"User"), style=wx.LC_REPORT|wx.LC_SINGLE_SEL, size=(800, 800))
def __init__(self, parent, name):
super(searchUsersPanel, self).__init__(parent, name)
self.create_list()
self.type = "user_searches"

View File

@ -0,0 +1 @@
import baseDialog, configuration, follow, lists, message, search, show_user, update_profile, urlList

View File

@ -0,0 +1,16 @@
import wx
class BaseWXDialog(wx.Dialog):
def __init__(self, *args, **kwargs):
super(BaseWXDialog, self).__init__(*args, **kwargs)
def get_response(self):
return self.ShowModal()
def get(self, control):
if hasattr(self, control):
control = getattr(self, control)
if hasattr(control, "GetValue"): return getattr(control, "GetValue")()
elif hasattr(control, "GetLabel"): return getattr(control, "GetLabel")()
else: return -1
else: return 0

View File

@ -0,0 +1,182 @@
# -*- coding: utf-8 -*-
import baseDialog
import wx
import logging as original_logger
class general(wx.Panel, baseDialog.BaseWXDialog):
def __init__(self, parent, languages):
super(general, self).__init__(parent)
sizer = wx.BoxSizer(wx.VERTICAL)
language = wx.StaticText(self, -1, _(u"Language"))
self.language = wx.ListBox(self, -1, choices=languages)
self.language.SetSize(self.language.GetBestSize())
langBox = wx.BoxSizer(wx.HORIZONTAL)
langBox.Add(language, 0, wx.ALL, 5)
langBox.Add(self.language, 0, wx.ALL, 5)
sizer.Add(langBox, 0, wx.ALL, 5)
self.relative_time = wx.CheckBox(self, -1, _(U"Relative times"))
sizer.Add(self.relative_time, 0, wx.ALL, 5)
self.disable_sapi5 = wx.CheckBox(self, -1, _(u"Activate Sapi5 when any other screen reader is not being run"))
sizer.Add(self.disable_sapi5, 0, wx.ALL, 5)
self.show_gui = wx.CheckBox(self, -1, _(u"Activate the auto-start of the invisible interface"))
sizer.Add(self.show_gui, 0, wx.ALL, 5)
apiCallsBox = wx.BoxSizer(wx.HORIZONTAL)
apiCallsBox.Add(wx.StaticText(self, -1, _(u"API calls when the stream is started (One API call equals to 200 tweetts, two API calls equals 400 tweets, etc):")), 0, wx.ALL, 5)
self.apiCalls = wx.SpinCtrl(self, -1)
self.apiCalls.SetRange(1, 10)
self.apiCalls.SetSize(self.apiCalls.GetBestSize())
apiCallsBox.Add(self.apiCalls, 0, wx.ALL, 5)
sizer.Add(apiCallsBox, 0, wx.ALL, 5)
tweetsPerCallBox = wx.BoxSizer(wx.HORIZONTAL)
tweetsPerCallBox.Add(wx.StaticText(self, -1, _(u"Items on each API call")), 0, wx.ALL, 5)
self.itemsPerApiCall = wx.SpinCtrl(self, -1)
self.itemsPerApiCall.SetRange(0, 200)
self.itemsPerApiCall.SetSize(self.itemsPerApiCall.GetBestSize())
tweetsPerCallBox.Add(self.itemsPerApiCall, 0, wx.ALL, 5)
sizer.Add(tweetsPerCallBox, 0, wx.ALL, 5)
self.reverse_timelines = wx.CheckBox(self, -1, _(u"Inverted buffers: The newest tweets will be shown at the beginning of the lists while the oldest at the end"))
sizer.Add(self.reverse_timelines, 0, wx.ALL, 5)
self.SetSizer(sizer)
class other_buffers(wx.Panel):
def __init__(self, parent):
super(other_buffers, self).__init__(parent)
sizer = wx.BoxSizer(wx.VERTICAL)
self.followers = wx.CheckBox(self, -1, _(u"Show followers"))
sizer.Add(self.followers, 0, wx.ALL, 5)
self.friends = wx.CheckBox(self, -1, _(u"Show friends"))
sizer.Add(self.friends, 0, wx.ALL, 5)
self.favs = wx.CheckBox(self, -1, _(u"Show favourites"))
sizer.Add(self.favs, 0, wx.ALL, 5)
self.blocks = wx.CheckBox(self, -1, _(u"Show blocked users"))
sizer.Add(self.blocks, 0, wx.ALL, 5)
self.mutes = wx.CheckBox(self, -1, _(u"Show muted users"))
sizer.Add(self.mutes, 0, wx.ALL, 5)
self.events = wx.CheckBox(self, -1, _(u"Show events"))
sizer.Add(self.events, 0, wx.ALL, 5)
self.SetSizer(sizer)
class ignoredClients(wx.Panel):
def __init__(self, parent, choices):
super(ignoredClients, self).__init__(parent=parent)
sizer = wx.BoxSizer(wx.VERTICAL)
label = wx.StaticText(self, -1, _(u"Ignored clients"))
self.clients = wx.ListBox(self, -1, choices=choices)
self.clients.SetSize(self.clients.GetBestSize())
clientsBox = wx.BoxSizer(wx.HORIZONTAL)
clientsBox.Add(label, 0, wx.ALL, 5)
clientsBox.Add(self.clients, 0, wx.ALL, 5)
add = wx.Button(self, -1, _(u"Add client"))
remove = wx.Button(self, -1, _(u"Remove client"))
btnBox = wx.BoxSizer(wx.HORIZONTAL)
btnBox.Add(add, 0, wx.ALL, 5)
btnBox.Add(remove, 0, wx.ALL, 5)
sizer.Add(clientsBox, 0, wx.ALL, 5)
sizer.Add(btnBox, 0, wx.ALL, 5)
self.SetSizer(sizer)
class sound(wx.Panel):
def __init__(self, parent, input_devices, output_devices, soundpacks):
wx.Panel.__init__(self, parent)
sizer = wx.BoxSizer(wx.VERTICAL)
volume = wx.StaticText(self, -1, _(u"Volume"))
self.volumeCtrl = wx.Slider(self)
self.volumeCtrl.SetRange(0, 100)
self.volumeCtrl.SetSize(self.volumeCtrl.GetBestSize())
volumeBox = wx.BoxSizer(wx.HORIZONTAL)
volumeBox.Add(volume, 0, wx.ALL, 5)
volumeBox.Add(self.volumeCtrl, 0, wx.ALL, 5)
sizer.Add(volumeBox, 0, wx.ALL, 5)
self.global_mute = wx.CheckBox(self, -1, _(u"Global mute"))
sizer.Add(self.global_mute, 0, wx.ALL, 5)
output_label = wx.StaticText(self, -1, _(u"Output device"))
self.output = wx.ComboBox(self, -1, choices=output_devices, style=wx.CB_READONLY)
self.output.SetSize(self.output.GetBestSize())
outputBox = wx.BoxSizer(wx.HORIZONTAL)
outputBox.Add(output_label, 0, wx.ALL, 5)
outputBox.Add(self.output, 0, wx.ALL, 5)
sizer.Add(outputBox, 0, wx.ALL, 5)
input_label = wx.StaticText(self, -1, _(u"Input device"))
self.input = wx.ComboBox(self, -1, choices=input_devices, style=wx.CB_READONLY)
self.input.SetSize(self.input.GetBestSize())
inputBox = wx.BoxSizer(wx.HORIZONTAL)
inputBox.Add(input_label, 0, wx.ALL, 5)
inputBox.Add(self.input, 0, wx.ALL, 5)
sizer.Add(inputBox, 0, wx.ALL, 5)
soundBox = wx.BoxSizer(wx.VERTICAL)
soundpack_label = wx.StaticText(self, -1, _(u"Sound pack"))
self.soundpack = wx.ComboBox(self, -1, choices=soundpacks, style=wx.CB_READONLY)
self.soundpack.SetSize(self.soundpack.GetBestSize())
soundBox.Add(soundpack_label, 0, wx.ALL, 5)
soundBox.Add(self.soundpack, 0, wx.ALL, 5)
sizer.Add(soundBox, 0, wx.ALL, 5)
self.SetSizer(sizer)
class audioServicesPanel(wx.Panel):
def __init__(self, parent):
super(audioServicesPanel, self).__init__(parent)
mainSizer = wx.BoxSizer(wx.VERTICAL)
apiKeyLabel = wx.StaticText(self, -1, _(u"If you've got a SndUp account, enter your API Key here. Whether the API Key is wrong, the App will fail to upload anything to the server. Whether there's no API Key here, then the audio files will be uploaded anonimously"))
self.apiKey = wx.TextCtrl(self, -1)
dc = wx.WindowDC(self.apiKey)
dc.SetFont(self.apiKey.GetFont())
self.apiKey.SetSize(dc.GetTextExtent("0"*100))
apiKeyBox = wx.BoxSizer(wx.HORIZONTAL)
apiKeyBox.Add(apiKeyLabel, 0, wx.ALL, 5)
apiKeyBox.Add(self.apiKey, 0, wx.ALL, 5)
mainSizer.Add(apiKeyBox, 0, wx.ALL, 5)
first_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.dropbox = wx.Button(self, -1)
first_sizer.Add(self.dropbox, 0, wx.ALL, 5)
mainSizer.Add(first_sizer, 0, wx.ALL, 5)
self.SetSizer(mainSizer)
class configurationDialog(wx.Dialog):
def __init__(self):
super(configurationDialog, self).__init__(None, -1)
self.panel = wx.Panel(self)
self.SetTitle(_(u"TW Blue preferences"))
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.notebook = wx.Notebook(self.panel)
def create_general(self, languageList):
self.general = general(self.notebook, languageList)
self.notebook.AddPage(self.general, _(u"General"))
self.general.SetFocus()
def create_other_buffers(self):
self.buffers = other_buffers(self.notebook)
self.notebook.AddPage(self.buffers, _(u"Show other buffers"))
def create_ignored_clients(self, ignored_clients_list):
self.ignored_clients = ignoredClients(self.notebook, ignored_clients_list)
self.notebook.AddPage(self.ignored_clients, _(u"Ignored clients"))
def create_sound(self, output_devices, input_devices, soundpacks):
self.sound = sound(self.notebook, output_devices, input_devices, soundpacks)
self.notebook.AddPage(self.sound, _(u"Sound"))
def create_audio_services(self):
self.services = audioServicesPanel(self.notebook)
self.notebook.AddPage(self.services, _(u"Audio Services"))
def realize(self):
self.sizer.Add(self.notebook, 0, wx.ALL, 5)
ok_cancel_box = wx.BoxSizer(wx.HORIZONTAL)
ok = wx.Button(self.panel, wx.ID_OK, _(u"Save"))
ok.SetDefault()
cancel = wx.Button(self.panel, wx.ID_CANCEL, _(u"Close"))
self.SetEscapeId(cancel.GetId())
ok_cancel_box.Add(ok, 0, wx.ALL, 5)
ok_cancel_box.Add(cancel, 0, wx.ALL, 5)
self.sizer.Add(ok_cancel_box, 0, wx.ALL, 5)
self.panel.SetSizer(self.sizer)
self.SetClientSize(self.sizer.CalcMin())
def get_value(self, panel, key):
p = getattr(self, panel)
return getattr(p, key).GetValue()
def set_value(self, panel, key):
p = getattr(self, panel)
getattr(self, p).SetValue(key)

View File

@ -0,0 +1,66 @@
# -*- coding: utf-8 -*-
import wx
class actionDialog(wx.Dialog):
def __init__(self, user=[], default="follow", *args, **kwargs):
super(actionDialog, self).__init__(parent=None, *args, **kwargs)
panel = wx.Panel(self)
userSizer = wx.BoxSizer()
self.SetTitle(_(u"Action"))
self.cb = wx.ComboBox(panel, -1, choices=user, value=user[0])
self.cb.SetFocus()
userSizer.Add(self.cb)
actionSizer = wx.BoxSizer(wx.VERTICAL)
label2 = wx.StaticText(panel, -1, _(u"Action"))
self.follow = wx.RadioButton(panel, -1, _(u"Follow"), style=wx.RB_GROUP)
self.unfollow = wx.RadioButton(panel, -1, _(u"Unfollow"))
self.mute = wx.RadioButton(panel, -1, _(u"Mute"))
self.unmute = wx.RadioButton(panel, -1, _(u"Unmute"))
self.block = wx.RadioButton(panel, -1, _(u"Block"))
self.unblock = wx.RadioButton(panel, -1, _(u"Unblock"))
self.reportSpam = wx.RadioButton(panel, -1, _(u"Report as spam"))
self.setup_default(default)
actionSizer.Add(label2)
actionSizer.Add(self.follow)
actionSizer.Add(self.unfollow)
actionSizer.Add(self.mute)
actionSizer.Add(self.unmute)
actionSizer.Add(self.block)
actionSizer.Add(self.unblock)
actionSizer.Add(self.reportSpam)
sizer = wx.BoxSizer(wx.VERTICAL)
ok = wx.Button(panel, wx.ID_OK, _(u"OK"))
ok.SetDefault()
cancel = wx.Button(panel, wx.ID_CANCEL, _(u"Close"))
btnsizer = wx.BoxSizer()
btnsizer.Add(ok)
btnsizer.Add(cancel)
sizer.Add(userSizer)
sizer.Add(actionSizer)
sizer.Add(btnsizer)
panel.SetSizer(sizer)
def get_action(self):
if self.follow.GetValue() == True: return "follow"
elif self.unfollow.GetValue() == True: return "unfollow"
elif self.mute.GetValue() == True: return "mute"
elif self.unmute.GetValue() == True: return "unmute"
elif self.reportSpam.GetValue() == True: return "report"
elif self.block.GetValue() == True: return "block"
elif self.unblock.GetValue() == True: return "unblock"
def setup_default(self, default):
if default == "follow":
self.follow.SetValue(True)
elif default == "unfollow":
self.unfollow.SetValue(True)
elif default == "mute":
self.mute.SetValue(True)
elif default == "unmute":
self.unmute.SetValue(True)
elif default == "report":
self.reportSpam.SetValue(True)
elif default == "block":
self.block.SetValue(True)
elif default == "unblock":
self.unblock.SetValue(True)

123
src/wxUI/dialogs/lists.py Normal file
View File

@ -0,0 +1,123 @@
# -*- coding: utf-8 -*-
import wx
from multiplatform_widgets import widgets
class listViewer(wx.Dialog):
def __init__(self, *args, **kwargs):
super(listViewer, self).__init__(parent=None, *args, **kwargs)
self.SetTitle(_(u"Lists manager"))
panel = wx.Panel(self)
label = wx.StaticText(panel, -1, _(u"Lists"))
self.lista = widgets.list(panel, _(u"List"), _(u"Description"), _(u"Owner"), _(u"Members"), _(u"mode"), size=(800, 800), style=wx.LC_REPORT|wx.LC_SINGLE_SEL)
self.lista.list.SetFocus()
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(label)
sizer.Add(self.lista.list)
self.createBtn = wx.Button(panel, wx.NewId(), _(u"Create a new list"))
self.editBtn = wx.Button(panel, -1, _(u"Edit"))
self.deleteBtn = wx.Button(panel, -1, _(u"Remove"))
self.view = wx.Button(panel, -1, _(u"Open in buffer"))
# self.members = wx.Button(panel, -1, _(u"View members"))
# self.members.Disable()
# self.subscriptors = wx.Button(panel, -1, _(u"View subscribers"))
# self.subscriptors.Disable()
# self.get_linkBtn = wx.Button(panel, -1, _(u"Get link for the list"))
# self.get_linkBtn.Bind(wx.EVT_BUTTON, self.onGetLink)
self.cancelBtn = wx.Button(panel, wx.ID_CANCEL)
btnSizer = wx.BoxSizer()
btnSizer.Add(self.createBtn)
btnSizer.Add(self.editBtn)
btnSizer.Add(self.cancelBtn)
panel.SetSizer(sizer)
def populate_list(self, lists):
for item in lists:
self.lista.insert_item(False, *item)
def get_item(self):
return self.lista.get_selected()
class userListViewer(listViewer):
def __init__(self, username, *args, **kwargs):
self.username = username
super(userListViewer, self).__init__(*args, **kwargs)
self.SetTitle(_(u"Viewing lists for %s") % (self.username))
self.createBtn.SetLabel(_(u"Subscribe"))
self.deleteBtn.SetLabel(_(u"Unsubscribe"))
self.editBtn.Disable()
self.view.Disable()
class createListDialog(wx.Dialog):
def __init__(self, *args, **kwargs):
super(createListDialog, self).__init__(*args, **kwargs)
self.SetTitle(_(u"Create a new list"))
panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
name = wx.StaticText(panel, -1, _(u"Name (20 characters maximun)"))
self.name = wx.TextCtrl(panel, -1)
nameSizer = wx.BoxSizer(wx.HORIZONTAL)
nameSizer.Add(name)
nameSizer.Add(self.name)
description = wx.StaticText(panel, -1, _(u"Description"))
self.description = wx.TextCtrl(panel, -1)
descriptionSizer = wx.BoxSizer(wx.HORIZONTAL)
descriptionSizer.Add(description)
descriptionSizer.Add(self.description)
mode = wx.StaticText(panel, -1, _(u"Mode"))
self.public = wx.RadioButton(panel, -1, _(u"Public"), style=wx.RB_GROUP)
self.private = wx.RadioButton(panel, -1, _(u"Private"))
modeBox = wx.BoxSizer(wx.HORIZONTAL)
modeBox.Add(mode)
modeBox.Add(self.public)
modeBox.Add(self.private)
ok = wx.Button(panel, wx.ID_OK)
ok.SetDefault()
cancel = wx.Button(panel, wx.ID_CANCEL)
btnBox = wx.BoxSizer(wx.HORIZONTAL)
btnBox.Add(ok)
btnBox.Add(cancel)
sizer.Add(nameSizer)
sizer.Add(descriptionSizer)
sizer.Add(modeBox)
sizer.Add(btnBox)
def get(self, field):
return getattr(self, field).GetValue()
class editListDialog(createListDialog):
def __init__(self, list, *args, **kwargs):
super(editListDialog, self).__init__(*args, **kwargs)
self.SetTitle(_(u"Editing the list %s") % (list["name"]))
self.name.ChangeValue(list["name"])
self.description.ChangeValue(list["description"])
if list["mode"] == "public":
self.public.SetValue(True)
else:
self.private.SetValue(True)
class addUserListDialog(listViewer):
def __init__(self, *args, **kwargs):
super(addUserListDialog, self).__init__(*args, **kwargs)
self.SetTitle(_(u"Select a list to add the user"))
self.createBtn.SetLabel(_(u"Add"))
self.createBtn.SetDefault()
self.editBtn.Disable()
self.view.Disable()
# self.subscriptors.Disable()
# self.members.Disable()
self.deleteBtn.Disable()
class removeUserListDialog(listViewer):
def __init__(self, *args, **kwargs):
super(removeUserListDialog, self).__init__(*args, **kwargs)
self.SetTitle(_(u"Select a list to remove the user"))
self.createBtn.SetLabel(_(u"Remove"))
self.createBtn.SetDefault()
self.editBtn.Disable()
self.view.Disable()
# self.subscriptors.Disable()
# self.members.Disable()
self.deleteBtn.Disable()

163
src/wxUI/dialogs/message.py Normal file
View File

@ -0,0 +1,163 @@
# -*- coding: utf-8 -*-
import wx
import baseDialog
class textLimited(baseDialog.BaseWXDialog):
def __init__(self, *args, **kwargs):
super(textLimited, self).__init__(parent=None, *args, **kwargs)
def createTextArea(self, message="", text=""):
self.panel = wx.Panel(self)
self.label = wx.StaticText(self.panel, -1, message)
self.SetTitle(str(len(text)))
self.text = wx.TextCtrl(self.panel, -1, text)
font = self.text.GetFont()
dc = wx.WindowDC(self.text)
dc.SetFont(font)
x, y = dc.GetTextExtent("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
self.text.SetSize((x, y))
self.text.SetFocus()
self.textBox = wx.BoxSizer(wx.HORIZONTAL)
self.textBox.Add(self.label, 0, wx.ALL, 5)
self.textBox.Add(self.text, 0, wx.ALL, 5)
def get_text(self):
return self.text.GetValue()
def onSelect(self, ev):
self.text.SelectAll()
class tweet(textLimited):
def createControls(self, message, title, text):
self.mainBox = wx.BoxSizer(wx.VERTICAL)
self.createTextArea(message, text)
self.mainBox.Add(self.textBox, 0, wx.ALL, 5)
self.upload_image = wx.Button(self.panel, -1, _(u"Upload a picture"), size=wx.DefaultSize)
self.spellcheck = wx.Button(self.panel, -1, _("Spelling correction"), size=wx.DefaultSize)
self.attach = wx.Button(self.panel, -1, _(u"Attach audio"), size=wx.DefaultSize)
self.shortenButton = wx.Button(self.panel, -1, _(u"Shorten URL"), size=wx.DefaultSize)
self.unshortenButton = wx.Button(self.panel, -1, _(u"Expand URL"), size=wx.DefaultSize)
self.shortenButton.Disable()
self.unshortenButton.Disable()
self.translateButton = wx.Button(self.panel, -1, _(u"Translate message"), size=wx.DefaultSize)
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)
self.buttonsBox1 = wx.BoxSizer(wx.HORIZONTAL)
self.buttonsBox1.Add(self.upload_image, 0, wx.ALL, 5)
self.buttonsBox1.Add(self.spellcheck, 0, wx.ALL, 5)
self.buttonsBox1.Add(self.attach, 0, wx.ALL, 5)
self.mainBox.Add(self.buttonsBox1, 0, wx.ALL, 5)
self.buttonsBox2 = wx.BoxSizer(wx.HORIZONTAL)
self.buttonsBox2.Add(self.shortenButton, 0, wx.ALL, 5)
self.buttonsBox2.Add(self.unshortenButton, 0, wx.ALL, 5)
self.buttonsBox2.Add(self.translateButton, 0, wx.ALL, 5)
self.mainBox.Add(self.buttonsBox2, 0, wx.ALL, 5)
self.ok_cancelSizer = wx.BoxSizer(wx.HORIZONTAL)
self.ok_cancelSizer.Add(self.okButton, 0, wx.ALL, 5)
self.ok_cancelSizer.Add(cancelButton, 0, wx.ALL, 5)
self.mainBox.Add(self.ok_cancelSizer)
selectId = wx.NewId()
self.Bind(wx.EVT_MENU, self.onSelect, id=selectId)
self.accel_tbl = wx.AcceleratorTable([
(wx.ACCEL_CTRL, ord('A'), selectId),
])
self.SetAcceleratorTable(self.accel_tbl)
self.panel.SetSizer(self.mainBox)
def __init__(self, message, title, text):
super(tweet, self).__init__()
self.createControls(message, title, text)
# self.onTimer(wx.EVT_CHAR_HOOK)
self.SetClientSize(self.mainBox.CalcMin())
class dm(textLimited):
def createControls(self, message, title, users):
self.panel = wx.Panel(self)
self.mainBox = wx.BoxSizer(wx.VERTICAL)
label = wx.StaticText(self.panel, -1, _(u"Recipient"))
self.cb = wx.ComboBox(self.panel, -1, choices=users, value=users[0], size=wx.DefaultSize)
self.createTextArea(message, text="")
self.mainBox.Add(self.cb, 0, wx.ALL, 5)
self.mainBox.Add(self.textBox, 0, wx.ALL, 5)
self.spellcheck = wx.Button(self.panel, -1, _("Spelling correction"), size=wx.DefaultSize)
self.attach = wx.Button(self.panel, -1, _(u"Attach audio"), size=wx.DefaultSize)
self.shortenButton = wx.Button(self.panel, -1, _(u"Shorten URL"), size=wx.DefaultSize)
self.unshortenButton = wx.Button(self.panel, -1, _(u"Expand URL"), size=wx.DefaultSize)
self.shortenButton.Disable()
self.unshortenButton.Disable()
self.translateButton = wx.Button(self.panel, -1, _(u"Translate message"), size=wx.DefaultSize)
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)
self.buttonsBox = wx.BoxSizer(wx.HORIZONTAL)
self.buttonsBox.Add(self.spellcheck, 0, wx.ALL, 5)
self.buttonsBox.Add(self.attach, 0, wx.ALL, 5)
self.mainBox.Add(self.buttonsBox, 0, wx.ALL, 5)
self.buttonsBox1 = wx.BoxSizer(wx.HORIZONTAL)
self.buttonsBox1.Add(self.shortenButton, 0, wx.ALL, 5)
self.buttonsBox1.Add(self.unshortenButton, 0, wx.ALL, 5)
self.buttonsBox1.Add(self.translateButton, 0, wx.ALL, 5)
self.mainBox.Add(self.buttonsBox1, 0, wx.ALL, 5)
self.buttonsBox3 = wx.BoxSizer(wx.HORIZONTAL)
self.buttonsBox3.Add(self.okButton, 0, wx.ALL, 5)
self.buttonsBox3.Add(cancelButton, 0, wx.ALL, 5)
self.mainBox.Add(self.buttonsBox3, 0, wx.ALL, 5)
self.panel.SetSizer(self.mainBox)
def __init__(self, message, title, users):
super(dm, self).__init__()
self.createControls(message, title, users)
# self.onTimer(wx.EVT_CHAR_HOOK)
self.SetClientSize(self.mainBox.CalcMin())
class reply(tweet):
def __init__(self, message, title, text):
super(reply, self).__init__(message, title, text)
self.text.SetInsertionPoint(len(self.text.GetValue()))
self.mentionAll = wx.Button(self, -1, _(u"Mention to all"), size=wx.DefaultSize)
self.mentionAll.Disable()
self.buttonsBox1.Add(self.mentionAll, 0, wx.ALL, 5)
self.buttonsBox1.Layout()
self.mainBox.Layout()
self.SetClientSize(self.mainBox.CalcMin())
class viewTweet(wx.Dialog):
def __init__(self, tweet):
super(viewTweet, self).__init__(None, size=(850,850))
self.SetTitle(_(u"Tweet - %i characters ") % (len(tweet)))
panel = wx.Panel(self)
label = wx.StaticText(panel, -1, _(u"Tweet"))
self.text = wx.TextCtrl(panel, -1, tweet, style=wx.TE_READONLY|wx.TE_MULTILINE, size=(250, 180))
dc = wx.WindowDC(self.text)
dc.SetFont(self.text.GetFont())
(x, y, z) = dc.GetMultiLineTextExtent("0"*140)
self.text.SetSize((x, y))
self.text.SetFocus()
textBox = wx.BoxSizer(wx.HORIZONTAL)
textBox.Add(label, 0, wx.ALL, 5)
textBox.Add(self.text, 1, wx.EXPAND, 5)
mainBox = wx.BoxSizer(wx.VERTICAL)
mainBox.Add(textBox, 0, wx.ALL, 5)
spellcheck = wx.Button(panel, -1, _("Spelling correction"), size=wx.DefaultSize)
self.unshortenButton = wx.Button(panel, -1, _(u"Expand URL"), size=wx.DefaultSize)
self.unshortenButton.Disable()
translateButton = wx.Button(panel, -1, _(u"Translate message"), size=wx.DefaultSize)
cancelButton = wx.Button(panel, wx.ID_CANCEL, _(u"Close"), size=wx.DefaultSize)
buttonsBox = wx.BoxSizer(wx.HORIZONTAL)
buttonsBox.Add(spellcheck, 0, wx.ALL, 5)
buttonsBox.Add(self.unshortenButton, 0, wx.ALL, 5)
buttonsBox.Add(translateButton, 0, wx.ALL, 5)
buttonsBox.Add(cancelButton, 0, wx.ALL, 5)
mainBox.Add(buttonsBox, 0, wx.ALL, 5)
selectId = wx.NewId()
self.Bind(wx.EVT_MENU, self.onSelect, id=selectId)
self.accel_tbl = wx.AcceleratorTable([
(wx.ACCEL_CTRL, ord('A'), selectId),
])
self.SetAcceleratorTable(self.accel_tbl)
panel.SetSizer(mainBox)
self.SetClientSize(mainBox.CalcMin())
def onSelect(self, ev):
self.text.SelectAll()

View File

@ -1,24 +1,8 @@
# -*- coding: utf-8 -*-
############################################################
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################
import baseDialog
import wx
class searchDialog(wx.Dialog):
class searchDialog(baseDialog.BaseWXDialog):
def __init__(self):
super(searchDialog, self).__init__(None, -1)
panel = wx.Panel(self)
@ -45,4 +29,4 @@ class searchDialog(wx.Dialog):
btnsizer.Add(cancel, 0, wx.ALL, 5)
sizer.Add(btnsizer, 0, wx.ALL, 5)
panel.SetSizer(sizer)
self.SetClientSize(sizer.CalcMin())
self.SetClientSize(sizer.CalcMin())

View File

@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
import wx
class showUserProfile(wx.Dialog):
def __init__(self, screen_name):
super(showUserProfile, self).__init__(self, None, -1)
self.SetTitle(_(u"Information for %s") % (screen_name))
panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
static = wx.StaticText(panel, -1, _(u"Details"))
sizer.Add(static, 0, wx.ALL, 5)
text = wx.TextCtrl(panel, -1, style=wx.TE_MULTILINE|wx.TE_READONLY)
text.SetFocus()
sizer.Add(text, 0, wx.ALL|wx.EXPAND, 5)
self.url = wx.Button(panel, -1, _(u"Go to URL"), size=wx.DefaultSize)
self.url.Disable()
close = wx.Button(panel, wx.ID_CANCEL, _(u"Close"))
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
btnSizer.Add(self.url, 0, wx.ALL, 5)
btnSizer.Add(close, 0, wx.ALL, 5)
sizer.Add(btnSizer, 0, wx.ALL, 5)
text.ChangeValue(self.compose_string())
text.SetSize(text.GetBestSize())
panel.SetSizer(sizer)
self.SetClientSize(sizer.CalcMin())
def get_response(self):
return self.ShowModal()

View File

@ -1,28 +1,8 @@
# -*- coding: utf-8 -*-
############################################################
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################
import wx
from twython import TwythonError
class updateProfile(wx.Dialog):
def __init__(self, parent):
self.twitter = parent.twitter
self.parent = parent
super(updateProfile, self).__init__(parent=None, id=-1)
self.SetTitle(_(u"Update your profile"))
panel = wx.Panel(self)
@ -78,42 +58,18 @@ class updateProfile(wx.Dialog):
sizer.Add(btnBox, 0, wx.ALL, 5)
panel.SetSizer(sizer)
self.SetClientSize(sizer.CalcMin())
self.get_data()
def onUpload_picture(self, ev):
if self.upload_image.GetLabel() == _(u"Discard image"):
self.image = None
del self.file
output.speak(_(u"Discarded"))
self.upload_image.SetLabel(_(u"Upload a picture"))
self.controller.clear_file()
else:
openFileDialog = wx.FileDialog(self, _(u"Select the picture to be uploaded"), "", "", _("Image files (*.png, *.jpg, *.gif)|*.png; *.jpg; *.gif"), wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)
if openFileDialog.ShowModal() == wx.ID_CANCEL:
return
self.file = open(openFileDialog.GetPath(), "rb")
self.image = True
self.controller.get_file(openFileDialog.GetPath())
self.upload_image.SetLabel(_(u"Discard image"))
ev.Skip()
def onUpdateProfile(self, ev):
try:
if self.image != None:
self.twitter.twitter.update_profile_image(image=self.file)
except TwythonError as e:
output.speak(u"Error %s. %s" % (e.error_code, e.msg))
try:
f = self.twitter.twitter.update_profile(name=self.name.GetValue(), location=self.location.GetValue(), url=self.url.GetValue(), description=self.description.GetValue())
self.EndModal(wx.ID_OK)
except TwythonError as e:
output.speak(u"Error %s. %s" % (e.error_code, e.msg))
return
def get_data(self):
data = self.twitter.twitter.show_user(screen_name=self.parent.db.settings["user_name"])
self.name.ChangeValue(data["name"])
if data["url"] != None:
self.url.ChangeValue(data["url"])
if len(data["location"]) > 0:
self.location.ChangeValue(data["location"])
if len(data["description"]) > 0:
self.description.ChangeValue(data["description"])
def get_response(self):
return self.ShowModal()

View File

@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
import wx
class urlList(wx.Dialog):
def __init__(self):
super(urlList, self).__init__(parent=None, title=_(u"Select an URL"))
panel = wx.Panel(self)
self.lista = wx.ListBox(panel, -1)
self.lista.SetFocus()
self.lista.SetSize(self.lista.GetBestSize())
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.lista, 0, wx.ALL, 5)
goBtn = wx.Button(panel, wx.ID_OK)
goBtn.SetDefault()
cancelBtn = wx.Button(panel, wx.ID_CANCEL)
btnSizer = wx.BoxSizer()
btnSizer.Add(goBtn, 0, wx.ALL, 5)
btnSizer.Add(cancelBtn, 0, wx.ALL, 5)
sizer.Add(btnSizer, 0, wx.ALL, 5)
panel.SetSizer(sizer)
self.SetClientSize(sizer.CalcMin())
def populate_list(self, urls):
for i in urls:
self.lista.Append(i)
self.lista.SetSelection(0)
def get_string(self):
return self.lista.GetStringSelection()
def get_item(self):
return self.lista.GetSelection()
def get_response(self):
return self.ShowModal()

29
src/wxUI/dialogs/utils.py Normal file
View File

@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
import wx
class selectUserDialog(wx.Dialog):
def __init__(self, users, *args, **kwargs):
super(selectUserDialog, self).__init__(self, None, -1, *args, **kwargs)
panel = wx.Panel(self)
userSizer = wx.BoxSizer()
self.cb = wx.ComboBox(panel, -1, choices=users, value=users[0], size=wx.DefaultSize)
self.cb.SetFocus()
userSizer.Add(wx.StaticText(panel, -1, _(u"User")), 0, wx.ALL, 5)
userSizer.Add(self.cb)
sizer = wx.BoxSizer(wx.VERTICAL)
ok = wx.Button(panel, wx.ID_OK, _(u"OK"))
ok.SetDefault()
cancel = wx.Button(panel, wx.ID_CANCEL, _(u"Close"))
btnsizer = wx.BoxSizer()
btnsizer.Add(ok, 0, wx.ALL, 5)
btnsizer.Add(cancel, 0, wx.ALL, 5)
sizer.Add(userSizer, 0, wx.ALL, 5)
sizer.Add(btnsizer, 0, wx.ALL, 5)
panel.SetSizer(sizer)
self.SetClientSize(sizer.CalcMin())
def get_selection(self):
return self.cb.GetValue()
def get_response(self):
return self.ShowModal()

175
src/wxUI/view.py Normal file
View File

@ -0,0 +1,175 @@
# -*- coding: utf-8 -*-
import wx
class mainFrame(wx.Frame):
""" Main class of the Frame. This is the Main Window."""
### MENU
def makeMenus(self):
""" Creates, bind and returns the menu bar for the application. Also in this function, the accel table is created."""
menuBar = wx.MenuBar()
# Application menu
app = wx.Menu()
updateProfile = app.Append(wx.NewId(), _(u"&Update profile"))
# self.Bind(wx.EVT_MENU, self.controller.update_profile, updateProfile)
show_hide = app.Append(wx.NewId(), _(u"&Hide window"))
# self.Bind(wx.EVT_MENU, self.controller.show_hide, show_hide)
search = app.Append(wx.NewId(), _(u"&Search"))
self.Bind(wx.EVT_MENU, self.controller.search, search)
lists = app.Append(wx.NewId(), _(u"&Lists manager"))
# self.view.Bind(wx.EVT_MENU, self.list_manager, lists)
sounds_tutorial = app.Append(wx.NewId(), _(u"Sounds &tutorial"))
# self.view.Bind(wx.EVT_MENU, self.learn_sounds, sounds_tutorial)
keystroke_editor = app.Append(wx.NewId(), _(u"&Edit keystrokes"))
self.Bind(wx.EVT_MENU, self.controller.edit_keystrokes, keystroke_editor)
prefs = app.Append(wx.ID_PREFERENCES, _(u"&Preferences"))
# self.view.Bind(wx.EVT_MENU, self.preferences, prefs)
close = app.Append(wx.ID_EXIT, _(u"E&xit"))
# self.view.Bind(wx.EVT_MENU, self.close, close)
# Tweet menu
tweet = wx.Menu()
compose = tweet.Append(wx.NewId(), _(u"&Tweet"))
# self.view.Bind(wx.EVT_MENU, self.compose, compose)
response = tweet.Append(wx.NewId(), _(u"Re&ply"))
# self.view.Bind(wx.EVT_MENU, self.reply, response)
retweet = tweet.Append(wx.NewId(), _(u"&Retweet"))
# self.view.Bind(wx.EVT_MENU, self.retweet, retweet)
fav = tweet.Append(wx.NewId(), _(u"Add to &favourites"))
# self.view.Bind(wx.EVT_MENU, self.fav, fav)
unfav = tweet.Append(wx.NewId(), _(u"Remove from favo&urites"))
# self.view.Bind(wx.EVT_MENU, self.unfav, unfav)
view = tweet.Append(wx.NewId(), _(u"&Show tweet"))
# self.view.Bind(wx.EVT_MENU, self.view, view)
delete = tweet.Append(wx.NewId(), _(u"&Delete"))
# self.view.Bind(wx.EVT_MENU, self.delete, delete)
# User menu
user = wx.Menu()
follow = user.Append(wx.NewId(), _(u"&Follow"))
# self.view.Bind(wx.EVT_MENU, self.onFollow, follow)
unfollow = user.Append(wx.NewId(), _(u"&Unfollow"))
# self.view.Bind(wx.EVT_MENU, self.onUnfollow, unfollow)
mute = user.Append(wx.NewId(), _(u"&Mute"))
# self.view.Bind(wx.EVT_MENU, self.onMute, mute)
unmute = user.Append(wx.NewId(), _(u"U&nmute"))
# self.view.Bind(wx.EVT_MENU, self.onUnmute, unmute)
report = user.Append(wx.NewId(), _(u"&Report as spam"))
# self.view.Bind(wx.EVT_MENU, self.onReport, report)
block = user.Append(wx.NewId(), _(u"&Block"))
# self.view.Bind(wx.EVT_MENU, self.onBlock, block)
unblock = user.Append(wx.NewId(), _(u"Unb&lock"))
# self.view.Bind(wx.EVT_MENU, self.onUnblock, unblock)
dm = user.Append(wx.NewId(), _(u"Direct me&ssage"))
# self.view.Bind(wx.EVT_MENU, self.dm, dm)
addToList = user.Append(wx.NewId(), _(u"&Add to list"))
# self.view.Bind(wx.EVT_MENU, self.add_to_list, addToList)
removeFromList = user.Append(wx.NewId(), _(u"R&emove from list"))
# self.view.Bind(wx.EVT_MENU, self.remove_from_list, removeFromList)
viewLists = user.Append(wx.NewId(), _(u"&View lists"))
# self.view.Bind(wx.EVT_MENU, self.view_user_lists, viewLists)
details = user.Append(wx.NewId(), _(u"Show user &profile"))
# self.view.Bind(wx.EVT_MENU, self.details, details)
timeline = user.Append(wx.NewId(), _(u"&Timeline"))
# self.view.Bind(wx.EVT_MENU, self.open_timeline, timeline)
favs = user.Append(wx.NewId(), _(u"V&iew favourites"))
# self.view.Bind(wx.EVT_MENU, self.favs_timeline, favs)
# buffer menu
buffer = wx.Menu()
mute = buffer.Append(wx.NewId(), _(u"&Mute"))
# self.view.Bind(wx.EVT_MENU, self.toggle_mute, mute)
autoread = buffer.Append(wx.NewId(), _(u"&Autoread tweets for this buffer"))
# self.view.Bind(wx.EVT_MENU, self.toggle_autoread, autoread)
clear = buffer.Append(wx.NewId(), _(u"&Clear buffer"))
# self.view.Bind(wx.EVT_MENU, self.clear_list, clear)
deleteTl = buffer.Append(wx.NewId(), _(u"&Remove buffer"))
# self.view.Bind(wx.EVT_MENU, self.delete_buffer, deleteTl)
# Help Menu
help = wx.Menu()
doc = help.Append(-1, _(u"&Documentation"))
# self.view.Bind(wx.EVT_MENU, self.onManual, doc)
changelog = help.Append(wx.NewId(), _(u"&What's new in this version?"))
# self.view.Bind(wx.EVT_MENU, self.onChangelog, changelog)
check_for_updates = help.Append(wx.NewId(), _(u"&Check for updates"))
# self.view.Bind(wx.EVT_MENU, self.onCheckForUpdates, check_for_updates)
reportError = help.Append(wx.NewId(), _(u"&Report an error"))
# self.view.Bind(wx.EVT_MENU, self.onReportBug, reportError)
visit_website = help.Append(-1, _(u"TW Blue &website"))
# self.view.Bind(wx.EVT_MENU, self.onVisit_website, visit_website)
about = help.Append(-1, _(u"About &TW Blue"))
# self.view.Bind(wx.EVT_MENU, self.onAbout, about)
# Add all to the menu Bar
menuBar.Append(app, _(u"&Application"))
menuBar.Append(tweet, _(u"&Tweet"))
menuBar.Append(user, _(u"&User"))
menuBar.Append(buffer, _(u"&Buffer"))
menuBar.Append(help, _(u"&Help"))
self.accel_tbl = wx.AcceleratorTable([
(wx.ACCEL_CTRL, ord('N'), compose.GetId()),
(wx.ACCEL_CTRL, ord('R'), response.GetId()),
(wx.ACCEL_CTRL|wx.ACCEL_SHIFT, ord('R'), retweet.GetId()),
(wx.ACCEL_CTRL, ord('F'), fav.GetId()),
(wx.ACCEL_CTRL|wx.ACCEL_SHIFT, ord('F'), unfav.GetId()),
(wx.ACCEL_CTRL|wx.ACCEL_SHIFT, ord('V'), view.GetId()),
(wx.ACCEL_CTRL, ord('D'), dm.GetId()),
(wx.ACCEL_CTRL, ord('Q'), close.GetId()),
(wx.ACCEL_CTRL, ord('S'), follow.GetId()),
(wx.ACCEL_CTRL|wx.ACCEL_SHIFT, ord('S'), unfollow.GetId()),
(wx.ACCEL_CTRL, ord('K'), block.GetId()),
(wx.ACCEL_CTRL|wx.ACCEL_SHIFT, ord('K'), report.GetId()),
(wx.ACCEL_CTRL, ord('I'), timeline.GetId()),
(wx.ACCEL_CTRL|wx.ACCEL_SHIFT, ord('I'), deleteTl.GetId()),
(wx.ACCEL_CTRL, ord('M'), show_hide.GetId()),
(wx.ACCEL_CTRL, ord('P'), updateProfile.GetId()),
])
self.SetAcceleratorTable(self.accel_tbl)
return menuBar
### MAIN
def __init__(self, controller):
""" Main function of this class."""
super(mainFrame, self).__init__(None, -1, "TW Blue", size=(1600, 1600))
self.controller = controller
self.panel = wx.Panel(self)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.SetTitle("TW Blue")
self.SetMenuBar(self.makeMenus())
self.nb = wx.Treebook(self.panel, wx.NewId())
self.buffers = {}
self.SetMenuBar(self.makeMenus())
def add_buffer(self, buffer, name):
self.nb.AddPage(buffer, name)
self.buffers[name] = buffer.GetId()
def insert_buffer(self, buffer, name, pos):
self.nb.InsertSubPage(pos, buffer, name)
self.buffers[name] = buffer.GetId()
def prepare(self):
self.sizer.Add(self.nb, 0, wx.ALL, 5)
self.panel.SetSizer(self.sizer)
self.SetClientSize(self.sizer.CalcMin())
def search(self, name_, account):
for i in range(0, self.nb.GetPageCount()):
if self.nb.GetPage(i).name == name_ and self.nb.GetPage(i).account == account: return i
def get_current_buffer(self):
return self.nb.GetCurrentPage()
def get_buffer(self, pos):
return self.GetPage(pos)
def get_buffer_by_id(self, id):
return self.nb.FindWindowById(id)
def show(self):
self.Show()