您的位置:首页 > 财经 > 产业 > 聚名网买卖域名合法吗_素材网站设计_首页图片点击率如何提高_河南网站建设报价

聚名网买卖域名合法吗_素材网站设计_首页图片点击率如何提高_河南网站建设报价

2024/12/27 11:06:59 来源:https://blog.csdn.net/Xiaomo1536/article/details/144719030  浏览:    关键词:聚名网买卖域名合法吗_素材网站设计_首页图片点击率如何提高_河南网站建设报价
聚名网买卖域名合法吗_素材网站设计_首页图片点击率如何提高_河南网站建设报价

嵌入式学习-QT-Day08

八、数据库

1、准备工作

2、连接数据库

3、创建表

4、增删改

5、查询

5.1 全查

5.2 模糊查询

八、数据库

1、准备工作

Qt本身并没有数据库的功能,但是Qt支持调用其他主流的数据库产品,并且这些数据库产品指定了统一的Qt接口,实际上使一种数据库的中间件。

Qt支持以下数据库类型。

嵌入式常用的数据库是SQLite3,本体只有几兆大小,非常适合集成到嵌入式产品当中。在Qt5版本及其以上也集成了SQLite数据库,因此可以直接通过驱动名称连接SQLite。

数据库编程中需要用到以下几个相关类:

  • QSqlDatabase

数据库相关类,用于一个数据库的连接。

  • QSqlQuery

数据库的操作类,可以操作SQL语句。

  • QSqlError

数据库操作信息类,用户手机数据库底层传递到Qt中的错误信息的。

数据库的相关产品无法直接使用,需要在.pro项目配置文件中添加sql模块。

添加完成后保存。

2、连接数据库

主要通过QsqlDatabase类进行连接,相关函数实现:

// 获得一个数据库连接对象
// 参数为数据库类型,详见本章第一节表格(注意大小写)
// 返回值:为连接对象
QSqlDatabase QSqlDatabase::​addDatabase(const QString & type)[static]
// 设置数据库名称
// 参数:要设置的数据库名称。对于SQLite,此函数表示数据库文件名。此文件会在项目目录中生成。
void QSqlDatabase::​setDatabaseName(const QString & name)
// 打开数据库连接
// 返回值为打开的结果,如果打开成功返回true、打开失败false。可以通过lastError函数获取错误信息。
bool QSqlDatabase::​open()
// 返回上一次的错误信息封装类
QSqlError QSqlDatabase::​lastError() const
// 从QSqlError对象中提取错误信息文本
QString QSqlError::​text() const
// 返回数据库连接的打开状态
bool QSqlDatabase::​isOpen() const
// 关闭数据库连接
void QSqlDatabase::​close()

dialog.h

#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QButtonGroup>
#include <QSqlDatabase>
#include <QDebug>
#include <QSqlError>
#include <QMessageBox>namespace Ui {
class Dialog;
}class Dialog : public QDialog
{
    Q_OBJECTpublic:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();private:
    Ui::Dialog *ui;
    QButtonGroup *group;
    QSqlDatabase db;    // 数据库连接对象
    void connetD2B();   // 连接到数据库private slots:
    void btnClickedSlots(int);
};#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    group = new QButtonGroup(this);
    group->addButton(ui->pushButtonInsert,1);
    group->addButton(ui->pushButtonDelete,2);
    group->addButton(ui->pushButtonUpdate,3);
    group->addButton(ui->pushButtonSelect,4);    connect(group,SIGNAL(buttonClicked(int)),
            this,SLOT(btnClickedSlots(int)));    connetD2B();
}Dialog::~Dialog()
{
    // 关闭数据库连接
    if(db.isOpen())
    {
        db.close();
    }
    delete ui;
}// 连接数据库
void Dialog::connetD2B()
{
    // 获取数据库的连接对象
    db = QSqlDatabase::addDatabase("QSQLITE");
    // 设置数据库名称
    db.setDatabaseName("book_management.db");
    // 打开数据库连接
    bool ret = db.open();
    if(ret == true)
    {
        qDebug () << "打开成功";
    }
    else
    {
        // 数据库连接打开失败
        QSqlError errInfo = db.lastError();
        QString text = errInfo.text();
        QMessageBox::critical(this,"错误",text);
    }
}void Dialog::btnClickedSlots(int id)
{
    if(id == 1)
    {
        qDebug () << "增加";
    }
    else if(id == 2)
    {
        qDebug () << "删除";
    }
    else if(id == 3)
    {
        qDebug () << "修改";
    }
    else if(id == 4)
    {
        qDebug () << "查找";
    }
    else
    {    }
}

