#include "database.h" #include #include #include #include #include #include "loadrunable.h" Database::Database(QObject *parent) : QObject(parent) { } bool Database::init() { QString path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); QDir dir(path); QSqlDatabase 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)"); m_database.exec("CREATE INDEX IF NOT EXISTS key_value ON fits_headers(key, value)"); 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(m_markQuery); } bool Database::unmark(const QString &filename) { m_unmarkQuery.bindValue(0, filename); m_unmarkQuery.exec(); return checkError(m_unmarkQuery); } bool Database::isMarked(const QString &filename) { m_isMarkedQuery.bindValue(":name", filename); m_isMarkedQuery.exec(); checkError(m_isMarkedQuery); return m_isMarkedQuery.next(); } QStringList Database::getMarkedFiles() { QSqlQuery markedFiles("SELECT * from files"); QStringList files; while(markedFiles.next()) { files << markedFiles.value("file").toString(); } qDebug() << files.size(); return files; } bool Database::checkError(QSqlQuery &query) { QSqlError error = query.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); QSqlDatabase database = QSqlDatabase::database(); database.transaction(); if(indexDir2(dir, progress)) database.commit(); else 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).toUTC().toString(Qt::ISODate); m_checkFile.bindValue(0, filePath); m_checkFile.exec(); if(m_checkFile.next()) { if(m_checkFile.value(1).toString() == mtime) 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; }