Basic invisible interface support

This commit is contained in:
Manuel Cortez 2015-01-19 12:15:57 -06:00
parent fd70bedc05
commit 7b1f2f9482
8 changed files with 210 additions and 30 deletions

View File

@ -12,25 +12,29 @@ input_device = string(default="Default")
output_device = string(default="Default") output_device = string(default="Default")
global_mute = boolean(default=False) global_mute = boolean(default=False)
current_soundpack = string(default="default") current_soundpack = string(default="default")
ask_at_exit = boolean(default=True)
use_invisible_keyboard_shorcuts = boolean(default=False)
[keymap] [keymap]
up = string(default="control+win+up") up = string(default="control+win+up")
down = string(default="control+win+down") down = string(default="control+win+down")
left = string(default="control+win+left") left = string(default="control+win+left")
right = string(default="control+win+right") right = string(default="control+win+right")
next_account = string(default="control+win+shift+right")
previous_account = string(default="control+win+shift+left")
conversation_up = string(default="control+win+shift+up") conversation_up = string(default="control+win+shift+up")
conversation_down = string(default="control+win+shift+down") conversation_down = string(default="control+win+shift+down")
show_hide = string(default="control+win+m") show_hide = string(default="control+win+m")
compose = string(default="control+win+n") post_tweet = string(default="control+win+n")
reply = string(default="control+win+r") post_reply = string(default="control+win+r")
retweet = string(default="control+win+shift+r") post_retweet = string(default="control+win+shift+r")
dm = string(default="control+win+d") send_dm = string(default="control+win+d")
fav = string(default="alt+win+f") add_to_favourites = string(default="alt+win+f")
unfav = string(default="alt+shift+win+f") remove_from_favourites = string(default="alt+shift+win+f")
action = string(default="control+win+s") action = string(default="control+win+s")
details = string(default="control+win+alt+n") details = string(default="control+win+alt+n")
view = string(default="control+win+v") view_item = string(default="control+win+v")
close = string(default="control+win+f4") exit = string(default="control+win+f4")
open_timeline = string(default="control+win+i") open_timeline = string(default="control+win+i")
delete_buffer = string(default="control+win+shift+i") delete_buffer = string(default="control+win+shift+i")
url = string(default="control+win+return") url = string(default="control+win+return")

View File

@ -2,11 +2,11 @@
name = 'TW Blue' name = 'TW Blue'
snapshot = False snapshot = False
if snapshot == False: if snapshot == False:
version = "0.47" version = "0.90"
update_url = 'http://twblue.com.mx/updates/tw_blue.json' update_url = 'http://twblue.es/updates/tw_blue.json'
else: else:
version = "4" version = "7"
update_url = 'http://twblue.com.mx/updates/snapshots.json' update_url = 'http://twblue.es/updates/snapshots.json'
author = u"Manuel Cortéz" author = u"Manuel Cortéz"
authorEmail = "info@twblue.com.mx" authorEmail = "info@twblue.com.mx"
copyright = u"copyright (C) 2013-2014, Manuel cortéz" copyright = u"copyright (C) 2013-2014, Manuel cortéz"

View File

