Beispiel #1
0
    def __init__(self, parent, project=None):
        QPlainTextEdit.__init__(self)
        EditorGeneric.__init__(self)
        BaseCentralWidget.__init__(self)
        self.parent = parent
        self.completer = Completer(self, project)
        self.setWordWrapMode(QTextOption.NoWrap)
        doc = self.document()
        option = QTextOption()
        option.setFlags(QTextOption.ShowTabsAndSpaces)
        doc.setDefaultTextOption(option)
        self.setDocument(doc)
        self.set_default_font()

        #file modification time POSIX
        self._mtime = None
        #Flag to dont bug the user when answer 'dont show the modification dialog'
        self.ask_if_externally_modified = True

        self.lineNumberArea = self.LineNumberArea(self)
        self.viewport().installEventFilter(self)

        self.highlighter = None
        styles.set_style(self, 'editor')

        self.connect(self, SIGNAL("cursorPositionChanged()"),
                     self.highlight_current_line)
        self.connect(self, SIGNAL("modificationChanged(bool)"),
                     self.modif_changed)
        self.highlight_current_line()
Beispiel #2
0
    def __init__(self, namespace=None):
        if namespace is not None:
            namespace = namespace()

        InteractiveInterpreter.__init__(self, namespace)
        self.output_trap = OutputTrap()
        self.completer = Completer(self.locals)
        self.input_count = 0
        self.interrupted = False
Beispiel #3
0
 def __init__(self, target, mode):
     self.version = '0.0.5'
     self.target = target
     self.mode = mode
     self.xtype = 'bufferoverflow'
     self.offset = 1
     self.nops = 0
     self.shellcode = ''
     self.lenght = 0
     self.addr1 = None
     self.addr2 = None
     self.arch = 'x86'
     self.port = 0
     if self.target:
         self.p1 = Popen(['gdb', "--silent", "{}".format(self.target)],
                         stdin=PIPE,
                         stdout=PIPE,
                         bufsize=1)
         gdbout = self.p1.stdout.readline()
     else:
         self.p1 = Popen(['gdb', '--silent'],
                         stdin=PIPE,
                         stdout=PIPE,
                         bufsize=1)
         #gdbout = self.p1.stdout.readline()
     completer = Completer(".gdb_history", "xploit")
Beispiel #4
0
    def __init__(self, parent, project=None):
        QPlainTextEdit.__init__(self)
        EditorGeneric.__init__(self)
        BaseCentralWidget.__init__(self)
        self.parent = parent
        self.completer = Completer(self, project)
        self.setWordWrapMode(QTextOption.NoWrap)
        doc = self.document()
        option = QTextOption()
        option.setFlags(QTextOption.ShowTabsAndSpaces)
        doc.setDefaultTextOption(option)
        self.setDocument(doc)
        self.set_default_font()

        #file modification time POSIX
        self._mtime = None
        #Flag to dont bug the user when answer 'dont show the modification dialog'
        self.ask_if_externally_modified = True

        self.lineNumberArea = self.LineNumberArea(self)
        self.viewport().installEventFilter(self)

        self.highlighter = None
        styles.set_style(self, 'editor')

        self.connect(self, SIGNAL("cursorPositionChanged()"), self.highlight_current_line)
        self.connect(self, SIGNAL("modificationChanged(bool)"), self.modif_changed)
        self.highlight_current_line()
Beispiel #5
0
def _coll(content, arg):
    """ List all plugin collections. """
    colls = Completer([])._get_collections()
    print('\n')
    for c in colls:
        print('%s\n %s' % ('-' * 40, c))
    print('-' * 40, '\n')
    return content
Beispiel #6
0
  def __init__(self, locals = __builtin__.globals()):
    InteractiveConsole.__init__(self, locals)

    self.stdout = sys.stdout
    self.stderr = sys.stderr
    
    self.pipe = Pipe()
    self.completer = Completer(locals)
Beispiel #7
0
    def __init__(self, namespace=None):
        if namespace is not None:
            namespace = namespace()

        InteractiveInterpreter.__init__(self, namespace)
        self.output_trap = OutputTrap()
        self.completer = Completer(self.locals)
        self.input_count = 0
        self.interrupted = False
Beispiel #8
0
def main():

    print("Running the configurator")
    # required for travis tests
    if len(sys.argv) > 2 and sys.argv[-2] == 'scripts/configurator_tests/':
        sys.argv = [sys.argv[:-2]]

    args = parsers._config_arg_parser()
    if args.error:
        utils.error_level = 1

    print("Starting Savu Config tool (please wait for prompt)")

    _reduce_logging_level()

    content = Content(level="all" if args.disp_all else 'user')

    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        content.failed = utils.populate_plugins(error_mode=args.error,
                                                examples=args.examples)

    comp = Completer(commands=commands, plugin_list=pu.plugins)
    utils._set_readline(comp.complete)

    # if file flag is passed then open it here
    if args.file:
        commands['open'](content, args.file)

    print("\n*** Press Enter for a list of available commands. ***\n")

    utils.load_history_file(utils.histfile)

    while True:
        try:
            in_list = raw_input(">>> ").strip().split(' ', 1)
        except KeyboardInterrupt:
            print()
            continue

        command, arg = in_list if len(in_list) == 2 else in_list + ['']
        command = command if command else 'help'
        if command not in commands:
            print("I'm sorry, that's not a command I recognise. Press Enter "
                  "for a list of available commands.")
        else:
            content = commands[command](content, arg)

        if content.is_finished():
            break

    print("Thanks for using the application")
Beispiel #9
0
def main():
    """ 
         Start the Slack Client 
    """
    os.system("clear; figlet 'Slack Gitsin' | lolcat")
    history = FileHistory(os.path.expanduser("~/.slackHistory"))
    while True:
        text = prompt("slack> ", history=history,
                      auto_suggest=AutoSuggestFromHistory(),
                      on_abort=AbortAction.RETRY,
                      style=DocumentStyle,
                      completer=Completer(fuzzy_match=False,
                                          text_utils=TextUtils()),
                      complete_while_typing=Always(),
                      get_bottom_toolbar_tokens=get_bottom_toolbar_tokens,
                      key_bindings_registry=manager.registry,
                      accept_action=AcceptAction.RETURN_DOCUMENT
        )
        slack = Slack(text)
        slack.run_command()
Beispiel #10
0
def main():

    # required for travis tests
    if len(sys.argv) > 2 and sys.argv[-2] == 'scripts/configurator_tests/':
        sys.argv = [sys.argv[:-2]]

    args = parsers._config_arg_parser()
    if args.error:
        utils.error_level = 1

    print("Starting Savu Config tool (please wait for prompt)")

    utils.populate_plugins()
    comp = Completer(commands=commands, plugin_list=pu.plugins)
    utils._set_readline(comp.complete)

    content = Content(level="all" if args.disp_all else 'user')

    # if file flag is passed then open it here
    if args.file:
        commands['open'](content, args.file)

    print("\n*** Press Enter for a list of available commands. ***\n")

    while True:
        in_list = raw_input(">>> ").strip().split(' ', 1)
        command, arg = in_list if len(in_list) is 2 else in_list + ['']
        command = command if command else 'help'
        if command not in commands:
            print("I'm sorry, that's not a command I recognise. Press Enter "
                  "for a list of available commands.")
        else:
            content = commands[command](content, arg)

        if content.is_finished():
            break

        # write the history to the history file
        utils.readline.write_history_file(utils.histfile)

    print("Thanks for using the application")
Beispiel #11
0
def play_next():
    if __last_played:
        keys = COUBS.keys()
        i = keys.index(__last_played)
        if i < len(COUBS) - 1:
            play(COUBS[keys[i + 1]]['permalink'])
        else:
            play(COUBS[keys[0]]['permalink'])
    elif len(COUBS) > 0:
        play(COUBS.itervalues().next()['permalink'])
    else:
        print 'nothing to play, get some coubs using get command'


if __name__ == '__main__':
    readline.set_completer(Completer(__autocomplete_dict).complete)
    if sys.platform == 'darwin':
        readline.parse_and_bind('bind ^I rl_complete')
    else:
        readline.parse_and_bind('tab: complete')

    print """
Howdy!
Start with \"get newest\" command and \"play\" some coubs, e.g. \"play 2vf1v\". To quit player screen press \"q\".
Btw, autocomplete activated.
"""

    while True:
        x = raw_input('> ')

        if x.startswith('get hot'):
