File indexing completed on 2024-05-12 04:21:07

0001 // SPDX-FileCopyrightText: 2014 Vishesh Handa <vhanda@kde.org>
0002 // SPDX-FileCopyrightText: 2017 Atul Sharma <atulsharma406@gmail.com>
0003 // SPDX-License-Identifier: LGPL-2.1-or-later
0004 
0005 #include "imagestorage.h"
0006 
0007 #include <QDataStream>
0008 #include <QDebug>
0009 #include <QGeoAddress>
0010 #include <QGeoCoordinate>
0011 
0012 #include <QDir>
0013 #include <QStandardPaths>
0014 #include <QUrl>
0015 
0016 #include <QSqlDatabase>
0017 #include <QSqlError>
0018 #include <QSqlQuery>
0019 
0020 ImageStorage::ImageStorage(QObject *parent)
0021     : QObject(parent)
0022 {
0023     QString dir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/koko";
0024     QDir().mkpath(dir);
0025 
0026     QSqlDatabase db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"));
0027     db.setDatabaseName(dir + "/imageData.sqlite3");
0028 
0029     if (!db.open()) {
0030         qDebug() << "Failed to open db" << db.lastError().text();
0031         return;
0032     }
0033 
0034     if (db.tables().contains("files")) {
0035         QSqlQuery query(db);
0036         query.prepare("PRAGMA table_info(files)");
0037         bool favorites_present = false;
0038         if (!query.exec()) {
0039             qDebug() << "Failed to read db" << query.lastError();
0040             return;
0041         }
0042         while (query.next()) {
0043             if (query.value(1).toString() == "favorite") {
0044                 favorites_present = true;
0045             }
0046         }
0047         if (!favorites_present) {
0048             // migrate to new table
0049             query.exec("ALTER TABLE files ADD COLUMN favorite INTEGER");
0050         }
0051 
0052         db.transaction();
0053 
0054         return;
0055     }
0056 
0057     QSqlQuery query(db);
0058     query.exec(
0059         "CREATE TABLE locations (id INTEGER PRIMARY KEY, country TEXT, state TEXT, city TEXT"
0060         "                        , UNIQUE(country, state, city) ON CONFLICT REPLACE"
0061         ")");
0062     query.exec("CREATE TABLE tags (url TEXT NOT NULL, tag TEXT)");
0063     query.exec(
0064         "CREATE TABLE files (url TEXT NOT NULL UNIQUE PRIMARY KEY,"
0065         "                    favorite INTEGER,"
0066         "                    location INTEGER,"
0067         "                    dateTime STRING NOT NULL,"
0068         "                    FOREIGN KEY(location) REFERENCES locations(id)"
0069         "                    FOREIGN KEY(url) REFERENCES tags(url)"
0070         "                    )");
0071 
0072     db.transaction();
0073 }
0074 
0075 ImageStorage::~ImageStorage()
0076 {
0077     QString name;
0078     {
0079         QSqlDatabase db = QSqlDatabase::database();
0080         db.commit();
0081         name = db.connectionName();
0082     }
0083     QSqlDatabase::removeDatabase(name);
0084 }
0085 
0086 ImageStorage *ImageStorage::instance()
0087 {
0088     static ImageStorage storage;
0089     return &storage;
0090 }
0091 
0092 void ImageStorage::addImage(const ImageInfo &ii)
0093 {
0094     if (imageExists(ii.path)) {
0095         removeImage(ii.path);
0096     }
0097     QMutexLocker lock(&m_mutex);
0098     QGeoAddress addr = ii.location.address();
0099 
0100     if (!addr.country().isEmpty()) {
0101         int locId = -1;
0102 
0103         if (!addr.city().isEmpty()) {
0104             QSqlQuery query;
0105             query.prepare("SELECT id FROM LOCATIONS WHERE country = ? AND state = ? AND city = ?");
0106             query.addBindValue(addr.country());
0107             query.addBindValue(addr.state());
0108             query.addBindValue(addr.city());
0109             if (!query.exec()) {
0110                 qDebug() << "LOC SELECT" << query.lastError();
0111             }
0112 
0113             if (query.next()) {
0114                 locId = query.value(0).toInt();
0115             }
0116         } else {
0117             QSqlQuery query;
0118             query.prepare("SELECT id FROM LOCATIONS WHERE country = ? AND state = ?");
0119             query.addBindValue(addr.country());
0120             query.addBindValue(addr.state());
0121             if (!query.exec()) {
0122                 qDebug() << "LOC SELECT" << query.lastError();
0123             }
0124 
0125             if (query.next()) {
0126                 locId = query.value(0).toInt();
0127             }
0128         }
0129 
0130         if (locId == -1) {
0131             QSqlQuery query;
0132             query.prepare("INSERT INTO LOCATIONS(country, state, city) VALUES (?, ?, ?)");
0133             query.addBindValue(addr.country());
0134             query.addBindValue(addr.state());
0135             query.addBindValue(addr.city());
0136             if (!query.exec()) {
0137                 qDebug() << "LOC INSERT" << query.lastError();
0138             }
0139 
0140             locId = query.lastInsertId().toInt();
0141         }
0142 
0143         QSqlQuery query;
0144         query.prepare("INSERT INTO FILES(url, favorite, location, dateTime) VALUES(?, ?, ?, ?)");
0145         query.addBindValue(ii.path);
0146         query.addBindValue(int(ii.favorite));
0147         query.addBindValue(locId);
0148         query.addBindValue(ii.dateTime.toString(Qt::ISODate));
0149         if (!query.exec()) {
0150             qDebug() << "FILE LOC INSERT" << query.lastError();
0151         }
0152     } else {
0153         QSqlQuery query;
0154         query.prepare("INSERT INTO FILES(url, favorite, dateTime) VALUES(?, ?, ?)");
0155         query.addBindValue(ii.path);
0156         query.addBindValue(int(ii.favorite));
0157         query.addBindValue(ii.dateTime.toString(Qt::ISODate));
0158         if (!query.exec()) {
0159             qDebug() << "FILE INSERT" << query.lastError();
0160         }
0161     }
0162 
0163     for (const auto &tag : std::as_const(ii.tags)) {
0164         QSqlQuery query;
0165         query.prepare("SELECT url FROM TAGS WHERE url = ? AND tag = ?");
0166         query.addBindValue(ii.path);
0167         query.addBindValue(tag);
0168 
0169         if (!query.exec()) {
0170             qDebug() << "tag select" << query.lastError();
0171         }
0172 
0173         if (!query.next()) {
0174             QSqlQuery query;
0175             query.prepare("INSERT INTO TAGS(url, tag) VALUES (?, ?)");
0176             query.addBindValue(ii.path);
0177             query.addBindValue(tag);
0178             if (!query.exec()) {
0179                 qDebug() << "tag insert" << query.lastError();
0180             }
0181         }
0182     }
0183 }
0184 
0185 bool ImageStorage::imageExists(const QString &filePath)
0186 {
0187     QMutexLocker lock(&m_mutex);
0188 
0189     QSqlQuery query;
0190     query.prepare("SELECT EXISTS(SELECT 1 FROM files WHERE url = ?)");
0191     query.addBindValue(filePath);
0192 
0193     if (!query.exec()) {
0194         qDebug() << query.lastError();
0195         return false;
0196     }
0197 
0198     return query.next();
0199 }
0200 
0201 void ImageStorage::removeImage(const QString &filePath)
0202 {
0203     QMutexLocker lock(&m_mutex);
0204 
0205     QSqlQuery query;
0206     query.prepare("DELETE FROM FILES WHERE URL = ?");
0207     query.addBindValue(filePath);
0208     if (!query.exec()) {
0209         qDebug() << "FILE del" << query.lastError();
0210     }
0211 
0212     QSqlQuery query2;
0213     query2.prepare("DELETE FROM LOCATIONS WHERE id NOT IN (SELECT DISTINCT location FROM files WHERE location IS NOT NULL)");
0214     if (!query2.exec()) {
0215         qDebug() << "Loc del" << query2.lastError();
0216     }
0217 
0218     QSqlQuery query3;
0219     query3.prepare("DELETE FROM TAGS WHERE url NOT IN (SELECT DISTINCT url FROM files)");
0220     if (!query3.exec()) {
0221         qDebug() << "tag delete" << query3.lastError();
0222     }
0223 }
0224 
0225 void ImageStorage::commit()
0226 {
0227     {
0228         QMutexLocker lock(&m_mutex);
0229         QSqlDatabase db = QSqlDatabase::database();
0230         db.commit();
0231         db.transaction();
0232     }
0233 
0234     emit storageModified();
0235 }
0236 
0237 QList<QPair<QByteArray, QString>> ImageStorage::locations(Types::LocationGroup loca)
0238 {
0239     QMutexLocker lock(&m_mutex);
0240     QList<QPair<QByteArray, QString>> list;
0241 
0242     if (loca == Types::LocationGroup::Country) {
0243         QSqlQuery query;
0244         query.prepare("SELECT DISTINCT country from locations");
0245 
0246         if (!query.exec()) {
0247             qDebug() << loca << query.lastError();
0248             return list;
0249         }
0250 
0251         while (query.next()) {
0252             QString val = query.value(0).toString();
0253             list << qMakePair(val.toUtf8(), val);
0254         }
0255         return list;
0256     } else if (loca == Types::LocationGroup::State) {
0257         QSqlQuery query;
0258         query.prepare("SELECT DISTINCT country, state from locations");
0259 
0260         if (!query.exec()) {
0261             qDebug() << loca << query.lastError();
0262             return list;
0263         }
0264 
0265         while (query.next()) {
0266             QString country = query.value(0).toString();
0267             QString state = query.value(1).toString();
0268             QString display = state + ", " + country;
0269 
0270             QByteArray key;
0271             QDataStream stream(&key, QIODevice::WriteOnly);
0272             stream << country << state;
0273 
0274             list << qMakePair(key, display);
0275         }
0276         return list;
0277     } else if (loca == Types::LocationGroup::City) {
0278         QSqlQuery query;
0279         query.prepare("SELECT DISTINCT country, state, city from locations");
0280 
0281         if (!query.exec()) {
0282             qDebug() << loca << query.lastError();
0283             return list;
0284         }
0285 
0286         while (query.next()) {
0287             QString country = query.value(0).toString();
0288             QString state = query.value(1).toString();
0289             QString city = query.value(2).toString();
0290 
0291             QString display;
0292             if (!city.isEmpty()) {
0293                 display = city + ", " + state + ", " + country;
0294             } else {
0295                 display = state + ", " + country;
0296             }
0297 
0298             QByteArray key;
0299             QDataStream stream(&key, QIODevice::WriteOnly);
0300             stream << country << state << city;
0301 
0302             list << qMakePair(key, display);
0303         }
0304         return list;
0305     }
0306 
0307     return list;
0308 }
0309 
0310 QStringList ImageStorage::imagesForFavorites()
0311 {
0312     QMutexLocker lock(&m_mutex);
0313     QSqlQuery query;
0314 
0315     query.prepare("SELECT DISTINCT url from files where favorite = 1");
0316 
0317     if (!query.exec()) {
0318         qDebug() << "imagesForFavorites: " << query.lastError();
0319         return QStringList();
0320     }
0321 
0322     QStringList files;
0323     while (query.next()) {
0324         files << QString("file://" + query.value(0).toString());
0325     }
0326 
0327     return files;
0328 }
0329 
0330 QStringList ImageStorage::tags()
0331 {
0332     QMutexLocker lock(&m_mutex);
0333     QSqlQuery query;
0334 
0335     query.prepare("SELECT DISTINCT tag from tags");
0336 
0337     if (!query.exec()) {
0338         qDebug() << "tags: " << query.lastError();
0339         return QStringList();
0340     }
0341 
0342     QStringList tags;
0343     while (query.next()) {
0344         tags << query.value(0).toString();
0345     }
0346 
0347     return tags;
0348 }
0349 
0350 QStringList ImageStorage::imagesForTag(const QString &tag)
0351 {
0352     QMutexLocker lock(&m_mutex);
0353     QSqlQuery query;
0354 
0355     query.prepare("SELECT DISTINCT url from tags where tag = ?");
0356     query.addBindValue(tag);
0357 
0358     if (!query.exec()) {
0359         qDebug() << "imagesForTag: " << query.lastError();
0360         return QStringList();
0361     }
0362 
0363     QStringList files;
0364     while (query.next()) {
0365         files << QString("file://" + query.value(0).toString());
0366     }
0367 
0368     return files;
0369 }
0370 
0371 QStringList ImageStorage::imagesForLocation(const QByteArray &name, Types::LocationGroup loc)
0372 {
0373     QMutexLocker lock(&m_mutex);
0374     QSqlQuery query;
0375     if (loc == Types::LocationGroup::Country) {
0376         query.prepare("SELECT DISTINCT url from files, locations where country = ? AND files.location = locations.id");
0377         query.addBindValue(QString::fromUtf8(name));
0378     } else if (loc == Types::LocationGroup::State) {
0379         QDataStream st(name);
0380 
0381         QString country;
0382         QString state;
0383         st >> country >> state;
0384 
0385         query.prepare("SELECT DISTINCT url from files, locations where country = ? AND state = ? AND files.location = locations.id");
0386         query.addBindValue(country);
0387         query.addBindValue(state);
0388     } else if (loc == Types::LocationGroup::City) {
0389         QDataStream st(name);
0390 
0391         QString country;
0392         QString state;
0393         QString city;
0394         st >> country >> state >> city;
0395 
0396         query.prepare("SELECT DISTINCT url from files, locations where country = ? AND state = ? AND files.location = locations.id");
0397         query.addBindValue(country);
0398         query.addBindValue(state);
0399     }
0400 
0401     if (!query.exec()) {
0402         qDebug() << "imagesForLocation: " << loc << query.lastError();
0403         return QStringList();
0404     }
0405 
0406     QStringList files;
0407     while (query.next()) {
0408         files << QString("file://" + query.value(0).toString());
0409     }
0410     return files;
0411 }
0412 
0413 QString ImageStorage::imageForLocation(const QByteArray &name, Types::LocationGroup loc)
0414 {
0415     QMutexLocker lock(&m_mutex);
0416     QSqlQuery query;
0417     if (loc == Types::LocationGroup::Country) {
0418         query.prepare("SELECT DISTINCT url from files, locations where country = ? AND files.location = locations.id");
0419         query.addBindValue(QString::fromUtf8(name));
0420     } else if (loc == Types::LocationGroup::State) {
0421         QDataStream st(name);
0422 
0423         QString country;
0424         QString state;
0425         st >> country >> state;
0426 
0427         query.prepare("SELECT DISTINCT url from files, locations where country = ? AND state = ? AND files.location = locations.id");
0428         query.addBindValue(country);
0429         query.addBindValue(state);
0430     } else if (loc == Types::LocationGroup::City) {
0431         QDataStream st(name);
0432 
0433         QString country;
0434         QString state;
0435         QString city;
0436         st >> country >> state >> city;
0437 
0438         query.prepare("SELECT DISTINCT url from files, locations where country = ? AND state = ? AND files.location = locations.id");
0439         query.addBindValue(country);
0440         query.addBindValue(state);
0441     }
0442 
0443     if (!query.exec()) {
0444         qDebug() << "imageForLocation: " << loc << query.lastError();
0445         return QString();
0446     }
0447 
0448     if (query.next()) {
0449         return QString("file://" + query.value(0).toString());
0450     }
0451     return QString();
0452 }
0453 
0454 QList<QPair<QByteArray, QString>> ImageStorage::timeTypes(Types::TimeGroup group)
0455 {
0456     QMutexLocker lock(&m_mutex);
0457     QList<QPair<QByteArray, QString>> list;
0458 
0459     QSqlQuery query;
0460     if (group == Types::TimeGroup::Year) {
0461         query.prepare("SELECT DISTINCT strftime('%Y', dateTime) from files");
0462         if (!query.exec()) {
0463             qDebug() << group << query.lastError();
0464             return list;
0465         }
0466 
0467         while (query.next()) {
0468             QString val = query.value(0).toString();
0469             list << qMakePair(val.toUtf8(), val);
0470         }
0471         return list;
0472     } else if (group == Types::TimeGroup::Month) {
0473         query.prepare("SELECT DISTINCT strftime('%Y', dateTime), strftime('%m', dateTime) from files");
0474         if (!query.exec()) {
0475             qDebug() << group << query.lastError();
0476             return list;
0477         }
0478 
0479         while (query.next()) {
0480             QString year = query.value(0).toString();
0481             QString month = query.value(1).toString();
0482 
0483             QString display = QLocale().monthName(month.toInt(), QLocale::LongFormat) + ", " + year;
0484 
0485             QByteArray key;
0486             QDataStream stream(&key, QIODevice::WriteOnly);
0487             stream << year << month;
0488 
0489             list << qMakePair(key, display);
0490         }
0491         return list;
0492     } else if (group == Types::TimeGroup::Week) {
0493         query.prepare("SELECT DISTINCT strftime('%Y', dateTime), strftime('%m', dateTime), strftime('%W', dateTime) from files");
0494         if (!query.exec()) {
0495             qDebug() << group << query.lastError();
0496             return list;
0497         }
0498 
0499         while (query.next()) {
0500             QString year = query.value(0).toString();
0501             QString month = query.value(1).toString();
0502             QString week = query.value(2).toString();
0503 
0504             QString display = "Week " + week + ", " + QLocale().monthName(month.toInt(), QLocale::LongFormat) + ", " + year;
0505 
0506             QByteArray key;
0507             QDataStream stream(&key, QIODevice::WriteOnly);
0508             stream << year << week;
0509 
0510             list << qMakePair(key, display);
0511         }
0512         return list;
0513     } else if (group == Types::TimeGroup::Day) {
0514         query.prepare("SELECT DISTINCT date(dateTime) from files");
0515         if (!query.exec()) {
0516             qDebug() << group << query.lastError();
0517             return list;
0518         }
0519 
0520         while (query.next()) {
0521             QDate date = query.value(0).toDate();
0522 
0523             QString display = QLocale::system().toString(date, QLocale::LongFormat);
0524             QByteArray key = date.toString(Qt::ISODate).toUtf8();
0525 
0526             list << qMakePair(key, display);
0527         }
0528         return list;
0529     }
0530 
0531     Q_ASSERT(0);
0532     return list;
0533 }
0534 
0535 QStringList ImageStorage::imagesForTime(const QByteArray &name, Types::TimeGroup group)
0536 {
0537     QMutexLocker lock(&m_mutex);
0538     QSqlQuery query;
0539     if (group == Types::TimeGroup::Year) {
0540         query.prepare("SELECT DISTINCT url from files where strftime('%Y', dateTime) = ?");
0541         query.addBindValue(QString::fromUtf8(name));
0542     } else if (group == Types::TimeGroup::Month) {
0543         QDataStream stream(name);
0544         QString year;
0545         QString month;
0546         stream >> year >> month;
0547 
0548         query.prepare("SELECT DISTINCT url from files where strftime('%Y', dateTime) = ? AND strftime('%m', dateTime) = ?");
0549         query.addBindValue(year);
0550         query.addBindValue(month);
0551     } else if (group == Types::TimeGroup::Week) {
0552         QDataStream stream(name);
0553         QString year;
0554         QString week;
0555         stream >> year >> week;
0556 
0557         query.prepare("SELECT DISTINCT url from files where strftime('%Y', dateTime) = ? AND strftime('%W', dateTime) = ?");
0558         query.addBindValue(year);
0559         query.addBindValue(week);
0560     } else if (group == Types::TimeGroup::Day) {
0561         QDate date = QDate::fromString(QString::fromUtf8(name), Qt::ISODate);
0562 
0563         query.prepare("SELECT DISTINCT url from files where date(dateTime) = ?");
0564         query.addBindValue(date);
0565     }
0566 
0567     if (!query.exec()) {
0568         qDebug() << group << query.lastError();
0569         return QStringList();
0570     }
0571 
0572     QStringList files;
0573     while (query.next()) {
0574         files << QString("file://" + query.value(0).toString());
0575     }
0576 
0577     return files;
0578 }
0579 
0580 QString ImageStorage::imageForTime(const QByteArray &name, Types::TimeGroup group)
0581 {
0582     QMutexLocker lock(&m_mutex);
0583     Q_ASSERT(!name.isEmpty());
0584 
0585     QSqlQuery query;
0586     if (group == Types::TimeGroup::Year) {
0587         query.prepare("SELECT DISTINCT url from files where strftime('%Y', dateTime) = ? LIMIT 1");
0588         query.addBindValue(QString::fromUtf8(name));
0589     } else if (group == Types::TimeGroup::Month) {
0590         QDataStream stream(name);
0591         QString year;
0592         QString month;
0593         stream >> year >> month;
0594 
0595         query.prepare("SELECT DISTINCT url from files where strftime('%Y', dateTime) = ? AND strftime('%m', dateTime) = ? LIMIT 1");
0596         query.addBindValue(year);
0597         query.addBindValue(month);
0598     } else if (group == Types::TimeGroup::Week) {
0599         QDataStream stream(name);
0600         QString year;
0601         QString week;
0602         stream >> year >> week;
0603 
0604         query.prepare("SELECT DISTINCT url from files where strftime('%Y', dateTime) = ? AND strftime('%W', dateTime) = ? LIMIT 1");
0605         query.addBindValue(year);
0606         query.addBindValue(week);
0607     } else if (group == Types::TimeGroup::Day) {
0608         QDate date = QDate::fromString(QString::fromUtf8(name), Qt::ISODate);
0609 
0610         query.prepare("SELECT DISTINCT url from files where date(dateTime) = ? LIMIT 1");
0611         query.addBindValue(date);
0612     }
0613 
0614     if (!query.exec()) {
0615         qDebug() << group << query.lastError();
0616         return QString();
0617     }
0618 
0619     if (query.next()) {
0620         return QString("file://" + query.value(0).toString());
0621     }
0622 
0623     Q_ASSERT(0);
0624     return QString();
0625 }
0626 
0627 QDate ImageStorage::dateForKey(const QByteArray &key, Types::TimeGroup group)
0628 {
0629     if (group == Types::TimeGroup::Year) {
0630         return QDate(key.toInt(), 1, 1);
0631     } else if (group == Types::TimeGroup::Month) {
0632         QDataStream stream(key);
0633         QString year;
0634         QString month;
0635         stream >> year >> month;
0636 
0637         return QDate(year.toInt(), month.toInt(), 1);
0638     } else if (group == Types::TimeGroup::Week) {
0639         QDataStream stream(key);
0640         QString year;
0641         QString week;
0642         stream >> year >> week;
0643 
0644         int month = week.toInt() / 4;
0645         int day = week.toInt() % 4;
0646         return QDate(year.toInt(), month, day);
0647     } else if (group == Types::TimeGroup::Day) {
0648         return QDate::fromString(QString::fromUtf8(key), Qt::ISODate);
0649     }
0650 
0651     Q_ASSERT(0);
0652     return QDate();
0653 }
0654 
0655 void ImageStorage::reset()
0656 {
0657     qDebug() << "Resetting database";
0658     QString dir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/koko";
0659     QDir(dir).removeRecursively();
0660 }
0661 
0662 bool ImageStorage::shouldReset()
0663 {
0664     bool shouldReset = false;
0665     {
0666         QString dir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/koko";
0667         QDir().mkpath(dir);
0668 
0669         QSqlDatabase db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), QStringLiteral("resetChecker"));
0670         db.setDatabaseName(dir + "/imageData.sqlite3");
0671 
0672         if (!db.open()) {
0673             qDebug() << "Failed to open db" << db.lastError().text();
0674             shouldReset = true;
0675         } else if (db.tables().contains("files") == true && db.tables().contains("tags") == false) {
0676             shouldReset = true;
0677         }
0678         db.close();
0679     }
0680     QSqlDatabase::removeDatabase(QStringLiteral("resetChecker"));
0681     return shouldReset;
0682 }
0683 
0684 QStringList ImageStorage::allImages(int size, int offset)
0685 {
0686     QMutexLocker lock(&m_mutex);
0687 
0688     QSqlQuery query;
0689     if (size == -1) {
0690         query.prepare("SELECT DISTINCT url from files ORDER BY dateTime DESC");
0691     } else {
0692         query.prepare("SELECT DISTINCT url from files ORDER BY dateTime DESC LIMIT ? OFFSET ?");
0693         query.addBindValue(size);
0694         query.addBindValue(offset);
0695     }
0696 
0697     if (!query.exec()) {
0698         qDebug() << query.lastError();
0699         return QStringList();
0700     }
0701 
0702     QStringList imageList;
0703     while (query.next())
0704         imageList << query.value(0).toString();
0705 
0706     return imageList;
0707 }