def __init__(self, base, column_id, include_header=True): QWidget.__init__(self) self.base = base self.setMinimumWidth(280) self.statuses = [] self.conversations = {} self.id_ = None #self.fgcolor = "#e3e3e3" #self.fgcolor = "#f9a231" #self.updating = False self.last_id = None self.loader = BarLoadIndicator() self.loader.setVisible(False) self.webview = StatusesWebView(self.base, self.id_) self.webview.link_clicked.connect(self.__link_clicked) self.webview.hashtag_clicked.connect(self.__hashtag_clicked) self.webview.profile_clicked.connect(self.__profile_clicked) self.webview.cmd_clicked.connect(self.__cmd_clicked) layout = QVBoxLayout() layout.setSpacing(0) layout.setContentsMargins(0, 0, 0, 0) if include_header: header = self.__build_header(column_id) layout.addWidget(header) layout.addWidget(self.loader) layout.addWidget(self.webview, 1) self.setLayout(layout)
def __init__(self, base): QWidget.__init__(self) self.base = base self.showed = False self.setFixedSize(500, 120) self.text_edit = CompletionTextEdit() self.upload_button = ImageButton(base, 'action-upload.png', i18n.get('upload_image')) self.short_button = ImageButton(base, 'action-shorten.png', i18n.get('short_urls')) font = QFont() font.setPointSize(18) font.setBold(True) self.char_count = QLabel('140') self.char_count.setFont(font) self.update_button = QPushButton(i18n.get('update')) self.update_button.setToolTip(self.base.get_shortcut_string('Enter')) self.queue_button = QPushButton(i18n.get('add_to_queue')) self.queue_button.setToolTip(self.base.get_shortcut_string('P')) self.accounts_combo = QComboBox() buttons = QHBoxLayout() buttons.setSpacing(4) buttons.addWidget(self.accounts_combo) buttons.addWidget(self.upload_button) buttons.addWidget(self.short_button) buttons.addStretch(0) buttons.addWidget(self.char_count) buttons.addWidget(self.queue_button) buttons.addWidget(self.update_button) self.loader = BarLoadIndicator() self.error_message = ErrorLabel() self.update_button.clicked.connect(self.__update_status) self.queue_button.clicked.connect(self.__queue_status) self.short_button.clicked.connect(self.__short_urls) self.upload_button.clicked.connect(self.__upload_image) self.text_edit.textChanged.connect(self.__update_count) self.text_edit.quit.connect(self.closeEvent) self.text_edit.activated.connect(self.__update_status) self.text_edit.enqueued.connect(self.__queue_status) layout = QVBoxLayout() layout.setSpacing(0) layout.addWidget(self.text_edit) layout.addWidget(self.loader) layout.addSpacing(5) layout.addWidget(self.error_message) layout.addLayout(buttons) layout.setContentsMargins(5, 5, 5, 5) self.setLayout(layout) self.__clear()
def __init__(self, base): Window.__init__(self, base, i18n.get('image_preview')) self.loader = BarLoadIndicator() self.view = QLabel() self.view.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) self.view.setScaledContents(True) scroll_area = QScrollArea() scroll_area.setBackgroundRole(QPalette.Dark) scroll_area.setWidget(self.view) scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.error_label = QLabel(i18n.get('error_loading_image')) self.error_label.setAlignment(Qt.AlignHCenter) self.error_label.setStyleSheet("QLabel {background-color: #ffecec;}") layout = QVBoxLayout() layout.setSpacing(0) layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self.loader) layout.addWidget(self.error_label) layout.addWidget(scroll_area) self.setLayout(layout) self.__clear()
class ImageView(Window): def __init__(self, base): Window.__init__(self, base, i18n.get('image_preview')) self.loader = BarLoadIndicator() self.view = QLabel() self.view.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) self.view.setScaledContents(True) scroll_area = QScrollArea() scroll_area.setBackgroundRole(QPalette.Dark) scroll_area.setWidget(self.view) scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.error_label = QLabel(i18n.get('error_loading_image')) self.error_label.setAlignment(Qt.AlignHCenter) self.error_label.setStyleSheet("QLabel {background-color: #ffecec;}") layout = QVBoxLayout() layout.setSpacing(0) layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self.loader) layout.addWidget(self.error_label) layout.addWidget(scroll_area) self.setLayout(layout) self.__clear() def __clear(self): self.resize(350, 350) self.view.setPixmap(QPixmap()) def closeEvent(self, event): event.ignore() self.__clear() self.hide() def start_loading(self): self.loader.setVisible(True) self.error_label.setVisible(False) self.show() def loading_finished(self, url): self.loader.setVisible(False) pix = self.base.load_image(url, True) self.view.setPixmap(pix) self.view.adjustSize() self.resize(pix.width() + 2, pix.height() + 2) self.show() def error(self): self.loader.setVisible(False) self.error_label.setVisible(True)
def loading(self): if self.child: self.clear_layout(self) image = self.base.load_image('turpial-196.png', True) logo = QLabel() logo.setPixmap(image) logo.setAlignment(Qt.AlignCenter) logo.setContentsMargins(0, 80, 0, 0) appname = QLabel('Turpial 3') if detect_os() == OS_MAC: font = QFont('Maven Pro Light', 28, 0, False) font2 = QFont('Ubuntu', 16, 0, False) else: font = QFont('Maven Pro Light', 18, QFont.Light, False) font2 = QFont('Ubuntu', 12, QFont.Normal, False) appname.setFont(font) welcome = QLabel() welcome.setText(i18n.get('hi_there')) welcome.setAlignment(Qt.AlignCenter) welcome.setFont(font) message = QLabel() message.setText(i18n.get('give_me_a_minute')) message.setAlignment(Qt.AlignCenter) message.setWordWrap(True) message.setFont(font2) loader = BarLoadIndicator() self.child = QVBoxLayout() self.child.addWidget(logo) self.child.addWidget(welcome) self.child.addSpacing(10) self.child.addWidget(message) #self.child.setSpacing(10) self.child.addStretch(1) self.child.addWidget(loader) self.child.setContentsMargins(30, 0, 30, 30) self.insertLayout(0, self.child) self.is_empty = True
class StatusesColumn(QWidget): NOTIFICATION_ERROR = 'error' NOTIFICATION_SUCCESS = 'success' NOTIFICATION_WARNING = 'warning' NOTIFICATION_INFO = 'notice' def __init__(self, base, column_id, include_header=True): QWidget.__init__(self) self.base = base self.setMinimumWidth(280) self.statuses = [] self.conversations = {} self.id_ = None #self.fgcolor = "#e3e3e3" #self.fgcolor = "#f9a231" #self.updating = False self.last_id = None self.loader = BarLoadIndicator() self.loader.setVisible(False) self.webview = StatusesWebView(self.base, self.id_) self.webview.link_clicked.connect(self.__link_clicked) self.webview.hashtag_clicked.connect(self.__hashtag_clicked) self.webview.profile_clicked.connect(self.__profile_clicked) self.webview.cmd_clicked.connect(self.__cmd_clicked) layout = QVBoxLayout() layout.setSpacing(0) layout.setContentsMargins(0, 0, 0, 0) if include_header: header = self.__build_header(column_id) layout.addWidget(header) layout.addWidget(self.loader) layout.addWidget(self.webview, 1) self.setLayout(layout) def __build_header(self, column_id): self.set_column_id(column_id) username = get_username_from(self.account_id) column_slug = get_column_slug_from(column_id) column_slug = column_slug.replace('%23', '#') column_slug = column_slug.replace('%40', '@') #font = QFont('Titillium Web', 18, QFont.Normal, False) # This is to handle the 96dpi vs 72dpi screen resolutions on Mac vs the world if detect_os() == OS_MAC: font = QFont('Maven Pro Light', 25, 0, False) font2 = QFont('Monda', 14, 0, False) else: font = QFont('Maven Pro Light', 16, QFont.Light, False) font2 = QFont('Monda', 10, QFont.Light, False) bg_style = "background-color: %s; color: %s;" % (self.base.bgcolor, self.base.fgcolor) label = "%s : %s" % (username, column_slug) caption = QLabel(username) caption.setStyleSheet("QLabel { %s }" % bg_style) caption.setFont(font) caption2 = QLabel(column_slug) caption2.setStyleSheet("QLabel { %s }" % bg_style) caption2.setFont(font2) caption2.setAlignment(Qt.AlignLeft | Qt.AlignBottom) caption_box = QHBoxLayout() caption_box.setSpacing(8) caption_box.addWidget(caption) caption_box.addWidget(caption2) caption_box.addStretch(1) close_button = ImageButton(self.base, 'action-delete-shadowed.png', i18n.get('delete_column')) close_button.clicked.connect(self.__delete_column) close_button.setStyleSheet("QToolButton { %s border: 0px solid %s;}" % (bg_style, self.base.bgcolor)) header_layout = QHBoxLayout() header_layout.addLayout(caption_box, 1) header_layout.addWidget(close_button) header = QWidget() header.setStyleSheet("QWidget { %s }" % bg_style) header.setLayout(header_layout) return header def __delete_column(self): self.base.core.delete_column(self.id_) def __link_clicked(self, url): url = str(url) preview_service = get_preview_service_from_url(url) self.base.open_url(url) def __hashtag_clicked(self, hashtag): self.base.add_search_column(self.account_id, str(hashtag)) def __profile_clicked(self, username): self.base.show_profile_dialog(self.account_id, str(username)) def __cmd_clicked(self, url): status_id = str(url.split(':')[1]) cmd = url.split(':')[0] status = None try: print 'Seeking for status in self array' for status_ in self.statuses: if status_.id_ == status_id: status = status_ break if status is None: raise KeyError except KeyError: print 'Seeking for status in conversations array' for status_root, statuses in self.conversations.iteritems(): for item in statuses: if item.id_ == status_id: status = item break if status is not None: break if status is None: self.notify_error(status_id, i18n.get('try_again')) if cmd == 'reply': self.__reply_status(status) elif cmd == 'quote': self.__quote_status(status) elif cmd == 'repeat': self.__repeat_status(status) elif cmd == 'delete': self.__delete_status(status) elif cmd == 'favorite': self.__mark_status_as_favorite(status) elif cmd == 'unfavorite': self.__unmark_status_as_favorite(status) elif cmd == 'delete_direct': self.__delete_direct_message(status) elif cmd == 'reply_direct': self.__reply_direct_message(status) elif cmd == 'view_conversation': self.__view_conversation(status) elif cmd == 'hide_conversation': self.__hide_conversation(status) elif cmd == 'show_avatar': self.__show_avatar(status) def __reply_status(self, status): self.base.show_update_box_for_reply(self.account_id, status) def __quote_status(self, status): self.base.show_update_box_for_quote(self.account_id, status) def __repeat_status(self, status): confirmation = self.base.show_confirmation_message(i18n.get('confirm_retweet'), i18n.get('do_you_want_to_retweet_status')) if confirmation: self.lock_status(status.id_) self.base.repeat_status(self.id_, self.account_id, status) def __delete_status(self, status): confirmation = self.base.show_confirmation_message(i18n.get('confirm_delete'), i18n.get('do_you_want_to_delete_status')) if confirmation: self.lock_status(status.id_) self.base.delete_status(self.id_, self.account_id, status) def __delete_direct_message(self, status): confirmation = self.base.show_confirmation_message(i18n.get('confirm_delete'), i18n.get('do_you_want_to_delete_direct_message')) if confirmation: self.base.delete_direct_message(self.id_, self.account_id, status) def __reply_direct_message(self, status): self.base.show_update_box_for_reply_direct(self.account_id, status) def __mark_status_as_favorite(self, status): self.lock_status(status.id_) self.base.mark_status_as_favorite(self.id_, self.account_id, status) def __unmark_status_as_favorite(self, status): self.lock_status(status.id_) self.base.unmark_status_as_favorite(self.id_, self.account_id, status) def __view_conversation(self, status): self.webview.view_conversation(status.id_) self.base.get_conversation(self.account_id, status, self.id_, status.id_) def __hide_conversation(self, status): del self.conversations[status.id_] self.webview.clear_conversation(status.id_) def __show_avatar(self, status): self.base.show_profile_image(self.account_id, status.username) def __set_last_status_id(self, statuses): if statuses[0].repeated_by: self.last_id = statuses[0].original_status_id else: self.last_id = statuses[0].id_ def set_column_id(self, column_id): self.id_ = column_id self.account_id = get_account_id_from(column_id) self.protocol_id = get_protocol_from(self.account_id) self.webview.column_id = column_id def clear(self): self.webview.clear() def start_updating(self): self.loader.setVisible(True) return self.last_id def stop_updating(self): self.loader.setVisible(False) def update_timestamps(self): self.webview.sync_timestamps(self.statuses) def update_statuses(self, statuses): self.__set_last_status_id(statuses) self.update_timestamps() self.webview.update_statuses(statuses) # Filter repeated statuses # FIXME: This should be done with list comprehension using comparation methods on status.py unique_statuses = [] for s1 in statuses: exist = False for s2 in self.statuses: if s1.id_ == s2.id_: exist = True break if not exist: unique_statuses.append(s1) # Remove old conversations to_remove = self.statuses[-(len(unique_statuses)):] self.statuses = statuses + self.statuses[: -(len(unique_statuses))] for status in to_remove: if self.conversations.has_key(status.id_): del self.conversations[status.id_] def update_conversation(self, status, status_root_id): status_root_id = str(status_root_id) self.webview.update_conversation(status, status_root_id) if status_root_id in self.conversations: self.conversations[status_root_id].append(status) else: self.conversations[status_root_id] = [status] def error_in_conversation(self, status_root_id): self.webview.clear_conversation(status_root_id) def mark_status_as_favorite(self, status_id): mark = "setFavorite('%s')" % status_id self.webview.execute_javascript(mark) def unmark_status_as_favorite(self, status_id): mark = "unsetFavorite('%s');" % status_id self.webview.execute_javascript(mark) def mark_status_as_repeated(self, status_id): mark = "setRepeated('%s');" % status_id self.webview.execute_javascript(mark) def remove_status(self, status_id): operation = "removeStatus('%s');" % status_id self.webview.execute_javascript(operation) def lock_status(self, status_id): operation = "lockStatus('%s');" % status_id self.webview.execute_javascript(operation) def release_status(self, status_id): operation = "releaseStatus('%s');" % status_id self.webview.execute_javascript(operation) def notify(self, id_, type_, message): message = message.replace("'", "\"") notification = "addNotify('%s', '%s', '%s');" % (id_, type_, message) self.webview.execute_javascript(notification) def notify_error(self, id_, message): self.notify(id_, self.NOTIFICATION_ERROR, message) def notify_success(self, id_, message): self.notify(id_, self.NOTIFICATION_SUCCESS, message) def notify_warning(self, id_, message): self.notify(id_, self.NOTIFICATION_WARNING, message) def notify_info(self, id_, message): self.notify(id_, self.NOTIFICATION_INFO, message)
def __init__(self, base): Window.__init__(self, base, i18n.get('user_profile')) self.account_id = None self.setFixedSize(380, 450) self.username = QLabel('') self.username.setTextFormat(Qt.RichText) self.fullname = QLabel('') self.options = ImageButton(base, 'action-status-menu.png', i18n.get('')) self.options.clicked.connect(self.__options_clicked) self.verified_icon = QLabel() self.verified_icon.setPixmap(base.load_image('mark-verified.png', True)) self.protected_icon = QLabel() self.protected_icon.setPixmap( base.load_image('mark-protected.png', True)) self.avatar = ClickableLabel() self.avatar.setPixmap(base.load_image('unknown.png', True)) self.avatar.clicked.connect(self.__show_avatar) self.you_label = QLabel(i18n.get('this_is_you')) self.you_label.setVisible(False) info_line1 = QHBoxLayout() info_line1.setSpacing(5) info_line1.addWidget(self.username) info_line1.addSpacing(5) info_line1.addWidget(self.verified_icon) info_line1.addWidget(self.protected_icon) info_line1.addStretch(0) info_line2 = QHBoxLayout() info_line2.addWidget(self.fullname, 1) info_line2.addWidget(self.options) info_line2.addWidget(self.you_label) user_info = QVBoxLayout() user_info.addLayout(info_line1) user_info.addLayout(info_line2) self.loader = BarLoadIndicator() self.loader.setVisible(False) self.error_message = ErrorLabel() self.error_message.setVisible(False) header = QHBoxLayout() header.setContentsMargins(5, 10, 5, 0) header.addWidget(self.avatar) header.addSpacing(10) header.addLayout(user_info) # User Info self.bio = UserField(base, 'bio', 'icon-bio.png') self.bio.set_word_wrap(True) self.bio.set_info('') self.location = UserField(base, 'location', 'icon-location.png') self.location.set_info('') self.web = UserField(base, 'web', 'icon-home.png') self.web.set_info('') self.tweets = StatInfoBox('tweets', '') self.following = StatInfoBox('following', '') self.followers = StatInfoBox('followers', '') self.favorites = StatInfoBox('favorites', '') footer_layout = QHBoxLayout() footer_layout.setContentsMargins(0, 5, 0, 10) footer_layout.setSpacing(0) footer_layout.addLayout(self.tweets) footer_layout.addWidget(VLine()) footer_layout.addLayout(self.following) footer_layout.addWidget(VLine()) footer_layout.addLayout(self.followers) footer_layout.addWidget(VLine()) footer_layout.addLayout(self.favorites) footer = QWidget() footer.setLayout(footer_layout) footer.setStyleSheet( "QWidget { background-color: #333; color: white; }") body_layout = QVBoxLayout() body_layout.setSpacing(15) body_layout.setContentsMargins(0, 0, 0, 0) body_layout.addLayout(self.bio) body_layout.addLayout(self.location) body_layout.addLayout(self.web) body_layout.addWidget(footer) body = QWidget() body.setLayout(body_layout) self.last_statuses = StatusesColumn(self.base, None, False) self.tabs = QTabWidget(self) self.tabs.setTabsClosable(False) self.tabs.setMovable(False) self.tabs.addTab(body, i18n.get('info')) self.tabs.addTab(self.last_statuses, i18n.get('recent')) self.hline = HLine() self.hline.setMinimumHeight(2) layout = QVBoxLayout() layout.addLayout(header) layout.addSpacing(10) layout.addWidget(self.hline) layout.addWidget(self.loader) layout.addWidget(self.error_message) layout.addSpacing(10) layout.addWidget(self.tabs, 1) layout.setSpacing(0) layout.setContentsMargins(5, 5, 5, 5) self.setLayout(layout) self.__clear()
class ProfileDialog(Window): options_clicked = pyqtSignal(QPoint, object) def __init__(self, base): Window.__init__(self, base, i18n.get('user_profile')) self.account_id = None self.setFixedSize(380, 450) self.username = QLabel('') self.username.setTextFormat(Qt.RichText) self.fullname = QLabel('') self.options = ImageButton(base, 'action-status-menu.png', i18n.get('')) self.options.clicked.connect(self.__options_clicked) self.verified_icon = QLabel() self.verified_icon.setPixmap(base.load_image('mark-verified.png', True)) self.protected_icon = QLabel() self.protected_icon.setPixmap( base.load_image('mark-protected.png', True)) self.avatar = ClickableLabel() self.avatar.setPixmap(base.load_image('unknown.png', True)) self.avatar.clicked.connect(self.__show_avatar) self.you_label = QLabel(i18n.get('this_is_you')) self.you_label.setVisible(False) info_line1 = QHBoxLayout() info_line1.setSpacing(5) info_line1.addWidget(self.username) info_line1.addSpacing(5) info_line1.addWidget(self.verified_icon) info_line1.addWidget(self.protected_icon) info_line1.addStretch(0) info_line2 = QHBoxLayout() info_line2.addWidget(self.fullname, 1) info_line2.addWidget(self.options) info_line2.addWidget(self.you_label) user_info = QVBoxLayout() user_info.addLayout(info_line1) user_info.addLayout(info_line2) self.loader = BarLoadIndicator() self.loader.setVisible(False) self.error_message = ErrorLabel() self.error_message.setVisible(False) header = QHBoxLayout() header.setContentsMargins(5, 10, 5, 0) header.addWidget(self.avatar) header.addSpacing(10) header.addLayout(user_info) # User Info self.bio = UserField(base, 'bio', 'icon-bio.png') self.bio.set_word_wrap(True) self.bio.set_info('') self.location = UserField(base, 'location', 'icon-location.png') self.location.set_info('') self.web = UserField(base, 'web', 'icon-home.png') self.web.set_info('') self.tweets = StatInfoBox('tweets', '') self.following = StatInfoBox('following', '') self.followers = StatInfoBox('followers', '') self.favorites = StatInfoBox('favorites', '') footer_layout = QHBoxLayout() footer_layout.setContentsMargins(0, 5, 0, 10) footer_layout.setSpacing(0) footer_layout.addLayout(self.tweets) footer_layout.addWidget(VLine()) footer_layout.addLayout(self.following) footer_layout.addWidget(VLine()) footer_layout.addLayout(self.followers) footer_layout.addWidget(VLine()) footer_layout.addLayout(self.favorites) footer = QWidget() footer.setLayout(footer_layout) footer.setStyleSheet( "QWidget { background-color: #333; color: white; }") body_layout = QVBoxLayout() body_layout.setSpacing(15) body_layout.setContentsMargins(0, 0, 0, 0) body_layout.addLayout(self.bio) body_layout.addLayout(self.location) body_layout.addLayout(self.web) body_layout.addWidget(footer) body = QWidget() body.setLayout(body_layout) self.last_statuses = StatusesColumn(self.base, None, False) self.tabs = QTabWidget(self) self.tabs.setTabsClosable(False) self.tabs.setMovable(False) self.tabs.addTab(body, i18n.get('info')) self.tabs.addTab(self.last_statuses, i18n.get('recent')) self.hline = HLine() self.hline.setMinimumHeight(2) layout = QVBoxLayout() layout.addLayout(header) layout.addSpacing(10) layout.addWidget(self.hline) layout.addWidget(self.loader) layout.addWidget(self.error_message) layout.addSpacing(10) layout.addWidget(self.tabs, 1) layout.setSpacing(0) layout.setContentsMargins(5, 5, 5, 5) self.setLayout(layout) self.__clear() def __clear(self): self.profile = None self.showed = False self.account_id = None self.verified_icon.setVisible(False) self.protected_icon.setVisible(False) self.you_label.setVisible(False) self.options.setVisible(False) self.loader.setVisible(False) self.error_message.setVisible(False) self.avatar.setPixmap(self.base.load_image('unknown.png', True)) self.bio.set_info('') self.location.set_info('') self.web.set_info('') self.tweets.set_value('') self.following.set_value('') self.followers.set_value('') self.favorites.set_value('') self.last_statuses.id_ = None self.last_statuses.clear() self.tabs.setCurrentIndex(0) def __options_clicked(self): self.options_clicked.emit(QCursor.pos(), self.profile) def __show_avatar(self): self.base.show_profile_image(self.account_id, self.profile.username) def __on_timeout(self): self.error_message.setText('') self.error_message.setVisible(False) def closeEvent(self, event=None): if event: event.ignore() self.__clear() self.hide() def start_loading(self, profile_username): self.__clear() self.hline.setVisible(False) self.loader.setVisible(True) self.username.setText('<b>%s</b>' % profile_username) self.fullname.setText(i18n.get('loading')) self.show() self.raise_() self.showed = True def loading_finished(self, profile, account_id): self.profile = profile self.account_id = str(account_id) self.loader.setVisible(False) self.hline.setVisible(False) self.username.setText('<b>%s</b>' % profile.username) self.fullname.setText(profile.fullname) if get_username_from(account_id) == profile.username: self.you_label.setVisible(True) self.options.setVisible(False) else: self.you_label.setVisible(False) self.options.setVisible(True) self.verified_icon.setVisible(profile.verified) self.protected_icon.setVisible(profile.protected) self.avatar.setPixmap(self.base.load_image('unknown.png', True)) self.bio.set_info(profile.bio) self.location.set_info(profile.location) self.web.set_info(profile.url) self.tweets.set_value(str(profile.statuses_count)) self.following.set_value(str(profile.friends_count)) self.followers.set_value(str(profile.followers_count)) self.favorites.set_value(str(profile.favorites_count)) column_id = "%s-profile_recent" % self.account_id self.last_statuses.set_column_id(column_id) self.last_statuses.update_statuses(profile.recent_updates) self.show() self.raise_() def is_for_profile(self, column_id): if column_id.find('profile_recent') > 0: return True return False def update_avatar(self, image_path, username): if username != self.profile.username or not self.showed: return self.avatar.setPixmap(self.base.load_image(image_path, True)) def update_following(self, username, following): if username != self.profile.username or not self.showed: return self.profile.following = following def error(self, message): self.loader.setVisible(False) self.hline.setVisible(False) self.fullname.setText('') self.error_message.setText(message) self.error_message.setVisible(True) self.timer = QTimer() self.timer.timeout.connect(self.__on_timeout) self.timer.start(5000) self.show() self.raise_() def error_marking_status_as_favorite(self, status_id): self.last_statuses.release_status(status_id) self.last_statuses.notify_error( status_id, i18n.get('error_marking_status_as_favorite')) def error_unmarking_status_as_favorite(self, status_id): self.last_statuses.release_status(status_id) self.last_statuses.notify_error( status_id, i18n.get('error_unmarking_status_as_favorite')) def error_repeating_status(self, status_id): self.last_statuses.release_status(status_id) self.last_statuses.notify_error(status_id, i18n.get('error_repeating_status')) def error_loading_conversation(self, status_root_id): self.last_statuses.error_in_conversation(status_root_id) self.last_statuses.notify_error(self.base.random_id(), i18n.get('error_loading_conversation'))
class StatusesColumn(QWidget): NOTIFICATION_ERROR = 'error' NOTIFICATION_SUCCESS = 'success' NOTIFICATION_WARNING = 'warning' NOTIFICATION_INFO = 'notice' def __init__(self, base, column_id, include_header=True): QWidget.__init__(self) self.base = base self.setMinimumWidth(280) self.statuses = [] self.conversations = {} self.id_ = None #self.fgcolor = "#e3e3e3" #self.fgcolor = "#f9a231" #self.updating = False self.last_id = None self.loader = BarLoadIndicator() self.loader.setVisible(False) self.webview = StatusesWebView(self.base, self.id_) self.webview.link_clicked.connect(self.__link_clicked) self.webview.hashtag_clicked.connect(self.__hashtag_clicked) self.webview.profile_clicked.connect(self.__profile_clicked) self.webview.cmd_clicked.connect(self.__cmd_clicked) layout = QVBoxLayout() layout.setSpacing(0) layout.setContentsMargins(0, 0, 0, 0) if include_header: header = self.__build_header(column_id) layout.addWidget(header) layout.addWidget(self.loader) layout.addWidget(self.webview, 1) self.setLayout(layout) def __build_header(self, column_id): self.set_column_id(column_id) username = get_username_from(self.account_id) column_slug = get_column_slug_from(column_id) column_slug = column_slug.replace('%23', '#') column_slug = column_slug.replace('%40', '@') #font = QFont('Titillium Web', 18, QFont.Normal, False) # This is to handle the 96dpi vs 72dpi screen resolutions on Mac vs the world if detect_os() == OS_MAC: font = QFont('Maven Pro Light', 25, 0, False) font2 = QFont('Monda', 14, 0, False) else: font = QFont('Maven Pro Light', 16, QFont.Light, False) font2 = QFont('Monda', 10, QFont.Light, False) bg_style = "background-color: %s; color: %s;" % (self.base.bgcolor, self.base.fgcolor) label = "%s : %s" % (username, column_slug) caption = QLabel(username) caption.setStyleSheet("QLabel { %s }" % bg_style) caption.setFont(font) caption2 = QLabel(column_slug) caption2.setStyleSheet("QLabel { %s }" % bg_style) caption2.setFont(font2) caption2.setAlignment(Qt.AlignLeft | Qt.AlignBottom) caption_box = QHBoxLayout() caption_box.setSpacing(8) caption_box.addWidget(caption) caption_box.addWidget(caption2) caption_box.addStretch(1) close_button = ImageButton(self.base, 'action-delete-shadowed.png', i18n.get('delete_column')) close_button.clicked.connect(self.__delete_column) close_button.setStyleSheet("QToolButton { %s border: 0px solid %s;}" % (bg_style, self.base.bgcolor)) header_layout = QHBoxLayout() header_layout.addLayout(caption_box, 1) header_layout.addWidget(close_button) header = QWidget() header.setStyleSheet("QWidget { %s }" % bg_style) header.setLayout(header_layout) return header def __delete_column(self): self.base.core.delete_column(self.id_) def __link_clicked(self, url): url = str(url) preview_service = get_preview_service_from_url(url) self.base.open_url(url) def __hashtag_clicked(self, hashtag): self.base.add_search_column(self.account_id, str(hashtag)) def __profile_clicked(self, username): self.base.show_profile_dialog(self.account_id, str(username)) def __cmd_clicked(self, url): status_id = str(url.split(':')[1]) cmd = url.split(':')[0] status = None try: print 'Seeking for status in self array' for status_ in self.statuses: if status_.id_ == status_id: status = status_ break if status is None: raise KeyError except KeyError: print 'Seeking for status in conversations array' for status_root, statuses in self.conversations.iteritems(): for item in statuses: if item.id_ == status_id: status = item break if status is not None: break if status is None: self.notify_error(status_id, i18n.get('try_again')) if cmd == 'reply': self.__reply_status(status) elif cmd == 'quote': self.__quote_status(status) elif cmd == 'repeat': self.__repeat_status(status) elif cmd == 'delete': self.__delete_status(status) elif cmd == 'favorite': self.__mark_status_as_favorite(status) elif cmd == 'unfavorite': self.__unmark_status_as_favorite(status) elif cmd == 'delete_direct': self.__delete_direct_message(status) elif cmd == 'reply_direct': self.__reply_direct_message(status) elif cmd == 'view_conversation': self.__view_conversation(status) elif cmd == 'hide_conversation': self.__hide_conversation(status) elif cmd == 'show_avatar': self.__show_avatar(status) def __reply_status(self, status): self.base.show_update_box_for_reply(self.account_id, status) def __quote_status(self, status): self.base.show_update_box_for_quote(self.account_id, status) def __repeat_status(self, status): confirmation = self.base.show_confirmation_message( i18n.get('confirm_retweet'), i18n.get('do_you_want_to_retweet_status')) if confirmation: self.lock_status(status.id_) self.base.repeat_status(self.id_, self.account_id, status) def __delete_status(self, status): confirmation = self.base.show_confirmation_message( i18n.get('confirm_delete'), i18n.get('do_you_want_to_delete_status')) if confirmation: self.lock_status(status.id_) self.base.delete_status(self.id_, self.account_id, status) def __delete_direct_message(self, status): confirmation = self.base.show_confirmation_message( i18n.get('confirm_delete'), i18n.get('do_you_want_to_delete_direct_message')) if confirmation: self.base.delete_direct_message(self.id_, self.account_id, status) def __reply_direct_message(self, status): self.base.show_update_box_for_reply_direct(self.account_id, status) def __mark_status_as_favorite(self, status): self.lock_status(status.id_) self.base.mark_status_as_favorite(self.id_, self.account_id, status) def __unmark_status_as_favorite(self, status): self.lock_status(status.id_) self.base.unmark_status_as_favorite(self.id_, self.account_id, status) def __view_conversation(self, status): self.webview.view_conversation(status.id_) self.base.get_conversation(self.account_id, status, self.id_, status.id_) def __hide_conversation(self, status): del self.conversations[status.id_] self.webview.clear_conversation(status.id_) def __show_avatar(self, status): self.base.show_profile_image(self.account_id, status.username) def __set_last_status_id(self, statuses): if statuses[0].repeated_by: self.last_id = statuses[0].original_status_id else: self.last_id = statuses[0].id_ def set_column_id(self, column_id): self.id_ = column_id self.account_id = get_account_id_from(column_id) self.protocol_id = get_protocol_from(self.account_id) self.webview.column_id = column_id def clear(self): self.webview.clear() def start_updating(self): self.loader.setVisible(True) return self.last_id def stop_updating(self): self.loader.setVisible(False) def update_timestamps(self): self.webview.sync_timestamps(self.statuses) def update_statuses(self, statuses): self.__set_last_status_id(statuses) self.update_timestamps() self.webview.update_statuses(statuses) # Filter repeated statuses # FIXME: This should be done with list comprehension using comparation methods on status.py unique_statuses = [] for s1 in statuses: exist = False for s2 in self.statuses: if s1.id_ == s2.id_: exist = True break if not exist: unique_statuses.append(s1) # Remove old conversations to_remove = self.statuses[-(len(unique_statuses)):] self.statuses = statuses + self.statuses[:-(len(unique_statuses))] for status in to_remove: if self.conversations.has_key(status.id_): del self.conversations[status.id_] def update_conversation(self, status, status_root_id): status_root_id = str(status_root_id) self.webview.update_conversation(status, status_root_id) if status_root_id in self.conversations: self.conversations[status_root_id].append(status) else: self.conversations[status_root_id] = [status] def error_in_conversation(self, status_root_id): self.webview.clear_conversation(status_root_id) def mark_status_as_favorite(self, status_id): mark = "setFavorite('%s')" % status_id self.webview.execute_javascript(mark) def unmark_status_as_favorite(self, status_id): mark = "unsetFavorite('%s');" % status_id self.webview.execute_javascript(mark) def mark_status_as_repeated(self, status_id): mark = "setRepeated('%s');" % status_id self.webview.execute_javascript(mark) def remove_status(self, status_id): operation = "removeStatus('%s');" % status_id self.webview.execute_javascript(operation) def lock_status(self, status_id): operation = "lockStatus('%s');" % status_id self.webview.execute_javascript(operation) def release_status(self, status_id): operation = "releaseStatus('%s');" % status_id self.webview.execute_javascript(operation) def notify(self, id_, type_, message): message = message.replace("'", "\"") notification = "addNotify('%s', '%s', '%s');" % (id_, type_, message) self.webview.execute_javascript(notification) def notify_error(self, id_, message): self.notify(id_, self.NOTIFICATION_ERROR, message) def notify_success(self, id_, message): self.notify(id_, self.NOTIFICATION_SUCCESS, message) def notify_warning(self, id_, message): self.notify(id_, self.NOTIFICATION_WARNING, message) def notify_info(self, id_, message): self.notify(id_, self.NOTIFICATION_INFO, message)
class UpdateBox(QWidget): def __init__(self, base): QWidget.__init__(self) self.base = base self.showed = False self.setFixedSize(500, 120) self.text_edit = CompletionTextEdit() self.upload_button = ImageButton(base, 'action-upload.png', i18n.get('upload_image')) self.short_button = ImageButton(base, 'action-shorten.png', i18n.get('short_urls')) font = QFont() font.setPointSize(18) font.setBold(True) self.char_count = QLabel('140') self.char_count.setFont(font) self.update_button = QPushButton(i18n.get('update')) self.update_button.setToolTip(self.base.get_shortcut_string('Enter')) self.queue_button = QPushButton(i18n.get('add_to_queue')) self.queue_button.setToolTip(self.base.get_shortcut_string('P')) self.accounts_combo = QComboBox() buttons = QHBoxLayout() buttons.setSpacing(4) buttons.addWidget(self.accounts_combo) buttons.addWidget(self.upload_button) buttons.addWidget(self.short_button) buttons.addStretch(0) buttons.addWidget(self.char_count) buttons.addWidget(self.queue_button) buttons.addWidget(self.update_button) self.loader = BarLoadIndicator() self.error_message = ErrorLabel() self.update_button.clicked.connect(self.__update_status) self.queue_button.clicked.connect(self.__queue_status) self.short_button.clicked.connect(self.__short_urls) self.upload_button.clicked.connect(self.__upload_image) self.text_edit.textChanged.connect(self.__update_count) self.text_edit.quit.connect(self.closeEvent) self.text_edit.activated.connect(self.__update_status) self.text_edit.enqueued.connect(self.__queue_status) layout = QVBoxLayout() layout.setSpacing(0) layout.addWidget(self.text_edit) layout.addWidget(self.loader) layout.addSpacing(5) layout.addWidget(self.error_message) layout.addLayout(buttons) layout.setContentsMargins(5, 5, 5, 5) self.setLayout(layout) self.__clear() def __count_chars(self): message = self.text_edit.toPlainText() urls = [str(url) for url in get_urls(message) if len(url) > 23] for url in urls: message = message.replace(url, '0' * 23) return MAX_CHAR - len(message) def __update_count(self): remaining_chars = self.__count_chars() if remaining_chars <= 10: self.char_count.setStyleSheet("QLabel { color: #D40D12 }") elif remaining_chars > 10 and remaining_chars <= 20: self.char_count.setStyleSheet("QLabel { color: #D4790D }") else: self.char_count.setStyleSheet("QLabel { color: #000000 }") self.char_count.setText(str(remaining_chars)) def __validate(self, message, accounts, index): if len(message) == 0: self.error(i18n.get('you_can_not_submit_an_empty_message')) return False if index == 0 and len(accounts) > 1: self.error(i18n.get('select_an_account_before_post')) return False if self.__count_chars() < 0: self.error(i18n.get('message_too_long')) return False return True def __short_urls(self): self.enable(False) message = unicode(self.text_edit.toPlainText()) self.base.short_urls(message) def __upload_image(self): index = self.accounts_combo.currentIndex() accounts = self.base.core.get_registered_accounts() if index == 0 and len(accounts) > 1: self.error(i18n.get('select_an_account_before_post')) return False account_id = str(self.accounts_combo.itemData(index).toPyObject()) filename = str(QFileDialog.getOpenFileName(self, i18n.get('upload_image'), self.base.home_path)) if filename != '': self.enable(False) self.base.upload_media(account_id, filename) def __update_status(self): index = self.accounts_combo.currentIndex() accounts = self.base.core.get_registered_accounts() message = unicode(self.text_edit.toPlainText()) if not self.__validate(message, accounts, index): self.enable(True) return self.enable(False) account_id = str(self.accounts_combo.itemData(index).toPyObject()) if self.direct_message_to: self.base.send_direct_message(account_id, self.direct_message_to, message) else: if account_id == 'broadcast': self.base.broadcast_status(message) else: self.base.update_status(account_id, message, self.in_reply_to_id) def __queue_status(self): index = self.accounts_combo.currentIndex() accounts = self.base.core.get_registered_accounts() account_id = str(self.accounts_combo.itemData(index).toPyObject()) message = unicode(self.text_edit.toPlainText()) if not self.__validate(message, accounts, index): self.enable(True) return self.enable(False) self.base.push_status_to_queue(account_id, message) def __clear(self): self.account_id = None self.in_reply_to_id = None self.in_reply_to_user = None self.direct_message_to = None self.quoting = False self.message = None self.cursor_position = None self.text_edit.setText('') self.accounts_combo.setCurrentIndex(0) self.queue_button.setEnabled(True) self.loader.setVisible(False) self.error_message.setVisible(False) self.error_message.setText('') self.enable(True) self.showed = False def __show(self): self.update_friends_list() short_service = self.base.get_shorten_url_service() short_tooltip = "%s (%s)" % (i18n.get('short_url'), short_service) self.short_button.setToolTip(short_tooltip) upload_service = self.base.get_upload_media_service() upload_tooltip = "%s (%s)" % (i18n.get('upload_image'), upload_service) self.upload_button.setToolTip(upload_tooltip) self.accounts_combo.clear() accounts = self.base.core.get_registered_accounts() if len(accounts) > 1: self.accounts_combo.addItem('--', '') for account in accounts: protocol = get_protocol_from(account.id_) icon = QIcon(self.base.get_image_path('%s.png' % protocol)) self.accounts_combo.addItem(icon, get_username_from(account.id_), account.id_) if len(accounts) > 1: icon = QIcon(self.base.get_image_path('action-conversation.png')) self.accounts_combo.addItem(icon, i18n.get('broadcast'), 'broadcast') if self.account_id: index = self.accounts_combo.findData(self.account_id) if index > 0: self.accounts_combo.setCurrentIndex(index) self.accounts_combo.setEnabled(False) if self.message: self.text_edit.setText(self.message) cursor = self.text_edit.textCursor() cursor.movePosition(self.cursor_position, QTextCursor.MoveAnchor) self.text_edit.setTextCursor(cursor) QWidget.show(self) self.showed = True def __on_timeout(self): self.error_message.setText('') self.error_message.setVisible(False) def show(self): if self.showed: return self.raise_() self.setWindowTitle(i18n.get('whats_happening')) self.__show() def show_for_reply(self, account_id, status): if self.showed: return self.raise_() title = "%s @%s" % (i18n.get('reply_to'), status.username) self.setWindowTitle(title) self.account_id = account_id self.in_reply_to_id = status.id_ self.in_reply_to_user = status.username mentions = ' '.join(["@%s" % user for user in status.get_mentions()]) self.message = "%s " % mentions self.cursor_position = QTextCursor.End self.__show() def show_for_send_direct(self, account_id, username): if self.showed: return self.raise_() title = "%s @%s" % (i18n.get('send_message_to'), username) self.setWindowTitle(title) self.account_id = account_id self.direct_message_to = username self.__show() self.queue_button.setEnabled(False) def show_for_reply_direct(self, account_id, status): if self.showed: return self.raise_() title = "%s @%s" % (i18n.get('send_message_to'), status.username) self.setWindowTitle(title) self.account_id = account_id self.direct_message_to = status.username self.__show() self.queue_button.setEnabled(False) def show_for_quote(self, account_id, status): if self.showed: return self.raise_() self.setWindowTitle(i18n.get('quoting')) self.account_id = account_id self.message = " RT @%s %s" % (status.username, status.text) self.cursor_position = QTextCursor.Start self.quoting = True self.__show() self.queue_button.setEnabled(False) def closeEvent(self, event=None): message = unicode(self.text_edit.toPlainText()) if len(message) > 0: confirmation = self.base.show_confirmation_message(i18n.get('confirm_discard'), i18n.get('do_you_want_to_discard_message')) if not confirmation: return if event: event.ignore() self.__clear() self.hide() def enable(self, value): self.text_edit.setEnabled(value) if not self.account_id: self.accounts_combo.setEnabled(value) if self.in_reply_to_id or self.direct_message_to or self.quoting: self.queue_button.setEnabled(False) else: self.queue_button.setEnabled(value) self.upload_button.setEnabled(value) self.short_button.setEnabled(value) self.update_button.setEnabled(value) self.loader.setVisible(not value) def done(self): self.__clear() self.hide() def error(self, message): self.enable(True) self.error_message.setText(message) self.error_message.setVisible(True) self.timer = QTimer() self.timer.timeout.connect(self.__on_timeout) self.timer.start(5000) def after_short_url(self, message): if self.base.is_exception(message): self.error(i18n.get('error_shorting_url')) else: self.text_edit.setText(message) self.enable(True) def after_upload_media(self, media_url): if self.base.is_exception(media_url): self.error(i18n.get('error_uploading_image')) else: text_cursor = self.text_edit.textCursor() text_cursor.select(QTextCursor.WordUnderCursor) if text_cursor.selectedText() != '': media_url = " %s" % media_url text_cursor.clearSelection() text_cursor.insertText(media_url) self.text_edit.setTextCursor(text_cursor) self.enable(True) def update_friends_list(self): completer = QCompleter(self.base.load_friends_list_with_extras()) self.text_edit.setCompleter(completer)
def __init__(self, base): Window.__init__(self, base, i18n.get('user_profile')) self.account_id = None self.setFixedSize(380, 450) self.username = QLabel('') self.username.setTextFormat(Qt.RichText) self.fullname = QLabel('') self.options = ImageButton(base, 'action-status-menu.png', i18n.get('')) self.options.clicked.connect(self.__options_clicked) self.verified_icon = QLabel() self.verified_icon.setPixmap(base.load_image('mark-verified.png', True)) self.protected_icon = QLabel() self.protected_icon.setPixmap(base.load_image('mark-protected.png', True)) self.avatar = ClickableLabel() self.avatar.setPixmap(base.load_image('unknown.png', True)) self.avatar.clicked.connect(self.__show_avatar) self.you_label = QLabel(i18n.get('this_is_you')) self.you_label.setVisible(False) info_line1 = QHBoxLayout() info_line1.setSpacing(5) info_line1.addWidget(self.username) info_line1.addSpacing(5) info_line1.addWidget(self.verified_icon) info_line1.addWidget(self.protected_icon) info_line1.addStretch(0) info_line2 = QHBoxLayout() info_line2.addWidget(self.fullname, 1) info_line2.addWidget(self.options) info_line2.addWidget(self.you_label) user_info = QVBoxLayout() user_info.addLayout(info_line1) user_info.addLayout(info_line2) self.loader = BarLoadIndicator() self.loader.setVisible(False) self.error_message = ErrorLabel() self.error_message.setVisible(False) header = QHBoxLayout() header.setContentsMargins(5, 10, 5, 0) header.addWidget(self.avatar) header.addSpacing(10) header.addLayout(user_info) # User Info self.bio = UserField(base, 'bio', 'icon-bio.png') self.bio.set_word_wrap(True) self.bio.set_info('') self.location = UserField(base, 'location', 'icon-location.png') self.location.set_info('') self.web = UserField(base, 'web', 'icon-home.png') self.web.set_info('') self.tweets = StatInfoBox('tweets', '') self.following = StatInfoBox('following', '') self.followers = StatInfoBox('followers', '') self.favorites = StatInfoBox('favorites', '') footer_layout = QHBoxLayout() footer_layout.setContentsMargins(0, 5, 0, 10) footer_layout.setSpacing(0) footer_layout.addLayout(self.tweets) footer_layout.addWidget(VLine()) footer_layout.addLayout(self.following) footer_layout.addWidget(VLine()) footer_layout.addLayout(self.followers) footer_layout.addWidget(VLine()) footer_layout.addLayout(self.favorites) footer = QWidget() footer.setLayout(footer_layout) footer.setStyleSheet("QWidget { background-color: #333; color: white; }") body_layout = QVBoxLayout() body_layout.setSpacing(15) body_layout.setContentsMargins(0, 0, 0, 0) body_layout.addLayout(self.bio) body_layout.addLayout(self.location) body_layout.addLayout(self.web) body_layout.addWidget(footer) body = QWidget() body.setLayout(body_layout) self.last_statuses = StatusesColumn(self.base, None, False) self.tabs = QTabWidget(self) self.tabs.setTabsClosable(False) self.tabs.setMovable(False) self.tabs.addTab(body, i18n.get('info')) self.tabs.addTab(self.last_statuses, i18n.get('recent')) self.hline = HLine() self.hline.setMinimumHeight(2) layout = QVBoxLayout() layout.addLayout(header) layout.addSpacing(10) layout.addWidget(self.hline) layout.addWidget(self.loader) layout.addWidget(self.error_message) layout.addSpacing(10) layout.addWidget(self.tabs, 1) layout.setSpacing(0) layout.setContentsMargins(5, 5, 5, 5) self.setLayout(layout) self.__clear()
class ProfileDialog(Window): options_clicked = pyqtSignal(QPoint, object) def __init__(self, base): Window.__init__(self, base, i18n.get('user_profile')) self.account_id = None self.setFixedSize(380, 450) self.username = QLabel('') self.username.setTextFormat(Qt.RichText) self.fullname = QLabel('') self.options = ImageButton(base, 'action-status-menu.png', i18n.get('')) self.options.clicked.connect(self.__options_clicked) self.verified_icon = QLabel() self.verified_icon.setPixmap(base.load_image('mark-verified.png', True)) self.protected_icon = QLabel() self.protected_icon.setPixmap(base.load_image('mark-protected.png', True)) self.avatar = ClickableLabel() self.avatar.setPixmap(base.load_image('unknown.png', True)) self.avatar.clicked.connect(self.__show_avatar) self.you_label = QLabel(i18n.get('this_is_you')) self.you_label.setVisible(False) info_line1 = QHBoxLayout() info_line1.setSpacing(5) info_line1.addWidget(self.username) info_line1.addSpacing(5) info_line1.addWidget(self.verified_icon) info_line1.addWidget(self.protected_icon) info_line1.addStretch(0) info_line2 = QHBoxLayout() info_line2.addWidget(self.fullname, 1) info_line2.addWidget(self.options) info_line2.addWidget(self.you_label) user_info = QVBoxLayout() user_info.addLayout(info_line1) user_info.addLayout(info_line2) self.loader = BarLoadIndicator() self.loader.setVisible(False) self.error_message = ErrorLabel() self.error_message.setVisible(False) header = QHBoxLayout() header.setContentsMargins(5, 10, 5, 0) header.addWidget(self.avatar) header.addSpacing(10) header.addLayout(user_info) # User Info self.bio = UserField(base, 'bio', 'icon-bio.png') self.bio.set_word_wrap(True) self.bio.set_info('') self.location = UserField(base, 'location', 'icon-location.png') self.location.set_info('') self.web = UserField(base, 'web', 'icon-home.png') self.web.set_info('') self.tweets = StatInfoBox('tweets', '') self.following = StatInfoBox('following', '') self.followers = StatInfoBox('followers', '') self.favorites = StatInfoBox('favorites', '') footer_layout = QHBoxLayout() footer_layout.setContentsMargins(0, 5, 0, 10) footer_layout.setSpacing(0) footer_layout.addLayout(self.tweets) footer_layout.addWidget(VLine()) footer_layout.addLayout(self.following) footer_layout.addWidget(VLine()) footer_layout.addLayout(self.followers) footer_layout.addWidget(VLine()) footer_layout.addLayout(self.favorites) footer = QWidget() footer.setLayout(footer_layout) footer.setStyleSheet("QWidget { background-color: #333; color: white; }") body_layout = QVBoxLayout() body_layout.setSpacing(15) body_layout.setContentsMargins(0, 0, 0, 0) body_layout.addLayout(self.bio) body_layout.addLayout(self.location) body_layout.addLayout(self.web) body_layout.addWidget(footer) body = QWidget() body.setLayout(body_layout) self.last_statuses = StatusesColumn(self.base, None, False) self.tabs = QTabWidget(self) self.tabs.setTabsClosable(False) self.tabs.setMovable(False) self.tabs.addTab(body, i18n.get('info')) self.tabs.addTab(self.last_statuses, i18n.get('recent')) self.hline = HLine() self.hline.setMinimumHeight(2) layout = QVBoxLayout() layout.addLayout(header) layout.addSpacing(10) layout.addWidget(self.hline) layout.addWidget(self.loader) layout.addWidget(self.error_message) layout.addSpacing(10) layout.addWidget(self.tabs, 1) layout.setSpacing(0) layout.setContentsMargins(5, 5, 5, 5) self.setLayout(layout) self.__clear() def __clear(self): self.profile = None self.showed = False self.account_id = None self.verified_icon.setVisible(False) self.protected_icon.setVisible(False) self.you_label.setVisible(False) self.options.setVisible(False) self.loader.setVisible(False) self.error_message.setVisible(False) self.avatar.setPixmap(self.base.load_image('unknown.png', True)) self.bio.set_info('') self.location.set_info('') self.web.set_info('') self.tweets.set_value('') self.following.set_value('') self.followers.set_value('') self.favorites.set_value('') self.last_statuses.id_ = None self.last_statuses.clear() self.tabs.setCurrentIndex(0) def __options_clicked(self): self.options_clicked.emit(QCursor.pos(), self.profile) def __show_avatar(self): self.base.show_profile_image(self.account_id, self.profile.username) def __on_timeout(self): self.error_message.setText('') self.error_message.setVisible(False) def closeEvent(self, event=None): if event: event.ignore() self.__clear() self.hide() def start_loading(self, profile_username): self.__clear() self.hline.setVisible(False) self.loader.setVisible(True) self.username.setText('<b>%s</b>' % profile_username) self.fullname.setText(i18n.get('loading')) self.show() self.raise_() self.showed = True def loading_finished(self, profile, account_id): self.profile = profile self.account_id = str(account_id) self.loader.setVisible(False) self.hline.setVisible(False) self.username.setText('<b>%s</b>' % profile.username) self.fullname.setText(profile.fullname) if get_username_from(account_id) == profile.username: self.you_label.setVisible(True) self.options.setVisible(False) else: self.you_label.setVisible(False) self.options.setVisible(True) self.verified_icon.setVisible(profile.verified) self.protected_icon.setVisible(profile.protected) self.avatar.setPixmap(self.base.load_image('unknown.png', True)) self.bio.set_info(profile.bio) self.location.set_info(profile.location) self.web.set_info(profile.url) self.tweets.set_value(str(profile.statuses_count)) self.following.set_value(str(profile.friends_count)) self.followers.set_value(str(profile.followers_count)) self.favorites.set_value(str(profile.favorites_count)) column_id = "%s-profile_recent" % self.account_id self.last_statuses.set_column_id(column_id) self.last_statuses.update_statuses(profile.recent_updates) self.show() self.raise_() def is_for_profile(self, column_id): if column_id.find('profile_recent') > 0: return True return False def update_avatar(self, image_path, username): if username != self.profile.username or not self.showed: return self.avatar.setPixmap(self.base.load_image(image_path, True)) def update_following(self, username, following): if username != self.profile.username or not self.showed: return self.profile.following = following def error(self, message): self.loader.setVisible(False) self.hline.setVisible(False) self.fullname.setText('') self.error_message.setText(message) self.error_message.setVisible(True) self.timer = QTimer() self.timer.timeout.connect(self.__on_timeout) self.timer.start(5000) self.show() self.raise_() def error_marking_status_as_favorite(self, status_id): self.last_statuses.release_status(status_id) self.last_statuses.notify_error(status_id, i18n.get('error_marking_status_as_favorite')) def error_unmarking_status_as_favorite(self, status_id): self.last_statuses.release_status(status_id) self.last_statuses.notify_error(status_id, i18n.get('error_unmarking_status_as_favorite')) def error_repeating_status(self, status_id): self.last_statuses.release_status(status_id) self.last_statuses.notify_error(status_id, i18n.get('error_repeating_status')) def error_loading_conversation(self, status_root_id): self.last_statuses.error_in_conversation(status_root_id) self.last_statuses.notify_error(self.base.random_id(), i18n.get('error_loading_conversation'))