Beispiel #12
0
class Interpreter(InteractiveInterpreter):

    def __init__(self, namespace=None):
        if namespace is not None:
            namespace = namespace()

        InteractiveInterpreter.__init__(self, namespace)
        self.output_trap = OutputTrap()
        self.completer = Completer(self.locals)
        self.input_count = 0
        self.interrupted = False

    def evaluate(self, input_string):
        """give the input_string to the python interpreter in the
        usernamespace"""
        self.output_trap.set()
        command_count = self._runcommands(input_string)
        stdout, stderr = self.output_trap.get_values()
        self.output_trap.reset()
        self.input_count += 1
        result = protocol.result_dict(input_string, stdout, 
                    in_count=self.input_count, 
                    cmd_count=command_count, err=stderr)
        return result

    def introspect(self, input_string):
        """See what information there is about this objects methods and
        attributes."""
        info = introspect(input_string)

    def complete(self, input_string):
        """
        Complete a name or attribute.
        """
        reName = "([a-zA-Z_][a-zA-Z_0-9]*)$"
        reAttribute = "([a-zA-Z_][a-zA-Z_0-9]*[.]+[a-zA-Z_.0-9]*)$"
        nameMatch = re.match(reName, input_string)
        attMatch = re.match(reAttribute, input_string)
        if nameMatch:
            matches = self.completer.global_matches(input_string)
            return {'out':matches}
        if attMatch:
            matches = self.completer.attr_matches(input_string)
            return {'out':matches}
        return {'out':[]}



    def complete_name(self, input_string):
        """See what possible completions there are for this object
        (input_string)."""
        matches = self.completer.global_matches(input_string)
        # return ' '.join(matches)
        return matches

    def complete_attr(self, input_string):

        matches = self.completer.attr_matches(input_string)
        return matches


    # 
    #-----------------------------------------------

    def _runcommands(self, input_string):
        """input_string could contain multiple lines, multiple commands, or
        multiple multiline commands. This method builds a compiled command
        line by line until a complete command has been compiled. Once it
        has a complete command, it execs it in the username space and the
        output is stored in the output trap. There may be more than one
        command; the number of complete commands is counted
        (Based off of ipython1.core.shell.InteractiveShell._runlines)"""

        command_buffer = []
        command_count = 0

        if self.interrupted:
            print>>sys.stderr, 'Aborted.'
            #sys.stderr.write('Aborted')
            return command_count
        lines = input_string.split('\n')
        lines = [l for l in lines if len(l) > 0]
        more = False
        for line in lines:
            line = self._pre_execute_filter(line)
            command_buffer.append(line)
            if line or more:
                torun = '\n'.join(command_buffer)
                try:
                    more = self.runsource(torun, symbol='exec')
                except OperationAborted, e:
                    print>>sys.stderr, e.value
                    #sys.stderr.write(e.value)
                    # XXX This could be bad if something other than the
                    # kernelConnection triggers an interrupt
                    #self.interrupted = True
                    return command_count
            if more:
                pass
            else:
                command_buffer = []
                command_count += 1
                more = False
        if more:
            command_buffer.append('\n')
            torun = '\n'.join(command_buffer)
            more = self.runsource(torun)
        return command_count
Beispiel #13
0
class Tab(QWidget):
    """Tab in the QTableWidget where user executes query and sees the result."""

    # ----------------------------------------------------------------------
    def __init__(self):
        """Initialize Tab with layout and behavior."""
        super(Tab, self).__init__()

        # regex pattern for SQL query block comments
        self.block_comment_re = re.compile(
            r'(^)?[^\S\n]*/(?:\*(.*?)\*/[^\S\n]*|/[^\n]*)($)?',
            re.DOTALL | re.MULTILINE)

        main_layout = QVBoxLayout(self)

        # define gdb props
        self.gdb = None
        self.gdb_items = None
        self.gdb_columns_names = None
        self.gdb_schemas = None

        # connected geodatabase path toolbar
        self.connected_gdb_path_label = QLabel('')
        self.connected_gdb_path_label.setTextInteractionFlags(
            Qt.TextSelectableByMouse)
        self.connected_gdb_path_label.setToolTip(
            'Connected geodatabase that queries will be run against')
        self.connected_gdb_path_label.setText(not_connected_to_gdb_message)

        self.browse_to_gdb = QPushButton('Browse')
        self.browse_to_gdb.setShortcut(QKeySequence('Ctrl+B'))
        self.browse_to_gdb.clicked.connect(
            lambda evt, arg=True: self.connect_to_geodatabase(
                evt, triggered_with_browse=True))

        self.gdb_sql_dialect_combobox = QComboBox()
        for dialect in sql_dialects_names:
            self.gdb_sql_dialect_combobox.addItem(dialect)

        self.gdb_browse_toolbar = QToolBar()
        self.gdb_browse_toolbar.setMaximumHeight(50)
        self.gdb_browse_toolbar.addWidget(self.browse_to_gdb)
        self.gdb_browse_toolbar.addWidget(self.connected_gdb_path_label)
        self.gdb_browse_toolbar.addSeparator()
        self.gdb_browse_toolbar.addWidget(self.gdb_sql_dialect_combobox)

        # table with results
        self.table = ResultTable()

        # execute SQL query
        self.execute = QAction('Execute', self)
        self.execute.setShortcuts(
            [QKeySequence('F5'),
             QKeySequence('Ctrl+Return')])
        self.execute.triggered.connect(self.run_query)
        self.addAction(self.execute)

        # enter a SQL query
        self.query = TextEditor()
        self.query.setPlainText('')
        font = self.query.font()
        font.setFamily('Consolas')
        font.setStyleHint(QFont.Monospace)

        # TODO: add line numbers to the text editor
        font.setPointSize(14)
        self.query.setFont(font)
        self.query.setTabStopWidth(20)
        self.highlighter = Highlighter(self.query.document())

        # TODO select block of text - Ctrl+/ and they become comments
        self.completer = Completer()
        self.query.set_completer(self.completer.completer)

        # errors panel to show if query fails to execute properly
        self.errors_panel = QPlainTextEdit()
        font = self.query.font()
        font.setPointSize(12)
        self.errors_panel.setStyleSheet('color:red')
        self.errors_panel.setFont(font)
        self.errors_panel.hide()

        # splitter between the toolbar, query window, and the result set table
        splitter = QSplitter(Qt.Vertical)
        splitter.addWidget(self.gdb_browse_toolbar)
        splitter.addWidget(self.query)
        splitter.addWidget(self.table)
        splitter.addWidget(self.errors_panel)

        # add the settings after the widget have been added
        splitter.setCollapsible(0, True)
        splitter.setCollapsible(1, False)
        splitter.setCollapsible(2, False)
        splitter.setCollapsible(3, False)
        splitter.setStretchFactor(0, 3)
        splitter.setStretchFactor(1, 7)
        splitter.setSizes((100, 200, 300))
        self.table.hide()

        # TOC
        self.toc = QTreeWidget()
        self.toc.setHeaderHidden(True)

        # second splitter between the TOC to the left and the query/table to the
        # right
        toc_splitter = QSplitter(Qt.Horizontal)
        toc_splitter.addWidget(self.toc)
        toc_splitter.addWidget(splitter)
        toc_splitter.setCollapsible(0, True)
        toc_splitter.setSizes((200, 800))  # set the TOC vs data panel

        main_layout.addWidget(toc_splitter)

        margins = QMargins()
        margins.setBottom(10)
        margins.setLeft(10)
        margins.setRight(10)
        margins.setTop(10)
        main_layout.setContentsMargins(margins)

        self.setLayout(main_layout)
        QApplication.setStyle(QStyleFactory.create('Cleanlooks'))
        self.show()

        return

    # ----------------------------------------------------------------------
    def connect_to_geodatabase(self, evt, triggered_with_browse=True):
        """Connect to geodatabase by letting user browse to a gdb folder."""
        if triggered_with_browse:
            gdb_connect_dialog = QFileDialog(self)
            gdb_connect_dialog.setFileMode(QFileDialog.Directory)
            gdb_path = gdb_connect_dialog.getExistingDirectory()

            # TODO: add a filter to show only .gdb folders?
            # https://stackoverflow.com/questions/4893122/filtering-in-qfiledialog
            if gdb_path and gdb_path.endswith('.gdb'):
                self.gdb = Geodatabase(gdb_path)
                if self.gdb.is_valid():
                    self.connected_gdb_path_label.setText(self.gdb.path)
                    self._set_gdb_items_highlight()
                    self._set_gdb_items_complete()
                    self._fill_toc()
                else:
                    msg = QMessageBox()
                    msg.setText('This is not a valid file geodatabase')
                    msg.setWindowTitle('Validation error')
                    msg.setStandardButtons(QMessageBox.Ok)
                    msg.exec_()
        else:
            if self.gdb.is_valid():
                self._set_gdb_items_highlight()
                self._set_gdb_items_complete()

        return

    # ----------------------------------------------------------------------
    def wheelEvent(self, event):  # noqa: N802
        """Override built-in method to handle mouse wheel scrolling.

        Necessary to do when the tab is focused.
        """
        modifiers = QApplication.keyboardModifiers()
        if modifiers == Qt.ControlModifier:
            if event.angleDelta().y() > 0:  # scroll forward
                self.query.zoomIn(1)
            else:
                self.query.zoomOut(1)
        return

    # ----------------------------------------------------------------------
    def run_query(self):
        """Run SQL query and draw the record set and call table drawing."""
        if not self.gdb:
            self.print_sql_execute_errors(not_connected_to_gdb_message)
            return
        try:
            if not self.gdb.is_valid():
                return

            # use the text of what user selected, if none -> need to run the
            # whole query
            part_sql_query = self.query.textCursor().selection().toPlainText()

            if part_sql_query:
                sql_query = part_sql_query
            else:
                sql_query = self.query.toPlainText()

            if sql_query:
                # removing block comments and single line comments
                sql_query = self.block_comment_re.sub(
                    self._strip_block_comments, sql_query)
                sql_query = self._strip_single_comments(sql_query)
            else:
                return

            # TODO: add threading to allow user to cancel a long running query
            QApplication.setOverrideCursor(Qt.WaitCursor)
            start_time = time.time()
            self.gdb.open_connection()
            res, errors = self.gdb.execute_sql(
                sql_query, self.gdb_sql_dialect_combobox.currentText())
            end_time = time.time()
            if errors:
                self.print_sql_execute_errors(errors)

            if res:
                self.table.show()
                self.errors_panel.hide()
                self.draw_result_table(res)
                msg = 'Executed in {exec_time:.1f} secs | {rows} rows'.format(
                    exec_time=end_time - start_time,
                    rows=self.table.table_data.number_layer_rows)
                self.update_app_status_bar(msg)

        except Exception as err:
            print(err)
        finally:
            QApplication.restoreOverrideCursor()
        return

    # ----------------------------------------------------------------------
    def result_should_include_geometry(self):
        """Get the setting defining whether to include the geometry column."""
        try:
            return self.parentWidget().parentWidget().parentWidget(
            ).do_include_geometry.isChecked()
        except Exception:
            return True

    # ----------------------------------------------------------------------
    def update_app_status_bar(self, message):
        """Update app status bar with the execution result details."""
        try:
            self.parentWidget().parentWidget().parentWidget().statusBar(
            ).showMessage(message)
        except Exception:
            pass
        return

    # ----------------------------------------------------------------------
    def draw_result_table(self, res):
        """Draw table with the record set received from the geodatabase."""
        geom_col_name = res.GetGeometryColumn(
        )  # shape col was in the sql query
        self.geometry_isin_query = bool(geom_col_name)

        self.table.draw_result(res,
                               show_shapes=bool(
                                   self.result_should_include_geometry()))
        self.table.view.resizeColumnsToContents()
        return

    # ----------------------------------------------------------------------
    def print_sql_execute_errors(self, err):
        """Print to a special panel errors that occurred during execution."""
        self.table.hide()
        self.errors_panel.show()
        self.errors_panel.setPlainText(err)
        return

    # ----------------------------------------------------------------------
    def _set_gdb_items_highlight(self):
        """Set completer and highlight properties for geodatabase items."""
        self.gdb_items = self.gdb.get_items()
        self.highlighter.set_highlight_rules_gdb_items(self.gdb_items, 'Table')

        self.gdb_schemas = self.gdb.get_schemas()
        self.gdb_columns_names = sorted(list(
            set(
                itertools.chain.from_iterable(
                    [i.keys() for i in self.gdb_schemas.values()]))),
                                        key=lambda x: x.lower())

    # ----------------------------------------------------------------------
    def _set_gdb_items_complete(self):
        """Update completer rules to include geodatabase items."""
        self.completer.update_completer_string_list(self.gdb_items +
                                                    self.gdb_columns_names)
        self.highlighter.set_highlight_rules_gdb_items(self.gdb_columns_names,
                                                       'Column')
        return

    # ----------------------------------------------------------------------
    def _fill_toc(self):
        """Fill TOC with geodatabase datasets and columns."""
        self.toc.clear()
        if not self.gdb_items:
            return

        for tbl_name in sorted(self.gdb_items, key=lambda i: i.lower()):
            if tbl_name.islower() or tbl_name.isupper():
                item = QTreeWidgetItem([tbl_name.title()])
            else:
                item = QTreeWidgetItem([tbl_name])
            font = QFont()
            font.setBold(True)
            item.setFont(0, font)

            for col_name, col_type in sorted(
                    self.gdb_schemas[tbl_name].items()):
                if col_name.islower() or col_name.isupper():
                    col_name = col_name.title()

                item_child = QTreeWidgetItem(
                    ['{0} ({1})'.format(col_name, col_type)])
                item.addChild(item_child)
            self.toc.addTopLevelItem(item)
        return

    # ----------------------------------------------------------------------
    def _do_toc_hide_show(self):
        """Hide TOC with tables and columns."""
        if self.toc.isVisible():
            self.toc.setVisible(False)
        else:
            self.toc.setVisible(True)
        return

    # ----------------------------------------------------------------------
    def _strip_block_comments(self, sql_query):
        """Strip the block comments in SQL query."""
        start, mid, end = sql_query.group(1, 2, 3)
        if mid is None:
            # this is a single-line comment
            return ''
        elif start is not None or end is not None:
            # this is a multi-line comment at start/end of a line
            return ''
        elif '\n' in mid:
            # this is a multi-line comment with line break
            return '\n'
        else:
            # this is a multi-line comment without line break
            return ' '

    # ----------------------------------------------------------------------
    def _strip_single_comments(self, sql_query):
        """Strip the single line comments in SQL query."""
        clean_query = []
        for line in sql_query.rstrip().split('\n'):
            clean_line = line.split('--')[0]
            if clean_line:
                clean_query.append(clean_line)
        return ' '.join([line for line in clean_query])
