Add option to ignore files and folders
parent
c88a867238
commit
6f54ccd44c
|
@ -52,6 +52,7 @@ set(SOURCES ${CMAKE_SOURCE_DIR}/src/main.cpp
|
|||
${CMAKE_SOURCE_DIR}/src/handler/contextMenu.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/handler/eventHandler.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/handler/mainMenu.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/handler/fileHandler.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/ui/listView.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/ui/listViewEntry.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/ui/webDAVView/webDAVView.cpp
|
||||
|
@ -59,6 +60,7 @@ set(SOURCES ${CMAKE_SOURCE_DIR}/src/main.cpp
|
|||
${CMAKE_SOURCE_DIR}/src/ui/loginView/loginView.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/ui/fileView/fileView.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/ui/fileView/fileViewEntry.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/ui/excludeFileView/excludeFileView.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/util/util.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/util/log.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/api/webDAV.cpp
|
||||
|
@ -78,6 +80,7 @@ include_directories(
|
|||
${CMAKE_SOURCE_DIR}/src/ui/webDAVView/
|
||||
${CMAKE_SOURCE_DIR}/src/ui/fileView/
|
||||
${CMAKE_SOURCE_DIR}/src/ui/loginView/
|
||||
${CMAKE_SOURCE_DIR}/src/ui/excludeFileView/
|
||||
${CMAKE_SOURCE_DIR}/src/api/
|
||||
)
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
#include "fileBrowser.h"
|
||||
#include "inkview.h"
|
||||
#include "fileHandler.h"
|
||||
#include "log.h"
|
||||
|
||||
#include <string>
|
||||
#include <experimental/filesystem>
|
||||
|
@ -18,6 +20,7 @@ using std::vector;
|
|||
|
||||
namespace fs = std::experimental::filesystem;
|
||||
|
||||
std::shared_ptr<FileHandler> FileBrowser::_fileHandler = std::shared_ptr<FileHandler>(new FileHandler());
|
||||
std::vector<FileItem> FileBrowser::getFileStructure(const std::string &path, const bool includeFiles, const bool includeHeader)
|
||||
{
|
||||
string localPath = path;
|
||||
|
@ -38,6 +41,7 @@ std::vector<FileItem> FileBrowser::getFileStructure(const std::string &path, con
|
|||
items.push_back(temp);
|
||||
}
|
||||
|
||||
const int storageLocationLength = _fileHandler->getStorageLocation().length();
|
||||
if (iv_access(localPath.c_str(), R_OK) == 0)
|
||||
{
|
||||
for (const auto &entry : fs::directory_iterator(localPath))
|
||||
|
@ -46,22 +50,29 @@ std::vector<FileItem> FileBrowser::getFileStructure(const std::string &path, con
|
|||
auto time = std::chrono::system_clock::to_time_t(fs::last_write_time(entry));
|
||||
temp.lastEditDate = *gmtime(&time);
|
||||
|
||||
|
||||
string directoryPath = temp.path;
|
||||
if (directoryPath.length() > storageLocationLength + 1) {
|
||||
directoryPath = directoryPath.substr(storageLocationLength + 1);
|
||||
}
|
||||
if(is_directory(entry))
|
||||
{
|
||||
temp.path = entry.path();
|
||||
temp.name = temp.path.substr(temp.path.find_last_of('/') + 1, temp.path.length());
|
||||
temp.type = Type::FFOLDER;
|
||||
if (!_fileHandler->excludeFolder(directoryPath + "/")) {
|
||||
items.push_back(temp);
|
||||
}
|
||||
}
|
||||
else if (includeFiles)
|
||||
{
|
||||
temp.path = entry.path();
|
||||
temp.name = temp.path.substr(temp.path.find_last_of('/') + 1, temp.path.length());
|
||||
temp.type = Type::FFILE;
|
||||
if (!_fileHandler->excludeFolder(directoryPath.substr(0, directoryPath.length())) || !_fileHandler->excludeFile(temp.name)) {
|
||||
items.push_back(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
|
|
@ -11,9 +11,11 @@
|
|||
#define FILEBROWSER
|
||||
|
||||
#include "fileModel.h"
|
||||
#include "fileHandler.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
class FileBrowser
|
||||
{
|
||||
|
@ -23,5 +25,7 @@ class FileBrowser
|
|||
private:
|
||||
FileBrowser(){};
|
||||
|
||||
static std::shared_ptr<FileHandler> _fileHandler;
|
||||
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#include "sqlite3.h"
|
||||
#include "log.h"
|
||||
#include "util.h"
|
||||
#include "fileHandler.h"
|
||||
#include "webDAV.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
@ -18,11 +20,13 @@ using std::string;
|
|||
|
||||
SqliteConnector::SqliteConnector(const string &DBpath) : _dbpath(DBpath)
|
||||
{
|
||||
_fileHandler = std::shared_ptr<FileHandler>(new FileHandler());
|
||||
}
|
||||
|
||||
SqliteConnector::~SqliteConnector()
|
||||
{
|
||||
sqlite3_close(_db);
|
||||
_fileHandler.reset();
|
||||
Log::writeInfoLog("closed DB");
|
||||
}
|
||||
|
||||
|
@ -119,11 +123,13 @@ std::vector<WebDAVItem> SqliteConnector::getItemsChildren(const string &parentPa
|
|||
int rs;
|
||||
sqlite3_stmt *stmt = 0;
|
||||
std::vector<WebDAVItem> items;
|
||||
std::vector<WebDAVItem> itemsToRemove;
|
||||
|
||||
rs = sqlite3_prepare_v2(_db, "SELECT title, localPath, path, size, etag, fileType, lastEditDate, type, state FROM 'metadata' WHERE path=? OR parentPath=? ORDER BY parentPath;", -1, &stmt, 0);
|
||||
rs = sqlite3_bind_text(stmt, 1, parentPath.c_str(), parentPath.length(), NULL);
|
||||
rs = sqlite3_bind_text(stmt, 2, parentPath.c_str(), parentPath.length(), NULL);
|
||||
|
||||
const int storageLocationLength = (NEXTCLOUD_ROOT_PATH + _fileHandler->getStorageUsername() + "/").length();
|
||||
while (sqlite3_step(stmt) == SQLITE_ROW)
|
||||
{
|
||||
WebDAVItem temp;
|
||||
|
@ -144,14 +150,55 @@ std::vector<WebDAVItem> SqliteConnector::getItemsChildren(const string &parentPa
|
|||
temp.state = FileState::ICLOUD;
|
||||
}
|
||||
|
||||
string direcotryPath = temp.path;
|
||||
if (direcotryPath.length() >= storageLocationLength) {
|
||||
direcotryPath = direcotryPath.substr(storageLocationLength);
|
||||
}
|
||||
if (temp.type == Itemtype::IFILE && ( _fileHandler->excludeFolder(direcotryPath) || _fileHandler->excludeFile(temp.title))) {
|
||||
//The file was previously cached and should be excluded from now on
|
||||
//TODO Maybe an SQL statement with REGEX match should be executed directly after changing the conifg
|
||||
itemsToRemove.push_back(temp);
|
||||
} else if (temp.type == Itemtype::IFOLDER && _fileHandler->excludeFolder(direcotryPath)) {
|
||||
itemsToRemove.push_back(temp);
|
||||
}
|
||||
else {
|
||||
items.push_back(temp);
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(_db);
|
||||
|
||||
for (WebDAVItem itemD : itemsToRemove) {
|
||||
if (itemD.type == Itemtype::IFOLDER) {
|
||||
deleteChildren(itemD.path);
|
||||
} else {
|
||||
deleteChild(itemD.path, itemD.title);
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
void SqliteConnector::deleteChild(const string &path, const string &title)
|
||||
{
|
||||
open();
|
||||
int rs;
|
||||
sqlite3_stmt *stmt = 0;
|
||||
rs = sqlite3_prepare_v2(_db, "DELETE FROM 'metadata' WHERE path = ? AND title = ?", -1, &stmt, 0);
|
||||
rs = sqlite3_bind_text(stmt, 1, path.c_str(), path.length(), NULL);
|
||||
rs = sqlite3_bind_text(stmt, 1, title.c_str(), title.length(), NULL);
|
||||
|
||||
rs = sqlite3_step(stmt);
|
||||
if (rs != SQLITE_DONE)
|
||||
{
|
||||
Log::writeErrorLog(std::string("An error ocurred trying to delete the item ") + sqlite3_errmsg(_db) + std::string(" (Error Code: ") + std::to_string(rs) + ")");
|
||||
}
|
||||
rs = sqlite3_clear_bindings(stmt);
|
||||
rs = sqlite3_reset(stmt);
|
||||
|
||||
}
|
||||
|
||||
void SqliteConnector::deleteChildren(const string &parentPath)
|
||||
{
|
||||
//TODO missing the onces where parentPath is one folder deeper and also destroyed
|
||||
|
|
|
@ -12,10 +12,13 @@
|
|||
|
||||
#include "webDAVModel.h"
|
||||
#include "sqlite3.h"
|
||||
#include "fileHandler.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <memory>
|
||||
|
||||
class SqliteConnector
|
||||
{
|
||||
public:
|
||||
|
@ -38,11 +41,15 @@ public:
|
|||
|
||||
void deleteChildren(const std::string &parentPath);
|
||||
|
||||
void deleteChild(const std::string &path, const std::string &title);
|
||||
|
||||
bool saveItemsChildren(const std::vector<WebDAVItem> &children);
|
||||
|
||||
private:
|
||||
std::string _dbpath;
|
||||
sqlite3 *_db;
|
||||
|
||||
std::shared_ptr<FileHandler> _fileHandler;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "util.h"
|
||||
#include "log.h"
|
||||
#include "eventHandler.h"
|
||||
#include "fileHandler.h"
|
||||
|
||||
#include <string>
|
||||
#include <experimental/filesystem>
|
||||
|
@ -37,9 +38,15 @@ WebDAV::WebDAV()
|
|||
_password = Util::accessConfig<string>(Action::IReadSecret,"password",{});
|
||||
_url = Util::accessConfig<string>(Action::IReadString, "url",{});
|
||||
_ignoreCert = Util::accessConfig<int>(Action::IReadInt, "ignoreCert",{});
|
||||
_fileHandler = std::shared_ptr<FileHandler>(new FileHandler());
|
||||
}
|
||||
}
|
||||
|
||||
WebDAV::~WebDAV()
|
||||
{
|
||||
_fileHandler.reset();
|
||||
}
|
||||
|
||||
|
||||
std::vector<WebDAVItem> WebDAV::login(const string &Url, const string &Username, const string &Pass, bool ignoreCert)
|
||||
{
|
||||
|
@ -176,7 +183,20 @@ 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 folderPath = tempItem.path;
|
||||
string prefix = NEXTCLOUD_ROOT_PATH + _username + "/";
|
||||
if (tempItem.path.find(prefix) != string::npos) {
|
||||
folderPath = tempItem.path.substr(prefix.length());
|
||||
if (tempItem.type == Itemtype::IFILE && folderPath.length() >= tempItem.title.length()) {
|
||||
folderPath = folderPath.substr(0, folderPath.length() - tempItem.title.length());
|
||||
}
|
||||
}
|
||||
|
||||
if (tempItem.type == Itemtype::IFILE && ( !_fileHandler->excludeFolder(folderPath) && !_fileHandler->excludeFile(tempItem.title) ))
|
||||
tempItems.push_back(tempItem);
|
||||
else if (tempItem.type == Itemtype::IFOLDER && !_fileHandler->excludeFolder(folderPath))
|
||||
tempItems.push_back(tempItem);
|
||||
|
||||
xmlItem = xmlItem.substr(end + endItem.length());
|
||||
begin = xmlItem.find(beginItem);
|
||||
}
|
||||
|
|
|
@ -11,11 +11,14 @@
|
|||
#define WEBDAV
|
||||
|
||||
#include "webDAVModel.h"
|
||||
#include "fileHandler.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
const std::string NEXTCLOUD_ROOT_PATH = "/remote.php/dav/files/";
|
||||
#include <memory>
|
||||
|
||||
const static std::string NEXTCLOUD_ROOT_PATH = "/remote.php/dav/files/";
|
||||
const std::string NEXTCLOUD_START_PATH = "/remote.php/";
|
||||
const std::string NEXTCLOUD_PATH = "/mnt/ext1/system/config/nextcloud";
|
||||
|
||||
|
@ -27,6 +30,7 @@ class WebDAV
|
|||
*
|
||||
*/
|
||||
WebDAV();
|
||||
~WebDAV();
|
||||
|
||||
std::vector<WebDAVItem> login(const std::string &Url, const std::string &Username, const std::string &Pass, bool ignoreCert = false);
|
||||
|
||||
|
@ -52,5 +56,7 @@ class WebDAV
|
|||
std::string _url;
|
||||
bool _ignoreCert;
|
||||
|
||||
std::shared_ptr<FileHandler> _fileHandler;
|
||||
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "fileBrowser.h"
|
||||
#include "fileView.h"
|
||||
#include "fileModel.h"
|
||||
#include "fileHandler.h"
|
||||
|
||||
#include <experimental/filesystem>
|
||||
#include <string>
|
||||
|
@ -36,6 +37,7 @@ EventHandler::EventHandler()
|
|||
//create an copy of the eventhandler to handle methods that require static functions
|
||||
_eventHandlerStatic = std::unique_ptr<EventHandler>(this);
|
||||
|
||||
_fileHandler = std::shared_ptr<FileHandler>(new FileHandler());
|
||||
_menu = std::unique_ptr<MainMenu>(new MainMenu("Nextcloud"));
|
||||
if (iv_access(CONFIG_PATH.c_str(), W_OK) == 0)
|
||||
{
|
||||
|
@ -203,8 +205,23 @@ void EventHandler::mainMenuHandler(const int index)
|
|||
Message(ICON_INFORMATION, "Info", "Reload page to see new order method in effect.", 2000);
|
||||
break;
|
||||
}
|
||||
//Select folder
|
||||
// Exclude and hide files
|
||||
case 104:
|
||||
{
|
||||
if (_fileView != nullptr) {
|
||||
_currentPath = _fileView->getCurrentEntry().path;
|
||||
_fileView.reset();
|
||||
} else {
|
||||
_currentPath = "";
|
||||
}
|
||||
|
||||
_webDAVView.reset();
|
||||
FillAreaRect(&_menu->getContentRect(), WHITE);
|
||||
_excludeFileView = std::unique_ptr<ExcludeFileView>(new ExcludeFileView(_menu->getContentRect()));
|
||||
break;
|
||||
}
|
||||
//Select folder
|
||||
case 105:
|
||||
{
|
||||
|
||||
_currentPath = _currentPath + ((_currentPath.back() != '/') ? "/nextcloud" : "nextcloud");
|
||||
|
@ -232,13 +249,13 @@ void EventHandler::mainMenuHandler(const int index)
|
|||
break;
|
||||
}
|
||||
//Info
|
||||
case 105:
|
||||
case 106:
|
||||
{
|
||||
Message(ICON_INFORMATION, "Info", "Version 1.02 \n For support please open a ticket at https://github.com/JuanJakobo/Pocketbook-Nextcloud-Client/issues", 1200);
|
||||
break;
|
||||
}
|
||||
//Exit
|
||||
case 106:
|
||||
case 107:
|
||||
CloseApp();
|
||||
break;
|
||||
default:
|
||||
|
@ -364,6 +381,42 @@ int EventHandler::pointerHandler(const int type, const int par1, const int par2)
|
|||
|
||||
return 0;
|
||||
}
|
||||
else if (_excludeFileView != nullptr) {
|
||||
int click = _excludeFileView->excludeClicked(par1, par2);
|
||||
if (click == 3) {
|
||||
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<int>(Action::IWriteInt, "ex_invertMatch", _excludeFileView->getInvertMatch());
|
||||
|
||||
_excludeFileView.reset();
|
||||
ShowHourglassForce();
|
||||
|
||||
FillAreaRect(&_menu->getContentRect(), WHITE);
|
||||
if (_currentPath != ""){
|
||||
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",{}) + '/');
|
||||
updateItems(currentWebDAVItems);
|
||||
drawWebDAVItems(currentWebDAVItems);
|
||||
}
|
||||
}
|
||||
else if (click == -1) {
|
||||
_excludeFileView.reset();
|
||||
ShowHourglassForce();
|
||||
|
||||
FillAreaRect(&_menu->getContentRect(), WHITE);
|
||||
if (_currentPath != ""){
|
||||
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",{}) + '/');
|
||||
updateItems(currentWebDAVItems);
|
||||
drawWebDAVItems(currentWebDAVItems);
|
||||
}
|
||||
}
|
||||
}
|
||||
//if loginView is shown
|
||||
else if (_loginView != nullptr)
|
||||
{
|
||||
|
@ -556,6 +609,7 @@ void EventHandler::getLocalFileStructure(std::vector<WebDAVItem> &tempItems)
|
|||
{
|
||||
vector<FileItem> currentFolder = FileBrowser::getFileStructure(localPath,true,false);
|
||||
|
||||
const int storageLocationLength = _fileHandler->getStorageLocation().length();
|
||||
for(const FileItem &local : currentFolder)
|
||||
{
|
||||
auto p = find_if(tempItems.begin()+1, tempItems.end(), [&] (const WebDAVItem &item) {return item.localPath.compare(local.path) == 0;});
|
||||
|
@ -567,16 +621,30 @@ void EventHandler::getLocalFileStructure(std::vector<WebDAVItem> &tempItems)
|
|||
temp.title = temp.localPath.substr(temp.localPath.find_last_of('/') + 1, temp.localPath.length());
|
||||
//Log::writeInfoLog(std::to_string(fs::file_size(entry)));
|
||||
temp.lastEditDate = local.lastEditDate;
|
||||
|
||||
string directoryPath = temp.localPath;
|
||||
if (directoryPath.length() > storageLocationLength) {
|
||||
directoryPath = directoryPath.substr(storageLocationLength + 1);
|
||||
}
|
||||
if(local.type == Type::FFOLDER)
|
||||
{
|
||||
if (_fileHandler->excludeFolder(directoryPath + "/")) {
|
||||
continue;
|
||||
}
|
||||
//create new dir in cloud
|
||||
temp.type = Itemtype::IFOLDER;
|
||||
}
|
||||
else
|
||||
{
|
||||
//put to cloud
|
||||
temp.fileType = "File";
|
||||
temp.type = Itemtype::IFILE;
|
||||
if (directoryPath.length() > temp.title.length()) {
|
||||
directoryPath = directoryPath.substr(0, directoryPath.length() - temp.title.length());
|
||||
}
|
||||
if (_fileHandler->excludeFolder(directoryPath) || _fileHandler->excludeFile(temp.title))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
tempItems.push_back(temp);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,10 @@
|
|||
#include "webDAVView.h"
|
||||
#include "loginView.h"
|
||||
#include "fileView.h"
|
||||
#include "excludeFileView.h"
|
||||
#include "sqliteConnector.h"
|
||||
#include "log.h"
|
||||
#include "fileHandler.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
@ -40,13 +43,17 @@ public:
|
|||
*/
|
||||
int eventDistributor(const int type, const int par1, const int par2);
|
||||
|
||||
|
||||
private:
|
||||
static std::unique_ptr<EventHandler> _eventHandlerStatic;
|
||||
std::unique_ptr<WebDAVView> _webDAVView;
|
||||
std::unique_ptr<LoginView> _loginView;
|
||||
std::unique_ptr<FileView> _fileView;
|
||||
std::unique_ptr<ExcludeFileView> _excludeFileView;
|
||||
std::unique_ptr<MainMenu> _menu;
|
||||
|
||||
std::shared_ptr<FileHandler> _fileHandler;
|
||||
|
||||
ContextMenu _contextMenu = ContextMenu();
|
||||
WebDAV _webDAV = WebDAV();
|
||||
SqliteConnector _sqllite = SqliteConnector(DB_PATH);
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
//------------------------------------------------------------------
|
||||
// fileHandler.cpp
|
||||
//
|
||||
// Author: RPJoshL
|
||||
// Date: 03.10.2022
|
||||
//
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
#include "fileHandler.h"
|
||||
#include "log.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <regex>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
using std::string;
|
||||
using std::find;
|
||||
using std::regex;
|
||||
|
||||
std::vector<FileHandler*> FileHandler::_instances;
|
||||
FileHandler::FileHandler()
|
||||
{
|
||||
_instances.push_back(this);
|
||||
|
||||
parseConfig(
|
||||
Util::getConfig<string>("ex_pattern", ""),
|
||||
Util::getConfig<string>("ex_folderPattern", ""),
|
||||
Util::getConfig<string>("ex_extensionList", ""),
|
||||
Util::getConfig<int>("ex_invertMatch", 0)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
void FileHandler::parseConfig(string regex, string folderRegex, string extensions, int invertMatch) {
|
||||
_extensions.clear();
|
||||
// split the comma seperated string
|
||||
if (!extensions.empty()) {
|
||||
string line;
|
||||
|
||||
std::stringstream ss(extensions);
|
||||
while(getline(ss, line, ',')) {
|
||||
_extensions.push_back(line);
|
||||
}
|
||||
}
|
||||
|
||||
// parse the regex only onces
|
||||
if (!regex.empty()) {
|
||||
try {
|
||||
_regex = std::regex(regex);
|
||||
_useRegex = true;
|
||||
} catch(std::regex_error err) {
|
||||
Log::writeErrorLog("Unable to parse regex '" + regex + "' for file: " + err.what());
|
||||
}
|
||||
} else {
|
||||
_useRegex = false;
|
||||
}
|
||||
|
||||
if (!folderRegex.empty()) {
|
||||
try {
|
||||
_folderRegex = std::regex(folderRegex);
|
||||
_useFolderRegex = true;
|
||||
} catch(std::regex_error err) {
|
||||
Log::writeErrorLog("Unable to parse regex '" + folderRegex + "' for folder: " + err.what());
|
||||
}
|
||||
} else {
|
||||
_useFolderRegex = false;
|
||||
}
|
||||
|
||||
_invertMatch = invertMatch;
|
||||
}
|
||||
|
||||
FileHandler::~FileHandler()
|
||||
{
|
||||
_instances.erase(std::remove(_instances.begin(), _instances.end(), this), _instances.end());
|
||||
}
|
||||
|
||||
bool FileHandler::excludeFile(std::string filename) {
|
||||
|
||||
// check for file extensions
|
||||
if (!_extensions.empty()) {
|
||||
int indexOfDot = filename.find_last_of(".");
|
||||
if (indexOfDot != std::string::npos && filename.length() > indexOfDot + 1) {
|
||||
string extension = filename.substr(filename.find_last_of(".") + 1);
|
||||
if(std::find(_extensions.begin(),_extensions.end(), extension) != _extensions.end()) {
|
||||
return !_invertMatch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_useRegex) {
|
||||
try {
|
||||
bool t = std::regex_match(filename, _regex) != _invertMatch;
|
||||
string ta = t ? "true" : "false";
|
||||
return t;
|
||||
} catch (std::regex_error err) {
|
||||
string errM = err.what();
|
||||
Log::writeErrorLog("Unable to parse regex for file:'" + errM);
|
||||
}
|
||||
}
|
||||
|
||||
return _invertMatch;
|
||||
}
|
||||
|
||||
bool FileHandler::excludeFolder(std::string folderName) {
|
||||
folderName = "/" + folderName;
|
||||
|
||||
// always display root folder because that can't be matched
|
||||
if (folderName == "/" || folderName == "//") {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_useFolderRegex) {
|
||||
try {
|
||||
bool t = std::regex_match(folderName, _folderRegex) != _invertMatch;
|
||||
return t;
|
||||
} catch (std::regex_error err) {
|
||||
string errM = err.what();
|
||||
Log::writeErrorLog("Unable to parse regex for folder:'" + errM);
|
||||
}
|
||||
}
|
||||
|
||||
return _invertMatch;
|
||||
}
|
||||
|
||||
void FileHandler::update(string regex, string folderRegex, string extensions, int invertMatch) {
|
||||
for (FileHandler *handler : _instances) {
|
||||
handler->parseConfig(regex, folderRegex, extensions, invertMatch);
|
||||
}
|
||||
}
|
||||
|
||||
string FileHandler::getStorageLocation() {
|
||||
return Util::accessConfig<string>(Action::IReadString, "storageLocation",{}) + getStorageUsername() + "/";
|
||||
}
|
||||
string FileHandler::getStorageUsername() {
|
||||
return Util::accessConfig<string>(Action::IReadString, "username",{});
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
//------------------------------------------------------------------
|
||||
// fileHandler.h
|
||||
//
|
||||
// Author: RPJoshL
|
||||
// Date: 03.10.2022
|
||||
//
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
#ifndef FILEHANDLER
|
||||
#define FILEHANDLER
|
||||
|
||||
#include <regex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <memory>
|
||||
|
||||
class FileHandler
|
||||
{
|
||||
public:
|
||||
FileHandler();
|
||||
~FileHandler();
|
||||
bool excludeFile(std::string filename);
|
||||
bool excludeFolder(std::string foldername);
|
||||
|
||||
std::string getStorageLocation();
|
||||
std::string getStorageUsername();
|
||||
static void update(std::string regex, std::string folderRegex, std::string extensions, int invertMatch);
|
||||
|
||||
private:
|
||||
std::regex _regex;
|
||||
std::regex _folderRegex;
|
||||
// can't use pointers with regex... Why? -> unable to null check
|
||||
bool _useRegex = false;
|
||||
bool _useFolderRegex = false;
|
||||
std::vector<std::string> _extensions;
|
||||
bool _invertMatch;
|
||||
|
||||
void parseConfig(std::string regex, std::string folderRegex, std::string extensions, int invertMatch);
|
||||
static std::vector<FileHandler *> _instances;
|
||||
|
||||
};
|
||||
#endif
|
|
@ -42,6 +42,7 @@ MainMenu::~MainMenu()
|
|||
free(_menu);
|
||||
free(_logout);
|
||||
free(_sortBy);
|
||||
free(_excludeFiles);
|
||||
free(_info);
|
||||
free(_exit);
|
||||
free(_chooseFolder);
|
||||
|
@ -61,14 +62,15 @@ 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, 103, _sortBy, NULL},
|
||||
{loggedIn ? (short)ITEM_ACTIVE : (short)ITEM_HIDDEN, 104, _excludeFiles, NULL},
|
||||
//show if filePicker is shown
|
||||
{filePicker ? (short)ITEM_ACTIVE : (short)ITEM_HIDDEN, 104, _chooseFolder, NULL},
|
||||
{filePicker ? (short)ITEM_ACTIVE : (short)ITEM_HIDDEN, 105, _chooseFolder, NULL},
|
||||
//show always
|
||||
{ITEM_ACTIVE, 105, _info, NULL},
|
||||
{ITEM_ACTIVE, 106, _info, NULL},
|
||||
//show logged in
|
||||
{loggedIn ? (short)ITEM_ACTIVE : (short)ITEM_HIDDEN, 102, _logout, NULL},
|
||||
//show always
|
||||
{ITEM_ACTIVE, 106, _exit, NULL},
|
||||
{ITEM_ACTIVE, 107, _exit, NULL},
|
||||
{0, 0, NULL, NULL}};
|
||||
|
||||
OpenMenu(mainMenu, 0, _panelMenuBeginX, _panelMenuBeginY, handler);
|
||||
|
|
|
@ -55,6 +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 *_info = strdup("Info");
|
||||
char *_exit = strdup("Close App");
|
||||
|
||||
|
|
|
@ -0,0 +1,200 @@
|
|||
//------------------------------------------------------------------
|
||||
// excludeFileView.cpp
|
||||
//
|
||||
// Author: RPJoshL
|
||||
// Date: 03.10.2022
|
||||
//
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
#include "excludeFileView.h"
|
||||
#include "log.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <regex>
|
||||
|
||||
using std::string;
|
||||
|
||||
std::shared_ptr<ExcludeFileView> ExcludeFileView::_excludeFileViewStatic;
|
||||
ExcludeFileView::ExcludeFileView(const irect &contentRect): _contentRect(contentRect)
|
||||
{
|
||||
_excludeFileViewStatic.reset(this);
|
||||
|
||||
_extensionList = Util::getConfig<string>("ex_extensionList", "");
|
||||
_regex = Util::getConfig<string>("ex_pattern", "");
|
||||
_folderRegex = Util::getConfig<string>("ex_folderPattern", "");
|
||||
_invertMatch = Util::getConfig<int>("ex_invertMatch",0);
|
||||
|
||||
int contentHeight = contentRect.h / 2;
|
||||
int contentWidth = _contentRect.w * 0.9;
|
||||
int checkBoxWidth = _contentRect.w * 0.1;
|
||||
|
||||
int beginY = 0.4 * contentHeight;
|
||||
int beginX = (_contentRect.w - contentWidth) / 2;
|
||||
|
||||
int contents = contentHeight / 7;
|
||||
|
||||
_fontHeight = contents / 2;
|
||||
|
||||
_font = OpenFont("LiberationMono", _fontHeight, FONT_STD);
|
||||
SetFont(_font, BLACK);
|
||||
FillAreaRect(&_contentRect, WHITE);
|
||||
|
||||
_extensionListButton = iRect(beginX, beginY, contentWidth, contents, ALIGN_CENTER);
|
||||
DrawTextRect(_extensionListButton.x, _extensionListButton.y - _fontHeight - _fontHeight/2, _extensionListButton.w, _extensionListButton.h, "Extensions:", ALIGN_LEFT);
|
||||
DrawString(_extensionListButton.x, _extensionListButton.y, _extensionList.c_str());
|
||||
DrawRect(_extensionListButton.x - 1, _extensionListButton.y - 1, _extensionListButton.w + 2, _extensionListButton.h + 2, BLACK);
|
||||
|
||||
_regexButton = iRect(beginX, beginY + 2 * contents, contentWidth, contents, ALIGN_CENTER);
|
||||
DrawTextRect(_regexButton.x, _regexButton.y - _fontHeight - _fontHeight/3, _regexButton.w, _regexButton.h, "File-Regex:", ALIGN_LEFT);
|
||||
DrawString(_regexButton.x, _regexButton.y, _regex.c_str());
|
||||
DrawRect(_regexButton.x - 1, _regexButton.y - 1, _regexButton.w + 2, _regexButton.h + 2, BLACK);
|
||||
|
||||
_folderRegexButton = iRect(beginX, beginY + 4 * contents, contentWidth, contents, ALIGN_CENTER);
|
||||
DrawTextRect(_folderRegexButton.x, _folderRegexButton.y - _fontHeight - _fontHeight/3, _folderRegexButton.w, _folderRegexButton.h, "Folder-Regex:", ALIGN_LEFT);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
FillAreaRect(&_cancelButton, BLACK);
|
||||
SetFont(_font, WHITE);
|
||||
DrawTextRect2(&_cancelButton, "Cancel");
|
||||
PartialUpdate(_contentRect.x, _contentRect.y, _contentRect.w, _contentRect.h);
|
||||
}
|
||||
|
||||
ExcludeFileView::~ExcludeFileView()
|
||||
{
|
||||
CloseFont(_font);
|
||||
}
|
||||
|
||||
int ExcludeFileView::excludeClicked(int x, int y)
|
||||
{
|
||||
_temp = "";
|
||||
|
||||
if (IsInRect(x, y, &_extensionListButton))
|
||||
{
|
||||
_target = ExcludeFileKeyboardTarget::IEXTENSIONS;
|
||||
if (!_extensionList.empty())
|
||||
_temp = _extensionList;
|
||||
_temp.resize(EXCLUDE_FILE_KEYBOARD_STRING_LENGHT);
|
||||
OpenKeyboard("docx,pdf,sdr", &_temp[0], EXCLUDE_FILE_KEYBOARD_STRING_LENGHT - 1, KBD_NORMAL, &keyboardHandlerStatic);
|
||||
return 1;
|
||||
}
|
||||
else if (IsInRect(x, y, &_regexButton))
|
||||
{
|
||||
_target = ExcludeFileKeyboardTarget::IREGEX;
|
||||
if (!_regex.empty())
|
||||
_temp = _regex;
|
||||
_temp.resize(EXCLUDE_FILE_KEYBOARD_STRING_LENGHT);
|
||||
OpenKeyboard("Pre.*Post\\.pdf", &_temp[0], EXCLUDE_FILE_KEYBOARD_STRING_LENGHT, KBD_NORMAL, &keyboardHandlerStatic);
|
||||
return 1;
|
||||
}
|
||||
else if (IsInRect(x, y, &_folderRegexButton))
|
||||
{
|
||||
_target = ExcludeFileKeyboardTarget::IFOLDERREGEX;
|
||||
if (!_folderRegex.empty())
|
||||
_temp = _folderRegex;
|
||||
_temp.resize(EXCLUDE_FILE_KEYBOARD_STRING_LENGHT);
|
||||
OpenKeyboard("/root/.*/test/", &_temp[0], EXCLUDE_FILE_KEYBOARD_STRING_LENGHT, KBD_NORMAL, &keyboardHandlerStatic);
|
||||
return 1;
|
||||
}
|
||||
else if (IsInRect(x, y, &_invertMatchButton))
|
||||
{
|
||||
_invertMatch = !_invertMatch;
|
||||
FillAreaRect(&_invertMatchButton, WHITE);
|
||||
if(_invertMatch)
|
||||
FillArea(_invertMatchButton.x - 1, _invertMatchButton.y - 1, _invertMatchButton.w + 2, _invertMatchButton.h + 2, BLACK);
|
||||
else
|
||||
DrawRect(_invertMatchButton.x - 1, _invertMatchButton.y - 1, _invertMatchButton.w + 2, _invertMatchButton.h + 2, BLACK);
|
||||
|
||||
PartialUpdate(_invertMatchButton.x, _invertMatchButton.y, _invertMatchButton.w, _invertMatchButton.h);
|
||||
|
||||
return 1;
|
||||
}
|
||||
else if (IsInRect(x, y, &_saveButton))
|
||||
{
|
||||
if (!_regex.empty()) {
|
||||
try {
|
||||
std::regex regP = std::regex(_regex);
|
||||
} catch(std::regex_error err) {
|
||||
Log::writeErrorLog("Unable to parse regex '" + _regex + "': " + err.what());
|
||||
Message(ICON_ERROR, "Error", "Unable to parse the regex for the files.", 1200);
|
||||
return 1;
|
||||
} catch(...) {
|
||||
Message(ICON_ERROR, "Error", "Unknown error occured while parsing the regex for the files.", 1200);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_folderRegex.empty()) {
|
||||
try {
|
||||
std::regex regP = std::regex(_folderRegex);
|
||||
} catch(std::regex_error err) {
|
||||
Log::writeErrorLog("Unable to parse regex for folder '" + _folderRegex + "': " + err.what());
|
||||
Message(ICON_ERROR, "Error", "Unable to parse the regex for the folders.", 1200);
|
||||
return 1;
|
||||
} catch(...) {
|
||||
Message(ICON_ERROR, "Error", "Unknown error occured while parsing the regex for the folders.", 1200);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
FileHandler::update(_regex, _folderRegex, _extensionList, _invertMatch);
|
||||
|
||||
return 3;
|
||||
}
|
||||
else if (IsInRect(x, y, &_cancelButton))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ExcludeFileView::keyboardHandlerStatic(char *text)
|
||||
{
|
||||
if (_excludeFileViewStatic != nullptr) {
|
||||
_excludeFileViewStatic->keyboardHandler(text);
|
||||
}
|
||||
}
|
||||
|
||||
void ExcludeFileView::keyboardHandler(char *text)
|
||||
{
|
||||
if (!text)
|
||||
return;
|
||||
|
||||
string s(text);
|
||||
if (s.empty())
|
||||
return;
|
||||
|
||||
if (_target == ExcludeFileKeyboardTarget::IEXTENSIONS)
|
||||
{
|
||||
_extensionList = s.c_str();
|
||||
FillAreaRect(&_extensionListButton, WHITE);
|
||||
DrawTextRect2(&_extensionListButton, s.c_str());
|
||||
}
|
||||
else if (_target == ExcludeFileKeyboardTarget::IREGEX)
|
||||
{
|
||||
_regex = s.c_str();
|
||||
FillAreaRect(&_regexButton, WHITE);
|
||||
DrawTextRect2(&_regexButton, s.c_str());
|
||||
}
|
||||
else if (_target == ExcludeFileKeyboardTarget::IFOLDERREGEX)
|
||||
{
|
||||
_folderRegex = s.c_str();
|
||||
FillAreaRect(&_folderRegexButton, WHITE);
|
||||
DrawTextRect2(&_folderRegexButton, s.c_str());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
//------------------------------------------------------------------
|
||||
// excludeFileView.h
|
||||
//
|
||||
// Author: RPJoshL
|
||||
// Date: 03.10.2022
|
||||
//
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifndef EXCLUDEFILEVIEW
|
||||
#define EXCLUDEFILEVIEW
|
||||
|
||||
using std::string;
|
||||
|
||||
#include "inkview.h"
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
enum class ExcludeFileKeyboardTarget
|
||||
{
|
||||
IEXTENSIONS,
|
||||
IREGEX,
|
||||
IFOLDERREGEX
|
||||
};
|
||||
|
||||
const int EXCLUDE_FILE_KEYBOARD_STRING_LENGHT = 90;
|
||||
|
||||
class ExcludeFileView
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Draws the excludeFileView including an textfield with Extension list and regex, checkbox for inverting the "excluding" and the
|
||||
* save and cancel button inside the contentRect
|
||||
*
|
||||
* @param contentRect area where the excludeFileView shall be drawn
|
||||
*/
|
||||
ExcludeFileView(const irect &contentRect);
|
||||
~ExcludeFileView();
|
||||
|
||||
/**
|
||||
* Checks which part of the view is shown and reacts accordingly
|
||||
*
|
||||
* @param x x-coordinate
|
||||
* @param y y-coordinate
|
||||
* @return int if event has been handled. Returns 2 if save has been clicked and all items are set, or -1 when cancel was fired
|
||||
*/
|
||||
int excludeClicked(int x, int y);
|
||||
|
||||
std::string getExtensionList() { return _extensionList; };
|
||||
std::string getRegex() { return _regex; };
|
||||
std::string getFolderRegex() { return _folderRegex; };
|
||||
int getInvertMatch() { return _invertMatch; };
|
||||
|
||||
private:
|
||||
static std::shared_ptr<ExcludeFileView> _excludeFileViewStatic;
|
||||
int _fontHeight;
|
||||
ifont *_font;
|
||||
const irect _contentRect;
|
||||
irect _saveButton;
|
||||
irect _cancelButton;
|
||||
irect _extensionListButton;
|
||||
irect _regexButton;
|
||||
irect _invertMatchButton;
|
||||
irect _folderRegexButton;
|
||||
ExcludeFileKeyboardTarget _target;
|
||||
std::string _extensionList;
|
||||
std::string _regex;
|
||||
std::string _folderRegex;
|
||||
bool _invertMatch = false;
|
||||
std::string _temp;
|
||||
|
||||
/**
|
||||
* Functions needed to call C function, handles the keyboard
|
||||
*
|
||||
* @param text text that has been typed in by the user
|
||||
*/
|
||||
static void keyboardHandlerStatic(char *text);
|
||||
|
||||
/**
|
||||
* Called by the static method and saves and writes the input from the user to the screen
|
||||
*
|
||||
* @param text text that has been typed in by the user
|
||||
*/
|
||||
void keyboardHandler(char *text);
|
||||
};
|
||||
#endif
|
|
@ -108,6 +108,35 @@ public:
|
|||
return returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the value from the config file
|
||||
* T defines the type of the item (e.g. int, string etc.)
|
||||
*
|
||||
* @param name of the requested item
|
||||
* @param defaultValue value to return when no was found
|
||||
*
|
||||
* @return value from config
|
||||
*/
|
||||
template <typename T>
|
||||
static T getConfig(string name, T defaultValue)
|
||||
{
|
||||
iconfigedit *temp = nullptr;
|
||||
iconfig *config = OpenConfig(CONFIG_PATH.c_str(), temp);
|
||||
T returnValue;
|
||||
|
||||
if constexpr(std::is_same<T, std::string>::value)
|
||||
{
|
||||
returnValue = ReadString(config, name.c_str(), ((std::string) defaultValue).c_str());
|
||||
}
|
||||
else if constexpr(std::is_same<T, int>::value)
|
||||
{
|
||||
returnValue = ReadInt(config, name.c_str(), defaultValue);
|
||||
}
|
||||
CloseConfig(config);
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an integer representing the download progress
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue