Files
tenmon/database.cpp
T
2022-04-09 14:12:41 +02:00

208 lines
6.4 KiB
C++

#include "database.h"
#include <QStandardPaths>
#include <QDir>
#include <QSqlError>
#include <QDebug>
#include <QDateTime>
#include "loadrunable.h"
Database::Database(QObject *parent) : QObject(parent)
{
}
bool Database::init()
{
QString path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
QDir dir(path);
m_database = QSqlDatabase::addDatabase("QSQLITE");
if(!dir.mkpath("."))
return false;
if(m_database.isValid())
{
m_database.setDatabaseName(dir.absoluteFilePath("database.db"));
if(m_database.open())
{
m_database.exec("PRAGMA foreign_keys = ON");
m_database.exec("CREATE TABLE IF NOT EXISTS files (id INTEGER PRIMARY KEY AUTOINCREMENT, file VARCHAR(255) UNIQUE)");
m_database.exec("CREATE TABLE IF NOT EXISTS fits_files (id INTEGER PRIMARY KEY AUTOINCREMENT, file VARCHAR(255) UNIQUE, mtime DATETIME)");
m_database.exec("CREATE TABLE IF NOT EXISTS fits_headers (id INTEGER PRIMARY KEY AUTOINCREMENT, id_file INTEGER,"
"key VARCHAR(81), value VARCHAR(81), comment VARCHAR(81), FOREIGN KEY(id_file) REFERENCES fits_files(id) ON DELETE CASCADE)");
QSqlError error = m_database.lastError();
if(error.type() == QSqlError::NoError)
{
m_markQuery = QSqlQuery(m_database);
m_markQuery.prepare("INSERT INTO files (file) VALUES (?)");
m_unmarkQuery = QSqlQuery(m_database);
m_unmarkQuery.prepare("DELETE FROM files WHERE file = (?)");
m_isMarkedQuery = QSqlQuery(m_database);
m_isMarkedQuery.prepare("SELECT * FROM files WHERE file = (:name)");
m_insertFile = QSqlQuery(m_database);
m_insertFile.prepare("INSERT INTO fits_files (file, mtime) VALUES (?, ?)");
m_insertFitsHeader = QSqlQuery(m_database);
m_insertFitsHeader.prepare("INSERT INTO fits_headers (id_file, key, value, comment) VALUES (?, ?, ?, ?)");
m_checkFile = QSqlQuery(m_database);
m_checkFile.prepare("SELECT id,mtime FROM fits_files WHERE file=?");
m_headerKeywords = QSqlQuery(m_database);
m_headerKeywords.prepare("SELECT DISTINCT key FROM fits_headers ORDER BY key");
m_deleteFile = QSqlQuery(m_database);
m_deleteFile.prepare("DELETE FROM fits_files WHERE id=?");
return true;
}
qDebug() << error.text();
}
}
return false;
}
bool Database::mark(const QString &filename)
{
m_markQuery.bindValue(0, filename);
m_markQuery.exec();
return checkError();
}
bool Database::unmark(const QString &filename)
{
m_unmarkQuery.bindValue(0, filename);
m_unmarkQuery.exec();
return checkError();
}
bool Database::isMarked(const QString &filename)
{
m_isMarkedQuery.bindValue(":name", filename);
m_isMarkedQuery.exec();
checkError();
return m_isMarkedQuery.next();
}
QStringList Database::getMarkedFiles()
{
QSqlQuery markedFiles("SELECT * from files", m_database);
QStringList files;
while(markedFiles.next())
{
files << markedFiles.value("file").toString();
}
qDebug() << files.size();
return files;
}
bool Database::checkError()
{
QSqlError error = m_database.lastError();
if(error.type() == QSqlError::NoError)
return true;
else
{
qDebug() << error.text();
return false;
}
}
static QStringList nameFilters = {"*.fit", "*.fits"};
static int countFiles(const QDir &dir, int count = 0)
{
count += dir.entryList(nameFilters, QDir::Files).size();
QStringList dirs = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
for(const QString &d : dirs)
count += countFiles(dir.filePath(d));
return count;
}
void Database::indexDir(const QDir &dir, QProgressDialog *progress)
{
m_progress = 0;
int count = countFiles(dir);
progress->setMaximum(count);
m_database.transaction();
if(indexDir2(dir, progress))
m_database.commit();
else
m_database.rollback();
}
QStringList Database::getFitsKeywords()
{
m_headerKeywords.exec();
QStringList keywords;
while(m_headerKeywords.next())
{
keywords << m_headerKeywords.value(0).toString();
}
return keywords;
}
bool Database::indexDir2(const QDir &dir, QProgressDialog *progress)
{
QFileInfoList files = dir.entryInfoList(nameFilters, QDir::Files);
QStringList dirs = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
for(const QString &d : dirs)
{
if(!indexDir2(dir.filePath(d), progress))
return false;
}
ImageInfoData info;
for(const QFileInfo &file : files)
{
progress->setValue(m_progress++);
if(progress->wasCanceled())return false;
QString filePath = file.absoluteFilePath();
QString mtime = file.fileTime(QFileDevice::FileModificationTime).toString(Qt::ISODate);
m_checkFile.bindValue(0, filePath);
m_checkFile.exec();
if(m_checkFile.next())
{
if(m_checkFile.value(1).toString() == file.fileTime(QFileDevice::FileModificationTime).toString(Qt::ISODate))
continue;
else
{
m_deleteFile.bindValue(0, m_checkFile.value(0).toLongLong());
m_deleteFile.exec();
}
}
readFITSHeader(filePath, info);
m_insertFile.bindValue(0, filePath);
m_insertFile.bindValue(1, mtime);
if(!m_insertFile.exec())
{
qDebug() << m_insertFile.lastError();
return false;
}
qlonglong last_id = m_insertFile.lastInsertId().toLongLong();
QVariantList file_id, keys, values, comments;
for(auto &record : info.fitsHeader)
{
file_id << last_id;
keys << QString(record.key);
values << record.value.toString();
comments << QString(record.comment);
}
m_insertFitsHeader.bindValue(0, file_id);
m_insertFitsHeader.bindValue(1, keys);
m_insertFitsHeader.bindValue(2, values);
m_insertFitsHeader.bindValue(3, comments);
if(!m_insertFitsHeader.execBatch())
{
qDebug() << m_insertFitsHeader.lastError();
return false;
}
qDebug() << filePath << last_id;
info.fitsHeader.clear();
}
return true;
}