QML - Урок 016. База данных SQLite и работа с ней в QML Qt

База данных, SQLite, Qt, QML, Android, DataBase, Model, View, MVC

Небольшой пример по работе с базой данных в QML Qt . В данном уроке сводится воедино информация о применении сигналов и слотов в QML Qt , о доступе к C++ классам из QML слоя, реализации интерфейса приложения на QML, а также о реализации модели/представлении для таблицы базы данных.

База данных содержит таблицу со списком людей, в которой имеется четыре колонки:

  • id (INTEGER) - уникальный номер записи;
  • FirstName (VARCHAR (255)) - Имя;
  • SurName (VARCHAR (255)) - Фамилия;
  • Nik (VARCHAR (255)) - Ник.

Приложение должно реализовывать удаление и добавление записей в базу данных через интерфейс приложения. Для добавления записей в Базу данных будет использоваться три поля для ввода данных и кнопка, которая инициализирует добавление данных в базу данных SQL . Добавление записей в таблицу осуществляется через класс обёртку предназначенным для этого методом.Также в приложении присутствует класс ListModel , который реализует модель представления данных для отображения информации в TableView в слое QML.

Структура проекта

  • QmlDataBase.pro - профайл проекта;
  • database.h - заголовочный файл класса-обёртки для работы с базой данных;
  • database.cpp - файл исходных кодов класса-обёртки для работы с базой данных;
  • listmodel.h - заголовочный файл модели данных;
  • listmodel.cpp - файл исходных кодов модели данных;
  • main.cpp - основной файл исходных кодов приложения;
  • main.qml - основной файл qml.

QmlDataBase.pro

Для работы с базой данных необходимо подключить модуль sql, а также модуль widgets для нативного внешнего вида приложения.

TEMPLATE = app

QT += qml quick widgets sql

SOURCES += main.cpp \
    database.cpp \
    listmodel.cpp

RESOURCES += qml.qrc

# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =

# Default rules for deployment.
include(deployment.pri)

HEADERS += \
    database.h \
    listmodel.h

main.cpp

В основном файле исходных кодов подключаем класс-обёртку для работы с базой данных и класс модели данных. Объекты этих классов необходимо объявить и инициализировать в данном файле, а также настроить доступ к этим объектам и их свойствам из QML слоя.

После того, как доступ к объектам настроен, из QML слоя становятся доступны следующие свойства и функции объекта, которые объявлены в его классе в качестве:

  1. Сигналов
  2. Слотов
  3. А также функции, которые фигурируют в макросе Q_PROPERTY
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>

#include "database.h"
#include "listmodel.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QQmlApplicationEngine engine;

    // Подключаемся к базе данных
    DataBase database;
    database.connectToDataBase();

    // Объявляем и инициализируем модель данных
    ListModel *model = new ListModel();

    // Обеспечиваем доступ к модели и классу для работы с базой данных из QML
    engine.rootContext()->setContextProperty("myModel", model);
    engine.rootContext()->setContextProperty("database", &database);

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

database.h

В данном классе объявлены методы для работы с базой данных:

  • методы для подключения к базе данных, её восстановления;
  • методы для добавления записи в базу данных;
  • методы для удаления записей в таблице данных.

Подключение к базе данных необходимо для правильной работы модели данных, которая наследована от QSqlQueryModel . И соответственно использует SQL запросы к открытой в приложении базы данных.

Данный класс реализует паттерн проектирования Facade, хотя и не полностью, поскольку как я уже сказал, что одна из сущностей QSqlQueryModel используется в модели данных в этом уроке.

ВНИМАНИЕ!!! - файл базы данных создается в папке C:/example , поэтому или поправьте метод DataBase::connectToDataBase() или создайте папку example на диске C .

#ifndef DATABASE_H
#define DATABASE_H

#include <QObject>
#include <QSql>
#include <QSqlQuery>
#include <QSqlError>
#include <QSqlDatabase>
#include <QFile>
#include <QDate>
#include <QDebug>

/* Директивы имен таблицы, полей таблицы и базы данных */
#define DATABASE_HOSTNAME   "NameDataBase"
#define DATABASE_NAME       "Name.db"

#define TABLE                   "NameTable"         // Название таблицы
#define TABLE_FNAME             "FisrtName"         // Вторая колонка
#define TABLE_SNAME             "SurName"           // Третья колонка
#define TABLE_NIK               "Nik"               // Четвертая колонка

// Первая колонка содержит Autoincrement ID

