From 5c33bf473e6b6e9165d1bb2788bd88216c438b80 Mon Sep 17 00:00:00 2001
From: SeeLook <945374+SeeLook@users.noreply.github.com>
Date: Sun, 1 Nov 2015 20:40:41 +0100
Subject: [PATCH] New TfileDialog for Mobile and calling it selector, creator
 and starter.

---
 TODO                                   |   2 -
 src/exam/tstartexamdlg.cpp             |   2 +-
 src/libs/core/level/tlevelselector.cpp |  34 +--
 src/libs/core/widgets/tfiledialog.cpp  | 369 +++++++++++++++++++------
 src/libs/core/widgets/tfiledialog.h    |  84 ++++--
 src/plugins/level/tlevelcreatordlg.cpp |  29 +-
 6 files changed, 378 insertions(+), 142 deletions(-)

diff --git a/TODO b/TODO
index 13cf1455d..e0e4bebc9 100644
--- a/TODO
+++ b/TODO
@@ -17,8 +17,6 @@ waring - merge with stable
 
 ANDROID:
 - crash when audio out was disables and enabled again in settings (audio in probably also)
-- keep extra dialogues maximized (file, color dialog)
-    or create special ones for mobile
 - add 'smallest font size' to Tmtr ???
 - add labels with smallest font under level cretor options instead of status tips
 - solve issue with restart for settings reset
