This commit is contained in:
Jesús Pavón Abián
2026-01-11 20:13:56 +01:00
parent 9d9d86160d
commit 932e44a9c9
391 changed files with 120828 additions and 1090 deletions

View File

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

View File

@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import mastodon
from .panels import accountPanel, emptyPanel

View File

@@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
from .base import basePanel
from .conversationList import conversationListPanel
from .notifications import notificationsPanel
from .user import userPanel

View File

@@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
import wx
from multiplatform_widgets import widgets
class basePanel(wx.Panel):
def set_focus_function(self, f):
self.list.list.Bind(wx.EVT_LIST_ITEM_FOCUSED, f)
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, 200)
self.list.set_windows_size(1, 600)
self.list.set_windows_size(2, 200)
self.list.set_windows_size(3, 200)
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.post = wx.Button(self, -1, _("Post"))
self.boost = wx.Button(self, -1, _("Boost"))
self.reply = wx.Button(self, -1, _(u"Reply"))
self.fav = wx.Button(self, wx.ID_ANY, _("Favorite"))
self.bookmark = wx.Button(self, wx.ID_ANY, _("Bookmark"))
self.dm = wx.Button(self, -1, _(u"Direct message"))
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
btnSizer.Add(self.post, 0, wx.ALL, 5)
btnSizer.Add(self.boost, 0, wx.ALL, 5)
btnSizer.Add(self.reply, 0, wx.ALL, 5)
btnSizer.Add(self.fav, 0, wx.ALL, 5)
btnSizer.Add(self.bookmark, 0, wx.ALL, 5)
btnSizer.Add(self.dm, 0, wx.ALL, 5)
self.sizer.Add(btnSizer, 0, wx.ALL, 5)
self.sizer.Add(self.list.list, 1, wx.ALL|wx.EXPAND, 5)
self.SetSizer(self.sizer)
self.SetClientSize(self.sizer.CalcMin())
def set_position(self, reversed=False):
if reversed == False:
self.list.select_item(self.list.get_count()-1)
else:
self.list.select_item(0)
def set_focus_in_list(self):
self.list.list.SetFocus()

View File

@@ -0,0 +1,41 @@
# -*- coding: utf-8 -*-
import wx
from multiplatform_widgets import widgets
class conversationListPanel(wx.Panel):
def set_focus_function(self, f):
self.list.list.Bind(wx.EVT_LIST_ITEM_FOCUSED, f)
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, 200)
self.list.set_windows_size(1, 600)
self.list.set_windows_size(2, 200)
self.list.set_windows_size(3, 200)
self.list.set_size()
def __init__(self, parent, name):
super(conversationListPanel, self).__init__(parent)
self.name = name
self.type = "baseBuffer"
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.create_list()
self.post = wx.Button(self, -1, _("Post"))
self.reply = wx.Button(self, -1, _(u"Reply"))
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
btnSizer.Add(self.post, 0, wx.ALL, 5)
btnSizer.Add(self.reply, 0, wx.ALL, 5)
self.sizer.Add(btnSizer, 0, wx.ALL, 5)
self.sizer.Add(self.list.list, 1, wx.ALL|wx.EXPAND, 5)
self.SetSizer(self.sizer)
self.SetClientSize(self.sizer.CalcMin())
def set_position(self, reversed=False):
if reversed == False:
self.list.select_item(self.list.get_count()-1)
else:
self.list.select_item(0)
def set_focus_in_list(self):
self.list.list.SetFocus()

View File

@@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
import wx
from multiplatform_widgets import widgets
class notificationsPanel(wx.Panel):
def set_focus_function(self, f):
self.list.list.Bind(wx.EVT_LIST_ITEM_FOCUSED, f)
def create_list(self):
self.list = widgets.list(self, _("Text"), _("Date"), style=wx.LC_REPORT|wx.LC_SINGLE_SEL|wx.LC_VRULES)
self.list.set_windows_size(0, 600)
self.list.set_windows_size(1, 200)
self.list.set_size()
def __init__(self, parent, name):
super(notificationsPanel, self).__init__(parent)
self.name = name
self.type = "baseBuffer"
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.create_list()
self.post = wx.Button(self, -1, _("Post"))
self.dismiss = wx.Button(self, -1, _("Dismiss"))
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
btnSizer.Add(self.post, 0, wx.ALL, 5)
btnSizer.Add(self.dismiss, 0, wx.ALL, 5)
self.sizer.Add(btnSizer, 0, wx.ALL, 5)
self.sizer.Add(self.list.list, 1, wx.ALL|wx.EXPAND, 5)
self.SetSizer(self.sizer)
self.SetClientSize(self.sizer.CalcMin())
def set_position(self, reversed=False):
if reversed == False:
self.list.select_item(self.list.get_count()-1)
else:
self.list.select_item(0)
def set_focus_in_list(self):
self.list.list.SetFocus()

View File

@@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
import wx
from multiplatform_widgets import widgets
class userPanel(wx.Panel):
def create_list(self):
self.list = widgets.list(self, _("User"), style=wx.LC_REPORT|wx.LC_SINGLE_SEL|wx.LC_VRULES)
self.list.set_windows_size(0, 600)
self.list.set_size()
def __init__(self, parent, name):
super(userPanel, self).__init__(parent)
self.name = name
self.type = "user"
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.create_list()
self.post = wx.Button(self, -1, _("Post"))
self.actions = wx.Button(self, -1, _("Actions"))
self.message = wx.Button(self, -1, _("Message"))
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
btnSizer.Add(self.post, 0, wx.ALL, 5)
btnSizer.Add(self.actions, 0, wx.ALL, 5)
btnSizer.Add(self.message, 0, wx.ALL, 5)
self.sizer.Add(btnSizer, 0, wx.ALL, 5)
self.sizer.Add(self.list.list, 1, wx.ALL|wx.EXPAND, 5)
self.SetSizer(self.sizer)
self.SetClientSize(self.sizer.CalcMin())
def set_position(self, reversed=False):
if reversed == False:
self.list.select_item(self.list.get_count()-1)
else:
self.list.select_item(0)
def set_focus_in_list(self):
self.list.list.SetFocus()

View File

@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
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.login = wx.Button(self, -1, _(u"Login"))
sizer.Add(self.login, 0, wx.ALL, 5)
self.autostart_account = wx.CheckBox(self, -1, _(u"Log in automatically"))
sizer.Add(self.autostart_account, 0, wx.ALL, 5)
self.SetSizer(sizer)
def change_login(self, login=True):
if login == True:
self.login.SetLabel(_(u"Login"))
else:
self.login.SetLabel(_(u"Logout"))
def change_autostart(self, autostart=True):
self.autostart_account.SetValue(autostart)
def get_autostart(self):
return self.autostart_account.GetValue()
class emptyPanel(wx.Panel):
def __init__(self, parent, name):
super(emptyPanel, self).__init__(parent=parent, name=name)
self.name = name
self.type = "account"
sizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(sizer)

View File