3、创建表

建表语句:

CREATE TABLE book(id INTEGER PRIMARY KEY,name TEXT,price  REAL,author TEXT);
// 执行SQL语句
// 参数为执行的SQL语句内容
// 返回值为执行的结果
bool QSqlQuery::​exec(const QString & query)
// 与本章第二节的同名函数用法完全一样
QSqlError QSqlQuery::​lastError() const

一个操作SQLite的可视化软件

下载链接:百度网盘 请输入提取码

提取码:hqyj

dialog.h

#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QButtonGroup>
#include <QSqlDatabase>
#include <QDebug>
#include <QSqlError>
#include <QMessageBox>
#include <QSqlQuery>private:
    void createTable(); // 创建表#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"// 连接数据库
void Dialog::connetD2B()
{
    // 获取数据库的连接对象
    db = QSqlDatabase::addDatabase("QSQLITE");
    // 设置数据库名称
    db.setDatabaseName("book_management.db");
    // 打开数据库连接
    bool ret = db.open();
    if(ret == true)
    {
        qDebug () << "打开成功";
        createTable();
    }
    else
    {
        // 数据库连接打开失败
        QSqlError errInfo = db.lastError();
        QString text = errInfo.text();
        QMessageBox::critical(this,"错误",text);
    }
}// 创建表
void Dialog::createTable()
{
    // sql语句
    QString sql = "CREATE TABLE book(id INTEGER PRIMARY KEY,name TEXT,price REAL,author TEXT);";    // 创建数据库操作类
    QSqlQuery sq;    if(sq.exec(sql))    // 表创建成功
    {
        qDebug() << "建表成功";
    }
    else    // 建表失败,注意:建表成功或者失败都很正常,如果要建立的表已经存在,就会建表失败
    {
        QSqlError errInfo = sq.lastError();
        QString text = errInfo.text();
        qDebug() << "建表失败:" << text;
    }
}

4、增删改

增删改操作都需要录入用户输入,然后把用户输入的数据组装成SQL语句,最后执行。

组装SQL语句有两种方式:

  • 字符串拼接

这种方式原理简单,但是容易出错,且安全性较低。

  • 预处理+占位符

推荐使用这种方式,这种方式需要先编写有占位符的预处理SQL语句,交给Qt,Qt内部就知道要执行的SQL语句格式,然后在进行参数与占位符的替换,最终执行。

占位符有两种表示风格:

  • Oracle风格

使用:字段的格式

UPDATE book SET name=:name,price=:price,author=:author WHERE id=:id;
  • ODBC风格

使用?的格式

INSERT INTO book VALUES(?,?,?,?);
// 预处理SQL语句,此时SQL语句并没有执行,只是送入到Qt内部。
// 参数为要处理的SQL语句
// 返回为预处理的结果
bool QSqlQuery::​prepare(const QString & query)
// 绑定ODBC风格的占位符参数,绑定时一定要注意参数的顺序。
// 参数为要绑定的数据
void QSqlQuery::​addBindValue(const QVariant & val)

dialog.h

