def setupModel(self):
        u"""Définit et configure le modèle sous-jacent à la table"""
        self._modele = QSqlTableModel(self)
        self._modele.setTable("intervenant")
        self._modele.setHeaderData(1, Qt.Horizontal, "Nom")
        self._modele.setHeaderData(2, Qt.Horizontal, u"Téléphone")
        self._modele.setHeaderData(3, Qt.Horizontal, "Email")
        self._modele.setEditStrategy(QSqlTableModel.OnFieldChange)
        self._modele.select()

        self._ui.tv.setModel(self._modele)
Exemple #2
0
 def setup_model(self):
     db = Db_Instance("oform_product").get_instance()
     if not db.open():
         self.log.error(db.lastError().text())
         message = unicode("Erro de conexão\n\n" "Banco de dados indisponível".decode("utf-8"))
         QMessageBox.critical(self, "Seareiros - Vendas do Bazar", message)
     else:
         # product order
         self._model = QSqlTableModel(self, db=db)
         self._model.setTable("order_request")
         # product order items
         self._items_model = QSqlTableModel(self, db=db)
         self._items_model.setTable("product_order_item")
Exemple #3
0
 def setup_model(self):
     db = Db_Instance("oform_book").get_instance()
     if not db.open():
         self.log.error(db.lastError().text())
         message = unicode("Erro de conexão\n\n""Banco de dados indisponível".decode('utf-8'))
         QMessageBox.critical(self, "Seareiros - Livraria", message)
     else:
         # book order
         self._model = QSqlTableModel(self, db=db)
         self._model.setTable("order_request")
         # book order items
         self._items_model = QSqlTableModel(self, db=db)
         self._items_model.setTable("book_order_item")
Exemple #4
0
 def __init__(self, parent=None):
     super(MainWindow, self).__init__(parent)
     database = QSqlDatabase.addDatabase('QSQLITE')
     database.setDatabaseName('astatsscraper.db') # Better lookup logic needed
     if not database.open():
         print('Error opening database!')
     model = QSqlTableModel(db=database)
     model.setTable('steam_apps')
     table = QTableView()
     table.setEditTriggers(QAbstractItemView.NoEditTriggers)
     table.setModel(model)
     self.setCentralWidget(table)
     table.show()
Exemple #5
0
 def __init__(self, parent=None):
     super(MainWindow, self).__init__(parent)
     database = QSqlDatabase.addDatabase('QSQLITE')
     database.setDatabaseName(
         'astatsscraper.db')  # Better lookup logic needed
     if not database.open():
         print('Error opening database!')
     model = QSqlTableModel(db=database)
     model.setTable('steam_apps')
     table = QTableView()
     table.setEditTriggers(QAbstractItemView.NoEditTriggers)
     table.setModel(model)
     self.setCentralWidget(table)
     table.show()
Exemple #6
0
class TableController(object):
	def __init__(self,tabHost,objectType,objectName,model):
		self.view=TableView(tabHost)
		self.model=model
		self.name=objectName
		self.type=objectType
		self._mapdata()
		self.wireUp()

	def _mapdata(self):
		assert self.model.isDBLoaded()
		self.datamodel=QSqlTableModel(self.view,self.model.db)
		self.datamodel.setTable(self.name)
		self.refresh()
	
	def wireUp(self):
		self.datamodel.setEditStrategy(QSqlTableModel.OnManualSubmit)
		self.view.ui.tableView.setModel(self.datamodel)
		self.view.ui.tableView.show()
		if self.type==self.model.ModelArea.TABLES:	##make widget read-write
			self.view.ui.tableView.setEditTriggers(QAbstractItemView.DoubleClicked | QAbstractItemView.SelectedClicked)
			self.datamodel.setEditStrategy(QSqlTableModel.OnRowChange)	#TODO: track edits for safe saving
		
	def refresh(self):
		self.datamodel.select()
Exemple #7
0
    def setup_model(self):
        db = Db_Instance("edit_book").get_instance()
        if not db.open():
            self.log.error(db.lastError().text())
            message = unicode("Erro de conexão\n\n""Banco de dados indisponível".decode('utf-8'))
            QMessageBox.critical(self, unicode("Seareiros - Edição de Livro".decode('utf-8')), message)
        else:
            # book
            self._model = QSqlRelationalTableModel(self, db=db)
            self._model.setTable("book")
            self._model.setFilter("id = " + str(self._record_id))
            # self._model.setRelation(self.column["author"], QSqlRelation("author", "id", "name"))
            # self._model.setRelation(self.column["s_author"], QSqlRelation("s_author", "id", "name"))
            # self._model.setRelation(self.column["publisher"], QSqlRelation("publisher", "id", "name"))
            self._model.select()
            self._record = self._model.record(0)
            # models for setting up qcompleters:
            # book_in_subject
            self._book_in_subj_model = QSqlTableModel(self, db=db)
            self._book_in_subj_model.setTable("book_in_subject")
            # subject
            self._subject_model = QSqlTableModel(self, db=db)
            self._subject_model.setTable("subject")
            self._subject_model.select()
            # author
            self._author_model = QSqlTableModel(self, db=db)
            self._author_model.setTable("author")
            self._author_model.select()
            # s_author
            self._s_author_model = QSqlTableModel(self, db=db)
            self._s_author_model.setTable("s_author")
            self._s_author_model.select()
            # publisher
            self._publisher_model = QSqlTableModel(self, db=db)
            self._publisher_model.setTable("publisher")
            self._publisher_model.select()

            # retrieving current subjects, should probably place this elsewhere but it's related to models
            self._subject_records = []
            sql_statement = """SELECT id, name FROM subject s, book_in_subject b_s
                               WHERE s.id = b_s.subject_id AND b_s.book_id = %s
                            """ % str(self._record_id)
            read_only_subject_model = QSqlQueryModel()
            read_only_subject_model.setQuery(sql_statement, db)
            # checking query validity
            if not read_only_subject_model.lastError().isValid():
                self._subj_records = iterate_model(read_only_subject_model)
    def setupModel(self):
        u"""Définit et configure le modèle sous-jacent à la table"""
        self._modele = QSqlTableModel(self)
        self._modele.setTable("intervenant")
        self._modele.setHeaderData(1, Qt.Horizontal, "Nom")
        self._modele.setHeaderData(2, Qt.Horizontal, u"Téléphone")
        self._modele.setHeaderData(3, Qt.Horizontal, "Email")
        self._modele.setEditStrategy(QSqlTableModel.OnFieldChange)
        self._modele.select()

        self._ui.tv.setModel(self._modele)
Exemple #9
0
 def setup_model(self):
     db = Db_Instance("form_book").get_instance()
     if not db.open():
         self.log.error(db.lastError().text())
         message = unicode("Erro de conexão\n\n" "Banco de dados indisponível".decode("utf-8"))
         QMessageBox.critical(self, "Seareiros - Cadastro de Livro", message)
     else:
         # book
         self._model = QSqlTableModel(self, db=db)
         self._model.setTable("book")
         # subject
         self._subject_model = QSqlTableModel(self, db=db)
         self._subject_model.setTable("subject")
         self._subject_model.select()
         # author
         self._author_model = QSqlTableModel(self, db=db)
         self._author_model.setTable("author")
         self._author_model.select()
         # sauthor
         self._s_author_model = QSqlTableModel(self, db=db)
         self._s_author_model.setTable("s_author")
         self._s_author_model.select()
         # publisher
         self._publisher_model = QSqlTableModel(self, db=db)
         self._publisher_model.setTable("publisher")
         self._publisher_model.select()
         # book subjects
         self._book_in_subj_model = QSqlTableModel(self, db=db)
         self._book_in_subj_model.setTable("book_in_subject")