class DataBase : public QObject
{
    Q_OBJECT
public:
    explicit DataBase(QObject *parent = 0);
    ~DataBase();
    /* Методы для непосредственной работы с классом
     * Подключение к базе данных и вставка записей в таблицу
     * */
    void connectToDataBase();

private:
    // Сам объект базы данных, с которым будет производиться работа
    QSqlDatabase    db;

private:
    /* Внутренние методы для работы с базой данных
     * */
    bool openDataBase();        // Открытие базы данных
    bool restoreDataBase();     // Восстановление базы данных
    void closeDataBase();       // Закрытие базы данных
    bool createTable();         // Создание базы таблицы в базе данных

public slots:
    bool inserIntoTable(const QVariantList &data);      // Добавление записей в таблицу
    bool inserIntoTable(const QString &fname, const QString &sname, const QString &nik);
    bool removeRecord(const int id); // Удаление записи из таблицы по её id
};

#endif // DATABASE_H

database.cpp

Инициализация подключения к базе данных производится методом connectToDataBase() . Название таблицы, базы данных, файла, а также колонок в таблице определены в директивах define в заголовочном файле.

#include "database.h"

DataBase::DataBase(QObject *parent) : QObject(parent)
{

}

DataBase::~DataBase()
{

}

/* Методы для подключения к базе данных
 * */
void DataBase::connectToDataBase()
{
    /* Перед подключением к базе данных производим проверку на её существование.
     * В зависимости от результата производим открытие базы данных или её восстановление
     * */
    if(!QFile("C:/example/" DATABASE_NAME).exists()){
        this->restoreDataBase();
    } else {
        this->openDataBase();
    }
}

/* Методы восстановления базы данных
 * */
bool DataBase::restoreDataBase()
{
    // Если база данных открылась ...
    if(this->openDataBase()){
        // Производим восстановление базы данных
        return (this->createTable()) ? true : false;
    } else {
        qDebug() << "Не удалось восстановить базу данных";
        return false;
    }
    return false;
}

/* Метод для открытия базы данных
 * */
bool DataBase::openDataBase()
{
    /* База данных открывается по заданному пути
     * и имени базы данных, если она существует
     * */
    db = QSqlDatabase::addDatabase("QSQLITE");
    db.setHostName(DATABASE_HOSTNAME);
    db.setDatabaseName("C:/example/" DATABASE_NAME);
    if(db.open()){
        return true;
    } else {
        return false;
    }
}

/* Методы закрытия базы данных
 * */
void DataBase::closeDataBase()
{
    db.close();
}

/* Метод для создания таблицы в базе данных
 * */
bool DataBase::createTable()
{
    /* В данном случае используется формирование сырого SQL-запроса
     * с последующим его выполнением.
     * */
    QSqlQuery query;
    if(!query.exec( "CREATE TABLE " TABLE " ("
                            "id INTEGER PRIMARY KEY AUTOINCREMENT, "
                            TABLE_FNAME     " VARCHAR(255)    NOT NULL,"
                            TABLE_SNAME     " VARCHAR(255)    NOT NULL,"
                            TABLE_NIK       " VARCHAR(255)    NOT NULL"
                        " )"
                    )){
        qDebug() << "DataBase: error of create " << TABLE;
        qDebug() << query.lastError().text();
        return false;
    } else {
        return true;
    }
    return false;
}

/* Метод для вставки записи в базу данных
 * */
bool DataBase::inserIntoTable(const QVariantList &data)
{
    /* Запрос SQL формируется из QVariantList,
     * в который передаются данные для вставки в таблицу.
     * */
    QSqlQuery query;
    /* В начале SQL запрос формируется с ключами,
     * которые потом связываются методом bindValue
     * для подстановки данных из QVariantList
     * */
    query.prepare("INSERT INTO " TABLE " ( " TABLE_FNAME ", "
                                             TABLE_SNAME ", "
                                             TABLE_NIK " ) "
                  "VALUES (:FName, :SName, :Nik)");
    query.bindValue(":FName",       data[0].toString());
    query.bindValue(":SName",       data[1].toString());
    query.bindValue(":Nik",         data[2].toString());

    // После чего выполняется запросом методом exec()
    if(!query.exec()){
        qDebug() << "error insert into " << TABLE;
        qDebug() << query.lastError().text();
        return false;
    } else {
        return true;
    }
    return false;
}

/* Второй метод для вставки записи в базу данных
 * */
