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

0001 /*
0002  * SPDX-FileCopyrightText: 2019-2023 Mattia Basaglia <dev@dragon.best>
0003  *
0004  * SPDX-License-Identifier: GPL-3.0-or-later
0005  */
0006 
0007 #ifndef GLAXNIMATEWINDOW_P_H
0008 #define GLAXNIMATEWINDOW_P_H
0009 
0010 #include <QToolButton>
0011 #include <QMessageBox>
0012 #include <QPointer>
0013 #include <QNetworkAccessManager>
0014 
0015 #include <KAutoSaveFile>
0016 
0017 #include "QtColorWidgets/color_delegate.hpp"
0018 #include "QtColorWidgets/color_palette_model.hpp"
0019 
0020 #include "ui_glaxnimate_window.h"
0021 #include "glaxnimate_window.hpp"
0022 
0023 #include "model/document.hpp"
0024 #include "command/structure_commands.hpp"
0025 
0026 #include "graphics/document_scene.hpp"
0027 #include "item_models/document_node_model.hpp"
0028 #include "item_models/property_model_single.hpp"
0029 #include "item_models/comp_filter_model.hpp"
0030 #include "item_models/asset_proxy_model.hpp"
0031 
0032 #include "style/dock_widget_style.hpp"
0033 #include "style/property_delegate.hpp"
0034 
0035 #include "app/settings/settings.hpp"
0036 #include "app/scripting/script_engine.hpp"
0037 #include "app/log/log_model.hpp"
0038 
0039 #include "plugin/plugin.hpp"
0040 #include "utils/pseudo_mutex.hpp"
0041 
0042 using namespace glaxnimate::gui;
0043 using namespace glaxnimate;
0044 
0045 namespace glaxnimate::model {
0046 class PreCompLayer;
0047 } // namespace glaxnimate::model
0048 
0049 namespace glaxnimate::gui {
0050     namespace tools {
0051     class Tool;
0052     } // namespace tools
0053 
0054 
0055     class IoStatusDialog;
0056     class AboutDialog;
0057     class ViewTransformWidget;
0058     class FlowLayout;
0059     class ShapeStylePreviewWidget;
0060 } // namespace glaxnimate::gui
0061 
0062 class QLocalSocket;
0063 class QDataStream;
0064 class QSharedMemory;
0065 
0066 template <typename T>
0067 struct QObjectDeleteLater : public std::default_delete<T>
0068 {
0069     void operator()(T *p)
0070     {
0071         p->deleteLater();
0072     }
0073 };
0074 
0075 template <typename T, class... Args>
0076 std::unique_ptr<T, QObjectDeleteLater<T>> qobject_make_unique(Args&&... args)
0077 {
0078     return std::unique_ptr<T, QObjectDeleteLater<T>>(
0079         new T(std::forward<Args>(args)...), QObjectDeleteLater<T>());
0080 }
0081 
0082 class GlaxnimateWindow::Private
0083 {
0084 public:
0085     struct CompState
0086     {
0087         CompState(model::VisualNode* single)
0088         : selection(1, single), current(single)
0089         {}
0090 
0091         CompState() : current(nullptr) {}
0092 
0093         std::vector<model::VisualNode*> selection;
0094         model::VisualNode* current;
0095     };
0096 
0097     enum class AlignPosition
0098     {
0099         Begin   = 0x01,
0100         Center  = 0x02,
0101         End     = 0x04,
0102     };
0103 
0104     enum class AlignDirection
0105     {
0106         Horizontal = 0x10,
0107         Vertical   = 0x20,
0108     };
0109 
0110     enum class LayoutPreset
0111     {
0112         Unknown,
0113         Custom,
0114         Auto,
0115         Wide,
0116         Medium,
0117         Compact
0118     };
0119 
0120     Ui::GlaxnimateWindow ui;
0121 
0122     std::unique_ptr<model::Document> current_document;
0123 
0124     item_models::PropertyModelSingle property_model;
0125     item_models::DocumentNodeModel document_node_model;
0126     item_models::AssetProxyModel asset_model;
0127     graphics::DocumentScene scene;
0128     model::Composition* comp = nullptr;
0129 
0130     GlaxnimateWindow* parent = nullptr;
0131 
0132     QStringList recent_files;
0133     io::Options export_options;
0134     bool current_document_has_file = false;
0135 
0136     QPointer<model::BrushStyle> main_brush;
0137     QPointer<model::BrushStyle> secondary_brush;
0138 
0139     tools::Tool* active_tool = nullptr;
0140     std::map<QString, std::vector<QWidget*>> tool_widgets;
0141     std::map<QString, std::vector<QAction*>> tool_actions;
0142 
0143     std::vector<CompState> comp_selections;
0144 
0145     QLabel* label_mouse_pos = nullptr;
0146     QLabel* label_recording = nullptr;
0147     QWidget* widget_recording = nullptr;
0148     ShapeStylePreviewWidget* widget_current_style = nullptr;
0149 
0150     utils::PseudoMutex update_selection;
0151     model::DocumentNode* current_node = nullptr;
0152 
0153     QNetworkAccessManager http;
0154 
0155     KAutoSaveFile autosave_file;
0156 
0157     // "set and forget" kinda variables
0158     int autosave_timer = 0;
0159     int autosave_timer_mins = 0;
0160     utils::PseudoMutex autosave_load;
0161     style::PropertyDelegate property_delegate;
0162     style::DockWidgetStyle dock_style;
0163     ViewTransformWidget* view_trans_widget;
0164     bool started = false;
0165     IoStatusDialog* dialog_import_status;
0166     IoStatusDialog* dialog_export_status;
0167     AboutDialog* about_dialog;
0168     FlowLayout* dock_tools_layout;
0169     app::log::LogModel log_model;
0170     color_widgets::ColorPaletteModel palette_model;
0171 
0172     // Stuff for IPC with Shotcut
0173     std::unique_ptr<QLocalSocket, QObjectDeleteLater<QLocalSocket>> ipc_socket;
0174     std::unique_ptr<QDataStream> ipc_stream;
0175     std::unique_ptr<QSharedMemory> ipc_memory;
0176 
0177     // document
0178     void do_setup_document();
0179     void setup_document_new(const QString& filename);
0180     bool setup_document_open(const io::Options& options);
0181     bool setup_document_open(QIODevice* file, const io::Options& options, bool is_file);
0182     void setup_document_ptr(std::unique_ptr<model::Document> doc);
0183     void refresh_title();
0184     bool close_document();
0185     bool save_document(bool force_dialog, bool export_opts);
0186     void document_open();
0187     void document_open_from_filename(const QString& filename, const QVariantMap& settings = {});
0188     io::Options options_from_filename(const QString& filename, const QVariantMap& settings = {});
0189     void drop_document(const QString& filename, bool as_comp);
0190     void document_reload();
0191     void preview_lottie(const QString& renderer);
0192     void preview_svg();
0193     void preview_rive();
0194     void preview(io::ImportExport& exporter, const QVariantMap& options);
0195     void save_frame_bmp();
0196     void save_frame_svg();
0197     void validate_tgs();
0198     void validate_discord();
0199     void autosave_timer_load_settings();
0200     void autosave_timer_start(int mins = -1);
0201     void autosave(bool force);
0202     void load_backup(KAutoSaveFile* file, bool io_options_from_current);
0203     QString drop_event_data(QDropEvent* ev);
0204     void import_image();
0205     void import_file();
0206     void import_file(const QString& name, const QVariantMap& settings);
0207     void import_file(const io::Options& options);
0208     void import_file(QIODevice* file, const io::Options& options);
0209     void load_pending();
0210     void load_remote_document(const QUrl& url, io::Options options, bool open);
0211     void check_autosaves();
0212     void show_stale_autosave_list(const QList<KAutoSaveFile*>& stale);
0213 
0214     // ui
0215     void setupUi(bool restore_state, bool debug, GlaxnimateWindow* parent);
0216     void retranslateUi(QMainWindow* parent);
0217     void view_fit();
0218     void reload_recent_menu();
0219     void most_recent_file(const QString& s);
0220     void show_warning(const QString& title, const QString& message, app::log::Severity icon = app::log::Warning);
0221     void help_about();
0222     void shutdown();
0223     void switch_tool(tools::Tool* tool);
0224     void switch_tool_action(QAction* action);
0225     void status_message(const QString& msg, int duration=5000);
0226     QVariant choose_option(const QString& label, const QVariantMap& options, const QString& title) const;
0227     void set_color_def(model::BrushStyle* sty, bool secondary);
0228     QStringList get_open_image_files(const QString& title, const QString& dir, QString* out_dir = nullptr, bool multiple = false);
0229     void set_brush_reference(model::BrushStyle* sty, bool secondary);
0230     void trace_dialog(model::DocumentNode* object);
0231     void mouse_moved(const QPointF& pos);
0232     template<class T> void add_modifier_menu_action(QMenu* menu);
0233     void show_startup_dialog();
0234     void drop_file(const QString& file);
0235     void insert_emoji();
0236     void style_change_event();
0237     void import_from_lottiefiles();
0238 
0239     void init_actions();
0240     void init_plugins();
0241     tools::Tool* init_tools_ui();
0242     void init_item_views();
0243     void init_status_bar();
0244     void init_docks();
0245     void init_menus();
0246     void init_debug();
0247     void init_tools(tools::Tool* to_activate);
0248     void init_restore_state();
0249     void init_template_menu();
0250 
0251     void layout_auto();
0252     void layout_wide();
0253     void layout_medium();
0254     void layout_compact();
0255     void layout_custom();
0256     void layout_update();
0257 
0258     // IPC
0259     void ipc_connect(const QString& name);
0260 
0261     // Model
0262     model::Composition* current_composition();
0263     model::VisualNode* current_document_node();
0264     void set_current_document_node(model::VisualNode* node);
0265     std::vector<model::VisualNode*> cleaned_selection();
0266     void duplicate_selection();
0267     void move_current(command::ReorderCommand::SpecialPosition pos);
0268     void group_shapes();
0269     void ungroup_shapes();
0270     void move_to();
0271     void cleanup_document();
0272     void to_path();
0273     void convert_to_path(const std::vector<model::ShapeElement*>& shapes, std::vector<model::ShapeElement*>* out);
0274     void align(AlignDirection direction, AlignPosition position, bool outside);
0275     QPointF align_point(const QRectF& rect, AlignDirection direction, AlignPosition position);
0276     void dropped(const QMimeData* data);
0277 
0278     void switch_composition(model::Composition* comp, int i);
0279     void setup_composition(model::Composition* comp, int index = -1);
0280     void add_composition();
0281     void objects_to_new_composition(
0282         model::Composition* comp,
0283         const std::vector<model::VisualNode*>& objects,
0284         model::ObjectListProperty<model::ShapeElement>* layer_parent,
0285         int layer_index
0286     );
0287     void on_remove_precomp(int index);
0288     void shape_to_composition(model::ShapeElement* node);
0289 
0290     void layer_new_layer();
0291     void layer_new_fill();
0292     void layer_new_stroke();
0293     void layer_new_group();
0294     void layer_delete();
0295     void layer_duplicate();
0296     void layer_new_comp_action(QAction* act);
0297 
0298     void text_put_on_path();
0299     void text_remove_from_path();
0300 
0301     // Selection
0302     void scene_selection_changed(const std::vector<model::VisualNode*>& selected, const std::vector<model::VisualNode*>& deselected);
0303     void timeline_current_node_changed(model::VisualNode* node);
0304     /**
0305      * \brief makes \p node the current object in all views
0306      */
0307     void set_current_object(model::DocumentNode* node);
0308     /**
0309      * \brief Forwards the selection to all models
0310      */
0311     void selection_changed(const std::vector<model::VisualNode*>& selected, const std::vector<model::VisualNode*>& deselected);
0312 };
0313 
0314 #endif // GLAXNIMATEWINDOW_P_H