Пример #1
0
class AutoCompleteLineEdit(QLineEdit):
    # http://blog.elentok.com/2011/08/autocomplete-textbox-for-multiple.html
    def __init__(self, items, parent=None):
        super(AutoCompleteLineEdit, self).__init__(parent)

        self._separators = [",", " "]

        self._completer = QCompleter(items, self)
        self._completer.setWidget(self)
        self._completer.activated[str].connect(self.__insertCompletion)
        self._completer.setCaseSensitivity(Qt.CaseInsensitive)

        self.__keysToIgnore = [
            Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape, Qt.Key_Tab
        ]

    def __insertCompletion(self, completion):
        extra = len(completion) - len(self._completer.completionPrefix())
        extra_text = completion[-extra:]
        extra_text += ', '
        self.setText(self.text() + extra_text)

    def textUnderCursor(self):
        text = self.text()
        text_under_cursor = ''
        i = self.cursorPosition() - 1
        while i >= 0 and text[i] not in self._separators:
            text_under_cursor = text[i] + text_under_cursor
            i -= 1
        return text_under_cursor

    def keyPressEvent(self, event):
        if self._completer.popup().isVisible():
            if event.key() in self.__keysToIgnore:
                event.ignore()
                return

        super(AutoCompleteLineEdit, self).keyPressEvent(event)

        completion_prefix = self.textUnderCursor()
        if completion_prefix != self._completer.completionPrefix():
            self.__updateCompleterPopupItems(completion_prefix)
        if len(event.text()) > 0 and len(completion_prefix) > 0:
            self._completer.complete()
        if len(completion_prefix) == 0:
            self._completer.popup().hide()

    def __updateCompleterPopupItems(self, completionPrefix):
        self._completer.setCompletionPrefix(completionPrefix)
        self._completer.popup().setCurrentIndex(
            self._completer.completionModel().index(0, 0))
Пример #2
0
class AutoCompleteLineEdit(QLineEdit):
    #http://blog.elentok.com/2011/08/autocomplete-textbox-for-multiple.html
    def __init__(self, items, parent=None):
        super(AutoCompleteLineEdit, self).__init__(parent)

        self.__separators = [",", " "]

        self.__completer = QCompleter(items, self)
        self.__completer.setWidget(self)
        self.__completer.activated[str].connect(self.__insertCompletion)
        self.__completer.setCaseSensitivity(Qt.CaseInsensitive)

        self.__keysToIgnore = [Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape, Qt.Key_Tab]

    def __insertCompletion(self, completion):
        extra = len(completion) - len(self.__completer.completionPrefix())
        extra_text = completion[-extra:]
        extra_text += ', '
        self.setText(self.text() + extra_text)


    def textUnderCursor(self):
        text = self.text()
        text_under_cursor = ''
        i = self.cursorPosition() - 1
        while i >=0 and text[i] not in self.__separators:
            text_under_cursor = text[i] + text_under_cursor
            i -= 1
        return text_under_cursor


    def keyPressEvent(self, event):
        if self.__completer.popup().isVisible():
            if event.key() in self.__keysToIgnore:
                event.ignore()
                return

        super(AutoCompleteLineEdit, self).keyPressEvent(event)

        completion_prefix = self.textUnderCursor()
        if completion_prefix != self.__completer.completionPrefix():
            self.__updateCompleterPopupItems(completion_prefix)
        if len(event.text()) > 0 and len(completion_prefix) > 0:
            self.__completer.complete()
        if len(completion_prefix) == 0:
            self.__completer.popup().hide()


    def __updateCompleterPopupItems(self, completionPrefix):
        self.__completer.setCompletionPrefix(completionPrefix)
        self.__completer.popup().setCurrentIndex(self.__completer.completionModel().index(0,0))
Пример #3
0
class ExtendedComboBox(QComboBox):
    def __init__(self, parent=None):
        super(ExtendedComboBox, self).__init__(parent)

        self.setFocusPolicy(Qt.StrongFocus)
        self.setEditable(True)
        self.pFilterModel = QSortFilterProxyModel(self)
        self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.pFilterModel.setSourceModel(self.model())
        self.completer = QCompleter(self.pFilterModel, self)
        self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
        self.completer.popup().setStyleSheet('min-height: 150px')
        self.completer.popup().setAlternatingRowColors(True)
        self.setCompleter(self.completer)
        self.lineEdit().textEdited[unicode].connect(self.pFilterModel.setFilterFixedString)
Пример #4
0
class ExtendedCombo(QComboBox):
    def __init__(self,  parent=None):
        super(ExtendedCombo, self).__init__(parent)

        self.setFocusPolicy(Qt.StrongFocus)
        self.setEditable(True)
        self.completer = QCompleter(self)
        self.selected_id = None

        # always show all completions
        self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion )
        self.pFilterModel = QSortFilterProxyModel(self)
        self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)

        self.completer.setPopup(self.view())
        self.setCompleter(self.completer)


        self.lineEdit().textEdited[unicode].connect(self.pFilterModel.setFilterFixedString)
        self.completer.activated.connect(self.setTextIfCompleterIsClicked)
        self.currentIndexChanged.connect(self.currentSelected)

    def setModel( self, model ):
        super(ExtendedCombo, self).setModel( model )
        self.pFilterModel.setSourceModel( model )
        self.completer.setModel(self.pFilterModel)

    def setModelColumn( self, column):
        self.completer.setCompletionColumn( column )
        self.pFilterModel.setFilterKeyColumn( column )
        super(ExtendedCombo, self).setModelColumn( column )


    def view(self):
        return self.completer.popup()

    def index(self):
        return self.currentIndex()

    def setTextIfCompleterIsClicked(self, text):
      if text:
        index = self.findText(text)
        self.setCurrentIndex(index)

    def currentSelected(self, text):
        if text:
            self.selected_id = self.currentText()
class ExtendedComboBox(QComboBox):
    """ Based off the extension of the combo box from below:
        http://stackoverflow.com/questions/4827207/how-do-i-filter-the-pyqt-qcombobox-items-based-on-the-text-input
    """
    def __init__(self, parent=None):
        super(ExtendedComboBox, self).__init__(parent)

        self.setFocusPolicy(Qt.StrongFocus)
        self.setEditable(True)

        self.setEditable(True)
        self.completer = QCompleter(self)

        # always show all completions
        self.completer.setCompletionMode(QCompleter.PopupCompletion)
        self.pFilterModel = QSortFilterProxyModel(self)
        self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)

        self.completer.setPopup(self.view())
        self.setCompleter(self.completer)

        self.lineEdit().textEdited[unicode].connect(
            self.pFilterModel.setFilterFixedString)
        self.completer.activated.connect(self.setTextIfCompleterIsClicked)

    def setModel(self, model):
        super(ExtendedComboBox, self).setModel(model)
        self.pFilterModel.setSourceModel(model)
        self.completer.setModel(self.pFilterModel)

    def setModelColumn(self, column):
        self.completer.setCompletionColumn(column)
        self.pFilterModel.setFilterKeyColumn(column)
        super(ExtendedComboBox, self).setModelColumn(column)

    def view(self):
        return self.completer.popup()

    def index(self):
        return self.currentIndex()

    def setTextIfCompleterIsClicked(self, text):
        if text:
            index = self.findText(text)
            self.setCurrentIndex(index)
class ExtendedComboBox(QComboBox):
    """ Based off the extension of the combo box from below:
        http://stackoverflow.com/questions/4827207/how-do-i-filter-the-pyqt-qcombobox-items-based-on-the-text-input
    """
    def __init__(self, parent = None):
        super(ExtendedComboBox, self).__init__(parent)

        self.setFocusPolicy(Qt.StrongFocus)
        self.setEditable(True)

        self.setEditable(True)
        self.completer = QCompleter(self)

        # always show all completions
        self.completer.setCompletionMode(QCompleter.PopupCompletion)
        self.pFilterModel = QSortFilterProxyModel(self)
        self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)

        self.completer.setPopup(self.view())
        self.setCompleter(self.completer)

        self.lineEdit().textEdited[unicode].connect(self.pFilterModel.setFilterFixedString)
        self.completer.activated.connect(self.setTextIfCompleterIsClicked)

    def setModel(self, model):
        super(ExtendedComboBox, self).setModel( model )
        self.pFilterModel.setSourceModel( model )
        self.completer.setModel(self.pFilterModel)

    def setModelColumn(self, column):
        self.completer.setCompletionColumn(column)
        self.pFilterModel.setFilterKeyColumn(column)
        super(ExtendedComboBox, self).setModelColumn(column)


    def view(self):
        return self.completer.popup()

    def index(self):
        return self.currentIndex()

    def setTextIfCompleterIsClicked(self, text):
      if text:
        index = self.findText(text)
        self.setCurrentIndex(index)
Пример #7
0
class ExtendedComboBox( QComboBox ):
    def __init__( self,  parent = None):
        super( ExtendedComboBox, self ).__init__( parent )
        self.setFocusPolicy( Qt.StrongFocus )
        self.setEditable( True )
        # add a filter model to filter matching items
        self.pFilterModel = QSortFilterProxyModel( self )
        self.pFilterModel.setFilterCaseSensitivity( Qt.CaseInsensitive )
        self.pFilterModel.setSourceModel(self.model())
        # add a completer, which uses the filter model
        self.completer = QCompleter(self.pFilterModel, self)
        # always show all completions
        self.completer.setCompletionMode( QCompleter.UnfilteredPopupCompletion )
        self.completer.setPopup( self.view() )
        self.setCompleter( self.completer )
        self.lineEdit().textEdited[unicode].connect( self.pFilterModel.setFilterFixedString )
        self.completer.activated.connect(self.on_completer_activated)

    def setModel( self, model ):
        super(ExtendedComboBox, self).setModel( model )
        self.pFilterModel.setSourceModel( model )
        self.completer.setModel(self.pFilterModel)

    def setModelColumn( self, column ):
        self.completer.setCompletionColumn( column )
        self.pFilterModel.setFilterKeyColumn( column )
        super(ExtendedComboBox, self).setModelColumn( column )

    def view( self ):
        return self.completer.popup()

    def index( self ):
        return self.currentIndex()

    def on_completer_activated(self, text):
        if text:
            index = self.findText(text)
            self.setCurrentIndex(index)
Пример #8
0
class SearchPanel(QComboBox):
    def __init__(self, model, parent=None, showTable=False):
        super(SearchPanel, self).__init__(parent)

        self.tabla = None
        self.setFocusPolicy(Qt.StrongFocus)
        self.setEditable(True)
        #        self.setModel( model )
        self.setEditable(True)
        self.completer = QCompleter(self)
        # always show all completions
        self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
        self.pFilterModel = QSortFilterProxyModel(self)
        self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.showTable = showTable

        if model != None:
            self.setModel(model)
        #        self.pFilterModel.setSourceModel( model );

        self.completer.setModel(self.pFilterModel)
        self.completerTable = SearchPanelView()
        self.completer.setPopup(self.completerTable)
        # Mostrar el Popup en forma de Tabla
        if self.showTable:
            self.tabla = SearchPanelView()
            self.setView(self.tabla)

        self.setCompleter(self.completer)

        self.setColumn(1)

        self.lineEdit().textEdited[unicode].connect(
            self.pFilterModel.setFilterFixedString if not showTable else self.pFilterModel.setFilterWildcard
        )

    def setModel(self, model):
        QComboBox.setModel(self, model)
        self.pFilterModel.setSourceModel(model)

    def setColumn(self, column):
        self.setModelColumn(1)
        self.completer.setCompletionColumn(column)
        self.pFilterModel.setFilterKeyColumn(column)
        self.setModelColumn(column)

    def view(self):
        return self.completer.popup()

    def data(self):
        return self.currentIndex()

    def index(self):
        return self.currentIndex()

    def setColumnHidden(self, col):
        self.completerTable.hiddenColumns.append(col)
        if self.showTable:
            self.tabla.hiddenColumns.append(col)

    def setMinimumWidth(self, width):
        self.completerTable.setMinimumWidth(width)
        if self.showTable:
            self.tabla.setMinimumWidth(width)
