Beispiel #1
0
    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)
Beispiel #2
0
    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)
Beispiel #3
0
    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)
Beispiel #4
0
    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)
Beispiel #5
0
    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)
Beispiel #6
0
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)
Beispiel #7
0
    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)
Beispiel #8
0
    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)
Beispiel #9
0
	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()
Beispiel #10
0
    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()
Beispiel #11
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))
Beispiel #12
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()
Beispiel #15
0
    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_()
Beispiel #16
0
    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_()
Beispiel #17
0
    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)
Beispiel #18
0
    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)
Beispiel #19
0
    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
Beispiel #20
0
class MyMainWindow(QMainWindow):
    ' Main Window '

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    def set_guimode(self):
        """Switch between simple and full UX"""
        for widget in (self.group2, self.group3, self.group4, self.group5,
                       self.icon, self.icon_label, self.btn3, self.toolbar,
                       self.statusBar()):
            widget.hide() if self.guimode.currentIndex() else widget.show()
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
Beispiel #22
0
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)
Beispiel #23
0
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")
Beispiel #24
0
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)
Beispiel #25
0
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()
Beispiel #26
0
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()
Beispiel #27
0
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())
Beispiel #28
0
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(
            "")
Beispiel #29
0
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)
Beispiel #30
0
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]))
Beispiel #31
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)
Beispiel #33
0
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')
Beispiel #34
0
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
Beispiel #35
0
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()
Beispiel #36
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.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
Beispiel #37
0
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()))
Beispiel #38
0
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())
Beispiel #39
0
    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()
Beispiel #41
0
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
Beispiel #43
0
#!/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_())
Beispiel #44
0
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()
Beispiel #45
0
class ParentAction(object):
    def __init__(self, iface, settings, controller, plugin_dir):
        """ Class constructor """

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

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

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

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

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

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

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

        return plugin_version

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

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

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

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

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

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

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

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

        return (giswater_file_path, giswater_build_version)

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

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

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

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

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

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

        return java_exe

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

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

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

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

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

        self.controller.start_program(program)

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

    def set_java_settings(self, show_warning=True):

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

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

    def set_gsw_settings(self):

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

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

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

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

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

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

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

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

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

        webbrowser.open(url)

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

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

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

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

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

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

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

        if dialog is None:
            dialog = self.dlg

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

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

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

        if dialog is None:
            dialog = self.dlg

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

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

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

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

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

        # Open dialog
        dlg.open()

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        selected_list = qtable_left.selectionModel().selectedRows()

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        if restore_cursor:
            self.set_cursor_restore()

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

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

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

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

        return cursor

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

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

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

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

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

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

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

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

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

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

    def set_label_current_psector(self, dialog):

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

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

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

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

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

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

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

        if not layer:
            return

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

        if geom_type:

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

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

            if zoom is not None:
                scale = zoom

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

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

        if not widget:
            return

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

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

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

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

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

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

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

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

        return action
Beispiel #46
0
 def updateCompletion(self):
     qc = QCompleter(QStringList(self.search_history), self)
     qc.setCaseSensitivity(Qt.CaseInsensitive)
     self.ui.searchEdit.setCompleter(qc)
Beispiel #47
0
class IdePanel(QPlainTextEdit):
    def __init__(self):
        QPlainTextEdit.__init__(self)
        self.setWordWrapMode(QTextOption.NoWrap)
        self.setFont(QFont("monospace", 10))
        self.setCursorWidth(2)
        self.installEventFilter(self)

        self.cursorPositionChanged.connect(self.showHelp)

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

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

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

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

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

        if user_data is not None:
            configuration_line = user_data.configuration_line

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

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

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

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

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

            else:
                self.setToolTip("")

        return QPlainTextEdit.eventFilter(self, qobject, qevent)

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

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

        user_data = block.userData()

        self.completer.setCompletionPrefix(word)

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

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

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

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

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

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

        QPlainTextEdit.keyPressEvent(self, qkeyevent)

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

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

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

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

        return False

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

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

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

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

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

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

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

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

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

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

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

    def selectFragment(self):
        text_cursor = self.textCursor()
        self.selectWordUnderCursor(text_cursor)
        self.setTextCursor(text_cursor)
Beispiel #48
0
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>&nbsp;</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()
Beispiel #49
0
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_())
Beispiel #50
0
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]))
Beispiel #51
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)
Beispiel #52
0
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("")
Beispiel #53
0
class IdePanel(QPlainTextEdit):
    def __init__(self):
        QPlainTextEdit.__init__(self)
        self.setWordWrapMode(QTextOption.NoWrap)
        self.setFont(QFont("monospace", 10))
        self.setCursorWidth(2)
        self.installEventFilter(self)

        self.cursorPositionChanged.connect(self.showHelp)

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


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

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

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

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

        if user_data is not None:
            configuration_line = user_data.configuration_line

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


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


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

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

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

            else:
                self.setToolTip("")


        return QPlainTextEdit.eventFilter(self, qobject, qevent)


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



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

        user_data = block.userData()

        self.completer.setCompletionPrefix(word)

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

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

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


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

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

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

        QPlainTextEdit.keyPressEvent(self, qkeyevent)


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

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

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

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

        return False

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

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

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

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

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

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

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

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


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

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

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


    def selectFragment(self):
        text_cursor = self.textCursor()
        self.selectWordUnderCursor(text_cursor)
        self.setTextCursor(text_cursor)
Beispiel #54
0
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
Beispiel #55
0
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
Beispiel #56
0
 def updateCompletion(self):
     qc = QCompleter(QStringList(self.search_history), self)
     qc.setCaseSensitivity(Qt.CaseInsensitive)
     self.ui.searchEdit.setCompleter(qc)
Beispiel #57
0
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>&nbsp;</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()