Beispiel #14
0
    def __init__(self):
        """Initialize Tab with layout and behavior."""
        super(Tab, self).__init__()

        # regex pattern for SQL query block comments
        self.block_comment_re = re.compile(
            r'(^)?[^\S\n]*/(?:\*(.*?)\*/[^\S\n]*|/[^\n]*)($)?',
            re.DOTALL | re.MULTILINE)

        main_layout = QVBoxLayout(self)

        # define gdb props
        self.gdb = None
        self.gdb_items = None
        self.gdb_columns_names = None
        self.gdb_schemas = None

        # connected geodatabase path toolbar
        self.connected_gdb_path_label = QLabel('')
        self.connected_gdb_path_label.setTextInteractionFlags(
            Qt.TextSelectableByMouse)
        self.connected_gdb_path_label.setToolTip(
            'Connected geodatabase that queries will be run against')
        self.connected_gdb_path_label.setText(not_connected_to_gdb_message)

        self.browse_to_gdb = QPushButton('Browse')
        self.browse_to_gdb.setShortcut(QKeySequence('Ctrl+B'))
        self.browse_to_gdb.clicked.connect(
            lambda evt, arg=True: self.connect_to_geodatabase(
                evt, triggered_with_browse=True))

        self.gdb_sql_dialect_combobox = QComboBox()
        for dialect in sql_dialects_names:
            self.gdb_sql_dialect_combobox.addItem(dialect)

        self.gdb_browse_toolbar = QToolBar()
        self.gdb_browse_toolbar.setMaximumHeight(50)
        self.gdb_browse_toolbar.addWidget(self.browse_to_gdb)
        self.gdb_browse_toolbar.addWidget(self.connected_gdb_path_label)
        self.gdb_browse_toolbar.addSeparator()
        self.gdb_browse_toolbar.addWidget(self.gdb_sql_dialect_combobox)

        # table with results
        self.table = ResultTable()

        # execute SQL query
        self.execute = QAction('Execute', self)
        self.execute.setShortcuts(
            [QKeySequence('F5'),
             QKeySequence('Ctrl+Return')])
        self.execute.triggered.connect(self.run_query)
        self.addAction(self.execute)

        # enter a SQL query
        self.query = TextEditor()
        self.query.setPlainText('')
        font = self.query.font()
        font.setFamily('Consolas')
        font.setStyleHint(QFont.Monospace)

        # TODO: add line numbers to the text editor
        font.setPointSize(14)
        self.query.setFont(font)
        self.query.setTabStopWidth(20)
        self.highlighter = Highlighter(self.query.document())

        # TODO select block of text - Ctrl+/ and they become comments
        self.completer = Completer()
        self.query.set_completer(self.completer.completer)

        # errors panel to show if query fails to execute properly
        self.errors_panel = QPlainTextEdit()
        font = self.query.font()
        font.setPointSize(12)
        self.errors_panel.setStyleSheet('color:red')
        self.errors_panel.setFont(font)
        self.errors_panel.hide()

        # splitter between the toolbar, query window, and the result set table
        splitter = QSplitter(Qt.Vertical)
        splitter.addWidget(self.gdb_browse_toolbar)
        splitter.addWidget(self.query)
        splitter.addWidget(self.table)
        splitter.addWidget(self.errors_panel)

        # add the settings after the widget have been added
        splitter.setCollapsible(0, True)
        splitter.setCollapsible(1, False)
        splitter.setCollapsible(2, False)
        splitter.setCollapsible(3, False)
        splitter.setStretchFactor(0, 3)
        splitter.setStretchFactor(1, 7)
        splitter.setSizes((100, 200, 300))
        self.table.hide()

        # TOC
        self.toc = QTreeWidget()
        self.toc.setHeaderHidden(True)

        # second splitter between the TOC to the left and the query/table to the
        # right
        toc_splitter = QSplitter(Qt.Horizontal)
        toc_splitter.addWidget(self.toc)
        toc_splitter.addWidget(splitter)
        toc_splitter.setCollapsible(0, True)
        toc_splitter.setSizes((200, 800))  # set the TOC vs data panel

        main_layout.addWidget(toc_splitter)

        margins = QMargins()
        margins.setBottom(10)
        margins.setLeft(10)
        margins.setRight(10)
        margins.setTop(10)
        main_layout.setContentsMargins(margins)

        self.setLayout(main_layout)
        QApplication.setStyle(QStyleFactory.create('Cleanlooks'))
        self.show()

        return