@@ -0,0 +1,61 @@
# -*- coding: utf-8 -*-
import wx
import application
def exit_dialog(parent):
dlg = wx.MessageDialog(parent, _(u"Do you really want to close {0}?").format(application.name,), _(u"Exit"), wx.YES_NO|wx.ICON_QUESTION)
return dlg.ShowModal()
def needs_restart():
wx.MessageDialog(None, _(u" {0} must be restarted for these changes to take effect.").format(application.name,), _("Restart {0} ").format(application.name,), wx.OK).ShowModal()
def delete_user_from_db():
return wx.MessageDialog(None, _(u"Are you sure you want to delete this user from the database? This user will not appear in autocomplete results anymore."), _(u"Confirm"), wx.YES_NO|wx.ICON_QUESTION).ShowModal()
def clear_list():
dlg = wx.MessageDialog(None, _(u"Do you really want to empty this buffer? It's items will be removed from the list but not from Twitter"), _(u"Empty buffer"), wx.ICON_QUESTION|wx.YES_NO)
return dlg.ShowModal()
def remove_buffer():
return wx.MessageDialog(None, _(u"Do you really want to destroy this buffer?"), _(u"Attention"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal()
def user_not_exist():
return wx.MessageDialog(None, _(u"That user does not exist"), _(u"Error"), wx.ICON_ERROR).ShowModal()
def timeline_exist():
return wx.MessageDialog(None, _(u"A timeline for this user already exists. You can't open another"), _(u"Existing timeline"), wx.ICON_ERROR).ShowModal()
def donation():
dlg = wx.MessageDialog(None, _(u"If you like {0} we need your help to keep it going. Help us by donating to the project. This will help us pay for the server, the domain and some other things to ensure that {0} will be actively maintained. Your donation will give us the means to continue the development of {0}, and to keep {0} free. Would you like to donate now?").format(application.name), _(u"We need your help"), wx.ICON_QUESTION|wx.YES_NO)
return dlg.ShowModal()
def changed_keymap(system, keystroke_editor_shortcut):
return wx.MessageDialog(None, _(f"TWBlue has detected that you're running {system} and has changed the default keymap to the {system} keymap. It means that some keyboard shorcuts could be different. Please check the keystroke editor by pressing {keystroke_editor_shortcut} to see all available keystrokes for this keymap."), _(u"Information"), wx.OK).ShowModal()
def invalid_configuration():
return wx.MessageDialog(None, _("The configuration file is invalid."), _("Error"), wx.ICON_ERROR).ShowModal()
def dead_pid():
return wx.MessageDialog(None, _(u"{0} quit unexpectedly the last time it was run. If the problem persists, please report it to the {0} developers.").format(application.name), _(u"Warning"), wx.OK).ShowModal()
def cant_update_source() -> wx.MessageDialog:
"""Shows a dialog telling a user he /she can't update because he / she is
running from source
"""
dlg = wx.MessageDialog(None, _("Sorry, you can't update while running {} from source.").format(application.name), _("Error"), wx.OK)
return dlg.ShowModal()
def invalid_instance():
return wx.MessageDialog(None, _("the provided instance is invalid. Please try again."), _("Invalid instance"), wx.ICON_ERROR).ShowModal()
def error_adding_filter():
return wx.MessageDialog(None, _("TWBlue was unable to add or update the filter with the specified settings. Please try again."), _("Error"), wx.ICON_ERROR).ShowModal()
def error_loading_filters():
return wx.MessageDialog(None, _("TWBlue was unable to load your filters from the instance. Please try again."), _("Error"), wx.ICON_ERROR).ShowModal()
def remove_filter():
dlg = wx.MessageDialog(None, _("Do you really want to delete this filter ?"), _("Delete filter"), wx.ICON_QUESTION|wx.YES_NO)
return dlg.ShowModal()
def error_removing_filters():
return wx.MessageDialog(None, _("TWBlue was unable to remove the filter you specified. Please try again."), _("Error"), wx.ICON_ERROR).ShowModal()

View File

View File

@@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
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
def set(self, control, text):
if hasattr(self, control):
control = getattr(self, control)
if hasattr(control, "SetValue"): return getattr(control, "SetValue")(text)
elif hasattr(control, "SetLabel"): return getattr(control, "SetLabel")(text)
elif hasattr(control, "ChangeValue"): return getattr(control, "ChangeValue")(text)
else: return -1
else: return 0
def set_title(self, title):
self.SetTitle(title)

View File

@@ -0,0 +1,269 @@
# -*- coding: utf-8 -*-
import logging as original_logger
import wx
import application
import output
import config
import widgetUtils
from . import baseDialog
from multiplatform_widgets import widgets
class general(wx.Panel, baseDialog.BaseWXDialog):
def __init__(self, parent, languages,keymaps):
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.ask_at_exit = wx.CheckBox(self, -1, _(U"&Ask before exiting {0}").format(application.name,))
sizer.Add(self.ask_at_exit, 0, wx.ALL, 5)
self.no_streaming = wx.CheckBox(self, -1, _(U"&Disable Streaming functions"))
sizer.Add(self.no_streaming, 0, wx.ALL, 5)
updatePeriodBox = wx.BoxSizer(wx.HORIZONTAL)
updatePeriodBox.Add(wx.StaticText(self, -1, _(u"&Buffer update interval, in minutes")), 0, wx.ALL, 5)
self.update_period = wx.SpinCtrl(self, wx.ID_ANY)
self.update_period.SetRange(1, 30)
self.update_period.SetSize(self.update_period.GetBestSize())
updatePeriodBox.Add(self.update_period, 0, wx.ALL, 5)
sizer.Add(updatePeriodBox, 0, wx.ALL, 5)
self.play_ready_sound = wx.CheckBox(self, -1, _(U"Pla&y a sound when {0} launches").format(application.name,))
sizer.Add(self.play_ready_sound, 0, wx.ALL, 5)
self.speak_ready_msg = wx.CheckBox(self, -1, _(U"Sp&eak a message when {0} launches").format(application.name,))
sizer.Add(self.speak_ready_msg, 0, wx.ALL, 5)
self.use_invisible_shorcuts = wx.CheckBox(self, -1, _(u"&Use invisible interface's keyboard shortcuts while GUI is visible"))
sizer.Add(self.use_invisible_shorcuts, 0, wx.ALL, 5)
self.disable_sapi5 = wx.CheckBox(self, -1, _(u"A&ctivate Sapi5 when any other screen reader is not being run"))
sizer.Add(self.disable_sapi5, 0, wx.ALL, 5)
self.hide_gui = wx.CheckBox(self, -1, _(u"&Hide GUI on launch"))
sizer.Add(self.hide_gui, 0, wx.ALL, 5)
self.read_long_posts_in_gui = wx.CheckBox(self, wx.ID_ANY, _("&Read long posts in GUI"))
sizer.Add(self.read_long_posts_in_gui, 0, wx.ALL, 5)
kmbox = wx.BoxSizer(wx.VERTICAL)
km_label = wx.StaticText(self, -1, _(u"&Keymap"))
self.km = wx.ComboBox(self, -1, choices=keymaps, style=wx.CB_READONLY)
self.km.SetSize(self.km.GetBestSize())
kmbox.Add(km_label, 0, wx.ALL, 5)
kmbox.Add(self.km, 0, wx.ALL, 5)
self.check_for_updates = wx.CheckBox(self, -1, _(U"Check for u&pdates when {0} launches").format(application.name,))
sizer.Add(self.check_for_updates, 0, wx.ALL, 5)
sizer.Add(kmbox, 0, wx.ALL, 5)
self.SetSizer(sizer)
class proxy(wx.Panel, baseDialog.BaseWXDialog):
def __init__(self, parent, proxyTypes):
super(proxy, self).__init__(parent)
sizer = wx.BoxSizer(wx.VERTICAL)
type=wx.StaticText(self, wx.ID_ANY, _(u"Proxy &type: "))
self.type=wx.ComboBox(self, -1, choices=proxyTypes, style=wx.CB_READONLY)
self.type.SetSize(self.type.GetBestSize())
typeBox = wx.BoxSizer(wx.HORIZONTAL)
typeBox.Add(type, 0, wx.ALL, 5)
typeBox.Add(self.type, 0, wx.ALL, 5)
sizer.Add(typeBox, 0, wx.ALL, 5)
lbl = wx.StaticText(self, wx.ID_ANY, _(u"Proxy s&erver: "))
self.server = wx.TextCtrl(self, -1)
serverBox = wx.BoxSizer(wx.HORIZONTAL)
serverBox.Add(lbl, 0, wx.ALL, 5)
serverBox.Add(self.server, 0, wx.ALL, 5)
sizer.Add(serverBox, 0, wx.ALL, 5)
lbl = wx.StaticText(self, wx.ID_ANY, _(u"&Port: "))
self.port = wx.SpinCtrl(self, wx.ID_ANY, min=1, max=65535)
portBox = wx.BoxSizer(wx.HORIZONTAL)
portBox.Add(lbl, 0, wx.ALL, 5)
portBox.Add(self.port, 0, wx.ALL, 5)
sizer.Add(portBox, 0, wx.ALL, 5)
lbl = wx.StaticText(self, wx.ID_ANY, _(u"&User: "))
self.user = wx.TextCtrl(self, wx.ID_ANY)
userBox = wx.BoxSizer(wx.HORIZONTAL)
userBox.Add(lbl, 0, wx.ALL, 5)
userBox.Add(self.user, 0, wx.ALL, 5)
sizer.Add(userBox, 0, wx.ALL, 5)
lbl = wx.StaticText(self, wx.ID_ANY, _(u"P&assword: "))
self.password = wx.TextCtrl(self, wx.ID_ANY, style=wx.TE_PASSWORD)
passwordBox = wx.BoxSizer(wx.HORIZONTAL)
passwordBox.Add(lbl, 0, wx.ALL, 5)
passwordBox.Add(self.password, 0, wx.ALL, 5)
sizer.Add(serverBox, 0, wx.ALL, 5)
self.SetSizer(sizer)
class reporting(wx.Panel, baseDialog.BaseWXDialog):
def __init__(self, parent):
super(reporting, self).__init__(parent)
sizer = wx.BoxSizer(wx.VERTICAL)
self.speech_reporting = wx.CheckBox(self, wx.ID_ANY, _(U"Enable automatic s&peech feedback"))
sizer.Add(self.speech_reporting, 0, wx.ALL, 5)
self.braille_reporting = wx.CheckBox(self, wx.ID_ANY, _(U"Enable automatic &Braille feedback"))
sizer.Add(self.braille_reporting, 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.buffers = widgets.list(self, _(u"Buffer"), _(u"Name"), _(u"Status"), style=wx.LC_SINGLE_SEL|wx.LC_REPORT)
sizer.Add(self.buffers.list, 0, wx.ALL, 5)
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
self.toggle_state = wx.Button(self, -1, _(u"S&how/hide"))
self.up = wx.Button(self, -1, _(u"Move &up"))
self.down = wx.Button(self, -1, _(u"Move &down"))
btnSizer.Add(self.toggle_state, 0, wx.ALL, 5)
btnSizer.Add(self.up, 0, wx.ALL, 5)
btnSizer.Add(self.down, 0, wx.ALL, 5)
sizer.Add(btnSizer, 0, wx.ALL, 5)
self.SetSizer(sizer)
def insert_buffers(self, buffers):
for i in buffers:
if i[2] == True:
self.buffers.insert_item(False, *[i[0], i[1], _(u"Show")])
else:
self.buffers.insert_item(False, *[i[0], i[1], _(u"Hide")])
def connect_hook_func(self, func):
self.buffers.list.Bind(wx.EVT_CHAR_HOOK, func)
def move_up(self, *args, **kwargs):
current = self.buffers.get_selected()
if current == -1:
output.speak(_(u"Select a buffer first."), True)
return False
if self.buffers.get_text_column(current, 2) == _(u"Hide"):
output.speak(_(u"The buffer is hidden, show it first."), True)
return False
if current <= 0:
output.speak(_(u"The buffer is already at the top of the list."), True)
return False
current_text = self.buffers.get_text_column(self.buffers.get_selected(), 0)
current_name = self.buffers.get_text_column(self.buffers.get_selected(), 1)
current_text_state = self.buffers.get_text_column(self.buffers.get_selected(), 2)
text_above = self.buffers.get_text_column(self.buffers.get_selected()-1, 0)
name_above = self.buffers.get_text_column(self.buffers.get_selected()-1, 1)
text_above_state = self.buffers.get_text_column(self.buffers.get_selected()-1, 2)
self.buffers.set_text_column(self.buffers.get_selected()-1, 0, current_text)
self.buffers.set_text_column(self.buffers.get_selected()-1, 1, current_name)
self.buffers.set_text_column(self.buffers.get_selected()-1, 2, current_text_state)
self.buffers.set_text_column(self.buffers.get_selected(), 0, text_above)
self.buffers.set_text_column(self.buffers.get_selected(), 1, name_above)
self.buffers.set_text_column(self.buffers.get_selected(), 2, text_above_state)
def move_down(self, *args, **kwargs):
current = self.buffers.get_selected()
if current == -1:
output.speak(_(u"Select a buffer first."), True)
return False
if self.buffers.get_text_column(current, 2) == _(u"Hide"):
output.speak(_(u"The buffer is hidden, show it first."), True)
return False
if current+1 >= self.buffers.get_count():
output.speak(_(u"The buffer is already at the bottom of the list."), True)
return False
current_text = self.buffers.get_text_column(self.buffers.get_selected(), 0)
current_name = self.buffers.get_text_column(self.buffers.get_selected(), 1)
current_text_state = self.buffers.get_text_column(self.buffers.get_selected(), 2)
text_below = self.buffers.get_text_column(self.buffers.get_selected()+1, 0)
name_below = self.buffers.get_text_column(self.buffers.get_selected()+1, 1)
text_below_state = self.buffers.get_text_column(self.buffers.get_selected()+1, 2)
self.buffers.set_text_column(self.buffers.get_selected()+1, 0, current_text)
self.buffers.set_text_column(self.buffers.get_selected()+1, 1, current_name)
self.buffers.set_text_column(self.buffers.get_selected()+1, 2, current_text_state)
self.buffers.set_text_column(self.buffers.get_selected(), 0, text_below)
self.buffers.set_text_column(self.buffers.get_selected(), 1, name_below)
self.buffers.set_text_column(self.buffers.get_selected(), 2, text_below_state)
def get_event(self, ev):
if ev.GetKeyCode() == wx.WXK_SPACE:
return True
else:
ev.Skip()
return False
def change_selected_item(self):
current = self.buffers.get_selected()
text = self.buffers.get_text_column(current, 2)
if text == _(u"Show"):
self.buffers.set_text_column(current, 2, _(u"Hide"))
else:
self.buffers.set_text_column(current, 2, _(u"Show"))
output.speak(self.buffers.get_text_column(current, 2),True)
def get_list(self):
buffers_list = []
for i in range(0, self.buffers.get_count()):
if self.buffers.get_text_column(i, 2) == _(u"Show"):
buffers_list.append(self.buffers.get_text_column(i, 0))
return buffers_list
class TranslatorPanel(wx.Panel, baseDialog.BaseWXDialog):
def __init__(self, parent):
super(TranslatorPanel, self).__init__(parent)
sizer = wx.BoxSizer(wx.VERTICAL)
lbl_libre_url = wx.StaticText(self, wx.ID_ANY, _(u"&LibreTranslate API URL: "))
self.libre_api_url = wx.TextCtrl(self, wx.ID_ANY)
libreUrlBox = wx.BoxSizer(wx.HORIZONTAL)
libreUrlBox.Add(lbl_libre_url, 0, wx.ALL, 5)
libreUrlBox.Add(self.libre_api_url, 1, wx.ALL | wx.EXPAND, 5)
sizer.Add(libreUrlBox, 0, wx.ALL | wx.EXPAND, 5)
lbl_libre_api_key = wx.StaticText(self, wx.ID_ANY, _(u"LibreTranslate API &Key (optional): "))
self.libre_api_key = wx.TextCtrl(self, wx.ID_ANY)
libreApiKeyBox = wx.BoxSizer(wx.HORIZONTAL)
libreApiKeyBox.Add(lbl_libre_api_key, 0, wx.ALL, 5)
libreApiKeyBox.Add(self.libre_api_key, 1, wx.ALL | wx.EXPAND, 5)
sizer.Add(libreApiKeyBox, 0, wx.ALL | wx.EXPAND, 5)
lbl_deepL_api_key = wx.StaticText(self, wx.ID_ANY, _(u"&DeepL API Key: "))
self.deepL_api_key = wx.TextCtrl(self, wx.ID_ANY)
deepLApiKeyBox = wx.BoxSizer(wx.HORIZONTAL)
deepLApiKeyBox.Add(lbl_deepL_api_key, 0, wx.ALL, 5)
deepLApiKeyBox.Add(self.deepL_api_key, 1, wx.ALL | wx.EXPAND, 5)
sizer.Add(deepLApiKeyBox, 0, wx.ALL | wx.EXPAND, 5)
self.SetSizer(sizer)
class configurationDialog(baseDialog.BaseWXDialog):
def set_title(self, title):
self.SetTitle(title)
def __init__(self):
super(configurationDialog, self).__init__(None, -1)
self.panel = wx.Panel(self)
self.SetTitle(_(u"{0} preferences").format(application.name,))
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.notebook = wx.Notebook(self.panel)
def create_general(self, languageList,keymaps):
self.general = general(self.notebook, languageList,keymaps)
self.notebook.AddPage(self.general, _(u"General"))
self.general.SetFocus()
def create_proxy(self, proxyTypes):
self.proxy = proxy(self.notebook, proxyTypes)
self.notebook.AddPage(self.proxy, _(u"Proxy"))
def create_translator_panel(self):
self.translator_panel= TranslatorPanel(self.notebook)
self.notebook.AddPage(self.translator_panel, _("Translation 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, value):
p = getattr(self, panel)
control = getattr(p, key)
getattr(control, "SetValue")(value)

View File

@@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import unicode_literals
# -*- coding: utf-8 -*-
from . import baseDialog
import wx
class findDialog(baseDialog.BaseWXDialog):
def __init__(self, value=""):
super(findDialog, self).__init__(None, -1)
panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
self.SetTitle(_(u"Find in current buffer"))
label = wx.StaticText(panel, -1, _(u"String"))
self.string = wx.TextCtrl(panel, -1, value)
dc = wx.WindowDC(self.string)
dc.SetFont(self.string.GetFont())
self.string.SetSize(dc.GetTextExtent("0"*40))
sizer.Add(label, 0, wx.ALL, 5)
sizer.Add(self.string, 0, wx.ALL, 5)
ok = wx.Button(panel, wx.ID_OK, _(u"OK"))
ok.SetDefault()
cancel = wx.Button(panel, wx.ID_CANCEL, _(u"Cancel"))
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

@@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
import wx
class CommunityTimeline(wx.Dialog):
def __init__(self, *args, **kwargs):
super(CommunityTimeline, self).__init__(parent=None, *args, **kwargs)
panel = wx.Panel(self)
communitySizer = wx.BoxSizer()
self.SetTitle(_("Create community timeline"))
communityLabel = wx.StaticText(panel, -1, _("Community URL"))
self.url = wx.TextCtrl(panel, -1)
self.url.SetFocus()
communitySizer.Add(communityLabel, 0, wx.ALL, 5)
communitySizer.Add(self.url, 0, wx.ALL, 5)
actionSizer = wx.BoxSizer(wx.VERTICAL)
label2 = wx.StaticText(panel, -1, _(u"Buffer type"))
self.local= wx.RadioButton(panel, -1, _("&Local timeline"), style=wx.RB_GROUP)
self.federated= wx.RadioButton(panel, -1, _("&Federated Timeline"))
hSizer = wx.BoxSizer(wx.HORIZONTAL)
hSizer.Add(label2, 0, wx.ALL, 5)
actionSizer.Add(self.local, 0, wx.ALL, 5)
actionSizer.Add(self.federated, 0, wx.ALL, 5)
hSizer.Add(actionSizer, 0, wx.ALL, 5)
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(communitySizer)
sizer.Add(hSizer, 0, wx.ALL, 5)
sizer.Add(btnsizer)
panel.SetSizer(sizer)
def get_action(self):
if self.local.GetValue() == True: return "local"
elif self.federated.GetValue() == True: return "federated"

View File

@@ -0,0 +1,188 @@
# -*- coding: utf-8 -*-
import wx
import widgetUtils
from wxUI.dialogs import baseDialog
# As some panels are the same than those used in Twitter sessions, let's import them directly.
from wxUI.dialogs.configuration import reporting, other_buffers
from multiplatform_widgets import widgets
class generalAccount(wx.Panel, baseDialog.BaseWXDialog):
def __init__(self, parent):
super(generalAccount, self).__init__(parent)
sizer = wx.BoxSizer(wx.VERTICAL)
userAutocompletionBox = wx.StaticBox(self, label=_("User autocompletion settings"))
self.userAutocompletionScan = wx.Button(self, wx.ID_ANY, _("Scan acc&ount and add followers and following users to the user autocompletion database"))
self.userAutocompletionManage = wx.Button(self, wx.ID_ANY, _("&Manage autocompletion database"))
autocompletionSizer = wx.StaticBoxSizer(userAutocompletionBox, wx.HORIZONTAL)
autocompletionSizer.Add(self.userAutocompletionScan, 0, wx.ALL, 5)
autocompletionSizer.Add(self.userAutocompletionManage, 0, wx.ALL, 5)
sizer.Add(autocompletionSizer, 0, wx.ALL, 5)
self.disable_streaming = wx.CheckBox(self, wx.ID_ANY, _("&Disable Streaming API endpoints"))
sizer.Add(self.disable_streaming, 0, wx.ALL, 5)
self.relative_time = wx.CheckBox(self, wx.ID_ANY, _("&Relative timestamps"))
sizer.Add(self.relative_time, 0, wx.ALL, 5)
self.read_preferences_from_instance = wx.CheckBox(self, wx.ID_ANY, _("R&ead preferences from instance (default visibility when publishing and displaying sensitive content)"))
sizer.Add(self.read_preferences_from_instance, 0, wx.ALL, 5)
itemsPerCallBox = wx.BoxSizer(wx.HORIZONTAL)
itemsPerCallBox.Add(wx.StaticText(self, -1, _("&Items on each API call")), 0, wx.ALL, 5)
self.itemsPerApiCall = wx.SpinCtrl(self, wx.ID_ANY)
self.itemsPerApiCall.SetRange(0, 40)
self.itemsPerApiCall.SetSize(self.itemsPerApiCall.GetBestSize())
itemsPerCallBox.Add(self.itemsPerApiCall, 0, wx.ALL, 5)
sizer.Add(itemsPerCallBox, 0, wx.ALL, 5)
self.reverse_timelines = wx.CheckBox(self, wx.ID_ANY, _("I&nverted buffers: The newest items will be shown at the beginning while the oldest at the end"))
sizer.Add(self.reverse_timelines, 0, wx.ALL, 5)
self.ask_before_boost = wx.CheckBox(self, wx.ID_ANY, _("&Ask confirmation before boosting a post"))
sizer.Add(self.ask_before_boost, 0, wx.ALL, 5)
self.show_screen_names = wx.CheckBox(self, wx.ID_ANY, _("S&how screen names instead of full names"))
sizer.Add(self.show_screen_names, 0, wx.ALL, 5)
self.hide_emojis = wx.CheckBox(self, wx.ID_ANY, _("Hide e&mojis in usernames"))
sizer.Add(self.hide_emojis, 0, wx.ALL, 5)
PersistSizeLabel = wx.StaticText(self, -1, _("&Number of items per buffer to cache in database (0 to disable caching, blank for unlimited)"))
self.persist_size = wx.TextCtrl(self, -1)
sizer.Add(PersistSizeLabel, 0, wx.ALL, 5)
sizer.Add(self.persist_size, 0, wx.ALL, 5)
self.load_cache_in_memory = wx.CheckBox(self, wx.NewId(), _("&Load cache for items in memory (much faster in big datasets but requires more RAM)"))
self.SetSizer(sizer)
class templates(wx.Panel, baseDialog.BaseWXDialog):
def __init__(self, parent, post_template, conversation_template, person_template):
super(templates, self).__init__(parent)
sizer = wx.BoxSizer(wx.VERTICAL)
self.post = wx.Button(self, wx.ID_ANY, _("Edit template for &posts. Current template: {}").format(post_template))
sizer.Add(self.post, 0, wx.ALL, 5)
self.conversation = wx.Button(self, wx.ID_ANY, _("Edit template for c&onversations. Current template: {}").format(conversation_template))
sizer.Add(self.conversation, 0, wx.ALL, 5)
self.person = wx.Button(self, wx.ID_ANY, _("Edit template for p&ersons. Current template: {}").format(person_template))
sizer.Add(self.person, 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)
# Connect a key handler here to handle volume slider being inverted when moving with up and down arrows.
# see https://github.com/manuelcortez/TWBlue/issues/261
widgetUtils.connect_event(self.volumeCtrl, widgetUtils.KEYPRESS, self.on_keypress)
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.session_mute = wx.CheckBox(self, -1, _(u"S&ession mute"))
sizer.Add(self.session_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.indicate_audio = wx.CheckBox(self, -1, _("Indicate &audio or video in posts with sound"))
sizer.Add(self.indicate_audio, 0, wx.ALL, 5)
self.indicate_img = wx.CheckBox(self, -1, _("Indicate posts containing i&mages with sound"))
sizer.Add(self.indicate_img, 0, wx.ALL, 5)
self.SetSizer(sizer)
def on_keypress(self, event, *args, **kwargs):
""" Invert movement of up and down arrow keys when dealing with a wX Slider.
See https://github.com/manuelcortez/TWBlue/issues/261
and http://trac.wxwidgets.org/ticket/2068
"""
keycode = event.GetKeyCode()
if keycode == wx.WXK_UP:
return self.volumeCtrl.SetValue(self.volumeCtrl.GetValue()+1)
elif keycode == wx.WXK_DOWN:
return self.volumeCtrl.SetValue(self.volumeCtrl.GetValue()-1)
event.Skip()
def get(self, control):
return getattr(self, control).GetStringSelection()
class extrasPanel(wx.Panel):
def __init__(self, parent, ocr_languages=[], translation_languages=[]):
super(extrasPanel, self).__init__(parent)
mainSizer = wx.BoxSizer(wx.VERTICAL)
OCRBox = wx.StaticBox(self, label=_(u"&Language for OCR"))
self.ocr_lang = wx.ListBox(self, -1, choices=ocr_languages)
self.ocr_lang.SetSize(self.ocr_lang.GetBestSize())
ocrLanguageSizer = wx.StaticBoxSizer(OCRBox, wx.HORIZONTAL)
ocrLanguageSizer.Add(self.ocr_lang, 0, wx.ALL, 5)
mainSizer.Add(ocrLanguageSizer, 0, wx.ALL, 5)
self.SetSizer(mainSizer)
class configurationDialog(baseDialog.BaseWXDialog):
def set_title(self, title):
self.SetTitle(title)
def __init__(self):
super(configurationDialog, self).__init__(None, -1)
self.panel = wx.Panel(self)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.notebook = wx.Notebook(self.panel)
def create_general_account(self):
self.general = generalAccount(self.notebook)
self.notebook.AddPage(self.general, _(u"General"))
self.general.SetFocus()
def create_reporting(self):
self.reporting = reporting(self.notebook)
self.notebook.AddPage(self.reporting, _(u"Feedback"))
def create_other_buffers(self):
self.buffers = other_buffers(self.notebook)
self.notebook.AddPage(self.buffers, _(u"Buffers"))
def create_templates(self, post_template, conversation_template, person_template):
self.templates = templates(self.notebook, post_template=post_template, conversation_template=conversation_template, person_template=person_template)
self.notebook.AddPage(self.templates, _("Templates"))
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_extras(self, ocr_languages=[], translator_languages=[]):
self.extras = extrasPanel(self.notebook, ocr_languages, translator_languages)
self.notebook.AddPage(self.extras, _(u"Extras"))
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, value):
p = getattr(self, panel)
control = getattr(p, key)
getattr(control, "SetValue")(value)

View File

@@ -0,0 +1,62 @@
# -*- coding: utf-8 -*-
import wx
import application
def boost_question():
result = False
dlg = wx.MessageDialog(None, _("Would you like to share this post?"), _("Boost"), wx.YES_NO|wx.ICON_QUESTION)
if dlg.ShowModal() == wx.ID_YES:
result = True
dlg.Destroy()
return result
def delete_post_dialog():
result = False
dlg = wx.MessageDialog(None, _("Do you really want to delete this post? It will be deleted from the instance as well."), _("Delete"), wx.ICON_QUESTION|wx.YES_NO)
if dlg.ShowModal() == wx.ID_YES:
result = True
dlg.Destroy()
return result
def delete_notification_dialog():
result = False
dlg = wx.MessageDialog(None, _("Are you sure you want to dismiss this notification? If you dismiss a mention notification, it also disappears from your mentions buffer. The post is not going to be deleted from the instance, though."), _("Dismiss"), wx.ICON_QUESTION|wx.YES_NO)
if dlg.ShowModal() == wx.ID_YES:
result = True
dlg.Destroy()
return result
def clear_list():
result = False
dlg = wx.MessageDialog(None, _("Do you really want to empty this buffer? It's items will be removed from the list but not from the instance"), _(u"Empty buffer"), wx.ICON_QUESTION|wx.YES_NO)
if dlg.ShowModal() == wx.ID_YES:
result = True
dlg.Destroy()
return result
def no_posts():
dlg = wx.MessageDialog(None, _("This user has no posts. {0} can't create a timeline.").format(application.name), _(u"Error"), wx.ICON_ERROR)
dlg.ShowModal()
dlg.Destroy()
def no_favs():
dlg = wx.MessageDialog(None, _(u"This user has no favorited posts. {0} can't create a timeline.").format(application.name), _(u"Error"), wx.ICON_ERROR)
dlg.ShowModal()
dlg.Destroy()
def no_followers():
dlg = wx.MessageDialog(None, _(u"This user has no followers yet. {0} can't create a timeline.").format(application.name), _(u"Error"), wx.ICON_ERROR)
dlg.ShowModal()
dlg.Destroy()
def no_following():
dlg = wx.MessageDialog(None, _("This user is not following anyone. {0} can't create a timeline.").format(application.name), _(u"Error"), wx.ICON_ERROR)
dlg.ShowModal()
dlg.Destroy()
dlg.Destroy()
def no_user():
dlg = wx.MessageDialog(None, _("The focused item has no user in it. {} ca't open a user profile").format(application.name), _(u"Error"), wx.ICON_ERROR)
dlg.ShowModal()
dlg.Destroy()

View File

@@ -0,0 +1,146 @@
# -*- coding: utf-8 -*-
import wx
class FilterKeywordPanel(wx.Panel):
"""panel to handle filter's keywords. """
def __init__(self, parent):
super(FilterKeywordPanel, self).__init__(parent)
self.keywords = []
# Add widgets
list_panel = wx.Panel(self)
self.keyword_list = wx.ListCtrl(list_panel, wx.ID_ANY, style=wx.LC_REPORT | wx.LC_SINGLE_SEL)
self.keyword_list.InsertColumn(0, _("Keyword"))
self.keyword_list.InsertColumn(1, _("Whole word"))
self.keyword_list.SetColumnWidth(0, wx.LIST_AUTOSIZE_USEHEADER)
self.keyword_list.SetColumnWidth(1, wx.LIST_AUTOSIZE_USEHEADER)
list_sizer = wx.BoxSizer(wx.VERTICAL)
list_sizer.Add(self.keyword_list, 1, wx.EXPAND)
list_panel.SetSizer(list_sizer)
keyword_label = wx.StaticText(self, wx.ID_ANY, label=_("Keyword:"))
self.keyword_text = wx.TextCtrl(self, wx.ID_ANY)
keyword_sizer = wx.BoxSizer(wx.VERTICAL)
keyword_sizer.Add(keyword_label, 0, wx.RIGHT, 5)
keyword_sizer.Add(self.keyword_text, 0, wx.EXPAND)
self.whole_word_checkbox = wx.CheckBox(self, wx.ID_ANY, label=_("Whole word"))
self.add_button = wx.Button(self, wx.ID_ANY, label=_("Add"))
self.remove_button = wx.Button(self, wx.ID_ANY, label=_("Remove"))
input_sizer = wx.BoxSizer(wx.HORIZONTAL)
input_sizer.Add(keyword_sizer, 1, wx.RIGHT, 5)
input_sizer.Add(self.whole_word_checkbox, 0)
button_sizer = wx.BoxSizer(wx.HORIZONTAL)
button_sizer.Add(self.add_button, 0, wx.RIGHT, 5)
button_sizer.Add(self.remove_button, 0)
main_sizer = wx.BoxSizer(wx.VERTICAL)
main_sizer.Add(wx.StaticText(self, label=_("Keywords to filter:")), 0, wx.BOTTOM, 5)
main_sizer.Add(list_panel, 1, wx.EXPAND | wx.BOTTOM, 5)
main_sizer.Add(input_sizer, 0, wx.EXPAND | wx.BOTTOM, 5)
main_sizer.Add(button_sizer, 0, wx.ALIGN_RIGHT)
self.SetSizer(main_sizer)
def add_keyword(self, keyword, whole_word=False):
""" Adds a keyword to the list. """
index = self.keyword_list.InsertItem(self.keyword_list.GetItemCount(), keyword)
self.keyword_list.SetItem(index, 1, _("Yes") if whole_word else _("No"))
self.keyword_list.SetColumnWidth(0, wx.LIST_AUTOSIZE)
self.keyword_list.SetColumnWidth(1, wx.LIST_AUTOSIZE_USEHEADER)
self.keyword_text.Clear()
self.whole_word_checkbox.SetValue(False)
def remove_keyword(self):
""" Remove a keyword from the list. """
selection = self.keyword_list.GetFirstSelected()
if selection != -1:
self.keyword_list.DeleteItem(selection)
return selection
def set_keywords(self, keywords):
""" Set the list of keyword. """
self.keyword_list.DeleteAllItems()
for keyword_data in keywords:
if isinstance(keyword_data, dict):
kw = keyword_data.get('keyword', '')
whole_word = keyword_data.get('whole_word', False)
self.keywords.append({'keyword': kw, 'whole_word': whole_word})
index = self.keyword_list.InsertItem(self.keyword_list.GetItemCount(), kw)
self.keyword_list.SetItem(index, 1, _("Yes") if whole_word else _("No"))
else:
self.keywords.append({'keyword': keyword_data, 'whole_word': False})
index = self.keyword_list.InsertItem(self.keyword_list.GetItemCount(), keyword_data)
self.keyword_list.SetItem(index, 1, _("No"))
self.keyword_list.SetColumnWidth(0, wx.LIST_AUTOSIZE)
self.keyword_list.SetColumnWidth(1, wx.LIST_AUTOSIZE_USEHEADER)
class CreateFilterDialog(wx.Dialog):
def __init__(self, parent, title=_("New filter")):
super(CreateFilterDialog, self).__init__(parent, title=title, style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
self.contexts = ["home", "public", "notifications", "thread", "account"]
self.context_labels = {
"home": _("Home timeline"),
"public": _("Public statuses"),
"notifications": _("Notifications"),
"thread": _("Threads"),
"account": _("Profiles")
}
self.actions = ["hide", "warn"]
self.action_labels = {
"hide": _("Hide posts"),
"warn": _("Set a content warning to posts")
}
self.expiration_options = [
("never", _("Never")),
("hours", _("Hours")),
("days", _("Days")),
("weeks", _("Weeks")),
("months", _("months"))
]
main_sizer = wx.BoxSizer(wx.VERTICAL)
name_label = wx.StaticText(self, wx.ID_ANY, label=_("Title:"))
self.name_ctrl = wx.TextCtrl(self, wx.ID_ANY)
name_sizer = wx.BoxSizer(wx.HORIZONTAL)
name_sizer.Add(name_label, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
name_sizer.Add(self.name_ctrl, 1, wx.EXPAND)
main_sizer.Add(name_sizer, 0, wx.EXPAND | wx.ALL, 10)
static_box = wx.StaticBox(self, wx.ID_ANY, label=_("Apply to:"))
context_sizer = wx.StaticBoxSizer(static_box, wx.VERTICAL)
self.context_checkboxes = {}
context_grid = wx.FlexGridSizer(rows=3, cols=2, vgap=5, hgap=10)
for context in self.contexts:
checkbox = wx.CheckBox(static_box, wx.ID_ANY, label=self.context_labels[context])
self.context_checkboxes[context] = checkbox
context_grid.Add(checkbox)
context_sizer.Add(context_grid, 0, wx.ALL, 10)
main_sizer.Add(context_sizer, 0, wx.EXPAND | wx.ALL, 10)
action_label = wx.StaticText(self, wx.ID_ANY, label=_("Action:"))
self.action_choice = wx.Choice(self, wx.ID_ANY)
for action in self.actions:
self.action_choice.Append(self.action_labels[action])
action_sizer = wx.BoxSizer(wx.HORIZONTAL)
action_sizer.Add(action_label, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
action_sizer.Add(self.action_choice, 1)
main_sizer.Add(action_sizer, 0, wx.EXPAND | wx.ALL, 10)
expiration_label = wx.StaticText(self, wx.ID_ANY, label=_("Expires in:"))
self.expiration_choice = wx.Choice(self, wx.ID_ANY)
for e, label in self.expiration_options:
self.expiration_choice.Append(label)
self.expiration_value = wx.SpinCtrl(self, wx.ID_ANY, min=1, max=9999, initial=1)
self.expiration_value.Enable(False)
self.expiration_choice.Bind(wx.EVT_CHOICE, self.on_expiration_changed)
expiration_sizer = wx.BoxSizer(wx.HORIZONTAL)
expiration_sizer.Add(expiration_label, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
expiration_sizer.Add(self.expiration_choice, 1, wx.RIGHT, 5)
expiration_sizer.Add(self.expiration_value, 0)
main_sizer.Add(expiration_sizer, 0, wx.EXPAND | wx.ALL, 10)
self.keyword_panel = FilterKeywordPanel(self)
main_sizer.Add(self.keyword_panel, 1, wx.EXPAND | wx.ALL, 10)
button_sizer = self.CreateButtonSizer(wx.OK | wx.CANCEL)
main_sizer.Add(button_sizer, 0, wx.EXPAND | wx.ALL, 10)
self.SetSizer(main_sizer)
self.SetSize((450, 550))
self.action_choice.SetSelection(0)
self.expiration_choice.SetSelection(0)
wx.CallAfter(self.name_ctrl.SetFocus)
def on_expiration_changed(self, event):
selection = self.expiration_choice.GetSelection()
self.expiration_value.Enable(selection != 0)

View File

@@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
import wx
class ManageFiltersDialog(wx.Dialog):
"""
A dialog that displays a list of Mastodon filters and provides controls
to add, edit and remove them.
"""
def __init__(self, parent, title=_("Filters"), *args, **kwargs):
"""Initialize the filters view dialog. """
super(ManageFiltersDialog, self).__init__(parent, title=title, *args, **kwargs)
main_sizer = wx.BoxSizer(wx.VERTICAL)
self.filter_list = wx.ListCtrl(self, style=wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.BORDER_SUNKEN)
self.filter_list.InsertColumn(0, _("Title"), width=150)
self.filter_list.InsertColumn(1, _("Keywords"), width=80)
self.filter_list.InsertColumn(2, _("Contexts"), width=150)
self.filter_list.InsertColumn(3, _("Action"), width=100)
self.filter_list.InsertColumn(4, _("Expires"), width=150)
main_sizer.Add(self.filter_list, 1, wx.EXPAND | wx.ALL, 10)
button_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.add_button = wx.Button(self, label=_("Add"))
self.edit_button = wx.Button(self, label=_("Edit"))
self.remove_button = wx.Button(self, label=_("Remove"))
close_button = wx.Button(self, wx.ID_CLOSE)
self.edit_button.Disable()
self.remove_button.Disable()
button_sizer.Add(self.add_button, 0, wx.RIGHT, 5)
button_sizer.Add(self.edit_button, 0, wx.RIGHT, 5)
button_sizer.Add(self.remove_button, 0, wx.RIGHT, 5)
button_sizer.Add((0, 0), 1, wx.EXPAND) # Spacer to push close button to right
button_sizer.Add(close_button, 0)
self.SetEscapeId(close_button.GetId())
main_sizer.Add(button_sizer, 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, 10)
self.SetSizer(main_sizer)

View File

@@ -0,0 +1,62 @@
# -*- coding: utf-8 -*-
import wx
class base(wx.Menu):
def __init__(self):
super(base, self).__init__()
self.boost = wx.MenuItem(self, wx.ID_ANY, _("&Boost"))
self.Append(self.boost)
self.reply = wx.MenuItem(self, wx.ID_ANY, _(u"Re&ply"))
self.Append(self.reply)
self.edit = wx.MenuItem(self, wx.ID_ANY, _(u"&Edit"))
self.Append(self.edit)
self.fav = wx.MenuItem(self, wx.ID_ANY, _(u"&Add to favorites"))
self.Append(self.fav)
self.unfav = wx.MenuItem(self, wx.ID_ANY, _(u"R&emove from favorites"))
self.Append(self.unfav)
self.mute = wx.MenuItem(self, wx.ID_ANY, _(u"Mute/Unmute conversation"))
self.Append(self.mute)
self.openUrl = wx.MenuItem(self, wx.ID_ANY, _("&Open URL"))
self.Append(self.openUrl)
self.openInBrowser = wx.MenuItem(self, wx.ID_ANY, _(u"&Open in instance"))
self.Append(self.openInBrowser)
self.play = wx.MenuItem(self, wx.ID_ANY, _(u"&Play audio"))
self.Append(self.play)
self.view = wx.MenuItem(self, wx.ID_ANY, _(u"&Show post"))
self.Append(self.view)
self.copy = wx.MenuItem(self, wx.ID_ANY, _(u"&Copy to clipboard"))
self.Append(self.copy)
self.remove = wx.MenuItem(self, wx.ID_ANY, _(u"&Delete"))
self.Append(self.remove)
self.userActions = wx.MenuItem(self, wx.ID_ANY, _(u"&User actions..."))
self.Append(self.userActions)
class notification(wx.Menu):
def __init__(self, item="status"):
super(notification, self).__init__()
valid_types = ["status", "mention", "reblog", "favourite", "update", "poll"]
if item in valid_types:
self.boost = wx.MenuItem(self, wx.ID_ANY, _("&Boost"))
self.Append(self.boost)
self.reply = wx.MenuItem(self, wx.ID_ANY, _(u"Re&ply"))
self.Append(self.reply)
self.edit = wx.MenuItem(self, wx.ID_ANY, _(u"&Edit"))
self.Append(self.edit)
self.fav = wx.MenuItem(self, wx.ID_ANY, _(u"&Add to favorites"))
self.Append(self.fav)
self.unfav = wx.MenuItem(self, wx.ID_ANY, _(u"R&emove from favorites"))
self.Append(self.unfav)
self.openUrl = wx.MenuItem(self, wx.ID_ANY, _("&Open URL"))
self.Append(self.openUrl)
self.play = wx.MenuItem(self, wx.ID_ANY, _(u"&Play audio"))
self.Append(self.play)
self.openInBrowser = wx.MenuItem(self, wx.ID_ANY, _(u"&Open in instance"))
self.Append(self.openInBrowser)
self.view = wx.MenuItem(self, wx.ID_ANY, _(u"&Show post"))
self.Append(self.view)
self.copy = wx.MenuItem(self, wx.ID_ANY, _(u"&Copy to clipboard"))
self.Append(self.copy)
self.remove = wx.MenuItem(self, wx.ID_ANY, _(u"&Dismiss"))
self.Append(self.remove)
self.userActions = wx.MenuItem(self, wx.ID_ANY, _(u"&User actions..."))
self.Append(self.userActions)

View File

@@ -0,0 +1,465 @@
# -*- coding: utf-8 -*-
import wx
import wx.adv
import datetime
class Post(wx.Dialog):
def __init__(self, caption=_("Post"), text="", languages=[], *args, **kwds):
super(Post, self).__init__(parent=None, id=wx.ID_ANY, *args, **kwds)
main_sizer = wx.BoxSizer(wx.VERTICAL)
post_sizer = wx.WrapSizer(wx.VERTICAL)
main_sizer.Add(post_sizer, 1, wx.EXPAND, 0)
post_label = wx.StaticText(self, wx.ID_ANY, caption)
post_sizer.Add(post_label, 0, 0, 0)
self.text = wx.TextCtrl(self, wx.ID_ANY, text, style=wx.TE_MULTILINE)
self.Bind(wx.EVT_CHAR_HOOK, self.handle_keys, self.text)
self.text.SetMinSize((350, -1))
post_sizer.Add(self.text, 0, 0, 0)
lists_sizer = wx.BoxSizer(wx.HORIZONTAL)
main_sizer.Add(lists_sizer, 1, wx.EXPAND, 0)
attachments_sizer = wx.WrapSizer(wx.VERTICAL)
lists_sizer.Add(attachments_sizer, 1, wx.EXPAND, 0)
attachments_label = wx.StaticText(self, wx.ID_ANY, _("Attachments"))
attachments_sizer.Add(attachments_label, 0, 0, 0)
self.attachments = wx.ListCtrl(self, wx.ID_ANY, style=wx.LC_HRULES | wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.LC_VRULES)
self.attachments.Enable(False)
self.attachments.AppendColumn(_("File"), format=wx.LIST_FORMAT_LEFT, width=-1)
self.attachments.AppendColumn(_("Type"), format=wx.LIST_FORMAT_LEFT, width=-1)
self.attachments.AppendColumn(_("Description"), format=wx.LIST_FORMAT_LEFT, width=-1)
attachments_sizer.Add(self.attachments, 1, wx.EXPAND, 0)
self.remove_attachment = wx.Button(self, wx.ID_ANY, _("Remove Attachment"))
self.remove_attachment.Enable(False)
attachments_sizer.Add(self.remove_attachment, 0, 0, 0)
posts_sizer = wx.WrapSizer(wx.VERTICAL)
lists_sizer.Add(posts_sizer, 1, wx.EXPAND, 0)
posts_label = wx.StaticText(self, wx.ID_ANY, _("Post in the thread"))
posts_sizer.Add(posts_label, 0, 0, 0)
self.posts = wx.ListCtrl(self, wx.ID_ANY, style=wx.LC_HRULES | wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.LC_VRULES)
self.posts.Enable(False)
self.posts.AppendColumn(_("Text"), format=wx.LIST_FORMAT_LEFT, width=-1)
self.posts.AppendColumn(_("Attachments"), format=wx.LIST_FORMAT_LEFT, width=-1)
posts_sizer.Add(self.posts, 1, wx.EXPAND, 0)
self.remove_post = wx.Button(self, wx.ID_ANY, _("Remove post"))
self.remove_post.Enable(False)
posts_sizer.Add(self.remove_post, 0, 0, 0)
post_actions_sizer = wx.BoxSizer(wx.HORIZONTAL)
main_sizer.Add(post_actions_sizer, 1, wx.EXPAND, 0)
visibility_sizer = wx.BoxSizer(wx.HORIZONTAL)
post_actions_sizer.Add(visibility_sizer, 1, wx.EXPAND, 0)
label_1 = wx.StaticText(self, wx.ID_ANY, _("&Visibility"))
visibility_sizer.Add(label_1, 0, 0, 0)
self.visibility = wx.ComboBox(self, wx.ID_ANY, choices=[_("Public"), _("Not listed"), _("Followers only"), _("Direct")], style=wx.CB_DROPDOWN | wx.CB_READONLY | wx.CB_SIMPLE)
self.visibility.SetSelection(0)
visibility_sizer.Add(self.visibility, 0, 0, 0)
language_sizer = wx.BoxSizer(wx.HORIZONTAL)
post_actions_sizer.Add(language_sizer, 0, wx.RIGHT, 20)
lang_label = wx.StaticText(self, wx.ID_ANY, _("&Language"))
language_sizer.Add(lang_label, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
self.language = wx.ComboBox(self, wx.ID_ANY, choices=languages, style=wx.CB_DROPDOWN | wx.CB_READONLY)
language_sizer.Add(self.language, 0, wx.ALIGN_CENTER_VERTICAL, 0)
self.add = wx.Button(self, wx.ID_ANY, _("A&dd"))
self.sensitive = wx.CheckBox(self, wx.ID_ANY, _("S&ensitive content"))
self.sensitive.SetValue(False)
self.sensitive.Bind(wx.EVT_CHECKBOX, self.on_sensitivity_changed)
main_sizer.Add(self.sensitive, 0, wx.ALL, 5)
# Scheduled post section
scheduled_box = wx.BoxSizer(wx.HORIZONTAL)
self.scheduled = wx.CheckBox(self, wx.ID_ANY, _("Schedule &post"))
self.scheduled.SetValue(False)
self.scheduled.Bind(wx.EVT_CHECKBOX, self.on_schedule_changed)
scheduled_box.Add(self.scheduled, 0, wx.ALL, 5)
# Default to now + 6 minutes to be safe for the 5 minute minimum
future_dt = wx.DateTime.Now()
future_dt.Add(wx.TimeSpan(0, 6, 0, 0))
self.date_picker = wx.adv.DatePickerCtrl(self, wx.ID_ANY, dt=future_dt, style=wx.adv.DP_DROPDOWN | wx.adv.DP_SHOWCENTURY)
self.date_picker.Enable(False)
scheduled_box.Add(self.date_picker, 0, wx.ALL, 5)
self.time_picker = wx.adv.TimePickerCtrl(self, wx.ID_ANY, dt=future_dt)
self.time_picker.Enable(False)
scheduled_box.Add(self.time_picker, 0, wx.ALL, 5)
main_sizer.Add(scheduled_box, 0, wx.ALL, 5)
spoiler_box = wx.BoxSizer(wx.HORIZONTAL)
spoiler_label = wx.StaticText(self, wx.ID_ANY, _("Content warning"))
self.spoiler = wx.TextCtrl(self, wx.ID_ANY)
self.spoiler.Enable(False)
spoiler_box.Add(spoiler_label, 0, wx.ALL, 5)
spoiler_box.Add(self.spoiler, 0, wx.ALL, 10)
main_sizer.Add(spoiler_box, 0, wx.ALL, 5)
post_actions_sizer.Add(self.add, 0, 0, 0)
self.add_post = wx.Button(self, wx.ID_ANY, _("Add p&ost"))
post_actions_sizer.Add(self.add_post, 0, 0, 0)
text_actions_sizer = wx.BoxSizer(wx.HORIZONTAL)
main_sizer.Add(text_actions_sizer, 1, wx.EXPAND, 0)
self.autocomplete_users = wx.Button(self, wx.ID_ANY, _("Auto&complete users"))
text_actions_sizer.Add(self.autocomplete_users, 0, 0, 0)
self.spellcheck = wx.Button(self, wx.ID_ANY, _("Check &spelling"))
text_actions_sizer.Add(self.spellcheck, 0, 0, 0)
self.translate = wx.Button(self, wx.ID_ANY, _("&Translate"))
text_actions_sizer.Add(self.translate, 0, 0, 0)
btn_sizer = wx.StdDialogButtonSizer()
main_sizer.Add(btn_sizer, 0, wx.ALIGN_RIGHT | wx.ALL, 4)
self.send = wx.Button(self, wx.ID_ANY, _("&Send"))
self.send.SetDefault()
self.send.Bind(wx.EVT_BUTTON, self.validate_and_send)
btn_sizer.AddButton(self.send)
self.close = wx.Button(self, wx.ID_CLOSE, "")
btn_sizer.AddButton(self.close)
btn_sizer.Realize()
self.SetSizer(main_sizer)
main_sizer.Fit(self)
self.SetEscapeId(self.close.GetId())
self.Layout()
def handle_keys(self, event: wx.Event, *args, **kwargs) -> None:
""" Allows to react to certain keyboard events from the text control. """
shift=event.ShiftDown()
if event.GetKeyCode() == wx.WXK_RETURN and shift==False and hasattr(self,'send'):
self.validate_and_send()
else:
event.Skip()
def validate_and_send(self, event=None):
scheduled_at = self.get_scheduled_at()
if scheduled_at:
min_time = datetime.datetime.now() + datetime.timedelta(minutes=5)
if scheduled_at < min_time:
wx.MessageDialog(self,
_("Scheduled posts must be set at least 5 minutes in the future. Please adjust the time."),
_("Invalid scheduled time"),
wx.ICON_ERROR | wx.OK).ShowModal()
return
self.EndModal(wx.ID_OK)
def on_sensitivity_changed(self, *args, **kwargs):
self.spoiler.Enable(self.sensitive.GetValue())
def on_schedule_changed(self, *args, **kwargs):
enabled = self.scheduled.GetValue()
self.date_picker.Enable(enabled)
self.time_picker.Enable(enabled)
def get_scheduled_at(self):
if not self.scheduled.GetValue():
return None
# Get date from date picker
wx_date = self.date_picker.GetValue()
# Get time from time picker
wx_time = self.time_picker.GetValue()
# Combine into a python datetime object
dt = datetime.datetime(
wx_date.GetYear(),
wx_date.GetMonth() + 1, # wx.DateTime months are 0-11
wx_date.GetDay(),
wx_time.GetHour(),
wx_time.GetMinute(),
wx_time.GetSecond()
)
return dt
def set_title(self, chars):
self.SetTitle(_("Post - {} characters").format(chars))
def reset_controls(self):
self.text.ChangeValue("")
self.attachments.DeleteAllItems()
def add_item(self, list_type="attachment", item=[]):
if list_type == "attachment":
self.attachments.Append(item)
else:
self.posts.Append(item)
def remove_item(self, list_type="attachment"):
if list_type == "attachment":
item = self.attachments.GetFocusedItem()
if item > -1:
self.attachments.DeleteItem(item)
else:
item = self.posts.GetFocusedItem()
if item > -1:
self.posts.DeleteItem(item)
def attach_menu(self, event=None, enabled=True, *args, **kwargs):
menu = wx.Menu()
self.add_image = menu.Append(wx.ID_ANY, _("Image"))
self.add_image.Enable(enabled)
self.add_video = menu.Append(wx.ID_ANY, _("Video"))
self.add_video.Enable(enabled)
self.add_audio = menu.Append(wx.ID_ANY, _("Audio"))
self.add_audio.Enable(enabled)
self.add_poll = menu.Append(wx.ID_ANY, _("Poll"))
self.add_poll.Enable(enabled)
return menu
def ask_description(self):
dlg = wx.TextEntryDialog(self, _(u"please provide a description"), _(u"Description"))
dlg.ShowModal()
result = dlg.GetValue()
dlg.Destroy()
return result
def get_image(self):
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 (None, None)
dsc = self.ask_description()
return (openFileDialog.GetPath(), dsc)
def get_video(self):
openFileDialog = wx.FileDialog(self, _("Select the video to be uploaded"), "", "", _("Video files (*.mp4, *.mov, *.m4v, *.webm)| *.mp4; *.m4v; *.mov; *.webm"), wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)
if openFileDialog.ShowModal() == wx.ID_CANCEL:
return (None, None)
dsc = self.ask_description()
return (openFileDialog.GetPath(), dsc)
def get_audio(self):
openFileDialog = wx.FileDialog(self, _("Select the audio file to be uploaded"), "", "", _("Audio files (*.mp3, *.ogg, *.wav, *.flac, *.opus, *.aac, *.m4a, *.3gp)|*.mp3; *.ogg; *.wav; *.flac; *.opus; *.aac; *.m4a; *.3gp"), wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)
if openFileDialog.ShowModal() == wx.ID_CANCEL:
return (None, None)
dsc = self.ask_description()
return (openFileDialog.GetPath(), dsc)
def unable_to_attach_file(self, *args, **kwargs):
return wx.MessageDialog(self, _("It is not possible to add more attachments. Please take into account that You can add only a maximum of 4 images, or one audio, video or poll per post. Please remove other attachments before continuing."), _("Error adding attachment"), wx.ICON_ERROR).ShowModal()
def unable_to_attach_poll(self, *args, **kwargs):
return wx.MessageDialog(self, _("You can add a poll or media files. In order to add your poll, please remove other attachments first."), _("Error adding poll"), wx.ICON_ERROR).ShowModal()
class viewPost(wx.Dialog):
def set_title(self, length):
self.SetTitle(_("Post - %i characters ") % length)
def __init__(self, text="", boosts_count=0, favs_count=0, source="", date="", privacy="", *args, **kwargs):
super(viewPost, self).__init__(parent=None, id=wx.ID_ANY, size=(850, 850))
self.init_ui(text, boosts_count, favs_count, source, date, privacy)
def init_ui(self, text, boosts_count, favs_count, source, date, privacy):
panel = wx.Panel(self)
main_sizer = wx.BoxSizer(wx.VERTICAL)
main_sizer.Add(self.create_text_section(panel, text), 1, wx.EXPAND | wx.ALL, 5)
main_sizer.Add(self.create_image_description_section(panel), 1, wx.EXPAND | wx.ALL, 5)
main_sizer.Add(self.create_info_section(panel, privacy, boosts_count, favs_count, source, date), 0, wx.EXPAND | wx.ALL, 5)
main_sizer.Add(self.create_buttons_section(panel), 0, wx.ALIGN_RIGHT | wx.ALL, 5)
panel.SetSizer(main_sizer)
self.SetClientSize(main_sizer.CalcMin())
def create_text_section(self, panel, text):
sizer = wx.StaticBoxSizer(wx.StaticBox(panel, wx.ID_ANY, _("Post")), wx.VERTICAL)
self.text = wx.TextCtrl(panel, -1, text, style=wx.TE_READONLY | wx.TE_MULTILINE)
sizer.Add(self.text, 1, wx.EXPAND | wx.ALL, 5)
return sizer
def create_image_description_section(self, panel):
sizer = wx.StaticBoxSizer(wx.StaticBox(panel, wx.ID_ANY, _("Image description")), wx.VERTICAL)
self.image_description = wx.TextCtrl(panel, -1, style=wx.TE_READONLY | wx.TE_MULTILINE)
self.image_description.Enable(False)
sizer.Add(self.image_description, 1, wx.EXPAND | wx.ALL, 5)
return sizer
def create_info_section(self, panel, privacy, boosts_count, favs_count, source, date):
sizer = wx.StaticBoxSizer(wx.StaticBox(panel, wx.ID_ANY, _("Information")), wx.VERTICAL)
flex_sizer = wx.FlexGridSizer(cols=3, hgap=10, vgap=10)
flex_sizer.AddGrowableCol(1)
flex_sizer.Add(wx.StaticText(panel, -1, _("Privacy")), 0, wx.ALIGN_CENTER_VERTICAL)
flex_sizer.Add(wx.TextCtrl(panel, -1, privacy, style=wx.TE_READONLY | wx.TE_MULTILINE), 1, wx.EXPAND)
flex_sizer.Add(self.create_boosts_section(panel, boosts_count), 1, wx.EXPAND | wx.ALL, 5)
flex_sizer.Add(self.create_favorites_section(panel, favs_count), 1, wx.EXPAND | wx.ALL, 5)
flex_sizer.Add(wx.StaticText(panel, -1, _("Source")), 0, wx.ALIGN_CENTER_VERTICAL)
flex_sizer.Add(wx.TextCtrl(panel, -1, source, style=wx.TE_READONLY | wx.TE_MULTILINE), 1, wx.EXPAND)
flex_sizer.Add(wx.StaticText(panel, -1, _("Date")), 0, wx.ALIGN_CENTER_VERTICAL)
flex_sizer.Add(wx.TextCtrl(panel, -1, date, style=wx.TE_READONLY | wx.TE_MULTILINE), 1, wx.EXPAND)
sizer.Add(flex_sizer, 1, wx.EXPAND | wx.ALL, 5)
return sizer
def create_boosts_section(self, panel, boosts_count):
sizer = wx.StaticBoxSizer(wx.StaticBox(panel, wx.ID_ANY, _("Boosts")), wx.VERTICAL)
self.boosts_button = wx.Button(panel, -1, str(boosts_count))
self.boosts_button.SetToolTip(_("View users who boosted this post"))
sizer.Add(self.boosts_button, 1, wx.EXPAND | wx.ALL, 5)
return sizer
def create_favorites_section(self, panel, favs_count):
sizer = wx.StaticBoxSizer(wx.StaticBox(panel, wx.ID_ANY, _("Favorites")), wx.VERTICAL)
self.favorites_button = wx.Button(panel, -1, str(favs_count))
self.favorites_button.SetToolTip(_("View users who favorited this post"))
sizer.Add(self.favorites_button, 1, wx.EXPAND | wx.ALL, 5)
return sizer
def create_buttons_section(self, panel):
sizer = wx.BoxSizer(wx.HORIZONTAL)
self.mute = wx.Button(panel, wx.ID_ANY, _("&Mute conversation"))
self.mute.Enable(False)
self.share = wx.Button(panel, wx.ID_ANY, _("&Copy link to clipboard"))
self.share.Enable(False)
self.spellcheck = wx.Button(panel, wx.ID_ANY, _("Check &spelling..."))
self.translateButton = wx.Button(panel, wx.ID_ANY, _("&Translate..."))
cancelButton = wx.Button(panel, wx.ID_CANCEL, _("C&lose"))
cancelButton.SetDefault()
sizer.Add(self.mute, 0, wx.ALL, 5)
sizer.Add(self.share, 0, wx.ALL, 5)
sizer.Add(self.spellcheck, 0, wx.ALL, 5)
sizer.Add(self.translateButton, 0, wx.ALL, 5)
sizer.Add(cancelButton, 0, wx.ALL, 5)
return sizer
def set_text(self, text):
self.text.ChangeValue(text)
def get_text(self):
return self.text.GetValue()
def text_focus(self):
self.text.SetFocus()
def onSelect(self, ev):
self.text.SelectAll()
def enable_button(self, buttonName):
if hasattr(self, buttonName):
return getattr(self, buttonName).Enable()
class viewText(wx.Dialog):
def __init__(self, title="", text="", *args, **kwargs):
super(viewText, self).__init__(parent=None, id=wx.ID_ANY, size=(850,850), title=title)
panel = wx.Panel(self)
label = wx.StaticText(panel, -1, _("Text"))
self.text = wx.TextCtrl(panel, -1, text, style=wx.TE_READONLY|wx.TE_MULTILINE, size=(250, 180))
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)
self.spellcheck = wx.Button(panel, -1, _("Check &spelling..."), size=wx.DefaultSize)
self.translateButton = wx.Button(panel, -1, _(u"&Translate..."), size=wx.DefaultSize)
cancelButton = wx.Button(panel, wx.ID_CANCEL, _(u"C&lose"), size=wx.DefaultSize)
cancelButton.SetDefault()
buttonsBox = wx.BoxSizer(wx.HORIZONTAL)
buttonsBox.Add(self.spellcheck, 0, wx.ALL, 5)
buttonsBox.Add(self.translateButton, 0, wx.ALL, 5)
buttonsBox.Add(cancelButton, 0, wx.ALL, 5)
mainBox.Add(buttonsBox, 0, wx.ALL, 5)
panel.SetSizer(mainBox)
self.SetClientSize(mainBox.CalcMin())
class poll(wx.Dialog):
def __init__(self, *args, **kwds):
super(poll, self).__init__(parent=None, id=wx.NewId(), title=_("Add a poll"))
sizer_1 = wx.BoxSizer(wx.VERTICAL)
period_sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer_1.Add(period_sizer, 1, wx.EXPAND, 0)
label_period = wx.StaticText(self, wx.ID_ANY, _("&Participation time"))
period_sizer.Add(label_period, 0, 0, 0)
self.period = wx.ComboBox(self, wx.ID_ANY, choices=[_("5 minutes"), _("30 minutes"), _("1 hour"), _("6 hours"), _("1 day"), _("2 days"), _("3 days"), _("4 days"), _("5 days"), _("6 days"), _("7 days")], style=wx.CB_DROPDOWN | wx.CB_READONLY | wx.CB_SIMPLE)
self.period.SetFocus()
self.period.SetSelection(0)
period_sizer.Add(self.period, 0, 0, 0)
sizer_2 = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, _("Choices")), wx.VERTICAL)
sizer_1.Add(sizer_2, 1, wx.EXPAND, 0)
option1_sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer_2.Add(option1_sizer, 1, wx.EXPAND, 0)
label_2 = wx.StaticText(self, wx.ID_ANY, _("Option &1"))
option1_sizer.Add(label_2, 0, 0, 0)
self.option1 = wx.TextCtrl(self, wx.ID_ANY, "")
self.option1.SetMaxLength(25)
option1_sizer.Add(self.option1, 0, 0, 0)
option2_sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer_2.Add(option2_sizer, 1, wx.EXPAND, 0)
label_3 = wx.StaticText(self, wx.ID_ANY, _("Option &2"))
option2_sizer.Add(label_3, 0, 0, 0)
self.option2 = wx.TextCtrl(self, wx.ID_ANY, "")
self.option2.SetMaxLength(25)
option2_sizer.Add(self.option2, 0, 0, 0)
option3_sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer_2.Add(option3_sizer, 1, wx.EXPAND, 0)
label_4 = wx.StaticText(self, wx.ID_ANY, _("Option &3"))
option3_sizer.Add(label_4, 0, 0, 0)
self.option3 = wx.TextCtrl(self, wx.ID_ANY, "")
self.option3.SetMaxLength(25)
option3_sizer.Add(self.option3, 0, 0, 0)
option4_sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer_2.Add(option4_sizer, 1, wx.EXPAND, 0)
label_5 = wx.StaticText(self, wx.ID_ANY, _("Option &4"))
option4_sizer.Add(label_5, 0, 0, 0)
self.option4 = wx.TextCtrl(self, wx.ID_ANY, "")
self.option4.SetMaxLength(25)
option4_sizer.Add(self.option4, 0, 0, 0)
self.multiple = wx.CheckBox(self, wx.ID_ANY, _("&Allow multiple choices per user"))
self.multiple.SetValue(False)
sizer_1.Add(self.multiple, 0, wx.ALL, 5)
self.hide_votes = wx.CheckBox(self, wx.ID_ANY, _("&Hide votes count until the poll expires"))
self.hide_votes.SetValue(False)
sizer_1.Add(self.hide_votes, 0, wx.ALL, 5)
btn_sizer = wx.StdDialogButtonSizer()
sizer_1.Add(btn_sizer, 0, wx.ALIGN_RIGHT | wx.ALL, 4)
self.button_OK = wx.Button(self, wx.ID_OK)
self.button_OK.SetDefault()
self.button_OK.Bind(wx.EVT_BUTTON, self.validate_data)
btn_sizer.AddButton(self.button_OK)
self.button_CANCEL = wx.Button(self, wx.ID_CANCEL, "")
btn_sizer.AddButton(self.button_CANCEL)
btn_sizer.Realize()
self.SetSizer(sizer_1)
sizer_1.Fit(self)
self.SetAffirmativeId(self.button_OK.GetId())
self.SetEscapeId(self.button_CANCEL.GetId())
self.Layout()
def get_options(self):
controls = [self.option1, self.option2, self.option3, self.option4]
options = [option.GetValue() for option in controls if option.GetValue() != ""]
return options
def validate_data(self, *args, **kwargs):
options = self.get_options()
if len(options) < 2:
return wx.MessageDialog(self, _("Please make sure you have provided at least two options for the poll."), _("Not enough information"), wx.ICON_ERROR).ShowModal()
self.EndModal(wx.ID_OK)
class attachedPoll(wx.Dialog):
def __init__(self, poll_options, multiple=False, *args, **kwds):
super(attachedPoll, self).__init__(parent=None, id=wx.NewId(), title=_("Vote in this poll"))
self.poll_options = poll_options
sizer_1 = wx.BoxSizer(wx.VERTICAL)
sizer_2 = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, _("Options")), wx.VERTICAL)
sizer_1.Add(sizer_2, 1, wx.EXPAND, 0)
if multiple == False:
for option in range(len(self.poll_options)):
if option == 0:
setattr(self, "option{}".format(option), wx.RadioButton(self, wx.ID_ANY, poll_options[option], style=wx.RB_GROUP))
else:
setattr(self, "option{}".format(option), wx.RadioButton(self, wx.ID_ANY, poll_options[option]))
else:
for option in range(len(self.poll_options)):
setattr(self, "option{}".format(option), wx.CheckBox(self, wx.ID_ANY, poll_options[option]))
sizer_2.Add(getattr(self, "option{}".format(option)), 1, wx.EXPAND, 0)
btn_sizer = wx.StdDialogButtonSizer()
sizer_1.Add(btn_sizer, 0, wx.ALIGN_RIGHT | wx.ALL, 4)
self.button_OK = wx.Button(self, wx.ID_OK)
self.button_OK.SetDefault()
btn_sizer.AddButton(self.button_OK)
self.button_CANCEL = wx.Button(self, wx.ID_CANCEL, "")
btn_sizer.AddButton(self.button_CANCEL)
btn_sizer.Realize()
self.SetSizer(sizer_1)
sizer_1.Fit(self)
self.SetAffirmativeId(self.button_OK.GetId())
self.SetEscapeId(self.button_CANCEL.GetId())
self.Layout()
def get_selected(self):
options = []
for option in range(len(self.poll_options)):
if getattr(self, "option{}".format(option)).GetValue() == True:
options.append(option)
return options

View File

@@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
import wx
class searchDialog(wx.Dialog):
def __init__(self, value=""):
super(searchDialog, self).__init__(parent=None, id=wx.ID_ANY)
panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
self.SetTitle(_("Search"))
label = wx.StaticText(panel, wx.ID_ANY, _("&Search"))
self.term = wx.TextCtrl(panel, wx.ID_ANY, value)
self.term.SetFocus()
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.posts = wx.RadioButton(panel, wx.ID_ANY, _("Posts"), style=wx.RB_GROUP)
self.users = wx.RadioButton(panel, wx.ID_ANY, _("Users"))
radioSizer = wx.BoxSizer(wx.HORIZONTAL)
radioSizer.Add(self.posts, 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, _("&Close"))
self.SetEscapeId(cancel.GetId())
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

@@ -0,0 +1,239 @@
# -*- coding: utf-8 -*-
"""Wx dialogs for showing a user's profile."""
from io import BytesIO
from pubsub import pub
from typing import Tuple
import requests
import wx
from logging import getLogger
from threading import Thread
from sessions.mastodon.utils import html_filter
log = getLogger(__name__)
def selectUserDialog(users: list) -> tuple:
"""Choose a user from a possible list of users"""
if len(users) == 1:
return users[0]
dlg = wx.Dialog(None, title=_("Select user"))
label = wx.StaticText(dlg, label="Select a user: ")
choiceList = []
for user in users:
if len(user) == 3: # (display_name, username, id)
choiceList.append(f"{user[0]}: @{user[1]}")
else: # (acct, id)
choiceList.append(f"{user[0]}")
choice = wx.Choice(dlg, choices=choiceList)
ok = wx.Button(dlg, wx.ID_OK, _("OK"))
ok.SetDefault()
cancel = wx.Button(dlg, wx.ID_CANCEL, _("Cancel"))
dlg.SetEscapeId(cancel.GetId())
#sizers
sizer = wx.GridSizer(2, 2, 5, 5)
sizer.Add(label, wx.SizerFlags().Center())
sizer.Add(choice, wx.SizerFlags().Center())
sizer.Add(ok, wx.SizerFlags().Center())
sizer.Add(cancel, wx.SizerFlags().Center())
if dlg.ShowModal() == wx.ID_CANCEL:
return ()
# return the selected user
return users[choice.GetSelection()]
def returnTrue():
return True
class ShowUserProfile(wx.Dialog):
"""
A dialog for Showing user profile
layout is:
```
header
avatar
name
bio
meta data
```
"""
def __init__(self, user):
"""Initialize update profile dialog
Parameters:
- user: user dictionary
"""
super().__init__(parent=None)
self.user = user
self.SetTitle(_("{}'s Profile").format(user.display_name))
self.panel = wx.Panel(self)
wrapperSizer = wx.BoxSizer(wx.VERTICAL)
mainSizer = wx.GridSizer(2, 5, 5)
# create widgets
nameLabel = wx.StaticText(self.panel, label=_("&Name: "))
name = self.createTextCtrl(user.display_name, size=(200, 30))
mainSizer.Add(nameLabel, wx.SizerFlags().Center())
mainSizer.Add(name, wx.SizerFlags().Center())
urlLabel = wx.StaticText(self.panel, label=_("&URL: "))
url = self.createTextCtrl(user.url, size=(200, 30))
mainSizer.Add(urlLabel, wx.SizerFlags().Center())
mainSizer.Add(url, wx.SizerFlags().Center())
bioLabel = wx.StaticText(self.panel, label=_("&Bio: "))
bio = self.createTextCtrl(html_filter(user.note), (400, 60))
mainSizer.Add(bioLabel, wx.SizerFlags().Center())
mainSizer.Add(bio, wx.SizerFlags().Center())
joinLabel = wx.StaticText(self.panel, label=_("&Joined at: "))
joinText = self.createTextCtrl(user.created_at.strftime('%d %B, %Y'), (80, 30))
mainSizer.Add(joinLabel, wx.SizerFlags().Center())
mainSizer.Add(joinText, wx.SizerFlags().Center())
actions = wx.Button(self.panel, label=_("&Actions"))
actions.Bind(wx.EVT_BUTTON, self.onAction)
mainSizer.Add(actions, wx.SizerFlags().Center())
# header
headerLabel = wx.StaticText(self.panel, label=_("Header: "))
# Create empty image
self.headerImage = wx.StaticBitmap(self.panel)
self.headerImage.AcceptsFocusFromKeyboard = returnTrue
mainSizer.Add(headerLabel, wx.SizerFlags().Center())
mainSizer.Add(self.headerImage, wx.SizerFlags().Center())
# avatar
avatarLabel = wx.StaticText(self.panel, label=_("Avatar: "))
# Create empty image
self.avatarImage = wx.StaticBitmap(self.panel)
self.avatarImage.AcceptsFocusFromKeyboard = returnTrue
mainSizer.Add(avatarLabel, wx.SizerFlags().Center())
mainSizer.Add(self.avatarImage, wx.SizerFlags().Center())
self.fields = []
for num, field in enumerate(user.fields):
labelSizer = wx.BoxSizer(wx.HORIZONTAL)
labelLabel = wx.StaticText(self.panel, label=_("Field &{} - Label: ").format(num + 1))
labelSizer.Add(labelLabel, wx.SizerFlags().Center().Border(wx.ALL, 5))
labelText = self.createTextCtrl(html_filter(field.name), (230, 30), True)
labelSizer.Add(labelText, wx.SizerFlags().Expand().Border(wx.ALL, 5))
mainSizer.Add(labelSizer, 0, wx.CENTER)
contentSizer = wx.BoxSizer(wx.HORIZONTAL)
contentLabel = wx.StaticText(self.panel, label=_("Content: "))
contentSizer.Add(contentLabel, wx.SizerFlags().Center())
contentText = self.createTextCtrl(html_filter(field.value), (400, 60), True)
contentSizer.Add(contentText, wx.SizerFlags().Center())
mainSizer.Add(contentSizer, 0, wx.CENTER | wx.LEFT, 10)
bullSwitch = {True: _('Yes'), False: _('No'), None: _('No')}
privateSizer = wx.BoxSizer(wx.HORIZONTAL)
privateLabel = wx.StaticText(self.panel, label=_("&Private account: "))
private = self.createTextCtrl(bullSwitch[user.locked], (30, 30))
privateSizer.Add(privateLabel, wx.SizerFlags().Center())
privateSizer.Add(private, wx.SizerFlags().Center())
mainSizer.Add(privateSizer, 0, wx.ALL | wx.CENTER)
botSizer = wx.BoxSizer(wx.HORIZONTAL)
botLabel = wx.StaticText(self.panel, label=_("B&ot account: "))
botText = self.createTextCtrl(bullSwitch[user.bot], (30, 30))
botSizer.Add(botLabel, wx.SizerFlags().Center())
botSizer.Add(botText, wx.SizerFlags().Center())
mainSizer.Add(botSizer, 0, wx.ALL | wx.CENTER)
discoverSizer = wx.BoxSizer(wx.HORIZONTAL)
discoverLabel = wx.StaticText(self.panel, label=_("&Discoverable account: "))
discoverText = self.createTextCtrl(bullSwitch[user.discoverable], (30, 30))
discoverSizer.Add(discoverLabel, wx.SizerFlags().Center())
discoverSizer.Add(discoverText, wx.SizerFlags().Center())
mainSizer.Add(discoverSizer, 0, wx.ALL | wx.CENTER)
posts = wx.Button(self.panel, label=_("{} pos&ts. Click to open posts timeline").format(user.statuses_count))
# posts.SetToolTip(_("Click to open {}'s posts").format(user.display_name))
posts.Bind(wx.EVT_BUTTON, self.onPost)
mainSizer.Add(posts, wx.SizerFlags().Center())
following = wx.Button(self.panel, label=_("{} &following. Click to open Following timeline").format(user.following_count))
mainSizer.Add(following, wx.SizerFlags().Center())
following.Bind(wx.EVT_BUTTON, self.onFollowing)
followers = wx.Button(self.panel, label=_("{} fo&llowers. Click to open followers timeline").format(user.followers_count))
mainSizer.Add(followers, wx.SizerFlags().Center())
followers.Bind(wx.EVT_BUTTON, self.onFollowers)
close = wx.Button(self.panel, wx.ID_CLOSE, _("&Close"))
self.SetEscapeId(close.GetId())
close.SetDefault()
wrapperSizer.Add(mainSizer, 0, wx.CENTER)
wrapperSizer.Add(close, wx.SizerFlags().Center())
self.panel.SetSizer(wrapperSizer)
wrapperSizer.Fit(self.panel)
self.panel.Center()
mainSizer.Fit(self)
self.Center()
imageDownloaderThread = Thread(target=self._getImages)
imageDownloaderThread.start()
def createTextCtrl(self, text: str, size: Tuple[int, int], multiline: bool = False) -> wx.TextCtrl:
"""Creates a wx.TextCtrl and returns it
Parameters:
text: The value of the wx.TextCtrl
size: The size of the wx.TextCtrl
Returns: the created wx.TextCtrl object
"""
if not multiline:
style= wx.TE_PROCESS_ENTER | wx.TE_PROCESS_TAB | wx.TE_READONLY
else:
style= wx.TE_PROCESS_ENTER | wx.TE_PROCESS_TAB | wx.TE_READONLY | wx.TE_MULTILINE
textCtrl = wx.TextCtrl(self.panel, value=text, size=size, style=style)
textCtrl.AcceptsFocusFromKeyboard = returnTrue
return textCtrl
def onAction(self, *args):
"""Opens the Open timeline dialog"""
pub.sendMessage('execute-action', action='follow')
def onPost(self, *args):
"""Open this user's timeline"""
pub.sendMessage('execute-action', action='openPostTimeline', kwargs=dict(user=self.user))
def onFollowing(self, *args):
"""Open following timeline for this user"""
pub.sendMessage('execute-action', action='openFollowingTimeline', kwargs=dict(user=self.user))
def onFollowers(self, *args):
"""Open followers timeline for this user"""
pub.sendMessage('execute-action', action='openFollowersTimeline', kwargs=dict(user=self.user))
def _getImages(self):
"""Downloads image from mastodon server
This method should run on a separate thread
"""
log.debug("Downloading user's header and avatar images...")
try:
header = requests.get(self.user.header)
avatar = requests.get(self.user.avatar)
except requests.exceptions.RequestException as mess:
log.exception("An exception was raised while downloading images:", mess)
return
wx.CallAfter(self._drawImages, header.content, avatar.content)
def _drawImages(self, headerImageBytes, avatarImageBytes):
"""Draws images on the bitmap ui"""
# log.debug("Drawing images...")
# Header
headerImage = wx.Image(BytesIO(headerImageBytes), wx.BITMAP_TYPE_ANY)
headerImage.Rescale(300, 100, wx.IMAGE_QUALITY_HIGH)
self.headerImage.SetBitmap(headerImage.ConvertToBitmap())
# Avatar
avatarImage = wx.Image(BytesIO(avatarImageBytes), wx.BITMAP_TYPE_ANY)
avatarImage.Rescale(150, 150, wx.IMAGE_QUALITY_HIGH)
self.avatarImage.SetBitmap(avatarImage.ConvertToBitmap())

View File

@@ -0,0 +1,205 @@
# -*- coding: utf-8 -*-
import os
import requests
from io import BytesIO
import wx
def return_true():
return True
class UpdateProfileDialog(wx.Dialog):
"""
A dialog for user to update his / her profile details.
layout is:
```
header
avatar
name
bio
meta data
```
"""
def __init__(self, display_name: str, note: str, header: str, avatar: str, fields: list, locked: bool, bot: bool, discoverable: bool):
"""Initialize update profile dialog
Parameters:
- display_name: The user's display name to show in the display name field
- note: The users bio to show in the bio field
- header: the users header pic link
- avatar: The users avatar pic link
"""
super().__init__(parent=None)
self.SetTitle(_("Update Profile"))
self.header = header
self.avatar = avatar
panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
# create widgets
display_name_label = wx.StaticText(panel, label=_("&Display Name"))
self.display_name = wx.TextCtrl(panel, value=display_name, style= wx.TE_PROCESS_ENTER, size=(200, 30))
name_sizer = wx.BoxSizer(wx.HORIZONTAL)
name_sizer.Add(display_name_label, wx.SizerFlags().Center())
name_sizer.Add(self.display_name, wx.SizerFlags().Center())
sizer.Add(name_sizer, wx.CENTER)
bio_label = wx.StaticText(panel, label=_("&Bio"))
self.bio = wx.TextCtrl(panel, value=note, style=wx.TE_PROCESS_ENTER | wx.TE_MULTILINE, size=(400, 60))
bio_sizer = wx.BoxSizer(wx.HORIZONTAL)
bio_sizer.Add(bio_label, wx.SizerFlags().Center())
bio_sizer.Add(self.bio, wx.SizerFlags().Center())
sizer.Add(bio_sizer, wx.CENTER)
# header
header_label = wx.StaticText(panel, label=_("Header"))
try:
response = requests.get(self.header)
except requests.exceptions.RequestException:
# Create empty image
self.header_image = wx.StaticBitmap()
else:
image_bytes = BytesIO(response.content)
image = wx.Image(image_bytes, wx.BITMAP_TYPE_ANY)
image.Rescale(300, 100, wx.IMAGE_QUALITY_HIGH)
self.header_image = wx.StaticBitmap(panel, bitmap=image.ConvertToBitmap())
self.header_image.AcceptsFocusFromKeyboard = return_true
self.change_header = wx.Button(panel, label=_("Change &header"))
header_sizer = wx.BoxSizer(wx.HORIZONTAL)
header_sizer.Add(header_label, wx.SizerFlags().Center())
header_sizer.Add(self.header_image, wx.SizerFlags().Center())
header_sizer.Add(self.change_header, wx.SizerFlags().Center())
sizer.Add(header_sizer, wx.CENTER)
# avatar
avatar_label = wx.StaticText(panel, label=_("Avatar"))
try:
response = requests.get(self.avatar)
except requests.exceptions.RequestException:
# Create empty image
self.avatar_image = wx.StaticBitmap()
else:
image_bytes = BytesIO(response.content)
image = wx.Image(image_bytes, wx.BITMAP_TYPE_ANY)
image.Rescale(150, 150, wx.IMAGE_QUALITY_HIGH)
self.avatar_image = wx.StaticBitmap(panel, bitmap=image.ConvertToBitmap())
self.avatar_image.AcceptsFocusFromKeyboard = return_true
self.change_avatar = wx.Button(panel, label=_("Change &avatar"))
avatar_sizer = wx.BoxSizer(wx.HORIZONTAL)
avatar_sizer.Add(avatar_label, wx.SizerFlags().Center())
avatar_sizer.Add(self.avatar_image, wx.SizerFlags().Center())
avatar_sizer.Add(self.change_avatar, wx.SizerFlags().Center())
sizer.Add(avatar_sizer, wx.CENTER)
self.fields = []
for i in range(1, 5):
field_sizer = wx.BoxSizer(wx.HORIZONTAL)
field_label = wx.StaticText(panel, label=_("Field &{}: Label").format(i))
field_sizer.Add(field_label, wx.SizerFlags().Center().Border(wx.ALL, 5))
label_textctrl = wx.TextCtrl(panel, style=wx.TE_PROCESS_ENTER | wx.TE_MULTILINE, size=(200, 30))
if i <= len(fields):
label_textctrl.SetValue(fields[i-1][0])
field_sizer.Add(label_textctrl, wx.SizerFlags().Expand().Border(wx.ALL, 5))
content_label = wx.StaticText(panel, label=_("Content"))
field_sizer.Add(content_label, wx.SizerFlags().Center().Border(wx.ALL, 5))
content_textctrl = wx.TextCtrl(panel, style=wx.TE_PROCESS_ENTER | wx.TE_MULTILINE, size=(400, 60))
if i <= len(fields):
content_textctrl.SetValue(fields[i-1][1])
field_sizer.Add(content_textctrl, wx.SizerFlags().Expand().Border(wx.ALL, 5))
sizer.Add(field_sizer, 0, wx.CENTER)
self.fields.append((label_textctrl, content_textctrl))
self.locked = wx.CheckBox(panel, label=_("&Private account"))
self.locked.SetValue(locked)
self.bot = wx.CheckBox(panel, label=_("B&ot account"))
self.bot.SetValue(bot)
self.discoverable = wx.CheckBox(panel, label=_("&Discoverable account"))
self.discoverable.SetValue(discoverable)
sizer.Add(self.locked, wx.SizerFlags().Expand().Border(wx.ALL, 5))
sizer.Add(self.bot, wx.SizerFlags().Expand().Border(wx.ALL, 5))
sizer.Add(self.discoverable, wx.SizerFlags().Expand().Border(wx.ALL, 5))
ok = wx.Button(panel, wx.ID_OK, _(u"&OK"))
ok.SetDefault()
cancel = wx.Button(panel, wx.ID_CANCEL, _("&Close"))
self.SetEscapeId(cancel.GetId())
action_sizer = wx.BoxSizer(wx.HORIZONTAL)
action_sizer.Add(ok, wx.SizerFlags().Center())
action_sizer.Add(cancel, wx.SizerFlags().Center())
sizer.Add(action_sizer, wx.CENTER)
panel.SetSizer(sizer)
sizer.Fit(self)
self.Center()
# manage events
ok.Bind(wx.EVT_BUTTON, self.on_ok)
self.change_header.Bind(wx.EVT_BUTTON, self.on_change_header)
self.change_avatar.Bind(wx.EVT_BUTTON, self.on_change_avatar)
self.AutoLayout = True
def on_ok(self, *args):
"""Method called when user clicks ok in dialog"""
self.data = {
'display_name': self.display_name.GetValue(),
'note': self.bio.GetValue(),
'header': self.header,
'avatar': self.avatar,
'fields': [(label.GetValue(), content.GetValue()) for label, content in self.fields if label.GetValue() and content.GetValue()],
'locked': self.locked.GetValue(),
'bot': self.bot.GetValue(),
'discoverable': self.discoverable.GetValue(),
}
self.EndModal(wx.ID_OK)
def on_change_header(self, *args):
"""Display a dialog for the user to choose a picture and update the
appropriate attribute"""
wildcard = "Images (*.png;*.jpg;*.gif)|*.png;*.jpg;*.gif"
dlg = wx.FileDialog(self, _("Select header image - max 2MB"), wildcard=wildcard)
if dlg.ShowModal() == wx.CLOSE:
return
if os.path.getsize(dlg.GetPath()) > 2097152:
# File size exceeds the limit
message = _("The selected file is larger than 2MB. Do you want to select another file?")
caption = _("File more than 2MB")
style = wx.YES_NO | wx.ICON_WARNING
# Display the message box
result = wx.MessageBox(message, caption, style)
return self.on_change_header() if result == wx.YES else None
self.header = dlg.GetPath()
image = wx.Image(self.header, wx.BITMAP_TYPE_ANY)
image.Rescale(150, 150, wx.IMAGE_QUALITY_HIGH)
self.header_image.SetBitmap(image.ConvertToBitmap())
def on_change_avatar(self, *args):
"""Display a dialog for the user to choose a picture and update the
appropriate attribute"""
wildcard = "Images (*.png;*.jpg;*.gif)|*.png;*.jpg;*.gif"
dlg = wx.FileDialog(self, _("Select avatar image - max 2MB"), wildcard=wildcard)
if dlg.ShowModal() == wx.CLOSE:
return
if os.path.getsize(dlg.GetPath()) > 2097152:
# File size exceeds the limit
message = _("The selected file is larger than 2MB. Do you want to select another file?")
caption = _("File more than 2MB")
style = wx.YES_NO | wx.ICON_WARNING
# Display the message box
result = wx.MessageBox(message, caption, style)
return self.on_change_avatar() if result == wx.YES else None
self.avatar = dlg.GetPath()
image = wx.Image(self.avatar, wx.BITMAP_TYPE_ANY)
image.Rescale(150, 150, wx.IMAGE_QUALITY_HIGH)
self.avatar_image.SetBitmap(image.ConvertToBitmap())

View File

@@ -0,0 +1,79 @@
# -*- coding: utf-8 -*-
import wx
class UserActionsDialog(wx.Dialog):
def __init__(self, users=[], default="follow", *args, **kwargs):
super(UserActionsDialog, self).__init__(parent=None, *args, **kwargs)
panel = wx.Panel(self)
userSizer = wx.BoxSizer()
self.SetTitle(_(u"Action"))
userLabel = wx.StaticText(panel, -1, _(u"&User"))
self.cb = wx.ComboBox(panel, -1, choices=users, value=users[0])
self.cb.SetFocus()
self.autocompletion = wx.Button(panel, -1, _(u"&Autocomplete users"))
userSizer.Add(userLabel, 0, wx.ALL, 5)
userSizer.Add(self.cb, 0, wx.ALL, 5)
userSizer.Add(self.autocompletion, 0, wx.ALL, 5)
actionSizer = wx.BoxSizer(wx.VERTICAL)
label2 = wx.StaticText(panel, -1, _(u"Action"))
self.follow = wx.RadioButton(panel, -1, _(u"&Follow"), name=_(u"Action"), style=wx.RB_GROUP)
self.unfollow = wx.RadioButton(panel, -1, _(u"U&nfollow"))
self.mute = wx.RadioButton(panel, -1, _(u"&Mute"))
self.unmute = wx.RadioButton(panel, -1, _(u"Unmu&te"))
self.block = wx.RadioButton(panel, -1, _(u"&Block"))
self.unblock = wx.RadioButton(panel, -1, _(u"Unbl&ock"))
self.setup_default(default)
hSizer = wx.BoxSizer(wx.HORIZONTAL)
hSizer.Add(label2, 0, wx.ALL, 5)
actionSizer.Add(self.follow, 0, wx.ALL, 5)
actionSizer.Add(self.unfollow, 0, wx.ALL, 5)
actionSizer.Add(self.mute, 0, wx.ALL, 5)
actionSizer.Add(self.unmute, 0, wx.ALL, 5)
actionSizer.Add(self.block, 0, wx.ALL, 5)
actionSizer.Add(self.unblock, 0, wx.ALL, 5)
hSizer.Add(actionSizer, 0, wx.ALL, 5)
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(hSizer, 0, wx.ALL, 5)
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.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 == "block":
self.block.SetValue(True)
elif default == "unblock":
self.unblock.SetValue(True)
def get_response(self):
return self.ShowModal()
def get_user(self):
return self.cb.GetValue()
def get_position(self):
return self.cb.GetPosition()
def popup_menu(self, menu):
self.PopupMenu(menu, self.cb.GetPosition())

View File

@@ -0,0 +1,57 @@
# -*- coding: utf-8 -*-
import wx
class UserTimeline(wx.Dialog):
def __init__(self, users=[], default="posts", *args, **kwargs):
super(UserTimeline, self).__init__(parent=None, *args, **kwargs)
panel = wx.Panel(self)
userSizer = wx.BoxSizer()
self.SetTitle(_("Timeline for %s") % (users[0]))
userLabel = wx.StaticText(panel, -1, _(u"User"))
self.cb = wx.ComboBox(panel, -1, choices=users, value=users[0])
self.cb.SetFocus()
self.autocompletion = wx.Button(panel, -1, _(u"&Autocomplete users"))
userSizer.Add(userLabel, 0, wx.ALL, 5)
userSizer.Add(self.cb, 0, wx.ALL, 5)
userSizer.Add(self.autocompletion, 0, wx.ALL, 5)
actionSizer = wx.BoxSizer(wx.VERTICAL)
label2 = wx.StaticText(panel, -1, _(u"Buffer type"))
self.posts = wx.RadioButton(panel, -1, _(u"&Posts"), style=wx.RB_GROUP)
self.followers = wx.RadioButton(panel, -1, _(u"&Followers"))
self.following = wx.RadioButton(panel, -1, _("Fo&llowing"))
self.setup_default(default)
hSizer = wx.BoxSizer(wx.HORIZONTAL)
hSizer.Add(label2, 0, wx.ALL, 5)
actionSizer.Add(self.posts, 0, wx.ALL, 5)
actionSizer.Add(self.followers, 0, wx.ALL, 5)
actionSizer.Add(self.following, 0, wx.ALL, 5)
hSizer.Add(actionSizer, 0, wx.ALL, 5)
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(hSizer, 0, wx.ALL, 5)
sizer.Add(btnsizer)
panel.SetSizer(sizer)
def get_action(self):
if self.posts.GetValue() == True: return "posts"
elif self.followers.GetValue() == True: return "followers"
elif self.following.GetValue() == True: return "following"
def setup_default(self, default):
if default == "posts":
self.posts.SetValue(True)
def get_user(self):
return self.cb.GetValue()
def get_position(self):
return self.cb.GetPosition()
def popup_menu(self, menu):
self.PopupMenu(menu, self.cb.GetPosition())

View File

@@ -0,0 +1,52 @@
# -*- coding: UTF-8 -*-
import wx
import output
from typing import List
class EditTemplateDialog(wx.Dialog):
def __init__(self, template: str, variables: List[str] = [], default_template: str = "", *args, **kwds) -> None:
super(EditTemplateDialog, self).__init__(parent=None, title=_("Edit Template"), *args, **kwds)
self.default_template = default_template
mainSizer = wx.BoxSizer(wx.VERTICAL)
sizer_1 = wx.BoxSizer(wx.HORIZONTAL)
mainSizer.Add(sizer_1, 1, wx.EXPAND, 0)
label_1 = wx.StaticText(self, wx.ID_ANY, _("Edit template"))
sizer_1.Add(label_1, 0, 0, 0)
self.template = wx.TextCtrl(self, wx.ID_ANY, template)
sizer_1.Add(self.template, 0, 0, 0)
sizer_2 = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, _("Available variables")), wx.HORIZONTAL)
mainSizer.Add(sizer_2, 1, wx.EXPAND, 0)
self.variables = wx.ListBox(self, wx.ID_ANY, choices=["$"+v for v in variables])
self.variables.Bind(wx.EVT_CHAR_HOOK, self.on_keypress)
sizer_2.Add(self.variables, 0, 0, 0)
sizer_3 = wx.StdDialogButtonSizer()
mainSizer.Add(sizer_3, 0, wx.ALIGN_RIGHT | wx.ALL, 4)
self.button_SAVE = wx.Button(self, wx.ID_SAVE)
self.button_SAVE.SetDefault()
sizer_3.AddButton(self.button_SAVE)
self.button_CANCEL = wx.Button(self, wx.ID_CANCEL)
sizer_3.AddButton(self.button_CANCEL)
self.button_RESTORE = wx.Button(self, wx.ID_ANY, _("&Restore template"))
self.button_RESTORE.Bind(wx.EVT_BUTTON, self.on_restore)
sizer_3.AddButton(self.button_CANCEL)
sizer_3.Realize()
self.SetSizer(mainSizer)
mainSizer.Fit(self)
self.SetAffirmativeId(self.button_SAVE.GetId())
self.SetEscapeId(self.button_CANCEL.GetId())
self.Layout()
def on_keypress(self, event, *args, **kwargs):
if event.GetKeyCode() == wx.WXK_RETURN:
self.template.ChangeValue(self.template.GetValue()+self.variables.GetStringSelection()+", ")
output.speak(self.template.GetValue()+self.variables.GetStringSelection()+", ")
return
event.Skip()
def on_restore(self, *args, **kwargs) -> None:
self.template.ChangeValue(self.default_template)
output.speak(_("Restored template to {}.").format(self.default_template))
self.template.SetFocus()
def invalid_template() -> None:
wx.MessageDialog(None, _("the template you have specified include variables that do not exists for the object. Please fix the template and try again. For your reference, you can see a list of all available variables in the variables list while editing your template."), _("Invalid template"), wx.ICON_ERROR).ShowModal()

View File

@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import wx
class urlList(wx.Dialog):
def __init__(self, title=_(u"Select URL")):
super(urlList, self).__init__(parent=None, title=title)
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()

View File

@@ -0,0 +1,95 @@
# -*- coding: utf-8 -*-
import wx
import gettext
from . import baseDialog
class addAliasDialog(baseDialog.BaseWXDialog):
def __init__(self, title, users):
super(addAliasDialog, self).__init__(parent=None, id=wx.ID_ANY, title=title)
panel = wx.Panel(self)
userSizer = wx.BoxSizer()
self.cb = wx.ComboBox(panel, -1, choices=users, value=users[0], size=wx.DefaultSize)
self.cb.SetFocus()
self.autocompletion = wx.Button(panel, -1, _(u"&Autocomplete users"))
userSizer.Add(wx.StaticText(panel, -1, _(u"User")), 0, wx.ALL, 5)
userSizer.Add(self.cb, 0, wx.ALL, 5)
userSizer.Add(self.autocompletion, 0, wx.ALL, 5)
aliasSizer = wx.BoxSizer(wx.HORIZONTAL)
aliasLabel = wx.StaticText(panel, wx.ID_ANY, _("Alias"))
self.alias = wx.TextCtrl(panel, wx.ID_ANY)
aliasSizer.Add(aliasLabel, 0, wx.ALL, 5)
aliasSizer.Add(self.alias, 0, wx.ALL, 5)
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(aliasSizer, 0, wx.ALL, 5)
sizer.Add(btnsizer, 0, wx.ALL, 5)
panel.SetSizer(sizer)
self.SetClientSize(sizer.CalcMin())
def get_user(self):
return (self.cb.GetValue(), self.alias.GetValue())
class userAliasEditorDialog(wx.Dialog):
def __init__(self, *args, **kwds):
super(userAliasEditorDialog, self).__init__(parent=None)
self.SetTitle(_("Edit user aliases"))
main_sizer = wx.BoxSizer(wx.VERTICAL)
userListSizer = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, _("Users")), wx.VERTICAL)
main_sizer.Add(userListSizer, 1, wx.EXPAND, 0)
self.users = wx.ListBox(self, wx.ID_ANY, choices=[])
self.users.Bind(wx.EVT_LISTBOX, self.on_selection_changes)
userListSizer.Add(self.users, 0, 0, 0)
actionsSizer = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, _("Actions")), wx.HORIZONTAL)
main_sizer.Add(actionsSizer, 1, wx.EXPAND, 0)
self.add = wx.Button(self, wx.ID_ANY, _("Add alias"))
self.add.SetToolTip(_("Adds a new user alias"))
actionsSizer.Add(self.add, 0, 0, 0)
self.edit = wx.Button(self, wx.ID_ANY, _("Edit"))
self.edit.SetToolTip(_("Edit the currently focused user Alias."))
self.edit.Enable(False)
actionsSizer.Add(self.edit, 0, 0, 0)
self.remove = wx.Button(self, wx.ID_ANY, _("Remove"))
self.remove.SetToolTip(_("Remove the currently focused user alias."))
self.remove.Enable(False)
actionsSizer.Add(self.remove, 0, 0, 0)
btnSizer = wx.StdDialogButtonSizer()
main_sizer.Add(btnSizer, 0, wx.ALIGN_RIGHT | wx.ALL, 4)
self.button_CLOSE = wx.Button(self, wx.ID_CLOSE, "")
btnSizer.AddButton(self.button_CLOSE)
btnSizer.Realize()
self.SetSizer(main_sizer)
main_sizer.Fit(self)
self.SetEscapeId(self.button_CLOSE.GetId())
self.Layout()
def on_selection_changes(self, *args, **kwargs):
selection = self.users.GetSelection()
if selection == -1:
self.enable_action_buttons(False)
else:
self.enable_action_buttons(True)
def get_selected_user(self):
return self.users.GetStringSelection()
def remove_alias_dialog(self, *args, **kwargs):
dlg = wx.MessageDialog(self, _("Are you sure you want to delete this user alias?"), _("Remove user alias"), wx.YES_NO)
if dlg.ShowModal() == wx.ID_YES:
return True
else:
return False
def enable_action_buttons(self, enabled=True):
self.edit.Enable(enabled)
self.remove.Enable(enabled)
def edit_alias_dialog(self, title):
dlg = wx.TextEntryDialog(self, title, _("User alias"))
if dlg.ShowModal() == wx.ID_OK:
return dlg.GetValue()

