File indexing completed on 2025-04-20 04:02:15
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 }