Пример #9
0
class MyMainWindow(QMainWindow):
    ' Main Window '

    def __init__(self, parent=None):
        ' Initialize QWidget inside MyMainWindow '
        super(MyMainWindow, self).__init__(parent)
        self.statusBar().showMessage(__doc__.title())
        self.setWindowTitle(__doc__)
        self.setMinimumSize(600, 800)
        self.setMaximumSize(2048, 1024)
        self.resize(1024, 800)
        self.setWindowIcon(QIcon.fromTheme("face-monkey"))
        if not A11Y:
            self.setStyleSheet('''QWidget{color:#fff;font-family:Oxygen}
            QWidget:item:hover, QWidget:item:selected {
                background-color: cyan; color: #000
            }
            QWidget:disabled { color: #404040; background-color: #323232 }
            QWidget:focus { border: 1px solid cyan }
            QPushButton {
                background-color: gray;
                padding: 3px; border: 1px solid gray; border-radius: 9px;
                margin: 0;font-size: 12px;
                padding-left: 5px; padding-right: 5px
            }
            QLineEdit, QTextEdit {
                background-color: #4a4a4a; border: 1px solid gray;
                border-radius: 0; font-size: 12px;
            }
            QPushButton:pressed { background-color: #323232 }
            QComboBox {
                background-color: #4a4a4a; padding-left: 9px;
                border: 1px solid gray; border-radius: 5px;
            }
            QComboBox:pressed { background-color: gray }
            QComboBox QAbstractItemView, QMenu {
                border: 1px solid #4a4a4a; background:grey;
                selection-background-color: cyan;
                selection-color: #000;
            }
            QSlider {
                padding: 3px; font-size: 8px; padding-left: 2px;
                padding-right: 2px; border: 5px solid #1e1e1e
            }
            QSlider::sub-page:vertical {
                background-color: QLinearGradient(spread:pad, x1:0, y1:0, x2:1,
                    y2:0.27, stop:0 rgba(255, 0, 0, 255),
                    stop:1 rgba(50, 0, 0, 200));
                border: 4px solid #1e1e1e; border-radius: 5px
            }
            QSlider::add-page:vertical {
                background-color: QLinearGradient(spread:pad, x1:0, y1:0, x2:1,
                    y2:0.27, stop:0 rgba(0, 255, 0, 255),
                    stop:1 rgba(0, 99, 0, 255));
                border: 4px solid #1e1e1e; border-radius: 5px;
            }
            QSlider::handle:vertical {
                background-color: QLinearGradient(spread:pad, x1:0, y1:0, x2:1,
                    y2:0.273, stop:0 rgba(0, 0, 0, 255), stop:1 gray);
                height: 5px; border: 1px dotted #fff; text-align: center;
                border-top-left-radius: 2px; border-bottom-left-radius: 2px;
                border-top-right-radius: 2px; border-bottom-right-radius 2px;
                margin-left: 2px; margin-right: 2px;
            }
            QSlider::handle:vertical:hover { border: 1px solid cyan }
            QSlider::sub-page:vertical:disabled {
                background: #bbb; border-color: #999;
            }
            QSlider::add-page:vertical:disabled {
                background: #eee; border-color: #999;
            }
            QSlider::handle:vertical:disabled {
                background: #eee; border: 1px solid #aaa; border-radius: 4px;
            }
            QToolBar, QStatusBar, QDockWidget::title{background-color:#323232;}
            QToolBar::handle,
            QToolBar::handle:vertical, QToolBar::handle:horizontal {
                border: 1px solid gray; border-radius: 9px; width: 19px;
                height: 19px; margin: 0.5px
            }
            QGroupBox {
                border: 1px solid gray; border-radius: 9px; padding-top: 9px;
            }
            QStatusBar, QToolBar::separator:horizontal,
            QToolBar::separator:vertical {color:gray}
            QScrollBar:vertical{
                background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0,
                    stop: 0 #212121,stop: 1.0 #323232);
                width: 10px;
            }
            QScrollBar:horizontal{
                background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                    stop: 0 #212121,stop: 1.0 #323232);
                height: 10px;
            }
            QScrollBar::handle:vertical{
                padding: 2px;
                min-height: 50px;
                background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0,
                    stop: 0 #585858,stop: 1.0 #404040);
                border-radius: 5px;
                border: 1px solid #191919;
            }
            QScrollBar::handle:horizontal{
                padding: 2px;
                min-width: 50px;
                background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                    stop: 0 #585858,stop: 1.0 #404040);
                border-radius: 5px;
                border: 1px solid #191919;
            }
            QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical,
            QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical,
            QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal,
            QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {
                background: none; border: none;
            }
            QDockWidget::close-button, QDockWidget::float-button {
                border: 1px solid gray;
                border-radius: 3px;
                background: darkgray;
            }''')

        self.process = QProcess()
        self.process.readyReadStandardOutput.connect(self.read_output)
        self.process.readyReadStandardError.connect(self.read_errors)
        self.process.finished.connect(self._process_finished)
        self.process.error.connect(self._process_finished)

        self.group0, self.group1 = QGroupBox("Options"), QGroupBox("Paths")
        self.group2 = QGroupBox("Nodes")
        self.group3 = QGroupBox("Python Code")
        self.group4, self.group5 = QGroupBox("Logs"), QGroupBox("Backend")
        g0grid, g1vlay = QGridLayout(self.group0), QVBoxLayout(self.group1)
        g5vlay = QVBoxLayout(self.group5)

        self.treeview_nodes, self.textedit_source = QTextEdit(), QTextEdit()
        self.dock1, self.dock2 = QDockWidget(), QDockWidget()
        self.output, self.dock3 = QTextEdit(), QDockWidget()
        self.treeview_nodes.setAutoFormatting(QTextEdit.AutoAll)
        self.treeview_nodes.setWordWrapMode(QTextOption.NoWrap)
        self.dock1.setWidget(self.treeview_nodes)
        self.dock2.setWidget(self.textedit_source)
        self.dock3.setWidget(self.output)
        self.dock1.setWindowTitle("Tree")
        self.dock2.setWindowTitle("Sources")
        self.dock3.setWindowTitle("STDOutput")
        featur = QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable
        self.dock1.setFeatures(featur)
        self.dock2.setFeatures(featur)
        self.dock3.setFeatures(featur)
        QVBoxLayout(self.group2).addWidget(self.dock1)
        QVBoxLayout(self.group3).addWidget(self.dock2)
        QVBoxLayout(self.group4).addWidget(self.dock3)
        self.slider1, self.slider2 = QSlider(), QSlider()
        g0grid.addWidget(self.slider1, 0, 0)
        g0grid.addWidget(QLabel('Use Debug'), 0, 1)
        self.slider2.setValue(1)
        g0grid.addWidget(self.slider2, 1, 0)
        g0grid.addWidget(QLabel('Use verbose'), 1, 1)

        self.slider3, self.slider4 = QSlider(), QSlider()
        self.slider3.setValue(1)
        g0grid.addWidget(self.slider3, 2, 0)
        g0grid.addWidget(QLabel('Show compiling progress'), 2, 1)
        self.slider4.setValue(1)
        g0grid.addWidget(self.slider4, 3, 0)
        g0grid.addWidget(QLabel('Show Scons building debug'), 3, 1)

        self.slider5, self.slider6 = QSlider(), QSlider()
        g0grid.addWidget(self.slider5, 4, 0)
        g0grid.addWidget(QLabel('Keep debug unstriped binary'), 4, 1)
        g0grid.addWidget(self.slider6, 5, 0)
        g0grid.addWidget(QLabel('Traced execution outputs'), 5, 1)

        self.slider7, self.slider8 = QSlider(), QSlider()
        self.slider7.setValue(1)
        g0grid.addWidget(self.slider7, 6, 0)
        g0grid.addWidget(QLabel('Remove the build folder'), 6, 1)
        g0grid.addWidget(self.slider8, 7, 0)
        g0grid.addWidget(QLabel('No Python Optimizations'), 7, 1)

        self.slider9, self.slider10 = QSlider(), QSlider()
        g0grid.addWidget(self.slider9, 8, 0)
        g0grid.addWidget(QLabel('No Statements line numbers'), 8, 1)
        g0grid.addWidget(self.slider10, 9, 0)
        g0grid.addWidget(QLabel('Execute the output binary'), 9, 1)

        self.slider11, self.slider12 = QSlider(), QSlider()
        g0grid.addWidget(self.slider11, 10, 0)
        g0grid.addWidget(QLabel('Warning detected implicit exceptions'), 10, 1)
        g0grid.addWidget(self.slider12, 11, 0)
        g0grid.addWidget(QLabel('Keep the PYTHONPATH, do not Reset it'), 11, 1)

        self.slider13 = QSlider()
        g0grid.addWidget(self.slider13, 12, 0)
        g0grid.addWidget(QLabel('Enhance compile, CPython incompatible'), 12,
                         1)

        self.slider1a, self.slider2a = QSlider(), QSlider()
        g0grid.addWidget(self.slider1a, 0, 2)
        g0grid.addWidget(QLabel('Descendent Recursive Compile'), 0, 3)
        self.slider2a.setValue(1)
        g0grid.addWidget(self.slider2a, 1, 2)
        g0grid.addWidget(QLabel('Force non recursive compile'), 1, 3)

        self.slider3a, self.slider4a = QSlider(), QSlider()
        g0grid.addWidget(self.slider3a, 2, 2)
        g0grid.addWidget(QLabel('STD Lib Recursive Compile'), 2, 3)
        g0grid.addWidget(self.slider4a, 3, 2)
        g0grid.addWidget(QLabel('Enforce the use of Clang'), 3, 3)

        self.slider5a, self.slider6a = QSlider(), QSlider()
        self.slider5a.setValue(1)
        g0grid.addWidget(self.slider5a, 4, 2)
        g0grid.addWidget(QLabel('Use G++ link time optimizations'), 4, 3)
        g0grid.addWidget(self.slider6a, 5, 2)
        g0grid.addWidget(QLabel('Disable the console window'), 5, 3)

        self.slider7a, self.slider8a = QSlider(), QSlider()
        g0grid.addWidget(self.slider7a, 6, 2)
        g0grid.addWidget(QLabel('Force compile for MS Windows'), 6, 3)
        g0grid.addWidget(self.slider8a, 7, 2)
        g0grid.addWidget(QLabel('Use Python Debug versions'), 7, 3)

        self.slider9a, self.slider10a = QSlider(), QSlider()
        self.slider9a.setValue(1)
        g0grid.addWidget(self.slider9a, 8, 2)
        g0grid.addWidget(QLabel('Create standalone executable'), 8, 3)
        g0grid.addWidget(self.slider10a, 9, 2)
        g0grid.addWidget(QLabel('Enable Standalone mode build'), 9, 3)

        self.slider11a, self.slider12a = QSlider(), QSlider()
        g0grid.addWidget(self.slider11a, 10, 2)
        g0grid.addWidget(QLabel('Make module executable instead of app'), 10,
                         3)
        g0grid.addWidget(self.slider12a, 11, 2)
        g0grid.addWidget(QLabel('No froze module of stdlib as bytecode'), 11,
                         3)

        self.slider13a = QSlider()
        g0grid.addWidget(self.slider13a, 12, 2)
        g0grid.addWidget(QLabel('Force use of MinGW on MS Windows'), 12, 3)

        for each_widget in (self.slider1, self.slider2, self.slider3,
                            self.slider4, self.slider5, self.slider6,
                            self.slider7, self.slider8, self.slider9,
                            self.slider10, self.slider11, self.slider12,
                            self.slider13, self.slider1a, self.slider2a,
                            self.slider3a, self.slider4a, self.slider5a,
                            self.slider6a, self.slider7a, self.slider8a,
                            self.slider9a, self.slider10a, self.slider11a,
                            self.slider12a, self.slider13a):
            each_widget.setRange(0, 1)
            each_widget.setCursor(QCursor(Qt.OpenHandCursor))
            each_widget.setTickInterval(1)
            each_widget.TickPosition(QSlider.TicksBothSides)

        self.combo1 = QComboBox()
        self.combo1.addItems(('2.7', '2.6', '3.2', '3.3'))
        g5vlay.addWidget(QLabel('Python Version'))
        g5vlay.addWidget(self.combo1)
        self.combo2 = QComboBox()
        self.combo2.addItems(('Default', 'Low', 'High'))
        g5vlay.addWidget(QLabel('CPU priority'))
        g5vlay.addWidget(self.combo2)
        self.combo3 = QComboBox()
        self.combo3.addItems(('1', '2', '3', '4', '5', '6', '7', '8', '9'))
        g5vlay.addWidget(QLabel('MultiProcessing Workers'))
        g5vlay.addWidget(self.combo3)

        self.outdir = QLineEdit()
        self.outdir.setStyleSheet("QLineEdit{margin-left:25px}")
        self.clearButton = QToolButton(self.outdir)
        self.clearButton.setIcon(QIcon.fromTheme("edit-clear"))
        self.clearButton.setIconSize(QSize(25, 25))
        self.clearButton.setStyleSheet("QToolButton{border:none}")
        self.clearButton.hide()
        self.clearButton.clicked.connect(self.outdir.clear)
        self.outdir.textChanged.connect(
            lambda: self.clearButton.setVisible(True))
        self.clearButton.clicked.connect(
            lambda: self.clearButton.setVisible(False))
        self.outdir.setPlaceholderText('Output Directory')
        if path.isfile('.nuitka-output-dir.txt'):
            self.outdir.setText(open('.nuitka-output-dir.txt', 'r').read())
        else:
            self.outdir.setText(path.expanduser("~"))
        self.completer, self.dirs = QCompleter(self), QDirModel(self)
        self.dirs.setFilter(QDir.Dirs | QDir.NoDotAndDotDot)
        self.completer.setModel(self.dirs)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setCompletionMode(QCompleter.PopupCompletion)
        self.completer.popup().setStyleSheet(
            """border:1px solid #4a4a4a;background:grey;
            selection-background-color:cyan;selection-color:#000""")
        self.completer.popup().setVerticalScrollBarPolicy(
            Qt.ScrollBarAlwaysOff)
        self.outdir.setCompleter(self.completer)

        self.btn1 = QPushButton(QIcon.fromTheme("document-open"),
                                'Open' if IS_WIN else '')
        self.btn1.clicked.connect(
            lambda: open('.nuitka-output-dir.txt', 'w').write(
                str(
                    QFileDialog.getExistingDirectory(
                        None, 'Open Output Directory', path.expanduser("~")))))
        self.btn1.released.connect(lambda: self.outdir.setText(
            open('.nuitka-output-dir.txt', 'r').read()))
        g1vlay.addWidget(QLabel('Output Directory'))
        g1vlay.addWidget(self.outdir)
        g1vlay.addWidget(self.btn1)

        self.target = QLineEdit()
        self.target.setStyleSheet("QLineEdit{margin-left:25px}")
        self.clearButton2 = QToolButton(self.target)
        self.clearButton2.setIcon(QIcon.fromTheme("edit-clear"))
        self.clearButton2.setIconSize(QSize(25, 25))
        self.clearButton2.setStyleSheet("QToolButton{border:none}")
        self.clearButton2.hide()
        self.clearButton2.clicked.connect(self.target.clear)
        self.target.textChanged.connect(
            lambda: self.clearButton2.setVisible(True))
        self.clearButton2.clicked.connect(
            lambda: self.clearButton2.setVisible(False))
        self.target.setPlaceholderText('Target Python App to Binary Compile')
        self.target.setCompleter(self.completer)
        self.btn2 = QPushButton(QIcon.fromTheme("document-open"),
                                'Open' if IS_WIN else '')
        self.btn2.clicked.connect(lambda: self.target.setText(
            str(
                QFileDialog.getOpenFileName(
                    None, "Open", path.expanduser("~"), ';;'.join([
                        '{}(*.{})'.format(e.upper(), e)
                        for e in ('py', 'pyw', '*')
                    ])))))
        g1vlay.addWidget(QLabel('Input File'))
        g1vlay.addWidget(self.target)
        g1vlay.addWidget(self.btn2)

        self.icon, self.icon_label = QLineEdit(), QLabel('Icon File')
        self.icon.setStyleSheet("QLineEdit{margin-left:25px}")
        self.clearButton3 = QToolButton(self.icon)
        self.clearButton3.setIcon(QIcon.fromTheme("edit-clear"))
        self.clearButton3.setIconSize(QSize(25, 25))
        self.clearButton3.setStyleSheet("QToolButton{border:none}")
        self.clearButton3.hide()
        self.clearButton3.clicked.connect(self.icon.clear)
        self.icon.textChanged.connect(
            lambda: self.clearButton3.setVisible(True))
        self.clearButton3.clicked.connect(
            lambda: self.clearButton3.setVisible(False))
        self.icon.setPlaceholderText('Path to Icon file for your App')
        self.icon.setCompleter(self.completer)
        self.btn3 = QPushButton(QIcon.fromTheme("document-open"),
                                'Open' if IS_WIN else '')
        self.btn3.clicked.connect(lambda: self.icon.setText(
            str(
                QFileDialog.getOpenFileName(
                    None, "Open", path.expanduser("~"), ';;'.join([
                        '{}(*.{})'.format(e.upper(), e)
                        for e in ('ico', 'png', 'bmp', 'svg', '*')
                    ])))))
        g1vlay.addWidget(self.icon_label)
        g1vlay.addWidget(self.icon)
        g1vlay.addWidget(self.btn3)

        # Menu Bar inicialization and detail definitions
        menu_salir = QAction(QIcon.fromTheme("application-exit"), 'Quit', self)
        menu_salir.setStatusTip('Quit')
        menu_salir.triggered.connect(exit)
        menu_minimize = QAction(QIcon.fromTheme("go-down"), 'Minimize', self)
        menu_minimize.setStatusTip('Minimize')
        menu_minimize.triggered.connect(lambda: self.showMinimized())
        menu_qt = QAction(QIcon.fromTheme("help-about"), 'About Qt', self)
        menu_qt.setStatusTip('About Qt...')
        menu_qt.triggered.connect(lambda: QMessageBox.aboutQt(self))
        menu_dev = QAction(QIcon.fromTheme("applications-development"),
                           'Developer Manual PDF', self)
        menu_dev.setStatusTip('Open Nuitka Developer Manual PDF...')
        menu_dev.triggered.connect(lambda: call(
            OPEN + '/usr/share/doc/nuitka/Developer_Manual.pdf.gz', shell=True)
                                   )
        menu_usr = QAction(QIcon.fromTheme("help-contents"), 'User Docs', self)
        menu_usr.setStatusTip('Open Nuitka End User Manual PDF...')
        menu_usr.triggered.connect(lambda: call(
            OPEN + '/usr/share/doc/nuitka/README.pdf.gz', shell=True))
        menu_odoc = QAction(QIcon.fromTheme("help-browser"), 'OnLine Doc',
                            self)
        menu_odoc.setStatusTip('Open Nuitka on line Documentation pages...')
        menu_odoc.triggered.connect(
            lambda: open_new_tab('http://nuitka.net/doc/user-manual.html'))
        menu_man = QAction(QIcon.fromTheme("utilities-terminal"), 'Man', self)
        menu_man.setStatusTip('Open Nuitka technical command line Man Pages..')
        menu_man.triggered.connect(
            lambda: call('xterm -e "man nuitka"', shell=True))
        menu_tra = QAction(QIcon.fromTheme("applications-development"),
                           'View Nuitka-GUI Source Code', self)
        menu_tra.setStatusTip('View, study, edit Nuitka-GUI Libre Source Code')
        menu_tra.triggered.connect(lambda: call(OPEN + __file__, shell=True))
        menu_foo = QAction(QIcon.fromTheme("folder"), 'Open Output Dir', self)
        menu_foo.setStatusTip('Open the actual Output Directory location...')
        menu_foo.triggered.connect(
            lambda: call(OPEN + str(self.outdir.text()), shell=True))
        menu_pic = QAction(QIcon.fromTheme("camera-photo"), 'Screenshot', self)
        menu_pic.setStatusTip('Take a Screenshot for Documentation purposes..')
        menu_pic.triggered.connect(
            lambda: QPixmap.grabWindow(QApplication.desktop().winId()).save(
                QFileDialog.getSaveFileName(None, "Save", path.expanduser("~"),
                                            'PNG(*.png)', 'png')))
        menu_don = QAction(QIcon.fromTheme("emblem-favorite"), 'Help Nuitka',
                           self)
        menu_don.setStatusTip('Help the Nuitka Open Source Libre Free Project')
        menu_don.triggered.connect(
            lambda: open_new_tab('http://nuitka.net/pages/donations.html'))

        # movable draggable toolbar
        self.toolbar = QToolBar(self)
        self.toolbar.setIconSize(QSize(16, 16))
        self.toolbar.toggleViewAction().setText("Show/Hide Toolbar")
        l_spacer, r_spacer = QWidget(self), QWidget(self)
        l_spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        r_spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.toolbar.addWidget(l_spacer)
        self.toolbar.addSeparator()
        self.toolbar.addActions((menu_salir, menu_minimize, menu_qt, menu_odoc,
                                 menu_foo, menu_pic, menu_don))
        if not IS_WIN:
            self.toolbar.addActions((menu_man, menu_dev, menu_tra, menu_usr))
        self.toolbar.addSeparator()
        self.toolbar.addWidget(r_spacer)
        self.addToolBar(Qt.BottomToolBarArea, self.toolbar)

        # Bottom Buttons Bar
        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Ok
                                          | QDialogButtonBox.Close)
        self.buttonBox.rejected.connect(exit)
        self.buttonBox.accepted.connect(self.run)

        self.guimode = QComboBox()
        self.guimode.addItems(('Full UX / UI', 'Simple UX / UI'))
        self.guimode.setStyleSheet(
            """QComboBox{background:transparent;border:0;
            margin-left:25px;color:gray;text-decoration:underline}""")
        self.guimode.currentIndexChanged.connect(self.set_guimode)

        container = QWidget()
        container_layout = QGridLayout(container)  # Y, X
        container_layout.addWidget(self.guimode, 0, 1)
        container_layout.addWidget(self.group2, 1, 0)
        container_layout.addWidget(self.group3, 2, 0)
        container_layout.addWidget(self.group0, 1, 1)
        container_layout.addWidget(self.group1, 2, 1)
        container_layout.addWidget(self.group4, 1, 2)
        container_layout.addWidget(self.group5, 2, 2)
        container_layout.addWidget(self.buttonBox, 3, 1)
        self.setCentralWidget(container)
        # Paleta de colores para pintar transparente
        if not A11Y:
            palette = self.palette()
            palette.setBrush(QPalette.Base, Qt.transparent)
            self.setPalette(palette)
            self.setAttribute(Qt.WA_OpaquePaintEvent, False)

    def get_fake_tree(self, target):
        """Return the fake tree."""
        try:
            fake_tree = check_output(NUITKA + ' --dump-xml ' + target,
                                     shell=True)
        except:
            fake_tree = "ERROR: Failed to get Tree Dump."
        finally:
            return fake_tree.strip()

    def run(self):
        ' run the actual backend process '
        self.treeview_nodes.clear()
        self.textedit_source.clear()
        self.output.clear()
        self.statusBar().showMessage('WAIT!, Working...')
        target = str(self.target.text()).strip()
        self.treeview_nodes.setText(self.get_fake_tree(target))
        self.textedit_source.setText(open(target, "r").read().strip())
        conditional_1 = sys.platform.startswith('linux')
        conditional_2 = self.combo3.currentIndex() != 2
        command_to_run_nuitka = " ".join(
            ('chrt -i 0' if conditional_1 and conditional_2 else '', NUITKA,
             '--debug' if self.slider1.value() else '',
             '--verbose' if self.slider2.value() else '',
             '--show-progress' if self.slider3.value() else '',
             '--show-scons --show-modules' if self.slider4.value() else '',
             '--unstriped' if self.slider5.value() else '',
             '--trace-execution' if self.slider6.value() else '',
             '--remove-output' if self.slider7.value() else '',
             '--no-optimization' if self.slider8.value() else '',
             '--code-gen-no-statement-lines' if self.slider9.value() else '',
             '--execute' if self.slider10.value() else '',
             '--recurse-all' if self.slider1a.value() else '',
             '--recurse-none' if self.slider2a.value() else '',
             '--recurse-stdlib' if self.slider3a.value() else '',
             '--clang' if self.slider4a.value() else '',
             '--lto' if self.slider5a.value() else '',
             '--windows-disable-console' if self.slider6a.value() else '',
             '--windows-target' if self.slider7a.value() else '',
             '--python-debug' if self.slider8a.value() else '',
             '--exe' if self.slider9a.value() else '',
             '--standalone' if self.slider10a.value() else '',
             '--module' if self.slider11a.value() else '',
             '--nofreeze-stdlib' if self.slider12a.value() else '',
             '--mingw' if self.slider13a.value() else '',
             '--warn-implicit-exceptions' if self.slider11.value() else '',
             '--execute-with-pythonpath' if self.slider12.value() else '',
             '--enhanced' if self.slider13.value() else '',
             '--icon="{}"'.format(self.icon.text())
             if self.icon.text() else '', '--python-version={}'.format(
                 self.combo1.currentText()), '--jobs={}'.format(
                     self.combo3.currentText()), '--output-dir="{}"'.format(
                         self.outdir.text()), "{}".format(target)))
        if DEBUG:
            print(command_to_run_nuitka)
        self.process.start(command_to_run_nuitka)
        if not self.process.waitForStarted() and not IS_WIN:
            return  # ERROR !
        self.statusBar().showMessage(__doc__.title())

    def _process_finished(self):
        """finished sucessfully"""
        self.output.setFocus()
        self.output.selectAll()

    def read_output(self):
        """Read and append output to the log"""
        self.output.append(str(self.process.readAllStandardOutput()))

    def read_errors(self):
        """Read and append errors to the log"""
        self.output.append(str(self.process.readAllStandardError()))

    def paintEvent(self, event):
        """Paint semi-transparent background,animated pattern,background text"""
        if not A11Y:
            p = QPainter(self)
            p.setRenderHint(QPainter.Antialiasing)
            p.setRenderHint(QPainter.TextAntialiasing)
            p.setRenderHint(QPainter.HighQualityAntialiasing)
            p.fillRect(event.rect(), Qt.transparent)
            # animated random dots background pattern
            for i in range(4096):
                x = randint(25, self.size().width() - 25)
                y = randint(25, self.size().height() - 25)
                # p.setPen(QPen(QColor(randint(9, 255), 255, 255), 1))
                p.drawPoint(x, y)
            p.setPen(QPen(Qt.white, 1))
            p.rotate(40)
            p.setFont(QFont('Ubuntu', 250))
            p.drawText(200, 99, "Nuitka")
            p.rotate(-40)
            p.setPen(Qt.NoPen)
            p.setBrush(QColor(0, 0, 0))
            p.setOpacity(0.8)
            p.drawRoundedRect(self.rect(), 9, 9)
            p.end()

    def set_guimode(self):
        """Switch between simple and full UX"""
        for widget in (self.group2, self.group3, self.group4, self.group5,
                       self.icon, self.icon_label, self.btn3, self.toolbar,
                       self.statusBar()):
            widget.hide() if self.guimode.currentIndex() else widget.show()