diff --git a/src/exam/tstartexamdlg.cpp b/src/exam/tstartexamdlg.cpp
index 88127ca0b..d33efa8c0 100644
--- a/src/exam/tstartexamdlg.cpp
+++ b/src/exam/tstartexamdlg.cpp
@@ -318,7 +318,7 @@ void TstartExamDlg::continuePrevExam() {
 
 void TstartExamDlg::examFromFileDialog() {
 #if defined (Q_OS_ANDROID)
-  QString fileName = TfileDialog::getOpenFileName(this, TexTrans::loadExamFileTxt(), m_examParams->examsDir, TexTrans::examFilterTxt());
+  QString fileName = TfileDialog::getOpenFileName(this, m_examParams->examsDir, QStringLiteral("noo"));
 #else
   QString fileName = QFileDialog::getOpenFileName(this, TexTrans::loadExamFileTxt(), m_examParams->examsDir, TexTrans::examFilterTxt());
 #endif
diff --git a/src/libs/core/level/tlevelselector.cpp b/src/libs/core/level/tlevelselector.cpp
index 9ceb647bd..557dd358d 100644
--- a/src/libs/core/level/tlevelselector.cpp
+++ b/src/libs/core/level/tlevelselector.cpp
@@ -37,7 +37,7 @@
 /*static*/
 
 QString TlevelSelector::checkLevel(Tlevel& l) {
-	QString warringText = "";
+	QString warringText;
 	if (Tcore::gl()->instrument == e_noInstrument && l.instrument != e_noInstrument)
 					warringText = tr("Level is not suitable for current instrument type");
 	else if (l.canBeGuitar() || (l.instrument != e_noInstrument && l.canBeSound())) {
@@ -102,8 +102,8 @@ TlevelSelector::TlevelSelector(QWidget *parent) :
 	mainLay->addWidget(m_levelPreview);
 	setLayout(mainLay);
 
-	m_fakeLevel.name = "";
-	m_fakeLevel.desc = "";
+	m_fakeLevel.name.clear();
+	m_fakeLevel.desc.clear();
 	findLevels();
 
 	connect(m_levelsListWdg, SIGNAL(currentRowChanged(int)), this, SLOT(levelSelected(int)));
@@ -125,7 +125,7 @@ TlevelSelector::~TlevelSelector() {
 void TlevelSelector::levelSelected(int id) {
 	if (id >= 0 && id < m_levelsListWdg->count()) {
     m_levelPreview->setLevel(m_levels[id].level);
-		if (m_levels[id].file == "")
+		if (m_levels[id].file.isEmpty())
 				m_removeButt->setDisabled(true);
 		else
 				m_removeButt->setDisabled(false);
@@ -153,7 +153,7 @@ void TlevelSelector::findLevels() {
       QFile file(recentLevels[i]);
       if (file.exists()) {
           Tlevel level = getLevelFromFile(file);
-          if (level.name != "") {
+          if (!level.name.isEmpty()) {
               addLevel(level, file.fileName());
               m_levels.last().suitable = isSuitable(level);
           } else
@@ -166,7 +166,7 @@ void TlevelSelector::findLevels() {
 
 
 void TlevelSelector::addLevel(const Tlevel& lev, QString levelFile, bool check) {
-  if (check && levelFile != "") {
+  if (check && !levelFile.isEmpty()) {
     int pos = -1;
     for (int i = 0; i < m_levels.size(); i++)
       if (m_levels[i].file == levelFile) // file and level exist
@@ -194,7 +194,7 @@ void TlevelSelector::addLevel(const Tlevel& lev, QString levelFile, bool check)
 
 bool TlevelSelector::isSuitable(Tlevel &l) {
 	QString warringText = checkLevel(l);
-	if (warringText != "") {
+	if (!warringText.isEmpty()) {
 			m_levels.last().item->setStatusTip("<span style=\"color: red;\">" + warringText + "</span>");
 			m_levels.last().item->setForeground(QBrush(Qt::red));
 			return false;
@@ -234,13 +234,13 @@ void TlevelSelector::selectLevel() {
 void TlevelSelector::loadFromFile(QString levelFile) {
   if (levelFile.isEmpty())
 #if defined (Q_OS_ANDROID)
-    levelFile = TfileDialog::getOpenFileName(this, tr("Load exam's level"), Tcore::gl()->E->levelsDir, levelFilterTxt() + " (*.nel)");
+    levelFile = TfileDialog::getOpenFileName(this, Tcore::gl()->E->levelsDir, QStringLiteral("nel"));
 #else
     levelFile = QFileDialog::getOpenFileName(this, tr("Load exam's level"), Tcore::gl()->E->levelsDir, levelFilterTxt() + " (*.nel)");
 #endif
   QFile file(levelFile);
   Tlevel level = getLevelFromFile(file);
-  if (level.name != "") {
+  if (!level.name.isEmpty()) {
       Tcore::gl()->E->levelsDir = QFileInfo(levelFile).absoluteDir().absolutePath();
       addLevel(level, levelFile, true);
       if (isSuitable(level))
@@ -261,7 +261,7 @@ Tlevel& TlevelSelector::getSelectedLevel() {
 void TlevelSelector::updateRecentLevels() {
 	QStringList recentLevels;
 	for (int i = m_levels.size() - 1; i > 1; i--) {
-		if (m_levels[i].file != "")
+		if (!m_levels[i].file.isEmpty())
 			recentLevels << m_levels[i].file;
 	}
 	Tcore::gl()->config->setValue("recentLevels", recentLevels);
@@ -280,7 +280,7 @@ void TlevelSelector::loadFromFilePrivate() {
 
 Tlevel TlevelSelector::getLevelFromFile(QFile &file) {
     Tlevel level;
-    level.name = "";
+    level.name.clear();;
     if (file.open(QIODevice::ReadOnly)) {
          QDataStream in(&file);
          in.setVersion(QDataStream::Qt_5_2);
@@ -310,13 +310,13 @@ Tlevel TlevelSelector::getLevelFromFile(QFile &file) {
 							wasLevelFile = false;
 				 file.close();
 				 if (!wasLevelFile) {
-						QMessageBox::critical(this, "", tr("File: %1 \n is not Nootka level file!").arg(file.fileName()));
-						level.name = "";
+						QMessageBox::critical(this, QString(), tr("File: %1 \n is not Nootka level file!").arg(file.fileName()));
+						level.name.clear();
 						return level;
 				 } else if (!wasLevelValid)
-             QMessageBox::warning(0, "", tr("Level file\n %1 \n was corrupted and repaired!\n Check please, if its parameters are as expected.").arg(file.fileName()));
+             QMessageBox::warning(0, QString(), tr("Level file\n %1 \n was corrupted and repaired!\n Check please, if its parameters are as expected.").arg(file.fileName()));
     } else {
-				if (file.fileName() != "") // skip empty file names (ignored by user)
+				if (!file.fileName().isEmpty()) // skip empty file names (ignored by user)
 					Tlevel::fileIOerrorMsg(file, this);
     }
     return level;
@@ -360,10 +360,10 @@ TremoveLevel::TremoveLevel(const QString& levelName, const QString& fileName, QW
 	QDialog(parent, Qt::CustomizeWindowHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint),
 	m_levelFile(fileName)
 {
-		setWindowTitle(removeTxt().replace("<b>", "").replace("</b>", ""));
+		setWindowTitle(removeTxt().replace("<b>", QString()).replace("</b>", QString()));
 		QLabel *removeLab = new QLabel(removeTxt(levelName), this);
 		m_deleteChB = new QCheckBox(tr("Also delete level file:"), this);
-		QLabel *fNameLab = new QLabel("<b>" + fileName + "</b>", this);
+		QLabel *fNameLab = new QLabel(QLatin1String("<b>") + fileName + QLatin1String("</b>"), this);
 		
 		QDialogButtonBox *stdButtons = new QDialogButtonBox(this);
 		QPushButton *removeButton = stdButtons->addButton(tr("Remove"), QDialogButtonBox::AcceptRole);
diff --git a/src/libs/core/widgets/tfiledialog.cpp b/src/libs/core/widgets/tfiledialog.cpp
index 02aa17d6f..e47505a65 100644
--- a/src/libs/core/widgets/tfiledialog.cpp
+++ b/src/libs/core/widgets/tfiledialog.cpp
@@ -1,112 +1,311 @@
-/***************************************************************************
- *   Copyright (C) 2015 by Tomasz Bojczuk                                  *
- *   tomaszbojczuk@gmail.com                                               *
- *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 3 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program is distributed in the hope that it will be useful,       *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
- *   GNU General Public License for more details.                          *
- *                                                                         *
- *  You should have received a copy of the GNU General Public License      *
- *  along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
- ***************************************************************************/
+
 
 #include "tfiledialog.h"
+#include "tmtr.h"
+#include <tpath.h>
 #include <QtWidgets/QtWidgets>
 
 
+class TiconProvider : public QFileIconProvider
+{
+
+public:
+
+  TiconProvider(QFileIconProvider *realProv) :
+    QFileIconProvider(),
+    m_realProvider(realProv)
+  {
+  }
+
+  virtual QIcon icon(const QFileInfo& info) const {
+    if (info.isDir())
+      return qApp->style()->standardIcon(QStyle::SP_DirIcon);
+    else if (info.suffix().contains(QLatin1String("nel")))
+      return QIcon(Tpath::img("nootka-level"));
+    else if (info.suffix().contains(QLatin1String("noo")))
+      return QIcon(Tpath::img("nootka-exam"));
+    else
+      return m_realProvider->icon(info);
+  }
+
+  virtual QIcon icon(IconType type) const {
+    switch (type) {
+      case Folder:
+        return qApp->style()->standardIcon(QStyle::SP_DirIcon);
+      default:
+        return qApp->style()->standardIcon(QStyle::SP_FileIcon);
+    }
+  }
+
+private:
+  QFileIconProvider           *m_realProvider;
+};
+
+
+class TnewDirMessage : public QDialog
+{
+
+public:
+  explicit TnewDirMessage(QWidget* parent = 0) :
+    QDialog(parent)
+  {
+    auto label = new QLabel(QApplication::translate("QFileDialog", "Create New Folder"), this);
+    m_edit = new QLineEdit(this);
+    m_edit->setPlaceholderText(QApplication::translate("QFileDialog", "Directory:"));
+    auto box = new QDialogButtonBox(this);
+    auto okButt = box->addButton(QDialogButtonBox::Ok);
+    okButt->setIcon(style()->standardIcon(QStyle::QStyle::SP_FileDialogNewFolder));
+    auto cancelButt = box->addButton(QDialogButtonBox::Cancel);
+    cancelButt->setIcon(style()->standardIcon(QStyle::SP_DialogCancelButton));
+
+    auto lay = new QVBoxLayout;
+    lay->addWidget(label);
+    lay->addWidget(m_edit);
+    lay->addWidget(box);
+    setLayout(lay);
+
+    connect(box, &QDialogButtonBox::accepted, this, &QDialog::accept);
+    connect(box, &QDialogButtonBox::rejected, this, &QDialog::reject);
+  }
+
+  QString getName() { return m_edit->text(); }
+
+  static QString dirName(QWidget* parent = 0) {
+    TnewDirMessage newDir(parent);
+    if (newDir.exec() == Accepted && !newDir.getName().isEmpty())
+      return newDir.getName();
+    else
+      return QString();
+  }
+
+private:
+  QLineEdit           *m_edit;
+};
+
+
+
 /* static */
-QString TfileDialog::getSaveFileName(QWidget* parent, const QString& caption, const QString& directory, const QString& filter) {
-  TfileDialog saveDialog(parent, caption, directory, filter);
-  saveDialog.setAcceptMode(AcceptSave);
-  if (saveDialog.exec() == QDialog::Accepted)
-    return saveDialog.selectedFiles().first();
+QString TfileDialog::getOpenFileName(QWidget* parent, const QString& directory, const QString& filter) {
+  TfileDialog openDialog(parent, directory, filter, TfileDialog::e_acceptOpen);
+  if (openDialog.exec() == QFileDialog::Accepted)
+    return openDialog.selectedFile();
   else
     return QString();
 }
 
 
-QString TfileDialog::getOpenFileName(QWidget* parent, const QString& caption, const QString& directory, const QString& filter) {
-  TfileDialog openDialog(parent, caption, directory, filter);
-  openDialog.setAcceptMode(AcceptOpen);
-  if (openDialog.exec() == QDialog::Accepted)
-    return openDialog.selectedFiles().first();
+QString TfileDialog::getSaveFileName(QWidget* parent, const QString& directory, const QString& filter) {
+  TfileDialog saveDialog(parent, directory, filter, TfileDialog::e_acceptSave);
+  if (saveDialog.exec() == QFileDialog::Accepted)
+    return saveDialog.selectedFile();
   else
     return QString();
 }
 
 
-
-TfileDialog::TfileDialog(QWidget* parent, const QString& caption, const QString& directory, const QString& filter) :
-  QFileDialog(parent, caption, directory, filter)
+//#################################################################################################
+//#################################################################################################
+//###################           class TfileDialog      ############################################
+//#################################################################################################
+//#################################################################################################
+TfileDialog::TfileDialog(QWidget *parent, const QString& directory, const QString& filter, EacceptMode mode) :
+  QDialog(parent),
+  m_acceptMode(mode)
 {
-//   setFileMode(QFileDialog::AnyFile);
-//   setOption(QFileDialog::DontUseNativeDialog);
-//   setOption(QFileDialog::HideNameFilterDetails);
-//   setOption(QFileDialog::DontUseCustomDirectoryIcons);
-
-#if defined (Q_OS_ANDROID)
   showMaximized();
-  layout()->setContentsMargins(0, 0, 0, 0);
-#endif
-
-  foreach(QAbstractScrollArea *a, findChildren<QAbstractScrollArea*>()) {
-//     qDebug() << "scrolls" << a->objectName();
-    a->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
-    a->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
-      QScroller::grabGesture(a->viewport(), QScroller::LeftMouseButtonGesture);
+
+  m_menu = new QListWidget(this);
+  m_menu->setIconSize(QSize(60, 60));
+  m_menu->setMaximumWidth(80);
+  m_menu->setViewMode(QListView::IconMode);
+  m_menu->setMovement(QListView::Static);
+  m_menu->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+  m_menu->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+  int bSize = qBound<int>(Tmtr::fingerPixels() * 1.1, Tmtr::longScreenSide() / 12, Tmtr::fingerPixels() * 1.6);
+  m_menu->setIconSize(QSize(bSize, bSize));
+  m_menu->setMaximumWidth(bSize + 10);
+  QFont f = font();
+  f.setPixelSize(qMin<int>(bSize / 5, fontMetrics().height()));
+  m_menu->setFont(f);
+//   m_menu->setObjectName("fileMenu"); // revert colors
+//   m_menu->setStyleSheet(m_menu->styleSheet() + " QListWidget#fileMenu { background: palette(text); color: palette(base); }");
+  QScroller::grabGesture(m_menu->viewport(), QScroller::LeftMouseButtonGesture);
+
+  if (mode == e_acceptSave)
+    m_acceptItem = addMenuItem(style()->standardIcon(QStyle::SP_DialogSaveButton), QApplication::translate("QShortcut", "Save"));
+  else
+    m_acceptItem = addMenuItem(style()->standardIcon(QStyle::SP_DialogOpenButton), QApplication::translate("QShortcut", "Open"));
+
+  m_dirUpItem = addMenuItem(style()->standardIcon(QStyle::SP_ArrowUp));
+  m_newDirItem = addMenuItem(style()->standardIcon(QStyle::QStyle::SP_FileDialogNewFolder));
+  m_cancelItem = addMenuItem(style()->standardIcon(QStyle::QStyle::SP_DialogCloseButton), QApplication::translate("QShortcut", "Close"));
+
+  m_locationLab = new QLabel(this);
+  m_locationLab->setAlignment(Qt::AlignRight);
+  m_locationLab->setFixedWidth(Tmtr::longScreenSide() / 3);
+
+  m_editName = new QLineEdit(this);
+  m_editName->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);;
+  if (mode == e_acceptOpen)
+    m_editName->setReadOnly(true);
+
+  m_extensionCombo = new QComboBox(this);
+  m_list = new QListView(this);
+  int is = style()->pixelMetric(QStyle::PM_SmallIconSize) * 1.1;
+  m_list->setIconSize(QSize(is, is));
+  m_list->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
+  m_list->setSelectionBehavior(QAbstractItemView::SelectItems);
+  m_list->setSelectionMode(QAbstractItemView::SingleSelection);
+  m_list->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+  m_list->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+  QScroller::grabGesture(m_list->viewport(), QScroller::LeftMouseButtonGesture);
+
+  m_lay = new QBoxLayout(QBoxLayout::LeftToRight);
+  m_lay->addWidget(m_menu);
+    auto innLay = new QVBoxLayout;
+    auto fileLay = new QHBoxLayout;
+      fileLay->addWidget(m_locationLab);
+      fileLay->addWidget(m_editName);
+      fileLay->addWidget(m_extensionCombo);
+    innLay->addLayout(fileLay);
+    innLay->addWidget(m_list);
+  m_lay->addLayout(innLay);
+  setLayout(m_lay);
+  m_lay->setContentsMargins(0, m_lay->contentsMargins().top(), m_lay->contentsMargins().right(), 0);
+
+  m_fileModel = new QFileSystemModel(this);
+
+  QFileInfo fi(directory);
+  if (fi.isDir())
+    m_fileModel->setRootPath(directory);
+  else {
+    m_fileModel->setRootPath(fi.absolutePath());
+    m_editName->setText(fi.fileName());
+  }
+  updateLocationLabel();
+
+  QStringList filters = filter.split(QLatin1String("|"));
+  if (filters.size()) {
+    for(int i = 0; i < filters.size(); ++i) {
+      filters[i].prepend(QLatin1String("."));
+      m_extensionCombo->addItem(filters[i]);
+      filters[i].prepend(QLatin1String("*"));
+    }
+    m_extensionCombo->setCurrentIndex(0);
+    m_fileModel->setNameFilters(filters);
+    m_fileModel->setNameFilterDisables(false);
   }
 
-  foreach(QWidget *w, findChildren<QWidget*>()) {
-//     qDebug() << "widgets" << w->objectName();
-    if (w->objectName() == QLatin1String("sidebar"))
-      w->hide();
-//     else if (w->objectName() == QLatin1String("lookInLabel"))
-//       w->hide();
-//     else if (w->objectName() == QLatin1String("lookInCombo"))
-//       w->hide();
-    else if (w->objectName() == QLatin1String("listModeButton"))
-      w->hide();
-    else if (w->objectName() == QLatin1String("detailModeButton"))
-      w->hide();
-    else if (w->objectName() == QLatin1String("fileTypeCombo"))
-      w->hide();
-    else if (w->objectName() == QLatin1String("fileTypeLabel"))
-      w->hide();
-    else if (w->objectName() == QLatin1String("fileTypeLabel"))
-      w->hide();
+  m_list->setModel(m_fileModel);
+  m_list->setRootIndex(m_fileModel->index(m_fileModel->rootPath()));
+
+  m_fileModel->setIconProvider(new TiconProvider(m_fileModel->iconProvider()));
+
+  connect(m_menu, &QListWidget::itemClicked, this, &TfileDialog::menuClickedSlot);
+  connect(m_list, &QListView::clicked, this, &TfileDialog::itemClickedSlot);
+}
+
+
+TfileDialog::~TfileDialog()
+{
+  delete m_fileModel;
+}
+
+
+//#################################################################################################
+//###################              PROTECTED           ############################################
+//#################################################################################################
+
+void TfileDialog::itemClickedSlot(const QModelIndex& index) {
+  if (m_fileModel->isDir(index)) {
+      m_list->setRootIndex(index);
+      m_fileModel->setRootPath(m_fileModel->filePath(index));
+      updateLocationLabel();
+      if (acceptMode() == e_acceptOpen) {
+        m_editName->setText(QString());
+        m_selectedFile.clear(); // reset previously selected file
+      }
+  } else {
+      m_selectedFile = m_fileModel->fileInfo(index).absoluteFilePath();
+      m_editName->setText(QFileInfo(m_selectedFile).fileName());
   }
+}
 
-  foreach(QPushButton *b, findChildren<QPushButton*>()) {
-//     qDebug() << "buttons" << b->objectName();
-    QSize iSize(style()->pixelMetric(QStyle::PM_SmallIconSize), style()->pixelMetric(QStyle::PM_SmallIconSize));
-    if (b->objectName() == QLatin1String("backButton"))
-      b->setIconSize(iSize);
-    else if (b->objectName() == QLatin1String("forwardButton"))
-      b->setIconSize(iSize);
-    else if (b->objectName() == QLatin1String("toParentButton"))
-      b->setIconSize(iSize);
-    else if (b->objectName() == QLatin1String("newFolderButton"))
-      b->setIconSize(iSize);
+
+void TfileDialog::performAction() {
+  if (acceptMode() == e_acceptSave) {
+    if (m_editName->text().isEmpty()) {
+        QMessageBox::warning(this, QString(), QApplication::translate("QFileSystemModel", "Invalid filename"));
+        return;
+    } else {
+      m_selectedFile = m_fileModel->rootPath() + QLatin1String("/") + m_editName->text();
+      QFileInfo fi(m_selectedFile);
+      bool addExt = false; // Add current file extension
+      if (!fi.suffix().isEmpty()) {
+        if (m_extensionCombo->currentIndex() > -1 && m_extensionCombo->currentText() != m_selectedFile.right(4))
+            addExt = true;
+      } else
+          addExt = true;
+      if (addExt) {
+        m_selectedFile.append(m_extensionCombo->currentText());
+        fi.setFile(m_selectedFile);
+      }
+      if (fi.exists()) {
+        if (QMessageBox::question(this, QString(),
+            QApplication::translate("QFileDialog", "%1 already exists.\nDo you want to replace it?").arg(m_selectedFile)) != QMessageBox::Ok) {
+                m_selectedFile.clear();
+                return;
+        }
+      }
+    }
   }
+  QDialog::accept();
+}
+
+
+void TfileDialog::menuClickedSlot(QListWidgetItem* item) {
+  if (item == m_cancelItem)
+    reject();
+  else if (item == m_acceptItem)
+    performAction();
+  else if (item == m_dirUpItem)
+    dirUpSlot();
+  else if (item == m_newDirItem)
+    newDirSlot();
+}
+
 
-  foreach(QListView *l, findChildren<QListView*>()) {
-//     qDebug() << "lists" << l->objectName();
-//     if (l->objectName() == QLatin1String("listView")) {
-      l->setFlow(QListView::TopToBottom);
-      l->setDragDropMode(QAbstractItemView::NoDragDrop);
-      l->setDragEnabled(false);
-//       l->setIconSize(QSize(48, 48));
-//       auto model = qobject_cast<QFileSystemModel*>(l->model());
-//       qDebug() << l->model()->columnCount() << model->iconProvider();
-//       model->setIconProvider(saveDialog.iconProvider());
-//       model->removeColumns(1, 10);
-//     }
+void TfileDialog::dirUpSlot() {
+  QDir dir(m_fileModel->rootDirectory());
+  if (dir.cdUp()) {
+    m_fileModel->setRootPath(dir.absolutePath());
+    m_list->setRootIndex(m_fileModel->index(dir.absolutePath()));
+    updateLocationLabel();
   }
+}
+
 
+void TfileDialog::newDirSlot() {
+  QString newDir = TnewDirMessage::dirName(this);
+  if (!newDir.isEmpty())
+    m_fileModel->mkdir(m_list->rootIndex(), newDir);
 }
+
+
+QListWidgetItem* TfileDialog::addMenuItem(const QIcon& icon, const QString& text) {
+  QListWidgetItem *menuButton = new QListWidgetItem(m_menu);
+  menuButton->setIcon(icon);
+  if (!text.isEmpty())
+    menuButton->setText(text);
+  menuButton->setTextAlignment(Qt::AlignHCenter);
+  menuButton->setFlags(Qt::ItemIsEnabled | Qt::ItemNeverHasChildren);
+  return menuButton;
+}
+
+
+void TfileDialog::updateLocationLabel() {
+  m_locationLab->setText(fontMetrics().elidedText(m_fileModel->rootPath() + QLatin1String("/"),
+                                                  Qt::ElideMiddle, m_locationLab->width(), Qt::TextShowMnemonic));
+}
+
+
diff --git a/src/libs/core/widgets/tfiledialog.h b/src/libs/core/widgets/tfiledialog.h
index 308c779ab..2a99efb95 100644
--- a/src/libs/core/widgets/tfiledialog.h
+++ b/src/libs/core/widgets/tfiledialog.h
@@ -1,37 +1,73 @@
-/***************************************************************************
- *   Copyright (C) 2015 by Tomasz Bojczuk                                  *
- *   tomaszbojczuk@gmail.com                                               *
- *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 3 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program is distributed in the hope that it will be useful,       *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
- *   GNU General Public License for more details.                          *
- *                                                                         *
- *  You should have received a copy of the GNU General Public License      *
- *  along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
- ***************************************************************************/
-
 #ifndef TFILEDIALOG_H
 #define TFILEDIALOG_H
 
-#include <QtWidgets/qfiledialog.h>
+#include <QtWidgets/qdialog.h>
+#include <QtWidgets/qfilesystemmodel.h>
+#include <QtWidgets/qboxlayout.h>
+
+
+class QListWidget;
+class QListWidgetItem;
+class QListView;
+class QLineEdit;
+class QLabel;
+class QComboBox;
 
 
 /**
- *
+ * Implementation of file dialog for mobile devices.
+ * It is far from ideal but much better than native QFileDialog.
+ * It has two static methods @p getOpenFileName and @p getSaveFileName
+ * with three parameters (in contrary to native there is no caption).
+ * Third @param filter may support multiple filters but only single one has been tested so far.
+ * NOTICE: In contrary to @class QFileDialog @param filter takes:
+ * only extension name WITHOUT any dots, parenthesis, asterisks or so.
+ * Multiple extensions can should be separated by |
+ * noo|nel or bz|gz|bz2
  */
-class TfileDialog : public QFileDialog
+class TfileDialog : public QDialog
 {
+  Q_OBJECT
+
 public:
-  TfileDialog(QWidget* parent, const QString& caption, const QString& directory, const QString& filter);
+  enum EacceptMode { e_acceptSave, e_acceptOpen }; /** File dialog type: for opening or saving */
+  Q_ENUM(EacceptMode)
+
+  explicit TfileDialog(QWidget* parent, const QString& directory, const QString& filter, EacceptMode mode);
+  ~TfileDialog();
+
+  static QString getSaveFileName(QWidget* parent = 0, const QString& directory = QString(), const QString& filter = QString());
+  static QString getOpenFileName(QWidget* parent = 0, const QString& directory = QString(), const QString& filter = QString());
+
+  QString selectedFile() const { return m_selectedFile; }
+
+  void setDirection(QBoxLayout::Direction dir) { m_lay->setDirection(dir); } /** Left to right by default */
+  EacceptMode acceptMode() { return m_acceptMode; }
+
+
+protected:
+  void itemClickedSlot(const QModelIndex& index);
+  void menuClickedSlot(QListWidgetItem* item);
+  void dirUpSlot();
+  void newDirSlot();
+  void performAction(); /** Open or save */
+
+  QListWidgetItem* addMenuItem(const QIcon& icon, const QString& text = QString());
+  void updateLocationLabel();
+
+private:
+  QFileSystemModel        *m_fileModel;
+  QString                  m_selectedFile;
+  EacceptMode              m_acceptMode;
+
+  QBoxLayout              *m_lay;
+  QListView               *m_list;
+  QListWidget             *m_menu;
+  QListWidgetItem         *m_acceptItem, *m_cancelItem, *m_dirUpItem, *m_newDirItem;
+  QLineEdit               *m_editName;
+  QLabel                  *m_locationLab;
+  QComboBox               *m_extensionCombo;
 
-  static QString getSaveFileName(QWidget* parent, const QString& caption, const QString& directory, const QString& filter);
-  static QString getOpenFileName(QWidget* parent, const QString& caption, const QString& directory, const QString& filter);
 };
 
 #endif // TFILEDIALOG_H
diff --git a/src/plugins/level/tlevelcreatordlg.cpp b/src/plugins/level/tlevelcreatordlg.cpp
index 64cd1952a..f0e58b080 100644
--- a/src/plugins/level/tlevelcreatordlg.cpp
+++ b/src/plugins/level/tlevelcreatordlg.cpp
@@ -137,8 +137,8 @@ void TlevelCreatorDlg::levelWasSelected(Tlevel level) {
 
 void TlevelCreatorDlg::levelNotSaved() {
 	if (!isNotSaved) {
-    navList->item(0)->setIcon(QIcon(Tcore::gl()->path+"picts/notSaved.png"));
-    setWindowTitle(levelCreatorTxt() + "  (" + tr("level not saved!") + ")");
+    navList->item(0)->setIcon(QIcon(Tcore::gl()->path + "picts/notSaved.png"));
+    setWindowTitle(levelCreatorTxt() + QLatin1String("  (") + tr("level not saved!") + QLatin1String(")"));
 		isNotSaved = true;
 	}
 }
@@ -148,7 +148,7 @@ void TlevelCreatorDlg::saveLevel() {
     if ( QMessageBox::question(this, tr("level not saved!"), tr("Level was changed and not saved!"),
 			QMessageBox::Save, QMessageBox::Cancel) == QMessageBox::Save ) {
         saveToFile();
-    } else 
+    } else
 				levelSaved();
 }
 
@@ -180,19 +180,22 @@ void TlevelCreatorDlg::saveToFile() {
   newLevel.name = nameList[0];
   newLevel.desc = nameList[1];
 // Saving to file
-  QString fName = QDir::toNativeSeparators(Tcore::gl()->E->examsDir + QStringLiteral("/") + newLevel.name);
-  if (QFileInfo(fName  + QStringLiteral(".nel")).exists())
-    fName += QStringLiteral("-") + QDateTime::currentDateTime().toString("(dd-MMM-hhmmss)");
-
+  QLatin1String dotNel(".nel");
+  QString fName = QDir::toNativeSeparators(Tcore::gl()->E->levelsDir + QLatin1String("/") + newLevel.name);
+  if (QFileInfo(fName  + dotNel).exists())
+    fName += QLatin1String("-") + QDateTime::currentDateTime().toString(QLatin1String("(dd-MMM-hhmmss)"));
+  qDebug() << "Sugested name" << fName;
 #if defined (Q_OS_ANDROID)
-  QString fileName = TfileDialog::getSaveFileName(this, tr("Save exam level"), fName, TlevelSelector::levelFilterTxt() + QStringLiteral(" (*.nel)"));
+  QString fileName = TfileDialog::getSaveFileName(this, fName, QStringLiteral("nel"));
 #else
-  QString fileName = QFileDialog::getSaveFileName(this, tr("Save exam level"), fName, TlevelSelector::levelFilterTxt() + QStringLiteral(" (*.nel)"));
+  QString fileName = QFileDialog::getSaveFileName(this, tr("Save exam level"), fName, TlevelSelector::levelFilterTxt() + QLatin1String(" (*.nel)"));
 #endif
-  if (fileName.isEmpty())
+  if (fileName.isEmpty()) {
+    qDebug() << "empty file name";
       return;
-  if (fileName.right(4) != QLatin1String(".nel"))
-    fileName += QStringLiteral(".nel");
+  }
+  if (fileName.right(4) != dotNel)
+    fileName += dotNel;
   Tcore::gl()->E->levelsDir = QFileInfo(fileName).absoluteDir().absolutePath();
   if (!Tlevel::saveToFile(newLevel, fileName)) {
       QMessageBox::critical(this, QStringLiteral(" "), tr("Cannot open file for writing"));
@@ -226,7 +229,7 @@ QString TlevelCreatorDlg::validateLevel(Tlevel &l) {
     if (!l.canBeScore() && ! l.canBeName() && !l.canBeGuitar() && !l.canBeSound()) {
         res = tr("There aren't any questions or answers selected.<br>Level makes no sense.");
         return res;
-    }      
+    }
   // checking range
   // determine the highest note of fret range on available strings
     if (l.canBeGuitar() || (l.instrument != e_noInstrument && l.answerIsSound())) {
-- 
GitLab