コード例 #1
0
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)
コード例 #2
0
ファイル: completer_widget.py プロジェクト: badanni/ninja-ide
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)
コード例 #3
0
ファイル: OWFile.py プロジェクト: AutumnLight/orange
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)
コード例 #4
0
ファイル: OWFile.py プロジェクト: rommeljohnsantos/orange
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)
コード例 #5
0
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()
コード例 #6
0
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()
コード例 #7
0
ファイル: gui_option.py プロジェクト: develersrl/devclient
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>&nbsp;</td><td>zero or more times</td></tr>"
        "<tr><td colspan=3>&nbsp;</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)