Пример #10
0
class IdePanel(QPlainTextEdit):
    def __init__(self):
        QPlainTextEdit.__init__(self)
        self.setWordWrapMode(QTextOption.NoWrap)
        self.setFont(QFont("monospace", 10))
        self.setCursorWidth(2)
        self.installEventFilter(self)

        self.cursorPositionChanged.connect(self.showHelp)

        self.completer = QCompleter(self)
        self.completer.setWidget(self)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.activated.connect(self.insertCompletion)

        auto_complete = QShortcut(QKeySequence("Ctrl+Space"), self)
        auto_complete.activated.connect(self.activateCompleter)

        copy_line = QShortcut(QKeySequence("Ctrl+D"), self)
        copy_line.activated.connect(self.duplicateLine)

        select_fragment = QShortcut(QKeySequence("Ctrl+J"), self)
        select_fragment.activated.connect(self.selectFragment)

    def showHelp(self):
        text_cursor = self.textCursor()
        user_data = text_cursor.block().userData()

        if user_data is not None:
            configuration_line = user_data.configuration_line

            if configuration_line.keyword().hasKeywordDefinition():
                HelpCenter.getHelpCenter("ERT").setHelpMessageLink("config/" + configuration_line.documentationLink())

    def getText(self):
        return self.document().toPlainText()

    def eventFilter(self, qobject, qevent):
        if qobject == self and qevent.type() == QEvent.ToolTip:
            text_cursor = self.cursorForPosition(qevent.pos())
            pos = text_cursor.positionInBlock()

            user_data = text_cursor.block().userData()
            if user_data is not None:
                #: :type: ConfigurationLine
                configuration_line = user_data.configuration_line
                # if configuration_line.keyword().hasKeywordDefinition():
                #     print(configuration_line.keyword().keywordDefinition().documentation)

                if pos in configuration_line.keyword():
                    self.setToolTip(configuration_line.validationStatusForToken(configuration_line.keyword()).message())
                else:
                    for argument in configuration_line.arguments():
                        if pos in argument:
                            self.setToolTip(configuration_line.validationStatusForToken(argument).message())

            else:
                self.setToolTip("")

        return QPlainTextEdit.eventFilter(self, qobject, qevent)

    def activateCompleter(self):
        text_cursor = self.textCursor()
        block = self.document().findBlock(text_cursor.position())
        position_in_block = text_cursor.positionInBlock()

        self.selectWordUnderCursor(text_cursor)
        word = unicode(text_cursor.selectedText())

        user_data = block.userData()

        self.completer.setCompletionPrefix(word)

        show_completer = False
        if user_data is None:
            self.completer.setModel(QStringListModel(self.handler_names))
            show_completer = True

        else:
            keyword = user_data.keyword
            options = keyword.handler.parameterOptions(keyword, word, position_in_block)

            if len(options) == 1:
                self.insertCompletion(options[0])
            elif len(options) > 1:
                self.completer.setModel(QStringListModel(options))
                if self.completer.completionCount() == 1:
                    self.insertCompletion(self.completer.currentCompletion())
                else:
                    show_completer = True

        if show_completer:
            rect = self.cursorRect(text_cursor)
            rect.setWidth(
                self.completer.popup().sizeHintForColumn(0)
                + self.completer.popup().verticalScrollBar().sizeHint().width()
            )
            self.completer.complete(rect)

    def keyPressEvent(self, qkeyevent):
        if self.completer.popup().isVisible():
            dead_keys = [Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape, Qt.Key_Tab, Qt.Key_Backtab]
            if qkeyevent.key() in dead_keys:
                qkeyevent.ignore()
                return

        if qkeyevent.modifiers() == Qt.ShiftModifier:
            if qkeyevent.key() & Qt.Key_Delete == Qt.Key_Delete:
                self.deleteLine()

        QPlainTextEdit.keyPressEvent(self, qkeyevent)

    def insertCompletion(self, string):
        text_cursor = self.textCursor()
        self.selectWordUnderCursor(text_cursor)
        text_cursor.insertText(string)

    def isCursorInSpace(self):
        text_cursor = self.textCursor()
        if text_cursor.positionInBlock() > 0:
            text_cursor.movePosition(QTextCursor.Left, QTextCursor.MoveAnchor)
            text_cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor)

        if text_cursor.positionInBlock() < text_cursor.block().length() - 1:
            text_cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor)

        if unicode(text_cursor.selectedText()).strip() == "":
            return True

        return False

    def selectWordUnderCursor(self, text_cursor):
        if not self.isCursorInSpace():
            # text_cursor.select(QTextCursor.WordUnderCursor)

            # pattern = "[\s|\v|\f|\n|\r|\t|\xe2\x80\xa8|\xe2\x80\xa9]"
            # pattern = "[\\s|\\xe2\\x80\\xa9|\\xe2\\x80\\xa8]"

            block_start = 0
            block_end = text_cursor.block().length()

            cursor_pos = text_cursor.positionInBlock()
            pos = cursor_pos
            pattern = u"[\s\u2029\u2028]"
            while pos >= block_start:
                text_cursor.movePosition(QTextCursor.Left, QTextCursor.KeepAnchor)
                text = text_cursor.selectedText()
                if re.search(pattern, text):
                    break
                pos -= 1

            text_cursor.movePosition(QTextCursor.Right, QTextCursor.MoveAnchor)

            while pos < block_end:
                text_cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor)
                text = text_cursor.selectedText()
                if re.search(pattern, text):
                    break
                pos += 1

            text_cursor.movePosition(QTextCursor.Left, QTextCursor.KeepAnchor)

            # pattern = "[\\s]"
            # start = self.document().find(QRegExp(pattern), text_cursor, QTextDocument.FindBackward | QTextDocument.FindCaseSensitively)
            # end = self.document().find(QRegExp(pattern), text_cursor, QTextDocument.FindCaseSensitively)
            # block_end_pos = text_cursor.block().position() + text_cursor.block().length()
            #
            # text_cursor.setPosition(start.position(), QTextCursor.MoveAnchor)
            # # text_cursor.setPosition(min(block_end_pos, end.position() - 1), QTextCursor.KeepAnchor)
            # text_cursor.setPosition(end.position() - 1, QTextCursor.KeepAnchor)

    def deleteLine(self):
        text_cursor = self.textCursor()
        text_cursor.beginEditBlock()
        text_cursor.select(QTextCursor.LineUnderCursor)
        text_cursor.removeSelectedText()
        text_cursor.deletePreviousChar()

        text_cursor.movePosition(QTextCursor.NextBlock)
        text_cursor.movePosition(QTextCursor.StartOfLine)
        self.setTextCursor(text_cursor)
        text_cursor.endEditBlock()

    def duplicateLine(self):
        text_cursor = self.textCursor()
        text_cursor.beginEditBlock()
        text_cursor.select(QTextCursor.LineUnderCursor)
        text = text_cursor.selectedText()
        text_cursor.movePosition(QTextCursor.EndOfLine)
        text_cursor.insertBlock()
        text_cursor.insertText(text)
        text_cursor.endEditBlock()

    def selectFragment(self):
        text_cursor = self.textCursor()
        self.selectWordUnderCursor(text_cursor)
        self.setTextCursor(text_cursor)
