MythTV  master
imagemanager.cpp
Go to the documentation of this file.
1 #include "imagemanager.h"
2 
3 #include <QImageReader>
4 #include <QRunnable>
5 #include <utility>
6 
8 #include "libmythbase/mythdate.h"
10 
11 #include "dbaccess.h" // for FileAssociations
12 
13 #define LOC QString("ImageManager: ")
14 #define DBLOC QString("ImageDb(%1): ").arg(m_table)
15 
16 // Must be empty as it's prepended to path
17 static constexpr const char* STORAGE_GROUP_MOUNT { "" };
18 
19 static constexpr const char* DB_TABLE { "gallery_files" };
20 
21 // NOLINTBEGIN(cppcoreguidelines-macro-usage)
22 #define RESULT_ERR(ERR, MESG) \
23 { LOG(VB_GENERAL, LOG_ERR, LOC + (MESG)); \
24  return QStringList("ERROR") << (ERR); }
25 
26 #define RESULT_OK(MESG) \
27 { LOG(VB_FILE, LOG_DEBUG, LOC + (MESG)); \
28  return QStringList("OK"); }
29 // NOLINTEND(cppcoreguidelines-macro-usage)
30 
31 static constexpr const char* IMPORTDIR { "Import" };
32 
33 
35 class Device
36 {
37 public:
38  Device(QString name, QString mount,
39  MythMediaDevice *media = nullptr, QTemporaryDir *import = nullptr)
40  : m_name(std::move(name)), m_mount(std::move(mount)),
41  m_media(media), m_dir(import)
42  {
43  // Path relative to TEMP storage group
44  m_thumbs = QString("%1/%2").arg(THUMBNAIL_SUBDIR, m_name);
45  }
46 
47 
50  {
51  Close();
52 
53  // Remove imported images
54  delete m_dir;
55 
56  // Clean up non-SG thumbnails
58  RemoveThumbs();
59  }
60 
61 
63  void Close(bool eject = false)
64  {
65  // Imports remain present; others do not
66  m_present = isImport();
67 
68  // Release device
69  if (m_media)
70  {
71  if (eject)
72  {
73  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Ejecting '%1' at '%2'")
74  .arg(m_name, m_mount));
76  }
77  else
78  {
79  LOG(VB_MEDIA, LOG_DEBUG, LOC + QString("Unlocked '%1'").arg(m_name));
80  }
81 
83  m_media = nullptr;
84  }
85  }
86 
87 
92  static void RemoveDirContents(const QString& path)
93  {
94  QDir(path).removeRecursively();
95  }
96 
97 
99  void RemoveThumbs(void) const
100  {
101  // Remove thumbnails
102  QString dirFmt = QString("%1/") % TEMP_SUBDIR % "/%2";
103  QString dir = dirFmt.arg(GetConfDir(), m_thumbs);
104  LOG(VB_FILE, LOG_INFO, LOC + QString("Removing thumbnails in %1").arg(dir));
105  RemoveDirContents(dir);
106  QDir::root().rmpath(dir);
107  }
108 
109 
110  bool isImport() const { return m_dir; }
111  bool isPresent() const { return m_present; }
112  void setPresent(MythMediaDevice *media) { m_present = true; m_media = media; }
113 
115  bool m_present { true };
116  QString m_name;
117  QString m_mount;
118  QString m_thumbs;
119  MythMediaDevice *m_media { nullptr };
120  QTemporaryDir *m_dir { nullptr };
121 };
122 
123 
124 static Device kNullDevice = Device("Unknown Device", "<Invalid Path>");
125 
126 
128 {
129  qDeleteAll(m_devices);
130 }
131 
132 
134 QString DeviceManager::DeviceMount(int devId) const
135 {
136  return m_devices.value(devId, &kNullDevice)->m_mount;
137 }
138 
139 
141 QString DeviceManager::DeviceName(int devId) const
142 {
143  return m_devices.value(devId, &kNullDevice)->m_name;
144 }
145 
146 
147 QString DeviceManager::ThumbDir(int fs) const
148 {
149  return m_devices.value(fs, &kNullDevice)->m_thumbs;
150 }
151 
152 
162 int DeviceManager::OpenDevice(const QString &name, const QString &mount,
163  MythMediaDevice *media, QTemporaryDir *dir)
164 {
165  // Handle devices reappearing at same mountpoint.
166  // If a USB is unplugged whilst in use (without unmounting) we get no event
167  // but we do when it's re-inserted
168  QString state("Known");
169  int id = LocateMount(mount);
170 
171  if (id == DEVICE_INVALID)
172  {
173  state = "New";
174  id = m_devices.isEmpty() ? 0 : m_devices.lastKey() + 1;
175  m_devices.insert(id, new Device(name, mount, media, dir));
176  }
177  else
178  {
179  Device *dev = m_devices.value(id);
180  if (dev)
181  dev->setPresent(media);
182  }
183 
184  LOG(VB_GENERAL, LOG_INFO, LOC +
185  QString("%1 device %2 mounted at '%3' [Id %4]")
186  .arg(state, name, mount).arg(id));
187 
188  return id;
189 }
190 
191 
198 QStringList DeviceManager::CloseDevices(int devId, const QString &action)
199 {
200  QStringList clear;
201 
202  if (action == "DEVICE CLOSE ALL")
203  {
204  // Close all devices but retain their thumbnails
205  for (auto *dev : std::as_const(m_devices))
206  if (dev)
207  dev->Close();
208  }
209  else if (action == "DEVICE CLEAR ALL")
210  {
211  // Remove all thumbnails but retain devices
212  for (const auto *dev : std::as_const(m_devices)) {
213  if (dev)
214  {
215  clear << dev->m_mount;
216  dev->RemoveThumbs();
217  }
218  }
219  }
220  else
221  {
222  // Remove single device & its thumbnails, optionally ejecting it
223  Device *dev = m_devices.take(devId);
224  if (dev)
225  {
226  if (action == "DEVICE EJECT")
227  dev->Close(true);
228  clear << dev->m_mount;
229  delete dev;
230  }
231  }
232  return clear;
233 }
234 
235 
241 int DeviceManager::LocateMount(const QString &mount) const
242 {
243  DeviceMap::const_iterator it = m_devices.constBegin();
244  while (it != m_devices.constEnd())
245  {
246  if (it.value()->m_mount == mount)
247  return it.key();
248  ++it;
249  }
250  return DEVICE_INVALID;
251 }
252 
253 
256 {
258  for (auto it = m_devices.constKeyValueBegin();
259  it != m_devices.constKeyValueEnd(); ++it)
260  {
261  if (it->second)
262  paths.insert(it->first, it->second->m_mount);
263  }
264  return paths;
265 }
266 
267 
270 {
271  QList<int> absent;
272  for (auto it = m_devices.constKeyValueBegin();
273  it != m_devices.constKeyValueEnd(); it++)
274  {
275  Device *dev = it->second;
276  if (dev && !dev->isPresent())
277  absent << it->first;
278  }
279  return absent;
280 }
281 
282 
287  m_imageFileExt(SupportedImages()),
288  m_videoFileExt(SupportedVideos())
289 {
290  // Generate glob list from supported extensions
291  QStringList glob;
292  QStringList allExt = m_imageFileExt + m_videoFileExt;
293  for (const auto& ext : std::as_const(allExt))
294  glob << "*." + ext;
295 
296  // Apply filters to only detect image files
297  m_dirFilter.setNameFilters(glob);
298  m_dirFilter.setFilter(QDir::AllDirs | QDir::Files | QDir::Readable |
299  QDir::NoDotAndDotDot | QDir::NoSymLinks);
300 
301  // Sync files before dirs to improve thumb generation response
302  // Order by time (oldest first) - this determines the order thumbs appear
303  m_dirFilter.setSorting(QDir::DirsLast | QDir::Time | QDir::Reversed);
304 }
305 
311 {
312  // Determine supported picture formats from Qt
313  QStringList formats;
314  QList<QByteArray> supported = QImageReader::supportedImageFormats();
315  for (const auto& ext : std::as_const(supported))
316  formats << QString(ext);
317  return formats;
318 }
319 
320 
326 {
327  // Determine supported video formats from MythVideo
328  QStringList formats;
331  for (const auto & fa : faList)
332  {
333  if (!fa.use_default && fa.playcommand == "Internal")
334  formats << QString(fa.extension);
335  }
336  return formats;
337 }
338 
339 
348 ImageItem *ImageAdapterLocal::CreateItem(const QFileInfo &fi, int parentId,
349  int devId, const QString & /*base*/) const
350 {
351  auto *im = new ImageItem();
352 
353  im->m_parentId = parentId;
354  im->m_device = devId;
355  im->m_filePath = fi.absoluteFilePath();
356 
357  if (parentId == GALLERY_DB_ID)
358  {
359  // Import devices show time of import, other devices show 'last scan time'
360  auto secs = im->m_filePath.contains(IMPORTDIR)
361  ? fi.lastModified().toSecsSinceEpoch()
362  : QDateTime::currentSecsSinceEpoch();
363  im->m_date = std::chrono::seconds(secs);
364  im->m_modTime = im->m_date;
365  im->m_type = kDevice;
366  return im;
367  }
368 
369  im->m_modTime = std::chrono::seconds(fi.lastModified().toSecsSinceEpoch());
370 
371  if (fi.isDir())
372  {
373  im->m_type = kDirectory;
374  return im;
375  }
376 
377  im->m_extension = fi.suffix().toLower();
378  im->m_type = GetImageType(im->m_extension);
379 
380  if (im->m_type == kUnknown)
381  {
382  delete im;
383  return nullptr;
384  }
385 
386  im->m_thumbPath = GetAbsThumbPath(ThumbDir(im->m_device), ThumbPath(*im));
387  im->m_size = fi.size();
388 
389  return im;
390 }
391 
392 
398 void ImageAdapterLocal::Notify(const QString &mesg,
399  const QStringList &extra)
400 {
401  QString host(gCoreContext->GetHostName());
402  gCoreContext->SendEvent(MythEvent(QString("%1 %2").arg(mesg, host), extra));
403 }
404 
405 
414 ImageItem *ImageAdapterSg::CreateItem(const QFileInfo &fi, int parentId,
415  int /*devId*/, const QString &base) const
416 {
417  auto *im = new ImageItem();
418 
419  im->m_device = 0;
420  im->m_parentId = parentId;
421 
422  if (parentId == GALLERY_DB_ID)
423  {
424  // All SG dirs map to a single Db dir
425  im->m_filePath = "";
426  im->m_type = kDevice;
427  im->m_date = std::chrono::seconds(QDateTime::currentSecsSinceEpoch());
428  im->m_modTime = im->m_date;
429  return im;
430  }
431 
432  // Strip SG path & leading / to leave a relative path
433  im->m_filePath = fi.absoluteFilePath().mid(base.size() + 1);
434  im->m_modTime = std::chrono::seconds(fi.lastModified().toSecsSinceEpoch());
435 
436  if (fi.isDir())
437  {
438  im->m_type = kDirectory;
439  return im;
440  }
441 
442  im->m_extension = fi.suffix().toLower();
443  im->m_type = GetImageType(im->m_extension);
444 
445  if (im->m_type == kUnknown)
446  {
447  delete im;
448  return nullptr;
449  }
450 
451  im->m_thumbPath = GetAbsThumbPath(ThumbDir(im->m_device), ThumbPath(*im));
452  im->m_size = fi.size();
453 
454  return im;
455 }
456 
457 
463 void ImageAdapterSg::Notify(const QString &mesg,
464  const QStringList &extra)
465 {
466  gCoreContext->SendEvent(MythEvent(mesg, extra));
467 }
468 
469 
475 {
476  StringMap map;
477  int i = 0;
478  QStringList paths = m_sg.GetDirList();
479  for (const auto& path : std::as_const(paths))
480  map.insert(i++, path);
481  return map;
482 }
483 
484 
492 {
493  if (im->IsDevice())
494  return m_sg.FindNextDirMostFree();
495  return im->m_filePath.startsWith("/") ? im->m_filePath
496  : m_sg.FindFile(im->m_filePath);
497 }
498 
499 
500 // Database fields used by several image queries
501 static constexpr const char* kDBColumns {
502 "file_id, filename, name, dir_id, type, modtime, size, "
503 "extension, date, hidden, orientation, angle, path, zoom"
504 // Id, filepath, basename, parentId, type, modtime, size,
505 // extension, image date, hidden, orientation, cover id, comment, device id
506 };
507 
513 template <class FS>
515 {
516  auto *im = new ImageItem(FS::ImageId(query.value(0).toInt()));
517 
518  // Ordered as per kDBColumns
519  im->m_filePath = query.value(1).toString();
520  im->m_baseName = query.value(2).toString();
521  im->m_parentId = FS::ImageId(query.value(3).toInt());
522  im->m_type = query.value(4).toInt();
523  im->m_modTime = std::chrono::seconds(query.value(5).toInt());
524  im->m_size = query.value(6).toInt();
525  im->m_extension = query.value(7).toString();
526  im->m_date = std::chrono::seconds(query.value(8).toUInt());
527  im->m_isHidden = query.value(9).toBool();
528  im->m_orientation = query.value(10).toInt();
529  im->m_userThumbnail = FS::ImageId(query.value(11).toInt());
530  im->m_comment = query.value(12).toString();
531  im->m_device = query.value(13).toInt();
532  im->m_url = FS::MakeFileUrl(im->m_filePath);
533 
534  if (im->IsFile())
535  {
536  // Only pics/vids have thumbs
537  QString thumbPath(FS::ThumbPath(*im));
538  QString devPath(FS::ThumbDir(im->m_device));
539  QString url(FS::MakeThumbUrl(devPath, thumbPath));
540 
541  im->m_thumbPath = FS::GetAbsThumbPath(devPath, thumbPath);
542  im->m_thumbNails.append(qMakePair(im->m_id, url));
543  }
544  return im;
545 }
546 
547 
556 template <class FS>
557 int ImageDb<FS>::GetImages(const QString &ids, ImageList &files, ImageList &dirs,
558  const QString &refine) const
559 {
560  if (ids.isEmpty())
561  return 0;
562 
563  QString select = QString("file_id IN (%1) %2").arg(FS::DbIds(ids), refine);
564  return ReadImages(dirs, files, select);
565 }
566 
567 
576 template <class FS>
577 int ImageDb<FS>::GetChildren(const QString &ids, ImageList &files, ImageList &dirs,
578  const QString &refine) const
579 {
580  QString select = QString("dir_id IN (%1) %2").arg(FS::DbIds(ids), refine);
581  return ReadImages(dirs, files, select);
582 }
583 
584 
594 template <class FS>
596  ImageList &files, ImageList &dirs,
597  const QString &refine) const
598 {
599  MSqlQuery query(MSqlQuery::InitCon());
600  query.prepare(QString("SELECT %1 FROM %2 "
601  "WHERE (dir_id = :ID1 OR file_id = :ID2) "
602  "%3;").arg(kDBColumns, m_table, refine));
603 
604  // Qt < 5.4 won't bind multiple occurrences
605  int dbId = FS::DbId(id);
606  query.bindValue(":ID1", dbId);
607  query.bindValue(":ID2", dbId);
608 
609  if (!query.exec())
610  {
611  MythDB::DBError(DBLOC, query);
612  return -1;
613  }
614  while (query.next())
615  {
616  ImagePtr im(CreateImage(query));
617 
618  if (im->IsFile())
619  files.append(im);
620  else if (im->m_id == id)
621  parent = im;
622  else
623  dirs.append(im);
624  }
625  return query.size();
626 }
627 
628 
636 template <class FS>
637 bool ImageDb<FS>::GetDescendants(const QString &ids,
638  ImageList &files, ImageList &dirs) const
639 {
640  if (ids.isEmpty())
641  return false;
642 
643  if (ReadImages(dirs, files, QString("file_id IN (%1)").arg(FS::DbIds(ids))) < 0)
644  return false;
645 
646  MSqlQuery query(MSqlQuery::InitCon());
647  QString sql =
648  QString("SELECT %1"
649  ", LENGTH(filename) - LENGTH(REPLACE(filename, '/', ''))"
650  " AS depth "
651  "FROM %2 WHERE filename LIKE :PREFIX "
652  "ORDER BY depth;").arg(kDBColumns,m_table);
653 
654  for (const auto& im1 : std::as_const(dirs))
655  {
656  query.prepare(sql);
657  query.bindValue(":PREFIX", im1->m_filePath + "/%");
658 
659  if (!query.exec())
660  {
661  MythDB::DBError(DBLOC, query);
662  return false;
663  }
664 
665  while (query.next())
666  {
667  ImagePtr im2(CreateImage(query));
668  if (im2->IsDirectory())
669  dirs.append(im2);
670  else
671  files.append(im2);
672  }
673  }
674  return true;
675 }
676 
677 
685 template <class FS>
686 bool ImageDb<FS>::GetImageTree(int id, ImageList &files, const QString &refine) const
687 {
688  // Load starting children
689  ImageList dirs;
690  if (GetChildren(QString::number(id), files, dirs, refine) < 0)
691  return false;
692 
693  for (const auto& im : std::as_const(dirs))
694  if (!GetImageTree(im->m_id, files, refine))
695  return false;
696  return true;
697 }
698 
699 
705 template <class FS>
707 {
708  MSqlQuery query(MSqlQuery::InitCon());
709  query.prepare(QString("SELECT %1 FROM %2").arg(kDBColumns, m_table));
710 
711  if (!query.exec())
712  {
713  MythDB::DBError(DBLOC, query);
714  return false;
715  }
716 
717  while (query.next())
718  {
719  ImagePtr im(CreateImage(query));
720  if (im->IsDirectory())
721  dirs.insert(im->m_filePath, im);
722  else
723  files.insert(im->m_filePath, im);
724  }
725  return true;
726 }
727 
728 
736 template <class FS>
737 void ImageDb<FS>::ClearDb(int devId, const QString &action)
738 {
739  if (action == "DEVICE CLOSE ALL")
740  // Retain Db images when closing UI
741  return;
742 
743  MSqlQuery query(MSqlQuery::InitCon());
744 
745  if (action == "DEVICE CLEAR ALL")
746  {
747  // Clear images from all devices. Reset auto-increment
748  query.prepare(QString("TRUNCATE TABLE %1;").arg(m_table));
749 
750  if (!query.exec())
751  MythDB::DBError(DBLOC, query);
752  }
753  else // Actions DEVICE REMOVE & DEVICE EJECT
754  {
755  // Delete all images of the device
756  query.prepare(QString("DELETE IGNORE FROM %1 WHERE zoom = :FS;").arg(m_table));
757  query.bindValue(":FS", devId);
758 
759  if (!query.exec())
760  MythDB::DBError(DBLOC, query);
761  }
762 }
763 
764 
772 template <class FS>
773 int ImageDb<FS>::InsertDbImage(ImageItemK &im, bool checkForDuplicate) const
774 {
775  MSqlQuery query(MSqlQuery::InitCon());
776 
777  if (checkForDuplicate)
778  {
779  query.prepare(QString("SELECT file_id FROM %1 WHERE filename = :NAME;")
780  .arg(m_table));
781 
782  query.bindValue(":NAME", im.m_filePath);
783 
784  if (!query.exec())
785  {
786  MythDB::DBError(DBLOC, query);
787  return -1;
788  }
789 
790  if (query.size() > 0)
791  {
792  LOG(VB_FILE, LOG_DEBUG, QString("Image: %1 already exists in Db")
793  .arg(im.m_filePath));
794  return query.value(0).toInt();
795  }
796  }
797 
798  query.prepare(QString("INSERT INTO %1 (%2) VALUES (0, "
799  ":FILEPATH, :NAME, :PARENT, :TYPE, :MODTIME, "
800  ":SIZE, :EXTENSION, :DATE, :HIDDEN, :ORIENT, "
801  ":COVER, :COMMENT, :FS);").arg(m_table, kDBColumns));
802 
803  query.bindValueNoNull(":FILEPATH", im.m_filePath);
804  query.bindValueNoNull(":NAME", FS::BaseNameOf(im.m_filePath));
805  query.bindValue(":FS", im.m_device);
806  query.bindValue(":PARENT", FS::DbId(im.m_parentId));
807  query.bindValue(":TYPE", im.m_type);
808  query.bindValue(":MODTIME", static_cast<qint64>(im.m_modTime.count()));
809  query.bindValue(":SIZE", im.m_size);
810  query.bindValueNoNull(":EXTENSION", im.m_extension);
811  query.bindValue(":DATE", static_cast<qint64>(im.m_date.count()));
812  query.bindValue(":ORIENT", im.m_orientation);
813  query.bindValueNoNull(":COMMENT", im.m_comment);
814  query.bindValue(":HIDDEN", im.m_isHidden);
815  query.bindValue(":COVER", FS::DbId(im.m_userThumbnail));
816 
817  if (query.exec())
818  return FS::ImageId(query.lastInsertId().toInt());
819 
820  MythDB::DBError(DBLOC, query);
821  return -1;
822 }
823 
824 
830 template <class FS>
832 {
833  MSqlQuery query(MSqlQuery::InitCon());
834  query.prepare(QString
835  ("UPDATE %1 SET "
836  "filename = :FILEPATH, name = :NAME, "
837  "dir_id = :PARENT, type = :TYPE, "
838  "modtime = :MODTIME, size = :SIZE, "
839  "extension = :EXTENSION, date = :DATE, zoom = :FS, "
840  "hidden = :HIDDEN, orientation = :ORIENT, "
841  "angle = :COVER, path = :COMMENT "
842  "WHERE file_id = :ID;").arg(m_table));
843 
844  query.bindValue(":ID", FS::DbId(im.m_id));
845  query.bindValue(":FILEPATH", im.m_filePath);
846  query.bindValue(":NAME", FS::BaseNameOf(im.m_filePath));
847  query.bindValue(":PARENT", FS::DbId(im.m_parentId));
848  query.bindValue(":TYPE", im.m_type);
849  query.bindValue(":MODTIME", static_cast<qint64>(im.m_modTime.count()));
850  query.bindValue(":SIZE", im.m_size);
851  query.bindValue(":EXTENSION", im.m_extension);
852  query.bindValue(":DATE", static_cast<qint64>(im.m_date.count()));
853  query.bindValue(":FS", im.m_device);
854  query.bindValue(":HIDDEN", im.m_isHidden);
855  query.bindValue(":ORIENT", im.m_orientation);
856  query.bindValue(":COVER", FS::DbId(im.m_userThumbnail));
857  query.bindValueNoNull(":COMMENT", im.m_comment);
858 
859  if (query.exec())
860  return true;
861 
862  MythDB::DBError(DBLOC, query);
863  return false;
864 }
865 
866 
873 template <class FS>
874 QStringList ImageDb<FS>::RemoveFromDB(const ImageList &imList) const
875 {
876  QStringList ids;
877  if (!imList.isEmpty())
878  {
879  for (const auto& im : std::as_const(imList))
880  ids << QString::number(FS::DbId(im->m_id));
881 
882  QString idents = ids.join(",");
883  MSqlQuery query(MSqlQuery::InitCon());
884  query.prepare(QString("DELETE IGNORE FROM %1 WHERE file_id IN (%2);")
885  .arg(m_table, idents));
886 
887  if (!query.exec())
888  {
889  MythDB::DBError(DBLOC, query);
890  return {};
891  }
892  }
893  return ids;
894 }
895 
896 
903 template <class FS>
904 bool ImageDb<FS>::SetHidden(bool hide, const QString &ids) const
905 {
906  if (ids.isEmpty())
907  return false;
908 
909  MSqlQuery query(MSqlQuery::InitCon());
910 
911  query.prepare(QString("UPDATE %1 SET "
912  "hidden = :HIDDEN "
913  "WHERE file_id IN (%2);").arg(m_table, FS::DbIds(ids)));
914  query.bindValue(":HIDDEN", hide ? 1 : 0);
915 
916  if (query.exec())
917  return true;
918 
919  MythDB::DBError(DBLOC, query);
920  return false;
921 }
922 
923 
929 template <class FS>
930 bool ImageDb<FS>::SetCover(int dir, int id) const
931 {
932  MSqlQuery query(MSqlQuery::InitCon());
933 
934  query.prepare(QString("UPDATE %1 SET "
935  "angle = :COVER "
936  "WHERE file_id = :DIR").arg(m_table));
937  query.bindValue(":COVER", FS::DbId(id));
938  query.bindValue(":DIR", FS::DbId(dir));
939  \
940  if (query.exec())
941  return true;
942 
943  MythDB::DBError(DBLOC, query);
944  return false;
945 }
946 
947 
953 template <class FS>
954 bool ImageDb<FS>::SetOrientation(int id, int orientation) const
955 {
956  MSqlQuery query(MSqlQuery::InitCon());
957 
958  query.prepare(QString("UPDATE %1 SET ").arg(m_table) +
959  "orientation = :ORIENTATION "
960  "WHERE file_id = :ID");
961  query.bindValue(":ORIENTATION", orientation);
962  query.bindValue(":ID", FS::DbId(id));
963  \
964  if (query.exec())
965  return true;
966 
967  MythDB::DBError(DBLOC, query);
968  return false;
969 }
970 
971 
979 template <class FS>
981  const QString &selector) const
982 {
983  MSqlQuery query(MSqlQuery::InitCon());
984  query.prepare(QString("SELECT %1 FROM %2 WHERE %3")
985  .arg(kDBColumns, m_table, selector));
986  if (!query.exec())
987  {
988  MythDB::DBError(DBLOC, query);
989  return -1;
990  }
991 
992  while (query.next())
993  {
994  ImagePtr im(CreateImage(query));
995 
996  if (im->IsFile())
997  files.append(im);
998  else
999  dirs.append(im);
1000  }
1001  return query.size();
1002 }
1003 
1004 
1014 template <class FS>
1015 void ImageDb<FS>::GetDescendantCount(int id, bool all, int &dirs,
1016  int &pics, int &videos, int &sizeKb) const
1017 {
1018  QString whereClause;
1019  if (!all)
1020  {
1021  whereClause = "WHERE filename LIKE "
1022  "( SELECT CONCAT(filename, '/%') "
1023  " FROM %2 WHERE file_id = :ID);";
1024  }
1025 
1026  MSqlQuery query(MSqlQuery::InitCon());
1027  query.prepare(QString("SELECT SUM(type <= :FLDR) AS Fldr, "
1028  " SUM(type = :PIC) AS Pics, "
1029  " SUM(type = :VID) AS Vids, "
1030  " SUM(size / 1024) "
1031  "FROM %2 %1;").arg(whereClause, m_table));
1032 
1033  query.bindValue(":FLDR", kDirectory);
1034  query.bindValue(":PIC", kImageFile);
1035  query.bindValue(":VID", kVideoFile);
1036  if (!all)
1037  query.bindValue(":ID", FS::DbId(id));
1038 
1039  if (!query.exec())
1040  {
1041  MythDB::DBError(DBLOC, query);
1042  }
1043  else if (query.next())
1044  {
1045  dirs += query.value(0).toInt();
1046  pics += query.value(1).toInt();
1047  videos += query.value(2).toInt();
1048  sizeKb += query.value(3).toInt();
1049  }
1050 }
1051 
1052 
1057 {
1058  // Be has a single SG device
1060 }
1061 
1062 
1067  : ImageDb(QString("`%1_%2`").arg(DB_TABLE, gCoreContext->GetHostName()))
1068 {
1069  // Remove any table leftover from a previous FE crash
1070  DropTable();
1071 }
1072 
1073 
1078 {
1079  MSqlQuery query(MSqlQuery::InitCon());
1080  query.prepare(QString("DROP TABLE IF EXISTS %1;").arg(m_table));
1081  if (query.exec())
1082  m_dbExists = false;
1083  else
1084  MythDB::DBError(DBLOC, query);
1085 }
1086 
1087 
1092 {
1093  if (m_dbExists)
1094  return true;
1095 
1096  MSqlQuery query(MSqlQuery::InitCon());
1097 
1098  // Create temporary table
1099  query.prepare(QString("CREATE TABLE %1 LIKE %2;").arg(m_table, DB_TABLE));
1100  if (query.exec())
1101  {
1102  // Store it in memory only
1103  query.prepare(QString("ALTER TABLE %1 ENGINE = MEMORY;").arg(m_table));
1104  if (query.exec())
1105  {
1106  m_dbExists = true;
1107  LOG(VB_FILE, LOG_DEBUG, QString("Created Db table %1").arg(m_table));
1108  return true;
1109  }
1110  }
1111  MythDB::DBError(DBLOC, query);
1112 
1113  // Clean up after failure
1114  query.prepare(QString("DROP TABLE IF EXISTS %1;").arg(m_table));
1115  query.exec();
1116  return false;
1117 }
1118 
1119 
1123 class ReadMetaThread : public QRunnable
1124 {
1125 public:
1126  ReadMetaThread(ImagePtrK im, QString path)
1127  : m_im(std::move(im)), m_path(std::move(path)) {}
1128 
1129  void run() override // QRunnable
1130  {
1131  QStringList tags;
1132  QString orientation;
1133  QString size;
1134 
1135  // Read metadata for files only
1136  if (m_im->IsFile())
1137  {
1138  ImageMetaData *metadata = (m_im->m_type == kVideoFile)
1141  tags = metadata->GetAllTags();
1142  orientation = Orientation(m_im->m_orientation).Description();
1143  size = ImageAdapterBase::FormatSize(m_im->m_size / 1024);
1144  delete metadata;
1145  }
1146 
1147  // Add identifier at front
1148  tags.prepend(QString::number(m_im->m_id));
1149 
1150  // Include file info
1151  tags << ImageMetaData::ToString(EXIF_MYTH_HOST, "Host",
1153  tags << ImageMetaData::ToString(EXIF_MYTH_PATH, "Path",
1155  tags << ImageMetaData::ToString(EXIF_MYTH_NAME, "Name",
1157  tags << ImageMetaData::ToString(EXIF_MYTH_SIZE, "Size", size);
1158  tags << ImageMetaData::ToString(EXIF_MYTH_ORIENT, "Orientation",
1159  orientation);
1160 
1161  MythEvent me("IMAGE_METADATA", tags);
1162  gCoreContext->SendEvent(me);
1163  }
1164 
1165 private:
1167  QString m_path;
1168 };
1169 
1170 
1179 template <class DBFS>
1180 QStringList ImageHandler<DBFS>::HandleGetMetadata(const QString &id) const
1181 {
1182  // Find image in DB
1183  ImageList files;
1184  ImageList dirs;
1185  if (DBFS::GetImages(id, files, dirs) != 1)
1186  RESULT_ERR("Image not found", QString("Unknown image %1").arg(id))
1187 
1188  ImagePtr im = files.isEmpty() ? dirs[0] : files[0];
1189 
1190  QString absPath = DBFS::GetAbsFilePath(im);
1191  if (absPath.isEmpty())
1192  RESULT_ERR("Image not found",
1193  QString("File %1 not found").arg(im->m_filePath))
1194 
1195  auto *worker = new ReadMetaThread(im, absPath);
1196 
1197  MThreadPool::globalInstance()->start(worker, "ImageMetaData");
1198 
1199  RESULT_OK(QString("Fetching metadata for %1").arg(id))
1200 }
1201 
1202 
1210 template <class DBFS>
1211 QStringList ImageHandler<DBFS>::HandleRename(const QString &id,
1212  const QString &newBase) const
1213 {
1214  // Sanity check new name
1215  if (newBase.isEmpty() || newBase.contains("/") || newBase.contains("\\"))
1216  RESULT_ERR("Invalid name", QString("Invalid name %1").arg(newBase))
1217 
1218  // Find image in DB
1219  ImageList files;
1220  ImageList dirs;
1221  if (DBFS::GetImages(id, files, dirs) != 1)
1222  RESULT_ERR("Image not found", QString("Image %1 not in Db").arg(id))
1223 
1224  ImagePtr im = files.isEmpty() ? dirs[0] : files[0];
1225 
1226  // Find file
1227  QString oldPath = DBFS::GetAbsFilePath(im);
1228  if (oldPath.isEmpty())
1229  RESULT_ERR("Image not found",
1230  QString("File %1 not found").arg(im->m_filePath))
1231 
1232  // Generate new filename
1233  QFileInfo oldFi = QFileInfo(oldPath);
1234  QString newName = im->IsDirectory()
1235  ? newBase : QString("%1.%2").arg(newBase, oldFi.suffix());
1236 
1237  im->m_filePath = DBFS::ConstructPath(DBFS::PathOf(im->m_filePath), newName);
1238 
1239  // Ensure no SG duplicate files are created. (Creating clone dirs is ok)
1240  if (im->IsFile())
1241  {
1242  QString existPath = DBFS::GetAbsFilePath(im);
1243  if (!existPath.isEmpty())
1244  RESULT_ERR("Filename already used",
1245  QString("Renaming %1 to %2 will create a duplicate of %3")
1246  .arg(oldPath, im->m_filePath, existPath))
1247  }
1248 
1249  // Rename file or directory
1250  QString newPath = oldFi.dir().absoluteFilePath(newName);
1251  if (!QFile::rename(oldPath, newPath))
1252  RESULT_ERR("Rename failed",
1253  QString("Rename of %1 -> %2 failed").arg(oldPath, newPath))
1254 
1255  if (im->IsDirectory())
1256  {
1257  // Dir name change affects path of all sub-dirs & files and their thumbs
1258  HandleScanRequest("START");
1259  }
1260  else // file
1261  {
1262  // Update db
1263  DBFS::UpdateDbImage(*im);
1264 
1265  // Image is modified, not deleted
1266  QStringList mesg("");
1267  mesg << QString::number(im->m_id);
1268 
1269  // Rename thumbnail.
1270  m_thumbGen->MoveThumbnail(im);
1271 
1272  // Notify clients of changed image
1273  DBFS::Notify("IMAGE_DB_CHANGED", mesg);
1274  }
1275  RESULT_OK(QString("Renamed %1 -> %2").arg(oldPath, newPath))
1276 }
1277 
1278 
1286 template <class DBFS>
1287 QStringList ImageHandler<DBFS>::HandleDelete(const QString &ids) const
1288 {
1289  // Get subtree of all files
1290  ImageList files;
1291  ImageList dirs;
1292  // Dirs will be in depth-first order, (subdirs after parent)
1293  DBFS::GetDescendants(ids, files, dirs);
1294 
1295  // Remove files from filesystem first
1296  RemoveFiles(files);
1297  // ... then dirs, which should now be empty
1298  RemoveFiles(dirs);
1299 
1300  // Fail if nothing deleted
1301  if (files.isEmpty() && dirs.isEmpty())
1302  RESULT_ERR("Delete failed", QString("Delete of %1 failed").arg(ids))
1303 
1304  // Update Db
1305  DBFS::RemoveFromDB(files + dirs);
1306 
1307  // Clean up thumbnails
1308  QStringList mesg(m_thumbGen->DeleteThumbs(files));
1309 
1310  // Notify clients of deleted ids
1311  DBFS::Notify("IMAGE_DB_CHANGED", mesg);
1312 
1313  return QStringList("OK");
1314 }
1315 
1316 
1329 template <class DBFS>
1330 QStringList ImageHandler<DBFS>::HandleDbCreate(QStringList defs) const
1331 {
1332  if (defs.isEmpty())
1333  RESULT_ERR("Copy Failed", "Empty defs")
1334 
1335  // First item is the field seperator
1336  const QString separator = defs.takeFirst();
1337 
1338  // Convert cover ids to their new equivalent. Map<source id, new id>
1339  // Dirs follow their children so new cover ids will be defined before they
1340  // are used
1341  QHash<QString, int> idMap;
1342 
1343  // Create skeleton Db images using copied settings.
1344  // Scanner will update other attributes
1345  ImageItem im;
1346  for (const auto& def : std::as_const(defs))
1347  {
1348  QStringList aDef = def.split(separator);
1349 
1350  // Expects id, type, path, hidden, orientation, cover
1351  if (aDef.size() != 6)
1352  {
1353  // Coding error
1354  LOG(VB_GENERAL, LOG_ERR,
1355  LOC + QString("Bad definition: (%1)").arg(def));
1356  continue;
1357  }
1358 
1359  LOG(VB_FILE, LOG_DEBUG, LOC + QString("Creating %1").arg(aDef.join(",")));
1360 
1361  im.m_type = aDef[1].toInt();
1362  im.m_filePath = aDef[2];
1363  im.m_isHidden = (aDef[3].toInt() != 0);
1364  im.m_orientation = aDef[4].toInt();
1365  im.m_userThumbnail = idMap.value(aDef[5]);
1366 
1367  // Don't insert duplicate filepaths
1368  int newId = DBFS::InsertDbImage(im, true);
1369 
1370  // Record old->new id map in case it's being used as a cover
1371  idMap.insert(aDef[0], newId);
1372  }
1373  HandleScanRequest("START");
1374 
1375  RESULT_OK("Created Db images")
1376 }
1377 
1378 
1388 template <class DBFS>
1389 QStringList ImageHandler<DBFS>::HandleDbMove(const QString &ids,
1390  const QString &srcPath,
1391  QString destPath) const
1392 {
1393  // Sanity check new path
1394  if (destPath.contains(".."))
1395  RESULT_ERR("Invalid path", QString("Invalid path %1").arg(destPath))
1396 
1397  // Get subtrees of renamed files
1398  ImageList images;
1399  ImageList dirs;
1400  ImageList files;
1401  bool ok = DBFS::GetDescendants(ids, files, dirs);
1402  images << dirs << files;
1403 
1404  if (!ok || images.isEmpty())
1405  RESULT_ERR("Image not found", QString("Images %1 not in Db").arg(ids))
1406 
1407  if (!destPath.isEmpty() && !destPath.endsWith(QChar('/')))
1408  destPath.append("/");
1409 
1410  // Update path of images only. Scanner will repair parentId
1411  for (const auto& im : std::as_const(images))
1412  {
1413  QString old = im->m_filePath;
1414 
1415  if (srcPath.isEmpty())
1416  {
1417  // Image in SG root
1418  im->m_filePath.prepend(destPath);
1419  }
1420  else if (im->m_filePath.startsWith(srcPath))
1421  {
1422  // All other images
1423  im->m_filePath.replace(srcPath, destPath);
1424  }
1425  else
1426  {
1427  // Coding error
1428  LOG(VB_GENERAL, LOG_ERR,
1429  LOC + QString("Bad image: (%1 -> %2)").arg(srcPath, destPath));
1430  continue;
1431  }
1432 
1433  LOG(VB_FILE, LOG_DEBUG,
1434  LOC + QString("Db Renaming %1 -> %2").arg(old, im->m_filePath));
1435 
1436  DBFS::UpdateDbImage(*im);
1437 
1438  // Rename thumbnail
1439  if (im->IsFile())
1440  m_thumbGen->MoveThumbnail(im);
1441  }
1442  HandleScanRequest("START");
1443 
1444  RESULT_OK(QString("Moved %1 from %2 -> %3").arg(ids, srcPath, destPath))
1445 }
1446 
1447 
1455 template <class DBFS>
1456 QStringList ImageHandler<DBFS>::HandleHide(bool hide, const QString &ids) const
1457 {
1458  if (!DBFS::SetHidden(hide, ids))
1459  RESULT_ERR("Hide failed", QString("Db hide failed for %1").arg(ids))
1460 
1461  // Send changed ids only (none deleted)
1462  QStringList mesg = QStringList("") << ids;
1463  DBFS::Notify("IMAGE_DB_CHANGED", mesg);
1464 
1465  RESULT_OK(QString("Images %1 now %2hidden").arg(ids, hide ? "" : "un"))
1466 }
1467 
1468 
1477 template <class DBFS>
1478 QStringList ImageHandler<DBFS>::HandleTransform(int transform,
1479  const QString &ids) const
1480 {
1481  if (transform < kResetToExif || transform > kFlipVertical)
1482  RESULT_ERR("Transform failed", QString("Bad transform %1").arg(transform))
1483 
1484  ImageList files;
1485  ImageList dirs;
1486  if (DBFS::GetImages(ids, files, dirs) < 1 || files.isEmpty())
1487  RESULT_ERR("Image not found", QString("Images %1 not in Db").arg(ids))
1488 
1489  // Update db
1490  for (const auto& im : std::as_const(files))
1491  {
1492  int old = im->m_orientation;
1493  im->m_orientation = Orientation(im->m_orientation).Transform(transform);
1494 
1495  // Update Db
1496  if (DBFS::SetOrientation(im->m_id, im->m_orientation))
1497  {
1498  LOG(VB_FILE, LOG_DEBUG, LOC + QString("Transformed %1 from %2 to %3")
1499  .arg(im->m_filePath).arg(old).arg(im->m_orientation));
1500  }
1501  }
1502 
1503  // Images are changed, not deleted
1504  QStringList mesg("");
1505 
1506  // Clean up thumbnails
1507  mesg << m_thumbGen->DeleteThumbs(files);
1508 
1509  // Notify clients of changed images
1510  DBFS::Notify("IMAGE_DB_CHANGED", mesg);
1511 
1512  return QStringList("OK");
1513 }
1514 
1515 
1524 template <class DBFS>
1525 QStringList ImageHandler<DBFS>::HandleDirs(const QString &destId,
1526  bool rescan,
1527  const QStringList &relPaths) const
1528 {
1529  // Find image in DB
1530  ImageList files;
1531  ImageList dirs;
1532  if (DBFS::GetImages(destId, files, dirs) != 1 || dirs.isEmpty())
1533  RESULT_ERR("Destination not found",
1534  QString("Image %1 not in Db").arg(destId))
1535 
1536  // Find dir. SG device (Photographs) uses most-free filesystem
1537  QString destPath = DBFS::GetAbsFilePath(dirs[0]);
1538  if (destPath.isEmpty())
1539  RESULT_ERR("Destination not found",
1540  QString("Dest dir %1 not found").arg(dirs[0]->m_filePath))
1541 
1542  QDir destDir(destPath);
1543  bool succeeded = false;
1544  for (const auto& relPath : std::as_const(relPaths))
1545  {
1546  // Validate dir name
1547  if (relPath.isEmpty() || relPath.contains("..") || relPath.startsWith(QChar('/')))
1548  continue;
1549 
1550  QString newPath = DBFS::ConstructPath(destDir.absolutePath(), relPath);
1551  if (!destDir.mkpath(relPath))
1552  {
1553  LOG(VB_GENERAL, LOG_ERR,
1554  LOC + QString("Failed to create dir %1").arg(newPath));
1555  continue;
1556  }
1557  LOG(VB_FILE, LOG_DEBUG, LOC + QString("Dir %1 created").arg(newPath));
1558  succeeded = true;
1559  }
1560 
1561  if (!succeeded)
1562  // Failures should only occur due to user input
1563  RESULT_ERR("Invalid Name", QString("Invalid name %1")
1564  .arg(relPaths.join(",")))
1565 
1566  if (rescan)
1567  // Rescan to detect new dir
1568  HandleScanRequest("START");
1569 
1570  return QStringList("OK");
1571 }
1572 
1573 
1580 template <class DBFS>
1581 QStringList ImageHandler<DBFS>::HandleCover(int dir, int cover) const
1582 {
1583  if (!DBFS::SetCover(dir, cover))
1584  RESULT_ERR("Set Cover failed",
1585  QString("Failed to set %1 to cover %2").arg(dir).arg(cover))
1586 
1587  // Image has changed, nothing deleted
1588  QStringList mesg = QStringList("") << QString::number(dir);
1589  DBFS::Notify("IMAGE_DB_CHANGED", mesg);
1590 
1591  RESULT_OK(QString("Cover of %1 is now %2").arg(dir).arg(cover));
1592 }
1593 
1594 
1603 template <class DBFS>
1604 QStringList ImageHandler<DBFS>::HandleIgnore(const QString &exclusions) const
1605 {
1606  // Save new setting. FE will have already saved it but not cleared the cache
1607  gCoreContext->SaveSettingOnHost("GalleryIgnoreFilter", exclusions, nullptr);
1608 
1609  // Rescan
1610  HandleScanRequest("START");
1611 
1612  RESULT_OK(QString("Using exclusions '%1'").arg(exclusions))
1613 }
1614 
1615 
1623 template <class DBFS>
1624 QStringList ImageHandler<DBFS>::HandleScanRequest(const QString &command,
1625  int devId) const
1626 {
1627  if (!m_scanner)
1628  RESULT_ERR("Missing Scanner", "Missing Scanner");
1629 
1630  if (command == "START")
1631  {
1632  // Must be dormant to start a scan
1633  if (m_scanner->IsScanning())
1634  RESULT_ERR("", "Scanner is busy");
1635 
1636  m_scanner->ChangeState(true);
1637  RESULT_OK("Scan requested");
1638  }
1639  else if (command == "STOP")
1640  {
1641  // Must be scanning to interrupt
1642  if (!m_scanner->IsScanning())
1643  RESULT_ERR("Scanner not running", "Scanner not running");
1644 
1645  m_scanner->ChangeState(false);
1646  RESULT_OK("Terminate scan requested");
1647  }
1648  else if (command == "QUERY")
1649  {
1650  return QStringList("OK") << m_scanner->GetProgress();
1651  }
1652  else if (command.startsWith(QString("DEVICE")))
1653  {
1654  m_scanner->EnqueueClear(devId, command);
1655  RESULT_OK(QString("Clearing device %1 %2").arg(command).arg(devId))
1656  }
1657  RESULT_ERR("Unknown command", QString("Unknown command %1").arg(command));
1658 }
1659 
1660 
1668 template <class DBFS>
1670 (const QStringList &message) const
1671 {
1672  if (message.size() != 2)
1673  RESULT_ERR("Unknown Command",
1674  QString("Bad request: %1").arg(message.join("|")))
1675 
1676  int priority = message.at(0).toInt()
1678 
1679  // get specific image details from db
1680  ImageList files;
1681  ImageList dirs;
1682  DBFS::GetImages(message.at(1), files, dirs);
1683 
1684  for (const auto& im : std::as_const(files))
1685  // notify clients when done; highest priority
1686  m_thumbGen->CreateThumbnail(im, priority, true);
1687 
1688  return QStringList("OK");
1689 }
1690 
1691 
1701 template <class DBFS>
1703 {
1704 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
1705  QMutableVectorIterator<ImagePtr> it(images);
1706 #else
1707  QMutableListIterator<ImagePtr> it(images);
1708 #endif
1709  it.toBack();
1710  while (it.hasPrevious())
1711  {
1712  ImagePtrK im = it.previous();
1713 
1714  // Remove file or directory
1715  QString absFilename = DBFS::GetAbsFilePath(im);
1716 
1717  bool success = !absFilename.isEmpty()
1718  && (im->IsFile() ? QFile::remove(absFilename)
1719  : QDir::root().rmdir(absFilename));
1720  if (success)
1721  LOG(VB_FILE, LOG_DEBUG, LOC + QString("Deleted %1").arg(absFilename));
1722  else
1723  {
1724  LOG(VB_GENERAL, LOG_ERR, LOC +
1725  QString("Can't delete %1").arg(absFilename));
1726  // Remove from list
1727  it.remove();
1728  }
1729  }
1730 }
1731 
1732 
1739 {
1740  switch (type)
1741  {
1742  case kPicOnly: return QString("AND type != %1").arg(kVideoFile);
1743  case kVideoOnly: return QString("AND type != %1").arg(kImageFile);
1744  case kPicAndVideo: return "";
1745  }
1746  return "";
1747 }
1748 
1749 
1756 {
1757  m_refineClause = QString("%2 %3 "
1758  "ORDER BY "
1759  "CASE WHEN type <= %1 THEN %4, "
1760  "CASE WHEN type > %1 THEN %5 ")
1761  .arg(kDirectory)
1762  .arg(m_showHidden ? "" : "AND hidden = 0",
1766 }
1767 
1768 
1775 {
1776  // prepare the sorting statement
1777  switch (order)
1778  {
1779  default:
1780  case kSortByNameAsc: return "name END ASC";
1781  case kSortByNameDesc: return "name END DESC";
1782  case kSortByModTimeAsc: return "modtime END ASC";
1783  case kSortByModTimeDesc: return "modtime END DESC";
1784  case kSortByExtAsc: return "extension END ASC, name ASC";
1785  case kSortByExtDesc: return "extension END DESC, name DESC";
1786  case kSortBySizeAsc: return "size END ASC, name ASC";
1787  case kSortBySizeDesc: return "size END DESC, name DESC";
1788  case kSortByDateAsc: return "IF(date=0, modtime, date) END ASC";
1789  case kSortByDateDesc: return "IF(date=0, modtime, date) END DESC";
1790  }
1791 }
1792 
1793 
1803  ImageList &files, ImageList &dirs) const
1804 {
1805  // Only Root node will invoke both Db queries but result set will be small
1806  // For Root the SG is always ordered before local devices
1807  // Root node has no Db entry so the 2 queries will not overwrite the parent.
1808  int count = 0;
1809  if (!ImageItem::IsLocalId(id))
1810  count = m_remote->GetDirectory(id, parent, files, dirs, m_refineClause);
1812  count += ImageHandler::GetDirectory(id, parent, files, dirs, m_refineClause);
1813 
1814  if (id == GALLERY_DB_ID)
1815  {
1816  // Add a Root node
1817  parent = ImagePtr(new ImageItem(GALLERY_DB_ID));
1818  parent->m_parentId = GALLERY_DB_ID;
1819  parent->m_type = kDevice;
1820 
1821  ++count;
1822  }
1823  return count;
1824 }
1825 
1826 
1835  ImageList &files, ImageList &dirs) const
1836 {
1837  // Ids are either all local or all remote. GALLERY_DB_ID not valid
1838  StringPair lists = ImageItem::PartitionIds(ids);
1839 
1840  if (!lists.second.isEmpty())
1841  return m_remote->GetImages(lists.second, files, dirs, m_refineClause);
1842  if (m_dbExists && !lists.first.isEmpty())
1843  return ImageHandler::GetImages(lists.first, files, dirs, m_refineClause);
1844  return 0;
1845 }
1846 
1847 
1855 int ImageDbReader::GetChildren(int id, ImageList &files, ImageList &dirs) const
1856 {
1857  int count = 0;
1858  if (!ImageItem::IsLocalId(id))
1859  count = m_remote->GetChildren(QString::number(id), files, dirs,
1860  m_refineClause);
1862  count += ImageHandler::GetChildren(QString::number(id), files, dirs,
1863  m_refineClause);
1864  return count;
1865 }
1866 
1867 
1875  ImageList &files, ImageList &dirs) const
1876 {
1877  // Ids are either all local or all remote
1878  StringPair lists = ImageItem::PartitionIds(ids);
1879 
1880  if (!lists.second.isEmpty())
1881  m_remote->GetDescendants(lists.second, files, dirs);
1882  if (m_dbExists && !lists.first.isEmpty())
1883  ImageHandler::GetDescendants(lists.first, files, dirs);
1884 }
1885 
1886 
1893 void ImageDbReader::GetImageTree(int id, ImageList &files) const
1894 {
1895  if (!ImageItem::IsLocalId(id))
1896  m_remote->GetImageTree(id, files, m_refineClause);
1898  ImageHandler::GetImageTree(id, files, m_refineClause);
1899 }
1900 
1901 
1910 void ImageDbReader::GetDescendantCount(int id, int &dirs, int &pics,
1911  int &videos, int &sizeKb) const
1912 {
1913  if (id == GALLERY_DB_ID)
1914  {
1915  // Sum both unfiltered tables
1916  m_remote->GetDescendantCount(id, true, dirs, pics, videos, sizeKb);
1917  if (m_dbExists)
1918  ImageHandler::GetDescendantCount(id, true, dirs, pics, videos, sizeKb);
1919  }
1920  else if (!ImageItem::IsLocalId(id))
1921  {
1922  // Don't filter on SG path (it's blank)
1924  dirs, pics, videos, sizeKb);
1925  }
1926  else if (m_dbExists)
1927  {
1928  // Always filter on device/dir
1929  ImageHandler::GetDescendantCount(id, false, dirs, pics, videos, sizeKb);
1930  }
1931 }
1932 
1933 
1938 
1939 
1945 {
1946  if (!s_instance)
1947  s_instance = new ImageManagerBe();
1948  return s_instance;
1949 }
1950 
1951 
1957 {
1958  if (!s_instance)
1959  {
1960  // Use saved settings
1962  (gCoreContext->GetNumSetting("GalleryImageOrder"),
1963  gCoreContext->GetNumSetting("GalleryDirOrder"),
1964  gCoreContext->GetBoolSetting("GalleryShowHidden"),
1965  gCoreContext->GetNumSetting("GalleryShowType"),
1966  gCoreContext->GetSetting("GalleryDateFormat"));
1967  }
1968  return *s_instance;
1969 }
1970 
1971 
1980 void ImageManagerFe::CreateThumbnails(const ImageIdList &ids, bool forFolder)
1981 {
1982  // Split images into <locals, remotes>
1983  StringPair lists = ImageItem::PartitionIds(ids);
1984 
1985  if (!lists.second.isEmpty())
1986  {
1987  LOG(VB_FILE, LOG_DEBUG, LOC +
1988  QString("Sending CREATE_THUMBNAILS %1 (forFolder %2)")
1989  .arg(lists.second).arg(forFolder));
1990 
1991  QStringList message;
1992  message << QString::number(static_cast<int>(forFolder)) << lists.second;
1993  gCoreContext->SendEvent(MythEvent("CREATE_THUMBNAILS", message));
1994  }
1995 
1996  if (!lists.first.isEmpty())
1997  {
1998  LOG(VB_FILE, LOG_DEBUG, LOC +
1999  QString("Creating local thumbnails %1 (forFolder %2)")
2000  .arg(lists.first).arg(forFolder));
2001 
2002  QStringList message;
2003  message << QString::number(static_cast<int>(forFolder)) << lists.first;
2004  HandleCreateThumbnails(message);
2005  }
2006 }
2007 
2008 
2015 QString ImageManagerFe::ScanImagesAction(bool start, bool local)
2016 {
2017  QStringList command;
2018  command << (start ? "START" : "STOP");
2019 
2020  if (!local)
2021  {
2022  command.push_front("IMAGE_SCAN");
2023  bool ok = gCoreContext->SendReceiveStringList(command, true);
2024  return ok ? "" : command[1];
2025  }
2026 
2027  // Create database on first scan
2028  if (!CreateTable())
2029  return "Couldn't create database";
2030 
2031  QStringList err = HandleScanRequest(command[0]);
2032  return err[0] == "OK" ? "" : err[1];
2033 }
2034 
2035 
2042 {
2043  QStringList strList;
2044  strList << "IMAGE_SCAN" << "QUERY";
2045 
2046  if (!gCoreContext->SendReceiveStringList(strList))
2047  {
2048  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Scan query failed : %1")
2049  .arg(strList.join(",")));
2050  }
2051  return strList;
2052 }
2053 
2054 
2061 QString ImageManagerFe::HideFiles(bool hidden, const ImageIdList &ids)
2062 {
2063  // Split images into <locals, remotes>
2064  StringPair lists = ImageItem::PartitionIds(ids);
2065  QString result = "";
2066 
2067  if (!lists.second.isEmpty())
2068  {
2069  QStringList message;
2070  message << "IMAGE_HIDE" << QString::number(static_cast<int>(hidden)) << lists.second;
2071 
2072  if (!gCoreContext->SendReceiveStringList(message, true))
2073  result = message[1];
2074  }
2075 
2076  if (!lists.first.isEmpty())
2077  {
2078  QStringList err = HandleHide(hidden, lists.first);
2079  if (err[0] != "OK")
2080  result = err[1];
2081  }
2082  return result;
2083 }
2084 
2085 
2093  const ImageIdList &ids)
2094 {
2095  // Split images into <locals, remotes>
2096  StringPair lists = ImageItem::PartitionIds(ids);
2097  QString result = "";
2098 
2099  if (!lists.second.isEmpty())
2100  {
2101  QStringList message;
2102  message << "IMAGE_TRANSFORM" << QString::number(transform) << lists.second;
2103 
2104  if (!gCoreContext->SendReceiveStringList(message, true))
2105  result = message[1];
2106  }
2107 
2108  if (!lists.first.isEmpty())
2109  {
2110  QStringList err = HandleTransform(transform, lists.first);
2111  if (err[0] != "OK")
2112  result = err[1];
2113  }
2114  return result;
2115 }
2116 
2117 
2124 QString ImageManagerFe::SetCover(int parent, int cover)
2125 {
2126  if (!ImageItem::IsLocalId(parent))
2127  {
2128  QStringList message;
2129  message << "IMAGE_COVER" << QString::number(parent) << QString::number(cover);
2130 
2131  bool ok = gCoreContext->SendReceiveStringList(message, true);
2132  return ok ? "" : message[1];
2133  }
2134 
2135  QStringList err = HandleCover(parent, cover);
2136  return err[0] == "OK" ? "" : err[1];
2137 }
2138 
2139 
2145 {
2146  if (ImageItem::IsLocalId(id))
2147  HandleGetMetadata(QString::number(id));
2148  else
2149  gCoreContext->SendEvent(MythEvent("IMAGE_GET_METADATA", QString::number(id)));
2150 }
2151 
2152 
2155 {
2156  QStringList message("IMAGE_SCAN");
2157  message << "DEVICE CLEAR ALL";
2158  gCoreContext->SendReceiveStringList(message, true);
2159 }
2160 
2161 
2168 QString ImageManagerFe::IgnoreDirs(const QString &excludes)
2169 {
2170  QStringList message("IMAGE_IGNORE");
2171  message << excludes;
2172  bool ok = gCoreContext->SendReceiveStringList(message, true);
2173  return ok ? "" : message[1];
2174 }
2175 
2176 
2184 QString ImageManagerFe::MakeDir(int parent, const QStringList &names, bool rescan)
2185 {
2186  QString destId = QString::number(parent);
2187 
2188  if (!ImageItem::IsLocalId(parent))
2189  {
2190  QStringList message("IMAGE_CREATE_DIRS");
2191  message << destId << QString::number(static_cast<int>(rescan)) << names;
2192  bool ok = gCoreContext->SendReceiveStringList(message, true);
2193  return ok ? "" : message[1];
2194  }
2195  QStringList err = HandleDirs(destId, rescan, names);
2196  return (err[0] == "OK") ? "" : err[1];
2197 }
2198 
2199 
2206 QString ImageManagerFe::RenameFile(const ImagePtrK& im, const QString &name)
2207 {
2208  if (!im->IsLocal())
2209  {
2210  QStringList message("IMAGE_RENAME");
2211  message << QString::number(im->m_id) << name;
2212  bool ok = gCoreContext->SendReceiveStringList(message, true);
2213  return ok ? "" : message[1];
2214  }
2215  QStringList err = HandleRename(QString::number(im->m_id), name);
2216  return (err[0] == "OK") ? "" : err[1];
2217 }
2218 
2219 
2226 QString ImageManagerFe::CreateImages(int destId, const ImageListK &images)
2227 {
2228  if (images.isEmpty())
2229  return "";
2230 
2231  // Define field seperator & include it in message
2232  const QString seperator("...");
2233  QStringList imageDefs(seperator);
2234  ImageIdList ids;
2235  for (const auto& im : std::as_const(images))
2236  {
2237  ids << im->m_id;
2238 
2239  // Copies preserve hide state, orientation & cover
2240  QStringList aDef;
2241  aDef << QString::number(im->m_id)
2242  << QString::number(im->m_type)
2243  << im->m_filePath
2244  << QString::number(static_cast<int>(im->m_isHidden))
2245  << QString::number(im->m_orientation)
2246  << QString::number(im->m_userThumbnail);
2247 
2248  imageDefs << aDef.join(seperator);
2249  }
2250 
2251  // Images are either all local or all remote
2252  if (ImageItem::IsLocalId(destId))
2253  {
2254  QStringList err = HandleDbCreate(imageDefs);
2255  return (err[0] == "OK") ? "" : err[1];
2256  }
2257  imageDefs.prepend("IMAGE_COPY");
2258  bool ok = gCoreContext->SendReceiveStringList(imageDefs, true);
2259  return ok ? "" : imageDefs[1];
2260 }
2261 
2262 
2270 QString ImageManagerFe::MoveDbImages(const ImagePtrK& destDir, ImageListK &images,
2271  const QString &srcPath)
2272 {
2273  QStringList idents;
2274  for (const auto& im : std::as_const(images))
2275  idents << QString::number(im->m_id);
2276 
2277  // Images are either all local or all remote
2278  if (destDir->IsLocal())
2279  {
2280  QStringList err = HandleDbMove(idents.join(","), srcPath,
2281  destDir->m_filePath);
2282  return (err[0] == "OK") ? "" : err[1];
2283  }
2284 
2285  QStringList message("IMAGE_MOVE");
2286  message << idents.join(",") << srcPath << destDir->m_filePath;
2287  bool ok = gCoreContext->SendReceiveStringList(message, true);
2288  return ok ? "" : message[1];
2289 }
2290 
2291 
2298 {
2299  StringPair lists = ImageItem::PartitionIds(ids);
2300 
2301  QString result = "";
2302  if (!lists.second.isEmpty())
2303  {
2304  QStringList message("IMAGE_DELETE");
2305  message << lists.second;
2306 
2307  bool ok = gCoreContext->SendReceiveStringList(message, true);
2308  if (!ok)
2309  result = message[1];
2310  }
2311  if (!lists.first.isEmpty())
2312  {
2313  QStringList err = HandleDelete(lists.first);
2314  if (err[0] != "OK")
2315  result = err[1];
2316  }
2317  return result;
2318 }
2319 
2320 
2328 {
2329  if (im->m_id == GALLERY_DB_ID)
2330  return "";
2331 
2332  std::chrono::seconds secs = 0s;
2334 
2335  if (im->m_date > 0s)
2336  {
2337  secs = im->m_date;
2338  format |= MythDate::kTime;
2339  }
2340  else
2341  {
2342  secs = im->m_modTime;
2343  }
2344 
2345  return MythDate::toString(QDateTime::fromSecsSinceEpoch(secs.count()), format);
2346 }
2347 
2348 
2355 QString ImageManagerFe::ShortDateOf(const ImagePtrK& im) const
2356 {
2357  if (im->m_id == GALLERY_DB_ID)
2358  return "";
2359 
2360  std::chrono::seconds secs(im->m_date > 0s ? im->m_date : im->m_modTime);
2361  return QDateTime::fromSecsSinceEpoch(secs.count()).date().toString(m_dateFormat);
2362 }
2363 
2364 
2371 {
2372  if (im.m_id == GALLERY_DB_ID)
2373  return tr("Gallery");
2374  if (im.m_id == PHOTO_DB_ID)
2375  return tr("Photographs");
2376  return im.IsLocal() ? DeviceName(im.m_device)
2377  : m_remote->DeviceName(im.m_device);
2378 }
2379 
2380 
2388 QString ImageManagerFe::CrumbName(ImageItemK &im, bool getPath) const
2389 {
2390  if (im.IsDevice())
2391  return DeviceCaption(im);
2392 
2393  if (!getPath)
2394  return im.m_baseName;
2395 
2396  QString dev;
2397  QString path(im.m_filePath);
2398 
2399  if (im.IsLocal())
2400  {
2401  // Replace local mount path with device name
2402  path.remove(0, DeviceMount(im.m_device).size());
2403  dev = DeviceName(im.m_device);
2404  }
2405  return dev + path.replace("/", " > ");
2406 }
2407 
2408 
2409 void ImageManagerFe::CloseDevices(int devId, bool eject)
2410 {
2411  QString reason { "DEVICE REMOVE" };
2412  if (devId == DEVICE_INVALID)
2413  reason = "DEVICE CLOSE ALL";
2414  else if (eject)
2415  reason = "DEVICE EJECT";
2416  HandleScanRequest(reason, devId);
2417 }
2418 
2419 
2425 {
2427  if (!monitor)
2428  return false;
2429 
2430  // Detect all local media
2431  QList<MythMediaDevice*> devices
2433 
2434  for (auto *dev : std::as_const(devices))
2435  {
2436  if (monitor->ValidateAndLock(dev) && dev->isUsable())
2437  OpenDevice(dev->getDeviceModel(), dev->getMountPath(), dev);
2438  else
2439  monitor->Unlock(dev);
2440  }
2441 
2442  if (DeviceCount() > 0)
2443  {
2444  // Close devices that are no longer present
2445  QList absentees = GetAbsentees();
2446  for (int devId : std::as_const(absentees))
2447  CloseDevices(devId);
2448 
2449  // Start local scan
2450  QString err = ScanImagesAction(true, true);
2451  if (!err.isEmpty())
2452  LOG(VB_GENERAL, LOG_ERR, LOC + err);
2453  }
2454  return DeviceCount() > 0;
2455 }
2456 
2457 
2463 {
2465 
2466  if (!event || !monitor)
2467  return;
2468 
2469  MythMediaDevice *dev = event->getDevice();
2470  if (!dev)
2471  return;
2472 
2473  MythMediaType type = dev->getMediaType();
2474  MythMediaStatus status = dev->getStatus();
2475 
2476  LOG(VB_FILE, LOG_DEBUG, LOC +
2477  QString("Media event for %1 (%2) at %3, type %4, status %5 (was %6)")
2478  .arg(dev->getDeviceModel(), dev->getVolumeID(), dev->getMountPath())
2479  .arg(type).arg(status).arg(event->getOldStatus()));
2480 
2482  {
2483  LOG(VB_FILE, LOG_DEBUG, LOC +
2484  QString("Ignoring event - wrong type %1").arg(type));
2485  return;
2486  }
2487 
2488  if (status == MEDIASTAT_USEABLE || status == MEDIASTAT_MOUNTED)
2489  {
2490  // New device. Lock it & scan
2491  if (monitor->ValidateAndLock(dev))
2492  {
2493  OpenDevice(dev->getDeviceModel(), dev->getMountPath(), dev);
2494  ScanImagesAction(true, true);
2495  }
2496  else
2497  {
2498  monitor->Unlock(dev);
2499  }
2500  return;
2501  }
2502 
2503  // Device has disappeared
2504  int devId = LocateMount(dev->getMountPath());
2505  if (devId != DEVICE_INVALID)
2506  CloseDevices(devId);
2507 }
2508 
2509 
2511 {
2512  auto *tmp = new QTemporaryDir(QDir::tempPath() % "/" % IMPORTDIR % "-XXXXXX");
2513  if (!tmp->isValid())
2514  {
2515  delete tmp;
2516  return "";
2517  }
2518 
2519  QString time(QDateTime::currentDateTime().toString("mm:ss"));
2520  OpenDevice("Import " + time, tmp->path(), nullptr, tmp);
2521  return tmp->path();
2522 }
2523 
2524 
2525 // Must define the valid template implementations to generate code for the
2526 // instantiations (as they are defined in the cpp rather than header).
2527 // Otherwise the linker will fail with undefined references...
2528 template class ImageDb<ImageAdapterSg>;
2529 template class ImageDb<ImageAdapterLocal>;
2530 template class ImageHandler<ImageDbSg>;
2531 template class ImageHandler<ImageDbLocal>;
MythMediaDevice::getMountPath
const QString & getMountPath() const
Definition: mythmedia.h:58
ImageAdapterBase::ImageAdapterBase
ImageAdapterBase()
Constructor.
Definition: imagemanager.cpp:286
MythMediaEvent::getOldStatus
MythMediaStatus getOldStatus(void) const
Definition: mythmedia.h:190
ImageManagerBe::s_instance
static ImageManagerBe * s_instance
BE Gallery instance.
Definition: imagemanager.h:398
ImageManagerFe::m_dateFormat
QString m_dateFormat
UI format for thumbnail date captions.
Definition: imagemanager.h:521
ImageManagerFe::ImageManagerFe
ImageManagerFe(int order, int dirOrder, bool showAll, int showType, QString dateFormat)
Definition: imagemanager.h:508
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:812
ImagePtrK
QSharedPointer< ImageItemK > ImagePtrK
Definition: imagetypes.h:165
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:127
ImageDbReader::m_showType
int m_showType
Type of images to display - pic only/video only/both.
Definition: imagemanager.h:450
ImageHandler::HandleRename
QStringList HandleRename(const QString &id, const QString &newBase) const
Change name of an image/dir.
Definition: imagemanager.cpp:1211
ImageDb::SetHidden
bool SetHidden(bool hide, const QString &ids) const
Sets hidden status of an image/dir in database.
Definition: imagemanager.cpp:904
Device::m_thumbs
QString m_thumbs
Dir sub-path of device thumbnails.
Definition: imagemanager.cpp:118
MythDate::toString
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:93
MSqlQuery::bindValueNoNull
void bindValueNoNull(const QString &placeholder, const QVariant &val)
Add a single binding, taking care not to set a NULL value.
Definition: mythdbcon.cpp:902
MSqlQuery::size
int size(void) const
Definition: mythdbcon.h:214
ImageDbReader::GetImages
int GetImages(const ImageIdList &ids, ImageList &files, ImageList &dirs) const
Returns images (local or remote but not a combination)
Definition: imagemanager.cpp:1834
DeviceManager::GetDeviceDirs
StringMap GetDeviceDirs() const
Get all known devices.
Definition: imagemanager.cpp:255
kSortBySizeAsc
@ kSortBySizeAsc
File size Smallest -> Largest.
Definition: imagetypes.h:52
ImageFileTransform
ImageFileTransform
Image transformations.
Definition: imagemetadata.h:46
ImageAdapterBase::BaseNameOf
static QString BaseNameOf(const QString &path)
Extracts file name (incl extension) from a filepath.
Definition: imagemanager.h:136
ImageManagerFe::CreateThumbnails
void CreateThumbnails(const ImageIdList &ids, bool forFolder)
Create thumbnails or verify that they already exist.
Definition: imagemanager.cpp:1980
kSortByModTimeAsc
@ kSortByModTimeAsc
File modified time Earliest -> Latest.
Definition: imagetypes.h:48
ImageDbLocal::m_dbExists
bool m_dbExists
Definition: imagemanager.h:336
ImageDbReader::GetImageTree
void GetImageTree(int id, ImageList &files) const
Return all files (local or remote) in the sub-trees of a dir.
Definition: imagemanager.cpp:1893
ImageItem::m_type
int m_type
Type of node: dir, video etc.
Definition: imagetypes.h:97
MediaMonitor::GetMedias
QList< MythMediaDevice * > GetMedias(unsigned mediatypes)
Ask for available media. Must be locked with ValidateAndLock().
Definition: mediamonitor.cpp:599
ReadMetaThread
Task to read all metadata from file.
Definition: imagemanager.cpp:1123
kUnknown
@ kUnknown
Unprocessable file type.
Definition: imagetypes.h:35
Device::isImport
bool isImport() const
Definition: imagemanager.cpp:110
ImageItem::m_id
int m_id
Uniquely identifies an image (file/dir).
Definition: imagetypes.h:89
ImageDb::UpdateDbImage
bool UpdateDbImage(ImageItemK &im) const
Updates or creates database image or dir.
Definition: imagemanager.cpp:831
MythCoreContext::SendReceiveStringList
bool SendReceiveStringList(QStringList &strlist, bool quickTimeout=false, bool block=true)
Send a message to the backend and wait for a response.
Definition: mythcorecontext.cpp:1379
ImageItem::m_comment
QString m_comment
User comment, from Exif metadata.
Definition: imagetypes.h:102
ImageDbReader::GetDirectory
int GetDirectory(int id, ImagePtr &parent, ImageList &files, ImageList &dirs) const
Return images (local and/or remote) for a dir and its direct children.
Definition: imagemanager.cpp:1802
ImageManagerFe::CreateImages
QString CreateImages(int destId, const ImageListK &images)
Copies database images (but not the files themselves).
Definition: imagemanager.cpp:2226
kSortByDateAsc
@ kSortByDateAsc
Exif date Earliest -> Latest.
Definition: imagetypes.h:54
ImageManagerFe::ScanImagesAction
QString ScanImagesAction(bool start, bool local=false)
Handle scanner start/stop commands.
Definition: imagemanager.cpp:2015
LOC
#define LOC
Definition: imagemanager.cpp:13
ImageHandler::HandleGetMetadata
QStringList HandleGetMetadata(const QString &id) const
Read meta data for an image.
Definition: imagemanager.cpp:1180
MediaMonitor::GetMediaMonitor
static MediaMonitor * GetMediaMonitor(void)
Definition: mediamonitor.cpp:75
ImageItem::IsLocal
bool IsLocal() const
Definition: imagetypes.h:119
ImageDbLocal::DropTable
void DropTable()
Remove local image table.
Definition: imagemanager.cpp:1077
ImageMetaData
Abstract class for image metadata.
Definition: imagemetadata.h:99
ImageManagerFe::s_instance
static ImageManagerFe * s_instance
FE Gallery instance.
Definition: imagemanager.h:518
kPicRequestPriority
@ kPicRequestPriority
Client request to display an image thumbnail.
Definition: imagethumbs.h:34
DeviceManager::DeviceName
QString DeviceName(int devId) const
Get model name of the device.
Definition: imagemanager.cpp:141
kNullDevice
static Device kNullDevice
Definition: imagemanager.cpp:124
ImageManagerFe::MakeDir
QString MakeDir(int parent, const QStringList &names, bool rescan=true)
Create directories.
Definition: imagemanager.cpp:2184
ImageDbReader::m_showHidden
bool m_showHidden
Whether hidden images are displayed.
Definition: imagemanager.h:449
ImageItem::m_isHidden
bool m_isHidden
If true, image won't be shown.
Definition: imagetypes.h:105
Device::RemoveDirContents
static void RemoveDirContents(const QString &path)
Clears all files and sub-dirs within a directory.
Definition: imagemanager.cpp:92
MEDIASTAT_USEABLE
@ MEDIASTAT_USEABLE
Definition: mythmedia.h:19
StorageGroup::FindFile
QString FindFile(const QString &filename)
Definition: storagegroup.cpp:597
MEDIATYPE_MIXED
@ MEDIATYPE_MIXED
Definition: mythmedia.h:27
MSqlQuery::lastInsertId
QVariant lastInsertId()
Return the id of the last inserted row.
Definition: mythdbcon.cpp:935
Device::m_mount
QString m_mount
Mountpoint.
Definition: imagemanager.cpp:117
MythEvent
This class is used as a container for messages.
Definition: mythevent.h:16
ImageManagerFe::DeviceEvent
void DeviceEvent(MythMediaEvent *event)
Manage events for local devices.
Definition: imagemanager.cpp:2462
Device::isPresent
bool isPresent() const
Definition: imagemanager.cpp:111
DeviceManager::DeviceCount
int DeviceCount() const
Definition: imagemanager.h:100
ImageManagerFe::IgnoreDirs
static QString IgnoreDirs(const QString &excludes)
Set directories to ignore during scans of the storage group.
Definition: imagemanager.cpp:2168
ImageAdapterBase::m_videoFileExt
QStringList m_videoFileExt
List of file extensions recognised as videos.
Definition: imagemanager.h:186
Device::m_media
MythMediaDevice * m_media
Set for MediaMonitor devices only.
Definition: imagemanager.cpp:119
RESULT_ERR
#define RESULT_ERR(ERR, MESG)
Definition: imagemanager.cpp:22
imagemanager.h
Manages a collection of images.
Device::Close
void Close(bool eject=false)
Releases device.
Definition: imagemanager.cpp:63
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:204
RemoveFromDB
bool RemoveFromDB(Bookmark *site)
Definition: browserdbutil.cpp:158
Device::RemoveThumbs
void RemoveThumbs(void) const
Delete thumbnails associated with device.
Definition: imagemanager.cpp:99
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:618
MythMediaDevice::getDevicePath
const QString & getDevicePath() const
Definition: mythmedia.h:61
MythMediaDevice::getStatus
MythMediaStatus getStatus() const
Definition: mythmedia.h:70
ImageAdapterSg::Notify
static void Notify(const QString &mesg, const QStringList &extra)
Send message to all clients about remote ids.
Definition: imagemanager.cpp:463
ImageManagerFe::HideFiles
QString HideFiles(bool hidden, const ImageIdList &ids)
Hide/unhide images.
Definition: imagemanager.cpp:2061
ImageAdapterSg::m_sg
StorageGroup m_sg
Images storage group.
Definition: imagemanager.h:273
EXIF_MYTH_NAME
static constexpr const char * EXIF_MYTH_NAME
Definition: imagemetadata.h:40
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
FileAssociations::getList
const association_list & getList() const
Definition: dbaccess.cpp:811
DB_TABLE
static constexpr const char * DB_TABLE
Definition: imagemanager.cpp:19
ImageDb::GetImages
int GetImages(const QString &ids, ImageList &files, ImageList &dirs, const QString &refine="") const
Read database images/dirs by id.
Definition: imagemanager.cpp:557
ImageDb::InsertDbImage
int InsertDbImage(ImageItemK &im, bool checkForDuplicate=false) const
Adds new image to database, optionally checking for existing filepath.
Definition: imagemanager.cpp:773
Device
A device containing images (ie. USB stick, CD, storage group etc)
Definition: imagemanager.cpp:35
ImageDb::CreateImage
ImageItem * CreateImage(const MSqlQuery &query) const
Create image from Db query data.
Definition: imagemanager.cpp:514
ImageHandler::HandleCover
QStringList HandleCover(int dir, int cover) const
Updates/resets cover thumbnail for an image dir.
Definition: imagemanager.cpp:1581
DeviceManager::ThumbDir
QString ThumbDir(int fs) const
Definition: imagemanager.cpp:147
ImageManagerBe::ImageManagerBe
ImageManagerBe()
Definition: imagemanager.h:391
ImageDbReader::TypeSelector
static QString TypeSelector(int type)
Generate SQL type filter clause.
Definition: imagemanager.cpp:1738
kSortByExtAsc
@ kSortByExtAsc
Extension A-Z.
Definition: imagetypes.h:50
mediamonitor.h
IMPORTDIR
static constexpr const char * IMPORTDIR
Definition: imagemanager.cpp:31
MythMediaDevice::getDeviceModel
const QString & getDeviceModel() const
Definition: mythmedia.h:67
kDirectory
@ kDirectory
A device sub directory.
Definition: imagetypes.h:38
ImageMetaData::FromVideo
static ImageMetaData * FromVideo(const QString &filePath)
Factory to retrieve metadata from videos.
Definition: imagemetadata.cpp:709
ImageItem::m_device
int m_device
Id of media device. Always 0 (SG) for remotes, 1+ for local devices.
Definition: imagetypes.h:95
ImageManagerFe::CloseDevices
void CloseDevices(int devId=DEVICE_INVALID, bool eject=false)
Definition: imagemanager.cpp:2409
ImageItem::PartitionIds
static StringPair PartitionIds(const ImageIdList &ids)
Separates list of ids into a list of local ids and a list of remote ids.
Definition: imagetypes.h:140
kVideoFile
@ kVideoFile
A video.
Definition: imagetypes.h:40
ImageDbSg::ImageDbSg
ImageDbSg()
SG database constructor.
Definition: imagemanager.cpp:1056
ImageManagerFe::ChangeOrientation
QString ChangeOrientation(ImageFileTransform transform, const ImageIdList &ids)
Apply an orientation transform to images.
Definition: imagemanager.cpp:2092
MythMediaType
MythMediaType
Definition: mythmedia.h:24
tmp
static guint32 * tmp
Definition: goom_core.cpp:26
kDevice
@ kDevice
Storage Group and local mounted media.
Definition: imagetypes.h:36
ImageHandler::HandleTransform
QStringList HandleTransform(int transform, const QString &ids) const
Change orientation of pictures by applying a transformation.
Definition: imagemanager.cpp:1478
dbaccess.h
ImageManagerFe::getInstance
static ImageManagerFe & getInstance()
Get Frontend Gallery.
Definition: imagemanager.cpp:1956
kPicAndVideo
@ kPicAndVideo
Show Pictures & Videos.
Definition: imagemanager.h:78
ImageAdapterLocal::CreateItem
ImageItem * CreateItem(const QFileInfo &fi, int parentId, int devId, const QString &base) const
Construct a local image from a file.
Definition: imagemanager.cpp:348
ImageManagerFe::DeviceCaption
QString DeviceCaption(ImageItemK &im) const
Return translated device name.
Definition: imagemanager.cpp:2370
Orientation::Transform
int Transform(int transform)
Adjust orientation to apply a transform to an image.
Definition: imagemetadata.cpp:26
ImageHandler::HandleDbCreate
QStringList HandleDbCreate(QStringList defs) const
Creates images for files created by a copy operation.
Definition: imagemanager.cpp:1330
ImageDbReader::m_refineClause
QString m_refineClause
SQL clause for image filtering/ordering.
Definition: imagemanager.h:451
ImageMetaData::ToString
static QString ToString(const QString &name, const QString &label, const QString &value)
Encodes metadata into a string as <tag name><tag label><tag value>
Definition: imagemetadata.h:112
ImageDb::GetImageTree
bool GetImageTree(int id, ImageList &files, const QString &refine) const
Returns all files in the sub-tree of a dir.
Definition: imagemanager.cpp:686
ImageHash
QHash< QString, ImagePtr > ImageHash
Definition: imagetypes.h:161
mythdate.h
MythDate::fromSecsSinceEpoch
MBASE_PUBLIC QDateTime fromSecsSinceEpoch(int64_t seconds)
This function takes the number of seconds since the start of the epoch and returns a QDateTime with t...
Definition: mythdate.cpp:81
kSortByNameAsc
@ kSortByNameAsc
Name A-Z.
Definition: imagetypes.h:46
ImageHandler::HandleDbMove
QStringList HandleDbMove(const QString &ids, const QString &srcPath, QString destPath) const
Updates images that have been renamed.
Definition: imagemanager.cpp:1389
GetConfDir
QString GetConfDir(void)
Definition: mythdirs.cpp:263
kImageFile
@ kImageFile
A picture.
Definition: imagetypes.h:39
ImageManagerFe::ClearStorageGroup
static void ClearStorageGroup()
Clear database & thumbnails of Storage Group images.
Definition: imagemanager.cpp:2154
MythCoreContext::SendEvent
void SendEvent(const MythEvent &event)
Definition: mythcorecontext.cpp:1538
kFlipVertical
@ kFlipVertical
Reflect about horizontal axis.
Definition: imagemetadata.h:51
DeviceManager::~DeviceManager
~DeviceManager()
Definition: imagemanager.cpp:127
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:550
IMAGE_STORAGE_GROUP
static constexpr const char * IMAGE_STORAGE_GROUP
Definition: imagemanager.h:63
FileAssociations::association_list
std::vector< file_association > association_list
Definition: dbaccess.h:154
StringMap
QMap< int, QString > StringMap
Definition: imagetypes.h:63
MythMediaStatus
MythMediaStatus
Definition: mythmedia.h:12
EXIF_MYTH_ORIENT
static constexpr const char * EXIF_MYTH_ORIENT
Definition: imagemetadata.h:42
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:225
ImageHandler< ImageDbSg >
ImageAdapterBase::FormatSize
static QString FormatSize(int sizeKib)
Definition: imagemanager.h:143
ImageDb::SetOrientation
bool SetOrientation(int id, int orientation) const
Sets image orientation in Db.
Definition: imagemanager.cpp:954
formats
const std::array< const std::string, 8 > formats
Definition: vbilut.cpp:189
MythMediaEvent
Definition: mythmedia.h:183
ImageDbReader::GetDescendants
void GetDescendants(const ImageIdList &ids, ImageList &files, ImageList &dirs) const
Return all (local or remote) images that are direct children of a dir.
Definition: imagemanager.cpp:1874
ImageAdapterBase::SupportedImages
static QStringList SupportedImages()
Return recognised pictures.
Definition: imagemanager.cpp:310
ImageDbReader::OrderSelector
static QString OrderSelector(int order)
Generate SQL ordering clause.
Definition: imagemanager.cpp:1774
ImageItem::m_modTime
std::chrono::seconds m_modTime
Filesystem modified datestamp.
Definition: imagetypes.h:98
DBLOC
#define DBLOC
Definition: imagemanager.cpp:14
ImageAdapterBase::PathOf
static QString PathOf(const QString &path)
Extracts path from a filepath.
Definition: imagemanager.h:140
ImageListK
QList< ImagePtrK > ImageListK
Definition: imagetypes.h:166
clear
static void clear(SettingsMap &cache, SettingsMap &overrides, const QString &myKey)
Definition: mythdb.cpp:896
MediaMonitor::Unlock
void Unlock(MythMediaDevice *pMedia)
decrements the MythMediaDevices reference count
Definition: mediamonitor.cpp:505
Orientation::Description
QString Description() const
Generate text description of orientation.
Definition: imagemetadata.cpp:226
ImageManagerFe::LongDateOf
static QString LongDateOf(const ImagePtrK &im)
Return a timestamp/datestamp for an image or dir.
Definition: imagemanager.cpp:2327
RESULT_OK
#define RESULT_OK(MESG)
Definition: imagemanager.cpp:26
MEDIASTAT_MOUNTED
@ MEDIASTAT_MOUNTED
Definition: mythmedia.h:21
kDBColumns
static constexpr const char * kDBColumns
Definition: imagemanager.cpp:501
StorageGroup::GetDirList
QStringList GetDirList(void) const
Definition: storagegroup.h:23
ImageManagerFe::SetCover
QString SetCover(int parent, int cover)
Set image to use as a cover thumbnail(s)
Definition: imagemanager.cpp:2124
ImageMetaData::FromPicture
static ImageMetaData * FromPicture(const QString &filePath)
Factory to retrieve metadata from pictures.
Definition: imagemetadata.cpp:700
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
ImageItem::IsLocalId
static bool IsLocalId(int id)
Determine image type (local/remote) from its id. Root/Gallery is remote.
Definition: imagetypes.h:122
ImageItem::m_orientation
int m_orientation
Image orientation.
Definition: imagetypes.h:101
ImageItem::m_baseName
QString m_baseName
File/Dir name with extension (no path)
Definition: imagetypes.h:92
MediaMonitor
Definition: mediamonitor.h:45
kSortByNameDesc
@ kSortByNameDesc
Name Z-A.
Definition: imagetypes.h:47
ImageList
QVector< ImagePtr > ImageList
Definition: imagetypes.h:160
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:916
DeviceManager::DeviceMount
QString DeviceMount(int devId) const
Get path at which the device is mounted.
Definition: imagemanager.cpp:134
ImageManagerFe::CreateImport
QString CreateImport()
Definition: imagemanager.cpp:2510
ImageItem::IsLocalParent
static bool IsLocalParent(int id)
Parents of locals are locals or root.
Definition: imagetypes.h:124
kDirRequestPriority
@ kDirRequestPriority
Client request to display a directory thumbnail.
Definition: imagethumbs.h:35
ImageHandler::RemoveFiles
void RemoveFiles(ImageList &images) const
Deletes images and dirs from the filesystem.
Definition: imagemanager.cpp:1702
ImageAdapterBase::GetAbsThumbPath
static QString GetAbsThumbPath(const QString &devPath, const QString &path)
Get absolute filepath for thumbnail of an image.
Definition: imagemanager.h:148
ImageMetaData::GetAllTags
virtual QStringList GetAllTags()=0
ImageDbReader::GetDescendantCount
void GetDescendantCount(int id, int &dirs, int &pics, int &videos, int &sizeKb) const
Return counts of dirs, pics and videos in the subtree of a dir. Also dir size.
Definition: imagemanager.cpp:1910
MythCoreContext::GetBoolSetting
bool GetBoolSetting(const QString &key, bool defaultval=false)
Definition: mythcorecontext.cpp:910
Device::m_present
bool m_present
True when gallery UI is running & device is useable. Always true for imports.
Definition: imagemanager.cpp:115
FileAssociations::getFileAssociation
static FileAssociations & getFileAssociation()
Definition: dbaccess.cpp:836
mthreadpool.h
Device::m_dir
QTemporaryDir * m_dir
Dir path of images: import devices only.
Definition: imagemanager.cpp:120
ImageHandler::HandleScanRequest
QStringList HandleScanRequest(const QString &command, int devId=DEVICE_INVALID) const
Process scan requests.
Definition: imagemanager.cpp:1624
ImageHandler::HandleDirs
QStringList HandleDirs(const QString &destId, bool rescan, const QStringList &relPaths) const
Creates new image directories.
Definition: imagemanager.cpp:1525
ImageManagerFe::MoveDbImages
QString MoveDbImages(const ImagePtrK &destDir, ImageListK &images, const QString &srcPath)
Moves database images (but not the files themselves).
Definition: imagemanager.cpp:2270
ImageAdapterBase::m_dirFilter
QDir m_dirFilter
A pre-configured dir for reading image/video files.
Definition: imagemanager.h:182
ImagePtr
QSharedPointer< ImageItem > ImagePtr
Definition: imagetypes.h:159
MythDate::kAddYear
@ kAddYear
Add year to string if not included.
Definition: mythdate.h:25
ImageManagerFe
The image manager for use by Frontends.
Definition: imagemanager.h:463
StorageGroup::FindNextDirMostFree
QString FindNextDirMostFree(void)
Definition: storagegroup.cpp:666
ImageDbReader::m_fileOrder
int m_fileOrder
Display ordering of pics/videos.
Definition: imagemanager.h:448
ImageDbReader::m_remote
ImageDbSg * m_remote
Remote database access.
Definition: imagemanager.h:445
ImageItem
Represents a picture, video or directory.
Definition: imagetypes.h:68
ImageDbLocal::ImageDbLocal
ImageDbLocal()
Local database constructor.
Definition: imagemanager.cpp:1066
Device::~Device
~Device()
Delete device, its thumbnails and any imported images.
Definition: imagemanager.cpp:49
MediaMonitor::EjectMedia
void EjectMedia(const QString &path)
Definition: mediamonitor.cpp:265
TEMP_SUBDIR
static constexpr const char * TEMP_SUBDIR
Definition: imagemanager.h:67
DeviceManager::LocateMount
int LocateMount(const QString &mount) const
Find the id of a device.
Definition: imagemanager.cpp:241
kSortByDateDesc
@ kSortByDateDesc
Exif date Latest -> Earliest.
Definition: imagetypes.h:55
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:888
Device::Device
Device(QString name, QString mount, MythMediaDevice *media=nullptr, QTemporaryDir *import=nullptr)
Definition: imagemanager.cpp:38
ImageHandler::HandleIgnore
QStringList HandleIgnore(const QString &exclusions) const
Updates exclusion list for images.
Definition: imagemanager.cpp:1604
DeviceManager::OpenDevice
int OpenDevice(const QString &name, const QString &mount, MythMediaDevice *media=nullptr, QTemporaryDir *dir=nullptr)
Define a new device and assign it a unique id. If the device is already known, its existing id is ret...
Definition: imagemanager.cpp:162
ImageDb::SetCover
bool SetCover(int dir, int id) const
Set the thumbnail(s) to be used for a dir.
Definition: imagemanager.cpp:930
ImageIdList
QList< int > ImageIdList
Definition: imagetypes.h:60
ImageAdapterBase::ThumbPath
static QString ThumbPath(const ImageItem &im)
Thumbnails of videos are a JPEG snapshot with jpg suffix appended.
Definition: imagemanager.h:155
ImageDb::ReadImages
int ReadImages(ImageList &dirs, ImageList &files, const QString &selector) const
Read selected database images/dirs.
Definition: imagemanager.cpp:980
ImageManagerFe::CrumbName
QString CrumbName(ImageItemK &im, bool getPath=false) const
Return a displayable name (with optional path) for an image.
Definition: imagemanager.cpp:2388
EXIF_MYTH_HOST
static constexpr const char * EXIF_MYTH_HOST
Definition: imagemetadata.h:38
ImageItem::m_parentId
int m_parentId
Id of parent dir.
Definition: imagetypes.h:96
MEDIATYPE_MGALLERY
@ MEDIATYPE_MGALLERY
Definition: mythmedia.h:33
ImageDb::ClearDb
void ClearDb(int devId, const QString &action)
Clear Db for device & remove device.
Definition: imagemanager.cpp:737
THUMBNAIL_SUBDIR
static constexpr const char * THUMBNAIL_SUBDIR
Definition: imagemanager.h:69
PHOTO_DB_ID
static constexpr int PHOTO_DB_ID
Definition: imagetypes.h:29
MEDIATYPE_DATA
@ MEDIATYPE_DATA
Definition: mythmedia.h:26
StringPair
QPair< QString, QString > StringPair
Definition: imagetypes.h:61
ImageDbReader::GetChildren
int GetChildren(int id, ImageList &files, ImageList &dirs) const
Return (local or remote) images that are direct children of a dir.
Definition: imagemanager.cpp:1855
MythMediaDevice::getMediaType
MythMediaType getMediaType() const
Definition: mythmedia.h:91
ImageAdapterSg::GetAbsFilePath
QString GetAbsFilePath(const ImagePtrK &im) const
Get absolute filepath for a remote image.
Definition: imagemanager.cpp:491
build_compdb.action
action
Definition: build_compdb.py:9
ImageDbReader::m_dirOrder
int m_dirOrder
Display ordering of dirs.
Definition: imagemanager.h:447
ImageManagerBe::getInstance
static ImageManagerBe * getInstance()
Get Backend Gallery.
Definition: imagemanager.cpp:1944
ImageDb::GetDirectory
int GetDirectory(int id, ImagePtr &parent, ImageList &files, ImageList &dirs, const QString &refine) const
Read a dir and its immediate children from Db.
Definition: imagemanager.cpp:595
DeviceManager::CloseDevices
QStringList CloseDevices(int devId, const QString &action)
Remove a device (or all devices)
Definition: imagemanager.cpp:198
ImageAdapterLocal::Notify
static void Notify(const QString &mesg, const QStringList &extra)
Send local message to UI about local ids.
Definition: imagemanager.cpp:398
ImageDb::RemoveFromDB
QStringList RemoveFromDB(const ImageList &imList) const
Remove images/dirs from database.
Definition: imagemanager.cpp:874
ImageDb::ReadAllImages
bool ReadAllImages(ImageHash &files, ImageHash &dirs) const
Read all database images and dirs as map. No filters or ordering applied.
Definition: imagemanager.cpp:706
ImageDbLocal::CreateTable
bool CreateTable()
Create local database table, if it doesn't exist.
Definition: imagemanager.cpp:1091
MediaMonitor::ValidateAndLock
bool ValidateAndLock(MythMediaDevice *pMedia)
Validates the MythMediaDevice and increments its reference count.
Definition: mediamonitor.cpp:488
MythDate::kDateFull
@ kDateFull
Default local time.
Definition: mythdate.h:19
DeviceManager::GetAbsentees
QList< int > GetAbsentees()
Get list of mountpoints for non-import devices.
Definition: imagemanager.cpp:269
kSortByExtDesc
@ kSortByExtDesc
Extension Z-A.
Definition: imagetypes.h:51
ImageDbReader::SetRefinementClause
void SetRefinementClause()
Sets filter/ordering SQL clause used when reading database according to current filter/sort settings.
Definition: imagemanager.cpp:1755
kSortBySizeDesc
@ kSortBySizeDesc
File size Largest -> Smallest.
Definition: imagetypes.h:53
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:842
ImageItem::m_userThumbnail
int m_userThumbnail
Id of thumbnail to use as cover (dirs only)
Definition: imagetypes.h:106
ImageHandler::HandleDelete
QStringList HandleDelete(const QString &ids) const
Deletes images/dirs.
Definition: imagemanager.cpp:1287
ImageItem::IsDevice
bool IsDevice() const
Definition: imagetypes.h:116
ImageAdapterSg::GetScanDirs
StringMap GetScanDirs() const
Returns SG dirs.
Definition: imagemanager.cpp:474
MythMediaDevice
Definition: mythmedia.h:48
ImageItem::m_date
std::chrono::seconds m_date
Image creation date, from Exif metadata.
Definition: imagetypes.h:100
ImageManagerFe::DeleteFiles
QString DeleteFiles(const ImageIdList &ids)
Delete images.
Definition: imagemanager.cpp:2297
ReadMetaThread::ReadMetaThread
ReadMetaThread(ImagePtrK im, QString path)
Definition: imagemanager.cpp:1126
ImageDb< ImageAdapterLocal >::m_table
QString m_table
Db table name.
Definition: imagemanager.h:317
Device::setPresent
void setPresent(MythMediaDevice *media)
Definition: imagemanager.cpp:112
ImageDb::GetChildren
int GetChildren(const QString &ids, ImageList &files, ImageList &dirs, const QString &refine="") const
Read immediate children of a dir.
Definition: imagemanager.cpp:577
ReadMetaThread::m_path
QString m_path
Definition: imagemanager.cpp:1167
ImageDb
Database API.
Definition: imagemanager.h:281
ImageItem::m_extension
QString m_extension
Image file extension.
Definition: imagetypes.h:94
MythDate::kTime
@ kTime
Default local time.
Definition: mythdate.h:22
GALLERY_DB_ID
static constexpr int GALLERY_DB_ID
Definition: imagetypes.h:27
ImageAdapterSg::CreateItem
ImageItem * CreateItem(const QFileInfo &fi, int parentId, int devId, const QString &base) const
Construct a remote image from a file.
Definition: imagemanager.cpp:414
ImageManagerBe
The image manager to be used by the Backend.
Definition: imagemanager.h:385
ImageDb::GetDescendants
bool GetDescendants(const QString &ids, ImageList &files, ImageList &dirs) const
Return images and all of their descendants.
Definition: imagemanager.cpp:637
ImageManagerFe::RequestMetaData
void RequestMetaData(int id)
Requests all exif/ffmpeg tags for an image, which returns by event.
Definition: imagemanager.cpp:2144
MThreadPool::globalInstance
static MThreadPool * globalInstance(void)
Definition: mthreadpool.cpp:307
kPicOnly
@ kPicOnly
Hide videos.
Definition: imagemanager.h:79
DeviceManager::m_devices
DeviceMap m_devices
Device store.
Definition: imagemanager.h:119
kVideoOnly
@ kVideoOnly
Hide pictures.
Definition: imagemanager.h:80
ImageDb::GetDescendantCount
void GetDescendantCount(int id, bool all, int &dirs, int &pics, int &videos, int &sizeKb) const
Return counts of dirs, pics, videos and size in the subtree of a dir.
Definition: imagemanager.cpp:1015
ImageAdapterBase::GetImageType
ImageNodeType GetImageType(const QString &ext) const
Determine file type from its extension.
Definition: imagemanager.h:168
ImageManagerFe::ScanQuery
static QStringList ScanQuery()
Returns storage group scanner status.
Definition: imagemanager.cpp:2041
MythCoreContext::SaveSettingOnHost
bool SaveSettingOnHost(const QString &key, const QString &newValue, const QString &host)
Definition: mythcorecontext.cpp:895
ImageManagerFe::RenameFile
QString RenameFile(const ImagePtrK &im, const QString &name)
Rename an image.
Definition: imagemanager.cpp:2206
MythMediaDevice::getVolumeID
const QString & getVolumeID() const
Definition: mythmedia.h:72
Device::m_name
QString m_name
Device model/volume/id.
Definition: imagemanager.cpp:116
ImageManagerFe::ShortDateOf
QString ShortDateOf(const ImagePtrK &im) const
Return a short datestamp for thumbnail captions.
Definition: imagemanager.cpp:2355
ImageHandler::HandleCreateThumbnails
QStringList HandleCreateThumbnails(const QStringList &message) const
Creates thumbnails on-demand.
Definition: imagemanager.cpp:1670
ReadMetaThread::m_im
ImagePtrK m_im
Definition: imagemanager.cpp:1166
ImageAdapterBase::m_imageFileExt
QStringList m_imageFileExt
List of file extensions recognised as pictures.
Definition: imagemanager.h:184
ImageHandler::HandleHide
QStringList HandleHide(bool hide, const QString &ids) const
Hides/unhides images/dirs.
Definition: imagemanager.cpp:1456
STORAGE_GROUP_MOUNT
static constexpr const char * STORAGE_GROUP_MOUNT
Definition: imagemanager.cpp:17
Orientation
Encapsulates Exif orientation processing.
Definition: imagemetadata.h:62
MThreadPool::start
void start(QRunnable *runnable, const QString &debugName, int priority=0)
Definition: mthreadpool.cpp:342
ImageItem::m_size
int m_size
Filesize (files only)
Definition: imagetypes.h:99
DEVICE_INVALID
static constexpr int DEVICE_INVALID
Definition: imagemanager.h:71
uint
unsigned int uint
Definition: freesurround.h:24
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:902
ImageAdapterBase::SupportedVideos
static QStringList SupportedVideos()
Return recognised video extensions.
Definition: imagemanager.cpp:325
ReadMetaThread::run
void run() override
Definition: imagemanager.cpp:1129
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:837
EXIF_MYTH_PATH
static constexpr const char * EXIF_MYTH_PATH
Definition: imagemetadata.h:39
EXIF_MYTH_SIZE
static constexpr const char * EXIF_MYTH_SIZE
Definition: imagemetadata.h:41
kSortByModTimeDesc
@ kSortByModTimeDesc
File modified time Latest -> Earliest.
Definition: imagetypes.h:49
ImageItem::m_filePath
QString m_filePath
Absolute for local images. Usually SG-relative for remotes.
Definition: imagetypes.h:93
build_compdb.paths
paths
Definition: build_compdb.py:13
ImageManagerFe::DetectLocalDevices
bool DetectLocalDevices()
Detect and scan local devices.
Definition: imagemanager.cpp:2424