diff --git a/src/application.py b/src/application.py index 4d467ad..178fdd9 100644 --- a/src/application.py +++ b/src/application.py @@ -19,4 +19,4 @@ update_stable_url = "https://files.manuelcortez.net/socializer/update/stable.jso # Every commit will trigger an update, so users wanting to have the bleeding edge code will get it as soon as it is committed here and build by a runner. update_next_url = "https://files.manuelcortez.net/socializer/update/alpha.json" # Short_id of the last commit, this is set to none here because it will be set manually by the building tools. -update_next_version = "03286a44" \ No newline at end of file +update_next_version = "03286a44" diff --git a/src/authenticator/official.py b/src/authenticator/official.py index 3fc9f61..3425fe3 100644 --- a/src/authenticator/official.py +++ b/src/authenticator/official.py @@ -8,24 +8,24 @@ log = logging.getLogger("authenticator.official") class AuthenticationError(Exception): pass def login(user, password): - """ Generates authentication workflow at VK servers. """ - log.info("Authenticating user account.") - access_token = None - try: - params = CommonParams(supported_clients.VK_OFFICIAL.user_agent) - receiver = TokenReceiverOfficial(user, password, params, "GET_CODE") - access_token = receiver.get_token()["access_token"] - log.debug("got a valid access token for {}".format(user)) - except TokenException as err: - if err.code == TokenException.TWOFA_REQ and 'validation_sid' in err.extra: - log.debug("User requires two factor verification. Calling methods to send an SMS...") - try: - TwoFAHelper(params).validate_phone(err.extra['validation_sid']) - except TokenException as err: - if err.code == TokenException.TWOFA_ERR: - wxUI.two_auth_limit() - raise AuthenticationError("Error authentication two factor auth.") - code, remember = wxUI.two_factor_auth() - receiver = TokenReceiverOfficial(user, password, params, code) - access_token = receiver.get_token()["access_token"] - return access_token \ No newline at end of file + """ Generates authentication workflow at VK servers. """ + log.info("Authenticating user account.") + access_token = None + try: + params = CommonParams(supported_clients.VK_OFFICIAL.user_agent) + receiver = TokenReceiverOfficial(user, password, params, "GET_CODE") + access_token = receiver.get_token()["access_token"] + log.debug("got a valid access token for {}".format(user)) + except TokenException as err: + if err.code == TokenException.TWOFA_REQ and 'validation_sid' in err.extra: + log.debug("User requires two factor verification. Calling methods to send an SMS...") + try: + TwoFAHelper(params).validate_phone(err.extra['validation_sid']) + except TokenException as err: + if err.code == TokenException.TWOFA_ERR: + wxUI.two_auth_limit() + raise AuthenticationError("Error authentication two factor auth.") + code, remember = wxUI.two_factor_auth() + receiver = TokenReceiverOfficial(user, password, params, code) + access_token = receiver.get_token()["access_token"] + return access_token diff --git a/src/authenticator/wxUI.py b/src/authenticator/wxUI.py index 3ac6381..015f3c2 100644 --- a/src/authenticator/wxUI.py +++ b/src/authenticator/wxUI.py @@ -5,16 +5,16 @@ import wx import widgetUtils def two_factor_auth(): - code = None - dlg = wx.TextEntryDialog(None, _("Please provide the authentication code you have received from VK."), _("Two factor authentication code")) - response = dlg.ShowModal() - if response == widgetUtils.OK: - code = dlg.GetValue() - dlg.Destroy() - return (code, True) + code = None + dlg = wx.TextEntryDialog(None, _("Please provide the authentication code you have received from VK."), _("Two factor authentication code")) + response = dlg.ShowModal() + if response == widgetUtils.OK: + code = dlg.GetValue() + dlg.Destroy() + return (code, True) def bad_password(): - return wx.MessageDialog(None, _("Your password or email address are incorrect. Please fix the mistakes and try it again."), _("Wrong data"), wx.ICON_ERROR).ShowModal() + return wx.MessageDialog(None, _("Your password or email address are incorrect. Please fix the mistakes and try it again."), _("Wrong data"), wx.ICON_ERROR).ShowModal() def two_auth_limit(): - return wx.MessageDialog(None, _("It seems you have reached the limits to request authorization via SMS. Please try it again in a couple of hours."), _("Error requiring sms verification"), wx.ICON_ERROR).ShowModal() \ No newline at end of file + return wx.MessageDialog(None, _("It seems you have reached the limits to request authorization via SMS. Please try it again in a couple of hours."), _("Error requiring sms verification"), wx.ICON_ERROR).ShowModal() diff --git a/src/config.py b/src/config.py index e6b6d78..3c60d7d 100644 --- a/src/config.py +++ b/src/config.py @@ -11,7 +11,6 @@ MAINSPEC = "app-configuration.defaults" app = None def setup (): - global app - log.debug("Loading global app settings...") - app = config_utils.load_config(os.path.join(paths.config_path(), MAINFILE), os.path.join(paths.app_path(), MAINSPEC)) - \ No newline at end of file + global app + log.debug("Loading global app settings...") + app = config_utils.load_config(os.path.join(paths.config_path(), MAINFILE), os.path.join(paths.app_path(), MAINSPEC)) diff --git a/src/config_utils.py b/src/config_utils.py index d38245c..50d061b 100644 --- a/src/config_utils.py +++ b/src/config_utils.py @@ -6,68 +6,68 @@ import string class ConfigLoadError(Exception): pass def load_config(config_path, configspec_path=None, *args, **kwargs): - if os.path.exists(config_path): - clean_config(config_path) - spec = ConfigObj(configspec_path, encoding='UTF8', list_values=False, _inspec=True) - try: - config = ConfigObj(infile=config_path, configspec=spec, create_empty=True, encoding='UTF8', *args, **kwargs) - except ParseError: - raise ConfigLoadError("Unable to load %r" % config_path) - validator = Validator() - validated = config.validate(validator, copy=True) - if validated == True: - config.write() - return config + if os.path.exists(config_path): + clean_config(config_path) + spec = ConfigObj(configspec_path, encoding='UTF8', list_values=False, _inspec=True) + try: + config = ConfigObj(infile=config_path, configspec=spec, create_empty=True, encoding='UTF8', *args, **kwargs) + except ParseError: + raise ConfigLoadError("Unable to load %r" % config_path) + validator = Validator() + validated = config.validate(validator, copy=True) + if validated == True: + config.write() + return config def is_blank(arg): - "Check if a line is blank." - for c in arg: - if c not in string.whitespace: - return False - return True + "Check if a line is blank." + for c in arg: + if c not in string.whitespace: + return False + return True def get_keys(path): - "Gets the keys of a configobj config file." - res=[] - fin=open(path) - for line in fin: - if not is_blank(line): - res.append(line[0:line.find('=')].strip()) - fin.close() - return res + "Gets the keys of a configobj config file." + res=[] + fin=open(path) + for line in fin: + if not is_blank(line): + res.append(line[0:line.find('=')].strip()) + fin.close() + return res def hist(keys): - "Generates a histogram of an iterable." - res={} - for k in keys: - res[k]=res.setdefault(k,0)+1 - return res + "Generates a histogram of an iterable." + res={} + for k in keys: + res[k]=res.setdefault(k,0)+1 + return res def find_problems(hist): - "Takes a histogram and returns a list of items occurring more than once." - res=[] - for k,v in list(hist.items()): - if v>1: - res.append(k) - return res + "Takes a histogram and returns a list of items occurring more than once." + res=[] + for k,v in list(hist.items()): + if v>1: + res.append(k) + return res def clean_config(path): - "Cleans a config file. If duplicate values are found, delete all of them and just use the default." - orig=[] - cleaned=[] - fin=open(path) - for line in fin: - orig.append(line) - fin.close() - for p in find_problems(hist(get_keys(path))): - for o in orig: - o.strip() - if p not in o: - cleaned.append(o) - if len(cleaned) != 0: - cam=open(path,'w') - for c in cleaned: - cam.write(c) - cam.close() - return True - else: - return False \ No newline at end of file + "Cleans a config file. If duplicate values are found, delete all of them and just use the default." + orig=[] + cleaned=[] + fin=open(path) + for line in fin: + orig.append(line) + fin.close() + for p in find_problems(hist(get_keys(path))): + for o in orig: + o.strip() + if p not in o: + cleaned.append(o) + if len(cleaned) != 0: + cam=open(path,'w') + for c in cleaned: + cam.write(c) + cam.close() + return True + else: + return False diff --git a/src/controller/buffers/audio.py b/src/controller/buffers/audio.py index f445fe8..9ec7131 100644 --- a/src/controller/buffers/audio.py +++ b/src/controller/buffers/audio.py @@ -21,289 +21,289 @@ from .wall import wallBuffer log = logging.getLogger("controller.buffers.audio") class audioBuffer(wallBuffer): - def create_tab(self, parent): - self.tab = audio.audioTab(parent) - self.tab.name = self.name - self.connect_events() - if self.name == "me_audio": - self.tab.post.Enable(True) + def create_tab(self, parent): + self.tab = audio.audioTab(parent) + self.tab.name = self.name + self.connect_events() + if self.name == "me_audio": + self.tab.post.Enable(True) - def get_event(self, ev): - if ev.GetKeyCode() == wx.WXK_RETURN: - if len(self.tab.list.get_multiple_selection()) < 2: - event = "play_all" - else: - event = "play_audio" - else: - event = None - ev.Skip() - if event != None: - try: - getattr(self, event)(skip_pause=True) - except AttributeError: - pass + def get_event(self, ev): + if ev.GetKeyCode() == wx.WXK_RETURN: + if len(self.tab.list.get_multiple_selection()) < 2: + event = "play_all" + else: + event = "play_audio" + else: + event = None + ev.Skip() + if event != None: + try: + getattr(self, event)(skip_pause=True) + except AttributeError: + pass - def connect_events(self): - widgetUtils.connect_event(self.tab.play, widgetUtils.BUTTON_PRESSED, self.play_audio) - widgetUtils.connect_event(self.tab.play_all, widgetUtils.BUTTON_PRESSED, self.play_all) - pub.subscribe(self.change_label, "playback-changed") - super(audioBuffer, self).connect_events() + def connect_events(self): + widgetUtils.connect_event(self.tab.play, widgetUtils.BUTTON_PRESSED, self.play_audio) + widgetUtils.connect_event(self.tab.play_all, widgetUtils.BUTTON_PRESSED, self.play_all) + pub.subscribe(self.change_label, "playback-changed") + super(audioBuffer, self).connect_events() - def play_audio(self, *args, **kwargs): - if player.player.check_is_playing() and not "skip_pause" in kwargs: - return pub.sendMessage("pause") - selected = self.tab.list.get_multiple_selection() - if len(selected) == 0: - return - elif len(selected) == 1: - pub.sendMessage("play", object=self.session.db[self.name]["items"][selected[0]]) - else: - selected_audios = [self.session.db[self.name]["items"][item] for item in selected] - pub.sendMessage("play-all", list_of_songs=selected_audios) - return True + def play_audio(self, *args, **kwargs): + if player.player.check_is_playing() and not "skip_pause" in kwargs: + return pub.sendMessage("pause") + selected = self.tab.list.get_multiple_selection() + if len(selected) == 0: + return + elif len(selected) == 1: + pub.sendMessage("play", object=self.session.db[self.name]["items"][selected[0]]) + else: + selected_audios = [self.session.db[self.name]["items"][item] for item in selected] + pub.sendMessage("play-all", list_of_songs=selected_audios) + return True - def play_next(self, *args, **kwargs): - selected = self.tab.list.get_selected() - if selected < 0: - selected = 0 - if self.tab.list.get_count() <= selected+1: - newpos = 0 - else: - newpos = selected+1 - self.tab.list.select_item(newpos) - self.play_audio() + def play_next(self, *args, **kwargs): + selected = self.tab.list.get_selected() + if selected < 0: + selected = 0 + if self.tab.list.get_count() <= selected+1: + newpos = 0 + else: + newpos = selected+1 + self.tab.list.select_item(newpos) + self.play_audio() - def play_previous(self, *args, **kwargs): - selected = self.tab.list.get_selected() - if selected <= 0: - selected = self.tab.list.get_count() - newpos = selected-1 - self.tab.list.select_item(newpos) - self.play_audio() + def play_previous(self, *args, **kwargs): + selected = self.tab.list.get_selected() + if selected <= 0: + selected = self.tab.list.get_count() + newpos = selected-1 + self.tab.list.select_item(newpos) + self.play_audio() - def open_post(self, *args, **kwargs): - selected = self.tab.list.get_multiple_selection() - if len(selected) < 1: - return - audios = [self.session.db[self.name]["items"][audio] for audio in selected] - a = presenters.displayAudioPresenter(session=self.session, postObject=audios, interactor=interactors.displayAudioInteractor(), view=views.displayAudio()) + def open_post(self, *args, **kwargs): + selected = self.tab.list.get_multiple_selection() + if len(selected) < 1: + return + audios = [self.session.db[self.name]["items"][audio] for audio in selected] + a = presenters.displayAudioPresenter(session=self.session, postObject=audios, interactor=interactors.displayAudioInteractor(), view=views.displayAudio()) - def play_all(self, *args, **kwargs): - selected = self.tab.list.get_selected() - if selected == -1: - selected = 0 - if self.name not in self.session.db: - return - audios = [i for i in self.session.db[self.name]["items"][selected:]] - pub.sendMessage("play-all", list_of_songs=audios) - return True + def play_all(self, *args, **kwargs): + selected = self.tab.list.get_selected() + if selected == -1: + selected = 0 + if self.name not in self.session.db: + return + audios = [i for i in self.session.db[self.name]["items"][selected:]] + pub.sendMessage("play-all", list_of_songs=audios) + return True - def remove_buffer(self, mandatory=False): - if "me_audio" == self.name or "popular_audio" == self.name or "recommended_audio" == self.name: - output.speak(_("This buffer can't be deleted")) - return False - else: - if mandatory == False: - dlg = commonMessages.remove_buffer() - else: - dlg = widgetUtils.YES - if dlg == widgetUtils.YES: - self.session.db.pop(self.name) - return True - else: - return False + def remove_buffer(self, mandatory=False): + if "me_audio" == self.name or "popular_audio" == self.name or "recommended_audio" == self.name: + output.speak(_("This buffer can't be deleted")) + return False + else: + if mandatory == False: + dlg = commonMessages.remove_buffer() + else: + dlg = widgetUtils.YES + if dlg == widgetUtils.YES: + self.session.db.pop(self.name) + return True + else: + return False - def get_more_items(self, *args, **kwargs): - # Translators: Some buffers can't use the get previous item feature due to API limitations. - output.speak(_("This buffer doesn't support getting more items.")) + def get_more_items(self, *args, **kwargs): + # Translators: Some buffers can't use the get previous item feature due to API limitations. + output.speak(_("This buffer doesn't support getting more items.")) - def onFocus(self, event, *args, **kwargs): - event.Skip() + def onFocus(self, event, *args, **kwargs): + event.Skip() - def add_to_library(self, *args, **kwargs): - call_threaded(self._add_to_library, *args, **kwargs) + def add_to_library(self, *args, **kwargs): + call_threaded(self._add_to_library, *args, **kwargs) - def _add_to_library(self, *args, **kwargs): - selected = self.tab.list.get_multiple_selection() - if len(selected) < 1: - return - audios = [self.session.db[self.name]["items"][audio] for audio in selected] - errors_detected = 0 - for i in audios: - args = {} - args["audio_id"] = i["id"] - if "album_id" in i: - args["album_id"] = i["album_id"] - args["owner_id"] = i["owner_id"] - try: - audio = self.session.vk.client.audio.add(**args) - except VkApiError: - errors_detected = errors_detected + 1 - continue - if audio != None and int(audio) < 21: - errors_detected = errors_detected + 1 - if errors_detected == 0: - if len(selected) == 1: - msg = _("Audio added to your library") - elif len(selected) > 1 and len(selected) < 5: - msg = _("{0} audios were added to your library.").format(len(selected),) - else: - msg = _("{audios} audios were added to your library.").format(audios=len(selected),) - output.speak(msg) - else: - output.speak(_("{0} errors occurred while attempting to add {1} audios to your library.").format(errors_detected, len(selected))) + def _add_to_library(self, *args, **kwargs): + selected = self.tab.list.get_multiple_selection() + if len(selected) < 1: + return + audios = [self.session.db[self.name]["items"][audio] for audio in selected] + errors_detected = 0 + for i in audios: + args = {} + args["audio_id"] = i["id"] + if "album_id" in i: + args["album_id"] = i["album_id"] + args["owner_id"] = i["owner_id"] + try: + audio = self.session.vk.client.audio.add(**args) + except VkApiError: + errors_detected = errors_detected + 1 + continue + if audio != None and int(audio) < 21: + errors_detected = errors_detected + 1 + if errors_detected == 0: + if len(selected) == 1: + msg = _("Audio added to your library") + elif len(selected) > 1 and len(selected) < 5: + msg = _("{0} audios were added to your library.").format(len(selected),) + else: + msg = _("{audios} audios were added to your library.").format(audios=len(selected),) + output.speak(msg) + else: + output.speak(_("{0} errors occurred while attempting to add {1} audios to your library.").format(errors_detected, len(selected))) - def remove_from_library(self, *args, **kwargs): - call_threaded(self._remove_from_library, *args, **kwargs) + def remove_from_library(self, *args, **kwargs): + call_threaded(self._remove_from_library, *args, **kwargs) - def _remove_from_library(self, *args, **kwargs): - selected = self.tab.list.get_multiple_selection() - if len(selected) < 1: - return - audios = [self.session.db[self.name]["items"][audio] for audio in selected] - errors_detected = 0 - audios_removed = 0 - for i in range(0, len(selected)): - args = {} - args["audio_id"] = audios[i]["id"] - args["owner_id"] = self.session.user_id - result = self.session.vk.client.audio.delete(**args) - if int(result) != 1: - errors_dtected = errors_detected + 1 - else: - self.session.db[self.name]["items"].pop(selected[i]-audios_removed) - self.tab.list.remove_item(selected[i]-audios_removed) - audios_removed = audios_removed + 1 - if errors_detected == 0: - if len(selected) == 1: - msg = _("Audio removed.") - elif len(selected) > 1 and len(selected) < 5: - msg = _("{0} audios were removed.").format(len(selected),) - else: - msg = _("{audios} audios were removed.").format(audios=len(selected),) - output.speak(msg) - else: - output.speak(_("{0} errors occurred while attempting to remove {1} audios.").format(errors_detected, len(selected))) + def _remove_from_library(self, *args, **kwargs): + selected = self.tab.list.get_multiple_selection() + if len(selected) < 1: + return + audios = [self.session.db[self.name]["items"][audio] for audio in selected] + errors_detected = 0 + audios_removed = 0 + for i in range(0, len(selected)): + args = {} + args["audio_id"] = audios[i]["id"] + args["owner_id"] = self.session.user_id + result = self.session.vk.client.audio.delete(**args) + if int(result) != 1: + errors_dtected = errors_detected + 1 + else: + self.session.db[self.name]["items"].pop(selected[i]-audios_removed) + self.tab.list.remove_item(selected[i]-audios_removed) + audios_removed = audios_removed + 1 + if errors_detected == 0: + if len(selected) == 1: + msg = _("Audio removed.") + elif len(selected) > 1 and len(selected) < 5: + msg = _("{0} audios were removed.").format(len(selected),) + else: + msg = _("{audios} audios were removed.").format(audios=len(selected),) + output.speak(msg) + else: + output.speak(_("{0} errors occurred while attempting to remove {1} audios.").format(errors_detected, len(selected))) - def move_to_album(self, *args, **kwargs): - if len(self.session.audio_albums) == 0: - return commonMessages.no_audio_albums() - album = selector.album(_("Select the album where you want to move this song"), self.session) - if album.item == None: - return - call_threaded(self._move_to_album, album.item, *args, **kwargs) + def move_to_album(self, *args, **kwargs): + if len(self.session.audio_albums) == 0: + return commonMessages.no_audio_albums() + album = selector.album(_("Select the album where you want to move this song"), self.session) + if album.item == None: + return + call_threaded(self._move_to_album, album.item, *args, **kwargs) - def _move_to_album(self, album, *args, **kwargs): - selected = self.tab.list.get_multiple_selection() - if len(selected) < 1: - return - audios = [self.session.db[self.name]["items"][audio] for audio in selected] - errors_detected = 0 - for i in audios: - id = i["id"] - try: - response = self.session.vk.client.audio.add(playlist_id=album, audio_id=id, owner_id=i["owner_id"]) - except VkApiError: - errors_detected = errors_detected + 1 - if errors_detected == 0: - if len(selected) == 1: - msg = _("Audio added to playlist.") - elif len(selected) > 1 and len(selected) < 5: - msg = _("{0} audios were added to playlist.").format(len(selected),) - else: - msg = _("{audios} audios were added to playlist.").format(audios=len(selected),) - output.speak(msg) - else: - output.speak(_("{0} errors occurred while attempting to add {1} audios to your playlist.").format(errors_detected, len(selected))) + def _move_to_album(self, album, *args, **kwargs): + selected = self.tab.list.get_multiple_selection() + if len(selected) < 1: + return + audios = [self.session.db[self.name]["items"][audio] for audio in selected] + errors_detected = 0 + for i in audios: + id = i["id"] + try: + response = self.session.vk.client.audio.add(playlist_id=album, audio_id=id, owner_id=i["owner_id"]) + except VkApiError: + errors_detected = errors_detected + 1 + if errors_detected == 0: + if len(selected) == 1: + msg = _("Audio added to playlist.") + elif len(selected) > 1 and len(selected) < 5: + msg = _("{0} audios were added to playlist.").format(len(selected),) + else: + msg = _("{audios} audios were added to playlist.").format(audios=len(selected),) + output.speak(msg) + else: + output.speak(_("{0} errors occurred while attempting to add {1} audios to your playlist.").format(errors_detected, len(selected))) - def get_menu(self): - p = self.get_post() - if p == None: - return - m = menus.audioMenu() - widgetUtils.connect_event(m, widgetUtils.MENU, self.open_post, menuitem=m.open) - widgetUtils.connect_event(m, widgetUtils.MENU, self.play_audio, menuitem=m.play) - widgetUtils.connect_event(m, widgetUtils.MENU, self.move_to_album, menuitem=m.move) - widgetUtils.connect_event(m, widgetUtils.MENU, self.download, menuitem=m.download) - widgetUtils.connect_event(m, widgetUtils.MENU, self.select_all, menuitem=m.select) - widgetUtils.connect_event(m, widgetUtils.MENU, self.deselect_all, menuitem=m.deselect) - # if owner_id is the current user, the audio is added to the user's audios. - if p["owner_id"] == self.session.user_id: - m.library.SetItemLabel(_("&Remove")) - widgetUtils.connect_event(m, widgetUtils.MENU, self.remove_from_library, menuitem=m.library) - else: - widgetUtils.connect_event(m, widgetUtils.MENU, self.add_to_library, menuitem=m.library) - return m + def get_menu(self): + p = self.get_post() + if p == None: + return + m = menus.audioMenu() + widgetUtils.connect_event(m, widgetUtils.MENU, self.open_post, menuitem=m.open) + widgetUtils.connect_event(m, widgetUtils.MENU, self.play_audio, menuitem=m.play) + widgetUtils.connect_event(m, widgetUtils.MENU, self.move_to_album, menuitem=m.move) + widgetUtils.connect_event(m, widgetUtils.MENU, self.download, menuitem=m.download) + widgetUtils.connect_event(m, widgetUtils.MENU, self.select_all, menuitem=m.select) + widgetUtils.connect_event(m, widgetUtils.MENU, self.deselect_all, menuitem=m.deselect) + # if owner_id is the current user, the audio is added to the user's audios. + if p["owner_id"] == self.session.user_id: + m.library.SetItemLabel(_("&Remove")) + widgetUtils.connect_event(m, widgetUtils.MENU, self.remove_from_library, menuitem=m.library) + else: + widgetUtils.connect_event(m, widgetUtils.MENU, self.add_to_library, menuitem=m.library) + return m - def post(self, *args, **kwargs): - """ Uploads an audio to the current user's library from the computer. """ - file = self.tab.get_file_to_upload() - if file == None: - return - audio_tags = ID3(file) - if "TIT2" in audio_tags: - title = audio_tags["TIT2"].text[0] - else: - title = _("Untitled") - if "TPE1" in audio_tags: - artist = audio_tags["TPE1"].text[0] - else: - artist = _("Unknown artist") - uploader = upload.VkUpload(self.session.vk.session_object) - call_threaded(uploader.audio, file, title=title, artist=artist) + def post(self, *args, **kwargs): + """ Uploads an audio to the current user's library from the computer. """ + file = self.tab.get_file_to_upload() + if file == None: + return + audio_tags = ID3(file) + if "TIT2" in audio_tags: + title = audio_tags["TIT2"].text[0] + else: + title = _("Untitled") + if "TPE1" in audio_tags: + artist = audio_tags["TPE1"].text[0] + else: + artist = _("Unknown artist") + uploader = upload.VkUpload(self.session.vk.session_object) + call_threaded(uploader.audio, file, title=title, artist=artist) - def open_in_browser(self, *args, **kwargs): - post = self.get_post() - if post == None: - return - url = "https://vk.com/audio{user_id}_{post_id}".format(user_id=post["owner_id"], post_id=post["id"]) - webbrowser.open_new_tab(url) + def open_in_browser(self, *args, **kwargs): + post = self.get_post() + if post == None: + return + url = "https://vk.com/audio{user_id}_{post_id}".format(user_id=post["owner_id"], post_id=post["id"]) + webbrowser.open_new_tab(url) - def change_label(self, stopped): - if hasattr(self.tab, "play"): - if stopped == False: - self.tab.play.SetLabel(_("P&ause")) - else: - self.tab.play.SetLabel(_("P&lay")) + def change_label(self, stopped): + if hasattr(self.tab, "play"): + if stopped == False: + self.tab.play.SetLabel(_("P&ause")) + else: + self.tab.play.SetLabel(_("P&lay")) - def __del__(self): - pub.unsubscribe(self.change_label, "playback-changed") + def __del__(self): + pub.unsubscribe(self.change_label, "playback-changed") - def download(self, *args, **kwargs): - selected = self.tab.list.get_multiple_selection() - if len(selected) < 1: - return - audios = [self.session.db[self.name]["items"][audio] for audio in selected] - if len(audios) == 0: - return - elif len(audios) == 1: - multiple = False - filename = utils.safe_filename("{0} - {1}.mp3".format(audios[0]["title"], audios[0]["artist"])) - else: - multiple = True - filename = "" # No default filename for multiple files. - path = self.tab.get_download_path(filename=filename, multiple=multiple) - self.download_threaded(path, multiple, audios) + def download(self, *args, **kwargs): + selected = self.tab.list.get_multiple_selection() + if len(selected) < 1: + return + audios = [self.session.db[self.name]["items"][audio] for audio in selected] + if len(audios) == 0: + return + elif len(audios) == 1: + multiple = False + filename = utils.safe_filename("{0} - {1}.mp3".format(audios[0]["title"], audios[0]["artist"])) + else: + multiple = True + filename = "" # No default filename for multiple files. + path = self.tab.get_download_path(filename=filename, multiple=multiple) + self.download_threaded(path, multiple, audios) - def download_threaded(self, path, multiple, audios): - if multiple == False: - url = audios[0]["url"] - pub.sendMessage("download-file", url=url, filename=path) - return - else: - downloads = [] - for i in audios: - filename = utils.safe_filename("{0} - {1}.mp3".format(i["title"], i["artist"])) - filepath = os.path.join(path, filename) - downloads.append((utils.transform_audio_url(i["url"]), filepath)) - pub.sendMessage("download-files", downloads=downloads) + def download_threaded(self, path, multiple, audios): + if multiple == False: + url = audios[0]["url"] + pub.sendMessage("download-file", url=url, filename=path) + return + else: + downloads = [] + for i in audios: + filename = utils.safe_filename("{0} - {1}.mp3".format(i["title"], i["artist"])) + filepath = os.path.join(path, filename) + downloads.append((utils.transform_audio_url(i["url"]), filepath)) + pub.sendMessage("download-files", downloads=downloads) - def select_all(self, *args, **kwargs): - items = self.tab.list.list.GetItemCount() - for i in range(0, items): - self.tab.list.list.SetItemImage(i, 1) + def select_all(self, *args, **kwargs): + items = self.tab.list.list.GetItemCount() + for i in range(0, items): + self.tab.list.list.SetItemImage(i, 1) - def deselect_all(self, *args, **kwargs): - items = self.tab.list.list.GetItemCount() - for i in range(0, items): - self.tab.list.list.SetItemImage(i, 0) \ No newline at end of file + def deselect_all(self, *args, **kwargs): + items = self.tab.list.list.GetItemCount() + for i in range(0, items): + self.tab.list.list.SetItemImage(i, 0) diff --git a/src/controller/buffers/audioAlbum.py b/src/controller/buffers/audioAlbum.py index 78c6519..85c12bb 100644 --- a/src/controller/buffers/audioAlbum.py +++ b/src/controller/buffers/audioAlbum.py @@ -9,26 +9,26 @@ from .audio import audioBuffer log = logging.getLogger("controller.buffers.audioPlaylist") class audioAlbumBuffer(audioBuffer): - """ this buffer was supposed to be used with audio albums - but is deprecated as VK removed its audio support for third party apps.""" + """ this buffer was supposed to be used with audio albums + but is deprecated as VK removed its audio support for third party apps.""" - def create_tab(self, parent): - self.tab = audioAlbum.audioAlbumTab(parent) - self.tab.play.Enable(False) - self.tab.play_all.Enable(False) - self.connect_events() - self.tab.name = self.name - if hasattr(self, "can_post") and self.can_post == False and hasattr(self.tab, "post"): - self.tab.post.Enable(False) + def create_tab(self, parent): + self.tab = audioAlbum.audioAlbumTab(parent) + self.tab.play.Enable(False) + self.tab.play_all.Enable(False) + self.connect_events() + self.tab.name = self.name + if hasattr(self, "can_post") and self.can_post == False and hasattr(self.tab, "post"): + self.tab.post.Enable(False) - def connect_events(self): - super(audioAlbumBuffer, self).connect_events() - widgetUtils.connect_event(self.tab.load, widgetUtils.BUTTON_PRESSED, self.load_album) + def connect_events(self): + super(audioAlbumBuffer, self).connect_events() + widgetUtils.connect_event(self.tab.load, widgetUtils.BUTTON_PRESSED, self.load_album) - def load_album(self, *args, **kwargs): - output.speak(_("Loading album...")) - self.can_get_items = True - self.tab.load.Enable(False) - wx.CallAfter(self.get_items) - self.tab.play.Enable(True) - self.tab.play_all.Enable(True) \ No newline at end of file + def load_album(self, *args, **kwargs): + output.speak(_("Loading album...")) + self.can_get_items = True + self.tab.load.Enable(False) + wx.CallAfter(self.get_items) + self.tab.play.Enable(True) + self.tab.play_all.Enable(True) diff --git a/src/controller/buffers/chat.py b/src/controller/buffers/chat.py index ff2fab1..fff68d5 100644 --- a/src/controller/buffers/chat.py +++ b/src/controller/buffers/chat.py @@ -22,286 +22,286 @@ log = logging.getLogger("controller.buffers.chat") class chatBuffer(homeBuffer): - def insert(self, item, reversed=False): - """ Add a new item to the list. Uses session.composefunc for parsing the dictionary and create a valid result for putting it in the list.""" - # as this tab is based in a text control, we have to overwrite the defaults. - item_ = getattr(renderers, self.compose_function)(item, self.session) - # the self.chat dictionary will have (first_line, last_line) as keys and message ID as a value for looking into it when needed. - # Here we will get first and last line of a chat message appended to the history. - values = self.tab.add_message(item_[0], reverse=reversed) - self.chats[values] = item["id"] + def insert(self, item, reversed=False): + """ Add a new item to the list. Uses session.composefunc for parsing the dictionary and create a valid result for putting it in the list.""" + # as this tab is based in a text control, we have to overwrite the defaults. + item_ = getattr(renderers, self.compose_function)(item, self.session) + # the self.chat dictionary will have (first_line, last_line) as keys and message ID as a value for looking into it when needed. + # Here we will get first and last line of a chat message appended to the history. + values = self.tab.add_message(item_[0], reverse=reversed) + self.chats[values] = item["id"] - def get_focused_post(self): - """ Gets chat message currently in focus""" - # this function replaces self.get_post for this buffer, as we rely in a TextCtrl control for getting chats. - # Instead of the traditional method to do the trick. - # Get text position here. - position = self.tab.history.PositionToXY(self.tab.history.GetInsertionPoint()) - id_ = None - # The dictionary keys should be looked in reverse order as we are interested in the last result only. - for i in reversed(list(self.chats.keys())): - # Check if position[2] (line position) matches with something in self.chats - # (All messages, except the last one, should be able to be matched here). - # position[2]+1 is added because line may start with 0, while in wx.TextCtrl.GetNumberOfLines() it returns a value counting from 1. - if position[2]+1 >= i[0]: - id_ = self.chats[i] - # If we find our chat message, let's skip the rest of the loop. - break - # Retrieve here the object based in id_ - if id_ != None: - for i in self.session.db[self.name]["items"]: - if i["id"] == id_: - return i - return False + def get_focused_post(self): + """ Gets chat message currently in focus""" + # this function replaces self.get_post for this buffer, as we rely in a TextCtrl control for getting chats. + # Instead of the traditional method to do the trick. + # Get text position here. + position = self.tab.history.PositionToXY(self.tab.history.GetInsertionPoint()) + id_ = None + # The dictionary keys should be looked in reverse order as we are interested in the last result only. + for i in reversed(list(self.chats.keys())): + # Check if position[2] (line position) matches with something in self.chats + # (All messages, except the last one, should be able to be matched here). + # position[2]+1 is added because line may start with 0, while in wx.TextCtrl.GetNumberOfLines() it returns a value counting from 1. + if position[2]+1 >= i[0]: + id_ = self.chats[i] + # If we find our chat message, let's skip the rest of the loop. + break + # Retrieve here the object based in id_ + if id_ != None: + for i in self.session.db[self.name]["items"]: + if i["id"] == id_: + return i + return False - get_post = get_focused_post + get_post = get_focused_post - def onFocus(self, event, *args, **kwargs): - if event.GetKeyCode() == wx.WXK_UP or event.GetKeyCode() == wx.WXK_DOWN or event.GetKeyCode() == wx.WXK_START or event.GetKeyCode() == wx.WXK_PAGEUP or event.GetKeyCode() == wx.WXK_PAGEDOWN or event.GetKeyCode() == wx.WXK_END: - msg = self.get_focused_post() - if msg == False: # Handle the case where the last line of the control cannot be matched to anything. - return - # Mark unread conversations as read. - if "read_state" in msg and msg["read_state"] == 0 and "out" in msg and msg["out"] == 0: - self.session.soundplayer.play("message_unread.ogg") - call_threaded(self.session.vk.client.messages.markAsRead, peer_id=self.kwargs["peer_id"]) - [i.update(read_state=1) for i in self.session.db[self.name]["items"]] - if "attachments" in msg and len(msg["attachments"]) > 0: - self.tab.attachments.list.Enable(True) - self.attachments = list() - self.tab.attachments.clear() - self.parse_attachments(msg) - else: - self.tab.attachments.list.Enable(False) - self.tab.attachments.clear() - event.Skip() + def onFocus(self, event, *args, **kwargs): + if event.GetKeyCode() == wx.WXK_UP or event.GetKeyCode() == wx.WXK_DOWN or event.GetKeyCode() == wx.WXK_START or event.GetKeyCode() == wx.WXK_PAGEUP or event.GetKeyCode() == wx.WXK_PAGEDOWN or event.GetKeyCode() == wx.WXK_END: + msg = self.get_focused_post() + if msg == False: # Handle the case where the last line of the control cannot be matched to anything. + return + # Mark unread conversations as read. + if "read_state" in msg and msg["read_state"] == 0 and "out" in msg and msg["out"] == 0: + self.session.soundplayer.play("message_unread.ogg") + call_threaded(self.session.vk.client.messages.markAsRead, peer_id=self.kwargs["peer_id"]) + [i.update(read_state=1) for i in self.session.db[self.name]["items"]] + if "attachments" in msg and len(msg["attachments"]) > 0: + self.tab.attachments.list.Enable(True) + self.attachments = list() + self.tab.attachments.clear() + self.parse_attachments(msg) + else: + self.tab.attachments.list.Enable(False) + self.tab.attachments.clear() + event.Skip() - def create_tab(self, parent): - self.tab = chat.chatTab(parent) - self.attachments = list() - self.connect_events() - self.tab.name = self.name - if hasattr(self, "can_post") and self.can_post == False and hasattr(self.tab, "post"): - self.tab.post.Enable(False) + def create_tab(self, parent): + self.tab = chat.chatTab(parent) + self.attachments = list() + self.connect_events() + self.tab.name = self.name + if hasattr(self, "can_post") and self.can_post == False and hasattr(self.tab, "post"): + self.tab.post.Enable(False) - def connect_events(self): - widgetUtils.connect_event(self.tab.send, widgetUtils.BUTTON_PRESSED, self.send_chat_to_user) - widgetUtils.connect_event(self.tab.attachment, widgetUtils.BUTTON_PRESSED, self.add_attachment) - widgetUtils.connect_event(self.tab.text, widgetUtils.KEYPRESS, self.catch_enter) - widgetUtils.connect_event(self.tab.actions, widgetUtils.BUTTON_PRESSED, self.actions) - self.tab.set_focus_function(self.onFocus) + def connect_events(self): + widgetUtils.connect_event(self.tab.send, widgetUtils.BUTTON_PRESSED, self.send_chat_to_user) + widgetUtils.connect_event(self.tab.attachment, widgetUtils.BUTTON_PRESSED, self.add_attachment) + widgetUtils.connect_event(self.tab.text, widgetUtils.KEYPRESS, self.catch_enter) + widgetUtils.connect_event(self.tab.actions, widgetUtils.BUTTON_PRESSED, self.actions) + self.tab.set_focus_function(self.onFocus) - def catch_enter(self, event, *args, **kwargs): - shift=event.ShiftDown() - if event.GetKeyCode() == wx.WXK_RETURN and shift == False: - return self.send_chat_to_user() - t = time.time() - if event.GetUnicodeKey() != wx.WXK_NONE and t-self.last_keypress > 5: - self.last_keypress = t - call_threaded(self.session.vk.client.messages.setActivity, peer_id=self.kwargs["peer_id"], type="typing") - event.Skip() + def catch_enter(self, event, *args, **kwargs): + shift=event.ShiftDown() + if event.GetKeyCode() == wx.WXK_RETURN and shift == False: + return self.send_chat_to_user() + t = time.time() + if event.GetUnicodeKey() != wx.WXK_NONE and t-self.last_keypress > 5: + self.last_keypress = t + call_threaded(self.session.vk.client.messages.setActivity, peer_id=self.kwargs["peer_id"], type="typing") + event.Skip() - def get_items(self, show_nextpage=False): - """ Update buffer with newest items or get older items in the buffer.""" - if self.can_get_items == False: return - retrieved = True - try: - num = getattr(self.session, "get_page")(show_nextpage=show_nextpage, name=self.name, *self.args, **self.kwargs) - except VkApiError as err: - log.error("Error {0}: {1}".format(err.code, err.error)) - retrieved = err.code - return retrieved - except: - log.exception("Connection error when updating buffer %s. Will try again in 2 minutes" % (self.name,)) - return False - if not hasattr(self, "tab"): - # Create GUI associated to this buffer. - self.create_tab(self.parent) - # Add name to the new control so we could look for it when needed. - self.tab.name = self.name - if show_nextpage == False: - if self.tab.history.GetValue() != "" and num > 0: - v = [i for i in self.session.db[self.name]["items"][:num]] - [self.insert(i, False) for i in v] - else: - [self.insert(i) for i in self.session.db[self.name]["items"][:num]] - else: - if num > 0: - # At this point we save more CPU and mathematical work if we just delete everything in the chat history and readd all messages. - # Otherwise we'd have to insert new lines at the top and recalculate positions everywhere else. - # Firstly, we'd have to save the current focused object so we will place the user in the right part of the text after loading everything again. - focused_post = self.get_post() - self.chats = dict() - wx.CallAfter(self.tab.history.SetValue, "") - v = [i for i in self.session.db[self.name]["items"]] - [self.insert(i) for i in v] - # Now it's time to set back the focus in the post. - for i in self.chats.keys(): - if self.chats[i] == focused_post["id"]: - line = i[0] - wx.CallAfter(self.tab.history.SetInsertionPoint, self.tab.history.XYToPosition(0, line)) - output.speak(_("Items loaded")) - break - if self.unread == True and num > 0: - self.session.db[self.name]["items"][-1].update(read_state=0) - return retrieved + def get_items(self, show_nextpage=False): + """ Update buffer with newest items or get older items in the buffer.""" + if self.can_get_items == False: return + retrieved = True + try: + num = getattr(self.session, "get_page")(show_nextpage=show_nextpage, name=self.name, *self.args, **self.kwargs) + except VkApiError as err: + log.error("Error {0}: {1}".format(err.code, err.error)) + retrieved = err.code + return retrieved + except: + log.exception("Connection error when updating buffer %s. Will try again in 2 minutes" % (self.name,)) + return False + if not hasattr(self, "tab"): + # Create GUI associated to this buffer. + self.create_tab(self.parent) + # Add name to the new control so we could look for it when needed. + self.tab.name = self.name + if show_nextpage == False: + if self.tab.history.GetValue() != "" and num > 0: + v = [i for i in self.session.db[self.name]["items"][:num]] + [self.insert(i, False) for i in v] + else: + [self.insert(i) for i in self.session.db[self.name]["items"][:num]] + else: + if num > 0: + # At this point we save more CPU and mathematical work if we just delete everything in the chat history and readd all messages. + # Otherwise we'd have to insert new lines at the top and recalculate positions everywhere else. + # Firstly, we'd have to save the current focused object so we will place the user in the right part of the text after loading everything again. + focused_post = self.get_post() + self.chats = dict() + wx.CallAfter(self.tab.history.SetValue, "") + v = [i for i in self.session.db[self.name]["items"]] + [self.insert(i) for i in v] + # Now it's time to set back the focus in the post. + for i in self.chats.keys(): + if self.chats[i] == focused_post["id"]: + line = i[0] + wx.CallAfter(self.tab.history.SetInsertionPoint, self.tab.history.XYToPosition(0, line)) + output.speak(_("Items loaded")) + break + if self.unread == True and num > 0: + self.session.db[self.name]["items"][-1].update(read_state=0) + return retrieved - def get_more_items(self): - output.speak(_("Getting more items...")) - call_threaded(self.get_items, show_nextpage=True) + def get_more_items(self): + output.speak(_("Getting more items...")) + call_threaded(self.get_items, show_nextpage=True) - def add_attachment(self, *args, **kwargs): - a = presenters.attachPresenter(session=self.session, view=views.attachDialog(voice_messages=True), interactor=interactors.attachInteractor()) - if len(a.attachments) != 0: - self.attachments_to_be_sent = a.attachments + def add_attachment(self, *args, **kwargs): + a = presenters.attachPresenter(session=self.session, view=views.attachDialog(voice_messages=True), interactor=interactors.attachInteractor()) + if len(a.attachments) != 0: + self.attachments_to_be_sent = a.attachments - def send_chat_to_user(self, *args, **kwargs): - text = self.tab.text.GetValue() - if text == "" and not hasattr(self, "attachments_to_be_sent"): - wx.Bell() - return - self.tab.text.SetValue("") - post_arguments = dict(random_id = random.randint(0, 100000), peer_id=self.kwargs["peer_id"]) - if len(text) > 0: - post_arguments.update(message=text) - if hasattr(self, "attachments_to_be_sent") and len(self.attachments_to_be_sent) > 0: - attachments = self.attachments_to_be_sent[::] - else: - attachments = [] - call_threaded(pub.sendMessage, "post", parent_endpoint="messages", child_endpoint="send", from_buffer=self.name, attachments_list=attachments, post_arguments=post_arguments) - if hasattr(self, "attachments_to_be_sent"): - del self.attachments_to_be_sent + def send_chat_to_user(self, *args, **kwargs): + text = self.tab.text.GetValue() + if text == "" and not hasattr(self, "attachments_to_be_sent"): + wx.Bell() + return + self.tab.text.SetValue("") + post_arguments = dict(random_id = random.randint(0, 100000), peer_id=self.kwargs["peer_id"]) + if len(text) > 0: + post_arguments.update(message=text) + if hasattr(self, "attachments_to_be_sent") and len(self.attachments_to_be_sent) > 0: + attachments = self.attachments_to_be_sent[::] + else: + attachments = [] + call_threaded(pub.sendMessage, "post", parent_endpoint="messages", child_endpoint="send", from_buffer=self.name, attachments_list=attachments, post_arguments=post_arguments) + if hasattr(self, "attachments_to_be_sent"): + del self.attachments_to_be_sent - def __init__(self, unread=False, *args, **kwargs): - super(chatBuffer, self).__init__(*args, **kwargs) - self.unread = unread - self.chats = dict() - self.peer_typing = 0 - self.last_keypress = time.time() + def __init__(self, unread=False, *args, **kwargs): + super(chatBuffer, self).__init__(*args, **kwargs) + self.unread = unread + self.chats = dict() + self.peer_typing = 0 + self.last_keypress = time.time() - def parse_attachments(self, post): - attachments = [] + def parse_attachments(self, post): + attachments = [] - if "attachments" in post: - for i in post["attachments"]: - # We don't need the photos_list attachment, so skip it. - if i["type"] == "photos_list": - continue - try: - rendered_object = renderers.add_attachment(i) - except: - log.exception("Error parsing the following attachment on chat: %r" % (i,)) - attachments.append(rendered_object) - self.attachments.append(i) - self.tab.attachments.list.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.open_attachment) - self.tab.insert_attachments(attachments) + if "attachments" in post: + for i in post["attachments"]: + # We don't need the photos_list attachment, so skip it. + if i["type"] == "photos_list": + continue + try: + rendered_object = renderers.add_attachment(i) + except: + log.exception("Error parsing the following attachment on chat: %r" % (i,)) + attachments.append(rendered_object) + self.attachments.append(i) + self.tab.attachments.list.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.open_attachment) + self.tab.insert_attachments(attachments) - def open_attachment(self, *args, **kwargs): - index = self.tab.attachments.get_selected() - attachment = self.attachments[index] - if attachment["type"] == "audio": - a = presenters.displayAudioPresenter(session=self.session, postObject=[attachment["audio"]], interactor=interactors.displayAudioInteractor(), view=views.displayAudio()) - elif attachment["type"] == "audio_message": - link = attachment["audio_message"]["link_mp3"] - pub.sendMessage("play-message", message_url=link) - elif attachment["type"] == "link": - output.speak(_("Opening URL..."), True) - webbrowser.open_new_tab(attachment["link"]["url"]) - elif attachment["type"] == "doc": - output.speak(_("Opening document in web browser...")) - webbrowser.open(attachment["doc"]["url"]) - elif attachment["type"] == "video": - # it seems VK doesn't like to attach video links as normal URLS, so we'll have to - # get the full video object and use its "player" key which will open a webbrowser in their site with a player for the video. - # see https://vk.com/dev/attachments_w and and https://vk.com/dev/video.get - # However, the flash player isn't good for visually impaired people (when you press play you won't be able to close the window with alt+f4), so it could be good to use the HTML5 player. - # For firefox, see https://addons.mozilla.org/ru/firefox/addon/force-html5-video-player-at-vk/ - # May be I could use a dialogue here for inviting people to use this addon in firefox. It seems it isn't possible to use this html5 player from the player URL. - object_id = "{0}_{1}".format(attachment["video"]["owner_id"], attachment["video"]["id"]) - video_object = self.session.vk.client.video.get(owner_id=attachment["video"]["owner_id"], videos=object_id) - video_object = video_object["items"][0] - output.speak(_("Opening video in web browser..."), True) - webbrowser.open_new_tab(video_object["player"]) - elif attachment["type"] == "photo": - output.speak(_("Opening photo in web browser..."), True) - # Possible photo sizes for looking in the attachment information. Try to use the biggest photo available. - possible_sizes = [1280, 604, 130, 75] - url = "" - for i in possible_sizes: - if "photo_{0}".format(i,) in attachment["photo"]: - url = attachment["photo"]["photo_{0}".format(i,)] - break - if url != "": - webbrowser.open_new_tab(url) - if attachment["type"] == "wall": - pub.sendMessage("open-post", post_object=attachment["wall"], controller_="displayPost") - else: - log.debug("Unhandled attachment: %r" % (attachment,)) + def open_attachment(self, *args, **kwargs): + index = self.tab.attachments.get_selected() + attachment = self.attachments[index] + if attachment["type"] == "audio": + a = presenters.displayAudioPresenter(session=self.session, postObject=[attachment["audio"]], interactor=interactors.displayAudioInteractor(), view=views.displayAudio()) + elif attachment["type"] == "audio_message": + link = attachment["audio_message"]["link_mp3"] + pub.sendMessage("play-message", message_url=link) + elif attachment["type"] == "link": + output.speak(_("Opening URL..."), True) + webbrowser.open_new_tab(attachment["link"]["url"]) + elif attachment["type"] == "doc": + output.speak(_("Opening document in web browser...")) + webbrowser.open(attachment["doc"]["url"]) + elif attachment["type"] == "video": + # it seems VK doesn't like to attach video links as normal URLS, so we'll have to + # get the full video object and use its "player" key which will open a webbrowser in their site with a player for the video. + # see https://vk.com/dev/attachments_w and and https://vk.com/dev/video.get + # However, the flash player isn't good for visually impaired people (when you press play you won't be able to close the window with alt+f4), so it could be good to use the HTML5 player. + # For firefox, see https://addons.mozilla.org/ru/firefox/addon/force-html5-video-player-at-vk/ + # May be I could use a dialogue here for inviting people to use this addon in firefox. It seems it isn't possible to use this html5 player from the player URL. + object_id = "{0}_{1}".format(attachment["video"]["owner_id"], attachment["video"]["id"]) + video_object = self.session.vk.client.video.get(owner_id=attachment["video"]["owner_id"], videos=object_id) + video_object = video_object["items"][0] + output.speak(_("Opening video in web browser..."), True) + webbrowser.open_new_tab(video_object["player"]) + elif attachment["type"] == "photo": + output.speak(_("Opening photo in web browser..."), True) + # Possible photo sizes for looking in the attachment information. Try to use the biggest photo available. + possible_sizes = [1280, 604, 130, 75] + url = "" + for i in possible_sizes: + if "photo_{0}".format(i,) in attachment["photo"]: + url = attachment["photo"]["photo_{0}".format(i,)] + break + if url != "": + webbrowser.open_new_tab(url) + if attachment["type"] == "wall": + pub.sendMessage("open-post", post_object=attachment["wall"], controller_="displayPost") + else: + log.debug("Unhandled attachment: %r" % (attachment,)) - def clear_reads(self): - for i in self.session.db[self.name]["items"]: - if "read_state" in i and i["read_state"] == 0: - i["read_state"] = 1 + def clear_reads(self): + for i in self.session.db[self.name]["items"]: + if "read_state" in i and i["read_state"] == 0: + i["read_state"] = 1 - def remove_buffer(self, mandatory=False): - """ Remove buffer if the current buffer is not the logged user's wall.""" - if mandatory == False: - dlg = commonMessages.remove_buffer() - else: - dlg = widgetUtils.YES - if dlg == widgetUtils.YES: - self.session.db.pop(self.name) - return True - else: - return False + def remove_buffer(self, mandatory=False): + """ Remove buffer if the current buffer is not the logged user's wall.""" + if mandatory == False: + dlg = commonMessages.remove_buffer() + else: + dlg = widgetUtils.YES + if dlg == widgetUtils.YES: + self.session.db.pop(self.name) + return True + else: + return False - def open_in_browser(self, *args, **kwargs): - peer_id = self.kwargs["peer_id"] - url = "https://vk.com/im?sel={peer_id}".format(peer_id=peer_id) - webbrowser.open_new_tab(url) + def open_in_browser(self, *args, **kwargs): + peer_id = self.kwargs["peer_id"] + url = "https://vk.com/im?sel={peer_id}".format(peer_id=peer_id) + webbrowser.open_new_tab(url) - def actions(self, *args, **kwargs): - menu = menus.toolsMenu() - widgetUtils.connect_event(menu, widgetUtils.MENU, self.translate_action, menuitem=menu.translate) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.spellcheck_action, menuitem=menu.spellcheck) - self.tab.PopupMenu(menu, self.tab.actions.GetPosition()) + def actions(self, *args, **kwargs): + menu = menus.toolsMenu() + widgetUtils.connect_event(menu, widgetUtils.MENU, self.translate_action, menuitem=menu.translate) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.spellcheck_action, menuitem=menu.spellcheck) + self.tab.PopupMenu(menu, self.tab.actions.GetPosition()) - def translate(self, text): - dlg = translator.gui.translateDialog() - if dlg.get_response() == widgetUtils.OK: - language_dict = translator.translator.available_languages() - for k in language_dict: - if language_dict[k] == dlg.dest_lang.GetStringSelection(): - dst = k - msg = translator.translator.translate(text, dst) - dlg.Destroy() - return msg + def translate(self, text): + dlg = translator.gui.translateDialog() + if dlg.get_response() == widgetUtils.OK: + language_dict = translator.translator.available_languages() + for k in language_dict: + if language_dict[k] == dlg.dest_lang.GetStringSelection(): + dst = k + msg = translator.translator.translate(text, dst) + dlg.Destroy() + return msg - def spellcheck(self, text): - checker = SpellChecker.spellchecker.spellChecker(text) - if hasattr(checker, "fixed_text"): - final_text = checker.fixed_text - return final_text + def spellcheck(self, text): + checker = SpellChecker.spellchecker.spellChecker(text) + if hasattr(checker, "fixed_text"): + final_text = checker.fixed_text + return final_text - def translate_action(self, *args, **kwargs): - text = self.tab.text.GetValue() - if text == "": - wx.Bell() - return - translated = self.translate(text) - if translated != None: - self.tab.text.ChangeValue(translated) - self.tab.text.SetFocus() + def translate_action(self, *args, **kwargs): + text = self.tab.text.GetValue() + if text == "": + wx.Bell() + return + translated = self.translate(text) + if translated != None: + self.tab.text.ChangeValue(translated) + self.tab.text.SetFocus() - def spellcheck_action(self, *args, **kwargs): - text = self.tab.text.GetValue() - fixed = self.spellcheck(text) - if fixed != None: - self.tab.text.ChangeValue(fixed) - self.tab.text.SetFocus() + def spellcheck_action(self, *args, **kwargs): + text = self.tab.text.GetValue() + fixed = self.spellcheck(text) + if fixed != None: + self.tab.text.ChangeValue(fixed) + self.tab.text.SetFocus() - def translate_message(self, *args, **kwargs): - pass + def translate_message(self, *args, **kwargs): + pass - def spellcheck_message(self, *args, **kwargs): - pass \ No newline at end of file + def spellcheck_message(self, *args, **kwargs): + pass diff --git a/src/controller/buffers/communityBoard.py b/src/controller/buffers/communityBoard.py index a9add16..f2cd012 100644 --- a/src/controller/buffers/communityBoard.py +++ b/src/controller/buffers/communityBoard.py @@ -16,53 +16,53 @@ log = logging.getLogger("controller.buffers.communityBoard") class communityBoardBuffer(wallBuffer): - def create_tab(self, parent): - self.tab = communityBoard.communityBoardTab(parent) - self.connect_events() - self.tab.name = self.name - if "can_create_topic" not in self.session.db["group_info"][self.kwargs["group_id"]*-1] or ("can_create_topic" in self.session.db["group_info"][self.kwargs["group_id"]*-1] and self.session.db["group_info"][self.kwargs["group_id"]*-1]["can_create_topic"] != True): - self.tab.post.Enable(False) + def create_tab(self, parent): + self.tab = communityBoard.communityBoardTab(parent) + self.connect_events() + self.tab.name = self.name + if "can_create_topic" not in self.session.db["group_info"][self.kwargs["group_id"]*-1] or ("can_create_topic" in self.session.db["group_info"][self.kwargs["group_id"]*-1] and self.session.db["group_info"][self.kwargs["group_id"]*-1]["can_create_topic"] != True): + self.tab.post.Enable(False) - def onFocus(self, event, *args, **kwargs): - event.Skip() + def onFocus(self, event, *args, **kwargs): + event.Skip() - def open_post(self, *args, **kwargs): - """ Opens the currently focused post.""" - post = self.get_post() - if post == None: - return - a = presenters.displayTopicPresenter(session=self.session, postObject=post, group_id=self.kwargs["group_id"], interactor=interactors.displayPostInteractor(), view=views.displayTopic()) + def open_post(self, *args, **kwargs): + """ Opens the currently focused post.""" + post = self.get_post() + if post == None: + return + a = presenters.displayTopicPresenter(session=self.session, postObject=post, group_id=self.kwargs["group_id"], interactor=interactors.displayPostInteractor(), view=views.displayTopic()) - def open_in_browser(self, *args, **kwargs): - post = self.get_post() - if post == None: - return - # In order to load the selected topic we firstly have to catch the group_id, which is present in self.kwargs - # After getting the group_id we should make it negative - group_id = self.kwargs["group_id"]*-1 - url = "https://vk.com/topic{group_id}_{topic_id}".format(group_id=group_id, topic_id=post["id"]) - webbrowser.open_new_tab(url) + def open_in_browser(self, *args, **kwargs): + post = self.get_post() + if post == None: + return + # In order to load the selected topic we firstly have to catch the group_id, which is present in self.kwargs + # After getting the group_id we should make it negative + group_id = self.kwargs["group_id"]*-1 + url = "https://vk.com/topic{group_id}_{topic_id}".format(group_id=group_id, topic_id=post["id"]) + webbrowser.open_new_tab(url) - def post(self, *args, **kwargs): - menu = wx.Menu() - user1 = self.session.get_user(self.session.user_id) - user2 = self.session.get_user(-1*self.kwargs["group_id"]) - user = menu.Append(wx.NewId(), _("Post as {user1_nom}").format(**user1)) - group = menu.Append(wx.NewId(), _("Post as {user1_nom}").format(**user2)) - menu.Bind(widgetUtils.MENU, lambda evt: self._post(evt, 1), group) - menu.Bind(widgetUtils.MENU, lambda evt: self._post(evt, 0), user) - self.tab.post.PopupMenu(menu, self.tab.post.GetPosition()) + def post(self, *args, **kwargs): + menu = wx.Menu() + user1 = self.session.get_user(self.session.user_id) + user2 = self.session.get_user(-1*self.kwargs["group_id"]) + user = menu.Append(wx.NewId(), _("Post as {user1_nom}").format(**user1)) + group = menu.Append(wx.NewId(), _("Post as {user1_nom}").format(**user2)) + menu.Bind(widgetUtils.MENU, lambda evt: self._post(evt, 1), group) + menu.Bind(widgetUtils.MENU, lambda evt: self._post(evt, 0), user) + self.tab.post.PopupMenu(menu, self.tab.post.GetPosition()) - def _post(self, event, from_group): - owner_id = self.kwargs["group_id"] - user = self.session.get_user(-1*owner_id, key="user1") - title = _("Create topic in {user1_nom}").format(**user) - p = presenters.createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createTopicDialog(title=title, message="", text="", topic_title="")) - if hasattr(p, "text") or hasattr(p, "privacy"): - title = p.view.title.GetValue() - msg = p.text - post_arguments = dict(title=title, text=msg, group_id=owner_id, from_group=from_group) - attachments = [] - if hasattr(p, "attachments"): - attachments = p.attachments - call_threaded(pub.sendMessage, "post", parent_endpoint="board", child_endpoint="addTopic", from_buffer=self.name, attachments_list=attachments, post_arguments=post_arguments) \ No newline at end of file + def _post(self, event, from_group): + owner_id = self.kwargs["group_id"] + user = self.session.get_user(-1*owner_id, key="user1") + title = _("Create topic in {user1_nom}").format(**user) + p = presenters.createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createTopicDialog(title=title, message="", text="", topic_title="")) + if hasattr(p, "text") or hasattr(p, "privacy"): + title = p.view.title.GetValue() + msg = p.text + post_arguments = dict(title=title, text=msg, group_id=owner_id, from_group=from_group) + attachments = [] + if hasattr(p, "attachments"): + attachments = p.attachments + call_threaded(pub.sendMessage, "post", parent_endpoint="board", child_endpoint="addTopic", from_buffer=self.name, attachments_list=attachments, post_arguments=post_arguments) diff --git a/src/controller/buffers/communityDocuments.py b/src/controller/buffers/communityDocuments.py index a662822..7feb904 100644 --- a/src/controller/buffers/communityDocuments.py +++ b/src/controller/buffers/communityDocuments.py @@ -6,11 +6,11 @@ from .documents import documentsBuffer log = logging.getLogger("controller.buffers.communityDocuments") class communityDocumentsBuffer(documentsBuffer): - can_get_items = True + can_get_items = True - def create_tab(self, parent): - self.tab = communityDocuments.communityDocumentsTab(parent) - self.connect_events() - self.tab.name = self.name - if hasattr(self, "can_post") and self.can_post == False and hasattr(self.tab, "post"): - self.tab.post.Enable(False) \ No newline at end of file + def create_tab(self, parent): + self.tab = communityDocuments.communityDocumentsTab(parent) + self.connect_events() + self.tab.name = self.name + if hasattr(self, "can_post") and self.can_post == False and hasattr(self.tab, "post"): + self.tab.post.Enable(False) diff --git a/src/controller/buffers/communityPeople.py b/src/controller/buffers/communityPeople.py index 52c75fa..619ae32 100644 --- a/src/controller/buffers/communityPeople.py +++ b/src/controller/buffers/communityPeople.py @@ -8,19 +8,19 @@ log = logging.getLogger("controller.buffers.communityPeople") class communityPeopleBuffer(peopleBuffer): - def get_menu(self, *args, **kwargs): - user = self.get_post() - m = wx.Menu() - if user.get("can_post") == True: - can_post = m.Append(wx.NewId(), _("&Post on user's wall")) - widgetUtils.connect_event(m, widgetUtils.MENU, self.post, menuitem=can_post) - if user.get("can_write_private_message") == True: - can_write_message = m.Append(wx.Id(), _("Send message")) - widgetUtils.connect_event(m, widgetUtils.MENU, self.new_chat, menuitem=can_write_message) - profile = m.Append(wx.NewId(), _("View profile")) - widgetUtils.connect_event(m, widgetUtils.MENU, self.open_person_profile, menuitem=profile) - timeline = m.Append(wx.NewId(), _("Open timeline")) - widgetUtils.connect_event(m, widgetUtils.MENU, self.open_timeline, menuitem=timeline) - open_in_browser = m.Append(wx.NewId(), _("Open in vk.com")) - widgetUtils.connect_event(m, widgetUtils.MENU, self.open_in_browser, menuitem=open_in_browser) - return m \ No newline at end of file + def get_menu(self, *args, **kwargs): + user = self.get_post() + m = wx.Menu() + if user.get("can_post") == True: + can_post = m.Append(wx.NewId(), _("&Post on user's wall")) + widgetUtils.connect_event(m, widgetUtils.MENU, self.post, menuitem=can_post) + if user.get("can_write_private_message") == True: + can_write_message = m.Append(wx.Id(), _("Send message")) + widgetUtils.connect_event(m, widgetUtils.MENU, self.new_chat, menuitem=can_write_message) + profile = m.Append(wx.NewId(), _("View profile")) + widgetUtils.connect_event(m, widgetUtils.MENU, self.open_person_profile, menuitem=profile) + timeline = m.Append(wx.NewId(), _("Open timeline")) + widgetUtils.connect_event(m, widgetUtils.MENU, self.open_timeline, menuitem=timeline) + open_in_browser = m.Append(wx.NewId(), _("Open in vk.com")) + widgetUtils.connect_event(m, widgetUtils.MENU, self.open_in_browser, menuitem=open_in_browser) + return m diff --git a/src/controller/buffers/communityWall.py b/src/controller/buffers/communityWall.py index ea28a90..bc3f2c2 100644 --- a/src/controller/buffers/communityWall.py +++ b/src/controller/buffers/communityWall.py @@ -16,54 +16,54 @@ log = logging.getLogger("controller.buffers.communityWall") class communityWallBuffer(wallBuffer): - def __init__(self, *args, **kwargs): - super(communityWallBuffer, self).__init__(*args, **kwargs) - self.group_id = self.kwargs["owner_id"] + def __init__(self, *args, **kwargs): + super(communityWallBuffer, self).__init__(*args, **kwargs) + self.group_id = self.kwargs["owner_id"] - def create_tab(self, parent): - self.tab = communityWall.communityWallTab(parent) - self.connect_events() - self.tab.name = self.name - self.tab.post.Enable(False) + def create_tab(self, parent): + self.tab = communityWall.communityWallTab(parent) + self.connect_events() + self.tab.name = self.name + self.tab.post.Enable(False) - def connect_events(self): - super(communityWallBuffer, self).connect_events() - widgetUtils.connect_event(self.tab.load, widgetUtils.BUTTON_PRESSED, self.load_community) + def connect_events(self): + super(communityWallBuffer, self).connect_events() + widgetUtils.connect_event(self.tab.load, widgetUtils.BUTTON_PRESSED, self.load_community) - def load_community(self, *args, **kwargs): - output.speak(_("Loading community...")) - self.can_get_items = True - self.tab.load.Enable(False) - wx.CallAfter(self.get_items) + def load_community(self, *args, **kwargs): + output.speak(_("Loading community...")) + self.can_get_items = True + self.tab.load.Enable(False) + wx.CallAfter(self.get_items) - def get_items(self, *args, **kwargs): - """ This method retrieves community information, useful to show different parts of the community itself.""" - if self.can_get_items: - # Strangely, groups.get does not return counters so we need those to show options for loading specific posts for communities. - group_info = self.session.vk.client.groups.getById(group_ids=-1*self.kwargs["owner_id"], fields="counters")[0] - self.session.db["group_info"][self.group_id].update(group_info) - if "can_post" in self.session.db["group_info"][self.group_id] and self.session.db["group_info"][self.group_id]["can_post"] == True: - self.tab.post.Enable(True) - super(communityWallBuffer, self).get_items(*args, **kwargs) + def get_items(self, *args, **kwargs): + """ This method retrieves community information, useful to show different parts of the community itself.""" + if self.can_get_items: + # Strangely, groups.get does not return counters so we need those to show options for loading specific posts for communities. + group_info = self.session.vk.client.groups.getById(group_ids=-1*self.kwargs["owner_id"], fields="counters")[0] + self.session.db["group_info"][self.group_id].update(group_info) + if "can_post" in self.session.db["group_info"][self.group_id] and self.session.db["group_info"][self.group_id]["can_post"] == True: + self.tab.post.Enable(True) + super(communityWallBuffer, self).get_items(*args, **kwargs) - def post(self, *args, **kwargs): - menu = wx.Menu() - user1 = self.session.get_user(self.session.user_id) - user2 = self.session.get_user(self.kwargs["owner_id"]) - user = menu.Append(wx.NewId(), _("Post as {user1_nom}").format(**user1)) - group = menu.Append(wx.NewId(), _("Post as {user1_nom}").format(**user2)) - menu.Bind(widgetUtils.MENU, lambda evt: self._post(evt, 1), group) - menu.Bind(widgetUtils.MENU, lambda evt: self._post(evt, 0), user) - self.tab.post.PopupMenu(menu, self.tab.post.GetPosition()) + def post(self, *args, **kwargs): + menu = wx.Menu() + user1 = self.session.get_user(self.session.user_id) + user2 = self.session.get_user(self.kwargs["owner_id"]) + user = menu.Append(wx.NewId(), _("Post as {user1_nom}").format(**user1)) + group = menu.Append(wx.NewId(), _("Post as {user1_nom}").format(**user2)) + menu.Bind(widgetUtils.MENU, lambda evt: self._post(evt, 1), group) + menu.Bind(widgetUtils.MENU, lambda evt: self._post(evt, 0), user) + self.tab.post.PopupMenu(menu, self.tab.post.GetPosition()) - def _post(self, event, from_group): - owner_id = self.kwargs["owner_id"] - user = self.session.get_user(owner_id, key="user1") - title = _("Post to {user1_nom}'s wall").format(**user) - p = presenters.createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=title, message="", text="")) - if hasattr(p, "text") or hasattr(p, "privacy"): - post_arguments=dict(privacy=p.privacy, message=p.text, owner_id=owner_id, from_group=from_group) - attachments = [] - if hasattr(p, "attachments"): - attachments = p.attachments - call_threaded(pub.sendMessage, "post", parent_endpoint="wall", child_endpoint="post", from_buffer=self.name, attachments_list=attachments, post_arguments=post_arguments) \ No newline at end of file + def _post(self, event, from_group): + owner_id = self.kwargs["owner_id"] + user = self.session.get_user(owner_id, key="user1") + title = _("Post to {user1_nom}'s wall").format(**user) + p = presenters.createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=title, message="", text="")) + if hasattr(p, "text") or hasattr(p, "privacy"): + post_arguments=dict(privacy=p.privacy, message=p.text, owner_id=owner_id, from_group=from_group) + attachments = [] + if hasattr(p, "attachments"): + attachments = p.attachments + call_threaded(pub.sendMessage, "post", parent_endpoint="wall", child_endpoint="post", from_buffer=self.name, attachments_list=attachments, post_arguments=post_arguments) diff --git a/src/controller/buffers/documents.py b/src/controller/buffers/documents.py index e6049a3..cd9a38e 100644 --- a/src/controller/buffers/documents.py +++ b/src/controller/buffers/documents.py @@ -17,77 +17,77 @@ from .wall import wallBuffer log = logging.getLogger("controller.buffers.documents") class documentsBuffer(wallBuffer): - can_get_items = False + can_get_items = False - def create_tab(self, parent): - self.tab = documents.documentsTab(parent) - self.connect_events() - self.tab.name = self.name - if hasattr(self, "can_post") and self.can_post == False and hasattr(self.tab, "post"): - self.tab.post.Enable(False) + def create_tab(self, parent): + self.tab = documents.documentsTab(parent) + self.connect_events() + self.tab.name = self.name + if hasattr(self, "can_post") and self.can_post == False and hasattr(self.tab, "post"): + self.tab.post.Enable(False) - def onFocus(self, event, *args,**kwargs): - post = self.get_post() - if post == None: - return - original_date = arrow.get(post["date"]) - created_at = original_date.humanize(locale=languageHandler.curLang[:2]) - self.tab.list.list.SetItem(self.tab.list.get_selected(), 4, created_at) - event.Skip() + def onFocus(self, event, *args,**kwargs): + post = self.get_post() + if post == None: + return + original_date = arrow.get(post["date"]) + created_at = original_date.humanize(locale=languageHandler.curLang[:2]) + self.tab.list.list.SetItem(self.tab.list.get_selected(), 4, created_at) + event.Skip() - def connect_events(self): - super(documentsBuffer, self).connect_events() - # Check if we have a load button in the tab, because documents community buffers don't include it. - if hasattr(self.tab, "load"): - widgetUtils.connect_event(self.tab.load, widgetUtils.BUTTON_PRESSED, self.load_documents) + def connect_events(self): + super(documentsBuffer, self).connect_events() + # Check if we have a load button in the tab, because documents community buffers don't include it. + if hasattr(self.tab, "load"): + widgetUtils.connect_event(self.tab.load, widgetUtils.BUTTON_PRESSED, self.load_documents) - def load_documents(self, *args, **kwargs): - output.speak(_("Loading documents...")) - self.can_get_items = True - self.tab.load.Enable(False) - wx.CallAfter(self.get_items) + def load_documents(self, *args, **kwargs): + output.speak(_("Loading documents...")) + self.can_get_items = True + self.tab.load.Enable(False) + wx.CallAfter(self.get_items) - def get_menu(self): - p = self.get_post() - if p == None: - return - if p["owner_id"] == self.session.user_id: - added = True - else: - added = False - m = menus.documentMenu(added) - widgetUtils.connect_event(m, widgetUtils.MENU, self.add_remove_document, menuitem=m.action) - widgetUtils.connect_event(m, widgetUtils.MENU, self.download, menuitem=m.download) - widgetUtils.connect_event(m, widgetUtils.MENU, self.open_in_browser, menuitem=m.open_in_browser) - return m + def get_menu(self): + p = self.get_post() + if p == None: + return + if p["owner_id"] == self.session.user_id: + added = True + else: + added = False + m = menus.documentMenu(added) + widgetUtils.connect_event(m, widgetUtils.MENU, self.add_remove_document, menuitem=m.action) + widgetUtils.connect_event(m, widgetUtils.MENU, self.download, menuitem=m.download) + widgetUtils.connect_event(m, widgetUtils.MENU, self.open_in_browser, menuitem=m.open_in_browser) + return m - def add_remove_document(self, *args, **kwargs): - p = self.get_post() - if p == None: - return - if p["owner_id"] == self.session.user_id: - result = self.session.vk.client.docs.delete(owner_id=p["owner_id"], doc_id=p["id"]) - if result == 1: - output.speak(_("The document has been successfully deleted.")) - self.session.db[self.name]["items"].pop(self.tab.list.get_selected()) - self.tab.list.remove_item(self.tab.list.get_selected()) - else: - result = self.session.vk.client.docs.add(owner_id=p["owner_id"], doc_id=p["id"]) - output.speak(_("The document has been successfully added.")) + def add_remove_document(self, *args, **kwargs): + p = self.get_post() + if p == None: + return + if p["owner_id"] == self.session.user_id: + result = self.session.vk.client.docs.delete(owner_id=p["owner_id"], doc_id=p["id"]) + if result == 1: + output.speak(_("The document has been successfully deleted.")) + self.session.db[self.name]["items"].pop(self.tab.list.get_selected()) + self.tab.list.remove_item(self.tab.list.get_selected()) + else: + result = self.session.vk.client.docs.add(owner_id=p["owner_id"], doc_id=p["id"]) + output.speak(_("The document has been successfully added.")) - def download(self, *args, **kwargs): - post = self.get_post() - filename = utils.safe_filename(post["title"]) - # If document does not end in .extension we must fix it so the file dialog will save it properly later. - if filename.endswith(post["ext"]) == False: - filename = filename+ "."+post["ext"] - filepath = self.tab.get_download_path(filename) - if filepath != None: - pub.sendMessage("download-file", url=post["url"], filename=filepath) + def download(self, *args, **kwargs): + post = self.get_post() + filename = utils.safe_filename(post["title"]) + # If document does not end in .extension we must fix it so the file dialog will save it properly later. + if filename.endswith(post["ext"]) == False: + filename = filename+ "."+post["ext"] + filepath = self.tab.get_download_path(filename) + if filepath != None: + pub.sendMessage("download-file", url=post["url"], filename=filepath) - def open_in_browser(self, *args, **kwargs): - post = self.get_post() - if post == None: - return - url = "https://vk.com/doc{user_id}_{post_id}".format(user_id=post["owner_id"], post_id=post["id"]) - webbrowser.open_new_tab(url) \ No newline at end of file + def open_in_browser(self, *args, **kwargs): + post = self.get_post() + if post == None: + return + url = "https://vk.com/doc{user_id}_{post_id}".format(user_id=post["owner_id"], post_id=post["id"]) + webbrowser.open_new_tab(url) diff --git a/src/controller/buffers/empty.py b/src/controller/buffers/empty.py index 2c6fef0..d415367 100644 --- a/src/controller/buffers/empty.py +++ b/src/controller/buffers/empty.py @@ -8,20 +8,20 @@ log = logging.getLogger("controller.buffers.empty") class emptyBuffer(object): - def __init__(self, name=None, parent=None, *args, **kwargs): - self.tab = empty.emptyTab(parent=parent, name=name) - self.name = name + def __init__(self, name=None, parent=None, *args, **kwargs): + self.tab = empty.emptyTab(parent=parent, name=name) + self.name = name - def get_items(self, *args, **kwargs): - if not hasattr(self, "tab"): - # Create GUI associated to this buffer. - self.create_tab(self.parent) - # Add name to the new control so we could look for it when needed. - self.tab.name = self.name - pass + def get_items(self, *args, **kwargs): + if not hasattr(self, "tab"): + # Create GUI associated to this buffer. + self.create_tab(self.parent) + # Add name to the new control so we could look for it when needed. + self.tab.name = self.name + pass - def get_more_items(self, *args, **kwargs): - output.speak(_("This buffer doesn't support getting more items.")) + def get_more_items(self, *args, **kwargs): + output.speak(_("This buffer doesn't support getting more items.")) - def remove_buffer(self, mandatory=False): - return False \ No newline at end of file + def remove_buffer(self, mandatory=False): + return False diff --git a/src/controller/buffers/friendRequests.py b/src/controller/buffers/friendRequests.py index cfb061d..cb44c4a 100644 --- a/src/controller/buffers/friendRequests.py +++ b/src/controller/buffers/friendRequests.py @@ -9,73 +9,73 @@ log = logging.getLogger("controller.buffers.friendRequests") class friendRequestsBuffer(peopleBuffer): - def get_items(self, show_nextpage=False): - if self.can_get_items == False: return - retrieved = True - try: - ids = self.session.vk.client.friends.getRequests(*self.args, **self.kwargs) - except VkApiError as err: - log.error("Error {0}: {1}".format(err.code, err.error)) - retrieved = err.code - return retrieved - except: - log.exception("Connection error when updating buffer %s. Will try again in 2 minutes" % (self.name,)) - return False - num = self.session.get_page(name=self.name, show_nextpage=show_nextpage, endpoint="get", parent_endpoint="users", count=1000, user_ids=", ".join([str(i) for i in ids["items"]]), fields="uid, first_name, last_name, last_seen") - if not hasattr(self, "tab"): - # Create GUI associated to this buffer. - self.create_tab(self.parent) - # Add name to the new control so we could look for it when needed. - self.tab.name = self.name - if show_nextpage == False: - if self.tab.list.get_count() > 0 and num > 0: - v = [i for i in self.session.db[self.name]["items"][:num]] - v.reverse() - [wx.CallAfter(self.insert, i, True) for i in v] - else: - [wx.CallAfter(self.insert, i) for i in self.session.db[self.name]["items"][:num]] - return retrieved + def get_items(self, show_nextpage=False): + if self.can_get_items == False: return + retrieved = True + try: + ids = self.session.vk.client.friends.getRequests(*self.args, **self.kwargs) + except VkApiError as err: + log.error("Error {0}: {1}".format(err.code, err.error)) + retrieved = err.code + return retrieved + except: + log.exception("Connection error when updating buffer %s. Will try again in 2 minutes" % (self.name,)) + return False + num = self.session.get_page(name=self.name, show_nextpage=show_nextpage, endpoint="get", parent_endpoint="users", count=1000, user_ids=", ".join([str(i) for i in ids["items"]]), fields="uid, first_name, last_name, last_seen") + if not hasattr(self, "tab"): + # Create GUI associated to this buffer. + self.create_tab(self.parent) + # Add name to the new control so we could look for it when needed. + self.tab.name = self.name + if show_nextpage == False: + if self.tab.list.get_count() > 0 and num > 0: + v = [i for i in self.session.db[self.name]["items"][:num]] + v.reverse() + [wx.CallAfter(self.insert, i, True) for i in v] + else: + [wx.CallAfter(self.insert, i) for i in self.session.db[self.name]["items"][:num]] + return retrieved - def accept_friendship(self, *args, **kwargs): - """ Adds a person to a list of friends. This method is done for accepting someone else's friend request. - https://vk.com/dev/friends.add - """ - person = self.get_post() - if person == None: - return - result = self.session.vk.client.friends.add(user_id=person["id"]) - if result == 2: - msg = _("{0} {1} now is your friend.").format(person["first_name"], person["last_name"]) - pub.sendMessage("notify", message=msg) - self.session.db[self.name]["items"].pop(self.tab.list.get_selected()) - self.tab.list.remove_item(self.tab.list.get_selected()) + def accept_friendship(self, *args, **kwargs): + """ Adds a person to a list of friends. This method is done for accepting someone else's friend request. + https://vk.com/dev/friends.add + """ + person = self.get_post() + if person == None: + return + result = self.session.vk.client.friends.add(user_id=person["id"]) + if result == 2: + msg = _("{0} {1} now is your friend.").format(person["first_name"], person["last_name"]) + pub.sendMessage("notify", message=msg) + self.session.db[self.name]["items"].pop(self.tab.list.get_selected()) + self.tab.list.remove_item(self.tab.list.get_selected()) - def decline_friendship(self, *args, **kwargs): - """ Declines a freind request. - https://vk.com/dev/friends.delete - """ - person = self.get_post() - if person == None: - return - result = self.session.vk.client.friends.delete(user_id=person["id"]) - if "out_request_deleted" in result: - msg = _("You've deleted the friends request to {0} {1}.").format(person["first_name"], person["last_name"]) - elif "in_request_deleted" in result: - msg = _("You've declined the friend request of {0} {1}.").format(person["first_name"], person["last_name"]) - pub.sendMessage("notify", message=msg) - self.session.db[self.name]["items"].pop(self.tab.list.get_selected()) - self.tab.list.remove_item(self.tab.list.get_selected()) + def decline_friendship(self, *args, **kwargs): + """ Declines a freind request. + https://vk.com/dev/friends.delete + """ + person = self.get_post() + if person == None: + return + result = self.session.vk.client.friends.delete(user_id=person["id"]) + if "out_request_deleted" in result: + msg = _("You've deleted the friends request to {0} {1}.").format(person["first_name"], person["last_name"]) + elif "in_request_deleted" in result: + msg = _("You've declined the friend request of {0} {1}.").format(person["first_name"], person["last_name"]) + pub.sendMessage("notify", message=msg) + self.session.db[self.name]["items"].pop(self.tab.list.get_selected()) + self.tab.list.remove_item(self.tab.list.get_selected()) - def keep_as_follower(self, *args, **kwargs): - """ Adds a person to The followers list of the current user. - https://vk.com/dev/friends.add - """ - person = self.get_post() - if person == None: - return - result = self.session.vk.client.friends.add(user_id=person["id"], follow=1) - if result == 2: - msg = _("{0} {1} is following you.").format(person["first_name"], person["last_name"]) - pub.sendMessage("notify", message=msg) - self.session.db[self.name]["items"].pop(self.tab.list.get_selected()) - self.tab.list.remove_item(self.tab.list.get_selected()) \ No newline at end of file + def keep_as_follower(self, *args, **kwargs): + """ Adds a person to The followers list of the current user. + https://vk.com/dev/friends.add + """ + person = self.get_post() + if person == None: + return + result = self.session.vk.client.friends.add(user_id=person["id"], follow=1) + if result == 2: + msg = _("{0} {1} is following you.").format(person["first_name"], person["last_name"]) + pub.sendMessage("notify", message=msg) + self.session.db[self.name]["items"].pop(self.tab.list.get_selected()) + self.tab.list.remove_item(self.tab.list.get_selected()) diff --git a/src/controller/buffers/home.py b/src/controller/buffers/home.py index f213f2d..1dc2d98 100644 --- a/src/controller/buffers/home.py +++ b/src/controller/buffers/home.py @@ -20,313 +20,313 @@ from wxUI import commonMessages, menus log = logging.getLogger("controller.buffers.home") class homeBuffer(object): - """ a basic representation of a buffer. Other buffers should be derived from this class. This buffer represents the "news feed" """ + """ a basic representation of a buffer. Other buffers should be derived from this class. This buffer represents the "news feed" """ - def get_post(self): - """ Return the currently focused post.""" - # Handle case where there are no items in the buffer. - if self.tab.list.get_count() == 0: - wx.Bell() - return None - return self.session.db[self.name]["items"][self.tab.list.get_selected()] + def get_post(self): + """ Return the currently focused post.""" + # Handle case where there are no items in the buffer. + if self.tab.list.get_count() == 0: + wx.Bell() + return None + return self.session.db[self.name]["items"][self.tab.list.get_selected()] - def __init__(self, parent=None, name="", session=None, composefunc=None, create_tab=True, *args, **kwargs): - """ Constructor: - @parent wx.Treebook: parent for the buffer panel, - @name str: Name for saving this buffer's data in the local storage variable, - @session sessionmanager.session.vkSession: Session for performing operations in the Vk API. This session should be logged in when this class is instanciated. - @composefunc str: This function will be called for composing the result which will be put in the listCtrl. Composefunc should exist in the sessionmanager.renderers module. - args and kwargs will be passed to get_items() without any filtering. Be careful there. - """ - super(homeBuffer, self).__init__() - self.parent = parent - self.args = args - self.kwargs = kwargs - self.session = session - self.compose_function = composefunc - self.name = name - if create_tab: - self.create_tab(self.parent) - #Update_function will be called every 3 minutes and it should be able to - # Get all new items in the buffer and sort them properly in the CtrlList. - # ToDo: Shall we allow dinamically set for update_function? - self.update_function = "get_page" - self.name = name - # source_key and post_key will point to the keys for sender and posts in VK API objects. - # They can be changed in the future for other item types in different buffers. - self.user_key = "source_id" - self.post_key = "post_id" - # When set to False, update_function won't be executed here. - self.can_get_items = True + def __init__(self, parent=None, name="", session=None, composefunc=None, create_tab=True, *args, **kwargs): + """ Constructor: + @parent wx.Treebook: parent for the buffer panel, + @name str: Name for saving this buffer's data in the local storage variable, + @session sessionmanager.session.vkSession: Session for performing operations in the Vk API. This session should be logged in when this class is instanciated. + @composefunc str: This function will be called for composing the result which will be put in the listCtrl. Composefunc should exist in the sessionmanager.renderers module. + args and kwargs will be passed to get_items() without any filtering. Be careful there. + """ + super(homeBuffer, self).__init__() + self.parent = parent + self.args = args + self.kwargs = kwargs + self.session = session + self.compose_function = composefunc + self.name = name + if create_tab: + self.create_tab(self.parent) + #Update_function will be called every 3 minutes and it should be able to + # Get all new items in the buffer and sort them properly in the CtrlList. + # ToDo: Shall we allow dinamically set for update_function? + self.update_function = "get_page" + self.name = name + # source_key and post_key will point to the keys for sender and posts in VK API objects. + # They can be changed in the future for other item types in different buffers. + self.user_key = "source_id" + self.post_key = "post_id" + # When set to False, update_function won't be executed here. + self.can_get_items = True - def create_tab(self, parent): - """ Create the Wx panel.""" - self.tab = home.homeTab(parent) - # Bind local events (they will respond to events happened in the buffer). - self.connect_events() - self.tab.name = self.name - if hasattr(self, "can_post") and self.can_post == False and hasattr(self.tab, "post"): - self.tab.post.Enable(False) + def create_tab(self, parent): + """ Create the Wx panel.""" + self.tab = home.homeTab(parent) + # Bind local events (they will respond to events happened in the buffer). + self.connect_events() + self.tab.name = self.name + if hasattr(self, "can_post") and self.can_post == False and hasattr(self.tab, "post"): + self.tab.post.Enable(False) - def insert(self, item, reversed=False): - """ Add a new item to the list. Uses renderers.composefunc for parsing the dictionary and create a valid result for putting it in the list.""" - try: - item_ = getattr(renderers, self.compose_function)(item, self.session) - wx.CallAfter(self.tab.list.insert_item, reversed, *item_) - except: - log.exception(item) + def insert(self, item, reversed=False): + """ Add a new item to the list. Uses renderers.composefunc for parsing the dictionary and create a valid result for putting it in the list.""" + try: + item_ = getattr(renderers, self.compose_function)(item, self.session) + wx.CallAfter(self.tab.list.insert_item, reversed, *item_) + except: + log.exception(item) - def get_items(self, show_nextpage=False): - """ Retrieve items from the VK API. This function is called repeatedly by the main controller and users could call it implicitly as well with the update buffer option. - @show_nextpage boolean: If it's true, it will try to load previous results. - """ - if self.can_get_items == False: return - retrieved = True # Control variable for handling unauthorised/connection errors. - try: - num = getattr(self.session, "get_newsfeed")(show_nextpage=show_nextpage, name=self.name, *self.args, **self.kwargs) - except VkApiError as err: - log.error("Error {0}: {1}".format(err.code, err.error)) - retrieved = err.code - return retrieved - except: - log.exception("Connection error when updating buffer %s. Will try again in 2 minutes" % (self.name,)) - return False - if not hasattr(self, "tab"): - # Create GUI associated to this buffer. - self.create_tab(self.parent) - # Add name to the new control so we could look for it when needed. - if show_nextpage == False: - if self.tab.list.get_count() > 0 and num > 0: - v = [i for i in self.session.db[self.name]["items"][:num]] - v.reverse() - [wx.CallAfter(self.insert, i, True) for i in v] - else: - [wx.CallAfter(self.insert, i) for i in self.session.db[self.name]["items"][:num]] - else: - if num > 0: - [wx.CallAfter(self.insert, i, False) for i in self.session.db[self.name]["items"][-num:]] - return retrieved + def get_items(self, show_nextpage=False): + """ Retrieve items from the VK API. This function is called repeatedly by the main controller and users could call it implicitly as well with the update buffer option. + @show_nextpage boolean: If it's true, it will try to load previous results. + """ + if self.can_get_items == False: return + retrieved = True # Control variable for handling unauthorised/connection errors. + try: + num = getattr(self.session, "get_newsfeed")(show_nextpage=show_nextpage, name=self.name, *self.args, **self.kwargs) + except VkApiError as err: + log.error("Error {0}: {1}".format(err.code, err.error)) + retrieved = err.code + return retrieved + except: + log.exception("Connection error when updating buffer %s. Will try again in 2 minutes" % (self.name,)) + return False + if not hasattr(self, "tab"): + # Create GUI associated to this buffer. + self.create_tab(self.parent) + # Add name to the new control so we could look for it when needed. + if show_nextpage == False: + if self.tab.list.get_count() > 0 and num > 0: + v = [i for i in self.session.db[self.name]["items"][:num]] + v.reverse() + [wx.CallAfter(self.insert, i, True) for i in v] + else: + [wx.CallAfter(self.insert, i) for i in self.session.db[self.name]["items"][:num]] + else: + if num > 0: + [wx.CallAfter(self.insert, i, False) for i in self.session.db[self.name]["items"][-num:]] + return retrieved - def get_more_items(self): - """ Returns previous items in the buffer.""" - self.get_items(show_nextpage=True) + def get_more_items(self): + """ Returns previous items in the buffer.""" + self.get_items(show_nextpage=True) - def post(self, *args, **kwargs): - """ Create a post in the current user's wall. - This process is handled in two parts. This is the first part, where the GUI is created and user can send the post. - During the second part (threaded), the post will be sent to the API.""" - p = presenters.createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Write your post"), message="", text="")) - if hasattr(p, "text") or hasattr(p, "privacy"): - post_arguments=dict(privacy=p.privacy, message=p.text) - attachments = [] - if hasattr(p, "attachments"): - attachments = p.attachments - call_threaded(pub.sendMessage, "post", parent_endpoint="wall", child_endpoint="post", from_buffer=self.name, attachments_list=attachments, post_arguments=post_arguments) + def post(self, *args, **kwargs): + """ Create a post in the current user's wall. + This process is handled in two parts. This is the first part, where the GUI is created and user can send the post. + During the second part (threaded), the post will be sent to the API.""" + p = presenters.createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Write your post"), message="", text="")) + if hasattr(p, "text") or hasattr(p, "privacy"): + post_arguments=dict(privacy=p.privacy, message=p.text) + attachments = [] + if hasattr(p, "attachments"): + attachments = p.attachments + call_threaded(pub.sendMessage, "post", parent_endpoint="wall", child_endpoint="post", from_buffer=self.name, attachments_list=attachments, post_arguments=post_arguments) - def connect_events(self): - """ Bind all events to this buffer""" - widgetUtils.connect_event(self.tab.post, widgetUtils.BUTTON_PRESSED, self.post) - widgetUtils.connect_event(self.tab.list.list, widgetUtils.KEYPRESS, self.get_event) - widgetUtils.connect_event(self.tab.list.list, wx.EVT_CONTEXT_MENU, self.show_menu) - self.tab.set_focus_function(self.onFocus) + def connect_events(self): + """ Bind all events to this buffer""" + widgetUtils.connect_event(self.tab.post, widgetUtils.BUTTON_PRESSED, self.post) + widgetUtils.connect_event(self.tab.list.list, widgetUtils.KEYPRESS, self.get_event) + widgetUtils.connect_event(self.tab.list.list, wx.EVT_CONTEXT_MENU, self.show_menu) + self.tab.set_focus_function(self.onFocus) - def show_menu(self, ev, pos=0, *args, **kwargs): - """ Show contextual menu when pressing menu key or right mouse click in a list item.""" - if self.tab.list.get_count() == 0: return - menu = self.get_menu() - if pos != 0: - self.tab.PopupMenu(menu, pos) - else: - self.tab.PopupMenu(menu, self.tab.list.list.GetPosition()) + def show_menu(self, ev, pos=0, *args, **kwargs): + """ Show contextual menu when pressing menu key or right mouse click in a list item.""" + if self.tab.list.get_count() == 0: return + menu = self.get_menu() + if pos != 0: + self.tab.PopupMenu(menu, pos) + else: + self.tab.PopupMenu(menu, self.tab.list.list.GetPosition()) - def show_menu_by_key(self, ev): - """ Show contextual menu when menu key is pressed""" - if self.tab.list.get_count() == 0: - return - if ev.GetKeyCode() == wx.WXK_WINDOWS_MENU: - self.show_menu(widgetUtils.MENU, pos=self.tab.list.list.GetPosition()) + def show_menu_by_key(self, ev): + """ Show contextual menu when menu key is pressed""" + if self.tab.list.get_count() == 0: + return + if ev.GetKeyCode() == wx.WXK_WINDOWS_MENU: + self.show_menu(widgetUtils.MENU, pos=self.tab.list.list.GetPosition()) - def get_menu(self): - """ Returns contextual menu options. They will change according to the focused item""" - p = self.get_post() - if p == None: - return - # determine if the current user is able to delete the object. - if "can_delete" in p: - can_delete = True==p["can_delete"] - else: - can_delete = False - m = menus.postMenu(can_delete=can_delete) - if ("likes" in p) == False: - m.like.Enable(False) - elif p["likes"]["user_likes"] == 1: - m.like.Enable(False) - m.dislike.Enable(True) - if ("comments" in p) == False: - m.comment.Enable(False) - m.open_in_browser.Enable(False) - if "type" in p and p["type"] != "friend" and p["type"] != "audio" and p["type"] != "video" and p["type"] != "playlist" or self.name != "home_timeline": - m.open_in_browser.Enable(True) - widgetUtils.connect_event(m, widgetUtils.MENU, self.open_post, menuitem=m.open) - widgetUtils.connect_event(m, widgetUtils.MENU, self.do_like, menuitem=m.like) - widgetUtils.connect_event(m, widgetUtils.MENU, self.do_dislike, menuitem=m.dislike) - widgetUtils.connect_event(m, widgetUtils.MENU, self.do_comment, menuitem=m.comment) - widgetUtils.connect_event(m, widgetUtils.MENU, self.open_in_browser, menuitem=m.open_in_browser) - if hasattr(m, "view_profile"): - widgetUtils.connect_event(m, widgetUtils.MENU, self.open_person_profile, menuitem=m.view_profile) - if hasattr(m, "delete"): - widgetUtils.connect_event(m, widgetUtils.MENU, self.delete, menuitem=m.delete) - return m + def get_menu(self): + """ Returns contextual menu options. They will change according to the focused item""" + p = self.get_post() + if p == None: + return + # determine if the current user is able to delete the object. + if "can_delete" in p: + can_delete = True==p["can_delete"] + else: + can_delete = False + m = menus.postMenu(can_delete=can_delete) + if ("likes" in p) == False: + m.like.Enable(False) + elif p["likes"]["user_likes"] == 1: + m.like.Enable(False) + m.dislike.Enable(True) + if ("comments" in p) == False: + m.comment.Enable(False) + m.open_in_browser.Enable(False) + if "type" in p and p["type"] != "friend" and p["type"] != "audio" and p["type"] != "video" and p["type"] != "playlist" or self.name != "home_timeline": + m.open_in_browser.Enable(True) + widgetUtils.connect_event(m, widgetUtils.MENU, self.open_post, menuitem=m.open) + widgetUtils.connect_event(m, widgetUtils.MENU, self.do_like, menuitem=m.like) + widgetUtils.connect_event(m, widgetUtils.MENU, self.do_dislike, menuitem=m.dislike) + widgetUtils.connect_event(m, widgetUtils.MENU, self.do_comment, menuitem=m.comment) + widgetUtils.connect_event(m, widgetUtils.MENU, self.open_in_browser, menuitem=m.open_in_browser) + if hasattr(m, "view_profile"): + widgetUtils.connect_event(m, widgetUtils.MENU, self.open_person_profile, menuitem=m.view_profile) + if hasattr(m, "delete"): + widgetUtils.connect_event(m, widgetUtils.MENU, self.delete, menuitem=m.delete) + return m - def do_like(self, *args, **kwargs): - """ Set like in the currently focused post.""" - post = self.get_post() - if post == None: - return - user = post[self.user_key] - id = post[self.post_key] - if "type" in post: - type_ = post["type"] - else: - type_ = "post" - l = self.session.vk.client.likes.add(owner_id=user, item_id=id, type=type_) - self.session.db[self.name]["items"][self.tab.list.get_selected()]["likes"]["count"] = l["likes"] - self.session.db[self.name]["items"][self.tab.list.get_selected()]["likes"]["user_likes"] = 1 - # Translators: This will be used when user presses like. - output.speak(_("You liked this")) + def do_like(self, *args, **kwargs): + """ Set like in the currently focused post.""" + post = self.get_post() + if post == None: + return + user = post[self.user_key] + id = post[self.post_key] + if "type" in post: + type_ = post["type"] + else: + type_ = "post" + l = self.session.vk.client.likes.add(owner_id=user, item_id=id, type=type_) + self.session.db[self.name]["items"][self.tab.list.get_selected()]["likes"]["count"] = l["likes"] + self.session.db[self.name]["items"][self.tab.list.get_selected()]["likes"]["user_likes"] = 1 + # Translators: This will be used when user presses like. + output.speak(_("You liked this")) - def do_dislike(self, *args, **kwargs): - """ Set dislike (undo like) in the currently focused post.""" - post = self.get_post() - if post == None: - return - user = post[self.user_key] - id = post[self.post_key] - if "type" in post: - type_ = post["type"] - else: - type_ = "post" - l = self.session.vk.client.likes.delete(owner_id=user, item_id=id, type=type_) - self.session.db[self.name]["items"][self.tab.list.get_selected()]["likes"]["count"] = l["likes"] - self.session.db[self.name]["items"][self.tab.list.get_selected()]["likes"]["user_likes"] = 2 - # Translators: This will be user in 'dislike' - output.speak(_("You don't like this")) + def do_dislike(self, *args, **kwargs): + """ Set dislike (undo like) in the currently focused post.""" + post = self.get_post() + if post == None: + return + user = post[self.user_key] + id = post[self.post_key] + if "type" in post: + type_ = post["type"] + else: + type_ = "post" + l = self.session.vk.client.likes.delete(owner_id=user, item_id=id, type=type_) + self.session.db[self.name]["items"][self.tab.list.get_selected()]["likes"]["count"] = l["likes"] + self.session.db[self.name]["items"][self.tab.list.get_selected()]["likes"]["user_likes"] = 2 + # Translators: This will be user in 'dislike' + output.speak(_("You don't like this")) - def do_comment(self, *args, **kwargs): - """ Make a comment into the currently focused post.""" - post = self.get_post() - if post == None: - return - comment = presenters.createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Add a comment"), message="", text="", mode="comment")) - if hasattr(comment, "text") or hasattr(comment, "privacy"): - msg = comment.text - try: - user = post[self.user_key] - id = post[self.post_key] - self.session.vk.client.wall.addComment(owner_id=user, post_id=id, text=msg) - output.speak(_("You've posted a comment")) - except Exception as msg: - log.error(msg) + def do_comment(self, *args, **kwargs): + """ Make a comment into the currently focused post.""" + post = self.get_post() + if post == None: + return + comment = presenters.createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Add a comment"), message="", text="", mode="comment")) + if hasattr(comment, "text") or hasattr(comment, "privacy"): + msg = comment.text + try: + user = post[self.user_key] + id = post[self.post_key] + self.session.vk.client.wall.addComment(owner_id=user, post_id=id, text=msg) + output.speak(_("You've posted a comment")) + except Exception as msg: + log.error(msg) - def delete(self, *args, **kwargs): - post = self.get_post() - if ("type" in post and post["type"] == "post") or self.name != "newsfeed": - question = commonMessages.remove_post() - if question == widgetUtils.NO: - return - if "owner_id" in self.kwargs: - result = self.session.vk.client.wall.delete(owner_id=self.kwargs["owner_id"], post_id=post[self.post_key]) - else: - result = self.session.vk.client.wall.delete(post_id=post[self.post_key]) - pub.sendMessage("post_deleted", post_id=post[self.post_key]) - self.session.db[self.name]["items"].pop(self.tab.list.get_selected()) - self.tab.list.remove_item(self.tab.list.get_selected()) + def delete(self, *args, **kwargs): + post = self.get_post() + if ("type" in post and post["type"] == "post") or self.name != "newsfeed": + question = commonMessages.remove_post() + if question == widgetUtils.NO: + return + if "owner_id" in self.kwargs: + result = self.session.vk.client.wall.delete(owner_id=self.kwargs["owner_id"], post_id=post[self.post_key]) + else: + result = self.session.vk.client.wall.delete(post_id=post[self.post_key]) + pub.sendMessage("post_deleted", post_id=post[self.post_key]) + self.session.db[self.name]["items"].pop(self.tab.list.get_selected()) + self.tab.list.remove_item(self.tab.list.get_selected()) - def get_event(self, ev): - """ Parses keyboard input in the ListCtrl and executes the event associated with user keypresses.""" - if ev.GetKeyCode() == wx.WXK_RETURN: event = "open_post" - else: - event = None - ev.Skip() - if event != None: - try: - getattr(self, event)() - except AttributeError: - pass + def get_event(self, ev): + """ Parses keyboard input in the ListCtrl and executes the event associated with user keypresses.""" + if ev.GetKeyCode() == wx.WXK_RETURN: event = "open_post" + else: + event = None + ev.Skip() + if event != None: + try: + getattr(self, event)() + except AttributeError: + pass - def volume_down(self): - """ Decreases player volume by 2%""" - player.player.volume = player.player.volume-2 + def volume_down(self): + """ Decreases player volume by 2%""" + player.player.volume = player.player.volume-2 - def volume_up(self): - """ Increases player volume by 2%""" - player.player.volume = player.player.volume+2 + def volume_up(self): + """ Increases player volume by 2%""" + player.player.volume = player.player.volume+2 - def play_audio(self, *args, **kwargs): - """ Play audio in currently focused buffer, if possible.""" - post = self.get_post() - if post == None: - return - if "type" in post and post["type"] == "audio": - pub.sendMessage("play", object=post["audio"]["items"][0]) - return True + def play_audio(self, *args, **kwargs): + """ Play audio in currently focused buffer, if possible.""" + post = self.get_post() + if post == None: + return + if "type" in post and post["type"] == "audio": + pub.sendMessage("play", object=post["audio"]["items"][0]) + return True - def open_person_profile(self, *args, **kwargs): - """ Views someone's profile.""" - selected = self.get_post() - if selected == None: - return - # Check all possible keys for an user object in VK API. - keys = ["from_id", "source_id", "id"] - for i in keys: - if i in selected: - pub.sendMessage("user-profile", person=selected[i]) - break + def open_person_profile(self, *args, **kwargs): + """ Views someone's profile.""" + selected = self.get_post() + if selected == None: + return + # Check all possible keys for an user object in VK API. + keys = ["from_id", "source_id", "id"] + for i in keys: + if i in selected: + pub.sendMessage("user-profile", person=selected[i]) + break - def open_post(self, *args, **kwargs): - """ Opens the currently focused post.""" - post = self.get_post() - if post == None: - return - if "type" in post and post["type"] == "audio": - a = presenters.displayAudioPresenter(session=self.session, postObject=post["audio"]["items"], interactor=interactors.displayAudioInteractor(), view=views.displayAudio()) - elif "type" in post and post["type"] == "friend": - pub.sendMessage("open-post", post_object=post, controller_="displayFriendship", vars=dict(caption=_("{user1_nom} added the following friends"))) - else: - pub.sendMessage("open-post", post_object=post, controller_="displayPost") + def open_post(self, *args, **kwargs): + """ Opens the currently focused post.""" + post = self.get_post() + if post == None: + return + if "type" in post and post["type"] == "audio": + a = presenters.displayAudioPresenter(session=self.session, postObject=post["audio"]["items"], interactor=interactors.displayAudioInteractor(), view=views.displayAudio()) + elif "type" in post and post["type"] == "friend": + pub.sendMessage("open-post", post_object=post, controller_="displayFriendship", vars=dict(caption=_("{user1_nom} added the following friends"))) + else: + pub.sendMessage("open-post", post_object=post, controller_="displayPost") - def pause_audio(self, *args, **kwargs): - """ pauses audio playback.""" - pub.sendMessage("pause") + def pause_audio(self, *args, **kwargs): + """ pauses audio playback.""" + pub.sendMessage("pause") - def remove_buffer(self, mandatory): - """ Function for removing a buffer. Returns True if removal is successful, False otherwise""" - return False + def remove_buffer(self, mandatory): + """ Function for removing a buffer. Returns True if removal is successful, False otherwise""" + return False - def get_users(self): - """ Returns source user in the post.""" - post = self.get_post() - if post == None: - return - if ("type" in post) == False: - return [post["from_id"]] - else: - return [post["source_id"]] + def get_users(self): + """ Returns source user in the post.""" + post = self.get_post() + if post == None: + return + if ("type" in post) == False: + return [post["from_id"]] + else: + return [post["source_id"]] - def onFocus(self, event, *args,**kwargs): - """ Function executed when the item in a list is selected. - For this buffer it updates the date of posts in the list.""" - post = self.get_post() - if post == None: - return - original_date = arrow.get(post["date"]) - created_at = original_date.humanize(locale=languageHandler.curLang[:2]) - self.tab.list.list.SetItem(self.tab.list.get_selected(), 2, created_at) - event.Skip() + def onFocus(self, event, *args,**kwargs): + """ Function executed when the item in a list is selected. + For this buffer it updates the date of posts in the list.""" + post = self.get_post() + if post == None: + return + original_date = arrow.get(post["date"]) + created_at = original_date.humanize(locale=languageHandler.curLang[:2]) + self.tab.list.list.SetItem(self.tab.list.get_selected(), 2, created_at) + event.Skip() - def open_in_browser(self, *args, **kwargs): - post = self.get_post() - if post == None: - return - url = "https://vk.com/wall{user_id}_{post_id}".format(user_id=post["source_id"], post_id=post["post_id"]) - webbrowser.open_new_tab(url) \ No newline at end of file + def open_in_browser(self, *args, **kwargs): + post = self.get_post() + if post == None: + return + url = "https://vk.com/wall{user_id}_{post_id}".format(user_id=post["source_id"], post_id=post["post_id"]) + webbrowser.open_new_tab(url) diff --git a/src/controller/buffers/notification.py b/src/controller/buffers/notification.py index 8d2a9cb..e718719 100644 --- a/src/controller/buffers/notification.py +++ b/src/controller/buffers/notification.py @@ -7,10 +7,10 @@ log = logging.getLogger("controller.buffers") class notificationBuffer(wallBuffer): - def create_tab(self, parent): - self.tab = notification.notificationTab(parent) - self.connect_events() - self.tab.name = self.name + def create_tab(self, parent): + self.tab = notification.notificationTab(parent) + self.connect_events() + self.tab.name = self.name - def onFocus(self, event, *args, **kwargs): - event.Skip() + def onFocus(self, event, *args, **kwargs): + event.Skip() diff --git a/src/controller/buffers/people.py b/src/controller/buffers/people.py index 0d3cbd0..e3976a1 100644 --- a/src/controller/buffers/people.py +++ b/src/controller/buffers/people.py @@ -21,205 +21,205 @@ log = logging.getLogger("controller.buffers.friends") class peopleBuffer(wallBuffer): - def post(self, *args, **kwargs): - user = self.get_post() - if "can_post" not in user: # retrieve data if not present in the object. - user = self.session.vk.client.users.get(user_ids=user["id"], fields="can_post")[0] - if user.get("can_post") == True: - user_str = self.session.get_user(user["id"], key="user1") - title = _("Post to {user1_nom}'s wall").format(**user_str) - p = presenters.createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=title, message="", text="")) - if hasattr(p, "text") or hasattr(p, "privacy"): - post_arguments=dict(privacy=p.privacy, message=p.text, owner_id=user["id"]) - attachments = [] - if hasattr(p, "attachments"): - attachments = p.attachments - call_threaded(pub.sendMessage, "post", parent_endpoint="wall", child_endpoint="post", from_buffer=self.name, attachments_list=attachments, post_arguments=post_arguments) + def post(self, *args, **kwargs): + user = self.get_post() + if "can_post" not in user: # retrieve data if not present in the object. + user = self.session.vk.client.users.get(user_ids=user["id"], fields="can_post")[0] + if user.get("can_post") == True: + user_str = self.session.get_user(user["id"], key="user1") + title = _("Post to {user1_nom}'s wall").format(**user_str) + p = presenters.createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=title, message="", text="")) + if hasattr(p, "text") or hasattr(p, "privacy"): + post_arguments=dict(privacy=p.privacy, message=p.text, owner_id=user["id"]) + attachments = [] + if hasattr(p, "attachments"): + attachments = p.attachments + call_threaded(pub.sendMessage, "post", parent_endpoint="wall", child_endpoint="post", from_buffer=self.name, attachments_list=attachments, post_arguments=post_arguments) - def create_tab(self, parent): - self.tab = people.peopleTab(parent) - self.connect_events() - self.tab.name = self.name - if hasattr(self, "can_post") and self.can_post == False and hasattr(self.tab, "post"): - self.tab.post.Enable(False) + def create_tab(self, parent): + self.tab = people.peopleTab(parent) + self.connect_events() + self.tab.name = self.name + if hasattr(self, "can_post") and self.can_post == False and hasattr(self.tab, "post"): + self.tab.post.Enable(False) - def connect_events(self): - super(peopleBuffer, self).connect_events() - widgetUtils.connect_event(self.tab.new_chat, widgetUtils.BUTTON_PRESSED, self.new_chat) + def connect_events(self): + super(peopleBuffer, self).connect_events() + widgetUtils.connect_event(self.tab.new_chat, widgetUtils.BUTTON_PRESSED, self.new_chat) - def new_chat(self, *args, **kwargs): - user = self.get_post() - if user == None: - return - user_id = user["id"] - pub.sendMessage("new-chat", user_id=user_id) + def new_chat(self, *args, **kwargs): + user = self.get_post() + if user == None: + return + user_id = user["id"] + pub.sendMessage("new-chat", user_id=user_id) - def onFocus(self, *args, **kwargs): - post = self.get_post() - if post == None: - return - if post.get("can_post") == True: - self.tab.post.Enable(True) - else: - self.tab.post.Enable(False) - # Check if we are allowed to contact people. this might be false for communitiy members. - if post.get("can_write_private_message") == True: - self.tab.new_chat.Enable(True) - else: - self.tab.new_chat.Enable(False) - if ("last_seen" in post) == False: return - original_date = arrow.get(post["last_seen"]["time"]) - now = arrow.now() - original_date.to(now.tzinfo) - diffdate = now-original_date - if diffdate.days == 0 and diffdate.seconds <= 360: - online_status = _("Online") - else: - # Translators: This is the date of last seen - online_status = _("Last seen {0}").format(original_date.humanize(locale=languageHandler.curLang[:2]),) - self.tab.list.list.SetItem(self.tab.list.get_selected(), 1, online_status) + def onFocus(self, *args, **kwargs): + post = self.get_post() + if post == None: + return + if post.get("can_post") == True: + self.tab.post.Enable(True) + else: + self.tab.post.Enable(False) + # Check if we are allowed to contact people. this might be false for communitiy members. + if post.get("can_write_private_message") == True: + self.tab.new_chat.Enable(True) + else: + self.tab.new_chat.Enable(False) + if ("last_seen" in post) == False: return + original_date = arrow.get(post["last_seen"]["time"]) + now = arrow.now() + original_date.to(now.tzinfo) + diffdate = now-original_date + if diffdate.days == 0 and diffdate.seconds <= 360: + online_status = _("Online") + else: + # Translators: This is the date of last seen + online_status = _("Last seen {0}").format(original_date.humanize(locale=languageHandler.curLang[:2]),) + self.tab.list.list.SetItem(self.tab.list.get_selected(), 1, online_status) - def open_timeline(self, *args, **kwargs): - user = self.get_post() - if user == None: - return - a = timeline.timelineDialog([self.session.get_user(user["id"])["user1_gen"]], show_selector=False) - if a.get_response() == widgetUtils.OK: - buffer_type = a.get_buffer_type() - user_id = user["id"] - pub.sendMessage("create-timeline", user_id=user_id, buffer_type=buffer_type) + def open_timeline(self, *args, **kwargs): + user = self.get_post() + if user == None: + return + a = timeline.timelineDialog([self.session.get_user(user["id"])["user1_gen"]], show_selector=False) + if a.get_response() == widgetUtils.OK: + buffer_type = a.get_buffer_type() + user_id = user["id"] + pub.sendMessage("create-timeline", user_id=user_id, buffer_type=buffer_type) - def get_menu(self, *args, **kwargs): - """ display menu for people buffers (friends and requests)""" - # If this is an incoming requests buffer, there is a flag in the peopleMenu that shows a few new options. - # So let's make sure we call it accordingly. - if self.name == "friend_requests": - m = menus.peopleMenu(is_request=True) - # Connect the accept and decline methods from here. - widgetUtils.connect_event(m, widgetUtils.MENU, self.accept_friendship, menuitem=m.accept) - widgetUtils.connect_event(m, widgetUtils.MENU, self.decline_friendship, menuitem=m.decline) - widgetUtils.connect_event(m, widgetUtils.MENU, self.keep_as_follower, menuitem=m.keep_as_follower) - elif self.name == "subscribers": - m = menus.peopleMenu(is_subscriber=True) - widgetUtils.connect_event(m, widgetUtils.MENU, self.accept_friendship, menuitem=m.add) - else: - m = menus.peopleMenu(is_request=False) - widgetUtils.connect_event(m, widgetUtils.MENU, self.decline_friendship, menuitem=m.decline) - widgetUtils.connect_event(m, widgetUtils.MENU, self.block_person, menuitem=m.block) - # It is not allowed to send messages to people who is not your friends, so let's disable it if we're in a pending or outgoing requests buffer. - if "friend_requests" in self.name: - m.message.Enable(False) - widgetUtils.connect_event(m, widgetUtils.MENU, self.new_chat, menuitem=m.message) - widgetUtils.connect_event(m, widgetUtils.MENU, self.open_timeline, menuitem=m.timeline) - widgetUtils.connect_event(m, widgetUtils.MENU, self.open_person_profile, menuitem=m.view_profile) - widgetUtils.connect_event(m, widgetUtils.MENU, self.open_in_browser, menuitem=m.open_in_browser) - return m + def get_menu(self, *args, **kwargs): + """ display menu for people buffers (friends and requests)""" + # If this is an incoming requests buffer, there is a flag in the peopleMenu that shows a few new options. + # So let's make sure we call it accordingly. + if self.name == "friend_requests": + m = menus.peopleMenu(is_request=True) + # Connect the accept and decline methods from here. + widgetUtils.connect_event(m, widgetUtils.MENU, self.accept_friendship, menuitem=m.accept) + widgetUtils.connect_event(m, widgetUtils.MENU, self.decline_friendship, menuitem=m.decline) + widgetUtils.connect_event(m, widgetUtils.MENU, self.keep_as_follower, menuitem=m.keep_as_follower) + elif self.name == "subscribers": + m = menus.peopleMenu(is_subscriber=True) + widgetUtils.connect_event(m, widgetUtils.MENU, self.accept_friendship, menuitem=m.add) + else: + m = menus.peopleMenu(is_request=False) + widgetUtils.connect_event(m, widgetUtils.MENU, self.decline_friendship, menuitem=m.decline) + widgetUtils.connect_event(m, widgetUtils.MENU, self.block_person, menuitem=m.block) + # It is not allowed to send messages to people who is not your friends, so let's disable it if we're in a pending or outgoing requests buffer. + if "friend_requests" in self.name: + m.message.Enable(False) + widgetUtils.connect_event(m, widgetUtils.MENU, self.new_chat, menuitem=m.message) + widgetUtils.connect_event(m, widgetUtils.MENU, self.open_timeline, menuitem=m.timeline) + widgetUtils.connect_event(m, widgetUtils.MENU, self.open_person_profile, menuitem=m.view_profile) + widgetUtils.connect_event(m, widgetUtils.MENU, self.open_in_browser, menuitem=m.open_in_browser) + return m - def open_post(self, *args, **kwargs): pass + def open_post(self, *args, **kwargs): pass - def play_audio(self, *args, **kwargs): return False + def play_audio(self, *args, **kwargs): return False - def pause_audio(self, *args, **kwargs): pass + def pause_audio(self, *args, **kwargs): pass - def accept_friendship(self, *args, **kwargs): - pass + def accept_friendship(self, *args, **kwargs): + pass - def decline_friendship(self, *args, **kwargs): - person = self.get_post() - if person == None: - return - user = self.session.get_user(person["id"]) - question = commonMessages.remove_friend(user) - if question == widgetUtils.NO: - return - result = self.session.vk.client.friends.delete(user_id=person["id"]) - if "friend_deleted" in result: - msg = _("You've removed {user1_nom} from your friends.").format(**user,) - pub.sendMessage("notify", message=msg) - self.session.db[self.name]["items"].pop(self.tab.list.get_selected()) - self.tab.list.remove_item(self.tab.list.get_selected()) + def decline_friendship(self, *args, **kwargs): + person = self.get_post() + if person == None: + return + user = self.session.get_user(person["id"]) + question = commonMessages.remove_friend(user) + if question == widgetUtils.NO: + return + result = self.session.vk.client.friends.delete(user_id=person["id"]) + if "friend_deleted" in result: + msg = _("You've removed {user1_nom} from your friends.").format(**user,) + pub.sendMessage("notify", message=msg) + self.session.db[self.name]["items"].pop(self.tab.list.get_selected()) + self.tab.list.remove_item(self.tab.list.get_selected()) - def block_person(self, *args, **kwargs): - person = self.get_post() - if person == None: - return - user = self.session.get_user(person["id"]) - question = commonMessages.block_person(user) - if question == widgetUtils.NO: - return - result = self.session.vk.client.account.ban(owner_id=person["id"]) - if result == 1: - msg = _("You've blocked {user1_nom} from your friends.").format(**user,) - pub.sendMessage("notify", message=msg) - self.session.db[self.name]["items"].pop(self.tab.list.get_selected()) - self.tab.list.remove_item(self.tab.list.get_selected()) + def block_person(self, *args, **kwargs): + person = self.get_post() + if person == None: + return + user = self.session.get_user(person["id"]) + question = commonMessages.block_person(user) + if question == widgetUtils.NO: + return + result = self.session.vk.client.account.ban(owner_id=person["id"]) + if result == 1: + msg = _("You've blocked {user1_nom} from your friends.").format(**user,) + pub.sendMessage("notify", message=msg) + self.session.db[self.name]["items"].pop(self.tab.list.get_selected()) + self.tab.list.remove_item(self.tab.list.get_selected()) - def keep_as_follower(self, *args, **kwargs): - pass + def keep_as_follower(self, *args, **kwargs): + pass - def add_person(self, person): - # This tracks if the user already exists here, in such case we just will update the last_seen variable - existing = False - for i in self.session.db[self.name]["items"]: - if person["id"] == i["id"]: - existing = True - i["last_seen"]["time"] = person["last_seen"]["time"] - break - # Add the new user to the buffer just if it does not exists previously. - if existing == False: - # Ensure the user won't loose the focus after the new item is added. - focused_item = self.tab.list.get_selected()+1 - self.session.db[self.name]["items"].insert(0, person) - self.insert(person, True) - # Selects back the previously focused item. - self.tab.list.select_item(focused_item) + def add_person(self, person): + # This tracks if the user already exists here, in such case we just will update the last_seen variable + existing = False + for i in self.session.db[self.name]["items"]: + if person["id"] == i["id"]: + existing = True + i["last_seen"]["time"] = person["last_seen"]["time"] + break + # Add the new user to the buffer just if it does not exists previously. + if existing == False: + # Ensure the user won't loose the focus after the new item is added. + focused_item = self.tab.list.get_selected()+1 + self.session.db[self.name]["items"].insert(0, person) + self.insert(person, True) + # Selects back the previously focused item. + self.tab.list.select_item(focused_item) - def remove_person(self, user_id): - # Make sure the user is present in the buffer, otherwise don't attempt to remove a None Value from the list. - user = None - focused_user = self.get_post() - for i in self.session.db[self.name]["items"]: - if i["id"] == user_id: - user = i - break - if user != None: - person_index = self.session.db[self.name]["items"].index(user) - focused_item = self.tab.list.get_selected() - self.session.db[self.name]["items"].pop(person_index) - self.tab.list.remove_item(person_index) - if user != focused_user: - # Let's find the position of the previously focused user. - focus = None - for i in range(0, len(self.session.db[self.name]["items"])): - if focused_user["id"] == self.session.db[self.name]["items"][i]["id"]: - self.tab.list.select_item(i) - return - elif user == focused_user and person_index < self.tab.list.get_count(): - self.tab.list.select_item(person_index) - else: - self.tab.list.select_item(self.tab.list.get_count()-1) + def remove_person(self, user_id): + # Make sure the user is present in the buffer, otherwise don't attempt to remove a None Value from the list. + user = None + focused_user = self.get_post() + for i in self.session.db[self.name]["items"]: + if i["id"] == user_id: + user = i + break + if user != None: + person_index = self.session.db[self.name]["items"].index(user) + focused_item = self.tab.list.get_selected() + self.session.db[self.name]["items"].pop(person_index) + self.tab.list.remove_item(person_index) + if user != focused_user: + # Let's find the position of the previously focused user. + focus = None + for i in range(0, len(self.session.db[self.name]["items"])): + if focused_user["id"] == self.session.db[self.name]["items"][i]["id"]: + self.tab.list.select_item(i) + return + elif user == focused_user and person_index < self.tab.list.get_count(): + self.tab.list.select_item(person_index) + else: + self.tab.list.select_item(self.tab.list.get_count()-1) - def get_friend(self, user_id): - for i in self.session.db["friends_"]["items"]: - if i["id"] == user_id: - return i - log.exception("Getting user manually...") - user = self.session.vk.client.users.get(user_ids=event.user_id, fields="last_seen")[0] - return user + def get_friend(self, user_id): + for i in self.session.db["friends_"]["items"]: + if i["id"] == user_id: + return i + log.exception("Getting user manually...") + user = self.session.vk.client.users.get(user_ids=event.user_id, fields="last_seen")[0] + return user - def update_online(self): - online_users = self.session.vk.client.friends.getOnline() - now = time.time() - for i in self.session.db[self.name]["items"]: - if i["id"] in online_users: - i["last_seen"]["time"] = now - else: - log.exception("Removing an user from online status manually... %r" % (i)) - self.remove_person(i["id"]) + def update_online(self): + online_users = self.session.vk.client.friends.getOnline() + now = time.time() + for i in self.session.db[self.name]["items"]: + if i["id"] in online_users: + i["last_seen"]["time"] = now + else: + log.exception("Removing an user from online status manually... %r" % (i)) + self.remove_person(i["id"]) - def open_in_browser(self, *args, **kwargs): - post = self.get_post() - if post == None: - return - url = "https://vk.com/id{user_id}".format(user_id=post["id"]) - webbrowser.open_new_tab(url) \ No newline at end of file + def open_in_browser(self, *args, **kwargs): + post = self.get_post() + if post == None: + return + url = "https://vk.com/id{user_id}".format(user_id=post["id"]) + webbrowser.open_new_tab(url) diff --git a/src/controller/buffers/video.py b/src/controller/buffers/video.py index d227b99..35f085c 100644 --- a/src/controller/buffers/video.py +++ b/src/controller/buffers/video.py @@ -12,114 +12,114 @@ from .wall import wallBuffer log = logging.getLogger("controller.buffers.video") class videoBuffer(wallBuffer): - """ This buffer represents video elements, and it can be used for showing videos for the logged user or someone else.""" + """ This buffer represents video elements, and it can be used for showing videos for the logged user or someone else.""" - def create_tab(self, parent): - self.tab = video.videoTab(parent) - self.connect_events() - self.tab.name = self.name - if hasattr(self, "can_post") and self.can_post == False and hasattr(self.tab, "post"): - self.tab.post.Enable(False) + def create_tab(self, parent): + self.tab = video.videoTab(parent) + self.connect_events() + self.tab.name = self.name + if hasattr(self, "can_post") and self.can_post == False and hasattr(self.tab, "post"): + self.tab.post.Enable(False) - def connect_events(self): - widgetUtils.connect_event(self.tab.play, widgetUtils.BUTTON_PRESSED, self.play_audio) - super(videoBuffer, self).connect_events() + def connect_events(self): + widgetUtils.connect_event(self.tab.play, widgetUtils.BUTTON_PRESSED, self.play_audio) + super(videoBuffer, self).connect_events() - def play_audio(self, *args, **kwargs): - """ Due to inheritance this method should be called play_audio, but play the currently focused video. - Opens a webbrowser pointing to the video's URL.""" - selected = self.tab.list.get_selected() - if self.tab.list.get_count() == 0: - return - if selected == -1: - selected = 0 - output.speak(_("Opening video in webbrowser...")) - webbrowser.open_new_tab(self.session.db[self.name]["items"][selected]["player"]) -# print self.session.db[self.name]["items"][selected] - return True + def play_audio(self, *args, **kwargs): + """ Due to inheritance this method should be called play_audio, but play the currently focused video. + Opens a webbrowser pointing to the video's URL.""" + selected = self.tab.list.get_selected() + if self.tab.list.get_count() == 0: + return + if selected == -1: + selected = 0 + output.speak(_("Opening video in webbrowser...")) + webbrowser.open_new_tab(self.session.db[self.name]["items"][selected]["player"]) +# print self.session.db[self.name]["items"][selected] + return True - def open_post(self, *args, **kwargs): - pass + def open_post(self, *args, **kwargs): + pass - def remove_buffer(self, mandatory=False): - if "me_video" == self.name: - output.speak(_("This buffer can't be deleted")) - return False - else: - if mandatory == False: - dlg = commonMessages.remove_buffer() - else: - dlg = widgetUtils.YES - if dlg == widgetUtils.YES: - self.session.db.pop(self.name) - return True - else: - return False + def remove_buffer(self, mandatory=False): + if "me_video" == self.name: + output.speak(_("This buffer can't be deleted")) + return False + else: + if mandatory == False: + dlg = commonMessages.remove_buffer() + else: + dlg = widgetUtils.YES + if dlg == widgetUtils.YES: + self.session.db.pop(self.name) + return True + else: + return False - def get_more_items(self, *args, **kwargs): - # Translators: Some buffers can't use the get previous item feature due to API limitations. - output.speak(_("This buffer doesn't support getting more items.")) + def get_more_items(self, *args, **kwargs): + # Translators: Some buffers can't use the get previous item feature due to API limitations. + output.speak(_("This buffer doesn't support getting more items.")) - def onFocus(self, event, *args, **kwargs): - event.Skip() + def onFocus(self, event, *args, **kwargs): + event.Skip() - def add_to_library(self, *args, **kwargs): - post = self.get_post() - if post == None: - return - args = {} - args["video_id"] = post["id"] - if "album_id" in post: - args["album_id"] = post["album_id"] - args["owner_id"] = post["owner_id"] - video = self.session.vk.client.video.add(**args) - if video != None and int(video) > 21: - output.speak(_("Video added to your library")) + def add_to_library(self, *args, **kwargs): + post = self.get_post() + if post == None: + return + args = {} + args["video_id"] = post["id"] + if "album_id" in post: + args["album_id"] = post["album_id"] + args["owner_id"] = post["owner_id"] + video = self.session.vk.client.video.add(**args) + if video != None and int(video) > 21: + output.speak(_("Video added to your library")) - def remove_from_library(self, *args, **kwargs): - post = self.get_post() - if post == None: - return - args = {} - args["video_id"] = post["id"] - args["owner_id"] = self.session.user_id - result = self.session.vk.client.video.delete(**args) - if int(result) == 1: - output.speak(_("Removed video from library")) - self.tab.list.remove_item(self.tab.list.get_selected()) + def remove_from_library(self, *args, **kwargs): + post = self.get_post() + if post == None: + return + args = {} + args["video_id"] = post["id"] + args["owner_id"] = self.session.user_id + result = self.session.vk.client.video.delete(**args) + if int(result) == 1: + output.speak(_("Removed video from library")) + self.tab.list.remove_item(self.tab.list.get_selected()) - def move_to_album(self, *args, **kwargs): - if len(self.session.video_albums) == 0: - return commonMessages.no_video_albums() - post= self.get_post() - if post == None: - return - album = selector.album(_("Select the album where you want to move this video"), self.session, "video_albums") - if album.item == None: return - id = post["id"] - response = self.session.vk.client.video.addToAlbum(album_ids=album.item, video_id=id, target_id=self.session.user_id, owner_id=self.get_post()["owner_id"]) - if response == 1: - # Translators: Used when the user has moved an video to an album. - output.speak(_("Moved")) + def move_to_album(self, *args, **kwargs): + if len(self.session.video_albums) == 0: + return commonMessages.no_video_albums() + post= self.get_post() + if post == None: + return + album = selector.album(_("Select the album where you want to move this video"), self.session, "video_albums") + if album.item == None: return + id = post["id"] + response = self.session.vk.client.video.addToAlbum(album_ids=album.item, video_id=id, target_id=self.session.user_id, owner_id=self.get_post()["owner_id"]) + if response == 1: + # Translators: Used when the user has moved an video to an album. + output.speak(_("Moved")) - def get_menu(self): - """ We'll use the same menu that is used for audio items, as the options are exactly the same""" - p = self.get_post() - if p == None: - return - m = menus.audioMenu() - widgetUtils.connect_event(m, widgetUtils.MENU, self.move_to_album, menuitem=m.move) - # if owner_id is the current user, the audio is added to the user's audios. - if p["owner_id"] == self.session.user_id: - m.library.SetItemLabel(_("&Remove")) - widgetUtils.connect_event(m, widgetUtils.MENU, self.remove_from_library, menuitem=m.library) - else: - widgetUtils.connect_event(m, widgetUtils.MENU, self.add_to_library, menuitem=m.library) - return m + def get_menu(self): + """ We'll use the same menu that is used for audio items, as the options are exactly the same""" + p = self.get_post() + if p == None: + return + m = menus.audioMenu() + widgetUtils.connect_event(m, widgetUtils.MENU, self.move_to_album, menuitem=m.move) + # if owner_id is the current user, the audio is added to the user's audios. + if p["owner_id"] == self.session.user_id: + m.library.SetItemLabel(_("&Remove")) + widgetUtils.connect_event(m, widgetUtils.MENU, self.remove_from_library, menuitem=m.library) + else: + widgetUtils.connect_event(m, widgetUtils.MENU, self.add_to_library, menuitem=m.library) + return m - def open_in_browser(self, *args, **kwargs): - post = self.get_post() - if post == None: - return - url = "https://vk.com/video{user_id}_{video_id}".format(user_id=post["owner_id"], video_id=post["id"]) - webbrowser.open_new_tab(url) \ No newline at end of file + def open_in_browser(self, *args, **kwargs): + post = self.get_post() + if post == None: + return + url = "https://vk.com/video{user_id}_{video_id}".format(user_id=post["owner_id"], video_id=post["id"]) + webbrowser.open_new_tab(url) diff --git a/src/controller/buffers/videoAlbum.py b/src/controller/buffers/videoAlbum.py index 2297eec..370dc3b 100644 --- a/src/controller/buffers/videoAlbum.py +++ b/src/controller/buffers/videoAlbum.py @@ -10,21 +10,21 @@ log = logging.getLogger("controller.buffers") class videoAlbumBuffer(videoBuffer): - def create_tab(self, parent): - self.tab = video.videoAlbumTab(parent) - self.tab.play.Enable(False) - self.connect_events() - self.tab.name = self.name - if hasattr(self, "can_post") and self.can_post == False and hasattr(self.tab, "post"): - self.tab.post.Enable(False) + def create_tab(self, parent): + self.tab = video.videoAlbumTab(parent) + self.tab.play.Enable(False) + self.connect_events() + self.tab.name = self.name + if hasattr(self, "can_post") and self.can_post == False and hasattr(self.tab, "post"): + self.tab.post.Enable(False) - def connect_events(self): - super(videoAlbumBuffer, self).connect_events() - widgetUtils.connect_event(self.tab.load, widgetUtils.BUTTON_PRESSED, self.load_album) + def connect_events(self): + super(videoAlbumBuffer, self).connect_events() + widgetUtils.connect_event(self.tab.load, widgetUtils.BUTTON_PRESSED, self.load_album) - def load_album(self, *args, **kwargs): - output.speak(_("Loading album...")) - self.can_get_items = True - self.tab.load.Enable(False) - wx.CallAfter(self.get_items) - self.tab.play.Enable(True) \ No newline at end of file + def load_album(self, *args, **kwargs): + output.speak(_("Loading album...")) + self.can_get_items = True + self.tab.load.Enable(False) + wx.CallAfter(self.get_items) + self.tab.play.Enable(True) diff --git a/src/controller/buffers/wall.py b/src/controller/buffers/wall.py index 2715cad..2d5d27c 100644 --- a/src/controller/buffers/wall.py +++ b/src/controller/buffers/wall.py @@ -17,88 +17,88 @@ from .home import homeBuffer log = logging.getLogger("controller.buffers.wall") class wallBuffer(homeBuffer): - """ This buffer represents an user's wall. It may be used either for the current user or someone else.""" + """ This buffer represents an user's wall. It may be used either for the current user or someone else.""" - def get_items(self, show_nextpage=False): - """ Update buffer with newest items or get older items in the buffer.""" - if self.can_get_items == False: return - retrieved = True - try: - num = getattr(self.session, "get_page")(show_nextpage=show_nextpage, name=self.name, *self.args, **self.kwargs) - except VkApiError as err: - log.error("Error {0}: {1}".format(err.code, err.error)) - retrieved = err.code - return retrieved - except: - log.exception("Connection error when updating buffer %s. Will try again in 2 minutes" % (self.name,)) - return False - if not hasattr(self, "tab"): - # Create GUI associated to this buffer. - self.create_tab(self.parent) - # Add name to the new control so we could look for it when needed. - self.tab.name = self.name - if show_nextpage == False: - if self.tab.list.get_count() > 0 and num > 0: - v = [i for i in self.session.db[self.name]["items"][:num]] - v.reverse() - [wx.CallAfter(self.insert, i, True) for i in v] - else: - [wx.CallAfter(self.insert, i) for i in self.session.db[self.name]["items"][:num]] - else: - if num > 0: - [wx.CallAfter(self.insert, i, False) for i in self.session.db[self.name]["items"][-num:]] - return retrieved + def get_items(self, show_nextpage=False): + """ Update buffer with newest items or get older items in the buffer.""" + if self.can_get_items == False: return + retrieved = True + try: + num = getattr(self.session, "get_page")(show_nextpage=show_nextpage, name=self.name, *self.args, **self.kwargs) + except VkApiError as err: + log.error("Error {0}: {1}".format(err.code, err.error)) + retrieved = err.code + return retrieved + except: + log.exception("Connection error when updating buffer %s. Will try again in 2 minutes" % (self.name,)) + return False + if not hasattr(self, "tab"): + # Create GUI associated to this buffer. + self.create_tab(self.parent) + # Add name to the new control so we could look for it when needed. + self.tab.name = self.name + if show_nextpage == False: + if self.tab.list.get_count() > 0 and num > 0: + v = [i for i in self.session.db[self.name]["items"][:num]] + v.reverse() + [wx.CallAfter(self.insert, i, True) for i in v] + else: + [wx.CallAfter(self.insert, i) for i in self.session.db[self.name]["items"][:num]] + else: + if num > 0: + [wx.CallAfter(self.insert, i, False) for i in self.session.db[self.name]["items"][-num:]] + return retrieved - def remove_buffer(self, mandatory=False): - """ Remove buffer if the current buffer is not the logged user's wall.""" - if "me_feed" == self.name: - output.speak(_("This buffer can't be deleted")) - return False - else: - if mandatory == False: - dlg = commonMessages.remove_buffer() - else: - dlg = widgetUtils.YES - if dlg == widgetUtils.YES: - self.session.db.pop(self.name) - return True - else: - return False + def remove_buffer(self, mandatory=False): + """ Remove buffer if the current buffer is not the logged user's wall.""" + if "me_feed" == self.name: + output.speak(_("This buffer can't be deleted")) + return False + else: + if mandatory == False: + dlg = commonMessages.remove_buffer() + else: + dlg = widgetUtils.YES + if dlg == widgetUtils.YES: + self.session.db.pop(self.name) + return True + else: + return False - def __init__(self, *args, **kwargs): - super(wallBuffer, self).__init__(*args, **kwargs) - self.user_key = "from_id" - self.post_key = "id" - self.can_post = True - self.can_write_private_message = True - # if this is an user timeline we must check permissions to hide buttons when needed. - if "owner_id" in self.kwargs and self.kwargs["owner_id"] > 0 and "feed" in self.name: - permissions = self.session.vk.client.users.get(user_ids=self.kwargs["owner_id"], fields="can_post, can_see_all_posts, can_write_private_message") - self.can_post = permissions[0]["can_post"] - self.can_see_all_posts = permissions[0]["can_see_all_posts"] - self.can_write_private_message = permissions[0]["can_write_private_message"] - log.debug("Checked permissions on buffer {0}, permissions were {1}".format(self.name, permissions)) + def __init__(self, *args, **kwargs): + super(wallBuffer, self).__init__(*args, **kwargs) + self.user_key = "from_id" + self.post_key = "id" + self.can_post = True + self.can_write_private_message = True + # if this is an user timeline we must check permissions to hide buttons when needed. + if "owner_id" in self.kwargs and self.kwargs["owner_id"] > 0 and "feed" in self.name: + permissions = self.session.vk.client.users.get(user_ids=self.kwargs["owner_id"], fields="can_post, can_see_all_posts, can_write_private_message") + self.can_post = permissions[0]["can_post"] + self.can_see_all_posts = permissions[0]["can_see_all_posts"] + self.can_write_private_message = permissions[0]["can_write_private_message"] + log.debug("Checked permissions on buffer {0}, permissions were {1}".format(self.name, permissions)) - def post(self, *args, **kwargs): - """ Create a post in the wall for the specified user - This process is handled in two parts. This is the first part, where the GUI is created and user can send the post. - During the second part (threaded), the post will be sent to the API.""" - if "owner_id" not in self.kwargs: - return super(wallBuffer, self).post() - owner_id = self.kwargs["owner_id"] - user = self.session.get_user(owner_id, key="user1") - title = _("Post to {user1_nom}'s wall").format(**user) - p = presenters.createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=title, message="", text="")) - if hasattr(p, "text") or hasattr(p, "privacy"): - post_arguments=dict(privacy=p.privacy, message=p.text, owner_id=owner_id) - attachments = [] - if hasattr(p, "attachments"): - attachments = p.attachments - call_threaded(pub.sendMessage, "post", parent_endpoint="wall", child_endpoint="post", from_buffer=self.name, attachments_list=attachments, post_arguments=post_arguments) + def post(self, *args, **kwargs): + """ Create a post in the wall for the specified user + This process is handled in two parts. This is the first part, where the GUI is created and user can send the post. + During the second part (threaded), the post will be sent to the API.""" + if "owner_id" not in self.kwargs: + return super(wallBuffer, self).post() + owner_id = self.kwargs["owner_id"] + user = self.session.get_user(owner_id, key="user1") + title = _("Post to {user1_nom}'s wall").format(**user) + p = presenters.createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=title, message="", text="")) + if hasattr(p, "text") or hasattr(p, "privacy"): + post_arguments=dict(privacy=p.privacy, message=p.text, owner_id=owner_id) + attachments = [] + if hasattr(p, "attachments"): + attachments = p.attachments + call_threaded(pub.sendMessage, "post", parent_endpoint="wall", child_endpoint="post", from_buffer=self.name, attachments_list=attachments, post_arguments=post_arguments) - def open_in_browser(self, *args, **kwargs): - post = self.get_post() - if post == None: - return - url = "https://vk.com/wall{user_id}_{post_id}".format(user_id=post["from_id"], post_id=post["id"]) - webbrowser.open_new_tab(url) \ No newline at end of file + def open_in_browser(self, *args, **kwargs): + post = self.get_post() + if post == None: + return + url = "https://vk.com/wall{user_id}_{post_id}".format(user_id=post["from_id"], post_id=post["id"]) + webbrowser.open_new_tab(url) diff --git a/src/controller/mainController.py b/src/controller/mainController.py index fc2d36a..8e7c2a6 100644 --- a/src/controller/mainController.py +++ b/src/controller/mainController.py @@ -38,1115 +38,1115 @@ log = logging.getLogger("controller.main") thread_pool_executor = futures.ThreadPoolExecutor(max_workers=1) def wx_call_after(target): - @functools.wraps(target) - def wrapper(self, *args, **kwargs): - args = (self,) + args - wx.CallAfter(target, *args, **kwargs) - return wrapper + @functools.wraps(target) + def wrapper(self, *args, **kwargs): + args = (self,) + args + wx.CallAfter(target, *args, **kwargs) + return wrapper def submit_to_pool_executor(executor): - def decorator(target): - @functools.wraps(target) - def wrapper(*args, **kwargs): - result = executor.submit(target, *args, **kwargs) - result.add_done_callback(executor_done_call_back) - return result - return wrapper - return decorator + def decorator(target): + @functools.wraps(target) + def wrapper(*args, **kwargs): + result = executor.submit(target, *args, **kwargs) + result.add_done_callback(executor_done_call_back) + return result + return wrapper + return decorator def executor_done_call_back(future): - exception = future.exception() - if exception: - raise exception + exception = future.exception() + if exception: + raise exception class Controller(object): - ### utils - # Important utility functions for the program which are not used directly by anyone. - def search(self, tab_name): - """ Search a buffer by name. Name should be the buffer.name argument. - returns a buffer object matching the pased name or None name.""" - for i in range(0, len(self.buffers)): - if self.buffers[i].name == tab_name: - return self.buffers[i] - return False - - def get_current_buffer(self): - """ Get the current bufferObject""" - buffer = self.window.get_current_buffer() - if hasattr(buffer, "name"): - buffer = self.search(buffer.name) - return buffer - - def get_all_buffers(self, contains): - """ Get all buffers containing the name passed as the only parameter. Similar to search, but this method returns a list with all buffers found. """ - results = [] - for i in self.buffers: - if contains in i.name: - results.append(i) - return results - - def __init__(self): - super(Controller, self).__init__() - log.debug("Starting main controller...") - self.buffers = [] - player.setup() - self.window = mainWindow.mainWindow() - log.debug("Main window created") - wx.CallAfter(self.window.change_status, _("Ready")) - self.session = session.sessions[list(session.sessions.keys())[0]] - self.window.Show() - self.connect_pubsub_events() - self.connect_gui_events() - self.create_controls() - call_threaded(updater.do_update, update_type=self.session.settings["general"]["update_channel"]) - - def is_focused(self): - """ Return True if the Socializer Window is Focused. """ - app_title = "socializer" - window_title = win32gui.GetWindowText(win32gui.GetForegroundWindow()).lower() - if app_title == window_title: - return True - return False - - ### action function - # These functions are called by other parts of the program, and are not connected to any event at all. - def create_controls(self): - """ Create all buffers for Socializer.""" - log.debug("Creating controls for the window...") - pub.sendMessage("create_buffer", buffer_type="emptyBuffer", buffer_title=_("Posts"), kwargs=dict(parent=self.window.tb, name="posts")) - pub.sendMessage("create_buffer", buffer_type="baseBuffer", buffer_title=_("Home"), parent_tab="posts", kwargs=dict(parent=self.window.tb, name="home_timeline", session=self.session, composefunc="render_newsfeed_item", endpoint="newsfeed", count=self.session.settings["buffers"]["count_for_wall_buffers"])) - pub.sendMessage("create_buffer", buffer_type="feedBuffer", buffer_title=_("My wall"), parent_tab="posts", kwargs=dict(parent=self.window.tb, name="me_feed", composefunc="render_status", session=self.session, endpoint="get", parent_endpoint="wall", extended=1, count=self.session.settings["buffers"]["count_for_wall_buffers"])) - pub.sendMessage("create_buffer", buffer_type="emptyBuffer", buffer_title=_("Music"), kwargs=dict(parent=self.window.tb, name="audios")) - pub.sendMessage("create_buffer", buffer_type="audioBuffer", buffer_title=_("My audios"), parent_tab="audios", kwargs=dict(parent=self.window.tb, name="me_audio", composefunc="render_audio", session=self.session, endpoint="get", parent_endpoint="audio")) - if self.session.settings["vk"]["use_alternative_tokens"] == False: - pub.sendMessage("create_buffer", buffer_type="audioBuffer", buffer_title=_("Populars"), parent_tab="audios", kwargs=dict(parent=self.window.tb, name="popular_audio", composefunc="render_audio", session=self.session, endpoint="getPopular", parent_endpoint="audio", full_list=True, count=self.session.settings["buffers"]["count_for_audio_buffers"])) - pub.sendMessage("create_buffer", buffer_type="audioBuffer", buffer_title=_("Recommendations"), parent_tab="audios", kwargs=dict(parent=self.window.tb, name="recommended_audio", composefunc="render_audio", session=self.session, endpoint="getRecommendations", parent_endpoint="audio", full_list=True, count=self.session.settings["buffers"]["count_for_audio_buffers"])) - pub.sendMessage("create_buffer", buffer_type="emptyBuffer", buffer_title=_("Albums"), parent_tab="audios", kwargs=dict(parent=self.window.tb, name="audio_albums")) - pub.sendMessage("create_buffer", buffer_type="emptyBuffer", buffer_title=_("Video"), kwargs=dict(parent=self.window.tb, name="videos")) - pub.sendMessage("create_buffer", buffer_type="videoBuffer", buffer_title=_("My videos"), parent_tab="videos", kwargs=dict(parent=self.window.tb, name="me_video", composefunc="render_video", session=self.session, endpoint="get", parent_endpoint="video", count=self.session.settings["buffers"]["count_for_video_buffers"])) - pub.sendMessage("create_buffer", buffer_type="emptyBuffer", buffer_title=_("Albums"), parent_tab="videos", kwargs=dict(parent=self.window.tb, name="video_albums")) - pub.sendMessage("create_buffer", buffer_type="emptyBuffer", buffer_title=_("People"), kwargs=dict(parent=self.window.tb, name="people")) - pub.sendMessage("create_buffer", buffer_type="peopleBuffer", buffer_title=_("Online"), parent_tab="people", kwargs=dict(parent=self.window.tb, name="online_friends", composefunc="render_person", session=self.session, endpoint="getOnline", parent_endpoint="friends", count=5000, order="hints", fields="uid, first_name, last_name, last_seen, can_post, can_write_private_message")) - pub.sendMessage("create_buffer", buffer_type="peopleBuffer", buffer_title=_("All friends"), parent_tab="people", kwargs=dict(parent=self.window.tb, name="friends_", composefunc="render_person", session=self.session, endpoint="get", parent_endpoint="friends", count=5000, order="hints", fields="uid, first_name, last_name, last_seen, can_post, can_write_private_message")) - pub.sendMessage("create_buffer", buffer_type="emptyBuffer", buffer_title=_("Friendship requests"), parent_tab="people", kwargs=dict(parent=self.window.tb, name="requests")) - pub.sendMessage("create_buffer", buffer_type="requestsBuffer", buffer_title=_("Pending requests"), parent_tab="requests", kwargs=dict(parent=self.window.tb, name="friend_requests", composefunc="render_person", session=self.session, count=1000, fields="can_post, can_write_private_message")) - pub.sendMessage("create_buffer", buffer_type="requestsBuffer", buffer_title=_("I follow"), parent_tab="requests", kwargs=dict(parent=self.window.tb, name="friend_requests_sent", composefunc="render_person", session=self.session, count=1000, out=1, fields="can_post, can_write_private_message")) - pub.sendMessage("create_buffer", buffer_type="requestsBuffer", buffer_title=_("Subscribers"), parent_tab="requests", kwargs=dict(parent=self.window.tb, name="subscribers", composefunc="render_person", session=self.session, count=1000, need_viewed=1, fields="can_post, can_write_private_message")) -# pub.sendMessage("create_buffer", buffer_type="notificationBuffer", buffer_title=_("Notifications"), parent_tab=None, loadable=False, kwargs=dict(parent=self.window.tb, name="notifications", composefunc="render_notification", session=self.session, endpoint="get", parent_endpoint="notifications", count=100, filters="wall,mentions,comments,likes,reposted,followers,friends")) - pub.sendMessage("create_buffer", buffer_type="documentBuffer", buffer_title=_("Documents"), parent_tab=None, loadable=True, kwargs=dict(parent=self.window.tb, name="documents", composefunc="render_document", session=self.session, endpoint="get", parent_endpoint="docs")) - pub.sendMessage("create_buffer", buffer_type="emptyBuffer", buffer_title=_("Groups"), kwargs=dict(parent=self.window.tb, name="communities")) - pub.sendMessage("create_buffer", buffer_type="emptyBuffer", buffer_title=_("Chats"), kwargs=dict(parent=self.window.tb, name="chats")) - pub.sendMessage("create_buffer", buffer_type="emptyBuffer", buffer_title=_("Timelines"), kwargs=dict(parent=self.window.tb, name="timelines")) - wx.CallAfter(self.window.realize) - self.repeatedUpdate = RepeatingTimer(120, self.update_all_buffers) - self.repeatedUpdate.start() - - def complete_buffer_creation(self, buffer, name_, position): - answer = buffer.get_items() - if answer is not True: - commonMessages.show_error_code(answer) - return - self.buffers.append(buffer) - self.window.insert_buffer(buffer.tab, name_, position) - - def search_chat_buffer(self, user_id): - for i in self.buffers: - if "_messages" in i.name: - if "peer_id" in i.kwargs and i.kwargs["peer_id"] == user_id: return i - return None - - def set_online(self, notify=False): - try: - r = self.session.vk.client.account.setOnline() - except: - log.error("Error in setting online for the current user") - if notify: - self.window.notify("Socializer", "online now!") - - def set_offline(self): - try: - r = self.session.vk.client.account.setOffline() - except: - log.error("Error in setting offline status for the current user") - - def create_unread_messages(self): - try: - log.debug("Creating conversation buffers...") - msgs = self.session.vk.client.messages.getConversations(count=200, filter="all") - log.debug("Total conversations count: {}".format(msgs.get("count"))) - log.debug("total conversations returned by VK: {}".format(len(msgs["items"]))) - log.debug("Dictionary keys of conversations object: {}".format(msgs.keys())) - except VkApiError as ex: - if ex.code == 6: - log.exception("Something went wrong when getting messages. Waiting a second to retry") - log.debug("Creating buffer conversation for {} buffers".format(len(msgs["items"]))) - for i in msgs["items"]: - log.debug("Creating chat buffer for peer_id {}".format(i["last_message"]["peer_id"])) - self.chat_from_id(i["last_message"]["peer_id"], setfocus=False, unread=False) - - def get_audio_albums(self, user_id=None, create_buffers=True, force_action=False): - if self.session.settings["load_at_startup"]["audio_albums"] == False and force_action == False: - return - log.debug("Create audio albums...") - if self.session.settings["vk"]["use_alternative_tokens"]: - albums = self.session.vk.client_audio.get_albums(owner_id=user_id) - else: - albums = self.session.vk.client.audio.getPlaylists(owner_id=user_id, count=100) - albums = albums["items"] - self.session.audio_albums = albums - if create_buffers: - for i in albums: - pub.sendMessage("create_buffer", buffer_type="audioAlbum", buffer_title=_("Album: {0}").format(i["title"],), parent_tab="audio_albums", loadable=True, kwargs=dict(parent=self.window.tb, name="{0}_audio_album".format(i["id"],), composefunc="render_audio", session=self.session, endpoint="get", parent_endpoint="audio", owner_id=user_id, album_id=i["id"])) - - def get_video_albums(self, user_id=None, create_buffers=True, force_action=False): - if self.session.settings["load_at_startup"]["video_albums"] == False and force_action == False: - return - log.debug("Create video albums...") - albums = self.session.vk.client.video.getAlbums(owner_id=user_id, count=100) - self.session.video_albums = albums["items"] - if create_buffers: - for i in albums["items"]: - pub.sendMessage("create_buffer", buffer_type="videoAlbum", buffer_title=_("Album: {0}").format(i["title"],), parent_tab="video_albums", loadable=True, kwargs=dict(parent=self.window.tb, name="{0}_video_album".format(i["id"],), composefunc="render_video", session=self.session, endpoint="get", parent_endpoint="video", count=self.session.settings["buffers"]["count_for_video_buffers"], user_id=user_id, album_id=i["id"])) - - def get_communities(self, user_id=None, create_buffers=True, force_action=False): - if self.session.settings["vk"]["invited_to_group"] == False: - self.session.settings["vk"]["invited_to_group"] = True - self.session.settings.write() - socializer_group = self.session.vk.client.groups.getById(group_ids="175825000")[0] - if socializer_group["is_member"] ==False: - d = commonMessages.join_group() - self.session.settings["vk"]["invited_to_group"] = True - self.session.settings.write() - if d == widgetUtils.YES: - result = self.session.vk.client.groups.join(group_id=socializer_group["id"]) - if result == 1: - commonMessages.group_joined() - else: - log.error("Invalid result when joining the Socializer's group: %d" % (result)) - if self.session.settings["load_at_startup"]["communities"] == False and force_action == False: - return - log.debug("Create community buffers...") - groups= self.session.vk.client.groups.get(user_id=user_id, extended=1, count=1000, fields="can_post,can_create_topic") - self.session.groups=groups["items"] - # Let's feed the local database cache with new groups coming from here. - data= dict(profiles=[], groups=self.session.groups) - self.session.process_usernames(data) - if create_buffers: - for i in self.session.groups: - self.session.db["group_info"][i["id"]*-1] = i - pub.sendMessage("create_buffer", buffer_type="communityBuffer", buffer_title=i["name"], parent_tab="communities", loadable=True, get_items=True, kwargs=dict(parent=self.window.tb, name="{0}_community".format(i["id"],), composefunc="render_status", session=self.session, endpoint="get", parent_endpoint="wall", extended=1, count=self.session.settings["buffers"]["count_for_wall_buffers"], owner_id=-1*i["id"])) - - - def login(self): - wx.CallAfter(self.window.change_status, _("Logging in VK")) - self.session.login() - wx.CallAfter(self.window.change_status, _("Ready")) - for i in self.buffers: - if hasattr(i, "get_items"): - # Translators: {0} will be replaced with the name of a buffer. - wx.CallAfter(self.window.change_status, _("Loading items for {0}").format(i.name,)) - i.get_items() - wx.CallAfter(self.window.change_status, _("Ready")) - self.create_unread_messages() - self.status_setter = RepeatingTimer(280, self.set_online) - self.status_setter.start() - self.set_online(notify=True) - self.get_audio_albums(self.session.user_id) - self.get_video_albums(self.session.user_id) - self.get_communities(self.session.user_id) - self.create_longpoll_thread() - - def create_longpoll_thread(self, notify=False): - try: - self.longpoll = longpollthread.worker(self.session) - self.longpoll.start() - if notify: - self.notify(message=_("Chat server reconnected")) - except ConnectionError: - pub.sendMessage("longpoll-read-timeout") - - def update_all_buffers(self): - log.debug("Updating buffers...") - self.get_audio_albums(self.session.user_id, create_buffers=False) - self.get_video_albums(self.session.user_id, create_buffers=False) - for i in self.buffers: - # Online friends buffer should not be updated, as chat LongPoll server already gives status about offline and online friends. - if hasattr(i, "get_items") and i.name != "online_friends": - i.get_items() - log.debug("Updated %s" % (i.name)) - else: - i.update_online() - - def reorder_buffer(self, buffer): - """ this puts the chat buffers at the top of the list when there are new incoming messages. - In order to do so, we search for the current buffer's tab, remove the page from the TreeCtrl (without destroying the associated tab) - and reinsert it as a new child of the chat buffer. - Lastly we ensure the user is focused in the same buffer than before.""" - buffer_window = self.window.search(buffer.name) - # If buffer window is already in the first position after chat, we should not do anything here because calculations for moving buffers are expensive. - if buffer_window == self.window.search("chats")+1: - return - # Gets buffer title so we don't have to generate it again in future. - buffer_title = self.window.get_buffer_text(buffer_window) - # Determine if the current buffer is the buffer receiving a new message. - if buffer == self.get_current_buffer(): - focused_buffer = True - else: - focused_buffer = False - # This call will not destroy the associated tab for the chat buffer, thus allowing us to readd it in other position. - self.window.remove_buffer_from_position(buffer_window) - self.window.insert_chat_buffer(buffer.tab, buffer_title, self.window.search("chats")+1) - # Let's manipulate focus so users will not notice the change in buffers. - if focused_buffer: - new_position = self.window.search(buffer.name) - self.window.change_buffer(new_position) - else: - new_position = self.window.search(self.get_current_buffer().name) - self.window.change_buffer(new_position) - - ### pubsub events - # All of these functions, except the first two, are responses to pubsub events. - def connect_pubsub_events(self): - log.debug("Connecting events to responses...") - pub.subscribe(self.in_post, "posted") - pub.subscribe(self.post_failed, "postFailed") - pub.subscribe(self.download, "download-file") - pub.subscribe(self.download_files, "download-files") - pub.subscribe(self.view_post, "open-post") - pub.subscribe(self.update_status_bar, "update-status-bar") - pub.subscribe(self.chat_from_id, "new-chat") - pub.subscribe(self.authorisation_failed, "authorisation-failed") - pub.subscribe(self.connection_error, "connection_error") - pub.subscribe(self.user_profile, "user-profile") - pub.subscribe(self.user_online, "user-online") - pub.subscribe(self.user_offline, "user-offline") - pub.subscribe(self.notify, "notify") - pub.subscribe(self.handle_longpoll_read_timeout, "longpoll-read-timeout") - pub.subscribe(self.create_buffer, "create_buffer") - pub.subscribe(self.user_typing, "user-typing") - pub.subscribe(self.edit_message, "edit-message") - pub.subscribe(self.get_chat, "order-sent-message") - pub.subscribe(self.create_timeline, "create-timeline") - pub.subscribe(self.api_error, "api-error") - - def disconnect_events(self): - log.debug("Disconnecting some events...") - pub.unsubscribe(self.in_post, "posted") - pub.unsubscribe(self.download, "download-file") - pub.unsubscribe(self.authorisation_failed, "authorisation-failed") - pub.unsubscribe(self.view_post, "open-post") - pub.unsubscribe(self.update_status_bar, "update-status-bar") - pub.unsubscribe(self.user_online, "user-online") - pub.unsubscribe(self.user_offline, "user-offline") - pub.unsubscribe(self.notify, "notify") - pub.subscribe(self.create_timeline, "create-timeline") - - def in_post(self, from_buffer=None): - if from_buffer != None and "_messages" not in from_buffer: - log.debug("Post received in buffer %s, updating... " % (from_buffer,)) - buffer = self.search(from_buffer) - buffer.get_items() - - def post_failed(self, parent_endpoint, child_endpoint, from_buffer=None, attachments_list=[], post_arguments={}): - """ Function to be called when the post (using the pubsub method) fails. It takes the same params than post() and use the parent and child endpoints to call the appropiate dialogs. """ - # Ask the user if he/she wants to attempt to post the same again. - msgdialog = commonMessages.post_failed() - if msgdialog != widgetUtils.YES: # Cancelled. - return - # Let's check which kind of post has failed, and do something about it. - if parent_endpoint == "wall": - if child_endpoint == "post": # A wall post has failed, so let's create it in a dialogue. - p = presenters.createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Write your post"), message="", text=post_arguments.get("message"))) - if hasattr(p, "text") or hasattr(p, "privacy"): - post_arguments.update(privacy=p.privacy, message=p.text) - if hasattr(p, "attachments"): - attachments_list = p.attachments - call_threaded(pub.sendMessage, "post", parent_endpoint=parent_endpoint, child_endpoint=child_endpoint, from_buffer=from_buffer, attachments_list=attachments_list, post_arguments=post_arguments) - elif child_endpoint == "repost": # repost - p = presenters.createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Repost"), message="", text=post_arguments.get("message"), mode="comment")) - if hasattr(p, "text") or hasattr(p, "privacy"): - post_arguments.update(message=p.text) - if hasattr(p, "attachments"): - attachments_list = p.attachments - call_threaded(pub.sendMessage, "post", parent_endpoint=parent_endpoint, child_endpoint=child_endpoint, from_buffer=from_buffer, attachments_list=attachments_list, post_arguments=post_arguments) - elif child_endpoint == "createComment": # comments. - p = presenters.createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Add a comment"), message="", text=post_arguments.get("message"), mode="comment")) - if hasattr(p, "text") or hasattr(p, "privacy"): - post_arguments.update(message=p.text) - if hasattr(p, "attachments"): - attachments_list = p.attachments - call_threaded(pub.sendMessage, "post", parent_endpoint=parent_endpoint, child_endpoint=child_endpoint, from_buffer=from_buffer, attachments_list=attachments_list, post_arguments=post_arguments) - elif parent_endpoint == "board": # topic creation and comments. - if child_endpoint == "addTopic": - p = presenters.createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createTopicDialog(title=_("Create topic"), message="", topic_title=post_arguments.get("title"), text=post_arguments.get("text"))) - if hasattr(p, "text") or hasattr(p, "privacy"): - post_arguments.update(title=p.view.title.GetValue(), text=p.text) - if hasattr(p, "attachments"): - attachments_list = p.attachments - call_threaded(pub.sendMessage, "post", parent_endpoint=parent_endpoint, child_endpoint=child_endpoint, from_buffer=from_buffer, attachments_list=attachments_list, post_arguments=post_arguments) - elif child_endpoint == "createComment": # topic comments. - p = presenters.createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Add a comment to the topic"), message="", text=post_arguments.get("message"), mode="comment")) - if hasattr(p, "text") or hasattr(p, "privacy"): - post_arguments.update(message=p.text) - if hasattr(p, "attachments"): - attachments_list = p.attachments - call_threaded(pub.sendMessage, "post", parent_endpoint=parent_endpoint, child_endpoint=child_endpoint, from_buffer=from_buffer, attachments_list=attachments_list, post_arguments=post_arguments) - elif parent_endpoint == "messages": # Private messages - if child_endpoint == "send": - buffer = self.search(from_buffer) - buffer_window = self.window.search(buffer.name) - self.window.change_buffer(buffer_window) - buffer.tab.text.SetValue(post_arguments.get("message")) - buffer.tab.text.SetFocus() - buffer.attachments_to_be_sent = attachments_list - - def api_error(self, code): - """ Display an understandable error dialog to users. """ - commonMessages.vk_error(code) - - def download(self, url, filename): - """ Download a file to te current user's computer. - @ url: The URl from where the file can be directly accessed. - @ filename: the current path to where the file will be saved. - The dowwload progress will be displayed in the status bar on the window. - """ - url = utils.transform_audio_url(url) - log.debug("downloading %s URL to %s filename" % (url, filename,)) - call_threaded(utils.download_file, url, filename) - - def download_files(self, downloads): - call_threaded(utils.download_files, downloads) - - def view_post(self, post_object, controller_, vars=dict()): - """ Display the passed post in the passed post presenter. - @ post_object dict: A post representation returned by the VK api. The fields present in this dict are different depending on the presenter used to render it. - @controller_ string: Name of the post controller, this name will be used for calling interactors, views and presenters. For example, displayPost, displayAudio, etc. - """ - p = getattr(presenters, controller_+"Presenter")(session=self.session, postObject=post_object, interactor=getattr(interactors, controller_+"Interactor")(), view=getattr(views, controller_)(), **vars) - - def update_status_bar(self, status): - """ Update the status bar present in the main Window. - @ status str: Text to be placed in the status bar. - """ - wx.CallAfter(self.window.change_status, status) - - def chat_from_id(self, user_id, setfocus=True, unread=False): - """ Create a conversation buffer for. - @ user_id: Vk user, chat or community ID to chat with. - @ setfocus boolean: If set to True, the buffer will receive focus automatically right after being created. - @ unread: if set to True, the last message of the buffer will be marked as unread - """ - log.debug("Received request to create buffer for conversation {0} with args of unread={1}, setfocus={2}".format(user_id, unread, setfocus)) - b = self.search_chat_buffer(user_id) - if b != None: - log.debug("Chat buffer found. Skipping...") - pos = self.window.search(b.name) - if setfocus: - self.window.change_buffer(pos) - return b.tab.text.SetFocus() - return - # Get name based in the ID. - # for users. - log.debug("Determining name for buffer...") - if user_id > 0 and user_id < 2000000000: - user = self.session.get_user(user_id, key="user1") - name = user["user1_nom"] - elif user_id > 2000000000: - chat = self.session.vk.client.messages.getChat(chat_id=user_id-2000000000) - name = chat["title"] - log.debug("Buffer name: {}".format(name,)) - elif user_id < -20000000: - app = self.session.vk.client.apps.get(id=user_id*-1) - log.debug(app) - name = app["items"][0]["title"] - pub.sendMessage("create_buffer", buffer_type="chatBuffer", buffer_title=name, parent_tab="chats", get_items=True, kwargs=dict(parent=self.window.tb, name="{0}_messages".format(user_id,), composefunc="render_message", parent_endpoint="messages", endpoint="getHistory", session=self.session, unread=unread, count=self.session.settings["buffers"]["count_for_chat_buffers"], peer_id=user_id, rev=0, extended=True, fields="id, user_id, date, read_state, out, body, attachments, deleted")) -# if setfocus: -# pos = self.window.search(buffer.name) -# self.window.change_buffer(pos) -# call_threaded(buffer.get_items, unread=unread) -# if setfocus: buffer.tab.text.SetFocus() -# return True - - def authorisation_failed(self): - """ display an informative message about a failed authorization process.""" - commonMessages.bad_authorisation() - restart.restart_program() - - def connection_error(self, *args, **kwargs): - commonMessages.connection_error() - self.disconnect_events() - volume = player.player.volume - config.app["sound"]["volume"] = volume - config.app.write() - self.window.Destroy() - wx.GetApp().ExitMainLoop() - - def user_profile(self, person): - """ display someone's profile. For now, only users are supported.""" - p = presenters.userProfilePresenter(session=self.session, user_id=person, view=views.userProfileDialog(), interactor=interactors.userProfileInteractor()) - - def user_online(self, event): - """ Add user to the online buffer and Send a notification of an user connecting to VK. - @ event vk_api.longpoll.event object: The event sent by the vk_api's longPoll module. - """ - if self.session.settings["chat"]["notify_online"] == True: - user_name = self.session.get_user(event.user_id) - msg = _("{user1_nom} is online.").format(**user_name) - sound = "friend_online.ogg" - self.notify(msg, sound, self.session.settings["chat"]["notifications"]) - online_buffer = self.search("online_friends") - user = None - for i in self.session.db["friends_"]["items"]: - if i["id"] == event.user_id: - user = i - user["last_seen"]["time"] = time.time() - break - if user == None: - log.exception("Getting user manually...") - user = self.session.vk.client.users.get(user_ids=event.user_id, fields="last_seen, can_post")[0] - wx.CallAfter(online_buffer.add_person, user) - - def user_offline(self, event): - """ Remove user from the online buffer and Send a notification of an user logging off in VK. - @ event vk_api.longpoll.event object: The event sent by the vk_api's longPoll module. - """ - if self.session.settings["chat"]["notify_offline"] == True: - user_name = self.session.get_user(event.user_id) - msg = _("{user1_nom} is offline.").format(**user_name) - sound = "friend_offline.ogg" - self.notify(msg, sound, self.session.settings["chat"]["notifications"]) - online_friends = self.search("online_friends") - wx.CallAfter(online_friends.remove_person, event.user_id) - - def notify(self, message="", sound="", type="native"): - """ display a notification in Socializer. - @message str: Message to display in the notification. - @sound str: sound file to play in the notification, if type is set to custom. - @type str: notification type: native or custom. - Native notifications are made with WX and don't have sound, while custom notifications have sound but are not displayed in the window. - """ - if type == "native": - wx.CallAfter(self.window.notify, _("Socializer"), message) - else: - if sound != "": - self.session.soundplayer.play(sound) - if message != "": - output.speak(message) - - def handle_longpoll_read_timeout(self): - """ This function tries to reconnect the long poll module until when it will get a successful connection. - Due to the way this method has been implemented, the function will be repeatedly called until it will connect properly. - """ - if hasattr(self, "longpoll"): - self.notify(message=_("Chat disconnected. Trying to connect in 60 seconds")) - time.sleep(60) - if hasattr(self, "longpoll"): - del self.longpoll - self.create_longpoll_thread(notify=True) - - @wx_call_after - def create_buffer(self, buffer_type="baseBuffer", buffer_title="", parent_tab=None, loadable=False, get_items=False, kwargs={}): - """ Create and insert a buffer in the specified place. - @buffer_type str: name of the buffer type to be created. This should be a class in the buffers.py module. - @buffer_title str: Buffer title to be used in the Treebook. - @parent_tab str or None: If set to None, the parent tab will be the root of the treebook. In all other cases, the parent tab will be searched in the treebook. - @loadable bool: If set to True, the new buffer will not be able to load contents until can_get_items will be set to True. - @get_items bool: If set to True, get_items will be called inmediately after creating the buffer. - """ - log.debug("Creating buffer of type {0} with parent_tab of {2} arguments {1}".format(buffer_type, kwargs, parent_tab)) - if not hasattr(buffers, buffer_type): - raise AttributeError("Specified buffer type does not exist: %s" % (buffer_type,)) - buffer = getattr(buffers, buffer_type)(**kwargs) - if loadable: - buffer.can_get_items = False - self.buffers.append(buffer) - if parent_tab == None: - log.debug("Appending buffer {}...".format(buffer,)) - self.window.add_buffer(buffer.tab, buffer_title) - else: - self.window.insert_buffer(buffer.tab, buffer_title, self.window.search(parent_tab)) - log.debug("Inserting buffer {0} into control {1}".format(buffer, self.window.search(parent_tab))) - if get_items: - call_threaded(buffer.get_items) - - def user_typing(self, obj): - """ Indicates when someone is typing. - @ event vk_api.longpoll.event object: The event sent by the vk_api's longPoll module. - """ - buffer = self.search_chat_buffer(obj.user_id) - if buffer != None and buffer == self.get_current_buffer() and self.is_focused(): - user = self.session.get_user(obj.user_id) - user1_nom = user["user1_nom"].split()[0] - output.speak(_("{user1_nom} is typing...").format(user1_nom=user1_nom)) - - def edit_message(self, obj): - print(vars(obj)) - - def get_chat(self, obj=None): - """ Searches or creates a chat buffer with the id of the user that is sending or receiving a message. - @obj vk_api.longpoll.EventType: an event wich defines some data from the vk's long poll server.""" - message = {} - uid = obj.peer_id - buffer = self.search_chat_buffer(uid) - if obj.from_me: - message.update(out=0) - # If there is no buffer, we must create one in a wxThread so it will not crash. - if buffer == None: - wx.CallAfter(self.chat_from_id, uid, setfocus=self.session.settings["chat"]["automove_to_conversations"], unread=True) - self.session.soundplayer.play("conversation_opened.ogg") - return - # If the chat already exists, let's create a dictionary wich will contains data of the received message. - message.update(id=obj.message_id, user_id=uid, date=obj.timestamp, body=utils.clean_text(obj.text), attachments=obj.attachments) - # if attachments is true or body contains at least an URL, let's request for the full message with attachments formatted in a better way. - # ToDo: code improvements. We shouldn't need to request the same message again just for these attachments. - if len(message["attachments"]) != 0 or len(utils.find_urls_in_text(message["body"])) != 0: - message_ids = message["id"] - results = self.session.vk.client.messages.getById(message_ids=message_ids) - message = results["items"][0] - if obj.from_me: - message["from_id"] = self.session.user_id - else: - message.update(read_state=0, out=0) - message["from_id"] = obj.user_id - data = [message] - # Let's add this to the buffer. - # ToDo: Clean this code and test how is the database working with this set to True. - buffer.session.db[buffer.name]["items"].append(message) - wx.CallAfter(buffer.insert, self.session.db[buffer.name]["items"][-1], False) - self.session.soundplayer.play("message_received.ogg") - wx.CallAfter(self.reorder_buffer, buffer) - # Check if we have to read the message aloud - if buffer == self.get_current_buffer(): - rendered_message = renderers.render_message(message, self.session) - output.speak(rendered_message[0]) - - def create_timeline(self, user_id, buffer_type, user=""): - if user_id == "": - user_data = self.session.vk.client.utils.resolveScreenName(screen_name=user) - if type(user_data) == list: - commonMessages.no_user_exist() - return - user_id = user_data["object_id"] - if buffer_type == "audio": - buffer = buffers.audioBuffer(parent=self.window.tb, name="{0}_audio".format(user_id,), composefunc="render_audio", session=self.session, create_tab=False, endpoint="get", parent_endpoint="audio", owner_id=user_id) - user = self.session.get_user(user_id, key="user1") - name_ = _("{user1_nom}'s audios").format(**user) - elif buffer_type == "wall": - buffer = buffers.feedBuffer(parent=self.window.tb, name="{0}_feed".format(user_id,), composefunc="render_status", session=self.session, create_tab=False, endpoint="get", parent_endpoint="wall", extended=1, count=self.session.settings["buffers"]["count_for_wall_buffers"], owner_id=user_id) - user = self.session.get_user(user_id, key="user1") - name_ = _("{user1_nom}'s posts").format(**user) - elif buffer_type == "video": - buffer = buffers.videoBuffer(parent=self.window.tb, name="{0}_video".format(user_id,), composefunc="render_video", session=self.session, create_tab=False, endpoint="get", parent_endpoint="video", owner_id=user_id, count=self.session.settings["buffers"]["count_for_video_buffers"]) - user = self.session.get_user(user_id, key="user1") - name_ = _("{user1_nom}'s videos").format(**user) - elif buffer_type == "friends": - buffer = buffers.peopleBuffer(parent=self.window.tb, name="friends_{0}".format(user_id,), composefunc="render_person", session=self.session, create_tab=False, endpoint="get", parent_endpoint="friends", count=5000, fields="uid, first_name, last_name, last_seen, can_post, can_write_private_message", user_id=user_id) - user = self.session.get_user(user_id, key="user1") - name_ = _("{user1_nom}'s friends").format(**user) - wx.CallAfter(self.complete_buffer_creation, buffer=buffer, name_=name_, position=self.window.search("timelines")) - - ### GUI events - # These functions are connected to GUI elements such as menus, buttons and so on. - def connect_gui_events(self): - widgetUtils.connectExitFunction(self.exit_) - widgetUtils.connect_event(self.window, widgetUtils.CLOSE_EVENT, self.exit) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.update_buffer, menuitem=self.window.update_buffer) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.check_for_updates, menuitem=self.window.check_for_updates) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.on_about, menuitem=self.window.about) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.search_audios, menuitem=self.window.search_audios) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.search_videos, menuitem=self.window.search_videos) - widgetUtils.connect_event(self.window, widgetUtils.MENU,self.remove_buffer, menuitem=self.window.remove_buffer_) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.get_more_items, menuitem=self.window.load_previous_items) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.changelog, menuitem=self.window.changelog) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.open_logs, menuitem=self.window.open_logs) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.open_config, menuitem=self.window.open_config) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.blacklist, menuitem=self.window.blacklist) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.manage_accounts, menuitem=self.window.accounts) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.configuration, menuitem=self.window.settings_dialog) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.new_timeline, menuitem=self.window.timeline) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.create_audio_album, menuitem=self.window.audio_album) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.delete_audio_album, menuitem=self.window.delete_audio_album) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.create_video_album, menuitem=self.window.video_album) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.delete_video_album, menuitem=self.window.delete_video_album) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.check_documentation, menuitem=self.window.documentation) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.menu_play_pause, menuitem=self.window.player_play) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.menu_play_next, menuitem=self.window.player_next) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.menu_play_previous, menuitem=self.window.player_previous) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.menu_play_all, menuitem=self.window.player_play_all) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.seek_left, menuitem=self.window.player_seek_left) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.seek_right, menuitem=self.window.player_seek_right) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.menu_volume_down, menuitem=self.window.player_volume_down) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.menu_volume_up, menuitem=self.window.player_volume_up) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.menu_mute, menuitem=self.window.player_mute) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.view_my_profile, menuitem=self.window.view_profile) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.view_my_profile_in_browser, menuitem=self.window.open_in_browser) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.set_status, menuitem=self.window.set_status) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.on_report_error, menuitem=self.window.report) - self.window.tb.Bind(wx.EVT_CONTEXT_MENU, self.on_context_menu) - - def exit(self, *args, **kwargs): - answer = commonMessages.exit() - if answer == widgetUtils.YES: - self.exit_() - - def exit_(self, *args, **kwargs): - """ Try to set offline in the current user's profile at VK, then closes the application. """ - log.debug("Receibed an exit signal. closing...") - self.set_offline() - self.disconnect_events() - volume = player.player.volume - config.app["sound"]["volume"] = volume - config.app.write() - self.window.Destroy() - wx.GetApp().ExitMainLoop() - - def update_buffer(self, *args, **kwargs): - """ Update the current buffer, getting the recent items.""" - b = self.get_current_buffer() - b.get_items() - - def check_for_updates(self, *args, **kwargs): - update = updater.do_update(update_type=self.session.settings["general"]["update_channel"]) - if update == False: - commonMessages.no_update_available() - - def on_about(self, *args, **kwargs): - channel = self.session.settings["general"]["update_channel"] - self.window.about_dialog(channel) - - def search_audios(self, *args, **kwargs): - dlg = searchDialogs.searchAudioDialog() - if dlg.get_response() == widgetUtils.OK: - q = dlg.get("term") - auto_complete = True - count = 300 - performer_only = dlg.get_state("title") - sort = dlg.get_sort_order() - newbuff = buffers.audioBuffer(parent=self.window.tb, name="{0}_audiosearch".format(q,), session=self.session, composefunc="render_audio", parent_endpoint="audio", endpoint="search", q=q, auto_complete=auto_complete, count=count, performer_only=performer_only, sort=sort) - self.buffers.append(newbuff) - call_threaded(newbuff.get_items) - # Translators: {0} will be replaced with the search term. - self.window.insert_buffer(newbuff.tab, _("Search for {0}").format(q,), self.window.search("audios")) - - def search_videos(self, *args, **kwargs): - dlg = searchDialogs.searchVideoDialog() - if dlg.get_response() == widgetUtils.OK: - params = {} - params["q"] = dlg.get("term") - params["count"] = 200 - hd = dlg.get_checkable("hd") - if hd != 0: - params["hd"] = 1 - params["adult"] = dlg.get_checkable("safe_search") - params["sort"] = dlg.get_sort_order() -# params["filters"] = "youtube, vimeo, short, long, mp4" -# print(params) - newbuff = buffers.videoBuffer(parent=self.window.tb, name="{0}_videosearch".format(params["q"],), session=self.session, composefunc="render_video", parent_endpoint="video", endpoint="search", **params) - self.buffers.append(newbuff) - call_threaded(newbuff.get_items) - # Translators: {0} will be replaced with the search term. - self.window.insert_buffer(newbuff.tab, _("Search for {0}").format(params["q"],), self.window.search("videos")) - - def remove_buffer(self, event, mandatory=False, *args, **kwargs): - buffer = self.get_current_buffer() - buff = self.window.search(buffer.name) - answer = buffer.remove_buffer(mandatory) - if answer == False: - return - self.window.remove_buffer(buff) - self.buffers.remove(buffer) - del buffer - - def get_more_items(self, *args, **kwargs): - b = self.get_current_buffer() - b.get_more_items() - - def changelog(self, *args, **kwargs): - lang = localization.get("documentation") - os.chdir("documentation/%s" % (lang,)) - webbrowser.open("changelog.html") - os.chdir("../../") - - def configuration(self, *args, **kwargs): - """ Opens the global settings dialogue.""" - presenter = presenters.configurationPresenter(session=self.session, view=views.configurationDialog(title=_("Preferences")), interactor=interactors.configurationInteractor()) - - def blacklist(self, *args, **kwargs): - """ Opens the blacklist presenter.""" - presenter = presenters.blacklistPresenter(session=self.session, view=views.blacklistDialog(), interactor=interactors.blacklistInteractor()) - - def manage_accounts(self, *args, **kwargs): - accounts = sessionManager.sessionManagerController(starting=False) - accounts.view.get_response() - if hasattr(accounts, "modified"): - restart_msg = commonMessages.restart_program() - if restart_msg == widgetUtils.YES: - restart.restart_program() - - def open_logs(self, *args, **kwargs): - subprocess.call(["explorer", paths.logs_path()]) - - def open_config(self, *args, **kwargs): - subprocess.call(["explorer", paths.config_path()]) - - def new_timeline(self, *args, **kwargs): - b = self.get_current_buffer() - # If executing this method from an empty buffer we should get the newsfeed buffer. - if not hasattr(b, "get_users"): - b = self.search("home_timeline") - # Get a list of (id, user) objects. - d = [] - for i in self.session.db["users"]: - d.append((i, self.session.get_user(i)["user1_gen"])) - # Do the same for communities. - for i in self.session.db["groups"]: - d.append((-i, self.session.get_user(-i)["user1_nom"])) - a = timeline.timelineDialog([i[1] for i in d]) - if a.get_response() == widgetUtils.OK: - user = a.get_user() - buffertype = a.get_buffer_type() - user_id = "" - for i in d: - if i[1] == user: - user_id = i[0] - pub.sendMessage("create-timeline", user_id=user_id, buffer_type=buffertype) - - def create_audio_album(self, *args, **kwargs): - d = creation.audio_album() - if d.get_response() == widgetUtils.OK and d.get("title") != "": - response = self.session.vk.client.audio.createPlaylist(owner_id=self.session.user_id, title=d.get("title")) - if "id" not in response: - return - album_id = response["id"] - buffer = buffers.audioAlbum(parent=self.window.tb, name="{0}_audio_album".format(album_id,), composefunc="render_audio", session=self.session, endpoint="get", parent_endpoint="audio", full_list=True, count=self.session.settings["buffers"]["count_for_audio_buffers"], user_id=self.session.user_id, album_id=album_id) - buffer.can_get_items = False - # Translators: {0} will be replaced with an audio album's title. - name_ = _("Album: {0}").format(d.get("title"),) - self.buffers.append(buffer) - self.window.insert_buffer(buffer.tab, name_, self.window.search("albums")) - buffer.get_items() - self.get_audio_albums(user_id=self.session.user_id, create_buffers=False) - - def delete_audio_album(self, *args, **kwargs): - if len(self.session.audio_albums) == 0: - return commonMessages.no_audio_albums() - answer = selector.album(_("Select the album you want to delete"), self.session) - if answer.item == None: - return - response = commonMessages.delete_audio_album() - if response != widgetUtils.YES: return - removal = self.session.vk.client.audio.deletePlaylist(playlist_id=answer.item, owner_id=self.session.user_id) - if removal == 1: - buffer = self.search("{0}_audio_album".format(answer.item,)) - buff = self.window.search(buffer.name) - self.window.remove_buffer(buff) - self.buffers.remove(buffer) - del buffer - self.get_audio_albums(user_id=self.session.user_id, create_buffers=False) - - def create_video_album(self, *args, **kwargs): - d = creation.audio_album() - if d.get_response() == widgetUtils.OK and d.get("title") != "": - response = self.session.vk.client.video.addAlbum(title=d.get("title")) - if ("album_id" in response) == False: return - album_id = response["album_id"] - buffer = buffers.videoAlbum(parent=self.window.tb, name="{0}_video_album".format(album_id,), composefunc="render_video", session=self.session, endpoint="get", parent_endpoint="video", count=self.session.settings["buffers"]["count_for_video_buffers"], user_id=self.session.user_id, album_id=album_id) - buffer.can_get_items = False - # Translators: {0} will be replaced with a video album's title. - name_ = _("Album: {0}").format(d.get("title"),) - self.buffers.append(buffer) - self.window.insert_buffer(buffer.tab, name_, self.window.search("video_albums")) - buffer.get_items() - self.session.video_albums = self.session.vk.client.video.getAlbums(owner_id=self.session.user_id)["items"] - - def delete_video_album(self, *args, **kwargs): - if len(self.session.video_albums) == 0: - return commonMessages.no_video_albums() - answer = selector.album(_("Select the album you want to delete"), self.session, "video_albums") - if answer.item == None: - return - response = commonMessages.delete_audio_album() - if response != widgetUtils.YES: return - removal = self.session.vk.client.video.deleteAlbum(album_id=answer.item) - buffer = self.search("{0}_video_album".format(answer.item,)) - buff = self.window.search(buffer.name) - self.window.remove_buffer(buff) - self.buffers.remove(buffer) - del buffer - self.session.video_albums = self.session.vk.client.video.getAlbums(owner_id=self.session.user_id)["items"] - - def check_documentation(self, *args, **kwargs): - lang = localization.get("documentation") - os.chdir("documentation/%s" % (lang,)) - webbrowser.open("manual.html") - os.chdir("../../") - - def menu_play_pause(self, *args, **kwargs): - if player.player.stream != None: - return player.player.pause() - else: - b = self.get_current_buffer() - if hasattr(b, "play_all"): - b.play_all() - else: - self.search("me_audio").play_all() - - def menu_play_next(self, *args, **kwargs): - pub.sendMessage("play-next") - - def menu_play_previous(self, *args, **kwargs): - pub.sendMessage("play-previous") - - def menu_play_all(self, *args, **kwargs): - b = self.get_current_buffer() - if hasattr(b, "play_all"): - b.play_all() - else: - self.search("me_audio").play_all() - - def menu_volume_down(self, *args, **kwargs): - if player.player != None: - player.player.volume = player.player.volume-2 - - def menu_volume_up(self, *args, **kwargs): - if player.player != None: - player.player.volume = player.player.volume+2 - - def menu_mute(self, *args, **kwargs): - if player.player != None: - player.player.volume = 0 - - def seek_left(self, *args, **kwargs): - pub.sendMessage("seek", ms=-500000) - - def seek_right(self, *args, **kwargs): - pub.sendMessage("seek", ms=500000) - - def view_my_profile(self, *args, **kwargs): - self.user_profile(self.session.user_id) - - def view_my_profile_in_browser(self, *args, **kwargs): - webbrowser.open_new_tab("https://vk.com/id{id}".format(id=self.session.user_id,)) - - def set_status(self, *args, **kwargs): - dlg = wx.TextEntryDialog(self.window, _("Write your status message"), _("Set status")) - if dlg.ShowModal() == widgetUtils.OK: - result = dlg.GetValue() - info = self.session.vk.client.account.saveProfileInfo(status=result) - commonMessages.updated_status() - dlg.Destroy() - - def on_report_error(self, *args, **kwargs): - r = issueReporter.reportBug() - - def on_context_menu(self, event, *args, **kwargs): - """ Handles context menu event in the tree buffers.""" - # If the focus is not in the TreeCtrl of the Treebook, then we should not display any menu. - if isinstance(self.window.FindFocus(), wx.TreeCtrl) == False: - event.Skip() - return - menu = None - # Get the current buffer and let's choose a different menu depending on the selected buffer. - current_buffer = self.get_current_buffer() - # Deal with menu for community buffers. - if current_buffer.name.endswith("_community"): - menu = menus.communityBufferMenu() - # disable post loading if the community has already loaded posts. - if current_buffer.can_get_items: - menu.load_posts.Enable(False) - # Disable loading of audios, videos, documents or topics depending in two conditions. - # 1. If the buffer already exists, which means they are already loaded, or - # 2. If the group_info does not have counters for such items, which would indicate there are no items posted yet. - if self.search(current_buffer.name+"_audios") != False: - menu.load_audios.Enable(False) - elif "counters" in self.session.db["group_info"][current_buffer.group_id] and "audios" not in self.session.db["group_info"][current_buffer.group_id]["counters"]: - menu.load_audios.Enable(False) - if self.search(current_buffer.name+"_videos") != False: - menu.load_videos.Enable(False) - elif "counters" in self.session.db["group_info"][current_buffer.group_id] and "videos" not in self.session.db["group_info"][current_buffer.group_id]["counters"]: - menu.load_videos.Enable(False) - if self.search(current_buffer.name+"_topics") != False: - menu.load_topics.Enable(False) - elif "counters" in self.session.db["group_info"][current_buffer.group_id] and "topics" not in self.session.db["group_info"][current_buffer.group_id]["counters"]: - menu.load_topics.Enable(False) - if self.search(current_buffer.name+"_documents") != False: - menu.load_documents.Enable(False) - elif "counters" in self.session.db["group_info"][current_buffer.group_id] and "docs" not in self.session.db["group_info"][current_buffer.group_id]["counters"]: - menu.load_documents.Enable(False) - # Connect the rest of the functions. - print(self.session.db["group_info"][current_buffer.group_id]) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_community_posts, menuitem=menu.load_posts) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_community_topics, menuitem=menu.load_topics) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_community_members, menuitem=menu.load_members) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_community_audios, menuitem=menu.load_audios) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_community_videos, menuitem=menu.load_videos) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_community_documents, menuitem=menu.load_documents) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.open_community_in_browser, menuitem=menu.open_in_browser) - # Deal with the communities section itself. - elif current_buffer.name == "communities": - menu = wx.Menu() - # Insert a different option depending if group buffers are loaded or scheduled to be loaded or not. - if self.session.settings["load_at_startup"]["communities"] == False and not hasattr(self.session, "groups"): - option = menu.Append(wx.NewId(), _("Load groups")) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_community_buffers, menuitem=option) - else: - option = menu.Append(wx.NewId(), _("Discard groups")) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.unload_community_buffers, menuitem=option) - # Deal with video and audio albums' sections. - elif current_buffer.name == "audio_albums": - menu = wx.Menu() - if self.session.settings["load_at_startup"]["audio_albums"] == False and not hasattr(self.session, "audio_albums"): - option = menu.Append(wx.NewId(), _("Load audio albums")) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_audio_album_buffers, menuitem=option) - else: - option = menu.Append(wx.NewId(), _("Discard audio albums")) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.unload_audio_album_buffers, menuitem=option) - elif current_buffer.name == "video_albums": - menu = wx.Menu() - if self.session.settings["load_at_startup"]["video_albums"] == False and not hasattr(self.session, "video_albums"): - option = menu.Append(wx.NewId(), _("Load video albums")) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_video_album_buffers, menuitem=option) - else: - option = menu.Append(wx.NewId(), _("Discard video albums")) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.unload_video_album_buffers, menuitem=option) - elif current_buffer.name.endswith("_messages"): - menu = menus.conversationBufferMenu() - widgetUtils.connect_event(menu, widgetUtils.MENU, self.delete_conversation, menuitem=menu.delete) - widgetUtils.connect_event(menu, widgetUtils.MENU, current_buffer.open_in_browser, menuitem=menu.open_in_browser) - if menu != None: - self.window.PopupMenu(menu, self.window.FindFocus().GetPosition()) - # If there are no available menus, let's indicate it. - else: - output.speak(_("menu unavailable for this buffer.")) - - def load_community_posts(self, *args, **kwargs): - """ Load community posts. It just calls to the needed method in the community buffer.""" - current_buffer = self.get_current_buffer() - if current_buffer.name.endswith("_community"): - current_buffer.load_community() - - def load_community_audios(self, *args, **kwargs): - """ Load community audios if they are not loaded already.""" - current_buffer = self.get_current_buffer() - # Get group_info if the community buffer does not have it already, so future menus will be able to use it. - if current_buffer.group_id not in self.session.db["group_info"] or "counters" not in self.session.db["group_info"][current_buffer.group_id]: - group_info = self.session.vk.client.groups.getById(group_ids=-1*current_buffer.kwargs["owner_id"], fields="counters,can_create_topics,can_post")[0] - self.session.db["group_info"][current_buffer.kwargs["owner_id"]].update(group_info) - if "audios" not in self.session.db["group_info"][current_buffer.group_id]["counters"]: - commonMessages.community_no_items() - return - new_name = current_buffer.name+"_audios" - pub.sendMessage("create_buffer", buffer_type="audioBuffer", buffer_title=_("Audios"), parent_tab=current_buffer.tab.name, get_items=True, kwargs=dict(parent=self.window.tb, name=new_name, composefunc="render_audio", session=self.session, endpoint="get", parent_endpoint="audio", owner_id=current_buffer.kwargs["owner_id"])) - - def load_community_videos(self, *args, **kwargs): - """ Load community videos if they are not loaded already.""" - current_buffer = self.get_current_buffer() - # Get group_info if the community buffer does not have it already, so future menus will be able to use it. - if current_buffer.group_id not in self.session.db["group_info"] or "counters" not in self.session.db["group_info"][current_buffer.group_id]: - group_info = self.session.vk.client.groups.getById(group_ids=-1*current_buffer.kwargs["owner_id"], fields="counters,can_create_topics,can_post")[0] - self.session.db["group_info"][current_buffer.kwargs["owner_id"]].update(group_info) - if "videos" not in self.session.db["group_info"][current_buffer.group_id]["counters"]: - commonMessages.community_no_items() - return - new_name = current_buffer.name+"_videos" - pub.sendMessage("create_buffer", buffer_type="videoBuffer", buffer_title=_("Videos"), parent_tab=current_buffer.tab.name, get_items=True, kwargs=dict(parent=self.window.tb, name=new_name, composefunc="render_video", session=self.session, endpoint="get", parent_endpoint="video", count=self.session.settings["buffers"]["count_for_video_buffers"], owner_id=current_buffer.kwargs["owner_id"])) - - def load_community_topics(self, *args, **kwargs): - """ Load community topics.""" - current_buffer = self.get_current_buffer() - # Get group_info if the community buffer does not have it already, so future menus will be able to use it. - if current_buffer.group_id not in self.session.db["group_info"] or "counters" not in self.session.db["group_info"][current_buffer.group_id]: - group_info = self.session.vk.client.groups.getById(group_ids=-1*current_buffer.kwargs["owner_id"], fields="counters,can_create_topic,can_post")[0] - self.session.db["group_info"][current_buffer.kwargs["owner_id"]].update(group_info) - if "topics" not in self.session.db["group_info"][current_buffer.group_id]["counters"]: - commonMessages.community_no_items() - return - new_name = current_buffer.name+"_topics" - pub.sendMessage("create_buffer", buffer_type="topicBuffer", buffer_title=_("Topics"), parent_tab=current_buffer.tab.name, get_items=True, kwargs=dict(parent=self.window.tb, name=new_name, composefunc="render_topic", session=self.session, endpoint="getTopics", parent_endpoint="board", count=100, group_id=-1*current_buffer.kwargs["owner_id"], extended=1)) - - def load_community_members(self, *args, **kwargs): - """ Load community members. """ - current_buffer = self.get_current_buffer() - # Get group_info if the community buffer does not have it already, so future menus will be able to use it. - if current_buffer.group_id not in self.session.db["group_info"] or "counters" not in self.session.db["group_info"][current_buffer.group_id]: - group_info = self.session.vk.client.groups.getById(group_ids=-1*current_buffer.kwargs["owner_id"], fields="counters,can_create_topic,can_post")[0] - self.session.db["group_info"][current_buffer.kwargs["owner_id"]].update(group_info) - # Determine whether we can request ordering by time descending or not. - if (self.session.db["group_info"][current_buffer.group_id].get("is_admin") != None and self.session.db["group_info"][current_buffer.group_id].get("is_admin") == 1): - sorting = "time_desc" - else: - sorting = "id_desc" - # Apparently, only administrators in a community are able to see invited users on it, despite users can invite the amount of friends they want. - # ToDo: This needs testing in groups where the current user is not a full admin (such as moderator or editor). - if (self.session.db["group_info"][current_buffer.group_id].get("is_admin") != None and self.session.db["group_info"][current_buffer.group_id].get("is_admin") == 1): - pub.sendMessage("create_buffer", buffer_type="emptyBuffer", buffer_title=_("People"), parent_tab=current_buffer.tab.name, kwargs=dict(parent=self.window.tb, name=current_buffer.tab.name+"_people")) - pub.sendMessage("create_buffer", buffer_type="communityPeopleBuffer", buffer_title=_("Members"), parent_tab=current_buffer.name+"_people", get_items=True, kwargs=dict(parent=self.window.tb, name=current_buffer.name+"_members", composefunc="render_person", session=self.session, endpoint="getMembers", parent_endpoint="groups", count=1000, order=sorting, fields="uid, first_name, last_name, last_seen, can_post", group_id=-1*current_buffer.kwargs["owner_id"])) - pub.sendMessage("create_buffer", buffer_type="communityPeopleBuffer", buffer_title=_("Invited users"), parent_tab=current_buffer.name+"_people", get_items=True, kwargs=dict(parent=self.window.tb, name=current_buffer.name+"_invites", composefunc="render_person", session=self.session, endpoint="getInvitedUsers", parent_endpoint="groups", count=1000, fields="first_name, last_name, last_seen, can_post, can_write_private_message", group_id=-1*current_buffer.kwargs["owner_id"])) - else: # Create this for non administrators. - pub.sendMessage("create_buffer", buffer_type="communityPeopleBuffer", buffer_title=_("Members"), parent_tab=current_buffer.tab.name, get_items=True, kwargs=dict(parent=self.window.tb, name=current_buffer.name+"_members", composefunc="render_person", session=self.session, endpoint="getMembers", parent_endpoint="groups", count=1000, order=sorting, fields="uid, first_name, last_name, last_seen, can_post, can_write_private_message", group_id=-1*current_buffer.kwargs["owner_id"])) - - def load_community_documents(self, *args, **kwargs): - current_buffer = self.get_current_buffer() - # Get group_info if the community buffer does not have it already, so future menus will be able to use it. - if current_buffer.group_id not in self.session.db["group_info"] or "counters" not in self.session.db["group_info"][current_buffer.group_id]: - group_info = self.session.vk.client.groups.getById(group_ids=-1*current_buffer.kwargs["owner_id"], fields="counters,can_create_topics,can_post")[0] - self.session.db["group_info"][current_buffer.kwargs["owner_id"]].update(group_info) - if "docs" not in self.session.db["group_info"][current_buffer.group_id]["counters"]: - commonMessages.community_no_items() - return - new_name = current_buffer.name+"_documents" - pub.sendMessage("create_buffer", buffer_type="documentCommunityBuffer", buffer_title=_("Documents"), parent_tab=current_buffer.tab.name, get_items=True, kwargs=dict(parent=self.window.tb, name=new_name, composefunc="render_document", session=self.session, endpoint="get", parent_endpoint="docs", owner_id=current_buffer.kwargs["owner_id"])) - - def open_community_in_browser(self, *args, **kwargs): - current_buffer = self.get_current_buffer() - if current_buffer.name.endswith("_community"): - webbrowser.open_new_tab("https://vk.com/club{0}".format(-1*current_buffer.kwargs["owner_id"])) - - def load_community_buffers(self, *args, **kwargs): - """ Load all community buffers regardless of the setting present in optional buffers tab of the preferences dialog.""" - call_threaded(self.get_communities, self.session.user_id, force_action=True) - - def unload_community_buffers(self, *args, **kwargs): - """ Delete all buffers belonging to groups.""" - communities = self.get_all_buffers("_community") - for buffer in communities: - buff = self.window.search(buffer.name) - self.window.remove_buffer(buff) - self.buffers.remove(buffer) - del self.session.groups - - def load_audio_album_buffers(self, *args, **kwargs): - """ Load all audio album buffers regardless of the setting present in optional buffers tab of the preferences dialog.""" - call_threaded(self.get_audio_albums, self.session.user_id, force_action=True) - - def unload_audio_album_buffers(self, *args, **kwargs): - """ Delete all buffers belonging to audio albums.""" - albums = self.get_all_buffers("_audio_album") - for buffer in albums: - buff = self.window.search(buffer.name) - self.window.remove_buffer(buff) - self.buffers.remove(buffer) - del self.session.audio_albums - - def load_video_album_buffers(self, *args, **kwargs): - """ Load all video album buffers regardless of the setting present in optional buffers tab of the preferences dialog.""" - call_threaded(self.get_video_albums, self.session.user_id, force_action=True) - - def unload_video_album_buffers(self, *args, **kwargs): - """ Delete all buffers belonging to video albums.""" - albums = self.get_all_buffers("_video_album") - for buffer in albums: - buff = self.window.search(buffer.name) - self.window.remove_buffer(buff) - self.buffers.remove(buffer) - del self.session.video_albums - - def delete_conversation(self, *args, **kwargs): - current_buffer = self.get_current_buffer() - d = commonMessages.delete_conversation() - if d == widgetUtils.YES: - results = self.session.vk.client.messages.deleteConversation(peer_id=current_buffer.kwargs["peer_id"]) - buff = self.window.search(current_buffer.name) - self.window.remove_buffer(buff) - self.buffers.remove(current_buffer) \ No newline at end of file + ### utils + # Important utility functions for the program which are not used directly by anyone. + def search(self, tab_name): + """ Search a buffer by name. Name should be the buffer.name argument. + returns a buffer object matching the pased name or None name.""" + for i in range(0, len(self.buffers)): + if self.buffers[i].name == tab_name: + return self.buffers[i] + return False + + def get_current_buffer(self): + """ Get the current bufferObject""" + buffer = self.window.get_current_buffer() + if hasattr(buffer, "name"): + buffer = self.search(buffer.name) + return buffer + + def get_all_buffers(self, contains): + """ Get all buffers containing the name passed as the only parameter. Similar to search, but this method returns a list with all buffers found. """ + results = [] + for i in self.buffers: + if contains in i.name: + results.append(i) + return results + + def __init__(self): + super(Controller, self).__init__() + log.debug("Starting main controller...") + self.buffers = [] + player.setup() + self.window = mainWindow.mainWindow() + log.debug("Main window created") + wx.CallAfter(self.window.change_status, _("Ready")) + self.session = session.sessions[list(session.sessions.keys())[0]] + self.window.Show() + self.connect_pubsub_events() + self.connect_gui_events() + self.create_controls() + call_threaded(updater.do_update, update_type=self.session.settings["general"]["update_channel"]) + + def is_focused(self): + """ Return True if the Socializer Window is Focused. """ + app_title = "socializer" + window_title = win32gui.GetWindowText(win32gui.GetForegroundWindow()).lower() + if app_title == window_title: + return True + return False + + ### action function + # These functions are called by other parts of the program, and are not connected to any event at all. + def create_controls(self): + """ Create all buffers for Socializer.""" + log.debug("Creating controls for the window...") + pub.sendMessage("create_buffer", buffer_type="emptyBuffer", buffer_title=_("Posts"), kwargs=dict(parent=self.window.tb, name="posts")) + pub.sendMessage("create_buffer", buffer_type="baseBuffer", buffer_title=_("Home"), parent_tab="posts", kwargs=dict(parent=self.window.tb, name="home_timeline", session=self.session, composefunc="render_newsfeed_item", endpoint="newsfeed", count=self.session.settings["buffers"]["count_for_wall_buffers"])) + pub.sendMessage("create_buffer", buffer_type="feedBuffer", buffer_title=_("My wall"), parent_tab="posts", kwargs=dict(parent=self.window.tb, name="me_feed", composefunc="render_status", session=self.session, endpoint="get", parent_endpoint="wall", extended=1, count=self.session.settings["buffers"]["count_for_wall_buffers"])) + pub.sendMessage("create_buffer", buffer_type="emptyBuffer", buffer_title=_("Music"), kwargs=dict(parent=self.window.tb, name="audios")) + pub.sendMessage("create_buffer", buffer_type="audioBuffer", buffer_title=_("My audios"), parent_tab="audios", kwargs=dict(parent=self.window.tb, name="me_audio", composefunc="render_audio", session=self.session, endpoint="get", parent_endpoint="audio")) + if self.session.settings["vk"]["use_alternative_tokens"] == False: + pub.sendMessage("create_buffer", buffer_type="audioBuffer", buffer_title=_("Populars"), parent_tab="audios", kwargs=dict(parent=self.window.tb, name="popular_audio", composefunc="render_audio", session=self.session, endpoint="getPopular", parent_endpoint="audio", full_list=True, count=self.session.settings["buffers"]["count_for_audio_buffers"])) + pub.sendMessage("create_buffer", buffer_type="audioBuffer", buffer_title=_("Recommendations"), parent_tab="audios", kwargs=dict(parent=self.window.tb, name="recommended_audio", composefunc="render_audio", session=self.session, endpoint="getRecommendations", parent_endpoint="audio", full_list=True, count=self.session.settings["buffers"]["count_for_audio_buffers"])) + pub.sendMessage("create_buffer", buffer_type="emptyBuffer", buffer_title=_("Albums"), parent_tab="audios", kwargs=dict(parent=self.window.tb, name="audio_albums")) + pub.sendMessage("create_buffer", buffer_type="emptyBuffer", buffer_title=_("Video"), kwargs=dict(parent=self.window.tb, name="videos")) + pub.sendMessage("create_buffer", buffer_type="videoBuffer", buffer_title=_("My videos"), parent_tab="videos", kwargs=dict(parent=self.window.tb, name="me_video", composefunc="render_video", session=self.session, endpoint="get", parent_endpoint="video", count=self.session.settings["buffers"]["count_for_video_buffers"])) + pub.sendMessage("create_buffer", buffer_type="emptyBuffer", buffer_title=_("Albums"), parent_tab="videos", kwargs=dict(parent=self.window.tb, name="video_albums")) + pub.sendMessage("create_buffer", buffer_type="emptyBuffer", buffer_title=_("People"), kwargs=dict(parent=self.window.tb, name="people")) + pub.sendMessage("create_buffer", buffer_type="peopleBuffer", buffer_title=_("Online"), parent_tab="people", kwargs=dict(parent=self.window.tb, name="online_friends", composefunc="render_person", session=self.session, endpoint="getOnline", parent_endpoint="friends", count=5000, order="hints", fields="uid, first_name, last_name, last_seen, can_post, can_write_private_message")) + pub.sendMessage("create_buffer", buffer_type="peopleBuffer", buffer_title=_("All friends"), parent_tab="people", kwargs=dict(parent=self.window.tb, name="friends_", composefunc="render_person", session=self.session, endpoint="get", parent_endpoint="friends", count=5000, order="hints", fields="uid, first_name, last_name, last_seen, can_post, can_write_private_message")) + pub.sendMessage("create_buffer", buffer_type="emptyBuffer", buffer_title=_("Friendship requests"), parent_tab="people", kwargs=dict(parent=self.window.tb, name="requests")) + pub.sendMessage("create_buffer", buffer_type="requestsBuffer", buffer_title=_("Pending requests"), parent_tab="requests", kwargs=dict(parent=self.window.tb, name="friend_requests", composefunc="render_person", session=self.session, count=1000, fields="can_post, can_write_private_message")) + pub.sendMessage("create_buffer", buffer_type="requestsBuffer", buffer_title=_("I follow"), parent_tab="requests", kwargs=dict(parent=self.window.tb, name="friend_requests_sent", composefunc="render_person", session=self.session, count=1000, out=1, fields="can_post, can_write_private_message")) + pub.sendMessage("create_buffer", buffer_type="requestsBuffer", buffer_title=_("Subscribers"), parent_tab="requests", kwargs=dict(parent=self.window.tb, name="subscribers", composefunc="render_person", session=self.session, count=1000, need_viewed=1, fields="can_post, can_write_private_message")) +# pub.sendMessage("create_buffer", buffer_type="notificationBuffer", buffer_title=_("Notifications"), parent_tab=None, loadable=False, kwargs=dict(parent=self.window.tb, name="notifications", composefunc="render_notification", session=self.session, endpoint="get", parent_endpoint="notifications", count=100, filters="wall,mentions,comments,likes,reposted,followers,friends")) + pub.sendMessage("create_buffer", buffer_type="documentBuffer", buffer_title=_("Documents"), parent_tab=None, loadable=True, kwargs=dict(parent=self.window.tb, name="documents", composefunc="render_document", session=self.session, endpoint="get", parent_endpoint="docs")) + pub.sendMessage("create_buffer", buffer_type="emptyBuffer", buffer_title=_("Groups"), kwargs=dict(parent=self.window.tb, name="communities")) + pub.sendMessage("create_buffer", buffer_type="emptyBuffer", buffer_title=_("Chats"), kwargs=dict(parent=self.window.tb, name="chats")) + pub.sendMessage("create_buffer", buffer_type="emptyBuffer", buffer_title=_("Timelines"), kwargs=dict(parent=self.window.tb, name="timelines")) + wx.CallAfter(self.window.realize) + self.repeatedUpdate = RepeatingTimer(120, self.update_all_buffers) + self.repeatedUpdate.start() + + def complete_buffer_creation(self, buffer, name_, position): + answer = buffer.get_items() + if answer is not True: + commonMessages.show_error_code(answer) + return + self.buffers.append(buffer) + self.window.insert_buffer(buffer.tab, name_, position) + + def search_chat_buffer(self, user_id): + for i in self.buffers: + if "_messages" in i.name: + if "peer_id" in i.kwargs and i.kwargs["peer_id"] == user_id: return i + return None + + def set_online(self, notify=False): + try: + r = self.session.vk.client.account.setOnline() + except: + log.error("Error in setting online for the current user") + if notify: + self.window.notify("Socializer", "online now!") + + def set_offline(self): + try: + r = self.session.vk.client.account.setOffline() + except: + log.error("Error in setting offline status for the current user") + + def create_unread_messages(self): + try: + log.debug("Creating conversation buffers...") + msgs = self.session.vk.client.messages.getConversations(count=200, filter="all") + log.debug("Total conversations count: {}".format(msgs.get("count"))) + log.debug("total conversations returned by VK: {}".format(len(msgs["items"]))) + log.debug("Dictionary keys of conversations object: {}".format(msgs.keys())) + except VkApiError as ex: + if ex.code == 6: + log.exception("Something went wrong when getting messages. Waiting a second to retry") + log.debug("Creating buffer conversation for {} buffers".format(len(msgs["items"]))) + for i in msgs["items"]: + log.debug("Creating chat buffer for peer_id {}".format(i["last_message"]["peer_id"])) + self.chat_from_id(i["last_message"]["peer_id"], setfocus=False, unread=False) + + def get_audio_albums(self, user_id=None, create_buffers=True, force_action=False): + if self.session.settings["load_at_startup"]["audio_albums"] == False and force_action == False: + return + log.debug("Create audio albums...") + if self.session.settings["vk"]["use_alternative_tokens"]: + albums = self.session.vk.client_audio.get_albums(owner_id=user_id) + else: + albums = self.session.vk.client.audio.getPlaylists(owner_id=user_id, count=100) + albums = albums["items"] + self.session.audio_albums = albums + if create_buffers: + for i in albums: + pub.sendMessage("create_buffer", buffer_type="audioAlbum", buffer_title=_("Album: {0}").format(i["title"],), parent_tab="audio_albums", loadable=True, kwargs=dict(parent=self.window.tb, name="{0}_audio_album".format(i["id"],), composefunc="render_audio", session=self.session, endpoint="get", parent_endpoint="audio", owner_id=user_id, album_id=i["id"])) + + def get_video_albums(self, user_id=None, create_buffers=True, force_action=False): + if self.session.settings["load_at_startup"]["video_albums"] == False and force_action == False: + return + log.debug("Create video albums...") + albums = self.session.vk.client.video.getAlbums(owner_id=user_id, count=100) + self.session.video_albums = albums["items"] + if create_buffers: + for i in albums["items"]: + pub.sendMessage("create_buffer", buffer_type="videoAlbum", buffer_title=_("Album: {0}").format(i["title"],), parent_tab="video_albums", loadable=True, kwargs=dict(parent=self.window.tb, name="{0}_video_album".format(i["id"],), composefunc="render_video", session=self.session, endpoint="get", parent_endpoint="video", count=self.session.settings["buffers"]["count_for_video_buffers"], user_id=user_id, album_id=i["id"])) + + def get_communities(self, user_id=None, create_buffers=True, force_action=False): + if self.session.settings["vk"]["invited_to_group"] == False: + self.session.settings["vk"]["invited_to_group"] = True + self.session.settings.write() + socializer_group = self.session.vk.client.groups.getById(group_ids="175825000")[0] + if socializer_group["is_member"] ==False: + d = commonMessages.join_group() + self.session.settings["vk"]["invited_to_group"] = True + self.session.settings.write() + if d == widgetUtils.YES: + result = self.session.vk.client.groups.join(group_id=socializer_group["id"]) + if result == 1: + commonMessages.group_joined() + else: + log.error("Invalid result when joining the Socializer's group: %d" % (result)) + if self.session.settings["load_at_startup"]["communities"] == False and force_action == False: + return + log.debug("Create community buffers...") + groups= self.session.vk.client.groups.get(user_id=user_id, extended=1, count=1000, fields="can_post,can_create_topic") + self.session.groups=groups["items"] + # Let's feed the local database cache with new groups coming from here. + data= dict(profiles=[], groups=self.session.groups) + self.session.process_usernames(data) + if create_buffers: + for i in self.session.groups: + self.session.db["group_info"][i["id"]*-1] = i + pub.sendMessage("create_buffer", buffer_type="communityBuffer", buffer_title=i["name"], parent_tab="communities", loadable=True, get_items=True, kwargs=dict(parent=self.window.tb, name="{0}_community".format(i["id"],), composefunc="render_status", session=self.session, endpoint="get", parent_endpoint="wall", extended=1, count=self.session.settings["buffers"]["count_for_wall_buffers"], owner_id=-1*i["id"])) + + + def login(self): + wx.CallAfter(self.window.change_status, _("Logging in VK")) + self.session.login() + wx.CallAfter(self.window.change_status, _("Ready")) + for i in self.buffers: + if hasattr(i, "get_items"): + # Translators: {0} will be replaced with the name of a buffer. + wx.CallAfter(self.window.change_status, _("Loading items for {0}").format(i.name,)) + i.get_items() + wx.CallAfter(self.window.change_status, _("Ready")) + self.create_unread_messages() + self.status_setter = RepeatingTimer(280, self.set_online) + self.status_setter.start() + self.set_online(notify=True) + self.get_audio_albums(self.session.user_id) + self.get_video_albums(self.session.user_id) + self.get_communities(self.session.user_id) + self.create_longpoll_thread() + + def create_longpoll_thread(self, notify=False): + try: + self.longpoll = longpollthread.worker(self.session) + self.longpoll.start() + if notify: + self.notify(message=_("Chat server reconnected")) + except ConnectionError: + pub.sendMessage("longpoll-read-timeout") + + def update_all_buffers(self): + log.debug("Updating buffers...") + self.get_audio_albums(self.session.user_id, create_buffers=False) + self.get_video_albums(self.session.user_id, create_buffers=False) + for i in self.buffers: + # Online friends buffer should not be updated, as chat LongPoll server already gives status about offline and online friends. + if hasattr(i, "get_items") and i.name != "online_friends": + i.get_items() + log.debug("Updated %s" % (i.name)) + else: + i.update_online() + + def reorder_buffer(self, buffer): + """ this puts the chat buffers at the top of the list when there are new incoming messages. + In order to do so, we search for the current buffer's tab, remove the page from the TreeCtrl (without destroying the associated tab) + and reinsert it as a new child of the chat buffer. + Lastly we ensure the user is focused in the same buffer than before.""" + buffer_window = self.window.search(buffer.name) + # If buffer window is already in the first position after chat, we should not do anything here because calculations for moving buffers are expensive. + if buffer_window == self.window.search("chats")+1: + return + # Gets buffer title so we don't have to generate it again in future. + buffer_title = self.window.get_buffer_text(buffer_window) + # Determine if the current buffer is the buffer receiving a new message. + if buffer == self.get_current_buffer(): + focused_buffer = True + else: + focused_buffer = False + # This call will not destroy the associated tab for the chat buffer, thus allowing us to readd it in other position. + self.window.remove_buffer_from_position(buffer_window) + self.window.insert_chat_buffer(buffer.tab, buffer_title, self.window.search("chats")+1) + # Let's manipulate focus so users will not notice the change in buffers. + if focused_buffer: + new_position = self.window.search(buffer.name) + self.window.change_buffer(new_position) + else: + new_position = self.window.search(self.get_current_buffer().name) + self.window.change_buffer(new_position) + + ### pubsub events + # All of these functions, except the first two, are responses to pubsub events. + def connect_pubsub_events(self): + log.debug("Connecting events to responses...") + pub.subscribe(self.in_post, "posted") + pub.subscribe(self.post_failed, "postFailed") + pub.subscribe(self.download, "download-file") + pub.subscribe(self.download_files, "download-files") + pub.subscribe(self.view_post, "open-post") + pub.subscribe(self.update_status_bar, "update-status-bar") + pub.subscribe(self.chat_from_id, "new-chat") + pub.subscribe(self.authorisation_failed, "authorisation-failed") + pub.subscribe(self.connection_error, "connection_error") + pub.subscribe(self.user_profile, "user-profile") + pub.subscribe(self.user_online, "user-online") + pub.subscribe(self.user_offline, "user-offline") + pub.subscribe(self.notify, "notify") + pub.subscribe(self.handle_longpoll_read_timeout, "longpoll-read-timeout") + pub.subscribe(self.create_buffer, "create_buffer") + pub.subscribe(self.user_typing, "user-typing") + pub.subscribe(self.edit_message, "edit-message") + pub.subscribe(self.get_chat, "order-sent-message") + pub.subscribe(self.create_timeline, "create-timeline") + pub.subscribe(self.api_error, "api-error") + + def disconnect_events(self): + log.debug("Disconnecting some events...") + pub.unsubscribe(self.in_post, "posted") + pub.unsubscribe(self.download, "download-file") + pub.unsubscribe(self.authorisation_failed, "authorisation-failed") + pub.unsubscribe(self.view_post, "open-post") + pub.unsubscribe(self.update_status_bar, "update-status-bar") + pub.unsubscribe(self.user_online, "user-online") + pub.unsubscribe(self.user_offline, "user-offline") + pub.unsubscribe(self.notify, "notify") + pub.subscribe(self.create_timeline, "create-timeline") + + def in_post(self, from_buffer=None): + if from_buffer != None and "_messages" not in from_buffer: + log.debug("Post received in buffer %s, updating... " % (from_buffer,)) + buffer = self.search(from_buffer) + buffer.get_items() + + def post_failed(self, parent_endpoint, child_endpoint, from_buffer=None, attachments_list=[], post_arguments={}): + """ Function to be called when the post (using the pubsub method) fails. It takes the same params than post() and use the parent and child endpoints to call the appropiate dialogs. """ + # Ask the user if he/she wants to attempt to post the same again. + msgdialog = commonMessages.post_failed() + if msgdialog != widgetUtils.YES: # Cancelled. + return + # Let's check which kind of post has failed, and do something about it. + if parent_endpoint == "wall": + if child_endpoint == "post": # A wall post has failed, so let's create it in a dialogue. + p = presenters.createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Write your post"), message="", text=post_arguments.get("message"))) + if hasattr(p, "text") or hasattr(p, "privacy"): + post_arguments.update(privacy=p.privacy, message=p.text) + if hasattr(p, "attachments"): + attachments_list = p.attachments + call_threaded(pub.sendMessage, "post", parent_endpoint=parent_endpoint, child_endpoint=child_endpoint, from_buffer=from_buffer, attachments_list=attachments_list, post_arguments=post_arguments) + elif child_endpoint == "repost": # repost + p = presenters.createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Repost"), message="", text=post_arguments.get("message"), mode="comment")) + if hasattr(p, "text") or hasattr(p, "privacy"): + post_arguments.update(message=p.text) + if hasattr(p, "attachments"): + attachments_list = p.attachments + call_threaded(pub.sendMessage, "post", parent_endpoint=parent_endpoint, child_endpoint=child_endpoint, from_buffer=from_buffer, attachments_list=attachments_list, post_arguments=post_arguments) + elif child_endpoint == "createComment": # comments. + p = presenters.createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Add a comment"), message="", text=post_arguments.get("message"), mode="comment")) + if hasattr(p, "text") or hasattr(p, "privacy"): + post_arguments.update(message=p.text) + if hasattr(p, "attachments"): + attachments_list = p.attachments + call_threaded(pub.sendMessage, "post", parent_endpoint=parent_endpoint, child_endpoint=child_endpoint, from_buffer=from_buffer, attachments_list=attachments_list, post_arguments=post_arguments) + elif parent_endpoint == "board": # topic creation and comments. + if child_endpoint == "addTopic": + p = presenters.createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createTopicDialog(title=_("Create topic"), message="", topic_title=post_arguments.get("title"), text=post_arguments.get("text"))) + if hasattr(p, "text") or hasattr(p, "privacy"): + post_arguments.update(title=p.view.title.GetValue(), text=p.text) + if hasattr(p, "attachments"): + attachments_list = p.attachments + call_threaded(pub.sendMessage, "post", parent_endpoint=parent_endpoint, child_endpoint=child_endpoint, from_buffer=from_buffer, attachments_list=attachments_list, post_arguments=post_arguments) + elif child_endpoint == "createComment": # topic comments. + p = presenters.createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Add a comment to the topic"), message="", text=post_arguments.get("message"), mode="comment")) + if hasattr(p, "text") or hasattr(p, "privacy"): + post_arguments.update(message=p.text) + if hasattr(p, "attachments"): + attachments_list = p.attachments + call_threaded(pub.sendMessage, "post", parent_endpoint=parent_endpoint, child_endpoint=child_endpoint, from_buffer=from_buffer, attachments_list=attachments_list, post_arguments=post_arguments) + elif parent_endpoint == "messages": # Private messages + if child_endpoint == "send": + buffer = self.search(from_buffer) + buffer_window = self.window.search(buffer.name) + self.window.change_buffer(buffer_window) + buffer.tab.text.SetValue(post_arguments.get("message")) + buffer.tab.text.SetFocus() + buffer.attachments_to_be_sent = attachments_list + + def api_error(self, code): + """ Display an understandable error dialog to users. """ + commonMessages.vk_error(code) + + def download(self, url, filename): + """ Download a file to te current user's computer. + @ url: The URl from where the file can be directly accessed. + @ filename: the current path to where the file will be saved. + The dowwload progress will be displayed in the status bar on the window. + """ + url = utils.transform_audio_url(url) + log.debug("downloading %s URL to %s filename" % (url, filename,)) + call_threaded(utils.download_file, url, filename) + + def download_files(self, downloads): + call_threaded(utils.download_files, downloads) + + def view_post(self, post_object, controller_, vars=dict()): + """ Display the passed post in the passed post presenter. + @ post_object dict: A post representation returned by the VK api. The fields present in this dict are different depending on the presenter used to render it. + @controller_ string: Name of the post controller, this name will be used for calling interactors, views and presenters. For example, displayPost, displayAudio, etc. + """ + p = getattr(presenters, controller_+"Presenter")(session=self.session, postObject=post_object, interactor=getattr(interactors, controller_+"Interactor")(), view=getattr(views, controller_)(), **vars) + + def update_status_bar(self, status): + """ Update the status bar present in the main Window. + @ status str: Text to be placed in the status bar. + """ + wx.CallAfter(self.window.change_status, status) + + def chat_from_id(self, user_id, setfocus=True, unread=False): + """ Create a conversation buffer for. + @ user_id: Vk user, chat or community ID to chat with. + @ setfocus boolean: If set to True, the buffer will receive focus automatically right after being created. + @ unread: if set to True, the last message of the buffer will be marked as unread + """ + log.debug("Received request to create buffer for conversation {0} with args of unread={1}, setfocus={2}".format(user_id, unread, setfocus)) + b = self.search_chat_buffer(user_id) + if b != None: + log.debug("Chat buffer found. Skipping...") + pos = self.window.search(b.name) + if setfocus: + self.window.change_buffer(pos) + return b.tab.text.SetFocus() + return + # Get name based in the ID. + # for users. + log.debug("Determining name for buffer...") + if user_id > 0 and user_id < 2000000000: + user = self.session.get_user(user_id, key="user1") + name = user["user1_nom"] + elif user_id > 2000000000: + chat = self.session.vk.client.messages.getChat(chat_id=user_id-2000000000) + name = chat["title"] + log.debug("Buffer name: {}".format(name,)) + elif user_id < -20000000: + app = self.session.vk.client.apps.get(id=user_id*-1) + log.debug(app) + name = app["items"][0]["title"] + pub.sendMessage("create_buffer", buffer_type="chatBuffer", buffer_title=name, parent_tab="chats", get_items=True, kwargs=dict(parent=self.window.tb, name="{0}_messages".format(user_id,), composefunc="render_message", parent_endpoint="messages", endpoint="getHistory", session=self.session, unread=unread, count=self.session.settings["buffers"]["count_for_chat_buffers"], peer_id=user_id, rev=0, extended=True, fields="id, user_id, date, read_state, out, body, attachments, deleted")) +# if setfocus: +# pos = self.window.search(buffer.name) +# self.window.change_buffer(pos) +# call_threaded(buffer.get_items, unread=unread) +# if setfocus: buffer.tab.text.SetFocus() +# return True + + def authorisation_failed(self): + """ display an informative message about a failed authorization process.""" + commonMessages.bad_authorisation() + restart.restart_program() + + def connection_error(self, *args, **kwargs): + commonMessages.connection_error() + self.disconnect_events() + volume = player.player.volume + config.app["sound"]["volume"] = volume + config.app.write() + self.window.Destroy() + wx.GetApp().ExitMainLoop() + + def user_profile(self, person): + """ display someone's profile. For now, only users are supported.""" + p = presenters.userProfilePresenter(session=self.session, user_id=person, view=views.userProfileDialog(), interactor=interactors.userProfileInteractor()) + + def user_online(self, event): + """ Add user to the online buffer and Send a notification of an user connecting to VK. + @ event vk_api.longpoll.event object: The event sent by the vk_api's longPoll module. + """ + if self.session.settings["chat"]["notify_online"] == True: + user_name = self.session.get_user(event.user_id) + msg = _("{user1_nom} is online.").format(**user_name) + sound = "friend_online.ogg" + self.notify(msg, sound, self.session.settings["chat"]["notifications"]) + online_buffer = self.search("online_friends") + user = None + for i in self.session.db["friends_"]["items"]: + if i["id"] == event.user_id: + user = i + user["last_seen"]["time"] = time.time() + break + if user == None: + log.exception("Getting user manually...") + user = self.session.vk.client.users.get(user_ids=event.user_id, fields="last_seen, can_post")[0] + wx.CallAfter(online_buffer.add_person, user) + + def user_offline(self, event): + """ Remove user from the online buffer and Send a notification of an user logging off in VK. + @ event vk_api.longpoll.event object: The event sent by the vk_api's longPoll module. + """ + if self.session.settings["chat"]["notify_offline"] == True: + user_name = self.session.get_user(event.user_id) + msg = _("{user1_nom} is offline.").format(**user_name) + sound = "friend_offline.ogg" + self.notify(msg, sound, self.session.settings["chat"]["notifications"]) + online_friends = self.search("online_friends") + wx.CallAfter(online_friends.remove_person, event.user_id) + + def notify(self, message="", sound="", type="native"): + """ display a notification in Socializer. + @message str: Message to display in the notification. + @sound str: sound file to play in the notification, if type is set to custom. + @type str: notification type: native or custom. + Native notifications are made with WX and don't have sound, while custom notifications have sound but are not displayed in the window. + """ + if type == "native": + wx.CallAfter(self.window.notify, _("Socializer"), message) + else: + if sound != "": + self.session.soundplayer.play(sound) + if message != "": + output.speak(message) + + def handle_longpoll_read_timeout(self): + """ This function tries to reconnect the long poll module until when it will get a successful connection. + Due to the way this method has been implemented, the function will be repeatedly called until it will connect properly. + """ + if hasattr(self, "longpoll"): + self.notify(message=_("Chat disconnected. Trying to connect in 60 seconds")) + time.sleep(60) + if hasattr(self, "longpoll"): + del self.longpoll + self.create_longpoll_thread(notify=True) + + @wx_call_after + def create_buffer(self, buffer_type="baseBuffer", buffer_title="", parent_tab=None, loadable=False, get_items=False, kwargs={}): + """ Create and insert a buffer in the specified place. + @buffer_type str: name of the buffer type to be created. This should be a class in the buffers.py module. + @buffer_title str: Buffer title to be used in the Treebook. + @parent_tab str or None: If set to None, the parent tab will be the root of the treebook. In all other cases, the parent tab will be searched in the treebook. + @loadable bool: If set to True, the new buffer will not be able to load contents until can_get_items will be set to True. + @get_items bool: If set to True, get_items will be called inmediately after creating the buffer. + """ + log.debug("Creating buffer of type {0} with parent_tab of {2} arguments {1}".format(buffer_type, kwargs, parent_tab)) + if not hasattr(buffers, buffer_type): + raise AttributeError("Specified buffer type does not exist: %s" % (buffer_type,)) + buffer = getattr(buffers, buffer_type)(**kwargs) + if loadable: + buffer.can_get_items = False + self.buffers.append(buffer) + if parent_tab == None: + log.debug("Appending buffer {}...".format(buffer,)) + self.window.add_buffer(buffer.tab, buffer_title) + else: + self.window.insert_buffer(buffer.tab, buffer_title, self.window.search(parent_tab)) + log.debug("Inserting buffer {0} into control {1}".format(buffer, self.window.search(parent_tab))) + if get_items: + call_threaded(buffer.get_items) + + def user_typing(self, obj): + """ Indicates when someone is typing. + @ event vk_api.longpoll.event object: The event sent by the vk_api's longPoll module. + """ + buffer = self.search_chat_buffer(obj.user_id) + if buffer != None and buffer == self.get_current_buffer() and self.is_focused(): + user = self.session.get_user(obj.user_id) + user1_nom = user["user1_nom"].split()[0] + output.speak(_("{user1_nom} is typing...").format(user1_nom=user1_nom)) + + def edit_message(self, obj): + print(vars(obj)) + + def get_chat(self, obj=None): + """ Searches or creates a chat buffer with the id of the user that is sending or receiving a message. + @obj vk_api.longpoll.EventType: an event wich defines some data from the vk's long poll server.""" + message = {} + uid = obj.peer_id + buffer = self.search_chat_buffer(uid) + if obj.from_me: + message.update(out=0) + # If there is no buffer, we must create one in a wxThread so it will not crash. + if buffer == None: + wx.CallAfter(self.chat_from_id, uid, setfocus=self.session.settings["chat"]["automove_to_conversations"], unread=True) + self.session.soundplayer.play("conversation_opened.ogg") + return + # If the chat already exists, let's create a dictionary wich will contains data of the received message. + message.update(id=obj.message_id, user_id=uid, date=obj.timestamp, body=utils.clean_text(obj.text), attachments=obj.attachments) + # if attachments is true or body contains at least an URL, let's request for the full message with attachments formatted in a better way. + # ToDo: code improvements. We shouldn't need to request the same message again just for these attachments. + if len(message["attachments"]) != 0 or len(utils.find_urls_in_text(message["body"])) != 0: + message_ids = message["id"] + results = self.session.vk.client.messages.getById(message_ids=message_ids) + message = results["items"][0] + if obj.from_me: + message["from_id"] = self.session.user_id + else: + message.update(read_state=0, out=0) + message["from_id"] = obj.user_id + data = [message] + # Let's add this to the buffer. + # ToDo: Clean this code and test how is the database working with this set to True. + buffer.session.db[buffer.name]["items"].append(message) + wx.CallAfter(buffer.insert, self.session.db[buffer.name]["items"][-1], False) + self.session.soundplayer.play("message_received.ogg") + wx.CallAfter(self.reorder_buffer, buffer) + # Check if we have to read the message aloud + if buffer == self.get_current_buffer(): + rendered_message = renderers.render_message(message, self.session) + output.speak(rendered_message[0]) + + def create_timeline(self, user_id, buffer_type, user=""): + if user_id == "": + user_data = self.session.vk.client.utils.resolveScreenName(screen_name=user) + if type(user_data) == list: + commonMessages.no_user_exist() + return + user_id = user_data["object_id"] + if buffer_type == "audio": + buffer = buffers.audioBuffer(parent=self.window.tb, name="{0}_audio".format(user_id,), composefunc="render_audio", session=self.session, create_tab=False, endpoint="get", parent_endpoint="audio", owner_id=user_id) + user = self.session.get_user(user_id, key="user1") + name_ = _("{user1_nom}'s audios").format(**user) + elif buffer_type == "wall": + buffer = buffers.feedBuffer(parent=self.window.tb, name="{0}_feed".format(user_id,), composefunc="render_status", session=self.session, create_tab=False, endpoint="get", parent_endpoint="wall", extended=1, count=self.session.settings["buffers"]["count_for_wall_buffers"], owner_id=user_id) + user = self.session.get_user(user_id, key="user1") + name_ = _("{user1_nom}'s posts").format(**user) + elif buffer_type == "video": + buffer = buffers.videoBuffer(parent=self.window.tb, name="{0}_video".format(user_id,), composefunc="render_video", session=self.session, create_tab=False, endpoint="get", parent_endpoint="video", owner_id=user_id, count=self.session.settings["buffers"]["count_for_video_buffers"]) + user = self.session.get_user(user_id, key="user1") + name_ = _("{user1_nom}'s videos").format(**user) + elif buffer_type == "friends": + buffer = buffers.peopleBuffer(parent=self.window.tb, name="friends_{0}".format(user_id,), composefunc="render_person", session=self.session, create_tab=False, endpoint="get", parent_endpoint="friends", count=5000, fields="uid, first_name, last_name, last_seen, can_post, can_write_private_message", user_id=user_id) + user = self.session.get_user(user_id, key="user1") + name_ = _("{user1_nom}'s friends").format(**user) + wx.CallAfter(self.complete_buffer_creation, buffer=buffer, name_=name_, position=self.window.search("timelines")) + + ### GUI events + # These functions are connected to GUI elements such as menus, buttons and so on. + def connect_gui_events(self): + widgetUtils.connectExitFunction(self.exit_) + widgetUtils.connect_event(self.window, widgetUtils.CLOSE_EVENT, self.exit) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.update_buffer, menuitem=self.window.update_buffer) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.check_for_updates, menuitem=self.window.check_for_updates) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.on_about, menuitem=self.window.about) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.search_audios, menuitem=self.window.search_audios) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.search_videos, menuitem=self.window.search_videos) + widgetUtils.connect_event(self.window, widgetUtils.MENU,self.remove_buffer, menuitem=self.window.remove_buffer_) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.get_more_items, menuitem=self.window.load_previous_items) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.changelog, menuitem=self.window.changelog) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.open_logs, menuitem=self.window.open_logs) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.open_config, menuitem=self.window.open_config) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.blacklist, menuitem=self.window.blacklist) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.manage_accounts, menuitem=self.window.accounts) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.configuration, menuitem=self.window.settings_dialog) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.new_timeline, menuitem=self.window.timeline) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.create_audio_album, menuitem=self.window.audio_album) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.delete_audio_album, menuitem=self.window.delete_audio_album) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.create_video_album, menuitem=self.window.video_album) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.delete_video_album, menuitem=self.window.delete_video_album) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.check_documentation, menuitem=self.window.documentation) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.menu_play_pause, menuitem=self.window.player_play) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.menu_play_next, menuitem=self.window.player_next) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.menu_play_previous, menuitem=self.window.player_previous) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.menu_play_all, menuitem=self.window.player_play_all) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.seek_left, menuitem=self.window.player_seek_left) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.seek_right, menuitem=self.window.player_seek_right) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.menu_volume_down, menuitem=self.window.player_volume_down) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.menu_volume_up, menuitem=self.window.player_volume_up) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.menu_mute, menuitem=self.window.player_mute) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.view_my_profile, menuitem=self.window.view_profile) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.view_my_profile_in_browser, menuitem=self.window.open_in_browser) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.set_status, menuitem=self.window.set_status) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.on_report_error, menuitem=self.window.report) + self.window.tb.Bind(wx.EVT_CONTEXT_MENU, self.on_context_menu) + + def exit(self, *args, **kwargs): + answer = commonMessages.exit() + if answer == widgetUtils.YES: + self.exit_() + + def exit_(self, *args, **kwargs): + """ Try to set offline in the current user's profile at VK, then closes the application. """ + log.debug("Receibed an exit signal. closing...") + self.set_offline() + self.disconnect_events() + volume = player.player.volume + config.app["sound"]["volume"] = volume + config.app.write() + self.window.Destroy() + wx.GetApp().ExitMainLoop() + + def update_buffer(self, *args, **kwargs): + """ Update the current buffer, getting the recent items.""" + b = self.get_current_buffer() + b.get_items() + + def check_for_updates(self, *args, **kwargs): + update = updater.do_update(update_type=self.session.settings["general"]["update_channel"]) + if update == False: + commonMessages.no_update_available() + + def on_about(self, *args, **kwargs): + channel = self.session.settings["general"]["update_channel"] + self.window.about_dialog(channel) + + def search_audios(self, *args, **kwargs): + dlg = searchDialogs.searchAudioDialog() + if dlg.get_response() == widgetUtils.OK: + q = dlg.get("term") + auto_complete = True + count = 300 + performer_only = dlg.get_state("title") + sort = dlg.get_sort_order() + newbuff = buffers.audioBuffer(parent=self.window.tb, name="{0}_audiosearch".format(q,), session=self.session, composefunc="render_audio", parent_endpoint="audio", endpoint="search", q=q, auto_complete=auto_complete, count=count, performer_only=performer_only, sort=sort) + self.buffers.append(newbuff) + call_threaded(newbuff.get_items) + # Translators: {0} will be replaced with the search term. + self.window.insert_buffer(newbuff.tab, _("Search for {0}").format(q,), self.window.search("audios")) + + def search_videos(self, *args, **kwargs): + dlg = searchDialogs.searchVideoDialog() + if dlg.get_response() == widgetUtils.OK: + params = {} + params["q"] = dlg.get("term") + params["count"] = 200 + hd = dlg.get_checkable("hd") + if hd != 0: + params["hd"] = 1 + params["adult"] = dlg.get_checkable("safe_search") + params["sort"] = dlg.get_sort_order() +# params["filters"] = "youtube, vimeo, short, long, mp4" +# print(params) + newbuff = buffers.videoBuffer(parent=self.window.tb, name="{0}_videosearch".format(params["q"],), session=self.session, composefunc="render_video", parent_endpoint="video", endpoint="search", **params) + self.buffers.append(newbuff) + call_threaded(newbuff.get_items) + # Translators: {0} will be replaced with the search term. + self.window.insert_buffer(newbuff.tab, _("Search for {0}").format(params["q"],), self.window.search("videos")) + + def remove_buffer(self, event, mandatory=False, *args, **kwargs): + buffer = self.get_current_buffer() + buff = self.window.search(buffer.name) + answer = buffer.remove_buffer(mandatory) + if answer == False: + return + self.window.remove_buffer(buff) + self.buffers.remove(buffer) + del buffer + + def get_more_items(self, *args, **kwargs): + b = self.get_current_buffer() + b.get_more_items() + + def changelog(self, *args, **kwargs): + lang = localization.get("documentation") + os.chdir("documentation/%s" % (lang,)) + webbrowser.open("changelog.html") + os.chdir("../../") + + def configuration(self, *args, **kwargs): + """ Opens the global settings dialogue.""" + presenter = presenters.configurationPresenter(session=self.session, view=views.configurationDialog(title=_("Preferences")), interactor=interactors.configurationInteractor()) + + def blacklist(self, *args, **kwargs): + """ Opens the blacklist presenter.""" + presenter = presenters.blacklistPresenter(session=self.session, view=views.blacklistDialog(), interactor=interactors.blacklistInteractor()) + + def manage_accounts(self, *args, **kwargs): + accounts = sessionManager.sessionManagerController(starting=False) + accounts.view.get_response() + if hasattr(accounts, "modified"): + restart_msg = commonMessages.restart_program() + if restart_msg == widgetUtils.YES: + restart.restart_program() + + def open_logs(self, *args, **kwargs): + subprocess.call(["explorer", paths.logs_path()]) + + def open_config(self, *args, **kwargs): + subprocess.call(["explorer", paths.config_path()]) + + def new_timeline(self, *args, **kwargs): + b = self.get_current_buffer() + # If executing this method from an empty buffer we should get the newsfeed buffer. + if not hasattr(b, "get_users"): + b = self.search("home_timeline") + # Get a list of (id, user) objects. + d = [] + for i in self.session.db["users"]: + d.append((i, self.session.get_user(i)["user1_gen"])) + # Do the same for communities. + for i in self.session.db["groups"]: + d.append((-i, self.session.get_user(-i)["user1_nom"])) + a = timeline.timelineDialog([i[1] for i in d]) + if a.get_response() == widgetUtils.OK: + user = a.get_user() + buffertype = a.get_buffer_type() + user_id = "" + for i in d: + if i[1] == user: + user_id = i[0] + pub.sendMessage("create-timeline", user_id=user_id, buffer_type=buffertype) + + def create_audio_album(self, *args, **kwargs): + d = creation.audio_album() + if d.get_response() == widgetUtils.OK and d.get("title") != "": + response = self.session.vk.client.audio.createPlaylist(owner_id=self.session.user_id, title=d.get("title")) + if "id" not in response: + return + album_id = response["id"] + buffer = buffers.audioAlbum(parent=self.window.tb, name="{0}_audio_album".format(album_id,), composefunc="render_audio", session=self.session, endpoint="get", parent_endpoint="audio", full_list=True, count=self.session.settings["buffers"]["count_for_audio_buffers"], user_id=self.session.user_id, album_id=album_id) + buffer.can_get_items = False + # Translators: {0} will be replaced with an audio album's title. + name_ = _("Album: {0}").format(d.get("title"),) + self.buffers.append(buffer) + self.window.insert_buffer(buffer.tab, name_, self.window.search("albums")) + buffer.get_items() + self.get_audio_albums(user_id=self.session.user_id, create_buffers=False) + + def delete_audio_album(self, *args, **kwargs): + if len(self.session.audio_albums) == 0: + return commonMessages.no_audio_albums() + answer = selector.album(_("Select the album you want to delete"), self.session) + if answer.item == None: + return + response = commonMessages.delete_audio_album() + if response != widgetUtils.YES: return + removal = self.session.vk.client.audio.deletePlaylist(playlist_id=answer.item, owner_id=self.session.user_id) + if removal == 1: + buffer = self.search("{0}_audio_album".format(answer.item,)) + buff = self.window.search(buffer.name) + self.window.remove_buffer(buff) + self.buffers.remove(buffer) + del buffer + self.get_audio_albums(user_id=self.session.user_id, create_buffers=False) + + def create_video_album(self, *args, **kwargs): + d = creation.audio_album() + if d.get_response() == widgetUtils.OK and d.get("title") != "": + response = self.session.vk.client.video.addAlbum(title=d.get("title")) + if ("album_id" in response) == False: return + album_id = response["album_id"] + buffer = buffers.videoAlbum(parent=self.window.tb, name="{0}_video_album".format(album_id,), composefunc="render_video", session=self.session, endpoint="get", parent_endpoint="video", count=self.session.settings["buffers"]["count_for_video_buffers"], user_id=self.session.user_id, album_id=album_id) + buffer.can_get_items = False + # Translators: {0} will be replaced with a video album's title. + name_ = _("Album: {0}").format(d.get("title"),) + self.buffers.append(buffer) + self.window.insert_buffer(buffer.tab, name_, self.window.search("video_albums")) + buffer.get_items() + self.session.video_albums = self.session.vk.client.video.getAlbums(owner_id=self.session.user_id)["items"] + + def delete_video_album(self, *args, **kwargs): + if len(self.session.video_albums) == 0: + return commonMessages.no_video_albums() + answer = selector.album(_("Select the album you want to delete"), self.session, "video_albums") + if answer.item == None: + return + response = commonMessages.delete_audio_album() + if response != widgetUtils.YES: return + removal = self.session.vk.client.video.deleteAlbum(album_id=answer.item) + buffer = self.search("{0}_video_album".format(answer.item,)) + buff = self.window.search(buffer.name) + self.window.remove_buffer(buff) + self.buffers.remove(buffer) + del buffer + self.session.video_albums = self.session.vk.client.video.getAlbums(owner_id=self.session.user_id)["items"] + + def check_documentation(self, *args, **kwargs): + lang = localization.get("documentation") + os.chdir("documentation/%s" % (lang,)) + webbrowser.open("manual.html") + os.chdir("../../") + + def menu_play_pause(self, *args, **kwargs): + if player.player.stream != None: + return player.player.pause() + else: + b = self.get_current_buffer() + if hasattr(b, "play_all"): + b.play_all() + else: + self.search("me_audio").play_all() + + def menu_play_next(self, *args, **kwargs): + pub.sendMessage("play-next") + + def menu_play_previous(self, *args, **kwargs): + pub.sendMessage("play-previous") + + def menu_play_all(self, *args, **kwargs): + b = self.get_current_buffer() + if hasattr(b, "play_all"): + b.play_all() + else: + self.search("me_audio").play_all() + + def menu_volume_down(self, *args, **kwargs): + if player.player != None: + player.player.volume = player.player.volume-2 + + def menu_volume_up(self, *args, **kwargs): + if player.player != None: + player.player.volume = player.player.volume+2 + + def menu_mute(self, *args, **kwargs): + if player.player != None: + player.player.volume = 0 + + def seek_left(self, *args, **kwargs): + pub.sendMessage("seek", ms=-500000) + + def seek_right(self, *args, **kwargs): + pub.sendMessage("seek", ms=500000) + + def view_my_profile(self, *args, **kwargs): + self.user_profile(self.session.user_id) + + def view_my_profile_in_browser(self, *args, **kwargs): + webbrowser.open_new_tab("https://vk.com/id{id}".format(id=self.session.user_id,)) + + def set_status(self, *args, **kwargs): + dlg = wx.TextEntryDialog(self.window, _("Write your status message"), _("Set status")) + if dlg.ShowModal() == widgetUtils.OK: + result = dlg.GetValue() + info = self.session.vk.client.account.saveProfileInfo(status=result) + commonMessages.updated_status() + dlg.Destroy() + + def on_report_error(self, *args, **kwargs): + r = issueReporter.reportBug() + + def on_context_menu(self, event, *args, **kwargs): + """ Handles context menu event in the tree buffers.""" + # If the focus is not in the TreeCtrl of the Treebook, then we should not display any menu. + if isinstance(self.window.FindFocus(), wx.TreeCtrl) == False: + event.Skip() + return + menu = None + # Get the current buffer and let's choose a different menu depending on the selected buffer. + current_buffer = self.get_current_buffer() + # Deal with menu for community buffers. + if current_buffer.name.endswith("_community"): + menu = menus.communityBufferMenu() + # disable post loading if the community has already loaded posts. + if current_buffer.can_get_items: + menu.load_posts.Enable(False) + # Disable loading of audios, videos, documents or topics depending in two conditions. + # 1. If the buffer already exists, which means they are already loaded, or + # 2. If the group_info does not have counters for such items, which would indicate there are no items posted yet. + if self.search(current_buffer.name+"_audios") != False: + menu.load_audios.Enable(False) + elif "counters" in self.session.db["group_info"][current_buffer.group_id] and "audios" not in self.session.db["group_info"][current_buffer.group_id]["counters"]: + menu.load_audios.Enable(False) + if self.search(current_buffer.name+"_videos") != False: + menu.load_videos.Enable(False) + elif "counters" in self.session.db["group_info"][current_buffer.group_id] and "videos" not in self.session.db["group_info"][current_buffer.group_id]["counters"]: + menu.load_videos.Enable(False) + if self.search(current_buffer.name+"_topics") != False: + menu.load_topics.Enable(False) + elif "counters" in self.session.db["group_info"][current_buffer.group_id] and "topics" not in self.session.db["group_info"][current_buffer.group_id]["counters"]: + menu.load_topics.Enable(False) + if self.search(current_buffer.name+"_documents") != False: + menu.load_documents.Enable(False) + elif "counters" in self.session.db["group_info"][current_buffer.group_id] and "docs" not in self.session.db["group_info"][current_buffer.group_id]["counters"]: + menu.load_documents.Enable(False) + # Connect the rest of the functions. + print(self.session.db["group_info"][current_buffer.group_id]) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_community_posts, menuitem=menu.load_posts) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_community_topics, menuitem=menu.load_topics) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_community_members, menuitem=menu.load_members) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_community_audios, menuitem=menu.load_audios) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_community_videos, menuitem=menu.load_videos) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_community_documents, menuitem=menu.load_documents) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.open_community_in_browser, menuitem=menu.open_in_browser) + # Deal with the communities section itself. + elif current_buffer.name == "communities": + menu = wx.Menu() + # Insert a different option depending if group buffers are loaded or scheduled to be loaded or not. + if self.session.settings["load_at_startup"]["communities"] == False and not hasattr(self.session, "groups"): + option = menu.Append(wx.NewId(), _("Load groups")) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_community_buffers, menuitem=option) + else: + option = menu.Append(wx.NewId(), _("Discard groups")) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.unload_community_buffers, menuitem=option) + # Deal with video and audio albums' sections. + elif current_buffer.name == "audio_albums": + menu = wx.Menu() + if self.session.settings["load_at_startup"]["audio_albums"] == False and not hasattr(self.session, "audio_albums"): + option = menu.Append(wx.NewId(), _("Load audio albums")) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_audio_album_buffers, menuitem=option) + else: + option = menu.Append(wx.NewId(), _("Discard audio albums")) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.unload_audio_album_buffers, menuitem=option) + elif current_buffer.name == "video_albums": + menu = wx.Menu() + if self.session.settings["load_at_startup"]["video_albums"] == False and not hasattr(self.session, "video_albums"): + option = menu.Append(wx.NewId(), _("Load video albums")) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_video_album_buffers, menuitem=option) + else: + option = menu.Append(wx.NewId(), _("Discard video albums")) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.unload_video_album_buffers, menuitem=option) + elif current_buffer.name.endswith("_messages"): + menu = menus.conversationBufferMenu() + widgetUtils.connect_event(menu, widgetUtils.MENU, self.delete_conversation, menuitem=menu.delete) + widgetUtils.connect_event(menu, widgetUtils.MENU, current_buffer.open_in_browser, menuitem=menu.open_in_browser) + if menu != None: + self.window.PopupMenu(menu, self.window.FindFocus().GetPosition()) + # If there are no available menus, let's indicate it. + else: + output.speak(_("menu unavailable for this buffer.")) + + def load_community_posts(self, *args, **kwargs): + """ Load community posts. It just calls to the needed method in the community buffer.""" + current_buffer = self.get_current_buffer() + if current_buffer.name.endswith("_community"): + current_buffer.load_community() + + def load_community_audios(self, *args, **kwargs): + """ Load community audios if they are not loaded already.""" + current_buffer = self.get_current_buffer() + # Get group_info if the community buffer does not have it already, so future menus will be able to use it. + if current_buffer.group_id not in self.session.db["group_info"] or "counters" not in self.session.db["group_info"][current_buffer.group_id]: + group_info = self.session.vk.client.groups.getById(group_ids=-1*current_buffer.kwargs["owner_id"], fields="counters,can_create_topics,can_post")[0] + self.session.db["group_info"][current_buffer.kwargs["owner_id"]].update(group_info) + if "audios" not in self.session.db["group_info"][current_buffer.group_id]["counters"]: + commonMessages.community_no_items() + return + new_name = current_buffer.name+"_audios" + pub.sendMessage("create_buffer", buffer_type="audioBuffer", buffer_title=_("Audios"), parent_tab=current_buffer.tab.name, get_items=True, kwargs=dict(parent=self.window.tb, name=new_name, composefunc="render_audio", session=self.session, endpoint="get", parent_endpoint="audio", owner_id=current_buffer.kwargs["owner_id"])) + + def load_community_videos(self, *args, **kwargs): + """ Load community videos if they are not loaded already.""" + current_buffer = self.get_current_buffer() + # Get group_info if the community buffer does not have it already, so future menus will be able to use it. + if current_buffer.group_id not in self.session.db["group_info"] or "counters" not in self.session.db["group_info"][current_buffer.group_id]: + group_info = self.session.vk.client.groups.getById(group_ids=-1*current_buffer.kwargs["owner_id"], fields="counters,can_create_topics,can_post")[0] + self.session.db["group_info"][current_buffer.kwargs["owner_id"]].update(group_info) + if "videos" not in self.session.db["group_info"][current_buffer.group_id]["counters"]: + commonMessages.community_no_items() + return + new_name = current_buffer.name+"_videos" + pub.sendMessage("create_buffer", buffer_type="videoBuffer", buffer_title=_("Videos"), parent_tab=current_buffer.tab.name, get_items=True, kwargs=dict(parent=self.window.tb, name=new_name, composefunc="render_video", session=self.session, endpoint="get", parent_endpoint="video", count=self.session.settings["buffers"]["count_for_video_buffers"], owner_id=current_buffer.kwargs["owner_id"])) + + def load_community_topics(self, *args, **kwargs): + """ Load community topics.""" + current_buffer = self.get_current_buffer() + # Get group_info if the community buffer does not have it already, so future menus will be able to use it. + if current_buffer.group_id not in self.session.db["group_info"] or "counters" not in self.session.db["group_info"][current_buffer.group_id]: + group_info = self.session.vk.client.groups.getById(group_ids=-1*current_buffer.kwargs["owner_id"], fields="counters,can_create_topic,can_post")[0] + self.session.db["group_info"][current_buffer.kwargs["owner_id"]].update(group_info) + if "topics" not in self.session.db["group_info"][current_buffer.group_id]["counters"]: + commonMessages.community_no_items() + return + new_name = current_buffer.name+"_topics" + pub.sendMessage("create_buffer", buffer_type="topicBuffer", buffer_title=_("Topics"), parent_tab=current_buffer.tab.name, get_items=True, kwargs=dict(parent=self.window.tb, name=new_name, composefunc="render_topic", session=self.session, endpoint="getTopics", parent_endpoint="board", count=100, group_id=-1*current_buffer.kwargs["owner_id"], extended=1)) + + def load_community_members(self, *args, **kwargs): + """ Load community members. """ + current_buffer = self.get_current_buffer() + # Get group_info if the community buffer does not have it already, so future menus will be able to use it. + if current_buffer.group_id not in self.session.db["group_info"] or "counters" not in self.session.db["group_info"][current_buffer.group_id]: + group_info = self.session.vk.client.groups.getById(group_ids=-1*current_buffer.kwargs["owner_id"], fields="counters,can_create_topic,can_post")[0] + self.session.db["group_info"][current_buffer.kwargs["owner_id"]].update(group_info) + # Determine whether we can request ordering by time descending or not. + if (self.session.db["group_info"][current_buffer.group_id].get("is_admin") != None and self.session.db["group_info"][current_buffer.group_id].get("is_admin") == 1): + sorting = "time_desc" + else: + sorting = "id_desc" + # Apparently, only administrators in a community are able to see invited users on it, despite users can invite the amount of friends they want. + # ToDo: This needs testing in groups where the current user is not a full admin (such as moderator or editor). + if (self.session.db["group_info"][current_buffer.group_id].get("is_admin") != None and self.session.db["group_info"][current_buffer.group_id].get("is_admin") == 1): + pub.sendMessage("create_buffer", buffer_type="emptyBuffer", buffer_title=_("People"), parent_tab=current_buffer.tab.name, kwargs=dict(parent=self.window.tb, name=current_buffer.tab.name+"_people")) + pub.sendMessage("create_buffer", buffer_type="communityPeopleBuffer", buffer_title=_("Members"), parent_tab=current_buffer.name+"_people", get_items=True, kwargs=dict(parent=self.window.tb, name=current_buffer.name+"_members", composefunc="render_person", session=self.session, endpoint="getMembers", parent_endpoint="groups", count=1000, order=sorting, fields="uid, first_name, last_name, last_seen, can_post", group_id=-1*current_buffer.kwargs["owner_id"])) + pub.sendMessage("create_buffer", buffer_type="communityPeopleBuffer", buffer_title=_("Invited users"), parent_tab=current_buffer.name+"_people", get_items=True, kwargs=dict(parent=self.window.tb, name=current_buffer.name+"_invites", composefunc="render_person", session=self.session, endpoint="getInvitedUsers", parent_endpoint="groups", count=1000, fields="first_name, last_name, last_seen, can_post, can_write_private_message", group_id=-1*current_buffer.kwargs["owner_id"])) + else: # Create this for non administrators. + pub.sendMessage("create_buffer", buffer_type="communityPeopleBuffer", buffer_title=_("Members"), parent_tab=current_buffer.tab.name, get_items=True, kwargs=dict(parent=self.window.tb, name=current_buffer.name+"_members", composefunc="render_person", session=self.session, endpoint="getMembers", parent_endpoint="groups", count=1000, order=sorting, fields="uid, first_name, last_name, last_seen, can_post, can_write_private_message", group_id=-1*current_buffer.kwargs["owner_id"])) + + def load_community_documents(self, *args, **kwargs): + current_buffer = self.get_current_buffer() + # Get group_info if the community buffer does not have it already, so future menus will be able to use it. + if current_buffer.group_id not in self.session.db["group_info"] or "counters" not in self.session.db["group_info"][current_buffer.group_id]: + group_info = self.session.vk.client.groups.getById(group_ids=-1*current_buffer.kwargs["owner_id"], fields="counters,can_create_topics,can_post")[0] + self.session.db["group_info"][current_buffer.kwargs["owner_id"]].update(group_info) + if "docs" not in self.session.db["group_info"][current_buffer.group_id]["counters"]: + commonMessages.community_no_items() + return + new_name = current_buffer.name+"_documents" + pub.sendMessage("create_buffer", buffer_type="documentCommunityBuffer", buffer_title=_("Documents"), parent_tab=current_buffer.tab.name, get_items=True, kwargs=dict(parent=self.window.tb, name=new_name, composefunc="render_document", session=self.session, endpoint="get", parent_endpoint="docs", owner_id=current_buffer.kwargs["owner_id"])) + + def open_community_in_browser(self, *args, **kwargs): + current_buffer = self.get_current_buffer() + if current_buffer.name.endswith("_community"): + webbrowser.open_new_tab("https://vk.com/club{0}".format(-1*current_buffer.kwargs["owner_id"])) + + def load_community_buffers(self, *args, **kwargs): + """ Load all community buffers regardless of the setting present in optional buffers tab of the preferences dialog.""" + call_threaded(self.get_communities, self.session.user_id, force_action=True) + + def unload_community_buffers(self, *args, **kwargs): + """ Delete all buffers belonging to groups.""" + communities = self.get_all_buffers("_community") + for buffer in communities: + buff = self.window.search(buffer.name) + self.window.remove_buffer(buff) + self.buffers.remove(buffer) + del self.session.groups + + def load_audio_album_buffers(self, *args, **kwargs): + """ Load all audio album buffers regardless of the setting present in optional buffers tab of the preferences dialog.""" + call_threaded(self.get_audio_albums, self.session.user_id, force_action=True) + + def unload_audio_album_buffers(self, *args, **kwargs): + """ Delete all buffers belonging to audio albums.""" + albums = self.get_all_buffers("_audio_album") + for buffer in albums: + buff = self.window.search(buffer.name) + self.window.remove_buffer(buff) + self.buffers.remove(buffer) + del self.session.audio_albums + + def load_video_album_buffers(self, *args, **kwargs): + """ Load all video album buffers regardless of the setting present in optional buffers tab of the preferences dialog.""" + call_threaded(self.get_video_albums, self.session.user_id, force_action=True) + + def unload_video_album_buffers(self, *args, **kwargs): + """ Delete all buffers belonging to video albums.""" + albums = self.get_all_buffers("_video_album") + for buffer in albums: + buff = self.window.search(buffer.name) + self.window.remove_buffer(buff) + self.buffers.remove(buffer) + del self.session.video_albums + + def delete_conversation(self, *args, **kwargs): + current_buffer = self.get_current_buffer() + d = commonMessages.delete_conversation() + if d == widgetUtils.YES: + results = self.session.vk.client.messages.deleteConversation(peer_id=current_buffer.kwargs["peer_id"]) + buff = self.window.search(current_buffer.name) + self.window.remove_buffer(buff) + self.buffers.remove(current_buffer) diff --git a/src/controller/selector.py b/src/controller/selector.py index daec451..71ee613 100644 --- a/src/controller/selector.py +++ b/src/controller/selector.py @@ -4,24 +4,23 @@ from wxUI.dialogs import selector as gui class album(object): - def __init__(self, title, session, album_type="audio_albums"): - super(album, self).__init__() - self.item = None - self.session = session - if not hasattr(self.session, album_type): - return - self.albums = getattr(self.session, album_type) - self.dialog = gui.selectAlbum(title=title, albums=self.get_albums_as_string()) - response = self.dialog.get_response() - if response == widgetUtils.OK: - self.item = self.search_item(self.dialog.get_string()) + def __init__(self, title, session, album_type="audio_albums"): + super(album, self).__init__() + self.item = None + self.session = session + if not hasattr(self.session, album_type): + return + self.albums = getattr(self.session, album_type) + self.dialog = gui.selectAlbum(title=title, albums=self.get_albums_as_string()) + response = self.dialog.get_response() + if response == widgetUtils.OK: + self.item = self.search_item(self.dialog.get_string()) - def get_albums_as_string(self): - return [i["title"] for i in self.albums] - - def search_item(self, item): - for i in self.albums: - if i["title"] == item: - return i["id"] - return None + def get_albums_as_string(self): + return [i["title"] for i in self.albums] + def search_item(self, item): + for i in self.albums: + if i["title"] == item: + return i["id"] + return None diff --git a/src/extra/SpellChecker/__init__.py b/src/extra/SpellChecker/__init__.py index f1eb69d..cf12053 100644 --- a/src/extra/SpellChecker/__init__.py +++ b/src/extra/SpellChecker/__init__.py @@ -3,4 +3,4 @@ from __future__ import unicode_literals from . import spellchecker import platform if platform.system() == "Windows": - from .wx_ui import * \ No newline at end of file + from .wx_ui import * diff --git a/src/extra/SpellChecker/spellchecker.py b/src/extra/SpellChecker/spellchecker.py index 19882b5..8837a47 100644 --- a/src/extra/SpellChecker/spellchecker.py +++ b/src/extra/SpellChecker/spellchecker.py @@ -15,62 +15,62 @@ from enchant import tokenize log = logging.getLogger("extra.SpellChecker.spellChecker") class spellChecker(object): - def __init__(self, text): - super(spellChecker, self).__init__() - self.active = True - try: - if config.app["app-settings"]["language"] == "system": - log.debug("Using the system language") - self.dict = enchant.DictWithPWL(languageHandler.curLang[:2], os.path.join(paths.config_path(), "wordlist.dict")) - else: - log.debug("Using language: %s" % (languageHandler.getLanguage(),)) - self.dict = enchant.DictWithPWL(languageHandler.getLanguage()[:2], os.path.join(paths.config_path(), "wordlist.dict")) - except DictNotFoundError: - log.exception("Dictionary for language %s not found." % (languageHandler.getLanguage(),)) - wx_ui.dict_not_found_error() - self.active = False - self.checker = SpellChecker(self.dict, filters=[twitterFilter.TwitterFilter, tokenize.EmailFilter, tokenize.URLFilter]) - self.checker.set_text(text) - if self.active == True: - log.debug("Creating dialog...") - self.dialog = wx_ui.spellCheckerDialog() - widgetUtils.connect_event(self.dialog.ignore, widgetUtils.BUTTON_PRESSED, self.ignore) - widgetUtils.connect_event(self.dialog.ignoreAll, widgetUtils.BUTTON_PRESSED, self.ignoreAll) - widgetUtils.connect_event(self.dialog.replace, widgetUtils.BUTTON_PRESSED, self.replace) - widgetUtils.connect_event(self.dialog.replaceAll, widgetUtils.BUTTON_PRESSED, self.replaceAll) - widgetUtils.connect_event(self.dialog.add, widgetUtils.BUTTON_PRESSED, self.add) - self.check() - self.dialog.get_response() - self.fixed_text = self.checker.get_text() + def __init__(self, text): + super(spellChecker, self).__init__() + self.active = True + try: + if config.app["app-settings"]["language"] == "system": + log.debug("Using the system language") + self.dict = enchant.DictWithPWL(languageHandler.curLang[:2], os.path.join(paths.config_path(), "wordlist.dict")) + else: + log.debug("Using language: %s" % (languageHandler.getLanguage(),)) + self.dict = enchant.DictWithPWL(languageHandler.getLanguage()[:2], os.path.join(paths.config_path(), "wordlist.dict")) + except DictNotFoundError: + log.exception("Dictionary for language %s not found." % (languageHandler.getLanguage(),)) + wx_ui.dict_not_found_error() + self.active = False + self.checker = SpellChecker(self.dict, filters=[twitterFilter.TwitterFilter, tokenize.EmailFilter, tokenize.URLFilter]) + self.checker.set_text(text) + if self.active == True: + log.debug("Creating dialog...") + self.dialog = wx_ui.spellCheckerDialog() + widgetUtils.connect_event(self.dialog.ignore, widgetUtils.BUTTON_PRESSED, self.ignore) + widgetUtils.connect_event(self.dialog.ignoreAll, widgetUtils.BUTTON_PRESSED, self.ignoreAll) + widgetUtils.connect_event(self.dialog.replace, widgetUtils.BUTTON_PRESSED, self.replace) + widgetUtils.connect_event(self.dialog.replaceAll, widgetUtils.BUTTON_PRESSED, self.replaceAll) + widgetUtils.connect_event(self.dialog.add, widgetUtils.BUTTON_PRESSED, self.add) + self.check() + self.dialog.get_response() + self.fixed_text = self.checker.get_text() - def check(self): - try: - next(self.checker) - textToSay = _(u"Misspelled word: %s") % (self.checker.word,) - context = u"... %s %s %s" % (self.checker.leading_context(10), self.checker.word, self.checker.trailing_context(10)) - self.dialog.set_title(textToSay) - output.speak(textToSay) - self.dialog.set_word_and_suggestions(word=self.checker.word, context=context, suggestions=self.checker.suggest()) - except StopIteration: - log.debug("Process finished.") - wx_ui.finished() - self.dialog.Destroy() + def check(self): + try: + next(self.checker) + textToSay = _(u"Misspelled word: %s") % (self.checker.word,) + context = u"... %s %s %s" % (self.checker.leading_context(10), self.checker.word, self.checker.trailing_context(10)) + self.dialog.set_title(textToSay) + output.speak(textToSay) + self.dialog.set_word_and_suggestions(word=self.checker.word, context=context, suggestions=self.checker.suggest()) + except StopIteration: + log.debug("Process finished.") + wx_ui.finished() + self.dialog.Destroy() - def ignore(self, ev): - self.check() + def ignore(self, ev): + self.check() - def ignoreAll(self, ev): - self.checker.ignore_always(word=self.checker.word) - self.check() + def ignoreAll(self, ev): + self.checker.ignore_always(word=self.checker.word) + self.check() - def replace(self, ev): - self.checker.replace(self.dialog.get_selected_suggestion()) - self.check() + def replace(self, ev): + self.checker.replace(self.dialog.get_selected_suggestion()) + self.check() - def replaceAll(self, ev): - self.checker.replace_always(self.dialog.get_selected_suggestion()) - self.check() + def replaceAll(self, ev): + self.checker.replace_always(self.dialog.get_selected_suggestion()) + self.check() - def add(self, ev): - self.checker.add() - self.check() + def add(self, ev): + self.checker.add() + self.check() diff --git a/src/extra/SpellChecker/wx_ui.py b/src/extra/SpellChecker/wx_ui.py index 3a13e9f..a116835 100644 --- a/src/extra/SpellChecker/wx_ui.py +++ b/src/extra/SpellChecker/wx_ui.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- ############################################################ # Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo -# +# # 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 @@ -21,63 +21,63 @@ import wx import application class spellCheckerDialog(wx.Dialog): - def __init__(self): - super(spellCheckerDialog, self).__init__(None, 1) - panel = wx.Panel(self) - sizer = wx.BoxSizer(wx.VERTICAL) - word = wx.StaticText(panel, -1, _(u"Misspelled word")) - self.word = wx.TextCtrl(panel, -1) - wordBox = wx.BoxSizer(wx.HORIZONTAL) - wordBox.Add(word, 0, wx.ALL, 5) - wordBox.Add(self.word, 0, wx.ALL, 5) - context = wx.StaticText(panel, -1, _(u"Context")) - self.context = wx.TextCtrl(panel, -1) - contextBox = wx.BoxSizer(wx.HORIZONTAL) - contextBox.Add(context, 0, wx.ALL, 5) - contextBox.Add(self.context, 0, wx.ALL, 5) - suggest = wx.StaticText(panel, -1, _(u"Suggestions")) - self.suggestions = wx.ListBox(panel, -1, choices=[], style=wx.LB_SINGLE) - suggestionsBox = wx.BoxSizer(wx.HORIZONTAL) - suggestionsBox.Add(suggest, 0, wx.ALL, 5) - suggestionsBox.Add(self.suggestions, 0, wx.ALL, 5) - self.ignore = wx.Button(panel, -1, _(u"&Ignore")) - self.ignoreAll = wx.Button(panel, -1, _(u"I&gnore all")) - self.replace = wx.Button(panel, -1, _(u"&Replace")) - self.replaceAll = wx.Button(panel, -1, _(u"R&eplace all")) - self.add = wx.Button(panel, -1, _(u"&Add to personal dictionary")) - close = wx.Button(panel, wx.ID_CANCEL) - btnBox = wx.BoxSizer(wx.HORIZONTAL) - btnBox.Add(self.ignore, 0, wx.ALL, 5) - btnBox.Add(self.ignoreAll, 0, wx.ALL, 5) - btnBox.Add(self.replace, 0, wx.ALL, 5) - btnBox.Add(self.replaceAll, 0, wx.ALL, 5) - btnBox.Add(self.add, 0, wx.ALL, 5) - btnBox.Add(close, 0, wx.ALL, 5) - sizer.Add(wordBox, 0, wx.ALL, 5) - sizer.Add(contextBox, 0, wx.ALL, 5) - sizer.Add(suggestionsBox, 0, wx.ALL, 5) - sizer.Add(btnBox, 0, wx.ALL, 5) - panel.SetSizer(sizer) - self.SetClientSize(sizer.CalcMin()) + def __init__(self): + super(spellCheckerDialog, self).__init__(None, 1) + panel = wx.Panel(self) + sizer = wx.BoxSizer(wx.VERTICAL) + word = wx.StaticText(panel, -1, _(u"Misspelled word")) + self.word = wx.TextCtrl(panel, -1) + wordBox = wx.BoxSizer(wx.HORIZONTAL) + wordBox.Add(word, 0, wx.ALL, 5) + wordBox.Add(self.word, 0, wx.ALL, 5) + context = wx.StaticText(panel, -1, _(u"Context")) + self.context = wx.TextCtrl(panel, -1) + contextBox = wx.BoxSizer(wx.HORIZONTAL) + contextBox.Add(context, 0, wx.ALL, 5) + contextBox.Add(self.context, 0, wx.ALL, 5) + suggest = wx.StaticText(panel, -1, _(u"Suggestions")) + self.suggestions = wx.ListBox(panel, -1, choices=[], style=wx.LB_SINGLE) + suggestionsBox = wx.BoxSizer(wx.HORIZONTAL) + suggestionsBox.Add(suggest, 0, wx.ALL, 5) + suggestionsBox.Add(self.suggestions, 0, wx.ALL, 5) + self.ignore = wx.Button(panel, -1, _(u"&Ignore")) + self.ignoreAll = wx.Button(panel, -1, _(u"I&gnore all")) + self.replace = wx.Button(panel, -1, _(u"&Replace")) + self.replaceAll = wx.Button(panel, -1, _(u"R&eplace all")) + self.add = wx.Button(panel, -1, _(u"&Add to personal dictionary")) + close = wx.Button(panel, wx.ID_CANCEL) + btnBox = wx.BoxSizer(wx.HORIZONTAL) + btnBox.Add(self.ignore, 0, wx.ALL, 5) + btnBox.Add(self.ignoreAll, 0, wx.ALL, 5) + btnBox.Add(self.replace, 0, wx.ALL, 5) + btnBox.Add(self.replaceAll, 0, wx.ALL, 5) + btnBox.Add(self.add, 0, wx.ALL, 5) + btnBox.Add(close, 0, wx.ALL, 5) + sizer.Add(wordBox, 0, wx.ALL, 5) + sizer.Add(contextBox, 0, wx.ALL, 5) + sizer.Add(suggestionsBox, 0, wx.ALL, 5) + sizer.Add(btnBox, 0, wx.ALL, 5) + panel.SetSizer(sizer) + self.SetClientSize(sizer.CalcMin()) - def get_response(self): - return self.ShowModal() + def get_response(self): + return self.ShowModal() - def set_title(self, title): - return self.SetTitle(title) + def set_title(self, title): + return self.SetTitle(title) - def set_word_and_suggestions(self, word, context, suggestions): - self.word.SetValue(word) - self.context.ChangeValue(context) - self.suggestions.Set(suggestions) - self.suggestions.SetFocus() + def set_word_and_suggestions(self, word, context, suggestions): + self.word.SetValue(word) + self.context.ChangeValue(context) + self.suggestions.Set(suggestions) + self.suggestions.SetFocus() - def get_selected_suggestion(self): - return self.suggestions.GetStringSelection() + def get_selected_suggestion(self): + return self.suggestions.GetStringSelection() def dict_not_found_error(): - wx.MessageDialog(None, _(u"An error has occurred. There are no dictionaries available for the selected language in {0}").format(application.name,), _(u"Error"), wx.ICON_ERROR).ShowModal() + wx.MessageDialog(None, _(u"An error has occurred. There are no dictionaries available for the selected language in {0}").format(application.name,), _(u"Error"), wx.ICON_ERROR).ShowModal() def finished(): - wx.MessageDialog(None, _(u"Spell check complete."), application.name, style=wx.OK).ShowModal() + wx.MessageDialog(None, _(u"Spell check complete."), application.name, style=wx.OK).ShowModal() diff --git a/src/extra/translator/__init__.py b/src/extra/translator/__init__.py index 70d57ae..60c593a 100644 --- a/src/extra/translator/__init__.py +++ b/src/extra/translator/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- import platform if platform.system() == "Windows": - from . import wx_ui as gui -from . import translator \ No newline at end of file + from . import wx_ui as gui +from . import translator diff --git a/src/extra/translator/translator.py b/src/extra/translator/translator.py index ae08a4e..9afa61e 100644 --- a/src/extra/translator/translator.py +++ b/src/extra/translator/translator.py @@ -9,12 +9,12 @@ log = logging.getLogger("extras.translator") t = None def translate(text="", target="en"): - global t - log.debug("Received translation request for language %s, text=%s" % (target, text)) - if t == None: - t = Translator() - vars = dict(text=text, dest=target) - return t.translate(**vars).text + global t + log.debug("Received translation request for language %s, text=%s" % (target, text)) + if t == None: + t = Translator() + vars = dict(text=text, dest=target) + return t.translate(**vars).text supported_langs = None @@ -113,4 +113,4 @@ languages = { } def available_languages(): - return dict(sorted(languages.items(), key=lambda x: x[1])) + return dict(sorted(languages.items(), key=lambda x: x[1])) diff --git a/src/extra/translator/wx_ui.py b/src/extra/translator/wx_ui.py index 0586a05..8e9a08a 100644 --- a/src/extra/translator/wx_ui.py +++ b/src/extra/translator/wx_ui.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- ############################################################ # Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo -# +# # 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 @@ -21,25 +21,25 @@ import wx from widgetUtils import BaseDialog class translateDialog(BaseDialog): - def __init__(self): - languages = [] - language_dict = translator.available_languages() - for k in language_dict: - languages.append(language_dict[k]) - super(translateDialog, self).__init__(None, -1, title=_(u"Translate message")) - panel = wx.Panel(self) - sizer = wx.BoxSizer(wx.VERTICAL) - staticDest = wx.StaticText(panel, -1, _(u"Target language")) - self.dest_lang = wx.ComboBox(panel, -1, choices=languages, style = wx.CB_READONLY) - self.dest_lang.SetFocus() - self.dest_lang.SetSelection(0) - listSizer = wx.BoxSizer(wx.HORIZONTAL) - listSizer.Add(staticDest) - listSizer.Add(self.dest_lang) - ok = wx.Button(panel, wx.ID_OK) - ok.SetDefault() - cancel = wx.Button(panel, wx.ID_CANCEL) - self.SetEscapeId(wx.ID_CANCEL) + def __init__(self): + languages = [] + language_dict = translator.available_languages() + for k in language_dict: + languages.append(language_dict[k]) + super(translateDialog, self).__init__(None, -1, title=_(u"Translate message")) + panel = wx.Panel(self) + sizer = wx.BoxSizer(wx.VERTICAL) + staticDest = wx.StaticText(panel, -1, _(u"Target language")) + self.dest_lang = wx.ComboBox(panel, -1, choices=languages, style = wx.CB_READONLY) + self.dest_lang.SetFocus() + self.dest_lang.SetSelection(0) + listSizer = wx.BoxSizer(wx.HORIZONTAL) + listSizer.Add(staticDest) + listSizer.Add(self.dest_lang) + ok = wx.Button(panel, wx.ID_OK) + ok.SetDefault() + cancel = wx.Button(panel, wx.ID_CANCEL) + self.SetEscapeId(wx.ID_CANCEL) - def get(self, control): - return getattr(self, control).GetSelection() \ No newline at end of file + def get(self, control): + return getattr(self, control).GetSelection() diff --git a/src/fixes/__init__.py b/src/fixes/__init__.py index 05d0851..ebe08f5 100644 --- a/src/fixes/__init__.py +++ b/src/fixes/__init__.py @@ -8,7 +8,7 @@ from . import fix_win32com from . import fix_libloader def setup(): - fix_requests.fix() -# if hasattr(sys, "frozen"): - fix_libloader.fix() - fix_win32com.fix() \ No newline at end of file + fix_requests.fix() +# if hasattr(sys, "frozen"): + fix_libloader.fix() + fix_win32com.fix() diff --git a/src/fixes/fix_libloader.py b/src/fixes/fix_libloader.py index 7878814..c73fae7 100644 --- a/src/fixes/fix_libloader.py +++ b/src/fixes/fix_libloader.py @@ -12,25 +12,25 @@ from libloader import com fixed=False def patched_getmodule(modname): - mod=__import__(modname) - return sys.modules[modname] + mod=__import__(modname) + return sys.modules[modname] def load_com(*names): - global fixed - if fixed==False: - gencache._GetModule=patched_getmodule - com.prepare_gencache() - fixed=True - result = None - for name in names: - try: - result = gencache.EnsureDispatch(name) - break - except com_error: - continue - if result is None: - raise com_error("Unable to load any of the provided com objects.") - return result + global fixed + if fixed==False: + gencache._GetModule=patched_getmodule + com.prepare_gencache() + fixed=True + result = None + for name in names: + try: + result = gencache.EnsureDispatch(name) + break + except com_error: + continue + if result is None: + raise com_error("Unable to load any of the provided com objects.") + return result def fix(): - com.load_com = load_com \ No newline at end of file + com.load_com = load_com diff --git a/src/fixes/fix_requests.py b/src/fixes/fix_requests.py index a0c4d3f..2925ef2 100644 --- a/src/fixes/fix_requests.py +++ b/src/fixes/fix_requests.py @@ -7,6 +7,6 @@ import logging log = logging.getLogger("fixes.fix_requests") def fix(): - log.debug("Applying fix for requests...") - os.environ["REQUESTS_CA_BUNDLE"] = os.path.join(paths.app_path(), "cacert.pem")#.encode(paths.fsencoding) -# log.debug("Changed CA path to %s" % (os.environ["REQUESTS_CA_BUNDLE"]))#.decode(paths.fsencoding))) \ No newline at end of file + log.debug("Applying fix for requests...") + os.environ["REQUESTS_CA_BUNDLE"] = os.path.join(paths.app_path(), "cacert.pem")#.encode(paths.fsencoding) +# log.debug("Changed CA path to %s" % (os.environ["REQUESTS_CA_BUNDLE"]))#.decode(paths.fsencoding))) diff --git a/src/fixes/fix_win32com.py b/src/fixes/fix_win32com.py index a135c90..bce0611 100644 --- a/src/fixes/fix_win32com.py +++ b/src/fixes/fix_win32com.py @@ -1,6 +1,6 @@ from __future__ import unicode_literals import win32com.client def fix(): - if win32com.client.gencache.is_readonly == True: - win32com.client.gencache.is_readonly = False - win32com.client.gencache.Rebuild() \ No newline at end of file + if win32com.client.gencache.is_readonly == True: + win32com.client.gencache.is_readonly = False + win32com.client.gencache.Rebuild() diff --git a/src/interactors/__init__.py b/src/interactors/__init__.py index dff7153..fefa07c 100644 --- a/src/interactors/__init__.py +++ b/src/interactors/__init__.py @@ -5,4 +5,4 @@ from . blacklist import * from .configuration import * from .postCreation import * from .postDisplayer import * -from .profiles import * \ No newline at end of file +from .profiles import * diff --git a/src/interactors/attach.py b/src/interactors/attach.py index f7061e6..171ccd1 100644 --- a/src/interactors/attach.py +++ b/src/interactors/attach.py @@ -8,86 +8,86 @@ from . import base class attachInteractor(base.baseInteractor): - def insert_attachment(self, attachment): - self.view.attachments.insert_item(False, *attachment) + def insert_attachment(self, attachment): + self.view.attachments.insert_item(False, *attachment) - def remove_attachment(self, attachment): - self.view.attachments.remove_item(attachment) + def remove_attachment(self, attachment): + self.view.attachments.remove_item(attachment) - def install(self, *args, **kwargs): - super(attachInteractor, self).install(*args, **kwargs) - widgetUtils.connect_event(self.view.photo, widgetUtils.BUTTON_PRESSED, self.on_image) - widgetUtils.connect_event(self.view.audio, widgetUtils.BUTTON_PRESSED, self.on_audio) - widgetUtils.connect_event(self.view.document, widgetUtils.BUTTON_PRESSED, self.on_document) - if hasattr(self.view, "voice_message"): - widgetUtils.connect_event(self.view.voice_message, widgetUtils.BUTTON_PRESSED, self.on_upload_voice_message) - widgetUtils.connect_event(self.view.remove, widgetUtils.BUTTON_PRESSED, self.on_remove_attachment) - pub.subscribe(self.insert_attachment, self.modulename+"_insert_attachment") - pub.subscribe(self.remove_attachment, self.modulename+"_remove_attachment") + def install(self, *args, **kwargs): + super(attachInteractor, self).install(*args, **kwargs) + widgetUtils.connect_event(self.view.photo, widgetUtils.BUTTON_PRESSED, self.on_image) + widgetUtils.connect_event(self.view.audio, widgetUtils.BUTTON_PRESSED, self.on_audio) + widgetUtils.connect_event(self.view.document, widgetUtils.BUTTON_PRESSED, self.on_document) + if hasattr(self.view, "voice_message"): + widgetUtils.connect_event(self.view.voice_message, widgetUtils.BUTTON_PRESSED, self.on_upload_voice_message) + widgetUtils.connect_event(self.view.remove, widgetUtils.BUTTON_PRESSED, self.on_remove_attachment) + pub.subscribe(self.insert_attachment, self.modulename+"_insert_attachment") + pub.subscribe(self.remove_attachment, self.modulename+"_remove_attachment") - def uninstall(self): - super(attachInteractor, self).uninstall() - pub.unsubscribe(self.insert_attachment, self.modulename+"_insert_attachment") - pub.unsubscribe(self.remove_attachment, self.modulename+"_remove_attachment") + def uninstall(self): + super(attachInteractor, self).uninstall() + pub.unsubscribe(self.insert_attachment, self.modulename+"_insert_attachment") + pub.unsubscribe(self.remove_attachment, self.modulename+"_remove_attachment") - def on_image(self, *args, **kwargs): - """ display menu for adding image attachments. """ - m = attachMenu() - # disable add from VK as it is not supported in images, yet. - m.add.Enable(False) - widgetUtils.connect_event(m, widgetUtils.MENU, self.on_upload_image, menuitem=m.upload) - self.view.PopupMenu(m, self.view.photo.GetPosition()) + def on_image(self, *args, **kwargs): + """ display menu for adding image attachments. """ + m = attachMenu() + # disable add from VK as it is not supported in images, yet. + m.add.Enable(False) + widgetUtils.connect_event(m, widgetUtils.MENU, self.on_upload_image, menuitem=m.upload) + self.view.PopupMenu(m, self.view.photo.GetPosition()) - def on_audio(self, *args, **kwargs): - """ display menu to add audio attachments.""" - m = attachMenu() - widgetUtils.connect_event(m, widgetUtils.MENU, self.on_upload_audio, menuitem=m.upload) - widgetUtils.connect_event(m, widgetUtils.MENU, self.on_add_audio, menuitem=m.add) - self.view.PopupMenu(m, self.view.audio.GetPosition()) + def on_audio(self, *args, **kwargs): + """ display menu to add audio attachments.""" + m = attachMenu() + widgetUtils.connect_event(m, widgetUtils.MENU, self.on_upload_audio, menuitem=m.upload) + widgetUtils.connect_event(m, widgetUtils.MENU, self.on_add_audio, menuitem=m.add) + self.view.PopupMenu(m, self.view.audio.GetPosition()) - def on_document(self, *args, **kwargs): - """ display menu for adding document attachments. """ - m = attachMenu() - # disable add from VK as it is not supported in documents, yet. - m.add.Enable(False) - widgetUtils.connect_event(m, widgetUtils.MENU, self.on_upload_document, menuitem=m.upload) - self.view.PopupMenu(m, self.view.photo.GetPosition()) + def on_document(self, *args, **kwargs): + """ display menu for adding document attachments. """ + m = attachMenu() + # disable add from VK as it is not supported in documents, yet. + m.add.Enable(False) + widgetUtils.connect_event(m, widgetUtils.MENU, self.on_upload_document, menuitem=m.upload) + self.view.PopupMenu(m, self.view.photo.GetPosition()) - def on_upload_image(self, *args, **kwargs): - """ allows uploading an image from the computer. - """ - image, description = self.view.get_image() - if image != None: - self.presenter.upload_image(image, description) + def on_upload_image(self, *args, **kwargs): + """ allows uploading an image from the computer. + """ + image, description = self.view.get_image() + if image != None: + self.presenter.upload_image(image, description) - def on_upload_audio(self, *args, **kwargs): - """ Allows uploading an audio file from the computer. Only mp3 files are supported. """ - audio = self.view.get_audio() - if audio != None: - self.presenter.upload_audio(audio) + def on_upload_audio(self, *args, **kwargs): + """ Allows uploading an audio file from the computer. Only mp3 files are supported. """ + audio = self.view.get_audio() + if audio != None: + self.presenter.upload_audio(audio) - def on_upload_document(self, *args, **kwargs): - """ allows uploading a document from the computer. - """ - document = self.view.get_document() - if document != None: - if document.endswith(".mp3") or document.endswith(".exe"): - self.view.invalid_attachment() - return - self.presenter.upload_document(document) + def on_upload_document(self, *args, **kwargs): + """ allows uploading a document from the computer. + """ + document = self.view.get_document() + if document != None: + if document.endswith(".mp3") or document.endswith(".exe"): + self.view.invalid_attachment() + return + self.presenter.upload_document(document) - def on_upload_voice_message(self, *args, **kwargs): - self.presenter.upload_voice_message() + def on_upload_voice_message(self, *args, **kwargs): + self.presenter.upload_voice_message() - def on_add_audio(self, *args, **kwargs): - """ Allow adding an audio directly from the user's audio library.""" - audios = self.presenter.get_available_audios() - select = selector.selectAttachment(_("Select the audio files you want to send"), audios) - if select.get_response() == widgetUtils.OK and select.attachments.GetCount() > 0: - attachments = select.get_all_attachments() - self.presenter.take_audios(attachments) + def on_add_audio(self, *args, **kwargs): + """ Allow adding an audio directly from the user's audio library.""" + audios = self.presenter.get_available_audios() + select = selector.selectAttachment(_("Select the audio files you want to send"), audios) + if select.get_response() == widgetUtils.OK and select.attachments.GetCount() > 0: + attachments = select.get_all_attachments() + self.presenter.take_audios(attachments) - def on_remove_attachment(self, *args, **kwargs): - """ Remove the currently focused item from the attachments list.""" - current_item = self.view.attachments.get_selected() - self.presenter.remove_attachment(current_item) \ No newline at end of file + def on_remove_attachment(self, *args, **kwargs): + """ Remove the currently focused item from the attachments list.""" + current_item = self.view.attachments.get_selected() + self.presenter.remove_attachment(current_item) diff --git a/src/interactors/audioRecorder.py b/src/interactors/audioRecorder.py index 83b7406..8c2ec4b 100644 --- a/src/interactors/audioRecorder.py +++ b/src/interactors/audioRecorder.py @@ -5,25 +5,25 @@ from pubsub import pub from . import base class audioRecorderInteractor(base.baseInteractor): - def install(self, presenter, view, modulename="audiorecorder"): - super(audioRecorderInteractor, self).install(view=view, presenter=presenter, modulename=modulename) - widgetUtils.connect_event(view.play, widgetUtils.BUTTON_PRESSED, self.on_play) - widgetUtils.connect_event(view.record, widgetUtils.BUTTON_PRESSED, self.on_record) - widgetUtils.connect_event(view.discard, widgetUtils.BUTTON_PRESSED, self.on_discard) + def install(self, presenter, view, modulename="audiorecorder"): + super(audioRecorderInteractor, self).install(view=view, presenter=presenter, modulename=modulename) + widgetUtils.connect_event(view.play, widgetUtils.BUTTON_PRESSED, self.on_play) + widgetUtils.connect_event(view.record, widgetUtils.BUTTON_PRESSED, self.on_record) + widgetUtils.connect_event(view.discard, widgetUtils.BUTTON_PRESSED, self.on_discard) - def start(self): - result = self.view.get_response() - if result == widgetUtils.OK: - self.on_postprocess() + def start(self): + result = self.view.get_response() + if result == widgetUtils.OK: + self.on_postprocess() - def on_record(self, *args, **kwargs): - self.presenter.toggle_recording() + def on_record(self, *args, **kwargs): + self.presenter.toggle_recording() - def on_discard(self, *args, **kwargs): - self.presenter.discard_recording() + def on_discard(self, *args, **kwargs): + self.presenter.discard_recording() - def on_play(self, *args, **kwargs): - self.presenter.play() + def on_play(self, *args, **kwargs): + self.presenter.play() - def on_postprocess(self): - self.presenter.postprocess() \ No newline at end of file + def on_postprocess(self): + self.presenter.postprocess() diff --git a/src/interactors/base.py b/src/interactors/base.py index 169292a..091a16b 100644 --- a/src/interactors/base.py +++ b/src/interactors/base.py @@ -3,38 +3,38 @@ from pubsub import pub class baseInteractor(object): - def install(self, view, presenter, modulename): - self.modulename = modulename - self.view = view - self.presenter = presenter - pub.subscribe(self.disable_control, "{modulename}_disable_control".format(modulename=modulename)) - pub.subscribe(self.enable_control, "{modulename}_enable_control".format(modulename=modulename)) - pub.subscribe(self.set_label, "{modulename}_set_label".format(modulename=modulename)) - pub.subscribe(self.focus_control, "{modulename}_focus_control".format(modulename=modulename)) - pub.subscribe(self.set_title, "{modulename}_set_title".format(modulename=modulename)) + def install(self, view, presenter, modulename): + self.modulename = modulename + self.view = view + self.presenter = presenter + pub.subscribe(self.disable_control, "{modulename}_disable_control".format(modulename=modulename)) + pub.subscribe(self.enable_control, "{modulename}_enable_control".format(modulename=modulename)) + pub.subscribe(self.set_label, "{modulename}_set_label".format(modulename=modulename)) + pub.subscribe(self.focus_control, "{modulename}_focus_control".format(modulename=modulename)) + pub.subscribe(self.set_title, "{modulename}_set_title".format(modulename=modulename)) - def uninstall(self): - pub.unsubscribe(self.disable_control, "{modulename}_disable_control".format(modulename=self.modulename)) - pub.unsubscribe(self.enable_control, "{modulename}_enable_control".format(modulename=self.modulename)) - pub.unsubscribe(self.set_label, "{modulename}_set_label".format(modulename=self.modulename)) - pub.unsubscribe(self.focus_control, "{modulename}_focus_control".format(modulename=self.modulename)) - pub.unsubscribe(self.set_title, "{modulename}_set_title".format(modulename=self.modulename)) - self.view.Destroy() + def uninstall(self): + pub.unsubscribe(self.disable_control, "{modulename}_disable_control".format(modulename=self.modulename)) + pub.unsubscribe(self.enable_control, "{modulename}_enable_control".format(modulename=self.modulename)) + pub.unsubscribe(self.set_label, "{modulename}_set_label".format(modulename=self.modulename)) + pub.unsubscribe(self.focus_control, "{modulename}_focus_control".format(modulename=self.modulename)) + pub.unsubscribe(self.set_title, "{modulename}_set_title".format(modulename=self.modulename)) + self.view.Destroy() - def start(self): - self.result = self.view.get_response() + def start(self): + self.result = self.view.get_response() - def disable_control(self, control): - self.view.disable(control) + def disable_control(self, control): + self.view.disable(control) - def enable_control(self, control): - self.view.enable(control) + def enable_control(self, control): + self.view.enable(control) - def focus_control(self, control): - getattr(self.view, control).SetFocus() + def focus_control(self, control): + getattr(self.view, control).SetFocus() - def set_label(self, control, label): - self.view.set(control, label) + def set_label(self, control, label): + self.view.set(control, label) - def set_title(self, value): - self.view.SetTitle(value) \ No newline at end of file + def set_title(self, value): + self.view.SetTitle(value) diff --git a/src/interactors/blacklist.py b/src/interactors/blacklist.py index 912e4eb..9be84e6 100644 --- a/src/interactors/blacklist.py +++ b/src/interactors/blacklist.py @@ -6,26 +6,26 @@ from . import base class blacklistInteractor(base.baseInteractor): - def add_items(self, control, items): - if not hasattr(self.view, control): - raise AttributeError("The control is not present in the view.") - for i in items: - getattr(self.view, control).insert_item(False, *i) + def add_items(self, control, items): + if not hasattr(self.view, control): + raise AttributeError("The control is not present in the view.") + for i in items: + getattr(self.view, control).insert_item(False, *i) - def install(self, *args, **kwargs): - super(blacklistInteractor, self).install(*args, **kwargs) - widgetUtils.connect_event(self.view.unblock, widgetUtils.BUTTON_PRESSED, self.on_unblock) - pub.subscribe(self.add_items, self.modulename+"_add_items") + def install(self, *args, **kwargs): + super(blacklistInteractor, self).install(*args, **kwargs) + widgetUtils.connect_event(self.view.unblock, widgetUtils.BUTTON_PRESSED, self.on_unblock) + pub.subscribe(self.add_items, self.modulename+"_add_items") - def uninstall(self): - super(blacklistInteractor, self).uninstall() - pub.unsubscribe(self.add_items, self.modulename+"_add_items") + def uninstall(self): + super(blacklistInteractor, self).uninstall() + pub.unsubscribe(self.add_items, self.modulename+"_add_items") - def on_unblock(self, *args, **kwargs): - question = commonMessages.unblock_person() - if question == widgetUtils.NO: - return - item = self.view.persons.get_selected() - if self.presenter.unblock_person(item) == 1: - self.view.persons.remove_item(item) + def on_unblock(self, *args, **kwargs): + question = commonMessages.unblock_person() + if question == widgetUtils.NO: + return + item = self.view.persons.get_selected() + if self.presenter.unblock_person(item) == 1: + self.view.persons.remove_item(item) diff --git a/src/interactors/configuration.py b/src/interactors/configuration.py index fc164dd..67a54ef 100644 --- a/src/interactors/configuration.py +++ b/src/interactors/configuration.py @@ -6,67 +6,67 @@ from . import base class configurationInteractor(base.baseInteractor): - def create_tab(self, tab, arglist=dict()): - getattr(self.view, "create_"+tab)(**arglist) + def create_tab(self, tab, arglist=dict()): + getattr(self.view, "create_"+tab)(**arglist) - def set_setting(self, tab, setting, value): - self.view.set_value(tab, setting, value) + def set_setting(self, tab, setting, value): + self.view.set_value(tab, setting, value) - def restart(self): - dlg = restart_program_dialog() - if dlg == widgetUtils.YES: - self.presenter.restart_application() + def restart(self): + dlg = restart_program_dialog() + if dlg == widgetUtils.YES: + self.presenter.restart_application() - def set_language(self, language): - self.view.general.language.SetSelection(language) + def set_language(self, language): + self.view.general.language.SetSelection(language) - def install(self, *args, **kwargs): - super(configurationInteractor, self).install(*args, **kwargs) - pub.subscribe(self.create_tab, self.modulename+"_create_tab") - pub.subscribe(self.set_setting, self.modulename+"_set") - pub.subscribe(self.restart, self.modulename+"_restart_program") - pub.subscribe(self.set_language, self.modulename+"_set_language") + def install(self, *args, **kwargs): + super(configurationInteractor, self).install(*args, **kwargs) + pub.subscribe(self.create_tab, self.modulename+"_create_tab") + pub.subscribe(self.set_setting, self.modulename+"_set") + pub.subscribe(self.restart, self.modulename+"_restart_program") + pub.subscribe(self.set_language, self.modulename+"_set_language") - def uninstall(self): - super(configurationInteractor, self).uninstall() - pub.unsubscribe(self.create_tab, self.modulename+"_create_tab") - pub.unsubscribe(self.set_setting, self.modulename+"_set") - pub.unsubscribe(self.restart, self.modulename+"_restart_program") - pub.unsubscribe(self.set_language, self.modulename+"_set_language") + def uninstall(self): + super(configurationInteractor, self).uninstall() + pub.unsubscribe(self.create_tab, self.modulename+"_create_tab") + pub.unsubscribe(self.set_setting, self.modulename+"_set") + pub.unsubscribe(self.restart, self.modulename+"_restart_program") + pub.unsubscribe(self.set_language, self.modulename+"_set_language") - def start(self): - self.view.realize() - result = self.view.get_response() - if result == widgetUtils.OK: - self.on_save_settings() + def start(self): + self.view.realize() + result = self.view.get_response() + if result == widgetUtils.OK: + self.on_save_settings() - def on_save_settings(self, *args, **kwargs): - self.presenter.update_setting(section="buffers", setting="count_for_wall_buffers", value=self.view.get_value("buffers", "wall_buffer_count")) - self.presenter.update_setting(section="buffers", setting="count_for_video_buffers", value=self.view.get_value("buffers", "video_buffers_count")) - self.presenter.update_setting(section="buffers", setting="count_for_chat_buffers", value=self.view.get_value("buffers", "chat_buffers_count")) - self.presenter.update_setting(section="general", setting="load_images", value=self.view.get_value("general", "load_images")) - update_channel = self.presenter.get_update_channel_type(self.view.get_value("general", "update_channel")) - if update_channel != self.presenter.session.settings["general"]["update_channel"]: - if update_channel == "stable": - self.presenter.update_setting(section="general", setting="update_channel", value=update_channel) - elif update_channel == "weekly": - dialog = self.view.weekly_channel() - if dialog == widgetUtils.YES: - self.presenter.update_setting(section="general", setting="update_channel", value=update_channel) - elif update_channel == "alpha": - dialog = self.view.alpha_channel() - if dialog == widgetUtils.YES: - self.presenter.update_setting(section="general", setting="update_channel", value=update_channel) - self.presenter.update_setting(section="chat", setting="notify_online", value=self.view.get_value("chat", "notify_online")) - self.presenter.update_setting(section="chat", setting="notify_offline", value=self.view.get_value("chat", "notify_offline")) - self.presenter.update_setting(section="chat", setting="notifications", value=self.presenter.get_notification_type(self.view.get_value("chat", "notifications"))) - self.presenter.update_setting(section="load_at_startup", setting="audio_albums", value=self.view.get_value("startup", "audio_albums")) - self.presenter.update_setting(section="load_at_startup", setting="video_albums", value=self.view.get_value("startup", "video_albums")) - self.presenter.update_setting(section="load_at_startup", setting="communities", value=self.view.get_value("startup", "communities")) - self.presenter.update_app_setting(section="app-settings", setting="language", value=self.presenter.codes[self.view.general.language.GetSelection()]) - self.presenter.update_app_setting(section="sound", setting="input_device", value=self.view.get_value("sound", "input")) - self.presenter.update_app_setting(section="sound", setting="output_device", value=self.view.get_value("sound", "output")) - self.presenter.update_app_setting(section="app-settings", setting="use_proxy", value=self.view.get_value("general", "use_proxy")) - self.presenter.update_app_setting(section="app-settings", setting="debug_logging", value=self.view.get_value("general", "debug_logging")) - self.presenter.save_app_settings_file() - self.presenter.save_settings_file() + def on_save_settings(self, *args, **kwargs): + self.presenter.update_setting(section="buffers", setting="count_for_wall_buffers", value=self.view.get_value("buffers", "wall_buffer_count")) + self.presenter.update_setting(section="buffers", setting="count_for_video_buffers", value=self.view.get_value("buffers", "video_buffers_count")) + self.presenter.update_setting(section="buffers", setting="count_for_chat_buffers", value=self.view.get_value("buffers", "chat_buffers_count")) + self.presenter.update_setting(section="general", setting="load_images", value=self.view.get_value("general", "load_images")) + update_channel = self.presenter.get_update_channel_type(self.view.get_value("general", "update_channel")) + if update_channel != self.presenter.session.settings["general"]["update_channel"]: + if update_channel == "stable": + self.presenter.update_setting(section="general", setting="update_channel", value=update_channel) + elif update_channel == "weekly": + dialog = self.view.weekly_channel() + if dialog == widgetUtils.YES: + self.presenter.update_setting(section="general", setting="update_channel", value=update_channel) + elif update_channel == "alpha": + dialog = self.view.alpha_channel() + if dialog == widgetUtils.YES: + self.presenter.update_setting(section="general", setting="update_channel", value=update_channel) + self.presenter.update_setting(section="chat", setting="notify_online", value=self.view.get_value("chat", "notify_online")) + self.presenter.update_setting(section="chat", setting="notify_offline", value=self.view.get_value("chat", "notify_offline")) + self.presenter.update_setting(section="chat", setting="notifications", value=self.presenter.get_notification_type(self.view.get_value("chat", "notifications"))) + self.presenter.update_setting(section="load_at_startup", setting="audio_albums", value=self.view.get_value("startup", "audio_albums")) + self.presenter.update_setting(section="load_at_startup", setting="video_albums", value=self.view.get_value("startup", "video_albums")) + self.presenter.update_setting(section="load_at_startup", setting="communities", value=self.view.get_value("startup", "communities")) + self.presenter.update_app_setting(section="app-settings", setting="language", value=self.presenter.codes[self.view.general.language.GetSelection()]) + self.presenter.update_app_setting(section="sound", setting="input_device", value=self.view.get_value("sound", "input")) + self.presenter.update_app_setting(section="sound", setting="output_device", value=self.view.get_value("sound", "output")) + self.presenter.update_app_setting(section="app-settings", setting="use_proxy", value=self.view.get_value("general", "use_proxy")) + self.presenter.update_app_setting(section="app-settings", setting="debug_logging", value=self.view.get_value("general", "debug_logging")) + self.presenter.save_app_settings_file() + self.presenter.save_settings_file() diff --git a/src/interactors/postCreation.py b/src/interactors/postCreation.py index 412c970..d4900ac 100644 --- a/src/interactors/postCreation.py +++ b/src/interactors/postCreation.py @@ -7,67 +7,67 @@ from .import base class createPostInteractor(base.baseInteractor): - def set(self, control, value): - if not hasattr(self.view, control): - raise AttributeError("The control is not present in the view.") - getattr(self.view, control).SetValue(value) + def set(self, control, value): + if not hasattr(self.view, control): + raise AttributeError("The control is not present in the view.") + getattr(self.view, control).SetValue(value) - def add_tagged_users(self, users): - self.view.text.SetValue(self.view.text.GetValue()+", ".join(users)) + def add_tagged_users(self, users): + self.view.text.SetValue(self.view.text.GetValue()+", ".join(users)) - def install(self, *args, **kwargs): - super(createPostInteractor, self).install(*args, **kwargs) - widgetUtils.connect_event(self.view.spellcheck, widgetUtils.BUTTON_PRESSED, self.on_spellcheck) - widgetUtils.connect_event(self.view.translateButton, widgetUtils.BUTTON_PRESSED, self.on_translate) - widgetUtils.connect_event(self.view.mention, widgetUtils.BUTTON_PRESSED, self.on_mention) - if hasattr(self.view, "attach"): - widgetUtils.connect_event(self.view.attach, widgetUtils.BUTTON_PRESSED, self.on_add_attachments) - pub.subscribe(self.set, self.modulename+"_set") - pub.subscribe(self.add_tagged_users, self.modulename+"_add_tagged_users") + def install(self, *args, **kwargs): + super(createPostInteractor, self).install(*args, **kwargs) + widgetUtils.connect_event(self.view.spellcheck, widgetUtils.BUTTON_PRESSED, self.on_spellcheck) + widgetUtils.connect_event(self.view.translateButton, widgetUtils.BUTTON_PRESSED, self.on_translate) + widgetUtils.connect_event(self.view.mention, widgetUtils.BUTTON_PRESSED, self.on_mention) + if hasattr(self.view, "attach"): + widgetUtils.connect_event(self.view.attach, widgetUtils.BUTTON_PRESSED, self.on_add_attachments) + pub.subscribe(self.set, self.modulename+"_set") + pub.subscribe(self.add_tagged_users, self.modulename+"_add_tagged_users") - def uninstall(self): - super(createPostInteractor, self).uninstall() - pub.unsubscribe(self.set, self.modulename+"_set") - pub.unsubscribe(self.add_tagged_users, self.modulename+"_add_tagged_users") + def uninstall(self): + super(createPostInteractor, self).uninstall() + pub.unsubscribe(self.set, self.modulename+"_set") + pub.unsubscribe(self.add_tagged_users, self.modulename+"_add_tagged_users") - def start(self): - self.result = self.view.get_response() - if self.result == widgetUtils.OK: - self.presenter.text = self.view.get_text() - if hasattr(self.view, "privacy"): - self.presenter.privacy = self.get_privacy_options() - else: - self.presenter.privacy = 0 + def start(self): + self.result = self.view.get_response() + if self.result == widgetUtils.OK: + self.presenter.text = self.view.get_text() + if hasattr(self.view, "privacy"): + self.presenter.privacy = self.get_privacy_options() + else: + self.presenter.privacy = 0 - def get_privacy_options(self): - p = self.view.get("privacy") - if p == _("Friends of friends"): - privacy = 0 - elif p == _("All users"): - privacy = 1 - return privacy + def get_privacy_options(self): + p = self.view.get("privacy") + if p == _("Friends of friends"): + privacy = 0 + elif p == _("All users"): + privacy = 1 + return privacy - def on_mention(self, *args, **kwargs): - users = self.presenter.get_friends() - select = selector.selectPeople(users) - if select.get_response() == widgetUtils.OK and select.users.GetCount() > 0: - tagged_users = select.get_all_users() - self.presenter.add_tagged_users(tagged_users) + def on_mention(self, *args, **kwargs): + users = self.presenter.get_friends() + select = selector.selectPeople(users) + if select.get_response() == widgetUtils.OK and select.users.GetCount() > 0: + tagged_users = select.get_all_users() + self.presenter.add_tagged_users(tagged_users) - def on_translate(self, *args, **kwargs): - dlg = translator.gui.translateDialog() - if dlg.get_response() == widgetUtils.OK: - text_to_translate = self.view.get_text() - language_dict = translator.translator.available_languages() - for k in language_dict: - if language_dict[k] == dlg.dest_lang.GetStringSelection(): - dst = k - self.presenter.translate(text_to_translate, dst) - dlg.Destroy() + def on_translate(self, *args, **kwargs): + dlg = translator.gui.translateDialog() + if dlg.get_response() == widgetUtils.OK: + text_to_translate = self.view.get_text() + language_dict = translator.translator.available_languages() + for k in language_dict: + if language_dict[k] == dlg.dest_lang.GetStringSelection(): + dst = k + self.presenter.translate(text_to_translate, dst) + dlg.Destroy() - def on_spellcheck(self, event=None): - text = self.view.get_text() - self.presenter.spellcheck(text) + def on_spellcheck(self, event=None): + text = self.view.get_text() + self.presenter.spellcheck(text) - def on_add_attachments(self, *args, **kwargs): - self.presenter.add_attachments() \ No newline at end of file + def on_add_attachments(self, *args, **kwargs): + self.presenter.add_attachments() diff --git a/src/interactors/postDisplayer.py b/src/interactors/postDisplayer.py index 97dd288..b4fda55 100644 --- a/src/interactors/postDisplayer.py +++ b/src/interactors/postDisplayer.py @@ -10,295 +10,295 @@ from .import base class displayPostInteractor(base.baseInteractor): - def set(self, control, value): - if not hasattr(self.view, control): - raise AttributeError("The control is not present in the view.") - getattr(self.view, control).SetValue(value) + def set(self, control, value): + if not hasattr(self.view, control): + raise AttributeError("The control is not present in the view.") + getattr(self.view, control).SetValue(value) - def load_image(self, image): - image = wx.Image(stream=six.BytesIO(image.content)) - try: - self.view.image.SetBitmap(wx.Bitmap(image)) - except ValueError: - return - self.view.panel.Layout() + def load_image(self, image): + image = wx.Image(stream=six.BytesIO(image.content)) + try: + self.view.image.SetBitmap(wx.Bitmap(image)) + except ValueError: + return + self.view.panel.Layout() - def add_items(self, control, items): - if not hasattr(self.view, control): - raise AttributeError("The control is not present in the view.") - for i in items: - getattr(self.view, control).insert_item(False, *i) + def add_items(self, control, items): + if not hasattr(self.view, control): + raise AttributeError("The control is not present in the view.") + for i in items: + getattr(self.view, control).insert_item(False, *i) - def add_item(self, control, item, reversed=False): - if not hasattr(self.view, control): - raise AttributeError("The control is not present in the view.") - getattr(self.view, control).insert_item(reversed, *item) + def add_item(self, control, item, reversed=False): + if not hasattr(self.view, control): + raise AttributeError("The control is not present in the view.") + getattr(self.view, control).insert_item(reversed, *item) - def enable_attachments(self): - self.view.attachments.list.Enable(True) + def enable_attachments(self): + self.view.attachments.list.Enable(True) - def enable_photo_controls(self, navigation): - self.view.enable_photo_controls(navigation) + def enable_photo_controls(self, navigation): + self.view.enable_photo_controls(navigation) - def clean_list(self, list): - if not hasattr(self.view, list): - raise AttributeError("The control is not present in the view.") - getattr(self.view, list).clear() + def clean_list(self, list): + if not hasattr(self.view, list): + raise AttributeError("The control is not present in the view.") + getattr(self.view, list).clear() - def post_deleted(self): - msg = commonMessages.post_deleted() + def post_deleted(self): + msg = commonMessages.post_deleted() - def install(self, *args, **kwargs): - super(displayPostInteractor, self).install(*args, **kwargs) - if hasattr(self.view, "comments"): - self.view.comments.list.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.on_show_comment) - self.view.comments.list.Bind(wx.EVT_LIST_ITEM_FOCUSED, self.on_comment_changed) - self.view.attachments.list.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.on_open_attachment) - widgetUtils.connect_event(self.view.like, widgetUtils.BUTTON_PRESSED, self.on_like) - widgetUtils.connect_event(self.view.comment, widgetUtils.BUTTON_PRESSED, self.on_add_comment) - widgetUtils.connect_event(self.view.tools, widgetUtils.BUTTON_PRESSED, self.on_show_tools_menu) - if hasattr(self.view, "likes"): - widgetUtils.connect_event(self.view.likes, widgetUtils.BUTTON_PRESSED, self.on_show_likes_menu) - if hasattr(self.view, "shares"): - widgetUtils.connect_event(self.view.shares, widgetUtils.BUTTON_PRESSED, self.on_show_shares_menu) - if hasattr(self.view, "repost"): - widgetUtils.connect_event(self.view.repost, widgetUtils.BUTTON_PRESSED, self.on_repost) - self.view.comments.list.Bind(wx.EVT_LIST_ITEM_FOCUSED, self.on_focus) - if hasattr(self.view, "reply"): - widgetUtils.connect_event(self.view.reply, widgetUtils.BUTTON_PRESSED, self.on_reply) - if hasattr(self.view, "load_more_comments"): - widgetUtils.connect_event(self.view.load_more_comments, widgetUtils.BUTTON_PRESSED, self.on_load_more_comments) -# self.view.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.on_show_menu, self.view.comments.list) -# self.view.Bind(wx.EVT_LIST_KEY_DOWN, self.on_show_menu_by_key, self.view.comments.list) - pub.subscribe(self.set, self.modulename+"_set") - pub.subscribe(self.load_image, self.modulename+"_load_image") - pub.subscribe(self.add_items, self.modulename+"_add_items") - pub.subscribe(self.add_item, self.modulename+"_add_item") - pub.subscribe(self.enable_attachments, self.modulename+"_enable_attachments") - pub.subscribe(self.enable_photo_controls, self.modulename+"_enable_photo_controls") - pub.subscribe(self.post_deleted, self.modulename+"_post_deleted") - pub.subscribe(self.clean_list, self.modulename+"_clean_list") + def install(self, *args, **kwargs): + super(displayPostInteractor, self).install(*args, **kwargs) + if hasattr(self.view, "comments"): + self.view.comments.list.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.on_show_comment) + self.view.comments.list.Bind(wx.EVT_LIST_ITEM_FOCUSED, self.on_comment_changed) + self.view.attachments.list.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.on_open_attachment) + widgetUtils.connect_event(self.view.like, widgetUtils.BUTTON_PRESSED, self.on_like) + widgetUtils.connect_event(self.view.comment, widgetUtils.BUTTON_PRESSED, self.on_add_comment) + widgetUtils.connect_event(self.view.tools, widgetUtils.BUTTON_PRESSED, self.on_show_tools_menu) + if hasattr(self.view, "likes"): + widgetUtils.connect_event(self.view.likes, widgetUtils.BUTTON_PRESSED, self.on_show_likes_menu) + if hasattr(self.view, "shares"): + widgetUtils.connect_event(self.view.shares, widgetUtils.BUTTON_PRESSED, self.on_show_shares_menu) + if hasattr(self.view, "repost"): + widgetUtils.connect_event(self.view.repost, widgetUtils.BUTTON_PRESSED, self.on_repost) + self.view.comments.list.Bind(wx.EVT_LIST_ITEM_FOCUSED, self.on_focus) + if hasattr(self.view, "reply"): + widgetUtils.connect_event(self.view.reply, widgetUtils.BUTTON_PRESSED, self.on_reply) + if hasattr(self.view, "load_more_comments"): + widgetUtils.connect_event(self.view.load_more_comments, widgetUtils.BUTTON_PRESSED, self.on_load_more_comments) +# self.view.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.on_show_menu, self.view.comments.list) +# self.view.Bind(wx.EVT_LIST_KEY_DOWN, self.on_show_menu_by_key, self.view.comments.list) + pub.subscribe(self.set, self.modulename+"_set") + pub.subscribe(self.load_image, self.modulename+"_load_image") + pub.subscribe(self.add_items, self.modulename+"_add_items") + pub.subscribe(self.add_item, self.modulename+"_add_item") + pub.subscribe(self.enable_attachments, self.modulename+"_enable_attachments") + pub.subscribe(self.enable_photo_controls, self.modulename+"_enable_photo_controls") + pub.subscribe(self.post_deleted, self.modulename+"_post_deleted") + pub.subscribe(self.clean_list, self.modulename+"_clean_list") - def uninstall(self): - super(displayPostInteractor, self).uninstall() - pub.unsubscribe(self.set, self.modulename+"_set") - pub.unsubscribe(self.load_image, self.modulename+"_load_image") - pub.unsubscribe(self.add_items, self.modulename+"_add_items") - pub.unsubscribe(self.add_item, self.modulename+"_add_item") - pub.unsubscribe(self.enable_attachments, self.modulename+"_enable_attachments") - pub.unsubscribe(self.enable_photo_controls, self.modulename+"_enable_photo_controls") - pub.unsubscribe(self.post_deleted, self.modulename+"_post_deleted") - pub.unsubscribe(self.clean_list, self.modulename+"_clean_list") + def uninstall(self): + super(displayPostInteractor, self).uninstall() + pub.unsubscribe(self.set, self.modulename+"_set") + pub.unsubscribe(self.load_image, self.modulename+"_load_image") + pub.unsubscribe(self.add_items, self.modulename+"_add_items") + pub.unsubscribe(self.add_item, self.modulename+"_add_item") + pub.unsubscribe(self.enable_attachments, self.modulename+"_enable_attachments") + pub.unsubscribe(self.enable_photo_controls, self.modulename+"_enable_photo_controls") + pub.unsubscribe(self.post_deleted, self.modulename+"_post_deleted") + pub.unsubscribe(self.clean_list, self.modulename+"_clean_list") - def on_focus(self, *args, **kwargs): - item = self.view.comments.get_selected() - if item == -1: - self.view.reply.Enable(False) - else: - self.view.reply.Enable(True) + def on_focus(self, *args, **kwargs): + item = self.view.comments.get_selected() + if item == -1: + self.view.reply.Enable(False) + else: + self.view.reply.Enable(True) - def on_like(self, *args, **kwargs): - self.presenter.post_like() + def on_like(self, *args, **kwargs): + self.presenter.post_like() - def on_repost(self, *args, **kwargs): - self.presenter.post_repost() + def on_repost(self, *args, **kwargs): + self.presenter.post_repost() - def on_reply(self, *args, **kwargs): - if hasattr(self.view, "comments") and (hasattr(self.view, "repost") or not hasattr(self, "post_view")): - comment = self.view.comments.get_selected() - self.presenter.reply(comment) - else: - self.presenter.reply() + def on_reply(self, *args, **kwargs): + if hasattr(self.view, "comments") and (hasattr(self.view, "repost") or not hasattr(self, "post_view")): + comment = self.view.comments.get_selected() + self.presenter.reply(comment) + else: + self.presenter.reply() - def on_add_comment(self, *args, **kwargs): - self.presenter.add_comment() + def on_add_comment(self, *args, **kwargs): + self.presenter.add_comment() - def on_load_more_comments(self, *args, **kwargs): - if hasattr(self.presenter, "load_more_comments"): - self.presenter.load_more_comments() + def on_load_more_comments(self, *args, **kwargs): + if hasattr(self.presenter, "load_more_comments"): + self.presenter.load_more_comments() - def on_show_tools_menu(self, *args, **kwargs): - menu = menus.toolsMenu() -# widgetUtils.connect_event(self.view, widgetUtils.MENU, self.on_open_url, menuitem=menu.url) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.on_translate, menuitem=menu.translate) - widgetUtils.connect_event(self.view, widgetUtils.MENU, self.on_spellcheck, menuitem=menu.spellcheck) - self.view.PopupMenu(menu, self.view.tools.GetPosition()) + def on_show_tools_menu(self, *args, **kwargs): + menu = menus.toolsMenu() +# widgetUtils.connect_event(self.view, widgetUtils.MENU, self.on_open_url, menuitem=menu.url) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.on_translate, menuitem=menu.translate) + widgetUtils.connect_event(self.view, widgetUtils.MENU, self.on_spellcheck, menuitem=menu.spellcheck) + self.view.PopupMenu(menu, self.view.tools.GetPosition()) - def on_open_url(self, *args, **kwargs): - pass + def on_open_url(self, *args, **kwargs): + pass - def on_open_attachment(self, *args, **kwargs): - attachment = self.view.attachments.get_selected() - self.presenter.open_attachment(attachment) + def on_open_attachment(self, *args, **kwargs): + attachment = self.view.attachments.get_selected() + self.presenter.open_attachment(attachment) - def on_translate(self, *args, **kwargs): - dlg = translator.gui.translateDialog() - if dlg.get_response() == widgetUtils.OK: - text_to_translate = self.view.get("post_view") - language_dict = translator.translator.available_languages() - for k in language_dict: - if language_dict[k] == dlg.dest_lang.GetStringSelection(): - dst = k - self.presenter.translate(text_to_translate, dst) - dlg.Destroy() + def on_translate(self, *args, **kwargs): + dlg = translator.gui.translateDialog() + if dlg.get_response() == widgetUtils.OK: + text_to_translate = self.view.get("post_view") + language_dict = translator.translator.available_languages() + for k in language_dict: + if language_dict[k] == dlg.dest_lang.GetStringSelection(): + dst = k + self.presenter.translate(text_to_translate, dst) + dlg.Destroy() - def on_spellcheck(self, event=None): - text = self.view.get("post_view") - self.presenter.spellcheck(text) + def on_spellcheck(self, event=None): + text = self.view.get("post_view") + self.presenter.spellcheck(text) - def on_show_comment(self, *args, **kwargs): - comment = self.view.comments.get_selected() - self.presenter.show_comment(comment) + def on_show_comment(self, *args, **kwargs): + comment = self.view.comments.get_selected() + self.presenter.show_comment(comment) - def on_comment_changed(self, *args, **kwargs): - if hasattr(self.presenter, "change_comment"): - comment = self.view.comments.get_selected() - self.presenter.change_comment(comment) + def on_comment_changed(self, *args, **kwargs): + if hasattr(self.presenter, "change_comment"): + comment = self.view.comments.get_selected() + self.presenter.change_comment(comment) - def on_show_likes_menu(self, *args, **kwargs): - self.presenter.show_likes() + def on_show_likes_menu(self, *args, **kwargs): + self.presenter.show_likes() - def on_show_shares_menu(self, *args, **kwargs): - self.presenter.show_shares() + def on_show_shares_menu(self, *args, **kwargs): + self.presenter.show_shares() class displayAudioInteractor(base.baseInteractor): - def set(self, control, value): - if not hasattr(self.view, control): - raise AttributeError("The control is not present in the view.") - getattr(self.view, control).SetValue(value) + def set(self, control, value): + if not hasattr(self.view, control): + raise AttributeError("The control is not present in the view.") + getattr(self.view, control).SetValue(value) - def add_items(self, control, items): - if not hasattr(self.view, control): - raise AttributeError("The control is not present in the view.") - for i in items: - getattr(self.view, control).Append(i) - getattr(self.view, control).SetSelection(0) + def add_items(self, control, items): + if not hasattr(self.view, control): + raise AttributeError("The control is not present in the view.") + for i in items: + getattr(self.view, control).Append(i) + getattr(self.view, control).SetSelection(0) - def change_label(self, stopped): + def change_label(self, stopped): - if stopped == False: - self.view.play.SetLabel(_("P&ause")) - else: - self.view.play.SetLabel(_("P&lay")) + if stopped == False: + self.view.play.SetLabel(_("P&ause")) + else: + self.view.play.SetLabel(_("P&lay")) - def install(self, *args, **kwargs): - super(displayAudioInteractor, self).install(*args, **kwargs) - widgetUtils.connect_event(self.view.list, widgetUtils.LISTBOX_CHANGED, self.on_change) - widgetUtils.connect_event(self.view.download, widgetUtils.BUTTON_PRESSED, self.on_download) - widgetUtils.connect_event(self.view.play, widgetUtils.BUTTON_PRESSED, self.on_play) - widgetUtils.connect_event(self.view.add, widgetUtils.BUTTON_PRESSED, self.on_add_to_library) - widgetUtils.connect_event(self.view.remove, widgetUtils.BUTTON_PRESSED, self.on_remove_from_library) - pub.subscribe(self.set, self.modulename+"_set") - pub.subscribe(self.add_items, self.modulename+"_add_items") - pub.subscribe(self.change_label, "playback-changed") + def install(self, *args, **kwargs): + super(displayAudioInteractor, self).install(*args, **kwargs) + widgetUtils.connect_event(self.view.list, widgetUtils.LISTBOX_CHANGED, self.on_change) + widgetUtils.connect_event(self.view.download, widgetUtils.BUTTON_PRESSED, self.on_download) + widgetUtils.connect_event(self.view.play, widgetUtils.BUTTON_PRESSED, self.on_play) + widgetUtils.connect_event(self.view.add, widgetUtils.BUTTON_PRESSED, self.on_add_to_library) + widgetUtils.connect_event(self.view.remove, widgetUtils.BUTTON_PRESSED, self.on_remove_from_library) + pub.subscribe(self.set, self.modulename+"_set") + pub.subscribe(self.add_items, self.modulename+"_add_items") + pub.subscribe(self.change_label, "playback-changed") - def uninstall(self): - super(displayAudioInteractor, self).uninstall() - pub.unsubscribe(self.set, self.modulename+"_set") - pub.unsubscribe(self.add_items, self.modulename+"_add_items") - pub.unsubscribe(self.change_label, "playback-changed") + def uninstall(self): + super(displayAudioInteractor, self).uninstall() + pub.unsubscribe(self.set, self.modulename+"_set") + pub.unsubscribe(self.add_items, self.modulename+"_add_items") + pub.unsubscribe(self.change_label, "playback-changed") - def on_change(self, *args, **kwargs): - post = self.view.get_audio() - self.presenter.handle_changes(post) + def on_change(self, *args, **kwargs): + post = self.view.get_audio() + self.presenter.handle_changes(post) - def on_download(self, *args, **kwargs): - post = self.view.get_audio() - suggested_filename = self.presenter.get_suggested_filename(post) - path = self.view.get_destination_path(suggested_filename) - self.presenter.download(post, path) + def on_download(self, *args, **kwargs): + post = self.view.get_audio() + suggested_filename = self.presenter.get_suggested_filename(post) + path = self.view.get_destination_path(suggested_filename) + self.presenter.download(post, path) - def on_play(self, *args, **kwargs): - post = self.view.get_audio() - self.presenter.play(post) + def on_play(self, *args, **kwargs): + post = self.view.get_audio() + self.presenter.play(post) - def on_add_to_library(self, *args, **kwargs): - post = self.view.get_audio() - self.presenter.add_to_library(post) + def on_add_to_library(self, *args, **kwargs): + post = self.view.get_audio() + self.presenter.add_to_library(post) - def on_remove_from_library(self, *args, **kwargs): - post = self.view.get_audio() - self.presenter.remove_from_library(post) + def on_remove_from_library(self, *args, **kwargs): + post = self.view.get_audio() + self.presenter.remove_from_library(post) class displayArticleInteractor(base.baseInteractor): - def set(self, control, value): - if not hasattr(self.view, control): - raise AttributeError("The control is not present in the view.") - getattr(self.view, control).SetValue(value) + def set(self, control, value): + if not hasattr(self.view, control): + raise AttributeError("The control is not present in the view.") + getattr(self.view, control).SetValue(value) - def install(self, *args, **kwargs): - super(displayArticleInteractor, self).install(*args, **kwargs) - pub.subscribe(self.set, self.modulename+"_set") + def install(self, *args, **kwargs): + super(displayArticleInteractor, self).install(*args, **kwargs) + pub.subscribe(self.set, self.modulename+"_set") - def uninstall(self): - super(displayArticleInteractor, self).uninstall() - pub.unsubscribe(self.set, self.modulename+"_set") + def uninstall(self): + super(displayArticleInteractor, self).uninstall() + pub.unsubscribe(self.set, self.modulename+"_set") class displayPollInteractor(base.baseInteractor): - def set(self, control, value): - if not hasattr(self.view, control): - raise AttributeError("The control is not present in the view.") - getattr(self.view, control).SetValue(value) + def set(self, control, value): + if not hasattr(self.view, control): + raise AttributeError("The control is not present in the view.") + getattr(self.view, control).SetValue(value) - def done(self): - self.view.done() + def done(self): + self.view.done() - def add_options(self, options, multiple): - self.view.add_options(options, multiple) + def add_options(self, options, multiple): + self.view.add_options(options, multiple) - def install(self, *args, **kwargs): - super(displayPollInteractor, self).install(*args, **kwargs) - pub.subscribe(self.set, self.modulename+"_set") - pub.subscribe(self.done, self.modulename+"_done") - pub.subscribe(self.add_options, self.modulename+"_add_options") + def install(self, *args, **kwargs): + super(displayPollInteractor, self).install(*args, **kwargs) + pub.subscribe(self.set, self.modulename+"_set") + pub.subscribe(self.done, self.modulename+"_done") + pub.subscribe(self.add_options, self.modulename+"_add_options") - def uninstall(self): - super(displayPollInteractor, self).uninstall() - pub.unsubscribe(self.set, self.modulename+"_set") - pub.unsubscribe(self.done, self.modulename+"_done") - pub.unsubscribe(self.add_options, self.modulename+"_add_options") + def uninstall(self): + super(displayPollInteractor, self).uninstall() + pub.unsubscribe(self.set, self.modulename+"_set") + pub.unsubscribe(self.done, self.modulename+"_done") + pub.unsubscribe(self.add_options, self.modulename+"_add_options") - def start(self, *args, **kwargs): - super(displayPollInteractor, self).start(*args, **kwargs) - if self.result == widgetUtils.OK: # USer votd. - answers = self.view.get_answers() - self.presenter.vote(answers) + def start(self, *args, **kwargs): + super(displayPollInteractor, self).start(*args, **kwargs) + if self.result == widgetUtils.OK: # USer votd. + answers = self.view.get_answers() + self.presenter.vote(answers) class displayFriendshipInteractor(base.baseInteractor): - def add_items(self, control, items): - if not hasattr(self.view, control): - raise AttributeError("The control is not present in the view.") - for i in items: - getattr(self.view, control).insert_item(False, *[i]) + def add_items(self, control, items): + if not hasattr(self.view, control): + raise AttributeError("The control is not present in the view.") + for i in items: + getattr(self.view, control).insert_item(False, *[i]) - def install(self, *args, **kwargs): - super(displayFriendshipInteractor, self).install(*args, **kwargs) - pub.subscribe(self.add_items, self.modulename+"_add_items") - self.view.friends.list.Bind(wx.EVT_CONTEXT_MENU, self.on_context_menu) + def install(self, *args, **kwargs): + super(displayFriendshipInteractor, self).install(*args, **kwargs) + pub.subscribe(self.add_items, self.modulename+"_add_items") + self.view.friends.list.Bind(wx.EVT_CONTEXT_MENU, self.on_context_menu) - def uninstall(self): - super(displayFriendshipInteractor, self).uninstall() - pub.unsubscribe(self.add_items, self.modulename+"_add_items") + def uninstall(self): + super(displayFriendshipInteractor, self).uninstall() + pub.unsubscribe(self.add_items, self.modulename+"_add_items") - def on_context_menu(self, *args, **kwargs): - item = self.view.friends.get_selected() - if item < 0: - return - menu = menus.peopleMenu(False, False, True) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.on_view_profile, menuitem=menu.view_profile) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.on_open_in_browser, menuitem=menu.open_in_browser) - # Generally message sending is blocked. - menu.message.Enable(False) - self.view.PopupMenu(menu, self.view.friends.list.GetPosition()) + def on_context_menu(self, *args, **kwargs): + item = self.view.friends.get_selected() + if item < 0: + return + menu = menus.peopleMenu(False, False, True) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.on_view_profile, menuitem=menu.view_profile) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.on_open_in_browser, menuitem=menu.open_in_browser) + # Generally message sending is blocked. + menu.message.Enable(False) + self.view.PopupMenu(menu, self.view.friends.list.GetPosition()) - def on_view_profile(self, *args, **kwargs): - item = self.view.friends.get_selected() - self.presenter.view_profile(item) + def on_view_profile(self, *args, **kwargs): + item = self.view.friends.get_selected() + self.presenter.view_profile(item) - def on_open_in_browser(self, *args, **kwargs): - item = self.view.friends.get_selected() - self.presenter.open_in_browser(item) \ No newline at end of file + def on_open_in_browser(self, *args, **kwargs): + item = self.view.friends.get_selected() + self.presenter.open_in_browser(item) diff --git a/src/interactors/profiles.py b/src/interactors/profiles.py index b33aa04..a905733 100644 --- a/src/interactors/profiles.py +++ b/src/interactors/profiles.py @@ -9,62 +9,62 @@ from . import base class userProfileInteractor(base.baseInteractor): - def enable_control(self, tab, control): - if not hasattr(self.view, tab): - raise AttributeError("The viw does not contain the specified tab.") - tab = getattr(self.view, tab) - if not hasattr(tab, control): - raise AttributeError("The control is not present in the tab.") - getattr(tab, control).Enable(True) + def enable_control(self, tab, control): + if not hasattr(self.view, tab): + raise AttributeError("The viw does not contain the specified tab.") + tab = getattr(self.view, tab) + if not hasattr(tab, control): + raise AttributeError("The control is not present in the tab.") + getattr(tab, control).Enable(True) - def set(self, tab, control, value): - if not hasattr(self.view, tab): - raise AttributeError("The view does not contain the specified tab.") - tab = getattr(self.view, tab) - if not hasattr(tab, control): - raise AttributeError("The control is not present in the tab.") - control = getattr(tab, control) - control.SetValue(value) + def set(self, tab, control, value): + if not hasattr(self.view, tab): + raise AttributeError("The view does not contain the specified tab.") + tab = getattr(self.view, tab) + if not hasattr(tab, control): + raise AttributeError("The control is not present in the tab.") + control = getattr(tab, control) + control.SetValue(value) - def set_label(self, tab, control, value): - if not hasattr(self.view, tab): - raise AttributeError("The viw does not contain the specified tab.") - tab = getattr(self.view, tab) - if not hasattr(tab, control): - raise AttributeError("The control is not present in the tab.") - control = getattr(tab, control) - control.SetLabel(value) + def set_label(self, tab, control, value): + if not hasattr(self.view, tab): + raise AttributeError("The viw does not contain the specified tab.") + tab = getattr(self.view, tab) + if not hasattr(tab, control): + raise AttributeError("The control is not present in the tab.") + control = getattr(tab, control) + control.SetLabel(value) - def load_image(self, image): - image = wx.Image(stream=six.BytesIO(image.content)) - try: - self.view.image.SetBitmap(wx.Bitmap(image)) - except ValueError: - return - self.view.panel.Layout() + def load_image(self, image): + image = wx.Image(stream=six.BytesIO(image.content)) + try: + self.view.image.SetBitmap(wx.Bitmap(image)) + except ValueError: + return + self.view.panel.Layout() - def install(self, *args, **kwargs): - super(userProfileInteractor, self).install(*args, **kwargs) - pub.subscribe(self.set, self.modulename+"_set") - pub.subscribe(self.load_image, self.modulename+"_load_image") - self.view.create_controls("main_info") - self.view.realice() - widgetUtils.connect_event(self.view.main_info.go_site, widgetUtils.BUTTON_PRESSED, self.on_visit_website) + def install(self, *args, **kwargs): + super(userProfileInteractor, self).install(*args, **kwargs) + pub.subscribe(self.set, self.modulename+"_set") + pub.subscribe(self.load_image, self.modulename+"_load_image") + self.view.create_controls("main_info") + self.view.realice() + widgetUtils.connect_event(self.view.main_info.go_site, widgetUtils.BUTTON_PRESSED, self.on_visit_website) - def uninstall(self): - super(userProfileInteractor, self).uninstall() - pub.unsubscribe(self.set, self.modulename+"_set") - pub.unsubscribe(self.load_image, self.modulename+"_load_image") + def uninstall(self): + super(userProfileInteractor, self).uninstall() + pub.unsubscribe(self.set, self.modulename+"_set") + pub.unsubscribe(self.load_image, self.modulename+"_load_image") - def on_visit_website(self, *args, **kwargs): - urls = self.presenter.get_urls() - if len(urls) == 1: - self.presenter.visit_url(urls[0]) - else: - dialog = urlList.urlList() - dialog.populate_list(urls) - if dialog.get_response() != widgetUtils.OK: - return - selected_url = urls[dialog.get_item()] - self.presenter.visit_url(selected_url) \ No newline at end of file + def on_visit_website(self, *args, **kwargs): + urls = self.presenter.get_urls() + if len(urls) == 1: + self.presenter.visit_url(urls[0]) + else: + dialog = urlList.urlList() + dialog.populate_list(urls) + if dialog.get_response() != widgetUtils.OK: + return + selected_url = urls[dialog.get_item()] + self.presenter.visit_url(selected_url) diff --git a/src/issueReporter/issueReporter.py b/src/issueReporter/issueReporter.py index 19ccdf0..6c6ddfd 100644 --- a/src/issueReporter/issueReporter.py +++ b/src/issueReporter/issueReporter.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- ############################################################ # Copyright (c) 2018 Manuel Cortez -# +# # 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 @@ -28,37 +28,37 @@ from mysc.thread_utils import call_threaded from . import wx_ui class reportBug(object): - def __init__(self): - self.dialog = wx_ui.reportBugDialog() - widgetUtils.connect_event(self.dialog.ok, widgetUtils.BUTTON_PRESSED, self.send) - self.dialog.get_response() + def __init__(self): + self.dialog = wx_ui.reportBugDialog() + widgetUtils.connect_event(self.dialog.ok, widgetUtils.BUTTON_PRESSED, self.send) + self.dialog.get_response() - def do_report(self, *args, **kwargs): - r = requests.post(*args, **kwargs) - if r.status_code > 300: - wx.CallAfter(self.dialog.error) - wx.CallAfter(self.dialog.progress.Destroy) - wx.CallAfter(self.dialog.success, r.json()["data"]["issue"]["id"]) + def do_report(self, *args, **kwargs): + r = requests.post(*args, **kwargs) + if r.status_code > 300: + wx.CallAfter(self.dialog.error) + wx.CallAfter(self.dialog.progress.Destroy) + wx.CallAfter(self.dialog.success, r.json()["data"]["issue"]["id"]) - def send(self, *args, **kwargs): - if self.dialog.get("summary") == "" or self.dialog.get("description") == "" or self.dialog.get("first_name") == "" or self.dialog.get("last_name") == "": - self.dialog.no_filled() - return - if self.dialog.get("agree") == False: - self.dialog.no_checkbox() - return - title = self.dialog.get("summary") - body = self.dialog.get("description") - issue_type = "issue" # for now just have issue - app_type = paths.mode - app_version = application.version - reporter_name = "{first_name} {last_name}".format(first_name=self.dialog.get("first_name"), last_name=self.dialog.get("last_name")) - reporter_contact_type = "email" # For now just email is supported in the issue reporter - reporter_contact_handle = self.dialog.get("email") - operating_system = platform.platform() - json = dict(title=title, issue_type=issue_type, body=body, operating_system=operating_system, app_type=app_type, app_version=app_version, reporter_name=reporter_name, reporter_contact_handle=reporter_contact_handle, reporter_contact_type=reporter_contact_type) - auth=HTTPBasicAuth(application.bts_name, application.bts_access_token) - url = "{bts_url}/issue/new".format(bts_url=application.bts_url) - call_threaded(self.do_report, url, json=json, auth=auth) - self.dialog.show_progress() - self.dialog.EndModal(wx.ID_OK) \ No newline at end of file + def send(self, *args, **kwargs): + if self.dialog.get("summary") == "" or self.dialog.get("description") == "" or self.dialog.get("first_name") == "" or self.dialog.get("last_name") == "": + self.dialog.no_filled() + return + if self.dialog.get("agree") == False: + self.dialog.no_checkbox() + return + title = self.dialog.get("summary") + body = self.dialog.get("description") + issue_type = "issue" # for now just have issue + app_type = paths.mode + app_version = application.version + reporter_name = "{first_name} {last_name}".format(first_name=self.dialog.get("first_name"), last_name=self.dialog.get("last_name")) + reporter_contact_type = "email" # For now just email is supported in the issue reporter + reporter_contact_handle = self.dialog.get("email") + operating_system = platform.platform() + json = dict(title=title, issue_type=issue_type, body=body, operating_system=operating_system, app_type=app_type, app_version=app_version, reporter_name=reporter_name, reporter_contact_handle=reporter_contact_handle, reporter_contact_type=reporter_contact_type) + auth=HTTPBasicAuth(application.bts_name, application.bts_access_token) + url = "{bts_url}/issue/new".format(bts_url=application.bts_url) + call_threaded(self.do_report, url, json=json, auth=auth) + self.dialog.show_progress() + self.dialog.EndModal(wx.ID_OK) diff --git a/src/issueReporter/wx_ui.py b/src/issueReporter/wx_ui.py index 15038ba..fe64d16 100644 --- a/src/issueReporter/wx_ui.py +++ b/src/issueReporter/wx_ui.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- ############################################################ # Copyright (c) 2018 Manuel cortez -# +# # 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 @@ -22,89 +22,89 @@ import widgetUtils import application class reportBugDialog(widgetUtils.BaseDialog): - def __init__(self): - super(reportBugDialog, self).__init__(parent=None, id=wx.NewId()) - self.SetTitle(_("Report an error")) - panel = wx.Panel(self) - sizer = wx.BoxSizer(wx.VERTICAL) + def __init__(self): + super(reportBugDialog, self).__init__(parent=None, id=wx.NewId()) + self.SetTitle(_("Report an error")) + panel = wx.Panel(self) + sizer = wx.BoxSizer(wx.VERTICAL) - summaryLabel = wx.StaticText(panel, -1, _("Briefly describe what happened. You will be able to thoroughly explain it later"), size=wx.DefaultSize) - self.summary = wx.TextCtrl(panel, -1) - dc = wx.WindowDC(self.summary) - dc.SetFont(self.summary.GetFont()) - self.summary.SetSize(dc.GetTextExtent("a"*80)) - summaryB = wx.BoxSizer(wx.HORIZONTAL) - summaryB.Add(summaryLabel, 0, wx.ALL, 5) - summaryB.Add(self.summary, 0, wx.ALL, 5) - sizer.Add(summaryB, 0, wx.ALL, 5) + summaryLabel = wx.StaticText(panel, -1, _("Briefly describe what happened. You will be able to thoroughly explain it later"), size=wx.DefaultSize) + self.summary = wx.TextCtrl(panel, -1) + dc = wx.WindowDC(self.summary) + dc.SetFont(self.summary.GetFont()) + self.summary.SetSize(dc.GetTextExtent("a"*80)) + summaryB = wx.BoxSizer(wx.HORIZONTAL) + summaryB.Add(summaryLabel, 0, wx.ALL, 5) + summaryB.Add(self.summary, 0, wx.ALL, 5) + sizer.Add(summaryB, 0, wx.ALL, 5) - first_nameLabel = wx.StaticText(panel, -1, _("First Name"), size=wx.DefaultSize) - self.first_name = wx.TextCtrl(panel, -1) - dc = wx.WindowDC(self.first_name) - dc.SetFont(self.first_name.GetFont()) - self.first_name.SetSize(dc.GetTextExtent("a"*40)) - first_nameB = wx.BoxSizer(wx.HORIZONTAL) - first_nameB.Add(first_nameLabel, 0, wx.ALL, 5) - first_nameB.Add(self.first_name, 0, wx.ALL, 5) - sizer.Add(first_nameB, 0, wx.ALL, 5) + first_nameLabel = wx.StaticText(panel, -1, _("First Name"), size=wx.DefaultSize) + self.first_name = wx.TextCtrl(panel, -1) + dc = wx.WindowDC(self.first_name) + dc.SetFont(self.first_name.GetFont()) + self.first_name.SetSize(dc.GetTextExtent("a"*40)) + first_nameB = wx.BoxSizer(wx.HORIZONTAL) + first_nameB.Add(first_nameLabel, 0, wx.ALL, 5) + first_nameB.Add(self.first_name, 0, wx.ALL, 5) + sizer.Add(first_nameB, 0, wx.ALL, 5) - last_nameLabel = wx.StaticText(panel, -1, _("Last Name"), size=wx.DefaultSize) - self.last_name = wx.TextCtrl(panel, -1) - dc = wx.WindowDC(self.last_name) - dc.SetFont(self.last_name.GetFont()) - self.last_name.SetSize(dc.GetTextExtent("a"*40)) - last_nameB = wx.BoxSizer(wx.HORIZONTAL) - last_nameB.Add(last_nameLabel, 0, wx.ALL, 5) - last_nameB.Add(self.last_name, 0, wx.ALL, 5) - sizer.Add(last_nameB, 0, wx.ALL, 5) + last_nameLabel = wx.StaticText(panel, -1, _("Last Name"), size=wx.DefaultSize) + self.last_name = wx.TextCtrl(panel, -1) + dc = wx.WindowDC(self.last_name) + dc.SetFont(self.last_name.GetFont()) + self.last_name.SetSize(dc.GetTextExtent("a"*40)) + last_nameB = wx.BoxSizer(wx.HORIZONTAL) + last_nameB.Add(last_nameLabel, 0, wx.ALL, 5) + last_nameB.Add(self.last_name, 0, wx.ALL, 5) + sizer.Add(last_nameB, 0, wx.ALL, 5) - emailLabel = wx.StaticText(panel, -1, _("Email address (Will not be public)"), size=wx.DefaultSize) - self.email = wx.TextCtrl(panel, -1) - dc = wx.WindowDC(self.email) - dc.SetFont(self.email.GetFont()) - self.email.SetSize(dc.GetTextExtent("a"*30)) - emailB = wx.BoxSizer(wx.HORIZONTAL) - emailB.Add(emailLabel, 0, wx.ALL, 5) - emailB.Add(self.email, 0, wx.ALL, 5) - sizer.Add(emailB, 0, wx.ALL, 5) + emailLabel = wx.StaticText(panel, -1, _("Email address (Will not be public)"), size=wx.DefaultSize) + self.email = wx.TextCtrl(panel, -1) + dc = wx.WindowDC(self.email) + dc.SetFont(self.email.GetFont()) + self.email.SetSize(dc.GetTextExtent("a"*30)) + emailB = wx.BoxSizer(wx.HORIZONTAL) + emailB.Add(emailLabel, 0, wx.ALL, 5) + emailB.Add(self.email, 0, wx.ALL, 5) + sizer.Add(emailB, 0, wx.ALL, 5) - descriptionLabel = wx.StaticText(panel, -1, _("Here, you can describe the bug in detail"), size=wx.DefaultSize) - self.description = wx.TextCtrl(panel, -1, style=wx.TE_MULTILINE) - dc = wx.WindowDC(self.description) - dc.SetFont(self.description.GetFont()) - (x, y) = dc.GetMultiLineTextExtent("0"*2000) - self.description.SetSize((x, y)) - descBox = wx.BoxSizer(wx.HORIZONTAL) - descBox.Add(descriptionLabel, 0, wx.ALL, 5) - descBox.Add(self.description, 0, wx.ALL, 5) - sizer.Add(descBox, 0, wx.ALL, 5) - self.agree = wx.CheckBox(panel, -1, _("I know that the {0} bug system will get my email address to contact me and fix the bug quickly").format(application.name,)) - self.agree.SetValue(False) - sizer.Add(self.agree, 0, wx.ALL, 5) - self.ok = wx.Button(panel, wx.ID_OK, _("Send report")) - self.ok.SetDefault() - cancel = wx.Button(panel, wx.ID_CANCEL, _("Cancel")) - btnBox = wx.BoxSizer(wx.HORIZONTAL) - btnBox.Add(self.ok, 0, wx.ALL, 5) - btnBox.Add(cancel, 0, wx.ALL, 5) - sizer.Add(btnBox, 0, wx.ALL, 5) - panel.SetSizer(sizer) - self.SetClientSize(sizer.CalcMin()) + descriptionLabel = wx.StaticText(panel, -1, _("Here, you can describe the bug in detail"), size=wx.DefaultSize) + self.description = wx.TextCtrl(panel, -1, style=wx.TE_MULTILINE) + dc = wx.WindowDC(self.description) + dc.SetFont(self.description.GetFont()) + (x, y) = dc.GetMultiLineTextExtent("0"*2000) + self.description.SetSize((x, y)) + descBox = wx.BoxSizer(wx.HORIZONTAL) + descBox.Add(descriptionLabel, 0, wx.ALL, 5) + descBox.Add(self.description, 0, wx.ALL, 5) + sizer.Add(descBox, 0, wx.ALL, 5) + self.agree = wx.CheckBox(panel, -1, _("I know that the {0} bug system will get my email address to contact me and fix the bug quickly").format(application.name,)) + self.agree.SetValue(False) + sizer.Add(self.agree, 0, wx.ALL, 5) + self.ok = wx.Button(panel, wx.ID_OK, _("Send report")) + self.ok.SetDefault() + cancel = wx.Button(panel, wx.ID_CANCEL, _("Cancel")) + btnBox = wx.BoxSizer(wx.HORIZONTAL) + btnBox.Add(self.ok, 0, wx.ALL, 5) + btnBox.Add(cancel, 0, wx.ALL, 5) + sizer.Add(btnBox, 0, wx.ALL, 5) + panel.SetSizer(sizer) + self.SetClientSize(sizer.CalcMin()) - def no_filled(self): - wx.MessageDialog(self, _("You must fill out the following fields: first name, last name, email address and issue information."), _("Error"), wx.OK|wx.ICON_ERROR).ShowModal() + def no_filled(self): + wx.MessageDialog(self, _("You must fill out the following fields: first name, last name, email address and issue information."), _("Error"), wx.OK|wx.ICON_ERROR).ShowModal() - def no_checkbox(self): - wx.MessageDialog(self, _("You need to mark the checkbox to provide us your email address to contact you if it is necessary."), _("Error"), wx.ICON_ERROR).ShowModal() + def no_checkbox(self): + wx.MessageDialog(self, _("You need to mark the checkbox to provide us your email address to contact you if it is necessary."), _("Error"), wx.ICON_ERROR).ShowModal() - def success(self, id): - wx.MessageDialog(self, _("Thanks for reporting this bug! In future versions, you may be able to find it in the changes list. You have received an email with more information regarding your report. You've reported the bug number %i") % (id), _("reported"), wx.OK).ShowModal() - self.Destroy() + def success(self, id): + wx.MessageDialog(self, _("Thanks for reporting this bug! In future versions, you may be able to find it in the changes list. You have received an email with more information regarding your report. You've reported the bug number %i") % (id), _("reported"), wx.OK).ShowModal() + self.Destroy() - def error(self): - wx.MessageDialog(self, _("Something unexpected occurred while trying to report the bug. Please, try again later"), _("Error while reporting"), wx.ICON_ERROR|wx.OK).ShowModal() - self.Destroy() + def error(self): + wx.MessageDialog(self, _("Something unexpected occurred while trying to report the bug. Please, try again later"), _("Error while reporting"), wx.ICON_ERROR|wx.OK).ShowModal() + self.Destroy() - def show_progress(self): - self.progress = wx.ProgressDialog(title=_("Sending report..."), message=_("Please wait while your report is being send."), maximum=100, parent=self) - self.progress.ShowModal() \ No newline at end of file + def show_progress(self): + self.progress = wx.ProgressDialog(title=_("Sending report..."), message=_("Please wait while your report is being send."), maximum=100, parent=self) + self.progress.ShowModal() diff --git a/src/keys/__init__.py b/src/keys/__init__.py index 773e719..c5929c9 100644 --- a/src/keys/__init__.py +++ b/src/keys/__init__.py @@ -5,12 +5,12 @@ log = logging.getLogger("keyring") keyring = None def setup(): - global keyring - if keyring == None: - keyring = Keyring() - log.debug("Keyring started") + global keyring + if keyring == None: + keyring = Keyring() + log.debug("Keyring started") class Keyring(object): - def get_api_key(self): - return "5093442" \ No newline at end of file + def get_api_key(self): + return "5093442" diff --git a/src/languageHandler.py b/src/languageHandler.py index d17aa61..93ef107 100644 --- a/src/languageHandler.py +++ b/src/languageHandler.py @@ -12,7 +12,7 @@ import gettext import paths import platform import application - + #a few Windows locale constants LOCALE_SLANGUAGE=0x2 LOCALE_SLANGDISPLAYNAME=0x6f @@ -20,195 +20,195 @@ LOCALE_SLANGDISPLAYNAME=0x6f curLang="en" def localeNameToWindowsLCID(localeName): - """Retreave the Windows locale identifier (LCID) for the given locale name - @param localeName: a string of 2letterLanguage_2letterCountry or or just 2letterLanguage - @type localeName: string - @returns: a Windows LCID - @rtype: integer - """ - #Windows Vista is able to convert locale names to LCIDs - func_LocaleNameToLCID=getattr(ctypes.windll.kernel32,'LocaleNameToLCID',None) - if func_LocaleNameToLCID is not None: - localeName=localeName.replace('_','-') - LCID=func_LocaleNameToLCID(str(localeName),0) - else: #Windows doesn't have this functionality, manually search Python's windows_locale dictionary for the LCID - localeName=locale.normalize(localeName) - if '.' in localeName: - localeName=localeName.split('.')[0] - LCList=[x[0] for x in locale.windows_locale.items() if x[1]==localeName] - if len(LCList)>0: - LCID=LCList[0] - else: - LCID=0 - return LCID + """Retreave the Windows locale identifier (LCID) for the given locale name + @param localeName: a string of 2letterLanguage_2letterCountry or or just 2letterLanguage + @type localeName: string + @returns: a Windows LCID + @rtype: integer + """ + #Windows Vista is able to convert locale names to LCIDs + func_LocaleNameToLCID=getattr(ctypes.windll.kernel32,'LocaleNameToLCID',None) + if func_LocaleNameToLCID is not None: + localeName=localeName.replace('_','-') + LCID=func_LocaleNameToLCID(str(localeName),0) + else: #Windows doesn't have this functionality, manually search Python's windows_locale dictionary for the LCID + localeName=locale.normalize(localeName) + if '.' in localeName: + localeName=localeName.split('.')[0] + LCList=[x[0] for x in locale.windows_locale.items() if x[1]==localeName] + if len(LCList)>0: + LCID=LCList[0] + else: + LCID=0 + return LCID def getLanguageDescription(language): - """Finds out the description (localized full name) of a given local name""" - desc=None - if platform.system() == "Windows": - LCID=localeNameToWindowsLCID(language) - if LCID!=0: - buf=ctypes.create_unicode_buffer(1024) - if '_' not in language: - res=ctypes.windll.kernel32.GetLocaleInfoW(LCID,LOCALE_SLANGDISPLAYNAME,buf,1024) - else: - res=0 - if res==0: - res=ctypes.windll.kernel32.GetLocaleInfoW(LCID,LOCALE_SLANGUAGE,buf,1024) - desc=buf.value - elif platform.system() == "Linux" or not desc: - desc={ - "am":pgettext("languageName","Amharic"), - "an":pgettext("languageName","Aragonese"), - "es":pgettext("languageName","Spanish"), - "pt":pgettext("languageName","Portuguese"), - "ru":pgettext("languageName","Russian"), - "it":pgettext("languageName","italian"), - "tr":pgettext("languageName","Turkey"), - "gl":pgettext("languageName","Galician"), - "ca":pgettext("languageName","Catala"), - "eu":pgettext("languageName","Vasque"), - "pl":pgettext("languageName","polish"), - "ar":pgettext("languageName","Arabic"), - "ne":pgettext("languageName","Nepali"), - "sr":pgettext("languageName","Serbian (Latin)"), - "ja":pgettext("languageName","Japanese"), - }.get(language,None) - return desc + """Finds out the description (localized full name) of a given local name""" + desc=None + if platform.system() == "Windows": + LCID=localeNameToWindowsLCID(language) + if LCID!=0: + buf=ctypes.create_unicode_buffer(1024) + if '_' not in language: + res=ctypes.windll.kernel32.GetLocaleInfoW(LCID,LOCALE_SLANGDISPLAYNAME,buf,1024) + else: + res=0 + if res==0: + res=ctypes.windll.kernel32.GetLocaleInfoW(LCID,LOCALE_SLANGUAGE,buf,1024) + desc=buf.value + elif platform.system() == "Linux" or not desc: + desc={ + "am":pgettext("languageName","Amharic"), + "an":pgettext("languageName","Aragonese"), + "es":pgettext("languageName","Spanish"), + "pt":pgettext("languageName","Portuguese"), + "ru":pgettext("languageName","Russian"), + "it":pgettext("languageName","italian"), + "tr":pgettext("languageName","Turkey"), + "gl":pgettext("languageName","Galician"), + "ca":pgettext("languageName","Catala"), + "eu":pgettext("languageName","Vasque"), + "pl":pgettext("languageName","polish"), + "ar":pgettext("languageName","Arabic"), + "ne":pgettext("languageName","Nepali"), + "sr":pgettext("languageName","Serbian (Latin)"), + "ja":pgettext("languageName","Japanese"), + }.get(language,None) + return desc def getAvailableLanguages(): - """generates a list of locale names, plus their full localized language and country names. - @rtype: list of tuples - """ - #Make a list of all the locales found in NVDA's locale dir - l=[x for x in os.listdir(paths.locale_path()) if not x.startswith('.')] - l=[x for x in l if os.path.isfile(os.path.join(paths.locale_path(), '%s/LC_MESSAGES/%s.po' % (x, application.short_name)))] - #Make sure that en (english) is in the list as it may not have any locale files, but is default - if 'en' not in l: - l.append('en') - l.sort() - #For each locale, ask Windows for its human readable display name - d=[] - for i in l: - desc=getLanguageDescription(i) - label="%s, %s"%(desc,i) if desc else i - d.append(label) - #include a 'user default, windows' language, which just represents the default language for this user account - l.append("system") - # Translators: the label for the Windows default NVDA interface language. - d.append(_("User default")) - #return a zipped up version of both the lists (a list with tuples of locale,label) - return list(zip(l,d)) + """generates a list of locale names, plus their full localized language and country names. + @rtype: list of tuples + """ + #Make a list of all the locales found in NVDA's locale dir + l=[x for x in os.listdir(paths.locale_path()) if not x.startswith('.')] + l=[x for x in l if os.path.isfile(os.path.join(paths.locale_path(), '%s/LC_MESSAGES/%s.po' % (x, application.short_name)))] + #Make sure that en (english) is in the list as it may not have any locale files, but is default + if 'en' not in l: + l.append('en') + l.sort() + #For each locale, ask Windows for its human readable display name + d=[] + for i in l: + desc=getLanguageDescription(i) + label="%s, %s"%(desc,i) if desc else i + d.append(label) + #include a 'user default, windows' language, which just represents the default language for this user account + l.append("system") + # Translators: the label for the Windows default NVDA interface language. + d.append(_("User default")) + #return a zipped up version of both the lists (a list with tuples of locale,label) + return list(zip(l,d)) def makePgettext(translations): - """Obtaina pgettext function for use with a gettext translations instance. - pgettext is used to support message contexts, - but Python 2.7's gettext module doesn't support this, - so NVDA must provide its own implementation. - """ - if isinstance(translations, gettext.GNUTranslations): - def pgettext(context, message): - message = str(message) - try: - # Look up the message with its context. - return translations._catalog["%s\x04%s" % (context, message)] - except KeyError: - return message - else: - def pgettext(context, message): - return str(message) - return pgettext + """Obtaina pgettext function for use with a gettext translations instance. + pgettext is used to support message contexts, + but Python 2.7's gettext module doesn't support this, + so NVDA must provide its own implementation. + """ + if isinstance(translations, gettext.GNUTranslations): + def pgettext(context, message): + message = str(message) + try: + # Look up the message with its context. + return translations._catalog["%s\x04%s" % (context, message)] + except KeyError: + return message + else: + def pgettext(context, message): + return str(message) + return pgettext def setLanguage(lang): - system = platform.system() - global curLang - try: - if lang=="system": - if system == "Windows": - windowsLCID=ctypes.windll.kernel32.GetUserDefaultUILanguage() - localeName=locale.windows_locale[windowsLCID] - elif system == "Darwin": - import Foundation - localeName = Foundation.NSLocale.currentLocale().identifier() - elif system == "Linux": - localeName = locale.getdefaultlocale()[0] - trans=gettext.translation(application.short_name, localedir=paths.locale_path(), languages=[localeName]) - curLang=localeName -# else: -# localeName=locale.getdefaultlocale()[0] -# trans=gettext.translation('twblue', localedir=paths.locale_path(), languages=[localeName]) -# curLang=localeName + system = platform.system() + global curLang + try: + if lang=="system": + if system == "Windows": + windowsLCID=ctypes.windll.kernel32.GetUserDefaultUILanguage() + localeName=locale.windows_locale[windowsLCID] + elif system == "Darwin": + import Foundation + localeName = Foundation.NSLocale.currentLocale().identifier() + elif system == "Linux": + localeName = locale.getdefaultlocale()[0] + trans=gettext.translation(application.short_name, localedir=paths.locale_path(), languages=[localeName]) + curLang=localeName +# else: +# localeName=locale.getdefaultlocale()[0] +# trans=gettext.translation('twblue', localedir=paths.locale_path(), languages=[localeName]) +# curLang=localeName - else: - trans=gettext.translation(application.short_name, localedir=paths.locale_path(), languages=[lang]) - curLang=lang - localeChanged=False - #Try setting Python's locale to lang -# try: - if system == "Windows": - locale.setlocale(locale.LC_ALL, langToWindowsLocale(lang)) - localeChanged=True - else: - locale.setlocale(locale.LC_ALL, lang) - localeChanged=True -# except: -# pass - if not localeChanged and '_' in lang: - #Python couldn'tsupport the language_country locale, just try language. - try: - locale.setlocale(locale.LC_ALL, lang.split('_')[0]) - except: - pass - #Set the windows locale for this thread (NVDA core) to this locale. - if system == "Windows": - LCID=localeNameToWindowsLCID(lang) - ctypes.windll.kernel32.SetThreadLocale(LCID) - except IOError: - trans=gettext.translation(application.short_name, fallback=True) - curLang="en" - if sys.version[0] == "3": - trans.install() - else: - trans.install(unicode=True) - # Install our pgettext function. -# __builtin__.__dict__["pgettext"] = makePgettext(trans) + else: + trans=gettext.translation(application.short_name, localedir=paths.locale_path(), languages=[lang]) + curLang=lang + localeChanged=False + #Try setting Python's locale to lang +# try: + if system == "Windows": + locale.setlocale(locale.LC_ALL, langToWindowsLocale(lang)) + localeChanged=True + else: + locale.setlocale(locale.LC_ALL, lang) + localeChanged=True +# except: +# pass + if not localeChanged and '_' in lang: + #Python couldn'tsupport the language_country locale, just try language. + try: + locale.setlocale(locale.LC_ALL, lang.split('_')[0]) + except: + pass + #Set the windows locale for this thread (NVDA core) to this locale. + if system == "Windows": + LCID=localeNameToWindowsLCID(lang) + ctypes.windll.kernel32.SetThreadLocale(LCID) + except IOError: + trans=gettext.translation(application.short_name, fallback=True) + curLang="en" + if sys.version[0] == "3": + trans.install() + else: + trans.install(unicode=True) + # Install our pgettext function. +# __builtin__.__dict__["pgettext"] = makePgettext(trans) def getLanguage(): - return curLang + return curLang def normalizeLanguage(lang): - """ - Normalizes a language-dialect string in to a standard form we can deal with. - Converts any dash to underline, and makes sure that language is lowercase and dialect is upercase. - """ - lang=lang.replace('-','_') - ld=lang.split('_') - ld[0]=ld[0].lower() - #Filter out meta languages such as x-western - if ld[0]=='x': - return None - if len(ld)>=2: - ld[1]=ld[1].upper() - return "_".join(ld) + """ + Normalizes a language-dialect string in to a standard form we can deal with. + Converts any dash to underline, and makes sure that language is lowercase and dialect is upercase. + """ + lang=lang.replace('-','_') + ld=lang.split('_') + ld[0]=ld[0].lower() + #Filter out meta languages such as x-western + if ld[0]=='x': + return None + if len(ld)>=2: + ld[1]=ld[1].upper() + return "_".join(ld) def langToWindowsLocale(lang): - languages = {"en": "eng", - "ar": "ara", - "ca": "cat", + languages = {"en": "eng", + "ar": "ara", + "ca": "cat", "de": "deu", - "es": "esp", - "fi": "fin", - "fr": "fre_FRA", - "gl": "glc", - "eu": "euq", - "hu": "hun", - "hr": "hrv", - "it": "ita", - "ja": "jpn", - "pl": "plk", - "pt": "ptb", - "ru": "rus", - "tr": "trk", - "sr": "eng", - } - return languages[lang] + "es": "esp", + "fi": "fin", + "fr": "fre_FRA", + "gl": "glc", + "eu": "euq", + "hu": "hun", + "hr": "hrv", + "it": "ita", + "ja": "jpn", + "pl": "plk", + "pt": "ptb", + "ru": "rus", + "tr": "trk", + "sr": "eng", + } + return languages[lang] diff --git a/src/main.py b/src/main.py index 2baaa73..6f5085c 100644 --- a/src/main.py +++ b/src/main.py @@ -15,7 +15,7 @@ import logging import keys import application if hasattr(sys, "frozen"): - sys.excepthook = lambda x, y, z: logging.critical(''.join(traceback.format_exception(x, y, z))) + sys.excepthook = lambda x, y, z: logging.critical(''.join(traceback.format_exception(x, y, z))) from mysc.thread_utils import call_threaded from wxUI import commonMessages @@ -24,48 +24,48 @@ log = logging.getLogger("main") orig_session_init = None def setup(): - global orig_session_init - log.debug("Starting Socializer %s" % (application.version,)) - config.setup() - if config.app["app-settings"]["debug_logging"] == True: - logger.app_handler.setLevel(logging.DEBUG) - log.info("Using %s %s" % (platform.system(), platform.architecture()[0])) - log.debug("Application path is %s" % (paths.app_path(),)) - log.debug("config path is %s" % (paths.config_path(),)) - output.setup() - languageHandler.setLanguage(config.app["app-settings"]["language"]) - log.debug("Language set to %s" % (languageHandler.getLanguage())) - keys.setup() - app = widgetUtils.mainLoopObject() - if config.app["app-settings"]["first_start"]: - log.debug("Detected first time execution.") - proxy_option = commonMessages.proxy_question() - if proxy_option == widgetUtils.YES: - config.app["app-settings"]["use_proxy"] = True - log.debug("User has requested to use proxy for connecting to VK.") - config.app["app-settings"]["first_start"] = False - config.app.write() - if config.app["app-settings"]["use_proxy"]: - log.debug("Enabling proxy support... ") - import requests - orig_session_init=requests.sessions.Session.__init__ - requests.sessions.Session.__init__=patched_session_init - requests.Session.__init__=patched_session_init - from controller import mainController - from sessionmanager import sessionManager + global orig_session_init + log.debug("Starting Socializer %s" % (application.version,)) + config.setup() + if config.app["app-settings"]["debug_logging"] == True: + logger.app_handler.setLevel(logging.DEBUG) + log.info("Using %s %s" % (platform.system(), platform.architecture()[0])) + log.debug("Application path is %s" % (paths.app_path(),)) + log.debug("config path is %s" % (paths.config_path(),)) + output.setup() + languageHandler.setLanguage(config.app["app-settings"]["language"]) + log.debug("Language set to %s" % (languageHandler.getLanguage())) + keys.setup() + app = widgetUtils.mainLoopObject() + if config.app["app-settings"]["first_start"]: + log.debug("Detected first time execution.") + proxy_option = commonMessages.proxy_question() + if proxy_option == widgetUtils.YES: + config.app["app-settings"]["use_proxy"] = True + log.debug("User has requested to use proxy for connecting to VK.") + config.app["app-settings"]["first_start"] = False + config.app.write() + if config.app["app-settings"]["use_proxy"]: + log.debug("Enabling proxy support... ") + import requests + orig_session_init=requests.sessions.Session.__init__ + requests.sessions.Session.__init__=patched_session_init + requests.Session.__init__=patched_session_init + from controller import mainController + from sessionmanager import sessionManager - log.debug("Created Application mainloop object") - sm = sessionManager.sessionManagerController() - sm.show() - del sm - r = mainController.Controller() - call_threaded(r.login) - app.run() + log.debug("Created Application mainloop object") + sm = sessionManager.sessionManagerController() + sm.show() + del sm + r = mainController.Controller() + call_threaded(r.login) + app.run() def patched_session_init(self): - global orig_session_init - orig_session_init(self) - self.proxies={"http": "http://socializer:socializer@socializer.su:3128", - "https": "http://socializer:socializer@socializer.su:3128"} + global orig_session_init + orig_session_init(self) + self.proxies={"http": "http://socializer:socializer@socializer.su:3128", + "https": "http://socializer:socializer@socializer.su:3128"} setup() diff --git a/src/mysc/localization.py b/src/mysc/localization.py index 01a7357..060ab40 100644 --- a/src/mysc/localization.py +++ b/src/mysc/localization.py @@ -5,14 +5,13 @@ import logging log = logging.getLogger("mysc.localization") def get(rootFolder): - log.debug("Getting documentation folder. RootFolder: %s" % (rootFolder,)) - defaultLocale = languageHandler.curLang - if len(defaultLocale) > 2: - defaultLocale = defaultLocale[:2] - log.debug("Locale: %s" % (defaultLocale,)) - if os.path.exists(rootFolder+"/"+defaultLocale): - return defaultLocale - else: - log.debug("The folder does not exist, using the English folder...") - return "en" - + log.debug("Getting documentation folder. RootFolder: %s" % (rootFolder,)) + defaultLocale = languageHandler.curLang + if len(defaultLocale) > 2: + defaultLocale = defaultLocale[:2] + log.debug("Locale: %s" % (defaultLocale,)) + if os.path.exists(rootFolder+"/"+defaultLocale): + return defaultLocale + else: + log.debug("The folder does not exist, using the English folder...") + return "en" diff --git a/src/mysc/repeating_timer.py b/src/mysc/repeating_timer.py index 41b4a5c..fcc3c02 100644 --- a/src/mysc/repeating_timer.py +++ b/src/mysc/repeating_timer.py @@ -4,34 +4,34 @@ import logging log = logging.getLogger("mysc.repeating_timer") class RepeatingTimer(threading.Thread): - """Call a function after a specified number of seconds, it will then repeat again after the specified number of seconds - Note: If the function provided takes time to execute, this time is NOT taken from the next wait period + """Call a function after a specified number of seconds, it will then repeat again after the specified number of seconds + Note: If the function provided takes time to execute, this time is NOT taken from the next wait period - t = RepeatingTimer(30.0, f, args=[], kwargs={}) - t.start() - t.cancel() # stop the timer's actions - """ + t = RepeatingTimer(30.0, f, args=[], kwargs={}) + t.start() + t.cancel() # stop the timer's actions + """ - def __init__(self, interval, function, daemon=True, *args, **kwargs): - threading.Thread.__init__(self) - self.daemon = daemon - self.interval = float(interval) - self.function = function - self.args = args - self.kwargs = kwargs - self.finished = threading.Event() + def __init__(self, interval, function, daemon=True, *args, **kwargs): + threading.Thread.__init__(self) + self.daemon = daemon + self.interval = float(interval) + self.function = function + self.args = args + self.kwargs = kwargs + self.finished = threading.Event() - def cancel(self): - """Stop the timer if it hasn't finished yet""" - log.debug("Stopping repeater for %s" % (self.function,)) - self.finished.set() - stop = cancel + def cancel(self): + """Stop the timer if it hasn't finished yet""" + log.debug("Stopping repeater for %s" % (self.function,)) + self.finished.set() + stop = cancel - def run(self): - while not self.finished.is_set(): - self.finished.wait(self.interval) - if not self.finished.is_set(): #In case someone has canceled while waiting - try: - self.function(*self.args, **self.kwargs) - except: - log.exception("Execution failed. Function: %r args: %r and kwargs: %r" % (self.function, self.args, self.kwargs)) + def run(self): + while not self.finished.is_set(): + self.finished.wait(self.interval) + if not self.finished.is_set(): #In case someone has canceled while waiting + try: + self.function(*self.args, **self.kwargs) + except: + log.exception("Execution failed. Function: %r args: %r and kwargs: %r" % (self.function, self.args, self.kwargs)) diff --git a/src/mysc/restart.py b/src/mysc/restart.py index 400ef53..82716ce 100644 --- a/src/mysc/restart.py +++ b/src/mysc/restart.py @@ -3,10 +3,10 @@ from __future__ import unicode_literals import sys, os def restart_program(): - """ Function that restarts the application if is executed.""" - args = sys.argv[:] - if not hasattr(sys, "frozen"): - args.insert(0, sys.executable) - if sys.platform == 'win32': - args = ['"%s"' % arg for arg in args] - os.execv(sys.executable, args) \ No newline at end of file + """ Function that restarts the application if is executed.""" + args = sys.argv[:] + if not hasattr(sys, "frozen"): + args.insert(0, sys.executable) + if sys.platform == 'win32': + args = ['"%s"' % arg for arg in args] + os.execv(sys.executable, args) diff --git a/src/mysc/thread_utils.py b/src/mysc/thread_utils.py index fec4bec..58d04f3 100644 --- a/src/mysc/thread_utils.py +++ b/src/mysc/thread_utils.py @@ -5,13 +5,13 @@ standard_library.install_aliases() import threading def call_threaded(func, *args, **kwargs): - #Call the given function in a daemonized thread and return the thread. - def new_func(*a, **k): + #Call the given function in a daemonized thread and return the thread. + def new_func(*a, **k): # try: - func(*a, **k) + func(*a, **k) # except: # pass - thread = threading.Thread(target=new_func, args=args, kwargs=kwargs) - thread.daemon = True - thread.start() - return thread + thread = threading.Thread(target=new_func, args=args, kwargs=kwargs) + thread.daemon = True + thread.start() + return thread diff --git a/src/output.py b/src/output.py index c5127d7..1729db1 100644 --- a/src/output.py +++ b/src/output.py @@ -9,34 +9,34 @@ speaker = None retries = 0 def speak(text, interrupt=0): - global speaker, retries - if not speaker: - setup() - try: - speaker.speak(text, interrupt) - except: - if retries < 5: - retries = retries + 1 - speak(text) + global speaker, retries + if not speaker: + setup() + try: + speaker.speak(text, interrupt) + except: + if retries < 5: + retries = retries + 1 + speak(text) # speaker.braille(text) def setup (): - global speaker - logger.debug("Initializing output subsystem.") - try: + global speaker + logger.debug("Initializing output subsystem.") + try: # speaker = speech.Speaker(speech.outputs.Sapi5()) # else: - speaker = outputs.auto.Auto() - except: - logger.exception("Output: Error during initialization.") + speaker = outputs.auto.Auto() + except: + logger.exception("Output: Error during initialization.") def enable_sapi(): - speaker = outputs.sapi.SAPI5() + speaker = outputs.sapi.SAPI5() def copy(text): - import win32clipboard - #Copies text to the clipboard. - win32clipboard.OpenClipboard() - win32clipboard.EmptyClipboard() - win32clipboard.SetClipboardText(text) - win32clipboard.CloseClipboard() + import win32clipboard + #Copies text to the clipboard. + win32clipboard.OpenClipboard() + win32clipboard.EmptyClipboard() + win32clipboard.SetClipboardText(text) + win32clipboard.CloseClipboard() diff --git a/src/paths.py b/src/paths.py index 8153a74..80c602d 100644 --- a/src/paths.py +++ b/src/paths.py @@ -15,58 +15,58 @@ fsencoding = sys.getfilesystemencoding() #log = logging.getLogger("paths") if len(glob.glob("Uninstall.exe")) > 0: # installed copy - mode= "installed" + mode= "installed" def app_path(): - return paths_.app_path() + return paths_.app_path() def config_path(): - global mode, directory - if mode == "portable": - if directory != None: path = os.path.join(directory, "config") - elif directory == None: path = os.path.join(app_path(), "config") - elif mode == "installed": - path = os.path.join(data_path(), "config") - if not os.path.exists(path): -# log.debug("%s path does not exist, creating..." % (path,)) - os.mkdir(path) - return path + global mode, directory + if mode == "portable": + if directory != None: path = os.path.join(directory, "config") + elif directory == None: path = os.path.join(app_path(), "config") + elif mode == "installed": + path = os.path.join(data_path(), "config") + if not os.path.exists(path): +# log.debug("%s path does not exist, creating..." % (path,)) + os.mkdir(path) + return path def logs_path(): - global mode, directory - if mode == "portable": - if directory != None: path = os.path.join(directory, "logs") - elif directory == None: path = os.path.join(app_path(), "logs") - elif mode == "installed": - path = os.path.join(data_path(), "logs") - if not os.path.exists(path): -# log.debug("%s path does not exist, creating..." % (path,)) - os.mkdir(path) - return path + global mode, directory + if mode == "portable": + if directory != None: path = os.path.join(directory, "logs") + elif directory == None: path = os.path.join(app_path(), "logs") + elif mode == "installed": + path = os.path.join(data_path(), "logs") + if not os.path.exists(path): +# log.debug("%s path does not exist, creating..." % (path,)) + os.mkdir(path) + return path def data_path(app_name='socializer'): - if platform.system() == "Windows": - data_path = os.path.join(os.getenv("AppData"), app_name) - else: - data_path = os.path.join(os.environ['HOME'], ".%s" % app_name) - if not os.path.exists(data_path): - os.mkdir(data_path) - return data_path + if platform.system() == "Windows": + data_path = os.path.join(os.getenv("AppData"), app_name) + else: + data_path = os.path.join(os.environ['HOME'], ".%s" % app_name) + if not os.path.exists(data_path): + os.mkdir(data_path) + return data_path def locale_path(): - return os.path.join(app_path(), "locales") + return os.path.join(app_path(), "locales") def sound_path(): - return os.path.join(app_path(), "sounds") + return os.path.join(app_path(), "sounds") def com_path(): - global mode, directory - if mode == "portable": - if directory != None: path = os.path.join(directory, "com_cache") - elif directory == None: path = os.path.join(app_path(), "com_cache") - elif mode == "installed": - path = os.path.join(data_path(), "com_cache") - if not os.path.exists(path): -# log.debug("%s path does not exist, creating..." % (path,)) - os.mkdir(path) - return path + global mode, directory + if mode == "portable": + if directory != None: path = os.path.join(directory, "com_cache") + elif directory == None: path = os.path.join(app_path(), "com_cache") + elif mode == "installed": + path = os.path.join(data_path(), "com_cache") + if not os.path.exists(path): +# log.debug("%s path does not exist, creating..." % (path,)) + os.mkdir(path) + return path diff --git a/src/presenters/__init__.py b/src/presenters/__init__.py index 78017fb..88fbb10 100644 --- a/src/presenters/__init__.py +++ b/src/presenters/__init__.py @@ -1,15 +1,15 @@ # -*- coding: utf-8 -*- """ A "presenter" in the socializer's terminology is a module that handles business logic in the application's workflow. - All presenter classes should derive from base.basePresenter and will be completely abstracted from views (the GUI elements). It means presenters and views don't know anything about the each other. - Both Presenters and views can communicate through the interactors. Interactors are responsible to receive user input and send requests to the presenters, aswell as receiving presenter requests and render those in the view. - So, in a tipical user interaction made in socializer, the following could happen when someone decides to do something: - 1. A new presenter is created, with two mandatory arguments: The corresponding view and interactor. - 2. The presenter will call to the install() method in the interactor, to connect all GUI events to their corresponding methods. All of these functions will be present in the interactor only. - 3. After install(), the presenter will run the View, which will display the graphical user interface that users can see and interact with. The view is the only layer directly accessible from the user world and does not handle any kind of logic. - 4. If the user presses a button or generates an event connected to a function in the interactor side, the function will be executed in the interactor. The interactor is aware of the View, and holds a reference to the presenter. The interactor should call other GUI elements if necessary and handle some logic (related to GUI, like yes/no dialogs). The interactor can call the presenter to retrieve some information, though the interactor cannot perform any business logic (like altering the cache database, retrieving usernames and so on). - 5. If the interactor calls something in the presenter, it will be executed. The presenter knows everything about VK and the session object, so it will fetch data, save it in the cache, call other methods from VK and what not. If the presenter wants to change something in the GUI elements (for example, hiding a control or displaying something else), it will send a pubsub event that the interactor will receive and act on accordingly. - - By using this design pattern it allows more decoupled code, easier testing (as we don't need to instantiate the views) and easy to switch (or add) a new graphical user interface by replacing interactors and views. + All presenter classes should derive from base.basePresenter and will be completely abstracted from views (the GUI elements). It means presenters and views don't know anything about the each other. + Both Presenters and views can communicate through the interactors. Interactors are responsible to receive user input and send requests to the presenters, aswell as receiving presenter requests and render those in the view. + So, in a tipical user interaction made in socializer, the following could happen when someone decides to do something: + 1. A new presenter is created, with two mandatory arguments: The corresponding view and interactor. + 2. The presenter will call to the install() method in the interactor, to connect all GUI events to their corresponding methods. All of these functions will be present in the interactor only. + 3. After install(), the presenter will run the View, which will display the graphical user interface that users can see and interact with. The view is the only layer directly accessible from the user world and does not handle any kind of logic. + 4. If the user presses a button or generates an event connected to a function in the interactor side, the function will be executed in the interactor. The interactor is aware of the View, and holds a reference to the presenter. The interactor should call other GUI elements if necessary and handle some logic (related to GUI, like yes/no dialogs). The interactor can call the presenter to retrieve some information, though the interactor cannot perform any business logic (like altering the cache database, retrieving usernames and so on). + 5. If the interactor calls something in the presenter, it will be executed. The presenter knows everything about VK and the session object, so it will fetch data, save it in the cache, call other methods from VK and what not. If the presenter wants to change something in the GUI elements (for example, hiding a control or displaying something else), it will send a pubsub event that the interactor will receive and act on accordingly. + + By using this design pattern it allows more decoupled code, easier testing (as we don't need to instantiate the views) and easy to switch (or add) a new graphical user interface by replacing interactors and views. """ from . import player from .base import * @@ -19,4 +19,4 @@ from .blacklist import * from .createPosts import * from .displayPosts import * from .configuration import * -from .profiles import * \ No newline at end of file +from .profiles import * diff --git a/src/presenters/__pycache__/__init__.py b/src/presenters/__pycache__/__init__.py index 7e7e8ea..5c6a587 100644 --- a/src/presenters/__pycache__/__init__.py +++ b/src/presenters/__pycache__/__init__.py @@ -1,19 +1,19 @@ # -*- coding: utf-8 -*- """ A "presenter" in the socializer's terminology is a module that handles business logic in the application's workflow. - All presenter classes should derive from base.basePresenter and will be completely abstracted from views (the GUI elements). It means presenters and views don't know anything about the each other. - Both Presenters and views can communicate through the interactors. Interactors are responsible to receive user input and send requests to the presenters, aswell as receiving presenter requests and render those in the view. - So, in a tipical user interaction made in socializer, the following could happen when someone decides to do something: - 1. A new presenter is created, with two mandatory arguments: The corresponding view and interactor. - 2. The presenter will call to the install() method in the interactor, to connect all GUI events to their corresponding methods. All of these functions will be present in the interactor only. - 3. After install(), the presenter will run the View, which will display the graphical user interface that users can see and interact with. The view is the only layer directly accessible from the user world and does not handle any kind of logic. - 4. If the user presses a button or generates an event connected to a function in the interactor side, the function will be executed in the interactor. The interactor is aware of the View, and holds a reference to the presenter. The interactor should call other GUI elements if necessary and handle some logic (related to GUI, like yes/no dialogs). The interactor can call the presenter to retrieve some information, though the interactor cannot perform any business logic (like altering the cache database, retrieving usernames and so on). - 5. If the interactor calls something in the presenter, it will be executed. The presenter knows everything about VK and the session object, so it will fetch data, save it in the cache, call other methods from VK and what not. If the presenter wants to change something in the GUI elements (for example, hiding a control or displaying something else), it will send a pubsub event that the interactor will receive and act on accordingly. - - By using this design pattern it allows more decoupled code, easier testing (as we don't need to instantiate the views) and easy to switch (or add) a new graphical user interface by replacing interactors and views. + All presenter classes should derive from base.basePresenter and will be completely abstracted from views (the GUI elements). It means presenters and views don't know anything about the each other. + Both Presenters and views can communicate through the interactors. Interactors are responsible to receive user input and send requests to the presenters, aswell as receiving presenter requests and render those in the view. + So, in a tipical user interaction made in socializer, the following could happen when someone decides to do something: + 1. A new presenter is created, with two mandatory arguments: The corresponding view and interactor. + 2. The presenter will call to the install() method in the interactor, to connect all GUI events to their corresponding methods. All of these functions will be present in the interactor only. + 3. After install(), the presenter will run the View, which will display the graphical user interface that users can see and interact with. The view is the only layer directly accessible from the user world and does not handle any kind of logic. + 4. If the user presses a button or generates an event connected to a function in the interactor side, the function will be executed in the interactor. The interactor is aware of the View, and holds a reference to the presenter. The interactor should call other GUI elements if necessary and handle some logic (related to GUI, like yes/no dialogs). The interactor can call the presenter to retrieve some information, though the interactor cannot perform any business logic (like altering the cache database, retrieving usernames and so on). + 5. If the interactor calls something in the presenter, it will be executed. The presenter knows everything about VK and the session object, so it will fetch data, save it in the cache, call other methods from VK and what not. If the presenter wants to change something in the GUI elements (for example, hiding a control or displaying something else), it will send a pubsub event that the interactor will receive and act on accordingly. + + By using this design pattern it allows more decoupled code, easier testing (as we don't need to instantiate the views) and easy to switch (or add) a new graphical user interface by replacing interactors and views. """ from .attach import * from .audioRecorder import * from .postCreation import * from .postDisplayer import * from .configuration import * -from .profiles import * \ No newline at end of file +from .profiles import * diff --git a/src/presenters/attach.py b/src/presenters/attach.py index b32f8c5..fd895e2 100644 --- a/src/presenters/attach.py +++ b/src/presenters/attach.py @@ -15,109 +15,109 @@ from . import audioRecorder, base log = logging.getLogger(__file__) class attachPresenter(base.basePresenter): - """ Controller used in some sections of the application, it can do the following: + """ Controller used in some sections of the application, it can do the following: - * Handle all user input related to adding local or online files (online files are those already uploaded in vk). - * Prepare local files to be uploaded once a post will be sent (no uploading work is done here, but structured dicts will be generated). - * Parse online files and allow addition of them as attachments, so this controller will add both local and online files in the same dialog. + * Handle all user input related to adding local or online files (online files are those already uploaded in vk). + * Prepare local files to be uploaded once a post will be sent (no uploading work is done here, but structured dicts will be generated). + * Parse online files and allow addition of them as attachments, so this controller will add both local and online files in the same dialog. """ - def __init__(self, session, view, interactor, voice_messages=False): - """ Constructor. - @ session sessionmanager.session object: an object capable of calling all VK methods and accessing the session database. - @voice_messages bool: If True, will add a button for sending voice messages. - """ - super(attachPresenter, self).__init__(view=view, interactor=interactor, modulename="attach") - self.session = session - # Self.attachments will hold a reference to all attachments added to the dialog. - self.attachments = list() - self.run() + def __init__(self, session, view, interactor, voice_messages=False): + """ Constructor. +@ session sessionmanager.session object: an object capable of calling all VK methods and accessing the session database. + @voice_messages bool: If True, will add a button for sending voice messages. + """ + super(attachPresenter, self).__init__(view=view, interactor=interactor, modulename="attach") + self.session = session + # Self.attachments will hold a reference to all attachments added to the dialog. + self.attachments = list() + self.run() - def upload_image(self, image, description): - """ allows uploading an image from the computer. Description will be used when posting to VK. - """ - imageInfo = {"type": "photo", "file": image, "description": description, "from": "local"} - self.attachments.append(imageInfo) - # Translators: This is the text displayed in the attachments dialog, when the user adds a photo. - info = [_("Photo"), description] - self.send_message("insert_attachment", attachment=info) - self.send_message("enable_control", control="remove") + def upload_image(self, image, description): + """ allows uploading an image from the computer. Description will be used when posting to VK. + """ + imageInfo = {"type": "photo", "file": image, "description": description, "from": "local"} + self.attachments.append(imageInfo) + # Translators: This is the text displayed in the attachments dialog, when the user adds a photo. + info = [_("Photo"), description] + self.send_message("insert_attachment", attachment=info) + self.send_message("enable_control", control="remove") - def upload_audio(self, audio): - """ Allows uploading an audio file from the computer. Only mp3 files are supported. """ - if audio != None: - # Define data structure for this attachment, as will be required by VK API later. - # Let's extract the ID3 tags to show them in the list and send them to VK, too. - try: - audio_tags = ID3(audio) - if "TIT2" in audio_tags: - title = audio_tags["TIT2"].text[0] - else: - title = _("Untitled") - if "TPE1" in audio_tags: - artist = audio_tags["TPE1"].text[0] - else: - artist = _("Unknown artist") - except ID3NoHeaderError: # File doesn't include ID3 tags so let's assume unknown artist. - artist = _("Unknown artist") - title = os.path.basename(audio).replace(".mp3", "") - audioInfo = {"type": "audio", "file": audio, "from": "local", "title": title, "artist": artist} - self.attachments.append(audioInfo) - # Translators: This is the text displayed in the attachments dialog, when the user adds an audio file. - info = [_("Audio file"), "{title} - {artist}".format(title=title, artist=artist)] - self.send_message("insert_attachment", attachment=info) - self.send_message("enable_control", control="remove") + def upload_audio(self, audio): + """ Allows uploading an audio file from the computer. Only mp3 files are supported. """ + if audio != None: + # Define data structure for this attachment, as will be required by VK API later. + # Let's extract the ID3 tags to show them in the list and send them to VK, too. + try: + audio_tags = ID3(audio) + if "TIT2" in audio_tags: + title = audio_tags["TIT2"].text[0] + else: + title = _("Untitled") + if "TPE1" in audio_tags: + artist = audio_tags["TPE1"].text[0] + else: + artist = _("Unknown artist") + except ID3NoHeaderError: # File doesn't include ID3 tags so let's assume unknown artist. + artist = _("Unknown artist") + title = os.path.basename(audio).replace(".mp3", "") + audioInfo = {"type": "audio", "file": audio, "from": "local", "title": title, "artist": artist} + self.attachments.append(audioInfo) + # Translators: This is the text displayed in the attachments dialog, when the user adds an audio file. + info = [_("Audio file"), "{title} - {artist}".format(title=title, artist=artist)] + self.send_message("insert_attachment", attachment=info) + self.send_message("enable_control", control="remove") - def upload_document(self, document): - """ allows uploading a document from the computer. - """ - doc_info = {"type": "document", "file": document, "from": "local", "title": os.path.basename(os.path.splitext(document)[0])} - self.attachments.append(doc_info) - # Translators: This is the text displayed in the attachments dialog, when the user adds a document. - info = [_("Document"), os.path.basename(document)] - self.send_message("insert_attachment", attachment=info) - self.send_message("enable_control", control="remove") + def upload_document(self, document): + """ allows uploading a document from the computer. + """ + doc_info = {"type": "document", "file": document, "from": "local", "title": os.path.basename(os.path.splitext(document)[0])} + self.attachments.append(doc_info) + # Translators: This is the text displayed in the attachments dialog, when the user adds a document. + info = [_("Document"), os.path.basename(document)] + self.send_message("insert_attachment", attachment=info) + self.send_message("enable_control", control="remove") - def upload_voice_message(self): - a = audioRecorder.audioRecorderPresenter(view=views.audioRecorderDialog(), interactor=interactors.audioRecorderInteractor()) - if a.file != None and a.duration != 0: - audioInfo = {"type": "voice_message", "file": a.file, "from": "local"} - self.attachments.append(audioInfo) - # Translators: This is the text displayed in the attachments dialog, when the user adds an audio file. - info = [_("Voice message"), seconds_to_string(a.duration,)] - self.send_message("insert_attachment", attachment=info) - self.send_message("enable_control", control="remove") + def upload_voice_message(self): + a = audioRecorder.audioRecorderPresenter(view=views.audioRecorderDialog(), interactor=interactors.audioRecorderInteractor()) + if a.file != None and a.duration != 0: + audioInfo = {"type": "voice_message", "file": a.file, "from": "local"} + self.attachments.append(audioInfo) + # Translators: This is the text displayed in the attachments dialog, when the user adds an audio file. + info = [_("Voice message"), seconds_to_string(a.duration,)] + self.send_message("insert_attachment", attachment=info) + self.send_message("enable_control", control="remove") - ####### ToDo: replace this with selector presenter when finished. - def get_available_audios(self): - # Let's reuse the already downloaded audios. - list_of_audios = self.session.db["me_audio"]["items"] - audios = [] - for i in list_of_audios: - audios.append("{0}, {1}".format(i["title"], i["artist"])) - return audios + ####### ToDo: replace this with selector presenter when finished. + def get_available_audios(self): + # Let's reuse the already downloaded audios. + list_of_audios = self.session.db["me_audio"]["items"] + audios = [] + for i in list_of_audios: + audios.append("{0}, {1}".format(i["title"], i["artist"])) + return audios - def take_audios(self, audios_list): - list_of_audios = self.session.db["me_audio"]["items"] - for i in audios_list: - info = dict(type="audio", id=list_of_audios[i]["id"], owner_id=list_of_audios[i]["owner_id"]) - info["from"] = "online" - self.attachments.append(info) - # Translators: This is the text displayed in the attachments dialog, when the user adds an audio file. - info2 = [_("Audio file"), "{0} - {1}".format(list_of_audios[i]["title"], list_of_audios[i]["artist"])] - self.send_message("insert_attachment", attachment=info2) - self.check_remove_status() + def take_audios(self, audios_list): + list_of_audios = self.session.db["me_audio"]["items"] + for i in audios_list: + info = dict(type="audio", id=list_of_audios[i]["id"], owner_id=list_of_audios[i]["owner_id"]) + info["from"] = "online" + self.attachments.append(info) + # Translators: This is the text displayed in the attachments dialog, when the user adds an audio file. + info2 = [_("Audio file"), "{0} - {1}".format(list_of_audios[i]["title"], list_of_audios[i]["artist"])] + self.send_message("insert_attachment", attachment=info2) + self.check_remove_status() - def remove_attachment(self, item_index): - """ Remove the currently focused item from the attachments list.""" - log.debug("Removing item %d" % (item_index,)) - if item_index == -1: item_index = 0 - self.attachments.pop(item_index) - self.send_message("remove_attachment", attachment=item_index) - self.check_remove_status() - log.debug("Removed") + def remove_attachment(self, item_index): + """ Remove the currently focused item from the attachments list.""" + log.debug("Removing item %d" % (item_index,)) + if item_index == -1: item_index = 0 + self.attachments.pop(item_index) + self.send_message("remove_attachment", attachment=item_index) + self.check_remove_status() + log.debug("Removed") - def check_remove_status(self): - """ Checks whether the remove button should remain enabled.""" - if len(self.attachments) == 0: - self.send_message("disable_control", control="remove") + def check_remove_status(self): + """ Checks whether the remove button should remain enabled.""" + if len(self.attachments) == 0: + self.send_message("disable_control", control="remove") diff --git a/src/presenters/audioRecorder.py b/src/presenters/audioRecorder.py index 04673c9..2545b04 100644 --- a/src/presenters/audioRecorder.py +++ b/src/presenters/audioRecorder.py @@ -10,102 +10,102 @@ from mysc.thread_utils import call_threaded from . import base class audioRecorderPresenter(base.basePresenter): - def __init__(self, view, interactor): - super(audioRecorderPresenter, self).__init__(view=view, interactor=interactor, modulename="audiorecorder") - self.recorded = False - self.recording = None - self.duration = 0 - self.playing = None - self.file = None - self.run() + def __init__(self, view, interactor): + super(audioRecorderPresenter, self).__init__(view=view, interactor=interactor, modulename="audiorecorder") + self.recorded = False + self.recording = None + self.duration = 0 + self.playing = None + self.file = None + self.run() - def toggle_recording(self, *args, **kwargs): - if self.recording != None: - self.stop_recording() - else: - self.start_recording() + def toggle_recording(self, *args, **kwargs): + if self.recording != None: + self.stop_recording() + else: + self.start_recording() - def start_recording(self): - self.file = tempfile.mktemp(suffix='.wav') - self.recording = sound.get_recording(self.file) - self.duration = time.time() - self.recording.play() - self.send_message("set_label", control="record", label=_("&Stop")) - output.speak(_("Recording")) - self.send_message("disable_control", control="ok") + def start_recording(self): + self.file = tempfile.mktemp(suffix='.wav') + self.recording = sound.get_recording(self.file) + self.duration = time.time() + self.recording.play() + self.send_message("set_label", control="record", label=_("&Stop")) + output.speak(_("Recording")) + self.send_message("disable_control", control="ok") - def stop_recording(self): - self.recording.stop() - self.duration = int(time.time()-self.duration) - self.recording.free() - output.speak(_("Stopped")) - self.recorded = True - self.send_message("set_label", control="record", label=_("&Record")) - self.send_message("disable_control", control="record") - self.send_message("enable_control", control="play") - self.send_message("enable_control", control="discard") - self.send_message("enable_control", control="ok") - self.send_message("focus_control", control="play") + def stop_recording(self): + self.recording.stop() + self.duration = int(time.time()-self.duration) + self.recording.free() + output.speak(_("Stopped")) + self.recorded = True + self.send_message("set_label", control="record", label=_("&Record")) + self.send_message("disable_control", control="record") + self.send_message("enable_control", control="play") + self.send_message("enable_control", control="discard") + self.send_message("enable_control", control="ok") + self.send_message("focus_control", control="play") - def discard_recording(self, *args, **kwargs): - if self.playing: - self._stop() - if self.recording != None: - self.cleanup() - self.send_message("disable_control", control="play") - self.send_message("disable_control", control="ok") - self.file = None - self.send_message("enable_control", control="record") - self.send_message("focus_control", control="record") - self.send_message("disable_control", control="discard") - self.recording = None - output.speak(_("Discarded")) + def discard_recording(self, *args, **kwargs): + if self.playing: + self._stop() + if self.recording != None: + self.cleanup() + self.send_message("disable_control", control="play") + self.send_message("disable_control", control="ok") + self.file = None + self.send_message("enable_control", control="record") + self.send_message("focus_control", control="record") + self.send_message("disable_control", control="discard") + self.recording = None + output.speak(_("Discarded")) - def play(self, *args, **kwargs): - if not self.playing: - call_threaded(self._play) - else: - self._stop() + def play(self, *args, **kwargs): + if not self.playing: + call_threaded(self._play) + else: + self._stop() - def _play(self): - output.speak(_("Playing...")) + def _play(self): + output.speak(_("Playing...")) # try: - self.playing = sound_lib.stream.FileStream(file=str(self.file), flags=sound_lib.stream.BASS_UNICODE) - self.playing.play() - self.send_message("set_label", control="play", label=_("&Stop")) - try: - while self.playing.is_playing: - pass - self.send_message("set_label", control="play", label=_("&Play")) - self.playing.free() - self.playing = None - except: - pass + self.playing = sound_lib.stream.FileStream(file=str(self.file), flags=sound_lib.stream.BASS_UNICODE) + self.playing.play() + self.send_message("set_label", control="play", label=_("&Stop")) + try: + while self.playing.is_playing: + pass + self.send_message("set_label", control="play", label=_("&Play")) + self.playing.free() + self.playing = None + except: + pass - def _stop(self): - output.speak(_("Stopped")) - self.playing.stop() - self.playing.free() - self.send_message("set_label", control="play", label=_("&Play")) - self.playing = None + def _stop(self): + output.speak(_("Stopped")) + self.playing.stop() + self.playing.free() + self.send_message("set_label", control="play", label=_("&Play")) + self.playing = None - def postprocess(self): - if self.file.lower().endswith('.wav'): - output.speak(_("Recoding audio...")) - sound.recode_audio(self.file) - self.wav_file = self.file - self.file = '%s.ogg' % self.file[:-4] - self.cleanup() + def postprocess(self): + if self.file.lower().endswith('.wav'): + output.speak(_("Recoding audio...")) + sound.recode_audio(self.file) + self.wav_file = self.file + self.file = '%s.ogg' % self.file[:-4] + self.cleanup() - def cleanup(self): - if self.playing and self.playing.is_playing: - self.playing.stop() - if self.recording != None: - if self.recording.is_playing: - self.recording.stop() - try: - self.recording.free() - except: - pass - if hasattr(self, 'wav_file'): - os.remove(self.wav_file) + def cleanup(self): + if self.playing and self.playing.is_playing: + self.playing.stop() + if self.recording != None: + if self.recording.is_playing: + self.recording.stop() + try: + self.recording.free() + except: + pass + if hasattr(self, 'wav_file'): + os.remove(self.wav_file) diff --git a/src/presenters/base.py b/src/presenters/base.py index 5269cc1..b939a50 100644 --- a/src/presenters/base.py +++ b/src/presenters/base.py @@ -5,15 +5,15 @@ from interactors import configuration as interactor class basePresenter(object): - def __init__(self, view, interactor, modulename): - self.modulename = modulename - self.interactor = interactor - self.view = view - self.interactor.install(view=view, presenter=self, modulename=modulename) + def __init__(self, view, interactor, modulename): + self.modulename = modulename + self.interactor = interactor + self.view = view + self.interactor.install(view=view, presenter=self, modulename=modulename) - def run(self): - self.interactor.start() - self.interactor.uninstall() + def run(self): + self.interactor.start() + self.interactor.uninstall() - def send_message(self, msg, *args, **kwargs): - pub.sendMessage(self.modulename+"_"+msg, *args, **kwargs) \ No newline at end of file + def send_message(self, msg, *args, **kwargs): + pub.sendMessage(self.modulename+"_"+msg, *args, **kwargs) diff --git a/src/presenters/blacklist.py b/src/presenters/blacklist.py index 02e3865..ce43622 100644 --- a/src/presenters/blacklist.py +++ b/src/presenters/blacklist.py @@ -5,26 +5,26 @@ from . import base class blacklistPresenter(base.basePresenter): - def __init__(self, session, view, interactor): - self.session = session - super(blacklistPresenter, self).__init__(view=view, interactor=interactor, modulename="blacklist") - self.worker = threading.Thread(target=self.load_information) - self.worker.finished = threading.Event() - self.worker.start() - self.run() + def __init__(self, session, view, interactor): + self.session = session + super(blacklistPresenter, self).__init__(view=view, interactor=interactor, modulename="blacklist") + self.worker = threading.Thread(target=self.load_information) + self.worker.finished = threading.Event() + self.worker.start() + self.run() - def load_information(self): - banned_users = self.session.vk.client.account.getBanned(count=200) - self.users = banned_users["profiles"] - items = [] - for i in self.users: - str_user = "{first_name} {last_name}".format(first_name=i["first_name"], last_name=i["last_name"]) - items.append([str_user]) - self.send_message("add_items", control="persons", items=items) + def load_information(self): + banned_users = self.session.vk.client.account.getBanned(count=200) + self.users = banned_users["profiles"] + items = [] + for i in self.users: + str_user = "{first_name} {last_name}".format(first_name=i["first_name"], last_name=i["last_name"]) + items.append([str_user]) + self.send_message("add_items", control="persons", items=items) - def unblock_person(self, item): - result = self.session.vk.client.account.unban(owner_id=self.users[item]["id"]) - if result == 1: - msg = _("You've unblocked {user1_nom} from your friends.").format(**self.session.get_user(self.users[item]["id"]),) - pub.sendMessage("notify", message=msg) - return result \ No newline at end of file + def unblock_person(self, item): + result = self.session.vk.client.account.unban(owner_id=self.users[item]["id"]) + if result == 1: + msg = _("You've unblocked {user1_nom} from your friends.").format(**self.session.get_user(self.users[item]["id"]),) + pub.sendMessage("notify", message=msg) + return result diff --git a/src/presenters/configuration.py b/src/presenters/configuration.py index c70aecd..3df7fc4 100644 --- a/src/presenters/configuration.py +++ b/src/presenters/configuration.py @@ -8,97 +8,97 @@ from . import base class configurationPresenter(base.basePresenter): - def __init__(self, session, view, interactor): - self.session = session - super(configurationPresenter, self).__init__(view=view, interactor=interactor, modulename="configuration") - # Control requirement for a restart of the application. - self.needs_restart = False - self.create_config() - self.run() + def __init__(self, session, view, interactor): + self.session = session + super(configurationPresenter, self).__init__(view=view, interactor=interactor, modulename="configuration") + # Control requirement for a restart of the application. + self.needs_restart = False + self.create_config() + self.run() - def get_notification_label(self, value): - if value == "native": - return _("Native") - else: - return _("Custom") + def get_notification_label(self, value): + if value == "native": + return _("Native") + else: + return _("Custom") - def get_update_channel_label(self, value): - if value == "stable": - return _("Stable") - elif value == "weekly": - return _("Weekly") - else: - return _("Alpha") + def get_update_channel_label(self, value): + if value == "stable": + return _("Stable") + elif value == "weekly": + return _("Weekly") + else: + return _("Alpha") - def get_notification_type(self, value): - if value == _("Native"): - return "native" - else: - return "custom" + def get_notification_type(self, value): + if value == _("Native"): + return "native" + else: + return "custom" - def get_update_channel_type(self, value): - if value == _("Stable"): - return "stable" - elif value == _("Weekly"): - return "weekly" - else: - return "alpha" + def get_update_channel_type(self, value): + if value == _("Stable"): + return "stable" + elif value == _("Weekly"): + return "weekly" + else: + return "alpha" - def create_config(self): - self.langs = languageHandler.getAvailableLanguages() - langs = [i[1] for i in self.langs] - self.codes = [i[0] for i in self.langs] - id = self.codes.index(config.app["app-settings"]["language"]) - self.send_message("create_tab", tab="general", arglist=dict(languages=langs)) - self.send_message("set_language", language=id) - self.send_message("set", tab="general", setting="load_images", value=self.session.settings["general"]["load_images"]) - self.send_message("set", tab="general", setting="use_proxy", value=config.app["app-settings"]["use_proxy"]) - self.send_message("set", tab="general", setting="debug_logging", value=config.app["app-settings"]["debug_logging"]) - self.send_message("set", tab="general", setting="update_channel", value=self.get_update_channel_label(self.session.settings["general"]["update_channel"])) - self.send_message("create_tab", tab="buffers") - self.send_message("set", tab="buffers", setting="wall_buffer_count", value=self.session.settings["buffers"]["count_for_wall_buffers"]) - self.send_message("set", tab="buffers", setting="video_buffers_count", value=self.session.settings["buffers"]["count_for_video_buffers"]) - self.send_message("set", tab="buffers", setting="chat_buffers_count", value=self.session.settings["buffers"]["count_for_chat_buffers"]) - self.send_message("create_tab", tab="chat") - self.send_message("set", tab="chat", setting="notify_online", value=self.session.settings["chat"]["notify_online"]) - self.send_message("set", tab="chat", setting="notify_offline", value=self.session.settings["chat"]["notify_offline"]) - self.send_message("set", tab="chat", setting="notifications", value=self.get_notification_label(self.session.settings["chat"]["notifications"])) - self.send_message("create_tab", tab="startup_options") - self.send_message("set", tab="startup", setting="audio_albums", value=self.session.settings["load_at_startup"]["audio_albums"]) - self.send_message("set", tab="startup", setting="video_albums", value=self.session.settings["load_at_startup"]["video_albums"]) - self.send_message("set", tab="startup", setting="communities", value=self.session.settings["load_at_startup"]["communities"]) - self.input_devices = sound_lib.input.Input.get_device_names() - self.output_devices = sound_lib.output.Output.get_device_names() - self.send_message("create_tab", tab="sound", arglist=dict(input_devices=self.input_devices, output_devices=self.output_devices, soundpacks=[])) - self.send_message("set", tab="sound", setting="input", value=config.app["sound"]["input_device"]) - self.send_message("set", tab="sound", setting="output", value=config.app["sound"]["output_device"]) + def create_config(self): + self.langs = languageHandler.getAvailableLanguages() + langs = [i[1] for i in self.langs] + self.codes = [i[0] for i in self.langs] + id = self.codes.index(config.app["app-settings"]["language"]) + self.send_message("create_tab", tab="general", arglist=dict(languages=langs)) + self.send_message("set_language", language=id) + self.send_message("set", tab="general", setting="load_images", value=self.session.settings["general"]["load_images"]) + self.send_message("set", tab="general", setting="use_proxy", value=config.app["app-settings"]["use_proxy"]) + self.send_message("set", tab="general", setting="debug_logging", value=config.app["app-settings"]["debug_logging"]) + self.send_message("set", tab="general", setting="update_channel", value=self.get_update_channel_label(self.session.settings["general"]["update_channel"])) + self.send_message("create_tab", tab="buffers") + self.send_message("set", tab="buffers", setting="wall_buffer_count", value=self.session.settings["buffers"]["count_for_wall_buffers"]) + self.send_message("set", tab="buffers", setting="video_buffers_count", value=self.session.settings["buffers"]["count_for_video_buffers"]) + self.send_message("set", tab="buffers", setting="chat_buffers_count", value=self.session.settings["buffers"]["count_for_chat_buffers"]) + self.send_message("create_tab", tab="chat") + self.send_message("set", tab="chat", setting="notify_online", value=self.session.settings["chat"]["notify_online"]) + self.send_message("set", tab="chat", setting="notify_offline", value=self.session.settings["chat"]["notify_offline"]) + self.send_message("set", tab="chat", setting="notifications", value=self.get_notification_label(self.session.settings["chat"]["notifications"])) + self.send_message("create_tab", tab="startup_options") + self.send_message("set", tab="startup", setting="audio_albums", value=self.session.settings["load_at_startup"]["audio_albums"]) + self.send_message("set", tab="startup", setting="video_albums", value=self.session.settings["load_at_startup"]["video_albums"]) + self.send_message("set", tab="startup", setting="communities", value=self.session.settings["load_at_startup"]["communities"]) + self.input_devices = sound_lib.input.Input.get_device_names() + self.output_devices = sound_lib.output.Output.get_device_names() + self.send_message("create_tab", tab="sound", arglist=dict(input_devices=self.input_devices, output_devices=self.output_devices, soundpacks=[])) + self.send_message("set", tab="sound", setting="input", value=config.app["sound"]["input_device"]) + self.send_message("set", tab="sound", setting="output", value=config.app["sound"]["output_device"]) - def update_setting(self, section, setting, value): - if section not in self.session.settings: - raise AttributeError("The configuration section is not present in the spec file.") - if setting not in self.session.settings[section]: - raise AttributeError("The setting you specified is not present in the config file.") - self.session.settings[section][setting] = value + def update_setting(self, section, setting, value): + if section not in self.session.settings: + raise AttributeError("The configuration section is not present in the spec file.") + if setting not in self.session.settings[section]: + raise AttributeError("The setting you specified is not present in the config file.") + self.session.settings[section][setting] = value - def save_settings_file(self): - self.session.settings.write() + def save_settings_file(self): + self.session.settings.write() - def update_app_setting(self, section, setting, value): - if section not in config.app: - raise AttributeError("The configuration section is not present in the spec file.") - if setting not in config.app[section]: - raise AttributeError("The setting you specified is not present in the config file.") - # check if certain settings have been changed so we'd restart the client. - # List of app settings that require a restart after being changed. - settings_needing_restart = ["language", "use_proxy", "input_device", "output_device", "debug_logging"] - if value != config.app[section][setting] and setting in settings_needing_restart: - self.needs_restart = True - config.app[section][setting] = value + def update_app_setting(self, section, setting, value): + if section not in config.app: + raise AttributeError("The configuration section is not present in the spec file.") + if setting not in config.app[section]: + raise AttributeError("The setting you specified is not present in the config file.") + # check if certain settings have been changed so we'd restart the client. + # List of app settings that require a restart after being changed. + settings_needing_restart = ["language", "use_proxy", "input_device", "output_device", "debug_logging"] + if value != config.app[section][setting] and setting in settings_needing_restart: + self.needs_restart = True + config.app[section][setting] = value - def save_app_settings_file(self): - config.app.write() - if self.needs_restart: - self.send_message("restart_program") + def save_app_settings_file(self): + config.app.write() + if self.needs_restart: + self.send_message("restart_program") - def restart_application(self): - restart.restart_program() \ No newline at end of file + def restart_application(self): + restart.restart_program() diff --git a/src/presenters/createPosts/__init__.py b/src/presenters/createPosts/__init__.py index ecd8504..72e3577 100644 --- a/src/presenters/createPosts/__init__.py +++ b/src/presenters/createPosts/__init__.py @@ -1,2 +1,2 @@ # -*- coding: utf-8 -*- -from .basePost import * \ No newline at end of file +from .basePost import * diff --git a/src/presenters/createPosts/basePost.py b/src/presenters/createPosts/basePost.py index 4c4bfff..f281d60 100644 --- a/src/presenters/createPosts/basePost.py +++ b/src/presenters/createPosts/basePost.py @@ -14,45 +14,45 @@ log = getLogger("controller.message") class createPostPresenter(base.basePresenter): - def __init__(self, session, view, interactor): - super(createPostPresenter, self).__init__(view=view, interactor=interactor, modulename="create_post") - self.session = session - self.images = [] - self.tagged_people = [] - self.run() + def __init__(self, session, view, interactor): + super(createPostPresenter, self).__init__(view=view, interactor=interactor, modulename="create_post") + self.session = session + self.images = [] + self.tagged_people = [] + self.run() - def get_friends(self): - try: - fields = "id, first_name, last_name" - self.friends = self.session.vk.client.friends.get(count=5000, fields=fields) - except AttributeError: - time.sleep(2) - log.exception("Error retrieving friends...") - return [] - self.users = [] - for i in self.friends["items"]: - self.users.append("{0} {1}".format(i["first_name"], i["last_name"])) - return self.users + def get_friends(self): + try: + fields = "id, first_name, last_name" + self.friends = self.session.vk.client.friends.get(count=5000, fields=fields) + except AttributeError: + time.sleep(2) + log.exception("Error retrieving friends...") + return [] + self.users = [] + for i in self.friends["items"]: + self.users.append("{0} {1}".format(i["first_name"], i["last_name"])) + return self.users - def add_tagged_users(self, tagged_users): - self.tagged_people = [] - for i in tagged_users: - self.tagged_people.append("[id%s|%s]" % (str(self.friends["items"][i]["id"]), self.friends["items"][i]["first_name"])) - self.send_message("add_tagged_users", users=self.tagged_people) + def add_tagged_users(self, tagged_users): + self.tagged_people = [] + for i in tagged_users: + self.tagged_people.append("[id%s|%s]" % (str(self.friends["items"][i]["id"]), self.friends["items"][i]["first_name"])) + self.send_message("add_tagged_users", users=self.tagged_people) - def translate(self, text, language): - msg = translator.translator.translate(text, language) - self.send_message("set", control="text", value=msg) - self.send_message("focus_control", control="text") - output.speak(_("Translated")) + def translate(self, text, language): + msg = translator.translator.translate(text, language) + self.send_message("set", control="text", value=msg) + self.send_message("focus_control", control="text") + output.speak(_("Translated")) - def spellcheck(self, text): - checker = SpellChecker.spellchecker.spellChecker(text) - if hasattr(checker, "fixed_text"): - self.send_message("set", control="text", value=checker.fixed_text) - self.send_message("focus_control", control="text") + def spellcheck(self, text): + checker = SpellChecker.spellchecker.spellChecker(text) + if hasattr(checker, "fixed_text"): + self.send_message("set", control="text", value=checker.fixed_text) + self.send_message("focus_control", control="text") - def add_attachments(self): - a = attach.attachPresenter(session=self.session, view=views.attachDialog(), interactor=interactors.attachInteractor()) - if len(a.attachments) != 0: - self.attachments = a.attachments + def add_attachments(self): + a = attach.attachPresenter(session=self.session, view=views.attachDialog(), interactor=interactors.attachInteractor()) + if len(a.attachments) != 0: + self.attachments = a.attachments diff --git a/src/presenters/displayPosts/__init__.py b/src/presenters/displayPosts/__init__.py index 4fdbac1..11cbcdd 100644 --- a/src/presenters/displayPosts/__init__.py +++ b/src/presenters/displayPosts/__init__.py @@ -6,4 +6,4 @@ from .comment import * from .peopleList import * from .poll import * from .topic import * -from .topicComment import * \ No newline at end of file +from .topicComment import * diff --git a/src/presenters/displayPosts/article.py b/src/presenters/displayPosts/article.py index 20b3053..af67fcd 100644 --- a/src/presenters/displayPosts/article.py +++ b/src/presenters/displayPosts/article.py @@ -10,38 +10,38 @@ from presenters import base log = logging.getLogger(__file__) class displayArticlePresenter(base.basePresenter): - def __init__(self, session, postObject, view, interactor): - super(displayArticlePresenter, self).__init__(view=view, interactor=interactor, modulename="display_article") - self.session = session - self.post = postObject - self.load_article() - self.run() + def __init__(self, session, postObject, view, interactor): + super(displayArticlePresenter, self).__init__(view=view, interactor=interactor, modulename="display_article") + self.session = session + self.post = postObject + self.load_article() + self.run() - def load_article(self): - """ Loads the article in the interactor. - This function retrieves, by using the params defined in the VK API, the web version of the article and extracts some info from it. - this is needed because there are no public API for articles so far. - """ - article = self.post[0] - # By using the vk_api's session, proxy settings are applied, thus might work in blocked countries. - article_body = self.session.vk.session_object.http.get(article["view_url"]) - # Parse and extract text from all paragraphs. - # ToDo: Extract all links and set those as attachments. - soup = BeautifulSoup(article_body.text, "lxml") - # ToDo: Article extraction require testing to see if you can add more tags beside paragraphs. - msg = [p.get_text() for p in soup.find_all("p")] - msg = "\n\n".join(msg) - self.send_message("set", control="article_view", value=msg) - self.send_message("set_title", value=article["title"]) - # Retrieve views count - views = soup.find("div", class_="articleView__views_info") - # This might return None if VK changes anything, so let's avoid errors. - if views == None: - views = str(-1) - else: - views = views.text - # Find the integer and remove the words from the string. - numbers = re.findall(r'\d+', views) - if len(numbers) != 0: - views = numbers[0] - self.send_message("set", control="views", value=views) \ No newline at end of file + def load_article(self): + """ Loads the article in the interactor. + This function retrieves, by using the params defined in the VK API, the web version of the article and extracts some info from it. + this is needed because there are no public API for articles so far. + """ + article = self.post[0] + # By using the vk_api's session, proxy settings are applied, thus might work in blocked countries. + article_body = self.session.vk.session_object.http.get(article["view_url"]) + # Parse and extract text from all paragraphs. + # ToDo: Extract all links and set those as attachments. + soup = BeautifulSoup(article_body.text, "lxml") + # ToDo: Article extraction require testing to see if you can add more tags beside paragraphs. + msg = [p.get_text() for p in soup.find_all("p")] + msg = "\n\n".join(msg) + self.send_message("set", control="article_view", value=msg) + self.send_message("set_title", value=article["title"]) + # Retrieve views count + views = soup.find("div", class_="articleView__views_info") + # This might return None if VK changes anything, so let's avoid errors. + if views == None: + views = str(-1) + else: + views = views.text + # Find the integer and remove the words from the string. + numbers = re.findall(r'\d+', views) + if len(numbers) != 0: + views = numbers[0] + self.send_message("set", control="views", value=views) diff --git a/src/presenters/displayPosts/audio.py b/src/presenters/displayPosts/audio.py index 61352f7..a0bb231 100644 --- a/src/presenters/displayPosts/audio.py +++ b/src/presenters/displayPosts/audio.py @@ -8,93 +8,93 @@ from presenters import base, player log = logging.getLogger(__file__) class displayAudioPresenter(base.basePresenter): - def __init__(self, session, postObject, view, interactor): - super(displayAudioPresenter, self).__init__(view=view, interactor=interactor, modulename="display_audio") - self.added_audios = {} - self.session = session - self.post = postObject - self.load_audios() - self.fill_information(0) - self.run() + def __init__(self, session, postObject, view, interactor): + super(displayAudioPresenter, self).__init__(view=view, interactor=interactor, modulename="display_audio") + self.added_audios = {} + self.session = session + self.post = postObject + self.load_audios() + self.fill_information(0) + self.run() - def add_to_library(self, audio_index): - post = self.post[audio_index] - args = {} - args["audio_id"] = post["id"] - if "album_id" in post: - args["album_id"] = post["album_id"] - args["owner_id"] = post["owner_id"] - audio = self.session.vk.client.audio.add(**args) - if audio != None and int(audio) > 21: - self.added_audios[post["id"]] = audio - self.send_message("disable_control", control="add") - self.send_message("enable_control", control="remove") + def add_to_library(self, audio_index): + post = self.post[audio_index] + args = {} + args["audio_id"] = post["id"] + if "album_id" in post: + args["album_id"] = post["album_id"] + args["owner_id"] = post["owner_id"] + audio = self.session.vk.client.audio.add(**args) + if audio != None and int(audio) > 21: + self.added_audios[post["id"]] = audio + self.send_message("disable_control", control="add") + self.send_message("enable_control", control="remove") - def remove_from_library(self, audio_index): - post = self.post[audio_index] - args = {} - if post["id"] in self.added_audios: - args["audio_id"] = self.added_audios[post["id"]] - args["owner_id"] = self.session.user_id - else: - args["audio_id"] = post["id"] - args["owner_id"] = post["owner_id"] - result = self.session.vk.client.audio.delete(**args) - if int(result) == 1: - self.send_message("enable_control", control="add") - self.send_message("disable_control", control="remove") - if post["id"] in self.added_audios: - self.added_audios.pop(post["id"]) + def remove_from_library(self, audio_index): + post = self.post[audio_index] + args = {} + if post["id"] in self.added_audios: + args["audio_id"] = self.added_audios[post["id"]] + args["owner_id"] = self.session.user_id + else: + args["audio_id"] = post["id"] + args["owner_id"] = post["owner_id"] + result = self.session.vk.client.audio.delete(**args) + if int(result) == 1: + self.send_message("enable_control", control="add") + self.send_message("disable_control", control="remove") + if post["id"] in self.added_audios: + self.added_audios.pop(post["id"]) - def fill_information(self, index): - post = self.post[index] - if "artist" in post: - self.send_message("set", control="artist", value=post["artist"]) - if "title" in post: - self.send_message("set", control="title", value=post["title"]) - if "duration" in post: - self.send_message("set", control="duration", value=utils.seconds_to_string(post["duration"])) - self.send_message("set_title", value="{0} - {1}".format(post["title"], post["artist"])) - call_threaded(self.get_lyrics, index) - if post["owner_id"] == self.session.user_id or (post["id"] in self.added_audios) == True: - self.send_message("enable_control", control="remove") - self.send_message("disable_control", control="add") - else: - self.send_message("enable_control", control="add") - self.send_message("disable_control", control="remove") + def fill_information(self, index): + post = self.post[index] + if "artist" in post: + self.send_message("set", control="artist", value=post["artist"]) + if "title" in post: + self.send_message("set", control="title", value=post["title"]) + if "duration" in post: + self.send_message("set", control="duration", value=utils.seconds_to_string(post["duration"])) + self.send_message("set_title", value="{0} - {1}".format(post["title"], post["artist"])) + call_threaded(self.get_lyrics, index) + if post["owner_id"] == self.session.user_id or (post["id"] in self.added_audios) == True: + self.send_message("enable_control", control="remove") + self.send_message("disable_control", control="add") + else: + self.send_message("enable_control", control="add") + self.send_message("disable_control", control="remove") - def get_lyrics(self, audio_index): - post = self.post[audio_index] - if "lyrics_id" in post: - l = self.session.vk.client.audio.getLyrics(lyrics_id=int(post["lyrics_id"])) - self.send_message("set", control="lyric", value=l["text"]) - else: - self.send_message("disable_control", control="lyric") + def get_lyrics(self, audio_index): + post = self.post[audio_index] + if "lyrics_id" in post: + l = self.session.vk.client.audio.getLyrics(lyrics_id=int(post["lyrics_id"])) + self.send_message("set", control="lyric", value=l["text"]) + else: + self.send_message("disable_control", control="lyric") - def get_suggested_filename(self, audio_index): - post = self.post[audio_index] - return utils.safe_filename("{0} - {1}.mp3".format(post["title"], post["artist"])) + def get_suggested_filename(self, audio_index): + post = self.post[audio_index] + return utils.safe_filename("{0} - {1}.mp3".format(post["title"], post["artist"])) - def download(self, audio_index, path): - post = self.post[audio_index] - if path != None: - pub.sendMessage("download-file", url=post["url"], filename=path) + def download(self, audio_index, path): + post = self.post[audio_index] + if path != None: + pub.sendMessage("download-file", url=post["url"], filename=path) - def play(self, audio_index): - post = self.post[audio_index] - if player.player.check_is_playing() == True: - return pub.sendMessage("stop") - pub.sendMessage("play", object=post) + def play(self, audio_index): + post = self.post[audio_index] + if player.player.check_is_playing() == True: + return pub.sendMessage("stop") + pub.sendMessage("play", object=post) - def load_audios(self): - audios = [] - for i in self.post: - s = "{0} - {1}. {2}".format(i["title"], i["artist"], utils.seconds_to_string(i["duration"])) - audios.append(s) - self.send_message("add_items", control="list", items=audios) - if len(self.post) == 1: - self.send_message("disable_control", control="list") - self.send_message("focus_control", control="title") + def load_audios(self): + audios = [] + for i in self.post: + s = "{0} - {1}. {2}".format(i["title"], i["artist"], utils.seconds_to_string(i["duration"])) + audios.append(s) + self.send_message("add_items", control="list", items=audios) + if len(self.post) == 1: + self.send_message("disable_control", control="list") + self.send_message("focus_control", control="title") - def handle_changes(self, audio_index): - self.fill_information(audio_index) \ No newline at end of file + def handle_changes(self, audio_index): + self.fill_information(audio_index) diff --git a/src/presenters/displayPosts/basePost.py b/src/presenters/displayPosts/basePost.py index d4141ab..cb429e7 100644 --- a/src/presenters/displayPosts/basePost.py +++ b/src/presenters/displayPosts/basePost.py @@ -20,359 +20,359 @@ from . import audio, poll, article log = logging.getLogger(__file__) def get_message(status): - message = "" - if "text" in status: - message = utils.clean_text(status["text"]) - return message + message = "" + if "text" in status: + message = utils.clean_text(status["text"]) + return message class displayPostPresenter(base.basePresenter): - """ Base class for post representation.""" + """ Base class for post representation.""" - def __init__(self, session, postObject, view, interactor): - super(displayPostPresenter, self).__init__(view=view, interactor=interactor, modulename="display_post") - self.type = "post" - self.session = session - self.post = postObject - # Posts from newsfeed contains this source_id instead from_id in walls. Also it uses post_id and walls use just id. - if "source_id" in self.post: - self.user_identifier = "source_id" - self.post_identifier = "post_id" - else: - # In wall's posts, if someone has posted in user's wall, owner_id should be used instead from_id - # This will help for retrieving comments, do likes, etc. - if "owner_id" not in self.post: - self.user_identifier = "from_id" - else: - self.user_identifier = "owner_id" - self.post_identifier = "id" - self.attachments = [] - self.load_images = False - # We'll put images here, so it will be easier to work with them. - self.images = [] - self.imageIndex = 0 - result = self.get_post_information() - # Stop loading everything else if post was deleted. - if result == False: - self.interactor.uninstall() - return - self.worker = threading.Thread(target=self.load_all_components) - self.worker.finished = threading.Event() - self.worker.start() - # connect here the pubsub event for successful posting of comments. - pub.subscribe(self.posted, "posted") - self.run() - pub.unsubscribe(self.posted, "posted") + def __init__(self, session, postObject, view, interactor): + super(displayPostPresenter, self).__init__(view=view, interactor=interactor, modulename="display_post") + self.type = "post" + self.session = session + self.post = postObject + # Posts from newsfeed contains this source_id instead from_id in walls. Also it uses post_id and walls use just id. + if "source_id" in self.post: + self.user_identifier = "source_id" + self.post_identifier = "post_id" + else: + # In wall's posts, if someone has posted in user's wall, owner_id should be used instead from_id + # This will help for retrieving comments, do likes, etc. + if "owner_id" not in self.post: + self.user_identifier = "from_id" + else: + self.user_identifier = "owner_id" + self.post_identifier = "id" + self.attachments = [] + self.load_images = False + # We'll put images here, so it will be easier to work with them. + self.images = [] + self.imageIndex = 0 + result = self.get_post_information() + # Stop loading everything else if post was deleted. + if result == False: + self.interactor.uninstall() + return + self.worker = threading.Thread(target=self.load_all_components) + self.worker.finished = threading.Event() + self.worker.start() + # connect here the pubsub event for successful posting of comments. + pub.subscribe(self.posted, "posted") + self.run() + pub.unsubscribe(self.posted, "posted") - def posted(self, from_buffer=None): - self.clear_comments_list() + def posted(self, from_buffer=None): + self.clear_comments_list() - def get_comments(self): - """ Get comments and insert them in a list.""" - user = self.post[self.user_identifier] - id = self.post[self.post_identifier] - comments_data = self.session.vk.client.wall.getComments(owner_id=user, post_id=id, need_likes=1, count=100, extended=1, preview_length=0, thread_items_count=10) - self.comments = dict(items=[], profiles=comments_data["profiles"]) - for i in comments_data["items"]: - self.comments["items"].append(i) - if i.get("thread") != None and i["thread"].get("count") > 0: - for newI in i["thread"]["items"]: - self.comments["items"].append(newI) - comments_ = [] - # Save profiles in session local storage for a future usage. - # Although community objects are returned here, we should not add those because their names are changed. - # For example, self reference to a group is marked as "Administrator", which would ruin this profile to be rendered somewhere else. - data = dict(groups=[], profiles=self.comments["profiles"]) - self.session.process_usernames(data) - for i in self.comments["items"]: - # If comment has a "deleted" key it should not be displayed, obviously. - if "deleted" in i: - continue - from_ = self.session.get_user(i["from_id"])["user1_nom"] - if "reply_to_user" in i: - extra_info = self.session.get_user(i["reply_to_user"])["user1_nom"] - from_ = _("{0} > {1}").format(from_, extra_info) - # As we set the comment reply properly in the from_ field, let's remove the first username from here if it exists. - fixed_text = utils.clean_text(i["text"]) - if len(fixed_text) > 140: - text = fixed_text[:141] - else: - text = fixed_text - original_date = arrow.get(i["date"]) - created_at = original_date.humanize(locale=languageHandler.curLang[:2]) - likes = str(i["likes"]["count"]) - comments_.append((from_, text, created_at, likes)) - self.send_message("add_items", control="comments", items=comments_) + def get_comments(self): + """ Get comments and insert them in a list.""" + user = self.post[self.user_identifier] + id = self.post[self.post_identifier] + comments_data = self.session.vk.client.wall.getComments(owner_id=user, post_id=id, need_likes=1, count=100, extended=1, preview_length=0, thread_items_count=10) + self.comments = dict(items=[], profiles=comments_data["profiles"]) + for i in comments_data["items"]: + self.comments["items"].append(i) + if i.get("thread") != None and i["thread"].get("count") > 0: + for newI in i["thread"]["items"]: + self.comments["items"].append(newI) + comments_ = [] + # Save profiles in session local storage for a future usage. + # Although community objects are returned here, we should not add those because their names are changed. + # For example, self reference to a group is marked as "Administrator", which would ruin this profile to be rendered somewhere else. + data = dict(groups=[], profiles=self.comments["profiles"]) + self.session.process_usernames(data) + for i in self.comments["items"]: + # If comment has a "deleted" key it should not be displayed, obviously. + if "deleted" in i: + continue + from_ = self.session.get_user(i["from_id"])["user1_nom"] + if "reply_to_user" in i: + extra_info = self.session.get_user(i["reply_to_user"])["user1_nom"] + from_ = _("{0} > {1}").format(from_, extra_info) + # As we set the comment reply properly in the from_ field, let's remove the first username from here if it exists. + fixed_text = utils.clean_text(i["text"]) + if len(fixed_text) > 140: + text = fixed_text[:141] + else: + text = fixed_text + original_date = arrow.get(i["date"]) + created_at = original_date.humanize(locale=languageHandler.curLang[:2]) + likes = str(i["likes"]["count"]) + comments_.append((from_, text, created_at, likes)) + self.send_message("add_items", control="comments", items=comments_) - def get_post_information(self): - from_ = self.session.get_user(self.post[self.user_identifier]) - if "copy_history" in self.post: - title = _("repost from {user1_nom}").format(**from_) - else: - if ("from_id" in self.post and "owner_id" in self.post) and (self.post["from_id"] != self.post["owner_id"]): - # Translators: {0} will be replaced with the user who is posting, and {1} with the wall owner. - user2 = self.session.get_user(self.post["owner_id"], "user2") - user2.update(from_) - title = _("Post from {user1_nom} in the {user2_nom}'s wall").format(**user2) - else: - title = _("Post from {user1_nom}").format(**from_) - self.send_message("set_title", value=title) - message = "" - # Retrieve again the post, so we'll make sure to get the most up to date information. - # And we add a counter for views. - post = self.session.vk.client.wall.getById(posts="{owner_id}_{post_id}".format(owner_id=self.post[self.user_identifier], post_id=self.post[self.post_identifier])) - # If this post has been deleted, let's send an event to the interactor so it won't be displayed. - if len(post) == 0: - self.send_message("post_deleted") - return False - self.post = post[0] - if "views" in self.post and self.post["views"]["count"] > 0: - self.send_message("set", control="views", value=str(self.post["views"]["count"])) - else: - self.send_message("disable_control", control="views") - if "owner_id" not in self.post: - self.user_identifier = "from_id" - else: - self.user_identifier = "owner_id" - self.post_identifier = "id" - message = get_message(self.post) - if "copy_history" in self.post: - nm = "\n" - for i in self.post["copy_history"]: - u = self.session.get_user(i["from_id"]) - u.update(message=get_message(i)) - nm += "{user1_nom}: {message}\n\n".format(**u) - self.get_attachments(i, get_message(i)) - message += nm - self.send_message("set", control="post_view", value=message) - self.get_attachments(self.post, message) - self.check_image_load() + def get_post_information(self): + from_ = self.session.get_user(self.post[self.user_identifier]) + if "copy_history" in self.post: + title = _("repost from {user1_nom}").format(**from_) + else: + if ("from_id" in self.post and "owner_id" in self.post) and (self.post["from_id"] != self.post["owner_id"]): + # Translators: {0} will be replaced with the user who is posting, and {1} with the wall owner. + user2 = self.session.get_user(self.post["owner_id"], "user2") + user2.update(from_) + title = _("Post from {user1_nom} in the {user2_nom}'s wall").format(**user2) + else: + title = _("Post from {user1_nom}").format(**from_) + self.send_message("set_title", value=title) + message = "" + # Retrieve again the post, so we'll make sure to get the most up to date information. + # And we add a counter for views. + post = self.session.vk.client.wall.getById(posts="{owner_id}_{post_id}".format(owner_id=self.post[self.user_identifier], post_id=self.post[self.post_identifier])) + # If this post has been deleted, let's send an event to the interactor so it won't be displayed. + if len(post) == 0: + self.send_message("post_deleted") + return False + self.post = post[0] + if "views" in self.post and self.post["views"]["count"] > 0: + self.send_message("set", control="views", value=str(self.post["views"]["count"])) + else: + self.send_message("disable_control", control="views") + if "owner_id" not in self.post: + self.user_identifier = "from_id" + else: + self.user_identifier = "owner_id" + self.post_identifier = "id" + message = get_message(self.post) + if "copy_history" in self.post: + nm = "\n" + for i in self.post["copy_history"]: + u = self.session.get_user(i["from_id"]) + u.update(message=get_message(i)) + nm += "{user1_nom}: {message}\n\n".format(**u) + self.get_attachments(i, get_message(i)) + message += nm + self.send_message("set", control="post_view", value=message) + self.get_attachments(self.post, message) + self.check_image_load() - def get_attachments(self, post, text): - attachments = [] - self.attachments = [] - if "attachments" in post: - for i in post["attachments"]: - # We don't need the photos_list attachment, so skip it. - if i["type"] == "photos_list": - continue - if i["type"] == "photo": - if self.load_images == False: self.load_images = True - self.images.append(i) - attachments.append(renderers.add_attachment(i)) - self.attachments.append(i) - # Links in text are not treated like normal attachments, so we'll have to catch and add those to the list without title - # We can't get a title because title is provided by the VK API and it will not work for links as simple text. - urls = utils.find_urls_in_text(text) - if len(urls) > 0: - links = [] - for i in urls: - links.append({"link": {"title": _("Untitled link"), "url": i}, "type": "link"}) - for i in links: - attachments.append(renderers.add_attachment(i)) - self.attachments.append(i) - if len(self.attachments) > 0: - self.send_message("enable_attachments") - self.send_message("add_items", control="attachments", items=attachments) - else: - self.interactor.view.attachments.list.Enable(False) + def get_attachments(self, post, text): + attachments = [] + self.attachments = [] + if "attachments" in post: + for i in post["attachments"]: + # We don't need the photos_list attachment, so skip it. + if i["type"] == "photos_list": + continue + if i["type"] == "photo": + if self.load_images == False: self.load_images = True + self.images.append(i) + attachments.append(renderers.add_attachment(i)) + self.attachments.append(i) + # Links in text are not treated like normal attachments, so we'll have to catch and add those to the list without title + # We can't get a title because title is provided by the VK API and it will not work for links as simple text. + urls = utils.find_urls_in_text(text) + if len(urls) > 0: + links = [] + for i in urls: + links.append({"link": {"title": _("Untitled link"), "url": i}, "type": "link"}) + for i in links: + attachments.append(renderers.add_attachment(i)) + self.attachments.append(i) + if len(self.attachments) > 0: + self.send_message("enable_attachments") + self.send_message("add_items", control="attachments", items=attachments) + else: + self.interactor.view.attachments.list.Enable(False) - def check_image_load(self): - if self.load_images and len(self.images) > 0 and self.session.settings["general"]["load_images"]: - self.send_message("enable_control", control="image") - nav = False # Disable navigation controls in photos - if len(self.images) > 1: - nav = True - self.send_message("enable_photo_controls", navigation=nav) - self.set_image(0) + def check_image_load(self): + if self.load_images and len(self.images) > 0 and self.session.settings["general"]["load_images"]: + self.send_message("enable_control", control="image") + nav = False # Disable navigation controls in photos + if len(self.images) > 1: + nav = True + self.send_message("enable_photo_controls", navigation=nav) + self.set_image(0) - def set_next_image(self, *args, **kwargs): - if self.imageIndex < -1 or self.imageIndex == len(self.images)-1: - self.imageIndex = -1 - if len(self.images) <= self.imageIndex+1: - self.imageIndex = 0 - else: - self.imageIndex = self.imageIndex + 1 - self.set_image(self.imageIndex) + def set_next_image(self, *args, **kwargs): + if self.imageIndex < -1 or self.imageIndex == len(self.images)-1: + self.imageIndex = -1 + if len(self.images) <= self.imageIndex+1: + self.imageIndex = 0 + else: + self.imageIndex = self.imageIndex + 1 + self.set_image(self.imageIndex) - def set_previous_image(self, *args, **kwargs): - if self.imageIndex <= 0: - self.imageIndex = len(self.images) - self.imageIndex = self.imageIndex - 1 - self.set_image(self.imageIndex) + def set_previous_image(self, *args, **kwargs): + if self.imageIndex <= 0: + self.imageIndex = len(self.images) + self.imageIndex = self.imageIndex - 1 + self.set_image(self.imageIndex) - def set_image(self, index): - if len(self.images) < index-1: - return - # Get's photo URL. - url = self.get_photo_url(self.images[index]["photo"], "x") - if url != "": - img = requests.get(url) - self.send_message("load_image", image=img) - # Translators: {0} is the number of the current photo and {1} is the total number of photos. - output.speak(_("Loaded photo {0} of {1}").format(index+1, len(self.images))) - return + def set_image(self, index): + if len(self.images) < index-1: + return + # Get's photo URL. + url = self.get_photo_url(self.images[index]["photo"], "x") + if url != "": + img = requests.get(url) + self.send_message("load_image", image=img) + # Translators: {0} is the number of the current photo and {1} is the total number of photos. + output.speak(_("Loaded photo {0} of {1}").format(index+1, len(self.images))) + return - def get_photo_url(self, photo, size="x"): - url = "" - for i in photo["sizes"]: - if i["type"] == size: - url = i["url"] - break - return url + def get_photo_url(self, photo, size="x"): + url = "" + for i in photo["sizes"]: + if i["type"] == size: + url = i["url"] + break + return url - def load_all_components(self): - self.get_likes() - self.get_reposts() - self.get_comments() - if self.post["comments"]["can_post"] == 0: - self.send_message("disable_control", control="comment") - if self.post["likes"]["can_like"] == 0 and self.post["likes"]["user_likes"] == 0: - self.send_message("disable_control", "like") - elif self.post["likes"]["user_likes"] == 1: - self.send_message("set_label", control="like", label=_("&Dislike")) - if self.post["likes"]["can_publish"] == 0: - self.send_message("disable_control", control="repost") + def load_all_components(self): + self.get_likes() + self.get_reposts() + self.get_comments() + if self.post["comments"]["can_post"] == 0: + self.send_message("disable_control", control="comment") + if self.post["likes"]["can_like"] == 0 and self.post["likes"]["user_likes"] == 0: + self.send_message("disable_control", "like") + elif self.post["likes"]["user_likes"] == 1: + self.send_message("set_label", control="like", label=_("&Dislike")) + if self.post["likes"]["can_publish"] == 0: + self.send_message("disable_control", control="repost") - def post_like(self): - if ("owner_id" in self.post) == False: - user = int(self.post[self.user_identifier]) - else: - user = int(self.post["owner_id"]) - id = int(self.post[self.post_identifier]) - if "type" in self.post: - type_ = self.post["type"] - else: - type_ = self.type - if self.post["likes"]["user_likes"] == 1: - l = self.session.vk.client.likes.delete(owner_id=user, item_id=id, type=type_) - output.speak(_("You don't like this")) - self.post["likes"]["count"] = l["likes"] - self.post["likes"]["user_likes"] = 2 - self.get_likes() - self.send_message("set_label", control="like", label=_("&Like")) - else: - l = self.session.vk.client.likes.add(owner_id=user, item_id=id, type=type_) - output.speak(_("You liked this")) - self.send_message("set_label", control="like", label=_("&Dislike")) - self.post["likes"]["count"] = l["likes"] - self.post["likes"]["user_likes"] = 1 - self.get_likes() + def post_like(self): + if ("owner_id" in self.post) == False: + user = int(self.post[self.user_identifier]) + else: + user = int(self.post["owner_id"]) + id = int(self.post[self.post_identifier]) + if "type" in self.post: + type_ = self.post["type"] + else: + type_ = self.type + if self.post["likes"]["user_likes"] == 1: + l = self.session.vk.client.likes.delete(owner_id=user, item_id=id, type=type_) + output.speak(_("You don't like this")) + self.post["likes"]["count"] = l["likes"] + self.post["likes"]["user_likes"] = 2 + self.get_likes() + self.send_message("set_label", control="like", label=_("&Like")) + else: + l = self.session.vk.client.likes.add(owner_id=user, item_id=id, type=type_) + output.speak(_("You liked this")) + self.send_message("set_label", control="like", label=_("&Dislike")) + self.post["likes"]["count"] = l["likes"] + self.post["likes"]["user_likes"] = 1 + self.get_likes() - def post_repost(self): - object_id = "wall{0}_{1}".format(self.post[self.user_identifier], self.post[self.post_identifier]) - p = createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Repost"), message=_("Add your comment here"), text="", mode="comment")) - if hasattr(p, "text") or hasattr(p, "privacy"): - post_arguments = dict(object=object_id, message=p.text) - attachments = [] - if hasattr(p, "attachments"): - attachments = p.attachments - call_threaded(pub.sendMessage, "post", parent_endpoint="wall", child_endpoint="repost", attachments_list=attachments, post_arguments=post_arguments) + def post_repost(self): + object_id = "wall{0}_{1}".format(self.post[self.user_identifier], self.post[self.post_identifier]) + p = createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Repost"), message=_("Add your comment here"), text="", mode="comment")) + if hasattr(p, "text") or hasattr(p, "privacy"): + post_arguments = dict(object=object_id, message=p.text) + attachments = [] + if hasattr(p, "attachments"): + attachments = p.attachments + call_threaded(pub.sendMessage, "post", parent_endpoint="wall", child_endpoint="repost", attachments_list=attachments, post_arguments=post_arguments) - def get_likes(self): - self.send_message("set_label", control="likes", label=_("{0} people like this").format(self.post["likes"]["count"],)) + def get_likes(self): + self.send_message("set_label", control="likes", label=_("{0} people like this").format(self.post["likes"]["count"],)) - def get_reposts(self): - self.send_message("set_label", control="shares", label=_("Shared {0} times").format(self.post["reposts"]["count"],)) + def get_reposts(self): + self.send_message("set_label", control="shares", label=_("Shared {0} times").format(self.post["reposts"]["count"],)) - def add_comment(self): - comment = createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Add a comment"), message="", text="", mode="comment")) - if hasattr(comment, "text") or hasattr(comment, "privacy"): - owner_id = self.post[self.user_identifier] - post_id = self.post[self.post_identifier] - post_arguments=dict(message=comment.text, owner_id=owner_id, post_id=post_id) - attachments = [] - if hasattr(comment, "attachments"): - attachments = comment.attachments - call_threaded(pub.sendMessage, "post", parent_endpoint="wall", child_endpoint="createComment", attachments_list=attachments, post_arguments=post_arguments) + def add_comment(self): + comment = createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Add a comment"), message="", text="", mode="comment")) + if hasattr(comment, "text") or hasattr(comment, "privacy"): + owner_id = self.post[self.user_identifier] + post_id = self.post[self.post_identifier] + post_arguments=dict(message=comment.text, owner_id=owner_id, post_id=post_id) + attachments = [] + if hasattr(comment, "attachments"): + attachments = comment.attachments + call_threaded(pub.sendMessage, "post", parent_endpoint="wall", child_endpoint="createComment", attachments_list=attachments, post_arguments=post_arguments) - def reply(self, comment): - c = self.comments["items"][comment] - comment = createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Reply to {user1_nom}").format(**self.session.get_user(c["from_id"])), message="", text="", mode="comment")) - if hasattr(comment, "text") or hasattr(comment, "privacy"): - post_id = self.post[self.post_identifier] - post_arguments=dict(message=comment.text, owner_id=c["owner_id"], reply_to_comment=c["id"], post_id=c["post_id"], reply_to_user=c["owner_id"]) - attachments = [] - if hasattr(comment, "attachments"): - attachments = comment.attachments - call_threaded(pub.sendMessage, "post", parent_endpoint="wall", child_endpoint="createComment", attachments_list=attachments, post_arguments=post_arguments) + def reply(self, comment): + c = self.comments["items"][comment] + comment = createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Reply to {user1_nom}").format(**self.session.get_user(c["from_id"])), message="", text="", mode="comment")) + if hasattr(comment, "text") or hasattr(comment, "privacy"): + post_id = self.post[self.post_identifier] + post_arguments=dict(message=comment.text, owner_id=c["owner_id"], reply_to_comment=c["id"], post_id=c["post_id"], reply_to_user=c["owner_id"]) + attachments = [] + if hasattr(comment, "attachments"): + attachments = comment.attachments + call_threaded(pub.sendMessage, "post", parent_endpoint="wall", child_endpoint="createComment", attachments_list=attachments, post_arguments=post_arguments) - def show_comment(self, comment_index): - from . import comment - c = self.comments["items"][comment_index] - c["post_id"] = self.post[self.post_identifier] - a = comment.displayCommentPresenter(session=self.session, postObject=c, interactor=interactors.displayPostInteractor(), view=views.displayComment()) + def show_comment(self, comment_index): + from . import comment + c = self.comments["items"][comment_index] + c["post_id"] = self.post[self.post_identifier] + a = comment.displayCommentPresenter(session=self.session, postObject=c, interactor=interactors.displayPostInteractor(), view=views.displayComment()) - def translate(self, text, language): - msg = translator.translator.translate(text, language) - self.send_message("set", control="post_view", value=msg) - self.send_message("focus_control", control="post_view") - output.speak(_("Translated")) + def translate(self, text, language): + msg = translator.translator.translate(text, language) + self.send_message("set", control="post_view", value=msg) + self.send_message("focus_control", control="post_view") + output.speak(_("Translated")) - def spellcheck(self, text): - checker = SpellChecker.spellchecker.spellChecker(text) - if hasattr(checker, "fixed_text"): - self.send_message("set", control="post_view", value=checker.fixed_text) - self.send_message("focus_control", control="post_view") + def spellcheck(self, text): + checker = SpellChecker.spellchecker.spellChecker(text) + if hasattr(checker, "fixed_text"): + self.send_message("set", control="post_view", value=checker.fixed_text) + self.send_message("focus_control", control="post_view") - def open_attachment(self, index): - attachment = self.attachments[index] - if attachment["type"] == "audio": - a = audio.displayAudioPresenter(session=self.session, postObject=[attachment["audio"]], interactor=interactors.displayAudioInteractor(), view=views.displayAudio()) - elif attachment["type"] == "link": - output.speak(_("Opening URL..."), True) - webbrowser.open_new_tab(attachment["link"]["url"]) - elif attachment["type"] == "doc": - output.speak(_("Opening document in web browser...")) - webbrowser.open(attachment["doc"]["url"]) - elif attachment["type"] == "video": - # it seems VK doesn't like to attach video links as normal URLS, so we'll have to - # get the full video object and use its "player" key which will open a webbrowser in their site with a player for the video. - # see https://vk.com/dev/attachments_w and and https://vk.com/dev/video.get - # However, the flash player isn't good for visually impaired people (when you press play you won't be able to close the window with alt+f4), so it could be good to use the HTML5 player. - # For firefox, see https://addons.mozilla.org/ru/firefox/addon/force-html5-video-player-at-vk/ - # May be I could use a dialogue here for inviting people to use this addon in firefox. It seems it isn't possible to use this html5 player from the player URL. - object_id = "{0}_{1}".format(attachment["video"]["owner_id"], attachment["video"]["id"]) - video_object = self.session.vk.client.video.get(owner_id=attachment["video"]["owner_id"], videos=object_id) - video_object = video_object["items"][0] - output.speak(_("Opening video in web browser..."), True) - webbrowser.open_new_tab(video_object["player"]) - elif attachment["type"] == "photo": - output.speak(_("Opening photo in web browser..."), True) - # Possible photo sizes for looking in the attachment information. Try to use the biggest photo available. - possible_sizes = [1280, 604, 130, 75] - url = "" - for i in possible_sizes: - if "photo_{0}".format(i,) in attachment["photo"]: - url = attachment["photo"]["photo_{0}".format(i,)] - break - if url != "": - webbrowser.open_new_tab(url) - elif attachment["type"] == "poll": - a = poll.displayPollPresenter(session=self.session, poll=attachment, interactor=interactors.displayPollInteractor(), view=views.displayPoll()) - elif attachment["type"] == "article": - a = article.displayArticlePresenter(session=self.session, postObject=[attachment["article"]], interactor=interactors.displayArticleInteractor(), view=views.displayArticle()) - else: - log.error("Unhandled attachment: %r" % (attachment,)) + def open_attachment(self, index): + attachment = self.attachments[index] + if attachment["type"] == "audio": + a = audio.displayAudioPresenter(session=self.session, postObject=[attachment["audio"]], interactor=interactors.displayAudioInteractor(), view=views.displayAudio()) + elif attachment["type"] == "link": + output.speak(_("Opening URL..."), True) + webbrowser.open_new_tab(attachment["link"]["url"]) + elif attachment["type"] == "doc": + output.speak(_("Opening document in web browser...")) + webbrowser.open(attachment["doc"]["url"]) + elif attachment["type"] == "video": + # it seems VK doesn't like to attach video links as normal URLS, so we'll have to + # get the full video object and use its "player" key which will open a webbrowser in their site with a player for the video. + # see https://vk.com/dev/attachments_w and and https://vk.com/dev/video.get + # However, the flash player isn't good for visually impaired people (when you press play you won't be able to close the window with alt+f4), so it could be good to use the HTML5 player. + # For firefox, see https://addons.mozilla.org/ru/firefox/addon/force-html5-video-player-at-vk/ + # May be I could use a dialogue here for inviting people to use this addon in firefox. It seems it isn't possible to use this html5 player from the player URL. + object_id = "{0}_{1}".format(attachment["video"]["owner_id"], attachment["video"]["id"]) + video_object = self.session.vk.client.video.get(owner_id=attachment["video"]["owner_id"], videos=object_id) + video_object = video_object["items"][0] + output.speak(_("Opening video in web browser..."), True) + webbrowser.open_new_tab(video_object["player"]) + elif attachment["type"] == "photo": + output.speak(_("Opening photo in web browser..."), True) + # Possible photo sizes for looking in the attachment information. Try to use the biggest photo available. + possible_sizes = [1280, 604, 130, 75] + url = "" + for i in possible_sizes: + if "photo_{0}".format(i,) in attachment["photo"]: + url = attachment["photo"]["photo_{0}".format(i,)] + break + if url != "": + webbrowser.open_new_tab(url) + elif attachment["type"] == "poll": + a = poll.displayPollPresenter(session=self.session, poll=attachment, interactor=interactors.displayPollInteractor(), view=views.displayPoll()) + elif attachment["type"] == "article": + a = article.displayArticlePresenter(session=self.session, postObject=[attachment["article"]], interactor=interactors.displayArticleInteractor(), view=views.displayArticle()) + else: + log.error("Unhandled attachment: %r" % (attachment,)) - def __del__(self): - if hasattr(self, "worker"): - self.worker.finished.set() + def __del__(self): + if hasattr(self, "worker"): + self.worker.finished.set() - def clear_comments_list(self): - self.send_message("clean_list", list="comments") - self.get_comments() + def clear_comments_list(self): + self.send_message("clean_list", list="comments") + self.get_comments() - def show_likes(self): - """ show likes for the specified post.""" - data = dict(type="post", owner_id=self.post[self.user_identifier], item_id=self.post["id"], extended=True, count=100, skip_own=True) - result = self.session.vk.client.likes.getList(**data) - if result["count"] > 0: - post = {"source_id": self.post[self.user_identifier], "friends": {"items": result["items"]}} - pub.sendMessage("open-post", post_object=post, controller_="displayFriendship", vars=dict(caption=_("people who liked this"))) + def show_likes(self): + """ show likes for the specified post.""" + data = dict(type="post", owner_id=self.post[self.user_identifier], item_id=self.post["id"], extended=True, count=100, skip_own=True) + result = self.session.vk.client.likes.getList(**data) + if result["count"] > 0: + post = {"source_id": self.post[self.user_identifier], "friends": {"items": result["items"]}} + pub.sendMessage("open-post", post_object=post, controller_="displayFriendship", vars=dict(caption=_("people who liked this"))) - def show_shares(self): - data = dict(type="post", owner_id=self.post[self.user_identifier], item_id=self.post["id"], extended=True, count=1000, skip_own=True, filter="copies") - result = self.session.vk.client.likes.getList(**data) - if result["count"] > 0: - post = {"source_id": self.post[self.user_identifier], "friends": {"items": result["items"]}} - pub.sendMessage("open-post", post_object=post, controller_="displayFriendship", vars=dict(caption=_("people who shared this"))) \ No newline at end of file + def show_shares(self): + data = dict(type="post", owner_id=self.post[self.user_identifier], item_id=self.post["id"], extended=True, count=1000, skip_own=True, filter="copies") + result = self.session.vk.client.likes.getList(**data) + if result["count"] > 0: + post = {"source_id": self.post[self.user_identifier], "friends": {"items": result["items"]}} + pub.sendMessage("open-post", post_object=post, controller_="displayFriendship", vars=dict(caption=_("people who shared this"))) diff --git a/src/presenters/displayPosts/comment.py b/src/presenters/displayPosts/comment.py index 232e14d..1198784 100644 --- a/src/presenters/displayPosts/comment.py +++ b/src/presenters/displayPosts/comment.py @@ -15,75 +15,75 @@ from . import basePost log = logging.getLogger(__file__) def get_message(status): - message = "" - if "text" in status: - message = utils.clean_text(status["text"]) - return message + message = "" + if "text" in status: + message = utils.clean_text(status["text"]) + return message class displayCommentPresenter(basePost.displayPostPresenter): - def __init__(self, session, postObject, view, interactor): - self.type = "comment" - self.modulename = "display_comment" - self.interactor = interactor - self.view = view - self.interactor.install(view=view, presenter=self, modulename=self.modulename) - self.session = session - self.post = postObject - self.user_identifier = "from_id" - self.post_identifier = "id" - self.worker = threading.Thread(target=self.load_all_components) - self.worker.finished = threading.Event() - self.worker.start() - self.attachments = [] - self.load_images = False - # We'll put images here, so it will be easier to work with them. - self.images = [] - self.imageIndex = 0 - # connect here the pubsub event for successful posting of comments. - pub.subscribe(self.posted, "posted") - self.run() - pub.unsubscribe(self.posted, "posted") + def __init__(self, session, postObject, view, interactor): + self.type = "comment" + self.modulename = "display_comment" + self.interactor = interactor + self.view = view + self.interactor.install(view=view, presenter=self, modulename=self.modulename) + self.session = session + self.post = postObject + self.user_identifier = "from_id" + self.post_identifier = "id" + self.worker = threading.Thread(target=self.load_all_components) + self.worker.finished = threading.Event() + self.worker.start() + self.attachments = [] + self.load_images = False + # We'll put images here, so it will be easier to work with them. + self.images = [] + self.imageIndex = 0 + # connect here the pubsub event for successful posting of comments. + pub.subscribe(self.posted, "posted") + self.run() + pub.unsubscribe(self.posted, "posted") - def load_all_components(self): - self.get_post_information() - self.get_likes() - self.send_message("disable_control", control="comment") - if self.post["likes"]["can_like"] == 0 and self.post["likes"]["user_likes"] == 0: - self.send_message("disable_control", "like") - elif self.post["likes"]["user_likes"] == 1: - self.send_message("set_label", control="like", label=_("&Dislike")) + def load_all_components(self): + self.get_post_information() + self.get_likes() + self.send_message("disable_control", control="comment") + if self.post["likes"]["can_like"] == 0 and self.post["likes"]["user_likes"] == 0: + self.send_message("disable_control", "like") + elif self.post["likes"]["user_likes"] == 1: + self.send_message("set_label", control="like", label=_("&Dislike")) - def get_post_information(self): - from_ = self.session.get_user(self.post[self.user_identifier]) - if ("from_id" in self.post and "owner_id" in self.post): - user2 = self.session.get_user(self.post["owner_id"], "user2") - user2.update(from_) - title = _("Comment from {user1_nom} in the {user2_nom}'s post").format(**user2) - self.send_message("set_title", value=title) - message = "" - message = get_message(self.post) - self.send_message("set", control="post_view", value=message) - self.get_attachments(self.post, message) - self.check_image_load() + def get_post_information(self): + from_ = self.session.get_user(self.post[self.user_identifier]) + if ("from_id" in self.post and "owner_id" in self.post): + user2 = self.session.get_user(self.post["owner_id"], "user2") + user2.update(from_) + title = _("Comment from {user1_nom} in the {user2_nom}'s post").format(**user2) + self.send_message("set_title", value=title) + message = "" + message = get_message(self.post) + self.send_message("set", control="post_view", value=message) + self.get_attachments(self.post, message) + self.check_image_load() - def reply(self, *args, **kwargs): - comment = createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Reply to {user1_nom}").format(**self.session.get_user(self.post["from_id"])), message="", text="", mode="comment")) - if hasattr(comment, "text") or hasattr(comment, "privacy"): - post_arguments = dict(owner_id=self.post["owner_id"], reply_to_comment=self.post["id"], post_id=self.post["post_id"], reply_to_user=self.post["owner_id"], message=comment.text) - attachments = [] - if hasattr(comment, "attachments"): - attachments = comment.attachments - call_threaded(pub.sendMessage, "post", parent_endpoint="wall", child_endpoint="createComment", attachments_list=attachments, post_arguments=post_arguments) + def reply(self, *args, **kwargs): + comment = createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Reply to {user1_nom}").format(**self.session.get_user(self.post["from_id"])), message="", text="", mode="comment")) + if hasattr(comment, "text") or hasattr(comment, "privacy"): + post_arguments = dict(owner_id=self.post["owner_id"], reply_to_comment=self.post["id"], post_id=self.post["post_id"], reply_to_user=self.post["owner_id"], message=comment.text) + attachments = [] + if hasattr(comment, "attachments"): + attachments = comment.attachments + call_threaded(pub.sendMessage, "post", parent_endpoint="wall", child_endpoint="createComment", attachments_list=attachments, post_arguments=post_arguments) - def show_likes(self): - """ show likes for the specified post.""" - data = dict(type="comment", owner_id=self.post["owner_id"], item_id=self.post["id"], extended=True, count=100, skip_own=True) - result = self.session.vk.client.likes.getList(**data) - if result["count"] > 0: - post = {"source_id": self.post[self.user_identifier], "friends": {"items": result["items"]}} - pub.sendMessage("open-post", post_object=post, controller_="displayFriendship", vars=dict(caption=_("people who liked this"))) + def show_likes(self): + """ show likes for the specified post.""" + data = dict(type="comment", owner_id=self.post["owner_id"], item_id=self.post["id"], extended=True, count=100, skip_own=True) + result = self.session.vk.client.likes.getList(**data) + if result["count"] > 0: + post = {"source_id": self.post[self.user_identifier], "friends": {"items": result["items"]}} + pub.sendMessage("open-post", post_object=post, controller_="displayFriendship", vars=dict(caption=_("people who liked this"))) - def posted(self, from_buffer=None): - self.interactor.uninstall() - return \ No newline at end of file + def posted(self, from_buffer=None): + self.interactor.uninstall() + return diff --git a/src/presenters/displayPosts/peopleList.py b/src/presenters/displayPosts/peopleList.py index cacf216..86aa1e5 100644 --- a/src/presenters/displayPosts/peopleList.py +++ b/src/presenters/displayPosts/peopleList.py @@ -8,43 +8,43 @@ log = logging.getLogger(__file__) class displayFriendshipPresenter(base.basePresenter): - def __init__(self, session, postObject, view, interactor, caption=""): - self.session = session - self.post = postObject - super(displayFriendshipPresenter, self).__init__(view=view, interactor=interactor, modulename="display_friendship") - list_of_friends = self.get_friend_names() - from_ = self.session.get_user(self.post["source_id"]) - title = caption.format(**from_) - self.send_message("set_title", value=title) - self.set_friends_list(list_of_friends) - self.run() + def __init__(self, session, postObject, view, interactor, caption=""): + self.session = session + self.post = postObject + super(displayFriendshipPresenter, self).__init__(view=view, interactor=interactor, modulename="display_friendship") + list_of_friends = self.get_friend_names() + from_ = self.session.get_user(self.post["source_id"]) + title = caption.format(**from_) + self.send_message("set_title", value=title) + self.set_friends_list(list_of_friends) + self.run() - def get_friend_names(self): - self.friends = self.post["friends"]["items"] - friends = list() - for i in self.friends: - if "user_id" in i: - friends.append(self.session.get_user(i["user_id"])["user1_nom"]) - else: - friends.append(self.session.get_user(i["id"])["user1_nom"]) - return friends + def get_friend_names(self): + self.friends = self.post["friends"]["items"] + friends = list() + for i in self.friends: + if "user_id" in i: + friends.append(self.session.get_user(i["user_id"])["user1_nom"]) + else: + friends.append(self.session.get_user(i["id"])["user1_nom"]) + return friends - def set_friends_list(self, friendslist): - self.send_message("add_items", control="friends", items=friendslist) + def set_friends_list(self, friendslist): + self.send_message("add_items", control="friends", items=friendslist) - def view_profile(self, item): - user = self.friends[item] - if "user_id" in user: - id = user["user_id"] - else: - id = user["id"] - pub.sendMessage("user-profile", person=id) + def view_profile(self, item): + user = self.friends[item] + if "user_id" in user: + id = user["user_id"] + else: + id = user["id"] + pub.sendMessage("user-profile", person=id) - def open_in_browser(self, item): - user = self.friends[item] - if "user_id" in user: - id = user["user_id"] - else: - id = user["id"] - url = "https://vk.com/id{user_id}".format(user_id=id) - webbrowser.open_new_tab(url) \ No newline at end of file + def open_in_browser(self, item): + user = self.friends[item] + if "user_id" in user: + id = user["user_id"] + else: + id = user["id"] + url = "https://vk.com/id{user_id}".format(user_id=id) + webbrowser.open_new_tab(url) diff --git a/src/presenters/displayPosts/poll.py b/src/presenters/displayPosts/poll.py index 4aceae3..c52b6c3 100644 --- a/src/presenters/displayPosts/poll.py +++ b/src/presenters/displayPosts/poll.py @@ -7,49 +7,49 @@ log = logging.getLogger(__file__) class displayPollPresenter(base.basePresenter): - def __init__(self, session, poll, view, interactor, show_results=False): - super(displayPollPresenter, self).__init__(view=view, interactor=interactor, modulename="display_poll") - self.poll = poll["poll"] - self.session = session - self.get_poll() - self.load_poll(show_results) - self.run() + def __init__(self, session, poll, view, interactor, show_results=False): + super(displayPollPresenter, self).__init__(view=view, interactor=interactor, modulename="display_poll") + self.poll = poll["poll"] + self.session = session + self.get_poll() + self.load_poll(show_results) + self.run() - def get_poll(self): - # Retrieve the poll again so we will have a fresh and updated object. - data = dict(owner_id=self.poll["owner_id"], is_board=int(self.poll["is_board"]), poll_id=self.poll["id"]) - self.poll = self.session.vk.client.polls.getById(**data) + def get_poll(self): + # Retrieve the poll again so we will have a fresh and updated object. + data = dict(owner_id=self.poll["owner_id"], is_board=int(self.poll["is_board"]), poll_id=self.poll["id"]) + self.poll = self.session.vk.client.polls.getById(**data) - def load_poll(self, load_results=False): - user = self.session.get_user(self.poll["author_id"]) - title = _("Poll from {user1_nom}").format(**user) - self.send_message("set_title", value=title) - self.send_message("set", control="question", value=self.poll["question"]) - if len(self.poll["answer_ids"]) > 0 or ("is_closed" in self.poll and self.poll["is_closed"] == True) or load_results == True or ("can_vote" in self.poll and self.poll["can_vote"] == False): - options = [] - for i in self.poll["answers"]: - options.append((i["text"], i["votes"], i["rate"])) - self.send_message("add_options", options=options, multiple=self.poll["multiple"]) - self.send_message("done") - self.send_message("disable_control", control="ok") - else: - options = [] - for i in self.poll["answers"]: - options.append(i["text"]) - self.send_message("add_options", options=options, multiple=self.poll["multiple"]) - self.send_message("done") + def load_poll(self, load_results=False): + user = self.session.get_user(self.poll["author_id"]) + title = _("Poll from {user1_nom}").format(**user) + self.send_message("set_title", value=title) + self.send_message("set", control="question", value=self.poll["question"]) + if len(self.poll["answer_ids"]) > 0 or ("is_closed" in self.poll and self.poll["is_closed"] == True) or load_results == True or ("can_vote" in self.poll and self.poll["can_vote"] == False): + options = [] + for i in self.poll["answers"]: + options.append((i["text"], i["votes"], i["rate"])) + self.send_message("add_options", options=options, multiple=self.poll["multiple"]) + self.send_message("done") + self.send_message("disable_control", control="ok") + else: + options = [] + for i in self.poll["answers"]: + options.append(i["text"]) + self.send_message("add_options", options=options, multiple=self.poll["multiple"]) + self.send_message("done") - def vote(self, answers): - ids = "" - for i in range(0, len(self.poll["answers"])): - if answers[i] == True: - ids = ids+"{answer_id},".format(answer_id=self.poll["answers"][i]["id"]) - if self.poll["multiple"] == False: - break - if ids == "": - log.exception("An error occurred when retrieving answer IDS for the following poll: %r. Provided answer list: %r" % (self.poll, answers)) - return - data = dict(owner_id=self.poll["owner_id"], poll_id=self.poll["id"], answer_ids=ids, is_board=int(self.poll["is_board"])) - result = self.session.vk.client.polls.addVote(**data) - if result == 1: - output.speak(_("Your vote has been added to this poll.")) \ No newline at end of file + def vote(self, answers): + ids = "" + for i in range(0, len(self.poll["answers"])): + if answers[i] == True: + ids = ids+"{answer_id},".format(answer_id=self.poll["answers"][i]["id"]) + if self.poll["multiple"] == False: + break + if ids == "": + log.exception("An error occurred when retrieving answer IDS for the following poll: %r. Provided answer list: %r" % (self.poll, answers)) + return + data = dict(owner_id=self.poll["owner_id"], poll_id=self.poll["id"], answer_ids=ids, is_board=int(self.poll["is_board"])) + result = self.session.vk.client.polls.addVote(**data) + if result == 1: + output.speak(_("Your vote has been added to this poll.")) diff --git a/src/presenters/displayPosts/topic.py b/src/presenters/displayPosts/topic.py index b764afd..f80bac8 100644 --- a/src/presenters/displayPosts/topic.py +++ b/src/presenters/displayPosts/topic.py @@ -18,151 +18,151 @@ log = logging.getLogger(__file__) class displayTopicPresenter(basePost.displayPostPresenter): - def __init__(self, session, postObject, group_id, view, interactor): - self.type = "topic" - self.modulename = "display_topic" - self.interactor = interactor - self.view = view - self.interactor.install(view=view, presenter=self, modulename=self.modulename) - self.session = session - self.post = postObject - self.group_id = group_id - self.load_images = False - # We'll put images here, so it will be easier to work with them. - self.images = [] - self.imageIndex = 0 - result = self.get_post_information() - # Stop loading everything else if post was deleted. - if result == False: - self.interactor.uninstall() - return - self.worker = threading.Thread(target=self.load_all_components) - self.worker.finished = threading.Event() - self.worker.start() - self.attachments = [] - # connect pubsub event for posted comments. - pub.subscribe(self.posted, "posted") - self.run() - pub.unsubscribe(self.posted, "posted") + def __init__(self, session, postObject, group_id, view, interactor): + self.type = "topic" + self.modulename = "display_topic" + self.interactor = interactor + self.view = view + self.interactor.install(view=view, presenter=self, modulename=self.modulename) + self.session = session + self.post = postObject + self.group_id = group_id + self.load_images = False + # We'll put images here, so it will be easier to work with them. + self.images = [] + self.imageIndex = 0 + result = self.get_post_information() + # Stop loading everything else if post was deleted. + if result == False: + self.interactor.uninstall() + return + self.worker = threading.Thread(target=self.load_all_components) + self.worker.finished = threading.Event() + self.worker.start() + self.attachments = [] + # connect pubsub event for posted comments. + pub.subscribe(self.posted, "posted") + self.run() + pub.unsubscribe(self.posted, "posted") - def load_all_components(self): - self.get_comments() + def load_all_components(self): + self.get_comments() - def get_post_information(self): - title = self.post["title"] - self.send_message("set_title", value=title) - return True + def get_post_information(self): + title = self.post["title"] + self.send_message("set_title", value=title) + return True - def get_comments(self): - """ Get comments and insert them in a list.""" - self.comments = self.session.vk.client.board.getComments(group_id=self.group_id, topic_id=self.post["id"], need_likes=1, count=100, extended=1, sort="desc") - comments_ = [] - data = dict(profiles=self.comments["profiles"], groups=[]) - self.session.process_usernames(data) - self.comments["items"].reverse() - # If there are less than 100 comments in the topic we should disable the "load previous" button. - if self.comments["count"] <= 100: - self.send_message("disable_control", control="load_more_comments") - else: - left_comments = self.comments["count"]-len(self.comments["items"]) - if left_comments > 100: - left_comments = 100 - self.send_message("set_label", control="load_more_comments", label=_("Load {comments} previous comments").format(comments=left_comments)) - for i in self.comments["items"]: - # If comment has a "deleted" key it should not be displayed, obviously. - if "deleted" in i: - continue - from_ = self.session.get_user(i["from_id"])["user1_nom"] - # match user mentions inside text comment. - original_date = arrow.get(i["date"]) - created_at = original_date.humanize(locale=languageHandler.curLang[:2]) - likes = str(i["likes"]["count"]) - text = utils.clean_text(text=i["text"]) - comments_.append((from_, text, created_at, likes)) - self.send_message("add_items", control="comments", items=comments_) + def get_comments(self): + """ Get comments and insert them in a list.""" + self.comments = self.session.vk.client.board.getComments(group_id=self.group_id, topic_id=self.post["id"], need_likes=1, count=100, extended=1, sort="desc") + comments_ = [] + data = dict(profiles=self.comments["profiles"], groups=[]) + self.session.process_usernames(data) + self.comments["items"].reverse() + # If there are less than 100 comments in the topic we should disable the "load previous" button. + if self.comments["count"] <= 100: + self.send_message("disable_control", control="load_more_comments") + else: + left_comments = self.comments["count"]-len(self.comments["items"]) + if left_comments > 100: + left_comments = 100 + self.send_message("set_label", control="load_more_comments", label=_("Load {comments} previous comments").format(comments=left_comments)) + for i in self.comments["items"]: + # If comment has a "deleted" key it should not be displayed, obviously. + if "deleted" in i: + continue + from_ = self.session.get_user(i["from_id"])["user1_nom"] + # match user mentions inside text comment. + original_date = arrow.get(i["date"]) + created_at = original_date.humanize(locale=languageHandler.curLang[:2]) + likes = str(i["likes"]["count"]) + text = utils.clean_text(text=i["text"]) + comments_.append((from_, text, created_at, likes)) + self.send_message("add_items", control="comments", items=comments_) - def post_like(self): - c = self.interactor.view.comments.get_selected() - id = self.comments["items"][c]["id"] - if self.comments["items"][c]["likes"]["user_likes"] == 1: - l = self.session.vk.client.likes.delete(owner_id=-1*self.group_id, item_id=id, type="topic_comment") - output.speak(_("You don't like this")) - self.comments["items"][c]["likes"]["count"] = l["likes"] - self.comments["items"][c]["likes"]["user_likes"] = 2 - self.send_message("set_label", control="like", label=_("&Like")) - else: - l = self.session.vk.client.likes.add(owner_id=-1*self.group_id, item_id=id, type="topic_comment") - output.speak(_("You liked this")) - self.send_message("set_label", control="like", label=_("&Dislike")) - self.comments["items"][c]["likes"]["count"] = l["likes"] - self.comments["items"][c]["likes"]["user_likes"] = 1 - self.clear_comments_list() + def post_like(self): + c = self.interactor.view.comments.get_selected() + id = self.comments["items"][c]["id"] + if self.comments["items"][c]["likes"]["user_likes"] == 1: + l = self.session.vk.client.likes.delete(owner_id=-1*self.group_id, item_id=id, type="topic_comment") + output.speak(_("You don't like this")) + self.comments["items"][c]["likes"]["count"] = l["likes"] + self.comments["items"][c]["likes"]["user_likes"] = 2 + self.send_message("set_label", control="like", label=_("&Like")) + else: + l = self.session.vk.client.likes.add(owner_id=-1*self.group_id, item_id=id, type="topic_comment") + output.speak(_("You liked this")) + self.send_message("set_label", control="like", label=_("&Dislike")) + self.comments["items"][c]["likes"]["count"] = l["likes"] + self.comments["items"][c]["likes"]["user_likes"] = 1 + self.clear_comments_list() - def change_comment(self, comment): - comment = self.comments["items"][comment] - self.send_message("clean_list", list="attachments") - self.get_attachments(comment, "") - if comment["likes"]["user_likes"] == 1: - self.send_message("set_label", control="like", label=_("&Dislike")) - else: - self.send_message("set_label", control="like", label=_("&Like")) + def change_comment(self, comment): + comment = self.comments["items"][comment] + self.send_message("clean_list", list="attachments") + self.get_attachments(comment, "") + if comment["likes"]["user_likes"] == 1: + self.send_message("set_label", control="like", label=_("&Dislike")) + else: + self.send_message("set_label", control="like", label=_("&Like")) - def add_comment(self): - comment = createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Add a comment"), message="", text="", mode="comment")) - if hasattr(comment, "text") or hasattr(comment, "privacy"): - post_arguments = dict(group_id=self.group_id, topic_id=self.post["id"], message=comment.text) - attachments = [] - if hasattr(comment, "attachments"): - attachments = comment.attachments - call_threaded(pub.sendMessage, "post", parent_endpoint="board", child_endpoint="createComment", attachments_list=attachments, post_arguments=post_arguments) + def add_comment(self): + comment = createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Add a comment"), message="", text="", mode="comment")) + if hasattr(comment, "text") or hasattr(comment, "privacy"): + post_arguments = dict(group_id=self.group_id, topic_id=self.post["id"], message=comment.text) + attachments = [] + if hasattr(comment, "attachments"): + attachments = comment.attachments + call_threaded(pub.sendMessage, "post", parent_endpoint="board", child_endpoint="createComment", attachments_list=attachments, post_arguments=post_arguments) - def reply(self, comment): - c = self.comments["items"][comment] - comment = createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Reply to {user1_nom}").format(**self.session.get_user(c["from_id"])), message="", text="", mode="comment")) - if hasattr(comment, "text") or hasattr(comment, "privacy"): - user = self.session.get_user(c["from_id"]) - name = user["user1_nom"].split(" ")[0] - comment.text = "[post{post_id}|{name}], {text}".format(post_id=c["id"], text=comment.text, name=name) - group_id = self.group_id - topic_id = self.post["id"] - post_arguments = dict(group_id=group_id, topic_id=topic_id, reply_to_comment=c["id"], message=comment.text) - attachments = [] - if hasattr(comment, "attachments"): - attachments = comment.attachments - call_threaded(pub.sendMessage, "post", parent_endpoint="board", child_endpoint="createComment", attachments_list=attachments, post_arguments=post_arguments) + def reply(self, comment): + c = self.comments["items"][comment] + comment = createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Reply to {user1_nom}").format(**self.session.get_user(c["from_id"])), message="", text="", mode="comment")) + if hasattr(comment, "text") or hasattr(comment, "privacy"): + user = self.session.get_user(c["from_id"]) + name = user["user1_nom"].split(" ")[0] + comment.text = "[post{post_id}|{name}], {text}".format(post_id=c["id"], text=comment.text, name=name) + group_id = self.group_id + topic_id = self.post["id"] + post_arguments = dict(group_id=group_id, topic_id=topic_id, reply_to_comment=c["id"], message=comment.text) + attachments = [] + if hasattr(comment, "attachments"): + attachments = comment.attachments + call_threaded(pub.sendMessage, "post", parent_endpoint="board", child_endpoint="createComment", attachments_list=attachments, post_arguments=post_arguments) - def show_comment(self, comment_index): - c = self.comments["items"][comment_index] - c["post_id"] = self.post["id"] - c["group_id"] = -1*self.group_id - a = displayTopicCommentPresenter(session=self.session, postObject=c, interactor=interactors.displayPostInteractor(), view=views.displayComment()) + def show_comment(self, comment_index): + c = self.comments["items"][comment_index] + c["post_id"] = self.post["id"] + c["group_id"] = -1*self.group_id + a = displayTopicCommentPresenter(session=self.session, postObject=c, interactor=interactors.displayPostInteractor(), view=views.displayComment()) - def load_more_comments(self): - offset = len(self.comments["items"]) - comments = self.session.vk.client.board.getComments(group_id=self.group_id, topic_id=self.post["id"], need_likes=1, count=100, extended=1, sort="desc", offset=offset) - data = dict(profiles=comments["profiles"], groups=[]) - self.session.process_usernames(data) - # If there are less than 100 comments in the topic we should disable the "load previous" button. - for i in comments["items"]: - self.comments["items"].insert(0, i) - for i in comments["items"]: - # If comment has a "deleted" key it should not be displayed, obviously. - if "deleted" in i: - continue - from_ = self.session.get_user(i["from_id"])["user1_nom"] - # match user mentions inside text comment. - original_date = arrow.get(i["date"]) - created_at = original_date.humanize(locale=languageHandler.curLang[:2]) - likes = str(i["likes"]["count"]) - text = utils.clean_text(text=i["text"]) - self.send_message("add_item", control="comments", item=(from_, text, created_at, likes), reversed=True) - if len(self.comments["items"]) == self.comments["count"]: - self.send_message("disable_control", control="load_more_comments") - else: - left_comments = self.comments["count"]-len(self.comments["items"]) - if left_comments > 100: - left_comments = 100 - self.send_message("set_label", control="load_more_comments", label=_("Load {comments} previous comments").format(comments=left_comments)) + def load_more_comments(self): + offset = len(self.comments["items"]) + comments = self.session.vk.client.board.getComments(group_id=self.group_id, topic_id=self.post["id"], need_likes=1, count=100, extended=1, sort="desc", offset=offset) + data = dict(profiles=comments["profiles"], groups=[]) + self.session.process_usernames(data) + # If there are less than 100 comments in the topic we should disable the "load previous" button. + for i in comments["items"]: + self.comments["items"].insert(0, i) + for i in comments["items"]: + # If comment has a "deleted" key it should not be displayed, obviously. + if "deleted" in i: + continue + from_ = self.session.get_user(i["from_id"])["user1_nom"] + # match user mentions inside text comment. + original_date = arrow.get(i["date"]) + created_at = original_date.humanize(locale=languageHandler.curLang[:2]) + likes = str(i["likes"]["count"]) + text = utils.clean_text(text=i["text"]) + self.send_message("add_item", control="comments", item=(from_, text, created_at, likes), reversed=True) + if len(self.comments["items"]) == self.comments["count"]: + self.send_message("disable_control", control="load_more_comments") + else: + left_comments = self.comments["count"]-len(self.comments["items"]) + if left_comments > 100: + left_comments = 100 + self.send_message("set_label", control="load_more_comments", label=_("Load {comments} previous comments").format(comments=left_comments)) - def posted(self, from_buffer=None): - self.clear_comments_list() \ No newline at end of file + def posted(self, from_buffer=None): + self.clear_comments_list() diff --git a/src/presenters/displayPosts/topicComment.py b/src/presenters/displayPosts/topicComment.py index c9a0a30..397a7be 100644 --- a/src/presenters/displayPosts/topicComment.py +++ b/src/presenters/displayPosts/topicComment.py @@ -10,44 +10,44 @@ from . import comment log = logging.getLogger(__file__) def get_message(status): - message = "" - if "text" in status: - message = utils.clean_text(status["text"]) - return message + message = "" + if "text" in status: + message = utils.clean_text(status["text"]) + return message class displayTopicCommentPresenter(comment.displayCommentPresenter): - def get_post_information(self): - from_ = self.session.get_user(self.post[self.user_identifier]) - title = from_["user1_nom"] - self.send_message("set_title", value=title) - message = "" - message = get_message(self.post) - self.send_message("set", control="post_view", value=message) - self.get_attachments(self.post, message) - self.check_image_load() - self.send_message("disable_control", control="reply") + def get_post_information(self): + from_ = self.session.get_user(self.post[self.user_identifier]) + title = from_["user1_nom"] + self.send_message("set_title", value=title) + message = "" + message = get_message(self.post) + self.send_message("set", control="post_view", value=message) + self.get_attachments(self.post, message) + self.check_image_load() + self.send_message("disable_control", control="reply") - def post_like(self): - id = self.post["id"] - if self.post["likes"]["user_likes"] == 1: - l = self.session.vk.client.likes.delete(owner_id=self.post["group_id"], item_id=id, type="topic_comment") - output.speak(_("You don't like this")) - self.post["likes"]["count"] = l["likes"] - self.post["likes"]["user_likes"] = 2 - self.send_message("set_label", control="like", label=_("&Like")) - else: - l = self.session.vk.client.likes.add(owner_id=self.post["group_id"], item_id=id, type="topic_comment") - output.speak(_("You liked this")) - self.send_message("set_label", control="like", label=_("&Dislike")) - self.post["likes"]["count"] = l["likes"] - self.post["likes"]["user_likes"] = 1 - self.get_likes() + def post_like(self): + id = self.post["id"] + if self.post["likes"]["user_likes"] == 1: + l = self.session.vk.client.likes.delete(owner_id=self.post["group_id"], item_id=id, type="topic_comment") + output.speak(_("You don't like this")) + self.post["likes"]["count"] = l["likes"] + self.post["likes"]["user_likes"] = 2 + self.send_message("set_label", control="like", label=_("&Like")) + else: + l = self.session.vk.client.likes.add(owner_id=self.post["group_id"], item_id=id, type="topic_comment") + output.speak(_("You liked this")) + self.send_message("set_label", control="like", label=_("&Dislike")) + self.post["likes"]["count"] = l["likes"] + self.post["likes"]["user_likes"] = 1 + self.get_likes() - def show_likes(self): - """ show likes for the specified post.""" - data = dict(type="topic_comment", owner_id=self.post["group_id"], item_id=self.post["id"], extended=True, count=100, skip_own=True) - result = self.session.vk.client.likes.getList(**data) - if result["count"] > 0: - post = {"source_id": self.post["group_id"], "friends": {"items": result["items"]}} - pub.sendMessage("open-post", post_object=post, controller_="displayFriendship", vars=dict(caption=_("people who liked this"))) \ No newline at end of file + def show_likes(self): + """ show likes for the specified post.""" + data = dict(type="topic_comment", owner_id=self.post["group_id"], item_id=self.post["id"], extended=True, count=100, skip_own=True) + result = self.session.vk.client.likes.getList(**data) + if result["count"] > 0: + post = {"source_id": self.post["group_id"], "friends": {"items": result["items"]}} + pub.sendMessage("open-post", post_object=post, controller_="displayFriendship", vars=dict(caption=_("people who liked this"))) diff --git a/src/presenters/longpollthread.py b/src/presenters/longpollthread.py index f3c9215..7b9ee65 100644 --- a/src/presenters/longpollthread.py +++ b/src/presenters/longpollthread.py @@ -8,22 +8,22 @@ from logging import getLogger log = getLogger("controller.longpolThread") class worker(threading.Thread): - def __init__(self, session): - super(worker, self).__init__() - log.debug("Instantiating longPoll server") - self.session = session - self.longpoll = VkLongPoll(self.session.vk.session_object) + def __init__(self, session): + super(worker, self).__init__() + log.debug("Instantiating longPoll server") + self.session = session + self.longpoll = VkLongPoll(self.session.vk.session_object) - def run(self): - try: - for event in self.longpoll.listen(): - if event.type == VkEventType.MESSAGE_NEW: - pub.sendMessage("order-sent-message", obj=event) - elif event.type == VkEventType.USER_ONLINE: - pub.sendMessage("user-online", event=event) - elif event.type == VkEventType.USER_OFFLINE: - pub.sendMessage("user-offline", event=event) - elif event.type == VkEventType.USER_TYPING: - pub.sendMessage("user-typing", obj=event) - except: - pub.sendMessage("longpoll-read-timeout") \ No newline at end of file + def run(self): + try: + for event in self.longpoll.listen(): + if event.type == VkEventType.MESSAGE_NEW: + pub.sendMessage("order-sent-message", obj=event) + elif event.type == VkEventType.USER_ONLINE: + pub.sendMessage("user-online", event=event) + elif event.type == VkEventType.USER_OFFLINE: + pub.sendMessage("user-offline", event=event) + elif event.type == VkEventType.USER_TYPING: + pub.sendMessage("user-typing", obj=event) + except: + pub.sendMessage("longpoll-read-timeout") diff --git a/src/presenters/main.py b/src/presenters/main.py index 3d1af8d..28638e1 100644 --- a/src/presenters/main.py +++ b/src/presenters/main.py @@ -24,813 +24,812 @@ log = logging.getLogger("controller.main") class Controller(base.basePresenter): - def search(self, tab_name): - for i in range(0, len(self.buffers)): - if self.buffers[i].name == tab_name: - return self.buffers[i] - return False - - def get_all_buffers(self, contains): - results = [] - for i in self.buffers: - if contains in i.name: - results.append(i) - return results - - def __init__(self, *args, **kwargs): - super(Controller, self).__init__(*args, **kwargs) - log.debug("Starting main controller...") - self.buffers = [] - player.setup() - self.session = session.sessions[list(session.sessions.keys())[0]] - self.create_controls() - call_threaded(updater.do_update, update_type=self.session.settings["general"]["update_channel"]) - - def create_buffer(self, buffer_type="baseBuffer", buffer_title="", parent_tab=None, loadable=False, get_items=False, kwargs={}): - if not hasattr(buffers, buffer_type): - raise AttributeError("Specified buffer type does not exist.") - buffer = getattr(buffers, buffer_type)(**kwargs) - if loadable: - buffer.can_get_items = False - self.buffers.append(buffer) - if parent_tab == None: - self.send_message("add_buffer", widget=buffer.tab, title=buffer_title) - else: - self.send_message("insert_buffer", widget=buffer.tab, title=buffer_title, parent=parent_tab) - if get_items: - call_threaded(buffer.get_items) - - def create_empty_buffer(self, buffer_type="empty", buffer_title="", parent_tab=None, kwargs={}): - if not hasattr(buffers, buffer_type): - raise AttributeError("Specified buffer type does not exist.") - buffer = getattr(buffers, buffer_type)(**kwargs) - self.buffers.append(buffer) - if parent_tab == None: - self.window.add_buffer(buffer.tab, buffer_title) - else: - self.window.insert_buffer(buffer.tab, buffer_title, self.window.search(parent_tab)) - - def create_controls(self): - log.debug("Creating controls for the window...") - pub.sendMessage("create_empty_buffer", buffer_title=_("Posts"), kwargs=dict(parent=self.window.tb, name="posts")) - pub.sendMessage("create_buffer", buffer_type="baseBuffer", buffer_title=_("Home"), parent_tab="posts", kwargs=dict(parent=self.window.tb, name="home_timeline", session=self.session, composefunc="render_newsfeed_item", endpoint="newsfeed", count=self.session.settings["buffers"]["count_for_wall_buffers"])) - pub.sendMessage("create_buffer", buffer_type="feedBuffer", buffer_title=_("My wall"), parent_tab="posts", kwargs=dict(parent=self.window.tb, name="me_feed", composefunc="render_status", session=self.session, endpoint="get", parent_endpoint="wall", extended=1, count=self.session.settings["buffers"]["count_for_wall_buffers"])) - pub.sendMessage("create_empty_buffer", buffer_title=_("Music"), kwargs=dict(parent=self.window.tb, name="audios")) - pub.sendMessage("create_buffer", buffer_type="audioBuffer", buffer_title=_("My audios"), parent_tab="audios", kwargs=dict(parent=self.window.tb, name="me_audio", composefunc="render_audio", session=self.session, endpoint="get", parent_endpoint="audio")) - if self.session.settings["vk"]["use_alternative_tokens"] == False: - pub.sendMessage("create_buffer", buffer_type="audioBuffer", buffer_title=_("Populars"), parent_tab="audios", kwargs=dict(parent=self.window.tb, name="popular_audio", composefunc="render_audio", session=self.session, endpoint="getPopular", parent_endpoint="audio", full_list=True, count=self.session.settings["buffers"]["count_for_audio_buffers"])) - pub.sendMessage("create_buffer", buffer_type="audioBuffer", buffer_title=_("Recommendations"), parent_tab="audios", kwargs=dict(parent=self.window.tb, name="recommended_audio", composefunc="render_audio", session=self.session, endpoint="getRecommendations", parent_endpoint="audio", full_list=True, count=self.session.settings["buffers"]["count_for_audio_buffers"])) - pub.sendMessage("create_empty_buffer", buffer_type="empty", buffer_title=_("Albums"), parent_tab="audios", kwargs=dict(parent=self.window.tb, name="albums")) - pub.sendMessage("create_empty_buffer", buffer_title=_("Video"), kwargs=dict(parent=self.window.tb, name="videos")) - pub.sendMessage("create_buffer", buffer_type="videoBuffer", buffer_title=_("My videos"), parent_tab="videos", kwargs=dict(parent=self.window.tb, name="me_video", composefunc="render_video", session=self.session, endpoint="get", parent_endpoint="video", count=self.session.settings["buffers"]["count_for_video_buffers"])) - pub.sendMessage("create_empty_buffer", buffer_title=_("Albums"), parent_tab="videos", kwargs=dict(parent=self.window.tb, name="video_albums")) - pub.sendMessage("create_empty_buffer", buffer_title=_("People"), kwargs=dict(parent=self.window.tb, name="people")) - pub.sendMessage("create_buffer", buffer_type="peopleBuffer", buffer_title=_("Friends"), parent_tab="people", kwargs=dict(parent=self.window.tb, name="friends_", composefunc="render_person", session=self.session, endpoint="get", parent_endpoint="friends", count=5000, order="hints", fields="uid, first_name, last_name, last_seen")) - pub.sendMessage("create_empty_buffer", buffer_title=_("Friendship requests"), parent_tab="people", kwargs=dict(parent=self.window.tb, name="requests")) - pub.sendMessage("create_buffer", buffer_type="requestsBuffer", buffer_title=_("Pending requests"), parent_tab="requests", kwargs=dict(parent=self.window.tb, name="friend_requests", composefunc="render_person", session=self.session, count=1000)) - pub.sendMessage("create_buffer", buffer_type="requestsBuffer", buffer_title=_("I follow"), parent_tab="requests", kwargs=dict(parent=self.window.tb, name="friend_requests_sent", composefunc="render_person", session=self.session, count=1000, out=1)) - pub.sendMessage("create_buffer", buffer_type="requestsBuffer", buffer_title=_("Subscribers"), parent_tab="requests", kwargs=dict(parent=self.window.tb, name="subscribers", composefunc="render_person", session=self.session, count=1000, need_viewed=1)) - pub.sendMessage("create_buffer", buffer_type="documentBuffer", buffer_title=_("Documents"), parent_tab=None, loadable=True, kwargs=dict(parent=self.window.tb, name="documents", composefunc="render_document", session=self.session, endpoint="get", parent_endpoint="docs")) - pub.sendMessage("create_empty_buffer", buffer_title=_("Communities"), kwargs=dict(parent=self.window.tb, name="communities")) - pub.sendMessage("create_empty_buffer", buffer_title=_("Chats"), kwargs=dict(parent=self.window.tb, name="chats")) - pub.sendMessage("create_empty_buffer", buffer_title=_("Timelines"), kwargs=dict(parent=self.window.tb, name="timelines")) - self.window.realize() - self.repeatedUpdate = RepeatingTimer(120, self.update_all_buffers) - self.repeatedUpdate.start() - self.readMarker = RepeatingTimer(60, self.mark_as_read) - self.readMarker.start() - - def connect_events(self): - log.debug("Connecting events to responses...") - pub.subscribe(self.in_post, "posted") - pub.subscribe(self.download, "download-file") - pub.subscribe(self.play_audio, "play-audio") - pub.subscribe(self.play_audios, "play-audios") - pub.subscribe(self.view_post, "open-post") - pub.subscribe(self.update_status_bar, "update-status-bar") - pub.subscribe(self.chat_from_id, "new-chat") - pub.subscribe(self.authorisation_failed, "authorisation-failed") - pub.subscribe(self.user_profile, "user-profile") - pub.subscribe(self.user_online, "user-online") - pub.subscribe(self.user_offline, "user-offline") - pub.subscribe(self.notify, "notify") - pub.subscribe(self.handle_longpoll_read_timeout, "longpoll-read-timeout") - pub.subscribe(self.create_buffer, "create_buffer") - pub.subscribe(self.create_empty_buffer, "create_empty_buffer") - pub.subscribe(self.user_typing, "user-typing") - widgetUtils.connect_event(self.window, widgetUtils.CLOSE_EVENT, self.exit) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.update_buffer, menuitem=self.window.update_buffer) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.check_for_updates, menuitem=self.window.check_for_updates) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.window.about_dialog, menuitem=self.window.about) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.search_audios, menuitem=self.window.search_audios) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.search_videos, menuitem=self.window.search_videos) - widgetUtils.connect_event(self.window, widgetUtils.MENU,self.remove_buffer, menuitem=self.window.remove_buffer_) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.get_more_items, menuitem=self.window.load_previous_items) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.changelog, menuitem=self.window.changelog) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.configuration, menuitem=self.window.settings_dialog) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.new_timeline, menuitem=self.window.timeline) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.create_audio_album, menuitem=self.window.audio_album) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.delete_audio_album, menuitem=self.window.delete_audio_album) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.create_video_album, menuitem=self.window.video_album) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.delete_video_album, menuitem=self.window.delete_video_album) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.check_documentation, menuitem=self.window.documentation) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.menu_play_pause, menuitem=self.window.player_play) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.menu_play_next, menuitem=self.window.player_next) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.menu_play_previous, menuitem=self.window.player_previous) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.menu_play_all, menuitem=self.window.player_play_all) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.menu_volume_down, menuitem=self.window.player_volume_down) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.menu_volume_up, menuitem=self.window.player_volume_up) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.menu_mute, menuitem=self.window.player_mute) - pub.subscribe(self.get_chat, "order-sent-message") - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.view_my_profile, menuitem=self.window.view_profile) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.view_my_profile_in_browser, menuitem=self.window.open_in_browser) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.set_status, menuitem=self.window.set_status) - widgetUtils.connect_event(self.window, widgetUtils.MENU, self.on_report_error, menuitem=self.window.report) - self.window.tb.Bind(wx.EVT_CONTEXT_MENU, self.on_context_menu) - - def disconnect_events(self): - log.debug("Disconnecting some events...") - pub.unsubscribe(self.in_post, "posted") - pub.unsubscribe(self.download, "download-file") - pub.unsubscribe(self.play_audio, "play-audio") - pub.unsubscribe(self.authorisation_failed, "authorisation-failed") - pub.unsubscribe(self.play_audios, "play-audios") - pub.unsubscribe(self.view_post, "open-post") - pub.unsubscribe(self.update_status_bar, "update-status-bar") - pub.unsubscribe(self.user_online, "user-online") - pub.unsubscribe(self.user_offline, "user-offline") - pub.unsubscribe(self.notify, "notify") - - def on_context_menu(self, event, *args, **kwargs): - """ Handles context menu event in the tree buffers.""" - # If the focus is not in the TreeCtrl of the Treebook, then we should not display any menu. - if isinstance(self.window.FindFocus(), wx.TreeCtrl) == False: - event.Skip() - return - menu = None - # Get the current buffer and let's choose a different menu depending on the selected buffer. - current_buffer = self.get_current_buffer() - # Deal with menu for community buffers. - if current_buffer.name.endswith("_community"): - menu = menus.communityBufferMenu() - # disable post loading if the community has already loaded posts. - if current_buffer.can_get_items: - menu.load_posts.Enable(False) - # Disable loading of audios, videos, documents or topics depending in two conditions. - # 1. If the buffer already exists, which means they are already loaded, or - # 2. If the group_info does not have counters for such items, which would indicate there are no items posted yet. - if self.search(current_buffer.name+"_audios") != False: - menu.load_audios.Enable(False) - elif hasattr(current_buffer, "group_info") and "audios" not in current_buffer.group_info["counters"]: - menu.load_audios.Enable(False) - if self.search(current_buffer.name+"_videos") != False: - menu.load_videos.Enable(False) - elif hasattr(current_buffer, "group_info") and "videos" not in current_buffer.group_info["counters"]: - menu.load_videos.Enable(False) - if self.search(current_buffer.name+"_topics") != False: - menu.load_topics.Enable(False) - elif hasattr(current_buffer, "group_info") and "topics" not in current_buffer.group_info["counters"]: - menu.load_topics.Enable(False) - - if self.search(current_buffer.name+"_documents") != False: - menu.load_documents.Enable(False) - elif hasattr(current_buffer, "group_info") and "docs" not in current_buffer.group_info["counters"]: - menu.load_documents.Enable(False) - # Connect the rest of the functions. - widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_community_posts, menuitem=menu.load_posts) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_community_topics, menuitem=menu.load_topics) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_community_audios, menuitem=menu.load_audios) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_community_videos, menuitem=menu.load_videos) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_community_documents, menuitem=menu.load_documents) - # Deal with the communities section itself. - if current_buffer.name == "communities": - menu = wx.Menu() - # Insert a different option depending if group buffers are loaded or scheduled to be loaded or not. - if self.session.settings["load_at_startup"]["communities"] == False and not hasattr(self.session, "groups"): - option = menu.Append(wx.NewId(), _("Load groups")) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_community_buffers, menuitem=option) - else: - option = menu.Append(wx.NewId(), _("Discard groups")) - widgetUtils.connect_event(menu, widgetUtils.MENU, self.unload_community_buffers, menuitem=option) - if menu != None: - self.window.PopupMenu(menu, self.window.FindFocus().GetPosition()) - # If there are no available menus, let's indicate it. - else: - output.speak(_("menu unavailable for this buffer.")) - - def authorisation_failed(self): - commonMessages.bad_authorisation() - - def login(self): - self.window.change_status(_("Logging in VK")) - self.session.login() - self.window.change_status(_("Ready")) - for i in self.buffers: - if hasattr(i, "get_items"): - # Translators: {0} will be replaced with the name of a buffer. - self.window.change_status(_("Loading items for {0}").format(i.name,)) - i.get_items() - self.window.change_status(_("Ready")) - self.create_unread_messages() - self.status_setter = RepeatingTimer(280, self.set_online) - self.status_setter.start() - self.set_online(notify=True) - self.get_audio_albums(self.session.user_id) - self.get_video_albums(self.session.user_id) - self.get_communities(self.session.user_id) - self.create_longpoll_thread() - - def create_longpoll_thread(self, notify=False): - try: - self.longpoll = longpollthread.worker(self.session) - self.longpoll.start() - if notify: - self.notify(message=_("Chat server reconnected")) - except ConnectionError: - pub.sendMessage("longpoll-read-timeout") - - def in_post(self, buffer): - buffer = self.search(buffer) - buffer.get_items() - buffer = self.search("home_timeline") - buffer.get_items() - - def update_all_buffers(self): - log.debug("Updating buffers...") - self.get_audio_albums(self.session.user_id, create_buffers=False) - self.get_video_albums(self.session.user_id, create_buffers=False) - for i in self.buffers: - if hasattr(i, "get_items"): - i.get_items() - log.debug("Updated %s" % (i.name)) - - def download(self, url, filename): - log.debug("downloading %s URL to %s filename" % (url, filename,)) - call_threaded(utils.download_file, url, filename, self.window) - - def play_audio(self, audio_object): - # Restricted audios don't include an URL paramether. - # Restriction can be due to licensed content to unauthorized countries. - if "url" in audio_object and audio_object["url"] =="": - self.notify(message=_("This file could not be played because it is not allowed in your country")) - return - call_threaded(player.player.play, audio_object, fresh=True) - - def play_audios(self, audios): - player.player.play_all(audios, shuffle=self.window.player_shuffle.IsChecked()) - - def view_post(self, post_object, controller_): - p = getattr(presenters, controller_+"Presenter")(session=self.session, postObject=post_object, interactor=getattr(interactors, controller_+"Interactor")(), view=getattr(views, controller_)()) - - def exit(self, *args, **kwargs): - log.debug("Receibed an exit signal. closing...") - self.set_offline() - self.disconnect_events() - volume = player.player.volume - config.app["sound"]["volume"] = volume - config.app.write() - self.window.Destroy() - wx.GetApp().ExitMainLoop() - - def update_buffer(self, *args, **kwargs): - b = self.get_current_buffer() - b.get_items() - - def get_more_items(self, *args, **kwargs): - b = self.get_current_buffer() - b.get_more_items() - - def check_for_updates(self, *args, **kwargs): - update = updater.do_update(update_type=self.session.settings["general"]["update_channel"]) - if update == False: - commonMessages.no_update_available() - - def search_audios(self, *args, **kwargs): - dlg = searchDialogs.searchAudioDialog() - if dlg.get_response() == widgetUtils.OK: - q = dlg.get("term") - auto_complete = True - count = 300 - performer_only = dlg.get_state("title") - sort = dlg.get_sort_order() - newbuff = buffers.audioBuffer(parent=self.window.tb, name="{0}_audiosearch".format(q,), session=self.session, composefunc="render_audio", parent_endpoint="audio", endpoint="search", q=q, auto_complete=auto_complete, count=count, performer_only=performer_only, sort=sort) - self.buffers.append(newbuff) - call_threaded(newbuff.get_items) - # Translators: {0} will be replaced with the search term. - self.window.insert_buffer(newbuff.tab, _("Search for {0}").format(q,), self.window.search("audios")) - - def search_videos(self, *args, **kwargs): - dlg = searchDialogs.searchVideoDialog() - if dlg.get_response() == widgetUtils.OK: - params = {} - params["q"] = dlg.get("term") - params["count"] = 200 - hd = dlg.get_checkable("hd") - if hd != 0: - params["hd"] = 1 - params["adult"] = dlg.get_checkable("safe_search") - params["sort"] = dlg.get_sort_order() -# params["filters"] = "youtube, vimeo, short, long, mp4" - print(params) - newbuff = buffers.videoBuffer(parent=self.window.tb, name="{0}_videosearch".format(params["q"],), session=self.session, composefunc="render_video", parent_endpoint="video", endpoint="search", **params) - self.buffers.append(newbuff) - call_threaded(newbuff.get_items) - # Translators: {0} will be replaced with the search term. - self.window.insert_buffer(newbuff.tab, _("Search for {0}").format(params["q"],), self.window.search("videos")) - - def update_status_bar(self, status): - self.window.change_status(status) - - def remove_buffer(self, event, mandatory=False, *args, **kwargs): - buffer = self.get_current_buffer() - buff = self.window.search(buffer.name) - answer = buffer.remove_buffer(mandatory) - if answer == False: - return - self.window.remove_buffer(buff) - self.buffers.remove(buffer) - del buffer - - def changelog(self, *args, **kwargs): - lang = localization.get("documentation") - os.chdir("documentation/%s" % (lang,)) - webbrowser.open("changelog.html") - os.chdir("../../") - - def configuration(self, *args, **kwargs): - """ Opens the global settings dialogue.""" - presenter = presenters.configurationPresenter(session=self.session, view=views.configurationDialog(title=_("Preferences")), interactor=interactors.configurationInteractor()) - - def new_timeline(self, *args, **kwargs): - b = self.get_current_buffer() - # If executing this method from an empty buffer we should get the newsfeed buffer. - if not hasattr(b, "get_users"): - b = self.search("home_timeline") - # Get a list of (id, user) objects. - d = [] - for i in self.session.db["users"]: - d.append((i, self.session.get_user(i)["user1_gen"])) - # Do the same for communities. - for i in self.session.db["groups"]: - d.append((-i, self.session.get_user(-i)["user1_nom"])) - a = timeline.timelineDialog([i[1] for i in d]) - if a.get_response() == widgetUtils.OK: - user = a.get_user() - buffertype = a.get_buffer_type() - user_id = "" - for i in d: - if i[1] == user: - user_id = i[0] - if user_id == "": - user_data = self.session.vk.client.utils.resolveScreenName(screen_name=user) - if type(user_data) == list: - commonMessages.no_user_exist() - return - user_id = user_data["object_id"] - if buffertype == "audio": - buffer = buffers.audioBuffer(parent=self.window.tb, name="{0}_audio".format(user_id,), composefunc="render_audio", session=self.session, create_tab=False, endpoint="get", parent_endpoint="audio", owner_id=user_id) - user = self.session.get_user(user_id, key="user1") - name_ = _("{user1_nom}'s audios").format(**user) - elif buffertype == "wall": - buffer = buffers.feedBuffer(parent=self.window.tb, name="{0}_feed".format(user_id,), composefunc="render_status", session=self.session, create_tab=False, endpoint="get", parent_endpoint="wall", extended=1, count=self.session.settings["buffers"]["count_for_wall_buffers"], owner_id=user_id) - user = self.session.get_user(user_id, key="user1") - name_ = _("{user1_nom}'s posts").format(**user) - elif buffertype == "friends": - buffer = buffers.peopleBuffer(parent=self.window.tb, name="friends_{0}".format(user_id,), composefunc="render_person", session=self.session, create_tab=False, endpoint="get", parent_endpoint="friends", count=5000, fields="uid, first_name, last_name, last_seen", user_id=user_id) - user = self.session.get_user(user_id, key="user1") - name_ = _("{user1_nom}'s friends").format(**user) - wx.CallAfter(self.complete_buffer_creation, buffer=buffer, name_=name_, position=self.window.search("timelines")) - - def complete_buffer_creation(self, buffer, name_, position): - answer = buffer.get_items() - if answer is not True: - commonMessages.show_error_code(answer) - return - self.buffers.append(buffer) - self.window.insert_buffer(buffer.tab, name_, position) - - def search_chat_buffer(self, user_id): - for i in self.buffers: - if "_messages" in i.name: - if "peer_id" in i.kwargs and i.kwargs["peer_id"] == user_id: return i - return None - - def chat_from_id(self, user_id, setfocus=True, unread=False): - b = self.search_chat_buffer(user_id) - if b != None: - pos = self.window.search(b.name) - if setfocus: - self.window.change_buffer(pos) - return b.tab.text.SetFocus() - return - # Get name based in the ID. - # for users. - if user_id > 0 and user_id < 2000000000: - user = self.session.get_user(user_id, key="user1") - name = user["user1_nom"] - elif user_id > 2000000000: - chat = self.session.vk.client.messages.getChat(chat_id=user_id-2000000000) - name = chat["title"] - wx.CallAfter(pub.sendMessage, "create_buffer", buffer_type="chatBuffer", buffer_title=name, parent_tab="chats", get_items=True, kwargs=dict(parent=self.window.tb, name="{0}_messages".format(user_id,), composefunc="render_message", session=self.session, unread=unread, count=200, peer_id=user_id, rev=0, extended=True, fields="id, user_id, date, read_state, out, body, attachments, deleted")) -# if setfocus: -# pos = self.window.search(buffer.name) -# self.window.change_buffer(pos) -# call_threaded(buffer.get_items, unread=unread) -# if setfocus: buffer.tab.text.SetFocus() -# return True - - def user_online(self, event): - if self.session.settings["chat"]["notify_online"] == False: - return - user_name = self.session.get_user(event.user_id) - msg = _("{user1_nom} is online.").format(**user_name) - sound = "friend_online.ogg" - self.notify(msg, sound, self.session.settings["chat"]["notifications"]) - - def user_offline(self, event): - if self.session.settings["chat"]["notify_offline"] == False: - return - user_name = self.session.get_user(event.user_id) - msg = _("{user1_nom} is offline.").format(**user_name) - sound = "friend_offline.ogg" - self.notify(msg, sound, self.session.settings["chat"]["notifications"]) - - def user_typing(self, obj): - buffer = self.search_chat_buffer(obj.user_id) - if buffer != None and buffer == self.get_current_buffer(): - user = self.session.get_user(obj.user_id) - output.speak(_("{user1_nom} is typing...").format(**user)) - - def get_chat(self, obj=None): - """ Searches or creates a chat buffer with the id of the user that is sending or receiving a message. - obj vk_api.longpoll.EventType: an event wich defines some data from the vk's long poll server.""" - message = {} - uid = obj.peer_id - buffer = self.search_chat_buffer(uid) - if obj.from_me: - message.update(out=0) - # If there is no buffer, we must create one in a wxThread so it will not crash. - if buffer == None: - wx.CallAfter(self.chat_from_id, uid, setfocus=self.session.settings["chat"]["automove_to_conversations"], unread=True) - self.session.soundplayer.play("conversation_opened.ogg") - return - # If the chat already exists, let's create a dictionary wich will contains data of the received message. - message.update(id=obj.message_id, user_id=uid, date=obj.timestamp, body=utils.clean_text(obj.text), attachments=obj.attachments) - # if attachments is true, let's request for the full message with attachments formatted in a better way. - # ToDo: code improvements. We shouldn't need to request the same message again just for these attachments. - if len(message["attachments"]) != 0: - message_ids = message["id"] - results = self.session.vk.client.messages.getById(message_ids=message_ids) - message = results["items"][0] - if obj.from_me: - message["from_id"] = self.session.user_id - else: - message.update(read_state=0, out=0) - message["from_id"] = obj.user_id - data = [message] - # Let's add this to the buffer. - # ToDo: Clean this code and test how is the database working with this set to True. - num = self.session.order_buffer(buffer.name, data, True) - buffer.insert(self.session.db[buffer.name]["items"][-1], False) - self.session.soundplayer.play("message_received.ogg") - wx.CallAfter(self.reorder_buffer, buffer) - # Check if we have to read the message aloud - if buffer == self.get_current_buffer(): - rendered_message = renderers.render_message(message, self.session) - output.speak(rendered_message[0]) - - def set_online(self, notify=False): - try: - r = self.session.vk.client.account.setOnline() - except: - log.error("Error in setting online for the current user") - if notify: - self.window.notify("Socializer", "online now!") - - def set_offline(self): - try: - r = self.session.vk.client.account.setOffline() - except: - log.error("Error in setting offline status for the current user") - - def create_unread_messages(self): - if self.session.settings["chat"]["open_unread_conversations"] == False: - return - try: - log.debug("Getting possible unread messages.") - msgs = self.session.vk.client.messages.getConversations(count=200) - except VkApiError as ex: - if ex.code == 6: - log.exception("Something went wrong when getting messages. Waiting a second to retry") - for i in msgs["items"]: - call_threaded(self.chat_from_id, i["last_message"]["peer_id"], setfocus=False, unread=False) - time.sleep(0.6) - - def mark_as_read(self): - for i in self.buffers: - if hasattr(i, "reads") and len(i.reads) != 0: - response = self.session.vk.client.messages.markAsRead(peer_id=i.kwargs["peer_id"]) - i.clear_reads() - i.reads = [] - time.sleep(1) - - def get_audio_albums(self, user_id=None, create_buffers=True): - if self.session.settings["load_at_startup"]["audio_albums"] == False: - return - log.debug("Create audio albums...") - if self.session.settings["vk"]["use_alternative_tokens"]: - albums = self.session.vk.client_audio.get_albums(owner_id=user_id) - else: - albums = self.session.vk.client.audio.getPlaylists(owner_id=user_id) - albums = albums["items"] - self.session.audio_albums = albums - if create_buffers: - for i in albums: - wx.CallAfter(pub.sendMessage, "create_buffer", buffer_type="audioAlbum", buffer_title=_("Album: {0}").format(i["title"],), parent_tab="albums", loadable=True, kwargs=dict(parent=self.window.tb, name="{0}_audio_album".format(i["id"],), composefunc="render_audio", session=self.session, endpoint="get", parent_endpoint="audio", owner_id=user_id, album_id=i["id"])) - time.sleep(0.6) - - def get_video_albums(self, user_id=None, create_buffers=True): - if self.session.settings["load_at_startup"]["video_albums"] == False: - return - log.debug("Create video albums...") - albums = self.session.vk.client.video.getAlbums(owner_id=user_id) - self.session.video_albums = albums["items"] - if create_buffers: - for i in albums["items"]: - wx.CallAfter(pub.sendMessage, "create_buffer", buffer_type="videoAlbum", buffer_title=_("Album: {0}").format(i["title"],), parent_tab="video_albums", loadable=True, kwargs=dict(parent=self.window.tb, name="{0}_video_album".format(i["id"],), composefunc="render_video", session=self.session, endpoint="get", parent_endpoint="video", count=self.session.settings["buffers"]["count_for_video_buffers"], user_id=user_id, album_id=i["id"])) - time.sleep(0.15) - - def get_communities(self, user_id=None, create_buffers=True, force_action=False): - if self.session.settings["vk"]["invited_to_group"] == False: - self.session.settings["vk"]["invited_to_group"] = True - self.session.settings.write() - socializer_group = self.session.vk.client.groups.getById(group_ids="175825000")[0] - if socializer_group["is_member"] ==False: - d = commonMessages.join_group() - self.session.settings["vk"]["invited_to_group"] = True - self.session.settings.write() - if d == widgetUtils.YES: - result = self.session.vk.client.groups.join(group_id=socializer_group["id"]) - if result == 1: - commonMessages.group_joined() - else: - log.error("Invalid result when joining the Socializer's group: %d" % (result)) - if self.session.settings["load_at_startup"]["communities"] == False and force_action == False: - return - log.debug("Create community buffers...") - groups= self.session.vk.client.groups.get(user_id=user_id, extended=1, count=1000) - self.session.groups=groups["items"] - # Let's feed the local database cache with new groups coming from here. - data= dict(profiles=[], groups=self.session.groups) - self.session.process_usernames(data) - if create_buffers: - for i in self.session.groups: - wx.CallAfter(pub.sendMessage, "create_buffer", buffer_type="communityBuffer", buffer_title=i["name"], parent_tab="communities", loadable=True, get_items=True, kwargs=dict(parent=self.window.tb, name="{0}_community".format(i["id"],), composefunc="render_status", session=self.session, endpoint="get", parent_endpoint="wall", count=self.session.settings["buffers"]["count_for_wall_buffers"], owner_id=-1*i["id"])) - time.sleep(0.15) - - def create_audio_album(self, *args, **kwargs): - d = creation.audio_album() - if d.get_response() == widgetUtils.OK and d.get("title") != "": - response = self.session.vk.client.audio.createPlaylist(owner_id=self.session.user_id, title=d.get("title")) - if "id" not in response: - return - album_id = response["id"] - buffer = buffers.audioAlbum(parent=self.window.tb, name="{0}_audio_album".format(album_id,), composefunc="render_audio", session=self.session, endpoint="get", parent_endpoint="audio", full_list=True, count=self.session.settings["buffers"]["count_for_audio_buffers"], user_id=self.session.user_id, album_id=album_id) - buffer.can_get_items = False - # Translators: {0} will be replaced with an audio album's title. - name_ = _("Album: {0}").format(d.get("title"),) - self.buffers.append(buffer) - self.window.insert_buffer(buffer.tab, name_, self.window.search("albums")) - buffer.get_items() - self.get_audio_albums(user_id=self.session.user_id, create_buffers=False) - - def delete_audio_album(self, *args, **kwargs): - if len(self.session.audio_albums) == 0: - return commonMessages.no_audio_albums() - answer = selector.album(_("Select the album you want to delete"), self.session) - if answer.item == None: - return - response = commonMessages.delete_audio_album() - if response != widgetUtils.YES: return - removal = self.session.vk.client.audio.deletePlaylist(playlist_id=answer.item, owner_id=self.session.user_id) - if removal == 1: - buffer = self.search("{0}_audio_album".format(answer.item,)) - buff = self.window.search(buffer.name) - self.window.remove_buffer(buff) - self.buffers.remove(buffer) - del buffer - self.get_audio_albums(user_id=self.session.user_id, create_buffers=False) - - def create_video_album(self, *args, **kwargs): - d = creation.audio_album() - if d.get_response() == widgetUtils.OK and d.get("title") != "": - response = self.session.vk.client.video.addAlbum(title=d.get("title")) - if ("album_id" in response) == False: return - album_id = response["album_id"] - buffer = buffers.videoAlbum(parent=self.window.tb, name="{0}_video_album".format(album_id,), composefunc="render_video", session=self.session, endpoint="get", parent_endpoint="video", count=self.session.settings["buffers"]["count_for_video_buffers"], user_id=self.session.user_id, album_id=album_id) - buffer.can_get_items = False - # Translators: {0} will be replaced with a video album's title. - name_ = _("Album: {0}").format(d.get("title"),) - self.buffers.append(buffer) - self.window.insert_buffer(buffer.tab, name_, self.window.search("video_albums")) - buffer.get_items() - self.session.video_albums = self.session.vk.client.video.getAlbums(owner_id=self.session.user_id)["items"] - - def delete_video_album(self, *args, **kwargs): - if len(self.session.video_albums) == 0: - return commonMessages.no_video_albums() - answer = selector.album(_("Select the album you want to delete"), self.session, "video_albums") - if answer.item == None: - return - response = commonMessages.delete_audio_album() - if response != widgetUtils.YES: return - removal = self.session.vk.client.video.deleteAlbum(album_id=answer.item) - buffer = self.search("{0}_video_album".format(answer.item,)) - buff = self.window.search(buffer.name) - self.window.remove_buffer(buff) - self.buffers.remove(buffer) - del buffer - self.session.video_albums = self.session.vk.client.video.getAlbums(owner_id=self.session.user_id)["items"] - - def check_documentation(self, *args, **kwargs): - lang = localization.get("documentation") - os.chdir("documentation/%s" % (lang,)) - webbrowser.open("manual.html") - os.chdir("../../") - - def menu_play_pause(self, *args, **kwargs): - if player.player.stream != None: - return player.player.pause() - else: - b = self.get_current_buffer() - if hasattr(b, "play_all"): - b.play_all() - else: - self.search("me_audio").play_all() - - def menu_play_next(self, *args, **kwargs): - return player.player.play_next() -# b = self.get_current_buffer() -# if hasattr(b, "play_next"): -# b.play_next() -# else: -# self.search("me_audio").play_next() - - def menu_play_previous(self, *args, **kwargs): - return player.player.play_previous() -# b = self.get_current_buffer() -# if hasattr(b, "play_previous"): -# b.play_previous() -# else: -# self.search("me_audio").play_previous() - - def menu_play_all(self, *args, **kwargs): - b = self.get_current_buffer() - if hasattr(b, "play_all"): - b.play_all() - else: - self.search("me_audio").play_all() - - def menu_volume_down(self, *args, **kwargs): - player.player.volume = player.player.volume-5 - - def menu_volume_up(self, *args, **kwargs): - player.player.volume = player.player.volume+5 - - def menu_mute(self, *args, **kwargs): - player.player.volume = 0 - - def user_profile(self, person): - p = presenters.userProfilePresenter(session=self.session, user_id=person, view=views.userProfileDialog(), interactor=interactors.userProfileInteractor()) - - def view_my_profile(self, *args, **kwargs): - self.user_profile(self.session.user_id) - - def view_my_profile_in_browser(self, *args, **kwargs): - webbrowser.open_new_tab("https://vk.com/id{id}".format(id=self.session.user_id,)) - - def notify(self, message="", sound="", type="native"): - if type == "native": - self.window.notify(_("Socializer"), message) - else: - if sound != "": - self.session.soundplayer.play(sound) - if message != "": - output.speak(message) - - def handle_longpoll_read_timeout(self): - if hasattr(self, "longpoll"): - self.notify(message=_("Chat disconnected. Trying to connect in 60 seconds")) - time.sleep(60) - if hasattr(self, "longpoll"): - del self.longpoll - self.create_longpoll_thread(notify=True) - - def set_status(self, *args, **kwargs): - dlg = wx.TextEntryDialog(self.window, _("Write your status message"), _("Set status")) - if dlg.ShowModal() == widgetUtils.OK: - result = dlg.GetValue() - info = self.session.vk.client.account.saveProfileInfo(status=result) - commonMessages.updated_status() - dlg.Destroy() - - def on_report_error(self, *args, **kwargs): - r = issueReporter.reportBug() - - def reorder_buffer(self, buffer): - """ this puts the chat buffers at the top of the list when there are new incoming messages. - In order to do so, we search for the current buffer's tab, remove the page from the TreeCtrl (without destroying the associated tab) - and reinsert it as a new child of the chat buffer. - Lastly we ensure the user is focused in the same buffer than before.""" - buffer_window = self.window.search(buffer.name) - # If buffer window is already in the first position after chat, we should not do anything here because calculations for moving buffers are expensive. - if buffer_window == self.window.search("chats")+1: - return - # Gets buffer title so we don't have to generate it again in future. - buffer_title = self.window.get_buffer_text(buffer_window) - # Determine if the current buffer is the buffer receiving a new message. - if buffer == self.get_current_buffer(): - focused_buffer = True - else: - focused_buffer = False - # This call will not destroy the associated tab for the chat buffer, thus allowing us to readd it in other position. - self.window.remove_buffer_from_position(buffer_window) - self.window.insert_chat_buffer(buffer.tab, buffer_title, self.window.search("chats")+1) - # Let's manipulate focus so users will not notice the change in buffers. - if focused_buffer: - new_position = self.window.search(buffer.name) - self.window.change_buffer(new_position) - else: - new_position = self.window.search(self.get_current_buffer().name) - self.window.change_buffer(new_position) - - def load_community_posts(self, *args, **kwargs): - """ Load community posts. It just calls to the needed method in the community buffer.""" - current_buffer = self.get_current_buffer() - if current_buffer.name.endswith("_community"): - current_buffer.load_community() - - def load_community_audios(self, *args, **kwargs): - """ Load community audios if they are not loaded already.""" - current_buffer = self.get_current_buffer() - # Get group_info if the community buffer does not have it already, so future menus will be able to use it. - if not hasattr(current_buffer, "group_info"): - group_info = self.session.vk.client.groups.getById(group_ids=-1*current_buffer.kwargs["owner_id"], fields="counters")[0] - current_buffer.group_info = group_info - if "audios" not in current_buffer.group_info["counters"]: - commonMessages.community_no_items() - return - new_name = current_buffer.name+"_audios" - wx.CallAfter(pub.sendMessage, "create_buffer", buffer_type="audioBuffer", buffer_title=_("Audios"), parent_tab=current_buffer.tab.name, get_items=True, kwargs=dict(parent=self.window.tb, name=new_name, composefunc="render_audio", session=self.session, endpoint="get", parent_endpoint="audio", owner_id=current_buffer.kwargs["owner_id"])) - - def load_community_videos(self, *args, **kwargs): - """ Load community videos if they are not loaded already.""" - current_buffer = self.get_current_buffer() - # Get group_info if the community buffer does not have it already, so future menus will be able to use it. - if not hasattr(current_buffer, "group_info"): - group_info = self.session.vk.client.groups.getById(group_ids=-1*current_buffer.kwargs["owner_id"], fields="counters")[0] - current_buffer.group_info = group_info - if "videos" not in current_buffer.group_info["counters"]: - commonMessages.community_no_items() - return - new_name = current_buffer.name+"_videos" - wx.CallAfter(pub.sendMessage, "create_buffer", buffer_type="videoBuffer", buffer_title=_("Videos"), parent_tab=current_buffer.tab.name, get_items=True, kwargs=dict(parent=self.window.tb, name=new_name, composefunc="render_video", session=self.session, endpoint="get", parent_endpoint="video", count=self.session.settings["buffers"]["count_for_video_buffers"], owner_id=current_buffer.kwargs["owner_id"])) - - def load_community_topics(self, *args, **kwargs): - """ Load community topics.""" - current_buffer = self.get_current_buffer() - # Get group_info if the community buffer does not have it already, so future menus will be able to use it. - if not hasattr(current_buffer, "group_info"): - group_info = self.session.vk.client.groups.getById(group_ids=-1*current_buffer.kwargs["owner_id"], fields="counters")[0] - current_buffer.group_info = group_info - if "topics" not in current_buffer.group_info["counters"]: - commonMessages.community_no_items() - return - new_name = current_buffer.name+"_topics" - wx.CallAfter(pub.sendMessage, "create_buffer", buffer_type="topicBuffer", buffer_title=_("Topics"), parent_tab=current_buffer.tab.name, get_items=True, kwargs=dict(parent=self.window.tb, name=new_name, composefunc="render_topic", session=self.session, endpoint="getTopics", parent_endpoint="board", count=100, group_id=-1*current_buffer.kwargs["owner_id"], extended=1)) - - def load_community_documents(self, *args, **kwargs): - current_buffer = self.get_current_buffer() - # Get group_info if the community buffer does not have it already, so future menus will be able to use it. - if not hasattr(current_buffer, "group_info"): - group_info = self.session.vk.client.groups.getById(group_ids=-1*current_buffer.kwargs["owner_id"], fields="counters")[0] - current_buffer.group_info = group_info - if "docs" not in current_buffer.group_info["counters"]: - commonMessages.community_no_items() - return - new_name = current_buffer.name+"_documents" - wx.CallAfter(pub.sendMessage, "create_buffer", buffer_type="documentCommunityBuffer", buffer_title=_("Documents"), parent_tab=current_buffer.tab.name, get_items=True, kwargs=dict(parent=self.window.tb, name=new_name, composefunc="render_document", session=self.session, endpoint="get", parent_endpoint="docs", owner_id=current_buffer.kwargs["owner_id"])) - - def load_community_buffers(self, *args, **kwargs): - """ Load all community buffers regardless of the setting present in optional buffers tab of the preferences dialog.""" - call_threaded(self.get_communities, self.session.user_id, force_action=True) - - def unload_community_buffers(self, *args, **kwargs): - """ Delete all buffers belonging to groups.""" - communities = self.get_all_buffers("_community") - for buffer in communities: - buff = self.window.search(buffer.name) - self.window.remove_buffer(buff) - self.buffers.remove(buffer) - del self.session.groups - + def search(self, tab_name): + for i in range(0, len(self.buffers)): + if self.buffers[i].name == tab_name: + return self.buffers[i] + return False + + def get_all_buffers(self, contains): + results = [] + for i in self.buffers: + if contains in i.name: + results.append(i) + return results + + def __init__(self, *args, **kwargs): + super(Controller, self).__init__(*args, **kwargs) + log.debug("Starting main controller...") + self.buffers = [] + player.setup() + self.session = session.sessions[list(session.sessions.keys())[0]] + self.create_controls() + call_threaded(updater.do_update, update_type=self.session.settings["general"]["update_channel"]) + + def create_buffer(self, buffer_type="baseBuffer", buffer_title="", parent_tab=None, loadable=False, get_items=False, kwargs={}): + if not hasattr(buffers, buffer_type): + raise AttributeError("Specified buffer type does not exist.") + buffer = getattr(buffers, buffer_type)(**kwargs) + if loadable: + buffer.can_get_items = False + self.buffers.append(buffer) + if parent_tab == None: + self.send_message("add_buffer", widget=buffer.tab, title=buffer_title) + else: + self.send_message("insert_buffer", widget=buffer.tab, title=buffer_title, parent=parent_tab) + if get_items: + call_threaded(buffer.get_items) + + def create_empty_buffer(self, buffer_type="empty", buffer_title="", parent_tab=None, kwargs={}): + if not hasattr(buffers, buffer_type): + raise AttributeError("Specified buffer type does not exist.") + buffer = getattr(buffers, buffer_type)(**kwargs) + self.buffers.append(buffer) + if parent_tab == None: + self.window.add_buffer(buffer.tab, buffer_title) + else: + self.window.insert_buffer(buffer.tab, buffer_title, self.window.search(parent_tab)) + + def create_controls(self): + log.debug("Creating controls for the window...") + pub.sendMessage("create_empty_buffer", buffer_title=_("Posts"), kwargs=dict(parent=self.window.tb, name="posts")) + pub.sendMessage("create_buffer", buffer_type="baseBuffer", buffer_title=_("Home"), parent_tab="posts", kwargs=dict(parent=self.window.tb, name="home_timeline", session=self.session, composefunc="render_newsfeed_item", endpoint="newsfeed", count=self.session.settings["buffers"]["count_for_wall_buffers"])) + pub.sendMessage("create_buffer", buffer_type="feedBuffer", buffer_title=_("My wall"), parent_tab="posts", kwargs=dict(parent=self.window.tb, name="me_feed", composefunc="render_status", session=self.session, endpoint="get", parent_endpoint="wall", extended=1, count=self.session.settings["buffers"]["count_for_wall_buffers"])) + pub.sendMessage("create_empty_buffer", buffer_title=_("Music"), kwargs=dict(parent=self.window.tb, name="audios")) + pub.sendMessage("create_buffer", buffer_type="audioBuffer", buffer_title=_("My audios"), parent_tab="audios", kwargs=dict(parent=self.window.tb, name="me_audio", composefunc="render_audio", session=self.session, endpoint="get", parent_endpoint="audio")) + if self.session.settings["vk"]["use_alternative_tokens"] == False: + pub.sendMessage("create_buffer", buffer_type="audioBuffer", buffer_title=_("Populars"), parent_tab="audios", kwargs=dict(parent=self.window.tb, name="popular_audio", composefunc="render_audio", session=self.session, endpoint="getPopular", parent_endpoint="audio", full_list=True, count=self.session.settings["buffers"]["count_for_audio_buffers"])) + pub.sendMessage("create_buffer", buffer_type="audioBuffer", buffer_title=_("Recommendations"), parent_tab="audios", kwargs=dict(parent=self.window.tb, name="recommended_audio", composefunc="render_audio", session=self.session, endpoint="getRecommendations", parent_endpoint="audio", full_list=True, count=self.session.settings["buffers"]["count_for_audio_buffers"])) + pub.sendMessage("create_empty_buffer", buffer_type="empty", buffer_title=_("Albums"), parent_tab="audios", kwargs=dict(parent=self.window.tb, name="albums")) + pub.sendMessage("create_empty_buffer", buffer_title=_("Video"), kwargs=dict(parent=self.window.tb, name="videos")) + pub.sendMessage("create_buffer", buffer_type="videoBuffer", buffer_title=_("My videos"), parent_tab="videos", kwargs=dict(parent=self.window.tb, name="me_video", composefunc="render_video", session=self.session, endpoint="get", parent_endpoint="video", count=self.session.settings["buffers"]["count_for_video_buffers"])) + pub.sendMessage("create_empty_buffer", buffer_title=_("Albums"), parent_tab="videos", kwargs=dict(parent=self.window.tb, name="video_albums")) + pub.sendMessage("create_empty_buffer", buffer_title=_("People"), kwargs=dict(parent=self.window.tb, name="people")) + pub.sendMessage("create_buffer", buffer_type="peopleBuffer", buffer_title=_("Friends"), parent_tab="people", kwargs=dict(parent=self.window.tb, name="friends_", composefunc="render_person", session=self.session, endpoint="get", parent_endpoint="friends", count=5000, order="hints", fields="uid, first_name, last_name, last_seen")) + pub.sendMessage("create_empty_buffer", buffer_title=_("Friendship requests"), parent_tab="people", kwargs=dict(parent=self.window.tb, name="requests")) + pub.sendMessage("create_buffer", buffer_type="requestsBuffer", buffer_title=_("Pending requests"), parent_tab="requests", kwargs=dict(parent=self.window.tb, name="friend_requests", composefunc="render_person", session=self.session, count=1000)) + pub.sendMessage("create_buffer", buffer_type="requestsBuffer", buffer_title=_("I follow"), parent_tab="requests", kwargs=dict(parent=self.window.tb, name="friend_requests_sent", composefunc="render_person", session=self.session, count=1000, out=1)) + pub.sendMessage("create_buffer", buffer_type="requestsBuffer", buffer_title=_("Subscribers"), parent_tab="requests", kwargs=dict(parent=self.window.tb, name="subscribers", composefunc="render_person", session=self.session, count=1000, need_viewed=1)) + pub.sendMessage("create_buffer", buffer_type="documentBuffer", buffer_title=_("Documents"), parent_tab=None, loadable=True, kwargs=dict(parent=self.window.tb, name="documents", composefunc="render_document", session=self.session, endpoint="get", parent_endpoint="docs")) + pub.sendMessage("create_empty_buffer", buffer_title=_("Communities"), kwargs=dict(parent=self.window.tb, name="communities")) + pub.sendMessage("create_empty_buffer", buffer_title=_("Chats"), kwargs=dict(parent=self.window.tb, name="chats")) + pub.sendMessage("create_empty_buffer", buffer_title=_("Timelines"), kwargs=dict(parent=self.window.tb, name="timelines")) + self.window.realize() + self.repeatedUpdate = RepeatingTimer(120, self.update_all_buffers) + self.repeatedUpdate.start() + self.readMarker = RepeatingTimer(60, self.mark_as_read) + self.readMarker.start() + + def connect_events(self): + log.debug("Connecting events to responses...") + pub.subscribe(self.in_post, "posted") + pub.subscribe(self.download, "download-file") + pub.subscribe(self.play_audio, "play-audio") + pub.subscribe(self.play_audios, "play-audios") + pub.subscribe(self.view_post, "open-post") + pub.subscribe(self.update_status_bar, "update-status-bar") + pub.subscribe(self.chat_from_id, "new-chat") + pub.subscribe(self.authorisation_failed, "authorisation-failed") + pub.subscribe(self.user_profile, "user-profile") + pub.subscribe(self.user_online, "user-online") + pub.subscribe(self.user_offline, "user-offline") + pub.subscribe(self.notify, "notify") + pub.subscribe(self.handle_longpoll_read_timeout, "longpoll-read-timeout") + pub.subscribe(self.create_buffer, "create_buffer") + pub.subscribe(self.create_empty_buffer, "create_empty_buffer") + pub.subscribe(self.user_typing, "user-typing") + widgetUtils.connect_event(self.window, widgetUtils.CLOSE_EVENT, self.exit) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.update_buffer, menuitem=self.window.update_buffer) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.check_for_updates, menuitem=self.window.check_for_updates) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.window.about_dialog, menuitem=self.window.about) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.search_audios, menuitem=self.window.search_audios) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.search_videos, menuitem=self.window.search_videos) + widgetUtils.connect_event(self.window, widgetUtils.MENU,self.remove_buffer, menuitem=self.window.remove_buffer_) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.get_more_items, menuitem=self.window.load_previous_items) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.changelog, menuitem=self.window.changelog) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.configuration, menuitem=self.window.settings_dialog) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.new_timeline, menuitem=self.window.timeline) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.create_audio_album, menuitem=self.window.audio_album) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.delete_audio_album, menuitem=self.window.delete_audio_album) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.create_video_album, menuitem=self.window.video_album) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.delete_video_album, menuitem=self.window.delete_video_album) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.check_documentation, menuitem=self.window.documentation) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.menu_play_pause, menuitem=self.window.player_play) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.menu_play_next, menuitem=self.window.player_next) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.menu_play_previous, menuitem=self.window.player_previous) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.menu_play_all, menuitem=self.window.player_play_all) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.menu_volume_down, menuitem=self.window.player_volume_down) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.menu_volume_up, menuitem=self.window.player_volume_up) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.menu_mute, menuitem=self.window.player_mute) + pub.subscribe(self.get_chat, "order-sent-message") + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.view_my_profile, menuitem=self.window.view_profile) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.view_my_profile_in_browser, menuitem=self.window.open_in_browser) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.set_status, menuitem=self.window.set_status) + widgetUtils.connect_event(self.window, widgetUtils.MENU, self.on_report_error, menuitem=self.window.report) + self.window.tb.Bind(wx.EVT_CONTEXT_MENU, self.on_context_menu) + + def disconnect_events(self): + log.debug("Disconnecting some events...") + pub.unsubscribe(self.in_post, "posted") + pub.unsubscribe(self.download, "download-file") + pub.unsubscribe(self.play_audio, "play-audio") + pub.unsubscribe(self.authorisation_failed, "authorisation-failed") + pub.unsubscribe(self.play_audios, "play-audios") + pub.unsubscribe(self.view_post, "open-post") + pub.unsubscribe(self.update_status_bar, "update-status-bar") + pub.unsubscribe(self.user_online, "user-online") + pub.unsubscribe(self.user_offline, "user-offline") + pub.unsubscribe(self.notify, "notify") + + def on_context_menu(self, event, *args, **kwargs): + """ Handles context menu event in the tree buffers.""" + # If the focus is not in the TreeCtrl of the Treebook, then we should not display any menu. + if isinstance(self.window.FindFocus(), wx.TreeCtrl) == False: + event.Skip() + return + menu = None + # Get the current buffer and let's choose a different menu depending on the selected buffer. + current_buffer = self.get_current_buffer() + # Deal with menu for community buffers. + if current_buffer.name.endswith("_community"): + menu = menus.communityBufferMenu() + # disable post loading if the community has already loaded posts. + if current_buffer.can_get_items: + menu.load_posts.Enable(False) + # Disable loading of audios, videos, documents or topics depending in two conditions. + # 1. If the buffer already exists, which means they are already loaded, or + # 2. If the group_info does not have counters for such items, which would indicate there are no items posted yet. + if self.search(current_buffer.name+"_audios") != False: + menu.load_audios.Enable(False) + elif hasattr(current_buffer, "group_info") and "audios" not in current_buffer.group_info["counters"]: + menu.load_audios.Enable(False) + if self.search(current_buffer.name+"_videos") != False: + menu.load_videos.Enable(False) + elif hasattr(current_buffer, "group_info") and "videos" not in current_buffer.group_info["counters"]: + menu.load_videos.Enable(False) + if self.search(current_buffer.name+"_topics") != False: + menu.load_topics.Enable(False) + elif hasattr(current_buffer, "group_info") and "topics" not in current_buffer.group_info["counters"]: + menu.load_topics.Enable(False) + + if self.search(current_buffer.name+"_documents") != False: + menu.load_documents.Enable(False) + elif hasattr(current_buffer, "group_info") and "docs" not in current_buffer.group_info["counters"]: + menu.load_documents.Enable(False) + # Connect the rest of the functions. + widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_community_posts, menuitem=menu.load_posts) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_community_topics, menuitem=menu.load_topics) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_community_audios, menuitem=menu.load_audios) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_community_videos, menuitem=menu.load_videos) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_community_documents, menuitem=menu.load_documents) + # Deal with the communities section itself. + if current_buffer.name == "communities": + menu = wx.Menu() + # Insert a different option depending if group buffers are loaded or scheduled to be loaded or not. + if self.session.settings["load_at_startup"]["communities"] == False and not hasattr(self.session, "groups"): + option = menu.Append(wx.NewId(), _("Load groups")) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.load_community_buffers, menuitem=option) + else: + option = menu.Append(wx.NewId(), _("Discard groups")) + widgetUtils.connect_event(menu, widgetUtils.MENU, self.unload_community_buffers, menuitem=option) + if menu != None: + self.window.PopupMenu(menu, self.window.FindFocus().GetPosition()) + # If there are no available menus, let's indicate it. + else: + output.speak(_("menu unavailable for this buffer.")) + + def authorisation_failed(self): + commonMessages.bad_authorisation() + + def login(self): + self.window.change_status(_("Logging in VK")) + self.session.login() + self.window.change_status(_("Ready")) + for i in self.buffers: + if hasattr(i, "get_items"): + # Translators: {0} will be replaced with the name of a buffer. + self.window.change_status(_("Loading items for {0}").format(i.name,)) + i.get_items() + self.window.change_status(_("Ready")) + self.create_unread_messages() + self.status_setter = RepeatingTimer(280, self.set_online) + self.status_setter.start() + self.set_online(notify=True) + self.get_audio_albums(self.session.user_id) + self.get_video_albums(self.session.user_id) + self.get_communities(self.session.user_id) + self.create_longpoll_thread() + + def create_longpoll_thread(self, notify=False): + try: + self.longpoll = longpollthread.worker(self.session) + self.longpoll.start() + if notify: + self.notify(message=_("Chat server reconnected")) + except ConnectionError: + pub.sendMessage("longpoll-read-timeout") + + def in_post(self, buffer): + buffer = self.search(buffer) + buffer.get_items() + buffer = self.search("home_timeline") + buffer.get_items() + + def update_all_buffers(self): + log.debug("Updating buffers...") + self.get_audio_albums(self.session.user_id, create_buffers=False) + self.get_video_albums(self.session.user_id, create_buffers=False) + for i in self.buffers: + if hasattr(i, "get_items"): + i.get_items() + log.debug("Updated %s" % (i.name)) + + def download(self, url, filename): + log.debug("downloading %s URL to %s filename" % (url, filename,)) + call_threaded(utils.download_file, url, filename, self.window) + + def play_audio(self, audio_object): + # Restricted audios don't include an URL paramether. + # Restriction can be due to licensed content to unauthorized countries. + if "url" in audio_object and audio_object["url"] =="": + self.notify(message=_("This file could not be played because it is not allowed in your country")) + return + call_threaded(player.player.play, audio_object, fresh=True) + + def play_audios(self, audios): + player.player.play_all(audios, shuffle=self.window.player_shuffle.IsChecked()) + + def view_post(self, post_object, controller_): + p = getattr(presenters, controller_+"Presenter")(session=self.session, postObject=post_object, interactor=getattr(interactors, controller_+"Interactor")(), view=getattr(views, controller_)()) + + def exit(self, *args, **kwargs): + log.debug("Receibed an exit signal. closing...") + self.set_offline() + self.disconnect_events() + volume = player.player.volume + config.app["sound"]["volume"] = volume + config.app.write() + self.window.Destroy() + wx.GetApp().ExitMainLoop() + + def update_buffer(self, *args, **kwargs): + b = self.get_current_buffer() + b.get_items() + + def get_more_items(self, *args, **kwargs): + b = self.get_current_buffer() + b.get_more_items() + + def check_for_updates(self, *args, **kwargs): + update = updater.do_update(update_type=self.session.settings["general"]["update_channel"]) + if update == False: + commonMessages.no_update_available() + + def search_audios(self, *args, **kwargs): + dlg = searchDialogs.searchAudioDialog() + if dlg.get_response() == widgetUtils.OK: + q = dlg.get("term") + auto_complete = True + count = 300 + performer_only = dlg.get_state("title") + sort = dlg.get_sort_order() + newbuff = buffers.audioBuffer(parent=self.window.tb, name="{0}_audiosearch".format(q,), session=self.session, composefunc="render_audio", parent_endpoint="audio", endpoint="search", q=q, auto_complete=auto_complete, count=count, performer_only=performer_only, sort=sort) + self.buffers.append(newbuff) + call_threaded(newbuff.get_items) + # Translators: {0} will be replaced with the search term. + self.window.insert_buffer(newbuff.tab, _("Search for {0}").format(q,), self.window.search("audios")) + + def search_videos(self, *args, **kwargs): + dlg = searchDialogs.searchVideoDialog() + if dlg.get_response() == widgetUtils.OK: + params = {} + params["q"] = dlg.get("term") + params["count"] = 200 + hd = dlg.get_checkable("hd") + if hd != 0: + params["hd"] = 1 + params["adult"] = dlg.get_checkable("safe_search") + params["sort"] = dlg.get_sort_order() +# params["filters"] = "youtube, vimeo, short, long, mp4" + print(params) + newbuff = buffers.videoBuffer(parent=self.window.tb, name="{0}_videosearch".format(params["q"],), session=self.session, composefunc="render_video", parent_endpoint="video", endpoint="search", **params) + self.buffers.append(newbuff) + call_threaded(newbuff.get_items) + # Translators: {0} will be replaced with the search term. + self.window.insert_buffer(newbuff.tab, _("Search for {0}").format(params["q"],), self.window.search("videos")) + + def update_status_bar(self, status): + self.window.change_status(status) + + def remove_buffer(self, event, mandatory=False, *args, **kwargs): + buffer = self.get_current_buffer() + buff = self.window.search(buffer.name) + answer = buffer.remove_buffer(mandatory) + if answer == False: + return + self.window.remove_buffer(buff) + self.buffers.remove(buffer) + del buffer + + def changelog(self, *args, **kwargs): + lang = localization.get("documentation") + os.chdir("documentation/%s" % (lang,)) + webbrowser.open("changelog.html") + os.chdir("../../") + + def configuration(self, *args, **kwargs): + """ Opens the global settings dialogue.""" + presenter = presenters.configurationPresenter(session=self.session, view=views.configurationDialog(title=_("Preferences")), interactor=interactors.configurationInteractor()) + + def new_timeline(self, *args, **kwargs): + b = self.get_current_buffer() + # If executing this method from an empty buffer we should get the newsfeed buffer. + if not hasattr(b, "get_users"): + b = self.search("home_timeline") + # Get a list of (id, user) objects. + d = [] + for i in self.session.db["users"]: + d.append((i, self.session.get_user(i)["user1_gen"])) + # Do the same for communities. + for i in self.session.db["groups"]: + d.append((-i, self.session.get_user(-i)["user1_nom"])) + a = timeline.timelineDialog([i[1] for i in d]) + if a.get_response() == widgetUtils.OK: + user = a.get_user() + buffertype = a.get_buffer_type() + user_id = "" + for i in d: + if i[1] == user: + user_id = i[0] + if user_id == "": + user_data = self.session.vk.client.utils.resolveScreenName(screen_name=user) + if type(user_data) == list: + commonMessages.no_user_exist() + return + user_id = user_data["object_id"] + if buffertype == "audio": + buffer = buffers.audioBuffer(parent=self.window.tb, name="{0}_audio".format(user_id,), composefunc="render_audio", session=self.session, create_tab=False, endpoint="get", parent_endpoint="audio", owner_id=user_id) + user = self.session.get_user(user_id, key="user1") + name_ = _("{user1_nom}'s audios").format(**user) + elif buffertype == "wall": + buffer = buffers.feedBuffer(parent=self.window.tb, name="{0}_feed".format(user_id,), composefunc="render_status", session=self.session, create_tab=False, endpoint="get", parent_endpoint="wall", extended=1, count=self.session.settings["buffers"]["count_for_wall_buffers"], owner_id=user_id) + user = self.session.get_user(user_id, key="user1") + name_ = _("{user1_nom}'s posts").format(**user) + elif buffertype == "friends": + buffer = buffers.peopleBuffer(parent=self.window.tb, name="friends_{0}".format(user_id,), composefunc="render_person", session=self.session, create_tab=False, endpoint="get", parent_endpoint="friends", count=5000, fields="uid, first_name, last_name, last_seen", user_id=user_id) + user = self.session.get_user(user_id, key="user1") + name_ = _("{user1_nom}'s friends").format(**user) + wx.CallAfter(self.complete_buffer_creation, buffer=buffer, name_=name_, position=self.window.search("timelines")) + + def complete_buffer_creation(self, buffer, name_, position): + answer = buffer.get_items() + if answer is not True: + commonMessages.show_error_code(answer) + return + self.buffers.append(buffer) + self.window.insert_buffer(buffer.tab, name_, position) + + def search_chat_buffer(self, user_id): + for i in self.buffers: + if "_messages" in i.name: + if "peer_id" in i.kwargs and i.kwargs["peer_id"] == user_id: return i + return None + + def chat_from_id(self, user_id, setfocus=True, unread=False): + b = self.search_chat_buffer(user_id) + if b != None: + pos = self.window.search(b.name) + if setfocus: + self.window.change_buffer(pos) + return b.tab.text.SetFocus() + return + # Get name based in the ID. + # for users. + if user_id > 0 and user_id < 2000000000: + user = self.session.get_user(user_id, key="user1") + name = user["user1_nom"] + elif user_id > 2000000000: + chat = self.session.vk.client.messages.getChat(chat_id=user_id-2000000000) + name = chat["title"] + wx.CallAfter(pub.sendMessage, "create_buffer", buffer_type="chatBuffer", buffer_title=name, parent_tab="chats", get_items=True, kwargs=dict(parent=self.window.tb, name="{0}_messages".format(user_id,), composefunc="render_message", session=self.session, unread=unread, count=200, peer_id=user_id, rev=0, extended=True, fields="id, user_id, date, read_state, out, body, attachments, deleted")) +# if setfocus: +# pos = self.window.search(buffer.name) +# self.window.change_buffer(pos) +# call_threaded(buffer.get_items, unread=unread) +# if setfocus: buffer.tab.text.SetFocus() +# return True + + def user_online(self, event): + if self.session.settings["chat"]["notify_online"] == False: + return + user_name = self.session.get_user(event.user_id) + msg = _("{user1_nom} is online.").format(**user_name) + sound = "friend_online.ogg" + self.notify(msg, sound, self.session.settings["chat"]["notifications"]) + + def user_offline(self, event): + if self.session.settings["chat"]["notify_offline"] == False: + return + user_name = self.session.get_user(event.user_id) + msg = _("{user1_nom} is offline.").format(**user_name) + sound = "friend_offline.ogg" + self.notify(msg, sound, self.session.settings["chat"]["notifications"]) + + def user_typing(self, obj): + buffer = self.search_chat_buffer(obj.user_id) + if buffer != None and buffer == self.get_current_buffer(): + user = self.session.get_user(obj.user_id) + output.speak(_("{user1_nom} is typing...").format(**user)) + + def get_chat(self, obj=None): + """ Searches or creates a chat buffer with the id of the user that is sending or receiving a message. + obj vk_api.longpoll.EventType: an event wich defines some data from the vk's long poll server.""" + message = {} + uid = obj.peer_id + buffer = self.search_chat_buffer(uid) + if obj.from_me: + message.update(out=0) + # If there is no buffer, we must create one in a wxThread so it will not crash. + if buffer == None: + wx.CallAfter(self.chat_from_id, uid, setfocus=self.session.settings["chat"]["automove_to_conversations"], unread=True) + self.session.soundplayer.play("conversation_opened.ogg") + return + # If the chat already exists, let's create a dictionary wich will contains data of the received message. + message.update(id=obj.message_id, user_id=uid, date=obj.timestamp, body=utils.clean_text(obj.text), attachments=obj.attachments) + # if attachments is true, let's request for the full message with attachments formatted in a better way. + # ToDo: code improvements. We shouldn't need to request the same message again just for these attachments. + if len(message["attachments"]) != 0: + message_ids = message["id"] + results = self.session.vk.client.messages.getById(message_ids=message_ids) + message = results["items"][0] + if obj.from_me: + message["from_id"] = self.session.user_id + else: + message.update(read_state=0, out=0) + message["from_id"] = obj.user_id + data = [message] + # Let's add this to the buffer. + # ToDo: Clean this code and test how is the database working with this set to True. + num = self.session.order_buffer(buffer.name, data, True) + buffer.insert(self.session.db[buffer.name]["items"][-1], False) + self.session.soundplayer.play("message_received.ogg") + wx.CallAfter(self.reorder_buffer, buffer) + # Check if we have to read the message aloud + if buffer == self.get_current_buffer(): + rendered_message = renderers.render_message(message, self.session) + output.speak(rendered_message[0]) + + def set_online(self, notify=False): + try: + r = self.session.vk.client.account.setOnline() + except: + log.error("Error in setting online for the current user") + if notify: + self.window.notify("Socializer", "online now!") + + def set_offline(self): + try: + r = self.session.vk.client.account.setOffline() + except: + log.error("Error in setting offline status for the current user") + + def create_unread_messages(self): + if self.session.settings["chat"]["open_unread_conversations"] == False: + return + try: + log.debug("Getting possible unread messages.") + msgs = self.session.vk.client.messages.getConversations(count=200) + except VkApiError as ex: + if ex.code == 6: + log.exception("Something went wrong when getting messages. Waiting a second to retry") + for i in msgs["items"]: + call_threaded(self.chat_from_id, i["last_message"]["peer_id"], setfocus=False, unread=False) + time.sleep(0.6) + + def mark_as_read(self): + for i in self.buffers: + if hasattr(i, "reads") and len(i.reads) != 0: + response = self.session.vk.client.messages.markAsRead(peer_id=i.kwargs["peer_id"]) + i.clear_reads() + i.reads = [] + time.sleep(1) + + def get_audio_albums(self, user_id=None, create_buffers=True): + if self.session.settings["load_at_startup"]["audio_albums"] == False: + return + log.debug("Create audio albums...") + if self.session.settings["vk"]["use_alternative_tokens"]: + albums = self.session.vk.client_audio.get_albums(owner_id=user_id) + else: + albums = self.session.vk.client.audio.getPlaylists(owner_id=user_id) + albums = albums["items"] + self.session.audio_albums = albums + if create_buffers: + for i in albums: + wx.CallAfter(pub.sendMessage, "create_buffer", buffer_type="audioAlbum", buffer_title=_("Album: {0}").format(i["title"],), parent_tab="albums", loadable=True, kwargs=dict(parent=self.window.tb, name="{0}_audio_album".format(i["id"],), composefunc="render_audio", session=self.session, endpoint="get", parent_endpoint="audio", owner_id=user_id, album_id=i["id"])) + time.sleep(0.6) + + def get_video_albums(self, user_id=None, create_buffers=True): + if self.session.settings["load_at_startup"]["video_albums"] == False: + return + log.debug("Create video albums...") + albums = self.session.vk.client.video.getAlbums(owner_id=user_id) + self.session.video_albums = albums["items"] + if create_buffers: + for i in albums["items"]: + wx.CallAfter(pub.sendMessage, "create_buffer", buffer_type="videoAlbum", buffer_title=_("Album: {0}").format(i["title"],), parent_tab="video_albums", loadable=True, kwargs=dict(parent=self.window.tb, name="{0}_video_album".format(i["id"],), composefunc="render_video", session=self.session, endpoint="get", parent_endpoint="video", count=self.session.settings["buffers"]["count_for_video_buffers"], user_id=user_id, album_id=i["id"])) + time.sleep(0.15) + + def get_communities(self, user_id=None, create_buffers=True, force_action=False): + if self.session.settings["vk"]["invited_to_group"] == False: + self.session.settings["vk"]["invited_to_group"] = True + self.session.settings.write() + socializer_group = self.session.vk.client.groups.getById(group_ids="175825000")[0] + if socializer_group["is_member"] ==False: + d = commonMessages.join_group() + self.session.settings["vk"]["invited_to_group"] = True + self.session.settings.write() + if d == widgetUtils.YES: + result = self.session.vk.client.groups.join(group_id=socializer_group["id"]) + if result == 1: + commonMessages.group_joined() + else: + log.error("Invalid result when joining the Socializer's group: %d" % (result)) + if self.session.settings["load_at_startup"]["communities"] == False and force_action == False: + return + log.debug("Create community buffers...") + groups= self.session.vk.client.groups.get(user_id=user_id, extended=1, count=1000) + self.session.groups=groups["items"] + # Let's feed the local database cache with new groups coming from here. + data= dict(profiles=[], groups=self.session.groups) + self.session.process_usernames(data) + if create_buffers: + for i in self.session.groups: + wx.CallAfter(pub.sendMessage, "create_buffer", buffer_type="communityBuffer", buffer_title=i["name"], parent_tab="communities", loadable=True, get_items=True, kwargs=dict(parent=self.window.tb, name="{0}_community".format(i["id"],), composefunc="render_status", session=self.session, endpoint="get", parent_endpoint="wall", count=self.session.settings["buffers"]["count_for_wall_buffers"], owner_id=-1*i["id"])) + time.sleep(0.15) + + def create_audio_album(self, *args, **kwargs): + d = creation.audio_album() + if d.get_response() == widgetUtils.OK and d.get("title") != "": + response = self.session.vk.client.audio.createPlaylist(owner_id=self.session.user_id, title=d.get("title")) + if "id" not in response: + return + album_id = response["id"] + buffer = buffers.audioAlbum(parent=self.window.tb, name="{0}_audio_album".format(album_id,), composefunc="render_audio", session=self.session, endpoint="get", parent_endpoint="audio", full_list=True, count=self.session.settings["buffers"]["count_for_audio_buffers"], user_id=self.session.user_id, album_id=album_id) + buffer.can_get_items = False + # Translators: {0} will be replaced with an audio album's title. + name_ = _("Album: {0}").format(d.get("title"),) + self.buffers.append(buffer) + self.window.insert_buffer(buffer.tab, name_, self.window.search("albums")) + buffer.get_items() + self.get_audio_albums(user_id=self.session.user_id, create_buffers=False) + + def delete_audio_album(self, *args, **kwargs): + if len(self.session.audio_albums) == 0: + return commonMessages.no_audio_albums() + answer = selector.album(_("Select the album you want to delete"), self.session) + if answer.item == None: + return + response = commonMessages.delete_audio_album() + if response != widgetUtils.YES: return + removal = self.session.vk.client.audio.deletePlaylist(playlist_id=answer.item, owner_id=self.session.user_id) + if removal == 1: + buffer = self.search("{0}_audio_album".format(answer.item,)) + buff = self.window.search(buffer.name) + self.window.remove_buffer(buff) + self.buffers.remove(buffer) + del buffer + self.get_audio_albums(user_id=self.session.user_id, create_buffers=False) + + def create_video_album(self, *args, **kwargs): + d = creation.audio_album() + if d.get_response() == widgetUtils.OK and d.get("title") != "": + response = self.session.vk.client.video.addAlbum(title=d.get("title")) + if ("album_id" in response) == False: return + album_id = response["album_id"] + buffer = buffers.videoAlbum(parent=self.window.tb, name="{0}_video_album".format(album_id,), composefunc="render_video", session=self.session, endpoint="get", parent_endpoint="video", count=self.session.settings["buffers"]["count_for_video_buffers"], user_id=self.session.user_id, album_id=album_id) + buffer.can_get_items = False + # Translators: {0} will be replaced with a video album's title. + name_ = _("Album: {0}").format(d.get("title"),) + self.buffers.append(buffer) + self.window.insert_buffer(buffer.tab, name_, self.window.search("video_albums")) + buffer.get_items() + self.session.video_albums = self.session.vk.client.video.getAlbums(owner_id=self.session.user_id)["items"] + + def delete_video_album(self, *args, **kwargs): + if len(self.session.video_albums) == 0: + return commonMessages.no_video_albums() + answer = selector.album(_("Select the album you want to delete"), self.session, "video_albums") + if answer.item == None: + return + response = commonMessages.delete_audio_album() + if response != widgetUtils.YES: return + removal = self.session.vk.client.video.deleteAlbum(album_id=answer.item) + buffer = self.search("{0}_video_album".format(answer.item,)) + buff = self.window.search(buffer.name) + self.window.remove_buffer(buff) + self.buffers.remove(buffer) + del buffer + self.session.video_albums = self.session.vk.client.video.getAlbums(owner_id=self.session.user_id)["items"] + + def check_documentation(self, *args, **kwargs): + lang = localization.get("documentation") + os.chdir("documentation/%s" % (lang,)) + webbrowser.open("manual.html") + os.chdir("../../") + + def menu_play_pause(self, *args, **kwargs): + if player.player.stream != None: + return player.player.pause() + else: + b = self.get_current_buffer() + if hasattr(b, "play_all"): + b.play_all() + else: + self.search("me_audio").play_all() + + def menu_play_next(self, *args, **kwargs): + return player.player.play_next() +# b = self.get_current_buffer() +# if hasattr(b, "play_next"): +# b.play_next() +# else: +# self.search("me_audio").play_next() + + def menu_play_previous(self, *args, **kwargs): + return player.player.play_previous() +# b = self.get_current_buffer() +# if hasattr(b, "play_previous"): +# b.play_previous() +# else: +# self.search("me_audio").play_previous() + + def menu_play_all(self, *args, **kwargs): + b = self.get_current_buffer() + if hasattr(b, "play_all"): + b.play_all() + else: + self.search("me_audio").play_all() + + def menu_volume_down(self, *args, **kwargs): + player.player.volume = player.player.volume-5 + + def menu_volume_up(self, *args, **kwargs): + player.player.volume = player.player.volume+5 + + def menu_mute(self, *args, **kwargs): + player.player.volume = 0 + + def user_profile(self, person): + p = presenters.userProfilePresenter(session=self.session, user_id=person, view=views.userProfileDialog(), interactor=interactors.userProfileInteractor()) + + def view_my_profile(self, *args, **kwargs): + self.user_profile(self.session.user_id) + + def view_my_profile_in_browser(self, *args, **kwargs): + webbrowser.open_new_tab("https://vk.com/id{id}".format(id=self.session.user_id,)) + + def notify(self, message="", sound="", type="native"): + if type == "native": + self.window.notify(_("Socializer"), message) + else: + if sound != "": + self.session.soundplayer.play(sound) + if message != "": + output.speak(message) + + def handle_longpoll_read_timeout(self): + if hasattr(self, "longpoll"): + self.notify(message=_("Chat disconnected. Trying to connect in 60 seconds")) + time.sleep(60) + if hasattr(self, "longpoll"): + del self.longpoll + self.create_longpoll_thread(notify=True) + + def set_status(self, *args, **kwargs): + dlg = wx.TextEntryDialog(self.window, _("Write your status message"), _("Set status")) + if dlg.ShowModal() == widgetUtils.OK: + result = dlg.GetValue() + info = self.session.vk.client.account.saveProfileInfo(status=result) + commonMessages.updated_status() + dlg.Destroy() + + def on_report_error(self, *args, **kwargs): + r = issueReporter.reportBug() + + def reorder_buffer(self, buffer): + """ this puts the chat buffers at the top of the list when there are new incoming messages. + In order to do so, we search for the current buffer's tab, remove the page from the TreeCtrl (without destroying the associated tab) + and reinsert it as a new child of the chat buffer. + Lastly we ensure the user is focused in the same buffer than before.""" + buffer_window = self.window.search(buffer.name) + # If buffer window is already in the first position after chat, we should not do anything here because calculations for moving buffers are expensive. + if buffer_window == self.window.search("chats")+1: + return + # Gets buffer title so we don't have to generate it again in future. + buffer_title = self.window.get_buffer_text(buffer_window) + # Determine if the current buffer is the buffer receiving a new message. + if buffer == self.get_current_buffer(): + focused_buffer = True + else: + focused_buffer = False + # This call will not destroy the associated tab for the chat buffer, thus allowing us to readd it in other position. + self.window.remove_buffer_from_position(buffer_window) + self.window.insert_chat_buffer(buffer.tab, buffer_title, self.window.search("chats")+1) + # Let's manipulate focus so users will not notice the change in buffers. + if focused_buffer: + new_position = self.window.search(buffer.name) + self.window.change_buffer(new_position) + else: + new_position = self.window.search(self.get_current_buffer().name) + self.window.change_buffer(new_position) + + def load_community_posts(self, *args, **kwargs): + """ Load community posts. It just calls to the needed method in the community buffer.""" + current_buffer = self.get_current_buffer() + if current_buffer.name.endswith("_community"): + current_buffer.load_community() + + def load_community_audios(self, *args, **kwargs): + """ Load community audios if they are not loaded already.""" + current_buffer = self.get_current_buffer() + # Get group_info if the community buffer does not have it already, so future menus will be able to use it. + if not hasattr(current_buffer, "group_info"): + group_info = self.session.vk.client.groups.getById(group_ids=-1*current_buffer.kwargs["owner_id"], fields="counters")[0] + current_buffer.group_info = group_info + if "audios" not in current_buffer.group_info["counters"]: + commonMessages.community_no_items() + return + new_name = current_buffer.name+"_audios" + wx.CallAfter(pub.sendMessage, "create_buffer", buffer_type="audioBuffer", buffer_title=_("Audios"), parent_tab=current_buffer.tab.name, get_items=True, kwargs=dict(parent=self.window.tb, name=new_name, composefunc="render_audio", session=self.session, endpoint="get", parent_endpoint="audio", owner_id=current_buffer.kwargs["owner_id"])) + + def load_community_videos(self, *args, **kwargs): + """ Load community videos if they are not loaded already.""" + current_buffer = self.get_current_buffer() + # Get group_info if the community buffer does not have it already, so future menus will be able to use it. + if not hasattr(current_buffer, "group_info"): + group_info = self.session.vk.client.groups.getById(group_ids=-1*current_buffer.kwargs["owner_id"], fields="counters")[0] + current_buffer.group_info = group_info + if "videos" not in current_buffer.group_info["counters"]: + commonMessages.community_no_items() + return + new_name = current_buffer.name+"_videos" + wx.CallAfter(pub.sendMessage, "create_buffer", buffer_type="videoBuffer", buffer_title=_("Videos"), parent_tab=current_buffer.tab.name, get_items=True, kwargs=dict(parent=self.window.tb, name=new_name, composefunc="render_video", session=self.session, endpoint="get", parent_endpoint="video", count=self.session.settings["buffers"]["count_for_video_buffers"], owner_id=current_buffer.kwargs["owner_id"])) + + def load_community_topics(self, *args, **kwargs): + """ Load community topics.""" + current_buffer = self.get_current_buffer() + # Get group_info if the community buffer does not have it already, so future menus will be able to use it. + if not hasattr(current_buffer, "group_info"): + group_info = self.session.vk.client.groups.getById(group_ids=-1*current_buffer.kwargs["owner_id"], fields="counters")[0] + current_buffer.group_info = group_info + if "topics" not in current_buffer.group_info["counters"]: + commonMessages.community_no_items() + return + new_name = current_buffer.name+"_topics" + wx.CallAfter(pub.sendMessage, "create_buffer", buffer_type="topicBuffer", buffer_title=_("Topics"), parent_tab=current_buffer.tab.name, get_items=True, kwargs=dict(parent=self.window.tb, name=new_name, composefunc="render_topic", session=self.session, endpoint="getTopics", parent_endpoint="board", count=100, group_id=-1*current_buffer.kwargs["owner_id"], extended=1)) + + def load_community_documents(self, *args, **kwargs): + current_buffer = self.get_current_buffer() + # Get group_info if the community buffer does not have it already, so future menus will be able to use it. + if not hasattr(current_buffer, "group_info"): + group_info = self.session.vk.client.groups.getById(group_ids=-1*current_buffer.kwargs["owner_id"], fields="counters")[0] + current_buffer.group_info = group_info + if "docs" not in current_buffer.group_info["counters"]: + commonMessages.community_no_items() + return + new_name = current_buffer.name+"_documents" + wx.CallAfter(pub.sendMessage, "create_buffer", buffer_type="documentCommunityBuffer", buffer_title=_("Documents"), parent_tab=current_buffer.tab.name, get_items=True, kwargs=dict(parent=self.window.tb, name=new_name, composefunc="render_document", session=self.session, endpoint="get", parent_endpoint="docs", owner_id=current_buffer.kwargs["owner_id"])) + + def load_community_buffers(self, *args, **kwargs): + """ Load all community buffers regardless of the setting present in optional buffers tab of the preferences dialog.""" + call_threaded(self.get_communities, self.session.user_id, force_action=True) + + def unload_community_buffers(self, *args, **kwargs): + """ Delete all buffers belonging to groups.""" + communities = self.get_all_buffers("_community") + for buffer in communities: + buff = self.window.search(buffer.name) + self.window.remove_buffer(buff) + self.buffers.remove(buffer) + del self.session.groups diff --git a/src/presenters/player.py b/src/presenters/player.py index 6a19b99..462380c 100644 --- a/src/presenters/player.py +++ b/src/presenters/player.py @@ -21,234 +21,234 @@ player = None log = logging.getLogger("player") def setup(): - global player - if player == None: - player = audioPlayer() + global player + if player == None: + player = audioPlayer() class audioPlayer(object): - """ A media player which will play all passed URLS.""" + """ A media player which will play all passed URLS.""" - def __init__(self): - # control variable for checking if another file has been sent to the player before, - # thus avoiding double file playback and other oddities happening in sound_lib from time to time. - self.is_playing = False - # This will be the URLStream handler - self.stream = None - self.message = None - self.vol = config.app["sound"]["volume"] - # this variable is set to true when the URLPlayer is decoding something, thus it will block other calls to the play method. - self.is_working = False - # Playback queue. - self.queue = [] - # Index of the currently playing track. - self.playing_track = 0 - self.playing_all = False - self.worker = RepeatingTimer(5, self.player_function) - self.worker.start() - # Status of the player. - self.stopped = True - # Modify some default settings present in Bass so it will increase timeout connection, thus causing less "connection timed out" errors when playing. - bassconfig = BassConfig() - # Set timeout connection to 30 seconds. - bassconfig["net_timeout"] = 30000 - # subscribe all pubsub events. - pub.subscribe(self.play, "play") - pub.subscribe(self.play_message, "play-message") - pub.subscribe(self.play_all, "play-all") - pub.subscribe(self.pause, "pause") - pub.subscribe(self.stop, "stop") - pub.subscribe(self.play_next, "play-next") - pub.subscribe(self.play_previous, "play-previous") - pub.subscribe(self.seek, "seek") + def __init__(self): + # control variable for checking if another file has been sent to the player before, + # thus avoiding double file playback and other oddities happening in sound_lib from time to time. + self.is_playing = False + # This will be the URLStream handler + self.stream = None + self.message = None + self.vol = config.app["sound"]["volume"] + # this variable is set to true when the URLPlayer is decoding something, thus it will block other calls to the play method. + self.is_working = False + # Playback queue. + self.queue = [] + # Index of the currently playing track. + self.playing_track = 0 + self.playing_all = False + self.worker = RepeatingTimer(5, self.player_function) + self.worker.start() + # Status of the player. + self.stopped = True + # Modify some default settings present in Bass so it will increase timeout connection, thus causing less "connection timed out" errors when playing. + bassconfig = BassConfig() + # Set timeout connection to 30 seconds. + bassconfig["net_timeout"] = 30000 + # subscribe all pubsub events. + pub.subscribe(self.play, "play") + pub.subscribe(self.play_message, "play-message") + pub.subscribe(self.play_all, "play-all") + pub.subscribe(self.pause, "pause") + pub.subscribe(self.stop, "stop") + pub.subscribe(self.play_next, "play-next") + pub.subscribe(self.play_previous, "play-previous") + pub.subscribe(self.seek, "seek") - # Stopped has a special function here, hence the decorator - # when stopped will be set to True, it will send a pubsub event to inform other parts of the application about the status change. - # this is useful for changing labels between play and pause, and so on, in buttons. - @property - def stopped(self): - return self._stopped + # Stopped has a special function here, hence the decorator + # when stopped will be set to True, it will send a pubsub event to inform other parts of the application about the status change. + # this is useful for changing labels between play and pause, and so on, in buttons. + @property + def stopped(self): + return self._stopped - @stopped.setter - def stopped(self, value): - self._stopped = value - pub.sendMessage("playback-changed", stopped=value) + @stopped.setter + def stopped(self, value): + self._stopped = value + pub.sendMessage("playback-changed", stopped=value) - def play(self, object, set_info=True, fresh=False): - """ Play an URl Stream. - @object dict: typically an audio object as returned by VK, with a "url" component which must be a valid URL to a media file. - @set_info bool: If true, will set information about the currently playing audio in the application status bar. - @fresh bool: If True, will remove everything playing in the queue and start this file only. otherwise it will play the new file but not remove the current queue.""" - if "url" in object and object["url"] =="": - pub.sendMessage("notify", message=_("This file could not be played because it is not allowed in your country")) - return - if self.stream != None and (self.stream.is_playing == True or self.stream.is_stalled == True): - try: - self.stream.stop() - except BassError: - log.exception("error when stopping the file") - self.stream = None - self.stopped = True - if fresh == True: - self.queue = [] - # Make sure that there are no other sounds trying to be played. - if self.is_working == False: - self.is_working = True - url_ = utils.transform_audio_url(object["url"]) - try: - self.stream = URLStream(url=url_) - except: - log.error("Unable to play URL %s" % (url_)) - return - # Translators: {0} will be replaced with a song's title and {1} with the artist. - if set_info: - msg = _("Playing {0} by {1}").format(object["title"], object["artist"]) - pub.sendMessage("update-status-bar", status=msg) - self.stream.volume = self.vol/100.0 - self.stream.play() - self.stopped = False - self.is_working = False + def play(self, object, set_info=True, fresh=False): + """ Play an URl Stream. + @object dict: typically an audio object as returned by VK, with a "url" component which must be a valid URL to a media file. + @set_info bool: If true, will set information about the currently playing audio in the application status bar. + @fresh bool: If True, will remove everything playing in the queue and start this file only. otherwise it will play the new file but not remove the current queue.""" + if "url" in object and object["url"] =="": + pub.sendMessage("notify", message=_("This file could not be played because it is not allowed in your country")) + return + if self.stream != None and (self.stream.is_playing == True or self.stream.is_stalled == True): + try: + self.stream.stop() + except BassError: + log.exception("error when stopping the file") + self.stream = None + self.stopped = True + if fresh == True: + self.queue = [] + # Make sure that there are no other sounds trying to be played. + if self.is_working == False: + self.is_working = True + url_ = utils.transform_audio_url(object["url"]) + try: + self.stream = URLStream(url=url_) + except: + log.error("Unable to play URL %s" % (url_)) + return + # Translators: {0} will be replaced with a song's title and {1} with the artist. + if set_info: + msg = _("Playing {0} by {1}").format(object["title"], object["artist"]) + pub.sendMessage("update-status-bar", status=msg) + self.stream.volume = self.vol/100.0 + self.stream.play() + self.stopped = False + self.is_working = False - def play_message(self, message_url): - if self.message != None and (self.message.is_playing == True or self.message.is_stalled == True): - return self.stop_message() - output.speak(_("Playing...")) - url_ = utils.transform_audio_url(message_url) - try: - self.message = URLStream(url=url_) - except: - log.error("Unable to play URL %s" % (url_)) - return - self.message.volume = self.vol/100.0 - self.message.play() - volume_percent = self.volume*0.25 - volume_step = self.volume*0.15 - while self.stream.volume*100 > volume_percent: - self.stream.volume = self.stream.volume-(volume_step/100) - time.sleep(0.1) + def play_message(self, message_url): + if self.message != None and (self.message.is_playing == True or self.message.is_stalled == True): + return self.stop_message() + output.speak(_("Playing...")) + url_ = utils.transform_audio_url(message_url) + try: + self.message = URLStream(url=url_) + except: + log.error("Unable to play URL %s" % (url_)) + return + self.message.volume = self.vol/100.0 + self.message.play() + volume_percent = self.volume*0.25 + volume_step = self.volume*0.15 + while self.stream.volume*100 > volume_percent: + self.stream.volume = self.stream.volume-(volume_step/100) + time.sleep(0.1) - def stop(self): - """ Stop audio playback. """ - if self.stream != None and self.stream.is_playing == True: - self.stream.stop() - self.stopped = True - self.queue = [] + def stop(self): + """ Stop audio playback. """ + if self.stream != None and self.stream.is_playing == True: + self.stream.stop() + self.stopped = True + self.queue = [] - def stop_message(self): - if hasattr(self, "message") and self.message != None and self.message.is_playing == True: - self.message.stop() - volume_step = self.volume*0.15 - while self.stream.volume*100 < self.volume: - self.stream.volume = self.stream.volume+(volume_step/100) - time.sleep(0.1) - self.message = None + def stop_message(self): + if hasattr(self, "message") and self.message != None and self.message.is_playing == True: + self.message.stop() + volume_step = self.volume*0.15 + while self.stream.volume*100 < self.volume: + self.stream.volume = self.stream.volume+(volume_step/100) + time.sleep(0.1) + self.message = None - def pause(self): - """ pause the current playback, without destroying the queue or the current stream. If the stream is already paused this function will resume the playback. """ - if self.stream != None: - if self.stream.is_playing == True: - self.stream.pause() - self.stopped = True - else: - try: - self.stream.play() - self.stopped = False - except BassError: - pass - if self.playing_all == False and len(self.queue) > 0: - self.playing_all = True + def pause(self): + """ pause the current playback, without destroying the queue or the current stream. If the stream is already paused this function will resume the playback. """ + if self.stream != None: + if self.stream.is_playing == True: + self.stream.pause() + self.stopped = True + else: + try: + self.stream.play() + self.stopped = False + except BassError: + pass + if self.playing_all == False and len(self.queue) > 0: + self.playing_all = True - @property - def volume(self): - return self.vol + @property + def volume(self): + return self.vol - @volume.setter - def volume(self, vol): - if vol <= 100 and vol >= 0: - self.vol = vol - elif vol < 0: - self.vol = 0 - elif vol > 100: - self.vol = 100 - if self.stream != None: - if self.message != None and self.message.is_playing: - self.stream.volume = (self.vol*0.25)/100.0 - self.message.volume = self.vol/100.0 - else: - self.stream.volume = self.vol/100.0 + @volume.setter + def volume(self, vol): + if vol <= 100 and vol >= 0: + self.vol = vol + elif vol < 0: + self.vol = 0 + elif vol > 100: + self.vol = 100 + if self.stream != None: + if self.message != None and self.message.is_playing: + self.stream.volume = (self.vol*0.25)/100.0 + self.message.volume = self.vol/100.0 + else: + self.stream.volume = self.vol/100.0 - def play_all(self, list_of_songs, shuffle=False): - """ Play all passed songs and adds all of those to the queue. - @list_of_songs list: A list of audio objects returned by VK. - @shuffle bool: If True, the files will be played randomly.""" - if self.is_working: - return - self.playing_track = 0 - self.stop() - # Skip all country restricted tracks as they are not playable here. - self.queue = [i for i in list_of_songs if i["url"] != ""] - if shuffle: - random.shuffle(self.queue) - call_threaded(self.play, self.queue[self.playing_track]) - self.playing_all = True + def play_all(self, list_of_songs, shuffle=False): + """ Play all passed songs and adds all of those to the queue. + @list_of_songs list: A list of audio objects returned by VK. + @shuffle bool: If True, the files will be played randomly.""" + if self.is_working: + return + self.playing_track = 0 + self.stop() + # Skip all country restricted tracks as they are not playable here. + self.queue = [i for i in list_of_songs if i["url"] != ""] + if shuffle: + random.shuffle(self.queue) + call_threaded(self.play, self.queue[self.playing_track]) + self.playing_all = True - def player_function(self): - """ Check if the stream has reached the end of the file so it will play the next song. """ - if self.message != None and self.message.is_playing == False and len(self.message) == self.message.position: - volume_step = self.volume*0.15 - while self.stream != None and self.stream.volume*100 < self.volume: - self.stream.volume = self.stream.volume+(volume_step/100) - time.sleep(0.1) - if self.stream != None and self.stream.is_playing == False and self.stopped == False and len(self.stream) == self.stream.position: - if self.playing_track >= len(self.queue): - self.stopped = True - self.playing_all = False - return - elif self.playing_all == False: - self.stopped = True - return - elif self.playing_track < len(self.queue): - self.playing_track += 1 - self.play(self.queue[self.playing_track]) + def player_function(self): + """ Check if the stream has reached the end of the file so it will play the next song. """ + if self.message != None and self.message.is_playing == False and len(self.message) == self.message.position: + volume_step = self.volume*0.15 + while self.stream != None and self.stream.volume*100 < self.volume: + self.stream.volume = self.stream.volume+(volume_step/100) + time.sleep(0.1) + if self.stream != None and self.stream.is_playing == False and self.stopped == False and len(self.stream) == self.stream.position: + if self.playing_track >= len(self.queue): + self.stopped = True + self.playing_all = False + return + elif self.playing_all == False: + self.stopped = True + return + elif self.playing_track < len(self.queue): + self.playing_track += 1 + self.play(self.queue[self.playing_track]) - def play_next(self): - """ Play the next song in the queue. """ - if len(self.queue) == 0: - return - if self.is_working: - return - if self.playing_track < len(self.queue)-1: - self.playing_track += 1 - else: - self.playing_track = 0 - call_threaded(self.play, self.queue[self.playing_track]) + def play_next(self): + """ Play the next song in the queue. """ + if len(self.queue) == 0: + return + if self.is_working: + return + if self.playing_track < len(self.queue)-1: + self.playing_track += 1 + else: + self.playing_track = 0 + call_threaded(self.play, self.queue[self.playing_track]) - def play_previous(self): - """ Play the previous song in the queue. """ - if len(self.queue) == 0: - return - if self.is_working: - return - if self.playing_track <= 0: - self.playing_track = len(self.queue)-1 - else: - self.playing_track -= 1 - call_threaded(self.play, self.queue[self.playing_track]) + def play_previous(self): + """ Play the previous song in the queue. """ + if len(self.queue) == 0: + return + if self.is_working: + return + if self.playing_track <= 0: + self.playing_track = len(self.queue)-1 + else: + self.playing_track -= 1 + call_threaded(self.play, self.queue[self.playing_track]) - def seek(self, ms=0): - if self.check_is_playing(): - if self.stream.position < 500000 and ms < 0: - self.stream.position = 0 - else: - try: - self.stream.position = self.stream.position+ms - except: - pass + def seek(self, ms=0): + if self.check_is_playing(): + if self.stream.position < 500000 and ms < 0: + self.stream.position = 0 + else: + try: + self.stream.position = self.stream.position+ms + except: + pass - def check_is_playing(self): - """ check if the player is already playing a stream. """ - if self.stream == None: - return False - if self.stream != None and self.stream.is_playing == False and self.stream.is_stalled == False: - return False - else: - return True \ No newline at end of file + def check_is_playing(self): + """ check if the player is already playing a stream. """ + if self.stream == None: + return False + if self.stream != None and self.stream.is_playing == False and self.stream.is_stalled == False: + return False + else: + return True diff --git a/src/presenters/profiles.py b/src/presenters/profiles.py index 45674e2..49d40f2 100644 --- a/src/presenters/profiles.py +++ b/src/presenters/profiles.py @@ -15,154 +15,154 @@ log = logging.getLogger("controller.profiles") class userProfilePresenter(base.basePresenter): - def __init__(self, session, user_id, view, interactor): - """ Default constructor: - @session vk.session: The main session object, capable of calling VK methods. - @user_id integer: User ID to retrieve information of. - At the current time, only users (and not communities) are supported. - """ - super(userProfilePresenter, self).__init__(view=view, interactor=interactor, modulename="user_profile") - # self.person will hold a reference to the user object when retrieved from VK. - self.person = None - self.session = session - self.user_id = user_id - # Get information in a threaded way here. - # Note: We do not handle any race condition here because due to the presenter only sending pubsub messages, - # Nothing happens if the pubsub send messages to the interactor after the latter has been destroyed. - # Pubsub messages are just skipped if there are no listeners for them. - call_threaded(self.get_basic_information) - self.run() + def __init__(self, session, user_id, view, interactor): + """ Default constructor: + @session vk.session: The main session object, capable of calling VK methods. + @user_id integer: User ID to retrieve information of. + At the current time, only users (and not communities) are supported. + """ + super(userProfilePresenter, self).__init__(view=view, interactor=interactor, modulename="user_profile") + # self.person will hold a reference to the user object when retrieved from VK. + self.person = None + self.session = session + self.user_id = user_id + # Get information in a threaded way here. + # Note: We do not handle any race condition here because due to the presenter only sending pubsub messages, + # Nothing happens if the pubsub send messages to the interactor after the latter has been destroyed. + # Pubsub messages are just skipped if there are no listeners for them. + call_threaded(self.get_basic_information) + self.run() - def get_basic_information(self): - """ Gets and inserts basic user information. - See https://vk.com/dev/users.get""" - # List of fields (information) to retrieve. For a list of fields available for user objects, - # see https://vk.com/dev/fields - fields = "first_name, last_name, bdate, city, country, home_town, photo_200_orig, online, site, status, last_seen, occupation, relation, relatives, personal, connections, activities, interests, music, movies, tv, books, games, about, quotes, can_write_private_message, contacts, has_mobile, universities, education, schools" - # ToDo: this method supports multiple user IDS, I'm not sure if this may be of any help for profile viewer. - person = self.session.vk.client.users.get(user_ids=self.user_id, fields=fields) - # If VK does not return anything it is very likely we have found a community. - if len(person) == 0: - return output.speak(_("Information for groups is not supported, yet.")) - person = person[0] - # toDo: remove this print when I will be done with creation of profile viewer logic. -# print(person) - # From this part we will format data from VK so users will see it in the GUI control. - # Format full name. - n = "{0} {1}".format(person["first_name"], person["last_name"]) - # format phones - if person.get("mobile_phone") != None and person.get("mobile_phone") != "": - self.send_message("enable_control", tab="main_info", control="mobile_phone") - self.send_message("set", tab="main_info", control="mobile_phone", value=person["mobile_phone"]) - if person.get("home_phone") != None and person.get("home_phone") != "": - self.send_message("enable_control", tab="main_info", control="home_phone") - self.send_message("set", tab="main_info", control="home_phone", value=person["home_phone"]) - # Format birthdate. - if "bdate" in person and person["bdate"] != "": - self.send_message("enable_control", tab="main_info", control="bdate") - # VK can display dd.mm or dd.mm.yyyy birthdates. So let's compare the string lenght to handle both cases accordingly. - if len(person["bdate"]) <= 5: # dd.mm - d = arrow.get(person["bdate"], "D.M") - self.send_message("set", tab="main_info", control="bdate", value=d.format(_("MMMM D"), locale=languageHandler.curLang[:2])) - else: # mm.dd.yyyy - d = arrow.get(person["bdate"], "D.M.YYYY") - # Calculate user's years. - now = arrow.get() - timedelta = now-d - years = int(timedelta.days/365) - date = d.format(_("MMMM D, YYYY"), locale=languageHandler.curLang[:2]) - msg = _("{date} ({age} years)").format(date=date, age=years) - self.send_message("set", tab="main_info", control="bdate", value=msg) - # Format current city and home town - city = "" - if "home_town" in person and person["home_town"] != "": - home_town = person["home_town"] - self.send_message("enable_control", tab="main_info", control="home_town") - self.send_message("set", tab="main_info", control="home_town", value=home_town) - if "city" in person and len(person["city"]) > 0: - city = person["city"]["title"] - if "country" in person and person["country"] != "": - if city != "": - city = city+", {0}".format(person["country"]["title"]) - else: - city = person["country"]["title"] - self.send_message("enable_control", tab="main_info", control="city") - self.send_message("set", tab="main_info", control="city", value=city) - self.send_message("set", tab="main_info", control="name", value=n) - # Format title - user = self.session.get_user(person["id"]) - self.send_message("set_title", value=_("{user1_nom}'s profile").format(**user)) - # Format website (or websites, if there are multiple of them). - if "site" in person and person["site"] != "": - self.send_message("enable_control", tab="main_info", control="website") - self.send_message("set", tab="main_info", control="website", value=person["site"]) - self.send_message("enable_control", tab="main_info", control="go_site") - # Format status message. - if "status" in person and person["status"] != "": - self.send_message("enable_control", tab="main_info", control="status") - self.send_message("set", tab="main_info", control="status", value=person["status"]) - # Format occupation. - # toDo: Research in this field is needed. Sometimes it returns university information even if users have active work places. - if "occupation" in person and person["occupation"] != None: - if person["occupation"]["type"] == "work": c1 = _("Work ") - elif person["occupation"]["type"] == "school": c1 = _("Student ") - elif person["occupation"]["type"] == "university": c1 = _("Student ") - if "name" in person["occupation"] and person["occupation"]["name"] != "": - c2 = _("In {0}").format(person["occupation"]["name"],) - else: - c2 = "" - self.send_message("enable_control", tab="main_info", control="occupation") - self.send_message("set", tab="main_info", control="occupation", value=c1+c2) - # format relationship status. - # ToDo: When dating someone, the button associated to the information should point to the profile of the user. - if "relation" in person and person["relation"] != 0: - if person["relation"] == 1: - r = _("Single") - elif person["relation"] == 2: - if "relation_partner" in person: - r = _("Dating with {0} {1}").format(person["relation_partner"]["first_name"], person["relation_partner"]["last_name"]) - else: - r = _("Dating") - elif person["relation"] == 3: - r = _("Engaged with {0} {1}").format(person["relation_partner"]["first_name"], person["relation_partner"]["last_name"]) - elif person["relation"] == 4: - if "relation_partner" in person: - r = _("Married to {0} {1}").format(person["relation_partner"]["first_name"], person["relation_partner"]["last_name"]) - else: - r = _("Married") - elif person["relation"] == 5: - r = _("It's complicated") - elif person["relation"] == 6: - r = _("Actively searching") - elif person["relation"] == 7: - r = _("In love") - self.send_message("enable_control", tab="main_info", control="relation") - self.send_message("set_label", tab="main_info", control="relation", value=_("Relationship: ")+r) - # format last seen. - if "last_seen" in person and person["last_seen"] != False: - original_date = arrow.get(person["last_seen"]["time"]) - # Translators: This is the date of last seen - last_seen = _("{0}").format(original_date.humanize(locale=languageHandler.curLang[:2]),) - self.send_message("enable_control", tab="main_info", control="last_seen") - self.send_message("set", tab="main_info", control="last_seen", value=last_seen) - self.person = person - # Adds photo to the dialog. - # ToDo: Need to ask if this has a visible effect in the dialog. - if "photo_200_orig" in person: - img = requests.get(person["photo_200_orig"]) - self.send_message("load_image", image=requests.get(person["photo_200_orig"])) - output.speak(_("Profile loaded")) + def get_basic_information(self): + """ Gets and inserts basic user information. + See https://vk.com/dev/users.get""" + # List of fields (information) to retrieve. For a list of fields available for user objects, + # see https://vk.com/dev/fields + fields = "first_name, last_name, bdate, city, country, home_town, photo_200_orig, online, site, status, last_seen, occupation, relation, relatives, personal, connections, activities, interests, music, movies, tv, books, games, about, quotes, can_write_private_message, contacts, has_mobile, universities, education, schools" + # ToDo: this method supports multiple user IDS, I'm not sure if this may be of any help for profile viewer. + person = self.session.vk.client.users.get(user_ids=self.user_id, fields=fields) + # If VK does not return anything it is very likely we have found a community. + if len(person) == 0: + return output.speak(_("Information for groups is not supported, yet.")) + person = person[0] + # toDo: remove this print when I will be done with creation of profile viewer logic. +# print(person) + # From this part we will format data from VK so users will see it in the GUI control. + # Format full name. + n = "{0} {1}".format(person["first_name"], person["last_name"]) + # format phones + if person.get("mobile_phone") != None and person.get("mobile_phone") != "": + self.send_message("enable_control", tab="main_info", control="mobile_phone") + self.send_message("set", tab="main_info", control="mobile_phone", value=person["mobile_phone"]) + if person.get("home_phone") != None and person.get("home_phone") != "": + self.send_message("enable_control", tab="main_info", control="home_phone") + self.send_message("set", tab="main_info", control="home_phone", value=person["home_phone"]) + # Format birthdate. + if "bdate" in person and person["bdate"] != "": + self.send_message("enable_control", tab="main_info", control="bdate") + # VK can display dd.mm or dd.mm.yyyy birthdates. So let's compare the string lenght to handle both cases accordingly. + if len(person["bdate"]) <= 5: # dd.mm + d = arrow.get(person["bdate"], "D.M") + self.send_message("set", tab="main_info", control="bdate", value=d.format(_("MMMM D"), locale=languageHandler.curLang[:2])) + else: # mm.dd.yyyy + d = arrow.get(person["bdate"], "D.M.YYYY") + # Calculate user's years. + now = arrow.get() + timedelta = now-d + years = int(timedelta.days/365) + date = d.format(_("MMMM D, YYYY"), locale=languageHandler.curLang[:2]) + msg = _("{date} ({age} years)").format(date=date, age=years) + self.send_message("set", tab="main_info", control="bdate", value=msg) + # Format current city and home town + city = "" + if "home_town" in person and person["home_town"] != "": + home_town = person["home_town"] + self.send_message("enable_control", tab="main_info", control="home_town") + self.send_message("set", tab="main_info", control="home_town", value=home_town) + if "city" in person and len(person["city"]) > 0: + city = person["city"]["title"] + if "country" in person and person["country"] != "": + if city != "": + city = city+", {0}".format(person["country"]["title"]) + else: + city = person["country"]["title"] + self.send_message("enable_control", tab="main_info", control="city") + self.send_message("set", tab="main_info", control="city", value=city) + self.send_message("set", tab="main_info", control="name", value=n) + # Format title + user = self.session.get_user(person["id"]) + self.send_message("set_title", value=_("{user1_nom}'s profile").format(**user)) + # Format website (or websites, if there are multiple of them). + if "site" in person and person["site"] != "": + self.send_message("enable_control", tab="main_info", control="website") + self.send_message("set", tab="main_info", control="website", value=person["site"]) + self.send_message("enable_control", tab="main_info", control="go_site") + # Format status message. + if "status" in person and person["status"] != "": + self.send_message("enable_control", tab="main_info", control="status") + self.send_message("set", tab="main_info", control="status", value=person["status"]) + # Format occupation. + # toDo: Research in this field is needed. Sometimes it returns university information even if users have active work places. + if "occupation" in person and person["occupation"] != None: + if person["occupation"]["type"] == "work": c1 = _("Work ") + elif person["occupation"]["type"] == "school": c1 = _("Student ") + elif person["occupation"]["type"] == "university": c1 = _("Student ") + if "name" in person["occupation"] and person["occupation"]["name"] != "": + c2 = _("In {0}").format(person["occupation"]["name"],) + else: + c2 = "" + self.send_message("enable_control", tab="main_info", control="occupation") + self.send_message("set", tab="main_info", control="occupation", value=c1+c2) + # format relationship status. + # ToDo: When dating someone, the button associated to the information should point to the profile of the user. + if "relation" in person and person["relation"] != 0: + if person["relation"] == 1: + r = _("Single") + elif person["relation"] == 2: + if "relation_partner" in person: + r = _("Dating with {0} {1}").format(person["relation_partner"]["first_name"], person["relation_partner"]["last_name"]) + else: + r = _("Dating") + elif person["relation"] == 3: + r = _("Engaged with {0} {1}").format(person["relation_partner"]["first_name"], person["relation_partner"]["last_name"]) + elif person["relation"] == 4: + if "relation_partner" in person: + r = _("Married to {0} {1}").format(person["relation_partner"]["first_name"], person["relation_partner"]["last_name"]) + else: + r = _("Married") + elif person["relation"] == 5: + r = _("It's complicated") + elif person["relation"] == 6: + r = _("Actively searching") + elif person["relation"] == 7: + r = _("In love") + self.send_message("enable_control", tab="main_info", control="relation") + self.send_message("set_label", tab="main_info", control="relation", value=_("Relationship: ")+r) + # format last seen. + if "last_seen" in person and person["last_seen"] != False: + original_date = arrow.get(person["last_seen"]["time"]) + # Translators: This is the date of last seen + last_seen = _("{0}").format(original_date.humanize(locale=languageHandler.curLang[:2]),) + self.send_message("enable_control", tab="main_info", control="last_seen") + self.send_message("set", tab="main_info", control="last_seen", value=last_seen) + self.person = person + # Adds photo to the dialog. + # ToDo: Need to ask if this has a visible effect in the dialog. + if "photo_200_orig" in person: + img = requests.get(person["photo_200_orig"]) + self.send_message("load_image", image=requests.get(person["photo_200_orig"])) + output.speak(_("Profile loaded")) - def get_urls(self, *args, **kwargs): - """ Allows to visit an user's website. """ - text = self.person["site"] - # Let's search for URLS with a regexp, as there are users with multiple websites in their profiles. - urls = utils.find_urls_in_text(text) - if len(urls) == 0: - output.speak(_("No URL addresses were detected.")) - return - return urls + def get_urls(self, *args, **kwargs): + """ Allows to visit an user's website. """ + text = self.person["site"] + # Let's search for URLS with a regexp, as there are users with multiple websites in their profiles. + urls = utils.find_urls_in_text(text) + if len(urls) == 0: + output.speak(_("No URL addresses were detected.")) + return + return urls - def visit_url(self, url): - output.speak(_("Opening URL...")) - webbrowser.open_new_tab(url) \ No newline at end of file + def visit_url(self, url): + output.speak(_("Opening URL...")) + webbrowser.open_new_tab(url) diff --git a/src/run_tests.py b/src/run_tests.py index 8873c4b..0df04ad 100644 --- a/src/run_tests.py +++ b/src/run_tests.py @@ -19,4 +19,4 @@ for t in testmodules: # else, just load all the test cases from the module. suite.addTest(unittest.defaultTestLoader.loadTestsFromName(t)) -unittest.TextTestRunner(verbosity=2).run(suite) \ No newline at end of file +unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/src/sessionmanager/config_utils.py b/src/sessionmanager/config_utils.py index a64cf22..09233fc 100644 --- a/src/sessionmanager/config_utils.py +++ b/src/sessionmanager/config_utils.py @@ -5,42 +5,42 @@ from validate import Validator, VdtValueError import os class ConfigurationResetException(Exception): - pass + pass class Configuration (UserDict): - def __init__ (self, file=None, spec=None, *args, **kwargs): - self.file = file - self.spec = spec - self.validator = Validator() - self.setup_config(file=file, spec=spec) - self.validated = self.config.validate(self.validator, copy=True) - if self.validated: - self.write() - UserDict.__init__(self, self.config) + def __init__ (self, file=None, spec=None, *args, **kwargs): + self.file = file + self.spec = spec + self.validator = Validator() + self.setup_config(file=file, spec=spec) + self.validated = self.config.validate(self.validator, copy=True) + if self.validated: + self.write() + UserDict.__init__(self, self.config) - def setup_config (self, file, spec): - spec = ConfigObj(spec, list_values=False, encoding="utf-8") - try: - self.config = ConfigObj(infile=file, configspec=spec, create_empty=True, stringify=True, encoding="utf-8") - except ParseError: - os.remove(file) - self.config = ConfigObj(infile=file, configspec=spec, create_empty=True, stringify=True) - raise ConfigurationResetException + def setup_config (self, file, spec): + spec = ConfigObj(spec, list_values=False, encoding="utf-8") + try: + self.config = ConfigObj(infile=file, configspec=spec, create_empty=True, stringify=True, encoding="utf-8") + except ParseError: + os.remove(file) + self.config = ConfigObj(infile=file, configspec=spec, create_empty=True, stringify=True) + raise ConfigurationResetException - def __getitem__ (self, *args, **kwargs): - return dict(self.config).__getitem__(*args, **kwargs) + def __getitem__ (self, *args, **kwargs): + return dict(self.config).__getitem__(*args, **kwargs) - def __setitem__ (self, *args, **kwargs): - self.config.__setitem__(*args, **kwargs) - UserDict.__setitem__(self, *args, **kwargs) + def __setitem__ (self, *args, **kwargs): + self.config.__setitem__(*args, **kwargs) + UserDict.__setitem__(self, *args, **kwargs) - def write (self): - if hasattr(self.config, 'write'): - self.config.write() + def write (self): + if hasattr(self.config, 'write'): + self.config.write() class SessionConfiguration (Configuration): - def setup_config (self, file, spec): - #No infile required. - spec = ConfigObj(spec, list_values=False) - self.config = ConfigObj(configspec=spec, stringify=True) + def setup_config (self, file, spec): + #No infile required. + spec = ConfigObj(spec, list_values=False) + self.config = ConfigObj(configspec=spec, stringify=True) diff --git a/src/sessionmanager/renderers.py b/src/sessionmanager/renderers.py index 98d400d..6af2bec 100644 --- a/src/sessionmanager/renderers.py +++ b/src/sessionmanager/renderers.py @@ -12,296 +12,296 @@ log = logging.getLogger(__file__) ### Some util functions def extract_attachment(attachment): - """ Adds information about attachment files in posts. It only adds the text, I mean, no attachment file is added here. - This will produce a result like: - 'website: http://url.com'. - 'photo: A forest'.""" - msg = "" - if attachment["type"] == "link": - msg = "{0}: {1}".format(attachment["link"]["title"], attachment["link"]["url"]) - elif attachment["type"] == "photo": - msg = attachment["photo"]["text"] - if msg == "": - return _("photo with no description available") - elif attachment["type"] == "video": - msg = _("video: {0}").format(attachment["video"]["title"],) - return msg + """ Adds information about attachment files in posts. It only adds the text, I mean, no attachment file is added here. + This will produce a result like: + 'website: http://url.com'. + 'photo: A forest'.""" + msg = "" + if attachment["type"] == "link": + msg = "{0}: {1}".format(attachment["link"]["title"], attachment["link"]["url"]) + elif attachment["type"] == "photo": + msg = attachment["photo"]["text"] + if msg == "": + return _("photo with no description available") + elif attachment["type"] == "video": + msg = _("video: {0}").format(attachment["video"]["title"],) + return msg def short_text(status): - """ This shorts the text to 140 characters for displaying it in the list control of buffers.""" - message = "" - # copy_story indicates that the post is a shared repost. - if "copy_history" in status: - txt = status["copy_history"][0]["text"] - else: - txt = status["text"] - if len(txt) < 140: - message = clean_text(txt) - else: - message = clean_text(txt[:139]) - return message + """ This shorts the text to 140 characters for displaying it in the list control of buffers.""" + message = "" + # copy_story indicates that the post is a shared repost. + if "copy_history" in status: + txt = status["copy_history"][0]["text"] + else: + txt = status["text"] + if len(txt) < 140: + message = clean_text(txt) + else: + message = clean_text(txt[:139]) + return message def clean_audio(audio): - """ Remove unavailable songs due to different reasons. This is used to clean the audio list when people adds audios and need to be displayed in the buffer.""" - for i in audio["items"][:]: - if type(i) == bool: - audio["items"].remove(i) - audio["count"] = audio["count"] -1 - return audio + """ Remove unavailable songs due to different reasons. This is used to clean the audio list when people adds audios and need to be displayed in the buffer.""" + for i in audio["items"][:]: + if type(i) == bool: + audio["items"].remove(i) + audio["count"] = audio["count"] -1 + return audio def add_attachment(attachment): - msg = "" - tpe = "" - if attachment["type"] == "link": - msg = "{0}: {1}".format(attachment["link"]["title"], attachment["link"]["url"]) - tpe = _("Link") - elif attachment["type"] == "photo": - tpe = _("Photo") - msg = attachment["photo"]["text"] - if msg == "": - msg = _("no description available") - elif attachment["type"] == "video": - msg = "{0}".format(attachment["video"]["title"],) - tpe = _("Video") - elif attachment["type"] == "audio": - msg = "{0}".format(" ".join(render_audio(attachment["audio"]))) - tpe = _("Audio") - elif attachment["type"] == "doc": - msg = "{0}".format(attachment["doc"]["title"]) - tpe = _("{0} file").format(attachment["doc"]["ext"]) - elif attachment["type"] == "audio_message": - msg = "{0}".format(" ".join(render_audio_message(attachment["audio_message"]))) - tpe = _("Voice message") - elif attachment["type"] == "poll": - tpe = _("Poll") - msg = attachment["poll"]["question"] - elif attachment["type"] == "wall": - tpe = _("Post") - user = attachment["wall"]["from"]["name"] - if len(attachment["wall"]["text"]) > 140: - text = attachment["wall"]["text"][:145]+"..." - else: - text = attachment["wall"]["text"] - msg = _("{user}: {post}").format(user=user, post=text) - elif attachment["type"] == "article": - tpe = _("Article") - msg = "{author}: {article}".format(author=attachment["article"]["owner_name"], article=attachment["article"]["title"]) - else: - print(attachment) - return [tpe, msg] + msg = "" + tpe = "" + if attachment["type"] == "link": + msg = "{0}: {1}".format(attachment["link"]["title"], attachment["link"]["url"]) + tpe = _("Link") + elif attachment["type"] == "photo": + tpe = _("Photo") + msg = attachment["photo"]["text"] + if msg == "": + msg = _("no description available") + elif attachment["type"] == "video": + msg = "{0}".format(attachment["video"]["title"],) + tpe = _("Video") + elif attachment["type"] == "audio": + msg = "{0}".format(" ".join(render_audio(attachment["audio"]))) + tpe = _("Audio") + elif attachment["type"] == "doc": + msg = "{0}".format(attachment["doc"]["title"]) + tpe = _("{0} file").format(attachment["doc"]["ext"]) + elif attachment["type"] == "audio_message": + msg = "{0}".format(" ".join(render_audio_message(attachment["audio_message"]))) + tpe = _("Voice message") + elif attachment["type"] == "poll": + tpe = _("Poll") + msg = attachment["poll"]["question"] + elif attachment["type"] == "wall": + tpe = _("Post") + user = attachment["wall"]["from"]["name"] + if len(attachment["wall"]["text"]) > 140: + text = attachment["wall"]["text"][:145]+"..." + else: + text = attachment["wall"]["text"] + msg = _("{user}: {post}").format(user=user, post=text) + elif attachment["type"] == "article": + tpe = _("Article") + msg = "{author}: {article}".format(author=attachment["article"]["owner_name"], article=attachment["article"]["title"]) + else: + print(attachment) + return [tpe, msg] ### Render functions def render_person(status, session): - """ Render users in people buffers such as everything related to friendships or buffers created with only people. - Example result: ["John Doe", "An hour ago"] - Reference: https://vk.com/dev/fields""" - # In case the user decided to not show his/her last seen information we must provide a default. - # ToDo: Shall we indicate this with a message? - online_status = "" - if "last_seen" in status: - original_date = arrow.get(status["last_seen"]["time"]) - now = arrow.now() - original_date.to(now.tzinfo) - diffdate = now-original_date - if diffdate.days == 0 and diffdate.seconds <= 360: - online_status = _("Online") - else: - # Translators: This is the date of last seen - online_status = _("Last seen {0}").format(original_date.humanize(locale=languageHandler.curLang[:2]),) - # Account suspended or deleted. - elif ("last_seen" in status) == False and "deactivated" in status: - online_status = _("Account deactivated") - return ["{0} {1}".format(status["first_name"], status["last_name"]), online_status] + """ Render users in people buffers such as everything related to friendships or buffers created with only people. + Example result: ["John Doe", "An hour ago"] + Reference: https://vk.com/dev/fields""" + # In case the user decided to not show his/her last seen information we must provide a default. + # ToDo: Shall we indicate this with a message? + online_status = "" + if "last_seen" in status: + original_date = arrow.get(status["last_seen"]["time"]) + now = arrow.now() + original_date.to(now.tzinfo) + diffdate = now-original_date + if diffdate.days == 0 and diffdate.seconds <= 360: + online_status = _("Online") + else: + # Translators: This is the date of last seen + online_status = _("Last seen {0}").format(original_date.humanize(locale=languageHandler.curLang[:2]),) + # Account suspended or deleted. + elif ("last_seen" in status) == False and "deactivated" in status: + online_status = _("Account deactivated") + return ["{0} {1}".format(status["first_name"], status["last_name"]), online_status] def render_newsfeed_item(status, session): - """ This me☻thod is used to render an item of the news feed. - References: - https://vk.com/dev/newsfeed.get - https://vk.com/dev/post_source - https://vk.com/dev/post - """ - user = session.get_user(status["source_id"], key="user1") - # See if this is a post or repost. - if "copy_history" in status: - # Get the second user (whose post is been shared). - user2 = session.get_user(status["copy_history"][0]["owner_id"], key="user2") - # Add contents of poster to the new dict, it will create both user1_nom and user2_nom. - user2.update(user) - user = dict(user1_nom=_("{user1_nom} has shared the {user2_nom}'s post").format(**user2)) - message = "" - original_date = arrow.get(status["date"]) - created_at = original_date.humanize(locale=languageHandler.curLang[:2]) - # handle status updates. - if status["type"] == "post": - message += short_text(status) - if "attachment" in status and len(status["attachment"]) > 0: - message += extract_attachment(status["attachment"]) - # If there is no message after adding text, it's because a pphoto with no description has been found. - # so let's manually add the "no description" tag here. - if message == "": - message = "no description available" - # Handle audio rendering. - elif status["type"] == "audio" and "audio" in status: - # removes deleted audios. - status["audio"] = clean_audio(status["audio"]) - if status["audio"]["count"] == 1: - data = dict(audio_file=", ".join(render_audio(status["audio"]["items"][0], session))) - data.update(user) - message = _("{user1_nom} has added an audio: {audio_file}").format(**data) - else: - prem = "" - for i in range(0, status["audio"]["count"]): - composed_audio = render_audio(status["audio"]["items"][i], session) - prem += "{0} - {1}, ".format(composed_audio[0], composed_audio[1]) - data = dict(audio_files=prem, total_audio_files=status["audio"]["count"]) - data.update(user) - message = _("{user1_nom} has added {total_audio_files} audios: {audio_files}").format(**data) - # Handle audio playlists - elif status["type"] == "audio_playlist": - if status["audio_playlist"]["count"] == 1: - data = dict(audio_album=status["audio_playlist"]["items"][0]["title"], audio_album_description=status["audio_playlist"]["items"][0]["description"]) - data.update(user) - message = _("{user1_nom} has added an audio album: {audio_album}, {audio_album_description}").format(**data) - else: - prestring = "" - for i in range(0, status["audio_playlist"]["count"]): - prestring += "{0} - {1}, ".format(status["audio_playlist"]["items"][i]["title"], status["audio_playlist"]["items"][i]["description"]) - data = dict(audio_albums=prestring, total_audio_albums=status["audio_playlist"]["count"]) - data.update(user) - message = _("{user1_nom} has added {total_audio_albums} audio albums: {audio_albums}").format(**data) - # handle new friends for people in the news buffer. - elif status["type"] == "friend": - msg_users = "" - if "friends" in status: - for i in status["friends"]["items"]: - msg_users = msg_users + "{0}, ".format(session.get_user(i["user_id"])["user1_nom"]) - else: - print(list(status.keys())) - data = dict(friends=msg_users) - data.update(user) - message = _("{user1_nom} added friends: {friends}").format(**data) - elif status["type"] == "video": - if status["video"]["count"] == 1: - data = dict(video=", ".join(render_video(status["video"]["items"][0], session))) - data.update(user) - message = _("{user1_nom} has added a video: {video}").format(**data) - else: - prem = "" - for i in range(0, status["video"]["count"]): - composed_video = render_video(status["video"]["items"][i], session) - prem += "{0} - {1}, ".format(composed_video[0], composed_video[1]) - data = dict(videos=prem, total_videos=status["video"]["count"]) - data.update(user) - message = _("{user1_nom} has added {total_videos} videos: {videos}").format(**data) - else: - if status["type"] != "post": print(status) - return [user["user1_nom"], message, created_at] + """ This me☻thod is used to render an item of the news feed. + References: + https://vk.com/dev/newsfeed.get + https://vk.com/dev/post_source + https://vk.com/dev/post + """ + user = session.get_user(status["source_id"], key="user1") + # See if this is a post or repost. + if "copy_history" in status: + # Get the second user (whose post is been shared). + user2 = session.get_user(status["copy_history"][0]["owner_id"], key="user2") + # Add contents of poster to the new dict, it will create both user1_nom and user2_nom. + user2.update(user) + user = dict(user1_nom=_("{user1_nom} has shared the {user2_nom}'s post").format(**user2)) + message = "" + original_date = arrow.get(status["date"]) + created_at = original_date.humanize(locale=languageHandler.curLang[:2]) + # handle status updates. + if status["type"] == "post": + message += short_text(status) + if "attachment" in status and len(status["attachment"]) > 0: + message += extract_attachment(status["attachment"]) + # If there is no message after adding text, it's because a pphoto with no description has been found. + # so let's manually add the "no description" tag here. + if message == "": + message = "no description available" + # Handle audio rendering. + elif status["type"] == "audio" and "audio" in status: + # removes deleted audios. + status["audio"] = clean_audio(status["audio"]) + if status["audio"]["count"] == 1: + data = dict(audio_file=", ".join(render_audio(status["audio"]["items"][0], session))) + data.update(user) + message = _("{user1_nom} has added an audio: {audio_file}").format(**data) + else: + prem = "" + for i in range(0, status["audio"]["count"]): + composed_audio = render_audio(status["audio"]["items"][i], session) + prem += "{0} - {1}, ".format(composed_audio[0], composed_audio[1]) + data = dict(audio_files=prem, total_audio_files=status["audio"]["count"]) + data.update(user) + message = _("{user1_nom} has added {total_audio_files} audios: {audio_files}").format(**data) + # Handle audio playlists + elif status["type"] == "audio_playlist": + if status["audio_playlist"]["count"] == 1: + data = dict(audio_album=status["audio_playlist"]["items"][0]["title"], audio_album_description=status["audio_playlist"]["items"][0]["description"]) + data.update(user) + message = _("{user1_nom} has added an audio album: {audio_album}, {audio_album_description}").format(**data) + else: + prestring = "" + for i in range(0, status["audio_playlist"]["count"]): + prestring += "{0} - {1}, ".format(status["audio_playlist"]["items"][i]["title"], status["audio_playlist"]["items"][i]["description"]) + data = dict(audio_albums=prestring, total_audio_albums=status["audio_playlist"]["count"]) + data.update(user) + message = _("{user1_nom} has added {total_audio_albums} audio albums: {audio_albums}").format(**data) + # handle new friends for people in the news buffer. + elif status["type"] == "friend": + msg_users = "" + if "friends" in status: + for i in status["friends"]["items"]: + msg_users = msg_users + "{0}, ".format(session.get_user(i["user_id"])["user1_nom"]) + else: + print(list(status.keys())) + data = dict(friends=msg_users) + data.update(user) + message = _("{user1_nom} added friends: {friends}").format(**data) + elif status["type"] == "video": + if status["video"]["count"] == 1: + data = dict(video=", ".join(render_video(status["video"]["items"][0], session))) + data.update(user) + message = _("{user1_nom} has added a video: {video}").format(**data) + else: + prem = "" + for i in range(0, status["video"]["count"]): + composed_video = render_video(status["video"]["items"][i], session) + prem += "{0} - {1}, ".format(composed_video[0], composed_video[1]) + data = dict(videos=prem, total_videos=status["video"]["count"]) + data.update(user) + message = _("{user1_nom} has added {total_videos} videos: {videos}").format(**data) + else: + if status["type"] != "post": print(status) + return [user["user1_nom"], message, created_at] def render_message(message, session): - """ Render a message posted in a private conversation. - Reference: https://vk.com/dev/message""" - user = session.get_user(message["from_id"], key="user1") - original_date = arrow.get(message["date"]) - now = arrow.now() - original_date = original_date.to(now.tzinfo) - # Format the date here differently depending in if this is the same day for both dates or not. - if original_date.day == now.day: - created_at = original_date.format(_("H:mm."), locale=languageHandler.curLang[:2]) - else: - created_at = original_date.format(_("H:mm. dddd, MMMM D, YYYY"), locale=languageHandler.curLang[:2]) - # No idea why some messages send "text" instead "body" - if "body" in message: - body = message["body"] - else: - body = message["text"] - data = dict(body=body, created_at=created_at) - data.update(user) - return ["{user1_nom}, {body} {created_at}".format(**data)] + """ Render a message posted in a private conversation. + Reference: https://vk.com/dev/message""" + user = session.get_user(message["from_id"], key="user1") + original_date = arrow.get(message["date"]) + now = arrow.now() + original_date = original_date.to(now.tzinfo) + # Format the date here differently depending in if this is the same day for both dates or not. + if original_date.day == now.day: + created_at = original_date.format(_("H:mm."), locale=languageHandler.curLang[:2]) + else: + created_at = original_date.format(_("H:mm. dddd, MMMM D, YYYY"), locale=languageHandler.curLang[:2]) + # No idea why some messages send "text" instead "body" + if "body" in message: + body = message["body"] + else: + body = message["text"] + data = dict(body=body, created_at=created_at) + data.update(user) + return ["{user1_nom}, {body} {created_at}".format(**data)] def render_status(status, session): - """ Render a wall post (shown in user's wall, not in newsfeed). - Reference: https://vk.com/dev/post""" - user = session.get_user(status["from_id"], key="user1") - if "copy_history" in status: - user2 = session.get_user(status["copy_history"][0]["owner_id"], key="user2") - user2.update(user) - user = dict(user1_nom=_("{user1_nom} has shared the {user2_nom}'s post").format(**user2)) - message = "" - original_date = arrow.get(status["date"]) - created_at = original_date.humanize(locale=languageHandler.curLang[:2]) - if "copy_owner_id" in status: - user2 = session.get_user(status["copy_owner_id"], key="user2") - user2.update(user) - user = _("{user1_nom} has shared the {user2_nom}'s post").format(**user2) - if status["post_type"] == "post" or status["post_type"] == "copy": - message += short_text(status) - if "attachment" in status and len(status["attachment"]) > 0: - message += extract_attachment(status["attachment"]) - if message == "": - message = "no description available" - return [user["user1_nom"], message, created_at] + """ Render a wall post (shown in user's wall, not in newsfeed). + Reference: https://vk.com/dev/post""" + user = session.get_user(status["from_id"], key="user1") + if "copy_history" in status: + user2 = session.get_user(status["copy_history"][0]["owner_id"], key="user2") + user2.update(user) + user = dict(user1_nom=_("{user1_nom} has shared the {user2_nom}'s post").format(**user2)) + message = "" + original_date = arrow.get(status["date"]) + created_at = original_date.humanize(locale=languageHandler.curLang[:2]) + if "copy_owner_id" in status: + user2 = session.get_user(status["copy_owner_id"], key="user2") + user2.update(user) + user = _("{user1_nom} has shared the {user2_nom}'s post").format(**user2) + if status["post_type"] == "post" or status["post_type"] == "copy": + message += short_text(status) + if "attachment" in status and len(status["attachment"]) > 0: + message += extract_attachment(status["attachment"]) + if message == "": + message = "no description available" + return [user["user1_nom"], message, created_at] def render_audio(audio, session=None): - """ Render audio files added to VK. - Example result: - ["Song title", "Artist", "03:15"] - reference: https://vk.com/dev/audio_object""" - if audio == False: return [_("Audio removed from library"), "", ""] - return [audio["title"], audio["artist"], seconds_to_string(audio["duration"])] + """ Render audio files added to VK. + Example result: + ["Song title", "Artist", "03:15"] + reference: https://vk.com/dev/audio_object""" + if audio == False: return [_("Audio removed from library"), "", ""] + return [audio["title"], audio["artist"], seconds_to_string(audio["duration"])] def render_video(video, session=None): - """ Render a video file from VK. - Example result: - ["Video title", "Video description", "01:30:28"] - Reference: https://vk.com/dev/video_object""" - if video == False: - return [_("Video not available"), "", ""] - return [video["title"], video["description"], seconds_to_string(video["duration"])] + """ Render a video file from VK. + Example result: + ["Video title", "Video description", "01:30:28"] + Reference: https://vk.com/dev/video_object""" + if video == False: + return [_("Video not available"), "", ""] + return [video["title"], video["description"], seconds_to_string(video["duration"])] def render_audio_message(audio_message, session=None): - """ Render a voice message from VK - Example result: - ["Voice message", "01:30:28"]""" - if audio_message == False: - return [_("Voice message not available"), "", ""] - return [seconds_to_string(audio_message["duration"])] + """ Render a voice message from VK + Example result: + ["Voice message", "01:30:28"]""" + if audio_message == False: + return [_("Voice message not available"), "", ""] + return [seconds_to_string(audio_message["duration"])] def render_topic(topic, session): - """ Render topics for a community. - Reference: https://vk.com/dev/objects/topic""" - user = session.get_user(topic["created_by"]) - title = topic["title"] - comments = topic["comments"] - last_commenter = session.get_user(topic["updated_by"]) - last_update = arrow.get(topic["updated"]).humanize(locale=languageHandler.curLang[:2]) - last_commenter.update(date=last_update) - lastupdate = _("Last post by {user1_nom} {date}").format(**last_commenter) - return [user["user1_nom"], title, str(comments), lastupdate] + """ Render topics for a community. + Reference: https://vk.com/dev/objects/topic""" + user = session.get_user(topic["created_by"]) + title = topic["title"] + comments = topic["comments"] + last_commenter = session.get_user(topic["updated_by"]) + last_update = arrow.get(topic["updated"]).humanize(locale=languageHandler.curLang[:2]) + last_commenter.update(date=last_update) + lastupdate = _("Last post by {user1_nom} {date}").format(**last_commenter) + return [user["user1_nom"], title, str(comments), lastupdate] def render_document(document, session): - doc_types = {1: _("Text document"), 2: _("Archive"), 3: _("Gif"), 4: _("Image"), 5: _("Audio"), 6: _("Video"), 7: _("Ebook"), 8: _("Unknown document")} - user = session.get_user(document["owner_id"]) - title = document["title"] - size = convert_bytes(document["size"]) - date = arrow.get(document["date"]).humanize(locale=languageHandler.curLang[:2]) - doc_type = doc_types[document["type"]] - return [user["user1_nom"], title, doc_type, size, date] + doc_types = {1: _("Text document"), 2: _("Archive"), 3: _("Gif"), 4: _("Image"), 5: _("Audio"), 6: _("Video"), 7: _("Ebook"), 8: _("Unknown document")} + user = session.get_user(document["owner_id"]) + title = document["title"] + size = convert_bytes(document["size"]) + date = arrow.get(document["date"]).humanize(locale=languageHandler.curLang[:2]) + doc_type = doc_types[document["type"]] + return [user["user1_nom"], title, doc_type, size, date] def render_notification(notification, session): - notification.pop("hide_buttons") - print(notification["icon_type"]) -# print(notification["header"]) - print(notification) - date = arrow.get(notification["date"]).humanize(locale=languageHandler.curLang[:2]) - msg = notification["header"] -# msg = notification["header"] -# if notification["type"] == "follow": -# if len(notification["feedback"]) == 1: -# user = session.get_user(notification["feedback"][0]) -# msg = _("{user1_nom} subscribed to your account").format(**user) -# else: -# users = ["{first_name} {last_name},".format(first_name=user["first_name"], last_name=user["last_name"]) for user in notification["feedback"]] -# msg = " ".join(users) -# print(msg) - return [msg, date] \ No newline at end of file + notification.pop("hide_buttons") + print(notification["icon_type"]) +# print(notification["header"]) + print(notification) + date = arrow.get(notification["date"]).humanize(locale=languageHandler.curLang[:2]) + msg = notification["header"] +# msg = notification["header"] +# if notification["type"] == "follow": +# if len(notification["feedback"]) == 1: +# user = session.get_user(notification["feedback"][0]) +# msg = _("{user1_nom} subscribed to your account").format(**user) +# else: +# users = ["{first_name} {last_name},".format(first_name=user["first_name"], last_name=user["last_name"]) for user in notification["feedback"]] +# msg = " ".join(users) +# print(msg) + return [msg, date] diff --git a/src/sessionmanager/session.py b/src/sessionmanager/session.py index 5d319d0..2141e02 100644 --- a/src/sessionmanager/session.py +++ b/src/sessionmanager/session.py @@ -29,370 +29,370 @@ identifiers = ["aid", "gid", "uid", "pid", "id", "post_id", "nid", "date"] post_types = dict(audio="audio", friend="friends", video="files", post="post_type", audio_playlist="audio_playlist") def find_item(list, item): - """ Find an item in a list by taking an identifier. - @list list: A list of dict objects. - @ item dict: A dictionary containing at least an identifier. - """ - # determine the kind of identifier that we are using - global identifiers - identifier = None - for i in identifiers: - if i in item: - identifier = i - break - if identifier == None: - # if there are objects that can't be processed by lack of identifier, let's print keys for finding one. - log.exception("Can't find an identifier for the following object: %r" % (item,)) - return False - for i in list: - if identifier in i and i[identifier] == item[identifier]: - return True - return False + """ Find an item in a list by taking an identifier. + @list list: A list of dict objects. + @ item dict: A dictionary containing at least an identifier. + """ + # determine the kind of identifier that we are using + global identifiers + identifier = None + for i in identifiers: + if i in item: + identifier = i + break + if identifier == None: + # if there are objects that can't be processed by lack of identifier, let's print keys for finding one. + log.exception("Can't find an identifier for the following object: %r" % (item,)) + return False + for i in list: + if identifier in i and i[identifier] == item[identifier]: + return True + return False class vkSession(object): - """ The only session available in socializer. Manages everything related to a model in an MVC app: calls to VK, sound handling, settings and a cache database.""" + """ The only session available in socializer. Manages everything related to a model in an MVC app: calls to VK, sound handling, settings and a cache database.""" - def order_buffer(self, name, data, show_nextpage): - """ Put new items on the local cache database. - @name str: The name for the buffer stored in the dictionary. - @data list: A list with items and some information about cursors. - returns the number of items that have been added in this execution""" - global post_types - # When this method is called by friends.getOnlyne, it gives only friend IDS so we need to retrieve full objects from VK. - # ToDo: It would be nice to investigate whether reusing some existing objects would be a good idea, whenever possible. - if name == "online_friends": - newdata = self.vk.client.users.get(user_ids=",".join([str(z) for z in data]), fields="last_seen") - data = newdata - first_addition = False - num = 0 - if (name in self.db) == False: - self.db[name] = {} - self.db[name]["items"] = [] - first_addition = True - # Handles chat messages case, as the buffer is inverted - if name.endswith("_messages") and show_nextpage == True: - show_nextpage = False - for i in data: - if "type" in i and (i["type"] == "wall_photo" or i["type"] == "photo_tag" or i["type"] == "photo" or i["type"] == False or i["type"] == True): - log.debug("Skipping unsupported item... %r" % (i,)) - continue - # for some reason, VK sends post data if the post has been deleted already. - # Example of this behaviour is when you upload an audio and inmediately delete the audio, VK still sends the post stating that you uploaded an audio file, - # But without the audio data, making socializer to render an empty post. - # Here we check if the post contains data of the type it advertises. - if i.get("type") != None and isinstance(i["type"], str) and post_types.get(i["type"]) not in i: - log.error("Detected invalid or unsupported post. Skipping...") - log.error(i) - continue - if find_item(self.db[name]["items"], i) == False: -# if i not in self.db[name]["items"]: - if first_addition == True or show_nextpage == True: - if self.settings["general"]["reverse_timelines"] == False: self.db[name]["items"].append(i) - else: self.db[name]["items"].insert(0, i) - else: - if self.settings["general"]["reverse_timelines"] == False: self.db[name]["items"].insert(0, i) - else: self.db[name]["items"].append(i) - num = num+1 - log.debug("There are %d items in the %s buffer" % (len(self.db[name]["items"]), name)) - return num + def order_buffer(self, name, data, show_nextpage): + """ Put new items on the local cache database. + @name str: The name for the buffer stored in the dictionary. + @data list: A list with items and some information about cursors. + returns the number of items that have been added in this execution""" + global post_types + # When this method is called by friends.getOnlyne, it gives only friend IDS so we need to retrieve full objects from VK. + # ToDo: It would be nice to investigate whether reusing some existing objects would be a good idea, whenever possible. + if name == "online_friends": + newdata = self.vk.client.users.get(user_ids=",".join([str(z) for z in data]), fields="last_seen") + data = newdata + first_addition = False + num = 0 + if (name in self.db) == False: + self.db[name] = {} + self.db[name]["items"] = [] + first_addition = True + # Handles chat messages case, as the buffer is inverted + if name.endswith("_messages") and show_nextpage == True: + show_nextpage = False + for i in data: + if "type" in i and (i["type"] == "wall_photo" or i["type"] == "photo_tag" or i["type"] == "photo" or i["type"] == False or i["type"] == True): + log.debug("Skipping unsupported item... %r" % (i,)) + continue + # for some reason, VK sends post data if the post has been deleted already. + # Example of this behaviour is when you upload an audio and inmediately delete the audio, VK still sends the post stating that you uploaded an audio file, + # But without the audio data, making socializer to render an empty post. + # Here we check if the post contains data of the type it advertises. + if i.get("type") != None and isinstance(i["type"], str) and post_types.get(i["type"]) not in i: + log.error("Detected invalid or unsupported post. Skipping...") + log.error(i) + continue + if find_item(self.db[name]["items"], i) == False: +# if i not in self.db[name]["items"]: + if first_addition == True or show_nextpage == True: + if self.settings["general"]["reverse_timelines"] == False: self.db[name]["items"].append(i) + else: self.db[name]["items"].insert(0, i) + else: + if self.settings["general"]["reverse_timelines"] == False: self.db[name]["items"].insert(0, i) + else: self.db[name]["items"].append(i) + num = num+1 + log.debug("There are %d items in the %s buffer" % (len(self.db[name]["items"]), name)) + return num - def __init__(self, session_id): - self.session_id = session_id - self.logged = False - self.settings = None - self.vk = vkSessionHandler.vkObject() - self.db = {} - self.db["users"] = {} - self.db["groups"] = {} - self.db["group_info"] = {} + def __init__(self, session_id): + self.session_id = session_id + self.logged = False + self.settings = None + self.vk = vkSessionHandler.vkObject() + self.db = {} + self.db["users"] = {} + self.db["groups"] = {} + self.db["group_info"] = {} - @property - def is_logged(self): - return self.logged + @property + def is_logged(self): + return self.logged - def get_configuration(self, nosound=False): + def get_configuration(self, nosound=False): - """ Gets settings for a session.""" - - file_ = "%s/session.conf" % (self.session_id,) + """ Gets settings for a session.""" + + file_ = "%s/session.conf" % (self.session_id,) # try: - log.debug("Creating config file %s" % (file_,)) - self.settings = Configuration(os.path.join(paths.config_path(), file_), os.path.join(paths.app_path(), "session.defaults")) - if nosound == False: - self.soundplayer = sound.soundSystem(config.app["sound"]) - pub.subscribe(self.play_sound, "play-sound") - pub.subscribe(self.post, "post") + log.debug("Creating config file %s" % (file_,)) + self.settings = Configuration(os.path.join(paths.config_path(), file_), os.path.join(paths.app_path(), "session.defaults")) + if nosound == False: + self.soundplayer = sound.soundSystem(config.app["sound"]) + pub.subscribe(self.play_sound, "play-sound") + pub.subscribe(self.post, "post") # except: # log.exception("The session configuration has failed.") - def play_sound(self, sound): - self.soundplayer.play(sound) + def play_sound(self, sound): + self.soundplayer.play(sound) - def login(self): - """ Logging in VK.com. This is basically the first method interacting with VK. """ - # If user is already logged in, we should skip this method. - if self.logged == True: - return - try: - config_filename = os.path.join(paths.config_path(), self.session_id, "vkconfig.json") - self.vk.login(self.settings["vk"]["user"], self.settings["vk"]["password"], token=self.settings["vk"]["token"], alt_token=self.settings["vk"]["use_alternative_tokens"], filename=config_filename) - self.settings["vk"]["token"] = self.vk.session_object.token["access_token"] - self.settings.write() - self.logged = True - self.get_my_data() - except VkApiError as error: - print(error) - if error.code == 5: # this means invalid access token. - self.settings["vk"]["user"] = "" - self.settings["vk"]["password"] = "" - self.settings["vk"]["token"] = "" - self.settings.write() - pub.sendMessage("authorisation-failed") - else: # print out error so we we will handle it in future versions. - log.exception("Fatal error when authenticating the application.") - log.exception(error.code) - log.exception(error.message) - except (ProxyError, ConnectionError): - pub.sendMessage("connection_error") + def login(self): + """ Logging in VK.com. This is basically the first method interacting with VK. """ + # If user is already logged in, we should skip this method. + if self.logged == True: + return + try: + config_filename = os.path.join(paths.config_path(), self.session_id, "vkconfig.json") + self.vk.login(self.settings["vk"]["user"], self.settings["vk"]["password"], token=self.settings["vk"]["token"], alt_token=self.settings["vk"]["use_alternative_tokens"], filename=config_filename) + self.settings["vk"]["token"] = self.vk.session_object.token["access_token"] + self.settings.write() + self.logged = True + self.get_my_data() + except VkApiError as error: + print(error) + if error.code == 5: # this means invalid access token. + self.settings["vk"]["user"] = "" + self.settings["vk"]["password"] = "" + self.settings["vk"]["token"] = "" + self.settings.write() + pub.sendMessage("authorisation-failed") + else: # print out error so we we will handle it in future versions. + log.exception("Fatal error when authenticating the application.") + log.exception(error.code) + log.exception(error.message) + except (ProxyError, ConnectionError): + pub.sendMessage("connection_error") - def post_wall_status(self, message, *args, **kwargs): - """ Sends a post to an user, group or community wall.""" - log.debug("Making a post to the user's wall with the following params: %r" % (kwargs,)) - response = self.vk.client.wall.post(message=message, *args, **kwargs) + def post_wall_status(self, message, *args, **kwargs): + """ Sends a post to an user, group or community wall.""" + log.debug("Making a post to the user's wall with the following params: %r" % (kwargs,)) + response = self.vk.client.wall.post(message=message, *args, **kwargs) - def get_newsfeed(self, name="newsfeed", show_nextpage=False, endpoint="", *args, **kwargs): - log.debug("Updating news feed...") - if show_nextpage == True and "cursor" in self.db[name]: - log.debug("user has requested previous items") - kwargs["start_from"] = self.db[name]["cursor"] - log.debug("Params for sending to vk: %r" % (kwargs,)) - data = getattr(self.vk.client.newsfeed, "get")(*args, **kwargs) - if data != None: - self.process_usernames(data) - num = self.order_buffer(name, data["items"], show_nextpage) - log.debug("Keys of the returned data for debug purposes: %r" % (list(data.keys()),)) - if "next_from" in data: - self.db[name]["cursor"] = data["next_from"] - log.debug("Next cursor saved for data: {cursor}".format(cursor=data["next_from"])) - return num + def get_newsfeed(self, name="newsfeed", show_nextpage=False, endpoint="", *args, **kwargs): + log.debug("Updating news feed...") + if show_nextpage == True and "cursor" in self.db[name]: + log.debug("user has requested previous items") + kwargs["start_from"] = self.db[name]["cursor"] + log.debug("Params for sending to vk: %r" % (kwargs,)) + data = getattr(self.vk.client.newsfeed, "get")(*args, **kwargs) + if data != None: + self.process_usernames(data) + num = self.order_buffer(name, data["items"], show_nextpage) + log.debug("Keys of the returned data for debug purposes: %r" % (list(data.keys()),)) + if "next_from" in data: + self.db[name]["cursor"] = data["next_from"] + log.debug("Next cursor saved for data: {cursor}".format(cursor=data["next_from"])) + return num - def get_page(self, name="", show_nextpage=False, endpoint="", *args, **kwargs): - data = None - if "audio" in endpoint and self.settings["vk"]["use_alternative_tokens"]: - log.info("Using alternative audio methods.") - c = self.vk.client_audio - else: - c = self.vk.client - formatted_endpoint = "" - if "parent_endpoint" in kwargs: - p = kwargs["parent_endpoint"] - formatted_endpoint = kwargs["parent_endpoint"] - if "audio" in p and self.settings["vk"]["use_alternative_tokens"]: - log.info("Using alternative audio methods.") - c = self.vk.client_audio - kwargs.pop("parent_endpoint") - try: - p = getattr(c, p) - except AttributeError: - p = c - if name in self.db and "offset" in self.db[name] and show_nextpage == True: - kwargs.update(offset=self.db[name]["offset"]) - else: - kwargs.update(offset=0) - formatted_endpoint = "{formatted_endpoint}.{new_path}".format(formatted_endpoint=formatted_endpoint, new_path=endpoint) - offset_deprecated = ["notifications.get"] - if formatted_endpoint in offset_deprecated: - kwargs.update(offset=None) - log.debug("Calling endpoint %s with params %r" % (formatted_endpoint, kwargs,)) - data = getattr(p, endpoint)(*args, **kwargs) - if data != None: - if "count" not in kwargs: - kwargs["count"] = 100 - # Let's handle a little exception when dealing with conversation buffers. - # the first results of the query should be reversed before being sent to order_buffer. - if type(data) == dict and "items" in data and endpoint == "getHistory" and kwargs["offset"] == 0: - data["items"].reverse() - if type(data) == dict: - num = self.order_buffer(name, data["items"], show_nextpage) - if formatted_endpoint not in offset_deprecated: - self.db[name]["offset"] = kwargs["offset"]+kwargs["count"] - if len(data["items"]) > 0 and "first_name" in data["items"][0]: - data2 = {"profiles": [], "groups": []} - for i in data["items"]: - data2["profiles"].append(i) - self.process_usernames(data2) - if "profiles" in data and "groups" in data: - self.process_usernames(data) - else: - num = self.order_buffer(name, data, show_nextpage) - self.db[name]["offset"] = kwargs["offset"]+kwargs["count"] - return num + def get_page(self, name="", show_nextpage=False, endpoint="", *args, **kwargs): + data = None + if "audio" in endpoint and self.settings["vk"]["use_alternative_tokens"]: + log.info("Using alternative audio methods.") + c = self.vk.client_audio + else: + c = self.vk.client + formatted_endpoint = "" + if "parent_endpoint" in kwargs: + p = kwargs["parent_endpoint"] + formatted_endpoint = kwargs["parent_endpoint"] + if "audio" in p and self.settings["vk"]["use_alternative_tokens"]: + log.info("Using alternative audio methods.") + c = self.vk.client_audio + kwargs.pop("parent_endpoint") + try: + p = getattr(c, p) + except AttributeError: + p = c + if name in self.db and "offset" in self.db[name] and show_nextpage == True: + kwargs.update(offset=self.db[name]["offset"]) + else: + kwargs.update(offset=0) + formatted_endpoint = "{formatted_endpoint}.{new_path}".format(formatted_endpoint=formatted_endpoint, new_path=endpoint) + offset_deprecated = ["notifications.get"] + if formatted_endpoint in offset_deprecated: + kwargs.update(offset=None) + log.debug("Calling endpoint %s with params %r" % (formatted_endpoint, kwargs,)) + data = getattr(p, endpoint)(*args, **kwargs) + if data != None: + if "count" not in kwargs: + kwargs["count"] = 100 + # Let's handle a little exception when dealing with conversation buffers. + # the first results of the query should be reversed before being sent to order_buffer. + if type(data) == dict and "items" in data and endpoint == "getHistory" and kwargs["offset"] == 0: + data["items"].reverse() + if type(data) == dict: + num = self.order_buffer(name, data["items"], show_nextpage) + if formatted_endpoint not in offset_deprecated: + self.db[name]["offset"] = kwargs["offset"]+kwargs["count"] + if len(data["items"]) > 0 and "first_name" in data["items"][0]: + data2 = {"profiles": [], "groups": []} + for i in data["items"]: + data2["profiles"].append(i) + self.process_usernames(data2) + if "profiles" in data and "groups" in data: + self.process_usernames(data) + else: + num = self.order_buffer(name, data, show_nextpage) + self.db[name]["offset"] = kwargs["offset"]+kwargs["count"] + return num - def get_messages(self, name="", *args, **kwargs): - data = self.vk.client.messages.getHistory(*args, **kwargs) - data["items"].reverse() - if data != None: - num = self.order_buffer(name, data["items"], False) - return num + def get_messages(self, name="", *args, **kwargs): + data = self.vk.client.messages.getHistory(*args, **kwargs) + data["items"].reverse() + if data != None: + num = self.order_buffer(name, data["items"], False) + return num - def get_users(self, user_ids=None, group_ids=None): - log.debug("Getting user information from the VK servers") - if user_ids != None: - u = self.vk.client.users.get(user_ids=user_ids, fields="uid, first_name, last_name") - for i in u: - self.db["users"][i["id"]] = dict(nom="{0} {1}".format(i["first_name"], i["last_name"])) - if group_ids != None: - g = self.vk.client.groups.getById(group_ids=group_ids, fields="name") - for i in g: - self.db["groups"][i["id"]] = dict(nom=i["name"], gen=i["name"], dat=i["name"], acc=i["name"], ins=i["name"], abl=i["name"]) + def get_users(self, user_ids=None, group_ids=None): + log.debug("Getting user information from the VK servers") + if user_ids != None: + u = self.vk.client.users.get(user_ids=user_ids, fields="uid, first_name, last_name") + for i in u: + self.db["users"][i["id"]] = dict(nom="{0} {1}".format(i["first_name"], i["last_name"])) + if group_ids != None: + g = self.vk.client.groups.getById(group_ids=group_ids, fields="name") + for i in g: + self.db["groups"][i["id"]] = dict(nom=i["name"], gen=i["name"], dat=i["name"], acc=i["name"], ins=i["name"], abl=i["name"]) - def get_user(self, user_id, key="user1"): - if user_id > 0: - if user_id in self.db["users"]: - user_data = {} - user_fields = "nom, gen, ins, dat, abl, acc".split(", ") - for i in user_fields: - k = "{key}_{case}".format(key=key, case=i) - v = "{first_name} {last_name}".format(first_name=self.db["users"][user_id]["first_name_"+i], last_name=self.db["users"][user_id]["last_name_"+i]) - user_data[k] = v - return user_data - # if User_id is not present in db. - else: - user = dict(id=user_id) - self.process_usernames(data=dict(profiles=[user], groups=[])) - return self.get_user(user_id) - else: - if abs(user_id) in self.db["groups"]: - user_data = {} - user_fields = "nom, gen, ins, dat, abl, acc".split(", ") - for i in user_fields: - k = "{key}_{case}".format(key=key, case=i) - v = self.db["groups"][abs(user_id)][i] - user_data[k] = v - else: - group = self.vk.client.groups.getById(group_ids=-1*user_id)[0] - self.process_usernames(data=dict(profiles=[], groups=[group])) - return self.get_user(user_id=user_id, key=key) - return user_data + def get_user(self, user_id, key="user1"): + if user_id > 0: + if user_id in self.db["users"]: + user_data = {} + user_fields = "nom, gen, ins, dat, abl, acc".split(", ") + for i in user_fields: + k = "{key}_{case}".format(key=key, case=i) + v = "{first_name} {last_name}".format(first_name=self.db["users"][user_id]["first_name_"+i], last_name=self.db["users"][user_id]["last_name_"+i]) + user_data[k] = v + return user_data + # if User_id is not present in db. + else: + user = dict(id=user_id) + self.process_usernames(data=dict(profiles=[user], groups=[])) + return self.get_user(user_id) + else: + if abs(user_id) in self.db["groups"]: + user_data = {} + user_fields = "nom, gen, ins, dat, abl, acc".split(", ") + for i in user_fields: + k = "{key}_{case}".format(key=key, case=i) + v = self.db["groups"][abs(user_id)][i] + user_data[k] = v + else: + group = self.vk.client.groups.getById(group_ids=-1*user_id)[0] + self.process_usernames(data=dict(profiles=[], groups=[group])) + return self.get_user(user_id=user_id, key=key) + return user_data - def process_usernames(self, data): - """ processes user IDS and saves them in a local storage system. - Every function wich needs to convert from an ID to user or community name will have to call the get_user_name function in this session object. - Every function that needs to save a set ot user ids for a future use needs to pass a data dictionary with a profiles key being a list of user objects. - It gets first and last name for people in the 6 russian cases and saves them for future reference.""" - log.debug("Adding usernames to the local database...") - ids = "" - for i in data["profiles"]: - if (i["id"] in self.db["users"]) == False: - ids = ids + "{0},".format(i["id"],) - gids = "" - for i in data["groups"]: - if i["id"] not in self.db["groups"]: - self.db["groups"][i["id"]] = dict(nom=i["name"], gen=i["name"], dat=i["name"], acc=i["name"], ins=i["name"], abl=i["name"]) - gids = "{0},".format(i["id"],) - user_fields = "first_name_nom, last_name_nom, first_name_gen, last_name_gen, first_name_ins, last_name_ins, first_name_dat, last_name_dat, first_name_abl, last_name_abl, first_name_acc, last_name_acc, sex" - user_fields_list = user_fields.split(", ") - if ids != "": - users = self.vk.client.users.get(user_ids=ids, fields=user_fields) - for i in users: - if i["id"] not in self.db["users"]: - userdata = {} - for field in user_fields_list: - if field in i: - userdata[field] = i[field] - self.db["users"][i["id"]] = userdata + def process_usernames(self, data): + """ processes user IDS and saves them in a local storage system. + Every function wich needs to convert from an ID to user or community name will have to call the get_user_name function in this session object. + Every function that needs to save a set ot user ids for a future use needs to pass a data dictionary with a profiles key being a list of user objects. + It gets first and last name for people in the 6 russian cases and saves them for future reference.""" + log.debug("Adding usernames to the local database...") + ids = "" + for i in data["profiles"]: + if (i["id"] in self.db["users"]) == False: + ids = ids + "{0},".format(i["id"],) + gids = "" + for i in data["groups"]: + if i["id"] not in self.db["groups"]: + self.db["groups"][i["id"]] = dict(nom=i["name"], gen=i["name"], dat=i["name"], acc=i["name"], ins=i["name"], abl=i["name"]) + gids = "{0},".format(i["id"],) + user_fields = "first_name_nom, last_name_nom, first_name_gen, last_name_gen, first_name_ins, last_name_ins, first_name_dat, last_name_dat, first_name_abl, last_name_abl, first_name_acc, last_name_acc, sex" + user_fields_list = user_fields.split(", ") + if ids != "": + users = self.vk.client.users.get(user_ids=ids, fields=user_fields) + for i in users: + if i["id"] not in self.db["users"]: + userdata = {} + for field in user_fields_list: + if field in i: + userdata[field] = i[field] + self.db["users"][i["id"]] = userdata - def get_my_data(self): - log.debug("Getting user identifier...") - user = self.vk.client.users.get(fields="uid, first_name, last_name") - self.user_id = user[0]["id"] + def get_my_data(self): + log.debug("Getting user identifier...") + user = self.vk.client.users.get(fields="uid, first_name, last_name") + self.user_id = user[0]["id"] - def post(self, parent_endpoint, child_endpoint, from_buffer=None, attachments_list=[], post_arguments={}): - """ Generic function to be called whenever user wants to post something to VK. - This function should be capable of uploading all attachments before posting, and send a special event in case the post has failed, - So the program can recreate the post and show it back to the user.""" - # Define a list of error codes that are handled by the application. - handled_errors = [7, 900] - # ToDo: this function will occasionally be called with attachments already set to post_arguments, example if the user could upload the files but was unable to send the post due to a connection problem. - # We should see what can be done (reuploading everything vs using the already added attachments). - attachments = "" - # Firstly, let's try to upload the attachments here. If peer_id exists in post_arguments, - # It means we are talking about private messages, whose attachment procedures have their own methods. - if len(attachments_list) > 0: - try: - attachments = self.upload_attachments(attachments_list, post_arguments.get("peer_id")) - except Exception as error: - log.error("Error calling method %s.%s with arguments: %r. Failed during loading attachments. Error: %s" % (parent_endpoint, child_endpoint, post_arguments, str(error))) - # Report a failed function here too with same arguments so the client should be able to recreate it again. - wx.CallAfter(pub.sendMessage, "postFailed", parent_endpoint=parent_endpoint, child_endpoint=child_endpoint, from_buffer=from_buffer, attachments_list=attachments_list, post_arguments=post_arguments) - # After modifying everything, let's update the post arguments if needed. - if len(attachments) > 0: - if parent_endpoint == "messages": - post_arguments.update(attachment=attachments) - else: - post_arguments.update(attachments=attachments) - # Determines the correct functions to call here. - endpoint = getattr(self.vk.client, parent_endpoint) - endpoint = getattr(endpoint, child_endpoint) - try: - post = endpoint(**post_arguments) - # Once the post has been send, let's report it to the interested objects. - pub.sendMessage("posted", from_buffer=from_buffer) - except Exception as error: - log.exception("Error calling method %s.%s with arguments: %r. Error: %s" % (parent_endpoint, child_endpoint, post_arguments, str(error))) - # Send handled errors to the corresponding function, call the default handler otherwise. - if error.code in handled_errors: - wx.CallAfter(pub.sendMessage, "api-error", code=error.code) - else: - # Report a failed function here too with same arguments so the client should be able to recreate it again. - wx.CallAfter(pub.sendMessage, "postFailed", parent_endpoint=parent_endpoint, child_endpoint=child_endpoint, from_buffer=from_buffer, attachments_list=attachments_list, post_arguments=post_arguments) + def post(self, parent_endpoint, child_endpoint, from_buffer=None, attachments_list=[], post_arguments={}): + """ Generic function to be called whenever user wants to post something to VK. + This function should be capable of uploading all attachments before posting, and send a special event in case the post has failed, + So the program can recreate the post and show it back to the user.""" + # Define a list of error codes that are handled by the application. + handled_errors = [7, 900] + # ToDo: this function will occasionally be called with attachments already set to post_arguments, example if the user could upload the files but was unable to send the post due to a connection problem. + # We should see what can be done (reuploading everything vs using the already added attachments). + attachments = "" + # Firstly, let's try to upload the attachments here. If peer_id exists in post_arguments, + # It means we are talking about private messages, whose attachment procedures have their own methods. + if len(attachments_list) > 0: + try: + attachments = self.upload_attachments(attachments_list, post_arguments.get("peer_id")) + except Exception as error: + log.error("Error calling method %s.%s with arguments: %r. Failed during loading attachments. Error: %s" % (parent_endpoint, child_endpoint, post_arguments, str(error))) + # Report a failed function here too with same arguments so the client should be able to recreate it again. + wx.CallAfter(pub.sendMessage, "postFailed", parent_endpoint=parent_endpoint, child_endpoint=child_endpoint, from_buffer=from_buffer, attachments_list=attachments_list, post_arguments=post_arguments) + # After modifying everything, let's update the post arguments if needed. + if len(attachments) > 0: + if parent_endpoint == "messages": + post_arguments.update(attachment=attachments) + else: + post_arguments.update(attachments=attachments) + # Determines the correct functions to call here. + endpoint = getattr(self.vk.client, parent_endpoint) + endpoint = getattr(endpoint, child_endpoint) + try: + post = endpoint(**post_arguments) + # Once the post has been send, let's report it to the interested objects. + pub.sendMessage("posted", from_buffer=from_buffer) + except Exception as error: + log.exception("Error calling method %s.%s with arguments: %r. Error: %s" % (parent_endpoint, child_endpoint, post_arguments, str(error))) + # Send handled errors to the corresponding function, call the default handler otherwise. + if error.code in handled_errors: + wx.CallAfter(pub.sendMessage, "api-error", code=error.code) + else: + # Report a failed function here too with same arguments so the client should be able to recreate it again. + wx.CallAfter(pub.sendMessage, "postFailed", parent_endpoint=parent_endpoint, child_endpoint=child_endpoint, from_buffer=from_buffer, attachments_list=attachments_list, post_arguments=post_arguments) - def upload_attachments(self, attachments, peer_id=None): - """ Upload attachments to VK before posting them. - Returns attachments formatted as string, as required by VK API. - @ peer_id int: if this value is passed, let's assume attachments will be send in private messages. - """ - # To do: Check the caption and description fields for this kind of attachments. - local_attachments = "" - uploader = upload.VkUpload(self.vk.session_object) - for i in attachments: - if i["from"] == "online": - local_attachments += "{0}{1}_{2},".format(i["type"], i["owner_id"], i["id"]) - elif i["from"] == "local" and i["type"] == "photo": - photos = i["file"] - description = i["description"] - if peer_id == None: - r = uploader.photo_wall(photos, caption=description) - else: - r = uploader.photo_messages(photos) - id = r[0]["id"] - owner_id = r[0]["owner_id"] - local_attachments += "photo{0}_{1},".format(owner_id, id) - elif i["from"] == "local" and i["type"] == "audio": - audio = i["file"] - title = "untitled" - artist = "unnamed" - if "artist" in i: - artist = i["artist"] - if "title" in i: - title = i["title"] - r = uploader.audio(audio, title=title, artist=artist) - id = r["id"] - owner_id = r["owner_id"] - local_attachments += "audio{0}_{1},".format(owner_id, id) - elif i["from"] == "local" and i["type"] == "voice_message": - r = uploader.audio_message(i["file"], peer_id=peer_id) - id = r["audio_message"]["id"] - owner_id = r["audio_message"]["owner_id"] - local_attachments += "audio_message{0}_{1},".format(owner_id, id) - elif i["from"] == "local" and i["type"] == "document": - document = i["file"] - title = i["title"] - if peer_id == None: - r = uploader.document(document, title=title, to_wall=True) - else: - r = uploader.document(document, title=title, message_peer_id=peer_id) - id = r["doc"]["id"] - owner_id = r["doc"]["owner_id"] - local_attachments += "doc{0}_{1},".format(owner_id, id) - return local_attachments \ No newline at end of file + def upload_attachments(self, attachments, peer_id=None): + """ Upload attachments to VK before posting them. + Returns attachments formatted as string, as required by VK API. + @ peer_id int: if this value is passed, let's assume attachments will be send in private messages. + """ + # To do: Check the caption and description fields for this kind of attachments. + local_attachments = "" + uploader = upload.VkUpload(self.vk.session_object) + for i in attachments: + if i["from"] == "online": + local_attachments += "{0}{1}_{2},".format(i["type"], i["owner_id"], i["id"]) + elif i["from"] == "local" and i["type"] == "photo": + photos = i["file"] + description = i["description"] + if peer_id == None: + r = uploader.photo_wall(photos, caption=description) + else: + r = uploader.photo_messages(photos) + id = r[0]["id"] + owner_id = r[0]["owner_id"] + local_attachments += "photo{0}_{1},".format(owner_id, id) + elif i["from"] == "local" and i["type"] == "audio": + audio = i["file"] + title = "untitled" + artist = "unnamed" + if "artist" in i: + artist = i["artist"] + if "title" in i: + title = i["title"] + r = uploader.audio(audio, title=title, artist=artist) + id = r["id"] + owner_id = r["owner_id"] + local_attachments += "audio{0}_{1},".format(owner_id, id) + elif i["from"] == "local" and i["type"] == "voice_message": + r = uploader.audio_message(i["file"], peer_id=peer_id) + id = r["audio_message"]["id"] + owner_id = r["audio_message"]["owner_id"] + local_attachments += "audio_message{0}_{1},".format(owner_id, id) + elif i["from"] == "local" and i["type"] == "document": + document = i["file"] + title = i["title"] + if peer_id == None: + r = uploader.document(document, title=title, to_wall=True) + else: + r = uploader.document(document, title=title, message_peer_id=peer_id) + id = r["doc"]["id"] + owner_id = r["doc"]["owner_id"] + local_attachments += "doc{0}_{1},".format(owner_id, id) + return local_attachments diff --git a/src/sessionmanager/sessionManager.py b/src/sessionmanager/sessionManager.py index 85255c1..b6b2abf 100644 --- a/src/sessionmanager/sessionManager.py +++ b/src/sessionmanager/sessionManager.py @@ -14,83 +14,83 @@ from .config_utils import Configuration log = logging.getLogger("sessionmanager.sessionManager") class sessionManagerController(object): - def __init__(self, starting=True): - super(sessionManagerController, self).__init__() - log.debug("Setting up the session manager.") - if starting: - title=_("Select an account") - else: - title = _("Manage accounts") - self.view = view.sessionManagerWindow(starting=starting, title=title) - widgetUtils.connect_event(self.view.new, widgetUtils.BUTTON_PRESSED, self.manage_new_account) - widgetUtils.connect_event(self.view.remove, widgetUtils.BUTTON_PRESSED, self.remove) - self.fill_list() - if len(self.sessions) == 0: - log.debug("the session list is empty, creating a new one...") - self.manage_new_account() + def __init__(self, starting=True): + super(sessionManagerController, self).__init__() + log.debug("Setting up the session manager.") + if starting: + title=_("Select an account") + else: + title = _("Manage accounts") + self.view = view.sessionManagerWindow(starting=starting, title=title) + widgetUtils.connect_event(self.view.new, widgetUtils.BUTTON_PRESSED, self.manage_new_account) + widgetUtils.connect_event(self.view.remove, widgetUtils.BUTTON_PRESSED, self.remove) + self.fill_list() + if len(self.sessions) == 0: + log.debug("the session list is empty, creating a new one...") + self.manage_new_account() - def fill_list(self): - self.sessions = [] - log.debug("Filling the session list...") - for i in os.listdir(paths.config_path()): - if i != "dicts" and os.path.isdir(os.path.join(paths.config_path(), i)): - log.debug("Adding session %s" % (i,)) - config_test = Configuration(os.path.join(paths.config_path(), i, "session.conf")) - name = config_test["vk"]["user"] - if name != "" and config_test["vk"]["password"] != "": - self.sessions.append((i, name)) - self.view.list.insert_item(False, *[name]) + def fill_list(self): + self.sessions = [] + log.debug("Filling the session list...") + for i in os.listdir(paths.config_path()): + if i != "dicts" and os.path.isdir(os.path.join(paths.config_path(), i)): + log.debug("Adding session %s" % (i,)) + config_test = Configuration(os.path.join(paths.config_path(), i, "session.conf")) + name = config_test["vk"]["user"] + if name != "" and config_test["vk"]["password"] != "": + self.sessions.append((i, name)) + self.view.list.insert_item(False, *[name]) - def manage_new_account(self, *args, **kwargs): - if view.new_account_dialog() == widgetUtils.YES: - location = (str(time.time())[-6:]) - log.debug("Creating session in the %s path" % (location,)) - s = session.vkSession(location) - path = os.path.join(paths.config_path(), location) - if not os.path.exists(path): - os.mkdir(path) - s.get_configuration(True) - self.get_authorisation(s) - name = s.settings["vk"]["user"] - self.sessions.append((location, name)) - self.view.list.insert_item(False, *[name]) - self.modified = True + def manage_new_account(self, *args, **kwargs): + if view.new_account_dialog() == widgetUtils.YES: + location = (str(time.time())[-6:]) + log.debug("Creating session in the %s path" % (location,)) + s = session.vkSession(location) + path = os.path.join(paths.config_path(), location) + if not os.path.exists(path): + os.mkdir(path) + s.get_configuration(True) + self.get_authorisation(s) + name = s.settings["vk"]["user"] + self.sessions.append((location, name)) + self.view.list.insert_item(False, *[name]) + self.modified = True - def get_authorisation(self, c): - log.debug("Starting the authorisation process...") - dl = view.newSessionDialog() - if dl.ShowModal() == widgetUtils.OK: - c.settings["vk"]["user"] = dl.get_email() - c.settings["vk"]["password"] = dl.get_password() - try: - c.login() - except AuthenticationError: - c.settings["vk"]["password"] = "" - c.settings["vk"]["user"] - return self.get_authorisation(c) + def get_authorisation(self, c): + log.debug("Starting the authorisation process...") + dl = view.newSessionDialog() + if dl.ShowModal() == widgetUtils.OK: + c.settings["vk"]["user"] = dl.get_email() + c.settings["vk"]["password"] = dl.get_password() + try: + c.login() + except AuthenticationError: + c.settings["vk"]["password"] = "" + c.settings["vk"]["user"] + return self.get_authorisation(c) - def do_ok(self): - selected_session = self.sessions[self.view.list.get_selected()] - self.session = selected_session[0] - self.session = session.vkSession(self.session) - self.session.get_configuration() - session.sessions[selected_session[1]] = self.session + def do_ok(self): + selected_session = self.sessions[self.view.list.get_selected()] + self.session = selected_session[0] + self.session = session.vkSession(self.session) + self.session.get_configuration() + session.sessions[selected_session[1]] = self.session - def show(self): - if len(self.sessions) > 1: - answer = self.view.get_response() - else: - answer = widgetUtils.OK - if answer == widgetUtils.OK: - self.do_ok() - else: - sys.exit() - self.view.destroy() + def show(self): + if len(self.sessions) > 1: + answer = self.view.get_response() + else: + answer = widgetUtils.OK + if answer == widgetUtils.OK: + self.do_ok() + else: + sys.exit() + self.view.destroy() - def remove(self, *args, **kwargs): - if self.view.remove_account_dialog() == widgetUtils.YES: - selected_session = self.sessions[self.view.list.get_selected()] - shutil.rmtree(path=os.path.join(paths.config_path(), selected_session[0]), ignore_errors=True) - self.sessions.remove(selected_session) - self.view.list.remove_item(self.view.list.get_selected()) - self.modified = True \ No newline at end of file + def remove(self, *args, **kwargs): + if self.view.remove_account_dialog() == widgetUtils.YES: + selected_session = self.sessions[self.view.list.get_selected()] + shutil.rmtree(path=os.path.join(paths.config_path(), selected_session[0]), ignore_errors=True) + self.sessions.remove(selected_session) + self.view.list.remove_item(self.view.list.get_selected()) + self.modified = True diff --git a/src/sessionmanager/utils.py b/src/sessionmanager/utils.py index de22f4d..da2d0e9 100644 --- a/src/sessionmanager/utils.py +++ b/src/sessionmanager/utils.py @@ -12,93 +12,93 @@ url_re = re.compile("(?:\w+://|www\.)[^ ,.?!#%=+][^ ]*") bad_chars = '\'\\.,[](){}:;"' def seconds_to_string(seconds, precision=0): - """ convert a number of seconds in a string representation.""" - # ToDo: Improve it to handle properly Russian plurals. - day = seconds // 86400 - hour = seconds // 3600 - min = (seconds // 60) % 60 - sec = seconds - (hour * 3600) - (min * 60) - sec_spec = "." + str(precision) + "f" - sec_string = sec.__format__(sec_spec) - string = "" - if day == 1: - string += _("%d day, ") % day - elif day >= 2: - string += _("%d days, ") % day - if (hour == 1): - string += _("%d hour, ") % hour - elif (hour >= 2): - string += _("%d hours, ") % hour - if (min == 1): - string += _("%d minute, ") % min - elif (min >= 2): - string += _("%d minutes, ") % min - if sec >= 0 and sec <= 2: - string += _("%s second") % sec_string - else: - string += _("%s seconds") % sec_string - return string + """ convert a number of seconds in a string representation.""" + # ToDo: Improve it to handle properly Russian plurals. + day = seconds // 86400 + hour = seconds // 3600 + min = (seconds // 60) % 60 + sec = seconds - (hour * 3600) - (min * 60) + sec_spec = "." + str(precision) + "f" + sec_string = sec.__format__(sec_spec) + string = "" + if day == 1: + string += _("%d day, ") % day + elif day >= 2: + string += _("%d days, ") % day + if (hour == 1): + string += _("%d hour, ") % hour + elif (hour >= 2): + string += _("%d hours, ") % hour + if (min == 1): + string += _("%d minute, ") % min + elif (min >= 2): + string += _("%d minutes, ") % min + if sec >= 0 and sec <= 2: + string += _("%s second") % sec_string + else: + string += _("%s seconds") % sec_string + return string def find_urls_in_text(text): - return [s.strip(bad_chars) for s in url_re.findall(text)] + return [s.strip(bad_chars) for s in url_re.findall(text)] def download_file(url, local_filename): - r = requests.get(url, stream=True) - pub.sendMessage("change_status", status=_("Downloading {0}").format(local_filename,)) - total_length = r.headers.get("content-length") - dl = 0 - total_length = int(total_length) - with open(local_filename, 'wb') as f: - for chunk in r.iter_content(chunk_size=512*1024): - if chunk: # filter out keep-alive new chunks - dl += len(chunk) - f.write(chunk) - done = int(100 * dl/total_length) - msg = _("Downloading {0} ({1}%)").format(os.path.basename(local_filename), done) -# print(msg) - pub.sendMessage("change_status", status=msg) - pub.sendMessage("change_status", status=_("Ready")) - return local_filename + r = requests.get(url, stream=True) + pub.sendMessage("change_status", status=_("Downloading {0}").format(local_filename,)) + total_length = r.headers.get("content-length") + dl = 0 + total_length = int(total_length) + with open(local_filename, 'wb') as f: + for chunk in r.iter_content(chunk_size=512*1024): + if chunk: # filter out keep-alive new chunks + dl += len(chunk) + f.write(chunk) + done = int(100 * dl/total_length) + msg = _("Downloading {0} ({1}%)").format(os.path.basename(local_filename), done) +# print(msg) + pub.sendMessage("change_status", status=msg) + pub.sendMessage("change_status", status=_("Ready")) + return local_filename def download_files(downloads): - for download in downloads: - download_file(download[0], download[1]) + for download in downloads: + download_file(download[0], download[1]) def detect_users(text): - """ Detect all users and communities mentionned in any text posted in VK.""" - # This regexp gets group and users mentionned in topic comments. - for matched_data in re.finditer("(\[)(id|club)(\d+:bp-\d+_\d+\|)(\D+)(\])", text): - text = re.sub("\[(id|club)\d+:bp-\d+_\d+\|\D+\]", matched_data.groups()[3]+", ", text, count=1) - # This is for users and communities just mentionned in wall comments or posts. - for matched_data in re.finditer("(\[)(id|club)(\d+\|)(\D+)(\])", text): - text = re.sub("\[(id|club)\d+\|\D+\]", matched_data.groups()[3]+", ", text, count=1) - return text + """ Detect all users and communities mentionned in any text posted in VK.""" + # This regexp gets group and users mentionned in topic comments. + for matched_data in re.finditer("(\[)(id|club)(\d+:bp-\d+_\d+\|)(\D+)(\])", text): + text = re.sub("\[(id|club)\d+:bp-\d+_\d+\|\D+\]", matched_data.groups()[3]+", ", text, count=1) + # This is for users and communities just mentionned in wall comments or posts. + for matched_data in re.finditer("(\[)(id|club)(\d+\|)(\D+)(\])", text): + text = re.sub("\[(id|club)\d+\|\D+\]", matched_data.groups()[3]+", ", text, count=1) + return text def clean_text(text): - """ Clean text, removing all unneeded HTMl and converting HTML represented characters in their unicode counterparts.""" - text = detect_users(text) - text = html.unescape(text) - return text + """ Clean text, removing all unneeded HTMl and converting HTML represented characters in their unicode counterparts.""" + text = detect_users(text) + text = html.unescape(text) + return text def transform_audio_url(url): - """ Transforms the URL offered by VK to the unencrypted stream so we can still play it. - This function will be updated every time VK decides to change something in their Audio API'S. - Changelog: - 30/04/2019: Re-enabled old methods as VK changed everything as how it was working on 16.04.2019. - 17.04.2019: Updated function. Now it is not required to strip anything, just replacing /index.m3u8 with .mp3 should be enough. - 16.04.2019: Implemented this function. For now it replaces /index.m3u8 by .mp3, also removes the path component before "/audios" if the URL contains the word /audios, or the last path component before the filename if doesn't. - """ - if "vkuseraudio.net" not in url and "index.m3u8" not in url: - return url - url = url.replace("/index.m3u8", ".mp3") - parts = url.split("/") - if "/audios" not in url: - url = url.replace("/"+parts[-2], "") - else: - url = url.replace("/"+parts[-3], "") - url = url.split(".mp3?")[0]+".mp3" - return url + """ Transforms the URL offered by VK to the unencrypted stream so we can still play it. + This function will be updated every time VK decides to change something in their Audio API'S. + Changelog: + 30/04/2019: Re-enabled old methods as VK changed everything as how it was working on 16.04.2019. + 17.04.2019: Updated function. Now it is not required to strip anything, just replacing /index.m3u8 with .mp3 should be enough. + 16.04.2019: Implemented this function. For now it replaces /index.m3u8 by .mp3, also removes the path component before "/audios" if the URL contains the word /audios, or the last path component before the filename if doesn't. + """ + if "vkuseraudio.net" not in url and "index.m3u8" not in url: + return url + url = url.replace("/index.m3u8", ".mp3") + parts = url.split("/") + if "/audios" not in url: + url = url.replace("/"+parts[-2], "") + else: + url = url.replace("/"+parts[-3], "") + url = url.split(".mp3?")[0]+".mp3" + return url def safe_filename(filename): - allowed_symbols = ["_", ".", ",", "-", "(", ")"] - return "".join([c for c in filename if c.isalpha() or c.isdigit() or c==' ' or c in allowed_symbols]).rstrip() \ No newline at end of file + allowed_symbols = ["_", ".", ",", "-", "(", ")"] + return "".join([c for c in filename if c.isalpha() or c.isdigit() or c==' ' or c in allowed_symbols]).rstrip() diff --git a/src/sessionmanager/vkSessionHandler.py b/src/sessionmanager/vkSessionHandler.py index a292cde..76639cf 100644 --- a/src/sessionmanager/vkSessionHandler.py +++ b/src/sessionmanager/vkSessionHandler.py @@ -9,28 +9,28 @@ log = logging.getLogger("vkSessionHandler") class vkObject(object): - def __init__(self): - self.api_key = keys.keyring.get_api_key() + def __init__(self): + self.api_key = keys.keyring.get_api_key() - def login(self, user, password, token, alt_token, filename): - if alt_token == False: - log.info("Using kate's token...") - # Let's import the patched vk_api module for using a different user agent - from . import vk_api_patched as vk_api - if token == "" or token == None: - log.info("Token is not valid. Generating one...") - original_token = official.login(user, password) - token = original_token - log.info("Token validated...") - self.session_object = vk_api.VkApi(app_id=self.api_key, login=user, password=password, token=token, scope="all", config_filename=filename) - else: - import vk_api - self.session_object = vk_api.VkApi(app_id=self.api_key, login=user, password=password, scope="offline, wall, notify, friends, photos, audio, video, docs, notes, pages, status, groups, messages, notifications, stats", config_filename=filename, auth_handler=two_factor_auth) - self.session_object.auth() - self.client = self.session_object.get_api() -# print self.client.audio.get() - log.debug("Getting tokens for 24 hours...") -# info = self.client.account.getProfileInfo() - # Add session data to the application statistics. - self.client.stats.trackVisitor() - self.client_audio = VkAudio(self.session_object) + def login(self, user, password, token, alt_token, filename): + if alt_token == False: + log.info("Using kate's token...") + # Let's import the patched vk_api module for using a different user agent + from . import vk_api_patched as vk_api + if token == "" or token == None: + log.info("Token is not valid. Generating one...") + original_token = official.login(user, password) + token = original_token + log.info("Token validated...") + self.session_object = vk_api.VkApi(app_id=self.api_key, login=user, password=password, token=token, scope="all", config_filename=filename) + else: + import vk_api + self.session_object = vk_api.VkApi(app_id=self.api_key, login=user, password=password, scope="offline, wall, notify, friends, photos, audio, video, docs, notes, pages, status, groups, messages, notifications, stats", config_filename=filename, auth_handler=two_factor_auth) + self.session_object.auth() + self.client = self.session_object.get_api() +# print self.client.audio.get() + log.debug("Getting tokens for 24 hours...") +# info = self.client.account.getProfileInfo() + # Add session data to the application statistics. + self.client.stats.trackVisitor() + self.client_audio = VkAudio(self.session_object) diff --git a/src/sessionmanager/wxUI.py b/src/sessionmanager/wxUI.py index 98ed8be..820129d 100644 --- a/src/sessionmanager/wxUI.py +++ b/src/sessionmanager/wxUI.py @@ -4,71 +4,71 @@ import wx import widgetUtils def new_account_dialog(): - return wx.MessageDialog(None, _("In order to continue, you need to configure your VK account before. Would you like to autorhise a new account now?"), _("Authorisation"), wx.YES_NO).ShowModal() + return wx.MessageDialog(None, _("In order to continue, you need to configure your VK account before. Would you like to autorhise a new account now?"), _("Authorisation"), wx.YES_NO).ShowModal() class newSessionDialog(widgetUtils.BaseDialog): - def __init__(self): - super(newSessionDialog, self).__init__(parent=None, id=wx.NewId(), title=_("Authorise VK")) - panel = wx.Panel(self) - lbl1 = wx.StaticText(panel, -1, _("&Email or phone number")) - self.email = wx.TextCtrl(panel, -1) - lbl2 = wx.StaticText(panel, -1, _("&Password")) - self.passw = wx.TextCtrl(panel, -1, style=wx.TE_PASSWORD) - sizer = wx.BoxSizer() - b1 = wx.BoxSizer(wx.HORIZONTAL) - b1.Add(lbl1, 0, wx.ALL, 5) - b1.Add(self.email, 0, wx.ALL, 5) - b2 = wx.BoxSizer(wx.HORIZONTAL) - b2.Add(lbl2, 0, wx.ALL, 5) - b2.Add(self.passw, 0, wx.ALL, 5) - sizer.Add(b1, 0, wx.ALL, 5) - sizer.Add(b2, 0, wx.ALL, 5) - ok = wx.Button(panel, wx.ID_OK) - ok.SetDefault() - cancel = wx.Button(panel, wx.ID_CANCEL) - btnb = wx.BoxSizer(wx.HORIZONTAL) - btnb.Add(ok, 0, wx.ALL, 5) - btnb.Add(cancel, 0, wx.ALL, 5) - sizer.Add(btnb, 0, wx.ALL, 5) - panel.SetSizer(sizer) + def __init__(self): + super(newSessionDialog, self).__init__(parent=None, id=wx.NewId(), title=_("Authorise VK")) + panel = wx.Panel(self) + lbl1 = wx.StaticText(panel, -1, _("&Email or phone number")) + self.email = wx.TextCtrl(panel, -1) + lbl2 = wx.StaticText(panel, -1, _("&Password")) + self.passw = wx.TextCtrl(panel, -1, style=wx.TE_PASSWORD) + sizer = wx.BoxSizer() + b1 = wx.BoxSizer(wx.HORIZONTAL) + b1.Add(lbl1, 0, wx.ALL, 5) + b1.Add(self.email, 0, wx.ALL, 5) + b2 = wx.BoxSizer(wx.HORIZONTAL) + b2.Add(lbl2, 0, wx.ALL, 5) + b2.Add(self.passw, 0, wx.ALL, 5) + sizer.Add(b1, 0, wx.ALL, 5) + sizer.Add(b2, 0, wx.ALL, 5) + ok = wx.Button(panel, wx.ID_OK) + ok.SetDefault() + cancel = wx.Button(panel, wx.ID_CANCEL) + btnb = wx.BoxSizer(wx.HORIZONTAL) + btnb.Add(ok, 0, wx.ALL, 5) + btnb.Add(cancel, 0, wx.ALL, 5) + sizer.Add(btnb, 0, wx.ALL, 5) + panel.SetSizer(sizer) - def get_email(self): - return self.email.GetValue() + def get_email(self): + return self.email.GetValue() - def get_password(self): - return self.passw.GetValue() + def get_password(self): + return self.passw.GetValue() class sessionManagerWindow(widgetUtils.BaseDialog): - def __init__(self, title, starting=True): - super(sessionManagerWindow, self).__init__(parent=None, title=title, size=wx.DefaultSize) - panel = wx.Panel(self) - sizer = wx.BoxSizer(wx.VERTICAL) - label = wx.StaticText(panel, -1, _(u"Accounts list"), size=wx.DefaultSize) - listSizer = wx.BoxSizer(wx.HORIZONTAL) - self.list = widgetUtils.list(panel, _("Account"), style=wx.LC_SINGLE_SEL|wx.LC_REPORT) - listSizer.Add(label, 0, wx.ALL, 5) - listSizer.Add(self.list.list, 0, wx.ALL, 5) - sizer.Add(listSizer, 0, wx.ALL, 5) - self.new = wx.Button(panel, -1, _("New account"), size=wx.DefaultSize) - self.remove = wx.Button(panel, -1, _(u"Remove account")) - if starting: - id_ok = wx.ID_OK - else: - id_ok = wx.ID_CANCEL - ok = wx.Button(panel, id_ok, size=wx.DefaultSize) - ok.SetDefault() - if starting: - cancel = wx.Button(panel, wx.ID_CANCEL, size=wx.DefaultSize) - self.SetAffirmativeId(id_ok) - buttons = wx.BoxSizer(wx.HORIZONTAL) - buttons.Add(self.new, 0, wx.ALL, 5) - buttons.Add(ok, 0, wx.ALL, 5) - if starting: - buttons.Add(cancel, 0, wx.ALL, 5) - sizer.Add(buttons, 0, wx.ALL, 5) - panel.SetSizer(sizer) - min = sizer.CalcMin() - self.SetClientSize(min) + def __init__(self, title, starting=True): + super(sessionManagerWindow, self).__init__(parent=None, title=title, size=wx.DefaultSize) + panel = wx.Panel(self) + sizer = wx.BoxSizer(wx.VERTICAL) + label = wx.StaticText(panel, -1, _(u"Accounts list"), size=wx.DefaultSize) + listSizer = wx.BoxSizer(wx.HORIZONTAL) + self.list = widgetUtils.list(panel, _("Account"), style=wx.LC_SINGLE_SEL|wx.LC_REPORT) + listSizer.Add(label, 0, wx.ALL, 5) + listSizer.Add(self.list.list, 0, wx.ALL, 5) + sizer.Add(listSizer, 0, wx.ALL, 5) + self.new = wx.Button(panel, -1, _("New account"), size=wx.DefaultSize) + self.remove = wx.Button(panel, -1, _(u"Remove account")) + if starting: + id_ok = wx.ID_OK + else: + id_ok = wx.ID_CANCEL + ok = wx.Button(panel, id_ok, size=wx.DefaultSize) + ok.SetDefault() + if starting: + cancel = wx.Button(panel, wx.ID_CANCEL, size=wx.DefaultSize) + self.SetAffirmativeId(id_ok) + buttons = wx.BoxSizer(wx.HORIZONTAL) + buttons.Add(self.new, 0, wx.ALL, 5) + buttons.Add(ok, 0, wx.ALL, 5) + if starting: + buttons.Add(cancel, 0, wx.ALL, 5) + sizer.Add(buttons, 0, wx.ALL, 5) + panel.SetSizer(sizer) + min = sizer.CalcMin() + self.SetClientSize(min) - def remove_account_dialog(self): - return wx.MessageDialog(self, _("Do you really want to delete this account?"), _("Remove account"), wx.YES_NO).ShowModal() \ No newline at end of file + def remove_account_dialog(self): + return wx.MessageDialog(self, _("Do you really want to delete this account?"), _("Remove account"), wx.YES_NO).ShowModal() diff --git a/src/setup.py b/src/setup.py index 45b1712..266f5a6 100644 --- a/src/setup.py +++ b/src/setup.py @@ -10,38 +10,38 @@ from babel.messages import frontend as babel languageHandler.setLanguage("en") def find_sound_lib_datafiles(): - import os - import platform - import sound_lib - path = os.path.join(sound_lib.__path__[0], 'lib') - if platform.architecture()[0] == '32bit' or platform.system() == 'Darwin': - arch = 'x86' - else: - arch = 'x64' - dest_dir = os.path.join('sound_lib', 'lib', arch) - source = os.path.join(path, arch) - return (source, dest_dir) + import os + import platform + import sound_lib + path = os.path.join(sound_lib.__path__[0], 'lib') + if platform.architecture()[0] == '32bit' or platform.system() == 'Darwin': + arch = 'x86' + else: + arch = 'x64' + dest_dir = os.path.join('sound_lib', 'lib', arch) + source = os.path.join(path, arch) + return (source, dest_dir) def find_accessible_output2_datafiles(): - import os - import accessible_output2 - path = os.path.join(accessible_output2.__path__[0], 'lib') - dest_dir = os.path.join('accessible_output2', 'lib') - return (path, dest_dir) + import os + import accessible_output2 + path = os.path.join(accessible_output2.__path__[0], 'lib') + dest_dir = os.path.join('accessible_output2', 'lib') + return (path, dest_dir) base = None if sys.platform == 'win32': base = 'Win32GUI' build_exe_options = dict( - build_exe="dist", - optimize=1, - include_msvcr=True, - zip_include_packages=["accessible_output2", "sound_lib", "arrow"], - replace_paths = [("*", "")], - include_files=["session.defaults", "cacert.pem", "app-configuration.defaults", "locales", "sounds", "documentation", "../windows-dependencies/x86/oggenc2.exe", "../windows-dependencies/x86/bootstrap.exe", find_sound_lib_datafiles(), find_accessible_output2_datafiles(), ("../windows-dependencies/msvc32", "."), ("../windows-dependencies/dictionaries", "lib/enchant/data/mingw32/share/enchant/hunspell")], - packages=["interactors", "presenters", "views", "wxUI"], - ) + build_exe="dist", + optimize=1, + include_msvcr=True, + zip_include_packages=["accessible_output2", "sound_lib", "arrow"], + replace_paths = [("*", "")], + include_files=["session.defaults", "cacert.pem", "app-configuration.defaults", "locales", "sounds", "documentation", "../windows-dependencies/x86/oggenc2.exe", "../windows-dependencies/x86/bootstrap.exe", find_sound_lib_datafiles(), find_accessible_output2_datafiles(), ("../windows-dependencies/msvc32", "."), ("../windows-dependencies/dictionaries", "lib/enchant/data/mingw32/share/enchant/hunspell")], + packages=["interactors", "presenters", "views", "wxUI"], + ) executables = [ Executable('main.py', base=base, targetName="socializer") diff --git a/src/sound.py b/src/sound.py index 9fb37e0..83a8cb9 100644 --- a/src/sound.py +++ b/src/sound.py @@ -18,72 +18,72 @@ from sound_lib import output, input log = logging.getLogger("sound") def recode_audio(filename, quality=10): - subprocess.call(r'"%s" --downmix -q %r "%s"' % (os.path.join(paths.app_path(), 'oggenc2.exe'), quality, filename)) + subprocess.call(r'"%s" --downmix -q %r "%s"' % (os.path.join(paths.app_path(), 'oggenc2.exe'), quality, filename)) def get_recording(filename): # try: - val = recording.WaveRecording(filename=filename) + val = recording.WaveRecording(filename=filename) # except sound_lib.main.BassError: # sound_lib.input.Input() # val = sound_lib.recording.WaveRecording(filename=filename) - return val + return val class soundSystem(object): - def check_soundpack(self): - """ Checks if the folder where live the current soundpack exists.""" - self.soundpack_OK = False - if os.path.exists(os.path.join(paths.sound_path(), self.config["current_soundpack"])): - self.path = os.path.join(paths.sound_path(), self.config["current_soundpack"]) - self.soundpack_OK = True - elif os.path.exists(os.path.join(paths.sound_path(), "default")): - log.error("The soundpack does not exist, using default...") - self.path = os.path.join(paths.sound_path(), "default") - self.soundpack_OK = True - else: - log.error("The current soundpack could not be found and the default soundpack has been deleted, Socializer will not play sounds.") - self.soundpack_OK = False + def check_soundpack(self): + """ Checks if the folder where live the current soundpack exists.""" + self.soundpack_OK = False + if os.path.exists(os.path.join(paths.sound_path(), self.config["current_soundpack"])): + self.path = os.path.join(paths.sound_path(), self.config["current_soundpack"]) + self.soundpack_OK = True + elif os.path.exists(os.path.join(paths.sound_path(), "default")): + log.error("The soundpack does not exist, using default...") + self.path = os.path.join(paths.sound_path(), "default") + self.soundpack_OK = True + else: + log.error("The current soundpack could not be found and the default soundpack has been deleted, Socializer will not play sounds.") + self.soundpack_OK = False - def __init__(self, soundConfig): - """ Sound Player.""" - self.config = soundConfig - # Set the output and input default devices. - try: - self.output = output.Output() - self.input = input.Input() - except: - pass + def __init__(self, soundConfig): + """ Sound Player.""" + self.config = soundConfig + # Set the output and input default devices. + try: + self.output = output.Output() + self.input = input.Input() + except: + pass # Try to use the selected device from the configuration. It can fail if the machine does not has a mic. - try: - log.debug("Setting input and output devices...") - self.output.set_device(self.output.find_device_by_name(self.config["output_device"])) - self.input.set_device(self.input.find_device_by_name(self.config["input_device"])) - except: - log.error("Error in input or output devices, using defaults...") - self.config["output_device"] = "Default" - self.config["input_device"] = "Default" - # Set proxy for audio. - if config.app["app-settings"]["use_proxy"]: - self.output.set_proxy(b"socializer:socializer@socializer.su:3128") - self.files = [] - self.cleaner = RepeatingTimer(60, self.clear_list) - self.cleaner.start() - self.check_soundpack() + try: + log.debug("Setting input and output devices...") + self.output.set_device(self.output.find_device_by_name(self.config["output_device"])) + self.input.set_device(self.input.find_device_by_name(self.config["input_device"])) + except: + log.error("Error in input or output devices, using defaults...") + self.config["output_device"] = "Default" + self.config["input_device"] = "Default" + # Set proxy for audio. + if config.app["app-settings"]["use_proxy"]: + self.output.set_proxy(b"socializer:socializer@socializer.su:3128") + self.files = [] + self.cleaner = RepeatingTimer(60, self.clear_list) + self.cleaner.start() + self.check_soundpack() - def clear_list(self): - if len(self.files) == 0: return - try: - for i in range(0, len(self.files)): - if self.files[i].is_playing == False: - self.files[i].free() - self.files.pop(i) - except IndexError: - pass + def clear_list(self): + if len(self.files) == 0: return + try: + for i in range(0, len(self.files)): + if self.files[i].is_playing == False: + self.files[i].free() + self.files.pop(i) + except IndexError: + pass - def play(self, sound, argument=False): - if self.soundpack_OK == False: return - if self.config["session_mute"] == True: return - sound_object = sound_lib.stream.FileStream(file="%s/%s" % (self.path, sound)) -# sound_object.volume = self.config["volume"]/100 - self.files.append(sound_object) - sound_object.play() + def play(self, sound, argument=False): + if self.soundpack_OK == False: return + if self.config["session_mute"] == True: return + sound_object = sound_lib.stream.FileStream(file="%s/%s" % (self.path, sound)) +# sound_object.volume = self.config["volume"]/100 + self.files.append(sound_object) + sound_object.play() diff --git a/src/test/test_audiorecorder.py b/src/test/test_audiorecorder.py index 2da437c..e647166 100644 --- a/src/test/test_audiorecorder.py +++ b/src/test/test_audiorecorder.py @@ -7,64 +7,64 @@ from interactors import audioRecorder as interactor class audioRecorderTestCase(unittest.TestCase): - """ Test both the presenter and interactor of the audio recorder feature. View stuff will be mocked.""" + """ Test both the presenter and interactor of the audio recorder feature. View stuff will be mocked.""" - @mock.patch("presenters.audioRecorder.sound_lib", esp_set=True) - @mock.patch("presenters.base.pub", esp_set=True) - @mock.patch("presenters.audioRecorder.tempfile", esp_set=True) - @mock.patch("presenters.audioRecorder.sound", esp_set=True) - @mock.patch("presenters.audioRecorder.output", esp_set=True) - @mock.patch("presenters.audioRecorder.os", esp_set=True) - def test_audiorecorder_presenter(self, os_mock, output_mock, sound_mock, tempfile_mock, pub_mock, soundlib_mock): - """ Test methods for audio recorder presenter. """ - tempfile_mock.mktemp.return_value = "somefile.wav" - sound_mock.get_recording.return_value = mock.MagicMock() - soundlib_mock.stream.fileStream.return_value = mock.MagicMock() - view=mock.MagicMock(name="view") - interactor_ = mock.MagicMock(name="interactor", esp_set=interactor.audioRecorderInteractor) - presenter_ = presenter.audioRecorderPresenter(view=view, interactor=interactor_) - # Start sending events to the presenter and see its reactions. - presenter_.start_recording() - tempfile_mock.mktemp.assert_any_call(suffix=".wav") - sound_mock.get_recording.assert_any_call(presenter_.file) - presenter_.recording.play.assert_any_call() - pub_mock.sendMessage.assert_any_call("audiorecorder_set_label", control="record", label=_("&Stop")) - pub_mock.sendMessage.assert_any_call("audiorecorder_disable_control", control="ok") - presenter_.stop_recording() - presenter_.recording.stop.assert_any_call() - presenter_.recording.free.assert_any_call() - pub_mock.sendMessage.assert_any_call("audiorecorder_set_label", control="record", label=_("&Record")) - pub_mock.sendMessage.assert_any_call("audiorecorder_disable_control", control="record") - pub_mock.sendMessage.assert_any_call("audiorecorder_enable_control", control="play") - pub_mock.sendMessage.assert_any_call("audiorecorder_enable_control", control="discard") - pub_mock.sendMessage.assert_any_call("audiorecorder_enable_control", control="ok") - pub_mock.sendMessage.assert_any_call("audiorecorder_focus_control", control="play") - presenter_.discard_recording() - self.assertTrue(presenter_.playing==None) + @mock.patch("presenters.audioRecorder.sound_lib", esp_set=True) + @mock.patch("presenters.base.pub", esp_set=True) + @mock.patch("presenters.audioRecorder.tempfile", esp_set=True) + @mock.patch("presenters.audioRecorder.sound", esp_set=True) + @mock.patch("presenters.audioRecorder.output", esp_set=True) + @mock.patch("presenters.audioRecorder.os", esp_set=True) + def test_audiorecorder_presenter(self, os_mock, output_mock, sound_mock, tempfile_mock, pub_mock, soundlib_mock): + """ Test methods for audio recorder presenter. """ + tempfile_mock.mktemp.return_value = "somefile.wav" + sound_mock.get_recording.return_value = mock.MagicMock() + soundlib_mock.stream.fileStream.return_value = mock.MagicMock() + view=mock.MagicMock(name="view") + interactor_ = mock.MagicMock(name="interactor", esp_set=interactor.audioRecorderInteractor) + presenter_ = presenter.audioRecorderPresenter(view=view, interactor=interactor_) + # Start sending events to the presenter and see its reactions. + presenter_.start_recording() + tempfile_mock.mktemp.assert_any_call(suffix=".wav") + sound_mock.get_recording.assert_any_call(presenter_.file) + presenter_.recording.play.assert_any_call() + pub_mock.sendMessage.assert_any_call("audiorecorder_set_label", control="record", label=_("&Stop")) + pub_mock.sendMessage.assert_any_call("audiorecorder_disable_control", control="ok") + presenter_.stop_recording() + presenter_.recording.stop.assert_any_call() + presenter_.recording.free.assert_any_call() + pub_mock.sendMessage.assert_any_call("audiorecorder_set_label", control="record", label=_("&Record")) + pub_mock.sendMessage.assert_any_call("audiorecorder_disable_control", control="record") + pub_mock.sendMessage.assert_any_call("audiorecorder_enable_control", control="play") + pub_mock.sendMessage.assert_any_call("audiorecorder_enable_control", control="discard") + pub_mock.sendMessage.assert_any_call("audiorecorder_enable_control", control="ok") + pub_mock.sendMessage.assert_any_call("audiorecorder_focus_control", control="play") + presenter_.discard_recording() + self.assertTrue(presenter_.playing==None) - @mock.patch("interactors.audioRecorder.widgetUtils", esp_set=True) - def test_audiorecorder_interactor(self, widgetUtils_mock): - view=mock.MagicMock(name="view") - interactor_ = interactor.audioRecorderInteractor() - presenter_ = mock.MagicMock(name="Presenter", esp_set=presenter.audioRecorderPresenter) - interactor_.install(view=view, presenter=presenter_) - # Test if events have been connected to WX - widgetUtils_mock.connect_event.assert_any_call(view.play, widgetUtils_mock.BUTTON_PRESSED, interactor_.on_play) - widgetUtils_mock.connect_event.assert_any_call(view.record, widgetUtils_mock.BUTTON_PRESSED, interactor_.on_record) - widgetUtils_mock.connect_event.assert_any_call(view.discard, widgetUtils_mock.BUTTON_PRESSED, interactor_.on_discard) - # Let's call some methods simulating user interaction. - interactor_.on_record() - presenter_.toggle_recording.assert_called_with() - interactor_.on_play() - presenter_.play.assert_called_with() - # Let's simulate user response here - view.get_response.return_value = widgetUtils_mock.OK - interactor_.start() - # this should call on_postprocess after receiving the OK signal. - presenter_.postprocess.assert_called_with() + @mock.patch("interactors.audioRecorder.widgetUtils", esp_set=True) + def test_audiorecorder_interactor(self, widgetUtils_mock): + view=mock.MagicMock(name="view") + interactor_ = interactor.audioRecorderInteractor() + presenter_ = mock.MagicMock(name="Presenter", esp_set=presenter.audioRecorderPresenter) + interactor_.install(view=view, presenter=presenter_) + # Test if events have been connected to WX + widgetUtils_mock.connect_event.assert_any_call(view.play, widgetUtils_mock.BUTTON_PRESSED, interactor_.on_play) + widgetUtils_mock.connect_event.assert_any_call(view.record, widgetUtils_mock.BUTTON_PRESSED, interactor_.on_record) + widgetUtils_mock.connect_event.assert_any_call(view.discard, widgetUtils_mock.BUTTON_PRESSED, interactor_.on_discard) + # Let's call some methods simulating user interaction. + interactor_.on_record() + presenter_.toggle_recording.assert_called_with() + interactor_.on_play() + presenter_.play.assert_called_with() + # Let's simulate user response here + view.get_response.return_value = widgetUtils_mock.OK + interactor_.start() + # this should call on_postprocess after receiving the OK signal. + presenter_.postprocess.assert_called_with() - def setUp(self): - languageHandler.setLanguage("en") + def setUp(self): + languageHandler.setLanguage("en") if __name__ == "__main__": - unittest.main() \ No newline at end of file + unittest.main() diff --git a/src/test/test_base_interactor.py b/src/test/test_base_interactor.py index a0a9a83..d72ccda 100644 --- a/src/test/test_base_interactor.py +++ b/src/test/test_base_interactor.py @@ -4,34 +4,34 @@ import mock from interactors import base class baseInteractorTestCase(unittest.TestCase): - """ some tests for the base interactor implementation.""" + """ some tests for the base interactor implementation.""" - @mock.patch("interactors.base.pub", esp_set=True) - def test_base_interactor(self, pub_mock): - """ Test the base interactor class. """ - view=mock.MagicMock(name="view") - interactor_ = base.baseInteractor() - presenter_ = mock.MagicMock(name="Presenter") - interactor_.install(view=view, presenter=presenter_, modulename="base") - # Check if the interactor has called pubsub correctly. - pub_mock.subscribe.assert_any_call(interactor_.disable_control, "base_disable_control"), - pub_mock.subscribe.assert_any_call(interactor_.enable_control, "base_enable_control"), - pub_mock.subscribe.assert_any_call(interactor_.set_label, "base_set_label"), - pub_mock.subscribe.assert_any_call(interactor_.focus_control, "base_focus_control") - # Now, simulate some event calls. - interactor_.disable_control(control="some_control") - view.disable.assert_called_with("some_control") - interactor_.enable_control(control="some_control") - view.enable.assert_called_with("some_control") - interactor_.set_label(control="some_control", label="label") - view.set.assert_called_with("some_control", "label") - interactor_.focus_control(control="some_control") - view.some_control.SetFocus.assert_called_with() - interactor_.uninstall() - pub_mock.unsubscribe.assert_any_call(interactor_.disable_control, "base_disable_control"), - pub_mock.unsubscribe.assert_any_call(interactor_.enable_control, "base_enable_control"), - pub_mock.unsubscribe.assert_any_call(interactor_.set_label, "base_set_label"), - pub_mock.unsubscribe.assert_any_call(interactor_.focus_control, "base_focus_control") + @mock.patch("interactors.base.pub", esp_set=True) + def test_base_interactor(self, pub_mock): + """ Test the base interactor class. """ + view=mock.MagicMock(name="view") + interactor_ = base.baseInteractor() + presenter_ = mock.MagicMock(name="Presenter") + interactor_.install(view=view, presenter=presenter_, modulename="base") + # Check if the interactor has called pubsub correctly. + pub_mock.subscribe.assert_any_call(interactor_.disable_control, "base_disable_control"), + pub_mock.subscribe.assert_any_call(interactor_.enable_control, "base_enable_control"), + pub_mock.subscribe.assert_any_call(interactor_.set_label, "base_set_label"), + pub_mock.subscribe.assert_any_call(interactor_.focus_control, "base_focus_control") + # Now, simulate some event calls. + interactor_.disable_control(control="some_control") + view.disable.assert_called_with("some_control") + interactor_.enable_control(control="some_control") + view.enable.assert_called_with("some_control") + interactor_.set_label(control="some_control", label="label") + view.set.assert_called_with("some_control", "label") + interactor_.focus_control(control="some_control") + view.some_control.SetFocus.assert_called_with() + interactor_.uninstall() + pub_mock.unsubscribe.assert_any_call(interactor_.disable_control, "base_disable_control"), + pub_mock.unsubscribe.assert_any_call(interactor_.enable_control, "base_enable_control"), + pub_mock.unsubscribe.assert_any_call(interactor_.set_label, "base_set_label"), + pub_mock.unsubscribe.assert_any_call(interactor_.focus_control, "base_focus_control") if __name__ == "__main__": - unittest.main() \ No newline at end of file + unittest.main() diff --git a/src/test/test_renderers.py b/src/test/test_renderers.py index 716c665..a4b18bb 100644 --- a/src/test/test_renderers.py +++ b/src/test/test_renderers.py @@ -7,22 +7,22 @@ from sessionmanager import renderers class renderersTestCase(unittest.TestCase): - def setUp(self): - languageHandler.setLanguage("en") - vk = testconfig.get_vk() - self.vk = vk.get_api() + def setUp(self): + languageHandler.setLanguage("en") + vk = testconfig.get_vk() + self.vk = vk.get_api() - def test_render_person(self): - """ Test the person renderer function.""" - user = self.vk.users.get(user_ids=1, fields="first_name, last_name, last_seen") - self.assertIsInstance(user, list) - self.assertEquals(len(user), 1) - user = user[0] - rendered_object = renderers.render_person(user, user["last_seen"]) - self.assertIsInstance(rendered_object, list) - self.assertEquals(len(rendered_object), 2) - self.assertIsInstance(rendered_object[0], str) - self.assertIsInstance(rendered_object[1], str) + def test_render_person(self): + """ Test the person renderer function.""" + user = self.vk.users.get(user_ids=1, fields="first_name, last_name, last_seen") + self.assertIsInstance(user, list) + self.assertEquals(len(user), 1) + user = user[0] + rendered_object = renderers.render_person(user, user["last_seen"]) + self.assertIsInstance(rendered_object, list) + self.assertEquals(len(rendered_object), 2) + self.assertIsInstance(rendered_object[0], str) + self.assertIsInstance(rendered_object[1], str) if __name__ == "__main__": - unittest.main() \ No newline at end of file + unittest.main() diff --git a/src/test/test_setup_py2exe.py b/src/test/test_setup_py2exe.py index 762a1f9..bedfe10 100644 --- a/src/test/test_setup_py2exe.py +++ b/src/test/test_setup_py2exe.py @@ -4,14 +4,14 @@ import application class py2exeTestCase(unittest.TestCase): - @unittest.skipUnless(sys.version[0] == "2", "this only fails under Python 2") - def test_application_not_unicode(self): - """ Testing if some strings present in application have not changed to unicode. """ - self.assertIsInstance(application.name, str) - self.assertIsInstance(application.author, str) - self.assertIsInstance(application.authorEmail, str) - self.assertIsInstance(application.version, str) - self.assertIsInstance(application.url, str) + @unittest.skipUnless(sys.version[0] == "2", "this only fails under Python 2") + def test_application_not_unicode(self): + """ Testing if some strings present in application have not changed to unicode. """ + self.assertIsInstance(application.name, str) + self.assertIsInstance(application.author, str) + self.assertIsInstance(application.authorEmail, str) + self.assertIsInstance(application.version, str) + self.assertIsInstance(application.url, str) if __name__ == "__main__": - unittest.main() \ No newline at end of file + unittest.main() diff --git a/src/test/testconfig.py b/src/test/testconfig.py index 94fd0be..0017ab5 100644 --- a/src/test/testconfig.py +++ b/src/test/testconfig.py @@ -3,8 +3,8 @@ import os from vk_api import VkApi def get_vk(): - login = os.environ['LOGIN'] - password = os.environ['PASSWORD'] - vk = VkApi(login, password) - vk.auth(token_only=True) - return vk \ No newline at end of file + login = os.environ['LOGIN'] + password = os.environ['PASSWORD'] + vk = VkApi(login, password) + vk.auth(token_only=True) + return vk diff --git a/src/update/__init__.py b/src/update/__init__.py index cff6566..5b99436 100644 --- a/src/update/__init__.py +++ b/src/update/__init__.py @@ -3,10 +3,10 @@ import os.path import platform def find_datafiles(): - system = platform.system() - if system == 'Windows': - file_ext = '*.exe' - else: - file_ext = '*.sh' - path = os.path.abspath(os.path.join(__path__[0], 'bootstrappers', file_ext)) - return [('', glob.glob(path))] + system = platform.system() + if system == 'Windows': + file_ext = '*.exe' + else: + file_ext = '*.sh' + path = os.path.abspath(os.path.join(__path__[0], 'bootstrappers', file_ext)) + return [('', glob.glob(path))] diff --git a/src/update/update.py b/src/update/update.py index 08e6d8d..e29d9cb 100644 --- a/src/update/update.py +++ b/src/update/update.py @@ -11,123 +11,123 @@ import tempfile import widgetUtils import webbrowser try: - import czipfile as zipfile + import czipfile as zipfile except ImportError: - import zipfile + import zipfile from platform_utils import paths def perform_update(endpoint, current_version, update_type="stable", app_name='', password=None, update_available_callback=None, progress_callback=None, update_complete_callback=None): - requests_session = create_requests_session(app_name=app_name, version=current_version) - available_update = find_update(endpoint, requests_session=requests_session) - if not available_update: - logger.debug("No update available") - return False - available_version, available_description, update_url = find_version_data(update_type, current_version, available_update) - if available_version == False: - return False - logger.info("A new update is available. Version %s" % available_version) - if callable(update_available_callback) and not update_available_callback(version=available_version, description=available_description): #update_available_callback should return a falsy value to stop the process - logger.info("User canceled update.") - return - base_path = tempfile.mkdtemp() - download_path = os.path.join(base_path, 'update.zip') - update_path = os.path.join(base_path, 'update') - downloaded = download_update(update_url, download_path, requests_session=requests_session, progress_callback=progress_callback) - extracted = extract_update(downloaded, update_path, password=password) - bootstrap_path = move_bootstrap(extracted) - execute_bootstrap(bootstrap_path, extracted) - logger.info("Update prepared for installation.") - if callable(update_complete_callback): - update_complete_callback() + requests_session = create_requests_session(app_name=app_name, version=current_version) + available_update = find_update(endpoint, requests_session=requests_session) + if not available_update: + logger.debug("No update available") + return False + available_version, available_description, update_url = find_version_data(update_type, current_version, available_update) + if available_version == False: + return False + logger.info("A new update is available. Version %s" % available_version) + if callable(update_available_callback) and not update_available_callback(version=available_version, description=available_description): #update_available_callback should return a falsy value to stop the process + logger.info("User canceled update.") + return + base_path = tempfile.mkdtemp() + download_path = os.path.join(base_path, 'update.zip') + update_path = os.path.join(base_path, 'update') + downloaded = download_update(update_url, download_path, requests_session=requests_session, progress_callback=progress_callback) + extracted = extract_update(downloaded, update_path, password=password) + bootstrap_path = move_bootstrap(extracted) + execute_bootstrap(bootstrap_path, extracted) + logger.info("Update prepared for installation.") + if callable(update_complete_callback): + update_complete_callback() def create_requests_session(app_name=None, version=None): - user_agent = '' - session = requests.session() - if app_name: - user_agent = ' %s/%r' % (app_name, version) - session.headers['User-Agent'] = session.headers['User-Agent'] + user_agent - return session + user_agent = '' + session = requests.session() + if app_name: + user_agent = ' %s/%r' % (app_name, version) + session.headers['User-Agent'] = session.headers['User-Agent'] + user_agent + return session def find_update(endpoint, requests_session): - response = requests_session.get(endpoint) - response.raise_for_status() - content = response.json() - return content + response = requests_session.get(endpoint) + response.raise_for_status() + content = response.json() + return content def find_version_data(update_type, current_version, available_update): - if update_type == "stable": - available_version = float(available_update['current_version']) - if not float(available_version) > float(current_version) or platform.system()+platform.architecture()[0][:2] not in available_update['downloads']: - logger.debug("No update for this architecture") - return (False, False, False) - available_description = available_update.get('description', None) - update_url = available_update ['downloads'][platform.system()+platform.architecture()[0][:2]] - return (available_version, available_description, update_url) - else: # Unstable versions, based in commits instead of version numbers. - available_version = available_update["current_version"] - if available_version == current_version: - return (False, False, False) - available_description = available_update["description"] - update_url = available_update ['downloads'][platform.system()+platform.architecture()[0][:2]] - return (available_version, available_description, update_url) + if update_type == "stable": + available_version = float(available_update['current_version']) + if not float(available_version) > float(current_version) or platform.system()+platform.architecture()[0][:2] not in available_update['downloads']: + logger.debug("No update for this architecture") + return (False, False, False) + available_description = available_update.get('description', None) + update_url = available_update ['downloads'][platform.system()+platform.architecture()[0][:2]] + return (available_version, available_description, update_url) + else: # Unstable versions, based in commits instead of version numbers. + available_version = available_update["current_version"] + if available_version == current_version: + return (False, False, False) + available_description = available_update["description"] + update_url = available_update ['downloads'][platform.system()+platform.architecture()[0][:2]] + return (available_version, available_description, update_url) def download_update(update_url, update_destination, requests_session, progress_callback=None, chunk_size=io.DEFAULT_BUFFER_SIZE): - total_downloaded = total_size = 0 - with io.open(update_destination, 'w+b') as outfile: - download = requests_session.get(update_url, stream=True) - total_size = int(download.headers.get('content-length', 0)) - logger.debug("Total update size: %d" % total_size) - download.raise_for_status() - for chunk in download.iter_content(chunk_size): - outfile.write(chunk) - total_downloaded += len(chunk) - if callable(progress_callback): - call_callback(progress_callback, total_downloaded, total_size) - logger.debug("Update downloaded") - return update_destination + total_downloaded = total_size = 0 + with io.open(update_destination, 'w+b') as outfile: + download = requests_session.get(update_url, stream=True) + total_size = int(download.headers.get('content-length', 0)) + logger.debug("Total update size: %d" % total_size) + download.raise_for_status() + for chunk in download.iter_content(chunk_size): + outfile.write(chunk) + total_downloaded += len(chunk) + if callable(progress_callback): + call_callback(progress_callback, total_downloaded, total_size) + logger.debug("Update downloaded") + return update_destination def extract_update(update_archive, destination, password=None): - """Given an update archive, extracts it. Returns the directory to which it has been extracted""" - with contextlib.closing(zipfile.ZipFile(update_archive)) as archive: - if password: - archive.setpassword(password) - archive.extractall(path=destination) - logger.debug("Update extracted") - return destination + """Given an update archive, extracts it. Returns the directory to which it has been extracted""" + with contextlib.closing(zipfile.ZipFile(update_archive)) as archive: + if password: + archive.setpassword(password) + archive.extractall(path=destination) + logger.debug("Update extracted") + return destination def move_bootstrap(extracted_path): - working_path = os.path.abspath(os.path.join(extracted_path, '..')) - if platform.system() == 'Darwin': - extracted_path = os.path.join(extracted_path, 'Contents', 'Resources') - downloaded_bootstrap = os.path.join(extracted_path, bootstrap_name()) - new_bootstrap_path = os.path.join(working_path, bootstrap_name()) - os.rename(downloaded_bootstrap, new_bootstrap_path) - return new_bootstrap_path + working_path = os.path.abspath(os.path.join(extracted_path, '..')) + if platform.system() == 'Darwin': + extracted_path = os.path.join(extracted_path, 'Contents', 'Resources') + downloaded_bootstrap = os.path.join(extracted_path, bootstrap_name()) + new_bootstrap_path = os.path.join(working_path, bootstrap_name()) + os.rename(downloaded_bootstrap, new_bootstrap_path) + return new_bootstrap_path def execute_bootstrap(bootstrap_path, source_path): - arguments = r'"%s" "%s" "%s" "%s"' % (os.getpid(), source_path, paths.app_path(), paths.get_executable()) - if platform.system() == 'Windows': - import win32api - win32api.ShellExecute(0, 'open', bootstrap_path, arguments, '', 5) - else: - import subprocess - make_executable(bootstrap_path) - subprocess.Popen(['%s %s' % (bootstrap_path, arguments)], shell=True) - logger.info("Bootstrap executed") + arguments = r'"%s" "%s" "%s" "%s"' % (os.getpid(), source_path, paths.app_path(), paths.get_executable()) + if platform.system() == 'Windows': + import win32api + win32api.ShellExecute(0, 'open', bootstrap_path, arguments, '', 5) + else: + import subprocess + make_executable(bootstrap_path) + subprocess.Popen(['%s %s' % (bootstrap_path, arguments)], shell=True) + logger.info("Bootstrap executed") def bootstrap_name(): - if platform.system() == 'Windows': return 'bootstrap.exe' - if platform.system() == 'Darwin': return 'bootstrap-mac.sh' - return 'bootstrap-lin.sh' + if platform.system() == 'Windows': return 'bootstrap.exe' + if platform.system() == 'Darwin': return 'bootstrap-mac.sh' + return 'bootstrap-lin.sh' def make_executable(path): - import stat - st = os.stat(path) - os.chmod(path, st.st_mode | stat.S_IEXEC) + import stat + st = os.stat(path) + os.chmod(path, st.st_mode | stat.S_IEXEC) def call_callback(callback, *args, **kwargs): # try: - callback(*args, **kwargs) + callback(*args, **kwargs) # except: # logger.exception("Failed calling callback %r with args %r and kwargs %r" % (callback, args, kwargs)) diff --git a/src/update/updater.py b/src/update/updater.py index 8fb1af4..9283f65 100644 --- a/src/update/updater.py +++ b/src/update/updater.py @@ -10,17 +10,17 @@ from .wxUpdater import * logger = logging.getLogger("updater") def do_update(update_type="stable"): - # Updates cannot be performed in the source code version of Socializer. - if hasattr(sys, "frozen") == False: - return - if update_type == "stable": - endpoint = application.update_stable_url - version = application.version - else: - endpoint = application.update_next_url - version = application.update_next_version - try: - return update.perform_update(endpoint=endpoint, current_version=version, app_name=application.name, update_type=update_type, update_available_callback=available_update_dialog, progress_callback=progress_callback, update_complete_callback=update_finished) - except ConnectionError: - logger.exception("Update failed.") - output.speak("An exception occurred while attempting to update " + application.name + ". If this message persists, contact the " + application.name + " developers. More information about the exception has been written to the error log.",True) \ No newline at end of file + # Updates cannot be performed in the source code version of Socializer. + if hasattr(sys, "frozen") == False: + return + if update_type == "stable": + endpoint = application.update_stable_url + version = application.version + else: + endpoint = application.update_next_url + version = application.update_next_version + try: + return update.perform_update(endpoint=endpoint, current_version=version, app_name=application.name, update_type=update_type, update_available_callback=available_update_dialog, progress_callback=progress_callback, update_complete_callback=update_finished) + except ConnectionError: + logger.exception("Update failed.") + output.speak("An exception occurred while attempting to update " + application.name + ". If this message persists, contact the " + application.name + " developers. More information about the exception has been written to the error log.",True) diff --git a/src/update/utils.py b/src/update/utils.py index 386640b..0a6009f 100644 --- a/src/update/utils.py +++ b/src/update/utils.py @@ -2,42 +2,42 @@ from __future__ import unicode_literals def convert_bytes(n): - K, M, G, T, P = 1 << 10, 1 << 20, 1 << 30, 1 << 40, 1 << 50 - if n >= P: - return '%.2fPb' % (float(n) / T) - elif n >= T: - return '%.2fTb' % (float(n) / T) - elif n >= G: - return '%.2fGb' % (float(n) / G) - elif n >= M: - return '%.2fMb' % (float(n) / M) - elif n >= K: - return '%.2fKb' % (float(n) / K) - else: - return '%d' % n + K, M, G, T, P = 1 << 10, 1 << 20, 1 << 30, 1 << 40, 1 << 50 + if n >= P: + return '%.2fPb' % (float(n) / T) + elif n >= T: + return '%.2fTb' % (float(n) / T) + elif n >= G: + return '%.2fGb' % (float(n) / G) + elif n >= M: + return '%.2fMb' % (float(n) / M) + elif n >= K: + return '%.2fKb' % (float(n) / K) + else: + return '%d' % n def seconds_to_string(seconds, precision=0): - day = seconds // 86400 - hour = seconds // 3600 - min = (seconds // 60) % 60 - sec = seconds - (hour * 3600) - (min * 60) - sec_spec = "." + str(precision) + "f" - sec_string = sec.__format__(sec_spec) - string = "" - if day == 1: - string += _("%d day, ") % day - elif day >= 2: - string += _("%d days, ") % day - if (hour == 1): - string += _("%d hour, ") % hour - elif (hour >= 2): - string += _("%d hours, ") % hour - if (min == 1): - string += _("%d minute, ") % min - elif (min >= 2): - string += _("%d minutes, ") % min - if sec >= 0 and sec <= 2: - string += _("%s second") % sec_string - else: - string += _("%s seconds") % sec_string - return string \ No newline at end of file + day = seconds // 86400 + hour = seconds // 3600 + min = (seconds // 60) % 60 + sec = seconds - (hour * 3600) - (min * 60) + sec_spec = "." + str(precision) + "f" + sec_string = sec.__format__(sec_spec) + string = "" + if day == 1: + string += _("%d day, ") % day + elif day >= 2: + string += _("%d days, ") % day + if (hour == 1): + string += _("%d hour, ") % hour + elif (hour >= 2): + string += _("%d hours, ") % hour + if (min == 1): + string += _("%d minute, ") % min + elif (min >= 2): + string += _("%d minutes, ") % min + if sec >= 0 and sec <= 2: + string += _("%s second") % sec_string + else: + string += _("%s seconds") % sec_string + return string diff --git a/src/update/wxUpdater.py b/src/update/wxUpdater.py index 203aa01..ea30eba 100644 --- a/src/update/wxUpdater.py +++ b/src/update/wxUpdater.py @@ -8,27 +8,27 @@ from . import utils progress_dialog = None def available_update_dialog(version, description): - dialog = wx.MessageDialog(None, _("There's a new {app_name} version available. Would you like to download it now?\n\n {app_name} version: {app_version}\n\nChanges:\n{changes}").format(app_name=application.name, app_version=version, changes=description), _("New version for %s") % application.name, style=wx.YES|wx.NO|wx.ICON_WARNING) - if dialog.ShowModal() == wx.ID_YES: - return True - else: - return False + dialog = wx.MessageDialog(None, _("There's a new {app_name} version available. Would you like to download it now?\n\n {app_name} version: {app_version}\n\nChanges:\n{changes}").format(app_name=application.name, app_version=version, changes=description), _("New version for %s") % application.name, style=wx.YES|wx.NO|wx.ICON_WARNING) + if dialog.ShowModal() == wx.ID_YES: + return True + else: + return False def create_progress_dialog(): - return wx.ProgressDialog(_("Download in Progress"), _("Downloading the new version..."), parent=None, maximum=100) + return wx.ProgressDialog(_("Download in Progress"), _("Downloading the new version..."), parent=None, maximum=100) def progress_callback(total_downloaded, total_size): - wx.CallAfter(_progress_callback, total_downloaded, total_size) + wx.CallAfter(_progress_callback, total_downloaded, total_size) def _progress_callback(total_downloaded, total_size): - global progress_dialog - if progress_dialog == None: - progress_dialog = create_progress_dialog() - progress_dialog.Show() - if total_downloaded == total_size: - progress_dialog.Destroy() - else: - progress_dialog.Update((total_downloaded*100)/total_size, _("Updating... {total_transferred} of {total_size}").format(total_transferred=utils.convert_bytes(total_downloaded), total_size=utils.convert_bytes(total_size))) + global progress_dialog + if progress_dialog == None: + progress_dialog = create_progress_dialog() + progress_dialog.Show() + if total_downloaded == total_size: + progress_dialog.Destroy() + else: + progress_dialog.Update((total_downloaded*100)/total_size, _("Updating... {total_transferred} of {total_size}").format(total_transferred=utils.convert_bytes(total_downloaded), total_size=utils.convert_bytes(total_size))) def update_finished(): - return wx.MessageDialog(None, _("The update has been downloaded and installed successfully. Press OK to continue."), _("Done!")).ShowModal() \ No newline at end of file + return wx.MessageDialog(None, _("The update has been downloaded and installed successfully. Press OK to continue."), _("Done!")).ShowModal() diff --git a/src/views/__init__.py b/src/views/__init__.py index e74e40f..ba9f87b 100644 --- a/src/views/__init__.py +++ b/src/views/__init__.py @@ -1,7 +1,7 @@ """ Views package for socializer. A view is the Graphical user interface in the application. This package includes everything needed to render a window. - No other functionality is assumed in this package. - All modules from here should be used via an interactor (read description of the interactors package). - Interactors will be routing user events (like buttons pressed, menus activated and so on) to presenter functions. + No other functionality is assumed in this package. + All modules from here should be used via an interactor (read description of the interactors package). + Interactors will be routing user events (like buttons pressed, menus activated and so on) to presenter functions. """ from .dialogs.attach import * from .dialogs.audioRecorder import * @@ -9,4 +9,4 @@ from .dialogs.blacklist import * from .dialogs.postCreation import * from .dialogs.postDisplay import * from .dialogs.configuration import * -from .dialogs.profiles import * \ No newline at end of file +from .dialogs.profiles import * diff --git a/src/views/dialogs/attach.py b/src/views/dialogs/attach.py index 51383a0..4a390a6 100644 --- a/src/views/dialogs/attach.py +++ b/src/views/dialogs/attach.py @@ -4,65 +4,65 @@ import wx import widgetUtils class attachDialog(widgetUtils.BaseDialog): - def __init__(self, voice_messages=False): - super(attachDialog, self).__init__(None, title=_("Add an attachment")) - panel = wx.Panel(self) - sizer = wx.BoxSizer(wx.VERTICAL) - lbl1 = wx.StaticText(panel, wx.NewId(), _("Attachments")) - self.attachments = widgetUtils.list(panel, _("Type"), _("Title"), style=wx.LC_REPORT) - box = wx.BoxSizer(wx.HORIZONTAL) - box.Add(lbl1, 0, wx.ALL, 5) - box.Add(self.attachments.list, 0, wx.ALL, 5) - sizer.Add(box, 0, wx.ALL, 5) - static = wx.StaticBoxSizer(parent=panel, orient=wx.HORIZONTAL, label=_("Add attachments")) - self.photo = wx.Button(static.GetStaticBox(), wx.NewId(), _("&Photo")) - self.audio = wx.Button(static.GetStaticBox(), wx.NewId(), _("Audio file")) - self.document = wx.Button(static.GetStaticBox(), wx.NewId(), _("Document")) - if voice_messages: - self.voice_message = wx.Button(static.GetStaticBox(), wx.NewId(), _("Voice message")) - self.remove = wx.Button(static.GetStaticBox(), wx.NewId(), _("Remove attachment")) - self.remove.Enable(False) - static.Add(self.photo, 0, wx.ALL, 5) - static.Add(self.audio, 0, wx.ALL, 5) - static.Add(self.document, 0, wx.ALL, 5) - if voice_messages: - static.Add(self.voice_message, 0, wx.ALL, 5) - sizer.Add(static, 0, wx.ALL, 5) - ok = wx.Button(panel, wx.ID_OK) - ok.SetDefault() - cancelBtn = wx.Button(panel, wx.ID_CANCEL) - btnSizer = wx.BoxSizer() - btnSizer.Add(ok, 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 __init__(self, voice_messages=False): + super(attachDialog, self).__init__(None, title=_("Add an attachment")) + panel = wx.Panel(self) + sizer = wx.BoxSizer(wx.VERTICAL) + lbl1 = wx.StaticText(panel, wx.NewId(), _("Attachments")) + self.attachments = widgetUtils.list(panel, _("Type"), _("Title"), style=wx.LC_REPORT) + box = wx.BoxSizer(wx.HORIZONTAL) + box.Add(lbl1, 0, wx.ALL, 5) + box.Add(self.attachments.list, 0, wx.ALL, 5) + sizer.Add(box, 0, wx.ALL, 5) + static = wx.StaticBoxSizer(parent=panel, orient=wx.HORIZONTAL, label=_("Add attachments")) + self.photo = wx.Button(static.GetStaticBox(), wx.NewId(), _("&Photo")) + self.audio = wx.Button(static.GetStaticBox(), wx.NewId(), _("Audio file")) + self.document = wx.Button(static.GetStaticBox(), wx.NewId(), _("Document")) + if voice_messages: + self.voice_message = wx.Button(static.GetStaticBox(), wx.NewId(), _("Voice message")) + self.remove = wx.Button(static.GetStaticBox(), wx.NewId(), _("Remove attachment")) + self.remove.Enable(False) + static.Add(self.photo, 0, wx.ALL, 5) + static.Add(self.audio, 0, wx.ALL, 5) + static.Add(self.document, 0, wx.ALL, 5) + if voice_messages: + static.Add(self.voice_message, 0, wx.ALL, 5) + sizer.Add(static, 0, wx.ALL, 5) + ok = wx.Button(panel, wx.ID_OK) + ok.SetDefault() + cancelBtn = wx.Button(panel, wx.ID_CANCEL) + btnSizer = wx.BoxSizer() + btnSizer.Add(ok, 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 get_image(self): - openFileDialog = wx.FileDialog(self, _("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_image(self): + openFileDialog = wx.FileDialog(self, _("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 ask_description(self): - dlg = wx.TextEntryDialog(self, _("please provide a description"), _("Description")) - dlg.ShowModal() - result = dlg.GetValue() - dlg.Destroy() - return result + def ask_description(self): + dlg = wx.TextEntryDialog(self, _("please provide a description"), _("Description")) + dlg.ShowModal() + result = dlg.GetValue() + dlg.Destroy() + return result - def get_audio(self): - openFileDialog = wx.FileDialog(self, _("Select the audio file to be uploaded"), "", "", _("Audio files (*.mp3)|*.mp3"), 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)|*.mp3"), wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) + if openFileDialog.ShowModal() == wx.ID_CANCEL: + return None + return openFileDialog.GetPath() - def get_document(self): - openFileDialog = wx.FileDialog(self, _("Select the file to be uploaded. All extensions are allowed except .mp3 and .exe."), "", "", _("All files (*.*)|*.*"), wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) - if openFileDialog.ShowModal() == wx.ID_CANCEL: - return None - return openFileDialog.GetPath() + def get_document(self): + openFileDialog = wx.FileDialog(self, _("Select the file to be uploaded. All extensions are allowed except .mp3 and .exe."), "", "", _("All files (*.*)|*.*"), wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) + if openFileDialog.ShowModal() == wx.ID_CANCEL: + return None + return openFileDialog.GetPath() - def invalid_attachment(self): - return wx.MessageDialog(None, _("The file you are trying to upload contains an extension that is not allowed by VK."), _("Error"), style=wx.ICON_ERROR).ShowModal() \ No newline at end of file + def invalid_attachment(self): + return wx.MessageDialog(None, _("The file you are trying to upload contains an extension that is not allowed by VK."), _("Error"), style=wx.ICON_ERROR).ShowModal() diff --git a/src/views/dialogs/audioRecorder.py b/src/views/dialogs/audioRecorder.py index 5c05e07..2eaef74 100644 --- a/src/views/dialogs/audioRecorder.py +++ b/src/views/dialogs/audioRecorder.py @@ -4,33 +4,33 @@ import wx import widgetUtils class audioRecorderDialog(widgetUtils.BaseDialog): - def __init__(self): - super(audioRecorderDialog, self).__init__(None, title=_("Record voice message")) - panel = wx.Panel(self) - sizer = wx.BoxSizer(wx.VERTICAL) - self.play = wx.Button(panel, -1, _("&Play")) - self.play.Disable() - self.record = wx.Button(panel, -1, _("&Record")) - self.record.SetFocus() - self.discard = wx.Button(panel, -1, _("&Discard")) - self.discard.Disable() - self.ok = wx.Button(panel, wx.ID_OK, _("&Add")) - cancel = wx.Button(panel, wx.ID_CANCEL, _("&Cancel")) - btnSizer = wx.BoxSizer(wx.HORIZONTAL) - btnSizer2 = wx.BoxSizer(wx.HORIZONTAL) - btnSizer.Add(self.play, 0, wx.ALL, 5) - btnSizer.Add(self.record, 0, wx.ALL, 5) - btnSizer2.Add(self.ok, 0, wx.ALL, 5) - btnSizer2.Add(cancel, 0, wx.ALL, 5) - sizer.Add(btnSizer, 0, wx.ALL, 5) - sizer.Add(btnSizer2, 0, wx.ALL, 5) - panel.SetSizer(sizer) - self.SetClientSize(sizer.CalcMin()) + def __init__(self): + super(audioRecorderDialog, self).__init__(None, title=_("Record voice message")) + panel = wx.Panel(self) + sizer = wx.BoxSizer(wx.VERTICAL) + self.play = wx.Button(panel, -1, _("&Play")) + self.play.Disable() + self.record = wx.Button(panel, -1, _("&Record")) + self.record.SetFocus() + self.discard = wx.Button(panel, -1, _("&Discard")) + self.discard.Disable() + self.ok = wx.Button(panel, wx.ID_OK, _("&Add")) + cancel = wx.Button(panel, wx.ID_CANCEL, _("&Cancel")) + btnSizer = wx.BoxSizer(wx.HORIZONTAL) + btnSizer2 = wx.BoxSizer(wx.HORIZONTAL) + btnSizer.Add(self.play, 0, wx.ALL, 5) + btnSizer.Add(self.record, 0, wx.ALL, 5) + btnSizer2.Add(self.ok, 0, wx.ALL, 5) + btnSizer2.Add(cancel, 0, wx.ALL, 5) + sizer.Add(btnSizer, 0, wx.ALL, 5) + sizer.Add(btnSizer2, 0, wx.ALL, 5) + panel.SetSizer(sizer) + self.SetClientSize(sizer.CalcMin()) - def enable_control(self, control): - if hasattr(self, control): - getattr(self, control).Enable() + def enable_control(self, control): + if hasattr(self, control): + getattr(self, control).Enable() - def disable_control(self, control): - if hasattr(self, control): - getattr(self, control).Disable() \ No newline at end of file + def disable_control(self, control): + if hasattr(self, control): + getattr(self, control).Disable() diff --git a/src/views/dialogs/blacklist.py b/src/views/dialogs/blacklist.py index 3e086c1..fd57a0f 100644 --- a/src/views/dialogs/blacklist.py +++ b/src/views/dialogs/blacklist.py @@ -3,17 +3,17 @@ import wx import widgetUtils class blacklistDialog(widgetUtils.BaseDialog): - def __init__(self): - super(blacklistDialog, self).__init__(parent=None, title=_("blacklist")) - panel = wx.Panel(self) - sizer = wx.BoxSizer(wx.VERTICAL) - box1 = wx.StaticBoxSizer(parent=panel, orient=wx.HORIZONTAL, label=_("blocked users")) - self.persons = widgetUtils.list(panel, _("User"), style=wx.LC_REPORT) - box1.Add(self.persons.list, 0, wx.ALL, 5) - sizer.Add(box1, 0, wx.ALL, 5) - self.unblock = wx.Button(panel, wx.NewId(), _("Unblock")) - sizer.Add(self.unblock, 0, wx.ALL, 5) - close = wx.Button(panel, wx.ID_CANCEL, _("Close")) - sizer.Add(close, 0, wx.ALL, 5) - panel.SetSizer(sizer) - self.SetClientSize(sizer.CalcMin()) + def __init__(self): + super(blacklistDialog, self).__init__(parent=None, title=_("blacklist")) + panel = wx.Panel(self) + sizer = wx.BoxSizer(wx.VERTICAL) + box1 = wx.StaticBoxSizer(parent=panel, orient=wx.HORIZONTAL, label=_("blocked users")) + self.persons = widgetUtils.list(panel, _("User"), style=wx.LC_REPORT) + box1.Add(self.persons.list, 0, wx.ALL, 5) + sizer.Add(box1, 0, wx.ALL, 5) + self.unblock = wx.Button(panel, wx.NewId(), _("Unblock")) + sizer.Add(self.unblock, 0, wx.ALL, 5) + close = wx.Button(panel, wx.ID_CANCEL, _("Close")) + sizer.Add(close, 0, wx.ALL, 5) + panel.SetSizer(sizer) + self.SetClientSize(sizer.CalcMin()) diff --git a/src/views/dialogs/configuration.py b/src/views/dialogs/configuration.py index 0726c16..0b60923 100644 --- a/src/views/dialogs/configuration.py +++ b/src/views/dialogs/configuration.py @@ -4,179 +4,179 @@ import wx import widgetUtils class general(wx.Panel, widgetUtils.BaseDialog): - def __init__(self, panel, languages): - super(general, self).__init__(panel) - sizer = wx.BoxSizer(wx.VERTICAL) - langBox = wx.StaticBoxSizer(parent=self, orient=wx.HORIZONTAL, label=_("Language")) - self.language = wx.ListBox(langBox.GetStaticBox(), wx.NewId(), choices=languages) - self.language.SetSize(self.language.GetBestSize()) - langBox.Add(self.language, 0, wx.ALL, 5) - sizer.Add(langBox, 0, wx.ALL, 5) - self.load_images = wx.CheckBox(self, wx.NewId(), _("Load images in posts")) - sizer.Add(self.load_images, 0, wx.ALL, 5) - self.use_proxy = wx.CheckBox(self, wx.NewId(), _("Use proxy")) - sizer.Add(self.use_proxy, 0, wx.ALL, 5) - self.debug_logging = wx.CheckBox(self, wx.NewId(), _("Enable debug logging (useful for reporting errors)")) - sizer.Add(self.debug_logging, 0, wx.ALL, 5) - lbl4 = wx.StaticText(self, wx.NewId(), _("Update channel")) - self.update_channel = wx.ComboBox(self, wx.NewId(), choices=[_("Stable"), _("Alpha")], value=_("Native"), style=wx.CB_READONLY) - box4 = wx.BoxSizer(wx.HORIZONTAL) - box4.Add(lbl4, 0, wx.ALL, 5) - box4.Add(self.update_channel, 0, wx.ALL, 5) - sizer.Add(box4, 0, wx.ALL, 5) - self.SetSizer(sizer) + def __init__(self, panel, languages): + super(general, self).__init__(panel) + sizer = wx.BoxSizer(wx.VERTICAL) + langBox = wx.StaticBoxSizer(parent=self, orient=wx.HORIZONTAL, label=_("Language")) + self.language = wx.ListBox(langBox.GetStaticBox(), wx.NewId(), choices=languages) + self.language.SetSize(self.language.GetBestSize()) + langBox.Add(self.language, 0, wx.ALL, 5) + sizer.Add(langBox, 0, wx.ALL, 5) + self.load_images = wx.CheckBox(self, wx.NewId(), _("Load images in posts")) + sizer.Add(self.load_images, 0, wx.ALL, 5) + self.use_proxy = wx.CheckBox(self, wx.NewId(), _("Use proxy")) + sizer.Add(self.use_proxy, 0, wx.ALL, 5) + self.debug_logging = wx.CheckBox(self, wx.NewId(), _("Enable debug logging (useful for reporting errors)")) + sizer.Add(self.debug_logging, 0, wx.ALL, 5) + lbl4 = wx.StaticText(self, wx.NewId(), _("Update channel")) + self.update_channel = wx.ComboBox(self, wx.NewId(), choices=[_("Stable"), _("Alpha")], value=_("Native"), style=wx.CB_READONLY) + box4 = wx.BoxSizer(wx.HORIZONTAL) + box4.Add(lbl4, 0, wx.ALL, 5) + box4.Add(self.update_channel, 0, wx.ALL, 5) + sizer.Add(box4, 0, wx.ALL, 5) + self.SetSizer(sizer) class buffers(wx.Panel, widgetUtils.BaseDialog): - def __init__(self, panel): - super(buffers, self).__init__(panel) - sizer = wx.BoxSizer(wx.VERTICAL) - lbl1 = wx.StaticText(self, wx.NewId(), _("Number of items to load for newsfeed and wall buffers (maximun 100)")) - self.wall_buffer_count = wx.SpinCtrl(self, wx.NewId()) - self.wall_buffer_count.SetRange(1, 100) - box1 = wx.BoxSizer(wx.HORIZONTAL) - box1.Add(lbl1, 0, wx.ALL, 5) - box1.Add(self.wall_buffer_count, 0, wx.ALL, 5) - sizer.Add(box1, 0, wx.ALL, 5) - lbl3 = wx.StaticText(self, wx.NewId(), _("Number of items to load in video buffers (maximun 200)")) - self.video_buffers_count = wx.SpinCtrl(self, wx.NewId()) - self.video_buffers_count.SetRange(1, 200) - box3 = wx.BoxSizer(wx.HORIZONTAL) - box3.Add(lbl3, 0, wx.ALL, 5) - box3.Add(self.video_buffers_count, 0, wx.ALL, 5) - sizer.Add(box3, 0, wx.ALL, 5) - lbl4 = wx.StaticText(self, wx.NewId(), _("Number of items to load in conversation buffers (maximun 200)")) - self.chat_buffers_count = wx.SpinCtrl(self, wx.NewId()) - self.chat_buffers_count.SetRange(1, 200) - box4 = wx.BoxSizer(wx.HORIZONTAL) - box4.Add(lbl4, 0, wx.ALL, 5) - box4.Add(self.chat_buffers_count, 0, wx.ALL, 5) - sizer.Add(box4, 0, wx.ALL, 5) - self.SetSizer(sizer) + def __init__(self, panel): + super(buffers, self).__init__(panel) + sizer = wx.BoxSizer(wx.VERTICAL) + lbl1 = wx.StaticText(self, wx.NewId(), _("Number of items to load for newsfeed and wall buffers (maximun 100)")) + self.wall_buffer_count = wx.SpinCtrl(self, wx.NewId()) + self.wall_buffer_count.SetRange(1, 100) + box1 = wx.BoxSizer(wx.HORIZONTAL) + box1.Add(lbl1, 0, wx.ALL, 5) + box1.Add(self.wall_buffer_count, 0, wx.ALL, 5) + sizer.Add(box1, 0, wx.ALL, 5) + lbl3 = wx.StaticText(self, wx.NewId(), _("Number of items to load in video buffers (maximun 200)")) + self.video_buffers_count = wx.SpinCtrl(self, wx.NewId()) + self.video_buffers_count.SetRange(1, 200) + box3 = wx.BoxSizer(wx.HORIZONTAL) + box3.Add(lbl3, 0, wx.ALL, 5) + box3.Add(self.video_buffers_count, 0, wx.ALL, 5) + sizer.Add(box3, 0, wx.ALL, 5) + lbl4 = wx.StaticText(self, wx.NewId(), _("Number of items to load in conversation buffers (maximun 200)")) + self.chat_buffers_count = wx.SpinCtrl(self, wx.NewId()) + self.chat_buffers_count.SetRange(1, 200) + box4 = wx.BoxSizer(wx.HORIZONTAL) + box4.Add(lbl4, 0, wx.ALL, 5) + box4.Add(self.chat_buffers_count, 0, wx.ALL, 5) + sizer.Add(box4, 0, wx.ALL, 5) + self.SetSizer(sizer) class chat(wx.Panel, widgetUtils.BaseDialog): - def __init__(self, panel): - super(chat, self).__init__(panel) - sizer = wx.BoxSizer(wx.VERTICAL) - self.notify_online = wx.CheckBox(self, wx.NewId(), _("Show notifications when users are online")) - sizer.Add(self.notify_online, 0, wx.ALL, 5) - self.notify_offline = wx.CheckBox(self, wx.NewId(), _("Show notifications when users are offline")) - sizer.Add(self.notify_offline, 0, wx.ALL, 5) - lbl = wx.StaticText(self, wx.NewId(), _("Notification type")) - self.notifications = wx.ComboBox(self, wx.NewId(), choices=[_("Native"), _("Custom"),], value=_("Native"), style=wx.CB_READONLY) - nbox = wx.BoxSizer(wx.HORIZONTAL) - nbox.Add(lbl, 0, wx.ALL, 5) - nbox.Add(self.notifications, 0, wx.ALL, 5) - sizer.Add(nbox, 0, wx.ALL, 5) - self.SetSizer(sizer) + def __init__(self, panel): + super(chat, self).__init__(panel) + sizer = wx.BoxSizer(wx.VERTICAL) + self.notify_online = wx.CheckBox(self, wx.NewId(), _("Show notifications when users are online")) + sizer.Add(self.notify_online, 0, wx.ALL, 5) + self.notify_offline = wx.CheckBox(self, wx.NewId(), _("Show notifications when users are offline")) + sizer.Add(self.notify_offline, 0, wx.ALL, 5) + lbl = wx.StaticText(self, wx.NewId(), _("Notification type")) + self.notifications = wx.ComboBox(self, wx.NewId(), choices=[_("Native"), _("Custom"),], value=_("Native"), style=wx.CB_READONLY) + nbox = wx.BoxSizer(wx.HORIZONTAL) + nbox.Add(lbl, 0, wx.ALL, 5) + nbox.Add(self.notifications, 0, wx.ALL, 5) + sizer.Add(nbox, 0, wx.ALL, 5) + self.SetSizer(sizer) class loadAtStartup(wx.Panel, widgetUtils.BaseDialog): - def __init__(self, panel): - super(loadAtStartup, self).__init__(panel) - sizer = wx.BoxSizer(wx.VERTICAL) - self.audio_albums = wx.CheckBox(self, wx.NewId(), _("Create buffers for audio albums at startup")) - sizer.Add(self.audio_albums, 0, wx.ALL, 5) - self.video_albums = wx.CheckBox(self, wx.NewId(), _("Create buffers for video albums at startup")) - sizer.Add(self.video_albums, 0, wx.ALL, 5) - self.communities = wx.CheckBox(self, wx.NewId(), _("Create buffers for communities and public pages at startup")) - sizer.Add(self.communities, 0, wx.ALL, 5) - self.SetSizer(sizer) + def __init__(self, panel): + super(loadAtStartup, self).__init__(panel) + sizer = wx.BoxSizer(wx.VERTICAL) + self.audio_albums = wx.CheckBox(self, wx.NewId(), _("Create buffers for audio albums at startup")) + sizer.Add(self.audio_albums, 0, wx.ALL, 5) + self.video_albums = wx.CheckBox(self, wx.NewId(), _("Create buffers for video albums at startup")) + sizer.Add(self.video_albums, 0, wx.ALL, 5) + self.communities = wx.CheckBox(self, wx.NewId(), _("Create buffers for communities and public pages at startup")) + sizer.Add(self.communities, 0, wx.ALL, 5) + self.SetSizer(sizer) class sound(wx.Panel, widgetUtils.BaseDialog): - def __init__(self, panel, input_devices, output_devices, soundpacks): - super(sound, self).__init__(panel) - sizer = wx.BoxSizer(wx.VERTICAL) - output_label = wx.StaticText(self, wx.NewId(), _("Output device")) - self.output = wx.ComboBox(self, wx.NewId(), 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, wx.NewId(), _("Input device")) - self.input = wx.ComboBox(self, wx.NewId(), 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, wx.NewId(), _(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.SetSizer(sizer) + def __init__(self, panel, input_devices, output_devices, soundpacks): + super(sound, self).__init__(panel) + sizer = wx.BoxSizer(wx.VERTICAL) + output_label = wx.StaticText(self, wx.NewId(), _("Output device")) + self.output = wx.ComboBox(self, wx.NewId(), 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, wx.NewId(), _("Input device")) + self.input = wx.ComboBox(self, wx.NewId(), 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, wx.NewId(), _(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.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 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() + def get(self, control): + return getattr(self, control).GetStringSelection() class configurationDialog(widgetUtils.BaseDialog): - def __init__(self, title): - super(configurationDialog, self).__init__(None, -1, title=title) - self.panel = wx.Panel(self) - self.sizer = wx.BoxSizer(wx.VERTICAL) - self.notebook = wx.Notebook(self.panel) + def __init__(self, title): + super(configurationDialog, self).__init__(None, -1, title=title) + self.panel = wx.Panel(self) + self.sizer = wx.BoxSizer(wx.VERTICAL) + self.notebook = wx.Notebook(self.panel) - def create_general(self, languages): - self.general = general(self.notebook, languages) - self.notebook.AddPage(self.general, _("General")) - self.general.SetFocus() + def create_general(self, languages): + self.general = general(self.notebook, languages) + self.notebook.AddPage(self.general, _("General")) + self.general.SetFocus() - def create_buffers(self): - self.buffers = buffers(self.notebook) - self.notebook.AddPage(self.buffers, _("Buffer settings")) + def create_buffers(self): + self.buffers = buffers(self.notebook) + self.notebook.AddPage(self.buffers, _("Buffer settings")) - def create_chat(self): - self.chat = chat(self.notebook) - self.notebook.AddPage(self.chat, _("Chat settings")) + def create_chat(self): + self.chat = chat(self.notebook) + self.notebook.AddPage(self.chat, _("Chat settings")) - def create_startup_options(self): - self.startup = loadAtStartup(self.notebook) - self.notebook.AddPage(self.startup, _("Optional buffers")) + def create_startup_options(self): + self.startup = loadAtStartup(self.notebook) + self.notebook.AddPage(self.startup, _("Optional buffers")) - def create_sound(self, input_devices, output_devices, soundpacks): - self.sound = sound(self.notebook, input_devices, output_devices, soundpacks) - self.notebook.AddPage(self.sound, _("Sound settings")) + def create_sound(self, input_devices, output_devices, soundpacks): + self.sound = sound(self.notebook, input_devices, output_devices, soundpacks) + self.notebook.AddPage(self.sound, _("Sound settings")) - 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, _("Save")) - ok.SetDefault() - cancel = wx.Button(self.panel, wx.ID_CANCEL, _("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 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, _("Save")) + ok.SetDefault() + cancel = wx.Button(self.panel, wx.ID_CANCEL, _("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 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) + def set_value(self, panel, key, value): + p = getattr(self, panel) + control = getattr(p, key) + getattr(control, "SetValue")(value) - def alpha_channel(self): - return wx.MessageDialog(self, _("The alpha channel contains bleeding edge changes introduced to Socializer. A new alpha update is generated every time there are new changes in the project. Take into account that updates are generated automatically and may fail at any time due to errors in the build process. Use alpha channels when you are sure you want to try the latest changes and contribute with reports to fix bugs. Never use alpha channel updates for everyday use. Do you want to continue?"), _("Attention"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal() + def alpha_channel(self): + return wx.MessageDialog(self, _("The alpha channel contains bleeding edge changes introduced to Socializer. A new alpha update is generated every time there are new changes in the project. Take into account that updates are generated automatically and may fail at any time due to errors in the build process. Use alpha channels when you are sure you want to try the latest changes and contribute with reports to fix bugs. Never use alpha channel updates for everyday use. Do you want to continue?"), _("Attention"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal() - def weekly_channel(self): - return wx.MessageDialog(self, _("The weekly channel generates an update automatically every week by building the source code present in the project. This version is used to test features added to the next stable version. Do you want to continue?"), _("Attention"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal() \ No newline at end of file + def weekly_channel(self): + return wx.MessageDialog(self, _("The weekly channel generates an update automatically every week by building the source code present in the project. This version is used to test features added to the next stable version. Do you want to continue?"), _("Attention"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal() diff --git a/src/views/dialogs/postCreation.py b/src/views/dialogs/postCreation.py index 6e0d64a..81e82b8 100644 --- a/src/views/dialogs/postCreation.py +++ b/src/views/dialogs/postCreation.py @@ -4,168 +4,167 @@ import wx import widgetUtils class createTextMessage(widgetUtils.BaseDialog): - def __init__(self, *args, **kwargs): - super(createTextMessage, self).__init__(parent=None, *args, **kwargs) + def __init__(self, *args, **kwargs): + super(createTextMessage, self).__init__(parent=None, *args, **kwargs) - def createTextArea(self, message="", text=""): - self.panel = wx.Panel(self) - self.label = wx.StaticText(self.panel, -1, message) - self.text = wx.TextCtrl(self.panel, -1, text, size=(439, -1), style=wx.TE_MULTILINE) - self.text.SetFocus() - self.textBox = wx.BoxSizer(wx.HORIZONTAL) - self.textBox.Add(self.label, 0, wx.ALL, 5) - self.textBox.Add(self.text, 0, wx.ALL, 5) + def createTextArea(self, message="", text=""): + self.panel = wx.Panel(self) + self.label = wx.StaticText(self.panel, -1, message) + self.text = wx.TextCtrl(self.panel, -1, text, size=(439, -1), style=wx.TE_MULTILINE) + self.text.SetFocus() + self.textBox = wx.BoxSizer(wx.HORIZONTAL) + self.textBox.Add(self.label, 0, wx.ALL, 5) + self.textBox.Add(self.text, 0, wx.ALL, 5) - def create_privacy_box(self): - lbl = wx.StaticText(self.panel, wx.NewId(), _("&Privacy")) - self.privacy = wx.ComboBox(self.panel, wx.NewId(), choices=[_("All users"), _("Friends of friends"),], value=_("All users"), style=wx.CB_READONLY) - self.privacyBox = wx.BoxSizer(wx.HORIZONTAL) - self.privacyBox.Add(lbl, 0, wx.ALL, 5) - self.privacyBox.Add(self.privacy, 0, wx.ALL, 5) + def create_privacy_box(self): + lbl = wx.StaticText(self.panel, wx.NewId(), _("&Privacy")) + self.privacy = wx.ComboBox(self.panel, wx.NewId(), choices=[_("All users"), _("Friends of friends"),], value=_("All users"), style=wx.CB_READONLY) + self.privacyBox = wx.BoxSizer(wx.HORIZONTAL) + self.privacyBox.Add(lbl, 0, wx.ALL, 5) + self.privacyBox.Add(self.privacy, 0, wx.ALL, 5) - def text_focus(self): - self.text.SetFocus() + def text_focus(self): + self.text.SetFocus() - def get_text(self): - return self.text.GetValue() + def get_text(self): + return self.text.GetValue() - def set_text(self, text): - return self.text.ChangeValue(text) + def set_text(self, text): + return self.text.ChangeValue(text) - def enable_button(self, buttonName): - if getattr(self, buttonName): - return getattr(self, buttonName).Enable() + def enable_button(self, buttonName): + if getattr(self, buttonName): + return getattr(self, buttonName).Enable() - def disable_button(self, buttonName): - if getattr(self, buttonName): - return getattr(self, buttonName).Disable() + def disable_button(self, buttonName): + if getattr(self, buttonName): + return getattr(self, buttonName).Disable() - def onSelect(self, ev): - self.text.SelectAll() + def onSelect(self, ev): + self.text.SelectAll() - def set_cursor_at_end(self): - self.text.SetInsertionPoint(len(self.text.GetValue())) + def set_cursor_at_end(self): + self.text.SetInsertionPoint(len(self.text.GetValue())) - def set_cursor_at_position(self, position): - self.text.SetInsertionPoint(position) + def set_cursor_at_position(self, position): + self.text.SetInsertionPoint(position) - def get_position(self): - return self.text.GetInsertionPoint() + def get_position(self): + return self.text.GetInsertionPoint() class createPostDialog(createTextMessage): - def createControls(self, title, message, text, mode): - self.mainBox = wx.BoxSizer(wx.VERTICAL) - self.createTextArea(message, text) - self.mainBox.Add(self.textBox, 0, wx.ALL, 5) - if mode == "post": - self.create_privacy_box() - self.mainBox.Add(self.privacyBox, 0, wx.ALL, 5) - self.attach = wx.Button(self.panel, -1, _("Attach"), size=wx.DefaultSize) - self.mention = wx.Button(self.panel, wx.NewId(), _("Tag a friend")) - self.spellcheck = wx.Button(self.panel, -1, _("Spelling &correction"), size=wx.DefaultSize) - self.translateButton = wx.Button(self.panel, -1, _("&Translate message"), size=wx.DefaultSize) - self.okButton = wx.Button(self.panel, wx.ID_OK, _("Send"), size=wx.DefaultSize) - self.okButton.SetDefault() - cancelButton = wx.Button(self.panel, wx.ID_CANCEL, _("Close"), size=wx.DefaultSize) - self.buttonsBox1 = wx.BoxSizer(wx.HORIZONTAL) - self.buttonsBox1.Add(self.attach, 0, wx.ALL, 10) - self.buttonsBox1.Add(self.mention, 0, wx.ALL, 10) - self.buttonsBox1.Add(self.spellcheck, 0, wx.ALL, 10) - self.buttonsBox1.Add(self.translateButton, 0, wx.ALL, 10) - self.mainBox.Add(self.buttonsBox1, 0, wx.ALL, 10) - self.ok_cancelSizer = wx.BoxSizer(wx.HORIZONTAL) - self.ok_cancelSizer.Add(self.okButton, 0, wx.ALL, 10) - self.ok_cancelSizer.Add(cancelButton, 0, wx.ALL, 10) - self.mainBox.Add(self.ok_cancelSizer) - selectId = wx.NewId() - self.Bind(wx.EVT_MENU, self.onSelect, id=selectId) - self.accel_tbl = wx.AcceleratorTable([ - (wx.ACCEL_CTRL, ord('A'), selectId),]) - self.SetAcceleratorTable(self.accel_tbl) - self.panel.SetSizer(self.mainBox) - self.SetTitle(title) + def createControls(self, title, message, text, mode): + self.mainBox = wx.BoxSizer(wx.VERTICAL) + self.createTextArea(message, text) + self.mainBox.Add(self.textBox, 0, wx.ALL, 5) + if mode == "post": + self.create_privacy_box() + self.mainBox.Add(self.privacyBox, 0, wx.ALL, 5) + self.attach = wx.Button(self.panel, -1, _("Attach"), size=wx.DefaultSize) + self.mention = wx.Button(self.panel, wx.NewId(), _("Tag a friend")) + self.spellcheck = wx.Button(self.panel, -1, _("Spelling &correction"), size=wx.DefaultSize) + self.translateButton = wx.Button(self.panel, -1, _("&Translate message"), size=wx.DefaultSize) + self.okButton = wx.Button(self.panel, wx.ID_OK, _("Send"), size=wx.DefaultSize) + self.okButton.SetDefault() + cancelButton = wx.Button(self.panel, wx.ID_CANCEL, _("Close"), size=wx.DefaultSize) + self.buttonsBox1 = wx.BoxSizer(wx.HORIZONTAL) + self.buttonsBox1.Add(self.attach, 0, wx.ALL, 10) + self.buttonsBox1.Add(self.mention, 0, wx.ALL, 10) + self.buttonsBox1.Add(self.spellcheck, 0, wx.ALL, 10) + self.buttonsBox1.Add(self.translateButton, 0, wx.ALL, 10) + self.mainBox.Add(self.buttonsBox1, 0, wx.ALL, 10) + self.ok_cancelSizer = wx.BoxSizer(wx.HORIZONTAL) + self.ok_cancelSizer.Add(self.okButton, 0, wx.ALL, 10) + self.ok_cancelSizer.Add(cancelButton, 0, wx.ALL, 10) + self.mainBox.Add(self.ok_cancelSizer) + selectId = wx.NewId() + self.Bind(wx.EVT_MENU, self.onSelect, id=selectId) + self.accel_tbl = wx.AcceleratorTable([ + (wx.ACCEL_CTRL, ord('A'), selectId),]) + self.SetAcceleratorTable(self.accel_tbl) + self.panel.SetSizer(self.mainBox) + self.SetTitle(title) - def __init__(self, title, message, text, mode="post"): - super(createPostDialog, self).__init__() - self.createControls(title, message, text, mode) - self.SetClientSize(self.mainBox.CalcMin()) + def __init__(self, title, message, text, mode="post"): + super(createPostDialog, self).__init__() + self.createControls(title, message, text, mode) + self.SetClientSize(self.mainBox.CalcMin()) class createCommentDialog(createTextMessage): - def createControls(self, title, message, text, **kwargs): - self.mainBox = wx.BoxSizer(wx.VERTICAL) - self.createTextArea(message, text) - self.mainBox.Add(self.textBox, 0, wx.ALL, 5) - self.spellcheck = wx.Button(self.panel, -1, _("Spelling correction"), size=wx.DefaultSize) - self.mention = wx.Button(self.panel, wx.NewId(), _("Tag a friend")) - self.translateButton = wx.Button(self.panel, -1, _("Translate message"), size=wx.DefaultSize) - self.okButton = wx.Button(self.panel, wx.ID_OK, _("Send"), size=wx.DefaultSize) - self.okButton.SetDefault() - cancelButton = wx.Button(self.panel, wx.ID_CANCEL, _("Close"), size=wx.DefaultSize) - self.buttonsBox1 = wx.BoxSizer(wx.HORIZONTAL) - self.buttonsBox1.Add(self.spellcheck, 0, wx.ALL, 10) - self.buttonsBox1.Add(self.mention, 0, wx.ALL, 10) - self.buttonsBox1.Add(self.translateButton, 0, wx.ALL, 10) - self.mainBox.Add(self.buttonsBox1, 0, wx.ALL, 10) - self.ok_cancelSizer = wx.BoxSizer(wx.HORIZONTAL) - self.ok_cancelSizer.Add(self.okButton, 0, wx.ALL, 10) - self.ok_cancelSizer.Add(cancelButton, 0, wx.ALL, 10) - self.mainBox.Add(self.ok_cancelSizer) - selectId = wx.NewId() - self.Bind(wx.EVT_MENU, self.onSelect, id=selectId) - self.accel_tbl = wx.AcceleratorTable([(wx.ACCEL_CTRL, ord('A'), selectId),]) - self.SetAcceleratorTable(self.accel_tbl) - self.panel.SetSizer(self.mainBox) - self.SetTitle(title) + def createControls(self, title, message, text, **kwargs): + self.mainBox = wx.BoxSizer(wx.VERTICAL) + self.createTextArea(message, text) + self.mainBox.Add(self.textBox, 0, wx.ALL, 5) + self.spellcheck = wx.Button(self.panel, -1, _("Spelling correction"), size=wx.DefaultSize) + self.mention = wx.Button(self.panel, wx.NewId(), _("Tag a friend")) + self.translateButton = wx.Button(self.panel, -1, _("Translate message"), size=wx.DefaultSize) + self.okButton = wx.Button(self.panel, wx.ID_OK, _("Send"), size=wx.DefaultSize) + self.okButton.SetDefault() + cancelButton = wx.Button(self.panel, wx.ID_CANCEL, _("Close"), size=wx.DefaultSize) + self.buttonsBox1 = wx.BoxSizer(wx.HORIZONTAL) + self.buttonsBox1.Add(self.spellcheck, 0, wx.ALL, 10) + self.buttonsBox1.Add(self.mention, 0, wx.ALL, 10) + self.buttonsBox1.Add(self.translateButton, 0, wx.ALL, 10) + self.mainBox.Add(self.buttonsBox1, 0, wx.ALL, 10) + self.ok_cancelSizer = wx.BoxSizer(wx.HORIZONTAL) + self.ok_cancelSizer.Add(self.okButton, 0, wx.ALL, 10) + self.ok_cancelSizer.Add(cancelButton, 0, wx.ALL, 10) + self.mainBox.Add(self.ok_cancelSizer) + selectId = wx.NewId() + self.Bind(wx.EVT_MENU, self.onSelect, id=selectId) + self.accel_tbl = wx.AcceleratorTable([(wx.ACCEL_CTRL, ord('A'), selectId),]) + self.SetAcceleratorTable(self.accel_tbl) + self.panel.SetSizer(self.mainBox) + self.SetTitle(title) - def __init__(self, title, message, text, *args, **kwargs): - super(createCommentDialog, self).__init__() - self.createControls(message, title, text, **kwargs) - self.SetClientSize(self.mainBox.CalcMin()) - self.SetTitle(title) + def __init__(self, title, message, text, *args, **kwargs): + super(createCommentDialog, self).__init__() + self.createControls(message, title, text, **kwargs) + self.SetClientSize(self.mainBox.CalcMin()) + self.SetTitle(title) class createTopicDialog(createCommentDialog): - def createTextArea(self, message="", text="", topic_title=""): - self.panel = wx.Panel(self) - label = wx.StaticText(self.panel, -1, _("Title")) - self.title = wx.TextCtrl(self.panel, wx.NewId(), topic_title) - label2 = wx.StaticText(self.panel, -1, _("Message")) - self.text = wx.TextCtrl(self.panel, -1, text, size=(439, -1), style=wx.TE_MULTILINE) - self.title.SetFocus() - self.textBox = wx.BoxSizer(wx.VERTICAL) - titleb = wx.BoxSizer(wx.HORIZONTAL) - titleb.Add(label, 0, wx.ALL, 5) - titleb.Add(self.title, 0, wx.ALL, 5) - self.textBox.Add(titleb, 0, wx.ALL, 5) - textb = wx.BoxSizer(wx.HORIZONTAL) - textb.Add(label2, 0, wx.ALL, 5) - textb.Add(self.text, 0, wx.ALL, 5) - self.textBox.Add(textb, 0, wx.ALL, 5) - - def createControls(self, title, message, text, topic_title): - self.mainBox = wx.BoxSizer(wx.VERTICAL) - self.createTextArea(message, text, topic_title) - self.mainBox.Add(self.textBox, 0, wx.ALL, 5) - self.attach = wx.Button(self.panel, -1, _("Attach"), size=wx.DefaultSize) - self.mention = wx.Button(self.panel, wx.NewId(), _("Tag a friend")) - self.spellcheck = wx.Button(self.panel, -1, _("Spelling &correction"), size=wx.DefaultSize) - self.translateButton = wx.Button(self.panel, -1, _("&Translate message"), size=wx.DefaultSize) - self.okButton = wx.Button(self.panel, wx.ID_OK, _("Send"), size=wx.DefaultSize) - self.okButton.SetDefault() - cancelButton = wx.Button(self.panel, wx.ID_CANCEL, _("Close"), size=wx.DefaultSize) - self.buttonsBox1 = wx.BoxSizer(wx.HORIZONTAL) - self.buttonsBox1.Add(self.attach, 0, wx.ALL, 10) - self.buttonsBox1.Add(self.mention, 0, wx.ALL, 10) - self.buttonsBox1.Add(self.spellcheck, 0, wx.ALL, 10) - self.buttonsBox1.Add(self.translateButton, 0, wx.ALL, 10) - self.mainBox.Add(self.buttonsBox1, 0, wx.ALL, 10) - self.ok_cancelSizer = wx.BoxSizer(wx.HORIZONTAL) - self.ok_cancelSizer.Add(self.okButton, 0, wx.ALL, 10) - self.ok_cancelSizer.Add(cancelButton, 0, wx.ALL, 10) - self.mainBox.Add(self.ok_cancelSizer) - selectId = wx.NewId() - self.Bind(wx.EVT_MENU, self.onSelect, id=selectId) - self.accel_tbl = wx.AcceleratorTable([ - (wx.ACCEL_CTRL, ord('A'), selectId),]) - self.SetAcceleratorTable(self.accel_tbl) - self.panel.SetSizer(self.mainBox) + def createTextArea(self, message="", text="", topic_title=""): + self.panel = wx.Panel(self) + label = wx.StaticText(self.panel, -1, _("Title")) + self.title = wx.TextCtrl(self.panel, wx.NewId(), topic_title) + label2 = wx.StaticText(self.panel, -1, _("Message")) + self.text = wx.TextCtrl(self.panel, -1, text, size=(439, -1), style=wx.TE_MULTILINE) + self.title.SetFocus() + self.textBox = wx.BoxSizer(wx.VERTICAL) + titleb = wx.BoxSizer(wx.HORIZONTAL) + titleb.Add(label, 0, wx.ALL, 5) + titleb.Add(self.title, 0, wx.ALL, 5) + self.textBox.Add(titleb, 0, wx.ALL, 5) + textb = wx.BoxSizer(wx.HORIZONTAL) + textb.Add(label2, 0, wx.ALL, 5) + textb.Add(self.text, 0, wx.ALL, 5) + self.textBox.Add(textb, 0, wx.ALL, 5) + def createControls(self, title, message, text, topic_title): + self.mainBox = wx.BoxSizer(wx.VERTICAL) + self.createTextArea(message, text, topic_title) + self.mainBox.Add(self.textBox, 0, wx.ALL, 5) + self.attach = wx.Button(self.panel, -1, _("Attach"), size=wx.DefaultSize) + self.mention = wx.Button(self.panel, wx.NewId(), _("Tag a friend")) + self.spellcheck = wx.Button(self.panel, -1, _("Spelling &correction"), size=wx.DefaultSize) + self.translateButton = wx.Button(self.panel, -1, _("&Translate message"), size=wx.DefaultSize) + self.okButton = wx.Button(self.panel, wx.ID_OK, _("Send"), size=wx.DefaultSize) + self.okButton.SetDefault() + cancelButton = wx.Button(self.panel, wx.ID_CANCEL, _("Close"), size=wx.DefaultSize) + self.buttonsBox1 = wx.BoxSizer(wx.HORIZONTAL) + self.buttonsBox1.Add(self.attach, 0, wx.ALL, 10) + self.buttonsBox1.Add(self.mention, 0, wx.ALL, 10) + self.buttonsBox1.Add(self.spellcheck, 0, wx.ALL, 10) + self.buttonsBox1.Add(self.translateButton, 0, wx.ALL, 10) + self.mainBox.Add(self.buttonsBox1, 0, wx.ALL, 10) + self.ok_cancelSizer = wx.BoxSizer(wx.HORIZONTAL) + self.ok_cancelSizer.Add(self.okButton, 0, wx.ALL, 10) + self.ok_cancelSizer.Add(cancelButton, 0, wx.ALL, 10) + self.mainBox.Add(self.ok_cancelSizer) + selectId = wx.NewId() + self.Bind(wx.EVT_MENU, self.onSelect, id=selectId) + self.accel_tbl = wx.AcceleratorTable([ + (wx.ACCEL_CTRL, ord('A'), selectId),]) + self.SetAcceleratorTable(self.accel_tbl) + self.panel.SetSizer(self.mainBox) diff --git a/src/views/dialogs/postDisplay.py b/src/views/dialogs/postDisplay.py index 0ab189e..cf6aea0 100644 --- a/src/views/dialogs/postDisplay.py +++ b/src/views/dialogs/postDisplay.py @@ -3,420 +3,419 @@ import wx import widgetUtils class displayBasicPost(widgetUtils.BaseDialog): - def __init__(self, *args, **kwargs): - super(displayBasicPost, self).__init__(parent=None, *args, **kwargs) - self.panel = wx.Panel(self, -1) - self.sizer = wx.BoxSizer(wx.VERTICAL) + def __init__(self, *args, **kwargs): + super(displayBasicPost, self).__init__(parent=None, *args, **kwargs) + self.panel = wx.Panel(self, -1) + self.sizer = wx.BoxSizer(wx.VERTICAL) - def done(self): - self.panel.SetSizer(self.sizer) - self.SetClientSize(self.sizer.CalcMin()) + def done(self): + self.panel.SetSizer(self.sizer) + self.SetClientSize(self.sizer.CalcMin()) - def create_post_view(self, label=_("Message")): - lbl = wx.StaticText(self.panel, -1, label) - self.post_view = wx.TextCtrl(self.panel, -1, size=(730, -1), style=wx.TE_READONLY|wx.TE_MULTILINE) - selectId = wx.NewId() - self.Bind(wx.EVT_MENU, self.onSelect, id=selectId) - self.accel_tbl = wx.AcceleratorTable([ - (wx.ACCEL_CTRL, ord('A'), selectId),]) - self.SetAcceleratorTable(self.accel_tbl) - box = wx.BoxSizer(wx.HORIZONTAL) - box.Add(lbl, 0, wx.ALL, 5) - box.Add(self.post_view, 0, wx.ALL, 5) - return box + def create_post_view(self, label=_("Message")): + lbl = wx.StaticText(self.panel, -1, label) + self.post_view = wx.TextCtrl(self.panel, -1, size=(730, -1), style=wx.TE_READONLY|wx.TE_MULTILINE) + selectId = wx.NewId() + self.Bind(wx.EVT_MENU, self.onSelect, id=selectId) + self.accel_tbl = wx.AcceleratorTable([ + (wx.ACCEL_CTRL, ord('A'), selectId),]) + self.SetAcceleratorTable(self.accel_tbl) + box = wx.BoxSizer(wx.HORIZONTAL) + box.Add(lbl, 0, wx.ALL, 5) + box.Add(self.post_view, 0, wx.ALL, 5) + return box - def onSelect(self, event): - self.post_view.SelectAll() + def onSelect(self, event): + self.post_view.SelectAll() - def create_views_control(self): - lbl = wx.StaticText(self.panel, -1, _("Views")) - self.views = wx.TextCtrl(self.panel, -1, style=wx.TE_READONLY|wx.TE_MULTILINE) - box = wx.BoxSizer(wx.HORIZONTAL) - box.Add(lbl, 0, wx.ALL, 5) - box.Add(self.views, 0, wx.ALL, 5) - return box + def create_views_control(self): + lbl = wx.StaticText(self.panel, -1, _("Views")) + self.views = wx.TextCtrl(self.panel, -1, style=wx.TE_READONLY|wx.TE_MULTILINE) + box = wx.BoxSizer(wx.HORIZONTAL) + box.Add(lbl, 0, wx.ALL, 5) + box.Add(self.views, 0, wx.ALL, 5) + return box - def create_comments_list(self): - lbl = wx.StaticText(self.panel, -1, _("Comments")) - self.comments = widgetUtils.list(self.panel, _("User"), _("Comment"), _("Date"), _("Likes"), style=wx.LC_REPORT) - self.reply = wx.Button(self.panel, -1, _("Reply to comment")) - self.reply.Enable(False) - box = wx.BoxSizer(wx.HORIZONTAL) - box.Add(lbl, 0, wx.ALL, 5) - box.Add(self.comments.list, 0, wx.ALL, 5) - box.Add(self.reply, 0, wx.ALL, 5) - return box + def create_comments_list(self): + lbl = wx.StaticText(self.panel, -1, _("Comments")) + self.comments = widgetUtils.list(self.panel, _("User"), _("Comment"), _("Date"), _("Likes"), style=wx.LC_REPORT) + self.reply = wx.Button(self.panel, -1, _("Reply to comment")) + self.reply.Enable(False) + box = wx.BoxSizer(wx.HORIZONTAL) + box.Add(lbl, 0, wx.ALL, 5) + box.Add(self.comments.list, 0, wx.ALL, 5) + box.Add(self.reply, 0, wx.ALL, 5) + return box - def create_attachments(self): - lbl = wx.StaticText(self.panel, -1, _("Attachments")) - self.attachments = widgetUtils.list(self.panel, _("Type"), _("Title"), style=wx.LC_REPORT) - box = wx.BoxSizer(wx.HORIZONTAL) - box.Add(lbl, 0, wx.ALL, 5) - box.Add(self.attachments.list, 0, wx.ALL, 5) - return box + def create_attachments(self): + lbl = wx.StaticText(self.panel, -1, _("Attachments")) + self.attachments = widgetUtils.list(self.panel, _("Type"), _("Title"), style=wx.LC_REPORT) + box = wx.BoxSizer(wx.HORIZONTAL) + box.Add(lbl, 0, wx.ALL, 5) + box.Add(self.attachments.list, 0, wx.ALL, 5) + return box - def create_photo_viewer(self): - self.image = wx.StaticBitmap(self.panel, bitmap=wx.Bitmap(1280, 860), size=(604, 604)) - self.sizer.Add(self.image, 1, wx.ALL, 10) - self.previous_photo = wx.Button(self.panel, wx.NewId(), _("Previous photo")) - self.view_photo = wx.Button(self.panel, wx.NewId(), _("View in full screen")) - self.next_photo = wx.Button(self.panel, wx.NewId(), _("Next photo")) - actionsS = wx.BoxSizer(wx.HORIZONTAL) - actionsS.Add(self.previous_photo, 0, wx.ALL, 5) - actionsS.Add(self.view_photo, 0, wx.ALL, 5) - actionsS.Add(self.next_photo, wx.ALL, 5) - self.previous_photo.Enable(False) - self.view_photo.Enable(False) - self.next_photo.Enable(False) - self.sizer.Add(actionsS, 0, wx.ALL, 5) + def create_photo_viewer(self): + self.image = wx.StaticBitmap(self.panel, bitmap=wx.Bitmap(1280, 860), size=(604, 604)) + self.sizer.Add(self.image, 1, wx.ALL, 10) + self.previous_photo = wx.Button(self.panel, wx.NewId(), _("Previous photo")) + self.view_photo = wx.Button(self.panel, wx.NewId(), _("View in full screen")) + self.next_photo = wx.Button(self.panel, wx.NewId(), _("Next photo")) + actionsS = wx.BoxSizer(wx.HORIZONTAL) + actionsS.Add(self.previous_photo, 0, wx.ALL, 5) + actionsS.Add(self.view_photo, 0, wx.ALL, 5) + actionsS.Add(self.next_photo, wx.ALL, 5) + self.previous_photo.Enable(False) + self.view_photo.Enable(False) + self.next_photo.Enable(False) + self.sizer.Add(actionsS, 0, wx.ALL, 5) - def enable_photo_controls(self, navigation=True): - self.view_photo.Enable(True) - if navigation: - self.previous_photo.Enable(True) - self.next_photo.Enable(True) + def enable_photo_controls(self, navigation=True): + self.view_photo.Enable(True) + if navigation: + self.previous_photo.Enable(True) + self.next_photo.Enable(True) - def create_likes_box(self): - self.likes = wx.Button(self.panel, -1, _("Loading data...")) - return self.likes + def create_likes_box(self): + self.likes = wx.Button(self.panel, -1, _("Loading data...")) + return self.likes - def create_shares_box(self): - self.shares = wx.Button(self.panel, -1, _("Loading data...")) - return self.shares + def create_shares_box(self): + self.shares = wx.Button(self.panel, -1, _("Loading data...")) + return self.shares - def create_action_buttons(self, comment=True): - self.like = wx.Button(self.panel, -1, _("&Like")) - self.repost = wx.Button(self.panel, -1, _("Repost")) - if comment: self.comment = wx.Button(self.panel, -1, _("Add comment")) - box = wx.BoxSizer(wx.HORIZONTAL) - box.Add(self.like, 0, wx.ALL, 5) - box.Add(self.repost, 0, wx.ALL, 5) - if comment: box.Add(self.comment, 0, wx.ALL, 5) - return box + def create_action_buttons(self, comment=True): + self.like = wx.Button(self.panel, -1, _("&Like")) + self.repost = wx.Button(self.panel, -1, _("Repost")) + if comment: self.comment = wx.Button(self.panel, -1, _("Add comment")) + box = wx.BoxSizer(wx.HORIZONTAL) + box.Add(self.like, 0, wx.ALL, 5) + box.Add(self.repost, 0, wx.ALL, 5) + if comment: box.Add(self.comment, 0, wx.ALL, 5) + return box - def create_tools_button(self): - self.tools = wx.Button(self.panel, -1, _("Actions")) + def create_tools_button(self): + self.tools = wx.Button(self.panel, -1, _("Actions")) - def create_dialog_buttons(self): - self.close = wx.Button(self.panel, wx.ID_CANCEL, _("Close")) - return self.close + def create_dialog_buttons(self): + self.close = wx.Button(self.panel, wx.ID_CANCEL, _("Close")) + return self.close - def set_post(self, text): - if hasattr(self, "post_view"): - self.post_view.ChangeValue(text) - else: - return False + def set_post(self, text): + if hasattr(self, "post_view"): + self.post_view.ChangeValue(text) + else: + return False - def insert_comments(self, comments): - for i in comments: - self.comments.insert_item(False, *i) + def insert_comments(self, comments): + for i in comments: + self.comments.insert_item(False, *i) - def insert_attachments(self, attachments): - for i in attachments: - self.attachments.insert_item(False, *i) + def insert_attachments(self, attachments): + for i in attachments: + self.attachments.insert_item(False, *i) - def set_likes(self, likes): - if hasattr(self, "likes"): - self.likes.SetLabel(_("{0} people like this").format(likes,)) - else: - return False + def set_likes(self, likes): + if hasattr(self, "likes"): + self.likes.SetLabel(_("{0} people like this").format(likes,)) + else: + return False - def set_shares(self, shares): - if hasattr(self, "shares"): - self.shares.SetLabel(_("Shared {0} times").format(shares,)) - else: - return False + def set_shares(self, shares): + if hasattr(self, "shares"): + self.shares.SetLabel(_("Shared {0} times").format(shares,)) + else: + return False class displayPost(displayBasicPost): - def __init__(self, *args, **kwargs): - super(displayPost, self).__init__(*args, **kwargs) - post_view_box = self.create_post_view() - self.sizer.Add(post_view_box, 0, wx.ALL, 5) - views_box = self.create_views_control() - self.sizer.Add(views_box, 0, wx.ALL, 5) - attachments_box = self.create_attachments() - self.sizer.Add(attachments_box, 0, wx.ALL, 5) - self.attachments.list.Enable(False) - self.create_photo_viewer() - self.image.Enable(False) - self.create_tools_button() - self.sizer.Add(self.tools, 0, wx.ALL, 5) - likes_box = self.create_likes_box() - self.sizer.Add(likes_box, 0, wx.ALL, 5) - shares_box = self.create_shares_box() - self.sizer.Add(shares_box, 0, wx.ALL, 5) - actions_box = self.create_action_buttons() - self.sizer.Add(actions_box, 0, wx.ALL, 5) - comments_box = self.create_comments_list() - self.sizer.Add(comments_box, 0, wx.ALL, 5) - self.sizer.Add(self.create_dialog_buttons()) - self.done() + def __init__(self, *args, **kwargs): + super(displayPost, self).__init__(*args, **kwargs) + post_view_box = self.create_post_view() + self.sizer.Add(post_view_box, 0, wx.ALL, 5) + views_box = self.create_views_control() + self.sizer.Add(views_box, 0, wx.ALL, 5) + attachments_box = self.create_attachments() + self.sizer.Add(attachments_box, 0, wx.ALL, 5) + self.attachments.list.Enable(False) + self.create_photo_viewer() + self.image.Enable(False) + self.create_tools_button() + self.sizer.Add(self.tools, 0, wx.ALL, 5) + likes_box = self.create_likes_box() + self.sizer.Add(likes_box, 0, wx.ALL, 5) + shares_box = self.create_shares_box() + self.sizer.Add(shares_box, 0, wx.ALL, 5) + actions_box = self.create_action_buttons() + self.sizer.Add(actions_box, 0, wx.ALL, 5) + comments_box = self.create_comments_list() + self.sizer.Add(comments_box, 0, wx.ALL, 5) + self.sizer.Add(self.create_dialog_buttons()) + self.done() class displayComment(displayBasicPost): - def __init__(self, *args, **kwargs): - super(displayComment, self).__init__(*args, **kwargs) - post_view_box = self.create_post_view() - self.sizer.Add(post_view_box, 0, wx.ALL, 5) - attachments_box = self.create_attachments() - self.sizer.Add(attachments_box, 0, wx.ALL, 5) - self.attachments.list.Enable(False) - self.create_photo_viewer() - self.image.Enable(False) - self.create_tools_button() - self.sizer.Add(self.tools, 0, wx.ALL, 5) - likes_box = self.create_likes_box() - self.sizer.Add(likes_box, 0, wx.ALL, 5) - actions_box = self.create_action_buttons() - self.sizer.Add(actions_box, 0, wx.ALL, 5) - self.sizer.Add(self.create_dialog_buttons()) - self.done() + def __init__(self, *args, **kwargs): + super(displayComment, self).__init__(*args, **kwargs) + post_view_box = self.create_post_view() + self.sizer.Add(post_view_box, 0, wx.ALL, 5) + attachments_box = self.create_attachments() + self.sizer.Add(attachments_box, 0, wx.ALL, 5) + self.attachments.list.Enable(False) + self.create_photo_viewer() + self.image.Enable(False) + self.create_tools_button() + self.sizer.Add(self.tools, 0, wx.ALL, 5) + likes_box = self.create_likes_box() + self.sizer.Add(likes_box, 0, wx.ALL, 5) + actions_box = self.create_action_buttons() + self.sizer.Add(actions_box, 0, wx.ALL, 5) + self.sizer.Add(self.create_dialog_buttons()) + self.done() - def create_action_buttons(self, comment=True): - self.like = wx.Button(self.panel, -1, _("&Like")) - self.reply = wx.Button(self.panel, -1, _("Reply")) - if comment: self.comment = wx.Button(self.panel, -1, _("Add comment")) - box = wx.BoxSizer(wx.HORIZONTAL) - box.Add(self.like, 0, wx.ALL, 5) - box.Add(self.reply, 0, wx.ALL, 5) - if comment: box.Add(self.comment, 0, wx.ALL, 5) - return box + def create_action_buttons(self, comment=True): + self.like = wx.Button(self.panel, -1, _("&Like")) + self.reply = wx.Button(self.panel, -1, _("Reply")) + if comment: self.comment = wx.Button(self.panel, -1, _("Add comment")) + box = wx.BoxSizer(wx.HORIZONTAL) + box.Add(self.like, 0, wx.ALL, 5) + box.Add(self.reply, 0, wx.ALL, 5) + if comment: box.Add(self.comment, 0, wx.ALL, 5) + return box class displayTopic(displayBasicPost): - def __init__(self, *args, **kwargs): - super(displayTopic, self).__init__(*args, **kwargs) - comments_box = self.create_comments_list() - self.sizer.Add(comments_box, 0, wx.ALL, 5) - attachments_box = self.create_attachments() - self.sizer.Add(attachments_box, 0, wx.ALL, 5) - self.attachments.list.Enable(False) - self.create_photo_viewer() - self.image.Enable(False) - self.create_tools_button() - self.sizer.Add(self.tools, 0, wx.ALL, 5) - actions_box = self.create_action_buttons() - self.sizer.Add(actions_box, 0, wx.ALL, 5) - self.sizer.Add(self.create_dialog_buttons()) - self.done() + def __init__(self, *args, **kwargs): + super(displayTopic, self).__init__(*args, **kwargs) + comments_box = self.create_comments_list() + self.sizer.Add(comments_box, 0, wx.ALL, 5) + attachments_box = self.create_attachments() + self.sizer.Add(attachments_box, 0, wx.ALL, 5) + self.attachments.list.Enable(False) + self.create_photo_viewer() + self.image.Enable(False) + self.create_tools_button() + self.sizer.Add(self.tools, 0, wx.ALL, 5) + actions_box = self.create_action_buttons() + self.sizer.Add(actions_box, 0, wx.ALL, 5) + self.sizer.Add(self.create_dialog_buttons()) + self.done() - def create_action_buttons(self, comment=True): - self.like = wx.Button(self.panel, -1, _("&Like")) - if comment: self.comment = wx.Button(self.panel, -1, _("Add comment")) - box = wx.BoxSizer(wx.HORIZONTAL) - box.Add(self.like, 0, wx.ALL, 5) - if comment: box.Add(self.comment, 0, wx.ALL, 5) - return box + def create_action_buttons(self, comment=True): + self.like = wx.Button(self.panel, -1, _("&Like")) + if comment: self.comment = wx.Button(self.panel, -1, _("Add comment")) + box = wx.BoxSizer(wx.HORIZONTAL) + box.Add(self.like, 0, wx.ALL, 5) + if comment: box.Add(self.comment, 0, wx.ALL, 5) + return box - def create_comments_list(self): - lbl = wx.StaticText(self.panel, -1, _("Posts")) - self.comments = widgetUtils.list(self.panel, _("User"), _("Comment"), _("Date"), _("Likes"), style=wx.LC_REPORT) - self.load_more_comments = wx.Button(self.panel, wx.NewId(), _("Load previous comments")) - self.reply = wx.Button(self.panel, -1, _("Reply")) - box = wx.BoxSizer(wx.HORIZONTAL) - box.Add(lbl, 0, wx.ALL, 5) - box.Add(self.comments.list, 0, wx.ALL, 5) - box.Add(self.reply, 0, wx.ALL, 5) - return box + def create_comments_list(self): + lbl = wx.StaticText(self.panel, -1, _("Posts")) + self.comments = widgetUtils.list(self.panel, _("User"), _("Comment"), _("Date"), _("Likes"), style=wx.LC_REPORT) + self.load_more_comments = wx.Button(self.panel, wx.NewId(), _("Load previous comments")) + self.reply = wx.Button(self.panel, -1, _("Reply")) + box = wx.BoxSizer(wx.HORIZONTAL) + box.Add(lbl, 0, wx.ALL, 5) + box.Add(self.comments.list, 0, wx.ALL, 5) + box.Add(self.reply, 0, wx.ALL, 5) + return box class displayAudio(widgetUtils.BaseDialog): - def __init__(self, *args, **kwargs): - super(displayAudio, self).__init__(parent=None, *args, **kwargs) - panel = wx.Panel(self) - sizer = wx.BoxSizer(wx.VERTICAL) - lbl_list = wx.StaticText(panel, wx.NewId(), _("Audio &files")) - self.list = wx.ListBox(panel, wx.NewId()) - listS = wx.BoxSizer(wx.HORIZONTAL) - listS.Add(lbl_list, 0, wx.ALL, 5) - listS.Add(self.list, 0, wx.ALL, 5) - sizer.Add(listS, 0, wx.ALL, 5) - lbl_title = wx.StaticText(panel, wx.NewId(), _("&Title")) - self.title = wx.TextCtrl(panel, wx.NewId(), size=(413, -1), style=wx.TE_READONLY|wx.TE_MULTILINE) - titleBox = wx.BoxSizer(wx.HORIZONTAL) - titleBox.Add(lbl_title, 0, wx.ALL, 5) - titleBox.Add(self.title, 0, wx.ALL, 5) - sizer.Add(titleBox, 0, wx.ALL, 5) - lbl_artist = wx.StaticText(panel, wx.NewId(), _("&Artist")) - self.artist = wx.TextCtrl(panel, wx.NewId(), size=(413, -1), style=wx.TE_READONLY|wx.TE_MULTILINE) - artistBox = wx.BoxSizer(wx.HORIZONTAL) - artistBox.Add(lbl_artist, 0, wx.ALL, 5) - artistBox.Add(self.artist, 0, wx.ALL, 5) - sizer.Add(artistBox, 0, wx.ALL, 5) - lbl_duration = wx.StaticText(panel, wx.NewId(), _("&Duration")) - self.duration = wx.TextCtrl(panel, wx.NewId(), size=(413, -1), style=wx.TE_READONLY|wx.TE_MULTILINE) - durationBox = wx.BoxSizer(wx.HORIZONTAL) - durationBox.Add(lbl_duration, 0, wx.ALL, 5) - durationBox.Add(self.duration, 0, wx.ALL, 5) - sizer.Add(durationBox, 0, wx.ALL, 5) - lbl_lyrics = wx.StaticText(panel, wx.NewId(), _("&Lyric")) - self.lyric = wx.TextCtrl(panel, wx.NewId(), size=(500, 500), style=wx.TE_READONLY|wx.TE_MULTILINE) - lbox = wx.BoxSizer(wx.HORIZONTAL) - lbox.Add(lbl_lyrics, 0, wx.ALL, 5) - lbox.Add(self.lyric, 0, wx.ALL, 5) - sizer.Add(lbox, 0, wx.ALL, 5) - self.play = wx.Button(panel, wx.NewId(), _("&Play")) - self.download = wx.Button(panel, wx.NewId(), _("&Download")) - self.add = wx.Button(panel, wx.NewId(), _("&Add to your library")) - self.remove = wx.Button(panel, wx.NewId(), _("&Remove from your library")) - self.add.Enable(False) - self.remove.Enable(False) - close = wx.Button(panel, wx.ID_CANCEL) - bbox = wx.BoxSizer(wx.HORIZONTAL) - bbox.Add(self.play, 0, wx.ALL, 5) - bbox.Add(self.download, 0, wx.ALL, 5) - bbox.Add(self.add, 0, wx.ALL, 5) - bbox.Add(self.remove, 0, wx.ALL, 5) - bbox.Add(close, 0, wx.ALL, 5) + def __init__(self, *args, **kwargs): + super(displayAudio, self).__init__(parent=None, *args, **kwargs) + panel = wx.Panel(self) + sizer = wx.BoxSizer(wx.VERTICAL) + lbl_list = wx.StaticText(panel, wx.NewId(), _("Audio &files")) + self.list = wx.ListBox(panel, wx.NewId()) + listS = wx.BoxSizer(wx.HORIZONTAL) + listS.Add(lbl_list, 0, wx.ALL, 5) + listS.Add(self.list, 0, wx.ALL, 5) + sizer.Add(listS, 0, wx.ALL, 5) + lbl_title = wx.StaticText(panel, wx.NewId(), _("&Title")) + self.title = wx.TextCtrl(panel, wx.NewId(), size=(413, -1), style=wx.TE_READONLY|wx.TE_MULTILINE) + titleBox = wx.BoxSizer(wx.HORIZONTAL) + titleBox.Add(lbl_title, 0, wx.ALL, 5) + titleBox.Add(self.title, 0, wx.ALL, 5) + sizer.Add(titleBox, 0, wx.ALL, 5) + lbl_artist = wx.StaticText(panel, wx.NewId(), _("&Artist")) + self.artist = wx.TextCtrl(panel, wx.NewId(), size=(413, -1), style=wx.TE_READONLY|wx.TE_MULTILINE) + artistBox = wx.BoxSizer(wx.HORIZONTAL) + artistBox.Add(lbl_artist, 0, wx.ALL, 5) + artistBox.Add(self.artist, 0, wx.ALL, 5) + sizer.Add(artistBox, 0, wx.ALL, 5) + lbl_duration = wx.StaticText(panel, wx.NewId(), _("&Duration")) + self.duration = wx.TextCtrl(panel, wx.NewId(), size=(413, -1), style=wx.TE_READONLY|wx.TE_MULTILINE) + durationBox = wx.BoxSizer(wx.HORIZONTAL) + durationBox.Add(lbl_duration, 0, wx.ALL, 5) + durationBox.Add(self.duration, 0, wx.ALL, 5) + sizer.Add(durationBox, 0, wx.ALL, 5) + lbl_lyrics = wx.StaticText(panel, wx.NewId(), _("&Lyric")) + self.lyric = wx.TextCtrl(panel, wx.NewId(), size=(500, 500), style=wx.TE_READONLY|wx.TE_MULTILINE) + lbox = wx.BoxSizer(wx.HORIZONTAL) + lbox.Add(lbl_lyrics, 0, wx.ALL, 5) + lbox.Add(self.lyric, 0, wx.ALL, 5) + sizer.Add(lbox, 0, wx.ALL, 5) + self.play = wx.Button(panel, wx.NewId(), _("&Play")) + self.download = wx.Button(panel, wx.NewId(), _("&Download")) + self.add = wx.Button(panel, wx.NewId(), _("&Add to your library")) + self.remove = wx.Button(panel, wx.NewId(), _("&Remove from your library")) + self.add.Enable(False) + self.remove.Enable(False) + close = wx.Button(panel, wx.ID_CANCEL) + bbox = wx.BoxSizer(wx.HORIZONTAL) + bbox.Add(self.play, 0, wx.ALL, 5) + bbox.Add(self.download, 0, wx.ALL, 5) + bbox.Add(self.add, 0, wx.ALL, 5) + bbox.Add(self.remove, 0, wx.ALL, 5) + bbox.Add(close, 0, wx.ALL, 5) - def change_state(self, button_name, state): - getattr(self, button_name).Enable(state) + def change_state(self, button_name, state): + getattr(self, button_name).Enable(state) - def get_destination_path(self, filename): - saveFileDialog = wx.FileDialog(self, _("Save this file"), "", filename, _("Audio Files(*.mp3)|*.mp3"), wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) - if saveFileDialog.ShowModal() == wx.ID_OK: - return saveFileDialog.GetPath() - saveFileDialog.Destroy() + def get_destination_path(self, filename): + saveFileDialog = wx.FileDialog(self, _("Save this file"), "", filename, _("Audio Files(*.mp3)|*.mp3"), wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) + if saveFileDialog.ShowModal() == wx.ID_OK: + return saveFileDialog.GetPath() + saveFileDialog.Destroy() - def insert_audio(self, audio_): - self.list.Append(audio_) + def insert_audio(self, audio_): + self.list.Append(audio_) - def get_audio(self): - return self.list.GetSelection() + def get_audio(self): + return self.list.GetSelection() class displayArticle(widgetUtils.BaseDialog): - def __init__(self, *args, **kwargs): - super(displayArticle, self).__init__(parent=None, *args, **kwargs) - self.panel = wx.Panel(self, -1) - self.sizer = wx.BoxSizer(wx.VERTICAL) - article_view_box = self.create_article_view() - self.sizer.Add(article_view_box, 0, wx.ALL, 5) - views_box = self.create_views_control() - self.sizer.Add(views_box, 0, wx.ALL, 5) - attachments_box = self.create_attachments() - self.sizer.Add(attachments_box, 0, wx.ALL, 5) - self.attachments.list.Enable(False) - self.create_tools_button() - self.sizer.Add(self.tools, 0, wx.ALL, 5) - self.sizer.Add(self.create_dialog_buttons()) - self.done() + def __init__(self, *args, **kwargs): + super(displayArticle, self).__init__(parent=None, *args, **kwargs) + self.panel = wx.Panel(self, -1) + self.sizer = wx.BoxSizer(wx.VERTICAL) + article_view_box = self.create_article_view() + self.sizer.Add(article_view_box, 0, wx.ALL, 5) + views_box = self.create_views_control() + self.sizer.Add(views_box, 0, wx.ALL, 5) + attachments_box = self.create_attachments() + self.sizer.Add(attachments_box, 0, wx.ALL, 5) + self.attachments.list.Enable(False) + self.create_tools_button() + self.sizer.Add(self.tools, 0, wx.ALL, 5) + self.sizer.Add(self.create_dialog_buttons()) + self.done() - def done(self): - self.panel.SetSizer(self.sizer) - self.SetClientSize(self.sizer.CalcMin()) + def done(self): + self.panel.SetSizer(self.sizer) + self.SetClientSize(self.sizer.CalcMin()) - def create_article_view(self, label=_("Article")): - lbl = wx.StaticText(self.panel, -1, label) - self.article_view = wx.TextCtrl(self.panel, -1, size=(730, -1), style=wx.TE_READONLY|wx.TE_MULTILINE|wx.BORDER_SIMPLE) - selectId = wx.NewId() - self.Bind(wx.EVT_MENU, self.onSelect, id=selectId) - self.accel_tbl = wx.AcceleratorTable([ - (wx.ACCEL_CTRL, ord('A'), selectId),]) - self.SetAcceleratorTable(self.accel_tbl) - box = wx.BoxSizer(wx.HORIZONTAL) - box.Add(lbl, 0, wx.ALL, 5) - box.Add(self.article_view, 0, wx.ALL, 5) - return box + def create_article_view(self, label=_("Article")): + lbl = wx.StaticText(self.panel, -1, label) + self.article_view = wx.TextCtrl(self.panel, -1, size=(730, -1), style=wx.TE_READONLY|wx.TE_MULTILINE|wx.BORDER_SIMPLE) + selectId = wx.NewId() + self.Bind(wx.EVT_MENU, self.onSelect, id=selectId) + self.accel_tbl = wx.AcceleratorTable([ + (wx.ACCEL_CTRL, ord('A'), selectId),]) + self.SetAcceleratorTable(self.accel_tbl) + box = wx.BoxSizer(wx.HORIZONTAL) + box.Add(lbl, 0, wx.ALL, 5) + box.Add(self.article_view, 0, wx.ALL, 5) + return box - def onSelect(self, event): - self.article_view.SelectAll() + def onSelect(self, event): + self.article_view.SelectAll() - def create_views_control(self): - lbl = wx.StaticText(self.panel, -1, _("Views")) - self.views = wx.TextCtrl(self.panel, -1, style=wx.TE_READONLY|wx.TE_MULTILINE) - box = wx.BoxSizer(wx.HORIZONTAL) - box.Add(lbl, 0, wx.ALL, 5) - box.Add(self.views, 0, wx.ALL, 5) - return box + def create_views_control(self): + lbl = wx.StaticText(self.panel, -1, _("Views")) + self.views = wx.TextCtrl(self.panel, -1, style=wx.TE_READONLY|wx.TE_MULTILINE) + box = wx.BoxSizer(wx.HORIZONTAL) + box.Add(lbl, 0, wx.ALL, 5) + box.Add(self.views, 0, wx.ALL, 5) + return box - def create_tools_button(self): - self.tools = wx.Button(self.panel, -1, _("Actions")) + def create_tools_button(self): + self.tools = wx.Button(self.panel, -1, _("Actions")) - def create_dialog_buttons(self): - self.close = wx.Button(self.panel, wx.ID_CANCEL, _("Close")) - return self.close + def create_dialog_buttons(self): + self.close = wx.Button(self.panel, wx.ID_CANCEL, _("Close")) + return self.close - def create_attachments(self): - lbl = wx.StaticText(self.panel, -1, _("Attachments")) - self.attachments = widgetUtils.list(self.panel, _("Type"), _("Title"), style=wx.LC_REPORT) - box = wx.BoxSizer(wx.HORIZONTAL) - box.Add(lbl, 0, wx.ALL, 5) - box.Add(self.attachments.list, 0, wx.ALL, 5) - return box + def create_attachments(self): + lbl = wx.StaticText(self.panel, -1, _("Attachments")) + self.attachments = widgetUtils.list(self.panel, _("Type"), _("Title"), style=wx.LC_REPORT) + box = wx.BoxSizer(wx.HORIZONTAL) + box.Add(lbl, 0, wx.ALL, 5) + box.Add(self.attachments.list, 0, wx.ALL, 5) + return box - def set_article(self, text): - if hasattr(self, "article_view"): - self.article_view.ChangeValue(text) - else: - return False + def set_article(self, text): + if hasattr(self, "article_view"): + self.article_view.ChangeValue(text) + else: + return False - def insert_attachments(self, attachments): - for i in attachments: - self.attachments.insert_item(False, *i) + def insert_attachments(self, attachments): + for i in attachments: + self.attachments.insert_item(False, *i) class displayFriendship(widgetUtils.BaseDialog): - def __init__(self): - super(displayFriendship, self).__init__(parent=None) - panel = wx.Panel(self) - sizer = wx.BoxSizer(wx.VERTICAL) - self.friends = widgetUtils.list(panel, [_("Friend")], style=wx.LC_REPORT) - sizer.Add(self.friends.list, 0, wx.ALL, 5) - close = wx.Button(panel, wx.ID_CANCEL) - btnbox = wx.BoxSizer(wx.HORIZONTAL) - btnbox.Add(close, 0, wx.ALL, 5) - sizer.Add(btnbox, 0, wx.ALL, 5) - panel.SetSizer(sizer) - self.SetClientSize(sizer.CalcMin()) + def __init__(self): + super(displayFriendship, self).__init__(parent=None) + panel = wx.Panel(self) + sizer = wx.BoxSizer(wx.VERTICAL) + self.friends = widgetUtils.list(panel, [_("Friend")], style=wx.LC_REPORT) + sizer.Add(self.friends.list, 0, wx.ALL, 5) + close = wx.Button(panel, wx.ID_CANCEL) + btnbox = wx.BoxSizer(wx.HORIZONTAL) + btnbox.Add(close, 0, wx.ALL, 5) + sizer.Add(btnbox, 0, wx.ALL, 5) + panel.SetSizer(sizer) + self.SetClientSize(sizer.CalcMin()) class displayPoll(widgetUtils.BaseDialog): - def __init__(self, question="", *args, **kwargs): - super(displayPoll, self).__init__(parent=None, *args, **kwargs) - self.panel = wx.Panel(self, -1) - self.sizer = wx.BoxSizer(wx.VERTICAL) - label = wx.StaticText(self.panel, wx.NewId(), _("Question")) - self.question = wx.TextCtrl(self.panel, wx.NewId(), question, style=wx.TE_MULTILINE|wx.TE_READONLY, size=(730, -1)) - self.sizer.Add(label, 0, wx.ALL, 5) - self.sizer.Add(self.question, 0, wx.ALL, 5) + def __init__(self, question="", *args, **kwargs): + super(displayPoll, self).__init__(parent=None, *args, **kwargs) + self.panel = wx.Panel(self, -1) + self.sizer = wx.BoxSizer(wx.VERTICAL) + label = wx.StaticText(self.panel, wx.NewId(), _("Question")) + self.question = wx.TextCtrl(self.panel, wx.NewId(), question, style=wx.TE_MULTILINE|wx.TE_READONLY, size=(730, -1)) + self.sizer.Add(label, 0, wx.ALL, 5) + self.sizer.Add(self.question, 0, wx.ALL, 5) - def add_options(self, options, multiple=False): - if not isinstance(options[0], str): - return self.add_results(options) - self.options = [] - sizer = wx.StaticBoxSizer(parent=self.panel, orient=wx.VERTICAL, label=_("Options")) - for i in options: - if multiple == False: - if len(self.options) == 0: - control = wx.RadioButton(sizer.GetStaticBox(), wx.NewId(), i, style=wx.RB_GROUP) - else: - control = wx.RadioButton(sizer.GetStaticBox(), wx.NewId(), i) - else: - control = wx.CheckBox(sizer.GetStaticBox(), wx.NewId(), i) - self.options.append(control) - sizer.Add(control, 0, wx.ALL, 5) - self.sizer.Add(sizer, 0, wx.ALL, 5) + def add_options(self, options, multiple=False): + if not isinstance(options[0], str): + return self.add_results(options) + self.options = [] + sizer = wx.StaticBoxSizer(parent=self.panel, orient=wx.VERTICAL, label=_("Options")) + for i in options: + if multiple == False: + if len(self.options) == 0: + control = wx.RadioButton(sizer.GetStaticBox(), wx.NewId(), i, style=wx.RB_GROUP) + else: + control = wx.RadioButton(sizer.GetStaticBox(), wx.NewId(), i) + else: + control = wx.CheckBox(sizer.GetStaticBox(), wx.NewId(), i) + self.options.append(control) + sizer.Add(control, 0, wx.ALL, 5) + self.sizer.Add(sizer, 0, wx.ALL, 5) - def get_answers(self): - answers = [] - for i in self.options: - answers.append(i.GetValue()) - return answers + def get_answers(self): + answers = [] + for i in self.options: + answers.append(i.GetValue()) + return answers - def add_results(self, options): - sizer = wx.StaticBoxSizer(parent=self.panel, orient=wx.VERTICAL, label=_("Poll results")) - for i in options: - sizer2 = wx.StaticBoxSizer(parent=sizer.GetStaticBox(), orient=wx.HORIZONTAL, label=i[0]) - staticcontrol = wx.StaticText(sizer2.GetStaticBox(), wx.NewId(), i[0]) - control = wx.TextCtrl(sizer2.GetStaticBox(), wx.NewId(), _("{votes} ({rate}%)").format(votes=i[1], rate=i[2]), style=wx.TE_READONLY|wx.TE_MULTILINE) - sizer2.Add(staticcontrol, 0, wx.ALL, 5) - sizer2.Add(control, 0, wx.ALL, 5) - sizer.Add(sizer2, 0, wx.ALL, 5) - self.sizer.Add(sizer, 0, wx.ALL, 5) - - def done(self): - self.ok = wx.Button(self.panel, wx.ID_OK, _("Vote")) - cancel = wx.Button(self.panel, wx.ID_CANCEL) - sizer = wx.BoxSizer(wx.HORIZONTAL) - sizer.Add(self.ok, 0, wx.ALL, 5) - sizer.Add(cancel, 0, wx.ALL, 5) - self.panel.SetSizer(self.sizer) - self.SetClientSize(self.sizer.CalcMin()) + def add_results(self, options): + sizer = wx.StaticBoxSizer(parent=self.panel, orient=wx.VERTICAL, label=_("Poll results")) + for i in options: + sizer2 = wx.StaticBoxSizer(parent=sizer.GetStaticBox(), orient=wx.HORIZONTAL, label=i[0]) + staticcontrol = wx.StaticText(sizer2.GetStaticBox(), wx.NewId(), i[0]) + control = wx.TextCtrl(sizer2.GetStaticBox(), wx.NewId(), _("{votes} ({rate}%)").format(votes=i[1], rate=i[2]), style=wx.TE_READONLY|wx.TE_MULTILINE) + sizer2.Add(staticcontrol, 0, wx.ALL, 5) + sizer2.Add(control, 0, wx.ALL, 5) + sizer.Add(sizer2, 0, wx.ALL, 5) + self.sizer.Add(sizer, 0, wx.ALL, 5) + def done(self): + self.ok = wx.Button(self.panel, wx.ID_OK, _("Vote")) + cancel = wx.Button(self.panel, wx.ID_CANCEL) + sizer = wx.BoxSizer(wx.HORIZONTAL) + sizer.Add(self.ok, 0, wx.ALL, 5) + sizer.Add(cancel, 0, wx.ALL, 5) + self.panel.SetSizer(self.sizer) + self.SetClientSize(self.sizer.CalcMin()) diff --git a/src/views/dialogs/profiles.py b/src/views/dialogs/profiles.py index 1c22552..35763b4 100644 --- a/src/views/dialogs/profiles.py +++ b/src/views/dialogs/profiles.py @@ -5,173 +5,173 @@ import wx import widgetUtils def text_size(wxObject, chars): - """ Takes a wx object and the amount of characters supposed to hold and gives the best size for the control. - wxObject wx.TextCtrl: Text control to be taken as a reference. - chars int: Number of characters the control would hold. - returns (x, y)""" - dc = wx.WindowDC(wxObject) - dc.SetFont(wxObject.GetFont()) - (x, y) = dc.GetMultiLineTextExtent("0"*chars) - return (x, -1) + """ Takes a wx object and the amount of characters supposed to hold and gives the best size for the control. + wxObject wx.TextCtrl: Text control to be taken as a reference. + chars int: Number of characters the control would hold. + returns (x, y)""" + dc = wx.WindowDC(wxObject) + dc.SetFont(wxObject.GetFont()) + (x, y) = dc.GetMultiLineTextExtent("0"*chars) + return (x, -1) class baseTab(wx.Panel): - """ Panel to store main user information in a profile viewer.""" + """ Panel to store main user information in a profile viewer.""" - 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 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(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 enable(self, control): - getattr(self, control).Enable(True) + def enable(self, control): + getattr(self, control).Enable(True) - def disable(self, control): - getattr(self, control).Enable(False) + def disable(self, control): + getattr(self, control).Enable(False) class mainInfo(baseTab): - def __init__(self, panel): - super(mainInfo, self).__init__(panel) - sizer = wx.BoxSizer(wx.VERTICAL) - lblName = wx.StaticText(self, wx.NewId(), _("Name")) - self.name = wx.TextCtrl(self, wx.NewId(), style=wx.TE_READONLY|wx.TE_MULTILINE) - self.name.SetMinSize(text_size(self.name, 60)) - sizerName = wx.BoxSizer(wx.HORIZONTAL) - sizerName.Add(lblName, 0, wx.ALL, 5) - sizerName.Add(self.name, 0, wx.ALL, 5) - sizer.Add(sizerName, 0, wx.ALL, 5) + def __init__(self, panel): + super(mainInfo, self).__init__(panel) + sizer = wx.BoxSizer(wx.VERTICAL) + lblName = wx.StaticText(self, wx.NewId(), _("Name")) + self.name = wx.TextCtrl(self, wx.NewId(), style=wx.TE_READONLY|wx.TE_MULTILINE) + self.name.SetMinSize(text_size(self.name, 60)) + sizerName = wx.BoxSizer(wx.HORIZONTAL) + sizerName.Add(lblName, 0, wx.ALL, 5) + sizerName.Add(self.name, 0, wx.ALL, 5) + sizer.Add(sizerName, 0, wx.ALL, 5) - lblStatus = wx.StaticText(self, wx.NewId(), _("Status")) - self.status = wx.TextCtrl(self, wx.NewId(), style=wx.TE_READONLY|wx.TE_MULTILINE) - self.status.Enable(False) - self.status.SetMinSize(text_size(self.status, 300)) - sizerStatus = wx.BoxSizer(wx.HORIZONTAL) - sizerStatus.Add(lblStatus, 0, wx.ALL, 5) - sizerStatus.Add(self.status, 0, wx.ALL, 5) - sizer.Add(sizerStatus, 0, wx.ALL, 5) + lblStatus = wx.StaticText(self, wx.NewId(), _("Status")) + self.status = wx.TextCtrl(self, wx.NewId(), style=wx.TE_READONLY|wx.TE_MULTILINE) + self.status.Enable(False) + self.status.SetMinSize(text_size(self.status, 300)) + sizerStatus = wx.BoxSizer(wx.HORIZONTAL) + sizerStatus.Add(lblStatus, 0, wx.ALL, 5) + sizerStatus.Add(self.status, 0, wx.ALL, 5) + sizer.Add(sizerStatus, 0, wx.ALL, 5) - lblLastSeen = wx.StaticText(self, wx.NewId(), _("Last seen")) - self.last_seen = wx.TextCtrl(self, wx.NewId(), style=wx.TE_READONLY|wx.TE_MULTILINE) - self.last_seen.Enable(False) - sizerLastSeen = wx.BoxSizer(wx.HORIZONTAL) - sizerLastSeen.Add(lblLastSeen, 0, wx.ALL, 5) - sizerLastSeen.Add(self.last_seen, 0, wx.ALL, 5) - sizer.Add(sizerLastSeen, 0, wx.ALL, 5) + lblLastSeen = wx.StaticText(self, wx.NewId(), _("Last seen")) + self.last_seen = wx.TextCtrl(self, wx.NewId(), style=wx.TE_READONLY|wx.TE_MULTILINE) + self.last_seen.Enable(False) + sizerLastSeen = wx.BoxSizer(wx.HORIZONTAL) + sizerLastSeen.Add(lblLastSeen, 0, wx.ALL, 5) + sizerLastSeen.Add(self.last_seen, 0, wx.ALL, 5) + sizer.Add(sizerLastSeen, 0, wx.ALL, 5) - lblMobilePhone = wx.StaticText(self, wx.NewId(), _("Mobile phone")) - self.mobile_phone = wx.TextCtrl(self, wx.NewId(), style=wx.TE_READONLY|wx.TE_MULTILINE) - self.mobile_phone.Enable(False) - sizerMobilePhone = wx.BoxSizer(wx.HORIZONTAL) - sizerMobilePhone.Add(lblMobilePhone, 0, wx.ALL, 5) - sizerMobilePhone.Add(self.mobile_phone, 0, wx.ALL, 5) - sizer.Add(sizerMobilePhone, 0, wx.ALL, 5) + lblMobilePhone = wx.StaticText(self, wx.NewId(), _("Mobile phone")) + self.mobile_phone = wx.TextCtrl(self, wx.NewId(), style=wx.TE_READONLY|wx.TE_MULTILINE) + self.mobile_phone.Enable(False) + sizerMobilePhone = wx.BoxSizer(wx.HORIZONTAL) + sizerMobilePhone.Add(lblMobilePhone, 0, wx.ALL, 5) + sizerMobilePhone.Add(self.mobile_phone, 0, wx.ALL, 5) + sizer.Add(sizerMobilePhone, 0, wx.ALL, 5) - lblHomePhone = wx.StaticText(self, wx.NewId(), _("Home phone")) - self.home_phone = wx.TextCtrl(self, wx.NewId(), style=wx.TE_READONLY|wx.TE_MULTILINE) - self.home_phone.Enable(False) - sizerHomePhone = wx.BoxSizer(wx.HORIZONTAL) - sizerHomePhone.Add(lblHomePhone, 0, wx.ALL, 5) - sizerHomePhone.Add(self.home_phone, 0, wx.ALL, 5) - sizer.Add(sizerHomePhone, 0, wx.ALL, 5) + lblHomePhone = wx.StaticText(self, wx.NewId(), _("Home phone")) + self.home_phone = wx.TextCtrl(self, wx.NewId(), style=wx.TE_READONLY|wx.TE_MULTILINE) + self.home_phone.Enable(False) + sizerHomePhone = wx.BoxSizer(wx.HORIZONTAL) + sizerHomePhone.Add(lblHomePhone, 0, wx.ALL, 5) + sizerHomePhone.Add(self.home_phone, 0, wx.ALL, 5) + sizer.Add(sizerHomePhone, 0, wx.ALL, 5) - lblBDate = wx.StaticText(self, wx.NewId(), _("Birthdate")) - self.bdate = wx.TextCtrl(self, wx.NewId(), style=wx.TE_READONLY|wx.TE_MULTILINE) - self.bdate.Enable(False) - sizerBDate = wx.BoxSizer(wx.HORIZONTAL) - sizerBDate.Add(lblBDate, 0, wx.ALL, 5) - sizerBDate.Add(self.bdate, 0, wx.ALL, 5) - sizer.Add(sizerBDate, 0, wx.ALL, 5) + lblBDate = wx.StaticText(self, wx.NewId(), _("Birthdate")) + self.bdate = wx.TextCtrl(self, wx.NewId(), style=wx.TE_READONLY|wx.TE_MULTILINE) + self.bdate.Enable(False) + sizerBDate = wx.BoxSizer(wx.HORIZONTAL) + sizerBDate.Add(lblBDate, 0, wx.ALL, 5) + sizerBDate.Add(self.bdate, 0, wx.ALL, 5) + sizer.Add(sizerBDate, 0, wx.ALL, 5) - self.relation = wx.Button(self, -1, "") - self.relation.Enable(False) - sizer.Add(self.relation, 0, wx.ALL, 5) + self.relation = wx.Button(self, -1, "") + self.relation.Enable(False) + sizer.Add(self.relation, 0, wx.ALL, 5) - lblCity = wx.StaticText(self, wx.NewId(), _("Current city")) - self.city = wx.TextCtrl(self, wx.NewId(), style=wx.TE_READONLY|wx.TE_MULTILINE) - self.city.SetMinSize(text_size(self.city, 40)) - self.city.Enable(False) - sizerCity = wx.BoxSizer(wx.HORIZONTAL) - sizerCity.Add(lblCity, 0, wx.ALL, 5) - sizerCity.Add(self.city, 0, wx.ALL, 5) - sizer.Add(sizerCity, 0, wx.ALL, 5) + lblCity = wx.StaticText(self, wx.NewId(), _("Current city")) + self.city = wx.TextCtrl(self, wx.NewId(), style=wx.TE_READONLY|wx.TE_MULTILINE) + self.city.SetMinSize(text_size(self.city, 40)) + self.city.Enable(False) + sizerCity = wx.BoxSizer(wx.HORIZONTAL) + sizerCity.Add(lblCity, 0, wx.ALL, 5) + sizerCity.Add(self.city, 0, wx.ALL, 5) + sizer.Add(sizerCity, 0, wx.ALL, 5) - lblHometown = wx.StaticText(self, wx.NewId(), _("Home Town")) - self.home_town = wx.TextCtrl(self, wx.NewId(), style=wx.TE_READONLY|wx.TE_MULTILINE) - self.home_town.SetMinSize(text_size(self.home_town, 40)) - self.home_town.Enable(False) - sizerHometown = wx.BoxSizer(wx.HORIZONTAL) - sizerHometown.Add(lblHometown, 0, wx.ALL, 5) - sizerHometown.Add(self.home_town, 0, wx.ALL, 5) - sizer.Add(sizerHometown, 0, wx.ALL, 5) + lblHometown = wx.StaticText(self, wx.NewId(), _("Home Town")) + self.home_town = wx.TextCtrl(self, wx.NewId(), style=wx.TE_READONLY|wx.TE_MULTILINE) + self.home_town.SetMinSize(text_size(self.home_town, 40)) + self.home_town.Enable(False) + sizerHometown = wx.BoxSizer(wx.HORIZONTAL) + sizerHometown.Add(lblHometown, 0, wx.ALL, 5) + sizerHometown.Add(self.home_town, 0, wx.ALL, 5) + sizer.Add(sizerHometown, 0, wx.ALL, 5) - lblWebsite = wx.StaticText(self, wx.NewId(), _("Website")) - self.website = wx.TextCtrl(self, wx.NewId(), style=wx.TE_READONLY|wx.TE_MULTILINE)#size=(500, -1)) - self.website.SetMinSize(text_size(self.website, 90)) - self.website.Enable(False) - self.go_site = wx.Button(self, -1, _("Visit website")) - self.go_site.Enable(False) - sizerWebsite = wx.BoxSizer(wx.HORIZONTAL) - sizerWebsite.Add(lblWebsite, 0, wx.ALL, 5) - sizerWebsite.Add(self.website, 1, wx.ALL, 5) - sizerWebsite.Add(self.go_site, 1, wx.ALL, 5) - sizer.Add(sizerWebsite, 1, wx.ALL, 5) + lblWebsite = wx.StaticText(self, wx.NewId(), _("Website")) + self.website = wx.TextCtrl(self, wx.NewId(), style=wx.TE_READONLY|wx.TE_MULTILINE)#size=(500, -1)) + self.website.SetMinSize(text_size(self.website, 90)) + self.website.Enable(False) + self.go_site = wx.Button(self, -1, _("Visit website")) + self.go_site.Enable(False) + sizerWebsite = wx.BoxSizer(wx.HORIZONTAL) + sizerWebsite.Add(lblWebsite, 0, wx.ALL, 5) + sizerWebsite.Add(self.website, 1, wx.ALL, 5) + sizerWebsite.Add(self.go_site, 1, wx.ALL, 5) + sizer.Add(sizerWebsite, 1, wx.ALL, 5) - lblOccupation = wx.StaticText(self, wx.NewId(), _("Occupation")) - self.occupation = wx.TextCtrl(self, wx.NewId(), style=wx.TE_READONLY|wx.TE_MULTILINE) - self.occupation.SetMinSize(text_size(self.occupation, 90)) - self.occupation.Enable(False) - sizerOccupation = wx.BoxSizer(wx.HORIZONTAL) - sizerOccupation.Add(lblOccupation, 0, wx.ALL, 5) - sizerOccupation.Add(self.occupation, 0, wx.ALL, 5) - sizer.Add(sizerOccupation, 0, wx.ALL, 5) - self.SetSizer(sizer) + lblOccupation = wx.StaticText(self, wx.NewId(), _("Occupation")) + self.occupation = wx.TextCtrl(self, wx.NewId(), style=wx.TE_READONLY|wx.TE_MULTILINE) + self.occupation.SetMinSize(text_size(self.occupation, 90)) + self.occupation.Enable(False) + sizerOccupation = wx.BoxSizer(wx.HORIZONTAL) + sizerOccupation.Add(lblOccupation, 0, wx.ALL, 5) + sizerOccupation.Add(self.occupation, 0, wx.ALL, 5) + sizer.Add(sizerOccupation, 0, wx.ALL, 5) + self.SetSizer(sizer) class userProfileDialog(widgetUtils.BaseDialog): - def __init__(self, *args, **kwargs): - super(userProfileDialog, self).__init__(parent=None, *args, **kwargs) - self.panel = wx.Panel(self) - self.sizer = wx.BoxSizer(wx.VERTICAL) - self.notebook = wx.Notebook(self.panel) + def __init__(self, *args, **kwargs): + super(userProfileDialog, self).__init__(parent=None, *args, **kwargs) + self.panel = wx.Panel(self) + self.sizer = wx.BoxSizer(wx.VERTICAL) + self.notebook = wx.Notebook(self.panel) - def create_controls(self, section): - if section == "main_info": - self.main_info = mainInfo(self.notebook) - self.notebook.AddPage(self.main_info, _("Basic information")) - self.main_info.SetFocus() + def create_controls(self, section): + if section == "main_info": + self.main_info = mainInfo(self.notebook) + self.notebook.AddPage(self.main_info, _("Basic information")) + self.main_info.SetFocus() - def realice(self): - self.image = wx.StaticBitmap(self.panel, bitmap=wx.Bitmap(200, 200), size=(200, 200)) - self.sizer.Add(self.image, 1, wx.ALL, 10) - self.sizer.Add(self.notebook, 1, wx.ALL, 5) - cancel = wx.Button(self.panel, wx.ID_CANCEL) - btnSizer = wx.BoxSizer(wx.HORIZONTAL) - btnSizer.Add(cancel, 0, wx.ALL, 5) - self.sizer.Add(btnSizer, 0, wx.ALL, 5) - self.panel.SetSizer(self.sizer) - self.SetClientSize(self.sizer.CalcMin()) + def realice(self): + self.image = wx.StaticBitmap(self.panel, bitmap=wx.Bitmap(200, 200), size=(200, 200)) + self.sizer.Add(self.image, 1, wx.ALL, 10) + self.sizer.Add(self.notebook, 1, wx.ALL, 5) + cancel = wx.Button(self.panel, wx.ID_CANCEL) + btnSizer = wx.BoxSizer(wx.HORIZONTAL) + btnSizer.Add(cancel, 0, wx.ALL, 5) + self.sizer.Add(btnSizer, 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 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) + def set_value(self, panel, key, value): + p = getattr(self, panel) + control = getattr(p, key) + getattr(control, "SetValue")(value) - def enable(self, panel, key, value=False): - p = getattr(self, panel) - control = getattr(p, key) - getattr(control, "Enable")(value) \ No newline at end of file + def enable(self, panel, key, value=False): + p = getattr(self, panel) + control = getattr(p, key) + getattr(control, "Enable")(value) diff --git a/src/views/dialogs/urlList.py b/src/views/dialogs/urlList.py index 1c38c62..e4f029c 100644 --- a/src/views/dialogs/urlList.py +++ b/src/views/dialogs/urlList.py @@ -3,34 +3,34 @@ from __future__ import unicode_literals import wx class urlList(wx.Dialog): - def __init__(self): - super(urlList, self).__init__(parent=None, title=_("Select URL")) - 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 __init__(self): + super(urlList, self).__init__(parent=None, title=_("Select URL")) + 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 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_string(self): + return self.lista.GetStringSelection() - def get_item(self): - return self.lista.GetSelection() + def get_item(self): + return self.lista.GetSelection() - def get_response(self): - return self.ShowModal() \ No newline at end of file + def get_response(self): + return self.ShowModal() diff --git a/src/widgetUtils/wxUtils.py b/src/widgetUtils/wxUtils.py index ee96be8..65a2404 100644 --- a/src/widgetUtils/wxUtils.py +++ b/src/widgetUtils/wxUtils.py @@ -63,172 +63,172 @@ LISTBOX_CHANGED = wx.EVT_LISTBOX LISTBOX_ITEM_ACTIVATED = wx.EVT_LIST_ITEM_ACTIVATED def exit_application(): - """ Closes the current window cleanly. """ - wx.GetApp().ExitMainLoop() + """ Closes the current window cleanly. """ + wx.GetApp().ExitMainLoop() def connect_event(parent, event, func, menuitem=None, *args, **kwargs): - """ Connects an event to a function. - parent wx.window: The widget that will listen for the event. - event widgetUtils.event: The event that will be listened for the parent. The event should be one of the widgetUtils events. - function func: The function that will be connected to the event.""" - if menuitem == None: - return getattr(parent, "Bind")(event, func, *args, **kwargs) - else: - return getattr(parent, "Bind")(event, func, menuitem, *args, **kwargs) + """ Connects an event to a function. + parent wx.window: The widget that will listen for the event. + event widgetUtils.event: The event that will be listened for the parent. The event should be one of the widgetUtils events. + function func: The function that will be connected to the event.""" + if menuitem == None: + return getattr(parent, "Bind")(event, func, *args, **kwargs) + else: + return getattr(parent, "Bind")(event, func, menuitem, *args, **kwargs) def connectExitFunction(exitFunction): - """ This connect the events in WX when an user is turning off the machine.""" - wx.GetApp().Bind(wx.EVT_QUERY_END_SESSION, exitFunction) - wx.GetApp().Bind(wx.EVT_END_SESSION, exitFunction) + """ This connect the events in WX when an user is turning off the machine.""" + wx.GetApp().Bind(wx.EVT_QUERY_END_SESSION, exitFunction) + wx.GetApp().Bind(wx.EVT_END_SESSION, exitFunction) class BaseDialog(wx.Dialog): - def __init__(self, *args, **kwargs): - super(BaseDialog, self).__init__(*args, **kwargs) + def __init__(self, *args, **kwargs): + super(BaseDialog, self).__init__(*args, **kwargs) - def get_response(self): - return self.ShowModal() + 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 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(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 destroy(self): - self.Destroy() + def destroy(self): + self.Destroy() - def set_title(self, title): - self.SetTitle(title) + def set_title(self, title): + self.SetTitle(title) - def get_title(self): - return self.GetTitle() + def get_title(self): + return self.GetTitle() - def enable(self, control): - getattr(self, control).Enable(True) + def enable(self, control): + getattr(self, control).Enable(True) - def disable(self, control): - getattr(self, control).Enable(False) + def disable(self, control): + getattr(self, control).Enable(False) class mainLoopObject(wx.App): - def __init__(self): - self.app = wx.App() - self.lc = wx.Locale() - lang=languageHandler.getLanguage() - wxLang=self.lc.FindLanguageInfo(lang) - if not wxLang and '_' in lang: - wxLang=self.lc.FindLanguageInfo(lang.split('_')[0]) - self.lc.AddCatalogLookupPathPrefix(paths.locale_path()) - if wxLang: - self.lc.Init(wxLang.Language) + def __init__(self): + self.app = wx.App() + self.lc = wx.Locale() + lang=languageHandler.getLanguage() + wxLang=self.lc.FindLanguageInfo(lang) + if not wxLang and '_' in lang: + wxLang=self.lc.FindLanguageInfo(lang.split('_')[0]) + self.lc.AddCatalogLookupPathPrefix(paths.locale_path()) + if wxLang: + self.lc.Init(wxLang.Language) - def run(self): - self.app.MainLoop() + def run(self): + self.app.MainLoop() class multiselectionBaseList(wx.ListCtrl, listmix.CheckListCtrlMixin): - def __init__(self, *args, **kwargs): - super(multiselectionBaseList, self).__init__(*args, **kwargs) -# wx.ListCtrl.__init__(self, *args, **kwargs) -# listmix.CheckListCtrlMixin.__init__(self) - self.Bind(wx.EVT_CHAR_HOOK, self.on_keydown) - self.Bind(wx.EVT_LIST_ITEM_FOCUSED, self.on_focus) + def __init__(self, *args, **kwargs): + super(multiselectionBaseList, self).__init__(*args, **kwargs) +# wx.ListCtrl.__init__(self, *args, **kwargs) +# listmix.CheckListCtrlMixin.__init__(self) + self.Bind(wx.EVT_CHAR_HOOK, self.on_keydown) + self.Bind(wx.EVT_LIST_ITEM_FOCUSED, self.on_focus) - def on_focus(self, event): - currentItem = self.GetFocusedItem() - if self.IsChecked(currentItem): - pub.sendMessage("play-sound", sound="selected.ogg") - event.Skip() + def on_focus(self, event): + currentItem = self.GetFocusedItem() + if self.IsChecked(currentItem): + pub.sendMessage("play-sound", sound="selected.ogg") + event.Skip() - def OnCheckItem(self, index, flag): - if flag == True: - pub.sendMessage("play-sound", sound="checked.ogg") - else: - pub.sendMessage("play-sound", sound="unchecked.ogg") + def OnCheckItem(self, index, flag): + if flag == True: + pub.sendMessage("play-sound", sound="checked.ogg") + else: + pub.sendMessage("play-sound", sound="unchecked.ogg") - def on_keydown(self, event): - if event.GetKeyCode() == wx.WXK_SPACE: - # In the example of wx multiselection list they call ToggleItem. - # however this didn't worked quite well. So let's implement it manually. - if self.IsChecked(self.GetFocusedItem()): - self.SetItemImage(self.GetFocusedItem(), 0) - self.OnCheckItem(self.GetFocusedItem(), False) - else: - self.SetItemImage(self.GetFocusedItem(), 1) - self.OnCheckItem(self.GetFocusedItem(), True) - event.Skip() + def on_keydown(self, event): + if event.GetKeyCode() == wx.WXK_SPACE: + # In the example of wx multiselection list they call ToggleItem. + # however this didn't worked quite well. So let's implement it manually. + if self.IsChecked(self.GetFocusedItem()): + self.SetItemImage(self.GetFocusedItem(), 0) + self.OnCheckItem(self.GetFocusedItem(), False) + else: + self.SetItemImage(self.GetFocusedItem(), 1) + self.OnCheckItem(self.GetFocusedItem(), True) + event.Skip() class list(object): - def __init__(self, parent, *columns, **listArguments): - self.columns = columns - self.listArguments = listArguments - self.create_list(parent) + def __init__(self, parent, *columns, **listArguments): + self.columns = columns + self.listArguments = listArguments + self.create_list(parent) - def set_windows_size(self, column, characters_max): - self.list.SetColumnWidth(column, characters_max*2) + def set_windows_size(self, column, characters_max): + self.list.SetColumnWidth(column, characters_max*2) - def set_size(self): - self.list.SetSize((self.list.GetBestSize()[0], 1000)) + def set_size(self): + self.list.SetSize((self.list.GetBestSize()[0], 1000)) - def create_list(self, parent): - self.list = wx.ListCtrl(parent, -1, **self.listArguments) - for i in range(0, len(self.columns)): - self.list.InsertColumn(i, "%s" % (self.columns[i])) + def create_list(self, parent): + self.list = wx.ListCtrl(parent, -1, **self.listArguments) + for i in range(0, len(self.columns)): + self.list.InsertColumn(i, "%s" % (self.columns[i])) - def insert_item(self, reversed, *item): - """ Inserts an item on the list.""" - if reversed == False: items = self.list.GetItemCount() - else: items = 0 - self.list.InsertItem(items, item[0]) - for i in range(1, len(self.columns)): - self.list.SetItem(items, i, item[i]) + def insert_item(self, reversed, *item): + """ Inserts an item on the list.""" + if reversed == False: items = self.list.GetItemCount() + else: items = 0 + self.list.InsertItem(items, item[0]) + for i in range(1, len(self.columns)): + self.list.SetItem(items, i, item[i]) - def remove_item(self, pos): - """ Deletes an item from the list.""" - if pos > 0: self.list.Focus(pos-1) - self.list.DeleteItem(pos) + def remove_item(self, pos): + """ Deletes an item from the list.""" + if pos > 0: self.list.Focus(pos-1) + self.list.DeleteItem(pos) - def clear(self): - self.list.DeleteAllItems() + def clear(self): + self.list.DeleteAllItems() - def get_selected(self): - return self.list.GetFocusedItem() + def get_selected(self): + return self.list.GetFocusedItem() - def select_item(self, pos): - self.list.Focus(pos) + def select_item(self, pos): + self.list.Focus(pos) - def get_count(self): - selected = self.list.GetItemCount() - if selected == -1: - return 0 - else: - return selected + def get_count(self): + selected = self.list.GetItemCount() + if selected == -1: + return 0 + else: + return selected - def Enable(self, value): - return self.list.Enable(value) + def Enable(self, value): + return self.list.Enable(value) class multiselectionList(list): - def create_list(self, parent): - self.list = multiselectionBaseList(parent, -1, **self.listArguments) - for i in range(0, len(self.columns)): - self.list.InsertColumn(i, "%s" % (self.columns[i])) + def create_list(self, parent): + self.list = multiselectionBaseList(parent, -1, **self.listArguments) + for i in range(0, len(self.columns)): + self.list.InsertColumn(i, "%s" % (self.columns[i])) - def get_multiple_selection(self): - selected = [] - for item in range(0, self.list.GetItemCount()): - if self.list.IsChecked(item): - selected.append(item) - if len(selected) == 0 and self.list.GetFocusedItem() != -1: - selected.append(self.list.GetFocusedItem()) - return selected \ No newline at end of file + def get_multiple_selection(self): + selected = [] + for item in range(0, self.list.GetItemCount()): + if self.list.IsChecked(item): + selected.append(item) + if len(selected) == 0 and self.list.GetFocusedItem() != -1: + selected.append(self.list.GetFocusedItem()) + return selected diff --git a/src/write_version_data.py b/src/write_version_data.py index ba4f84b..07f1b6f 100644 --- a/src/write_version_data.py +++ b/src/write_version_data.py @@ -16,4 +16,4 @@ file.close() file2 = open("application.py", "w", encoding="utf-8") file2.writelines(lines) file2.close() -print("Wrote application.py with the new version info.") \ No newline at end of file +print("Wrote application.py with the new version info.") diff --git a/src/wxUI/commonMessages.py b/src/wxUI/commonMessages.py index 9d7f2b8..13a1fa9 100644 --- a/src/wxUI/commonMessages.py +++ b/src/wxUI/commonMessages.py @@ -4,89 +4,89 @@ import wx import application def no_data_entered(): - return wx.MessageDialog(None, _("You must provide Both user and password."), _("Information needed"), wx.ICON_ERROR).ShowModal() + return wx.MessageDialog(None, _("You must provide Both user and password."), _("Information needed"), wx.ICON_ERROR).ShowModal() def no_update_available(): - return wx.MessageDialog(None, _("Your {0} version is up to date").format(application.name,), _("Update"), style=wx.OK).ShowModal() + return wx.MessageDialog(None, _("Your {0} version is up to date").format(application.name,), _("Update"), style=wx.OK).ShowModal() def remove_buffer(): - return wx.MessageDialog(None, _("Do you really want to dismiss this buffer?"), _("Attention"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal() + return wx.MessageDialog(None, _("Do you really want to dismiss this buffer?"), _("Attention"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal() def no_user_exist(): - wx.MessageDialog(None, _("This user does not exist"), _("Error"), style=wx.ICON_ERROR).ShowModal() + wx.MessageDialog(None, _("This user does not exist"), _("Error"), style=wx.ICON_ERROR).ShowModal() def show_error_code(code): - title = "" - message = "" - if code == 201: - title = _("Restricted access") - message = _("Access to user's audio is denied by the owner. Error code {0}").format(code,) - return wx.MessageDialog(None, message, title, style=wx.ICON_ERROR).ShowModal() + title = "" + message = "" + if code == 201: + title = _("Restricted access") + message = _("Access to user's audio is denied by the owner. Error code {0}").format(code,) + return wx.MessageDialog(None, message, title, style=wx.ICON_ERROR).ShowModal() def bad_authorisation(): - return wx.MessageDialog(None, _("authorisation failed. Your configuration will be deleted. If you recently changed your password in VK, you need to reauthorize Socializer. The application will be restarted and prompt you again for your user and password. Press OK to continue."), _("Error"), style=wx.ICON_ERROR).ShowModal() + return wx.MessageDialog(None, _("authorisation failed. Your configuration will be deleted. If you recently changed your password in VK, you need to reauthorize Socializer. The application will be restarted and prompt you again for your user and password. Press OK to continue."), _("Error"), style=wx.ICON_ERROR).ShowModal() def connection_error(): - return wx.MessageDialog(None, _("Socializer could not connect to VK due to a connection issue. Be sure you have a working internet connection. The application will be closed when you press the OK button. If your internet connection is working correctly, please try to open socializer in a few minutes. If this problem persists, contact the developers to receive further assistance."), _("Connection Error"), style=wx.ICON_ERROR).ShowModal() + return wx.MessageDialog(None, _("Socializer could not connect to VK due to a connection issue. Be sure you have a working internet connection. The application will be closed when you press the OK button. If your internet connection is working correctly, please try to open socializer in a few minutes. If this problem persists, contact the developers to receive further assistance."), _("Connection Error"), style=wx.ICON_ERROR).ShowModal() def no_audio_albums(): - return wx.MessageDialog(None, _("You do not have audio albums."), _("Error"), style=wx.ICON_ERROR).ShowModal() + return wx.MessageDialog(None, _("You do not have audio albums."), _("Error"), style=wx.ICON_ERROR).ShowModal() def no_video_albums(): - return wx.MessageDialog(None, _("You do not have video albums."), _("Error"), style=wx.ICON_ERROR).ShowModal() + return wx.MessageDialog(None, _("You do not have video albums."), _("Error"), style=wx.ICON_ERROR).ShowModal() def delete_audio_album(): - return wx.MessageDialog(None, _("Do you really want to delete this Album? this will be deleted from VK too."), _("Attention"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal() + return wx.MessageDialog(None, _("Do you really want to delete this Album? this will be deleted from VK too."), _("Attention"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal() def updated_status(): - return wx.MessageDialog(None, _("Your status message has been successfully updated."), _("Success")).ShowModal() + return wx.MessageDialog(None, _("Your status message has been successfully updated."), _("Success")).ShowModal() def remove_post(): - return wx.MessageDialog(None, _("Do you really want to delete this post?"), _("Attention"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal() + return wx.MessageDialog(None, _("Do you really want to delete this post?"), _("Attention"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal() def join_group(): - return wx.MessageDialog(None, _("If you like socializer, you can join or community from where you can ask for help, give us your feedback and help other users of the application. New releases are posted in the group too. Would you like to join the Socializer community?"), _("Attention"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal() + return wx.MessageDialog(None, _("If you like socializer, you can join or community from where you can ask for help, give us your feedback and help other users of the application. New releases are posted in the group too. Would you like to join the Socializer community?"), _("Attention"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal() def group_joined(): - return wx.MessageDialog(None, _("You have joined the Socializer community."), _("Success")).ShowModal() + return wx.MessageDialog(None, _("You have joined the Socializer community."), _("Success")).ShowModal() def proxy_question(): - return wx.MessageDialog(None, _("If you live in a country where VK is blocked, you can use a proxy to bypass such restrictions. Socializer includes a working proxy to ensure all users can connect to VK. Do you want to use Socializer through the proxy?"), _("Attention"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal() + return wx.MessageDialog(None, _("If you live in a country where VK is blocked, you can use a proxy to bypass such restrictions. Socializer includes a working proxy to ensure all users can connect to VK. Do you want to use Socializer through the proxy?"), _("Attention"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal() def remove_friend(user): - return wx.MessageDialog(None, _("Are you sure you want to remove {user1_nom} from your friends?").format(**user), _("Attention"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal() + return wx.MessageDialog(None, _("Are you sure you want to remove {user1_nom} from your friends?").format(**user), _("Attention"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal() def post_deleted(): - return wx.MessageDialog(None, _("This post has been removed."), _("Error"), wx.ICON_ERROR).ShowModal() + return wx.MessageDialog(None, _("This post has been removed."), _("Error"), wx.ICON_ERROR).ShowModal() def restart_program(): - return wx.MessageDialog(None, _("In order to apply the changes you requested, you must restart the program. Do you want to restart Socializer now?"), _("Attention"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal() + return wx.MessageDialog(None, _("In order to apply the changes you requested, you must restart the program. Do you want to restart Socializer now?"), _("Attention"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal() def community_no_items(): - return wx.MessageDialog(None, _("There are 0 items for this community."), _("Error"), wx.ICON_ERROR).ShowModal() + return wx.MessageDialog(None, _("There are 0 items for this community."), _("Error"), wx.ICON_ERROR).ShowModal() def delete_conversation(): - return wx.MessageDialog(None, _("do you really want to delete all messages of this conversation in VK?"), _("Attention"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal() + return wx.MessageDialog(None, _("do you really want to delete all messages of this conversation in VK?"), _("Attention"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal() def block_person(person): - return wx.MessageDialog(None, _("Are you really sure you want to block {user1_nom} from your VK account?").format(**person,), _("Attention"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal() + return wx.MessageDialog(None, _("Are you really sure you want to block {user1_nom} from your VK account?").format(**person,), _("Attention"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal() def unblock_person(): - return wx.MessageDialog(None, _("Are you sure you want to unblock this user?"), _("Attention"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal() + return wx.MessageDialog(None, _("Are you sure you want to unblock this user?"), _("Attention"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal() def post_failed(): - return wx.MessageDialog(None, _("Unfortunately, we could not send your last post or message to VK. Would you like to try again?"), _("Post failed"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal() + return wx.MessageDialog(None, _("Unfortunately, we could not send your last post or message to VK. Would you like to try again?"), _("Post failed"), style=wx.ICON_QUESTION|wx.YES_NO).ShowModal() def exit(): - dlg = wx.MessageDialog(None, _("Do you really want to close Socializer?"), _("Exit"), wx.YES_NO|wx.ICON_QUESTION) - return dlg.ShowModal() + dlg = wx.MessageDialog(None, _("Do you really want to close Socializer?"), _("Exit"), wx.YES_NO|wx.ICON_QUESTION) + return dlg.ShowModal() def vk_error(code): - title = _("VK error") - if code == 7: - msg = _("You are not allowed to perform this action. Please be sure you are not attempting to post or send a message to a blocked or banned user. Error code 7.") - elif code == 900: - msg = _("You cannot send messages to users in your blacklist.") - else: - msg = str(code) - return wx.MessageDialog(None, msg, title, wx.ICON_ERROR).ShowModal() \ No newline at end of file + title = _("VK error") + if code == 7: + msg = _("You are not allowed to perform this action. Please be sure you are not attempting to post or send a message to a blocked or banned user. Error code 7.") + elif code == 900: + msg = _("You cannot send messages to users in your blacklist.") + else: + msg = str(code) + return wx.MessageDialog(None, msg, title, wx.ICON_ERROR).ShowModal() diff --git a/src/wxUI/dialogs/creation.py b/src/wxUI/dialogs/creation.py index 5cfe203..9b80927 100644 --- a/src/wxUI/dialogs/creation.py +++ b/src/wxUI/dialogs/creation.py @@ -5,22 +5,22 @@ import widgetUtils class audio_album(widgetUtils.BaseDialog): - def __init__(self, *args, **kwargs): - super(audio_album, self).__init__(title=_("Create a new album"), parent=None) - panel = wx.Panel(self) - sizer = wx.BoxSizer(wx.VERTICAL) - lbl = wx.StaticText(panel, wx.NewId(), _("Album title")) - self.title = wx.TextCtrl(panel, wx.NewId()) - box = wx.BoxSizer(wx.HORIZONTAL) - box.Add(lbl, 1, wx.ALL, 5) - box.Add(self.title, 1, wx.ALL, 5) - sizer.Add(box, 1, wx.ALL, 5) - ok = wx.Button(panel, wx.ID_OK, _("&OK")) - ok.SetDefault() - cancel = wx.Button(panel, wx.ID_CANCEL, _("&Close")) - 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()) \ No newline at end of file + def __init__(self, *args, **kwargs): + super(audio_album, self).__init__(title=_("Create a new album"), parent=None) + panel = wx.Panel(self) + sizer = wx.BoxSizer(wx.VERTICAL) + lbl = wx.StaticText(panel, wx.NewId(), _("Album title")) + self.title = wx.TextCtrl(panel, wx.NewId()) + box = wx.BoxSizer(wx.HORIZONTAL) + box.Add(lbl, 1, wx.ALL, 5) + box.Add(self.title, 1, wx.ALL, 5) + sizer.Add(box, 1, wx.ALL, 5) + ok = wx.Button(panel, wx.ID_OK, _("&OK")) + ok.SetDefault() + cancel = wx.Button(panel, wx.ID_CANCEL, _("&Close")) + 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()) diff --git a/src/wxUI/dialogs/player.py b/src/wxUI/dialogs/player.py index 12e4c64..0135e71 100644 --- a/src/wxUI/dialogs/player.py +++ b/src/wxUI/dialogs/player.py @@ -5,6 +5,6 @@ import widgetUtils class audioPlayerDialog(widgetUtils.BaseDialog): - def __init__(self): - super(audioPlayerDialog, self).__init__(None, wx.NewId(), _("Audio player")) - sizer = wx.BoxSizer(wx.VERTICAL) \ No newline at end of file + def __init__(self): + super(audioPlayerDialog, self).__init__(None, wx.NewId(), _("Audio player")) + sizer = wx.BoxSizer(wx.VERTICAL) diff --git a/src/wxUI/dialogs/search.py b/src/wxUI/dialogs/search.py index 6082ae6..77e0126 100644 --- a/src/wxUI/dialogs/search.py +++ b/src/wxUI/dialogs/search.py @@ -4,87 +4,87 @@ import widgetUtils import wx class searchAudioDialog(widgetUtils.BaseDialog): - def __init__(self, value=""): - super(searchAudioDialog, self).__init__(None, -1) - panel = wx.Panel(self) - sizer = wx.BoxSizer(wx.VERTICAL) - self.SetTitle(_("audio Search")) - label = wx.StaticText(panel, -1, _("&Search")) - self.term = wx.TextCtrl(panel, -1, value) - 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) - radioSizer = wx.StaticBoxSizer(parent=panel, orient=wx.HORIZONTAL, label=_("Search by")) - self.title = wx.RadioButton(radioSizer.GetStaticBox(), wx.NewId(), _("Title"), style=wx.RB_GROUP) - self.artist = wx.RadioButton(radioSizer.GetStaticBox(), wx.NewId(), _("Artist")) - radioSizer.Add(self.title, 0, wx.ALL, 5) - radioSizer.Add(self.artist, 0, wx.ALL, 5) - sizer.Add(radioSizer, 0, wx.ALL, 5) - sortBox = wx.StaticBoxSizer(parent=panel, orient=wx.HORIZONTAL, label=_("Sort by")) - self.sortorder = wx.ComboBox(sortBox.GetStaticBox(), wx.NewId(), choices=[_("Date added"), _("Duration"), _("Popularity")], value=_("Popularity"), style=wx.CB_READONLY) - sortBox.Add(self.sortorder, 0, wx.ALL, 5) - sizer.Add(sortBox, 0, wx.ALL, 5) - ok = wx.Button(panel, wx.ID_OK, _("&OK")) - ok.SetDefault() - cancel = wx.Button(panel, wx.ID_CANCEL, _("&Close")) - 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()) + def __init__(self, value=""): + super(searchAudioDialog, self).__init__(None, -1) + panel = wx.Panel(self) + sizer = wx.BoxSizer(wx.VERTICAL) + self.SetTitle(_("audio Search")) + label = wx.StaticText(panel, -1, _("&Search")) + self.term = wx.TextCtrl(panel, -1, value) + 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) + radioSizer = wx.StaticBoxSizer(parent=panel, orient=wx.HORIZONTAL, label=_("Search by")) + self.title = wx.RadioButton(radioSizer.GetStaticBox(), wx.NewId(), _("Title"), style=wx.RB_GROUP) + self.artist = wx.RadioButton(radioSizer.GetStaticBox(), wx.NewId(), _("Artist")) + radioSizer.Add(self.title, 0, wx.ALL, 5) + radioSizer.Add(self.artist, 0, wx.ALL, 5) + sizer.Add(radioSizer, 0, wx.ALL, 5) + sortBox = wx.StaticBoxSizer(parent=panel, orient=wx.HORIZONTAL, label=_("Sort by")) + self.sortorder = wx.ComboBox(sortBox.GetStaticBox(), wx.NewId(), choices=[_("Date added"), _("Duration"), _("Popularity")], value=_("Popularity"), style=wx.CB_READONLY) + sortBox.Add(self.sortorder, 0, wx.ALL, 5) + sizer.Add(sortBox, 0, wx.ALL, 5) + ok = wx.Button(panel, wx.ID_OK, _("&OK")) + ok.SetDefault() + cancel = wx.Button(panel, wx.ID_CANCEL, _("&Close")) + 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()) - def get_state(self, control): - if getattr(self, control).GetValue() == True: - return 1 - else: - return 0 + def get_state(self, control): + if getattr(self, control).GetValue() == True: + return 1 + else: + return 0 - def get_sort_order(self): - return self.sortorder.GetSelection() + def get_sort_order(self): + return self.sortorder.GetSelection() class searchVideoDialog(widgetUtils.BaseDialog): - def __init__(self, value=""): - super(searchVideoDialog, self).__init__(None, -1) - panel = wx.Panel(self) - sizer = wx.BoxSizer(wx.VERTICAL) - self.SetTitle(_("video Search")) - label = wx.StaticText(panel, -1, _("&Search")) - self.term = wx.TextCtrl(panel, -1, value) - 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) - sort_order = wx.StaticText(panel, -1, _("&Sort order by: ")) - self.sortorder = wx.ComboBox(panel, wx.NewId(), choices=[_("Date added"), _("Duration"), _("Popularity")], value=_("Popularity"), style=wx.CB_READONLY) - rBox = wx.BoxSizer(wx.HORIZONTAL) - rBox.Add(sort_order, 0, wx.ALL, 5) - rBox.Add(self.sortorder, 0, wx.ALL, 5) - sizer.Add(rBox, 0, wx.ALL, 5) - self.hd = wx.CheckBox(panel, wx.NewId(), _("Search only for videos in &High definition")) - self.hd.SetValue(False) - sizer.Add(self.hd, 0, wx.ALL, 5) - self.safe_search = wx.CheckBox(panel, wx.NewId(), _("S&afe search")) - self.safe_search.SetValue(True) - sizer.Add(self.safe_search, 0, wx.ALL, 5) - ok = wx.Button(panel, wx.ID_OK, _("&OK")) - ok.SetDefault() - cancel = wx.Button(panel, wx.ID_CANCEL, _("&Close")) - 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()) + def __init__(self, value=""): + super(searchVideoDialog, self).__init__(None, -1) + panel = wx.Panel(self) + sizer = wx.BoxSizer(wx.VERTICAL) + self.SetTitle(_("video Search")) + label = wx.StaticText(panel, -1, _("&Search")) + self.term = wx.TextCtrl(panel, -1, value) + 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) + sort_order = wx.StaticText(panel, -1, _("&Sort order by: ")) + self.sortorder = wx.ComboBox(panel, wx.NewId(), choices=[_("Date added"), _("Duration"), _("Popularity")], value=_("Popularity"), style=wx.CB_READONLY) + rBox = wx.BoxSizer(wx.HORIZONTAL) + rBox.Add(sort_order, 0, wx.ALL, 5) + rBox.Add(self.sortorder, 0, wx.ALL, 5) + sizer.Add(rBox, 0, wx.ALL, 5) + self.hd = wx.CheckBox(panel, wx.NewId(), _("Search only for videos in &High definition")) + self.hd.SetValue(False) + sizer.Add(self.hd, 0, wx.ALL, 5) + self.safe_search = wx.CheckBox(panel, wx.NewId(), _("S&afe search")) + self.safe_search.SetValue(True) + sizer.Add(self.safe_search, 0, wx.ALL, 5) + ok = wx.Button(panel, wx.ID_OK, _("&OK")) + ok.SetDefault() + cancel = wx.Button(panel, wx.ID_CANCEL, _("&Close")) + 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()) - def get_checkable(self, control): - if getattr(self, control).GetValue() == True: - return 1 - else: - return 0 + def get_checkable(self, control): + if getattr(self, control).GetValue() == True: + return 1 + else: + return 0 - def get_sort_order(self): - return self.sortorder.GetSelection() \ No newline at end of file + def get_sort_order(self): + return self.sortorder.GetSelection() diff --git a/src/wxUI/dialogs/selector.py b/src/wxUI/dialogs/selector.py index 78333aa..8aed502 100644 --- a/src/wxUI/dialogs/selector.py +++ b/src/wxUI/dialogs/selector.py @@ -4,141 +4,141 @@ import wx import widgetUtils class selectAlbum(wx.Dialog): - def __init__(self, title, albums): - super(selectAlbum, self).__init__(parent=None, title=title) - panel = wx.Panel(self) - self.lista = wx.ListBox(panel, -1, choices=albums) - self.lista.SetFocus() - self.lista.SetSelection(0) - 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 __init__(self, title, albums): + super(selectAlbum, self).__init__(parent=None, title=title) + panel = wx.Panel(self) + self.lista = wx.ListBox(panel, -1, choices=albums) + self.lista.SetFocus() + self.lista.SetSelection(0) + 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 get_string(self): - return self.lista.GetStringSelection() + def get_string(self): + return self.lista.GetStringSelection() - def get_item(self): - return self.lista.GetSelection() + def get_item(self): + return self.lista.GetSelection() - def get_response(self): - return self.ShowModal() + def get_response(self): + return self.ShowModal() class selectPeople(widgetUtils.BaseDialog): - def __init__(self, users=[]): - super(selectPeople, self).__init__(parent=None, title=_("Tag friends")) - self.indexes = [] - self.users_list = users - panel = wx.Panel(self) - sizer = wx.BoxSizer(wx.HORIZONTAL) - userLabel = wx.StaticText(panel, -1, _("All friends")) - self.cb = wx.ComboBox(panel, -1, choices=users, value=users[0]) - self.cb.SetFocus() - userSizer = wx.BoxSizer() - userSizer.Add(userLabel, 0, wx.ALL, 5) - userSizer.Add(self.cb, 0, wx.ALL, 5) - self.add = wx.Button(panel, wx.NewId(), _("Select")) - self.add.Bind(wx.EVT_BUTTON, self.add_user) - userSizer.Add(self.add, 0, wx.ALL, 5) - sizer.Add(userSizer, 0, wx.ALL, 5) - lbl = wx.StaticText(panel, wx.NewId(), _("Tagged users")) - self.users = wx.ListBox(panel, -1) - self.remove = wx.Button(panel, wx.NewId(), _("Remove")) - self.remove.Bind(wx.EVT_BUTTON, self.remove_user) - selectionSizer = wx.BoxSizer(wx.HORIZONTAL) - selectionSizer.Add(lbl, 0, wx.ALL, 5) - selectionSizer.Add(self.users, 0, wx.ALL, 5) - selectionSizer.Add(self.remove, 0, wx.ALL, 5) - sizer.Add(selectionSizer, 0, wx.ALL, 5) - ok = wx.Button(panel, wx.ID_OK, _("&OK")) - ok.SetDefault() - cancel = wx.Button(panel, wx.ID_CANCEL, _("&Close")) - 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()) + def __init__(self, users=[]): + super(selectPeople, self).__init__(parent=None, title=_("Tag friends")) + self.indexes = [] + self.users_list = users + panel = wx.Panel(self) + sizer = wx.BoxSizer(wx.HORIZONTAL) + userLabel = wx.StaticText(panel, -1, _("All friends")) + self.cb = wx.ComboBox(panel, -1, choices=users, value=users[0]) + self.cb.SetFocus() + userSizer = wx.BoxSizer() + userSizer.Add(userLabel, 0, wx.ALL, 5) + userSizer.Add(self.cb, 0, wx.ALL, 5) + self.add = wx.Button(panel, wx.NewId(), _("Select")) + self.add.Bind(wx.EVT_BUTTON, self.add_user) + userSizer.Add(self.add, 0, wx.ALL, 5) + sizer.Add(userSizer, 0, wx.ALL, 5) + lbl = wx.StaticText(panel, wx.NewId(), _("Tagged users")) + self.users = wx.ListBox(panel, -1) + self.remove = wx.Button(panel, wx.NewId(), _("Remove")) + self.remove.Bind(wx.EVT_BUTTON, self.remove_user) + selectionSizer = wx.BoxSizer(wx.HORIZONTAL) + selectionSizer.Add(lbl, 0, wx.ALL, 5) + selectionSizer.Add(self.users, 0, wx.ALL, 5) + selectionSizer.Add(self.remove, 0, wx.ALL, 5) + sizer.Add(selectionSizer, 0, wx.ALL, 5) + ok = wx.Button(panel, wx.ID_OK, _("&OK")) + ok.SetDefault() + cancel = wx.Button(panel, wx.ID_CANCEL, _("&Close")) + 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()) - def get_user(self): - return self.cb.GetValue() + def get_user(self): + return self.cb.GetValue() - def add_user(self, *args, **kwargs): - selection = self.get_user() - if selection in self.users_list: - self.users.Append(selection) - self.indexes.append(self.cb.GetSelection()) + def add_user(self, *args, **kwargs): + selection = self.get_user() + if selection in self.users_list: + self.users.Append(selection) + self.indexes.append(self.cb.GetSelection()) - def remove_user(self, *args, **kwargs): - n = self.users.GetSelection() - self.users.Delete(n) - self.indexes.remove(n) + def remove_user(self, *args, **kwargs): + n = self.users.GetSelection() + self.users.Delete(n) + self.indexes.remove(n) - def get_all_users(self): - return self.indexes + def get_all_users(self): + return self.indexes class selectAttachment(widgetUtils.BaseDialog): - def __init__(self, title="", attachments=[]): - super(selectAttachment, self).__init__(parent=None, title=title) - self.indexes = [] - self.attachments_list = attachments - panel = wx.Panel(self) - sizer = wx.BoxSizer(wx.HORIZONTAL) - label = wx.StaticText(panel, -1, _("Available attachments")) - self.cb = wx.ComboBox(panel, -1, choices=attachments, value=attachments[0]) - self.cb.SetFocus() - attachmentSizer = wx.BoxSizer() - attachmentSizer.Add(label, 0, wx.ALL, 5) - attachmentSizer.Add(self.cb, 0, wx.ALL, 5) - self.add = wx.Button(panel, wx.NewId(), _("Select")) - self.add.Bind(wx.EVT_BUTTON, self.add_attachment) - attachmentSizer.Add(self.add, 0, wx.ALL, 5) - sizer.Add(attachmentSizer, 0, wx.ALL, 5) - lbl = wx.StaticText(panel, wx.NewId(), _("Selected attachments")) - self.attachments = wx.ListBox(panel, -1) - self.remove = wx.Button(panel, wx.NewId(), _("Remove")) - self.remove.Bind(wx.EVT_BUTTON, self.remove_attachment) - selectionSizer = wx.BoxSizer(wx.HORIZONTAL) - selectionSizer.Add(lbl, 0, wx.ALL, 5) - selectionSizer.Add(self.attachments, 0, wx.ALL, 5) - selectionSizer.Add(self.remove, 0, wx.ALL, 5) - sizer.Add(selectionSizer, 0, wx.ALL, 5) - ok = wx.Button(panel, wx.ID_OK, _("&OK")) - ok.SetDefault() - cancel = wx.Button(panel, wx.ID_CANCEL, _("&Close")) - 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()) + def __init__(self, title="", attachments=[]): + super(selectAttachment, self).__init__(parent=None, title=title) + self.indexes = [] + self.attachments_list = attachments + panel = wx.Panel(self) + sizer = wx.BoxSizer(wx.HORIZONTAL) + label = wx.StaticText(panel, -1, _("Available attachments")) + self.cb = wx.ComboBox(panel, -1, choices=attachments, value=attachments[0]) + self.cb.SetFocus() + attachmentSizer = wx.BoxSizer() + attachmentSizer.Add(label, 0, wx.ALL, 5) + attachmentSizer.Add(self.cb, 0, wx.ALL, 5) + self.add = wx.Button(panel, wx.NewId(), _("Select")) + self.add.Bind(wx.EVT_BUTTON, self.add_attachment) + attachmentSizer.Add(self.add, 0, wx.ALL, 5) + sizer.Add(attachmentSizer, 0, wx.ALL, 5) + lbl = wx.StaticText(panel, wx.NewId(), _("Selected attachments")) + self.attachments = wx.ListBox(panel, -1) + self.remove = wx.Button(panel, wx.NewId(), _("Remove")) + self.remove.Bind(wx.EVT_BUTTON, self.remove_attachment) + selectionSizer = wx.BoxSizer(wx.HORIZONTAL) + selectionSizer.Add(lbl, 0, wx.ALL, 5) + selectionSizer.Add(self.attachments, 0, wx.ALL, 5) + selectionSizer.Add(self.remove, 0, wx.ALL, 5) + sizer.Add(selectionSizer, 0, wx.ALL, 5) + ok = wx.Button(panel, wx.ID_OK, _("&OK")) + ok.SetDefault() + cancel = wx.Button(panel, wx.ID_CANCEL, _("&Close")) + 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()) - def get_attachment(self): - return self.cb.GetValue() + def get_attachment(self): + return self.cb.GetValue() - def add_attachment(self, *args, **kwargs): - selection = self.get_attachment() - if selection in self.attachments_list: - self.attachments.Append(selection) - self.indexes.append(self.cb.GetSelection()) - self.remove.Enable(True) + def add_attachment(self, *args, **kwargs): + selection = self.get_attachment() + if selection in self.attachments_list: + self.attachments.Append(selection) + self.indexes.append(self.cb.GetSelection()) + self.remove.Enable(True) - def remove_attachment(self, *args, **kwargs): - n = self.attachments.GetSelection() - self.attachments.Delete(n) - self.indexes.pop(n) - if len(self.indexes) == 0: - self.remove.Enable(False) + def remove_attachment(self, *args, **kwargs): + n = self.attachments.GetSelection() + self.attachments.Delete(n) + self.indexes.pop(n) + if len(self.indexes) == 0: + self.remove.Enable(False) - def get_all_attachments(self): - return self.indexes \ No newline at end of file + def get_all_attachments(self): + return self.indexes diff --git a/src/wxUI/dialogs/timeline.py b/src/wxUI/dialogs/timeline.py index 0388ee7..91408f0 100644 --- a/src/wxUI/dialogs/timeline.py +++ b/src/wxUI/dialogs/timeline.py @@ -5,47 +5,47 @@ import widgetUtils class timelineDialog(widgetUtils.BaseDialog): - def __init__(self, users=[], show_selector=True): - super(timelineDialog, self).__init__(parent=None, title=_("New timeline for {0}").format(users[0],)) - panel = wx.Panel(self) - sizer = wx.BoxSizer(wx.HORIZONTAL) - if show_selector: - userLabel = wx.StaticText(panel, -1, _("User")) - self.cb = wx.ComboBox(panel, -1, choices=users, value=users[0]) - self.cb.SetFocus() - userSizer = wx.BoxSizer() - userSizer.Add(userLabel, 0, wx.ALL, 5) - userSizer.Add(self.cb, 0, wx.ALL, 5) - sizer.Add(userSizer, 0, wx.ALL, 5) - actionsSizer = wx.StaticBoxSizer(parent=panel, orient=wx.VERTICAL, label=_("Buffer type")) - self.wall = wx.RadioButton(actionsSizer.GetStaticBox(), wx.NewId(), _("&Wall posts"), style=wx.RB_GROUP) - self.audio = wx.RadioButton(actionsSizer.GetStaticBox(), wx.NewId(), _("Audio")) - self.video = wx.RadioButton(actionsSizer.GetStaticBox(), wx.NewId(), _("Video")) - self.friends = wx.RadioButton(actionsSizer.GetStaticBox(), wx.NewId(), _("Friends")) - actionsSizer.Add(self.wall, 0, wx.ALL, 5) - actionsSizer.Add(self.audio, 0, wx.ALL, 5) - actionsSizer.Add(self.video, 0, wx.ALL, 5) - actionsSizer.Add(self.friends, 0, wx.ALL, 5) - sizer.Add(actionsSizer, 0, wx.ALL, 5) - ok = wx.Button(panel, wx.ID_OK, _("&OK")) - ok.SetDefault() - cancel = wx.Button(panel, wx.ID_CANCEL, _("&Close")) - btnsizer = wx.BoxSizer(wx.HORIZONTAL) - 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()) + def __init__(self, users=[], show_selector=True): + super(timelineDialog, self).__init__(parent=None, title=_("New timeline for {0}").format(users[0],)) + panel = wx.Panel(self) + sizer = wx.BoxSizer(wx.HORIZONTAL) + if show_selector: + userLabel = wx.StaticText(panel, -1, _("User")) + self.cb = wx.ComboBox(panel, -1, choices=users, value=users[0]) + self.cb.SetFocus() + userSizer = wx.BoxSizer() + userSizer.Add(userLabel, 0, wx.ALL, 5) + userSizer.Add(self.cb, 0, wx.ALL, 5) + sizer.Add(userSizer, 0, wx.ALL, 5) + actionsSizer = wx.StaticBoxSizer(parent=panel, orient=wx.VERTICAL, label=_("Buffer type")) + self.wall = wx.RadioButton(actionsSizer.GetStaticBox(), wx.NewId(), _("&Wall posts"), style=wx.RB_GROUP) + self.audio = wx.RadioButton(actionsSizer.GetStaticBox(), wx.NewId(), _("Audio")) + self.video = wx.RadioButton(actionsSizer.GetStaticBox(), wx.NewId(), _("Video")) + self.friends = wx.RadioButton(actionsSizer.GetStaticBox(), wx.NewId(), _("Friends")) + actionsSizer.Add(self.wall, 0, wx.ALL, 5) + actionsSizer.Add(self.audio, 0, wx.ALL, 5) + actionsSizer.Add(self.video, 0, wx.ALL, 5) + actionsSizer.Add(self.friends, 0, wx.ALL, 5) + sizer.Add(actionsSizer, 0, wx.ALL, 5) + ok = wx.Button(panel, wx.ID_OK, _("&OK")) + ok.SetDefault() + cancel = wx.Button(panel, wx.ID_CANCEL, _("&Close")) + btnsizer = wx.BoxSizer(wx.HORIZONTAL) + 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()) - def get_user(self): - return self.cb.GetValue() + def get_user(self): + return self.cb.GetValue() - def get_buffer_type(self): - if self.audio.GetValue() == True: - return "audio" - elif self.video.GetValue() == True: - return "video" - elif self.wall.GetValue() == True: - return "wall" - elif self.friends.GetValue() == True: - return "friends" \ No newline at end of file + def get_buffer_type(self): + if self.audio.GetValue() == True: + return "audio" + elif self.video.GetValue() == True: + return "video" + elif self.wall.GetValue() == True: + return "wall" + elif self.friends.GetValue() == True: + return "friends" diff --git a/src/wxUI/dialogs/urlList.py b/src/wxUI/dialogs/urlList.py index 1c38c62..e4f029c 100644 --- a/src/wxUI/dialogs/urlList.py +++ b/src/wxUI/dialogs/urlList.py @@ -3,34 +3,34 @@ from __future__ import unicode_literals import wx class urlList(wx.Dialog): - def __init__(self): - super(urlList, self).__init__(parent=None, title=_("Select URL")) - 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 __init__(self): + super(urlList, self).__init__(parent=None, title=_("Select URL")) + 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 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_string(self): + return self.lista.GetStringSelection() - def get_item(self): - return self.lista.GetSelection() + def get_item(self): + return self.lista.GetSelection() - def get_response(self): - return self.ShowModal() \ No newline at end of file + def get_response(self): + return self.ShowModal() diff --git a/src/wxUI/mainWindow.py b/src/wxUI/mainWindow.py index d122163..e58a446 100644 --- a/src/wxUI/mainWindow.py +++ b/src/wxUI/mainWindow.py @@ -5,159 +5,159 @@ import application from pubsub import pub class mainWindow(wx.Frame): - def makeMenu(self): - mb = wx.MenuBar() - app_ = wx.Menu() - create = wx.Menu() - self.audio_album = create.Append(wx.NewId(), _("Audio album")) - self.video_album = create.Append(wx.NewId(), _("Video album")) - app_.Append(wx.NewId(), _("Create"), create) - delete = wx.Menu() - self.delete_audio_album = delete.Append(wx.NewId(), _("Audio album")) - self.delete_video_album = delete.Append(wx.NewId(), _("Video album")) - app_.Append(wx.NewId(), _("Delete"), delete) - self.blacklist = app_.Append(wx.NewId(), _("Blacklist")) - self.accounts = app_.Append(wx.NewId(), _("Manage accounts")) - self.settings_dialog = app_.Append(wx.NewId(), _("Preferences")) - me = wx.Menu() - profile = wx.Menu() - self.view_profile = profile.Append(wx.NewId(), _("View profile")) -# self.edit_profile = profile.Append(wx.NewId(), _("Edit profile")) - self.open_in_browser = profile.Append(wx.NewId(), _("Open in browser")) - me.Append(wx.NewId(), _("Profile"), profile) - self.set_status = me.Append(wx.NewId(), _("Set status message")) - buffer = wx.Menu() - search = wx.Menu() - self.search_audios = search.Append(wx.NewId(), _("Audio")) - self.search_videos = search.Append(wx.NewId(), _("Video")) - self.timeline = buffer.Append(wx.NewId(), _("&New timeline")) - buffer.Append(wx.NewId(), _("Search"), search) - self.update_buffer = buffer.Append(wx.NewId(), _("Update current buffer")) - self.load_previous_items = buffer.Append(wx.NewId(), _("Load previous items")) - self.remove_buffer_ = buffer.Append(wx.NewId(), _("&Remove buffer")) - mb.Append(app_, _("Application")) - mb.Append(me, _("Me")) - mb.Append(buffer, _("Buffer")) - player = wx.Menu() - self.player_play = player.Append(wx.NewId(), _("Play/Pause")) - self.player_play_all = player.Append(wx.NewId(), _("Play all")) - self.player_previous = player.Append(wx.NewId(), _("Previous")) - self.player_next = player.Append(wx.NewId(), _("Next")) - self.player_shuffle = player.AppendCheckItem(wx.NewId(), _("Shuffle")) - self.player_seek_left = player.Append(wx.NewId(), _("Seek backwards")) - self.player_seek_right = player.Append(wx.NewId(), _("Seek forwards")) - self.player_volume_up = player.Append(wx.NewId(), _("Volume up")) - self.player_volume_down = player.Append(wx.NewId(), _("Volume down")) - self.player_mute = player.Append(wx.NewId(), _("Mute")) - help_ = wx.Menu() - self.about = help_.Append(wx.NewId(), _("About {0}").format(application.name,)) - self.documentation = help_.Append(wx.NewId(), _("Manual")) - self.check_for_updates = help_.Append(wx.NewId(), _("Check for updates")) - self.changelog = help_.Append(wx.NewId(), _("Chan&gelog")) - self.open_logs = help_.Append(wx.NewId(), _("Open logs directory")) - self.open_config = help_.Append(wx.NewId(), _("Open config directory")) + def makeMenu(self): + mb = wx.MenuBar() + app_ = wx.Menu() + create = wx.Menu() + self.audio_album = create.Append(wx.NewId(), _("Audio album")) + self.video_album = create.Append(wx.NewId(), _("Video album")) + app_.Append(wx.NewId(), _("Create"), create) + delete = wx.Menu() + self.delete_audio_album = delete.Append(wx.NewId(), _("Audio album")) + self.delete_video_album = delete.Append(wx.NewId(), _("Video album")) + app_.Append(wx.NewId(), _("Delete"), delete) + self.blacklist = app_.Append(wx.NewId(), _("Blacklist")) + self.accounts = app_.Append(wx.NewId(), _("Manage accounts")) + self.settings_dialog = app_.Append(wx.NewId(), _("Preferences")) + me = wx.Menu() + profile = wx.Menu() + self.view_profile = profile.Append(wx.NewId(), _("View profile")) +# self.edit_profile = profile.Append(wx.NewId(), _("Edit profile")) + self.open_in_browser = profile.Append(wx.NewId(), _("Open in browser")) + me.Append(wx.NewId(), _("Profile"), profile) + self.set_status = me.Append(wx.NewId(), _("Set status message")) + buffer = wx.Menu() + search = wx.Menu() + self.search_audios = search.Append(wx.NewId(), _("Audio")) + self.search_videos = search.Append(wx.NewId(), _("Video")) + self.timeline = buffer.Append(wx.NewId(), _("&New timeline")) + buffer.Append(wx.NewId(), _("Search"), search) + self.update_buffer = buffer.Append(wx.NewId(), _("Update current buffer")) + self.load_previous_items = buffer.Append(wx.NewId(), _("Load previous items")) + self.remove_buffer_ = buffer.Append(wx.NewId(), _("&Remove buffer")) + mb.Append(app_, _("Application")) + mb.Append(me, _("Me")) + mb.Append(buffer, _("Buffer")) + player = wx.Menu() + self.player_play = player.Append(wx.NewId(), _("Play/Pause")) + self.player_play_all = player.Append(wx.NewId(), _("Play all")) + self.player_previous = player.Append(wx.NewId(), _("Previous")) + self.player_next = player.Append(wx.NewId(), _("Next")) + self.player_shuffle = player.AppendCheckItem(wx.NewId(), _("Shuffle")) + self.player_seek_left = player.Append(wx.NewId(), _("Seek backwards")) + self.player_seek_right = player.Append(wx.NewId(), _("Seek forwards")) + self.player_volume_up = player.Append(wx.NewId(), _("Volume up")) + self.player_volume_down = player.Append(wx.NewId(), _("Volume down")) + self.player_mute = player.Append(wx.NewId(), _("Mute")) + help_ = wx.Menu() + self.about = help_.Append(wx.NewId(), _("About {0}").format(application.name,)) + self.documentation = help_.Append(wx.NewId(), _("Manual")) + self.check_for_updates = help_.Append(wx.NewId(), _("Check for updates")) + self.changelog = help_.Append(wx.NewId(), _("Chan&gelog")) + self.open_logs = help_.Append(wx.NewId(), _("Open logs directory")) + self.open_config = help_.Append(wx.NewId(), _("Open config directory")) - self.report = help_.Append(wx.NewId(), _("Report an error")) - mb.Append(player, _("Audio player")) - mb.Append(help_, _("Help")) - self.SetMenuBar(mb) - self.accel_tbl = wx.AcceleratorTable([ - # Assign keystrokes to control the player object. - (wx.ACCEL_ALT, wx.WXK_LEFT, self.player_previous.GetId()), - (wx.ACCEL_ALT, wx.WXK_RIGHT, self.player_next.GetId()), - (wx.ACCEL_ALT, wx.WXK_DOWN, self.player_volume_down.GetId()), - (wx.ACCEL_ALT, wx.WXK_UP, self.player_volume_up.GetId()), - # Translators: Keystroke used to play/pause the current item in the playback queue. Use the latin alphabet, but you can match a different key here. For example if you want to assign this to the key "П", use G. - (wx.ACCEL_CTRL, ord(_("P")), self.player_play.GetId()), - (wx.ACCEL_CTRL|wx.ACCEL_SHIFT, ord(_("P")), self.player_play_all.GetId()), - (wx.ACCEL_ALT|wx.ACCEL_SHIFT, wx.WXK_LEFT, self.player_seek_left.GetId()), - (wx.ACCEL_ALT|wx.ACCEL_SHIFT, wx.WXK_RIGHT, self.player_seek_right.GetId()), - ]) - self.SetAcceleratorTable(self.accel_tbl) + self.report = help_.Append(wx.NewId(), _("Report an error")) + mb.Append(player, _("Audio player")) + mb.Append(help_, _("Help")) + self.SetMenuBar(mb) + self.accel_tbl = wx.AcceleratorTable([ + # Assign keystrokes to control the player object. + (wx.ACCEL_ALT, wx.WXK_LEFT, self.player_previous.GetId()), + (wx.ACCEL_ALT, wx.WXK_RIGHT, self.player_next.GetId()), + (wx.ACCEL_ALT, wx.WXK_DOWN, self.player_volume_down.GetId()), + (wx.ACCEL_ALT, wx.WXK_UP, self.player_volume_up.GetId()), + # Translators: Keystroke used to play/pause the current item in the playback queue. Use the latin alphabet, but you can match a different key here. For example if you want to assign this to the key "П", use G. + (wx.ACCEL_CTRL, ord(_("P")), self.player_play.GetId()), + (wx.ACCEL_CTRL|wx.ACCEL_SHIFT, ord(_("P")), self.player_play_all.GetId()), + (wx.ACCEL_ALT|wx.ACCEL_SHIFT, wx.WXK_LEFT, self.player_seek_left.GetId()), + (wx.ACCEL_ALT|wx.ACCEL_SHIFT, wx.WXK_RIGHT, self.player_seek_right.GetId()), + ]) + self.SetAcceleratorTable(self.accel_tbl) - def __init__(self): - super(mainWindow, self).__init__(parent=None, id=wx.NewId(), title=application.name) - self.Maximize() - self.makeMenu() - self.panel = wx.Panel(self) - self.sizer = wx.BoxSizer(wx.VERTICAL) - self.sb = self.CreateStatusBar() - self.tb = wx.Treebook(self.panel, -1) - self.sizer.Add(self.tb, 1, wx.ALL|wx.EXPAND, 5) - pub.subscribe(self.change_status, "change_status") + def __init__(self): + super(mainWindow, self).__init__(parent=None, id=wx.NewId(), title=application.name) + self.Maximize() + self.makeMenu() + self.panel = wx.Panel(self) + self.sizer = wx.BoxSizer(wx.VERTICAL) + self.sb = self.CreateStatusBar() + self.tb = wx.Treebook(self.panel, -1) + self.sizer.Add(self.tb, 1, wx.ALL|wx.EXPAND, 5) + pub.subscribe(self.change_status, "change_status") - def realize(self): - self.panel.SetSizer(self.sizer) - self.SetClientSize(self.sizer.CalcMin()) - self.Layout() - self.SetSize(self.GetBestSize()) + def realize(self): + self.panel.SetSizer(self.sizer) + self.SetClientSize(self.sizer.CalcMin()) + self.Layout() + self.SetSize(self.GetBestSize()) - def change_status(self, status): - wx.CallAfter(self.sb.SetStatusText, status) + def change_status(self, status): + wx.CallAfter(self.sb.SetStatusText, status) - def connection_error(self): - wx.MessageDialog(self, _("There is a connection error. Check your internet connection and try again later."), _("Connection error"), wx.ICON_ERROR).ShowModal() + def connection_error(self): + wx.MessageDialog(self, _("There is a connection error. Check your internet connection and try again later."), _("Connection error"), wx.ICON_ERROR).ShowModal() - def get_buffer_count(self): - return self.tb.GetPageCount() + def get_buffer_count(self): + return self.tb.GetPageCount() - def add_buffer(self, buffer, name): - self.tb.AddPage(buffer, name) + def add_buffer(self, buffer, name): + self.tb.AddPage(buffer, name) - def insert_buffer(self, buffer, name, pos): - return self.tb.InsertSubPage(pos, buffer, name) + def insert_buffer(self, buffer, name, pos): + return self.tb.InsertSubPage(pos, buffer, name) - def insert_chat_buffer(self, buffer, name, pos): - return self.tb.InsertPage(pos, buffer, name) + def insert_chat_buffer(self, buffer, name, pos): + return self.tb.InsertPage(pos, buffer, name) - def search(self, name_): - for i in range(0, self.tb.GetPageCount()): - if self.tb.GetPage(i).name == name_: return i + def search(self, name_): + for i in range(0, self.tb.GetPageCount()): + if self.tb.GetPage(i).name == name_: return i - def get_current_buffer(self): - return self.tb.GetCurrentPage() + def get_current_buffer(self): + return self.tb.GetCurrentPage() - def get_current_buffer_pos(self): - return self.tb.GetSelection() + def get_current_buffer_pos(self): + return self.tb.GetSelection() - def get_buffer(self, pos): - return self.GetPage(pos) + def get_buffer(self, pos): + return self.GetPage(pos) - def change_buffer(self, position): - self.tb.ChangeSelection(position) + def change_buffer(self, position): + self.tb.ChangeSelection(position) - def get_buffer_text(self, pos=None): - if pos == None: - pos = self.tb.GetSelection() - return self.tb.GetPageText(pos) + def get_buffer_text(self, pos=None): + if pos == None: + pos = self.tb.GetSelection() + return self.tb.GetPageText(pos) - def get_buffer_by_id(self, id): - return self.nb.FindWindowById(id) + def get_buffer_by_id(self, id): + return self.nb.FindWindowById(id) - def advance_selection(self, forward): - self.tb.AdvanceSelection(forward) + def advance_selection(self, forward): + self.tb.AdvanceSelection(forward) - def about_dialog(self, channel="stable", *args, **kwargs): - if channel == "stable": - version = _("{version} (stable)").format(version=application.version) - else: - version = _("{version} (alpha)").format(version=application.update_next_version) - info = wx.adv.AboutDialogInfo() - info.SetName(application.name) - info.SetVersion(version) - info.SetDescription(application.description) - info.SetCopyright(application.copyright) - info.SetTranslators(application.translators) + def about_dialog(self, channel="stable", *args, **kwargs): + if channel == "stable": + version = _("{version} (stable)").format(version=application.version) + else: + version = _("{version} (alpha)").format(version=application.update_next_version) + info = wx.adv.AboutDialogInfo() + info.SetName(application.name) + info.SetVersion(version) + info.SetDescription(application.description) + info.SetCopyright(application.copyright) + info.SetTranslators(application.translators) # info.SetLicence(application.licence) - info.AddDeveloper(application.author) - wx.adv.AboutBox(info) + info.AddDeveloper(application.author) + wx.adv.AboutBox(info) - def remove_buffer(self, pos): - self.tb.DeletePage(pos) + def remove_buffer(self, pos): + self.tb.DeletePage(pos) - def remove_buffer_from_position(self, pos): - return self.tb.RemovePage(pos) + def remove_buffer_from_position(self, pos): + return self.tb.RemovePage(pos) - def notify(self, title, text): - self.notification = wx.adv.NotificationMessage(title=title, message=text, parent=self) - self.notification.Show() \ No newline at end of file + def notify(self, title, text): + self.notification = wx.adv.NotificationMessage(title=title, message=text, parent=self) + self.notification.Show() diff --git a/src/wxUI/menus.py b/src/wxUI/menus.py index cb657be..1c51803 100644 --- a/src/wxUI/menus.py +++ b/src/wxUI/menus.py @@ -4,113 +4,113 @@ from __future__ import unicode_literals import wx class postMenu(wx.Menu): - """ Display a menu with actions related to posts in the news feed or walls. """ + """ Display a menu with actions related to posts in the news feed or walls. """ - def __init__(self, can_delete=False, *args, **kwargs): - super(postMenu, self).__init__(*args, **kwargs) - self.open = self.Append(wx.NewId(), _("Open")) - self.like = self.Append(wx.NewId(), _("Like")) - self.dislike = self.Append(wx.NewId(), _("Dislike")) - self.dislike.Enable(False) - self.comment = self.Append(wx.NewId(), _("Add comment")) - self.fav = self.Append(wx.NewId(), _("Add to favorites")) - self.fav.Enable(False) - if can_delete: - self.delete = self.Append(wx.NewId(), _("Delete")) - else: - self.post_in_wall = self.Append(wx.NewId(), _("Post to this profile")) - self.post_in_wall.Enable(False) - self.view_profile = self.Append(wx.NewId(), _("View user profile")) - self.open_in_browser = self.Append(wx.NewId(), _("Open in vk.com")) + def __init__(self, can_delete=False, *args, **kwargs): + super(postMenu, self).__init__(*args, **kwargs) + self.open = self.Append(wx.NewId(), _("Open")) + self.like = self.Append(wx.NewId(), _("Like")) + self.dislike = self.Append(wx.NewId(), _("Dislike")) + self.dislike.Enable(False) + self.comment = self.Append(wx.NewId(), _("Add comment")) + self.fav = self.Append(wx.NewId(), _("Add to favorites")) + self.fav.Enable(False) + if can_delete: + self.delete = self.Append(wx.NewId(), _("Delete")) + else: + self.post_in_wall = self.Append(wx.NewId(), _("Post to this profile")) + self.post_in_wall.Enable(False) + self.view_profile = self.Append(wx.NewId(), _("View user profile")) + self.open_in_browser = self.Append(wx.NewId(), _("Open in vk.com")) class audioMenu(wx.Menu): - def __init__(self, *args, **kwargs): - super(audioMenu, self).__init__(*args, **kwargs) - self.open = self.Append(wx.NewId(), _("&Open")) - self.play = self.Append(wx.NewId(), _("&Play")) - self.library = self.Append(wx.NewId(), _("&Add to library")) - self.move = self.Append(wx.NewId(), _("Move to album")) - self.download = self.Append(wx.NewId(), _("Download")) - self.select = self.Append(wx.NewId(), _("Select all")) - self.deselect = self.Append(wx.NewId(), _("Unselect all")) + def __init__(self, *args, **kwargs): + super(audioMenu, self).__init__(*args, **kwargs) + self.open = self.Append(wx.NewId(), _("&Open")) + self.play = self.Append(wx.NewId(), _("&Play")) + self.library = self.Append(wx.NewId(), _("&Add to library")) + self.move = self.Append(wx.NewId(), _("Move to album")) + self.download = self.Append(wx.NewId(), _("Download")) + self.select = self.Append(wx.NewId(), _("Select all")) + self.deselect = self.Append(wx.NewId(), _("Unselect all")) class peopleMenu(wx.Menu): - def __init__(self, is_request=False, is_subscriber=False, not_friend=False, *args, **kwargs): - super(peopleMenu, self).__init__(*args, **kwargs) - if is_request: - self.create_request_items() - elif is_subscriber: - self.create_subscriber_items() - self.view_profile = self.Append(wx.NewId(), _("View profile")) - self.message = self.Append(wx.NewId(), _("Send a message")) - self.timeline = self.Append(wx.NewId(), _("Open timeline")) - self.fav = self.Append(wx.NewId(), _("Add to favorites")) - self.fav.Enable(False) - if not_friend == False: - self.common_friends = self.Append(wx.NewId(), _("View friends in common")) - if is_request == False and is_subscriber == False and not_friend == False: - self.decline = self.Append(wx.NewId(), _("Remove from friends")) - self.block = self.Append(wx.NewId(), _("Block")) - self.open_in_browser = self.Append(wx.NewId(), _("Open in vk.com")) + def __init__(self, is_request=False, is_subscriber=False, not_friend=False, *args, **kwargs): + super(peopleMenu, self).__init__(*args, **kwargs) + if is_request: + self.create_request_items() + elif is_subscriber: + self.create_subscriber_items() + self.view_profile = self.Append(wx.NewId(), _("View profile")) + self.message = self.Append(wx.NewId(), _("Send a message")) + self.timeline = self.Append(wx.NewId(), _("Open timeline")) + self.fav = self.Append(wx.NewId(), _("Add to favorites")) + self.fav.Enable(False) + if not_friend == False: + self.common_friends = self.Append(wx.NewId(), _("View friends in common")) + if is_request == False and is_subscriber == False and not_friend == False: + self.decline = self.Append(wx.NewId(), _("Remove from friends")) + self.block = self.Append(wx.NewId(), _("Block")) + self.open_in_browser = self.Append(wx.NewId(), _("Open in vk.com")) - def create_request_items(self): - self.accept = self.Append(wx.NewId(), _("Accept")) - self.decline = self.Append(wx.NewId(), _("Decline")) - self.keep_as_follower = self.Append(wx.NewId(), _("Keep as follower")) - self.block = self.Append(wx.NewId(), _("Block")) + def create_request_items(self): + self.accept = self.Append(wx.NewId(), _("Accept")) + self.decline = self.Append(wx.NewId(), _("Decline")) + self.keep_as_follower = self.Append(wx.NewId(), _("Keep as follower")) + self.block = self.Append(wx.NewId(), _("Block")) - def create_subscriber_items(self): - self.add = self.Append(wx.NewId(), _("Add to friends")) - self.block = self.Append(wx.NewId(), _("Block")) + def create_subscriber_items(self): + self.add = self.Append(wx.NewId(), _("Add to friends")) + self.block = self.Append(wx.NewId(), _("Block")) class documentMenu(wx.Menu): - def __init__(self, added=False, *args, **kwargs): - super(documentMenu, self).__init__(*args, **kwargs) - self.download = self.Append(wx.NewId(), _("Download document")) - if added == True: - self.action = self.Append(wx.NewId(), _("Remove from my documents")) - else: - self.action = self.Append(wx.NewId(), _("Add to my documents")) - self.open_in_browser = self.Append(wx.NewId(), _("Open in vk.com")) - self.fav = self.Append(wx.NewId(), _("Add to favorites")) - self.fav.Enable(False) + def __init__(self, added=False, *args, **kwargs): + super(documentMenu, self).__init__(*args, **kwargs) + self.download = self.Append(wx.NewId(), _("Download document")) + if added == True: + self.action = self.Append(wx.NewId(), _("Remove from my documents")) + else: + self.action = self.Append(wx.NewId(), _("Add to my documents")) + self.open_in_browser = self.Append(wx.NewId(), _("Open in vk.com")) + self.fav = self.Append(wx.NewId(), _("Add to favorites")) + self.fav.Enable(False) class commentMenu(wx.Menu): - def __init__(self, *args, **kwargs): - super(commentMenu, self).__init__(*args, **kwargs) - self.open = self.Append(wx.NewId(), _("Open")) - self.like = self.Append(wx.NewId(), _("Like")) - self.dislike = self.Append(wx.NewId(), _("Dislike")) - self.open_in_browser = self.Append(wx.NewId(), _("Open in vk.com")) + def __init__(self, *args, **kwargs): + super(commentMenu, self).__init__(*args, **kwargs) + self.open = self.Append(wx.NewId(), _("Open")) + self.like = self.Append(wx.NewId(), _("Like")) + self.dislike = self.Append(wx.NewId(), _("Dislike")) + self.open_in_browser = self.Append(wx.NewId(), _("Open in vk.com")) class attachMenu(wx.Menu): - def __init__(self): - super(attachMenu, self).__init__() - self.upload = self.Append(wx.NewId(), _("Upload from computer")) - self.add = self.Append(wx.NewId(), _("Add from VK")) + def __init__(self): + super(attachMenu, self).__init__() + self.upload = self.Append(wx.NewId(), _("Upload from computer")) + self.add = self.Append(wx.NewId(), _("Add from VK")) class communityBufferMenu(wx.Menu): - def __init__(self): - super(communityBufferMenu, self).__init__() - load = wx.Menu() - self.load_posts = load.Append(wx.NewId(), _("Load posts")) - self.load_topics = load.Append(wx.NewId(), _("Load topics")) - self.load_members = load.Append(wx.NewId(), _("Load members")) - self.load_audios = load.Append(wx.NewId(), _("Load audios")) - self.load_videos = load.Append(wx.NewId(), _("Load videos")) - self.load_documents = load.Append(wx.NewId(), _("Load documents")) - self.Append(wx.NewId(), _("Load"), load) - self.open_in_browser = self.Append(wx.NewId(), _("Open in vk.com")) + def __init__(self): + super(communityBufferMenu, self).__init__() + load = wx.Menu() + self.load_posts = load.Append(wx.NewId(), _("Load posts")) + self.load_topics = load.Append(wx.NewId(), _("Load topics")) + self.load_members = load.Append(wx.NewId(), _("Load members")) + self.load_audios = load.Append(wx.NewId(), _("Load audios")) + self.load_videos = load.Append(wx.NewId(), _("Load videos")) + self.load_documents = load.Append(wx.NewId(), _("Load documents")) + self.Append(wx.NewId(), _("Load"), load) + self.open_in_browser = self.Append(wx.NewId(), _("Open in vk.com")) class conversationBufferMenu(wx.Menu): - def __init__(self): - super(conversationBufferMenu, self).__init__() - self.delete = self.Append(wx.NewId(), _("Delete conversation")) - self.open_in_browser = self.Append(wx.NewId(), _("Open in vk.com")) + def __init__(self): + super(conversationBufferMenu, self).__init__() + self.delete = self.Append(wx.NewId(), _("Delete conversation")) + self.open_in_browser = self.Append(wx.NewId(), _("Open in vk.com")) class toolsMenu(wx.Menu): - def __init__(self, *args, **kwargs): - super(toolsMenu, self).__init__(*args, **kwargs) - self.translate = self.Append(wx.NewId(), _("&Translate message")) - self.spellcheck = self.Append(wx.NewId(), _("Spelling &correction")) \ No newline at end of file + def __init__(self, *args, **kwargs): + super(toolsMenu, self).__init__(*args, **kwargs) + self.translate = self.Append(wx.NewId(), _("&Translate message")) + self.spellcheck = self.Append(wx.NewId(), _("Spelling &correction")) diff --git a/src/wxUI/tabs/audio.py b/src/wxUI/tabs/audio.py index bcdb07e..ded286f 100644 --- a/src/wxUI/tabs/audio.py +++ b/src/wxUI/tabs/audio.py @@ -4,36 +4,36 @@ import widgetUtils from .home import homeTab class audioTab(homeTab): - def create_list(self): - self.lbl = wx.StaticText(self, wx.NewId(), _("Mu&sic")) - self.list = widgetUtils.multiselectionList(self, *[_("Title"), _("Artist"), _("Duration")], style=wx.LC_REPORT, name=_("Music")) - self.list.set_windows_size(0, 160) - self.list.set_windows_size(1, 380) - self.list.set_windows_size(2, 80) - self.list.set_size() - self.list.list.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnKeyDown) + def create_list(self): + self.lbl = wx.StaticText(self, wx.NewId(), _("Mu&sic")) + self.list = widgetUtils.multiselectionList(self, *[_("Title"), _("Artist"), _("Duration")], style=wx.LC_REPORT, name=_("Music")) + self.list.set_windows_size(0, 160) + self.list.set_windows_size(1, 380) + self.list.set_windows_size(2, 80) + self.list.set_size() + self.list.list.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnKeyDown) - def create_post_buttons(self): - self.postBox = wx.StaticBoxSizer(parent=self, orient=wx.HORIZONTAL, label=_("Actions")) - self.post = wx.Button(self.postBox.GetStaticBox(), -1, _("&Upload audio")) - self.post.Enable(False) - self.play = wx.Button(self.postBox.GetStaticBox(), -1, _("P&lay")) - self.play_all = wx.Button(self.postBox.GetStaticBox(), -1, _("Play &All")) - self.postBox.Add(self.post, 0, wx.ALL, 5) - self.postBox.Add(self.play, 0, wx.ALL, 5) - self.postBox.Add(self.play_all, 0, wx.ALL, 5) + def create_post_buttons(self): + self.postBox = wx.StaticBoxSizer(parent=self, orient=wx.HORIZONTAL, label=_("Actions")) + self.post = wx.Button(self.postBox.GetStaticBox(), -1, _("&Upload audio")) + self.post.Enable(False) + self.play = wx.Button(self.postBox.GetStaticBox(), -1, _("P&lay")) + self.play_all = wx.Button(self.postBox.GetStaticBox(), -1, _("Play &All")) + self.postBox.Add(self.post, 0, wx.ALL, 5) + self.postBox.Add(self.play, 0, wx.ALL, 5) + self.postBox.Add(self.play_all, 0, wx.ALL, 5) - def get_file_to_upload(self): - openFileDialog = wx.FileDialog(self, _("Select the audio file to be uploaded"), "", "", _("Audio files (*.mp3)|*.mp3"), wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) - if openFileDialog.ShowModal() == wx.ID_CANCEL: - return None - return openFileDialog.GetPath() + def get_file_to_upload(self): + openFileDialog = wx.FileDialog(self, _("Select the audio file to be uploaded"), "", "", _("Audio files (*.mp3)|*.mp3"), wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) + if openFileDialog.ShowModal() == wx.ID_CANCEL: + return None + return openFileDialog.GetPath() - def get_download_path(self, filename="", multiple=False): - if multiple == False: - d = wx.FileDialog(self, _("Save this file"), "", filename, _("Audio Files(*.mp3)|*.mp3"), wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) - else: - d = wx.DirDialog(None, _("Select a folder to save all files")) - if d.ShowModal() == wx.ID_OK: - return d.GetPath() - d.Destroy() \ No newline at end of file + def get_download_path(self, filename="", multiple=False): + if multiple == False: + d = wx.FileDialog(self, _("Save this file"), "", filename, _("Audio Files(*.mp3)|*.mp3"), wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) + else: + d = wx.DirDialog(None, _("Select a folder to save all files")) + if d.ShowModal() == wx.ID_OK: + return d.GetPath() + d.Destroy() diff --git a/src/wxUI/tabs/audioAlbum.py b/src/wxUI/tabs/audioAlbum.py index dc426b0..471acd7 100644 --- a/src/wxUI/tabs/audioAlbum.py +++ b/src/wxUI/tabs/audioAlbum.py @@ -4,13 +4,13 @@ from .audio import audioTab class audioAlbumTab(audioTab): - def create_post_buttons(self): - self.postBox = wx.StaticBoxSizer(parent=self, orient=wx.HORIZONTAL, label=_("Actions")) - self.load = wx.Button(self.postBox.GetStaticBox(), wx.NewId(), _("Load buffer")) - self.post = wx.Button(self.postBox.GetStaticBox(), -1, _("&Post")) - self.play = wx.Button(self.postBox.GetStaticBox(), -1, _("P&lay")) - self.play_all = wx.Button(self.postBox.GetStaticBox(), -1, _("Play &All")) - self.postBox.Add(self.load, 0, wx.ALL, 5) - self.postBox.Add(self.post, 0, wx.ALL, 5) - self.postBox.Add(self.play, 0, wx.ALL, 5) - self.postBox.Add(self.play_all, 0, wx.ALL, 5) \ No newline at end of file + def create_post_buttons(self): + self.postBox = wx.StaticBoxSizer(parent=self, orient=wx.HORIZONTAL, label=_("Actions")) + self.load = wx.Button(self.postBox.GetStaticBox(), wx.NewId(), _("Load buffer")) + self.post = wx.Button(self.postBox.GetStaticBox(), -1, _("&Post")) + self.play = wx.Button(self.postBox.GetStaticBox(), -1, _("P&lay")) + self.play_all = wx.Button(self.postBox.GetStaticBox(), -1, _("Play &All")) + self.postBox.Add(self.load, 0, wx.ALL, 5) + self.postBox.Add(self.post, 0, wx.ALL, 5) + self.postBox.Add(self.play, 0, wx.ALL, 5) + self.postBox.Add(self.play_all, 0, wx.ALL, 5) diff --git a/src/wxUI/tabs/chat.py b/src/wxUI/tabs/chat.py index 73e2468..8ce79c5 100644 --- a/src/wxUI/tabs/chat.py +++ b/src/wxUI/tabs/chat.py @@ -6,75 +6,75 @@ from pubsub import pub class chatTab(wx.Panel): - def insert_attachments(self, attachments): - """ Insert a list of previously rendered attachments in the tab's attachments list. - @ attachments list: A list of attachments already rendered. - """ - for i in attachments: - self.attachments.insert_item(False, *i) + def insert_attachments(self, attachments): + """ Insert a list of previously rendered attachments in the tab's attachments list. + @ attachments list: A list of attachments already rendered. + """ + for i in attachments: + self.attachments.insert_item(False, *i) - def __init__(self, parent): - super(chatTab, self).__init__(parent=parent) - sizer = wx.BoxSizer(wx.VERTICAL) - sizer.Add(self.create_controls()) - sizer.Add(self.create_attachments(), 0, wx.ALL, 5) - sizer.Add(self.create_chat(), 0, wx.ALL, 5) - self.attachment = wx.Button(self, wx.NewId(), _("Add")) - self.actions = wx.Button(self, wx.NewId(), _("Actions")) - buttonsBox = wx.BoxSizer(wx.HORIZONTAL) - buttonsBox.Add(self.attachment, 0, wx.ALL, 5) - buttonsBox.Add(self.actions, 0, wx.ALL, 5) - sizer.Add(buttonsBox, 0, wx.ALL, 5) - self.send = wx.Button(self, -1, _("Send")) - sizer.Add(self.send, 0, wx.ALL, 5) - self.SetSizer(sizer) + def __init__(self, parent): + super(chatTab, self).__init__(parent=parent) + sizer = wx.BoxSizer(wx.VERTICAL) + sizer.Add(self.create_controls()) + sizer.Add(self.create_attachments(), 0, wx.ALL, 5) + sizer.Add(self.create_chat(), 0, wx.ALL, 5) + self.attachment = wx.Button(self, wx.NewId(), _("Add")) + self.actions = wx.Button(self, wx.NewId(), _("Actions")) + buttonsBox = wx.BoxSizer(wx.HORIZONTAL) + buttonsBox.Add(self.attachment, 0, wx.ALL, 5) + buttonsBox.Add(self.actions, 0, wx.ALL, 5) + sizer.Add(buttonsBox, 0, wx.ALL, 5) + self.send = wx.Button(self, -1, _("Send")) + sizer.Add(self.send, 0, wx.ALL, 5) + self.SetSizer(sizer) - def create_controls(self): - lbl1 = wx.StaticText(self, wx.NewId(), _("History")) - self.history = wx.TextCtrl(self, wx.NewId(), style=wx.TE_READONLY|wx.TE_MULTILINE, size=(500, 300)) - selectId = wx.NewId() - self.Bind(wx.EVT_MENU, self.onSelect, id=selectId) - self.accel_tbl = wx.AcceleratorTable([(wx.ACCEL_CTRL, ord('A'), selectId)]) - self.SetAcceleratorTable(self.accel_tbl) - box = wx.BoxSizer(wx.HORIZONTAL) - box.Add(lbl1, 0, wx.ALL, 5) - box.Add(self.history, 0, wx.ALL, 5) - return box + def create_controls(self): + lbl1 = wx.StaticText(self, wx.NewId(), _("History")) + self.history = wx.TextCtrl(self, wx.NewId(), style=wx.TE_READONLY|wx.TE_MULTILINE, size=(500, 300)) + selectId = wx.NewId() + self.Bind(wx.EVT_MENU, self.onSelect, id=selectId) + self.accel_tbl = wx.AcceleratorTable([(wx.ACCEL_CTRL, ord('A'), selectId)]) + self.SetAcceleratorTable(self.accel_tbl) + box = wx.BoxSizer(wx.HORIZONTAL) + box.Add(lbl1, 0, wx.ALL, 5) + box.Add(self.history, 0, wx.ALL, 5) + return box - def onSelect(self, event, *args, **kwargs): - if self.history.HasFocus(): - self.history.SelectAll() - else: - self.text.SelectAll() - event.Skip() + def onSelect(self, event, *args, **kwargs): + if self.history.HasFocus(): + self.history.SelectAll() + else: + self.text.SelectAll() + event.Skip() - def create_attachments(self): - lbl = wx.StaticText(self, -1, _("Attachments")) - self.attachments = widgetUtils.list(self, _("Type"), _("Title"), style=wx.LC_REPORT) - box = wx.BoxSizer(wx.HORIZONTAL) - box.Add(lbl, 0, wx.ALL, 5) - box.Add(self.attachments.list, 0, wx.ALL, 5) - self.attachments.list.Enable(False) - return box + def create_attachments(self): + lbl = wx.StaticText(self, -1, _("Attachments")) + self.attachments = widgetUtils.list(self, _("Type"), _("Title"), style=wx.LC_REPORT) + box = wx.BoxSizer(wx.HORIZONTAL) + box.Add(lbl, 0, wx.ALL, 5) + box.Add(self.attachments.list, 0, wx.ALL, 5) + self.attachments.list.Enable(False) + return box - def create_chat(self): - lbl2 = wx.StaticText(self, -1, _("Write a message")) - self.text = wx.TextCtrl(self, -1, size=(400, -1), style=wx.TE_MULTILINE) - box = wx.BoxSizer(wx.HORIZONTAL) - box.Add(lbl2, 0, wx.ALL, 20) - box.Add(self.text, 0, wx.ALL, 5) - return box + def create_chat(self): + lbl2 = wx.StaticText(self, -1, _("Write a message")) + self.text = wx.TextCtrl(self, -1, size=(400, -1), style=wx.TE_MULTILINE) + box = wx.BoxSizer(wx.HORIZONTAL) + box.Add(lbl2, 0, wx.ALL, 20) + box.Add(self.text, 0, wx.ALL, 5) + return box - def set_focus_function(self, focus_function): - self.history.Bind(wx.EVT_KEY_UP , focus_function) + def set_focus_function(self, focus_function): + self.history.Bind(wx.EVT_KEY_UP , focus_function) - def add_message(self, message, reverse=False): - old_line = self.history.GetNumberOfLines()#.count("\n") - point = self.history.GetInsertionPoint() - if reverse: - wx.CallAfter(self.history.SetValue, message+"\n"+self.history.GetValue()) - else: - wx.CallAfter(self.history.AppendText, message+"\n") - wx.CallAfter(self.history.SetInsertionPoint, point) - new_line = self.history.GetNumberOfLines()#.count("\n") - return (old_line, new_line) \ No newline at end of file + def add_message(self, message, reverse=False): + old_line = self.history.GetNumberOfLines()#.count("\n") + point = self.history.GetInsertionPoint() + if reverse: + wx.CallAfter(self.history.SetValue, message+"\n"+self.history.GetValue()) + else: + wx.CallAfter(self.history.AppendText, message+"\n") + wx.CallAfter(self.history.SetInsertionPoint, point) + new_line = self.history.GetNumberOfLines()#.count("\n") + return (old_line, new_line) diff --git a/src/wxUI/tabs/communityBoard.py b/src/wxUI/tabs/communityBoard.py index 916a4cc..0b76752 100644 --- a/src/wxUI/tabs/communityBoard.py +++ b/src/wxUI/tabs/communityBoard.py @@ -4,12 +4,12 @@ import widgetUtils from .home import homeTab class communityBoardTab(homeTab): - def create_list(self): - self.lbl = wx.StaticText(self, wx.NewId(), _("Topics")) - self.list = widgetUtils.list(self, *[_("User"), _("Title"), _("Posts"), _("Last")], style=wx.LC_REPORT) - self.list.set_windows_size(0, 200) - self.list.set_windows_size(1, 64) - self.list.set_windows_size(2, 15) - self.list.set_windows_size(2, 250) - self.list.set_size() - self.list.list.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnKeyDown) + def create_list(self): + self.lbl = wx.StaticText(self, wx.NewId(), _("Topics")) + self.list = widgetUtils.list(self, *[_("User"), _("Title"), _("Posts"), _("Last")], style=wx.LC_REPORT) + self.list.set_windows_size(0, 200) + self.list.set_windows_size(1, 64) + self.list.set_windows_size(2, 15) + self.list.set_windows_size(2, 250) + self.list.set_size() + self.list.list.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnKeyDown) diff --git a/src/wxUI/tabs/communityDocuments.py b/src/wxUI/tabs/communityDocuments.py index 79e37c3..704e4d1 100644 --- a/src/wxUI/tabs/communityDocuments.py +++ b/src/wxUI/tabs/communityDocuments.py @@ -4,18 +4,18 @@ import widgetUtils from .home import homeTab class communityDocumentsTab(homeTab): - def create_list(self): - self.lbl = wx.StaticText(self, wx.NewId(), _("Documents")) - self.list = widgetUtils.list(self, *[_("User"), _("Title"), _("Type"), _("Size"), _("Date")], style=wx.LC_REPORT) - self.list.set_windows_size(0, 200) - self.list.set_windows_size(1, 128) - self.list.set_windows_size(2, 35) - self.list.set_windows_size(3, 15) - self.list.set_windows_size(4, 25) - self.list.set_size() - self.list.list.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnKeyDown) + def create_list(self): + self.lbl = wx.StaticText(self, wx.NewId(), _("Documents")) + self.list = widgetUtils.list(self, *[_("User"), _("Title"), _("Type"), _("Size"), _("Date")], style=wx.LC_REPORT) + self.list.set_windows_size(0, 200) + self.list.set_windows_size(1, 128) + self.list.set_windows_size(2, 35) + self.list.set_windows_size(3, 15) + self.list.set_windows_size(4, 25) + self.list.set_size() + self.list.list.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnKeyDown) - def get_download_path(self, filename): - saveFileDialog = wx.FileDialog(self, _("Save document as"), "", filename, _("All files (*.*)|*.*"), wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) - if saveFileDialog.ShowModal() == widgetUtils.OK: - return saveFileDialog.GetPath() \ No newline at end of file + def get_download_path(self, filename): + saveFileDialog = wx.FileDialog(self, _("Save document as"), "", filename, _("All files (*.*)|*.*"), wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) + if saveFileDialog.ShowModal() == widgetUtils.OK: + return saveFileDialog.GetPath() diff --git a/src/wxUI/tabs/communityWall.py b/src/wxUI/tabs/communityWall.py index 1770f34..074889a 100644 --- a/src/wxUI/tabs/communityWall.py +++ b/src/wxUI/tabs/communityWall.py @@ -4,9 +4,9 @@ from .home import homeTab class communityWallTab(homeTab): - def create_post_buttons(self): - self.postBox = wx.StaticBoxSizer(parent=self, orient=wx.HORIZONTAL, label=_("Actions")) - self.load = wx.Button(self.postBox.GetStaticBox(), wx.NewId(), _("Load buffer")) - self.post = wx.Button(self.postBox.GetStaticBox(), -1, _("&Post in group")) - self.postBox.Add(self.load, 0, wx.ALL, 5) - self.postBox.Add(self.post, 0, wx.ALL, 5) \ No newline at end of file + def create_post_buttons(self): + self.postBox = wx.StaticBoxSizer(parent=self, orient=wx.HORIZONTAL, label=_("Actions")) + self.load = wx.Button(self.postBox.GetStaticBox(), wx.NewId(), _("Load buffer")) + self.post = wx.Button(self.postBox.GetStaticBox(), -1, _("&Post in group")) + self.postBox.Add(self.load, 0, wx.ALL, 5) + self.postBox.Add(self.post, 0, wx.ALL, 5) diff --git a/src/wxUI/tabs/documents.py b/src/wxUI/tabs/documents.py index 379f259..87851d7 100644 --- a/src/wxUI/tabs/documents.py +++ b/src/wxUI/tabs/documents.py @@ -3,9 +3,9 @@ import wx from .communityDocuments import communityDocumentsTab class documentsTab(communityDocumentsTab): - def create_post_buttons(self): - self.postBox = wx.StaticBoxSizer(parent=self, orient=wx.HORIZONTAL, label=_("Actions")) - self.load = wx.Button(self.postBox.GetStaticBox(), wx.NewId(), _("Load buffer")) - self.post = wx.Button(self.postBox.GetStaticBox(), -1, _("&Post")) - self.postBox.Add(self.load, 0, wx.ALL, 5) - self.postBox.Add(self.post, 0, wx.ALL, 5) \ No newline at end of file + def create_post_buttons(self): + self.postBox = wx.StaticBoxSizer(parent=self, orient=wx.HORIZONTAL, label=_("Actions")) + self.load = wx.Button(self.postBox.GetStaticBox(), wx.NewId(), _("Load buffer")) + self.post = wx.Button(self.postBox.GetStaticBox(), -1, _("&Post")) + self.postBox.Add(self.load, 0, wx.ALL, 5) + self.postBox.Add(self.post, 0, wx.ALL, 5) diff --git a/src/wxUI/tabs/empty.py b/src/wxUI/tabs/empty.py index b24d238..67fcf55 100644 --- a/src/wxUI/tabs/empty.py +++ b/src/wxUI/tabs/empty.py @@ -2,8 +2,8 @@ import wx class emptyTab(wx.Panel): - def __init__(self, parent, name): - super(emptyTab, self).__init__(parent=parent, name=name) - self.name = name - sizer = wx.BoxSizer(wx.VERTICAL) - self.SetSizer(sizer) \ No newline at end of file + def __init__(self, parent, name): + super(emptyTab, self).__init__(parent=parent, name=name) + self.name = name + sizer = wx.BoxSizer(wx.VERTICAL) + self.SetSizer(sizer) diff --git a/src/wxUI/tabs/home.py b/src/wxUI/tabs/home.py index 4161fe5..bf8ccd3 100644 --- a/src/wxUI/tabs/home.py +++ b/src/wxUI/tabs/home.py @@ -5,43 +5,43 @@ from pubsub import pub class homeTab(wx.Panel): - def create_list(self): - self.lbl = wx.StaticText(self, wx.NewId(), _("Po&sts")) - self.list = widgetUtils.list(self, *[_("User"), _("Text"), _("Date")], style=wx.LC_REPORT, name=_("Posts")) - self.list.set_windows_size(0, 200) - self.list.set_windows_size(1, 300) - self.list.set_windows_size(2, 250) - self.list.set_size() - self.list.list.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnKeyDown) + def create_list(self): + self.lbl = wx.StaticText(self, wx.NewId(), _("Po&sts")) + self.list = widgetUtils.list(self, *[_("User"), _("Text"), _("Date")], style=wx.LC_REPORT, name=_("Posts")) + self.list.set_windows_size(0, 200) + self.list.set_windows_size(1, 300) + self.list.set_windows_size(2, 250) + self.list.set_size() + self.list.list.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnKeyDown) - def create_post_buttons(self): - self.postBox = wx.StaticBoxSizer(parent=self, orient=wx.HORIZONTAL, label=_("Actions")) - self.post = wx.Button(self.postBox.GetStaticBox(), wx.NewId(), _("&Post")) - self.postBox.Add(self.post, 0, wx.ALL, 5) + def create_post_buttons(self): + self.postBox = wx.StaticBoxSizer(parent=self, orient=wx.HORIZONTAL, label=_("Actions")) + self.post = wx.Button(self.postBox.GetStaticBox(), wx.NewId(), _("&Post")) + self.postBox.Add(self.post, 0, wx.ALL, 5) - def __init__(self, parent): - super(homeTab, self).__init__(parent=parent) - sizer = wx.BoxSizer(wx.VERTICAL) - self.create_list() - self.create_post_buttons() - sizer.Add(self.postBox, 0, wx.ALL, 5) - sizer.Add(self.lbl, 0, wx.ALL, 5) - sizer.Add(self.list.list, 1, wx.EXPAND, 5) - self.SetSizer(sizer) - self.SetClientSize(sizer.CalcMin()) + def __init__(self, parent): + super(homeTab, self).__init__(parent=parent) + sizer = wx.BoxSizer(wx.VERTICAL) + self.create_list() + self.create_post_buttons() + sizer.Add(self.postBox, 0, wx.ALL, 5) + sizer.Add(self.lbl, 0, wx.ALL, 5) + sizer.Add(self.list.list, 1, wx.EXPAND, 5) + self.SetSizer(sizer) + self.SetClientSize(sizer.CalcMin()) - def OnKeyDown(self, ev=None): - pub.sendMessage("show-current-status", buffer=self.name) - ev.Skip() + def OnKeyDown(self, ev=None): + pub.sendMessage("show-current-status", buffer=self.name) + ev.Skip() - def showMenu(self, ev): - if self.list.get_count() == 0: return - pub.sendMessage("show-menu", position=ev.GetPosition()) + def showMenu(self, ev): + if self.list.get_count() == 0: return + pub.sendMessage("show-menu", position=ev.GetPosition()) - def showMenuByKey(self, ev): - if self.list.get_count() == 0: return - if ev.GetKeyCode() == wx.WXK_WINDOWS_MENU: - pub.sendMessage("show-menu", position=self.results.list.GetPosition()) + def showMenuByKey(self, ev): + if self.list.get_count() == 0: return + if ev.GetKeyCode() == wx.WXK_WINDOWS_MENU: + pub.sendMessage("show-menu", position=self.results.list.GetPosition()) - def set_focus_function(self, focus_function): - self.list.list.Bind(wx.EVT_LIST_ITEM_FOCUSED, focus_function) \ No newline at end of file + def set_focus_function(self, focus_function): + self.list.list.Bind(wx.EVT_LIST_ITEM_FOCUSED, focus_function) diff --git a/src/wxUI/tabs/notification.py b/src/wxUI/tabs/notification.py index b33a493..1c81101 100644 --- a/src/wxUI/tabs/notification.py +++ b/src/wxUI/tabs/notification.py @@ -5,12 +5,12 @@ from pubsub import pub from .home import homeTab class notificationTab(homeTab): - def OnKeyDown(self, ev=None): - pub.sendMessage("show-notification", buffer=self.name) - ev.Skip() + def OnKeyDown(self, ev=None): + pub.sendMessage("show-notification", buffer=self.name) + ev.Skip() - def create_list(self): - self.lbl = wx.StaticText(self, wx.NewId(), _("Po&sts")) - self.list = widgetUtils.list(self, *[_("Notification"), _("Date")], style=wx.LC_REPORT) - self.list.set_windows_size(0, 190) - self.list.list.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnKeyDown) \ No newline at end of file + def create_list(self): + self.lbl = wx.StaticText(self, wx.NewId(), _("Po&sts")) + self.list = widgetUtils.list(self, *[_("Notification"), _("Date")], style=wx.LC_REPORT) + self.list.set_windows_size(0, 190) + self.list.list.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnKeyDown) diff --git a/src/wxUI/tabs/people.py b/src/wxUI/tabs/people.py index 177945e..d0c0717 100644 --- a/src/wxUI/tabs/people.py +++ b/src/wxUI/tabs/people.py @@ -6,17 +6,17 @@ from .home import homeTab class peopleTab(homeTab): - def create_list(self): - self.lbl = wx.StaticText(self, wx.NewId(), _("Friends")) - self.list = widgetUtils.list(self, *[_("Name"), _("Last seen")], style=wx.LC_REPORT) - self.list.set_windows_size(0, 190) - self.list.set_windows_size(1, 100) - self.list.set_size() - self.list.list.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnKeyDown) + def create_list(self): + self.lbl = wx.StaticText(self, wx.NewId(), _("Friends")) + self.list = widgetUtils.list(self, *[_("Name"), _("Last seen")], style=wx.LC_REPORT) + self.list.set_windows_size(0, 190) + self.list.set_windows_size(1, 100) + self.list.set_size() + self.list.list.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnKeyDown) - def create_post_buttons(self): - self.postBox = wx.StaticBoxSizer(parent=self, orient=wx.HORIZONTAL, label=_("Actions")) - self.post = wx.Button(self.postBox.GetStaticBox(), -1, _("&Post on user's wall")) - self.new_chat = wx.Button(self.postBox.GetStaticBox(), wx.NewId(), _("Send message")) - self.postBox.Add(self.post, 0, wx.ALL, 5) - self.postBox.Add(self.new_chat, 0, wx.ALL, 5) + def create_post_buttons(self): + self.postBox = wx.StaticBoxSizer(parent=self, orient=wx.HORIZONTAL, label=_("Actions")) + self.post = wx.Button(self.postBox.GetStaticBox(), -1, _("&Post on user's wall")) + self.new_chat = wx.Button(self.postBox.GetStaticBox(), wx.NewId(), _("Send message")) + self.postBox.Add(self.post, 0, wx.ALL, 5) + self.postBox.Add(self.new_chat, 0, wx.ALL, 5) diff --git a/src/wxUI/tabs/photoAlbum.py b/src/wxUI/tabs/photoAlbum.py index 4208ffa..83d0f0f 100644 --- a/src/wxUI/tabs/photoAlbum.py +++ b/src/wxUI/tabs/photoAlbum.py @@ -5,19 +5,19 @@ from pubsub import pub from .home import homeTab class albumTab(homeTab): - def __init__(self, parent): - super(albumTab, self).__init__(parent=parent) - self.name = "albums" + def __init__(self, parent): + super(albumTab, self).__init__(parent=parent) + self.name = "albums" - def OnKeyDown(self, ev=None): - pub.sendMessage("show-album", buffer=self.name) - ev.Skip() + def OnKeyDown(self, ev=None): + pub.sendMessage("show-album", buffer=self.name) + ev.Skip() - def create_list(self): - self.list = widgetUtils.list(self, *[_("User"), _("Name"), _("Description"), _("Photos"), _("Created at")], style=wx.LC_REPORT) - self.list.set_windows_size(0, 190) - self.list.set_windows_size(1, 320) - self.list.set_windows_size(2, 513) - self.list.set_windows_size(3, 390) - self.list.set_windows_size(4, 180) - self.list.list.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnKeyDown) \ No newline at end of file + def create_list(self): + self.list = widgetUtils.list(self, *[_("User"), _("Name"), _("Description"), _("Photos"), _("Created at")], style=wx.LC_REPORT) + self.list.set_windows_size(0, 190) + self.list.set_windows_size(1, 320) + self.list.set_windows_size(2, 513) + self.list.set_windows_size(3, 390) + self.list.set_windows_size(4, 180) + self.list.list.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnKeyDown) diff --git a/src/wxUI/tabs/video.py b/src/wxUI/tabs/video.py index 3f66800..5361812 100644 --- a/src/wxUI/tabs/video.py +++ b/src/wxUI/tabs/video.py @@ -4,18 +4,18 @@ import widgetUtils from .home import homeTab class videoTab(homeTab): - def create_list(self): - self.lbl = wx.StaticText(self, wx.NewId(), _("Video&s")) - self.list = widgetUtils.list(self, *[_("Title"), _("Description"), _("Duration")], style=wx.LC_REPORT) - self.list.set_windows_size(0, 160) - self.list.set_windows_size(1, 380) - self.list.set_windows_size(2, 80) - self.list.set_size() - self.list.list.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnKeyDown) + def create_list(self): + self.lbl = wx.StaticText(self, wx.NewId(), _("Video&s")) + self.list = widgetUtils.list(self, *[_("Title"), _("Description"), _("Duration")], style=wx.LC_REPORT) + self.list.set_windows_size(0, 160) + self.list.set_windows_size(1, 380) + self.list.set_windows_size(2, 80) + self.list.set_size() + self.list.list.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnKeyDown) - def create_post_buttons(self): - self.postBox = wx.StaticBoxSizer(parent=self, orient=wx.HORIZONTAL, label=_("Actions")) - self.post = wx.Button(self.postBox.GetStaticBox(), -1, _("&Post")) - self.play = wx.Button(self.postBox.GetStaticBox(), -1, _("P&lay")) - self.postBox.Add(self.post, 0, wx.ALL, 5) - self.postBox.Add(self.play, 0, wx.ALL, 5) \ No newline at end of file + def create_post_buttons(self): + self.postBox = wx.StaticBoxSizer(parent=self, orient=wx.HORIZONTAL, label=_("Actions")) + self.post = wx.Button(self.postBox.GetStaticBox(), -1, _("&Post")) + self.play = wx.Button(self.postBox.GetStaticBox(), -1, _("P&lay")) + self.postBox.Add(self.post, 0, wx.ALL, 5) + self.postBox.Add(self.play, 0, wx.ALL, 5) diff --git a/src/wxUI/tabs/videoAlbum.py b/src/wxUI/tabs/videoAlbum.py index 1a808e9..5accb4b 100644 --- a/src/wxUI/tabs/videoAlbum.py +++ b/src/wxUI/tabs/videoAlbum.py @@ -4,10 +4,10 @@ from .video import videoTab class videoAlbumTab(videoTab): - def create_post_buttons(self): - self.postBox = wx.BoxSizer(parent=self, orient=wx.HORIZONTAL, label=_("Actions")) - self.load = wx.Button(self.postBox.GetStaticBox(), wx.NewId(), _("Load buffer")) - self.post = wx.Button(self.postBox.GetStaticBox(), -1, _("&Post")) - self.play = wx.Button(self.postBox.GetStaticBox(), -1, _("P&lay")) - self.postBox.Add(self.post, 0, wx.ALL, 5) - self.postBox.Add(self.play, 0, wx.ALL, 5) + def create_post_buttons(self): + self.postBox = wx.BoxSizer(parent=self, orient=wx.HORIZONTAL, label=_("Actions")) + self.load = wx.Button(self.postBox.GetStaticBox(), wx.NewId(), _("Load buffer")) + self.post = wx.Button(self.postBox.GetStaticBox(), -1, _("&Post")) + self.play = wx.Button(self.postBox.GetStaticBox(), -1, _("P&lay")) + self.postBox.Add(self.post, 0, wx.ALL, 5) + self.postBox.Add(self.play, 0, wx.ALL, 5)