Add option to set the default start folder when opening the app

master
Jonas Letzbor 2022-10-06 18:31:38 +02:00
parent 2f84fec1a9
commit 75dd96222e
11 changed files with 150 additions and 15 deletions

View File

@ -16,6 +16,8 @@
#include <string>
#include <vector>
#include <regex>
using std::string;
SqliteConnector::SqliteConnector(const string &DBpath) : _dbpath(DBpath)
@ -259,6 +261,28 @@ void SqliteConnector::deleteChild(const string &path, const string &title)
rs = sqlite3_reset(stmt);
}
void SqliteConnector::deleteItemsNotBeginsWith(string beginPath)
{
open();
// escape characters
beginPath = std::regex_replace(beginPath, std::regex("%"), "#%");
beginPath = std::regex_replace(beginPath, std::regex("_"), "#_");
beginPath = beginPath + "%";
int rs;
sqlite3_stmt *stmt = 0;
rs = sqlite3_prepare_v2(_db, "DELETE FROM 'metadata' WHERE path NOT LIKE ? ESCAPE '#'", -1, &stmt, 0);
rs = sqlite3_bind_text(stmt, 1, beginPath.c_str(), beginPath.length(), NULL);
rs = sqlite3_step(stmt);
if (rs != SQLITE_DONE)
{
Log::writeErrorLog(std::string("An error ocurred trying to delete the items that begins with " + beginPath) + sqlite3_errmsg(_db) + std::string(" (Error Code: ") + std::to_string(rs) + ")");
}
rs = sqlite3_clear_bindings(stmt);
rs = sqlite3_reset(stmt);
}
bool SqliteConnector::resetHideState()
{

View File

@ -47,6 +47,8 @@ public:
void deleteChild(const std::string &path, const std::string &title);
void deleteItemsNotBeginsWith(std::string beginPath);
bool resetHideState();
bool saveItemsChildren(const std::vector<WebDAVItem> &children);

View File

@ -19,6 +19,7 @@
#include <fstream>
#include <sstream>
#include <math.h>
#include <regex>
using std::ifstream;
using std::ofstream;
@ -27,6 +28,20 @@ using std::vector;
namespace fs = std::experimental::filesystem;
std::string WebDAV::getRootPath(bool encode) {
string rootPath = Util::getConfig<std::string>("ex_relativeRootPath", "/");
if (rootPath == "")
rootPath += "/";
string rtc = NEXTCLOUD_ROOT_PATH + Util::getConfig<std::string>("UUID", "") + rootPath;
if (encode) {
Util::encodeUrl(rtc);
rtc = std::regex_replace(rtc, std::regex("%2F"), "/");
}
return rtc;
}
WebDAV::WebDAV()
{
if (iv_access(NEXTCLOUD_PATH.c_str(), W_OK) != 0)
@ -184,7 +199,7 @@ vector<WebDAVItem> WebDAV::getDataStructure(const string &pathUrl)
tempItem.title = tempItem.title.substr(tempItem.title.find_last_of("/") + 1, tempItem.title.length());
Util::decodeUrl(tempItem.title);
string &pathDecoded = tempItem.path;
string pathDecoded = tempItem.path;
Util::decodeUrl(pathDecoded);
tempItem.hide = _fileHandler->getHideState(tempItem.type, prefix,(pathDecoded), tempItem.title);
@ -233,6 +248,7 @@ string WebDAV::propfind(const string &pathUrl)
string readBuffer;
CURLcode res;
CURL *curl = curl_easy_init();
Log::writeInfoLog("Path: " + pathUrl);
if (curl)
{
@ -274,7 +290,33 @@ string WebDAV::propfind(const string &pathUrl)
switch (response_code)
{
case 404:
if (getRootPath().compare( NEXTCLOUD_ROOT_PATH + Util::getConfig<std::string>("uuid", "")) != 0) {
if (propfind(NEXTCLOUD_ROOT_PATH + Util::getConfig<std::string>("UUID", "")) != "") {
// Own root path defined
string output;
int dialogResult = DialogSynchro(
ICON_ERROR,
"Action",
output.append("The specified start folder does not seem to exist:\n").append(Util::getConfig<std::string>("ex_relativeRootPath", "/")).append("\n\nWhat would you like to do?").c_str(),
"Reset start folder", "Close App", NULL
);
switch (dialogResult)
{
case 1:
{
Util::accessConfig<string>(Action::IWriteString, "ex_relativeRootPath", "");
return propfind(NEXTCLOUD_ROOT_PATH + Util::getConfig<std::string>("UUID", ""));
}
break;
case 2:
default:
CloseApp();
break;
}
}
} else {
Message(ICON_ERROR, "Error", "The URL seems to be incorrect. You can look up the WebDav URL in the settings of the files webapp. ", 4000);
}
break;
case 401:
Message(ICON_ERROR, "Error", "Username/password incorrect.", 4000);

View File

@ -38,6 +38,12 @@ class WebDAV
std::vector<WebDAVItem> getDataStructure(const std::string &pathUrl);
/**
* Returns the root path of the nextcloud server
* (e.g. /remote.php/dav/files/userName/startFolder/)
*/
static std::string getRootPath(bool encode = false);
/**
* gets the dataStructure of the given URL and writes its WEBDAV items to the items vector
*

View File

@ -49,7 +49,7 @@ EventHandler::EventHandler()
iv_mkdir(Util::accessConfig<string>(Action::IReadString, "storageLocation",{}).c_str(), 0777);
std::vector<WebDAVItem> currentWebDAVItems;
string path = NEXTCLOUD_ROOT_PATH + Util::accessConfig<string>(Action::IReadString,"UUID",{}) + '/';
string path = WebDAV::getRootPath(true);
currentWebDAVItems = _webDAV.getDataStructure(path);
_menu = std::unique_ptr<MainMenu>(new MainMenu("Nextcloud"));
@ -234,7 +234,7 @@ void EventHandler::mainMenuHandler(const int index)
else
{
Util::accessConfig<string>(Action::IWriteString, "storageLocation", _currentPath);
std::vector<WebDAVItem> currentWebDAVItems = _webDAV.getDataStructure(NEXTCLOUD_ROOT_PATH + Util::accessConfig<string>(Action::IReadString,"UUID",{}) + '/');
std::vector<WebDAVItem> currentWebDAVItems = _webDAV.getDataStructure(WebDAV::getRootPath(true));
if (currentWebDAVItems.empty())
{
Message(ICON_ERROR, "Error", "Failed to get items. Please try again.", 1000);
@ -388,8 +388,14 @@ int EventHandler::pointerHandler(const int type, const int par1, const int par2)
Util::accessConfig<string>(Action::IWriteString, "ex_extensionList", _excludeFileView->getExtensionList());
Util::accessConfig<string>(Action::IWriteString, "ex_pattern",_excludeFileView->getRegex());
Util::accessConfig<string>(Action::IWriteString, "ex_folderPattern",_excludeFileView->getFolderRegex());
Util::accessConfig<string>(Action::IWriteString, "ex_relativeRootPath", _excludeFileView->getStartFolder());
Util::accessConfig<int>(Action::IWriteInt, "ex_invertMatch", _excludeFileView->getInvertMatch());
_sqllite.resetHideState();
if (_excludeFileView->getStartFolder() != "")
{
_sqllite.deleteItemsNotBeginsWith(WebDAV::getRootPath(true));
}
_excludeFileView.reset();
ShowHourglassForce();
@ -399,7 +405,7 @@ int EventHandler::pointerHandler(const int type, const int par1, const int par2)
vector<FileItem> currentFolder = FileBrowser::getFileStructure(_currentPath,false,true);
_fileView.reset(new FileView(_menu->getContentRect(), currentFolder,1));
} else {
std::vector<WebDAVItem> currentWebDAVItems = _webDAV.getDataStructure(NEXTCLOUD_ROOT_PATH + Util::accessConfig<string>(Action::IReadString,"UUID",{}) + '/');
std::vector<WebDAVItem> currentWebDAVItems = _webDAV.getDataStructure(WebDAV::getRootPath(true));
updateItems(currentWebDAVItems);
drawWebDAVItems(currentWebDAVItems);
}
@ -413,7 +419,7 @@ int EventHandler::pointerHandler(const int type, const int par1, const int par2)
vector<FileItem> currentFolder = FileBrowser::getFileStructure(_currentPath,false,true);
_fileView.reset(new FileView(_menu->getContentRect(), currentFolder,1));
} else {
std::vector<WebDAVItem> currentWebDAVItems = _webDAV.getDataStructure(NEXTCLOUD_ROOT_PATH + Util::accessConfig<string>(Action::IReadString,"UUID",{}) + '/');
std::vector<WebDAVItem> currentWebDAVItems = _webDAV.getDataStructure(WebDAV::getRootPath(true));
updateItems(currentWebDAVItems);
drawWebDAVItems(currentWebDAVItems);
}
@ -509,7 +515,6 @@ void EventHandler::openItem()
void EventHandler::openFolder()
{
std::vector<WebDAVItem> currentWebDAVItems;
switch ((_webDAVView->getCurrentEntry().state == FileState::ILOCAL) ? FileState::ILOCAL : _sqllite.getState(_webDAVView->getCurrentEntry().path))

View File

@ -55,7 +55,7 @@ private:
char *_logout = strdup("Logout");
char *_chooseFolder = strdup("Create here");
char *_sortBy = strdup("Order items by");
char *_excludeFiles = strdup("Exclude and hide files");
char *_excludeFiles = strdup("Exclude and hide items");
char *_info = strdup("Info");
char *_exit = strdup("Close App");

View File

@ -22,6 +22,7 @@ ExcludeFileView::ExcludeFileView(const irect &contentRect): _contentRect(content
_extensionList = Util::getConfig<string>("ex_extensionList", "");
_regex = Util::getConfig<string>("ex_pattern", "");
_folderRegex = Util::getConfig<string>("ex_folderPattern", "");
_startFolder = Util::getConfig<string>("ex_relativeRootPath", "");
_invertMatch = Util::getConfig<int>("ex_invertMatch",0);
int contentHeight = contentRect.h / 2;
@ -54,20 +55,25 @@ ExcludeFileView::ExcludeFileView(const irect &contentRect): _contentRect(content
DrawString(_folderRegexButton.x, _folderRegexButton.y, _folderRegex.c_str());
DrawRect(_folderRegexButton.x - 1, _folderRegexButton.y - 1, _folderRegexButton.w + 2, _folderRegexButton.h + 2, BLACK);
_invertMatchButton = iRect(_contentRect.w - 2 * checkBoxWidth, beginY + 6 * contents, checkBoxWidth, contents, ALIGN_CENTER);
_startFolderButton = iRect(beginX, beginY + 6 * contents, contentWidth, contents, ALIGN_CENTER);
DrawTextRect(_startFolderButton.x, _startFolderButton.y - _fontHeight - _fontHeight/3, _startFolderButton.w, _startFolderButton.h, "Start folder:", ALIGN_LEFT);
DrawString(_startFolderButton.x, _startFolderButton.y, _startFolder.c_str());
DrawRect(_startFolderButton.x - 1, _startFolderButton.y - 1, _startFolderButton.w + 2, _startFolderButton.h + 2, BLACK);
_invertMatchButton = iRect(_contentRect.w - 2 * checkBoxWidth, beginY + 8 * contents, checkBoxWidth, contents, ALIGN_CENTER);
DrawTextRect(beginX, _invertMatchButton.y, contentWidth, _invertMatchButton.h, "Only include matching:", ALIGN_LEFT);
DrawRect(_invertMatchButton.x - 1, _invertMatchButton.y - 1, _invertMatchButton.w + 2, _invertMatchButton.h + 2, BLACK);
if (_invertMatch) {
FillArea(_invertMatchButton.x - 1, _invertMatchButton.y - 1, _invertMatchButton.w + 2, _invertMatchButton.h + 2, BLACK);
}
_saveButton = iRect(beginX, beginY + 8 * contents, contentWidth / 2 - 20, contents, ALIGN_CENTER);
_saveButton = iRect(beginX, beginY + 10 * contents, contentWidth / 2 - 20, contents, ALIGN_CENTER);
FillAreaRect(&_saveButton, BLACK);
SetFont(_font, WHITE);
DrawTextRect2(&_saveButton, "Save");
PartialUpdate(_contentRect.x, _contentRect.y, _contentRect.w, _contentRect.h);
_cancelButton = iRect(beginX + contentWidth / 2, beginY + 8 * contents, contentWidth / 2 - 20, contents, ALIGN_CENTER);
_cancelButton = iRect(beginX + contentWidth / 2, beginY + 10 * contents, contentWidth / 2 - 20, contents, ALIGN_CENTER);
FillAreaRect(&_cancelButton, BLACK);
SetFont(_font, WHITE);
DrawTextRect2(&_cancelButton, "Cancel");
@ -111,6 +117,15 @@ int ExcludeFileView::excludeClicked(int x, int y)
OpenKeyboard("/root/.*/test/", &_temp[0], EXCLUDE_FILE_KEYBOARD_STRING_LENGHT, KBD_NORMAL, &keyboardHandlerStatic);
return 1;
}
else if (IsInRect(x, y, &_startFolderButton))
{
_target = ExcludeFileKeyboardTarget::ISTARTFOLDER;
if (!_startFolder.empty())
_temp = _startFolder;
_temp.resize(EXCLUDE_FILE_KEYBOARD_STRING_LENGHT);
OpenKeyboard("/MyBooks/", &_temp[0], EXCLUDE_FILE_KEYBOARD_STRING_LENGHT, KBD_NORMAL, &keyboardHandlerStatic);
return 1;
}
else if (IsInRect(x, y, &_invertMatchButton))
{
_invertMatch = !_invertMatch;
@ -198,4 +213,18 @@ void ExcludeFileView::keyboardHandler(char *text)
FillAreaRect(&_folderRegexButton, WHITE);
DrawTextRect2(&_folderRegexButton, s.c_str());
}
else if (_target == ExcludeFileKeyboardTarget::ISTARTFOLDER)
{
_startFolder = s.c_str();
if (_startFolder.length() > 1 && _startFolder != "/") {
if (_startFolder.substr(0, 1) != "/") {
_startFolder = "/" + _startFolder;
}
if (_startFolder.substr(_startFolder.length() - 1) != "/") {
_startFolder = _startFolder + "/";
}
}
FillAreaRect(&_startFolderButton, WHITE);
DrawTextRect2(&_startFolderButton, _startFolder.c_str());
}
}

View File

@ -22,7 +22,8 @@ enum class ExcludeFileKeyboardTarget
{
IEXTENSIONS,
IREGEX,
IFOLDERREGEX
IFOLDERREGEX,
ISTARTFOLDER,
};
const int EXCLUDE_FILE_KEYBOARD_STRING_LENGHT = 90;
@ -51,6 +52,7 @@ public:
std::string getExtensionList() { return _extensionList; };
std::string getRegex() { return _regex; };
std::string getFolderRegex() { return _folderRegex; };
std::string getStartFolder() { return _startFolder; };
int getInvertMatch() { return _invertMatch; };
private:
@ -64,10 +66,12 @@ private:
irect _regexButton;
irect _invertMatchButton;
irect _folderRegexButton;
irect _startFolderButton;
ExcludeFileKeyboardTarget _target;
std::string _extensionList;
std::string _regex;
std::string _folderRegex;
std::string _startFolder;
bool _invertMatch = false;
std::string _temp;

View File

@ -41,7 +41,9 @@ WebDAVView::WebDAVView(const irect &contentRect, vector<WebDAVItem> &itemsUnfilt
std::vector<WebDAVItem>::iterator begin;
if (items.at(0).path.compare(NEXTCLOUD_ROOT_PATH) == 0)
string rootPath = WebDAV::getRootPath(false);
string parentRootPath = rootPath.substr(0, rootPath.substr(0, rootPath.length() - 1).find_last_of("/") + 1);
if (items.at(0).path.compare(parentRootPath) == 0)
{
items.erase(items.begin());
begin = items.begin();

View File

@ -100,6 +100,18 @@ void Util::decodeUrl(string &text)
curl_easy_cleanup(curl);
}
void Util::encodeUrl(string &text)
{
char *buffer;
CURL *curl = curl_easy_init();
buffer = curl_easy_escape(curl, text.c_str(), 0);
text = buffer;
curl_free(buffer);
curl_easy_cleanup(curl);
}
void kill_child(int sig)
{
//SIGKILL

View File

@ -15,6 +15,8 @@
#include "log.h"
#include <string>
using std::string;
enum class Action
{
IWriteSecret,
@ -25,7 +27,7 @@ enum class Action
IReadInt
};
const std::string CONFIG_PATH = CONFIG_FOLDER + "/nextcloud.cfg";
const std::string CONFIG_PATH = "/mnt/ext1/system/config/nextcloud/nextcloud.cfg";
class Util
{
@ -155,6 +157,13 @@ public:
*/
static void decodeUrl(std::string &text);
/**
* Encodes an URL
*
* @param text text that shall be converted
*/
static void encodeUrl(std::string &text);
/**
* Updates the library of the Pocketbook
*