Beispiel #15
0
class Editor(QPlainTextEdit, EditorGeneric, BaseCentralWidget):

    def __init__(self, parent, project=None):
        QPlainTextEdit.__init__(self)
        EditorGeneric.__init__(self)
        BaseCentralWidget.__init__(self)
        self.parent = parent
        self.completer = Completer(self, project)
        self.setWordWrapMode(QTextOption.NoWrap)
        doc = self.document()
        option = QTextOption()
        option.setFlags(QTextOption.ShowTabsAndSpaces)
        doc.setDefaultTextOption(option)
        self.setDocument(doc)
        self.set_default_font()

        #file modification time POSIX
        self._mtime = None
        #Flag to dont bug the user when answer 'dont show the modification dialog'
        self.ask_if_externally_modified = True

        self.lineNumberArea = self.LineNumberArea(self)
        self.viewport().installEventFilter(self)

        self.highlighter = None
        styles.set_style(self, 'editor')

        self.connect(self, SIGNAL("cursorPositionChanged()"), self.highlight_current_line)
        self.connect(self, SIGNAL("modificationChanged(bool)"), self.modif_changed)
        self.highlight_current_line()

    def set_path(self, fileName):
        super(Editor, self).set_path(fileName)
        self.newDocument = False
        self._mtime = manage_files.get_last_modification(fileName)

    def check_external_modification(self):
        if self.newDocument:
            return False
        #Saved document we can ask for modification!
        return manage_files.check_for_external_modification(self.path, self._mtime)

    def has_write_permission(self):
        if self.newDocument:
            return True
        return manage_files.has_write_prmission(self.path)

    def register_syntax(self, fileName):
        ext = manage_files.get_file_extension(fileName)[1:]
        if self.highlighter is not None and \
            not self.path.endswith(ext):
            self.highlighter.deleteLater()
        if not self.path.endswith(ext):
            if ext in loader.extensions:
                self.highlighter = Highlighter(self.document(),
                    loader.extensions.get(ext, 'py'))
            else:
                try:
                    self.highlighter = HighlighterPygments(self.document(), fileName)
                except:
                    print 'There is no lexer for this file'
            #for apply rehighlighting (rehighlighting form highlighter not responding)
            self.firstVisibleBlock().document().find('\n').insertText('')

    def set_font(self, font):
        self.document().setDefaultFont(font)
        self.font_family = str(font.family())
        self.font_size = font.pointSize()
        self.parent.notify_font_change()

    def set_default_font(self):
        #Set Font and FontSize
        font = QFont(self.font_family, self.font_size)
        self.document().setDefaultFont(font)

    def get_font(self):
        return self.document().defaultFont()

    def get_text(self):
        return self.toPlainText()

    def modif_changed(self, val):
        if self.parent is not None:
            self.parent.mark_as_changed(val)

    def zoom_in(self):
        font = self.font()
        size = font.pointSize()
        if size < self.font_max_size:
            size += 2
            font.setPointSize(size)
        self.setFont(font)

    def zoom_out(self):
        font = self.font()
        size = font.pointSize()
        if size > self.font_min_size:
            size -= 2
            font.setPointSize(size)
        self.setFont(font)

    def comment(self):
        lang = manage_files.get_file_extension(self.get_path())[1:]
        key = loader.extensions.get(lang, 'python')
        comment_wildcard = loader.syntax[key]['comment'][0]
        
        #cursor is a COPY all changes do not affect the QPlainTextEdit's cursor!!!
        cursor = self.textCursor()
        start = self.document().findBlock(cursor.selectionStart()).firstLineNumber()
        end = self.document().findBlock(cursor.selectionEnd()).firstLineNumber()
        startPosition = self.document().findBlockByLineNumber(start).position()
        
        #Start a undo block
        cursor.beginEditBlock()
        
        #Move the COPY cursor
        cursor.setPosition(startPosition)
        #Move the QPlainTextEdit Cursor where the COPY cursor IS!
        self.setTextCursor(cursor)
        self.moveCursor(QTextCursor.StartOfLine)
        self.moveCursor(QTextCursor.Right, QTextCursor.KeepAnchor)
        text = self.textCursor().selectedText()
        if text == comment_wildcard:
            cursor.endEditBlock()
            self.uncomment(start, end, startPosition)
            return
        else:
            self.moveCursor(QTextCursor.StartOfLine)
        for i in xrange(start, end+1):
            self.textCursor().insertText(comment_wildcard)
            self.moveCursor(QTextCursor.Down)
            self.moveCursor(QTextCursor.StartOfLine)
        
        #End a undo block
        cursor.endEditBlock()

    def uncomment(self, start=-1, end=-1, startPosition=-1):
        lang = manage_files.get_file_extension(self.get_path())[1:]
        key = loader.extensions.get(lang, 'python')
        comment_wildcard = loader.syntax[key]['comment'][0]

        #cursor is a COPY all changes do not affect the QPlainTextEdit's cursor!!!
        cursor = self.textCursor()
        if start == -1 and end == -1 and startPosition == -1:
            start = self.document().findBlock(cursor.selectionStart()).firstLineNumber()
            end = self.document().findBlock(cursor.selectionEnd()).firstLineNumber()
            startPosition = self.document().findBlockByLineNumber(start).position()
        
        #Start a undo block
        cursor.beginEditBlock()
        
        #Move the COPY cursor
        cursor.setPosition(startPosition)
        #Move the QPlainTextEdit Cursor where the COPY cursor IS!
        self.setTextCursor(cursor)
        self.moveCursor(QTextCursor.StartOfLine)
        for i in xrange(start, end+1):
            self.moveCursor(QTextCursor.Right, QTextCursor.KeepAnchor)
            text = self.textCursor().selectedText()
            if text == comment_wildcard:
                self.textCursor().removeSelectedText()
            elif u'\u2029' in text:
                #\u2029 is the unicode char for \n
                #if there is a newline, rollback the selection made above.
                self.moveCursor(QTextCursor.Left, QTextCursor.KeepAnchor)
            
            self.moveCursor(QTextCursor.Down)
            self.moveCursor(QTextCursor.StartOfLine)
        
        #End a undo block
        cursor.endEditBlock()

    def insert_horizontal_line(self):
        self.moveCursor(QTextCursor.StartOfLine, QTextCursor.KeepAnchor)
        text = unicode(self.textCursor().selection().toPlainText())
        self.moveCursor(QTextCursor.EndOfLine, QTextCursor.MoveAnchor)
        comment = '#' * (80 - len(text))
        self.textCursor().insertText(comment)

    def indent_more(self):
        #cursor is a COPY all changes do not affect the QPlainTextEdit's cursor!!!
        cursor = self.textCursor()
        selectionStart =  cursor.selectionStart()
        selectionEnd = cursor.selectionEnd()
        #line where indent_more should start and end
        start = self.document().findBlock(cursor.selectionStart()).firstLineNumber()
        end = self.document().findBlock(cursor.selectionEnd()).firstLineNumber()
        startPosition = self.document().findBlockByLineNumber(start).position()
        
        #Start a undo block
        cursor.beginEditBlock()
        
        #Decide which lines will be indented
        cursor.setPosition(selectionEnd)
        self.setTextCursor(cursor)
        #Select one char at left
        #If there is a newline \u2029 (\n) then skip it
        self.moveCursor(QTextCursor.Left, QTextCursor.KeepAnchor)
        if u'\u2029' in self.textCursor().selectedText():
            end -= 1
        
        cursor.setPosition(selectionStart)
        self.setTextCursor(cursor)
        self.moveCursor(QTextCursor.StartOfLine)
        #Indent loop; line by line 
        for i in xrange(start, end+1):
            self.textCursor().insertText(' '*Editor.indent)
            self.moveCursor(QTextCursor.Down, QTextCursor.MoveAnchor)

        #Restore the user selection
        cursor.setPosition(startPosition)
        selectionEnd = selectionEnd + (EditorGeneric.indent*(end-start+1))
        cursor.setPosition(selectionEnd, QTextCursor.KeepAnchor)
        self.setTextCursor(cursor)
        #End a undo block
        cursor.endEditBlock()

    def indent_less(self):
        #save the total of movements made after indent_less
        totalIndent = 0
        #cursor is a COPY all changes do not affect the QPlainTextEdit's cursor!!!
        cursor = self.textCursor()
        selectionEnd = cursor.selectionEnd()
        #line where indent_less should start and end
        start = self.document().findBlock(cursor.selectionStart()).firstLineNumber()
        end = self.document().findBlock(cursor.selectionEnd()).firstLineNumber()
        startPosition = self.document().findBlockByLineNumber(start).position()
        
        #Start a undo block
        cursor.beginEditBlock()
        
        #Decide which lines will be indented_less
        cursor.setPosition(selectionEnd)
        self.setTextCursor(cursor)
        #Select one char at left
        self.moveCursor(QTextCursor.Left, QTextCursor.KeepAnchor)
        #If there is a newline \u2029 (\n) then dont indent this line; skip it!
        if u'\u2029' in self.textCursor().selectedText():
            end -= 1

        cursor.setPosition(startPosition)
        self.setTextCursor(cursor)
        self.moveCursor(QTextCursor.StartOfLine)
        #Indent_less loop; line by line 
        for i in xrange(start, end+1):
            #Select EditorGeneric.indent chars from the current line
            for j in xrange(EditorGeneric.indent):
                self.moveCursor(QTextCursor.Right, QTextCursor.KeepAnchor)
            
            text = self.textCursor().selectedText()
            if text == ' '*EditorGeneric.indent:
                self.textCursor().removeSelectedText()
                totalIndent += EditorGeneric.indent
            elif u'\u2029' in text:
                #\u2029 is the unicode char for \n
                #if there is a newline, rollback the selection made above.
                for j in xrange(EditorGeneric.indent):
                    self.moveCursor(QTextCursor.Left, QTextCursor.KeepAnchor)
            
            #Go Down to the next line!
            self.moveCursor(QTextCursor.Down)
        #Restore the user selection
        cursor.setPosition(startPosition)
        cursor.setPosition(selectionEnd-totalIndent, QTextCursor.KeepAnchor)
        self.setTextCursor(cursor)
        #End a undo block
        cursor.endEditBlock()

    def find_match(self, word, back=False, sensitive=False, whole=False):
        b = QTextDocument.FindBackward if back else None
        s = QTextDocument.FindCaseSensitively if sensitive else None
        w = QTextDocument.FindWholeWords if whole else None
        self.moveCursor(QTextCursor.NoMove, QTextCursor.KeepAnchor)
        if back or sensitive or whole:
            self.find(word, b or s or w)
        else:
            self.find(word)

    def replace_match(self, wordOld, wordNew, sensitive=False, whole=False, all=False):
        s = QTextDocument.FindCaseSensitively if sensitive else None
        w = QTextDocument.FindWholeWords if whole else None
        self.moveCursor(QTextCursor.NoMove, QTextCursor.KeepAnchor)

        cursor = self.textCursor()
        cursor.beginEditBlock()

        self.moveCursor(QTextCursor.Start)
        replace = True
        while (replace or all):
            result = False
            if back or sensitive or whole:
                result = self.find(wordOld, s or w)
            else:
                result = self.find(wordOld)

            if result:
                tc = self.textCursor()
                if tc.hasSelection():
                    tc.insertText(wordNew)
            else:
                break
            replace = False

        cursor.endEditBlock()

    def highlight_current_line(self):
        extraSelections = []

        if not self.isReadOnly():
            selection = QTextEdit.ExtraSelection()
            lineColor = QColor(Qt.darkCyan)
            lineColor.setAlpha(20)
            selection.format.setBackground(lineColor)
            selection.format.setProperty(QTextFormat.FullWidthSelection, True)
            selection.cursor = self.textCursor()
            selection.cursor.clearSelection()
            extraSelections.append(selection)
        self.setExtraSelections(extraSelections)

    def resizeEvent(self,e):
        self.lineNumberArea.setFixedHeight(self.height())
        QPlainTextEdit.resizeEvent(self,e)

    def eventFilter(self, object, event):
        if object is self.viewport():
            self.lineNumberArea.update()
            return False
        return QPlainTextEdit.eventFilter(object, event)

    def keyPressEvent(self, event):
        if self.completer is not None and self.completer.popup().isVisible():
            if event.key() in (Qt.Key_Enter, Qt.Key_Return, Qt.Key_Tab,
              Qt.Key_Escape, Qt.Key_Backtab):
                event.ignore()
                self.completer.popup().hide()
                return
            elif event.key == Qt.Key_Space:
                self.completer.popup().hide()

        if event.key() == Qt.Key_Tab:
            if self.textCursor().hasSelection():
                self.indent_more()
                return
            else:
                self.textCursor().insertText(' '*EditorGeneric.indent)
                return
        elif event.key() == Qt.Key_Backspace:
            if self.textCursor().hasSelection():
                super(Editor, self).keyPressEvent(event)
                return
            for i in xrange(EditorGeneric.indent):
                self.moveCursor(QTextCursor.Left, QTextCursor.KeepAnchor)
            text = self.textCursor().selection()
            if unicode(text.toPlainText()) == ' '*EditorGeneric.indent:
                self.textCursor().removeSelectedText()
                return
            else:
                for i in xrange(EditorGeneric.indent):
                    self.moveCursor(QTextCursor.Right)
        elif event.key() == Qt.Key_Home:
            if event.modifiers() == Qt.ShiftModifier:
                move = QTextCursor.KeepAnchor
            else:
                move = QTextCursor.MoveAnchor
            if self.textCursor().atBlockStart():
                self.moveCursor(QTextCursor.WordRight, move)
                return

        super(Editor, self).keyPressEvent(event)
        
        if event.key() in (Qt.Key_Enter, Qt.Key_Return):
            text = unicode(self.document().findBlock(self.textCursor().position()-1).text())
            spaces = self.get_indentation(text)
            self.textCursor().insertText(spaces)
            if text != '' and text == ' '*len(text):
                previousLine = self.document().findBlock(self.textCursor().position()-1)
                self.moveCursor(QTextCursor.Up)
                self.moveCursor(QTextCursor.EndOfLine, QTextCursor.KeepAnchor)
                self.textCursor().removeSelectedText()
                self.moveCursor(QTextCursor.Down)
            self.eventKeyReturn()
        elif unicode(event.text()) in self.braces_strings:
            self.textCursor().insertText(self.braces_strings[str(event.text())])
            self.moveCursor(QTextCursor.Left)
        completionPrefix = self.text_under_cursor()
        if event.key() == Qt.Key_Period or \
          (event.key() == Qt.Key_Space and event.modifiers() == Qt.ControlModifier):
            self.completer.setCompletionPrefix('')
            cr = self.cursorRect()
            self.completer.complete(cr)
        if self.completer is not None and self.completer.popup().isVisible():
            if completionPrefix != self.completer.completionPrefix():
                self.completer.setCompletionPrefix(completionPrefix)
                self.completer.popup().setCurrentIndex(self.completer.completionModel().index(0, 0))
                self.completer.setCurrentRow(0)
                cr = self.cursorRect()
                self.completer.complete(cr)
        self.eventKeyAny()

    def text_under_cursor(self):
        tc = self.textCursor()
        tc.select(QTextCursor.WordUnderCursor)
        return tc.selectedText()

    def wheelEvent(self, event):
        if event.modifiers() == Qt.ControlModifier:
            if event.delta() == 120:
                self.zoom_in()
            elif event.delta() == -120:
                self.zoom_out()
            event.ignore()
        else:
            super(Editor, self).wheelEvent(event)

    def focusInEvent(self, event):
        super(Editor, self).focusInEvent(event)
        self.parent.editor_focus()

    def dropEvent(self, event):
        if event.mimeData().hasText():
            fileName = str(event.mimeData().text())[7:].rstrip()
            content = manage_files.read_file_content(fileName)
            self.setPlainText(content)

    def contextMenuEvent(self, event):
        popup_menu = self.createStandardContextMenu()

        lang = manage_files.get_file_extension(self.get_path())[1:]
        if EditorGeneric.extraMenus.get(lang, False):
            popup_menu.insertSeparator(popup_menu.actions()[0])
            popup_menu.insertMenu(popup_menu.actions()[0], EditorGeneric.extraMenus[lang])

        popup_menu.exec_(event.globalPos())


    #based on: http://john.nachtimwald.com/2009/08/15/qtextedit-with-line-numbers/ (MIT license)
    class LineNumberArea(QWidget):

        def __init__(self, editor):
            QWidget.__init__(self, editor)
            self.edit = editor
            self.highest_line = 0
            css = '''
            QWidget {
              font-family: monospace;
              font-size: 10;
              color: black;
            }'''
            self.setStyleSheet(css)
 
        def update(self, *args):
            width = QFontMetrics(self.edit.document().defaultFont()).width(str(self.highest_line)) + 10
            if self.width() != width:
                self.setFixedWidth(width)
                self.edit.setViewportMargins(width,0,0,0)
            QWidget.update(self, *args)
 
        def paintEvent(self, event):
            contents_y = 0
            page_bottom = self.edit.viewport().height()
            font_metrics = QFontMetrics(self.edit.document().defaultFont())
            current_block = self.edit.document().findBlock(self.edit.textCursor().position())
 
            painter = QPainter(self)
            painter.fillRect(self.rect(), Qt.lightGray)
            
            block = self.edit.firstVisibleBlock()
            viewport_offset = self.edit.contentOffset()
            line_count = block.blockNumber()
            painter.setFont(self.edit.document().defaultFont())
            while block.isValid():
                line_count += 1
                # The top left position of the block in the document
                position = self.edit.blockBoundingGeometry(block).topLeft() + viewport_offset
                # Check if the position of the block is out side of the visible area
                if position.y() > page_bottom:
                    break
 
                # We want the line number for the selected line to be bold.
                bold = False
                if block == current_block:
                    bold = True
                    font = painter.font()
                    font.setBold(True)
                    painter.setFont(font)
 
                # Draw the line number right justified at the y position of the
                # line. 3 is a magic padding number. drawText(x, y, text).
                painter.drawText(self.width() - font_metrics.width(str(line_count)) - 3,
                    round(position.y()) + font_metrics.ascent()+font_metrics.descent()-1,
                    str(line_count))
 
                # Remove the bold style if it was set previously.
                if bold:
                    font = painter.font()
                    font.setBold(False)
                    painter.setFont(font)
 
                block = block.next()
 
            self.highest_line = line_count
            painter.end()
 
            QWidget.paintEvent(self, event)