bool DataBase::inserIntoTable(const QString &fname, const QString &sname, const QString &nik)
{
    QVariantList data;
    data.append(fname);
    data.append(sname);
    data.append(nik);

    if(inserIntoTable(data))
        return true;
    else
        return false;
}

/* Метод для удаления записи из таблицы
 * */
bool DataBase::removeRecord(const int id)
{
    // Удаление строки из базы данных будет производитсья с помощью SQL-запроса
    QSqlQuery query;

    // Удаление производим по id записи, который передается в качестве аргумента функции
    query.prepare("DELETE FROM " TABLE " WHERE id= :ID ;");
    query.bindValue(":ID", id);

    // Выполняем удаление
    if(!query.exec()){
        qDebug() << "error delete row " << TABLE;
        qDebug() << query.lastError().text();
        return false;
    } else {
        return true;
    }
    return false;
}

listmodel.h

Модель данных является классом, наследованным от QSqlQueryModel, в котором переопределены методы data() и roleNames(). Также в классе перечислены роли, по которым передается информация в представление в интерфейсе. Для удаления данных необходимо получать уникальный ID записи, который вытягивается из модели по методом getID() по роли и номеру строки, который был передан из представления. Для получения данных из Базы данных используется метод updateModel(), в котором устанавливается SQL-запрос к Базе данных.

#ifndef LISTMODEL_H
#define LISTMODEL_H

#include <QObject>
#include <QSqlQueryModel>

class ListModel : public QSqlQueryModel
{
    Q_OBJECT
public:
    /* Перечисляем все роли, которые будут использоваться в TableView
     * Как видите, они должны лежать в памяти выше параметра Qt::UserRole
     * Связано с тем, что информация ниже этого адреса не для кастомизаций
     * */
    enum Roles {
        IdRole = Qt::UserRole + 1,      // id
        FNameRole,                      // имя
        SNameRole,                      // фамилия
        NikRole                         // ник
    };

    // объявляем конструктор класса
    explicit ListModel(QObject *parent = 0);

    // Переопределяем метод, который будет возвращать данные
    QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;

protected:
    /* хешированная таблица ролей для колонок.
     * Метод используется в дебрях базового класса QAbstractItemModel,
     * от которого наследован класс QSqlQueryModel
     * */
    QHash<int, QByteArray> roleNames() const;

signals:

public slots:
    void updateModel();
    int getId(int row);
};

#endif // LISTMODEL_H

listmodel.cpp

Для реализации работы модели в файл исходных кодов подключаем заголовочный файл database.h, в котором имеются директивы define для названий таблицы и колонок. Возвращение данных производится по предопределенным ролям, которые должны быть идентичными в TableView, который будет использован для отображения данных.

#include "listmodel.h"
#include "database.h"

ListModel::ListModel(QObject *parent) :
    QSqlQueryModel(parent)
{
    this->updateModel();
}

// Метод для получения данных из модели
QVariant ListModel::data(const QModelIndex & index, int role) const {

    // Определяем номер колонки, адрес так сказать, по номеру роли
    int columnId = role - Qt::UserRole - 1;
    // Создаём индекс с помощью новоиспечённого ID колонки
    QModelIndex modelIndex = this->index(index.row(), columnId);

    /* И с помощью уже метода data() базового класса
     * вытаскиваем данные для таблицы из модели
     * */
    return QSqlQueryModel::data(modelIndex, Qt::DisplayRole);
}

// Метод для получения имен ролей через хешированную таблицу.
QHash<int, QByteArray> ListModel::roleNames() const {
    /* То есть сохраняем в хеш-таблицу названия ролей
     * по их номеру
     * */
    QHash<int, QByteArray> roles;
    roles[IdRole] = "id";
    roles[FNameRole] = "fname";
    roles[SNameRole] = "sname";
    roles[NikRole] = "nik";
    return roles;
}

// Метод обновления таблицы в модели представления данных
void ListModel::updateModel()
{
    // Обновление производится SQL-запросом к базе данных
    this->setQuery("SELECT id, " TABLE_FNAME ", " TABLE_SNAME ", " TABLE_NIK " FROM " TABLE);
}

// Получение id из строки в модели представления данных
int ListModel::getId(int row)
{
    return this->data(this->index(row, 0), IdRole).toInt();
}

main.qml

