1 /*
2 * Copyright 2012, 2013 Thomas Schöps
3 * Copyright 2012-2018 Kai Pastor
4 *
5 * This file is part of OpenOrienteering.
6 *
7 * OpenOrienteering is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * OpenOrienteering is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with OpenOrienteering. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21
22 #include "home_screen_widget.h"
23
24 #include <QApplication> // IWYU pragma: keep
25 #include <QAbstractButton>
26 #include <QCheckBox>
27 #include <QCommandLinkButton>
28 #include <QDirIterator>
29 #include <QFileInfo>
30 #include <QLabel>
31 #include <QListWidget>
32 #include <QMessageBox>
33 #include <QPainter>
34 #include <QScroller>
35 #include <QSettings>
36 #include <QVBoxLayout>
37
38 #include "settings.h"
39 #include "core/app_permissions.h"
40 #include "core/storage_location.h" // IWYU pragma: keep
41 #include "fileformats/file_format_registry.h"
42 #include "gui/home_screen_controller.h"
43 #include "gui/main_window.h"
44 #include "gui/settings_dialog.h"
45 #include "gui/util_gui.h"
46
47
48 namespace OpenOrienteering {
49
50 //### AbstractHomeScreenWidget ###
51
AbstractHomeScreenWidget(HomeScreenController * controller,QWidget * parent)52 AbstractHomeScreenWidget::AbstractHomeScreenWidget(HomeScreenController* controller, QWidget* parent)
53 : QWidget(parent),
54 controller(controller)
55 {
56 Q_ASSERT(controller->getWindow());
57 }
58
~AbstractHomeScreenWidget()59 AbstractHomeScreenWidget::~AbstractHomeScreenWidget()
60 {
61 // nothing
62 }
63
makeHeadline(const QString & text,QWidget * parent) const64 QLabel* AbstractHomeScreenWidget::makeHeadline(const QString& text, QWidget* parent) const
65 {
66 QLabel* title_label = new QLabel(text, parent);
67 QFont title_font = title_label->font();
68 int pixel_size = title_font.pixelSize();
69 if (pixel_size > 0)
70 {
71 title_font.setPixelSize(pixel_size * 2);
72 }
73 else
74 {
75 pixel_size = title_font.pointSize();
76 title_font.setPointSize(pixel_size * 2);
77 }
78 title_font.setBold(true);
79 title_label->setFont(title_font);
80 title_label->setAlignment(Qt::AlignLeft | Qt::AlignTop);
81 return title_label;
82 }
83
makeButton(const QString & text,QWidget * parent) const84 QAbstractButton* AbstractHomeScreenWidget::makeButton(const QString& text, QWidget* parent) const
85 {
86 QAbstractButton* button = new QCommandLinkButton(text, parent);
87 QFont button_font = button->font();
88 int pixel_size = button_font.pixelSize();
89 if (pixel_size > 0)
90 {
91 button_font.setPixelSize(pixel_size * 3 / 2);
92 }
93 else
94 {
95 pixel_size = button_font.pointSize();
96 button_font.setPointSize(pixel_size * 3 / 2);
97 }
98 button->setFont(button_font);
99 return button;
100 }
101
makeButton(const QString & text,const QIcon & icon,QWidget * parent) const102 QAbstractButton* AbstractHomeScreenWidget::makeButton(const QString& text, const QIcon& icon, QWidget* parent) const
103 {
104 QAbstractButton* button = makeButton(text, parent);
105 button->setIcon(icon);
106 return button;
107 }
108
109
110
111 //### HomeScreenWidgetDesktop ###
112
HomeScreenWidgetDesktop(HomeScreenController * controller,QWidget * parent)113 HomeScreenWidgetDesktop::HomeScreenWidgetDesktop(HomeScreenController* controller, QWidget* parent)
114 : AbstractHomeScreenWidget(controller, parent)
115 {
116 QLabel* title_label = new QLabel(QString::fromLatin1("<img src=\":/images/title.png\"/>"));
117 title_label->setAlignment(Qt::AlignCenter);
118 QWidget* menu_widget = makeMenuWidget(controller, parent);
119 QWidget* recent_files_widget = makeRecentFilesWidget(controller, parent);
120 QWidget* tips_widget = makeTipsWidget(controller, parent);
121
122 QGridLayout* layout = new QGridLayout();
123 layout->setSpacing(2 * layout->spacing());
124 layout->addWidget(title_label, 0, 0, 1, 2);
125 layout->addWidget(menu_widget, 1, 0, 2, 1);
126 layout->addWidget(recent_files_widget, 1, 1);
127 layout->setRowStretch(1, 4);
128 layout->addWidget(tips_widget, 2, 1);
129 layout->setRowStretch(2, 3);
130 setLayout(layout);
131
132 setAutoFillBackground(false);
133 }
134
~HomeScreenWidgetDesktop()135 HomeScreenWidgetDesktop::~HomeScreenWidgetDesktop()
136 {
137 // nothing
138 }
139
makeMenuWidget(HomeScreenController * controller,QWidget * parent)140 QWidget* HomeScreenWidgetDesktop::makeMenuWidget(HomeScreenController* controller, QWidget* parent)
141 {
142 MainWindow* window = controller->getWindow();
143
144 QVBoxLayout* menu_layout = new QVBoxLayout();
145
146 QLabel* menu_headline = makeHeadline(tr("Activities"));
147 menu_layout->addWidget(menu_headline);
148 QAbstractButton* button_new_map = makeButton(
149 tr("Create a new map ..."), QIcon(QString::fromLatin1(":/images/new.png")));
150 menu_layout->addWidget(button_new_map);
151 QAbstractButton* button_open_map = makeButton(
152 tr("Open map ..."), QIcon(QString::fromLatin1(":/images/open.png")));
153 menu_layout->addWidget(button_open_map);
154
155 menu_layout->addStretch(1);
156
157 auto* button_touch = makeButton(tr("Touch mode"), QIcon{QLatin1String(":/images/tool-touch-cursor.png")});
158 button_touch->setCheckable(true);
159 button_touch->setChecked(Settings::getInstance().touchModeEnabled());
160 menu_layout->addWidget(button_touch);
161 QAbstractButton* button_settings = makeButton(
162 tr("Settings"), QIcon(QString::fromLatin1(":/images/settings.png")));
163 menu_layout->addWidget(button_settings);
164 QAbstractButton* button_about = makeButton(
165 tr("About %1", "As in 'About OpenOrienteering Mapper'").arg(window->appName()), QIcon(QString::fromLatin1(":/images/about.png")));
166 menu_layout->addWidget(button_about);
167 QAbstractButton* button_help = makeButton(
168 tr("Help"), QIcon(QString::fromLatin1(":/images/help.png")));
169 menu_layout->addWidget(button_help);
170 QAbstractButton* button_exit = makeButton(
171 tr("Exit"), QIcon(QString::fromLatin1(":/qt-project.org/styles/commonstyle/images/standardbutton-close-32.png"))); // From Qt5
172 menu_layout->addWidget(button_exit);
173
174 connect(button_new_map, &QAbstractButton::clicked, window, &MainWindow::showNewMapWizard);
175 connect(button_open_map, &QAbstractButton::clicked, window, &MainWindow::showOpenDialog);
176 connect(button_touch, &QAbstractButton::toggled, this, [](bool enabled) { Settings::getInstance().setTouchModeEnabled(enabled); });
177 connect(button_settings, &QAbstractButton::clicked, window, &MainWindow::showSettings);
178 connect(button_about, &QAbstractButton::clicked, window, &MainWindow::showAbout);
179 connect(button_help, &QAbstractButton::clicked, window, &MainWindow::showHelp);
180 connect(button_exit, &QAbstractButton::clicked, qApp, &QApplication::closeAllWindows);
181
182 QWidget* menu_widget = new QWidget(parent);
183 menu_widget->setLayout(menu_layout);
184 menu_widget->setAutoFillBackground(true);
185 return menu_widget;
186 }
187
makeRecentFilesWidget(HomeScreenController * controller,QWidget * parent)188 QWidget* HomeScreenWidgetDesktop::makeRecentFilesWidget(HomeScreenController* controller, QWidget* parent)
189 {
190 QGridLayout* recent_files_layout = new QGridLayout();
191
192 QLabel* recent_files_headline = makeHeadline(tr("Recent maps"));
193 recent_files_layout->addWidget(recent_files_headline, 0, 0, 1, 2);
194
195 recent_files_list = new QListWidget();
196 QFont list_font = recent_files_list->font();
197 int pixel_size = list_font.pixelSize();
198 if (pixel_size > 0)
199 {
200 list_font.setPixelSize(pixel_size * 3 / 2);
201 }
202 else
203 {
204 pixel_size = list_font.pointSize();
205 list_font.setPointSize(pixel_size * 3 / 2);
206 }
207 recent_files_list->setFont(list_font);
208 recent_files_list->setSpacing(pixel_size/2);
209 recent_files_list->setCursor(Qt::PointingHandCursor);
210 recent_files_list->setStyleSheet(QString::fromLatin1(" \
211 QListWidget::item:hover { \
212 color: palette(highlighted-text); \
213 background: palette(highlight); \
214 } "));
215 recent_files_layout->addWidget(recent_files_list, 1, 0, 1, 2);
216
217 open_mru_file_check = new QCheckBox(tr("Open most recently used file on start"));
218 recent_files_layout->addWidget(open_mru_file_check, 2, 0, 1, 1);
219
220 QPushButton* clear_list_button = new QPushButton(tr("Clear list"));
221 recent_files_layout->addWidget(clear_list_button, 2, 1, 1, 1);
222
223 recent_files_layout->setRowStretch(1, 1);
224 recent_files_layout->setColumnStretch(0, 1);
225
226 connect(recent_files_list, &QListWidget::itemClicked, this, &HomeScreenWidgetDesktop::recentFileClicked);
227 connect(open_mru_file_check, &QAbstractButton::clicked, controller, &HomeScreenController::setOpenMRUFile);
228 connect(clear_list_button, &QAbstractButton::clicked, controller, &HomeScreenController::clearRecentFiles);
229
230 QWidget* recent_files_widget = new QWidget(parent);
231 recent_files_widget->setLayout(recent_files_layout);
232 recent_files_widget->setAutoFillBackground(true);
233 return recent_files_widget;
234 }
235
makeTipsWidget(HomeScreenController * controller,QWidget * parent)236 QWidget* HomeScreenWidgetDesktop::makeTipsWidget(HomeScreenController* controller, QWidget* parent)
237 {
238 QGridLayout* tips_layout = new QGridLayout();
239 QWidget* tips_headline = makeHeadline(tr("Tip of the day"));
240 tips_layout->addWidget(tips_headline, 0, 0, 1, 3);
241 tips_label = new QLabel();
242 tips_label->setWordWrap(true);
243 tips_label->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
244 tips_check = new QCheckBox(tr("Show tip of the day"));
245 tips_check->setChecked(true);
246 tips_layout->addWidget(tips_check, 2, 0, 1, 1);
247 tips_layout->addWidget(tips_label, 1, 0, 1, 3);
248 QPushButton* prev_button = new QPushButton(QIcon(QString::fromLatin1(":/images/arrow-left.png")), tr("Previous"));
249 tips_layout->addWidget(prev_button, 2, 1, 1, 1);
250 QPushButton* next_button = new QPushButton(QIcon(QString::fromLatin1(":/images/arrow-right.png")), tr("Next"));
251 tips_layout->addWidget(next_button, 2, 2, 1, 1);
252
253 tips_layout->setRowStretch(1, 1);
254 tips_layout->setColumnStretch(0, 1);
255
256 tips_children.reserve(4);
257 tips_children.push_back(tips_headline);
258 tips_children.push_back(tips_label);
259 tips_children.push_back(prev_button);
260 tips_children.push_back(next_button);
261
262 MainWindow* window = controller->getWindow();
263 connect(tips_label, &QLabel::linkActivated, window, &MainWindow::linkClicked);
264 connect(tips_check, &QAbstractButton::clicked, controller, &HomeScreenController::setTipsVisible);
265 connect(prev_button, &QAbstractButton::clicked, controller, &HomeScreenController::goToPreviousTip);
266 connect(next_button, &QAbstractButton::clicked, controller, &HomeScreenController::goToNextTip);
267
268 QWidget* tips_widget = new QWidget(parent);
269 tips_widget->setLayout(tips_layout);
270 tips_widget->setAutoFillBackground(true);
271 return tips_widget;
272 }
273
setRecentFiles(const QStringList & files)274 void HomeScreenWidgetDesktop::setRecentFiles(const QStringList& files)
275 {
276 recent_files_list->clear();
277 for (auto&& file : files)
278 {
279 QListWidgetItem* new_item = new QListWidgetItem(QFileInfo(file).fileName());
280 new_item->setData(pathRole(), file);
281 new_item->setToolTip(file);
282 recent_files_list->addItem(new_item);
283 }
284 }
285
recentFileClicked(QListWidgetItem * item)286 void HomeScreenWidgetDesktop::recentFileClicked(QListWidgetItem* item)
287 {
288 setEnabled(false);
289 QApplication::processEvents(QEventLoop::ExcludeUserInputEvents, 100 /* ms */);
290 QString path = item->data(pathRole()).toString();
291 controller->getWindow()->openPath(path);
292 setEnabled(true);
293 }
294
paintEvent(QPaintEvent *)295 void HomeScreenWidgetDesktop::paintEvent(QPaintEvent*)
296 {
297 // Background
298 QPainter p(this);
299 p.setPen(Qt::NoPen);
300 p.setBrush(Qt::gray);
301 p.drawRect(rect());
302 }
303
setOpenMRUFileChecked(bool state)304 void HomeScreenWidgetDesktop::setOpenMRUFileChecked(bool state)
305 {
306 open_mru_file_check->setChecked(state);
307 }
308
setTipOfTheDay(const QString & text)309 void HomeScreenWidgetDesktop::setTipOfTheDay(const QString& text)
310 {
311 tips_label->setText(text);
312 }
313
setTipsVisible(bool state)314 void HomeScreenWidgetDesktop::setTipsVisible(bool state)
315 {
316 QGridLayout* layout = qobject_cast<QGridLayout*>(this->layout());
317 for (auto widget : tips_children)
318 {
319 widget->setVisible(state);
320 }
321 if (layout)
322 layout->setRowStretch(2, state ? 3 : 0);
323
324 tips_check->setChecked(state);
325 }
326
327
328
329 //### HomeScreenWidgetMobile ###
330
HomeScreenWidgetMobile(HomeScreenController * controller,QWidget * parent)331 HomeScreenWidgetMobile::HomeScreenWidgetMobile(HomeScreenController* controller, QWidget* parent)
332 : AbstractHomeScreenWidget(controller, parent)
333 {
334 auto* layout = new QVBoxLayout();
335 layout->setSpacing(2 * layout->spacing());
336
337 title_pixmap = QPixmap::fromImage(QImage(QString::fromLatin1(":/images/title.png")));
338 title_label = new QLabel();
339 title_label->setPixmap(title_pixmap);
340 title_label->setAlignment(Qt::AlignCenter);
341 layout->addWidget(title_label);
342
343 file_list_widget = makeFileListWidget();
344 connect(file_list_widget, &QListWidget::itemClicked, this, &HomeScreenWidgetMobile::itemClicked);
345 layout->addWidget(file_list_widget, 1);
346
347 auto settings_button = new QPushButton(HomeScreenWidgetDesktop::tr("Settings"));
348 connect(settings_button, &QPushButton::clicked, controller->getWindow(), &MainWindow::showSettings);
349 QPushButton* help_button = new QPushButton(HomeScreenWidgetDesktop::tr("Help"));
350 connect(help_button, &QPushButton::clicked, controller->getWindow(), &MainWindow::showHelp);
351 QPushButton* about_button = new QPushButton(tr("About Mapper"));
352 connect(about_button, &QPushButton::clicked, controller->getWindow(), &MainWindow::showAbout);
353 QHBoxLayout* buttons_layout = new QHBoxLayout();
354 buttons_layout->setContentsMargins(0, 0, 0, 0);
355 buttons_layout->addWidget(settings_button);
356 buttons_layout->addStretch(1);
357 buttons_layout->addWidget(help_button);
358 buttons_layout->addWidget(about_button);
359 layout->addLayout(buttons_layout);
360
361 setLayout(layout);
362 setAutoFillBackground(false);
363
364 updateFileListWidget();
365 }
366
367 HomeScreenWidgetMobile::~HomeScreenWidgetMobile() = default;
368
369
resizeEvent(QResizeEvent *)370 void HomeScreenWidgetMobile::resizeEvent(QResizeEvent* /*event*/)
371 {
372 adjustTitlePixmapSize();
373 }
374
adjustTitlePixmapSize()375 void HomeScreenWidgetMobile::adjustTitlePixmapSize()
376 {
377 auto label_size = title_label->size();
378 auto scaled_width = qRound(title_pixmap.devicePixelRatio() * label_size.width());
379 if (title_pixmap.width() > scaled_width)
380 {
381 if (title_label->pixmap()->width() != scaled_width)
382 {
383 label_size.setHeight(title_pixmap.height());
384 title_label->setPixmap(title_pixmap.scaled(label_size, Qt::KeepAspectRatio, Qt::SmoothTransformation));
385 }
386 }
387 else if (title_label->pixmap()->width() != title_pixmap.width())
388 {
389 title_label->setPixmap(title_pixmap);
390 }
391 }
392
setRecentFiles(const QStringList &)393 void HomeScreenWidgetMobile::setRecentFiles(const QStringList& /*files*/)
394 {
395 // nothing
396 }
397
setOpenMRUFileChecked(bool)398 void HomeScreenWidgetMobile::setOpenMRUFileChecked(bool /*state*/)
399 {
400 // nothing
401 }
402
setTipOfTheDay(const QString &)403 void HomeScreenWidgetMobile::setTipOfTheDay(const QString& /*text*/)
404 {
405 // nothing
406 }
407
setTipsVisible(bool)408 void HomeScreenWidgetMobile::setTipsVisible(bool /*state*/)
409 {
410 // nothing
411 }
412
showSettings()413 void HomeScreenWidgetMobile::showSettings()
414 {
415 auto window = this->window();
416
417 SettingsDialog dialog(window);
418 dialog.setGeometry(window->geometry());
419 dialog.exec();
420 }
421
itemClicked(QListWidgetItem * item)422 void HomeScreenWidgetMobile::itemClicked(QListWidgetItem* item)
423 {
424 auto file_path = item->data(pathRole()).toString();
425 auto hint = static_cast<StorageLocation::Hint>(item->data(hintRole()).toInt());
426
427 if (file_path == QLatin1String("doc:"))
428 {
429 #ifdef Q_OS_ANDROID
430 Util::showHelp(window(), "android-storage.html");
431 #endif
432 }
433 else if (file_path == QLatin1String(".."))
434 {
435 if (!history.empty())
436 history.pop_back();
437 updateFileListWidget();
438 }
439 else if (hint == StorageLocation::HintNoAccess)
440 {
441 AppPermissions::requestPermission(AppPermissions::StorageAccess, this, &HomeScreenWidgetMobile::permissionRequestDone);
442 }
443 else if (QFileInfo(file_path).isDir())
444 {
445 history.emplace_back(file_path, hint);
446 updateFileListWidget();
447 }
448 else
449 {
450 setEnabled(false);
451 if (hint != StorageLocation::HintNormal)
452 {
453 auto hint_text = StorageLocation::fileHintTextTemplate(hint);
454 QMessageBox::warning(this, ::OpenOrienteering::MainWindow::tr("Warning"), hint_text.arg(item->data(Qt::DisplayRole).toString()));
455 }
456
457 QApplication::processEvents(QEventLoop::ExcludeUserInputEvents, 100 /* ms */);
458 controller->getWindow()->openPath(file_path);
459 setEnabled(true);
460 }
461 }
462
permissionRequestDone()463 void HomeScreenWidgetMobile::permissionRequestDone()
464 {
465 auto* item = file_list_widget->currentItem();
466 if (AppPermissions::checkPermission(AppPermissions::StorageAccess) == AppPermissions::Granted
467 && item != nullptr)
468 {
469 // We only handle permissions for top-level storage locations.
470 auto path = item->data(pathRole()).toString();
471 StorageLocation::refresh();
472 const auto locations = StorageLocation::knownLocations();
473 for (const auto& location : *locations)
474 {
475 if (QFileInfo(location.path()).filePath() == path)
476 {
477 item->setData(hintRole(), location.hint());
478 itemClicked(item);
479 break;
480 }
481 }
482 }
483 }
484
makeFileListWidget()485 QListWidget* HomeScreenWidgetMobile::makeFileListWidget()
486 {
487 file_list_widget = new QListWidget();
488 QScroller::grabGesture(file_list_widget->viewport(), QScroller::TouchGesture);
489 QFont list_font = file_list_widget->font();
490 int pixel_size = list_font.pixelSize();
491 if (pixel_size > 0)
492 {
493 list_font.setPixelSize(pixel_size * 3 / 2);
494 }
495 else
496 {
497 pixel_size = list_font.pointSize();
498 list_font.setPointSize(pixel_size * 3 / 2);
499 }
500 file_list_widget->setFont(list_font);
501 file_list_widget->setSpacing(pixel_size/2);
502 file_list_widget->setCursor(Qt::PointingHandCursor);
503 file_list_widget->setStyleSheet(QString::fromLatin1(" \
504 QListWidget::item:hover { \
505 color: palette(highlighted-text); \
506 background: palette(highlight); \
507 } "));
508
509 return file_list_widget;
510 }
511
updateFileListWidget()512 void HomeScreenWidgetMobile::updateFileListWidget()
513 {
514 file_list_widget->clear();
515
516 if (history.empty())
517 {
518 // First screen.
519 // Recent files first.
520 Settings& settings = Settings::getInstance();
521 auto recent_files = settings.getSetting(Settings::General_RecentFilesList).toStringList();
522 for (auto& file_path : recent_files)
523 {
524 auto file_info = QFileInfo(file_path);
525 if (file_info.exists())
526 addItemToFileList(file_info);
527 }
528
529 #ifdef Q_OS_ANDROID
530 // If there are no recent files, offer a link to the Android storage manual page.
531 if (file_list_widget->count() == 0)
532 {
533 auto* help_item = new QListWidgetItem(tr("Help"));
534 help_item->setData(pathRole(), QLatin1String("doc:"));
535 help_item->setIcon(file_list_widget->style()->standardIcon(QStyle::SP_DialogHelpButton));
536 file_list_widget->addItem(help_item);
537 }
538 #endif
539
540 // Device-specific locations next.
541 // For disambiguation, using the full path for the label.
542 StorageLocation::refresh();
543 const auto locations = StorageLocation::knownLocations();
544 for (const auto& location : *locations)
545 {
546 auto file_info = QFileInfo(location.path());
547 auto icon = file_list_widget->style()->standardIcon(QStyle::SP_DirIcon);
548 addItemToFileList(location.path(), file_info, location.hint(), icon);
549 }
550
551 // Examples last.
552 // The examples path isn't writable, so the hint will be overridden.
553 auto file_info = QFileInfo(QLatin1String("data:/examples"));
554 addItemToFileList(tr("Examples"), file_info);
555 }
556 else
557 {
558 // Backwards navigation on top.
559 auto* parent_item = new QListWidgetItem(QLatin1String(".."));
560 parent_item->setData(pathRole(), QLatin1String(".."));
561 parent_item->setIcon(file_list_widget->style()->standardIcon(QStyle::SP_FileDialogToParent));
562 file_list_widget->addItem(parent_item);
563
564 // Contents of selected location, files first.
565 const auto& location = history.back();
566 QIcon icon;
567 switch (location.hint())
568 {
569 case StorageLocation::HintApplication:
570 icon = file_list_widget->style()->standardIcon(QStyle::SP_MessageBoxInformation);
571 break;
572 case StorageLocation::HintReadOnly:
573 icon = file_list_widget->style()->standardIcon(QStyle::SP_MessageBoxWarning);
574 break;
575 case StorageLocation::HintNormal:
576 case StorageLocation::HintNoAccess:
577 case StorageLocation::HintInvalid:
578 break;
579 }
580
581 constexpr auto filters = QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot;
582 constexpr auto flags = QDir::DirsLast | QDir::Name | QDir::IgnoreCase | QDir::LocaleAware;
583 auto const info_list = QDir(location.path()).entryInfoList(filters, flags);
584 for (const auto& file_info : info_list)
585 {
586 addItemToFileList(file_info, location.hint(), icon);
587 }
588 }
589 }
590
591
addItemToFileList(const QFileInfo & file_info,int hint,const QIcon & icon)592 void HomeScreenWidgetMobile::addItemToFileList(const QFileInfo& file_info, int hint, const QIcon& icon)
593 {
594 addItemToFileList(file_info.fileName(), file_info, hint, icon);
595 }
596
addItemToFileList(const QString & label,const QFileInfo & file_info,int hint,const QIcon & icon)597 void HomeScreenWidgetMobile::addItemToFileList(const QString& label, const QFileInfo& file_info, int hint, const QIcon& icon)
598 {
599 const auto file_path = file_info.filePath();
600 if (hint == StorageLocation::HintNoAccess)
601 {
602 // When there is no access, avoid extra QFileInfo calls.
603 auto* new_item = new QListWidgetItem(label);
604 new_item->setData(pathRole(), file_path);
605 new_item->setData(hintRole(), hint);
606 new_item->setToolTip(StorageLocation::fileHintTextTemplate(StorageLocation::HintNoAccess).arg(file_path));
607 new_item->setIcon(style()->standardIcon(QStyle::SP_MessageBoxQuestion));
608 file_list_widget->addItem(new_item);
609 return;
610 }
611
612 const auto* format = FileFormats.findFormatForFilename(file_path, &FileFormat::supportsReading);
613 if (file_info.isDir() ||
614 (format && format->fileType() == FileFormat::MapFile))
615 {
616 auto* new_item = new QListWidgetItem(label);
617 new_item->setData(pathRole(), file_path);
618 new_item->setData(hintRole(), hint);
619 new_item->setToolTip(file_path);
620 if (file_info.isDir())
621 {
622 // Use dir icon.
623 new_item->setIcon(icon.isNull() ? file_list_widget->style()->standardIcon(QStyle::SP_DirIcon) : icon);
624 }
625 else if (hint == StorageLocation::HintReadOnly
626 || (file_info.isWritable() && format->supportsWriting()))
627 {
628 // Use icon as-is.
629 new_item->setIcon(icon);
630 }
631 else
632 {
633 // Override with read-only warning.
634 new_item->setData(hintRole(), StorageLocation::HintReadOnly);
635 new_item->setIcon(file_list_widget->style()->standardIcon(QStyle::SP_MessageBoxWarning));
636 new_item->setToolTip(StorageLocation::fileHintTextTemplate(StorageLocation::HintReadOnly).arg(file_path));
637 }
638 file_list_widget->addItem(new_item);
639 }
640 }
641
642
643 } // namespace OpenOrienteering
644