Beispiel #16
0
class Interpreter(InteractiveInterpreter):
    def __init__(self, namespace=None):
        if namespace is not None:
            namespace = namespace()

        InteractiveInterpreter.__init__(self, namespace)
        self.output_trap = OutputTrap()
        self.completer = Completer(self.locals)
        self.input_count = 0
        self.interrupted = False

    def _result_dict(self, out, in_string="", err="", in_count="", cmd_count=""):
        return {"input_count": in_count, "cmd_count": cmd_count, "in": in_string, "out": out, "err": err}

    # ------------------------------------------------
    # Main methods to call external
    #
    def cancel_interrupt(self):
        self.interrupted = False
        return self._result_dict("ok")

    def evaluate(self, input_string):
        """give the input_string to the python interpreter in the
        usernamespace"""
        self.output_trap.set()
        command_count = self._runcommands(input_string)
        out_values = self.output_trap.get_values()
        self.output_trap.reset()
        self.input_count += 1
        result = {
            "input_count": self.input_count,
            "cmd_count": command_count,
            "in": input_string,
            "out": out_values[0],
            "err": out_values[1],
        }
        return result

    def introspect(self, input_string):
        """See what information there is about this objects methods and
        attributes."""
        info = introspect(input_string)

    def complete_name(self, input_string):
        """See what possible completions there are for this object
        (input_string)."""
        matches = self.completer.global_matches(input_string)
        # return ' '.join(matches)
        return matches

    def complete_attr(self, input_string):

        matches = self.completer.attr_matches(input_string)
        return matches

    #
    # -----------------------------------------------

    def _runcommands(self, input_string):
        """input_string could contain multiple lines, multiple commands, or
        multiple multiline commands. This method builds a compiled command
        line by line until a complete command has been compiled. Once it
        has a complete command, it execs it in the username space and the
        output is stored in the output trap. There may be more than one
        command; the number of complete commands is counted
        (Based off of ipython1.core.shell.InteractiveShell._runlines)"""

        command_buffer = []
        command_count = 0

        if self.interrupted:
            print >>sys.stderr, "Aborted."
            # sys.stderr.write('Aborted')
            return command_count
        lines = input_string.split("\n")
        lines = [l for l in lines if len(l) > 0]
        more = False
        for line in lines:
            line = self._pre_execute_filter(line)
            command_buffer.append(line)
            if line or more:
                torun = "\n".join(command_buffer)
                try:
                    more = self.runsource(torun)
                except OperationAborted, e:
                    print >>sys.stderr, e.value
                    # sys.stderr.write(e.value)
                    # XXX This could be bad if something other than the
                    # kernelConnection triggers an interrupt
                    self.interrupted = True
                    return command_count
            if more:
                pass
            else:
                command_buffer = []
                command_count += 1
                more = False
        if more:
            command_buffer.append("\n")
            torun = "\n".join(command_buffer)
            more = self.runsource(torun)
        return command_count
