MythTV  master
gallerythumbview.cpp
Go to the documentation of this file.
1 // C++
2 #include <algorithm>
3 #include <chrono> // for milliseconds
4 #include <thread> // for sleep_for
5 #include <utility>
6 
7 // Qt
8 #include <QApplication>
9 
10 // MythTV
11 #include "libmythbase/compat.h"
13 #include "libmythbase/remotefile.h"
17 #include "libmythui/mythuitext.h"
18 
19 // MythFrontend
20 #include "galleryconfig.h"
21 #include "gallerythumbview.h"
22 
23 #define LOC QString("Thumbview: ")
24 
25 // EXIF tag 0x9286 UserComment can contain garbage
26 static QString clean_comment(const QString &comment)
27 {
28  QString result;
29  std::copy_if(comment.cbegin(), comment.cend(), std::back_inserter(result), [](QChar x) { return x.isPrint(); } );
30  return result;
31 }
32 
34 class ShellThread: public MThread
35 {
36 public:
37  ShellThread(QString cmd, QString path)
38  : MThread("Import"), m_command(std::move(cmd)), m_path(std::move(path)) {}
39 
40  int GetResult(void) const { return m_result; }
41 
42  void run() override // MThread
43  {
44  RunProlog();
45 
46  QString cmd = QString("cd %1 && %2").arg(m_path, m_command);
47  LOG(VB_GENERAL, LOG_INFO, QString("Executing \"%1\"").arg(cmd));
48 
49  m_result = myth_system(cmd);
50 
51  LOG(VB_GENERAL, LOG_INFO, QString(" ...with result %1").arg(m_result));
52 
53  RunEpilog();
54  }
55 
56 private:
57  int m_result {0};
58  QString m_command;
59  QString m_path;
60 };
61 
62 
64 class TransferThread : public MThread
65 {
66  Q_DECLARE_TR_FUNCTIONS(FileTransferWorker);
67 public:
68  using TransferMap = QMap<ImagePtrK, QString>;
69  using ImageSet = QSet<ImagePtrK>;
70 
71  TransferThread(TransferMap files, bool move, MythUIProgressDialog *dialog)
72  : MThread("FileTransfer"),
73  m_move(move), m_files(std::move(files)), m_dialog(dialog) {}
74 
75  ImageSet GetResult(void) { return m_failed; }
76 
77  void run() override // MThread
78  {
79  RunProlog();
80 
81  QString action = m_move ? tr("Moving") : tr("Copying");
82 
83  // Sum file sizes
84  auto keys = m_files.keys();
85  auto add_size = [](int t, const ImagePtrK & im){ return t + im->m_size; };
86  int total = std::accumulate(keys.cbegin(), keys.cend(), 0, add_size);
87 
88  int progressSize = 0;
89  for (auto it = m_files.constKeyValueBegin();
90  it != m_files.constKeyValueEnd(); it++)
91  {
92  const ImagePtrK & im = it->first;
93  QString newPath = it->second;
94  // Update progress dialog
95  if (m_dialog)
96  {
97  QString message = QString("%1 %2\n%3")
98  .arg(action, QFileInfo(im->m_url).fileName(),
99  ImageAdapterBase::FormatSize(im->m_size / 1024));
100 
101  auto *pue = new ProgressUpdateEvent(progressSize, total, message);
102  QApplication::postEvent(m_dialog, pue);
103  }
104 
105  LOG(VB_FILE, LOG_INFO, QString("%2 %3 -> %4")
106  .arg(action, im->m_url, newPath));
107 
108  bool success = m_move ? RemoteFile::MoveFile(im->m_url, newPath)
109  : RemoteFile::CopyFile(im->m_url, newPath,
110  false, true);
111  if (!success)
112  {
113  // Flag failures
114  m_failed.insert(im);
115 
116  LOG(VB_GENERAL, LOG_ERR,
117  QString("%1: Failed to copy/move %2 -> %3")
118  .arg(objectName(), im->m_url, m_files[im]));
119  }
120 
121  progressSize += im->m_size;
122  }
123 
124  // Update progress dialog
125  if (m_dialog)
126  {
127  auto *pue =
128  new ProgressUpdateEvent(progressSize, total, tr("Complete"));
129  QApplication::postEvent(m_dialog, pue);
130  }
131 
132  RunEpilog();
133  }
134 
135 private:
136  bool m_move;
140 };
141 
142 
147 static void WaitUntilDone(MThread &worker)
148 {
149  worker.start();
150  while (!worker.isFinished())
151  {
152  std::this_thread::sleep_for(1ms);
153  QCoreApplication::processEvents();
154  }
155 }
156 
157 
164  : MythScreenType(parent, name),
165  m_popupStack(*GetMythMainWindow()->GetStack("popup stack")),
166  m_mgr(ImageManagerFe::getInstance()),
167  // This screen uses a single fixed view (Parent dir, ordered dirs, ordered images)
168  m_view(new DirectoryView(kOrdered)),
169  m_infoList(*this),
170  // Start in edit mode unless a password exists
171  m_editsAllowed(gCoreContext->GetSetting("GalleryPassword").isEmpty())
172 {
173  // Hide hidden when edits disallowed
174  if (!m_editsAllowed)
175  m_mgr.SetVisibility(false);
176 }
177 
178 
183 {
184  LOG(VB_GUI, LOG_DEBUG, LOC + "Exiting Gallery");
185  delete m_view;
186 }
187 
188 
193 {
194  LOG(VB_GUI, LOG_DEBUG, LOC + "Closing Gallery");
195 
197 
198  // Cleanup local devices
200 
201  // Cleanup view
202  m_view->Clear();
203 
205 }
206 
207 
212 {
213  if (!LoadWindowFromXML("image-ui.xml", "gallery", this))
214  return false;
215 
216  // Determine zoom levels supported by theme
217  // images0 must exist; images1, images2 etc. are optional and enable zoom
218  int zoom = 0;
219  MythUIButtonList *widget = nullptr;
220  do
221  {
222  QString name = QString("images%1").arg(zoom++);
223  widget = dynamic_cast<MythUIButtonList *>(this->GetChild(name));
224  if (widget)
225  {
226  m_zoomWidgets.append(widget);
227  widget->SetVisible(false);
228  }
229  }
230  while (widget);
231 
232  if (m_zoomWidgets.isEmpty())
233  {
234  LOG(VB_GENERAL, LOG_ERR, LOC + "Screen 'Gallery' is missing 'images0'");
235  return false;
236  }
237  LOG(VB_GUI, LOG_DEBUG, LOC + QString("Screen 'Gallery' found %1 zoom levels")
238  .arg(m_zoomWidgets.size()));
239 
240  // File details list is managed elsewhere
241  if (!m_infoList.Create(false))
242  {
243  LOG(VB_GENERAL, LOG_ERR, LOC + "Cannot load 'Info buttonlist'");
244  return false;
245  }
246 
247  UIUtilW::Assign(this, m_captionText, "caption");
248  UIUtilW::Assign(this, m_emptyText, "noimages");
249  UIUtilW::Assign(this, m_positionText, "position");
250  UIUtilW::Assign(this, m_crumbsText, "breadcrumbs");
251  UIUtilW::Assign(this, m_hideFilterText, "hidefilter");
252  UIUtilW::Assign(this, m_typeFilterText, "typefilter");
253  UIUtilW::Assign(this, m_scanProgressText, "scanprogresstext");
254  UIUtilW::Assign(this, m_scanProgressBar, "scanprogressbar");
255 
256  if (m_scanProgressText)
258  if (m_scanProgressBar)
260 
261  BuildFocusList();
262 
263  // Initialise list widget with appropriate zoom level for this theme.
264  m_zoomLevel = gCoreContext->GetNumSetting("GalleryZoomLevel", 0);
265  SelectZoomWidget(0);
266 
267  return true;
268 }
269 
270 
275 bool GalleryThumbView::keyPressEvent(QKeyEvent *event)
276 {
277  if (GetFocusWidget()->keyPressEvent(event))
278  return true;
279 
280  QStringList actions;
281  bool handled = GetMythMainWindow()->TranslateKeyPress("Images", event, actions);
282 
283  for (int i = 0; i < actions.size() && !handled; i++)
284  {
285  const QString& action = actions[i];
286  handled = true;
287 
288  if (action == "MENU")
289  MenuMain();
290  else if (action == "INFO")
291  ShowDetails();
292  else if (action == "ZOOMIN")
293  ZoomIn();
294  else if (action == "ZOOMOUT")
295  ZoomOut();
296  else if (action == "ROTRIGHT")
297  RotateCW();
298  else if (action == "ROTLEFT")
299  RotateCCW();
300  else if (action == "FLIPHORIZONTAL")
301  FlipHorizontal();
302  else if (action == "FLIPVERTICAL")
303  FlipVertical();
304  else if (action == "COVER")
305  {
306  ImagePtrK im = m_view->GetSelected();
307  if (m_editsAllowed && im)
308  {
309  if (im == m_view->GetParent())
310  {
311  // Reset dir
312  m_mgr.SetCover(im->m_id, 0);
313  }
314  else
315  {
316  // Set parent cover
317  m_mgr.SetCover(im->m_parentId, im->m_id);
318  }
319  }
320  }
321  else if (action == "PLAY")
322  {
323  Slideshow();
324  }
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  {
354  handled = false;
355  }
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::kMythEventMessage)
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 : std::as_const(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  QStringList idDeleted =
437  extra[0].split(",", Qt::SkipEmptyParts);
438  RemoveImages(idDeleted);
439  }
440  if (extra.size() >= 2)
441  {
442  QStringList idChanged =
443  extra[1].split(",", Qt::SkipEmptyParts);
444  RemoveImages(idChanged, false);
445  }
446 
447  // Refresh display
449  }
450  else if (token[0] == "IMAGE_DEVICE_CHANGED")
451  {
452  // Expects list of url prefixes
453  LOG(VB_GENERAL, LOG_DEBUG, LOC +
454  QString("Rx %1 : %2").arg(token[0], extra.join(",")));
455 
456  // Clear everything. Local devices will be rebuilt
457  m_view->Clear();
458  m_thumbExists.clear();
459 
460  // Remove thumbs & images from image cache using supplied prefixes
461  for (const QString & url : std::as_const(extra))
463 
464  // Refresh display
466  }
467  else if (token[0] == "IMAGE_SCAN_STATUS" && extra.size() == 3)
468  {
469  // Expects scanner id, scanned#, total#
470  UpdateScanProgress(extra[0], extra[1].toInt(), extra[2].toInt());
471  }
472  }
473  else if (event->type() == DialogCompletionEvent::kEventType)
474  {
475  auto *dce = (DialogCompletionEvent *)(event);
476 
477  QString resultid = dce->GetId();
478  int buttonnum = dce->GetResult();
479 
480  if (resultid == "FileRename")
481  {
482  QString newName = dce->GetResultText();
484  {
485  QString err = m_mgr.RenameFile(m_menuState.m_selected,
486  newName);
487  if (!err.isEmpty())
488  ShowOkPopup(err);
489  }
490  }
491  else if (resultid == "MakeDir")
492  {
494  {
495  // Prohibit subtrees
496  QString name = dce->GetResultText();
497  QString err = name.contains("/")
498  ? tr("Invalid Name")
500  QStringList(name));
501  if (!err.isEmpty())
502  ShowOkPopup(err);
503  }
504  }
505  else if (resultid == "SlideOrderMenu")
506  {
507  SlideOrderType slideOrder = kOrdered;
508 
509  switch (buttonnum)
510  {
511  case 0: slideOrder = kOrdered; break;
512  case 1: slideOrder = kShuffle; break;
513  case 2: slideOrder = kRandom; break;
514  case 3: slideOrder = kSeasonal; break;
515  }
516  gCoreContext->SaveSetting("GallerySlideOrder", slideOrder);
517  LOG(VB_FILE, LOG_DEBUG, LOC + QString("Order %1").arg(slideOrder));
518  }
519  else if (resultid == "ImageCaptionMenu")
520  {
521  ImageCaptionType captions = kNoCaption;
522 
523  switch (buttonnum)
524  {
525  case 0: captions = kNameCaption; break;
526  case 1: captions = kDateCaption; break;
527  case 2: captions = kUserCaption; break;
528  case 3: captions = kNoCaption; break;
529  }
530  gCoreContext->SaveSetting("GalleryImageCaption", captions);
531  BuildImageList();
532  }
533  else if (resultid == "DirCaptionMenu")
534  {
535  ImageCaptionType captions = kNoCaption;
536 
537  switch (buttonnum)
538  {
539  case 0: captions = kNameCaption; break;
540  case 1: captions = kDateCaption; break;
541  case 2: captions = kNoCaption; break;
542  }
543  gCoreContext->SaveSetting("GalleryDirCaption", captions);
544  BuildImageList();
545  }
546  else if (resultid == "Password")
547  {
548  QString password = dce->GetResultText();
549  m_editsAllowed = (password == gCoreContext->GetSetting("GalleryPassword"));
550  }
551  else if (buttonnum == 1)
552  {
553  // Confirm current file deletion
554  QString err;
555  if (resultid == "ConfirmDelete" && m_menuState.m_selected)
556  {
558  err = m_mgr.DeleteFiles(ids);
559  }
560  // Confirm marked file deletion
561  else if (resultid == "ConfirmDeleteMarked")
562  {
564  }
565  else
566  {
567  return;
568  }
569 
570  if (!err.isEmpty())
571  ShowOkPopup(err);
572  }
573  }
574 }
575 
576 
582 void GalleryThumbView::RemoveImages(const QStringList &ids, bool deleted)
583 {
584  for (const QString & id : std::as_const(ids))
585  {
586  // Remove image from view
587  QStringList urls = m_view->RemoveImage(id.toInt(), deleted);
588  // Cleanup url lookup
589  m_thumbExists.remove(id.toInt());
590 
591  // Remove thumbs & images from image cache
592  for (const QString & url : std::as_const(urls))
593  {
594  LOG(VB_FILE, LOG_DEBUG, LOC +
595  QString("Clearing image cache of '%1'").arg(url));
596 
598  }
599  }
600 }
601 
602 
607 {
608  // Detect any running BE scans
609  // Expects OK, scanner id, current#, total#
610  QStringList message = ImageManagerFe::ScanQuery();
611  if (message.size() == 4 && message[0] == "OK")
612  {
613  UpdateScanProgress(message[1], message[2].toInt(), message[3].toInt());
614  }
615 
616  // Only receive events after device/scan status has been established
617  gCoreContext->addListener(this);
618 
619  // Start at Root if devices exist. Otherwise go straight to SG node
621 
622  LoadData(start);
623 }
624 
625 
631 {
633 
634  // Load view for parent directory
635  if (m_view->LoadFromDb(parent))
636  {
637  m_imageList->SetVisible(true);
638  if (m_emptyText)
639  {
640  m_emptyText->SetVisible(false);
641  m_emptyText->Reset();
642  }
643 
644  // Construct the buttonlist
645  BuildImageList();
646  }
647  else
648  {
649  m_infoList.Hide();
650  m_imageList->SetVisible(false);
651  if (m_emptyText)
652  {
653  m_emptyText->SetVisible(true);
654  m_emptyText->SetText(tr("No images found.\n"
655  "Scan storage group using menu,\n"
656  "or insert/mount local media.\n"));
657  }
658  }
659 }
660 
661 
666 {
667  m_imageList->Reset();
668  m_pendingMap.clear();
669 
670  // Get parent & all children
671  ImageListK nodes = m_view->GetAllNodes();
672  ImagePtrK selected = m_view->GetSelected();
673 
674  // go through the entire list and update
675  for (const ImagePtrK & im : std::as_const(nodes))
676  {
677  if (im)
678  {
679  // Data must be set by constructor: First item is automatically
680  // selected and must have data available for selection event, as
681  // subsequent reselection of same item will always fail.
682  auto *item = new MythUIButtonListItem(m_imageList, "",
683  QVariant::fromValue(im));
684 
685  item->setCheckable(true);
686  item->setChecked(MythUIButtonListItem::NotChecked);
687 
688  // assign and display all information about
689  // the current item, like title and subdirectory count
690  UpdateImageItem(item);
691 
692  // Treat parent differently
693  if (im == nodes[0])
694  {
695  // Only non-root parents can ascend
696  if (im->m_id != GALLERY_DB_ID)
697  item->DisplayState("upfolder", "parenttype");
698  }
699  else if (im == selected)
700  {
701  // Reinstate the active button item. Note this would fail for parent
703  }
704  }
705  }
706 }
707 
708 
714 {
715  auto im = item->GetData().value<ImagePtrK >();
716  if (!im)
717  return;
718 
719  // Allow themes to distinguish between roots, folders, pics, videos
720  switch (im->m_type)
721  {
722  case kDevice:
723  case kCloneDir:
724  case kDirectory:
725  if (im->m_dirCount > 0)
726  {
727  item->SetText(QString("%1/%2")
728  .arg(im->m_fileCount).arg(im->m_dirCount),
729  "childcount");
730  }
731  else
732  {
733  item->SetText(QString::number(im->m_fileCount), "childcount");
734  }
735 
736  item->DisplayState(im->IsDevice() ? "device" : "subfolder", "buttontype");
737  break;
738 
739  case kImageFile:
740  item->DisplayState("image", "buttontype");
741  break;
742 
743  case kVideoFile:
744  item->DisplayState("video", "buttontype");
745  break;
746 
747  default:
748  break;
749  }
750 
751  // Allow theme to distinguish visible/hidden nodes
752  QString hideState = (im->m_isHidden) ? "hidden" : "visible";
753  item->DisplayState(hideState, "buttonstate");
754 
755  // Caption
756  QString text;
758  im->IsFile() ? "GalleryImageCaption"
759  : "GalleryDirCaption");
760  switch (show)
761  {
762  case kNameCaption: text = m_mgr.CrumbName(*im); break;
763  case kDateCaption: text = m_mgr.ShortDateOf(im); break;
764  case kUserCaption: text = clean_comment(im->m_comment); break;
765  default:
766  case kNoCaption: text = ""; break;
767  }
768  item->SetText(text);
769 
770  // Set marked state
772  = m_view->IsMarked(im->m_id)
775 
776  item->setChecked(state);
777 
778  // Thumbnails required
779  ImageIdList request;
780 
781  if (im->m_thumbNails.size() == 1)
782  {
783  // Single thumbnail
784  QString url = CheckThumbnail(item, im, request, 0);
785 
786  if (!url.isEmpty())
787  UpdateThumbnail(item, im, url, 0);
788  }
789  else
790  {
791  // Dir showing up to 4 thumbs. Set them all at same time
792  InfoMap thumbMap;
793  for (int index = 0; index < im->m_thumbNails.size(); ++index)
794  {
795  QString url = CheckThumbnail(item, im, request, index);
796  if (!url.isEmpty())
797  thumbMap.insert(QString("thumbimage%1").arg(index), url);
798  }
799  if (!thumbMap.isEmpty())
800  item->SetImageFromMap(thumbMap);
801  }
802 
803  // Request creation/verification of unknown thumbnails.
804  if (!request.isEmpty())
805  m_mgr.CreateThumbnails(request, im->IsDirectory());
806 }
807 
808 
821  ImageIdList &request, int index)
822 {
823  ThumbPair thumb(im->m_thumbNails.at(index));
824  int id = thumb.first;
825 
826  if (m_thumbExists.contains(id))
827  return thumb.second;
828 
829  // Request BE thumbnail check if it is not already pending
830  if (!m_pendingMap.contains(id))
831  request << id;
832 
833  // Note this button is awaiting an update
834  m_pendingMap.insert(id, qMakePair(item, index));
835 
836  return "";
837 }
838 
839 
848  const ImagePtrK& im, const QString &url,
849  int index)
850 {
851  if (im->m_thumbNails.size() == 1)
852  {
853  // Pics, dirs & videos use separate widgets
854  switch (im->m_type)
855  {
856  case kImageFile: button->SetImage(url); break;
857  case kVideoFile: button->SetImage(url, "videoimage"); break;
858  default: button->SetImage(url, "folderimage"); break;
859  }
860  }
861  else
862  {
863  // Dir with 4 thumbnails
864  button->SetImage(url, QString("thumbimage%1").arg(index));
865  }
866 }
867 
868 
876 void GalleryThumbView::UpdateScanProgress(const QString &scanner,
877  int current, int total)
878 {
879  // Scan update
880  m_scanProgress.insert(scanner, qMakePair(current, total));
881 
882  // Detect end of this scan
883  if (current >= total)
884  {
885  LOG(VB_GUI, LOG_DEBUG, LOC + QString("Scan Finished %1 %2/%3")
886  .arg(scanner).arg(current).arg(total));
887 
888  // Mark inactive scanner
889  m_scanActive.remove(scanner);
890 
891  // Detect end of last scan
892  if (m_scanActive.isEmpty())
893  {
894  if (m_scanProgressText)
895  {
898  }
899  if (m_scanProgressBar)
900  {
903  }
904 
905  m_scanProgress.clear();
906 
907  return;
908  }
909  }
910  else
911  {
912  // Detect first scan update
913  if (m_scanActive.isEmpty())
914  {
915  // Show progressbar when first scan starts
916  if (m_scanProgressBar)
917  {
920  }
921  if (m_scanProgressText)
923  }
924 
925  if (!m_scanActive.contains(scanner))
926  {
927  LOG(VB_GUI, LOG_DEBUG, LOC + QString("Scan Started %1 %2/%3")
928  .arg(scanner).arg(current).arg(total));
929 
930  // Mark active scanner
931  m_scanActive.insert(scanner);
932  }
933  }
934 
935  // Aggregate all running scans
936  int currentAgg = 0;
937  int totalAgg = 0;
938  for (IntPair scan : std::as_const(m_scanProgress))
939  {
940  currentAgg += scan.first;
941  totalAgg += scan.second;
942  }
943 
944  if (m_scanProgressBar)
945  {
946  m_scanProgressBar->SetUsed(currentAgg);
947  m_scanProgressBar->SetTotal(totalAgg);
948  }
949  if (m_scanProgressText)
950  m_scanProgressText->SetText(tr("%L1 of %L3").arg(currentAgg).arg(totalAgg));
951 }
952 
953 
958 {
959  if (m_positionText)
961 
962  if (m_captionText)
963  m_captionText->Reset();
964 
965  if (m_crumbsText)
966  m_crumbsText->Reset();
967 
968  if (m_hideFilterText)
970 
971  if (m_typeFilterText)
973 }
974 
975 
981 {
982  auto im = item->GetData().value<ImagePtrK >();
983  if (im)
984  {
985  // update the position in the node list
986  m_view->Select(im->m_id);
987 
988  // show the name/path of the image
989  if (m_crumbsText)
990  m_crumbsText->SetText(m_mgr.CrumbName(*im, true));
991 
992  if (m_captionText)
993  {
994  // show the date & comment of non-root nodes
995  QStringList text;
996  if (im->m_id != GALLERY_DB_ID)
997  {
998  if (im->IsFile() || im->IsDevice())
999  text << ImageManagerFe::LongDateOf(im);
1000 
1001  QString comment = clean_comment(im->m_comment);
1002  if (!comment.isEmpty())
1003  text << comment;
1004  }
1005  m_captionText->SetText(text.join(" - "));
1006  }
1007 
1008  if (m_hideFilterText)
1009  {
1010  m_hideFilterText->SetText(m_mgr.GetVisibility() ? tr("Hidden") : "");
1011  }
1012 
1013  if (m_typeFilterText)
1014  {
1015  QString text = "";
1016  switch (m_mgr.GetType())
1017  {
1018  case kPicAndVideo : text = ""; break;
1019  case kPicOnly : text = tr("Pictures"); break;
1020  case kVideoOnly : text = tr("Videos"); break;
1021  }
1022  m_typeFilterText->SetText(text);
1023  }
1024 
1025  // show the position of the image
1026  if (m_positionText)
1028 
1029  // Update any file details information
1030  m_infoList.Update(im);
1031  }
1032 }
1033 
1034 
1039 {
1040  // Create the main menu
1041  auto *menu = new MythMenu(tr("Gallery Options"), this, "mainmenu");
1042 
1043  // Menu options depend on the marked files and the current node
1045 
1046  if (m_menuState.m_selected)
1047  {
1048  if (m_editsAllowed)
1049  {
1050  MenuMarked(menu);
1051  MenuPaste(menu);
1053  MenuAction(menu);
1054  }
1056  MenuShow(menu);
1057  if (!m_editsAllowed)
1058  menu->AddItem(tr("Enable Edits"), &GalleryThumbView::ShowPassword);
1059  }
1060 
1061  // Depends on current status of backend scanner - string(number(isBackend()))
1062  if (m_scanActive.contains("1"))
1063  menu->AddItem(tr("Stop Scan"), &GalleryThumbView::StopScan);
1064  else
1065  menu->AddItem(tr("Scan Storage Group"), &GalleryThumbView::StartScan);
1066 
1067  menu->AddItem(tr("Settings"), &GalleryThumbView::ShowSettings);
1068 
1069  auto *popup = new MythDialogBox(menu, &m_popupStack, "menuPopup");
1070  if (popup->Create())
1071  m_popupStack.AddScreen(popup);
1072  else
1073  delete popup;
1074 }
1075 
1076 
1082 {
1083  ImagePtrK parent = m_view->GetParent();
1084 
1085  if (m_menuState.m_childCount == 0 || parent.isNull())
1086  return;
1087 
1088  QString title = tr("%L1 marked").arg(m_menuState.m_markedId.size());
1089  auto *menu = new MythMenu(title, this, "markmenu");
1090 
1091  // Mark/unmark selected
1092  if (m_menuState.m_selected->IsFile())
1093  {
1095  menu->AddItem(tr("Unmark File"), &GalleryThumbView::UnmarkItem);
1096  else
1097  menu->AddItem(tr("Mark File"), &GalleryThumbView::MarkItem);
1098  }
1099  // Cannot mark/unmark parent dir from this level
1100  else if (!m_menuState.m_selected->IsDevice()
1101  && m_menuState.m_selected != parent)
1102  {
1104  menu->AddItem(tr("Unmark Directory"), &GalleryThumbView::UnmarkItem);
1105  else
1106  menu->AddItem(tr("Mark Directory"), &GalleryThumbView::MarkItem);
1107  }
1108 
1109  if (parent->m_id != GALLERY_DB_ID)
1110  {
1111  // Mark All if unmarked files exist
1113  menu->AddItem(tr("Mark All"), &GalleryThumbView::MarkAll);
1114 
1115  // Unmark All if marked files exist
1116  if (!m_menuState.m_markedId.isEmpty())
1117  {
1118  menu->AddItem(tr("Unmark All"), &GalleryThumbView::UnmarkAll);
1119  menu->AddItem(tr("Invert Marked"), &GalleryThumbView::MarkInvertAll);
1120  }
1121  }
1122 
1123  if (menu->IsEmpty())
1124  delete menu;
1125  else
1126  mainMenu->AddItem(tr("Mark"), nullptr, menu);
1127 }
1128 
1129 
1135 {
1136  // Can only copy/move into non-root dirs
1137  if (m_menuState.m_selected->IsDirectory()
1138  && m_menuState.m_selected->m_id != GALLERY_DB_ID)
1139  {
1140  // Operate on current marked files, if any
1142  if (files.isEmpty())
1143  files = m_menuState.m_prevMarkedId;
1144  if (files.isEmpty())
1145  return;
1146 
1147  QString title = tr("%L1 marked").arg(files.size());
1148 
1149  auto *menu = new MythMenu(title, this, "pastemenu");
1150 
1151  menu->AddItem(tr("Move Marked Into"), &GalleryThumbView::Move);
1152  menu->AddItem(tr("Copy Marked Into"), qOverload<>(&GalleryThumbView::Copy));
1153 
1154  mainMenu->AddItem(tr("Paste"), nullptr, menu);
1155  }
1156 }
1157 
1158 
1164 {
1165  // Operate on marked files, if any, otherwise selected node
1166  if (!m_menuState.m_markedId.isEmpty())
1167  {
1168  QString title = tr("%L1 marked").arg(m_menuState.m_markedId.size());
1169 
1170  auto *menu = new MythMenu(title, this, "");
1171 
1172  menu->AddItem(tr("Rotate Marked CW"), &GalleryThumbView::RotateCWMarked);
1173  menu->AddItem(tr("Rotate Marked CCW"), &GalleryThumbView::RotateCCWMarked);
1174  menu->AddItem(tr("Flip Marked Horizontal"), &GalleryThumbView::FlipHorizontalMarked);
1175  menu->AddItem(tr("Flip Marked Vertical"), &GalleryThumbView::FlipVerticalMarked);
1176  menu->AddItem(tr("Reset Marked to Exif"), &GalleryThumbView::ResetExifMarked);
1177 
1178  mainMenu->AddItem(tr("Transforms"), nullptr, menu);
1179  }
1180  else if (m_menuState.m_selected->IsFile())
1181  {
1182  auto *menu = new MythMenu(m_menuState.m_selected->m_baseName, this, "");
1183 
1184  menu->AddItem(tr("Rotate CW"), &GalleryThumbView::RotateCW);
1185  menu->AddItem(tr("Rotate CCW"), &GalleryThumbView::RotateCCW);
1186  menu->AddItem(tr("Flip Horizontal"), &GalleryThumbView::FlipHorizontal);
1187  menu->AddItem(tr("Flip Vertical"), &GalleryThumbView::FlipVertical);
1188  menu->AddItem(tr("Reset to Exif"), &GalleryThumbView::ResetExif);
1189 
1190  mainMenu->AddItem(tr("Transforms"), nullptr, menu);
1191  }
1192 }
1193 
1194 
1200 {
1201  MythMenu *menu = nullptr;
1202  ImagePtrK selected = m_menuState.m_selected;
1203 
1204  // Operate on current marked files, if any
1205  if (!m_menuState.m_markedId.empty())
1206  {
1207  QString title = tr("%L1 marked").arg(m_menuState.m_markedId.size());
1208 
1209  menu = new MythMenu(title, this, "actionmenu");
1210 
1211  // Only offer Hide/Unhide if relevant
1213  menu->AddItem(tr("Hide Marked"), &GalleryThumbView::HideMarked);
1215  menu->AddItem(tr("Unhide Marked"), &GalleryThumbView::UnhideMarked);
1216 
1217  menu->AddItem(tr("Delete Marked"), &GalleryThumbView::DeleteMarked);
1218  }
1219  else
1220  {
1221  // Operate on selected file/dir
1222  menu = new MythMenu(selected->m_baseName, this, "actionmenu");
1223 
1224  // Prohibit actions on devices and parent dirs
1225  if (!selected->IsDevice() && selected != m_view->GetParent())
1226  {
1227  if (selected->m_isHidden)
1228  menu->AddItem(tr("Unhide"), &GalleryThumbView::Unhide);
1229  else
1230  menu->AddItem(tr("Hide"), &GalleryThumbView::HideItem);
1231 
1232  menu->AddItem(tr("Use as Cover"), &GalleryThumbView::SetCover);
1233  menu->AddItem(tr("Delete"), &GalleryThumbView::DeleteItem);
1234  menu->AddItem(tr("Rename"), &GalleryThumbView::ShowRenameInput);
1235  }
1236  else if (selected->m_userThumbnail)
1237  {
1238  menu->AddItem(tr("Reset Cover"), &GalleryThumbView::ResetCover);
1239  }
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  {
1295  menu->AddItem(tr("Current Directory"), &GalleryThumbView::Slideshow);
1296  }
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  {
1332  menu->AddItem(type == kPicOnly ? tr("Show Videos") : tr("Show Pictures"),
1334  }
1335 
1336  int show = gCoreContext->GetNumSetting("GalleryImageCaption");
1337  auto *captionMenu = new MythMenu(tr("Image Captions"), this,
1338  "ImageCaptionMenu");
1339 
1340  captionMenu->AddItem(tr("Name"), nullptr, nullptr, show == kNameCaption);
1341  captionMenu->AddItem(tr("Date"), nullptr, nullptr, show == kDateCaption);
1342  captionMenu->AddItem(tr("Comment"), nullptr, nullptr, show == kUserCaption);
1343  captionMenu->AddItem(tr("None"), nullptr, nullptr, show == kNoCaption);
1344 
1345  menu->AddItem(tr("Image Captions"), nullptr, captionMenu);
1346 
1347  show = gCoreContext->GetNumSetting("GalleryDirCaption");
1348  captionMenu = new MythMenu(tr("Directory Captions"), this, "DirCaptionMenu");
1349 
1350  captionMenu->AddItem(tr("Name"), nullptr, nullptr, show == kNameCaption);
1351  captionMenu->AddItem(tr("Date"), nullptr, nullptr, show == kDateCaption);
1352  captionMenu->AddItem(tr("None"), nullptr, nullptr, show == kNoCaption);
1353 
1354  menu->AddItem(tr("Directory Captions"), nullptr, captionMenu);
1355 
1356  if (m_editsAllowed)
1357  {
1358  if (m_mgr.GetVisibility())
1359  menu->AddItem(tr("Hide Hidden Items"), &GalleryThumbView::HideHidden);
1360  else
1361  menu->AddItem(tr("Show Hidden Items"), &GalleryThumbView::ShowHidden);
1362  }
1363 
1364  if (m_zoomLevel > 0)
1365  menu->AddItem(tr("Zoom Out"), &GalleryThumbView::ZoomOut);
1366  if (m_zoomLevel < m_zoomWidgets.size() - 1)
1367  menu->AddItem(tr("Zoom In"), &GalleryThumbView::ZoomIn);
1368 
1369  QString details = m_infoList.GetState() == kNoInfo
1370  ? tr("Show Details") : tr("Hide Details");
1371 
1372  menu->AddItem(details, &GalleryThumbView::ShowDetails);
1373 
1374  mainMenu->AddItem(tr("Show"), nullptr, menu);
1375 }
1376 
1377 
1383 {
1384  // Only update selection if image is currently displayed
1385  if (m_view->Select(id, -1))
1386  BuildImageList();
1387 }
1388 
1389 
1395 {
1396  if (!item)
1397  return;
1398 
1399  auto im = item->GetData().value<ImagePtrK>();
1400  if (!im)
1401  return;
1402 
1403  switch (im->m_type)
1404  {
1405  case kDevice:
1406  case kCloneDir:
1407  case kDirectory:
1408  if (im == m_view->GetParent())
1409  DirSelectUp();
1410  else
1411  DirSelectDown();
1412  break;
1413 
1414  case kImageFile:
1415  case kVideoFile:
1416  StartSlideshow(kBrowseSlides); break;
1417  };
1418 }
1419 
1420 
1426 {
1427  QString err = m_mgr.ScanImagesAction(start);
1428  if (!err.isEmpty())
1429  ShowOkPopup(err);
1430 }
1431 
1432 
1438 {
1439  ImagePtrK selected = m_view->GetSelected();
1440  if (!selected)
1441  return;
1442 
1444  auto *slide = new GallerySlideView(mainStack, "galleryslideview",
1445  m_editsAllowed);
1446  if (slide->Create())
1447  {
1448  mainStack->AddScreen(slide);
1449 
1450  // Update selected item when slideshow exits
1451  connect(slide, &GallerySlideView::ImageSelected,
1453 
1454  if (selected->IsDirectory())
1455  {
1456  // Show selected dir
1457  slide->Start(mode, selected->m_id);
1458  }
1459  else
1460  {
1461  // Show current dir starting at selection
1462  slide->Start(mode, selected->m_parentId, selected->m_id);
1463  }
1464  }
1465  else
1466  {
1467  delete slide;
1468  }
1469 }
1470 
1471 
1476 {
1477  ImagePtrK im = m_view->GetParent();
1478  if (im)
1479  {
1480  LOG(VB_GUI, LOG_DEBUG, LOC +
1481  QString("Going up from %1").arg(im->m_filePath));
1482 
1483  // Select the upfolder in the higher dir
1484  m_view->Select(im->m_id);
1485 
1486  // Create tree rooted at parent of the kUpFolder directory node
1487  LoadData(im->m_parentId);
1488  }
1489  return true;
1490 }
1491 
1492 
1497 {
1498  ImagePtrK im = m_view->GetSelected();
1499  if (im)
1500  {
1501  LOG(VB_GUI, LOG_DEBUG, LOC +
1502  QString("Going down to %1").arg(im->m_filePath));
1503 
1504  // Create tree rooted at selected item
1505  LoadData(im->m_id);
1506  }
1507 }
1508 
1509 
1515 {
1516  ImagePtrK im = m_view->GetSelected();
1517  if (im)
1518  {
1519  // Mark/unmark selected item
1520  m_view->Mark(im->m_id, mark);
1521 
1522  // Redisplay buttonlist as a parent dir may have been unmarked
1523  BuildImageList();
1524  }
1525 }
1526 
1527 
1533 {
1534  if (mark)
1535  m_view->MarkAll();
1536  else
1537  m_view->ClearMarked();
1538 
1539  // Redisplay buttonlist
1540  BuildImageList();
1541 }
1542 
1543 
1548 {
1549  m_view->InvertMarked();
1550 
1551  // Redisplay buttonlist
1552  BuildImageList();
1553 }
1554 
1555 
1561 {
1562  ImagePtrK im = m_view->GetSelected();
1563  if (im && m_editsAllowed)
1564  {
1565  ImageIdList ids;
1566  ids.append(im->m_id);
1567  QString err = m_mgr.ChangeOrientation(transform, ids);
1568  if (!err.isEmpty())
1569  ShowOkPopup(err);
1570  }
1571 }
1572 
1573 
1579 {
1580  QString err = m_mgr.ChangeOrientation(transform, m_menuState.m_markedId);
1581  if (!err.isEmpty())
1582  ShowOkPopup(err);
1583 }
1584 
1585 
1591 {
1592  if (m_menuState.m_selected)
1593  {
1594  ImageIdList ids;
1595  ids.append(m_menuState.m_selected->m_id);
1596 
1597  QString err = m_mgr.HideFiles(hide, ids);
1598  if (!err.isEmpty())
1599  {
1600  ShowOkPopup(err);
1601  }
1602  else if (hide && !m_mgr.GetVisibility())
1603  {
1604  // Unmark invisible file
1605  m_view->Mark(m_menuState.m_selected->m_id, false);
1606  }
1607  }
1608 }
1609 
1610 
1616 {
1617  QString err = m_mgr.HideFiles(hide, m_menuState.m_markedId);
1618  if (!err.isEmpty())
1619  {
1620  ShowOkPopup(err);
1621  }
1622  else if (hide && !m_mgr.GetVisibility())
1623  {
1624  // Unmark invisible files
1625  for (int id : std::as_const(m_menuState.m_markedId))
1626  m_view->Mark(id, false);
1627  }
1628 }
1629 
1630 
1635 {
1636  if (m_menuState.m_selected)
1637  ShowDialog(tr("Do you want to delete\n%1 ?")
1638  .arg(m_menuState.m_selected->m_baseName), "ConfirmDelete");
1639 }
1640 
1641 
1646 {
1647  ShowDialog(tr("Do you want to delete all marked files ?"),
1648  "ConfirmDeleteMarked");
1649 }
1650 
1651 
1656 {
1657  // Show settings dialog
1658  auto *config = new GallerySettings(m_editsAllowed);
1660  auto *ssd = new StandardSettingDialog(mainStack, "gallerysettings", config);
1661  if (!ssd->Create())
1662  {
1663  delete ssd;
1664  return;
1665  }
1666 
1667  mainStack->AddScreen(ssd);
1668 
1669  // Effect setting changes when dialog saves on exit
1670 
1671  connect(config, &GallerySettings::ClearDbPressed,
1673 
1674  connect(config, &GallerySettings::OrderChanged,
1675  this, [this]()
1676  {
1677  // Update db view, reset cover cache & reload
1678  int sortIm = gCoreContext->GetNumSetting("GalleryImageOrder");
1679  int sortDir = gCoreContext->GetNumSetting("GalleryDirOrder");
1680  m_mgr.SetSortOrder(sortIm, sortDir);
1681  m_view->ClearCache();
1683  });
1684 
1685  connect(config, &GallerySettings::DateChanged,
1686  this, [this]()
1687  {
1688  QString date = gCoreContext->GetSetting("GalleryDateFormat");
1689  m_mgr.SetDateFormat(date);
1690  BuildImageList();
1691  });
1692 
1693  connect(config, &GallerySettings::ExclusionsChanged,
1694  this, [this]()
1695  {
1696  // Request rescan
1697  QString exclusions = gCoreContext->GetSetting("GalleryIgnoreFilter");
1698  m_view->ClearCache();
1699  ImageManagerFe::IgnoreDirs(exclusions);
1700  });
1701 }
1702 
1703 
1709 {
1710  gCoreContext->SaveBoolSetting("GalleryShowHidden", show);
1711 
1712  // Update Db(s)
1714 
1715  // Reset dir thumbnail cache
1716  m_view->ClearCache();;
1717 
1719 }
1720 
1721 
1727 void GalleryThumbView::ShowDialog(const QString& msg, const QString& event)
1728 {
1729  auto *popup = new MythConfirmationDialog(&m_popupStack, msg, true);
1730 
1731  if (popup->Create())
1732  {
1733  popup->SetReturnEvent(this, event);
1734  m_popupStack.AddScreen(popup);
1735  }
1736  else
1737  {
1738  delete popup;
1739  }
1740 }
1741 
1742 
1747 {
1748  if (m_menuState.m_selected)
1749  {
1750  QString base = QFileInfo(m_menuState.m_selected->m_baseName).completeBaseName();
1751  QString msg = tr("Enter a new name:");
1752  auto *popup = new MythTextInputDialog(&m_popupStack, msg, FilterNone,
1753  false, base);
1754  if (popup->Create())
1755  {
1756  popup->SetReturnEvent(this, "FileRename");
1757  m_popupStack.AddScreen(popup);
1758  }
1759  else
1760  {
1761  delete popup;
1762  }
1763  }
1764 }
1765 
1766 
1771 {
1773 }
1774 
1775 
1780 {
1781  QString msg = tr("Enter password:");
1782  auto *popup = new MythTextInputDialog(&m_popupStack, msg, FilterNone, true);
1783  if (popup->Create())
1784  {
1785  popup->SetReturnEvent(this, "Password");
1786  m_popupStack.AddScreen(popup);
1787  }
1788  else
1789  {
1790  delete popup;
1791  }
1792 }
1793 
1794 
1799 {
1800  gCoreContext->SaveSetting("GalleryShowType", type);
1801 
1802  // Update Db(s)
1803  m_mgr.SetType(type);
1804 
1805  // Reset dir thumbnail cache
1806  m_view->ClearCache();
1807 
1809 }
1810 
1811 
1817 {
1818  if (m_menuState.m_selected)
1819  {
1820  QString err = reset ? m_mgr.SetCover(m_menuState.m_selected->m_id, 0)
1821  : m_mgr.SetCover(m_menuState.m_selected->m_parentId,
1822  m_menuState.m_selected->m_id);
1823  if (!err.isEmpty())
1824  ShowOkPopup(err);
1825  }
1826 }
1827 
1828 
1833 {
1834  SelectZoomWidget(-1);
1835  BuildImageList();
1836 }
1837 
1838 
1843 {
1844  SelectZoomWidget(1);
1845  BuildImageList();
1846 }
1847 
1848 
1854 {
1855  m_zoomLevel += change;
1856 
1857  // constrain to zoom levels supported by theme
1858  m_zoomLevel = std::max(m_zoomLevel, 0);
1859  if (m_zoomLevel >= m_zoomWidgets.size())
1860  m_zoomLevel = m_zoomWidgets.size() - 1;
1861 
1862  // Store any requested change, but not constraining adjustments
1863  // Thus, changing to a theme with fewer zoom levels will not overwrite the
1864  // setting
1865  if (change != 0)
1866  gCoreContext->SaveSetting("GalleryZoomLevel", m_zoomLevel);
1867 
1868  // dump the current list widget
1869  if (m_imageList)
1870  {
1871  m_imageList->SetVisible(false);
1872  disconnect(m_imageList, nullptr, this, nullptr);
1873  }
1874 
1875  // initialise new list widget
1877 
1878  m_imageList->SetVisible(true);
1880 
1881  // Monitor list actions (after focus events have been ignored)
1886 }
1887 
1888 
1893 {
1894  auto *popup = new MythTextInputDialog(&m_popupStack,
1895  tr("Enter name of new directory"),
1896  FilterNone, false);
1897  if (popup->Create())
1898  {
1899  popup->SetReturnEvent(this, "MakeDir");
1900  m_popupStack.AddScreen(popup);
1901  }
1902  else
1903  {
1904  delete popup;
1905  }
1906 }
1907 
1908 
1913 {
1915  if (dir)
1916  m_mgr.CloseDevices(dir->m_device, true);
1917 }
1918 
1919 
1929 void GalleryThumbView::Copy(bool deleteAfter)
1930 {
1931  // Destination must be a dir
1932  ImagePtrK destDir = m_menuState.m_selected;
1933  if (!destDir || destDir->IsFile())
1934  return;
1935 
1936  // Use current markings, if any. Otherwise use previous markings
1937  ImageIdList markedIds = m_menuState.m_markedId;
1938  if (markedIds.isEmpty())
1939  {
1940  markedIds = m_menuState.m_prevMarkedId;
1941  if (markedIds.isEmpty())
1942  {
1943  ShowOkPopup(tr("No files specified"));
1944  return;
1945  }
1946  }
1947 
1948  // Get all files/dirs in subtree(s). Only files are copied
1949  ImageList files;
1950  ImageList dirs;
1951  m_mgr.GetDescendants(markedIds, files, dirs);
1952 
1953  if (dirs.isEmpty() && files.isEmpty())
1954  {
1955  ShowOkPopup(tr("No images"));
1956  // Nothing to clean up
1957  return;
1958  }
1959 
1960  // Child dirs appear before their subdirs. If no dirs, images are all direct children
1961  ImagePtrK aChild = dirs.isEmpty() ? files[0] : dirs[0];
1962 
1963  // Determine parent path including trailing /
1964  int basePathSize = aChild->m_filePath.size() - aChild->m_baseName.size();
1965 
1966  // Update filepaths for Db & generate URLs for filesystem copy
1967  // Only copy files, destination dirs will be created automatically
1968  TransferThread::TransferMap transfers;
1969  for (const ImagePtr & im : std::as_const(files))
1970  {
1971  // Replace base path with destination path
1972  im->m_filePath = ImageManagerFe::ConstructPath(destDir->m_filePath,
1973  im->m_filePath.mid(basePathSize));
1974 
1975  transfers.insert(im, m_mgr.BuildTransferUrl(im->m_filePath,
1976  destDir->IsLocal()));
1977  }
1978 
1979  // Create progress dialog
1980  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
1981  auto *progress = new MythUIProgressDialog(tr("Copying files"), popupStack,
1982  "copydialog");
1983  if (progress->Create())
1984  popupStack->AddScreen(progress, false);
1985  else
1986  {
1987  delete progress;
1988  progress = nullptr;
1989  }
1990 
1991  // Copy files in a servant thread
1992  TransferThread copy(transfers, false, progress);
1994  TransferThread::ImageSet failed = copy.GetResult();
1995 
1996  if (progress)
1997  progress->Close();
1998 
1999  if (!failed.isEmpty())
2000  ShowOkPopup(tr("Failed to copy %L1/%Ln file(s)", nullptr, transfers.size())
2001  .arg(failed.size()));
2002 
2003  // Don't update Db for files that failed
2004  for (const ImagePtrK & im : std::as_const(failed))
2005  transfers.remove(im);
2006 
2007  ImageListK newImages = transfers.keys();
2008 
2009  // Include dirs
2010  QStringList dirPaths;
2011  for (const ImagePtr & im : std::as_const(dirs))
2012  {
2013  QString relPath = im->m_filePath.mid(basePathSize);
2014 
2015  dirPaths << relPath;
2016 
2017  // Replace base path with destination path
2018  im->m_filePath = ImageManagerFe::ConstructPath(destDir->m_filePath, relPath);
2019 
2020  // Append dirs so that hidden state & cover is preserved for new dirs
2021  // Pre-existing dirs will take precedance over these.
2022  newImages.append(im);
2023  }
2024 
2025  // Copy empty dirs as well (will fail for non-empty dirs)
2026  if (!dirPaths.isEmpty())
2027  m_mgr.MakeDir(destDir->m_id, dirPaths, false);
2028 
2029  if (!newImages.isEmpty())
2030  {
2031  // Update Db
2032  m_mgr.CreateImages(destDir->m_id, newImages);
2033 
2034  if (deleteAfter)
2035  {
2036  // Delete files/dirs that have been successfully copied
2037  // Will fail for dirs containing images that failed to copy
2038  ImageIdList ids;
2039  for (const ImagePtrK & im : std::as_const(newImages))
2040  ids << im->m_id;
2041 
2042  m_mgr.DeleteFiles(ids);
2043  }
2044  }
2045 }
2046 
2047 
2058 {
2059  // Destination must be a dir
2060  ImagePtrK destDir = m_menuState.m_selected;
2061  if (!destDir || destDir->IsFile())
2062  return;
2063 
2064  // Use current markings, if any. Otherwise use previous markings
2065  ImageIdList markedIds = m_menuState.m_markedId;
2066  if (markedIds.isEmpty())
2067  {
2068  markedIds = m_menuState.m_prevMarkedId;
2069  if (markedIds.isEmpty())
2070  {
2071  ShowOkPopup(tr("No files specified"));
2072  return;
2073  }
2074  }
2075 
2076  // Note UI mandates that transferees are either all local or all remote
2077  if (destDir->IsLocal() != ImageItem::IsLocalId(markedIds[0]))
2078  {
2079  // Moves between hosts require copy/delete
2080  Copy(true);
2081  return;
2082  }
2083 
2084  // Get marked images. Each file and dir will be renamed
2085  ImageList files;
2086  ImageList dirs;
2087  if (m_mgr.GetImages(markedIds, files, dirs) <= 0)
2088  {
2089  ShowOkPopup(tr("No images specified"));
2090  // Nothing to clean up
2091  return;
2092  }
2093  ImageList images;
2094  if (!dirs.isEmpty())
2095  images += dirs;
2096  if (!files.isEmpty())
2097  images += files;
2098 
2099  // Determine parent from first dir or pic
2100  ImagePtr aChild = images[0];
2101 
2102  // Determine parent path including trailing /
2103  // Note UI mandates that transferees all have same parent.
2104  int basePathSize = aChild->m_filePath.size() - aChild->m_baseName.size();
2105  QString parentPath = aChild->m_filePath.left(basePathSize);
2106 
2107  // Determine destination URLs
2108  TransferThread::TransferMap transfers;
2109  for (const QSharedPointer<ImageItem> & im : std::as_const(images))
2110  {
2111  // Replace base path with destination path
2112  QString newPath = ImageManagerFe::ConstructPath(destDir->m_filePath,
2113  im->m_filePath.mid(basePathSize));
2114 
2115  transfers.insert(im, m_mgr.BuildTransferUrl(newPath, aChild->IsLocal()));
2116  }
2117 
2118  // Create progress dialog
2119  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
2120  auto *progress = new MythUIProgressDialog(tr("Moving files"), popupStack,
2121  "movedialog");
2122 
2123  if (progress->Create())
2124  popupStack->AddScreen(progress, false);
2125  else
2126  {
2127  delete progress;
2128  progress = nullptr;
2129  }
2130 
2131  // Move files in a servant thread
2132  TransferThread move(transfers, true, progress);
2133  WaitUntilDone(move);
2134  TransferThread::ImageSet failed = move.GetResult();
2135 
2136  if (progress)
2137  progress->Close();
2138 
2139  if (!failed.isEmpty())
2140  ShowOkPopup(tr("Failed to move %L1/%Ln file(s)", nullptr, transfers.size())
2141  .arg(failed.size()));
2142 
2143  // Don't update Db for files that failed
2144  for (const ImagePtrK & im : std::as_const(failed))
2145  transfers.remove(im);
2146 
2147  if (!transfers.isEmpty())
2148  {
2149  ImageListK moved = transfers.keys();
2150 
2151  // Unmark moved files
2152  for (const ImagePtrK & im : std::as_const(moved))
2153  m_view->Mark(im->m_id, false);
2154 
2155  // Update Db
2156  m_mgr.MoveDbImages(destDir, moved, parentPath);
2157  }
2158 }
2159 
2160 
2165 {
2166  QString path = m_mgr.CreateImport();
2167  if (path.isEmpty())
2168  {
2169  ShowOkPopup(tr("Failed to create temporary directory."));
2170  return;
2171  }
2172 
2173  // Replace placeholder in command
2174  QString cmd = gCoreContext->GetSetting("GalleryImportCmd");
2175  cmd.replace("%TMPDIR%", path);
2176 
2177  // Run command in a separate thread
2178  MythUIBusyDialog *busy =
2179  ShowBusyPopup(tr("Running Import command.\nPlease wait..."));
2180 
2181  ShellThread thread(cmd, path);
2182  WaitUntilDone(thread);
2183 
2184  if (busy)
2185  busy->Close();
2186 
2187  int error = thread.GetResult();
2188  if (error != 0)
2189  ShowOkPopup(tr("Import command failed.\nError: %1").arg(error));
2190 
2191  // Rescan local devices
2192  QString err = m_mgr.ScanImagesAction(true, true);
2193  if (!err.isEmpty())
2194  LOG(VB_GENERAL, LOG_ERR, LOC + err);
2195 }
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:847
ImagePtrK
QSharedPointer< ImageItemK > ImagePtrK
Definition: imagetypes.h:165
MythMainWindow::GetMainStack
MythScreenStack * GetMainStack()
Definition: mythmainwindow.cpp:317
MenuSubjects::m_prevMarkedId
ImageIdList m_prevMarkedId
Ids of marked items in previous dir.
Definition: galleryviews.h:69
SlideOrderType
SlideOrderType
Order of images in slideshow.
Definition: galleryviews.h:21
InfoList::Display
void Display(ImageItemK &im, const QStringList &tagStrings)
Build list of metadata tags.
Definition: galleryinfo.cpp:224
ImageDbReader::GetImages
int GetImages(const ImageIdList &ids, ImageList &files, ImageList &dirs) const
Returns images (local or remote but not a combination)
Definition: imagemanager.cpp:1834
MThread::start
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:283
ShowBusyPopup
MythUIBusyDialog * ShowBusyPopup(const QString &message)
Definition: mythprogressdialog.cpp:97
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
ImageCaptionType
ImageCaptionType
Type of captions to display.
Definition: gallerythumbview.h:14
GalleryThumbView::IntPair
QPair< int, int > IntPair
Definition: gallerythumbview.h:127
mythuitext.h
mythuiprogressbar.h
ImageFileTransform
ImageFileTransform
Image transformations.
Definition: imagemetadata.h:46
ImageAdapterBase::ConstructPath
static QString ConstructPath(const QString &path, const QString &name)
Assembles a canonical file path without corrupting its absolute/relative nature.
Definition: imagemanager.h:132
MythEvent::kMythEventMessage
static const Type kMythEventMessage
Definition: mythevent.h:79
ImageManagerFe::CreateThumbnails
void CreateThumbnails(const ImageIdList &ids, bool forFolder)
Create thumbnails or verify that they already exist.
Definition: imagemanager.cpp:1980
TransferThread::m_failed
ImageSet m_failed
Definition: gallerythumbview.cpp:138
GalleryThumbView::m_positionText
MythUIText * m_positionText
Definition: gallerythumbview.h:136
DirectoryView::GetPosition
QString GetPosition() const
Get positional status.
Definition: galleryviews.cpp:487
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:65
error
static void error(const char *str,...)
Definition: vbi.cpp:37
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
GalleryThumbView::MenuPaste
void MenuPaste(MythMenu *mainMenu)
Add a Paste submenu.
Definition: gallerythumbview.cpp:1134
GalleryThumbView::m_imageList
MythUIButtonList * m_imageList
Definition: gallerythumbview.h:130
MythUIButtonListItem::DisplayState
void DisplayState(const QString &state, const QString &name)
Definition: mythuibuttonlist.cpp:3613
MythUIButtonListItem::FullChecked
@ FullChecked
Definition: mythuibuttonlist.h:48
ImageManagerFe::CreateImages
QString CreateImages(int destId, const ImageListK &images)
Copies database images (but not the files themselves).
Definition: imagemanager.cpp:2226
GalleryThumbView::MakeDir
void MakeDir()
Show dialog to input new directory name.
Definition: gallerythumbview.cpp:1892
GalleryThumbView::SelectZoomWidget
void SelectZoomWidget(int change)
Change buttonlist to use a different size.
Definition: gallerythumbview.cpp:1853
ImageManagerFe::ScanImagesAction
QString ScanImagesAction(bool start, bool local=false)
Handle scanner start/stop commands.
Definition: imagemanager.cpp:2015
MythScreenType::Close
virtual void Close()
Definition: mythscreentype.cpp:383
MythUIButtonListItem::SetImageFromMap
void SetImageFromMap(const InfoMap &imageMap)
Definition: mythuibuttonlist.cpp:3511
ImageManagerFe::BuildTransferUrl
QString BuildTransferUrl(const QString &path, bool local) const
Generate Myth URL for a local or remote path.
Definition: imagemanager.h:503
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:66
GalleryThumbView::DirSelectDown
void DirSelectDown()
Goes one directory level down.
Definition: gallerythumbview.cpp:1496
GallerySettings
Definition: galleryconfig.h:9
MenuSubjects::m_unhiddenMarked
bool m_unhiddenMarked
Is any marked item unhidden ?
Definition: galleryviews.h:72
GalleryThumbView::UnmarkAll
void UnmarkAll()
Definition: gallerythumbview.h:88
DirectoryView::Mark
void Mark(int id, bool mark)
Mark/unmark an image/dir.
Definition: galleryviews.cpp:745
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:2184
MythUIType::GetChild
MythUIType * GetChild(const QString &name) const
Get a named child of this UIType.
Definition: mythuitype.cpp:138
MenuSubjects::m_markedId
ImageIdList m_markedId
Ids of all marked items.
Definition: galleryviews.h:68
GalleryThumbView::ShowPassword
void ShowPassword()
Displays dialog to accept password.
Definition: gallerythumbview.cpp:1779
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:2168
MythUIProgressBar::SetUsed
void SetUsed(int value)
Definition: mythuiprogressbar.cpp:72
GalleryThumbView::GalleryThumbView
GalleryThumbView(MythScreenStack *parent, const char *name)
Constructor.
Definition: gallerythumbview.cpp:163
mythdialogbox.h
MythScreenStack
Definition: mythscreenstack.h:16
GalleryThumbView::FlipVertical
void FlipVertical()
Definition: gallerythumbview.h:76
GalleryThumbView::LoadData
void LoadData(int parent)
Loads & displays images from database.
Definition: gallerythumbview.cpp:630
TransferThread::m_files
TransferMap m_files
Maps source filepath to destination filepath.
Definition: gallerythumbview.cpp:137
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:77
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:198
MythUIButtonListItem::CheckState
CheckState
Definition: mythuibuttonlist.h:44
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:2061
GalleryThumbView::MenuAction
void MenuAction(MythMenu *mainMenu)
Add a Action submenu.
Definition: gallerythumbview.cpp:1199
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MThread::RunProlog
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
Definition: mthread.cpp:196
MenuSubjects::m_childCount
ssize_t m_childCount
Number of images & dirs excl parent.
Definition: galleryviews.h:70
ImageManagerFe::SetDateFormat
void SetDateFormat(const QString &format)
Definition: imagemanager.h:496
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:341
GalleryThumbView::m_hideFilterText
MythUIText * m_hideFilterText
Definition: gallerythumbview.h:134
GalleryThumbView::Import
void Import()
Executes user 'Import command'.
Definition: gallerythumbview.cpp:2164
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:421
GalleryThumbView::ZoomIn
void ZoomIn()
Use smaller buttonlist widgets.
Definition: gallerythumbview.cpp:1842
GalleryThumbView::HideHidden
void HideHidden()
Definition: gallerythumbview.h:99
GalleryThumbView::DoHideItem
void DoHideItem(bool hide=true)
Hide or unhide item.
Definition: gallerythumbview.cpp:1590
TransferThread::TransferThread
TransferThread(TransferMap files, bool move, MythUIProgressDialog *dialog)
Definition: gallerythumbview.cpp:71
GalleryThumbView::m_menuState
MenuSubjects m_menuState
Current selection/marked files when menu is invoked.
Definition: gallerythumbview.h:155
kDirectory
@ kDirectory
A device sub directory.
Definition: imagetypes.h:38
TransferThread::TransferMap
QMap< ImagePtrK, QString > TransferMap
Definition: gallerythumbview.cpp:68
ImageManagerFe::CloseDevices
void CloseDevices(int devId=DEVICE_INVALID, bool eject=false)
Definition: imagemanager.cpp:2409
FlatView::Select
bool Select(int id, int fallback=0)
Selects first occurrence of an image.
Definition: galleryviews.cpp:119
kVideoFile
@ kVideoFile
A video.
Definition: imagetypes.h:40
hardwareprofile.scan.scan
def scan(profile, smoonURL, gate)
Definition: scan.py:55
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:15
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
kRandom
@ kRandom
Random selection from view. An image may be absent or appear multiple times.
Definition: galleryviews.h:24
GalleryThumbView::Create
bool Create() override
Initialises and shows the graphical elements.
Definition: gallerythumbview.cpp:211
ImageManagerFe::ChangeOrientation
QString ChangeOrientation(ImageFileTransform transform, const ImageIdList &ids)
Apply an orientation transform to images.
Definition: imagemanager.cpp:2092
kDevice
@ kDevice
Storage Group and local mounted media.
Definition: imagetypes.h:36
MythScreenType::GetFocusWidget
MythUIType * GetFocusWidget(void) const
Definition: mythscreentype.cpp:110
GalleryThumbView::MenuMain
void MenuMain()
Shows the main menu when the MENU button was pressed.
Definition: gallerythumbview.cpp:1038
mythsystemlegacy.h
kPicAndVideo
@ kPicAndVideo
Show Pictures & Videos.
Definition: imagemanager.h:78
DirectoryView::MarkAll
void MarkAll()
Mark all images/dirs.
Definition: galleryviews.cpp:732
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:3319
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:980
GalleryThumbView::keyPressEvent
bool keyPressEvent(QKeyEvent *event) override
Handle keypresses.
Definition: gallerythumbview.cpp:275
GalleryThumbView::DoSetCover
void DoSetCover(bool reset=false)
Set or reset thumbnails to use for a directory cover.
Definition: gallerythumbview.cpp:1816
MythUIButtonListItem
Definition: mythuibuttonlist.h:41
TransferThread
Worker thread for copying/moving files.
Definition: gallerythumbview.cpp:64
TransferThread::m_move
bool m_move
Copy if false, Move if true.
Definition: gallerythumbview.cpp:136
ProgressUpdateEvent
Definition: mythprogressdialog.h:16
StandardSettingDialog
Definition: standardsettings.h:468
kUserCaption
@ kUserCaption
Exif comments.
Definition: gallerythumbview.h:18
MythUIProgressBar::SetTotal
void SetTotal(int value)
Definition: mythuiprogressbar.cpp:78
ShellThread
Worker thread for running import.
Definition: gallerythumbview.cpp:34
GalleryThumbView::ResetUiSelection
void ResetUiSelection()
Clears all text widgets for selected item.
Definition: gallerythumbview.cpp:957
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
kImageFile
@ kImageFile
A picture.
Definition: imagetypes.h:39
GalleryThumbView::MenuShow
void MenuShow(MythMenu *mainMenu)
Add a Show submenu.
Definition: gallerythumbview.cpp:1320
GalleryThumbView::ShowSettings
void ShowSettings()
Show configuration screen.
Definition: gallerythumbview.cpp:1655
MythUIButtonList::itemClicked
void itemClicked(MythUIButtonListItem *item)
ImageDbReader::SetSortOrder
void SetSortOrder(int order, int dirOrder)
Definition: imagemanager.h:418
GalleryThumbView::UpdateScanProgress
void UpdateScanProgress(const QString &scanner, int current, int total)
Update progressbar with scan status.
Definition: gallerythumbview.cpp:876
MythMainWindow::TranslateKeyPress
bool TranslateKeyPress(const QString &Context, QKeyEvent *Event, QStringList &Actions, bool AllowJumps=true)
Get a list of actions for a keypress in the given context.
Definition: mythmainwindow.cpp:1111
remotefile.h
MythFile::copy
MBASE_PUBLIC long long copy(QFile &dst, QFile &src, uint block_size=0)
Copies src file to dst file.
Definition: mythmiscutil.cpp:263
MythUIProgressBar::Reset
void Reset(void) override
Reset the widget to it's original state, should not reset changes made by the theme.
Definition: mythuiprogressbar.cpp:19
MythUIProgressDialog
Definition: mythprogressdialog.h:59
MythScreenType::SetFocusWidget
bool SetFocusWidget(MythUIType *widget=nullptr)
Definition: mythscreentype.cpp:115
hardwareprofile.i18n.t
t
Definition: i18n.py:36
GalleryThumbView::TransformMarked
void TransformMarked(ImageFileTransform tran=kRotateCW)
Apply transform to marked images.
Definition: gallerythumbview.cpp:1578
MythDialogBox
Basic menu dialog, message and a list of options.
Definition: mythdialogbox.h:166
menu
static MythThemedMenu * menu
Definition: mythtv-setup.cpp:58
GalleryThumbView::SelectImage
void SelectImage(int id)
Select item if it is displayed.
Definition: gallerythumbview.cpp:1382
compat.h
GalleryThumbView::ResetCover
void ResetCover()
Definition: gallerythumbview.h:102
GalleryThumbView::DoShowHidden
void DoShowHidden(bool show=true)
Show or hide hidden files.
Definition: gallerythumbview.cpp:1708
mark
Definition: lang.cpp:22
ImageDbReader::GetType
int GetType() const
Definition: imagemanager.h:412
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:203
gallerythumbview.h
Implements Gallery Thumbnail screen.
kDateCaption
@ kDateCaption
Dates.
Definition: gallerythumbview.h:17
GalleryThumbView::MenuSlideshow
void MenuSlideshow(MythMenu *mainMenu)
Add a Slideshow submenu.
Definition: gallerythumbview.cpp:1267
GalleryThumbView::ClearSgDb
static void ClearSgDb()
Definition: gallerythumbview.h:34
GalleryThumbView::BuildImageList
void BuildImageList()
Displays all images in current view.
Definition: gallerythumbview.cpp:665
ImageDbReader::GetDescendants
void GetDescendants(const ImageIdList &ids, ImageList &files, ImageList &dirs) const
Return all (local or remote) images that are direct children of a dir.
Definition: imagemanager.cpp:1874
GalleryThumbView::StartSlideshow
void StartSlideshow(ImageSlideShowType mode)
Start slideshow screen.
Definition: gallerythumbview.cpp:1437
GalleryThumbView::ShowRenameInput
void ShowRenameInput()
Show dialog to allow input.
Definition: gallerythumbview.cpp:1746
kNameCaption
@ kNameCaption
Filenames.
Definition: gallerythumbview.h:16
GalleryThumbView::ShowDialog
void ShowDialog(const QString &msg, const QString &event="")
Show a confirmation dialog.
Definition: gallerythumbview.cpp:1727
FlatView::GetAllNodes
ImageListK GetAllNodes() const
Get all images/dirs in view.
Definition: galleryviews.cpp:53
DirectoryView::InvertMarked
void InvertMarked()
Mark all unmarked items, unmark all marked items.
Definition: galleryviews.cpp:764
MythUIThemeCache::RemoveFromCacheByFile
void RemoveFromCacheByFile(const QString &File)
Definition: mythuithemecache.cpp:508
GalleryThumbView::DeleteMarked
void DeleteMarked()
Confirm user deletion of marked files.
Definition: gallerythumbview.cpp:1645
GalleryThumbView::Unhide
void Unhide()
Definition: gallerythumbview.h:92
ImageListK
QList< ImagePtrK > ImageListK
Definition: imagetypes.h:166
MThread::RunEpilog
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:209
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:2327
kNoCaption
@ kNoCaption
None.
Definition: gallerythumbview.h:15
ShellThread::m_command
QString m_command
Definition: gallerythumbview.cpp:58
MythUIBusyDialog
Definition: mythprogressdialog.h:36
ImageDbReader::GetVisibility
bool GetVisibility() const
Definition: imagemanager.h:413
GalleryThumbView::ZoomOut
void ZoomOut()
Use larger buttonlist widgets.
Definition: gallerythumbview.cpp:1832
MThread::isFinished
bool isFinished(void) const
Definition: mthread.cpp:258
GalleryThumbView::ResetExif
void ResetExif()
Definition: gallerythumbview.h:77
FlatView::GetSelected
ImagePtrK GetSelected() const
Get current selection.
Definition: galleryviews.cpp:66
kBrowseSlides
@ kBrowseSlides
Definition: galleryslideview.h:16
MythUIButtonListItem::GetData
QVariant GetData()
Definition: mythuibuttonlist.cpp:3715
ImageManagerFe::SetCover
QString SetCover(int parent, int cover)
Set image to use as a cover thumbnail(s)
Definition: imagemanager.cpp:2124
GallerySettings::ClearDbPressed
void ClearDbPressed()
GalleryThumbView::ItemClicked
void ItemClicked(MythUIButtonListItem *item)
Action item click.
Definition: gallerythumbview.cpp:1394
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
InfoList::GetState
InfoVisibleState GetState() const
Definition: galleryinfo.h:34
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:23
GallerySettings::OrderChanged
void OrderChanged()
GalleryThumbView::DoHideMarked
void DoHideMarked(bool hide=true)
Hide or unhide marked items.
Definition: gallerythumbview.cpp:1615
GalleryThumbView::DirSelectUp
bool DirSelectUp()
Goes up one directory level.
Definition: gallerythumbview.cpp:1475
GalleryThumbView::UpdateImageItem
void UpdateImageItem(MythUIButtonListItem *item)
Initialises a single buttonlist item.
Definition: gallerythumbview.cpp:713
TransferThread::GetResult
ImageSet GetResult(void)
Definition: gallerythumbview.cpp:75
GalleryThumbView::ShowDetails
void ShowDetails()
Shows exif info/details about an item.
Definition: gallerythumbview.cpp:1770
GalleryThumbView::CheckThumbnail
QString CheckThumbnail(MythUIButtonListItem *item, const ImagePtrK &im, ImageIdList &request, int index)
Verify thumbnail is known to exist.
Definition: gallerythumbview.cpp:820
RemoteFile::CopyFile
static bool CopyFile(const QString &src, const QString &dst, bool overwrite=false, bool verify=false)
Definition: remotefile.cpp:586
GalleryThumbView::FlipHorizontal
void FlipHorizontal()
Definition: gallerythumbview.h:75
FilterNone
@ FilterNone
Definition: mythuitextedit.h:21
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:1560
ImageManagerFe::CreateImport
QString CreateImport()
Definition: imagemanager.cpp:2510
GalleryThumbView::RotateCW
void RotateCW()
Definition: gallerythumbview.h:73
GalleryThumbView::RepeatOn
static void RepeatOn()
Definition: gallerythumbview.h:123
UIUtilDisp::Assign
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
Definition: mythuiutils.h:27
GalleryThumbView::m_scanProgressText
MythUIText * m_scanProgressText
Definition: gallerythumbview.h:137
GalleryThumbView::MarkInvertAll
void MarkInvertAll()
Invert all marked items.
Definition: gallerythumbview.cpp:1547
DirectoryView::LoadFromDb
bool LoadFromDb(int parentId) override
Populate view from database as images/subdirs of a directory. View is ordered: Parent dir,...
Definition: galleryviews.cpp:501
MythUIButtonListItem::NotChecked
@ NotChecked
Definition: mythuibuttonlist.h:46
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:121
TransferThread::ImageSet
QSet< ImagePtrK > ImageSet
Definition: gallerythumbview.cpp:69
ImageSlideShowType
ImageSlideShowType
Type of slide show.
Definition: galleryslideview.h:15
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:2057
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:2270
GalleryThumbView::m_mgr
ImageManagerFe & m_mgr
Manages the images.
Definition: gallerythumbview.h:145
GalleryThumbView::SetCover
void SetCover()
Definition: gallerythumbview.h:101
MythScreenType::keyPressEvent
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
Definition: mythscreentype.cpp:401
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:415
GalleryThumbView::HidePictures
void HidePictures()
Definition: gallerythumbview.h:105
ImageManagerFe
The image manager for use by Frontends.
Definition: imagemanager.h:463
kCloneDir
@ kCloneDir
A device sub dir comprised from multiple SG dirs.
Definition: imagetypes.h:37
XMLParseBase::LoadWindowFromXML
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
Definition: xmlparsebase.cpp:701
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:3479
FlatView::GetParentId
int GetParentId() const
Definition: galleryviews.h:105
GalleryThumbView::Copy
void Copy()
Definition: gallerythumbview.h:119
WaitUntilDone
static void WaitUntilDone(MThread &worker)
Runs a worker thread and waits for it to finish.
Definition: gallerythumbview.cpp:147
DialogCompletionEvent
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
Definition: mythdialogbox.h:41
GalleryThumbView::DoMarkAll
void DoMarkAll(bool mark=true)
Mark or unmark all items.
Definition: gallerythumbview.cpp:1532
ImageIdList
QList< int > ImageIdList
Definition: imagetypes.h:60
ShellThread::GetResult
int GetResult(void) const
Definition: gallerythumbview.cpp:40
ImageManagerFe::CrumbName
QString CrumbName(ImageItemK &im, bool getPath=false) const
Return a displayable name (with optional path) for an image.
Definition: imagemanager.cpp:2388
MythUIText::SetText
virtual void SetText(const QString &text)
Definition: mythuitext.cpp:115
MythUIType::SetVisible
virtual void SetVisible(bool visible)
Definition: mythuitype.cpp:1105
RemoteFile::MoveFile
static bool MoveFile(const QString &src, const QString &dst, bool overwrite=false)
Definition: remotefile.cpp:676
MThread
This is a wrapper around QThread that does several additional things.
Definition: mthread.h:48
GalleryThumbView::DeleteItem
void DeleteItem()
Confirm user deletion of an item.
Definition: gallerythumbview.cpp:1634
DirectoryView::GetMenuSubjects
MenuSubjects GetMenuSubjects()
Determine current selection, markings & various info to support menu display.
Definition: galleryviews.cpp:816
GalleryThumbView::ShowHidden
void ShowHidden()
Definition: gallerythumbview.h:98
PHOTO_DB_ID
static constexpr int PHOTO_DB_ID
Definition: imagetypes.h:29
DialogCompletionEvent::kEventType
static const Type kEventType
Definition: mythdialogbox.h:57
GalleryThumbView::m_zoomWidgets
QList< MythUIButtonList * > m_zoomWidgets
Theme buttonlist widgets implementing zoom levels.
Definition: gallerythumbview.h:141
MythUIButtonList::Reset
void Reset() override
Reset the widget to it's original state, should not reset changes made by the theme.
Definition: mythuibuttonlist.cpp:116
GetMythMainWindow
MythMainWindow * GetMythMainWindow(void)
Definition: mythmainwindow.cpp:104
MythUIButtonList::SetItemCurrent
void SetItemCurrent(MythUIButtonListItem *item)
Definition: mythuibuttonlist.cpp:1581
GalleryThumbView::UnhideMarked
void UnhideMarked()
Definition: gallerythumbview.h:95
GalleryThumbView::~GalleryThumbView
~GalleryThumbView() override
Destructor.
Definition: gallerythumbview.cpp:182
build_compdb.action
action
Definition: build_compdb.py:9
DirectoryView::ClearCache
void ClearCache()
Clears UI cache.
Definition: galleryviews.cpp:896
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:582
GalleryThumbView::MarkAll
void MarkAll()
Definition: gallerythumbview.h:87
DirectoryView::Clear
void Clear(bool resetParent=true)
Resets view.
Definition: galleryviews.cpp:721
kSeasonal
@ kSeasonal
Biased random selection so that images are more likely to appear on anniversaries.
Definition: galleryviews.h:25
ShellThread::ShellThread
ShellThread(QString cmd, QString path)
Definition: gallerythumbview.cpp:37
GalleryThumbView::UnmarkItem
void UnmarkItem()
Definition: gallerythumbview.h:85
MThread::objectName
QString objectName(void) const
Definition: mthread.cpp:243
MythMainWindow::GetStack
MythScreenStack * GetStack(const QString &Stackname)
Definition: mythmainwindow.cpp:322
GalleryThumbView::DoShowType
void DoShowType(int type)
Show/hide pictures or videos.
Definition: gallerythumbview.cpp:1798
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:911
GalleryThumbView::DoMarkItem
void DoMarkItem(bool mark)
Mark or unmark a single item.
Definition: gallerythumbview.cpp:1514
GalleryThumbView::MenuTransform
void MenuTransform(MythMenu *mainMenu)
Add a Transform submenu.
Definition: gallerythumbview.cpp:1163
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
GalleryThumbView::ThumbLocation
QPair< MythUIButtonListItem *, int > ThumbLocation
Definition: gallerythumbview.h:157
ImageManagerFe::DeleteFiles
QString DeleteFiles(const ImageIdList &ids)
Delete images.
Definition: imagemanager.cpp:2297
GalleryThumbView::m_captionText
MythUIText * m_captionText
Definition: gallerythumbview.h:131
ShellThread::m_path
QString m_path
Definition: gallerythumbview.cpp:59
GalleryThumbView::DoScanAction
void DoScanAction(bool start)
Action scan request.
Definition: gallerythumbview.cpp:1425
kOrdered
@ kOrdered
Ordered as per user setting GallerySortOrder.
Definition: galleryviews.h:22
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
GALLERY_DB_ID
static constexpr int GALLERY_DB_ID
Definition: imagetypes.h:27
DirectoryView
A datastore of images for display by a screen. Provides an ordered list of dirs & images from a singl...
Definition: galleryviews.h:170
kShuffle
@ kShuffle
Each image appears exactly once, but in random order.
Definition: galleryviews.h:23
GetMythUI
MythUIHelper * GetMythUI()
Definition: mythuihelper.cpp:66
MythUIButtonList
List widget, displays list items in a variety of themeable arrangements and can trigger signals when ...
Definition: mythuibuttonlist.h:191
clean_comment
static QString clean_comment(const QString &comment)
Definition: gallerythumbview.cpp:26
DirectoryView::IsMarked
bool IsMarked(int id) const
Definition: galleryviews.h:188
MythUIProgressBar::SetVisible
void SetVisible(bool visible) override
Definition: mythuiprogressbar.cpp:193
kPicOnly
@ kPicOnly
Hide videos.
Definition: imagemanager.h:79
DirectoryView::ClearMarked
void ClearMarked()
Unmark all items.
Definition: galleryviews.cpp:775
kVideoOnly
@ kVideoOnly
Hide pictures.
Definition: imagemanager.h:80
GalleryThumbView::MenuMarked
void MenuMarked(MythMenu *mainMenu)
Adds a Marking submenu.
Definition: gallerythumbview.cpp:1081
MythUIButtonListItem::setChecked
void setChecked(CheckState state)
Definition: mythuibuttonlist.cpp:3679
MythScreenStack::AddScreen
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Definition: mythscreenstack.cpp:52
GalleryThumbView::Close
void Close() override
Exit Gallery.
Definition: gallerythumbview.cpp:192
ImageManagerFe::ScanQuery
static QStringList ScanQuery()
Returns storage group scanner status.
Definition: imagemanager.cpp:2041
ShowOkPopup
MythConfirmationDialog * ShowOkPopup(const QString &message, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
Definition: mythdialogbox.cpp:566
ImageManagerFe::RenameFile
QString RenameFile(const ImagePtrK &im, const QString &name)
Rename an image.
Definition: imagemanager.cpp:2206
ImageManagerFe::ShortDateOf
QString ShortDateOf(const ImagePtrK &im) const
Return a short datestamp for thumbnail captions.
Definition: imagemanager.cpp:2355
GalleryThumbView::Eject
void Eject()
Remove local device (or Import) from Gallery.
Definition: gallerythumbview.cpp:1912
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:42
MythCoreContext::SaveBoolSetting
void SaveBoolSetting(const QString &key, bool newValue)
Definition: mythcorecontext.h:160
TransferThread::m_dialog
MythUIProgressDialog * m_dialog
Images for which copy/move failed.
Definition: gallerythumbview.cpp:139
ShellThread::m_result
int m_result
Definition: gallerythumbview.cpp:57
kNoInfo
@ kNoInfo
Details not displayed.
Definition: galleryinfo.h:17
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:606
MenuSubjects::m_hiddenMarked
bool m_hiddenMarked
Is any marked item hidden ?
Definition: galleryviews.h:71
ImageManagerFe::DetectLocalDevices
bool DetectLocalDevices()
Detect and scan local devices.
Definition: imagemanager.cpp:2424