File indexing completed on 2025-03-09 04:00:16

0001 /*
0002  * SPDX-FileCopyrightText: 2019-2023 Mattia Basaglia <dev@dragon.best>
0003  *
0004  * SPDX-License-Identifier: GPL-3.0-or-later
0005  */
0006 
0007 #pragma once
0008 
0009 #include "model/object.hpp"
0010 #include "model/property/object_list_property.hpp"
0011 #include "model/property/sub_object_property.hpp"
0012 #include "named_color.hpp"
0013 #include "bitmap.hpp"
0014 #include "gradient.hpp"
0015 #include "composition.hpp"
0016 #include "embedded_font.hpp"
0017 #include "network_downloader.hpp"
0018 
0019 
0020 namespace glaxnimate::model {
0021 
0022 
0023 namespace detail {
0024     DocumentNode* defs(model::Document* doc);
0025 } // detail
0026 
0027 template<class T, class Derived>
0028 class AssetListBase : public DocumentNode
0029 {
0030 protected:
0031     using Ctor = AssetListBase;
0032 
0033 public:
0034     ObjectListProperty<T> values{this, kli18n("values"),
0035         &AssetListBase::on_added,
0036         &AssetListBase::on_removed,
0037         &AssetListBase::docnode_child_add_begin,
0038         &AssetListBase::docnode_child_remove_begin,
0039         &AssetListBase::docnode_child_move_begin,
0040         &AssetListBase::docnode_child_move_end
0041     };
0042 
0043 public:
0044     using DocumentNode::DocumentNode;
0045 
0046     DocumentNode* docnode_parent() const override
0047     {
0048         return detail::defs(document());
0049     }
0050 
0051     int docnode_child_count() const override
0052     {
0053         return values.size();
0054     }
0055 
0056     DocumentNode* docnode_child(int index) const override
0057     {
0058         return values[index];
0059     }
0060 
0061     int docnode_child_index(DocumentNode* dn) const override
0062     {
0063         return values.index_of(static_cast<T*>(dn));
0064     }
0065 
0066     QIcon instance_icon() const override
0067     {
0068         return tree_icon();
0069     }
0070 
0071 protected:
0072     virtual void on_added(T* obj, int row)
0073     {
0074         obj->attach();
0075         Q_EMIT docnode_child_add_end(obj, row);
0076     }
0077 
0078     virtual void on_removed(T* obj, int row)
0079     {
0080         obj->detach();
0081         Q_EMIT docnode_child_remove_end(obj, row);
0082     }
0083 };
0084 
0085 #define ASSET_LIST_CLASS(type)                  \
0086     GLAXNIMATE_PROPERTY_LIST_IMPL(type, values) \
0087 public:                                         \
0088     using Ctor::Ctor;                           \
0089 // END
0090 
0091 class NamedColorList : public AssetListBase<NamedColor, NamedColorList>
0092 {
0093     GLAXNIMATE_OBJECT(NamedColorList)
0094     ASSET_LIST_CLASS(NamedColor)
0095 
0096 public:
0097     QIcon tree_icon() const override;
0098     QString type_name_human() const override { return i18n("Swatch"); }
0099 
0100 Q_SIGNALS:
0101     void color_changed(int position, model::NamedColor* color);
0102     void color_added(int position, model::NamedColor* color);
0103     void color_removed(int position, model::NamedColor* color);
0104 
0105 protected:
0106     void on_added(model::NamedColor* color, int position) override;
0107     void on_removed(model::NamedColor* color, int position) override;
0108 };
0109 
0110 class BitmapList : public AssetListBase<Bitmap, BitmapList>
0111 {
0112     GLAXNIMATE_OBJECT(BitmapList)
0113     ASSET_LIST_CLASS(Bitmap)
0114 
0115 public:
0116     QIcon tree_icon() const override;
0117     QString type_name_human() const override { return i18n("Images"); }
0118 };
0119 
0120 class GradientColorsList : public AssetListBase<GradientColors, GradientColorsList>
0121 {
0122     GLAXNIMATE_OBJECT(GradientColorsList)
0123     ASSET_LIST_CLASS(GradientColors)
0124 
0125 public:
0126     QIcon tree_icon() const override;
0127     QString type_name_human() const override { return i18n("Gradient Colors"); }
0128 };
0129 
0130 class GradientList : public AssetListBase<Gradient, GradientList>
0131 {
0132     GLAXNIMATE_OBJECT(GradientList)
0133     ASSET_LIST_CLASS(Gradient)
0134 
0135 public:
0136     QIcon tree_icon() const override;
0137     QString type_name_human() const override { return i18n("Gradients"); }
0138 };
0139 
0140 class CompositionList : public AssetListBase<Composition, CompositionList>
0141 {
0142     GLAXNIMATE_OBJECT(CompositionList)
0143     ASSET_LIST_CLASS(Composition)
0144 
0145 public:
0146     QIcon tree_icon() const override;
0147 
0148 protected:
0149     void on_added(model::Composition* obj, int position) override;
0150     void on_removed(model::Composition* obj, int position) override;
0151     QString type_name_human() const override { return i18n("Compositions"); }
0152 
0153 Q_SIGNALS:
0154     void precomp_added(model::Composition* obj, int position);
0155 };
0156 
0157 class FontList : public AssetListBase<EmbeddedFont, FontList>
0158 {
0159     GLAXNIMATE_OBJECT(FontList)
0160     ASSET_LIST_CLASS(EmbeddedFont)
0161 
0162 public:
0163     QIcon tree_icon() const override { return QIcon::fromTheme("font"); }
0164 
0165 
0166 protected:
0167     void on_added(model::EmbeddedFont* obj, int position) override;
0168 
0169 Q_SIGNALS:
0170     void font_added(model::EmbeddedFont* font);
0171 
0172 protected:
0173     QString type_name_human() const override { return i18n("Fonts"); }
0174 };
0175 
0176 
0177 class Assets : public DocumentNode
0178 {
0179     GLAXNIMATE_OBJECT(Assets)
0180 
0181     GLAXNIMATE_SUBOBJECT(NamedColorList, colors)
0182     GLAXNIMATE_SUBOBJECT(BitmapList, images)
0183     GLAXNIMATE_SUBOBJECT(GradientColorsList, gradient_colors)
0184     GLAXNIMATE_SUBOBJECT(GradientList, gradients)
0185     GLAXNIMATE_SUBOBJECT(CompositionList, compositions)
0186     GLAXNIMATE_SUBOBJECT(FontList, fonts)
0187 
0188 public:
0189     using DocumentNode::DocumentNode;
0190 
0191     Q_INVOKABLE glaxnimate::model::NamedColor* add_color(const QColor& color, const QString& name = {});
0192     Q_INVOKABLE glaxnimate::model::Bitmap* add_image_file(const QString& filename, bool embed);
0193     Q_INVOKABLE glaxnimate::model::Bitmap* add_image(const QImage& image, const QString& store_as = "png");
0194     Q_INVOKABLE glaxnimate::model::GradientColors* add_gradient_colors(int index = -1);
0195     Q_INVOKABLE glaxnimate::model::Gradient* add_gradient(int index = -1);
0196     Q_INVOKABLE glaxnimate::model::EmbeddedFont* add_font(const QByteArray& ttf_data);
0197     glaxnimate::model::EmbeddedFont* add_font(const CustomFont& font);
0198     Q_INVOKABLE glaxnimate::model::EmbeddedFont* font_by_index(int database_index) const;
0199     glaxnimate::model::Composition* add_comp_no_undo();
0200 
0201     DocumentNode* docnode_parent() const override;
0202     int docnode_child_count() const override;
0203     DocumentNode* docnode_child(int index) const override;
0204     int docnode_child_index(DocumentNode* dn) const override;
0205     QIcon tree_icon() const override;
0206     QIcon instance_icon() const override;
0207     QString type_name_human() const override { return i18n("Assets"); }
0208 
0209     NetworkDownloader network_downloader;
0210 };
0211 
0212 } // namespace glaxnimate::model