Пример #11
0
class ParentAction(object):
    def __init__(self, iface, settings, controller, plugin_dir):
        """ Class constructor """

        # Initialize instance attributes
        self.giswater_version = "3.1"
        self.iface = iface
        self.canvas = self.iface.mapCanvas()
        self.settings = settings
        self.controller = controller
        self.plugin_dir = plugin_dir
        self.dao = self.controller.dao
        self.schema_name = self.controller.schema_name
        self.project_type = None
        self.file_gsw = None
        self.gsw_settings = None

        # Get files to execute giswater jar (only in Windows)
        if 'nt' in sys.builtin_module_names:
            self.plugin_version = self.get_plugin_version()
            self.java_exe = self.get_java_exe()
            (self.giswater_file_path,
             self.giswater_build_version) = self.get_giswater_jar()

    def set_controller(self, controller):
        """ Set controller class """

        self.controller = controller
        self.schema_name = self.controller.schema_name

    def get_plugin_version(self):
        """ Get plugin version from metadata.txt file """

        # Check if metadata file exists
        metadata_file = os.path.join(self.plugin_dir, 'metadata.txt')
        if not os.path.exists(metadata_file):
            message = "Metadata file not found" + metadata_file
            self.controller.show_warning(message, parameter=metadata_file)
            return None

        metadata = ConfigParser.ConfigParser()
        metadata.read(metadata_file)
        plugin_version = metadata.get('general', 'version')
        if plugin_version is None:
            message = "Plugin version not found"
            self.controller.show_warning(message)

        return plugin_version

    def get_giswater_jar(self):
        """ Get executable Giswater file and build version from windows registry """

        reg_hkey = "HKEY_LOCAL_MACHINE"
        reg_path = "SOFTWARE\\Giswater\\" + self.giswater_version
        reg_name = "InstallFolder"
        giswater_folder = utils_giswater.get_reg(reg_hkey, reg_path, reg_name)
        if giswater_folder is None:
            message = "Cannot get giswater folder from windows registry"
            self.controller.log_info(message, parameter=reg_path)
            return (None, None)

        # Check if giswater folder exists
        if not os.path.exists(giswater_folder):
            message = "Giswater folder not found"
            self.controller.log_info(message, parameter=giswater_folder)
            return (None, None)

        # Check if giswater executable file file exists
        giswater_file_path = giswater_folder + "\giswater.jar"
        if not os.path.exists(giswater_file_path):
            message = "Giswater executable file not found"
            self.controller.log_info(message, parameter=giswater_file_path)
            return (None, None)

        # Get giswater major version
        reg_name = "MajorVersion"
        major_version = utils_giswater.get_reg(reg_hkey, reg_path, reg_name)
        if major_version is None:
            message = "Cannot get giswater major version from windows registry"
            self.controller.log_info(message, parameter=reg_path)
            return (giswater_file_path, None)

        # Get giswater minor version
        reg_name = "MinorVersion"
        minor_version = utils_giswater.get_reg(reg_hkey, reg_path, reg_name)
        if minor_version is None:
            message = "Cannot get giswater minor version from windows registry" + reg_path
            self.controller.log_info(message, parameter=reg_path)
            return (giswater_file_path, None)

        # Get giswater build version
        reg_name = "BuildVersion"
        build_version = utils_giswater.get_reg(reg_hkey, reg_path, reg_name)
        if build_version is None:
            message = "Cannot get giswater build version from windows registry"
            self.controller.log_info(message, parameter=reg_path)
            return (giswater_file_path, None)

        giswater_build_version = major_version + '.' + minor_version + '.' + build_version

        return (giswater_file_path, giswater_build_version)

    def get_java_exe(self):
        """ Get executable Java file from windows registry """

        reg_hkey = "HKEY_LOCAL_MACHINE"
        reg_path = "SOFTWARE\\JavaSoft\\Java Runtime Environment"
        reg_name = "CurrentVersion"
        java_version = utils_giswater.get_reg(reg_hkey, reg_path, reg_name)

        # Check if java version exists (64 bits)
        if java_version is None:
            reg_path = "SOFTWARE\\Wow6432Node\\JavaSoft\\Java Runtime Environment"
            java_version = utils_giswater.get_reg(reg_hkey, reg_path, reg_name)
            # Check if java version exists (32 bits)
            if java_version is None:
                message = "Cannot get current Java version from windows registry"
                self.controller.log_info(message, parameter=reg_path)
                return None

        # Get java folder
        reg_path += "\\" + java_version
        reg_name = "JavaHome"
        java_folder = utils_giswater.get_reg(reg_hkey, reg_path, reg_name)
        if java_folder is None:
            message = "Cannot get Java folder from windows registry"
            self.controller.log_info(message, parameter=reg_path)
            return None

        # Check if java folder exists
        if not os.path.exists(java_folder):
            message = "Java folder not found"
            self.controller.log_info(message, parameter=java_folder)
            return None

        # Check if java executable file exists
        java_exe = java_folder + "/bin/java.exe"
        if not os.path.exists(java_exe):
            message = "Java executable file not found"
            self.controller.log_info(message, parameter=java_exe)
            return None

        return java_exe

    def execute_giswater(self, parameter):
        """ Executes giswater with selected parameter """

        if self.giswater_file_path is None or self.java_exe is None:
            return

        # Save database connection parameters into GSW file
        self.save_database_parameters()

        # Check if gsw file exists. If not giswater will open with the last .gsw file
        if self.file_gsw is None:
            self.file_gsw = ""
        if self.file_gsw:
            if self.file_gsw != "" and not os.path.exists(self.file_gsw):
                message = "GSW file not found"
                self.controller.show_info(message, parameter=self.file_gsw)
                self.file_gsw = ""

        # Start program
        aux = '"' + self.giswater_file_path + '"'
        if self.file_gsw != "":
            aux += ' "' + self.file_gsw + '"'
            program = [
                self.java_exe, "-jar", self.giswater_file_path, self.file_gsw,
                parameter
            ]
        else:
            program = [
                self.java_exe, "-jar", self.giswater_file_path, "", parameter
            ]

        self.controller.start_program(program)

        # Compare Java and Plugin versions
        if self.plugin_version <> self.giswater_build_version:
            msg = ("Giswater and plugin versions are different. "
                   "Giswater version: " + self.giswater_build_version + ""
                   " - Plugin version: " + self.plugin_version)
            self.controller.show_info(msg, 10)
        # Show information message
        else:
            message = "Executing..."
            self.controller.show_info(message, parameter=aux)

    def set_java_settings(self, show_warning=True):

        # Get giswater properties file
        users_home = os.path.expanduser("~")
        filename = "giswater_" + self.giswater_version + ".properties"
        java_properties_path = users_home + os.sep + "giswater" + os.sep + "config" + os.sep + filename
        if not os.path.exists(java_properties_path):
            message = "Giswater properties file not found"
            if show_warning:
                self.controller.show_warning(
                    message, parameter=str(java_properties_path))
            return False

        self.java_settings = QSettings(java_properties_path,
                                       QSettings.IniFormat)
        self.java_settings.setIniCodec(sys.getfilesystemencoding())
        self.file_gsw = utils_giswater.get_settings_value(
            self.java_settings, 'FILE_GSW')

    def set_gsw_settings(self):

        if not self.file_gsw:
            self.set_java_settings(False)

        self.gsw_settings = QSettings(self.file_gsw, QSettings.IniFormat)

    def save_database_parameters(self):
        """ Save database connection parameters into GSW file """

        if self.gsw_settings is None:
            self.set_gsw_settings()

        # Get layer version
        layer = self.controller.get_layer_by_tablename('version')
        if not layer:
            return

        # Get database connection paramaters and save them into GSW file
        layer_source = self.controller.get_layer_source_from_credentials()
        if layer_source is None:
            return

        self.gsw_settings.setValue('POSTGIS_DATABASE', layer_source['db'])
        self.gsw_settings.setValue('POSTGIS_HOST', layer_source['host'])
        self.gsw_settings.setValue('POSTGIS_PORT', layer_source['port'])
        self.gsw_settings.setValue('POSTGIS_USER', layer_source['user'])
        self.gsw_settings.setValue('POSTGIS_USESSL', 'false')

    def open_web_browser(self, dialog, widget=None):
        """ Display url using the default browser """

        if widget is not None:
            url = utils_giswater.getWidgetText(dialog, widget)
            if url == 'null':
                url = 'www.giswater.org'
        else:
            url = 'www.giswater.org'

        webbrowser.open(url)

    def get_file_dialog(self, dialog, widget):
        """ Get file dialog """

        # Check if selected file exists. Set default value if necessary
        file_path = utils_giswater.getWidgetText(dialog, widget)
        if file_path is None or file_path == 'null' or not os.path.exists(
                str(file_path)):
            folder_path = self.plugin_dir
        else:
            folder_path = os.path.dirname(file_path)

        # Open dialog to select file
        os.chdir(folder_path)
        file_dialog = QFileDialog()
        file_dialog.setFileMode(QFileDialog.AnyFile)
        message = "Select file"
        folder_path = file_dialog.getOpenFileName(
            parent=None, caption=self.controller.tr(message))
        if folder_path:
            utils_giswater.setWidgetText(dialog, widget, str(folder_path))

    def get_folder_dialog(self, dialog, widget):
        """ Get folder dialog """

        # Check if selected folder exists. Set default value if necessary
        folder_path = utils_giswater.getWidgetText(dialog, widget)
        if folder_path is None or folder_path == 'null' or not os.path.exists(
                folder_path):
            folder_path = os.path.expanduser("~")

        # Open dialog to select folder
        os.chdir(folder_path)
        file_dialog = QFileDialog()
        file_dialog.setFileMode(QFileDialog.Directory)
        message = "Select folder"
        folder_path = file_dialog.getExistingDirectory(
            parent=None,
            caption=self.controller.tr(message),
            directory=folder_path)
        if folder_path:
            utils_giswater.setWidgetText(dialog, widget, str(folder_path))

    def load_settings(self, dialog=None):
        """ Load QGIS settings related with dialog position and size """

        if dialog is None:
            dialog = self.dlg

        try:
            x = self.controller.plugin_settings_value(dialog.objectName() +
                                                      "_x")
            y = self.controller.plugin_settings_value(dialog.objectName() +
                                                      "_y")
            width = self.controller.plugin_settings_value(
                dialog.objectName() + "_width", dialog.property('width'))
            height = self.controller.plugin_settings_value(
                dialog.objectName() + "_height", dialog.property('height'))

            if int(x) < 0 or int(y) < 0:
                dialog.resize(int(width), int(height))
            else:
                screens = ctypes.windll.user32
                screen_x = screens.GetSystemMetrics(78)
                screen_y = screens.GetSystemMetrics(79)
                if int(x) > screen_x:
                    x = int(screen_x) - int(width)
                if int(y) > screen_y:
                    y = int(screen_y)
                dialog.setGeometry(int(x), int(y), int(width), int(height))
        except:
            pass

    def save_settings(self, dialog=None):
        """ Save QGIS settings related with dialog position and size """

        if dialog is None:
            dialog = self.dlg

        self.controller.plugin_settings_set_value(
            dialog.objectName() + "_width", dialog.property('width'))
        self.controller.plugin_settings_set_value(
            dialog.objectName() + "_height", dialog.property('height'))
        self.controller.plugin_settings_set_value(dialog.objectName() + "_x",
                                                  dialog.pos().x() + 8)
        self.controller.plugin_settings_set_value(dialog.objectName() + "_y",
                                                  dialog.pos().y() + 31)

    def open_dialog(self,
                    dlg=None,
                    dlg_name=None,
                    maximize_button=True,
                    stay_on_top=True):
        """ Open dialog """

        if dlg is None or type(dlg) is bool:
            dlg = self.dlg

        # Manage i18n of the dialog
        if dlg_name:
            self.controller.manage_translation(dlg_name, dlg)

        # Manage stay on top and maximize button
        if maximize_button and stay_on_top:
            dlg.setWindowFlags(Qt.WindowMinimizeButtonHint
                               | Qt.WindowMaximizeButtonHint
                               | Qt.WindowStaysOnTopHint)
        elif not maximize_button and stay_on_top:
            dlg.setWindowFlags(Qt.WindowMinimizeButtonHint
                               | Qt.WindowStaysOnTopHint)
        elif maximize_button and not stay_on_top:
            dlg.setWindowFlags(Qt.WindowMaximizeButtonHint)

        # Open dialog
        dlg.open()

    def close_dialog(self, dlg=None):
        """ Close dialog """

        if dlg is None or type(dlg) is bool:
            dlg = self.dlg
        try:
            self.save_settings(dlg)
            dlg.close()
            map_tool = self.canvas.mapTool()
            # If selected map tool is from the plugin, set 'Pan' as current one
            if map_tool.toolName() == '':
                self.iface.actionPan().trigger()
        except AttributeError:
            pass

    def multi_row_selector(self,
                           dialog,
                           tableleft,
                           tableright,
                           field_id_left,
                           field_id_right,
                           name='name',
                           index=[
                               0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
                               15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
                               27, 28, 29, 30
                           ]):

        # fill QTableView all_rows
        tbl_all_rows = dialog.findChild(QTableView, "all_rows")
        tbl_all_rows.setSelectionBehavior(QAbstractItemView.SelectRows)

        query_left = "SELECT * FROM " + self.schema_name + "." + tableleft + " WHERE " + name + " NOT IN "
        query_left += "(SELECT " + tableleft + "." + name + " FROM " + self.schema_name + "." + tableleft
        query_left += " RIGHT JOIN " + self.schema_name + "." + tableright + " ON " + tableleft + "." + field_id_left + " = " + tableright + "." + field_id_right
        query_left += " WHERE cur_user = current_user)"

        self.fill_table_by_query(tbl_all_rows, query_left)
        self.hide_colums(tbl_all_rows, index)
        tbl_all_rows.setColumnWidth(1, 200)

        # fill QTableView selected_rows
        tbl_selected_rows = dialog.findChild(QTableView, "selected_rows")
        tbl_selected_rows.setSelectionBehavior(QAbstractItemView.SelectRows)
        query_right = "SELECT " + tableleft + "." + name + ", cur_user, " + tableleft + "." + field_id_left + ", " + tableright + "." + field_id_right + " FROM " + self.schema_name + "." + tableleft
        query_right += " JOIN " + self.schema_name + "." + tableright + " ON " + tableleft + "." + field_id_left + " = " + tableright + "." + field_id_right
        query_right += " WHERE cur_user = current_user"

        self.fill_table_by_query(tbl_selected_rows, query_right)
        self.hide_colums(tbl_selected_rows, [1, 2, 3])
        tbl_selected_rows.setColumnWidth(0, 200)
        # Button select
        dialog.btn_select.clicked.connect(
            partial(self.multi_rows_selector, tbl_all_rows, tbl_selected_rows,
                    field_id_left, tableright, field_id_right, query_left,
                    query_right, field_id_right))

        # Button unselect
        query_delete = "DELETE FROM " + self.schema_name + "." + tableright
        query_delete += " WHERE current_user = cur_user AND " + tableright + "." + field_id_right + "="
        dialog.btn_unselect.clicked.connect(
            partial(self.unselector, tbl_all_rows, tbl_selected_rows,
                    query_delete, query_left, query_right, field_id_right))
        # QLineEdit
        dialog.txt_name.textChanged.connect(
            partial(self.query_like_widget_text, dialog, dialog.txt_name,
                    tbl_all_rows, tableleft, tableright, field_id_right,
                    field_id_left, name))

    def hide_colums(self, widget, comuns_to_hide):
        for i in range(0, len(comuns_to_hide)):
            widget.hideColumn(comuns_to_hide[i])

    def unselector(self, qtable_left, qtable_right, query_delete, query_left,
                   query_right, field_id_right):

        selected_list = qtable_right.selectionModel().selectedRows()
        if len(selected_list) == 0:
            message = "Any record selected"
            self.controller.show_warning(message)
            return
        expl_id = []
        for i in range(0, len(selected_list)):
            row = selected_list[i].row()
            id_ = str(qtable_right.model().record(row).value(field_id_right))
            expl_id.append(id_)
        for i in range(0, len(expl_id)):
            self.controller.execute_sql(query_delete + str(expl_id[i]))

        # Refresh
        self.fill_table_by_query(qtable_left, query_left)
        self.fill_table_by_query(qtable_right, query_right)
        self.refresh_map_canvas()

    def multi_rows_selector(self, qtable_left, qtable_right, id_ori,
                            tablename_des, id_des, query_left, query_right,
                            field_id):
        """
            :param qtable_left: QTableView origin
            :param qtable_right: QTableView destini
            :param id_ori: Refers to the id of the source table
            :param tablename_des: table destini
            :param id_des: Refers to the id of the target table, on which the query will be made
            :param query_right:
            :param query_left:
            :param field_id:
        """

        selected_list = qtable_left.selectionModel().selectedRows()

        if len(selected_list) == 0:
            message = "Any record selected"
            self.controller.show_warning(message)
            return
        expl_id = []
        curuser_list = []
        for i in range(0, len(selected_list)):
            row = selected_list[i].row()
            id_ = qtable_left.model().record(row).value(id_ori)
            expl_id.append(id_)
            curuser = qtable_left.model().record(row).value("cur_user")
            curuser_list.append(curuser)
        for i in range(0, len(expl_id)):
            # Check if expl_id already exists in expl_selector
            sql = ("SELECT DISTINCT(" + id_des + ", cur_user)"
                   " FROM " + self.schema_name + "." + tablename_des + ""
                   " WHERE " + id_des + " = '" + str(expl_id[i]) +
                   "' AND cur_user = current_user")
            row = self.controller.get_row(sql)

            if row:
                # if exist - show warning
                message = "Id already selected"
                self.controller.show_info_box(message,
                                              "Info",
                                              parameter=str(expl_id[i]))
            else:
                sql = ("INSERT INTO " + self.schema_name + "." +
                       tablename_des + " (" + field_id + ", cur_user) "
                       " VALUES (" + str(expl_id[i]) + ", current_user)")
                self.controller.execute_sql(sql)

        # Refresh
        self.fill_table_by_query(qtable_right, query_right)
        self.fill_table_by_query(qtable_left, query_left)
        self.refresh_map_canvas()

    def fill_table_psector(self,
                           widget,
                           table_name,
                           set_edit_strategy=QSqlTableModel.OnManualSubmit):
        """ Set a model with selected @table_name. Attach that model to selected table """
        if self.schema_name not in table_name:
            table_name = self.schema_name + "." + table_name
        # Set model
        self.model = QSqlTableModel()
        self.model.setTable(table_name)
        self.model.setEditStrategy(set_edit_strategy)
        self.model.setSort(0, 0)
        self.model.select()

        # Check for errors
        if self.model.lastError().isValid():
            self.controller.show_warning(self.model.lastError().text())

        # Attach model to table view
        widget.setModel(self.model)

    def fill_table(self,
                   widget,
                   table_name,
                   set_edit_strategy=QSqlTableModel.OnManualSubmit):
        """ Set a model with selected filter.
        Attach that model to selected table """
        if self.schema_name not in table_name:
            table_name = self.schema_name + "." + table_name
        # Set model
        self.model = QSqlTableModel()
        self.model.setTable(table_name)
        self.model.setEditStrategy(set_edit_strategy)
        self.model.setSort(0, 0)
        self.model.select()

        # Check for errors
        if self.model.lastError().isValid():
            self.controller.show_warning(self.model.lastError().text())
        # Attach model to table view
        widget.setModel(self.model)

    def fill_table_by_query(self, qtable, query):
        """
        :param qtable: QTableView to show
        :param query: query to set model
        """
        model = QSqlQueryModel()
        model.setQuery(query)
        qtable.setModel(model)
        qtable.show()

        # Check for errors
        if model.lastError().isValid():
            self.controller.show_warning(model.lastError().text())

    def query_like_widget_text(self,
                               dialog,
                               text_line,
                               qtable,
                               tableleft,
                               tableright,
                               field_id_r,
                               field_id_l,
                               name='name'):
        """ Fill the QTableView by filtering through the QLineEdit"""

        query = utils_giswater.getWidgetText(dialog,
                                             text_line,
                                             return_string_null=False).lower()
        sql = ("SELECT * FROM " + self.schema_name + "." + tableleft +
               " WHERE " + name + " NOT IN "
               "(SELECT " + tableleft + "." + name + " FROM " +
               self.schema_name + "." + tableleft + ""
               " RIGHT JOIN " + self.schema_name + "." + tableright + ""
               " ON " + tableleft + "." + field_id_l + " = " + tableright +
               "." + field_id_r + ""
               " WHERE cur_user = current_user) AND LOWER(" + name +
               "::text) LIKE '%" + query + "%'")
        self.fill_table_by_query(qtable, sql)

    def set_icon(self, widget, icon):
        """ Set @icon to selected @widget """

        # Get icons folder
        icons_folder = os.path.join(self.plugin_dir, 'icons')
        icon_path = os.path.join(icons_folder, str(icon) + ".png")
        if os.path.exists(icon_path):
            widget.setIcon(QIcon(icon_path))
        else:
            self.controller.log_info("File not found", parameter=icon_path)

    def check_expression(self, expr_filter, log_info=False):
        """ Check if expression filter @expr_filter is valid """

        if log_info:
            self.controller.log_info(expr_filter)
        expr = QgsExpression(expr_filter)
        if expr.hasParserError():
            message = "Expression Error"
            self.controller.log_warning(message, parameter=expr_filter)
            return (False, expr)
        return (True, expr)

    def refresh_map_canvas(self, restore_cursor=False):
        """ Refresh all layers present in map canvas """

        self.canvas.refreshAllLayers()
        for layer_refresh in self.canvas.layers():
            layer_refresh.triggerRepaint()

        if restore_cursor:
            self.set_cursor_restore()

    def set_cursor_wait(self):
        """ Change cursor to 'WaitCursor' """
        QApplication.setOverrideCursor(Qt.WaitCursor)

    def set_cursor_restore(self):
        """ Restore to previous cursors """
        QApplication.restoreOverrideCursor()

    def get_cursor_multiple_selection(self):
        """ Set cursor for multiple selection """

        path_folder = os.path.join(os.path.dirname(__file__), os.pardir)
        path_cursor = os.path.join(path_folder, 'icons', '201.png')
        if os.path.exists(path_cursor):
            cursor = QCursor(QPixmap(path_cursor))
        else:
            cursor = QCursor(Qt.ArrowCursor)

        return cursor

    def set_table_columns(self, dialog, widget, table_name):
        """ Configuration of tables. Set visibility and width of columns """

        widget = utils_giswater.getWidget(dialog, widget)
        if not widget:
            return

        # Set width and alias of visible columns
        columns_to_delete = []
        sql = ("SELECT column_index, width, alias, status"
               " FROM " + self.schema_name + ".config_client_forms"
               " WHERE table_id = '" + table_name + "'"
               " ORDER BY column_index")
        rows = self.controller.get_rows(sql, log_info=False)
        if not rows:
            return

        for row in rows:
            if not row['status']:
                columns_to_delete.append(row['column_index'] - 1)
            else:
                width = row['width']
                if width is None:
                    width = 100
                widget.setColumnWidth(row['column_index'] - 1, width)
                widget.model().setHeaderData(row['column_index'] - 1,
                                             Qt.Horizontal, row['alias'])

        # Set order
        # widget.model().setSort(0, Qt.AscendingOrder)
        widget.model().select()

        # Delete columns
        for column in columns_to_delete:
            widget.hideColumn(column)

    def connect_signal_selection_changed(self, option):
        """ Connect signal selectionChanged """

        try:
            if option == "mincut_connec":
                self.canvas.selectionChanged.connect(
                    partial(self.snapping_selection_connec))
            elif option == "mincut_hydro":
                self.canvas.selectionChanged.connect(
                    partial(self.snapping_selection_hydro))
        except Exception:
            pass

    def disconnect_signal_selection_changed(self):
        """ Disconnect signal selectionChanged """

        try:
            self.canvas.selectionChanged.disconnect()
        except Exception:
            pass

    def set_label_current_psector(self, dialog):

        sql = (
            "SELECT t1.name FROM " + self.schema_name + ".plan_psector AS t1 "
            " INNER JOIN " + self.schema_name +
            ".config_param_user AS t2 ON t1.psector_id::text = t2.value "
            " WHERE t2.parameter='psector_vdefault' AND cur_user = current_user"
        )
        row = self.controller.get_row(sql)
        if not row:
            return
        utils_giswater.setWidgetText(dialog, 'lbl_vdefault_psector', row[0])

    def multi_rows_delete(self, widget, table_name, column_id):
        """ Delete selected elements of the table
        :param QTableView widget: origin
        :param table_name: table origin
        :param column_id: Refers to the id of the source table
        """

        # Get selected rows
        selected_list = widget.selectionModel().selectedRows()
        if len(selected_list) == 0:
            message = "Any record selected"
            self.controller.show_warning(message)
            return

        inf_text = ""
        list_id = ""
        for i in range(0, len(selected_list)):
            row = selected_list[i].row()
            id_ = widget.model().record(row).value(str(column_id))
            inf_text += str(id_) + ", "
            list_id = list_id + "'" + str(id_) + "', "
        inf_text = inf_text[:-2]
        list_id = list_id[:-2]
        message = "Are you sure you want to delete these records?"
        title = "Delete records"
        answer = self.controller.ask_question(message, title, inf_text)
        if answer:
            sql = "DELETE FROM " + self.schema_name + "." + table_name
            sql += " WHERE " + column_id + " IN (" + list_id + ")"
            self.controller.execute_sql(sql)
            widget.model().select()

    def select_features_by_expr(self, layer, expr):
        """ Select features of @layer applying @expr """

        if expr is None:
            layer.removeSelection()
        else:
            it = layer.getFeatures(QgsFeatureRequest(expr))
            # Build a list of feature id's from the previous result and select them
            id_list = [i.id() for i in it]
            if len(id_list) > 0:
                layer.selectByIds(id_list)
            else:
                layer.removeSelection()

    def zoom_to_selected_features(self, layer, geom_type=None, zoom=None):
        """ Zoom to selected features of the @layer with @geom_type """

        if not layer:
            return

        self.iface.setActiveLayer(layer)
        self.iface.actionZoomToSelected().trigger()

        if geom_type:

            # Set scale = scale_zoom
            if geom_type in ('node', 'connec', 'gully'):
                scale = self.scale_zoom

            # Set scale = max(current_scale, scale_zoom)
            elif geom_type == 'arc':
                scale = self.iface.mapCanvas().scale()
                if int(scale) < int(self.scale_zoom):
                    scale = self.scale_zoom
            else:
                scale = 5000

            if zoom is not None:
                scale = zoom

            self.iface.mapCanvas().zoomScale(float(scale))

    def set_completer(self, tablename, widget, field_search, color='black'):
        """ Set autocomplete of widget @table_object + "_id"
            getting id's from selected @table_object
        """

        if not widget:
            return

        # Set SQL
        sql = ("SELECT DISTINCT(" + field_search + ")"
               " FROM " + self.schema_name + "." + tablename + ""
               " ORDER BY " + field_search + "")
        row = self.controller.get_rows(sql)

        for i in range(0, len(row)):
            aux = row[i]
            row[i] = str(aux[0])

        # Set completer and model: add autocomplete in the widget
        self.completer = QCompleter()
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setCompletionMode(0)
        self.completer.popup().setStyleSheet("color: " + color + ";")
        widget.setCompleter(self.completer)

        model = QStringListModel()
        model.setStringList(row)
        self.completer.setModel(model)

    def zoom_to_rectangle(self, x1, y1, x2, y2, margin=5):
        # rect = QgsRectangle(float(x1)+10, float(y1)+10, float(x2)-10, float(y2)-10)
        rect = QgsRectangle(
            float(x1) - margin,
            float(y1) - margin,
            float(x2) + margin,
            float(y2) + margin)
        self.canvas.setExtent(rect)
        self.canvas.refresh()

    def create_action(self,
                      action_name,
                      action_group,
                      icon_num=None,
                      text=None):
        """ Creates a new action with selected parameters """

        icon = None
        icon_folder = self.plugin_dir + '/icons/'
        icon_path = icon_folder + icon_num + '.png'
        if os.path.exists(icon_path):
            icon = QIcon(icon_path)

        if icon is None:
            action = QAction(text, action_group)
        else:
            action = QAction(icon, text, action_group)
        action.setObjectName(action_name)

        return action
Пример #12
0
class IdePanel(QPlainTextEdit):
    def __init__(self):
        QPlainTextEdit.__init__(self)
        self.setWordWrapMode(QTextOption.NoWrap)
        self.setFont(QFont("monospace", 10))
        self.setCursorWidth(2)
        self.installEventFilter(self)

        self.cursorPositionChanged.connect(self.showHelp)

        self.completer = QCompleter(self)
        self.completer.setWidget(self)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.activated.connect(self.insertCompletion)


        auto_complete = QShortcut(QKeySequence("Ctrl+Space"), self)
        auto_complete.activated.connect(self.activateCompleter)

        copy_line = QShortcut(QKeySequence("Ctrl+D"), self)
        copy_line.activated.connect(self.duplicateLine)

        select_fragment = QShortcut(QKeySequence("Ctrl+J"), self)
        select_fragment.activated.connect(self.selectFragment)

    def showHelp(self):
        text_cursor = self.textCursor()
        user_data = text_cursor.block().userData()

        if user_data is not None:
            configuration_line = user_data.configuration_line

            if configuration_line.keyword().hasKeywordDefinition():
                HelpCenter.getHelpCenter("ERT").setHelpMessageLink("config/" + configuration_line.documentationLink())


    def getText(self):
        return self.document().toPlainText()


    def eventFilter(self, qobject, qevent):
        if qobject == self and qevent.type() == QEvent.ToolTip:
            text_cursor = self.cursorForPosition(qevent.pos())
            pos = text_cursor.positionInBlock()

            user_data = text_cursor.block().userData()
            if user_data is not None:
                #: :type: ConfigurationLine
                configuration_line = user_data.configuration_line
                # if configuration_line.keyword().hasKeywordDefinition():
                #     print(configuration_line.keyword().keywordDefinition().documentation)

                if pos in configuration_line.keyword():
                    self.setToolTip(configuration_line.validationStatusForToken(configuration_line.keyword()).message())
                else:
                    for argument in configuration_line.arguments():
                        if pos in argument:
                            self.setToolTip(configuration_line.validationStatusForToken(argument).message())

            else:
                self.setToolTip("")


        return QPlainTextEdit.eventFilter(self, qobject, qevent)


    def activateCompleter(self):
        text_cursor = self.textCursor()
        block = self.document().findBlock(text_cursor.position())
        position_in_block = text_cursor.positionInBlock()



        self.selectWordUnderCursor(text_cursor)
        word = unicode(text_cursor.selectedText())

        user_data = block.userData()

        self.completer.setCompletionPrefix(word)

        show_completer = False
        if user_data is None:
            self.completer.setModel(QStringListModel(self.handler_names))
            show_completer = True

        else:
            keyword = user_data.keyword
            options = keyword.handler.parameterOptions(keyword, word, position_in_block)

            if len(options) == 1:
                self.insertCompletion(options[0])
            elif len(options) > 1:
                self.completer.setModel(QStringListModel(options))
                if self.completer.completionCount() == 1:
                    self.insertCompletion(self.completer.currentCompletion())
                else:
                    show_completer = True


        if show_completer:
            rect = self.cursorRect(text_cursor)
            rect.setWidth(self.completer.popup().sizeHintForColumn(0) + self.completer.popup().verticalScrollBar().sizeHint().width())
            self.completer.complete(rect)

    def keyPressEvent(self, qkeyevent):
        if self.completer.popup().isVisible():
            dead_keys = [Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape, Qt.Key_Tab, Qt.Key_Backtab]
            if qkeyevent.key() in dead_keys:
                qkeyevent.ignore()
                return

        if qkeyevent.modifiers() == Qt.ShiftModifier:
            if qkeyevent.key() & Qt.Key_Delete == Qt.Key_Delete:
                self.deleteLine()

        QPlainTextEdit.keyPressEvent(self, qkeyevent)


    def insertCompletion(self, string):
        text_cursor = self.textCursor()
        self.selectWordUnderCursor(text_cursor)
        text_cursor.insertText(string)

    def isCursorInSpace(self):
        text_cursor = self.textCursor()
        if text_cursor.positionInBlock() > 0:
            text_cursor.movePosition(QTextCursor.Left, QTextCursor.MoveAnchor)
            text_cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor)

        if text_cursor.positionInBlock() < text_cursor.block().length() - 1:
            text_cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor)

        if unicode(text_cursor.selectedText()).strip() == "":
            return True

        return False

    def selectWordUnderCursor(self, text_cursor):
        if not self.isCursorInSpace():
            # text_cursor.select(QTextCursor.WordUnderCursor)

            # pattern = "[\s|\v|\f|\n|\r|\t|\xe2\x80\xa8|\xe2\x80\xa9]"
            # pattern = "[\\s|\\xe2\\x80\\xa9|\\xe2\\x80\\xa8]"

            block_start = 0
            block_end = text_cursor.block().length()

            cursor_pos = text_cursor.positionInBlock()
            pos = cursor_pos
            pattern = u"[\s\u2029\u2028]"
            while pos >= block_start:
                text_cursor.movePosition(QTextCursor.Left, QTextCursor.KeepAnchor)
                text = text_cursor.selectedText()
                if re.search(pattern, text):
                    break
                pos -= 1

            text_cursor.movePosition(QTextCursor.Right, QTextCursor.MoveAnchor)

            while pos < block_end:
                text_cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor)
                text = text_cursor.selectedText()
                if re.search(pattern, text):
                    break
                pos += 1

            text_cursor.movePosition(QTextCursor.Left, QTextCursor.KeepAnchor)

            # pattern = "[\\s]"
            # start = self.document().find(QRegExp(pattern), text_cursor, QTextDocument.FindBackward | QTextDocument.FindCaseSensitively)
            # end = self.document().find(QRegExp(pattern), text_cursor, QTextDocument.FindCaseSensitively)
            # block_end_pos = text_cursor.block().position() + text_cursor.block().length()
            #
            # text_cursor.setPosition(start.position(), QTextCursor.MoveAnchor)
            # # text_cursor.setPosition(min(block_end_pos, end.position() - 1), QTextCursor.KeepAnchor)
            # text_cursor.setPosition(end.position() - 1, QTextCursor.KeepAnchor)


    def deleteLine(self):
        text_cursor = self.textCursor()
        text_cursor.beginEditBlock()
        text_cursor.select(QTextCursor.LineUnderCursor)
        text_cursor.removeSelectedText()
        text_cursor.deletePreviousChar()

        text_cursor.movePosition(QTextCursor.NextBlock)
        text_cursor.movePosition(QTextCursor.StartOfLine)
        self.setTextCursor(text_cursor)
        text_cursor.endEditBlock()

    def duplicateLine(self):
        text_cursor = self.textCursor()
        text_cursor.beginEditBlock()
        text_cursor.select(QTextCursor.LineUnderCursor)
        text = text_cursor.selectedText()
        text_cursor.movePosition(QTextCursor.EndOfLine)
        text_cursor.insertBlock()
        text_cursor.insertText(text)
        text_cursor.endEditBlock()


    def selectFragment(self):
        text_cursor = self.textCursor()
        self.selectWordUnderCursor(text_cursor)
        self.setTextCursor(text_cursor)
Пример #13
0
class Console(QObject):

    @property
    def _currentCursor(self):
        return self.widget.textCursor()

    @_currentCursor.setter
    def _currentCursor(self, cursor):
        self.widget.setTextCursor(cursor)

    @property
    def _endCursor(self):
        return self._lastBlock.endCursor()

    @property
    def _currentBlock(self):
        return TextBlock(self._currentCursor)

    @property
    def _document(self):
        return self.widget.document()

    def _canDeletePreviousChar(self):
        if self._currentBlock.type in TextBlock.EDITABLE_TYPES and self._cursorInEditableArea():
            return self._currentBlock.containsCursor(self._currentCursor, in_active_area='strict')
        return False

    def _cursorInEditableArea(self, cursor=None):
        if cursor is None:
            cursor = self._currentCursor
        return self._lastBlock.isCursorInRelatedBlock(cursor) and self._currentBlock.containsCursor(cursor)

    def _canEditCurrentChar(self):
        if not self._currentBlock.type in TextBlock.EDITABLE_TYPES:
            return False
        if not self._currentBlock.containsCursor(self._currentCursor):
            return False

    def _gotoBlockStart(self):
        self._currentCursor = self._currentBlock.startCursor()

    def _gotoBlockEnd(self):
        self._currentCursor = self._currentBlock.endCursor()

    @property
    def _lastBlock(self):
        return TextBlock(self._document.lastBlock())

    def _gotoEnd(self):
        self._currentCursor = self._endCursor

    def _insertBlock(self, cursor=None, block_type=TextBlock.TYPE_CODE_CONTINUED, content=""):
        if cursor is None:
            cursor = self._currentCursor
        b = TextBlock(cursor, create_new=True, typ=block_type)
        if len(content):
            b.appendText(content)
        return b

    def _appendBlock(self, block_type, content="", html=False):
        b = TextBlock(self._endCursor, create_new=True, typ=block_type)
        if len(content) > 0:
            if html:
                b.appendHtml(content)
            else:
                b.appendText(content)
        return b

    def _blocks(self):
        b = TextBlock(self._document.begin())
        ret = []
        while not b.isLast():
            ret.append(b)
            b = b.next()
        ret.append(b)
        return ret

    def _saveBlocksToJSON(self,num_of_blocks=None):
        if num_of_blocks is None:
            num_of_blocks = 0
        ret = []
        for b in self._blocks()[-num_of_blocks:]:
            ret += [json.dumps({'block_type':b.type,'content':b.content()})]
        return '\n'.join(ret)

    def save_history(self, fname=None):
        if fname is None:
            fname = config.history_file
        fname = expanduser(fname)
        if fname.endswith('.gz'):
            f = gzip.open(fname,'wb')
        else:
            f = open(fname,'wb')
        try:
            hist_size = config.history_size
        except:
            hist_size = None
        f.write(self._saveBlocksToJSON(num_of_blocks=hist_size))
        f.close()

    def load_history(self, fname=None):
        if fname is None:
            fname = config.history_file
        fname = expanduser(fname)
        if not os.path.exists(fname):
            return
        if fname.endswith('.gz'):
            f = gzip.open(fname,'rb')
        else:
            f = open(fname,'rb')
        blocks = f.readlines()
        for b in blocks:
            bl = json.loads(b.strip())
            self._appendBlock(**bl)


    def _joinCurrentToPreviousBlock(self):
        logger.debug(msg("Deleting current block"))
        cur = self._currentBlock
        prev = cur.previous()
        prev.appendText(cur.content())
        cur.deleteBlock()

    def wordUnderCursor(self, cursor=None, delta=0):
        """ Returns the word (name) under cursor @cursor (or self._currentCursor)
            if @cursor is None. The cursor is shifted by @delta """
        if cursor is None:
            cursor = self._currentCursor
        if delta > 0:
            cursor.movePosition(QTextCursor.Right, QTextCursor.MoveAnchor, delta)
        elif delta < 0:
            cursor.movePosition(QTextCursor.Left, QTextCursor.MoveAnchor, abs(delta))
        return self._currentBlock.wordUnderCursor(cursor)

    def _containing_function(self):
        """ Determines whether the cursor is located in the argument part of a function.
            If yes, returns a (@cursor,@func_name) where  @cursor points to the opening brace
            and @func_name is the function name. """
        ct = self.textToCursor()
        i=len(ct)-1
        brackets = 0
        logger.debug("ct == " + ct)
        while i >= 0:
            if ct[i] == ')':
                brackets -=1
            if ct[i] == '(':
                if brackets < 0:
                    brackets += 1
                elif i > 0 and ct[i-1] not in TextBlock.WORD_STOP_CHARS:
                    cursor = self._currentBlock.cursorAt(i-1)
                    func_name = self._currentBlock.wordUnderCursor(cursor)
                    cursor = self._currentBlock.cursorAt(i+len(func_name))
                    logger.debug("func_name == "+ func_name)
                    return (cursor,func_name)
            i -= 1
        return None


    def textToCursor(self):
        return self._currentBlock.contentToCursor(self._currentCursor)

    def _guessDictPrefix(self, char):
        """ Tries to determine whether the user is typing a string-key in a dict. If yes
            returns the dict name and the key typed so far. Otherwise returns None. """
        c = self._currentCursor
        block_content = self._currentBlock.content(include_decoration=True)
        pos = min(c.positionInBlock(), len(block_content))
        block_content = unicode(block_content[:pos]+char)

        double_quotes = block_content.count('"')
        single_quotes = block_content.count("'")

        if double_quotes % 2 == 0 and single_quotes % 2 == 0:
            return None

        stop_chars = '"\' '
        ret = []
        while pos >= 0 and block_content[pos] not in stop_chars:
            ret.append(block_content[pos])
            pos -= 1
        ret.reverse()
        if pos > 0 and block_content[pos-1] == '[':
            pos -= 1
            dct = []
            while pos >= 0 and block_content[pos] not in [ ' ', "\n", "\t"]:
                dct.append(block_content[pos])
                pos -= 1
            dct.reverse()
            logger.debug(msg('dct:',''.join(dct[:-1]), 'key:',''.join(ret)))
            return ''.join(dct[:-1]), ''.join(ret)
        else:
            return None

    def _guessStringPrefix(self, char):
        """Tries to guess whether the user is typing a string (i.e. inside quotes)
           and if yes, returns the string typed so far. Otherwise returns None. """
        c = self._currentCursor
        block_content = self._currentBlock.content(include_decoration=True)
        pos = min(c.positionInBlock(), len(block_content))
        block_content = unicode(block_content[:pos]+char)

        double_quotes = block_content.count('"')
        single_quotes = block_content.count("'")

        if double_quotes % 2 == 0 and single_quotes % 2 == 0:
            return None

        stop_chars = '"\' '
        ret = []
        while pos >= 0 and block_content[pos] not in stop_chars:
            ret.append(block_content[pos])
            pos -= 1
        ret.reverse()
        logger.debug(''.join(ret))
        return ''.join(ret)

    @pyqtSlot(unicode)
    def _insertCompletion(self, completion):
        insertion = completion[len(self.completer.completionPrefix()):]
        if len(insertion) == 0:
            self._process_enter()
        else:
            c = self._currentCursor
            c.movePosition(QTextCursor.Left)
            c.movePosition(QTextCursor.EndOfWord)
            c.insertText(insertion)
            self._currentCursor = c

    DEFAULT_INDENT = 4

    MODE_RUNNING = 0
    MODE_CODE_EDITING = 1
    MODE_RAW_INPUT = 2
    MODE_READ_ONLY = 3
    MODE_WAITING_FOR_INTERRUPT = 4

    # run_code = pyqtSignal(unicode)
    run_code = signal(unicode)
    read_line = signal(unicode)
    restart_shell = signal()
    interrupt_shell = signal()
    quit = pyqtSignal()
    file_watched = signal(unicode)

    def __init__(self, widget):
        super(Console, self).__init__()
        self.font_size = 10
        self.font = QFont("Ubuntu Mono", self.font_size)
        self.allow_quit = True
        self.indent = self.DEFAULT_INDENT
        self.widget = widget
        self.hilighter = PythonHighlighter(self.widget.document())
        self.parser = PyParser(self.indent, self.indent)

        self.widget.setFont(self.font)

        # The source file's we are watching
        self.watcher = QFileSystemWatcher()
        self.watcher.fileChanged.connect(self._sourceChanged)
        self._watched_files_menu = QMenu(self.widget.tr("&Watched Files"))
        self._watched_files_actions = {}
        self._lost_files = []

        self._widgetKeyPressEvent = self.widget.keyPressEvent
        self.widget.keyPressEvent = self.keyPressEvent
        self._widgetFocusInEvent = self.widget.focusInEvent
        self.widget.focusInEvent = self.focusInEvent
        self.widget.dragEnterEvent = self.dragEnterEvent
        self.widget.dragMoveEvent = self.dragMoveEvent
        self.widget.dropEvent = self.dropEvent

        # Code Completion
        self.completer = QCompleter(
            [kw for kw in PythonHighlighter.keywords if len(kw) > 3])
        self.completer.setCompletionMode(QCompleter.PopupCompletion)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.activated.connect(self._insertCompletion)
        self.completer.popup().setStyleSheet(
            "QWidget {border-width: 1px; border-color: black;}")
        self.completer.popup().setVerticalScrollBarPolicy(
            Qt.ScrollBarAlwaysOff)
        self.completer.setWidget(self.widget)
        self.completion_enabled = True

        if config.history:
            self.load_history()

        self._lastBlock.setType(TextBlock.TYPE_MESSAGE)
        self._lastBlock.appendText("PyShell v 0.5: Starting ...")
        self._write_message("Python version ", sys.version)
        self.start_editing()

        # Restart shell timer
        self.timer = QTimer(self)

    @property
    def watched_files_menu(self):
        return self._watched_files_menu

    @property
    def mode(self):
        return self._mode

    @pyqtSlot()
    def increase_font(self):
        self.font_size += 1
        self.font = QFont("Ubuntu Mono", self.font_size)
        self.widget.setFont(self.font)

    @pyqtSlot()
    def decrease_font(self):
        self.font_size -= 1
        self.font = QFont("Ubuntu Mono", self.font_size)
        self.widget.setFont(self.font)

    @pyqtSlot(unicode, unicode)
    def write(self, stream, string):
        #assert self.mode == Console.MODE_RUNNING or self.mode == Console.MODE_WAITING_FOR_INTERRUPT, "Cannot write " + \
        #    string + " to console stream "+stream+" in "+str(
        #        self.mode) + " (need to be RUNNING/INTERRUPT mode) "
        if string.startswith('<html_snippet>'):
            self._lastBlock.appendHtml(string.replace(
                "<html_snippet>", "").replace("</html_snippet>", ""))
        else:
            lines = string.split('\n')
            block_type = block_type_for_stream(stream)
            for ln in lines[:-1]:
                self._lastBlock.appendText(ln)
                self._lastBlock.setType(block_type)
                self._appendBlock(block_type)
            self._lastBlock.appendText(lines[-1])
            self._gotoEnd()

    def write_object(self, obj):
        logger.debug(msg("Received object", obj, "writing it to stdout"))
        self.write('stdout',print_hooks.html_repr(obj, self._document))

    @pyqtSlot()
    def do_readline(self):
        assert self.mode != Console.MODE_RAW_INPUT, "Cannot call readline before previous call finished"
        assert self.mode == Console.MODE_RUNNING, "readline may be called only in the RUNNING mode"
        self._lastBlock.setType(TextBlock.TYPE_RAW_INPUT)
        self._mode = Console.MODE_RAW_INPUT

    @pyqtSlot()
    def shell_restarted(self):
        logger.debug("Shell restarted!")
        self._write_message("<span style='color:green'>","="*20,
                            "</span> SHELL RESTARTED <span style='color:green'>","="*20,"</span>", html=True)
        self._write_message('Python version ',sys.version, html=True)
        self.start_editing()

    @pyqtSlot()
    def finished_running(self):
        logger.debug("Finished running.")
        if len(self._lastBlock.content()) == 0:
            self._lastBlock.deleteBlock()
        self.start_editing()

    @pyqtSlot()
    def start_editing(self):
        new_code_block = self._appendBlock(TextBlock.TYPE_CODE_START)
        self._gotoEnd()
        self._mode = Console.MODE_CODE_EDITING

    @pyqtSlot()
    def exec_command(self,*args, **kwargs):
        """ Executes a command in the console context.
            The command is given by the cmd keyword argument.
            It is either a predefined command or the name of
            a method of the console object, in which case this
            method is called with *args and **kwargs (where cmd
            is first deleted from kwargs) """
        if 'cmd' in kwargs:
            cmd = kwargs['cmd']
            del kwargs['cmd']
            if cmd == 'watch.list_files':
                self._write_message("Currently watching the following files:")
                self._write_message([unicode(x) for x in self.watcher.files()])
                self._write_message("Total watched:",len(self.watcher.files()))
                logger.debug(msg([x for x in self.watcher.files()]))
            elif cmd == 'watch.reload':
                self._reload_watch_files()
            elif cmd in dir(self):
                attr = self.__getattribute__(cmd)
                if type(attr) == type(self.exec_command):
                    attr(*args, **kwargs)
                else:
                    self.write_object(attr)

    def _write_message(self, *args, **kwargs):
        """ Outputs a "System" message to the console. The message is composed
            of string representations of args. If the keyword argument html
            is present, the message is assumed to be html. """
        if 'html' in kwargs:
            html = kwargs['html']
        else:
            html = True
        msg = u''
        for a in args:
            try:
                msg += unicode(a)
            except Exception, e:
                logger.warn("Exception while writing to console" + str(e))
        self._appendBlock(TextBlock.TYPE_MESSAGE, msg, html)