Exemple #10
0
class ProductOrderForm(QScrollArea, Ui_ProductOForm):
    """ Interface for ordering products """

    column = {"associate": 1, "obs": 3, "total": 4, "paid": 5, "type": 7}

    def __init__(self, parent=None):
        super(ProductOrderForm, self).__init__(parent)
        self.setupUi(self)
        # had to subclass this spinbox to support return grabbing
        self.edQuantity = ReturnKeySpinBox(self)
        self.edQuantityHolder.addWidget(self.edQuantity)

        self._access = statics.access_level
        # for currency formatting
        self._locale = QLocale()

        # had to hardcode these, wouldn't work otherwise:
        self.contentsLayout.setAlignment(self.groupBox, QtCore.Qt.AlignTop)
        self.contentsLayout.setAlignment(self.groupBox_2, QtCore.Qt.AlignTop)
        self.contentsLayout.setAlignment(self.groupBox_3, QtCore.Qt.AlignTop)
        self.contentsLayout.setAlignment(self.groupBox_4, QtCore.Qt.AlignTop)

        self.log = logging.getLogger("ProductOForm")

        self.setup_model()
        self.setup_fields()

        # associate present flag
        self._associate_id = None
        # product internals
        self._product_list = []
        self._total = 0.0

        # flag to indicate whether there were changes to the fields
        self._dirty = False

    def is_dirty(self):
        return self._dirty

    def setup_model(self):
        db = Db_Instance("oform_product").get_instance()
        if not db.open():
            self.log.error(db.lastError().text())
            message = unicode("Erro de conexão\n\n" "Banco de dados indisponível".decode("utf-8"))
            QMessageBox.critical(self, "Seareiros - Vendas do Bazar", message)
        else:
            # product order
            self._model = QSqlTableModel(self, db=db)
            self._model.setTable("order_request")
            # product order items
            self._items_model = QSqlTableModel(self, db=db)
            self._items_model.setTable("product_order_item")

    def setup_fields(self):
        """ setting up validators and stuff """
        # validators
        self.edProductName.setValidator(UppercaseValidator())
        self.edPrice.setValidator(CurrencyValidator(self.edPrice))
        # hiding associate frame and clean button
        self.frameAssociate.setVisible(False)
        self.btnCleanAssociate.setVisible(False)
        # connecting return key to tab
        for lineEdit in self.findChildren(QLineEdit):
            # qspinbox has a C++ originated qlineedit "hidden" in it, we don't wanna mess with that
            if lineEdit.objectName() != "qt_spinbox_lineedit":
                lineEdit.returnPressed.connect(lineEdit.focusNextChild)
                # detect changes on line edits
                lineEdit.textChanged.connect(self.check_changes)
        self.edQuantity.setMinimum(1)
        self.edQuantity.setMaximum(2000)
        self.edQuantity.setValue(1)
        # fixing tab order
        self.setTabOrder(self.edPrice, self.edQuantity)
        self.setTabOrder(self.edQuantity, self.btnAddProduct)

    def check_changes(self, txt):
        if txt != "":
            self._dirty = True

    def submit_data(self):
        # I should block empty orders I guess
        if len(self._product_list) == 0:
            message = unicode(
                "Venda vazia!\n\n" "" "É necessário adicionar um produto antes de concluir uma venda".decode("utf-8")
            )
            QMessageBox.critical(self, "Seareiros - Vendas do Bazar", message)
            self.edProductName.setFocus()
            return False
        data = self.extract_input()
        # filling a product order
        self._model.insertRow(0)
        for key, val in data.items():
            self._model.setData(self._model.index(0, self.column[key]), val)
        order_id = submit_and_get_id(self, self._model, self.log)
        if order_id:
            # order creation success, placing items
            error = False
            for item in self._product_list:
                product_name = item[0]
                product_price = item[1]
                product_quantity = item[2]
                self._items_model.insertRow(0)
                self._items_model.setData(self._items_model.index(0, 1), order_id)
                self._items_model.setData(self._items_model.index(0, 2), product_name)
                self._items_model.setData(self._items_model.index(0, 3), product_price)
                self._items_model.setData(self._items_model.index(0, 4), product_quantity)
                ok = self._items_model.submitAll()
                if not ok:
                    error = True
                    break
            if error:
                self.log.error(self._items_model.lastError().text())
                message = unicode(
                    "Erro\n\n"
                    "Venda registrada e contabilizada, porém ocorreu um problema e"
                    " não será possível visualizar seus itens.".decode("utf-8")
                )
                QMessageBox.warning(self, "Seareiros - Vendas do Bazar", message)
                return False
            else:
                # all went fine
                # retrieving some brief info of the order to display at the main window
                if "associate" in data:
                    desc = "Venda do bazar no valor de R$ %s para %s" % (
                        self._locale.toString(data["total"], "f", 2).replace(".", ""),
                        self.lblNickname.text(),
                    )
                else:
                    desc = "Venda do bazar no valor de R$ %s" % self._locale.toString(data["total"], "f", 2).replace(
                        ".", ""
                    )
                if not log_to_history(self._model.database(), "venda_bazar", order_id, desc):
                    self.log.error(self._model.lastError().text())
                message = unicode("Sucesso!\n\n" "Venda concluída.".decode("utf-8"))
                QMessageBox.information(self, "Seareiros - Vendas do Bazar", message)
                return True
        # failed to insert a row
        return False

    def clear(self):
        """ Globally cleans this form """
        self._dirty = False
        for lineEdit in self.findChildren(QLineEdit):
            lineEdit.clear()
        # product
        # edProduct is a QLineEdit so... already clean
        self.clear_table()
        self.lblTotal.setText("0,00")
        self.edQuantity.setValue(1)
        # associate
        self.clear_associate()

        self.edProductName.setFocus()

    def clear_associate(self):
        # resets associate frame
        self.lblName.clear()
        self.lblNickname.clear()
        self._associate_id = None
        self.frameAssociate.setVisible(False)
        self.btnCleanAssociate.setVisible(False)
        # can't allow an order to be paid later without an associate to relate to
        self.rdNotPaid.setEnabled(False)
        self.rdPaid.setChecked(True)

    @QtCore.Slot()
    def on_btnAddProduct_clicked(self):
        txt = self.edProductName.text()
        price = self._locale.toDouble(self.edPrice.text())[0]
        quantity = self.edQuantity.value()
        if txt != "":
            data = [txt, price, quantity]
            self.add_product(data)
            self.update_total(price * quantity)
            self.refresh_tableProducts()
            # cleaning product related input
            self.edProductName.clear()
            self.edPrice.setText("0,00")
            self.edQuantity.setValue(1)
            self.edProductName.setFocus()

    @QtCore.Slot()
    def on_btnSelectAssociate_clicked(self):
        associate_dialog = AssociateSelectDialog()
        if associate_dialog.exec_() == QDialog.Accepted:
            record = associate_dialog.get_record()
            self._associate_id = record.value("id")
            self.set_associate_info(record.value("fullname"), record.value("nickname"))
            self.frameAssociate.setVisible(True)
            self.btnCleanAssociate.setVisible(True)
            # a registered associate can pay later
            self.rdNotPaid.setEnabled(True)
            self.edProductName.setFocus()

    def set_associate_info(self, fullname, nickname):
        self.lblName.setText(fullname)
        self.lblNickname.setText(nickname)

    @QtCore.Slot()
    def on_btnCleanAssociate_clicked(self):
        self.clear_associate()

    def update_total(self, price, add=True):
        if add:
            self._total += price
        else:
            self._total -= price
        txt = self._locale.toString(self._total, "f", 2).replace(".", "")
        if txt == "0":
            txt = txt.replace(txt, "0,00")
        self.lblTotal.setText(txt)

    @QtCore.Slot()
    def on_btnCleanProducts_clicked(self):
        self.clear_table()
        self._total = 0.0
        self.update_total(0.0)
        self.edPrice.setText("0,00")
        self.edQuantity.setValue(1)
        self.edProductName.clear()
        self.edProductName.setFocus()

    def clear_table(self):
        self._product_list = []
        self.tableProducts.clear()
        self.refresh_tableProducts()

    def add_product(self, data):
        """ adds a product to the list then sort it """
        self._product_list.append(data)
        # sorts by name
        self._product_list.sort(key=operator.itemgetter(0))

    def refresh_tableProducts(self):
        if len(self._product_list) > 0:
            self.tableProducts.setColumnCount(len(self._product_list[0]) + 1)
            col_labels = ["Produto", unicode("Preço (R$)".decode("utf-8")), "Qtd", ""]
            self.tableProducts.setHorizontalHeaderLabels(col_labels)
        else:
            self.tableProducts.setColumnCount(0)
        self.tableProducts.setRowCount(len(self._product_list))
        for i, row in enumerate(self._product_list):
            for j, col in enumerate(row):
                if j == 1:
                    # product price
                    item = QTableWidgetItem(self._locale.toString(col, "f", 2).replace(".", ""))
                elif j == 2:
                    # product quantity
                    item = QTableWidgetItem(str(col))
                else:
                    item = QTableWidgetItem(col)
                self.tableProducts.setItem(i, j, item)
            # icon to remove rows individually
            remove_icon = QIcon(":icons/conn_failed.png")
            remove_btn = QPushButton(remove_icon, "")
            remove_btn.clicked.connect(partial(self.remove_product, product=row))
            self.tableProducts.setCellWidget(i, len(row), remove_btn)
        self.tableProducts.resizeColumnsToContents()
        self.tableProducts.horizontalHeader().setResizeMode(0, QHeaderView.Stretch)

    def remove_product(self, product):
        # remove a row based on its value
        subtract_value = product[1] * product[2]
        self._product_list.remove(product)
        self.refresh_tableProducts()
        self.update_total(subtract_value, add=False)

    def extract_input(self):
        data = {}
        if self._associate_id:
            data["associate"] = self._associate_id
        data["obs"] = self.edObs.toPlainText()
        data["total"] = self._total
        if self.rdPaid.isChecked():
            data["paid"] = True
        else:
            data["paid"] = False
        data["type"] = constants.ORDER_PRODUCT
        return data
Exemple #11
0
	def _mapdata(self):
		assert self.model.isDBLoaded()
		self.datamodel=QSqlTableModel(self.view,self.model.db)
		self.datamodel.setTable(self.name)
		self.refresh()
Exemple #12
0
    def InitTable(self):
        """Funzione che accede al database ed imposta il data model"""
        db = QSqlDatabase.addDatabase("QSQLITE")

        db.setDatabaseName(self.myWidget.txtPercorso.text())
        db.open()

        model = QSqlTableModel()
        model.setTable("contatti")
        model.setEditStrategy(QSqlTableModel.OnManualSubmit)
        model.select()
        model.setHeaderData(0, QtCore.Qt.Horizontal, "Nome")
        model.setHeaderData(1, QtCore.Qt.Horizontal, "Cognome")
        model.setHeaderData(2, QtCore.Qt.Horizontal, "Telefono")

        self.tableModel = model
        self.myWidget.lstRubrica.setModel(model)
Exemple #13
0
class BookOrderForm(QScrollArea, Ui_BookOForm):
    """ Interface for ordering books """

    column = { 'associate':1, 'obs':3, 'total':4, 'paid':5, 'type':7 }


    def __init__(self, parent=None):
        super(BookOrderForm, self).__init__(parent)
        self.setupUi(self)

        self._access = statics.access_level
        # for currency formatting
        self._locale = QLocale()

        # had to hardcode these, wouldn't work otherwise:
        self.contentsLayout.setAlignment(self.groupBox, QtCore.Qt.AlignTop)
        self.contentsLayout.setAlignment(self.groupBox_2, QtCore.Qt.AlignTop)
        self.contentsLayout.setAlignment(self.groupBox_3, QtCore.Qt.AlignTop)
        self.contentsLayout.setAlignment(self.groupBox_4, QtCore.Qt.AlignTop)


        self.log = logging.getLogger('BookOForm')

        self.setup_model()
        self.setup_fields()

        # associate present flag
        self._associate_id = None
        # book internals
        self._book_list = []
        self._total = 0.0

        # flag to indicate whether there were changes to the fields
        self._dirty = False

    def is_dirty(self):
        return self._dirty

    def setup_model(self):
        db = Db_Instance("oform_book").get_instance()
        if not db.open():
            self.log.error(db.lastError().text())
            message = unicode("Erro de conexão\n\n""Banco de dados indisponível".decode('utf-8'))
            QMessageBox.critical(self, "Seareiros - Livraria", message)
        else:
            # book order
            self._model = QSqlTableModel(self, db=db)
            self._model.setTable("order_request")
            # book order items
            self._items_model = QSqlTableModel(self, db=db)
            self._items_model.setTable("book_order_item")

    def setup_fields(self):
        """ setting up validators and stuff """
        # validators
        self.edBarcode.setValidator(NumericValidator())
        # hiding associate frame and clean button
        self.frameAssociate.setVisible(False)
        self.btnCleanAssociate.setVisible(False)
        # detect changes on edBarcode for dirtiness and completion
        self.edBarcode.textChanged.connect(self.check_changes)
        self.edBarcode.textChanged.connect(self.check_barcode)

    def check_changes(self, txt):
        if txt != '':
            self._dirty = True

    def check_barcode(self, txt):
        if len(txt) == self.edBarcode.maxLength():
            db = Db_Instance("obook_barcode_search").get_instance()
            try:
                if db.open():
                    query = QSqlQuery(db)
                    query.prepare("SELECT * FROM book WHERE barcode = :barcode")
                    query.bindValue(":barcode", txt)
                    query.exec_()
                    if query.next():
                        self.add_book_from_record(query.record())
                        self.edBarcode.clear()
                    else:
                        raise RecordNotFoundException
                else:
                    raise DbUnavailableException
            except RecordNotFoundException:
                message = unicode("Código de barra inválido!\n\n"""
                              "O código informado não corresponde a nenhum livro cadastrado".decode('utf-8'))
                QMessageBox.critical(self, "Seareiros - Livraria", message)
            except DbUnavailableException:
                self.log.error(db.lastError().text())
                message = unicode("Erro de conexão\n\n""Banco de dados indisponível".decode('utf-8'))
                QMessageBox.critical(self, "Seareiros - Livraria", message)
            self.edBarcode.setFocus()

    def submit_data(self):
        if len(self._book_list) == 0:
            message = unicode("Venda vazia!\n\n"""
                              "É necessário adicionar um livro antes de concluir uma venda".decode('utf-8'))
            QMessageBox.critical(self, "Seareiros - Livraria", message)
            self.edBarcode.setFocus()
            return False
        data = self.extract_input()
        # filling a book order
        self._model.insertRow(0)
        for key,val in data.items():
            self._model.setData(self._model.index(0, self.column[key]), val)
        order_id = submit_and_get_id(self, self._model, self.log)
        if order_id:
            # order creation success, placing items
            error = False
            for item in self._book_list:
                book_id = item[0]
                book_quantity = item[3]
                self._items_model.insertRow(0)
                self._items_model.setData(self._items_model.index(0,1), order_id)
                self._items_model.setData(self._items_model.index(0,2), book_id)
                self._items_model.setData(self._items_model.index(0,3), book_quantity)
                ok = self._items_model.submitAll()
                if not ok:
                    error = True
                    break
            if error:
                self.log.error(self._items_model.lastError().text())
                message = unicode("Erro\n\n""Venda registrada e contabilizada, porém ocorreu um problema e"
                              " não será possível visualizar seus itens.".decode('utf-8'))
                QMessageBox.warning(self, "Seareiros - Livraria", message)
                return False
            else:
                # all went fine
                # retrieving some brief info of the order to display at the main window
                if 'associate' in data:
                    desc = "Venda da livraria no valor de R$ %s para %s" % \
                           (self._locale.toString(data['total'], 'f', 2).replace('.',''), self.lblNickname.text())
                else:
                    desc = "Venda da livraria no valor de R$ %s" % self._locale.toString(data['total'], 'f', 2).replace('.','')
                if not log_to_history(self._model.database(), "venda_livraria", order_id, desc):
                    self.log.error(self._model.lastError().text())
                message = unicode("Sucesso!\n\n""Venda concluída.".decode('utf-8'))
                QMessageBox.information(self, "Seareiros - Livraria", message)
                return True
        # failed to insert a row
        return False

    def clear(self):
        """ Globally cleans this form """
        self._dirty = False
        for lineEdit in self.findChildren(QLineEdit):
            lineEdit.clear()
        # book
        self.clear_table()
        self.lblTotal.setText("0,00")
        # associate
        self.clear_associate()

        self.edBarcode.setFocus()

    def clear_associate(self):
        # resets associate frame
        self.lblName.clear()
        self.lblNickname.clear()
        self._associate_id = None
        self.frameAssociate.setVisible(False)
        self.btnCleanAssociate.setVisible(False)
        # can't allow an order to be paid later without an associate to relate to
        self.rdNotPaid.setEnabled(False)
        self.rdPaid.setChecked(True)

    @QtCore.Slot()
    def on_btnSelectAssociate_clicked(self):
        associate_dialog = AssociateSelectDialog()
        if associate_dialog.exec_() == QDialog.Accepted:
            record = associate_dialog.get_record()
            self._associate_id = record.value("id")
            self.set_associate_info(record.value("fullname"), record.value("nickname"))
            self.frameAssociate.setVisible(True)
            self.btnCleanAssociate.setVisible(True)
            # a registered associate can pay later
            self.rdNotPaid.setEnabled(True)
            self.edBarcode.setFocus()

    @QtCore.Slot()
    def on_btnSelectBook_clicked(self):
        book_dialog = BookSelectDialog()
        if book_dialog.exec_() == QDialog.Accepted:
            record = book_dialog.get_record()
            self.add_book_from_record(record)

    def add_book_from_record(self, record):
        book_id = record.value("id")
        book_title = record.value("title")
        book_price = record.value("price")
        book_quantity = 1
        book_stock = record.value("stock")
        data = [book_id, book_title, book_price, book_quantity, book_stock]
        try:
            self.add_book(data)
            self.refresh_tableBooks()
            self.edBarcode.clear()
            self.edBarcode.setFocus()
        except StockOverflowException:
            message = unicode("Estoque Insuficiente!\n\n""A quantidade do item excedeu o estoque".decode('utf-8'))
            QMessageBox.critical(self, "Seareiros - Livraria", message)

    def set_associate_info(self, fullname, nickname):
        self.lblName.setText(fullname)
        self.lblNickname.setText(nickname)

    @QtCore.Slot()
    def on_btnCleanAssociate_clicked(self):
        self.clear_associate()

    def update_total(self, price, add=True):
        if add:
            self._total += price
        else:
            self._total -= price
        txt = self._locale.toString(self._total, 'f', 2).replace('.','')
        if txt == '0':
            txt = txt.replace(txt, "0,00")
        self.lblTotal.setText(txt)

    @QtCore.Slot()
    def on_btnCleanBooks_clicked(self):
        self.clear_table()
        self._total = 0.0
        self.update_total(0.0)
        self.edBarcode.clear()
        self.edBarcode.setFocus()

    def clear_table(self):
        self._book_list = []
        self.tableBooks.clear()
        self.refresh_tableBooks()

    def add_book(self, data):
        """ adds a book to the list then sort it """
        # checking for duplicate
        dup_index = [i for i,x in enumerate(self._book_list) if x[0] == data[0]]
        if not dup_index:
            # not a duplicate
            self._book_list.append(data)
        else:
            # duplicate
            idx = dup_index[0]
            # increment quantity
            new_quantity = self._book_list[idx][3] + 1
            stock = self._book_list[idx][4]
            if new_quantity > stock:
                raise StockOverflowException
            else:
                self._book_list[idx][3] += 1
        self.update_total(data[2], add=True)
        # sorts by title
        self._book_list.sort(key=operator.itemgetter(1))

    def refresh_tableBooks(self):
        if len(self._book_list) > 0:
            self.tableBooks.setColumnCount(len(self._book_list[0])-1)
            col_labels = ["Livro", unicode("Preço (R$)".decode('utf-8')), "Qtd", ""]
            self.tableBooks.setHorizontalHeaderLabels(col_labels)
        else:
            self.tableBooks.setColumnCount(0)
        self.tableBooks.setRowCount(len(self._book_list))
        for i, row in enumerate(self._book_list):
            for j, col in enumerate(row):
                if j == 1:
                    # title
                    item = QTableWidgetItem(col)
                elif j == 2:
                    # price
                    item = QTableWidgetItem(self._locale.toString(col, 'f', 2).replace('.',''))
                elif j == 3:
                    # quantity
                    edQuantity = ReturnKeySpinBox(self)
                    edQuantity.setMinimum(1)
                    edQuantity.setMaximum(row[4])
                    edQuantity.setValue(col)
                    edQuantity.valueChanged.connect(partial(self.update_quantity, book=row))
                    self.tableBooks.setCellWidget(i, j-1, edQuantity)
                if j in [1,2]:
                    # ignoring id
                    self.tableBooks.setItem(i, j-1, item)
            # remove button on last column
            remove_icon = QIcon(":icons/conn_failed.png")
            remove_btn = QPushButton(remove_icon, "")
            remove_btn.clicked.connect(partial(self.remove_book, book=row))
            self.tableBooks.setCellWidget(i, len(row)-2, remove_btn)
        self.tableBooks.resizeColumnsToContents()
        self.tableBooks.horizontalHeader().setResizeMode(0, QHeaderView.Stretch)

    def remove_book(self, book):
        # remove a row based on its value
        subtract_value = book[2] * book[3]
        self._book_list.remove(book)
        self.refresh_tableBooks()
        self.update_total(subtract_value, add=False)

    def update_quantity(self, i, book):
        new_value = i
        old_value = book[3]
        if old_value == new_value:
            # this happens sometimes when refreshing the table
            return
        price = book[1]
        index = self._book_list.index(book)
        book[3] = new_value
        self._book_list[index] = book
        if new_value > old_value:
            # incremented
            self.update_total((new_value - old_value)*book[2], add=True)
        elif new_value < old_value:
            # decremented
            self.update_total((old_value - new_value)*book[2], add=False)

    def extract_input(self):
        data = {}
        if self._associate_id:
            data['associate'] = self._associate_id
        data['obs'] = self.edObs.toPlainText()
        data['total'] = self._total
        if self.rdPaid.isChecked():
            data['paid'] = True
        else:
            data['paid'] = False
        data['type'] = constants.ORDER_BOOK
        return data
Exemple #14
0
class BookEditForm(QScrollArea, Ui_BookForm):
    """ Interface for book edit """

    column = {
            'id':0, 'barcode':1, 'title':2, 'author':3, 's_author':4, 'publisher':5, 'year':6, 'price':7,
            'description':8, 'stock':9, 'image':10, 'availability':11 }
    IMG_SIZE = (150, 150)

    def __init__(self, record_id, parent=None):
        super(BookEditForm, self).__init__(parent)
        self.setupUi(self)
        # had to subclass this spinbox to support return grabbing
        self.edYear = ReturnKeySpinBox(self)
        self.edYearHolder.addWidget(self.edYear)
        # configuring id's for radio group
        self.radioAvailability.setId(self.rdSell,0)
        self.radioAvailability.setId(self.rdRent,1)
        self.radioAvailability.setId(self.rdInactive,2)
        # overlaying a clean button over the image (couldn't do it in designer)
        self.btnCleanImage = QPushButton()
        self.btnCleanImage.setIcon(QIcon(":icons/clean.png"))
        self.btnCleanImage.setFixedWidth(35)
        self.btnCleanImage.clicked.connect(self.clear_image)
        self.btnCleanImage.setVisible(False)
        clean_img_layout = QVBoxLayout(self.edImage)
        clean_img_layout.addWidget(self.btnCleanImage)
        clean_img_layout.setAlignment(Qt.AlignTop | Qt.AlignLeft)
        clean_img_layout.setContentsMargins(2,2,0,0)

        self._access = statics.access_level
        # for currency formatting
        self._locale = QLocale()
        self._record_id = record_id

        # had to hardcode these, wouldn't work otherwise:
        self.contentsLayout.setAlignment(self.groupBox, QtCore.Qt.AlignTop)
        self.contentsLayout.setAlignment(self.groupBox_2, QtCore.Qt.AlignTop)

        self.log = logging.getLogger('BookEditForm')

        self._subject_list = []

        self._removed_subjects = []
        self._added_subjects = []

        self.setup_model()
        self.fill_form()
        self.setup_fields()
        self._old_data = self.extract_input(text_only=True)

        # flag to indicate whether there were changes to the fields
        self._dirty = False
        # user did input an image
        self._image_set = False
        # image changed during edit
        self._image_changed = False

    def is_dirty(self):
        return self._dirty

    def setup_fields(self):
        """ setting up validators and stuff """
        # validators
        # forcing uppercasing on these fields
        self.edTitle.setValidator(UppercaseValidator())
        self.edAuthor.setValidator(UppercaseValidator())
        self.edSAuthor.setValidator(UppercaseValidator())
        self.edPublisher.setValidator(UppercaseValidator())
        self.edPrice.setValidator(CurrencyValidator(self.edPrice))
        self.edBarcode.setValidator(NumericValidator())
        self.edYear.setMinimum(1900)
        self.edYear.setMaximum(date.today().year)
        self.edYear.setValue(date.today().year)
        # fixing tab order
        self.setTabOrder(self.edPublisher, self.edYear)
        self.setTabOrder(self.edYear, self.edPrice)
        # connecting return key to tab
        lineEditList = self.findChildren(QLineEdit)
        for lineEdit in lineEditList:
            # had some problem with C++ originated objects
            if lineEdit.objectName() not in ['qt_spinbox_lineedit', 'edSubject']:
                lineEdit.returnPressed.connect(lineEdit.focusNextChild)
            # detect changes on line edits
            lineEdit.textChanged.connect(self.check_changes)
        # different behaviour for these
        self.edBarcode.textChanged.connect(self.check_barcode)
        self.edSubject.returnPressed.connect(self.on_btnAddSubject_clicked)

        # completers
        config_completer(self.edSubject, self._subject_model, "name")
        config_completer(self.edAuthor, self._author_model, "name")
        config_completer(self.edSAuthor, self._s_author_model, "name")
        config_completer(self.edPublisher, self._publisher_model, "name")

        # making image clickable
        clickable(self.edImage).connect(self.handle_image)

    def fill_form(self):
        # retrieving book info
        self.edBarcode.setText(self._record.value("barcode"))
        self.edTitle.setText(self._record.value("title"))
        self.edYear.setValue(self._record.value("year"))
        self.edDescription.setPlainText(self._record.value("description"))
        self.radioAvailability.button(self._record.value("availability")).setChecked(True)
        # retrieving image
        ba = QByteArray(self._record.value("image"))
        if ba:
            self._image_set = True
            img = qbytearray_to_qimage(ba)
            self.set_image(img, clean_visible=True)
        # currency
        # TODO: ARRUMAR
        self.edPrice.setText(self._locale.toString(self._record.value("price"), 'f', 2).replace('.',''))
        # qcompleter fields
        self.edAuthor.setText(self._get_name_from_id("author", self._record.value("author_id")))
        self.edSAuthor.setText(self._get_name_from_id("s_author", self._record.value("s_author_id")))
        self.edPublisher.setText(self._get_name_from_id("publisher", self._record.value("publisher_id")))

        # retrieving subjects
        for subj_record in self._subj_records:
            self.add_subject([subj_record.value("id"),subj_record.value("name")])

        # clearing changes
        self._added_subjects[:] = []
        self.refresh_tableSubjects()

    def clear_image(self):
        img = QImage(":icons/no_image.png")
        self.set_image(img, clean_visible=False)
        if self._image_set:
            self._image_set = False
        self._image_changed = True

    def handle_image(self):
        image_path = QFileDialog.getOpenFileName(self, "Escolha uma imagem", os.getenv("HOME"), "Imagens (*.png, *.jpg *.bmp)")[0]
        if os.path.exists(image_path):
            self.set_image(QImage(image_path), clean_visible=True)
            self._image_set = True
            self._image_changed = True

    def set_image(self, img, clean_visible=False):
        pix = QPixmap.fromImage(img)
        pix = pix.scaled(self.IMG_SIZE[0], self.IMG_SIZE[1], Qt.KeepAspectRatio)
        self.edImage.setPixmap(pix)
        self.edImage.setScaledContents(True)
        self.btnCleanImage.setVisible(clean_visible)

    def check_changes(self, txt):
        # getting sender info
        sender = self.sender().objectName().split('ed')[1].lower()
        if sender != 'subject' and self._old_data[sender] != txt:
            self._dirty = True

    def check_barcode(self, txt):
        if len(txt) == self.edBarcode.maxLength():
            self.edBarcode.focusNextChild()

    def extract_input(self, text_only=False):
        data = {}
        data['barcode'] = self.edBarcode.text()
        data['title'] = self.edTitle.text()

        # completer fields
        for c_field, line_edit in [("author", self.edAuthor), ("s_author", self.edSAuthor), ("publisher", self.edPublisher)]:
            if not text_only:
                data[c_field] = self._get_cfield_value(c_field, line_edit.text())
            else:
                data[c_field] = line_edit.text()
        data['year'] = self.edYear.value()
        data['price'] = self._locale.toDouble(self.edPrice.text())[0]
        data['description'] = self.edDescription.toPlainText()
        if not text_only and self._image_changed and self._image_set:
            data['image'] = qpixmap_to_qbytearray(self.edImage.pixmap())

        data['availability'] = self.radioAvailability.checkedId()

        return data

    def setup_model(self):
        db = Db_Instance("edit_book").get_instance()
        if not db.open():
            self.log.error(db.lastError().text())
            message = unicode("Erro de conexão\n\n""Banco de dados indisponível".decode('utf-8'))
            QMessageBox.critical(self, unicode("Seareiros - Edição de Livro".decode('utf-8')), message)
        else:
            # book
            self._model = QSqlRelationalTableModel(self, db=db)
            self._model.setTable("book")
            self._model.setFilter("id = " + str(self._record_id))
            # self._model.setRelation(self.column["author"], QSqlRelation("author", "id", "name"))
            # self._model.setRelation(self.column["s_author"], QSqlRelation("s_author", "id", "name"))
            # self._model.setRelation(self.column["publisher"], QSqlRelation("publisher", "id", "name"))
            self._model.select()
            self._record = self._model.record(0)
            # models for setting up qcompleters:
            # book_in_subject
            self._book_in_subj_model = QSqlTableModel(self, db=db)
            self._book_in_subj_model.setTable("book_in_subject")
            # subject
            self._subject_model = QSqlTableModel(self, db=db)
            self._subject_model.setTable("subject")
            self._subject_model.select()
            # author
            self._author_model = QSqlTableModel(self, db=db)
            self._author_model.setTable("author")
            self._author_model.select()
            # s_author
            self._s_author_model = QSqlTableModel(self, db=db)
            self._s_author_model.setTable("s_author")
            self._s_author_model.select()
            # publisher
            self._publisher_model = QSqlTableModel(self, db=db)
            self._publisher_model.setTable("publisher")
            self._publisher_model.select()

            # retrieving current subjects, should probably place this elsewhere but it's related to models
            self._subject_records = []
            sql_statement = """SELECT id, name FROM subject s, book_in_subject b_s
                               WHERE s.id = b_s.subject_id AND b_s.book_id = %s
                            """ % str(self._record_id)
            read_only_subject_model = QSqlQueryModel()
            read_only_subject_model.setQuery(sql_statement, db)
            # checking query validity
            if not read_only_subject_model.lastError().isValid():
                self._subj_records = iterate_model(read_only_subject_model)

    def update_data(self):
        data = self.extract_input()
        # checking fields that aren't inserted yet
        for val, model in [('author', self._author_model), ('s_author', self._s_author_model),
                           ('publisher', self._publisher_model)]:
            if isinstance(data[val], unicode):
                # needs to be inserted
                model.insertRow(0)
                model.setData(model.index(0,1), data[val])
                data[val] = submit_and_get_id(self, model, self.log)
                if not data[val]:
                    # won't proceed if this fails
                    return False
        for key,val in data.items():
            self._model.setData(self._model.index(0, self.column[key]), val)
        if 'image' not in data and self._image_changed:
            # user cleared the image
            ok = self._model.setData(self._model.index(0, self.column['image']), None)
            print ok

        # try to commit changes
        if not self._model.submitAll():
            self.log.error(self._model.lastError().text())
            message = unicode("Erro de transação\n\n""Não foi possível salvar no banco de dados".decode('utf-8'))
            QMessageBox.critical(self, "Seareiros - Edição de Livro", message)
            return False
        else:
            # updating subjects
            error = False
            # added subjects
            for subj in self._added_subjects:
                # the list has the format [id, text] for existing subjects or [None, text] otherwise
                if not subj[0]:
                    # need to insert the subject before associating it with the book
                    self._subject_model.insertRow(0)
                    self._subject_model.setData(self._subject_model.index(0,1), subj[1])
                    subj[0] = submit_and_get_id(self, self._subject_model, self.log)
                    if not subj[0]:
                        error = True
                        break
                # have a valid record id for the subject to be associated
                self._book_in_subj_model.insertRow(0)
                self._book_in_subj_model.setData(self._book_in_subj_model.index(0,0), self._record_id)
                self._book_in_subj_model.setData(self._book_in_subj_model.index(0,1), subj[0])
                ok = self._book_in_subj_model.submitAll()
                if not ok:
                    error = True
                    self.log.error(self._book_in_subj_model.setLastError().text())
                    break
            # removed subjects
            for removed_id in self._removed_subjects:
                self._book_in_subj_model.setFilter("book_id = %s AND subject_id = %s" % (str(self._record_id),str(removed_id)))
                self._book_in_subj_model.select()
                self._book_in_subj_model.removeRow(0)
                if self._book_in_subj_model.lastError().isValid():
                    error = True
                    self.log.error(self._book_in_subj_model.lastError().text())
                    break
            if not error:
                message = unicode("Sucesso!\n\n""O livro foi atualizado com êxito no banco de dados".decode('utf-8'))
                QMessageBox.information(self, unicode("Seareiros - Edição de Livro".decode('utf-8')), message)
            else:
                message = unicode("Erro\n\n""Associado alterado, "
                                  "porém ocorreu um problema ao salvar suas atividades".decode('utf-8'))
                QMessageBox.warning(self, unicode("Seareiros - Edição de Livro".decode('utf-8')), message)
            # if I don't set this flag here it'll trigger a warning for altering data on the form
            self._dirty = False
            return True

    def _get_id_from_name(self, table, name):
        db = Db_Instance(table + "_fetch_" + name + "_id").get_instance()
        if not db.open():
            return None
        else:
            query = QSqlQuery(db)
            query.prepare("SELECT id FROM %s WHERE name = :name" % table)
            query.bindValue(":name", name)
            query.exec_()
            if query.next():
                return query.record().value("id")
            else:
                return None

    def _get_name_from_id(self, table, id):
        db = Db_Instance(table + "_fetch_" + str(id) + "_name").get_instance()
        if not db.open():
            return None
        else:
            query = QSqlQuery(db)
            query.prepare("SELECT name FROM %s WHERE id = :id" % table)
            query.bindValue(":name", id)
            query.exec_()
            if query.next():
                return query.record().value("name")
            else:
                return None

    @QtCore.Slot()
    def on_btnAddSubject_clicked(self):
        txt = self.edSubject.text()
        if txt != '':
            id = self._get_id_from_name('subject', self.edSubject.text())
            if id:
                # known register
                data = [id, txt]
            else:
                # new data
                data = [None, txt]
            not_a_duplicate = self.add_subject(data)
            if not_a_duplicate:
                self.refresh_tableSubjects()
                self.edSubject.clear()
            self.edSubject.setFocus()

    @QtCore.Slot()
    def on_btnCleanSubjects_clicked(self):
        self.clear_table()
        self.edSubject.setFocus()

    def clear_table(self):
        # can't directly change activity_list here
        itens = [i for i in self._subject_list]
        for item in itens:
            self.remove_subject(item)
        self._added_subjects[:] = []

    def add_subject(self, data):
        """ adds a subject to the list except for duplicates """
        if data in self._subject_list:
            return False
        else:
            if self.is_in_del_queue(data[0]):
                self._removed_subjects.remove(data[0])
            else:
                self._added_subjects.append(data)
            self._subject_list.append(data)
            # sorts by name
            self._subject_list.sort(key=operator.itemgetter(1))
            return True

    def refresh_tableSubjects(self):
        if len(self._subject_list) > 0:
            self.tableSubjects.setColumnCount(len(self._subject_list[0])+1)
            col_labels = ["", "Nome", ""]
            self.tableSubjects.setHorizontalHeaderLabels(col_labels)
            self.tableSubjects.setColumnHidden(0, True)
        else:
            self.tableSubjects.setColumnCount(0)
        self.tableSubjects.setRowCount(len(self._subject_list))
        for i, row in enumerate(self._subject_list):
            for j, col in enumerate(row):
                item = QTableWidgetItem(col)
                self.tableSubjects.setItem(i, j, item)
            # icon to remove rows individually
            remove_icon = QIcon(":icons/conn_failed.png")
            remove_btn = QPushButton(remove_icon, "")
            remove_btn.clicked.connect(partial(self.remove_subject, subject=row))
            self.tableSubjects.setCellWidget(i, len(row), remove_btn)
        self.tableSubjects.resizeColumnsToContents()
        self.tableSubjects.horizontalHeader().setResizeMode(1, QHeaderView.Stretch)

    def is_in_del_queue(self, id):
        return id in self._removed_subjects

    def is_in_add_queue(self, data):
        return data in self._added_subjects

    def remove_subject(self, subject):
        # remove a row based on its value
        self._subject_list.remove(subject)
        if self.is_in_add_queue(subject):
             # unqueue previously added activity
            self._added_subjects.remove(subject)
        else:
            id = subject[0]
            if id:
                self._removed_subjects.append(id)
        self.refresh_tableSubjects()

    def _get_cfield_value(self, c_field, text):
        if text == '':
            return None
        id = self._get_id_from_name(c_field, text)
        if id:
            return id
        else:
            return text
Exemple #15
0
    def InitTable(self):
        """Funzione che accede al database ed imposta il data model"""
        db = QSqlDatabase.addDatabase("QSQLITE")

        db.setDatabaseName(self.myWidget.txtPercorso.text())
        db.open()
        
        model =  QSqlTableModel()
        model.setTable("contatti")
        model.setEditStrategy(QSqlTableModel.OnManualSubmit)
        model.select()
        model.setHeaderData(0, QtCore.Qt.Horizontal, "Nome")
        model.setHeaderData(1, QtCore.Qt.Horizontal, "Cognome")
        model.setHeaderData(2, QtCore.Qt.Horizontal, "Telefono")
                
        self.tableModel = model
        self.myWidget.lstRubrica.setModel(model)
Exemple #16
0
class BookAddForm(QScrollArea, Ui_BookForm):
    """ Interface for book input """

    column = {
        "barcode": 1,
        "title": 2,
        "author": 3,
        "s_author": 4,
        "publisher": 5,
        "year": 6,
        "price": 7,
        "description": 8,
        "stock": 9,
        "image": 10,
        "availability": 11,
    }

    IMG_SIZE = (150, 150)

    def __init__(self, parent=None):
        super(BookAddForm, self).__init__(parent)
        self.setupUi(self)
        # had to subclass this spinbox to support return grabbing
        self.edYear = ReturnKeySpinBox(self)
        self.edYearHolder.addWidget(self.edYear)
        # configuring id's for radio group
        self.radioAvailability.setId(self.rdSell, 0)
        self.radioAvailability.setId(self.rdRent, 1)
        self.radioAvailability.setId(self.rdInactive, 2)

        self._access = statics.access_level
        # for currency formatting
        self._locale = QLocale()

        # had to hardcode these, wouldn't work otherwise:
        self.contentsLayout.setAlignment(self.groupBox, QtCore.Qt.AlignTop)
        self.contentsLayout.setAlignment(self.groupBox_2, QtCore.Qt.AlignTop)

        self.log = logging.getLogger("BookForm")

        self.setup_model()
        self.setup_fields()

        self._subject_list = []

        # flag to indicate whether there were changes to the fields
        self._dirty = False
        # for use in selection docks, indicates a saved record
        self._book_id = None
        # user did input an image
        self._image_set = False

        # overlaying a clean button over the image (couldn't do it in designer)
        self.btnCleanImage = QPushButton()
        self.btnCleanImage.setIcon(QIcon(":icons/clean.png"))
        self.btnCleanImage.setFixedWidth(35)
        self.btnCleanImage.clicked.connect(self.clear_image)
        self.btnCleanImage.setVisible(False)
        clean_img_layout = QVBoxLayout(self.edImage)
        clean_img_layout.addWidget(self.btnCleanImage)
        clean_img_layout.setAlignment(Qt.AlignTop | Qt.AlignLeft)
        clean_img_layout.setContentsMargins(2, 2, 0, 0)

    def is_dirty(self):
        return self._dirty

    def setup_model(self):
        db = Db_Instance("form_book").get_instance()
        if not db.open():
            self.log.error(db.lastError().text())
            message = unicode("Erro de conexão\n\n" "Banco de dados indisponível".decode("utf-8"))
            QMessageBox.critical(self, "Seareiros - Cadastro de Livro", message)
        else:
            # book
            self._model = QSqlTableModel(self, db=db)
            self._model.setTable("book")
            # subject
            self._subject_model = QSqlTableModel(self, db=db)
            self._subject_model.setTable("subject")
            self._subject_model.select()
            # author
            self._author_model = QSqlTableModel(self, db=db)
            self._author_model.setTable("author")
            self._author_model.select()
            # sauthor
            self._s_author_model = QSqlTableModel(self, db=db)
            self._s_author_model.setTable("s_author")
            self._s_author_model.select()
            # publisher
            self._publisher_model = QSqlTableModel(self, db=db)
            self._publisher_model.setTable("publisher")
            self._publisher_model.select()
            # book subjects
            self._book_in_subj_model = QSqlTableModel(self, db=db)
            self._book_in_subj_model.setTable("book_in_subject")

    def setup_fields(self):
        """ setting up validators and stuff """
        # validators
        # forcing uppercasing on these fields
        self.edTitle.setValidator(UppercaseValidator())
        self.edAuthor.setValidator(UppercaseValidator())
        self.edSAuthor.setValidator(UppercaseValidator())
        self.edPublisher.setValidator(UppercaseValidator())
        self.edPrice.setValidator(CurrencyValidator(self.edPrice))
        self.edBarcode.setValidator(NumericValidator())
        self.edYear.setMinimum(1900)
        self.edYear.setMaximum(date.today().year)
        self.edYear.setValue(date.today().year)
        # fixing tab order
        self.setTabOrder(self.edPublisher, self.edYear)
        self.setTabOrder(self.edYear, self.edPrice)
        # connecting return key to tab
        lineEditList = self.findChildren(QLineEdit)
        for lineEdit in lineEditList:
            # had some problem with C++ originated objects
            if lineEdit.objectName() not in ["qt_spinbox_lineedit", "edSubject"]:
                lineEdit.returnPressed.connect(lineEdit.focusNextChild)
            # detect changes on line edits
            lineEdit.textChanged.connect(self.check_changes)
        # different behaviour for these
        self.edBarcode.textChanged.connect(self.check_barcode)
        self.edSubject.returnPressed.connect(self.on_btnAddSubject_clicked)

        # completers
        config_completer(self.edSubject, self._subject_model, "name")
        config_completer(self.edAuthor, self._author_model, "name")
        config_completer(self.edSAuthor, self._s_author_model, "name")
        config_completer(self.edPublisher, self._publisher_model, "name")

        # making image clickable
        clickable(self.edImage).connect(self.handle_image)

    def clear_image(self):
        img = QImage(":icons/no_image.png")
        self.set_image(img)
        self._image_set = False
        self.btnCleanImage.setVisible(False)

    def handle_image(self):
        image_path = QFileDialog.getOpenFileName(
            self, "Escolha uma imagem", os.getenv("HOME"), "Imagens (*.png, *.jpg *.bmp)"
        )[0]
        if os.path.exists(image_path):
            self.set_image(QImage(image_path))
            self._image_set = True
            self.btnCleanImage.setVisible(True)

    def set_image(self, img):
        pix = QPixmap.fromImage(img)
        pix = pix.scaled(self.IMG_SIZE[0], self.IMG_SIZE[1], Qt.KeepAspectRatio)
        self.edImage.setPixmap(pix)
        self.edImage.setScaledContents(True)

    def check_changes(self, txt):
        if txt != "":
            self._dirty = True

    def check_barcode(self, txt):
        if len(txt) == self.edBarcode.maxLength():
            self.edBarcode.focusNextChild()

    def _get_id_from_name(self, table, name):
        db = Db_Instance(table + "_fetch_" + name + "_id").get_instance()
        if not db.open():
            return None
        else:
            query = QSqlQuery(db)
            query.prepare("SELECT id FROM %s WHERE name = :name" % table)
            query.bindValue(":name", name)
            query.exec_()
            if query.next():
                return query.record().value("id")
            else:
                return None

    def submit_data(self):
        data = self.extract_input()
        # checking fields that aren't inserted yet
        for val, model in [
            ("author", self._author_model),
            ("s_author", self._s_author_model),
            ("publisher", self._publisher_model),
        ]:
            if isinstance(data[val], unicode):
                # needs to be inserted
                model.insertRow(0)
                model.setData(model.index(0, 1), data[val])
                data[val] = submit_and_get_id(self, model, self.log)
                if not data[val]:
                    # won't proceed if this fails
                    return False
        # filling a book row
        self._model.insertRow(0)
        for key, val in data.items():
            self._model.setData(self._model.index(0, self.column[key]), val)
        book_id = submit_and_get_id(self, self._model, self.log)
        if book_id:
            # for use in selection docks
            self.setBookId(book_id)
            # book sucessfully added, now associating related subjects
            subjects, new_subjects = self.extract_subjects_input()
            for subj in new_subjects:
                self._subject_model.insertRow(0)
                self._subject_model.setData(self._subject_model.index(0, 1), subj)
                id = submit_and_get_id(self, self._subject_model, self.log)
                if not id:
                    # issue saving new subject
                    return False
                subjects.append(int(id))
            # associating book and it's subjects
            error = False
            for subj_id in subjects:
                self._book_in_subj_model.insertRow(0)
                self._book_in_subj_model.setData(self._book_in_subj_model.index(0, 0), book_id)
                self._book_in_subj_model.setData(self._book_in_subj_model.index(0, 1), subj_id)
                ok = self._book_in_subj_model.submitAll()
                if not ok:
                    error = True
                    break
            if error:
                self.log.error(self._book_in_subj_model.lastError.text())
                message = unicode(
                    "Erro\n\n"
                    "Livro cadastrado, porém ocorreu um problema ao"
                    " salvar os temas a que está associado".decode("utf-8")
                )
                QMessageBox.warning(self, "Seareiros - Cadastro de Livro", message)
                return False
            else:
                message = unicode("Sucesso!\n\n" "O livro foi salvo com êxito no banco de dados".decode("utf-8"))
                QMessageBox.information(self, "Seareiros - Cadastro de Livro", message)
                return True
        # failed to insert a row
        return False

    def setBookId(self, id):
        self._book_id = id

    def get_added_record(self):
        db = Db_Instance("added_book_record").get_instance()
        if db.open() and self._book_id:
            query = QSqlQuery(db)
            query.prepare("SELECT * FROM book WHERE id = :id")
            query.bindValue(":id", self._book_id)
            query.exec_()
            if query.next():
                return query.record()
            else:
                return None
        else:
            return None

    def clear(self):
        self._dirty = False
        lineEditList = self.findChildren(QLineEdit)
        for lineEdit in lineEditList:
            lineEdit.clear()
        self.clear_table()
        self.clear_image()
        self.edBarcode.setFocus()

    @QtCore.Slot()
    def on_btnAddSubject_clicked(self):
        txt = self.edSubject.text()
        if txt != "":
            id = self._get_id_from_name("subject", self.edSubject.text())
            if id:
                # known register
                data = [id, txt]
            else:
                # new data
                data = [None, txt]
            not_a_duplicate = self.add_subject(data)
            if not_a_duplicate:
                self.refresh_tableSubjects()
                self.edSubject.clear()
            self.edSubject.setFocus()

    @QtCore.Slot()
    def on_btnCleanSubjects_clicked(self):
        self.clear_table()
        self.edSubject.setFocus()

    def clear_table(self):
        self._subject_list = []
        self.tableSubjects.clear()
        self.refresh_tableSubjects()

    def add_subject(self, data):
        """ adds a subject to the list except for duplicates """
        if data in self._subject_list:
            return False
        else:
            self._subject_list.append(data)
            # sorts by name
            self._subject_list.sort(key=operator.itemgetter(1))
            return True

    def refresh_tableSubjects(self):
        if len(self._subject_list) > 0:
            self.tableSubjects.setColumnCount(len(self._subject_list[0]) + 1)
            col_labels = ["", "Nome", ""]
            self.tableSubjects.setHorizontalHeaderLabels(col_labels)
            self.tableSubjects.setColumnHidden(0, True)
        else:
            self.tableSubjects.setColumnCount(0)
        self.tableSubjects.setRowCount(len(self._subject_list))
        for i, row in enumerate(self._subject_list):
            for j, col in enumerate(row):
                item = QTableWidgetItem(col)
                self.tableSubjects.setItem(i, j, item)
            # icon to remove rows individually
            remove_icon = QIcon(":icons/conn_failed.png")
            remove_btn = QPushButton(remove_icon, "")
            remove_btn.clicked.connect(partial(self.remove_subject, subject=row))
            self.tableSubjects.setCellWidget(i, len(row), remove_btn)
        self.tableSubjects.resizeColumnsToContents()
        self.tableSubjects.horizontalHeader().setResizeMode(1, QHeaderView.Stretch)

    def remove_subject(self, subject):
        # remove a row based on its value
        self._subject_list.remove(subject)
        self.refresh_tableSubjects()

    def extract_input(self):
        data = {}
        data["barcode"] = self.edBarcode.text()
        data["title"] = self.edTitle.text()

        # completer fields
        for c_field, line_edit in [
            ("author", self.edAuthor),
            ("s_author", self.edSAuthor),
            ("publisher", self.edPublisher),
        ]:
            data[c_field] = self._get_cfield_value(c_field, line_edit.text())
        data["year"] = self.edYear.value()
        data["price"] = self._locale.toDouble(self.edPrice.text())[0]
        data["description"] = self.edDescription.toPlainText()
        if self._image_set:
            data["image"] = qpixmap_to_qbytearray(self.edImage.pixmap())

        data["availability"] = self.radioAvailability.checkedId()

        return data

    def _get_cfield_value(self, c_field, text):
        if text == "":
            return None
        id = self._get_id_from_name(c_field, text)
        if id:
            return id
        else:
            return text

    def extract_subjects_input(self):
        # grab id of selected activities
        subjects = []
        new_subjects = []
        for subj in self._subject_list:
            if subj[0]:
                # selected from previously added subjects
                subjects.append(subj[0])
            else:
                # new subject
                new_subjects.append(subj[1])
        return (subjects, new_subjects)
class IntervenantUI(TableUI):
    """Classe chargée de l'interface de gestion des intervenants"""
    def setupModel(self):
        u"""Définit et configure le modèle sous-jacent à la table"""
        self._modele = QSqlTableModel(self)
        self._modele.setTable("intervenant")
        self._modele.setHeaderData(1, Qt.Horizontal, "Nom")
        self._modele.setHeaderData(2, Qt.Horizontal, u"Téléphone")
        self._modele.setHeaderData(3, Qt.Horizontal, "Email")
        self._modele.setEditStrategy(QSqlTableModel.OnFieldChange)
        self._modele.select()

        self._ui.tv.setModel(self._modele)

    def msgValidationNouveau(self):
        u"""Message d'erreur quand on veut créer deux items de suite"""
        return u"Valider l'intervenant avant d'en recréer un nouveau"

    def titreErrSuppression(self):
        return u"Cliquer sur l'intervenant à supprimer"

    def msgErrSuppression(self):
        return u"""Veuiller cliquer sur un intervenant avant de cliquer sur \
supprimer"""

    def msgSuppression(self, index):
        return u"Êtes-vous sûr de vouloir supprimer l'intervenant " + index.sibling(
            index.row(), 1).data() + " ? "

    def preSupprVerification(self, index):
        u"""Vérification à effectuer avant d'autoriser à supprimer un item
        
        Renvoit False si la suppression est interdite
        
        """
        sql = """
          SELECT COUNT(*)
          FROM absence
          WHERE id_intervenant=""" + str(index.sibling(index.row(), 0).data())
        req = QSqlQuery()
        if req.exec_(sql):
            req.next()
            nbAbsences = req.record().value(0)
            if nbAbsences != 0:
                pl = ""
                if nbAbsences != 1:
                    pl = "s"
                QMessageBox.critical(
                    self, "Impossible de suppprimer",
                    u"L'intervenant a encore " + str(nbAbsences) +
                    u" absence" + pl + u" enregistrée" + pl + "<br />" +
                    u"Il faut les supprimer avant")
                # TODO trouver un moyen de setter l'onglet de l'application
                # self._ui.tabWidget.setCurrentIndex(1)
                return False
        # TODO gérer le else, au moins logger quelque chose

        return True