#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QButtonGroup>
#include <QSqlDatabase>
#include <QDebug>
#include <QSqlError>
#include <QMessageBox>
#include <QSqlQuery>namespace Ui {
class Dialog;
}class Dialog : public QDialog
{
    Q_OBJECT
private:
    void insertData();  // 添加数据
};#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"// 插入数据
void Dialog::insertData()
{
    QString name = ui->lineEdit->text();
    if(name == "")
    {
        QMessageBox::warning(this,"提示","请输入书名");
        return;
    }
    QString author = ui->lineEdit_2->text();
    if(author == "")
    {
        QMessageBox::warning(this,"提示","请输入作者名称");
        return;
    }    int id = ui->spinBox->value();
    double price = ui->doubleSpinBox->value();    // 预处理的SQL语句
    QString sql = "INSERT INTO book VALUES(?,?,?,?)";    // 预处理
    QSqlQuery sq;
    sq.prepare(sql);    // 绑定参数
    sq.addBindValue(id);
    sq.addBindValue(name);
    sq.addBindValue(price);
    sq.addBindValue(author);    // 执行绑定后的SQL语句
    if(sq.exec())
    {
        QMessageBox::information(this,"通知","数据插入成功");
    }
    else // 失败
    {
       // 获取错误信息封装类
        QSqlError info = sq.lastError();
        QString text = info.text();
        QMessageBox::warning(this,"通知","数据插入失败");
        qDebug() << text;
    }
}void Dialog::btnClickedSlots(int id)
{
    if(id == 1)
    {
        qDebug () << "增加";
        insertData();
    }
    else if(id == 2)
    {
        qDebug () << "删除";
    }
    else if(id == 3)
    {
        qDebug () << "修改";
    }
    else if(id == 4)
    {
        qDebug () << "查找";
    }
    else
    {    }
}

删除

dialog.h

#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QButtonGroup>
#include <QSqlDatabase>
#include <QDebug>
#include <QSqlError>
#include <QMessageBox>
#include <QSqlQuery>class Dialog : public QDialog
{
private:
    void deleteData();  // 删除数据
};#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"// 删除数据
void Dialog::deleteData()
{
    int id = ui->spinBox->value();    // 查询表中id是否存在
    // TODO    // 预处理的SQL语句
    QString sql = "DELETE FROM book WHERE id=?";    // 预处理
    QSqlQuery sq;
    sq.prepare(sql);    // 绑定参数
    sq.addBindValue(id);    if(sq.exec())
    {
        QMessageBox::information(this,"通知","数据删除成功");
    }
    else
    {
        // 获取错误信息封装类
        QSqlError info = sq.lastError();
        QString text = info.text();
        QMessageBox::critical(this,"通知",text);
    }
}void Dialog::btnClickedSlots(int id)
{
    if(id == 1)
    {
        qDebug () << "增加";
        insertData();
    }
    else if(id == 2)
    {
        qDebug () << "删除";
        deleteData();
    }
    else if(id == 3)
    {
        qDebug () << "修改";
    }
    else if(id == 4)
    {
        qDebug () << "查找";
    }
    else
    {
    }
}

// 绑定Oracle风格的占位符参数,绑定的顺序可以乱序
// 参数1:占位符
// 参数2:要绑定的数据
void	bindValue(const QString & placeholder, const QVariant & val)

dialog.h

#ifndef DIALOG_H
#define DIALOG_Hclass Dialog : public QDialog
{private:
    void updateData();  // 更改数据
};#endif // DIALOG_H

dilaog.cpp

