From 945013e0a6d3111213caa54d2cf671c94999ce22 Mon Sep 17 00:00:00 2001 From: JuanJakobo Date: Thu, 8 Sep 2022 12:21:52 +0200 Subject: [PATCH] Feature #27: Include sort by date --- src/api/sqliteConnector.cpp | 9 +++++--- src/api/webDAV.cpp | 3 +-- src/api/webDAVModel.h | 2 +- src/handler/eventHandler.cpp | 24 ++++++++++++++++++--- src/handler/mainMenu.cpp | 3 +++ src/handler/mainMenu.h | 1 + src/ui/webDAVView/webDAVView.cpp | 36 ++++++++++++++++++++++++++++++-- src/util/util.cpp | 28 +++++++++++++++++++++++++ src/util/util.h | 20 +++++++++++++++++- 9 files changed, 114 insertions(+), 12 deletions(-) diff --git a/src/api/sqliteConnector.cpp b/src/api/sqliteConnector.cpp index e2da06a..3d240fa 100644 --- a/src/api/sqliteConnector.cpp +++ b/src/api/sqliteConnector.cpp @@ -10,6 +10,7 @@ #include "sqliteConnector.h" #include "sqlite3.h" #include "log.h" +#include "util.h" #include #include @@ -133,7 +134,7 @@ std::vector SqliteConnector::getItemsChildren(const string &parentPa temp.size = reinterpret_cast(sqlite3_column_text(stmt, 3)); temp.etag = reinterpret_cast(sqlite3_column_text(stmt, 4)); temp.fileType = reinterpret_cast(sqlite3_column_text(stmt, 5)); - temp.lastEditDate = reinterpret_cast(sqlite3_column_text(stmt, 6)); + temp.lastEditDate = Util::webDAVStringToTm(reinterpret_cast(sqlite3_column_text(stmt, 6))); temp.type = static_cast(sqlite3_column_int(stmt,7)); temp.state = static_cast(sqlite3_column_int(stmt,8)); @@ -194,7 +195,8 @@ bool SqliteConnector::saveItemsChildren(const std::vector &items) rs = sqlite3_bind_text(stmt, 5, parent.c_str(), parent.length(), NULL); rs = sqlite3_bind_text(stmt, 6, item.etag.c_str(), item.etag.length(), NULL); rs = sqlite3_bind_text(stmt, 7, item.fileType.c_str(), item.fileType.length(), NULL); - rs = sqlite3_bind_text(stmt, 8, item.lastEditDate.c_str(), item.lastEditDate.length(), NULL); + string lastEditDateString = Util::webDAVTmToString(item.lastEditDate); + rs = sqlite3_bind_text(stmt, 8, lastEditDateString.c_str(), lastEditDateString.length(), NULL); rs = sqlite3_bind_int(stmt, 9, item.type); rs = sqlite3_bind_int(stmt, 10, item.state); @@ -207,7 +209,8 @@ bool SqliteConnector::saveItemsChildren(const std::vector &items) rs = sqlite3_prepare_v2(_db, "UPDATE 'metadata' SET state=?, etag=?, lastEditDate=?, size=? WHERE path=?", -1, &stmt, 0); rs = sqlite3_bind_int(stmt, 1, item.state); rs = sqlite3_bind_text(stmt, 2, item.etag.c_str(), item.etag.length(), NULL); - rs = sqlite3_bind_text(stmt, 3, item.lastEditDate.c_str(), item.lastEditDate.length(), NULL); + string lastEditDateString = Util::webDAVTmToString(item.lastEditDate); + rs = sqlite3_bind_text(stmt, 3, lastEditDateString.c_str(), lastEditDateString.length(), NULL); rs = sqlite3_bind_text(stmt, 4, item.size.c_str(), item.size.length(), NULL); rs = sqlite3_bind_text(stmt, 5, item.path.c_str(), item.path.length(), NULL); rs = sqlite3_step(stmt); diff --git a/src/api/webDAV.cpp b/src/api/webDAV.cpp index de92574..7af05ee 100644 --- a/src/api/webDAV.cpp +++ b/src/api/webDAV.cpp @@ -114,7 +114,7 @@ vector WebDAV::getDataStructure(const string &pathUrl) tempItem.etag = Util::getXMLAttribute(xmlItem, "d:getetag"); tempItem.path = Util::getXMLAttribute(xmlItem, "d:href"); - tempItem.lastEditDate = Util::getXMLAttribute(xmlItem, "d:getlastmodified"); + tempItem.lastEditDate = Util::webDAVStringToTm(Util::getXMLAttribute(xmlItem, "d:getlastmodified")); double size = atof(Util::getXMLAttribute(xmlItem, "oc:size").c_str()); if (size < 1024) @@ -235,7 +235,6 @@ string WebDAV::propfind(const string &pathUrl) if (iv_access(CACERT_PATH.c_str(), R_OK) == 0) curl_easy_setopt(curl, CURLOPT_CAINFO, CACERT_PATH.c_str()); - //TODO add sorter here curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "<\?xml version=\"1.0\" encoding=\"UTF-8\"\?> \ \ \ diff --git a/src/api/webDAVModel.h b/src/api/webDAVModel.h index 394d0cd..453e9f7 100644 --- a/src/api/webDAVModel.h +++ b/src/api/webDAVModel.h @@ -34,7 +34,7 @@ struct WebDAVItem : Entry{ std::string localPath; FileState state{FileState::ICLOUD}; Itemtype type; - std::string lastEditDate{"Error"}; + tm lastEditDate = { 0 }; std::string size; std::string fileType; }; diff --git a/src/handler/eventHandler.cpp b/src/handler/eventHandler.cpp index 47be7b9..5292985 100644 --- a/src/handler/eventHandler.cpp +++ b/src/handler/eventHandler.cpp @@ -181,8 +181,26 @@ void EventHandler::mainMenuHandler(const int index) _loginView = std::unique_ptr(new LoginView(_menu->getContentRect())); break; } - //Select folder + //Sort by case 103: + { + int dialogResult = DialogSynchro(ICON_QUESTION, "Action", "By what do you want to sort?", "Filename", "Last modified", "Cancel"); + switch (dialogResult) + { + case 1: + Util::accessConfig(Action::IWriteInt, "sortBy", 1); + break; + case 2: + Util::accessConfig(Action::IWriteInt, "sortBy", 2); + break; + default: + return; + } + Message(ICON_INFORMATION, "Info", "Reload page to see new order method in effect.", 2000); + break; + } + //Select folder + case 104: { _currentPath =+ (_currentPath.back() != '/') ? "/nextcloud" : "nextcloud"; @@ -207,13 +225,13 @@ void EventHandler::mainMenuHandler(const int index) break; } //Info - case 104: + case 105: { Message(ICON_INFORMATION, "Info", "Version 0.98 \n For support please open a ticket at https://github.com/JuanJakobo/Pocketbook-Nextcloud-Client/issues", 1200); break; } //Exit - case 105: + case 106: CloseApp(); break; default: diff --git a/src/handler/mainMenu.cpp b/src/handler/mainMenu.cpp index 9c1c7eb..80c61f5 100644 --- a/src/handler/mainMenu.cpp +++ b/src/handler/mainMenu.cpp @@ -41,6 +41,7 @@ MainMenu::~MainMenu() free(_syncFolder); free(_menu); free(_logout); + free(_sortBy); free(_info); free(_exit); free(_chooseFolder); @@ -60,6 +61,8 @@ int MainMenu::createMenu(bool filePicker, bool loggedIn, iv_menuhandler handler) //show logged in {loggedIn ? (short)ITEM_ACTIVE : (short)ITEM_HIDDEN, 101, _syncFolder, NULL}, {loggedIn ? (short)ITEM_ACTIVE : (short)ITEM_HIDDEN, 102, _logout, NULL}, + {loggedIn ? (short)ITEM_ACTIVE : (short)ITEM_HIDDEN, 103, _sortBy, NULL}, + //show if filePicker is shown {filePicker ? (short)ITEM_ACTIVE : (short)ITEM_HIDDEN, 103, _chooseFolder, NULL}, //show always {ITEM_ACTIVE, 104, _info, NULL}, diff --git a/src/handler/mainMenu.h b/src/handler/mainMenu.h index 16896b2..ab1d3cb 100644 --- a/src/handler/mainMenu.h +++ b/src/handler/mainMenu.h @@ -54,6 +54,7 @@ private: char *_syncFolder = strdup("Actualize folder"); char *_logout = strdup("Logout"); char *_chooseFolder = strdup("Create here"); + char *_sortBy = strdup("Order items by"); char *_info = strdup("Info"); char *_exit = strdup("Close App"); diff --git a/src/ui/webDAVView/webDAVView.cpp b/src/ui/webDAVView/webDAVView.cpp index 598f5ba..9247593 100644 --- a/src/ui/webDAVView/webDAVView.cpp +++ b/src/ui/webDAVView/webDAVView.cpp @@ -9,9 +9,11 @@ #include "webDAVView.h" #include "webDAVModel.h" #include "webDAV.h" +#include "util.h" #include #include +#include using std::vector; @@ -29,9 +31,40 @@ WebDAVView::WebDAVView(const irect &contentRect, vector &items, int header = header.substr(0, header.find_last_of("/") + 1); items.at(0).path = header; items.at(0).title += "\nclick to go back"; - items.at(0).lastEditDate = ""; + items.at(0).lastEditDate.tm_year = 2100; + + std::vector::iterator begin; + if (items.at(0).path.compare(NEXTCLOUD_ROOT_PATH) == 0) + { items.erase(items.begin()); + begin = items.begin(); + } + else + { + begin = items.begin()+1; + } + + sort(begin, items.end(), []( WebDAVItem &w1, WebDAVItem &w2) -> bool + { + if(Util::accessConfig(Action::IReadInt, "sortBy", 0) == 2) + { + //sort by lastmodified + time_t t1 = mktime(&w1.lastEditDate); + time_t t2 = mktime(&w2.lastEditDate); + return difftime(t1,t2) > 0 ? true : false; + } + else + { + //folders first then files + if(w1.type == Itemtype::IFILE && w2.type == Itemtype::IFOLDER) + return false; + else if(w1.type == Itemtype::IFOLDER && w2.type == Itemtype::IFILE) + return true; + else + return w1.title < w2.title; + } + }); for(auto item : items) { @@ -56,4 +89,3 @@ WebDAVView::WebDAVView(const irect &contentRect, vector &items, int } draw(); } - diff --git a/src/util/util.cpp b/src/util/util.cpp index 6d4ac16..1939984 100644 --- a/src/util/util.cpp +++ b/src/util/util.cpp @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include @@ -125,3 +127,29 @@ void Util::updatePBLibrary(int seconds) exit(1); } } + +tm Util::webDAVStringToTm(const std::string ×tring) +{ + tm t = {0}; + std::istringstream ss(timestring); + //format depends on nextcloud config? + //weekday, day month year Hour Minute Second Timezone + ss >> std::get_time(&t, "%a, %d %b %Y %H:%M:%S"); + if (ss.fail()) + Log::writeErrorLog("Failed to read in data format."); + return t; +} + +string Util::webDAVTmToString(const tm ×tring) +{ + std::ostringstream ss; + string result = {}; + //format depends on nextcloud config? + //weekday, day month year Hour Minute Second Timezone + ss << std::put_time(×tring, "%a, %d %b %Y %H:%M:%S"); + if (ss.fail()) + Log::writeErrorLog("Failed to read out data format."); + else + result = ss.str(); + return result; +} diff --git a/src/util/util.h b/src/util/util.h index 642253d..bcb9a5e 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -99,7 +99,7 @@ public: returnValue = 0; break; case Action::IReadInt: - returnValue = ReadInt(config, name.c_str(), 0); + returnValue = ReadInt(config, name.c_str(), -1); break; default: break; @@ -134,6 +134,24 @@ public: */ static void updatePBLibrary(int seconds); + /** + * Convert string to tm + * + * @param timestring of the string + * + * @return time in tm format + */ + static tm webDAVStringToTm(const std::string ×tring); + + /** + * Convert tm to string + * + * @param time in tm format + * + * @return timestring of the string + */ + static std::string webDAVTmToString(const tm ×tring); + private: Util() {} };