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 
26 class ShellThread: public MThread
27 {
28 public:
29  ShellThread(QString cmd, QString path)
30  : MThread("Import"), m_command(std::move(cmd)), m_path(std::move(path)) {}
31 
32  int GetResult(void) const { return m_result; }
33 
34  void run() override // MThread
35  {
36  RunProlog();
37 
38  QString cmd = QString("cd %1 && %2").arg(m_path, m_command);
39  LOG(VB_GENERAL, LOG_INFO, QString("Executing \"%1\"").arg(cmd));
40 
41  m_result = myth_system(cmd);
42 
43  LOG(VB_GENERAL, LOG_INFO, QString(" ...with result %1").arg(m_result));
44 
45  RunEpilog();
46  }
47 
48 private:
49  int m_result {0};
50  QString m_command;
51  QString m_path;
52 };
53 
54 
56 class TransferThread : public MThread
57 {
58  Q_DECLARE_TR_FUNCTIONS(FileTransferWorker);
59 public:
60  using TransferMap = QMap<ImagePtrK, QString>;
61  using ImageSet = QSet<ImagePtrK>;
62 
63  TransferThread(TransferMap files, bool move, MythUIProgressDialog *dialog)
64  : MThread("FileTransfer"),
65  m_move(move), m_files(std::move(files)), m_dialog(dialog) {}
66 
67  ImageSet GetResult(void) { return m_failed; }
68 
69  void run() override // MThread
70  {
71  RunProlog();
72 
73  QString action = m_move ? tr("Moving") : tr("Copying");
74 
75  // Sum file sizes
76  auto keys = m_files.keys();
77  auto add_size = [](int t, const ImagePtrK & im){ return t + im->m_size; };
78  int total = std::accumulate(keys.cbegin(), keys.cend(), 0, add_size);
79 
80  int progressSize = 0;
81 #if QT_VERSION < QT_VERSION_CHECK(5,10,0)
82  for (const ImagePtrK & im : m_files.keys())
83  {
84  QString newPath = m_files.value(im);
85 #elif QT_VERSION < QT_VERSION_CHECK(5,15,0)
86  for (auto it = m_files.constKeyValueBegin();
87  it != m_files.constKeyValueEnd(); it++)
88  {
89  const ImagePtrK & im = (*it).first;
90  QString newPath = (*it).second;
91 #else
92  for (auto it = m_files.constKeyValueBegin();
93  it != m_files.constKeyValueEnd(); it++)
94  {
95  const ImagePtrK & im = it->first;
96  QString newPath = it->second;
97 #endif
98  // Update progress dialog
99  if (m_dialog)
100  {
101  QString message = QString("%1 %2\n%3")
102  .arg(action, QFileInfo(im->m_url).fileName(),
103  ImageAdapterBase::FormatSize(im->m_size / 1024));
104 
105  auto *pue = new ProgressUpdateEvent(progressSize, total, message);
106  QApplication::postEvent(m_dialog, pue);
107  }
108 
109  LOG(VB_FILE, LOG_INFO, QString("%2 %3 -> %4")
110  .arg(action, im->m_url, newPath));
111 
112  bool success = m_move ? RemoteFile::MoveFile(im->m_url, newPath)
113  : RemoteFile::CopyFile(im->m_url, newPath,
114  false, true);
115  if (!success)
116  {
117  // Flag failures
118  m_failed.insert(im);
119 
120  LOG(VB_GENERAL, LOG_ERR,
121  QString("%1: Failed to copy/move %2 -> %3")
122  .arg(objectName(), im->m_url, m_files[im]));
123  }
124 
125  progressSize += im->m_size;
126  }
127 
128  // Update progress dialog
129  if (m_dialog)
130  {
131  auto *pue =
132  new ProgressUpdateEvent(progressSize, total, tr("Complete"));
133  QApplication::postEvent(m_dialog, pue);
134  }
135 
136  RunEpilog();
137  }
138 
139 private:
140  bool m_move;
144 };
145 
146 
151 static void WaitUntilDone(MThread &worker)
152 {
153  worker.start();
154  while (!worker.isFinished())
155  {
156  std::this_thread::sleep_for(1ms);
157  QCoreApplication::processEvents();
158  }
159 }
160 
161 
168  : MythScreenType(parent, name),
169  m_popupStack(*GetMythMainWindow()->GetStack("popup stack")),
170  m_mgr(ImageManagerFe::getInstance()),
171  // This screen uses a single fixed view (Parent dir, ordered dirs, ordered images)
172  m_view(new DirectoryView(kOrdered)),
173  m_infoList(*this),
174  // Start in edit mode unless a password exists
175  m_editsAllowed(gCoreContext->GetSetting("GalleryPassword").isEmpty())
176 {
177  // Hide hidden when edits disallowed
178  if (!m_editsAllowed)
179  m_mgr.SetVisibility(false);
180 }
181 
182 
187 {
188  LOG(VB_GUI, LOG_DEBUG, LOC + "Exiting Gallery");
189  delete m_view;
190 }
191 
192 
197 {
198  LOG(VB_GUI, LOG_DEBUG, LOC + "Closing Gallery");
199 
201 
202  // Cleanup local devices
204 
205  // Cleanup view
206  m_view->Clear();
207 
209 }
210 
211 
216 {
217  if (!LoadWindowFromXML("image-ui.xml", "gallery", this))
218  return false;
219 
220  // Determine zoom levels supported by theme
221  // images0 must exist; images1, images2 etc. are optional and enable zoom
222  int zoom = 0;
223  MythUIButtonList *widget = nullptr;
224  do
225  {
226  QString name = QString("images%1").arg(zoom++);
227  widget = dynamic_cast<MythUIButtonList *>(this->GetChild(name));
228  if (widget)
229  {
230  m_zoomWidgets.append(widget);
231  widget->SetVisible(false);
232  }
233  }
234  while (widget);
235 
236  if (m_zoomWidgets.isEmpty())
237  {
238  LOG(VB_GENERAL, LOG_ERR, LOC + "Screen 'Gallery' is missing 'images0'");
239  return false;
240  }
241  LOG(VB_GUI, LOG_DEBUG, LOC + QString("Screen 'Gallery' found %1 zoom levels")
242  .arg(m_zoomWidgets.size()));
243 
244  // File details list is managed elsewhere
245  if (!m_infoList.Create(false))
246  {
247  LOG(VB_GENERAL, LOG_ERR, LOC + "Cannot load 'Info buttonlist'");
248  return false;
249  }
250 
251  UIUtilW::Assign(this, m_captionText, "caption");
252  UIUtilW::Assign(this, m_emptyText, "noimages");
253  UIUtilW::Assign(this, m_positionText, "position");
254  UIUtilW::Assign(this, m_crumbsText, "breadcrumbs");
255  UIUtilW::Assign(this, m_hideFilterText, "hidefilter");
256  UIUtilW::Assign(this, m_typeFilterText, "typefilter");
257  UIUtilW::Assign(this, m_scanProgressText, "scanprogresstext");
258  UIUtilW::Assign(this, m_scanProgressBar, "scanprogressbar");
259 
260  if (m_scanProgressText)
262  if (m_scanProgressBar)
264 
265  BuildFocusList();
266 
267  // Initialise list widget with appropriate zoom level for this theme.
268  m_zoomLevel = gCoreContext->GetNumSetting("GalleryZoomLevel", 0);
269  SelectZoomWidget(0);
270 
271  return true;
272 }
273 
274 
279 bool GalleryThumbView::keyPressEvent(QKeyEvent *event)
280 {
281  if (GetFocusWidget()->keyPressEvent(event))
282  return true;
283 
284  QStringList actions;
285  bool handled = GetMythMainWindow()->TranslateKeyPress("Images", event, actions);
286 
287  for (int i = 0; i < actions.size() && !handled; i++)
288  {
289  QString action = actions[i];
290  handled = true;
291 
292  if (action == "MENU")
293  MenuMain();
294  else if (action == "INFO")
295  ShowDetails();
296  else if (action == "ZOOMIN")
297  ZoomIn();
298  else if (action == "ZOOMOUT")
299  ZoomOut();
300  else if (action == "ROTRIGHT")
301  RotateCW();
302  else if (action == "ROTLEFT")
303  RotateCCW();
304  else if (action == "FLIPHORIZONTAL")
305  FlipHorizontal();
306  else if (action == "FLIPVERTICAL")
307  FlipVertical();
308  else if (action == "COVER")
309  {
310  ImagePtrK im = m_view->GetSelected();
311  if (m_editsAllowed && im)
312  {
313  if (im == m_view->GetParent())
314  {
315  // Reset dir
316  m_mgr.SetCover(im->m_id, 0);
317  }
318  else
319  {
320  // Set parent cover
321  m_mgr.SetCover(im->m_parentId, im->m_id);
322  }
323  }
324  }
325  else if (action == "PLAY")
326  Slideshow();
327  else if (action == "RECURSIVESHOW")
328  {
329  ImagePtrK im = m_view->GetSelected();
330  if (im && im->IsDirectory())
332  }
333  else if (action == "MARK")
334  {
335  ImagePtrK im = m_view->GetSelected();
336  if (m_editsAllowed && im && im != m_view->GetParent())
337  DoMarkItem(!m_view->IsMarked(im->m_id));
338  }
339  else if (action == "ESCAPE" && !GetMythMainWindow()->IsExitingToMain())
340  {
341  // Exit info list, if shown
342  handled = m_infoList.Hide();
343 
344  // Ascend the tree unless parent is root,
345  // or a device and multiple devices/imports exist
346  if (!handled)
347  {
348  ImagePtrK node = m_view->GetParent();
349  if (node && node->m_id != GALLERY_DB_ID
350  && (!node->IsDevice() || m_mgr.DeviceCount() > 0))
351  handled = DirSelectUp();
352  }
353  }
354  else
355  handled = false;
356  }
357 
358  if (!handled)
359  handled = MythScreenType::keyPressEvent(event);
360 
361  return handled;
362 }
363 
364 
369 void GalleryThumbView::customEvent(QEvent *event)
370 {
371 
372  if (event->type() == MythEvent::MythEventMessage)
373  {
374  auto *me = dynamic_cast<MythEvent *>(event);
375  if (me == nullptr)
376  return;
377 
378  const QString& mesg = me->Message();
379  QStringList extra = me->ExtraDataList();
380 
381  // Internal messages contain a hostname. Ignore other FE messages
382  QStringList token = mesg.split(' ');
383  if (token.size() >= 2 && token[1] != gCoreContext->GetHostName())
384  return;
385 
386  if (token[0] == "IMAGE_METADATA")
387  {
388  int id = extra[0].toInt();
389  ImagePtrK selected = m_view->GetSelected();
390 
391  if (selected && selected->m_id == id)
392  m_infoList.Display(*selected, extra.mid(1));
393  }
394  else if (token[0] == "THUMB_AVAILABLE")
395  {
396  int id = extra[0].toInt();
397 
398  // Note existance of all thumbs
399  m_thumbExists.insert(id);
400 
401  // Get all buttons waiting for this thumbnail
402  QList<ThumbLocation> affected = m_pendingMap.values(id);
403 
404  // Only concerned with thumbnails we've requested
405  if (affected.isEmpty())
406  return;
407 
408  LOG(VB_GENERAL, LOG_DEBUG, LOC +
409  QString("Rx %1 : %2").arg(token[0], extra.join(",")));
410 
411  // Thumb url was cached when request was sent
412  QString url = m_view->GetCachedThumbUrl(id);
413 
414  // Set thumbnail for each button now it exists
415  for (const ThumbLocation & location : qAsConst(affected))
416  {
417  MythUIButtonListItem *button = location.first;
418  int index = location.second;
419 
420  auto im = button->GetData().value<ImagePtrK>();
421  if (im)
422  UpdateThumbnail(button, im, url, index);
423  }
424 
425  // Cancel pending request
426  m_pendingMap.remove(id);
427  }
428  else if (token[0] == "IMAGE_DB_CHANGED")
429  {
430  // Expects csv list of deleted ids, csv list of changed ids
431  LOG(VB_GENERAL, LOG_DEBUG, LOC +
432  QString("Rx %1 : %2").arg(token[0], extra.join(",")));
433 
434  if (!extra.isEmpty())
435  {
436 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
437  QStringList idDeleted =
438  extra[0].split(",", QString::SkipEmptyParts);
439 #else
440  QStringList idDeleted =
441  extra[0].split(",", Qt::SkipEmptyParts);
442 #endif
443 
444  RemoveImages(idDeleted);
445  }
446  if (extra.size() >= 2)
447  {
448 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
449  QStringList idChanged =
450  extra[1].split(",", QString::SkipEmptyParts);
451 #else
452  QStringList idChanged =
453  extra[1].split(",", Qt::SkipEmptyParts);
454 #endif
455  RemoveImages(idChanged, false);
456  }
457 
458  // Refresh display
460  }
461  else if (token[0] == "IMAGE_DEVICE_CHANGED")
462  {
463  // Expects list of url prefixes
464  LOG(VB_GENERAL, LOG_DEBUG, LOC +
465  QString("Rx %1 : %2").arg(token[0], extra.join(",")));
466 
467  // Clear everything. Local devices will be rebuilt
468  m_view->Clear();
469  m_thumbExists.clear();
470 
471  // Remove thumbs & images from image cache using supplied prefixes
472  for (const QString & url : qAsConst(extra))
474 
475  // Refresh display
477  }
478  else if (token[0] == "IMAGE_SCAN_STATUS" && extra.size() == 3)
479  {
480  // Expects scanner id, scanned#, total#
481  UpdateScanProgress(extra[0], extra[1].toInt(), extra[2].toInt());
482  }
483  }
484  else if (event->type() == DialogCompletionEvent::kEventType)
485  {
486  auto *dce = (DialogCompletionEvent *)(event);
487 
488  QString resultid = dce->GetId();
489  int buttonnum = dce->GetResult();
490 
491  if (resultid == "FileRename")
492  {
493  QString newName = dce->GetResultText();
495  {
496  QString err = m_mgr.RenameFile(m_menuState.m_selected,
497  newName);
498  if (!err.isEmpty())
499  ShowOkPopup(err);
500  }
501  }
502  else if (resultid == "MakeDir")
503  {
505  {
506  // Prohibit subtrees
507  QString name = dce->GetResultText();
508  QString err = name.contains("/")
509  ? tr("Invalid Name")
511  QStringList(name));
512  if (!err.isEmpty())
513  ShowOkPopup(err);
514  }
515  }
516  else if (resultid == "SlideOrderMenu")
517  {
518  SlideOrderType slideOrder = kOrdered;
519 
520  switch (buttonnum)
521  {
522  case 0: slideOrder = kOrdered; break;
523  case 1: slideOrder = kShuffle; break;
524  case 2: slideOrder = kRandom; break;
525  case 3: slideOrder = kSeasonal; break;
526  }
527  gCoreContext->SaveSetting("GallerySlideOrder", slideOrder);
528  LOG(VB_FILE, LOG_DEBUG, LOC + QString("Order %1").arg(slideOrder));
529  }
530  else if (resultid == "ImageCaptionMenu")
531  {
532  ImageCaptionType captions = kNoCaption;
533 
534  switch (buttonnum)
535  {
536  case 0: captions = kNameCaption; break;
537  case 1: captions = kDateCaption; break;
538  case 2: captions = kUserCaption; break;
539  case 3: captions = kNoCaption; break;
540  }
541  gCoreContext->SaveSetting("GalleryImageCaption", captions);
542  BuildImageList();
543  }
544  else if (resultid == "DirCaptionMenu")
545  {
546  ImageCaptionType captions = kNoCaption;
547 
548  switch (buttonnum)
549  {
550  case 0: captions = kNameCaption; break;
551  case 1: captions = kDateCaption; break;
552  case 2: captions = kNoCaption; break;
553  }
554  gCoreContext->SaveSetting("GalleryDirCaption", captions);
555  BuildImageList();
556  }
557  else if (resultid == "Password")
558  {
559  QString password = dce->GetResultText();
560  m_editsAllowed = (password == gCoreContext->GetSetting("GalleryPassword"));
561  }
562  else if (buttonnum == 1)
563  {
564  // Confirm current file deletion
565  QString err;
566  if (resultid == "ConfirmDelete" && m_menuState.m_selected)
567  {
569  err = m_mgr.DeleteFiles(ids);
570  }
571  // Confirm marked file deletion
572  else if (resultid == "ConfirmDeleteMarked")
573  {
575  }
576  else
577  return;
578 
579  if (!err.isEmpty())
580  ShowOkPopup(err);
581  }
582  }
583 }
584 
585 
591 void GalleryThumbView::RemoveImages(const QStringList &ids, bool deleted)
592 {
593  for (const QString & id : qAsConst(ids))
594  {
595  // Remove image from view
596  QStringList urls = m_view->RemoveImage(id.toInt(), deleted);
597  // Cleanup url lookup
598  m_thumbExists.remove(id.toInt());
599 
600  // Remove thumbs & images from image cache
601  for (const QString & url : qAsConst(urls))
602  {
603  LOG(VB_FILE, LOG_DEBUG, LOC +
604  QString("Clearing image cache of '%1'").arg(url));
605 
607  }
608  }
609 }
610 
611 
616 {
617  // Detect any running BE scans
618  // Expects OK, scanner id, current#, total#
619  QStringList message = ImageManagerFe::ScanQuery();
620  if (message.size() == 4 && message[0] == "OK")
621  {
622  UpdateScanProgress(message[1], message[2].toInt(), message[3].toInt());
623  }
624 
625  // Only receive events after device/scan status has been established
626  gCoreContext->addListener(this);
627 
628  // Start at Root if devices exist. Otherwise go straight to SG node
630 
631  LoadData(start);
632 }
633 
634 
640 {
642 
643  // Load view for parent directory
644  if (m_view->LoadFromDb(parent))
645  {
646  m_imageList->SetVisible(true);
647  if (m_emptyText)
648  {
649  m_emptyText->SetVisible(false);
650  m_emptyText->Reset();
651  }
652 
653  // Construct the buttonlist
654  BuildImageList();
655  }
656  else
657  {
658  m_infoList.Hide();
659  m_imageList->SetVisible(false);
660  if (m_emptyText)
661  {
662  m_emptyText->SetVisible(true);
663  m_emptyText->SetText(tr("No images found.\n"
664  "Scan storage group using menu,\n"
665  "or insert/mount local media.\n"));
666  }
667  }
668 }
669 
670 
675 {
676  m_imageList->Reset();
677  m_pendingMap.clear();
678 
679  // Get parent & all children
680  ImageListK nodes = m_view->GetAllNodes();
681  ImagePtrK selected = m_view->GetSelected();
682 
683  // go through the entire list and update
684  for (const ImagePtrK & im : qAsConst(nodes))
685  {
686  if (im)
687  {
688  // Data must be set by constructor: First item is automatically
689  // selected and must have data available for selection event, as
690  // subsequent reselection of same item will always fail.
691  auto *item = new MythUIButtonListItem(m_imageList, "",
692  QVariant::fromValue(im));
693 
694  item->setCheckable(true);
695  item->setChecked(MythUIButtonListItem::NotChecked);
696 
697  // assign and display all information about
698  // the current item, like title and subdirectory count
699  UpdateImageItem(item);
700 
701  // Treat parent differently
702  if (im == nodes[0])
703  {
704  // Only non-root parents can ascend
705  if (im->m_id != GALLERY_DB_ID)
706  item->DisplayState("upfolder", "parenttype");
707  }
708  else if (im == selected)
709  // Reinstate the active button item. Note this would fail for parent
711  }
712  }
713 }
714 
715 
721 {
722  auto im = item->GetData().value<ImagePtrK >();
723  if (!im)
724  return;
725 
726  // Allow themes to distinguish between roots, folders, pics, videos
727  switch (im->m_type)
728  {
729  case kDevice:
730  case kCloneDir:
731  case kDirectory:
732  if (im->m_dirCount > 0)
733  {
734  item->SetText(QString("%1/%2")
735  .arg(im->m_fileCount).arg(im->m_dirCount),
736  "childcount");
737  }
738  else
739  {
740  item->SetText(QString::number(im->m_fileCount), "childcount");
741  }
742 
743  item->DisplayState(im->IsDevice() ? "device" : "subfolder", "buttontype");
744  break;
745 
746  case kImageFile:
747  item->DisplayState("image", "buttontype");
748  break;
749 
750  case kVideoFile:
751  item->DisplayState("video", "buttontype");
752  break;
753 
754  default:
755  break;
756  }
757 
758  // Allow theme to distinguish visible/hidden nodes
759  QString hideState = (im->m_isHidden) ? "hidden" : "visible";
760  item->DisplayState(hideState, "buttonstate");
761 
762  // Caption
763  QString text;
765  im->IsFile() ? "GalleryImageCaption"
766  : "GalleryDirCaption");
767  switch (show)
768  {
769  case kNameCaption: text = m_mgr.CrumbName(*im); break;
770  case kDateCaption: text = m_mgr.ShortDateOf(im); break;
771  case kUserCaption: text = im->m_comment; break;
772  default:
773  case kNoCaption: text = ""; break;
774  }
775  item->SetText(text);
776 
777  // Set marked state
779  = m_view->IsMarked(im->m_id)
782 
783  item->setChecked(state);
784 
785  // Thumbnails required
786  ImageIdList request;
787 
788  if (im->m_thumbNails.size() == 1)
789  {
790  // Single thumbnail
791  QString url = CheckThumbnail(item, im, request, 0);
792 
793  if (!url.isEmpty())
794  UpdateThumbnail(item, im, url, 0);
795  }
796  else
797  {
798  // Dir showing up to 4 thumbs. Set them all at same time
799  InfoMap thumbMap;
800  for (int index = 0; index < im->m_thumbNails.size(); ++index)
801  {
802  QString url = CheckThumbnail(item, im, request, index);
803  if (!url.isEmpty())
804  thumbMap.insert(QString("thumbimage%1").arg(index), url);
805  }
806  if (!thumbMap.isEmpty())
807  item->SetImageFromMap(thumbMap);
808  }
809 
810  // Request creation/verification of unknown thumbnails.
811  if (!request.isEmpty())
812  m_mgr.CreateThumbnails(request, im->IsDirectory());
813 }
814 
815 
828  ImageIdList &request, int index)
829 {
830  ThumbPair thumb(im->m_thumbNails.at(index));
831  int id = thumb.first;
832 
833  if (m_thumbExists.contains(id))
834  return thumb.second;
835 
836  // Request BE thumbnail check if it is not already pending
837  if (!m_pendingMap.contains(id))
838  request << id;
839 
840  // Note this button is awaiting an update
841  m_pendingMap.insert(id, qMakePair(item, index));
842 
843  return "";
844 }
845 
846 
855  const ImagePtrK& im, const QString &url,
856  int index)
857 {
858  if (im->m_thumbNails.size() == 1)
859  {
860  // Pics, dirs & videos use separate widgets
861  switch (im->m_type)
862  {
863  case kImageFile: button->SetImage(url); break;
864  case kVideoFile: button->SetImage(url, "videoimage"); break;
865  default: button->SetImage(url, "folderimage"); break;
866  }
867  }
868  else
869  // Dir with 4 thumbnails
870  button->SetImage(url, QString("thumbimage%1").arg(index));
871 }
872 
873 
881 void GalleryThumbView::UpdateScanProgress(const QString &scanner,
882  int current, int total)
883 {
884  // Scan update
885  m_scanProgress.insert(scanner, qMakePair(current, total));
886 
887  // Detect end of this scan
888  if (current >= total)
889  {
890  LOG(VB_GUI, LOG_DEBUG, LOC + QString("Scan Finished %1 %2/%3")
891  .arg(scanner).arg(current).arg(total));
892 
893  // Mark inactive scanner
894  m_scanActive.remove(scanner);
895 
896  // Detect end of last scan
897  if (m_scanActive.isEmpty())
898  {
899  if (m_scanProgressText)
900  {
903  }
904  if (m_scanProgressBar)
905  {
908  }
909 
910  m_scanProgress.clear();
911 
912  return;
913  }
914  }
915  else
916  {
917  // Detect first scan update
918  if (m_scanActive.isEmpty())
919  {
920  // Show progressbar when first scan starts
921  if (m_scanProgressBar)
922  {
925  }
926  if (m_scanProgressText)
928  }
929 
930  if (!m_scanActive.contains(scanner))
931  {
932  LOG(VB_GUI, LOG_DEBUG, LOC + QString("Scan Started %1 %2/%3")
933  .arg(scanner).arg(current).arg(total));
934 
935  // Mark active scanner
936  m_scanActive.insert(scanner);
937  }
938  }
939 
940  // Aggregate all running scans
941  int currentAgg = 0;
942  int totalAgg = 0;
943  for (IntPair scan : qAsConst(m_scanProgress))
944  {
945  currentAgg += scan.first;
946  totalAgg += scan.second;
947  }
948 
949  if (m_scanProgressBar)
950  {
951  m_scanProgressBar->SetUsed(currentAgg);
952  m_scanProgressBar->SetTotal(totalAgg);
953  }
954  if (m_scanProgressText)
955  m_scanProgressText->SetText(tr("%L1 of %L3").arg(currentAgg).arg(totalAgg));
956 }
957 
958 
963 {
964  if (m_positionText)
966 
967  if (m_captionText)
968  m_captionText->Reset();
969 
970  if (m_crumbsText)
971  m_crumbsText->Reset();
972 
973  if (m_hideFilterText)
975 
976  if (m_typeFilterText)
978 }
979 
980 
986 {
987  auto im = item->GetData().value<ImagePtrK >();
988  if (im)
989  {
990  // update the position in the node list
991  m_view->Select(im->m_id);
992 
993  // show the name/path of the image
994  if (m_crumbsText)
995  m_crumbsText->SetText(m_mgr.CrumbName(*im, true));
996 
997  if (m_captionText)
998  {
999  // show the date & comment of non-root nodes
1000  QStringList text;
1001  if (im->m_id != GALLERY_DB_ID)
1002  {
1003  if (im->IsFile() || im->IsDevice())
1004  text << ImageManagerFe::LongDateOf(im);
1005 
1006  if (!im->m_comment.isEmpty())
1007  text << im->m_comment;
1008  }
1009  m_captionText->SetText(text.join(" - "));
1010  }
1011 
1012  if (m_hideFilterText)
1013  {
1014  m_hideFilterText->SetText(m_mgr.GetVisibility() ? tr("Hidden") : "");
1015  }
1016 
1017  if (m_typeFilterText)
1018  {
1019  QString text = "";
1020  switch (m_mgr.GetType())
1021  {
1022  case kPicAndVideo : text = ""; break;
1023  case kPicOnly : text = tr("Pictures"); break;
1024  case kVideoOnly : text = tr("Videos"); break;
1025  }
1026  m_typeFilterText->SetText(text);
1027  }
1028 
1029  // show the position of the image
1030  if (m_positionText)
1032 
1033  // Update any file details information
1034  m_infoList.Update(im);
1035  }
1036 }
1037 
1038 
1043 {
1044  // Create the main menu
1045  auto *menu = new MythMenu(tr("Gallery Options"), this, "mainmenu");
1046 
1047  // Menu options depend on the marked files and the current node
1049 
1050  if (m_menuState.m_selected)
1051  {
1052  if (m_editsAllowed)
1053  {
1054  MenuMarked(menu);
1055  MenuPaste(menu);
1057  MenuAction(menu);
1058  }
1060  MenuShow(menu);
1061  if (!m_editsAllowed)
1062  menu->AddItem(tr("Enable Edits"), &GalleryThumbView::ShowPassword);
1063  }
1064 
1065  // Depends on current status of backend scanner - string(number(isBackend()))
1066  if (m_scanActive.contains("1"))
1067  menu->AddItem(tr("Stop Scan"), &GalleryThumbView::StopScan);
1068  else
1069  menu->AddItem(tr("Scan Storage Group"), &GalleryThumbView::StartScan);
1070 
1071  menu->AddItem(tr("Settings"), &GalleryThumbView::ShowSettings);
1072 
1073  auto *popup = new MythDialogBox(menu, &m_popupStack, "menuPopup");
1074  if (popup->Create())
1075  m_popupStack.AddScreen(popup);
1076  else
1077  delete popup;
1078 }
1079 
1080 
1086 {
1087  ImagePtrK parent = m_view->GetParent();
1088 
1089  if (m_menuState.m_childCount == 0 || parent.isNull())
1090  return;
1091 
1092  QString title = tr("%L1 marked").arg(m_menuState.m_markedId.size());
1093  auto *menu = new MythMenu(title, this, "markmenu");
1094 
1095  // Mark/unmark selected
1096  if (m_menuState.m_selected->IsFile())
1097  {
1099  menu->AddItem(tr("Unmark File"), &GalleryThumbView::UnmarkItem);
1100  else
1101  menu->AddItem(tr("Mark File"), &GalleryThumbView::MarkItem);
1102  }
1103  // Cannot mark/unmark parent dir from this level
1104  else if (!m_menuState.m_selected->IsDevice()
1105  && m_menuState.m_selected != parent)
1106  {
1108  menu->AddItem(tr("Unmark Directory"), &GalleryThumbView::UnmarkItem);
1109  else
1110  menu->AddItem(tr("Mark Directory"), &GalleryThumbView::MarkItem);
1111  }
1112 
1113  if (parent->m_id != GALLERY_DB_ID)
1114  {
1115  // Mark All if unmarked files exist
1117  menu->AddItem(tr("Mark All"), &GalleryThumbView::MarkAll);
1118 
1119  // Unmark All if marked files exist
1120  if (!m_menuState.m_markedId.isEmpty())
1121  {
1122  menu->AddItem(tr("Unmark All"), &GalleryThumbView::UnmarkAll);
1123  menu->AddItem(tr("Invert Marked"), &GalleryThumbView::MarkInvertAll);
1124  }
1125  }
1126 
1127  if (menu->IsEmpty())
1128  delete menu;
1129  else
1130  mainMenu->AddItem(tr("Mark"), nullptr, menu);
1131 }
1132 
1133 
1139 {
1140  // Can only copy/move into non-root dirs
1141  if (m_menuState.m_selected->IsDirectory()
1142  && m_menuState.m_selected->m_id != GALLERY_DB_ID)
1143  {
1144  // Operate on current marked files, if any
1146  if (files.isEmpty())
1147  files = m_menuState.m_prevMarkedId;
1148  if (files.isEmpty())
1149  return;
1150 
1151  QString title = tr("%L1 marked").arg(files.size());
1152 
1153  auto *menu = new MythMenu(title, this, "pastemenu");
1154 
1155  menu->AddItem(tr("Move Marked Into"), &GalleryThumbView::Move);
1156  menu->AddItem(tr("Copy Marked Into"), qOverload<>(&GalleryThumbView::Copy));
1157 
1158  mainMenu->AddItem(tr("Paste"), nullptr, menu);
1159  }
1160 }
1161 
1162 
1168 {
1169  // Operate on marked files, if any, otherwise selected node
1170  if (!m_menuState.m_markedId.isEmpty())
1171  {
1172  QString title = tr("%L1 marked").arg(m_menuState.m_markedId.size());
1173 
1174  auto *menu = new MythMenu(title, this, "");
1175 
1176  menu->AddItem(tr("Rotate Marked CW"), &GalleryThumbView::RotateCWMarked);
1177  menu->AddItem(tr("Rotate Marked CCW"), &GalleryThumbView::RotateCCWMarked);
1178  menu->AddItem(tr("Flip Marked Horizontal"), &GalleryThumbView::FlipHorizontalMarked);
1179  menu->AddItem(tr("Flip Marked Vertical"), &GalleryThumbView::FlipVerticalMarked);
1180  menu->AddItem(tr("Reset Marked to Exif"), &GalleryThumbView::ResetExifMarked);
1181 
1182  mainMenu->AddItem(tr("Transforms"), nullptr, menu);
1183  }
1184  else if (m_menuState.m_selected->IsFile())
1185  {
1186  auto *menu = new MythMenu(m_menuState.m_selected->m_baseName, this, "");
1187 
1188  menu->AddItem(tr("Rotate CW"), &GalleryThumbView::RotateCW);
1189  menu->AddItem(tr("Rotate CCW"), &GalleryThumbView::RotateCCW);
1190  menu->AddItem(tr("Flip Horizontal"), &GalleryThumbView::FlipHorizontal);
1191  menu->AddItem(tr("Flip Vertical"), &GalleryThumbView::FlipVertical);
1192  menu->AddItem(tr("Reset to Exif"), &GalleryThumbView::ResetExif);
1193 
1194  mainMenu->AddItem(tr("Transforms"), nullptr, menu);
1195  }
1196 }
1197 
1198 
1204 {
1205  MythMenu *menu = nullptr;
1206  ImagePtrK selected = m_menuState.m_selected;
1207 
1208  // Operate on current marked files, if any
1209  if (!m_menuState.m_markedId.empty())
1210  {
1211  QString title = tr("%L1 marked").arg(m_menuState.m_markedId.size());
1212 
1213  menu = new MythMenu(title, this, "actionmenu");
1214 
1215  // Only offer Hide/Unhide if relevant
1217  menu->AddItem(tr("Hide Marked"), &GalleryThumbView::HideMarked);
1219  menu->AddItem(tr("Unhide Marked"), &GalleryThumbView::UnhideMarked);
1220 
1221  menu->AddItem(tr("Delete Marked"), &GalleryThumbView::DeleteMarked);
1222  }
1223  else
1224  {
1225  // Operate on selected file/dir
1226  menu = new MythMenu(selected->m_baseName, this, "actionmenu");
1227 
1228  // Prohibit actions on devices and parent dirs
1229  if (!selected->IsDevice() && selected != m_view->GetParent())
1230  {
1231  if (selected->m_isHidden)
1232  menu->AddItem(tr("Unhide"), &GalleryThumbView::Unhide);
1233  else
1234  menu->AddItem(tr("Hide"), &GalleryThumbView::HideItem);
1235 
1236  menu->AddItem(tr("Use as Cover"), &GalleryThumbView::SetCover);
1237  menu->AddItem(tr("Delete"), &GalleryThumbView::DeleteItem);
1238  menu->AddItem(tr("Rename"), &GalleryThumbView::ShowRenameInput);
1239  }
1240  else if (selected->m_userThumbnail)
1241  menu->AddItem(tr("Reset Cover"), &GalleryThumbView::ResetCover);
1242  }
1243 
1244  // Can only mkdir in a non-root dir
1245  if (selected->IsDirectory()
1246  && selected->m_id != GALLERY_DB_ID)
1247  menu->AddItem(tr("Create Directory"), &GalleryThumbView::MakeDir);
1248 
1249  // Only show import command on root, when defined
1250  if (selected->m_id == GALLERY_DB_ID
1251  && !gCoreContext->GetSetting("GalleryImportCmd").isEmpty())
1252  menu->AddItem(tr("Import"), &GalleryThumbView::Import);
1253 
1254  // Only show eject when devices (excluding import) exist
1255  if (selected->IsDevice() && selected->IsLocal())
1256  menu->AddItem(tr("Eject media"), &GalleryThumbView::Eject);
1257 
1258  if (menu->IsEmpty())
1259  delete menu;
1260  else
1261  mainMenu->AddItem(tr("Actions"), nullptr, menu);
1262 }
1263 
1264 
1270 {
1271  int order = gCoreContext->GetNumSetting("GallerySlideOrder", kOrdered);
1272 
1273  QString ordering;
1274  switch (order)
1275  {
1276  case kShuffle : ordering = tr("Shuffled"); break;
1277  case kRandom : ordering = tr("Random"); break;
1278  case kSeasonal : ordering = tr("Seasonal"); break;
1279  default:
1280  case kOrdered : ordering = tr("Ordered"); break;
1281  }
1282 
1283  auto *menu = new MythMenu(tr("Slideshow") + " (" + ordering + ")",
1284  this, "SlideshowMenu");
1285 
1286  // Use selected dir or parent, if image selected
1287  if (m_menuState.m_selected->IsDirectory())
1288  {
1289  if (m_menuState.m_selected->m_fileCount > 0)
1290  menu->AddItem(tr("Directory"), &GalleryThumbView::Slideshow);
1291 
1292  if (m_menuState.m_selected->m_dirCount > 0)
1293  menu->AddItem(tr("Recursive"), &GalleryThumbView::RecursiveSlideshow);
1294  }
1295  else
1296  menu->AddItem(tr("Current Directory"), &GalleryThumbView::Slideshow);
1297 
1298  auto *orderMenu = new MythMenu(tr("Slideshow Order"), this, "SlideOrderMenu");
1299 
1300  orderMenu->AddItem(tr("Ordered"), nullptr, nullptr, order == kOrdered);
1301  orderMenu->AddItem(tr("Shuffled"), nullptr, nullptr, order == kShuffle);
1302  orderMenu->AddItem(tr("Random"), nullptr, nullptr, order == kRandom);
1303  orderMenu->AddItem(tr("Seasonal"), nullptr, nullptr, order == kSeasonal);
1304 
1305  menu->AddItem(tr("Change Order"), nullptr, orderMenu);
1306 
1307  if (gCoreContext->GetBoolSetting("GalleryRepeat", false))
1308  menu->AddItem(tr("Turn Repeat Off"), &GalleryThumbView::RepeatOff);
1309  else
1310  menu->AddItem(tr("Turn Repeat On"), &GalleryThumbView::RepeatOn);
1311 
1312  mainMenu->AddItem(tr("Slideshow"), nullptr, menu);
1313 }
1314 
1315 
1321 {
1322  auto *menu = new MythMenu(tr("Show Options"), this, "showmenu");
1323 
1324  int type = m_mgr.GetType();
1325  if (type == kPicAndVideo)
1326  {
1327  menu->AddItem(tr("Hide Pictures"), &GalleryThumbView::HidePictures);
1328  menu->AddItem(tr("Hide Videos"), &GalleryThumbView::HideVideos);
1329  }
1330  else
1331  menu->AddItem(type == kPicOnly ? tr("Show Videos") : tr("Show Pictures"),
1333 
1334  int show = gCoreContext->GetNumSetting("GalleryImageCaption");
1335  auto *captionMenu = new MythMenu(tr("Image Captions"), this,
1336  "ImageCaptionMenu");
1337 
1338  captionMenu->AddItem(tr("Name"), nullptr, nullptr, show == kNameCaption);
1339  captionMenu->AddItem(tr("Date"), nullptr, nullptr, show == kDateCaption);
1340  captionMenu->AddItem(tr("Comment"), nullptr, nullptr, show == kUserCaption);
1341  captionMenu->AddItem(tr("None"), nullptr, nullptr, show == kNoCaption);
1342 
1343  menu->AddItem(tr("Image Captions"), nullptr, captionMenu);
1344 
1345  show = gCoreContext->GetNumSetting("GalleryDirCaption");
1346  captionMenu = new MythMenu(tr("Directory Captions"), this, "DirCaptionMenu");
1347 
1348  captionMenu->AddItem(tr("Name"), nullptr, nullptr, show == kNameCaption);
1349  captionMenu->AddItem(tr("Date"), nullptr, nullptr, show == kDateCaption);
1350  captionMenu->AddItem(tr("None"), nullptr, nullptr, show == kNoCaption);
1351 
1352  menu->AddItem(tr("Directory Captions"), nullptr, captionMenu);
1353 
1354  if (m_editsAllowed)
1355  {
1356  if (m_mgr.GetVisibility())
1357  menu->AddItem(tr("Hide Hidden Items"), &GalleryThumbView::HideHidden);
1358  else
1359  menu->AddItem(tr("Show Hidden Items"), &GalleryThumbView::ShowHidden);
1360  }
1361 
1362  if (m_zoomLevel > 0)
1363  menu->AddItem(tr("Zoom Out"), &GalleryThumbView::ZoomOut);
1364  if (m_zoomLevel < m_zoomWidgets.size() - 1)
1365  menu->AddItem(tr("Zoom In"), &GalleryThumbView::ZoomIn);
1366 
1367  QString details = m_infoList.GetState() == kNoInfo
1368  ? tr("Show Details") : tr("Hide Details");
1369 
1370  menu->AddItem(details, &GalleryThumbView::ShowDetails);
1371 
1372  mainMenu->AddItem(tr("Show"), nullptr, menu);
1373 }
1374 
1375 
1381 {
1382  // Only update selection if image is currently displayed
1383  if (m_view->Select(id, -1))
1384  BuildImageList();
1385 }
1386 
1387 
1393 {
1394  if (!item)
1395  return;
1396 
1397  auto im = item->GetData().value<ImagePtrK>();
1398  if (!im)
1399  return;
1400 
1401  switch (im->m_type)
1402  {
1403  case kDevice:
1404  case kCloneDir:
1405  case kDirectory:
1406  if (im == m_view->GetParent())
1407  DirSelectUp();
1408  else
1409  DirSelectDown();
1410  break;
1411 
1412  case kImageFile:
1413  case kVideoFile:
1414  StartSlideshow(kBrowseSlides); break;
1415  };
1416 }
1417 
1418 
1424 {
1425  QString err = m_mgr.ScanImagesAction(start);
1426  if (!err.isEmpty())
1427  ShowOkPopup(err);
1428 }
1429 
1430 
1436 {
1437  ImagePtrK selected = m_view->GetSelected();
1438  if (!selected)
1439  return;
1440 
1442  auto *slide = new GallerySlideView(mainStack, "galleryslideview",
1443  m_editsAllowed);
1444  if (slide->Create())
1445  {
1446  mainStack->AddScreen(slide);
1447 
1448  // Update selected item when slideshow exits
1449  connect(slide, &GallerySlideView::ImageSelected,
1451 
1452  if (selected->IsDirectory())
1453  {
1454  // Show selected dir
1455  slide->Start(mode, selected->m_id);
1456  }
1457  else
1458  {
1459  // Show current dir starting at selection
1460  slide->Start(mode, selected->m_parentId, selected->m_id);
1461  }
1462  }
1463  else
1464  delete slide;
1465 }
1466 
1467 
1472 {
1473  ImagePtrK im = m_view->GetParent();
1474  if (im)
1475  {
1476  LOG(VB_GUI, LOG_DEBUG, LOC +
1477  QString("Going up from %1").arg(im->m_filePath));
1478 
1479  // Select the upfolder in the higher dir
1480  m_view->Select(im->m_id);
1481 
1482  // Create tree rooted at parent of the kUpFolder directory node
1483  LoadData(im->m_parentId);
1484  }
1485  return true;
1486 }
1487 
1488 
1493 {
1494  ImagePtrK im = m_view->GetSelected();
1495  if (im)
1496  {
1497  LOG(VB_GUI, LOG_DEBUG, LOC +
1498  QString("Going down to %1").arg(im->m_filePath));
1499 
1500  // Create tree rooted at selected item
1501  LoadData(im->m_id);
1502  }
1503 }
1504 
1505 
1511 {
1512  ImagePtrK im = m_view->GetSelected();
1513  if (im)
1514  {
1515  // Mark/unmark selected item
1516  m_view->Mark(im->m_id, mark);
1517 
1518  // Redisplay buttonlist as a parent dir may have been unmarked
1519  BuildImageList();
1520  }
1521 }
1522 
1523 
1529 {
1530  if (mark)
1531  m_view->MarkAll();
1532  else
1533  m_view->ClearMarked();
1534 
1535  // Redisplay buttonlist
1536  BuildImageList();
1537 }
1538 
1539 
1544 {
1545  m_view->InvertMarked();
1546 
1547  // Redisplay buttonlist
1548  BuildImageList();
1549 }
1550 
1551 
1557 {
1558  ImagePtrK im = m_view->GetSelected();
1559  if (im && m_editsAllowed)
1560  {
1561  ImageIdList ids;
1562  ids.append(im->m_id);
1563  QString err = m_mgr.ChangeOrientation(transform, ids);
1564  if (!err.isEmpty())
1565  ShowOkPopup(err);
1566  }
1567 }
1568 
1569 
1575 {
1576  QString err = m_mgr.ChangeOrientation(transform, m_menuState.m_markedId);
1577  if (!err.isEmpty())
1578  ShowOkPopup(err);
1579 }
1580 
1581 
1587 {
1588  if (m_menuState.m_selected)
1589  {
1590  ImageIdList ids;
1591  ids.append(m_menuState.m_selected->m_id);
1592 
1593  QString err = m_mgr.HideFiles(hide, ids);
1594  if (!err.isEmpty())
1595  {
1596  ShowOkPopup(err);
1597  }
1598  else if (hide && !m_mgr.GetVisibility())
1599  {
1600  // Unmark invisible file
1601  m_view->Mark(m_menuState.m_selected->m_id, false);
1602  }
1603  }
1604 }
1605 
1606 
1612 {
1613  QString err = m_mgr.HideFiles(hide, m_menuState.m_markedId);
1614  if (!err.isEmpty())
1615  {
1616  ShowOkPopup(err);
1617  }
1618  else if (hide && !m_mgr.GetVisibility())
1619  {
1620  // Unmark invisible files
1621  for (int id : qAsConst(m_menuState.m_markedId))
1622  m_view->Mark(id, false);
1623  }
1624 }
1625 
1626 
1631 {
1632  if (m_menuState.m_selected)
1633  ShowDialog(tr("Do you want to delete\n%1 ?")
1634  .arg(m_menuState.m_selected->m_baseName), "ConfirmDelete");
1635 }
1636 
1637 
1642 {
1643  ShowDialog(tr("Do you want to delete all marked files ?"),
1644  "ConfirmDeleteMarked");
1645 }
1646 
1647 
1652 {
1653  // Show settings dialog
1654  auto *config = new GallerySettings(m_editsAllowed);
1656  auto *ssd = new StandardSettingDialog(mainStack, "gallerysettings", config);
1657  if (!ssd->Create())
1658  {
1659  delete ssd;
1660  return;
1661  }
1662 
1663  mainStack->AddScreen(ssd);
1664 
1665  // Effect setting changes when dialog saves on exit
1666 
1667  connect(config, &GallerySettings::ClearDbPressed,
1669 
1670  connect(config, &GallerySettings::OrderChanged,
1671  this, [this]()
1672  {
1673  // Update db view, reset cover cache & reload
1674  int sortIm = gCoreContext->GetNumSetting("GalleryImageOrder");
1675  int sortDir = gCoreContext->GetNumSetting("GalleryDirOrder");
1676  m_mgr.SetSortOrder(sortIm, sortDir);
1677  m_view->ClearCache();
1679  });
1680 
1681  connect(config, &GallerySettings::DateChanged,
1682  this, [this]()
1683  {
1684  QString date = gCoreContext->GetSetting("GalleryDateFormat");
1685  m_mgr.SetDateFormat(date);
1686  BuildImageList();
1687  });
1688 
1689  connect(config, &GallerySettings::ExclusionsChanged,
1690  this, [this]()
1691  {
1692  // Request rescan
1693  QString exclusions = gCoreContext->GetSetting("GalleryIgnoreFilter");
1694  m_view->ClearCache();
1695  ImageManagerFe::IgnoreDirs(exclusions);
1696  });
1697 }
1698 
1699 
1705 {
1706  gCoreContext->SaveBoolSetting("GalleryShowHidden", show);
1707 
1708  // Update Db(s)
1710 
1711  // Reset dir thumbnail cache
1712  m_view->ClearCache();;
1713 
1715 }
1716 
1717 
1723 void GalleryThumbView::ShowDialog(const QString& msg, const QString& event)
1724 {
1725  auto *popup = new MythConfirmationDialog(&m_popupStack, msg, true);
1726 
1727  if (popup->Create())
1728  {
1729  popup->SetReturnEvent(this, event);
1730  m_popupStack.AddScreen(popup);
1731  }
1732  else
1733  delete popup;
1734 }
1735 
1736 
1741 {
1742  if (m_menuState.m_selected)
1743  {
1744  QString base = QFileInfo(m_menuState.m_selected->m_baseName).completeBaseName();
1745  QString msg = tr("Enter a new name:");
1746  auto *popup = new MythTextInputDialog(&m_popupStack, msg, FilterNone,
1747  false, base);
1748  if (popup->Create())
1749  {
1750  popup->SetReturnEvent(this, "FileRename");
1751  m_popupStack.AddScreen(popup);
1752  }
1753  else
1754  delete popup;
1755  }
1756 }
1757 
1758 
1763 {
1765 }
1766 
1767 
1772 {
1773  QString msg = tr("Enter password:");
1774  auto *popup = new MythTextInputDialog(&m_popupStack, msg, FilterNone, true);
1775  if (popup->Create())
1776  {
1777  popup->SetReturnEvent(this, "Password");
1778  m_popupStack.AddScreen(popup);
1779  }
1780  else
1781  delete popup;
1782 }
1783 
1784 
1789 {
1790  gCoreContext->SaveSetting("GalleryShowType", type);
1791 
1792  // Update Db(s)
1793  m_mgr.SetType(type);
1794 
1795  // Reset dir thumbnail cache
1796  m_view->ClearCache();
1797 
1799 }
1800 
1801 
1807 {
1808  if (m_menuState.m_selected)
1809  {
1810  QString err = reset ? m_mgr.SetCover(m_menuState.m_selected->m_id, 0)
1811  : m_mgr.SetCover(m_menuState.m_selected->m_parentId,
1812  m_menuState.m_selected->m_id);
1813  if (!err.isEmpty())
1814  ShowOkPopup(err);
1815  }
1816 }
1817 
1818 
1823 {
1824  SelectZoomWidget(-1);
1825  BuildImageList();
1826 }
1827 
1828 
1833 {
1834  SelectZoomWidget(1);
1835  BuildImageList();
1836 }
1837 
1838 
1844 {
1845  m_zoomLevel += change;
1846 
1847  // constrain to zoom levels supported by theme
1848  if (m_zoomLevel < 0)
1849  m_zoomLevel = 0;
1850  if (m_zoomLevel >= m_zoomWidgets.size())
1851  m_zoomLevel = m_zoomWidgets.size() - 1;
1852 
1853  // Store any requested change, but not constraining adjustments
1854  // Thus, changing to a theme with fewer zoom levels will not overwrite the
1855  // setting
1856  if (change != 0)
1857  gCoreContext->SaveSetting("GalleryZoomLevel", m_zoomLevel);
1858 
1859  // dump the current list widget
1860  if (m_imageList)
1861  {
1862  m_imageList->SetVisible(false);
1863  disconnect(m_imageList, nullptr, this, nullptr);
1864  }
1865 
1866  // initialise new list widget
1868 
1869  m_imageList->SetVisible(true);
1871 
1872  // Monitor list actions (after focus events have been ignored)
1877 }
1878 
1879 
1884 {
1885  auto *popup = new MythTextInputDialog(&m_popupStack,
1886  tr("Enter name of new directory"),
1887  FilterNone, false);
1888  if (popup->Create())
1889  {
1890  popup->SetReturnEvent(this, "MakeDir");
1891  m_popupStack.AddScreen(popup);
1892  }
1893  else
1894  delete popup;
1895 }
1896 
1897 
1902 {
1904  if (dir)
1905  m_mgr.CloseDevices(dir->m_device, true);
1906 }
1907 
1908 
1918 void GalleryThumbView::Copy(bool deleteAfter)
1919 {
1920  // Destination must be a dir
1921  ImagePtrK destDir = m_menuState.m_selected;
1922  if (!destDir || destDir->IsFile())
1923  return;
1924 
1925  // Use current markings, if any. Otherwise use previous markings
1926  ImageIdList markedIds = m_menuState.m_markedId;
1927  if (markedIds.isEmpty())
1928  {
1929  markedIds = m_menuState.m_prevMarkedId;
1930  if (markedIds.isEmpty())
1931  {
1932  ShowOkPopup(tr("No files specified"));
1933  return;
1934  }
1935  }
1936 
1937  // Get all files/dirs in subtree(s). Only files are copied
1938  ImageList files;
1939  ImageList dirs;
1940  m_mgr.GetDescendants(markedIds, files, dirs);
1941 
1942  if (dirs.isEmpty() && files.isEmpty())
1943  {
1944  ShowOkPopup(tr("No images"));
1945  // Nothing to clean up
1946  return;
1947  }
1948 
1949  // Child dirs appear before their subdirs. If no dirs, images are all direct children
1950  ImagePtrK aChild = dirs.isEmpty() ? files[0] : dirs[0];
1951 
1952  // Determine parent path including trailing /
1953  int basePathSize = aChild->m_filePath.size() - aChild->m_baseName.size();
1954 
1955  // Update filepaths for Db & generate URLs for filesystem copy
1956  // Only copy files, destination dirs will be created automatically
1957  TransferThread::TransferMap transfers;
1958  for (const ImagePtr & im : qAsConst(files))
1959  {
1960  // Replace base path with destination path
1961  im->m_filePath = ImageManagerFe::ConstructPath(destDir->m_filePath,
1962  im->m_filePath.mid(basePathSize));
1963 
1964  transfers.insert(im, m_mgr.BuildTransferUrl(im->m_filePath,
1965  destDir->IsLocal()));
1966  }
1967 
1968  // Create progress dialog
1969  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
1970  auto *progress = new MythUIProgressDialog(tr("Copying files"), popupStack,
1971  "copydialog");
1972  if (progress->Create())
1973  popupStack->AddScreen(progress, false);
1974  else
1975  {
1976  delete progress;
1977  progress = nullptr;
1978  }
1979 
1980  // Copy files in a servant thread
1981  TransferThread copy(transfers, false, progress);
1983  TransferThread::ImageSet failed = copy.GetResult();
1984 
1985  if (progress)
1986  progress->Close();
1987 
1988  if (!failed.isEmpty())
1989  ShowOkPopup(tr("Failed to copy %L1/%Ln file(s)", nullptr, transfers.size())
1990  .arg(failed.size()));
1991 
1992  // Don't update Db for files that failed
1993  for (const ImagePtrK & im : qAsConst(failed))
1994  transfers.remove(im);
1995 
1996  ImageListK newImages = transfers.keys();
1997 
1998  // Include dirs
1999  QStringList dirPaths;
2000  for (const ImagePtr & im : qAsConst(dirs))
2001  {
2002  QString relPath = im->m_filePath.mid(basePathSize);
2003 
2004  dirPaths << relPath;
2005 
2006  // Replace base path with destination path
2007  im->m_filePath = ImageManagerFe::ConstructPath(destDir->m_filePath, relPath);
2008 
2009  // Append dirs so that hidden state & cover is preserved for new dirs
2010  // Pre-existing dirs will take precedance over these.
2011  newImages.append(im);
2012  }
2013 
2014  // Copy empty dirs as well (will fail for non-empty dirs)
2015  if (!dirPaths.isEmpty())
2016  m_mgr.MakeDir(destDir->m_id, dirPaths, false);
2017 
2018  if (!newImages.isEmpty())
2019  {
2020  // Update Db
2021  m_mgr.CreateImages(destDir->m_id, newImages);
2022 
2023  if (deleteAfter)
2024  {
2025  // Delete files/dirs that have been successfully copied
2026  // Will fail for dirs containing images that failed to copy
2027  ImageIdList ids;
2028  for (const ImagePtrK & im : qAsConst(newImages))
2029  ids << im->m_id;
2030 
2031  m_mgr.DeleteFiles(ids);
2032  }
2033  }
2034 }
2035 
2036 
2047 {
2048  // Destination must be a dir
2049  ImagePtrK destDir = m_menuState.m_selected;
2050  if (!destDir || destDir->IsFile())
2051  return;
2052 
2053  // Use current markings, if any. Otherwise use previous markings
2054  ImageIdList markedIds = m_menuState.m_markedId;
2055  if (markedIds.isEmpty())
2056  {
2057  markedIds = m_menuState.m_prevMarkedId;
2058  if (markedIds.isEmpty())
2059  {
2060  ShowOkPopup(tr("No files specified"));
2061  return;
2062  }
2063  }
2064 
2065  // Note UI mandates that transferees are either all local or all remote
2066  if (destDir->IsLocal() != ImageItem::IsLocalId(markedIds[0]))
2067  {
2068  // Moves between hosts require copy/delete
2069  Copy(true);
2070  return;
2071  }
2072 
2073  // Get marked images. Each file and dir will be renamed
2074  ImageList files;
2075  ImageList dirs;
2076  if (m_mgr.GetImages(markedIds, files, dirs) <= 0)
2077  {
2078  ShowOkPopup(tr("No images specified"));
2079  // Nothing to clean up
2080  return;
2081  }
2082  ImageList images = dirs + files;
2083 
2084  // Determine parent from first dir or pic
2085  ImagePtr aChild = images[0];
2086 
2087  // Determine parent path including trailing /
2088  // Note UI mandates that transferees all have same parent.
2089  int basePathSize = aChild->m_filePath.size() - aChild->m_baseName.size();
2090  QString parentPath = aChild->m_filePath.left(basePathSize);
2091 
2092  // Determine destination URLs
2093  TransferThread::TransferMap transfers;
2094  for (const QSharedPointer<ImageItem> & im : qAsConst(images))
2095  {
2096  // Replace base path with destination path
2097  QString newPath = ImageManagerFe::ConstructPath(destDir->m_filePath,
2098  im->m_filePath.mid(basePathSize));
2099 
2100  transfers.insert(im, m_mgr.BuildTransferUrl(newPath, aChild->IsLocal()));
2101  }
2102 
2103  // Create progress dialog
2104  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
2105  auto *progress = new MythUIProgressDialog(tr("Moving files"), popupStack,
2106  "movedialog");
2107 
2108  if (progress->Create())
2109  popupStack->AddScreen(progress, false);
2110  else
2111  {
2112  delete progress;
2113  progress = nullptr;
2114  }
2115 
2116  // Move files in a servant thread
2117  TransferThread move(transfers, true, progress);
2118  WaitUntilDone(move);
2119  TransferThread::ImageSet failed = move.GetResult();
2120 
2121  if (progress)
2122  progress->Close();
2123 
2124  if (!failed.isEmpty())
2125  ShowOkPopup(tr("Failed to move %L1/%Ln file(s)", nullptr, transfers.size())
2126  .arg(failed.size()));
2127 
2128  // Don't update Db for files that failed
2129  for (const ImagePtrK & im : qAsConst(failed))
2130  transfers.remove(im);
2131 
2132  if (!transfers.isEmpty())
2133  {
2134  ImageListK moved = transfers.keys();
2135 
2136  // Unmark moved files
2137  for (const ImagePtrK & im : qAsConst(moved))
2138  m_view->Mark(im->m_id, false);
2139 
2140  // Update Db
2141  m_mgr.MoveDbImages(destDir, moved, parentPath);
2142  }
2143 }
2144 
2145 
2150 {
2151  QString path = m_mgr.CreateImport();
2152  if (path.isEmpty())
2153  {
2154  ShowOkPopup(tr("Failed to create temporary directory."));
2155  return;
2156  }
2157 
2158  // Replace placeholder in command
2159  QString cmd = gCoreContext->GetSetting("GalleryImportCmd");
2160  cmd.replace("%TMPDIR%", path);
2161 
2162  // Run command in a separate thread
2163  MythUIBusyDialog *busy =
2164  ShowBusyPopup(tr("Running Import command.\nPlease wait..."));
2165 
2166  ShellThread thread(cmd, path);
2167  WaitUntilDone(thread);
2168 
2169  if (busy)
2170  busy->Close();
2171 
2172  int error = thread.GetResult();
2173  if (error != 0)
2174  ShowOkPopup(tr("Import command failed.\nError: %1").arg(error));
2175 
2176  // Rescan local devices
2177  QString err = m_mgr.ScanImagesAction(true, true);
2178  if (!err.isEmpty())
2179  LOG(VB_GENERAL, LOG_ERR, LOC + err);
2180 }
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:854
kPicAndVideo
@ kPicAndVideo
Show Pictures & Videos.
Definition: imagemanager.h:78
ImagePtrK
QSharedPointer< ImageItemK > ImagePtrK
Definition: imagetypes.h:165
MythMainWindow::GetMainStack
MythScreenStack * GetMainStack()
Definition: mythmainwindow.cpp:315
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
PHOTO_DB_ID
#define PHOTO_DB_ID
Definition: imagetypes.h:29
ImageDbReader::GetImages
int GetImages(const ImageIdList &ids, ImageList &files, ImageList &dirs) const
Returns images (local or remote but not a combination)
Definition: imagemanager.cpp:1862
MythEvent::MythEventMessage
static Type MythEventMessage
Definition: mythevent.h:79
MThread::start
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:286
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
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:2008
TransferThread::m_failed
ImageSet m_failed
Definition: gallerythumbview.cpp:142
GalleryThumbView::m_positionText
MythUIText * m_positionText
Definition: gallerythumbview.h:136
DirectoryView::GetPosition
QString GetPosition() const
Get positional status.
Definition: galleryviews.cpp:490
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:1138
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:2254
GalleryThumbView::MakeDir
void MakeDir()
Show dialog to input new directory name.
Definition: gallerythumbview.cpp:1883
GalleryThumbView::SelectZoomWidget
void SelectZoomWidget(int change)
Change buttonlist to use a different size.
Definition: gallerythumbview.cpp:1843
ImageManagerFe::ScanImagesAction
QString ScanImagesAction(bool start, bool local=false)
Handle scanner start/stop commands.
Definition: imagemanager.cpp:2043
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:496
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:369
MythUIProgressBar::SetStart
void SetStart(int value)
Definition: mythuiprogressbar.cpp:63
GalleryThumbView::DirSelectDown
void DirSelectDown()
Goes one directory level down.
Definition: gallerythumbview.cpp:1492
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:742
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:2212
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
DialogCompletionEvent::kEventType
static Type kEventType
Definition: mythdialogbox.h:57
GalleryThumbView::ShowPassword
void ShowPassword()
Displays dialog to accept password.
Definition: gallerythumbview.cpp:1771
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:2196
MythUIProgressBar::SetUsed
void SetUsed(int value)
Definition: mythuiprogressbar.cpp:69
GalleryThumbView::GalleryThumbView
GalleryThumbView(MythScreenStack *parent, const char *name)
Constructor.
Definition: gallerythumbview.cpp:167
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:639
TransferThread::m_files
TransferMap m_files
Maps source filepath to destination filepath.
Definition: gallerythumbview.cpp:141
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:69
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:2089
GalleryThumbView::MenuAction
void MenuAction(MythMenu *mainMenu)
Add a Action submenu.
Definition: gallerythumbview.cpp:1203
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
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:489
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:2149
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:414
GalleryThumbView::ZoomIn
void ZoomIn()
Use smaller buttonlist widgets.
Definition: gallerythumbview.cpp:1832
GalleryThumbView::HideHidden
void HideHidden()
Definition: gallerythumbview.h:99
GalleryThumbView::DoHideItem
void DoHideItem(bool hide=true)
Hide or unhide item.
Definition: gallerythumbview.cpp:1586
TransferThread::TransferThread
TransferThread(TransferMap files, bool move, MythUIProgressDialog *dialog)
Definition: gallerythumbview.cpp:63
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:60
ImageManagerFe::CloseDevices
void CloseDevices(int devId=DEVICE_INVALID, bool eject=false)
Definition: imagemanager.cpp:2435
FlatView::Select
bool Select(int id, int fallback=0)
Selects first occurrence of an image.
Definition: galleryviews.cpp:117
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:215
ImageManagerFe::ChangeOrientation
QString ChangeOrientation(ImageFileTransform transform, const ImageIdList &ids)
Apply an orientation transform to images.
Definition: imagemanager.cpp:2120
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:1042
mythsystemlegacy.h
DirectoryView::MarkAll
void MarkAll()
Mark all images/dirs.
Definition: galleryviews.cpp:729
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:985
GalleryThumbView::keyPressEvent
bool keyPressEvent(QKeyEvent *event) override
Handle keypresses.
Definition: gallerythumbview.cpp:279
GalleryThumbView::DoSetCover
void DoSetCover(bool reset=false)
Set or reset thumbnails to use for a directory cover.
Definition: gallerythumbview.cpp:1806
MythUIButtonListItem
Definition: mythuibuttonlist.h:41
TransferThread
Worker thread for copying/moving files.
Definition: gallerythumbview.cpp:56
ImageFileTransform
ImageFileTransform
Image transformations.
Definition: imagemetadata.h:46
TransferThread::m_move
bool m_move
Copy if false, Move if true.
Definition: gallerythumbview.cpp:140
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:26
GalleryThumbView::ResetUiSelection
void ResetUiSelection()
Clears all text widgets for selected item.
Definition: gallerythumbview.cpp:962
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:1320
kPicOnly
@ kPicOnly
Hide videos.
Definition: imagemanager.h:79
GalleryThumbView::ShowSettings
void ShowSettings()
Show configuration screen.
Definition: gallerythumbview.cpp:1651
MythUIButtonList::itemClicked
void itemClicked(MythUIButtonListItem *item)
ImageDbReader::SetSortOrder
void SetSortOrder(int order, int dirOrder)
Definition: imagemanager.h:411
GalleryThumbView::UpdateScanProgress
void UpdateScanProgress(const QString &scanner, int current, int total)
Update progressbar with scan status.
Definition: gallerythumbview.cpp:881
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:1104
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:268
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:1574
MythDialogBox
Basic menu dialog, message and a list of options.
Definition: mythdialogbox.h:166
menu
static MythThemedMenu * menu
Definition: mythtv-setup.cpp:57
GalleryThumbView::SelectImage
void SelectImage(int id)
Select item if it is displayed.
Definition: gallerythumbview.cpp:1380
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:1704
mark
Definition: lang.cpp:22
ImageDbReader::GetType
int GetType() const
Definition: imagemanager.h:405
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:1269
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:674
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:1902
GalleryThumbView::StartSlideshow
void StartSlideshow(ImageSlideShowType mode)
Start slideshow screen.
Definition: gallerythumbview.cpp:1435
GalleryThumbView::ShowRenameInput
void ShowRenameInput()
Show dialog to allow input.
Definition: gallerythumbview.cpp:1740
GalleryThumbView::ShowDialog
void ShowDialog(const QString &msg, const QString &event="")
Show a confirmation dialog.
Definition: gallerythumbview.cpp:1723
FlatView::GetAllNodes
ImageListK GetAllNodes() const
Get all images/dirs in view.
Definition: galleryviews.cpp:51
DirectoryView::InvertMarked
void InvertMarked()
Mark all unmarked items, unmark all marked items.
Definition: galleryviews.cpp:761
MythUIThemeCache::RemoveFromCacheByFile
void RemoveFromCacheByFile(const QString &File)
Definition: mythuithemecache.cpp:525
GalleryThumbView::DeleteMarked
void DeleteMarked()
Confirm user deletion of marked files.
Definition: gallerythumbview.cpp:1641
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:2355
ShellThread::m_command
QString m_command
Definition: gallerythumbview.cpp:50
MythUIBusyDialog
Definition: mythprogressdialog.h:36
ImageDbReader::GetVisibility
bool GetVisibility() const
Definition: imagemanager.h:406
GalleryThumbView::ZoomOut
void ZoomOut()
Use larger buttonlist widgets.
Definition: gallerythumbview.cpp:1822
MThread::isFinished
bool isFinished(void) const
Definition: mthread.cpp:261
GalleryThumbView::ResetExif
void ResetExif()
Definition: gallerythumbview.h:77
FlatView::GetSelected
ImagePtrK GetSelected() const
Get current selection.
Definition: galleryviews.cpp:64
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:2152
GallerySettings::ClearDbPressed
void ClearDbPressed()
GalleryThumbView::ItemClicked
void ItemClicked(MythUIButtonListItem *item)
Action item click.
Definition: gallerythumbview.cpp:1392
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:59
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:1611
GalleryThumbView::DirSelectUp
bool DirSelectUp()
Goes up one directory level.
Definition: gallerythumbview.cpp:1471
GalleryThumbView::UpdateImageItem
void UpdateImageItem(MythUIButtonListItem *item)
Initialises a single buttonlist item.
Definition: gallerythumbview.cpp:720
TransferThread::GetResult
ImageSet GetResult(void)
Definition: gallerythumbview.cpp:67
GalleryThumbView::ShowDetails
void ShowDetails()
Shows exif info/details about an item.
Definition: gallerythumbview.cpp:1762
GalleryThumbView::CheckThumbnail
QString CheckThumbnail(MythUIButtonListItem *item, const ImagePtrK &im, ImageIdList &request, int index)
Verify thumbnail is known to exist.
Definition: gallerythumbview.cpp:827
RemoteFile::CopyFile
static bool CopyFile(const QString &src, const QString &dst, bool overwrite=false, bool verify=false)
Definition: remotefile.cpp:588
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:916
GalleryThumbView::TransformItem
void TransformItem(ImageFileTransform tran=kRotateCW)
Apply transform to an image.
Definition: gallerythumbview.cpp:1556
ImageManagerFe::CreateImport
QString CreateImport()
Definition: imagemanager.cpp:2532
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:1543
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:504
MythCoreContext::GetBoolSetting
bool GetBoolSetting(const QString &key, bool defaultval=false)
Definition: mythcorecontext.cpp:910
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:61
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:2046
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:2298
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:408
GalleryThumbView::HidePictures
void HidePictures()
Definition: gallerythumbview.h:105
ImageManagerFe
The image manager for use by Frontends.
Definition: imagemanager.h:456
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:151
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:1528
ImageIdList
QList< int > ImageIdList
Definition: imagetypes.h:60
ShellThread::GetResult
int GetResult(void) const
Definition: gallerythumbview.cpp:32
ImageManagerFe::CrumbName
QString CrumbName(ImageItemK &im, bool getPath=false) const
Return a displayable name (with optional path) for an image.
Definition: imagemanager.cpp:2414
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:678
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:1630
DirectoryView::GetMenuSubjects
MenuSubjects GetMenuSubjects()
Determine current selection, markings & various info to support menu display.
Definition: galleryviews.cpp:813
GalleryThumbView::ShowHidden
void ShowHidden()
Definition: gallerythumbview.h:98
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:102
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:186
build_compdb.action
action
Definition: build_compdb.py:9
DirectoryView::ClearCache
void ClearCache()
Clears UI cache.
Definition: galleryviews.cpp:893
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:591
GalleryThumbView::MarkAll
void MarkAll()
Definition: gallerythumbview.h:87
DirectoryView::Clear
void Clear(bool resetParent=true)
Resets view.
Definition: galleryviews.cpp:718
ShellThread::ShellThread
ShellThread(QString cmd, QString path)
Definition: gallerythumbview.cpp:29
GalleryThumbView::UnmarkItem
void UnmarkItem()
Definition: gallerythumbview.h:85
MThread::objectName
QString objectName(void) const
Definition: mthread.cpp:246
MythMainWindow::GetStack
MythScreenStack * GetStack(const QString &Stackname)
Definition: mythmainwindow.cpp:320
GalleryThumbView::DoShowType
void DoShowType(int type)
Show/hide pictures or videos.
Definition: gallerythumbview.cpp:1788
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:908
GalleryThumbView::DoMarkItem
void DoMarkItem(bool mark)
Mark or unmark a single item.
Definition: gallerythumbview.cpp:1510
GalleryThumbView::MenuTransform
void MenuTransform(MythMenu *mainMenu)
Add a Transform submenu.
Definition: gallerythumbview.cpp:1167
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:842
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:2325
GalleryThumbView::m_captionText
MythUIText * m_captionText
Definition: gallerythumbview.h:131
ShellThread::m_path
QString m_path
Definition: gallerythumbview.cpp:51
GalleryThumbView::DoScanAction
void DoScanAction(bool start)
Action scan request.
Definition: gallerythumbview.cpp:1423
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:885
GalleryThumbView::HideVideos
void HideVideos()
Definition: gallerythumbview.h:106
GalleryThumbView::MarkItem
void MarkItem()
Definition: gallerythumbview.h:84
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
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:772
GalleryThumbView::MenuMarked
void MenuMarked(MythMenu *mainMenu)
Adds a Marking submenu.
Definition: gallerythumbview.cpp:1085
MythUIButtonListItem::setChecked
void setChecked(CheckState state)
Definition: mythuibuttonlist.cpp:3629
MythScreenStack::AddScreen
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Definition: mythscreenstack.cpp:50
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:196
ImageManagerFe::ScanQuery
static QStringList ScanQuery()
Returns storage group scanner status.
Definition: imagemanager.cpp:2069
ShowOkPopup
MythConfirmationDialog * ShowOkPopup(const QString &message, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
Definition: mythdialogbox.cpp:563
ImageManagerFe::RenameFile
QString RenameFile(const ImagePtrK &im, const QString &name)
Rename an image.
Definition: imagemanager.cpp:2234
ImageManagerFe::ShortDateOf
QString ShortDateOf(const ImagePtrK &im) const
Return a short datestamp for thumbnail captions.
Definition: imagemanager.cpp:2381
GalleryThumbView::Eject
void Eject()
Remove local device (or Import) from Gallery.
Definition: gallerythumbview.cpp:1901
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:34
MythCoreContext::SaveBoolSetting
void SaveBoolSetting(const QString &key, bool newValue)
Definition: mythcorecontext.h:165
TransferThread::m_dialog
MythUIProgressDialog * m_dialog
Images for which copy/move failed.
Definition: gallerythumbview.cpp:143
ShellThread::m_result
int m_result
Definition: gallerythumbview.cpp:49
kCloneDir
@ kCloneDir
A device sub dir comprised from multiple SG dirs.
Definition: imagetypes.h:37
GALLERY_DB_ID
#define GALLERY_DB_ID
Definition: imagetypes.h:27
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:902
GalleryThumbView::StopScan
void StopScan()
Definition: gallerythumbview.h:112
GalleryThumbView::Start
void Start()
Start Thumbnail screen.
Definition: gallerythumbview.cpp:615
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:2448