#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
}// 更改数据
void Dialog::updateData()
{
    // 获取用户输入
    QString name = ui->lineEdit->text();
    if(name == "")
    {
        QMessageBox::warning(this,"提示","请输入书名!");
        return;
    }
    QString author = ui->lineEdit_2->text();
    if(author == "")
    {
        QMessageBox::warning(this,"提示","请输入作者名!");
        return;
    }    int id = ui->spinBox->value();
    double price = ui->doubleSpinBox->value();    // 预处理sql语句(Oracle风格)
    QString sql = "UPDATE book SET name=:name,price=:price,author=:author WHERE id=:id";    // 预处理
    QSqlQuery sq;
    sq.prepare(sql);    // 绑定数据
    sq.bindValue(":price",price);
    sq.bindValue(":id",id);
    sq.bindValue(":author",author);
    sq.bindValue(":name",name);    // 执行绑定后的sql语句
    if(sq.exec())
    {
        qDebug() << "更新成功";
        QMessageBox::information(this,"提示","数据更改成功");
    }
    else
    {
        QString text =  sq.lastError().text();
        QMessageBox::critical(this,"提示",text);
    }}void Dialog::btnClickedSlots(int id)
{
    if(id == 1)
    {
        qDebug () << "增加";
        insertData();
    }
    else if(id == 2)
    {
        qDebug () << "删除";
        deleteData();
    }
    else if(id == 3)
    {
        qDebug () << "修改";
        updateData();
    }
    else if(id == 4)
    {
        qDebug () << "查找";
    }
    else
    {    }
}

5、查询

5.1 全查

相关函数

// 判断查询结果有无数据,如果有则移动游标并取出,没有返回false
bool QSqlQuery::​next()
// 按照字段序号取出对应的值,需要从0开始
// 返回值为QVariant类型,可以根据需要直接转为所需类型
QVariant QSqlQuery::​value(int index) const
// 按照字段名称取出对应的值
// 返回值为QVariant类型,可以根据需要直接转为所需类型
QVariant QSqlQuery::​value(const QString & name) const

dialog.h

#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QButtonGroup>
#include <QSqlDatabase>
#include <QDebug>
#include <QSqlError>
#include <QMessageBox>
#include <QSqlQuery>namespace Ui {
class Dialog;
}class Dialog : public QDialog
{
private:
    void seleteAll();   // 查找全部数据
    bool isDataExists(int id);  // 判断数据是否存在
};#endif // DIALOG_H

dilaog.cpp

#include "dialog.h"
#include "ui_dialog.h"// 全查
void Dialog::seleteAll()
{
    ui->textBrowser->clear();
    QString sql = "SELECT * FROM book";
    QSqlQuery sq;    if(sq.exec(sql))
    {
        while(sq.next())    // 循环取出
        {
           QString id = sq.value(0).toString();
           QString name = sq.value(1).toString();
           QString price = sq.value(2).toString();
           QString author = sq.value(3).toString();           QString text = id.append("-")+name.append("-")+price.append("-")+author;
           ui->textBrowser->append(text);
        }
    }
}// 判断数据是否存在,采用字符串拼接的方式
bool Dialog::isDataExists(int id)
{
    QString idText = QString::number(id);
    QString sql = "SELECT *FROM book WHERE id=";
    sql.append(idText); // 拼接只为证明可以使用,但是不建议    QSqlQuery sq;
    if(sq.exec(sql))
    {
       return sq.next();
    }
    else
    {
        return false;
    }
}void Dialog::btnClickedSlots(int id)
{
    if(id == 1)
    {
        qDebug () << "增加";
        insertData();
    }
    else if(id == 2)
    {
        qDebug () << "删除";
        deleteData();
    }
    else if(id == 3)
    {
        qDebug () << "修改";
        updateData();
    }
    else if(id == 4)
    {
        qDebug () << "查找";
        seleteAll();
    }
    else
    {    }
}

5.2 模糊查询

可以使用LIKE关键字配合两个通配符实现模糊查询。

  • %

任意多个(0,1,......n)字符

  • _

任意一个字符

[查询] 查询“文”字辈的人员信息。

SELECT * FROM book WHERE name LIKE "_文%";

[例子]查询姓名中包含"文"的人员信息

SELECT * FROM book WHERE name LIKE "%文%";

dialog.h