View File

@@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
import wx
class UserListDialog(wx.Dialog):
def __init__(self, parent=None, title="", users=[]):
super(UserListDialog, self).__init__(parent=parent, title=title, size=(400, 300))
self.users = users
self.init_ui()
def init_ui(self):
panel = wx.Panel(self)
main_sizer = wx.BoxSizer(wx.VERTICAL)
title_text = wx.StaticText(panel, label=self.GetTitle())
title_font = title_text.GetFont()
title_font.PointSize += 2
title_font = title_font.Bold()
title_text.SetFont(title_font)
main_sizer.Add(title_text, 0, wx.ALIGN_CENTER | wx.TOP, 10)
user_list_box = wx.StaticBox(panel, wx.ID_ANY, "Users")
user_list_sizer = wx.StaticBoxSizer(user_list_box, wx.VERTICAL)
self.user_list = wx.ListBox(panel, wx.ID_ANY, choices=self.users, style=wx.LB_SINGLE)
user_list_sizer.Add(self.user_list, 1, wx.EXPAND | wx.ALL, 10)
main_sizer.Add(user_list_sizer, 1, wx.EXPAND | wx.ALL, 15)
buttons_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.actions_button = wx.Button(panel, wx.ID_ANY, "&Actions")
buttons_sizer.Add(self.actions_button, 0, wx.RIGHT, 10)
self.details_button = wx.Button(panel, wx.ID_ANY, _("&View profile"))
buttons_sizer.Add(self.details_button, 0, wx.RIGHT, 10)
close_button = wx.Button(panel, wx.ID_CANCEL, "&Close")
buttons_sizer.Add(close_button, 0)
main_sizer.Add(buttons_sizer, 0, wx.ALIGN_CENTER | wx.BOTTOM, 15)
panel.SetSizer(main_sizer)
# self.SetSizerAndFit(main_sizer)

