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