File indexing completed on 2025-02-02 04:11:25

0001 /*
0002  * SPDX-FileCopyrightText: 2019-2023 Mattia Basaglia <dev@dragon.best>
0003  *
0004  * SPDX-License-Identifier: GPL-3.0-or-later
0005  */
0006 
0007 #include "plugin_ui_dialog.hpp"
0008 
0009 #include <QMetaObject>
0010 #include <QVBoxLayout>
0011 #include <QtUiTools/QUiLoader>
0012 #include <QDialogButtonBox>
0013 
0014 #include "app/log/log.hpp"
0015 #include "app/application.hpp"
0016 
0017 #include <QtColorWidgets/ColorSelector>
0018 #include <QtColorWidgets/color_2d_slider.hpp>
0019 #include <QtColorWidgets/ColorDialog>
0020 #include <QtColorWidgets/ColorListWidget>
0021 #include <QtColorWidgets/ColorPreview>
0022 #include <QtColorWidgets/ColorWheel>
0023 #include <QtColorWidgets/color_palette_widget.hpp>
0024 #include <QtColorWidgets/GradientEditor>
0025 #include <QtColorWidgets/GradientSlider>
0026 #include <QtColorWidgets/HueSlider>
0027 #include <QtColorWidgets/swatch.hpp>
0028 #include <QtColorWidgets/HarmonyColorWheel>
0029 
0030 using namespace glaxnimate::gui;
0031 using namespace glaxnimate;
0032 
0033 /**
0034  * On mac widgets created from the plugin don't work right, so we fake it...
0035  */
0036 class ColoredUiLoader : public QUiLoader
0037 {
0038 public:
0039     using QUiLoader::QUiLoader;
0040 
0041     QWidget* createWidget(const QString & className, QWidget * parent, const QString & name) override
0042     {
0043         if ( className.startsWith("color_widgets::") )
0044         {
0045             auto it = ctors().find(className);
0046             if ( it != ctors().end() )
0047             {
0048                 QWidget* widget = it->second->create(parent);
0049                 widget->setObjectName(name);
0050                 return widget;
0051 
0052             }
0053         }
0054         return QUiLoader::createWidget(className, parent, name);
0055     }
0056 
0057 private:
0058     class CtorBase
0059     {
0060     public:
0061         virtual ~CtorBase() = default;
0062         virtual QWidget* create(QWidget* parent) const = 0;
0063     };
0064 
0065     template<class Wid>
0066     class Ctor : public CtorBase
0067     {
0068     public:
0069         QWidget* create(QWidget* parent) const override
0070         {
0071             return new Wid(parent);
0072         }
0073 
0074         static std::pair<QString, std::unique_ptr<CtorBase>> pair()
0075         {
0076             return {
0077                 Wid::staticMetaObject.className(),
0078                 std::make_unique<Ctor>()
0079             };
0080         }
0081     };
0082 
0083     static const std::map<QString, std::unique_ptr<CtorBase>>& ctors()
0084     {
0085         static std::map<QString, std::unique_ptr<CtorBase>> meta;
0086         if ( meta.empty() )
0087         {
0088             meta.insert(Ctor<color_widgets::Color2DSlider>::pair());
0089             meta.insert(Ctor<color_widgets::ColorSelector>::pair());
0090             meta.insert(Ctor<color_widgets::ColorDialog>::pair());
0091             meta.insert(Ctor<color_widgets::ColorListWidget>::pair());
0092             meta.insert(Ctor<color_widgets::ColorPreview>::pair());
0093             meta.insert(Ctor<color_widgets::ColorWheel>::pair());
0094             meta.insert(Ctor<color_widgets::ColorPaletteWidget>::pair());
0095             meta.insert(Ctor<color_widgets::GradientEditor>::pair());
0096             meta.insert(Ctor<color_widgets::GradientSlider>::pair());
0097             meta.insert(Ctor<color_widgets::HueSlider>::pair());
0098             meta.insert(Ctor<color_widgets::Swatch>::pair());
0099             meta.insert(Ctor<color_widgets::HarmonyColorWheel>::pair());
0100         }
0101 
0102         return meta;
0103     }
0104 };
0105 
0106 PluginUiDialog::PluginUiDialog(QIODevice& file, const plugin::Plugin& data, QWidget* parent)
0107     : QDialog(parent)
0108 {
0109     ColoredUiLoader loader;
0110     loader.setWorkingDirectory(data.data().dir);
0111     loader.setLanguageChangeEnabled(true);
0112     // for ( const auto& dir : app::Application::instance()->data_paths("lib") )
0113         // loader.addPluginPath(dir);
0114 
0115     QWidget* child = loader.load(&file, nullptr);
0116     if ( !child )
0117     {
0118         data.logger().stream(app::log::Error) << "Could not load UI:" << loader.errorString();
0119         return;
0120     }
0121 
0122     if ( child->windowIcon().cacheKey() == qApp->windowIcon().cacheKey() )
0123         setWindowIcon(data.icon());
0124     else
0125         setWindowIcon(child->windowIcon());
0126 
0127     if ( child->windowTitle().isEmpty() )
0128         setWindowTitle(data.data().name);
0129     else
0130         setWindowTitle(child->windowTitle());
0131 
0132     resize(child->size());
0133 
0134     setSizePolicy(child->sizePolicy());
0135 
0136 
0137     if ( auto d = qobject_cast<QDialog*>(child) )
0138     {
0139         child->setVisible(false);
0140         connect(this, &QObject::destroyed, child, &QObject::deleteLater);
0141         connect(d, &QDialog::accepted, this, &QDialog::accept);
0142         connect(d, &QDialog::rejected, this, &QDialog::reject);
0143         setLayout(child->layout());
0144     }
0145     else
0146     {
0147         auto lay = new QVBoxLayout;
0148         setLayout(lay);
0149         lay->addWidget(child);
0150         auto box = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
0151         lay->addWidget(box);
0152         connect(box, &QDialogButtonBox::accepted, this, &QDialog::accept);
0153         connect(box, &QDialogButtonBox::rejected, this, &QDialog::reject);
0154     }
0155 }
0156 
0157 QVariant PluginUiDialog::get_value(const QString& widget, const QString& property)
0158 {
0159     QWidget* wid = findChild<QWidget*>(widget);
0160     if ( !wid )
0161         return {};
0162 
0163     return wid->property(property.toStdString().c_str());
0164 }
0165 
0166 bool PluginUiDialog::set_value(const QString& widget, const QString& property, const QVariant& value)
0167 {
0168     QWidget* wid = findChild<QWidget*>(widget);
0169     if ( !wid )
0170         return {};
0171 
0172     return wid->setProperty(property.toStdString().c_str(), value);
0173 }