From 3ac113857071fc1f225b2e1b42547269e568c6b7 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Tue, 11 Aug 2020 22:35:12 +0100 Subject: New upstream version 2.2.4.4 --- test/button.png | Bin 0 -> 3962 bytes test/button.xcf | Bin 0 -> 7496 bytes test/chartarea/MainWindow.cpp | 26 ++ test/chartarea/MainWindow.h | 26 ++ test/chartarea/MainWindow.ui | 49 +++ test/chartarea/chartarea.pro | 35 ++ test/chartarea/main.cpp | 11 + test/chartarea/widget.cpp | 134 +++++++ test/chartarea/widget.h | 49 +++ test/darkbutton/DarkButton.cpp | 99 +++++ test/darkbutton/DarkButton.h | 22 ++ test/darkbutton/MainWindow.cpp | 41 ++ test/darkbutton/MainWindow.h | 26 ++ test/darkbutton/MainWindow.ui | 26 ++ test/darkbutton/cancelDarkD.png | Bin 0 -> 151 bytes test/darkbutton/cancelDarkE.png | Bin 0 -> 473 bytes test/darkbutton/darkButton.png | Bin 0 -> 3969 bytes test/darkbutton/darkButtonOver.png | Bin 0 -> 4286 bytes test/darkbutton/darkButtonPushed.png | Bin 0 -> 3903 bytes test/darkbutton/darkbutton.pro | 38 ++ test/darkbutton/main.cpp | 11 + test/darkbutton/res.qrc | 9 + test/progressbardark/MainWindow.cpp | 32 ++ test/progressbardark/MainWindow.h | 26 ++ test/progressbardark/MainWindow.ui | 26 ++ test/progressbardark/ProgressBarDark.cpp | 50 +++ test/progressbardark/ProgressBarDark.h | 16 + test/progressbardark/main.cpp | 11 + test/progressbardark/progressBarin.png | Bin 0 -> 4487 bytes test/progressbardark/progressBarout.png | Bin 0 -> 1287 bytes test/progressbardark/progressbardark.pro | 38 ++ .../progressbardark.pro.user.4.8-pre1 | 336 +++++++++++++++++ test/progressbardark/res.qrc | 6 + test/radialmap/Config.cpp | 31 ++ test/radialmap/Config.h | 45 +++ test/radialmap/MainWindow.cpp | 81 ++++ test/radialmap/MainWindow.h | 29 ++ test/radialmap/MainWindow.ui | 46 +++ test/radialmap/fileTree.cpp | 54 +++ test/radialmap/fileTree.h | 157 ++++++++ test/radialmap/main.cpp | 11 + test/radialmap/radialMap/labels.cpp | 317 ++++++++++++++++ test/radialmap/radialMap/map.cpp | 413 +++++++++++++++++++++ test/radialmap/radialMap/map.h | 84 +++++ test/radialmap/radialMap/radialMap.h | 109 ++++++ test/radialmap/radialMap/sincos.h | 45 +++ test/radialmap/radialMap/widget.cpp | 191 ++++++++++ test/radialmap/radialMap/widget.h | 112 ++++++ test/radialmap/radialMap/widgetEvents.cpp | 212 +++++++++++ test/radialmap/radialmap.pro | 46 +++ 50 files changed, 3126 insertions(+) create mode 100644 test/button.png create mode 100644 test/button.xcf create mode 100644 test/chartarea/MainWindow.cpp create mode 100644 test/chartarea/MainWindow.h create mode 100644 test/chartarea/MainWindow.ui create mode 100644 test/chartarea/chartarea.pro create mode 100644 test/chartarea/main.cpp create mode 100644 test/chartarea/widget.cpp create mode 100644 test/chartarea/widget.h create mode 100644 test/darkbutton/DarkButton.cpp create mode 100644 test/darkbutton/DarkButton.h create mode 100644 test/darkbutton/MainWindow.cpp create mode 100644 test/darkbutton/MainWindow.h create mode 100644 test/darkbutton/MainWindow.ui create mode 100644 test/darkbutton/cancelDarkD.png create mode 100644 test/darkbutton/cancelDarkE.png create mode 100644 test/darkbutton/darkButton.png create mode 100644 test/darkbutton/darkButtonOver.png create mode 100644 test/darkbutton/darkButtonPushed.png create mode 100644 test/darkbutton/darkbutton.pro create mode 100644 test/darkbutton/main.cpp create mode 100644 test/darkbutton/res.qrc create mode 100644 test/progressbardark/MainWindow.cpp create mode 100644 test/progressbardark/MainWindow.h create mode 100644 test/progressbardark/MainWindow.ui create mode 100644 test/progressbardark/ProgressBarDark.cpp create mode 100644 test/progressbardark/ProgressBarDark.h create mode 100644 test/progressbardark/main.cpp create mode 100644 test/progressbardark/progressBarin.png create mode 100644 test/progressbardark/progressBarout.png create mode 100644 test/progressbardark/progressbardark.pro create mode 100644 test/progressbardark/progressbardark.pro.user.4.8-pre1 create mode 100644 test/progressbardark/res.qrc create mode 100644 test/radialmap/Config.cpp create mode 100644 test/radialmap/Config.h create mode 100644 test/radialmap/MainWindow.cpp create mode 100644 test/radialmap/MainWindow.h create mode 100644 test/radialmap/MainWindow.ui create mode 100644 test/radialmap/fileTree.cpp create mode 100644 test/radialmap/fileTree.h create mode 100644 test/radialmap/main.cpp create mode 100644 test/radialmap/radialMap/labels.cpp create mode 100644 test/radialmap/radialMap/map.cpp create mode 100644 test/radialmap/radialMap/map.h create mode 100644 test/radialmap/radialMap/radialMap.h create mode 100644 test/radialmap/radialMap/sincos.h create mode 100644 test/radialmap/radialMap/widget.cpp create mode 100644 test/radialmap/radialMap/widget.h create mode 100644 test/radialmap/radialMap/widgetEvents.cpp create mode 100644 test/radialmap/radialmap.pro (limited to 'test') diff --git a/test/button.png b/test/button.png new file mode 100644 index 0000000..40bdd15 Binary files /dev/null and b/test/button.png differ diff --git a/test/button.xcf b/test/button.xcf new file mode 100644 index 0000000..274e2a8 Binary files /dev/null and b/test/button.xcf differ diff --git a/test/chartarea/MainWindow.cpp b/test/chartarea/MainWindow.cpp new file mode 100644 index 0000000..489fa6f --- /dev/null +++ b/test/chartarea/MainWindow.cpp @@ -0,0 +1,26 @@ +#include "MainWindow.h" +#include "ui_MainWindow.h" +#include + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow), + m_map(new ChartArea::Widget(this)) +{ + ui->setupUi(this); + //m_map->hide(); + ui->verticalLayout->addWidget(m_map); + + connect(&timer,&QTimer::timeout,this,&MainWindow::addValue); + timer.start(1000); +} + +MainWindow::~MainWindow() +{ + delete ui; +} + +void MainWindow::addValue() +{ + m_map->addValue(rand()%5000); +} diff --git a/test/chartarea/MainWindow.h b/test/chartarea/MainWindow.h new file mode 100644 index 0000000..29a297d --- /dev/null +++ b/test/chartarea/MainWindow.h @@ -0,0 +1,26 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +#include "widget.h" + +namespace Ui { +class MainWindow; +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + void addValue(); +private: + Ui::MainWindow *ui; + ChartArea::Widget * m_map; + QTimer timer; +}; + +#endif // MAINWINDOW_H diff --git a/test/chartarea/MainWindow.ui b/test/chartarea/MainWindow.ui new file mode 100644 index 0000000..312e028 --- /dev/null +++ b/test/chartarea/MainWindow.ui @@ -0,0 +1,49 @@ + + + MainWindow + + + + 0 + 0 + 400 + 300 + + + + MainWindow + + + background-color: rgb(240, 240, 240); + + + + + + + + 30 + 30 + + + + background-color: rgb(255, 255, 255,0); + + + 24 + + + Qt::Vertical + + + + + + + + + + + + + diff --git a/test/chartarea/chartarea.pro b/test/chartarea/chartarea.pro new file mode 100644 index 0000000..91b165d --- /dev/null +++ b/test/chartarea/chartarea.pro @@ -0,0 +1,35 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2019-05-30T12:37:58 +# +#------------------------------------------------- + +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = radialmap +TEMPLATE = app + +# The following define makes your compiler emit warnings if you use +# any feature of Qt which has been marked as deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + + +SOURCES += \ + main.cpp \ + MainWindow.cpp \ + widget.cpp +HEADERS += \ + MainWindow.h \ + widget.h + +FORMS += \ + MainWindow.ui diff --git a/test/chartarea/main.cpp b/test/chartarea/main.cpp new file mode 100644 index 0000000..af9caac --- /dev/null +++ b/test/chartarea/main.cpp @@ -0,0 +1,11 @@ +#include "MainWindow.h" +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; + w.show(); + + return a.exec(); +} diff --git a/test/chartarea/widget.cpp b/test/chartarea/widget.cpp new file mode 100644 index 0000000..0da898d --- /dev/null +++ b/test/chartarea/widget.cpp @@ -0,0 +1,134 @@ +/*********************************************************************** +* Copyright 2003-2004 Max Howell +* Copyright 2008-2009 Martin Sandsmark +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +***********************************************************************/ + +#include "widget.h" + +#include +#include +#include +#include +#include + +ChartArea::Widget::Widget(QWidget *parent) + : QWidget(parent) +{ + setSizePolicy(QSizePolicy::Preferred,QSizePolicy::MinimumExpanding); + setMinimumHeight(20); + setMinimumWidth(100); +} + +ChartArea::Widget::~Widget() +{ +} + +void ChartArea::Widget::invalidate() +{ +} + +void ChartArea::Widget::resizeEvent(QResizeEvent*) +{ + /*std::cerr << "width(): " << width() << std::endl; + std::cerr << "height(): " << height() << std::endl;*/ +} + +void ChartArea::Widget::addValue(uint64_t value) +{ + //m_values.push_back(value); + while(m_values.size()>64) + m_values.erase(m_values.begin()); + update(); +} + +void ChartArea::Widget::paintEvent(QPaintEvent*) +{ + //std::cerr << "paintEvent(): " << width() << std::endl; + + QPainter painter; + painter.begin(this); + painter.drawRect(0,0,width()-1,height()-1); + painter.setRenderHint(QPainter::Antialiasing,true); + painter.setRenderHint(QPainter::SmoothPixmapTransform,true); + painter.setRenderHint(QPainter::HighQualityAntialiasing,true); + + while(m_values.size()<64) + m_values.insert(m_values.begin(),0); + std::vector values=m_values; + QVector points; + { + uint64_t max=0; + unsigned int index=0; + while(index250000) + painter.setPen(QPen(QColor(160,240,160), 3)); + else + painter.setPen(QPen(QColor(160,240,160), 2)); + painter.drawPolyline(QPolygonF(points)); + + + // todo: bounding rect + center flag + if(height()>30) + { + QFont font = painter.font(); + int heightTemp=height()/5; + if(heightTemp<14) + heightTemp=14; + font.setPixelSize(heightTemp); + painter.setFont(font); + + painter.setPen(QPen(QColor(140,140,140), 3)); + painter.drawText(0,0,width(),height(),Qt::AlignHCenter | Qt::AlignBottom,tr("%1B/s").arg(m_values.back())); + } + painter.end(); +} diff --git a/test/chartarea/widget.h b/test/chartarea/widget.h new file mode 100644 index 0000000..8a4c742 --- /dev/null +++ b/test/chartarea/widget.h @@ -0,0 +1,49 @@ +/*********************************************************************** +* Copyright 2003-2004 Max Howell +* Copyright 2008-2009 Martin Sandsmark +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +***********************************************************************/ + +#ifndef WIDGET_H +#define WIDGET_H + +#include +#include + +namespace ChartArea +{ + +class Widget : public QWidget +{ + Q_OBJECT + +public: + explicit Widget(QWidget* = nullptr); + ~Widget() override; + void addValue(uint64_t value); +public Q_SLOTS: + void invalidate(); +protected: + void paintEvent(QPaintEvent*) override; + void resizeEvent(QResizeEvent*) override; +private: + std::vector m_values; +}; +} + +#endif diff --git a/test/darkbutton/DarkButton.cpp b/test/darkbutton/DarkButton.cpp new file mode 100644 index 0000000..b785961 --- /dev/null +++ b/test/darkbutton/DarkButton.cpp @@ -0,0 +1,99 @@ +#include "DarkButton.h" +#include + +DarkButton::DarkButton(QWidget *parent) : + QPushButton(parent) +{ + setMinimumHeight(36); + setMaximumHeight(36); + setStyleSheet("border:none;color:#afb;"); + over=false; + enabled=true; +} + +void DarkButton::paintEvent(QPaintEvent * event) +{ + if(backgroundLeft.isNull() || backgroundLeft.height()!=height()) + { + QPixmap background(":/darkButton.png"); + if(background.isNull()) + abort(); + QPixmap backgroundPushed(":/darkButtonPushed.png"); + if(backgroundPushed.isNull()) + abort(); + QPixmap over(":/darkButtonOver.png"); + if(over.isNull()) + abort(); + if(height()==background.height()) + { + backgroundLeft=background.copy(0,0,10,36); + backgroundMiddle=background.copy(10,0,46,36); + backgroundRight=background.copy(56,0,10,36); + backgroundPushedLeft=backgroundPushed.copy(0,0,10,36); + backgroundPushedMiddle=backgroundPushed.copy(10,0,46,36); + backgroundPushedRight=backgroundPushed.copy(56,0,10,36); + overLeft=over.copy(0,0,10,36); + overMiddle=over.copy(10,0,46,36); + overRight=over.copy(56,0,10,36); + } + else + { + backgroundLeft=background.copy(0,0,10,36).scaledToHeight(height(),Qt::SmoothTransformation); + backgroundMiddle=background.copy(10,0,46,36).scaledToHeight(height(),Qt::SmoothTransformation); + backgroundRight=background.copy(56,0,10,36).scaledToHeight(height(),Qt::SmoothTransformation); + backgroundPushedLeft=backgroundPushed.copy(0,0,10,36).scaledToHeight(height(),Qt::SmoothTransformation); + backgroundPushedMiddle=backgroundPushed.copy(10,0,46,36).scaledToHeight(height(),Qt::SmoothTransformation); + backgroundPushedRight=backgroundPushed.copy(56,0,10,36).scaledToHeight(height(),Qt::SmoothTransformation); + overLeft=over.copy(0,0,10,36).scaledToHeight(height(),Qt::SmoothTransformation); + overMiddle=over.copy(10,0,46,36).scaledToHeight(height(),Qt::SmoothTransformation); + overRight=over.copy(56,0,10,36).scaledToHeight(height(),Qt::SmoothTransformation); + } + } + QPainter paint; + paint.begin(this); + if(enabled && !isEnabled()) + { + setStyleSheet("border:none;color:#fab;"); + enabled=false; + } + if(!enabled && isEnabled()) + { + setStyleSheet("border:none;color:#afb;"); + enabled=true; + } + if(isDown() && isEnabled()) + { + paint.drawPixmap(0,0,backgroundPushedLeft.width(), backgroundPushedLeft.height(), backgroundPushedLeft); + paint.drawPixmap(backgroundPushedLeft.width(), 0, + width()-backgroundPushedLeft.width()-backgroundPushedRight.width(), backgroundPushedLeft.height(),backgroundPushedMiddle); + paint.drawPixmap(width()-backgroundPushedRight.width(),0, backgroundPushedRight.width(), backgroundPushedRight.height(),backgroundPushedRight); + } + else + { + paint.drawPixmap(0,0,backgroundLeft.width(), backgroundLeft.height(), backgroundLeft); + paint.drawPixmap(backgroundLeft.width(), 0, + width()-backgroundLeft.width()-backgroundRight.width(), backgroundLeft.height(),backgroundMiddle); + paint.drawPixmap(width()-backgroundRight.width(),0, backgroundRight.width(), backgroundRight.height(),backgroundRight); + } + if(over && isEnabled()) + { + paint.drawPixmap(0,0,overLeft.width(), overLeft.height(), overLeft); + paint.drawPixmap(overLeft.width(), 0, + width()-overLeft.width()-overRight.width(), overLeft.height(),overMiddle); + paint.drawPixmap(width()-overRight.width(),0, overRight.width(), overRight.height(),overRight); + } + QPushButton::paintEvent(event); +} + +void DarkButton::enterEvent(QEvent *e) +{ + over=true; + QWidget::enterEvent(e); + update(); +} +void DarkButton::leaveEvent(QEvent *e) +{ + over=false; + QWidget::leaveEvent(e); + update(); +} diff --git a/test/darkbutton/DarkButton.h b/test/darkbutton/DarkButton.h new file mode 100644 index 0000000..38dbb60 --- /dev/null +++ b/test/darkbutton/DarkButton.h @@ -0,0 +1,22 @@ +#ifndef DarkButton_H +#define DarkButton_H + +#include + +class DarkButton : public QPushButton +{ +public: + DarkButton(QWidget *parent = nullptr); + void paintEvent(QPaintEvent *) override; +protected: + void enterEvent(QEvent *e) override; + void leaveEvent(QEvent *e) override; +private: + QPixmap backgroundLeft,backgroundMiddle,backgroundRight; + QPixmap backgroundPushedLeft,backgroundPushedMiddle,backgroundPushedRight; + QPixmap overLeft,overMiddle,overRight; + bool over; + bool enabled; +}; + +#endif // PROGRESSBARDARK_H diff --git a/test/darkbutton/MainWindow.cpp b/test/darkbutton/MainWindow.cpp new file mode 100644 index 0000000..78cda6a --- /dev/null +++ b/test/darkbutton/MainWindow.cpp @@ -0,0 +1,41 @@ +#include "MainWindow.h" +#include "ui_MainWindow.h" +#include +#include +#include +#include + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow), + darkButton(new DarkButton) +{ + ui->setupUi(this); + + darkButton->setText("toto"); + QIcon icon; + icon.addFile(QString::fromUtf8(":/cancelDarkD.png"), QSize(), QIcon::Normal, QIcon::Off); + icon.addFile(QString::fromUtf8(":/cancelDarkE.png"), QSize(), QIcon::Normal, QIcon::On); + darkButton->setIcon(icon); + darkButton->setCheckable(true); + + ui->verticalLayout->addWidget(darkButton); + connect(&timer,&QTimer::timeout,this,&MainWindow::create); + timer.start(1000); +} + +MainWindow::~MainWindow() +{ + delete ui; +} + +void MainWindow::create() +{ + if(darkButton->isChecked()) + { + darkButton->setEnabled(!darkButton->isEnabled()); + darkButton->setChecked(false); + } + else + darkButton->setChecked(true); +} diff --git a/test/darkbutton/MainWindow.h b/test/darkbutton/MainWindow.h new file mode 100644 index 0000000..118257f --- /dev/null +++ b/test/darkbutton/MainWindow.h @@ -0,0 +1,26 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +#include "DarkButton.h" + +namespace Ui { +class MainWindow; +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + void create(); +private: + Ui::MainWindow *ui; + DarkButton * darkButton; + QTimer timer; +}; + +#endif // MAINWINDOW_H diff --git a/test/darkbutton/MainWindow.ui b/test/darkbutton/MainWindow.ui new file mode 100644 index 0000000..246d92c --- /dev/null +++ b/test/darkbutton/MainWindow.ui @@ -0,0 +1,26 @@ + + + MainWindow + + + + 0 + 0 + 400 + 300 + + + + MainWindow + + + #MainWindow{background-color: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, stop:0 rgb(70, 70, 70), stop:1 rgb(40, 40, 40));} + + + + + + + + + diff --git a/test/darkbutton/cancelDarkD.png b/test/darkbutton/cancelDarkD.png new file mode 100644 index 0000000..a2f4556 Binary files /dev/null and b/test/darkbutton/cancelDarkD.png differ diff --git a/test/darkbutton/cancelDarkE.png b/test/darkbutton/cancelDarkE.png new file mode 100644 index 0000000..1cda258 Binary files /dev/null and b/test/darkbutton/cancelDarkE.png differ diff --git a/test/darkbutton/darkButton.png b/test/darkbutton/darkButton.png new file mode 100644 index 0000000..561fc02 Binary files /dev/null and b/test/darkbutton/darkButton.png differ diff --git a/test/darkbutton/darkButtonOver.png b/test/darkbutton/darkButtonOver.png new file mode 100644 index 0000000..ea42018 Binary files /dev/null and b/test/darkbutton/darkButtonOver.png differ diff --git a/test/darkbutton/darkButtonPushed.png b/test/darkbutton/darkButtonPushed.png new file mode 100644 index 0000000..e2e63a5 Binary files /dev/null and b/test/darkbutton/darkButtonPushed.png differ diff --git a/test/darkbutton/darkbutton.pro b/test/darkbutton/darkbutton.pro new file mode 100644 index 0000000..fc31c76 --- /dev/null +++ b/test/darkbutton/darkbutton.pro @@ -0,0 +1,38 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2019-05-30T12:37:58 +# +#------------------------------------------------- + +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = darkbutton +TEMPLATE = app + +# The following define makes your compiler emit warnings if you use +# any feature of Qt which has been marked as deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +FORMS += \ + MainWindow.ui + +HEADERS += \ + MainWindow.h \ + DarkButton.h + +SOURCES += \ + main.cpp \ + MainWindow.cpp \ + DarkButton.cpp + +RESOURCES += \ + res.qrc diff --git a/test/darkbutton/main.cpp b/test/darkbutton/main.cpp new file mode 100644 index 0000000..af9caac --- /dev/null +++ b/test/darkbutton/main.cpp @@ -0,0 +1,11 @@ +#include "MainWindow.h" +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; + w.show(); + + return a.exec(); +} diff --git a/test/darkbutton/res.qrc b/test/darkbutton/res.qrc new file mode 100644 index 0000000..cd9341b --- /dev/null +++ b/test/darkbutton/res.qrc @@ -0,0 +1,9 @@ + + + darkButton.png + darkButtonPushed.png + darkButtonOver.png + cancelDarkE.png + cancelDarkD.png + + diff --git a/test/progressbardark/MainWindow.cpp b/test/progressbardark/MainWindow.cpp new file mode 100644 index 0000000..07939bc --- /dev/null +++ b/test/progressbardark/MainWindow.cpp @@ -0,0 +1,32 @@ +#include "MainWindow.h" +#include "ui_MainWindow.h" +#include +#include +#include +#include + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow), + progressBarDark(new ProgressBarDark) +{ + ui->setupUi(this); + ui->verticalLayout->addWidget(progressBarDark); + connect(&treeTimer,&QTimer::timeout,this,&MainWindow::create); + treeTimer.start(100); +} + +MainWindow::~MainWindow() +{ + delete ui; +} + +void MainWindow::create() +{ + int val=progressBarDark->value(); + if(val>=100) + val=0; + else + val++; + progressBarDark->setValue(val); +} diff --git a/test/progressbardark/MainWindow.h b/test/progressbardark/MainWindow.h new file mode 100644 index 0000000..7fcf988 --- /dev/null +++ b/test/progressbardark/MainWindow.h @@ -0,0 +1,26 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +#include "ProgressBarDark.h" + +namespace Ui { +class MainWindow; +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + void create(); +private: + Ui::MainWindow *ui; + ProgressBarDark * progressBarDark; + QTimer treeTimer; +}; + +#endif // MAINWINDOW_H diff --git a/test/progressbardark/MainWindow.ui b/test/progressbardark/MainWindow.ui new file mode 100644 index 0000000..246d92c --- /dev/null +++ b/test/progressbardark/MainWindow.ui @@ -0,0 +1,26 @@ + + + MainWindow + + + + 0 + 0 + 400 + 300 + + + + MainWindow + + + #MainWindow{background-color: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, stop:0 rgb(70, 70, 70), stop:1 rgb(40, 40, 40));} + + + + + + + + + diff --git a/test/progressbardark/ProgressBarDark.cpp b/test/progressbardark/ProgressBarDark.cpp new file mode 100644 index 0000000..a03167e --- /dev/null +++ b/test/progressbardark/ProgressBarDark.cpp @@ -0,0 +1,50 @@ +#include "ProgressBarDark.h" +#include + +ProgressBarDark::ProgressBarDark(QWidget *parent) : + QProgressBar(parent) +{ + setMinimumHeight(22); + setMaximumHeight(22); +} + +void ProgressBarDark::paintEvent(QPaintEvent *) +{ + if(backgroundLeft.isNull() || backgroundLeft.height()!=height()) + { + QPixmap background(":/progressBarout.png"); + QPixmap bar(":/progressBarin.png"); + if(height()==background.height()) + { + backgroundLeft=background.copy(0,0,24,55); + backgroundMiddle=background.copy(24,0,701,55); + backgroundRight=background.copy(725,0,24,55); + barLeft=bar.copy(0,0,24,55); + barMiddle=bar.copy(24,0,701,55); + barRight=bar.copy(725,0,24,55); + } + else + { + backgroundLeft=background.copy(0,0,24,55).scaledToHeight(height(),Qt::SmoothTransformation); + backgroundMiddle=background.copy(24,0,701,55).scaledToHeight(height(),Qt::SmoothTransformation); + backgroundRight=background.copy(725,0,24,55).scaledToHeight(height(),Qt::SmoothTransformation); + barLeft=bar.copy(0,0,24,55).scaledToHeight(height(),Qt::SmoothTransformation); + barMiddle=bar.copy(24,0,701,55).scaledToHeight(height(),Qt::SmoothTransformation); + barRight=bar.copy(725,0,24,55).scaledToHeight(height(),Qt::SmoothTransformation); + } + } + int size=width()-barLeft.width()-barRight.width(); + int inpixel=value()*size/maximum(); + QPainter paint; + paint.begin(this); + paint.drawPixmap(0,0,backgroundLeft.width(), backgroundLeft.height(), backgroundLeft); + paint.drawPixmap(0,0,barLeft.width(), barLeft.height(), barLeft); + + paint.drawPixmap(backgroundLeft.width(), 0, + width()-backgroundLeft.width()-backgroundRight.width(), backgroundLeft.height(),backgroundMiddle); + paint.drawPixmap(barLeft.width(), 0, + inpixel, barLeft.height(),barMiddle); + + paint.drawPixmap(width()-backgroundRight.width(),0, backgroundRight.width(), backgroundRight.height(),backgroundRight); + paint.drawPixmap(barLeft.width()+inpixel, 0, barRight.width(), barRight.height(),barRight); +} diff --git a/test/progressbardark/ProgressBarDark.h b/test/progressbardark/ProgressBarDark.h new file mode 100644 index 0000000..9bf92f8 --- /dev/null +++ b/test/progressbardark/ProgressBarDark.h @@ -0,0 +1,16 @@ +#ifndef PROGRESSBARDARK_H +#define PROGRESSBARDARK_H + +#include + +class ProgressBarDark : public QProgressBar +{ +public: + ProgressBarDark(QWidget *parent = nullptr); + void paintEvent(QPaintEvent *) override; +private: + QPixmap backgroundLeft,backgroundMiddle,backgroundRight; + QPixmap barLeft,barMiddle,barRight; +}; + +#endif // PROGRESSBARDARK_H diff --git a/test/progressbardark/main.cpp b/test/progressbardark/main.cpp new file mode 100644 index 0000000..af9caac --- /dev/null +++ b/test/progressbardark/main.cpp @@ -0,0 +1,11 @@ +#include "MainWindow.h" +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; + w.show(); + + return a.exec(); +} diff --git a/test/progressbardark/progressBarin.png b/test/progressbardark/progressBarin.png new file mode 100644 index 0000000..6af26c7 Binary files /dev/null and b/test/progressbardark/progressBarin.png differ diff --git a/test/progressbardark/progressBarout.png b/test/progressbardark/progressBarout.png new file mode 100644 index 0000000..08f3748 Binary files /dev/null and b/test/progressbardark/progressBarout.png differ diff --git a/test/progressbardark/progressbardark.pro b/test/progressbardark/progressbardark.pro new file mode 100644 index 0000000..bdf4f71 --- /dev/null +++ b/test/progressbardark/progressbardark.pro @@ -0,0 +1,38 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2019-05-30T12:37:58 +# +#------------------------------------------------- + +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = progressbardark +TEMPLATE = app + +# The following define makes your compiler emit warnings if you use +# any feature of Qt which has been marked as deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +FORMS += \ + MainWindow.ui + +HEADERS += \ + MainWindow.h \ + ProgressBarDark.h + +SOURCES += \ + main.cpp \ + MainWindow.cpp \ + ProgressBarDark.cpp + +RESOURCES += \ + res.qrc diff --git a/test/progressbardark/progressbardark.pro.user.4.8-pre1 b/test/progressbardark/progressbardark.pro.user.4.8-pre1 new file mode 100644 index 0000000..efcb89e --- /dev/null +++ b/test/progressbardark/progressbardark.pro.user.4.8-pre1 @@ -0,0 +1,336 @@ + + + + + + EnvironmentId + {74ab603f-f657-4135-92cf-c93af71b2f91} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + true + false + 0 + true + true + 0 + 8 + true + 1 + true + true + true + true + + + + ProjectExplorer.Project.PluginSettings + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop + {23178a1c-09be-4e9f-9aab-ff55e05e7637} + 0 + 0 + 0 + + /home/user/Desktop/ultracopier/sources/test/build-progressbardark-Desktop-Debug + + + true + qmake + + QtProjectManager.QMakeBuildStep + true + + false + false + false + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Debug + Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + true + + + /home/user/Desktop/ultracopier/sources/test/build-progressbardark-Desktop-Release + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + + false + false + true + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + + /home/user/Desktop/ultracopier/sources/test/build-progressbardark-Desktop-Profile + + + true + qmake + + QtProjectManager.QMakeBuildStep + true + + false + true + true + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Profile + Profile + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + 3 + + + 0 + Deploy + + ProjectExplorer.BuildSteps.Deploy + + 1 + Deploy Configuration + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + 2 + + progressbardark + + Qt4ProjectManager.Qt4RunConfiguration:/home/user/Desktop/ultracopier/sources/test/progressbardark/progressbardark.pro + true + + progressbardark.pro + false + + /home/user/Desktop/ultracopier/sources/test/build-progressbardark-Desktop-Debug + 3768 + false + true + false + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 18 + + + Version + 18 + + diff --git a/test/progressbardark/res.qrc b/test/progressbardark/res.qrc new file mode 100644 index 0000000..c4486c9 --- /dev/null +++ b/test/progressbardark/res.qrc @@ -0,0 +1,6 @@ + + + progressBarin.png + progressBarout.png + + diff --git a/test/radialmap/Config.cpp b/test/radialmap/Config.cpp new file mode 100644 index 0000000..b36c392 --- /dev/null +++ b/test/radialmap/Config.cpp @@ -0,0 +1,31 @@ +/*********************************************************************** +* Copyright 2003-2004 Max Howell +* Copyright 2008-2009 Martin Sandsmark +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +***********************************************************************/ + +#include "Config.h" + +#include + +bool Config::varyLabelFontSizes=true; +bool Config::showSmallFiles=false; +bool Config::antialias=true; +uint Config::contrast=94; +int Config::minFontPitch=QFont().pointSize() - 3; +uint Config::defaultRingDepth=4; diff --git a/test/radialmap/Config.h b/test/radialmap/Config.h new file mode 100644 index 0000000..1fb43df --- /dev/null +++ b/test/radialmap/Config.h @@ -0,0 +1,45 @@ +/*********************************************************************** +* Copyright 2003-2004 Max Howell +* Copyright 2008-2009 Martin Sandsmark +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +***********************************************************************/ + +#ifndef Config_H +#define Config_H + +#include + +namespace Filelight +{ +class Config +{ +public: + //keep everything positive, avoid using DON'T, NOT or NO + + static bool varyLabelFontSizes; + static bool showSmallFiles; + static uint contrast; + static bool antialias; + static int minFontPitch; + static uint defaultRingDepth; +}; +} + +using Filelight::Config; + +#endif diff --git a/test/radialmap/MainWindow.cpp b/test/radialmap/MainWindow.cpp new file mode 100644 index 0000000..5bebc05 --- /dev/null +++ b/test/radialmap/MainWindow.cpp @@ -0,0 +1,81 @@ +#include "MainWindow.h" +#include "ui_MainWindow.h" +#include "radialMap/widget.h" +#include +#include +#include +#include + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow), + m_map(new RadialMap::Widget(this)), + tree(new Folder("")) +{ + recursiveTreeLoad(tree,"/etc/"); + + ui->setupUi(this); + //m_map->hide(); + ui->verticalLayout->addWidget(m_map); + connect(&treeTimer,&QTimer::timeout,this,&MainWindow::create); + treeTimer.setSingleShot(true); + treeTimer.start(1); +} + +MainWindow::~MainWindow() +{ + delete ui; +} + +void MainWindow::create() +{ + m_map->create(tree); +} + +uint64_t MainWindow::recursiveTreeLoad(Folder * tree,std::string folder) +{ + uint64_t size=0; + DIR *d; + struct dirent *entry; + d = opendir(folder.c_str()); + if (d) + { + while ((entry = readdir(d)) != NULL) + { + if(entry==NULL) + break; + bool skip=false; + if(entry->d_name[0]=='.') + { + if(entry->d_name[1]==0x00) + skip=true; + else if(entry->d_name[1]=='.' && entry->d_name[2]==0x00) + skip=true; + } + if(!skip) + { + + if(entry->d_type == DT_DIR) + { + Folder * newDir=new Folder(entry->d_name); + size+=recursiveTreeLoad(newDir,folder+entry->d_name+"/"); + tree->append(newDir); + } + else + { + struct stat statbuf; + std::string path=folder+entry->d_name; + if(stat(path.c_str(), &statbuf) != -1) + { + size+=statbuf.st_size; + tree->append(entry->d_name,statbuf.st_size); + } + } + } + } + closedir(d); + } + if(tree->size()!=size)//wrong is recursiveTreeLoad() is call after append + abort(); + return size; +} diff --git a/test/radialmap/MainWindow.h b/test/radialmap/MainWindow.h new file mode 100644 index 0000000..1e0a4f7 --- /dev/null +++ b/test/radialmap/MainWindow.h @@ -0,0 +1,29 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +#include "radialMap/widget.h" + +namespace Ui { +class MainWindow; +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + void create(); +private: + Ui::MainWindow *ui; + RadialMap::Widget * m_map; + Folder * tree; + QTimer treeTimer; + + uint64_t recursiveTreeLoad(Folder * tree, std::string folder); +}; + +#endif // MAINWINDOW_H diff --git a/test/radialmap/MainWindow.ui b/test/radialmap/MainWindow.ui new file mode 100644 index 0000000..7b51134 --- /dev/null +++ b/test/radialmap/MainWindow.ui @@ -0,0 +1,46 @@ + + + MainWindow + + + + 0 + 0 + 400 + 300 + + + + MainWindow + + + + + + + + 30 + 30 + + + + background-color: rgb(255, 255, 255,0); + + + 24 + + + Qt::Vertical + + + + + + + + + + + + + diff --git a/test/radialmap/fileTree.cpp b/test/radialmap/fileTree.cpp new file mode 100644 index 0000000..84c7938 --- /dev/null +++ b/test/radialmap/fileTree.cpp @@ -0,0 +1,54 @@ +/*********************************************************************** +* Copyright 2003-2004 Max Howell +* Copyright 2008-2009 Martin Sandsmark +* Copyright 2017 Harald Sitter +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +***********************************************************************/ + +#include "fileTree.h" + +#include +#include + +QString File::displayName() const { + const QString decodedName = QFile::decodeName(m_name); + return url().isLocalFile() ? QDir::toNativeSeparators(decodedName) : decodedName; +} + +QString File::displayPath(const Folder *root) const +{ + // Use QUrl to sanitize the path for display and then run it through + // QDir to make sure we use native path separators. + const QUrl url = this->url(root); + const QString cleanPath = url.toDisplayString(QUrl::PreferLocalFile | QUrl::NormalizePathSegments); + return url.isLocalFile() ? QDir::toNativeSeparators(cleanPath) : cleanPath; +} + +QUrl File::url(const Folder *root) const +{ + QString path; + + if (root == this) + root = nullptr; //prevent returning empty string when there is something we could return + + for (const Folder *d = (Folder*)this; d != root && d; d = d->parent()) { + path.prepend(QFile::decodeName(d->name8Bit())); + } + + return QUrl::fromUserInput(path, QString(), QUrl::AssumeLocalFile); +} diff --git a/test/radialmap/fileTree.h b/test/radialmap/fileTree.h new file mode 100644 index 0000000..6baa316 --- /dev/null +++ b/test/radialmap/fileTree.h @@ -0,0 +1,157 @@ +/*********************************************************************** +* Copyright 2003-2004 Max Howell +* Copyright 2008-2009 Martin Sandsmark +* Copyright 2017 Harald Sitter +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +***********************************************************************/ + +#ifndef FILETREE_H +#define FILETREE_H + +#include //qstrdup +#include //decodeName() +#include +#include + +#include + +typedef quint64 FileSize; +typedef quint64 Dirsize; //**** currently unused + +class Folder; + +class File +{ +public: + friend class Folder; + +public: + File(const char *name, FileSize size) : m_parent(nullptr), m_name(qstrdup(name)), m_size(size) {} + virtual ~File() { + delete [] m_name; + } + + Folder *parent() const { + return m_parent; + } + + /** Do not use for user visible strings. Use name instead. */ + const char *name8Bit() const { + return m_name; + } + /** Decoded name. Use when you need a QString. */ + QString decodedName() const { + return QFile::decodeName(m_name); + } + /** + * Human readable name (including native separators where applicable). + * Only use for display. + */ + QString displayName() const; + + FileSize size() const { + return m_size; + } + + virtual bool isFolder() const { + return false; + } + + /** + * Human readable path for display (including native separators where applicable. + * Only use for display. + */ + QString displayPath(const Folder * = nullptr) const; + QString humanReadableSize() const { + return QString::number(m_size); + } + + /** Builds a complete QUrl by walking up to root. */ + QUrl url(const Folder *root = nullptr) const; + +protected: + File(const char *name, FileSize size, Folder *parent) : m_parent(parent), m_name(qstrdup(name)), m_size(size) {} + + Folder *m_parent; //0 if this is treeRoot + char *m_name; + FileSize m_size; //in units of KiB + +private: + File(const File&); + void operator=(const File&); +}; + + +class Folder : public File +{ +public: + Folder(const char *name) : File(name, 0), m_children(0) {} //DON'T pass the full path! + + uint children() const { + return m_children; + } + bool isFolder() const override { + return true; + } + + ///appends a Folder + void append(Folder *d, const char *name=nullptr) + { + if (name) { + delete [] d->m_name; + d->m_name = qstrdup(name); + } //directories that had a fullpath copy just their names this way + + m_children += d->children(); //doesn't include the dir itself + d->m_parent = this; + append((File*)d); //will add 1 to filecount for the dir itself + } + + ///appends a File + void append(const char *name, FileSize size) + { + append(new File(name, size, this)); + } + + /// removes a file + void remove(const File *f) { + files.removeAll(const_cast(f)); + + for (Folder *d = this; d; d = d->parent()) { + d->m_size -= f->size(); + } + } + + QList files; + +private: + void append(File *p) + { + m_children++; + m_size += p->size(); + files.append(p); + } + + uint m_children; + +private: + Folder(const Folder&); //undefined + void operator=(const Folder&); //undefined +}; + +#endif diff --git a/test/radialmap/main.cpp b/test/radialmap/main.cpp new file mode 100644 index 0000000..af9caac --- /dev/null +++ b/test/radialmap/main.cpp @@ -0,0 +1,11 @@ +#include "MainWindow.h" +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; + w.show(); + + return a.exec(); +} diff --git a/test/radialmap/radialMap/labels.cpp b/test/radialmap/radialMap/labels.cpp new file mode 100644 index 0000000..030f4f4 --- /dev/null +++ b/test/radialmap/radialMap/labels.cpp @@ -0,0 +1,317 @@ +/*********************************************************************** +* Copyright 2003-2004 Max Howell +* Copyright 2008-2009 Martin Sandsmark +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +***********************************************************************/ + +#include +#include +#include +#include + +#include "Config.h" +#include "fileTree.h" +#include "radialMap.h" +#include "sincos.h" +#include "widget.h" + + + +namespace RadialMap +{ +class Label +{ +public: + Label(const RadialMap::Segment *s, int l) : segment(s), level(l), angle(segment->start() + (segment->length() / 2)) { } + + bool tooClose(const int otherAngle) const { + return (angle > otherAngle - LABEL_ANGLE_MARGIN && angle < otherAngle + LABEL_ANGLE_MARGIN); + } + + const RadialMap::Segment *segment; + const unsigned int level; + const int angle; + + int targetX, targetY, middleX, startY, startX; + int textX, textY, tw, th; + + QString qs; +}; + +void RadialMap::Widget::paintExplodedLabels(QPainter &paint) const +{ + //we are a friend of RadialMap::Map + + QVector list; + unsigned int startLevel = 0; + + + //1. Create list of labels sorted in the order they will be rendered + + if (m_focus && m_focus->file() != m_tree) { //separate behavior for selected vs unselected segments + //don't bother with files + if (m_focus && m_focus->file() && !m_focus->file()->isFolder()) { + return; + } + + //find the range of levels we will be potentially drawing labels for + //startLevel is the level above whatever m_focus is in + for (const Folder *p = (const Folder*)m_focus->file(); p != m_tree; ++startLevel) { + p = p->parent(); + } + + //range=2 means 2 levels to draw labels for + + const uint start = m_focus->start(); + const uint end = m_focus->end(); //boundary angles + const uint minAngle = int(m_focus->length() * LABEL_MIN_ANGLE_FACTOR); + + + //**** Levels should be on a scale starting with 0 + //**** range is a useless parameter + //**** keep a topblock var which is the lowestLevel OR startLevel for indentation purposes + for (unsigned int i = startLevel; i <= m_map.m_visibleDepth; ++i) { + for (const Segment *segment : m_map.m_signature[i]) { + if (segment->start() >= start && segment->end() <= end) { + if (segment->length() > minAngle) { + list.append(new Label(segment, i)); + } + } + } + } + } else { + for (Segment *segment : *m_map.m_signature) { + if (segment->length() > 288) { + list.append(new Label(segment, 0)); + + } + } + } + + std::sort(list.begin(), list.end(), [](Label *item1, Label *item2) { + //you add 1440 to work round the fact that later you want the circle split vertically + //and as it is you start at 3 o' clock. It's to do with rightPrevY, stops annoying bug + + int angle1 = (item1)->angle + 1440; + int angle2 = (item2)->angle + 1440; + + // Also sort by level + if (angle1 == angle2) { + return (item1->level > item2->level); + } + + if (angle1 > 5760) angle1 -= 5760; + if (angle2 > 5760) angle2 -= 5760; + + return (angle1 < angle2); + + }); + + //2. Check to see if any adjacent labels are too close together + // if so, remove it (the least significant labels, since we sort by level too). + + int pos = 0; + while (pos < list.size() - 1) { + if (list[pos]->tooClose(list[pos+1]->angle)) { + delete list.takeAt(pos+1); + } else { + ++pos; + } + } + + //used in next two steps + bool varySizes; + //**** should perhaps use doubles + int *sizes = new int [ m_map.m_visibleDepth + 1 ]; //**** make sizes an array of floats I think instead (or doubles) + + // If the minimum is larger than the default it fucks up further down + if (paint.font().pointSize() < 0 || + paint.font().pointSize() < Config::minFontPitch) { + QFont font = paint.font(); + font.setPointSize(Config::minFontPitch); + paint.setFont(font); + } + + QVector::iterator it; + + do { + //3. Calculate font sizes + + { + //determine current range of levels to draw for + uint range = 0; + + for (Label *label : list) { + range = qMax(range, label->level); + + //**** better way would just be to assign if nothing is range + } + + range -= startLevel; //range 0 means 1 level of labels + + varySizes = Config::varyLabelFontSizes && (range != 0); + + if (varySizes) { + //create an array of font sizes for various levels + //will exceed normal font pitch automatically if necessary, but not minPitch + //**** this needs to be checked lots + + //**** what if this is negative (min size gtr than default size) + uint step = (paint.font().pointSize() - Config::minFontPitch) / range; + if (step == 0) { + step = 1; + } + + for (uint x = range + startLevel, y = Config::minFontPitch; x >= startLevel; y += step, --x) { + sizes[x] = y; + } + } + } + + //4. determine label co-ordinates + + + const int preSpacer = int(m_map.m_ringBreadth * 0.5) + m_map.m_innerRadius; + const int fullStrutLength = (m_map.width() - m_map.MAP_2MARGIN) / 2 + LABEL_MAP_SPACER; //full length of a strut from map center + + int prevLeftY = 0; + int prevRightY = height(); + + QFont font; + + for (it = list.begin(); it != list.end(); ++it) { + Label *label = *it; + //** bear in mind that text is drawn with QPoint param as BOTTOM left corner of text box + QString string = label->segment->file()->displayName(); + if (varySizes) { + font.setPointSize(sizes[label->level]); + } + QFontMetrics fontMetrics(font); + const int minTextWidth = fontMetrics.width(QString::fromLatin1("M...")) + LABEL_TEXT_HMARGIN; // Fully elided string + + const int fontHeight = fontMetrics.height() + LABEL_TEXT_VMARGIN; //used to ensure label texts don't overlap + const int lineSpacing = fontHeight / 4; + + const bool rightSide = (label->angle < 1440 || label->angle > 4320); + + double sinra, cosra; + const double ra = M_PI/2880 * label->angle; //convert to radians + sincos(ra, &sinra, &cosra); + + + const int spacer = preSpacer + m_map.m_ringBreadth * label->level; + + const int centerX = m_map.width() / 2 + m_offset.x(); //centre relative to canvas + const int centerY = m_map.height() / 2 + m_offset.y(); + int targetX = centerX + cosra * spacer; + int targetY = centerY - sinra * spacer; + int startX = targetX + cosra * (fullStrutLength - spacer + m_map.m_ringBreadth / 2); + int startY = targetY - sinra * (fullStrutLength - spacer); + + if (rightSide) { //righthand side, going upwards + if (startY > prevRightY /*- fmh*/) { //then it is too low, needs to be drawn higher + startY = prevRightY /*- fmh*/; + } + } else {//lefthand side, going downwards + if (startY < prevLeftY/* + fmh*/) { //then we're too high, need to be drawn lower + startY = prevLeftY /*+ fmh*/; + } + } + + int middleX = targetX - (startY - targetY) / tan(ra); + int textY = startY + lineSpacing; + + int textX; + const int textWidth = fontMetrics.width(string) + LABEL_TEXT_HMARGIN; + if (rightSide) { + if (startX + minTextWidth > width() || textY < fontHeight || middleX < targetX) { + //skip this strut + //**** don't duplicate this code + list.erase(it); //will delete the label and set it to list.current() which _should_ be the next ptr + break; + } + + prevRightY = textY - fontHeight - lineSpacing; //must be after above's "continue" + + if (m_offset.x() + m_map.width() + textWidth < width()) { + startX = m_offset.x() + m_map.width(); + } else { + startX = qMax(width() - textWidth, startX); + string = fontMetrics.elidedText(string, Qt::ElideMiddle, width() - startX); + } + + textX = startX + LABEL_TEXT_HMARGIN; + } else { // left side + if (startX - minTextWidth < 0 || textY > height() || middleX > targetX) { + //skip this strut + list.erase(it); //will delete the label and set it to list.current() which _should_ be the next ptr + break; + } + + prevLeftY = textY + fontHeight - lineSpacing; + + if (m_offset.x() - textWidth > 0) { + startX = m_offset.x(); + textX = startX - textWidth - LABEL_TEXT_HMARGIN; + } else { + textX = 0; + string = fontMetrics.elidedText(string, Qt::ElideMiddle, startX); + startX = fontMetrics.width(string) + LABEL_TEXT_HMARGIN; + } + } + + label->targetX = targetX; + label->targetY = targetY; + label->middleX = middleX; + label->startY = startY; + label->startX = startX; + label->textX = textX; + label->textY = textY; + label->qs = string; + } + + //if an element is deleted at this stage, we need to do this whole + //iteration again, thus the following loop + //**** in rare case that deleted label was last label in top level + // and last in labelList too, this will not work as expected (not critical) + + } while (it != list.end()); + + + //5. Render labels + + QFont font; + for (Label *label : list) { + if (varySizes) { + //**** how much overhead in making new QFont each time? + // (implicate sharing remember) + font.setPointSize(sizes[label->level]); + paint.setFont(font); + } + + paint.drawLine(label->targetX, label->targetY, label->middleX, label->startY); + paint.drawLine(label->middleX, label->startY, label->startX, label->startY); + + paint.drawText(label->textX, label->textY, label->qs); + } + + qDeleteAll(list); + delete [] sizes; +} +} + diff --git a/test/radialmap/radialMap/map.cpp b/test/radialmap/radialMap/map.cpp new file mode 100644 index 0000000..16d492b --- /dev/null +++ b/test/radialmap/radialMap/map.cpp @@ -0,0 +1,413 @@ +/*********************************************************************** +* Copyright 2003-2004 Max Howell +* Copyright 2008-2009 Martin Sandsmark +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +***********************************************************************/ + +#include //make() +#include //make() & paint() +#include //ctor +#include //ctor +#include +#include + +#include "radialMap.h" // defines + +#include "Config.h" +#include "fileTree.h" +#define SINCOS_H_IMPLEMENTATION (1) +#include "sincos.h" +#include "widget.h" + +RadialMap::Map::Map() + : m_signature(nullptr) + , m_visibleDepth(DEFAULT_RING_DEPTH) + , m_ringBreadth(MIN_RING_BREADTH) + , m_innerRadius(0) +{ + + //FIXME this is all broken. No longer is a maximum depth! + const int fmh = QFontMetrics(QFont()).height(); + const int fmhD4 = fmh / 4; + MAP_2MARGIN = 2 * (fmh - (fmhD4 - LABEL_MAP_SPACER)); //margin is dependent on fitting in labels at top and bottom + + m_minSize=27300; +} + +RadialMap::Map::~Map() +{ + delete [] m_signature; +} + +void RadialMap::Map::invalidate() +{ + delete [] m_signature; + m_signature = nullptr; + + m_visibleDepth = Config::defaultRingDepth; +} + +void RadialMap::Map::make(const Folder *tree, bool refresh) +{ + if(height()<1) + abort(); + //slow operation so set the wait cursor + QApplication::setOverrideCursor(Qt::WaitCursor); + + //build a signature of visible components + { + //**** REMOVE NEED FOR the +1 with MAX_RING_DEPTH uses + //**** add some angle bounds checking (possibly in Segment ctor? can I delete in a ctor?) + //**** this is a mess + + delete [] m_signature; + m_signature = new QList[m_visibleDepth + 1]; + + m_root = tree; + + if (!refresh) { + quint64 varSize=tree->size(); + quint64 varHeight=height(); + quint64 varA=(varSize * 3); + quint64 varB=(PI * varHeight - MAP_2MARGIN); + m_minSize = varA / varB; + findVisibleDepth(tree); + } + + setRingBreadth(); + + // Calculate ring size limits + m_limits.resize(m_visibleDepth + 1); + const double size = m_root->size(); + const double pi2B = M_PI * 4 * m_ringBreadth; + for (uint depth = 0; depth <= m_visibleDepth; ++depth) { + m_limits[depth] = uint(size / double(pi2B * (depth + 1))); //min is angle that gives 3px outer diameter for that depth + } + + build(tree); + } + + //colour the segments + colorise(); + + m_centerText = tree->humanReadableSize(); + + //paint the pixmap + paint(); + + QApplication::restoreOverrideCursor(); +} + +void RadialMap::Map::setRingBreadth() +{ + //FIXME called too many times on creation + + m_ringBreadth = (height() - MAP_2MARGIN) / (2 * m_visibleDepth + 4); + m_ringBreadth = qBound(MIN_RING_BREADTH, m_ringBreadth, MAX_RING_BREADTH); +} + +void RadialMap::Map::findVisibleDepth(const Folder *dir, uint currentDepth) +{ + + //**** because I don't use the same minimumSize criteria as in the visual function + // this can lead to incorrect visual representation + //**** BUT, you can't set those limits until you know m_depth! + + //**** also this function doesn't check to see if anything is actually visible + // it just assumes that when it reaches a new level everything in it is visible + // automatically. This isn't right especially as there might be no files in the + // dir provided to this function! + + static uint stopDepth = 0; + + if (dir == m_root) { + stopDepth = m_visibleDepth; + m_visibleDepth = 0; + } + + if (m_visibleDepth < currentDepth) m_visibleDepth = currentDepth; + if (m_visibleDepth >= stopDepth) return; + + for (File *file : dir->files) { + if (file->isFolder() && file->size() > m_minSize) { + findVisibleDepth((Folder *)file, currentDepth + 1); //if no files greater than min size the depth is still recorded + } + } +} + +//**** segments currently overlap at edges (i.e. end of first is start of next) +bool RadialMap::Map::build(const Folder * const dir, const uint depth, uint a_start, const uint a_end) +{ + //first iteration: dir == m_root + + if (dir->children() == 0) //we do fileCount rather than size to avoid chance of divide by zero later + return false; + + FileSize hiddenSize = 0; + uint hiddenFileCount = 0; + + for (File *file : dir->files) { + if (file->size() < m_limits[depth] * 6) { // limit is half a degree? we want at least 3 degrees + hiddenSize += file->size(); + if (file->isFolder()) { //**** considered virtual, but dir wouldn't count itself! + hiddenFileCount += static_cast(file)->children(); //need to add one to count the dir as well + } + ++hiddenFileCount; + continue; + } + + unsigned int a_len = (unsigned int)(5760 * ((double)file->size() / (double)m_root->size())); + + Segment *s = new Segment(file, a_start, a_len); + m_signature[depth].append(s); + + if (file->isFolder()) { + if (depth != m_visibleDepth) { + //recurse + s->m_hasHiddenChildren = build((Folder*)file, depth + 1, a_start, a_start + a_len); + } else { + s->m_hasHiddenChildren = true; + } + } + + a_start += a_len; //**** should we add 1? + } + + if (hiddenFileCount == dir->children() && !Config::showSmallFiles) { + return true; + } + + if ((depth == 0 || Config::showSmallFiles) && hiddenSize >= m_limits[depth] && hiddenFileCount > 0) { + //append a segment for unrepresented space - a "fake" segment + const QString s = QObject::tr("1 file, with an average size of %2", + "%1 files, with an average size of %2").arg(hiddenFileCount) + .arg(QString::number(hiddenSize/hiddenFileCount)); + + + (m_signature + depth)->append(new Segment(new File(s.toUtf8().constData(), hiddenSize), a_start, a_end - a_start, true)); + } + + return false; +} + +bool RadialMap::Map::resize(const QRect &rect) +{ + //there's a MAP_2MARGIN border + +#define mw width() +#define mh height() +#define cw rect.width() +#define ch rect.height() + + if (cw < mw || ch < mh || (cw > mw && ch > mh)) + { + uint size = ((cw < ch) ? cw : ch) - MAP_2MARGIN; + + //this also causes uneven sizes to always resize when resizing but map is small in that dimension + //size -= size % 2; //even sizes mean less staggered non-antialiased resizing + + { + const uint minSize = MIN_RING_BREADTH * 2 * (m_visibleDepth + 2); + + if (size < minSize) + size = minSize; + + //this QRect is used by paint() + m_rect.setRect(0,0,size,size); + } + m_pixmap = QPixmap(m_rect.size()); + + //resize the pixmap + size += MAP_2MARGIN; + + if (m_signature != nullptr) + { + setRingBreadth(); + paint(); + } + + return true; + } + +#undef mw +#undef mh +#undef cw +#undef ch + + return false; +} + +void RadialMap::Map::colorise() +{ + if (!m_signature || m_signature->isEmpty()) { + qDebug() << "no signature yet"; + return; + } + + QColor cp, cb; + double darkness = 1; + double contrast = (double)Config::contrast / (double)100; + int h, s1, s2, v1, v2; + + for (uint i = 0; i <= m_visibleDepth; ++i, darkness += 0.04) { + for (Segment *segment : m_signature[i]) { + h = int(segment->start() / 16); + s1 = 160; + v1 = (int)(255.0 / darkness); //doing this more often than once seems daft! + + v2 = v1 - int(contrast * v1); + s2 = s1 + int(contrast * (255 - s1)); + + if (s1 < 80) s1 = 80; //can fall too low and makes contrast between the files hard to discern + + if (segment->isFake()) { //multi-file + cb.setHsv(h, s2, (v2 < 90) ? 90 : v2); //too dark if < 100 + cp.setHsv(h, 17, v1); + } else if (!segment->file()->isFolder()) { //file + cb.setHsv(h, 17, v1); + cp.setHsv(h, 17, v2); + } else { //folder + cb.setHsv(h, s1, v1); //v was 225 + cp.setHsv(h, s2, v2); //v was 225 - delta + } + + segment->setPalette(cp, cb); + } + } +} + +void RadialMap::Map::paint(bool antialias) +{ + QPainter paint; + QRect rect = m_rect; + + rect.adjust(5, 5, -5, -5); + m_pixmap.fill(QColor(255,255,255)); + + //m_rect.moveRight(1); // Uncommenting this breaks repainting when recreating map from cache + + + //**** best option you can think of is to make the circles slightly less perfect, + // ** i.e. slightly eliptic when resizing inbetween + + if (m_pixmap.isNull()) + return; + + if (!paint.begin(&m_pixmap)) { + qWarning() << "Filelight::RadialMap Failed to initialize painting, returning..."; + return; + } + + if (antialias && Config::antialias) { + paint.translate(0.7, 0.7); + paint.setRenderHint(QPainter::Antialiasing); + } + + int step = m_ringBreadth; + int excess = -1; + + //do intelligent distribution of excess to prevent nasty resizing + if (m_ringBreadth != MAX_RING_BREADTH && m_ringBreadth != MIN_RING_BREADTH) { + excess = rect.width() % m_ringBreadth; + ++step; + } + + + for (int x = m_visibleDepth; x >= 0; --x) + { + int width = rect.width() / 2; + //clever geometric trick to find largest angle that will give biggest arrow head + uint a_max = int(acos((double)width / double((width + 5))) * (180*16 / M_PI)); + + for (Segment *segment : m_signature[x]) { + //draw the pie segments, most of this code is concerned with drawing the little + //arrows on the ends of segments when they have hidden files + + paint.setPen(segment->pen()); + + if (segment->hasHiddenChildren()) + { + //draw arrow head to indicate undisplayed files/directories + QPolygon pts(3); + QPoint pos, cpos = rect.center(); + uint a[3] = { segment->start(), segment->length(), 0 }; + + a[2] = a[0] + (a[1] / 2); //assign to halfway between + if (a[1] > a_max) + { + a[1] = a_max; + a[0] = a[2] - a_max / 2; + } + + a[1] += a[0]; + + for (int i = 0, radius = width; i < 3; ++i) + { + double ra = M_PI/(180*16) * a[i], sinra, cosra; + + if (i == 2) + radius += 5; + sincos(ra, &sinra, &cosra); + pos.rx() = cpos.x() + static_cast(cosra * radius); + pos.ry() = cpos.y() - static_cast(sinra * radius); + pts.setPoint(i, pos); + } + + paint.setBrush(segment->pen()); + paint.drawPolygon(pts); + } + + paint.setBrush(segment->brush()); + paint.drawPie(rect, segment->start(), segment->length()); + + if (segment->hasHiddenChildren()) + { + //**** code is bloated! + paint.save(); + QPen pen = paint.pen(); + int width = 2; + pen.setWidth(width); + paint.setPen(pen); + QRect rect2 = rect; + width /= 2; + rect2.adjust(width, width, -width, -width); + paint.drawArc(rect2, segment->start(), segment->length()); + paint.restore(); + } + } + + if (excess >= 0) { //excess allows us to resize more smoothly (still crud tho) + if (excess < 2) //only decrease rect by more if even number of excesses left + --step; + excess -= 2; + } + + rect.adjust(step, step, -step, -step); + } + + // if(excess > 0) rect.addCoords(excess, excess, 0, 0); //ugly + + paint.setPen(QColor(0,0,0)); + paint.setBrush(QColor(255,255,255)); + paint.drawEllipse(rect); + paint.drawText(rect, Qt::AlignCenter, m_centerText); + + m_innerRadius = rect.width() / 2; //rect.width should be multiple of 2 + + paint.end(); +} diff --git a/test/radialmap/radialMap/map.h b/test/radialmap/radialMap/map.h new file mode 100644 index 0000000..da899b0 --- /dev/null +++ b/test/radialmap/radialMap/map.h @@ -0,0 +1,84 @@ +/*********************************************************************** +* Copyright 2003-2004 Max Howell +* Copyright 2008-2009 Martin Sandsmark +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +***********************************************************************/ + +#ifndef MAP_H +#define MAP_H + +#include "fileTree.h" + +#include +#include +#include + +namespace RadialMap { +class Segment; + +class Map +{ +public: + explicit Map(); + ~Map(); + + void make(const Folder *, bool = false); + bool resize(const QRect&); + + bool isNull() const { + return (m_signature == nullptr); + } + void invalidate(); + + int height() const { + return m_rect.height(); + } + int width() const { + return m_rect.width(); + } + QPixmap pixmap() const { + return m_pixmap; + } + + + friend class Widget; + +private: + void paint(bool antialias = true); + void colorise(); + void setRingBreadth(); + void findVisibleDepth(const Folder *dir, uint currentDepth = 0); + bool build(const Folder* const dir, const uint depth =0, uint a_start =0, const uint a_end =5760); + + QList *m_signature; + + const Folder *m_root; + uint m_minSize; + QVector m_limits; + QRect m_rect; + uint m_visibleDepth; ///visible level depth of system + QPixmap m_pixmap; + int m_ringBreadth; + uint m_innerRadius; ///radius of inner circle + QString m_centerText; + + uint MAP_2MARGIN; +}; +} + +#endif diff --git a/test/radialmap/radialMap/radialMap.h b/test/radialmap/radialMap/radialMap.h new file mode 100644 index 0000000..5bbba10 --- /dev/null +++ b/test/radialmap/radialMap/radialMap.h @@ -0,0 +1,109 @@ +/*********************************************************************** +* Copyright 2003-2004 Max Howell +* Copyright 2008-2009 Martin Sandsmark +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +***********************************************************************/ + +#ifndef RADIALMAP_H +#define RADIALMAP_H + +#include + +class File; + +namespace RadialMap +{ +class Segment //all angles are in 16ths of degrees +{ +public: + Segment(const File *f, uint s, uint l, bool isFake = false) + : m_angleStart(s) + , m_angleSegment(l) + , m_file(f) + , m_hasHiddenChildren(false) + , m_fake(isFake) {} + ~Segment(); + + uint start() const { + return m_angleStart; + } + uint length() const { + return m_angleSegment; + } + uint end() const { + return m_angleStart + m_angleSegment; + } + const File *file() const { + return m_file; + } + const QColor& pen() const { + return m_pen; + } + const QColor& brush() const { + return m_brush; + } + + bool isFake() const { + return m_fake; + } + bool hasHiddenChildren() const { + return m_hasHiddenChildren; + } + + bool intersects(uint a) const { + return ((a >= start()) && (a < end())); + } + + friend class Map; + friend class Builder; + +private: + void setPalette(const QColor &p, const QColor &b) { + m_pen = p; + m_brush = b; + } + + const uint m_angleStart, m_angleSegment; + const File* const m_file; + QColor m_pen, m_brush; + bool m_hasHiddenChildren; + const bool m_fake; +}; +} + + +#ifndef PI +#define PI 3.141592653589793 +#endif +#ifndef M_PI +#define M_PI 3.14159265358979323846264338327 +#endif + +#define MIN_RING_BREADTH 20 +#define MAX_RING_BREADTH 60 +#define DEFAULT_RING_DEPTH 4 //first level = 0 +#define MIN_RING_DEPTH 0 + +#define LABEL_MAP_SPACER 7 +#define LABEL_TEXT_HMARGIN 5 +#define LABEL_TEXT_VMARGIN 0 +#define LABEL_ANGLE_MARGIN 32 +#define LABEL_MIN_ANGLE_FACTOR 0.05 +#define LABEL_MAX_CHARS 30 + +#endif diff --git a/test/radialmap/radialMap/sincos.h b/test/radialmap/radialMap/sincos.h new file mode 100644 index 0000000..2fe716d --- /dev/null +++ b/test/radialmap/radialMap/sincos.h @@ -0,0 +1,45 @@ +/*********************************************************************** +* Copyright 2003-2004 Max Howell +* Copyright 2008-2009 Martin Sandsmark +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +***********************************************************************/ + +#ifndef SINCOS_H +#define SINCOS_H + +#include + +#if !defined(__GLIBC__) || (__GLIBC__ < 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1) + +#include + +void +sincos(double angleRadians, double *Sin, double *Cos); + +#ifdef SINCOS_H_IMPLEMENTATION +void +sincos(double angleRadians, double *Sin, double *Cos) +{ + *Sin = qSin(angleRadians); + *Cos = qCos(angleRadians); +} +#endif + +#endif + +#endif diff --git a/test/radialmap/radialMap/widget.cpp b/test/radialmap/radialMap/widget.cpp new file mode 100644 index 0000000..145de20 --- /dev/null +++ b/test/radialmap/radialMap/widget.cpp @@ -0,0 +1,191 @@ +/*********************************************************************** +* Copyright 2003-2004 Max Howell +* Copyright 2008-2009 Martin Sandsmark +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +***********************************************************************/ + +#include "widget.h" + +#include "Config.h" +#include "fileTree.h" +#include "radialMap.h" //constants +#include "map.h" + +#include + +#include //sendEvent +#include //ctor - finding cursor size +#include //slotPostMouseEvent() +#include //member +#include + + +RadialMap::Widget::Widget(QWidget *parent) + : QWidget(parent) + , m_tree(nullptr) + , m_focus(nullptr) + , m_map() + , m_rootSegment(nullptr) //TODO we don't delete it, *shrug* + , m_toBeDeleted(nullptr) +{ + setAcceptDrops(true); + setMinimumSize(350, 250); + + connect(this, &Widget::folderCreated, this, &Widget::sendFakeMouseEvent); + connect(&m_timer, &QTimer::timeout, this, &Widget::resizeTimeout); + m_tooltip.setFrameShape(QFrame::StyledPanel); + m_tooltip.setWindowFlags(Qt::ToolTip | Qt::WindowTransparentForInput); +} + +RadialMap::Widget::~Widget() +{ + delete m_rootSegment; +} + + +QString RadialMap::Widget::path() const +{ + return m_tree->displayPath(); +} + +QUrl RadialMap::Widget::url(File const * const file) const +{ + return file ? file->url() : m_tree->url(); +} + +void RadialMap::Widget::invalidate() +{ + if (isValid()) + { + //**** have to check that only way to invalidate is this function frankly + //**** otherwise you may get bugs.. + + //disable mouse tracking + setMouseTracking(false); + + // Get this before reseting m_tree below + QUrl invalidatedUrl(url()); + + //ensure this class won't think we have a map still + m_tree = nullptr; + m_focus = nullptr; + + delete m_rootSegment; + m_rootSegment = nullptr; + + //FIXME move this disablement thing no? + // it is confusing in other areas, like the whole createFromCache() thing + m_map.invalidate(); + update(); + + //tell rest of Filelight + emit invalidated(invalidatedUrl); + } +} + +void +RadialMap::Widget::create(const Folder *tree) +{ + //it is not the responsibility of create() to invalidate first + //skip invalidation at your own risk + + //FIXME make it the responsibility of create to invalidate first + + if (tree) + { + m_focus = nullptr; + //generate the filemap image + m_map.make(tree); + + //this is the inner circle in the center + m_rootSegment = new Segment(tree, 0, 16*360); + + setMouseTracking(true); + } + + m_tree = tree; + + //tell rest of Filelight + emit folderCreated(tree); +} + +void +RadialMap::Widget::createFromCache(const Folder *tree) +{ + //no scan was necessary, use cached tree, however we MUST still emit invalidate + invalidate(); + create(tree); +} + +void +RadialMap::Widget::sendFakeMouseEvent() //slot +{ + QMouseEvent me(QEvent::MouseMove, mapFromGlobal(QCursor::pos()), Qt::NoButton, Qt::NoButton, Qt::NoModifier); + QApplication::sendEvent(this, &me); + update(); +} + +void +RadialMap::Widget::resizeTimeout() //slot +{ + // the segments are about to erased! + // this was a horrid bug, and proves the OO programming should be obeyed always! + m_focus = nullptr; + if (m_tree) + m_map.make(m_tree, true); + update(); +} + +void +RadialMap::Widget::refresh(int filth) +{ + //TODO consider a more direct connection + + if (!m_map.isNull()) + { + switch (filth) + { + case 1: + m_focus=nullptr; + m_map.make(m_tree, true); //true means refresh only + break; + + case 2: + m_map.paint(true); //antialiased painting + break; + + case 3: + m_map.colorise(); //FALL THROUGH! + case 4: + m_map.paint(); + + default: + break; + } + + update(); + } +} + +RadialMap::Segment::~Segment() +{ + if (isFake()) + delete m_file; //created by us in Builder::build() +} + + diff --git a/test/radialmap/radialMap/widget.h b/test/radialmap/radialMap/widget.h new file mode 100644 index 0000000..35d1f1d --- /dev/null +++ b/test/radialmap/radialMap/widget.h @@ -0,0 +1,112 @@ +/*********************************************************************** +* Copyright 2003-2004 Max Howell +* Copyright 2008-2009 Martin Sandsmark +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +***********************************************************************/ + +#ifndef WIDGET_H +#define WIDGET_H + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "map.h" + +class Folder; +class File; +namespace KIO { +class Job; +} + +namespace RadialMap +{ +class Segment; + +class Widget : public QWidget +{ + Q_OBJECT + +public: + explicit Widget(QWidget* = nullptr); + ~Widget() override; + QString path() const; + QUrl url(File const * const = nullptr) const; + + bool isValid() const { + return m_tree != nullptr; + } + + friend class Label; //FIXME badness + +public Q_SLOTS: + void create(const Folder*); + void invalidate(); + void refresh(int); + +private Q_SLOTS: + void resizeTimeout(); + void sendFakeMouseEvent(); + void createFromCache(const Folder*); + +Q_SIGNALS: + void activated(const QUrl&); + void invalidated(const QUrl&); + void folderCreated(const Folder*); + void mouseHover(const QString&); + void giveMeTreeFor(const QUrl&); + +protected: + void changeEvent(QEvent*) override; + void mouseMoveEvent(QMouseEvent*) override; + void paintEvent(QPaintEvent*) override; + void resizeEvent(QResizeEvent*) override; + void enterEvent(QEvent*) override; + void leaveEvent(QEvent*) override; + +protected: + const Segment *segmentAt(QPoint&) const; //FIXME const reference for a library others can use + const Segment *rootSegment() const { + return m_rootSegment; ///never == 0 + } + const Segment *focusSegment() const { + return m_focus; ///0 == nothing in focus + } + +private: + void paintExplodedLabels(QPainter&) const; + + const Folder *m_tree; + const Segment *m_focus; + QPoint m_offset; + QTimer m_timer; + Map m_map; + Segment *m_rootSegment; + const Segment *m_toBeDeleted; + QLabel m_tooltip; +}; +} + +#endif diff --git a/test/radialmap/radialMap/widgetEvents.cpp b/test/radialmap/radialMap/widgetEvents.cpp new file mode 100644 index 0000000..0dd980d --- /dev/null +++ b/test/radialmap/radialMap/widgetEvents.cpp @@ -0,0 +1,212 @@ +/*********************************************************************** +* Copyright 2003-2004 Max Howell +* Copyright 2008-2009 Martin Sandsmark +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +***********************************************************************/ + +#include "fileTree.h" +#include "Config.h" +#include "radialMap.h" //class Segment +#include "widget.h" + +#include //::mousePressEvent() +#include + +#include //QApplication::setOverrideCursor() +#include +#include +#include //::resizeEvent() +#include +#include +#include +#include +#include +#include +#include + +#include //::segmentAt() + +void RadialMap::Widget::resizeEvent(QResizeEvent*) +{ + if (m_map.resize(rect())) + m_timer.setSingleShot(true); + m_timer.start(500); //will cause signature to rebuild for new size + + //always do these as they need to be initialised on creation + m_offset.rx() = (width() - m_map.width()) / 2; + m_offset.ry() = (height() - m_map.height()) / 2; +} + +void RadialMap::Widget::paintEvent(QPaintEvent*) +{ + QPainter paint; + paint.begin(this); + + if (!m_map.isNull()) + paint.drawPixmap(m_offset, m_map.pixmap()); + else + { + paint.drawText(rect(), 0, tr("We messed up, the user needs to initiate a rescan.")); + return; + } + + //exploded labels + if (!m_map.isNull() && !m_timer.isActive()) + { + if (Config::antialias) { + paint.setRenderHint(QPainter::Antialiasing); + //make lines appear on pixel boundaries + paint.translate(0.5, 0.5); + } + paintExplodedLabels(paint); + } +} + +const RadialMap::Segment* RadialMap::Widget::segmentAt(QPoint &e) const +{ + //determine which segment QPoint e is above + + e -= m_offset; + + if (!m_map.m_signature) + return nullptr; + + if (e.x() <= m_map.width() && e.y() <= m_map.height()) + { + //transform to cartesian coords + e.rx() -= m_map.width() / 2; //should be an int + e.ry() = m_map.height() / 2 - e.y(); + + double length = hypot(e.x(), e.y()); + + if (length >= m_map.m_innerRadius) //not hovering over inner circle + { + uint depth = ((int)length - m_map.m_innerRadius) / m_map.m_ringBreadth; + + if (depth <= m_map.m_visibleDepth) //**** do earlier since you can //** check not outside of range + { + //vector calculation, reduces to simple trigonometry + //cos angle = (aibi + ajbj) / albl + //ai = x, bi=1, aj=y, bj=0 + //cos angle = x / (length) + + uint a = (uint)(acos((double)e.x() / length) * 916.736); //916.7324722 = #radians in circle * 16 + + //acos only understands 0-180 degrees + if (e.y() < 0) a = 5760 - a; + + for (Segment *segment : m_map.m_signature[depth]) { + if (segment->intersects(a)) + return segment; + } + } + } + else return m_rootSegment; //hovering over inner circle + } + + return nullptr; +} + +void RadialMap::Widget::mouseMoveEvent(QMouseEvent *e) +{ + //set m_focus to what we hover over, update UI if it's a new segment + + Segment const * const oldFocus = m_focus; + QPoint p = e->pos(); + + m_focus = segmentAt(p); //NOTE p is passed by non-const reference + + if (m_focus) + { + m_tooltip.move(e->globalX() + 20, e->globalY() + 20); + if (m_focus != oldFocus) //if not same as last time + { + setCursor(Qt::PointingHandCursor); + + QString string; + + + string = QObject::tr("Tooltip of file/folder, %1 is path, %2 is size") + .arg(m_focus->file()->displayPath()) + .arg(m_focus->file()->humanReadableSize()); + + if (m_focus->file()->isFolder()) { + int files = static_cast(m_focus->file())->children(); + const uint percent = uint((100 * files) / (double)m_tree->children()); + + string += QLatin1Char('\n'); + if (percent > 0) { + string += QObject::tr("Tooltip of folder, %1 File (%2%)") + .arg(files).arg(percent); + } else { + string += QObject::tr("Tooltip of folder, %1 File") + .arg(files); + } + } + + + // Calculate a semi-sane size for the tooltip + QFontMetrics fontMetrics(font()); + int tooltipWidth = 0; + int tooltipHeight = 0; + for (const QString &part : string.split(QLatin1Char('\n'))) { + tooltipHeight += fontMetrics.height(); + tooltipWidth = qMax(tooltipWidth, fontMetrics.width(part)); + } + // Limit it to the window size, probably should find something better + tooltipWidth = qMin(tooltipWidth, window()->width()); + tooltipWidth += 10; + tooltipHeight += 10; + m_tooltip.resize(tooltipWidth, tooltipHeight); + m_tooltip.setText(string); + m_tooltip.show(); + + emit mouseHover(m_focus->file()->displayPath()); + update(); + } + } + else if (oldFocus && oldFocus->file() != m_tree) + { + m_tooltip.hide(); + unsetCursor(); + update(); + + emit mouseHover(QString()); + } +} + +void RadialMap::Widget::enterEvent(QEvent *) +{ + if (!m_focus) return; + + setCursor(Qt::PointingHandCursor); + emit mouseHover(m_focus->file()->displayPath()); + update(); +} + +void RadialMap::Widget::leaveEvent(QEvent *) +{ + m_tooltip.hide(); +} + +void RadialMap::Widget::changeEvent(QEvent *e) +{ + if (e->type() == QEvent::ApplicationPaletteChange || + e->type() == QEvent::PaletteChange) + m_map.paint(); +} diff --git a/test/radialmap/radialmap.pro b/test/radialmap/radialmap.pro new file mode 100644 index 0000000..0a560ab --- /dev/null +++ b/test/radialmap/radialmap.pro @@ -0,0 +1,46 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2019-05-30T12:37:58 +# +#------------------------------------------------- + +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = radialmap +TEMPLATE = app + +# The following define makes your compiler emit warnings if you use +# any feature of Qt which has been marked as deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + + +SOURCES += \ + main.cpp \ + MainWindow.cpp \ + radialMap/labels.cpp \ + radialMap/map.cpp \ + radialMap/widgetEvents.cpp \ + radialMap/widget.cpp \ + fileTree.cpp \ + Config.cpp + +HEADERS += \ + MainWindow.h \ + radialMap/map.h \ + radialMap/widget.h \ + radialMap/radialMap.h \ + radialMap/sincos.h \ + fileTree.h \ + Config.h + +FORMS += \ + MainWindow.ui -- cgit v1.2.3