@ -25,6 +25,7 @@ class bufferController(object):
self.buffer = None self.buffer = None
self.account = "" self.account = ""
self.needs_init = True self.needs_init = True
self.invisible = False # False if the buffer will be ignored on the invisible interface.
def get_event(self, ev): def get_event(self, ev):
if ev.GetKeyCode() == wx.WXK_RETURN and ev.ControlDown(): event = "audio" if ev.GetKeyCode() == wx.WXK_RETURN and ev.ControlDown(): event = "audio"
@ -148,6 +149,7 @@ class baseBufferController(bufferController):
self.buffer = getattr(buffers, bufferType)(parent, name) self.buffer = getattr(buffers, bufferType)(parent, name)
else: else:
self.buffer = buffers.basePanel(parent, name) self.buffer = buffers.basePanel(parent, name)
self.invisible = True
self.name = name self.name = name
self.type = self.buffer.type self.type = self.buffer.type
self.id = self.buffer.GetId() self.id = self.buffer.GetId()
@ -159,7 +161,7 @@ class baseBufferController(bufferController):
self.bind_events() self.bind_events()
def get_message(self): def get_message(self):
return " ".join(self.compose_function(self.get_right_tweet(), self.session.db, self.session.settings["general"]["relative_times"])[1:-2]) return " ".join(self.compose_function(self.get_right_tweet(), self.session.db, self.session.settings["general"]["relative_times"]))
def start_stream(self): def start_stream(self):
log.debug("Starting stream for buffer %s, account %s and type %s" % (self.name, self.account, self.type)) log.debug("Starting stream for buffer %s, account %s and type %s" % (self.name, self.account, self.type))
@ -261,7 +263,7 @@ class baseBufferController(bufferController):
tweet = self.get_tweet() tweet = self.get_tweet()
if self.session.settings["general"]["relative_times"] == True: if self.session.settings["general"]["relative_times"] == True:
# fix this: # fix this:
original_date = arrow.get(self.session.db[self.name_buffer][self.list.get_selected()]["created_at"], "ddd MMM D H:m:s Z YYYY", locale="en") original_date = arrow.get(self.session.db[self.name][self.buffer.list.get_selected()]["created_at"], "ddd MMM D H:m:s Z YYYY", locale="en")
ts = original_date.humanize(locale=languageHandler.getLanguage()) ts = original_date.humanize(locale=languageHandler.getLanguage())
self.buffer.list.list.SetStringItem(self.buffer.list.get_selected(), 2, ts) self.buffer.list.list.SetStringItem(self.buffer.list.get_selected(), 2, ts)
if utils.is_audio(tweet): if utils.is_audio(tweet):
@ -319,6 +321,7 @@ class eventsBufferController(bufferController):
def __init__(self, parent, name, session, account, *args, **kwargs): def __init__(self, parent, name, session, account, *args, **kwargs):
super(eventsBufferController, self).__init__(parent, *args, **kwargs) super(eventsBufferController, self).__init__(parent, *args, **kwargs)
log.debug("Initializing buffer %s, account %s" % (name, account,)) log.debug("Initializing buffer %s, account %s" % (name, account,))
self.invisible = True
self.buffer = buffers.eventsPanel(parent, name) self.buffer = buffers.eventsPanel(parent, name)
self.name = name self.name = name
self.account = account self.account = account
@ -329,12 +332,9 @@ class eventsBufferController(bufferController):
self.type = self.buffer.type self.type = self.buffer.type
def get_message(self): def get_message(self):
if self.list.get_count() == 0: return _(u"Empty") if self.buffer.list.get_count() == 0: return _(u"Empty")
# fix this: # fix this:
if platform.system() == "Windows":
return "%s. %s" % (self.buffer.list.list.GetItemText(self.buffer.list.get_selected()), self.buffer.list.list.GetItemText(self.buffer.list.get_selected(), 1)) return "%s. %s" % (self.buffer.list.list.GetItemText(self.buffer.list.get_selected()), self.buffer.list.list.GetItemText(self.buffer.list.get_selected(), 1))
else:
return self.buffer.list.list.GetStringSelection()
def add_new_item(self, item): def add_new_item(self, item):
tweet = self.compose_function(item, self.session.db["user_name"]) tweet = self.compose_function(item, self.session.db["user_name"])
@ -348,7 +348,7 @@ class peopleBufferController(baseBufferController):
super(peopleBufferController, self).__init__(parent, function, name, sessionObject, account, bufferType="peoplePanel") super(peopleBufferController, self).__init__(parent, function, name, sessionObject, account, bufferType="peoplePanel")
log.debug("Initializing buffer %s, account %s" % (name, account,)) log.debug("Initializing buffer %s, account %s" % (name, account,))
self.compose_function = compose.compose_followers_list self.compose_function = compose.compose_followers_list
log.debug("Compose_function: self.compose_function" % (self.compose_function,)) log.debug("Compose_function: %s" % (self.compose_function,))
self.get_tweet = self.get_right_tweet self.get_tweet = self.get_right_tweet
def onFocus(self, ev): def onFocus(self, ev):
@ -364,12 +364,12 @@ class peopleBufferController(baseBufferController):
log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs)) log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs))
val = self.session.get_cursored_stream(self.name, self.function, *self.args, **self.kwargs) val = self.session.get_cursored_stream(self.name, self.function, *self.args, **self.kwargs)
# self.session.order_cursored_buffer(self.name, self.session.db[self.name]) # self.session.order_cursored_buffer(self.name, self.session.db[self.name])
log.debug("Number of items retrieved: %d" % (val,)) # log.debug("Number of items retrieved: %d" % (val,))
self.put_items_on_list(val) self.put_items_on_list(val)
def put_items_on_list(self, number_of_items): def put_items_on_list(self, number_of_items):
log.debug("The list contains %d items" % (self.buffer.list.get_count(),)) log.debug("The list contains %d items" % (self.buffer.list.get_count(),))
log.debug("Putting %d items on the list..." % (number_of_items,)) # log.debug("Putting %d items on the list..." % (number_of_items,))
if self.buffer.list.get_count() == 0: if self.buffer.list.get_count() == 0:
for i in self.session.db[self.name]["items"]: for i in self.session.db[self.name]["items"]:
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"]) tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"])

