class CodeCompletionWidget(QFrame): def __init__(self, editor): super(CodeCompletionWidget, self).__init__(None, Qt.FramelessWindowHint | Qt.ToolTip) self._editor = editor self._revision = 0 self._block = 0 self.stack_layout = QStackedLayout(self) self.stack_layout.setContentsMargins(0, 0, 0, 0) self.stack_layout.setSpacing(0) self.completion_list = QListWidget() self.completion_list.setMinimumHeight(200) self.completion_list.setAlternatingRowColors(True) self._list_index = self.stack_layout.addWidget(self.completion_list) self._icons = { 'a': resources.IMAGES['attribute'], 'f': resources.IMAGES['function'], 'c': resources.IMAGES['class'], 'm': resources.IMAGES['module'] } self.cc = code_completion.CodeCompletion() self._completion_results = {} self._prefix = '' self.setVisible(False) self.source = '' self._key_operations = { Qt.Key_Up: self._select_previous_row, Qt.Key_Down: self._select_next_row, Qt.Key_PageUp: (lambda: self._select_previous_row(6)), Qt.Key_PageDown: (lambda: self._select_next_row(6)), Qt.Key_Right: lambda: None, Qt.Key_Left: lambda: None, Qt.Key_Enter: self.pre_key_insert_completion, Qt.Key_Return: self.pre_key_insert_completion, Qt.Key_Tab: self.pre_key_insert_completion, Qt.Key_Space: self.hide_completer, Qt.Key_Escape: self.hide_completer, Qt.Key_Backtab: self.hide_completer, Qt.NoModifier: self.hide_completer, Qt.ShiftModifier: self.hide_completer, } self.desktop = QApplication.instance().desktop() self.connect(self.completion_list, SIGNAL("itemClicked(QListWidgetItem*)"), self.pre_key_insert_completion) self.connect(self._editor.document(), SIGNAL("cursorPositionChanged(QTextCursor)"), self.update_metadata) def _select_next_row(self, move=1): new_row = self.completion_list.currentRow() + move if new_row < self.completion_list.count(): self.completion_list.setCurrentRow(new_row) else: self.completion_list.setCurrentRow(0) return True def _select_previous_row(self, move=1): new_row = self.completion_list.currentRow() - move if new_row >= 0: self.completion_list.setCurrentRow(new_row) else: self.completion_list.setCurrentRow(self.completion_list.count() - move) return True def update_metadata(self, cursor): if settings.CODE_COMPLETION: if self._editor.document().revision() != self._revision and \ cursor.block().blockNumber() != self._block: source = self._editor.get_text() source = source.encode(self._editor.encoding) self.cc.analyze_file(self._editor.ID, source, self._editor.indent, self._editor.useTabs) self._revision = self._editor.document().revision() self._block = cursor.block().blockNumber() def insert_completion(self, insert, type_=ord('a')): if insert != self._prefix: closing = '' if type_ in (ord('f'), ord('c')): closing = '()' extra = len(self._prefix) - len(insert) insertion = '%s%s' % (insert[extra:], closing) self._editor.textCursor().insertText(insertion) self.hide_completer() def _get_geometry(self): cr = self._editor.cursorRect() desktop_geometry = self.desktop.availableGeometry(self._editor) point = self._editor.mapToGlobal(cr.topLeft()) cr.moveTopLeft(point) #Check new position according desktop geometry width = (self.completion_list.sizeHintForColumn(0) + self.completion_list.verticalScrollBar().sizeHint().width() + 10) height = 200 orientation = (point.y() + height) < desktop_geometry.height() if orientation: cr.moveTop(cr.bottom()) cr.setWidth(width) cr.setHeight(height) if not orientation: cr.moveBottom(cr.top()) xpos = desktop_geometry.width() - (point.x() + width) if xpos < 0: cr.moveLeft(cr.left() + xpos) return cr def complete(self, results): self.add_list_items(results) self.completion_list.setCurrentRow(0) cr = self._get_geometry() self.setGeometry(cr) self.completion_list.updateGeometries() self.show() def add_list_items(self, proposals): self.completion_list.clear() for p in proposals: self.completion_list.addItem( QListWidgetItem(QIcon( self._icons.get(p[0], resources.IMAGES['attribute'])), p[1], type=ord(p[0]))) def set_completion_prefix(self, prefix, valid=True): self._prefix = prefix proposals = [] proposals += [('m', item) for item in self._completion_results.get('modules', []) if item.startswith(prefix)] proposals += [('c', item) for item in self._completion_results.get('classes', []) if item.startswith(prefix)] proposals += [ ('a', item) for item in self._completion_results.get('attributes', []) if item.startswith(prefix) ] proposals += [ ('f', item) for item in self._completion_results.get('functions', []) if item.startswith(prefix) ] if proposals and valid: self.complete(proposals) else: self.hide_completer() def _invalid_completion_position(self): result = False cursor = self._editor.textCursor() cursor.movePosition(QTextCursor.StartOfLine, QTextCursor.KeepAnchor) selection = cursor.selectedText()[:-1].split(' ') if len(selection) == 0 or selection[-1] == '' or \ selection[-1].isdigit(): result = True return result def fill_completer(self, force_completion=False): if not force_completion and (self._editor.cursor_inside_string() or self._editor.cursor_inside_comment() or self._invalid_completion_position()): return source = self._editor.get_text() source = source.encode(self._editor.encoding) offset = self._editor.textCursor().position() results = self.cc.get_completion(source, offset) self._completion_results = results if force_completion: cursor = self._editor.textCursor() cursor.movePosition(QTextCursor.StartOfWord, QTextCursor.KeepAnchor) prefix = cursor.selectedText() else: prefix = self._editor._text_under_cursor() self.set_completion_prefix(prefix) def hide_completer(self): self._prefix = '' self.hide() def pre_key_insert_completion(self): type_ = ord('a') current = self.completion_list.currentItem() insert = current.text() if not insert.endswith(')'): type_ = current.type() self.insert_completion(insert, type_) self.hide_completer() return True def process_pre_key_event(self, event): if not self.isVisible() or self._editor.lang != "python": return False skip = self._key_operations.get(event.key(), lambda: False)() self._key_operations.get(event.modifiers(), lambda: False)() if skip is None: skip = False return skip def process_post_key_event(self, event): if not settings.CODE_COMPLETION or self._editor.lang != "python": return if self.isVisible(): source = self._editor.get_text() source = source.encode(self._editor.encoding) offset = self._editor.textCursor().position() prefix, valid = self.cc.get_prefix(source, offset) self.set_completion_prefix(prefix, valid) self.completion_list.setCurrentRow(0) force_completion = (event.key() == Qt.Key_Space and event.modifiers() == Qt.ControlModifier) if event.key() == Qt.Key_Period or force_completion: self.fill_completer(force_completion)
class CodeCompletionWidget(QFrame): def __init__(self, editor): super(CodeCompletionWidget, self).__init__( None, Qt.FramelessWindowHint | Qt.ToolTip) self._editor = editor self._revision = 0 self._block = 0 self.stack_layout = QStackedLayout(self) self.stack_layout.setContentsMargins(0, 0, 0, 0) self.stack_layout.setSpacing(0) self.completion_list = QListWidget() self.completion_list.setMinimumHeight(200) self.completion_list.setAlternatingRowColors(True) self._list_index = self.stack_layout.addWidget(self.completion_list) self._icons = {'a': resources.IMAGES['attribute'], 'f': resources.IMAGES['function'], 'c': resources.IMAGES['class'], 'm': resources.IMAGES['module']} self.cc = code_completion.CodeCompletion() self._completion_results = {} self._prefix = u'' self.setVisible(False) self.source = '' self._key_operations = { Qt.Key_Up: self._select_previous_row, Qt.Key_Down: self._select_next_row, Qt.Key_PageUp: (lambda: self._select_previous_row(6)), Qt.Key_PageDown: (lambda: self._select_next_row(6)), Qt.Key_Right: lambda: None, Qt.Key_Left: lambda: None, Qt.Key_Enter: self.pre_key_insert_completion, Qt.Key_Return: self.pre_key_insert_completion, Qt.Key_Tab: self.pre_key_insert_completion, Qt.Key_Space: self.hide_completer, Qt.Key_Escape: self.hide_completer, Qt.Key_Backtab: self.hide_completer, Qt.NoModifier: self.hide_completer, Qt.ShiftModifier: self.hide_completer, } self.desktop = QApplication.instance().desktop() self.connect(self.completion_list, SIGNAL("itemClicked(QListWidgetItem*)"), self.pre_key_insert_completion) self.connect(self._editor.document(), SIGNAL("cursorPositionChanged(QTextCursor)"), self.update_metadata) def _select_next_row(self, move=1): new_row = self.completion_list.currentRow() + move if new_row < self.completion_list.count(): self.completion_list.setCurrentRow(new_row) else: self.completion_list.setCurrentRow(0) return True def _select_previous_row(self, move=1): new_row = self.completion_list.currentRow() - move if new_row >= 0: self.completion_list.setCurrentRow(new_row) else: self.completion_list.setCurrentRow( self.completion_list.count() - move) return True def update_metadata(self, cursor): if settings.CODE_COMPLETION: if self._editor.document().revision() != self._revision and \ cursor.block().blockNumber() != self._block: source = self._editor.get_text() source = source.encode(self._editor.encoding) self.cc.analyze_file(self._editor.ID, source) self._revision = self._editor.document().revision() self._block = cursor.block().blockNumber() def insert_completion(self, insert, type_=ord('a')): if insert != self._prefix: closing = '' if type_ in (ord('f'), ord('c')): closing = '()' extra = len(self._prefix) - len(insert) insertion = '%s%s' % (insert[extra:], closing) self._editor.textCursor().insertText(insertion) self.hide_completer() def _get_geometry(self): cr = self._editor.cursorRect() desktop_geometry = self.desktop.availableGeometry(self._editor) point = self._editor.mapToGlobal(cr.topLeft()) cr.moveTopLeft(point) #Check new position according desktop geometry width = (self.completion_list.sizeHintForColumn(0) + self.completion_list.verticalScrollBar().sizeHint().width() + 10) height = 200 orientation = (point.y() + height) < desktop_geometry.height() if orientation: cr.moveTop(cr.bottom()) cr.setWidth(width) cr.setHeight(height) if not orientation: cr.moveBottom(cr.top()) xpos = desktop_geometry.width() - (point.x() + width) if xpos < 0: cr.moveLeft(cr.left() + xpos) return cr def complete(self, results): self.add_list_items(results) self.completion_list.setCurrentRow(0) cr = self._get_geometry() self.setGeometry(cr) self.completion_list.updateGeometries() self.show() def add_list_items(self, proposals): self.completion_list.clear() for p in proposals: self.completion_list.addItem( QListWidgetItem( QIcon(self._icons.get(p[0], resources.IMAGES['attribute'])), p[1], type=ord(p[0]))) def set_completion_prefix(self, prefix, valid=True): self._prefix = prefix proposals = [] proposals += [('m', item) for item in self._completion_results.get('modules', []) if item.startswith(prefix)] proposals += [('c', item) for item in self._completion_results.get('classes', []) if item.startswith(prefix)] proposals += [('a', item) for item in self._completion_results.get('attributes', []) if item.startswith(prefix)] proposals += [('f', item) for item in self._completion_results.get('functions', []) if item.startswith(prefix)] if proposals and valid: self.complete(proposals) else: self.hide_completer() def _invalid_completion_position(self): result = False cursor = self._editor.textCursor() cursor.movePosition(QTextCursor.StartOfLine, QTextCursor.KeepAnchor) selection = unicode(cursor.selectedText())[:-1].split(' ') if len(selection) == 0 or selection[-1] == '' or \ selection[-1].isdigit(): result = True return result def fill_completer(self, force_completion=False): if not force_completion and (self._editor.cursor_inside_string() or self._editor.cursor_inside_comment() or self._invalid_completion_position()): return source = self._editor.get_text() source = source.encode(self._editor.encoding) offset = self._editor.textCursor().position() results = self.cc.get_completion(source, offset) self._completion_results = results if force_completion: cursor = self._editor.textCursor() cursor.movePosition(QTextCursor.StartOfWord, QTextCursor.KeepAnchor) prefix = cursor.selectedText() else: prefix = self._editor._text_under_cursor() self.set_completion_prefix(prefix) def hide_completer(self): self._prefix = '' self.hide() def pre_key_insert_completion(self): type_ = ord('a') current = self.completion_list.currentItem() insert = unicode(current.text()) if not insert.endswith(')'): type_ = current.type() self.insert_completion(insert, type_) self.hide_completer() return True def process_pre_key_event(self, event): if not self.isVisible() or self._editor.lang != "python": return False skip = self._key_operations.get(event.key(), lambda: False)() self._key_operations.get(event.modifiers(), lambda: False)() if skip is None: skip = False return skip def process_post_key_event(self, event): if not settings.CODE_COMPLETION or self._editor.lang != "python": return if self.isVisible(): source = self._editor.get_text() source = source.encode(self._editor.encoding) offset = self._editor.textCursor().position() prefix, valid = self.cc.get_prefix(source, offset) self.set_completion_prefix(prefix, valid) self.completion_list.setCurrentRow(0) force_completion = (event.key() == Qt.Key_Space and event.modifiers() == Qt.ControlModifier) if event.key() == Qt.Key_Period or force_completion: self.fill_completer(force_completion)
class CSVImportDialog(QDialog): def __init__(self, parent=None, **kwargs): super(CSVImportDialog, self).__init__(parent, **kwargs) self.setLayout(QVBoxLayout()) self._options = None self._path = None self.__update_pending = False self._optionswidget = CSVOptionsWidget() self._optionswidget.format_changed.connect(self._invalidate_preview) self._stack = QStackedLayout() self._stack.setContentsMargins(0, 0, 0, 0) prev_box = QGroupBox("Preview") prev_box.setLayout(self._stack) self._preview = QTableView(tabKeyNavigation=False) self._preview_error = QLabel() self._stack.addWidget(self._preview) self._stack.addWidget(self._preview_error) buttons = QDialogButtonBox( orientation=Qt.Horizontal, standardButtons=(QDialogButtonBox.Ok | QDialogButtonBox.Cancel | QDialogButtonBox.Reset) ) buttons.accepted.connect(self.accept) buttons.rejected.connect(self.reject) def on_clicked(button): if buttons.buttonRole(button) == QDialogButtonBox.ResetRole: self.reset() buttons.clicked.connect(on_clicked) self.layout().addWidget(self._optionswidget) self.layout().addWidget(prev_box) self.layout().addWidget(buttons) def set_options(self, options): self._options = options self._optionswidget.set_dialect(options.dialect) self._optionswidget.set_header_format(options.header_format) self._optionswidget.set_missing_values(options.missing_values or "") self._invalidate_preview() def options(self): missing_values = self._optionswidget.missing_values() return CSV(self._optionswidget.dialect(), header_format=self._optionswidget.header_format(), missing_values=missing_values) def set_path(self, path): """Set the preview path.""" if self._path != path: self._path = path self._invalidate_preview() def path(self): """Return the preview path""" return self._path def reset(self): """Reset the options to their default values.""" self.set_options(self._options) def _invalidate_preview(self): if not self.__update_pending: self.__update_pending = True QApplication.postEvent(self, QEvent(QEvent.User)) def customEvent(self, event): if self.__update_pending: self.__update_pending = False self._update_preview() def _update_preview(self): if not self._path: return head = itertools.islice(open(self._path, "rU"), 20) head = StringIO("".join(head)) try: data = load_csv(head, **self.options()._asdict()) except csv.Error as err: self._preview_error.setText( "Cannot load data preview:\n {!s}".format(err) ) self._stack.setCurrentWidget(self._preview_error) except (Orange.data.io.CSVFormatError, Orange.data.io.VariableDefinitionError) as err: self._preview_error.setText( "Data formating error:\n {!s}".format(err) ) self._stack.setCurrentWidget(self._preview_error) except Exception as err: self._preview_error.setText( "Cannot load data preview:\n {!s}".format(err) ) self._stack.setCurrentWidget(self._preview_error) raise else: model = TableModel(data, None, self) self._preview.setModel(model) self._preview.resizeColumnsToContents() self._stack.setCurrentWidget(self._preview)
class CSVImportDialog(QDialog): def __init__(self, parent=None, **kwargs): super(CSVImportDialog, self).__init__(parent, **kwargs) self.setLayout(QVBoxLayout()) self._options = None self._path = None self.__update_pending = False self._optionswidget = CSVOptionsWidget() self._optionswidget.format_changed.connect(self._invalidate_preview) self._stack = QStackedLayout() self._stack.setContentsMargins(0, 0, 0, 0) prev_box = QGroupBox("Preview") prev_box.setLayout(self._stack) self._preview = QTableView(tabKeyNavigation=False) self._preview_error = QLabel() self._stack.addWidget(self._preview) self._stack.addWidget(self._preview_error) buttons = QDialogButtonBox( orientation=Qt.Horizontal, standardButtons=(QDialogButtonBox.Ok | QDialogButtonBox.Cancel | QDialogButtonBox.Reset)) buttons.accepted.connect(self.accept) buttons.rejected.connect(self.reject) def on_clicked(button): if buttons.buttonRole(button) == QDialogButtonBox.ResetRole: self.reset() buttons.clicked.connect(on_clicked) self.layout().addWidget(self._optionswidget) self.layout().addWidget(prev_box) self.layout().addWidget(buttons) def set_options(self, options): self._options = options self._optionswidget.set_dialect(options.dialect) self._optionswidget.set_header_format(options.header_format) self._optionswidget.set_missing_values(options.missing_values or "") self._invalidate_preview() def options(self): missing_values = self._optionswidget.missing_values() return CSV(self._optionswidget.dialect(), header_format=self._optionswidget.header_format(), missing_values=missing_values) def set_path(self, path): """Set the preview path.""" if self._path != path: self._path = path self._invalidate_preview() def path(self): """Return the preview path""" return self._path def reset(self): """Reset the options to their default values.""" self.set_options(self._options) def _invalidate_preview(self): if not self.__update_pending: self.__update_pending = True QApplication.postEvent(self, QEvent(QEvent.User)) def customEvent(self, event): if self.__update_pending: self.__update_pending = False self._update_preview() def _update_preview(self): if not self._path: return head = itertools.islice(open(self._path, "rU"), 20) head = StringIO("".join(head)) try: data = load_csv(head, **self.options()._asdict()) except csv.Error as err: self._preview_error.setText( "Cannot load data preview:\n {!s}".format(err)) self._stack.setCurrentWidget(self._preview_error) except (Orange.data.io.CSVFormatError, Orange.data.io.VariableDefinitionError) as err: self._preview_error.setText( "Data formating error:\n {!s}".format(err)) self._stack.setCurrentWidget(self._preview_error) except Exception as err: self._preview_error.setText( "Cannot load data preview:\n {!s}".format(err)) self._stack.setCurrentWidget(self._preview_error) raise else: model = TableModel(data, None, self) self._preview.setModel(model) self._preview.resizeColumnsToContents() self._stack.setCurrentWidget(self._preview)
class CodeCompletionWidget(QFrame): def __init__(self, editor): super(CodeCompletionWidget, self).__init__(None, Qt.FramelessWindowHint | Qt.ToolTip) self._editor = editor self.stack_layout = QStackedLayout(self) self.stack_layout.setContentsMargins(0, 0, 0, 0) self.stack_layout.setSpacing(0) self.completion_list = QListWidget() self.completion_list.setMinimumHeight(200) self.completion_list.setAlternatingRowColors(True) self._list_index = self.stack_layout.addWidget(self.completion_list) self._icons = { 'a': resources.IMAGES['attribute'], 'f': resources.IMAGES['function'], 'c': resources.IMAGES['class'], 'm': resources.IMAGES['module'] } self.cc = code_completion.CodeCompletion() self._completion_results = {} self._prefix = u'' self.setVisible(False) self.source = '' self._key_operations = { Qt.Key_Up: self._select_previous_row, Qt.Key_Down: self._select_next_row, Qt.Key_PageUp: (lambda: self._select_previous_row(6)), Qt.Key_PageDown: (lambda: self._select_next_row(6)), Qt.Key_Right: lambda: None, Qt.Key_Left: lambda: None, Qt.Key_Enter: self.pre_key_insert_completion, Qt.Key_Return: self.pre_key_insert_completion, Qt.Key_Tab: self.pre_key_insert_completion, Qt.Key_Space: self.hide_completer, Qt.Key_Escape: self.hide_completer, Qt.Key_Backtab: self.hide_completer, Qt.NoModifier: self.hide_completer, Qt.ShiftModifier: self.hide_completer, } desktop = QApplication.instance().desktop() self._desktop_geometry = desktop.availableGeometry() self.connect(self._editor.document(), SIGNAL("blockCountChanged(int)"), self.update_metadata) def _select_next_row(self, move=1): new_row = self.completion_list.currentRow() + move if new_row < self.completion_list.count(): self.completion_list.setCurrentRow(new_row) else: self.completion_list.setCurrentRow(0) return True def _select_previous_row(self, move=1): new_row = self.completion_list.currentRow() - move if new_row >= 0: self.completion_list.setCurrentRow(new_row) else: self.completion_list.setCurrentRow(self.completion_list.count() - move) return True def update_metadata(self): source = self._editor.get_text() source = source.encode(self._editor.encoding) self.cc.analyze_file('', source) def insert_completion(self, insert): if insert != self._prefix: extra = len(self._prefix) - len(insert) self._editor.textCursor().insertText(insert[extra:]) self.hide_completer() def _get_geometry(self): cr = self._editor.cursorRect() point = self._editor.mapToGlobal(cr.topLeft()) cr.moveTopLeft(point) #Check new position according desktop geometry width = (self.completion_list.sizeHintForColumn(0) + \ self.completion_list.verticalScrollBar().sizeHint().width() + 10) height = 200 orientation = (point.y() + height) < self._desktop_geometry.height() if orientation: cr.moveTop(cr.bottom()) cr.setWidth(width) cr.setHeight(height) if not orientation: cr.moveBottom(cr.top()) xpos = self._desktop_geometry.width() - (point.x() + width) if xpos < 0: cr.moveLeft(cr.left() + xpos) return cr def complete(self, results): self.add_list_items(results) self.completion_list.setCurrentRow(0) cr = self._get_geometry() self.setGeometry(cr) self.completion_list.updateGeometries() self.show() def add_list_items(self, proposals): self.completion_list.clear() for p in proposals: self.completion_list.addItem( QListWidgetItem( QIcon(self._icons.get(p[0], resources.IMAGES['attribute'])), p[1])) def set_completion_prefix(self, prefix, valid=True): self._prefix = prefix proposals = [] proposals += [('m', item) \ for item in self._completion_results.get('modules', []) \ if item.startswith(prefix)] proposals += [('c', item) \ for item in self._completion_results.get('classes', []) \ if item.startswith(prefix)] proposals += [('a', item) \ for item in self._completion_results.get('attributes', []) \ if item.startswith(prefix)] proposals += [('f', item) \ for item in self._completion_results.get('functions', []) \ if item.startswith(prefix)] if proposals and valid: self.complete(proposals) else: self.hide_completer() def fill_completer(self): source = self._editor.get_text() source = source.encode(self._editor.encoding) offset = self._editor.textCursor().position() results = self.cc.get_completion(source, offset) self._completion_results = results prefix = self._editor._text_under_cursor() self.set_completion_prefix(prefix) def hide_completer(self): self._prefix = '' self.hide() def pre_key_insert_completion(self): insert = unicode(self.completion_list.currentItem().text()) self.insert_completion(insert) self.hide_completer() return True def process_pre_key_event(self, event): if not self.isVisible() or self._editor.lang != "python": return False skip = self._key_operations.get(event.key(), lambda: False)() self._key_operations.get(event.modifiers(), lambda: False)() if skip is None: skip = False return skip def process_post_key_event(self, event): if not settings.CODE_COMPLETION or self._editor.lang != "python": return if self.isVisible(): source = self._editor.get_text() source = source.encode(self._editor.encoding) offset = self._editor.textCursor().position() prefix, valid = self.cc.get_prefix(source, offset) self.set_completion_prefix(prefix, valid) self.completion_list.setCurrentRow(0) if event.key() == Qt.Key_Period or (event.key() == Qt.Key_Space and \ event.modifiers() == Qt.ControlModifier): self.fill_completer()
class CodeCompletionWidget(QFrame): def __init__(self, editor): super(CodeCompletionWidget, self).__init__(None, Qt.FramelessWindowHint | Qt.ToolTip) self._editor = editor self.stack_layout = QStackedLayout(self) self.stack_layout.setContentsMargins(0, 0, 0, 0) self.stack_layout.setSpacing(0) self.completion_list = QListWidget() self.completion_list.setMinimumHeight(200) self.completion_list.setAlternatingRowColors(True) self._list_index = self.stack_layout.addWidget(self.completion_list) self._icons = { "a": resources.IMAGES["attribute"], "f": resources.IMAGES["function"], "c": resources.IMAGES["class"], } self.cc = code_completion.CodeCompletion() self._completion_results = [] self._prefix = u"" self.setVisible(False) self.source = "" self._key_operations = { Qt.Key_Up: self._select_previous_row, Qt.Key_Down: self._select_next_row, Qt.Key_PageUp: (lambda: self._select_previous_row(6)), Qt.Key_PageDown: (lambda: self._select_next_row(6)), Qt.Key_Right: lambda: None, Qt.Key_Left: lambda: None, Qt.Key_Enter: self.pre_key_insert_completion, Qt.Key_Return: self.pre_key_insert_completion, Qt.Key_Tab: self.pre_key_insert_completion, Qt.Key_Space: self.hide_completer, Qt.Key_Escape: self.hide_completer, Qt.Key_Backtab: self.hide_completer, Qt.NoModifier: self.hide_completer, Qt.ShiftModifier: self.hide_completer, } desktop = QApplication.instance().desktop() self._desktop_geometry = desktop.availableGeometry() self.connect(self._editor.document(), SIGNAL("blockCountChanged(int)"), self.update_metadata) def _select_next_row(self, move=1): new_row = self.completion_list.currentRow() + move if new_row < self.completion_list.count(): self.completion_list.setCurrentRow(new_row) else: self.completion_list.setCurrentRow(0) return True def _select_previous_row(self, move=1): new_row = self.completion_list.currentRow() - move if new_row >= 0: self.completion_list.setCurrentRow(new_row) else: self.completion_list.setCurrentRow(self.completion_list.count() - move) return True def update_metadata(self): source = self._editor.get_text() source = source.encode(self._editor.encoding) self.cc.analyze_file("", source) def insert_completion(self, insert): if insert != self._prefix: extra = len(self._prefix) - len(insert) self._editor.textCursor().insertText(insert[extra:]) self.hide_completer() def _get_geometry(self): cr = self._editor.cursorRect() point = self._editor.mapToGlobal(cr.topLeft()) cr.moveTopLeft(point) # Check new position according desktop geometry width = ( self.completion_list.sizeHintForColumn(0) + self.completion_list.verticalScrollBar().sizeHint().width() + 10 ) height = 200 orientation = (point.y() + height) < self._desktop_geometry.height() if orientation: cr.moveTop(cr.bottom()) cr.setWidth(width) cr.setHeight(height) if not orientation: cr.moveBottom(cr.top()) xpos = self._desktop_geometry.width() - (point.x() + width) if xpos < 0: cr.moveLeft(cr.left() + xpos) return cr def complete(self, results): self.add_list_items(results) self.completion_list.setCurrentRow(0) cr = self._get_geometry() self.setGeometry(cr) self.completion_list.updateGeometries() self.show() def add_list_items(self, proposals): self.completion_list.clear() for p in proposals: self.completion_list.addItem( QListWidgetItem(QIcon(self._icons.get(p[0], resources.IMAGES["attribute"])), p[1]) ) def set_completion_prefix(self, prefix): self._prefix = prefix proposals = [] proposals += [("c", item) for item in self.completion_results.get("classes", []) if item.startswith(prefix)] proposals += [("a", item) for item in self.completion_results.get("attributes", []) if item.startswith(prefix)] proposals += [("f", item) for item in self.completion_results.get("functions", []) if item.startswith(prefix)] if proposals: self.complete(proposals) else: self.hide_completer() def fill_completer(self): source = self._editor.get_text() source = source.encode(self._editor.encoding) offset = self._editor.textCursor().position() results = self.cc.get_completion(source, offset) self.completion_results = results prefix = self._editor._text_under_cursor() self.set_completion_prefix(prefix) def hide_completer(self): self._prefix = "" self.hide() def pre_key_insert_completion(self): insert = unicode(self.completion_list.currentItem().text()) self.insert_completion(insert) self.hide_completer() return True def process_pre_key_event(self, event): if not self.isVisible(): return False skip = self._key_operations.get(event.key(), lambda: False)() self._key_operations.get(event.modifiers(), lambda: False)() if skip is None: skip = False return skip def process_post_key_event(self, event): if not settings.CODE_COMPLETION or self._editor.lang != "python": return if self.isVisible(): source = self._editor.get_text() source = source.encode(self._editor.encoding) offset = self._editor.textCursor().position() prefix = self.cc.get_prefix(source, offset) self.set_completion_prefix(prefix) self.completion_list.setCurrentRow(0) if event.key() == Qt.Key_Period or (event.key() == Qt.Key_Space and event.modifiers() == Qt.ControlModifier): self.fill_completer()
class Ui_option(object): def createLine(self): line = QFrame() line.setFrameShape(QFrame.HLine) line.setFrameShadow(QFrame.Sunken) return line def createSquareLabel(self): label = QLabel() label.setEnabled(False) label.setFixedSize(24, 24) label.setFrameShape(QFrame.StyledPanel) return label def addVerticalStretch(self, page_layout): vert_spacer = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Expanding) page_layout.addItem(vert_spacer, page_layout.rowCount(), 0, 1, page_layout.columnCount()) def createConnSection(self, page_layout, label, combobox, num_column): conn_layout = QHBoxLayout() conn_layout.setSpacing(5) conn_layout.setContentsMargins(0, 0, 0, 0) conn_layout.addWidget(label) conn_layout.addItem(QSpacerItem(40, 20, QSizePolicy.Fixed, QSizePolicy.Minimum)) conn_layout.addWidget(combobox, 1) page_layout.addLayout(conn_layout, page_layout.rowCount(), 0, 1, num_column) page_layout.addWidget(self.createLine(), page_layout.rowCount(), 0, 1, num_column) vert_spacer = QSpacerItem(20, 20, QSizePolicy.Fixed, QSizePolicy.Fixed) page_layout.addItem(vert_spacer, page_layout.rowCount(), 0, 1, num_column) def createConnPage(self): self.conn_page = QWidget() self.conn_page.setObjectName("conn_page") self.conn_page.setToolTip(QApplication.translate("option", "<b>Add/Modify/Delete a connection for a MUD server.</b>" "<p>Set the IP or hostname and the port of the MUD server.<br/>" "You have to define a connection to use all the functionality " "related (accounts, aliases, macros and triggers).</p>")) page_layout = QGridLayout(self.conn_page) page_layout.setSpacing(7) page_layout.setContentsMargins(10, 20, 0, 10) page_layout.setColumnMinimumWidth(0, 100) self.label_conn = QLabel() self.label_conn.setText(QApplication.translate("option", "Connection")) page_layout.addWidget(self.label_conn, 0, 0) self.list_conn = QComboBox() self.list_conn.addItem(QApplication.translate("option", "Create New")) page_layout.addWidget(self.list_conn, 0, 1, 1, 2) self.label_name_conn = QLabel() self.label_name_conn.setText(QApplication.translate("option", "Name")) page_layout.addWidget(self.label_name_conn, 1, 0) self.name_conn = QLineEdit() page_layout.addWidget(self.name_conn, 1, 1, 1, 2) self.label_host_conn = QLabel() self.label_host_conn.setText(QApplication.translate("option", "Host")) page_layout.addWidget(self.label_host_conn, 2, 0) self.host_conn = QLineEdit() page_layout.addWidget(self.host_conn, 2, 1, 1, 2) self.label_port_conn = QLabel() self.label_port_conn.setText(QApplication.translate("option", "Port")) page_layout.addWidget(self.label_port_conn, 3, 0) page_layout.addItem(QSpacerItem(80, 20), 3, 1) # horizontal spacer self.port_conn = QLineEdit() self.port_conn.setMaxLength(8) page_layout.addWidget(self.port_conn, 3, 2) vert_spacer = QSpacerItem(271,20,QSizePolicy.Minimum,QSizePolicy.Fixed) page_layout.addItem(vert_spacer, 4, 0, 1, 3) buttons_box = QHBoxLayout() buttons_box.setSpacing(5) buttons_box.setContentsMargins(0, 0, 0, 0) self.save_conn = QPushButton() self.save_conn.setFixedHeight(28) self.save_conn.setIcon(QIcon(":/images/button-save.png")) self.save_conn.setText(QApplication.translate("option", "Save")) buttons_box.addWidget(self.save_conn) self.delete_conn = QPushButton() self.delete_conn.setFixedHeight(28) self.delete_conn.setIcon(QIcon(":/images/button-cancel.png")) self.delete_conn.setText(QApplication.translate("option", "Delete")) buttons_box.addWidget(self.delete_conn) page_layout.addLayout(buttons_box, 5, 0, 1, 3, Qt.AlignRight) self.addVerticalStretch(page_layout) return self.conn_page def createAccountPage(self): self.account_page = QWidget() self.account_page.setObjectName("account_page") self.account_page.setToolTip(QApplication.translate("option", "<b>Manage the accounts.</b>" "<p>Set the Save account flag to activate/disactivate the automatic " "saving of the accounts during the connection phase.<br/>After that " "the account has been created, you can use it for auto-login by " "simply selecting the account in the main window.<br/>You can " "also erase an already saved account, or define a custom prompt " "(see the relative help box).</p>")) page_layout = QGridLayout(self.account_page) page_layout.setSpacing(10) page_layout.setContentsMargins(10, 20, 0, 10) page_layout.setColumnMinimumWidth(0, 130) self.save_account = QCheckBox() self.save_account.setText(QApplication.translate("option", "Save accounts")) page_layout.addWidget(self.save_account, 0, 0) self.label_conn_account = QLabel() self.label_conn_account.setText(QApplication.translate("option", "Connection")) self.list_conn_account = QComboBox() self.createConnSection(page_layout, self.label_conn_account, self.list_conn_account, 2) self.label_account_account = QLabel() self.label_account_account.setText(QApplication.translate("option", "Account")) page_layout.addWidget(self.label_account_account, 4, 0) self.list_account = QComboBox() page_layout.addWidget(self.list_account, 4, 1) buttons_box = QHBoxLayout() buttons_box.setSpacing(5) self.change_prompt = QPushButton() self.change_prompt.setEnabled(False) self.change_prompt.setFixedHeight(28) self.change_prompt.setIcon(QIcon(":/images/prompt.png")) self.change_prompt.setText(QApplication.translate("option", "Change Prompt")) buttons_box.addWidget(self.change_prompt) self.delete_account = QPushButton() self.delete_account.setEnabled(False) self.delete_account.setFixedHeight(28) self.delete_account.setIcon(QIcon(":/images/button-cancel.png")) self.delete_account.setText(QApplication.translate("option", "Delete")) buttons_box.addWidget(self.delete_account) page_layout.addLayout(buttons_box, 5, 0, 1, 2, Qt.AlignRight) self.box_prompt = QGroupBox() self.box_prompt.setTitle(QApplication.translate("option", "Prompt")) self.box_prompt.setToolTip(QApplication.translate("option", "<table>" "<tr><td colspan=3><b>Prompt format:</b></td></tr>" "<tr><td>%h</td><td>-></td><td>Current hit points</td></tr>" "<tr><td>%H</td><td>-></td><td>Maximum hit points</td></tr>" "<tr><td>%m</td><td>-></td><td>Current mana</td></tr>" "<tr><td>%M</td><td>-></td><td>Maximum mana</td></tr>" "<tr><td>%v</td><td>-></td><td>Current moves</td></tr>" "<tr><td>%V</td><td>-></td><td>Maximum moves</td></tr>" "<tr><td>*<td>-></td><td>Represent any char, repeated</td></tr>" "<tr><td colspan=2> </td><td>zero or more times</td></tr>" "<tr><td colspan=3> </td></tr>" "</table>" "<table>" "<tr><td><b>Example:</b></td></tr>" "<tr><td>[ %h/%Hhp %m/%Mmn %v/%Vmv *] ></td></tr>" "<tr><td>is a valid representation for:</td></tr>" "<tr><td>[ 111/111hp 100/100mn 500/500mv 1000tnl] ></td></tr>" "</table>")) prompt_layout = QGridLayout(self.box_prompt) prompt_layout.setSpacing(5) prompt_layout.setContentsMargins(5, 5, 5, 5) label_normal = QLabel() label_normal.setText(QApplication.translate("option", "Normal")) prompt_layout.addWidget(label_normal, 0, 0) self.normal_prompt = QLineEdit() prompt_layout.addWidget(self.normal_prompt, 0, 1) label_fight = QLabel() label_fight.setText(QApplication.translate("option", "Fight")) prompt_layout.addWidget(label_fight, 1, 0) self.fight_prompt = QLineEdit() prompt_layout.addWidget(self.fight_prompt, 1, 1) self.save_prompt = QPushButton() self.save_prompt.setFixedHeight(28) self.save_prompt.setIcon(QIcon(":/images/button-save.png")) self.save_prompt.setText(QApplication.translate("option", "Save")) prompt_layout.addWidget(self.save_prompt, 2, 0, 1, 2, Qt.AlignRight) page_layout.addWidget(self.box_prompt, 6, 0, 1, 2) self.addVerticalStretch(page_layout) return self.account_page def createAliasPage(self): self.alias_page = QWidget() self.alias_page.setObjectName("alias_page") self.alias_page.setToolTip(QApplication.translate("option", "<b>Add/Modify/Delete an alias.</b>" "<p>An alias is a textual shortcut that you can use to increase " "the typing speed. <br/>Thus, when you enter the text of the " "label you actually send to the server the text of the body.</p>")) page_layout = QGridLayout(self.alias_page) page_layout.setSpacing(7) page_layout.setContentsMargins(10, 20, 0, 10) page_layout.setColumnMinimumWidth(0, 80) self.label_conn_alias = QLabel() self.label_conn_alias.setText(QApplication.translate("option", "Connection")) self.list_conn_alias = QComboBox() self.createConnSection(page_layout, self.label_conn_alias, self.list_conn_alias, 3) self.label_alias_alias = QLabel() self.label_alias_alias.setText(QApplication.translate("option", "Alias")) page_layout.addWidget(self.label_alias_alias, 3, 0) page_layout.addItem(QSpacerItem(80, 20, QSizePolicy.Fixed, QSizePolicy.Minimum), 3, 1) self.list_alias = QComboBox() self.list_alias.setEnabled(False) page_layout.addWidget(self.list_alias, 3, 2) self.label_label_alias = QLabel() self.label_label_alias.setText(QApplication.translate("option", "Label")) page_layout.addWidget(self.label_label_alias, 4, 0) page_layout.addItem(QSpacerItem(80, 20, QSizePolicy.Fixed, QSizePolicy.Minimum), 4, 1) self.label_alias = QLineEdit() self.label_alias.setEnabled(False) page_layout.addWidget(self.label_alias, 4, 2) self.label_body_alias = QLabel() self.label_body_alias.setText(QApplication.translate("option", "Body")) page_layout.addWidget(self.label_body_alias, 5, 0) self.body_alias = QLineEdit() self.body_alias.setEnabled(False) page_layout.addWidget(self.body_alias, 5, 1, 1, 2) vert_spacer = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Fixed) page_layout.addItem(vert_spacer, 6, 0, 1, 3) buttons_layout = QHBoxLayout() buttons_layout.setSpacing(5) buttons_layout.setContentsMargins(0, 0, 0, 0) self.save_alias = QPushButton() self.save_alias.setFixedHeight(28) self.save_alias.setIcon(QIcon(":/images/button-save.png")) self.save_alias.setText(QApplication.translate("option", "Save")) buttons_layout.addWidget(self.save_alias) self.delete_alias = QPushButton() self.delete_alias.setFixedHeight(28) self.delete_alias.setIcon(QIcon(":/images/button-cancel.png")) self.delete_alias.setText(QApplication.translate("option", "Delete")) buttons_layout.addWidget(self.delete_alias) page_layout.addLayout(buttons_layout, 7, 0, 1, 3, Qt.AlignRight) self.addVerticalStretch(page_layout) return self.alias_page def createMacroPage(self): self.macro_page = QWidget() self.macro_page.setObjectName("macro_page") self.macro_page.setToolTip(QApplication.translate("option", "<b>Add/Modify/Delete a macro.</b>" "<p>A macro is a key-based shortcut to send some text to the server." "<br/>You can define a key (or a combination of keys, likes CTRL+A) " "that if pressed during the game fires the macro, which sends the " "command to the server.</p><p><b>NOTE:</b> You cannot use for a " "macro a key already used for a standard shortcut.</p>")) page_layout = QGridLayout(self.macro_page) page_layout.setSpacing(7) page_layout.setContentsMargins(10, 20, 0, 10) page_layout.setColumnMinimumWidth(0, 80) self.label_conn_macro = QLabel() self.list_conn_macro = QComboBox() self.createConnSection(page_layout, self.label_conn_macro, self.list_conn_macro, 3) self.label_macro_macro = QLabel() page_layout.addWidget(self.label_macro_macro, 3, 0) horiz_spacer = QSpacerItem(20, 20, QSizePolicy.Fixed,QSizePolicy.Minimum) page_layout.addItem(horiz_spacer, 3, 1) self.list_macro = QComboBox() self.list_macro.setEnabled(False) page_layout.addWidget(self.list_macro, 3, 2) self.label_keys_macro = QLabel() page_layout.addWidget(self.label_keys_macro, 4, 0) self.register_macro = QPushButton() self.register_macro.setEnabled(False) self.register_macro.setFixedHeight(28) page_layout.addWidget(self.register_macro, 4, 1) self.keys_macro = QLineEdit() self.keys_macro.setEnabled(False) self.keys_macro.setProperty("highlight_color",QVariant("#C8C8C8")) page_layout.addWidget(self.keys_macro, 4, 2) self.label_command_macro = QLabel() page_layout.addWidget(self.label_command_macro, 5, 0) self.command_macro = QLineEdit() self.command_macro.setEnabled(False) page_layout.addWidget(self.command_macro, 5, 1, 1, 2) vert_spacer = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Fixed) page_layout.addItem(vert_spacer, 6, 0, 1, 3) buttons_layout = QHBoxLayout() buttons_layout.setSpacing(5) buttons_layout.setContentsMargins(0, 0, 0, 0) self.save_macro = QPushButton() self.save_macro.setFixedHeight(28) self.save_macro.setIcon(QIcon(":/images/button-save.png")) buttons_layout.addWidget(self.save_macro) self.delete_macro = QPushButton() self.delete_macro.setFixedHeight(28) self.delete_macro.setIcon(QIcon(":/images/button-cancel.png")) buttons_layout.addWidget(self.delete_macro) page_layout.addLayout(buttons_layout, 7, 0, 1, 3, Qt.AlignRight) self.addVerticalStretch(page_layout) self.label_conn_macro.setText(QApplication.translate("option", "Connection")) self.label_macro_macro.setText(QApplication.translate("option", "Macro")) self.label_keys_macro.setText(QApplication.translate("option", "Keys")) self.label_command_macro.setText(QApplication.translate("option", "Command")) self.register_macro.setText(QApplication.translate("option", "Register")) self.save_macro.setText(QApplication.translate("option", "Save")) self.delete_macro.setText(QApplication.translate("option", "Delete")) return self.macro_page def createKeyPad(self): def createKey(text, size): layout = QVBoxLayout() layout.addStretch(1) label = QLabel(text) label.setAlignment(Qt.AlignHCenter) layout.addWidget(label) line_input = QLineEdit() if size != -1: line_input.setFixedWidth(size) self.keypad_fields[text] = line_input layout.addWidget(line_input) return layout keypad = QWidget() self.keypad_fields = {} layout = QGridLayout(keypad) layout.setHorizontalSpacing(30) layout.setVerticalSpacing(15) layout.setContentsMargins(5, 5, 5, 5) layout.addLayout(createKey('7', 60), 0, 0) layout.addLayout(createKey('8', 60), 0, 1) layout.addLayout(createKey('9', 60), 0, 2) layout.addLayout(createKey('4', 60), 1, 0) layout.addLayout(createKey('5', 60), 1, 1) layout.addLayout(createKey('6', 60), 1, 2) layout.addLayout(createKey('1', 60), 2, 0) layout.addLayout(createKey('2', 60), 2, 1) layout.addLayout(createKey('3', 60), 2, 2) layout.addLayout(createKey('0', -1), 3, 0, 1, 2) layout.addLayout(createKey('.', 60), 3, 2) return keypad def createKeypadPage(self): self.keypad_page = QWidget() self.keypad_page.setObjectName("keypad_page") self.keypad_page.setToolTip(QApplication.translate("option", "<b>Connect the keypad keys with custom actions</b>" "<p>Enter the text in the spaces to connect the correspondent key " "in order to use as a shortcut to send the text to the server.</p>")) page_layout = QGridLayout(self.keypad_page) page_layout.setSpacing(7) page_layout.setContentsMargins(10, 20, 0, 10) page_layout.setColumnMinimumWidth(0, 80) self.label_conn_keypad = QLabel() self.list_conn_keypad = QComboBox() self.createConnSection(page_layout, self.label_conn_keypad, self.list_conn_keypad, 1) page_layout.addWidget(self.createKeyPad(), 3, 0, 1, 1, Qt.AlignRight) self.addVerticalStretch(page_layout) self.save_keypad = QPushButton() self.save_keypad.setFixedHeight(28) self.save_keypad.setIcon(QIcon(":/images/button-save.png")) self.save_keypad.setText(QApplication.translate("option", "Save")) page_layout.addWidget(self.save_keypad, 4, 0, 1, 1, Qt.AlignRight) self.label_conn_keypad.setText(QApplication.translate("option", "Connection")) return self.keypad_page def createTriggerPage(self): self.trigger_page = QWidget() self.trigger_page.setObjectName("trigger_page") self.trigger_page.setToolTip(QApplication.translate("option", "<b>Add/Modify/Delete a trigger.</b>" "<p>A trigger is an event that happen when some text came from " "server.<br/>After has been received a text that match with the " "pattern (see the relative help box), the trigger can send another " "text to the server or highlight the incoming one.</p>")) page_layout = QGridLayout(self.trigger_page) page_layout.setSpacing(7) page_layout.setContentsMargins(10, 20, 0, 10) page_layout.setColumnMinimumWidth(1, 140) self.label_conn_trigger = QLabel() self.list_conn_trigger = QComboBox() self.createConnSection(page_layout, self.label_conn_trigger, self.list_conn_trigger, 2) self.label_trigger = QLabel() page_layout.addWidget(self.label_trigger, 3, 0, 1, 1) self.list_trigger = QComboBox() page_layout.addWidget(self.list_trigger, 3, 1, 1, 1) tooltip_pattern_trigger = QApplication.translate("option", "<table width=\"350\">" "<tr><td colspan=3><b>Pattern special characters:</b></td></tr>" "<tr><td>*</td><td>-></td><td width=\"250\">A sequence of any chars</td></tr>" "<tr><td>?</td><td>-></td><td width=\"250\">Any single character</td></tr>" "<tr><td>%w</td><td>-></td><td width=\"250\">A sequence of alphanumeric chars</td></tr>" "<tr><td>%d</td><td>-></td><td width=\"250\">A sequence of numeric characters</td></tr>" "<tr><td colspan=3>Every time that you use the special chars %w or %d " "you can also put the relative extracted text in the command using the " "sintax %number where number represents the positional order of the " "special char.</td></tr>" "</table><br/>" "<table width=\"350\">" "<tr><td colspan=2><b>Example:</b></td></tr>" "<tr><td>Pattern:</td><td width=\"250\">%w the ogre is fighting against %w</td></tr>" "<tr><td>Command:</td><td width=\"250\">kill %2</td></tr>" "<tr><td colspan=2>The trigger will fire when an ogre will fight " "against an unknown enemy, and as reaction you will fight with the " "ogre against his enemy.</td></tr>" "</table>") self.label_pattern_trigger = QLabel() self.label_pattern_trigger.setToolTip(tooltip_pattern_trigger) page_layout.addWidget(self.label_pattern_trigger, 4, 0, 1, 1) self.pattern_trigger = QLineEdit() self.pattern_trigger.setToolTip(tooltip_pattern_trigger) page_layout.addWidget(self.pattern_trigger, 4, 1, 1, 1) self.case_trigger = QCheckBox() page_layout.addWidget(self.case_trigger, 5, 0, 1, 2, Qt.AlignLeft) self.label_command_trigger = QLabel() self.label_command_trigger.setText(QApplication.translate("option", "Command")) page_layout.addWidget(self.label_command_trigger, 6, 0) self.command_trigger = QLineEdit() page_layout.addWidget(self.command_trigger, 6, 1) self.label_color_trigger = QLabel() self.label_color_trigger.setText(QApplication.translate("option", "Change color to")) page_layout.addWidget(self.label_color_trigger, 7, 0) horiz_spacer = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) page_layout.addItem(horiz_spacer, 7, 1) colors_layout = QHBoxLayout() colors_layout.setSpacing(3) self.text_color_trigger_button = QPushButton() self.text_color_trigger_button.setFixedHeight(28) self.text_color_trigger_button.setIcon(QIcon(":/images/button-color.png")) colors_layout.addWidget(self.text_color_trigger_button) self.text_color_trigger = self.createSquareLabel() colors_layout.addWidget(self.text_color_trigger) colors_spacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) colors_layout.addItem(colors_spacer) self.bg_color_trigger_button = QPushButton() self.bg_color_trigger_button.setFixedHeight(28) self.bg_color_trigger_button.setIcon(QIcon(":/images/button-color.png")) colors_layout.addWidget(self.bg_color_trigger_button) self.bg_color_trigger = self.createSquareLabel() colors_layout.addWidget(self.bg_color_trigger) page_layout.addLayout(colors_layout, 8, 0, 1, 2) horiz_spacer2 = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) page_layout.addItem(horiz_spacer2, 9, 0, 1, 2) buttons_layout = QHBoxLayout() buttons_layout.setSpacing(5) self.save_trigger = QPushButton() self.save_trigger.setFixedHeight(28) self.save_trigger.setIcon(QIcon(":/images/button-save.png")) buttons_layout.addWidget(self.save_trigger) self.delete_trigger = QPushButton() self.delete_trigger.setFixedHeight(28) self.delete_trigger.setIcon(QIcon(":/images/button-cancel.png")) buttons_layout.addWidget(self.delete_trigger) page_layout.addLayout(buttons_layout, 10, 0, 1, 2, Qt.AlignRight) self.label_conn_trigger.setText(QApplication.translate("option", "Connection")) self.label_trigger.setText(QApplication.translate("option", "Trigger")) self.label_pattern_trigger.setText(QApplication.translate("option", "Pattern")) self.case_trigger.setText(QApplication.translate("option", "Ignore case")) self.text_color_trigger_button.setText(QApplication.translate("option", "Text")) self.text_color_trigger.setProperty("label_color", QVariant(True)) self.bg_color_trigger_button.setText(QApplication.translate("option", "Background")) self.bg_color_trigger.setProperty("label_color", QVariant(True)) self.save_trigger.setText(QApplication.translate("option", "Save")) self.delete_trigger.setText(QApplication.translate("option", "Delete")) return self.trigger_page def createPrefPage(self): self.pref_page = QWidget() self.pref_page.setObjectName("pref_page") page_layout = QVBoxLayout(self.pref_page) page_layout.setSpacing(7) page_layout.setContentsMargins(10, 20, 0, 10) textBox = QGroupBox() textBox.setTitle(QApplication.translate("option", "Text inserted")) text_layout = QGridLayout(textBox) text_layout.setSpacing(7) text_layout.setContentsMargins(10, 10, 10, 10) self.echo_color_button = QPushButton() self.echo_color_button.setFixedHeight(28) self.echo_color_button.setIcon(QIcon(":/images/button-color.png")) self.echo_color_button.setText(QApplication.translate("option", "Echo Color")) text_layout.addWidget(self.echo_color_button, 0, 0) self.echo_color = self.createSquareLabel() self.echo_color.setProperty('label_color', QVariant(True)) text_layout.addWidget(self.echo_color, 0, 3) horiz_spacer = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) text_layout.addItem(horiz_spacer, 0, 4) self.label_cmd_separator = QLabel() self.label_cmd_separator.setText(QApplication.translate("option", "Command separator")) text_layout.addWidget(self.label_cmd_separator, 1, 0, 1, 2) self.cmd_separator = QLineEdit() self.cmd_separator.setFixedSize(24, 24) font = QtGui.QFont() font.setWeight(75) font.setBold(True) self.cmd_separator.setFont(font) self.cmd_separator.setMaxLength(1) self.cmd_separator.setAlignment(Qt.AlignCenter) text_layout.addWidget(self.cmd_separator, 1, 3) horiz_spacer2 = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) text_layout.addItem(horiz_spacer2, 1, 4) self.keep_text = QCheckBox() self.keep_text.setText(QApplication.translate("option", "Keep text entered")) text_layout.addWidget(self.keep_text, 2, 0, 1, 4, Qt.AlignLeft) page_layout.addWidget(textBox) generalBox = QGroupBox() generalBox.setTitle(QApplication.translate("option", "General")) general_layout = QVBoxLayout(generalBox) general_layout.setSpacing(7) general_layout.setContentsMargins(10, 10, 10, 10) self.save_log = QCheckBox() self.save_log.setText(QApplication.translate("option", "Save log")) general_layout.addWidget(self.save_log, 0, Qt.AlignLeft) horiz_spacer = QSpacerItem(20, 20, QSizePolicy.Fixed, QSizePolicy.Minimum) general_layout.addItem(horiz_spacer) page_layout.addWidget(generalBox) horiz_spacer2 = QSpacerItem(20, 20, QSizePolicy.Fixed, QSizePolicy.Minimum) page_layout.addItem(horiz_spacer2) self.save_preferences = QPushButton() self.save_preferences.setFixedHeight(28) self.save_preferences.setIcon(QIcon(":/images/button-save.png")) self.save_preferences.setText(QApplication.translate("option", "Save")) page_layout.addWidget(self.save_preferences, 0, Qt.AlignRight) return self.pref_page def populatePages(self): self.page_container.addWidget(self.createConnPage()) self.page_container.addWidget(self.createAccountPage()) self.page_container.addWidget(self.createAliasPage()) self.page_container.addWidget(self.createMacroPage()) self.page_container.addWidget(self.createKeypadPage()) self.page_container.addWidget(self.createTriggerPage()) self.page_container.addWidget(self.createPrefPage()) def createListOption(self): def addItem(label, icon_pixmap, width, height): item = QListWidgetItem(list_option) item.setText(label) item.setTextAlignment(Qt.AlignHCenter) item.setIcon(QIcon(icon_pixmap)) item.setSizeHint(QSize(width, height)) list_option = QListWidget() list_option.setAutoFillBackground(True) list_option.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) list_option.setTextElideMode(Qt.ElideNone) list_option.setMovement(QListView.Static) list_option.setFlow(QListView.TopToBottom) list_option.setProperty("isWrapping", QVariant(False)) list_option.setSpacing(3) list_option.setViewMode(QListView.IconMode) items = [] items.append((QApplication.translate("option", "Connections"), "connections.png")) items.append((QApplication.translate("option", "Accounts"), "accounts.png")) items.append((QApplication.translate("option", "Aliases"), "aliases.png")) items.append((QApplication.translate("option", "Macros"), "macros.png")) items.append((QApplication.translate("option", "Keypad"), "keypad.png")) items.append((QApplication.translate("option", "Triggers"), "triggers.png")) items.append((QApplication.translate("option", "Preferences"), "preferences.png")) max_width = 0 for label, icon_name in items: w = list_option.fontMetrics().boundingRect(label).width() if w > max_width: max_width = w # An empiric method to align element in the center of the QListWidget max_width += 15 total_height = 0 for label, icon_name in items: icon_pixmap = QPixmap(":/images/" + icon_name) height = icon_pixmap.height() + list_option.fontMetrics().height() + 3 total_height += height + 5 addItem(label, icon_pixmap, max_width, height) list_option.setUniformItemSizes(True) list_option.setFixedWidth(max_width + 10) list_option.setMinimumHeight(total_height) return list_option def setupUi(self, option): option.setWindowTitle(QApplication.translate("option", "Option")) main_layout = QGridLayout(option) main_layout.setSpacing(5) main_layout.setContentsMargins(10, 10, 10, 10) main_layout.setColumnStretch(1, 1) self.list_option = self.createListOption() main_layout.addWidget(self.list_option, 0, 0) self.page_container = QStackedLayout() self.page_container.setContentsMargins(0, 0, 0, 0) main_layout.addLayout(self.page_container, 0, 1) self.populatePages() main_layout.addWidget(self.createLine(), 1, 0, 1, 2) close_layout = QHBoxLayout() close_layout.setContentsMargins(0, 0, 5, 0) close_layout.setSpacing(5) close_option = QPushButton() close_option.setText(QApplication.translate("option", "Close")) option.connect(close_option, QtCore.SIGNAL("clicked()"), option.accept) close_layout.addWidget(close_option) main_layout.addLayout(close_layout, 2, 1, 1, 2, Qt.AlignRight) self.list_option.setCurrentRow(0) self.page_container.setCurrentIndex(0) option.setTabOrder(self.list_option, self.list_conn) option.setTabOrder(self.list_conn, self.name_conn) option.setTabOrder(self.name_conn, self.host_conn) option.setTabOrder(self.host_conn, self.port_conn) option.setTabOrder(self.port_conn, self.save_conn) option.setTabOrder(self.save_conn, self.delete_conn) option.setTabOrder(self.delete_conn, self.list_conn_account) option.setTabOrder(self.list_conn_account, self.list_account) option.setTabOrder(self.list_account, self.delete_account) option.setTabOrder(self.delete_account, self.list_conn_alias) option.setTabOrder(self.list_conn_alias, self.list_alias) option.setTabOrder(self.list_alias, self.label_alias) option.setTabOrder(self.label_alias, self.body_alias) option.setTabOrder(self.body_alias, self.save_alias) option.setTabOrder(self.save_alias, self.delete_alias) option.setTabOrder(self.delete_alias, self.list_conn_macro) option.setTabOrder(self.list_conn_macro, self.list_macro) option.setTabOrder(self.list_macro, self.register_macro) option.setTabOrder(self.register_macro, self.keys_macro) option.setTabOrder(self.keys_macro, self.command_macro) option.setTabOrder(self.command_macro, self.save_macro) option.setTabOrder(self.save_macro, self.delete_macro) option.setTabOrder(self.delete_macro, self.echo_color_button) option.setTabOrder(self.echo_color_button, self.save_log)