From ba8b9a52da91426d20044b1289769408a929292c Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Tue, 15 May 2018 02:58:56 +0200 Subject: [PATCH] Ref T264, Ref T263 simple approach to remember last directory (load/save) in view * utility function "unwrapCache" to unwrap cache data * fixed loading from file, also supporting memoized formats as well * remember last directory --- src/blackgui/views/viewbase.cpp | 51 +++++++++++++++++++++++++++------ src/blackgui/views/viewbase.h | 22 ++++++++++++-- src/blackmisc/json.cpp | 28 +++++++++++++++++- src/blackmisc/json.h | 10 +++++++ 4 files changed, 98 insertions(+), 13 deletions(-) diff --git a/src/blackgui/views/viewbase.cpp b/src/blackgui/views/viewbase.cpp index cc04c9efa..90b71aa6b 100644 --- a/src/blackgui/views/viewbase.cpp +++ b/src/blackgui/views/viewbase.cpp @@ -309,6 +309,29 @@ namespace BlackGui } } + void CViewBaseNonTemplate::rememberLastJsonDirectory(const QString &selectedFileOrDir) + { + if (selectedFileOrDir.isEmpty()) { return; } + const QFileInfo fi(selectedFileOrDir); + if ((fi.isDir() && fi.exists()) || (fi.isFile() && fi.exists())) + { + // existing dir + m_lastJsonDirectory = fi.absolutePath(); + } + } + + QString CViewBaseNonTemplate::getRememberedLastJsonDirectory() const + { + if (!m_lastJsonDirectory.isEmpty()) { return m_lastJsonDirectory; } + QString dirCandidate = m_dirSettings.get(); + const QFileInfo fi(dirCandidate); + if ((fi.isDir() && fi.exists()) || (fi.isFile() && fi.exists())) + { + return fi.absolutePath(); + } + return QStringLiteral(""); + } + void CViewBaseNonTemplate::customMenu(CMenuActions &menuActions) { // delegate? @@ -530,16 +553,16 @@ namespace BlackGui }); } - QString CViewBaseNonTemplate::getSettingsFileName(bool load) const + QString CViewBaseNonTemplate::getFileDialogFileName(bool load) const { // some logic to find a useful default name - const QString dir = m_dirSettings.get(); if (load) { - return CFileUtils::appendFilePaths(dir, CFileUtils::jsonWildcardAppendix()); + return CFileUtils::appendFilePaths(this->getRememberedLastJsonDirectory(), CFileUtils::jsonWildcardAppendix()); } // Save file path + const QString dir = m_dirSettings.get(); QString name(m_saveFileName); if (name.isEmpty()) { @@ -818,7 +841,7 @@ namespace BlackGui void CViewBaseNonTemplate::dragEnterEvent(QDragEnterEvent *event) { if (!event || !this->acceptDrop(event->mimeData())) { return; } - setBackgroundRole(QPalette::Highlight); + this->setBackgroundRole(QPalette::Highlight); event->acceptProposedAction(); } @@ -1478,7 +1501,7 @@ namespace BlackGui do { const QString fileName = QFileDialog::getOpenFileName(nullptr, - tr("Load data file"), getSettingsFileName(true), + tr("Load data file"), this->getFileDialogFileName(true), tr("swift (*.json *.txt)")); if (fileName.isEmpty()) { @@ -1497,16 +1520,26 @@ namespace BlackGui m = CStatusMessage(this).warning("No swift JSON '%1'") << fileName; break; } + + this->rememberLastJsonDirectory(fileName); + try { - CVariant containerVariant; - containerVariant.convertFromJson(Json::jsonObjectFromString(json)); - if (!containerVariant.canConvert()) + const bool allowCacheFormat = this->allowCacheFileFormatJson(); + const QJsonObject jsonObject = Json::jsonObjectFromString(json, allowCacheFormat); + if (jsonObject.isEmpty()) { m = CStatusMessage(this).warning("No valid swift JSON '%1'") << fileName; break; } + CVariant containerVariant; + containerVariant.convertFromJson(jsonObject); + if (!containerVariant.canConvert()) + { + m = CStatusMessage(this).warning("No valid swift JSON '%1'") << fileName; + break; + } ContainerType container = containerVariant.value(); const int countBefore = container.size(); m = this->modifyLoadedJsonData(container); @@ -1534,7 +1567,7 @@ namespace BlackGui CStatusMessage CViewBase::ps_saveJson() { const QString fileName = QFileDialog::getSaveFileName(nullptr, - tr("Save data file"), getSettingsFileName(false), + tr("Save data file"), getFileDialogFileName(false), tr("swift (*.json *.txt)")); if (fileName.isEmpty()) { return CStatusMessage(this, CStatusMessage::SeverityDebug, "Save canceled", true); } const QString json(this->toJsonString()); // save as CVariant JSON diff --git a/src/blackgui/views/viewbase.h b/src/blackgui/views/viewbase.h index e05941b03..d9383ef7c 100644 --- a/src/blackgui/views/viewbase.h +++ b/src/blackgui/views/viewbase.h @@ -277,6 +277,12 @@ namespace BlackGui //! Save file name (optional) void setSaveFileName(const QString &saveName) { m_saveFileName = saveName; } + //! Allow cache file JSON to be loaded + bool allowCacheFileFormatJson() const { return m_allowCacheFileJson; } + + //! Enable/disable cache file format to be loaded as JSON + void setAllowCacheFileFormatJson(bool allow) { m_allowCacheFileJson = allow; } + //! Force that columns are extended to full viewport width. //! Workaround as of https://stackoverflow.com/q/3433664/356726 void setForceColumnsToMaxSize(bool force) { m_forceColumnsToMaxSize = force; } @@ -415,7 +421,7 @@ namespace BlackGui void init(); //! Default file for load/save operations - QString getSettingsFileName(bool load) const; + QString getFileDialogFileName(bool load) const; //! Init menu actions Menus::CMenuActions initMenuActions(MenuFlag menu); @@ -438,7 +444,14 @@ namespace BlackGui //! Settings have been changed void settingsChanged(); - QString m_saveFileName; //!< save file name (JSON) + //! JSON directory + //! \remark Default implementation, can be overridden with specifi implementation + virtual void rememberLastJsonDirectory(const QString &selectedFileOrDir); + + //! JSON directory + //! \remark Default implementation, can be overridden with specifi implementation + virtual QString getRememberedLastJsonDirectory() const; + ResizeMode m_resizeMode = PresizeSubset; //!< mode RowsResizeMode m_rowResizeMode = Interactive; //!< row resize mode for row height SelectionMode m_originalSelectionMode = this->selectionMode(); //!< Selection mode set @@ -456,14 +469,17 @@ namespace BlackGui bool m_enableDeleteSelectedRows = false; //!< selected rows can be deleted bool m_dropIndicator = false; //!< draw indicator bool m_forceColumnsToMaxSize = true; //!< force that columns are extended to full viewport width + bool m_allowCacheFileJson = true; //!< allow Cache format JSON to be loaded QWidget *m_filterWidget = nullptr; //!< filter widget or dialog Menu m_menus = MenuDefault; //!< Default menu settings Menus::IMenuDelegate *m_menu = nullptr; //!< custom menu if any Menus::CFontMenu *m_fontMenu = nullptr; //!< font menu if applicable CLoadIndicator *m_loadIndicator = nullptr; //!< load indicator if needed QMap m_menuFlagActions; //!< initialized actions - BlackMisc::CSettingReadOnly m_guiSettings { this, &CViewBaseNonTemplate::settingsChanged }; //!< general GUI settings + QString m_saveFileName; //!< save file name (JSON) + QString m_lastJsonDirectory; //!< remember last JSON directory BlackMisc::CSetting m_dirSettings { this }; //!< directory for load/save + BlackMisc::CSettingReadOnly m_guiSettings { this, &CViewBaseNonTemplate::settingsChanged }; //!< general GUI settings protected slots: //! Helper method with template free signature serving as callback from threaded worker diff --git a/src/blackmisc/json.cpp b/src/blackmisc/json.cpp index ac744e6fe..fd9e5c04b 100644 --- a/src/blackmisc/json.cpp +++ b/src/blackmisc/json.cpp @@ -392,7 +392,8 @@ namespace BlackMisc { if (json.isEmpty()) { return QJsonObject();} const QJsonDocument jsonDoc(QJsonDocument::fromJson(json.toUtf8())); - return acceptCacheFormat ? Json::swiftDataObjectValue(jsonDoc.object()) : jsonDoc.object(); + return acceptCacheFormat ? Json::unwrapCache(jsonDoc.object()) : jsonDoc.object(); + // return acceptCacheFormat ? Json::swiftDataObjectValue(jsonDoc.object()) : jsonDoc.object(); } QString stringFromJsonObject(const QJsonObject &jsonObject, QJsonDocument::JsonFormat format) @@ -487,11 +488,28 @@ namespace BlackMisc const QJsonObject cacheObject = object.value(key).toObject(); if (cacheObject.contains("type") && cacheObject.contains("value")) { + const QString type = cacheObject.value("type").toString(); // just to verify in debugger + Q_UNUSED(type); return cacheObject.value("value").toObject(); } return object; } + QJsonObject unwrapCache(const QJsonObject &object) + { + if (object.size() != 1) { return object; } // no cache format + const QString key = object.keys().front(); + const QJsonObject cacheObject = object.value(key).toObject(); + if (cacheObject.contains("type") && cacheObject.contains("value")) + { + // return object in form type/value + const QString type = cacheObject.value("type").toString(); // just to verify in debugger + Q_UNUSED(type); + return cacheObject; + } + return object; + } + QJsonObject swiftDataObjectValue(const QString &jsonString) { const QJsonObject obj = jsonObjectFromString(jsonString); @@ -499,6 +517,14 @@ namespace BlackMisc return swiftDataObjectValue(obj); } + + QJsonObject unwrapCache(const QString &jsonString) + { + const QJsonObject obj = jsonObjectFromString(jsonString); + if (obj.isEmpty()) { return obj; } + return unwrapCache(obj); + } + bool looksLikeSwiftContainerJson(const QJsonObject &object) { // CContainerbase::convertFromJson diff --git a/src/blackmisc/json.h b/src/blackmisc/json.h index 9bcee26c0..a868f0cd5 100644 --- a/src/blackmisc/json.h +++ b/src/blackmisc/json.h @@ -275,6 +275,16 @@ namespace BlackMisc //! \remark if data object unstrip from that, otherwise leave unchanged BLACKMISC_EXPORT QJsonObject swiftDataObjectValue(const QString &jsonString); + //! The value of a cache/setting object + //! \remark if cache object unstrip from that, otherwise leave unchanged + //! \remark format is type/value + BLACKMISC_EXPORT QJsonObject unwrapCache(const QJsonObject &object); + + //! The value of a cache/setting object + //! \remark if cache object unstrip from that, otherwise leave unchanged + //! \remark format is type/value + BLACKMISC_EXPORT QJsonObject unwrapCache(const QString &jsonString); + /*! * Load JSON file and init by that */