Add FITS files indexing support to database
This commit is contained in:
+100
-1
@@ -3,6 +3,8 @@
|
||||
#include <QDir>
|
||||
#include <QSqlError>
|
||||
#include <QDebug>
|
||||
#include <QDateTime>
|
||||
#include "loadrunable.h"
|
||||
|
||||
Database::Database(QObject *parent) : QObject(parent)
|
||||
{
|
||||
@@ -23,7 +25,11 @@ bool Database::init()
|
||||
m_database.setDatabaseName(dir.absoluteFilePath("database.db"));
|
||||
if(m_database.open())
|
||||
{
|
||||
m_database.exec("CREATE TABLE IF NOT EXISTS files (id INTEGER PRIMARY KEY AUTOINCREMENT, file VARCHAR(255) UNIQUE);");
|
||||
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)
|
||||
@@ -34,6 +40,17 @@ bool Database::init()
|
||||
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");
|
||||
m_deleteFile = QSqlQuery(m_database);
|
||||
m_deleteFile.prepare("DELETE FROM fits_files WHERE id=?");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -90,3 +107,85 @@ bool Database::checkError()
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Database::indexDir(const QDir &dir)
|
||||
{
|
||||
//m_database.exec("DROP TABLE fits_files");
|
||||
m_database.transaction();
|
||||
if(indexDir2(dir))
|
||||
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)
|
||||
{
|
||||
static QStringList nameFilters = {"*.fit", "*.fits"};
|
||||
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)))
|
||||
return false;
|
||||
}
|
||||
ImageInfoData info;
|
||||
for(const QFileInfo &file : files)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
+11
@@ -4,6 +4,7 @@
|
||||
#include <QObject>
|
||||
#include <QSqlDatabase>
|
||||
#include <QSqlQuery>
|
||||
#include <QDir>
|
||||
|
||||
class Database : public QObject
|
||||
{
|
||||
@@ -12,6 +13,12 @@ class Database : public QObject
|
||||
QSqlQuery m_markQuery;
|
||||
QSqlQuery m_unmarkQuery;
|
||||
QSqlQuery m_isMarkedQuery;
|
||||
|
||||
QSqlQuery m_insertFile;
|
||||
QSqlQuery m_insertFitsHeader;
|
||||
QSqlQuery m_checkFile;
|
||||
QSqlQuery m_headerKeywords;
|
||||
QSqlQuery m_deleteFile;
|
||||
public:
|
||||
explicit Database(QObject *parent = 0);
|
||||
bool init();
|
||||
@@ -19,7 +26,11 @@ public:
|
||||
bool unmark(const QString &filename);
|
||||
bool isMarked(const QString &filename);
|
||||
QStringList getMarkedFiles();
|
||||
|
||||
void indexDir(const QDir &dir);
|
||||
QStringList getFitsKeywords();
|
||||
protected:
|
||||
bool indexDir2(const QDir &dir);
|
||||
bool checkError();
|
||||
};
|
||||
|
||||
|
||||
+18
-1
@@ -127,7 +127,7 @@ bool loadRAW(QString path, ImageInfoData &info, RawImage **image)
|
||||
return true;
|
||||
}
|
||||
|
||||
void loadFITSHeader(fitsfile *file, ImageInfoData &info)
|
||||
int loadFITSHeader(fitsfile *file, ImageInfoData &info)
|
||||
{
|
||||
int nexist;
|
||||
int status = 0;
|
||||
@@ -159,8 +159,13 @@ void loadFITSHeader(fitsfile *file, ImageInfoData &info)
|
||||
status = 0;
|
||||
info.fitsHeader.append({key, var, comm});
|
||||
}
|
||||
else
|
||||
{
|
||||
return status;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
bool loadFITS(QString path, ImageInfoData &info, RawImage **image)
|
||||
{
|
||||
@@ -350,3 +355,15 @@ void LoadRunable::run()
|
||||
|
||||
QMetaObject::invokeMethod(m_receiver, "imageLoaded", Qt::QueuedConnection, Q_ARG(void*, rawImage), Q_ARG(ImageInfoData, info));
|
||||
}
|
||||
|
||||
bool readFITSHeader(const QString &path, ImageInfoData &info)
|
||||
{
|
||||
fitsfile *fr;
|
||||
int status = 0;
|
||||
fits_open_diskfile(&fr, path.toLocal8Bit().data(), READONLY, &status);
|
||||
|
||||
status = loadFITSHeader(fr, info);
|
||||
|
||||
fits_close_file(fr, &status);
|
||||
return status == 0;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <QString>
|
||||
#include "imageinfo.h"
|
||||
|
||||
bool readFITSHeader(const QString &path, ImageInfoData &info);
|
||||
|
||||
class Image;
|
||||
|
||||
class LoadRunable : public QRunnable
|
||||
|
||||
@@ -158,6 +158,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
delete m_database;
|
||||
}
|
||||
|
||||
void MainWindow::keyPressEvent(QKeyEvent *event)
|
||||
|
||||
Reference in New Issue
Block a user