├── Qt-Color-Widgets ├── include │ └── QtColorWidgets │ │ ├── ColorDialog │ │ ├── ColorWheel │ │ ├── HueSlider │ │ ├── ColorDelegate │ │ ├── ColorPreview │ │ ├── ColorSelector │ │ ├── ColorListWidget │ │ ├── GradientEditor │ │ ├── GradientSlider │ │ ├── AbstractWidgetList │ │ ├── BoundColorSelector │ │ ├── GradientListModel │ │ ├── HarmonyColorWheel │ │ ├── colorwidgets_global.hpp │ │ ├── CMakeLists.txt │ │ ├── bound_color_selector.hpp │ │ ├── color_names.hpp │ │ ├── color_delegate.hpp │ │ ├── color_utils.hpp │ │ ├── color_list_widget.hpp │ │ ├── harmony_color_wheel.hpp │ │ ├── abstract_widget_list.hpp │ │ ├── gradient_helper.hpp │ │ ├── color_line_edit.hpp │ │ ├── hue_slider.hpp │ │ ├── color_selector.hpp │ │ ├── gradient_slider.hpp │ │ ├── gradient_delegate.hpp │ │ ├── color_2d_slider.hpp │ │ ├── color_preview.hpp │ │ ├── gradient_editor.hpp │ │ ├── color_palette_model.hpp │ │ ├── color_dialog.hpp │ │ ├── gradient_list_model.hpp │ │ ├── color_wheel.hpp │ │ ├── swatch.hpp │ │ ├── color_palette_widget.hpp │ │ └── color_palette.hpp ├── resources │ └── QtColorWidgets │ │ ├── color_widgets.qrc │ │ ├── alphaback.png │ │ └── CMakeLists.txt ├── src │ └── QtColorWidgets │ │ ├── color_dialog.cpp │ │ ├── CMakeLists.txt │ │ ├── bound_color_selector.cpp │ │ ├── color_utils.cpp │ │ ├── color_names.cpp │ │ ├── hue_slider.cpp │ │ ├── color_list_widget.cpp │ │ ├── color_delegate.cpp │ │ ├── color_selector.cpp │ │ ├── abstract_widget_list.cpp │ │ ├── color_preview.cpp │ │ ├── color_line_edit.cpp │ │ ├── color_palette_widget.ui │ │ ├── harmony_color_wheel.cpp │ │ ├── color_2d_slider.cpp │ │ └── gradient_slider.cpp └── color_widgets.pri ├── GUI.png ├── data ├── img_s.png └── palette.obj ├── paletteviewwidget.cpp ├── main.cpp ├── rgbwidget.h ├── opengl3dwidget.h ├── imagewidget.h ├── paletteviewwidget.h ├── mainwindow.h ├── openglwidget.h ├── RgbPalette_Recolor_GUI.sln ├── image2mp4.py ├── README.md ├── opengl3dwidget.cpp ├── imagewidget.cpp ├── RgbPalette_Recolor_GUI.pro ├── data.h ├── my_util.h ├── openglwidget.cpp ├── utility.h ├── rgbwidget.cpp ├── vec3.h └── utility.cpp /Qt-Color-Widgets/include/QtColorWidgets/ColorDialog: -------------------------------------------------------------------------------- 1 | #include "color_dialog.hpp" 2 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/ColorWheel: -------------------------------------------------------------------------------- 1 | #include "color_wheel.hpp" 2 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/HueSlider: -------------------------------------------------------------------------------- 1 | #include "hue_slider.hpp" 2 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/ColorDelegate: -------------------------------------------------------------------------------- 1 | #include "color_delegate.hpp" 2 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/ColorPreview: -------------------------------------------------------------------------------- 1 | #include "color_preview.hpp" 2 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/ColorSelector: -------------------------------------------------------------------------------- 1 | #include "color_selector.hpp" 2 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/ColorListWidget: -------------------------------------------------------------------------------- 1 | #include "color_list_widget.hpp" 2 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/GradientEditor: -------------------------------------------------------------------------------- 1 | #include "gradient_editor.hpp" 2 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/GradientSlider: -------------------------------------------------------------------------------- 1 | #include "gradient_slider.hpp" 2 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/AbstractWidgetList: -------------------------------------------------------------------------------- 1 | #include "abstract_widget_list.hpp" 2 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/BoundColorSelector: -------------------------------------------------------------------------------- 1 | #include "bound_color_selector.hpp" 2 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/GradientListModel: -------------------------------------------------------------------------------- 1 | #include "gradient_list_model.hpp" 2 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/HarmonyColorWheel: -------------------------------------------------------------------------------- 1 | #include "harmony_color_wheel.hpp" 2 | -------------------------------------------------------------------------------- /GUI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zhengjun-Du/Convexhull-based-Image-Recoloring-GUI/HEAD/GUI.png -------------------------------------------------------------------------------- /data/img_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zhengjun-Du/Convexhull-based-Image-Recoloring-GUI/HEAD/data/img_s.png -------------------------------------------------------------------------------- /paletteviewwidget.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zhengjun-Du/Convexhull-based-Image-Recoloring-GUI/HEAD/paletteviewwidget.cpp -------------------------------------------------------------------------------- /Qt-Color-Widgets/resources/QtColorWidgets/color_widgets.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | alphaback.png 4 | 5 | 6 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/src/QtColorWidgets/color_dialog.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zhengjun-Du/Convexhull-based-Image-Recoloring-GUI/HEAD/Qt-Color-Widgets/src/QtColorWidgets/color_dialog.cpp -------------------------------------------------------------------------------- /Qt-Color-Widgets/resources/QtColorWidgets/alphaback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zhengjun-Du/Convexhull-based-Image-Recoloring-GUI/HEAD/Qt-Color-Widgets/resources/QtColorWidgets/alphaback.png -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "mainwindow.h" 3 | #include "openglwidget.h" 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | using namespace std; 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | QApplication a(argc, argv); 14 | MainWindow w; 15 | w.show(); 16 | 17 | return a.exec(); 18 | } 19 | -------------------------------------------------------------------------------- /data/palette.obj: -------------------------------------------------------------------------------- 1 | v 0.19265958366850472 0.2449361096093332 0.6248451143203233 2 | v 0.9261599310002775 0.9749654614172395 1.0 3 | v 0.4414301759963405 0.850881832181207 0.9785412017079019 4 | v 0.0 0.0 0.0 5 | v 1.0 0.19304083417015647 7.081126416897743e-17 6 | v 1.0 0.8922744468227546 6.219342577385976e-17 7 | f 6 5 4 8 | f 2 5 6 9 | f 5 1 4 10 | f 1 5 2 11 | f 3 6 4 12 | f 3 2 6 13 | f 1 3 4 14 | f 3 1 2 15 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/resources/QtColorWidgets/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set (SOURCES 2 | alphaback.png 3 | color_widgets.qrc 4 | ) 5 | 6 | file(RELATIVE_PATH 7 | PREFIX 8 | ${PROJECT_SOURCE_DIR} 9 | ${CMAKE_CURRENT_LIST_DIR}) 10 | 11 | 12 | foreach (SOURCE IN LISTS SOURCES) 13 | target_sources (${TARGET_NAME} 14 | PRIVATE 15 | $) 16 | endforeach (SOURCE IN SOURCES) 17 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/colorwidgets_global.hpp: -------------------------------------------------------------------------------- 1 | #ifndef QT_COLOR_WIDGETS_GLOBAL_H 2 | #define QT_COLOR_WIDGETS_GLOBAL_H 3 | 4 | #include 5 | 6 | #if defined(QTCOLORWIDGETS_STATICALLY_LINKED) 7 | # define QCP_EXPORT 8 | #elif defined(QTCOLORWIDGETS_LIBRARY) 9 | # define QCP_EXPORT Q_DECL_EXPORT 10 | #else 11 | //# define QCP_EXPORT Q_DECL_IMPORT 12 | # define QCP_EXPORT 13 | #endif 14 | 15 | #endif // QT_COLOR_WIDGETS_GLOBAL_H 16 | -------------------------------------------------------------------------------- /rgbwidget.h: -------------------------------------------------------------------------------- 1 | #ifndef RGBWIDGET_H 2 | #define RGBWIDGET_H 3 | 4 | #include 5 | #include"data.h" 6 | #include 7 | 8 | class RGBWidget : public OpenGL3DWidget 9 | { 10 | protected: 11 | void paintGL() Q_DECL_OVERRIDE; 12 | void mouseMoveEvent(QMouseEvent *event) override; 13 | 14 | public: 15 | RGBWidget(); 16 | 17 | private: 18 | QSharedMemory sharedMemory; 19 | static double _rotate_x; 20 | static double _rotate_y; 21 | static double _rotate_z; 22 | }; 23 | 24 | #endif // RGBWIDGET_H 25 | -------------------------------------------------------------------------------- /opengl3dwidget.h: -------------------------------------------------------------------------------- 1 | #ifndef OPENGL3DWIDGET_H 2 | #define OPENGL3DWIDGET_H 3 | 4 | #include"openglwidget.h" 5 | 6 | class OpenGL3DWidget : public OpenGLWidget 7 | { 8 | public: 9 | OpenGL3DWidget(QWidget *parent = 0); 10 | protected: 11 | void paintGL() Q_DECL_OVERRIDE; 12 | void mousePressEvent(QMouseEvent *event) override; 13 | void mouseMoveEvent(QMouseEvent *event) override; 14 | protected: 15 | double rotate_x; 16 | double rotate_y; 17 | double rotate_z; 18 | private: 19 | QPoint lastPos; 20 | }; 21 | 22 | #endif // OPENGL3DWIDGET_H 23 | -------------------------------------------------------------------------------- /imagewidget.h: -------------------------------------------------------------------------------- 1 | #ifndef ImageWidget_H 2 | #define ImageWidget_H 3 | 4 | #include 5 | #include 6 | #include "data.h" 7 | 8 | class ImageWidget : public QWidget 9 | { 10 | Q_OBJECT 11 | public: 12 | explicit ImageWidget(bool _isAfter, QWidget *parent = nullptr); 13 | 14 | void setData(Data *value); 15 | 16 | protected: 17 | virtual void paintEvent(QPaintEvent *event); 18 | signals: 19 | 20 | public slots: 21 | void setTime(int t); 22 | void update(); 23 | 24 | protected: 25 | Data *data = nullptr; 26 | int time = 0; 27 | 28 | private: 29 | bool isAfter; 30 | }; 31 | 32 | #endif // ImageWidget_H 33 | -------------------------------------------------------------------------------- /paletteviewwidget.h: -------------------------------------------------------------------------------- 1 | #ifndef PALETTEVIEWWIDGET_H 2 | #define PALETTEVIEWWIDGET_H 3 | 4 | #include 5 | #include 6 | 7 | class PaletteViewWidget : public OpenGLWidget 8 | { 9 | Q_OBJECT 10 | public: 11 | explicit PaletteViewWidget(QWidget *parent = 0); 12 | 13 | protected: 14 | void paintGL() Q_DECL_OVERRIDE; 15 | void mousePressEvent(QMouseEvent *event) override; 16 | 17 | public Q_SLOTS: 18 | void getColor(QColor c); 19 | void setTime(int t_); 20 | 21 | void resetPaletteColor(); 22 | void resetAllPaletteColors(); 23 | 24 | Q_SIGNALS: 25 | void setColor(QColor c); 26 | 27 | private: 28 | bool blink = false; 29 | double scale = 1.95; 30 | int selected_vid = -1; 31 | double aspect = 1.0; 32 | int time = 0; 33 | 34 | vector palette_pos; 35 | QMenu *pMenu; 36 | }; 37 | 38 | #endif // PALETTEVIEWWIDGET_H 39 | -------------------------------------------------------------------------------- /mainwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class MainWindow : public QMainWindow 9 | { 10 | Q_OBJECT 11 | 12 | public: 13 | explicit MainWindow(QWidget *parent = nullptr); 14 | ~MainWindow(); 15 | 16 | private: 17 | QDockWidget *imageBeforeDockWidget = nullptr; 18 | QDockWidget *imageAfterDockWidget = nullptr; 19 | void exportImage(); 20 | void importPalette(); 21 | void exportPalette(); 22 | 23 | 24 | void openFile(bool merge); 25 | Data *data = nullptr; 26 | QSlider *slider = nullptr; 27 | QSlider *mergeStepSlider = nullptr; 28 | 29 | // QString title = "Video Recoloring Tool (Build " __DATE__ " " __TIME__ ")"; 30 | QString title = "Image Recoloring Tool"; 31 | 32 | bool isPlaying = false; 33 | }; 34 | 35 | #endif // MAINWINDOW_H 36 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/src/QtColorWidgets/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set (SOURCES 2 | abstract_widget_list.cpp 3 | bound_color_selector.cpp 4 | color_2d_slider.cpp 5 | color_delegate.cpp 6 | color_dialog.cpp 7 | color_dialog.ui 8 | color_line_edit.cpp 9 | color_list_widget.cpp 10 | color_names.cpp 11 | color_palette.cpp 12 | color_palette_model.cpp 13 | color_palette_widget.cpp 14 | color_palette_widget.ui 15 | color_preview.cpp 16 | color_selector.cpp 17 | color_utils.cpp 18 | color_wheel.cpp 19 | gradient_slider.cpp 20 | hue_slider.cpp 21 | swatch.cpp 22 | gradient_editor.cpp 23 | harmony_color_wheel.cpp 24 | gradient_list_model.cpp 25 | ) 26 | 27 | file(RELATIVE_PATH 28 | PREFIX 29 | ${PROJECT_SOURCE_DIR} 30 | ${CMAKE_CURRENT_LIST_DIR}) 31 | 32 | 33 | foreach (SOURCE IN LISTS SOURCES) 34 | target_sources (${TARGET_NAME} 35 | PRIVATE 36 | $) 37 | endforeach (SOURCE IN SOURCES) 38 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set (HEADERS 2 | abstract_widget_list.hpp 3 | bound_color_selector.hpp 4 | color_2d_slider.hpp 5 | color_delegate.hpp 6 | color_dialog.hpp 7 | color_line_edit.hpp 8 | color_list_widget.hpp 9 | color_names.hpp 10 | color_palette.hpp 11 | color_palette_model.hpp 12 | color_palette_widget.hpp 13 | color_preview.hpp 14 | color_selector.hpp 15 | color_wheel.hpp 16 | colorwidgets_global.hpp 17 | gradient_slider.hpp 18 | hue_slider.hpp 19 | swatch.hpp 20 | gradient_editor.hpp 21 | harmony_color_wheel.hpp 22 | gradient_list_model.hpp 23 | gradient_delegate.hpp 24 | ) 25 | 26 | file(RELATIVE_PATH 27 | PREFIX 28 | ${PROJECT_SOURCE_DIR} 29 | ${CMAKE_CURRENT_LIST_DIR}) 30 | 31 | 32 | foreach (HEADER IN LISTS HEADERS) 33 | target_sources (${TARGET_NAME} 34 | PRIVATE 35 | $ 36 | $) 37 | endforeach (HEADER IN HEADERS) 38 | -------------------------------------------------------------------------------- /openglwidget.h: -------------------------------------------------------------------------------- 1 | #ifndef OPENGLWIDGET_H 2 | #define OPENGLWIDGET_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include"data.h" 14 | 15 | class OpenGLWidget:public QOpenGLWidget, protected QOpenGLFunctions 16 | { 17 | public: 18 | explicit OpenGLWidget(QWidget *parent = 0); 19 | 20 | void setData(Data *value); 21 | 22 | public slots: 23 | void update(); 24 | void setTime(int t); 25 | void setShowImageData(bool _showImageData); 26 | void setPreview(int percentage); 27 | 28 | protected: 29 | void initializeGL() Q_DECL_OVERRIDE; 30 | void resizeGL(int w, int h) Q_DECL_OVERRIDE; 31 | void paintGL() Q_DECL_OVERRIDE; 32 | 33 | private: 34 | 35 | protected: 36 | Data *data = nullptr; 37 | 38 | int time = 0; 39 | 40 | bool showImageData = true; 41 | double preview =.25; 42 | 43 | }; 44 | 45 | #endif // OPENGLWIDGET_H 46 | -------------------------------------------------------------------------------- /RgbPalette_Recolor_GUI.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RgbPalette_Recolor_GUI", "RgbPalette_Recolor_GUI.vcxproj", "{8C6E3580-7B5B-3679-990B-F6EAE4EE2555}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {8C6E3580-7B5B-3679-990B-F6EAE4EE2555}.Debug|x64.ActiveCfg = Debug|x64 15 | {8C6E3580-7B5B-3679-990B-F6EAE4EE2555}.Debug|x64.Build.0 = Debug|x64 16 | {8C6E3580-7B5B-3679-990B-F6EAE4EE2555}.Release|x64.ActiveCfg = Release|x64 17 | {8C6E3580-7B5B-3679-990B-F6EAE4EE2555}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /image2mp4.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | from cv2 import VideoWriter, VideoWriter_fourcc, imread, resize 3 | import os 4 | from PIL import Image 5 | import sys 6 | 7 | 8 | def Pic2Video(imgPath,videoPath ): 9 | images = os.listdir(imgPath) 10 | fps = 15 # 每秒15帧数 11 | 12 | # VideoWriter_fourcc为视频编解码器 ('I', '4', '2', '0') —>(.avi) 、('P', 'I', 'M', 'I')—>(.avi)、('X', 'V', 'I', 'D')—>(.avi)、('T', 'H', 'E', 'O')—>.ogv、('F', 'L', 'V', '1')—>.flv、('m', 'p', '4', 'v')—>.mp4 13 | fourcc = VideoWriter_fourcc('m', 'p', '4', 'v') 14 | 15 | image = Image.open(imgPath + "/" + images[0]) 16 | videoWriter = cv2.VideoWriter(videoPath + "/recolored.mp4", fourcc, fps, image.size) 17 | 18 | 19 | for i in range(len(images)): 20 | 21 | frame = cv2.imread(imgPath + "/" + str(i) + ".png") # 这里的路径只能是英文路径 22 | print(imgPath + "/" + str(i) + ".png") 23 | videoWriter.write(frame) 24 | print("图片转视频结束!") 25 | videoWriter.release() 26 | cv2.destroyAllWindows() 27 | 28 | if __name__ == '__main__': 29 | imgPath = sys.argv[1] 30 | videoPath = sys.argv[2] 31 | Pic2Video(imgPath,videoPath) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Convexhull-based-Image-Recoloring-GUI 2 | A GUI written by Qt for convex hull palette based image recoloring 3 | 4 | ![LC-CRF-SLAM](https://github.com/Zhengjun-Du/Convexhull-based-Image-Recoloring-GUI/blob/main/GUI.png) 5 | 6 | ### Compile platform 7 | Windows 10 + Qt 5.14.1 + Visual Studio 2015 8 | 9 | ### Feature 10 | **Open Image and Palette**: test the GUI use image and palette in the 'data' directory 11 | **MVC minxing weights:** click the "Calc MVC" button to calculate the mixing weights 12 | **RGB view**: see the point cloud of the image and its convex hull 13 | **Export Image**: export recolored image 14 | **Import/Export Palette**: save the modified palette colors 15 | 16 | ### Reference Paper 17 | 1. Tan J, Lien J M, Gingold Y. Decomposing images into layers via RGB-space geometry[J]. ACM Transactions on Graphics (TOG), 2016, 36(1): 1-14. 18 | 19 | 2. Tan J, Echevarria J, Gingold Y. Efficient palette-based decomposition and recoloring of images via RGBXY-space geometry[J]. ACM Transactions on Graphics (TOG), 2018, 37(6): 1-10. 20 | 21 | 3. Wang Y, Liu Y, Xu K. An Improved Geometric Approach for Palette‐based Image Decomposition and Recoloring[C]//Computer Graphics Forum. 2019, 38(7): 11-22. 22 | 23 | Any question, please feel free to contact me: duzqhu@aliyun.com 24 | 25 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/src/QtColorWidgets/bound_color_selector.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | #include "QtColorWidgets/bound_color_selector.hpp" 23 | 24 | namespace color_widgets { 25 | 26 | BoundColorSelector::BoundColorSelector(QColor* reference, QWidget *parent) : 27 | ColorSelector(parent), ref(reference) 28 | { 29 | setColor(*reference); 30 | connect(this,&ColorPreview::colorChanged,this, &BoundColorSelector::update_reference); 31 | } 32 | 33 | void BoundColorSelector::update_reference(QColor c) 34 | { 35 | *ref = c; 36 | } 37 | 38 | } // namespace color_widgets 39 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/bound_color_selector.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | #ifndef BOUND_COLOR_SELECTOR_HPP 23 | #define BOUND_COLOR_SELECTOR_HPP 24 | 25 | #include "color_selector.hpp" 26 | 27 | namespace color_widgets { 28 | /** 29 | * \brief A color selector bound to a color reference 30 | * \todo Maybe this can be removed 31 | */ 32 | class QCP_EXPORT BoundColorSelector : public ColorSelector 33 | { 34 | Q_OBJECT 35 | private: 36 | QColor* ref; 37 | public: 38 | explicit BoundColorSelector(QColor* reference, QWidget *parent = 0); 39 | 40 | private Q_SLOTS: 41 | void update_reference(QColor); 42 | }; 43 | } // namespace color_widgets 44 | #endif // BOUND_COLOR_SELECTOR_HPP 45 | -------------------------------------------------------------------------------- /opengl3dwidget.cpp: -------------------------------------------------------------------------------- 1 | #include "opengl3dwidget.h" 2 | #include 3 | #include 4 | 5 | // basic OpenGL 3D Widget 6 | 7 | OpenGL3DWidget::OpenGL3DWidget(QWidget *parent) : OpenGLWidget(parent), rotate_x(-15), rotate_y(-70), rotate_z(0), lastPos(0, 0) 8 | { 9 | lastPos.setX(0); 10 | lastPos.setY(0); 11 | } 12 | 13 | void OpenGL3DWidget::paintGL() 14 | { 15 | OpenGLWidget::paintGL(); 16 | 17 | // Otras transformaciones 18 | // glTranslatef( 0.1, 0.0, 0.0 ); // No incluido 19 | // glRotatef( 180, 0.0, 1.0, 0.0 ); // No incluido 20 | 21 | // Rotar cuando el usuario cambie “rotate_x” y “rotate_y” 22 | glRotatef( rotate_x, 1.0, 0.0, 0.0 ); 23 | glRotatef( rotate_y, 0.0, 1.0, 0.0 ); 24 | glRotatef( rotate_z, 0.0, 0.0, 1.0 ); 25 | glScalef( 1.2, 1.2, -1.2 ); 26 | 27 | } 28 | 29 | void OpenGL3DWidget::mousePressEvent(QMouseEvent *event) 30 | { 31 | lastPos = event->pos(); 32 | } 33 | 34 | void OpenGL3DWidget::mouseMoveEvent(QMouseEvent *event) 35 | { 36 | QOpenGLWidget::mouseMoveEvent(event); 37 | 38 | if (event->buttons() & Qt::LeftButton) 39 | { 40 | int dx = event->x() - lastPos.x(); 41 | int dy = event->y() - lastPos.y(); 42 | 43 | // qDebug() << rotate_x << rotate_y << event->x() << event->y() << lastPos.x() << lastPos.y(); 44 | 45 | lastPos = event->pos(); 46 | rotate_x -= dy; 47 | rotate_y -= dx; 48 | qDebug() << "mouseMoveEvent" << rotate_x << rotate_y; 49 | 50 | update(); 51 | } 52 | } 53 | 54 | 55 | -------------------------------------------------------------------------------- /imagewidget.cpp: -------------------------------------------------------------------------------- 1 | #include "imagewidget.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | ImageWidget::ImageWidget(bool _isAfter, QWidget *parent) : QWidget(parent), isAfter(_isAfter) 9 | { 10 | } 11 | 12 | void ImageWidget::paintEvent(QPaintEvent *event) 13 | { 14 | QWidget::paintEvent(event); 15 | 16 | if (data == nullptr) return; 17 | 18 | int width = data->GetFrameWidth(); 19 | int height = data->GetFrameHeight(); 20 | int depth = data->GetFrameDepth(); 21 | double *video = data->GetImage(isAfter); 22 | 23 | QPainter painter(this); 24 | 25 | uchar *data = new uchar[width * height * depth]; 26 | 27 | for (int i = 0; i < width * height * depth; i++) 28 | { 29 | int x = static_cast(video[i] * 255); 30 | if (x > 255) x = 255; 31 | if (x < 0) x = 0; 32 | 33 | data[i] = static_cast(x); 34 | } 35 | 36 | cout << endl; 37 | for (int i = 0; i < 3; i++) 38 | cout << (int)data[i * 3] << "," << (int)data[i * 3 + 1] << "," << (int)data[i * 3 + 2] << endl; 39 | 40 | QImage im(data, width, height, width*3, QImage::Format_RGB888); 41 | 42 | cout << im.height() << "," << im.width() << "," << im.depth() << endl; 43 | 44 | 45 | painter.setPen(QPen(Qt::red, 3)); 46 | 47 | painter.drawImage(QRectF(0, 0, width, height), im); 48 | 49 | //painter.drawRect(0, 0, width, height); 50 | 51 | painter.end(); 52 | delete[] data; 53 | } 54 | 55 | void ImageWidget::setTime(int t) 56 | { 57 | time = t; 58 | 59 | update(); 60 | } 61 | 62 | void ImageWidget::update() 63 | { 64 | QWidget::update(); 65 | 66 | int w = data->GetFrameWidth(); 67 | int h = data->GetFrameHeight(); 68 | 69 | setMaximumSize(w, h); 70 | setMinimumSize(w, h); 71 | } 72 | 73 | void ImageWidget::setData(Data *value) 74 | { 75 | data = value; 76 | connect(value, &Data::updated, this, &ImageWidget::update); 77 | } 78 | -------------------------------------------------------------------------------- /RgbPalette_Recolor_GUI.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2020-04-06T14:49:16 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += core gui widgets datavisualization opengl 8 | LIBS += -lopengl32 -lglu32 -openmp 9 | QMAKE_CXXFLAGS += -openmp 10 | 11 | #note: linux -fopenmp 12 | 13 | 14 | TARGET = Recolor_GUI 15 | TEMPLATE = app 16 | 17 | # The following define makes your compiler emit warnings if you use 18 | # any feature of Qt which has been marked as deprecated (the exact warnings 19 | # depend on your compiler). Please consult the documentation of the 20 | # deprecated API in order to know how to port your code away from it. 21 | DEFINES += QT_DEPRECATED_WARNINGS 22 | 23 | # You can also make your code fail to compile if you use deprecated APIs. 24 | # In order to do so, uncomment the following line. 25 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 26 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 27 | 28 | 29 | 30 | CONFIG += c++11 31 | 32 | SOURCES += \ 33 | data.cpp \ 34 | main.cpp \ 35 | mainwindow.cpp \ 36 | opengl3dwidget.cpp \ 37 | openglwidget.cpp \ 38 | paletteviewwidget.cpp \ 39 | rgbwidget.cpp \ 40 | utility.cpp \ 41 | videowidget.cpp 42 | 43 | HEADERS += \ 44 | data.h \ 45 | mainwindow.h \ 46 | opengl3dwidget.h \ 47 | openglwidget.h \ 48 | paletteviewwidget.h \ 49 | rgbwidget.h \ 50 | utility.h \ 51 | videowidget.h 52 | 53 | 54 | DEFINES += QUAZIP_BUILD 55 | 56 | #INCLUDEPATH += $$PWDQt-Color-Widgets 57 | include(Qt-Color-Widgets/color_widgets.pri) 58 | 59 | FORMS += 60 | 61 | # Default rules for deployment. 62 | qnx: target.path = /tmp/$${TARGET}/bin 63 | else: unix:!android: target.path = /opt/$${TARGET}/bin 64 | !isEmpty(target.path): INSTALLS += target 65 | -------------------------------------------------------------------------------- /data.h: -------------------------------------------------------------------------------- 1 | #ifndef DATA_H 2 | #define DATA_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include"utility.h" 9 | #include "vec3.h" 10 | #include 11 | using namespace std; 12 | 13 | class Data : public QObject 14 | { 15 | Q_OBJECT 16 | 17 | public: 18 | Data(); 19 | void OpenImage(QString fileName); 20 | void OpenPalette(string fileName); 21 | void reset(); 22 | 23 | double *GetImage(bool isAfter = true) const { return isAfter ? recolored_image : original_image; } 24 | Polyhedron GetChangedPalette() { return changed_palette; } 25 | Polyhedron GetOriginalPalette() { return original_palette; } 26 | Polyhedron GetPalette() { return is_mvc_calculated ? changed_palette : original_palette; } 27 | 28 | vector ComputeSingleVertexMVCWeights(int vid, const vec3 &x); 29 | vector ComputeSingleVertexMVCWeightsForceInside(int vid, const vec3 &x); 30 | const void ComputeMVCWeights(); 31 | 32 | vec3 RecolorSinglePixel(int vid, const vec3 &x); 33 | void Recolor(); 34 | 35 | int GetFrameWidth() const { return image_width; } 36 | int GetFrameHeight() const{ return image_height; } 37 | int GetFrameDepth() const{ return image_depth; } 38 | 39 | void setPaletteColor(int id, QColor c); 40 | void resetPaletteColor(int id); 41 | void resetAllPaletteColors(); 42 | 43 | void ExportOriginalVideo(string path); 44 | void ExportRecoloredImage(string path); 45 | void ExportChangedPalette(string path); 46 | void ImportChangedPalette(string path); 47 | 48 | public slots: 49 | signals: 50 | void updated(); 51 | 52 | private: 53 | double* recolored_image = nullptr; 54 | double* original_image = nullptr; 55 | 56 | Polyhedron changed_palette; 57 | Polyhedron original_palette; 58 | 59 | vector > mvc_weights; 60 | bool is_mvc_calculated; 61 | 62 | int image_width = 0; 63 | int image_height = 0; 64 | int image_depth = 0; 65 | }; 66 | 67 | #endif // DATA_H -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/color_names.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | #ifndef COLOR_WIDGETS_COLOR_NAMES_HPP 23 | #define COLOR_WIDGETS_COLOR_NAMES_HPP 24 | 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | namespace color_widgets { 31 | 32 | /** 33 | * \brief Convert a string into a color 34 | * 35 | * Supported string formats: 36 | * * Short hex strings #f00 37 | * * Long hex strings #ff0000 38 | * * Color names red 39 | * * Function-like rgb(255,0,0) 40 | * 41 | * Additional string formats supported only when \p alpha is true: 42 | * * Long hex strings #ff0000ff 43 | * * Function like rgba(255,0,0,255) 44 | */ 45 | QCP_EXPORT QColor colorFromString(const QString& string, bool alpha = true); 46 | 47 | /** 48 | * \brief Convert a color into a string 49 | * 50 | * Format: 51 | * * If the color has full alpha: #ff0000 52 | * * If alpha is true and the color has non-full alpha: #ff000088 53 | */ 54 | QCP_EXPORT QString stringFromColor(const QColor& color, bool alpha = true); 55 | 56 | } // namespace color_widgets 57 | #endif // COLOR_WIDGETS_COLOR_NAMES_HPP 58 | -------------------------------------------------------------------------------- /my_util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | template std::ostream& operator<< (std::ostream& os, const std::vector& vec) { 8 | os << "["; 9 | for (int i = 0; i < (int)vec.size(); i++) 10 | { 11 | if (i != 0) 12 | os << ","; 13 | os << vec[i]; 14 | } 15 | os << "]"; 16 | return os; 17 | } 18 | 19 | template T fromString(const std::string& str) { 20 | T t; 21 | std::stringstream ss(str); 22 | ss >> t; 23 | return t; 24 | } 25 | 26 | namespace my_util { 27 | 28 | template T clamp(const T&val, const T&val_min, const T&val_max) 29 | { 30 | T tmp = std::min(val, val_max); 31 | tmp = std::max(val, val_min); 32 | return tmp; 33 | } 34 | 35 | /* 36 | e.g.: 37 | directory: "." => "./", 38 | directory: "./" => "./" 39 | */ 40 | inline std::string addSlashToEnd(const std::string& directory) { 41 | if (directory.length() == 0) 42 | return directory; 43 | int last_pos = directory.length() - 1; 44 | if (directory[last_pos] == '\\' || directory[last_pos] == '/') 45 | return directory; 46 | else if (directory.find('\\') != -1) 47 | return directory + "\\"; 48 | else 49 | return directory + "/"; 50 | } 51 | 52 | 53 | /* 54 | e.g: fullpath: "D:\\test\\aaa.png" => "aaa.png", 55 | */ 56 | inline std::string getFilenameWithExt(const std::string& fullpath) { 57 | int pos2 = fullpath.find_last_of('\\'); 58 | int pos3 = fullpath.find_last_of('/'); 59 | int pos4 = std::max(pos2, pos3); 60 | if (pos4 == -1) { 61 | return fullpath; 62 | } 63 | else { 64 | return fullpath.substr(pos4 + 1); 65 | } 66 | } 67 | 68 | /* 69 | e.g: fullpath: "D:\\test\\aaa.png" => "aaa", 70 | */ 71 | inline std::string getFilename(const std::string& fullpath) { 72 | std::string filename; 73 | 74 | std::string fnWithExt = getFilenameWithExt(fullpath); 75 | 76 | //remove extension 77 | int pos = fnWithExt.find_last_of('.'); 78 | if (pos == -1) { 79 | filename = fnWithExt; 80 | } 81 | else { 82 | filename = fnWithExt.substr(0, pos); 83 | } 84 | 85 | return filename; 86 | } 87 | } -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/color_delegate.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | #ifndef COLOR_DELEGATE_HPP 23 | #define COLOR_DELEGATE_HPP 24 | 25 | #include "colorwidgets_global.hpp" 26 | 27 | #include 28 | 29 | namespace color_widgets { 30 | 31 | /** 32 | Delegate to use a ColorSelector in a color list 33 | */ 34 | class QCP_EXPORT ColorDelegate : public QStyledItemDelegate 35 | { 36 | Q_OBJECT 37 | public: 38 | explicit ColorDelegate(QWidget *parent = 0); 39 | 40 | void paint(QPainter *painter, const QStyleOptionViewItem &option, 41 | const QModelIndex &index) const Q_DECL_OVERRIDE; 42 | 43 | QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, 44 | const QModelIndex &index) const Q_DECL_OVERRIDE; 45 | 46 | void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE; 47 | 48 | void setModelData(QWidget *editor, QAbstractItemModel *model, 49 | const QModelIndex &index) const Q_DECL_OVERRIDE; 50 | 51 | QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE; 52 | 53 | void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, 54 | const QModelIndex &index) const Q_DECL_OVERRIDE; 55 | 56 | 57 | private slots: 58 | void close_editor(); 59 | void color_changed(); 60 | }; 61 | 62 | } // namespace color_widgets 63 | 64 | #endif // COLOR_DELEGATE_HPP 65 | -------------------------------------------------------------------------------- /openglwidget.cpp: -------------------------------------------------------------------------------- 1 | #include "openglwidget.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | // basic OpenGL 2D widget 8 | 9 | OpenGLWidget::OpenGLWidget(QWidget *parent) : QOpenGLWidget(parent) 10 | { 11 | } 12 | 13 | void OpenGLWidget::initializeGL() 14 | { 15 | initializeOpenGLFunctions(); 16 | // glEnable(GL_DEPTH_TEST); 17 | glEnable(GL_POINT_SMOOTH); 18 | glEnable(GL_LINE_SMOOTH); 19 | glEnable(GL_BLEND); 20 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 21 | 22 | glEnable(GL_BLEND); //Enable blending. 23 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //Set blending function. 24 | 25 | glEnable(GL_DEPTH_TEST); 26 | glDepthFunc(GL_LESS); 27 | 28 | glClearDepth(1.0f); 29 | // Borrar pantalla y Z-buffer 30 | glClearColor(.5f, .5f, .5f, 0.0f); 31 | } 32 | 33 | void OpenGLWidget::resizeGL(int w, int h) 34 | { 35 | qDebug() << "resizeGL" << w << h; 36 | int m = w < h ? w : h; 37 | glViewport(0, 0, m, m); 38 | update(); 39 | } 40 | 41 | void OpenGLWidget::paintGL() 42 | { 43 | QOpenGLWidget::paintGL(); 44 | 45 | 46 | glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 47 | 48 | glShadeModel(GL_SMOOTH); 49 | // Resetear transformaciones 50 | glLoadIdentity(); 51 | 52 | } 53 | 54 | void OpenGLWidget::setData(Data *value) 55 | { 56 | data = value; 57 | connect(value, &Data::updated, this, &OpenGLWidget::update); 58 | } 59 | 60 | void OpenGLWidget::update() 61 | { 62 | QOpenGLWidget::update(); 63 | } 64 | 65 | void OpenGLWidget::setTime(int t) 66 | { 67 | // qDebug() << t; 68 | 69 | time = t; 70 | update(); 71 | } 72 | 73 | void OpenGLWidget::setShowImageData(bool _showImageData) 74 | { 75 | showImageData = _showImageData; 76 | update(); 77 | } 78 | 79 | void OpenGLWidget::setPreview(int percentage) 80 | { 81 | preview = percentage / 1000.; 82 | update(); 83 | } 84 | 85 | /* 86 | void OpenGLWidget::graficarLineas() 87 | { 88 | glBegin(GL_LINES); 89 | glColor3f(1,0,0); 90 | glVertex3f(0,0,0); 91 | glVertex3f(20,0,0); 92 | 93 | glColor3f(1,1,0); 94 | glVertex3f(0,0,0); 95 | glVertex3f(0,20,0); 96 | 97 | glColor3f(0,1,1); 98 | glVertex3f(0,0,0); 99 | glVertex3f(0,0,20); 100 | glEnd(); 101 | } 102 | */ 103 | 104 | 105 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/color_utils.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | #ifndef COLOR_UTILS_HPP 23 | #define COLOR_UTILS_HPP 24 | 25 | #include 26 | #include 27 | 28 | #include "QtColorWidgets/colorwidgets_global.hpp" 29 | 30 | namespace color_widgets { 31 | namespace detail { 32 | 33 | 34 | inline qreal color_chromaF(const QColor& c) 35 | { 36 | qreal max = qMax(c.redF(), qMax(c.greenF(), c.blueF())); 37 | qreal min = qMin(c.redF(), qMin(c.greenF(), c.blueF())); 38 | return max - min; 39 | } 40 | 41 | inline qreal color_lumaF(const QColor& c) 42 | { 43 | return 0.30 * c.redF() + 0.59 * c.greenF() + 0.11 * c.blueF(); 44 | } 45 | QColor color_from_lch(qreal hue, qreal chroma, qreal luma, qreal alpha = 1 ); 46 | 47 | inline QColor rainbow_lch(qreal hue) 48 | { 49 | return color_from_lch(hue,1,1); 50 | } 51 | 52 | inline QColor rainbow_hsv(qreal hue) 53 | { 54 | return QColor::fromHsvF(hue,1,1); 55 | } 56 | 57 | inline qreal color_lightnessF(const QColor& c) 58 | { 59 | return ( qMax(c.redF(),qMax(c.greenF(),c.blueF())) + 60 | qMin(c.redF(),qMin(c.greenF(),c.blueF())) ) / 2; 61 | } 62 | 63 | inline qreal color_HSL_saturationF(const QColor& col) 64 | { 65 | qreal c = color_chromaF(col); 66 | qreal l = color_lightnessF(col); 67 | if ( qFuzzyCompare(l+1,1) || qFuzzyCompare(l+1,2) ) 68 | return 0; 69 | return c / (1-qAbs(2*l-1)); 70 | } 71 | 72 | QCP_EXPORT QColor color_from_hsl(qreal hue, qreal sat, qreal lig, qreal alpha = 1 ); 73 | 74 | } // namespace detail 75 | } // namespace color_widgets 76 | 77 | #endif // COLOR_UTILS_HPP 78 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/color_list_widget.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | #ifndef COLOR_LIST_WIDGET_HPP 23 | #define COLOR_LIST_WIDGET_HPP 24 | 25 | #include "abstract_widget_list.hpp" 26 | #include "color_wheel.hpp" 27 | 28 | namespace color_widgets { 29 | 30 | class QCP_EXPORT ColorListWidget : public AbstractWidgetList 31 | { 32 | Q_OBJECT 33 | 34 | Q_PROPERTY(QList colors READ colors WRITE setColors NOTIFY colorsChanged ) 35 | Q_PROPERTY(ColorWheel::ShapeEnum wheelShape READ wheelShape WRITE setWheelShape NOTIFY wheelShapeChanged) 36 | Q_PROPERTY(ColorWheel::ColorSpaceEnum colorSpace READ colorSpace WRITE setColorSpace NOTIFY colorSpaceChanged) 37 | Q_PROPERTY(bool wheelRotating READ wheelRotating WRITE setWheelRotating NOTIFY wheelRotatingChanged) 38 | 39 | public: 40 | explicit ColorListWidget(QWidget *parent = 0); 41 | ~ColorListWidget(); 42 | 43 | QList colors() const; 44 | void setColors(const QList& colors); 45 | 46 | void swap(int a, int b); 47 | 48 | void append(); 49 | 50 | ColorWheel::ShapeEnum wheelShape() const; 51 | ColorWheel::ColorSpaceEnum colorSpace() const; 52 | bool wheelRotating() const; 53 | 54 | Q_SIGNALS: 55 | void colorsChanged(const QList&); 56 | void wheelShapeChanged(ColorWheel::ShapeEnum shape); 57 | void colorSpaceChanged(ColorWheel::ColorSpaceEnum space); 58 | void wheelRotatingChanged(bool rotating); 59 | 60 | public Q_SLOTS: 61 | void setWheelShape(ColorWheel::ShapeEnum shape); 62 | void setColorSpace(ColorWheel::ColorSpaceEnum space); 63 | void setWheelRotating(bool rotating); 64 | 65 | private Q_SLOTS: 66 | void emit_changed(); 67 | void handle_removed(int); 68 | void color_changed(int row); 69 | 70 | private: 71 | class Private; 72 | Private * const p; 73 | void append_widget(int col); 74 | }; 75 | 76 | } // namespace color_widgets 77 | 78 | #endif // COLOR_LIST_WIDGET_HPP 79 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/src/QtColorWidgets/color_utils.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | #include "QtColorWidgets/color_utils.hpp" 23 | 24 | namespace color_widgets { 25 | namespace detail { 26 | 27 | QColor color_from_lch(qreal hue, qreal chroma, qreal luma, qreal alpha ) 28 | { 29 | qreal h1 = hue*6; 30 | qreal x = chroma*(1-qAbs(std::fmod(h1,2)-1)); 31 | QColor col; 32 | if ( h1 >= 0 && h1 < 1 ) 33 | col = QColor::fromRgbF(chroma,x,0); 34 | else if ( h1 < 2 ) 35 | col = QColor::fromRgbF(x,chroma,0); 36 | else if ( h1 < 3 ) 37 | col = QColor::fromRgbF(0,chroma,x); 38 | else if ( h1 < 4 ) 39 | col = QColor::fromRgbF(0,x,chroma); 40 | else if ( h1 < 5 ) 41 | col = QColor::fromRgbF(x,0,chroma); 42 | else if ( h1 < 6 ) 43 | col = QColor::fromRgbF(chroma,0,x); 44 | 45 | qreal m = luma - color_lumaF(col); 46 | 47 | return QColor::fromRgbF( 48 | qBound(0.0,col.redF()+m,1.0), 49 | qBound(0.0,col.greenF()+m,1.0), 50 | qBound(0.0,col.blueF()+m,1.0), 51 | alpha); 52 | } 53 | 54 | QColor color_from_hsl(qreal hue, qreal sat, qreal lig, qreal alpha ) 55 | { 56 | qreal chroma = (1 - qAbs(2*lig-1))*sat; 57 | qreal h1 = hue*6; 58 | qreal x = chroma*(1-qAbs(std::fmod(h1,2)-1)); 59 | QColor col; 60 | if ( h1 >= 0 && h1 < 1 ) 61 | col = QColor::fromRgbF(chroma,x,0); 62 | else if ( h1 < 2 ) 63 | col = QColor::fromRgbF(x,chroma,0); 64 | else if ( h1 < 3 ) 65 | col = QColor::fromRgbF(0,chroma,x); 66 | else if ( h1 < 4 ) 67 | col = QColor::fromRgbF(0,x,chroma); 68 | else if ( h1 < 5 ) 69 | col = QColor::fromRgbF(x,0,chroma); 70 | else if ( h1 < 6 ) 71 | col = QColor::fromRgbF(chroma,0,x); 72 | 73 | qreal m = lig-chroma/2; 74 | 75 | return QColor::fromRgbF( 76 | qBound(0.0,col.redF()+m,1.0), 77 | qBound(0.0,col.greenF()+m,1.0), 78 | qBound(0.0,col.blueF()+m,1.0), 79 | alpha); 80 | } 81 | 82 | } // namespace detail 83 | } // namespace color_widgets 84 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/src/QtColorWidgets/color_names.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | #include "QtColorWidgets/color_names.hpp" 23 | #include 24 | 25 | static QRegularExpression regex_qcolor (QStringLiteral("^(?:(?:#[[:xdigit:]]{3})|(?:#[[:xdigit:]]{6})|(?:[[:alpha:]]+))$")); 26 | static QRegularExpression regex_func_rgb (QStringLiteral(R"(^rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)$)")); 27 | static QRegularExpression regex_hex_rgba (QStringLiteral("^#[[:xdigit:]]{8}$")); 28 | static QRegularExpression regex_func_rgba (QStringLiteral(R"(^rgba?\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)$)")); 29 | 30 | namespace color_widgets { 31 | 32 | 33 | QString stringFromColor(const QColor& color, bool alpha) 34 | { 35 | if ( !alpha || color.alpha() == 255 ) 36 | return color.name(); 37 | return color.name()+QStringLiteral("%1").arg(color.alpha(), 2, 16, QChar('0')); 38 | } 39 | 40 | QColor colorFromString(const QString& string, bool alpha) 41 | { 42 | QString xs = string.trimmed(); 43 | QRegularExpressionMatch match; 44 | 45 | match = regex_qcolor.match(xs); 46 | if ( match.hasMatch() ) 47 | { 48 | return QColor(xs); 49 | } 50 | 51 | match = regex_func_rgb.match(xs); 52 | if ( match.hasMatch() ) 53 | { 54 | return QColor( 55 | match.captured(1).toInt(), 56 | match.captured(2).toInt(), 57 | match.captured(3).toInt() 58 | ); 59 | } 60 | 61 | if ( alpha ) 62 | { 63 | match = regex_hex_rgba.match(xs); 64 | if ( match.hasMatch() ) 65 | { 66 | return QColor( 67 | xs.mid(1,2).toInt(nullptr,16), 68 | xs.mid(3,2).toInt(nullptr,16), 69 | xs.mid(5,2).toInt(nullptr,16), 70 | xs.mid(7,2).toInt(nullptr,16) 71 | ); 72 | } 73 | 74 | match = regex_func_rgba.match(xs); 75 | if ( match.hasMatch() ) 76 | { 77 | return QColor( 78 | match.captured(1).toInt(), 79 | match.captured(2).toInt(), 80 | match.captured(3).toInt(), 81 | match.captured(4).toInt() 82 | ); 83 | } 84 | } 85 | 86 | return QColor(); 87 | } 88 | 89 | } // namespace color_widgets 90 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/harmony_color_wheel.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * \copyright Copyright (C) 2017 caryoscelus 8 | * 9 | * This program is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published by 11 | * the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | #ifndef HARMONY_COLOR_WHEEL_HPP 24 | #define HARMONY_COLOR_WHEEL_HPP 25 | 26 | 27 | #include "color_wheel.hpp" 28 | 29 | namespace color_widgets { 30 | 31 | /** 32 | * \brief ColorWheel with color harmonies 33 | */ 34 | class QCP_EXPORT HarmonyColorWheel : public ColorWheel 35 | { 36 | Q_OBJECT 37 | 38 | public: 39 | explicit HarmonyColorWheel(QWidget *parent = 0); 40 | ~HarmonyColorWheel(); 41 | 42 | /// Get all harmony colors (including main) 43 | QList harmonyColors() const; 44 | 45 | /// Get number of harmony colors (including main) 46 | unsigned int harmonyCount() const; 47 | 48 | /// Clear harmony color scheme 49 | void clearHarmonies(); 50 | 51 | /** 52 | * @brief Add harmony color 53 | * @param hue_diff Initial hue difference (in [0-1) range) 54 | * @param editable Whether this harmony should be editable 55 | * @returns Index of newly added harmony 56 | */ 57 | unsigned addHarmony(double hue_diff, bool editable); 58 | 59 | /** 60 | * @brief Add symmetric harmony color 61 | * @param relative_to Index of other harmony that should be symmetric relative to main hue 62 | * @returns Index of newly added harmony 63 | * Editability is inherited from symmetric editor 64 | */ 65 | unsigned addSymmetricHarmony(unsigned relative_to); 66 | 67 | /** 68 | * @brief Add opposite harmony color 69 | * @param relative_to Index of other harmony that should be opposite to this 70 | * @returns Index of newly added harmony 71 | * Editability is inherited from opposite editor 72 | */ 73 | unsigned addOppositeHarmony(unsigned relative_to); 74 | 75 | Q_SIGNALS: 76 | /** 77 | * Emitted when harmony settings or harmony colors are changed (including due to main hue change) 78 | */ 79 | void harmonyChanged(); 80 | 81 | protected: 82 | void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE; 83 | void mouseMoveEvent(QMouseEvent *) Q_DECL_OVERRIDE; 84 | void mousePressEvent(QMouseEvent *) Q_DECL_OVERRIDE; 85 | void mouseReleaseEvent(QMouseEvent *) Q_DECL_OVERRIDE; 86 | 87 | private: 88 | class Private; 89 | Private * p; 90 | }; 91 | 92 | } // namespace color_widgets 93 | 94 | #endif // COLOR_WHEEL_HPP 95 | 96 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/abstract_widget_list.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | #ifndef ABSTRACT_WIDGET_LIST_HPP 23 | #define ABSTRACT_WIDGET_LIST_HPP 24 | 25 | #include "colorwidgets_global.hpp" 26 | 27 | #include 28 | #include 29 | 30 | class QCP_EXPORT AbstractWidgetList : public QWidget 31 | { 32 | Q_OBJECT 33 | public: 34 | explicit AbstractWidgetList(QWidget *parent = 0); 35 | ~AbstractWidgetList(); 36 | 37 | /** 38 | * \brief Get the number of items 39 | */ 40 | int count() const; 41 | 42 | /** 43 | * \brief Swap row a and row b 44 | */ 45 | virtual void swap(int a, int b) = 0; 46 | 47 | 48 | /// Whether the given row index is valid 49 | bool isValidRow(int i) const { return i >= 0 && i < count(); } 50 | 51 | void setRowHeight(int row, int height); 52 | 53 | 54 | public Q_SLOTS: 55 | /** 56 | * \brief Remove row i 57 | */ 58 | void remove(int i); 59 | 60 | /** 61 | * \brief append a default row 62 | */ 63 | virtual void append() = 0; 64 | 65 | Q_SIGNALS: 66 | void removed(int i); 67 | 68 | protected: 69 | 70 | /** 71 | * \brief Create a new row with the given widget 72 | * 73 | * Must be caled by implementations of append() 74 | */ 75 | void appendWidget(QWidget* w); 76 | 77 | /** 78 | * \brief get the widget found at the given row 79 | */ 80 | QWidget* widget(int i); 81 | 82 | 83 | /** 84 | * \brief get the widget found at the given row 85 | */ 86 | template 87 | T* widget_cast(int i) { return qobject_cast(widget(i)); } 88 | 89 | /** 90 | * \brief clear all rows without emitting signals 91 | * 92 | * May be useful when implementation want to set all values at once 93 | */ 94 | void clear(); 95 | 96 | private Q_SLOTS: 97 | void remove_clicked(QWidget* w); 98 | void up_clicked(QWidget* w); 99 | void down_clicked(QWidget* w); 100 | 101 | private: 102 | class Private; 103 | Private * const p; 104 | 105 | QWidget* create_button(QWidget* data, QSignalMapper*mapper, 106 | QString icon_name, QString text, 107 | QString tooltip = QString()) const; 108 | }; 109 | 110 | #endif // ABSTRACT_WIDGET_LIST_HPP 111 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/gradient_helper.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | #ifndef GRADIENT_HELPER_HPP 23 | #define GRADIENT_HELPER_HPP 24 | 25 | #include "colorwidgets_global.hpp" 26 | 27 | #include 28 | 29 | namespace color_widgets { 30 | 31 | inline QColor blendColors(const QColor& a, const QColor& b, qreal ratio) 32 | { 33 | return QColor::fromRgbF( 34 | a.redF() * (1-ratio) + b.redF() * ratio, 35 | a.greenF() * (1-ratio) + b.greenF() * ratio, 36 | a.blueF() * (1-ratio) + b.blueF() * ratio, 37 | a.alphaF() * (1-ratio) + b.alphaF() * ratio 38 | ); 39 | } 40 | 41 | 42 | /** 43 | * \brief Get an insertion point in the gradient 44 | * \param gradient Gradient stops to look into (must be properly set up) 45 | * \param factor Value in [0, 1] to get the color for 46 | * \return A pair whose first element is the index to insert the new value at, and a GradientStop 47 | */ 48 | inline QPair Q_DECL_EXPORT gradientBlendedColorInsert(const QGradientStops& gradient, qreal factor) 49 | { 50 | if ( gradient.empty() ) 51 | return {0, {0, QColor()}}; 52 | 53 | if ( gradient.size() == 1 || factor <= 0 ) 54 | return {0, gradient.front()}; 55 | 56 | int i = 0; 57 | QGradientStop s1; 58 | for ( auto s2 : gradient ) 59 | { 60 | if ( factor < s2.first ) 61 | { 62 | qreal ratio = (factor - s1.first) / (s2.first - s1.first); 63 | return {i, {factor, blendColors(s1.second, s2.second, ratio)}}; 64 | } 65 | s1 = s2; 66 | ++i; 67 | } 68 | 69 | return {gradient.size(), gradient.back()}; 70 | } 71 | 72 | /** 73 | * \brief Returns a color in the gradient 74 | * \param gradient Gradient stops to look into (must be properly set up) 75 | * \param factor Value in [0, 1] to get the color for 76 | */ 77 | inline QColor Q_DECL_EXPORT gradientBlendedColor(const QGradientStops& gradient, qreal factor) 78 | { 79 | return gradientBlendedColorInsert(gradient, factor).second.second; 80 | } 81 | 82 | /** 83 | * \brief Returns a color in the gradient 84 | * \param gradient Gradient to look into 85 | * \param factor Value in [0, 1] to get the color for 86 | */ 87 | inline QColor Q_DECL_EXPORT gradientBlendedColor(const QGradient& gradient, qreal factor) 88 | { 89 | return gradientBlendedColor(gradient.stops(), factor); 90 | } 91 | 92 | } // namespace color_widgets 93 | 94 | 95 | 96 | 97 | #endif // GRADIENT_HELPER_HPP 98 | 99 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/color_line_edit.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | #ifndef COLOR_WIDGETS_COLOR_LINE_EDIT_HPP 23 | #define COLOR_WIDGETS_COLOR_LINE_EDIT_HPP 24 | 25 | #include "colorwidgets_global.hpp" 26 | #include 27 | #include 28 | 29 | namespace color_widgets { 30 | 31 | /** 32 | * \brief A line edit used to define a color name 33 | * 34 | * Supported string formats: 35 | * * Short hex strings #f00 36 | * * Long hex strings #ff0000 37 | * * Color names red 38 | * * Function-like rgb(255,0,0) 39 | * 40 | * Additional string formats supported when showAlpha is true: 41 | * * Long hex strings #ff0000ff 42 | * * Function like rgba(255,0,0,255) 43 | */ 44 | class QCP_EXPORT ColorLineEdit : public QLineEdit 45 | { 46 | Q_OBJECT 47 | Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) 48 | /** 49 | * \brief Whether the widget displays and edits the alpha channel 50 | */ 51 | Q_PROPERTY(bool showAlpha READ showAlpha WRITE setShowAlpha NOTIFY showAlphaChanged) 52 | /** 53 | * \brief If \b true, the background of the widget is changed to show the color 54 | */ 55 | Q_PROPERTY(bool previewColor READ previewColor WRITE setPreviewColor NOTIFY previewColorChanged) 56 | 57 | public: 58 | explicit ColorLineEdit(QWidget* parent = nullptr); 59 | ~ColorLineEdit(); 60 | 61 | QColor color() const; 62 | bool showAlpha() const; 63 | bool previewColor() const; 64 | 65 | public Q_SLOTS: 66 | void setColor(const QColor& color); 67 | void setShowAlpha(bool showAlpha); 68 | void setPreviewColor(bool previewColor); 69 | 70 | Q_SIGNALS: 71 | /** 72 | * \brief Emitted when the color is changed by any means 73 | */ 74 | void colorChanged(const QColor& color); 75 | /** 76 | * \brief Emitted when the user is typing a color but has not finished yet 77 | */ 78 | void colorEdited(const QColor& color); 79 | /** 80 | * \brief Emitted when the user finished to edit a string 81 | */ 82 | void colorEditingFinished(const QColor& color); 83 | 84 | void showAlphaChanged(bool showAlpha); 85 | void previewColorChanged(bool previewColor); 86 | 87 | protected: 88 | void dragEnterEvent(QDragEnterEvent *event) Q_DECL_OVERRIDE; 89 | void dropEvent(QDropEvent * event) Q_DECL_OVERRIDE; 90 | void paintEvent(QPaintEvent* event) Q_DECL_OVERRIDE; 91 | 92 | private: 93 | class Private; 94 | Private* p; 95 | }; 96 | 97 | } // namespace color_widgets 98 | #endif // COLOR_WIDGETS_COLOR_LINE_EDIT_HPP 99 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/hue_slider.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2014 Calle Laakkonen 7 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 8 | * 9 | * This program is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published by 11 | * the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | #ifndef HUE_SLIDER_HPP 24 | #define HUE_SLIDER_HPP 25 | 26 | #include "gradient_slider.hpp" 27 | 28 | namespace color_widgets { 29 | 30 | /** 31 | * \brief A slider for selecting a hue value 32 | */ 33 | class QCP_EXPORT HueSlider : public GradientSlider 34 | { 35 | Q_OBJECT 36 | /** 37 | * \brief Saturation used in the rainbow gradient, as a [0-1] float 38 | */ 39 | Q_PROPERTY(qreal colorSaturation READ colorSaturation WRITE setColorSaturation NOTIFY colorSaturationChanged) 40 | /** 41 | * \brief Value used in the rainbow gradient, as a [0-1] float 42 | */ 43 | Q_PROPERTY(qreal colorValue READ colorValue WRITE setColorValue NOTIFY colorValueChanged) 44 | /** 45 | * \brief Alpha used in the rainbow gradient, as a [0-1] float 46 | */ 47 | Q_PROPERTY(qreal colorAlpha READ colorAlpha WRITE setColorAlpha NOTIFY colorAlphaChanged) 48 | 49 | /** 50 | * \brief Color with corresponding color* components 51 | */ 52 | Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) 53 | 54 | /** 55 | * \brief Normalized Hue, as indicated from the slider 56 | */ 57 | Q_PROPERTY(qreal colorHue READ colorHue WRITE setColorHue NOTIFY colorHueChanged) 58 | 59 | 60 | public: 61 | explicit HueSlider(QWidget *parent = nullptr); 62 | explicit HueSlider(Qt::Orientation orientation, QWidget *parent = nullptr); 63 | ~HueSlider(); 64 | 65 | qreal colorSaturation() const; 66 | qreal colorValue() const; 67 | qreal colorAlpha() const; 68 | QColor color() const; 69 | qreal colorHue() const; 70 | 71 | public Q_SLOTS: 72 | void setColorValue(qreal value); 73 | void setColorSaturation(qreal value); 74 | void setColorAlpha(qreal alpha); 75 | void setColorHue(qreal colorHue); 76 | /** 77 | * \brief Set Hue Saturation and ColorValue, ignoring alpha 78 | */ 79 | void setColor(const QColor& color); 80 | /** 81 | * \brief Set Hue Saturation, ColorValue and Alpha 82 | */ 83 | void setFullColor(const QColor& color); 84 | 85 | Q_SIGNALS: 86 | void colorHueChanged(qreal colorHue); 87 | void colorChanged(QColor); 88 | void colorAlphaChanged(qreal v); 89 | void colorSaturationChanged(qreal v); 90 | void colorValueChanged(qreal v); 91 | 92 | private: 93 | class Private; 94 | Private * const p; 95 | }; 96 | 97 | } // namespace color_widgets 98 | 99 | #endif // HUE_SLIDER_HPP 100 | 101 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/color_widgets.pri: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2013-2019 Mattia Basaglia 2 | # 3 | # 4 | # This software is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Lesser General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This software is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Lesser General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Lesser General Public License 15 | # along with Color Widgets. If not, see . 16 | 17 | CONFIG += c++11 18 | 19 | INCLUDEPATH += $$PWD/src $$PWD/include 20 | 21 | SOURCES += \ 22 | $$PWD/src/QtColorWidgets/abstract_widget_list.cpp \ 23 | $$PWD/src/QtColorWidgets/bound_color_selector.cpp \ 24 | $$PWD/src/QtColorWidgets/color_2d_slider.cpp \ 25 | $$PWD/src/QtColorWidgets/color_delegate.cpp \ 26 | $$PWD/src/QtColorWidgets/color_dialog.cpp \ 27 | $$PWD/src/QtColorWidgets/color_line_edit.cpp \ 28 | $$PWD/src/QtColorWidgets/color_list_widget.cpp \ 29 | $$PWD/src/QtColorWidgets/color_names.cpp \ 30 | $$PWD/src/QtColorWidgets/color_palette.cpp \ 31 | $$PWD/src/QtColorWidgets/color_palette_model.cpp \ 32 | $$PWD/src/QtColorWidgets/color_palette_widget.cpp \ 33 | $$PWD/src/QtColorWidgets/color_preview.cpp \ 34 | $$PWD/src/QtColorWidgets/color_selector.cpp \ 35 | $$PWD/src/QtColorWidgets/color_utils.cpp \ 36 | $$PWD/src/QtColorWidgets/color_wheel.cpp \ 37 | $$PWD/src/QtColorWidgets/gradient_editor.cpp \ 38 | $$PWD/src/QtColorWidgets/gradient_list_model.cpp \ 39 | $$PWD/src/QtColorWidgets/gradient_slider.cpp \ 40 | $$PWD/src/QtColorWidgets/harmony_color_wheel.cpp \ 41 | $$PWD/src/QtColorWidgets/hue_slider.cpp \ 42 | $$PWD/src/QtColorWidgets/swatch.cpp 43 | 44 | HEADERS += \ 45 | $$PWD/include/QtColorWidgets/abstract_widget_list.hpp \ 46 | $$PWD/include/QtColorWidgets/bound_color_selector.hpp \ 47 | $$PWD/include/QtColorWidgets/color_2d_slider.hpp \ 48 | $$PWD/include/QtColorWidgets/color_delegate.hpp \ 49 | $$PWD/include/QtColorWidgets/color_dialog.hpp \ 50 | $$PWD/include/QtColorWidgets/color_line_edit.hpp \ 51 | $$PWD/include/QtColorWidgets/color_list_widget.hpp \ 52 | $$PWD/include/QtColorWidgets/color_names.hpp \ 53 | $$PWD/include/QtColorWidgets/color_palette.hpp \ 54 | $$PWD/include/QtColorWidgets/color_palette_model.hpp \ 55 | $$PWD/include/QtColorWidgets/color_palette_widget.hpp \ 56 | $$PWD/include/QtColorWidgets/color_preview.hpp \ 57 | $$PWD/include/QtColorWidgets/color_selector.hpp \ 58 | $$PWD/include/QtColorWidgets/color_utils.hpp \ 59 | $$PWD/include/QtColorWidgets/color_wheel.hpp \ 60 | $$PWD/include/QtColorWidgets/color_wheel_private.hpp \ 61 | $$PWD/include/QtColorWidgets/colorwidgets_global.hpp \ 62 | $$PWD/include/QtColorWidgets/gradient_delegate.hpp \ 63 | $$PWD/include/QtColorWidgets/gradient_editor.hpp \ 64 | $$PWD/include/QtColorWidgets/gradient_helper.hpp \ 65 | $$PWD/include/QtColorWidgets/gradient_list_model.hpp \ 66 | $$PWD/include/QtColorWidgets/gradient_slider.hpp \ 67 | $$PWD/include/QtColorWidgets/harmony_color_wheel.hpp \ 68 | $$PWD/include/QtColorWidgets/hue_slider.hpp \ 69 | $$PWD/include/QtColorWidgets/swatch.hpp 70 | 71 | FORMS += \ 72 | $$PWD/src/QtColorWidgets/color_dialog.ui \ 73 | $$PWD/src/QtColorWidgets/color_palette_widget.ui 74 | 75 | RESOURCES += \ 76 | $$PWD/resources/QtColorWidgets/color_widgets.qrc 77 | 78 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/color_selector.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | #ifndef COLOR_SELECTOR_HPP 23 | #define COLOR_SELECTOR_HPP 24 | 25 | #include "color_preview.hpp" 26 | #include "color_wheel.hpp" 27 | 28 | namespace color_widgets { 29 | 30 | /** 31 | * Color preview that opens a color dialog 32 | */ 33 | class QCP_EXPORT ColorSelector : public ColorPreview 34 | { 35 | Q_OBJECT 36 | Q_ENUMS(UpdateMode) 37 | Q_PROPERTY(UpdateMode updateMode READ updateMode WRITE setUpdateMode NOTIFY updateModeChanged) 38 | Q_PROPERTY(Qt::WindowModality dialogModality READ dialogModality WRITE setDialogModality NOTIFY dialogModalityChanged) 39 | Q_PROPERTY(ColorWheel::ShapeEnum wheelShape READ wheelShape WRITE setWheelShape NOTIFY wheelShapeChanged) 40 | Q_PROPERTY(ColorWheel::ColorSpaceEnum colorSpace READ colorSpace WRITE setColorSpace NOTIFY colorSpaceChanged) 41 | Q_PROPERTY(bool wheelRotating READ wheelRotating WRITE setWheelRotating NOTIFY wheelRotatingChanged) 42 | 43 | public: 44 | enum UpdateMode { 45 | Confirm, ///< Update color only after the dialog has been accepted 46 | Continuous ///< Update color as it's being modified in the dialog 47 | }; 48 | 49 | explicit ColorSelector(QWidget *parent = 0); 50 | ~ColorSelector(); 51 | 52 | void setUpdateMode(UpdateMode m); 53 | UpdateMode updateMode() const; 54 | 55 | Qt::WindowModality dialogModality() const; 56 | void setDialogModality(Qt::WindowModality m); 57 | 58 | ColorWheel::ShapeEnum wheelShape() const; 59 | ColorWheel::ColorSpaceEnum colorSpace() const; 60 | bool wheelRotating() const; 61 | 62 | Q_SIGNALS: 63 | void wheelShapeChanged(ColorWheel::ShapeEnum shape); 64 | void colorSpaceChanged(ColorWheel::ColorSpaceEnum space); 65 | void wheelRotatingChanged(bool rotating); 66 | void updateModeChanged(UpdateMode); 67 | void dialogModalityChanged(Qt::WindowModality); 68 | /// Emitted when a color is selected by the user 69 | void colorSelected(const QColor& c); 70 | 71 | public Q_SLOTS: 72 | void showDialog(); 73 | void setWheelShape(ColorWheel::ShapeEnum shape); 74 | void setColorSpace(ColorWheel::ColorSpaceEnum space); 75 | void setWheelRotating(bool rotating); 76 | 77 | private Q_SLOTS: 78 | void accept_dialog(); 79 | void reject_dialog(); 80 | void update_old_color(const QColor &c); 81 | 82 | protected: 83 | void dragEnterEvent(QDragEnterEvent *event); 84 | void dropEvent(QDropEvent * event); 85 | 86 | private: 87 | /// Connect/Disconnect colorChanged based on UpdateMode 88 | void connect_dialog(); 89 | 90 | /// Disconnect from dialog update 91 | void disconnect_dialog(); 92 | 93 | class Private; 94 | Private * const p; 95 | }; 96 | 97 | } // namespace color_widgets 98 | 99 | #endif // COLOR_SELECTOR_HPP 100 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/gradient_slider.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file gradient_slider.hpp 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * \copyright Copyright (C) 2014 Calle Laakkonen 8 | * \copyright Copyright (C) 2017 caryoscelus 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public License as published by 12 | * the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Lesser General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | #ifndef GRADIENT_SLIDER_HPP 25 | #define GRADIENT_SLIDER_HPP 26 | 27 | #include "colorwidgets_global.hpp" 28 | 29 | #include 30 | #include 31 | 32 | namespace color_widgets { 33 | 34 | /** 35 | * \brief A slider that moves on top of a gradient 36 | */ 37 | class QCP_EXPORT GradientSlider : public QSlider 38 | { 39 | Q_OBJECT 40 | Q_PROPERTY(QBrush background READ background WRITE setBackground NOTIFY backgroundChanged) 41 | Q_PROPERTY(QGradientStops colors READ colors WRITE setColors DESIGNABLE false) 42 | Q_PROPERTY(QColor firstColor READ firstColor WRITE setFirstColor STORED false) 43 | Q_PROPERTY(QColor lastColor READ lastColor WRITE setLastColor STORED false) 44 | Q_PROPERTY(QLinearGradient gradient READ gradient WRITE setGradient) 45 | 46 | public: 47 | explicit GradientSlider(QWidget *parent = 0); 48 | explicit GradientSlider(Qt::Orientation orientation, QWidget *parent = 0); 49 | ~GradientSlider(); 50 | 51 | /// Get the background, it's visible for transparent gradient stops 52 | QBrush background() const; 53 | /// Set the background, it's visible for transparent gradient stops 54 | void setBackground(const QBrush &bg); 55 | 56 | /// Get the colors that make up the gradient 57 | QGradientStops colors() const; 58 | /// Set the colors that make up the gradient 59 | void setColors(const QGradientStops &colors); 60 | 61 | /// Get the gradient 62 | QLinearGradient gradient() const; 63 | /// Set the gradient 64 | void setGradient(const QLinearGradient &gradient); 65 | 66 | /** 67 | * Overload: create an evenly distributed gradient of the given colors 68 | */ 69 | void setColors(const QVector &colors); 70 | 71 | /** 72 | * \brief Set the first color of the gradient 73 | * 74 | * If the gradient is currently empty it will create a stop with the given color 75 | */ 76 | void setFirstColor(const QColor &c); 77 | 78 | /** 79 | * \brief Set the last color of the gradient 80 | * 81 | * If the gradient is has less than two colors, 82 | * it will create a stop with the given color 83 | */ 84 | void setLastColor(const QColor &c); 85 | 86 | /** 87 | * \brief Get the first color 88 | * 89 | * \returns QColor() con empty gradient 90 | */ 91 | QColor firstColor() const; 92 | 93 | /** 94 | * \brief Get the last color 95 | * 96 | * \returns QColor() con empty gradient 97 | */ 98 | QColor lastColor() const; 99 | 100 | Q_SIGNALS: 101 | void backgroundChanged(const QBrush&); 102 | 103 | protected: 104 | void paintEvent(QPaintEvent *ev) override; 105 | 106 | void mousePressEvent(QMouseEvent *ev) override; 107 | void mouseMoveEvent(QMouseEvent *ev) override; 108 | void mouseReleaseEvent(QMouseEvent *ev) override; 109 | 110 | private: 111 | class Private; 112 | Private * const p; 113 | }; 114 | 115 | } // namespace color_widgets 116 | 117 | #endif // GRADIENT_SLIDER_HPP 118 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/gradient_delegate.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | 23 | #ifndef COLOR_WIDGETS_GRADIENT_DELEGATE_HPP 24 | #define COLOR_WIDGETS_GRADIENT_DELEGATE_HPP 25 | 26 | 27 | #include 28 | #include 29 | 30 | #include "QtColorWidgets/gradient_editor.hpp" 31 | 32 | namespace color_widgets { 33 | 34 | /** 35 | * \brief Item delegate to edits gradients 36 | * 37 | * In order to make it work, return as edit data from the model a QBrush with a gradient 38 | */ 39 | class QCP_EXPORT GradientDelegate : public QStyledItemDelegate 40 | { 41 | Q_OBJECT 42 | 43 | public: 44 | QWidget * createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const Q_DECL_OVERRIDE 45 | { 46 | QVariant data = index.data(Qt::EditRole); 47 | if ( data.canConvert() ) 48 | { 49 | QBrush brush = data.value(); 50 | if ( brush.gradient() ) 51 | { 52 | GradientEditor* editor = new GradientEditor(parent); 53 | editor->setStops(brush.gradient()->stops()); 54 | return editor; 55 | } 56 | } 57 | 58 | return QStyledItemDelegate::createEditor(parent, option, index); 59 | } 60 | 61 | void setModelData(QWidget * widget, QAbstractItemModel * model, const QModelIndex & index) const Q_DECL_OVERRIDE 62 | { 63 | if ( GradientEditor* editor = qobject_cast(widget) ) 64 | model->setData(index, QBrush(editor->gradient()), Qt::EditRole); 65 | else 66 | QStyledItemDelegate::setModelData(widget, model, index); 67 | } 68 | 69 | void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const Q_DECL_OVERRIDE 70 | { 71 | QVariant display_data = index.data(Qt::DisplayRole); 72 | QVariant gradient_data = display_data.isValid() ? display_data : index.data(Qt::EditRole); 73 | if ( gradient_data.canConvert() ) 74 | { 75 | QBrush brush = gradient_data.value(); 76 | if ( brush.gradient() ) 77 | { 78 | QBrush background; 79 | background.setTexture(QPixmap(QStringLiteral(":/color_widgets/alphaback.png"))); 80 | painter->fillRect(option.rect, background); 81 | 82 | QLinearGradient g(option.rect.topLeft(), option.rect.topRight()); 83 | g.setStops(brush.gradient()->stops()); 84 | painter->fillRect(option.rect, g); 85 | 86 | if ( option.state & QStyle::State_Selected ) 87 | { 88 | int border = 2; 89 | painter->setBrush(Qt::transparent); 90 | painter->setPen(QPen(option.palette.highlight(), border)); 91 | painter->drawRect(option.rect.adjusted(border/2, border/2, -border/2, -border/2)); 92 | } 93 | return; 94 | } 95 | } 96 | 97 | QStyledItemDelegate::paint(painter, option, index); 98 | } 99 | }; 100 | 101 | } // namespace color_widgets 102 | 103 | #endif // COLOR_WIDGETS_GRADIENT_DELEGATE_HPP 104 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/color_2d_slider.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | #ifndef COLOR_WIDGETS_COLOR_2D_SLIDER_HPP 23 | #define COLOR_WIDGETS_COLOR_2D_SLIDER_HPP 24 | 25 | #include "colorwidgets_global.hpp" 26 | #include 27 | 28 | namespace color_widgets { 29 | 30 | /** 31 | * \brief A 2D slider that edits 2 color components 32 | */ 33 | class QCP_EXPORT Color2DSlider : public QWidget 34 | { 35 | Q_OBJECT 36 | 37 | Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged DESIGNABLE true STORED false ) 38 | Q_PROPERTY(qreal hue READ hue WRITE setHue DESIGNABLE false ) 39 | Q_PROPERTY(qreal saturation READ saturation WRITE setSaturation DESIGNABLE false ) 40 | Q_PROPERTY(qreal value READ value WRITE setValue DESIGNABLE false ) 41 | /** 42 | * \brief Which color component is used on the x axis 43 | */ 44 | Q_PROPERTY(Component componentX READ componentX WRITE setComponentX NOTIFY componentXChanged) 45 | /** 46 | * \brief Which color component is used on the y axis 47 | */ 48 | Q_PROPERTY(Component componentY READ componentY WRITE setComponentY NOTIFY componentYChanged) 49 | 50 | 51 | public: 52 | enum Component { 53 | Hue, Saturation, Value 54 | }; 55 | Q_ENUMS(Component) 56 | 57 | explicit Color2DSlider(QWidget *parent = nullptr); 58 | ~Color2DSlider(); 59 | 60 | /// Get current color 61 | QColor color() const; 62 | 63 | QSize sizeHint() const Q_DECL_OVERRIDE; 64 | 65 | /// Get current hue in the range [0-1] 66 | qreal hue() const; 67 | 68 | /// Get current saturation in the range [0-1] 69 | qreal saturation() const; 70 | 71 | /// Get current value in the range [0-1] 72 | qreal value() const; 73 | 74 | Component componentX() const; 75 | Component componentY() const; 76 | 77 | public Q_SLOTS: 78 | 79 | /// Set current color 80 | void setColor(const QColor& c); 81 | 82 | /** 83 | * @param h Hue [0-1] 84 | */ 85 | void setHue(qreal h); 86 | 87 | /** 88 | * @param s Saturation [0-1] 89 | */ 90 | void setSaturation(qreal s); 91 | 92 | /** 93 | * @param v Value [0-1] 94 | */ 95 | void setValue(qreal v); 96 | 97 | void setComponentX(Component componentX); 98 | void setComponentY(Component componentY); 99 | 100 | Q_SIGNALS: 101 | /** 102 | * Emitted when the user selects a color or setColor is called 103 | */ 104 | void colorChanged(QColor); 105 | 106 | /** 107 | * Emitted when the user selects a color 108 | */ 109 | void colorSelected(QColor); 110 | 111 | void componentXChanged(Component componentX); 112 | void componentYChanged(Component componentY); 113 | 114 | protected: 115 | void paintEvent(QPaintEvent* event) Q_DECL_OVERRIDE; 116 | void mousePressEvent(QMouseEvent* event) Q_DECL_OVERRIDE; 117 | void mouseMoveEvent(QMouseEvent* event) Q_DECL_OVERRIDE; 118 | void mouseReleaseEvent(QMouseEvent* event) Q_DECL_OVERRIDE; 119 | void resizeEvent(QResizeEvent* event) Q_DECL_OVERRIDE; 120 | 121 | private: 122 | class Private; 123 | Private * const p; 124 | }; 125 | 126 | } // namespace color_widgets 127 | 128 | #endif // COLOR_WIDGETS_COLOR_2D_SLIDER_HPP 129 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/color_preview.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * \copyright Copyright (C) 2014 Calle Laakkonen 8 | * 9 | * This program is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published by 11 | * the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | #ifndef COLOR_PREVIEW_HPP 24 | #define COLOR_PREVIEW_HPP 25 | 26 | #include "colorwidgets_global.hpp" 27 | 28 | #include 29 | 30 | namespace color_widgets { 31 | 32 | /** 33 | * Simple widget that shows a preview of a color 34 | */ 35 | class QCP_EXPORT ColorPreview : public QWidget 36 | { 37 | Q_OBJECT 38 | Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged DESIGNABLE true) 39 | Q_PROPERTY(QColor comparisonColor READ comparisonColor WRITE setComparisonColor NOTIFY comparisonColorChanged DESIGNABLE true) 40 | Q_PROPERTY(DisplayMode display_mode READ displayMode WRITE setDisplayMode NOTIFY displayModeChanged DESIGNABLE true) 41 | Q_PROPERTY(QBrush background READ background WRITE setBackground NOTIFY backgroundChanged DESIGNABLE true) 42 | Q_PROPERTY(bool drawFrame READ drawFrame WRITE setDrawFrame NOTIFY drawFrameChanged DESIGNABLE true) 43 | Q_ENUMS(DisplayMode) 44 | public: 45 | enum DisplayMode 46 | { 47 | NoAlpha, ///< Show current color with no transparency 48 | AllAlpha, ///< show current color with transparency 49 | SplitAlpha, ///< Show both solid and transparent side by side 50 | SplitColor, ///< Show current and comparison colors side by side 51 | SplitColorReverse, ///< Like Split color but swapped 52 | }; 53 | Q_ENUMS(DisplayMode) 54 | 55 | explicit ColorPreview(QWidget *parent = 0); 56 | ~ColorPreview(); 57 | 58 | /// Get the background visible under transparent colors 59 | QBrush background() const; 60 | 61 | /// Change the background visible under transparent colors 62 | void setBackground(const QBrush &bk); 63 | 64 | /// Get color display mode 65 | DisplayMode displayMode() const; 66 | 67 | /// Set how transparent colors are handled 68 | void setDisplayMode(DisplayMode dm); 69 | 70 | /// Get current color 71 | QColor color() const; 72 | 73 | /// Get the comparison color 74 | QColor comparisonColor() const; 75 | 76 | QSize sizeHint () const; 77 | 78 | void paint(QPainter &painter, QRect rect) const; 79 | 80 | /// Whether to draw a frame around the color 81 | bool drawFrame() const; 82 | void setDrawFrame(bool); 83 | 84 | public Q_SLOTS: 85 | /// Set current color 86 | void setColor(const QColor &c); 87 | 88 | /// Set the comparison color 89 | void setComparisonColor(const QColor &c); 90 | 91 | Q_SIGNALS: 92 | /// Emitted when the user clicks on the widget 93 | void clicked(); 94 | 95 | /// Emitted on setColor 96 | void colorChanged(QColor); 97 | 98 | void comparisonColorChanged(QColor); 99 | void displayModeChanged(DisplayMode); 100 | void backgroundChanged(const QBrush&); 101 | void drawFrameChanged(bool); 102 | protected: 103 | void paintEvent(QPaintEvent *); 104 | void resizeEvent(QResizeEvent *); 105 | void mouseReleaseEvent(QMouseEvent *ev); 106 | void mouseMoveEvent(QMouseEvent *ev); 107 | 108 | private: 109 | class Private; 110 | Private * const p; 111 | }; 112 | 113 | } // namespace color_widgets 114 | Q_DECLARE_METATYPE(color_widgets::ColorPreview::DisplayMode) 115 | 116 | #endif // COLOR_PREVIEW_HPP 117 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/gradient_editor.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file gradient_editor.hpp 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | #ifndef GRADIENT_EDITOR_HPP 23 | #define GRADIENT_EDITOR_HPP 24 | 25 | #include "colorwidgets_global.hpp" 26 | 27 | #include 28 | #include 29 | 30 | namespace color_widgets { 31 | 32 | class ColorDialog; 33 | 34 | /** 35 | * \brief A slider that moves on top of a gradient 36 | */ 37 | class QCP_EXPORT GradientEditor : public QWidget 38 | { 39 | Q_OBJECT 40 | Q_PROPERTY(QBrush background READ background WRITE setBackground NOTIFY backgroundChanged) 41 | Q_PROPERTY(QGradientStops stops READ stops WRITE setStops NOTIFY stopsChanged) 42 | Q_PROPERTY(QLinearGradient gradient READ gradient WRITE setGradient) 43 | Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation) 44 | Q_PROPERTY(int selectedStop READ selectedStop WRITE setSelectedStop NOTIFY selectedStopChanged) 45 | Q_PROPERTY(QColor selectedColor READ selectedColor WRITE setSelectedColor) 46 | 47 | public: 48 | explicit GradientEditor(QWidget *parent = 0); 49 | explicit GradientEditor(Qt::Orientation orientation, QWidget *parent = 0); 50 | ~GradientEditor(); 51 | 52 | QSize sizeHint() const override; 53 | 54 | /// Get the background, it's visible for transparent gradient stops 55 | QBrush background() const; 56 | /// Set the background, it's visible for transparent gradient stops 57 | void setBackground(const QBrush &bg); 58 | 59 | /// Get the colors that make up the gradient 60 | QGradientStops stops() const; 61 | /// Set the colors that make up the gradient 62 | void setStops(const QGradientStops &colors); 63 | 64 | /// Get the gradient 65 | QLinearGradient gradient() const; 66 | /// Set the gradient 67 | void setGradient(const QLinearGradient &gradient); 68 | 69 | Qt::Orientation orientation() const; 70 | 71 | /** 72 | * \brief Dialog shown when double clicking a stop 73 | */ 74 | ColorDialog* dialog() const; 75 | 76 | /** 77 | * \brief Index of the currently selected gradient stop (or -1 if there is no selection) 78 | */ 79 | int selectedStop() const; 80 | 81 | /** 82 | * \brief Color of the selected stop 83 | */ 84 | QColor selectedColor() const; 85 | 86 | public Q_SLOTS: 87 | void setOrientation(Qt::Orientation); 88 | void setSelectedStop(int stop); 89 | void setSelectedColor(const QColor& color); 90 | void addStop(); 91 | void removeStop(); 92 | 93 | Q_SIGNALS: 94 | void backgroundChanged(const QBrush&); 95 | void stopsChanged(const QGradientStops&); 96 | void selectedStopChanged(int); 97 | 98 | protected: 99 | void paintEvent(QPaintEvent *ev) override; 100 | 101 | void mousePressEvent(QMouseEvent *ev) override; 102 | void mouseMoveEvent(QMouseEvent *ev) override; 103 | void mouseReleaseEvent(QMouseEvent *ev) override; 104 | void leaveEvent(QEvent * event) override; 105 | void mouseDoubleClickEvent(QMouseEvent *event) override; 106 | 107 | void dragEnterEvent(QDragEnterEvent *event) override; 108 | void dragMoveEvent(QDragMoveEvent* event) override; 109 | void dragLeaveEvent(QDragLeaveEvent *event) override; 110 | void dropEvent(QDropEvent* event) override; 111 | 112 | private Q_SLOTS: 113 | void dialogUpdate(const QColor& c); 114 | 115 | private: 116 | class Private; 117 | Private * const p; 118 | }; 119 | 120 | } // namespace color_widgets 121 | 122 | #endif // GRADIENT_EDITOR_HPP 123 | 124 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/src/QtColorWidgets/hue_slider.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2014 Calle Laakkonen 7 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 8 | * \copyright Copyright (C) 2017 caryoscelus 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public License as published by 12 | * the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Lesser General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | #include "QtColorWidgets/hue_slider.hpp" 25 | 26 | namespace color_widgets { 27 | 28 | class HueSlider::Private 29 | { 30 | private: 31 | HueSlider *w; 32 | 33 | public: 34 | qreal saturation = 1; 35 | qreal value = 1; 36 | qreal alpha = 1; 37 | 38 | Private(HueSlider *widget) 39 | : w(widget) 40 | { 41 | w->setRange(0, 359); 42 | connect(w, &QSlider::valueChanged, [this]{ 43 | Q_EMIT w->colorHueChanged(w->colorHue()); 44 | Q_EMIT w->colorChanged(w->color()); 45 | }); 46 | updateGradient(); 47 | } 48 | 49 | void updateGradient() 50 | { 51 | static const double n_colors = 6; 52 | QGradientStops colors; 53 | colors.reserve(n_colors+1); 54 | for ( int i = 0; i <= n_colors; ++i ) 55 | colors.append(QGradientStop(i/n_colors, QColor::fromHsvF(i/n_colors, saturation, value))); 56 | w->setColors(colors); 57 | } 58 | }; 59 | 60 | HueSlider::HueSlider(QWidget *parent) : 61 | GradientSlider(parent), p(new Private(this)) 62 | { 63 | } 64 | 65 | HueSlider::HueSlider(Qt::Orientation orientation, QWidget *parent) : 66 | GradientSlider(orientation, parent), p(new Private(this)) 67 | { 68 | } 69 | 70 | HueSlider::~HueSlider() 71 | { 72 | delete p; 73 | } 74 | 75 | qreal HueSlider::colorSaturation() const 76 | { 77 | return p->saturation; 78 | } 79 | 80 | void HueSlider::setColorSaturation(qreal s) 81 | { 82 | p->saturation = qBound(0.0, s, 1.0); 83 | p->updateGradient(); 84 | Q_EMIT colorSaturationChanged(s); 85 | } 86 | 87 | qreal HueSlider::colorValue() const 88 | { 89 | return p->value; 90 | } 91 | 92 | void HueSlider::setColorValue(qreal v) 93 | { 94 | p->value = qBound(0.0, v, 1.0); 95 | p->updateGradient(); 96 | Q_EMIT colorValueChanged(v); 97 | } 98 | 99 | qreal HueSlider::colorAlpha() const 100 | { 101 | return p->alpha; 102 | } 103 | 104 | void HueSlider::setColorAlpha(qreal alpha) 105 | { 106 | p->alpha = alpha; 107 | p->updateGradient(); 108 | Q_EMIT colorAlphaChanged(alpha); 109 | } 110 | 111 | QColor HueSlider::color() const 112 | { 113 | return QColor::fromHsvF(colorHue(), p->saturation, p->value, p->alpha); 114 | } 115 | 116 | void HueSlider::setColor(const QColor& color) 117 | { 118 | p->saturation = color.saturationF(); 119 | p->value = color.valueF(); 120 | p->updateGradient(); 121 | setColorHue(color.hueF()); 122 | Q_EMIT colorValueChanged(p->alpha); 123 | Q_EMIT colorSaturationChanged(p->alpha); 124 | } 125 | 126 | void HueSlider::setFullColor(const QColor& color) 127 | { 128 | p->alpha = color.alphaF(); 129 | setColor(color); 130 | Q_EMIT colorAlphaChanged(p->alpha); 131 | } 132 | 133 | qreal HueSlider::colorHue() const 134 | { 135 | if (maximum() == minimum()) 136 | return 0; 137 | auto hue = qreal(value() - minimum()) / (maximum() - minimum()); 138 | if (orientation() == Qt::Vertical) 139 | hue = 1 - hue; 140 | return hue; 141 | } 142 | 143 | void HueSlider::setColorHue(qreal colorHue) 144 | { 145 | // TODO: consider supporting invertedAppearance? 146 | if (orientation() == Qt::Vertical) 147 | colorHue = 1 - colorHue; 148 | setValue(minimum()+colorHue*(maximum()-minimum())); 149 | Q_EMIT colorHueChanged(colorHue); 150 | Q_EMIT colorChanged(color()); 151 | } 152 | 153 | } // namespace color_widgets 154 | -------------------------------------------------------------------------------- /utility.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILITY_H 2 | #define UTILITY_H 3 | 4 | float myasin(float x); 5 | float myacos(float x); 6 | float mysqrt(float x); 7 | float mylog(float x); 8 | 9 | #include 10 | #include "vec3.h" 11 | #include "my_util.h" 12 | #include 13 | using namespace std; 14 | 15 | 16 | struct TripleSegment { 17 | int a, b, c, d, e, f; 18 | double w_ab, w_cd, w_ef; 19 | TripleSegment(int a_, int b_, int c_, int d_, int e_, int f_, double w_ab_ = 0, double w_cd_ = 0, double w_ef_ = 0) { 20 | a = a_, b = b_, c = c_, d = d_, e = e_, f = f_; 21 | w_ab = w_ab_, w_cd = w_cd_, w_ef = w_ef_; 22 | } 23 | TripleSegment() { 24 | a = b = c = d = e = f = w_ab = w_cd = w_ef = 0; 25 | } 26 | }; 27 | 28 | class myfloat3 29 | { 30 | public: 31 | explicit myfloat3(); 32 | explicit myfloat3(float x, float y, float z); 33 | const float norm2() const; 34 | const float norm() const; 35 | float dot(myfloat3 another); 36 | myfloat3 cross(myfloat3 another); 37 | 38 | const myfloat3 operator +(const myfloat3 another) const; 39 | const myfloat3 operator -(const myfloat3 another) const; 40 | 41 | const myfloat3 operator *(float x) const; 42 | const myfloat3 operator /(float x) const; 43 | 44 | float getX() const; 45 | float getY() const; 46 | float getZ() const; 47 | 48 | friend float dot(myfloat3 x, myfloat3 y); 49 | friend myfloat3 cross(myfloat3 x, myfloat3 y); 50 | 51 | private: 52 | float x, y, z; 53 | }; 54 | 55 | class Triangle { 56 | public: 57 | vec3 p, q, r; 58 | 59 | Triangle() {} 60 | Triangle(vec3 v1_, vec3 v2_, vec3 v3_) { 61 | p = v1_; 62 | q = v2_; 63 | r = v3_; 64 | } 65 | }; 66 | 67 | class int3 { 68 | public: 69 | int x, y, z; 70 | int3(int x_ = 0, int y_ = 0, int z_ = 0) { 71 | x = x_; 72 | y = y_; 73 | z = z_; 74 | } 75 | int operator[] (int idx) { 76 | if (idx == 0) 77 | return x; 78 | else if (idx == 1) 79 | return y; 80 | else if (idx == 2) 81 | return z; 82 | } 83 | }; 84 | 85 | class Polyhedron { 86 | public: 87 | vector faces; 88 | vector vertices; 89 | vector current_vertices; 90 | vector correspondences; 91 | 92 | Polyhedron(){} 93 | Polyhedron(vector& verts, vector& fs, vector& corres) { 94 | faces = fs; 95 | vertices = verts; 96 | current_vertices = verts; 97 | correspondences = corres; 98 | } 99 | }; 100 | 101 | class int2 { 102 | public: 103 | int u, v; 104 | int2() { u = 0, v = 0; } 105 | int2(int u_, int v_) { 106 | u = u_; 107 | v = v_; 108 | } 109 | int operator[] (int idx) const { 110 | if (idx == 0) 111 | return u; 112 | else if (idx == 1) 113 | return v; 114 | } 115 | }; 116 | 117 | class vec4 { 118 | public: 119 | float v[4]; 120 | vec4(){} 121 | vec4(float a, float b, float c, float d) { 122 | v[0] = a; 123 | v[1] = b; 124 | v[2] = c; 125 | v[3] = d; 126 | } 127 | float operator[] (int idx) const { 128 | return v[idx]; 129 | } 130 | 131 | vec4 operator*(float mul) const { 132 | return vec4(v[0] * mul, v[1] * mul, v[2] * mul, v[3] * mul); 133 | } 134 | vec4 operator+(const vec4 &another) const { 135 | return vec4( 136 | v[0] + another.v[0], 137 | v[1] + another.v[1], 138 | v[2] + another.v[2], 139 | v[3] + another.v[3] 140 | ); 141 | } 142 | vec4 operator-(const vec4 &another) const { 143 | return vec4( 144 | v[0] - another.v[0], 145 | v[1] - another.v[1], 146 | v[2] - another.v[2], 147 | v[3] - another.v[3] 148 | ); 149 | } 150 | }; 151 | 152 | class VideoPalette { 153 | public: 154 | vector edges; 155 | vector vertices; 156 | void clear() { 157 | edges.clear(); 158 | vertices.clear(); 159 | } 160 | }; 161 | 162 | vec3 closesPointOnTriangle(const vec3 *triangle, const vec3 &sourcePosition); 163 | 164 | bool cut(double time, vec4 p, vec4 q, double &r, double &g, double &b); 165 | void RGBtoHSV(double src_r, double src_g, double src_b, double &dst_h, double &dst_s, double &dst_v); 166 | 167 | double norm2(double x, double y, double z); 168 | void cross(double x1, double y1, double z1, double x2, double y2, double z2, double &x, double &y, double &z); 169 | double angle(double x1, double y1, double z1, double x2, double y2, double z2); 170 | double dot(double x1, double y1, double z1, double x2, double y2, double z2); 171 | 172 | #endif // UTILITY_H 173 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/src/QtColorWidgets/color_list_widget.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | #include "QtColorWidgets/color_list_widget.hpp" 23 | #include "QtColorWidgets/color_selector.hpp" 24 | 25 | namespace color_widgets { 26 | 27 | class ColorListWidget::Private 28 | { 29 | public: 30 | QList colors; 31 | QSignalMapper mapper; 32 | ColorWheel::ShapeEnum wheel_shape = ColorWheel::ShapeTriangle; 33 | ColorWheel::ColorSpaceEnum color_space = ColorWheel::ColorHSV; 34 | bool wheel_rotating = true; 35 | }; 36 | 37 | ColorListWidget::ColorListWidget(QWidget *parent) 38 | : AbstractWidgetList(parent), p(new Private) 39 | { 40 | connect(this, &AbstractWidgetList::removed, this, &ColorListWidget::handle_removed); 41 | connect(&p->mapper, SIGNAL(mapped(int)), SLOT(color_changed(int))); 42 | } 43 | 44 | ColorListWidget::~ColorListWidget() 45 | { 46 | delete p; 47 | } 48 | 49 | QList ColorListWidget::colors() const 50 | { 51 | return p->colors; 52 | } 53 | 54 | void ColorListWidget::setColors(const QList &colors) 55 | { 56 | clear(); 57 | p->colors = colors; 58 | for(int i = 0;i < colors.size();i++ ) 59 | append_widget(i); 60 | Q_EMIT colorsChanged(colors); 61 | } 62 | 63 | void ColorListWidget::swap(int a, int b) 64 | { 65 | ColorSelector* sa = widget_cast(a); 66 | ColorSelector* sb = widget_cast(b); 67 | if ( sa && sb ) 68 | { 69 | QColor ca = sa->color(); 70 | sa->setColor(sb->color()); 71 | sb->setColor(ca); 72 | Q_EMIT colorsChanged(p->colors); 73 | } 74 | } 75 | 76 | void ColorListWidget::append() 77 | { 78 | p->colors.push_back(Qt::black); 79 | append_widget(p->colors.size()-1); 80 | Q_EMIT colorsChanged(p->colors); 81 | } 82 | 83 | void ColorListWidget::emit_changed() 84 | { 85 | Q_EMIT colorsChanged(p->colors); 86 | } 87 | 88 | void ColorListWidget::handle_removed(int i) 89 | { 90 | p->colors.removeAt(i); 91 | Q_EMIT colorsChanged(p->colors); 92 | } 93 | 94 | void ColorListWidget::color_changed(int row) 95 | { 96 | ColorSelector *cs = widget_cast(row); 97 | if ( cs ) 98 | { 99 | p->colors[row] = cs->color(); 100 | Q_EMIT colorsChanged(p->colors); 101 | } 102 | } 103 | 104 | void ColorListWidget::append_widget(int col) 105 | { 106 | ColorSelector* cbs = new ColorSelector; 107 | cbs->setDisplayMode(ColorPreview::AllAlpha); 108 | cbs->setColor(p->colors[col]); 109 | //connect(cbs,SIGNAL(colorChanged(QColor)),SLOT(emit_changed())); 110 | p->mapper.setMapping(cbs,col); 111 | connect(cbs,SIGNAL(colorChanged(QColor)),&p->mapper,SLOT(map())); 112 | connect(this, &ColorListWidget::wheelRotatingChanged, cbs, &ColorSelector::setWheelRotating); 113 | connect(this, &ColorListWidget::wheelShapeChanged, cbs, &ColorSelector::setWheelShape); 114 | connect(this, &ColorListWidget::colorSpaceChanged, cbs, &ColorSelector::setColorSpace); 115 | appendWidget(cbs); 116 | setRowHeight(count()-1,22); 117 | } 118 | 119 | void ColorListWidget::setWheelShape(ColorWheel::ShapeEnum shape) 120 | { 121 | Q_EMIT wheelShapeChanged(p->wheel_shape = shape); 122 | } 123 | 124 | ColorWheel::ShapeEnum ColorListWidget::wheelShape() const 125 | { 126 | return p->wheel_shape; 127 | } 128 | 129 | void ColorListWidget::setColorSpace(ColorWheel::ColorSpaceEnum space) 130 | { 131 | Q_EMIT colorSpaceChanged(p->color_space = space); 132 | } 133 | 134 | ColorWheel::ColorSpaceEnum ColorListWidget::colorSpace() const 135 | { 136 | return p->color_space; 137 | } 138 | 139 | void ColorListWidget::setWheelRotating(bool rotating) 140 | { 141 | Q_EMIT wheelRotatingChanged(p->wheel_rotating = rotating); 142 | } 143 | 144 | bool ColorListWidget::wheelRotating() const 145 | { 146 | return p->wheel_rotating; 147 | } 148 | 149 | } // namespace color_widgets 150 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/src/QtColorWidgets/color_delegate.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | #include "QtColorWidgets/color_delegate.hpp" 23 | #include "QtColorWidgets/color_selector.hpp" 24 | #include "QtColorWidgets/color_dialog.hpp" 25 | #include 26 | #include 27 | #include 28 | 29 | namespace color_widgets { 30 | 31 | ColorDelegate::ColorDelegate(QWidget *parent) : 32 | QStyledItemDelegate(parent) 33 | { 34 | } 35 | 36 | void ColorDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, 37 | const QModelIndex &index) const 38 | { 39 | if ( index.data().type() == QVariant::Color ) 40 | { 41 | QStyleOptionFrame panel; 42 | panel.initFrom(option.widget); 43 | if (option.widget->isEnabled()) 44 | panel.state = QStyle::State_Enabled; 45 | panel.rect = option.rect; 46 | panel.lineWidth = 2; 47 | panel.midLineWidth = 0; 48 | panel.state |= QStyle::State_Sunken; 49 | option.widget->style()->drawPrimitive(QStyle::PE_Frame, &panel, painter, nullptr); 50 | QRect r = option.widget->style()->subElementRect(QStyle::SE_FrameContents, &panel, nullptr); 51 | painter->fillRect(r, index.data().value()); 52 | } 53 | else 54 | { 55 | QStyledItemDelegate::paint(painter, option, index); 56 | } 57 | } 58 | 59 | QSize ColorDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const 60 | { 61 | if ( index.data().type() == QVariant::Color ) 62 | return QSize(24,16); 63 | return QStyledItemDelegate::sizeHint(option, index); 64 | } 65 | 66 | QWidget *ColorDelegate::createEditor(QWidget *parent, 67 | const QStyleOptionViewItem &option, 68 | const QModelIndex &index) const 69 | { 70 | if ( index.data().type() == QVariant::Color ) 71 | { 72 | ColorDialog *editor = new ColorDialog(const_cast(parent)); 73 | connect(editor, &QDialog::accepted, this, &ColorDelegate::close_editor); 74 | connect(editor, &ColorDialog::colorSelected, this, &ColorDelegate::color_changed); 75 | return editor; 76 | } 77 | 78 | return QStyledItemDelegate::createEditor(parent, option, index); 79 | } 80 | 81 | void ColorDelegate::color_changed() 82 | { 83 | ColorDialog *editor = qobject_cast(sender()); 84 | emit commitData(editor); 85 | } 86 | 87 | void ColorDelegate::close_editor() 88 | { 89 | ColorDialog *editor = qobject_cast(sender()); 90 | emit closeEditor(editor); 91 | } 92 | 93 | void ColorDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const 94 | { 95 | 96 | if ( index.data().type() == QVariant::Color ) 97 | { 98 | ColorDialog *selector = qobject_cast(editor); 99 | selector->setColor(qvariant_cast(index.data())); 100 | return; 101 | } 102 | 103 | QStyledItemDelegate::setEditorData(editor, index); 104 | } 105 | 106 | void ColorDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, 107 | const QModelIndex &index) const 108 | { 109 | if ( index.data().type() == QVariant::Color ) 110 | { 111 | ColorDialog *selector = qobject_cast(editor); 112 | model->setData(index, QVariant::fromValue(selector->color())); 113 | return; 114 | } 115 | 116 | QStyledItemDelegate::setModelData(editor, model, index); 117 | } 118 | 119 | void ColorDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, 120 | const QModelIndex &index) const 121 | { 122 | if ( index.data().type() == QVariant::Color ) 123 | { 124 | return; 125 | } 126 | 127 | 128 | QStyledItemDelegate::updateEditorGeometry(editor, option, index); 129 | 130 | } 131 | 132 | } // namespace color_widgets 133 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/color_palette_model.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | #ifndef COLOR_WIDGETS_COLOR_PALETTE_MODEL_HPP 23 | #define COLOR_WIDGETS_COLOR_PALETTE_MODEL_HPP 24 | 25 | #include 26 | #include "color_palette.hpp" 27 | 28 | namespace color_widgets { 29 | 30 | class QCP_EXPORT ColorPaletteModel : public QAbstractListModel 31 | { 32 | Q_OBJECT 33 | /** 34 | * \brief List of directories to be scanned for palette files 35 | */ 36 | Q_PROPERTY(QStringList searchPaths READ searchPaths WRITE setSearchPaths NOTIFY searchPathsChanged) 37 | 38 | /** 39 | * \brief Default directory to be used when saving a palette 40 | */ 41 | Q_PROPERTY(QString savePath READ savePath WRITE setSavePath NOTIFY savePathChanged) 42 | 43 | /** 44 | * \brief Size of the icon used for the palette previews 45 | */ 46 | Q_PROPERTY(QSize iconSize READ iconSize WRITE setIconSize NOTIFY iconSizeChanged) 47 | 48 | 49 | public: 50 | ColorPaletteModel(); 51 | ~ColorPaletteModel(); 52 | int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; 53 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; 54 | bool removeRows(int row, int count, const QModelIndex & parent = QModelIndex()) Q_DECL_OVERRIDE; 55 | 56 | QString savePath() const; 57 | QStringList searchPaths() const; 58 | QSize iconSize() const; 59 | 60 | /** 61 | * \brief Number of palettes 62 | */ 63 | int count() const; 64 | 65 | /** 66 | * \brief Returns a reference to the first palette with the given name 67 | * \pre hasPalette(name) 68 | */ 69 | const ColorPalette& palette(const QString& name) const; 70 | 71 | /** 72 | * \brief Whether a palette with the given name exists in the model 73 | */ 74 | bool hasPalette(const QString& name) const; 75 | 76 | /** 77 | * \brief Get the palette at the given index (row) 78 | * \pre 0 <= index < count() 79 | */ 80 | const ColorPalette& palette(int index) const; 81 | 82 | /** 83 | * \brief Updates an existing palette 84 | * \param index Palette index 85 | * \param palette New palette 86 | * \param save Whether to save the palette to the filesystem 87 | * 88 | * Saving will try: (in this order) 89 | * * To overwrite the file pointed by the old palette 90 | * * To write to the new palette file name 91 | * * To create a file in the save path 92 | * If all of the above fail, the palette will be replaced interally 93 | * but not on the filesystem 94 | * 95 | * \returns \b true if the palette has been successfully updated (and saved) 96 | */ 97 | bool updatePalette(int index, const ColorPalette& palette, bool save = true); 98 | 99 | /** 100 | * \brief Remove a palette from the model and optionally from the filesystem 101 | * \returns \b true if the palette has been successfully removed 102 | */ 103 | bool removePalette(int index, bool remove_file = true); 104 | 105 | /** 106 | * \brief Remove a palette to the model and optionally to the filesystem 107 | * \returns \b true if the palette has been successfully added 108 | */ 109 | bool addPalette(const ColorPalette& palette, bool save = true); 110 | 111 | /** 112 | * \brief The index of the palette with the given file name 113 | * \returns -1 if none is found 114 | */ 115 | int indexFromFile(const QString& filename) const; 116 | 117 | public Q_SLOTS: 118 | void setSavePath(const QString& savePath); 119 | void setSearchPaths(const QStringList& searchPaths); 120 | void addSearchPath(const QString& path); 121 | void setIconSize(const QSize& iconSize); 122 | 123 | /** 124 | * \brief Load palettes files found in the search paths 125 | */ 126 | void load(); 127 | 128 | Q_SIGNALS: 129 | void savePathChanged(const QString& savePath); 130 | void searchPathsChanged(const QStringList& searchPaths); 131 | void iconSizeChanged(const QSize& iconSize); 132 | 133 | private: 134 | class Private; 135 | Private* p; 136 | }; 137 | 138 | } // namespace color_widgets 139 | 140 | #endif // COLOR_WIDGETS_COLOR_PALETTE_MODEL_HPP 141 | -------------------------------------------------------------------------------- /rgbwidget.cpp: -------------------------------------------------------------------------------- 1 | #include "rgbwidget.h" 2 | #include 3 | #include 4 | #include 5 | #include"utility.h" 6 | #include 7 | 8 | // Widget shows a RGB view 9 | 10 | RGBWidget::RGBWidget():sharedMemory("RGBWidget") 11 | { 12 | QTimer *timer = new QTimer(this); 13 | if (!sharedMemory.attach()) 14 | { 15 | sharedMemory.create(sizeof(float[3])); 16 | } 17 | 18 | connect(timer, &QTimer::timeout, [=]() { 19 | sharedMemory.lock(); 20 | const float *data = (float*)sharedMemory.constData(); 21 | rotate_x = data[0]; 22 | rotate_y = data[1]; 23 | rotate_z = data[2]; 24 | sharedMemory.unlock(); 25 | update(); 26 | }); 27 | timer->start(40); 28 | 29 | } 30 | 31 | void RGBWidget::paintGL() 32 | { 33 | OpenGL3DWidget::paintGL(); 34 | 35 | Polyhedron poly = data->GetPalette(); 36 | 37 | 38 | glLineWidth(1.f); 39 | glBegin(GL_LINES); 40 | 41 | for (int p = 0; p <= 1; p++) 42 | for (int r = 0; r <= 1; r++) 43 | { 44 | double q = p - .5; 45 | double s = r - .5; 46 | 47 | glColor3f(p, r, 0.); 48 | glVertex3f(q, s, -.5); 49 | glColor3f(p, r, 1.); 50 | glVertex3f(q, s, .5); 51 | glColor3f(p, 0., r); 52 | glVertex3f(q, -.5, s); 53 | glColor3f(p, 1., r); 54 | glVertex3f(q, .5, s); 55 | glColor3f(0., p, r); 56 | glVertex3f(-.5, q, s); 57 | glColor3f(1., p, r); 58 | glVertex3f(.5, q, s); 59 | } 60 | 61 | glEnd(); 62 | 63 | if (data == nullptr) return; 64 | 65 | int width = data->GetFrameWidth(); 66 | int height = data->GetFrameHeight(); 67 | int depth = data->GetFrameDepth(); 68 | double *video = data->GetImage(); 69 | 70 | int n_vertex = 0; 71 | int n_line = 0; 72 | int n_face = 0; 73 | 74 | //auto face = data->getFace(); 75 | 76 | const double *vertex = nullptr; 77 | const int *line = nullptr; 78 | 79 | if (showImageData) 80 | { 81 | QRandomGenerator rng; 82 | 83 | glPointSize(2.f); 84 | glBegin(GL_POINTS); 85 | 86 | for (int i = 0; i < width * height; i++) 87 | { 88 | if (rng.bounded(1.) > preview) continue; 89 | 90 | double *p = video + time * width * height * depth + i * depth; 91 | double r = p[0], g = p[1], b = p[2]; 92 | 93 | glColor3f(r, g, b); 94 | glVertex3f(r - .5, g - .5, b - .5); 95 | } 96 | 97 | glEnd(); 98 | } 99 | 100 | glPointSize(10.f); 101 | glBegin(GL_POINTS); 102 | 103 | vector vertices = poly.vertices; 104 | 105 | for (int i = 0; i < vertices.size(); i++) 106 | { 107 | vec3 p = vertices[i]; 108 | 109 | double r = p[0], g = p[1], b = p[2]; 110 | glColor3f(r, g, b); 111 | glVertex3f(r - .5, g - .5, b - .5); 112 | } 113 | 114 | glEnd(); 115 | 116 | glLineWidth(3.f); 117 | glBegin(GL_LINES); 118 | 119 | int fcnt = poly.faces.size(); 120 | 121 | for (int i = 0; i < fcnt; i++) 122 | { 123 | int vid1 = poly.faces[i].x; 124 | int vid2 = poly.faces[i].y; 125 | int vid3 = poly.faces[i].z; 126 | 127 | vec3 p = poly.vertices[vid1]; 128 | vec3 q = poly.vertices[vid2]; 129 | vec3 r = poly.vertices[vid3]; 130 | 131 | double center[3] = { 132 | (p[0] + q[0] + r[0]) / 3., 133 | (p[1] + q[1] + r[1]) / 3., 134 | (p[2] + q[2] + r[2]) / 3., 135 | }; 136 | 137 | glColor3f(p[0], p[1], p[2]); 138 | glVertex3f(p[0] - .5, p[1] - .5, p[2] - .5); 139 | 140 | glColor3f(q[0], q[1], q[2]); 141 | glVertex3f(q[0] - .5, q[1] - .5, q[2] - .5); 142 | 143 | glColor3f(p[0], p[1], p[2]); 144 | glVertex3f(p[0] - .5, p[1] - .5, p[2] - .5); 145 | 146 | glColor3f(r[0], r[1], r[2]); 147 | glVertex3f(r[0] - .5, r[1] - .5, r[2] - .5); 148 | 149 | glColor3f(q[0], q[1], q[2]); 150 | glVertex3f(q[0] - .5, q[1] - .5, q[2] - .5); 151 | 152 | glColor3f(r[0], r[1], r[2]); 153 | glVertex3f(r[0] - .5, r[1] - .5, r[2] - .5); 154 | 155 | glColor3f(center[0], center[1], center[2]); 156 | 157 | double d1[3] = { 158 | q[0] - p[0], 159 | q[1] - p[1], 160 | q[2] - p[2], 161 | }; 162 | double d2[3] = { 163 | r[0] - p[0], 164 | r[1] - p[1], 165 | r[2] - p[2], 166 | }; 167 | double n[3] = { 168 | d1[1] * d2[2] - d1[2] * d2[1], 169 | d1[2] * d2[0] - d1[0] * d2[2], 170 | d1[0] * d2[1] - d1[1] * d2[0], 171 | }; 172 | 173 | double norm = n[0] * n[0] + n[1] * n[1] + n[2] * n[2]; 174 | 175 | qDebug() << "DEBUG norm" << norm; 176 | 177 | /* 178 | if (norm > 1e-6) 179 | { 180 | double k = 0.1 / sqrt(norm); 181 | n[0] *= k; 182 | n[1] *= k; 183 | n[2] *= k; 184 | 185 | glColor3f(center[0], center[1], center[2]); 186 | glVertex3f(center[0] - .5, center[1] - .5, center[2] - .5); 187 | 188 | glColor3f(center[0], center[1], center[2]); 189 | glVertex3f(center[0] + n[0] - .5, center[1] + n[1] - .5, center[2] + n[2] - .5); 190 | } 191 | */ 192 | } 193 | glEnd(); 194 | glFlush(); 195 | this->makeCurrent(); 196 | } 197 | 198 | void RGBWidget::mouseMoveEvent(QMouseEvent *event) 199 | { 200 | OpenGL3DWidget::mouseMoveEvent(event); 201 | sharedMemory.lock(); 202 | float *data = (float*)sharedMemory.data(); 203 | data[0] = rotate_x; 204 | data[1] = rotate_y; 205 | data[2] = rotate_z; 206 | sharedMemory.unlock(); 207 | } 208 | 209 | double RGBWidget::_rotate_x = 15.; 210 | double RGBWidget::_rotate_y = -70.; 211 | double RGBWidget::_rotate_z = 0.; -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/color_dialog.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | #ifndef COLOR_DIALOG_HPP 23 | #define COLOR_DIALOG_HPP 24 | 25 | #include "colorwidgets_global.hpp" 26 | #include "color_preview.hpp" 27 | #include "color_wheel.hpp" 28 | 29 | 30 | #include 31 | 32 | class QAbstractButton; 33 | 34 | namespace color_widgets { 35 | 36 | class QCP_EXPORT ColorDialog : public QDialog 37 | { 38 | Q_OBJECT 39 | Q_ENUMS(ButtonMode) 40 | Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged DESIGNABLE true) 41 | Q_PROPERTY(ColorWheel::ShapeEnum wheelShape READ wheelShape WRITE setWheelShape NOTIFY wheelShapeChanged) 42 | Q_PROPERTY(ColorWheel::ColorSpaceEnum colorSpace READ colorSpace WRITE setColorSpace NOTIFY colorSpaceChanged) 43 | Q_PROPERTY(bool wheelRotating READ wheelRotating WRITE setWheelRotating NOTIFY wheelRotatingChanged) 44 | /** 45 | * \brief whether the color alpha channel can be edited. 46 | * 47 | * If alpha is disabled, the selected color's alpha will always be 255. 48 | */ 49 | Q_PROPERTY(bool alphaEnabled READ alphaEnabled WRITE setAlphaEnabled NOTIFY alphaEnabledChanged) 50 | 51 | public: 52 | enum ButtonMode { 53 | OkCancel, 54 | OkApplyCancel, 55 | Close 56 | }; 57 | 58 | explicit ColorDialog(QWidget *parent = 0, Qt::WindowFlags f = 0); 59 | 60 | ~ColorDialog(); 61 | 62 | /** 63 | * Get currently selected color 64 | */ 65 | QColor color() const; 66 | 67 | /** 68 | * Set the display mode for the color preview 69 | */ 70 | void setPreviewDisplayMode(ColorPreview::DisplayMode mode); 71 | 72 | /** 73 | * Get the color preview diplay mode 74 | */ 75 | ColorPreview::DisplayMode previewDisplayMode() const; 76 | 77 | bool alphaEnabled() const; 78 | 79 | /** 80 | * Select which dialog buttons to show 81 | * 82 | * There are three predefined modes: 83 | * OkCancel - this is useful when the dialog is modal and we just want to return a color 84 | * OkCancelApply - this is for non-modal dialogs 85 | * Close - for non-modal dialogs with direct color updates via colorChanged signal 86 | */ 87 | void setButtonMode(ButtonMode mode); 88 | ButtonMode buttonMode() const; 89 | 90 | QSize sizeHint() const; 91 | 92 | ColorWheel::ShapeEnum wheelShape() const; 93 | ColorWheel::ColorSpaceEnum colorSpace() const; 94 | bool wheelRotating() const; 95 | 96 | public Q_SLOTS: 97 | 98 | /** 99 | * Change color 100 | */ 101 | void setColor(const QColor &c); 102 | 103 | /** 104 | * Set the current color and show the dialog 105 | */ 106 | void showColor(const QColor &oldcolor); 107 | 108 | void setWheelShape(ColorWheel::ShapeEnum shape); 109 | void setColorSpace(ColorWheel::ColorSpaceEnum space); 110 | void setWheelRotating(bool rotating); 111 | void getCurrentColor(); 112 | 113 | /** 114 | * Set whether the color alpha channel can be edited. 115 | * If alpha is disabled, the selected color's alpha will always be 255. 116 | */ 117 | void setAlphaEnabled(bool a); 118 | 119 | Q_SIGNALS: 120 | /** 121 | * The current color was changed 122 | */ 123 | void colorChanged(QColor); 124 | 125 | /** 126 | * The user selected the new color by pressing Ok/ 127 | 128 | */ 129 | void colorSelected(QColor); 130 | 131 | void wheelShapeChanged(ColorWheel::ShapeEnum shape); 132 | void colorSpaceChanged(ColorWheel::ColorSpaceEnum space); 133 | void wheelRotatingChanged(bool rotating); 134 | 135 | void alphaEnabledChanged(bool alphaEnabled); 136 | 137 | void sendColor(QColor c); 138 | 139 | private Q_SLOTS: 140 | /// Update all the Ui elements to match the selected color 141 | void setColorInternal(const QColor &color); 142 | /// Update from HSV sliders 143 | void set_hsv(); 144 | /// Update from RGB sliders 145 | void set_rgb(); 146 | /// Update from Alpha slider 147 | void set_alpha(); 148 | 149 | void on_edit_hex_colorChanged(const QColor& color); 150 | void on_edit_hex_colorEditingFinished(const QColor& color); 151 | 152 | void on_buttonBox_clicked(QAbstractButton*); 153 | 154 | protected: 155 | void dragEnterEvent(QDragEnterEvent *event); 156 | void dropEvent(QDropEvent * event); 157 | void mouseReleaseEvent(QMouseEvent *event); 158 | void mouseMoveEvent(QMouseEvent *event); 159 | 160 | private: 161 | class Private; 162 | Private * const p; 163 | }; 164 | 165 | } // namespace color_widgets 166 | 167 | #endif // COLOR_DIALOG_HPP 168 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/gradient_list_model.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | #ifndef COLOR_WIDGETS_GRADIENT_LIST_MODEL_HPP 23 | #define COLOR_WIDGETS_GRADIENT_LIST_MODEL_HPP 24 | 25 | #include "colorwidgets_global.hpp" 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | namespace color_widgets { 32 | 33 | class QCP_EXPORT GradientListModel : public QAbstractListModel 34 | { 35 | Q_OBJECT 36 | 37 | /** 38 | * \brief Size of the icon used for the gradient previews 39 | */ 40 | Q_PROPERTY(QSize iconSize READ iconSize WRITE setIconSize NOTIFY iconSizeChanged) 41 | 42 | Q_PROPERTY(ItemEditMode editMode READ editMode WRITE setEditMode NOTIFY editModeChanged) 43 | 44 | public: 45 | enum ItemEditMode 46 | { 47 | EditNone = 0, 48 | EditName, 49 | EditGradient, 50 | }; 51 | 52 | Q_ENUM(ItemEditMode); 53 | 54 | GradientListModel(QObject *parent = nullptr); 55 | ~GradientListModel(); 56 | int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; 57 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; 58 | Qt::ItemFlags flags(const QModelIndex & index) const Q_DECL_OVERRIDE; 59 | bool setData(const QModelIndex & index, const QVariant & value, int role) Q_DECL_OVERRIDE; 60 | 61 | QSize iconSize() const; 62 | 63 | /** 64 | * \brief Number of gradients 65 | */ 66 | int count() const; 67 | 68 | /** 69 | * \brief Remove all gradients 70 | */ 71 | void clear(); 72 | 73 | /** 74 | * \brief Returns a reference to the first gradient with the given name 75 | * \pre hasGradient(name) 76 | */ 77 | const QLinearGradient& gradient(const QString& name) const; 78 | 79 | /** 80 | * \brief Returns a reference to the first gradient with the given name 81 | * \pre hasGradient(name) 82 | */ 83 | QGradientStops gradientStops(const QString& name) const; 84 | 85 | /** 86 | * \brief Whether a gradient with the given name exists in the model 87 | */ 88 | bool hasGradient(const QString& name) const; 89 | 90 | /** 91 | * \brief Get the gradient at the given index (row) 92 | * \pre 0 <= index < count() 93 | */ 94 | const QLinearGradient& gradient(int index) const; 95 | 96 | /** 97 | * \brief Get the gradient stops at the given index (row) 98 | * \pre 0 <= index < count() 99 | */ 100 | QGradientStops gradientStops(int index) const; 101 | 102 | /** 103 | * \brief Inserts or updates a gradient 104 | * \returns The index for the new gradient 105 | */ 106 | int setGradient(const QString& name, const QGradient& gradient); 107 | 108 | int setGradient(const QString& name, const QGradientStops& gradient); 109 | 110 | /** 111 | * \brief Updates the gradient at \p index 112 | */ 113 | bool setGradient(int index, const QGradient& gradient); 114 | 115 | bool setGradient(int index, const QGradientStops& gradient); 116 | 117 | /** 118 | * \brief Renames the gradient at \p index 119 | * \returns \b true on success 120 | */ 121 | bool rename(int index, const QString& new_name); 122 | 123 | /** 124 | * \brief Renames a gradient 125 | * \returns \b true on success 126 | */ 127 | bool rename(const QString& old_name, const QString& new_name); 128 | 129 | /** 130 | * \brief Remove a gradient from the model 131 | * \returns \b true if the gradient has been successfully removed 132 | */ 133 | bool removeGradient(const QString& name); 134 | 135 | 136 | bool removeGradient(int index); 137 | 138 | /** 139 | * \brief The index of the gradient with the given name 140 | * \returns -1 if none is found 141 | */ 142 | int indexFromName(const QString& name) const; 143 | 144 | /** 145 | * \brief Name of the gradient at index 146 | */ 147 | QString nameFromIndex(int index) const; 148 | 149 | ItemEditMode editMode() const; 150 | 151 | /** 152 | * \brief Brush for a gradient 153 | * \pre 0 <= \p index < count() 154 | */ 155 | QBrush gradientBrush(int index) const; 156 | 157 | public Q_SLOTS: 158 | void setIconSize(const QSize& iconSize); 159 | void setEditMode(ItemEditMode mode); 160 | 161 | Q_SIGNALS: 162 | void iconSizeChanged(const QSize& iconSize); 163 | void editModeChanged(ItemEditMode mode); 164 | 165 | private: 166 | class Private; 167 | std::unique_ptr d; 168 | }; 169 | 170 | } // namespace color_widgets 171 | 172 | #endif // COLOR_WIDGETS_GRADIENT_LIST_MODEL_HPP 173 | 174 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/src/QtColorWidgets/color_selector.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | #include "QtColorWidgets/color_selector.hpp" 23 | #include "QtColorWidgets/color_dialog.hpp" 24 | #include 25 | #include 26 | #include 27 | 28 | namespace color_widgets { 29 | 30 | class ColorSelector::Private 31 | { 32 | public: 33 | UpdateMode update_mode; 34 | ColorDialog *dialog; 35 | QColor old_color; 36 | 37 | Private(QWidget *widget) : dialog(new ColorDialog(widget)) 38 | { 39 | dialog->setButtonMode(ColorDialog::OkCancel); 40 | } 41 | }; 42 | 43 | ColorSelector::ColorSelector(QWidget *parent) : 44 | ColorPreview(parent), p(new Private(this)) 45 | { 46 | setUpdateMode(Continuous); 47 | p->old_color = color(); 48 | 49 | connect(this,&ColorPreview::clicked,this,&ColorSelector::showDialog); 50 | connect(this,SIGNAL(colorChanged(QColor)),this,SLOT(update_old_color(QColor))); 51 | connect(p->dialog,&QDialog::rejected,this,&ColorSelector::reject_dialog); 52 | connect(p->dialog,&ColorDialog::colorSelected, this, &ColorSelector::accept_dialog); 53 | 54 | connect(p->dialog, &ColorDialog::wheelRotatingChanged, this, &ColorSelector::wheelRotatingChanged); 55 | connect(p->dialog, &ColorDialog::wheelShapeChanged, this, &ColorSelector::wheelShapeChanged); 56 | connect(p->dialog, &ColorDialog::colorSpaceChanged, this, &ColorSelector::colorSpaceChanged); 57 | 58 | setAcceptDrops(true); 59 | } 60 | 61 | ColorSelector::~ColorSelector() 62 | { 63 | delete p; 64 | } 65 | 66 | ColorSelector::UpdateMode ColorSelector::updateMode() const 67 | { 68 | return p->update_mode; 69 | } 70 | 71 | void ColorSelector::setUpdateMode(UpdateMode m) 72 | { 73 | p->update_mode = m; 74 | Q_EMIT updateModeChanged(m); 75 | } 76 | 77 | Qt::WindowModality ColorSelector::dialogModality() const 78 | { 79 | return p->dialog->windowModality(); 80 | } 81 | 82 | void ColorSelector::setDialogModality(Qt::WindowModality m) 83 | { 84 | p->dialog->setWindowModality(m); 85 | Q_EMIT dialogModalityChanged(m); 86 | } 87 | 88 | void ColorSelector::setWheelShape(ColorWheel::ShapeEnum shape) 89 | { 90 | p->dialog->setWheelShape(shape); 91 | } 92 | 93 | ColorWheel::ShapeEnum ColorSelector::wheelShape() const 94 | { 95 | return p->dialog->wheelShape(); 96 | } 97 | 98 | void ColorSelector::setColorSpace(ColorWheel::ColorSpaceEnum space) 99 | { 100 | p->dialog->setColorSpace(space); 101 | } 102 | 103 | ColorWheel::ColorSpaceEnum ColorSelector::colorSpace() const 104 | { 105 | return p->dialog->colorSpace(); 106 | } 107 | 108 | void ColorSelector::setWheelRotating(bool rotating) 109 | { 110 | p->dialog->setWheelRotating(rotating); 111 | } 112 | 113 | bool ColorSelector::wheelRotating() const 114 | { 115 | return p->dialog->wheelRotating(); 116 | } 117 | 118 | void ColorSelector::showDialog() 119 | { 120 | p->old_color = color(); 121 | p->dialog->setColor(color()); 122 | connect_dialog(); 123 | p->dialog->show(); 124 | } 125 | 126 | 127 | void ColorSelector::connect_dialog() 128 | { 129 | if (p->update_mode == Continuous) 130 | connect(p->dialog, SIGNAL(colorChanged(QColor)), this, SLOT(setColor(QColor)), Qt::UniqueConnection); 131 | else 132 | disconnect_dialog(); 133 | } 134 | 135 | void ColorSelector::disconnect_dialog() 136 | { 137 | disconnect(p->dialog, SIGNAL(colorChanged(QColor)), this, SLOT(setColor(QColor))); 138 | } 139 | 140 | void ColorSelector::accept_dialog() 141 | { 142 | setColor(p->dialog->color()); 143 | p->old_color = color(); 144 | Q_EMIT colorSelected(color()); 145 | } 146 | 147 | void ColorSelector::reject_dialog() 148 | { 149 | setColor(p->old_color); 150 | } 151 | 152 | void ColorSelector::update_old_color(const QColor &c) 153 | { 154 | if (!p->dialog->isVisible()) 155 | p->old_color = c; 156 | } 157 | 158 | void ColorSelector::dragEnterEvent(QDragEnterEvent *event) 159 | { 160 | if ( event->mimeData()->hasColor() || 161 | ( event->mimeData()->hasText() && QColor(event->mimeData()->text()).isValid() ) ) 162 | event->acceptProposedAction(); 163 | } 164 | 165 | 166 | void ColorSelector::dropEvent(QDropEvent *event) 167 | { 168 | if ( event->mimeData()->hasColor() ) 169 | { 170 | setColor(event->mimeData()->colorData().value()); 171 | event->accept(); 172 | } 173 | else if ( event->mimeData()->hasText() ) 174 | { 175 | QColor col(event->mimeData()->text()); 176 | if ( col.isValid() ) 177 | { 178 | setColor(col); 179 | event->accept(); 180 | } 181 | } 182 | } 183 | 184 | } // namespace color_widgets 185 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/src/QtColorWidgets/abstract_widget_list.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | #include "QtColorWidgets/abstract_widget_list.hpp" 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | class AbstractWidgetList::Private 29 | { 30 | public: 31 | QList widgets; 32 | QSignalMapper mapper_up; 33 | QSignalMapper mapper_down; 34 | QSignalMapper mapper_remove; 35 | QTableWidget *table; 36 | }; 37 | 38 | AbstractWidgetList::AbstractWidgetList(QWidget *parent) : 39 | QWidget(parent), p(new Private) 40 | { 41 | connect(&p->mapper_up,SIGNAL(mapped(QWidget*)),SLOT(up_clicked(QWidget*))); 42 | connect(&p->mapper_down,SIGNAL(mapped(QWidget*)),SLOT(down_clicked(QWidget*))); 43 | connect(&p->mapper_remove,SIGNAL(mapped(QWidget*)),SLOT(remove_clicked(QWidget*))); 44 | 45 | 46 | QVBoxLayout *verticalLayout = new QVBoxLayout(this); 47 | verticalLayout->setContentsMargins(0, 0, 0, 0); 48 | p->table = new QTableWidget(this); 49 | verticalLayout->addWidget(p->table); 50 | 51 | 52 | p->table->insertColumn(0); 53 | p->table->insertColumn(1); 54 | p->table->insertColumn(2); 55 | p->table->insertColumn(3); 56 | 57 | p->table->setColumnWidth(0,128); 58 | p->table->setColumnWidth(1,24); 59 | p->table->setColumnWidth(2,24); 60 | p->table->setColumnWidth(3,24); 61 | 62 | p->table->horizontalHeader()->hide(); 63 | p->table->verticalHeader()->hide(); 64 | p->table->setShowGrid(false); 65 | 66 | QPushButton* add_button = new QPushButton(QIcon::fromTheme(QStringLiteral("list-add")), 67 | tr("Add New")); 68 | 69 | verticalLayout->addWidget(add_button); 70 | connect(add_button,&QAbstractButton::clicked,this, &AbstractWidgetList::append); 71 | 72 | } 73 | 74 | AbstractWidgetList::~AbstractWidgetList() 75 | { 76 | delete p; 77 | } 78 | 79 | int AbstractWidgetList::count() const 80 | { 81 | return p->widgets.size(); 82 | } 83 | 84 | void AbstractWidgetList::setRowHeight(int row, int height) 85 | { 86 | p->table->setRowHeight(row,height); 87 | } 88 | 89 | void AbstractWidgetList::clear() 90 | { 91 | p->widgets.clear(); 92 | while(p->table->rowCount() > 0) 93 | p->table->removeRow(0); 94 | } 95 | 96 | 97 | void AbstractWidgetList::remove(int i) 98 | { 99 | if ( isValidRow(i) ) 100 | { 101 | p->widgets.removeAt(i); 102 | p->table->removeRow(i); 103 | if ( i == 0 && !p->widgets.isEmpty() ) 104 | p->table->cellWidget(0,1)->setEnabled(false); 105 | else if ( i != 0 && i == count() ) 106 | p->table->cellWidget(count()-1,2)->setEnabled(false); 107 | 108 | Q_EMIT removed(i); 109 | } 110 | } 111 | 112 | 113 | void AbstractWidgetList::appendWidget(QWidget *w) 114 | { 115 | int row = count(); 116 | p->table->insertRow(row); 117 | 118 | QWidget* b_up = create_button(w,&p->mapper_up,QStringLiteral("go-up"),tr("Move Up")); 119 | QWidget* b_down = create_button(w,&p->mapper_down,QStringLiteral("go-down"),tr("Move Down")); 120 | QWidget* b_remove = create_button(w,&p->mapper_remove,QStringLiteral("list-remove"),tr("Remove")); 121 | if ( row == 0 ) 122 | b_up->setEnabled(false); 123 | else 124 | p->table->cellWidget(row-1,2)->setEnabled(true); 125 | b_down->setEnabled(false); 126 | 127 | p->table->setCellWidget(row,0,w); 128 | p->table->setCellWidget(row,1,b_up); 129 | p->table->setCellWidget(row,2,b_down); 130 | p->table->setCellWidget(row,3,b_remove); 131 | 132 | p->widgets.push_back(w); 133 | } 134 | 135 | QWidget *AbstractWidgetList::widget(int i) 136 | { 137 | if ( isValidRow(i) ) 138 | return p->widgets[i]; 139 | return 0; 140 | } 141 | 142 | 143 | QWidget *AbstractWidgetList::create_button(QWidget *data, QSignalMapper *mapper, 144 | QString icon_name, 145 | QString text, QString tooltip) const 146 | { 147 | 148 | QToolButton* btn = new QToolButton; 149 | btn->setIcon(QIcon::fromTheme(icon_name)); 150 | btn->setText(text); 151 | btn->setToolTip(tooltip.isNull() ? btn->text() : tooltip ); 152 | connect(btn,SIGNAL(clicked()),mapper,SLOT(map())); 153 | mapper->setMapping(btn,data); 154 | return btn; 155 | } 156 | 157 | void AbstractWidgetList::remove_clicked(QWidget *w) 158 | { 159 | int row = p->widgets.indexOf(w); 160 | remove(row); 161 | } 162 | 163 | void AbstractWidgetList::up_clicked(QWidget *w) 164 | { 165 | int row = p->widgets.indexOf(w); 166 | if ( row > 0 ) 167 | swap(row,row-1); 168 | } 169 | 170 | void AbstractWidgetList::down_clicked(QWidget *w) 171 | { 172 | int row = p->widgets.indexOf(w); 173 | if ( row+1 < count() ) 174 | swap(row,row+1); 175 | } 176 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/src/QtColorWidgets/color_preview.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * \copyright Copyright (C) 2014 Calle Laakkonen 8 | * 9 | * This program is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published by 11 | * the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | #include "QtColorWidgets/color_preview.hpp" 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | namespace color_widgets { 32 | 33 | class ColorPreview::Private 34 | { 35 | public: 36 | QColor col; ///< color to be viewed 37 | QColor comparison; ///< comparison color 38 | QBrush back;///< Background brush, visible on a transparent color 39 | DisplayMode display_mode; ///< How the color(s) are to be shown 40 | bool draw_frame = true; ///< Whether to draw a frame around the color 41 | 42 | Private() : col(Qt::red), back(Qt::darkGray, Qt::DiagCrossPattern), display_mode(NoAlpha) 43 | {} 44 | }; 45 | 46 | ColorPreview::ColorPreview(QWidget *parent) : 47 | QWidget(parent), p(new Private) 48 | { 49 | p->back.setTexture(QPixmap(QStringLiteral(":/color_widgets/alphaback.png"))); 50 | } 51 | 52 | ColorPreview::~ColorPreview() 53 | { 54 | delete p; 55 | } 56 | 57 | void ColorPreview::setBackground(const QBrush &bk) 58 | { 59 | p->back = bk; 60 | update(); 61 | Q_EMIT backgroundChanged(bk); 62 | } 63 | 64 | QBrush ColorPreview::background() const 65 | { 66 | return p->back; 67 | } 68 | 69 | ColorPreview::DisplayMode ColorPreview::displayMode() const 70 | { 71 | return p->display_mode; 72 | } 73 | 74 | void ColorPreview::setDisplayMode(DisplayMode m) 75 | { 76 | p->display_mode = m; 77 | update(); 78 | Q_EMIT displayModeChanged(m); 79 | } 80 | 81 | QColor ColorPreview::color() const 82 | { 83 | return p->col; 84 | } 85 | 86 | QColor ColorPreview::comparisonColor() const 87 | { 88 | return p->comparison; 89 | } 90 | 91 | QSize ColorPreview::sizeHint() const 92 | { 93 | return QSize(24,24); 94 | } 95 | 96 | void ColorPreview::paint(QPainter &painter, QRect rect) const 97 | { 98 | QColor c1, c2; 99 | switch(p->display_mode) { 100 | case DisplayMode::NoAlpha: 101 | c1 = c2 = p->col.rgb(); 102 | break; 103 | case DisplayMode::AllAlpha: 104 | c1 = c2 = p->col; 105 | break; 106 | case DisplayMode::SplitAlpha: 107 | c1 = p->col.rgb(); 108 | c2 = p->col; 109 | break; 110 | case DisplayMode::SplitColor: 111 | c1 = p->comparison; 112 | c2 = p->col; 113 | break; 114 | case DisplayMode::SplitColorReverse: 115 | c1 = p->col; 116 | c2 = p->comparison; 117 | break; 118 | } 119 | 120 | if ( p->draw_frame ) 121 | { 122 | QStyleOptionFrame panel; 123 | panel.initFrom(this); 124 | panel.lineWidth = 2; 125 | panel.midLineWidth = 0; 126 | panel.state |= QStyle::State_Sunken; 127 | style()->drawPrimitive(QStyle::PE_Frame, &panel, &painter, this); 128 | QRect r = style()->subElementRect(QStyle::SE_FrameContents, &panel, this); 129 | painter.setClipRect(r); 130 | } 131 | 132 | if ( c1.alpha() < 255 || c2.alpha() < 255 ) 133 | painter.fillRect(0, 0, rect.width(), rect.height(), p->back); 134 | 135 | int w = rect.width() / 2; 136 | int h = rect.height(); 137 | painter.fillRect(0, 0, w, h, c1); 138 | painter.fillRect(w, 0, w, h, c2); 139 | } 140 | 141 | void ColorPreview::setColor(const QColor &c) 142 | { 143 | p->col = c; 144 | update(); 145 | Q_EMIT colorChanged(c); 146 | } 147 | 148 | void ColorPreview::setComparisonColor(const QColor &c) 149 | { 150 | p->comparison = c; 151 | update(); 152 | Q_EMIT comparisonColorChanged(c); 153 | } 154 | 155 | void ColorPreview::paintEvent(QPaintEvent *) 156 | { 157 | QStylePainter painter(this); 158 | 159 | paint(painter, geometry()); 160 | } 161 | 162 | void ColorPreview::resizeEvent(QResizeEvent *) 163 | { 164 | update(); 165 | } 166 | 167 | void ColorPreview::mouseReleaseEvent(QMouseEvent * ev) 168 | { 169 | if ( QRect(QPoint(0,0),size()).contains(ev->pos()) ) 170 | Q_EMIT clicked(); 171 | } 172 | 173 | void ColorPreview::mouseMoveEvent(QMouseEvent *ev) 174 | { 175 | 176 | if ( ev->buttons() &Qt::LeftButton && !QRect(QPoint(0,0),size()).contains(ev->pos()) ) 177 | { 178 | QMimeData *data = new QMimeData; 179 | 180 | data->setColorData(p->col); 181 | 182 | QDrag* drag = new QDrag(this); 183 | drag->setMimeData(data); 184 | 185 | QPixmap preview(24,24); 186 | preview.fill(p->col); 187 | drag->setPixmap(preview); 188 | 189 | drag->exec(); 190 | } 191 | } 192 | 193 | bool ColorPreview::drawFrame() const 194 | { 195 | return p->draw_frame; 196 | } 197 | 198 | void ColorPreview::setDrawFrame(bool draw) 199 | { 200 | Q_EMIT drawFrameChanged(p->draw_frame = draw); 201 | update(); 202 | } 203 | 204 | } // namespace color_widgets 205 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/color_wheel.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | #ifndef COLOR_WHEEL_HPP 23 | #define COLOR_WHEEL_HPP 24 | 25 | #include 26 | 27 | #include "colorwidgets_global.hpp" 28 | 29 | 30 | namespace color_widgets { 31 | 32 | /** 33 | * \brief Display an analog widget that allows the selection of a HSV color 34 | * 35 | * It has an outer wheel to select the Hue and an intenal square to select 36 | * Saturation and Lightness. 37 | */ 38 | class QCP_EXPORT ColorWheel : public QWidget 39 | { 40 | Q_OBJECT 41 | 42 | Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged DESIGNABLE true STORED false ) 43 | Q_PROPERTY(qreal hue READ hue WRITE setHue DESIGNABLE false ) 44 | Q_PROPERTY(qreal saturation READ saturation WRITE setSaturation DESIGNABLE false ) 45 | Q_PROPERTY(qreal value READ value WRITE setValue DESIGNABLE false ) 46 | Q_PROPERTY(unsigned wheelWidth READ wheelWidth WRITE setWheelWidth NOTIFY wheelWidthChanged DESIGNABLE true ) 47 | Q_PROPERTY(ShapeEnum selectorShape READ selectorShape WRITE setSelectorShape NOTIFY selectorShapeChanged DESIGNABLE true ) 48 | Q_PROPERTY(bool rotatingSelector READ rotatingSelector WRITE setRotatingSelector NOTIFY rotatingSelectorChanged DESIGNABLE true ) 49 | Q_PROPERTY(ColorSpaceEnum colorSpace READ colorSpace WRITE setColorSpace NOTIFY colorSpaceChanged DESIGNABLE true ) 50 | 51 | public: 52 | enum ShapeEnum 53 | { 54 | ShapeTriangle, ///< A triangle 55 | ShapeSquare, ///< A square 56 | }; 57 | 58 | enum AngleEnum 59 | { 60 | AngleFixed, ///< The inner part doesn't rotate 61 | AngleRotating, ///< The inner part follows the hue selector 62 | }; 63 | 64 | enum ColorSpaceEnum 65 | { 66 | ColorHSV, ///< Use the HSV color space 67 | ColorHSL, ///< Use the HSL color space 68 | ColorLCH, ///< Use Luma Chroma Hue (Y_601') 69 | }; 70 | 71 | Q_ENUM(ShapeEnum); 72 | Q_ENUM(AngleEnum); 73 | Q_ENUM(ColorSpaceEnum); 74 | 75 | explicit ColorWheel(QWidget *parent = 0); 76 | ~ColorWheel(); 77 | 78 | /// Get current color 79 | QColor color() const; 80 | 81 | virtual QSize sizeHint() const Q_DECL_OVERRIDE; 82 | 83 | /// Get current hue in the range [0-1] 84 | qreal hue() const; 85 | 86 | /// Get current saturation in the range [0-1] 87 | qreal saturation() const; 88 | 89 | /// Get current value in the range [0-1] 90 | qreal value() const; 91 | 92 | /// Get the width in pixels of the outer wheel 93 | unsigned int wheelWidth() const; 94 | 95 | /// Set the width in pixels of the outer wheel 96 | void setWheelWidth(unsigned int w); 97 | 98 | /// Shape of the internal selector 99 | ShapeEnum selectorShape() const; 100 | 101 | /// Whether the internal selector should rotare in accordance with the hue 102 | bool rotatingSelector() const; 103 | 104 | /// Color space used to preview/edit the color 105 | ColorSpaceEnum colorSpace() const; 106 | 107 | public Q_SLOTS: 108 | 109 | /// Set current color 110 | void setColor(QColor c); 111 | 112 | /** 113 | * @param h Hue [0-1] 114 | */ 115 | void setHue(qreal h); 116 | 117 | /** 118 | * @param s Saturation [0-1] 119 | */ 120 | void setSaturation(qreal s); 121 | 122 | /** 123 | * @param v Value [0-1] 124 | */ 125 | void setValue(qreal v); 126 | 127 | /// Sets the shape of the internal selector 128 | void setSelectorShape(ShapeEnum shape); 129 | 130 | /// Sets whether the internal selector should rotare in accordance with the hue 131 | void setRotatingSelector(bool rotating); 132 | 133 | /// Sets the color space used to preview/edit the color 134 | void setColorSpace(ColorSpaceEnum space); 135 | 136 | Q_SIGNALS: 137 | /** 138 | * Emitted when the user selects a color or setColor is called 139 | */ 140 | void colorChanged(QColor); 141 | 142 | /** 143 | * Emitted when the user selects a color 144 | */ 145 | void colorSelected(QColor); 146 | 147 | void wheelWidthChanged(unsigned); 148 | 149 | void selectorShapeChanged(ShapeEnum shape); 150 | 151 | void rotatingSelectorChanged(bool rotating); 152 | 153 | void colorSpaceChanged(ColorSpaceEnum space); 154 | 155 | protected: 156 | void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE; 157 | void mouseMoveEvent(QMouseEvent *) Q_DECL_OVERRIDE; 158 | void mousePressEvent(QMouseEvent *) Q_DECL_OVERRIDE; 159 | void mouseReleaseEvent(QMouseEvent *) Q_DECL_OVERRIDE; 160 | void resizeEvent(QResizeEvent *) Q_DECL_OVERRIDE; 161 | void dragEnterEvent(QDragEnterEvent* event) Q_DECL_OVERRIDE; 162 | void dropEvent(QDropEvent* event) Q_DECL_OVERRIDE; 163 | 164 | protected: 165 | class Private; 166 | ColorWheel(QWidget *parent, Private* data); 167 | Private* data() const { return p; } 168 | 169 | private: 170 | Private * const p; 171 | 172 | }; 173 | 174 | } // namespace color_widgets 175 | 176 | #endif // COLOR_WHEEL_HPP 177 | -------------------------------------------------------------------------------- /vec3.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by YILI WANG on 3/11/19. 3 | // 4 | 5 | #ifndef PALEfloatfloatE_EDIfloat_VEC3_H 6 | #define PALEfloatfloatE_EDIfloat_VEC3_H 7 | 8 | #include "utility.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | class vec3 18 | { 19 | public: 20 | 21 | vec3(float x_, float y_, float z_) { v[0] = x_; v[1] = y_; v[2] = z_; } 22 | 23 | vec3(const vec3 & p) 24 | { 25 | v[0] = (float)(p[0]); 26 | v[1] = (float)(p[1]); 27 | v[2] = (float)(p[2]); 28 | } 29 | 30 | vec3() { v[0] = 0; v[1] = 0; v[2] = 0; } 31 | 32 | inline float x() const { return v[0]; } 33 | inline float y() const { return v[1]; } 34 | inline float z() const { return v[2]; } 35 | 36 | inline float operator [] (unsigned int c) const 37 | { 38 | return v[c]; 39 | } 40 | inline float & operator [] (unsigned int c) 41 | { 42 | return v[c]; 43 | } 44 | 45 | static vec3 Zero() { return vec3(0, 0, 0); } 46 | 47 | void setZero() 48 | { 49 | v[0] = 0; 50 | v[1] = 0; 51 | v[2] = 0; 52 | } 53 | 54 | void operator = (const vec3 & other) 55 | { 56 | v[0] = other.x(); 57 | v[1] = other.y(); 58 | v[2] = other.z(); 59 | } 60 | 61 | void operator += (const vec3 & other) 62 | { 63 | v[0] += other.x(); 64 | v[1] += other.y(); 65 | v[2] += other.z(); 66 | } 67 | 68 | void operator -= (const vec3 & other) 69 | { 70 | v[0] -= other.x(); 71 | v[1] -= other.y(); 72 | v[2] -= other.z(); 73 | } 74 | 75 | // floathis is going to create problems if the compiler needs to resolve umbiguous casts, but it's the cleaner way to do it 76 | void operator *= (int s) 77 | { 78 | v[0] *= s; 79 | v[1] *= s; 80 | v[2] *= s; 81 | } 82 | void operator *= (unsigned int s) 83 | { 84 | v[0] *= s; 85 | v[1] *= s; 86 | v[2] *= s; 87 | } 88 | void operator *= (float s) 89 | { 90 | v[0] *= s; 91 | v[1] *= s; 92 | v[2] *= s; 93 | } 94 | void operator *= (double s) 95 | { 96 | v[0] *= s; 97 | v[1] *= s; 98 | v[2] *= s; 99 | } 100 | void operator /= (int s) 101 | { 102 | v[0] /= s; 103 | v[1] /= s; 104 | v[2] /= s; 105 | } 106 | void operator /= (unsigned int s) 107 | { 108 | v[0] /= s; 109 | v[1] /= s; 110 | v[2] /= s; 111 | } 112 | void operator /= (float s) 113 | { 114 | v[0] /= s; 115 | v[1] /= s; 116 | v[2] /= s; 117 | } 118 | void operator /= (double s) 119 | { 120 | v[0] /= s; 121 | v[1] /= s; 122 | v[2] /= s; 123 | } 124 | 125 | vec3 getOrthogonal() const 126 | { 127 | if (v[0] == 0) 128 | { 129 | return vec3(0, v[2], -v[1]); 130 | } 131 | else if (v[1] == 0) 132 | { 133 | return vec3(v[2], 0, -v[0]); 134 | } 135 | 136 | return vec3(v[1], -v[0], 0); 137 | } 138 | 139 | 140 | float sqrnorm() const 141 | { 142 | return v[0] * v[0] + v[1] * v[1] + v[2] * v[2]; 143 | } 144 | 145 | float norm() const 146 | { 147 | return mysqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); 148 | } 149 | 150 | void normalize() 151 | { 152 | float _n = norm(); 153 | v[0] /= _n; 154 | v[1] /= _n; 155 | v[2] /= _n; 156 | } 157 | 158 | //float dot(const vec3& anotherVec) const { 159 | // return ::dot(*this,anotherVec); 160 | //} 161 | operator QString() const { 162 | QString result; 163 | QTextStream(&result) << "vec3(" << v[0] << ", " << v[1] << ", " << v[2] << ")"; 164 | return result; 165 | } 166 | 167 | private: 168 | float v[3]; 169 | }; 170 | 171 | 172 | 173 | 174 | inline 175 | float dot(const vec3 & p1, const vec3 & p2) 176 | { 177 | return p1.x() * p2.x() + p1.y() * p2.y() + p1.z() * p2.z(); 178 | } 179 | inline 180 | vec3 cross(const vec3 & p1, const vec3 & p2) { 181 | return vec3( 182 | p1.y() * p2.z() - p1.z() * p2.y(), 183 | p1.z() * p2.x() - p1.x() * p2.z(), 184 | p1.x() * p2.y() - p1.y() * p2.x() 185 | ); 186 | } 187 | 188 | inline 189 | vec3 operator + (const vec3 & p1, const vec3 & p2) 190 | { 191 | return vec3(p1.x() + p2.x(), p1.y() + p2.y(), p1.z() + p2.z()); 192 | } 193 | inline 194 | vec3 operator - (const vec3 & p1, const vec3 & p2) 195 | { 196 | return vec3(p1.x() - p2.x(), p1.y() - p2.y(), p1.z() - p2.z()); 197 | } 198 | 199 | 200 | inline 201 | vec3 operator - (const vec3 & p2) 202 | { 203 | return vec3(-p2.x(), -p2.y(), -p2.z()); 204 | } 205 | 206 | inline 207 | vec3 operator * (const vec3 & p, int s) 208 | { 209 | return vec3(s*p.x(), s*p.y(), s*p.z()); 210 | } 211 | inline 212 | vec3 operator * (const vec3 & p, float s) 213 | { 214 | return vec3(s*p.x(), s*p.y(), s*p.z()); 215 | } 216 | inline 217 | vec3 operator * (const vec3 & p, double s) 218 | { 219 | return vec3(s*p.x(), s*p.y(), s*p.z()); 220 | } 221 | inline 222 | vec3 operator * (int s, const vec3 & p) 223 | { 224 | return vec3(s*p.x(), s*p.y(), s*p.z()); 225 | } 226 | inline 227 | vec3 operator * (float s, const vec3 & p) 228 | { 229 | return vec3(s*p.x(), s*p.y(), s*p.z()); 230 | } 231 | inline 232 | vec3 operator * (double s, const vec3 & p) 233 | { 234 | return vec3(s*p.x(), s*p.y(), s*p.z()); 235 | } 236 | 237 | 238 | inline 239 | vec3 operator / (const vec3 & p, int s) 240 | { 241 | return vec3(p.x() / s, p.y() / s, p.z() / s); 242 | } 243 | inline 244 | vec3 operator / (const vec3 & p, float s) 245 | { 246 | return vec3(p.x() / s, p.y() / s, p.z() / s); 247 | } 248 | inline 249 | vec3 operator / (const vec3 & p, double s) 250 | { 251 | return vec3(p.x() / s, p.y() / s, p.z() / s); 252 | } 253 | 254 | 255 | inline 256 | float operator * (const vec3 & p1, const vec3 & p2) 257 | { 258 | return p1.x() * p2.x() + p1.y() * p2.y() + p1.z() * p2.z(); 259 | } 260 | 261 | 262 | inline 263 | vec3 operator % (const vec3 & p1, const vec3 & p2) 264 | { 265 | return cross(p1, p2); 266 | } 267 | 268 | 269 | inline std::ostream & operator << (std::ostream & s, vec3 const & p) 270 | { 271 | s << p[0] << " \t" << p[1] << " \t" << p[2]; 272 | return s; 273 | } 274 | 275 | 276 | #endif //PALEfloatfloatE_EDIfloat_VEC3_H 277 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/src/QtColorWidgets/color_line_edit.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * \copyright Copyright (C) 2017 caryoscelus 8 | * 9 | * This program is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published by 11 | * the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | #include "QtColorWidgets/color_line_edit.hpp" 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "QtColorWidgets/color_utils.hpp" 33 | #include "QtColorWidgets/color_names.hpp" 34 | 35 | namespace color_widgets { 36 | 37 | 38 | class ColorLineEdit::Private 39 | { 40 | public: 41 | QColor color; 42 | bool show_alpha = false; 43 | bool preview_color = false; 44 | QBrush background; 45 | 46 | bool customAlpha() 47 | { 48 | return preview_color && show_alpha && color.alpha() < 255; 49 | } 50 | 51 | void setPalette(const QColor& color, ColorLineEdit* parent) 52 | { 53 | if ( preview_color ) 54 | { 55 | QColor bg = customAlpha() ? Qt::transparent : color; 56 | QColor text = detail::color_lumaF(color) > 0.5 || color.alphaF() < 0.2 ? Qt::black : Qt::white; 57 | parent->setStyleSheet( 58 | QString("background-color: %1; color: %2;") 59 | .arg(bg.name()).arg(text.name()) 60 | ); 61 | } 62 | } 63 | }; 64 | 65 | ColorLineEdit::ColorLineEdit(QWidget* parent) 66 | : QLineEdit(parent), p(new Private) 67 | { 68 | p->background.setTexture(QPixmap(QStringLiteral(":/color_widgets/alphaback.png"))); 69 | setColor(Qt::white); 70 | /// \todo determine if having this connection might be useful 71 | /*connect(this, &QLineEdit::textChanged, [this](const QString& text){ 72 | QColor color = p->colorFromString(text); 73 | if ( color.isValid() ) 74 | Q_EMIT colorChanged(color); 75 | });*/ 76 | connect(this, &QLineEdit::textEdited, [this](const QString& text){ 77 | QColor color = color_widgets::colorFromString(text, p->show_alpha); 78 | if ( color.isValid() ) 79 | { 80 | p->color = color; 81 | p->setPalette(color, this); 82 | Q_EMIT colorEdited(color); 83 | Q_EMIT colorChanged(color); 84 | } 85 | }); 86 | connect(this, &QLineEdit::editingFinished, [this](){ 87 | QColor color = color_widgets::colorFromString(text(), p->show_alpha); 88 | if ( color.isValid() ) 89 | { 90 | p->color = color; 91 | Q_EMIT colorEditingFinished(color); 92 | Q_EMIT colorChanged(color); 93 | } 94 | else 95 | { 96 | setText(color_widgets::stringFromColor(p->color, p->show_alpha)); 97 | Q_EMIT colorEditingFinished(p->color); 98 | Q_EMIT colorChanged(color); 99 | } 100 | p->setPalette(p->color, this); 101 | }); 102 | } 103 | 104 | ColorLineEdit::~ColorLineEdit() 105 | { 106 | delete p; 107 | } 108 | 109 | QColor ColorLineEdit::color() const 110 | { 111 | return p->color; 112 | } 113 | 114 | void ColorLineEdit::setColor(const QColor& color) 115 | { 116 | if ( color != p->color ) 117 | { 118 | p->color = color; 119 | p->setPalette(p->color, this); 120 | setText(color_widgets::stringFromColor(p->color, p->show_alpha)); 121 | Q_EMIT colorChanged(p->color); 122 | } 123 | } 124 | 125 | void ColorLineEdit::setShowAlpha(bool showAlpha) 126 | { 127 | if ( p->show_alpha != showAlpha ) 128 | { 129 | p->show_alpha = showAlpha; 130 | p->setPalette(p->color, this); 131 | setText(color_widgets::stringFromColor(p->color, p->show_alpha)); 132 | Q_EMIT showAlphaChanged(p->show_alpha); 133 | } 134 | } 135 | 136 | bool ColorLineEdit::showAlpha() const 137 | { 138 | return p->show_alpha; 139 | } 140 | 141 | void ColorLineEdit::dragEnterEvent(QDragEnterEvent *event) 142 | { 143 | if ( isReadOnly() ) 144 | return; 145 | 146 | if ( event->mimeData()->hasColor() || 147 | ( event->mimeData()->hasText() && 148 | color_widgets::colorFromString(event->mimeData()->text(), p->show_alpha).isValid() ) ) 149 | { 150 | event->acceptProposedAction(); 151 | } 152 | } 153 | 154 | 155 | void ColorLineEdit::dropEvent(QDropEvent *event) 156 | { 157 | if ( isReadOnly() ) 158 | return; 159 | 160 | if ( event->mimeData()->hasColor() ) 161 | { 162 | setColor(event->mimeData()->colorData().value()); 163 | event->accept(); 164 | } 165 | else if ( event->mimeData()->hasText() ) 166 | { 167 | QColor col = color_widgets::colorFromString(event->mimeData()->text(), p->show_alpha); 168 | if ( col.isValid() ) 169 | { 170 | setColor(col); 171 | event->accept(); 172 | } 173 | } 174 | } 175 | 176 | bool ColorLineEdit::previewColor() const 177 | { 178 | return p->preview_color; 179 | } 180 | 181 | void ColorLineEdit::setPreviewColor(bool previewColor) 182 | { 183 | if ( previewColor != p->preview_color ) 184 | { 185 | p->preview_color = previewColor; 186 | 187 | if ( p->preview_color ) 188 | p->setPalette(p->color, this); 189 | else 190 | setPalette(QApplication::palette()); 191 | 192 | Q_EMIT previewColorChanged(p->preview_color); 193 | } 194 | } 195 | 196 | void ColorLineEdit::paintEvent(QPaintEvent* event) 197 | { 198 | if ( p->customAlpha() ) 199 | { 200 | QPainter painter(this); 201 | QStyleOptionFrame panel; 202 | initStyleOption(&panel); 203 | QRect r = style()->subElementRect(QStyle::SE_LineEditContents, &panel, nullptr); 204 | painter.fillRect(r, p->background); 205 | painter.fillRect(r, p->color); 206 | } 207 | 208 | QLineEdit::paintEvent(event); 209 | } 210 | 211 | } // namespace color_widgets 212 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/src/QtColorWidgets/color_palette_widget.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | color_widgets::ColorPaletteWidget 4 | 5 | 6 | 7 | 0 8 | 0 9 | 227 10 | 186 11 | 12 | 13 | 14 | 15 | 0 16 | 17 | 18 | 0 19 | 20 | 21 | 0 22 | 23 | 24 | 0 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 0 33 | 0 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 0 43 | 44 | 45 | 0 46 | 47 | 48 | 0 49 | 50 | 51 | 0 52 | 53 | 54 | 0 55 | 56 | 57 | 58 | 59 | Open a new palette from file 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | Create a new palette 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | Duplicate the current palette 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 0 105 | 106 | 107 | 0 108 | 109 | 110 | 0 111 | 112 | 113 | 0 114 | 115 | 116 | 0 117 | 118 | 119 | 120 | 121 | Delete the current palette 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | Revert changes to the current palette 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | Save changes to the current palette 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | Qt::Horizontal 158 | 159 | 160 | 161 | 40 162 | 20 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | Add a color to the palette 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | Remove the selected color from the palette 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | color_widgets::Swatch 199 | QWidget 200 |
QtColorWidgets/swatch.hpp
201 |
202 |
203 | 204 | 205 |
206 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/swatch.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | #ifndef COLOR_WIDGETS_SWATCH_HPP 23 | #define COLOR_WIDGETS_SWATCH_HPP 24 | 25 | #include 26 | #include 27 | #include "color_palette.hpp" 28 | 29 | namespace color_widgets { 30 | 31 | /** 32 | * \brief A widget drawing a palette 33 | */ 34 | class QCP_EXPORT Swatch : public QWidget 35 | { 36 | Q_OBJECT 37 | 38 | /** 39 | * \brief Palette shown by the widget 40 | */ 41 | Q_PROPERTY(const ColorPalette& palette READ palette WRITE setPalette NOTIFY paletteChanged) 42 | /** 43 | * \brief Currently selected color (-1 if no color is selected) 44 | */ 45 | Q_PROPERTY(int selected READ selected WRITE setSelected NOTIFY selectedChanged) 46 | 47 | /** 48 | * \brief Preferred size for a color square 49 | */ 50 | Q_PROPERTY(QSize colorSize READ colorSize WRITE setColorSize NOTIFY colorSizeChanged) 51 | 52 | Q_PROPERTY(ColorSizePolicy colorSizePolicy READ colorSizePolicy WRITE setColorSizePolicy NOTIFY colorSizePolicyChanged) 53 | 54 | /** 55 | * \brief Border around the colors 56 | */ 57 | Q_PROPERTY(QPen border READ border WRITE setBorder NOTIFY borderChanged) 58 | 59 | /** 60 | * \brief Forces the Swatch to display that many rows of colors 61 | * 62 | * If there are too few elements, the widget will display less than this 63 | * many rows. 64 | * 65 | * A value of0 means that the number of rows is automatic. 66 | * 67 | * \note Conflicts with forcedColumns 68 | */ 69 | Q_PROPERTY(int forcedRows READ forcedRows WRITE setForcedRows NOTIFY forcedRowsChanged) 70 | 71 | /** 72 | * \brief Forces the Swatch to display that many columns of colors 73 | * 74 | * If there are too few elements, the widget will display less than this 75 | * many columns. 76 | * 77 | * A value of 0 means that the number of columns is automatic. 78 | * 79 | * \note Conflicts with forcedRows 80 | */ 81 | Q_PROPERTY(int forcedColumns READ forcedColumns WRITE setForcedColumns NOTIFY forcedColumnsChanged) 82 | 83 | /** 84 | * \brief Whether the palette can be modified via user interaction 85 | * \note Even when this is \b false, it can still be altered programmatically 86 | */ 87 | Q_PROPERTY(bool readOnly READ readOnly WRITE setReadOnly NOTIFY readOnlyChanged) 88 | 89 | 90 | public: 91 | enum ColorSizePolicy 92 | { 93 | Hint, ///< The size is just a hint 94 | Minimum, ///< Can expand but not contract 95 | Fixed ///< Must be exactly as specified 96 | }; 97 | Q_ENUMS(ColorSizePolicy) 98 | 99 | Swatch(QWidget* parent = 0); 100 | ~Swatch(); 101 | 102 | QSize sizeHint() const Q_DECL_OVERRIDE; 103 | QSize minimumSizeHint() const Q_DECL_OVERRIDE; 104 | 105 | const ColorPalette& palette() const; 106 | ColorPalette& palette(); 107 | int selected() const; 108 | /** 109 | * \brief Color at the currently selected index 110 | */ 111 | QColor selectedColor() const; 112 | 113 | /** 114 | * \brief Color index at the given position within the widget 115 | * \param p Point in local coordinates 116 | * \returns -1 if the position doesn't represent any color 117 | */ 118 | int indexAt(const QPoint& p); 119 | 120 | /** 121 | * \brief Color at the given position within the widget 122 | * \param p Point in local coordinates 123 | */ 124 | QColor colorAt(const QPoint& p); 125 | 126 | QSize colorSize() const; 127 | ColorSizePolicy colorSizePolicy() const; 128 | QPen border() const; 129 | 130 | int forcedRows() const; 131 | int forcedColumns() const; 132 | 133 | bool readOnly() const; 134 | 135 | public Q_SLOTS: 136 | void setPalette(const ColorPalette& palette); 137 | void setSelected(int selected); 138 | void clearSelection(); 139 | void setColorSize(const QSize& colorSize); 140 | void setColorSizePolicy(ColorSizePolicy colorSizePolicy); 141 | void setBorder(const QPen& border); 142 | void setForcedRows(int forcedRows); 143 | void setForcedColumns(int forcedColumns); 144 | void setReadOnly(bool readOnly); 145 | /** 146 | * \brief Remove the currently seleceted color 147 | **/ 148 | void removeSelected(); 149 | 150 | Q_SIGNALS: 151 | void paletteChanged(const ColorPalette& palette); 152 | void selectedChanged(int selected); 153 | void colorSelected(const QColor& color); 154 | void colorSizeChanged(const QSize& colorSize); 155 | void colorSizePolicyChanged(ColorSizePolicy colorSizePolicy); 156 | void doubleClicked(int index); 157 | void rightClicked(int index); 158 | void forcedRowsChanged(int forcedRows); 159 | void forcedColumnsChanged(int forcedColumns); 160 | void readOnlyChanged(bool readOnly); 161 | void borderChanged(const QPen& border); 162 | 163 | protected: 164 | bool event(QEvent* event) Q_DECL_OVERRIDE; 165 | 166 | void paintEvent(QPaintEvent* event) Q_DECL_OVERRIDE; 167 | 168 | void keyPressEvent(QKeyEvent* event) Q_DECL_OVERRIDE; 169 | 170 | void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; 171 | void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; 172 | void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; 173 | void mouseDoubleClickEvent(QMouseEvent *event) Q_DECL_OVERRIDE; 174 | void wheelEvent(QWheelEvent* event) Q_DECL_OVERRIDE; 175 | 176 | void dragEnterEvent(QDragEnterEvent *event) Q_DECL_OVERRIDE; 177 | void dragMoveEvent(QDragMoveEvent* event) Q_DECL_OVERRIDE; 178 | void dragLeaveEvent(QDragLeaveEvent *event) Q_DECL_OVERRIDE; 179 | void dropEvent(QDropEvent* event) Q_DECL_OVERRIDE; 180 | 181 | protected Q_SLOTS: 182 | /** 183 | * \brief Connected to the internal palette object to keep eveything consistent 184 | */ 185 | void paletteModified(); 186 | 187 | private: 188 | class Private; 189 | Private* p; 190 | }; 191 | 192 | 193 | } // namespace color_widgets 194 | #endif // COLOR_WIDGETS_SWATCH_HPP 195 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/src/QtColorWidgets/harmony_color_wheel.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * \copyright Copyright (C) 2017 caryoscelus 8 | * 9 | * This program is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as published by 11 | * the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | #include "QtColorWidgets/color_wheel_private.hpp" 24 | #include "QtColorWidgets/harmony_color_wheel.hpp" 25 | 26 | namespace color_widgets { 27 | 28 | struct RingEditor 29 | { 30 | double hue_diff; 31 | bool editable; 32 | int symmetric_to; 33 | int opposite_to; 34 | RingEditor(double hue_diff, bool editable, int symmetric_to=-1, int opposite_to=-1) : 35 | hue_diff(hue_diff), 36 | editable(editable), 37 | symmetric_to(symmetric_to), 38 | opposite_to(opposite_to) 39 | { 40 | } 41 | }; 42 | 43 | class HarmonyColorWheel::Private : public ColorWheel::Private 44 | { 45 | public: 46 | using ColorWheel::Private::Private; 47 | 48 | std::vector ring_editors; 49 | int current_ring_editor = -1; 50 | 51 | /** 52 | * Puts a double into [0; 1) range 53 | */ 54 | static inline double normalize(double angle) 55 | { 56 | return angle - std::floor(angle); 57 | } 58 | }; 59 | 60 | 61 | HarmonyColorWheel::HarmonyColorWheel(QWidget *parent) : 62 | ColorWheel(parent, new Private(this)) 63 | { 64 | connect(this, SIGNAL(colorChanged(QColor)), this, SIGNAL(harmonyChanged())); 65 | p = static_cast(data()); 66 | } 67 | 68 | HarmonyColorWheel::~HarmonyColorWheel() = default; 69 | 70 | QList HarmonyColorWheel::harmonyColors() const 71 | { 72 | QList result; 73 | result.push_back(color()); 74 | for (auto const& harmony : p->ring_editors) 75 | { 76 | auto hue = Private::normalize(p->hue+harmony.hue_diff); 77 | result.push_back(p->color_from(hue, p->sat, p->val, 1)); 78 | } 79 | return result; 80 | } 81 | 82 | unsigned int HarmonyColorWheel::harmonyCount() const 83 | { 84 | return 1 + p->ring_editors.size(); 85 | } 86 | 87 | void HarmonyColorWheel::clearHarmonies() 88 | { 89 | p->ring_editors.clear(); 90 | p->current_ring_editor = -1; 91 | Q_EMIT harmonyChanged(); 92 | update(); 93 | } 94 | 95 | unsigned HarmonyColorWheel::addHarmony(double hue_diff, bool editable) 96 | { 97 | auto count = p->ring_editors.size(); 98 | p->ring_editors.emplace_back(Private::normalize(hue_diff), editable, -1, -1); 99 | Q_EMIT harmonyChanged(); 100 | update(); 101 | return count; 102 | } 103 | 104 | unsigned HarmonyColorWheel::addSymmetricHarmony(unsigned relative_to) 105 | { 106 | auto count = p->ring_editors.size(); 107 | if (relative_to >= count) 108 | throw std::out_of_range("incorrect call to addSymmetricHarmony: harmony number out of range"); 109 | auto& relative = p->ring_editors[relative_to]; 110 | relative.symmetric_to = count; 111 | p->ring_editors.emplace_back(Private::normalize(-relative.hue_diff), relative.editable, relative_to, -1); 112 | Q_EMIT harmonyChanged(); 113 | update(); 114 | return count; 115 | } 116 | 117 | unsigned HarmonyColorWheel::addOppositeHarmony(unsigned relative_to) 118 | { 119 | auto count = p->ring_editors.size(); 120 | if (relative_to >= count) 121 | throw std::out_of_range("incorrect call to addOppositeHarmony: harmony number out of range"); 122 | auto& relative = p->ring_editors[relative_to]; 123 | relative.opposite_to = count; 124 | p->ring_editors.emplace_back(Private::normalize(0.5+relative.hue_diff), relative.editable, -1, relative_to); 125 | Q_EMIT harmonyChanged(); 126 | update(); 127 | return count; 128 | } 129 | 130 | void HarmonyColorWheel::paintEvent(QPaintEvent * ev) 131 | { 132 | ColorWheel::paintEvent(ev); 133 | 134 | QPainter painter(this); 135 | painter.setRenderHint(QPainter::Antialiasing); 136 | painter.translate(geometry().width()/2,geometry().height()/2); 137 | 138 | for (auto const& editor : p->ring_editors) 139 | { 140 | auto hue = p->hue+editor.hue_diff; 141 | // TODO: better color for uneditable indicator 142 | auto color = editor.editable ? Qt::white : Qt::gray; 143 | p->draw_ring_editor(hue, painter, color); 144 | } 145 | } 146 | 147 | 148 | void HarmonyColorWheel::mousePressEvent(QMouseEvent *ev) 149 | { 150 | if ( ev->buttons() & Qt::LeftButton ) 151 | { 152 | QLineF ray = p->line_to_point(ev->pos()); 153 | if ( ray.length() <= p->outer_radius() && ray.length() > p->inner_radius() ) 154 | { 155 | p->mouse_status = DragCircle; 156 | auto hue_diff = Private::normalize(ray.angle()/360 - p->hue); 157 | auto i = 0; 158 | for (auto const& editor : p->ring_editors) 159 | { 160 | const double eps = 1.0/64; 161 | if (editor.editable && 162 | editor.hue_diff <= hue_diff + eps && 163 | editor.hue_diff >= hue_diff - eps) 164 | { 165 | p->current_ring_editor = i; 166 | // no need to update color.. 167 | return; 168 | } 169 | ++i; 170 | } 171 | } 172 | } 173 | ColorWheel::mousePressEvent(ev); 174 | } 175 | 176 | 177 | void HarmonyColorWheel::mouseMoveEvent(QMouseEvent *ev) 178 | { 179 | if ( p->mouse_status == DragCircle && p->current_ring_editor != -1 ) 180 | { 181 | auto hue = p->line_to_point(ev->pos()).angle()/360.0; 182 | auto& editor = p->ring_editors[p->current_ring_editor]; 183 | editor.hue_diff = Private::normalize(hue - p->hue); 184 | if (editor.symmetric_to != -1) 185 | { 186 | auto& symmetric = p->ring_editors[editor.symmetric_to]; 187 | symmetric.hue_diff = Private::normalize(p->hue - hue); 188 | } 189 | else if (editor.opposite_to != -1) 190 | { 191 | auto& opposite = p->ring_editors[editor.opposite_to]; 192 | opposite.hue_diff = Private::normalize(editor.hue_diff-0.5); 193 | } 194 | Q_EMIT harmonyChanged(); 195 | update(); 196 | return; 197 | } 198 | ColorWheel::mouseMoveEvent(ev); 199 | } 200 | 201 | void HarmonyColorWheel::mouseReleaseEvent(QMouseEvent *ev) 202 | { 203 | ColorWheel::mouseReleaseEvent(ev); 204 | p->current_ring_editor = -1; 205 | } 206 | 207 | } // namespace color_widgets 208 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/color_palette_widget.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | #ifndef COLOR_WIDGETS_COLOR_PALETTE_WIDGET_HPP 23 | #define COLOR_WIDGETS_COLOR_PALETTE_WIDGET_HPP 24 | 25 | #include 26 | #include 27 | #include "color_palette_model.hpp" 28 | #include "swatch.hpp" 29 | 30 | namespace color_widgets { 31 | 32 | /** 33 | * \brief A widget to use and modify palettes 34 | */ 35 | class QCP_EXPORT ColorPaletteWidget : public QWidget 36 | { 37 | Q_OBJECT 38 | 39 | /** 40 | * \brief Model used to store the palettes 41 | */ 42 | Q_PROPERTY(ColorPaletteModel* model READ model WRITE setModel NOTIFY modelChanged) 43 | 44 | /** 45 | * \brief Size of a single color in the swatch widget 46 | */ 47 | Q_PROPERTY(QSize colorSize READ colorSize WRITE setColorSize NOTIFY colorSizeChanged) 48 | /** 49 | * \brief Policy for colorSize 50 | **/ 51 | Q_PROPERTY(color_widgets::Swatch::ColorSizePolicy colorSizePolicy READ colorSizePolicy WRITE setColorSizePolicy NOTIFY colorSizePolicyChanged) 52 | 53 | /** 54 | * \brief Border around the colors 55 | */ 56 | Q_PROPERTY(QPen border READ border WRITE setBorder NOTIFY borderChanged) 57 | 58 | /** 59 | * \brief Forces the Swatch to display that many rows of colors 60 | * 61 | * If there are too few elements, the widget will display less than this 62 | * many rows. 63 | * 64 | * A value of0 means that the number of rows is automatic. 65 | * 66 | * \note Conflicts with forcedColumns 67 | */ 68 | Q_PROPERTY(int forcedRows READ forcedRows WRITE setForcedRows NOTIFY forcedRowsChanged) 69 | 70 | /** 71 | * \brief Forces the Swatch to display that many columns of colors 72 | * 73 | * If there are too few elements, the widget will display less than this 74 | * many columns. 75 | * 76 | * A value of 0 means that the number of columns is automatic. 77 | * 78 | * \note Conflicts with forcedRows 79 | */ 80 | Q_PROPERTY(int forcedColumns READ forcedColumns WRITE setForcedColumns NOTIFY forcedColumnsChanged) 81 | 82 | /** 83 | * \brief Whether the palettes can be modified via user interaction 84 | */ 85 | Q_PROPERTY(bool readOnly READ readOnly WRITE setReadOnly NOTIFY readOnlyChanged) 86 | 87 | /** 88 | * \brief Currently selected color 89 | */ 90 | Q_PROPERTY(QColor currentColor READ currentColor WRITE setCurrentColor NOTIFY currentColorChanged) 91 | 92 | /** 93 | * \brief Currently selected model row 94 | */ 95 | Q_PROPERTY(int currentRow READ currentRow WRITE setCurrentRow NOTIFY currentRowChanged) 96 | 97 | /** 98 | * \brief Palette shown by the widget 99 | */ 100 | Q_PROPERTY(const ColorPalette& currentPalette READ currentPalette NOTIFY currentPaletteChanged) 101 | 102 | /** 103 | * \brief If a valid color, it's used when adding new colors to palettes 104 | */ 105 | Q_PROPERTY(QColor defaultColor READ defaultColor WRITE setDefaultColor NOTIFY defaultColorChanged) 106 | 107 | public: 108 | ColorPaletteWidget(QWidget* parent = nullptr); 109 | ~ColorPaletteWidget(); 110 | 111 | ColorPaletteModel* model() const; 112 | 113 | /** 114 | * \brief Currently selected palette 115 | * \pre model() != nullptr and there is a selected palette 116 | */ 117 | const ColorPalette& currentPalette() const; 118 | 119 | QSize colorSize() const; 120 | Swatch::ColorSizePolicy colorSizePolicy() const; 121 | QPen border() const; 122 | 123 | int forcedRows() const; 124 | int forcedColumns() const; 125 | 126 | bool readOnly() const; 127 | QColor currentColor() const; 128 | 129 | int currentRow() const; 130 | 131 | /** 132 | * \brief Default color when adding a color to the current palette 133 | */ 134 | QColor defaultColor() const; 135 | 136 | public Q_SLOTS: 137 | void setModel(ColorPaletteModel* model); 138 | void setColorSize(const QSize& colorSize); 139 | void setColorSizePolicy(Swatch::ColorSizePolicy colorSizePolicy); 140 | void setBorder(const QPen& border); 141 | void setForcedRows(int forcedRows); 142 | void setForcedColumns(int forcedColumns); 143 | void setReadOnly(bool readOnly); 144 | /** 145 | * \brief Clear the selected color 146 | */ 147 | void clearCurrentColor(); 148 | /** 149 | * \brief Attempt to select a color 150 | * 151 | * If the given color is available in the current palete, it will be selected 152 | * \return \b true on success 153 | */ 154 | bool setCurrentColor(const QColor& color); 155 | /** 156 | * \brief Attempt to select a color by name 157 | * 158 | * If the given color is available in the current palete, it will be selected 159 | * \return \b true on success 160 | */ 161 | bool setCurrentColor(const QString& name); 162 | /** 163 | * \brief Attempt to select a color by index 164 | * 165 | * If the given color is available in the current palete, it will be selected 166 | * \return \b true on success 167 | */ 168 | bool setCurrentColor(int index); 169 | /** 170 | * \brief Set the selected row in the model 171 | */ 172 | void setCurrentRow(int currentRow); 173 | 174 | /** 175 | * \brief Sets the default for new colors 176 | * If invalid, it will show a dialog 177 | */ 178 | void setDefaultColor(const QColor& color); 179 | 180 | Q_SIGNALS: 181 | void modelChanged(ColorPaletteModel* model); 182 | void colorSizeChanged(const QSize& colorSize); 183 | void colorSizePolicyChanged(Swatch::ColorSizePolicy colorSizePolicy); 184 | void forcedRowsChanged(int forcedRows); 185 | void forcedColumnsChanged(int forcedColumns); 186 | void readOnlyChanged(bool readOnly); 187 | void currentColorChanged(const QColor& currentColor); 188 | void currentColorChanged(int index); 189 | void borderChanged(const QPen& border); 190 | void currentRowChanged(int currentRow); 191 | void currentPaletteChanged(const ColorPalette& palette); 192 | void defaultColorChanged(const QColor& color); 193 | 194 | private Q_SLOTS: 195 | void on_palette_list_currentIndexChanged(int index); 196 | void on_swatch_doubleClicked(int index); 197 | 198 | private: 199 | class Private; 200 | std::unique_ptr p; 201 | }; 202 | 203 | } // namespace color_widgets 204 | #endif // COLOR_WIDGETS_COLOR_PALETTE_WIDGET_HPP 205 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/src/QtColorWidgets/color_2d_slider.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | #include "QtColorWidgets/color_2d_slider.hpp" 23 | #include "QtColorWidgets/color_utils.hpp" 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | namespace color_widgets { 30 | 31 | static const double selector_radius = 6; 32 | 33 | class Color2DSlider::Private 34 | { 35 | public: 36 | qreal hue = 1, sat = 1, val = 1; 37 | Component comp_x = Saturation; 38 | Component comp_y = Value; 39 | QImage square; 40 | 41 | qreal PixHue(float x, float y) 42 | { 43 | if ( comp_x == Hue ) 44 | return x; 45 | if ( comp_y == Hue ) 46 | return y; 47 | return hue; 48 | } 49 | 50 | qreal PixSat(float x, float y) 51 | { 52 | if ( comp_x == Saturation ) 53 | return x; 54 | if ( comp_y == Saturation ) 55 | return y; 56 | return sat; 57 | } 58 | 59 | qreal PixVal(float x, float y) 60 | { 61 | if ( comp_x == Value ) 62 | return x; 63 | if ( comp_y == Value ) 64 | return y; 65 | return val; 66 | } 67 | 68 | void renderSquare(const QSize& size) 69 | { 70 | square = QImage(size, QImage::Format_RGB32); 71 | 72 | for ( int y = 0; y < size.height(); ++y ) 73 | { 74 | qreal yfloat = 1 - qreal(y) / size.height(); 75 | for ( int x = 0; x < size.width(); ++x ) 76 | { 77 | qreal xfloat = qreal(x) / size.width(); 78 | square.setPixel( x, y, QColor::fromHsvF( 79 | PixHue(xfloat, yfloat), 80 | PixSat(xfloat, yfloat), 81 | PixVal(xfloat, yfloat) 82 | ).rgb()); 83 | } 84 | } 85 | } 86 | 87 | QPointF selectorPos(const QSize& size) 88 | { 89 | QPointF pt; 90 | switch ( comp_x ) 91 | { 92 | case Hue: pt.setX(size.width()*hue); break; 93 | case Saturation:pt.setX(size.width()*sat); break; 94 | case Value: pt.setX(size.width()*val); break; 95 | } 96 | switch ( comp_y ) 97 | { 98 | case Hue: pt.setY(size.height()*(1-hue)); break; 99 | case Saturation:pt.setY(size.height()*(1-sat)); break; 100 | case Value: pt.setY(size.height()*(1-val)); break; 101 | } 102 | return pt; 103 | } 104 | 105 | void setColorFromPos(const QPoint& pt, const QSize& size) 106 | { 107 | QPointF ptfloat( 108 | qBound(0.0, qreal(pt.x()) / size.width(), 1.0), 109 | qBound(0.0, 1 - qreal(pt.y()) / size.height(), 1.0) 110 | ); 111 | switch ( comp_x ) 112 | { 113 | case Hue: hue = ptfloat.x(); break; 114 | case Saturation:sat = ptfloat.x(); break; 115 | case Value: val = ptfloat.x(); break; 116 | } 117 | switch ( comp_y ) 118 | { 119 | case Hue: hue = ptfloat.y(); break; 120 | case Saturation:sat = ptfloat.y(); break; 121 | case Value: val = ptfloat.y(); break; 122 | } 123 | } 124 | }; 125 | 126 | Color2DSlider::Color2DSlider(QWidget* parent) 127 | : QWidget(parent), p(new Private) 128 | { 129 | setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 130 | } 131 | 132 | Color2DSlider::~Color2DSlider() 133 | { 134 | delete p; 135 | } 136 | 137 | QColor Color2DSlider::color() const 138 | { 139 | return QColor::fromHsvF(p->hue, p->sat, p->val); 140 | } 141 | 142 | QSize Color2DSlider::sizeHint() const 143 | { 144 | return {128, 128}; 145 | } 146 | 147 | qreal Color2DSlider::hue() const 148 | { 149 | return p->hue; 150 | } 151 | 152 | qreal Color2DSlider::saturation() const 153 | { 154 | return p->sat; 155 | } 156 | 157 | qreal Color2DSlider::value() const 158 | { 159 | return p->val; 160 | } 161 | 162 | Color2DSlider::Component Color2DSlider::componentX() const 163 | { 164 | return p->comp_x; 165 | } 166 | 167 | Color2DSlider::Component Color2DSlider::componentY() const 168 | { 169 | return p->comp_y; 170 | } 171 | 172 | void Color2DSlider::setColor(const QColor& c) 173 | { 174 | p->hue = c.hsvHueF(); 175 | p->sat = c.saturationF(); 176 | p->val = c.valueF(); 177 | p->renderSquare(size()); 178 | update(); 179 | Q_EMIT colorChanged(color()); 180 | } 181 | 182 | void Color2DSlider::setHue(qreal h) 183 | { 184 | p->hue = h; 185 | p->renderSquare(size()); 186 | update(); 187 | Q_EMIT colorChanged(color()); 188 | } 189 | 190 | void Color2DSlider::setSaturation(qreal s) 191 | { 192 | p->sat = s; 193 | p->renderSquare(size()); 194 | update(); 195 | Q_EMIT colorChanged(color()); 196 | } 197 | 198 | void Color2DSlider::setValue(qreal v) 199 | { 200 | p->val = v; 201 | p->renderSquare(size()); 202 | update(); 203 | Q_EMIT colorChanged(color()); 204 | } 205 | 206 | void Color2DSlider::setComponentX(Color2DSlider::Component componentX) 207 | { 208 | if ( componentX != p->comp_x ) 209 | { 210 | p->comp_x = componentX; 211 | p->renderSquare(size()); 212 | update(); 213 | Q_EMIT componentXChanged(p->comp_x); 214 | } 215 | } 216 | 217 | void Color2DSlider::setComponentY(Color2DSlider::Component componentY) 218 | { 219 | if ( componentY != p->comp_y ) 220 | { 221 | p->comp_y = componentY; 222 | p->renderSquare(size()); 223 | update(); 224 | Q_EMIT componentXChanged(p->comp_y); 225 | } 226 | } 227 | 228 | void Color2DSlider::paintEvent(QPaintEvent*) 229 | { 230 | QPainter painter(this); 231 | painter.setRenderHint(QPainter::Antialiasing); 232 | painter.drawImage(0,0,p->square); 233 | 234 | painter.setPen(QPen(p->val > 0.5 ? Qt::black : Qt::white, 3)); 235 | painter.setBrush(Qt::NoBrush); 236 | painter.drawEllipse(p->selectorPos(size()), selector_radius, selector_radius); 237 | } 238 | 239 | void Color2DSlider::mousePressEvent(QMouseEvent* event) 240 | { 241 | p->setColorFromPos(event->pos(), size()); 242 | Q_EMIT colorChanged(color()); 243 | update(); 244 | } 245 | 246 | void Color2DSlider::mouseMoveEvent(QMouseEvent* event) 247 | { 248 | p->setColorFromPos(event->pos(), size()); 249 | Q_EMIT colorChanged(color()); 250 | update(); 251 | } 252 | 253 | void Color2DSlider::mouseReleaseEvent(QMouseEvent* event) 254 | { 255 | p->setColorFromPos(event->pos(), size()); 256 | Q_EMIT colorChanged(color()); 257 | update(); 258 | } 259 | 260 | void Color2DSlider::resizeEvent(QResizeEvent* event) 261 | { 262 | p->renderSquare(event->size()); 263 | update(); 264 | } 265 | 266 | 267 | } // namespace color_widgets 268 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/include/QtColorWidgets/color_palette.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | #ifndef COLOR_WIDGETS_COLOR_PALETTE_HPP 23 | #define COLOR_WIDGETS_COLOR_PALETTE_HPP 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "colorwidgets_global.hpp" 32 | 33 | namespace color_widgets { 34 | 35 | class QCP_EXPORT ColorPalette : public QObject 36 | { 37 | Q_OBJECT 38 | 39 | /** 40 | * \brief The list of colors 41 | */ 42 | Q_PROPERTY(QVector colors READ colors WRITE setColors NOTIFY colorsChanged) 43 | /** 44 | * \brief Name of the palette 45 | */ 46 | Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) 47 | /** 48 | * \brief Number of colors to display in a row, if 0 unspecified 49 | */ 50 | Q_PROPERTY(int columns READ columns WRITE setColumns NOTIFY columnsChanged) 51 | /** 52 | * \brief Number of colors 53 | */ 54 | Q_PROPERTY(int count READ count) 55 | /** 56 | * \brief Name of the file the palette has been read from 57 | */ 58 | Q_PROPERTY(QString fileName READ fileName WRITE setFileName NOTIFY fileNameChanged) 59 | /** 60 | * \brief Whether it has been modified and it might be advisable to save it 61 | */ 62 | Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged) 63 | 64 | public: 65 | typedef QPair value_type; 66 | 67 | ColorPalette(const QVector& colors, const QString& name = QString(), int columns = 0); 68 | ColorPalette(const QVector >& colors, const QString& name = QString(), int columns = 0); 69 | explicit ColorPalette(const QString& name = QString()); 70 | ColorPalette(const ColorPalette& other); 71 | ColorPalette& operator=(const ColorPalette& other); 72 | ~ColorPalette(); 73 | ColorPalette(ColorPalette&& other); 74 | ColorPalette& operator=(ColorPalette&& other); 75 | 76 | /** 77 | * \brief Color at the given index 78 | */ 79 | Q_INVOKABLE QColor colorAt(int index) const; 80 | 81 | /** 82 | * \brief Color name at the given index 83 | */ 84 | Q_INVOKABLE QString nameAt(int index) const; 85 | 86 | QVector > colors() const; 87 | QVector onlyColors() const; 88 | 89 | int count() const; 90 | int columns(); 91 | 92 | QString name() const; 93 | 94 | /** 95 | * \brief Use a color table to set the colors 96 | */ 97 | Q_INVOKABLE void loadColorTable(const QVector& color_table); 98 | 99 | /** 100 | * \brief Convert to a color table 101 | */ 102 | Q_INVOKABLE QVector colorTable() const; 103 | 104 | /** 105 | * \brief Creates a ColorPalette from a color table 106 | */ 107 | static ColorPalette fromColorTable(const QVector& table); 108 | 109 | /** 110 | * \brief Use the pixels on an image to set the palette colors 111 | */ 112 | Q_INVOKABLE bool loadImage(const QImage& image); 113 | 114 | /** 115 | * \brief Creates a ColorPalette from a Gimp palette (gpl) file 116 | */ 117 | static ColorPalette fromImage(const QImage& image); 118 | 119 | /** 120 | * \brief Load contents from a Gimp palette (gpl) file 121 | * \returns \b true On Success 122 | * \note If this function returns \b false, the palette will become empty 123 | */ 124 | Q_INVOKABLE bool load(const QString& name); 125 | 126 | /** 127 | * \brief Creates a ColorPalette from a Gimp palette (gpl) file 128 | */ 129 | static ColorPalette fromFile(const QString& name); 130 | 131 | QString fileName() const; 132 | 133 | bool dirty() const; 134 | 135 | /** 136 | * \brief Returns a preview image of the colors in the palette 137 | */ 138 | QPixmap preview(const QSize& size, const QColor& background=Qt::transparent) const; 139 | 140 | public Q_SLOTS: 141 | void setColumns(int columns); 142 | 143 | void setColors(const QVector& colors); 144 | void setColors(const QVector >& colors); 145 | 146 | /** 147 | * \brief Change the color at the given index 148 | */ 149 | void setColorAt(int index, const QColor& color); 150 | /** 151 | * \brief Change the color at the given index 152 | */ 153 | void setColorAt(int index, const QColor& color, const QString& name); 154 | /** 155 | * \brief Change the name of a color 156 | */ 157 | void setNameAt(int index, const QString& name = QString()); 158 | /** 159 | * \brief Append a color at the end 160 | */ 161 | void appendColor(const QColor& color, const QString& name = QString()); 162 | /** 163 | * \brief Insert a color in an arbitrary location 164 | */ 165 | void insertColor(int index, const QColor& color, const QString& name = QString()); 166 | /** 167 | * \brief Remove the color at the given index 168 | */ 169 | void eraseColor(int index); 170 | 171 | /** 172 | * \brief Change file name and save 173 | * \returns \b true on success 174 | */ 175 | bool save(const QString& filename); 176 | /** 177 | * \brief save to file, the filename is \c fileName or determined automatically 178 | * \returns \b true on success 179 | */ 180 | bool save(); 181 | 182 | void setName(const QString& name); 183 | void setFileName(const QString& name); 184 | void setDirty(bool dirty); 185 | 186 | Q_SIGNALS: 187 | /** 188 | * \brief Emitted when all the colors have changed 189 | */ 190 | void colorsChanged(const QVector >&); 191 | void columnsChanged(int); 192 | void nameChanged(const QString&); 193 | void fileNameChanged(const QString&); 194 | void dirtyChanged(bool); 195 | /** 196 | * \brief Emitted when the color or the name at the given index has been modified 197 | */ 198 | void colorChanged(int index); 199 | /** 200 | * \brief Emitted when the color at the given index has been removed 201 | */ 202 | void colorRemoved(int index); 203 | /** 204 | * \brief Emitted when a single color has been added 205 | */ 206 | void colorAdded(int index); 207 | /** 208 | * \brief Emitted when the colors have been modified with a simple operation (set, append etc.) 209 | */ 210 | void colorsUpdated(const QVector>&); 211 | 212 | private: 213 | /** 214 | * \brief Returns \c name if it isn't null, otherwise a default value 215 | */ 216 | QString unnamed(const QString& name = QString()) const; 217 | 218 | /** 219 | * \brief Emit all the necessary signals when the palette has been completely overwritten 220 | */ 221 | void emitUpdate(); 222 | 223 | class Private; 224 | Private *p; 225 | }; 226 | 227 | } // namespace color_widgets 228 | 229 | #endif // COLOR_WIDGETS_COLOR_PALETTE_HPP 230 | -------------------------------------------------------------------------------- /utility.cpp: -------------------------------------------------------------------------------- 1 | #include "utility.h" 2 | #include 3 | #include 4 | 5 | // utility usually used 6 | // 4d poly cutting 7 | // hsv rgb converting 8 | // vector operations 9 | 10 | bool cut(double time, vec4 p, vec4 q, double &r, double &g, double &b) 11 | { 12 | if(p[3] > q[3]) { vec4 tmp = p; p = q; q = tmp; } 13 | 14 | if(p[3] < time + 1e-6 && time < q[3] + 1e-6) 15 | { 16 | double wp = q[3] - time; 17 | double wq = time - p[3]; 18 | 19 | r = (p[0] * wp + q[0] * wq) / (wp + wq); 20 | g = (p[1] * wp + q[1] * wq) / (wp + wq); 21 | b = (p[2] * wp + q[2] * wq) / (wp + wq); 22 | return true; 23 | } 24 | else 25 | { 26 | return false; 27 | } 28 | } 29 | 30 | 31 | void RGBtoHSV(double src_r, double src_g, double src_b, 32 | double &dst_h, double &dst_s, double &dst_v) 33 | { 34 | float r = src_r; 35 | float g = src_g; 36 | float b = src_b; 37 | 38 | float h, s, v; // h:0-360.0, s:0.0-1.0, v:0.0-1.0 39 | 40 | float max = 0; // std::max(std::max(r, g), b); 41 | float min = 0; // std::max(std::max(r, g), b); 42 | 43 | if(r > max) max = r; 44 | if(g > max) max = g; 45 | if(b > max) max = b; 46 | if(r < min) min = r; 47 | if(g < min) min = g; 48 | if(b < min) min = b; 49 | 50 | v = max; 51 | 52 | if (max == 0.0f) { 53 | s = 0; 54 | h = 0; 55 | } 56 | else if (max - min == 0.0f) { 57 | s = 0; 58 | h = 0; 59 | } 60 | else { 61 | s = (max - min) / max; 62 | 63 | if (max == r) { 64 | h = 60 * ((g - b) / (max - min)) + 0; 65 | } 66 | else if (max == g) { 67 | h = 60 * ((b - r) / (max - min)) + 120; 68 | } 69 | else { 70 | h = 60 * ((r - g) / (max - min)) + 240; 71 | } 72 | } 73 | 74 | if (h < 0) h += 360.0f; 75 | 76 | dst_h = (h); // dst_h : 0-360 77 | dst_s = (s); // dst_s : 0-255 78 | dst_v = (v); // dst_v : 0-255 79 | } 80 | 81 | void cross(double x1, double y1, double z1, double x2, double y2, double z2, double &x, double &y, double &z) 82 | { 83 | x = y1 * z2 - z1 * y2; 84 | y = z1 * x2 - x1 * z2; 85 | z = x1 * y2 - y1 * x2; 86 | } 87 | 88 | double norm2(double x, double y, double z) 89 | { 90 | return x * x + y * y + z * z; 91 | } 92 | 93 | double angle(double x1, double y1, double z1, double x2, double y2, double z2) 94 | { 95 | double norm2_1 = norm2(x1, y1, z1); 96 | double norm2_2 = norm2(x2, y2, z2); 97 | 98 | if(norm2_1 < 1e-6 || norm2_2 < 1e-6) return 0; 99 | 100 | double c = (x1 * x2 + y1 * y2 + z1 * z2) / mysqrt(norm2_1 * norm2_2); 101 | if(c > 1) c = 1; 102 | if(c < -1) c = -1; 103 | return myacos(c); 104 | 105 | } 106 | 107 | double dot(double x1, double y1, double z1, double x2, double y2, double z2) 108 | { 109 | return x1 * x2 + y1 * y2 + z1 * z2; 110 | } 111 | 112 | myfloat3::myfloat3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) 113 | { 114 | } 115 | 116 | myfloat3::myfloat3() : x(0.f), y(0.f), z(0.f) 117 | { 118 | } 119 | 120 | const float myfloat3::norm2() const 121 | { 122 | return x * x + y * y + z * z; 123 | } 124 | 125 | const float myfloat3::norm() const 126 | { 127 | float ans = x * x + y * y + z * z; 128 | if(ans < 0) ans = 0; 129 | return sqrtf(ans); 130 | } 131 | 132 | float myfloat3::dot(myfloat3 another) 133 | { 134 | return x * another.x + y * another.y + z * another.z; 135 | } 136 | 137 | myfloat3 myfloat3::cross(myfloat3 another) 138 | { 139 | const float &x_ = another.x; 140 | const float &y_ = another.y; 141 | const float &z_ = another.z; 142 | 143 | return myfloat3( 144 | y * z_ - z * y_, 145 | z * x_ - x * z_, 146 | x * y_ - y * x_ 147 | ); 148 | } 149 | 150 | const myfloat3 myfloat3::operator +(const myfloat3 another) const 151 | { 152 | const float &x_ = another.x; 153 | const float &y_ = another.y; 154 | const float &z_ = another.z; 155 | 156 | return myfloat3(x + x_, y + y_, z + z_); 157 | } 158 | 159 | const myfloat3 myfloat3::operator -(const myfloat3 another) const 160 | { 161 | const float &x_ = another.x; 162 | const float &y_ = another.y; 163 | const float &z_ = another.z; 164 | 165 | return myfloat3(x - x_, y - y_, z - z_); 166 | } 167 | 168 | const myfloat3 myfloat3::operator *(float k) const 169 | { 170 | return myfloat3(x * k, y * k, z * k); 171 | } 172 | 173 | const myfloat3 myfloat3::operator /(float k) const 174 | { 175 | k = 1.f / k; 176 | return myfloat3(x * k, y * k, z * k); 177 | } 178 | 179 | float myfloat3::getX() const 180 | { 181 | return x; 182 | } 183 | 184 | float myfloat3::getY() const 185 | { 186 | return y; 187 | } 188 | 189 | float myfloat3::getZ() const 190 | { 191 | return z; 192 | } 193 | 194 | float dot(myfloat3 x, myfloat3 y) 195 | { 196 | return x.dot(y); 197 | } 198 | 199 | myfloat3 cross(myfloat3 x, myfloat3 y) 200 | { 201 | return x.cross(y); 202 | } 203 | 204 | QDebug operator<<(QDebug debug, const myfloat3 &c) 205 | { 206 | QDebugStateSaver saver(debug); 207 | debug.nospace() << '(' << c.getX() << ", " << c.getY() << ", " << c.getZ() << ')'; 208 | 209 | return debug; 210 | } 211 | 212 | 213 | //Yili Wang's code 214 | vec3 closesPointOnTriangle(const vec3 *triangle, const vec3 &sourcePosition) 215 | { 216 | vec3 edge0 = triangle[1] - triangle[0]; 217 | vec3 edge1 = triangle[2] - triangle[0]; 218 | vec3 v0 = triangle[0] - sourcePosition; 219 | 220 | float a = dot(edge0, edge0); 221 | float b = dot(edge0, edge1); 222 | float c = dot(edge1, edge1); 223 | float d = dot(edge0, v0); 224 | float e = dot(edge1, v0); 225 | 226 | float det = a*c - b*b; 227 | float s = b*e - c*d; 228 | float t = b*d - a*e; 229 | 230 | if (s + t < det) 231 | { 232 | if (s < 0.f) 233 | { 234 | if (t < 0.f) 235 | { 236 | if (d < 0.f) 237 | { 238 | s = my_util::clamp(-d / a, 0.f, 1.f); 239 | t = 0.f; 240 | } 241 | else 242 | { 243 | s = 0.f; 244 | t = my_util::clamp(-e / c, 0.f, 1.f); 245 | } 246 | } 247 | else 248 | { 249 | s = 0.f; 250 | t = my_util::clamp(-e / c, 0.f, 1.f); 251 | } 252 | } 253 | else if (t < 0.f) 254 | { 255 | s = my_util::clamp(-d / a, 0.f, 1.f); 256 | t = 0.f; 257 | } 258 | else 259 | { 260 | float invDet = 1.f / det; 261 | s *= invDet; 262 | t *= invDet; 263 | } 264 | } 265 | else 266 | { 267 | if (s < 0.f) 268 | { 269 | float tmp0 = b + d; 270 | float tmp1 = c + e; 271 | if (tmp1 > tmp0) 272 | { 273 | float numer = tmp1 - tmp0; 274 | float denom = a - 2 * b + c; 275 | s = my_util::clamp(numer / denom, 0.f, 1.f); 276 | t = 1 - s; 277 | } 278 | else 279 | { 280 | t = my_util::clamp(-e / c, 0.f, 1.f); 281 | s = 0.f; 282 | } 283 | } 284 | else if (t < 0.f) 285 | { 286 | if (a + d > b + e) 287 | { 288 | float numer = c + e - b - d; 289 | float denom = a - 2 * b + c; 290 | s = my_util::clamp(numer / denom, 0.f, 1.f); 291 | t = 1 - s; 292 | } 293 | else 294 | { 295 | s = my_util::clamp(-e / c, 0.f, 1.f); 296 | t = 0.f; 297 | } 298 | } 299 | else 300 | { 301 | float numer = c + e - b - d; 302 | float denom = a - 2 * b + c; 303 | s = my_util::clamp(numer / denom, 0.f, 1.f); 304 | t = 1.f - s; 305 | } 306 | } 307 | 308 | return triangle[0] + s * edge0 + t * edge1; 309 | } 310 | 311 | float myasin(float x) 312 | { 313 | if(x > 1) x = 1; 314 | if(x < -1) x = -1; 315 | return asin(x); 316 | } 317 | 318 | float myacos(float x) 319 | { 320 | if(x > 1) x = 1; 321 | if(x < -1) x = -1; 322 | return acos(x); 323 | } 324 | 325 | float mysqrt(float x) 326 | { 327 | if(x < 0) x = 0; 328 | return sqrt(x); 329 | } 330 | 331 | float mylog(float x) 332 | { 333 | if(x < 0) x = 0; 334 | return log(x); 335 | } 336 | -------------------------------------------------------------------------------- /Qt-Color-Widgets/src/QtColorWidgets/gradient_slider.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * \file gradient_slider.cpp 3 | * 4 | * \author Mattia Basaglia 5 | * 6 | * \copyright Copyright (C) 2013-2020 Mattia Basaglia 7 | * \copyright Copyright (C) 2014 Calle Laakkonen 8 | * \copyright Copyright (C) 2017 caryoscelus 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Lesser General Public License as published by 12 | * the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Lesser General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | #include "QtColorWidgets/gradient_slider.hpp" 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | static void loadResource() 33 | { 34 | static bool loaded = false; 35 | if ( !loaded ) 36 | { 37 | Q_INIT_RESOURCE(color_widgets); 38 | loaded = true; 39 | } 40 | } 41 | 42 | namespace color_widgets { 43 | 44 | class GradientSlider::Private 45 | { 46 | public: 47 | QLinearGradient gradient; 48 | QBrush back; 49 | 50 | Private() : 51 | back(Qt::darkGray, Qt::DiagCrossPattern) 52 | { 53 | loadResource(); 54 | back.setTexture(QPixmap(QStringLiteral(":/color_widgets/alphaback.png"))); 55 | gradient.setCoordinateMode(QGradient::StretchToDeviceMode); 56 | gradient.setSpread(QGradient::RepeatSpread); 57 | } 58 | 59 | void mouse_event(QMouseEvent *ev, GradientSlider* owner) 60 | { 61 | qreal pos = (owner->geometry().width() > 5) ? 62 | static_cast(ev->pos().x() - 2.5) / (owner->geometry().width() - 5) : 0; 63 | pos = qMax(qMin(pos, 1.0), 0.0); 64 | owner->setSliderPosition(qRound(owner->minimum() + 65 | pos * (owner->maximum() - owner->minimum()))); 66 | } 67 | 68 | }; 69 | 70 | GradientSlider::GradientSlider(QWidget *parent) : 71 | GradientSlider(Qt::Horizontal, parent) 72 | {} 73 | 74 | GradientSlider::GradientSlider(Qt::Orientation orientation, QWidget *parent) : 75 | QSlider(orientation, parent), p(new Private) 76 | { 77 | setTickPosition(NoTicks); 78 | } 79 | 80 | GradientSlider::~GradientSlider() 81 | { 82 | delete p; 83 | } 84 | 85 | void GradientSlider::mousePressEvent(QMouseEvent *ev) 86 | { 87 | if ( ev->button() == Qt::LeftButton ) 88 | { 89 | ev->accept(); 90 | setSliderDown(true); 91 | p->mouse_event(ev, this); 92 | update(); 93 | } 94 | else 95 | { 96 | QSlider::mousePressEvent(ev); 97 | } 98 | } 99 | 100 | void GradientSlider::mouseMoveEvent(QMouseEvent *ev) 101 | { 102 | if ( ev->buttons() & Qt::LeftButton ) 103 | { 104 | ev->accept(); 105 | p->mouse_event(ev, this); 106 | update(); 107 | } 108 | else 109 | { 110 | QSlider::mouseMoveEvent(ev); 111 | } 112 | } 113 | 114 | void GradientSlider::mouseReleaseEvent(QMouseEvent *ev) 115 | { 116 | if ( ev->button() == Qt::LeftButton ) 117 | { 118 | ev->accept(); 119 | setSliderDown(false); 120 | update(); 121 | } 122 | else 123 | { 124 | QSlider::mousePressEvent(ev); 125 | } 126 | } 127 | 128 | QBrush GradientSlider::background() const 129 | { 130 | return p->back; 131 | } 132 | 133 | void GradientSlider::setBackground(const QBrush &bg) 134 | { 135 | p->back = bg; 136 | update(); 137 | Q_EMIT backgroundChanged(bg); 138 | } 139 | 140 | QGradientStops GradientSlider::colors() const 141 | { 142 | return p->gradient.stops(); 143 | } 144 | 145 | void GradientSlider::setColors(const QGradientStops &colors) 146 | { 147 | p->gradient.setStops(colors); 148 | update(); 149 | } 150 | 151 | QLinearGradient GradientSlider::gradient() const 152 | { 153 | return p->gradient; 154 | } 155 | 156 | void GradientSlider::setGradient(const QLinearGradient &gradient) 157 | { 158 | p->gradient = gradient; 159 | update(); 160 | } 161 | 162 | void GradientSlider::setColors(const QVector &colors) 163 | { 164 | QGradientStops stops; 165 | stops.reserve(colors.size()); 166 | 167 | double c = colors.size() - 1; 168 | if(c==0) { 169 | stops.append(QGradientStop(0, colors.at(0))); 170 | 171 | } else { 172 | for(int i=0;igradient.stops(); 182 | if(stops.isEmpty()) 183 | stops.push_back(QGradientStop(0.0, c)); 184 | else 185 | stops.front().second = c; 186 | p->gradient.setStops(stops); 187 | 188 | update(); 189 | } 190 | 191 | void GradientSlider::setLastColor(const QColor &c) 192 | { 193 | QGradientStops stops = p->gradient.stops(); 194 | if(stops.size()<2) 195 | stops.push_back(QGradientStop(1.0, c)); 196 | else 197 | stops.back().second = c; 198 | p->gradient.setStops(stops); 199 | update(); 200 | } 201 | 202 | QColor GradientSlider::firstColor() const 203 | { 204 | QGradientStops s = colors(); 205 | return s.empty() ? QColor() : s.front().second; 206 | } 207 | 208 | QColor GradientSlider::lastColor() const 209 | { 210 | QGradientStops s = colors(); 211 | return s.empty() ? QColor() : s.back().second; 212 | } 213 | 214 | void GradientSlider::paintEvent(QPaintEvent *) 215 | { 216 | QPainter painter(this); 217 | 218 | QStyleOptionFrame panel; 219 | panel.initFrom(this); 220 | panel.lineWidth = 1; 221 | panel.midLineWidth = 0; 222 | panel.state |= QStyle::State_Sunken; 223 | style()->drawPrimitive(QStyle::PE_Frame, &panel, &painter, this); 224 | QRect r = style()->subElementRect(QStyle::SE_FrameContents, &panel, this); 225 | painter.setClipRect(r); 226 | 227 | qreal gradient_direction = invertedAppearance() ? -1 : 1; 228 | 229 | if(orientation() == Qt::Horizontal) 230 | p->gradient.setFinalStop(gradient_direction, 0); 231 | else 232 | p->gradient.setFinalStop(0, -gradient_direction); 233 | 234 | painter.setPen(Qt::NoPen); 235 | painter.setBrush(p->back); 236 | painter.drawRect(1,1,geometry().width()-2,geometry().height()-2); 237 | painter.setBrush(p->gradient); 238 | painter.drawRect(1,1,geometry().width()-2,geometry().height()-2); 239 | 240 | qreal pos = (maximum() != 0) ? 241 | static_cast(value() - minimum()) / maximum() : 0; 242 | QColor color; 243 | auto stops = p->gradient.stops(); 244 | int i; 245 | for (i = 0; i < stops.size(); i++) { 246 | if (stops[i].first > pos) 247 | break; 248 | } 249 | if (i == 0) { 250 | color = firstColor(); 251 | } if (i == stops.size()) { 252 | color = lastColor(); 253 | } else { 254 | auto &a = stops[i - 1]; 255 | auto &b = stops[i]; 256 | auto c = (b.first - a.first); 257 | qreal q = (c != 0) ? 258 | (pos - a.first) / c : 0; 259 | color = QColor::fromRgbF(b.second.redF() * q + a.second.redF() * (1.0 - q), 260 | b.second.greenF() * q + a.second.greenF() * (1.0 - q), 261 | b.second.blueF() * q + a.second.blueF() * (1.0 - q), 262 | b.second.alphaF() * q + a.second.alphaF() * (1.0 - q)); 263 | } 264 | 265 | pos = pos * (geometry().width() - 5); 266 | if (color.valueF() > 0.5 || color.alphaF() < 0.5) { 267 | painter.setPen(QPen(Qt::black, 3)); 268 | } else { 269 | painter.setPen(QPen(Qt::white, 3)); 270 | } 271 | QPointF p1 = QPointF(2.5, 2.5) + QPointF(pos, 0); 272 | QPointF p2 = p1 + QPointF(0, geometry().height() - 5); 273 | painter.drawLine(p1, p2); 274 | } 275 | 276 | } // namespace color_widgets 277 | --------------------------------------------------------------------------------