В Qt парадигма модели/вида/контроллера изменена на модель/представление. Представление объединяет в себе контроллер и вид. Таким образом, main.qml обрабатывает информацию, которую вводит пользователь и передаёт её в backend в удобоваримом виде, но если учесть, что к объекту класса database дан доступ из QML слоя, а добавление данных производится через функцию слот, то условно можно принять, что контроллер реализован в представлении.

import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.1
import QtQuick.Dialogs 1.2

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    // Слой с TaxtField`ами и Button для занесения записей в базу данных
    RowLayout {
        id: rowLayout
        anchors.top: parent.top
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.margins: 5

        spacing: 10

        Text {text: qsTr("Имя")}
        TextField {id: fnameField}
        Text {text: qsTr("Фамилия")}
        TextField { id: snameField}
        Text {text: qsTr("НИК")}
        TextField {id: nikField}

        Button {
            text: qsTr("Добавить")

            // Вносим новую запись в базу данных
            onClicked: {
                database.inserIntoTable(fnameField.text , snameField.text, nikField.text)
                myModel.updateModel() // И обновляем модель данных с новой записью
            }
        }
    }

    TableView {
        id: tableView
        anchors.top: rowLayout.bottom
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.bottom: parent.bottom
        anchors.margins: 5

        TableViewColumn {
            role: "fname"
            title: "Имя"
        }
        TableViewColumn {
            role: "sname"
            title: "Фамилия"
        }
        TableViewColumn {
            role: "nik"
            title: "НИК"
        }

        model: myModel

        // Настройка строки в TableView для перехавата левого клика мыши
        rowDelegate: Rectangle {
            anchors.fill: parent
            color: styleData.selected ? 'skyblue' : (styleData.alternate ? 'whitesmoke' : 'white');
            MouseArea {
                anchors.fill: parent
                acceptedButtons: Qt.RightButton | Qt.LeftButton
                onClicked: {
                    tableView.selection.clear()
                    tableView.selection.select(styleData.row)
                    tableView.currentRow = styleData.row
                    tableView.focus = true

                    switch(mouse.button) {
                    case Qt.RightButton:
                        contextMenu.popup() // Вызываем контексткное меню
                        break
                    default:
                        break
                    }
                }
            }
        }
    }

    // Контекстно меню предлагает удаление строки из базы данных
    Menu {
        id: contextMenu

        MenuItem {
            text: qsTr("Удалить")
            onTriggered: {
                /* Вызываем диалоговое окно,
                 * которое уточнит намерение удалить строку из базы данных
                 * */
                dialogDelete.open()
            }
        }
    }

    // Диалог подтверждения удаления строки из базы данных
    MessageDialog {
        id: dialogDelete
        title: qsTr("Удаление записи")
        text: qsTr("Подтвердите удаление записи из журнала")
        icon: StandardIcon.Warning
        standardButtons: StandardButton.Ok | StandardButton.Cancel

        // При положительном ответе ...
        onAccepted: {
            /* ... удаляем строку по id,
             * который забираем из модели данных
             * по номеру строки в представлении
             * */
            database.removeRecord(myModel.getId(tableView.currentRow))
            myModel.updateModel();  // Обновляем модель данных
        }
    }
}

Итог

В результате Вы получите приложение, которое будет выглядеть так, как показано на ниже следующем рисунке. Также рекомендую к ознакомлению видеоурок по данной статье, поскольку в нём имеется более подробная информация и дополнения по данному программному коду.

Кроме этого рекомендую почитать подробнее о паттерне проектирования Facade и посмотреть более полный вариант реализации данного паттерна в следующей статье: Шаблон проектирования "Фасад"

Видеоурок

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.
Поддержать автора Donate
Добрый день, запустил ваш пример при нажатии на кнопку получаю вот эту ошибку

ASSERT failure in QList<T>::operator[]: "index out of range", file ../../Qt5.11.0/5.11.0/gcc_64/include/QtCore/qlist.h, line 545

Подскажите пожалуйста в чём может быть дело на что она указывает где искать ?
Разобрался, не правильное добавление записи в БД а именно лишний запрос query.bindValue стоял в методе inserIntoTable.
W
  • #
  • 15 июня 2018 г. 14:08

Добрый день, пытаюсь передать текст из QML слоя в C++ при нажатии на кнопку. При нажатии на кнопку выводит ошибку.


TypeError: Property 'remove_db' of object [object Object] is not a function
Не могу понять в чем ошибка(новичок в Qt) Если есть возможно можно простой пример как передать текст или число из QML лося в C++ или где ошибка в моем коде. Спасибо заранее)
QML:

