diff --git a/.gitignore b/.gitignore
index e60dcfd..684ef9c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,4 +32,5 @@
*.app
build/
+debug/
.cache/
diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
old mode 100644
new mode 100755
index 8ddeeb0..4428452
--- a/.vscode/c_cpp_properties.json
+++ b/.vscode/c_cpp_properties.json
@@ -1,14 +1,24 @@
{
"configurations": [
{
- "name": "Linux",
+ "name": "linux-gcc-x64",
"includePath": [
- "${default}"
+ "${workspaceFolder}/**",
+ "${default}",
+ "/usr/include/**"
],
- "defines": [],
- "compilerPath": "/usr/bin/clang",
- "intelliSenseMode": "linux-clang-x64"
+ "compilerPath": "/usr/bin/gcc",
+ "cStandard": "c99",
+ "cppStandard": "c++17",
+ "intelliSenseMode": "linux-gcc-x64",
+ "compilerArgs": [
+ ""
+ ],
+ "configurationProvider": "ms-vscode.cmake-tools",
+ "browse": {
+ "limitSymbolsToIncludedHeaders": true
+ }
}
],
"version": 4
-}
\ No newline at end of file
+}
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100755
index 0000000..b45e098
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,25 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "C/C++ Runner: Debug Session",
+ "type": "cppdbg",
+ "request": "launch",
+ "args": [],
+ "stopAtEntry": false,
+ "externalConsole": false,
+ "cwd": "/home/crylia/Dokumente/git/QutieFM_ref",
+ "program": "/home/crylia/Dokumente/git/QutieFM_ref/build/Debug/outDebug",
+ "MIMode": "gdb",
+ "miDebuggerPath": "gdb",
+ "setupCommands": [
+ {
+ "description": "Enable pretty-printing for gdb",
+ "text": "-enable-pretty-printing",
+ "ignoreFailures": true
+ }
+ ],
+ "visualizerFile": "/home/crylia/.config/Code/User/workspaceStorage/086fea89ac5a7d8a91ed9ed2242bec2f/tonka3000.qtvsctools/qt.natvis.xml"
+ }
+ ]
+}
diff --git a/.vscode/settings.json b/.vscode/settings.json
old mode 100644
new mode 100755
index 08cc22f..7624880
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,83 +1,59 @@
{
- "files.associations": {
- "cctype": "cpp",
- "cmath": "cpp",
- "cstdarg": "cpp",
- "cstddef": "cpp",
- "cstdio": "cpp",
- "cstdlib": "cpp",
- "cstring": "cpp",
- "ctime": "cpp",
- "cwchar": "cpp",
- "cwctype": "cpp",
- "array": "cpp",
- "atomic": "cpp",
- "bit": "cpp",
- "*.tcc": "cpp",
- "bitset": "cpp",
- "charconv": "cpp",
- "chrono": "cpp",
- "cinttypes": "cpp",
- "clocale": "cpp",
- "codecvt": "cpp",
- "compare": "cpp",
- "concepts": "cpp",
- "condition_variable": "cpp",
- "cstdint": "cpp",
- "deque": "cpp",
- "list": "cpp",
- "map": "cpp",
- "set": "cpp",
- "string": "cpp",
- "unordered_map": "cpp",
- "unordered_set": "cpp",
- "vector": "cpp",
- "exception": "cpp",
- "algorithm": "cpp",
- "functional": "cpp",
- "iterator": "cpp",
- "memory": "cpp",
- "memory_resource": "cpp",
- "numeric": "cpp",
- "optional": "cpp",
- "random": "cpp",
- "ratio": "cpp",
- "string_view": "cpp",
- "system_error": "cpp",
- "tuple": "cpp",
- "type_traits": "cpp",
- "utility": "cpp",
- "format": "cpp",
- "future": "cpp",
- "initializer_list": "cpp",
- "iomanip": "cpp",
- "iosfwd": "cpp",
- "istream": "cpp",
- "limits": "cpp",
- "mutex": "cpp",
- "new": "cpp",
- "numbers": "cpp",
- "ostream": "cpp",
- "semaphore": "cpp",
- "span": "cpp",
- "sstream": "cpp",
- "stdexcept": "cpp",
- "stdfloat": "cpp",
- "stop_token": "cpp",
- "streambuf": "cpp",
- "text_encoding": "cpp",
- "thread": "cpp",
- "typeinfo": "cpp",
- "variant": "cpp",
- "__bit_reference": "cpp",
- "__config": "cpp",
- "__hash_table": "cpp",
- "__locale": "cpp",
- "__node_handle": "cpp",
- "__split_buffer": "cpp",
- "__threading_support": "cpp",
- "__verbose_abort": "cpp",
- "ios": "cpp",
- "locale": "cpp"
- }
-}
+ "C_Cpp_Runner.cCompilerPath": "gcc",
+ "C_Cpp_Runner.cppCompilerPath": "g++",
+ "C_Cpp_Runner.debuggerPath": "gdb",
+ "C_Cpp_Runner.cStandard": "c99",
+ "C_Cpp_Runner.cppStandard": "c++17",
+ "C_Cpp_Runner.msvcBatchPath": "",
+ "C_Cpp_Runner.useMsvc": false,
+ "C_Cpp_Runner.warnings": [
+ "-Wall",
+ "-Wextra",
+ "-Wpedantic",
+ "-Wshadow",
+ "-Wformat=2",
+ "-Wcast-align",
+ "-Wconversion",
+ "-Wsign-conversion",
+ "-Wnull-dereference"
+ ],
+ "C_Cpp_Runner.msvcWarnings": [
+ "/W4",
+ "/permissive-",
+ "/w14242",
+ "/w14287",
+ "/w14296",
+ "/w14311",
+ "/w14826",
+ "/w44062",
+ "/w44242",
+ "/w14905",
+ "/w14906",
+ "/w14263",
+ "/w44265",
+ "/w14928"
+ ],
+ "C_Cpp_Runner.enableWarnings": true,
+ "C_Cpp_Runner.warningsAsError": false,
+ "C_Cpp_Runner.compilerArgs": [],
+ "C_Cpp_Runner.linkerArgs": [],
+ "C_Cpp_Runner.includePaths": [],
+ "C_Cpp_Runner.includeSearch": [
+ "*",
+ "**/*"
+ ],
+ "C_Cpp_Runner.excludeSearch": [
+ "**/build",
+ "**/build/**",
+ "**/.*",
+ "**/.*/**",
+ "**/.vscode",
+ "**/.vscode/**"
+ ],
+ "C_Cpp_Runner.useAddressSanitizer": false,
+ "C_Cpp_Runner.useUndefinedSanitizer": false,
+ "C_Cpp_Runner.useLeakSanitizer": false,
+ "C_Cpp_Runner.showCompilationTime": false,
+ "C_Cpp_Runner.useLinkTimeOptimization": false,
+ "C_Cpp_Runner.msvcSecureNoWarnings": false
+}
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
old mode 100644
new mode 100755
diff --git a/assets/icons/android-studio.svg b/assets/icons/android-studio.svg
new file mode 100644
index 0000000..0c2d27a
--- /dev/null
+++ b/assets/icons/android-studio.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/chevron-left.png b/assets/icons/chevron-left.png
new file mode 100755
index 0000000..e6f065d
Binary files /dev/null and b/assets/icons/chevron-left.png differ
diff --git a/assets/icons/chevron-left.svg b/assets/icons/chevron-left.svg
new file mode 100755
index 0000000..75dcd62
--- /dev/null
+++ b/assets/icons/chevron-left.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/chevron-right.png b/assets/icons/chevron-right.png
new file mode 100755
index 0000000..3ad907b
Binary files /dev/null and b/assets/icons/chevron-right.png differ
diff --git a/assets/icons/chevron-right.svg b/assets/icons/chevron-right.svg
new file mode 100755
index 0000000..a763cfd
--- /dev/null
+++ b/assets/icons/chevron-right.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/delete.svg b/assets/icons/delete.svg
new file mode 100644
index 0000000..21c80c2
--- /dev/null
+++ b/assets/icons/delete.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/download.svg b/assets/icons/download.svg
new file mode 100644
index 0000000..2cfe720
--- /dev/null
+++ b/assets/icons/download.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/file-document-outline.svg b/assets/icons/file-document-outline.svg
new file mode 100644
index 0000000..bbae024
--- /dev/null
+++ b/assets/icons/file-document-outline.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/folder-account.svg b/assets/icons/folder-account.svg
new file mode 100644
index 0000000..84b7d2f
--- /dev/null
+++ b/assets/icons/folder-account.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/home.svg b/assets/icons/home.svg
new file mode 100644
index 0000000..ccee5c3
--- /dev/null
+++ b/assets/icons/home.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/image.svg b/assets/icons/image.svg
new file mode 100644
index 0000000..f0dd157
--- /dev/null
+++ b/assets/icons/image.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/monitor.svg b/assets/icons/monitor.svg
new file mode 100644
index 0000000..024553c
--- /dev/null
+++ b/assets/icons/monitor.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/music-note.svg b/assets/icons/music-note.svg
new file mode 100644
index 0000000..aa1ecf9
--- /dev/null
+++ b/assets/icons/music-note.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/video-outline.svg b/assets/icons/video-outline.svg
new file mode 100644
index 0000000..ad1f03b
--- /dev/null
+++ b/assets/icons/video-outline.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/resources.qrc b/assets/resources.qrc
new file mode 100755
index 0000000..792d140
--- /dev/null
+++ b/assets/resources.qrc
@@ -0,0 +1,5 @@
+
+
+ icons/
+
+
diff --git a/src/Controller/FileController/FileController.cpp b/src/Controller/FileController/FileController.cpp
deleted file mode 100644
index 7f6a1a6..0000000
--- a/src/Controller/FileController/FileController.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-#include "FileController.hpp"
-#include
-#include
-#include
-#include
-#include
-
-FileController::FileController( ) {
- m_fmWorker = std::make_shared(
- std::chrono::milliseconds(1000));
- m_fmWorker->moveToThread(&m_fsThread);
-
- // starts the directory monitoring thread, forgot why it has to be a signal, only works this way not with a direct call
- connect(this, &FileController::operate, m_fmWorker.get( ),
- &FileMonitor::start);
- // main signal to populate the file grid, passes the path and event each time a file is deleted, created or updated
- connect(m_fmWorker.get( ), &FileMonitor::changed, this,
- &FileController::update);
- // Propagating signal from the monitor that fires when the path is changed
- connect(m_fmWorker.get( ), &FileMonitor::pathChanged, this,
- &FileController::newPath);
-#ifdef _WIN32
- m_fmWorker.get( )->SetPath(std::filesystem::path(std::getenv("USERPROFILE")));
-#else
- m_fmWorker.get( )->SetPath(std::filesystem::path(std::getenv("HOME")));
-#endif
- // Signal to update the path, when fired passes the new path and will be given to the monitor
- connect(this, &FileController::updatePath, this, [this](std::filesystem::path p) {
- previousPaths.push(m_fmWorker.get( )->GetPath( ));
- m_fmWorker.get( )->SetPath(p);
- });
- connect(this, &FileController::previousPath, this, [this]( ) {
- if (previousPaths.empty( )) return;
-
- m_fmWorker.get( )->SetPath(previousPaths.top( ));
- previousPaths.pop( );
- });
- m_fsThread.start( );
-
- emit operate( );
-}
-
-FileController::~FileController( ) {
- m_fsThread.quit( );
- m_fmWorker.get( )->stop( );
- m_fsThread.wait( );
-}
-
-void FileController::newPath(const std::filesystem::path p) {
- emit pathChanged(p);
-}
-
-void FileController::update(const std::filesystem::path path,
- const FileEvent event) {
- emit contentChanged(path, event);
-}
diff --git a/src/Controller/FileController/FileController.hpp b/src/Controller/FileController/FileController.hpp
deleted file mode 100644
index ae46bbc..0000000
--- a/src/Controller/FileController/FileController.hpp
+++ /dev/null
@@ -1,51 +0,0 @@
-#pragma once
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "../../Core/FileMonitor/FileMonitor.hpp"
-
-class FileController : public QObject {
- Q_OBJECT
-public:
- // Static method to access the singleton instance
- static FileController* instance( ) {
- static FileController instance;
- return &instance;
- }
-
- // Deleting the copy constructor and assignment operator to prevent copying
- FileController(const FileController&) = delete;
- FileController& operator=(const FileController&) = delete;
-
- std::stack previousPaths;
-
-private:
- // Private constructor to prevent instantiation
- FileController( );
- ~FileController( );
-
-private:
- QThread m_fsThread;
- std::shared_ptr m_fmWorker;
-
-private slots:
- void update(const std::filesystem::path path, const FileEvent event);
- void newPath(const std::filesystem::path p);
-
-signals:
- // Start signal to start the function in the thread
- void operate( );
- // Stop signal to stop the function in the thread
- void pause( );
- // Signal to update the path inside the thread
- void updatePath(const std::filesystem::path& p);
-
- void pathChanged(const std::filesystem::path p);
- void contentChanged(std::filesystem::path path, FileEvent event);
- void previousPath( );
-};
diff --git a/src/Core/FileMonitor/FileMonitor.cpp b/src/Core/FileMonitor/FileMonitor.cpp
deleted file mode 100644
index 0deda93..0000000
--- a/src/Core/FileMonitor/FileMonitor.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-#include "FileMonitor.hpp"
-#include
-#include
-#include
-
-FileMonitor::FileMonitor(std::chrono::duration delay)
- : m_delay(delay) { }
-
-void FileMonitor::SetPath(std::filesystem::path newPath) {
- m_path = newPath;
- emit pathChanged(m_path);
- initPathsMap( );
-}
-
-void FileMonitor::initPathsMap( ) {
- m_paths.clear( );
-}
-
-bool FileMonitor::is_hidden(const std::filesystem::path& p) {
-#ifdef _WIN32
- DWORD attrs = GetFileAttributes(p.c_str( ));
- if (attrs == INVALID_FILE_ATTRIBUTES) {
- throw std::runtime_error("Error getting file attributes");
- }
- return (attrs & FILE_ATTRIBUTE_HIDDEN);
-#elif __unix__
- return p.filename( ).string( ).front( ) == '.';
-#endif
- return false;
-}
-
-void FileMonitor::start( ) {
- while (m_running) {
- std::this_thread::sleep_for(m_delay);
-
- auto pbegin = m_paths.begin( );
- while (pbegin != m_paths.end( )) {
- if (!std::filesystem::exists(pbegin->first)) {
- emit changed(pbegin->first, FileEvent::erased);
- pbegin = m_paths.erase(pbegin);
- } else
- pbegin++;
- }
- try {
- for (auto& file : std::filesystem::directory_iterator(m_path)) {
- std::filesystem::file_time_type curr_file_last_write;
- if (!file.is_symlink( )) {
- curr_file_last_write = std::filesystem::last_write_time(file);
- } else {
- curr_file_last_write = std::filesystem::file_time_type(std::chrono::nanoseconds(0));
- }
-
-
- if (!is_hidden(file)) {
- if (!contains(file.path( ))) {
- m_paths[file.path( )] = curr_file_last_write;
- emit changed(file.path( ), FileEvent::created);
- } else {
- if (m_paths[file.path( )] != curr_file_last_write) {
- m_paths[file.path( )] = curr_file_last_write;
- emit changed(file.path( ), FileEvent::modified);
- }
- }
- }
- }
- }
- catch (std::filesystem::filesystem_error err) {
- std::cout << err.what( ) << std::endl;
- }
- }
-}
-
-void FileMonitor::stop( ) { m_running = false; }
-
-bool FileMonitor::contains(const std::filesystem::path& key) {
- return m_paths.find(key) != m_paths.end( );
-}
diff --git a/src/Core/FileMonitor/FileMonitor.hpp b/src/Core/FileMonitor/FileMonitor.hpp
deleted file mode 100644
index 2018294..0000000
--- a/src/Core/FileMonitor/FileMonitor.hpp
+++ /dev/null
@@ -1,49 +0,0 @@
-#pragma once
-
-#include
-#include
-#include
-#include
-
-#ifdef _WIN32
-#include
-#elif __unix__
-#include
-#endif
-
-enum class FileEvent { created, modified, erased };
-
-class FileMonitor : public QObject {
- Q_OBJECT
-public:
- std::chrono::duration m_delay;
-
- FileMonitor(std::chrono::duration delay);
- ~FileMonitor( ) = default;
-
- void SetPath(std::filesystem::path path);
- std::filesystem::path GetPath( ) {
- return m_path;
- }
-
- void stop( );
-
-public slots:
- void start( );
-
-private:
- std::unordered_map
- m_paths;
- bool m_running = true;
- std::filesystem::path m_path;
-
- bool contains(const std::filesystem::path& key);
-
- void initPathsMap( );
-
- bool is_hidden(const std::filesystem::path& p);
-
-signals:
- void changed(const std::filesystem::path path, const FileEvent);
- void pathChanged(const std::filesystem::path p);
-};
diff --git a/src/View/GridItemView/GridItemView.cpp b/src/View/GridItemView/GridItemView.cpp
deleted file mode 100644
index cb7386b..0000000
--- a/src/View/GridItemView/GridItemView.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-#include "GridItemView.hpp"
-#include
-
-GridItemView::GridItemView(QWidget* parent)
- : QFrame(parent), fileController(FileController::instance( )) {
-
- QVBoxLayout* mainLayout = new QVBoxLayout(this);
- QGridLayout* gridLayout = new QGridLayout( );
-
- gridLayout->setAlignment(Qt::AlignTop);
-
- mainLayout->addLayout(gridLayout);
- setLayout(mainLayout);
-
- connect(fileController, &FileController::pathChanged, this,
- [this, gridLayout](const std::filesystem::path path) {
- // No, QT Does not offer a better way to clear a layout, at least this solution doesnt segfault
- QLayoutItem* wItem;
- while ((wItem = gridLayout->takeAt(0)) != 0) {
- if (wItem->widget( ))
- wItem->widget( )->setParent(nullptr);
- delete wItem;
- }
- gridMap.clear( );
- });
-
- connect(fileController, &FileController::contentChanged, this, [this, gridLayout](std::filesystem::path path, FileEvent event) {
- if (event == FileEvent::created) {
- auto w = new GridItem(path);
- gridMap[path] = w;
- connect(w, &GridItem::doubleClicked, this, [this, path]( ) {
- if (!std::filesystem::is_directory(path))
- return;
- emit fileController->updatePath(path);
- });
- connect(w, &GridItem::clicked, this, [this, path]( ) {
- if (std::filesystem::is_directory(path))
- return;
-
- std::string cmd = "xdg-open \"" + path.string( ) + "\"";
- std::system(cmd.c_str( ));
- });
- int pos = gridMap.size( ) - 1;
- gridLayout->addWidget(w, pos / 8, pos % 8);
- w->show( );
- } else if (event == FileEvent::erased) {
- gridLayout->removeWidget(gridMap[path]);
- delete gridMap[path];
- gridMap.erase(path);
-
- int pos = 0;
- for (const auto& [key, widget] : gridMap) {
- gridLayout->addWidget(widget, pos / 8, pos % 8);
- pos++;
- }
- } else if (event == FileEvent::modified) {
- // Idk what this would be used for
- }
-
- });
-
-}
-
-GridItemView::~GridItemView( ) { }
diff --git a/src/View/GridItemView/GridItemView.hpp b/src/View/GridItemView/GridItemView.hpp
deleted file mode 100644
index a7ae72b..0000000
--- a/src/View/GridItemView/GridItemView.hpp
+++ /dev/null
@@ -1,31 +0,0 @@
-#pragma once
-
-#include
-#include
-#include
-
-#include "../Widgets/GridItem/GridItem.hpp"
-#include "../../Controller/FileController/FileController.hpp"
-
-class GridItemView : public QFrame {
- Q_OBJECT
-private:
- int m_rows;
- int m_cols;
- int m_spacing;
-
- QList m_gridItemList;
-
- FileController* fileController;
-
- //Grid map to keep track of the widgets, and delete them easily as QT doesnt
- //provide an easy way to find children by a property
- std::unordered_map gridMap;
-
-public:
- GridItemView(QWidget* parent = nullptr);
- ~GridItemView( );
-
-private slots:
- //void onSizeChanged( );
-};
diff --git a/src/View/MainWidget/MainWidget.cpp b/src/View/MainWidget/MainWidget.cpp
deleted file mode 100644
index 4dbc6c5..0000000
--- a/src/View/MainWidget/MainWidget.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-#include "MainWidget.hpp"
-#include
-
-MainWidget::MainWidget(QWidget* parent) {
-
- auto path_mainContentLayout = new QVBoxLayout(this);
- auto fileTree_fileGridLayout = new QHBoxLayout( );
- auto gridLayout = new GridItemView( );
-
- auto path = new Path( );
- auto backButton = new QPushButton("<");
- backButton->setFixedSize(40, 40);
- auto pathBackLayout = new QHBoxLayout( );
- pathBackLayout->addWidget(backButton);
- pathBackLayout->addWidget(path);
-
-
- auto fileController = FileController::instance( );
- connect(backButton, &QPushButton::clicked, this, [fileController]( ) {
- emit fileController->previousPath( );
- });
-
-
- fileTree_fileGridLayout->addWidget(gridLayout);
-
- path_mainContentLayout->addLayout(pathBackLayout);
- path_mainContentLayout->addLayout(fileTree_fileGridLayout);
-
- setLayout(path_mainContentLayout);
-}
-
-MainWidget::~MainWidget( ) { }
diff --git a/src/View/MainWidget/MainWidget.hpp b/src/View/MainWidget/MainWidget.hpp
deleted file mode 100644
index 63fa285..0000000
--- a/src/View/MainWidget/MainWidget.hpp
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma once
-
-#include
-#include
-#include
-#include
-#include
-
-#include "../Widgets/GridItem/GridItem.hpp"
-#include "../GridItemView/GridItemView.hpp"
-#include "../Path/Path.hpp"
-
-class MainWidget : public QWidget {
- Q_OBJECT
-public:
- MainWidget(QWidget* parent = nullptr);
- ~MainWidget( );
-};
diff --git a/src/View/MainWindow/MainWindow.cpp b/src/View/MainWindow/MainWindow.cpp
deleted file mode 100644
index 72c137f..0000000
--- a/src/View/MainWindow/MainWindow.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "MainWindow.hpp"
-
-MainWindow::MainWindow(QWidget* parent)
- : QMainWindow(parent), m_mainWidget(new MainWidget( )) {
- setWindowTitle("QutieFM");
-
- setObjectName("MainWindow");
-
- this->setCentralWidget(m_mainWidget);
-}
-
-MainWindow::~MainWindow( ) { }
diff --git a/src/View/MainWindow/MainWindow.hpp b/src/View/MainWindow/MainWindow.hpp
deleted file mode 100644
index fda47c7..0000000
--- a/src/View/MainWindow/MainWindow.hpp
+++ /dev/null
@@ -1,16 +0,0 @@
-#pragma once
-
-#include
-
-#include "../MainWidget/MainWidget.hpp"
-
-class MainWindow : public QMainWindow {
- Q_OBJECT
-public:
- MainWindow(QWidget* parent = nullptr);
- ~MainWindow( );
-
-private:
-
- MainWidget* m_mainWidget;
-};
diff --git a/src/View/Path/Path.cpp b/src/View/Path/Path.cpp
deleted file mode 100644
index 71244a9..0000000
--- a/src/View/Path/Path.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-#include "Path.hpp"
-
-
-Path::Path(QWidget* parent)
- :QWidget(parent),
- m_fileController(FileController::instance( )),
-#ifdef _WIN32
- m_pathLabel(new QLabel(std::getenv("USERPROFILE"))) {
-#else
- m_pathLabel(new QLabel(std::getenv("HOME"))) {
-#endif
-
- auto layout = new QHBoxLayout(this);
-
- m_pathLabel->setStyleSheet(R"(
-
- background-color: #313131;
- border: 2px solid #414141;
- border-radius: 6px;
- color: #D8D8D8;
- font-size: 22px;
- )");
-
- setFixedHeight(48);
-
- connect(m_fileController, &FileController::pathChanged, this,
- [this](const std::filesystem::path path) {
- setPath(QString::fromStdString(path.string( )));
- });
- layout->addWidget(m_pathLabel);
-}
-
-Path::~Path( ) { }
diff --git a/src/View/Path/Path.hpp b/src/View/Path/Path.hpp
deleted file mode 100644
index 54f2366..0000000
--- a/src/View/Path/Path.hpp
+++ /dev/null
@@ -1,29 +0,0 @@
-#pragma once
-
-#include
-#include
-#include
-
-#include "../../Controller/FileController/FileController.hpp"
-
-class Path : public QWidget {
- Q_OBJECT
-private:
- QLabel* m_pathLabel;
- QString m_path;
-
- FileController* m_fileController;
-
-public:
- Path(QWidget* parent = nullptr);
- ~Path( );
-
- QString path( ) { return m_path; }
- void setPath(QString path) {
- if (path == this->m_path) { return; }
-
- m_path = path;
- m_pathLabel->setText(m_path);
- }
-};
-
diff --git a/src/View/Widgets/GridItem/GridItem.hpp b/src/View/Widgets/GridItem/GridItem.hpp
deleted file mode 100644
index 72ac709..0000000
--- a/src/View/Widgets/GridItem/GridItem.hpp
+++ /dev/null
@@ -1,47 +0,0 @@
-#pragma once
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-class GridItem : public QWidget {
- Q_OBJECT
-private:
- QString m_name;
- QIcon m_icon;
- int m_size;
-
- std::filesystem::path m_path;
-
- QSize widgetSize;
-
- void formatText(const QString& text);
-
- QIcon getIconForFileType(const std::filesystem::path path) const;
-
-public:
- GridItem(const std::filesystem::path path, QWidget* parent = nullptr);
- ~GridItem( );
-
- QLabel* m_nameLabel;
- QLabel* m_iconLabel;
-
- void setIconSize(const QSize& size);
-
-protected:
- void paintEvent(QPaintEvent* event) override;
- void mousePressEvent(QMouseEvent* event) override;
- void mouseDoubleClickEvent(QMouseEvent*) override;
- void enterEvent(QEnterEvent* event) override;
- void leaveEvent(QEvent* event) override;
-
-signals:
- void clicked( );
- void doubleClicked( );
-};
diff --git a/src/controller/FileMonitorController.cpp b/src/controller/FileMonitorController.cpp
new file mode 100755
index 0000000..8da2c89
--- /dev/null
+++ b/src/controller/FileMonitorController.cpp
@@ -0,0 +1,72 @@
+#include "FileMonitorController.hpp"
+
+FileMonitorController::FileMonitorController(
+ shared_ptr fileMonitor,
+ GridView* gridView
+) :
+ m_FileMonitor(fileMonitor),
+ m_GridView(gridView),
+ m_previousPaths(make_unique>( )) {
+
+ m_FileMonitor->moveToThread(&m_Thread);
+
+ connect(this, &FileMonitorController::operate,
+ m_FileMonitor.get( ), &FileMonitor::start);
+
+ connect(m_FileMonitor.get( ), &FileMonitor::update,
+ this, &FileMonitorController::fm_changed);
+
+ connect(m_FileMonitor.get( ), &FileMonitor::pathChanged,
+ this, &FileMonitorController::clear_gridLayout);
+
+#ifdef _WIN32
+ m_FileMonitor.get( )->SetPath(fs::path(getenv("USERPROFILE")));
+#else
+ m_FileMonitor.get( )->SetPath(fs::path(getenv("HOME")));
+#endif
+
+ m_Thread.start( );
+
+ emit operate( );
+}
+
+void FileMonitorController::setPath(const fs::path path) const {
+ if (path == m_FileMonitor->GetPath( ))
+ return;
+
+ m_previousPaths->push(m_FileMonitor->GetPath( ));
+ m_FileMonitor->SetPath(path);
+}
+
+const fs::path FileMonitorController::getPath( ) const {
+ return m_FileMonitor->GetPath( );
+}
+
+void FileMonitorController::fm_changed(const fs::path path, FileEvent event) {
+ if (event == FileEvent::created) {
+ auto w = new GridItem(path);
+
+ connect(w, &GridItem::doubleClicked, this, [this, path]( ) {
+ if (!std::filesystem::is_directory(path))
+ return;
+ m_FileMonitor->SetPath(path);
+ });
+ connect(w, &GridItem::clicked, this, [this, path]( ) {
+ if (std::filesystem::is_directory(path))
+ return;
+
+ std::string cmd = "xdg-open \"" + path.string( ) + "\"";
+ std::system(cmd.c_str( ));
+ });
+
+ m_GridView->addWidget(w);
+ } else if (event == FileEvent::erased) {
+ m_GridView->removeWidgetByPath(path);
+ } else if (event == FileEvent::modified) {
+ // Idk what this would be used for
+ }
+}
+
+void FileMonitorController::clear_gridLayout(fs::path path) {
+ m_GridView->clear( );
+}
diff --git a/src/controller/FileMonitorController.hpp b/src/controller/FileMonitorController.hpp
new file mode 100755
index 0000000..08eaa6e
--- /dev/null
+++ b/src/controller/FileMonitorController.hpp
@@ -0,0 +1,64 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+
+#include "../model/FileMonitor.hpp"
+#include "../view/GridView.hpp"
+
+using namespace std;
+namespace fs = filesystem;
+
+class FileMonitorController : public QObject {
+ Q_OBJECT
+public:
+ /**
+ * @brief Construct a new File Monitor Controller object, manages the file monitor
+ * thread and updates the gridview when the file monitor updates
+ *
+ * @param fileMonitor
+ * @param gridView
+ */
+ explicit FileMonitorController(shared_ptr fileMonitor, GridView* gridView);
+ ~FileMonitorController( ) = default;
+ FileMonitorController& operator= (const FileMonitorController& other) = delete;
+ FileMonitorController(FileMonitorController&& other) noexcept = default;
+ FileMonitorController& operator= (FileMonitorController&& other) noexcept = default;
+
+ /**
+ * @brief Get the Path object
+ *
+ * @return const fs::path
+ */
+ const fs::path getPath( ) const;
+
+ /**
+ * @brief Set the Path object and puts the it onto the previousPath stack
+ *
+ * @param path
+ */
+ void setPath(const fs::path path) const;
+
+private:
+ shared_ptr m_FileMonitor;
+ GridView* m_GridView;
+
+ unique_ptr> m_previousPaths;
+
+ QThread m_Thread;
+
+private slots:
+ /**
+ * @brief Slot executed when the filemonitor sends a changed signal
+ *
+ * @param path
+ */
+ void fm_changed(const fs::path path, FileEvent event);
+
+ void clear_gridLayout(fs::path path);
+
+signals:
+ void operate( );
+};
diff --git a/src/controller/PlacesController.cpp b/src/controller/PlacesController.cpp
new file mode 100644
index 0000000..562c50b
--- /dev/null
+++ b/src/controller/PlacesController.cpp
@@ -0,0 +1,42 @@
+#include "PlacesController.hpp"
+
+PlacesController::PlacesController(PlacesSidebar* placesSidebar, shared_ptr fileMonitorcontroller) :
+ m_placesSidebar(placesSidebar),
+ m_fileMonitorController(fileMonitorcontroller) {
+
+ const std::vector> defaultPlaces = {
+ {"Home", getenv("HOME"), ":icons/home.svg"},
+ {"Desktop", string(getenv("HOME")) + "/Desktop", ":/icons/monitor.svg"},
+ {"Bilder", string(getenv("HOME")) + "/Bilder", ":/icons/image.svg"},
+ {"Dokumente", string(getenv("HOME")) + "/Dokumente", ":/icons/file-document-outline.svg"},
+ {"Downloads", string(getenv("HOME")) + "/Downloads", ":/icons/download.svg"},
+ {"Musik", string(getenv("HOME")) + "/Musik", ":/icons/music-note.svg"},
+ {"Videos", string(getenv("HOME")) + "/Videos", ":/icons/video-outline.svg"},
+ {"Offentlich", string(getenv("HOME")) + "/Öffentlich", ":/icons/folder-account.svg"},
+ {"Vorgaben", string(getenv("HOME")) + "/Vorgaben", ":/icons/android-studio.svg"},
+ {"Papierkorb", string(getenv("HOME")) + "/.local/share/Trash", ":/icons/delete.svg"}
+ };
+
+ for (auto&& place : defaultPlaces) {
+ auto p = make_shared(
+ QString::fromStdString(get<0>(place)),
+ fs::path(get<1>(place)),
+ QString::fromStdString(get<2>(place)),
+ PlaceType::MyComputer
+ );
+
+ //m_placesList->append(p);
+
+ auto pb = new PlacesButton(
+ p->getName( ),
+ p->getIconPath( )
+ );
+
+ connect(pb, &PlacesButton::clicked, this, [this, p]( ) {
+ this->m_fileMonitorController->setPath(p->getPath( ));
+ });
+
+ m_placesSidebar->addComputerToList(pb);
+ }
+
+}
diff --git a/src/controller/PlacesController.hpp b/src/controller/PlacesController.hpp
new file mode 100644
index 0000000..3327e28
--- /dev/null
+++ b/src/controller/PlacesController.hpp
@@ -0,0 +1,30 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+
+#include "../model/Place.hpp"
+#include "../view/PlacesButton.hpp"
+#include "../view/PlacesSidebar.hpp"
+#include "../controller/FileMonitorController.hpp"
+
+using namespace std;
+namespace fs = filesystem;
+
+class PlacesController :public QObject {
+ Q_OBJECT
+private:
+ QList>* m_placesList;
+ PlacesSidebar* m_placesSidebar;
+ shared_ptr m_fileMonitorController;
+
+public:
+ explicit PlacesController(PlacesSidebar* placesSidebar, shared_ptr fileMonitorcontroller);
+ ~PlacesController( ) = default;
+ PlacesController& operator= (const PlacesController& other) = default;
+ PlacesController(PlacesController&& other) = delete;
+ PlacesController& operator=(PlacesController&& other) noexcept = default;
+};
diff --git a/src/main.cpp b/src/main.cpp
old mode 100644
new mode 100755
index cf06d79..62efe38
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,4 +1,4 @@
-#include "View/MainWindow/MainWindow.hpp"
+#include "view/MainWindow.hpp"
#include
#include
diff --git a/src/model/FileMonitor.cpp b/src/model/FileMonitor.cpp
new file mode 100755
index 0000000..bdc439a
--- /dev/null
+++ b/src/model/FileMonitor.cpp
@@ -0,0 +1,116 @@
+#include "FileMonitor.hpp"
+#include
+#include
+#include
+
+bool is_hidden(const std::filesystem::path& p) {
+#ifdef _WIN32
+ DWORD attrs = GetFileAttributes(p.c_str( ));
+ if (attrs == INVALID_FILE_ATTRIBUTES) {
+ throw std::runtime_error("Error getting file attributes");
+ }
+ return (attrs & FILE_ATTRIBUTE_HIDDEN);
+#elif __unix__
+ return p.filename( ).string( ).front( ) == '.';
+#endif
+ return false;
+}
+
+FileMonitor::FileMonitor(std::chrono::duration delay)
+ : m_delay(delay) { }
+
+FileMonitor::~FileMonitor( ) {
+ stop( );
+}
+
+FileMonitor::FileMonitor(const FileMonitor& other) :
+ m_delay(other.m_delay),
+ m_paths(other.m_paths),
+ m_running(other.m_running),
+ m_path(other.m_path) { }
+
+const FileMonitor& FileMonitor::operator=(const FileMonitor& other) {
+ if (this == &other) return *this;
+
+ m_delay = other.m_delay;
+ m_paths = other.m_paths;
+ m_running = other.m_running;
+ m_path = other.m_path;
+ return *this;
+}
+
+FileMonitor::FileMonitor(FileMonitor&& other) noexcept :
+ m_delay(move(other.m_delay)),
+ m_paths(move(other.m_paths)),
+ m_running(other.m_running),
+ m_path(move(other.m_path)) {
+ other.m_running = false;
+}
+
+const FileMonitor& FileMonitor::operator=(FileMonitor&& other) noexcept {
+ if (this == &other) return *this;
+
+ m_delay = move(other.m_delay);
+ m_paths = move(other.m_paths);
+ m_running = other.m_running;
+ m_path = move(other.m_path);
+ other.m_running = false;
+ return *this;
+}
+
+void FileMonitor::SetPath(std::filesystem::path newPath) {
+ if (m_path == newPath) return;
+
+ m_path = newPath;
+ //stop( );
+ emit pathChanged(m_path);
+ m_paths.clear( );
+ //start( );
+}
+
+fs::path FileMonitor::GetPath( ) {
+ return m_path;
+}
+
+void FileMonitor::start( ) {
+ while (m_running) {
+ std::this_thread::sleep_for(m_delay);
+
+ auto pbegin = m_paths.begin( );
+ while (pbegin != m_paths.end( )) {
+ if (!std::filesystem::exists(pbegin->first)) {
+ emit update(pbegin->first, FileEvent::erased);
+ pbegin = m_paths.erase(pbegin);
+ } else
+ pbegin++;
+ }
+ try {
+ for (auto& file : std::filesystem::directory_iterator(m_path)) {
+ std::filesystem::file_time_type curr_file_last_write;
+ if (!file.is_symlink( )) {
+ curr_file_last_write = std::filesystem::last_write_time(file);
+ } else {
+ curr_file_last_write = std::filesystem::file_time_type(std::chrono::nanoseconds(0));
+ }
+
+
+ if (!is_hidden(file)) {
+ if (!(m_paths.find(file.path( )) != m_paths.end( ))) {
+ m_paths[file.path( )] = curr_file_last_write;
+ emit update(file.path( ), FileEvent::created);
+ } else {
+ if (m_paths[file.path( )] != curr_file_last_write) {
+ m_paths[file.path( )] = curr_file_last_write;
+ emit update(file.path( ), FileEvent::modified);
+ }
+ }
+ }
+ }
+ }
+ catch (std::filesystem::filesystem_error err) {
+ std::cout << err.what( ) << std::endl;
+ }
+ }
+}
+
+void FileMonitor::stop( ) { m_running = false; }
diff --git a/src/model/FileMonitor.hpp b/src/model/FileMonitor.hpp
new file mode 100755
index 0000000..65cf1a4
--- /dev/null
+++ b/src/model/FileMonitor.hpp
@@ -0,0 +1,86 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+
+#ifdef _WIN32
+#include
+#elif __unix__
+#include
+#endif
+
+using namespace std;
+namespace fs = filesystem;
+
+enum class FileEvent { created, modified, erased };
+
+class FileMonitor : public QObject {
+ Q_OBJECT
+public:
+ /**
+ * @brief Construct a new File Monitor object and automatically created the
+ * file monitor thread then starts it
+ *
+ * @param delay Delay in milliseconds for the update interval on the file monitor
+ */
+ explicit FileMonitor(chrono::duration delay);
+ ~FileMonitor( );
+ FileMonitor(const FileMonitor& other);
+ const FileMonitor& operator=(const FileMonitor& other);
+ FileMonitor(FileMonitor&& other) noexcept;
+ const FileMonitor& operator=(FileMonitor&& other) noexcept;
+
+ /**
+ * @brief Set the Path object
+ *
+ * @param path
+ */
+ void SetPath(fs::path path);
+
+ /**
+ * @brief Get the Path object
+ *
+ * @return fs::path
+ */
+ fs::path GetPath( );
+
+public slots:
+ /**
+ * @brief Start slot for the main thread, no idea why it doesnt work as a regular function
+ * but it works.
+ *
+ */
+ void start( );
+
+ /**
+ * @brief Stop function for the worker thread
+ *
+ */
+ void stop( );
+
+private:
+ chrono::duration m_delay;
+
+ unordered_map m_paths;
+ bool m_running = true;
+ fs::path m_path;
+
+signals:
+ /**
+ * @brief Fires when a file is deleted or created, created also means
+ * if its found when the paths map is created for the first time
+ *
+ * @param path path of the created/deleted path
+ * @param fe Event indicating if its deleted or created
+ */
+ void update(const fs::path path, const FileEvent fe);
+
+ /**
+ * @brief Signal fired when the path is changed and the paths map is cleared
+ * This is so that the view gets cleared before new paths come in
+ *
+ */
+ void pathChanged(fs::path path);
+};
diff --git a/src/model/Place.cpp b/src/model/Place.cpp
new file mode 100644
index 0000000..79ec12c
--- /dev/null
+++ b/src/model/Place.cpp
@@ -0,0 +1,12 @@
+#include "Place.hpp"
+
+Place::Place(QString name, fs::path path, QString iconPath, PlaceType type) :
+ m_name(name),
+ m_iconPath(iconPath),
+ m_path(path),
+ m_type(type) { }
+
+const QString& Place::getName( ) const { return m_name; }
+const fs::path& Place::getPath( ) const { return m_path; }
+const PlaceType& Place::getType( ) const { return m_type; }
+const QString& Place::getIconPath( ) const { return m_iconPath; }
diff --git a/src/model/Place.hpp b/src/model/Place.hpp
new file mode 100644
index 0000000..57a63a7
--- /dev/null
+++ b/src/model/Place.hpp
@@ -0,0 +1,31 @@
+#pragma once
+
+#include
+#include
+#include
+
+using namespace std;
+namespace fs = filesystem;
+
+enum class PlaceType { MyComputer, Device };
+
+class Place : public QObject {
+ Q_OBJECT
+private:
+ QString m_name;
+ fs::path m_path;
+ PlaceType m_type;
+ QString m_iconPath;
+
+public:
+ Place(QString name, fs::path path, QString iconPath, PlaceType type);
+ ~Place( ) = default;
+ Place& operator=(const Place& other) = delete;
+ Place(Place&& other) noexcept = delete;
+ Place& operator=(Place&& other) noexcept = default;
+
+ const QString& getName( ) const;
+ const fs::path& getPath( ) const;
+ const PlaceType& getType( ) const;
+ const QString& getIconPath( ) const;
+};
diff --git a/src/View/Widgets/GridItem/GridItem.cpp b/src/view/GridItem.cpp
old mode 100644
new mode 100755
similarity index 69%
rename from src/View/Widgets/GridItem/GridItem.cpp
rename to src/view/GridItem.cpp
index 0189bdf..cf29329
--- a/src/View/Widgets/GridItem/GridItem.cpp
+++ b/src/view/GridItem.cpp
@@ -1,49 +1,52 @@
#include "GridItem.hpp"
-#include
-GridItem::GridItem(const std::filesystem::path path, QWidget* parent)
- : QWidget(parent),
- m_path(path),
- m_name(QString::fromStdString(path.filename( ).string( ))),
- m_icon(getIconForFileType(path)) {
- widgetSize = QSize(128, 128);
- setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
- setMinimumSize(widgetSize);
- setMaximumSize(widgetSize);
-
- setObjectName("gridItem");
- setAttribute(Qt::WA_Hover);
-
- auto vLayout = new QVBoxLayout(this);
- vLayout->setSpacing(10);
-
- m_iconLabel = new QLabel(this);
- m_iconLabel->setPixmap(m_icon.pixmap(widgetSize.width( ), widgetSize.height( )));
- m_iconLabel->setAlignment(Qt::AlignCenter);
-
- m_nameLabel = new QLabel(this);
- formatText(m_name);
- m_nameLabel->setAlignment(Qt::AlignCenter);
- m_nameLabel->setWordWrap(true);
-
- vLayout->addWidget(m_iconLabel);
- vLayout->addWidget(m_nameLabel);
+bool isImageFile(const fs::path path) {
+ static const std::vector imageExtensions = { ".png", ".jpg", ".jpeg", ".bmp", ".gif" };
+ return std::find(imageExtensions.begin( ), imageExtensions.end( ), path.extension( ).string( )) != imageExtensions.end( );
}
-GridItem::~GridItem( ) { }
+QIcon getIconForFileType(const fs::path path) {
+ if (!fs::is_directory(path)) {
+ QIcon icon;
+ if (isImageFile(path)) {
+ QPixmap pixmap(QString::fromStdString(path.string( )));
+ icon = QIcon(pixmap);
+ } else {
+ auto mdb = make_unique( );
+ QMimeType mime_type = mdb->mimeTypeForFile(QString::fromStdString(path.string( )));
+ icon = QIcon::fromTheme(mime_type.iconName( ));
+ }
-void GridItem::formatText(const QString& text) {
- QFontMetrics metrics(m_nameLabel->font( ));
- QString elidedText = metrics.elidedText(text, Qt::ElideRight, m_nameLabel->width( ) * 3);
+ if (!icon.isNull( )) {
+ QPixmap pixmap = icon.pixmap(QSize(64, 64));
+ icon = QIcon(pixmap);
+ }
+
+ return icon.isNull( ) ? QApplication::style( )->standardIcon(QStyle::SP_FileIcon) : icon;
+ } else {
+ auto icon = QIcon::fromTheme("folder");
+
+ if (!icon.isNull( )) {
+ QPixmap pixmap = icon.pixmap(QSize(64, 64));
+ icon = QIcon(pixmap);
+ }
+
+ return icon;
+ }
+}
+
+QString formatText(const QString& text, const QSize& size) {
+ QFontMetrics metrics(text);
+ QString elidedText = metrics.elidedText(text, Qt::ElideRight, size.width( ) * 3);
QStringList lines = elidedText.split(' ');
QStringList finalText;
QString currentLine;
for (const QString& word : lines) {
- QString testLine = currentLine.isEmpty( ) ? word : currentLine + ' ' + word;
- if (metrics.horizontalAdvance(testLine) <= m_nameLabel->width( )) {
- currentLine = testLine;
+ QString textLine = currentLine.isEmpty( ) ? word : currentLine + ' ' + word;
+ if (metrics.horizontalAdvance(textLine) <= size.width( )) {
+ currentLine = textLine;
} else {
finalText.append(currentLine);
currentLine = word;
@@ -59,48 +62,41 @@ void GridItem::formatText(const QString& text) {
finalText.append(currentLine);
}
- m_nameLabel->setText(finalText.join('\n'));
+ return finalText.join('\n');
}
-bool isImageFile(std::filesystem::path path) {
- static const std::vector imageExtensions = { ".png", ".jpg", ".jpeg", ".bmp", ".gif" };
- return std::find(imageExtensions.begin( ), imageExtensions.end( ), path.extension( ).string( )) != imageExtensions.end( );
-}
+GridItem::GridItem(const fs::path path, QWidget* parent) :
+ QWidget(parent),
+ m_path(path),
+ m_name(QString::fromStdString(path.filename( ).string( ))),
+ m_icon(getIconForFileType(path)),
+ m_size(QSize(128, 128)) {
+ setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ setMinimumSize(m_size);
+ setMaximumSize(m_size);
+ setObjectName("gridItem");
+ setAttribute(Qt::WA_Hover);
-QIcon GridItem::getIconForFileType(const std::filesystem::path path) const {
- if (!std::filesystem::is_directory(path)) {
- QIcon icon;
- if (isImageFile(path)) {
- QPixmap pixmap(QString::fromStdString(path.string( )));
- icon = QIcon(pixmap);
- } else {
- auto mdb = new QMimeDatabase( );
- QMimeType mime_type = mdb->mimeTypeForFile(QString::fromStdString(path.string( )));
- icon = QIcon::fromTheme(mime_type.iconName( ));
- delete mdb;
+ auto vLayout = new QVBoxLayout(this);
+ vLayout->setSpacing(10);
+
+ m_iconLabel = new QLabel(this);
+ m_iconLabel->setPixmap(m_icon.pixmap(m_size));
+ m_iconLabel->setAlignment(Qt::AlignCenter);
+
+ m_nameLabel = new QLabel(formatText(m_name, m_size), this);
+ m_nameLabel->setAlignment(Qt::AlignCenter);
+ m_nameLabel->setWordWrap(true);
+
+ vLayout->addWidget(m_iconLabel);
+ vLayout->addWidget(m_nameLabel);
+
+ setStyleSheet(R"(
+ QLabel{
+ color: #D8D8D8;
+ font - weight: bold;
}
-
- if (!icon.isNull( )) {
- QPixmap pixmap = icon.pixmap(QSize(64, 64));
- icon = QIcon(pixmap);
- }
-
- return icon.isNull( ) ? QApplication::style( )->standardIcon(QStyle::SP_FileIcon) : icon;
- } else {
-
- auto icon = QIcon::fromTheme("folder");
-
- if (!icon.isNull( )) {
- QPixmap pixmap = icon.pixmap(QSize(64, 64));
- icon = QIcon(pixmap);
- }
-
- return icon;
- }
-}
-
-void GridItem::setIconSize(const QSize& size) {
- widgetSize = size;
+ )");
}
void GridItem::paintEvent(QPaintEvent* event) {
@@ -131,11 +127,15 @@ void GridItem::mouseDoubleClickEvent(QMouseEvent* event) {
void GridItem::enterEvent(QEnterEvent* event) {
setStyleSheet(R"(
#gridItem{
- border: 2px solid #414141;
- background-color: #00ACC1;
+ background-color: #80DEEA;
border-radius: 8px;
}
+ QLabel{
+ color: #212121;
+ font-weight: bold;
+ }
)");
+
QWidget::enterEvent(event);
}
@@ -143,9 +143,16 @@ void GridItem::leaveEvent(QEvent* event) {
setStyleSheet(R"(
#gridItem{
background-color: none;
- border: 0px solid #414141;
border-radius: 8px;
}
+ QLabel{
+ color: #D8D8D8;
+ font-weight: bold;
+ }
)");
QWidget::leaveEvent(event);
}
+
+const fs::path GridItem::getPath( ) const {
+ return m_path;
+}
diff --git a/src/view/GridItem.hpp b/src/view/GridItem.hpp
new file mode 100755
index 0000000..7102510
--- /dev/null
+++ b/src/view/GridItem.hpp
@@ -0,0 +1,59 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace std;
+namespace fs = filesystem;
+
+class GridItem : public QWidget {
+ Q_OBJECT
+private:
+ QString m_name;
+ QIcon m_icon;
+ QSize m_size;
+
+ const fs::path m_path;
+
+public:
+ /**
+ * @brief Construct a new Grid Item object and automatically find the correct icon.
+ * Will also create a preview for image files
+ *
+ * @param path
+ * @param parent
+ */
+ explicit GridItem(const fs::path path, QWidget* parent = nullptr);
+ ~GridItem( ) = default;
+ GridItem& operator=(const GridItem& other) = delete;
+ GridItem(GridItem&& other) = delete;
+ GridItem& operator=(GridItem&& other) noexcept = default;
+
+ QLabel* m_nameLabel;
+ QLabel* m_iconLabel;
+
+ /**
+ * @brief Get the Path object
+ *
+ * @return const fs::path
+ */
+ const fs::path getPath( ) const;
+
+protected:
+ void paintEvent(QPaintEvent* event) override;
+ void mousePressEvent(QMouseEvent* event) override;
+ void mouseDoubleClickEvent(QMouseEvent* event) override;
+ void enterEvent(QEnterEvent* event) override;
+ void leaveEvent(QEvent* event) override;
+
+signals:
+ void clicked( );
+ void doubleClicked( );
+};
diff --git a/src/view/GridView.cpp b/src/view/GridView.cpp
new file mode 100755
index 0000000..5a7dd88
--- /dev/null
+++ b/src/view/GridView.cpp
@@ -0,0 +1,47 @@
+#include "GridView.hpp"
+
+GridView::GridView(QWidget* parent) :
+ QWidget(parent) {
+ m_gridLayout = new QGridLayout( );
+
+ m_gridLayout->setAlignment(Qt::AlignTop);
+ setLayout(m_gridLayout);
+}
+
+QGridLayout* GridView::getGridLayout( ) {
+ return m_gridLayout;
+}
+
+const void GridView::addWidget(GridItem* widget) {
+ m_gridMap[widget->getPath( )] = widget;
+ int pos = m_gridMap.size( ) - 1;
+ m_gridLayout->addWidget(widget, pos / 8, pos % 8);
+ widget->show( );
+}
+
+const void GridView::removeWidgetByPath(const fs::path& path) {
+ m_gridLayout->removeWidget(m_gridMap.at(path));
+ delete m_gridMap[path];
+ m_gridMap.erase(path);
+
+ // Rearrange the widgets so there is no random hole in the grid
+ int pos = 0;
+ for (const auto& [key, widget] : m_gridMap) {
+ m_gridLayout->addWidget(widget, pos / 8, pos % 8);
+ pos++;
+ }
+}
+
+unordered_map& GridView::getGridMap( ) {
+ return m_gridMap;
+}
+
+void GridView::clear( ) {
+ QLayoutItem* wItem;
+ while ((wItem = m_gridLayout->takeAt(0)) != 0) {
+ if (wItem->widget( ))
+ wItem->widget( )->setParent(nullptr);
+ delete wItem;
+ }
+ m_gridMap.clear( );
+}
diff --git a/src/view/GridView.hpp b/src/view/GridView.hpp
new file mode 100755
index 0000000..58a322b
--- /dev/null
+++ b/src/view/GridView.hpp
@@ -0,0 +1,63 @@
+#pragma once
+
+#include
+#include
+
+#include "GridItem.hpp"
+
+class GridView : public QWidget {
+ Q_OBJECT
+private:
+ int m_rows;
+ int m_cols;
+ int m_spacing;
+
+ QList m_gridItemList;
+
+ unordered_map m_gridMap;
+
+ QGridLayout* m_gridLayout;
+
+public:
+ /**
+ * @brief Construct a new Grid View object
+ * Widgets are managed by a seperate unordered gridMap since its easier
+ * than to traverse the Qt widget tree to find a specific widget
+ *
+ * @param parent
+ */
+ explicit GridView(QWidget* parent = nullptr);
+ ~GridView( ) = default;
+ GridView& operator= (const GridView& other) = delete;
+ GridView(GridView&& other) = delete;
+ GridView& operator=(GridView&& other) noexcept = default;
+
+ QGridLayout* getGridLayout( );
+
+ /**
+ * @brief Add a widget to the gridLayout, position is determined automatically
+ *
+ * @param widget
+ */
+ const void addWidget(GridItem* widget);
+
+ /**
+ * @brief Remove a widget by a given path
+ *
+ * @param path
+ */
+ const void removeWidgetByPath(const fs::path& path);
+
+ /**
+ * @brief Get the Grid Map object
+ *
+ * @return unordered_map*
+ */
+ unordered_map& getGridMap( );
+
+ /**
+ * @brief Clear the gridLayout and the gridMap
+ *
+ */
+ void clear( );
+};
diff --git a/src/view/MainWindow.cpp b/src/view/MainWindow.cpp
new file mode 100755
index 0000000..96097b2
--- /dev/null
+++ b/src/view/MainWindow.cpp
@@ -0,0 +1,73 @@
+#include "MainWindow.hpp"
+
+MainWindow::MainWindow(QWidget* parent)
+ : QMainWindow(parent) {
+ setWindowTitle("QutieFM");
+
+ setObjectName("MainWindow");
+ setStyleSheet(R"(
+ #MainWindow{
+ background-color: #212121;
+ }
+ )");
+ shared_ptr fileMonitor = make_shared(chrono::milliseconds(1000));
+ auto gridView = new GridView( );
+ m_fileMonitorController = make_shared(fileMonitor, gridView);
+
+ auto mainLayout = new QVBoxLayout( );
+ auto fileTree_fileGridLayout = new QHBoxLayout( );
+ auto placesSideBar = new PlacesSidebar( );
+
+ m_placesController = make_unique(placesSideBar, m_fileMonitorController);
+
+ auto pathWidget = new QLabel(
+ QString::fromStdString(
+ m_fileMonitorController->getPath( ).string( )
+ )
+ );
+ pathWidget->setStyleSheet(R"(
+ background-color: #313131;
+ border: 2px solid #414141;
+ border-radius: 6px;
+ color: #D8D8D8;
+ font-size: 16px;
+ )");
+ pathWidget->setFixedHeight(32);
+ connect(fileMonitor.get( ), &FileMonitor::pathChanged, this, [pathWidget](fs::path path) {
+ pathWidget->setText(QString::fromStdString(
+ path.string( )
+ ));
+ });
+
+ QSvgRenderer renderer(QString(":/icons/chevron-left.svg"));
+ QPixmap pixmap(36, 36);
+ pixmap.fill(Qt::transparent);
+ QPainter painter(&pixmap);
+ renderer.render(&painter);
+ auto backButton = new NavigationButton(pixmap);
+ backButton->setStyleSheet(R"(
+ QPushButton{
+ background-color: #212121;
+ border: 2px solid #414141;
+ font-size: 26px;
+ font-weight: 900;
+ color: #F48FB1;
+ border-radius: 8;
+ }
+ )");
+ backButton->setFixedSize(32, 32);
+ auto pathBackLayout = new QHBoxLayout( );
+ pathBackLayout->addWidget(backButton);
+ pathBackLayout->addWidget(pathWidget);
+
+ fileTree_fileGridLayout->addWidget(placesSideBar);
+ fileTree_fileGridLayout->addWidget(gridView);
+
+ mainLayout->addLayout(pathBackLayout);
+ mainLayout->addLayout(fileTree_fileGridLayout);
+
+ auto centralWidget = new QWidget(this);
+ centralWidget->setLayout(mainLayout);
+
+ setCentralWidget(centralWidget);
+}
diff --git a/src/view/MainWindow.hpp b/src/view/MainWindow.hpp
new file mode 100755
index 0000000..5d80727
--- /dev/null
+++ b/src/view/MainWindow.hpp
@@ -0,0 +1,37 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+
+#include "../model/FileMonitor.hpp"
+#include "../controller/FileMonitorController.hpp"
+#include "../controller/PlacesController.hpp"
+#include "../model/FileMonitor.hpp"
+#include "GridItem.hpp"
+#include "GridView.hpp"
+#include "NavigationButton.hpp"
+#include "PlacesSidebar.hpp"
+
+using namespace std;
+namespace fs = filesystem;
+
+class MainWindow : public QMainWindow {
+ Q_OBJECT
+private:
+ shared_ptr m_fileMonitorController;
+ unique_ptr m_placesController;
+public:
+ /**
+ * @brief Construct a new Main Window object
+ *
+ * @param parent
+ */
+ explicit MainWindow(QWidget* parent = nullptr);
+ ~MainWindow( ) = default;
+ MainWindow operator= (const MainWindow& other) = delete;
+ MainWindow(MainWindow&& other) = delete;
+ MainWindow& operator= (MainWindow&& other) noexcept = default;
+};
diff --git a/src/view/NavigationButton.cpp b/src/view/NavigationButton.cpp
new file mode 100755
index 0000000..9fc3873
--- /dev/null
+++ b/src/view/NavigationButton.cpp
@@ -0,0 +1,47 @@
+#include "NavigationButton.hpp"
+
+NavigationButton::NavigationButton(const QPixmap& icon, QWidget* parent) :
+ QPushButton(parent) {
+ setIcon(icon);
+ setMouseTracking(true);
+}
+
+void NavigationButton::enterEvent(QEnterEvent* event) {
+ QPushButton::enterEvent(event);
+ setStyleSheet(R"(
+ QPushButton{
+ background-color: #212121;
+ border: 2px solid #F48FB1;
+ font-size: 26px;
+ font-weight: 900;
+ color: #F48FB1;
+ border-radius: 8;
+ }
+ )");
+}
+
+void NavigationButton::leaveEvent(QEvent* event) {
+ QPushButton::leaveEvent(event);
+
+ setStyleSheet(R"(
+ QPushButton{
+ background-color: #212121;
+ border: 2px solid #414141;
+ font-size: 26px;
+ font-weight: 900;
+ color: #F48FB1;
+ border-radius: 8;
+ }
+ )");
+}
+
+void NavigationButton::mousePressEvent(QMouseEvent* event) {
+ if (event->button( ) == Qt::LeftButton) {
+ emit clicked( );
+ }
+ QPushButton::mousePressEvent(event);
+}
+
+void NavigationButton::setIcon(const QPixmap& icon) {
+ QPushButton::setIcon(icon);
+}
diff --git a/src/view/NavigationButton.hpp b/src/view/NavigationButton.hpp
new file mode 100755
index 0000000..39e553f
--- /dev/null
+++ b/src/view/NavigationButton.hpp
@@ -0,0 +1,35 @@
+#pragma once
+
+#include
+#include
+
+class NavigationButton :public QPushButton {
+ Q_OBJECT
+public:
+ /**
+ * @brief Construct a new Navigation Button object
+ *
+ * @param icon
+ * @param parent
+ */
+ explicit NavigationButton(const QPixmap& icon, QWidget* parent = nullptr);
+ ~NavigationButton( ) = default;
+ NavigationButton& operator= (const NavigationButton& other) = delete;
+ NavigationButton(NavigationButton&& other) = delete;
+ NavigationButton& operator= (NavigationButton&& other) noexcept = default;
+
+ /**
+ * @brief Set the Icon object
+ *
+ * @param icon
+ */
+ void setIcon(const QPixmap& icon);
+
+protected:
+ void enterEvent(QEnterEvent* event) override;
+ void leaveEvent(QEvent* event) override;
+ void mousePressEvent(QMouseEvent* event) override;
+
+signals:
+ void clicked( );
+};
diff --git a/src/view/PlacesButton.cpp b/src/view/PlacesButton.cpp
new file mode 100755
index 0000000..4ffddb6
--- /dev/null
+++ b/src/view/PlacesButton.cpp
@@ -0,0 +1,81 @@
+#include "PlacesButton.hpp"
+
+PlacesButton::PlacesButton(QString name, QString icon, QWidget* parent) {
+ auto layout = new QHBoxLayout(this);
+
+ setObjectName("PlacesButton");
+
+ QSvgRenderer renderer(icon);
+ QPixmap pixmap(16, 16);
+ pixmap.fill(Qt::transparent);
+ QPainter painter(&pixmap);
+ renderer.render(&painter);
+
+ m_icon = new QLabel( );
+ m_icon->setPixmap(pixmap);
+ m_name = new QLabel(name);
+
+ layout->addWidget(m_icon, 0, Qt::AlignLeft);
+ layout->addWidget(m_name, 1, Qt::AlignLeft);
+
+ setObjectName("placesbutton");
+
+ setStyleSheet(R"(
+ #placesbutton{
+ color: #212121;
+ background-color: #80DEEA;
+ font-size: 14px;
+ border-radius: 4px;
+ }
+ )");
+}
+
+void PlacesButton::paintEvent(QPaintEvent* event) {
+ QStyleOption opt;
+ opt.initFrom(this);
+ QPainter p(this);
+ style( )->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
+ QWidget::paintEvent(event);
+}
+
+void PlacesButton::mousePressEvent(QMouseEvent* event) {
+ if (event->button( ) == Qt::LeftButton) {
+ emit clicked( );
+ } else if (event->button( ) == Qt::RightButton) {
+
+ }
+ QWidget::mousePressEvent(event);
+}
+
+void PlacesButton::mouseDoubleClickEvent(QMouseEvent* event) {
+ if (event->button( ) == Qt::LeftButton) {
+ emit doubleClicked( );
+ }
+
+ QWidget::mousePressEvent(event);
+}
+
+void PlacesButton::enterEvent(QEnterEvent* event) {
+ setStyleSheet(R"(
+ #placesbutton{
+ color: #212121;
+ background-color: #90EEFA;
+ font-size: 14px;
+ border-radius: 4px;
+ }
+ )");
+
+ QWidget::enterEvent(event);
+}
+
+void PlacesButton::leaveEvent(QEvent* event) {
+ setStyleSheet(R"(
+ #placesbutton{
+ color: #212121;
+ background-color: #80DEEA;
+ font-size: 14px;
+ border-radius: 4px;
+ }
+ )");
+ QWidget::leaveEvent(event);
+}
diff --git a/src/view/PlacesButton.hpp b/src/view/PlacesButton.hpp
new file mode 100755
index 0000000..5d6fffa
--- /dev/null
+++ b/src/view/PlacesButton.hpp
@@ -0,0 +1,48 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace std;
+namespace fs = filesystem;
+
+class PlacesButton : public QWidget {
+ Q_OBJECT
+private:
+ QLabel* m_name;
+ QLabel* m_icon;
+
+public:
+ /**
+ * @brief Construct a new Places object
+ *
+ * @param name
+ * @param path
+ * @param icon
+ * @param parent
+ */
+ explicit PlacesButton(QString name, QString icon, QWidget* parent = nullptr);
+ ~PlacesButton( ) = default;
+ PlacesButton& operator= (const PlacesButton& other) = default;
+ PlacesButton(PlacesButton&& other) = delete;
+ PlacesButton& operator= (PlacesButton&& other) noexcept = default;
+
+protected:
+ void paintEvent(QPaintEvent* event) override;
+ void mousePressEvent(QMouseEvent* event) override;
+ void mouseDoubleClickEvent(QMouseEvent*) override;
+ void enterEvent(QEnterEvent* event) override;
+ void leaveEvent(QEvent* event) override;
+
+signals:
+ void clicked( );
+ void doubleClicked( );
+};
diff --git a/src/view/PlacesSidebar.cpp b/src/view/PlacesSidebar.cpp
new file mode 100755
index 0000000..0127155
--- /dev/null
+++ b/src/view/PlacesSidebar.cpp
@@ -0,0 +1,58 @@
+#include "PlacesSidebar.hpp"
+
+PlacesSidebar::PlacesSidebar(QWidget* parent) :
+ QFrame(parent),
+ m_mainLayout(new QVBoxLayout(this)),
+ m_mycomputerLayout(new QVBoxLayout( )),
+ m_devicesLayout(new QVBoxLayout( )) {
+
+ auto myComputerLabel = new QLabel("Mein Computer");
+ auto devicesLabel = new QLabel("Geräte");
+
+ myComputerLabel->setObjectName("mycomputerLabel");
+ myComputerLabel->setContentsMargins(QMargins(10, 5, 10, 5));
+ devicesLabel->setObjectName("devicesLabel");
+ devicesLabel->setContentsMargins(QMargins(10, 5, 10, 5));
+
+ setStyleSheet(R"(
+ #devicesLabel{
+ background-color: #9FA8DA;
+ color: #212121;
+ font-weight: bold;
+ font-size: 18px;
+ border-radius: 4;
+ }
+ #mycomputerLabel{
+ background-color: #81D4FA;
+ color: #212121;
+ font-weight: bold;
+ font-size: 18px;
+ border-radius: 4;
+ }
+ )");
+
+ m_mycomputerLayout->addWidget(myComputerLabel, 0, Qt::AlignTop);
+ m_devicesLayout->addWidget(devicesLabel, 0, Qt::AlignTop);
+
+ m_mainLayout->addLayout(m_mycomputerLayout);
+ m_mainLayout->addLayout(m_devicesLayout);
+}
+
+const QList& PlacesSidebar::getComputerList( ) const {
+ return m_computerList;
+}
+const QList& PlacesSidebar::getDevicesList( ) const {
+ return m_devicesList;
+}
+
+const void PlacesSidebar::addComputerToList(PlacesButton* place) {
+ m_computerList.append(place);
+ m_mycomputerLayout->addWidget(place);
+ place->show( );
+}
+const void PlacesSidebar::addDeviceToList(PlacesButton* place) {
+ m_devicesList.append(place);
+ m_devicesLayout->addWidget(place);
+ place->show( );
+}
+
diff --git a/src/view/PlacesSidebar.hpp b/src/view/PlacesSidebar.hpp
new file mode 100755
index 0000000..900a3b7
--- /dev/null
+++ b/src/view/PlacesSidebar.hpp
@@ -0,0 +1,57 @@
+#pragma once
+
+#include
+#include
+
+#include "PlacesButton.hpp"
+
+class PlacesSidebar :public QFrame {
+ Q_OBJECT
+private:
+ QList m_computerList;
+ QList m_devicesList;
+
+ QVBoxLayout* m_mainLayout;
+ QVBoxLayout* m_mycomputerLayout;
+ QVBoxLayout* m_devicesLayout;
+public:
+ /**
+ * @brief Construct a new Places Sidebar object
+ *
+ * @param parent
+ */
+ explicit PlacesSidebar(QWidget* parent = nullptr);
+ ~PlacesSidebar( ) = default;
+ PlacesSidebar& operator= (const PlacesSidebar& other) = delete;
+ PlacesSidebar(PlacesSidebar&& other) = delete;
+ PlacesSidebar& operator= (PlacesSidebar&& other) noexcept = default;
+
+ /**
+ * @brief Get the Computer List object
+ *
+ * @return const QList&
+ */
+ const QList& getComputerList( ) const;
+
+ /**
+ * @brief Get the Devices List object
+ *
+ * @return const QList&
+ */
+ const QList& getDevicesList( ) const;
+
+ /**
+ * @brief Add a new place to the computer layout
+ *
+ * @param place
+ */
+ const void addComputerToList(PlacesButton* place);
+
+ /**
+ * @brief Add a new place to the device layout
+ *
+ * @param place
+ */
+ const void addDeviceToList(PlacesButton* place);
+
+};