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))
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))
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)
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)
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)
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)
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()
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)
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
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)
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)
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)
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))