File indexing completed on 2025-01-26 04:02:01

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 "glaxnimate_app.hpp"
0008 
0009 #include "app_info.hpp"
0010 
0011 #include <QDir>
0012 #include <QStandardPaths>
0013 
0014 using namespace glaxnimate::gui;
0015 using namespace glaxnimate;
0016 
0017 #ifdef MOBILE_UI
0018 
0019 #include <QScreen>
0020 
0021 static qreal get_mult()
0022 {
0023 #ifndef Q_OS_ANDROID
0024     return 1;
0025 }
0026 #else
0027     auto sz = QApplication::primaryScreen()->size();
0028     return qMin(sz.width(), sz.height()) / 240.;
0029 
0030 }
0031 
0032 QString GlaxnimateApp::data_file(const QString &name) const
0033 {
0034     return "assets:/share/glaxnimate/glaxnimate/" + name;
0035 }
0036 
0037 #endif
0038 
0039 qreal GlaxnimateApp::handle_size_multiplier()
0040 {
0041     static qreal mult = get_mult();
0042     return mult;
0043 }
0044 
0045 qreal GlaxnimateApp::handle_distance_multiplier()
0046 {
0047     return handle_size_multiplier() / 2.;
0048 }
0049 
0050 void GlaxnimateApp::set_clipboard_data(QMimeData *data)
0051 {
0052     clipboard.reset(data);
0053 }
0054 
0055 const QMimeData *GlaxnimateApp::get_clipboard_data()
0056 {
0057     return clipboard.get();
0058 }
0059 
0060 #else
0061 
0062 #include <QPalette>
0063 #include <QClipboard>
0064 
0065 #include <KLocalizedString>
0066 
0067 #include "app/settings/settings.hpp"
0068 #include "app/settings/palette_settings.hpp"
0069 #include "app/settings/keyboard_shortcuts.hpp"
0070 #include "app/log/listener_file.hpp"
0071 #include "settings/plugin_settings_group.hpp"
0072 #include "settings/clipboard_settings.hpp"
0073 #include "settings/toolbar_settings.hpp"
0074 #include "settings/api_credentials.hpp"
0075 
0076 static QVariantMap avail_icon_themes()
0077 {
0078     QVariantMap avail_icon_themes;
0079     avail_icon_themes[i18n("Glaxnimate Default")] = "";
0080     for ( QDir search : QIcon::themeSearchPaths() )
0081     {
0082         for ( const auto& avail : search.entryInfoList(QDir::Dirs|QDir::NoDotAndDotDot) )
0083         {
0084             QDir subdir(avail.filePath());
0085             if ( subdir.exists("index.theme") )
0086                 avail_icon_themes[avail.baseName()] = avail.baseName();
0087         }
0088     }
0089 
0090     return avail_icon_themes;
0091 }
0092 
0093 static QString default_icon_theme()
0094 {
0095     QPalette palette = QGuiApplication::palette();
0096     if ( palette.color(QPalette::Button).value() < 100 )
0097         return "breeze-dark";
0098     else
0099         return "breeze";
0100 }
0101 
0102 static void set_icon_theme(const QVariant& v)
0103 {
0104     QString theme_name = v.toString();
0105 
0106     if ( theme_name.isEmpty() )
0107         theme_name = default_icon_theme();
0108 
0109     QIcon::setThemeName(theme_name);
0110 }
0111 
0112 static QVariantMap avail_languages()
0113 {
0114     QVariantMap avail_languages;
0115     for ( const QString& name : app::TranslationService::instance().available_languages().keys() )
0116     {
0117         avail_languages[name] = app::TranslationService::instance().available_languages()[name];
0118     }
0119 
0120     return avail_languages;
0121 }
0122 
0123 static void set_language(const QVariant& v)
0124 {
0125     QString code = v.toString();
0126     app::TranslationService::instance().change_lang_code(code);
0127 }
0128 
0129 static void icon_theme_fixup()
0130 {
0131     QString default_theme = default_icon_theme();
0132     QIcon::setFallbackThemeName(default_theme);
0133 
0134     QString old = QIcon::themeName();
0135     if ( old == "breeze" || old == "breeze-dark" )
0136         QIcon::setThemeName(default_theme);
0137     else
0138         set_icon_theme(old);
0139 }
0140 
0141 static void load_themes(GlaxnimateApp* app, app::settings::PaletteSettings* settings)
0142 {
0143     for ( QDir themedir : app->data_paths("themes") )
0144     {
0145         for ( const auto& theme : themedir.entryList({"*.ini"}, QDir::Files|QDir::Readable, QDir::Name|QDir::IgnoreCase) )
0146         {
0147             QSettings ini_parser(themedir.absoluteFilePath(theme), QSettings::IniFormat);
0148             settings->load_palette(ini_parser, true);
0149         }
0150     }
0151 }
0152 
0153 void GlaxnimateApp::on_initialize()
0154 {
0155 
0156     app::log::Logger::instance().add_listener<app::log::ListenerFile>(writable_data_path("log.txt"));
0157     app::log::Logger::instance().add_listener<app::log::ListenerStderr>();
0158     store_logger = app::log::Logger::instance().add_listener<app::log::ListenerStore>();
0159 
0160     setWindowIcon(QIcon(data_file("images/logo.svg")));
0161 
0162     QDir().mkpath(backup_path());
0163 }
0164 
0165 void GlaxnimateApp::on_initialize_settings()
0166 {
0167     using namespace app::settings;
0168     QString curr_lang = app::TranslationService::instance().current_language_code();
0169 
0170     Settings::instance().add_group("ui", i18nc("@title settings group", "User Interface"), "preferences-desktop-theme", {
0171         //      slug            Label/Tooltip                                               Type                default     choices             side effects
0172         Setting("language",
0173                 i18nc("@label:listbox", "Language"),
0174                 i18nc("@info:tooltip", "Interface Language"),                        Setting::String,    curr_lang,  avail_languages(),  set_language),
0175         Setting("icon_theme", i18nc("@label:listbox", "Icon Theme"),  {},             Setting::String,    "",         avail_icon_themes(), ::set_icon_theme),
0176         // Setting("startup_dialog", i18nc("@option:check", "Show startup dialog"), {},  Setting::Bool,      true),
0177         Setting("timeline_scroll_horizontal",
0178                 i18nc("@option:check", "Horizontal Timeline Scroll"),
0179                 i18nc("@info:tooltip", "If enabled, the timeline will scroll horizontally by default and vertically with Shift or Alt"),
0180                                                                                             Setting::Bool,      false),
0181         Setting("layout",            {}, {},                                                Setting::Internal,  0),
0182         Setting("window_state",      {}, {},                                                Setting::Internal,  QByteArray{}),
0183         Setting("window_geometry",   {}, {},                                                Setting::Internal,  QByteArray{}),
0184         Setting("timeline_splitter", {}, {},                                                Setting::Internal,  QByteArray{}),
0185     });
0186     Settings::instance().add_group("defaults", i18nc("@title settings group", "New Animation Defaults"), "video-webm", {
0187         Setting("width",
0188             i18nc("@label:spinbox", "Width"),    "",
0189             512,   0, 1000000),
0190         Setting("height",
0191             i18nc("@label:spinbox", "Height"),   "",
0192             512,   0, 1000000),
0193         Setting("fps",
0194             i18nc("@label:spinbox", "FPS"),
0195             i18nc("@info:tooltip", "Frames per second"),
0196             60.f, 0.f, 1000.f),
0197         Setting("duration",
0198             i18nc("@label:spinbox", "Duration"),
0199             i18nc("@info:tooltip", "Duration in seconds"),
0200             3.f, 0.f, 90000.f),
0201     });
0202     Settings::instance().add_group("open_save", i18nc("@title settings group", "Open / Save"), "kfloppy", {
0203         Setting("max_recent_files", i18nc("@label:spinbox", "Max Recent Files"), {},      5, 0, 16),
0204         Setting("path",             {},         {},                        Setting::Internal,  QString{}),
0205         Setting("recent_files",     {},         {},                        Setting::Internal,  QStringList{}),
0206         Setting("backup_frequency",
0207                 i18nc("@label:spinbox", "Backup Frequency"),
0208                 i18nc("@info:tooltip", "How often to save a backup copy (in minutes)"),  5, 0, 60),
0209         Setting("render_path",      {},         {},                        Setting::Internal,  QString{}),
0210         Setting("import_path",      {},         {},                        Setting::Internal,  QString{}),
0211         Setting("native_dialog",    i18nc("@option:check", "Use system file dialog"), {}, Setting::Bool, true),
0212     });
0213     Settings::instance().add_group("scripting", i18nc("@title settings group", "Scripting"), "utilities-terminal", {
0214         //      slug                Label       Tooltip                    Type                default
0215         Setting("history",          {},         {},                        Setting::Internal,  QStringList{}),
0216         Setting("max_history",      {},         {},                        Setting::Internal,  100),
0217     });
0218     Settings::instance().add_group("tools", i18nc("@title settings group", "Tools"), "tools", {
0219         //      slug                Label       Tooltip                    Type                default
0220         Setting("shape_group",      {},         {},                        Setting::Internal,  true),
0221         Setting("shape_fill",       {},         {},                        Setting::Internal,  true),
0222         Setting("shape_stroke",     {},         {},                        Setting::Internal,  true),
0223         Setting("edit_mask",        {},         {},                        Setting::Internal,  false),
0224         Setting("color_main",       {},         {},                        Setting::Internal,  "#ffffff"),
0225         Setting("color_secondary",  {},         {},                        Setting::Internal,  "#000000"),
0226         Setting("stroke_width",     {},         {},                        Setting::Internal,  1.),
0227         Setting("stroke_cap",       {},         {},                        Setting::Internal,  int(Qt::RoundCap)),
0228         Setting("stroke_join",      {},         {},                        Setting::Internal,  int(Qt::RoundJoin)),
0229         Setting("stroke_miter",     {},         {},                        Setting::Internal,  4.),
0230         Setting("star_type",        {},         {},                        Setting::Internal,  1),
0231         Setting("star_ratio",       {},         {},                        Setting::Internal,  0.5),
0232         Setting("star_points",      {},         {},                        Setting::Internal,  5),
0233     });
0234     // catch all
0235     Settings::instance().add_group("internal", "", "", {});
0236 
0237     app::settings::Settings::instance().add_group(std::make_unique<settings::ToolbarSettingsGroup>());
0238     app::settings::Settings::instance().add_group(std::make_unique<settings::PluginSettingsGroup>(QStringList{
0239         "AnimatedRaster", "ReplaceColor", "dotLottie", "FrameByFrame"
0240     }));
0241     app::settings::Settings::instance().add_group(std::make_unique<settings::ClipboardSettings>());
0242 
0243     auto palette_settings = std::make_unique<app::settings::PaletteSettings>();
0244     load_themes(this, palette_settings.get());
0245     app::settings::Settings::instance().add_group(std::move(palette_settings));
0246 
0247     auto sc_settings = std::make_unique<app::settings::ShortcutSettings>();
0248     shortcut_settings = sc_settings.get();
0249     app::settings::Settings::instance().add_group(std::move(sc_settings));
0250 
0251     app::settings::Settings::instance().add_group(std::make_unique<settings::ApiCredentials>());
0252 
0253 }
0254 
0255 app::settings::ShortcutSettings * GlaxnimateApp::shortcuts() const
0256 {
0257     return shortcut_settings;
0258 }
0259 
0260 void GlaxnimateApp::set_clipboard_data(QMimeData *data)
0261 {
0262     return QGuiApplication::clipboard()->setMimeData(data);
0263 }
0264 
0265 const QMimeData *GlaxnimateApp::get_clipboard_data()
0266 {
0267     return QGuiApplication::clipboard()->mimeData();
0268 }
0269 
0270 void glaxnimate::gui::GlaxnimateApp::on_initialize_translations()
0271 {
0272     app::TranslationService::instance().initialize("en_US");
0273 }
0274 
0275 bool GlaxnimateApp::event(QEvent *event)
0276 {
0277     if ( event->type() == QEvent::ApplicationPaletteChange )
0278         icon_theme_fixup();
0279 
0280     return app::Application::event(event);
0281 }
0282 
0283 #endif
0284 
0285 
0286 
0287 QString GlaxnimateApp::temp_path()
0288 {
0289     QDir tempdir = QDir::temp();
0290     QString subdir = AppInfo::instance().slug();
0291 
0292     if ( !tempdir.exists(subdir) )
0293         if ( !tempdir.mkpath(subdir) )
0294             return "";
0295 
0296     return tempdir.filePath(subdir);
0297 }
0298 
0299 QString GlaxnimateApp::backup_path() const
0300 {
0301 
0302     return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)
0303         + QLatin1String("/stalefiles/")
0304         + QCoreApplication::instance()->applicationName()
0305     ;
0306 }