View File

@ -11,14 +11,19 @@ from mysc.thread_utils import call_threaded
from mysc.repeating_timer import RepeatingTimer from mysc.repeating_timer import RepeatingTimer
import config import config
import widgetUtils import widgetUtils
import pygeocoder
from pygeolib import GeocoderError
import platform import platform
from extra import SoundsTutorial from extra import SoundsTutorial
import logging import logging
if platform.system() == "Windows": if platform.system() == "Windows":
import keystrokeEditor import keystrokeEditor
from keyboard_handler.wx_handler import WXKeyboardHandler
log = logging.getLogger("mainController") log = logging.getLogger("mainController")
geocoder = pygeocoder.Geocoder()
class Controller(object): class Controller(object):
""" Main Controller for TWBlue. It manages the main window and sessions.""" """ Main Controller for TWBlue. It manages the main window and sessions."""
@ -49,6 +54,18 @@ class Controller(object):
buffer = self.search_buffer(view_buffer.name, view_buffer.account) buffer = self.search_buffer(view_buffer.name, view_buffer.account)
return buffer return buffer
def get_first_buffer(self, account):
for i in self.buffers:
if i.account == account:
buff = i
break
return self.view.search(buff.name, buff.account)
def get_last_buffer(self, account):
results = []
[results.append(i) for i in self.buffers if i.account == account]
return self.view.search(results[-1].name, results[-1].account)
def bind_stream_events(self): def bind_stream_events(self):
log.debug("Binding events for the Twitter stream API...") log.debug("Binding events for the Twitter stream API...")
pub.subscribe(self.manage_home_timelines, "item-in-home") pub.subscribe(self.manage_home_timelines, "item-in-home")
@ -71,6 +88,7 @@ class Controller(object):
log.debug("Binding other application events...") log.debug("Binding other application events...")
pub.subscribe(self.editing_keystroke, "editing_keystroke") pub.subscribe(self.editing_keystroke, "editing_keystroke")
pub.subscribe(self.manage_stream_errors, "stream-error") pub.subscribe(self.manage_stream_errors, "stream-error")
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.show_hide, menuitem=self.view.show_hide)
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.search, menuitem=self.view.menuitem_search) widgetUtils.connect_event(self.view, widgetUtils.MENU, self.search, menuitem=self.view.menuitem_search)
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.learn_sounds, menuitem=self.view.sounds_tutorial) widgetUtils.connect_event(self.view, widgetUtils.MENU, self.learn_sounds, menuitem=self.view.sounds_tutorial)
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.exit, menuitem=self.view.close) widgetUtils.connect_event(self.view, widgetUtils.MENU, self.exit, menuitem=self.view.close)
@ -82,11 +100,16 @@ class Controller(object):
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.view_item, self.view.view) widgetUtils.connect_event(self.view, widgetUtils.MENU, self.view_item, self.view.view)
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.delete, self.view.delete) widgetUtils.connect_event(self.view, widgetUtils.MENU, self.delete, self.view.delete)
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.send_dm, self.view.dm) widgetUtils.connect_event(self.view, widgetUtils.MENU, self.send_dm, self.view.dm)
widgetUtils.connect_event(self.view.nb, widgetUtils.NOTEBOOK_PAGE_CHANGED, self.buffer_changed)
def __init__(self): def __init__(self):
super(Controller, self).__init__() super(Controller, self).__init__()
self.showing = True
self.view = view.mainFrame() self.view = view.mainFrame()
self.buffers = [] self.buffers = []
self.accounts = []
self.buffer_positions = {}
self.current_account = ""
self.view.prepare() self.view.prepare()
self.bind_stream_events() self.bind_stream_events()
self.bind_other_events() self.bind_other_events()
@ -104,6 +127,8 @@ class Controller(object):
def create_buffers(self, session): def create_buffers(self, session):
session.get_user_info() session.get_user_info()
self.accounts.append(session.db["user_name"])
self.buffer_positions[session.db["user_name"]] = 1
account = buffersController.accountPanel(self.view.nb, session.db["user_name"], session.db["user_name"]) account = buffersController.accountPanel(self.view.nb, session.db["user_name"], session.db["user_name"])
self.buffers.append(account) self.buffers.append(account)
self.view.add_buffer(account.buffer , name=session.db["user_name"]) self.view.add_buffer(account.buffer , name=session.db["user_name"])
@ -259,7 +284,7 @@ class Controller(object):
else: else:
buffer.reply() buffer.reply()
def send_dm(self, user): def send_dm(self, *args, **kwargs):
buffer = self.get_current_buffer() buffer = self.get_current_buffer()
if buffer.name == "sent_direct_messages" or buffer.name == "sent-tweets": return if buffer.name == "sent_direct_messages" or buffer.name == "sent-tweets": return
else: else:
@ -309,8 +334,18 @@ class Controller(object):
def remove_buffer(self): def remove_buffer(self):
pass pass
def show_hide(self): def show_hide(self, *args, **kwargs):
pass km = self.create_invisible_keyboard_shorcuts()
if self.showing == True:
if config.app["app-settings"]["use_invisible_keyboard_shorcuts"] == False:
self.register_invisible_keyboard_shorcuts(km)
self.view.Hide()
self.showing = False
else:
if config.app["app-settings"]["use_invisible_keyboard_shorcuts"] == False:
self.unregister_invisible_keyboard_shorcuts(km)
self.view.Show()
self.showing = True
def toggle_global_mute(self): def toggle_global_mute(self):
pass pass
@ -321,7 +356,124 @@ class Controller(object):
def toggle_autoread(self): def toggle_autoread(self):
pass pass
def go_conversation(self, orientation): def skip_buffer(self, forward=True):
buff = self.get_current_buffer()
if buff.invisible == False:
self.view.advance_selection(forward)
def buffer_changed(self, *args, **kwargs):
if self.get_current_buffer().account != self.current_account: self.current_account = self.get_current_buffer().account
def up(self, *args, **kwargs):
page = self.get_current_buffer()
position = page.buffer.list.get_selected()
index = position-1
try:
page.buffer.list.select_item(index)
except:
pass
if position == page.buffer.list.get_selected():
sound.player.play("limit.ogg")
try:
output.speak(page.get_message())
except:
pass
def down(self, *args, **kwargs):
page = self.get_current_buffer()
position = page.buffer.list.get_selected()
index = position+1
try:
page.buffer.list.select_item(index)
except:
pass
if position == page.buffer.list.get_selected():
sound.player.play("limit.ogg")
try:
output.speak(page.get_message())
except:
pass
def left(self, *args, **kwargs):
buff = self.view.get_current_buffer_pos()
buffer = self.get_current_buffer()
if buff == self.get_first_buffer(buffer.account) or buff == 0:
self.view.change_buffer(self.get_last_buffer(buffer.account))
else:
self.view.change_buffer(buff-1)
while self.get_current_buffer().invisible == False: self.skip_buffer(False)
buffer = self.get_current_buffer()
try:
msg = _(u"%s, %s of %s") % (self.view.get_buffer_text(), buffer.buffer.list.get_selected()+1, buffer.buffer.list.get_count())
except:
msg = _(u"%s. Empty") % (self.view.get_buffer_text(),)
output.speak(msg)
def right(self, *args, **kwargs):
buff = self.view.get_current_buffer_pos()
buffer = self.get_current_buffer()
if buff == self.get_last_buffer(buffer.account) or buff+1 == self.view.get_buffer_count():
self.view.change_buffer(self.get_first_buffer(buffer.account))
else:
self.view.change_buffer(buff+1)
while self.get_current_buffer().invisible == False: self.skip_buffer(True)
buffer = self.get_current_buffer()
try:
msg = _(u"%s, %s of %s") % (self.view.get_buffer_text(), buffer.buffer.list.get_selected()+1, buffer.buffer.list.get_count())
except:
msg = _(u"%s. Empty") % (self.view.get_buffer_text(),)
output.speak(msg)
def next_account(self, *args, **kwargs):
index = self.accounts.index(self.current_account)
if index+1 == len(self.accounts):
index = 0
else:
index = index+1
account = self.accounts[index]
self.current_account = account
buff = self.view.search("home_timeline", account)
self.view.change_buffer(buff)
buffer = self.get_current_buffer()
try:
msg = _(u"%s. %s, %s of %s") % (buffer.account, self.view.get_buffer_text(), buffer.buffer.list.get_selected()+1, buffer.buffer.list.get_count())
except:
msg = _(u"%s. Empty") % (self.view.get_buffer_text(),)
output.speak(msg)
def previous_account(self, *args, **kwargs):
index = self.accounts.index(self.current_account)
if index-1 < 0:
index = len(self.accounts)-1
else:
index = index-1
account = self.accounts[index]
self.current_account = account
buff = self.view.search("home_timeline", account)
self.view.change_buffer(buff)
buffer = self.get_current_buffer()
try:
msg = _(u"%s. %s, %s of %s") % (buffer.account, self.view.get_buffer_text(), buffer.buffer.list.get_selected()+1, buffer.buffer.list.get_count())
except:
msg = _(u"%s. Empty") % (self.view.get_buffer_text(),)
output.speak(msg)
def create_invisible_keyboard_shorcuts(self):
keymap = {}
for i in config.app["keymap"]:
if hasattr(self, i):
keymap[config.app["keymap"][i]] = getattr(self, i)
return keymap
def register_invisible_keyboard_shorcuts(self, keymap):
self.keyboard_handler = WXKeyboardHandler(self.view)
self.keyboard_handler.register_keys(keymap)
def unregister_invisible_keyboard_shorcuts(self, keymap):
try:
self.keyboard_handler.unregister_keys(keymap)
del self.keyboard_handler
except AttributeError:
pass pass
def notify(self, play_sound=None, message=None, notification=False): def notify(self, play_sound=None, message=None, notification=False):

