Exemplo n.º 1
0
    def import_cases_and_attributes(self):
        """ Import from a csv file with the cases and any attributes.
        The csv file must have a header row which details the attribute names.
        The csv file must be comma delimited. The first column must have the case ids.
        The attribute types are calculated from the data.
        """

        if self.cases != []:
            logger.warning(_("Cases have already been created."))
        filename = QtWidgets.QFileDialog.getOpenFileName(
            None, _('Select attributes file'), self.app.settings['directory'],
            "(*.csv)")[0]
        if filename == "":
            return
        if filename[-4:].lower() != ".csv":
            msg = filename + "\n" + _("is not a .csv file. File not imported")
            Message(self.app, _("Warning"), msg, "warning").exec_()
            self.parent_textEdit.append(msg)
            return
        values = []
        with open(filename, 'r', newline='') as f:
            reader = csv.reader(f, delimiter=',', quoting=csv.QUOTE_MINIMAL)
            try:
                for row in reader:
                    values.append(row)
            except csv.Error as e:
                logger.warning(
                    ('file %s, line %d: %s' % (filename, reader.line_num, e)))
        if len(values) <= 1:
            logger.info(_("Cannot import from csv, only one row in file"))
            return
        now_date = str(
            datetime.datetime.now().astimezone().strftime("%Y-%m-%d %H:%M:%S"))
        header = values[0]
        values = values[1:]
        # insert cases
        cur = self.app.conn.cursor()
        for v in values:
            item = {
                'name': v[0],
                'memo': "",
                'owner': self.app.settings['codername'],
                'date': now_date
            }
            try:
                cur.execute(
                    "insert into cases (name,memo,owner,date) values(?,?,?,?)",
                    (item['name'], item['memo'], item['owner'], item['date']))
                self.app.conn.commit()
                cur.execute("select last_insert_rowid()")
                item['caseid'] = cur.fetchone()[0]
                self.cases.append(item)
            except Exception as e:
                logger.error("item:" + str(item) + ", " + str(e))
        # determine attribute type
        attribute_value_type = ["character"] * len(header)
        for col, att_name in enumerate(header):
            numeric = True
            for val in values:
                try:
                    float(val[col])
                except ValueError:
                    numeric = False
            if numeric:
                attribute_value_type[col] = "numeric"
        # insert attribute types
        for col, att_name in enumerate(header):
            if col > 0:
                try:
                    cur.execute(
                        "insert into attribute_type (name,date,owner,memo, \
                    valueType, caseOrFile) values(?,?,?,?,?,?)",
                        (att_name, now_date, self.app.settings['codername'],
                         "", attribute_value_type[col], 'case'))
                    self.app.conn.commit()
                except Exception as e:
                    logger.error(_("attribute:") + att_name + ", " + str(e))
        # insert attributes
        sql = "select name, caseid from cases"
        cur.execute(sql)
        name_and_ids = cur.fetchall()
        for n_i in name_and_ids:
            for v in values:
                if n_i[0] == v[0]:
                    for col in range(1, len(v)):
                        sql = "insert into attribute (name, value, id, attr_type, date, owner) values (?,?,?,?,?,?)"
                        cur.execute(sql,
                                    (header[col], v[col], n_i[1], 'case',
                                     now_date, self.app.settings['codername']))
        self.app.conn.commit()
        self.load_cases_and_attributes()
        self.fill_tableWidget()
        msg = _("Cases and attributes imported from: ") + filename
        self.app.delete_backup = False
        self.parent_textEdit.append(msg)
        logger.info(msg)
