久久建筑下载网,网站品牌词优化怎么做,WordPress单页生成插件,wordpress打开文章响应慢目录 继承关系入口浅析qsqlquery刷新数据 扩展列或者移除列以及取别名读取数据与增减行读取数据 下一章节#xff1a;如何使用qsqlquerymodel 与 qtableview实现自定义表格 继承关系
qsqlquerymodel 继承与qabstracttablemodel
入口
负责填充数据
void QSqlQueryModel::s… 目录 继承关系入口浅析qsqlquery刷新数据 扩展列或者移除列以及取别名读取数据与增减行读取数据 下一章节如何使用qsqlquerymodel 与 qtableview实现自定义表格 继承关系
qsqlquerymodel 继承与qabstracttablemodel
入口
负责填充数据
void QSqlQueryModel::setQuery(const QString query, const QSqlDatabase db) //无法配置绑定参数
void QSqlQueryModel::setQuery(const QSqlQuery query) //非常友好支持自定义query浅析qsqlquery
你会发现提供的构造qsqlquery中如果 携带sql字符串语句则 if (!query.isEmpty()) q-exec(query);自动执行具体请看qInit() 所以在使用qsqlquery的过程中如果传入sql语句则不用手动执行 否则就需要自己执行exec
QSqlQuery::QSqlQuery(QSqlDatabase db)
{d QSqlQueryPrivate::shared_null();qInit(this, QString(), db);
}
QSqlQuery::QSqlQuery(const QString query, QSqlDatabase db)
{d QSqlQueryPrivate::shared_null();qInit(this, query, db);
}
//1.提供的数据库连接无效则获取默认的数据库且未开启static void qInit(QSqlQuery *q, const QString query, QSqlDatabase db)
{QSqlDatabase database db;if (!database.isValid())database QSqlDatabase::database(QLatin1String(QSqlDatabase::defaultConnection), false);if (database.isValid()) {*q QSqlQuery(database.driver()-createResult());}if (!query.isEmpty())q-exec(query);
}
数据返回 sqlResult 是由不同的数据库驱动提供的
QSqlRecord QSqlQuery::record() const
{QSqlRecord rec d-sqlResult-record();if (isValid()) {for (int i 0; i rec.count(); i)rec.setValue(i, value(i));}return rec;
}QVariant QSqlQuery::value(int index) const
{if (isActive() isValid() (index -1))return d-sqlResult-data(index);qWarning(QSqlQuery::value: not positioned on a valid record);return QVariant();
}
而为什么qsqlquery可以使用qsqlresult的protected东西虽然不是相互继承关系 但因为在qsqlresult中声明了qsqlquery为友元类所以依旧能够使用 但是外部是无法使用的 所以外部提供的 没什么太大的作用
const QSqlResult * result() const实际
qsqlquery.record() 第一行是表头
所以执行next再获取才是数据库里面查询结果的第一行数据
setquery分析所以我们了解了qsqlquery的处理机制 我们就明白在执行qsqlquerymodel 的setquery 就是将已经存在数据的query填充到querymodel 模型中供外部使用
void QSqlQueryModel::setQuery(const QSqlQuery query)
{Q_D(QSqlQueryModel);beginResetModel();QSqlRecord newRec query.record();bool columnsChanged (newRec ! d-rec);//设置列数if (d-colOffsets.size() ! newRec.count() || columnsChanged)d-initColOffsets(newRec.count());d-bottom QModelIndex(); //最后一行与最后一列的坐标d-error QSqlError();d-query query;d-rec newRec; //表头d-atEnd true; //最后一行吗//获取数据的方式是由下往上则//这个模型不支持这样子的queryif (query.isForwardOnly()) {d-error QSqlError(QLatin1String(Forward-only queries cannot be used in a data model),QString(), QSqlError::ConnectionError);endResetModel();return;}if (!query.isActive()) {d-error query.lastError();endResetModel();return;}//query是否存在数据if (query.driver()-hasFeature(QSqlDriver::QuerySize) d-query.size() 0) {d-bottom createIndex(d-query.size() - 1, d-rec.count() - 1);} else {d-bottom createIndex(-1, d-rec.count() - 1);d-atEnd false;}// fetchMore does the rowsInserted stuff for incremental modelsfetchMore(); //endResetModel();queryChange();
}不难看出初始化数据需要这样子的闭合关系
beginResetModel();
//-----填充数据域
endResetModel();刷新数据
void QSqlQueryModel::fetchMore(const QModelIndex parent)
{Q_D(QSqlQueryModel);if (parent.isValid())return;//预先刷新多少行QSQL_PREFETCH255d-prefetch(qMax(d-bottom.row(), 0) QSQL_PREFETCH);
}//limit255
void QSqlQueryModelPrivate::prefetch(int limit)
{Q_Q(QSqlQueryModel);// 如果确实是最后一行则不往下执行if (atEnd || limit bottom.row() || bottom.column() -1)return;QModelIndex newBottom;const int oldBottomRow qMax(bottom.row(), 0);// try to seek directly// 查看数据是否超过limit行则新行先预加载到这里//一个预加载操作if (query.seek(limit)) {newBottom q-createIndex(limit, bottom.column());} else {// have to seek back to our old position for MS Accessint i oldBottomRow;if (query.seek(i)) {while (query.next())i;newBottom q-createIndex(i, bottom.column());} else {// empty or invalid querynewBottom q-createIndex(-1, bottom.column());}atEnd true; // this is the end.}if (newBottom.row() 0 newBottom.row() bottom.row()) {q-beginInsertRows(QModelIndex(), bottom.row() 1, newBottom.row());bottom newBottom; //更新最后一行坐标q-endInsertRows();} else {bottom newBottom;}
}可以看到执行插入操作
beginInsertRows();
//插入操作作用域
endInsertRows();扩展列或者移除列以及取别名
不难发现就是往rect表头管理的record里面加入一个新的qsqlfield //批量增加列
bool QSqlQueryModel::insertColumns(int column, int count, const QModelIndex parent)
{Q_D(QSqlQueryModel);if (count 0 || parent.isValid() || column 0 || column d-rec.count())return false;beginInsertColumns(parent, column, column count - 1);for (int c 0; c count; c) {QSqlField field;field.setReadOnly(true);field.setGenerated(false);d-rec.insert(column, field);if (d-colOffsets.size() d-rec.count()) {int nVal d-colOffsets.isEmpty() ? 0 : d-colOffsets[d-colOffsets.size() - 1];d-colOffsets.append(nVal);Q_ASSERT(d-colOffsets.size() d-rec.count());}for (int i column 1; i d-colOffsets.count(); i)d-colOffsets[i];}endInsertColumns();return true;
}//批量删除列
bool QSqlQueryModel::removeColumns(int column, int count, const QModelIndex parent)
{Q_D(QSqlQueryModel);if (count 0 || parent.isValid() || column 0 || column d-rec.count())return false;beginRemoveColumns(parent, column, column count - 1);int i;for (i 0; i count; i)d-rec.remove(column);for (i column; i d-colOffsets.count(); i)d-colOffsets[i] - count;endRemoveColumns();return true;
}
//取别名
bool QSqlQueryModel::setHeaderData(int section, Qt::Orientation orientation,const QVariant value, int role)
{Q_D(QSqlQueryModel);if (orientation ! Qt::Horizontal || section 0 || columnCount() section)return false;if (d-headers.size() section)d-headers.resize(qMax(section 1, 16));d-headers[section][role] value;emit headerDataChanged(orientation, section, section);return true;
}// 获取表头列名
QVariant QSqlQueryModel::headerData(int section, Qt::Orientation orientation, int role) const
{Q_D(const QSqlQueryModel);if (orientation Qt::Horizontal) {QVariant val d-headers.value(section).value(role);if (role Qt::DisplayRole !val.isValid())val d-headers.value(section).value(Qt::EditRole);if (val.isValid())return val;if (role Qt::DisplayRole d-rec.count() section d-columnInQuery(section) ! -1)return d-rec.fieldName(section);}return QAbstractItemModel::headerData(section, orientation, role);
}
读取数据与增减行
因为是数据库查询的我觉的没必要setData 我们只需要控制我们的列就行了 比如我们可以在前面加一列—到时候传入个checkbox或者单选框 在加入一个选择管理器就可以做到选择功能 最后就是一列多个按键我们也可以通过多增加列进行 model-insertColumns(0,1);model-setHeaderData(0,Qt::Horizontal,QString(选择));动态列的字段数据 0: QSqlField(, , tableName: (not specified), generated: no, autoValue: false, readOnly: true) 读取数据 //返回行数据
QSqlRecord QSqlQueryModel::record(int row) const
{Q_D(const QSqlQueryModel);if (row 0)return d-rec;QSqlRecord rec d-rec;for (int i 0; i rec.count(); i)rec.setValue(i, data(createIndex(row, i), Qt::EditRole));return rec;
}//表头数据
QSqlRecord QSqlQueryModel::record() const
{Q_D(const QSqlQueryModel);return d-rec;
}QVariant QSqlQueryModel::data(const QModelIndex item, int role) const
{Q_D(const QSqlQueryModel);if (!item.isValid())return QVariant();QVariant v;if (role ~(Qt::DisplayRole | Qt::EditRole))return v;// 非原来的 则直接返回 就是调用insertColumns加的则直接返回if (!d-rec.isGenerated(item.column()))return v;//获取在query中实际位置QModelIndex dItem indexInQuery(item);if (dItem.row() d-bottom.row())const_castQSqlQueryModelPrivate *(d)-prefetch(dItem.row());if (!d-query.seek(dItem.row())) {d-error d-query.lastError();return v;}return d-query.value(dItem.column());
}QModelIndex QSqlQueryModel::indexInQuery(const QModelIndex item) const
{Q_D(const QSqlQueryModel);int modelColumn d-columnInQuery(item.column());if (modelColumn 0)return QModelIndex();return createIndex(item.row(), modelColumn, item.internalPointer());
}int QSqlQueryModelPrivate::columnInQuery(int modelColumn) const
{if (modelColumn 0 || modelColumn rec.count() || !rec.isGenerated(modelColumn) || modelColumn colOffsets.size())return -1;return modelColumn - colOffsets[modelColumn];
}// 提供给委托使用的 如果设置
QHashint, QByteArray QSqlQueryModel::roleNames() const
{return QHashint, QByteArray {{ Qt::DisplayRole, QByteArrayLiteral(display) }};
}
而rolename有什么用 主要用于在qml中可以使用属性名如model.name , model.display之类的 void initializeConstructor(QQmlAdaptorModelEngineData *const data){QV4::ExecutionEngine *v4 data-v4;QV4::Scope scope(v4);QV4::ScopedObject proto(scope, v4-newObject());proto-defineAccessorProperty(QStringLiteral(index), get_index, nullptr);proto-defineAccessorProperty(QStringLiteral(hasModelChildren), get_hasModelChildren, nullptr);QV4::ScopedProperty p(scope);typedef QHashQByteArray, int::const_iterator iterator;for (iterator it roleNames.constBegin(), end roleNames.constEnd(); it ! end; it) {const int propertyId propertyRoles.indexOf(it.value());const QByteArray propertyName it.key();QV4::ScopedString name(scope, v4-newString(QString::fromUtf8(propertyName)));QV4::ExecutionContext *global v4-rootContext();QV4::ScopedFunctionObject g(scope, v4-memoryManager-allocateQV4::IndexedBuiltinFunction(global, propertyId, QQmlDMCachedModelData::get_property));QV4::ScopedFunctionObject s(scope, v4-memoryManager-allocateQV4::IndexedBuiltinFunction(global, propertyId, QQmlDMCachedModelData::set_property));p-setGetter(g);p-setSetter(s);proto-insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotEnumerable|QV4::Attr_NotConfigurable);}prototype.set(v4, proto);}下一章节如何使用qsqlquerymodel 与 qtableview实现自定义表格