From 2c298577cc53a9d837f4ae7539fdfc2fbaf87c6f Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Fri, 11 Nov 2022 15:51:16 -0600 Subject: [PATCH] Re-added toot dialog to make it more compatible with mastodon. Added visibility and audio attachments --- src/controller/buffers/mastodon/base.py | 41 +++-- src/controller/mastodon/messages.py | 197 +++++++++++++++++---- src/sessions/mastodon/session.py | 23 +-- src/sessions/mastodon/templates.py | 2 +- src/wxUI/dialogs/mastodon/tootDialogs.py | 214 ++++++++++++++++++++++- 5 files changed, 417 insertions(+), 60 deletions(-) diff --git a/src/controller/buffers/mastodon/base.py b/src/controller/buffers/mastodon/base.py index 8c383a3e..ae5d5a52 100644 --- a/src/controller/buffers/mastodon/base.py +++ b/src/controller/buffers/mastodon/base.py @@ -63,8 +63,8 @@ class BaseBuffer(base.Buffer): toot = messages.toot(session=self.session, title=title, caption=caption) response = toot.message.ShowModal() if response == wx.ID_OK: - toot_data = toot.get_tweet_data() - call_threaded(self.session.send_toot, toots=toot_data, **kwargs) + toot_data = toot.get_data() + call_threaded(self.session.send_toot, toots=toot_data, visibility=toot.get_visibility(), **kwargs) if hasattr(toot.message, "destroy"): toot.message.destroy() @@ -296,32 +296,41 @@ class BaseBuffer(base.Buffer): else: title = _("Reply to {}").format(item.account.username) caption = _("Write your reply here") - users = [user.acct for user in item.mentions if user.id != self.session.db["user_id"]] - toot = messages.reply(session=self.session, title=title, caption=caption, users=users) + if item.reblog != None: + users = ["@{}".format(user.acct) for user in item.reblog.mentions if user.id != self.session.db["user_id"]] + if item.reblog.account.acct != item.account.acct and "@{} ".format(item.reblog.account.acct) not in users: + users.append("@{} ".format(item.reblog.account.acct)) + else: + users = ["@{}".format(user.acct) for user in item.mentions if user.id != self.session.db["user_id"]] + if "@{} ".format(item.account.acct) not in users and item.account.id != self.session.db["user_id"]: + users.insert(0, "@{} ".format(item.account.acct)) + users_str = "".join(users) + toot = messages.toot(session=self.session, title=title, caption=caption, text=users_str) response = toot.message.ShowModal() if response == wx.ID_OK: - toot_data = toot.get_tweet_data() - users = toot.get_people() - if item.account.acct not in users and item.account.id != self.session.db["user_id"]: - users = "@{} {}".format(item.account.acct, users) - call_threaded(self.session.send_toot, reply_to=item.id, users=users, toots=toot_data, visibility=visibility) + toot_data = toot.get_data() + call_threaded(self.session.send_toot, reply_to=item.id, toots=toot_data, visibility=visibility) if hasattr(toot.message, "destroy"): toot.message.destroy() - # conversations are replies with different wording and privacy settings. def send_message(self, *args, **kwargs): item = self.get_item() title = _("Conversation with {}").format(item.account.username) caption = _("Write your message here") - users = [user.acct for user in item.mentions if user.id != self.session.db["user_id"]] - toot = messages.reply(session=self.session, title=title, caption=caption, users=users) + if item.reblog != None: + users = ["@{}".format(user.acct) for user in item.reblog.mentions if user.id != self.session.db["user_id"]] + if item.reblog.account.acct != item.account.acct and "@{} ".format(item.reblog.account.acct) not in users: + users.append("@{} ".format(item.reblog.account.acct)) + else: + users = ["@{}".format(user.acct) for user in item.mentions if user.id != self.session.db["user_id"]] + if item.account.acct not in users and item.account.id != self.session.db["user_id"]: + users.insert(0, "@{} ".format(item.account.acct)) + users_str = "".join(users) + toot = messages.toot(session=self.session, title=title, caption=caption, text=users_str) response = toot.message.ShowModal() if response == wx.ID_OK: toot_data = toot.get_tweet_data() - users = toot.get_people() - if item.account.acct not in users and item.account.id != self.session.db["user_id"]: - users = "@{} {}".format(item.account.acct, users) - call_threaded(self.session.send_toot, users=users, toots=toot_data, visibility="direct") + call_threaded(self.session.send_toot, toots=toot_data, visibility="direct") if hasattr(toot.message, "destroy"): toot.message.destroy() diff --git a/src/controller/mastodon/messages.py b/src/controller/mastodon/messages.py index 07884feb..8d09d76b 100644 --- a/src/controller/mastodon/messages.py +++ b/src/controller/mastodon/messages.py @@ -1,4 +1,6 @@ # -*- coding: utf-8 -*- +import os +import wx import widgetUtils import config import output @@ -6,50 +8,179 @@ from controller.twitter import messages from sessions.mastodon import templates from wxUI.dialogs.mastodon import tootDialogs -class toot(messages.tweet): - def __init__(self, max=500, *args, **kwargs): - super(toot, self).__init__(max=max, *args, **kwargs) - if hasattr(self.message, "add_tweet"): - self.message.add_tweet.SetLabel(_("Add toot")) - -class reply(toot): - def __init__(self, users=[], *a, **b): - super(reply, self).__init__(messageType="reply", users=users, *a, **b) - self.users = users - if len(users) > 0: - widgetUtils.connect_event(self.message.mention_all, widgetUtils.CHECKBOX, self.mention_all) - self.message.mention_all.Enable(True) - if config.app["app-settings"]["remember_mention_and_longtweet"]: - self.message.mention_all.SetValue(config.app["app-settings"]["mention_all"]) - self.mention_all() +class toot(messages.basicTweet): + def __init__(self, session, title, caption, text="", max=500, *args, **kwargs): + self.max = max + self.title = title + self.session = session + self.message = tootDialogs.Toot(caption=caption, text=text, *args, **kwargs) + self.message.SetTitle(title) self.message.text.SetInsertionPoint(len(self.message.text.GetValue())) + widgetUtils.connect_event(self.message.spellcheck, widgetUtils.BUTTON_PRESSED, self.spellcheck) + widgetUtils.connect_event(self.message.text, widgetUtils.ENTERED_TEXT, self.text_processor) + widgetUtils.connect_event(self.message.translate, widgetUtils.BUTTON_PRESSED, self.translate) + widgetUtils.connect_event(self.message.add, widgetUtils.BUTTON_PRESSED, self.on_attach) + widgetUtils.connect_event(self.message.remove_attachment, widgetUtils.BUTTON_PRESSED, self.remove_attachment) + # ToDo: Add autocomplete feature to mastodon and uncomment this. + # widgetUtils.connect_event(self.message.autocomplete_users, widgetUtils.BUTTON_PRESSED, self.autocomplete_users) + widgetUtils.connect_event(self.message.add_toot, widgetUtils.BUTTON_PRESSED, self.add_toot) + widgetUtils.connect_event(self.message.remove_toot, widgetUtils.BUTTON_PRESSED, self.remove_toot) + self.attachments = [] + self.thread = [] self.text_processor() + def add_toot(self, event, update_gui=True, *args, **kwargs): + text = self.message.text.GetValue() + attachments = self.attachments[::] + tootdata = dict(text=text, attachments=attachments) + self.thread.append(tootdata) + self.attachments = [] + if update_gui: + self.message.reset_controls() + self.message.add_item(item=[text, len(attachments)], list_type="toot") + self.message.text.SetFocus() + self.text_processor() + + def get_toot_data(self): + self.add_toot(event=None, update_gui=False) + return self.thread + def text_processor(self, *args, **kwargs): super(toot, self).text_processor(*args, **kwargs) + if len(self.thread) > 0: + if hasattr(self.message, "toots"): + self.message.toots.Enable(True) + self.message.remove_toot.Enable(True) + else: + self.message.toots.Enable(False) + self.message.remove_toot.Enable(False) if len(self.attachments) > 0: self.message.attachments.Enable(True) self.message.remove_attachment.Enable(True) else: self.message.attachments.Enable(False) self.message.remove_attachment.Enable(False) - - def mention_all(self, *args, **kwargs): - if self.message.mention_all.GetValue() == True: - for i in self.message.checkboxes: - i.SetValue(True) - i.Hide() + if len(self.message.text.GetValue()) > 0 or len(self.attachments) > 0: + self.message.add_toot.Enable(True) else: - for i in self.message.checkboxes: - i.SetValue(False) - i.Show() + self.message.add_toot.Enable(False) - def get_people(self): - people = "" - for i in range(0, len(self.message.checkboxes)): - if self.message.checkboxes[i].GetValue() == True: - people = people + "{0} ".format(self.message.checkboxes[i].GetLabel(),) - return people + def remove_toot(self, *args, **kwargs): + toot = self.message.toots.GetFocusedItem() + if toot > -1 and len(self.thread) > toot: + self.thread.pop(toot) + self.message.remove_item(list_type="toot") + self.text_processor() + self.message.text.SetFocus() + + def can_attach(self): + if len(self.attachments) == 0: + return True + elif len(self.attachments) == 1 and (self.attachments[0]["type"] == "poll" or self.attachments[0]["type"] == "video" or self.attachments[0]["type"] == "audio"): + return False + elif len(self.attachments) < 4: + return True + return False + + def on_attach(self, *args, **kwargs): + can_attach = self.can_attach() + menu = self.message.attach_menu(can_attach) + self.message.Bind(wx.EVT_MENU, self.on_attach_image, self.message.add_image) + self.message.Bind(wx.EVT_MENU, self.on_attach_video, self.message.add_video) + self.message.Bind(wx.EVT_MENU, self.on_attach_audio, self.message.add_audio) + self.message.Bind(wx.EVT_MENU, self.on_attach_poll, self.message.add_poll) + self.message.PopupMenu(menu, self.message.add.GetPosition()) + + def on_attach_image(self, *args, **kwargs): + can_attach = self.can_attach() + big_media_present = False + for a in self.attachments: + if a["type"] == "video" or a["type"] == "audio" or a["type"] == "poll": + big_media_present = True + break + if can_attach == False or big_media_present == True: + return self.message.unable_to_attach_file() + image, description = self.message.get_image() + if image != None: + if image.endswith("gif"): + image_type = "gif" + else: + image_type = "photo" + imageInfo = {"type": image_type, "file": image, "description": description} + if len(self.attachments) > 0 and image_type == "gif": + return self.message.unable_to_attach_file() + self.attachments.append(imageInfo) + self.message.add_item(item=[os.path.basename(imageInfo["file"]), imageInfo["type"], imageInfo["description"]]) + self.text_processor() + + def on_attach_video(self, *args, **kwargs): + if len(self.attachments) >= 4: + return self.message.unable_to_attach_file() + can_attach = self.can_attach() + big_media_present = False + for a in self.attachments: + if a["type"] == "video" or a["type"] == "audio" or a["type"] == "poll": + big_media_present = True + break + if can_attach == False or big_media_present == True: + return self.message.unable_to_attach_file() + video = self.message.get_video() + if video != None: + videoInfo = {"type": "video", "file": video, "description": ""} + self.attachments.append(videoInfo) + self.message.add_item(item=[os.path.basename(videoInfo["file"]), videoInfo["type"], videoInfo["description"]]) + self.text_processor() + + def on_attach_audio(self, *args, **kwargs): + if len(self.attachments) >= 4: + return self.message.unable_to_attach_file() + can_attach = self.can_attach() + big_media_present = False + for a in self.attachments: + if a["type"] == "video" or a["type"] == "audio" or a["type"] == "poll": + big_media_present = True + break + if can_attach == False or big_media_present == True: + return self.message.unable_to_attach_file() + audio = self.message.get_audio() + if audio != None: + audioInfo = {"type": "audio", "file": audio, "description": ""} + self.attachments.append(audioInfo) + self.message.add_item(item=[os.path.basename(audioInfo["file"]), audioInfo["type"], audioInfo["description"]]) + self.text_processor() + + def on_attach_poll(self, *args, **kwargs): + if len(self.attachments) > 0: + return self.message.unable_to_attach_poll() + can_attach = self.can_attach() + big_media_present = False + for a in self.attachments: + if a["type"] == "video" or a["type"] == "audio" or a["type"] == "poll": + big_media_present = True + break + if can_attach == False or big_media_present == True: + return self.message.unable_to_attach_file() + dlg = tootDialogs.poll() + if dlg.ShowModal() == wx.ID_OK: + day = 86400 + periods = [300, 1800, 3600, 21600, day, day*2, day*3, day*4, day*5, day*6, day*7] + period = periods[dlg.period.GetSelection()] + poll_options = dlg.get_options() + multiple = dlg.multiple.GetValue() + hide_totals = dlg.hide_votes.GetValue() + data = dict(type="poll", file="", description=_("Poll with {} options").format(len(poll_options)), options=poll_options, expires_in=period, multiple=multiple, hide_totals=hide_totals) + self.attachments.append(data) + self.message.add_item(item=[data["file"], data["type"], data["description"]]) + self.text_processor() + dlg.Destroy() + + def get_data(self): + self.add_toot(event=None, update_gui=False) + return self.thread + + def get_visibility(self): + visibility_settings = ["public", "unlisted", "private", "direct"] + return visibility_settings[self.message.visibility.GetSelection()] class viewToot(toot): def __init__(self, toot, offset_hours=0, date="", item_url=""): @@ -60,6 +191,8 @@ class viewToot(toot): image_description = templates.process_image_descriptions(toot.media_attachments) text = templates.process_text(toot, safe=False) date = templates.process_date(toot.created_at, relative_times=False, offset_hours=offset_hours) + privacy_settings = dict(public=_("Public"), unlisted=_("Not listed"), private=_("followers only"), direct=_("Mentioned people")) + privacy = privacy_settings.get(toot.visibility) boost_count = str(toot.reblogs_count) favs_count = str(toot.favourites_count) # Gets the client from where this toot was made. @@ -68,7 +201,7 @@ class viewToot(toot): source = _("Remote instance") else: source = source_obj.get("name") - self.message = tootDialogs.viewToot(text=text, boosts_count=boost_count, favs_count=favs_count, source=source, date=date) + self.message = tootDialogs.viewToot(text=text, boosts_count=boost_count, favs_count=favs_count, source=source, date=date, privacy=privacy) self.message.SetTitle(title) if image_description != "": self.message.image_description.Enable(True) diff --git a/src/sessions/mastodon/session.py b/src/sessions/mastodon/session.py index 589b1249..14d6e145 100644 --- a/src/sessions/mastodon/session.py +++ b/src/sessions/mastodon/session.py @@ -146,17 +146,20 @@ class Session(base.baseSession): """ Convenience function to send a thread. """ in_reply_to_id = reply_to for obj in toots: - if users != None: - text = users+obj.get("text") - else: - text = obj.get("text") + text = obj.get("text") if len(obj["attachments"]) == 0: item = self.api_call(call_name="status_post", status=text, _sound="tweet_send.ogg", in_reply_to_id=in_reply_to_id, visibility=visibility) - in_reply_to_id = item["id"] + if item != None: + in_reply_to_id = item["id"] else: media_ids = [] - for i in obj["attachments"]: - img = self.api_call("media_post", media_file=i["file"], description=i["description"]) - media_ids.append(img.id) - item = self.api_call(call_name="status_post", status=text, _sound="tweet_send.ogg", in_reply_to_id=in_reply_to_id, media_ids=media_ids, visibility=visibility) - in_reply_to_id = item["id"] + poll = None + if len(obj["attachments"]) == 1 and obj["attachments"][0]["type"] == "poll": + poll = self.api.make_poll(options=obj["attachments"][0]["options"], expires_in=obj["attachments"][0]["expires_in"], multiple=obj["attachments"][0]["multiple"], hide_totals=obj["attachments"][0]["hide_totals"]) + else: + for i in obj["attachments"]: + img = self.api_call("media_post", media_file=i["file"], description=i["description"]) + media_ids.append(img.id) + item = self.api_call(call_name="status_post", status=text, _sound="tweet_send.ogg", in_reply_to_id=in_reply_to_id, media_ids=media_ids, visibility=visibility, poll=poll) + if item != None: + in_reply_to_id = item["id"] diff --git a/src/sessions/mastodon/templates.py b/src/sessions/mastodon/templates.py index 0bb25780..d8e783e8 100644 --- a/src/sessions/mastodon/templates.py +++ b/src/sessions/mastodon/templates.py @@ -35,7 +35,7 @@ def process_image_descriptions(media_attachments): """ Attempt to extract information for image descriptions. """ image_descriptions = [] for media in media_attachments: - if media.get("description", "") != "": + if media.get("description") != None and media.get("description") != "": image_descriptions.append(media.get("description")) idescriptions = "" for image in image_descriptions: diff --git a/src/wxUI/dialogs/mastodon/tootDialogs.py b/src/wxUI/dialogs/mastodon/tootDialogs.py index a4f73971..9ef65d4d 100644 --- a/src/wxUI/dialogs/mastodon/tootDialogs.py +++ b/src/wxUI/dialogs/mastodon/tootDialogs.py @@ -1,6 +1,144 @@ -""" GUI dialogs for tweet writing and displaying. """ import wx +class Toot(wx.Dialog): + def __init__(self, caption=_("toot"), text="", *args, **kwds): + super(Toot, self).__init__(parent=None, id=wx.ID_ANY, *args, **kwds) + main_sizer = wx.BoxSizer(wx.VERTICAL) + toot_sizer = wx.WrapSizer(wx.VERTICAL) + main_sizer.Add(toot_sizer, 1, wx.EXPAND, 0) + toot_label = wx.StaticText(self, wx.ID_ANY, caption) + toot_sizer.Add(toot_label, 0, 0, 0) + self.text = wx.TextCtrl(self, wx.ID_ANY, text, style=wx.TE_MULTILINE) + self.text.SetMinSize((350, -1)) + toot_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) + toots_sizer = wx.WrapSizer(wx.VERTICAL) + lists_sizer.Add(toots_sizer, 1, wx.EXPAND, 0) + toots_label = wx.StaticText(self, wx.ID_ANY, _("Toots in the thread")) + toots_sizer.Add(toots_label, 0, 0, 0) + self.toots = wx.ListCtrl(self, wx.ID_ANY, style=wx.LC_HRULES | wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.LC_VRULES) + self.toots.Enable(False) + self.toots.AppendColumn(_("Text"), format=wx.LIST_FORMAT_LEFT, width=-1) + self.toots.AppendColumn(_("Attachments"), format=wx.LIST_FORMAT_LEFT, width=-1) + toots_sizer.Add(self.toots, 1, wx.EXPAND, 0) + self.remove_toot = wx.Button(self, wx.ID_ANY, _("Remove toot")) + self.remove_toot.Enable(False) + toots_sizer.Add(self.remove_toot, 0, 0, 0) + toot_actions_sizer = wx.BoxSizer(wx.HORIZONTAL) + main_sizer.Add(toot_actions_sizer, 1, wx.EXPAND, 0) + visibility_sizer = wx.BoxSizer(wx.HORIZONTAL) + toot_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"), _("Mentionned accounts")], style=wx.CB_DROPDOWN | wx.CB_READONLY | wx.CB_SIMPLE) + self.visibility.SetSelection(0) + visibility_sizer.Add(self.visibility, 0, 0, 0) + self.add = wx.Button(self, wx.ID_ANY, _("A&dd")) + toot_actions_sizer.Add(self.add, 0, 0, 0) + self.add_toot = wx.Button(self, wx.ID_ANY, _("Add t&oot")) + toot_actions_sizer.Add(self.add_toot, 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_OK, "") + self.send.SetDefault() + 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 set_title(self, chars): + self.SetTitle(_("Toot - {} 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.toots.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.toots.GetFocusedItem() + if item > -1: + self.toots.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 + return openFileDialog.GetPath() + + 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 + return openFileDialog.GetPath() + + 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 toot. 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 viewToot(wx.Dialog): def set_title(self, lenght): self.SetTitle(_("Toot - %i characters ") % (lenght,)) @@ -91,3 +229,77 @@ class viewToot(wx.Dialog): def enable_button(self, buttonName): if hasattr(self, buttonName): return getattr(self, buttonName).Enable() + +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 votes 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) \ No newline at end of file