Exemplo n.º 2
0
    def insert_data(self):
        """ Insert case, attributes, attribute values and qualitative text. """

        now_date = str(
            datetime.datetime.now().astimezone().strftime("%Y-%m-%d %H:%M:%S"))
        cur = self.app.conn.cursor()
        name_and_caseids = []
        for i, c in enumerate(self.data):
            try:
                self.ui.label_msg.setText(_("Inserting cases: " + str(i)))
                cur.execute(
                    "insert into cases (name,memo,owner,date) values(?,?,?,?)",
                    (c[0], "", self.app.settings['codername'], now_date))
                self.app.conn.commit()
                cur.execute("select last_insert_rowid()")
                name_and_caseids.append([c[0], cur.fetchone()[0]])
                QtWidgets.QApplication.processEvents()
            except sqlite3.IntegrityError as e:
                self.fail_msg = str(e) + _(
                    " - Duplicate case names, either in the file, or duplicates with existing cases in the project"
                )
                logger.error(_("Survey not loaded: ") + self.fail_msg)
                mb = QtWidgets.QMessageBox()
                mb.setIcon(QtWidgets.QMessageBox.Warning)
                mb.setStyleSheet("* {font-size:" +
                                 str(self.app.settings['fontsize']) + "pt} ")
                mb.setWindowTitle(_('Survey not loaded'))
                mb.setText(self.fail_msg)
                mb.exec_()
                self.parent_textEdit.append(
                    _("Survey not loaded: ") + self.fail_msg)
                return
        # insert non-qualitative attribute types, except if they are already present
        sql = "select name from attribute_type where caseOrFile='case'"
        cur.execute(sql)
        result = cur.fetchall()
        existing_attr_names = []
        for r in result:
            existing_attr_names.append(r[0])
        sql = "insert into attribute_type (name,date,owner,memo, valueType, caseOrFile) values(?,?,?,?,?,?)"
        for col, name in enumerate(self.fields):
            if self.fields_type[
                    col] != "qualitative" and col > 0:  # col==0 is the case identifier
                if name not in existing_attr_names:
                    logger.debug(name +
                                 " is not in case attribute_types. Adding.")
                    cur.execute(
                        sql, (name, now_date, self.app.settings['codername'],
                              "", self.fields_type[col], 'case'))
        self.app.conn.commit()

        # Look for pre-existing attributes that are not in the survey and insert blank value rows if present
        survey_field_names = []
        for col, fld_name in enumerate(self.fields):
            if self.fields_type[col] != "qualitative" and col > 0:
                survey_field_names.append(fld_name)
        for name in existing_attr_names:
            if name not in survey_field_names:
                for name_id in name_and_caseids:
                    sql = "insert into attribute (name, value, id, attr_type, date, owner) values (?,'',?,?,?,?)"
                    cur.execute(sql, (name, name_id[1], 'case', now_date,
                                      self.app.settings['codername']))
        self.app.conn.commit()

        # insert non-qualitative values to each case using caseids
        sql = "insert into attribute (name, value, id, attr_type, date, owner) values (?,?,?,?,?,?)"
        for i, name_id in enumerate(name_and_caseids):
            self.ui.label_msg.setText(
                _("Inserting attributes to cases: ") + str(i))
            for val in self.data:
                if name_id[0] == val[0]:
                    for col in range(1, len(val)):
                        if self.fields_type[col] != "qualitative":
                            cur.execute(sql, (self.fields[col], val[col],
                                              name_id[1], 'case', now_date,
                                              self.app.settings['codername']))
            QtWidgets.QApplication.processEvents()
        self.app.conn.commit()

        # insert qualitative data into source table
        self.ui.label_msg.setText(_("Creating qualitative text file"))
        source_sql = "insert into source(name,fulltext,memo,owner,date, mediapath) values(?,?,?,?,?, Null)"
        for field in range(1, len(self.fields)):  # column 0 is for identifiers
            case_text_list = []
            if self.fields_type[field] == "qualitative":
                self.fields[field]
                # create one text file combining each row, prefix [case identifier] to each row.
                pos0 = 0
                pos1 = 0
                fulltext = ""
                for row in range(0, len(self.data)):
                    if self.data[row][field] != "":
                        fulltext += "[" + str(self.data[row][0]) + "] "
                        pos0 = len(fulltext) - 1
                        fulltext += str(self.data[row][field]) + "\n\n"
                        pos1 = len(fulltext) - 2
                        case_text = [
                            self.app.settings['codername'], now_date, "", pos0,
                            pos1, name_and_caseids[row][1]
                        ]
                        case_text_list.append(case_text)
                # add the current time to the file name to ensure uniqueness and to
                # prevent sqlite Integrity Error. Do not use now_date which contains colons
                now = str(datetime.datetime.now().astimezone().strftime(
                    "%Y-%m-%d %H-%M-%S"))
                cur.execute(source_sql,
                            (self.fields[field] + "_" + now, fulltext, "",
                             self.app.settings['codername'], now_date))
                self.app.conn.commit()
                cur.execute("select last_insert_rowid()")
                fid = cur.fetchone()[0]
                case_text_sql = "insert into case_text (owner, date, memo, pos0, pos1, caseid, fid) values(?,?,?,?,?,?,?)"
                for case_text in case_text_list:
                    case_text.append(fid)
                    cur.execute(case_text_sql, case_text)
                self.app.conn.commit()
        logger.info(_("Survey imported"))
        self.parent_textEdit.append(_("Survey imported."))
        Message(self.app, _("Survey imported"), _("Survey imported")).exec_()
        self.app.delete_backup = False