MythTV  master
fileselector.cpp
Go to the documentation of this file.
1 #include <cstdlib>
2 
3 // Qt
4 #include <QApplication>
5 #include <QDir>
6 #include <QFileInfo>
7 #include <QVariant>
8 
9 // Myth
10 #include <mythcontext.h>
11 #include <mythdb.h>
12 #include <mythuihelper.h>
13 #include <mythuitext.h>
14 #include <mythuitextedit.h>
15 #include <mythuibutton.h>
16 #include <mythuiimage.h>
17 #include <mythuibuttonlist.h>
18 #include <mythmainwindow.h>
19 #include <mythdialogbox.h>
20 
21 // mytharchive
22 #include "fileselector.h"
23 #include "archiveutil.h"
24 
26 
28 {
29  while (!m_fileData.isEmpty())
30  delete m_fileData.takeFirst();
31 }
32 
34 {
35  // Load the theme for this screen
36  bool foundtheme = LoadWindowFromXML("mytharchive-ui.xml", "file_selector", this);
37  if (!foundtheme)
38  return false;
39 
40  bool err = false;
41  UIUtilW::Assign(this, m_titleText, "title_text");
42  UIUtilE::Assign(this, m_fileButtonList, "filelist", &err);
43  UIUtilE::Assign(this, m_locationEdit, "location_edit", &err);
44  UIUtilE::Assign(this, m_backButton, "back_button", &err);
45  UIUtilE::Assign(this, m_homeButton, "home_button", &err);
46  UIUtilE::Assign(this, m_okButton, "ok_button", &err);
47  UIUtilE::Assign(this, m_cancelButton, "cancel_button", &err);
48 
49  if (err)
50  {
51  LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'file_selector'");
52  return false;
53  }
54 
55  if (m_titleText)
56  {
57  switch (m_selectorType)
58  {
59  case FSTYPE_FILE:
60  m_titleText->SetText(tr("Find File"));
61  break;
62  case FSTYPE_DIRECTORY:
63  m_titleText->SetText(tr("Find Directory"));
64  break;
65  default:
66  m_titleText->SetText(tr("Find Files"));
67  break;
68  }
69  }
70 
71  connect(m_okButton, SIGNAL(Clicked()), this, SLOT(OKPressed()));
72  connect(m_cancelButton, SIGNAL(Clicked()), this, SLOT(cancelPressed()));
73 
74  connect(m_locationEdit, SIGNAL(LosingFocus()),
75  this, SLOT(locationEditLostFocus()));
77 
78  connect(m_backButton, SIGNAL(Clicked()), this, SLOT(backPressed()));
79  connect(m_homeButton, SIGNAL(Clicked()), this, SLOT(homePressed()));
80 
82  this, SLOT(itemClicked(MythUIButtonListItem *)));
83 
85 
87 
90 
91  return true;
92 }
93 
94 bool FileSelector::keyPressEvent(QKeyEvent *event)
95 {
96  if (GetFocusWidget()->keyPressEvent(event))
97  return true;
98 
99  QStringList actions;
100  bool handled = GetMythMainWindow()->TranslateKeyPress("Global", event, actions);
101 
102  for (int i = 0; i < actions.size() && !handled; i++)
103  {
104  QString action = actions[i];
105  handled = true;
106 
107  if (action == "MENU")
108  {
109 
110  }
111  else
112  handled = false;
113  }
114 
115  if (!handled && MythScreenType::keyPressEvent(event))
116  handled = true;
117 
118  return handled;
119 }
120 
122 {
123  if (!item)
124  return;
125 
126  FileData *fileData = item->GetData().value<FileData*>();
127 
128  if (fileData->directory)
129  {
130  if (fileData->filename == "..")
131  {
132  // move up on directory
133  int pos = m_curDirectory.lastIndexOf('/');
134  if (pos > 0)
135  m_curDirectory = m_curDirectory.left(pos);
136  else
137  m_curDirectory = "/";
138  }
139  else
140  {
141  if (!m_curDirectory.endsWith("/"))
142  m_curDirectory += "/";
143  m_curDirectory += fileData->filename;
144  }
145  updateFileList();
146  }
147  else
148  {
150  {
151  QString fullPath = m_curDirectory;
152  if (!fullPath.endsWith("/"))
153  fullPath += "/";
154  fullPath += fileData->filename;
155 
157  {
158  m_selectedList.removeAll(fullPath);
160  }
161  else
162  {
163  if (m_selectedList.indexOf(fullPath) == -1)
164  m_selectedList.append(fullPath);
166  }
167  }
168  }
169 }
170 
172 {
173  return m_curDirectory;
174 }
175 
177 {
179  updateFileList();
180 }
181 
183 {
184  // move up one directory
185  int pos = m_curDirectory.lastIndexOf('/');
186  if (pos > 0)
187  m_curDirectory = m_curDirectory.left(pos);
188  else
189  m_curDirectory = "/";
190 
191  updateFileList();
192 }
193 
195 {
196  char *home = getenv("HOME");
197  m_curDirectory = home;
198 
199  updateFileList();
200 }
201 
203 {
205  {
206  // loop though selected files and add them to the list
207  QString f;
208  ArchiveItem *a;
209 
210  // remove any items that have been removed from the list
211  QList<ArchiveItem *> tempAList;
212  for (int x = 0; x < m_archiveList->size(); x++)
213  {
214  a = m_archiveList->at(x);
215  bool found = false;
216 
217  for (int y = 0; y < m_selectedList.size(); y++)
218  {
219  f = m_selectedList.at(y);
220  if (a->type != "File" || a->filename == f)
221  {
222  found = true;
223  break;
224  }
225  }
226 
227  if (!found)
228  tempAList.append(a);
229  }
230 
231  for (int x = 0; x < tempAList.size(); x++)
232  m_archiveList->removeAll(tempAList.at(x));
233 
234  // remove any items that are already in the list
235  QStringList tempSList;
236  for (int x = 0; x < m_selectedList.size(); x++)
237  {
238  f = m_selectedList.at(x);
239 
240  for (int y = 0; y < m_archiveList->size(); y++)
241  {
242  a = m_archiveList->at(y);
243  if (a->filename == f)
244  {
245  tempSList.append(f);
246  break;
247  }
248  }
249  }
250 
251  for (int x = 0; x < tempSList.size(); x++)
252  m_selectedList.removeAll(tempSList.at(x));
253 
254  // add all that are left
255  for (int x = 0; x < m_selectedList.size(); x++)
256  {
257  f = m_selectedList.at(x);
258 
259  QFile file(f);
260  if (file.exists())
261  {
262  QString title = f;
263  int pos = f.lastIndexOf('/');
264  if (pos > 0)
265  title = f.mid(pos + 1);
266 
267  a = new ArchiveItem;
268  a->type = "File";
269  a->title = title;
270  a->subtitle = "";
271  a->description = "";
272  a->startDate = "";
273  a->startTime = "";
274  a->size = (int64_t)file.size();
275  a->filename = f;
276  a->hasCutlist = false;
277  a->useCutlist = false;
278  a->duration = 0;
279  a->cutDuration = 0;
280  a->videoWidth = 0;
281  a->videoHeight = 0;
282  a->fileCodec = "";
283  a->videoCodec = "";
284  a->encoderProfile = nullptr;
285  a->editedDetails = false;
286  m_archiveList->append(a);
287  }
288  }
289  }
290  else
291  {
293  FileData *fileData = item->GetData().value<FileData*>();
294 
296  {
297  if (!fileData->directory)
298  {
299  ShowOkPopup(tr("The selected item is not a directory!"));
300  return;
301  }
302 
303  if (fileData->filename != "..")
304  {
305  if (!m_curDirectory.endsWith("/"))
306  m_curDirectory += "/";
307  m_curDirectory += fileData->filename;
308  }
309  }
310  else
311  {
312  if (fileData->directory)
313  {
314  if (!m_curDirectory.endsWith("/"))
315  m_curDirectory += "/";
316  }
317  else
318  {
319  if (!m_curDirectory.endsWith("/"))
320  m_curDirectory += "/";
321  m_curDirectory += fileData->filename;
322  }
323  }
324  }
325 
327  emit haveResult(true);
328  else
329  emit haveResult(getSelected());
330  Close();
331 }
332 
334 {
336  emit haveResult(true);
337  else
338  emit haveResult(QString());
339  Close();
340 }
341 
343 {
344  if (!m_archiveList)
345  return;
346 
347  while (!m_selectedList.isEmpty())
348  m_selectedList.takeFirst();
349  m_selectedList.clear();
350 
351  for (int x = 0; x < m_archiveList->size(); x++)
352  {
353  ArchiveItem *a = m_archiveList->at(x);
354  for (int y = 0; y < m_fileData.size(); y++)
355  {
356  FileData *f = m_fileData.at(y);
357  if (f->filename == a->filename)
358  {
359  if (m_selectedList.indexOf(f->filename) == -1)
360  m_selectedList.append(f->filename);
361  break;
362  }
363  }
364  }
365 }
366 
368 {
369  if (!m_fileButtonList)
370  return;
371 
373  while (!m_fileData.isEmpty())
374  delete m_fileData.takeFirst();
375  m_fileData.clear();
376 
377  QDir d;
378 
379  d.setPath(m_curDirectory);
380  if (d.exists())
381  {
382  // first get a list of directory's in the current directory
383  QStringList filters;
384  filters << "*";
385  QFileInfoList list = d.entryInfoList(filters, QDir::Dirs, QDir::Name);
386  QFileInfo fi;
387 
388  for (int x = 0; x < list.size(); x++)
389  {
390  fi = list.at(x);
391  if (fi.fileName() != ".")
392  {
393  FileData *data = new FileData;
394  data->selected = false;
395  data->directory = true;
396  data->filename = fi.fileName();
397  data->size = 0;
398  m_fileData.append(data);
399 
400  // add a row to the MythUIButtonList
401  MythUIButtonListItem* item = new
403  item->setCheckable(false);
404  item->SetImage("ma_folder.png");
405  item->SetData(qVariantFromValue(data));
406  }
407  }
408 
410  {
411  // second get a list of file's in the current directory
412  filters.clear();
413  filters = m_filemask.split(" ", QString::SkipEmptyParts);
414  list = d.entryInfoList(filters, QDir::Files, QDir::Name);
415  for (int x = 0; x < list.size(); x++)
416  {
417  fi = list.at(x);
418  FileData *data = new FileData;
419  data->selected = false;
420  data->directory = false;
421  data->filename = fi.fileName();
422  data->size = fi.size();
423  m_fileData.append(data);
424 
425  // add a row to the UIListBtnArea
426  MythUIButtonListItem* item =
428  item->SetText(formatSize(data->size / 1024, 2), "size");
429 
431  {
432  item->setCheckable(true);
433 
434  QString fullPath = m_curDirectory;
435  if (!fullPath.endsWith("/"))
436  fullPath += "/";
437  fullPath += data->filename;
438 
439  if (m_selectedList.indexOf(fullPath) != -1)
440  {
442  }
443  else
444  {
446  }
447  }
448  else
449  item->setCheckable(false);
450 
451  item->SetData(qVariantFromValue(data));
452  }
453  }
455  }
456  else
457  {
458  m_locationEdit->SetText("/");
459  LOG(VB_GENERAL, LOG_ERR,
460  "MythArchive: current directory does not exist!");
461  }
462 }
QList< FileData * > m_fileData
Definition: fileselector.h:79
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 LosingFocus()
MythConfirmationDialog * ShowOkPopup(const QString &message, QObject *parent, const char *slot, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
MythUIText * m_titleText
Definition: fileselector.h:85
void cancelPressed(void)
void SetData(QVariant data)
MythUIButton * m_okButton
Definition: fileselector.h:88
bool hasCutlist
Definition: archiveutil.h:69
bool selected
Definition: fileselector.h:20
bool useCutlist
Definition: archiveutil.h:70
virtual void SetText(const QString &text)
Definition: mythuitext.cpp:136
void backPressed(void)
int videoWidth
Definition: archiveutil.h:68
void updateFileList(void)
QString m_curDirectory
Definition: fileselector.h:78
bool Create(void) override
void BuildFocusList(void)
MythUIButton * m_homeButton
Definition: fileselector.h:91
void SetImage(MythImage *image, const QString &name="")
Sets an image directly, should only be used in special circumstances since it bypasses the cache.
QString startTime
Definition: archiveutil.h:59
QString filename
Definition: archiveutil.h:60
virtual void Close()
void setCheckable(bool flag)
void updateSelectedList(void)
MythUIButton * m_cancelButton
Definition: fileselector.h:89
static const uint16_t * d
MythUIButtonList * m_fileButtonList
Definition: fileselector.h:86
QString fileCodec
Definition: archiveutil.h:66
bool editedDetails
Definition: archiveutil.h:71
int cutDuration
Definition: archiveutil.h:64
FSTYPE m_selectorType
Definition: fileselector.h:76
int64_t size
Definition: fileselector.h:22
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
Definition: mythuiutils.h:27
void SetText(const QString &text, const QString &name="", const QString &state="")
void homePressed(void)
bool directory
Definition: fileselector.h:19
CheckState state() const
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
void SetText(const QString &text, bool moveCursor=true)
MythUIType * GetFocusWidget(void) const
QString type
Definition: archiveutil.h:54
void Reset() override
Reset the widget to it's original state, should not reset changes made by the theme.
MythMainWindow * GetMythMainWindow(void)
QString filename
Definition: fileselector.h:21
QString subtitle
Definition: archiveutil.h:56
static QString formatSize(int64_t sizeKB, int prec)
QString videoCodec
Definition: archiveutil.h:67
QStringList m_selectedList
Definition: fileselector.h:80
bool keyPressEvent(QKeyEvent *) override
Key event handler.
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
QString startDate
Definition: archiveutil.h:58
QString title
Definition: archiveutil.h:55
bool keyPressEvent(QKeyEvent *e) override
Key event handler.
QList< ArchiveItem * > * m_archiveList
Definition: fileselector.h:81
MythUIButton * m_backButton
Definition: fileselector.h:90
EncoderProfile * encoderProfile
Definition: archiveutil.h:65
void OKPressed(void)
int videoHeight
Definition: archiveutil.h:68
QString description
Definition: archiveutil.h:57
QString getSelected(void)
bool SetFocusWidget(MythUIType *widget=nullptr)
int64_t size
Definition: archiveutil.h:61
void itemClicked(MythUIButtonListItem *item)
void haveResult(bool ok)
void setChecked(CheckState state)
void locationEditLostFocus(void)
QString m_filemask
Definition: fileselector.h:77
QString GetText(void) const
MythUIButtonListItem * GetItemCurrent() const
MythUITextEdit * m_locationEdit
Definition: fileselector.h:87