Beispiel #17
0
class Interpreter(InteractiveInterpreter):
    def __init__(self, namespace=None):
        if namespace is not None:
            namespace = namespace()

        InteractiveInterpreter.__init__(self, namespace)
        self.output_trap = OutputTrap()
        self.completer = Completer(self.locals)
        self.input_count = 0
        self.interrupted = False

    def _result_dict(self,
                     out,
                     in_string='',
                     err='',
                     in_count='',
                     cmd_count=''):
        return {
            'input_count': in_count,
            'cmd_count': cmd_count,
            'in': in_string,
            'out': out,
            'err': err
        }

    #------------------------------------------------
    # Main methods to call external
    #
    def cancel_interrupt(self):
        self.interrupted = False
        return self._result_dict('ok')

    def evaluate(self, input_string):
        """give the input_string to the python interpreter in the
        usernamespace"""
        self.output_trap.set()
        command_count = self._runcommands(input_string)
        out_values = self.output_trap.get_values()
        self.output_trap.reset()
        self.input_count += 1
        result = {
            'input_count': self.input_count,
            'cmd_count': command_count,
            'in': input_string,
            'out': out_values[0],
            'err': out_values[1]
        }
        return result

    def introspect(self, input_string):
        """See what information there is about this objects methods and
        attributes."""
        info = introspect(input_string)

    def complete(self, input_string):
        """
        Complete a name or attribute.
        """
        reName = "([a-zA-Z_][a-zA-Z_0-9]*)$"
        reAttribute = "([a-zA-Z_][a-zA-Z_0-9]*[.]+[a-zA-Z_.0-9]*)$"
        nameMatch = re.match(reName, input_string)
        attMatch = re.match(reAttribute, input_string)
        if nameMatch:
            matches = self.completer.global_matches(input_string)
            return {'out': matches}
        if attMatch:
            matches = self.completer.attr_matches(input_string)
            return {'out': matches}
        return {'out': []}

    def complete_name(self, input_string):
        """See what possible completions there are for this object
        (input_string)."""
        matches = self.completer.global_matches(input_string)
        # return ' '.join(matches)
        return matches

    def complete_attr(self, input_string):

        matches = self.completer.attr_matches(input_string)
        return matches

    #
    #-----------------------------------------------

    def _runcommands(self, input_string):
        """input_string could contain multiple lines, multiple commands, or
        multiple multiline commands. This method builds a compiled command
        line by line until a complete command has been compiled. Once it
        has a complete command, it execs it in the username space and the
        output is stored in the output trap. There may be more than one
        command; the number of complete commands is counted
        (Based off of ipython1.core.shell.InteractiveShell._runlines)"""

        command_buffer = []
        command_count = 0

        if self.interrupted:
            print >> sys.stderr, 'Aborted.'
            #sys.stderr.write('Aborted')
            return command_count
        lines = input_string.split('\n')
        lines = [l for l in lines if len(l) > 0]
        more = False
        for line in lines:
            line = self._pre_execute_filter(line)
            command_buffer.append(line)
            if line or more:
                torun = '\n'.join(command_buffer)
                try:
                    more = self.runsource(torun)
                except OperationAborted, e:
                    print >> sys.stderr, e.value
                    #sys.stderr.write(e.value)
                    # XXX This could be bad if something other than the
                    # kernelConnection triggers an interrupt
                    #self.interrupted = True
                    return command_count
            if more:
                pass
            else:
                command_buffer = []
                command_count += 1
                more = False
        if more:
            command_buffer.append('\n')
            torun = '\n'.join(command_buffer)
            more = self.runsource(torun)
        return command_count
