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