import QtQuick 2.0
import Sailfish.Silica 1.0
import QtPositioning 5.3
import QtLocation 5.0
import QtQuick 2.0
import QtWebKit 3.0
import MyModule 1.0

Page{
    id: pageMenu
    GPSCoor{
        id:data
        // @disable-check M16
        onSendToTime:
        {
            myModel.append({"time" : data_time_real_time})
        }
    }

    Rectangle{
        id: kv_menu
        anchors.fill: parent                                                 //Привязка к радителю
        color: "steelblue"
        ListView
        {
            id: myListView
            anchors
            {
                top: kv_menu.top
                right: kv_menu.right
                left: kv_menu.left
                bottom: buttonHistory.top

                rightMargin: 30
                leftMargin: 30
                topMargin: 30
                bottomMargin: 100
            }

            model: myModel
            delegate: Item{
                id:itemrec
                width: myListView.width
                height: 90

                Button{
                    id: rectest
                    anchors.margins: 6
                    anchors.fill: parent

                    Text
                    {
                        id:textNuj
                        objectName: "textZae"
                        color: "white"
                        font.pixelSize: 40
                        text: time + " - " + (model.index+1)
                        anchors.horizontalCenter: rectest.horizontalCenter
                        anchors.verticalCenter: rectest.verticalCenter
                    }
                    onClicked:
                    {
//                        console.log("text - " + text)
//                        console.log("modelN - "+ model.index)
//                        console.log("textNuj - " + textNuj.text)
//                        //pageStack.push(dialog)
                        data.remove_db(model.index);
                    }
                }
            }
        }
        ListModel
        {
            id:myModel
        }
        Button
        {
            id: buttonHistory
            height: 90
            anchors{
                right: kv_menu.right
                left: kv_menu.left
                bottom: kv_menu.bottom

                rightMargin: 30
                leftMargin: 30
                bottomMargin: 30
            }
            Label{
                color: "white"
                text: "Показать треки"
                anchors.horizontalCenter: buttonHistory.horizontalCenter
                anchors.verticalCenter: buttonHistory.verticalCenter
            }
            onClicked: {
                data.pageMapX()
            }
        }
    }
    Component{
        id: dialog
        Dialog {
            id: winDialog
            property string name

            Rectangle{
                id:winDialogRec1
                color: "steelblue"
                anchors.fill: parent
                property string name
                DialogHeader
                {   id: dialogHeader
                    acceptText: qsTr("Принять")
                    cancelText: qsTr("Отменить")
                }
                Rectangle{
                    id:winDialogRec
                    color: "steelblue"
                    anchors.horizontalCenter: parent.horizontalCenter
                    anchors.top: parent.top
                    anchors.topMargin: 400

                    Label{
                        id:label1
                        anchors{
                           horizontalCenter: winDialogRec.horizontalCenter
                           top: parent.top
                        }
                        color: "white"
                        text: "Вы действительно хотите удалить трек?"
                    }
                    Label{
                        id: label2
                        anchors{
                            horizontalCenter: winDialogRec.horizontalCenter
                            top: parent.top

                            topMargin: 250

                        }
                        color: "white"
                        text: name
                    }
                    Button{
                        width: parent / 2 - 45
                        anchors{
                            top: parent.top
                            left: parent.left
                            topMargin: 120
                            leftMargin: 30
                        }
                        text: "Нет"
                        onClicked:
                        {
                           label2.text = "Нет, не удалять этот трек"
                        }
                    }
                    Button{

                        width: parent / 2 - 45
                        anchors{
                            top: parent.top
                            right: parent.right
                            topMargin: 120
                            rightMargin: 30
                        }

                        text: "Да"
                        onClicked:
                        {
                           label2.text = "Да, удалить этот трек"
                         }
                    }

                }

            }

        }
    }
}
Заголовок:
#ifndef GPSCOOR_H
#define GPSCOOR_H
#include <QObject>
#include <QDebug>

class GPSCoor: public QObject
{
    Q_OBJECT
    Q_PROPERTY(double x_cor READ  getSomePropertyX   WRITE setSomePropertyX   NOTIFY sendToQml)     //Для обменна даными с переменной x_cor
    Q_PROPERTY(double y_cor READ  getSomePropertyY   WRITE setSomePropertyY   NOTIFY sendToQml)     //Для обменна даными с переменной y_cor
    Q_PROPERTY(QString way   READ  getSomePropertyWay WRITE setSomePropertyWay NOTIFY sendToWay)     //Для обменна даными о времени t
    Q_PROPERTY(QString data_time_real_time  READ  getSomePropertyTime   WRITE setSomePropertyTime   NOTIFY sendToTime)     //Для обменна даными о расстоянии m

    //    Q_PROPERTY(double arreyXY READ  getSomePropertyX WRITE setSomePropertyX NOTIFY sendToQml)     //Для обменна даными с переменной x_cor

public:
    explicit GPSCoor(QObject *parent = 0);
    Q_INVOKABLE void remove_db();

    double getSomePropertyX()const;                                                             //Для обменна даными с переменной x_cor
    double getSomePropertyY()const;                                                             //Для обменна даными с переменной y_cor
    QString getSomePropertyTime()const;                                                          //Для обменна даными о времени t
    QString getSomePropertyWay()const;                                                           //Для обменна даными о расстоянии m

    void setSomePropertyY(const double &);                                                      //Для обменна даными с переменной y_cor
    void setSomePropertyX(const double &);                                                      //Для обменна даными с переменной x_cor
    void setSomePropertyTime(const QString &);                                                   //Для обменна даными о времени t
    void setSomePropertyWay(const QString &);                                                    //Для обменна даными о расстоянии m

    void creat_db();                                                                            //Для создания базы данных и записи данных
    void insert_db();                                                                           //Для извлечения данных и бызы
    void distance();

    //Для выисления растояния от точки до точки
signals:
    void sendToQml(double);                                                                     //Сигнал для передачи данных в qml
    void sendToWay(QString);
    void sendToTime(QString);

public slots:

    void reciveX();                                                                             //Сигнал для получения данных с qml(FirstPage)
    void reciveTime();                                                                          //Сигнал для получения данных о времени
    //   void reciveWay();
    void pageMapX();                                                                            //Сигнал для получения данных с qml(Map)


private:
    QString data_time_real_time;
    QString way;
    double x_cor;                                                                               //Перменная координата х_cor
    double y_cor;                                                                               //Перменная координата y_cor
    int data_time;                                                                              //Перменная для измерении времени

    double Way_point=0;

    float CMX11 = 0;
    float CMY11 = 0;
    float CMX21 = 0;
    float CMY21 = 0;
    const float pi = 3.141592653589793;
    const float radius = 6378.16;
    double num =  1;                                                                               //Перменная счетчик для цыкла
    double n = 1000;
    double z = 2;
    //    double arreyXY[2][1000];

};
#endif // GPSCOOR_H
С++:
#include "gpscoor.h"
#include <QObject>
#include <QDebug>
#include "QtSql/QSqlDatabase"
#include "QSqlQuery"
#include <QtSql>
#include <QTime>
#include <QLocale>
#include <QDateTime>
#include <QtMath>
#include <math.h>

GPSCoor::GPSCoor(QObject *parent): QObject(parent)
{


}

void GPSCoor::remove_db()
{

    qDebug()<<"remuve_db() = "<<data_time_real_time<<endl;
    QSqlQuery query;                                                     //Осуществляем запрос
    // Удаление строки из базы данных будет производитсья с помощью SQL-запроса


       // Удаление производим по id записи, который передается в качестве аргумента функции
       query.prepare("DELETE FROM my_ta WHERE data_time= :data_time;");
       query.bindValue(":data_time", data_time_real_time);

       // Выполняем удаление
       if(!query.exec()){
           qDebug() << "error delete row " << "my_ta";
           qDebug() << query.lastError().text();

       } else
       {

       }

    //    query.exec("SELECT id, data_time ,x_cor, y_cor FROM my_ta ");
//    while (query.next())                                                 //Выводим значения из запроса
//    {
//        int id = query.value(0).toInt();                                 //Получаю данные из БД
//        data_time = query.value(1).toInt();                          //Получаю данные из БД
//        x_cor = query.value(2).toDouble();                               //Получаю данные из БД
//        y_cor = query.value(3).toDouble();                               //Получаю данные из БД
//        QString data_time_2 = QString::number(data_time);
//        if(data_time_real_time == data_time_2)
//        {
//            query.exec("DELETE FROM jobs WHERE data_time = ?");
//            query.addBindValue(data_time);
//            qDebug()<<"Delete for BD good"<<endl;
//        }
//        else{
//            qDebug()<<"Error Delete for BD bad"<<endl;
//        }
//    }

}

void GPSCoor::reciveTime()
{
   emit sendToTime(data_time_real_time);
}

