MythTV  master
iconview.cpp
Go to the documentation of this file.
1 /* ============================================================
2  * File : iconview.cpp
3  * Description :
4  *
5  * This program is free software; you can redistribute it
6  * and/or modify it under the terms of the GNU General
7  * Public License as published bythe Free Software Foundation;
8  * either version 2, or (at your option)
9  * any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * ============================================================ */
17 
18 // POSIX headers
19 #include <unistd.h>
20 
21 // ANSI C headers
22 #include <cmath>
23 
24 // C++ headers
25 #include <algorithm>
26 
27 using namespace std;
28 
29 // Qt headers
30 #include <QApplication>
31 #include <QEvent>
32 #include <QDir>
33 #include <QMatrix>
34 #include <QList>
35 #include <QFileInfo>
36 
37 // MythTV headers
38 #include <mythdate.h>
39 #include <mythdbcon.h>
40 #include <mythsystemlegacy.h>
41 #include <mythcontext.h>
42 #include <mythlogging.h>
43 #include <mythmainwindow.h>
44 #include <mythprogressdialog.h>
45 #include <mythmediamonitor.h>
46 
47 // MythGallery headers
48 #include "config.h"
49 #include "galleryutil.h"
50 #include "gallerysettings.h"
51 #include "galleryfilter.h"
52 #include "thumbgenerator.h"
53 #include "iconview.h"
54 #include "singleview.h"
55 #include "glsingleview.h"
56 
57 #define LOC QString("IconView: ")
58 
59 QEvent::Type ChildCountEvent::kEventType =
60  (QEvent::Type) QEvent::registerEventType();
61 
62 class FileCopyThread : public MThread
63 {
64  public:
65  FileCopyThread(IconView *parent, bool move);
66  void run() override; // MThread
67  int GetProgress(void) { return m_progress; }
68 
69  private:
70  bool m_move;
72  volatile int m_progress;
73 };
74 
76  MThread("FileCopy"), m_move(move), m_parent(parent), m_progress(0)
77 {
78 }
79 
81 {
82  RunProlog();
83 
84  QStringList::iterator it;
85  QFileInfo fi;
86  QFileInfo dest;
87 
88  m_progress = 0;
89 
90  for (it = m_parent->m_itemMarked.begin();
91  it != m_parent->m_itemMarked.end(); ++it)
92  {
93  fi.setFile(*it);
94  dest.setFile(QDir(m_parent->m_currDir), fi.fileName());
95 
96  if (fi.exists())
98 
99  m_progress++;
100  }
101 
102  RunEpilog();
103 }
104 
106 
107 ImportThread::ImportThread(const QString &cmd) :
108  MThread("import"), m_command(cmd)
109 {
110 }
111 
113 {
114  RunProlog();
115  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Executing %1").arg(m_command));
117  RunEpilog();
118 }
119 
121 
123  const QString &galleryDir, MythMediaDevice *initialDevice)
124  : MythScreenType(parent, name),
125  m_galleryDir(galleryDir),
126  m_galleryFilter(new GalleryFilter()),
127  m_imageList(nullptr),
128  m_captionText(nullptr), m_crumbsText(nullptr),
129  m_positionText(nullptr), m_noImagesText(nullptr),
130  m_selectedImage(nullptr), m_menuPopup(nullptr),
131  m_popupStack(nullptr),
132  m_isGallery(false), m_showDevices(false),
133  m_currDevice(initialDevice),
134  m_thumbGen(new ThumbGenerator(this, 0, 0)),
135  m_childCountThread(new ChildCountThread(this))
136 {
137  m_showcaption = gCoreContext->GetNumSetting("GalleryOverlayCaption", 0);
138  m_sortorder = gCoreContext->GetNumSetting("GallerySortOrder", 0);
139  m_useOpenGL = gCoreContext->GetBoolSetting("SlideshowUseOpenGL", false);
140  m_recurse = gCoreContext->GetBoolSetting("GalleryRecursiveSlideshow", false);
141  m_paths = gCoreContext->GetSetting("GalleryImportDirs").split(":");
142  m_allowImportScripts = gCoreContext->GetBoolSetting("GalleryAllowImportScripts", false);
143 
144  QDir dir(m_galleryDir);
145  if (!dir.exists() || !dir.isReadable())
146  {
147  m_errorStr = tr("MythGallery Directory '%1' does not exist "
148  "or is unreadable.").arg(m_galleryDir);
149  return;
150  }
151 
152  m_popupStack = GetMythMainWindow()->GetStack("popup stack");
153 }
154 
156 {
157  if (m_thumbGen)
158  {
159  delete m_thumbGen;
160  m_thumbGen = nullptr;
161  }
162  if (m_galleryFilter)
163  {
164  delete m_galleryFilter;
165  m_galleryFilter = nullptr;
166  }
167  if (m_childCountThread)
168  {
169  delete m_childCountThread;
170  m_childCountThread = nullptr;
171  }
172 }
173 
175 {
176  // Load the theme for this screen
177  bool foundtheme = LoadWindowFromXML("gallery-ui.xml", "gallery", this);
178  if (!foundtheme)
179  return false;
180 
181  bool err = false;
182  UIUtilE::Assign(this, m_imageList, "images", &err);
183  UIUtilW::Assign(this, m_captionText, "title");
184  UIUtilW::Assign(this, m_noImagesText, "noimages");
185  UIUtilW::Assign(this, m_selectedImage, "selectedimage");
186  UIUtilW::Assign(this, m_positionText, "position");
187  UIUtilW::Assign(this, m_crumbsText, "breadcrumbs");
188 
189  if (err)
190  {
191  LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'gallery'");
192  return false;
193  }
194 
195  connect(m_imageList, SIGNAL(itemClicked( MythUIButtonListItem*)),
196  this, SLOT( HandleItemSelect(MythUIButtonListItem*)));
197  connect(m_imageList, SIGNAL(itemSelected( MythUIButtonListItem*)),
198  this, SLOT( UpdateText(MythUIButtonListItem*)));
199  connect(m_imageList, SIGNAL(itemSelected( MythUIButtonListItem*)),
200  this, SLOT( UpdateImage(MythUIButtonListItem*)));
201 
202  if (m_noImagesText)
203  {
204  m_noImagesText->SetText(tr("No images found in this folder."));
205  m_noImagesText->SetVisible(false);
206  }
207 
208  BuildFocusList();
209 
210  // TODO Not accurate, the image may be smaller than the button
211  int thumbWidth = m_imageList->ItemWidth();
212  int thumbHeight = m_imageList->ItemHeight();
213  if (m_selectedImage && (m_selectedImage->GetArea().width() > thumbWidth ||
214  m_selectedImage->GetArea().height() > thumbHeight))
215  {
216  thumbWidth = m_selectedImage->GetArea().width();
217  thumbHeight = m_selectedImage->GetArea().height();
218  }
219 
220  if (m_thumbGen)
221  m_thumbGen->setSize(thumbWidth, thumbHeight);
222 
224  if (!m_currDevice)
226 
227  return true;
228 }
229 
230 void IconView::LoadDirectory(const QString &dir)
231 {
232  if (m_thumbGen && m_thumbGen->isRunning())
233  m_thumbGen->cancel();
234 
237 
238  QDir d(dir);
239  if (!d.exists())
240  {
241  LOG(VB_GENERAL, LOG_ERR, LOC + "LoadDirectory called with " +
242  QString("non-existant directory: '%1'").arg(dir));
243  return;
244  }
245 
246  m_showDevices = false;
247 
248  m_currDir = d.absolutePath();
249 
250  while (!m_itemList.isEmpty())
251  delete m_itemList.takeFirst();
252 
253  m_itemHash.clear();
254  m_imageList->Reset();
255 
257  false, &m_itemHash, m_thumbGen);
258 
259  if (m_thumbGen && !m_thumbGen->isRunning())
260  m_thumbGen->start();
261 
262  for (int x = 0; x < m_itemList.size(); x++)
263  {
264  ThumbItem *thumbitem = m_itemList.at(x);
265 
266  thumbitem->InitCaption(m_showcaption);
267  MythUIButtonListItem* item =
268  new MythUIButtonListItem(m_imageList, thumbitem->GetCaption(), nullptr,
270  item->SetData(qVariantFromValue(thumbitem));
271  if (thumbitem->IsDir())
272  {
273  item->DisplayState("subfolder", "nodetype");
274  m_childCountThread->addFile(thumbitem->GetPath());
275  }
276 
277  LoadThumbnail(thumbitem);
278 
279  if (QFile(thumbitem->GetImageFilename()).exists())
280  item->SetImage(thumbitem->GetImageFilename());
281 
282  if (m_itemMarked.contains(thumbitem->GetPath()))
284  }
285 
288 
289  if (m_noImagesText)
291 
292  if (!m_itemList.isEmpty())
293  {
296  }
297 }
298 
300 {
301  if (!item)
302  return;
303 
304  bool canLoadGallery = m_isGallery;
305 
306  QString imagePath;
307  if (canLoadGallery)
308  {
309  if (item->IsDir())
310  {
311  // try to find a highlight
312  QDir subdir(item->GetPath(), "*.highlight.*",
313  QDir::Name, QDir::Files);
314 
315  if (subdir.count() > 0)
316  {
317  // check if the image format is understood
318  QFileInfoList::const_iterator it = subdir.entryInfoList().begin();
319  if (it != subdir.entryInfoList().end())
320  {
321  imagePath = it->absoluteFilePath();
322  }
323  }
324  }
325  else
326  {
327  QString fn = item->GetName();
328  int firstDot = fn.indexOf('.');
329  if (firstDot > 0)
330  {
331  fn.insert(firstDot, ".thumb");
332  imagePath = QString("%1/%2").arg(m_currDir).arg(fn);
333  }
334  }
335 
336  canLoadGallery = !(QFile(imagePath).exists());
337  }
338 
339  if (!canLoadGallery)
340  imagePath = QString("%1%2.jpg")
342  .arg(item->GetName());
343 
344  item->SetImageFilename(imagePath);
345 }
346 
348 {
349 #ifdef _WIN32
350  if (m_currDevice)
352 #else
354  if (m_currDevice && mon && mon->ValidateAndLock(m_currDevice))
355  {
356  bool mounted = m_currDevice->isMounted();
357  if (!mounted)
358  mounted = m_currDevice->mount();
359 
360  if (mounted)
361  {
362  connect(m_currDevice,
363  SIGNAL(statusChanged(MythMediaStatus, MythMediaDevice*)),
365 
367 
368  mon->Unlock(m_currDevice);
369  return;
370  }
371  else
372  {
373 // DialogBox *dlg = new DialogBox(GetMythMainWindow(),
374 // tr("Failed to mount device: ") +
375 // m_currDevice->getDevicePath() + "\n\n" +
376 // tr("Showing the default MythGallery directory."));
377 // dlg->AddButton(tr("OK"));
378 // dlg->exec();
379 // dlg->deleteLater();
380  mon->Unlock(m_currDevice);
381  }
382  }
383 #endif // _WIN32
384 }
385 
387 {
388  if (!item)
389  {
390  if (m_positionText)
392  return;
393  }
394 
395  if (m_positionText)
396  m_positionText->SetText(tr("%1 of %2")
397  .arg(m_imageList->IsEmpty() ? 0 : m_imageList->GetCurrentPos() + 1)
398  .arg(m_imageList->GetCount()));
399 
400  ThumbItem *thumbitem = item->GetData().value<ThumbItem *>();
401  if (!thumbitem)
402  return;
403 
404  if (m_crumbsText)
405  {
406  QString path = thumbitem->GetPath();
407  path.replace(m_galleryDir, tr("Gallery Home"));
408  path.replace("/", " > ");
409  m_crumbsText->SetText(path);
410  }
411 
412  if (m_captionText)
413  {
414  QString caption;
415  caption = thumbitem->GetCaption();
416  caption = (caption.isNull()) ? "" : caption;
417  m_captionText->SetText(caption);
418  }
419 }
420 
422 {
423  if (!m_selectedImage)
424  return;
425 
426  ThumbItem *thumbitem = item->GetData().value<ThumbItem *>();
427 
428  QString selectedimage;
429  if (thumbitem)
430  {
431  selectedimage = thumbitem->GetImageFilename();
432  selectedimage = (selectedimage.isNull()) ? "" : selectedimage;
433  }
434  m_selectedImage->SetFilename(selectedimage);
436 }
437 
438 
439 bool IconView::keyPressEvent(QKeyEvent *event)
440 {
441  if (GetFocusWidget()->keyPressEvent(event))
442  return true;
443 
444  QStringList actions;
445  bool handled = GetMythMainWindow()->TranslateKeyPress("Gallery", event, actions);
446 
447  for (int i = 0; i < actions.size() && !handled; i++)
448  {
449  QString action = actions[i];
450  handled = true;
451 
452  if (!m_itemList.isEmpty())
453  {
454  if (action == "ROTRIGHT")
455  HandleRotateCW();
456  else if (action == "ROTLEFT")
457  HandleRotateCCW();
458  else if (action == "DELETE")
459  HandleDelete();
460  else if (action == "EDIT")
461  HandleRename();
462  else if (action == "MARK")
463  {
464  ThumbItem *thumbitem = GetCurrentThumb();
466 
467  if (thumbitem)
468  {
469  if (!m_itemMarked.contains(thumbitem->GetPath()))
470  {
471  m_itemMarked.append(thumbitem->GetPath());
473  }
474  else
475  {
476  m_itemMarked.removeAll(thumbitem->GetPath());
478  }
479  }
480  }
481  else if (action == "SLIDESHOW")
482  HandleSlideShow();
483  else if (action == "RANDOMSHOW")
485  else if (action == "SEASONALSHOW")
487  else
488  handled = false;
489  }
490 
491  if (action == "ESCAPE")
492  {
493  if (GetMythMainWindow()->IsExitingToMain())
494  {
495  while ( m_currDir != m_galleryDir &&
497  }
498  handled = HandleEscape();
499  }
500  else if (action == "MENU")
501  {
502  HandleMainMenu();
503  }
504  }
505 
506  if (!handled && MythScreenType::keyPressEvent(event))
507  handled = true;
508 
509  return handled;
510 }
511 
513 {
514  bool handled = false;
515 
516  ThumbItem *thumbitem = item->GetData().value<ThumbItem *>();
517 
518  if (!thumbitem)
519  return;
520 
521  // if the selected thumbitem is a Media Device
522  // attempt to mount it if it isn't already
523  if (thumbitem->GetMediaDevice())
524  handled = HandleMediaDeviceSelect(thumbitem);
525 
526  if (!handled && thumbitem->IsDir())
527  {
528  m_history.push_back(m_imageList->GetCurrentPos());
529  LoadDirectory(thumbitem->GetPath());
530 
531  handled = true;
532  }
533 
534  if (!handled)
535  HandleImageSelect("SELECT");
536 }
537 
539 {
541  if (mon && mon->ValidateAndLock(item->GetMediaDevice()))
542  {
543  m_currDevice = item->GetMediaDevice();
544 
545 #ifdef _WIN32
547 #else
548  if (!m_currDevice->isMounted(false))
549  m_currDevice->mount();
550 
551  item->SetPath(m_currDevice->getMountPath(), true);
552 
553  connect(m_currDevice,
554  SIGNAL(statusChanged(MythMediaStatus,
555  MythMediaDevice*)),
557  MythMediaDevice*)));
558 
560 #endif
561 
562  mon->Unlock(m_currDevice);
563  }
564  else
565  {
566  // device was removed
567  QString msg = tr("Error") + '\n' +
568  tr("The selected device is no longer available");
569  ShowOkPopup(msg, this, SLOT(HandleShowDevices()));
570  }
571 
572  return true;
573 }
574 
576 {
577  HandleImageSelect("SLIDESHOW");
578 
580 }
581 
583 {
584  HandleImageSelect("RANDOMSHOW");
585 
587 }
588 
590 {
591  HandleImageSelect("SEASONALSHOW");
592 
594 }
595 
597 {
598  ThumbItem *thumbitem = GetCurrentThumb();
599 
600  if (!thumbitem || (thumbitem->IsDir() && !m_recurse))
601  return false;
602 
603  int slideShow = ((action == "PLAY" || action == "SLIDESHOW") ? 1 :
604  (action == "RANDOMSHOW") ? 2 :
605  (action == "SEASONALSHOW" ? 3 : 0));
606 
607  int pos = m_imageList->GetCurrentPos();
608 
609 #ifdef USING_OPENGL
610  if (m_useOpenGL && QGLFormat::hasOpenGL())
611  {
612  GLSDialog gv(m_itemList, &pos,
613  slideShow, m_sortorder,
615  gv.exec();
616  }
617  else
618 #endif
619  {
620  SingleView sv(m_itemList, &pos, slideShow, m_sortorder,
622  sv.exec();
623  }
624 
625  // if the user deleted files while in single view mode
626  // the cached contents of the directory will be out of
627  // sync, reload the current directory to refresh the view
629 
631 
632  return true;
633 }
634 
636 {
637  bool handled = false;
638  QDir curdir(m_currDir);
639  QList<MythMediaDevice*> removables = mon->GetMedias(MEDIATYPE_DATA|MEDIATYPE_MGALLERY|MEDIATYPE_MVIDEO);
640  QList<MythMediaDevice*>::iterator it = removables.begin();
641  for (; !handled && (it != removables.end()); ++it)
642  {
643  if (!mon->ValidateAndLock(*it))
644  continue;
645 
646  if (curdir == QDir((*it)->getMountPath()))
647  {
649 
650  // Make sure previous devices are visible and selected
651  ThumbItem *item = nullptr;
652  if (!(*it)->getVolumeID().isEmpty())
653  item = m_itemHash.value((*it)->getVolumeID());
654  else
655  item = m_itemHash.value((*it)->getDevicePath());
656 
657  if (item)
658  {
659  int pos = m_itemList.indexOf(item);
661  }
662 
663  handled = true;
664  }
665  else
666  {
667  handled = HandleSubDirEscape((*it)->getMountPath());
668  }
669 
670  mon->Unlock(*it);
671  }
672 
673  return handled;
674 }
675 
676 static bool is_subdir(const QDir &parent, const QDir &subdir)
677 {
678  QString pstr = QDir::cleanPath(parent.path());
679  QString cstr = QDir::cleanPath(subdir.path());
680  bool ret = !cstr.indexOf(pstr);
681 
682  return ret;
683 }
684 
685 bool IconView::HandleSubDirEscape(const QString &parent)
686 {
687  bool handled = false;
688 
689  QDir curdir(m_currDir);
690  QDir pdir(parent);
691  if ((curdir != pdir) && is_subdir(pdir, curdir) && !m_history.empty())
692  {
693  QString oldDirName = curdir.dirName();
694  curdir.cdUp();
695  LoadDirectory(curdir.absolutePath());
696 
697  int pos = m_history.back();
698  m_history.pop_back();
700  handled = true;
701  }
702 
703  return handled;
704 }
705 
707 {
708 #if 0
709  LOG(VB_GENERAL, LOG_INFO, LOC + "HandleEscape() " +
710  QString("showDevices: %1").arg(m_showDevices));
711 #endif
712 
713  bool handled = false;
714 
715  // If we are showing the attached devices, ESCAPE should always exit..
716  if (m_showDevices)
717  {
718 #if 0
719  LOG(VB_GENERAL, LOG_INFO, LOC +
720  "HandleEscape() exiting on showDevices");
721 #endif
722  return false;
723  }
724 
725  // If we are viewing an attached device we should show the attached devices
727  if (mon && m_currDevice)
728  handled = HandleMediaEscape(mon);
729 
730  // If we are viewing a subdirectory of the gallery directory, we should
731  // move up the directory tree, otherwise ESCAPE should exit..
732  if (!handled)
733  handled = HandleSubDirEscape(m_galleryDir);
734 
735 #if 0
736  LOG(VB_GENERAL, LOG_INFO, LOC + QString("HandleEscape() handled: %1")
737  .arg(handled));
738 #endif
739 
740  return handled;
741 }
742 
743 void IconView::customEvent(QEvent *event)
744 {
745  if (event->type() == ThumbGenEvent::kEventType)
746  {
747  ThumbGenEvent *tge = dynamic_cast<ThumbGenEvent *>(event);
748 
749  if (!tge)
750  return;
751 
752  ThumbData *td = tge->thumbData;
753  if (!td)
754  return;
755 
756  ThumbItem *thumbitem = m_itemHash.value(td->fileName);
757  if (thumbitem)
758  {
759  int rotateAngle = thumbitem->GetRotationAngle();
760 
761  if (rotateAngle)
762  {
763  QMatrix matrix;
764  matrix.rotate(rotateAngle);
765  td->thumb = td->thumb.transformed(
766  matrix, Qt::SmoothTransformation);
767  }
768 
769  int pos = m_itemList.indexOf(thumbitem);
770 
771  LoadThumbnail(thumbitem);
772 
774  if (QFile(thumbitem->GetImageFilename()).exists())
775  item->SetImage(thumbitem->GetImageFilename());
776 
777  if (m_imageList->GetCurrentPos() == pos)
778  UpdateImage(item);
779  }
780  delete td;
781  }
782  else if (event->type() == ChildCountEvent::kEventType)
783  {
784  ChildCountEvent *cce = dynamic_cast<ChildCountEvent *>(event);
785 
786  if (!cce)
787  return;
788 
789  ChildCountData *ccd = cce->childCountData;
790  if (!ccd)
791  return;
792 
793  ThumbItem *thumbitem = m_itemHash.value(ccd->fileName);
794  if (thumbitem)
795  {
796  int pos = m_itemList.indexOf(thumbitem);
798  if (item)
799  item->SetText(QString("%1").arg(ccd->count), "childcount");
800  }
801  delete ccd;
802  }
803  else if (event->type() == DialogCompletionEvent::kEventType)
804  {
806 
807  QString resultid = dce->GetId();
808  int resultdata = dce->GetData().toInt();
809 
810  if (resultid == "mainmenu")
811  {
812  switch (resultdata)
813  {
814  case 0:
815  HandleSlideShow();
816  break;
817  case 1:
819  break;
820  case 2:
821  break;
822  case 3:
823  break;
824  case 4:
826  break;
827  case 5:
828  break;
829  case 6:
830  HandleSettings();
831  break;
832  case 7:
834  break;
835  }
836  }
837  else if (resultid == "metadatamenu")
838  {
839  switch (resultdata)
840  {
841  case 0:
842  HandleRotateCW();
843  break;
844  case 1:
845  HandleRotateCCW();
846  break;
847  }
848  }
849  else if (resultid == "markingmenu")
850  {
851  switch (resultdata)
852  {
853  case 0:
854  HandleSelectOne();
855  break;
856  case 1:
858  break;
859  case 2:
860  HandleSelectAll();
861  break;
862  case 3:
864  break;
865  }
866  }
867  else if (resultid == "filemenu")
868  {
869  switch (resultdata)
870  {
871  case 0:
873  break;
874  case 1:
875  HandleEject();
876  break;
877  case 2:
878  HandleImport();
879  break;
880  case 3:
881  HandleCopyHere();
882  break;
883  case 4:
884  HandleMoveHere();
885  break;
886  case 5:
887  HandleDelete();
888  break;
889  case 6:
890  HandleMkDir();
891  break;
892  case 7:
893  HandleRename();
894  break;
895  }
896  }
897 
898  m_menuPopup = nullptr;
899 
900  }
901 
902 }
903 
905 {
907 }
908 
910 {
911  QString label = tr("Gallery Options");
912 
913  MythMenu *menu = new MythMenu(label, this, "mainmenu");
914 
915  if (!m_itemList.isEmpty())
916  {
917  menu->AddItem(tr("SlideShow"), nullptr);
918  menu->AddItem(tr("Random"), 1);
919 #ifdef EXIF_SUPPORT
920  menu->AddItem(tr("Seasonal"), 7);
921 #endif // EXIF_SUPPORT
922  menu->AddItem(tr("Meta Data Options"), 2, CreateMetadataMenu());
923  }
924 
925  menu->AddItem(tr("Marking Options"), 3, CreateMarkingMenu());
926  menu->AddItem(tr("Filter / Sort..."), 4);
927  menu->AddItem(tr("File Options"), 5, CreateFileMenu());
928  menu->AddItem(tr("Settings..."), 6);
929 // if (m_showDevices)
930 // {
931 // QDir d(m_currDir);
932 // if (!d.exists())
933 // m_currDir = m_galleryDir;
934 //
935 // LoadDirectory(m_currDir);
936 // m_showDevices = false;
937 // }
938 
939  m_menuPopup = new MythDialogBox(menu, m_popupStack, "mythgallerymenupopup");
940 
941  if (!m_menuPopup->Create())
942  {
943  delete m_menuPopup;
944  m_menuPopup = nullptr;
945  return;
946  }
947 
949 }
950 
952 {
953  QString label = tr("Metadata Options");
954 
955  MythMenu *menu = new MythMenu(label, this, "metadatamenu");
956 
957  menu->AddItem(tr("Rotate CW"), nullptr);
958  menu->AddItem(tr("Rotate CCW"), 1);
959 
960  return menu;
961 }
962 
964 {
965  QString label = tr("Marking Options");
966 
967  MythMenu *menu = new MythMenu(label, this, "markingmenu");
968 
969  menu->AddItem(tr("Select One"), nullptr);
970  menu->AddItem(tr("Clear One Marked"), 1);
971  menu->AddItem(tr("Select All"), 2);
972  menu->AddItem(tr("Clear Marked"), 3);
973 
974  return menu;
975 }
976 
978 {
979  MythScreenStack *mainStack = GetScreenStack();
980 
981  GalleryFilterDialog *filterdialog =
982  new GalleryFilterDialog(mainStack, "galleryfilter", m_galleryFilter);
983 
984  if (filterdialog->Create())
985  mainStack->AddScreen(filterdialog);
986 
987  connect(filterdialog, SIGNAL(filterChanged()), SLOT(reloadData()));
988 }
989 
991 {
992  QString label = tr("File Options");
993 
994  MythMenu *menu = new MythMenu(label, this, "filemenu");
995 
996  menu->AddItem(tr("Show Devices"), nullptr);
997  menu->AddItem(tr("Eject"), 1);
998  menu->AddItem(tr("Import"), 2);
999 
1000  if (!m_itemMarked.isEmpty())
1001  {
1002  menu->AddItem(tr("Copy here"), 3);
1003  menu->AddItem(tr("Move here"), 4);
1004  }
1005 
1006  if (!m_imageList->IsEmpty())
1007  menu->AddItem(tr("Delete"), 5);
1008 
1009  menu->AddItem(tr("Create folder"), 6);
1010 
1011  if (!m_imageList->IsEmpty())
1012  menu->AddItem(tr("Rename"), 7);
1013 
1014  return menu;
1015 }
1016 
1018 {
1019  ThumbItem *thumbitem = GetCurrentThumb();
1020 
1021  if (!thumbitem || thumbitem->IsDir())
1022  return;
1023 
1024  int rotAngle = thumbitem->GetRotationAngle();
1025 
1026  rotAngle += 90;
1027 
1028  if (rotAngle >= 360)
1029  rotAngle -= 360;
1030 
1031  if (rotAngle < 0)
1032  rotAngle += 360;
1033 
1034  thumbitem->SetRotationAngle(rotAngle);
1035 }
1036 
1038 {
1039  ThumbItem *thumbitem = GetCurrentThumb();
1040 
1041  if (!thumbitem || thumbitem->IsDir())
1042  return;
1043 
1044  int rotAngle = thumbitem->GetRotationAngle();
1045 
1046  rotAngle -= 90;
1047 
1048  if (rotAngle >= 360)
1049  rotAngle -= 360;
1050 
1051  if (rotAngle < 0)
1052  rotAngle += 360;
1053 
1054  thumbitem->SetRotationAngle(rotAngle);
1055 }
1056 
1058 {
1059  ThumbItem *thumbitem = GetCurrentThumb();
1060 
1061  if (!thumbitem)
1062  return;
1063 
1064  QString title = tr("Delete Current File or Folder");
1065  QString msg = (thumbitem->IsDir()) ?
1066  tr("Deleting 1 folder, including any subfolders and files.") :
1067  tr("Deleting 1 image.");
1068 
1069  ShowOkPopup(title + '\n' + msg, this, SLOT(DoDeleteCurrent(bool)), true);
1070 }
1071 
1072 void IconView::DoDeleteCurrent(bool doDelete)
1073 {
1074  if (doDelete)
1075  {
1076  ThumbItem *thumbitem = GetCurrentThumb();
1077 
1078  int currPos = 0;
1080  if (item)
1081  currPos = m_imageList->GetCurrentPos();
1082 
1083  if (!thumbitem)
1084  return;
1085 
1086  QFileInfo fi;
1087  fi.setFile(thumbitem->GetPath());
1088  GalleryUtil::Delete(fi);
1089 
1091 
1092  m_imageList->SetItemCurrent(currPos);
1093  }
1094 }
1095 
1097 {
1099  StandardSettingDialog *ssd =
1100  new StandardSettingDialog(mainStack, "gallerysettings",
1101  new GallerySettings());
1102 
1103  if (ssd->Create())
1104  {
1105  mainStack->AddScreen(ssd);
1106 // connect(ssd, SIGNAL(Close()), this, SLOT(ReloadSettings()));
1107  }
1108  else
1109  delete ssd;
1110 
1111 }
1112 
1114 {
1116 
1117  // reload settings
1118  m_showcaption = gCoreContext->GetNumSetting("GalleryOverlayCaption", 0);
1119  m_sortorder = gCoreContext->GetNumSetting("GallerySortOrder", 0);
1120  m_useOpenGL = gCoreContext->GetBoolSetting("SlideshowUseOpenGL", false);
1121  m_recurse = gCoreContext->GetBoolSetting("GalleryRecursiveSlideshow", false);
1122  m_paths = gCoreContext->GetSetting("GalleryImportDirs").split(":");
1123  m_allowImportScripts = gCoreContext->GetBoolSetting("GalleryAllowImportScripts", false);
1124 
1125  // reload directory
1127  if (m_currDevice && mon && mon->ValidateAndLock(m_currDevice))
1128  {
1129 #ifdef _WIN32
1131 #else
1133 #endif
1134  mon->Unlock(m_currDevice);
1135  }
1136  else
1137  {
1138  m_currDevice = nullptr;
1140  }
1141 
1143 }
1144 
1146 {
1148 }
1149 
1151 {
1152  QFileInfo path;
1153  QDir importdir;
1154 
1155  // Makes import directory samba/windows friendly (no colon)
1156  QString idirname = m_currDir + "/" +
1157  MythDate::current().toString("yyyy-MM-dd_hh-mm-ss");
1158 
1159  importdir.mkdir(idirname);
1160  importdir.setPath(idirname);
1161 
1162  for (QStringList::const_iterator it = m_paths.begin();
1163  it != m_paths.end(); ++it)
1164  {
1165  path.setFile(*it);
1166  if (path.isDir() && path.isReadable())
1167  {
1168  ImportFromDir(*it, importdir.absolutePath());
1169  }
1170  else if (path.isFile() && path.isExecutable())
1171  {
1173  {
1174  QString cmd = *it + " " + importdir.absolutePath();
1175 
1176  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
1177  MythUIBusyDialog *busy =
1178  new MythUIBusyDialog(tr("Importing images from camera. Please wait..."),
1179  popupStack,
1180  "importbusydialog");
1181 
1182  if (busy->Create())
1183  {
1184  popupStack->AddScreen(busy, false);
1185  }
1186  else
1187  {
1188  delete busy;
1189  busy = nullptr;
1190  }
1191 
1192  ImportThread *import = new ImportThread(cmd);
1193  import->start();
1194 
1195  while (!import->isFinished())
1196  {
1197  usleep(500);
1198  qApp->processEvents();
1199  }
1200 
1201  delete import;
1202 
1203  if (busy)
1204  busy->Close();
1205  }
1206  else
1207  {
1208  ShowOkPopup(tr("Found an import script (%1) but running them has been disabled in the settings!")
1209  .arg(*it));
1210  importdir.rmdir(importdir.absolutePath());
1211  return;
1212  }
1213  }
1214  else
1215  {
1216  LOG(VB_GENERAL, LOG_ERR, LOC +
1217  QString("Could not read or execute %1").arg(*it));
1218 
1219  ShowOkPopup(tr("Could not read or execute %1").arg(*it));
1220  }
1221  }
1222 
1223  importdir.setFilter(QDir::Files | QDir::Readable | QDir::NoDotAndDotDot);
1224  importdir.refresh();
1225  if (importdir.count() == 0)
1226  {
1227  ShowOkPopup(tr("Nothing found to import"));
1228  importdir.rmdir(importdir.absolutePath());
1229  return;
1230  }
1231  else
1232  ShowOkPopup(tr("Found %n image(s)", "", importdir.count()));
1233 
1235 }
1236 
1238 {
1240 #ifndef _WIN32
1241  if (m_currDevice && mon && mon->ValidateAndLock(m_currDevice))
1242  {
1243  m_currDevice->disconnect(this);
1244  mon->Unlock(m_currDevice);
1245  }
1246  else
1248 #endif
1249 
1250  m_currDevice = nullptr;
1251 
1252  m_showDevices = true;
1253 
1254  while (!m_itemList.isEmpty())
1255  delete m_itemList.takeFirst();
1256 
1257  m_itemHash.clear();
1258  m_imageList->Reset();
1259 
1260  m_thumbGen->cancel();
1262 
1263  // add gallery directory
1264  ThumbItem *item = new ThumbItem("Gallery", m_galleryDir, true);
1265  m_itemList.append(item);
1266  m_itemHash.insert(item->GetName(), item);
1267 
1268  if (mon)
1269  {
1271  QList<MythMediaDevice*> removables = mon->GetMedias(type);
1272  QList<MythMediaDevice*>::Iterator it = removables.begin();
1273  for (; it != removables.end(); ++it)
1274  {
1275  if (mon->ValidateAndLock(*it))
1276  {
1277  ThumbItem *item2 = new ThumbItem(
1278  (*it)->getVolumeID().isEmpty() ?
1279  (*it)->getDevicePath() : (*it)->getVolumeID(),
1280  (*it)->getMountPath(), true, *it);
1281 
1282  m_itemList.append(item2);
1283  m_itemHash.insert(item2->GetName(), item2);
1284 
1285  mon->Unlock(*it);
1286  }
1287  }
1288  }
1289 
1290  for (int x = 0; x < m_itemList.size(); x++)
1291  {
1292  ThumbItem *item3 = m_itemList.at(x);
1293 
1294  item3->InitCaption(m_showcaption);
1295  MythUIButtonListItem* menuitem =
1296  new MythUIButtonListItem(m_imageList, item3->GetCaption(), nullptr,
1298  menuitem->SetData(qVariantFromValue(item3));
1299  }
1300 
1301  // exit from menu on show devices action..
1303 }
1304 
1306 {
1307  CopyMarkedFiles(false);
1309 }
1310 
1312 {
1313  CopyMarkedFiles(true);
1315 }
1316 
1318 {
1319  if (m_itemMarked.isEmpty())
1321  else
1323 }
1324 
1326 {
1327  QString msg = /*tr("Delete Marked Files") + "\n\n" +*/
1328  tr("Deleting %1 images and folders, including "
1329  "any subfolders and files.").arg(m_itemMarked.count());
1330  ShowOkPopup(msg, this, SLOT(DoDeleteMarked(bool)), true);
1331 }
1332 
1333 void IconView::DoDeleteMarked(bool doDelete)
1334 {
1335  if (doDelete)
1336  {
1337  QStringList::iterator it;
1338  QFileInfo fi;
1339 
1340  for (it = m_itemMarked.begin(); it != m_itemMarked.end(); ++it)
1341  {
1342  fi.setFile(*it);
1343 
1344  GalleryUtil::Delete(fi);
1345  }
1346 
1347  m_itemMarked.clear();
1348 
1350  }
1351 }
1352 
1354 {
1356  if (!item)
1357  return;
1359 }
1360 
1362 {
1364  if (!item)
1365  return;
1367 }
1368 
1370 {
1371  m_itemMarked.clear();
1373 }
1374 
1376 {
1377  for (int x = 0; x < m_itemList.size(); x++)
1378  {
1379  ThumbItem *item = m_itemList.at(x);
1380 
1381  if (!m_itemMarked.contains(item->GetPath()))
1382  m_itemMarked.append(item->GetPath());
1383  }
1384 
1386 }
1387 
1389 {
1390  QString folderName = tr("New Folder");
1391 
1392  QString message = tr("Create New Folder");
1393 
1394  MythTextInputDialog *dialog = new MythTextInputDialog(m_popupStack, message);
1395 
1396  if (dialog->Create())
1397  m_popupStack->AddScreen(dialog);
1398 
1399  connect(dialog, SIGNAL(haveResult(QString)),
1400  SLOT(DoMkDir(QString)), Qt::QueuedConnection);
1401 }
1402 
1403 void IconView::DoMkDir(QString folderName)
1404 {
1405  QDir cdir(m_currDir);
1406  cdir.mkdir(folderName);
1407 
1409 }
1410 
1411 
1413 {
1414  ThumbItem *thumbitem = GetCurrentThumb();
1415 
1416  if (!thumbitem)
1417  return;
1418 
1419  QString folderName = thumbitem->GetName();
1420 
1421  QString message = tr("Rename");
1422 
1424  message, FilterNone, false, folderName);
1425 
1426  if (dialog->Create())
1427  m_popupStack->AddScreen(dialog);
1428 
1429  connect(dialog, SIGNAL(haveResult(QString)),
1430  SLOT(DoRename(QString)), Qt::QueuedConnection);
1431 }
1432 
1433 void IconView::DoRename(QString folderName)
1434 {
1435  if (folderName.isEmpty() || folderName == "." || folderName == "..")
1436  return;
1437 
1438  ThumbItem *thumbitem = GetCurrentThumb();
1439 
1440  int currPos = 0;
1442  if (item)
1443  {
1444  currPos = m_imageList->GetCurrentPos() + 1;
1445 
1446  if (currPos >= m_imageList->GetCount())
1447  currPos = m_imageList->GetCount() - 1;
1448  }
1449 
1450  if (!thumbitem)
1451  return;
1452 
1453  if (!GalleryUtil::Rename(m_currDir, thumbitem->GetName(), folderName))
1454  {
1455  QString msg;
1456  if (thumbitem->IsDir())
1457  msg = tr("Failed to rename folder");
1458  else
1459  msg = tr("Failed to rename file");
1460 
1461  ShowOkPopup(msg);
1462 
1463  return;
1464  }
1465 
1467 
1468  m_imageList->SetItemCurrent(currPos);
1469 }
1470 
1471 void IconView::ImportFromDir(const QString &fromDir, const QString &toDir)
1472 {
1473  QDir d(fromDir);
1474 
1475  if (!d.exists())
1476  return;
1477 
1478  d.setNameFilters(GalleryUtil::GetMediaFilter());
1479  d.setSorting((QDir::SortFlag)m_sortorder);
1480  d.setFilter(QDir::Files | QDir::AllDirs |
1481  QDir::NoSymLinks | QDir::Readable |
1482  QDir::NoDotAndDotDot);
1483  QFileInfoList list = d.entryInfoList();
1484  QFileInfoList::const_iterator it = list.begin();
1485 
1486  while (it != list.end())
1487  {
1488  const QFileInfo *fi = &(*it);
1489  ++it;
1490 
1491  if (fi->isDir())
1492  {
1493  QString newdir(toDir + "/" + fi->fileName());
1494  d.mkdir(newdir);
1495  ImportFromDir(fi->absoluteFilePath(), newdir);
1496  }
1497  else
1498  {
1499  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Copying %1 to %2")
1500  .arg(fi->absoluteFilePath())
1501  .arg(toDir));
1502 
1503  // TODO FIXME, we shouldn't need a myth_system call here
1504  QString cmd = QString("cp \"%1\" \"%2\"")
1505  .arg(fi->absoluteFilePath()).arg(toDir);
1506  cmd = QString(cmd.toLocal8Bit().constData());
1507  myth_system(cmd);
1508  }
1509  }
1510 }
1511 
1513 {
1514  if (m_itemMarked.isEmpty())
1515  return;
1516 
1517  QString msg = (move) ?
1518  tr("Moving marked images...") : tr("Copying marked images...");
1519 
1520  MythUIProgressDialog *copy_progress = new MythUIProgressDialog(msg,
1521  m_popupStack,
1522  "copyprogressdialog");
1523 
1524  if (copy_progress->Create())
1525  {
1526  m_popupStack->AddScreen(copy_progress, false);
1527  copy_progress->SetTotal(m_itemMarked.count());
1528  }
1529  else
1530  {
1531  delete copy_progress;
1532  copy_progress = nullptr;
1533  }
1534 
1535  FileCopyThread *filecopy = new FileCopyThread(this, move);
1536  int progress = -1;
1537  filecopy->start();
1538 
1539  while (!filecopy->isFinished())
1540  {
1541  if (copy_progress)
1542  {
1543  if (progress != filecopy->GetProgress())
1544  {
1545  progress = filecopy->GetProgress();
1546  copy_progress->SetProgress(progress);
1547  }
1548  }
1549 
1550  usleep(500);
1551  qApp->processEvents();
1552  }
1553 
1554  delete filecopy;
1555 
1556  if (copy_progress)
1557  copy_progress->Close();
1558 
1560 }
1561 
1563  MythMediaDevice *pMedia)
1564 {
1565  (void) oldStatus;
1566  if (m_currDevice == pMedia)
1567  {
1569 
1570  // UpdateText();
1571  }
1572 }
1573 
1575 {
1577  if (item)
1578  return item->GetData().value<ThumbItem *>();
1579  return nullptr;
1580 }
1581 
1583 
1585  MThread("ChildCountThread"), m_parent(parent)
1586 {
1587 }
1588 
1590 {
1591  cancel();
1592  wait();
1593 }
1594 
1595 void ChildCountThread::addFile(const QString& filePath)
1596 {
1597  m_mutex.lock();
1598  m_fileList.append(filePath);
1599  m_mutex.unlock();
1600 }
1601 
1603 {
1604  m_mutex.lock();
1605  m_fileList.clear();
1606  m_mutex.unlock();
1607 }
1608 
1610 {
1611  RunProlog();
1612 
1613  while (moreWork())
1614  {
1615  QString file;
1616 
1617  m_mutex.lock();
1618  file = m_fileList.first();
1619  if (!m_fileList.isEmpty())
1620  m_fileList.pop_front();
1621  m_mutex.unlock();
1622 
1623  if (file.isEmpty())
1624  continue;
1625  int count = getChildCount(file);
1626 
1627  ChildCountData *ccd = new ChildCountData;
1628  ccd->fileName = file.section('/', -1);
1629  ccd->count = count;
1630 
1631  // inform parent we have got a count ready for it
1632  QApplication::postEvent(m_parent, new ChildCountEvent(ccd));
1633  }
1634 
1635  RunEpilog();
1636 }
1637 
1639 {
1640  bool result;
1641  m_mutex.lock();
1642  result = !m_fileList.isEmpty();
1643  m_mutex.unlock();
1644  return result;
1645 }
1646 
1647 int ChildCountThread::getChildCount(const QString &filepath)
1648 {
1649  QDir d(filepath);
1650 
1651  bool isGallery;
1652  QFileInfoList gList = d.entryInfoList(QStringList("serial*.dat"),
1653  QDir::Files);
1654  isGallery = (gList.count() != 0);
1655 
1656  QFileInfoList list = d.entryInfoList(GalleryUtil::GetMediaFilter(),
1657  QDir::Files | QDir::AllDirs |
1658  QDir::NoDotAndDotDot);
1659 
1660  if (list.isEmpty())
1661  return 0;
1662 
1663  QFileInfoList::const_iterator it = list.begin();
1664 
1665  int count = 0;
1666  while (it != list.end())
1667  {
1668  const QFileInfo *fi = &(*it);
1669  ++it;
1670 
1671  // remove these already-resized pictures.
1672  if (isGallery && (
1673  (fi->fileName().indexOf(".thumb.") > 0) ||
1674  (fi->fileName().indexOf(".sized.") > 0) ||
1675  (fi->fileName().indexOf(".highlight.") > 0)))
1676  continue;
1677 
1678  count++;
1679  }
1680 
1681  return count;
1682 }
1683 
1684 /*
1685  * vim:ts=4:sw=4:ai:et:si:sts=4
1686  */
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:216
void HandleRotateCW(void)
Definition: iconview.cpp:1017
void start(QThread::Priority=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:295
QString GetCaption(void) const
Definition: thumbview.h:57
MythScreenStack * GetScreenStack() const
QMutex m_mutex
Definition: iconview.h:203
void UpdateText(MythUIButtonListItem *)
Definition: iconview.cpp:386
void HandleClearMarked(void)
Definition: iconview.cpp:1369
This is a wrapper around QThread that does several additional things.
Definition: mthread.h:46
const QString & getDevicePath() const
Definition: mythmedia.h:61
QString fileName
void HandleSettings(void)
Definition: iconview.cpp:1096
void HandleSeasonalShow(void)
Definition: iconview.cpp:589
MythMediaType
Definition: mythmedia.h:24
QImage thumb
QString m_errorStr
Definition: iconview.h:149
void HandleCopyHere(void)
Definition: iconview.cpp:1305
bool TranslateKeyPress(const QString &context, QKeyEvent *e, QStringList &actions, bool allowJumps=true)
Get a list of actions for a keypress in the given context.
void mediaStatusChanged(MythMediaStatus oldStatus, MythMediaDevice *pMedia)
Definition: iconview.cpp:1562
QObject * m_parent
Definition: iconview.h:201
void SetProgress(uint count)
bool HandleImageSelect(const QString &action)
Definition: iconview.cpp:596
MythConfirmationDialog * ShowOkPopup(const QString &message, QObject *parent, const char *slot, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
bool Create(void) override
void HandleItemSelect(MythUIButtonListItem *)
Definition: iconview.cpp:512
vector< int > m_history
Definition: iconview.h:123
void SetData(QVariant data)
bool Create(void) override
Definition: iconview.cpp:174
static void ejectOpticalDisc(void)
Eject a disk, unmount a drive, open a tray.
void HandleMoveHere(void)
Definition: iconview.cpp:1311
bool wait(unsigned long time=ULONG_MAX)
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:312
Basic menu dialog, message and a list of options.
void customEvent(QEvent *) override
Definition: iconview.cpp:743
MythMediaDevice * GetMediaDevice(void)
Definition: thumbview.h:68
static bool Rename(const QString &currDir, const QString &oldName, const QString &newName)
void run() override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
Definition: iconview.cpp:1609
virtual void SetText(const QString &text)
Definition: mythuitext.cpp:168
friend class FileCopyThread
Definition: iconview.h:162
bool m_recurse
Definition: iconview.h:146
bool HandleMediaDeviceSelect(ThumbItem *item)
Definition: iconview.cpp:538
static bool LoadDirectory(ThumbList &itemList, const QString &dir, const GalleryFilter &flt, bool recurse, ThumbHash *itemHash, ThumbGenerator *thumbGen)
int getChildCount(const QString &fileName)
Definition: iconview.cpp:1647
MythScreenStack * GetStack(const QString &stackname)
void HandleSelectAll(void)
Definition: iconview.cpp:1375
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
MythScreenStack * GetMainStack()
void HandleShowDevices(void)
Definition: iconview.cpp:1237
MythUIText * m_positionText
Definition: iconview.h:129
MythUIButtonListItem * GetItemAt(int pos) const
int matrix[4][2]
void HandleDeleteCurrent(void)
Definition: iconview.cpp:1057
static MythThemedMenu * menu
ChildCountData * childCountData
Definition: iconview.h:178
void HandleEject(void)
Definition: iconview.cpp:1145
bool Load(bool allowLoadInBackground=true, bool forceStat=false)
Load the image(s), wraps ImageLoader::LoadImage()
void BuildFocusList(void)
MythScreenStack * m_popupStack
Definition: iconview.h:133
static Type kEventType
Definition: mythdialogbox.h:50
bool HandleSubDirEscape(const QString &parent)
Definition: iconview.cpp:685
void SetImage(MythImage *image, const QString &name="")
Sets an image directly, should only be used in special circumstances since it bypasses the cache.
void LoadDirectory(const QString &dir)
Definition: iconview.cpp:230
void HandleSubMenuFilter(void)
Definition: iconview.cpp:977
void addFile(const QString &fileName)
Definition: iconview.cpp:1595
MythUIButtonList * m_imageList
Definition: iconview.h:126
ThumbItem * GetCurrentThumb(void)
Definition: iconview.cpp:1574
bool m_isGallery
Definition: iconview.h:135
virtual void Close()
volatile int m_progress
Definition: iconview.cpp:72
void CopyMarkedFiles(bool move=false)
Definition: iconview.cpp:1512
QString m_galleryDir
Definition: iconview.h:122
static bool CopyMove(const QFileInfo &src, QFileInfo &dst, bool move)
Definition: galleryutil.h:56
FileCopyThread(IconView *parent, bool move)
Definition: iconview.cpp:75
bool Create(void) override
static int run(MythMediaDevice *dev=nullptr, bool startRandomShow=false)
int m_showcaption
Definition: iconview.h:143
virtual void SetVisible(bool visible)
IconView(MythScreenStack *parent, const char *name, const QString &galleryDir, MythMediaDevice *initialDevice)
Definition: iconview.cpp:122
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
static QStringList GetMediaFilter(void)
Definition: galleryutil.cpp:95
QString GetName(void) const
Definition: thumbview.h:55
long GetRotationAngle(void)
Definition: thumbview.cpp:81
GalleryFilter * m_galleryFilter
Definition: iconview.h:124
bool IsDir(void) const
Definition: thumbview.h:62
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:85
bool Create(void) override
MythUIText * m_crumbsText
Definition: iconview.h:128
static bool Delete(const QFileInfo &file)
MythDialogBox * m_menuPopup
Definition: iconview.h:132
IconView * m_parent
Definition: iconview.cpp:71
ChildCountThread * m_childCountThread
Definition: iconview.h:141
bool m_allowImportScripts
Definition: iconview.h:151
static const uint16_t * d
virtual MythRect GetArea(void) const
If the object has a minimum area defined, return it, other wise return the default area.
Definition: mythuitype.cpp:885
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
QString GetSetting(const QString &key, const QString &defaultval="")
void reloadData()
Definition: iconview.cpp:904
static MediaMonitor * GetMediaMonitor(void)
static QString getThumbcacheDir(const QString &inDir)
MythUIText * m_noImagesText
Definition: iconview.h:130
void Reset(void) override
Reset the widget to it's original state, should not reset changes made by the theme.
Definition: mythuitext.cpp:116
bool isRunning(void) const
Definition: mthread.cpp:275
void run() override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
Definition: iconview.cpp:112
QList< MythMediaDevice * > GetMedias(unsigned mediatypes)
Ask for available media.
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
Definition: mythuiutils.h:27
void HandleClearOneMarked(void)
Definition: iconview.cpp:1353
void SetText(const QString &text, const QString &name="", const QString &state="")
void SetAllChecked(MythUIButtonListItem::CheckState state)
void HandleSelectOne(void)
Definition: iconview.cpp:1361
const char * name
Definition: ParseText.cpp:339
void SetImageFilename(const QString &filename)
Definition: thumbview.h:47
void DoDeleteCurrent(bool doDelete)
Definition: iconview.cpp:1072
void Unlock(MythMediaDevice *pMedia)
decrements the MythMediaDevices reference count
uint myth_system(const QString &command, uint flags, uint timeout)
DialogCode exec(void)
int GetProgress(void)
Definition: iconview.cpp:67
int m_sortorder
Definition: iconview.h:144
ImportThread(const QString &cmd)
Definition: iconview.cpp:107
MythMenu * CreateFileMenu(void)
Definition: iconview.cpp:990
void SetPath(const QString &path, bool isDir)
Definition: thumbview.h:45
bool Create() override
void UpdateImage(MythUIButtonListItem *)
Definition: iconview.cpp:421
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
MythUIType * GetFocusWidget(void) const
void ReloadSettings(void)
Definition: iconview.cpp:1113
QHash< QString, ThumbItem * > m_itemHash
Definition: iconview.h:120
void HandleMainMenu(void)
Definition: iconview.cpp:909
void Reset() override
Reset the widget to it's original state, should not reset changes made by the theme.
MythMainWindow * GetMythMainWindow(void)
void run() override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
Definition: iconview.cpp:80
MythUIText * m_captionText
Definition: iconview.h:127
QString m_currDir
Definition: iconview.h:137
QStringList m_itemMarked
Definition: iconview.h:121
void HandleRandomShow(void)
Definition: iconview.cpp:582
QString GetPath(void) const
Definition: thumbview.h:61
static Type kEventType
ThumbData * thumbData
int GetNumSetting(const QString &key, int defaultval=0)
Dialog prompting the user to enter a text string.
QString GetImageFilename(void) const
Definition: thumbview.h:60
bool HandleMediaEscape(MediaMonitor *)
Definition: iconview.cpp:635
void DoDeleteMarked(bool doDelete)
Definition: iconview.cpp:1333
void DoMkDir(QString folderName)
Definition: iconview.cpp:1403
void LoadThumbnail(ThumbItem *item)
Definition: iconview.cpp:299
bool keyPressEvent(QKeyEvent *) override
Key event handler.
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
QStringList m_paths
Definition: iconview.h:147
MythMenu * CreateMarkingMenu(void)
Definition: iconview.cpp:963
bool Create(void) override
bool ValidateAndLock(MythMediaDevice *pMedia)
Validates the MythMediaDevice and increments its reference count.
ThumbGenerator * m_thumbGen
Definition: iconview.h:140
bool GetBoolSetting(const QString &key, bool defaultval=false)
void HandleDeleteMarked(void)
Definition: iconview.cpp:1325
void InitCaption(bool get_caption)
Definition: thumbview.cpp:44
#define LOC
Definition: iconview.cpp:57
void SetRotationAngle(int angle)
Definition: thumbview.cpp:58
void DoRename(QString folderName)
Definition: iconview.cpp:1433
void SetFilename(const QString &filename)
Must be followed by a call to Load() to load the image.
const QString & getMountPath() const
Definition: mythmedia.h:58
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
Definition: mthread.cpp:203
void HandleRotateCCW(void)
Definition: iconview.cpp:1037
void HandleSlideShow(void)
Definition: iconview.cpp:575
bool m_showDevices
Definition: iconview.h:136
void HandleImport(void)
Definition: iconview.cpp:1150
ChildCountThread(QObject *parent)
Definition: iconview.cpp:1584
void ClearSettingsCache(const QString &myKey=QString(""))
bool isMounted(bool bVerify=true)
Tells us if m_DevicePath is a mounted device.
Definition: mythmedia.cpp:363
void SetItemCurrent(MythUIButtonListItem *item)
bool isFinished(void) const
Definition: mthread.cpp:270
QString m_command
Definition: iconview.h:212
bool SetFocusWidget(MythUIType *widget=nullptr)
MythMediaStatus
Definition: mythmedia.h:12
bool m_useOpenGL
Definition: iconview.h:145
MythMediaDevice * m_currDevice
Definition: iconview.h:138
Screen in which all other widgets are contained and rendered.
void HandleMkDir(void)
Definition: iconview.cpp:1388
int GetCurrentPos() const
bool HandleEscape(void)
Definition: iconview.cpp:706
static Type kEventType
Definition: iconview.h:180
QStringList m_fileList
Definition: iconview.h:202
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
Definition: mythdialogbox.h:37
void DisplayState(const QString &state, const QString &name)
QList< ThumbItem * > m_itemList
Definition: iconview.h:119
void HandleRename(void)
Definition: iconview.cpp:1412
MythMenu * CreateMetadataMenu(void)
Definition: iconview.cpp:951
void SetupMediaMonitor(void)
Definition: iconview.cpp:347
static bool is_subdir(const QDir &parent, const QDir &subdir)
Definition: iconview.cpp:676
void setSize(int w, int h)
QString fileName
Definition: iconview.h:167
void setChecked(CheckState state)
void HandleDelete(void)
Definition: iconview.cpp:1317
MythUIButtonListItem * GetItemCurrent() const
MythUIImage * m_selectedImage
Definition: iconview.h:131
bool Create(void) override
bool keyPressEvent(QKeyEvent *) override
Key event handler.
Definition: iconview.cpp:439
void ImportFromDir(const QString &fromDir, const QString &toDir)
Definition: iconview.cpp:1471