refactor everything
1
.gitignore
vendored
@@ -32,4 +32,5 @@
|
|||||||
*.app
|
*.app
|
||||||
|
|
||||||
build/
|
build/
|
||||||
|
debug/
|
||||||
.cache/
|
.cache/
|
||||||
|
|||||||
22
.vscode/c_cpp_properties.json
vendored
Normal file → Executable file
@@ -1,14 +1,24 @@
|
|||||||
{
|
{
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "Linux",
|
"name": "linux-gcc-x64",
|
||||||
"includePath": [
|
"includePath": [
|
||||||
"${default}"
|
"${workspaceFolder}/**",
|
||||||
|
"${default}",
|
||||||
|
"/usr/include/**"
|
||||||
],
|
],
|
||||||
"defines": [],
|
"compilerPath": "/usr/bin/gcc",
|
||||||
"compilerPath": "/usr/bin/clang",
|
"cStandard": "c99",
|
||||||
"intelliSenseMode": "linux-clang-x64"
|
"cppStandard": "c++17",
|
||||||
|
"intelliSenseMode": "linux-gcc-x64",
|
||||||
|
"compilerArgs": [
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"configurationProvider": "ms-vscode.cmake-tools",
|
||||||
|
"browse": {
|
||||||
|
"limitSymbolsToIncludedHeaders": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"version": 4
|
"version": 4
|
||||||
}
|
}
|
||||||
|
|||||||
25
.vscode/launch.json
vendored
Executable file
@@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
140
.vscode/settings.json
vendored
Normal file → Executable file
@@ -1,83 +1,59 @@
|
|||||||
{
|
{
|
||||||
"files.associations": {
|
"C_Cpp_Runner.cCompilerPath": "gcc",
|
||||||
"cctype": "cpp",
|
"C_Cpp_Runner.cppCompilerPath": "g++",
|
||||||
"cmath": "cpp",
|
"C_Cpp_Runner.debuggerPath": "gdb",
|
||||||
"cstdarg": "cpp",
|
"C_Cpp_Runner.cStandard": "c99",
|
||||||
"cstddef": "cpp",
|
"C_Cpp_Runner.cppStandard": "c++17",
|
||||||
"cstdio": "cpp",
|
"C_Cpp_Runner.msvcBatchPath": "",
|
||||||
"cstdlib": "cpp",
|
"C_Cpp_Runner.useMsvc": false,
|
||||||
"cstring": "cpp",
|
"C_Cpp_Runner.warnings": [
|
||||||
"ctime": "cpp",
|
"-Wall",
|
||||||
"cwchar": "cpp",
|
"-Wextra",
|
||||||
"cwctype": "cpp",
|
"-Wpedantic",
|
||||||
"array": "cpp",
|
"-Wshadow",
|
||||||
"atomic": "cpp",
|
"-Wformat=2",
|
||||||
"bit": "cpp",
|
"-Wcast-align",
|
||||||
"*.tcc": "cpp",
|
"-Wconversion",
|
||||||
"bitset": "cpp",
|
"-Wsign-conversion",
|
||||||
"charconv": "cpp",
|
"-Wnull-dereference"
|
||||||
"chrono": "cpp",
|
],
|
||||||
"cinttypes": "cpp",
|
"C_Cpp_Runner.msvcWarnings": [
|
||||||
"clocale": "cpp",
|
"/W4",
|
||||||
"codecvt": "cpp",
|
"/permissive-",
|
||||||
"compare": "cpp",
|
"/w14242",
|
||||||
"concepts": "cpp",
|
"/w14287",
|
||||||
"condition_variable": "cpp",
|
"/w14296",
|
||||||
"cstdint": "cpp",
|
"/w14311",
|
||||||
"deque": "cpp",
|
"/w14826",
|
||||||
"list": "cpp",
|
"/w44062",
|
||||||
"map": "cpp",
|
"/w44242",
|
||||||
"set": "cpp",
|
"/w14905",
|
||||||
"string": "cpp",
|
"/w14906",
|
||||||
"unordered_map": "cpp",
|
"/w14263",
|
||||||
"unordered_set": "cpp",
|
"/w44265",
|
||||||
"vector": "cpp",
|
"/w14928"
|
||||||
"exception": "cpp",
|
],
|
||||||
"algorithm": "cpp",
|
"C_Cpp_Runner.enableWarnings": true,
|
||||||
"functional": "cpp",
|
"C_Cpp_Runner.warningsAsError": false,
|
||||||
"iterator": "cpp",
|
"C_Cpp_Runner.compilerArgs": [],
|
||||||
"memory": "cpp",
|
"C_Cpp_Runner.linkerArgs": [],
|
||||||
"memory_resource": "cpp",
|
"C_Cpp_Runner.includePaths": [],
|
||||||
"numeric": "cpp",
|
"C_Cpp_Runner.includeSearch": [
|
||||||
"optional": "cpp",
|
"*",
|
||||||
"random": "cpp",
|
"**/*"
|
||||||
"ratio": "cpp",
|
],
|
||||||
"string_view": "cpp",
|
"C_Cpp_Runner.excludeSearch": [
|
||||||
"system_error": "cpp",
|
"**/build",
|
||||||
"tuple": "cpp",
|
"**/build/**",
|
||||||
"type_traits": "cpp",
|
"**/.*",
|
||||||
"utility": "cpp",
|
"**/.*/**",
|
||||||
"format": "cpp",
|
"**/.vscode",
|
||||||
"future": "cpp",
|
"**/.vscode/**"
|
||||||
"initializer_list": "cpp",
|
],
|
||||||
"iomanip": "cpp",
|
"C_Cpp_Runner.useAddressSanitizer": false,
|
||||||
"iosfwd": "cpp",
|
"C_Cpp_Runner.useUndefinedSanitizer": false,
|
||||||
"istream": "cpp",
|
"C_Cpp_Runner.useLeakSanitizer": false,
|
||||||
"limits": "cpp",
|
"C_Cpp_Runner.showCompilationTime": false,
|
||||||
"mutex": "cpp",
|
"C_Cpp_Runner.useLinkTimeOptimization": false,
|
||||||
"new": "cpp",
|
"C_Cpp_Runner.msvcSecureNoWarnings": false
|
||||||
"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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
0
CMakeLists.txt
Normal file → Executable file
1
assets/icons/android-studio.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M11,2H13V4H13.5A1.5,1.5 0 0,1 15,5.5V9L14.56,9.44L16.2,12.28C17.31,11.19 18,9.68 18,8H20C20,10.42 18.93,12.59 17.23,14.06L20.37,19.5L20.5,21.72L18.63,20.5L15.56,15.17C14.5,15.7 13.28,16 12,16C10.72,16 9.5,15.7 8.44,15.17L5.37,20.5L3.5,21.72L3.63,19.5L9.44,9.44L9,9V5.5A1.5,1.5 0 0,1 10.5,4H11V2M9.44,13.43C10.22,13.8 11.09,14 12,14C12.91,14 13.78,13.8 14.56,13.43L13.1,10.9H13.09C12.47,11.5 11.53,11.5 10.91,10.9H10.9L9.44,13.43M12,6A1,1 0 0,0 11,7A1,1 0 0,0 12,8A1,1 0 0,0 13,7A1,1 0 0,0 12,6Z" /></svg>
|
||||||
|
After Width: | Height: | Size: 573 B |
BIN
assets/icons/chevron-left.png
Executable file
|
After Width: | Height: | Size: 2.9 KiB |
1
assets/icons/chevron-left.svg
Executable file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M15.41,16.58L10.83,12L15.41,7.41L14,6L8,12L14,18L15.41,16.58Z" /></svg>
|
||||||
|
After Width: | Height: | Size: 140 B |
BIN
assets/icons/chevron-right.png
Executable file
|
After Width: | Height: | Size: 2.9 KiB |
1
assets/icons/chevron-right.svg
Executable file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M8.59,16.58L13.17,12L8.59,7.41L10,6L16,12L10,18L8.59,16.58Z" /></svg>
|
||||||
|
After Width: | Height: | Size: 138 B |
1
assets/icons/delete.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z" /></svg>
|
||||||
|
After Width: | Height: | Size: 160 B |
1
assets/icons/download.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M5,20H19V18H5M19,9H15V3H9V9H5L12,16L19,9Z" /></svg>
|
||||||
|
After Width: | Height: | Size: 120 B |
1
assets/icons/file-document-outline.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M6,2A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2H6M6,4H13V9H18V20H6V4M8,12V14H16V12H8M8,16V18H13V16H8Z" /></svg>
|
||||||
|
After Width: | Height: | Size: 195 B |
1
assets/icons/folder-account.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19,17H11V16C11,14.67 13.67,14 15,14C16.33,14 19,14.67 19,16M15,9A2,2 0 0,1 17,11A2,2 0 0,1 15,13A2,2 0 0,1 13,11C13,9.89 13.9,9 15,9M20,6H12L10,4H4C2.89,4 2,4.89 2,6V18A2,2 0 0,0 4,20H20A2,2 0 0,0 22,18V8C22,6.89 21.1,6 20,6Z" /></svg>
|
||||||
|
After Width: | Height: | Size: 305 B |
1
assets/icons/home.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M10,20V14H14V20H19V12H22L12,3L2,12H5V20H10Z" /></svg>
|
||||||
|
After Width: | Height: | Size: 122 B |
1
assets/icons/image.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M8.5,13.5L11,16.5L14.5,12L19,18H5M21,19V5C21,3.89 20.1,3 19,3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19Z" /></svg>
|
||||||
|
After Width: | Height: | Size: 194 B |
1
assets/icons/monitor.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M21,16H3V4H21M21,2H3C1.89,2 1,2.89 1,4V16A2,2 0 0,0 3,18H10V20H8V22H16V20H14V18H21A2,2 0 0,0 23,16V4C23,2.89 22.1,2 21,2Z" /></svg>
|
||||||
|
After Width: | Height: | Size: 200 B |
1
assets/icons/music-note.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 3V13.55C11.41 13.21 10.73 13 10 13C7.79 13 6 14.79 6 17S7.79 21 10 21 14 19.21 14 17V7H18V3H12Z" /></svg>
|
||||||
|
After Width: | Height: | Size: 178 B |
1
assets/icons/video-outline.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M15,8V16H5V8H15M16,6H4A1,1 0 0,0 3,7V17A1,1 0 0,0 4,18H16A1,1 0 0,0 17,17V13.5L21,17.5V6.5L17,10.5V7A1,1 0 0,0 16,6Z" /></svg>
|
||||||
|
After Width: | Height: | Size: 195 B |
5
assets/resources.qrc
Executable file
@@ -0,0 +1,5 @@
|
|||||||
|
<RCC>
|
||||||
|
<qresource prefix="/">
|
||||||
|
<file>icons/</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
#include "FileController.hpp"
|
|
||||||
#include <chrono>
|
|
||||||
#include <filesystem>
|
|
||||||
#include <iostream>
|
|
||||||
#include <memory>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
FileController::FileController( ) {
|
|
||||||
m_fmWorker = std::make_shared<FileMonitor>(
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QThread>
|
|
||||||
#include <memory>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <filesystem>
|
|
||||||
#include <QApplication>
|
|
||||||
#include <stack>
|
|
||||||
|
|
||||||
#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<std::filesystem::path> previousPaths;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Private constructor to prevent instantiation
|
|
||||||
FileController( );
|
|
||||||
~FileController( );
|
|
||||||
|
|
||||||
private:
|
|
||||||
QThread m_fsThread;
|
|
||||||
std::shared_ptr<FileMonitor> 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( );
|
|
||||||
};
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
#include "FileMonitor.hpp"
|
|
||||||
#include <filesystem>
|
|
||||||
#include <iostream>
|
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
FileMonitor::FileMonitor(std::chrono::duration<int, std::milli> 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( );
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <chrono>
|
|
||||||
#include <filesystem>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <windows.h>
|
|
||||||
#elif __unix__
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum class FileEvent { created, modified, erased };
|
|
||||||
|
|
||||||
class FileMonitor : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
std::chrono::duration<int, std::milli> m_delay;
|
|
||||||
|
|
||||||
FileMonitor(std::chrono::duration<int, std::milli> 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<std::filesystem::path, std::filesystem::file_time_type>
|
|
||||||
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);
|
|
||||||
};
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
#include "GridItemView.hpp"
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
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( ) { }
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QFrame>
|
|
||||||
#include <QScrollArea>
|
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
#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<GridItem> 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<std::filesystem::path, QWidget*> gridMap;
|
|
||||||
|
|
||||||
public:
|
|
||||||
GridItemView(QWidget* parent = nullptr);
|
|
||||||
~GridItemView( );
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
//void onSizeChanged( );
|
|
||||||
};
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
#include "MainWidget.hpp"
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
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( ) { }
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QLayout>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QGridLayout>
|
|
||||||
#include <QPushButton>
|
|
||||||
|
|
||||||
#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( );
|
|
||||||
};
|
|
||||||
@@ -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( ) { }
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QMainWindow>
|
|
||||||
|
|
||||||
#include "../MainWidget/MainWidget.hpp"
|
|
||||||
|
|
||||||
class MainWindow : public QMainWindow {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
MainWindow(QWidget* parent = nullptr);
|
|
||||||
~MainWindow( );
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
MainWidget* m_mainWidget;
|
|
||||||
};
|
|
||||||
@@ -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( ) { }
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QHBoxLayout>
|
|
||||||
|
|
||||||
#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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QLayout>
|
|
||||||
#include <QStyleOption>
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QMimeDatabase>
|
|
||||||
#include <QApplication>
|
|
||||||
#include <filesystem>
|
|
||||||
#include <QMouseEvent>
|
|
||||||
|
|
||||||
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( );
|
|
||||||
};
|
|
||||||
72
src/controller/FileMonitorController.cpp
Executable file
@@ -0,0 +1,72 @@
|
|||||||
|
#include "FileMonitorController.hpp"
|
||||||
|
|
||||||
|
FileMonitorController::FileMonitorController(
|
||||||
|
shared_ptr<FileMonitor> fileMonitor,
|
||||||
|
GridView* gridView
|
||||||
|
) :
|
||||||
|
m_FileMonitor(fileMonitor),
|
||||||
|
m_GridView(gridView),
|
||||||
|
m_previousPaths(make_unique<stack<fs::path>>( )) {
|
||||||
|
|
||||||
|
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( );
|
||||||
|
}
|
||||||
64
src/controller/FileMonitorController.hpp
Executable file
@@ -0,0 +1,64 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <stack>
|
||||||
|
#include <QThread>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
#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> 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<FileMonitor> m_FileMonitor;
|
||||||
|
GridView* m_GridView;
|
||||||
|
|
||||||
|
unique_ptr<stack<fs::path>> 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( );
|
||||||
|
};
|
||||||
42
src/controller/PlacesController.cpp
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
#include "PlacesController.hpp"
|
||||||
|
|
||||||
|
PlacesController::PlacesController(PlacesSidebar* placesSidebar, shared_ptr<FileMonitorController> fileMonitorcontroller) :
|
||||||
|
m_placesSidebar(placesSidebar),
|
||||||
|
m_fileMonitorController(fileMonitorcontroller) {
|
||||||
|
|
||||||
|
const std::vector<std::tuple<std::string, std::string, std::string>> 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<Place>(
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
30
src/controller/PlacesController.hpp
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QList>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#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<shared_ptr<Place>>* m_placesList;
|
||||||
|
PlacesSidebar* m_placesSidebar;
|
||||||
|
shared_ptr<FileMonitorController> m_fileMonitorController;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit PlacesController(PlacesSidebar* placesSidebar, shared_ptr<FileMonitorController> fileMonitorcontroller);
|
||||||
|
~PlacesController( ) = default;
|
||||||
|
PlacesController& operator= (const PlacesController& other) = default;
|
||||||
|
PlacesController(PlacesController&& other) = delete;
|
||||||
|
PlacesController& operator=(PlacesController&& other) noexcept = default;
|
||||||
|
};
|
||||||
2
src/main.cpp
Normal file → Executable file
@@ -1,4 +1,4 @@
|
|||||||
#include "View/MainWindow/MainWindow.hpp"
|
#include "view/MainWindow.hpp"
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
|||||||
116
src/model/FileMonitor.cpp
Executable file
@@ -0,0 +1,116 @@
|
|||||||
|
#include "FileMonitor.hpp"
|
||||||
|
#include <filesystem>
|
||||||
|
#include <iostream>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
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<int, std::milli> 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; }
|
||||||
86
src/model/FileMonitor.hpp
Executable file
@@ -0,0 +1,86 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <chrono>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#elif __unix__
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#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<int, milli> 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<int, milli> m_delay;
|
||||||
|
|
||||||
|
unordered_map<fs::path, fs::file_time_type> 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);
|
||||||
|
};
|
||||||
12
src/model/Place.cpp
Normal file
@@ -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; }
|
||||||
31
src/model/Place.hpp
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
159
src/View/Widgets/GridItem/GridItem.cpp → src/view/GridItem.cpp
Normal file → Executable file
@@ -1,49 +1,52 @@
|
|||||||
#include "GridItem.hpp"
|
#include "GridItem.hpp"
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
GridItem::GridItem(const std::filesystem::path path, QWidget* parent)
|
bool isImageFile(const fs::path path) {
|
||||||
: QWidget(parent),
|
static const std::vector<std::string> imageExtensions = { ".png", ".jpg", ".jpeg", ".bmp", ".gif" };
|
||||||
m_path(path),
|
return std::find(imageExtensions.begin( ), imageExtensions.end( ), path.extension( ).string( )) != imageExtensions.end( );
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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<QMimeDatabase>( );
|
||||||
|
QMimeType mime_type = mdb->mimeTypeForFile(QString::fromStdString(path.string( )));
|
||||||
|
icon = QIcon::fromTheme(mime_type.iconName( ));
|
||||||
|
}
|
||||||
|
|
||||||
void GridItem::formatText(const QString& text) {
|
if (!icon.isNull( )) {
|
||||||
QFontMetrics metrics(m_nameLabel->font( ));
|
QPixmap pixmap = icon.pixmap(QSize(64, 64));
|
||||||
QString elidedText = metrics.elidedText(text, Qt::ElideRight, m_nameLabel->width( ) * 3);
|
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 lines = elidedText.split(' ');
|
||||||
QStringList finalText;
|
QStringList finalText;
|
||||||
QString currentLine;
|
QString currentLine;
|
||||||
|
|
||||||
for (const QString& word : lines) {
|
for (const QString& word : lines) {
|
||||||
QString testLine = currentLine.isEmpty( ) ? word : currentLine + ' ' + word;
|
QString textLine = currentLine.isEmpty( ) ? word : currentLine + ' ' + word;
|
||||||
if (metrics.horizontalAdvance(testLine) <= m_nameLabel->width( )) {
|
if (metrics.horizontalAdvance(textLine) <= size.width( )) {
|
||||||
currentLine = testLine;
|
currentLine = textLine;
|
||||||
} else {
|
} else {
|
||||||
finalText.append(currentLine);
|
finalText.append(currentLine);
|
||||||
currentLine = word;
|
currentLine = word;
|
||||||
@@ -59,48 +62,41 @@ void GridItem::formatText(const QString& text) {
|
|||||||
finalText.append(currentLine);
|
finalText.append(currentLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_nameLabel->setText(finalText.join('\n'));
|
return finalText.join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isImageFile(std::filesystem::path path) {
|
GridItem::GridItem(const fs::path path, QWidget* parent) :
|
||||||
static const std::vector<std::string> imageExtensions = { ".png", ".jpg", ".jpeg", ".bmp", ".gif" };
|
QWidget(parent),
|
||||||
return std::find(imageExtensions.begin( ), imageExtensions.end( ), path.extension( ).string( )) != imageExtensions.end( );
|
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 {
|
auto vLayout = new QVBoxLayout(this);
|
||||||
if (!std::filesystem::is_directory(path)) {
|
vLayout->setSpacing(10);
|
||||||
QIcon icon;
|
|
||||||
if (isImageFile(path)) {
|
m_iconLabel = new QLabel(this);
|
||||||
QPixmap pixmap(QString::fromStdString(path.string( )));
|
m_iconLabel->setPixmap(m_icon.pixmap(m_size));
|
||||||
icon = QIcon(pixmap);
|
m_iconLabel->setAlignment(Qt::AlignCenter);
|
||||||
} else {
|
|
||||||
auto mdb = new QMimeDatabase( );
|
m_nameLabel = new QLabel(formatText(m_name, m_size), this);
|
||||||
QMimeType mime_type = mdb->mimeTypeForFile(QString::fromStdString(path.string( )));
|
m_nameLabel->setAlignment(Qt::AlignCenter);
|
||||||
icon = QIcon::fromTheme(mime_type.iconName( ));
|
m_nameLabel->setWordWrap(true);
|
||||||
delete mdb;
|
|
||||||
|
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) {
|
void GridItem::paintEvent(QPaintEvent* event) {
|
||||||
@@ -131,11 +127,15 @@ void GridItem::mouseDoubleClickEvent(QMouseEvent* event) {
|
|||||||
void GridItem::enterEvent(QEnterEvent* event) {
|
void GridItem::enterEvent(QEnterEvent* event) {
|
||||||
setStyleSheet(R"(
|
setStyleSheet(R"(
|
||||||
#gridItem{
|
#gridItem{
|
||||||
border: 2px solid #414141;
|
background-color: #80DEEA;
|
||||||
background-color: #00ACC1;
|
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
QLabel{
|
||||||
|
color: #212121;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
)");
|
)");
|
||||||
|
|
||||||
QWidget::enterEvent(event);
|
QWidget::enterEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,9 +143,16 @@ void GridItem::leaveEvent(QEvent* event) {
|
|||||||
setStyleSheet(R"(
|
setStyleSheet(R"(
|
||||||
#gridItem{
|
#gridItem{
|
||||||
background-color: none;
|
background-color: none;
|
||||||
border: 0px solid #414141;
|
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
QLabel{
|
||||||
|
color: #D8D8D8;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
)");
|
)");
|
||||||
QWidget::leaveEvent(event);
|
QWidget::leaveEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fs::path GridItem::getPath( ) const {
|
||||||
|
return m_path;
|
||||||
|
}
|
||||||
59
src/view/GridItem.hpp
Executable file
@@ -0,0 +1,59 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QLayout>
|
||||||
|
#include <QStyleOption>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QMimeDatabase>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <QMouseEvent>
|
||||||
|
|
||||||
|
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( );
|
||||||
|
};
|
||||||
47
src/view/GridView.cpp
Executable file
@@ -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<fs::path, QWidget*>& 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( );
|
||||||
|
}
|
||||||
63
src/view/GridView.hpp
Executable file
@@ -0,0 +1,63 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "GridItem.hpp"
|
||||||
|
|
||||||
|
class GridView : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
private:
|
||||||
|
int m_rows;
|
||||||
|
int m_cols;
|
||||||
|
int m_spacing;
|
||||||
|
|
||||||
|
QList<GridItem> m_gridItemList;
|
||||||
|
|
||||||
|
unordered_map<fs::path, QWidget*> 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<fs::path, QWidget*>*
|
||||||
|
*/
|
||||||
|
unordered_map<fs::path, QWidget*>& getGridMap( );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clear the gridLayout and the gridMap
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void clear( );
|
||||||
|
};
|
||||||
73
src/view/MainWindow.cpp
Executable file
@@ -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> fileMonitor = make_shared<FileMonitor>(chrono::milliseconds(1000));
|
||||||
|
auto gridView = new GridView( );
|
||||||
|
m_fileMonitorController = make_shared<FileMonitorController>(fileMonitor, gridView);
|
||||||
|
|
||||||
|
auto mainLayout = new QVBoxLayout( );
|
||||||
|
auto fileTree_fileGridLayout = new QHBoxLayout( );
|
||||||
|
auto placesSideBar = new PlacesSidebar( );
|
||||||
|
|
||||||
|
m_placesController = make_unique<PlacesController>(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);
|
||||||
|
}
|
||||||
37
src/view/MainWindow.hpp
Executable file
@@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <QPointer>
|
||||||
|
#include <QSvgRenderer>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QPushButton>
|
||||||
|
|
||||||
|
#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<FileMonitorController> m_fileMonitorController;
|
||||||
|
unique_ptr<PlacesController> 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;
|
||||||
|
};
|
||||||
47
src/view/NavigationButton.cpp
Executable file
@@ -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);
|
||||||
|
}
|
||||||
35
src/view/NavigationButton.hpp
Executable file
@@ -0,0 +1,35 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QMouseEvent>
|
||||||
|
|
||||||
|
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( );
|
||||||
|
};
|
||||||
81
src/view/PlacesButton.cpp
Executable file
@@ -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);
|
||||||
|
}
|
||||||
48
src/view/PlacesButton.hpp
Executable file
@@ -0,0 +1,48 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QWidget>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QStyleOption>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QMouseEvent>
|
||||||
|
#include <QEvent>
|
||||||
|
#include <QSvgRenderer>
|
||||||
|
|
||||||
|
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( );
|
||||||
|
};
|
||||||
58
src/view/PlacesSidebar.cpp
Executable file
@@ -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<PlacesButton*>& PlacesSidebar::getComputerList( ) const {
|
||||||
|
return m_computerList;
|
||||||
|
}
|
||||||
|
const QList<PlacesButton*>& 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( );
|
||||||
|
}
|
||||||
|
|
||||||
57
src/view/PlacesSidebar.hpp
Executable file
@@ -0,0 +1,57 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QFrame>
|
||||||
|
|
||||||
|
#include "PlacesButton.hpp"
|
||||||
|
|
||||||
|
class PlacesSidebar :public QFrame {
|
||||||
|
Q_OBJECT
|
||||||
|
private:
|
||||||
|
QList<PlacesButton*> m_computerList;
|
||||||
|
QList<PlacesButton*> 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<Places*>&
|
||||||
|
*/
|
||||||
|
const QList<PlacesButton*>& getComputerList( ) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the Devices List object
|
||||||
|
*
|
||||||
|
* @return const QList<Places*>&
|
||||||
|
*/
|
||||||
|
const QList<PlacesButton*>& 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);
|
||||||
|
|
||||||
|
};
|
||||||