Пример #14
0
class SearchPanel(QComboBox):
    def __init__(self, model, parent=None, showTable=False):
        super(SearchPanel, self).__init__(parent)

        self.tabla = None
        self.setFocusPolicy(Qt.StrongFocus)
        self.setEditable(True)
        #        self.setModel( model )
        self.setEditable(True)
        self.completer = QCompleter(self)
        # always show all completions
        self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
        self.pFilterModel = QSortFilterProxyModel(self)
        self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.showTable = showTable

        if model != None:
            self.setModel(model)


#        self.pFilterModel.setSourceModel( model );

        self.completer.setModel(self.pFilterModel)
        self.completerTable = SearchPanelView()
        self.completer.setPopup(self.completerTable)
        #Mostrar el Popup en forma de Tabla
        if self.showTable:
            self.tabla = SearchPanelView()
            self.setView(self.tabla)

        self.setCompleter(self.completer)

        self.setColumn(1)

        self.lineEdit().textEdited[unicode].connect(
            self.pFilterModel.setFilterFixedString if not showTable else self.
            pFilterModel.setFilterWildcard)

    def setModel(self, model):
        QComboBox.setModel(self, model)
        self.pFilterModel.setSourceModel(model)

    def setColumn(self, column):
        self.setModelColumn(1)
        self.completer.setCompletionColumn(column)
        self.pFilterModel.setFilterKeyColumn(column)
        self.setModelColumn(column)

    def view(self):
        return self.completer.popup()

    def data(self):
        return self.currentIndex()

    def index(self):
        return self.currentIndex()

    def setColumnHidden(self, col):
        self.completerTable.hiddenColumns.append(col)
        if self.showTable:
            self.tabla.hiddenColumns.append(col)

    def setMinimumWidth(self, width):
        self.completerTable.setMinimumWidth(width)
        if self.showTable:
            self.tabla.setMinimumWidth(width)