View File

@ -6,10 +6,18 @@ import commandline
import config import config
import sound import sound
import output import output
from logger import logger as logging from logger import logger
import logging
import platform
import application
log = logging.getLogger("main")
def setup(): def setup():
log.debug("Starting TWBlue %s" % (application.version,))
config.setup() config.setup()
log.debug("Using %s %s" % (platform.system(), platform.architecture()[0]))
log.debug("Application path is %s" % (paths.app_path(),))
log.debug("Data path is %s" % (paths.data_path(),))
sound.setup() sound.setup()
output.setup() output.setup()
languageHandler.setLanguage(config.app["app-settings"]["language"]) languageHandler.setLanguage(config.app["app-settings"]["language"])

View File

@ -1,4 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import logging
log = logging.getLogger("mysc.thread_utils")
import threading import threading
import wx import wx
from pubsub import pub from pubsub import pub
@ -13,7 +15,7 @@ def call_threaded(func, *args, **kwargs):
except TwythonRateLimitError: except TwythonRateLimitError:
pass pass
except: except:
logging.exception("Thread %d with function %r, args of %r, and kwargs of %r failed to run." % (threading.current_thread().ident, func, a, k)) log.exception("Thread %d with function %r, args of %r, and kwargs of %r failed to run." % (threading.current_thread().ident, func, a, k))
# pass # pass
thread = threading.Thread(target=new_func, args=args, kwargs=kwargs) thread = threading.Thread(target=new_func, args=args, kwargs=kwargs)
thread.daemon = True thread.daemon = True