double GPSCoor::getSomePropertyX()const                 //Для обменна даными с переменной x_cor
{
    return x_cor;
}

double GPSCoor::getSomePropertyY()const                 //Для обменна даными с переменной y_cor
{    
    return y_cor;
}

QString GPSCoor::getSomePropertyWay()const                 //Для обменна даными с переменной way
{
    return way;
}

QString GPSCoor::getSomePropertyTime()const                 //Для обменна даными с переменной time
{
    return data_time_real_time;
}

void GPSCoor::setSomePropertyX(const double &i)         //Для обменна даными с переменной x_cor
{
    x_cor = i;
    emit sendToQml(x_cor);
}

void GPSCoor::setSomePropertyY(const double &i)         //Для обменна даными с переменной y_cor
{
    y_cor = i;
    emit sendToQml(y_cor);
}

void GPSCoor::setSomePropertyWay(const QString &i)         //Для обменна даными с переменной way
{
    way = i;
    emit sendToWay(way);
}

void GPSCoor::setSomePropertyTime(const QString &i)         //Для обменна даными с переменной time
{
    data_time_real_time = i;
    emit sendToTime(data_time_real_time);
}

void GPSCoor::reciveX()                                 //Принимаю данные из QML(FirstPage)
{
    emit sendToQml(x_cor);                              //Принимаю данные в QML(FirstPage)
    emit sendToQml(y_cor);                              //Принимаю данные в QML(FirstPage)
    emit creat_db();                                    //Для создания и записи БД на стороне С++
    //emit insert_db();                                 //Для извлечения данных и бызы на стороне С++
}

void GPSCoor::pageMapX()                                //Принимаю данные из QML(Map)
{
    emit insert_db();                                   //Для извлечения данных и бызы на стороне С++
}

void GPSCoor::creat_db()                                //Создаем SQLite
{
    QTime time = QTime::currentTime();                  //Создаю обект для получения реальное время
    data_time = time.msecsSinceStartOfDay();            //Записываю время в переменную в формате миллисекунд
    qDebug()<<data_time<<endl;

    QSqlDatabase dbase = QSqlDatabase::addDatabase("QSQLITE");          //Создая обект для QSQLite
    dbase.setDatabaseName("test_2.sqlite");                             //Создаю БД
    if (!dbase.open()) {                                                //Проверяю БД
        qDebug() << "Error db";
    }else{
        qDebug()<<"Good db";
    }

    QSqlQuery a_query;
    // DDL query
    QString str = "CREATE TABLE my_ta ("               //создаю таблицу
            "id integer PRIMARY KEY NOT NULL, "
            "data_time integer,"
            "x_cor double, "
            "y_cor double"
            ");";
    bool b = a_query.exec(str);                        //Проверка на создания
    if (!b) {
        qDebug() << "error2!";
    }
    else{
        qDebug()<<"send2";
    }

    //        QString str_insrt = "INSERT INTO my_ta (data_time,x_cor,y_cor) VALUES (%1, %2, %3);";             // Записываю данные в Таблицу
    //        str = str_insrt.arg(data_time)
    //                .arg(x_cor)
    //                .arg(y_cor);
    //        b = a_query.exec(str);
    //        if (!b) {
    //            qDebug() << "error3";
    //        }else{
    //            qDebug()<<"Send3";
    //        }
}

void GPSCoor::insert_db()                               //Вывести данные из db и отправить в map.qml
{

    QSqlQuery query;                                                     //Осуществляем запрос
    query.exec("SELECT id, data_time ,x_cor, y_cor FROM my_ta ");
    while (query.next())                                                 //Выводим значения из запроса
    {

        int id = query.value(0).toInt();                                 //Получаю данные из БД
        data_time = query.value(1).toInt();                              //Получаю данные из БД
        x_cor = query.value(2).toDouble();                               //Получаю данные из БД
        y_cor = query.value(3).toDouble();                               //Получаю данные из БД

        if(id == num)
        {
            emit sendToQml(x_cor);                                      //Отправляю данные в QML(Map)
            emit sendToQml(y_cor);                                      //Отправляю данные в QML(Map)

            QTime time = QTime::fromMSecsSinceStartOfDay(data_time);
            data_time_real_time = time.toString("hh:mm:ss"); //str = "20:04:23.003"
            emit sendToTime(data_time_real_time);

            qDebug()<< "id - "<< id << endl;                            //простая проерка данных, вывожу на экран
            qDebug()<< "data_time_real_time - "<< data_time_real_time << endl;              //простая проерка данных, вывожу на экран
            qDebug()<< "y_cor - "<< x_cor << endl;
            qDebug()<< "x_cor - "<< y_cor << endl;
            //Вычисление растояния между 2 координатами гипатенуза
            CMX11 = y_cor;
            CMY11 = x_cor;
            if(id==1)
            {
//                CMX21 = y_cor;
//                CMY21 = x_cor;
            }
            else{
               emit distance();

                qDebug()<<"Way (км)  "<< Way_point << endl;
            }
            CMX21 = CMX11;
            CMY21 = CMY11;

        }
        else
        {
        }

    }
    num += 20;                       //Увеличиваю num++
}
void GPSCoor::distance(){
    Way_point = round((Way_point + sqrt(pow((CMX21 - CMX11),2) + pow((CMY21 - CMY11),2))*100)*100)/100;
    way = QString::number(Way_point);
    emit sendToWay(way);
}

