From 3ec8ac31a51d767fd68ed8285b4f9641094206a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Cort=C3=A9z?= Date: Tue, 25 Nov 2014 12:30:00 -0600 Subject: [PATCH] Autocompletion for users has been implemented --- src/extra/AudioUploader/gui.py | 3 +- src/extra/autocompletionUsers/__init__.py | 1 + src/extra/autocompletionUsers/completion.py | 31 +++++++++++++++ src/extra/autocompletionUsers/settings.py | 29 ++++++++++++++ src/extra/autocompletionUsers/storage.py | 41 ++++++++++++++++++++ src/extra/autocompletionUsers/wx_menu.py | 18 +++++++++ src/extra/autocompletionUsers/wx_settings.py | 23 +++++++++++ src/gui/dialogs/configuration.py | 8 ++++ src/gui/dialogs/message.py | 10 +++++ src/gui/main.py | 3 +- src/twitter/twitter.py | 3 ++ 11 files changed, 168 insertions(+), 2 deletions(-) create mode 100644 src/extra/autocompletionUsers/__init__.py create mode 100644 src/extra/autocompletionUsers/completion.py create mode 100644 src/extra/autocompletionUsers/settings.py create mode 100644 src/extra/autocompletionUsers/storage.py create mode 100644 src/extra/autocompletionUsers/wx_menu.py create mode 100644 src/extra/autocompletionUsers/wx_settings.py diff --git a/src/extra/AudioUploader/gui.py b/src/extra/AudioUploader/gui.py index 0388fa65..ec21dc88 100644 --- a/src/extra/AudioUploader/gui.py +++ b/src/extra/AudioUploader/gui.py @@ -68,7 +68,8 @@ class audioDialog(wx.Dialog): services = [] if config.main["services"]["dropbox_token"] != "": services.append("Dropbox") - services.append("SNDUp") + service.append("TwUp") + services.append("SNDUp") return services def onPause(self, ev): diff --git a/src/extra/autocompletionUsers/__init__.py b/src/extra/autocompletionUsers/__init__.py new file mode 100644 index 00000000..40a96afc --- /dev/null +++ b/src/extra/autocompletionUsers/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/src/extra/autocompletionUsers/completion.py b/src/extra/autocompletionUsers/completion.py new file mode 100644 index 00000000..d85bc656 --- /dev/null +++ b/src/extra/autocompletionUsers/completion.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +import storage +import output +import wx_menu + +class autocompletionUsers(object): + def __init__(self, window): + super(autocompletionUsers, self).__init__() + self.window = window + + def show_menu(self): + position = self.window.text.GetInsertionPoint() + text = self.window.text.GetValue() + text = text[:position] + try: + pattern = text.split()[-1] + except IndexError: + output.speak(_(u"You have to start to write")) + return + if pattern.startswith("@") == True: + db = storage.storage() + menu = wx_menu.menu(self.window.text, pattern[1:]) + users = db.get_users(pattern[1:]) + if len(users) > 0: + menu.append_options(users) + self.window.PopupMenu(menu, self.window.text.GetPosition()) + menu.Destroy() + else: + output.speak(_(u"There is not 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/settings.py b/src/extra/autocompletionUsers/settings.py new file mode 100644 index 00000000..0737a121 --- /dev/null +++ b/src/extra/autocompletionUsers/settings.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +import storage +import wx +import wx_settings +import output +from mysc.thread_utils import call_threaded + +class autocompletionSettings(object): + def __init__(self, window): + super(autocompletionSettings, self).__init__() + self.window = window + self.dialog = wx_settings.autocompletionSettingsDialog() + if self.dialog.ShowModal() == wx.ID_OK: + call_threaded(self.add_users_to_database) + + def add_users_to_database(self): + output.speak(_(u"Updating database... You can close this window now. A message will tell you when the process finishes.")) + database = storage.storage() + if self.dialog.followers_buffer.GetValue() == True: + buffer = self.window.search_buffer("people", "followers") + for i in buffer.db.settings[buffer.name_buffer]: + database.set_user(i["screen_name"], i["name"]) + if self.dialog.friends_buffer.GetValue() == True: + buffer = self.window.search_buffer("people", "friends") + for i in buffer.db.settings[buffer.name_buffer]: + database.set_user(i["screen_name"], i["name"]) + wx_settings.show_success_dialog() + self.dialog.Destroy() + \ 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..b5eb410a --- /dev/null +++ b/src/extra/autocompletionUsers/storage.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +import sqlite3, paths +from sessionmanager import manager + +class storage(object): + def __init__(self): + self.connection = sqlite3.connect(paths.config_path("%s/autocompletionUsers.dat" % (manager.manager.get_current_session()))) + self.cursor = self.connection.cursor() + if self.table_exist("users") == False: + self.create_table() + + 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_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): + self.cursor.execute("""insert or ignore into users values(?, ?)""", (screen_name, user_name)) + self.connection.commit() + + def remove_user(self, user): + self.cursor.execute("""DELETE FROM users WHERE user = ?""", (user,)) + return self.cursor.fetchone() + + def create_table(self): + self.cursor.execute(""" + create table users( +user TEXT UNIQUE, +name TEXT +)""") + + def __del__(self): + self.cursor.close() + self.connection.close() \ 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..410d7f0f --- /dev/null +++ b/src/extra/autocompletionUsers/wx_menu.py @@ -0,0 +1,18 @@ +# -*- 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() \ 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..03e99c82 --- /dev/null +++ b/src/extra/autocompletionUsers/wx_settings.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +import wx + +class autocompletionSettingsDialog(wx.Dialog): + def __init__(self): + super(autocompletionSettingsDialog, self).__init__(parent=None, id=-1, title=_(u"Autocompletion 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) + 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"Users TwBlue-database has been updated with new users."), _(u"Done"), wx.OK).ShowModal() \ No newline at end of file diff --git a/src/gui/dialogs/configuration.py b/src/gui/dialogs/configuration.py index 782ea44d..ff9a5741 100644 --- a/src/gui/dialogs/configuration.py +++ b/src/gui/dialogs/configuration.py @@ -29,6 +29,7 @@ import webbrowser import paths import platform from mysc import restart +from extra.autocompletionUsers import settings log = original_logger.getLogger("configuration") system = platform.system() @@ -50,6 +51,8 @@ class general(wx.Panel): langBox.Add(language, 0, wx.ALL, 5) langBox.Add(self.language, 0, wx.ALL, 5) sizer.Add(langBox, 0, wx.ALL, 5) + self.au = wx.Button(self, -1, u"Configure autocompltion") +# self.Bind(wx.EVT_BUTTON, self.autocompletion, au) 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) @@ -84,6 +87,7 @@ class general(wx.Panel): 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) @@ -264,6 +268,7 @@ class configurationDialog(wx.Dialog): self.general = general(notebook) notebook.AddPage(self.general, _(u"General")) self.general.SetFocus() + self.Bind(wx.EVT_BUTTON, self.autocompletion, self.general.au) self.buffers = other_buffers(notebook) notebook.AddPage(self.buffers, _(u"Show other buffers")) self.ignored_clients = ignoredClients(notebook) @@ -285,6 +290,9 @@ class configurationDialog(wx.Dialog): panel.SetSizer(sizer) self.SetClientSize(sizer.CalcMin()) + def autocompletion(self, ev): + configuration = settings.autocompletionSettings(self.parent) + def check_followers_change(self): if self.buffers.followers.GetValue() != self.buffers.followers_value: if self.buffers.followers.GetValue() == True: diff --git a/src/gui/dialogs/message.py b/src/gui/dialogs/message.py index 894814bd..b0250166 100644 --- a/src/gui/dialogs/message.py +++ b/src/gui/dialogs/message.py @@ -30,6 +30,7 @@ from twython import TwythonError from extra import translator, AudioUploader import platform from extra.AudioUploader import transfer +from extra.autocompletionUsers import completion if platform.system() != "Darwin": from extra.AudioUploader import dropbox_transfer from extra.SpellChecker import gui as spellCheckerGUI @@ -183,6 +184,8 @@ class tweet(textLimited): 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() + autocompletionButton = wx.Button(self.panel, -1, _(u"&Autocomplete users")) + self.Bind(wx.EVT_BUTTON, self.autocompletion, autocompletionButton) 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) @@ -202,8 +205,11 @@ class tweet(textLimited): self.mainBox.Add(self.ok_cancelSizer) selectId = wx.NewId() self.Bind(wx.EVT_MENU, self.onSelect, id=selectId) +# autocompletionId = wx.NewId() +# self.Bind(wx.EVT_MENU, self.autocompletion, id=autocompletionId) self.accel_tbl = wx.AcceleratorTable([ (wx.ACCEL_CTRL, ord('A'), selectId), +#(wx.ACCEL_ALT, ord('A'), autocompletionId), ]) self.SetAcceleratorTable(self.accel_tbl) self.panel.SetSizer(self.mainBox) @@ -215,6 +221,10 @@ class tweet(textLimited): self.onTimer(wx.EVT_CHAR_HOOK) self.SetClientSize(self.mainBox.CalcMin()) + def autocompletion(self, event=None): + c = completion.autocompletionUsers(self) + c.show_menu() + def onUpload_image(self, ev): if self.upload_image.GetLabel() == _(u"Discard image"): self.image = None diff --git a/src/gui/main.py b/src/gui/main.py index 6de271f1..f71830d9 100644 --- a/src/gui/main.py +++ b/src/gui/main.py @@ -211,7 +211,7 @@ class mainFrame(wx.Frame): 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) + self.sysTray=sysTrayIcon.SysTrayIcon(self) panel = wx.Panel(self) self.sizer = wx.BoxSizer(wx.VERTICAL) self.SetTitle("TW Blue") @@ -590,6 +590,7 @@ class mainFrame(wx.Frame): def exit(self, event=None): config.main.write() log.debug("Exiting...") + self.sysTray.RemoveIcon() try: self.check_streams.cancel() except AttributeError: diff --git a/src/twitter/twitter.py b/src/twitter/twitter.py index 77445acb..e64e8c2c 100644 --- a/src/twitter/twitter.py +++ b/src/twitter/twitter.py @@ -25,6 +25,7 @@ class handler(BaseHTTPServer.BaseHTTPRequestHandler): 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.") + self.wfile.close() class twitter(object): @@ -48,6 +49,8 @@ class twitter(object): 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"]) + httpd.server_close() + def save_configuration(self, user_key=None, user_secret=None): if user_key != None and user_secret != None: