Пример #1
0
 def setup_model(self):
     db = Db_Instance("edit_associate").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 Associado".decode('utf-8')), message)
     else:
         self._model = QSqlRelationalTableModel(self, db=db)
         self._model.setTable("associate")
         self._act_model = QSqlRelationalTableModel(self, db=db)
         self._act_model.setTable("associate_in_activity")
         # TODO: Maybe I should validate these
         # associate
         self._model.setFilter("id = " + str(self._record_id))
         self._model.select()
         self._record = self._model.record(0)
         # activities
         self._activity_records = []
         sql_statement = """SELECT id, description, room, weekday, weektime FROM activity a,
                            associate_in_activity a_a WHERE
                            a.id = a_a.id_activity AND a_a.id_associate = %s
                         """ % str(self._record_id)
         model_activities = QSqlQueryModel()
         model_activities.setQuery(sql_statement, db)
         # checking query validity
         if not model_activities.lastError().isValid():
             self._activity_records = iterate_model(model_activities)
Пример #2
0
 def setup_model(self):
     db = Db_Instance("form_associate").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 Associado", message)
     else:
         self._model = QSqlRelationalTableModel(self, db=db)
         self._model.setTable("associate")
         self._act_model = QSqlRelationalTableModel(self, db=db)
         self._act_model.setTable("associate_in_activity")
Пример #3
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)
Пример #4
0
    def __init__(self, parent=None, *args):
        QSqlRelationalTableModel.__init__(self, parent=None, *args)

        self.name = 'Employees'
        self.table = 'employee' # the actual name of the table
        self.setTable(self.table)
        self.setEditStrategy(QSqlRelationalTableModel.OnManualSubmit)

        #   This is the name that will be displayed to the user when referencing the data in this dataset.

        self.fieldnames = {
            0: ('id', 'ID')
            , 1: ('department_id', 'Department')
            , 2: ('first_name', 'First Name')
            , 3: ('last_name', 'Last Name')
            , 4: ('age', 'Age')
            , 5: ('sex', 'Gender')
            , 6: ('income', 'Income')
            , 7: ('last_update', 'Last Update')
            , 8: ('date_added', 'Date Added')
        }

    #   set default values for when new records are added
        self.default_values = {
            1: '1'
            , 4: '30'
            , 5: 'Male'
            , 7: timestr()
            , 8: timestr() 
        }

    #   set filter specs
        self.filter_specs = {
            0: None
            , 1: 'match' # currently, only uses case-insensitive match
            , 2: 'like' 
            , 3: 'like'
            , 4: 'range'
            , 5: 'match'
            , 6: 'range' # eg, x - y, or just x
            , 7: 'date_match' # match on the day, sans the time
        }
        # other possibilities to implement: 'one_cent' match within 1 cent

    #   specify combobox value list for fields with rigid options
        self.combobox_list = {
            5: ['Male', 'Female']
        }

        self.locked_fields = [0, 7, 8]
        self.hidden_fields = [0, 7]

    #   set up relationships
        self.foreign_keys = [1]
        self.setRelation(1, QSqlRelation('department', 'id', 'name'))

    #   set regex validation rules
        self.regex_patterns = {
            4: '^([1-9]|[0-9]{2}|1[0-2][0-9])$' # age must be between 1 and 129
        }

    #   set default sort order
        self.setSort(2, Qt.AscendingOrder)

    #   set default filter
        self.default_filter = self.table + ".id <= 1000"
        self.setFilter(self.default_filter)

        self.select()
Пример #5
0
class AssociateAddForm(QScrollArea, Ui_AssociateForm):
    """ Interface for associate input """

    column = {
            'fullname':1, 'nickname':2, 'rg':3, 'cpf':4, 'maritalstatus':5, 'email':6, 'streetaddress':7,
            'complement':8, 'district':9, 'province':10, 'city':11, 'cep':12,
            'phoneres':13, 'phonecom':14, 'phonepriv':15, 'active':17 }

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

        self._access = statics.access_level

        # configuring id's for radio group
        self.radioStatus.setId(self.rdActive,0)
        self.radioStatus.setId(self.rdInactive,1)

        # had to hardcode these, wouldn't work otherwise:
        self.contentsLayout.setAlignment(self.groupBox_5, QtCore.Qt.AlignTop)
        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('AssociateForm')
        self.setup_fields()

        self._activity_list = []

        self.setup_model()

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

    def is_dirty(self):
        return self._dirty

    def setup_fields(self):
        # setting up validators and stuff
        self.edFullName.setValidator(UppercaseValidator())
        self.edNickname.setValidator(UppercaseValidator())
        self.edEmail.setValidator(EmailValidator())
        self.edRG.setValidator(AlphaNumericValidator())
        lineEditList = self.findChildren(QLineEdit)
        comboBoxList = self.findChildren(QComboBox)
        for lineEdit in lineEditList:
            lineEdit.returnPressed.connect(lineEdit.focusNextChild)
            # detect changes on line edits
            lineEdit.textChanged.connect(self.check_changes)
        for comboBox in comboBoxList:
            comboBox.activated.connect(comboBox.focusNextChild)

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

    def setup_model(self):
        db = Db_Instance("form_associate").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 Associado", message)
        else:
            self._model = QSqlRelationalTableModel(self, db=db)
            self._model.setTable("associate")
            self._act_model = QSqlRelationalTableModel(self, db=db)
            self._act_model.setTable("associate_in_activity")

    def submit_data(self):
        self._model.insertRow(0)
        data = self.extract_input()
        for key,val in data.items():
            self._model.setData(self._model.index(0, self.column[key]), val)
        # try to commit a record
        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 - Cadastro de Atividade", message)
            return False
        else:
            # successfully added an associate, adding it's activities
            activities = self.extract_activities_input()
            error = False
            if len(activities) > 0:
                associate_id = self.get_added_record().value("id")
                for id in activities:
                    self._act_model.insertRow(0)
                    self._act_model.setData(self._act_model.index(0, 0), associate_id)
                    self._act_model.setData(self._act_model.index(0, 1), id)
                    ok = self._act_model.submitAll()
                    if not ok:
                        error = True
                        self.log.error(self._act_model.lastError().text())
            if not error:
                message = unicode("Sucesso!\n\n""O associado foi salvo com êxito no banco de dados".decode('utf-8'))
                QMessageBox.information(self, "Seareiros - Cadastro de Associado", message)
            else:
                message = unicode("Erro\n\n""Associado cadastrado, "
                                  "porém ocorreu um problema ao salvar suas atividades".decode('utf-8'))
                QMessageBox.warning(self, "Seareiros - Cadastro de Associado", message)

            return True

    def clear(self):
        self._dirty = False
        lineEditList = self.findChildren(QLineEdit)
        for lineEdit in lineEditList:
            lineEdit.clear()
        self.comboMaritalStatus.setCurrentIndex(0)
        self.comboProvince.setCurrentIndex(24)
        self.clear_table()
        self.edFullName.setFocus()

    @QtCore.Slot()
    def on_btnAddActivity_clicked(self):
        activity_dialog = ActivitySelectDialog()
        if activity_dialog.exec_() == QDialog.Accepted:
            record = activity_dialog.get_record()
            not_a_duplicate = self.add_activity(record)
            if not_a_duplicate:
                self.refresh_tableActivities()

    @QtCore.Slot()
    def on_btnCleanActivities_clicked(self):
        self.clear_table()

    def clear_table(self):
        self._activity_list = []
        self.tableActivities.clear()
        self.refresh_tableActivities()

    def refresh_tableActivities(self):
        if len(self._activity_list) > 0:
            self.tableActivities.setColumnCount(len(self._activity_list[0])+1)
            col_labels = ["", unicode("Descrição".decode("utf-8")), "Sala", "Dia", unicode("Horário".decode("utf-8")),""]
            self.tableActivities.setHorizontalHeaderLabels(col_labels)
            self.tableActivities.setColumnHidden(0, True)
        else:
            self.tableActivities.setColumnCount(0)
        self.tableActivities.setRowCount(len(self._activity_list))
        for i, row in enumerate(self._activity_list):
            for j, col in enumerate(row):
                # custom sorting for weekdays
                if j == 3:
                    item = WeekdayTableWidgetItem(col)
                else:
                    item = QTableWidgetItem(col)
                self.tableActivities.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_activity, activity=row))
            self.tableActivities.setCellWidget(i, len(row), remove_btn)
        self.tableActivities.resizeColumnsToContents()
        self.tableActivities.horizontalHeader().setResizeMode(1, QHeaderView.Stretch)

    def add_activity(self, record):
        """ adds an activity to the list except for duplicates """
        # this brings shame to me but meh, faster to hardcode (see model_activity)
        # id = str(record.value("id"))
        id = record.value("id")
        room = record.value("room")
        if room == 0:
            room = "Nenhuma"
        else:
            room = str(room)
        weekday = constants.days_of_the_week[record.value("weekday")]
        weektime = record.value("weektime").toString("HH:mm")
        entry = (id, record.value("description"), room,
                 weekday, weektime)

        if entry in self._activity_list:
            return False
        else:
            self._activity_list.append(entry)
            # sorts by day/time
            self._activity_list.sort(key=operator.itemgetter(3,4))
            # self._activity_list = sorted(self._activity_list, key=lambda dia_hora: (dia_hora[3], dia_hora[2]))
            return True

    def remove_activity(self, activity):
        # remove a row based on its value
        self._activity_list.remove(activity)
        self.refresh_tableActivities()

    def extract_input(self):
        data = {}
        data['fullname'] = self.edFullName.text()
        data['nickname'] = self.edNickname.text()
        data['rg'] = self.edRG.text()
        data['cpf'] = self.remove_mask_when_empty(self.edCPF.text())
        data['maritalstatus'] = self.comboMaritalStatus.currentIndex()
        data['email'] = self.edEmail.text()
        data['streetaddress'] = self.edStreet.text()
        data['complement'] = self.edComplement.text()
        data['district'] = self.edDistrict.text()
        data['province'] = self.comboProvince.currentIndex()
        data['city'] = self.edCity.text()
        data['cep'] = self.remove_mask_when_empty(self.edCEP.text())
        data['phoneres'] = self.remove_mask_when_empty(self.edPhoneRes.text())
        data['phonecom'] = self.remove_mask_when_empty(self.edPhoneCom.text())
        data['phonepriv'] = self.remove_mask_when_empty(self.edPhonePriv.text())
        if self.radioStatus.checkedId() == 0:
            data['active'] = True
        else:
            data['active'] = False
        return data

    def remove_mask_when_empty(self, text):
        """ I don't want to save a mask when there's no user input """
        if text in ['()-', '.-', '..-']:
            return ''
        else:
            return text

    def extract_activities_input(self):
        # grab id of selected activities
        activity_id_list = []
        for act in self._activity_list:
            activity_id_list.append(act[0])
        return activity_id_list

    def get_added_record(self):
        """ My workaround to get the last inserted id without any postgres specific queries """
        db = Db_Instance("add_associate_last_id").get_instance()
        if not db.open():
            return None
        else:
            query = QSqlQuery(db)
            query.prepare("SELECT * FROM associate WHERE fullname = :fullname")
            query.bindValue(":fullname", self.edFullName.text())
            query.exec_()
            if query.next():
                return query.record()
            else:
                return None
Пример #6
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
Пример #7
0
class AssociateEditForm(QScrollArea, Ui_AssociateForm):
    """ Interface for associate edit """

    column = {
            'id':0, 'fullname':1, 'nickname':2, 'rg':3, 'cpf':4, 'maritalstatus':5, 'email':6, 'streetaddress':7,
            'complement':8, 'district':9, 'province':10, 'city':11, 'cep':12, 'phoneres':13, 'phonecom':14,
            'phonepriv':15, 'active':17 }

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

        self._access = statics.access_level
        self._record_id = record_id

        # configuring id's for radio group
        self.radioStatus.setId(self.rdActive,0)
        self.radioStatus.setId(self.rdInactive,1)

        # 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('AssociateEditForm')

        self._activity_list = []

        self._removed_activities = []
        self._added_activities = []
        self.setup_model()

        self.fill_form()
        self._old_data = self.extract_input()
        self.setup_fields()

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

    def is_dirty(self):
        return self._dirty

    def setup_fields(self):
        # tries to make things easier for user by allowing him to tab with return key
        # or after selecting something from a combobox
        self.edFullName.setValidator(UppercaseValidator())
        self.edNickname.setValidator(UppercaseValidator())
        self.edEmail.setValidator(EmailValidator())
        self.edRG.setValidator(AlphaNumericValidator())
        lineEditList = self.findChildren(QLineEdit)
        comboBoxList = self.findChildren(QComboBox)
        for lineEdit in lineEditList:
            lineEdit.returnPressed.connect(lineEdit.focusNextChild)
            # detect changes to the line edits
            lineEdit.textChanged.connect(self.check_changes)
        for comboBox in comboBoxList:
            comboBox.activated.connect(comboBox.focusNextChild)

    def fill_form(self):
        # retrieving associate info
        self.edFullName.setText(self._record.value(1))
        self.edNickname.setText(self._record.value(2))
        self.edRG.setText(self._record.value(3))
        self.edCPF.setText(self._record.value(4))
        self.comboMaritalStatus.setCurrentIndex(self._record.value(5))
        self.edEmail.setText(self._record.value(6))
        self.edStreet.setText(self._record.value(7))
        self.edComplement.setText(self._record.value(8))
        self.edDistrict.setText(self._record.value(9))
        self.comboProvince.setCurrentIndex(self._record.value(10))
        self.edCity.setText(self._record.value(11))
        self.edCEP.setText(self._record.value(12))
        self.edPhoneRes.setText(self._record.value(13))
        self.edPhoneCom.setText(self._record.value(14))
        self.edPhonePriv.setText(self._record.value(15))
        if self._record.value("active"):
            self.rdActive.setChecked(True)
        else:
            self.rdInactive.setChecked(True)
        # retrieving associate activities
        for act_record in self._activity_records:
            self.add_activity(act_record)
        # clearing changes
        self._added_activities[:] = []
        self.refresh_tableActivities()

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

    def check_activities_changes(self):
        if self._added_activities and self._removed_activities:
            return False
        else:
            return True

    def extract_input(self):
        data = {}
        data['fullname'] = self.edFullName.text()
        data['nickname'] = self.edNickname.text()
        data['rg'] = self.edRG.text()
        data['cpf'] = self.remove_mask_when_empty(self.edCPF.text())
        data['maritalstatus'] = self.comboMaritalStatus.currentIndex()
        data['email'] = self.edEmail.text()
        data['streetaddress'] = self.edStreet.text()
        data['complement'] = self.edComplement.text()
        data['district'] = self.edDistrict.text()
        data['province'] = self.comboProvince.currentIndex()
        data['city'] = self.edCity.text()
        data['cep'] = self.remove_mask_when_empty(self.edCEP.text())
        data['phoneres'] = self.remove_mask_when_empty(self.edPhoneRes.text())
        data['phonecom'] = self.remove_mask_when_empty(self.edPhoneCom.text())
        data['phonepriv'] = self.remove_mask_when_empty(self.edPhonePriv.text())
        if self.radioStatus.checkedId() == 0:
            data['active'] = True
        else:
            data['active'] = False
        return data

    def setup_model(self):
        db = Db_Instance("edit_associate").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 Associado".decode('utf-8')), message)
        else:
            self._model = QSqlRelationalTableModel(self, db=db)
            self._model.setTable("associate")
            self._act_model = QSqlRelationalTableModel(self, db=db)
            self._act_model.setTable("associate_in_activity")
            # TODO: Maybe I should validate these
            # associate
            self._model.setFilter("id = " + str(self._record_id))
            self._model.select()
            self._record = self._model.record(0)
            # activities
            self._activity_records = []
            sql_statement = """SELECT id, description, room, weekday, weektime FROM activity a,
                               associate_in_activity a_a WHERE
                               a.id = a_a.id_activity AND a_a.id_associate = %s
                            """ % str(self._record_id)
            model_activities = QSqlQueryModel()
            model_activities.setQuery(sql_statement, db)
            # checking query validity
            if not model_activities.lastError().isValid():
                self._activity_records = iterate_model(model_activities)

    def update_data(self):
        data = self.extract_input()
        for key,val in data.items():
            self._model.setData(self._model.index(0, self.column[key]), val)
        # 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 - Cadastro de Atividade", message)
            return False
        else:
            # updating activities
            error = False
            for added_id in self._added_activities:
                self._act_model.insertRow(0)
                self._act_model.setData(self._act_model.index(0, 0), self._record_id)
                self._act_model.setData(self._act_model.index(0, 1), added_id)
                ok = self._act_model.submitAll()
                if not ok:
                    error = True
                    self.log.error(self._act_model.lastError().text())
                    break
                    # TODO: raise some kind of exception here
            for removed_id in self._removed_activities:
                self._act_model.setFilter("id_associate = %s AND id_activity = %s" % (str(self._record_id), str(removed_id)))
                self._act_model.select()
                self._act_model.removeRow(0)
                if self._act_model.lastError().isValid():
                    error = True
                    self.log.error(self._act_model.lastError().text())
                    break
            if not error:
                message = unicode("Sucesso!\n\n""O associado foi atualizado com êxito no banco de dados".decode('utf-8'))
                QMessageBox.information(self, unicode("Seareiros - Edição de Associado".decode('utf-8')), message)
            else:
                message = unicode("Erro\n\n""Associado alterado, "
                                  "porém ocorreu um problema ao atualizar suas atividades".decode('utf-8'))
                QMessageBox.warning(self, unicode("Seareiros - Edição de Associado".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

    @QtCore.Slot()
    def on_btnAddActivity_clicked(self):
        activity_dialog = ActivitySelectDialog()
        if activity_dialog.exec_() == QDialog.Accepted:
            record = activity_dialog.get_record()
            not_a_duplicate = self.add_activity(record)
            if not_a_duplicate:
                self.refresh_tableActivities()

    @QtCore.Slot()
    def on_btnCleanActivities_clicked(self):
        self.clear_table()

    def clear_table(self):
        # can't directly change activity_list here
        itens = [i for i in self._activity_list]
        for item in itens:
            self.remove_activity(item)
        self._added_activities[:] = []

    def refresh_tableActivities(self):
        if len(self._activity_list) > 0:
            self.tableActivities.setColumnCount(len(self._activity_list[0])+1)
            col_labels = ["", unicode("Descrição".decode("utf-8")), "Sala", "Dia", unicode("Horário".decode("utf-8")),""]
            self.tableActivities.setHorizontalHeaderLabels(col_labels)
            self.tableActivities.setColumnHidden(0, True)
        else:
            self.tableActivities.setColumnCount(0)
        self.tableActivities.setRowCount(len(self._activity_list))
        for i, row in enumerate(self._activity_list):
            for j, col in enumerate(row):
                # custom sorting for weekdays
                if j == 3:
                    item = WeekdayTableWidgetItem(col)
                else:
                    item = QTableWidgetItem(col)
                self.tableActivities.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_activity, activity=row))
            self.tableActivities.setCellWidget(i, len(row), remove_btn)
        self.tableActivities.resizeColumnsToContents()
        self.tableActivities.horizontalHeader().setResizeMode(1, QHeaderView.Stretch)

    def is_in_del_queue(self, record):
        return record in self._removed_activities

    def is_in_add_queue(self, record):
        return record in self._added_activities

    def add_activity(self, record):
        """ adds an activity to the list except for duplicates """
        # this brings shame to me but meh, faster to hardcode (see model_activity)
        # id = str(record.value("id"))
        id = record.value("id")
        room = record.value("room")
        if room == 0:
            room = "Nenhuma"
        else:
            room = str(room)
        weekday = constants.days_of_the_week[record.value("weekday")]
        weektime = record.value("weektime").toString("HH:mm")
        entry = (id, record.value("description"), room,
                 weekday, weektime)

        if entry in self._activity_list:
            return False
        else:
            if self.is_in_del_queue(id):
                # no real need to add as it was queued to be removed
                self._removed_activities.remove(id)
            else:
                self._added_activities.append(id)
            # print self._added_activities

            self._activity_list.append(entry)
            # sorts by day/time
            self._activity_list.sort(key=operator.itemgetter(3,4))
            # self._activity_list = sorted(self._activity_list, key=lambda dia_hora: (dia_hora[3], dia_hora[2]))
            return True

    def remove_activity(self, activity):
        # remove a row based on its value
        self._activity_list.remove(activity)
        id = activity[0]
        if self.is_in_add_queue(id):
            # unqueue previously added activity
            self._added_activities.remove(id)
        else:
            self._removed_activities.append(id)
        self.refresh_tableActivities()

    def remove_mask_when_empty(self, text):
        """ I don't want to save a mask when there's no user input """
        if text in ['()-', '.-', '..-']:
            return ''
        else:
            return text
Пример #8
0
 def data(self, index, role):
     if (role == Qt.TextAlignmentRole):
         return Qt.AlignCenter
     return QSqlRelationalTableModel.data(self, index, role)
Пример #9
0
 def data(self, index, role):
     if (role == Qt.TextAlignmentRole):
         return Qt.AlignCenter
     return QSqlRelationalTableModel.data(self, index, role)