View File

@@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
""" A systray for TW Blue """
from __future__ import unicode_literals
############################################################
# Copyright (c) 2014 José Manuel Delicado Alcolea <jmdaweb@gmail.com>
#
# 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 wx.adv
import application
import paths
import os
class SysTrayIcon(wx.adv.TaskBarIcon):
def __init__(self):
super(SysTrayIcon, self).__init__()
icon=wx.Icon(os.path.join(paths.app_path(), "icon.ico"), wx.BITMAP_TYPE_ICO)
self.SetIcon(icon, application.name)
self.menu=wx.Menu()
self.post = self.menu.Append(wx.ID_ANY, _(u"Post"))
self.global_settings = self.menu.Append(wx.ID_ANY, _(u"&Global settings"))
self.account_settings = self.menu.Append(wx.ID_ANY, _(u"Account se&ttings"))
# self.update_profile = self.menu.Append(wx.ID_ANY, _(u"Update &profile"))
self.show_hide = self.menu.Append(wx.ID_ANY, _(u"&Show / hide"))
self.doc = self.menu.Append(wx.ID_ANY, _(u"&Documentation"))
self.check_for_updates = self.menu.Append(wx.ID_ANY, _(u"Check for &updates"))
self.exit = self.menu.Append(wx.ID_ANY, _(u"&Exit"))
def show_menu(self):
self.PopupMenu(self.menu)
def Destroy(self):
self.menu.Destroy()
super(SysTrayIcon, self).Destroy()