#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QButtonGroup>
#include <QSqlDatabase>
#include <QDebug>
#include <QSqlError>
#include <QMessageBox>
#include <QSqlQuery>namespace Ui {
class Dialog;
}class Dialog : public QDialog
{
    Q_OBJECTpublic:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();private:
    Ui::Dialog *ui;
    QButtonGroup *group;
    QSqlDatabase db;    // 数据库连接对象
    void connetD2B();   // 连接到数据库
    void createTable(); // 创建表
    void insertData();  // 添加数据
    void deleteData();  // 删除数据
    void updateData();  // 更改数据
    void seleteAll();   // 查找全部数据
    bool isDataExists(int id);  // 判断数据是否存在
    void selectLike();  // 模糊查询private slots:
    void btnClickedSlots(int);
};#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    group = new QButtonGroup(this);
    group->addButton(ui->pushButtonInsert,1);
    group->addButton(ui->pushButtonDelete,2);
    group->addButton(ui->pushButtonUpdate,3);
    group->addButton(ui->pushButtonSelect,4);    connect(group,SIGNAL(buttonClicked(int)),
            this,SLOT(btnClickedSlots(int)));    connetD2B();
}Dialog::~Dialog()
{
    // 关闭数据库连接
    if(db.isOpen())
    {
        db.close();
    }
    delete ui;
}// 连接数据库
void Dialog::connetD2B()
{
    // 获取数据库的连接对象
    db = QSqlDatabase::addDatabase("QSQLITE");
    // 设置数据库名称
    db.setDatabaseName("book_management.db");
    // 打开数据库连接
    bool ret = db.open();
    if(ret == true)
    {
        qDebug () << "打开成功";
        createTable();
    }
    else
    {
        // 数据库连接打开失败
        QSqlError errInfo = db.lastError();
        QString text = errInfo.text();
        QMessageBox::critical(this,"错误",text);
    }
}// 创建表
void Dialog::createTable()
{
    // sql语句
    QString sql = "CREATE TABLE book(id INTEGER PRIMARY KEY,name TEXT,price REAL,author TEXT);";    // 创建数据库操作类
    QSqlQuery sq;    if(sq.exec(sql))    // 表创建成功
    {
        qDebug() << "建表成功";
    }
    else    // 建表失败,注意:建表成功或者失败都很正常,如果要建立的表已经存在,就会建表失败
    {
        QSqlError errInfo = sq.lastError();
        QString text = errInfo.text();
        qDebug() << "建表失败:" << text;
    }
}// 插入数据
void Dialog::insertData()
{
    QString name = ui->lineEdit->text();
    if(name == "")
    {
        QMessageBox::warning(this,"提示","请输入书名");
        return;
    }
    QString author = ui->lineEdit_2->text();
    if(author == "")
    {
        QMessageBox::warning(this,"提示","请输入作者名称");
        return;
    }    int id = ui->spinBox->value();
    double price = ui->doubleSpinBox->value();    // 预处理的SQL语句
    QString sql = "INSERT INTO book VALUES(?,?,?,?)";    // 预处理
    QSqlQuery sq;
    sq.prepare(sql);    // 绑定参数
    sq.addBindValue(id);
    sq.addBindValue(name);
    sq.addBindValue(price);
    sq.addBindValue(author);    // 执行绑定后的SQL语句
    if(sq.exec())
    {
        QMessageBox::information(this,"通知","数据插入成功");
    }
    else // 失败
    {
       // 获取错误信息封装类
        QSqlError info = sq.lastError();
        QString text = info.text();
        QMessageBox::warning(this,"通知","数据插入失败");
        qDebug() << text;
    }
}// 删除数据
void Dialog::deleteData()
{
    int id = ui->spinBox->value();    // 查询表中id是否存在
    if(!isDataExists(id))
    {
        QMessageBox::information(this,"提示","没有找到要删除的数据");
        return;
    }    // 预处理的SQL语句
    QString sql = "DELETE FROM book WHERE id=?";    // 预处理
    QSqlQuery sq;
    sq.prepare(sql);    // 绑定参数
    sq.addBindValue(id);    if(sq.exec())
    {
        QMessageBox::information(this,"通知","数据删除成功");
    }
    else
    {
        // 获取错误信息封装类
        QSqlError info = sq.lastError();
        QString text = info.text();
        QMessageBox::critical(this,"通知",text);
    }
}// 更改数据
void Dialog::updateData()
{
    // 获取用户输入
    QString name = ui->lineEdit->text();
    if(name == "")
    {
        QMessageBox::warning(this,"提示","请输入书名!");
        return;
    }
    QString author = ui->lineEdit_2->text();
    if(author == "")
    {
        QMessageBox::warning(this,"提示","请输入作者名!");
        return;
    }    int id = ui->spinBox->value();
    double price = ui->doubleSpinBox->value();    // 查询表中id是否存在
    if(!isDataExists(id))
    {
        QMessageBox::information(this,"提示","没有找到要修改的数据");
        return;
    }    // 预处理sql语句(Oracle风格)
    QString sql = "UPDATE book SET name=:name,price=:price,author=:author WHERE id=:id";    // 预处理
    QSqlQuery sq;
    sq.prepare(sql);    // 绑定数据
    sq.bindValue(":price",price);
    sq.bindValue(":id",id);
    sq.bindValue(":author",author);
    sq.bindValue(":name",name);    // 执行绑定后的sql语句
    if(sq.exec())
    {
        qDebug() << "更新成功";
        QMessageBox::information(this,"提示","数据更改成功");
    }
    else
    {
        QString text =  sq.lastError().text();
        QMessageBox::critical(this,"提示",text);
    }}// 全查
