/* Copyright 2006-2020 QElectroTech Team This file is part of QElectroTech. QElectroTech is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. QElectroTech is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with QElectroTech. If not, see . */ #include "projectdbmodel.h" #include "projectdatabase.h" #include "qetproject.h" #include "qetxml.h" #include "qetapp.h" #include #include /** * @brief ProjectDBModel::ProjectDBModel * @param project :project of this nomenclature * @param parent : parent QObject */ ProjectDBModel::ProjectDBModel(QETProject *project, QObject *parent) : QAbstractTableModel(parent), m_project(project) { connect(m_project->dataBase(), &projectDataBase::dataBaseUpdated, this, &ProjectDBModel::dataBaseUpdated); } /** * @brief ProjectDBModel::ProjectDBModel * @param other_model */ ProjectDBModel::ProjectDBModel(const ProjectDBModel &other_model) : QAbstractTableModel(other_model.parent()) { this->setParent(other_model.parent()); m_project = other_model.m_project; connect(m_project->dataBase(), &projectDataBase::dataBaseUpdated, this, &ProjectDBModel::dataBaseUpdated); m_index_0_0_data = other_model.m_index_0_0_data; setQuery(other_model.queryString()); } /** * @brief ProjectDBModel::rowCount * Reimplemented for QAbstractTableModel * @param parent * @return */ int ProjectDBModel::rowCount(const QModelIndex &parent) const { if (parent.isValid()) return 0; return m_record.count(); } /** * @brief ProjectDBModel::columnCount * Reimplemented for QAbstractTableModel * @param parent * @return */ int ProjectDBModel::columnCount(const QModelIndex &parent) const { if (parent.isValid()) return 0; if (m_record.count()) { return m_record.first().count(); } return 0; } /** * @brief ProjectDBModel::setHeaderData * Reimplemented from QAbstractTableModel. * Only horizontal orientation is accepted. * @param section * @param orientation * @param value * @param role * @return */ bool ProjectDBModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role) { if (orientation == Qt::Vertical) { return false; } auto hash_ = m_header_data.value(section); hash_.insert(role, value); m_header_data.insert(section, hash_); emit headerDataChanged(orientation, section, section); return true; } /** * @brief ProjectDBModel::headerData * Reimplemented from QAbstractTableModel. * @param section * @param orientation * @param role * @return */ QVariant ProjectDBModel::headerData(int section, Qt::Orientation orientation, int role) const { if (orientation == Qt::Vertical) { return QVariant(); } if (m_header_data.contains(section)) { auto hash_ = m_header_data.value(section); if (role == Qt::DisplayRole && !hash_.contains(Qt::DisplayRole)) { //special case to have the same behavior as Qt return hash_.value(Qt::EditRole); } return m_header_data.value(section).value(role); } return QVariant(); } /** * @brief ProjectDBModel::setData * Only store the data for the index 0.0 * @param index * @param value * @param role * @return */ bool ProjectDBModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (!index.isValid() || index.row() != 0 || index.column() != 0) { return false; } m_index_0_0_data.insert(role, value); emit dataChanged(index, index, QVector(role)); return true; } /** * @brief ProjectDBModel::data * Reimplemented for QAbstractTableModel * @param index * @param role * @return */ QVariant ProjectDBModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); if (index.row() == 0 && index.column() == 0 && role != Qt::DisplayRole) { return m_index_0_0_data.value(role); } if (role == Qt::DisplayRole) { QVariant v(m_record.at(index.row()).at(index.column())); return v; } return QVariant(); } /** * @brief ProjectDBModel::setQuery * Query the internall bd with @query. * @param query */ void ProjectDBModel::setQuery(const QString &query) { auto rm_ = m_query != query; if (rm_) { emit beginResetModel(); } m_query = query; if (m_project) { if (rm_) { disconnect(m_project->dataBase(), &projectDataBase::dataBaseUpdated, this, &ProjectDBModel::dataBaseUpdated); } m_project->dataBase()->updateDB(); if (rm_) { setHeaderString(); fillValue(); connect(m_project->dataBase(), &projectDataBase::dataBaseUpdated, this, &ProjectDBModel::dataBaseUpdated); } } if (rm_) { emit endResetModel(); } } /** * @brief ProjectDBModel::queryString * @return the current query used by this model */ QString ProjectDBModel::queryString() const { return m_query; } QETProject *ProjectDBModel::project() const { return m_project.data(); } /** * @brief ProjectDBModel::toXml * Save the model to xml,since model can have unlimited data we only save few data (only these used by qelectrotech). * The query, all header data. and some data of index::(0,0). All other data are not saved. * @param document * @return */ QDomElement ProjectDBModel::toXml(QDomDocument &document) const { auto dom_element = document.createElement(xmlTagName()); //Identifier auto dom_identifier = document.createElement("identifier"); auto dom_identifier_text = document.createTextNode(m_identifier); dom_identifier.appendChild(dom_identifier_text); dom_element.appendChild(dom_identifier); //query auto dom_query = document.createElement("query"); auto dom_query_text = document.createTextNode(m_query); dom_query.appendChild(dom_query_text); dom_element.appendChild(dom_query); //Add index 0,0 data auto index_00 = document.createElement("index00"); index_00.setAttribute("font", m_index_0_0_data.value(Qt::FontRole).toString()); auto me = QMetaEnum::fromType(); index_00.setAttribute("alignment", me.valueToKey(m_index_0_0_data.value(Qt::TextAlignmentRole).toInt())); dom_element.appendChild(index_00); index_00.setAttribute("margins", m_index_0_0_data.value(Qt::UserRole+1).toString()); //header data QHash> horizontal_; for (auto key : m_header_data.keys()) { //We save all data except the display role, because he was generated in the fly auto list = m_header_data.value(key).keys(); list.removeAll(Qt::DisplayRole); horizontal_.insert(key, list); } dom_element.appendChild(QETXML::modelHeaderDataToXml(document, this, horizontal_, QHash>())); return dom_element; } /** * @brief ProjectDBModel::fromXml * Restore the model from xml * @param element */ void ProjectDBModel::fromXml(const QDomElement &element) { if (element.tagName() != xmlTagName()) return; setIdentifier(element.firstChildElement("identifier").text()); setQuery(element.firstChildElement("query").text()); //Index 0,0 auto index_00 = element.firstChildElement("index00"); QFont font_; font_.fromString(index_00.attribute("font")); m_index_0_0_data.insert(Qt::FontRole, font_); auto me = QMetaEnum::fromType(); m_index_0_0_data.insert(Qt::TextAlignmentRole, me.keyToValue(index_00.attribute("alignment").toStdString().data())); m_index_0_0_data.insert(Qt::UserRole+1, index_00.attribute("margins")); QETXML::modelHeaderDataFromXml(element.firstChildElement("header_data"), this); } /** * @brief ProjectDBModel::setIdentifier * Set the identifier of this model to @identifier * @param identifier */ void ProjectDBModel::setIdentifier(const QString &identifier) { m_identifier = identifier; } /** * @brief ProjectDBModel::dataBaseUpdated * slot called when the project database is updated */ void ProjectDBModel::dataBaseUpdated() { auto original_record = m_record; fillValue(); auto new_record = m_record; m_record = original_record; //This a very special case, if this nomenclature model is added //befor any element, column count return 0, so in this case we emit column inserted if (new_record.size() != m_record.size()) { emit beginResetModel(); m_record = new_record; emit endResetModel(); } else { m_record = new_record; auto row = m_record.size(); auto col = row ? m_record.first().count() : 1; emit dataChanged(this->index(0,0), this->index(row-1, col-1), QVector(Qt::DisplayRole)); } } void ProjectDBModel::setHeaderString() { auto q = m_project->dataBase()->newQuery(m_query); auto record = q.record(); for (auto i=0 ; isetHeaderData(i, Qt::Horizontal, header_name, Qt::DisplayRole); } } void ProjectDBModel::fillValue() { m_record.clear(); auto query_ = m_project->dataBase()->newQuery(m_query); if (!query_.exec()) { qDebug() << "Query error : " << query_.lastError(); } while (query_.next()) { QStringList record_; auto i=0; while (query_.value(i).isValid()) { auto date = query_.value(i).toDate(); if (!date.isNull()) { record_ << QLocale::system().toString(query_.value(i).toDate(), QLocale::ShortFormat); } else { record_ << query_.value(i).toString(); } ++i; } m_record << record_; } }