что-то мне сдаётся, что здесь просто пересобрать проект нужно с удалением build каталога

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
TT
13 июня 2019 г. 19:01
Taimoor Tanweer

C++ - Тест 001. Первая программа и типы данных

  • Результат:66баллов,
  • Очки рейтинга-1
TT
13 июня 2019 г. 18:51
Taimoor Tanweer

C++ - Тест 002. Константы

  • Результат:75баллов,
  • Очки рейтинга2
ВМ
13 июня 2019 г. 12:30
Ваня Мороз

C++ - Тест 001. Первая программа и типы данных

  • Результат:100баллов,
  • Очки рейтинга10
Последние комментарии
i
17 июня 2019 г. 6:10
ingenfly

Только по осям xAxis2, уAxis2 значения начинаются с 0. Почему-то xAxis2 и xAxis не синхронизированы по данным. Ну и QCustomPlot последний.
16 июня 2019 г. 20:21
Евгений Легоцкой

Добрый день. Ну точно также добавляете ту же самую информацию на ось xAxis2, только добавляете другое форматирование customPlot->xAxis2->setDateTimeFormat("hh:mm"); если я ...
EF
14 июня 2019 г. 13:56
Egor Fomin

Спасибо за ваш ответ, у меня получилось реализовать это. Тем не менее появилась другая проблема, поэтому опять надеюсь на вашу помощь. Скажем, я уже выставил точки и они соеденены. Когда я нач...
d
13 июня 2019 г. 14:47
damix

Можно классу, который описывает точку, добавить сигнал, который подавать (emit), когда точка перемещается (переопределить mouseMoveEvent или mouseReleaseEvent). Так вот эти сигналы у каждой из...
i
13 июня 2019 г. 14:09
ingenfly

Здравствайте! Подскажите, пожалуйста: customPlot->xAxis2->setTickLabels(true); //Здесь включается отображение данных на оси xAxis2. а можно как-то продублировать информацию cus...
Сейчас обсуждают на форуме
20 июня 2019 г. 9:30
IscanderChe

Вернулся к этой задачке только-только, поэтому и не ответил ничего раньше.Как переопределить mouseReleaseEvent(QMouseEvent* event) у QTableView, если QTableView задан в ui? Или задавать QTabl...
I
19 июня 2019 г. 13:41
Intruder

Всем добрый день. При разборе XML файла наткнулся на тег вот такого плана: <TagName attribute1="value1" attribute2="value2" /> При попытке проверить на наличие такого элеме...
19 июня 2019 г. 12:55
Михаиллл

Скажите пожалуйста, как его в таком случае перемещать и удалять?
18 июня 2019 г. 19:50
Дмитрий

Большое спасибо! SDK заработал.К сожалению удалось продвинутся только на один шаг. При сборке чистого проекта NDK выдаёт следующие ошибки C:\Android\ndk-bundle/toolchains/arm-linux-andr...
18 июня 2019 г. 16:59
Михаиллл

Добрый день.В этом учебнике представлен код INSTALLED_APPS = ( ... 'rest_framework', 'snippets.apps.SnippetsConfig',) На строчке 'snippets.apps.SnippetsConf...
Ищу работу?
25,000.00 руб. - 30,000.00 руб.
Разработчик Qt/C++
Barnaul, Altai Krai, Russia

Для зарегистрированных пользователей на сайте присутствует минимальное количество рекламы

EVILEG
О нас
Услуги
Присоединяйтесь к нам
© EVILEG 2015-2019
Рекомендует хостинг TIMEWEB