diff --git a/src/Conf.defaults b/src/Conf.defaults index ad1934bd..25582b31 100644 --- a/src/Conf.defaults +++ b/src/Conf.defaults @@ -36,6 +36,8 @@ autoread_buffers = list(default=list()) [mysc] spelling_language = string(default="") +save_followers_in_autocompletion_db = boolean(default=False) +save_friends_in_autocompletion_db = boolean(default=False) [services] dropbox_token=string(default="") diff --git a/src/controller/buffersController.py b/src/controller/buffersController.py index aad7a477..c465b221 100644 --- a/src/controller/buffersController.py +++ b/src/controller/buffersController.py @@ -142,7 +142,7 @@ class emptyPanel(bufferController): self.needs_init = True class baseBufferController(bufferController): - def __init__(self, parent, function, name, sessionObject, account, bufferType=None, *args, **kwargs): + def __init__(self, parent, function, name, sessionObject, account, sound=None, bufferType=None, *args, **kwargs): super(baseBufferController, self).__init__(parent, function, *args, **kwargs) log.debug("Initializing buffer %s, account %s" % (name, account,)) if bufferType != None: @@ -159,6 +159,7 @@ class baseBufferController(bufferController): self.account = account self.buffer.account = account self.bind_events() + self.sound = sound def get_formatted_message(self): if self.type == "dm" or self.name == "sent_tweets" or self.name == "sent_direct_messages": return self.compose_function(self.get_right_tweet(), self.session.db, self.session.settings["general"]["relative_times"])[1] @@ -174,6 +175,9 @@ class baseBufferController(bufferController): number_of_items = self.session.order_buffer(self.name, val) log.debug("Number of items retrieved: %d" % (number_of_items,)) self.put_items_on_list(number_of_items) + if self.sound == None: return + if number_of_items > 0 and self.name != "sent_tweets" and self.name != "sent_direct_messages": + self.session.sound.play(self.sound) def put_items_on_list(self, number_of_items): log.debug("The list contains %d items " % (self.buffer.list.get_count(),)) diff --git a/src/controller/mainController.py b/src/controller/mainController.py index 036bd15b..6caa7ed3 100644 --- a/src/controller/mainController.py +++ b/src/controller/mainController.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- from wxUI import (view, dialogs, commonMessageDialogs) +from sessionmanager import manager import buffersController import messages import settings @@ -90,6 +91,7 @@ class Controller(object): log.debug("Binding other application events...") pub.subscribe(self.editing_keystroke, "editing_keystroke") pub.subscribe(self.manage_stream_errors, "stream-error") + pub.subscribe(self.create_new_buffer, "create-new-buffer") 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.learn_sounds, menuitem=self.view.sounds_tutorial) @@ -127,17 +129,19 @@ class Controller(object): if config.app["app-settings"]["use_invisible_keyboard_shorcuts"] == True: km = self.create_invisible_keyboard_shorcuts() self.register_invisible_keyboard_shorcuts(km) - self.do_work() def do_work(self): log.debug("Creating buffers for all sessions...") for i in session_.sessions: log.debug("Working on session %s" % (i,)) self.create_buffers(session_.sessions[i]) - call_threaded(self.start_buffers, session_.sessions[i]) - session_.sessions[session_.sessions.keys()[0]].sound.play("tweet_timeline.ogg") self.checker_function = RepeatingTimer(60, self.check_connection) self.checker_function.start() + def start(self): + for i in session_.sessions: + self.start_buffers(session_.sessions[i]) + session_.sessions[session_.sessions.keys()[0]].sound.play("ready.ogg") + output.speak(_(u"Ready")) def create_buffers(self, session): session.get_user_info() @@ -149,14 +153,12 @@ class Controller(object): home = buffersController.baseBufferController(self.view.nb, "get_home_timeline", "home_timeline", session, session.db["user_name"]) self.buffers.append(home) 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"]) + mentions = buffersController.baseBufferController(self.view.nb, "get_mentions_timeline", "mentions", session, session.db["user_name"], sound="mention_received.ogg") self.buffers.append(mentions) self.view.insert_buffer(mentions.buffer, name=_(u"Mentions"), pos=self.view.search(session.db["user_name"], session.db["user_name"])) - session.sound.play("mention_received.ogg") - dm = buffersController.baseBufferController(self.view.nb, "get_direct_messages", "direct_messages", session, session.db["user_name"], bufferType="dmPanel") + dm = buffersController.baseBufferController(self.view.nb, "get_direct_messages", "direct_messages", session, session.db["user_name"], bufferType="dmPanel", sound="dm_received.ogg") self.buffers.append(dm) self.view.insert_buffer(dm.buffer, name=_(u"Direct messages"), pos=self.view.search(session.db["user_name"], session.db["user_name"])) - session.sound.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) self.view.insert_buffer(sent_dm.buffer, name=_(u"Sent direct messages"), pos=self.view.search(session.db["user_name"], session.db["user_name"])) @@ -259,12 +261,14 @@ class Controller(object): def accountConfiguration(self, *args, **kwargs): buff = self.get_best_buffer() - d = settings.accountSettingsController(buff.session.settings, buff.session.db["user_name"]) -# if d.response == widgetUtils.OK: -# d.save_configuration() -# if d.needs_restart == True: -# commonMessageDialogs.needs_restart() -# restart.restart_program() + manager.manager.set_current_session(buff.session.session_id) + d = settings.accountSettingsController(buff, self) + if d.response == widgetUtils.OK: + d.save_configuration() + if d.needs_restart == True: + commonMessageDialogs.needs_restart() + buff.session.settings.write() + restart.restart_program() def update_profile(self): pass @@ -398,7 +402,8 @@ class Controller(object): 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 + if self.get_current_buffer().account != self.current_account: + self.current_account = self.get_current_buffer().account def fix_wrong_buffer(self): buffer = self.get_current_buffer() @@ -671,5 +676,38 @@ class Controller(object): for i in session_.sessions: session_.sessions[i].check_connection() + def create_new_buffer(self, buffer, account, create): + buff = self.search_buffer("home_timeline", account) + if create == True: + if buffer == "favourites": + favourites = buffersController.baseBufferController(self.view.nb, "get_favorites", "favourites", buff.session, buff.session.db["user_name"]) + self.buffers.append(favourites) + self.view.insert_buffer(favourites.buffer, name=_(u"Favourites"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"])) + favourites.start_stream() + if buffer == "followers": + followers = buffersController.peopleBufferController(self.view.nb, "get_followers_list", "followers", buff.session, buff.session.db["user_name"], screen_name=buff.session.db["user_name"]) + self.buffers.append(followers) + self.view.insert_buffer(followers.buffer, name=_(u"Followers"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"])) + followers.start_stream() + elif buffer == "friends": + friends = buffersController.peopleBufferController(self.view.nb, "get_friends_list", "friends", buff.session, buff.session.db["user_name"], screen_name=buff.session.db["user_name"]) + self.buffers.append(friends) + self.view.insert_buffer(friends.buffer, name=_(u"Friends"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"])) + friends.start_stream() + elif buffer == "blocks": + blocks = buffersController.peopleBufferController(self.view.nb, "list_blocks", "blocked", buff.session, buff.session.db["user_name"]) + self.buffers.append(blocks) + self.view.insert_buffer(blocks.buffer, name=_(u"Blocked users"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"])) + blocks.start_stream() + elif buffer == "mutes": + muted = buffersController.peopleBufferController(self.view.nb, "get_muted_users_list", "muted", buff.session, buff.session.db["user_name"]) + self.buffers.append(muted) + self.view.insert_buffer(muted.buffer, name=_(u"Muted users"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"])) + muted.start_stream() + elif buffer == "events": + events = buffersController.eventsBufferController(self.view.nb, "events", buff.session, buff.session.db["user_name"], bufferType="dmPanel", screen_name=buff.session.db["user_name"]) + self.buffers.append(events) + self.view.insert_buffer(events.buffer, name=_(u"Events"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"])) + def __del__(self): config.app.write() \ No newline at end of file diff --git a/src/controller/messages.py b/src/controller/messages.py index 11f94593..26f40abe 100644 --- a/src/controller/messages.py +++ b/src/controller/messages.py @@ -5,7 +5,7 @@ import url_shortener import sound from pubsub import pub from wxUI.dialogs import message, urlList -from extra import translator, SpellChecker +from extra import translator, SpellChecker, autocompletionUsers from extra.AudioUploader import audioUploader from twitter import utils @@ -101,6 +101,7 @@ class tweet(basicTweet): super(tweet, self).__init__(session, title, caption, text, messageType) self.image = None widgetUtils.connect_event(self.message.upload_image, widgetUtils.BUTTON_PRESSED, self.upload_image) + widgetUtils.connect_event(self.message.autocompletionButton, widgetUtils.BUTTON_PRESSED, self.autocomplete_users) def upload_image(self, *args, **kwargs): if self.message.get("upload_image") == _(u"Discard image"): @@ -112,6 +113,10 @@ class tweet(basicTweet): self.image = self.message.get_image() self.message.set("upload_image", _(u"Discard image")) + def autocomplete_users(self, *args, **kwargs): + c = autocompletionUsers.completion.autocompletionUsers(self.message, self.session.session_id) + c.show_menu() + class reply(tweet): def __init__(self, session, title, caption, text, users=None): super(reply, self).__init__(session, title, caption, text, messageType="reply") diff --git a/src/controller/settings.py b/src/controller/settings.py index 21a4ebff..427889c2 100644 --- a/src/controller/settings.py +++ b/src/controller/settings.py @@ -1,11 +1,14 @@ # -*- coding: utf-8 -*- import os +import webbrowser import sound_lib import paths import widgetUtils import config import languageHandler from wxUI.dialogs import configuration +from extra.autocompletionUsers import settings +from extra.AudioUploader import dropbox_transfer from pubsub import pub import logging log = logging.getLogger("Settings") @@ -15,6 +18,7 @@ class globalSettingsController(object): super(globalSettingsController, self).__init__() self.dialog = configuration.configurationDialog() self.create_config() + self.needs_restart = False def create_config(self): self.langs = languageHandler.getAvailableLanguages() @@ -30,7 +34,6 @@ class globalSettingsController(object): self.dialog.set_value("general", "disable_sapi5", config.app["app-settings"]["voice_enabled"]) self.dialog.set_value("general", "hide_gui", config.app["app-settings"]["hide_gui"]) self.dialog.realize() - self.needs_restart = False self.response = self.dialog.get_response() def save_configuration(self): @@ -46,9 +49,11 @@ class globalSettingsController(object): config.app.write() class accountSettingsController(globalSettingsController): - def __init__(self, config, user_name): - self.config = config - self.user = user_name + def __init__(self, buffer, window): + self.user = buffer.session.db["user_name"] + self.buffer = buffer + self.window = window + self.config = buffer.session.settings super(accountSettingsController, self).__init__() def create_config(self): @@ -66,6 +71,8 @@ class accountSettingsController(globalSettingsController): self.dialog.set_value("buffers", "mutes", self.config["other_buffers"]["show_muted_users"]) self.dialog.set_value("buffers", "events", self.config["other_buffers"]["show_events"]) self.dialog.create_ignored_clients(self.config["twitter"]["ignored_clients"]) + widgetUtils.connect_event(self.dialog.ignored_clients.add, widgetUtils.BUTTON_PRESSED, self.add_ignored_client) + widgetUtils.connect_event(self.dialog.ignored_clients.remove, widgetUtils.BUTTON_PRESSED, self.remove_ignored_client) self.input_devices = sound_lib.input.Input.get_device_names() self.output_devices = sound_lib.output.Output.get_device_names() self.soundpacks = [] @@ -77,9 +84,100 @@ class accountSettingsController(globalSettingsController): self.dialog.set_value("sound", "global_mute", self.config["sound"]["global_mute"]) self.dialog.set_value("sound", "soundpack", self.config["sound"]["current_soundpack"]) self.dialog.create_audio_services() + if self.config["services"]["dropbox_token"] == "": + self.dialog.services.set_dropbox(False) + else: + self.dialog.services.set_dropbox(True) + widgetUtils.connect_event(self.dialog.services.dropbox, widgetUtils.BUTTON_PRESSED, self.manage_dropbox) + self.dialog.set_value("services", "apiKey", self.config["sound"]["sndup_api_key"]) self.dialog.realize() self.dialog.set_title(_(u"Account settings for %s") % (self.user,)) self.response = self.dialog.get_response() - def save_config(self): pass - def manage_autocomplete(self, *args, **kwargs): pass \ No newline at end of file + def save_configuration(self): + if self.config["general"]["relative_times"] != self.dialog.get_value("general", "relative_time"): + self.needs_restart = True + self.config["general"]["relative_times"] = self.dialog.get_value("general", "relative_time") + self.config["general"]["max_api_calls"] = self.dialog.get_value("general", "apiCalls") + self.config["general"]["max_tweets_per_call"] = self.dialog.get_value("general", "itemsPerApiCall") + if self.config["general"]["reverse_timelines"] != self.dialog.get_value("general", "reverse_timelines"): + self.needs_restart = True + self.config["general"]["reverse_timelines"] = self.dialog.get_value("general", "reverse_timelines") + if self.config["other_buffers"]["show_followers"] != self.dialog.get_value("buffers", "followers"): + self.config["other_buffers"]["show_followers"] = self.dialog.get_value("buffers", "followers") + pub.sendMessage("create-new-buffer", buffer="followers", account=self.user, create=self.config["other_buffers"]["show_followers"]) + if self.config["other_buffers"]["show_friends"] != self.dialog.get_value("buffers", "friends"): + self.config["other_buffers"]["show_friends"] = self.dialog.get_value("buffers", "friends") + pub.sendMessage("create-new-buffer", buffer="friends", account=self.user, create=self.config["other_buffers"]["show_friends"]) + if self.config["other_buffers"]["show_favourites"] != self.dialog.get_value("buffers", "favs"): + self.config["other_buffers"]["show_favourites"] = self.dialog.get_value("buffers", "favs") + pub.sendMessage("create-new-buffer", buffer="favourites", account=self.user, create=self.config["other_buffers"]["show_favourites"]) + if self.config["other_buffers"]["show_blocks"] != self.dialog.get_value("buffers", "blocks"): + self.config["other_buffers"]["show_blocks"] = self.dialog.get_value("buffers", "blocks") + pub.sendMessage("create-new-buffer", buffer="blocks", account=self.user, create=self.config["other_buffers"]["show_blocks"]) + if self.config["other_buffers"]["show_muted_users"] != self.dialog.get_value("buffers", "mutes"): + self.config["other_buffers"]["show_muted_users"] = self.dialog.get_value("buffers", "mutes") + pub.sendMessage("create-new-buffer", buffer="mutes", account=self.user, create=self.config["other_buffers"]["show_muted_users"]) + if self.config["other_buffers"]["show_events"] != self.dialog.get_value("buffers", "events"): + self.config["other_buffers"]["show_events"] = self.dialog.get_value("buffers", "events") + pub.sendMessage("create-new-buffer", buffer="events", account=self.user, create=self.config["other_buffers"]["show_events"]) + if self.config["sound"]["input_device"] != self.dialog.sound.get("input"): + self.config["sound"]["input_device"] = self.dialog.sound.get("input") + try: + self.buffer.session.sound.input.set_device(self.buffer.session.sound.input.find_device_by_name(self.config["sound"]["input_device"])) + except: + self.config["sound"]["input_device"] = "default" + if self.config["sound"]["output_device"] != self.dialog.sound.get("output"): + self.config["sound"]["output_device"] = self.dialog.sound.get("output") + try: + self.buffer.session.sound.output.set_device(self.buffer.session.sound.output.find_device_by_name(self.config["sound"]["output_device"])) + except: + self.config["sound"]["output_device"] = "default" + self.config["sound"]["volume"] = self.dialog.get_value("sound", "volumeCtrl")/100.0 + self.config["sound"]["global_mute"] = self.dialog.get_value("sound", "global_mute") + self.config["sound"]["soundpack"] = self.dialog.sound.get("soundpack") + self.buffer.session.sound.check_soundpack() + self.config["sound"]["sndup_api_key"] = self.dialog.get_value("services", "apiKey") + + + def manage_autocomplete(self, *args, **kwargs): + configuration = settings.autocompletionSettings(self.buffer.session.settings, self.buffer, self.window) + + def add_ignored_client(self, *args, **kwargs): + client = commonMessageDialogs.get_ignored_client() + if client == None: return + if client not in self.config["twitter"]["ignored_clients"]: + self.config["twitter"]["ignored_clients"].append(client) + self.dialog.ignored_clients.append(client) + + def remove_ignored_client(self, *args, **kwargs): + if self.dialog.ignored_clients.get_clients() == 0: return + id = self.dialog.ignored_clients.get_client_id() + self.config["twitter"]["ignored_clients"].pop(id) + self.dialog.ignored_clients.remove(id) + + def manage_dropbox(self, *args, **kwargs): + if self.dialog.services.get_dropbox() == _(u"Link your Dropbox account"): + self.connect_dropbox() + else: + self.disconnect_dropbox() + + def connect_dropbox(self): + auth = dropbox_transfer.dropboxLogin(self.config) + url = auth.get_url() + self.dialog.services.show_dialog() + webbrowser.open(url) + resp = self.dialog.services.get_response() + if resp == "": + self.dialog.services.set_dropbox(False) + else: + try: + auth.authorise(resp) + self.dialog.services.set_dropbox() + except: + self.dialog.services.show_error() + self.dialog.services.set_dropbox(False) + + def disconnect_dropbox(self): + self.config["services"]["dropbox_token"] = "" + self.dialog.services.set_dropbox(False) diff --git a/src/extra/AudioUploader/dropbox_transfer.py b/src/extra/AudioUploader/dropbox_transfer.py index e2a4ace2..e7aa5f42 100644 --- a/src/extra/AudioUploader/dropbox_transfer.py +++ b/src/extra/AudioUploader/dropbox_transfer.py @@ -55,7 +55,7 @@ class dropboxLogin(object): log.debug("Authorising TWBlue in Dropbox...") access_token, user_id = self.flow.finish(code) log.debug("Saving tokens...") - config["services"]["dropbox_token"] = access_token + self.config["services"]["dropbox_token"] = access_token self.logged = True class dropboxUploader(object): diff --git a/src/extra/autocompletionUsers/__init__.py b/src/extra/autocompletionUsers/__init__.py new file mode 100644 index 00000000..343ea6c0 --- /dev/null +++ b/src/extra/autocompletionUsers/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +import completion, settings \ No newline at end of file diff --git a/src/extra/autocompletionUsers/completion.py b/src/extra/autocompletionUsers/completion.py new file mode 100644 index 00000000..13a4326d --- /dev/null +++ b/src/extra/autocompletionUsers/completion.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +import output +import storage +import wx_menu + +class autocompletionUsers(object): + def __init__(self, window, session_id): + super(autocompletionUsers, self).__init__() + self.window = window + self.db = storage.storage(session_id) + + def show_menu(self): + position = self.window.get_position() + text = self.window.get_text() + text = text[:position] + try: + pattern = text.split()[-1] + except IndexError: + output.speak(_(u"You have to start writing")) + return + if pattern.startswith("@") == True: + menu = wx_menu.menu(self.window.text, pattern[1:]) + users = self.db.get_users(pattern[1:]) + if len(users) > 0: + menu.append_options(users) + self.window.popup_menu(menu) + menu.destroy() + else: + output.speak(_(u"There are no results in your users database")) + else: + output.speak(_(u"Autocompletion only works for users.")) \ No newline at end of file diff --git a/src/extra/autocompletionUsers/manage.py b/src/extra/autocompletionUsers/manage.py new file mode 100644 index 00000000..60e34ddc --- /dev/null +++ b/src/extra/autocompletionUsers/manage.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +import storage +import widgetUtils +import wx_manage +from wxUI import commonMessageDialogs + +class autocompletionManage(object): + def __init__(self, session): + super(autocompletionManage, self).__init__() + self.session = session + self.dialog = wx_manage.autocompletionManageDialog() + self.database = storage.storage(self.session.session_id) + self.users = self.database.get_all_users() + self.dialog.put_users(self.users) + widgetUtils.connect_event(self.dialog.add, widgetUtils.BUTTON_PRESSED, self.add_user) + widgetUtils.connect_event(self.dialog.remove, widgetUtils.BUTTON_PRESSED, self.remove_user) + self.dialog.get_response() + + def update_list(self): + item = self.dialog.users.get_selected() + self.dialog.users.clear() + self.users = self.database.get_all_users() + self.dialog.put_users(self.users) + self.dialog.users.select_item(item) + + def add_user(self, *args, **kwargs): + usr = self.dialog.get_user() + if usr == False: + return + try: + data = self.session.twitter.twitter.show_user(screen_name=usr) + except: + self.dialog.show_invalid_user_error() + return + self.database.set_user(data["screen_name"], data["name"], 0) + self.update_list() + + def remove_user(self, ev): + if commonMessageDialogs.delete_user_from_db() == widgetUtils.YES: + item = self.dialog.users.get_selected() + user = self.users[item] + self.database.remove_user(user[0]) + self.update_list() \ No newline at end of file diff --git a/src/extra/autocompletionUsers/settings.py b/src/extra/autocompletionUsers/settings.py new file mode 100644 index 00000000..6eb0762d --- /dev/null +++ b/src/extra/autocompletionUsers/settings.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +import storage +import widgetUtils +import wx_settings +import manage +import output +from mysc.thread_utils import call_threaded + +class autocompletionSettings(object): + def __init__(self, config, buffer, window): + super(autocompletionSettings, self).__init__() + self.config = config + self.buffer = buffer + self.window = window + self.dialog = wx_settings.autocompletionSettingsDialog() + self.dialog.set("friends_buffer", self.config["mysc"]["save_friends_in_autocompletion_db"]) + self.dialog.set("followers_buffer", self.config["mysc"]["save_followers_in_autocompletion_db"]) + widgetUtils.connect_event(self.dialog.viewList, widgetUtils.BUTTON_PRESSED, self.view_list) + if self.dialog.get_response() == widgetUtils.OK: + call_threaded(self.add_users_to_database) + + def add_users_to_database(self): + self.config["mysc"]["save_friends_in_autocompletion_db"] = self.dialog.get("friends_buffer") + self.config["mysc"]["save_followers_in_autocompletion_db"] = self.dialog.get("followers_buffer") + output.speak(_(u"Updating database... You can close this window now. A message will tell you when the process finishes.")) + database = storage.storage(self.buffer.session.session_id) + if self.dialog.get("followers_buffer") == True: + buffer = self.window.search_buffer("followers", self.config["twitter"]["user_name"]) + for i in buffer.session.db[buffer.name]["items"]: + database.set_user(i["screen_name"], i["name"], 1) + else: + database.remove_by_buffer(1) + if self.dialog.get("friends_buffer") == True: + buffer = self.window.search_buffer("friends", self.config["twitter"]["user_name"]) + for i in buffer.session.db[buffer.name]["items"]: + database.set_user(i["screen_name"], i["name"], 2) + else: + database.remove_by_buffer(2) + wx_settings.show_success_dialog() + self.dialog.destroy() + + def view_list(self, ev): + q = manage.autocompletionManage(self.buffer.session) + + +def execute_at_startup(window, buffer, config): + database = storage.storage(buffer.session.session_id) + if config["mysc"]["save_followers_in_autocompletion_db"] == True and config["other_buffers"]["show_followers"] == True: + buffer = window.search_buffer("followers", config["twitter"]["user_name"]) + for i in buffer.session.db[buffer.name]: + database.set_user(i["screen_name"], i["name"], 1) + else: + database.remove_by_buffer(1) + if config["mysc"]["save_friends_in_autocompletion_db"] == True and config["other_buffers"]["show_friends"] == True: + buffer = window.search_buffer("friends", config["twitter"]["user_name"]) + for i in buffer.session.db[buffer.name]: + database.set_user(i["screen_name"], i["name"], 2) + else: + database.remove_by_buffer(2) \ No newline at end of file diff --git a/src/extra/autocompletionUsers/storage.py b/src/extra/autocompletionUsers/storage.py new file mode 100644 index 00000000..ed9896b2 --- /dev/null +++ b/src/extra/autocompletionUsers/storage.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +import sqlite3, paths + +class storage(object): + def __init__(self, session_id): + self.connection = sqlite3.connect(paths.config_path("%s/autocompletionUsers.dat" % (session_id))) + self.cursor = self.connection.cursor() + if self.table_exist("users") == False: + self.create_table() + + def table_exist(self, table): + ask = self.cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='%s'" % (table)) + answer = ask.fetchone() + if answer == None: + return False + else: + return True + + def get_all_users(self): + self.cursor.execute("""select * from users""") + return self.cursor.fetchall() + + def get_users(self, term): + self.cursor.execute("""SELECT * FROM users WHERE user LIKE ?""", ('{}%'.format(term),)) + return self.cursor.fetchall() + + def set_user(self, screen_name, user_name, from_a_buffer): + self.cursor.execute("""insert or ignore into users values(?, ?, ?)""", (screen_name, user_name, from_a_buffer)) + self.connection.commit() + + def remove_user(self, user): + self.cursor.execute("""DELETE FROM users WHERE user = ?""", (user,)) + self.connection.commit() + return self.cursor.fetchone() + + def remove_by_buffer(self, bufferType): + """ Removes all users saved on a buffer. BufferType is 0 for no buffer, 1 for friends and 2 for followers""" + self.cursor.execute("""DELETE FROM users WHERE from_a_buffer = ?""", (bufferType,)) + self.connection.commit() + return self.cursor.fetchone() + + def create_table(self): + self.cursor.execute(""" + create table users( +user TEXT UNIQUE, +name TEXT, +from_a_buffer INTEGER +)""") + + def __del__(self): + self.cursor.close() + self.connection.close() \ No newline at end of file diff --git a/src/extra/autocompletionUsers/wx_manage.py b/src/extra/autocompletionUsers/wx_manage.py new file mode 100644 index 00000000..911e5533 --- /dev/null +++ b/src/extra/autocompletionUsers/wx_manage.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +import wx +import widgetUtils +from multiplatform_widgets import widgets + +class autocompletionManageDialog(widgetUtils.BaseDialog): + def __init__(self): + super(autocompletionManageDialog, self).__init__(parent=None, id=-1, title=_(u"Manage Autocomplete users’ database")) + panel = wx.Panel(self) + sizer = wx.BoxSizer(wx.VERTICAL) + label = wx.StaticText(panel, -1, _(u"Editing TWBlue users database")) + self.users = widgets.list(panel, _(u"Username"), _(u"Name"), style=wx.LC_REPORT) + sizer.Add(label, 0, wx.ALL, 5) + sizer.Add(self.users.list, 0, wx.ALL, 5) + self.add = wx.Button(panel, -1, _(u"Add user")) + self.remove = wx.Button(panel, -1, _(u"Remove user")) + optionsBox = wx.BoxSizer(wx.HORIZONTAL) + optionsBox.Add(self.add, 0, wx.ALL, 5) + optionsBox.Add(self.remove, 0, wx.ALL, 5) + sizer.Add(optionsBox, 0, wx.ALL, 5) + ok = wx.Button(panel, wx.ID_OK) + cancel = wx.Button(panel, wx.ID_CANCEL) + sizerBtn = wx.BoxSizer(wx.HORIZONTAL) + sizerBtn.Add(ok, 0, wx.ALL, 5) + sizer.Add(cancel, 0, wx.ALL, 5) + sizer.Add(sizerBtn, 0, wx.ALL, 5) + panel.SetSizer(sizer) + self.SetClientSize(sizer.CalcMin()) + + def put_users(self, users): + for i in users: + j = [i[0], i[1]] + self.users.insert_item(False, *j) + + def get_user(self): + usr = False + userDlg = wx.TextEntryDialog(None, _(u"Twitter username"), _(u"Add user to database")) + if userDlg.ShowModal() == wx.ID_OK: + usr = userDlg.GetValue() + return usr + + def show_invalid_user_error(self): + wx.MessageDialog(None, _(u"The user does not exist"), _(u"Error!"), wx.ICON_ERROR).ShowModal() \ No newline at end of file diff --git a/src/extra/autocompletionUsers/wx_menu.py b/src/extra/autocompletionUsers/wx_menu.py new file mode 100644 index 00000000..627a76eb --- /dev/null +++ b/src/extra/autocompletionUsers/wx_menu.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +import wx + +class menu(wx.Menu): + def __init__(self, window, pattern): + super(menu, self).__init__() + self.window = window + self.pattern = pattern + + def append_options(self, options): + for i in options: + item = wx.MenuItem(self, wx.NewId(), "%s (@%s)" % (i[1], i[0])) + self.AppendItem(item) + self.Bind(wx.EVT_MENU, lambda evt, temp=i[0]: self.select_text(evt, temp), item) + + def select_text(self, ev, text): + self.window.ChangeValue(self.window.GetValue().replace("@"+self.pattern, "@"+text+" ")) + self.window.SetInsertionPointEnd() + + def destroy(self): + self.Destroy() \ No newline at end of file diff --git a/src/extra/autocompletionUsers/wx_settings.py b/src/extra/autocompletionUsers/wx_settings.py new file mode 100644 index 00000000..7cc25de4 --- /dev/null +++ b/src/extra/autocompletionUsers/wx_settings.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +import wx +import widgetUtils + +class autocompletionSettingsDialog(widgetUtils.BaseDialog): + def __init__(self): + super(autocompletionSettingsDialog, self).__init__(parent=None, id=-1, title=_(u"Autocomplete users’ settings")) + panel = wx.Panel(self) + sizer = wx.BoxSizer(wx.VERTICAL) + self.followers_buffer = wx.CheckBox(panel, -1, _(u"Add users from followers buffer")) + self.friends_buffer = wx.CheckBox(panel, -1, _(u"Add users from friends buffer")) + sizer.Add(self.followers_buffer, 0, wx.ALL, 5) + sizer.Add(self.friends_buffer, 0, wx.ALL, 5) + self.viewList = wx.Button(panel, -1, _(u"See the users list")) + sizer.Add(self.viewList, 0, wx.ALL, 5) + ok = wx.Button(panel, wx.ID_OK) + cancel = wx.Button(panel, wx.ID_CANCEL) + sizerBtn = wx.BoxSizer(wx.HORIZONTAL) + sizerBtn.Add(ok, 0, wx.ALL, 5) + sizer.Add(cancel, 0, wx.ALL, 5) + sizer.Add(sizerBtn, 0, wx.ALL, 5) + panel.SetSizer(sizer) + self.SetClientSize(sizer.CalcMin()) + +def show_success_dialog(): + wx.MessageDialog(None, _(u"TWBlue's database of users has been updated."), _(u"Done"), wx.OK).ShowModal() \ No newline at end of file diff --git a/src/logger.py b/src/logger.py index ed41a36b..8bb5dbd8 100644 --- a/src/logger.py +++ b/src/logger.py @@ -28,7 +28,7 @@ logger.setLevel(logging.DEBUG) #handlers -app_handler = RotatingFileHandler(paths.logs_path(APP_LOG_FILE), maxBytes=1000000, mode="w") +app_handler = RotatingFileHandler(paths.logs_path(APP_LOG_FILE), mode="w") app_handler.setFormatter(formatter) app_handler.setLevel(logging.DEBUG) logger.addHandler(app_handler) diff --git a/src/main.py b/src/main.py index 809b0129..c2b0d412 100644 --- a/src/main.py +++ b/src/main.py @@ -10,6 +10,7 @@ from logger import logger import logging import platform import application +from mysc.thread_utils import call_threaded log = logging.getLogger("main") def setup(): @@ -32,6 +33,8 @@ def setup(): del sm r = mainController.Controller() r.view.Show() + r.do_work() + call_threaded(r.start) app.MainLoop() setup() \ No newline at end of file diff --git a/src/sessionmanager/session.py b/src/sessionmanager/session.py index 5950c48a..6a8dee65 100644 --- a/src/sessionmanager/session.py +++ b/src/sessionmanager/session.py @@ -187,7 +187,7 @@ class Session(object): 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) + data = getattr(self.twitter.twitter, update_function)(max_id=max_id, count=self.settings["general"]["max_tweets_per_call"], *args, **kwargs) results.extend(data) results.reverse() return results diff --git a/src/widgetUtils/baseDialog.py b/src/widgetUtils/baseDialog.py index 9d1faa44..ac09f797 100644 --- a/src/widgetUtils/baseDialog.py +++ b/src/widgetUtils/baseDialog.py @@ -22,4 +22,7 @@ class BaseDialog(wx.Dialog): elif hasattr(control, "SetLabel"): return getattr(control, "SetLabel")(text) elif hasattr(control, "ChangeValue"): return getattr(control, "ChangeValue")(text) else: return -1 - else: return 0 \ No newline at end of file + else: return 0 + + def destroy(self): + self.Destroy() \ No newline at end of file diff --git a/src/wxUI/commonMessageDialogs.py b/src/wxUI/commonMessageDialogs.py index 22e7cf39..57b2f8ef 100644 --- a/src/wxUI/commonMessageDialogs.py +++ b/src/wxUI/commonMessageDialogs.py @@ -12,4 +12,12 @@ def exit_dialog(): return dlg.ShowModal() def needs_restart(): - 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() \ No newline at end of file + 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() +def delete_user_from_db(): + return wx.MessageDialog(None, _(u"Are you sure you want to delete this user from the database? This user will not appear on the autocomplete results anymore."), _(u"Confirm"), wx.YES_NO|wx.ICON_QUESTION).ShowModal() + +def get_ignored_client(): + entry = wx.TextEntryDialog(None, _(u"Enter the name of the client here"), _(u"Add a new ignored client")) + if entry.ShowModal() == wx.ID_OK: + return entry.GetValue() + return None \ No newline at end of file diff --git a/src/wxUI/dialogs/configuration.py b/src/wxUI/dialogs/configuration.py index d3d20f99..a581d614 100644 --- a/src/wxUI/dialogs/configuration.py +++ b/src/wxUI/dialogs/configuration.py @@ -87,6 +87,18 @@ class ignoredClients(wx.Panel): sizer.Add(btnBox, 0, wx.ALL, 5) self.SetSizer(sizer) + def append(self, client): + self.clients.Append(client) + + def get_clients(self): + return self.clients.GetCount() + + def get_client_id(self): + return self.clients.GetSelection() + + def remove(self, id): + self.clients.Delete(id) + class sound(wx.Panel): def __init__(self, parent, input_devices, output_devices, soundpacks): wx.Panel.__init__(self, parent) @@ -124,6 +136,9 @@ class sound(wx.Panel): sizer.Add(soundBox, 0, wx.ALL, 5) self.SetSizer(sizer) + def get(self, control): + return getattr(self, control).GetStringSelection() + class audioServicesPanel(wx.Panel): def __init__(self, parent): super(audioServicesPanel, self).__init__(parent) @@ -143,6 +158,27 @@ class audioServicesPanel(wx.Panel): mainSizer.Add(first_sizer, 0, wx.ALL, 5) self.SetSizer(mainSizer) + def set_dropbox(self, active=True): + if active == True: + self.dropbox.SetLabel(_(u"Unlink your Dropbox account")) + else: + self.dropbox.SetLabel(_(u"Link your Dropbox account")) + + def show_dialog(self): + wx.MessageDialog(self, _(u"The 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() + + def get_response(self): + dlg = wx.TextEntryDialog(self, _(u"Enter the code here."), _(u"Verification code")) + if dlg.ShowModal() == wx.ID_CANCEL: + return False + return dlg.GetValue() + + def show_error(self): + wx.MessageDialog(self, _(u"Error during authorisation. Try again later."), _(u"Error!"), wx.ICON_ERROR).ShowModal() + + def get_dropbox(self): + return self.dropbox.GetLabel() + class configurationDialog(baseDialog.BaseWXDialog): def set_title(self, title): diff --git a/src/wxUI/dialogs/message.py b/src/wxUI/dialogs/message.py index d68c3f13..00831b92 100644 --- a/src/wxUI/dialogs/message.py +++ b/src/wxUI/dialogs/message.py @@ -50,6 +50,11 @@ class textLimited(widgetUtils.BaseDialog): def set_cursor_at_position(self, position): self.text.SetInsertionPoint(position) + def get_position(self): + return self.text.GetInsertionPoint() + + def popup_menu(self, menu): + self.PopupMenu(menu, self.text.GetPosition()) class tweet(textLimited): def createControls(self, title, message, text): @@ -64,6 +69,7 @@ class tweet(textLimited): self.shortenButton.Disable() self.unshortenButton.Disable() self.translateButton = wx.Button(self.panel, -1, _(u"Translate message"), size=wx.DefaultSize) + self.autocompletionButton = wx.Button(self.panel, -1, _(u"&Autocomplete users")) self.okButton = wx.Button(self.panel, wx.ID_OK, _(u"Send"), size=wx.DefaultSize) self.okButton.SetDefault() cancelButton = wx.Button(self.panel, wx.ID_CANCEL, _(u"Close"), size=wx.DefaultSize) @@ -78,6 +84,7 @@ class tweet(textLimited): 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.autocompletionButton, 0, wx.ALL, 5) 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)