View File

@ -22,7 +22,7 @@ ENTERED_TEXT = wx.EVT_TEXT
MENU = wx.EVT_MENU MENU = wx.EVT_MENU
KEYPRESS = wx.EVT_CHAR_HOOK KEYPRESS = wx.EVT_CHAR_HOOK
KEYUP = wx.EVT_KEY_UP KEYUP = wx.EVT_KEY_UP
NOTEBOOK_PAGE_CHANGED = wx.EVT_NOTEBOOK_PAGE_CHANGED NOTEBOOK_PAGE_CHANGED = wx.EVT_TREEBOOK_PAGE_CHANGED
def exit_application(): def exit_application():
""" Closes the current window cleanly. """ """ Closes the current window cleanly. """
wx.GetApp().ExitMainLoop() wx.GetApp().ExitMainLoop()

View File

@ -104,6 +104,9 @@ class mainFrame(wx.Frame):
self.nb = wx.Treebook(self.panel, wx.NewId()) self.nb = wx.Treebook(self.panel, wx.NewId())
self.buffers = {} self.buffers = {}
def get_buffer_count(self):
return self.nb.GetPageCount()
def add_buffer(self, buffer, name): def add_buffer(self, buffer, name):
self.nb.AddPage(buffer, name) self.nb.AddPage(buffer, name)
self.buffers[name] = buffer.GetId() self.buffers[name] = buffer.GetId()
@ -124,11 +127,22 @@ class mainFrame(wx.Frame):
def get_current_buffer(self): def get_current_buffer(self):
return self.nb.GetCurrentPage() return self.nb.GetCurrentPage()
def get_current_buffer_pos(self):
return self.nb.GetSelection()
def get_buffer(self, pos): def get_buffer(self, pos):
return self.GetPage(pos) return self.GetPage(pos)
def change_buffer(self, position):
self.nb.ChangeSelection(position)
def get_buffer_text(self):
return self.nb.GetPageText(self.nb.GetSelection())
def get_buffer_by_id(self, id): def get_buffer_by_id(self, id):
return self.nb.FindWindowById(id) return self.nb.FindWindowById(id)
def advance_selection(self, forward):
self.nb.AdvanceSelection(forward)
def show(self): def show(self):
self.Show() self.Show()