def __init__(self): WizardPage.__init__(self) self.fetch_config = None self.app_model = QStringListModel( REGISTRY.names( lambda klass: not getattr(klass, 'disable_in_gui', None))) self.ui.app_combo.setModel(self.app_model) if mozinfo.bits == 64: if mozinfo.os == 'mac': self.bits_model = QStringListModel(['64']) bits_index = 0 else: self.bits_model = QStringListModel(['32', '64']) bits_index = 1 elif mozinfo.bits == 32: self.bits_model = QStringListModel(['32']) bits_index = 0 self.ui.bits_combo.setModel(self.bits_model) self.ui.bits_combo.setCurrentIndex(bits_index) self.build_type_model = QStringListModel() self.ui.app_combo.currentIndexChanged.connect(self._set_fetch_config) self.ui.bits_combo.currentIndexChanged.connect(self._set_fetch_config) self.ui.app_combo.setCurrentIndex( self.ui.app_combo.findText("firefox")) self.ui.repository.textChanged.connect(self._on_repo_changed) completer = QCompleter(sorted(get_branches()), self) completer.setCaseSensitivity(Qt.CaseInsensitive) self.ui.repository.setCompleter(completer) QApplication.instance().focusChanged.connect(self._on_focus_changed)
def __init__(self): WizardPage.__init__(self) self.fetch_config = None self.app_model = QStringListModel( REGISTRY.names( lambda klass: not getattr(klass, 'disable_in_gui', None))) self.ui.app_combo.setModel(self.app_model) if mozinfo.bits == 64: if mozinfo.os == 'mac': self.bits_model = QStringListModel(['64']) bits_index = 0 else: self.bits_model = QStringListModel(['32', '64']) bits_index = 1 elif mozinfo.bits == 32: self.bits_model = QStringListModel(['32']) bits_index = 0 self.ui.bits_combo.setModel(self.bits_model) self.ui.bits_combo.setCurrentIndex(bits_index) self.build_type_model = QStringListModel() self.ui.app_combo.currentIndexChanged.connect(self._set_fetch_config) self.ui.bits_combo.currentIndexChanged.connect(self._set_fetch_config) self.ui.app_combo.setCurrentIndex( self.ui.app_combo.findText("firefox")) completer = QCompleter() completer.setModel(QStringListModel(branches.get_branches( include_aliases=True), self)) completer.setCaseSensitivity(Qt.CaseInsensitive) self.ui.repository.setCompleter(completer)
def __init__(self, parent=None): super(NewEntryDialog, self).__init__(parent) loadUi(__file__, self) # General window settings self.monthTab = parent.currentMonthTab() self.setWindowTitle('New Entry for \'%s\'' % self.monthTab.month()) self.setFixedSize(self.size()) # Entry name LineEdit settings strValidator = QRegExpValidator(QRegExp('.+')) self.nameLineEdit.setValidator(strValidator) completer = QCompleter(self.monthTab.entriesStringList()) completer.setCaseSensitivity(Qt.CaseInsensitive) self.nameLineEdit.setCompleter(completer) # DateEdit settings date = QDate(parent.year(), self.monthTab.monthIndex() + 1, 1) self.dateEdit.setDateRange( date, QDate(date.year(), date.month(), date.daysInMonth())) self.dateEdit.setDate(date) self.dateEdit.setCalendarPopup(True) self.dateEdit.calendarWidget().setFirstDayOfWeek(Qt.Monday) # CategoryComboBox settings self.categoryComboBox.setModel(self.monthTab.categoriesModel()) # OK PushButton settings self.okButton = self.buttonBox.button(QDialogButtonBox.Ok) self.okButton.setEnabled(False) # CONNECTIONS self.nameLineEdit.textEdited.connect(self.setOKButton)
def __init__(self): WizardPage.__init__(self) self.fetch_config = None self.app_model = QStringListModel( REGISTRY.names( lambda klass: not getattr(klass, 'disable_in_gui', None))) self.ui.app_combo.setModel(self.app_model) if mozinfo.bits == 64: if mozinfo.os == 'mac': self.bits_model = QStringListModel(['64']) bits_index = 0 else: self.bits_model = QStringListModel(['32', '64']) bits_index = 1 elif mozinfo.bits == 32: self.bits_model = QStringListModel(['32']) bits_index = 0 self.ui.bits_combo.setModel(self.bits_model) self.ui.bits_combo.setCurrentIndex(bits_index) self.build_type_model = QStringListModel() self.ui.app_combo.currentIndexChanged.connect(self._set_fetch_config) self.ui.bits_combo.currentIndexChanged.connect(self._set_fetch_config) self.ui.app_combo.setCurrentIndex( self.ui.app_combo.findText("firefox")) completer = QCompleter(sorted(get_branches()), self) completer.setCaseSensitivity(Qt.CaseInsensitive) self.ui.repository.setCompleter(completer) QApplication.instance().focusChanged.connect(self._on_focus_changed)
def __init__(self, table_p, parent, product=None, *args, **kwargs): QDialog.__init__(self, parent, *args, **kwargs) self.table_p = table_p self.prod = product self.parent = parent self.filename = "Parcourire ..." self.path_filename = None if self.prod: self.title = u"Modification de l'article {}".format(self.prod.name) self.succes_msg = u"L'article <b>%s</b> a été mise à jour" % self.prod.name try: self.filename = self.prod.file_join.file_name except: pass else: self.succes_msg = u"L'article a été bien enregistré" self.title = u"Ajout de nouvel article" self.prod = Product() self.setWindowTitle(self.title) # self.code = LineEdit(self.prod.code) self.name_field = LineEdit(self.prod.name) try: self.category_name = Category.select().where( Category.name == self.prod.category.name).get().name except: self.category_name = "" self.category_field = LineEdit(self.category_name) self.number_parts_box_field = IntLineEdit( str(self.prod.number_parts_box)) self.number_parts_box_field.setValidator(QIntValidator()) completion_values = [catg.name for catg in Category.all()] completer = QCompleter(completion_values, parent=self) completer.setCaseSensitivity(Qt.CaseInsensitive) completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion) self.category_field.setCompleter(completer) vbox = QVBoxLayout() formbox = QFormLayout() formbox.addRow(FLabel(u"Nom"), self.name_field) formbox.addRow(FLabel(u"Categorie"), self.category_field) # formbox.addRow( # FLabel(u"Quantité (carton)"), self.number_parts_box_field) self.butt_parco = QPushButton( QIcon.fromTheme('document-open', QIcon('')), self.filename) self.butt_parco.clicked.connect(self.import_image) butt_cancel = Warning_btt(u"Annuler") butt_cancel.clicked.connect(self.cancel) # formbox.addRow(FLabel(u"Image"), self.butt_parco) butt = Button_save(u"&Enregistrer") butt.clicked.connect(self.add_or_edit_prod) formbox.addRow(butt_cancel, butt) vbox.addLayout(formbox) self.setLayout(vbox)
class MyLineEdit(Plasma.LineEdit): """Custom LineEdit for Pylou.""" def __init__(self, *args): """Init class.""" Plasma.LineEdit.__init__(self, *args) self.nativeWidget().setClearButtonShown(True) self.nativeWidget().setPlaceholderText("Type to Search...") self.nativeWidget().setToolTip("""<p>Type and press ENTER:to Search<br> UP-DOWN: History navigation<br>Search Empty Query: Clear out""") self.completer = QCompleter(tuple(sorted(set( [_ for _ in listdir(path.expanduser("~")) if not _.startswith(".")] ))), self.nativeWidget()) self.completer.setCompletionMode(QCompleter.InlineCompletion) self.completer.setCaseSensitivity(0) # Qt.CaseInsensitive self.nativeWidget().setCompleter(self.completer) def event(self, event): """Override to enable History Navigation.""" # Qt.Key_Up if event.type() == QEvent.KeyPress and event.key() == 0x01000013: self.emit(SIGNAL("keyUPPressed")) return True # Qt.Key_Down if event.type() == QEvent.KeyPress and event.key() == 0x01000015: self.emit(SIGNAL("keyDownPressed")) return True return Plasma.LineEdit.event(self, event)
def __init__(self): super(CWord, self).__init__(None) self.setWindowTitle("CWord") word_list = QStringList() word_list << "Java" << "C++" << "C#" << "PHP" << "Perl" << "Python" << "Delphi" << "Ruby" completer2 = QCompleter(word_list, self) completer2.setCaseSensitivity(Qt.CaseInsensitive) self.setCompleter(completer2)
def _set_search_completer(self): # Set the completer for the search line edit for showing # previously saved searches. ds = self._config.data_source filter_col = self.cbo_column.itemData(self.cbo_column.currentIndex()) searches = column_searches(ds, filter_col) # Create and set completer completer = QCompleter(searches, self) completer.setCaseSensitivity(Qt.CaseInsensitive) self.txt_keyword.setCompleter(completer)
def __init__(self,expdat): super(DBAnnotateSave, self).__init__() print("DBAnnotateSave") uic.loadUi(os.path.join(hs.heatsequerdir,'ui/manualdata.py'), self) self.bplus.clicked.connect(self.plus) self.bminus.clicked.connect(self.minus) self.bontoinput.returnPressed.connect(self.plus) self.bstudyinfo.clicked.connect(self.studyinfo) self.bisa.toggled.connect(self.radiotoggle) self.bdiffpres.toggled.connect(self.radiotoggle) self.bisatype.currentIndexChanged.connect(self.isatypechanged) self.bhistory.clicked.connect(self.history) self.cexp=expdat self.lnumbact.setText(str(len(expdat.selectedseqs))) completer = QCompleter() self.bontoinput.setCompleter(completer) scdb=hs.scdb self.scdb=scdb self.dataid=hs.supercooldb.finddataid(scdb,datamd5=self.cexp.datamd5,mapmd5=self.cexp.mapmd5) model = QStringListModel() completer.setModel(model) # completer.setCompletionMode(QCompleter.InlineCompletion) completer.maxVisibleItems=10 completer.setCaseSensitivity(Qt.CaseInsensitive) # make the completer selection also erase the text edit completer.activated.connect(self.cleartext,type=Qt.QueuedConnection) # in qt5 should work with middle complete as well... # completer.setFilterMode(Qt.MatchContains) if not hs.scdb.ontologyfromid: hs.scdb=hs.supercooldb.loaddbonto(hs.scdb) self.ontology=hs.scdb.ontology self.ontologyfromid=hs.scdb.ontologyfromid nlist=list(self.ontology.keys()) # nlist=sorted(nlist) nlist=sorted(nlist, key=lambda s: s.lower()) print("sorted ontology") model.setStringList(nlist) self.setWindowTitle(self.cexp.studyname) try: tt=hs.lastdatamd5 except: hs.lastdatamd5='' if self.cexp.datamd5==hs.lastdatamd5: self.fillfromcuration(hs.lastcurations[-1],onlyall=True) self.prefillinfo() self.bontoinput.setFocus()
def __init__(self): super(AddNewWord, self).__init__(None) self.setWindowTitle("AddNewWord") completer = QCompleter(self) self.string_list_model = QStringListModel(self) completer.setCaseSensitivity(Qt.CaseInsensitive) completer.setModel(self.string_list_model) self.setCompleter(completer) self.connect(self, SIGNAL("editingFinished()"), self.editComplete) self.word_list = QStringList()
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))
def _load_labels(self): labels = self.github.get_labels() model = QStringListModel() completer_model = model compl = QCompleter() compl.setModel(model) compl.setCaseSensitivity(Qt.CaseInsensitive) compl.setMaxVisibleItems(50) compl.setModelSorting(QCompleter.CaseInsensitivelySortedModel) compl.setCompletionMode(QCompleter.UnfilteredPopupCompletion) completer_model.setStringList(labels) self.LabelsLineEdit.setCompleter(compl) self.LabelsLineEdit.setText("")
def search_tag(self): ' dialog with an entry field and autocompleter to search and use tags ' dialog, group0, stringy = QDialog(), QGroupBox(), QLineEdit() button, glow = QPushButton(' Make Django Template Tag '), QGraphicsDropShadowEffect() group0.setTitle(__doc__) stringy.setPlaceholderText(' Type to Search . . . ') button.setMinimumSize(200, 50) button.clicked.connect(lambda: self.templatag(str(stringy.text()).lower().strip())) stringy.returnPressed.connect(lambda: self.templatag(str(stringy.text()).lower().strip())) button.released.connect(lambda: dialog.close()) glow.setOffset(0) glow.setBlurRadius(99) glow.setColor(QColor(99, 255, 255)) button.setGraphicsEffect(glow) vboxg0 = QVBoxLayout(group0) for each_widget in (QLabel('<b>Search Tags and Filters as I Type'), stringy, QLabel('<center><small><i>{}'.format(''.join((__doc__, __version__, __license__, 'by', __author__)))), button): vboxg0.addWidget(each_widget) each_widget.setToolTip(each_widget.text()) stringy.setToolTip(' Type and press ENTER ') QVBoxLayout(dialog).addWidget(group0) completer = QCompleter(('autoescape', 'block', 'comment', 'csrf_token', 'cycle', 'debug', 'extends', 'filter', 'firstof', 'for', 'for...empty', 'if', 'ifchanged', 'ifequal', 'ifnotequal', 'include', 'load', 'now', 'regroup', 'spaceless', 'ssi', 'templatetag', 'verbatim', 'in operator', 'not in operator', 'widthratio', 'with', 'add', 'addslashes', 'capfirst', 'center', 'cut', 'date', 'default', 'default_if_none', 'dictsort', 'dictsortreversed', 'divisibleby', 'escape', 'escapejs', 'filesizeformat', 'first', 'fix_ampersands', 'floatformat', 'force_escape', 'get_digit', 'iriencode', 'join', 'last', 'lenght', 'lenght_is', 'linebreaks', 'linebreaksbr', 'linenumbers', 'ljust', 'lower', 'make_list', 'phone2numeric', 'pluralize', 'pprint', 'random', 'removetags', 'rjust', 'safe', 'safeseq', 'slice', 'slugify', 'stringformat', 'striptags', 'time', 'timesince', 'timeuntil', 'title', 'truncatechars', 'truncatewords', 'truncatewords_html', 'htmlcomment', 'unordered_list', 'upper', 'urlencode', 'urlize', 'urlizetrunc', 'wordcount', 'wordwrap', 'yesno', 'apnumber', 'intcomma', 'intword', 'naturalday', 'naturaltime', 'ordinal', 'lorem', 'static', 'iecomment', 'get_static_prefix', 'get_media_prefix', 'singlelinecomment', 'multilinecomment', 'singlelinecommentpopup', 'multilinecommentpopup', 'singlelinecommentclipboard', 'multilinecommentclipboard', 'multilinecommentfile', 'singlelinecommentdatetime'), self) completer.setCompletionMode(QCompleter.PopupCompletion) completer.setCaseSensitivity(0) stringy.setCompleter(completer) dialog.show()
def __init__(self, base): ModalDialog.__init__(self, 290, 110) self.base = base self.setWindowTitle(i18n.get('select_friend_to_send_message')) self.accounts_combo = QComboBox() accounts = self.base.core.get_registered_accounts() for account in accounts: protocol = get_protocol_from(account.id_) icon = QIcon(base.get_image_path('%s.png' % protocol)) self.accounts_combo.addItem(icon, get_username_from(account.id_), account.id_) completer = QCompleter(self.base.load_friends_list()) completer.setCaseSensitivity(Qt.CaseInsensitive) self.friend = QLineEdit() self.friend.setCompleter(completer) select_button = QPushButton(i18n.get('select')) select_button.clicked.connect(self.__validate) friend_caption = "%s (@)" % i18n.get('friend') form = QFormLayout() form.addRow(friend_caption, self.friend) form.addRow(i18n.get('account'), self.accounts_combo) form.setContentsMargins(30, 10, 10, 5) form.setFieldGrowthPolicy(QFormLayout.AllNonFixedFieldsGrow) button = QPushButton(i18n.get('search')) button_box = QHBoxLayout() button_box.addStretch(0) button_box.addWidget(select_button) button_box.setContentsMargins(0, 0, 15, 15) layout = QVBoxLayout() layout.addLayout(form) layout.addLayout(button_box) layout.setSpacing(5) layout.setContentsMargins(0, 0, 0, 0) self.setLayout(layout) #load_button = ImageButton(base, 'action-status-menu.png', # i18n.get('load_friends_list')) self.exec_()
def __init__(self, base): ModalDialog.__init__(self, 290, 110) self.base = base self.setWindowTitle(i18n.get('select_friend_to_send_message')) self.accounts_combo = QComboBox() accounts = self.base.core.get_registered_accounts() for account in accounts: protocol = get_protocol_from(account.id_) icon = QIcon(base.get_image_path('%s.png' % protocol)) self.accounts_combo.addItem(icon, get_username_from(account.id_), account.id_) completer = QCompleter(self.base.load_friends_list()) completer.setCaseSensitivity(Qt.CaseInsensitive) self.friend = QLineEdit() self.friend.setCompleter(completer) select_button = QPushButton(i18n.get('select')) select_button.clicked.connect(self.__validate) friend_caption = "%s (@)" % i18n.get('friend') form = QFormLayout() form.addRow(friend_caption, self.friend) form.addRow(i18n.get('account'), self.accounts_combo) form.setContentsMargins(30, 10, 10, 5) form.setFieldGrowthPolicy(QFormLayout.AllNonFixedFieldsGrow) button = QPushButton(i18n.get('search')) button_box = QHBoxLayout() button_box.addStretch(0) button_box.addWidget(select_button) button_box.setContentsMargins(0, 0, 15, 15) layout = QVBoxLayout() layout.addLayout(form) layout.addLayout(button_box) layout.setSpacing(5) layout.setContentsMargins(0, 0, 0, 0) self.setLayout(layout) #load_button = ImageButton(base, 'action-status-menu.png', # i18n.get('load_friends_list')) self.exec_()
def __init__(self): super(GeneralPreferences, self).__init__() grid = QGridLayout(self) grid.setSpacing(20) grid.setColumnStretch(1, 10) # directory auto completer completer = QCompleter(self) dirs = QDirModel(self) dirs.setFilter(QDir.AllDirs | QDir.NoDotAndDotDot) completer.setModel(dirs) completer.setCaseSensitivity(Qt.CaseInsensitive) completer.setCompletionMode(QCompleter.PopupCompletion) l = QLabel( u"<b>Ingresá el directorio donde descargar los videos...</b>") l.setTextFormat(Qt.RichText) grid.addWidget(l, 0, 0, 1, 2) grid.addWidget(QLabel(u"Descargar en:"), 1, 0, 2, 1) prv = config.get('downloaddir', '') self.downloaddir_entry = QLineEdit(prv) self.downloaddir_entry.setCompleter(completer) self.downloaddir_entry.setPlaceholderText(u'Ingresá un directorio') grid.addWidget(self.downloaddir_entry, 1, 1, 2, 2) self.downloaddir_buttn = QPushButton(u"Elegir un directorio") self.downloaddir_buttn.clicked.connect(self._choose_dir) grid.addWidget(self.downloaddir_buttn, 2, 1, 3, 2) self.autoreload_checkbox = QCheckBox( u"Recargar automáticamente la lista de episodios al iniciar") prv = config.get('autorefresh', False) self.autoreload_checkbox.setChecked(prv) grid.addWidget(self.autoreload_checkbox, 3, 0, 4, 2) self.shownotifs_checkbox = QCheckBox( u"Mostrar una notificación cuando termina cada descarga") prv = config.get('notification', True) self.shownotifs_checkbox.setChecked(prv) grid.addWidget(self.shownotifs_checkbox, 4, 0, 5, 2)
def __init__(self): super(GeneralPreferences, self).__init__() grid = QGridLayout(self) grid.setSpacing(20) grid.setColumnStretch(1, 10) # directory auto completer completer = QCompleter(self) dirs = QDirModel(self) dirs.setFilter(QDir.AllDirs | QDir.NoDotAndDotDot) completer.setModel(dirs) completer.setCaseSensitivity(Qt.CaseInsensitive) completer.setCompletionMode(QCompleter.PopupCompletion) l = QLabel( u"<b>Ingresá el directorio donde descargar los videos...</b>") l.setTextFormat(Qt.RichText) grid.addWidget(l, 0, 0, 1, 2) grid.addWidget(QLabel(u"Descargar en:"), 1, 0, 2, 1) prv = config.get('downloaddir', '') self.downloaddir_entry = QLineEdit(prv) self.downloaddir_entry.setCompleter(completer) self.downloaddir_entry.setPlaceholderText(u'Ingresá un directorio') grid.addWidget(self.downloaddir_entry, 1, 1, 2, 2) self.downloaddir_buttn = QPushButton(u"Elegir un directorio") self.downloaddir_buttn.clicked.connect(self._choose_dir) grid.addWidget(self.downloaddir_buttn, 2, 1, 3, 2) self.autoreload_checkbox = QCheckBox( u"Recargar automáticamente la lista de episodios al iniciar") prv = config.get('autorefresh', False) self.autoreload_checkbox.setChecked(prv) grid.addWidget(self.autoreload_checkbox, 3, 0, 4, 2) self.shownotifs_checkbox = QCheckBox( u"Mostrar una notificación cuando termina cada descarga") prv = config.get('notification', True) self.shownotifs_checkbox.setChecked(prv) grid.addWidget(self.shownotifs_checkbox, 4, 0, 5, 2)
def updateEditModels( self ): # Rellenar el combobox de los proveedores self.providersModel.setQuery( """ SELECT idpersona , nombre AS proveedor FROM personas WHERE tipopersona = 2 """ ) if not self.providersModel.rowCount( QModelIndex() ) > 0: raise UserWarning( "No existen proveedores en la base de datos" ) self.cbProvider.setModel( self.providersModel ) self.cbProvider.setModelColumn( 1 ) completer = QCompleter() completer.setCaseSensitivity( Qt.CaseInsensitive ) completer.setModel( self.providersModel ) completer.setCompletionColumn( 1 ) self.editmodel.providerId = self.providersModel.record( self.cbProvider.currentIndex() ).value( "idpersona" ).toInt()[0] query = QSqlQuery( """ SELECT idarticulo, Descripcion as descripcion FROM vw_articulosdescritos """ ) if not query.size() > 0: raise UserWarning( "No existen productos en la base de datos" ) prods = SingleSelectionModel() query.exec_() while query.next(): prods.items.append( [ query.value( 0 ).toInt()[0], query.value( 1 ).toString() ] ) prods.headers = ["idarticulo", "Articulo"] self.delegate.prods = prods
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 ParentManage(ParentAction, object): def __init__(self, iface, settings, controller, plugin_dir): """ Class to keep common functions of classes 'ManageDocument', 'ManageElement' and 'ManageVisit' of toolbar 'edit'.""" super(ParentManage, self).__init__(iface, settings, controller, plugin_dir) self.x = "" self.y = "" self.canvas = self.iface.mapCanvas() self.plan_om = None self.previous_map_tool = None self.autocommit = True self.lazy_widget = None self.workcat_id_end = None def reset_lists(self): """ Reset list of selected records """ self.ids = [] self.list_ids = {} self.list_ids['node'] = [] def reset_layers(self): """ Reset list of layers """ self.layers = {} self.layers['node'] = [] self.visible_layers = [] def remove_selection(self): """ Remove all previous selections """ try: for layer in self.layers['node']: if layer in self.visible_layers: self.iface.legendInterface().setLayerVisible(layer, False) for layer in self.layers['node']: if layer in self.visible_layers: self.iface.legendInterface().setLayerVisible(layer, True) layer.removeSelection() except: pass self.canvas.refresh() self.canvas.setMapTool(self.previous_map_tool) def add_point(self): """ Create the appropriate map tool and connect to the corresponding signal """ self.emit_point = QgsMapToolEmitPoint(self.canvas) self.previous_map_tool = self.canvas.mapTool() self.canvas.setMapTool(self.emit_point) self.emit_point.canvasClicked.connect(partial(self.get_xy)) def get_xy(self, point): """ Get coordinates of selected point """ self.x = point.x() self.y = point.y() message = "Geometry has been added!" self.controller.show_info(message) self.emit_point.canvasClicked.disconnect() def set_completer_feature_id(self, widget, geom_type, viewname): """ Set autocomplete of widget 'feature_id' getting id's from selected @viewname """ # Adding auto-completion to a QLineEdit self.completer = QCompleter() self.completer.setCaseSensitivity(Qt.CaseInsensitive) widget.setCompleter(self.completer) model = QStringListModel() sql = ("SELECT " + geom_type + "_id" " FROM " + self.schema_name + "." + viewname) row = self.controller.get_rows(sql, commit=self.autocommit) if row: for i in range(0, len(row)): aux = row[i] row[i] = str(aux[0]) model.setStringList(row) self.completer.setModel(model) def set_table_model(self, qtable, geom_type, expr_filter): """ Sets a TableModel to @widget_name attached to @table_name and filter @expr_filter """ expr = None if expr_filter: # Check expression (is_valid, expr) = self.check_expression(expr_filter) # @UnusedVariable if not is_valid: return expr # Set a model with selected filter expression table_name = "v_edit_" + geom_type if self.schema_name not in table_name: table_name = self.schema_name + "." + table_name # Set the model model = QSqlTableModel() model.setTable(table_name) model.setEditStrategy(QSqlTableModel.OnManualSubmit) model.select() if model.lastError().isValid(): self.controller.show_warning(model.lastError().text()) return expr # Attach model to selected widget if type(qtable) is QTableView: widget = qtable else: message = "Table_object is not a table name or QTableView" self.controller.log_info(message) return expr if expr_filter: widget.setModel(model) widget.model().setFilter(expr_filter) widget.model().select() else: widget.setModel(None) return expr def apply_lazy_init(self, widget): """Apply the init function related to the model. It's necessary a lazy init because model is changed everytime is loaded.""" if self.lazy_widget is None: return if widget != self.lazy_widget: return self.lazy_init_function(self.lazy_widget) def lazy_configuration(self, widget, init_function): """set the init_function where all necessary events are set. This is necessary to allow a lazy setup of the events because set_table_events can create a table with a None model loosing any event connection.""" # TODO: create a dictionary with key:widged.objectName value:initFuction # to allow multiple lazy initialization self.lazy_widget = widget self.lazy_init_function = init_function def select_features_by_ids(self, geom_type, expr): """ Select features of layers of group @geom_type applying @expr """ # Build a list of feature id's and select them for layer in self.layers[geom_type]: if expr is None: layer.removeSelection() else: it = layer.getFeatures(QgsFeatureRequest(expr)) id_list = [i.id() for i in it] if len(id_list) > 0: layer.selectByIds(id_list) else: layer.removeSelection() def delete_records(self, dialog, table_object): """ Delete selected elements of the table """ self.disconnect_signal_selection_changed() if type(table_object) is str: widget_name = "tbl_" + table_object + "_x_" + self.geom_type widget = widget_manager.getWidget(dialog, widget_name) if not widget: message = "Widget not found" self.controller.show_warning(message, parameter=widget_name) return elif type(table_object) is QTableView: widget = table_object else: message = "Table_object is not a table name or QTableView" self.controller.log_info(message) return # Get selected rows selected_list = widget.selectionModel().selectedRows() if len(selected_list) == 0: message = "Any record selected" self.controller.show_info_box(message) return self.ids = self.list_ids[self.geom_type] field_id = self.geom_type + "_id" del_id = [] inf_text = "" for i in range(0, len(selected_list)): row = selected_list[i].row() id_feature = widget.model().record(row).value(field_id) inf_text += str(id_feature) + ", " del_id.append(id_feature) inf_text = inf_text[:-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: for el in del_id: self.ids.remove(el) else: return expr_filter = None expr = None if len(self.ids) > 0: # Set expression filter with features in the list expr_filter = "\"" + field_id + "\" IN (" for i in range(len(self.ids)): expr_filter += "'" + str(self.ids[i]) + "', " expr_filter = expr_filter[:-2] + ")" # Check expression (is_valid, expr) = self.check_expression(expr_filter) # @UnusedVariable if not is_valid: return # Update model of the widget with selected expr_filter self.reload_table(table_object, self.geom_type, expr_filter) self.apply_lazy_init(table_object) # Select features with previous filter # Build a list of feature id's and select them self.select_features_by_ids(self.geom_type, expr) # Update list self.list_ids[self.geom_type] = self.ids self.connect_signal_selection_changed(table_object) def selection_init(self, table_object): """ Set canvas map tool to an instance of class 'MultipleSelection' """ current_visible_layers = self.get_visible_layers() for layer in current_visible_layers: if layer not in self.visible_layers: self.visible_layers.append(layer) self.controller.log_info(str(self.visible_layers)) multiple_selection = MultipleSelection(self.iface, self.controller, self.layers[self.geom_type], parent_manage=self, table_object=table_object) self.previous_map_tool = self.canvas.mapTool() self.canvas.setMapTool(multiple_selection) self.disconnect_signal_selection_changed() self.connect_signal_selection_changed(table_object) cursor = self.get_cursor_multiple_selection() self.canvas.setCursor(cursor) def selection_changed(self, qtable, geom_type): """ Slot function for signal 'canvas.selectionChanged' """ self.disconnect_signal_selection_changed() field_id = geom_type + "_id" self.ids = [] # Iterate over all layers of the group for layer in self.layers[self.geom_type]: if layer.selectedFeatureCount() > 0 and self.iface.legendInterface( ).isLayerVisible(layer): # Get selected features of the layer features = layer.selectedFeatures() for feature in features: # Append 'feature_id' into the list selected_id = feature.attribute(field_id) if selected_id not in self.ids: self.ids.append(selected_id) if geom_type == 'node': self.list_ids['node'] = self.ids expr_filter = None if len(self.ids) > 0: # Set 'expr_filter' with features that are in the list expr_filter = "\"" + field_id + "\" IN (" for i in range(len(self.ids)): expr_filter += "'" + str(self.ids[i]) + "', " expr_filter = expr_filter[:-2] + ")" # Check expression (is_valid, expr) = self.check_expression(expr_filter) # @UnusedVariable if not is_valid: return self.select_features_by_ids(geom_type, expr) # Reload contents of table 'tbl_@table_object_x_@geom_type' self.reload_table(qtable, self.geom_type, expr_filter) self.apply_lazy_init(qtable) # Remove selection in generic 'v_edit' layers #self.remove_selection(False) self.connect_signal_selection_changed(qtable) def insert_feature(self, widget, table_object): """ Select feature with entered id. Set a model with selected filter. Attach that model to selected table """ self.disconnect_signal_selection_changed() # Clear list of ids self.ids = [] field_id = self.geom_type + "_id" feature_id = widget.text() if feature_id == 'null': message = "You need to enter a feature id" self.controller.show_info_box(message) return # Iterate over all layers of the group for layer in self.layers[self.geom_type]: if layer.selectedFeatureCount() > 0: # Get selected features of the layer features = layer.selectedFeatures() for feature in features: # Append 'feature_id' into the list selected_id = feature.attribute(field_id) self.ids.append(selected_id) if feature_id not in self.ids: # If feature id doesn't exist in list -> add self.ids.append(str(feature_id)) # Set expression filter with features in the list expr_filter = "\"" + field_id + "\" IN (" for i in range(len(self.ids)): expr_filter += "'" + str(self.ids[i]) + "', " expr_filter = expr_filter[:-2] + ")" # Check expression (is_valid, expr) = self.check_expression(expr_filter) if not is_valid: return # Select features with previous filter # Build a list of feature id's and select them for layer in self.layers[self.geom_type]: it = layer.getFeatures(QgsFeatureRequest(expr)) id_list = [i.id() for i in it] if len(id_list) > 0: layer.selectByIds(id_list) # Reload contents of table 'tbl_???_x_@geom_type' self.reload_table(table_object, self.geom_type, expr_filter) self.apply_lazy_init(table_object) # Update list self.list_ids[self.geom_type] = self.ids self.connect_signal_selection_changed(table_object) def disconnect_snapping(self): """ Select 'Pan' as current map tool and disconnect snapping """ try: self.iface.actionPan().trigger() self.canvas.xyCoordinates.disconnect() if self.emit_point: self.emit_point.canvasClicked.disconnect() except: pass def connect_signal_selection_changed(self, table_object): """ Connect signal selectionChanged """ try: self.canvas.selectionChanged.connect( partial(self.selection_changed, table_object, self.geom_type)) except Exception: pass def disconnect_signal_selection_changed(self): """ Disconnect signal selectionChanged """ try: self.canvas.selectionChanged.disconnect() except Exception: pass def fill_widget_with_fields(self, dialog, data_object, field_names): """Fill the Widget with value get from data_object limited to the list of field_names.""" for field_name in field_names: value = getattr(data_object, field_name) if not hasattr(dialog, field_name): continue widget = getattr(dialog, field_name) if type(widget) in [QDateEdit, QDateTimeEdit]: widget.setDateTime(value if value else QDate.currentDate()) if type(widget) in [QLineEdit, QTextEdit]: if value: widget.setText(value) else: widget.clear() if type(widget) in [QComboBox]: if not value: widget.setCurrentIndex(0) continue # look the value in item text index = widget.findText(str(value)) if index >= 0: widget.setCurrentIndex(index) continue # look the value in itemData index = widget.findData(value) if index >= 0: widget.setCurrentIndex(index) continue def reload_table(self, qtable, geom_type, expr_filter): """ Reload @widget with contents of @tablename applying selected @expr_filter """ if type(qtable) is QTableView: widget = qtable else: message = "Table_object is not a table name or QTableView" self.controller.log_info(message) return None expr = self.set_table_model(widget, geom_type, expr_filter) return expr def get_visible_layers(self, return_as_list=True): """ Return list or string as {...} with all visible layer in TOC """ visible_layer = [] if return_as_list: for layer in self.iface.legendInterface().layers(): if self.iface.legendInterface().isLayerVisible(layer): visible_layer.append(layer) #visible_layer = [lyr for lyr in QgsMapLayerRegistry.instance().mapLayers().values()] return visible_layer for layer in self.iface.legendInterface().layers(): if self.iface.legendInterface().isLayerVisible(layer): visible_layer += '"' + str(layer.name()) + '", ' visible_layer = visible_layer[:-2] + "}" return visible_layer
class TagCompleterWidget(QObject): """ widget in lineEdit-style with integrated qcompleter """ def __init__(self, max_tags, expiry_prefix=None, tag_list=None, parent=None, separator=",", show_datestamp=False): QWidget.__init__(self, parent) self.__completer_active = False self.__max_tags = max_tags self.__tag_separator = separator self.__tag_list = tag_list self.__parent = parent self.__tag_line = QLineEdit(self.__parent) #self.__tag_line = TagLineEdit(self.__parent) self.__show_datestamp = show_datestamp self.__datestamp_format = TsConstants.DATESTAMP_FORMAT_DAY self.__expiry_prefix = expiry_prefix ## flag, if the line should be checked of emptiness self.__check_not_empty = False self.__check_tag_limit = False self.__restricted_vocabulary = False ## the latest activated suggestion self.__activated_text = None # value of the actual datestamp self.__datestamp = None self.__datestamp_hidden = False self.__completer = QCompleter(self.__tag_list, self); self.__completer.setCaseSensitivity(Qt.CaseInsensitive) self.__completer.setWidget(self.__tag_line) #self.__handle_datestamp() self.connect(self.__tag_line, SIGNAL("textChanged(QString)"), self.__text_changed_by_user) self.connect(self.__completer, SIGNAL("activated(QString)"), self.__text_activated) self.connect(self.__completer, SIGNAL("highlighted(QString)"), self.__text_highlighted) def __text_highlighted(self, item_name): """ a suggestion has been selected in the dropdownbox """ # set this variable to True just to know, that # this value comes from the completer and not from the user self.__completer_active = True self.__text_selected(item_name) self.__completer_active = False def __handle_datestamp(self, is_hidden): """ if the show_datestamp flag is set to True, provide an automatic datestamp on the tagline """ if self.__show_datestamp: self.__datestamp = time.strftime(self.__datestamp_format) if not is_hidden: self.__tag_line.clear() self.__tag_line.setText(self.__datestamp) def set_datestamp_format(self, format, is_hidden): self.__datestamp_format = format self.__datestamp_hidden = is_hidden self.__handle_datestamp(is_hidden) def show_datestamp(self, show): self.__show_datestamp = show self.__handle_datestamp(show) def clear_line(self): """ clear the tagline ... if auto datestamp is set to "on" a fresh stamp will be placed into the tagline """ self.__tag_line.clear() if self.__show_datestamp: self.__handle_datestamp(self.__datestamp_hidden) def set_check_not_empty(self, check_necessary): """ set this to True, if there should be sent a signal that indicates that the tagline is not empty anymore """ self.__check_not_empty = True def set_restricted_vocabulary(self, is_restricted): """ use True/False to turn the restricted function on/off """ self.__restricted_vocabulary = is_restricted def select_line(self): """ select the tagline ... """ self.__tag_line.selectAll() self.__tag_line.setFocus(QtCore.Qt.OtherFocusReason) def __text_changed_by_user(self, text): # create a QByteArray in utf8 all_text = text.toUtf8() # make a python string out of it all_text = str(all_text) # convert the python string tu unicode utf-8 all_text = unicode(all_text, "utf-8") if self.__check_not_empty: if all_text is not None and all_text != "": self.emit(QtCore.SIGNAL("line_empty"), False) else: self.emit(QtCore.SIGNAL("line_empty"), True) text = all_text[:self.__tag_line.cursorPosition()] ## remove whitespace and filter out duplicates by using a set tag_set = set([]) for tag in all_text.split(self.__tag_separator): strip_tag = tag.strip() if strip_tag != "": tag_set.add(strip_tag) max_tags = self.__max_tags if self.__datestamp_hidden: max_tags = max_tags - 1; ## do not proceed if the max tag count is reached if len(tag_set) > max_tags: self.emit(QtCore.SIGNAL("tag_limit_reached"), True) self.__check_tag_limit = True return else: if self.__check_tag_limit: self.emit(QtCore.SIGNAL("tag_limit_reached"), False) self.__check_tag_limit = False prefix = text.split(self.__tag_separator)[-1].strip() if not self.__completer_active: self.__update_completer(tag_set, prefix) def __update_completer(self, tag_set, completion_prefix): if self.__tag_list is None: return tags = list(set(self.__tag_list).difference(tag_set)) #tags = list(self.__tag_list) model = QStringListModel(tags, self) self.__completer.setModel(model) self.__completer.setCompletionPrefix(completion_prefix) if self.__restricted_vocabulary: self.__check_vocabulary(tag_set, completion_prefix) if completion_prefix.strip() != '': ## use the default completion algorithm self.__completer.complete() def __check_finished_tags(self, typed_tags_list): """ use this method to control all typed tags. this means all tags terminated with a comma """ pass def __check_in_completion_list(self, tag): """ if a written tag equals a tag of the completion list - the tag will be removed from the completion list so the completer will return a completion count of 0 for this tag. in this case there would be displayed an error message at the dialog (when controlled vocab is activated) so check manually, if the provided tag is contained in the suggestion_list """ #for sug_tag in self.__tag_list: # if sug_tag == tag: # return True #return False return tag in self.__tag_list def __check_vocabulary(self, tag_set, completion_prefix): """ have a look at the entered tag to be completed. if restricted vocabulary is turned on: datestamps do not have to be checked. """ not_allowed_tags_count = 0 no_completion_found = False stripped_text = unicode(self.__tag_line.text()).strip() ##when a tag separator is on the last position, there should have been entered a new tag ##check this tag for its correctness if len(stripped_text) > 0: ##check if all written tags are allowed (incl. datestamps an expiry tags) for tag in tag_set: ## tag can be a datestamp -> OK if not SpecialCharHelper.is_datestamp(tag) and tag != "": ## tag can be an expiry tag -> OK # if self.__expiry_prefix is not None and not SpecialCharHelper.is_expiry_tag(self.__expiry_prefix, tag): if self.__expiry_prefix is None or not SpecialCharHelper.is_partial_expiry_tag(self.__expiry_prefix, tag): if unicode(tag) not in self.__tag_list: not_allowed_tags_count += 1 if(completion_prefix.strip() == ""): ## if the prefix is an empty string - manually set the completion_count to 0 ## because the completer would return the whole number of tags in its suggestion list completion_count = 0 else: completion_count = self.__completer.completionCount() if self.__restricted_vocabulary and completion_count == 0: ## additionally check if the prefix equals a tag from the suggestion list ## this has to be done, because we do not get a completionCount > 0 if the prefix equals a given tag #if completion_prefix not in self.__tag_list: if completion_prefix is not None and len(completion_prefix) > 0 and completion_prefix.strip() != "": ## just send the signal if the tag is no datestamp AND if it is no full tag if not SpecialCharHelper.is_datestamp(completion_prefix) and not self.__check_in_completion_list(completion_prefix): if not SpecialCharHelper.is_partial_expiry_tag(self.__expiry_prefix, completion_prefix): no_completion_found = True ## there are tags (terminated with comma) which are not in the allowed tag_list if not_allowed_tags_count > 1: self.emit(QtCore.SIGNAL("no_completion_found"), True) return if not_allowed_tags_count > 0: ## in this case the user has entered a not allowed tag and terminated it with a comma to mark it as a tag ## the completion count is 0 because there is nothing after the last comma in the taglist if completion_count == 0: self.emit(QtCore.SIGNAL("no_completion_found"), True) return ## it could be the case, that the user is still typing an allowed tag ## so check, if the completer has a possible completion ## if not -> send the signal if no_completion_found: self.emit(QtCore.SIGNAL("no_completion_found"), True) return ## everytime there is no completion found, emit the signal elif no_completion_found: self.emit(QtCore.SIGNAL("no_completion_found"), True) return ## in this case everything is fine self.emit(QtCore.SIGNAL("no_completion_found"), False) def __text_selected(self, text): self.__activated_text = text cursor_pos = self.__tag_line.cursorPosition() before_text = unicode(self.__tag_line.text())[:cursor_pos] #after_text = unicode(self.__tag_line.text())[cursor_pos:] prefix_len = len(before_text.split(self.__tag_separator)[-1].strip()) self.__tag_line.setText("%s%s" % (before_text[:cursor_pos - prefix_len], text)) self.__tag_line.setCursorPosition(cursor_pos - prefix_len + len(text) + 2) def __text_activated(self, text): """ a suggestion has been choosen by the user """ self.__text_selected(text) self.emit(QtCore.SIGNAL("activated")) def get_tag_list(self): tag_string = unicode(self.__tag_line.text()) result = set([]) tag_list = tag_string.split(self.__tag_separator) for tag in tag_list: strip_tag = tag.strip() if strip_tag != "": result.add(strip_tag) # if the datestamp is hidden, add it manually to the taglist if self.__datestamp_hidden: result.add(self.__datestamp) return result def get_tag_line(self): return self.__tag_line def get_completer(self): return self.__completer def set_enabled(self, enable): self.__tag_line.setEnabled(enable) def set_text(self, text): self.__tag_line.setText(text) def set_tag_completion_list(self, tag_list): self.__tag_list = tag_list self.__completer.setModel(QtGui.QStringListModel(QtCore.QStringList(tag_list))) def get_tag_completion_list(self): return self.__tag_list def is_empty(self): if self.__tag_line.text() == "": return True else: return False def set_place_holder_text(self, text): self.__tag_line.setPlaceholderText(text)
class ParentManage(ParentAction, object): def __init__(self, iface, settings, controller, plugin_dir): """ Class to keep common functions of classes 'ManageDocument', 'ManageElement' and 'ManageVisit' of toolbar 'edit'.""" super(ParentManage, self).__init__(iface, settings, controller, plugin_dir) self.x = "" self.y = "" self.canvas = self.iface.mapCanvas() self.plan_om = None self.previous_map_tool = None self.autocommit = True self.lazy_widget = None self.workcat_id_end = None self.xyCoordinates_conected = False self.remove_ids = True def reset_lists(self): """ Reset list of selected records """ self.ids = [] self.list_ids = {} self.list_ids['arc'] = [] self.list_ids['node'] = [] self.list_ids['connec'] = [] self.list_ids['gully'] = [] self.list_ids['element'] = [] def reset_layers(self): """ Reset list of layers """ self.layers = {} self.layers['arc'] = [] self.layers['node'] = [] self.layers['connec'] = [] self.layers['gully'] = [] self.layers['element'] = [] def reset_model(self, dialog, table_object, geom_type): """ Reset model of the widget """ table_relation = table_object + "_x_" + geom_type widget_name = "tbl_" + table_relation widget = utils_giswater.getWidget(dialog, widget_name) if widget: widget.setModel(None) def remove_selection(self, remove_groups=True): """ Remove all previous selections """ layer = self.controller.get_layer_by_tablename("v_edit_arc") if layer: layer.removeSelection() layer = self.controller.get_layer_by_tablename("v_edit_node") if layer: layer.removeSelection() layer = self.controller.get_layer_by_tablename("v_edit_connec") if layer: layer.removeSelection() layer = self.controller.get_layer_by_tablename("v_edit_element") if layer: layer.removeSelection() if self.project_type == 'ud': layer = self.controller.get_layer_by_tablename("v_edit_gully") if layer: layer.removeSelection() try: if remove_groups: for layer in self.layers['arc']: layer.removeSelection() for layer in self.layers['node']: layer.removeSelection() for layer in self.layers['connec']: layer.removeSelection() for layer in self.layers['gully']: layer.removeSelection() for layer in self.layers['element']: layer.removeSelection() except: pass self.canvas.refresh() def reset_widgets(self, dialog, table_object): """ Clear contents of input widgets """ if table_object == "doc": utils_giswater.setWidgetText(dialog, "doc_type", "") utils_giswater.setWidgetText(dialog, "observ", "") utils_giswater.setWidgetText(dialog, "path", "") elif table_object == "element": utils_giswater.setWidgetText(dialog, "elementcat_id", "") utils_giswater.setWidgetText(dialog, "state", "") utils_giswater.setWidgetText(dialog, "expl_id","") utils_giswater.setWidgetText(dialog, "ownercat_id", "") utils_giswater.setWidgetText(dialog, "location_type", "") utils_giswater.setWidgetText(dialog, "buildercat_id", "") utils_giswater.setWidgetText(dialog, "workcat_id", "") utils_giswater.setWidgetText(dialog, "workcat_id_end", "") utils_giswater.setWidgetText(dialog, "comment", "") utils_giswater.setWidgetText(dialog, "observ", "") utils_giswater.setWidgetText(dialog, "path", "") utils_giswater.setWidgetText(dialog, "rotation", "") utils_giswater.setWidgetText(dialog, "verified", "") utils_giswater.setWidgetText(dialog, dialog.num_elements, "") def fill_widgets(self, dialog, table_object, row): """ Fill input widgets with data int he @row """ if table_object == "doc": utils_giswater.setWidgetText(dialog, "doc_type", row["doc_type"]) utils_giswater.setWidgetText(dialog, "observ", row["observ"]) utils_giswater.setWidgetText(dialog, "path", row["path"]) elif table_object == "element": state = "" if row['state']: sql = ("SELECT name FROM " + self.schema_name + ".value_state" " WHERE id = '" + str(row['state']) + "'") row_aux = self.controller.get_row(sql, commit=self.autocommit) if row_aux: state = row_aux[0] expl_id = "" if row['expl_id']: sql = ("SELECT name FROM " + self.schema_name + ".exploitation" " WHERE expl_id = '" + str(row['expl_id']) + "'") row_aux = self.controller.get_row(sql, commit=self.autocommit) if row_aux: expl_id = row_aux[0] utils_giswater.setWidgetText(dialog, "code", row['code']) sql = ("SELECT elementtype_id FROM " + self.schema_name + ".cat_element" " WHERE id = '" + str(row['elementcat_id']) + "'") row_type = self.controller.get_row(sql) if row_type: utils_giswater.setWidgetText(dialog, "element_type", row_type[0]) utils_giswater.setWidgetText(dialog, "elementcat_id", row['elementcat_id']) utils_giswater.setWidgetText(dialog, "num_elements", row['num_elements']) utils_giswater.setWidgetText(dialog, "state", state) utils_giswater.setWidgetText(dialog, "expl_id", expl_id) utils_giswater.setWidgetText(dialog, "ownercat_id", row['ownercat_id']) utils_giswater.setWidgetText(dialog, "location_type", row['location_type']) utils_giswater.setWidgetText(dialog, "buildercat_id", row['buildercat_id']) builtdate = QDate.fromString(str(row['builtdate']), 'yyyy-MM-dd') dialog.builtdate.setDate(builtdate) utils_giswater.setWidgetText(dialog, "workcat_id", row['workcat_id']) utils_giswater.setWidgetText(dialog, "workcat_id_end", row['workcat_id_end']) utils_giswater.setWidgetText(dialog, "comment", row['comment']) utils_giswater.setWidgetText(dialog, "observ", row['observ']) utils_giswater.setWidgetText(dialog, "link", row['link']) utils_giswater.setWidgetText(dialog, "verified", row['verified']) utils_giswater.setWidgetText(dialog, "rotation", row['rotation']) if str(row['undelete']) == 'True': dialog.undelete.setChecked(True) def get_records_geom_type(self, dialog, table_object, geom_type): """ Get records of @geom_type associated to selected @table_object """ object_id = utils_giswater.getWidgetText(dialog, table_object + "_id") table_relation = table_object + "_x_" + geom_type widget_name = "tbl_" + table_relation exists = self.controller.check_table(table_relation) if not exists: self.controller.log_info("Not found: " + str(table_relation)) return sql = ("SELECT " + geom_type + "_id" " FROM " + self.schema_name + "." + table_relation + "" " WHERE " + table_object + "_id = '" + str(object_id) + "'") rows = self.controller.get_rows(sql, log_info=False) if rows: for row in rows: self.list_ids[geom_type].append(str(row[0])) self.ids.append(str(row[0])) expr_filter = self.get_expr_filter(geom_type) self.set_table_model(dialog, widget_name, geom_type, expr_filter) def exist_object(self, dialog, table_object): """ Check if selected object (document or element) already exists """ # Reset list of selected records self.reset_lists() field_object_id = "id" if table_object == "element": field_object_id = table_object + "_id" object_id = utils_giswater.getWidgetText(dialog, table_object + "_id") # Check if we already have data with selected object_id sql = ("SELECT * " " FROM " + self.schema_name + "." + str(table_object) + "" " WHERE " + str(field_object_id) + " = '" + str(object_id) + "'") row = self.controller.get_row(sql, log_info=False) # If object_id not found: Clear data if not row: self.reset_widgets(dialog, table_object) if table_object == 'element': self.set_combo(dialog, 'state', 'value_state', 'state_vdefault', field_name='name') self.set_combo(dialog, 'expl_id', 'exploitation', 'exploitation_vdefault', field_id='expl_id',field_name='name') self.set_calendars(dialog, 'builtdate', 'config_param_user', 'value', 'builtdate_vdefault') self.set_combo(dialog, 'workcat_id', 'cat_work', 'workcat_vdefault', field_id='id', field_name='id') if hasattr(self, 'single_tool_mode'): # some tools can work differently if standalone or integrated in # another tool if self.single_tool_mode: self.remove_selection(True) else: self.remove_selection(True) self.reset_model(dialog, table_object, "arc") self.reset_model(dialog, table_object, "node") self.reset_model(dialog, table_object, "connec") self.reset_model(dialog, table_object, "element") if self.project_type == 'ud': self.reset_model(dialog, table_object, "gully") return # Fill input widgets with data of the @row self.fill_widgets(dialog, table_object, row) # Check related 'arcs' self.get_records_geom_type(dialog, table_object, "arc") # Check related 'nodes' self.get_records_geom_type(dialog, table_object, "node") # Check related 'connecs' self.get_records_geom_type(dialog, table_object, "connec") # Check related 'elements' self.get_records_geom_type(dialog, table_object, "element") # Check related 'gullys' if self.project_type == 'ud': self.get_records_geom_type(dialog, table_object, "gully") def populate_combo(self, dialog, widget, table_name, field_name="id"): """ Executes query and fill combo box """ sql = ("SELECT " + field_name + "" " FROM " + self.schema_name + "." + table_name + "" " ORDER BY " + field_name) rows = self.controller.get_rows(sql, commit=self.autocommit) utils_giswater.fillComboBox(dialog, widget, rows) if rows: utils_giswater.setCurrentIndex(dialog, widget, 0) def set_combo(self, dialog, widget, table_name, parameter, field_id='id', field_name='id'): """ Executes query and set combo box """ sql = ("SELECT t1." + field_name + " FROM " + self.schema_name + "." + table_name + " as t1" " INNER JOIN " + self.schema_name + ".config_param_user as t2 ON t1." + field_id + "::text = t2.value::text" " WHERE parameter = '" + parameter + "' AND cur_user = current_user") row = self.controller.get_row(sql) if row: utils_giswater.setWidgetText(dialog, widget, row[0]) def set_calendars(self, dialog, widget, table_name, value, parameter): """ Executes query and set QDateEdit """ sql = ("SELECT " + value + " FROM " + self.schema_name + "." + table_name + "" " WHERE parameter = '" + parameter + "' AND cur_user = current_user") row = self.controller.get_row(sql) if row: date = QDate.fromString(row[0], 'yyyy-MM-dd') else: date = QDate.currentDate() utils_giswater.setCalendarDate(dialog, widget, date) def add_point(self): """ Create the appropriate map tool and connect to the corresponding signal """ active_layer = self.iface.activeLayer() if active_layer is None: active_layer = self.controller.get_layer_by_tablename('version') self.iface.setActiveLayer(active_layer) # Vertex marker self.vertex_marker = QgsVertexMarker(self.canvas) self.vertex_marker.setColor(QColor(255, 100, 255)) self.vertex_marker.setIconSize(15) self.vertex_marker.setIconType(QgsVertexMarker.ICON_CROSS) self.vertex_marker.setPenWidth(3) # Snapper self.snapper = QgsMapCanvasSnapper(self.canvas) self.emit_point = QgsMapToolEmitPoint(self.canvas) self.previous_map_tool = self.canvas.mapTool() self.canvas.setMapTool(self.emit_point) #self.canvas.connect(self.canvas, SIGNAL("xyCoordinates(const QgsPoint&)"), self.mouse_move) self.canvas.xyCoordinates.connect(self.mouse_move) self.xyCoordinates_conected = True self.emit_point.canvasClicked.connect(partial(self.get_xy)) def mouse_move(self, p): self.snapped_point = None self.vertex_marker.hide() map_point = self.canvas.getCoordinateTransform().transform(p) x = map_point.x() y = map_point.y() eventPoint = QPoint(x, y) # Snapping (retval, result) = self.snapper.snapToBackgroundLayers(eventPoint) # @UnusedVariable # That's the snapped point if result: # Check feature for snapped_point in result: self.snapped_point = QgsPoint(snapped_point.snappedVertex) self.vertex_marker.setCenter(self.snapped_point) self.vertex_marker.show() else: self.vertex_marker.hide() def get_xy(self, point): """ Get coordinates of selected point """ if self.snapped_point: self.x = self.snapped_point.x() self.y = self.snapped_point.y() else: self.x = point.x() self.y = point.y() message = "Geometry has been added!" self.controller.show_info(message) self.emit_point.canvasClicked.disconnect() self.canvas.xyCoordinates.disconnect() self.xyCoordinates_conected = False self.iface.mapCanvas().refreshAllLayers() self.vertex_marker.hide() def get_values_from_form(self, dialog): self.enddate = utils_giswater.getCalendarDate(dialog, "enddate") self.workcat_id_end = utils_giswater.getWidgetText(dialog, "workcat_id_end") self.description = utils_giswater.getWidgetText(dialog, "descript") def tab_feature_changed(self, dialog, table_object, feature_id=None): """ Set geom_type and layer depending selected tab @table_object = ['doc' | 'element' | 'cat_work'] """ self.get_values_from_form(dialog) if dialog.tab_feature.currentIndex() == 3: dialog.btn_snapping.setEnabled(False) else: dialog.btn_snapping.setEnabled(True) tab_position = dialog.tab_feature.currentIndex() if tab_position == 0: self.geom_type = "arc" elif tab_position == 1: self.geom_type = "node" elif tab_position == 2: self.geom_type = "connec" elif tab_position == 3: self.geom_type = "element" elif tab_position == 4: self.geom_type = "gully" self.hide_generic_layers() widget_name = "tbl_" + table_object + "_x_" + str(self.geom_type) viewname = "v_edit_" + str(self.geom_type) self.widget = utils_giswater.getWidget(dialog, widget_name) # Adding auto-completion to a QLineEdit self.set_completer_feature_id(dialog.feature_id, self.geom_type, viewname) self.iface.actionPan().trigger() def set_completer_object(self, dialog, table_object): """ Set autocomplete of widget @table_object + "_id" getting id's from selected @table_object """ widget = utils_giswater.getWidget(dialog, table_object + "_id") if not widget: return # Set SQL field_object_id = "id" if table_object == "element": field_object_id = table_object + "_id" sql = ("SELECT DISTINCT(" + field_object_id + ")" " FROM " + self.schema_name + "." + table_object) row = self.controller.get_rows(sql, commit=self.autocommit) 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) widget.setCompleter(self.completer) model = QStringListModel() model.setStringList(row) self.completer.setModel(model) def set_completer_widget(self, tablename, widget, field_id): """ Set autocomplete of widget @table_object + "_id" getting id's from selected @table_object """ if not widget: return # Set SQL sql = ("SELECT DISTINCT(" + field_id + ")" " FROM " + self.schema_name + "." + tablename +"" " ORDER BY "+ field_id + "") 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) widget.setCompleter(self.completer) model = QStringListModel() model.setStringList(row) self.completer.setModel(model) def set_completer_feature_id(self, widget, geom_type, viewname): """ Set autocomplete of widget 'feature_id' getting id's from selected @viewname """ # Adding auto-completion to a QLineEdit self.completer = QCompleter() self.completer.setCaseSensitivity(Qt.CaseInsensitive) widget.setCompleter(self.completer) model = QStringListModel() sql = ("SELECT " + geom_type + "_id" " FROM " + self.schema_name + "." + viewname) row = self.controller.get_rows(sql, commit=self.autocommit) if row: for i in range(0, len(row)): aux = row[i] row[i] = str(aux[0]) model.setStringList(row) self.completer.setModel(model) def get_expr_filter(self, geom_type): """ Set an expression filter with the contents of the list. Set a model with selected filter. Attach that model to selected table """ list_ids = self.list_ids[geom_type] field_id = geom_type + "_id" if len(list_ids) == 0: return None # Set expression filter with features in the list expr_filter = field_id + " IN (" for i in range(len(list_ids)): expr_filter += "'" + str(list_ids[i]) + "', " expr_filter = expr_filter[:-2] + ")" # Check expression (is_valid, expr) = self.check_expression(expr_filter) if not is_valid: return None # Select features of layers applying @expr self.select_features_by_ids(geom_type, expr) return expr_filter def reload_table(self, dialog, table_object, geom_type, expr_filter): """ Reload @widget with contents of @tablename applying selected @expr_filter """ if type(table_object) is str: widget_name = "tbl_" + table_object + "_x_" + geom_type widget = utils_giswater.getWidget(dialog, widget_name) if not widget: message = "Widget not found" self.controller.log_info(message, parameter=widget_name) return None elif type(table_object) is QTableView: widget = table_object else: message = "Table_object is not a table name or QTableView" self.controller.log_info(message) return None expr = self.set_table_model(dialog, widget, geom_type, expr_filter) return expr def set_table_model(self, dialog, table_object, geom_type, expr_filter): """ Sets a TableModel to @widget_name attached to @table_name and filter @expr_filter """ expr = None if expr_filter: # Check expression (is_valid, expr) = self.check_expression(expr_filter) #@UnusedVariable if not is_valid: return expr # Set a model with selected filter expression table_name = "v_edit_" + geom_type if self.schema_name not in table_name: table_name = self.schema_name + "." + table_name # Set the model model = QSqlTableModel() model.setTable(table_name) model.setEditStrategy(QSqlTableModel.OnManualSubmit) model.select() if model.lastError().isValid(): self.controller.show_warning(model.lastError().text()) return expr # Attach model to selected widget if type(table_object) is str: widget = utils_giswater.getWidget(dialog, table_object) if not widget: message = "Widget not found" self.controller.log_info(message, parameter=table_object) return expr elif type(table_object) is QTableView: widget = table_object else: message = "Table_object is not a table name or QTableView" self.controller.log_info(message) return expr if expr_filter: widget.setModel(model) widget.model().setFilter(expr_filter) widget.model().select() else: widget.setModel(None) return expr def apply_lazy_init(self, widget): """Apply the init function related to the model. It's necessary a lazy init because model is changed everytime is loaded.""" if self.lazy_widget is None: return if widget != self.lazy_widget: return self.lazy_init_function(self.lazy_widget) def lazy_configuration(self, widget, init_function): """set the init_function where all necessary events are set. This is necessary to allow a lazy setup of the events because set_table_events can create a table with a None model loosing any event connection.""" # TODO: create a dictionary with key:widged.objectName value:initFuction # to allow multiple lazy initialization self.lazy_widget = widget self.lazy_init_function = init_function def select_features_by_ids(self, geom_type, expr): """ Select features of layers of group @geom_type applying @expr """ # Build a list of feature id's and select them for layer in self.layers[geom_type]: if expr is None: layer.removeSelection() else: it = layer.getFeatures(QgsFeatureRequest(expr)) id_list = [i.id() for i in it] if len(id_list) > 0: layer.selectByIds(id_list) else: layer.removeSelection() def delete_records(self, dialog, table_object, query=False): """ Delete selected elements of the table """ self.disconnect_signal_selection_changed() if type(table_object) is str: widget_name = "tbl_" + table_object + "_x_" + self.geom_type widget = utils_giswater.getWidget(dialog, widget_name) if not widget: message = "Widget not found" self.controller.show_warning(message, parameter=widget_name) return elif type(table_object) is QTableView: widget = table_object else: message = "Table_object is not a table name or QTableView" self.controller.log_info(message) return # Get selected rows selected_list = widget.selectionModel().selectedRows() if len(selected_list) == 0: message = "Any record selected" self.controller.show_info_box(message) return if query: full_list = widget.model() for x in range(0, full_list.rowCount()): self.ids.append(widget.model().record(x).value(str(self.geom_type)+"_id")) else: self.ids = self.list_ids[self.geom_type] field_id = self.geom_type + "_id" del_id = [] inf_text = "" list_id = "" for i in range(0, len(selected_list)): row = selected_list[i].row() id_feature = widget.model().record(row).value(field_id) inf_text += str(id_feature) + ", " list_id = list_id + "'" + str(id_feature) + "', " del_id.append(id_feature) 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: for el in del_id: self.ids.remove(el) else: return expr_filter = None expr = None if len(self.ids) > 0: # Set expression filter with features in the list expr_filter = "\"" + field_id + "\" IN (" for i in range(len(self.ids)): expr_filter += "'" + str(self.ids[i]) + "', " expr_filter = expr_filter[:-2] + ")" # Check expression (is_valid, expr) = self.check_expression(expr_filter) #@UnusedVariable if not is_valid: return # Update model of the widget with selected expr_filter if query: self.delete_feature_at_plan(dialog, self.geom_type, list_id) self.reload_qtable(dialog, self.geom_type, self.plan_om) else: self.reload_table(dialog, table_object, self.geom_type, expr_filter) self.apply_lazy_init(table_object) # Select features with previous filter # Build a list of feature id's and select them self.select_features_by_ids(self.geom_type, expr) if query: self.remove_selection() # Update list self.list_ids[self.geom_type] = self.ids self.enable_feature_type(dialog) self.connect_signal_selection_changed(dialog, table_object) def manage_close(self, dialog, table_object, cur_active_layer=None): """ Close dialog and disconnect snapping """ if cur_active_layer: self.iface.setActiveLayer(cur_active_layer) if hasattr(self, 'single_tool_mode'): # some tools can work differently if standalone or integrated in # another tool if self.single_tool_mode: self.remove_selection(True) else: self.remove_selection(True) self.reset_model(dialog, table_object, "arc") self.reset_model(dialog, table_object, "node") self.reset_model(dialog, table_object, "connec") self.reset_model(dialog, table_object, "element") if self.project_type == 'ud': self.reset_model(dialog, table_object, "gully") self.close_dialog(dialog) self.hide_generic_layers() self.disconnect_snapping() self.disconnect_signal_selection_changed() # reset previous dialog in not in single_tool_mode # if hasattr(self, 'single_tool_mode') and not self.single_tool_mode: # if hasattr(self, 'previous_dialog'): def selection_init(self, dialog, table_object, query=False): """ Set canvas map tool to an instance of class 'MultipleSelection' """ multiple_selection = MultipleSelection(self.iface, self.controller, self.layers[self.geom_type], parent_manage=self, table_object=table_object, dialog=dialog) self.previous_map_tool = self.canvas.mapTool() self.canvas.setMapTool(multiple_selection) self.disconnect_signal_selection_changed() self.connect_signal_selection_changed(dialog, table_object, query) cursor = self.get_cursor_multiple_selection() self.canvas.setCursor(cursor) def selection_changed(self, dialog, table_object, geom_type, query=False): """ Slot function for signal 'canvas.selectionChanged' """ self.disconnect_signal_selection_changed() field_id = geom_type + "_id" if self.remove_ids: self.ids = [] # Iterate over all layers of the group for layer in self.layers[self.geom_type]: if layer.selectedFeatureCount() > 0: # Get selected features of the layer features = layer.selectedFeatures() for feature in features: # Append 'feature_id' into the list selected_id = feature.attribute(field_id) if selected_id not in self.ids: self.ids.append(selected_id) if geom_type == 'arc': self.list_ids['arc'] = self.ids elif geom_type == 'node': self.list_ids['node'] = self.ids elif geom_type == 'connec': self.list_ids['connec'] = self.ids elif geom_type == 'gully': self.list_ids['gully'] = self.ids elif geom_type == 'element': self.list_ids['element'] = self.ids expr_filter = None if len(self.ids) > 0: # Set 'expr_filter' with features that are in the list expr_filter = "\"" + field_id + "\" IN (" for i in range(len(self.ids)): expr_filter += "'" + str(self.ids[i]) + "', " expr_filter = expr_filter[:-2] + ")" # Check expression (is_valid, expr) = self.check_expression(expr_filter) #@UnusedVariable if not is_valid: return self.select_features_by_ids(geom_type, expr) # Reload contents of table 'tbl_@table_object_x_@geom_type' if query: self.insert_feature_to_plan(dialog, self.geom_type) if self.plan_om == 'plan': self.remove_selection() self.reload_qtable(dialog, geom_type, self.plan_om) else: self.reload_table(dialog, table_object, self.geom_type, expr_filter) self.apply_lazy_init(table_object) # Remove selection in generic 'v_edit' layers if self.plan_om == 'plan': self.remove_selection(False) self.enable_feature_type(dialog) self.connect_signal_selection_changed(dialog, table_object) def delete_feature_at_plan(self, dialog, geom_type, list_id): """ Delete features_id to table plan_@geom_type_x_psector""" value = utils_giswater.getWidgetText(dialog, dialog.psector_id) sql = ("DELETE FROM " + self.schema_name + "." + self.plan_om + "_psector_x_" + geom_type + "" " WHERE " + geom_type + "_id IN (" + list_id + ") AND psector_id = '" + str(value) + "'") self.controller.execute_sql(sql) def enable_feature_type(self, dialog): feature_type = dialog.findChild(QComboBox, 'feature_type') assigned_to = dialog.findChild(QComboBox, 'cmb_assigned_to') visit_class = dialog.findChild(QComboBox, 'cmb_visit_class') table = dialog.findChild(QTableView, 'tbl_relation') if feature_type is not None and table is not None: if len(self.ids) > 0: feature_type.setEnabled(False) if assigned_to is not None: assigned_to.setEnabled(False) if assigned_to is not None: visit_class.setEnabled(False) else: feature_type.setEnabled(True) if assigned_to is not None: assigned_to.setEnabled(True) if assigned_to is not None: visit_class.setEnabled(True) def insert_feature(self, dialog, table_object, query=False, remove_ids=True): """ Select feature with entered id. Set a model with selected filter. Attach that model to selected table """ self.disconnect_signal_selection_changed() # Clear list of ids if remove_ids: self.ids = [] field_id = self.geom_type + "_id" feature_id = utils_giswater.getWidgetText(dialog, "feature_id") if feature_id == 'null': message = "You need to enter a feature id" self.controller.show_info_box(message) return # Iterate over all layers of the group for layer in self.layers[self.geom_type]: if layer.selectedFeatureCount() > 0: # Get selected features of the layer features = layer.selectedFeatures() for feature in features: # Append 'feature_id' into the list selected_id = feature.attribute(field_id) if selected_id not in self.ids: self.ids.append(selected_id) if feature_id not in self.ids: # If feature id doesn't exist in list -> add self.ids.append(str(feature_id)) # Set expression filter with features in the list expr_filter = "\"" + field_id + "\" IN (" for i in range(len(self.ids)): expr_filter += "'" + str(self.ids[i]) + "', " expr_filter = expr_filter[:-2] + ")" # Check expression (is_valid, expr) = self.check_expression(expr_filter) if not is_valid: return # Select features with previous filter # Build a list of feature id's and select them for layer in self.layers[self.geom_type]: it = layer.getFeatures(QgsFeatureRequest(expr)) id_list = [i.id() for i in it] if len(id_list) > 0: layer.selectByIds(id_list) # Reload contents of table 'tbl_???_x_@geom_type' if query: self.insert_feature_to_plan(dialog, self.geom_type) self.remove_selection() else: self.reload_table(dialog, table_object, self.geom_type, expr_filter) self.apply_lazy_init(table_object) # Update list self.list_ids[self.geom_type] = self.ids self.enable_feature_type(dialog) self.connect_signal_selection_changed(dialog, table_object) def insert_feature_to_plan(self, dialog, geom_type): """ Insert features_id to table plan_@geom_type_x_psector""" value = utils_giswater.getWidgetText(dialog, dialog.psector_id) for i in range(len(self.ids)): sql = ("SELECT " + geom_type + "_id" " FROM " + self.schema_name + "." + self.plan_om + "_psector_x_" + geom_type + "" " WHERE " + geom_type + "_id = '" + str(self.ids[i]) + "' AND psector_id = '" + str(value) + "'") row = self.controller.get_row(sql) if not row: sql = ("INSERT INTO " + self.schema_name + "." + self.plan_om + "_psector_x_" + geom_type + "" "(" + geom_type + "_id, psector_id) VALUES('" + str(self.ids[i]) + "', '" + str(value) + "')") self.controller.execute_sql(sql) self.reload_qtable(dialog, geom_type, self.plan_om) def reload_qtable(self, dialog, geom_type, plan_om): """ Reload QtableView """ value = utils_giswater.getWidgetText(dialog, dialog.psector_id) sql = ("SELECT * FROM " + self.schema_name + "." + plan_om + "_psector_x_" + geom_type + "" " WHERE psector_id = '" + str(value) + "'") qtable = utils_giswater.getWidget(dialog, 'tbl_psector_x_' + geom_type) self.fill_table_by_query(qtable, sql) self.set_table_columns(dialog, qtable, plan_om + "_psector_x_"+geom_type) self.refresh_map_canvas() def disconnect_snapping(self): """ Select 'Pan' as current map tool and disconnect snapping """ try: self.iface.actionPan().trigger() self.canvas.xyCoordinates.disconnect() if self.emit_point: self.emit_point.canvasClicked.disconnect() except: pass def fill_table_object(self, widget, table_name, expr_filter=None): """ 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 model = QSqlTableModel() model.setTable(table_name) model.setEditStrategy(QSqlTableModel.OnManualSubmit) model.sort(0, 1) if expr_filter: model.setFilter(expr_filter) model.select() # Check for errors if model.lastError().isValid(): self.controller.show_warning(model.lastError().text()) # Attach model to table view widget.setModel(model) def filter_by_id(self, dialog, widget_table, widget_txt, table_object, field_object_id='id'): field_object_id = "id" if table_object == "element": field_object_id = table_object + "_id" object_id = utils_giswater.getWidgetText(dialog, widget_txt) if object_id != 'null': expr = field_object_id + "::text ILIKE '%" + str(object_id) + "%'" # Refresh model with selected filter widget_table.model().setFilter(expr) widget_table.model().select() else: self.fill_table_object(widget_table, self.schema_name + "." + table_object) def delete_selected_object(self, widget, table_object): """ Delete selected objects of the table (by object_id) """ # 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 = "" field_object_id = "id" if table_object == "element": field_object_id = table_object + "_id" elif "v_ui_om_visitman_x_" in table_object: field_object_id = "visit_id" for i in range(0, len(selected_list)): row = selected_list[i].row() id_ = widget.model().record(row).value(str(field_object_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_object + "" " WHERE " + field_object_id + " IN (" + list_id + ")") self.controller.execute_sql(sql, commit=self.autocommit) widget.model().select() def open_selected_object(self, dialog, widget, table_object): """ Open object form with selected record of the table """ selected_list = widget.selectionModel().selectedRows() if len(selected_list) == 0: message = "Any record selected" self.controller.show_warning(message) return row = selected_list[0].row() # Get object_id from selected row field_object_id = "id" widget_id = table_object + "_id" if table_object == "element": field_object_id = table_object + "_id" if table_object == "v_ui_om_visit": widget_id = "visit_id" elif "v_ui_om_visitman_x_" in table_object: field_object_id = "visit_id" selected_object_id = widget.model().record(row).value(field_object_id) # Close this dialog and open selected object dialog.close() # set previous dialog # if hasattr(self, 'previous_dialog'): if table_object == "doc": self.manage_document() utils_giswater.setWidgetText(self.dlg_add_doc, widget_id, selected_object_id) elif table_object == "element": self.manage_element(new_element_id=False) utils_giswater.setWidgetText(self.dlg_add_element, widget_id, selected_object_id) elif table_object == "v_ui_om_visit": self.manage_visit(visit_id=selected_object_id) elif "v_ui_om_visitman_x_" in table_object: self.manage_visit(visit_id=selected_object_id) def set_selectionbehavior(self, dialog): # Get objects of type: QTableView widget_list = dialog.findChildren(QTableView) for widget in widget_list: widget.setSelectionBehavior(QAbstractItemView.SelectRows) def hide_generic_layers(self, visible=False): """ Hide generic layers """ layer = self.controller.get_layer_by_tablename("v_edit_arc") if layer: self.iface.legendInterface().setLayerVisible(layer, visible) layer = self.controller.get_layer_by_tablename("v_edit_node") if layer: self.iface.legendInterface().setLayerVisible(layer, visible) layer = self.controller.get_layer_by_tablename("v_edit_connec") if layer: self.iface.legendInterface().setLayerVisible(layer, visible) layer = self.controller.get_layer_by_tablename("v_edit_element") if layer: self.iface.legendInterface().setLayerVisible(layer, visible) if self.project_type == 'ud': layer = self.controller.get_layer_by_tablename("v_edit_gully") if layer: self.iface.legendInterface().setLayerVisible(layer, visible) def connect_signal_selection_changed(self, dialog, table_object, query=False): """ Connect signal selectionChanged """ try: self.canvas.selectionChanged.connect(partial(self.selection_changed, dialog, table_object, self.geom_type, query)) except Exception: pass def disconnect_signal_selection_changed(self): """ Disconnect signal selectionChanged """ try: self.canvas.selectionChanged.disconnect() except Exception: pass def fill_widget_with_fields(self, dialog, data_object, field_names): """Fill the Widget with value get from data_object limited to the list of field_names.""" for field_name in field_names: value = getattr(data_object, field_name) if not hasattr(dialog, field_name): continue widget = getattr(dialog, field_name) if type(widget) in [QDateEdit, QDateTimeEdit]: widget.setDateTime(value if value else QDate.currentDate() ) if type(widget) in [QLineEdit, QTextEdit]: if value: widget.setText(value) else: widget.clear() if type(widget) in [QComboBox]: if not value: widget.setCurrentIndex(0) continue # look the value in item text index = widget.findText(str(value)) if index >= 0: widget.setCurrentIndex(index) continue # look the value in itemData index = widget.findData(value) if index >= 0: widget.setCurrentIndex(index) continue def set_model_to_table(self, widget, table_name, expr_filter): """ Set a model with selected filter. Attach that model to selected table """ # Set model model = QSqlTableModel(); model.setTable(table_name) model.setEditStrategy(QSqlTableModel.OnManualSubmit) model.setFilter(expr_filter) model.select() # Check for errors if model.lastError().isValid(): self.controller.show_warning(model.lastError().text()) # Attach model to table view if widget: widget.setModel(model) else: self.controller.log_info("set_model_to_table: widget not found")
class TalkEditorApp(FreeseerApp): '''Freeseer talk database editor main gui class''' def __init__(self, config, db): FreeseerApp.__init__(self) self.config = config self.db = db icon = QIcon() icon.addPixmap(QPixmap(':/freeseer/logo.png'), QIcon.Normal, QIcon.Off) self.setWindowIcon(icon) self.resize(960, 600) # # Setup Layout # self.mainWidget = QWidget() self.mainLayout = QVBoxLayout() self.mainWidget.setLayout(self.mainLayout) self.setCentralWidget(self.mainWidget) self.mainLayout.setAlignment(QtCore.Qt.AlignTop) # Add the Title Row (Use BOLD / Big Font) #self.titleLayout = QHBoxLayout() #self.backButton = QPushButton('Back to Recorder') #if backButton: # Only show the back button if requested by caller # self.titleLayout.addWidget(self.backButton) #self.titleLayout.addStretch() # Add custom widgets self.commandButtons = CommandButtons() self.tableView = QTableView() self.tableView.setSortingEnabled(True) self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows) self.talkDetailsWidget = TalkDetailsWidget() self.importTalksWidget = ImportTalksWidget() self.mainLayout.addWidget(self.importTalksWidget) #self.mainLayout.addLayout(self.titleLayout) self.mainLayout.addWidget(self.commandButtons) self.mainLayout.addWidget(self.tableView) self.mainLayout.addWidget(self.talkDetailsWidget) self.mainLayout.addWidget(self.importTalksWidget) # --- End Layout # Initialize geometry, to be used for restoring window positioning. self.geometry = None # # Setup Menubar # self.actionExportCsv = QAction(self) self.actionExportCsv.setObjectName('actionExportCsv') self.actionRemoveAll = QAction(self) self.actionRemoveAll.setObjectName('actionRemoveAll') # Actions self.menuFile.insertAction(self.actionExit, self.actionExportCsv) self.menuFile.insertAction(self.actionExit, self.actionRemoveAll) # --- End Menubar # # TableView Connections # self.connect(self.tableView, SIGNAL('activated(const QModelIndex)'), self.talk_selected) self.connect(self.tableView, SIGNAL('selected(const QModelIndex)'), self.talk_selected) self.connect(self.tableView, SIGNAL('clicked(const QModelIndex)'), self.talk_selected) # Import Widget self.connect(self.importTalksWidget.csvRadioButton, SIGNAL('toggled(bool)'), self.toggle_import) self.connect(self.importTalksWidget.importButton, SIGNAL('clicked()'), self.import_talks) self.connect(self.importTalksWidget.cancelButton, SIGNAL('clicked()'), self.hide_import_talks_widget) self.importTalksWidget.setHidden(True) self.connect(self.importTalksWidget.csvFileSelectButton, QtCore.SIGNAL('clicked()'), self.csv_file_select) self.connect(self.importTalksWidget.csvLineEdit, QtCore.SIGNAL('returnPressed()'), self.importTalksWidget.importButton.click) self.connect(self.importTalksWidget.rssLineEdit, QtCore.SIGNAL('returnPressed()'), self.importTalksWidget.importButton.click) self.connect(self.actionExportCsv, QtCore.SIGNAL('triggered()'), self.export_talks_to_csv) self.connect(self.actionRemoveAll, QtCore.SIGNAL('triggered()'), self.confirm_reset) # Command Buttons self.connect(self.commandButtons.removeButton, SIGNAL('clicked()'), self.remove_talk) self.connect(self.commandButtons.removeAllButton, SIGNAL('clicked()'), self.confirm_reset) self.connect(self.commandButtons.importButton, SIGNAL('clicked()'), self.show_import_talks_widget) self.connect(self.commandButtons.exportButton, SIGNAL('clicked()'), self.export_talks_to_csv) self.connect(self.commandButtons.searchButton, SIGNAL('clicked()'), self.search_talks) self.connect(self.commandButtons.searchLineEdit, SIGNAL('textEdited(QString)'), self.search_talks) self.connect(self.commandButtons.searchLineEdit, SIGNAL('returnPressed()'), self.search_talks) # Talk Details Buttons self.connect(self.talkDetailsWidget.addButton, SIGNAL('clicked()'), self.clear_talk_details_widget) self.connect(self.talkDetailsWidget.saveButton, SIGNAL('clicked()'), self.add_talk) # Load default language actions = self.menuLanguage.actions() for action in actions: if action.data().toString() == self.config.default_language: action.setChecked(True) self.translate(action) break # Load Talk Database self.load_presentations_model() # Setup Autocompletion self.update_autocomple_fields() # Select first item #self.tableView.setCurrentIndex(self.proxy.index(0,0)) #self.talk_selected(self.proxy.index(0,0)) # # Translation # def retranslate(self): self.setWindowTitle(self.app.translate("TalkEditorApp", "Freeseer Talk Editor")) # # Reusable Strings # self.confirmDBClearTitleString = self.app.translate("TalkEditorApp", "Remove All Talks from Database") self.confirmDBClearQuestionString = self.app.translate("TalkEditorApp", "Are you sure you want to clear the DB?") # --- End Reusable Strings # # Menubar # self.actionExportCsv.setText(self.app.translate("TalkEditorApp", "&Export to CSV")) self.actionRemoveAll.setText(self.app.translate("TalkEditorApp", "&Remove All Talks")) # --- End Menubar # # TalkDetailsWidget # self.talkDetailsWidget.titleLabel.setText(self.app.translate("TalkEditorApp", "Title")) self.talkDetailsWidget.presenterLabel.setText(self.app.translate("TalkEditorApp", "Presenter")) self.talkDetailsWidget.categoryLabel.setText(self.app.translate("TalkEditorApp", "Category")) self.talkDetailsWidget.eventLabel.setText(self.app.translate("TalkEditorApp", "Event")) self.talkDetailsWidget.roomLabel.setText(self.app.translate("TalkEditorApp", "Room")) self.talkDetailsWidget.dateLabel.setText(self.app.translate("TalkEditorApp", "Date")) self.talkDetailsWidget.timeLabel.setText(self.app.translate("TalkEditorApp", "Time")) # --- End TalkDetailsWidget # # Import Talks Widget Translations # self.importTalksWidget.rssRadioButton.setText(self.app.translate("TalkEditorApp", "RSS URL")) self.importTalksWidget.csvRadioButton.setText(self.app.translate("TalkEditorApp", "CSV File")) self.importTalksWidget.importButton.setText(self.app.translate("TalkEditorApp", "Import")) # --- End Talks Widget Translations # # Command Button Translations\ # #self.commandButtons.addButton.setText(self.app.translate("TalkEditorApp", "Add")) self.commandButtons.importButton.setText(self.app.translate("TalkEditorApp", "Import")) self.commandButtons.exportButton.setText(self.app.translate("TalkEditorApp", "Export")) self.commandButtons.removeButton.setText(self.app.translate("TalkEditorApp", "Remove")) self.commandButtons.removeAllButton.setText(self.app.translate("TalkEditorApp", "Remove All")) # --- End Command Butotn Translations # # Search Widget Translations # self.commandButtons.searchButton.setText(self.app.translate("TalkEditorApp", "Search")) # --- End Command Button Translations def load_presentations_model(self): # Load Presentation Model self.presentationModel = self.db.get_presentations_model() self.proxy = QSortFilterProxyModel() self.proxy.setSourceModel(self.presentationModel) self.tableView.setModel(self.proxy) self.proxy.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive) # Fill table whitespace. self.tableView.horizontalHeader().setStretchLastSection(False) self.tableView.horizontalHeader().setResizeMode(1, QHeaderView.Stretch) # Hide the ID field self.tableView.setColumnHidden(0, True) # Map data to widgets self.mapper = QDataWidgetMapper() self.mapper.setModel(self.proxy) self.mapper.addMapping(self.talkDetailsWidget.titleLineEdit, 1) self.mapper.addMapping(self.talkDetailsWidget.presenterLineEdit, 2) self.mapper.addMapping(self.talkDetailsWidget.categoryLineEdit, 4) self.mapper.addMapping(self.talkDetailsWidget.eventLineEdit, 5) self.mapper.addMapping(self.talkDetailsWidget.roomLineEdit, 6) self.mapper.addMapping(self.talkDetailsWidget.descriptionTextEdit, 3) self.mapper.addMapping(self.talkDetailsWidget.dateEdit, 7) self.mapper.addMapping(self.talkDetailsWidget.timeEdit, 8) # Load StringLists self.titleList = QStringList(self.db.get_string_list("Title")) #self.speakerList = QStringList(self.db.get_speaker_list()) #self.categoryList = QStringList(self.db.get_category_list()) #self.eventList = QStringList(self.db.get_event_list()) #self.roomList = QStringList(self.db.get_room_list()) #Disble input self.talkDetailsWidget.disable_input_fields() def search_talks(self): # The default value is 0. If the value is -1, the keys will be read from all columns. self.proxy.setFilterKeyColumn(-1) self.proxy.setFilterFixedString(self.commandButtons.searchLineEdit.text()) def talk_selected(self, model): self.talkDetailsWidget.saveButton.setEnabled(False) self.mapper.setCurrentIndex(model.row()) self.talkDetailsWidget.enable_input_fields() def toggle_import(self): if self.importTalksWidget.csvRadioButton.isChecked(): self.importTalksWidget.csvLineEdit.setEnabled(True) self.importTalksWidget.csvFileSelectButton.setEnabled(True) self.importTalksWidget.rssLineEdit.setEnabled(False) else: self.importTalksWidget.csvLineEdit.setEnabled(False) self.importTalksWidget.csvFileSelectButton.setEnabled(False) self.importTalksWidget.rssLineEdit.setEnabled(True) def show_import_talks_widget(self): self.commandButtons.setHidden(True) self.tableView.setHidden(True) self.talkDetailsWidget.setHidden(True) self.importTalksWidget.setHidden(False) def hide_import_talks_widget(self): self.commandButtons.setHidden(False) self.tableView.setHidden(False) self.talkDetailsWidget.setHidden(False) self.importTalksWidget.setHidden(True) def add_talk(self): date = self.talkDetailsWidget.dateEdit.date() time = self.talkDetailsWidget.timeEdit.time() #datetime = QtCore.QDateTime(date, time) presentation = Presentation( unicode(self.talkDetailsWidget.titleLineEdit.text()), unicode(self.talkDetailsWidget.presenterLineEdit.text()), unicode(self.talkDetailsWidget.descriptionTextEdit.toPlainText()), unicode(self.talkDetailsWidget.categoryLineEdit.text()), unicode(self.talkDetailsWidget.eventLineEdit.text()), unicode(self.talkDetailsWidget.roomLineEdit.text()), unicode(date.toString(QtCore.Qt.ISODate)), unicode(time.toString(QtCore.Qt.ISODate))) # Do not add talks if they are empty strings if (len(presentation.title) == 0): return self.db.insert_presentation(presentation) # Update Model, Refreshes TableView self.presentationModel.select() # Select Last Row self.tableView.selectRow(self.presentationModel.rowCount() - 1) self.tableView.setCurrentIndex(self.proxy.index(self.proxy.rowCount() - 1, 0)) self.talk_selected(self.proxy.index(self.proxy.rowCount() - 1, 0)) self.update_autocomple_fields() self.talkDetailsWidget.disable_input_fields() def clear_talk_details_widget(self): self.talkDetailsWidget.saveButton.setEnabled(True) self.talkDetailsWidget.enable_input_fields() self.talkDetailsWidget.titleLineEdit.clear() self.talkDetailsWidget.presenterLineEdit.clear() self.talkDetailsWidget.descriptionTextEdit.clear() #self.talkDetailsWidget.categoryLineEdit.clear() #self.talkDetailsWidget.eventLineEdit.clear() #self.talkDetailsWidget.roomLineEdit.clear() self.presentationModel.select() def remove_talk(self): try: rows_selected = self.tableView.selectionModel().selectedRows() except: return # Reversed because rows in list change position once row is removed for row in reversed(rows_selected): self.presentationModel.removeRow(row.row()) def load_talk(self): try: self.tableView.currentIndex().row() except: return self.mapper.addMapping(self.talkDetailsWidget.roomLineEdit, 6) self.presentationModel.select() def reset(self): self.db.clear_database() self.presentationModel.select() def confirm_reset(self): """Presents a confirmation dialog to ask the user if they are sure they wish to remove the talk database. If Yes call the reset() function""" confirm = QMessageBox.question(self, self.confirmDBClearTitleString, self.confirmDBClearQuestionString, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if confirm == QMessageBox.Yes: self.reset() def add_talks_from_rss(self): rss_url = unicode(self.importTalksWidget.rssLineEdit.text()) if rss_url: self.db.add_talks_from_rss(rss_url) self.presentationModel.select() self.hide_import_talks_widget() else: error = QMessageBox() error.setText("Please enter a RSS URL") error.exec_() def closeEvent(self, event): log.info('Exiting talk database editor...') self.geometry = self.saveGeometry() event.accept() def csv_file_select(self): fname = QFileDialog.getOpenFileName( self, 'Select file', "", "*.csv") if fname: self.importTalksWidget.csvLineEdit.setText(fname) def add_talks_from_csv(self): fname = self.importTalksWidget.csvLineEdit.text() if fname: self.db.add_talks_from_csv(fname) self.presentationModel.select() self.hide_import_talks_widget() else: error = QMessageBox() error.setText("Please select a file") error.exec_() def import_talks(self): if self.importTalksWidget.csvRadioButton.isChecked(): self.add_talks_from_csv() else: self.add_talks_from_rss() self.update_autocomple_fields() def export_talks_to_csv(self): fname = QFileDialog.getSaveFileName(self, 'Select file', "", "*.csv") if fname: self.db.export_talks_to_csv(fname) def update_autocomple_fields(self): self.titleList = QStringList(self.db.get_string_list("Title")) self.speakerList = QStringList(self.db.get_string_list("Speaker")) self.categoryList = QStringList(self.db.get_string_list("Category")) self.eventList = QStringList(self.db.get_string_list("Event")) self.roomList = QStringList(self.db.get_string_list("Room")) self.titleCompleter = QCompleter(self.titleList) self.titleCompleter.setCaseSensitivity(Qt.CaseInsensitive) self.speakerCompleter = QCompleter(self.speakerList) self.speakerCompleter.setCaseSensitivity(Qt.CaseInsensitive) self.categoryCompleter = QCompleter(self.categoryList) self.categoryCompleter.setCaseSensitivity(Qt.CaseInsensitive) self.eventCompleter = QCompleter(self.eventList) self.eventCompleter.setCaseSensitivity(Qt.CaseInsensitive) self.roomCompleter = QCompleter(self.roomList) self.roomCompleter.setCaseSensitivity(Qt.CaseInsensitive) self.talkDetailsWidget.titleLineEdit.setCompleter(self.titleCompleter) self.talkDetailsWidget.presenterLineEdit.setCompleter(self.speakerCompleter) self.talkDetailsWidget.categoryLineEdit.setCompleter(self.categoryCompleter) self.talkDetailsWidget.eventLineEdit.setCompleter(self.eventCompleter) self.talkDetailsWidget.roomLineEdit.setCompleter(self.roomCompleter)
class Main(plugin.Plugin): ' main class for plugin ' def initialize(self, *args, **kwargs): ' class init ' super(Main, self).initialize(*args, **kwargs) self.process = QProcess() self.process.readyReadStandardOutput.connect(self.readOutput) self.process.readyReadStandardError.connect(self.readErrors) self.process.finished.connect(self._process_finished) self.process.error.connect(self._process_finished) # directory auto completer 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) menu = QMenu('Clones') menu.addAction('Analyze for Code Clones here', lambda: self.make_clon()) self.locator.get_service('explorer').add_project_menu(menu, lang='all') self.group1 = QGroupBox() self.group1.setTitle(' Target ') self.outdir, self.igndir = QLineEdit(path.expanduser("~")), QLineEdit() self.outdir.setCompleter(self.completer) self.btn1 = QPushButton(QIcon.fromTheme("document-open"), ' Open ') self.btn1.clicked.connect(lambda: self.outdir.setText(str( QFileDialog.getExistingDirectory(self.dock, 'Please, Open a Target Directory...', path.expanduser("~"))))) self.btn1a = QPushButton(QIcon.fromTheme("face-smile"), 'Get from Ninja active project') self.btn1a.clicked.connect(lambda: self.outdir.setText( self.locator.get_service('explorer').get_current_project_item().path)) self.ignckb, self.ignmor = QComboBox(), QTextEdit() self.ignckb.addItems(['Single Directory', 'Multiple Directories CSV']) self.ignckb.currentIndexChanged.connect(self.on_ignore_changed) self.ignmor.hide() self.igndir.setPlaceholderText('Exclude directory') self.igndir.setCompleter(self.completer) self.btn2 = QPushButton(QIcon.fromTheme("document-open"), ' Open ') self.btn2.clicked.connect(lambda: self.igndir.setText(str( QFileDialog.getExistingDirectory(self.dock, 'Please, Open a Ignore Directory...', path.expanduser("~"))))) vboxg1 = QVBoxLayout(self.group1) for each_widget in (QLabel('<b>Target directory path: '), self.outdir, self.btn1, self.btn1a, QLabel('<b>Ignore directory path: '), self.ignckb, self.ignmor, self.igndir, self.btn2, ): vboxg1.addWidget(each_widget) self.group2 = QGroupBox() self.group2.setTitle(' Output ') self.outfle = QLineEdit(path.join(path.expanduser("~"), 'output.html')) self.outfle.setPlaceholderText('Exclude directory') self.outfle.setCompleter(self.completer) self.btn3 = QPushButton(QIcon.fromTheme("document-save"), ' Save ') self.btn3.clicked.connect(lambda: self.outfle.setText( QFileDialog.getSaveFileName(self.dock, 'Save', path.expanduser("~"), 'XML(*.xml)' if self.xmlo.isChecked() is True else 'HTML(*.html)'))) vboxg2 = QVBoxLayout(self.group2) for each_widget in (QLabel('<b>Output report file path:'), self.outfle, self.btn3): vboxg2.addWidget(each_widget) self.group3 = QGroupBox() self.group3.setTitle(' Options ') self.group3.setCheckable(True) self.group3.setGraphicsEffect(QGraphicsBlurEffect(self)) self.group3.graphicsEffect().setEnabled(False) self.group3.toggled.connect(self.toggle_options_group) self.qckb1, self.qckb2 = QCheckBox('Recursive'), QCheckBox('Time-less') self.qckb3, self.qckb4 = QCheckBox('Force Diff'), QCheckBox('Fast Mode') self.qckb5, self.tm = QCheckBox('Save a LOG file to target'), QLabel('') self.xmlo = QCheckBox('XML Output instead of HTML') self.opeo = QCheckBox('Open Clones Report when done') self.chrt = QCheckBox('LOW CPU priority for Backend Process') self.mdist, self.hdep, self.output = QSpinBox(), QSpinBox(), QTextEdit() self.ign_func = QLineEdit('test, forward, backward, Migration') self.mdist.setValue(5) self.hdep.setValue(1) self.mdist.setToolTip('''<b>Maximum amount of difference between pair of sequences in clone pair (5 default).Larger value more false positive''') self.hdep.setToolTip('''<b>Computation can be speeded up by increasing this value, but some clones can be missed (1 default)''') [a.setChecked(True) for a in (self.qckb1, self.qckb3, self.qckb5, self.chrt, self.opeo)] vboxg3 = QVBoxLayout(self.group3) for each_widget in (self.qckb1, self.qckb2, self.qckb3, self.qckb4, self.qckb5, self.chrt, self.xmlo, self.opeo, QLabel('<b>Max Distance Threshold:'), self.mdist, QLabel('<b>Max Hashing Depth:'), self.hdep, QLabel('<b>Ignore code block prefix:'), self.ign_func): vboxg3.addWidget(each_widget) self.group4, self.auto = QGroupBox(), QComboBox() self.group4.setTitle(' Automation ') self.group4.setCheckable(True) self.group4.setToolTip('<font color="red"><b>WARNING:Advanced Setting!') self.group4.toggled.connect(lambda: self.group4.hide()) self.auto.addItems(['Never run automatically', 'Run when File Saved', 'Run when File Executed', 'Run when Tab Changed', 'Run when File Opened', 'Run before File Saved']) self.auto.currentIndexChanged.connect(self.on_auto_changed) QVBoxLayout(self.group4).addWidget(self.auto) self.button = QPushButton(' Analyze for Clones ') self.button.setMinimumSize(75, 50) self.button.clicked.connect(self.run) glow = QGraphicsDropShadowEffect(self) glow.setOffset(0) glow.setBlurRadius(99) glow.setColor(QColor(99, 255, 255)) self.button.setGraphicsEffect(glow) self.butkil = QPushButton(' Force Kill Clones ') self.butkil.clicked.connect(lambda: self.process.kill()) class TransientWidget(QWidget): ' persistant widget thingy ' def __init__(self, widget_list): ' init sub class ' super(TransientWidget, self).__init__() vbox = QVBoxLayout(self) for each_widget in widget_list: vbox.addWidget(each_widget) tw = TransientWidget((QLabel('<i>D.R.Y. principle analyzer'), self.group1, self.group2, self.group3, self.group4, QLabel('<b>Backend Logs'), self.output, self.tm, self.button, self.butkil)) self.scrollable, self.dock = QScrollArea(), QDockWidget() self.scrollable.setWidgetResizable(True) self.scrollable.setWidget(tw) self.dock.setWindowTitle(__doc__) self.dock.setStyleSheet('QDockWidget::title{text-align: center;}') self.dock.setWidget(self.scrollable) ExplorerContainer().addTab(self.dock, "Clones") QPushButton(QIcon.fromTheme("help-about"), 'About', self.dock ).clicked.connect(lambda: QMessageBox.information(self.dock, __doc__, HELPMSG)) def readOutput(self): """Read and append output to the logBrowser""" self.output.append(str(self.process.readAllStandardOutput()).strip()) def readErrors(self): """Read and append errors to the logBrowser""" self.output.append(self.formatErrorMsg(str( self.process.readAllStandardError()))) def formatErrorMsg(self, msg): """Format error messages in red color""" return self.formatMsg(msg, 'red') def formatInfoMsg(self, msg): """Format informative messages in blue color""" return self.formatMsg(msg, 'green') def formatMsg(self, msg, color): """Format message with the given color""" return '<font color="{}">{}</font>'.format(color, msg) def make_clon(self): ' make clones analyze from contextual sub menu ' self.outdir.setText( self.locator.get_service('explorer').get_current_project_item().path) self.run() def run(self): ' run the actions ' self.output.clear() self.output.append(self.formatInfoMsg('INFO:{}'.format(datetime.now()))) self.tm.setText('<center><b>Last Clone: </b>' + datetime.now().isoformat().split('.')[0]) self.button.setDisabled(True) if not len(self.outdir.text()) and not len(self.outfle.text()): self.output.append(self.formatErrorMsg('ERROR: FAIL: Target empty')) self.button.setEnabled(True) return # run the subprocesses cmd = ' '.join(( 'chrt -i 0' if self.chrt.isChecked() is True else '', 'clonedigger', '' if self.qckb1.isChecked() is True else '--no-recursion', '--dont-print-time' if self.qckb2.isChecked() is True else '', '--force' if self.qckb3.isChecked() is True else '', '--fast' if self.qckb4.isChecked() is True else '', '--cpd-output' if self.xmlo.isChecked() is True else '', '' if self.xmlo.isChecked() is True else '--report-unifiers', '--distance-threshold={}'.format(self.mdist.value()), '--hashing-depth={}'.format(self.hdep.value()), '--ignore-dir="{}"'.format(self.igndir.text() if self.ignckb.currentIndex() is 0 else self.ignmor.toPlainText()), '--func-prefixes="{}"'.format(self.ign_func.text()), '--output="{}"'.format(self.outfle.text()), '--language=python', path.abspath(self.outdir.text()), )) self.output.append(self.formatInfoMsg('INFO:OK:Command:{}'.format(cmd))) self.process.start(cmd) if not self.process.waitForStarted(): self.output.append(self.formatErrorMsg(' ERROR: FAIL: Meh. ')) self.output.append(self.formatErrorMsg('ERROR:FAIL:{}'.format(cmd))) self.button.setEnabled(True) return self.readOutput() self.readErrors() self.button.setEnabled(True) def _process_finished(self): """ finished sucessfully """ self.output.append(self.formatInfoMsg('INFO:{}'.format(datetime.now()))) # write a .log file on target if self.qckb5.isChecked() is True: log_file = 'ninja_clones.log' with open(path.join(str(self.outdir.text()), log_file), 'w') as log: self.output.append(self.formatInfoMsg('''INFO: OK: Writing Logs: {}'''.format(path.join(str(self.outdir.text()), log_file)))) log.write(self.output.toPlainText()) log.close() # open target output if self.opeo.isChecked() is True and self.xmlo.isChecked() is False: try: startfile(self.outfle.text()) except: Popen(["xdg-open", self.outfle.text()]) self.output.selectAll() self.output.setFocus() def toggle_options_group(self): ' toggle on off the options group ' if self.group3.isChecked() is True: [a.setChecked(True) for a in (self.qckb1, self.qckb3, self.qckb5, self.chrt, self.opeo)] self.mdist.setValue(5) self.hdep.setValue(1) self.group3.graphicsEffect().setEnabled(False) else: [a.setChecked(False) for a in (self.qckb1, self.qckb3, self.qckb5, self.chrt, self.opeo)] self.group3.graphicsEffect().setEnabled(True) def on_ignore_changed(self): 'hide or show one widget or another depending what kind of input need' if self.ignckb.currentIndex() is 0: self.igndir.show() self.btn2.show() self.ignmor.hide() else: self.igndir.hide() self.btn2.hide() self.ignmor.show() def on_auto_changed(self): ' automation connects ' if self.auto.currentIndex() is 1: self.locator.get_service('editor').fileSaved.connect(lambda: self.run()) QMessageBox.information(self.dock, __doc__, '<b>Now Actions will Run Automatically when any File is Saved !') elif self.auto.currentIndex() is 2: self.locator.get_service('editor').fileExecuted.connect(lambda: self.run()) QMessageBox.information(self.dock, __doc__, '<b>Now Actions will Run Automatically when any File is Executed !') elif self.auto.currentIndex() is 3: self.locator.get_service('editor').currentTabChanged.connect(lambda: self.run()) QMessageBox.information(self.dock, __doc__, '<b>Now Actions will Run Automatically when current Tab is Changed') elif self.auto.currentIndex() is 4: self.locator.get_service('editor').fileOpened.connect(lambda: self.run()) QMessageBox.information(self.dock, __doc__, '<b>Now Actions will Run Automatically when any File is Opened !') elif self.auto.currentIndex() is 5: self.locator.get_service('editor').beforeFileSaved.connect(lambda: self.run()) QMessageBox.information(self.dock, __doc__, '<b>Now Actions will Run Automatically before any File is Saved !') self.group4.setDisabled(True) def finish(self): ' clear when finish ' self.process.kill()
class Search_QLineEdit(QLineEdit): """ Defines a `QLineEdit <http://doc.qt.nokia.com/qlinedit.html>`_ subclass providing a search field with clearing capabilities. """ def __init__(self, parent=None, uiSearchImage=None, uiSearchClickedImage=None, uiClearImage=None, uiClearClickedImage=None): """ Initializes the class. :param parent: Widget parent. :type parent: QObject :param uiSearchImage: Search button image path. :type uiSearchImage: str :param uiSearchClickedImage: Search button clicked image path. :type uiSearchClickedImage: str :param uiClearImage: Clear button image path. :type uiClearImage: str :param uiClearClickedImage: Clear button clicked image path. :type uiClearClickedImage: str """ LOGGER.debug("> Initializing '{0}()' class.".format( self.__class__.__name__)) QLineEdit.__init__(self, parent) # --- Setting class attributes. --- self.__uiSearchImage = None self.uiSearchImage = uiSearchImage or umbra.ui.common.getResourcePath( "images/Search_Glass.png") self.__uiSearchClickedImage = None self.uiSearchClickedImage = uiSearchClickedImage or umbra.ui.common.getResourcePath( "images/Search_Glass_Clicked.png") self.__uiClearImage = None self.uiClearImage = uiClearImage or umbra.ui.common.getResourcePath( "images/Search_Clear.png") self.__uiClearClickedImage = None self.uiClearClickedImage = uiClearClickedImage or umbra.ui.common.getResourcePath( "images/Search_Clear_Clicked.png") self.__searchActiveLabel = Active_QLabel( self, QPixmap(self.__uiSearchImage), QPixmap(self.__uiSearchImage), QPixmap(self.__uiSearchClickedImage)) self.__searchActiveLabel.setObjectName("Search_Field_activeLabel") self.__searchActiveLabel.showEvent = lambda event: reduce( lambda *args: None, (self.__setStyleSheet(), Active_QLabel.showEvent(self.__searchActiveLabel, event))) self.__searchActiveLabel.hideEvent = lambda event: reduce( lambda *args: None, (self.__setStyleSheet(), Active_QLabel.hideEvent(self.__searchActiveLabel, event))) self.__clearButton = QToolButton(self) self.__clearButton.setObjectName("Clear_Field_button") self.__completer = QCompleter() self.setCompleter(self.__completer) self.__completerVisibleItemsCount = 16 Search_QLineEdit.__initializeUi(self) self.__setClearButtonVisibility(self.text()) # Signals / Slots. self.__clearButton.clicked.connect(self.clear) self.textChanged.connect(self.__setClearButtonVisibility) #****************************************************************************************************************** #*** Attributes properties. #****************************************************************************************************************** @property def uiSearchImage(self): """ Property for **self.__uiSearchImage** attribute. :return: self.__uiSearchImage. :rtype: str """ return self.__uiSearchImage @uiSearchImage.setter @foundations.exceptions.handleExceptions(AssertionError) def uiSearchImage(self, value): """ Setter for **self.__uiSearchImage** attribute. :param value: Attribute value. :type value: str """ if value is not None: assert type( value ) is unicode, "'{0}' attribute: '{1}' type is not 'unicode'!".format( "uiSearchImage", value) assert os.path.exists( value), "'{0}' attribute: '{1}' file doesn't exists!".format( "uiSearchImage", value) self.__uiSearchImage = value @uiSearchImage.deleter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def uiSearchImage(self): """ Deleter for **self.__uiSearchImage** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format( self.__class__.__name__, "uiSearchImage")) @property def uiSearchClickedImage(self): """ Property for **self.__uiSearchClickedImage** attribute. :return: self.__uiSearchClickedImage. :rtype: str """ return self.__uiSearchClickedImage @uiSearchClickedImage.setter @foundations.exceptions.handleExceptions(AssertionError) def uiSearchClickedImage(self, value): """ Setter for **self.__uiSearchClickedImage** attribute. :param value: Attribute value. :type value: str """ if value is not None: assert type( value ) is unicode, "'{0}' attribute: '{1}' type is not 'unicode'!".format( "uiSearchClickedImage", value) assert os.path.exists( value), "'{0}' attribute: '{1}' file doesn't exists!".format( "uiSearchClickedImage", value) self.__uiSearchClickedImage = value @uiSearchClickedImage.deleter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def uiSearchClickedImage(self): """ Deleter for **self.__uiSearchClickedImage** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format( self.__class__.__name__, "uiSearchClickedImage")) @property def uiClearImage(self): """ Property for **self.__uiClearImage** attribute. :return: self.__uiClearImage. :rtype: str """ return self.__uiClearImage @uiClearImage.setter @foundations.exceptions.handleExceptions(AssertionError) def uiClearImage(self, value): """ Setter for **self.__uiClearImage** attribute. :param value: Attribute value. :type value: str """ if value is not None: assert type( value ) is unicode, "'{0}' attribute: '{1}' type is not 'unicode'!".format( "uiClearImage", value) assert os.path.exists( value), "'{0}' attribute: '{1}' file doesn't exists!".format( "uiClearImage", value) self.__uiClearImage = value @uiClearImage.deleter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def uiClearImage(self): """ Deleter for **self.__uiClearImage** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format( self.__class__.__name__, "uiClearImage")) @property def uiClearClickedImage(self): """ Property for **self.__uiClearClickedImage** attribute. :return: self.__uiClearClickedImage. :rtype: str """ return self.__uiClearClickedImage @uiClearClickedImage.setter @foundations.exceptions.handleExceptions(AssertionError) def uiClearClickedImage(self, value): """ Setter for **self.__uiClearClickedImage** attribute. :param value: Attribute value. :type value: str """ if value is not None: assert type( value ) is unicode, "'{0}' attribute: '{1}' type is not 'unicode'!".format( "uiClearClickedImage", value) assert os.path.exists( value), "'{0}' attribute: '{1}' file doesn't exists!".format( "uiClearClickedImage", value) self.__uiClearClickedImage = value @uiClearClickedImage.deleter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def uiClearClickedImage(self): """ Deleter for **self.__uiClearClickedImage** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format( self.__class__.__name__, "uiClearClickedImage")) @property def searchActiveLabel(self): """ Property for **self.__searchActiveLabel** attribute. :return: self.__searchActiveLabel. :rtype: QPushButton """ return self.__searchActiveLabel @searchActiveLabel.setter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def searchActiveLabel(self, value): """ Setter for **self.__searchActiveLabel** attribute. :param value: Attribute value. :type value: QPushButton """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format( self.__class__.__name__, "searchActiveLabel")) @searchActiveLabel.deleter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def searchActiveLabel(self): """ Deleter for **self.__searchActiveLabel** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format( self.__class__.__name__, "searchActiveLabel")) @property def clearButton(self): """ Property for **self.__clearButton** attribute. :return: self.__clearButton. :rtype: QPushButton """ return self.__clearButton @clearButton.setter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def clearButton(self, value): """ Setter for **self.__clearButton** attribute. :param value: Attribute value. :type value: QPushButton """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format( self.__class__.__name__, "clearButton")) @clearButton.deleter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def clearButton(self): """ Deleter for **self.__clearButton** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format( self.__class__.__name__, "clearButton")) @property def completer(self): """ Property for **self.__completer** attribute. :return: self.__completer. :rtype: QCompleter """ return self.__completer @completer.setter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def completer(self, value): """ Setter for **self.__completer** attribute. :param value: Attribute value. :type value: QCompleter """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format( self.__class__.__name__, "completer")) @completer.deleter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def completer(self): """ Deleter for **self.__completer** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format( self.__class__.__name__, "completer")) @property def completerVisibleItemsCount(self): """ Property for **self.__completerVisibleItemsCount** attribute. :return: self.__completerVisibleItemsCount. :rtype: int """ return self.__completerVisibleItemsCount @completerVisibleItemsCount.setter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def completerVisibleItemsCount(self, value): """ Setter for **self.__completerVisibleItemsCount** attribute. :param value: Attribute value. :type value: int """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format( self.__class__.__name__, "completerVisibleItemsCount")) @completerVisibleItemsCount.deleter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def completerVisibleItemsCount(self): """ Deleter for **self.__completerVisibleItemsCount** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format( self.__class__.__name__, "completerVisibleItemsCount")) #****************************************************************************************************************** #*** Class methods. #****************************************************************************************************************** def resizeEvent(self, event): """ Reimplements the :meth:`QLineEdit.QResizeEvent` method. :param event: Resize event. :type event: QResizeEvent """ frameWidth = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth) searchActiveLabelSize = self.__searchActiveLabel.sizeHint() self.__searchActiveLabel.move( self.rect().left() + frameWidth, (self.rect().bottom() - searchActiveLabelSize.height()) / 2 + frameWidth / 2) clearButtonSize = self.__clearButton.sizeHint() self.__clearButton.move( self.rect().right() - frameWidth - clearButtonSize.width(), (self.rect().bottom() - clearButtonSize.height()) / 2 + frameWidth / 2) def __initializeUi(self): """ Initializes the Widget ui. """ self.__clearButton.setCursor(Qt.ArrowCursor) if self.__uiClearImage and self.__uiClearClickedImage: pixmap = QPixmap(self.__uiClearImage) clickedPixmap = QPixmap(self.__uiClearClickedImage) self.__clearButton.setIcon(QIcon(pixmap)) self.__clearButton.setMaximumSize(pixmap.size()) # Signals / Slots. self.__clearButton.pressed.connect( functools.partial(self.__clearButton.setIcon, QIcon(clickedPixmap))) self.__clearButton.released.connect( functools.partial(self.__clearButton.setIcon, QIcon(pixmap))) else: self.__clearButton.setText("Clear") self.__setStyleSheet() frameWidth = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth) self.setMinimumSize( max(self.minimumSizeHint().width(), self.__clearButton.sizeHint().height() + frameWidth * 2), max(self.minimumSizeHint().height(), self.__clearButton.sizeHint().height() + frameWidth * 2)) self.__completer.setCaseSensitivity(Qt.CaseInsensitive) self.__completer.setCompletionMode( QCompleter.UnfilteredPopupCompletion) # self.__completer.setMaxVisibleItems(self.__completerVisibleItemsCount) def __setStyleSheet(self): """ Sets the Widget stylesheet. """ frameWidth = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth) self.setStyleSheet( QString( "QLineEdit {{ padding-left: {0}px; padding-right: {1}px; }}\nQToolButton {{ border: none; padding: 0px; }}" .format( self.__searchActiveLabel.sizeHint().width() if self.__searchActiveLabel.isVisible() else 0 + frameWidth, self.__clearButton.sizeHint().width() + frameWidth))) def __setClearButtonVisibility(self, text): """ Sets the clear button visibility. :param text: Current field text. :type text: QString """ if text: self.__clearButton.show() else: self.__clearButton.hide()
class Main(plugin.Plugin): " Main Class " def initialize(self, *args, **kwargs): " Init Main Class " super(Main, self).initialize(*args, **kwargs) self.process = QProcess() self.process.readyReadStandardOutput.connect(self.readOutput) self.process.readyReadStandardError.connect(self.readErrors) self.process.finished.connect(self._process_finished) self.process.error.connect(self._process_finished) # directory auto completer self.completer, self.dirs = QCompleter(self), QDirModel(self) self.dirs.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot) self.completer.setModel(self.dirs) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setCompletionMode(QCompleter.PopupCompletion) self.group0 = QGroupBox() self.group0.setTitle(' Source ') self.source, self.infile = QComboBox(), QLineEdit(path.expanduser("~")) self.source.addItems(['Local File', 'Remote URL']) self.source.currentIndexChanged.connect(self.on_source_changed) self.infile.setPlaceholderText(' /full/path/to/file.html ') self.infile.setCompleter(self.completer) self.open = QPushButton(QIcon.fromTheme("folder-open"), 'Open') self.open.setCursor(QCursor(Qt.PointingHandCursor)) self.open.clicked.connect(lambda: self.infile.setText( str( QFileDialog.getOpenFileName( self.dock, "Open a File to read from", path.expanduser( "~"), ';;'.join([ '{}(*.{})'.format(e.upper(), e) for e in ['html', 'webp', 'webm', 'svg', 'css', 'js', '*'] ]))))) self.inurl, self.output = QLineEdit('http://www.'), QTextEdit() self.inurl.setPlaceholderText( 'http://www.full/url/to/remote/file.html') self.inurl.hide() vboxg0 = QVBoxLayout(self.group0) for each_widget in (self.source, self.infile, self.open, self.inurl): vboxg0.addWidget(each_widget) self.group1 = QGroupBox() self.group1.setTitle(' Mobile ') self.ckcss1 = QCheckBox('Run in full screen using current resolution') self.ckcss2 = QCheckBox('Disable touch mode and use keypad mode') self.ckcss3 = QCheckBox( 'Disable touch mode but allow to use the mouse') self.ckcss4 = QCheckBox( 'Enable mouse,disable pointer & zoom emulation') self.ckcss5 = QCheckBox('Start the Mobile version of the browser') self.ckcss6 = QCheckBox('Start the Tablet version of the browser') self.ckcss7 = QCheckBox('Emulate hardware with Menu and Back keys') self.ckcss8 = QCheckBox('Start the browser in Kiosk mode') self.width, self.height = QSpinBox(), QSpinBox() self.zoom, self.ram, self.dpi = QSpinBox(), QSpinBox(), QSpinBox() self.cpulag, self.gpulag = QSpinBox(), QSpinBox() self.lang, self.agent = QComboBox(), QComboBox() self.lang.addItems(['EN', 'ES', 'PT', 'JA', 'ZH', 'DE', 'RU', 'FR']) self.agent.addItems(['Default', 'Android', 'MeeGo', 'Desktop']) self.fonts = QLineEdit() self.width.setMaximum(9999) self.width.setMinimum(100) self.width.setValue(480) self.height.setMaximum(9999) self.height.setMinimum(100) self.height.setValue(800) self.zoom.setMaximum(999) self.zoom.setMinimum(1) self.zoom.setValue(100) self.ram.setMaximum(999) self.ram.setMinimum(1) self.ram.setValue(100) self.dpi.setMaximum(200) self.dpi.setMinimum(50) self.dpi.setValue(96) self.cpulag.setMaximum(9999) self.cpulag.setMinimum(0) self.cpulag.setValue(1) self.gpulag.setMaximum(9999) self.gpulag.setMinimum(0) self.gpulag.setValue(1) vboxg1 = QVBoxLayout(self.group1) for each_widget in ( self.ckcss1, self.ckcss2, self.ckcss3, self.ckcss4, self.ckcss5, self.ckcss6, self.ckcss7, self.ckcss8, QLabel('Width Pixels of the emulated device screen'), self.width, QLabel('Height Pixels of the emulated device screen'), self.height, QLabel('Zoom Percentage of emulated screen'), self.zoom, QLabel('RAM MegaBytes of the emulated device'), self.ram, QLabel('Language of the emulated device'), self.lang, QLabel('D.P.I. of the emulated device'), self.dpi, QLabel('User-Agent of the emulated device'), self.agent, QLabel('CPU Core Lag Miliseconds of emulated device'), self.cpulag, QLabel('GPU Video Lag Miliseconds of emulated device'), self.gpulag, QLabel('Extra Fonts Directory Full Path'), self.fonts): vboxg1.addWidget(each_widget) self.group2 = QGroupBox() self.group2.setTitle(' General ') self.nice, self.opera = QSpinBox(), QLineEdit(path.expanduser("~")) self.nice.setValue(20) self.nice.setMaximum(20) self.nice.setMinimum(0) self.opera.setCompleter(self.completer) if path.exists(CONFIG_FILE): with codecs.open(CONFIG_FILE, encoding='utf-8') as fp: self.opera.setText(fp.read()) self.open2 = QPushButton(QIcon.fromTheme("folder-open"), 'Open') self.open2.setCursor(QCursor(Qt.PointingHandCursor)) self.open2.clicked.connect(lambda: self.opera.setText( str( QFileDialog.getOpenFileName( self.dock, "Open Opera Mobile Emulator", path.expanduser("~"), 'Opera Mobile Emulator Executable(opera-mobile-emulator)')) )) self.help1 = QLabel('''<a href= "http://www.opera.com/developer/mobile-emulator"> <small><center>Download Opera Mobile Emulator !</a>''') self.help1.setTextInteractionFlags(Qt.LinksAccessibleByMouse) self.help1.setOpenExternalLinks(True) vboxg4 = QVBoxLayout(self.group2) for each_widget in (QLabel(' Backend CPU priority: '), self.nice, QLabel(' Opera Mobile Emulator Full Path: '), self.opera, self.open2, self.help1): vboxg4.addWidget(each_widget) self.button = QPushButton('Preview on Mobile') self.button.setCursor(QCursor(Qt.PointingHandCursor)) self.button.setMinimumSize(100, 50) self.button.clicked.connect(self.run) glow = QGraphicsDropShadowEffect(self) glow.setOffset(0) glow.setBlurRadius(99) glow.setColor(QColor(99, 255, 255)) self.button.setGraphicsEffect(glow) glow.setEnabled(True) class TransientWidget(QWidget): ' persistant widget thingy ' def __init__(self, widget_list): ' init sub class ' super(TransientWidget, self).__init__() vbox = QVBoxLayout(self) for each_widget in widget_list: vbox.addWidget(each_widget) tw = TransientWidget(( QLabel('<b>Mobile Browser Emulator'), self.group0, self.group1, self.group2, self.output, self.button, )) self.scrollable, self.dock = QScrollArea(), QDockWidget() self.scrollable.setWidgetResizable(True) self.scrollable.setWidget(tw) self.dock.setWindowTitle(__doc__) self.dock.setStyleSheet('QDockWidget::title{text-align: center;}') self.dock.setWidget(self.scrollable) ExplorerContainer().addTab(self.dock, "Mobile") QPushButton( QIcon.fromTheme("help-about"), 'About', self.dock).clicked.connect( lambda: QMessageBox.information(self.dock, __doc__, HELPMSG)) def run(self): ' run the string replacing ' self.output.clear() self.button.setEnabled(False) self.output.append(self.formatInfoMsg('INFO:{}'.format( datetime.now()))) if self.source.currentText() == 'Local File': target = 'file://' + str(self.infile.text()).strip() else: target = self.inurl.text() self.output.append(self.formatInfoMsg(' INFO: OK: Parsing Arguments')) cmd = ' '.join( ('nice --adjustment={}'.format(self.nice.value()), '"{}"'.format( self.opera.text()), '-fullscreen' if self.ckcss1.isChecked() is True else '', '-notouch' if self.ckcss2.isChecked() is True else '', '-notouchwithtouchevents' if self.ckcss3.isChecked() is True else '', '-usemouse' if self.ckcss4.isChecked() is True else '', '-mobileui' if self.ckcss5.isChecked() is True else '', '-tabletui' if self.ckcss6.isChecked() is True else '', '-hasmenuandback' if self.ckcss7.isChecked() is True else '', '-k' if self.ckcss8.isChecked() is True else '', '-displaysize {}x{}'.format( self.width.value(), self.height.value()), '-displayzoom {}'.format( self.zoom.value()), '-mem {}M'.format(self.ram.value()), '-lang {}'.format(self.lang.currentText()), '-ppi {}'.format( self.dpi.value()), '-extra-fonts {}'.format(self.fonts.text()) if str(self.fonts.text()).strip() is not '' else '', '-user-agent-string {}'.format( self.agent.currentText()), '-delaycorethread {}'.format( self.cpulag.value()), '-delayuithread {}'.format( self.gpulag.value()), '-url "{}"'.format(target))) self.output.append(self.formatInfoMsg( 'INFO:OK:Command:{}'.format(cmd))) self.process.start(cmd) if not self.process.waitForStarted(): self.output.append(self.formatErrorMsg(' ERROR: FAIL: Meh. ')) self.output.append( self.formatErrorMsg( 'ERROR: FAIL: Failed with Arguments: {} '.format(cmd))) self.button.setEnabled(True) return self.output.setFocus() self.output.selectAll() self.button.setEnabled(True) def on_source_changed(self): ' do something when the desired source has changed ' if self.source.currentText() == 'Local File': self.open.show() self.infile.show() self.inurl.hide() else: self.inurl.show() self.open.hide() self.infile.hide() def _process_finished(self): """ finished sucessfully """ self.output.append(self.formatInfoMsg('INFO:{}'.format( datetime.now()))) self.output.selectAll() self.output.setFocus() def readOutput(self): """Read and append output to the logBrowser""" self.output.append(str(self.process.readAllStandardOutput()).strip()) def readErrors(self): """Read and append errors to the logBrowser""" self.output.append( self.formatErrorMsg(str(self.process.readAllStandardError()))) def formatErrorMsg(self, msg): """Format error messages in red color""" return self.formatMsg(msg, 'red') def formatInfoMsg(self, msg): """Format informative messages in blue color""" return self.formatMsg(msg, 'green') def formatMsg(self, msg, color): """Format message with the given color""" return '<font color="{}">{}</font>'.format(color, msg) def finish(self): ' save when finish ' with codecs.open(CONFIG_FILE, "w", encoding='utf-8') as fp: fp.write(self.opera.text())
class TalkEditorApp(FreeseerApp): '''Freeseer talk database editor main gui class''' def __init__(self, config, db): super(TalkEditorApp, self).__init__(config) self.db = db icon = QIcon() icon.addPixmap(QPixmap(':/freeseer/logo.png'), QIcon.Normal, QIcon.Off) self.setWindowIcon(icon) self.resize(960, 600) # # Setup Layout # self.mainWidget = QWidget() self.mainLayout = QVBoxLayout() self.mainWidget.setLayout(self.mainLayout) self.setCentralWidget(self.mainWidget) self.mainLayout.setAlignment(Qt.AlignTop) # Add custom widgets self.commandButtons = CommandButtons() self.tableView = QTableView() self.tableView.setSortingEnabled(True) self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows) self.talkDetailsWidget = TalkDetailsWidget() self.importTalksWidget = ImportTalksWidget() self.newTalkWidget = NewTalkWidget() self.mainLayout.addWidget(self.importTalksWidget) #self.mainLayout.addLayout(self.titleLayout) self.mainLayout.addWidget(self.commandButtons) self.mainLayout.addWidget(self.tableView) self.mainLayout.addWidget(self.talkDetailsWidget) self.mainLayout.addWidget(self.importTalksWidget) # --- End Layout # Keep track of index of the most recently selected talk self.currentTalkIndex = QPersistentModelIndex() # Prompt user to "Continue Editing", "Discard Changes" or "Save Changes" self.savePromptBox = QMessageBox() self.savePromptBox.setWindowTitle("Unsaved Changes Exist") self.savePromptBox.setIcon(QMessageBox.Information) self.savePromptBox.setText( "The talk you were editing has unsaved changes.") self.continueButton = self.savePromptBox.addButton( "Continue Editing", QMessageBox.RejectRole) self.discardButton = self.savePromptBox.addButton( "Discard Changes", QMessageBox.DestructiveRole) self.saveButton = self.savePromptBox.addButton("Save Changes", QMessageBox.AcceptRole) self.savePromptBox.setDefaultButton(self.saveButton) # Initialize geometry, to be used for restoring window positioning. self.geometry = None # # Setup Menubar # self.actionExportCsv = QAction(self) self.actionExportCsv.setObjectName('actionExportCsv') self.actionRemoveAll = QAction(self) self.actionRemoveAll.setObjectName('actionRemoveAll') # Actions self.menuFile.insertAction(self.actionExit, self.actionExportCsv) self.menuFile.insertAction(self.actionExit, self.actionRemoveAll) # --- End Menubar # # TableView Connections # self.connect(self.tableView, SIGNAL('activated(const QModelIndex)'), self.click_talk) self.connect(self.tableView, SIGNAL('selected(const QModelIndex)'), self.click_talk) self.connect(self.tableView, SIGNAL('clicked(const QModelIndex)'), self.click_talk) # Import Widget self.connect(self.importTalksWidget.csvRadioButton, SIGNAL('toggled(bool)'), self.toggle_import) self.connect(self.importTalksWidget.importButton, SIGNAL('clicked()'), self.import_talks) self.connect(self.importTalksWidget.cancelButton, SIGNAL('clicked()'), self.hide_import_talks_widget) self.importTalksWidget.setHidden(True) self.connect(self.importTalksWidget.csvFileSelectButton, SIGNAL('clicked()'), self.csv_file_select) self.connect(self.importTalksWidget.csvLineEdit, SIGNAL('returnPressed()'), self.importTalksWidget.importButton.click) self.connect(self.importTalksWidget.rssLineEdit, SIGNAL('returnPressed()'), self.importTalksWidget.importButton.click) self.connect(self.actionExportCsv, SIGNAL('triggered()'), self.export_talks_to_csv) self.connect(self.actionRemoveAll, SIGNAL('triggered()'), self.confirm_reset) # Command Buttons self.connect(self.commandButtons.addButton, SIGNAL('clicked()'), self.click_add_button) self.connect(self.commandButtons.removeButton, SIGNAL('clicked()'), self.remove_talk) self.connect(self.commandButtons.removeAllButton, SIGNAL('clicked()'), self.confirm_reset) self.connect(self.commandButtons.importButton, SIGNAL('clicked()'), self.show_import_talks_widget) self.connect(self.commandButtons.exportButton, SIGNAL('clicked()'), self.export_talks_to_csv) self.connect(self.commandButtons.searchButton, SIGNAL('clicked()'), self.search_talks) self.connect(self.commandButtons.searchLineEdit, SIGNAL('textEdited(QString)'), self.search_talks) self.connect(self.commandButtons.searchLineEdit, SIGNAL('returnPressed()'), self.search_talks) # Talk Details Buttons self.connect(self.talkDetailsWidget.saveButton, SIGNAL('clicked()'), self.update_talk) # Talk Details Widget self.connect(self.talkDetailsWidget.titleLineEdit, SIGNAL('textEdited(const QString)'), self.enable_save) self.connect(self.talkDetailsWidget.presenterLineEdit, SIGNAL('textEdited(const QString)'), self.enable_save) self.connect(self.talkDetailsWidget.categoryLineEdit, SIGNAL('textEdited(const QString)'), self.enable_save) self.connect(self.talkDetailsWidget.eventLineEdit, SIGNAL('textEdited(const QString)'), self.enable_save) self.connect(self.talkDetailsWidget.roomLineEdit, SIGNAL('textEdited(const QString)'), self.enable_save) self.connect(self.talkDetailsWidget.descriptionTextEdit, SIGNAL('modificationChanged(bool)'), self.enable_save) self.connect(self.talkDetailsWidget.dateEdit, SIGNAL('dateChanged(const QDate)'), self.enable_save) self.connect(self.talkDetailsWidget.startTimeEdit, SIGNAL('timeChanged(const QTime)'), self.enable_save) self.connect(self.talkDetailsWidget.endTimeEdit, SIGNAL('timeChanged(const QTime)'), self.enable_save) # New Talk Widget self.newTalkWidget.connect(self.newTalkWidget.addButton, SIGNAL('clicked()'), self.add_talk) self.newTalkWidget.connect(self.newTalkWidget.cancelButton, SIGNAL('clicked()'), self.newTalkWidget.reject) # Load default language actions = self.menuLanguage.actions() for action in actions: if action.data().toString() == self.config.default_language: action.setChecked(True) self.translate(action) break # Load Talk Database self.load_presentations_model() # Setup Autocompletion self.update_autocomplete_fields() self.talkDetailsWidget.saveButton.setEnabled(False) # Select first item #self.tableView.setCurrentIndex(self.proxy.index(0,0)) #self.talk_selected(self.proxy.index(0,0)) # # Translation # def retranslate(self): self.setWindowTitle( self.app.translate("TalkEditorApp", "Freeseer Talk Editor")) # # Reusable Strings # self.confirmDBClearTitleString = self.app.translate( "TalkEditorApp", "Remove All Talks from Database") self.confirmDBClearQuestionString = self.app.translate( "TalkEditorApp", "Are you sure you want to clear the DB?") self.confirmTalkDetailsClearTitleString = self.app.translate( "TalkEditorApp", "Unsaved Data") self.confirmTalkDetailsClearQuestionString = self.app.translate( "TalkEditorApp", "Unsaved talk details will be lost. Continue?") # --- End Reusable Strings # # Menubar # self.actionExportCsv.setText( self.app.translate("TalkEditorApp", "&Export to CSV")) self.actionRemoveAll.setText( self.app.translate("TalkEditorApp", "&Remove All Talks")) # --- End Menubar # # TalkDetailsWidget # self.talkDetailsWidget.titleLabel.setText( self.app.translate("TalkEditorApp", "Title")) self.talkDetailsWidget.presenterLabel.setText( self.app.translate("TalkEditorApp", "Presenter")) self.talkDetailsWidget.categoryLabel.setText( self.app.translate("TalkEditorApp", "Category")) self.talkDetailsWidget.eventLabel.setText( self.app.translate("TalkEditorApp", "Event")) self.talkDetailsWidget.roomLabel.setText( self.app.translate("TalkEditorApp", "Room")) self.talkDetailsWidget.dateLabel.setText( self.app.translate("TalkEditorApp", "Date")) self.talkDetailsWidget.startTimeLabel.setText( self.app.translate("TalkEditorApp", "Start Time")) self.talkDetailsWidget.endTimeLabel.setText( self.app.translate("TalkEditorApp", "End Time")) # --- End TalkDetailsWidget # # Import Talks Widget Translations # self.importTalksWidget.rssRadioButton.setText( self.app.translate("TalkEditorApp", "RSS URL")) self.importTalksWidget.csvRadioButton.setText( self.app.translate("TalkEditorApp", "CSV File")) self.importTalksWidget.importButton.setText( self.app.translate("TalkEditorApp", "Import")) # --- End Talks Widget Translations # # Command Button Translations\ # self.commandButtons.importButton.setText( self.app.translate("TalkEditorApp", "Import")) self.commandButtons.exportButton.setText( self.app.translate("TalkEditorApp", "Export")) self.commandButtons.addButton.setText( self.app.translate("TalkEditorApp", "Add New Talk")) self.commandButtons.removeButton.setText( self.app.translate("TalkEditorApp", "Remove")) self.commandButtons.removeAllButton.setText( self.app.translate("TalkEditorApp", "Remove All")) # --- End Command Butotn Translations # # Search Widget Translations # self.commandButtons.searchButton.setText( self.app.translate("TalkEditorApp", "Search")) # --- End Command Button Translations def load_presentations_model(self): # Load Presentation Model self.presentationModel = self.db.get_presentations_model() self.proxy = QSortFilterProxyModel() self.proxy.setSourceModel(self.presentationModel) self.tableView.setModel(self.proxy) self.proxy.setFilterCaseSensitivity(Qt.CaseInsensitive) # Fill table whitespace. self.tableView.horizontalHeader().setStretchLastSection(False) self.tableView.horizontalHeader().setResizeMode(1, QHeaderView.Stretch) # Hide the ID field self.tableView.setColumnHidden(0, True) # Map data to widgets self.mapper = QDataWidgetMapper() self.mapper.setModel(self.proxy) self.mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit) self.mapper.addMapping(self.talkDetailsWidget.titleLineEdit, 1) self.mapper.addMapping(self.talkDetailsWidget.presenterLineEdit, 2) self.mapper.addMapping(self.talkDetailsWidget.categoryLineEdit, 4) self.mapper.addMapping(self.talkDetailsWidget.eventLineEdit, 5) self.mapper.addMapping(self.talkDetailsWidget.roomLineEdit, 6) self.mapper.addMapping(self.talkDetailsWidget.descriptionTextEdit, 3) self.mapper.addMapping(self.talkDetailsWidget.dateEdit, 7) self.mapper.addMapping(self.talkDetailsWidget.startTimeEdit, 8) self.mapper.addMapping(self.talkDetailsWidget.endTimeEdit, 9) # Load StringLists self.titleList = QStringList(self.db.get_string_list("Title")) #self.speakerList = QStringList(self.db.get_speaker_list()) #self.categoryList = QStringList(self.db.get_category_list()) #self.eventList = QStringList(self.db.get_event_list()) #self.roomList = QStringList(self.db.get_room_list()) #Disble input self.talkDetailsWidget.disable_input_fields() def search_talks(self): # The default value is 0. If the value is -1, the keys will be read from all columns. self.proxy.setFilterKeyColumn(-1) self.proxy.setFilterFixedString( self.commandButtons.searchLineEdit.text()) def show_save_prompt(self): """Prompts the user to save or discard changes, or continue editing.""" self.savePromptBox.exec_() self.savePromptBox.setDefaultButton(self.saveButton) return self.savePromptBox.clickedButton() def click_talk(self, model): """Warns user if there are unsaved changes, and selects talk clicked by the user.""" log.info("Selecting row %d", model.row()) modelRow = model.row() if self.unsaved_details_exist(): log.info("Unsaved changes exist in row %d", self.currentTalkIndex.row()) confirm = self.show_save_prompt() if confirm == self.saveButton: log.info("Saving changes in row %d...", self.currentTalkIndex.row()) self.tableView.selectRow(self.currentTalkIndex.row()) self.update_talk() newModel = self.tableView.currentIndex().sibling(modelRow, 0) self.select_talk(newModel) elif confirm == self.discardButton: log.info("Discarding changes in row %d...", self.currentTalkIndex.row()) self.talk_selected(model) else: log.info("Continue editing row %d", self.currentTalkIndex.row()) self.tableView.selectRow(self.currentTalkIndex.row()) else: self.talk_selected(model) def click_add_button(self): """Warns user if there are unsaved changes, and shows the New Talk window.""" if self.unsaved_details_exist(): log.info("Unsaved changes exist in row %d", self.currentTalkIndex.row()) confirm = self.show_save_prompt() if confirm == self.saveButton: log.info("Saving changes in row %d...", self.currentTalkIndex.row()) self.update_talk() self.show_new_talk_popup() elif confirm == self.discardButton: log.info("Discarding changes in row %d...", self.currentTalkIndex.row()) # Ensure that changes are discarded self.talk_selected(self.currentTalkIndex) self.show_new_talk_popup() else: log.info("Continue editing row %d", self.currentTalkIndex.row()) else: self.show_new_talk_popup() def talk_selected(self, model): self.mapper.setCurrentIndex(model.row()) self.talkDetailsWidget.enable_input_fields() self.talkDetailsWidget.saveButton.setEnabled(False) self.currentTalkIndex = QPersistentModelIndex(model) def toggle_import(self): if self.importTalksWidget.csvRadioButton.isChecked(): self.importTalksWidget.csvLineEdit.setEnabled(True) self.importTalksWidget.csvFileSelectButton.setEnabled(True) self.importTalksWidget.rssLineEdit.setEnabled(False) else: self.importTalksWidget.csvLineEdit.setEnabled(False) self.importTalksWidget.csvFileSelectButton.setEnabled(False) self.importTalksWidget.rssLineEdit.setEnabled(True) def show_import_talks_widget(self): self.commandButtons.setHidden(True) self.tableView.setHidden(True) self.talkDetailsWidget.setHidden(True) self.importTalksWidget.setHidden(False) def hide_import_talks_widget(self): self.commandButtons.setHidden(False) self.tableView.setHidden(False) self.talkDetailsWidget.setHidden(False) self.importTalksWidget.setHidden(True) def add_talk(self): """Adds a new talk to the database using data from the NewTalkWidget input fields""" presentation = self.create_presentation( self.newTalkWidget.talkDetailsWidget) if presentation: self.db.insert_presentation(presentation) self.newTalkWidget.accept() # Close the dialog def update_talk(self): """Updates the currently selected talk using data from the TalkEditorApp input fields""" selected_talk = self.tableView.currentIndex() if selected_talk.row( ) >= 0: # The tableView index begins at 0 and is -1 by default talk_id = selected_talk.sibling(selected_talk.row(), 0).data().toString() presentation = self.create_presentation(self.talkDetailsWidget) if presentation: self.db.update_presentation(talk_id, presentation) self.apply_changes(selected_talk) self.talkDetailsWidget.saveButton.setEnabled(False) def create_presentation(self, talkDetailsWidget): """Creates and returns an instance of Presentation using data from the input fields""" date = talkDetailsWidget.dateEdit.date() startTime = talkDetailsWidget.startTimeEdit.time() endTime = talkDetailsWidget.endTimeEdit.time() title = unicode(talkDetailsWidget.titleLineEdit.text()).strip() if title: return Presentation( unicode(talkDetailsWidget.titleLineEdit.text()).strip(), unicode(talkDetailsWidget.presenterLineEdit.text()).strip(), unicode(talkDetailsWidget.descriptionTextEdit.toPlainText()). strip(), unicode(talkDetailsWidget.categoryLineEdit.text()).strip(), unicode(talkDetailsWidget.eventLineEdit.text()).strip(), unicode(talkDetailsWidget.roomLineEdit.text()).strip(), unicode(date.toString(Qt.ISODate)), unicode(startTime.toString(Qt.ISODate)), unicode(endTime.toString(Qt.ISODate))) def show_new_talk_popup(self): """Displays a modal dialog with a talk details view When Add is selected, a new talk is added to the database using the input field data. When Cancel is selected, no talk is added. """ log.info('Opening Add Talk window...') self.clear_new_talk_fields() self.remove_new_talk_placeholder_text() self.newTalkWidget.talkDetailsWidget.titleLineEdit.setFocus() if self.newTalkWidget.exec_() == 1: self.apply_changes() self.talkDetailsWidget.disable_input_fields() else: log.info('No talk added...') def apply_changes(self, updated_talk=None): """Repopulates the model to display the effective changes Updates the autocomplete fields. Displays the updated model in the table view, and selects the newly updated/added talk. """ self.presentationModel.select() self.select_talk(updated_talk) self.update_autocomplete_fields() def select_talk(self, talk=None): """Selects the given talk in the table view If no talk is given, the last row in the table view is selected. """ if talk: row = talk.row() column = talk.column() else: row = self.presentationModel.rowCount() - 1 # Select last row column = 0 self.tableView.selectRow(row) self.tableView.setCurrentIndex(self.proxy.index(row, column)) self.talk_selected(self.proxy.index(row, column)) def remove_talk(self): try: rows_selected = self.tableView.selectionModel().selectedRows() except: return # Reversed because rows in list change position once row is removed for row in reversed(rows_selected): self.presentationModel.removeRow(row.row()) self.talkDetailsWidget.clear_input_fields() self.talkDetailsWidget.disable_input_fields() def load_talk(self): try: self.tableView.currentIndex().row() except: return self.mapper.addMapping(self.talkDetailsWidget.roomLineEdit, 6) self.presentationModel.select() def reset(self): self.db.clear_database() self.presentationModel.select() self.talkDetailsWidget.clear_input_fields() self.talkDetailsWidget.disable_input_fields() def confirm_reset(self): """Presents a confirmation dialog to ask the user if they are sure they wish to remove the talk database. If Yes call the reset() function""" confirm = QMessageBox.question(self, self.confirmDBClearTitleString, self.confirmDBClearQuestionString, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if confirm == QMessageBox.Yes: self.reset() def add_talks_from_rss(self): rss_url = unicode(self.importTalksWidget.rssLineEdit.text()) if rss_url: self.db.add_talks_from_rss(rss_url) self.presentationModel.select() self.hide_import_talks_widget() else: error = QMessageBox() error.setText("Please enter a RSS URL") error.exec_() def closeEvent(self, event): if self.unsaved_details_exist(): log.info("Unsaved changes exist in row %d", self.currentTalkIndex.row()) confirm = self.show_save_prompt() if confirm == self.saveButton: log.info("Saving changes in row %d...", self.currentTalkIndex.row()) self.update_talk() log.info('Exiting talk database editor...') self.geometry = self.saveGeometry() event.accept() elif confirm == self.discardButton: log.info("Discarding changes in row %d...", self.currentTalkIndex.row()) # Ensure that changes are discarded self.talk_selected(self.currentTalkIndex) log.info('Exiting talk database editor...') self.geometry = self.saveGeometry() event.accept() else: log.info("Continue editing row %d", self.currentTalkIndex.row()) event.ignore() else: log.info('Exiting talk database editor...') self.geometry = self.saveGeometry() event.accept() def csv_file_select(self): fname = QFileDialog.getOpenFileName(self, 'Select file', "", "*.csv") if fname: self.importTalksWidget.csvLineEdit.setText(fname) def add_talks_from_csv(self): fname = self.importTalksWidget.csvLineEdit.text() if fname: self.db.add_talks_from_csv(fname) self.presentationModel.select() self.hide_import_talks_widget() else: error = QMessageBox() error.setText("Please select a file") error.exec_() def import_talks(self): if self.importTalksWidget.csvRadioButton.isChecked(): self.add_talks_from_csv() else: self.add_talks_from_rss() self.update_autocomplete_fields() def export_talks_to_csv(self): fname = QFileDialog.getSaveFileName(self, 'Select file', "", "*.csv") if fname: self.db.export_talks_to_csv(fname) def update_autocomplete_fields(self): self.titleList = QStringList(self.db.get_string_list("Title")) self.speakerList = QStringList(self.db.get_string_list("Speaker")) self.categoryList = QStringList(self.db.get_string_list("Category")) self.eventList = QStringList(self.db.get_string_list("Event")) self.roomList = QStringList(self.db.get_string_list("Room")) self.titleCompleter = QCompleter(self.titleList) self.titleCompleter.setCaseSensitivity(Qt.CaseInsensitive) self.speakerCompleter = QCompleter(self.speakerList) self.speakerCompleter.setCaseSensitivity(Qt.CaseInsensitive) self.categoryCompleter = QCompleter(self.categoryList) self.categoryCompleter.setCaseSensitivity(Qt.CaseInsensitive) self.eventCompleter = QCompleter(self.eventList) self.eventCompleter.setCaseSensitivity(Qt.CaseInsensitive) self.roomCompleter = QCompleter(self.roomList) self.roomCompleter.setCaseSensitivity(Qt.CaseInsensitive) self.talkDetailsWidget.titleLineEdit.setCompleter(self.titleCompleter) self.talkDetailsWidget.presenterLineEdit.setCompleter( self.speakerCompleter) self.talkDetailsWidget.categoryLineEdit.setCompleter( self.categoryCompleter) self.talkDetailsWidget.eventLineEdit.setCompleter(self.eventCompleter) self.talkDetailsWidget.roomLineEdit.setCompleter(self.roomCompleter) def are_fields_enabled(self): return (self.talkDetailsWidget.titleLineEdit.isEnabled() and self.talkDetailsWidget.presenterLineEdit.isEnabled() and self.talkDetailsWidget.categoryLineEdit.isEnabled() and self.talkDetailsWidget.eventLineEdit.isEnabled() and self.talkDetailsWidget.roomLineEdit.isEnabled() and self.talkDetailsWidget.dateEdit.isEnabled() and self.talkDetailsWidget.startTimeEdit.isEnabled() and self.talkDetailsWidget.endTimeEdit.isEnabled()) def unsaved_details_exist(self): """Checks if changes have been made to new/existing talk details Looks for text in the input fields and check the enabled state of the Save Talk button If the Save Talk button is enabled, the input fields contain modified values """ return (self.talkDetailsWidget.saveButton.isEnabled() and (self.talkDetailsWidget.titleLineEdit.text() or self.talkDetailsWidget.presenterLineEdit.text() or self.talkDetailsWidget.categoryLineEdit.text() or self.talkDetailsWidget.descriptionTextEdit.toPlainText())) def enable_save(self): self.talkDetailsWidget.saveButton.setEnabled(True) def clear_new_talk_fields(self): """Removes existing data from all NewTalkWidget fields except event, room, date and time""" self.newTalkWidget.talkDetailsWidget.titleLineEdit.clear() self.newTalkWidget.talkDetailsWidget.presenterLineEdit.clear() self.newTalkWidget.talkDetailsWidget.descriptionTextEdit.clear() self.newTalkWidget.talkDetailsWidget.categoryLineEdit.clear() def remove_new_talk_placeholder_text(self): """Removes placeholder text in NewTalkWidget originally set by TalkDetailsWidget""" self.newTalkWidget.talkDetailsWidget.titleLineEdit.setPlaceholderText( "") self.newTalkWidget.talkDetailsWidget.presenterLineEdit.setPlaceholderText( "") self.newTalkWidget.talkDetailsWidget.categoryLineEdit.setPlaceholderText( "") self.newTalkWidget.talkDetailsWidget.eventLineEdit.setPlaceholderText( "") self.newTalkWidget.talkDetailsWidget.roomLineEdit.setPlaceholderText( "")
class Main(plugin.Plugin): " Main Class " def initialize(self, *args, **kwargs): " Init Main Class " super(Main, self).initialize(*args, **kwargs) self.infile = QLineEdit(path.expanduser("~")) self.infile.setPlaceholderText(' /full/path/to/file ') self.infile.returnPressed.connect(self.run) self.completer, self.dirs = QCompleter(self), QDirModel(self) self.dirs.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot) self.completer.setModel(self.dirs) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setCompletionMode(QCompleter.PopupCompletion) self.infile.setCompleter(self.completer) self.menu = QMenu('Base64') self.menu.aboutToShow.connect(self.build_submenu) self.ex_locator = self.locator.get_service('explorer') self.ex_locator.add_project_menu(self.menu, lang='all') self.open = QPushButton(QIcon.fromTheme("folder-open"), 'Open') self.open.setCursor(QCursor(Qt.PointingHandCursor)) self.open.clicked.connect(lambda: self.infile.setText(str( QFileDialog.getOpenFileName(self.dock, "Open a File to Encode...", path.expanduser("~"), ';;'.join(['{}(*.{})'.format(e.upper(), e) for e in ['*', 'jpg', 'png', 'webp', 'svg', 'gif', 'webm']]))))) self.chckbx1 = QCheckBox('Use basic Caesar Cipher (ROT13)') self.chckbx1.setToolTip('Use "string".decode("rot13") to Decipher ! ') self.chckbx2 = QCheckBox('Use "data:type/subtype;base64,..."') self.chckbx2.setChecked(True) self.chckbx3 = QCheckBox('Copy encoded output to Clipboard') self.chckbx4 = QCheckBox('Use URL-Safe Base64 Encoder') self.combo1 = QComboBox() self.combo1.addItems(['Do Not Generate Code', 'Generate CSS embed Code', 'Generate Python Embed Code', 'Generate HTML embed Code', 'Generate JS embed Code', 'Generate QML embed Code']) self.combo1.currentIndexChanged.connect(self.combo_changed) self.output = QTextEdit(''' We can only see a short distance ahead, but we can see plenty there that needs to be done. - Alan Turing ''') self.output.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.button = QPushButton(QIcon.fromTheme("face-cool"), 'Encode BASE64') self.button.setCursor(QCursor(Qt.PointingHandCursor)) self.button.setMinimumSize(100, 50) self.button.clicked.connect(self.run) glow = QGraphicsDropShadowEffect(self) glow.setOffset(0) glow.setBlurRadius(99) glow.setColor(QColor(99, 255, 255)) self.button.setGraphicsEffect(glow) glow.setEnabled(True) class TransientWidget(QWidget): ' persistant widget thingy ' def __init__(self, widget_list): ' init sub class ' super(TransientWidget, self).__init__() vbox = QVBoxLayout(self) for each_widget in widget_list: vbox.addWidget(each_widget) tw = TransientWidget((QLabel('<i>Encode file as plain text string</i>'), QLabel('<b>File to Encode:'), self.infile, self.open, self.chckbx2, self.chckbx3, self.chckbx1, self.chckbx4, QLabel('<b>Embedding Template Code:'), self.combo1, QLabel(' <b>Base64 String Output: '), self.output, QLabel('<center><small><i>' + ''.join((__doc__, __version__, __license__, 'by', __author__))), self.button )) self.scrollable, self.dock = QScrollArea(), QDockWidget() self.scrollable.setWidgetResizable(True) self.scrollable.setWidget(tw) self.dock.setWindowTitle(__doc__) self.dock.setStyleSheet('QDockWidget::title{text-align: center;}') self.dock.setWidget(self.scrollable) ExplorerContainer().addTab(self.dock, "Base64") self.guimode = QComboBox(self.dock) self.guimode.addItems(['Full Mode', 'Simple Mode']) self.guimode.currentIndexChanged.connect(self.guimode_change) def guimode_change(self): """ Change from Simple Mode to Full Mode by Hide or Show Widgets """ if self.guimode.currentIndex() is 0: self.chckbx1.show() self.chckbx2.show() self.chckbx3.show() self.chckbx4.show() else: self.chckbx1.hide() self.chckbx2.hide() self.chckbx3.hide() self.chckbx4.hide() self.chckbx1.setChecked(False) self.chckbx2.setChecked(True) self.chckbx3.setChecked(False) self.chckbx4.setChecked(False) def build_submenu(self): ''' build sub menu on the fly based on file path ''' self.menu.clear() if self.ex_locator.get_current_project_item().isFolder is not True: filenam = self.ex_locator.get_current_project_item().get_full_path() self.menu.addActions([ QAction('Copy {} as Base64'.format(path.basename(filenam)[:50]), self, triggered=lambda: QApplication.clipboard().setText( '"data:{};charset=utf-8;base64,{}"'.format( guess_type(filenam, strict=False)[0], b64encode(open(filenam, "rb").read())))), QAction('Copy {} as Base64 URL-Safe'.format( path.basename(filenam)[:50]), self, triggered=lambda: QApplication.clipboard().setText( '"data:{};charset=utf-8;base64,{}"'.format( guess_type(filenam, strict=False)[0], urlsafe_b64encode(open(filenam, "rb").read()))))]) self.menu.show() def run(self): ' run the encoding ' mimetype = guess_type(str(self.infile.text()).strip(), strict=False)[0] _mime = mimetype if mimetype is not None else self.ask_mime() fle = str(self.infile.text()).strip().replace('file:///', '/') encoder = urlsafe_b64encode if self.chckbx4.isChecked() else b64encode if int(path.getsize(fle)) / 1024 / 1024 >= 1: QMessageBox.information(self.dock, __doc__, '''<b style="color:red"> WARNING!: File size is > 1 Megabyte!,<br> this will take some time, depending your CPU Processing power!.''') output = '"{}{}{}{}"'.format( 'data:' if self.chckbx2.isChecked() is True else '', _mime if self.chckbx2.isChecked() is True else '', ';charset=utf-8;base64,' if self.chckbx2.isChecked() is True else '', encoder(open(fle, "rb").read())) if self.combo1.currentIndex() is 1: output = ('html, body { margin:0; padding:0; background: url(' + output + ') no-repeat center center fixed; background-size:cover }') elif self.combo1.currentIndex() is 2: output = PY_EMBED.format(getuser(), datetime.now().isoformat().split('.')[0], output) elif self.combo1.currentIndex() is 3: output = '<img src={} alt="{}" title="{}"/>'.format(output, fle.split(sep)[-1], fle.split(sep)[-1]) elif self.combo1.currentIndex() is 4: output = 'var embedded_file = window.atob({}); '.format(output) elif self.combo1.currentIndex() is 5: output = 'Image { source: ' + output + ' } ' if self.chckbx1.isChecked() is True: output = str(output).encode('rot13') if self.chckbx3.isChecked() is True: QApplication.clipboard().setText(output) self.output.setPlainText(output) self.output.setFocus() self.output.selectAll() def ask_mime(self): ' ask user for mime type ' return str(QInputDialog.getText(self.dock, __doc__, 'Write a MIME-Type', QLineEdit.Normal, 'application/octet-stream')[0]).strip().lower() def combo_changed(self): ' on combo changed ' if self.combo1.currentIndex() is 1 or self.combo1.currentIndex() is 3: self.chckbx1.setChecked(False) self.chckbx2.setChecked(True) elif self.combo1.currentIndex() is 2 or self.combo1.currentIndex() is 4: self.chckbx1.setChecked(False) self.chckbx2.setChecked(False)
class MainWidget(QWidget, PM, Ui_MainWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) self.setupUi(self) self.parent = parent self._selectedGroups = [] self._preexceptions = [] self._postexceptions = [] self.state = StateManager(self) self.currentState = None self.completer = None self._updatesCheckedOnce = False # Search Thread self._searchThread = PThread(self, self.startSearch, self.searchFinished) self.statusUpdater = StatusUpdater() self.basket = BasketDialog(self.state, self.parent) self._postexceptions.append(lambda: self.basket.setActionEnabled(True)) self.searchButton.setIcon(KIcon(("edit-find", "find"))) self.initializeUpdateTypeList() model = PackageModel(self) proxy = PackageProxy(self) proxy.setSourceModel(model) self.packageList.setModel(proxy) self.packageList.setItemDelegate(PackageDelegate(self, self.parent)) self.packageList.setColumnWidth(0, 32) self.connect(self.packageList.model(), SIGNAL("dataChanged(QModelIndex,QModelIndex)"), self.statusChanged) self.connect(self.packageList, SIGNAL("updateRequested()"), self.initialize) self.updateSettings() self.setActionButton() self.operation = OperationManager(self.state) self.progressDialog = ProgressDialog(self.state, self.parent) self._preexceptions.append(self.progressDialog._hide) self.progressDialog.registerFunction( FINISHED, lambda: self.parent.statusBar().setVisible( not self.progressDialog.isVisible())) self.progressDialog.registerFunction( OUT, lambda: self.parent.statusBar().show()) self.summaryDialog = SummaryDialog() self.connectOperationSignals() self.pdsMessageBox = PMessageBox(self.content) def connectMainSignals(self): self.connect(self.actionButton, SIGNAL("clicked()"), self.showBasket) self.connect(self.checkUpdatesButton, SIGNAL("clicked()"), self.state.updateRepoAction) self.connect(self.searchButton, SIGNAL("clicked()"), self.searchActivated) self.connect(self.searchLine, SIGNAL("textEdited(const QString&)"), self.searchLineChanged) self.connect(self.searchLine, SIGNAL("returnPressed()"), self.searchActivated) self.connect(self.searchLine, SIGNAL("clearButtonClicked()"), self.groupFilter) self.connect(self.typeCombo, SIGNAL("activated(int)"), self.typeFilter) self.connect(self.stateTab, SIGNAL("currentChanged(int)"), self.switchState) self.connect(self.groupList, SIGNAL("groupChanged()"), self.groupFilter) self.connect(self.groupList, SIGNAL("groupChanged()"), lambda: self.searchButton.setEnabled(False)) self.connect(self.packageList.select_all, SIGNAL("clicked(bool)"), self.toggleSelectAll) self.connect(self.statusUpdater, SIGNAL("selectedInfoChanged(int, QString, int, QString)"), self.emitStatusBarInfo) self.connect( self.statusUpdater, SIGNAL("selectedInfoChanged(QString)"), lambda message: self.emit( SIGNAL("selectionStatusChanged(QString)"), message)) self.connect(self.statusUpdater, SIGNAL("finished()"), self.statusUpdated) def initialize(self): waitCursor() self.searchLine.clear() self._started = False self._last_packages = None self.state.reset() self.initializePackageList() self.initializeGroupList() self.initializeStatusUpdater() self.statusChanged() self._selectedGroups = [] self.packageList.select_all.setChecked(False) self.initializeBasket() self.searchLine.setFocus(True) if self.currentState == self.state.UPGRADE: if self.groupList.count() == 0: QTimer.singleShot(0, \ lambda: self.pdsMessageBox.showMessage(i18n("All packages are up to date"), icon = "info")) if self.groupList.count() > 0: if self.state.inUpgrade(): self.pdsMessageBox.hideMessage(force=True) restoreCursor() def initializeStatusUpdater(self): self.statusUpdater.calculate_deps = not self.state.state == self.state.ALL self.statusUpdater.setModel(self.packageList.model().sourceModel()) def initializeBasket(self): waitCursor() self.basket.setModel(self.packageList.model().sourceModel()) restoreCursor() def initializePackageList(self): self.packageList.model().reset() self.packageList.setPackages(self.state.packages()) if self.completer: self.completer.deleteLater() del self.completer self.completer = QCompleter(self.state.packages(), self) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.searchLine.setCompleter(self.completer) def selectComponent(self, component): if not self.state.iface.operationInProgress(): if self.basket.isVisible(): self.basket._hide() self.stateTab.setCurrentIndex(1) self.switchState(self.state.INSTALL) if component in self.groupList._list: self.groupList.setCurrentItem(self.groupList._list[component]) self.groupFilter() def updateSettings(self): self.packageList.showComponents = PMConfig().showComponents() self.packageList.showIsA = PMConfig().showIsA() self.packageList.setFocus() def searchLineChanged(self, text): self.searchButton.setEnabled(bool(text)) if text == '': self.searchActivated() def statusUpdated(self): if self.statusUpdater.needsUpdate: self.statusUpdater.needsUpdate = False self.statusChanged() def statusChanged(self): self.setActionEnabled() if self.statusUpdater.isRunning(): self.statusUpdater.needsUpdate = True else: self.emit(SIGNAL("updatingStatus()")) self.statusUpdater.start() def initializeGroupList(self): self.groupList.clear() self.groupList._list = {} self.groupList.setAlternatingRowColors(True) self.groupList.setIconSize(QSize(32, 32)) self.groupList.setState(self.state) self.groupList.addGroups(self.state.groups()) if self.state.state == self.state.UPGRADE: self.typeCombo.show() else: self.typeCombo.hide() self.state._typeFilter = 'normal' self.groupFilter() def packageFilter(self, text): self.packageList.model().setFilterRole(Qt.DisplayRole) self.packageList.model().setFilterRegExp( QRegExp(unicode(text), Qt.CaseInsensitive, QRegExp.FixedString)) def typeFilter(self, index): if self.state.state == self.state.UPGRADE: filter = self.typeCombo.itemData(index).toString() if not self.state._typeFilter == filter: self.state._typeFilter = filter self.initializeGroupList() def groupFilter(self): waitCursor() self.packageList.resetMoreInfoRow() packages = self.state.groupPackages(self.groupList.currentGroup()) self.packageList.model().setFilterRole(GroupRole) self.packageList.model().setFilterPackages(packages) self.packageList.scrollToTop() self.packageList.select_all.setChecked( self.groupList.currentGroup() in self._selectedGroups) restoreCursor() def searchActivated(self): if self.currentState == self.state.UPGRADE: if self.groupList.count() == 0 and not self.searchUsed: return if not self.searchLine.text() == '': self.pdsMessageBox.showMessage(i18n("Searching..."), busy=True) self.groupList.lastSelected = None self._searchThread.start() self.searchUsed = True else: self.state.cached_packages = None self.state.packages() self.searchUsed = False self.searchFinished() def searchFinished(self): if self.state.cached_packages == []: self.pdsMessageBox.showMessage(i18n("No results found."), "dialog-information") else: self.pdsMessageBox.hideMessage() self.initializeGroupList() def startSearch(self): searchText = str(self.searchLine.text()).split() sourceModel = self.packageList.model().sourceModel() self.state.cached_packages = sourceModel.search(searchText) def setActionButton(self): self.actionButton.setEnabled(False) if self.state.state == self.state.ALL: menu = QMenu(self.actionButton) self.__install_action = menu.addAction( self.state.getActionIcon(self.state.INSTALL), self.state.getActionName(self.state.INSTALL), self.showBasket) self.__remove_action = menu.addAction( self.state.getActionIcon(self.state.REMOVE), self.state.getActionName(self.state.REMOVE), self.showBasket) self.actionButton.setMenu(menu) else: self.actionButton.setMenu(None) self.actionButton.setIcon(self.state.getActionIcon()) self.actionButton.setText(self.state.getActionName()) def actionStarted(self, operation): self.pdsMessageBox.hideMessage() self.progressDialog.reset() if not operation in [ "System.Manager.updateRepository", "System.Manager.updateAllRepositories" ]: totalPackages = self.packageList.packageCount() self.operation.setTotalPackages(totalPackages) self.progressDialog.updateStatus(0, totalPackages, self.state.toBe()) if self.isVisible(): if operation in [ "System.Manager.updateRepository", "System.Manager.updateAllRepositories" ]: self.progressDialog.repoOperationView() if self.basket.isVisible(): self.basket._hide() QTimer.singleShot(0, self.progressDialog._show) else: self.progressDialog._show() if not self._started: self.progressDialog.disableCancel() else: self.progressDialog.enableCancel() def actionFinished(self, operation): if operation in ("System.Manager.installPackage", "System.Manager.removePackage", "System.Manager.updatePackage"): self.notifyFinished() if operation == "System.Manager.installPackage" and self._started: KIconLoader.updateAvailableIcons() self.summaryDialog.setDesktopFiles(self.operation.desktopFiles) self.summaryDialog.showSummary() if operation in ("System.Manager.updateRepository", "System.Manager.updateAllRepositories"): self.emit(SIGNAL("repositoriesUpdated()")) self.searchLine.clear() self.state.reset() self.progressDialog._hide() if not self.currentState == self.state.UPGRADE: self.switchState(self.currentState) self.initialize() def actionCancelled(self): self.progressDialog._hide() self.progressDialog.reset() self.switchState(self.currentState) self.groupFilter() def setActionEnabled(self): enabled = self.packageList.isSelected() self.actionButton.setEnabled(enabled) self.basket.setActionEnabled(enabled) def switchState(self, state): self.pdsMessageBox.hideMessage() self._states[state][1].setChecked(True) self.state.setState(state) self.currentState = state self._selectedGroups = [] if not state == self.state.HISTORY: self.setActionButton() self.state.cached_packages = None if state == self.state.UPGRADE or (state == self.state.INSTALL and self.groupList.count() == 1): if not self._updatesCheckedOnce: self._updatesCheckedOnce = self.state.updateRepoAction( silence=True) self.checkUpdatesButton.setHidden(not state == self.state.UPGRADE) self.initialize() def emitStatusBarInfo(self, packages, packagesSize, extraPackages, extraPackagesSize): self.emit( SIGNAL("selectionStatusChanged(QString)"), self.state.statusText(packages, packagesSize, extraPackages, extraPackagesSize)) def setSelectAll(self, packages=None): if packages: self.packageList.reverseSelection(packages) def setReverseAll(self, packages=None): if packages: self.packageList.selectAll(packages) def toggleSelectAll(self, toggled): self._last_packages = self.packageList.model().getFilteredPackages() if toggled: if self.groupList.currentGroup() not in self._selectedGroups: self._selectedGroups.append(self.groupList.currentGroup()) self.setReverseAll(self._last_packages) else: if self.groupList.currentGroup() in self._selectedGroups: self._selectedGroups.remove(self.groupList.currentGroup()) self.setSelectAll(self._last_packages) self.packageList.setFocus() self.statusChanged() def showBasket(self): if self.basket.isVisible(): return waitCursor() self.statusUpdater.wait() if self.currentState == self.state.ALL: action = { self.__remove_action: self.state.REMOVE, self.__install_action: self.state.INSTALL }.get(self.sender(), self.state.INSTALL) if action: if action == self.state.REMOVE: installed_packages = self.state.iface.getInstalledPackages( ) filtered_packages = filter( lambda x: x not in installed_packages, self.basket.model.selectedPackages()) if filtered_packages == self.basket.model.selectedPackages( ): restoreCursor() QMessageBox( i18n("Select packages"), i18n( "You must select at least one installed package" ), QMessageBox.Information, QMessageBox.Ok, 0, 0).exec_() return self.packageList.model().sourceModel().selectPackages( filtered_packages, state=False) self.state.state = action self.basket._show() restoreCursor() def initializeUpdateTypeList(self): self.typeCombo.clear() UPDATE_TYPES = [[ 'normal', i18n('All Updates'), ('system-software-update', 'ledgreen') ], [ 'security', i18n('Security Updates'), ('security-medium', 'ledyellow') ], [ 'critical', i18n('Critical Updates'), ('security-low', 'ledred') ]] for type in UPDATE_TYPES: self.typeCombo.addItem(KIcon(type[2]), type[1], QVariant(type[0]))
def newDocument( self ): """ activar todos los controles, llenar los modelos necesarios, crear el modelo Pago, aniadir una linea a la tabla """ if not self.database.isOpen(): if not self.database.open(): raise UserWarning( u"No se pudo establecer la conexión con "\ + "la base de datos" ) query = QSqlQuery() try: # Rellenar el combobox de las CONCEPTOS self.conceptosModel.setQuery( """ SELECT idconcepto, descripcion FROM conceptos c WHERE idtipodoc = %d; """ % constantes.IDPAGO ) if self.conceptosModel.rowCount() == 0: raise UserWarning( u"No existen conceptos en la base de "\ + "datos para los pagos" ) self.beneficiariosModel = QSqlQueryModel() self.beneficiariosModel.setQuery( """ SELECT s.idpersona, s.nombre FROM personas s WHERE s.tipopersona <> %d ORDER BY s.nombre """ % constantes.AUTOR ) if self.beneficiariosModel.rowCount() == 0: raise UserWarning( u"No existen personas en la base de datos" ) # Rellenar el combobox de las retenciones self.retencionModel = QSqlQueryModel() self.retencionModel.setQuery( """ SELECT idcostoagregado, FORMAT(valorcosto,0) as tasa FROM costosagregados WHERE idtipocosto IN (%d,%d) AND activo=1 ORDER BY valorcosto desc; """ % ( constantes.RETENCIONPROFESIONALES, constantes.RETENCIONFUENTE ) ) if self.retencionModel.rowCount() == 0: raise UserWarning( u"No existe ninguna tasa de retención en "\ + "la base de datos" ) query = QSqlQuery( """ SELECT SUM(IF(m.idtipomoneda = %d,m.monto,0)) as totalC, SUM(IF(m.idtipomoneda = %d,m.monto,0)) as totalD FROM movimientoscaja m JOIN documentos d ON d.iddocumento = m.iddocumento WHERE d.idcaja = %d AND m.idtipomovimiento=%d ; """ % ( constantes.IDCORDOBAS, constantes.IDDOLARES, self.sesion.cajaId, constantes.IDPAGOEFECTIVO ) ) if not query.exec_(): raise UserWarning( u"No pudo obtenerse de la base de datos la cantidad de dinero en caja" ) query.first() maxCordoba = Decimal( query.value( 0 ).toString() ) maxDolar = Decimal( query.value( 1 ).toString() ) if maxCordoba <= 0 and maxDolar <= 0: raise UserWarning( u"No hay Efectivo en Caja" ) query = QSqlQuery( "SELECT fnCONSECUTIVO(%d,null);" % constantes.IDPAGO ) if not query.exec_(): raise UserWarning( u"No pudo obtenerse el número del comprobante" ) query.first() ndoc = query.value( 0 ).toString() self.lblnpago.setText( ndoc ) self.txttipocambio.setText( moneyfmt( self.sesion.tipoCambioBanco, 4 ) ) self.cbtasaret.setModel( self.retencionModel ) self.cbtasaret.setModelColumn( 1 ) self.cbtasaret.setCurrentIndex( -1 ) self.retencionId = 0 self.cbbeneficiario.setModel( self.beneficiariosModel ) self.cbbeneficiario.setCurrentIndex( -1 ) self.cbbeneficiario.setModelColumn( 1 ) completer = QCompleter() completer.setCaseSensitivity( Qt.CaseInsensitive ) completer.setModel( self.beneficiariosModel ) completer.setCompletionColumn( 1 ) self.cbconcepto.setModel( self.conceptosModel ) self.cbconcepto.setCurrentIndex( -1 ) self.cbconcepto.setModelColumn( 1 ) completerconcepto = QCompleter() completerconcepto.setCaseSensitivity( Qt.CaseInsensitive ) completerconcepto.setModel( self.conceptosModel ) completerconcepto.setCompletionColumn( 1 ) self.editmodel = PagoModel( self.sesion ) self.editmodel.docImpreso = ndoc self.editmodel.maxCordoba = maxCordoba self.editmodel.maxDolar = maxDolar self.sbtotalc.setToolTip( "Max= " + moneyfmt( maxCordoba, 4, 'C$' ) ) self.sbtotald.setToolTip( "Max= " + moneyfmt( maxDolar, 4, 'US$' ) ) self.sbtotalc.setMaximum( maxCordoba ) self.sbtotald.setMaximum( maxDolar ) query = QSqlQuery( """ SELECT idcostoagregado, valorcosto FROM costosagregados c WHERE idtipocosto = %d AND activo = 1; """ % constantes.IVA ) if not query.exec_(): raise UserWarning( u"No pudo obtenerse la tasa de IVA" ) query.first() self.editmodel.ivaId = query.value( 0 ).toInt()[0] self.editmodel.ivaTasa = Decimal( query.value( 1 ).toString() ) self.ckiva.setToolTip( query.value( 1 ).toString() + '%' ) self.status = False except UserWarning as inst: QMessageBox.critical( self, qApp.organizationName(), unicode( inst ) ) logging.error( unicode( inst ) ) logging.error( query.lastError().text() ) # except Exception as inst: # QMessageBox.critical( self, qApp.organizationName(), # "Hubo un problema al tratar de crear"\ # + " el nuevo pago" ) # logging.critical( unicode( inst ) ) # logging.error( query.lastError().text() ) finally: if QSqlDatabase.database().isOpen(): QSqlDatabase.database().close()
class MyMainWindow(QMainWindow): " Main Window " def __init__(self, parent=None): " Initialize QWidget inside MyMainWindow " super(MyMainWindow, self).__init__(parent) QWidget.__init__(self) self.statusBar().showMessage(" {}".format(__doc__)) self.setStyleSheet("QStatusBar{color:grey;}") self.setWindowTitle(__doc__) self.setWindowIcon(QIcon.fromTheme("face-monkey")) self.setFont(QFont("Ubuntu Light", 10)) self.setMaximumSize(QDesktopWidget().screenGeometry().width(), QDesktopWidget().screenGeometry().height()) # directory auto completer self.completer = QCompleter(self) self.dirs = QDirModel(self) self.dirs.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot) self.completer.setModel(self.dirs) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setCompletionMode(QCompleter.PopupCompletion) # Proxy support, by reading http_proxy os env variable proxy_url = QUrl(environ.get("http_proxy", "")) QNetworkProxy.setApplicationProxy( QNetworkProxy( QNetworkProxy.HttpProxy if str(proxy_url.scheme()).startswith("http") else QNetworkProxy.Socks5Proxy, proxy_url.host(), proxy_url.port(), proxy_url.userName(), proxy_url.password(), ) ) if "http_proxy" in environ else None print((" INFO: Proxy Auto-Config as " + str(proxy_url))) # basic widgets layouts and set up self.mainwidget = QTabWidget() self.mainwidget.setToolTip(__doc__) self.mainwidget.setContextMenuPolicy(Qt.CustomContextMenu) self.mainwidget.tabCloseRequested.connect(lambda: self.mainwidget.setTabPosition(randint(0, 3))) # if self.mainwidget.tabPosition() == 0 # else self.mainwidget.setTabPosition(0)) self.mainwidget.setStyleSheet("QTabBar{color:white;font-weight:bold;}") self.mainwidget.setTabBar(TabBar(self)) self.mainwidget.setMovable(True) self.mainwidget.setTabsClosable(True) self.mainwidget.setTabShape(QTabWidget.Triangular) self.setCentralWidget(self.mainwidget) self.dock1 = QDockWidget() self.dock2 = QDockWidget() self.dock3 = QDockWidget() for a in (self.dock1, self.dock2, self.dock3): a.setWindowModality(Qt.NonModal) a.setWindowOpacity(0.9) a.setWindowTitle(__doc__ if a.windowTitle() == "" else a.windowTitle()) a.setStyleSheet(" QDockWidget::title{text-align:center;}") self.mainwidget.addTab(a, QIcon.fromTheme("face-smile"), "Double Click Me") # Paleta de colores para pintar transparente self.palette().setBrush(QPalette.Base, Qt.transparent) self.setPalette(self.palette()) self.setAttribute(Qt.WA_OpaquePaintEvent, False) # toolbar and basic actions self.toolbar = QToolBar(self) self.toolbar.setIconSize(QSize(24, 24)) # spacer widget for left self.left_spacer = QWidget(self) self.left_spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) # spacer widget for right self.right_spacer = QWidget(self) self.right_spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) qaqq = QAction(QIcon.fromTheme("application-exit"), "Quit", self) qaqq.setShortcut("Ctrl+Q") qaqq.triggered.connect(exit) qamin = QAction(QIcon.fromTheme("go-down"), "Minimize", self) qamin.triggered.connect(lambda: self.showMinimized()) qamax = QAction(QIcon.fromTheme("go-up"), "Maximize", self) qanor = QAction(QIcon.fromTheme("view-fullscreen"), "AutoCenter AutoResize", self) qanor.triggered.connect(self.center) qatim = QAction(QIcon.fromTheme("mail-signed-verified"), "View Date and Time", self) qatim.triggered.connect(self.timedate) qabug = QAction(QIcon.fromTheme("help-about"), "Report a Problem", self) qabug.triggered.connect( lambda: qabug.setDisabled(True) if not call("xdg-open mailto:" + "*****@*****.**".decode("rot13"), shell=True) else " ERROR " ) qamax.triggered.connect(lambda: self.showMaximized()) qaqt = QAction(QIcon.fromTheme("help-about"), "About Qt", self) qaqt.triggered.connect(lambda: QMessageBox.aboutQt(self)) qakde = QAction(QIcon.fromTheme("help-about"), "About KDE", self) if KDE: qakde.triggered.connect(KHelpMenu(self, "", False).aboutKDE) qaslf = QAction(QIcon.fromTheme("help-about"), "About Self", self) if KDE: qaslf.triggered.connect(KAboutApplicationDialog(aboutData, self).exec_) else: qaslf.triggered.connect( lambda: QMessageBox.about( self.mainwidget, __doc__, "".join( ( __doc__, linesep, "version ", __version__, ", (", __license__, "), by ", __author__, ", ( ", __email__, " )", linesep, ) ), ) ) qafnt = QAction(QIcon.fromTheme("tools-check-spelling"), "Set GUI Font", self) if KDE: font = QFont() qafnt.triggered.connect( lambda: self.setStyleSheet( "".join(("*{font-family:", str(font.toString()), "}")) if KFontDialog.getFont(font)[0] == QDialog.Accepted else "" ) ) else: qafnt.triggered.connect( lambda: self.setStyleSheet("".join(("*{font-family:", str(QFontDialog.getFont()[0].toString()), "}"))) ) qasrc = QAction(QIcon.fromTheme("applications-development"), "View Source Code", self) qasrc.triggered.connect(lambda: call("xdg-open {}".format(__file__), 1)) qakb = QAction(QIcon.fromTheme("input-keyboard"), "Keyboard Shortcuts", self) qakb.triggered.connect( lambda: QMessageBox.information(self.mainwidget, "Keyboard Shortcuts", " Ctrl+Q = Quit ") ) qapic = QAction(QIcon.fromTheme("camera-photo"), "Take a Screenshot", self) qapic.triggered.connect( lambda: QPixmap.grabWindow(QApplication.desktop().winId()).save( QFileDialog.getSaveFileName( self.mainwidget, " Save Screenshot As ...", path.expanduser("~"), ";;(*.png) PNG", "png" ) ) ) qatb = QAction(QIcon.fromTheme("go-top"), "Toggle ToolBar", self) qatb.triggered.connect(lambda: self.toolbar.hide() if self.toolbar.isVisible() is True else self.toolbar.show()) qati = QAction(QIcon.fromTheme("help-browser"), "Switch ToolBar Icon Size", self) qati.triggered.connect( lambda: self.toolbar.setIconSize(self.toolbar.iconSize() * 4) if self.toolbar.iconSize().width() * 4 == 24 else self.toolbar.setIconSize(self.toolbar.iconSize() / 4) ) qasb = QAction(QIcon.fromTheme("zoom-in"), "Toggle Tabs Bar", self) qasb.triggered.connect( lambda: self.mainwidget.tabBar().hide() if self.mainwidget.tabBar().isVisible() is True else self.mainwidget.tabBar().show() ) qadoc = QAction(QIcon.fromTheme("help-browser"), "On-line Docs", self) qadoc.triggered.connect(lambda: open_new_tab(__url__)) qapy = QAction(QIcon.fromTheme("help-about"), "About Python", self) qapy.triggered.connect(lambda: open_new_tab("http://python.org/about")) qali = QAction(QIcon.fromTheme("help-browser"), "Read Licence", self) qali.triggered.connect(lambda: open_new_tab(__full_licence__)) qacol = QAction(QIcon.fromTheme("preferences-system"), "Set GUI Colors", self) if KDE: color = QColor() qacol.triggered.connect( lambda: self.setStyleSheet("".join(("* { background-color: ", str(color.name()), "}"))) if KColorDialog.getColor(color, self) else "" ) else: qacol.triggered.connect( lambda: self.setStyleSheet( "".join((" * { background-color: ", str(QColorDialog.getColor().name()), " } ")) ) ) qatit = QAction(QIcon.fromTheme("preferences-system"), "Set the App Window Title", self) qatit.triggered.connect(self.seTitle) self.toolbar.addWidget(self.left_spacer) self.toolbar.addSeparator() for b in ( qaqq, qamin, qanor, qamax, qasrc, qakb, qacol, qatim, qatb, qafnt, qati, qasb, qatit, qapic, qadoc, qali, qaslf, qaqt, qakde, qapy, qabug, ): self.toolbar.addAction(b) self.addToolBar(Qt.TopToolBarArea, self.toolbar) self.toolbar.addSeparator() self.toolbar.addWidget(self.right_spacer) # define the menu menu = self.menuBar() # File menu items menu.addMenu("&File").addActions((qaqq,)) menu.addMenu("&Window").addActions((qamax, qanor, qamin)) # Settings menu menu.addMenu("&Settings").addActions((qasrc, qacol, qafnt, qatim, qatb, qati, qasb, qapic)) # Help menu items menu.addMenu("&Help").addActions((qadoc, qakb, qabug, qali, qaqt, qakde, qapy, qaslf)) # Tray Icon tray = QSystemTrayIcon(QIcon.fromTheme("face-devilish"), self) tray.setToolTip(__doc__) traymenu = QMenu() traymenu.addActions((qamax, qanor, qamin, qaqq)) tray.setContextMenu(traymenu) tray.show() def contextMenuRequested(point): " quick and dirty custom context menu " menu = QMenu() menu.addActions( ( qaqq, qamin, qanor, qamax, qasrc, qakb, qacol, qafnt, qati, qasb, qatb, qatim, qatit, qapic, qadoc, qali, qaslf, qaqt, qakde, qapy, qabug, ) ) menu.exec_(self.mapToGlobal(point)) self.mainwidget.customContextMenuRequested.connect(contextMenuRequested) def must_be_checked(widget_list): " widget tuple passed as argument should be checked as ON " for each_widget in widget_list: try: each_widget.setChecked(True) except: pass def must_have_tooltip(widget_list): " widget tuple passed as argument should have tooltips " for each_widget in widget_list: try: each_widget.setToolTip(each_widget.text()) except: each_widget.setToolTip(each_widget.currentText()) finally: each_widget.setCursor(QCursor(Qt.PointingHandCursor)) def must_autofillbackground(widget_list): " widget tuple passed as argument should have filled background " for each_widget in widget_list: try: each_widget.setAutoFillBackground(True) except: pass def must_glow(widget_list): " apply an glow effect to the widget " for glow, each_widget in enumerate(widget_list): try: if each_widget.graphicsEffect() is None: glow = QGraphicsDropShadowEffect(self) glow.setOffset(0) glow.setBlurRadius(99) glow.setColor(QColor(99, 255, 255)) each_widget.setGraphicsEffect(glow) # glow.setEnabled(False) try: each_widget.clicked.connect( lambda: each_widget.graphicsEffect().setEnabled(True) if each_widget.graphicsEffect().isEnabled() is False else each_widget.graphicsEffect().setEnabled(False) ) except: each_widget.sliderPressed.connect( lambda: each_widget.graphicsEffect().setEnabled(True) if each_widget.graphicsEffect().isEnabled() is False else each_widget.graphicsEffect().setEnabled(False) ) except: pass ####################################################################### self.group1 = QGroupBox() self.group1.setTitle(__doc__) self.frmt = QComboBox(self.group1) self.frmt.addItems(["blah ", "blah blah", "blah blah blah"]) self.file1 = QLineEdit() self.file1.setPlaceholderText("/full/path/to/one_file.py") self.file1.setCompleter(self.completer) self.borig = QPushButton(QIcon.fromTheme("folder-open"), "Open") vboxg1 = QVBoxLayout(self.group1) for each_widget in ( QLabel('<b style="color:white;">some comment'), self.file1, self.borig, QLabel('<b style="color:white;">Lorem Impsum'), self.frmt, ): vboxg1.addWidget(each_widget) self.group2 = QGroupBox() self.group2.setTitle(__doc__) self.nwfl = QCheckBox("Be Awesome") self.smll = QCheckBox("Solve the Squaring of the Circle") self.lrgf = QCheckBox("Im just a QCheckBox") self.case = QCheckBox("Use Quantum Processing") vboxg2 = QVBoxLayout(self.group2) for each_widget in (self.nwfl, self.smll, self.lrgf, self.case): vboxg2.addWidget(each_widget) group3 = QGroupBox() group3.setTitle(__doc__) self.plai = QCheckBox("May the Force be with You") self.nocr = QCheckBox("Im just a Place Holder") self.ridt = QCheckBox("Lorem Impsum") self.nocm = QCheckBox("Divide by Zero") vboxg3 = QVBoxLayout(group3) for each_widget in (self.plai, self.nocr, self.ridt, self.nocm): vboxg3.addWidget(each_widget) container = QWidget() hbox = QHBoxLayout(container) for each_widget in (self.group2, self.group1, group3): hbox.addWidget(each_widget) self.dock1.setWidget(container) # dock 2 self.dock2.setWidget(QPlainTextEdit()) # dock 3 self.dock3.setWidget(QCalendarWidget()) # configure some widget settings must_be_checked((self.nwfl, self.smll, self.lrgf, self.plai)) must_have_tooltip((self.plai, self.nocr, self.ridt, self.nocm, self.nwfl, self.smll, self.lrgf, self.case)) must_autofillbackground( (self.plai, self.nocr, self.ridt, self.nocm, self.nwfl, self.smll, self.lrgf, self.case) ) must_glow((self.plai, self.nocr, self.ridt, self.nocm, self.nwfl)) def run(self): " run forest run " print((" INFO: Working at {}".format(str(datetime.datetime.now())))) ########################################################################### def paintEvent(self, event): "Paint semi-transparent background, animated pattern, background text" # because we are on 2012 !, its time to showcase how Qt we are ! QWidget.paintEvent(self, event) # make a painter p = QPainter(self) p.setRenderHint(QPainter.TextAntialiasing) p.setRenderHint(QPainter.HighQualityAntialiasing) # fill a rectangle with transparent painting p.fillRect(event.rect(), Qt.transparent) # animated random dots background pattern for i in range(4096): x = randint(9, self.size().width() - 9) y = randint(9, self.size().height() - 9) p.setPen(QPen(QColor(randint(9, 255), randint(9, 255), 255), 1)) p.drawPoint(x, y) # set pen to use white color p.setPen(QPen(QColor(randint(9, 255), randint(9, 255), 255), 1)) # Rotate painter 45 Degree p.rotate(30) # Set painter Font for text p.setFont(QFont("Ubuntu", 200)) # draw the background text, with antialiasing if KDE: p.drawText(99, 99, "PyKDE") else: p.drawText(99, 99, "PyQt") # Rotate -45 the QPen back ! p.rotate(-30) # set the pen to no pen p.setPen(Qt.NoPen) # Background Color p.setBrush(QColor(0, 0, 0)) # Background Opacity p.setOpacity(0.75) # Background Rounded Borders p.drawRoundedRect(self.rect(), 50, 50) # finalize the painter p.end() def seTitle(self): " set the title of the main window " dialog = QDialog(self) textEditInput = QLineEdit(" Type Title Here ") ok = QPushButton(" O K ") ok.clicked.connect(lambda: self.setWindowTitle(textEditInput.text())) ly = QVBoxLayout() [ly.addWidget(wdgt) for wdgt in (QLabel("Title:"), textEditInput, ok)] dialog.setLayout(ly) dialog.exec_() def timedate(self): " get the time and date " dialog = QDialog(self) clock = QLCDNumber() clock.setNumDigits(24) timer = QTimer() timer.timeout.connect(lambda: clock.display(datetime.now().strftime("%d-%m-%Y %H:%M:%S %p"))) timer.start(1000) clock.setToolTip(datetime.now().strftime("%c %x")) ok = QPushButton(" O K ") ok.clicked.connect(dialog.close) ly = QVBoxLayout() [ly.addWidget(wdgt) for wdgt in (QCalendarWidget(), clock, ok)] dialog.setLayout(ly) dialog.exec_() def closeEvent(self, event): " Ask to Quit " if ( QMessageBox.question(self, " Close ", " Quit ? ", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) == QMessageBox.Yes ): event.accept() else: event.ignore() def center(self): " Center and resize the window " self.showNormal() self.resize( QDesktopWidget().screenGeometry().width() // 1.25, QDesktopWidget().screenGeometry().height() // 1.25 ) qr = self.frameGeometry() qr.moveCenter(QDesktopWidget().availableGeometry().center()) self.move(qr.topLeft()) def nepomuk_set(self, file_tag=None, __tag="", _label="", _description=""): " Quick and Easy Nepomuk Taggify for Files " print( ( """ INFO: Semantic Desktop Experience is Tagging Files : {}, {}, {}, {})""".format( file_tag, __tag, _label, _description ) ) ) if Nepomuk.ResourceManager.instance().init() is 0: fle = Nepomuk.Resource(KUrl(QFileInfo(file_tag).absoluteFilePath())) _tag = Nepomuk.Tag(__tag) _tag.setLabel(_label) fle.addTag(_tag) fle.setDescription(_description) print(([str(a.label()) for a in fle.tags()], fle.description())) return ([str(a.label()) for a in fle.tags()], fle.description()) else: print(" ERROR: FAIL: Nepomuk is not running ! ") return def nepomuk_get(self, query_to_search): " Quick and Easy Nepomuk Query for Files " print( ( """ INFO: Semantic Desktop Experience is Quering Files : {} """.format( query_to_search ) ) ) results = [] nepo = Nepomuk.Query.QueryServiceClient() nepo.desktopQuery("hasTag:{}".format(query_to_search)) def _query(data): """ ('filename.ext', 'file description', ['list', 'of', 'tags']) """ results.append( ( [str(a.resource().genericLabel()) for a in data][0], [str(a.resource().description()) for a in data][0], [str(a.label()) for a in iter([a.resource().tags() for a in data][0])], ) ) nepo.newEntries.connect(_query) def _end(): """ [ ('filename.ext', 'file description', ['list', 'of', 'tags']), ('filename.ext', 'file description', ['list', 'of', 'tags']), ('filename.ext', 'file description', ['list', 'of', 'tags']) ] """ nepo.newEntries.disconnect print(results) return results nepo.finishedListing.connect(_end) def kio_get(self, url_string): " multi-threaded, multi-protocol, resumable, error-checked download " downloader_thread = KIO.storedGet(KUrl(str(url_string).strip())) def kio_job_data_or_error(job): " retrieve job data or job error " print((job.data() if not job.error() else job.error())) return job.data() if not job.error() else job.error() downloader_thread.result.connect(kio_job_data_or_error)
class SearchForm(QWidget, Ui_SearchForm): """The Luma search form widget. This class provides easy getters for the various input and selection options provided by the widget. """ availableScopes = ['SCOPE_BASE', 'SCOPE_ONELEVEL', 'SCOPE_SUBTREE'] def __init__(self, parent=None): super(SearchForm, self).__init__(parent) self.setupUi(self) self.serverBox.addItem('') self.scopeBox.addItems(self.availableScopes) self.errorIcon.setVisible(False) self.errorLabel.setVisible(False) self.__connectSlots() def __connectSlots(self): """Connect signals and slots. """ self.filterBoxEdit.currentIndexChanged['QString'].connect( self.onSearchCriteriaChanged) self.filterBoxEdit.editTextChanged['QString'].connect( self.onSearchCriteriaChanged) self.filterBoxEdit.lineEdit().returnPressed.connect( self.searchButton.animateClick) def __escape(self, text): """FIXME: Dummy escaping """ if not text.startswith(u'('): text = u'({0}'.format(text) if not text.endswith(u')'): text = u'{0})'.format(text) return text def onSearchCriteriaChanged(self, text): """Slot for the search edit widget Enable or disable the search button. If `text` is empty the search button is disabled. If not it is enabled. """ self.searchButton.setDisabled(text == '') def populateBaseDNBox(self, baseDNList=[]): """Populate the base DN combo box with a available base DNs. Parameters: - `baseDNList`: a list containing base DN. """ self.baseDNBox.clear() # This should fix the no-network bug if not baseDNList is None: for x in baseDNList: self.baseDNBox.addItem(x) def populateFilterBookmarks(self, filterBookmarks): """Populates the search edit combobox with saved search filters. """ tmp = [self.filterBoxEdit.currentText()] self.filterBoxEdit.clear() tmp.extend(filterBookmarks) self.filterBoxEdit.addItems(tmp) def initAutoComplete(self, attributes): """Initialize the filter input auto completion. Try to fetches the list of available `attributes` from the server selected in the server combo box. This list will be used to give the user auto complete options while building search filters. """ # If we get an attribute list off the server we set up the # attribute auto completer. if len(attributes) > 0: self.completer = QCompleter(attributes, self) self.completer.setCaseSensitivity(Qt.CaseSensitive) self.completer.setCompletionPrefix(',') self.filterBoxEdit.setCompleter(self.completer) def setAndUseFilter(self, filter): """Insert, set as current, and search with the filter. """ self.filterBoxEdit.insertItem(0, filter) self.filterBoxEdit.setCurrentIndex(0) self.searchButton.clicked.emit(True) def onSearchError(self, isError, msg=''): """Displays a error message if the search operation fails. Parameters: - `isError`: a boolean value indicating if it is an error or not. That is, we also use this method to hide any previous error messages on new a search. - `e`: the exception object returned from the search operation, cointaining information about the error. """ self.errorLabel.setText(msg) self.errorIcon.setVisible(isError) self.errorLabel.setVisible(isError) @property def server(self): return encodeUTF8(unicode(self.serverBox.currentText())) @property def baseDN(self): # Python-LDAP takes strings in UTF8 return encodeUTF8(unicode(self.baseDNBox.currentText())) @property def scope(self): return self.scopeBox.currentIndex() @scope.setter def scope(self, index): self.scopeBox.setCurrentIndex(index) @property def sizeLimit(self): return self.sizeLimitSpinBox.value() @sizeLimit.setter def sizeLimit(self, limit): self.sizeLimitSpinBox.setValue(limit) @property def filter(self): # Python-LDAP takes strings in UTF8 filter = unicode(self.filterBoxEdit.currentText()) escaped = self.__escape(filter) return filter.encode('utf-8')
class Main(plugin.Plugin): " Main Class " def initialize(self, *args, **kwargs): " Init Main Class " super(Main, self).initialize(*args, **kwargs) self.process = QProcess() self.process.readyReadStandardOutput.connect(self.readOutput) self.process.readyReadStandardError.connect(self.readErrors) self.process.finished.connect(self._process_finished) # self.process.error.connect(self._process_error) self.sourceDirectory, self.outputDirectory = None, None self.group2 = QGroupBox() self.group2.setTitle(' Paths ') self.inf = QLineEdit(path.expanduser("~")) self.inf.setPlaceholderText(' /full/path/to/directory ') self.out, self.fle = QLineEdit(path.expanduser("~")), QLineEdit() self.out.setPlaceholderText(' /full/path/to/directory ') self.fle.setPlaceholderText(' /full/path/to/single/file ') self.completer, self.dirs = QCompleter(self), QDirModel(self) self.dirs.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot) self.completer.setModel(self.dirs) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setCompletionMode(QCompleter.PopupCompletion) self.inf.setCompleter(self.completer) self.out.setCompleter(self.completer) self.fle.setCompleter(self.completer) self.open1 = QPushButton(QIcon.fromTheme("folder-open"), 'Open') self.open1.setCursor(QCursor(Qt.PointingHandCursor)) self.open1.clicked.connect(lambda: self.inf.setText(str( QFileDialog.getExistingDirectory(self.dock, "Open Source Directory", path.expanduser("~"))))) self.open2 = QPushButton(QIcon.fromTheme("folder-open"), 'Open') self.open2.setCursor(QCursor(Qt.PointingHandCursor)) self.open2.clicked.connect(lambda: self.out.setText(str( QFileDialog.getExistingDirectory(self.dock, "Open Target Directory", path.expanduser("~"))))) self.open3 = QPushButton(QIcon.fromTheme("folder-open"), 'Open') self.open3.setCursor(QCursor(Qt.PointingHandCursor)) self.open3.clicked.connect(lambda: self.fle.setText(str( QFileDialog.getOpenFileName(self.dock, "Open a Target File...", path.expanduser("~"), ';;'.join(['{}(*.{})'.format(e.upper(), e) for e in ['py', 'pyw', '*']]))))) vboxg2 = QVBoxLayout(self.group2) for each_widget in ( QLabel('Source Directory Project:'), self.inf, self.open1, QLabel(' Target Directory Outputs: '), self.out, self.open2, QLabel(' Source Single File (Optional):'), self.fle, self.open3, ): vboxg2.addWidget(each_widget) self.group1 = QGroupBox() self.group1.setTitle(' Options ') self.chckbx1 = QCheckBox(' Inject Twitter Bootstrap CSS3 ') self.chckbx1.toggled.connect(self.toggle_styles_group) self.chckbx2 = QCheckBox(' Warn all missing references ') self.chckbx3 = QCheckBox(' Open Docs when done building ') self.chckbx4 = QCheckBox('Save Bash script to reproduce Sphinx Builds') vboxg1 = QVBoxLayout(self.group1) for each_widget in (self.chckbx1, self.chckbx2, self.chckbx3, self.chckbx4): vboxg1.addWidget(each_widget) each_widget.setChecked(True) self.group3 = QGroupBox() self.group3.setTitle(' Styles ') self.group3.setGraphicsEffect(QGraphicsBlurEffect(self)) self.group3.graphicsEffect().setEnabled(False) self.basecss, self.fontcss = QComboBox(), QComboBox() self.basecss.addItems(['slate', 'united', 'spacelab', 'superhero', 'simplex', 'journal', 'flatly', 'cyborg', 'cosmo', 'cerulean']) self.fontcss.addItems(['Ubuntu Light', 'Oxygen', 'Roboto', 'Droid Sans', 'Open Sans', 'Pacifico', 'Rancho', 'Arvo', 'Fresca', 'Graduate']) self.backcss = QComboBox() self.backcss.addItems(['shattered', 'retina_wood', 'ricepaper', 'brickwall', 'sneaker_mesh_fabric', 'diagonales_decalees', 'noisy_grid', 'pw_pattern', 'escheresque', 'diamond_upholstery']) vboxg3 = QVBoxLayout(self.group3) for each_widget in (QLabel('<b>Twitter Bootstrap Theme'), self.basecss, QLabel('<b>Fonts Family'), self.fontcss, QLabel('<b>Background Seamless Tiled Pattern'), self.backcss): vboxg3.addWidget(each_widget) self.output = QTextEdit(''' My brain is something more than merely mortal; As time will show. - Ada Lovelace ''') self.output.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.button = QPushButton('Document My Code') self.button.setCursor(QCursor(Qt.PointingHandCursor)) self.button.setMinimumSize(75, 50) self.button.clicked.connect(self.build) glow = QGraphicsDropShadowEffect(self) glow.setOffset(0) glow.setBlurRadius(99) glow.setColor(QColor(99, 255, 255)) self.button.setGraphicsEffect(glow) class TransientWidget(QWidget): ' persistant widget thingy ' def __init__(self, widget_list): ' init sub class ' super(TransientWidget, self).__init__() vbox = QVBoxLayout(self) for each_widget in widget_list: vbox.addWidget(each_widget) tw = TransientWidget((self.group2, self.group1, self.group3, QLabel(linesep + ' Logs: '), self.output, self.button)) self.scrollable, self.dock = QScrollArea(), QDockWidget() self.scrollable.setWidgetResizable(True) self.scrollable.setWidget(tw) self.dock.setWindowTitle(__doc__) self.dock.setStyleSheet('QDockWidget::title{text-align: center;}') self.dock.setWidget(self.scrollable) ExplorerContainer().addTab(self.dock, "Sphinx") QPushButton(QIcon.fromTheme("help-about"), 'About', self.dock ).clicked.connect(lambda: QMessageBox.information(self.dock, __doc__, HELPMSG)) def readOutput(self): """Read and append sphinx-build output to the logBrowser""" self.output.append(str(self.process.readAllStandardOutput())) def readErrors(self): """Read and append sphinx-build errors to the logBrowser""" self.output.append(self.formatErrorMsg(str( self.process.readAllStandardError()))) def formatErrorMsg(self, msg): """Format error messages in red color""" return self.formatMsg(msg, 'red') def formatInfoMsg(self, msg): """Format informative messages in blue color""" return self.formatMsg(msg, 'green') def formatMsg(self, msg, color): """Format message with the given color""" return '<font color="{}">{}</font>'.format(color, msg) def build(self): """Main function calling sphinx-build to generate the project""" self.output.setText('') self.output.append(self.formatInfoMsg( 'INFO: OK: Starting at {}'.format(datetime.now()))) self.button.setDisabled(True) self.sourceDirectory = str(self.inf.text()).strip() self.outputDirectory = str(self.out.text()).strip() if not len(self.sourceDirectory): self.output.append(' ERROR: FAIL: Source directory cannot be empty') else: self.output.append(self.formatInfoMsg( 'INFO: OK: Source Directory is {}'.format(self.sourceDirectory))) if not len(self.outputDirectory): self.output.append(' ERROR: FAIL: Output directory cannot be empty') else: self.output.append(self.formatInfoMsg( 'INFO: OK: Output Directory is {}'.format(self.outputDirectory))) if not(len(self.sourceDirectory) or len(self.outputDirectory)): self.button.setDisabled(False) return self.output.append(self.formatInfoMsg('INFO:OK: Building. Please wait')) args = ['-n' if self.chckbx2.isChecked() is True else '', '-b', 'html', self.sourceDirectory, self.outputDirectory] if len(self.fle.text()): args.append(str(self.fle.text()).strip().replace('file:///', '/')) self.output.append(self.formatInfoMsg( 'INFO: OK: Source Single File is {}'.format(self.fle.text()))) self.output.append(self.formatInfoMsg('INFO:OK: Running sphinx-build!')) self.process.start('sphinx-build', args) if not self.process.waitForStarted(): self.output.append(self.formatErrorMsg('ERROR: FAIL: Build Failed')) self.output.append(self.formatErrorMsg( 'ERROR: FAIL: Failed with Arguments: {} '.format(args))) self.button.setEnabled(True) return # write a .sh bash script file on target if self.chckbx4.isChecked() is True: sh_file = 'build_sphinx_documentation.sh' with open(path.join(self.sourceDirectory, sh_file), 'w') as _sh: self.output.append(self.formatInfoMsg('''INFO: OK: Writing Bash: {}'''.format(path.join(self.sourceDirectory, sh_file)))) _sh.write('#!/usr/bin/env bash {}'.format(linesep) + 'sphinx-build {}'.format(' '.join(args))) _sh.close() self.output.append(self.formatInfoMsg('INFO: OK: Bash chmod: 775')) try: chmod(path.join(self.sourceDirectory, sh_file), 0775) # Py2 except: chmod(path.join(self.sourceDirectory, sh_file), 0o775) # Py3 self.button.setEnabled(True) def _process_finished(self): """sphinx-build finished sucessfully""" self.output.append(self.formatInfoMsg( 'INFO: OK: Finished at {}'.format(datetime.now()))) if self.chckbx1.isChecked() is True: with open(path.join(self.outputDirectory, '_static', 'default.css'), 'a') as f: css = CSS3.replace('CSSWEBFONT', str(self.fontcss.currentText()) ).replace('CSSBACKGR', str(self.backcss.currentText()) ).replace('CSSCUSTOM', str(self.basecss.currentText())) f.write(css) f.close() if self.chckbx3.isChecked() is True: call('xdg-open ' + path.join(self.outputDirectory, 'index.html'), shell=True) def toggle_styles_group(self): ' toggle on or off the styles checkboxes ' try: if self.chckbx1.isChecked() is True: self.group3.graphicsEffect().setEnabled(False) self.group3.setEnabled(True) else: self.group3.graphicsEffect().setEnabled(True) self.group3.setEnabled(False) except: pass
class osmSearchDialog(QDockWidget , Ui_osmSearch ): def __init__(self,iface): self.iface = iface QDockWidget.__init__(self) self.setupUi(self) self.iface.addDockWidget(Qt.BottomDockWidgetArea,self) self.canvas = self.iface.mapCanvas() self.rb = QgsRubberBand(self.canvas, QGis.Point) self.rb.setColor(QColor( 255, 0, 0, 150 )) self.searchCacheLimit = 1000 self.wgs84 = QgsCoordinateReferenceSystem() self.wgs84.createFromSrid(4326) self.proj = self.canvas.mapRenderer().destinationCrs() self.transform = QgsCoordinateTransform(self.wgs84, self.proj) self.bSearch.clicked.connect(self.startSearch) self.eOutput.currentItemChanged.connect(self.itemChanged) self.eOutput.clickedOutsideOfItems.connect(self.itemChanged) self.eText.cleared.connect(self.clearEdit) self.canvas.mapRenderer().destinationSrsChanged.connect(self.crsChanged) self.iface.newProjectCreated.connect(self.clearEdit) self.iface.projectRead.connect(self.clearEdit) self.cbCenter.stateChanged.connect(self.autocenter) db = cacheDB() self.autocompleteList = db.getAutocompleteList() db.closeConnection() self.completer = QCompleter(self.autocompleteList) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.eText.setCompleter(self.completer) def startSearch(self): text = self.eText.text().encode('utf-8') if text == "": self.clearEdit() #url = 'http://open.mapquestapi.com/nominatim/v1/search.php' url = 'http://nominatim.openstreetmap.org/search' params = urllib.urlencode({'q': text,'format': 'json','polygon_text':'1'}) response = json.load(urllib2.urlopen(url+'?'+params)) self.loadData(response) def loadData(self, data): self.rb.reset(QGis.Point) self.eOutput.clear() items = [] for d in data: try: geometry = d['geotext'] except KeyError: geometry = 'POINT(%s %s)' % (d['lon'], d['lat']) item = QTreeWidgetItem([d['display_name'], d['type']]) item.setData(0, Qt.UserRole, geometry) if geometry.lower().startswith('point'): item.setIcon(0, QgsApplication.getThemeIcon('/mIconPointLayer.svg')) elif geometry.lower().startswith('linestring'): item.setIcon(0, QgsApplication.getThemeIcon('/mIconLineLayer.svg')) elif geometry.lower().startswith('polygon'): item.setIcon(0, QgsApplication.getThemeIcon('/mIconPolygonLayer.svg')) items.append(item) if items: self.eOutput.insertTopLevelItems(0, items) self.addSearchTerm(unicode(self.eText.text().lower())) else: self.iface.messageBar().pushMessage('Nothing was found!', QgsMessageBar.CRITICAL, 2) def itemChanged(self, current=None, previous=None): if current: wkt = str(current.data(0,Qt.UserRole)) geom = QgsGeometry.fromWkt(wkt) if self.proj.srsid() != 4326: try: geom.transform(self.transform) except: self.iface.messageBar().pushMessage('CRS transformation error!', QgsMessageBar.CRITICAL, 2) self.rb.reset(QGis.Point) return self.rb.setToGeometry(geom, None) if self.cbCenter.isChecked(): self.moveCanvas(geom.centroid().asPoint(), self.canvas.extent()) else: self.rb.reset(QGis.Point) self.eOutput.setCurrentItem(None) def crsChanged(self): self.proj = self.canvas.mapRenderer().destinationCrs() self.transform = QgsCoordinateTransform(self.wgs84, self.proj) def clearEdit(self): self.eOutput.clear() self.eText.clear() if hasattr(self, 'rb'): self.rb.reset(QGis.Point) def setCompleter(self): self.completer.model().setStringList(self.autocompleteList) def addSearchTerm(self, text): if not text in self.autocompleteList: self.autocompleteList.append(text) self.setCompleter() while len(self.autocompleteList) > self.searchCacheLimit: self.autocompleteList.pop(0) def autocenter(self, state): if state and self.rb.size(): self.moveCanvas(self.rb.asGeometry().centroid().asPoint(), self.canvas.extent()) def moveCanvas(self, newCenter, oldExtent): newExtent = QgsRectangle(oldExtent) newExtent.scale(1, newCenter) self.canvas.setExtent(newExtent) self.canvas.refresh()
class DiffGUI(object): ' diff gui class ' def __init__(self): ' make a diff method with GUI ' self.dialog = QDialog() self.diff_path = None # directory auto completer self.completer = QCompleter(self.dialog) self.dirs = QDirModel(self.dialog) self.dirs.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot) self.completer.setModel(self.dirs) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setCompletionMode(QCompleter.PopupCompletion) self.group1 = QGroupBox() self.group1.setTitle('Diff') self.frmt = QComboBox(self.group1) self.frmt.addItems(['Unified', 'Normal', 'Context']) self.file1 = QLineEdit() self.file1.setPlaceholderText('/full/path/to/one_file.py') self.file1.setCompleter(self.completer) self.file2 = QLineEdit() self.file2.setPlaceholderText('/full/path/to/another_file.py') self.file2.setCompleter(self.completer) self.fout = QLineEdit() self.fout.setText(''.join((path.join(gettempdir(), datetime.now().strftime('%d-%b-%Y_%H:%M:%S.diff'))))) self.fout.setPlaceholderText('/full/path/to/output_file.diff') self.fout.setCompleter(self.completer) self.regex = QLineEdit() self.regex.setPlaceholderText('DONT use unless you know what are doing') self.regex.setToolTip('Do NOT use unless you know what you are doing !') self.borig = QPushButton(QIcon.fromTheme("folder-open"), 'Open') self.borig.clicked.connect(lambda: self.file1.setText(str( QFileDialog.getOpenFileName(self.dialog, 'Open file to compare', path.expanduser("~"), ';;(*.*)')))) self.bmodi = QPushButton(QIcon.fromTheme("folder-open"), 'Open') self.bmodi.clicked.connect(lambda: self.file2.setText(str( QFileDialog.getOpenFileName(self.dialog, 'Open file to compare', path.expanduser("~"), ';;(*.*)')))) self.bout = QPushButton(QIcon.fromTheme("folder-open"), 'Open') self.bout.clicked.connect(lambda: self.fout.setText(str( QFileDialog.getSaveFileName(self.dialog, 'Save a Diff file', path.expanduser("~"), ';;(*.diff)')))) vboxg1 = QVBoxLayout(self.group1) for each_widget in (QLabel('Original file full path'), self.file1, self.borig, QLabel('Modified file full path'), self.file2, self.bmodi, QLabel('Output file full Path'), self.fout, self.bout, QLabel('Diff Output Format'), self.frmt, QLabel('Diff REGEX to Ignore (ADVANCED)'), self.regex): vboxg1.addWidget(each_widget) self.group2 = QGroupBox() self.group2.setTitle('Options') self.nwfl = QCheckBox('Treat new files as Empty') self.smll = QCheckBox('Look for smaller changes') self.lrgf = QCheckBox('Optimize for large files') self.case = QCheckBox('Ignore case changes on content') self.cnvt = QCheckBox('Convert Tabs to Spaces') self.blnk = QCheckBox('Ignore added or removed Blank lines') self.spac = QCheckBox('Ignore changes in amount of Spaces') self.whit = QCheckBox('Ignore ALL white Spaces') self.tabz = QCheckBox('Ignore changes by Tab expansions') self.sprs = QCheckBox('Remove Space or Tab before empty lines') self.filn = QCheckBox('Ignore case when comparing file names') self.tbs = QComboBox(self.group2) self.tbs.addItems(['4', '6', '8', '10', '2']) self.nice = QComboBox(self.group2) self.nice.addItems(['20', '15', '10', '5', '0']) vboxg2 = QVBoxLayout(self.group2) for each_widget in (self.nwfl, self.smll, self.lrgf, self.case, self.cnvt, self.blnk, self.spac, self.whit, self.tabz, self.sprs, self.filn, QLabel('Diff Tabs-to-Spaces Size'), self.tbs, QLabel('Diff Backend CPU Priority'), self.nice): vboxg2.addWidget(each_widget) try: each_widget.setToolTip(each_widget.text()) except: each_widget.setToolTip(each_widget.currentText()) each_widget.setCursor(QCursor(Qt.PointingHandCursor)) group3 = QGroupBox() group3.setTitle('Even More Options') self.plai = QCheckBox('Force treat all files as plain text') self.nocr = QCheckBox('Force strip trailing carriage return') self.ridt = QCheckBox('Report when two files are identical') self.nocm = QCheckBox('Do not output common lines') self.rdif = QCheckBox('Report only when files differ') self.clip = QCheckBox('Copy Diff to Clipboard when done') self.noti = QCheckBox('Use system Notification when done') self.pret = QCheckBox('Align all Tabs by prepending a Tab') self.lolz = QCheckBox('Output Diff in two equal columns') self.odif = QCheckBox('Open Diff with Ninja-IDE when done') self.plac = QCheckBox('Make an Awesome Diff view when done') self.wdth = QComboBox(group3) self.wdth.addItems(['80', '100', '120', '130', '250', '500', '9999999']) self.bcknd = QComboBox(group3) self.bcknd.addItems(['diff', 'diff.py']) self.bcknd.setDisabled(True) # TODO this feature needs work vboxg3 = QVBoxLayout(group3) for each_widget in (self.plai, self.nocr, self.ridt, self.nocm, self.rdif, self.pret, self.clip, self.noti, self.lolz, self.odif, self.plac, QLabel('Diff Maximum Total Width'), self.wdth, QLabel('Diff Backend (EXPERIMENTAL)'), self.bcknd): vboxg3.addWidget(each_widget) try: each_widget.setToolTip(each_widget.text()) except: each_widget.setToolTip(each_widget.currentText()) each_widget.setCursor(QCursor(Qt.PointingHandCursor)) for widget_should_be_checked in (self.nwfl, self.smll, self.lrgf, self.clip, self.cnvt, self.plai, self.noti): widget_should_be_checked.setChecked(True) container = QWidget() hbox = QHBoxLayout(container) for each_widget in (self.group2, self.group1, group3): hbox.addWidget(each_widget) buttons = QDialogButtonBox() buttons.resize(self.dialog.size().width(), buttons.size().height() * 2) buttons.setOrientation(Qt.Horizontal) buttons.setStandardButtons( QDialogButtonBox.Ok | QDialogButtonBox.Cancel | QDialogButtonBox.Close | QDialogButtonBox.Help) buttons.setCenterButtons(False) buttons.helpRequested.connect(lambda: QMessageBox.about( self.dialog, __doc__, ''.join((__doc__, ' GUI and Visualizer Plugin,', linesep, 'version ', __version__, ', (', __license__, '), by ', linesep, __author__, ', ( ', __email__, ' ).', linesep)))) buttons.rejected.connect(self.dialog.close) buttons.accepted.connect(self.make_diff) info = QLabel(''.join(('<b> Current Backend Diff Engine: </b>', getoutput('diff --version').split(linesep)[0]))) vbox = QVBoxLayout(self.dialog) for each_widget in ( QLabel('<center><h2> Ninja IDE Diff and Patch </h2></center>'), container, info, buttons): vbox.addWidget(each_widget) self.dialog.resize(1024, self.dialog.size().height()) self.dialog.exec_() def make_diff(self): ' make the diff ' diff_command = ''.join(( 'nice --adjustment=', str(self.nice.currentText()).strip(), ' ', str(self.bcknd.currentText()).strip(), ' --', str(self.frmt.currentText()).strip().lower(), ' --new-file ' if self.nwfl.isChecked() is True else '', ' --minimal ' if self.smll.isChecked() is True else '', ' --speed-large-files ' if self.lrgf.isChecked() is True else '', ' --ignore-self.case ' if self.case.isChecked() is True else '', ' --expand-tabs ' if self.cnvt.isChecked() is True else '', ' --ignore-blank-lines ' if self.blnk.isChecked() is True else '', ' --ignore-space-change ' if self.spac.isChecked() is True else '', ' --ignore-all-space ' if self.whit.isChecked() is True else '', ' --ignore-tab-expansion ' if self.tabz.isChecked() is True else '', ' --suppress-blank-empty ' if self.sprs.isChecked() is True else '', ' --ignore-file-name-case ' if self.filn.isChecked() is True else '', ' --text ' if self.plai.isChecked() is True else '', ' --strip-trailing-cr ' if self.nocr.isChecked() is True else '', ' --suppress-common-lines ' if self.nocm.isChecked() is True else '', ' --initial-tab ' if self.pret.isChecked() is True else '', ' --side-by-side ' if self.lolz.isChecked() is True else '', ' --tabsize=', str(self.tbs.currentText()).strip(), ' --width=', str(self.wdth.currentText()).strip(), str(' --ignore-matching-lines=' + str(self.regex.text()).strip()) if str(self.regex.text()).strip() is not '' else '', ' ', path.abspath(str(self.file1.text())) if str(self.file1.text()).strip() is not '' else __file__, ' ', path.abspath(str(self.file2.text())) if str(self.file2.text()).strip() is not '' else __file__ )) print(diff_command) diff_output = getoutput(diff_command) try: print(' INFO: OK, Saving new Diff to disk...') output_file = file(path.abspath(str(self.fout.text())), 'w') output_file.write(diff_output) output_file.close() except: print(' ERROR: FAIL, Can not save Diff to disk!') if self.clip.isChecked() is True: print(' INFO: OK, Diff Copied to Clipboard...') QApplication.clipboard().setText(diff_output) if self.noti.isChecked() is True: call('notify-send [Ninja-IDE] ¡Diff_is_Ready!', shell=True) if self.odif.isChecked() is True: print(' INFO: OK, Opening Diff with Ninja-IDE') call('ninja-ide ' + path.abspath(str(self.fout.text())), shell=True) self.diff_path = path.abspath(str(self.fout.text())) return self.diff_path
class TalkEditorApp(FreeseerApp): '''Freeseer talk database editor main gui class''' def __init__(self, config, db): FreeseerApp.__init__(self) self.config = config self.db = db icon = QIcon() icon.addPixmap(QPixmap(':/freeseer/logo.png'), QIcon.Normal, QIcon.Off) self.setWindowIcon(icon) self.resize(960, 600) # # Setup Layout # self.mainWidget = QWidget() self.mainLayout = QVBoxLayout() self.mainWidget.setLayout(self.mainLayout) self.setCentralWidget(self.mainWidget) self.mainLayout.setAlignment(QtCore.Qt.AlignTop) # Add the Title Row (Use BOLD / Big Font) #self.titleLayout = QHBoxLayout() #self.backButton = QPushButton('Back to Recorder') #if backButton: # Only show the back button if requested by caller # self.titleLayout.addWidget(self.backButton) #self.titleLayout.addStretch() # Add custom widgets self.commandButtons = CommandButtons() self.tableView = QTableView() self.tableView.setSortingEnabled(True) self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows) self.talkDetailsWidget = TalkDetailsWidget() self.importTalksWidget = ImportTalksWidget() self.mainLayout.addWidget(self.importTalksWidget) #self.mainLayout.addLayout(self.titleLayout) self.mainLayout.addWidget(self.commandButtons) self.mainLayout.addWidget(self.tableView) self.mainLayout.addWidget(self.talkDetailsWidget) self.mainLayout.addWidget(self.importTalksWidget) # --- End Layout # Initialize geometry, to be used for restoring window positioning. self.geometry = None # # Setup Menubar # self.actionExportCsv = QAction(self) self.actionExportCsv.setObjectName('actionExportCsv') self.actionRemoveAll = QAction(self) self.actionRemoveAll.setObjectName('actionRemoveAll') # Actions self.menuFile.insertAction(self.actionExit, self.actionExportCsv) self.menuFile.insertAction(self.actionExit, self.actionRemoveAll) # --- End Menubar # # TableView Connections # self.connect(self.tableView, SIGNAL('activated(const QModelIndex)'), self.talk_selected) self.connect(self.tableView, SIGNAL('selected(const QModelIndex)'), self.talk_selected) self.connect(self.tableView, SIGNAL('clicked(const QModelIndex)'), self.talk_selected) # Import Widget self.connect(self.importTalksWidget.csvRadioButton, SIGNAL('toggled(bool)'), self.toggle_import) self.connect(self.importTalksWidget.importButton, SIGNAL('clicked()'), self.import_talks) self.connect(self.importTalksWidget.cancelButton, SIGNAL('clicked()'), self.hide_import_talks_widget) self.importTalksWidget.setHidden(True) self.connect(self.importTalksWidget.csvFileSelectButton, QtCore.SIGNAL('clicked()'), self.csv_file_select) self.connect(self.importTalksWidget.csvLineEdit, QtCore.SIGNAL('returnPressed()'), self.importTalksWidget.importButton.click) self.connect(self.importTalksWidget.rssLineEdit, QtCore.SIGNAL('returnPressed()'), self.importTalksWidget.importButton.click) self.connect(self.actionExportCsv, QtCore.SIGNAL('triggered()'), self.export_talks_to_csv) self.connect(self.actionRemoveAll, QtCore.SIGNAL('triggered()'), self.confirm_reset) # Command Buttons self.connect(self.commandButtons.removeButton, SIGNAL('clicked()'), self.remove_talk) self.connect(self.commandButtons.removeAllButton, SIGNAL('clicked()'), self.confirm_reset) self.connect(self.commandButtons.importButton, SIGNAL('clicked()'), self.show_import_talks_widget) self.connect(self.commandButtons.exportButton, SIGNAL('clicked()'), self.export_talks_to_csv) self.connect(self.commandButtons.searchButton, SIGNAL('clicked()'), self.search_talks) self.connect(self.commandButtons.searchLineEdit, SIGNAL('textEdited(QString)'), self.search_talks) self.connect(self.commandButtons.searchLineEdit, SIGNAL('returnPressed()'), self.search_talks) # Talk Details Buttons self.connect(self.talkDetailsWidget.addButton, SIGNAL('clicked()'), self.confirm_add) self.connect(self.talkDetailsWidget.saveButton, SIGNAL('clicked()'), self.add_talk) # Load default language actions = self.menuLanguage.actions() for action in actions: if action.data().toString() == self.config.default_language: action.setChecked(True) self.translate(action) break # Load Talk Database self.load_presentations_model() # Setup Autocompletion self.update_autocomple_fields() # Select first item #self.tableView.setCurrentIndex(self.proxy.index(0,0)) #self.talk_selected(self.proxy.index(0,0)) # # Translation # def retranslate(self): self.setWindowTitle(self.app.translate("TalkEditorApp", "Freeseer Talk Editor")) # # Reusable Strings # self.confirmDBClearTitleString = self.app.translate("TalkEditorApp", "Remove All Talks from Database") self.confirmDBClearQuestionString = self.app.translate("TalkEditorApp", "Are you sure you want to clear the DB?") self.confirmTalkDetailsClearTitleString = self.app.translate("TalkEditorApp", "Unsaved Data") self.confirmTalkDetailsClearQuestionString = self.app.translate("TalkEditorApp", "Unsaved talk details will be lost. Continue?") # --- End Reusable Strings # # Menubar # self.actionExportCsv.setText(self.app.translate("TalkEditorApp", "&Export to CSV")) self.actionRemoveAll.setText(self.app.translate("TalkEditorApp", "&Remove All Talks")) # --- End Menubar # # TalkDetailsWidget # self.talkDetailsWidget.titleLabel.setText(self.app.translate("TalkEditorApp", "Title")) self.talkDetailsWidget.presenterLabel.setText(self.app.translate("TalkEditorApp", "Presenter")) self.talkDetailsWidget.categoryLabel.setText(self.app.translate("TalkEditorApp", "Category")) self.talkDetailsWidget.eventLabel.setText(self.app.translate("TalkEditorApp", "Event")) self.talkDetailsWidget.roomLabel.setText(self.app.translate("TalkEditorApp", "Room")) self.talkDetailsWidget.dateLabel.setText(self.app.translate("TalkEditorApp", "Date")) self.talkDetailsWidget.timeLabel.setText(self.app.translate("TalkEditorApp", "Time")) # --- End TalkDetailsWidget # # Import Talks Widget Translations # self.importTalksWidget.rssRadioButton.setText(self.app.translate("TalkEditorApp", "RSS URL")) self.importTalksWidget.csvRadioButton.setText(self.app.translate("TalkEditorApp", "CSV File")) self.importTalksWidget.importButton.setText(self.app.translate("TalkEditorApp", "Import")) # --- End Talks Widget Translations # # Command Button Translations\ # #self.commandButtons.addButton.setText(self.app.translate("TalkEditorApp", "Add")) self.commandButtons.importButton.setText(self.app.translate("TalkEditorApp", "Import")) self.commandButtons.exportButton.setText(self.app.translate("TalkEditorApp", "Export")) self.commandButtons.removeButton.setText(self.app.translate("TalkEditorApp", "Remove")) self.commandButtons.removeAllButton.setText(self.app.translate("TalkEditorApp", "Remove All")) # --- End Command Butotn Translations # # Search Widget Translations # self.commandButtons.searchButton.setText(self.app.translate("TalkEditorApp", "Search")) # --- End Command Button Translations def load_presentations_model(self): # Load Presentation Model self.presentationModel = self.db.get_presentations_model() self.proxy = QSortFilterProxyModel() self.proxy.setSourceModel(self.presentationModel) self.tableView.setModel(self.proxy) self.proxy.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive) # Fill table whitespace. self.tableView.horizontalHeader().setStretchLastSection(False) self.tableView.horizontalHeader().setResizeMode(1, QHeaderView.Stretch) # Hide the ID field self.tableView.setColumnHidden(0, True) # Map data to widgets self.mapper = QDataWidgetMapper() self.mapper.setModel(self.proxy) self.mapper.addMapping(self.talkDetailsWidget.titleLineEdit, 1) self.mapper.addMapping(self.talkDetailsWidget.presenterLineEdit, 2) self.mapper.addMapping(self.talkDetailsWidget.categoryLineEdit, 4) self.mapper.addMapping(self.talkDetailsWidget.eventLineEdit, 5) self.mapper.addMapping(self.talkDetailsWidget.roomLineEdit, 6) self.mapper.addMapping(self.talkDetailsWidget.descriptionTextEdit, 3) self.mapper.addMapping(self.talkDetailsWidget.dateEdit, 7) self.mapper.addMapping(self.talkDetailsWidget.timeEdit, 8) # Load StringLists self.titleList = QStringList(self.db.get_string_list("Title")) #self.speakerList = QStringList(self.db.get_speaker_list()) #self.categoryList = QStringList(self.db.get_category_list()) #self.eventList = QStringList(self.db.get_event_list()) #self.roomList = QStringList(self.db.get_room_list()) #Disble input self.talkDetailsWidget.disable_input_fields() def search_talks(self): # The default value is 0. If the value is -1, the keys will be read from all columns. self.proxy.setFilterKeyColumn(-1) self.proxy.setFilterFixedString(self.commandButtons.searchLineEdit.text()) def talk_selected(self, model): self.talkDetailsWidget.saveButton.setEnabled(False) self.mapper.setCurrentIndex(model.row()) self.talkDetailsWidget.enable_input_fields() def toggle_import(self): if self.importTalksWidget.csvRadioButton.isChecked(): self.importTalksWidget.csvLineEdit.setEnabled(True) self.importTalksWidget.csvFileSelectButton.setEnabled(True) self.importTalksWidget.rssLineEdit.setEnabled(False) else: self.importTalksWidget.csvLineEdit.setEnabled(False) self.importTalksWidget.csvFileSelectButton.setEnabled(False) self.importTalksWidget.rssLineEdit.setEnabled(True) def show_import_talks_widget(self): self.commandButtons.setHidden(True) self.tableView.setHidden(True) self.talkDetailsWidget.setHidden(True) self.importTalksWidget.setHidden(False) def hide_import_talks_widget(self): self.commandButtons.setHidden(False) self.tableView.setHidden(False) self.talkDetailsWidget.setHidden(False) self.importTalksWidget.setHidden(True) def add_talk(self): date = self.talkDetailsWidget.dateEdit.date() time = self.talkDetailsWidget.timeEdit.time() #datetime = QtCore.QDateTime(date, time) presentation = Presentation( unicode(self.talkDetailsWidget.titleLineEdit.text()).strip(), unicode(self.talkDetailsWidget.presenterLineEdit.text()).strip(), unicode(self.talkDetailsWidget.descriptionTextEdit.toPlainText()).strip(), unicode(self.talkDetailsWidget.categoryLineEdit.text()).strip(), unicode(self.talkDetailsWidget.eventLineEdit.text()).strip(), unicode(self.talkDetailsWidget.roomLineEdit.text()).strip(), unicode(date.toString(QtCore.Qt.ISODate)), unicode(time.toString(QtCore.Qt.ISODate))) # Do not add talks if they are empty strings if (len(presentation.title) == 0): return self.db.insert_presentation(presentation) # Update Model, Refreshes TableView self.presentationModel.select() # Select Last Row self.tableView.selectRow(self.presentationModel.rowCount() - 1) self.tableView.setCurrentIndex(self.proxy.index(self.proxy.rowCount() - 1, 0)) self.talk_selected(self.proxy.index(self.proxy.rowCount() - 1, 0)) self.update_autocomple_fields() self.talkDetailsWidget.disable_input_fields() def confirm_add(self): """Requests confirmation before clearing fields for a new talk.""" if self.are_fields_enabled() and self.unsaved_details_exist(): confirm = QMessageBox.question(self, self.confirmTalkDetailsClearTitleString, self.confirmTalkDetailsClearQuestionString, QMessageBox.Yes, QMessageBox.No) if confirm == QMessageBox.Yes: self.clear_talk_details_widget() else: self.clear_talk_details_widget() def clear_talk_details_widget(self): self.talkDetailsWidget.saveButton.setEnabled(True) self.talkDetailsWidget.enable_input_fields() self.talkDetailsWidget.titleLineEdit.clear() self.talkDetailsWidget.presenterLineEdit.clear() self.talkDetailsWidget.descriptionTextEdit.clear() self.talkDetailsWidget.categoryLineEdit.clear() #self.talkDetailsWidget.eventLineEdit.clear() #self.talkDetailsWidget.roomLineEdit.clear() self.presentationModel.select() def remove_talk(self): try: rows_selected = self.tableView.selectionModel().selectedRows() except: return # Reversed because rows in list change position once row is removed for row in reversed(rows_selected): self.presentationModel.removeRow(row.row()) def load_talk(self): try: self.tableView.currentIndex().row() except: return self.mapper.addMapping(self.talkDetailsWidget.roomLineEdit, 6) self.presentationModel.select() def reset(self): self.db.clear_database() self.presentationModel.select() def confirm_reset(self): """Presents a confirmation dialog to ask the user if they are sure they wish to remove the talk database. If Yes call the reset() function""" confirm = QMessageBox.question(self, self.confirmDBClearTitleString, self.confirmDBClearQuestionString, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if confirm == QMessageBox.Yes: self.reset() def add_talks_from_rss(self): rss_url = unicode(self.importTalksWidget.rssLineEdit.text()) if rss_url: self.db.add_talks_from_rss(rss_url) self.presentationModel.select() self.hide_import_talks_widget() else: error = QMessageBox() error.setText("Please enter a RSS URL") error.exec_() def closeEvent(self, event): log.info('Exiting talk database editor...') self.geometry = self.saveGeometry() event.accept() def csv_file_select(self): fname = QFileDialog.getOpenFileName( self, 'Select file', "", "*.csv") if fname: self.importTalksWidget.csvLineEdit.setText(fname) def add_talks_from_csv(self): fname = self.importTalksWidget.csvLineEdit.text() if fname: self.db.add_talks_from_csv(fname) self.presentationModel.select() self.hide_import_talks_widget() else: error = QMessageBox() error.setText("Please select a file") error.exec_() def import_talks(self): if self.importTalksWidget.csvRadioButton.isChecked(): self.add_talks_from_csv() else: self.add_talks_from_rss() self.update_autocomple_fields() def export_talks_to_csv(self): fname = QFileDialog.getSaveFileName(self, 'Select file', "", "*.csv") if fname: self.db.export_talks_to_csv(fname) def update_autocomple_fields(self): self.titleList = QStringList(self.db.get_string_list("Title")) self.speakerList = QStringList(self.db.get_string_list("Speaker")) self.categoryList = QStringList(self.db.get_string_list("Category")) self.eventList = QStringList(self.db.get_string_list("Event")) self.roomList = QStringList(self.db.get_string_list("Room")) self.titleCompleter = QCompleter(self.titleList) self.titleCompleter.setCaseSensitivity(Qt.CaseInsensitive) self.speakerCompleter = QCompleter(self.speakerList) self.speakerCompleter.setCaseSensitivity(Qt.CaseInsensitive) self.categoryCompleter = QCompleter(self.categoryList) self.categoryCompleter.setCaseSensitivity(Qt.CaseInsensitive) self.eventCompleter = QCompleter(self.eventList) self.eventCompleter.setCaseSensitivity(Qt.CaseInsensitive) self.roomCompleter = QCompleter(self.roomList) self.roomCompleter.setCaseSensitivity(Qt.CaseInsensitive) self.talkDetailsWidget.titleLineEdit.setCompleter(self.titleCompleter) self.talkDetailsWidget.presenterLineEdit.setCompleter(self.speakerCompleter) self.talkDetailsWidget.categoryLineEdit.setCompleter(self.categoryCompleter) self.talkDetailsWidget.eventLineEdit.setCompleter(self.eventCompleter) self.talkDetailsWidget.roomLineEdit.setCompleter(self.roomCompleter) def are_fields_enabled(self): return (self.talkDetailsWidget.titleLineEdit.isEnabled() and self.talkDetailsWidget.presenterLineEdit.isEnabled() and self.talkDetailsWidget.categoryLineEdit.isEnabled() and self.talkDetailsWidget.eventLineEdit.isEnabled() and self.talkDetailsWidget.roomLineEdit.isEnabled() and self.talkDetailsWidget.dateEdit.isEnabled() and self.talkDetailsWidget.timeEdit.isEnabled()) def unsaved_details_exist(self): """Checks if details exist for a new talk Looks for text in the input fields and check the enabled state of the Save Talk button If the Save Talk button is enabled, the input fields contain values for a new talk Otherwise, the input fields contain values for an existing selected talk """ return (self.talkDetailsWidget.saveButton.isEnabled() and (self.talkDetailsWidget.titleLineEdit.text() or self.talkDetailsWidget.presenterLineEdit.text() or self.talkDetailsWidget.categoryLineEdit.text() or self.talkDetailsWidget.descriptionTextEdit.toPlainText()))
class MyMainWindow(QMainWindow): " Main Window " def __init__(self, parent=None): " Initialize QWidget inside MyMainWindow " super(MyMainWindow, self).__init__(parent) QWidget.__init__(self) self.statusBar().showMessage(" " + __doc__) self.setStyleSheet("QStatusBar{color:grey;}") self.setWindowTitle(__doc__) self.setWindowIcon(QIcon.fromTheme("face-monkey")) self.setFont(QFont("Ubuntu Light", 10)) self.setMaximumSize(QDesktopWidget().screenGeometry().width(), QDesktopWidget().screenGeometry().height()) # directory auto completer self.completer = QCompleter(self) self.dirs = QDirModel(self) self.dirs.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot) self.completer.setModel(self.dirs) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setCompletionMode(QCompleter.PopupCompletion) # process self.process = QProcess(self) # self.process.finished.connect(self.on_process_finished) # self.process.error.connect(self.on_process_error) # Proxy support, by reading http_proxy os env variable proxy_url = QUrl(environ.get("http_proxy", "")) QNetworkProxy.setApplicationProxy( QNetworkProxy( QNetworkProxy.HttpProxy if str(proxy_url.scheme()).startswith("http") else QNetworkProxy.Socks5Proxy, proxy_url.host(), proxy_url.port(), proxy_url.userName(), proxy_url.password(), ) ) if "http_proxy" in environ else None print((" INFO: Proxy Auto-Config as " + str(proxy_url))) # basic widgets layouts and set up self.mainwidget = QTabWidget() self.mainwidget.setToolTip(__doc__) self.mainwidget.setMovable(True) self.mainwidget.setTabShape(QTabWidget.Triangular) self.mainwidget.setTabsClosable(True) self.mainwidget.setContextMenuPolicy(Qt.CustomContextMenu) self.mainwidget.tabCloseRequested.connect( lambda: self.mainwidget.setTabPosition(1) if self.mainwidget.tabPosition() == 0 else self.mainwidget.setTabPosition(0) ) self.setCentralWidget(self.mainwidget) self.dock1 = QDockWidget() self.dock2 = QDockWidget() self.dock3 = QDockWidget() for a in (self.dock1, self.dock2, self.dock3): a.setWindowModality(Qt.NonModal) a.setWindowOpacity(0.9) a.setWindowTitle(__doc__ if a.windowTitle() == "" else a.windowTitle()) a.setStyleSheet(" QDockWidget::title{text-align:center;}") a.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.mainwidget.addTab(a, QIcon.fromTheme("face-cool"), str(a.windowTitle()).strip().lower()) # Paleta de colores para pintar transparente self.palette().setBrush(QPalette.Base, Qt.transparent) self.setPalette(self.palette()) self.setAttribute(Qt.WA_OpaquePaintEvent, False) # toolbar and basic actions self.toolbar = QToolBar(self) self.toolbar.setIconSize(QSize(24, 24)) # spacer widget for left self.left_spacer = QWidget(self) self.left_spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) # spacer widget for right self.right_spacer = QWidget(self) self.right_spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) qaqq = QAction(QIcon.fromTheme("application-exit"), "Quit", self) qaqq.setShortcut("Ctrl+Q") qaqq.triggered.connect(exit) qamin = QAction(QIcon.fromTheme("go-down"), "Minimize", self) qamin.triggered.connect(lambda: self.showMinimized()) qamax = QAction(QIcon.fromTheme("go-up"), "Maximize", self) qanor = QAction(QIcon.fromTheme("go-up"), "AutoCenter AutoResize", self) qanor.triggered.connect(self.center) qatim = QAction(QIcon.fromTheme("go-up"), "View Date and Time", self) qatim.triggered.connect(self.timedate) qabug = QAction(QIcon.fromTheme("help-about"), "Report a Problem", self) qabug.triggered.connect( lambda: qabug.setDisabled(True) if not call("xdg-open mailto:" + "*****@*****.**".decode("rot13"), shell=True) else " ERROR " ) qamax.triggered.connect(lambda: self.showMaximized()) qaqt = QAction(QIcon.fromTheme("help-about"), "About Qt", self) qaqt.triggered.connect(lambda: QMessageBox.aboutQt(self)) qaslf = QAction(QIcon.fromTheme("help-about"), "About Self", self) qaslf.triggered.connect( lambda: QMessageBox.about( self.mainwidget, __doc__, "".join( ( __doc__, linesep, "version ", __version__, ", (", __license__, "), by ", __author__, ", ( ", __email__, " )", linesep, ) ), ) ) qasrc = QAction(QIcon.fromTheme("applications-development"), "View Source Code", self) qasrc.triggered.connect(lambda: call("xdg-open " + __file__, shell=1)) qakb = QAction(QIcon.fromTheme("input-keyboard"), "Keyboard Shortcuts", self) qakb.triggered.connect( lambda: QMessageBox.information(self.mainwidget, "Keyboard Shortcuts", " Ctrl+Q = Quit ") ) qapic = QAction(QIcon.fromTheme("camera-photo"), "Take a Screenshot", self) qapic.triggered.connect( lambda: QPixmap.grabWindow(QApplication.desktop().winId()).save( QFileDialog.getSaveFileName( self.mainwidget, " Save Screenshot As ...", path.expanduser("~"), ";;(*.png) PNG", "png" ) ) ) qatb = QAction(QIcon.fromTheme("help-browser"), "Toggle ToolBar", self) qatb.triggered.connect(lambda: self.toolbar.hide() if self.toolbar.isVisible() is True else self.toolbar.show()) qati = QAction(QIcon.fromTheme("help-browser"), "Switch ToolBar Icon Size", self) qati.triggered.connect( lambda: self.toolbar.setIconSize(self.toolbar.iconSize() * 4) if self.toolbar.iconSize().width() * 4 == 24 else self.toolbar.setIconSize(self.toolbar.iconSize() / 4) ) qasb = QAction(QIcon.fromTheme("help-browser"), "Toggle Tabs Bar", self) qasb.triggered.connect( lambda: self.mainwidget.tabBar().hide() if self.mainwidget.tabBar().isVisible() is True else self.mainwidget.tabBar().show() ) qadoc = QAction(QIcon.fromTheme("help-browser"), "On-line Docs", self) qadoc.triggered.connect(lambda: open_new_tab(__url__)) qapy = QAction(QIcon.fromTheme("help-browser"), "About Python", self) qapy.triggered.connect(lambda: open_new_tab("http://python.org/about")) qali = QAction(QIcon.fromTheme("help-browser"), "Read Licence", self) qali.triggered.connect(lambda: open_new_tab(__full_licence__)) qacol = QAction(QIcon.fromTheme("preferences-system"), "Set GUI Colors", self) qacol.triggered.connect( lambda: self.setStyleSheet( """ * { background-color: %s } """ % QColorDialog.getColor().name() ) ) qatit = QAction(QIcon.fromTheme("preferences-system"), "Set the App Window Title", self) qatit.triggered.connect(self.seTitle) qafnt = QAction(QIcon.fromTheme("help-about"), "Set GUI Font", self) if KDE: font = QFont() qafnt.triggered.connect( lambda: self.setStyleSheet("*{font-family: %s}" % font.toString()) if KFontDialog.getFont(font)[0] == QDialog.Accepted else "" ) else: qafnt.triggered.connect( lambda: self.setStyleSheet("*{font-family: %s}" % QFontDialog.getFont()[0].toString()) ) self.toolbar.addWidget(self.left_spacer) self.toolbar.addSeparator() for b in ( qaqq, qamin, qanor, qamax, qasrc, qakb, qacol, qatim, qatb, qati, qasb, qatit, qafnt, qapic, qadoc, qali, qaslf, qaqt, qapy, qabug, ): self.toolbar.addAction(b) self.addToolBar(Qt.TopToolBarArea, self.toolbar) self.toolbar.addSeparator() self.toolbar.addWidget(self.right_spacer) def contextMenuRequested(point): " quick and dirty custom context menu " menu = QMenu() menu.addActions( ( qaqq, qamin, qanor, qamax, qasrc, qakb, qacol, qati, qasb, qatb, qatim, qatit, qafnt, qapic, qadoc, qali, qaslf, qaqt, qapy, qabug, ) ) menu.exec_(self.mapToGlobal(point)) self.mainwidget.customContextMenuRequested.connect(contextMenuRequested) def must_be_checked(widget_list): " widget tuple passed as argument should be checked as ON " for each_widget in widget_list: try: each_widget.setChecked(True) except: pass def must_have_tooltip(widget_list): " widget tuple passed as argument should have tooltips " for each_widget in widget_list: try: each_widget.setToolTip(each_widget.text()) except: each_widget.setToolTip(each_widget.currentText()) finally: each_widget.setCursor(QCursor(Qt.PointingHandCursor)) def must_autofillbackground(widget_list): " widget tuple passed as argument should have filled background " for each_widget in widget_list: try: each_widget.setAutoFillBackground(True) except: pass ####################################################################### self.group1 = QGroupBox() self.group1.setTitle(" Blender ") self.arch = QLabel("<center><b>" + architecture()[0]) self.ost = QLabel("<center><b>" + sys.platform) self.downf = QLineEdit(path.join(path.expanduser("~"), "blender")) self.downf.setCompleter(self.completer) self.borig = QPushButton(QIcon.fromTheme("folder-open"), "Open") self.borig.clicked.connect( lambda: self.downf.setText( path.join( str(QFileDialog.getExistingDirectory(self.mainwidget, "Open a Folder", path.expanduser("~"))), "blender", ) ) ) self.bugs = QPushButton(QIcon.fromTheme("help-faq"), "Report Bugs!") self.bugs.clicked.connect(lambda: open_new_tab("http://www.blender.org/development/report-a-bug")) self.go = QPushButton(QIcon.fromTheme("emblem-favorite"), "Run Blender") self.go.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.go.clicked.connect(self.run) vboxg1 = QVBoxLayout(self.group1) for each_widget in ( self.go, QLabel(""), QLabel('<h3 style="color:white;"> Download Folder Path: </h3>'), self.downf, self.borig, QLabel('<h3 style="color:white;"> Bugs: </h3>'), self.bugs, QLabel('<h3 style="color:white;"> OS: </h3>'), self.ost, QLabel('<h3 style="color:white;"> Architexture: </h3>'), self.arch, QLabel( """<i style="color:white;"> Warning: this builds arent as stable as releases, use at your own risk</i>""" ), ): vboxg1.addWidget(each_widget) self.group2 = QGroupBox() self.group2.setTitle("Options") self.nwfl = QCheckBox("Force opening with borders") self.smll = QCheckBox("Auto Center and Auto Resize the Window") self.lrgf = QCheckBox("Start with the console window open") self.case = QCheckBox("BGE: Run on 50 hertz without dropping frames") self.cnvt = QCheckBox("BGE: Use Vertex Arrays for rendering") self.blnk = QCheckBox("BGE: No Texture Mipmapping") self.spac = QCheckBox("BGE: Linear Texture Mipmap instead of Nearest") self.whit = QCheckBox("Turn Debugging ON") self.tabz = QCheckBox("Enable floating point exceptions") self.sprs = QCheckBox("Disable the crash handler") self.filn = QCheckBox("Enable debug messages from FFmpeg library") self.plac = QCheckBox("Enable debug messages for python") self.plac = QCheckBox("Enable debug messages for the event system") self.plac = QCheckBox("Enable debug messages for event handling") self.plac = QCheckBox("Enable debug messages for the window manager") self.tbs = QComboBox(self.group2) self.tbs.addItems(["0", "1", "2", "3"]) self.nice = QComboBox(self.group2) self.nice.addItems(["0", "1", "2", "3"]) vboxg2 = QVBoxLayout(self.group2) for each_widget in ( self.nwfl, self.smll, self.lrgf, self.case, self.cnvt, self.blnk, self.spac, self.whit, self.tabz, self.sprs, self.filn, QLabel("BLAH BLAH BLAH"), self.tbs, QLabel("BLAH BLAH BLAH"), self.nice, ): vboxg2.addWidget(each_widget) group3 = QGroupBox() group3.setTitle("Even More Options") self.plai = QCheckBox("Enable debug messages from libmv library") self.nocr = QCheckBox("Skip reading the startup.blend in the home dir") self.ridt = QCheckBox("Set BLENDER_SYSTEM_DATAFILES environment var") self.nocm = QCheckBox("Set BLENDER_SYSTEM_SCRIPTS environment var") self.rdif = QCheckBox("Set BLENDER_SYSTEM_PYTHON environment var") self.clip = QCheckBox("Disable joystick support") self.noti = QCheckBox("Disable GLSL shading") self.pret = QCheckBox("Force sound system to None") self.lolz = QCheckBox("Disable automatic python script execution") self.odif = QCheckBox("Run blender with an interactive console") self.plac = QCheckBox("Enable all debug messages, excludes libmv") self.plac = QCheckBox("Enable time profiling for background jobs") self.plac = QCheckBox("Do not use native pixel size for high res") self.wdth = QComboBox(group3) self.wdth.addItems(["OPENAL", "NULL", "SDL", "JACK"]) self.bcknd = QComboBox(group3) self.bcknd.addItems(["0", "5", "10", "15", "20"]) vboxg3 = QVBoxLayout(group3) for each_widget in ( self.plai, self.nocr, self.ridt, self.nocm, self.rdif, self.pret, self.clip, self.noti, self.lolz, self.odif, self.plac, QLabel('<b style="color:white">Force sound system to specific device'), self.wdth, QLabel('<b style="color:white">CPU Priority'), self.bcknd, ): vboxg3.addWidget(each_widget) # dock 2 the waterfall scrollable = QScrollArea() scrollable.setWidget(QLabel("".join((urlopen("http://builder.blender.org/waterfall").readlines()[23:])))) self.dock2.setWidget(scrollable) # dock 3 the build status stats = QLabel( "<center>" + "".join((urlopen("http://builder.blender.org/one_line_per_build").readlines()[23:])).strip() + "</center>" ) self.dock3.setWidget(stats) # configure some widget settings must_be_checked((self.nwfl, self.smll, self.lrgf, self.clip, self.cnvt, self.plai, self.noti)) must_have_tooltip( ( self.plai, self.nocr, self.ridt, self.nocm, self.rdif, self.pret, self.clip, self.noti, self.lolz, self.odif, self.plac, self.wdth, self.bcknd, self.nwfl, self.smll, self.lrgf, self.case, self.cnvt, self.blnk, self.spac, self.whit, self.tabz, self.sprs, self.filn, self.tbs, self.nice, self.arch, self.ost, ) ) must_autofillbackground( ( self.plai, self.nocr, self.ridt, self.nocm, self.rdif, self.pret, self.clip, self.noti, self.lolz, self.odif, self.plac, self.wdth, self.bcknd, self.nwfl, self.smll, self.lrgf, self.case, self.cnvt, self.blnk, self.spac, self.whit, self.tabz, self.sprs, self.filn, self.tbs, self.nice, scrollable, stats, self.arch, self.ost, ) ) container = QWidget() hbox = QHBoxLayout(container) for each_widget in (self.group2, self.group1, group3): hbox.addWidget(each_widget) self.dock1.setWidget(container) def run(self): " run the actual conversion " print((" INFO: Working at " + str(datetime.now()))) print(" INFO: Loading Blender awesomeness . . . ") self.go.setDisabled(True) # create the output directory try: mkdir(str(self.downf.text())) print((" INFO: Preparing Directory " + str(self.downf.text()))) except: print((" INFO: Preparing Directory " + str(self.downf.text()))) # parse local system architecture architecturez = "x86_64" if "64bit" in architecture()[0] else "i686" print((" INFO: System Architecture is " + architecturez)) # parse remote blender filename blenderfile = [ a.strip().lower().replace('<td><a href="', "").replace("</a></td>", "").split('">')[0] for a in urlopen("http://builder.blender.org/download/").readlines()[40:80] if '<td><a href="blender-' in a and sub("[^a-z]", "", str(sys.platform).lower()) in a and architecturez in a ][0] print((" INFO: System OS is " + sys.platform)) print((" INFO: Blender Remote Filename is " + blenderfile)) if path.isfile(path.join(str(self.downf.text()), blenderfile)): print((" INFO: Blender Local Filename is " + blenderfile)) print(" INFO: Local and Remote Files are similar, Skiping Download") else: print(" INFO: Local and Remote Files differ, Requesting Download") print((" INFO: URL is builder.blender.org/download/" + blenderfile)) # get the file downloader = Downloader( self.mainwidget, "http://builder.blender.org/download/" + blenderfile, str(self.downf.text()) ) downloader.show() ########################################################################### def paintEvent(self, event): "Paint semi-transparent background, animated pattern, background text" # because we are on 2012 !, its time to showcase how Qt we are ! QWidget.paintEvent(self, event) # make a painter p = QPainter(self) p.setRenderHint(QPainter.TextAntialiasing) p.setRenderHint(QPainter.HighQualityAntialiasing) # fill a rectangle with transparent painting p.fillRect(event.rect(), Qt.transparent) # animated random dots background pattern for i in range(8192): x = randint(9, self.size().width() - 9) y = randint(9, self.size().height() - 9) p.setPen(QPen(QColor(randint(9, 255), randint(9, 255), 255), 1)) p.drawPoint(x, y) # set pen to use white color p.setPen(QPen(QColor(randint(9, 255), randint(9, 255), 255), 1)) # Rotate painter 45 Degree p.rotate(30) # Set painter Font for text p.setFont(QFont("Ubuntu", 200)) # draw the background text, with antialiasing p.drawText(99, 99, "Blender") # Rotate -45 the QPen back ! p.rotate(-30) # set the pen to no pen p.setPen(Qt.NoPen) # Background Color p.setBrush(QColor(0, 0, 0)) # Background Opacity p.setOpacity(0.75) # Background Rounded Borders p.drawRoundedRect(self.rect(), 50, 50) # finalize the painter p.end() def seTitle(self): " set the title of the main window " dialog = QDialog(self) textEditInput = QLineEdit(" Type Title Here ") ok = QPushButton(" O K ") ok.clicked.connect(lambda: self.setWindowTitle(textEditInput.text())) ly = QVBoxLayout() [ly.addWidget(wdgt) for wdgt in (QLabel("Title:"), textEditInput, ok)] dialog.setLayout(ly) dialog.exec_() def timedate(self): " get the time and date " dialog = QDialog(self) clock = QLCDNumber() clock.setNumDigits(24) timer = QTimer() timer.timeout.connect(lambda: clock.display(datetime.now().strftime("%d-%m-%Y %H:%M:%S %p"))) timer.start(1000) clock.setToolTip(datetime.now().strftime("%c %x")) ok = QPushButton(" O K ") ok.clicked.connect(dialog.close) ly = QVBoxLayout() [ly.addWidget(wdgt) for wdgt in (QCalendarWidget(), clock, ok)] dialog.setLayout(ly) dialog.exec_() def closeEvent(self, event): " Ask to Quit " if ( QMessageBox.question(self, " Close ", " Quit ? ", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) == QMessageBox.Yes ): event.accept() else: event.ignore() def center(self): " Center and resize the window " self.resize( QDesktopWidget().screenGeometry().width() // 1.25, QDesktopWidget().screenGeometry().height() // 1.25 ) qr = self.frameGeometry() qr.moveCenter(QDesktopWidget().availableGeometry().center()) self.move(qr.topLeft())
def newDocument( self ): """ activar todos los controles, llenar los modelos necesarios, crear el modelo EntradaCompraModel, aniadir una linea a la tabla """ try: if not self.database.isOpen(): if not self.database.open(): raise UserWarning( u"No se pudo establecer la conexión"\ + " con la base de datos" ) self.facturasmodel.setQuery( """ SELECT s.iddocumento, s.ndocimpreso, s.Saldo, s.tasaiva, s.idpersona FROM vw_saldofacturas s WHERE s.saldo>0 and s.idestado = %d ; """ % constantes.CONFIRMADO ) self.tablefacturas.setModel( self.facturasproxymodel ) self.tablefacturas.setColumnHidden( IDDOCUMENTO, True ) # self.tablefacturas.setColumnHidden( 3, True ) # Rellenar el combobox de los CLLIENTES self.clientesModel = QSqlQueryModel() self.clientesModel.setQuery( """ SELECT s.idpersona, s.nombre FROM vw_saldofacturas s WHERE s.idestado = %d GROUP BY s.idpersona HAVING SUM(s.saldo)>0 ORDER BY s.nombre """ % constantes.CONFIRMADO ) #Verificar si existen clientes morosos if self.clientesModel.rowCount() == 0: raise UserWarning( "No existen clientes morosos" ) # Rellenar el combobox de las CONCEPTOS self.conceptosModel = QSqlQueryModel() self.conceptosModel.setQuery( """ SELECT idconcepto, descripcion FROM conceptos c WHERE idtipodoc = %d; """ % constantes.IDRECIBO ) if self.conceptosModel.rowCount() == 0: raise UserWarning( "No existen conceptos para los recibos,"\ + " por favor cree uno" ) self.cbcliente.setModel( self.clientesModel ) self.cbcliente.setCurrentIndex( -1 ) self.cbcliente.setModelColumn( 1 ) completer = QCompleter() completer.setCaseSensitivity( Qt.CaseInsensitive ) completer.setModel( self.clientesModel ) completer.setCompletionColumn( 1 ) self.cbconcepto.setModel( self.conceptosModel ) self.cbconcepto.setCurrentIndex( -1 ) self.cbconcepto.setModelColumn( 1 ) completerconcepto = QCompleter() completerconcepto.setCaseSensitivity( Qt.CaseInsensitive ) completerconcepto.setModel( self.conceptosModel ) completerconcepto.setCompletionColumn( 1 ) self.datosRecibo = DatosRecibo( self.parentWindow.datosSesion ) self.editmodel = ReciboModel( self.datosRecibo.lineas, self.datosRecibo.datosSesion.tipoCambioBanco ) self.abonoeditmodel = AbonoModel( self.datosRecibo.lineasAbonos ) self.datosRecibo.cargarRetenciones( self.cbtasaret ) if self.datosRecibo.retencionModel.rowCount() == 0: raise UserWarning( u"No existe ninguna tasa de retención."\ + " Por favor contacte al administrador"\ + " del sistema" ) # Asigno el modelo del recibo self.datosRecibo.cargarNumeros( self ) self.tablefacturas.setSelectionMode( QAbstractItemView.SingleSelection ) self.tablefacturas.setSelectionBehavior( QAbstractItemView.SelectRows ) self.tableabonos.setModel( self.abonoeditmodel ) self.tabledetails.setModel( self.editmodel ) # ASIGNO EL DELEGADO A LA TABLA DE LOS PAGO delegate = ReciboDelegate() self.tabledetails.setItemDelegate( delegate ) # ASIGNO EL DELEGADO A LA TABLA DE LOS ABONOS delegado = AbonoDelegate() self.tableabonos.setItemDelegate( delegado ) self.status = False self.frbotones.setVisible( True ) self.updateFacturasFilter() self.abonoeditmodel.dataChanged[QModelIndex, QModelIndex].connect( self.updateLabels ) except UserWarning as inst: logging.error( unicode( inst ) ) QMessageBox.critical( self, qApp.organizationName(), unicode( inst ) ) except Exception as inst: logging.critical( unicode( inst ) ) QMessageBox.critical( self, qApp.organizationName(), u"Hubo un error al tratar de obtener los datos" ) finally: if self.database.isOpen(): self.database.close()
class Main(plugin.Plugin): ' main class for plugin ' def initialize(self, *args, **kwargs): ' class init ' super(Main, self).initialize(*args, **kwargs) self.process = QProcess() self.process.readyReadStandardOutput.connect(self.readOutput) self.process.readyReadStandardError.connect(self.readErrors) self.process.finished.connect(self._process_finished) self.process.error.connect(self._process_finished) # directory auto completer 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) # menu menu = QMenu('VirtualEnv') menu.addAction('Make VirtualEnv here', lambda: self.make_virtualenv()) self.locator.get_service('explorer').add_project_menu(menu, lang='all') self.group1 = QGroupBox() self.group1.setTitle(' Paths ') self.outdir = QLineEdit(path.expanduser("~")) self.outdir.setPlaceholderText('Target Directory for Virtualenv files') self.outdir.setCompleter(self.completer) self.btn1 = QPushButton(QIcon.fromTheme("document-open"), ' Open ') self.btn1.clicked.connect(lambda: self.outdir.setText(str( QFileDialog.getExistingDirectory(self.dock, 'Please, Open a Target Directory for the Python VirtualEnv...', path.expanduser("~"))))) self.srcdir, self.prefx = QLineEdit(), QLineEdit() self.srcdir.setPlaceholderText( 'Extra search path to look for setuptools/distribute/pip') self.srcdir.setToolTip(''' Specify Extra search path to look for setuptools/distribute/pip. Defaults to Empty, then the setting is ignored.Defaults are OK.''') self.srcdir.setCompleter(self.completer) self.btn2 = QPushButton(QIcon.fromTheme("document-open"), ' Open ') self.btn2.setToolTip( 'Specify Extra search path to look for setuptools/distribute/pip') self.btn2.clicked.connect(lambda: self.srcdir.setText(str( QFileDialog.getExistingDirectory(self.dock, 'Please, Open a Extra search path to look for setuptools/pip...', path.expanduser("~"))))) self.prefx.setPlaceholderText('Prompt prefix for this environment') self.prefx.setToolTip(''' Specify a custom alternative prompt prefix for this environment. Defaults to Empty,this is optional,short prefix are recommended.''') self.btn3 = QPushButton(QIcon.fromTheme("face-smile-big"), 'Suggestion') self.btn3.setToolTip('Suggest me a Random CLI prompt prefix !') self.btn3.clicked.connect(lambda: self.prefx.setText(choice((getuser(), 'tesla', 'einstein', 'turing', 'ritchie', 'darwin', 'curie', 'planck', 'lovelace', 'dijsktra', 'galileo', 'schroedinger', 'perlman', 'hopper', 'newton', 'pasteur', 'maxwell', 'aristotle', 'volta', 'mendelev', 'bohr', 'crick', 'watson', 'archimedes', 'nash', 'fermi', 'dirac', 'feynman', 'kepler', 'copernicus', 'lorentz', 'faraday', 'heisenberg', )))) vboxg1 = QVBoxLayout(self.group1) for each_widget in ( QLabel(' Target directory dath: '), self.outdir, self.btn1, QLabel(' Extra search path: '), self.srcdir, self.btn2, QLabel(' CLI Prompt prefix (Optional): '), self.prefx, self.btn3): vboxg1.addWidget(each_widget) self.group2 = QGroupBox() self.group2.setTitle(' Options ') self.group2.setCheckable(True) self.group2.setGraphicsEffect(QGraphicsBlurEffect(self)) self.group2.graphicsEffect().setEnabled(False) self.group2.toggled.connect(self.toggle_options_group) self.qckb1, self.combo1 = QCheckBox(' Use Debug'), QDoubleSpinBox() self.qckb2 = QCheckBox(' Clear out the target directory') self.qckb3 = QCheckBox(' System-wide Python Packages') self.qckb4 = QCheckBox(' Unzip Setuptool or Distribute to virtualenv') self.qckb5 = QCheckBox(' Force the use of SetupTools') self.qckb6 = QCheckBox(' Never download packages') self.qckb7 = QCheckBox(' Delete .PYC files from virtualenv') self.qckb8 = QCheckBox(' Open target directory later') self.qckb9 = QCheckBox(' Save a LOG file to target later') self.qckb10 = QCheckBox(' No install PIP in the new virtualenv') self.qckb11 = QCheckBox('Save Bash script to reproduce virtenv later') self.chrt = QCheckBox('LOW CPU priority for Backend Process') self.combo1.setValue(2.7) self.combo1.setMaximum(3.4) self.combo1.setMinimum(2.4) self.combo1.setDecimals(1) self.combo1.setSingleStep(0.1) try: self.vinfo = QLabel('<small><b> Virtualenv Version: </b>' + getoutput('virtualenv --version', shell=1).strip()) except: self.vinfo = QLabel('Warning: Failed to query Virtualenv Backend!') [a.setChecked(True) for a in (self.qckb1, self.qckb4, self.qckb7, self.chrt, self.qckb8, self.qckb9, self.qckb11)] vboxg2 = QVBoxLayout(self.group2) for each_widget in (self.qckb1, self.qckb2, self.qckb3, self.qckb4, self.qckb5, self.qckb6, self.qckb7, self.qckb8, self.qckb9, self.qckb10, self.qckb11, QLabel(' Python interpreter version: '), self.combo1, QLabel(' Backend CPU priority: '), self.chrt): vboxg2.addWidget(each_widget) self.button = QPushButton(' Make Virtualenv ') self.button.setCursor(QCursor(Qt.PointingHandCursor)) self.button.setMinimumSize(75, 50) self.button.clicked.connect(self.run) glow = QGraphicsDropShadowEffect(self) glow.setOffset(0) glow.setBlurRadius(99) glow.setColor(QColor(99, 255, 255)) self.button.setGraphicsEffect(glow) self.output = QTextEdit(''' " Let the future tell the truth, and evaluate each one according to his work and accomplishments. The present is theirs; the future, for which I really worked, is mine. " -Nikola Tesla. ''') class TransientWidget(QWidget): ' persistant widget thingy ' def __init__(self, widget_list): ' init sub class ' super(TransientWidget, self).__init__() vbox = QVBoxLayout(self) for each_widget in widget_list: vbox.addWidget(each_widget) tw = TransientWidget((self.group1, self.group2, QLabel('Backend Logs'), self.output, self.vinfo, self.button)) self.scrollable, self.dock = QScrollArea(), QDockWidget() self.scrollable.setWidgetResizable(True) self.scrollable.setWidget(tw) self.dock.setWindowTitle(__doc__) self.dock.setStyleSheet('QDockWidget::title{text-align: center;}') self.dock.setWidget(self.scrollable) ExplorerContainer().addTab(self.dock, "Virtualenv") QPushButton(QIcon.fromTheme("help-about"), 'About', self.dock ).clicked.connect(lambda: QMessageBox.information(self.dock, __doc__, HELPMSG)) def readOutput(self): """Read and append sphinx-build output to the logBrowser""" self.output.append(str(self.process.readAllStandardOutput()).strip()) def readErrors(self): """Read and append sphinx-build errors to the logBrowser""" self.output.append(self.formatErrorMsg(str( self.process.readAllStandardError()))) def formatErrorMsg(self, msg): """Format error messages in red color""" return self.formatMsg(msg, 'red') def formatInfoMsg(self, msg): """Format informative messages in blue color""" return self.formatMsg(msg, 'green') def formatMsg(self, msg, color): """Format message with the given color""" return '<font color="{}">{}</font>'.format(color, msg) def make_virtualenv(self): ' make virtualenv from contextual sub menu ' self.outdir.setText(self.ex_locator.get_current_project_item().path) self.run() def run(self): ' run the actions ' self.output.clear() self.output.append(self.formatInfoMsg( 'INFO: OK: Starting at {}'.format(datetime.now()))) self.button.setDisabled(True) # Parse Values arg0 = '' if self.qckb10.isChecked() is False else '--no-pip ' arg1 = '--quiet ' if self.qckb1.isChecked() is False else '--verbose ' arg2 = '' if self.qckb2.isChecked() is False else '--clear ' arg3 = '' if self.qckb3.isChecked() is False else '--system-site-packages ' arg4 = '' if self.qckb4.isChecked() is False else '--unzip-setuptools ' arg5 = '' if self.qckb5.isChecked() is False else '--setuptools ' arg6 = '' if self.qckb6.isChecked() is False else '--never-download ' # if the target is empty return if not len(str(self.outdir.text()).strip()): self.output.append(self.formatErrorMsg('ERROR: FAIL: Target empty')) self.button.setEnabled(True) return else: self.output.append(self.formatInfoMsg( 'INFO: OK: Output Directory is {}'.format(self.outdir.text()))) # prefix prf = str(self.prefx.text()).upper().strip().replace(' ', '') arg10 = '' if prf is '' else '--prompt="{}_" '.format(prf) self.output.append(self.formatInfoMsg('INFO: Prefix: {}'.format(arg10))) # extra search dir src = str(self.srcdir.text()).strip() arg11 = '' if src is '' else '--extra-search-dir="{}" '.format(src) self.output.append(self.formatInfoMsg(' INFO: Extra: {}'.format(arg11))) self.output.append(self.formatInfoMsg( ' INFO: OK: Write Logs ?: {} '.format(self.qckb9.isChecked()))) self.output.append(self.formatInfoMsg( ' INFO: OK: Open Directory ?: {} '.format(self.qckb8.isChecked()))) # run the subprocesses cmd = '{}virtualenv {}{}{}{}{}{}{}-p python{} {}{} {}'.format( 'chrt --verbose -i 0 ' if self.chrt.isChecked() is True else '', arg0, arg1, arg2, arg3, arg4, arg5, arg6, self.combo1.value(), arg11, arg10, str(self.outdir.text()).strip()) self.output.append(self.formatInfoMsg('INFO:OK:Command:{}'.format(cmd))) self.process.start(cmd) if not self.process.waitForStarted(): self.output.append(self.formatErrorMsg(' ERROR: FAIL: Meh. ')) self.output.append(self.formatErrorMsg( 'ERROR: FAIL: Failed with Arguments: {} '.format(cmd))) self.button.setEnabled(True) return # write a .sh bash script file on target if self.qckb11.isChecked() is True: sh_file = 'create_virtualenv.sh' with open(path.join(str(self.outdir.text()), sh_file), 'w') as _sh: self.output.append(self.formatInfoMsg('''INFO: OK: Writing Bash: {}'''.format(path.join(str(self.outdir.text()), sh_file)))) _sh.write('#!/usr/bin/env bash' + linesep + cmd) _sh.close() self.output.append(self.formatInfoMsg('INFO: OK: Bash chmod: 775')) try: chmod(path.join(str(self.outdir.text()), sh_file), 0775) # Py2 except: chmod(path.join(str(self.outdir.text()), sh_file), 0o775) # Py3 self.readOutput() self.readErrors() self.button.setEnabled(True) def _process_finished(self): """ finished sucessfully """ self.output.append(self.formatInfoMsg( 'INFO: OK: Finished at {}'.format(datetime.now()))) # remove all *.PYC bytecode if self.qckb7.isChecked() is True: self.output.append(self.formatInfoMsg(' INFO: OK: Removing *.PYC ')) self.output.append(self.formatInfoMsg(' INFO: This takes a moment')) [remove(path.join(root, f)) for root, f in list(itertools.chain(* [list(itertools.product([root], files)) for root, dirs, files in walk(str(self.outdir.text()).strip())])) if f.endswith(('.pyc', '.PYC')) and not f.startswith('.')] # write a .log file on target if self.qckb9.isChecked() is True: log_file = 'virtualenv_gui.log' with open(path.join(str(self.outdir.text()), log_file), 'w') as log: self.output.append(self.formatInfoMsg('''INFO: OK: Writing Logs: {}'''.format(path.join(str(self.outdir.text()), log_file)))) log.write(self.output.toPlainText()) log.close() # open target dir if self.qckb8.isChecked() is True: try: startfile(str(self.outdir.text())) except: Popen(["xdg-open", str(self.outdir.text())]) self.output.selectAll() self.output.setFocus() def toggle_options_group(self): ' toggle on off the options group ' if self.group2.isChecked() is True: [a.setChecked(True) for a in (self.qckb1, self.qckb4, self.qckb7, self.chrt, self.qckb8, self.qckb9, self.qckb11)] self.combo1.setValue(2.7) self.group2.graphicsEffect().setEnabled(False) else: [a.setChecked(False) for a in (self.qckb1, self.qckb4, self.qckb7, self.chrt, self.qckb8, self.qckb9, self.qckb11)] self.group2.graphicsEffect().setEnabled(True) def finish(self): ' clear when finish ' self.process.kill()
class dlgPersona( QDialog, Ui_dlgPersona ): def __init__( self ,tipopersona, parent ): ''' Constructor ''' super( dlgPersona, self ).__init__( parent ) self.setupUi(self) # self.tableview.addActions( ( self.actionEdit, self.actionNew ) ) self.idtipopersona = tipopersona self.table = "" self.backmodel = QSqlQueryModel() self.database = parent.database self.filtermodel = QSortFilterProxyModel( self ) self.filtermodel.setSourceModel( self.backmodel ) self.filtermodel.setDynamicSortFilter( True ) self.filtermodel.setFilterKeyColumn( -1 ) self.filtermodel.setFilterCaseSensitivity( Qt.CaseInsensitive ) self.paisesModel = QSqlQueryModel() self.cbpais.setModel( self.paisesModel ) self.cbpais.setCurrentIndex( -1 ) self.cbpais.setFocus() self.cbpais.setModelColumn( 1 ) self.paisescompleter = QCompleter() self.paisescompleter.setCaseSensitivity( Qt.CaseInsensitive ) self.paisescompleter.setModel( self.paisesModel ) self.paisescompleter.setCompletionColumn( 1 ) self.cbpais.setCompleter( self.paisescompleter ) self.proveedoresModel = QSqlQueryModel() self.cbproveedor.setModel( self.proveedoresModel ) self.cbproveedor.setCurrentIndex( -1 ) self.cbproveedor.setFocus() self.cbproveedor.setModelColumn( 1 ) self.proveedorcompleter = QCompleter() self.proveedorcompleter.setCaseSensitivity( Qt.CaseInsensitive ) self.proveedorcompleter.setModel( self.proveedoresModel ) self.proveedorcompleter.setCompletionColumn( 1 ) self.cbproveedor.setCompleter( self.proveedorcompleter ) # self.tableview.setModel(self.filtermodel) self.cbsexo.setCurrentIndex(-1) self.txtnombre.setFocus() self.setReadOnly(True) QTimer.singleShot( 0, self.updateModels ) @pyqtSlot( "QString" ) def on_txtSearch_textChanged( self, text ): """ Cambiar el filtro de busqueda """ self.filtermodel.setFilterRegExp( text ) def setReadOnly(self,status): self.txtSearch.setText("") self.txtnombre.setText("") self.txtempresa.setText("") self.txttelefono.setText("") self.txtcorreo.setText("") self.cbpais.setCurrentIndex(-1) self.txtnombre.setFocus() if status: self.editmodel = None self.swpanel.setCurrentIndex(0) else: self.editmodel = PersonaModel(self.database,self.idtipopersona) self.swpanel.setCurrentIndex(1) # # if status: # self.tableview.setEditTriggers( QAbstractItemView.AllEditTriggers ) ## self.tableview.edit( self.tableview.selectionModel().currentIndex() ) # else: # self.tableview.setEditTriggers( QAbstractItemView.NoEditTriggers ) # # self.actionNew.setVisible( status ) # self.actionEdit.setVisible( status ) # self.actionDelete.setVisible( status ) # self.actionCancel.setVisible( not status ) # self.actionSave.setVisible(not status ) # self.backmodel.readOnly = status def updateModels( self ): """ Actualizar los modelos, despues de toda operacion que cambie la base de datos se tienen que actualizar los modelos """ try: if not self.database.isOpen(): if not self.database.open(): raise UserWarning( u"No se pudo conectar con la base de datos" ) self.backmodel.setQuery(""" SELECT d.idpersona as Id, d.Nombre, d.Telefono, d.Correo, p.nombre as Pais FROM personas d JOIN paises p ON p.idpais = d.idpais WHERE idaccion = %d""" %self.idtipopersona ) self.tableview.setModel( self.filtermodel ) self.tableview.setColumnHidden(0,True) # self.tableview.setColumnWidth(0,200) # self.tableview.set self.paisesModel.setQuery( """ SELECT idpais , nombre FROM paises """ ) if self.paisesModel.rowCount() == 0: raise UserWarning( "No existen paises en la"\ + " base de datos" ) self.cbpais.setModel( self.paisesModel ) self.cbpais.setCurrentIndex( -1 ) self.cbpais.setModelColumn( 1 ) self.paisescompleter.setCaseSensitivity( Qt.CaseInsensitive ) self.paisescompleter.setModel( self.paisesModel ) self.paisescompleter.setCompletionColumn( 1 ) self.cbpais.setCompleter( self.paisescompleter ) self.proveedoresModel.setQuery( """ SELECT idproveedor, nombre FROM proveedores p where p.idproveedor not in (select origen from proveedores where origen is not null);""" ) if self.proveedoresModel.rowCount() == 0: raise UserWarning( "No existen proveedores en la"\ + " base de datos" ) self.cbproveedor.setModel( self.proveedoresModel ) self.cbproveedor.setCurrentIndex( -1 ) self.cbproveedor.setFocus() self.cbproveedor.setModelColumn( 1 ) self.proveedorcompleter.setCaseSensitivity( Qt.CaseInsensitive ) self.proveedorcompleter.setModel( self.proveedoresModel ) self.proveedorcompleter.setCompletionColumn( 1 ) self.cbproveedor.setCompleter( self.proveedorcompleter ) self.cbproveedor.setModel( self.proveedoresModel ) self.cbproveedor.setCurrentIndex(-1) self.database.close() except Exception as inst: print( unicode( inst ) ) return False finally: if self.database.isOpen(): self.database.close() return True @pyqtSlot() def on_btnadd_clicked(self): self.setReadOnly(False) @pyqtSlot() def on_btnagregar_pais_clicked(self): paisdialog = DlgPais(self) paisdialog.exec_() self.updateModels() @pyqtSlot() def on_btncancelar_clicked(self): self.setReadOnly(True) @pyqtSlot( int ) def on_cbproveedor_currentIndexChanged( self, index ): """ asignar la concepto al objeto self.editmodel """ if self.editmodel is not None: self.editmodel.idproveedor = self.proveedoresModel.record( index ).value( "idproveedor" ).toInt()[0] @pyqtSlot( int ) def on_cbpais_currentIndexChanged( self, index ): """ asignar la concepto al objeto self.editmodel """ if self.editmodel is not None: self.editmodel.idpais = self.paisesModel.record( index ).value( "idpais" ).toInt()[0] @pyqtSlot() def on_btnguardar_clicked(self): self.editmodel.nombre = self.txtnombre.text() self.editmodel.telefono = self.txttelefono.text() self.editmodel.correo = self.txtcorreo.text() self.editmodel.empresa = self.txtempresa.text() self.editmodel.eshombre = self.cbsexo.currentIndex() self.editmodel.descuento = self.txtdescuento.value() if self.editmodel.valid(): if self.editmodel.save(): QMessageBox.information(None,"Guardar", self.editmodel.mensaje) self.setReadOnly(True) self.updateModels() else: QMessageBox.critical(None,"Guardar", self.editmodel.mensaje) else: QMessageBox.critical(None,"Guardar", self.editmodel.mensaje) @pyqtSlot( int ) def on_cbproveedor_currentIndexChanged( self, index ): """ asignar la concepto al objeto self.editmodel """ if self.editmodel is not None: self.editmodel.idproveedor = self.proveedoresModel.record( index ).value( "idproveedor" ).toInt()[0]
class DiffGUI(object): ' diff gui class ' def __init__(self): ' make a diff method with GUI ' self.dialog = QDialog() self.diff_path = None # directory auto completer self.completer = QCompleter(self.dialog) self.dirs = QDirModel(self.dialog) self.dirs.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot) self.completer.setModel(self.dirs) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setCompletionMode(QCompleter.PopupCompletion) #self.completer.setCompletionMode(QCompleter.InlineCompletion) self.group1 = QGroupBox() self.group1.setTitle('Diff') self.frmt = QComboBox(self.group1) self.frmt.addItems(['Unified', 'Normal', 'Context']) self.file1 = QLineEdit() self.file1.setPlaceholderText('/full/path/to/one_file.py') self.file1.setCompleter(self.completer) self.file2 = QLineEdit() self.file2.setPlaceholderText('/full/path/to/another_file.py') self.file2.setCompleter(self.completer) self.fout = QLineEdit() self.fout.setText(''.join((path.join(gettempdir(), datetime.now().strftime('%d-%b-%Y_%H:%M:%S.diff'))))) self.fout.setPlaceholderText('/full/path/to/output_file.diff') self.fout.setCompleter(self.completer) self.regex = QLineEdit() self.regex.setPlaceholderText('DONT use unless you know what are doing') self.regex.setToolTip('Do NOT use unless you know what you are doing !') self.borig = QPushButton(QIcon.fromTheme("folder-open"), 'Open') self.borig.clicked.connect(lambda: self.file1.setText(str( QFileDialog.getOpenFileName(self.dialog, 'Open file to compare', path.expanduser("~"), ';;(*.*)')))) self.bmodi = QPushButton(QIcon.fromTheme("folder-open"), 'Open') self.bmodi.clicked.connect(lambda: self.file2.setText(str( QFileDialog.getOpenFileName(self.dialog, 'Open file to compare', path.expanduser("~"), ';;(*.*)')))) self.bout = QPushButton(QIcon.fromTheme("folder-open"), 'Open') self.bout.clicked.connect(lambda: self.fout.setText(str( QFileDialog.getSaveFileName(self.dialog, 'Save a Diff file', path.expanduser("~"), ';;(*.diff)')))) vboxg1 = QVBoxLayout(self.group1) for each_widget in (QLabel('Original file full path'), self.file1, self.borig, QLabel('Modified file full path'), self.file2, self.bmodi, QLabel('Output file full Path'), self.fout, self.bout, QLabel('Diff Output Format'), self.frmt, QLabel('Diff REGEX to Ignore (ADVANCED)'), self.regex): vboxg1.addWidget(each_widget) self.group2 = QGroupBox() self.group2.setTitle('Options') self.nwfl = QCheckBox('Treat new files as Empty') self.smll = QCheckBox('Look for smaller changes') self.lrgf = QCheckBox('Optimize for large files') self.case = QCheckBox('Ignore case changes on content') self.cnvt = QCheckBox('Convert Tabs to Spaces') self.blnk = QCheckBox('Ignore added or removed Blank lines') self.spac = QCheckBox('Ignore changes in amount of Spaces') self.whit = QCheckBox('Ignore ALL white Spaces') self.tabz = QCheckBox('Ignore changes by Tab expansions') self.sprs = QCheckBox('Remove Space or Tab before empty lines') self.filn = QCheckBox('Ignore case when comparing file names') self.tbs = QComboBox(self.group2) self.tbs.addItems(['4', '6', '8', '10', '2']) self.nice = QComboBox(self.group2) self.nice.addItems(['20', '15', '10', '5', '0']) vboxg2 = QVBoxLayout(self.group2) for each_widget in (self.nwfl, self.smll, self.lrgf, self.case, self.cnvt, self.blnk, self.spac, self.whit, self.tabz, self.sprs, self.filn, QLabel('Diff Tabs-to-Spaces Size'), self.tbs, QLabel('Diff Backend CPU Priority'), self.nice): vboxg2.addWidget(each_widget) try: each_widget.setToolTip(each_widget.text()) except: each_widget.setToolTip(each_widget.currentText()) each_widget.setCursor(QCursor(Qt.PointingHandCursor)) group3 = QGroupBox() group3.setTitle('Even More Options') self.plai = QCheckBox('Force treat all files as plain text') self.nocr = QCheckBox('Force strip trailing carriage return') self.ridt = QCheckBox('Report when two files are identical') self.nocm = QCheckBox('Do not output common lines') self.rdif = QCheckBox('Report only when files differ') self.clip = QCheckBox('Copy Diff to Clipboard when done') self.noti = QCheckBox('Use system Notification when done') self.pret = QCheckBox('Align all Tabs by prepending a Tab') self.lolz = QCheckBox('Output Diff in two equal columns') self.odif = QCheckBox('Open Diff with Ninja-IDE when done') self.plac = QCheckBox('Make an Awesome Diff view when done') self.wdth = QComboBox(group3) self.wdth.addItems(['80', '100', '120', '130', '250', '500', '999999']) self.bcknd = QComboBox(group3) self.bcknd.addItems(['diff', 'diff.py']) self.bcknd.setDisabled(True) #TODO this feature needs work vboxg3 = QVBoxLayout(group3) for each_widget in (self.plai, self.nocr, self.ridt, self.nocm, self.rdif, self.pret, self.clip, self.noti, self.lolz, self.odif, self.plac, QLabel('Diff Maximum Total Width'), self.wdth, QLabel('Diff Backend (EXPERIMENTAL)'), self.bcknd): vboxg3.addWidget(each_widget) try: each_widget.setToolTip(each_widget.text()) except: each_widget.setToolTip(each_widget.currentText()) each_widget.setCursor(QCursor(Qt.PointingHandCursor)) for widget_should_be_checked in (self.nwfl, self.smll, self.lrgf, self.clip, self.cnvt, self.plai, self.noti): widget_should_be_checked.setChecked(True) container = QWidget() hbox = QHBoxLayout(container) for each_widget in (self.group2, self.group1, group3): hbox.addWidget(each_widget) buttons = QDialogButtonBox() buttons.resize(self.dialog.size().width(), buttons.size().height() * 2) buttons.setOrientation(Qt.Horizontal) buttons.setStandardButtons( QDialogButtonBox.Ok | QDialogButtonBox.Cancel | QDialogButtonBox.Close | QDialogButtonBox.Help) buttons.setCenterButtons(False) buttons.helpRequested.connect(lambda: QMessageBox.about( self.dialog, __doc__, ''.join((__doc__, ' GUI and Visualizer Plugin,', linesep, 'version ', __version__, ', (', __license__, '), by ', linesep, __author__, ', ( ', __email__, ' ).', linesep)))) buttons.rejected.connect(self.dialog.close) buttons.accepted.connect(self.make_diff) info = QLabel(''.join(('<b> Current Backend Diff Engine: </b>', getoutput('diff --version').split(linesep)[0]))) vbox = QVBoxLayout(self.dialog) for each_widget in ( QLabel('<center><h2> Ninja IDE Diff and Patch </h2></center>'), container, info, buttons): vbox.addWidget(each_widget) self.dialog.resize(1024, self.dialog.size().height()) self.dialog.exec_() def make_diff(self): ' make the diff ' diff_command = ''.join(( 'nice --adjustment=', str(self.nice.currentText()).strip(), ' ', str(self.bcknd.currentText()).strip(), ' --', str(self.frmt.currentText()).strip().lower(), ' --new-file ' if self.nwfl.isChecked() is True else '', ' --minimal ' if self.smll.isChecked() is True else '', ' --speed-large-files ' if self.lrgf.isChecked() is True else '', ' --ignore-self.case ' if self.case.isChecked() is True else '', ' --expand-tabs ' if self.cnvt.isChecked() is True else '', ' --ignore-blank-lines ' if self.blnk.isChecked() is True else '', ' --ignore-space-change ' if self.spac.isChecked() is True else '', ' --ignore-all-space ' if self.whit.isChecked() is True else '', ' --ignore-tab-expansion ' if self.tabz.isChecked() is True else '', ' --suppress-blank-empty ' if self.sprs.isChecked() is True else '', ' --ignore-file-name-case ' if self.filn.isChecked() is True else '', ' --text ' if self.plai.isChecked() is True else '', ' --strip-trailing-cr ' if self.nocr.isChecked() is True else '', ' --suppress-common-lines ' if self.nocm.isChecked() is True else '', ' --initial-tab ' if self.pret.isChecked() is True else '', ' --side-by-side ' if self.lolz.isChecked() is True else '', ' --tabsize=', str(self.tbs.currentText()).strip(), ' --width=', str(self.wdth.currentText()).strip(), str(' --ignore-matching-lines=' + str(self.regex.text()).strip()) if str(self.regex.text()).strip() is not '' else '', ' ', path.abspath(str(self.file1.text())) if str(self.file1.text()).strip() is not '' else __file__, ' ', path.abspath(str(self.file2.text())) if str(self.file2.text()).strip() is not '' else __file__ )) print(diff_command) diff_output = getoutput(diff_command) try: print(' INFO: OK, Saving new Diff to disk...') output_file = file(path.abspath(str(self.fout.text())), 'w') output_file.write(diff_output) output_file.close() except: print(' ERROR: FAIL, Can not save Diff to disk!') if self.clip.isChecked() is True: print(' INFO: OK, Diff Copied to Clipboard...') QApplication.clipboard().setText(diff_output) if self.noti.isChecked() is True: call('notify-send [Ninja-IDE] ¡Diff_is_Ready!', shell=True) if self.odif.isChecked() is True: print(' INFO: OK, Opening Diff with Ninja-IDE') call('ninja-ide ' + path.abspath(str(self.fout.text())), shell=True) self.diff_path = path.abspath(str(self.fout.text())) return self.diff_path
#!/usr/bin/env python import sys from PyQt4.QtCore import Qt from PyQt4.QtGui import QApplication, QCompleter, QLineEdit, QStringListModel, QSortFilterProxyModel def get_data(model): model.setStringList(["Paola Llosa", "Pedro Cardozo", "wara", "here"]) if __name__ == "__main__": app = QApplication(sys.argv) edit = QLineEdit() model = QStringListModel() completer = QCompleter() completer.setModel(model) completer.setCaseSensitivity(Qt.CaseInsensitive) edit.setCompleter(completer) get_data(model) edit.show() sys.exit(app.exec_())
class Search_QLineEdit(QLineEdit): """ Defines a `QLineEdit <http://doc.qt.nokia.com/qlinedit.html>`_ subclass providing a search field with clearing capabilities. """ def __init__( self, parent=None, uiSearchImage=None, uiSearchClickedImage=None, uiClearImage=None, uiClearClickedImage=None ): """ Initializes the class. :param parent: Widget parent. :type parent: QObject :param uiSearchImage: Search button image path. :type uiSearchImage: str :param uiSearchClickedImage: Search button clicked image path. :type uiSearchClickedImage: str :param uiClearImage: Clear button image path. :type uiClearImage: str :param uiClearClickedImage: Clear button clicked image path. :type uiClearClickedImage: str """ LOGGER.debug("> Initializing '{0}()' class.".format(self.__class__.__name__)) QLineEdit.__init__(self, parent) # --- Setting class attributes. --- self.__uiSearchImage = None self.uiSearchImage = uiSearchImage or umbra.ui.common.getResourcePath("images/Search_Glass.png") self.__uiSearchClickedImage = None self.uiSearchClickedImage = uiSearchClickedImage or umbra.ui.common.getResourcePath( "images/Search_Glass_Clicked.png" ) self.__uiClearImage = None self.uiClearImage = uiClearImage or umbra.ui.common.getResourcePath("images/Search_Clear.png") self.__uiClearClickedImage = None self.uiClearClickedImage = uiClearClickedImage or umbra.ui.common.getResourcePath( "images/Search_Clear_Clicked.png" ) self.__searchActiveLabel = Active_QLabel( self, QPixmap(self.__uiSearchImage), QPixmap(self.__uiSearchImage), QPixmap(self.__uiSearchClickedImage) ) self.__searchActiveLabel.setObjectName("Search_Field_activeLabel") self.__searchActiveLabel.showEvent = lambda event: reduce( lambda *args: None, (self.__setStyleSheet(), Active_QLabel.showEvent(self.__searchActiveLabel, event)) ) self.__searchActiveLabel.hideEvent = lambda event: reduce( lambda *args: None, (self.__setStyleSheet(), Active_QLabel.hideEvent(self.__searchActiveLabel, event)) ) self.__clearButton = QToolButton(self) self.__clearButton.setObjectName("Clear_Field_button") self.__completer = QCompleter() self.setCompleter(self.__completer) self.__completerVisibleItemsCount = 16 Search_QLineEdit.__initializeUi(self) self.__setClearButtonVisibility(self.text()) # Signals / Slots. self.__clearButton.clicked.connect(self.clear) self.textChanged.connect(self.__setClearButtonVisibility) # ****************************************************************************************************************** # *** Attributes properties. # ****************************************************************************************************************** @property def uiSearchImage(self): """ Property for **self.__uiSearchImage** attribute. :return: self.__uiSearchImage. :rtype: str """ return self.__uiSearchImage @uiSearchImage.setter @foundations.exceptions.handleExceptions(AssertionError) def uiSearchImage(self, value): """ Setter for **self.__uiSearchImage** attribute. :param value: Attribute value. :type value: str """ if value is not None: assert type(value) is unicode, "'{0}' attribute: '{1}' type is not 'unicode'!".format( "uiSearchImage", value ) assert os.path.exists(value), "'{0}' attribute: '{1}' file doesn't exists!".format("uiSearchImage", value) self.__uiSearchImage = value @uiSearchImage.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def uiSearchImage(self): """ Deleter for **self.__uiSearchImage** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "uiSearchImage") ) @property def uiSearchClickedImage(self): """ Property for **self.__uiSearchClickedImage** attribute. :return: self.__uiSearchClickedImage. :rtype: str """ return self.__uiSearchClickedImage @uiSearchClickedImage.setter @foundations.exceptions.handleExceptions(AssertionError) def uiSearchClickedImage(self, value): """ Setter for **self.__uiSearchClickedImage** attribute. :param value: Attribute value. :type value: str """ if value is not None: assert type(value) is unicode, "'{0}' attribute: '{1}' type is not 'unicode'!".format( "uiSearchClickedImage", value ) assert os.path.exists(value), "'{0}' attribute: '{1}' file doesn't exists!".format( "uiSearchClickedImage", value ) self.__uiSearchClickedImage = value @uiSearchClickedImage.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def uiSearchClickedImage(self): """ Deleter for **self.__uiSearchClickedImage** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "uiSearchClickedImage") ) @property def uiClearImage(self): """ Property for **self.__uiClearImage** attribute. :return: self.__uiClearImage. :rtype: str """ return self.__uiClearImage @uiClearImage.setter @foundations.exceptions.handleExceptions(AssertionError) def uiClearImage(self, value): """ Setter for **self.__uiClearImage** attribute. :param value: Attribute value. :type value: str """ if value is not None: assert type(value) is unicode, "'{0}' attribute: '{1}' type is not 'unicode'!".format("uiClearImage", value) assert os.path.exists(value), "'{0}' attribute: '{1}' file doesn't exists!".format("uiClearImage", value) self.__uiClearImage = value @uiClearImage.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def uiClearImage(self): """ Deleter for **self.__uiClearImage** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "uiClearImage") ) @property def uiClearClickedImage(self): """ Property for **self.__uiClearClickedImage** attribute. :return: self.__uiClearClickedImage. :rtype: str """ return self.__uiClearClickedImage @uiClearClickedImage.setter @foundations.exceptions.handleExceptions(AssertionError) def uiClearClickedImage(self, value): """ Setter for **self.__uiClearClickedImage** attribute. :param value: Attribute value. :type value: str """ if value is not None: assert type(value) is unicode, "'{0}' attribute: '{1}' type is not 'unicode'!".format( "uiClearClickedImage", value ) assert os.path.exists(value), "'{0}' attribute: '{1}' file doesn't exists!".format( "uiClearClickedImage", value ) self.__uiClearClickedImage = value @uiClearClickedImage.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def uiClearClickedImage(self): """ Deleter for **self.__uiClearClickedImage** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "uiClearClickedImage") ) @property def searchActiveLabel(self): """ Property for **self.__searchActiveLabel** attribute. :return: self.__searchActiveLabel. :rtype: QPushButton """ return self.__searchActiveLabel @searchActiveLabel.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def searchActiveLabel(self, value): """ Setter for **self.__searchActiveLabel** attribute. :param value: Attribute value. :type value: QPushButton """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "searchActiveLabel") ) @searchActiveLabel.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def searchActiveLabel(self): """ Deleter for **self.__searchActiveLabel** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "searchActiveLabel") ) @property def clearButton(self): """ Property for **self.__clearButton** attribute. :return: self.__clearButton. :rtype: QPushButton """ return self.__clearButton @clearButton.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def clearButton(self, value): """ Setter for **self.__clearButton** attribute. :param value: Attribute value. :type value: QPushButton """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "clearButton") ) @clearButton.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def clearButton(self): """ Deleter for **self.__clearButton** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "clearButton") ) @property def completer(self): """ Property for **self.__completer** attribute. :return: self.__completer. :rtype: QCompleter """ return self.__completer @completer.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def completer(self, value): """ Setter for **self.__completer** attribute. :param value: Attribute value. :type value: QCompleter """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "completer") ) @completer.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def completer(self): """ Deleter for **self.__completer** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "completer") ) @property def completerVisibleItemsCount(self): """ Property for **self.__completerVisibleItemsCount** attribute. :return: self.__completerVisibleItemsCount. :rtype: int """ return self.__completerVisibleItemsCount @completerVisibleItemsCount.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def completerVisibleItemsCount(self, value): """ Setter for **self.__completerVisibleItemsCount** attribute. :param value: Attribute value. :type value: int """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "completerVisibleItemsCount") ) @completerVisibleItemsCount.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def completerVisibleItemsCount(self): """ Deleter for **self.__completerVisibleItemsCount** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "completerVisibleItemsCount") ) # ****************************************************************************************************************** # *** Class methods. # ****************************************************************************************************************** def resizeEvent(self, event): """ Reimplements the :meth:`QLineEdit.QResizeEvent` method. :param event: Resize event. :type event: QResizeEvent """ frameWidth = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth) searchActiveLabelSize = self.__searchActiveLabel.sizeHint() self.__searchActiveLabel.move( self.rect().left() + frameWidth, (self.rect().bottom() - searchActiveLabelSize.height()) / 2 + frameWidth / 2, ) clearButtonSize = self.__clearButton.sizeHint() self.__clearButton.move( self.rect().right() - frameWidth - clearButtonSize.width(), (self.rect().bottom() - clearButtonSize.height()) / 2 + frameWidth / 2, ) def __initializeUi(self): """ Initializes the Widget ui. """ self.__clearButton.setCursor(Qt.ArrowCursor) if self.__uiClearImage and self.__uiClearClickedImage: pixmap = QPixmap(self.__uiClearImage) clickedPixmap = QPixmap(self.__uiClearClickedImage) self.__clearButton.setIcon(QIcon(pixmap)) self.__clearButton.setMaximumSize(pixmap.size()) # Signals / Slots. self.__clearButton.pressed.connect(functools.partial(self.__clearButton.setIcon, QIcon(clickedPixmap))) self.__clearButton.released.connect(functools.partial(self.__clearButton.setIcon, QIcon(pixmap))) else: self.__clearButton.setText("Clear") self.__setStyleSheet() frameWidth = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth) self.setMinimumSize( max(self.minimumSizeHint().width(), self.__clearButton.sizeHint().height() + frameWidth * 2), max(self.minimumSizeHint().height(), self.__clearButton.sizeHint().height() + frameWidth * 2), ) self.__completer.setCaseSensitivity(Qt.CaseInsensitive) self.__completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion) # self.__completer.setMaxVisibleItems(self.__completerVisibleItemsCount) def __setStyleSheet(self): """ Sets the Widget stylesheet. """ frameWidth = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth) self.setStyleSheet( QString( "QLineEdit {{ padding-left: {0}px; padding-right: {1}px; }}\nQToolButton {{ border: none; padding: 0px; }}".format( self.__searchActiveLabel.sizeHint().width() if self.__searchActiveLabel.isVisible() else 0 + frameWidth, self.__clearButton.sizeHint().width() + frameWidth, ) ) ) def __setClearButtonVisibility(self, text): """ Sets the clear button visibility. :param text: Current field text. :type text: QString """ if text: self.__clearButton.show() else: self.__clearButton.hide()
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
def updateCompletion(self): qc = QCompleter(QStringList(self.search_history), self) qc.setCaseSensitivity(Qt.CaseInsensitive) self.ui.searchEdit.setCompleter(qc)
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 tbFactura( QTabWidget ,Ui_tbFactura ): """ Implementacion de la interfaz grafica para facturas """ web = "facturas.php?doc=" DATE_FORMAT = "dd/MM/yyyy" def __init__( self ): ''' Constructor ''' super( tbFactura, self ).__init__( ) # ESTABLECER LA INTERFAZ AL FORMULARIO self.setupUi(self) # VALIDADOR DE MODO DE EDICION self.readOnly = True self.editmodel = None #ESTABLECER LA FECHA INICIAL , (establecida al dia de mañana) self.categoriesview.headers = ["Descripcion", "Precio", "Unidades","Existencia","","",""] # Crear el modelo para cargar catalogo de clientes self.clientesModel = QSqlQueryModel() # Crear lista de autocompletado para el combo de clientes self.clienteCompleter = QCompleter() # Modelo que carga el catalogo de productos self.existenciaModel = QSqlQueryModel() # Establecer todos los controles en modo de edicion self.setControls( False ) # Crear la conexion a la base de datos self.database = QSqlDatabase.database() self.vistaprevia = False # Cargar los modelos del modo de edicion self.updateEditModels() self.parent = self.parent() def newDocument( self ): """ activar todos los controles, llenar los modelos necesarios, crear el modelo FacturaModel, aniadir una linea a la tabla """ self.readOnly = False if not self.updateEditModels(): return self.status = False self.dtPicker.setDate( self.parentWindow.datosSesion.fecha ) def updateEditModels( self ): """ Este metodo actualiza los modelos usados en el modo edición """ resultado = False try: if not self.database.isOpen(): if not self.database.open(): raise UserWarning( u"No se pudo abrir la conexión "\ + "con la base de datos" ) self.clientesModel.setQuery( """ SELECT idpersona , nombre AS cliente FROM personas WHERE escliente = 1 """) self.cbcliente.setModel( self.clientesModel ) self.cbcliente.setModelColumn( 1 ) self.clienteCompleter.setCaseSensitivity( Qt.CaseInsensitive ) self.clienteCompleter.setModel( self.clientesModel ) self.clienteCompleter.setCompletionColumn( 1 ) self.cbcliente.setCompleter( self.clienteCompleter ) self.editmodel = FacturaModel( ) # Cargar el numero de la factura actual query = QSqlQuery( """ SELECT MAX(CAST( IFNULL(referencia,0) AS SIGNED)) FROM documentos d WHERE idtipodoc =%d; """ % constantes.IDFACTURA ) if not query.exec_(): raise Exception( "No se pudo obtener el numero de la factura" ) query.first() if query.size()==0: n =1 else: n = str(int(query.value(0)) + 1) self.editmodel.printedDocumentNumber = str(int(query.value(0)) + 1) self.lblnumero.setText(n) # if self.clientesModel.rowCount() == 0: # raise UserWarning( "No existen clientes en la"\ # + " base de datos" ) # return self.clienteCompleter.setModel(self.clientesModel) self.cbcliente.setModel(self.clientesModel) self.cbcliente.setCompleter(self.clienteCompleter) # #Crear el delegado con los articulo y verificar si existen articulos self.existenciaModel.setQuery( QSqlQuery( """ SELECT categoria, descripcion, precio, unidadesxcaja, -- cajas, 100 as cajas, idprecioproducto FROM vw_articulos -- WHERE existencia >0 """ ) ) self.categoriesview.update(""" SELECT categoria, descripcion, precio, unidadesxcaja, -- cajas, 100 as cajas, idprecioproducto FROM vw_articulos WHERE idprecioproducto IS NOT NULL -- WHERE existencia >0 """) self.categoriesview.expandAll() self.categoriesview.setColumnHidden(3,True) self.categoriesview.setColumnHidden(4,True) self.categoriesview.setColumnWidth(0,150) self.categoriesview.setColumnWidth(1,60) self.categoriesview.setColumnWidth(2,20) self.proxyexistenciaModel = SingleSelectionModel() self.proxyexistenciaModel.setSourceModel( self.existenciaModel ) # self.proxyexistenciaModel.setFilterKeyColumn( IDBODEGAEX ) if self.proxyexistenciaModel.rowCount() == 0: raise UserWarning( "No hay articulos en bodega" ) delegate = FacturaDelegate( self.proxyexistenciaModel ) self.tabledetails.setItemDelegate( delegate ) self.tabledetails.setModel( self.editmodel ) self.tabledetails.setColumnHidden(0,True) # self.editmodel.insertRow(1) self.editmodel.dataChanged[QModelIndex, QModelIndex].connect( self.updateLabels ) self.txtobservaciones.setPlainText( "" ) self.dtPicker.setDate(QDate.currentDate().addDays(1)) self.editmodel.fecha = QDate.currentDate().addDays(1) self.cbcliente.setCurrentIndex( -1 ) resultado = True except UserWarning as inst: logging.error( unicode( inst ) ) QMessageBox.critical( self, qApp.organizationName(), unicode( inst ) ) finally: if self.database.isOpen(): self.database.close() return resultado def addActionsToToolBar( self ): self.actionRefresh = self.createAction( text = "Actualizar", icon = QIcon.fromTheme( 'view-refresh', QIcon( ":/icons/res/view-refresh.png" ) ), slot = self.refresh, shortcut = Qt.Key_F5 ) self.toolBar.addActions( [ self.actionNew, self.actionRefresh, self.actionPreview, self.actionPrint, self.actionSave, self.actionCancel, ] ) self.toolBar.addSeparator() self.toolBar.addActions( [ self.actionGoFirst, self.actionGoPrevious, self.actionGoLast, self.actionGoNext, self.actionGoLast ] ) def refresh( self ): """ Actualizar los modelos de edición """ if not self.status: if QMessageBox.question( self, qApp.organizationName(), u"Se perderán todos los cambios en la factura. ¿Esta seguro que desea actualizar?", QMessageBox.Yes | QMessageBox.No ) == QMessageBox.No: return self.updateEditModels() else: if self.updateModels(): QMessageBox.information( None, "Factura", u"Los datos fueron actualizados con éxito" ) def printDocument1(self): html = u"" date = QDate.currentDate().toString(self.DATE_FORMAT) address = Qt.escape("Bario francisco mesa").replace(",","<br>") contact = Qt.escape("Luis Mejia") balance = 5000 html += ("<p align=right><img src=':/logo.png'></p>" "<p> align = right>Greasy hands ltd." "<br>New Lombard Street" "<br>London<br>WC13 4PX<br>%s</p>" "<p>%s</p><p>Dear %s, </p>" "<p>The balance of your account is %s.")% ( date, address, contact, QString("$ %L1").arg(float(balance),0,"f",2)) if balance <0 : html += ("<p><font color =red><b> Please remit the amount owing immediately.</b></font>") else: html += "We are delighted to have done business with you." html += ("</p><p> </p><p>" "<table border=1 cellpadding=2 cellspacing=2><tr><td colspan=3>Transaction</td></tr>") transactions = [ (QDate.currentDate(),500), (QDate.currentDate(),500), (QDate.currentDate(),-500), (QDate.currentDate(),500) ] for date, amount in transactions: color, status = "black", "Credit" if amount <0: color, status = "red", "Debid" html += ("<tr>" "<td align= right>%s</td>" "<td>%s</td><td align=right><font color=%s>%s</font></td></tr>" % ( date.toString(self.DATE_FORMAT), status,color, QString("$ %L1").arg(float(abs(amount)), 0, "f",2))) html += ("</table></p><p style='page-break-after=always;'>" "We hope to continue doing business with you</p>") pdialog = QPrintDialog() if pdialog.exec_() == QDialog.Accepted: printer = pdialog.printer() document = QTextDocument() document.setHtml(html) document.print_(printer) def printDocument2(self): dialog = QPrintDialog() if not dialog.exec_(): return self.printer = dialog.printer() headFormat = QTextBlockFormat() headFormat.setAlignment(Qt.AlignLeft) headFormat.setTextIndent( self.printer.pageRect().width()-216) bodyFormat = QTextBlockFormat() bodyFormat.setAlignment(Qt.AlignJustify) lastParaBodyFormat = QTextBlockFormat(bodyFormat) lastParaBodyFormat.setPageBreakPolicy(QTextFormat.PageBreak_AlwaysAfter) rightBodyFormat = QTextBlockFormat() rightBodyFormat.setAlignment(Qt.AlignRight) headCharFormat = QTextCharFormat() headCharFormat.setFont(QFont("Helvetica",10)) bodyCharFormat = QTextCharFormat() bodyCharFormat.setFont(QFont("Times",11)) redBodyCharFormat = QTextCharFormat(bodyCharFormat) redBodyCharFormat.setForeground(Qt.red) tableFormat = QTextTableFormat() tableFormat.setBorder(1) tableFormat.setCellPadding(2) document = QTextDocument() cursor = QTextCursor(document) mainFrame = cursor.currentFrame() page = 1 cursor.insertBlock(headFormat, headCharFormat) for text in ("Greasy Hands Ltd.", "New Lombard Street","London" , "WC13", QDate.currentDate().toString(self.DATE_FORMAT)): cursor.insertBlock(headFormat,headCharFormat) cursor.insertText(text) cursor.insertBlock(bodyFormat,bodyCharFormat) cursor.insertText("Barrio Francisco Meza") cursor.insertBlock(bodyFormat) cursor.insertBlock(bodyFormat,bodyCharFormat) cursor.insertText("Dear Lyuis") cursor.insertBlock(bodyFormat) cursor.insertBlock(bodyFormat,bodyCharFormat) cursor.insertText(QString("The balance of your account is $ %L1.").arg(float(500.987),0,"f",2)) cursor.insertBlock(bodyFormat,redBodyCharFormat) cursor.insertText("Please remit the amount") cursor.insertBlock(bodyFormat,bodyCharFormat) cursor.insertText("Transaction") transactions = [ (QDate.currentDate(),500), (QDate.currentDate(),500), (QDate.currentDate(),-500), (QDate.currentDate(),500) ] table = cursor.insertTable(len(transactions), 3, tableFormat) row = 0 for date, amount in transactions: cellCursor = table.cellAt(row,0).firstCursorPosition() cellCursor.setBlockFormat(rightBodyFormat) cellCursor.insertText(date.toString(self.DATE_FORMAT),bodyCharFormat) cellCursor = table.cellAt(row,1).firstCursorPosition() cellCursor.insertText("Credit",bodyCharFormat) cellCursor = table.cellAt(row,2).firstCursorPosition() cellCursor.setBlockFormat(rightBodyFormat) cellCursor.insertText(QString("The balance of your account is $ %L1.").arg(float(amount),0,"f",2),redBodyCharFormat) row += 1 cursor.setPosition(mainFrame.lastPosition()) cursor.insertBlock(bodyFormat,bodyCharFormat) cursor.insertText("We hope") document.print_(self.printer) def printDocument(self): dialog = QPrintDialog() if not dialog.exec_(): return self.printer = dialog.printer() self.imprimir(self.printer) self.document.load(self.editmodel) def preview(self): self.vistaprevia = True preview = frmImpresion(self) preview.exec_() def save( self ): """ Guardar el documento actual @rtype: bool """ result = False try: if not self.valid: return False if QMessageBox.question( self, qApp.organizationName(), u"¿Esta seguro que desea guardar la factura?", QMessageBox.Yes | QMessageBox.No ) == QMessageBox.Yes: if not self.database.isOpen(): if not self.database.open(): raise UserWarning( u"No se pudo conectar con la base de datos" ) self.editmodel.observaciones = self.txtobservaciones.toPlainText() if not self.editmodel.save(): raise UserWarning( "No se ha podido guardar la factura" ) QMessageBox.information( None, qApp.organizationName() , u"""El documento se ha guardado con éxito""" ) self.readOnly = True self.updateModels() # self.navigate( 'last' ) # self.status = True result = True except UserWarning as inst: logging.error( unicode( inst ) ) QMessageBox.critical( self, qApp.organizationName(), unicode( inst ) ) except Exception as inst: logging.critical( unicode( inst ) ) QMessageBox.critical( self, qApp.organizationName(), u"Hubo un error al guardar la factura" ) finally: if self.database.isOpen(): self.database.close() return result # @pyqtSlot(QModelIndex) # def on_categoriesview_doubleClicked(self,index): @pyqtSlot(QModelIndex) def on_categoriesview_activated(self,index): articulo = self.categoriesview.model().asRecord(index) if len(articulo)>0: nuevo = True for i, line in enumerate(self.editmodel.lines): if line.itemId == articulo [5]: nuevo = False fila = i line = self.editmodel.lines[self.editmodel.rowCount()-1] if nuevo: fila = self.editmodel.rowCount() self.editmodel.insertRow(fila) self.parent.saveAct.setEnabled(True) linea = self.editmodel.lines[fila] linea.itemDescription = articulo[0] + " " + articulo [1] linea.itemPrice = Decimal(articulo[2]) linea.itemId = articulo[5] linea.quantityperbox = int(articulo[3]) self.editmodel.lines[fila].quantity += 1 self.editmodel.lines[fila].existencia = int(articulo[4]) - self.editmodel.lines[fila].quantity indice =self.editmodel.index( fila,2) self.editmodel.dataChanged.emit( indice, indice ) indice =self.editmodel.index( fila,3) self.editmodel.dataChanged.emit( indice, indice ) indice =self.editmodel.index( fila,5) self.editmodel.dataChanged.emit( indice, indice ) @pyqtSlot() def on_btneditar_clicked( self ): articulo = dlgArticulo(self) articulo.exec_() self.updateEditModels() @pyqtSlot( int ) def on_cbcliente_currentIndexChanged( self, index ): """ asignar proveedor al objeto self.editmodel """ if self.editmodel is not None: numero = self.clientesModel.record( index ).value( "idpersona" ) self.editmodel.clienteId = int(numero) if numero is not None else 0 @pyqtSlot( unicode ) def on_cbcliente_editTextChanged( self, text ): """ asignar proveedor al objeto self.editmodel """ if self.editmodel is not None: self.editmodel.cliente =str( text) @pyqtSlot( int ) def on_cbvendedor_currentIndexChanged( self, index ): """ asignar proveedor al objeto self.editmodel """ self.editmodel.vendedorId = self.vendedoresModel.record( index ).value( "idpersona" ).toInt()[0] @pyqtSlot( QDate) def on_dtPicker_dateChanged( self, date ): if self.editmodel is not None: self.editmodel.fecha = date @pyqtSlot( bool ) def on_rbcontado_toggled( self, on ): """ Asignar las observaciones al objeto editmodel """ self.editmodel.escontado = 1 if on else 0 def on_txtSearch_textChanged( self, text ): """ Cambiar el filtro de busqueda """ self.filtermodel.setFilterRegExp( text ) def setControls( self, status ): """ @param status: false = editando true = navegando """ # self.actionPrint.setVisible( status ) self.readOnly = status self.txtobservaciones.setReadOnly( status ) # self.actionPreview.setVisible( status ) # self.actionAnular.setVisible( status ) # self.toolBar.setVisible(status) # self.lblnfac.setText( self.editmodel.printedDocumentNumber ) self.swcliente.setCurrentIndex( 0 ) self.lbltotal.setText( "C$ 0.00" ) self.tabledetails.setEditTriggers( QAbstractItemView.AllEditTriggers ) # self.lblanulado.setHidden( True ) self.tabledetails.horizontalHeader().setStretchLastSection(True) self.tabledetails.setColumnHidden( IDARTICULO, True ) self.tabledetails.setColumnHidden( IDDOCUMENTOT, True ) def updateLabels( self ): self.lbltotal.setText( moneyfmt( self.editmodel.total, 2, "C$ " ) ) @property def valid( self ): """ Un documento es valido cuando self.printedDocumentNumber != "" self.providerId !=0 self.validLines >0 self.ivaId !=0 self.uid != 0 self.warehouseId != 0 """ if int( self.editmodel.clienteId) == 0 and self.editmodel.cliente == "": QMessageBox.warning( self, qApp.organizationName(), "Por favor elija el cliente" ) self.cbcliente.setFocus() elif self.editmodel.rowCount() == 0: QMessageBox.warning( self, qApp.organizationName(), "Por favor agregue algun articulo a la factura" ) else: return True return False def imprimir(self,printer): leftMargin = 72 widthCol = 100 arialFont = QFont("Helvetica",16,3) fuente =QFontMetrics(arialFont) arialLineHeight = fuente.height() fondo = QPixmap(":/images/res/fondo.png") painter = QPainter(printer) pageRect = printer.pageRect() page = 1 painter.save() if self.vistaprevia: painter.drawPixmap(0, 0, 530, 830, fondo) painter.setFont(arialFont) y = 180 x = 35 painter.drawText(x,y,self.editmodel.fecha.toString("dd MM yy")) y = 210 x = 85 painter.drawText(x,y, self.editmodel.cliente) painter.setFont(arialFont) cajasFont = QFont("Helvetica",10,2) x = -5 y = 295 painter.setFont(cajasFont) painter.drawText(x,y - arialLineHeight - 1,"Cajas") for row in self.editmodel.lines: painter.setFont(cajasFont) x = 2 painter.drawText(x,y,row.cantidad()) painter.setFont(arialFont) total = moneyfmt(row.total,2,"") x = 470 - fuente.width(total) painter.drawText(x,y,total) x =310 painter.drawText(x,y,moneyfmt(row.itemPrice,2,"")) x = 30 painter.drawText(x,y,row.unidades()) x = 80 painter.drawText(x,y,row.itemDescription) y+= arialLineHeight total = moneyfmt(self.editmodel.total,2,"") y= 690 x = 470 - fuente.width(total) painter.drawText(x,y,total) painter.setPen(Qt.black) # printer.newPage() painter.restore()
import sys from PyQt4.QtCore import Qt from PyQt4.QtGui import QApplication, QCompleter, QLineEdit, QStringListModel class textbox(QLineEdit): def __init__(self): pass def focusInEvent(self, e): msg = QMessageBox(QMessageBox.Waring, 'Titulo', 'Mensahe') msg.Exec_() if __name__ == "__main__": app = QApplication(sys.argv) edit = textbox() # QLineEdit() # Se instancia la clase para Qlineedit lista = ('Carlos', 'Carla', 'Alberto', 'Adrian', 'garcia', 'Diaz') # Se crea la lista que se mostrara autoCompletar = QCompleter(lista) # se define la lista autoCompletar.setCaseSensitivity(Qt.CaseInsensitive) # se desactiva el case sensitive edit.setCompleter(autoCompletar) # Se asigna la lista al QlineEdit edit.show() sys.exit(app.exec_())
class MainWidget(QWidget, PM, Ui_MainWidget): def __init__(self, parent = None): QWidget.__init__(self, parent) self.setupUi(self) self.parent = parent self._selectedGroups = [] self._preexceptions = [] self._postexceptions = [] self.state = StateManager(self) self.currentState = None self.completer = None self._updatesCheckedOnce = False #set style self._style = "/usr/share/kde4/apps/package-manager/data/style.qss" self.setStyleSheet(file(self._style).read()) # Search Thread self._searchThread = PThread(self, self.startSearch, self.searchFinished) self.statusUpdater = StatusUpdater() self.basket = BasketDialog(self.state, self.parent) self._postexceptions.append(lambda: self.basket.setActionEnabled(True)) self.searchButton.setIcon(KIcon("edit-find")) self.initializeUpdateTypeList() self.morewidgets = MoreWidgets(self.state, self.parent) self.morewidgets._show() self.webdialog = WebDialog(self.state, self.parent) model = PackageModel(self) proxy = PackageProxy(self) proxy.setSourceModel(model) self.packageList.setModel(proxy) self.packageList.setItemDelegate(PackageDelegate(self, self.parent)) self.packageList.setColumnWidth(0, 32) self.connect(self.packageList.model(), SIGNAL("dataChanged(QModelIndex,QModelIndex)"), self.statusChanged) self.connect(self.packageList, SIGNAL("updateRequested()"), self.initialize) self.connect(self.morewidgets.randomPackageList, SIGNAL("itemDoubleClicked(QListWidgetItem*)"), self.showWebdialog) self.updateSettings() self.setActionButton() self.operation = OperationManager(self.state) self.progressDialog = ProgressDialog(self.state, self.parent) self._preexceptions.append(self.progressDialog._hide) self.progressDialog.registerFunction(FINISHED, lambda: self.parent.statusBar().setVisible(not self.progressDialog.isVisible())) self.progressDialog.registerFunction(OUT, lambda: self.parent.statusBar().show()) self.summaryDialog = SummaryDialog() self.connectOperationSignals() self.pdsMessageBox = PMessageBox(self.content) def connectMainSignals(self): self.connect(self.actionButton, SIGNAL("clicked()"), self.showBasket) self.connect(self.buttonMore, SIGNAL("clicked()"), self.showMoreWidgets) self.connect(self.checkUpdatesButton, SIGNAL("clicked()"), self.state.updateRepoAction) self.connect(self.searchButton, SIGNAL("clicked()"), self.searchActivated) self.connect(self.searchLine, SIGNAL("textEdited(const QString&)"), self.searchLineChanged) self.connect(self.searchLine, SIGNAL("returnPressed()"), self.searchActivated) self.connect(self.searchLine, SIGNAL("clearButtonClicked()"), self.groupFilter) self.connect(self.typeCombo, SIGNAL("activated(int)"), self.typeFilter) self.connect(self.stateTab, SIGNAL("currentChanged(int)"), self.switchState) self.connect(self.groupList, SIGNAL("groupChanged()"), self.groupFilter) self.connect(self.groupList, SIGNAL("groupChanged()"), lambda:self.searchButton.setEnabled(False)) self.connect(self.packageList.select_all, SIGNAL("clicked(bool)"), self.toggleSelectAll) self.connect(self.statusUpdater, SIGNAL("selectedInfoChanged(int, QString, int, QString)"), self.emitStatusBarInfo) self.connect(self.statusUpdater, SIGNAL("selectedInfoChanged(QString)"), lambda message: self.emit(SIGNAL("selectionStatusChanged(QString)"), message)) self.connect(self.statusUpdater, SIGNAL("finished()"), self.statusUpdated) def initialize(self): waitCursor() self.searchLine.clear() self._started = False self._last_packages = None self.state.reset() self.initializePackageList() self.initializeGroupList() self.initializeStatusUpdater() self.statusChanged() self._selectedGroups = [] self.packageList.select_all.setChecked(False) self.initializeBasket() self.searchLine.setFocus(True) if self.currentState == self.state.UPGRADE: if self.groupList.count() == 0: QTimer.singleShot(0, \ lambda: self.pdsMessageBox.showMessage(i18n("All packages are up to date"), icon = "games-endturn")) if self.groupList.count() > 0: if self.state.inUpgrade(): self.pdsMessageBox.hideMessage(force = True) restoreCursor() def initializeStatusUpdater(self): self.statusUpdater.calculate_deps = not self.state.state == self.state.ALL self.statusUpdater.setModel(self.packageList.model().sourceModel()) def initializeBasket(self): waitCursor() self.basket.setModel(self.packageList.model().sourceModel()) restoreCursor() def initializePackageList(self): self.packageList.model().reset() self.packageList.setPackages(self.state.packages()) if self.completer: self.completer.deleteLater() del self.completer self.completer = QCompleter(self.state.packages(), self) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.searchLine.setCompleter(self.completer) def selectComponent(self, component): if not self.state.iface.operationInProgress(): if self.basket.isVisible(): self.basket._hide() self.stateTab.setCurrentIndex(1) self.switchState(self.state.INSTALL) if component in self.groupList._list: self.groupList.setCurrentItem(self.groupList._list[component]) self.groupFilter() def updateSettings(self): self.packageList.showComponents = PMConfig().showComponents() self.packageList.showIsA = PMConfig().showIsA() self.packageList.setFocus() def searchLineChanged(self, text): self.searchButton.setEnabled(bool(text)) if text == '': self.searchActivated() def statusUpdated(self): if self.statusUpdater.needsUpdate: self.statusUpdater.needsUpdate = False self.statusChanged() def statusChanged(self): self.setActionEnabled() if self.statusUpdater.isRunning(): self.statusUpdater.needsUpdate = True else: self.emit(SIGNAL("updatingStatus()")) self.statusUpdater.start() def initializeGroupList(self): self.groupList.clear() self.groupList._list = {} self.groupList.setAlternatingRowColors(False) self.groupList.setIconSize(QSize(32, 32)) self.groupList.setState(self.state) self.groupList.addGroups(self.state.groups()) if self.state.state == self.state.UPGRADE: self.typeCombo.show() else: self.typeCombo.hide() self.state._typeFilter = 'normal' self.groupFilter() def packageFilter(self, text): self.packageList.model().setFilterRole(Qt.DisplayRole) self.packageList.model().setFilterRegExp(QRegExp(unicode(text), Qt.CaseInsensitive, QRegExp.FixedString)) def typeFilter(self, index): if self.state.state == self.state.UPGRADE: filter = self.typeCombo.itemData(index).toString() if not self.state._typeFilter == filter: self.state._typeFilter = filter self.initializeGroupList() def groupFilter(self): waitCursor() self.packageList.resetMoreInfoRow() packages = self.state.groupPackages(self.groupList.currentGroup()) self.packageList.model().setFilterRole(GroupRole) self.packageList.model().setFilterPackages(packages) self.packageList.scrollToTop() self.packageList.select_all.setChecked(self.groupList.currentGroup() in self._selectedGroups) restoreCursor() def searchActivated(self): if self.currentState == self.state.UPGRADE: if self.groupList.count() == 0 and not self.searchUsed: return if not self.searchLine.text() == '': self.pdsMessageBox.showMessage(i18n("Searching..."), busy = True) self.groupList.lastSelected = None self._searchThread.start() self.searchUsed = True else: self.state.cached_packages = None self.state.packages() self.searchUsed = False self.searchFinished() def searchFinished(self): if self.state.cached_packages == []: self.pdsMessageBox.showMessage(i18n("No results found."), "dialog-information") else: self.pdsMessageBox.hideMessage() self.initializeGroupList() def startSearch(self): searchText = str(self.searchLine.text()).split() sourceModel = self.packageList.model().sourceModel() self.state.cached_packages = sourceModel.search(searchText) def setActionButton(self): self.actionButton.setEnabled(False) if self.state.state == self.state.ALL: menu = QMenu(self.actionButton) self.__install_action = menu.addAction(self.state.getActionIcon(self.state.INSTALL), self.state.getActionName(self.state.INSTALL), self.showBasket) self.__remove_action = menu.addAction(self.state.getActionIcon(self.state.REMOVE), self.state.getActionName(self.state.REMOVE), self.showBasket) self.actionButton.setMenu(menu) else: self.actionButton.setMenu(None) self.actionButton.setIcon(self.state.getActionIcon()) self.actionButton.setText(self.state.getActionName()) def actionStarted(self, operation): self.pdsMessageBox.hideMessage() self.progressDialog.reset() if not operation in ["System.Manager.updateRepository", "System.Manager.updateAllRepositories"]: totalPackages = self.packageList.packageCount() extraPackages = self.packageList.extraPackagesCount() self.operation.setTotalPackages(totalPackages) self.operation.setExtraPackages(extraPackages) self.progressDialog.updateStatus(0, totalPackages, self.state.toBe()) if self.isVisible(): if operation in ["System.Manager.updateRepository", "System.Manager.updateAllRepositories"]: self.progressDialog.repoOperationView() if self.basket.isVisible(): self.basket._hide() QTimer.singleShot(0, self.progressDialog._show) else: self.progressDialog._show() if not self._started: self.progressDialog.disableCancel() else: self.progressDialog.enableCancel() def actionFinished(self, operation): if operation in ("System.Manager.installPackage", "System.Manager.removePackage", "System.Manager.updatePackage"): self.notifyFinished() if operation == "System.Manager.installPackage" and self._started: self.summaryDialog.setDesktopFiles(self.operation.desktopFiles) self.summaryDialog.showSummary() if operation in ("System.Manager.updateRepository", "System.Manager.updateAllRepositories"): self.emit(SIGNAL("repositoriesUpdated()")) self.searchLine.clear() self.state.reset() self.progressDialog._hide() if not self.currentState == self.state.UPGRADE: self.switchState(self.currentState) self.initialize() def actionCancelled(self): self.progressDialog._hide() self.progressDialog.reset() self.switchState(self.currentState) self.groupFilter() def setActionEnabled(self): enabled = self.packageList.isSelected() self.actionButton.setEnabled(enabled) self.basket.setActionEnabled(enabled) def switchState(self, state): self.pdsMessageBox.hideMessage(force = True) self._states[state][1].setChecked(True) self.state.setState(state) self.currentState = state self._selectedGroups = [] if not state == self.state.HISTORY: self.setActionButton() self.state.cached_packages = None if state == self.state.UPGRADE or (state == self.state.INSTALL and self.groupList.count() == 1): if not self._updatesCheckedOnce: self._updatesCheckedOnce = self.state.updateRepoAction(silence = True) self.checkUpdatesButton.setHidden(not state == self.state.UPGRADE) self.initialize() # self.contentHistory.hide() self.content.show() # else: # self.contentHistory.show() # self.content.hide() def emitStatusBarInfo(self, packages, packagesSize, extraPackages, extraPackagesSize): self.emit(SIGNAL("selectionStatusChanged(QString)"), self.state.statusText(packages, packagesSize, extraPackages, extraPackagesSize)) def setSelectAll(self, packages=None): if packages: self.packageList.reverseSelection(packages) def setReverseAll(self, packages=None): if packages: self.packageList.selectAll(packages) def toggleSelectAll(self, toggled): self._last_packages = self.packageList.model().getFilteredPackages() if toggled: if self.groupList.currentGroup() not in self._selectedGroups: self._selectedGroups.append(self.groupList.currentGroup()) self.setReverseAll(self._last_packages) else: if self.groupList.currentGroup() in self._selectedGroups: self._selectedGroups.remove(self.groupList.currentGroup()) self.setSelectAll(self._last_packages) # A hacky solution to repaint the list to take care of selection changes # FIXME Later self.packageList.setFocus() self.statusChanged() def showBasket(self): if self.basket.isVisible(): return waitCursor() self.statusUpdater.wait() if self.currentState == self.state.ALL: action = {self.__remove_action:self.state.REMOVE, self.__install_action:self.state.INSTALL}.get(self.sender(), self.state.INSTALL) if action: if action == self.state.REMOVE: installed_packages = self.state.iface.getInstalledPackages() filtered_packages = filter(lambda x: x not in installed_packages, self.basket.model.selectedPackages()) if filtered_packages == self.basket.model.selectedPackages(): restoreCursor() QMessageBox(i18n("Select packages"), i18n("You must select at least one installed package"), QMessageBox.Information, QMessageBox.Ok, 0, 0).exec_() return self.packageList.model().sourceModel().selectPackages(filtered_packages, state = False) self.state.state = action self.basket._show() restoreCursor() def showMoreWidgets(self): if self.morewidgets.isVisible(): return waitCursor() self.morewidgets._show() restoreCursor() def showWebdialog(self): packageName = str(unicode(self.morewidgets.randomPackageList.currentItem().text())) liste = [] liste.append(packageName) print liste waitCursor() self.morewidgets._hide() #self.webdialog._show() restoreCursor() #self.packageList.setPackages(liste) self.packageList.selectAll(liste) #self.packageList.setItemDelegate(PackageDelegate(self, self, showDetailsButton=True)) #self.packageList.setColumnWidth(0, 32) self.operation = OperationManager(self.state) reinstall = False answer = True actions = self.state.checkInstallActions(liste) if actions: answer = askForActions(actions, i18n("Selected packages are already installed.<br>" "If you continue, the packages will be reinstalled"), i18n("Already Installed Packages"), i18n("Installed Packages")) if not answer: self.initializePackageList() self.initializeBasket() self.initializeStatusUpdater() self.state.state = self.parent.cw.currentState self.parent.cw.initialize() return if actions: reinstall = True if reinstall == False: self.initializeStatusUpdater() self.initializeBasket() self.statusUpdated() self.showBasket() self.initializeBasket() self.initializeStatusUpdater() def initializeUpdateTypeList(self): self.typeCombo.clear() UPDATE_TYPES = [['normal', i18n('All Updates'), 'system-software-update'], ['security', i18n('Security Updates'), 'security-medium'], ['critical', i18n('Critical Updates'), 'security-low']] for type in UPDATE_TYPES: self.typeCombo.addItem(KIcon(type[2]), type[1], QVariant(type[0]))
class Main(plugin.Plugin): " Main Class " def initialize(self, *args, **kwargs): " Init Main Class " ec = ExplorerContainer() super(Main, self).initialize(*args, **kwargs) # directory auto completer self.completer, self.dirs = QCompleter(self), QDirModel(self) self.dirs.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot) self.completer.setModel(self.dirs) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setCompletionMode(QCompleter.PopupCompletion) self.RUNS, self.FAILS = 0, 0 self.group0 = QGroupBox() self.group0.setTitle(' Source and Target ') self.baseurl = QLineEdit('http://google.com') self.outfile = QLineEdit(path.join(path.expanduser("~"), 'test.py')) self.outfile.setCompleter(self.completer) self.open = QPushButton(QIcon.fromTheme("folder-open"), 'Open') self.open.clicked.connect(lambda: self.outfile.setText( QFileDialog.getSaveFileName(self.dock, "Save", path.expanduser( "~"), 'PYTHON(*.py)'))) vboxg0 = QVBoxLayout(self.group0) for each_widget in (QLabel('<b>Base URL'), self.baseurl, QLabel('<b>Local File Target'), self.outfile, self.open): vboxg0.addWidget(each_widget) self.group1 = QGroupBox() self.group1.setTitle(' Selenium ') self.group1.setCheckable(True) self.group1.setGraphicsEffect(QGraphicsBlurEffect(self)) self.group1.graphicsEffect().setEnabled(False) self.group1.toggled.connect(self.toggle_group) self.ckcss1 = QCheckBox('Test for correct Page Loading behaviour') self.ckcss2 = QCheckBox('Test for Sucessfull Status Code return') self.ckcss3 = QCheckBox('Test for valid Title of the web page') self.ckcss4 = QCheckBox('Test for Cookies Basic functionality') self.ckcss5 = QCheckBox('Test for Back, Forward, Reload behaviour') self.ckcss6 = QCheckBox('Take a Screenshot of page (CSS Debug)') self.ckcss7 = QCheckBox('Test for Search Form Field of the page') self.ckcss8 = QCheckBox( 'Test for Arbitrary Javascript (User provided)') self.ckcss9 = QCheckBox('Test for iFrame of the web page') self.ckcss10 = QCheckBox('Test for HTML5 Canvas element on the page') self.ckcss11 = QCheckBox('Test for HTML5 SVG element on the page') self.ckcss12 = QCheckBox('Test for HTML5 Audio element on the page') self.ckcss13 = QCheckBox('Test for HTML5 Video element on the page') self.ckcss14 = QCheckBox('Test for File Upload form on the page') self.ckcss15 = QCheckBox('Add ChromeDriver path to sys.path') self.webdriver = QComboBox() self.webdriver.addItems( ['firefox', 'chrome', 'zope.testbrowser', 'phantomjs']) self.titletxt = QLineEdit('Google') self.javascript = QLineEdit('console.log("test")') self.authdata, self.formdata = QLineEdit(), QLineEdit() self.authdata.setPlaceholderText( "{'username':'******','password':'******'}") self.formdata.setPlaceholderText("{'name': 'Joe', 'age': '25'}") self.iframurl = QLineEdit() self.chrmedrv = QLineEdit('/usr/bin/chromedriver') self.timeout = QSpinBox() self.timeout.setMaximum(99) self.timeout.setMinimum(0) self.timeout.setValue(9) vboxg1 = QVBoxLayout(self.group1) for each_widget in ( self.ckcss1, self.ckcss2, self.ckcss3, self.ckcss4, self.ckcss5, self.ckcss6, self.ckcss7, self.ckcss8, self.ckcss9, self.ckcss10, self.ckcss11, self.ckcss12, self.ckcss13, self.ckcss14, self.ckcss15, QLabel('<b>WebDriver'), self.webdriver, QLabel('''<center><small><i>Firefox is only Driver that dont require additional configuration'''), QLabel('<b>Title Content must contain'), self.titletxt, QLabel('<b>Minified Javascript for Test'), self.javascript, QLabel('<b>Arbitrary Authentication Data for Test'), self.authdata, QLabel('<b>Arbitrary Form Data for Test'), self.formdata, QLabel('<b>iFrame URL for Test'), self.iframurl, QLabel('<b>Chrome Driver'), self.chrmedrv, QLabel('<b>Timeout Timer Limit'), self.timeout): vboxg1.addWidget(each_widget) try: each_widget.setToolTip(each_widget.text()) except: each_widget.setToolTip(each_widget.currentText()) self.group4 = QGroupBox() self.group4.setTitle(' General ') self.chckbx1 = QCheckBox('Run the Tests after Writing') self.chckbx2 = QCheckBox('Open the Tests with Ninja after Writing') self.chckbx3 = QCheckBox('Add SheBang, Encoding and Metadata to Tests') self.nice = QSpinBox() self.nice.setMaximum(20) self.nice.setMinimum(0) self.nice.setValue(20) self.help1 = QLabel( '''<a href="http://splinter.cobrateam.info/docs/api" ><center><b>API Reference</a>''') self.help1.setTextInteractionFlags(Qt.LinksAccessibleByMouse) self.help1.setOpenExternalLinks(True) vboxg4 = QVBoxLayout(self.group4) for each_widget in (self.chckbx1, self.chckbx2, self.chckbx3, QLabel('Backend CPU priority:'), self.nice, self.help1): vboxg4.addWidget(each_widget) each_widget.setToolTip(each_widget.text()) [ a.setChecked(True) for a in (self.ckcss1, self.ckcss2, self.ckcss3, self.ckcss4, self.ckcss5, self.ckcss6, self.ckcss7, self.ckcss8, self.ckcss15, self.chckbx1, self.chckbx2, self.chckbx3) ] self.button = QPushButton(QIcon.fromTheme("face-cool"), 'Write and Run Test') self.button.setCursor(QCursor(Qt.PointingHandCursor)) self.button.setMinimumSize(100, 50) self.button.clicked.connect(self.run) glow = QGraphicsDropShadowEffect(self) glow.setOffset(0) glow.setBlurRadius(99) glow.setColor(QColor(99, 255, 255)) self.button.setGraphicsEffect(glow) glow.setEnabled(True) self.output = QPlainTextEdit() self.runs = QLabel('<font color="green"><b>Runs: 0') self.failures = QLabel('<font color="red"><b>Failures: 0') class TransientWidget(QWidget): ' persistant widget thingy ' def __init__(self, widget_list): ' init sub class ' super(TransientWidget, self).__init__() vbox = QVBoxLayout(self) for each_widget in widget_list: vbox.addWidget(each_widget) tw = TransientWidget( (QLabel('<b>Selenium Tests'), self.group0, self.group1, self.group4, QLabel('<b>Log'), self.output, self.runs, self.failures, self.button)) self.scrollable, self.dock = QScrollArea(), QDockWidget() self.scrollable.setWidgetResizable(True) self.scrollable.setWidget(tw) self.dock.setWindowTitle(__doc__) self.dock.setStyleSheet('QDockWidget::title{text-align: center;}') self.dock.setWidget(self.scrollable) ec.addTab(self.dock, "Selenium") QPushButton( QIcon.fromTheme("help-about"), 'About', self.dock).clicked.connect( lambda: QMessageBox.information(self.dock, __doc__, HELPMSG)) QPushButton( QIcon.fromTheme("media-record"), 'Record', self.group1, ).clicked.connect(lambda: QMessageBox.information( self.dock, __doc__, 'Not working. If you know how to make it Record, send me Pull Request' )) def run(self): ' run ' self.RUNS = self.RUNS + 1 self.runs.setText('<font color="green"><b>Runs: {}'.format(self.RUNS)) self.output.clear() self.output.append(self.formatInfoMsg('INFO:{}'.format( datetime.now()))) self.button.setDisabled(True) self.output.append(self.formatInfoMsg(' INFO: OK: Parsing Data ')) selenium_test = SELENIUM_TEMPLATE.format( HEADER if self.chckbx3.isChecked() is True else '', self.chrmedrv.text() if self.ckcss15.isChecked() is True else '', self.baseurl.text(), self.authdata.text() if str(self.authdata.text()) is not '' else {}, self.formdata.text() if str( self.formdata.text()) is not '' else {}, self.iframurl.text(), self.javascript.text(), self.titletxt.text(), self.webdriver.currentText(), '# ' if self.ckcss1.isChecked() is not True else '', '# ' if self.ckcss2.isChecked() is not True else '', '# ' if self.ckcss2.isChecked() is not True else '', '# ' if self.ckcss3.isChecked() is not True else '', '# ' if self.ckcss4.isChecked() is not True else '', '# ' if self.ckcss5.isChecked() is not True else '', '# ' if self.ckcss6.isChecked() is not True else '', '# ' if self.ckcss7.isChecked() is not True else '', '# ' if self.ckcss8.isChecked() is not True else '', '# ' if self.ckcss9.isChecked() is not True else '', '# ' if self.ckcss10.isChecked() is not True else '', '# ' if self.ckcss11.isChecked() is not True else '', '# ' if self.ckcss12.isChecked() is not True else '', '# ' if self.ckcss13.isChecked() is not True else '', '# ' if self.ckcss14.isChecked() is not True else '', self.timeout.value()) with open(path.abspath(self.outfile.text()), 'w') as f: self.output.append(self.formatInfoMsg(' INFO: OK: Writing Tests ')) f.write(selenium_test) if self.chckbx2.isChecked() is True: self.output.append(self.formatInfoMsg(' INFO: OK: Opening Tests ')) try: startfile(str(path.abspath(self.outfile.text()))) except: Popen(["ninja-ide", str(path.abspath(self.outfile.text()))]) if self.chckbx1.isChecked() is True: try: self.output.append( self.formatInfoMsg('INFO: OK: Runing Tests')) Popen(["python", str(path.abspath(self.outfile.text()))]) except: self.output.append( self.formatErrorMsg('INFO:FAIL: Tests Fail')) self.FAILS = self.FAILS + 1 self.failures.setText( '<font color="red"><b>Failures: {}'.format(self.FAILS)) self.output.append(self.formatInfoMsg('INFO:{}'.format( datetime.now()))) self.button.setDisabled(False) self.output.setFocus() self.output.selectAll() def toggle_group(self): ' toggle on or off the css checkboxes ' if self.group1.isChecked() is True: [ a.setChecked(True) for a in (self.ckcss1, self.ckcss2, self.ckcss3, self.ckcss4, self.ckcss5, self.ckcss6, self.ckcss7, self.ckcss8, self.ckcss15) ] self.group1.graphicsEffect().setEnabled(False) else: [ a.setChecked(False) for a in (self.ckcss1, self.ckcss2, self.ckcss3, self.ckcss4, self.ckcss5, self.ckcss6, self.ckcss7, self.ckcss8, self.ckcss15) ] self.group1.graphicsEffect().setEnabled(True) def formatErrorMsg(self, msg): """Format error messages in red color""" return self.formatMsg(msg, 'red') def formatInfoMsg(self, msg): """Format informative messages in blue color""" return self.formatMsg(msg, 'green') def formatMsg(self, msg, color): """Format message with the given color""" return '<font color="{}">{}</font>'.format(color, msg)
class TalkEditorApp(FreeseerApp): '''Freeseer talk database editor main gui class''' def __init__(self, config, db): FreeseerApp.__init__(self) self.config = config self.db = db icon = QIcon() icon.addPixmap(QPixmap(':/freeseer/logo.png'), QIcon.Normal, QIcon.Off) self.setWindowIcon(icon) self.resize(960, 600) # # Setup Layout # self.mainWidget = QWidget() self.mainLayout = QVBoxLayout() self.mainWidget.setLayout(self.mainLayout) self.setCentralWidget(self.mainWidget) self.mainLayout.setAlignment(Qt.AlignTop) # Add custom widgets self.commandButtons = CommandButtons() self.tableView = QTableView() self.tableView.setSortingEnabled(True) self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows) self.talkDetailsWidget = TalkDetailsWidget() self.importTalksWidget = ImportTalksWidget() self.newTalkWidget = NewTalkWidget() self.mainLayout.addWidget(self.importTalksWidget) #self.mainLayout.addLayout(self.titleLayout) self.mainLayout.addWidget(self.commandButtons) self.mainLayout.addWidget(self.tableView) self.mainLayout.addWidget(self.talkDetailsWidget) self.mainLayout.addWidget(self.importTalksWidget) # --- End Layout # Initialize geometry, to be used for restoring window positioning. self.geometry = None # # Setup Menubar # self.actionExportCsv = QAction(self) self.actionExportCsv.setObjectName('actionExportCsv') self.actionRemoveAll = QAction(self) self.actionRemoveAll.setObjectName('actionRemoveAll') # Actions self.menuFile.insertAction(self.actionExit, self.actionExportCsv) self.menuFile.insertAction(self.actionExit, self.actionRemoveAll) # --- End Menubar # # TableView Connections # self.connect(self.tableView, SIGNAL('activated(const QModelIndex)'), self.talk_selected) self.connect(self.tableView, SIGNAL('selected(const QModelIndex)'), self.talk_selected) self.connect(self.tableView, SIGNAL('clicked(const QModelIndex)'), self.talk_selected) # Import Widget self.connect(self.importTalksWidget.csvRadioButton, SIGNAL('toggled(bool)'), self.toggle_import) self.connect(self.importTalksWidget.importButton, SIGNAL('clicked()'), self.import_talks) self.connect(self.importTalksWidget.cancelButton, SIGNAL('clicked()'), self.hide_import_talks_widget) self.importTalksWidget.setHidden(True) self.connect(self.importTalksWidget.csvFileSelectButton, SIGNAL('clicked()'), self.csv_file_select) self.connect(self.importTalksWidget.csvLineEdit, SIGNAL('returnPressed()'), self.importTalksWidget.importButton.click) self.connect(self.importTalksWidget.rssLineEdit, SIGNAL('returnPressed()'), self.importTalksWidget.importButton.click) self.connect(self.actionExportCsv, SIGNAL('triggered()'), self.export_talks_to_csv) self.connect(self.actionRemoveAll, SIGNAL('triggered()'), self.confirm_reset) # Command Buttons self.connect(self.commandButtons.addButton, SIGNAL('clicked()'), self.show_new_talk_popup) self.connect(self.commandButtons.removeButton, SIGNAL('clicked()'), self.remove_talk) self.connect(self.commandButtons.removeAllButton, SIGNAL('clicked()'), self.confirm_reset) self.connect(self.commandButtons.importButton, SIGNAL('clicked()'), self.show_import_talks_widget) self.connect(self.commandButtons.exportButton, SIGNAL('clicked()'), self.export_talks_to_csv) self.connect(self.commandButtons.searchButton, SIGNAL('clicked()'), self.search_talks) self.connect(self.commandButtons.searchLineEdit, SIGNAL('textEdited(QString)'), self.search_talks) self.connect(self.commandButtons.searchLineEdit, SIGNAL('returnPressed()'), self.search_talks) # Talk Details Buttons self.connect(self.talkDetailsWidget.saveButton, SIGNAL('clicked()'), self.update_talk) # Talk Details Widget self.connect(self.talkDetailsWidget.titleLineEdit, SIGNAL('textEdited(const QString)'), self.enable_save) self.connect(self.talkDetailsWidget.presenterLineEdit, SIGNAL('textEdited(const QString)'), self.enable_save) self.connect(self.talkDetailsWidget.categoryLineEdit, SIGNAL('textEdited(const QString)'), self.enable_save) self.connect(self.talkDetailsWidget.eventLineEdit, SIGNAL('textEdited(const QString)'), self.enable_save) self.connect(self.talkDetailsWidget.roomLineEdit, SIGNAL('textEdited(const QString)'), self.enable_save) self.connect(self.talkDetailsWidget.descriptionTextEdit, SIGNAL('modificationChanged(bool)'), self.enable_save) self.connect(self.talkDetailsWidget.dateEdit, SIGNAL('dateChanged(const QDate)'), self.enable_save) self.connect(self.talkDetailsWidget.startTimeEdit, SIGNAL('timeChanged(const QTime)'), self.enable_save) self.connect(self.talkDetailsWidget.endTimeEdit, SIGNAL('timeChanged(const QTime)'), self.enable_save) # New Talk Widget self.newTalkWidget.connect(self.newTalkWidget.addButton, SIGNAL('clicked()'), self.add_talk) self.newTalkWidget.connect(self.newTalkWidget.cancelButton, SIGNAL('clicked()'), self.newTalkWidget.reject) # Load default language actions = self.menuLanguage.actions() for action in actions: if action.data().toString() == self.config.default_language: action.setChecked(True) self.translate(action) break # Load Talk Database self.load_presentations_model() # Setup Autocompletion self.update_autocomplete_fields() self.talkDetailsWidget.saveButton.setEnabled(False) # Select first item #self.tableView.setCurrentIndex(self.proxy.index(0,0)) #self.talk_selected(self.proxy.index(0,0)) # # Translation # def retranslate(self): self.setWindowTitle(self.app.translate("TalkEditorApp", "Freeseer Talk Editor")) # # Reusable Strings # self.confirmDBClearTitleString = self.app.translate("TalkEditorApp", "Remove All Talks from Database") self.confirmDBClearQuestionString = self.app.translate("TalkEditorApp", "Are you sure you want to clear the DB?") self.confirmTalkDetailsClearTitleString = self.app.translate("TalkEditorApp", "Unsaved Data") self.confirmTalkDetailsClearQuestionString = self.app.translate("TalkEditorApp", "Unsaved talk details will be lost. Continue?") # --- End Reusable Strings # # Menubar # self.actionExportCsv.setText(self.app.translate("TalkEditorApp", "&Export to CSV")) self.actionRemoveAll.setText(self.app.translate("TalkEditorApp", "&Remove All Talks")) # --- End Menubar # # TalkDetailsWidget # self.talkDetailsWidget.titleLabel.setText(self.app.translate("TalkEditorApp", "Title")) self.talkDetailsWidget.presenterLabel.setText(self.app.translate("TalkEditorApp", "Presenter")) self.talkDetailsWidget.categoryLabel.setText(self.app.translate("TalkEditorApp", "Category")) self.talkDetailsWidget.eventLabel.setText(self.app.translate("TalkEditorApp", "Event")) self.talkDetailsWidget.roomLabel.setText(self.app.translate("TalkEditorApp", "Room")) self.talkDetailsWidget.dateLabel.setText(self.app.translate("TalkEditorApp", "Date")) self.talkDetailsWidget.startTimeLabel.setText(self.app.translate("TalkEditorApp", "Start Time")) self.talkDetailsWidget.endTimeLabel.setText(self.app.translate("TalkEditorApp", "End Time")) # --- End TalkDetailsWidget # # Import Talks Widget Translations # self.importTalksWidget.rssRadioButton.setText(self.app.translate("TalkEditorApp", "RSS URL")) self.importTalksWidget.csvRadioButton.setText(self.app.translate("TalkEditorApp", "CSV File")) self.importTalksWidget.importButton.setText(self.app.translate("TalkEditorApp", "Import")) # --- End Talks Widget Translations # # Command Button Translations\ # self.commandButtons.importButton.setText(self.app.translate("TalkEditorApp", "Import")) self.commandButtons.exportButton.setText(self.app.translate("TalkEditorApp", "Export")) self.commandButtons.addButton.setText(self.app.translate("TalkEditorApp", "Add New Talk")) self.commandButtons.removeButton.setText(self.app.translate("TalkEditorApp", "Remove")) self.commandButtons.removeAllButton.setText(self.app.translate("TalkEditorApp", "Remove All")) # --- End Command Butotn Translations # # Search Widget Translations # self.commandButtons.searchButton.setText(self.app.translate("TalkEditorApp", "Search")) # --- End Command Button Translations def load_presentations_model(self): # Load Presentation Model self.presentationModel = self.db.get_presentations_model() self.proxy = QSortFilterProxyModel() self.proxy.setSourceModel(self.presentationModel) self.tableView.setModel(self.proxy) self.proxy.setFilterCaseSensitivity(Qt.CaseInsensitive) # Fill table whitespace. self.tableView.horizontalHeader().setStretchLastSection(False) self.tableView.horizontalHeader().setResizeMode(1, QHeaderView.Stretch) # Hide the ID field self.tableView.setColumnHidden(0, True) # Map data to widgets self.mapper = QDataWidgetMapper() self.mapper.setModel(self.proxy) self.mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit) self.mapper.addMapping(self.talkDetailsWidget.titleLineEdit, 1) self.mapper.addMapping(self.talkDetailsWidget.presenterLineEdit, 2) self.mapper.addMapping(self.talkDetailsWidget.categoryLineEdit, 4) self.mapper.addMapping(self.talkDetailsWidget.eventLineEdit, 5) self.mapper.addMapping(self.talkDetailsWidget.roomLineEdit, 6) self.mapper.addMapping(self.talkDetailsWidget.descriptionTextEdit, 3) self.mapper.addMapping(self.talkDetailsWidget.dateEdit, 7) self.mapper.addMapping(self.talkDetailsWidget.startTimeEdit, 8) self.mapper.addMapping(self.talkDetailsWidget.endTimeEdit, 9) # Load StringLists self.titleList = QStringList(self.db.get_string_list("Title")) #self.speakerList = QStringList(self.db.get_speaker_list()) #self.categoryList = QStringList(self.db.get_category_list()) #self.eventList = QStringList(self.db.get_event_list()) #self.roomList = QStringList(self.db.get_room_list()) #Disble input self.talkDetailsWidget.disable_input_fields() def search_talks(self): # The default value is 0. If the value is -1, the keys will be read from all columns. self.proxy.setFilterKeyColumn(-1) self.proxy.setFilterFixedString(self.commandButtons.searchLineEdit.text()) def talk_selected(self, model): self.mapper.setCurrentIndex(model.row()) self.talkDetailsWidget.enable_input_fields() self.talkDetailsWidget.saveButton.setEnabled(False) def toggle_import(self): if self.importTalksWidget.csvRadioButton.isChecked(): self.importTalksWidget.csvLineEdit.setEnabled(True) self.importTalksWidget.csvFileSelectButton.setEnabled(True) self.importTalksWidget.rssLineEdit.setEnabled(False) else: self.importTalksWidget.csvLineEdit.setEnabled(False) self.importTalksWidget.csvFileSelectButton.setEnabled(False) self.importTalksWidget.rssLineEdit.setEnabled(True) def show_import_talks_widget(self): self.commandButtons.setHidden(True) self.tableView.setHidden(True) self.talkDetailsWidget.setHidden(True) self.importTalksWidget.setHidden(False) def hide_import_talks_widget(self): self.commandButtons.setHidden(False) self.tableView.setHidden(False) self.talkDetailsWidget.setHidden(False) self.importTalksWidget.setHidden(True) def add_talk(self): """Adds a new talk to the database using data from the NewTalkWidget input fields""" presentation = self.create_presentation(self.newTalkWidget.talkDetailsWidget) if presentation: self.db.insert_presentation(presentation) self.newTalkWidget.accept() # Close the dialog def update_talk(self): """Updates the currently selected talk using data from the TalkEditorApp input fields""" selected_talk = self.tableView.currentIndex() if selected_talk.row() >= 0: # The tableView index begins at 0 and is -1 by default talk_id = selected_talk.sibling(selected_talk.row(), 0).data().toString() presentation = self.create_presentation(self.talkDetailsWidget) if presentation: self.db.update_presentation(talk_id, presentation) self.apply_changes(selected_talk) self.talkDetailsWidget.saveButton.setEnabled(False) def create_presentation(self, talkDetailsWidget): """Creates and returns an instance of Presentation using data from the input fields""" date = talkDetailsWidget.dateEdit.date() startTime = talkDetailsWidget.startTimeEdit.time() endTime = talkDetailsWidget.endTimeEdit.time() title = unicode(talkDetailsWidget.titleLineEdit.text()).strip() if title: return Presentation( unicode(talkDetailsWidget.titleLineEdit.text()).strip(), unicode(talkDetailsWidget.presenterLineEdit.text()).strip(), unicode(talkDetailsWidget.descriptionTextEdit.toPlainText()).strip(), unicode(talkDetailsWidget.categoryLineEdit.text()).strip(), unicode(talkDetailsWidget.eventLineEdit.text()).strip(), unicode(talkDetailsWidget.roomLineEdit.text()).strip(), unicode(date.toString(Qt.ISODate)), unicode(startTime.toString(Qt.ISODate)), unicode(endTime.toString(Qt.ISODate))) def show_new_talk_popup(self): """Displays a modal dialog with a talk details view When Add is selected, a new talk is added to the database using the input field data. When Cancel is selected, no talk is added. """ log.info('Opening Add Talk window...') self.clear_new_talk_fields() self.remove_new_talk_placeholder_text() self.newTalkWidget.talkDetailsWidget.titleLineEdit.setFocus() if self.newTalkWidget.exec_() == 1: self.apply_changes() self.talkDetailsWidget.disable_input_fields() else: log.info('No talk added...') def apply_changes(self, updated_talk=None): """Repopulates the model to display the effective changes Updates the autocomplete fields. Displays the updated model in the table view, and selects the newly updated/added talk. """ self.presentationModel.select() self.select_talk(updated_talk) self.update_autocomplete_fields() def select_talk(self, talk=None): """Selects the given talk in the table view If no talk is given, the last row in the table view is selected. """ if talk: row = talk.row() column = talk.column() else: row = self.presentationModel.rowCount() - 1 # Select last row column = 0 self.tableView.selectRow(row) self.tableView.setCurrentIndex(self.proxy.index(row, column)) self.talk_selected(self.proxy.index(row, column)) def remove_talk(self): try: rows_selected = self.tableView.selectionModel().selectedRows() except: return # Reversed because rows in list change position once row is removed for row in reversed(rows_selected): self.presentationModel.removeRow(row.row()) def load_talk(self): try: self.tableView.currentIndex().row() except: return self.mapper.addMapping(self.talkDetailsWidget.roomLineEdit, 6) self.presentationModel.select() def reset(self): self.db.clear_database() self.presentationModel.select() def confirm_reset(self): """Presents a confirmation dialog to ask the user if they are sure they wish to remove the talk database. If Yes call the reset() function""" confirm = QMessageBox.question(self, self.confirmDBClearTitleString, self.confirmDBClearQuestionString, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if confirm == QMessageBox.Yes: self.reset() def add_talks_from_rss(self): rss_url = unicode(self.importTalksWidget.rssLineEdit.text()) if rss_url: self.db.add_talks_from_rss(rss_url) self.presentationModel.select() self.hide_import_talks_widget() else: error = QMessageBox() error.setText("Please enter a RSS URL") error.exec_() def closeEvent(self, event): log.info('Exiting talk database editor...') self.geometry = self.saveGeometry() event.accept() def csv_file_select(self): fname = QFileDialog.getOpenFileName( self, 'Select file', "", "*.csv") if fname: self.importTalksWidget.csvLineEdit.setText(fname) def add_talks_from_csv(self): fname = self.importTalksWidget.csvLineEdit.text() if fname: self.db.add_talks_from_csv(fname) self.presentationModel.select() self.hide_import_talks_widget() else: error = QMessageBox() error.setText("Please select a file") error.exec_() def import_talks(self): if self.importTalksWidget.csvRadioButton.isChecked(): self.add_talks_from_csv() else: self.add_talks_from_rss() self.update_autocomplete_fields() def export_talks_to_csv(self): fname = QFileDialog.getSaveFileName(self, 'Select file', "", "*.csv") if fname: self.db.export_talks_to_csv(fname) def update_autocomplete_fields(self): self.titleList = QStringList(self.db.get_string_list("Title")) self.speakerList = QStringList(self.db.get_string_list("Speaker")) self.categoryList = QStringList(self.db.get_string_list("Category")) self.eventList = QStringList(self.db.get_string_list("Event")) self.roomList = QStringList(self.db.get_string_list("Room")) self.titleCompleter = QCompleter(self.titleList) self.titleCompleter.setCaseSensitivity(Qt.CaseInsensitive) self.speakerCompleter = QCompleter(self.speakerList) self.speakerCompleter.setCaseSensitivity(Qt.CaseInsensitive) self.categoryCompleter = QCompleter(self.categoryList) self.categoryCompleter.setCaseSensitivity(Qt.CaseInsensitive) self.eventCompleter = QCompleter(self.eventList) self.eventCompleter.setCaseSensitivity(Qt.CaseInsensitive) self.roomCompleter = QCompleter(self.roomList) self.roomCompleter.setCaseSensitivity(Qt.CaseInsensitive) self.talkDetailsWidget.titleLineEdit.setCompleter(self.titleCompleter) self.talkDetailsWidget.presenterLineEdit.setCompleter(self.speakerCompleter) self.talkDetailsWidget.categoryLineEdit.setCompleter(self.categoryCompleter) self.talkDetailsWidget.eventLineEdit.setCompleter(self.eventCompleter) self.talkDetailsWidget.roomLineEdit.setCompleter(self.roomCompleter) def are_fields_enabled(self): return (self.talkDetailsWidget.titleLineEdit.isEnabled() and self.talkDetailsWidget.presenterLineEdit.isEnabled() and self.talkDetailsWidget.categoryLineEdit.isEnabled() and self.talkDetailsWidget.eventLineEdit.isEnabled() and self.talkDetailsWidget.roomLineEdit.isEnabled() and self.talkDetailsWidget.dateEdit.isEnabled() and self.talkDetailsWidget.startTimeEdit.isEnabled() and self.talkDetailsWidget.endTimeEdit.isEnabled()) def unsaved_details_exist(self): """Checks if changes have been made to new/existing talk details Looks for text in the input fields and check the enabled state of the Save Talk button If the Save Talk button is enabled, the input fields contain modified values """ return (self.talkDetailsWidget.saveButton.isEnabled() and (self.talkDetailsWidget.titleLineEdit.text() or self.talkDetailsWidget.presenterLineEdit.text() or self.talkDetailsWidget.categoryLineEdit.text() or self.talkDetailsWidget.descriptionTextEdit.toPlainText())) def enable_save(self): self.talkDetailsWidget.saveButton.setEnabled(True) def clear_new_talk_fields(self): """Removes existing data from all NewTalkWidget fields except event, room, date and time""" self.newTalkWidget.talkDetailsWidget.titleLineEdit.clear() self.newTalkWidget.talkDetailsWidget.presenterLineEdit.clear() self.newTalkWidget.talkDetailsWidget.descriptionTextEdit.clear() self.newTalkWidget.talkDetailsWidget.categoryLineEdit.clear() def remove_new_talk_placeholder_text(self): """Removes placeholder text in NewTalkWidget originally set by TalkDetailsWidget""" self.newTalkWidget.talkDetailsWidget.titleLineEdit.setPlaceholderText("") self.newTalkWidget.talkDetailsWidget.presenterLineEdit.setPlaceholderText("") self.newTalkWidget.talkDetailsWidget.categoryLineEdit.setPlaceholderText("") self.newTalkWidget.talkDetailsWidget.eventLineEdit.setPlaceholderText("") self.newTalkWidget.talkDetailsWidget.roomLineEdit.setPlaceholderText("")
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 FrmFactura( Base, Ui_frmFactura ): """ Implementacion de la interfaz grafica para facturas """ web = "facturas.php?doc=" def __init__( self, parent ): ''' Constructor ''' super( FrmFactura, self ).__init__( parent ) self.readOnly = True self.recibo = None self.clientesModel = QSqlQueryModel() # las acciones deberian de estar ocultas self.actionSave.setVisible( False ) self.actionCancel.setVisible( False ) # El modelo principal self.navmodel = QSqlQueryModel( self ) # El modelo que filtra a self.navmodel self.navproxymodel = QSortFilterProxyModel( self ) self.navproxymodel.setSourceModel( self.navmodel ) self.navproxymodel.setFilterKeyColumn( -1 ) self.navproxymodel.setFilterCaseSensitivity ( Qt.CaseInsensitive ) # Este es el modelo con los datos de la con los detalles self.detailsmodel = QSqlQueryModel( self ) self.detailsproxymodel = QSortFilterProxyModel( self ) self.detailsproxymodel.setSourceModel( self.detailsmodel ) #inicializando el documento self.editmodel = None self.lblanulado.setHidden( True ) self.toolBar.removeAction( self.actionAnular ) self.toolBar.addAction( self.actionAnular ) self.recibo = None self.cargarRecibos() self.existenciaModel = QSqlQueryModel() self.vendedoresModel = QSqlQueryModel() self.bodegasModel = QSqlQueryModel() self.anulable = 2 """ @ivar: Si la factura actual se puede anular o no @type: int """ self.tabledetails.setOrder( 1, 3 ) self.completer = QCompleter() self.completerVendedor = QCompleter() QTimer.singleShot( 0, self.loadModels ) def cargarRecibos( self ): self.recibo = FrmRecibo( self ) #dlgRecibo( self, True ) self.recibo.setWindowModality( Qt.WindowModal ) self.recibo.setWindowFlags( Qt.Dialog ) self.recibo.actionNew.setVisible( False ) def cancel( self ): """ Aca se cancela la edición del documento """ self.editmodel = None self.tablenavigation.setModel( self.navproxymodel ) self.tabledetails.setModel( self.detailsproxymodel ) self.readOnly = True self.status = True def newDocument( self ): """ activar todos los controles, llenar los modelos necesarios, crear el modelo FacturaModel, aniadir una linea a la tabla """ self.readOnly = False if not self.updateEditModels(): return self.status = False self.dtPicker.setDate( self.parentWindow.datosSesion.fecha ) def updateEditModels( self ): """ Este metodo actualiza los modelos usados en el modo edición """ resultado = False try: if not self.database.isOpen(): if not self.database.open(): raise UserWarning( u"No se pudo abrir la conexión "\ + "con la base de datos" ) self.editmodel = FacturaModel( self.parentWindow.datosSesion ) # Cargar el numero de la factura actual query = QSqlQuery( """ SELECT fnConsecutivo(%d,NULL); """ % constantes.IDFACTURA ) if not query.exec_(): raise Exception( "No se pudo obtener el numero de la factura" ) query.first() n = query.value( 0 ).toString() self.editmodel.printedDocumentNumber = n self.clientesModel.setQuery( """ SELECT idpersona , nombre AS cliente FROM personas WHERE tipopersona = %d """ % constantes.CLIENTE ) if self.clientesModel.rowCount() == 0: raise UserWarning( "No existen clientes en la"\ + " base de datos" ) return # Rellenar el combobox de los vendedores self.vendedoresModel.setQuery( """ SELECT idpersona, nombre AS Vendedor FROM personas WHERE tipopersona = %d """ % constantes.VENDEDOR ) #Verificar si existen clientes if self.vendedoresModel.rowCount() == 0: raise UserWarning( "No existen vendedores en la "\ + "base de datos" ) #Crear el delegado con los articulo y verificar si existen articulos self.existenciaModel.setQuery( QSqlQuery( """ SELECT idarticulo, descripcion, precio, ROUND(costo,4) as costo, Existencia, idbodega FROM vw_articulosenbodegas WHERE existencia >0 """ ) ) self.proxyexistenciaModel = SingleSelectionModel() self.proxyexistenciaModel.setSourceModel( self.existenciaModel ) self.proxyexistenciaModel.setFilterKeyColumn( IDBODEGAEX ) if self.proxyexistenciaModel.rowCount() == 0: raise UserWarning( "No hay articulos en bodega" ) delegate = FacturaDelegate( self.proxyexistenciaModel ) # Rellenar el combobox de las BODEGAS self.bodegasModel.setQuery( """ SELECT b.idbodega, b.nombrebodega as Bodega FROM bodegas b JOIN documentos d ON b.idbodega=d.idbodega JOIN docpadrehijos ph ON ph.idpadre =d.iddocumento JOIN documentos k ON ph.idhijo = k.iddocumento AND k.idtipodoc = %d JOIN articulosxdocumento ad ON ad.iddocumento=d.iddocumento GROUP BY b.idbodega HAVING SUM(ad.unidades)>0 """ % constantes.IDKARDEX ) #Verificar si existen bodegas if self.bodegasModel.rowCount() == 0: raise UserWarning( "No existe ninguna bodega "\ + "en la base de datos" ) #Verificar IVA query = QSqlQuery( """ SELECT idcostoagregado, valorcosto FROM costosagregados c WHERE idtipocosto = 1 AND activo = 1 ORDER BY idtipocosto; """ ) query.exec_() if not query.size() == 1: raise UserWarning( "No fue posible obtener el "\ + "porcentaje del IVA" ) query.first() self.editmodel.ivaId = query.value( 0 ).toInt()[0] self.lbltasaiva.setText( ( '0' if self.editmodel.bodegaId != 1 else str( self.editmodel.ivaTasa ) ) + '%' ) self.editmodel.ivaTasa = Decimal( query.value( 1 ).toString() ) self.tabledetails.setItemDelegate( delegate ) self.cbcliente.setModel( self.clientesModel ) self.cbcliente.setCurrentIndex( -1 ) self.cbcliente.setFocus() self.cbcliente.setModelColumn( 1 ) self.completer.setCaseSensitivity( Qt.CaseInsensitive ) self.completer.setModel( self.clientesModel ) self.completer.setCompletionColumn( 1 ) self.cbcliente.setCompleter( self.completer ) self.cbbodega.setModel( self.bodegasModel ) self.cbbodega.setCurrentIndex( -1 ) self.cbbodega.setModelColumn( 1 ) self.completerbodega = QCompleter() self.completerbodega.setCaseSensitivity( Qt.CaseInsensitive ) self.completerbodega.setModel( self.bodegasModel ) self.completerbodega.setCompletionColumn( 1 ) self.cbbodega.setCompleter( self.completerbodega ) self.cbvendedor.setModel( self.vendedoresModel ) self.cbvendedor.setCurrentIndex( -1 ) self.cbvendedor.setModelColumn( 1 ) self.completerVendedor.setCaseSensitivity( Qt.CaseInsensitive ) self.completerVendedor.setModel( self.vendedoresModel ) self.completerVendedor.setCompletionColumn( 1 ) self.cbvendedor.setCompleter( self.completerVendedor ) self.tabledetails.setModel( self.editmodel ) self.addLine() self.editmodel.dataChanged[QModelIndex, QModelIndex].connect( self.updateLabels ) self.rbcontado.setChecked( True ) self.txtobservaciones.setPlainText( "" ) resultado = True except UserWarning as inst: logging.error( unicode( inst ) ) QMessageBox.critical( self, qApp.organizationName(), unicode( inst ) ) finally: if self.database.isOpen(): self.database.close() return resultado @property def printIdentifier( self ): return self.navmodel.record( self.mapper.currentIndex() ).value( "iddocumento" ).toString() def addActionsToToolBar( self ): self.actionRefresh = self.createAction( text = "Actualizar", icon = QIcon.fromTheme( 'view-refresh', QIcon( ":/icons/res/view-refresh.png" ) ), slot = self.refresh, shortcut = Qt.Key_F5 ) self.toolBar.addActions( [ self.actionNew, self.actionRefresh, self.actionPreview, self.actionPrint, self.actionSave, self.actionCancel, ] ) self.toolBar.addSeparator() self.toolBar.addActions( [ self.actionGoFirst, self.actionGoPrevious, self.actionGoLast, self.actionGoNext, self.actionGoLast ] ) def refresh( self ): """ Actualizar los modelos de edición """ if not self.status: if QMessageBox.question( self, qApp.organizationName(), u"Se perderán todos los cambios en la factura. ¿Esta seguro que desea actualizar?", QMessageBox.Yes | QMessageBox.No ) == QMessageBox.No: return self.updateEditModels() else: if self.updateModels(): QMessageBox.information( None, "Factura", u"Los datos fueron actualizados con éxito" ) def save( self ): """ Guardar el documento actual @rtype: bool """ result = False try: if not self.valid: return False if self.editmodel.escontado: recibo = DlgRecibo( self ) if recibo.datosRecibo.retencionValida: if recibo.datosRecibo.retencionModel.rowCount() == 0: raise UserWarning( "No es posible crear un recibo "\ + "porque no existen retenciones en la base de datos" ) else: recibo.ckretener.setChecked( False ) recibo.ckretener.setEnabled( False ) if recibo.exec_() == QDialog.Rejected: return else: credito = DlgCredito( self ) if not credito.exec_() == QDialog.Accepted: return self.editmodel.fechaTope = credito.dtFechaTope.date() self.editmodel.multa = Decimal( str( credito.sbTaxRate.value() ) ) if QMessageBox.question( self, qApp.organizationName(), u"¿Esta seguro que desea guardar la factura?", QMessageBox.Yes | QMessageBox.No ) == QMessageBox.Yes: if not self.database.isOpen(): if not self.database.open(): raise UserWarning( u"No se pudo conectar con la base de datos" ) self.editmodel.observaciones = self.txtobservaciones.toPlainText() if self.editmodel.escontado: recibo.datosRecibo.observaciones = recibo.txtobservaciones.toPlainText() if not self.editmodel.save( recibo.datosRecibo if self.editmodel.escontado else None ): raise UserWarning( "No se ha podido guardar la factura" ) QMessageBox.information( None, qApp.organizationName() , u"""El documento se ha guardado con éxito""" ) self.editmodel = None self.readOnly = True self.updateModels() self.cargarRecibos() self.navigate( 'last' ) self.status = True result = True except UserWarning as inst: logging.error( unicode( inst ) ) QMessageBox.critical( self, qApp.organizationName(), unicode( inst ) ) except Exception as inst: logging.critical( unicode( inst ) ) QMessageBox.critical( self, qApp.organizationName(), u"Hubo un error al guardar la factura" ) finally: if self.database.isOpen(): self.database.close() return result #FIXME: Hay demasiados if y cosas por el estilo en esta función...deberia de #hacerse un refactor @pyqtSlot() def on_actionAnular_activated( self ): if self.anulable == 2: QMessageBox.warning( self, qApp.organizationName(), u"La factura no puede anularse. Solo las"\ + " facturas confirmadas o en proceso de "\ + "autorización pueden anularse" ) elif self.anulable == 3: QMessageBox.warning( self, qApp.organizationName(), u"La factura no puede anularse porque no "\ + "es del día de hoy" ) elif self.anulable == 4: QMessageBox.warning( self, qApp.organizationName(), u"La factura no puede anularse porque tiene"\ + " abonos" ) elif self.anulable == 5: QMessageBox.warning( self, qApp.organizationName(), u"La factura no puede anularse porque tiene"\ + " devoluciones" ) elif self.anulable == 1: currentIndex = self.mapper.currentIndex() record = self.navmodel.record( currentIndex ) doc = record.value( "iddocumento" ).toInt()[0] estado = record.value( "idestado" ).toInt()[0] total = record.value( "totalfac" ).toString() bodega = record.value( IDBODEGA ).toInt()[0] if total != "": total = Decimal( total ) query = QSqlQuery() try: if not self.database.isOpen(): if not self.database.open(): raise Exception( "NO se pudo abrir la Base de datos" ) if estado == 3: if QMessageBox.question( self, qApp.organizationName(), u"Esta factura no fue confirmada,"\ + " ¿Desea eliminarla?", QMessageBox.Yes | QMessageBox.No ) == QMessageBox.Yes: query = QSqlQuery() query.prepare( "CALL spEliminarFactura(:doc)" ) query.bindValue( ":doc", doc ) if not query.exec_(): raise Exception( "No se pudo eliminar el la factura" ) QMessageBox.information( self, qApp.organizationName(), "La factura fue eliminada correctamente" ) self.updateModels() else: if QMessageBox.question( self, qApp.organizationName(), u"¿Esta seguro que desea anular la factura?", QMessageBox.Yes | QMessageBox.No ) == QMessageBox.Yes: nfac = self.navmodel.record( self.mapper.currentIndex() ).value( "No. Factura" ).toString() anulardialog = DlgAnular( nfac ) if anulardialog.conceptosmodel.rowCount() == 0: QMessageBox.warning( self, qApp.organizationName(), u"No existen conceptos para la anulación" ) else: if anulardialog.exec_() == QDialog.Accepted: if anulardialog.cboConceptos.currentIndex() == -1 and anulardialog.txtObservaciones.toPlainText() == "": QMessageBox.critical( self, qApp.organizationName(), "No ingreso los datos correctos", QMessageBox.Ok ) else: if not self.database.transaction(): raise Exception( "No se pudo comenzar la transacción" ) #Cambiar estado Anulado=1 para documento query.prepare( "UPDATE documentos d SET idestado=%d where iddocumento=%d LIMIT 1" % ( constantes.ANULACIONPENDIENTE, doc ) ) if not query.exec_(): raise Exception( "No se logro cambiar el estado a el documento" ) #Insertar documento anulacion if not query.prepare( """ INSERT INTO documentos(ndocimpreso,total,fechacreacion,idtipodoc,observacion,idestado, idbodega) VALUES(:ndocimpreso,:total,NOW(),:idtipodoc,:observacion,:idestado, :idbodega)""" ): raise Exception( query.lastError().text() ) query.bindValue( ":ndocimpreso", nfac ) query.bindValue( ":total", str( total ) ) # query.bindValue( ":fechacreacion", QDateTime.currentDateTime().toString('yyyyMMddhhmmss') ) query.bindValue( ":idtipodoc", constantes.IDANULACION ) query.bindValue( ":observacion", anulardialog.txtObservaciones.toPlainText() ) query.bindValue( ":idestado", constantes.PENDIENTE ) query.bindValue( ":idbodega", bodega ) if not query.exec_(): raise Exception( "No se pudo insertar el documento Anulacion" ) insertedId = query.lastInsertId().toString() if not query.prepare( "INSERT INTO docpadrehijos (idpadre,idhijo) VALUES" + "(:idfac," + insertedId + ")" ): # "(:usuario," + insertedId + ",0)," # "(:supervisor," + insertedId + ",1)"): raise Exception( query.lastError().text() + "No se preparo la relacion de la anulacion con la factura" ) query.bindValue( ":idfac", doc ) if not query.exec_(): raise Exception( "No se pudo insertar la relacion de la Anulacion con la factura" ) if not query.prepare( "INSERT INTO personasxdocumento (idpersona,iddocumento,idaccion) VALUES" \ + "(:usuario," + insertedId + ",:accion)" ): raise Exception( "No se inserto el usuario y autoriza" ) query.bindValue( ":usuario", self.parentWindow.datosSesion.usuarioId ) query.bindValue ( ":accion", constantes.AUTOR ) if not query.exec_(): raise Exception( "No se pudo Insertar la relacion de la anulacion con el usuario" ) if not self.database.commit(): raise Exception( "No se hizo el commit para la Anulacion" ) QMessageBox.information( self, qApp.organizationName(), "Factura anulada Correctamente", QMessageBox.Ok ) self.updateModels() except Exception as inst: logging.error( unicode( inst ) ) logging.error( query.lastError().text() ) QMessageBox.critical( self, qApp.organizationName(), unicode( inst ) ) self.database.rollback() except Exception as inst: logging.critical( unicode( inst ) ) logging.critical( query.lastError().text() ) QMessageBox.critical( self, qApp.organizationName(), "Hubo un error al intentar anular "\ + "la factura" ) self.database.rollback() finally: if self.database.isOpen(): self.database.close() @pyqtSlot() def on_actionRecibo_activated( self ): index = self.mapper.currentIndex() record = self.navmodel.record( index ) self.recibo.remoteProxyModel.setFilterRegExp( "(%s)" % record.value( "iddocumento" ).toString() ) if self.recibo.remoteProxyModel.rowCount() > 0: self.recibo.mapper.setCurrentIndex( 1 ) if self.recibo.remoteProxyModel.rowCount() != 0: self.recibo.mapper.setCurrentIndex( 0 ) self.recibo.show() @pyqtSlot( int ) def on_cboFiltro_currentIndexChanged( self, index ): """ asignar la bodega al objeto self.editmodel """ self.navproxymodel.setFilterKeyColumn( ANULADO ) if index == 0: self.navproxymodel.setFilterRegExp( "" ) else: self.navproxymodel.setFilterRegExp( "^%d$" % index ) @pyqtSlot( int ) @if_edit_model def on_cbbodega_currentIndexChanged( self, index ): """ asignar la bodega al objeto self.editmodel """ if self.editmodel.rowCount() > 0 and self.editmodel.lines[0].itemDescription != "": self.editmodel.removeRows( 0, self.editmodel.rowCount() ) self.editmodel.bodegaId = self.bodegasModel.record( index ).value( "idbodega" ).toInt()[0] self.proxyexistenciaModel.setFilterRegExp( '^%d$' % self.editmodel.bodegaId ) self.tabledetails.setColumnHidden( IDARTICULO, True ) self.updateLabels() @pyqtSlot( int ) @if_edit_model def on_cbcliente_currentIndexChanged( self, index ): """ asignar proveedor al objeto self.editmodel """ self.editmodel.clienteId = self.clientesModel.record( index ).value( "idpersona" ).toInt()[0] @pyqtSlot( int ) @if_edit_model def on_cbvendedor_currentIndexChanged( self, index ): """ asignar proveedor al objeto self.editmodel """ self.editmodel.vendedorId = self.vendedoresModel.record( index ).value( "idpersona" ).toInt()[0] @pyqtSlot( QDateTime ) def on_dtPicker_dateTimeChanged( self, datetime ): pass @pyqtSlot( bool ) @if_edit_model def on_rbcontado_toggled( self, on ): """ Asignar las observaciones al objeto editmodel """ self.editmodel.escontado = 1 if on else 0 def setControls( self, status ): """ @param status: false = editando true = navegando """ self.actionPrint.setVisible( status ) self.readOnly = status self.txtobservaciones.setReadOnly( status ) self.rbcontado.setEnabled( ( not status ) ) self.rbcredito.setEnabled( not status ) self.actionSave.setVisible( not status ) self.actionCancel.setVisible( not status ) self.tabnavigation.setEnabled( status ) self.actionNew.setVisible( status ) self.actionGoFirst.setVisible( status ) self.actionGoPrevious.setVisible( status ) self.actionGoNext.setVisible( status ) self.actionGoLast.setVisible( status ) self.actionPreview.setVisible( status ) self.actionAnular.setVisible( status ) self.actionRecibo.setVisible( status ) if status: self.navigate( 'last' ) self.swcliente.setCurrentIndex( 1 ) self.swbodega.setCurrentIndex( 1 ) self.swvendedor.setCurrentIndex( 1 ) self.tabledetails.setEditTriggers( QAbstractItemView.NoEditTriggers ) self.tabledetails.removeAction( self.actionDeleteRow ) self.tablenavigation.setColumnHidden( IDDOCUMENTO, True ) self.tablenavigation.setColumnHidden( OBSERVACION, True ) self.tablenavigation.setColumnHidden( SUBTOTAL, True ) self.tablenavigation.setColumnHidden( IVA, True ) self.tablenavigation.setColumnHidden( TASAIVA, True ) self.tablenavigation.setColumnHidden( TASA, True ) self.tablenavigation.setColumnHidden( ESCONTADO, True ) self.tablenavigation.setColumnHidden( ANULADO, True ) self.tablenavigation.setColumnHidden( TOTALFAC, True ) self.tablenavigation.setColumnHidden( IDBODEGA, True ) self.tablenavigation.setColumnHidden( ANULABLE, True ) else: # self.btnrecibo.setHidden( True ) self.tabWidget.setCurrentIndex( 0 ) self.lblnfac.setText( self.editmodel.printedDocumentNumber ) self.swcliente.setCurrentIndex( 0 ) self.swbodega.setCurrentIndex( 0 ) self.swvendedor.setCurrentIndex( 0 ) self.lblsubtotal.setText( "0.0000" ) self.lbliva.setText( "0.0000" ) self.lbltotal.setText( "0.0000" ) self.tabledetails.setEditTriggers( QAbstractItemView.AllEditTriggers ) self.lblanulado.setHidden( True ) self.tabledetails.addAction( self.actionDeleteRow ) # self.tabledetails.horizontalHeader().setStretchLastSection(True) self.tabledetails.setColumnHidden( IDARTICULO, True ) self.tabledetails.setColumnHidden( IDDOCUMENTOT, True ) def updateDetailFilter( self, index ): record = self.navmodel.record( index ) self.lbltasaiva.setText( record.value( "tasaiva" ).toString() + '%' ) self.lblanulado.setHidden( record.value( "idestado" ).toInt()[0] != constantes.ANULADO ) self.anulable = record.value( ANULABLE ).toInt()[0] # self.actionAnular.setEnabled() escontado = record.value( "escontado" ).toBool() if escontado: self.rbcontado.setChecked( True ) else: self.rbcredito.setChecked( True ) # self.recibo.setHidden(True) self.detailsproxymodel.setFilterKeyColumn( IDDOCUMENTOT ) self.detailsproxymodel.setFilterRegExp( record.value( "iddocumento" ).toString() ) self.tablenavigation.selectRow( self.mapper.currentIndex() ) def updateLabels( self ): self.lblsubtotal.setText( moneyfmt( self.editmodel.subtotal, 4, "US$ " ) ) self.lbliva.setText( moneyfmt( self.editmodel.IVA, 4, "US$ " ) ) self.lbltotal.setText( moneyfmt( self.editmodel.total, 4, "US$ " ) ) self.lbltasaiva.setText( str( self.editmodel.ivaTasa ) + '%' ) self.tabledetails.resizeColumnsToContents() def updateModels( self ): """ Recargar todos los modelos """ resultado = False try: if not self.database.isOpen(): if not self.database.open(): raise UserWarning( u"No se pudo establecer la "\ + "conexión con la base de datos" ) # El modelo principal query = """ SELECT d.iddocumento, d.ndocimpreso as 'No. Factura', GROUP_CONCAT(IF(pxd.idaccion=%d,p.nombre,"") SEPARATOR '') as Cliente, GROUP_CONCAT(IF(pxd.idaccion=%d,p.nombre,"") SEPARATOR '') as Vendedor, CONCAT('US$ ',FORMAT(ROUND(d.total / (1+ IF(valorcosto IS NULL,0,valorcosto/100)),4),4)) as subtotal, CONCAT('US$ ',FORMAT(d.total- ROUND(d.total / (1+ IF(valorcosto IS NULL,0,valorcosto/100)),4),4)) as iva, CONCAT('US$ ',FORMAT(d.Total,4)) as Total, d.observacion, d.fechacreacion as Fecha, b.nombrebodega as Bodega, tc.tasa as 'Tipo de Cambio Oficial', valorcosto as tasaiva, ed.descripcion as Estado, d.idestado, d.escontado, d.total as totalfac, fnFacturaAnulable(d.iddocumento,d.idtipodoc,%d,%d,%d,%d) as anulable, b.idbodega FROM documentos d JOIN estadosdocumento ed ON ed.idestado = d.idestado JOIN bodegas b ON b.idbodega=d.idbodega JOIN tiposcambio tc ON tc.idtc=d.idtipocambio JOIN personasxdocumento pxd ON pxd.iddocumento=d.iddocumento JOIN personas p ON p.idpersona=pxd.idpersona LEFT JOIN costosxdocumento cd ON cd.iddocumento=d.iddocumento LEFT JOIN costosagregados ca ON ca.idcostoagregado=cd.idcostoagregado WHERE d.idtipodoc=%d GROUP BY d.iddocumento ORDER BY CAST(IF(ndocimpreso='S/N',0,d.ndocimpreso) AS SIGNED) ; """ % ( constantes.CLIENTE, constantes.VENDEDOR, constantes.IDRECIBO, constantes.IDNC, constantes.CONFIRMADO, constantes.PENDIENTE, constantes.IDFACTURA ) self.navmodel.setQuery( query ) # Este es el modelo con los datos de la tabla para navegar self.detailsmodel.setQuery( u""" SELECT ad.idarticulo, ad.descripcion as 'Descripción', -a.unidades as Unidades, CONCAT('US$ ',FORMAT(a.precioventa,4)) as 'Precio Unit.', CONCAT('US$ ',FORMAT(-a.unidades*a.precioventa,4)) as 'Total', a.iddocumento FROM articulosxdocumento a JOIN vw_articulosdescritos ad on a.idarticulo=ad.idarticulo WHERE a.precioventa IS NOT NULL ; """ ) # Este objeto mapea una fila del modelo self.navproxymodel a los controles self.mapper.setSubmitPolicy( QDataWidgetMapper.ManualSubmit ) self.mapper.setModel( self.navproxymodel ) self.mapper.addMapping( self.lblnfac, NDOCIMPRESO , "text" ) self.mapper.addMapping( self.txtobservaciones, OBSERVACION ) self.mapper.addMapping( self.txtcliente, CLIENTE, "text" ) self.mapper.addMapping( self.txtvendedor, VENDEDOR, "text" ) self.mapper.addMapping( self.txtbodega, BODEGA, "text" ) self.mapper.addMapping( self.lbltotal, TOTAL, "text" ) self.mapper.addMapping( self.lblsubtotal, SUBTOTAL, "text" ) self.mapper.addMapping( self.lbliva, IVA, "text" ) self.mapper.addMapping( self.dtPicker, FECHA ) # asignar los modelos a sus tablas self.tablenavigation.setModel( self.navproxymodel ) self.tabledetails.setModel( self.detailsproxymodel ) resultado = True except UserWarning as inst: logging.error( unicode( inst ) ) QMessageBox.critical( self, qApp.organizationName(), unicode( inst ) ) self.status = True except Exception as inst: logging.critical( unicode( inst ) ) QMessageBox.critical( self, qApp.organizationName(), u"Hubo un error al actualizar los datos" ) self.status = True finally: if self.database.isOpen(): self.database.close() return resultado @property def valid( self ): """ Un documento es valido cuando self.printedDocumentNumber != "" self.providerId !=0 self.validLines >0 self.ivaId !=0 self.uid != 0 self.warehouseId != 0 """ if int( self.editmodel.datosSesion.usuarioId ) == 0: raise Exception( "No existe el usuario" ) elif int( self.editmodel.clienteId ) == 0: QMessageBox.warning( self, qApp.organizationName(), "Por favor elija el cliente" ) self.cbcliente.setFocus() elif int( self.editmodel.vendedorId ) == 0: QMessageBox.warning( self, qApp.organizationName(), "Por favor elija el vendedor" ) self.cbvendedor.setFocus() elif int( self.editmodel.bodegaId ) == 0: QMessageBox.warning( self, qApp.organizationName(), "Por favor elija la bodega" ) self.cbbodega.setFocus() elif int( self.editmodel.validLines ) == 0: QMessageBox.warning( self, qApp.organizationName(), "Por favor complete la información de los artículos comprados" ) else: return True return False
class ParentAction(object): def __init__(self, iface, settings, controller, plugin_dir): ''' Class constructor ''' # Initialize instance attributes self.tree_manage_version = "1.0" 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 self.lazy_widget = None 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 load_settings(self, dialog=None): """ Load QGIS settings related with dialog position and size """ screens = ctypes.windll.user32 screen_x = screens.GetSystemMetrics(78) screen_y = screens.GetSystemMetrics(79) 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: 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.width()) self.controller.plugin_settings_set_value( dialog.objectName() + "_height", dialog.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 """ 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 hide_colums(self, widget, comuns_to_hide): for i in range(0, len(comuns_to_hide)): widget.hideColumn(comuns_to_hide[i]) 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 set_table_columns(self, dialog, widget, table_name, project_type=None): """ Configuration of tables. Set visibility and width of columns """ widget = widget_manager.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 + "'") if project_type is not None: sql += (" AND project_type = '" + project_type + "' ") sql += (" 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 not None: widget.setColumnWidth(row['column_index'] - 1, width) widget.model().setHeaderData(row['column_index'] - 1, Qt.Horizontal, row['alias']) widget.model().select() # Delete columns for column in columns_to_delete: widget.hideColumn(column) def set_completer_object(self, tablename, widget, field_search): """ 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] = aux[0] # Set completer and model: add autocomplete in the widget self.completer = QCompleter() self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setCompletionMode(0) widget.setCompleter(self.completer) model = QStringListModel() model.setStringList(row) self.completer.setModel(model) 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_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 fill_table(self, qtable, table_name, set_edit_triggers=QTableView.NoEditTriggers, expr_filter=None): """ Fill table @widget filtering query by @workcat_id Set a model with selected filter. Attach that model to selected table @setEditStrategy: 0: OnFieldChange 1: OnRowChange 2: OnManualSubmit """ expr = None if expr_filter: # Check expression (is_valid, expr) = self.check_expression(expr_filter) # @UnusedVariable if not is_valid: return expr # Set a model with selected filter expression if self.schema_name not in table_name: table_name = self.schema_name + "." + table_name # Set model model = QSqlTableModel() model.setTable(table_name) model.setEditStrategy(QSqlTableModel.OnManualSubmit) model.setSort(0, 0) model.select() # When change some field we need to refresh Qtableview and filter by psector_id qtable.setEditTriggers(set_edit_triggers) # Check for errors if model.lastError().isValid(): self.controller.show_warning(model.lastError().text()) # Attach model to table view if expr: qtable.setModel(model) qtable.model().setFilter(expr_filter) else: qtable.setModel(model) return expr def get_feature_by_id(self, layer, id, field_id): iter = layer.getFeatures() for feature in iter: if feature[field_id] == id: return feature return False
def updateCompletion(self): qc = QCompleter(QStringList(self.search_history), self) qc.setCaseSensitivity(Qt.CaseInsensitive) self.ui.searchEdit.setCompleter(qc)
class tbFactura(QTabWidget, Ui_tbFactura): """ Implementacion de la interfaz grafica para facturas """ web = "facturas.php?doc=" DATE_FORMAT = "dd/MM/yyyy" def __init__(self): ''' Constructor ''' super(tbFactura, self).__init__() # ESTABLECER LA INTERFAZ AL FORMULARIO self.setupUi(self) # VALIDADOR DE MODO DE EDICION self.readOnly = True self.editmodel = None #ESTABLECER LA FECHA INICIAL , (establecida al dia de mañana) self.categoriesview.headers = [ "Descripcion", "Precio", "Unidades", "Existencia", "", "", "" ] # Crear el modelo para cargar catalogo de clientes self.clientesModel = QSqlQueryModel() # Crear lista de autocompletado para el combo de clientes self.clienteCompleter = QCompleter() # Modelo que carga el catalogo de productos self.existenciaModel = QSqlQueryModel() # Establecer todos los controles en modo de edicion self.setControls(False) # Crear la conexion a la base de datos self.database = QSqlDatabase.database() self.vistaprevia = False # Cargar los modelos del modo de edicion self.updateEditModels() self.parent = self.parent() def newDocument(self): """ activar todos los controles, llenar los modelos necesarios, crear el modelo FacturaModel, aniadir una linea a la tabla """ self.readOnly = False if not self.updateEditModels(): return self.status = False self.dtPicker.setDate(self.parentWindow.datosSesion.fecha) def updateEditModels(self): """ Este metodo actualiza los modelos usados en el modo edición """ resultado = False try: if not self.database.isOpen(): if not self.database.open(): raise UserWarning( u"No se pudo abrir la conexión "\ + "con la base de datos" ) self.clientesModel.setQuery(""" SELECT idpersona , nombre AS cliente FROM personas WHERE escliente = 1 """) self.cbcliente.setModel(self.clientesModel) self.cbcliente.setModelColumn(1) self.clienteCompleter.setCaseSensitivity(Qt.CaseInsensitive) self.clienteCompleter.setModel(self.clientesModel) self.clienteCompleter.setCompletionColumn(1) self.cbcliente.setCompleter(self.clienteCompleter) self.editmodel = FacturaModel() # Cargar el numero de la factura actual query = QSqlQuery(""" SELECT MAX(CAST( IFNULL(referencia,0) AS SIGNED)) FROM documentos d WHERE idtipodoc =%d; """ % constantes.IDFACTURA) if not query.exec_(): raise Exception("No se pudo obtener el numero de la factura") query.first() if query.size() == 0: n = 1 else: n = str(int(query.value(0)) + 1) self.editmodel.printedDocumentNumber = str( int(query.value(0)) + 1) self.lblnumero.setText(n) # if self.clientesModel.rowCount() == 0: # raise UserWarning( "No existen clientes en la"\ # + " base de datos" ) # return self.clienteCompleter.setModel(self.clientesModel) self.cbcliente.setModel(self.clientesModel) self.cbcliente.setCompleter(self.clienteCompleter) # #Crear el delegado con los articulo y verificar si existen articulos self.existenciaModel.setQuery( QSqlQuery(""" SELECT categoria, descripcion, precio, unidadesxcaja, -- cajas, 100 as cajas, idprecioproducto FROM vw_articulos -- WHERE existencia >0 """)) self.categoriesview.update(""" SELECT categoria, descripcion, precio, unidadesxcaja, -- cajas, 100 as cajas, idprecioproducto FROM vw_articulos WHERE idprecioproducto IS NOT NULL -- WHERE existencia >0 """) self.categoriesview.expandAll() self.categoriesview.setColumnHidden(3, True) self.categoriesview.setColumnHidden(4, True) self.categoriesview.setColumnWidth(0, 150) self.categoriesview.setColumnWidth(1, 60) self.categoriesview.setColumnWidth(2, 20) self.proxyexistenciaModel = SingleSelectionModel() self.proxyexistenciaModel.setSourceModel(self.existenciaModel) # self.proxyexistenciaModel.setFilterKeyColumn( IDBODEGAEX ) if self.proxyexistenciaModel.rowCount() == 0: raise UserWarning("No hay articulos en bodega") delegate = FacturaDelegate(self.proxyexistenciaModel) self.tabledetails.setItemDelegate(delegate) self.tabledetails.setModel(self.editmodel) self.tabledetails.setColumnHidden(0, True) # self.editmodel.insertRow(1) self.editmodel.dataChanged[QModelIndex, QModelIndex].connect(self.updateLabels) self.txtobservaciones.setPlainText("") self.dtPicker.setDate(QDate.currentDate().addDays(1)) self.editmodel.fecha = QDate.currentDate().addDays(1) self.cbcliente.setCurrentIndex(-1) resultado = True except UserWarning as inst: logging.error(unicode(inst)) QMessageBox.critical(self, qApp.organizationName(), unicode(inst)) finally: if self.database.isOpen(): self.database.close() return resultado def addActionsToToolBar(self): self.actionRefresh = self.createAction( text="Actualizar", icon=QIcon.fromTheme('view-refresh', QIcon(":/icons/res/view-refresh.png")), slot=self.refresh, shortcut=Qt.Key_F5) self.toolBar.addActions([ self.actionNew, self.actionRefresh, self.actionPreview, self.actionPrint, self.actionSave, self.actionCancel, ]) self.toolBar.addSeparator() self.toolBar.addActions([ self.actionGoFirst, self.actionGoPrevious, self.actionGoLast, self.actionGoNext, self.actionGoLast ]) def refresh(self): """ Actualizar los modelos de edición """ if not self.status: if QMessageBox.question( self, qApp.organizationName(), u"Se perderán todos los cambios en la factura. ¿Esta seguro que desea actualizar?", QMessageBox.Yes | QMessageBox.No) == QMessageBox.No: return self.updateEditModels() else: if self.updateModels(): QMessageBox.information( None, "Factura", u"Los datos fueron actualizados con éxito") def printDocument1(self): html = u"" date = QDate.currentDate().toString(self.DATE_FORMAT) address = Qt.escape("Bario francisco mesa").replace(",", "<br>") contact = Qt.escape("Luis Mejia") balance = 5000 html += ("<p align=right><img src=':/logo.png'></p>" "<p> align = right>Greasy hands ltd." "<br>New Lombard Street" "<br>London<br>WC13 4PX<br>%s</p>" "<p>%s</p><p>Dear %s, </p>" "<p>The balance of your account is %s.") % ( date, address, contact, QString("$ %L1").arg( float(balance), 0, "f", 2)) if balance < 0: html += ( "<p><font color =red><b> Please remit the amount owing immediately.</b></font>" ) else: html += "We are delighted to have done business with you." html += ( "</p><p> </p><p>" "<table border=1 cellpadding=2 cellspacing=2><tr><td colspan=3>Transaction</td></tr>" ) transactions = [(QDate.currentDate(), 500), (QDate.currentDate(), 500), (QDate.currentDate(), -500), (QDate.currentDate(), 500)] for date, amount in transactions: color, status = "black", "Credit" if amount < 0: color, status = "red", "Debid" html += ( "<tr>" "<td align= right>%s</td>" "<td>%s</td><td align=right><font color=%s>%s</font></td></tr>" % (date.toString(self.DATE_FORMAT), status, color, QString("$ %L1").arg(float(abs(amount)), 0, "f", 2))) html += ("</table></p><p style='page-break-after=always;'>" "We hope to continue doing business with you</p>") pdialog = QPrintDialog() if pdialog.exec_() == QDialog.Accepted: printer = pdialog.printer() document = QTextDocument() document.setHtml(html) document.print_(printer) def printDocument2(self): dialog = QPrintDialog() if not dialog.exec_(): return self.printer = dialog.printer() headFormat = QTextBlockFormat() headFormat.setAlignment(Qt.AlignLeft) headFormat.setTextIndent(self.printer.pageRect().width() - 216) bodyFormat = QTextBlockFormat() bodyFormat.setAlignment(Qt.AlignJustify) lastParaBodyFormat = QTextBlockFormat(bodyFormat) lastParaBodyFormat.setPageBreakPolicy( QTextFormat.PageBreak_AlwaysAfter) rightBodyFormat = QTextBlockFormat() rightBodyFormat.setAlignment(Qt.AlignRight) headCharFormat = QTextCharFormat() headCharFormat.setFont(QFont("Helvetica", 10)) bodyCharFormat = QTextCharFormat() bodyCharFormat.setFont(QFont("Times", 11)) redBodyCharFormat = QTextCharFormat(bodyCharFormat) redBodyCharFormat.setForeground(Qt.red) tableFormat = QTextTableFormat() tableFormat.setBorder(1) tableFormat.setCellPadding(2) document = QTextDocument() cursor = QTextCursor(document) mainFrame = cursor.currentFrame() page = 1 cursor.insertBlock(headFormat, headCharFormat) for text in ("Greasy Hands Ltd.", "New Lombard Street", "London", "WC13", QDate.currentDate().toString(self.DATE_FORMAT)): cursor.insertBlock(headFormat, headCharFormat) cursor.insertText(text) cursor.insertBlock(bodyFormat, bodyCharFormat) cursor.insertText("Barrio Francisco Meza") cursor.insertBlock(bodyFormat) cursor.insertBlock(bodyFormat, bodyCharFormat) cursor.insertText("Dear Lyuis") cursor.insertBlock(bodyFormat) cursor.insertBlock(bodyFormat, bodyCharFormat) cursor.insertText( QString("The balance of your account is $ %L1.").arg( float(500.987), 0, "f", 2)) cursor.insertBlock(bodyFormat, redBodyCharFormat) cursor.insertText("Please remit the amount") cursor.insertBlock(bodyFormat, bodyCharFormat) cursor.insertText("Transaction") transactions = [(QDate.currentDate(), 500), (QDate.currentDate(), 500), (QDate.currentDate(), -500), (QDate.currentDate(), 500)] table = cursor.insertTable(len(transactions), 3, tableFormat) row = 0 for date, amount in transactions: cellCursor = table.cellAt(row, 0).firstCursorPosition() cellCursor.setBlockFormat(rightBodyFormat) cellCursor.insertText(date.toString(self.DATE_FORMAT), bodyCharFormat) cellCursor = table.cellAt(row, 1).firstCursorPosition() cellCursor.insertText("Credit", bodyCharFormat) cellCursor = table.cellAt(row, 2).firstCursorPosition() cellCursor.setBlockFormat(rightBodyFormat) cellCursor.insertText( QString("The balance of your account is $ %L1.").arg( float(amount), 0, "f", 2), redBodyCharFormat) row += 1 cursor.setPosition(mainFrame.lastPosition()) cursor.insertBlock(bodyFormat, bodyCharFormat) cursor.insertText("We hope") document.print_(self.printer) def printDocument(self): dialog = QPrintDialog() if not dialog.exec_(): return self.printer = dialog.printer() self.imprimir(self.printer) self.document.load(self.editmodel) def preview(self): self.vistaprevia = True preview = frmImpresion(self) preview.exec_() def save(self): """ Guardar el documento actual @rtype: bool """ result = False try: if not self.valid: return False if QMessageBox.question( self, qApp.organizationName(), u"¿Esta seguro que desea guardar la factura?", QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes: if not self.database.isOpen(): if not self.database.open(): raise UserWarning( u"No se pudo conectar con la base de datos") self.editmodel.observaciones = self.txtobservaciones.toPlainText( ) if not self.editmodel.save(): raise UserWarning("No se ha podido guardar la factura") QMessageBox.information( None, qApp.organizationName(), u"""El documento se ha guardado con éxito""") self.readOnly = True self.updateModels() # self.navigate( 'last' ) # self.status = True result = True except UserWarning as inst: logging.error(unicode(inst)) QMessageBox.critical(self, qApp.organizationName(), unicode(inst)) except Exception as inst: logging.critical(unicode(inst)) QMessageBox.critical(self, qApp.organizationName(), u"Hubo un error al guardar la factura") finally: if self.database.isOpen(): self.database.close() return result # @pyqtSlot(QModelIndex) # def on_categoriesview_doubleClicked(self,index): @pyqtSlot(QModelIndex) def on_categoriesview_activated(self, index): articulo = self.categoriesview.model().asRecord(index) if len(articulo) > 0: nuevo = True for i, line in enumerate(self.editmodel.lines): if line.itemId == articulo[5]: nuevo = False fila = i line = self.editmodel.lines[self.editmodel.rowCount() - 1] if nuevo: fila = self.editmodel.rowCount() self.editmodel.insertRow(fila) self.parent.saveAct.setEnabled(True) linea = self.editmodel.lines[fila] linea.itemDescription = articulo[0] + " " + articulo[1] linea.itemPrice = Decimal(articulo[2]) linea.itemId = articulo[5] linea.quantityperbox = int(articulo[3]) self.editmodel.lines[fila].quantity += 1 self.editmodel.lines[fila].existencia = int( articulo[4]) - self.editmodel.lines[fila].quantity indice = self.editmodel.index(fila, 2) self.editmodel.dataChanged.emit(indice, indice) indice = self.editmodel.index(fila, 3) self.editmodel.dataChanged.emit(indice, indice) indice = self.editmodel.index(fila, 5) self.editmodel.dataChanged.emit(indice, indice) @pyqtSlot() def on_btneditar_clicked(self): articulo = dlgArticulo(self) articulo.exec_() self.updateEditModels() @pyqtSlot(int) def on_cbcliente_currentIndexChanged(self, index): """ asignar proveedor al objeto self.editmodel """ if self.editmodel is not None: numero = self.clientesModel.record(index).value("idpersona") self.editmodel.clienteId = int(numero) if numero is not None else 0 @pyqtSlot(unicode) def on_cbcliente_editTextChanged(self, text): """ asignar proveedor al objeto self.editmodel """ if self.editmodel is not None: self.editmodel.cliente = str(text) @pyqtSlot(int) def on_cbvendedor_currentIndexChanged(self, index): """ asignar proveedor al objeto self.editmodel """ self.editmodel.vendedorId = self.vendedoresModel.record(index).value( "idpersona").toInt()[0] @pyqtSlot(QDate) def on_dtPicker_dateChanged(self, date): if self.editmodel is not None: self.editmodel.fecha = date @pyqtSlot(bool) def on_rbcontado_toggled(self, on): """ Asignar las observaciones al objeto editmodel """ self.editmodel.escontado = 1 if on else 0 def on_txtSearch_textChanged(self, text): """ Cambiar el filtro de busqueda """ self.filtermodel.setFilterRegExp(text) def setControls(self, status): """ @param status: false = editando true = navegando """ # self.actionPrint.setVisible( status ) self.readOnly = status self.txtobservaciones.setReadOnly(status) # self.actionPreview.setVisible( status ) # self.actionAnular.setVisible( status ) # self.toolBar.setVisible(status) # self.lblnfac.setText( self.editmodel.printedDocumentNumber ) self.swcliente.setCurrentIndex(0) self.lbltotal.setText("C$ 0.00") self.tabledetails.setEditTriggers(QAbstractItemView.AllEditTriggers) # self.lblanulado.setHidden( True ) self.tabledetails.horizontalHeader().setStretchLastSection(True) self.tabledetails.setColumnHidden(IDARTICULO, True) self.tabledetails.setColumnHidden(IDDOCUMENTOT, True) def updateLabels(self): self.lbltotal.setText(moneyfmt(self.editmodel.total, 2, "C$ ")) @property def valid(self): """ Un documento es valido cuando self.printedDocumentNumber != "" self.providerId !=0 self.validLines >0 self.ivaId !=0 self.uid != 0 self.warehouseId != 0 """ if int(self.editmodel.clienteId) == 0 and self.editmodel.cliente == "": QMessageBox.warning(self, qApp.organizationName(), "Por favor elija el cliente") self.cbcliente.setFocus() elif self.editmodel.rowCount() == 0: QMessageBox.warning( self, qApp.organizationName(), "Por favor agregue algun articulo a la factura") else: return True return False def imprimir(self, printer): leftMargin = 72 widthCol = 100 arialFont = QFont("Helvetica", 16, 3) fuente = QFontMetrics(arialFont) arialLineHeight = fuente.height() fondo = QPixmap(":/images/res/fondo.png") painter = QPainter(printer) pageRect = printer.pageRect() page = 1 painter.save() if self.vistaprevia: painter.drawPixmap(0, 0, 530, 830, fondo) painter.setFont(arialFont) y = 180 x = 35 painter.drawText(x, y, self.editmodel.fecha.toString("dd MM yy")) y = 210 x = 85 painter.drawText(x, y, self.editmodel.cliente) painter.setFont(arialFont) cajasFont = QFont("Helvetica", 10, 2) x = -5 y = 295 painter.setFont(cajasFont) painter.drawText(x, y - arialLineHeight - 1, "Cajas") for row in self.editmodel.lines: painter.setFont(cajasFont) x = 2 painter.drawText(x, y, row.cantidad()) painter.setFont(arialFont) total = moneyfmt(row.total, 2, "") x = 470 - fuente.width(total) painter.drawText(x, y, total) x = 310 painter.drawText(x, y, moneyfmt(row.itemPrice, 2, "")) x = 30 painter.drawText(x, y, row.unidades()) x = 80 painter.drawText(x, y, row.itemDescription) y += arialLineHeight total = moneyfmt(self.editmodel.total, 2, "") y = 690 x = 470 - fuente.width(total) painter.drawText(x, y, total) painter.setPen(Qt.black) # printer.newPage() painter.restore()