206
srcantiguo/wxUI/view.py Normal file
View File

@@ -0,0 +1,206 @@
# -*- coding: utf-8 -*-
import wx
import wx.adv
import application
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."""
self.menubar = wx.MenuBar()
# Application menu
self.menubar_application = wx.Menu()
self.manage_accounts = self.menubar_application.Append(wx.ID_ANY, _(u"&Manage accounts"))
self.updateProfile = self.menubar_application.Append(wx.ID_ANY, _("&Update profile"))
self.show_hide = self.menubar_application.Append(wx.ID_ANY, _(u"&Hide window"))
self.menuitem_search = self.menubar_application.Append(wx.ID_ANY, _(u"&Search"))
self.lists = self.menubar_application.Append(wx.ID_ANY, _(u"&Lists manager"))
self.lists.Enable(False)
self.manageAliases = self.menubar_application.Append(wx.ID_ANY, _("M&anage user aliases"))
self.keystroke_editor = self.menubar_application.Append(wx.ID_ANY, _(u"&Edit keystrokes"))
self.account_settings = self.menubar_application.Append(wx.ID_ANY, _(u"Account se&ttings"))
self.prefs = self.menubar_application.Append(wx.ID_PREFERENCES, _(u"&Global settings"))
self.close = self.menubar_application.Append(wx.ID_EXIT, _(u"E&xit"))
# Compose menu
self.menubar_item = wx.Menu()
self.compose = self.menubar_item.Append(wx.ID_ANY, _(u"&Post"))
self.reply = self.menubar_item.Append(wx.ID_ANY, _(u"Re&ply"))
self.share = self.menubar_item.Append(wx.ID_ANY, _(u"&Boost"))
self.fav = self.menubar_item.Append(wx.ID_ANY, _(u"&Add to favorites"))
self.unfav = self.menubar_item.Append(wx.ID_ANY, _(u"&Remove from favorites"))
self.view = self.menubar_item.Append(wx.ID_ANY, _(u"&Show post"))
self.view_conversation = self.menubar_item.Append(wx.ID_ANY, _(u"View conversa&tion"))
self.ocr = self.menubar_item.Append(wx.ID_ANY, _(u"Read text in picture"))
self.ocr.Enable(False)
self.delete = self.menubar_item.Append(wx.ID_ANY, _(u"&Delete"))
# User menu
self.menubar_user = wx.Menu()
self.follow = self.menubar_user.Append(wx.ID_ANY, _(u"&Actions..."))
self.timeline = self.menubar_user.Append(wx.ID_ANY, _(u"&View timeline..."))
self.dm = self.menubar_user.Append(wx.ID_ANY, _(u"Direct me&ssage"))
self.addAlias = self.menubar_user.Append(wx.ID_ANY, _("Add a&lias"))
self.addToList = self.menubar_user.Append(wx.ID_ANY, _(u"&Add to list"))
self.removeFromList = self.menubar_user.Append(wx.ID_ANY, _(u"R&emove from list"))
self.details = self.menubar_user.Append(wx.ID_ANY, _(u"Show user &profile"))
self.favs = self.menubar_user.Append(wx.ID_ANY, _(u"V&iew likes"))
# buffer menu
self.menubar_buffer = wx.Menu()
self.update_buffer = self.menubar_buffer.Append(wx.ID_ANY, _(u"&Update buffer"))
self.community_timeline = self.menubar_buffer.Append(wx.ID_ANY, _("Create community timeline"))
self.trends = self.menubar_buffer.Append(wx.ID_ANY, _(u"New &trending topics buffer..."))
self.filter = self.menubar_buffer.Append(wx.ID_ANY, _(u"Create a &filter"))
self.manage_filters = self.menubar_buffer.Append(wx.ID_ANY, _(u"&Manage filters"))
self.find = self.menubar_buffer.Append(wx.ID_ANY, _(u"F&ind a string in the currently focused buffer..."))
self.load_previous_items = self.menubar_buffer.Append(wx.ID_ANY, _(u"&Load previous items"))
self.menubar_buffer.AppendSeparator()
self.mute_buffer = self.menubar_buffer.AppendCheckItem(wx.ID_ANY, _(u"&Mute"))
self.autoread = self.menubar_buffer.AppendCheckItem(wx.ID_ANY, _(u"&Autoread"))
self.clear = self.menubar_buffer.Append(wx.ID_ANY, _(u"&Clear buffer"))
self.deleteTl = self.menubar_buffer.Append(wx.ID_ANY, _(u"&Destroy"))
# audio menu
self.menubar_audio = wx.Menu()
self.seekLeft = self.menubar_audio.Append(wx.ID_ANY, _(u"Seek &back 5 seconds"))
self.seekRight = self.menubar_audio.Append(wx.ID_ANY, _(u"Seek &forward 5 seconds"))
# Help Menu
self.menubar_help = wx.Menu()
self.doc = self.menubar_help.Append(-1, _(u"&Documentation"))
self.sounds_tutorial = self.menubar_help.Append(wx.ID_ANY, _(u"Sounds &tutorial"))
self.changelog = self.menubar_help.Append(wx.ID_ANY, _(u"&What's new in this version?"))
self.check_for_updates = self.menubar_help.Append(wx.ID_ANY, _(u"&Check for updates"))
self.reportError = self.menubar_help.Append(wx.ID_ANY, _(u"&Report an error"))
self.visit_website = self.menubar_help.Append(-1, _(u"{0}'s &website").format(application.name,))
self.get_soundpacks = self.menubar_help.Append(-1, _(u"Get soundpacks for TWBlue"))
self.about = self.menubar_help.Append(-1, _(u"About &{0}").format(application.name,))
# Add all to the menu Bar
self.menubar.Append(self.menubar_application, _(u"&Application"))
self.menubar.Append(self.menubar_item, _("&Tweet"))
self.menubar.Append(self.menubar_user, _(u"&User"))
self.menubar.Append(self.menubar_buffer, _(u"&Buffer"))
self.menubar.Append(self.menubar_audio, _(u"&Audio"))
self.menubar.Append(self.menubar_help, _(u"&Help"))
self.accel_tbl = wx.AcceleratorTable([
(wx.ACCEL_CTRL, ord('N'), self.compose.GetId()),
(wx.ACCEL_CTRL, ord('R'), self.reply.GetId()),
(wx.ACCEL_CTRL|wx.ACCEL_SHIFT, ord('R'), self.share.GetId()),
(wx.ACCEL_CTRL, ord('F'), self.fav.GetId()),
(wx.ACCEL_CTRL|wx.ACCEL_SHIFT, ord('F'), self.unfav.GetId()),
(wx.ACCEL_CTRL|wx.ACCEL_SHIFT, ord('V'), self.view.GetId()),
(wx.ACCEL_CTRL, ord('D'), self.dm.GetId()),
(wx.ACCEL_CTRL, ord('Q'), self.close.GetId()),
(wx.ACCEL_CTRL, ord('S'), self.follow.GetId()),
(wx.ACCEL_CTRL, ord('I'), self.timeline.GetId()),
(wx.ACCEL_CTRL|wx.ACCEL_SHIFT, ord('I'), self.deleteTl.GetId()),
(wx.ACCEL_CTRL, ord('M'), self.show_hide.GetId()),
(wx.ACCEL_CTRL, wx.WXK_LEFT, self.seekLeft.GetId()),
(wx.ACCEL_CTRL, ord('P'), self.updateProfile.GetId()),
(wx.ACCEL_CTRL, wx.WXK_RIGHT, self.seekRight.GetId()),
(wx.ACCEL_CTRL, ord(' '), self.seekLeft.GetId()),
])
self.SetAcceleratorTable(self.accel_tbl)
### MAIN
def __init__(self):
""" Main function of this class."""
super(mainFrame, self).__init__(None, -1, application.name, size=(1600, 1600))
self.panel = wx.Panel(self)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.SetTitle(application.name)
self.makeMenus()
self.SetMenuBar(self.menubar)
self.nb = wx.Treebook(self.panel, wx.ID_ANY)
self.buffers = {}
def get_buffer_count(self):
return self.nb.GetPageCount()
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, 1, wx.ALL | wx.EXPAND, 5)
self.panel.SetSizer(self.sizer)
self.Maximize()
self.sizer.Layout()
self.SetClientSize(self.sizer.CalcMin())
# print self.GetSize()
def get_buffers(self):
return [self.nb.GetPage(i) for i in range(0, self.nb.GetPageCount())]
def search(self, name_, account):
for i in range(0, self.nb.GetPageCount()):
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_current_buffer_pos(self):
return self.nb.GetSelection()
def get_buffer(self, 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):
return self.nb.FindWindowById(id)
def advance_selection(self, forward):
self.nb.AdvanceSelection(forward)
def show(self):
self.Show()
def show_address(self, address):
wx.MessageDialog(self, address, _(u"Address"), wx.OK).ShowModal()
def delete_buffer(self, pos):
self.nb.DeletePage(pos)
def about_dialog(self):
info = wx.adv.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)
for i in application.authors:
info.AddDeveloper(i)
wx.adv.AboutBox(info)
def set_focus(self):
self.SetFocus()
def check_menuitem(self, menuitem, check=True):
if hasattr(self, menuitem):
getattr(self, menuitem).Check(check)
def set_page_title(self, page, title):
return self.nb.SetPageText(page, title)
def get_page_title(self, page):
return self.nb.GetPageText(page)
def no_update_available():
wx.MessageDialog(None, _(u"Your {0} version is up to date").format(application.name,), _(u"Update"), style=wx.OK).ShowModal()