File indexing completed on 2024-05-12 15:54:50
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 (auto tag : qAsConst(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 QStringList groups; 0266 while (query.next()) { 0267 QString country = query.value(0).toString(); 0268 QString state = query.value(1).toString(); 0269 QString display = state + ", " + country; 0270 0271 QByteArray key; 0272 QDataStream stream(&key, QIODevice::WriteOnly); 0273 stream << country << state; 0274 0275 list << qMakePair(key, display); 0276 } 0277 return list; 0278 } else if (loca == Types::LocationGroup::City) { 0279 QSqlQuery query; 0280 query.prepare("SELECT DISTINCT country, state, city from locations"); 0281 0282 if (!query.exec()) { 0283 qDebug() << loca << query.lastError(); 0284 return list; 0285 } 0286 0287 while (query.next()) { 0288 QString country = query.value(0).toString(); 0289 QString state = query.value(1).toString(); 0290 QString city = query.value(2).toString(); 0291 0292 QString display; 0293 if (!city.isEmpty()) { 0294 display = city + ", " + state + ", " + country; 0295 } else { 0296 display = state + ", " + country; 0297 } 0298 0299 QByteArray key; 0300 QDataStream stream(&key, QIODevice::WriteOnly); 0301 stream << country << state << city; 0302 0303 list << qMakePair(key, display); 0304 } 0305 return list; 0306 } 0307 0308 return list; 0309 } 0310 0311 QStringList ImageStorage::imagesForFavorites() 0312 { 0313 QMutexLocker lock(&m_mutex); 0314 QSqlQuery query; 0315 0316 query.prepare("SELECT DISTINCT url from files where favorite = 1"); 0317 0318 if (!query.exec()) { 0319 qDebug() << "imagesForFavorites: " << query.lastError(); 0320 return QStringList(); 0321 } 0322 0323 QStringList files; 0324 while (query.next()) { 0325 files << QString("file://" + query.value(0).toString()); 0326 } 0327 0328 return files; 0329 } 0330 0331 QStringList ImageStorage::tags() 0332 { 0333 QMutexLocker lock(&m_mutex); 0334 QSqlQuery query; 0335 0336 query.prepare("SELECT DISTINCT tag from tags"); 0337 0338 if (!query.exec()) { 0339 qDebug() << "tags: " << query.lastError(); 0340 return QStringList(); 0341 } 0342 0343 QStringList tags; 0344 while (query.next()) { 0345 tags << query.value(0).toString(); 0346 } 0347 0348 return tags; 0349 } 0350 0351 QStringList ImageStorage::imagesForTag(const QString &tag) 0352 { 0353 QMutexLocker lock(&m_mutex); 0354 QSqlQuery query; 0355 0356 query.prepare("SELECT DISTINCT url from tags where tag = ?"); 0357 query.addBindValue(tag); 0358 0359 if (!query.exec()) { 0360 qDebug() << "imagesForTag: " << query.lastError(); 0361 return QStringList(); 0362 } 0363 0364 QStringList files; 0365 while (query.next()) { 0366 files << QString("file://" + query.value(0).toString()); 0367 } 0368 0369 return files; 0370 } 0371 0372 QStringList ImageStorage::imagesForLocation(const QByteArray &name, Types::LocationGroup loc) 0373 { 0374 QMutexLocker lock(&m_mutex); 0375 QSqlQuery query; 0376 if (loc == Types::LocationGroup::Country) { 0377 query.prepare("SELECT DISTINCT url from files, locations where country = ? AND files.location = locations.id"); 0378 query.addBindValue(QString::fromUtf8(name)); 0379 } else if (loc == Types::LocationGroup::State) { 0380 QDataStream st(name); 0381 0382 QString country; 0383 QString state; 0384 st >> country >> state; 0385 0386 query.prepare("SELECT DISTINCT url from files, locations where country = ? AND state = ? AND files.location = locations.id"); 0387 query.addBindValue(country); 0388 query.addBindValue(state); 0389 } else if (loc == Types::LocationGroup::City) { 0390 QDataStream st(name); 0391 0392 QString country; 0393 QString state; 0394 QString city; 0395 st >> country >> state >> city; 0396 0397 query.prepare("SELECT DISTINCT url from files, locations where country = ? AND state = ? AND files.location = locations.id"); 0398 query.addBindValue(country); 0399 query.addBindValue(state); 0400 } 0401 0402 if (!query.exec()) { 0403 qDebug() << "imagesForLocation: " << loc << query.lastError(); 0404 return QStringList(); 0405 } 0406 0407 QStringList files; 0408 while (query.next()) { 0409 files << QString("file://" + query.value(0).toString()); 0410 } 0411 return files; 0412 } 0413 0414 QString ImageStorage::imageForLocation(const QByteArray &name, Types::LocationGroup loc) 0415 { 0416 QMutexLocker lock(&m_mutex); 0417 QSqlQuery query; 0418 if (loc == Types::LocationGroup::Country) { 0419 query.prepare("SELECT DISTINCT url from files, locations where country = ? AND files.location = locations.id"); 0420 query.addBindValue(QString::fromUtf8(name)); 0421 } else if (loc == Types::LocationGroup::State) { 0422 QDataStream st(name); 0423 0424 QString country; 0425 QString state; 0426 st >> country >> state; 0427 0428 query.prepare("SELECT DISTINCT url from files, locations where country = ? AND state = ? AND files.location = locations.id"); 0429 query.addBindValue(country); 0430 query.addBindValue(state); 0431 } else if (loc == Types::LocationGroup::City) { 0432 QDataStream st(name); 0433 0434 QString country; 0435 QString state; 0436 QString city; 0437 st >> country >> state >> city; 0438 0439 query.prepare("SELECT DISTINCT url from files, locations where country = ? AND state = ? AND files.location = locations.id"); 0440 query.addBindValue(country); 0441 query.addBindValue(state); 0442 } 0443 0444 if (!query.exec()) { 0445 qDebug() << "imageForLocation: " << loc << query.lastError(); 0446 return QString(); 0447 } 0448 0449 if (query.next()) { 0450 return QString("file://" + query.value(0).toString()); 0451 } 0452 return QString(); 0453 } 0454 0455 QList<QPair<QByteArray, QString>> ImageStorage::timeTypes(Types::TimeGroup group) 0456 { 0457 QMutexLocker lock(&m_mutex); 0458 QList<QPair<QByteArray, QString>> list; 0459 0460 QSqlQuery query; 0461 if (group == Types::TimeGroup::Year) { 0462 query.prepare("SELECT DISTINCT strftime('%Y', dateTime) from files"); 0463 if (!query.exec()) { 0464 qDebug() << group << query.lastError(); 0465 return list; 0466 } 0467 0468 while (query.next()) { 0469 QString val = query.value(0).toString(); 0470 list << qMakePair(val.toUtf8(), val); 0471 } 0472 return list; 0473 } else if (group == Types::TimeGroup::Month) { 0474 query.prepare("SELECT DISTINCT strftime('%Y', dateTime), strftime('%m', dateTime) from files"); 0475 if (!query.exec()) { 0476 qDebug() << group << query.lastError(); 0477 return list; 0478 } 0479 0480 QStringList groups; 0481 while (query.next()) { 0482 QString year = query.value(0).toString(); 0483 QString month = query.value(1).toString(); 0484 0485 QString display = QLocale().monthName(month.toInt(), QLocale::LongFormat) + ", " + year; 0486 0487 QByteArray key; 0488 QDataStream stream(&key, QIODevice::WriteOnly); 0489 stream << year << month; 0490 0491 list << qMakePair(key, display); 0492 } 0493 return list; 0494 } else if (group == Types::TimeGroup::Week) { 0495 query.prepare("SELECT DISTINCT strftime('%Y', dateTime), strftime('%m', dateTime), strftime('%W', dateTime) from files"); 0496 if (!query.exec()) { 0497 qDebug() << group << query.lastError(); 0498 return list; 0499 } 0500 0501 while (query.next()) { 0502 QString year = query.value(0).toString(); 0503 QString month = query.value(1).toString(); 0504 QString week = query.value(2).toString(); 0505 0506 QString display = "Week " + week + ", " + QLocale().monthName(month.toInt(), QLocale::LongFormat) + ", " + year; 0507 0508 QByteArray key; 0509 QDataStream stream(&key, QIODevice::WriteOnly); 0510 stream << year << week; 0511 0512 list << qMakePair(key, display); 0513 } 0514 return list; 0515 } else if (group == Types::TimeGroup::Day) { 0516 query.prepare("SELECT DISTINCT date(dateTime) from files"); 0517 if (!query.exec()) { 0518 qDebug() << group << query.lastError(); 0519 return list; 0520 } 0521 0522 while (query.next()) { 0523 QDate date = query.value(0).toDate(); 0524 0525 QString display = QLocale::system().toString(date, QLocale::LongFormat); 0526 QByteArray key = date.toString(Qt::ISODate).toUtf8(); 0527 0528 list << qMakePair(key, display); 0529 } 0530 return list; 0531 } 0532 0533 Q_ASSERT(0); 0534 return list; 0535 } 0536 0537 QStringList ImageStorage::imagesForTime(const QByteArray &name, Types::TimeGroup group) 0538 { 0539 QMutexLocker lock(&m_mutex); 0540 QSqlQuery query; 0541 if (group == Types::TimeGroup::Year) { 0542 query.prepare("SELECT DISTINCT url from files where strftime('%Y', dateTime) = ?"); 0543 query.addBindValue(QString::fromUtf8(name)); 0544 } else if (group == Types::TimeGroup::Month) { 0545 QDataStream stream(name); 0546 QString year; 0547 QString month; 0548 stream >> year >> month; 0549 0550 query.prepare("SELECT DISTINCT url from files where strftime('%Y', dateTime) = ? AND strftime('%m', dateTime) = ?"); 0551 query.addBindValue(year); 0552 query.addBindValue(month); 0553 } else if (group == Types::TimeGroup::Week) { 0554 QDataStream stream(name); 0555 QString year; 0556 QString week; 0557 stream >> year >> week; 0558 0559 query.prepare("SELECT DISTINCT url from files where strftime('%Y', dateTime) = ? AND strftime('%W', dateTime) = ?"); 0560 query.addBindValue(year); 0561 query.addBindValue(week); 0562 } else if (group == Types::TimeGroup::Day) { 0563 QDate date = QDate::fromString(QString::fromUtf8(name), Qt::ISODate); 0564 0565 query.prepare("SELECT DISTINCT url from files where date(dateTime) = ?"); 0566 query.addBindValue(date); 0567 } 0568 0569 if (!query.exec()) { 0570 qDebug() << group << query.lastError(); 0571 return QStringList(); 0572 } 0573 0574 QStringList files; 0575 while (query.next()) { 0576 files << QString("file://" + query.value(0).toString()); 0577 } 0578 0579 return files; 0580 } 0581 0582 QString ImageStorage::imageForTime(const QByteArray &name, Types::TimeGroup group) 0583 { 0584 QMutexLocker lock(&m_mutex); 0585 Q_ASSERT(!name.isEmpty()); 0586 0587 QSqlQuery query; 0588 if (group == Types::TimeGroup::Year) { 0589 query.prepare("SELECT DISTINCT url from files where strftime('%Y', dateTime) = ? LIMIT 1"); 0590 query.addBindValue(QString::fromUtf8(name)); 0591 } else if (group == Types::TimeGroup::Month) { 0592 QDataStream stream(name); 0593 QString year; 0594 QString month; 0595 stream >> year >> month; 0596 0597 query.prepare("SELECT DISTINCT url from files where strftime('%Y', dateTime) = ? AND strftime('%m', dateTime) = ? LIMIT 1"); 0598 query.addBindValue(year); 0599 query.addBindValue(month); 0600 } else if (group == Types::TimeGroup::Week) { 0601 QDataStream stream(name); 0602 QString year; 0603 QString week; 0604 stream >> year >> week; 0605 0606 query.prepare("SELECT DISTINCT url from files where strftime('%Y', dateTime) = ? AND strftime('%W', dateTime) = ? LIMIT 1"); 0607 query.addBindValue(year); 0608 query.addBindValue(week); 0609 } else if (group == Types::TimeGroup::Day) { 0610 QDate date = QDate::fromString(QString::fromUtf8(name), Qt::ISODate); 0611 0612 query.prepare("SELECT DISTINCT url from files where date(dateTime) = ? LIMIT 1"); 0613 query.addBindValue(date); 0614 } 0615 0616 if (!query.exec()) { 0617 qDebug() << group << query.lastError(); 0618 return QString(); 0619 } 0620 0621 if (query.next()) { 0622 return QString("file://" + query.value(0).toString()); 0623 } 0624 0625 Q_ASSERT(0); 0626 return QString(); 0627 } 0628 0629 QDate ImageStorage::dateForKey(const QByteArray &key, Types::TimeGroup group) 0630 { 0631 if (group == Types::TimeGroup::Year) { 0632 return QDate(key.toInt(), 1, 1); 0633 } else if (group == Types::TimeGroup::Month) { 0634 QDataStream stream(key); 0635 QString year; 0636 QString month; 0637 stream >> year >> month; 0638 0639 return QDate(year.toInt(), month.toInt(), 1); 0640 } else if (group == Types::TimeGroup::Week) { 0641 QDataStream stream(key); 0642 QString year; 0643 QString week; 0644 stream >> year >> week; 0645 0646 int month = week.toInt() / 4; 0647 int day = week.toInt() % 4; 0648 return QDate(year.toInt(), month, day); 0649 } else if (group == Types::TimeGroup::Day) { 0650 return QDate::fromString(QString::fromUtf8(key), Qt::ISODate); 0651 } 0652 0653 Q_ASSERT(0); 0654 return QDate(); 0655 } 0656 0657 void ImageStorage::reset() 0658 { 0659 qDebug() << "Reseting database"; 0660 QString dir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/koko"; 0661 QDir(dir).removeRecursively(); 0662 } 0663 0664 bool ImageStorage::shouldReset() 0665 { 0666 bool shouldReset = false; 0667 { 0668 QString dir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/koko"; 0669 QDir().mkpath(dir); 0670 0671 QSqlDatabase db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), QStringLiteral("resetChecker")); 0672 db.setDatabaseName(dir + "/imageData.sqlite3"); 0673 0674 if (!db.open()) { 0675 qDebug() << "Failed to open db" << db.lastError().text(); 0676 shouldReset = true; 0677 } else if (db.tables().contains("files") == true && db.tables().contains("tags") == false) { 0678 shouldReset = true; 0679 } 0680 db.close(); 0681 } 0682 QSqlDatabase::removeDatabase(QStringLiteral("resetChecker")); 0683 return shouldReset; 0684 } 0685 0686 QStringList ImageStorage::allImages(int size, int offset) 0687 { 0688 QMutexLocker lock(&m_mutex); 0689 0690 QSqlQuery query; 0691 if (size == -1) { 0692 query.prepare("SELECT DISTINCT url from files ORDER BY dateTime DESC"); 0693 } else { 0694 query.prepare("SELECT DISTINCT url from files ORDER BY dateTime DESC LIMIT ? OFFSET ?"); 0695 query.addBindValue(size); 0696 query.addBindValue(offset); 0697 } 0698 0699 if (!query.exec()) { 0700 qDebug() << query.lastError(); 0701 return QStringList(); 0702 } 0703 0704 QStringList imageList; 0705 while (query.next()) 0706 imageList << query.value(0).toString(); 0707 0708 return imageList; 0709 }