Beispiel #18
0
class Editor(QPlainTextEdit, EditorGeneric, BaseCentralWidget):
    def __init__(self, parent, project=None):
        QPlainTextEdit.__init__(self)
        EditorGeneric.__init__(self)
        BaseCentralWidget.__init__(self)
        self.parent = parent
        self.completer = Completer(self, project)
        self.setWordWrapMode(QTextOption.NoWrap)
        doc = self.document()
        option = QTextOption()
        option.setFlags(QTextOption.ShowTabsAndSpaces)
        doc.setDefaultTextOption(option)
        self.setDocument(doc)
        self.set_default_font()

        #file modification time POSIX
        self._mtime = None
        #Flag to dont bug the user when answer 'dont show the modification dialog'
        self.ask_if_externally_modified = True

        self.lineNumberArea = self.LineNumberArea(self)
        self.viewport().installEventFilter(self)

        self.highlighter = None
        styles.set_style(self, 'editor')

        self.connect(self, SIGNAL("cursorPositionChanged()"),
                     self.highlight_current_line)
        self.connect(self, SIGNAL("modificationChanged(bool)"),
                     self.modif_changed)
        self.highlight_current_line()

    def set_path(self, fileName):
        super(Editor, self).set_path(fileName)
        self.newDocument = False
        self._mtime = manage_files.get_last_modification(fileName)

    def check_external_modification(self):
        if self.newDocument:
            return False
        #Saved document we can ask for modification!
        return manage_files.check_for_external_modification(
            self.path, self._mtime)

    def has_write_permission(self):
        if self.newDocument:
            return True
        return manage_files.has_write_prmission(self.path)

    def register_syntax(self, fileName):
        ext = manage_files.get_file_extension(fileName)[1:]
        if self.highlighter is not None and \
            not self.path.endswith(ext):
            self.highlighter.deleteLater()
        if not self.path.endswith(ext):
            if ext in loader.extensions:
                self.highlighter = Highlighter(
                    self.document(), loader.extensions.get(ext, 'py'))
            else:
                try:
                    self.highlighter = HighlighterPygments(
                        self.document(), fileName)
                except:
                    print 'There is no lexer for this file'
            #for apply rehighlighting (rehighlighting form highlighter not responding)
            self.firstVisibleBlock().document().find('\n').insertText('')

    def set_font(self, font):
        self.document().setDefaultFont(font)
        self.font_family = str(font.family())
        self.font_size = font.pointSize()
        self.parent.notify_font_change()

    def set_default_font(self):
        #Set Font and FontSize
        font = QFont(self.font_family, self.font_size)
        self.document().setDefaultFont(font)

    def get_font(self):
        return self.document().defaultFont()

    def get_text(self):
        return self.toPlainText()

    def modif_changed(self, val):
        if self.parent is not None:
            self.parent.mark_as_changed(val)

    def zoom_in(self):
        font = self.font()
        size = font.pointSize()
        if size < self.font_max_size:
            size += 2
            font.setPointSize(size)
        self.setFont(font)

    def zoom_out(self):
        font = self.font()
        size = font.pointSize()
        if size > self.font_min_size:
            size -= 2
            font.setPointSize(size)
        self.setFont(font)

    def comment(self):
        lang = manage_files.get_file_extension(self.get_path())[1:]
        key = loader.extensions.get(lang, 'python')
        comment_wildcard = loader.syntax[key]['comment'][0]

        #cursor is a COPY all changes do not affect the QPlainTextEdit's cursor!!!
        cursor = self.textCursor()
        start = self.document().findBlock(
            cursor.selectionStart()).firstLineNumber()
        end = self.document().findBlock(
            cursor.selectionEnd()).firstLineNumber()
        startPosition = self.document().findBlockByLineNumber(start).position()

        #Start a undo block
        cursor.beginEditBlock()

        #Move the COPY cursor
        cursor.setPosition(startPosition)
        #Move the QPlainTextEdit Cursor where the COPY cursor IS!
        self.setTextCursor(cursor)
        self.moveCursor(QTextCursor.StartOfLine)
        self.moveCursor(QTextCursor.Right, QTextCursor.KeepAnchor)
        text = self.textCursor().selectedText()
        if text == comment_wildcard:
            cursor.endEditBlock()
            self.uncomment(start, end, startPosition)
            return
        else:
            self.moveCursor(QTextCursor.StartOfLine)
        for i in xrange(start, end + 1):
            self.textCursor().insertText(comment_wildcard)
            self.moveCursor(QTextCursor.Down)
            self.moveCursor(QTextCursor.StartOfLine)

        #End a undo block
        cursor.endEditBlock()

    def uncomment(self, start=-1, end=-1, startPosition=-1):
        lang = manage_files.get_file_extension(self.get_path())[1:]
        key = loader.extensions.get(lang, 'python')
        comment_wildcard = loader.syntax[key]['comment'][0]

        #cursor is a COPY all changes do not affect the QPlainTextEdit's cursor!!!
        cursor = self.textCursor()
        if start == -1 and end == -1 and startPosition == -1:
            start = self.document().findBlock(
                cursor.selectionStart()).firstLineNumber()
            end = self.document().findBlock(
                cursor.selectionEnd()).firstLineNumber()
            startPosition = self.document().findBlockByLineNumber(
                start).position()

        #Start a undo block
        cursor.beginEditBlock()

        #Move the COPY cursor
        cursor.setPosition(startPosition)
        #Move the QPlainTextEdit Cursor where the COPY cursor IS!
        self.setTextCursor(cursor)
        self.moveCursor(QTextCursor.StartOfLine)
        for i in xrange(start, end + 1):
            self.moveCursor(QTextCursor.Right, QTextCursor.KeepAnchor)
            text = self.textCursor().selectedText()
            if text == comment_wildcard:
                self.textCursor().removeSelectedText()
            elif u'\u2029' in text:
                #\u2029 is the unicode char for \n
                #if there is a newline, rollback the selection made above.
                self.moveCursor(QTextCursor.Left, QTextCursor.KeepAnchor)

            self.moveCursor(QTextCursor.Down)
            self.moveCursor(QTextCursor.StartOfLine)

        #End a undo block
        cursor.endEditBlock()

    def insert_horizontal_line(self):
        self.moveCursor(QTextCursor.StartOfLine, QTextCursor.KeepAnchor)
        text = unicode(self.textCursor().selection().toPlainText())
        self.moveCursor(QTextCursor.EndOfLine, QTextCursor.MoveAnchor)
        comment = '#' * (80 - len(text))
        self.textCursor().insertText(comment)

    def indent_more(self):
        #cursor is a COPY all changes do not affect the QPlainTextEdit's cursor!!!
        cursor = self.textCursor()
        selectionStart = cursor.selectionStart()
        selectionEnd = cursor.selectionEnd()
        #line where indent_more should start and end
        start = self.document().findBlock(
            cursor.selectionStart()).firstLineNumber()
        end = self.document().findBlock(
            cursor.selectionEnd()).firstLineNumber()
        startPosition = self.document().findBlockByLineNumber(start).position()

        #Start a undo block
        cursor.beginEditBlock()

        #Decide which lines will be indented
        cursor.setPosition(selectionEnd)
        self.setTextCursor(cursor)
        #Select one char at left
        #If there is a newline \u2029 (\n) then skip it
        self.moveCursor(QTextCursor.Left, QTextCursor.KeepAnchor)
        if u'\u2029' in self.textCursor().selectedText():
            end -= 1

        cursor.setPosition(selectionStart)
        self.setTextCursor(cursor)
        self.moveCursor(QTextCursor.StartOfLine)
        #Indent loop; line by line
        for i in xrange(start, end + 1):
            self.textCursor().insertText(' ' * Editor.indent)
            self.moveCursor(QTextCursor.Down, QTextCursor.MoveAnchor)

        #Restore the user selection
        cursor.setPosition(startPosition)
        selectionEnd = selectionEnd + (EditorGeneric.indent *
                                       (end - start + 1))
        cursor.setPosition(selectionEnd, QTextCursor.KeepAnchor)
        self.setTextCursor(cursor)
        #End a undo block
        cursor.endEditBlock()

    def indent_less(self):
        #save the total of movements made after indent_less
        totalIndent = 0
        #cursor is a COPY all changes do not affect the QPlainTextEdit's cursor!!!
        cursor = self.textCursor()
        selectionEnd = cursor.selectionEnd()
        #line where indent_less should start and end
        start = self.document().findBlock(
            cursor.selectionStart()).firstLineNumber()
        end = self.document().findBlock(
            cursor.selectionEnd()).firstLineNumber()
        startPosition = self.document().findBlockByLineNumber(start).position()

        #Start a undo block
        cursor.beginEditBlock()

        #Decide which lines will be indented_less
        cursor.setPosition(selectionEnd)
        self.setTextCursor(cursor)
        #Select one char at left
        self.moveCursor(QTextCursor.Left, QTextCursor.KeepAnchor)
        #If there is a newline \u2029 (\n) then dont indent this line; skip it!
        if u'\u2029' in self.textCursor().selectedText():
            end -= 1

        cursor.setPosition(startPosition)
        self.setTextCursor(cursor)
        self.moveCursor(QTextCursor.StartOfLine)
        #Indent_less loop; line by line
        for i in xrange(start, end + 1):
            #Select EditorGeneric.indent chars from the current line
            for j in xrange(EditorGeneric.indent):
                self.moveCursor(QTextCursor.Right, QTextCursor.KeepAnchor)

            text = self.textCursor().selectedText()
            if text == ' ' * EditorGeneric.indent:
                self.textCursor().removeSelectedText()
                totalIndent += EditorGeneric.indent
            elif u'\u2029' in text:
                #\u2029 is the unicode char for \n
                #if there is a newline, rollback the selection made above.
                for j in xrange(EditorGeneric.indent):
                    self.moveCursor(QTextCursor.Left, QTextCursor.KeepAnchor)

            #Go Down to the next line!
            self.moveCursor(QTextCursor.Down)
        #Restore the user selection
        cursor.setPosition(startPosition)
        cursor.setPosition(selectionEnd - totalIndent, QTextCursor.KeepAnchor)
        self.setTextCursor(cursor)
        #End a undo block
        cursor.endEditBlock()

    def find_match(self, word, back=False, sensitive=False, whole=False):
        b = QTextDocument.FindBackward if back else None
        s = QTextDocument.FindCaseSensitively if sensitive else None
        w = QTextDocument.FindWholeWords if whole else None
        self.moveCursor(QTextCursor.NoMove, QTextCursor.KeepAnchor)
        if back or sensitive or whole:
            self.find(word, b or s or w)
        else:
            self.find(word)

    def replace_match(self,
                      wordOld,
                      wordNew,
                      sensitive=False,
                      whole=False,
                      all=False):
        s = QTextDocument.FindCaseSensitively if sensitive else None
        w = QTextDocument.FindWholeWords if whole else None
        self.moveCursor(QTextCursor.NoMove, QTextCursor.KeepAnchor)

        cursor = self.textCursor()
        cursor.beginEditBlock()

        self.moveCursor(QTextCursor.Start)
        replace = True
        while (replace or all):
            result = False
            if back or sensitive or whole:
                result = self.find(wordOld, s or w)
            else:
                result = self.find(wordOld)

            if result:
                tc = self.textCursor()
                if tc.hasSelection():
                    tc.insertText(wordNew)
            else:
                break
            replace = False

        cursor.endEditBlock()

    def highlight_current_line(self):
        extraSelections = []

        if not self.isReadOnly():
            selection = QTextEdit.ExtraSelection()
            lineColor = QColor(Qt.darkCyan)
            lineColor.setAlpha(20)
            selection.format.setBackground(lineColor)
            selection.format.setProperty(QTextFormat.FullWidthSelection, True)
            selection.cursor = self.textCursor()
            selection.cursor.clearSelection()
            extraSelections.append(selection)
        self.setExtraSelections(extraSelections)

    def resizeEvent(self, e):
        self.lineNumberArea.setFixedHeight(self.height())
        QPlainTextEdit.resizeEvent(self, e)

    def eventFilter(self, object, event):
        if object is self.viewport():
            self.lineNumberArea.update()
            return False
        return QPlainTextEdit.eventFilter(object, event)

    def keyPressEvent(self, event):
        if self.completer is not None and self.completer.popup().isVisible():
            if event.key() in (Qt.Key_Enter, Qt.Key_Return, Qt.Key_Tab,
                               Qt.Key_Escape, Qt.Key_Backtab):
                event.ignore()
                self.completer.popup().hide()
                return
            elif event.key == Qt.Key_Space:
                self.completer.popup().hide()

        if event.key() == Qt.Key_Tab:
            if self.textCursor().hasSelection():
                self.indent_more()
                return
            else:
                self.textCursor().insertText(' ' * EditorGeneric.indent)
                return
        elif event.key() == Qt.Key_Backspace:
            if self.textCursor().hasSelection():
                super(Editor, self).keyPressEvent(event)
                return
            for i in xrange(EditorGeneric.indent):
                self.moveCursor(QTextCursor.Left, QTextCursor.KeepAnchor)
            text = self.textCursor().selection()
            if unicode(text.toPlainText()) == ' ' * EditorGeneric.indent:
                self.textCursor().removeSelectedText()
                return
            else:
                for i in xrange(EditorGeneric.indent):
                    self.moveCursor(QTextCursor.Right)
        elif event.key() == Qt.Key_Home:
            if event.modifiers() == Qt.ShiftModifier:
                move = QTextCursor.KeepAnchor
            else:
                move = QTextCursor.MoveAnchor
            if self.textCursor().atBlockStart():
                self.moveCursor(QTextCursor.WordRight, move)
                return

        super(Editor, self).keyPressEvent(event)

        if event.key() in (Qt.Key_Enter, Qt.Key_Return):
            text = unicode(
                self.document().findBlock(self.textCursor().position() -
                                          1).text())
            spaces = self.get_indentation(text)
            self.textCursor().insertText(spaces)
            if text != '' and text == ' ' * len(text):
                previousLine = self.document().findBlock(
                    self.textCursor().position() - 1)
                self.moveCursor(QTextCursor.Up)
                self.moveCursor(QTextCursor.EndOfLine, QTextCursor.KeepAnchor)
                self.textCursor().removeSelectedText()
                self.moveCursor(QTextCursor.Down)
            self.eventKeyReturn()
        elif unicode(event.text()) in self.braces_strings:
            self.textCursor().insertText(self.braces_strings[str(
                event.text())])
            self.moveCursor(QTextCursor.Left)
        completionPrefix = self.text_under_cursor()
        if event.key() == Qt.Key_Period or \
          (event.key() == Qt.Key_Space and event.modifiers() == Qt.ControlModifier):
            self.completer.setCompletionPrefix('')
            cr = self.cursorRect()
            self.completer.complete(cr)
        if self.completer is not None and self.completer.popup().isVisible():
            if completionPrefix != self.completer.completionPrefix():
                self.completer.setCompletionPrefix(completionPrefix)
                self.completer.popup().setCurrentIndex(
                    self.completer.completionModel().index(0, 0))
                self.completer.setCurrentRow(0)
                cr = self.cursorRect()
                self.completer.complete(cr)
        self.eventKeyAny()

    def text_under_cursor(self):
        tc = self.textCursor()
        tc.select(QTextCursor.WordUnderCursor)
        return tc.selectedText()

    def wheelEvent(self, event):
        if event.modifiers() == Qt.ControlModifier:
            if event.delta() == 120:
                self.zoom_in()
            elif event.delta() == -120:
                self.zoom_out()
            event.ignore()
        else:
            super(Editor, self).wheelEvent(event)

    def focusInEvent(self, event):
        super(Editor, self).focusInEvent(event)
        self.parent.editor_focus()

    def dropEvent(self, event):
        if event.mimeData().hasText():
            fileName = str(event.mimeData().text())[7:].rstrip()
            content = manage_files.read_file_content(fileName)
            self.setPlainText(content)

    def contextMenuEvent(self, event):
        popup_menu = self.createStandardContextMenu()

        lang = manage_files.get_file_extension(self.get_path())[1:]
        if EditorGeneric.extraMenus.get(lang, False):
            popup_menu.insertSeparator(popup_menu.actions()[0])
            popup_menu.insertMenu(popup_menu.actions()[0],
                                  EditorGeneric.extraMenus[lang])

        popup_menu.exec_(event.globalPos())

    #based on: http://john.nachtimwald.com/2009/08/15/qtextedit-with-line-numbers/ (MIT license)
    class LineNumberArea(QWidget):
        def __init__(self, editor):
            QWidget.__init__(self, editor)
            self.edit = editor
            self.highest_line = 0
            css = '''
            QWidget {
              font-family: monospace;
              font-size: 10;
              color: black;
            }'''
            self.setStyleSheet(css)

        def update(self, *args):
            width = QFontMetrics(self.edit.document().defaultFont()).width(
                str(self.highest_line)) + 10
            if self.width() != width:
                self.setFixedWidth(width)
                self.edit.setViewportMargins(width, 0, 0, 0)
            QWidget.update(self, *args)

        def paintEvent(self, event):
            contents_y = 0
            page_bottom = self.edit.viewport().height()
            font_metrics = QFontMetrics(self.edit.document().defaultFont())
            current_block = self.edit.document().findBlock(
                self.edit.textCursor().position())

            painter = QPainter(self)
            painter.fillRect(self.rect(), Qt.lightGray)

            block = self.edit.firstVisibleBlock()
            viewport_offset = self.edit.contentOffset()
            line_count = block.blockNumber()
            painter.setFont(self.edit.document().defaultFont())
            while block.isValid():
                line_count += 1
                # The top left position of the block in the document
                position = self.edit.blockBoundingGeometry(
                    block).topLeft() + viewport_offset
                # Check if the position of the block is out side of the visible area
                if position.y() > page_bottom:
                    break

                # We want the line number for the selected line to be bold.
                bold = False
                if block == current_block:
                    bold = True
                    font = painter.font()
                    font.setBold(True)
                    painter.setFont(font)

                # Draw the line number right justified at the y position of the
                # line. 3 is a magic padding number. drawText(x, y, text).
                painter.drawText(
                    self.width() - font_metrics.width(str(line_count)) - 3,
                    round(position.y()) + font_metrics.ascent() +
                    font_metrics.descent() - 1, str(line_count))

                # Remove the bold style if it was set previously.
                if bold:
                    font = painter.font()
                    font.setBold(False)
                    painter.setFont(font)

                block = block.next()

            self.highest_line = line_count
            painter.end()

            QWidget.paintEvent(self, event)
