class Dock(QStatusBar): accounts_clicked = pyqtSignal() columns_clicked = pyqtSignal(QPoint) search_clicked = pyqtSignal() updates_clicked = pyqtSignal() messages_clicked = pyqtSignal() queue_clicked = pyqtSignal() filters_clicked = pyqtSignal() preferences_clicked = pyqtSignal() LOADING = -1 EMPTY = 0 WITH_ACCOUNTS = 1 NORMAL = 2 def __init__(self, base): QStatusBar.__init__(self) self.base = base self.status = self.LOADING style = "background-color: %s; border: 0px solid %s;" % ( self.base.bgcolor, self.base.bgcolor) self.updates_button = ImageButton(base, 'dock-updates.png', i18n.get('update_status')) self.messages_button = ImageButton(base, 'dock-messages.png', i18n.get('send_direct_message')) self.search_button = ImageButton(base, 'dock-search.png', i18n.get('search')) self.settings_button = ImageButton(base, 'dock-preferences.png', i18n.get('settings')) self.updates_button.clicked.connect(self.__updates_clicked) self.messages_button.clicked.connect(self.__messages_clicked) self.search_button.clicked.connect(self.__search_clicked) self.settings_button.clicked.connect(self.__settings_clicked) separator = QWidget() separator.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) toolbar = QToolBar() toolbar.addWidget(self.settings_button) toolbar.addWidget(separator) toolbar.addWidget(self.search_button) toolbar.addWidget(self.messages_button) toolbar.addWidget(self.updates_button) toolbar.setMinimumHeight(30) toolbar.setContentsMargins(0, 0, 0, 0) toolbar.setStyleSheet( "QToolBar { %s }; QToolButton { %s opacity: 128; }; QToolButton:hover { %s opacity: 255;}" % (style, style, style)) self.addPermanentWidget(toolbar, 1) self.setSizeGripEnabled(False) self.setContentsMargins(0, 0, 0, 0) self.setStyleSheet("QStatusBar { %s }" % style) self.loading() def __accounts_clicked(self): self.accounts_clicked.emit() def __columns_clicked(self): self.columns_clicked.emit(QCursor.pos()) def __search_clicked(self): self.search_clicked.emit() def __updates_clicked(self): self.updates_clicked.emit() def __messages_clicked(self): self.messages_clicked.emit() def __queue_clicked(self): self.queue_clicked.emit() def __filters_clicked(self): self.filters_clicked.emit() def __preferences_clicked(self): self.preferences_clicked.emit() def __about_clicked(self): self.base.show_about_dialog() def __settings_clicked(self): self.settings_menu = QMenu(self) accounts = QAction(i18n.get('accounts'), self) accounts.triggered.connect(partial(self.__accounts_clicked)) queue = QAction(i18n.get('messages_queue'), self) queue.triggered.connect(partial(self.__queue_clicked)) columns = QAction(i18n.get('columns'), self) filters = QAction(i18n.get('filters'), self) filters.triggered.connect(partial(self.__filters_clicked)) preferences = QAction(i18n.get('preferences'), self) preferences.triggered.connect(partial(self.__preferences_clicked)) about_turpial = QAction(i18n.get('about_turpial'), self) about_turpial.triggered.connect(partial(self.__about_clicked)) if self.status > self.EMPTY: columns_menu = self.base.build_columns_menu() columns.setMenu(columns_menu) elif self.status == self.EMPTY: queue.setEnabled(False) columns.setEnabled(False) elif self.status == self.LOADING: accounts.setEnabled(False) queue.setEnabled(False) columns.setEnabled(False) filters.setEnabled(False) preferences.setEnabled(False) self.settings_menu.addAction(accounts) self.settings_menu.addAction(columns) #self.settings_menu.addAction(filters) self.settings_menu.addAction(queue) self.settings_menu.addSeparator() self.settings_menu.addAction(preferences) self.settings_menu.addSeparator() self.settings_menu.addAction(about_turpial) self.settings_menu.exec_(QCursor.pos()) def loading(self): self.updates_button.setEnabled(False) self.messages_button.setEnabled(False) self.search_button.setEnabled(False) self.status = self.LOADING def empty(self, with_accounts=None): self.updates_button.setEnabled(False) self.messages_button.setEnabled(False) self.search_button.setEnabled(False) if with_accounts: self.status = self.WITH_ACCOUNTS else: self.status = self.EMPTY def normal(self): self.updates_button.setEnabled(True) self.messages_button.setEnabled(True) self.search_button.setEnabled(True) self.status = self.NORMAL
class Dock(QStatusBar): accounts_clicked = pyqtSignal() columns_clicked = pyqtSignal(QPoint) search_clicked = pyqtSignal() updates_clicked = pyqtSignal() messages_clicked = pyqtSignal() queue_clicked = pyqtSignal() filters_clicked = pyqtSignal() preferences_clicked = pyqtSignal() LOADING = -1 EMPTY = 0 WITH_ACCOUNTS = 1 NORMAL = 2 def __init__(self, base): QStatusBar.__init__(self) self.base = base self.status = self.LOADING style = "background-color: %s; border: 0px solid %s;" % (self.base.bgcolor, self.base.bgcolor) self.updates_button = ImageButton(base, 'dock-updates.png', i18n.get('update_status')) self.messages_button = ImageButton(base, 'dock-messages.png', i18n.get('send_direct_message')) self.search_button = ImageButton(base, 'dock-search.png', i18n.get('search')) self.settings_button = ImageButton(base, 'dock-preferences.png', i18n.get('settings')) self.updates_button.clicked.connect(self.__updates_clicked) self.messages_button.clicked.connect(self.__messages_clicked) self.search_button.clicked.connect(self.__search_clicked) self.settings_button.clicked.connect(self.__settings_clicked) separator = QWidget() separator.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) toolbar = QToolBar() toolbar.addWidget(self.settings_button) toolbar.addWidget(separator) toolbar.addWidget(self.search_button) toolbar.addWidget(self.messages_button) toolbar.addWidget(self.updates_button) toolbar.setMinimumHeight(30) toolbar.setContentsMargins(0, 0, 0, 0) toolbar.setStyleSheet("QToolBar { %s }; QToolButton { %s opacity: 128; }; QToolButton:hover { %s opacity: 255;}" % (style, style, style)) self.addPermanentWidget(toolbar, 1) self.setSizeGripEnabled(False) self.setContentsMargins(0, 0, 0, 0) self.setStyleSheet("QStatusBar { %s }" % style) self.loading() def __accounts_clicked(self): self.accounts_clicked.emit() def __columns_clicked(self): self.columns_clicked.emit(QCursor.pos()) def __search_clicked(self): self.search_clicked.emit() def __updates_clicked(self): self.updates_clicked.emit() def __messages_clicked(self): self.messages_clicked.emit() def __queue_clicked(self): self.queue_clicked.emit() def __filters_clicked(self): self.filters_clicked.emit() def __preferences_clicked(self): self.preferences_clicked.emit() def __about_clicked(self): self.base.show_about_dialog() def __settings_clicked(self): self.settings_menu = QMenu(self) accounts = QAction(i18n.get('accounts'), self) accounts.triggered.connect(partial(self.__accounts_clicked)) queue = QAction(i18n.get('messages_queue'), self) queue.triggered.connect(partial(self.__queue_clicked)) columns = QAction(i18n.get('columns'), self) filters = QAction(i18n.get('filters'), self) filters.triggered.connect(partial(self.__filters_clicked)) preferences = QAction(i18n.get('preferences'), self) preferences.triggered.connect(partial(self.__preferences_clicked)) about_turpial = QAction(i18n.get('about_turpial'), self) about_turpial.triggered.connect(partial(self.__about_clicked)) if self.status > self.EMPTY: columns_menu = self.base.build_columns_menu() columns.setMenu(columns_menu) elif self.status == self.EMPTY: queue.setEnabled(False) columns.setEnabled(False) elif self.status == self.LOADING: accounts.setEnabled(False) queue.setEnabled(False) columns.setEnabled(False) filters.setEnabled(False) preferences.setEnabled(False) self.settings_menu.addAction(accounts) self.settings_menu.addAction(columns) #self.settings_menu.addAction(filters) self.settings_menu.addAction(queue) self.settings_menu.addSeparator() self.settings_menu.addAction(preferences) self.settings_menu.addSeparator() self.settings_menu.addAction(about_turpial) self.settings_menu.exec_(QCursor.pos()) def loading(self): self.updates_button.setEnabled(False) self.messages_button.setEnabled(False) self.search_button.setEnabled(False) self.status = self.LOADING def empty(self, with_accounts=None): self.updates_button.setEnabled(False) self.messages_button.setEnabled(False) self.search_button.setEnabled(False) if with_accounts: self.status = self.WITH_ACCOUNTS else: self.status = self.EMPTY def normal(self): self.updates_button.setEnabled(True) self.messages_button.setEnabled(True) self.search_button.setEnabled(True) self.status = self.NORMAL
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)