MythTV  master
gallerythumbview.cpp
Go to the documentation of this file.
1 // C++
2 #include <chrono> // for milliseconds
3 #include <thread> // for sleep_for
4 #include <utility>
5 
6 // Qt
7 #include <QApplication>
8 
9 // MythTV
10 #include "libmythbase/compat.h"
12 #include "libmythbase/remotefile.h"
16 #include "libmythui/mythuitext.h"
17 
18 // MythFrontend
19 #include "galleryconfig.h"
20 #include "gallerythumbview.h"
21 
22 #define LOC QString("Thumbview: ")
23 
24 // EXIF tag 0x9286 UserComment can contain garbage
25 static QString clean_comment(const QString &comment)
26 {
27  QString result;
28  std::copy_if(comment.cbegin(), comment.cend(), std::back_inserter(result), [](QChar x) { return x.isPrint(); } );
29  return result;
30 }
31 
33 class ShellThread: public MThread
34 {
35 public:
36  ShellThread(QString cmd, QString path)
37  : MThread("Import"), m_command(std::move(cmd)), m_path(std::move(path)) {}
38 
39  int GetResult(void) const { return m_result; }
40 
41  void run() override // MThread
42  {
43  RunProlog();
44 
45  QString cmd = QString("cd %1 && %2").arg(m_path, m_command);
46  LOG(VB_GENERAL, LOG_INFO, QString("Executing \"%1\"").arg(cmd));
47 
48  m_result = myth_system(cmd);
49 
50  LOG(VB_GENERAL, LOG_INFO, QString(" ...with result %1").arg(m_result));
51 
52  RunEpilog();
53  }
54 
55 private:
56  int m_result {0};
57  QString m_command;
58  QString m_path;
59 };
60 
61 
63 class TransferThread : public MThread
64 {
65  Q_DECLARE_TR_FUNCTIONS(FileTransferWorker);
66 public:
67  using TransferMap = QMap<ImagePtrK, QString>;
68  using ImageSet = QSet<ImagePtrK>;
69 
70  TransferThread(TransferMap files, bool move, MythUIProgressDialog *dialog)
71  : MThread("FileTransfer"),
72  m_move(move), m_files(std::move(files)), m_dialog(dialog) {}
73 
74  ImageSet GetResult(void) { return m_failed; }
75 
76  void run() override // MThread
77  {
78  RunProlog();
79 
80  QString action = m_move ? tr("Moving") : tr("Copying");
81 
82  // Sum file sizes
83  auto keys = m_files.keys();
84  auto add_size = [](int t, const ImagePtrK & im){ return t + im->m_size; };
85  int total = std::accumulate(keys.cbegin(), keys.cend(), 0, add_size);
86 
87  int progressSize = 0;
88 #if QT_VERSION < QT_VERSION_CHECK(5,15,0)
89  for (auto it = m_files.constKeyValueBegin();
90  it != m_files.constKeyValueEnd(); it++)
91  {
92  const ImagePtrK & im = (*it).first;
93  QString newPath = (*it).second;
94 #else
95  for (auto it = m_files.constKeyValueBegin();
96  it != m_files.constKeyValueEnd(); it++)
97  {
98  const ImagePtrK & im = it->first;
99  QString newPath = it->second;
100 #endif
101  // Update progress dialog
102  if (m_dialog)
103  {
104  QString message = QString("%1 %2\n%3")
105  .arg(action, QFileInfo(im->m_url).fileName(),
106  ImageAdapterBase::FormatSize(im->m_size / 1024));
107 
108  auto *pue = new ProgressUpdateEvent(progressSize, total, message);
109  QApplication::postEvent(m_dialog, pue);
110  }
111 
112  LOG(VB_FILE, LOG_INFO, QString("%2 %3 -> %4")
113  .arg(action, im->m_url, newPath));
114 
115  bool success = m_move ? RemoteFile::MoveFile(im->m_url, newPath)
116  : RemoteFile::CopyFile(im->m_url, newPath,
117  false, true);
118  if (!success)
119  {
120  // Flag failures
121  m_failed.insert(im);
122 
123  LOG(VB_GENERAL, LOG_ERR,
124  QString("%1: Failed to copy/move %2 -> %3")
125  .arg(objectName(), im->m_url, m_files[im]));
126  }
127 
128  progressSize += im->m_size;
129  }
130 
131  // Update progress dialog
132  if (m_dialog)
133  {
134  auto *pue =
135  new ProgressUpdateEvent(progressSize, total, tr("Complete"));
136  QApplication::postEvent(m_dialog, pue);
137  }
138 
139  RunEpilog();
140  }
141 
142 private:
143  bool m_move;
147 };
148 
149 
154 static void WaitUntilDone(MThread &worker)
155 {
156  worker.start();
157  while (!worker.isFinished())
158  {
159  std::this_thread::sleep_for(1ms);
160  QCoreApplication::processEvents();
161  }
162 }
163 
164 
171  : MythScreenType(parent, name),
172  m_popupStack(*GetMythMainWindow()->GetStack("popup stack")),
173  m_mgr(ImageManagerFe::getInstance()),
174  // This screen uses a single fixed view (Parent dir, ordered dirs, ordered images)
175  m_view(new DirectoryView(kOrdered)),
176  m_infoList(*this),
177  // Start in edit mode unless a password exists
178  m_editsAllowed(gCoreContext->GetSetting("GalleryPassword").isEmpty())
179 {
180  // Hide hidden when edits disallowed
181  if (!m_editsAllowed)
182  m_mgr.SetVisibility(false);
183 }
184 
185 
190 {
191  LOG(VB_GUI, LOG_DEBUG, LOC + "Exiting Gallery");
192  delete m_view;
193 }
194 
195 
200 {
201  LOG(VB_GUI, LOG_DEBUG, LOC + "Closing Gallery");
202 
204 
205  // Cleanup local devices
207 
208  // Cleanup view
209  m_view->Clear();
210 
212 }
213 
214 
219 {
220  if (!LoadWindowFromXML("image-ui.xml", "gallery", this))
221  return false;
222 
223  // Determine zoom levels supported by theme
224  // images0 must exist; images1, images2 etc. are optional and enable zoom
225  int zoom = 0;
226  MythUIButtonList *widget = nullptr;
227  do
228  {
229  QString name = QString("images%1").arg(zoom++);
230  widget = dynamic_cast<MythUIButtonList *>(this->GetChild(name));
231  if (widget)
232  {
233  m_zoomWidgets.append(widget);
234  widget->SetVisible(false);
235  }
236  }
237  while (widget);
238 
239  if (m_zoomWidgets.isEmpty())
240  {
241  LOG(VB_GENERAL, LOG_ERR, LOC + "Screen 'Gallery' is missing 'images0'");
242  return false;
243  }
244  LOG(VB_GUI, LOG_DEBUG, LOC + QString("Screen 'Gallery' found %1 zoom levels")
245  .arg(m_zoomWidgets.size()));
246 
247  // File details list is managed elsewhere
248  if (!m_infoList.Create(false))
249  {
250  LOG(VB_GENERAL, LOG_ERR, LOC + "Cannot load 'Info buttonlist'");
251  return false;
252  }
253 
254  UIUtilW::Assign(this, m_captionText, "caption");
255  UIUtilW::Assign(this, m_emptyText, "noimages");
256  UIUtilW::Assign(this, m_positionText, "position");
257  UIUtilW::Assign(this, m_crumbsText, "breadcrumbs");
258  UIUtilW::Assign(this, m_hideFilterText, "hidefilter");
259  UIUtilW::Assign(this, m_typeFilterText, "typefilter");
260  UIUtilW::Assign(this, m_scanProgressText, "scanprogresstext");
261  UIUtilW::Assign(this, m_scanProgressBar, "scanprogressbar");
262 
263  if (m_scanProgressText)
265  if (m_scanProgressBar)
267 
268  BuildFocusList();
269 
270  // Initialise list widget with appropriate zoom level for this theme.
271  m_zoomLevel = gCoreContext->GetNumSetting("GalleryZoomLevel", 0);
272  SelectZoomWidget(0);
273 
274  return true;
275 }
276 
277 
282 bool GalleryThumbView::keyPressEvent(QKeyEvent *event)
283 {
284  if (GetFocusWidget()->keyPressEvent(event))
285  return true;
286 
287  QStringList actions;
288  bool handled = GetMythMainWindow()->TranslateKeyPress("Images", event, actions);
289 
290  for (int i = 0; i < actions.size() && !handled; i++)
291  {
292  QString action = actions[i];
293  handled = true;
294 
295  if (action == "MENU")
296  MenuMain();
297  else if (action == "INFO")
298  ShowDetails();
299  else if (action == "ZOOMIN")
300  ZoomIn();
301  else if (action == "ZOOMOUT")
302  ZoomOut();
303  else if (action == "ROTRIGHT")
304  RotateCW();
305  else if (action == "ROTLEFT")
306  RotateCCW();
307  else if (action == "FLIPHORIZONTAL")
308  FlipHorizontal();
309  else if (action == "FLIPVERTICAL")
310  FlipVertical();
311  else if (action == "COVER")
312  {
313  ImagePtrK im = m_view->GetSelected();
314  if (m_editsAllowed && im)
315  {
316  if (im == m_view->GetParent())
317  {
318  // Reset dir
319  m_mgr.SetCover(im->m_id, 0);
320  }
321  else
322  {
323  // Set parent cover
324  m_mgr.SetCover(im->m_parentId, im->m_id);
325  }
326  }
327  }
328  else if (action == "PLAY")
329  Slideshow();
330  else if (action == "RECURSIVESHOW")
331  {
332  ImagePtrK im = m_view->GetSelected();
333  if (im && im->IsDirectory())
335  }
336  else if (action == "MARK")
337  {
338  ImagePtrK im = m_view->GetSelected();
339  if (m_editsAllowed && im && im != m_view->GetParent())
340  DoMarkItem(!m_view->IsMarked(im->m_id));
341  }
342  else if (action == "ESCAPE" && !GetMythMainWindow()->IsExitingToMain())
343  {
344  // Exit info list, if shown
345  handled = m_infoList.Hide();
346 
347  // Ascend the tree unless parent is root,
348  // or a device and multiple devices/imports exist
349  if (!handled)
350  {
351  ImagePtrK node = m_view->GetParent();
352  if (node && node->m_id != GALLERY_DB_ID
353  && (!node->IsDevice() || m_mgr.DeviceCount() > 0))
354  handled = DirSelectUp();
355  }
356  }
357  else
358  handled = false;
359  }
360 
361  if (!handled)
362  handled = MythScreenType::keyPressEvent(event);
363 
364  return handled;
365 }
366 
367 
372 void GalleryThumbView::customEvent(QEvent *event)
373 {
374 
375  if (event->type() == MythEvent::kMythEventMessage)
376  {
377  auto *me = dynamic_cast<MythEvent *>(event);
378  if (me == nullptr)
379  return;
380 
381  const QString& mesg = me->Message();
382  QStringList extra = me->ExtraDataList();
383 
384  // Internal messages contain a hostname. Ignore other FE messages
385  QStringList token = mesg.split(' ');
386  if (token.size() >= 2 && token[1] != gCoreContext->GetHostName())
387  return;
388 
389  if (token[0] == "IMAGE_METADATA")
390  {
391  int id = extra[0].toInt();
392  ImagePtrK selected = m_view->GetSelected();
393 
394  if (selected && selected->m_id == id)
395  m_infoList.Display(*selected, extra.mid(1));
396  }
397  else if (token[0] == "THUMB_AVAILABLE")
398  {
399  int id = extra[0].toInt();
400 
401  // Note existance of all thumbs
402  m_thumbExists.insert(id);
403 
404  // Get all buttons waiting for this thumbnail
405  QList<ThumbLocation> affected = m_pendingMap.values(id);
406 
407  // Only concerned with thumbnails we've requested
408  if (affected.isEmpty())
409  return;
410 
411  LOG(VB_GENERAL, LOG_DEBUG, LOC +
412  QString("Rx %1 : %2").arg(token[0], extra.join(",")));
413 
414  // Thumb url was cached when request was sent
415  QString url = m_view->GetCachedThumbUrl(id);
416 
417  // Set thumbnail for each button now it exists
418  for (const ThumbLocation & location : qAsConst(affected))
419  {
420  MythUIButtonListItem *button = location.first;
421  int index = location.second;
422 
423  auto im = button->GetData().value<ImagePtrK>();
424  if (im)
425  UpdateThumbnail(button, im, url, index);
426  }
427 
428  // Cancel pending request
429  m_pendingMap.remove(id);
430  }
431  else if (token[0] == "IMAGE_DB_CHANGED")
432  {
433  // Expects csv list of deleted ids, csv list of changed ids
434  LOG(VB_GENERAL, LOG_DEBUG, LOC +
435  QString("Rx %1 : %2").arg(token[0], extra.join(",")));
436 
437  if (!extra.isEmpty())
438  {
439 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
440  QStringList idDeleted =
441  extra[0].split(",", QString::SkipEmptyParts);
442 #else
443  QStringList idDeleted =
444  extra[0].split(",", Qt::SkipEmptyParts);
445 #endif
446 
447  RemoveImages(idDeleted);
448  }
449  if (extra.size() >= 2)
450  {
451 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
452  QStringList idChanged =
453  extra[1].split(",", QString::SkipEmptyParts);
454 #else
455  QStringList idChanged =
456  extra[1].split(",", Qt::SkipEmptyParts);
457 #endif
458  RemoveImages(idChanged, false);
459  }
460 
461  // Refresh display
463  }
464  else if (token[0] == "IMAGE_DEVICE_CHANGED")
465  {
466  // Expects list of url prefixes
467  LOG(VB_GENERAL, LOG_DEBUG, LOC +
468  QString("Rx %1 : %2").arg(token[0], extra.join(",")));
469 
470  // Clear everything. Local devices will be rebuilt
471  m_view->Clear();
472  m_thumbExists.clear();
473 
474  // Remove thumbs & images from image cache using supplied prefixes
475  for (const QString & url : qAsConst(extra))
477 
478  // Refresh display
480  }
481  else if (token[0] == "IMAGE_SCAN_STATUS" && extra.size() == 3)
482  {
483  // Expects scanner id, scanned#, total#
484  UpdateScanProgress(extra[0], extra[1].toInt(), extra[2].toInt());
485  }
486  }
487  else if (event->type() == DialogCompletionEvent::kEventType)
488  {
489  auto *dce = (DialogCompletionEvent *)(event);
490 
491  QString resultid = dce->GetId();
492  int buttonnum = dce->GetResult();
493 
494  if (resultid == "FileRename")
495  {
496  QString newName = dce->GetResultText();
498  {
499  QString err = m_mgr.RenameFile(m_menuState.m_selected,
500  newName);
501  if (!err.isEmpty())
502  ShowOkPopup(err);
503  }
504  }
505  else if (resultid == "MakeDir")
506  {
508  {
509  // Prohibit subtrees
510  QString name = dce->GetResultText();
511  QString err = name.contains("/")
512  ? tr("Invalid Name")
514  QStringList(name));
515  if (!err.isEmpty())
516  ShowOkPopup(err);
517  }
518  }
519  else if (resultid == "SlideOrderMenu")
520  {
521  SlideOrderType slideOrder = kOrdered;
522 
523  switch (buttonnum)
524  {
525  case 0: slideOrder = kOrdered; break;
526  case 1: slideOrder = kShuffle; break;
527  case 2: slideOrder = kRandom; break;
528  case 3: slideOrder = kSeasonal; break;
529  }
530  gCoreContext->SaveSetting("GallerySlideOrder", slideOrder);
531  LOG(VB_FILE, LOG_DEBUG, LOC + QString("Order %1").arg(slideOrder));
532  }
533  else if (resultid == "ImageCaptionMenu")
534  {
535  ImageCaptionType captions = kNoCaption;
536 
537  switch (buttonnum)
538  {
539  case 0: captions = kNameCaption; break;
540  case 1: captions = kDateCaption; break;
541  case 2: captions = kUserCaption; break;
542  case 3: captions = kNoCaption; break;
543  }
544  gCoreContext->SaveSetting("GalleryImageCaption", captions);
545  BuildImageList();
546  }
547  else if (resultid == "DirCaptionMenu")
548  {
549  ImageCaptionType captions = kNoCaption;
550 
551  switch (buttonnum)
552  {
553  case 0: captions = kNameCaption; break;
554  case 1: captions = kDateCaption; break;
555  case 2: captions = kNoCaption; break;
556  }
557  gCoreContext->SaveSetting("GalleryDirCaption", captions);
558  BuildImageList();
559  }
560  else if (resultid == "Password")
561  {
562  QString password = dce->GetResultText();
563  m_editsAllowed = (password == gCoreContext->GetSetting("GalleryPassword"));
564  }
565  else if (buttonnum == 1)
566  {
567  // Confirm current file deletion
568  QString err;
569  if (resultid == "ConfirmDelete" && m_menuState.m_selected)
570  {
572  err = m_mgr.DeleteFiles(ids);
573  }
574  // Confirm marked file deletion
575  else if (resultid == "ConfirmDeleteMarked")
576  {
578  }
579  else
580  return;
581 
582  if (!err.isEmpty())
583  ShowOkPopup(err);
584  }
585  }
586 }
587 
588 
594 void GalleryThumbView::RemoveImages(const QStringList &ids, bool deleted)
595 {
596  for (const QString & id : qAsConst(ids))
597  {
598  // Remove image from view
599  QStringList urls = m_view->RemoveImage(id.toInt(), deleted);
600  // Cleanup url lookup
601  m_thumbExists.remove(id.toInt());
602 
603  // Remove thumbs & images from image cache
604  for (const QString & url : qAsConst(urls))
605  {
606  LOG(VB_FILE, LOG_DEBUG, LOC +
607  QString("Clearing image cache of '%1'").arg(url));
608 
610  }
611  }
612 }
613 
614 
619 {
620  // Detect any running BE scans
621  // Expects OK, scanner id, current#, total#
622  QStringList message = ImageManagerFe::ScanQuery();
623  if (message.size() == 4 && message[0] == "OK")
624  {
625  UpdateScanProgress(message[1], message[2].toInt(), message[3].toInt());
626  }
627 
628  // Only receive events after device/scan status has been established
629  gCoreContext->addListener(this);
630 
631  // Start at Root if devices exist. Otherwise go straight to SG node
633 
634  LoadData(start);
635 }
636 
637 
643 {
645 
646  // Load view for parent directory
647  if (m_view->LoadFromDb(parent))
648  {
649  m_imageList->SetVisible(true);
650  if (m_emptyText)
651  {
652  m_emptyText->SetVisible(false);
653  m_emptyText->Reset();
654  }
655 
656  // Construct the buttonlist
657  BuildImageList();
658  }
659  else
660  {
661  m_infoList.Hide();
662  m_imageList->SetVisible(false);
663  if (m_emptyText)
664  {
665  m_emptyText->SetVisible(true);
666  m_emptyText->SetText(tr("No images found.\n"
667  "Scan storage group using menu,\n"
668  "or insert/mount local media.\n"));
669  }
670  }
671 }
672 
673 
678 {
679  m_imageList->Reset();
680  m_pendingMap.clear();
681 
682  // Get parent & all children
683  ImageListK nodes = m_view->GetAllNodes();
684  ImagePtrK selected = m_view->GetSelected();
685 
686  // go through the entire list and update
687  for (const ImagePtrK & im : qAsConst(nodes))
688  {
689  if (im)
690  {
691  // Data must be set by constructor: First item is automatically
692  // selected and must have data available for selection event, as
693  // subsequent reselection of same item will always fail.
694  auto *item = new MythUIButtonListItem(m_imageList, "",
695  QVariant::fromValue(im));
696 
697  item->setCheckable(true);
698  item->setChecked(MythUIButtonListItem::NotChecked);
699 
700  // assign and display all information about
701  // the current item, like title and subdirectory count
702  UpdateImageItem(item);
703 
704  // Treat parent differently
705  if (im == nodes[0])
706  {
707  // Only non-root parents can ascend
708  if (im->m_id != GALLERY_DB_ID)
709  item->DisplayState("upfolder", "parenttype");
710  }
711  else if (im == selected)
712  // Reinstate the active button item. Note this would fail for parent
714  }
715  }
716 }
717 
718 
724 {
725  auto im = item->GetData().value<ImagePtrK >();
726  if (!im)
727  return;
728 
729  // Allow themes to distinguish between roots, folders, pics, videos
730  switch (im->m_type)
731  {
732  case kDevice:
733  case kCloneDir:
734  case kDirectory:
735  if (im->m_dirCount > 0)
736  {
737  item->SetText(QString("%1/%2")
738  .arg(im->m_fileCount).arg(im->m_dirCount),
739  "childcount");
740  }
741  else
742  {
743  item->SetText(QString::number(im->m_fileCount), "childcount");
744  }
745 
746  item->DisplayState(im->IsDevice() ? "device" : "subfolder", "buttontype");
747  break;
748 
749  case kImageFile:
750  item->DisplayState("image", "buttontype");
751  break;
752 
753  case kVideoFile:
754  item->DisplayState("video", "buttontype");
755  break;
756 
757  default:
758  break;
759  }
760 
761  // Allow theme to distinguish visible/hidden nodes
762  QString hideState = (im->m_isHidden) ? "hidden" : "visible";
763  item->DisplayState(hideState, "buttonstate");
764 
765  // Caption
766  QString text;
768  im->IsFile() ? "GalleryImageCaption"
769  : "GalleryDirCaption");
770  switch (show)
771  {
772  case kNameCaption: text = m_mgr.CrumbName(*im); break;
773  case kDateCaption: text = m_mgr.ShortDateOf(im); break;
774  case kUserCaption: text = clean_comment(im->m_comment); break;
775  default:
776  case kNoCaption: text = ""; break;
777  }
778  item->SetText(text);
779 
780  // Set marked state
782  = m_view->IsMarked(im->m_id)
785 
786  item->setChecked(state);
787 
788  // Thumbnails required
789  ImageIdList request;
790 
791  if (im->m_thumbNails.size() == 1)
792  {
793  // Single thumbnail
794  QString url = CheckThumbnail(item, im, request, 0);
795 
796  if (!url.isEmpty())
797  UpdateThumbnail(item, im, url, 0);
798  }
799  else
800  {
801  // Dir showing up to 4 thumbs. Set them all at same time
802  InfoMap thumbMap;
803  for (int index = 0; index < im->m_thumbNails.size(); ++index)
804  {
805  QString url = CheckThumbnail(item, im, request, index);
806  if (!url.isEmpty())
807  thumbMap.insert(QString("thumbimage%1").arg(index), url);
808  }
809  if (!thumbMap.isEmpty())
810  item->SetImageFromMap(thumbMap);
811  }
812 
813  // Request creation/verification of unknown thumbnails.
814  if (!request.isEmpty())
815  m_mgr.CreateThumbnails(request, im->IsDirectory());
816 }
817 
818 
831  ImageIdList &request, int index)
832 {
833  ThumbPair thumb(im->m_thumbNails.at(index));
834  int id = thumb.first;
835 
836  if (m_thumbExists.contains(id))
837  return thumb.second;
838 
839  // Request BE thumbnail check if it is not already pending
840  if (!m_pendingMap.contains(id))
841  request << id;
842 
843  // Note this button is awaiting an update
844  m_pendingMap.insert(id, qMakePair(item, index));
845 
846  return "";
847 }
848 
849 
858  const ImagePtrK& im, const QString &url,
859  int index)
860 {
861  if (im->m_thumbNails.size() == 1)
862  {
863  // Pics, dirs & videos use separate widgets
864  switch (im->m_type)
865  {
866  case kImageFile: button->SetImage(url); break;
867  case kVideoFile: button->SetImage(url, "videoimage"); break;
868  default: button->SetImage(url, "folderimage"); break;
869  }
870  }
871  else
872  // Dir with 4 thumbnails
873  button->SetImage(url, QString("thumbimage%1").arg(index));
874 }
875 
876 
884 void GalleryThumbView::UpdateScanProgress(const QString &scanner,
885  int current, int total)
886 {
887  // Scan update
888  m_scanProgress.insert(scanner, qMakePair(current, total));
889 
890  // Detect end of this scan
891  if (current >= total)
892  {
893  LOG(VB_GUI, LOG_DEBUG, LOC + QString("Scan Finished %1 %2/%3")
894  .arg(scanner).arg(current).arg(total));
895 
896  // Mark inactive scanner
897  m_scanActive.remove(scanner);
898 
899  // Detect end of last scan
900  if (m_scanActive.isEmpty())
901  {
902  if (m_scanProgressText)
903  {
906  }
907  if (m_scanProgressBar)
908  {
911  }
912 
913  m_scanProgress.clear();
914 
915  return;
916  }
917  }
918  else
919  {
920  // Detect first scan update
921  if (m_scanActive.isEmpty())
922  {
923  // Show progressbar when first scan starts
924  if (m_scanProgressBar)
925  {
928  }
929  if (m_scanProgressText)
931  }
932 
933  if (!m_scanActive.contains(scanner))
934  {
935  LOG(VB_GUI, LOG_DEBUG, LOC + QString("Scan Started %1 %2/%3")
936  .arg(scanner).arg(current).arg(total));
937 
938  // Mark active scanner
939  m_scanActive.insert(scanner);
940  }
941  }
942 
943  // Aggregate all running scans
944  int currentAgg = 0;
945  int totalAgg = 0;
946  for (IntPair scan : qAsConst(m_scanProgress))
947  {
948  currentAgg += scan.first;
949  totalAgg += scan.second;
950  }
951 
952  if (m_scanProgressBar)
953  {
954  m_scanProgressBar->SetUsed(currentAgg);
955  m_scanProgressBar->SetTotal(totalAgg);
956  }
957  if (m_scanProgressText)
958  m_scanProgressText->SetText(tr("%L1 of %L3").arg(currentAgg).arg(totalAgg));
959 }
960 
961 
966 {
967  if (m_positionText)
969 
970  if (m_captionText)
971  m_captionText->Reset();
972 
973  if (m_crumbsText)
974  m_crumbsText->Reset();
975 
976  if (m_hideFilterText)
978 
979  if (m_typeFilterText)
981 }
982 
983 
989 {
990  auto im = item->GetData().value<ImagePtrK >();
991  if (im)
992  {
993  // update the position in the node list
994  m_view->Select(im->m_id);
995 
996  // show the name/path of the image
997  if (m_crumbsText)
998  m_crumbsText->SetText(m_mgr.CrumbName(*im, true));
999 
1000  if (m_captionText)
1001  {
1002  // show the date & comment of non-root nodes
1003  QStringList text;
1004  if (im->m_id != GALLERY_DB_ID)
1005  {
1006  if (im->IsFile() || im->IsDevice())
1007  text << ImageManagerFe::LongDateOf(im);
1008 
1009  QString comment = clean_comment(im->m_comment);
1010  if (!comment.isEmpty())
1011  text << comment;
1012  }
1013  m_captionText->SetText(text.join(" - "));
1014  }
1015 
1016  if (m_hideFilterText)
1017  {
1018  m_hideFilterText->SetText(m_mgr.GetVisibility() ? tr("Hidden") : "");
1019  }
1020 
1021  if (m_typeFilterText)
1022  {
1023  QString text = "";
1024  switch (m_mgr.GetType())
1025  {
1026  case kPicAndVideo : text = ""; break;
1027  case kPicOnly : text = tr("Pictures"); break;
1028  case kVideoOnly : text = tr("Videos"); break;
1029  }
1030  m_typeFilterText->SetText(text);
1031  }
1032 
1033  // show the position of the image
1034  if (m_positionText)
1036 
1037  // Update any file details information
1038  m_infoList.Update(im);
1039  }
1040 }
1041 
1042 
1047 {
1048  // Create the main menu
1049  auto *menu = new MythMenu(tr("Gallery Options"), this, "mainmenu");
1050 
1051  // Menu options depend on the marked files and the current node
1053 
1054  if (m_menuState.m_selected)
1055  {
1056  if (m_editsAllowed)
1057  {
1058  MenuMarked(menu);
1059  MenuPaste(menu);
1061  MenuAction(menu);
1062  }
1064  MenuShow(menu);
1065  if (!m_editsAllowed)
1066  menu->AddItem(tr("Enable Edits"), &GalleryThumbView::ShowPassword);
1067  }
1068 
1069  // Depends on current status of backend scanner - string(number(isBackend()))
1070  if (m_scanActive.contains("1"))
1071  menu->AddItem(tr("Stop Scan"), &GalleryThumbView::StopScan);
1072  else
1073  menu->AddItem(tr("Scan Storage Group"), &GalleryThumbView::StartScan);
1074 
1075  menu->AddItem(tr("Settings"), &GalleryThumbView::ShowSettings);
1076 
1077  auto *popup = new MythDialogBox(menu, &m_popupStack, "menuPopup");
1078  if (popup->Create())
1079  m_popupStack.AddScreen(popup);
1080  else
1081  delete popup;
1082 }
1083 
1084 
1090 {
1091  ImagePtrK parent = m_view->GetParent();
1092 
1093  if (m_menuState.m_childCount == 0 || parent.isNull())
1094  return;
1095 
1096  QString title = tr("%L1 marked").arg(m_menuState.m_markedId.size());
1097  auto *menu = new MythMenu(title, this, "markmenu");
1098 
1099  // Mark/unmark selected
1100  if (m_menuState.m_selected->IsFile())
1101  {
1103  menu->AddItem(tr("Unmark File"), &GalleryThumbView::UnmarkItem);
1104  else
1105  menu->AddItem(tr("Mark File"), &GalleryThumbView::MarkItem);
1106  }
1107  // Cannot mark/unmark parent dir from this level
1108  else if (!m_menuState.m_selected->IsDevice()
1109  && m_menuState.m_selected != parent)
1110  {
1112  menu->AddItem(tr("Unmark Directory"), &GalleryThumbView::UnmarkItem);
1113  else
1114  menu->AddItem(tr("Mark Directory"), &GalleryThumbView::MarkItem);
1115  }
1116 
1117  if (parent->m_id != GALLERY_DB_ID)
1118  {
1119  // Mark All if unmarked files exist
1121  menu->AddItem(tr("Mark All"), &GalleryThumbView::MarkAll);
1122 
1123  // Unmark All if marked files exist
1124  if (!m_menuState.m_markedId.isEmpty())
1125  {
1126  menu->AddItem(tr("Unmark All"), &GalleryThumbView::UnmarkAll);
1127  menu->AddItem(tr("Invert Marked"), &GalleryThumbView::MarkInvertAll);
1128  }
1129  }
1130 
1131  if (menu->IsEmpty())
1132  delete menu;
1133  else
1134  mainMenu->AddItem(tr("Mark"), nullptr, menu);
1135 }
1136 
1137 
1143 {
1144  // Can only copy/move into non-root dirs
1145  if (m_menuState.m_selected->IsDirectory()
1146  && m_menuState.m_selected->m_id != GALLERY_DB_ID)
1147  {
1148  // Operate on current marked files, if any
1150  if (files.isEmpty())
1151  files = m_menuState.m_prevMarkedId;
1152  if (files.isEmpty())
1153  return;
1154 
1155  QString title = tr("%L1 marked").arg(files.size());
1156 
1157  auto *menu = new MythMenu(title, this, "pastemenu");
1158 
1159  menu->AddItem(tr("Move Marked Into"), &GalleryThumbView::Move);
1160  menu->AddItem(tr("Copy Marked Into"), qOverload<>(&GalleryThumbView::Copy));
1161 
1162  mainMenu->AddItem(tr("Paste"), nullptr, menu);
1163  }
1164 }
1165 
1166 
1172 {
1173  // Operate on marked files, if any, otherwise selected node
1174  if (!m_menuState.m_markedId.isEmpty())
1175  {
1176  QString title = tr("%L1 marked").arg(m_menuState.m_markedId.size());
1177 
1178  auto *menu = new MythMenu(title, this, "");
1179 
1180  menu->AddItem(tr("Rotate Marked CW"), &GalleryThumbView::RotateCWMarked);
1181  menu->AddItem(tr("Rotate Marked CCW"), &GalleryThumbView::RotateCCWMarked);
1182  menu->AddItem(tr("Flip Marked Horizontal"), &GalleryThumbView::FlipHorizontalMarked);
1183  menu->AddItem(tr("Flip Marked Vertical"), &GalleryThumbView::FlipVerticalMarked);
1184  menu->AddItem(tr("Reset Marked to Exif"), &GalleryThumbView::ResetExifMarked);
1185 
1186  mainMenu->AddItem(tr("Transforms"), nullptr, menu);
1187  }
1188  else if (m_menuState.m_selected->IsFile())
1189  {
1190  auto *menu = new MythMenu(m_menuState.m_selected->m_baseName, this, "");
1191 
1192  menu->AddItem(tr("Rotate CW"), &GalleryThumbView::RotateCW);
1193  menu->AddItem(tr("Rotate CCW"), &GalleryThumbView::RotateCCW);
1194  menu->AddItem(tr("Flip Horizontal"), &GalleryThumbView::FlipHorizontal);
1195  menu->AddItem(tr("Flip Vertical"), &GalleryThumbView::FlipVertical);
1196  menu->AddItem(tr("Reset to Exif"), &GalleryThumbView::ResetExif);
1197 
1198  mainMenu->AddItem(tr("Transforms"), nullptr, menu);
1199  }
1200 }
1201 
1202 
1208 {
1209  MythMenu *menu = nullptr;
1210  ImagePtrK selected = m_menuState.m_selected;
1211 
1212  // Operate on current marked files, if any
1213  if (!m_menuState.m_markedId.empty())
1214  {
1215  QString title = tr("%L1 marked").arg(m_menuState.m_markedId.size());
1216 
1217  menu = new MythMenu(title, this, "actionmenu");
1218 
1219  // Only offer Hide/Unhide if relevant
1221  menu->AddItem(tr("Hide Marked"), &GalleryThumbView::HideMarked);
1223  menu->AddItem(tr("Unhide Marked"), &GalleryThumbView::UnhideMarked);
1224 
1225  menu->AddItem(tr("Delete Marked"), &GalleryThumbView::DeleteMarked);
1226  }
1227  else
1228  {
1229  // Operate on selected file/dir
1230  menu = new MythMenu(selected->m_baseName, this, "actionmenu");
1231 
1232  // Prohibit actions on devices and parent dirs
1233  if (!selected->IsDevice() && selected != m_view->GetParent())
1234  {
1235  if (selected->m_isHidden)
1236  menu->AddItem(tr("Unhide"), &GalleryThumbView::Unhide);
1237  else
1238  menu->AddItem(tr("Hide"), &GalleryThumbView::HideItem);
1239 
1240  menu->AddItem(tr("Use as Cover"), &GalleryThumbView::SetCover);
1241  menu->AddItem(tr("Delete"), &GalleryThumbView::DeleteItem);
1242  menu->AddItem(tr("Rename"), &GalleryThumbView::ShowRenameInput);
1243  }
1244  else if (selected->m_userThumbnail)
1245  menu->AddItem(tr("Reset Cover"), &GalleryThumbView::ResetCover);
1246  }
1247 
1248  // Can only mkdir in a non-root dir
1249  if (selected->IsDirectory()
1250  && selected->m_id != GALLERY_DB_ID)
1251  menu->AddItem(tr("Create Directory"), &GalleryThumbView::MakeDir);
1252 
1253  // Only show import command on root, when defined
1254  if (selected->m_id == GALLERY_DB_ID
1255  && !gCoreContext->GetSetting("GalleryImportCmd").isEmpty())
1256  menu->AddItem(tr("Import"), &GalleryThumbView::Import);
1257 
1258  // Only show eject when devices (excluding import) exist
1259  if (selected->IsDevice() && selected->IsLocal())
1260  menu->AddItem(tr("Eject media"), &GalleryThumbView::Eject);
1261 
1262  if (menu->IsEmpty())
1263  delete menu;
1264  else
1265  mainMenu->AddItem(tr("Actions"), nullptr, menu);
1266 }
1267 
1268 
1274 {
1275  int order = gCoreContext->GetNumSetting("GallerySlideOrder", kOrdered);
1276 
1277  QString ordering;
1278  switch (order)
1279  {
1280  case kShuffle : ordering = tr("Shuffled"); break;
1281  case kRandom : ordering = tr("Random"); break;
1282  case kSeasonal : ordering = tr("Seasonal"); break;
1283  default:
1284  case kOrdered : ordering = tr("Ordered"); break;
1285  }
1286 
1287  auto *menu = new MythMenu(tr("Slideshow") + " (" + ordering + ")",
1288  this, "SlideshowMenu");
1289 
1290  // Use selected dir or parent, if image selected
1291  if (m_menuState.m_selected->IsDirectory())
1292  {
1293  if (m_menuState.m_selected->m_fileCount > 0)
1294  menu->AddItem(tr("Directory"), &GalleryThumbView::Slideshow);
1295 
1296  if (m_menuState.m_selected->m_dirCount > 0)
1297  menu->AddItem(tr("Recursive"), &GalleryThumbView::RecursiveSlideshow);
1298  }
1299  else
1300  menu->AddItem(tr("Current Directory"), &GalleryThumbView::Slideshow);
1301 
1302  auto *orderMenu = new MythMenu(tr("Slideshow Order"), this, "SlideOrderMenu");
1303 
1304  orderMenu->AddItem(tr("Ordered"), nullptr, nullptr, order == kOrdered);
1305  orderMenu->AddItem(tr("Shuffled"), nullptr, nullptr, order == kShuffle);
1306  orderMenu->AddItem(tr("Random"), nullptr, nullptr, order == kRandom);
1307  orderMenu->AddItem(tr("Seasonal"), nullptr, nullptr, order == kSeasonal);
1308 
1309  menu->AddItem(tr("Change Order"), nullptr, orderMenu);
1310 
1311  if (gCoreContext->GetBoolSetting("GalleryRepeat", false))
1312  menu->AddItem(tr("Turn Repeat Off"), &GalleryThumbView::RepeatOff);
1313  else
1314  menu->AddItem(tr("Turn Repeat On"), &GalleryThumbView::RepeatOn);
1315 
1316  mainMenu->AddItem(tr("Slideshow"), nullptr, menu);
1317 }
1318 
1319 
1325 {
1326  auto *menu = new MythMenu(tr("Show Options"), this, "showmenu");
1327 
1328  int type = m_mgr.GetType();
1329  if (type == kPicAndVideo)
1330  {
1331  menu->AddItem(tr("Hide Pictures"), &GalleryThumbView::HidePictures);
1332  menu->AddItem(tr("Hide Videos"), &GalleryThumbView::HideVideos);
1333  }
1334  else
1335  menu->AddItem(type == kPicOnly ? tr("Show Videos") : tr("Show Pictures"),
1337 
1338  int show = gCoreContext->GetNumSetting("GalleryImageCaption");
1339  auto *captionMenu = new MythMenu(tr("Image Captions"), this,
1340  "ImageCaptionMenu");
1341 
1342  captionMenu->AddItem(tr("Name"), nullptr, nullptr, show == kNameCaption);
1343  captionMenu->AddItem(tr("Date"), nullptr, nullptr, show == kDateCaption);
1344  captionMenu->AddItem(tr("Comment"), nullptr, nullptr, show == kUserCaption);
1345  captionMenu->AddItem(tr("None"), nullptr, nullptr, show == kNoCaption);
1346 
1347  menu->AddItem(tr("Image Captions"), nullptr, captionMenu);
1348 
1349  show = gCoreContext->GetNumSetting("GalleryDirCaption");
1350  captionMenu = new MythMenu(tr("Directory Captions"), this, "DirCaptionMenu");
1351 
1352  captionMenu->AddItem(tr("Name"), nullptr, nullptr, show == kNameCaption);
1353  captionMenu->AddItem(tr("Date"), nullptr, nullptr, show == kDateCaption);
1354  captionMenu->AddItem(tr("None"), nullptr, nullptr, show == kNoCaption);
1355 
1356  menu->AddItem(tr("Directory Captions"), nullptr, captionMenu);
1357 
1358  if (m_editsAllowed)
1359  {
1360  if (m_mgr.GetVisibility())
1361  menu->AddItem(tr("Hide Hidden Items"), &GalleryThumbView::HideHidden);
1362  else
1363  menu->AddItem(tr("Show Hidden Items"), &GalleryThumbView::ShowHidden);
1364  }
1365 
1366  if (m_zoomLevel > 0)
1367  menu->AddItem(tr("Zoom Out"), &GalleryThumbView::ZoomOut);
1368  if (m_zoomLevel < m_zoomWidgets.size() - 1)
1369  menu->AddItem(tr("Zoom In"), &GalleryThumbView::ZoomIn);
1370 
1371  QString details = m_infoList.GetState() == kNoInfo
1372  ? tr("Show Details") : tr("Hide Details");
1373 
1374  menu->AddItem(details, &GalleryThumbView::ShowDetails);
1375 
1376  mainMenu->AddItem(tr("Show"), nullptr, menu);
1377 }
1378 
1379 
1385 {
1386  // Only update selection if image is currently displayed
1387  if (m_view->Select(id, -1))
1388  BuildImageList();
1389 }
1390 
1391 
1397 {
1398  if (!item)
1399  return;
1400 
1401  auto im = item->GetData().value<ImagePtrK>();
1402  if (!im)
1403  return;
1404 
1405  switch (im->m_type)
1406  {
1407  case kDevice:
1408  case kCloneDir:
1409  case kDirectory:
1410  if (im == m_view->GetParent())
1411  DirSelectUp();
1412  else
1413  DirSelectDown();
1414  break;
1415 
1416  case kImageFile:
1417  case kVideoFile:
1418  StartSlideshow(kBrowseSlides); break;
1419  };
1420 }
1421 
1422 
1428 {
1429  QString err = m_mgr.ScanImagesAction(start);
1430  if (!err.isEmpty())
1431  ShowOkPopup(err);
1432 }
1433 
1434 
1440 {
1441  ImagePtrK selected = m_view->GetSelected();
1442  if (!selected)
1443  return;
1444 
1446  auto *slide = new GallerySlideView(mainStack, "galleryslideview",
1447  m_editsAllowed);
1448  if (slide->Create())
1449  {
1450  mainStack->AddScreen(slide);
1451 
1452  // Update selected item when slideshow exits
1453  connect(slide, &GallerySlideView::ImageSelected,
1455 
1456  if (selected->IsDirectory())
1457  {
1458  // Show selected dir
1459  slide->Start(mode, selected->m_id);
1460  }
1461  else
1462  {
1463  // Show current dir starting at selection
1464  slide->Start(mode, selected->m_parentId, selected->m_id);
1465  }
1466  }
1467  else
1468  delete slide;
1469 }
1470 
1471 
1476 {
1477  ImagePtrK im = m_view->GetParent();
1478  if (im)
1479  {
1480  LOG(VB_GUI, LOG_DEBUG, LOC +
1481  QString("Going up from %1").arg(im->m_filePath));
1482 
1483  // Select the upfolder in the higher dir
1484  m_view->Select(im->m_id);
1485 
1486  // Create tree rooted at parent of the kUpFolder directory node
1487  LoadData(im->m_parentId);
1488  }
1489  return true;
1490 }
1491 
1492 
1497 {
1498  ImagePtrK im = m_view->GetSelected();
1499  if (im)
1500  {
1501  LOG(VB_GUI, LOG_DEBUG, LOC +
1502  QString("Going down to %1").arg(im->m_filePath));
1503 
1504  // Create tree rooted at selected item
1505  LoadData(im->m_id);
1506  }
1507 }
1508 
1509 
1515 {
1516  ImagePtrK im = m_view->GetSelected();
1517  if (im)
1518  {
1519  // Mark/unmark selected item
1520  m_view->Mark(im->m_id, mark);
1521 
1522  // Redisplay buttonlist as a parent dir may have been unmarked
1523  BuildImageList();
1524  }
1525 }
1526 
1527 
1533 {
1534  if (mark)
1535  m_view->MarkAll();
1536  else
1537  m_view->ClearMarked();
1538 
1539  // Redisplay buttonlist
1540  BuildImageList();
1541 }
1542 
1543 
1548 {
1549  m_view->InvertMarked();
1550 
1551  // Redisplay buttonlist
1552  BuildImageList();
1553 }
1554 
1555 
1561 {
1562  ImagePtrK im = m_view->GetSelected();
1563  if (im && m_editsAllowed)
1564  {
1565  ImageIdList ids;
1566  ids.append(im->m_id);
1567  QString err = m_mgr.ChangeOrientation(transform, ids);
1568  if (!err.isEmpty())
1569  ShowOkPopup(err);
1570  }
1571 }
1572 
1573 
1579 {
1580  QString err = m_mgr.ChangeOrientation(transform, m_menuState.m_markedId);
1581  if (!err.isEmpty())
1582  ShowOkPopup(err);
1583 }
1584 
1585 
1591 {
1592  if (m_menuState.m_selected)
1593  {
1594  ImageIdList ids;
1595  ids.append(m_menuState.m_selected->m_id);
1596 
1597  QString err = m_mgr.HideFiles(hide, ids);
1598  if (!err.isEmpty())
1599  {
1600  ShowOkPopup(err);
1601  }
1602  else if (hide && !m_mgr.GetVisibility())
1603  {
1604  // Unmark invisible file
1605  m_view->Mark(m_menuState.m_selected->m_id, false);
1606  }
1607  }
1608 }
1609 
1610 
1616 {
1617  QString err = m_mgr.HideFiles(hide, m_menuState.m_markedId);
1618  if (!err.isEmpty())
1619  {
1620  ShowOkPopup(err);
1621  }
1622  else if (hide && !m_mgr.GetVisibility())
1623  {
1624  // Unmark invisible files
1625  for (int id : qAsConst(m_menuState.m_markedId))
1626  m_view->Mark(id, false);
1627  }
1628 }
1629 
1630 
1635 {
1636  if (m_menuState.m_selected)
1637  ShowDialog(tr("Do you want to delete\n%1 ?")
1638  .arg(m_menuState.m_selected->m_baseName), "ConfirmDelete");
1639 }
1640 
1641 
1646 {
1647  ShowDialog(tr("Do you want to delete all marked files ?"),
1648  "ConfirmDeleteMarked");
1649 }
1650 
1651 
1656 {
1657  // Show settings dialog
1658  auto *config = new GallerySettings(m_editsAllowed);
1660  auto *ssd = new StandardSettingDialog(mainStack, "gallerysettings", config);
1661  if (!ssd->Create())
1662  {
1663  delete ssd;
1664  return;
1665  }
1666 
1667  mainStack->AddScreen(ssd);
1668 
1669  // Effect setting changes when dialog saves on exit
1670 
1671  connect(config, &GallerySettings::ClearDbPressed,
1673 
1674  connect(config, &GallerySettings::OrderChanged,
1675  this, [this]()
1676  {
1677  // Update db view, reset cover cache & reload
1678  int sortIm = gCoreContext->GetNumSetting("GalleryImageOrder");
1679  int sortDir = gCoreContext->GetNumSetting("GalleryDirOrder");
1680  m_mgr.SetSortOrder(sortIm, sortDir);
1681  m_view->ClearCache();
1683  });
1684 
1685  connect(config, &GallerySettings::DateChanged,
1686  this, [this]()
1687  {
1688  QString date = gCoreContext->GetSetting("GalleryDateFormat");
1689  m_mgr.SetDateFormat(date);
1690  BuildImageList();
1691  });
1692 
1693  connect(config, &GallerySettings::ExclusionsChanged,
1694  this, [this]()
1695  {
1696  // Request rescan
1697  QString exclusions = gCoreContext->GetSetting("GalleryIgnoreFilter");
1698  m_view->ClearCache();
1699  ImageManagerFe::IgnoreDirs(exclusions);
1700  });
1701 }
1702 
1703 
1709 {
1710  gCoreContext->SaveBoolSetting("GalleryShowHidden", show);
1711 
1712  // Update Db(s)
1714 
1715  // Reset dir thumbnail cache
1716  m_view->ClearCache();;
1717 
1719 }
1720 
1721 
1727 void GalleryThumbView::ShowDialog(const QString& msg, const QString& event)
1728 {
1729  auto *popup = new MythConfirmationDialog(&m_popupStack, msg, true);
1730 
1731  if (popup->Create())
1732  {
1733  popup->SetReturnEvent(this, event);
1734  m_popupStack.AddScreen(popup);
1735  }
1736  else
1737  delete popup;
1738 }
1739 
1740 
1745 {
1746  if (m_menuState.m_selected)
1747  {
1748  QString base = QFileInfo(m_menuState.m_selected->m_baseName).completeBaseName();
1749  QString msg = tr("Enter a new name:");
1750  auto *popup = new MythTextInputDialog(&m_popupStack, msg, FilterNone,
1751  false, base);
1752  if (popup->Create())
1753  {
1754  popup->SetReturnEvent(this, "FileRename");
1755  m_popupStack.AddScreen(popup);
1756  }
1757  else
1758  delete popup;
1759  }
1760 }
1761 
1762 
1767 {
1769 }
1770 
1771 
1776 {
1777  QString msg = tr("Enter password:");
1778  auto *popup = new MythTextInputDialog(&m_popupStack, msg, FilterNone, true);
1779  if (popup->Create())
1780  {
1781  popup->SetReturnEvent(this, "Password");
1782  m_popupStack.AddScreen(popup);
1783  }
1784  else
1785  delete popup;
1786 }
1787 
1788 
1793 {
1794  gCoreContext->SaveSetting("GalleryShowType", type);
1795 
1796  // Update Db(s)
1797  m_mgr.SetType(type);
1798 
1799  // Reset dir thumbnail cache
1800  m_view->ClearCache();
1801 
1803 }
1804 
1805 
1811 {
1812  if (m_menuState.m_selected)
1813  {
1814  QString err = reset ? m_mgr.SetCover(m_menuState.m_selected->m_id, 0)
1815  : m_mgr.SetCover(m_menuState.m_selected->m_parentId,
1816  m_menuState.m_selected->m_id);
1817  if (!err.isEmpty())
1818  ShowOkPopup(err);
1819  }
1820 }
1821 
1822 
1827 {
1828  SelectZoomWidget(-1);
1829  BuildImageList();
1830 }
1831 
1832 
1837 {
1838  SelectZoomWidget(1);
1839  BuildImageList();
1840 }
1841 
1842 
1848 {
1849  m_zoomLevel += change;
1850 
1851  // constrain to zoom levels supported by theme
1852  if (m_zoomLevel < 0)
1853  m_zoomLevel = 0;
1854  if (m_zoomLevel >= m_zoomWidgets.size())
1855  m_zoomLevel = m_zoomWidgets.size() - 1;
1856 
1857  // Store any requested change, but not constraining adjustments
1858  // Thus, changing to a theme with fewer zoom levels will not overwrite the
1859  // setting
1860  if (change != 0)
1861  gCoreContext->SaveSetting("GalleryZoomLevel", m_zoomLevel);
1862 
1863  // dump the current list widget
1864  if (m_imageList)
1865  {
1866  m_imageList->SetVisible(false);
1867  disconnect(m_imageList, nullptr, this, nullptr);
1868  }
1869 
1870  // initialise new list widget
1872 
1873  m_imageList->SetVisible(true);
1875 
1876  // Monitor list actions (after focus events have been ignored)
1881 }
1882 
1883 
1888 {
1889  auto *popup = new MythTextInputDialog(&m_popupStack,
1890  tr("Enter name of new directory"),
1891  FilterNone, false);
1892  if (popup->Create())
1893  {
1894  popup->SetReturnEvent(this, "MakeDir");
1895  m_popupStack.AddScreen(popup);
1896  }
1897  else
1898  delete popup;
1899 }
1900 
1901 
1906 {
1908  if (dir)
1909  m_mgr.CloseDevices(dir->m_device, true);
1910 }
1911 
1912 
1922 void GalleryThumbView::Copy(bool deleteAfter)
1923 {
1924  // Destination must be a dir
1925  ImagePtrK destDir = m_menuState.m_selected;
1926  if (!destDir || destDir->IsFile())
1927  return;
1928 
1929  // Use current markings, if any. Otherwise use previous markings
1930  ImageIdList markedIds = m_menuState.m_markedId;
1931  if (markedIds.isEmpty())
1932  {
1933  markedIds = m_menuState.m_prevMarkedId;
1934  if (markedIds.isEmpty())
1935  {
1936  ShowOkPopup(tr("No files specified"));
1937  return;
1938  }
1939  }
1940 
1941  // Get all files/dirs in subtree(s). Only files are copied
1942  ImageList files;
1943  ImageList dirs;
1944  m_mgr.GetDescendants(markedIds, files, dirs);
1945 
1946  if (dirs.isEmpty() && files.isEmpty())
1947  {
1948  ShowOkPopup(tr("No images"));
1949  // Nothing to clean up
1950  return;
1951  }
1952 
1953  // Child dirs appear before their subdirs. If no dirs, images are all direct children
1954  ImagePtrK aChild = dirs.isEmpty() ? files[0] : dirs[0];
1955 
1956  // Determine parent path including trailing /
1957  int basePathSize = aChild->m_filePath.size() - aChild->m_baseName.size();
1958 
1959  // Update filepaths for Db & generate URLs for filesystem copy
1960  // Only copy files, destination dirs will be created automatically
1961  TransferThread::TransferMap transfers;
1962  for (const ImagePtr & im : qAsConst(files))
1963  {
1964  // Replace base path with destination path
1965  im->m_filePath = ImageManagerFe::ConstructPath(destDir->m_filePath,
1966  im->m_filePath.mid(basePathSize));
1967 
1968  transfers.insert(im, m_mgr.BuildTransferUrl(im->m_filePath,
1969  destDir->IsLocal()));
1970  }
1971 
1972  // Create progress dialog
1973  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
1974  auto *progress = new MythUIProgressDialog(tr("Copying files"), popupStack,
1975  "copydialog");
1976  if (progress->Create())
1977  popupStack->AddScreen(progress, false);
1978  else
1979  {
1980  delete progress;
1981  progress = nullptr;
1982  }
1983 
1984  // Copy files in a servant thread
1985  TransferThread copy(transfers, false, progress);
1987  TransferThread::ImageSet failed = copy.GetResult();
1988 
1989  if (progress)
1990  progress->Close();
1991 
1992  if (!failed.isEmpty())
1993  ShowOkPopup(tr("Failed to copy %L1/%Ln file(s)", nullptr, transfers.size())
1994  .arg(failed.size()));
1995 
1996  // Don't update Db for files that failed
1997  for (const ImagePtrK & im : qAsConst(failed))
1998  transfers.remove(im);
1999 
2000  ImageListK newImages = transfers.keys();
2001 
2002  // Include dirs
2003  QStringList dirPaths;
2004  for (const ImagePtr & im : qAsConst(dirs))
2005  {
2006  QString relPath = im->m_filePath.mid(basePathSize);
2007 
2008  dirPaths << relPath;
2009 
2010  // Replace base path with destination path
2011  im->m_filePath = ImageManagerFe::ConstructPath(destDir->m_filePath, relPath);
2012 
2013  // Append dirs so that hidden state & cover is preserved for new dirs
2014  // Pre-existing dirs will take precedance over these.
2015  newImages.append(im);
2016  }
2017 
2018  // Copy empty dirs as well (will fail for non-empty dirs)
2019  if (!dirPaths.isEmpty())
2020  m_mgr.MakeDir(destDir->m_id, dirPaths, false);
2021 
2022  if (!newImages.isEmpty())
2023  {
2024  // Update Db
2025  m_mgr.CreateImages(destDir->m_id, newImages);
2026 
2027  if (deleteAfter)
2028  {
2029  // Delete files/dirs that have been successfully copied
2030  // Will fail for dirs containing images that failed to copy
2031  ImageIdList ids;
2032  for (const ImagePtrK & im : qAsConst(newImages))
2033  ids << im->m_id;
2034 
2035  m_mgr.DeleteFiles(ids);
2036  }
2037  }
2038 }
2039 
2040 
2051 {
2052  // Destination must be a dir
2053  ImagePtrK destDir = m_menuState.m_selected;
2054  if (!destDir || destDir->IsFile())
2055  return;
2056 
2057  // Use current markings, if any. Otherwise use previous markings
2058  ImageIdList markedIds = m_menuState.m_markedId;
2059  if (markedIds.isEmpty())
2060  {
2061  markedIds = m_menuState.m_prevMarkedId;
2062  if (markedIds.isEmpty())
2063  {
2064  ShowOkPopup(tr("No files specified"));
2065  return;
2066  }
2067  }
2068 
2069  // Note UI mandates that transferees are either all local or all remote
2070  if (destDir->IsLocal() != ImageItem::IsLocalId(markedIds[0]))
2071  {
2072  // Moves between hosts require copy/delete
2073  Copy(true);
2074  return;
2075  }
2076 
2077  // Get marked images. Each file and dir will be renamed
2078  ImageList files;
2079  ImageList dirs;
2080  if (m_mgr.GetImages(markedIds, files, dirs) <= 0)
2081  {
2082  ShowOkPopup(tr("No images specified"));
2083  // Nothing to clean up
2084  return;
2085  }
2086  ImageList images = dirs + files;
2087 
2088  // Determine parent from first dir or pic
2089  ImagePtr aChild = images[0];
2090 
2091  // Determine parent path including trailing /
2092  // Note UI mandates that transferees all have same parent.
2093  int basePathSize = aChild->m_filePath.size() - aChild->m_baseName.size();
2094  QString parentPath = aChild->m_filePath.left(basePathSize);
2095 
2096  // Determine destination URLs
2097  TransferThread::TransferMap transfers;
2098  for (const QSharedPointer<ImageItem> & im : qAsConst(images))
2099  {
2100  // Replace base path with destination path
2101  QString newPath = ImageManagerFe::ConstructPath(destDir->m_filePath,
2102  im->m_filePath.mid(basePathSize));
2103 
2104  transfers.insert(im, m_mgr.BuildTransferUrl(newPath, aChild->IsLocal()));
2105  }
2106 
2107  // Create progress dialog
2108  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
2109  auto *progress = new MythUIProgressDialog(tr("Moving files"), popupStack,
2110  "movedialog");
2111 
2112  if (progress->Create())
2113  popupStack->AddScreen(progress, false);
2114  else
2115  {
2116  delete progress;
2117  progress = nullptr;
2118  }
2119 
2120  // Move files in a servant thread
2121  TransferThread move(transfers, true, progress);
2122  WaitUntilDone(move);
2123  TransferThread::ImageSet failed = move.GetResult();
2124 
2125  if (progress)
2126  progress->Close();
2127 
2128  if (!failed.isEmpty())
2129  ShowOkPopup(tr("Failed to move %L1/%Ln file(s)", nullptr, transfers.size())
2130  .arg(failed.size()));
2131 
2132  // Don't update Db for files that failed
2133  for (const ImagePtrK & im : qAsConst(failed))
2134  transfers.remove(im);
2135 
2136  if (!transfers.isEmpty())
2137  {
2138  ImageListK moved = transfers.keys();
2139 
2140  // Unmark moved files
2141  for (const ImagePtrK & im : qAsConst(moved))
2142  m_view->Mark(im->m_id, false);
2143 
2144  // Update Db
2145  m_mgr.MoveDbImages(destDir, moved, parentPath);
2146  }
2147 }
2148 
2149 
2154 {
2155  QString path = m_mgr.CreateImport();
2156  if (path.isEmpty())
2157  {
2158  ShowOkPopup(tr("Failed to create temporary directory."));
2159  return;
2160  }
2161 
2162  // Replace placeholder in command
2163  QString cmd = gCoreContext->GetSetting("GalleryImportCmd");
2164  cmd.replace("%TMPDIR%", path);
2165 
2166  // Run command in a separate thread
2167  MythUIBusyDialog *busy =
2168  ShowBusyPopup(tr("Running Import command.\nPlease wait..."));
2169 
2170  ShellThread thread(cmd, path);
2171  WaitUntilDone(thread);
2172 
2173  if (busy)
2174  busy->Close();
2175 
2176  int error = thread.GetResult();
2177  if (error != 0)
2178  ShowOkPopup(tr("Import command failed.\nError: %1").arg(error));
2179 
2180  // Rescan local devices
2181  QString err = m_mgr.ScanImagesAction(true, true);
2182  if (!err.isEmpty())
2183  LOG(VB_GENERAL, LOG_ERR, LOC + err);
2184 }
GalleryThumbView::FlipVerticalMarked
void FlipVerticalMarked()
Definition: gallerythumbview.h:81
GalleryThumbView::UpdateThumbnail
static void UpdateThumbnail(MythUIButtonListItem *button, const ImagePtrK &im, const QString &url, int index)
Update the buttonlist item with a thumbnail.
Definition: gallerythumbview.cpp:857
kPicAndVideo
@ kPicAndVideo
Show Pictures & Videos.
Definition: imagemanager.h:78
ImagePtrK
QSharedPointer< ImageItemK > ImagePtrK
Definition: imagetypes.h:165
MythMainWindow::GetMainStack
MythScreenStack * GetMainStack()
Definition: mythmainwindow.cpp:318
MenuSubjects::m_prevMarkedId
ImageIdList m_prevMarkedId
Ids of marked items in previous dir.
Definition: galleryviews.h:69
InfoList::Display
void Display(ImageItemK &im, const QStringList &tagStrings)
Build list of metadata tags.
Definition: galleryinfo.cpp:222
ImageDbReader::GetImages
int GetImages(const ImageIdList &ids, ImageList &files, ImageList &dirs) const
Returns images (local or remote but not a combination)
Definition: imagemanager.cpp:1851
MThread::start
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:283
ShowBusyPopup
MythUIBusyDialog * ShowBusyPopup(const QString &message)
Definition: mythprogressdialog.cpp:95
GalleryThumbView::m_scanProgressBar
MythUIProgressBar * m_scanProgressBar
Definition: gallerythumbview.h:138
GalleryThumbView::m_thumbExists
QSet< int > m_thumbExists
Images where thumbnails are known to exist.
Definition: gallerythumbview.h:161
GalleryThumbView::IntPair
QPair< int, int > IntPair
Definition: gallerythumbview.h:127
mythuitext.h
mythuiprogressbar.h
ImageAdapterBase::ConstructPath
static QString ConstructPath(const QString &path, const QString &name)
Assembles a canonical file path without corrupting its absolute/relative nature.
Definition: imagemanager.h:132
MythEvent::kMythEventMessage
static const Type kMythEventMessage
Definition: mythevent.h:79
FilterNone
@ FilterNone
Definition: mythuitextedit.h:21
ImageManagerFe::CreateThumbnails
void CreateThumbnails(const ImageIdList &ids, bool forFolder)
Create thumbnails or verify that they already exist.
Definition: imagemanager.cpp:1997
TransferThread::m_failed
ImageSet m_failed
Definition: gallerythumbview.cpp:145
GalleryThumbView::m_positionText
MythUIText * m_positionText
Definition: gallerythumbview.h:136
DirectoryView::GetPosition
QString GetPosition() const
Get positional status.
Definition: galleryviews.cpp:484
GallerySettings::DateChanged
void DateChanged()
MythUIText::Reset
void Reset(void) override
Reset the widget to it's original state, should not reset changes made by the theme.
Definition: mythuitext.cpp:82
error
static void error(const char *str,...)
Definition: vbi.cpp:36
kVideoFile
@ kVideoFile
A video.
Definition: imagetypes.h:40
GallerySettings::ExclusionsChanged
void ExclusionsChanged()
GalleryThumbView::StartScan
void StartScan()
Definition: gallerythumbview.h:111
TransferThread::Q_DECLARE_TR_FUNCTIONS
Q_DECLARE_TR_FUNCTIONS(FileTransferWorker)
GalleryThumbView::HideMarked
void HideMarked()
Definition: gallerythumbview.h:94
ImageSlideShowType
ImageSlideShowType
Type of slide show.
Definition: galleryslideview.h:15
GalleryThumbView::MenuPaste
void MenuPaste(MythMenu *mainMenu)
Add a Paste submenu.
Definition: gallerythumbview.cpp:1142
GalleryThumbView::m_imageList
MythUIButtonList * m_imageList
Definition: gallerythumbview.h:130
MythUIButtonListItem::DisplayState
void DisplayState(const QString &state, const QString &name)
Definition: mythuibuttonlist.cpp:3563
ImageManagerFe::CreateImages
QString CreateImages(int destId, const ImageListK &images)
Copies database images (but not the files themselves).
Definition: imagemanager.cpp:2243
GalleryThumbView::MakeDir
void MakeDir()
Show dialog to input new directory name.
Definition: gallerythumbview.cpp:1887
GalleryThumbView::SelectZoomWidget
void SelectZoomWidget(int change)
Change buttonlist to use a different size.
Definition: gallerythumbview.cpp:1847
ImageManagerFe::ScanImagesAction
QString ScanImagesAction(bool start, bool local=false)
Handle scanner start/stop commands.
Definition: imagemanager.cpp:2032
MythScreenType::Close
virtual void Close()
Definition: mythscreentype.cpp:386
MythUIButtonListItem::SetImageFromMap
void SetImageFromMap(const InfoMap &imageMap)
Definition: mythuibuttonlist.cpp:3461
ImageManagerFe::BuildTransferUrl
QString BuildTransferUrl(const QString &path, bool local) const
Generate Myth URL for a local or remote path.
Definition: imagemanager.h:499
GalleryThumbView::m_scanProgress
QHash< QString, IntPair > m_scanProgress
Last scan updates received from scanners.
Definition: gallerythumbview.h:150
progress
bool progress
Definition: mythcommflag.cpp:69
GalleryThumbView::customEvent
void customEvent(QEvent *event) override
Handle custom events.
Definition: gallerythumbview.cpp:372
MythUIProgressBar::SetStart
void SetStart(int value)
Definition: mythuiprogressbar.cpp:63
GalleryThumbView::DirSelectDown
void DirSelectDown()
Goes one directory level down.
Definition: gallerythumbview.cpp:1496
GallerySettings
Definition: galleryconfig.h:9
MenuSubjects::m_unhiddenMarked
bool m_unhiddenMarked
Is any marked item unhidden ?
Definition: galleryviews.h:72
GalleryThumbView::UnmarkAll
void UnmarkAll()
Definition: gallerythumbview.h:88
DirectoryView::Mark
void Mark(int id, bool mark)
Mark/unmark an image/dir.
Definition: galleryviews.cpp:736
GalleryThumbView::m_infoList
InfoList m_infoList
Image details overlay.
Definition: gallerythumbview.h:147
ImageManagerFe::MakeDir
QString MakeDir(int parent, const QStringList &names, bool rescan=true)
Create directories.
Definition: imagemanager.cpp:2201
MythUIType::GetChild
MythUIType * GetChild(const QString &name) const
Get a named child of this UIType.
Definition: mythuitype.cpp:133
MenuSubjects::m_markedId
ImageIdList m_markedId
Ids of all marked items.
Definition: galleryviews.h:68
kDirectory
@ kDirectory
A device sub directory.
Definition: imagetypes.h:38
GalleryThumbView::ShowPassword
void ShowPassword()
Displays dialog to accept password.
Definition: gallerythumbview.cpp:1775
kBrowseSlides
@ kBrowseSlides
Definition: galleryslideview.h:16
ImageManagerFe::DeviceCount
int DeviceCount() const
Definition: imagemanager.h:100
MythUIButtonList::itemSelected
void itemSelected(MythUIButtonListItem *item)
MythEvent
This class is used as a container for messages.
Definition: mythevent.h:16
GalleryThumbView::FlipHorizontalMarked
void FlipHorizontalMarked()
Definition: gallerythumbview.h:80
MythMenu::AddItem
void AddItem(const QString &title)
Definition: mythdialogbox.h:110
ImageManagerFe::IgnoreDirs
static QString IgnoreDirs(const QString &excludes)
Set directories to ignore during scans of the storage group.
Definition: imagemanager.cpp:2185
MythUIProgressBar::SetUsed
void SetUsed(int value)
Definition: mythuiprogressbar.cpp:69
GalleryThumbView::GalleryThumbView
GalleryThumbView(MythScreenStack *parent, const char *name)
Constructor.
Definition: gallerythumbview.cpp:170
mythdialogbox.h
MythScreenStack
Definition: mythscreenstack.h:16
GalleryThumbView::FlipVertical
void FlipVertical()
Definition: gallerythumbview.h:76
MythUIButtonListItem::FullChecked
@ FullChecked
Definition: mythuibuttonlist.h:48
GalleryThumbView::LoadData
void LoadData(int parent)
Loads & displays images from database.
Definition: gallerythumbview.cpp:642
TransferThread::m_files
TransferMap m_files
Maps source filepath to destination filepath.
Definition: gallerythumbview.cpp:144
TransferThread::run
void run() override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
Definition: gallerythumbview.cpp:76
kNoInfo
@ kNoInfo
Details not displayed.
Definition: galleryinfo.h:16
kDateCaption
@ kDateCaption
Dates.
Definition: gallerythumbview.h:17
GalleryThumbView::m_crumbsText
MythUIText * m_crumbsText
Definition: gallerythumbview.h:132
InfoList::Update
void Update(const ImagePtrK &im)
Populates available exif details for the current image/dir.
Definition: galleryinfo.cpp:196
kNoCaption
@ kNoCaption
None.
Definition: gallerythumbview.h:15
GalleryThumbView::m_typeFilterText
MythUIText * m_typeFilterText
Definition: gallerythumbview.h:135
ImageManagerFe::HideFiles
QString HideFiles(bool hidden, const ImageIdList &ids)
Hide/unhide images.
Definition: imagemanager.cpp:2078
GalleryThumbView::MenuAction
void MenuAction(MythMenu *mainMenu)
Add a Action submenu.
Definition: gallerythumbview.cpp:1207
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MThread::RunProlog
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
Definition: mthread.cpp:196
MenuSubjects::m_childCount
ssize_t m_childCount
Number of images & dirs excl parent.
Definition: galleryviews.h:70
ImageManagerFe::SetDateFormat
void SetDateFormat(const QString &format)
Definition: imagemanager.h:492
MythScreenType
Screen in which all other widgets are contained and rendered.
Definition: mythscreentype.h:45
show
static void show(uint8_t *buf, int length)
Definition: ringbuffer.cpp:339
kSeasonal
@ kSeasonal
Biased random selection so that images are more likely to appear on anniversaries.
Definition: galleryviews.h:25
GalleryThumbView::m_hideFilterText
MythUIText * m_hideFilterText
Definition: gallerythumbview.h:134
GalleryThumbView::Import
void Import()
Executes user 'Import command'.
Definition: gallerythumbview.cpp:2153
DirectoryView::GetParent
ImagePtrK GetParent() const
Definition: galleryviews.h:175
myth_system
uint myth_system(const QString &command, uint flags, std::chrono::seconds timeout)
Definition: mythsystemlegacy.cpp:506
ImageDbReader::SetVisibility
void SetVisibility(bool showHidden)
Definition: imagemanager.h:417
GalleryThumbView::ZoomIn
void ZoomIn()
Use smaller buttonlist widgets.
Definition: gallerythumbview.cpp:1836
GalleryThumbView::HideHidden
void HideHidden()
Definition: gallerythumbview.h:99
GalleryThumbView::DoHideItem
void DoHideItem(bool hide=true)
Hide or unhide item.
Definition: gallerythumbview.cpp:1590
TransferThread::TransferThread
TransferThread(TransferMap files, bool move, MythUIProgressDialog *dialog)
Definition: gallerythumbview.cpp:70
GalleryThumbView::m_menuState
MenuSubjects m_menuState
Current selection/marked files when menu is invoked.
Definition: gallerythumbview.h:155
TransferThread::TransferMap
QMap< ImagePtrK, QString > TransferMap
Definition: gallerythumbview.cpp:67
ImageManagerFe::CloseDevices
void CloseDevices(int devId=DEVICE_INVALID, bool eject=false)
Definition: imagemanager.cpp:2424
FlatView::Select
bool Select(int id, int fallback=0)
Selects first occurrence of an image.
Definition: galleryviews.cpp:119
hardwareprofile.scan.scan
def scan(profile, smoonURL, gate)
Definition: scan.py:57
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:14
mythprogressdialog.h
MythEvent::Message
const QString & Message() const
Definition: mythevent.h:65
MenuSubjects::m_selectedMarked
bool m_selectedMarked
Is selected item marked ?
Definition: galleryviews.h:67
MythUIButtonListItem::CheckState
CheckState
Definition: mythuibuttonlist.h:44
GalleryThumbView::Create
bool Create() override
Initialises and shows the graphical elements.
Definition: gallerythumbview.cpp:218
ImageManagerFe::ChangeOrientation
QString ChangeOrientation(ImageFileTransform transform, const ImageIdList &ids)
Apply an orientation transform to images.
Definition: imagemanager.cpp:2109
MythScreenType::GetFocusWidget
MythUIType * GetFocusWidget(void) const
Definition: mythscreentype.cpp:113
GalleryThumbView::MenuMain
void MenuMain()
Shows the main menu when the MENU button was pressed.
Definition: gallerythumbview.cpp:1046
mythsystemlegacy.h
DirectoryView::MarkAll
void MarkAll()
Mark all images/dirs.
Definition: galleryviews.cpp:723
InfoMap
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
GalleryThumbView::HideItem
void HideItem()
Definition: gallerythumbview.h:91
MythUIButtonListItem::SetText
void SetText(const QString &text, const QString &name="", const QString &state="")
Definition: mythuibuttonlist.cpp:3268
GalleryThumbView::RepeatOff
static void RepeatOff()
Definition: gallerythumbview.h:124
MythObservable::addListener
void addListener(QObject *listener)
Add a listener to the observable.
Definition: mythobservable.cpp:38
GalleryThumbView::SetUiSelection
void SetUiSelection(MythUIButtonListItem *item)
Updates text widgets for selected item.
Definition: gallerythumbview.cpp:988
GalleryThumbView::keyPressEvent
bool keyPressEvent(QKeyEvent *event) override
Handle keypresses.
Definition: gallerythumbview.cpp:282
GalleryThumbView::DoSetCover
void DoSetCover(bool reset=false)
Set or reset thumbnails to use for a directory cover.
Definition: gallerythumbview.cpp:1810
MythUIButtonListItem
Definition: mythuibuttonlist.h:41
TransferThread
Worker thread for copying/moving files.
Definition: gallerythumbview.cpp:63
ImageFileTransform
ImageFileTransform
Image transformations.
Definition: imagemetadata.h:46
TransferThread::m_move
bool m_move
Copy if false, Move if true.
Definition: gallerythumbview.cpp:143
ProgressUpdateEvent
Definition: mythprogressdialog.h:16
StandardSettingDialog
Definition: standardsettings.h:468
MythUIProgressBar::SetTotal
void SetTotal(int value)
Definition: mythuiprogressbar.cpp:81
ShellThread
Worker thread for running import.
Definition: gallerythumbview.cpp:33
GalleryThumbView::ResetUiSelection
void ResetUiSelection()
Clears all text widgets for selected item.
Definition: gallerythumbview.cpp:965
GallerySlideView
Slideshow screen.
Definition: galleryslideview.h:23
InfoList::Toggle
void Toggle(const ImagePtrK &im)
Toggle infolist state for an image. Focusable widgets toggle between Basic & Full info....
Definition: galleryinfo.cpp:85
GalleryThumbView::RotateCCWMarked
void RotateCCWMarked()
Definition: gallerythumbview.h:79
GalleryThumbView::MenuShow
void MenuShow(MythMenu *mainMenu)
Add a Show submenu.
Definition: gallerythumbview.cpp:1324
kPicOnly
@ kPicOnly
Hide videos.
Definition: imagemanager.h:79
GalleryThumbView::ShowSettings
void ShowSettings()
Show configuration screen.
Definition: gallerythumbview.cpp:1655
MythUIButtonList::itemClicked
void itemClicked(MythUIButtonListItem *item)
ImageDbReader::SetSortOrder
void SetSortOrder(int order, int dirOrder)
Definition: imagemanager.h:414
GalleryThumbView::UpdateScanProgress
void UpdateScanProgress(const QString &scanner, int current, int total)
Update progressbar with scan status.
Definition: gallerythumbview.cpp:884
MythMainWindow::TranslateKeyPress
bool TranslateKeyPress(const QString &Context, QKeyEvent *Event, QStringList &Actions, bool AllowJumps=true)
Get a list of actions for a keypress in the given context.
Definition: mythmainwindow.cpp:1111
remotefile.h
MythFile::copy
MBASE_PUBLIC long long copy(QFile &dst, QFile &src, uint block_size=0)
Copies src file to dst file.
Definition: mythmiscutil.cpp:263
MythUIProgressBar::Reset
void Reset(void) override
Reset the widget to it's original state, should not reset changes made by the theme.
Definition: mythuiprogressbar.cpp:16
MythUIProgressDialog
Definition: mythprogressdialog.h:59
MythScreenType::SetFocusWidget
bool SetFocusWidget(MythUIType *widget=nullptr)
Definition: mythscreentype.cpp:118
hardwareprofile.i18n.t
t
Definition: i18n.py:36
GalleryThumbView::TransformMarked
void TransformMarked(ImageFileTransform tran=kRotateCW)
Apply transform to marked images.
Definition: gallerythumbview.cpp:1578
MythDialogBox
Basic menu dialog, message and a list of options.
Definition: mythdialogbox.h:166
menu
static MythThemedMenu * menu
Definition: mythtv-setup.cpp:58
GalleryThumbView::SelectImage
void SelectImage(int id)
Select item if it is displayed.
Definition: gallerythumbview.cpp:1384
compat.h
GalleryThumbView::ResetCover
void ResetCover()
Definition: gallerythumbview.h:102
GalleryThumbView::DoShowHidden
void DoShowHidden(bool show=true)
Show or hide hidden files.
Definition: gallerythumbview.cpp:1708
mark
Definition: lang.cpp:22
ImageDbReader::GetType
int GetType() const
Definition: imagemanager.h:408
ImageAdapterBase::FormatSize
static QString FormatSize(int sizeKib)
Definition: imagemanager.h:143
GalleryThumbView::m_view
DirectoryView * m_view
List of images comprising the view.
Definition: gallerythumbview.h:146
MythScreenType::BuildFocusList
void BuildFocusList(void)
Definition: mythscreentype.cpp:206
gallerythumbview.h
Implements Gallery Thumbnail screen.
GalleryThumbView::MenuSlideshow
void MenuSlideshow(MythMenu *mainMenu)
Add a Slideshow submenu.
Definition: gallerythumbview.cpp:1273
kShuffle
@ kShuffle
Each image appears exactly once, but in random order.
Definition: galleryviews.h:23
GalleryThumbView::ClearSgDb
static void ClearSgDb()
Definition: gallerythumbview.h:34
GalleryThumbView::BuildImageList
void BuildImageList()
Displays all images in current view.
Definition: gallerythumbview.cpp:677
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:1891
GalleryThumbView::StartSlideshow
void StartSlideshow(ImageSlideShowType mode)
Start slideshow screen.
Definition: gallerythumbview.cpp:1439
GalleryThumbView::ShowRenameInput
void ShowRenameInput()
Show dialog to allow input.
Definition: gallerythumbview.cpp:1744
GalleryThumbView::ShowDialog
void ShowDialog(const QString &msg, const QString &event="")
Show a confirmation dialog.
Definition: gallerythumbview.cpp:1727
FlatView::GetAllNodes
ImageListK GetAllNodes() const
Get all images/dirs in view.
Definition: galleryviews.cpp:53
DirectoryView::InvertMarked
void InvertMarked()
Mark all unmarked items, unmark all marked items.
Definition: galleryviews.cpp:755
MythUIThemeCache::RemoveFromCacheByFile
void RemoveFromCacheByFile(const QString &File)
Definition: mythuithemecache.cpp:508
GalleryThumbView::DeleteMarked
void DeleteMarked()
Confirm user deletion of marked files.
Definition: gallerythumbview.cpp:1645
GalleryThumbView::Unhide
void Unhide()
Definition: gallerythumbview.h:92
ImageListK
QList< ImagePtrK > ImageListK
Definition: imagetypes.h:166
MThread::RunEpilog
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:209
ImageCaptionType
ImageCaptionType
Type of captions to display.
Definition: gallerythumbview.h:14
GalleryThumbView::m_scanActive
QSet< QString > m_scanActive
Scanners currently scanning.
Definition: gallerythumbview.h:152
FlatView::GetCachedThumbUrl
QString GetCachedThumbUrl(int id) const
Definition: galleryviews.h:121
GalleryThumbView::RotateCCW
void RotateCCW()
Definition: gallerythumbview.h:74
ImageManagerFe::LongDateOf
static QString LongDateOf(const ImagePtrK &im)
Return a timestamp/datestamp for an image or dir.
Definition: imagemanager.cpp:2344
ShellThread::m_command
QString m_command
Definition: gallerythumbview.cpp:57
MythUIBusyDialog
Definition: mythprogressdialog.h:36
ImageDbReader::GetVisibility
bool GetVisibility() const
Definition: imagemanager.h:409
GalleryThumbView::ZoomOut
void ZoomOut()
Use larger buttonlist widgets.
Definition: gallerythumbview.cpp:1826
MThread::isFinished
bool isFinished(void) const
Definition: mthread.cpp:258
GalleryThumbView::ResetExif
void ResetExif()
Definition: gallerythumbview.h:77
FlatView::GetSelected
ImagePtrK GetSelected() const
Get current selection.
Definition: galleryviews.cpp:66
MythUIButtonListItem::GetData
QVariant GetData()
Definition: mythuibuttonlist.cpp:3665
ImageManagerFe::SetCover
QString SetCover(int parent, int cover)
Set image to use as a cover thumbnail(s)
Definition: imagemanager.cpp:2141
GallerySettings::ClearDbPressed
void ClearDbPressed()
GalleryThumbView::ItemClicked
void ItemClicked(MythUIButtonListItem *item)
Action item click.
Definition: gallerythumbview.cpp:1396
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
InfoList::GetState
InfoVisibleState GetState() const
Definition: galleryinfo.h:33
ImageItem::IsLocalId
static bool IsLocalId(int id)
Determine image type (local/remote) from its id. Root/Gallery is remote.
Definition: imagetypes.h:122
LOC
#define LOC
Definition: gallerythumbview.cpp:22
GallerySettings::OrderChanged
void OrderChanged()
GalleryThumbView::DoHideMarked
void DoHideMarked(bool hide=true)
Hide or unhide marked items.
Definition: gallerythumbview.cpp:1615
GalleryThumbView::DirSelectUp
bool DirSelectUp()
Goes up one directory level.
Definition: gallerythumbview.cpp:1475
GalleryThumbView::UpdateImageItem
void UpdateImageItem(MythUIButtonListItem *item)
Initialises a single buttonlist item.
Definition: gallerythumbview.cpp:723
TransferThread::GetResult
ImageSet GetResult(void)
Definition: gallerythumbview.cpp:74
GalleryThumbView::ShowDetails
void ShowDetails()
Shows exif info/details about an item.
Definition: gallerythumbview.cpp:1766
GalleryThumbView::CheckThumbnail
QString CheckThumbnail(MythUIButtonListItem *item, const ImagePtrK &im, ImageIdList &request, int index)
Verify thumbnail is known to exist.
Definition: gallerythumbview.cpp:830
RemoteFile::CopyFile
static bool CopyFile(const QString &src, const QString &dst, bool overwrite=false, bool verify=false)
Definition: remotefile.cpp:580
GalleryThumbView::FlipHorizontal
void FlipHorizontal()
Definition: gallerythumbview.h:75
GalleryThumbView::m_popupStack
MythScreenStack & m_popupStack
Definition: gallerythumbview.h:144
GalleryThumbView::m_pendingMap
QMultiHash< int, ThumbLocation > m_pendingMap
Buttons waiting for thumbnails to be created.
Definition: gallerythumbview.h:159
ImageList
QVector< ImagePtr > ImageList
Definition: imagetypes.h:160
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:911
GalleryThumbView::TransformItem
void TransformItem(ImageFileTransform tran=kRotateCW)
Apply transform to an image.
Definition: gallerythumbview.cpp:1560
ImageManagerFe::CreateImport
QString CreateImport()
Definition: imagemanager.cpp:2521
GalleryThumbView::RotateCW
void RotateCW()
Definition: gallerythumbview.h:73
GalleryThumbView::RepeatOn
static void RepeatOn()
Definition: gallerythumbview.h:123
UIUtilDisp::Assign
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
Definition: mythuiutils.h:27
GalleryThumbView::m_scanProgressText
MythUIText * m_scanProgressText
Definition: gallerythumbview.h:137
GalleryThumbView::MarkInvertAll
void MarkInvertAll()
Invert all marked items.
Definition: gallerythumbview.cpp:1547
DirectoryView::LoadFromDb
bool LoadFromDb(int parentId) override
Populate view from database as images/subdirs of a directory. View is ordered: Parent dir,...
Definition: galleryviews.cpp:498
MythCoreContext::GetBoolSetting
bool GetBoolSetting(const QString &key, bool defaultval=false)
Definition: mythcorecontext.cpp:905
GalleryThumbView::RecursiveSlideshow
void RecursiveSlideshow()
Definition: gallerythumbview.h:71
InfoList::Hide
bool Hide()
Remove infolist from display.
Definition: galleryinfo.cpp:119
TransferThread::ImageSet
QSet< ImagePtrK > ImageSet
Definition: gallerythumbview.cpp:68
GalleryThumbView::m_emptyText
MythUIText * m_emptyText
Definition: gallerythumbview.h:133
GalleryThumbView::Move
void Move()
Move marked images to selected dir. If no marked files, use previously marked files....
Definition: gallerythumbview.cpp:2050
kImageFile
@ kImageFile
A picture.
Definition: imagetypes.h:39
MythMenu
Definition: mythdialogbox.h:99
ImageManagerFe::MoveDbImages
QString MoveDbImages(const ImagePtrK &destDir, ImageListK &images, const QString &srcPath)
Moves database images (but not the files themselves).
Definition: imagemanager.cpp:2287
GalleryThumbView::m_mgr
ImageManagerFe & m_mgr
Manages the images.
Definition: gallerythumbview.h:145
kUserCaption
@ kUserCaption
Exif comments.
Definition: gallerythumbview.h:18
GalleryThumbView::SetCover
void SetCover()
Definition: gallerythumbview.h:101
MythScreenType::keyPressEvent
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
Definition: mythscreentype.cpp:404
GallerySlideView::ImageSelected
void ImageSelected(int)
ImagePtr
QSharedPointer< ImageItem > ImagePtr
Definition: imagetypes.h:159
GalleryThumbView::m_editsAllowed
bool m_editsAllowed
Edit privileges.
Definition: gallerythumbview.h:162
MythConfirmationDialog
Dialog asking for user confirmation. Ok and optional Cancel button.
Definition: mythdialogbox.h:272
ImageDbReader::SetType
void SetType(int showType)
Definition: imagemanager.h:411
GalleryThumbView::HidePictures
void HidePictures()
Definition: gallerythumbview.h:105
ImageManagerFe
The image manager for use by Frontends.
Definition: imagemanager.h:459
XMLParseBase::LoadWindowFromXML
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
Definition: xmlparsebase.cpp:695
MythUIButtonListItem::SetImage
void SetImage(MythImage *image, const QString &name="")
Sets an image directly, should only be used in special circumstances since it bypasses the cache.
Definition: mythuibuttonlist.cpp:3429
FlatView::GetParentId
int GetParentId() const
Definition: galleryviews.h:105
GalleryThumbView::Copy
void Copy()
Definition: gallerythumbview.h:119
std
Definition: mythchrono.h:23
WaitUntilDone
static void WaitUntilDone(MThread &worker)
Runs a worker thread and waits for it to finish.
Definition: gallerythumbview.cpp:154
DialogCompletionEvent
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
Definition: mythdialogbox.h:41
GalleryThumbView::DoMarkAll
void DoMarkAll(bool mark=true)
Mark or unmark all items.
Definition: gallerythumbview.cpp:1532
ImageIdList
QList< int > ImageIdList
Definition: imagetypes.h:60
ShellThread::GetResult
int GetResult(void) const
Definition: gallerythumbview.cpp:39
ImageManagerFe::CrumbName
QString CrumbName(ImageItemK &im, bool getPath=false) const
Return a displayable name (with optional path) for an image.
Definition: imagemanager.cpp:2403
MythUIText::SetText
virtual void SetText(const QString &text)
Definition: mythuitext.cpp:132
MythUIType::SetVisible
virtual void SetVisible(bool visible)
Definition: mythuitype.cpp:1108
RemoteFile::MoveFile
static bool MoveFile(const QString &src, const QString &dst, bool overwrite=false)
Definition: remotefile.cpp:670
MThread
This is a wrapper around QThread that does several additional things.
Definition: mthread.h:48
GalleryThumbView::DeleteItem
void DeleteItem()
Confirm user deletion of an item.
Definition: gallerythumbview.cpp:1634
DirectoryView::GetMenuSubjects
MenuSubjects GetMenuSubjects()
Determine current selection, markings & various info to support menu display.
Definition: galleryviews.cpp:807
GalleryThumbView::ShowHidden
void ShowHidden()
Definition: gallerythumbview.h:98
PHOTO_DB_ID
static constexpr int PHOTO_DB_ID
Definition: imagetypes.h:29
DialogCompletionEvent::kEventType
static const Type kEventType
Definition: mythdialogbox.h:57
GalleryThumbView::m_zoomWidgets
QList< MythUIButtonList * > m_zoomWidgets
Theme buttonlist widgets implementing zoom levels.
Definition: gallerythumbview.h:141
MythUIButtonList::Reset
void Reset() override
Reset the widget to it's original state, should not reset changes made by the theme.
Definition: mythuibuttonlist.cpp:116
GetMythMainWindow
MythMainWindow * GetMythMainWindow(void)
Definition: mythmainwindow.cpp:104
SlideOrderType
SlideOrderType
Order of images in slideshow.
Definition: galleryviews.h:21
MythUIButtonList::SetItemCurrent
void SetItemCurrent(MythUIButtonListItem *item)
Definition: mythuibuttonlist.cpp:1554
GalleryThumbView::UnhideMarked
void UnhideMarked()
Definition: gallerythumbview.h:95
GalleryThumbView::~GalleryThumbView
~GalleryThumbView() override
Destructor.
Definition: gallerythumbview.cpp:189
build_compdb.action
action
Definition: build_compdb.py:9
DirectoryView::ClearCache
void ClearCache()
Clears UI cache.
Definition: galleryviews.cpp:887
GalleryThumbView::m_zoomLevel
int m_zoomLevel
Definition: gallerythumbview.h:142
GalleryThumbView::RemoveImages
void RemoveImages(const QStringList &ids, bool deleted=true)
Cleanup UI & image caches when a device is removed.
Definition: gallerythumbview.cpp:594
GalleryThumbView::MarkAll
void MarkAll()
Definition: gallerythumbview.h:87
DirectoryView::Clear
void Clear(bool resetParent=true)
Resets view.
Definition: galleryviews.cpp:712
ShellThread::ShellThread
ShellThread(QString cmd, QString path)
Definition: gallerythumbview.cpp:36
GalleryThumbView::UnmarkItem
void UnmarkItem()
Definition: gallerythumbview.h:85
MThread::objectName
QString objectName(void) const
Definition: mthread.cpp:243
MythMainWindow::GetStack
MythScreenStack * GetStack(const QString &Stackname)
Definition: mythmainwindow.cpp:323
GalleryThumbView::DoShowType
void DoShowType(int type)
Show/hide pictures or videos.
Definition: gallerythumbview.cpp:1792
GalleryThumbView::Slideshow
void Slideshow()
Definition: gallerythumbview.h:70
DirectoryView::RemoveImage
QStringList RemoveImage(int id, bool deleted=false)
Clear file/dir and all its ancestors from UI cache so that ancestor thumbnails are recalculated....
Definition: galleryviews.cpp:902
GalleryThumbView::DoMarkItem
void DoMarkItem(bool mark)
Mark or unmark a single item.
Definition: gallerythumbview.cpp:1514
GalleryThumbView::MenuTransform
void MenuTransform(MythMenu *mainMenu)
Add a Transform submenu.
Definition: gallerythumbview.cpp:1171
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:837
ThumbPair
QPair< int, QString > ThumbPair
Definition: imagetypes.h:64
MenuSubjects::m_selected
ImagePtrK m_selected
Selected item.
Definition: galleryviews.h:66
kOrdered
@ kOrdered
Ordered as per user setting GallerySortOrder.
Definition: galleryviews.h:22
GalleryThumbView::ThumbLocation
QPair< MythUIButtonListItem *, int > ThumbLocation
Definition: gallerythumbview.h:157
ImageManagerFe::DeleteFiles
QString DeleteFiles(const ImageIdList &ids)
Delete images.
Definition: imagemanager.cpp:2314
GalleryThumbView::m_captionText
MythUIText * m_captionText
Definition: gallerythumbview.h:131
ShellThread::m_path
QString m_path
Definition: gallerythumbview.cpp:58
GalleryThumbView::DoScanAction
void DoScanAction(bool start)
Action scan request.
Definition: gallerythumbview.cpp:1427
GalleryThumbView::ResetExifMarked
void ResetExifMarked()
Definition: gallerythumbview.h:82
InfoList::Create
bool Create(bool focusable)
Initialise buttonlist from XML.
Definition: galleryinfo.cpp:67
galleryconfig.h
Provides Gallery configuration screens.
MythTextInputDialog
Dialog prompting the user to enter a text string.
Definition: mythdialogbox.h:314
MythCoreContext::SaveSetting
void SaveSetting(const QString &key, int newValue)
Definition: mythcorecontext.cpp:880
GalleryThumbView::HideVideos
void HideVideos()
Definition: gallerythumbview.h:106
GalleryThumbView::MarkItem
void MarkItem()
Definition: gallerythumbview.h:84
GALLERY_DB_ID
static constexpr int GALLERY_DB_ID
Definition: imagetypes.h:27
DirectoryView
A datastore of images for display by a screen. Provides an ordered list of dirs & images from a singl...
Definition: galleryviews.h:170
kDevice
@ kDevice
Storage Group and local mounted media.
Definition: imagetypes.h:36
GetMythUI
MythUIHelper * GetMythUI()
Definition: mythuihelper.cpp:66
MythUIButtonList
List widget, displays list items in a variety of themeable arrangements and can trigger signals when ...
Definition: mythuibuttonlist.h:191
clean_comment
static QString clean_comment(const QString &comment)
Definition: gallerythumbview.cpp:25
DirectoryView::IsMarked
bool IsMarked(int id) const
Definition: galleryviews.h:188
MythUIProgressBar::SetVisible
void SetVisible(bool visible) override
Definition: mythuiprogressbar.cpp:196
DirectoryView::ClearMarked
void ClearMarked()
Unmark all items.
Definition: galleryviews.cpp:766
GalleryThumbView::MenuMarked
void MenuMarked(MythMenu *mainMenu)
Adds a Marking submenu.
Definition: gallerythumbview.cpp:1089
MythUIButtonListItem::setChecked
void setChecked(CheckState state)
Definition: mythuibuttonlist.cpp:3629
MythScreenStack::AddScreen
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Definition: mythscreenstack.cpp:52
kNameCaption
@ kNameCaption
Filenames.
Definition: gallerythumbview.h:16
kRandom
@ kRandom
Random selection from view. An image may be absent or appear multiple times.
Definition: galleryviews.h:24
GalleryThumbView::Close
void Close() override
Exit Gallery.
Definition: gallerythumbview.cpp:199
ImageManagerFe::ScanQuery
static QStringList ScanQuery()
Returns storage group scanner status.
Definition: imagemanager.cpp:2058
ShowOkPopup
MythConfirmationDialog * ShowOkPopup(const QString &message, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
Definition: mythdialogbox.cpp:562
ImageManagerFe::RenameFile
QString RenameFile(const ImagePtrK &im, const QString &name)
Rename an image.
Definition: imagemanager.cpp:2223
ImageManagerFe::ShortDateOf
QString ShortDateOf(const ImagePtrK &im) const
Return a short datestamp for thumbnail captions.
Definition: imagemanager.cpp:2370
GalleryThumbView::Eject
void Eject()
Remove local device (or Import) from Gallery.
Definition: gallerythumbview.cpp:1905
MythObservable::removeListener
void removeListener(QObject *listener)
Remove a listener to the observable.
Definition: mythobservable.cpp:55
GalleryThumbView::RotateCWMarked
void RotateCWMarked()
Definition: gallerythumbview.h:78
ShellThread::run
void run() override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
Definition: gallerythumbview.cpp:41
MythCoreContext::SaveBoolSetting
void SaveBoolSetting(const QString &key, bool newValue)
Definition: mythcorecontext.h:161
TransferThread::m_dialog
MythUIProgressDialog * m_dialog
Images for which copy/move failed.
Definition: gallerythumbview.cpp:146
ShellThread::m_result
int m_result
Definition: gallerythumbview.cpp:56
kCloneDir
@ kCloneDir
A device sub dir comprised from multiple SG dirs.
Definition: imagetypes.h:37
kVideoOnly
@ kVideoOnly
Hide pictures.
Definition: imagemanager.h:80
GalleryThumbView::ShowType
void ShowType()
Definition: gallerythumbview.h:104
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:897
GalleryThumbView::StopScan
void StopScan()
Definition: gallerythumbview.h:112
GalleryThumbView::Start
void Start()
Start Thumbnail screen.
Definition: gallerythumbview.cpp:618
MenuSubjects::m_hiddenMarked
bool m_hiddenMarked
Is any marked item hidden ?
Definition: galleryviews.h:71
MythUIButtonListItem::NotChecked
@ NotChecked
Definition: mythuibuttonlist.h:46
ImageManagerFe::DetectLocalDevices
bool DetectLocalDevices()
Detect and scan local devices.
Definition: imagemanager.cpp:2437