class IntervenantUI(TableUI):
    """Classe chargée de l'interface de gestion des intervenants"""

    def setupModel(self):
        u"""Définit et configure le modèle sous-jacent à la table"""
        self._modele = QSqlTableModel(self)
        self._modele.setTable("intervenant")
        self._modele.setHeaderData(1, Qt.Horizontal, "Nom")
        self._modele.setHeaderData(2, Qt.Horizontal, u"Téléphone")
        self._modele.setHeaderData(3, Qt.Horizontal, "Email")
        self._modele.setEditStrategy(QSqlTableModel.OnFieldChange)
        self._modele.select()

        self._ui.tv.setModel(self._modele)

    def msgValidationNouveau(self):
        u"""Message d'erreur quand on veut créer deux items de suite"""
        return u"Valider l'intervenant avant d'en recréer un nouveau"

    def titreErrSuppression(self):
        return u"Cliquer sur l'intervenant à supprimer"

    def msgErrSuppression(self):
        return u"""Veuiller cliquer sur un intervenant avant de cliquer sur \
supprimer"""

    def msgSuppression(self, index):
        return u"Êtes-vous sûr de vouloir supprimer l'intervenant " + index.sibling(index.row(), 1).data() + " ? "

    def preSupprVerification(self, index):
        u"""Vérification à effectuer avant d'autoriser à supprimer un item
        
        Renvoit False si la suppression est interdite
        
        """
        sql = """
          SELECT COUNT(*)
          FROM absence
          WHERE id_intervenant=""" + str(index.sibling(index.row(), 0).data())
        req = QSqlQuery()
        if req.exec_(sql):
            req.next()
            nbAbsences = req.record().value(0)
            if nbAbsences != 0:
                pl = ""
                if nbAbsences != 1:
                    pl = "s"
                QMessageBox.critical(self, "Impossible de suppprimer",
                    u"L'intervenant a encore " + str(nbAbsences) +
                    u" absence" + pl + u" enregistrée" + pl + "<br />" +
                    u"Il faut les supprimer avant")
                # TODO trouver un moyen de setter l'onglet de l'application
                # self._ui.tabWidget.setCurrentIndex(1)
                return False
        # TODO gérer le else, au moins logger quelque chose

        return True
Exemple #19
0
def log_to_history(db_session, type, id_ref, description):
    """ logs a short summary to be displayed on the overview dock """
    # history
    model = QSqlTableModel(db=db_session)
    model.setTable("history")
    model.insertRow(0)
    model.setData(model.index(0,1), type)
    model.setData(model.index(0,2), id_ref)
    model.setData(model.index(0,3), description)
    model.setData(model.index(0,5), statics.username)
    if model.submitAll():
        return True
    return False