From 9f6cb9a72f438cfd54d4bb940a9207139a34946a Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Wed, 28 Nov 2018 00:07:26 +0100 Subject: [PATCH] Allow to delete data directory from application view * allow to re-init applicazion list (needed because directories can be deleted) * context menu for "delete data directory" --- .../components/copyconfigurationcomponent.cpp | 2 +- .../models/applicationinfolistmodel.cpp | 4 +- .../models/applicationinfolistmodel.h | 2 +- src/blackgui/views/applicationinfoview.cpp | 42 ++++++++++++++ src/blackgui/views/applicationinfoview.h | 26 ++++++++- src/blackmisc/applicationinfolist.cpp | 16 ++---- src/blackmisc/applicationinfolist.h | 4 +- src/blackmisc/directoryutils.cpp | 57 +++++++++---------- src/blackmisc/directoryutils.h | 4 +- 9 files changed, 108 insertions(+), 49 deletions(-) diff --git a/src/blackgui/components/copyconfigurationcomponent.cpp b/src/blackgui/components/copyconfigurationcomponent.cpp index 174304871..c1343f199 100644 --- a/src/blackgui/components/copyconfigurationcomponent.cpp +++ b/src/blackgui/components/copyconfigurationcomponent.cpp @@ -419,7 +419,7 @@ namespace BlackGui void CCopyConfigurationComponent::initOtherSwiftVersions() { ui->cb_OtherVersions->clear(); - const QMap otherVersions = CDirectoryUtils::applicationDataDirectoryMapWithoutCurrentVersion(); + const QMap otherVersions = CDirectoryUtils::applicationDataDirectoryMapWithoutCurrentVersion(true); for (const QString &directory : otherVersions.keys()) { const CApplicationInfo info(otherVersions.value(directory)); diff --git a/src/blackgui/models/applicationinfolistmodel.cpp b/src/blackgui/models/applicationinfolistmodel.cpp index e77fd41fb..eef5e89e9 100644 --- a/src/blackgui/models/applicationinfolistmodel.cpp +++ b/src/blackgui/models/applicationinfolistmodel.cpp @@ -40,9 +40,9 @@ namespace BlackGui m_sortOrder = Qt::DescendingOrder; } - void CApplicationInfoListModel::otherSwiftVersionsFromDataDirectories() + void CApplicationInfoListModel::otherSwiftVersionsFromDataDirectories(bool reinit) { - this->update(CApplicationInfoList::fromOtherSwiftVersionsFromDataDirectories()); + this->update(CApplicationInfoList::fromOtherSwiftVersionsFromDataDirectories(reinit)); } } // namespace } // namespace diff --git a/src/blackgui/models/applicationinfolistmodel.h b/src/blackgui/models/applicationinfolistmodel.h index 88986832b..52737d7ce 100644 --- a/src/blackgui/models/applicationinfolistmodel.h +++ b/src/blackgui/models/applicationinfolistmodel.h @@ -34,7 +34,7 @@ namespace BlackGui virtual ~CApplicationInfoListModel() {} //! \copydoc BlackMisc::CApplicationInfoList::fromOtherSwiftVersionsFromDataDirectories - void otherSwiftVersionsFromDataDirectories(); + void otherSwiftVersionsFromDataDirectories(bool reinit); }; } // ns } // ns diff --git a/src/blackgui/views/applicationinfoview.cpp b/src/blackgui/views/applicationinfoview.cpp index 1ce0f05ae..766ea32a3 100644 --- a/src/blackgui/views/applicationinfoview.cpp +++ b/src/blackgui/views/applicationinfoview.cpp @@ -8,9 +8,14 @@ */ #include "applicationinfoview.h" +#include "blackmisc/fileutils.h" + +#include +#include using namespace BlackMisc; using namespace BlackGui::Models; +using namespace BlackGui::Menus; namespace BlackGui { @@ -19,6 +24,7 @@ namespace BlackGui CApplicationInfoView::CApplicationInfoView(QWidget *parent) : CViewBase(parent) { this->standardInit(new CApplicationInfoListModel(this)); + this->setCustomMenu(new CApplicationInfoMenu(this)); } int CApplicationInfoView::otherSwiftVersionsFromDataDirectories() @@ -28,5 +34,41 @@ namespace BlackGui m_acceptRowSelection = (others.size() > 0); return others.size(); } + + void CApplicationInfoView::deleteSelectedDataDirectories() + { + if (!this->hasSelection()) { return; } + const QMessageBox::StandardButton reply = QMessageBox::question(this, "Delete?", "Delete selected data directories?", QMessageBox::Yes | QMessageBox::No); + if (reply != QMessageBox::Yes) { return; } + + QStringList deletedDirectories; + for (const CApplicationInfo &info : this->selectedObjects()) + { + const QString d = CFileUtils::fixWindowsUncPath(info.getApplicationDataDirectory()); + QDir dir(d); + if (!dir.exists()) { continue; } + if (dir.removeRecursively()) + { + deletedDirectories << d; + } + } + if (deletedDirectories.isEmpty()) { return; } + this->otherSwiftVersionsFromDataDirectories(); + } + + void CApplicationInfoMenu::customMenu(CMenuActions &menuActions) + { + if (!this->view()) { return; } + if (!this->view()->isEmpty()) + { + m_menuActionDeleteDirectory = menuActions.addAction(m_menuActionDeleteDirectory, CIcons::delete16(), "Delete data directories", CMenuAction::pathNone(), this, { this->view(), &CApplicationInfoView::deleteSelectedDataDirectories }); + } + this->nestedCustomMenu(menuActions); + } + + CApplicationInfoView *CApplicationInfoMenu::view() const + { + return static_cast(this->parent()); + } } // namespace } // namespace diff --git a/src/blackgui/views/applicationinfoview.h b/src/blackgui/views/applicationinfoview.h index 80b720e70..daf5774ee 100644 --- a/src/blackgui/views/applicationinfoview.h +++ b/src/blackgui/views/applicationinfoview.h @@ -14,9 +14,10 @@ #include "blackgui/views/viewbase.h" #include "blackgui/models/applicationinfolistmodel.h" +#include "blackgui/menus/menudelegate.h" #include "blackgui/blackguiexport.h" -class QWidget; +#include namespace BlackGui { @@ -31,7 +32,28 @@ namespace BlackGui //! BlackMisc::CApplicationInfoList::otherSwiftVersionsFromDataDirectories int otherSwiftVersionsFromDataDirectories(); + + //! Delete the selected directories + void deleteSelectedDataDirectories(); }; - } + + //! Menu base class for aircraft model view menus + class CApplicationInfoMenu : public Menus::IMenuDelegate + { + public: + //! Constructor + CApplicationInfoMenu(CApplicationInfoView *modelView) : Menus::IMenuDelegate(modelView) + {} + + //! \copydoc Menus::IMenuDelegate::customMenu + virtual void customMenu(Menus::CMenuActions &menuActions); + + private: + //! Model view + CApplicationInfoView *view() const; + + QAction *m_menuActionDeleteDirectory = nullptr; //!< action to delete menu + }; + } // ns } // ns #endif // guard diff --git a/src/blackmisc/applicationinfolist.cpp b/src/blackmisc/applicationinfolist.cpp index 443a3678c..436476df8 100644 --- a/src/blackmisc/applicationinfolist.cpp +++ b/src/blackmisc/applicationinfolist.cpp @@ -42,10 +42,10 @@ namespace BlackMisc return names; } - int CApplicationInfoList::otherSwiftVersionsFromDataDirectories() + int CApplicationInfoList::otherSwiftVersionsFromDataDirectories(bool reinit) { this->clear(); - const QMap otherVersions = CDirectoryUtils::applicationDataDirectoryMapWithoutCurrentVersion(); + const QMap otherVersions = CDirectoryUtils::applicationDataDirectoryMapWithoutCurrentVersion(reinit); for (const QString &directory : otherVersions.keys()) { CApplicationInfo info(otherVersions.value(directory)); @@ -54,14 +54,10 @@ namespace BlackMisc return this->size(); } - CApplicationInfoList CApplicationInfoList::fromOtherSwiftVersionsFromDataDirectories() + CApplicationInfoList CApplicationInfoList::fromOtherSwiftVersionsFromDataDirectories(bool reinit) { - static CApplicationInfoList info = [] - { - CApplicationInfoList il; - il.otherSwiftVersionsFromDataDirectories(); - return il; - }(); - return info; + CApplicationInfoList il; + il.otherSwiftVersionsFromDataDirectories(reinit); + return il; } } // ns diff --git a/src/blackmisc/applicationinfolist.h b/src/blackmisc/applicationinfolist.h index ec87e7868..b4e1a2bf4 100644 --- a/src/blackmisc/applicationinfolist.h +++ b/src/blackmisc/applicationinfolist.h @@ -44,10 +44,10 @@ namespace BlackMisc QStringList processNames() const; //! Fill from cache data directories - int otherSwiftVersionsFromDataDirectories(); + int otherSwiftVersionsFromDataDirectories(bool reinit = false); //! Filled from cache data directories - static CApplicationInfoList fromOtherSwiftVersionsFromDataDirectories(); + static CApplicationInfoList fromOtherSwiftVersionsFromDataDirectories(bool reinit = false); }; } // ns diff --git a/src/blackmisc/directoryutils.cpp b/src/blackmisc/directoryutils.cpp index 5714e7a2e..3aa234fcd 100644 --- a/src/blackmisc/directoryutils.cpp +++ b/src/blackmisc/directoryutils.cpp @@ -144,42 +144,41 @@ namespace BlackMisc return dirs; } - const CDirectoryUtils::FilePerApplication &CDirectoryUtils::applicationDataDirectoryMapWithoutCurrentVersion() + const CDirectoryUtils::FilePerApplication &CDirectoryUtils::applicationDataDirectoryMapWithoutCurrentVersion(bool reinit) { - static const FilePerApplication dirs = [ = ]() -> FilePerApplication - { - FilePerApplication directories; - for (const QFileInfo &info : CDirectoryUtils::applicationDataDirectories()) - { - if (caseInsensitiveStringCompare(info.filePath(), CDirectoryUtils::normalizedApplicationDataDirectory())) { continue; } + static FilePerApplication dirs; + if (!reinit && !dirs.isEmpty()) { return dirs; } - // the application info will be written by each swift application started - // so the application type will always contain that application - const QString appInfoFile = CFileUtils::appendFilePaths(info.filePath(), CApplicationInfo::fileName()); - const QString appInfoJson = CFileUtils::readFileToString(appInfoFile); - CApplicationInfo appInfo; - if (appInfoJson.isEmpty()) - { - const QString exeDir = CDirectoryUtils::decodeNormalizedDirectory(info.filePath()); - appInfo.setExecutablePath(exeDir); - } - else - { - appInfo = CApplicationInfo::fromJson(appInfoJson); - } - appInfo.setApplicationDataDirectory(info.filePath()); - directories.insert(info.filePath(), appInfo); + FilePerApplication directories; + for (const QFileInfo &info : CDirectoryUtils::applicationDataDirectories()) + { + if (caseInsensitiveStringCompare(info.filePath(), CDirectoryUtils::normalizedApplicationDataDirectory())) { continue; } + + // the application info will be written by each swift application started + // so the application type will always contain that application + const QString appInfoFile = CFileUtils::appendFilePaths(info.filePath(), CApplicationInfo::fileName()); + const QString appInfoJson = CFileUtils::readFileToString(appInfoFile); + CApplicationInfo appInfo; + if (appInfoJson.isEmpty()) + { + const QString exeDir = CDirectoryUtils::decodeNormalizedDirectory(info.filePath()); + appInfo.setExecutablePath(exeDir); } - // https://stackoverflow.com/q/51635959/356726 - // cppcheck-suppress returnReference - return directories; - }(); + else + { + appInfo = CApplicationInfo::fromJson(appInfoJson); + } + appInfo.setApplicationDataDirectory(info.filePath()); + directories.insert(info.filePath(), appInfo); + } + + dirs = directories; return dirs; } - bool CDirectoryUtils::hasOtherSwiftDataDirectories() + bool CDirectoryUtils::hasOtherSwiftDataDirectories(bool reinit) { - return CDirectoryUtils::applicationDataDirectoryMapWithoutCurrentVersion().size() > 0; + return CDirectoryUtils::applicationDataDirectoryMapWithoutCurrentVersion(reinit).size() > 0; } const QString &CDirectoryUtils::normalizedApplicationDataDirectory() diff --git a/src/blackmisc/directoryutils.h b/src/blackmisc/directoryutils.h index 6201fc174..313c09de7 100644 --- a/src/blackmisc/directoryutils.h +++ b/src/blackmisc/directoryutils.h @@ -62,10 +62,10 @@ namespace BlackMisc static QStringList applicationDataDirectoryList(bool withoutCurrent = false, bool decodedDirName = false); //! swift application data sub directories with info if available - static const FilePerApplication &applicationDataDirectoryMapWithoutCurrentVersion(); + static const FilePerApplication &applicationDataDirectoryMapWithoutCurrentVersion(bool reinit = false); //! Other swift data directories - static bool hasOtherSwiftDataDirectories(); + static bool hasOtherSwiftDataDirectories(bool reinit = false); //! Is MacOS application bundle? //! \remark: Means the currently running executable is a MacOS bundle, but not all our executables are bundles on MacOS