Beispiel #19
0
class Console(InteractiveConsole):
  def __init__(self, locals = __builtin__.globals()):
    InteractiveConsole.__init__(self, locals)

    self.stdout = sys.stdout
    self.stderr = sys.stderr
    
    self.pipe = Pipe()
    self.completer = Completer(locals)

#-------------------------------------------------------------------------------

  def redirectOutput(self, stdout, stderr):
    sys.stdout = stdout
    sys.stderr = stderr

#-------------------------------------------------------------------------------

  def push(self, input):
    self.redirectOutput(self.pipe, self.pipe)
    InteractiveConsole.push(self, input)
    self.redirectOutput(self.stdout, self.stderr)

    output = self.pipe.flush()

    return output

#-------------------------------------------------------------------------------

  def complete(self, input):
    completed = input
    candidates = []
    
    words = input.split(" ")
    matches = self.completer.getMatches(words[-1])

    for match in matches:
      if callable(matches[match]):
        candidates.append(match+"()")
      else:
        candidates.append(match)

    if len(matches) == 1:
      match = matches.iterkeys().next()
      words = words[0:-1]
      words.append(match)

      completed = " ".join(words)
      if callable(matches[match]):
        completed += "("

    return completed, candidates
  
#-------------------------------------------------------------------------------

  def help(self, input):
    text = None
    
    doc = self.push("%s.__doc__" % input)
    if ("Traceback" in doc) or ("SyntaxError" in doc):
      doc = None
    
    self.push("import inspect")
    src = self.push("inspect.getsourcelines(%s)[0][0:6]" % input)
    if ("Traceback" in src) or ("SyntaxError" in src):
      src = None
    
    if doc:
      exec("text = ''.join(%s)" % doc)
    elif src:
      exec("text = ''.join(%s)" % src)

    if text:
      text = text.strip(os.linesep)
    return text
Beispiel #20
0
    readline.read_history_file(history_file)
except IOError:
    pass

import atexit
atexit.register(readline.write_history_file, history_file)

del history_file
del atexit
del path, environ

# Establish client.
# cicada = Client(host = 'bee2')

cicada = Client()
completer = Completer()

# Set the command prompt
def set_prompt(prompt, sentinel = '>', spacer = True):
    sys.ps1 = prompt + sentinel

    sys.ps2 = ''
    for c in sys.ps1:
        sys.ps2 += '.'

    if spacer:
        sys.ps1 += ' '
        sys.ps2 += ' '

# This may ignore useful completion items; unignore or use unregister instead.
completer.ignore(globals())