Пример #15
0
class WithCompletion(QPlainTextEdit):
    """\
Mixin to add base completion funtionallity to QPlainTextEdit

It will propose completion with words from current file

When the word you are writting is bigger than two, it will request for
possible completions but with no default selection.

If you press Ctrl-Space, the proposal will choose the first one as default

Specific mixings will have to implement the get_text_completion_list method
"""

    def get_text_completion_list(self):
        return []

    def __init__(self, *args):
        self.model_completer = QStringListModel()
        self.completer = QCompleter(self)
        self.completer.popup().setFont(QFont("Monospace", 11))
        # self.completer.setModelSorting(QCompleter.CaseInsensitivelySortedModel
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setWrapAround(False)
        self.completer.setWidget(self)
        self.completer.setCompletionMode(QCompleter.PopupCompletion)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setModel(self.model_completer)
        self.completer.activated.connect(self.insert_completion)

    def keyPressEvent(self, event):
        event_key = event.key()
        if self.completer.popup().isVisible():
            # The following keys are forwarded by the completer to the widget
            if event_key in [Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape, Qt.Key_Tab, Qt.Key_Backtab]:
                if self.completer.popup().currentIndex().row() >= 0:
                    event.ignore()
                    return  # let the completer do default behavior
                else:
                    self.completer.popup().hide()

        super(WithCompletion, self).keyPressEvent(event)

        if (event.modifiers() | event.key()) == QKeySequence("Ctrl+Space"):
            self.show_completer(True)

        elif event_key in [Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape, Qt.Key_Tab, Qt.Key_Backtab]:
            pass
        else:
            pressed_key_as_string = QKeySequence(event.key()).toString()
            word_till_cursor = unicode(self.word_till_cursor())
            if (len(word_till_cursor) > 2 or (self.completer.popup().isVisible() and len(word_till_cursor) > 0)) and (
                (event.text() != "" and regex.match("^[A-Za-z0-9_-]*$", unicode(pressed_key_as_string[0])))
                or self.completer.popup().isVisible()
            ):
                self.show_completer(self.completer.popup().currentIndex().row() >= 0)
            else:
                self.completer.popup().setCurrentIndex(self.completer.completionModel().index(-1, 0))
                self.completer.popup().hide()

    def show_completer(self, select_first):
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        completion_words = self.get_text_completion_list()
        QApplication.restoreOverrideCursor()

        if not completion_words or len(completion_words) < 1:
            self.completer.popup().hide()
            return

        self.model_completer.setStringList(completion_words)

        cr = self.cursorRect()
        width = (
            self.completer.popup().sizeHintForColumn(0) + self.completer.popup().verticalScrollBar().sizeHint().width()
        )
        cr.setWidth(width if width < 300 else 300)
        self.completer.complete(cr)
        if select_first:
            self.completer.popup().setCurrentIndex(self.completer.completionModel().index(0, 0))

    def word_under_cursor(self):
        result = ""
        for i in range(self.current_pos_init_of_word(), self.current_pos_end_of_word()):
            result = result + unichr(self.document().characterAt(i).unicode())
        return QString(result)

    def word_till_cursor(self):
        result = ""
        for i in range(self.current_pos_init_of_word(), self.textCursor().position()):
            result = result + unichr(self.document().characterAt(i).unicode())
        return QString(result)

    def current_pos_init_of_word(self):
        pos = self.textCursor().position() - 1
        while True:
            char = unichr(self.document().characterAt(pos).unicode())
            if not char in WORD_SYMBOLS or pos < 0:
                # if char=='\n' or re.match("^[A-Za-z0-9_-ñÑ]*$", unicode(char)) == None  or pos==0:
                break
            pos = pos - 1
        return pos + 1

    def current_pos_end_of_word(self):
        pos = self.textCursor().position()
        while True:
            char = unichr(self.document().characterAt(pos).unicode())
            if not char in WORD_SYMBOLS or pos == self.document().characterCount():
                # if char.isSpace() or re.match("^[A-Za-z0-9_-ñÑ]*$", unicode(char)) == None:
                break
            pos = pos + 1
        return pos

    def insert_completion(self, completion_text):
        if self.completer.widget() != self:
            return
        tc = self.textCursor()
        till_pos = tc.position()
        tc.movePosition(
            QTextCursor.Left, QTextCursor.MoveAnchor, self.textCursor().position() - self.current_pos_init_of_word()
        )
        # tc.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor, self.current_pos_end_of_word()-self.current_pos_init_of_word())
        tc.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor, till_pos - self.current_pos_init_of_word())
        tc.removeSelectedText()
        tc.insertText(completion_text)
        self.setTextCursor(tc)
class LineEdit_Autocomplete(QLineEdit):

    AutoComplete = pyqtSignal(QString)

    def __init__(self, *args, **kwargs):
        QLineEdit.__init__(self, *args, **kwargs)
       
        self.completions = []                   # All available completions
        self.googlesuggestions = []             # This will be filled automatically if GOOGLESEARCH is True
        self.partials = []                      # Parsed completions according to partially typed word
        self.staticsuggestions = []             # Static suggestions list
       
        self.cursorpos = 0
        self.wordstart = -1                     # Start of word where cursor positioned
        self.wordend = -1                       # End of word where cursor is positioned
        self.lastindex = -1                     # Last used completion of available completions

        ######################## Completer for first part (without trigger)

        self.completer = QCompleter()
        self.completer.setParent(self)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.popup().setMinimumHeight(40)           # Keep a minumum heigt if the completer is shown
        self.setCompleter(self.completer)
        self.model = QStringListModel()
        self.model.setParent(self.completer)
        self.completer.setModel(self.model)
        self.completer.setMaxVisibleItems(6)
        self.__set_data(self.model)


        self.setCompletionDialogFoam()            # Set to standard (PopupCompletion)
        self.setKeyWordForCompletion()            # default keyword = "whitespace" - " "

        self.Timer = QTimer()                     # Setup singleshot Timer for GoogleSuggestions
        self.Timer.setSingleShot(True)

        self.setGOOGLESEARCH_attr = False         # initial Settings
        self.languageForGOOGLESEARCH = "en"


        self.textEdited.connect(self.onTextEdit)  # define connections
        self.Timer.timeout.connect(self.googlesearch)

        self.toolButton = None

    def set_data(self):
        """
        :Triggers the internal __set_data Methode
        """
        self.__set_data(self.model)

    def __set_data(self, model):
        """
        :param model: QStringlistmodel which is used
        :Is adding all suggestions which are available at the time of call to the model which manage the input
        for the used completer (Popup, Inline or Unfiltered Popup Completion
        """
        #print("Setup Completer with available completions")
        stringlist = []

        for item in self.staticsuggestions:
            stringlist.append(item)

        for item in self.googlesuggestions:
            stringlist.append(item)

        model.setStringList(stringlist)



    def setCompletionDialogFoam(self, QCompleter_Mode=QCompleter.PopupCompletion):
        '''
        Possible Options:    QCompleter.UnfilteredPopupCompletion
                             QCompleter.PopupCompletion
                             QCompleter.InlineCompletion
        '''
        self.completer.setCompletionMode(QCompleter_Mode)


    def setGOOGLESEARCH(self, bool):
        '''
        With this attribute the "google-suggest" function can be activated, and deactivated....
        '''
        self.setGOOGLESEARCH_attr = bool

    def setLanguageForGOOGLESEARCH(self, language="en"):
        self.languageForGOOGLESEARCH = language


    @pyqtSlot(QString)
    def onTextEdit(self, Text=None):
        '''
        If Googelsearch is set to "True" this will trigger the suggestions after 500ms, when the user do not enter
        anything.
        '''
        if self.setGOOGLESEARCH_attr:
            self.Timer.start(500)
            # Timer is connected to "googlesearch"

    @pyqtSlot()
    def googlesearch(self):
        '''
        Is collecting the current text entered and is requesting a suggestion-list
        This list is replacing the current self.googlesuggest
        '''
        #print("Googlesearch")
        query = self.text()
        text = unicode(query)              #convert QString to str.
        text = text.encode('utf-8')

        if text.find(self.keyWord) != -1:
            self.googlesuggestions = []
            self.__set_data(self.model)
            return

        result = self.get_querySuggestionList(text, self.languageForGOOGLESEARCH)

        self.googlesuggestions = []

        for suggestion in result:
            self.googlesuggestions.append(unicode(suggestion))

        #print(self.googlesuggestions)
        self.__set_data(self.model)

    def addCompletion(self, word):
        '''
        Adds a Word to the custom completions-list
        '''
        if not word in self.completions:
            self.completions.append(word)
           
    def delCompletion(self, word):
        '''
        Removes a Word from the custom completions-list
        '''
        if word in self.completions:
            self.completions.remove(word)
           
    def setCompletions(self, items=[]):
        '''
        items is a List of Strings
        '''
        self.completions = items

    def setKeyWordForCompletion(self, Regex_String=".*", Wordseparator=" "):
        '''
        Regex_String is something like this: ".*@.+"
        Per default, the Completion-List will be applied for evey Word entered
        '''
        self.keyWordREGEX = Regex_String     #".*@.+"
        self.keyWord = Wordseparator         # " @"     ... is watching for a "@" with a whitespace in front of it
       
    def getWords(self):
        #print('Func "getWords"')
        text = unicode(self.text())#.encode('utf-8')
        #print(text)
        if self.lastindex == -1:
            self.cursorpos = self.cursorPosition()
            self.wordstart = text.rfind(self.keyWord, 0, self.cursorpos) + 1  # all, which is in front of " @" is ONE word. and is ignored.
            #print(self.wordstart)
            #print(self.cursorpos)

        pattern = text[self.wordstart:self.cursorpos]

        #xyz = text.split(" ")
        #pattern = xyz[len(xyz) -1]
        #pattern = "".join(pattern)

        #print(pattern)

        self.partials = [item for item in self.completions if item.lower().startswith(pattern.lower())]
        #print(self.partials)
        return self.partials
       
    def applyCompletion(self, text):
        #oldlen = len(str(self.text()))
        #print('Laenge ohne Umwandlung "old":',oldlen)
        old = unicode(self.text())#.encode('utf-8')
        #print('Laenge nach Umwandlung "%s" ist %d Zeichen lang:' %(old, len(old)))

        self.wordend = old.find(" ", self.cursorpos)
       
        if self.wordend == -1:
            self.wordend = len(old)

        new = unicode(old[:self.wordstart]) + text + unicode(old[self.wordend:]) #beide decodieren ?

        self.setText(new)
        self.setSelection(len(unicode(old)), len(new))   #decode ?

    def get_querySuggestionList(self, query, language='de'):
        '''
        Takes a "query" and a "language"-definition (de = deutsch, en = englisch) and returns a list with search-suggestions
        by Google.com

        Example:
        myreturn = get_querySuggestionList("die", "de")
        print(myreturn)
        [u'die bahn', u'die zeit', u'die welt', u'die bestimmunng]

        please note, that the result is in unicode !
        '''
        querynew = query.replace(" ", "%20")     # replacing all whitespaces wit "%20"
        if query == "":
            #print("EMPTY")
            return []
        link = ('http://suggestqueries.google.com/complete/search?hl=%s&client=chrome&q=%s&hjson=t&cp3' %(language, querynew))
        #print("Asking Google for suggestions...")
        try:
            j = json.loads(unicode(urllib2.urlopen(link, timeout=400).read(), "ISO-8859-1"))
            if len(j) > 0:
                results = j[1]         # result for query "die" = [u'die bahn', u'die zeit', u'die welt', u'die bestimmun...]
            else:
                results = []
            #for suggestion in results:
                #print(suggestion.encode('utf-8'))     # for german umlauts
            #print("Suggestions received")
        except:
            #print("There was a Problem during response ... received an empty list :-(")
            results = []

        return results          # result for query "die" = [u'die bahn', u'die zeit', u'die welt', u'die bestimmun...]
       
    def event(self, event):
        if event.type() == QEvent.KeyPress:

            if event.key() in (Qt.Key_Shift, Qt.Key_Control, Qt.Key_AltGr, Qt.Key_Alt):
                return True

            regex = QRegExp(self.keyWordREGEX, Qt.CaseInsensitive, QRegExp.RegExp)
            if regex.exactMatch(self.text()) and not (event.key() == Qt.Key_Backspace): # 16777219 is the backspace
            #if event.key() != Qt.Key_Backspace and event.key() != Qt.Key_Space:
                QLineEdit.event(self, event)
                self.getWords()
                if not len(self.completions):
                    return True
                if self.text() == "":
                    return True

                if len(self.partials) >= 1:
                    autocomplete = self.partials[0]
                    self.applyCompletion(autocomplete)
                    signalAttach = QString(autocomplete)
                    self.AutoComplete.emit(signalAttach)    #if autocomplete got a "@" in it, only the part, starting with "@..." will be sent
                    return True
                else:
                    signalAttach = QString('NONE')
                    self.AutoComplete.emit(signalAttach)
                    return True


            else:
                return QLineEdit.event(self, event)

        else:
            return QLineEdit.event(self, event)

    ####################### New in V2 ############### Add a clickable Butten into the LineEdit....

    def setSpecialToolButton(self, iconpath=None, Alignment=Qt.AlignRight, tooltip=None):

        self.toolButton = QToolButton(self)
        self.toolButton.setCursor(Qt.PointingHandCursor)
        self.toolButton.setFocusPolicy(Qt.NoFocus)
        if iconpath is not None:
            self.toolButton.setIcon(QIcon(iconpath))
            self.toolButton.setStyleSheet("background: transparent; border: none;")

        layout = QHBoxLayout(self)
        layout.addWidget(self.toolButton,0,Alignment)

        layout.setSpacing(0)
        layout.setMargin(5)
        # ToolTip
        if tooltip is not None:
            self.toolButton.setToolTip(tooltip)
    
    def setSpecialToolButton_newIcon(self, iconpath):
        
        if self.toolButton is not None:
            self.toolButton.setIcon(QIcon(iconpath))