some work on the grid layout and items
This commit is contained in:
83
.vscode/settings.json
vendored
Normal file
83
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,12 +4,19 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
FileController::FileController( ) {
|
FileController::FileController( ) {
|
||||||
m_fmWorker = std::make_shared<FileMonitor>(QString("/home/crylia/Dokumente"),
|
#ifdef _WIN32
|
||||||
|
m_fmWorker = std::make_shared<FileMonitor>(std::filesystem::path(std::getenv("USERPROFILE")),
|
||||||
std::chrono::milliseconds(1000));
|
std::chrono::milliseconds(1000));
|
||||||
|
#else
|
||||||
|
m_fmWorker = std::make_shared<FileMonitor>(std::filesystem::path("/home/crylia/Dokumente"),
|
||||||
|
std::chrono::milliseconds(1000));
|
||||||
|
#endif
|
||||||
|
|
||||||
m_fmWorker->moveToThread(&m_fsThread);
|
m_fmWorker->moveToThread(&m_fsThread);
|
||||||
|
|
||||||
connect(this, &FileController::operate, m_fmWorker.get( ), &FileMonitor::start);
|
connect(this, &FileController::operate, m_fmWorker.get( ), &FileMonitor::start);
|
||||||
connect(m_fmWorker.get( ), &FileMonitor::update, this, &FileController::update);
|
connect(m_fmWorker.get( ), &FileMonitor::update, this, &FileController::update);
|
||||||
|
connect(m_fmWorker.get( ), &FileMonitor::newPathEntered, this, &FileController::emitNewPath);
|
||||||
|
|
||||||
m_fsThread.start( );
|
m_fsThread.start( );
|
||||||
|
|
||||||
@@ -21,6 +28,11 @@ FileController::~FileController( ) {
|
|||||||
m_fsThread.wait( );
|
m_fsThread.wait( );
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileController::update(const QString path, const FileEvent event) {
|
void FileController::update(const std::filesystem::path path, const FileEvent event) {
|
||||||
std::cout << path.toStdString( ) << std::endl;
|
std::cout << path.string( ) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileController::emitNewPath(const std::unordered_map<std::filesystem::path, std::filesystem::file_time_type> paths) {
|
||||||
|
std::cout << "test" << std::endl;
|
||||||
|
emit newPathEntered(paths);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ private:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void update(const QString path, const FileEvent);
|
void update(const std::filesystem::path path, const FileEvent);
|
||||||
|
void emitNewPath(const std::unordered_map<std::filesystem::path, std::filesystem::file_time_type> paths);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
// Start signal to start the function in the thread
|
// Start signal to start the function in the thread
|
||||||
@@ -26,5 +27,7 @@ signals:
|
|||||||
// Stop signal to stop the function in the thread
|
// Stop signal to stop the function in the thread
|
||||||
void pause( );
|
void pause( );
|
||||||
// Signal to update the path inside the thread
|
// Signal to update the path inside the thread
|
||||||
void updatePath(const QString&);
|
void updatePath(const std::filesystem::path&);
|
||||||
|
|
||||||
|
void newPathEntered(const std::unordered_map<std::filesystem::path, std::filesystem::file_time_type> paths);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,16 +1,19 @@
|
|||||||
#include "FileMonitor.hpp"
|
#include "FileMonitor.hpp"
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
FileMonitor::FileMonitor(QString path,
|
FileMonitor::FileMonitor(std::filesystem::path path,
|
||||||
std::chrono::duration<int, std::milli> delay)
|
std::chrono::duration<int, std::milli> delay)
|
||||||
: m_path(path), m_delay(delay) {
|
: m_path(path), m_delay(delay) {
|
||||||
|
|
||||||
for (auto& file :
|
for (auto& file :
|
||||||
std::filesystem::directory_iterator(m_path.toStdString( ))) {
|
std::filesystem::directory_iterator(m_path)) {
|
||||||
m_paths[QString::fromStdString(file.path( ).string( ))] =
|
m_paths[file.path( )] = std::filesystem::last_write_time(file);
|
||||||
std::filesystem::last_write_time(file);
|
std::cout << file.path( ).string( ) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emit newPathEntered(m_paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileMonitor::start( ) {
|
void FileMonitor::start( ) {
|
||||||
@@ -19,7 +22,7 @@ void FileMonitor::start( ) {
|
|||||||
|
|
||||||
auto pbegin = m_paths.begin( );
|
auto pbegin = m_paths.begin( );
|
||||||
while (pbegin != m_paths.end( )) {
|
while (pbegin != m_paths.end( )) {
|
||||||
if (!std::filesystem::exists(pbegin->first.toStdString( ))) {
|
if (!std::filesystem::exists(pbegin->first)) {
|
||||||
emit update(pbegin->first, FileEvent::erased);
|
emit update(pbegin->first, FileEvent::erased);
|
||||||
pbegin = m_paths.erase(pbegin);
|
pbegin = m_paths.erase(pbegin);
|
||||||
} else
|
} else
|
||||||
@@ -27,21 +30,19 @@ void FileMonitor::start( ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (auto& file :
|
for (auto& file :
|
||||||
std::filesystem::directory_iterator(m_path.toStdString( ))) {
|
std::filesystem::directory_iterator(m_path)) {
|
||||||
auto curr_file_last_write = std::filesystem::last_write_time(file);
|
auto curr_file_last_write = std::filesystem::last_write_time(file);
|
||||||
|
|
||||||
if (!contains(QString::fromStdString(file.path( ).string( )))) {
|
if (!contains(file.path( ))) {
|
||||||
m_paths[QString::fromStdString(file.path( ).string( ))] =
|
m_paths[file.path( )] =
|
||||||
curr_file_last_write;
|
curr_file_last_write;
|
||||||
emit update(QString::fromStdString(file.path( ).string( )),
|
emit update(file.path( ), FileEvent::created);
|
||||||
FileEvent::created);
|
|
||||||
} else {
|
} else {
|
||||||
if (m_paths[QString::fromStdString(file.path( ).string( ))] !=
|
if (m_paths[file.path( )] !=
|
||||||
curr_file_last_write) {
|
curr_file_last_write) {
|
||||||
m_paths[QString::fromStdString(file.path( ).string( ))] =
|
m_paths[file.path( )] =
|
||||||
curr_file_last_write;
|
curr_file_last_write;
|
||||||
emit update(QString::fromStdString(file.path( ).string( )),
|
emit update(file.path( ), FileEvent::modified);
|
||||||
FileEvent::modified);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -50,6 +51,6 @@ void FileMonitor::start( ) {
|
|||||||
|
|
||||||
void FileMonitor::stop( ) { m_running = false; }
|
void FileMonitor::stop( ) { m_running = false; }
|
||||||
|
|
||||||
bool FileMonitor::contains(const QString& key) {
|
bool FileMonitor::contains(const std::filesystem::path& key) {
|
||||||
return m_paths.find(key) != m_paths.end( );
|
return m_paths.find(key) != m_paths.end( );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QString>
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
@@ -13,22 +12,23 @@ class FileMonitor : public QObject {
|
|||||||
public:
|
public:
|
||||||
std::chrono::duration<int, std::milli> m_delay;
|
std::chrono::duration<int, std::milli> m_delay;
|
||||||
|
|
||||||
FileMonitor(QString path, std::chrono::duration<int, std::milli> delay);
|
FileMonitor(std::filesystem::path path, std::chrono::duration<int, std::milli> delay);
|
||||||
~FileMonitor( ) = default;
|
~FileMonitor( ) = default;
|
||||||
|
|
||||||
void SetPath(QString path) { m_path = path; }
|
void SetPath(std::filesystem::path path) { m_path = path; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void start( );
|
void start( );
|
||||||
void stop( );
|
void stop( );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<QString, std::filesystem::file_time_type> m_paths;
|
std::unordered_map<std::filesystem::path, std::filesystem::file_time_type> m_paths;
|
||||||
bool m_running;
|
bool m_running;
|
||||||
QString m_path;
|
std::filesystem::path m_path;
|
||||||
|
|
||||||
bool contains(const QString& key);
|
bool contains(const std::filesystem::path& key);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void update(const QString path, const FileEvent);
|
void update(const std::filesystem::path path, const FileEvent);
|
||||||
|
void newPathEntered(const std::unordered_map<std::filesystem::path, std::filesystem::file_time_type> paths);
|
||||||
};
|
};
|
||||||
|
|||||||
20
src/View/GridItemView/GridItemView.cpp
Normal file
20
src/View/GridItemView/GridItemView.cpp
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#include "GridItemView.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
GridItemView::GridItemView(QWidget* parent)
|
||||||
|
: QFrame(parent),
|
||||||
|
fileController(std::make_shared<FileController>( )) {
|
||||||
|
|
||||||
|
QGridLayout* mainLayout = new QGridLayout( );
|
||||||
|
|
||||||
|
connect(fileController.get( ), &FileController::newPathEntered, this, [this, mainLayout](const std::unordered_map<std::filesystem::path, std::filesystem::file_time_type> paths) {
|
||||||
|
std::cout << "path.first" << std::endl;
|
||||||
|
|
||||||
|
for (auto path : paths) {
|
||||||
|
mainLayout->addWidget(new GridItem(path.first, this));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
GridItemView::~GridItemView( ) { }
|
||||||
25
src/View/GridItemView/GridItemView.hpp
Normal file
25
src/View/GridItemView/GridItemView.hpp
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QFrame>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
|
||||||
|
std::shared_ptr<FileController> fileController;
|
||||||
|
|
||||||
|
public:
|
||||||
|
GridItemView(QWidget* parent = nullptr);
|
||||||
|
~GridItemView( );
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
//void onSizeChanged( );
|
||||||
|
};
|
||||||
@@ -2,14 +2,16 @@
|
|||||||
|
|
||||||
MainWidget::MainWidget(QWidget* parent) {
|
MainWidget::MainWidget(QWidget* parent) {
|
||||||
|
|
||||||
auto path_mainContentLayout = std::make_shared<QHBoxLayout>(this);
|
auto path_mainContentLayout = new QHBoxLayout(this);
|
||||||
auto fileTree_fileGridLayout = std::make_shared<QVBoxLayout>(this);
|
auto fileTree_fileGridLayout = new QVBoxLayout(this);
|
||||||
|
|
||||||
path_mainContentLayout->addLayout(fileTree_fileGridLayout.get( ));
|
auto gridLayout = new GridItemView(this);
|
||||||
|
|
||||||
setLayout(path_mainContentLayout.get( ));
|
fileTree_fileGridLayout->addWidget(gridLayout);
|
||||||
|
|
||||||
auto fmc = new FileController( );
|
path_mainContentLayout->addLayout(fileTree_fileGridLayout);
|
||||||
|
|
||||||
|
setLayout(path_mainContentLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWidget::~MainWidget( ) { }
|
MainWidget::~MainWidget( ) { }
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
#include <QLayout>
|
#include <QLayout>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
#include <QGridLayout>
|
||||||
|
|
||||||
#include "../../Controller/FileController/FileController.hpp"
|
#include "../Widgets/GridItem/GridItem.hpp"
|
||||||
|
#include "../GridItemView/GridItemView.hpp"
|
||||||
|
|
||||||
class MainWidget : public QWidget {
|
class MainWidget : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
#include "MainWindow.hpp"
|
#include "MainWindow.hpp"
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget* parent)
|
MainWindow::MainWindow(QWidget* parent)
|
||||||
: QMainWindow(parent), m_mainWidget(std::make_shared<MainWidget>( )) {
|
: QMainWindow(parent), m_mainWidget(new MainWidget( )) {
|
||||||
setWindowTitle("QutieFM");
|
setWindowTitle("QutieFM");
|
||||||
|
|
||||||
setObjectName("MainWindow");
|
setObjectName("MainWindow");
|
||||||
|
|
||||||
this->setCentralWidget(m_mainWidget.get( ));
|
this->setCentralWidget(m_mainWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::~MainWindow( ) { }
|
MainWindow::~MainWindow( ) { }
|
||||||
|
|||||||
@@ -12,5 +12,5 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::shared_ptr<MainWidget> m_mainWidget;
|
MainWidget* m_mainWidget;
|
||||||
};
|
};
|
||||||
|
|||||||
67
src/View/Widgets/GridItem/GridItem.cpp
Normal file
67
src/View/Widgets/GridItem/GridItem.cpp
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#include "GridItem.hpp"
|
||||||
|
|
||||||
|
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);
|
||||||
|
setMinimumSize(widgetSize);
|
||||||
|
setMaximumSize(widgetSize);
|
||||||
|
|
||||||
|
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(m_name, this);
|
||||||
|
m_nameLabel->setAlignment(Qt::AlignCenter);
|
||||||
|
m_nameLabel->setWordWrap(true);
|
||||||
|
|
||||||
|
vLayout->addWidget(m_iconLabel);
|
||||||
|
vLayout->addWidget(m_nameLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
GridItem::~GridItem( ) { }
|
||||||
|
|
||||||
|
QString GridItem::formatText(const QString& text) {
|
||||||
|
QFontMetrics fm(font( ));
|
||||||
|
QString elidedText = fm.elidedText(text, Qt::ElideRight, widgetSize.width( ));
|
||||||
|
QString result;
|
||||||
|
QStringList lines = elidedText.split('\n');
|
||||||
|
for (int i = 0; i < std::min((int)lines.size( ), 3); ++i)
|
||||||
|
result.append(lines.at(i)).append('\n');
|
||||||
|
|
||||||
|
if (lines.size( ) > 3)
|
||||||
|
result.append("...");
|
||||||
|
|
||||||
|
return result.trimmed( );
|
||||||
|
}
|
||||||
|
|
||||||
|
QIcon GridItem::getIconForFileType(const std::filesystem::path path) const {
|
||||||
|
if (!std::filesystem::is_directory(path)) {
|
||||||
|
QIcon icon;
|
||||||
|
QList<QMimeType> mime_types = mime_database.mimeTypesForFileName(QString::fromStdString(path.string( )));
|
||||||
|
|
||||||
|
for (int i = 0; i < mime_types.count( ) && icon.isNull( ); ++i)
|
||||||
|
icon = QIcon::fromTheme(mime_types[i].iconName( ));
|
||||||
|
|
||||||
|
return icon.isNull( ) ? QApplication::style( )->standardIcon(QStyle::SP_FileIcon) : icon;
|
||||||
|
} else {
|
||||||
|
return QIcon::fromTheme("folder");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridItem::setIconSize(const QSize& size) {
|
||||||
|
widgetSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridItem::paintEvent(QPaintEvent* event) {
|
||||||
|
QStyleOption opt;
|
||||||
|
opt.initFrom(this);
|
||||||
|
QPainter p(this);
|
||||||
|
style( )->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
|
||||||
|
QWidget::paintEvent(event);
|
||||||
|
}
|
||||||
39
src/View/Widgets/GridItem/GridItem.hpp
Normal file
39
src/View/Widgets/GridItem/GridItem.hpp
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QLayout>
|
||||||
|
#include <QStyleOption>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QMimeDatabase>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
class GridItem : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
private:
|
||||||
|
QString m_name;
|
||||||
|
QIcon m_icon;
|
||||||
|
int m_size;
|
||||||
|
|
||||||
|
std::filesystem::path m_path;
|
||||||
|
|
||||||
|
QSize widgetSize;
|
||||||
|
QMimeDatabase mime_database;
|
||||||
|
|
||||||
|
QString 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;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user