void Dialog::seleteAll()
{
    ui->textBrowser->clear();
    QString sql = "SELECT * FROM book";
    QSqlQuery sq;    if(sq.exec(sql))
    {
        while(sq.next())    // 循环取出
        {
           QString id = sq.value(0).toString();
           QString name = sq.value(1).toString();
           QString price = sq.value(2).toString();
           QString author = sq.value(3).toString();           QString text = id.append("-")+name.append("-")+price.append("-")+author;
           ui->textBrowser->append(text);
        }
    }
}// 判断数据是否存在,采用字符串拼接的方式
bool Dialog::isDataExists(int id)
{
    QString idText = QString::number(id);
    QString sql = "SELECT *FROM book WHERE id=";
    sql.append(idText); // 拼接只为证明可以使用,但是不建议    QSqlQuery sq;
    if(sq.exec(sql))
    {
       return sq.next();
    }
    else
    {
        return false;
    }
}// 模糊查询
void Dialog::selectLike()
{
    // 获取用户输入数据
    QString name = ui->lineEdit->text();
    if(name == "")
    {
        QMessageBox::warning(this,"提示","请输入书名");
        return;
    }    QString sql = "SELECT * FROM book WHERE name LIKE ?";    // 预处理
    QSqlQuery sq;
    sq.prepare(sql);
    sq.addBindValue(name.prepend("%").append("%"));
    if(sq.exec())
    {
        // 是否查询到状态
        bool retState = true;
        // 清空上一次显式
        ui->textBrowser->clear();        while(sq.next())
        {
            QString id = sq.value(0).toString();
            QString name = sq.value(1).toString();
            QString price = sq.value(2).toString();
            QString author = sq.value(3).toString();            // 显式
            QString text = id.append("-")+name.append("-")+price.append("-")+author;
            ui->textBrowser->append(text);
            retState = false;
        }
        if(retState)
        {
            QMessageBox::information(this,"提示","没有查询到相关数据");
        }
    }
    else
    {
        QString text = sq.lastError().text();
        text.append("查询失败");
        QMessageBox::critical(this,"错误",text);
    }
}void Dialog::btnClickedSlots(int id)
{
    if(id == 1)
    {
        qDebug () << "增加";
        insertData();
    }
    else if(id == 2)
    {
        qDebug () << "删除";
        deleteData();
    }
    else if(id == 3)
    {
        qDebug () << "修改";
        updateData();
    }
    else if(id == 4)
    {
        qDebug () << "查找";
        selectLike();
    }
    else
    {    }
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com