diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 3741e547..5f8b9750 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -1,125 +1,125 @@ set(lattedock-app_SRCS alternativeshelper.cpp + apptypes.cpp infoview.cpp lattecorona.cpp screenpool.cpp - types.cpp main.cpp ) add_subdirectory(indicator) add_subdirectory(layout) add_subdirectory(layouts) add_subdirectory(package) add_subdirectory(plasma/extended) add_subdirectory(settings) add_subdirectory(settings/controllers) add_subdirectory(settings/data) add_subdirectory(settings/delegates) add_subdirectory(settings/dialogs) add_subdirectory(settings/handlers) add_subdirectory(settings/models) add_subdirectory(settings/tools) add_subdirectory(settings/views) add_subdirectory(settings/widgets) add_subdirectory(shortcuts) add_subdirectory(tools) add_subdirectory(view) add_subdirectory(view/helpers) add_subdirectory(view/indicator) add_subdirectory(view/settings) add_subdirectory(view/windowstracker) add_subdirectory(wm) add_subdirectory(wm/tracker) set(latte_dbusXML dbus/org.kde.LatteDock.xml) qt5_add_dbus_adaptor(lattedock-app_SRCS ${latte_dbusXML} lattecorona.h Latte::Corona lattedockadaptor) ki18n_wrap_ui(lattedock-app_SRCS settings/dialogs/detailsdialog.ui) ki18n_wrap_ui(lattedock-app_SRCS settings/dialogs/settingsdialog.ui) add_executable(latte-dock ${lattedock-app_SRCS}) include(FakeTarget.cmake) if(${KF5_VERSION_MINOR} LESS "62") target_link_libraries(latte-dock Qt5::DBus Qt5::Quick Qt5::Qml KF5::Activities KF5::Archive KF5::CoreAddons KF5::Crash KF5::DBusAddons KF5::Declarative KF5::GuiAddons KF5::GlobalAccel KF5::I18n KF5::IconThemes KF5::KIOWidgets KF5::Notifications KF5::NewStuff KF5::QuickAddons KF5::Plasma KF5::PlasmaQuick KF5::ProcessCore KF5::WaylandClient KF5::XmlGui Latte ) else() target_link_libraries(latte-dock Qt5::DBus Qt5::Quick Qt5::Qml KF5::Activities KF5::Archive KF5::CoreAddons KF5::Crash KF5::DBusAddons KF5::Declarative KF5::GuiAddons KF5::GlobalAccel KF5::I18n KF5::IconThemes KF5::KIOWidgets KF5::Notifications KF5::NewStuff KF5::QuickAddons KF5::Plasma KF5::PlasmaQuick KF5::WaylandClient KF5::XmlGui Latte ) endif() if(HAVE_X11) target_link_libraries(latte-dock Qt5::X11Extras KF5::WindowSystem ${X11_LIBRARIES} ${XCB_LIBRARIES} ) endif() configure_file(org.kde.latte-dock.desktop.cmake org.kde.latte-dock.desktop) configure_file(org.kde.latte-dock.appdata.xml.cmake org.kde.latte-dock.appdata.xml) install(TARGETS latte-dock ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.kde.latte-dock.desktop DESTINATION ${KDE_INSTALL_APPDIR}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.kde.latte-dock.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR}) install(FILES dbus/org.kde.LatteDock.xml DESTINATION ${KDE_INSTALL_DBUSINTERFACEDIR}) install(FILES lattedock.notifyrc DESTINATION ${KNOTIFYRC_INSTALL_DIR}) if(${KF5_VERSION_MINOR} LESS "57") install(FILES latte-layouts.knsrc DESTINATION ${CONFIG_INSTALL_DIR}) install(FILES latte-indicators.knsrc DESTINATION ${CONFIG_INSTALL_DIR}) else() install(FILES latte-layouts.knsrc DESTINATION ${KDE_INSTALL_KNSRCDIR}) install(FILES latte-indicators.knsrc DESTINATION ${KDE_INSTALL_KNSRCDIR}) endif() add_subdirectory(packageplugins) diff --git a/app/types.cpp b/app/apptypes.cpp similarity index 97% rename from app/types.cpp rename to app/apptypes.cpp index 36496aff..36643e00 100644 --- a/app/types.cpp +++ b/app/apptypes.cpp @@ -1,21 +1,21 @@ /* * Copyright 2020 Michail Vourlakos * * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#include "types.h" +#include "apptypes.h" diff --git a/app/types.h b/app/apptypes.h similarity index 65% rename from app/types.h rename to app/apptypes.h index dea6ea81..c3818df0 100644 --- a/app/types.h +++ b/app/apptypes.h @@ -1,42 +1,63 @@ /* * Copyright 2020 Michail Vourlakos * * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef LATTEAPPLOCALTYPES_H #define LATTEAPPLOCALTYPES_H // Qt #include +//! These are LatteApp::Types that will be used ONLY from Latte App c++ implementation. +//! Such types are irrelevant and not used from plasma applets. + namespace Latte { namespace ImportExport { Q_NAMESPACE enum State { FailedState = 0, UpdatedState = 2, InstalledState = 4 }; Q_ENUM_NS(State); } } +namespace Latte { +namespace Settings { +Q_NAMESPACE + +enum MouseSensitivity +{ + LowMouseSensitivity = 0, + MediumMouseSensitivity, + HighMouseSensitivity +}; +Q_ENUM_NS(MouseSensitivity); + +} +} + +//! These are LatteApp::Types that will be used from Latte App c++ implementation AND +//! Latte containment qml. Such types are irrelevant and not used from plasma applets. + #endif diff --git a/app/indicator/factory.h b/app/indicator/factory.h index d20ac37c..65fe5954 100644 --- a/app/indicator/factory.h +++ b/app/indicator/factory.h @@ -1,94 +1,94 @@ /* * Copyright 2019 Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef INDICATORFACTORY_H #define INDICATORFACTORY_H // local -#include "../types.h" +#include "../apptypes.h" // Qt #include #include #include class KPluginMetaData; namespace Latte { namespace Indicator { class Factory : public QObject { Q_OBJECT public: Factory(QObject *parent); ~Factory() override; int customPluginsCount(); QStringList customPluginIds(); QStringList customPluginNames(); QStringList customLocalPluginIds(); KPluginMetaData metadata(QString pluginId); void downloadIndicator(); void removeIndicator(QString id); bool pluginExists(QString id) const; bool isCustomType(const QString &id) const; QString uiPath(QString pluginName) const; //! metadata record static bool metadataAreValid(KPluginMetaData &metadata); //! metadata file static bool metadataAreValid(QString &file); //! imports an indicator compressed file static Latte::ImportExport::State importIndicatorFile(QString compressedFile); signals: void indicatorChanged(const QString &indicatorId); void indicatorRemoved(const QString &indicatorId); private: void reload(const QString &indicatorPath); void removeIndicatorRecords(const QString &path); void discoverNewIndicators(const QString &main); private: QHash m_plugins; QHash m_pluginUiPaths; QStringList m_customPluginIds; QStringList m_customPluginNames; QStringList m_customLocalPluginIds; //! plugins paths QStringList m_mainPaths; QStringList m_indicatorsPaths; QWidget *m_parentWidget; }; } } #endif diff --git a/app/lattecorona.cpp b/app/lattecorona.cpp index 01bc9bc7..3974f7dd 100644 --- a/app/lattecorona.cpp +++ b/app/lattecorona.cpp @@ -1,1298 +1,1305 @@ /* * Copyright 2016 Smith AR * Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "lattecorona.h" // local #include "alternativeshelper.h" +#include "apptypes.h" #include "lattedockadaptor.h" #include "screenpool.h" #include "indicator/factory.h" #include "layout/centrallayout.h" #include "layout/genericlayout.h" #include "layout/sharedlayout.h" #include "layouts/importer.h" #include "layouts/manager.h" #include "layouts/synchronizer.h" #include "layouts/launcherssignals.h" #include "shortcuts/globalshortcuts.h" #include "package/lattepackage.h" #include "plasma/extended/screengeometries.h" #include "plasma/extended/screenpool.h" #include "plasma/extended/theme.h" #include "settings/universalsettings.h" #include "settings/dialogs/settingsdialog.h" #include "view/view.h" #include "view/windowstracker/windowstracker.h" #include "view/windowstracker/allscreenstracker.h" #include "view/windowstracker/currentscreentracker.h" #include "wm/abstractwindowinterface.h" #include "wm/schemecolors.h" #include "wm/waylandinterface.h" #include "wm/xwindowinterface.h" #include "wm/tracker/lastactivewindow.h" #include "wm/tracker/schemes.h" #include "wm/tracker/windowstracker.h" // Qt #include #include #include #include #include #include #include #include #include #include // Plasma #include #include #include #include // KDE #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Latte { Corona::Corona(bool defaultLayoutOnStartup, QString layoutNameOnStartUp, int userSetMemoryUsage, QObject *parent) : Plasma::Corona(parent), m_defaultLayoutOnStartup(defaultLayoutOnStartup), m_userSetMemoryUsage(userSetMemoryUsage), m_layoutNameOnStartUp(layoutNameOnStartUp), m_activitiesConsumer(new KActivities::Consumer(this)), m_screenPool(new ScreenPool(KSharedConfig::openConfig(), this)), m_indicatorFactory(new Indicator::Factory(this)), m_universalSettings(new UniversalSettings(KSharedConfig::openConfig(), this)), m_globalShortcuts(new GlobalShortcuts(this)), m_plasmaScreenPool(new PlasmaExtended::ScreenPool(this)), m_themeExtended(new PlasmaExtended::Theme(KSharedConfig::openConfig(), this)), m_layoutsManager(new Layouts::Manager(this)), m_plasmaGeometries(new PlasmaExtended::ScreenGeometries(this)), m_dialogShadows(new PanelShadows(this, QStringLiteral("dialogs/background"))) { //! create the window manager if (KWindowSystem::isPlatformWayland()) { m_wm = new WindowSystem::WaylandInterface(this); } else { m_wm = new WindowSystem::XWindowInterface(this); } setupWaylandIntegration(); KPackage::Package package(new Latte::Package(this)); m_screenPool->load(); if (!package.isValid()) { qWarning() << staticMetaObject.className() << "the package" << package.metadata().rawData() << "is invalid!"; return; } else { qDebug() << staticMetaObject.className() << "the package" << package.metadata().rawData() << "is valid!"; } setKPackage(package); //! universal settings / extendedtheme must be loaded after the package has been set m_universalSettings->load(); m_themeExtended->load(); qmlRegisterTypes(); if (m_activitiesConsumer && (m_activitiesConsumer->serviceStatus() == KActivities::Consumer::Running)) { load(); } connect(m_activitiesConsumer, &KActivities::Consumer::serviceStatusChanged, this, &Corona::load); m_viewsScreenSyncTimer.setSingleShot(true); m_viewsScreenSyncTimer.setInterval(m_universalSettings->screenTrackerInterval()); connect(&m_viewsScreenSyncTimer, &QTimer::timeout, this, &Corona::syncLatteViewsToScreens); connect(m_universalSettings, &UniversalSettings::screenTrackerIntervalChanged, this, [this]() { m_viewsScreenSyncTimer.setInterval(m_universalSettings->screenTrackerInterval()); }); //! initialize the background tracer for broadcasted backgrounds m_backgroundTracer = new KDeclarative::QmlObjectSharedEngine(this); m_backgroundTracer->setInitializationDelayed(true); m_backgroundTracer->setSource(kPackage().filePath("backgroundTracer")); m_backgroundTracer->completeInitialization(); //! Dbus adaptor initialization new LatteDockAdaptor(this); QDBusConnection dbus = QDBusConnection::sessionBus(); dbus.registerObject(QStringLiteral("/Latte"), this); } Corona::~Corona() { //! BEGIN: Give the time to slide-out views when closing m_layoutsManager->synchronizer()->hideAllViews(); //! Don't delay the destruction under wayland in any case //! because it creates a crash with kwin effects //! https://bugs.kde.org/show_bug.cgi?id=392890 if (!KWindowSystem::isPlatformWayland()) { QTimer::singleShot(400, [this]() { m_quitTimedEnded = true; }); while (!m_quitTimedEnded) { QGuiApplication::processEvents(QEventLoop::AllEvents, 50); } } //! END: slide-out views when closing m_viewsScreenSyncTimer.stop(); if (m_layoutsManager->memoryUsage() == Types::SingleLayout) { cleanConfig(); } qDebug() << "Latte Corona - unload: containments ..."; m_layoutsManager->unload(); m_plasmaGeometries->deleteLater(); m_wm->deleteLater(); m_dialogShadows->deleteLater(); m_globalShortcuts->deleteLater(); m_layoutsManager->deleteLater(); m_screenPool->deleteLater(); m_universalSettings->deleteLater(); m_plasmaScreenPool->deleteLater(); m_backgroundTracer->deleteLater(); m_themeExtended->deleteLater(); m_indicatorFactory->deleteLater(); disconnect(m_activitiesConsumer, &KActivities::Consumer::serviceStatusChanged, this, &Corona::load); delete m_activitiesConsumer; qDebug() << "Latte Corona - deleted..."; if (!m_importFullConfigurationFile.isEmpty()) { //!NOTE: Restart latte to import the new configuration QString importCommand = "latte-dock --import-full \"" + m_importFullConfigurationFile + "\""; qDebug() << "Executing Import Full Configuration command : " << importCommand; QProcess::startDetached(importCommand); } } void Corona::load() { if (m_activitiesConsumer && (m_activitiesConsumer->serviceStatus() == KActivities::Consumer::Running) && m_activitiesStarting) { m_activitiesStarting = false; disconnect(m_activitiesConsumer, &KActivities::Consumer::serviceStatusChanged, this, &Corona::load); m_layoutsManager->load(); connect(this, &Corona::availableScreenRectChangedFrom, this, &Plasma::Corona::availableScreenRectChanged); connect(this, &Corona::availableScreenRegionChangedFrom, this, &Plasma::Corona::availableScreenRegionChanged); connect(qGuiApp, &QGuiApplication::primaryScreenChanged, this, &Corona::primaryOutputChanged, Qt::UniqueConnection); connect(m_screenPool, &ScreenPool::primaryPoolChanged, this, &Corona::screenCountChanged); QString assignedLayout = m_layoutsManager->synchronizer()->shouldSwitchToLayout(m_activitiesConsumer->currentActivity()); QString loadLayoutName = ""; if (!m_defaultLayoutOnStartup && m_layoutNameOnStartUp.isEmpty()) { if (!assignedLayout.isEmpty() && assignedLayout != m_universalSettings->currentLayoutName()) { loadLayoutName = assignedLayout; } else { loadLayoutName = m_universalSettings->currentLayoutName(); } if (!m_layoutsManager->synchronizer()->layoutExists(loadLayoutName)) { loadLayoutName = m_layoutsManager->defaultLayoutName(); m_layoutsManager->importDefaultLayout(false); } } else if (m_defaultLayoutOnStartup) { loadLayoutName = m_layoutsManager->importer()->uniqueLayoutName(m_layoutsManager->defaultLayoutName()); m_layoutsManager->importDefaultLayout(true); } else { loadLayoutName = m_layoutNameOnStartUp; } if (m_userSetMemoryUsage != -1 && !KWindowSystem::isPlatformWayland()) { Types::LayoutsMemoryUsage usage = static_cast(m_userSetMemoryUsage); m_universalSettings->setLayoutsMemoryUsage(usage); } if (KWindowSystem::isPlatformWayland()) { m_universalSettings->setLayoutsMemoryUsage(Types::SingleLayout); } m_layoutsManager->loadLayoutOnStartup(loadLayoutName); //! load screens signals such screenGeometryChanged in order to support //! plasmoid.screenGeometry properly for (QScreen *screen : qGuiApp->screens()) { addOutput(screen); } connect(qGuiApp, &QGuiApplication::screenAdded, this, &Corona::addOutput, Qt::UniqueConnection); connect(qGuiApp, &QGuiApplication::screenRemoved, this, &Corona::screenRemoved, Qt::UniqueConnection); } } void Corona::unload() { qDebug() << "unload: removing containments..."; while (!containments().isEmpty()) { //deleting a containment will remove it from the list due to QObject::destroyed connect in Corona //this form doesn't crash, while qDeleteAll(containments()) does delete containments().first(); } } void Corona::setupWaylandIntegration() { if (!KWindowSystem::isPlatformWayland()) { return; } using namespace KWayland::Client; auto connection = ConnectionThread::fromApplication(this); if (!connection) { return; } Registry *registry{new Registry(this)}; registry->create(connection); connect(registry, &Registry::plasmaShellAnnounced, this , [this, registry](quint32 name, quint32 version) { m_waylandCorona = registry->createPlasmaShell(name, version, this); }); QObject::connect(registry, &KWayland::Client::Registry::plasmaWindowManagementAnnounced, [this, registry](quint32 name, quint32 version) { KWayland::Client::PlasmaWindowManagement *pwm = registry->createPlasmaWindowManagement(name, version, this); WindowSystem::WaylandInterface *wI = qobject_cast(m_wm); if (wI) { wI->initWindowManagement(pwm); } }); #if KF5_VERSION_MINOR >= 52 QObject::connect(registry, &KWayland::Client::Registry::plasmaVirtualDesktopManagementAnnounced, [this, registry] (quint32 name, quint32 version) { KWayland::Client::PlasmaVirtualDesktopManagement *vdm = registry->createPlasmaVirtualDesktopManagement(name, version, this); WindowSystem::WaylandInterface *wI = qobject_cast(m_wm); if (wI) { wI->initVirtualDesktopManagement(vdm); } }); #endif registry->setup(); connection->roundtrip(); } KWayland::Client::PlasmaShell *Corona::waylandCoronaInterface() const { return m_waylandCorona; } void Corona::cleanConfig() { auto containmentsEntries = config()->group("Containments"); bool changed = false; for(const auto &cId : containmentsEntries.groupList()) { if (!containmentExists(cId.toUInt())) { //cleanup obsolete containments containmentsEntries.group(cId).deleteGroup(); changed = true; qDebug() << "obsolete containment configuration deleted:" << cId; } else { //cleanup obsolete applets of running containments auto appletsEntries = containmentsEntries.group(cId).group("Applets"); for(const auto &appletId : appletsEntries.groupList()) { if (!appletExists(cId.toUInt(), appletId.toUInt())) { appletsEntries.group(appletId).deleteGroup(); changed = true; qDebug() << "obsolete applet configuration deleted:" << appletId; } } } } if (changed) { config()->sync(); qDebug() << "configuration file cleaned..."; } } bool Corona::containmentExists(uint id) const { for(const auto containment : containments()) { if (id == containment->id()) { return true; } } return false; } bool Corona::appletExists(uint containmentId, uint appletId) const { Plasma::Containment *containment = nullptr; for(const auto cont : containments()) { if (containmentId == cont->id()) { containment = cont; break; } } if (!containment) { return false; } for(const auto applet : containment->applets()) { if (applet->id() == appletId) { return true; } } return false; } KActivities::Consumer *Corona::activitiesConsumer() const { return m_activitiesConsumer; } PanelShadows *Corona::dialogShadows() const { return m_dialogShadows; } GlobalShortcuts *Corona::globalShortcuts() const { return m_globalShortcuts; } ScreenPool *Corona::screenPool() const { return m_screenPool; } UniversalSettings *Corona::universalSettings() const { return m_universalSettings; } WindowSystem::AbstractWindowInterface *Corona::wm() const { return m_wm; } Indicator::Factory *Corona::indicatorFactory() const { return m_indicatorFactory; } Layouts::Manager *Corona::layoutsManager() const { return m_layoutsManager; } PlasmaExtended::ScreenPool *Corona::plasmaScreenPool() const { return m_plasmaScreenPool; } PlasmaExtended::Theme *Corona::themeExtended() const { return m_themeExtended; } int Corona::numScreens() const { return qGuiApp->screens().count(); } QRect Corona::screenGeometry(int id) const { const auto screens = qGuiApp->screens(); const QScreen *screen{qGuiApp->primaryScreen()}; QString screenName; if (m_screenPool->hasId(id)) { screenName = m_screenPool->connector(id); } for(const auto scr : screens) { if (scr->name() == screenName) { screen = scr; break; } } return screen->geometry(); } CentralLayout *Corona::centralLayout(QString name) const { CentralLayout *result{nullptr}; if (name.isEmpty()) { result = m_layoutsManager->currentLayout(); } else { CentralLayout *tempCentral = m_layoutsManager->synchronizer()->centralLayout(name); if (!tempCentral) { //! Identify best active layout to be used for metrics calculations. //! Active layouts are always take into account their shared layouts for their metrics SharedLayout *sharedLayout = m_layoutsManager->synchronizer()->sharedLayout(name); if (sharedLayout) { tempCentral = sharedLayout->currentCentralLayout(); } } if (tempCentral) { result = tempCentral; } } return result; } Layout::GenericLayout *Corona::layout(QString name) const { Layout::GenericLayout *result{nullptr}; if (name.isEmpty()) { result = m_layoutsManager->currentLayout(); } else { result = m_layoutsManager->synchronizer()->layout(name); if (!result) { result = m_layoutsManager->currentLayout(); } } return result; } QRegion Corona::availableScreenRegion(int id) const { return availableScreenRegionWithCriteria(id); } QRegion Corona::availableScreenRegionWithCriteria(int id, QString forLayout, QList ignoreModes, QList ignoreEdges, bool ignoreExternalPanels, bool desktopUse) const { const QScreen *screen = m_screenPool->screenForId(id); CentralLayout *layout = centralLayout(forLayout); if (!screen) { return {}; } QRegion available = ignoreExternalPanels ? screen->geometry() : screen->availableGeometry(); if (!layout) { return available; } //! blacklist irrelevant visibility modes if (!ignoreModes.contains(Latte::Types::None)) { ignoreModes << Latte::Types::None; } if (!ignoreModes.contains(Latte::Types::NormalWindow)) { ignoreModes << Latte::Types::NormalWindow; } bool allEdges = ignoreEdges.isEmpty(); QList views = layout->latteViews(); for (const auto *view : views) { if (view && view->containment() && view->screen() == screen && ((allEdges || !ignoreEdges.contains(view->location())) && (view->visibility() && !ignoreModes.contains(view->visibility()->mode())))) { int realThickness = view->normalThickness(); // Usually availableScreenRect is used by the desktop, // but Latte don't have desktop, then here just // need calculate available space for top and bottom location, // because the left and right are those who dodge others views switch (view->location()) { case Plasma::Types::TopEdge: if (view->behaveAsPlasmaPanel()) { QRect viewGeometry = view->geometry(); if (desktopUse) { //! ignore any real window slide outs in all cases viewGeometry.moveTop(view->screen()->geometry().top() + view->screenEdgeMargin()); } available -= viewGeometry; } else { QRect realGeometry; int realWidth = view->maxLength() * view->width(); switch (view->alignment()) { case Latte::Types::Left: realGeometry = QRect(view->x(), view->y(), realWidth, realThickness); break; case Latte::Types::Center: case Latte::Types::Justify: realGeometry = QRect(qMax(view->geometry().x(), view->geometry().center().x() - realWidth / 2), view->y(), realWidth, realThickness); break; case Latte::Types::Right: realGeometry = QRect(view->geometry().right() - realWidth + 1, view->y(), realWidth, realThickness); break; } available -= realGeometry; } break; case Plasma::Types::BottomEdge: if (view->behaveAsPlasmaPanel()) { QRect viewGeometry = view->geometry(); if (desktopUse) { //! ignore any real window slide outs in all cases viewGeometry.moveTop(view->screen()->geometry().bottom() - view->screenEdgeMargin() - viewGeometry.height()); } available -= viewGeometry; } else { QRect realGeometry; int realWidth = view->maxLength() * view->width(); int realY = view->geometry().bottom() - realThickness + 1; switch (view->alignment()) { case Latte::Types::Left: realGeometry = QRect(view->x(), realY, realWidth, realThickness); break; case Latte::Types::Center: case Latte::Types::Justify: realGeometry = QRect(qMax(view->geometry().x(), view->geometry().center().x() - realWidth / 2), realY, realWidth, realThickness); break; case Latte::Types::Right: realGeometry = QRect(view->geometry().right() - realWidth + 1, realY, realWidth, realThickness); break; } available -= realGeometry; } break; case Plasma::Types::LeftEdge: if (view->behaveAsPlasmaPanel()) { QRect viewGeometry = view->geometry(); if (desktopUse) { //! ignore any real window slide outs in all cases viewGeometry.moveLeft(view->screen()->geometry().left() + view->screenEdgeMargin()); } available -= viewGeometry; } else { QRect realGeometry; int realHeight = view->maxLength() * view->height(); switch (view->alignment()) { case Latte::Types::Top: realGeometry = QRect(view->x(), view->y(), realThickness, realHeight); break; case Latte::Types::Center: case Latte::Types::Justify: realGeometry = QRect(view->x(), qMax(view->geometry().y(), view->geometry().center().y() - realHeight / 2), realThickness, realHeight); break; case Latte::Types::Bottom: realGeometry = QRect(view->x(), view->geometry().bottom() - realHeight + 1, realThickness, realHeight); break; } available -= realGeometry; } break; case Plasma::Types::RightEdge: if (view->behaveAsPlasmaPanel()) { QRect viewGeometry = view->geometry(); if (desktopUse) { //! ignore any real window slide outs in all cases viewGeometry.moveLeft(view->screen()->geometry().right() - view->screenEdgeMargin() - viewGeometry.width()); } available -= viewGeometry; } else { QRect realGeometry; int realHeight = view->maxLength() * view->height(); int realX = view->geometry().right() - realThickness + 1; switch (view->alignment()) { case Latte::Types::Top: realGeometry = QRect(realX, view->y(), realThickness, realHeight); break; case Latte::Types::Center: case Latte::Types::Justify: realGeometry = QRect(realX, qMax(view->geometry().y(), view->geometry().center().y() - realHeight / 2), realThickness, realHeight); break; case Latte::Types::Bottom: realGeometry = QRect(realX, view->geometry().bottom() - realHeight + 1, realThickness, realHeight); break; } available -= realGeometry; } break; default: //! bypass clang warnings break; } } } /*qDebug() << "::::: FREE AREAS :::::"; for (int i = 0; i < available.rectCount(); ++i) { qDebug() << available.rects().at(i); } qDebug() << "::::: END OF FREE AREAS :::::";*/ return available; } QRect Corona::availableScreenRect(int id) const { return availableScreenRectWithCriteria(id); } QRect Corona::availableScreenRectWithCriteria(int id, QString forLayout, QList ignoreModes, QList ignoreEdges, bool ignoreExternalPanels, bool desktopUse) const { const QScreen *screen = m_screenPool->screenForId(id); CentralLayout *layout = centralLayout(forLayout); if (!screen) { return {}; } QRect available = ignoreExternalPanels ? screen->geometry() : screen->availableGeometry(); if (!layout) { return available; } //! blacklist irrelevant visibility modes if (!ignoreModes.contains(Latte::Types::None)) { ignoreModes << Latte::Types::None; } if (!ignoreModes.contains(Latte::Types::NormalWindow)) { ignoreModes << Latte::Types::NormalWindow; } bool allEdges = ignoreEdges.isEmpty(); QList views = layout->latteViews(); for (const auto *view : views) { if (view && view->containment() && view->screen() == screen && ((allEdges || !ignoreEdges.contains(view->location())) && (view->visibility() && !ignoreModes.contains(view->visibility()->mode())))) { int appliedThickness = view->behaveAsPlasmaPanel() ? view->screenEdgeMargin() + view->normalThickness() : view->normalThickness(); // Usually availableScreenRect is used by the desktop, // but Latte don't have desktop, then here just // need calculate available space for top and bottom location, // because the left and right are those who dodge others docks switch (view->location()) { case Plasma::Types::TopEdge: if (view->behaveAsPlasmaPanel() && desktopUse) { //! ignore any real window slide outs in all cases available.setTop(qMax(available.top(), view->screen()->geometry().top() + appliedThickness)); } else { available.setTop(qMax(available.top(), view->y() + appliedThickness)); } break; case Plasma::Types::BottomEdge: if (view->behaveAsPlasmaPanel() && desktopUse) { //! ignore any real window slide outs in all cases available.setBottom(qMin(available.bottom(), view->screen()->geometry().bottom() - appliedThickness)); } else { available.setBottom(qMin(available.bottom(), view->y() + view->height() - appliedThickness)); } break; case Plasma::Types::LeftEdge: if (view->behaveAsPlasmaPanel() && desktopUse) { //! ignore any real window slide outs in all cases available.setLeft(qMax(available.left(), view->screen()->geometry().left() + appliedThickness)); } else { available.setLeft(qMax(available.left(), view->x() + appliedThickness)); } break; case Plasma::Types::RightEdge: if (view->behaveAsPlasmaPanel() && desktopUse) { //! ignore any real window slide outs in all cases available.setRight(qMin(available.right(), view->screen()->geometry().right() - appliedThickness)); } else { available.setRight(qMin(available.right(), view->x() + view->width() - appliedThickness)); } break; default: //! bypass clang warnings break; } } } return available; } void Corona::addOutput(QScreen *screen) { Q_ASSERT(screen); int id = m_screenPool->id(screen->name()); if (id == -1) { int newId = m_screenPool->firstAvailableId(); m_screenPool->insertScreenMapping(newId, screen->name()); } connect(screen, &QScreen::geometryChanged, this, [ = ]() { const int id = m_screenPool->id(screen->name()); if (id >= 0) { emit screenGeometryChanged(id); emit availableScreenRegionChanged(); emit availableScreenRectChanged(); } }); emit availableScreenRectChanged(); emit screenAdded(m_screenPool->id(screen->name())); screenCountChanged(); } void Corona::primaryOutputChanged() { m_viewsScreenSyncTimer.start(); } void Corona::screenRemoved(QScreen *screen) { screenCountChanged(); } void Corona::screenCountChanged() { m_viewsScreenSyncTimer.start(); } //! the central functions that updates loading/unloading latteviews //! concerning screen changed (for multi-screen setups mainly) void Corona::syncLatteViewsToScreens() { m_layoutsManager->synchronizer()->syncLatteViewsToScreens(); } int Corona::primaryScreenId() const { return m_screenPool->id(qGuiApp->primaryScreen()->name()); } void Corona::quitApplication() { //! this code must be called asynchronously because it is called //! also from qml (Settings window). QTimer::singleShot(300, [this]() { m_layoutsManager->hideLatteSettingsDialog(); m_layoutsManager->synchronizer()->hideAllViews(); }); //! give the time for the views to hide themselves QTimer::singleShot(800, [this]() { qGuiApp->quit(); }); } void Corona::aboutApplication() { if (aboutDialog) { aboutDialog->hide(); aboutDialog->deleteLater(); } aboutDialog = new KAboutApplicationDialog(KAboutData::applicationData()); connect(aboutDialog.data(), &QDialog::finished, aboutDialog.data(), &QObject::deleteLater); m_wm->skipTaskBar(*aboutDialog); m_wm->setKeepAbove(aboutDialog->winId(), true); aboutDialog->show(); } int Corona::screenForContainment(const Plasma::Containment *containment) const { //FIXME: indexOf is not a proper way to support multi-screen // as for environment to environment the indexes change // also there is the following issue triggered // from latteView adaptToScreen() // // in a multi-screen environment that // primary screen is not set to 0 it was // created an endless showing loop at // startup (catch-up race) between // screen:0 and primaryScreen //case in which this containment is child of an applet, hello systray :) if (Plasma::Applet *parentApplet = qobject_cast(containment->parent())) { if (Plasma::Containment *cont = parentApplet->containment()) { return screenForContainment(cont); } else { return -1; } } Plasma::Containment *c = const_cast(containment); Latte::View *view = m_layoutsManager->synchronizer()->viewForContainment(c); if (view && view->screen()) { return m_screenPool->id(view->screen()->name()); } //Failed? fallback on lastScreen() //lastScreen() is the correct screen for panels //It is also correct for desktops *that have the correct activity()* //a containment with lastScreen() == 0 but another activity, //won't be associated to a screen // qDebug() << "ShellCorona screenForContainment: " << containment << " Last screen is " << containment->lastScreen(); for (auto screen : qGuiApp->screens()) { // containment->lastScreen() == m_screenPool->id(screen->name()) to check if the lastScreen refers to a screen that exists/it's known if (containment->lastScreen() == m_screenPool->id(screen->name()) && (containment->activity() == m_activitiesConsumer->currentActivity() || containment->containmentType() == Plasma::Types::PanelContainment || containment->containmentType() == Plasma::Types::CustomPanelContainment)) { return containment->lastScreen(); } } return -1; } void Corona::showAlternativesForApplet(Plasma::Applet *applet) { const QString alternativesQML = kPackage().filePath("appletalternativesui"); if (alternativesQML.isEmpty()) { return; } Latte::View *latteView = m_layoutsManager->synchronizer()->viewForContainment(applet->containment()); KDeclarative::QmlObjectSharedEngine *qmlObj{nullptr}; if (latteView) { latteView->setAlternativesIsShown(true); qmlObj = new KDeclarative::QmlObjectSharedEngine(latteView); } else { qmlObj = new KDeclarative::QmlObjectSharedEngine(this); } qmlObj->setInitializationDelayed(true); qmlObj->setSource(QUrl::fromLocalFile(alternativesQML)); AlternativesHelper *helper = new AlternativesHelper(applet, qmlObj); qmlObj->rootContext()->setContextProperty(QStringLiteral("alternativesHelper"), helper); m_alternativesObjects << qmlObj; qmlObj->completeInitialization(); //! Alternative dialog signals connect(helper, &QObject::destroyed, this, [latteView]() { latteView->setAlternativesIsShown(false); }); connect(qmlObj->rootObject(), SIGNAL(visibleChanged(bool)), this, SLOT(alternativesVisibilityChanged(bool))); connect(applet, &Plasma::Applet::destroyedChanged, this, [this, qmlObj](bool destroyed) { if (!destroyed) { return; } QMutableListIterator it(m_alternativesObjects); while (it.hasNext()) { KDeclarative::QmlObjectSharedEngine *obj = it.next(); if (obj == qmlObj) { it.remove(); obj->deleteLater(); } } }); } void Corona::alternativesVisibilityChanged(bool visible) { if (visible) { return; } QObject *root = sender(); QMutableListIterator it(m_alternativesObjects); while (it.hasNext()) { KDeclarative::QmlObjectSharedEngine *obj = it.next(); if (obj->rootObject() == root) { it.remove(); obj->deleteLater(); } } } void Corona::addViewForLayout(QString layoutName) { qDebug() << "loading default layout"; //! Setting mutable for create a containment setImmutability(Plasma::Types::Mutable); QVariantList args; auto defaultContainment = createContainmentDelayed("org.kde.latte.containment", args); defaultContainment->setContainmentType(Plasma::Types::PanelContainment); defaultContainment->init(); if (!defaultContainment || !defaultContainment->kPackage().isValid()) { qWarning() << "the requested containment plugin can not be located or loaded"; return; } auto config = defaultContainment->config(); defaultContainment->restore(config); using Plasma::Types; QList edges{Types::BottomEdge, Types::LeftEdge, Types::TopEdge, Types::RightEdge}; Layout::GenericLayout *currentLayout = m_layoutsManager->synchronizer()->layout(layoutName); if (currentLayout) { edges = currentLayout->freeEdges(defaultContainment->screen()); } if ((edges.count() > 0)) { defaultContainment->setLocation(edges.at(0)); } else { defaultContainment->setLocation(Plasma::Types::BottomEdge); } if (m_layoutsManager->memoryUsage() == Latte::Types::MultipleLayouts) { config.writeEntry("layoutId", layoutName); } defaultContainment->updateConstraints(Plasma::Types::StartupCompletedConstraint); defaultContainment->save(config); requestConfigSync(); defaultContainment->flushPendingConstraintsEvents(); emit containmentAdded(defaultContainment); emit containmentCreated(defaultContainment); defaultContainment->createApplet(QStringLiteral("org.kde.latte.plasmoid")); defaultContainment->createApplet(QStringLiteral("org.kde.plasma.analogclock")); } void Corona::loadDefaultLayout() { addViewForLayout(m_layoutsManager->currentLayoutName()); } QStringList Corona::containmentsIds() { QStringList ids; for(const auto containment : containments()) { ids << QString::number(containment->id()); } return ids; } QStringList Corona::appletsIds() { QStringList ids; for(const auto containment : containments()) { auto applets = containment->config().group("Applets"); ids << applets.groupList(); } return ids; } //! Activate launcher menu through dbus interface void Corona::activateLauncherMenu() { m_globalShortcuts->activateLauncherMenu(); } void Corona::windowColorScheme(QString windowIdAndScheme) { int firstSlash = windowIdAndScheme.indexOf("-"); QString windowIdStr = windowIdAndScheme.mid(0, firstSlash); QString schemeStr = windowIdAndScheme.mid(firstSlash + 1); if (KWindowSystem::isPlatformWayland()) { QTimer::singleShot(200, [this, schemeStr]() { //! [Wayland Case] - give the time to be informed correctly for the active window id //! otherwise the active window id may not be the same with the one trigerred //! the color scheme dbus signal QString windowIdStr = m_wm->activeWindow().toString(); m_wm->schemesTracker()->setColorSchemeForWindow(windowIdStr.toUInt(), schemeStr); }); } else { m_wm->schemesTracker()->setColorSchemeForWindow(windowIdStr.toUInt(), schemeStr); } } //! update badge for specific view item void Corona::updateDockItemBadge(QString identifier, QString value) { m_globalShortcuts->updateViewItemBadge(identifier, value); } void Corona::switchToLayout(QString layout) { if ((layout.startsWith("file:/") || layout.startsWith("/")) && layout.endsWith(".layout.latte")) { //! Import and load runtime a layout through dbus interface //! It can be used from external programs that want to update runtime //! the Latte shown layout QString layoutPath = layout; //! cleanup layout path if (layoutPath.startsWith("file:///")) { layoutPath = layout.remove("file://"); } else if (layoutPath.startsWith("file://")) { layoutPath = layout.remove("file:/"); } //! check out layoutpath existence if (QFileInfo(layoutPath).exists()) { qDebug() << " Layout is going to be imported and loaded from file :: " << layoutPath; QString importedLayout = m_layoutsManager->importer()->importLayoutHelper(layoutPath); if (importedLayout.isEmpty()) { qDebug() << i18n("The layout cannot be imported from file :: ") << layoutPath; } else { m_layoutsManager->synchronizer()->loadLayouts(); m_layoutsManager->switchToLayout(importedLayout); } } else { qDebug() << " Layout from missing file can not be imported and loaded :: " << layoutPath; } } else { m_layoutsManager->switchToLayout(layout); } } void Corona::showSettingsWindow(int page) { Settings::Dialog::ConfigurationPage p = Settings::Dialog::LayoutPage; if (page >= Settings::Dialog::LayoutPage && page <= Settings::Dialog::PreferencesPage) { p = static_cast(page); } m_layoutsManager->showLatteSettingsDialog(p); } void Corona::setContextMenuView(int id) { //! set context menu view id m_contextMenuViewId = id; } QStringList Corona::contextMenuData() { QStringList data; Types::ViewType viewType{Types::DockView}; Latte::CentralLayout *currentLayout = m_layoutsManager->currentLayout(); if (currentLayout) { viewType = currentLayout->latteViewType(m_contextMenuViewId); } data << QString::number((int)m_layoutsManager->memoryUsage()); data << m_layoutsManager->currentLayoutName(); data << QString::number((int)viewType); for(const auto &layoutName : m_layoutsManager->menuLayouts()) { if (m_layoutsManager->synchronizer()->centralLayout(layoutName)) { data << QString("1," + layoutName); } else { data << QString("0," + layoutName); } } //! reset context menu view id m_contextMenuViewId = -1; return data; } void Corona::setBackgroundFromBroadcast(QString activity, QString screenName, QString filename) { if (filename.startsWith("file://")) { filename = filename.remove(0,7); } QMetaObject::invokeMethod(m_backgroundTracer->rootObject(), "setBackgroundFromBroadcast", Q_ARG(QVariant, activity), Q_ARG(QVariant, screenName), Q_ARG(QVariant, filename)); } void Corona::setBroadcastedBackgroundsEnabled(QString activity, QString screenName, bool enabled) { QMetaObject::invokeMethod(m_backgroundTracer->rootObject(), "setBroadcastedBackgroundsEnabled", Q_ARG(QVariant, activity), Q_ARG(QVariant, screenName), Q_ARG(QVariant, enabled)); } void Corona::toggleHiddenState(QString layoutName, QString screenName, int screenEdge) { Layout::GenericLayout *gLayout = layout(layoutName); if (gLayout) { gLayout->toggleHiddenState(screenName, (Plasma::Types::Location)screenEdge); } } void Corona::importFullConfiguration(const QString &file) { m_importFullConfigurationFile = file; quitApplication(); } inline void Corona::qmlRegisterTypes() const { + qmlRegisterUncreatableMetaObject(Latte::Settings::staticMetaObject, + "org.kde.latte.private.app", // import statement + 0, 1, // major and minor version of the import + "Settings", // name in QML + "Error: only enums of latte app settings"); + #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) qmlRegisterType(); qmlRegisterType(); qmlRegisterType(); qmlRegisterType(); qmlRegisterType(); qmlRegisterType(); qmlRegisterType(); #else qmlRegisterAnonymousType("latte-dock", 1); qmlRegisterAnonymousType("latte-dock", 1); qmlRegisterAnonymousType("latte-dock", 1); qmlRegisterAnonymousType("latte-dock", 1); qmlRegisterAnonymousType("latte-dock", 1); qmlRegisterAnonymousType("latte-dock", 1); qmlRegisterAnonymousType("latte-dock", 1); #endif } } diff --git a/app/settings/data/preferencesdata.cpp b/app/settings/data/preferencesdata.cpp index 25101b95..9272978a 100644 --- a/app/settings/data/preferencesdata.cpp +++ b/app/settings/data/preferencesdata.cpp @@ -1,144 +1,144 @@ /* * Copyright 2020 Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "preferencesdata.h" namespace Latte { namespace Settings { namespace Data { const bool Preferences::BADGE3DSTYLE; const bool Preferences::LAYOUTSINFORMATIONWINDOW; const bool Preferences::AUTOSTART; const bool Preferences::BORDERLESSMAXIMIZED; const bool Preferences::METAPRESSFORAPPLAUNCHER; const bool Preferences::METAHOLDFORBADGES; const int Preferences::SCREENSDELAY; const int Preferences::OUTLINEWIDTH; -const Latte::Types::MouseSensitivity Preferences::MOUSESENSITIVITY; +const Settings::MouseSensitivity Preferences::MOUSESENSITIVITY; Preferences::Preferences() { } Preferences::Preferences(Preferences &&o) : badgeStyle3D(o.badgeStyle3D), layoutsInformationWindow(o.layoutsInformationWindow), autostart(o.autostart), borderlessMaximized(o.borderlessMaximized), metaPressForAppLauncher(o.metaPressForAppLauncher), metaHoldForBadges(o.metaHoldForBadges), mouseSensitivity(o.mouseSensitivity), screensDelay(o.screensDelay), outlineWidth(o.outlineWidth) { } Preferences::Preferences(const Preferences &o) : badgeStyle3D(o.badgeStyle3D), layoutsInformationWindow(o.layoutsInformationWindow), autostart(o.autostart), borderlessMaximized(o.borderlessMaximized), metaPressForAppLauncher(o.metaPressForAppLauncher), metaHoldForBadges(o.metaHoldForBadges), mouseSensitivity(o.mouseSensitivity), screensDelay(o.screensDelay), outlineWidth(o.outlineWidth) { } Preferences &Preferences::operator=(const Preferences &rhs) { badgeStyle3D = rhs.badgeStyle3D; layoutsInformationWindow = rhs.layoutsInformationWindow; autostart = rhs.autostart; borderlessMaximized = rhs.borderlessMaximized; metaPressForAppLauncher = rhs.metaPressForAppLauncher; metaHoldForBadges = rhs.metaHoldForBadges; mouseSensitivity = rhs.mouseSensitivity; screensDelay = rhs.screensDelay; outlineWidth = rhs.outlineWidth; return (*this); } Preferences &Preferences::operator=(Preferences &&rhs) { badgeStyle3D = rhs.badgeStyle3D; layoutsInformationWindow = rhs.layoutsInformationWindow; autostart = rhs.autostart; borderlessMaximized = rhs.borderlessMaximized; metaPressForAppLauncher = rhs.metaPressForAppLauncher; metaHoldForBadges = rhs.metaHoldForBadges; mouseSensitivity = rhs.mouseSensitivity; screensDelay = rhs.screensDelay; outlineWidth = rhs.outlineWidth; return (*this); } bool Preferences::operator==(const Preferences &rhs) const { return (badgeStyle3D == rhs.badgeStyle3D) && (layoutsInformationWindow == rhs.layoutsInformationWindow) && (autostart == rhs.autostart) && (borderlessMaximized == rhs.borderlessMaximized) && (metaPressForAppLauncher == rhs.metaPressForAppLauncher) && (metaHoldForBadges == rhs.metaHoldForBadges) && (mouseSensitivity == rhs.mouseSensitivity) && (screensDelay == rhs.screensDelay) && (outlineWidth == rhs.outlineWidth); } bool Preferences::operator!=(const Preferences &rhs) const { return !(*this == rhs); } bool Preferences::inDefaultValues() const { return (badgeStyle3D == BADGE3DSTYLE) && (layoutsInformationWindow == LAYOUTSINFORMATIONWINDOW) && (autostart == AUTOSTART) && (borderlessMaximized == BORDERLESSMAXIMIZED) && (metaPressForAppLauncher == METAPRESSFORAPPLAUNCHER) && (metaHoldForBadges == METAHOLDFORBADGES) && (mouseSensitivity == MOUSESENSITIVITY) && (screensDelay == SCREENSDELAY) && (outlineWidth == OUTLINEWIDTH); } void Preferences::setToDefaults() { badgeStyle3D = BADGE3DSTYLE; layoutsInformationWindow = LAYOUTSINFORMATIONWINDOW; autostart = AUTOSTART; borderlessMaximized = BORDERLESSMAXIMIZED; metaPressForAppLauncher = METAPRESSFORAPPLAUNCHER; metaHoldForBadges = METAHOLDFORBADGES; mouseSensitivity = MOUSESENSITIVITY; screensDelay = SCREENSDELAY; outlineWidth = OUTLINEWIDTH; } } } } diff --git a/app/settings/data/preferencesdata.h b/app/settings/data/preferencesdata.h index 3416765e..6bb3387b 100644 --- a/app/settings/data/preferencesdata.h +++ b/app/settings/data/preferencesdata.h @@ -1,73 +1,73 @@ /* * Copyright 2020 Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #ifndef SETTINGSDATAPREFERENCES_H #define SETTINGSDATAPREFERENCES_H -// Latte -#include +// local +#include "../../apptypes.h" namespace Latte { namespace Settings { namespace Data { class Preferences { public: static const bool BADGE3DSTYLE = true; static const bool LAYOUTSINFORMATIONWINDOW = true; static const bool AUTOSTART = true; static const bool BORDERLESSMAXIMIZED = false; static const bool METAPRESSFORAPPLAUNCHER = false; static const bool METAHOLDFORBADGES = true; static const int SCREENSDELAY = 2500; static const int OUTLINEWIDTH = 1; - static const Latte::Types::MouseSensitivity MOUSESENSITIVITY = Latte::Types::HighSensitivity; + static const Settings::MouseSensitivity MOUSESENSITIVITY = Settings::HighMouseSensitivity; Preferences(); Preferences(Preferences &&o); Preferences(const Preferences &o); //! Preferences data bool badgeStyle3D{BADGE3DSTYLE}; bool layoutsInformationWindow{LAYOUTSINFORMATIONWINDOW}; bool autostart{AUTOSTART}; bool borderlessMaximized{BORDERLESSMAXIMIZED}; bool metaPressForAppLauncher{METAPRESSFORAPPLAUNCHER}; bool metaHoldForBadges{METAHOLDFORBADGES}; int screensDelay{SCREENSDELAY}; int outlineWidth{OUTLINEWIDTH}; - Latte::Types::MouseSensitivity mouseSensitivity{MOUSESENSITIVITY}; + Settings::MouseSensitivity mouseSensitivity{MOUSESENSITIVITY}; bool inDefaultValues() const; void setToDefaults(); //! Operators Preferences &operator=(const Preferences &rhs); Preferences &operator=(Preferences &&rhs); bool operator==(const Preferences &rhs) const; bool operator!=(const Preferences &rhs) const; }; } } } #endif diff --git a/app/settings/handlers/tabpreferenceshandler.cpp b/app/settings/handlers/tabpreferenceshandler.cpp index ce56c21f..3af61655 100644 --- a/app/settings/handlers/tabpreferenceshandler.cpp +++ b/app/settings/handlers/tabpreferenceshandler.cpp @@ -1,188 +1,189 @@ /* * Copyright 2020 Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "tabpreferenceshandler.h" //! local #include "ui_settingsdialog.h" #include "../universalsettings.h" #include "../dialogs/settingsdialog.h" +#include "../../apptypes.h" #include "../../lattecorona.h" #include "../../plasma/extended/theme.h" // Latte #include namespace Latte { namespace Settings { namespace Handler { TabPreferences::TabPreferences(Latte::Settings::Dialog::SettingsDialog *parent) : Generic(parent), m_parentDialog(parent), m_corona(m_parentDialog->corona()), m_ui(m_parentDialog->ui()) { initSettings(); initUi(); } void TabPreferences::initUi() { //! exclusive group m_mouseSensitivityButtons = new QButtonGroup(this); - m_mouseSensitivityButtons->addButton(m_ui->lowSensitivityBtn, Latte::Types::LowSensitivity); - m_mouseSensitivityButtons->addButton(m_ui->mediumSensitivityBtn, Latte::Types::MediumSensitivity); - m_mouseSensitivityButtons->addButton(m_ui->highSensitivityBtn, Latte::Types::HighSensitivity); + m_mouseSensitivityButtons->addButton(m_ui->lowSensitivityBtn, Latte::Settings::LowMouseSensitivity); + m_mouseSensitivityButtons->addButton(m_ui->mediumSensitivityBtn, Latte::Settings::MediumMouseSensitivity); + m_mouseSensitivityButtons->addButton(m_ui->highSensitivityBtn, Latte::Settings::HighMouseSensitivity); m_mouseSensitivityButtons->setExclusive(true); //! signals connect(m_mouseSensitivityButtons, static_cast(&QButtonGroup::buttonToggled), [ = ](int id, bool checked) { if (checked) { - m_preferences.mouseSensitivity = static_cast(id); + m_preferences.mouseSensitivity = static_cast(id); emit dataChanged(); } }); connect(m_ui->screenTrackerSpinBox, QOverload::of(&QSpinBox::valueChanged), [ = ](int i) { m_preferences.screensDelay = m_ui->screenTrackerSpinBox->value(); emit dataChanged(); }); connect(m_ui->outlineSpinBox, QOverload::of(&QSpinBox::valueChanged), [ = ](int i) { m_preferences.outlineWidth = m_ui->outlineSpinBox->value(); emit dataChanged(); }); connect(m_ui->autostartChkBox, &QCheckBox::stateChanged, this, [&]() { m_preferences.autostart = m_ui->autostartChkBox->isChecked(); emit dataChanged(); }); connect(m_ui->badges3DStyleChkBox, &QCheckBox::stateChanged, this, [&]() { m_preferences.badgeStyle3D = m_ui->badges3DStyleChkBox->isChecked(); emit dataChanged(); }); connect(m_ui->metaPressChkBox, &QCheckBox::stateChanged, this, [&]() { m_preferences.metaPressForAppLauncher = m_ui->metaPressChkBox->isChecked(); emit dataChanged(); }); connect(m_ui->metaPressHoldChkBox, &QCheckBox::stateChanged, this, [&]() { m_preferences.metaHoldForBadges = m_ui->metaPressHoldChkBox->isChecked(); emit dataChanged(); }); connect(m_ui->infoWindowChkBox, &QCheckBox::stateChanged, this, [&]() { m_preferences.layoutsInformationWindow = m_ui->infoWindowChkBox->isChecked(); emit dataChanged(); }); connect(m_ui->noBordersForMaximizedChkBox, &QCheckBox::stateChanged, this, [&]() { m_preferences.borderlessMaximized = m_ui->noBordersForMaximizedChkBox->isChecked(); emit dataChanged(); }); } void TabPreferences::initSettings() { o_preferences.autostart = m_corona->universalSettings()->autostart(); o_preferences.badgeStyle3D = m_corona->universalSettings()->badges3DStyle(); o_preferences.layoutsInformationWindow = m_corona->universalSettings()->showInfoWindow(); o_preferences.metaPressForAppLauncher = m_corona->universalSettings()->kwin_metaForwardedToLatte(); o_preferences.metaHoldForBadges = m_corona->universalSettings()->metaPressAndHoldEnabled(); o_preferences.borderlessMaximized = m_corona->universalSettings()->canDisableBorders(); - o_preferences.mouseSensitivity = m_corona->universalSettings()->mouseSensitivity(); + o_preferences.mouseSensitivity = m_corona->universalSettings()->sensitivity(); o_preferences.screensDelay = m_corona->universalSettings()->screenTrackerInterval(); o_preferences.outlineWidth = m_corona->themeExtended()->outlineWidth(); m_preferences = o_preferences; updateUi(); } void TabPreferences::updateUi() { //! ui load m_ui->autostartChkBox->setChecked(m_preferences.autostart); m_ui->badges3DStyleChkBox->setChecked(m_preferences.badgeStyle3D); m_ui->infoWindowChkBox->setChecked(m_preferences.layoutsInformationWindow); m_ui->metaPressChkBox->setChecked(m_preferences.metaPressForAppLauncher); m_ui->metaPressHoldChkBox->setChecked(m_preferences.metaHoldForBadges); m_ui->noBordersForMaximizedChkBox->setChecked(m_preferences.borderlessMaximized); m_ui->screenTrackerSpinBox->setValue(m_preferences.screensDelay); m_ui->outlineSpinBox->setValue(m_preferences.outlineWidth); - if (m_preferences.mouseSensitivity == Types::LowSensitivity) { + if (m_preferences.mouseSensitivity == Settings::LowMouseSensitivity) { m_ui->lowSensitivityBtn->setChecked(true); - } else if (m_preferences.mouseSensitivity == Types::MediumSensitivity) { + } else if (m_preferences.mouseSensitivity == Settings::MediumMouseSensitivity) { m_ui->mediumSensitivityBtn->setChecked(true); - } else if (m_preferences.mouseSensitivity == Types::HighSensitivity) { + } else if (m_preferences.mouseSensitivity == Settings::HighMouseSensitivity) { m_ui->highSensitivityBtn->setChecked(true); } emit dataChanged(); } bool TabPreferences::dataAreChanged() const { return o_preferences != m_preferences; } bool TabPreferences::inDefaultValues() const { return m_preferences.inDefaultValues(); } void TabPreferences::reset() { m_preferences = o_preferences; updateUi(); } void TabPreferences::resetDefaults() { m_preferences.setToDefaults(); updateUi(); } void TabPreferences::save() { - m_corona->universalSettings()->setMouseSensitivity(m_preferences.mouseSensitivity); + m_corona->universalSettings()->setSensitivity(m_preferences.mouseSensitivity); m_corona->universalSettings()->setAutostart(m_preferences.autostart); m_corona->universalSettings()->setBadges3DStyle(m_preferences.badgeStyle3D); m_corona->universalSettings()->kwin_forwardMetaToLatte(m_preferences.metaPressForAppLauncher); m_corona->universalSettings()->setMetaPressAndHoldEnabled(m_preferences.metaHoldForBadges); m_corona->universalSettings()->setShowInfoWindow(m_preferences.layoutsInformationWindow); m_corona->universalSettings()->setCanDisableBorders(m_preferences.borderlessMaximized); m_corona->universalSettings()->setScreenTrackerInterval(m_preferences.screensDelay); m_corona->themeExtended()->setOutlineWidth(m_preferences.outlineWidth); o_preferences = m_preferences; emit dataChanged(); } } } } diff --git a/app/settings/universalsettings.cpp b/app/settings/universalsettings.cpp index dbff8c45..8f94179e 100644 --- a/app/settings/universalsettings.cpp +++ b/app/settings/universalsettings.cpp @@ -1,571 +1,571 @@ /* * Copyright 2017 Smith AR * Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "universalsettings.h" // local #include "../layouts/importer.h" #include "../layouts/manager.h" // Qt #include #include #include #include // KDE #include #include #define KWINMETAFORWARDTOLATTESTRING "org.kde.lattedock,/Latte,org.kde.LatteDock,activateLauncherMenu" #define KWINMETAFORWARDTOPLASMASTRING "org.kde.plasmashell,/PlasmaShell,org.kde.PlasmaShell,activateLauncherMenu" #define KWINCOLORSSCRIPT "kwin/scripts/lattewindowcolors" #define KWINRC "/.config/kwinrc" #define KWINRCTRACKERINTERVAL 2500 namespace Latte { UniversalSettings::UniversalSettings(KSharedConfig::Ptr config, QObject *parent) : QObject(parent), m_config(config), m_universalGroup(KConfigGroup(config, QStringLiteral("UniversalSettings"))) { m_corona = qobject_cast(parent); connect(this, &UniversalSettings::badges3DStyleChanged, this, &UniversalSettings::saveConfig); connect(this, &UniversalSettings::canDisableBordersChanged, this, &UniversalSettings::saveConfig); connect(this, &UniversalSettings::currentLayoutNameChanged, this, &UniversalSettings::saveConfig); connect(this, &UniversalSettings::lastNonAssignedLayoutNameChanged, this, &UniversalSettings::saveConfig); connect(this, &UniversalSettings::launchersChanged, this, &UniversalSettings::saveConfig); connect(this, &UniversalSettings::layoutsMemoryUsageChanged, this, &UniversalSettings::saveConfig); connect(this, &UniversalSettings::metaPressAndHoldEnabledChanged, this, &UniversalSettings::saveConfig); - connect(this, &UniversalSettings::mouseSensitivityChanged, this, &UniversalSettings::saveConfig); + connect(this, &UniversalSettings::sensitivityChanged, this, &UniversalSettings::saveConfig); connect(this, &UniversalSettings::screenTrackerIntervalChanged, this, &UniversalSettings::saveConfig); connect(this, &UniversalSettings::showInfoWindowChanged, this, &UniversalSettings::saveConfig); connect(this, &UniversalSettings::versionChanged, this, &UniversalSettings::saveConfig); connect(this, &UniversalSettings::screenScalesChanged, this, &UniversalSettings::saveScalesConfig); connect(qGuiApp, &QGuiApplication::screenAdded, this, &UniversalSettings::screensCountChanged); connect(qGuiApp, &QGuiApplication::screenRemoved, this, &UniversalSettings::screensCountChanged); } UniversalSettings::~UniversalSettings() { saveConfig(); cleanupSettings(); } void UniversalSettings::load() { //! check if user has set the autostart option bool autostartUserSet = m_universalGroup.readEntry("userConfiguredAutostart", false); if (!autostartUserSet && !autostart()) { setAutostart(true); } //! init screen scales m_screenScalesGroup = m_universalGroup.group("ScreenScales"); //! load configuration loadConfig(); //! Track KWin Colors Script Presence updateColorsScriptIsPresent(); QStringList colorsScriptPaths = Layouts::Importer::standardPathsFor(KWINCOLORSSCRIPT); for(auto path: colorsScriptPaths) { KDirWatch::self()->addDir(path); } //! Track KWin rc options const QString kwinrcFilePath = QDir::homePath() + KWINRC; KDirWatch::self()->addFile(kwinrcFilePath); recoverKWinOptions(); m_kwinrcTrackerTimer.setSingleShot(true); m_kwinrcTrackerTimer.setInterval(KWINRCTRACKERINTERVAL); connect(&m_kwinrcTrackerTimer, &QTimer::timeout, this, &UniversalSettings::recoverKWinOptions); connect(KDirWatch::self(), &KDirWatch::created, this, &UniversalSettings::trackedFileChanged); connect(KDirWatch::self(), &KDirWatch::deleted, this, &UniversalSettings::trackedFileChanged); connect(KDirWatch::self(), &KDirWatch::dirty, this, &UniversalSettings::trackedFileChanged); //! this is needed to inform globalshortcuts to update its modifiers tracking emit metaPressAndHoldEnabledChanged(); } bool UniversalSettings::showInfoWindow() const { return m_showInfoWindow; } void UniversalSettings::setShowInfoWindow(bool show) { if (m_showInfoWindow == show) { return; } m_showInfoWindow = show; emit showInfoWindowChanged(); } int UniversalSettings::version() const { return m_version; } void UniversalSettings::setVersion(int ver) { if (m_version == ver) { return; } m_version = ver; qDebug() << "Universal Settings version updated to : " << m_version; emit versionChanged(); } int UniversalSettings::screenTrackerInterval() const { return m_screenTrackerInterval; } void UniversalSettings::setScreenTrackerInterval(int duration) { if (m_screenTrackerInterval == duration) { return; } m_screenTrackerInterval = duration; emit screenTrackerIntervalChanged(); } QString UniversalSettings::currentLayoutName() const { return m_currentLayoutName; } void UniversalSettings::setCurrentLayoutName(QString layoutName) { if (m_currentLayoutName == layoutName) { return; } m_currentLayoutName = layoutName; emit currentLayoutNameChanged(); } QString UniversalSettings::lastNonAssignedLayoutName() const { return m_lastNonAssignedLayoutName; } void UniversalSettings::setLastNonAssignedLayoutName(QString layoutName) { if (m_lastNonAssignedLayoutName == layoutName) { return; } m_lastNonAssignedLayoutName = layoutName; emit lastNonAssignedLayoutNameChanged(); } QStringList UniversalSettings::launchers() const { return m_launchers; } void UniversalSettings::setLaunchers(QStringList launcherList) { if (m_launchers == launcherList) { return; } m_launchers = launcherList; emit launchersChanged(); } bool UniversalSettings::autostart() const { QFile autostartFile(QDir::homePath() + "/.config/autostart/org.kde.latte-dock.desktop"); return autostartFile.exists(); } void UniversalSettings::setAutostart(bool state) { //! remove old autostart file QFile oldAutostartFile(QDir::homePath() + "/.config/autostart/latte-dock.desktop"); if (oldAutostartFile.exists()) { oldAutostartFile.remove(); } //! end of removal of old autostart file QFile autostartFile(QDir::homePath() + "/.config/autostart/org.kde.latte-dock.desktop"); QFile metaFile(Layouts::Importer::standardPath("applications/org.kde.latte-dock.desktop", false)); if (!state && autostartFile.exists()) { //! the first time that the user disables the autostart, this is recorded //! and from now own it will not be recreated it in the beginning if (!m_universalGroup.readEntry("userConfiguredAutostart", false)) { m_universalGroup.writeEntry("userConfiguredAutostart", true); } autostartFile.remove(); emit autostartChanged(); } else if (state && metaFile.exists()) { //! check if autostart folder exists and create otherwise QDir autostartDir(QDir::homePath() + "/.config/autostart"); if (!autostartDir.exists()) { QDir configDir(QDir::homePath() + "/.config"); configDir.mkdir("autostart"); } metaFile.copy(autostartFile.fileName()); //! I haven't added the flag "OnlyShowIn=KDE;" into the autostart file //! because I fall onto a Plasma 5.8 case that this flag //! didn't let the plasma desktop to start emit autostartChanged(); } } bool UniversalSettings::badges3DStyle() const { return m_badges3DStyle; } void UniversalSettings::setBadges3DStyle(bool enable) { if (m_badges3DStyle == enable) { return; } m_badges3DStyle = enable; emit badges3DStyleChanged(); } bool UniversalSettings::canDisableBorders() const { return m_canDisableBorders; } void UniversalSettings::setCanDisableBorders(bool enable) { if (m_canDisableBorders == enable) { return; } m_canDisableBorders = enable; emit canDisableBordersChanged(); } bool UniversalSettings::colorsScriptIsPresent() const { return m_colorsScriptIsPresent; } void UniversalSettings::setColorsScriptIsPresent(bool present) { if (m_colorsScriptIsPresent == present) { return; } m_colorsScriptIsPresent = present; emit colorsScriptIsPresentChanged(); } void UniversalSettings::updateColorsScriptIsPresent() { qDebug() << "Updating Latte Colors Script presence..."; setColorsScriptIsPresent(!Layouts::Importer::standardPath(KWINCOLORSSCRIPT).isEmpty()); } void UniversalSettings::trackedFileChanged(const QString &file) { if (file.endsWith(KWINCOLORSSCRIPT)) { updateColorsScriptIsPresent(); } if (file.endsWith(KWINRC)) { m_kwinrcTrackerTimer.start(); } } bool UniversalSettings::kwin_metaForwardedToLatte() const { return m_kwinMetaForwardedToLatte; } bool UniversalSettings::kwin_borderlessMaximizedWindowsEnabled() const { return m_kwinBorderlessMaximizedWindows; } void UniversalSettings::kwin_forwardMetaToLatte(bool forward) { if (m_kwinMetaForwardedToLatte == forward) { return; } QProcess process; QStringList parameters; parameters << "--file" << "kwinrc" << "--group" << "ModifierOnlyShortcuts" << "--key" << "Meta"; if (forward) { parameters << KWINMETAFORWARDTOLATTESTRING; } else { parameters << KWINMETAFORWARDTOPLASMASTRING; } process.start("kwriteconfig5", parameters); process.waitForFinished(); QDBusInterface iface("org.kde.KWin", "/KWin", "", QDBusConnection::sessionBus()); if (iface.isValid()) { iface.call("reconfigure"); } } void UniversalSettings::kwin_setDisabledMaximizedBorders(bool disable) { if (m_kwinBorderlessMaximizedWindows == disable) { return; } QString disableText = disable ? "true" : "false"; QProcess process; QString commandStr = "kwriteconfig5 --file kwinrc --group Windows --key BorderlessMaximizedWindows --type bool " + disableText; process.start(commandStr); process.waitForFinished(); QDBusInterface iface("org.kde.KWin", "/KWin", "", QDBusConnection::sessionBus()); if (iface.isValid()) { iface.call("reconfigure"); } } void UniversalSettings::recoverKWinOptions() { qDebug() << "kwinrc: recovering values..."; //! Meta forwarded to Latte option QProcess process; process.start("kreadconfig5 --file kwinrc --group ModifierOnlyShortcuts --key Meta"); process.waitForFinished(); QString output(process.readAllStandardOutput()); output = output.remove("\n"); m_kwinMetaForwardedToLatte = (output == KWINMETAFORWARDTOLATTESTRING); //! BorderlessMaximizedWindows option process.start("kreadconfig5 --file kwinrc --group Windows --key BorderlessMaximizedWindows"); process.waitForFinished(); output = process.readAllStandardOutput(); output = output.remove("\n"); m_kwinBorderlessMaximizedWindows = (output == "true"); } bool UniversalSettings::metaPressAndHoldEnabled() const { return m_metaPressAndHoldEnabled; } void UniversalSettings::setMetaPressAndHoldEnabled(bool enabled) { if (m_metaPressAndHoldEnabled == enabled) { return; } m_metaPressAndHoldEnabled = enabled; emit metaPressAndHoldEnabledChanged(); } Types::LayoutsMemoryUsage UniversalSettings::layoutsMemoryUsage() const { return m_memoryUsage; } void UniversalSettings::setLayoutsMemoryUsage(Types::LayoutsMemoryUsage layoutsMemoryUsage) { if (m_memoryUsage == layoutsMemoryUsage) { return; } m_memoryUsage = layoutsMemoryUsage; emit layoutsMemoryUsageChanged(); } -Types::MouseSensitivity UniversalSettings::mouseSensitivity() const +Settings::MouseSensitivity UniversalSettings::sensitivity() { - return m_mouseSensitivity; + return m_sensitivity; } -void UniversalSettings::setMouseSensitivity(Types::MouseSensitivity sensitivity) +void UniversalSettings::setSensitivity(Settings::MouseSensitivity sense) { - if (m_mouseSensitivity == sensitivity) { + if (m_sensitivity == sense) { return; } - m_mouseSensitivity = sensitivity; - emit mouseSensitivityChanged(); + m_sensitivity = sense; + emit sensitivityChanged(); } float UniversalSettings::screenWidthScale(QString screenName) const { if (!m_screenScales.contains(screenName)) { return 1; } return m_screenScales[screenName].first; } float UniversalSettings::screenHeightScale(QString screenName) const { if (!m_screenScales.contains(screenName)) { return 1; } return m_screenScales[screenName].second; } void UniversalSettings::setScreenScales(QString screenName, float widthScale, float heightScale) { if (!m_screenScales.contains(screenName)) { m_screenScales[screenName].first = widthScale; m_screenScales[screenName].second = heightScale; } else { if (m_screenScales[screenName].first == widthScale && m_screenScales[screenName].second == heightScale) { return; } m_screenScales[screenName].first = widthScale; m_screenScales[screenName].second = heightScale; } emit screenScalesChanged(); } void UniversalSettings::loadConfig() { m_version = m_universalGroup.readEntry("version", 1); m_badges3DStyle = m_universalGroup.readEntry("badges3DStyle", false); m_canDisableBorders = m_universalGroup.readEntry("canDisableBorders", false); m_currentLayoutName = m_universalGroup.readEntry("currentLayout", QString()); m_lastNonAssignedLayoutName = m_universalGroup.readEntry("lastNonAssignedLayout", QString()); m_launchers = m_universalGroup.readEntry("launchers", QStringList()); m_metaPressAndHoldEnabled = m_universalGroup.readEntry("metaPressAndHoldEnabled", true); m_screenTrackerInterval = m_universalGroup.readEntry("screenTrackerInterval", 2500); m_showInfoWindow = m_universalGroup.readEntry("showInfoWindow", true); m_memoryUsage = static_cast(m_universalGroup.readEntry("memoryUsage", (int)Types::SingleLayout)); - m_mouseSensitivity = static_cast(m_universalGroup.readEntry("mouseSensitivity", (int)Types::HighSensitivity)); + m_sensitivity = static_cast(m_universalGroup.readEntry("mouseSensitivity", (int)Settings::HighMouseSensitivity)); loadScalesConfig(); } void UniversalSettings::saveConfig() { m_universalGroup.writeEntry("version", m_version); m_universalGroup.writeEntry("badges3DStyle", m_badges3DStyle); m_universalGroup.writeEntry("canDisableBorders", m_canDisableBorders); m_universalGroup.writeEntry("currentLayout", m_currentLayoutName); m_universalGroup.writeEntry("lastNonAssignedLayout", m_lastNonAssignedLayoutName); m_universalGroup.writeEntry("launchers", m_launchers); m_universalGroup.writeEntry("metaPressAndHoldEnabled", m_metaPressAndHoldEnabled); m_universalGroup.writeEntry("screenTrackerInterval", m_screenTrackerInterval); m_universalGroup.writeEntry("showInfoWindow", m_showInfoWindow); m_universalGroup.writeEntry("memoryUsage", (int)m_memoryUsage); - m_universalGroup.writeEntry("mouseSensitivity", (int)m_mouseSensitivity); + m_universalGroup.writeEntry("mouseSensitivity", (int)m_sensitivity); m_universalGroup.sync(); } void UniversalSettings::cleanupSettings() { KConfigGroup containments = KConfigGroup(m_config, QStringLiteral("Containments")); containments.deleteGroup(); containments.sync(); } QString UniversalSettings::splitterIconPath() { return m_corona->kPackage().filePath("splitter"); } QString UniversalSettings::trademarkIconPath() { return m_corona->kPackage().filePath("trademark"); } QQmlListProperty UniversalSettings::screens() { return QQmlListProperty(this, nullptr, &countScreens, &atScreens); } int UniversalSettings::countScreens(QQmlListProperty *property) { Q_UNUSED(property) return qGuiApp->screens().count(); } QScreen *UniversalSettings::atScreens(QQmlListProperty *property, int index) { Q_UNUSED(property) return qGuiApp->screens().at(index); } void UniversalSettings::loadScalesConfig() { for (const auto &screenName : m_screenScalesGroup.keyList()) { QString scalesStr = m_screenScalesGroup.readEntry(screenName, QString()); QStringList scales = scalesStr.split(";"); if (scales.count() == 2) { m_screenScales[screenName] = qMakePair(scales[0].toFloat(), scales[1].toFloat()); } } } void UniversalSettings::saveScalesConfig() { for (const auto &screenName : m_screenScales.keys()) { QStringList scales; scales << QString::number(m_screenScales[screenName].first) << QString::number(m_screenScales[screenName].second); m_screenScalesGroup.writeEntry(screenName, scales.join(";")); } m_screenScalesGroup.sync(); } } diff --git a/app/settings/universalsettings.h b/app/settings/universalsettings.h index c07368c0..0e42aee4 100644 --- a/app/settings/universalsettings.h +++ b/app/settings/universalsettings.h @@ -1,211 +1,212 @@ /* * Copyright 2017 Smith AR * Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef UNIVERSALSETTINGS_H #define UNIVERSALSETTINGS_H // local +#include "../apptypes.h" #include "../lattecorona.h" // Qt #include #include #include #include #include #include #include // KDE #include #include // Latte #include namespace Latte { namespace Layouts { class Manager; } } namespace Latte { //width_scale, height_scale typedef QPair ScreenScales; //! This class holds all the settings that are universally available //! independent of layouts class UniversalSettings : public QObject { Q_OBJECT Q_PROPERTY(bool autostart READ autostart WRITE setAutostart NOTIFY autostartChanged) Q_PROPERTY(bool badges3DStyle READ badges3DStyle WRITE setBadges3DStyle NOTIFY badges3DStyleChanged) Q_PROPERTY(bool colorsScriptIsPresent READ colorsScriptIsPresent NOTIFY colorsScriptIsPresentChanged) Q_PROPERTY(bool showInfoWindow READ showInfoWindow WRITE setShowInfoWindow NOTIFY showInfoWindowChanged) Q_PROPERTY(QString currentLayoutName READ currentLayoutName WRITE setCurrentLayoutName NOTIFY currentLayoutNameChanged) Q_PROPERTY(QStringList launchers READ launchers WRITE setLaunchers NOTIFY launchersChanged) - Q_PROPERTY(Latte::Types::MouseSensitivity mouseSensitivity READ mouseSensitivity WRITE setMouseSensitivity NOTIFY mouseSensitivityChanged) + Q_PROPERTY(Latte::Settings::MouseSensitivity sensitivity READ sensitivity WRITE setSensitivity NOTIFY sensitivityChanged) Q_PROPERTY(QQmlListProperty screens READ screens) public: UniversalSettings(KSharedConfig::Ptr config, QObject *parent = nullptr); ~UniversalSettings() override; void load(); bool autostart() const; void setAutostart(bool state); bool badges3DStyle() const; void setBadges3DStyle(bool enable); bool canDisableBorders() const; void setCanDisableBorders(bool enable); bool colorsScriptIsPresent() const; bool kwin_metaForwardedToLatte() const; void kwin_forwardMetaToLatte(bool forward); bool kwin_borderlessMaximizedWindowsEnabled() const; void kwin_setDisabledMaximizedBorders(bool disable); bool metaPressAndHoldEnabled() const; void setMetaPressAndHoldEnabled(bool enabled); bool showInfoWindow() const; void setShowInfoWindow(bool show); int version() const; void setVersion(int ver); int screenTrackerInterval() const; void setScreenTrackerInterval(int duration); QString currentLayoutName() const; void setCurrentLayoutName(QString layoutName); QString lastNonAssignedLayoutName() const; void setLastNonAssignedLayoutName(QString layoutName); QStringList launchers() const; void setLaunchers(QStringList launcherList); - Types::MouseSensitivity mouseSensitivity() const; - void setMouseSensitivity(Types::MouseSensitivity sensitivity); + Settings::MouseSensitivity sensitivity(); + void setSensitivity(Settings::MouseSensitivity sense); QQmlListProperty screens(); static int countScreens(QQmlListProperty *property); //! is needed by screens() static QScreen *atScreens(QQmlListProperty *property, int index); //! is needed by screens() public slots: Q_INVOKABLE QString splitterIconPath(); Q_INVOKABLE QString trademarkIconPath(); Q_INVOKABLE float screenWidthScale(QString screenName) const; Q_INVOKABLE float screenHeightScale(QString screenName) const; Q_INVOKABLE void setScreenScales(QString screenName, float widthScale, float heightScale); signals: void autostartChanged(); void badges3DStyleChanged(); void canDisableBordersChanged(); void colorsScriptIsPresentChanged(); void currentLayoutNameChanged(); void downloadWindowSizeChanged(); void lastNonAssignedLayoutNameChanged(); void layoutsColumnWidthsChanged(); void layoutsWindowSizeChanged(); void launchersChanged(); void layoutsMemoryUsageChanged(); void metaPressAndHoldEnabledChanged(); - void mouseSensitivityChanged(); + void sensitivityChanged(); void screensCountChanged(); void screenScalesChanged(); void screenTrackerIntervalChanged(); void showInfoWindowChanged(); void versionChanged(); private slots: void loadConfig(); void loadScalesConfig(); void saveConfig(); void saveScalesConfig(); void recoverKWinOptions(); void updateColorsScriptIsPresent(); void trackedFileChanged(const QString &file); private: void cleanupSettings(); void setColorsScriptIsPresent(bool present); Types::LayoutsMemoryUsage layoutsMemoryUsage() const; void setLayoutsMemoryUsage(Types::LayoutsMemoryUsage layoutsMemoryUsage); private: bool m_badges3DStyle{false}; bool m_canDisableBorders{false}; bool m_colorsScriptIsPresent{false}; bool m_metaPressAndHoldEnabled{true}; bool m_showInfoWindow{true}; //!kwinrc tracking bool m_kwinMetaForwardedToLatte{false}; bool m_kwinBorderlessMaximizedWindows{false}; //when there isnt a version it is an old universal file int m_version{1}; int m_screenTrackerInterval{2500}; QString m_currentLayoutName; QString m_lastNonAssignedLayoutName; QStringList m_launchers; Types::LayoutsMemoryUsage m_memoryUsage; - Types::MouseSensitivity m_mouseSensitivity{Types::HighSensitivity}; + Settings::MouseSensitivity m_sensitivity{Settings::HighMouseSensitivity}; //! ScreenName, QHash m_screenScales; QPointer m_corona; KConfigGroup m_screenScalesGroup; KConfigGroup m_universalGroup; KSharedConfig::Ptr m_config; //! reading kwinrc values is costly; a tracker protects from //! reading too many times with no real reason QTimer m_kwinrcTrackerTimer; friend class Layouts::Manager; friend class Latte::Corona; }; } #endif //UNIVERSALSETTINGS_H diff --git a/containment/package/contents/ui/main.qml b/containment/package/contents/ui/main.qml index 50491f78..886dc0a7 100644 --- a/containment/package/contents/ui/main.qml +++ b/containment/package/contents/ui/main.qml @@ -1,1925 +1,1927 @@ /* * Copyright 2016 Smith AR * Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ import QtQuick 2.8 import QtQuick.Layouts 1.1 import QtQuick.Window 2.2 import QtGraphicalEffects 1.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.kquickcontrolsaddons 2.0 import org.kde.plasma.plasmoid 2.0 import org.kde.latte.core 0.2 as LatteCore import org.kde.latte.components 1.0 as LatteComponents +import org.kde.latte.private.app 0.1 as LatteApp import org.kde.latte.private.containment 0.1 as LatteContainment + import "abilities" as Ability import "applet" as Applet import "colorizer" as Colorizer import "editmode" as EditMode import "indicators" as Indicators import "layouts" as Layouts import "../code/LayoutManager.js" as LayoutManager Item { id: root objectName: "containmentViewLayout" LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft && !root.isVertical LayoutMirroring.childrenInherit: true //// BEGIN SIGNALS signal clearZoomSignal(); signal destroyInternalViewSplitters(); signal emptyAreasWheel(QtObject wheel); signal separatorsUpdated(); signal signalActivateEntryAtIndex(int entryIndex); signal signalNewInstanceForEntryAtIndex(int entryIndex); signal updateEffectsArea(); signal updateIndexes(); signal updateScale(int delegateIndex, real newScale, real step); signal broadcastedToApplet(string pluginName, string action, variant value); //// END SIGNALS ////BEGIN properties property bool debugMode: Qt.application.arguments.indexOf("--graphics")>=0 property bool debugModeLocalGeometry: Qt.application.arguments.indexOf("--localgeometry")>=0 property bool debugModeSpacers: Qt.application.arguments.indexOf("--spacers")>=0 property bool debugModeTimers: Qt.application.arguments.indexOf("--timers")>=0 property bool debugModeWindow: Qt.application.arguments.indexOf("--with-window")>=0 property bool debugModeOverloadedIcons: Qt.application.arguments.indexOf("--overloaded-icons")>=0 readonly property int version: LatteCore.Environment.makeVersion(0,9,4) property bool globalDirectRender: false //it is used as a globalDirectRender for all elements in the dock property int directRenderAnimationTime: 0 property bool addLaunchersMessage: false property bool addLaunchersInTaskManager: plasmoid.configuration.addLaunchersInTaskManager property bool backgroundOnlyOnMaximized: plasmoid.configuration.backgroundOnlyOnMaximized property bool behaveAsPlasmaPanel: { if (!LatteCore.WindowSystem.compositingActive) { //! In NOCOMPOSITING mode VIEWS should behave as real windows and that way //! we gain also the snapping features from KWin return true; } if (!latteView || !latteView.visibility) { return false; } if (screenEdgeMarginEnabled && plasmoid.configuration.fittsLawIsRequested) { //! dont use when floating views are requesting Fitt's Law return false; } return (visibilityManager.panelIsBiggerFromIconSize && (maxZoomFactor === 1.0) && (plasmoid.configuration.alignment === LatteCore.Types.Justify) && !root.editMode && !visibilityManager.inLocationAnimation); } property int viewType: { if ((plasmoid.configuration.alignment === LatteCore.Types.Justify) && (plasmoid.configuration.useThemePanel) && (plasmoid.configuration.panelSize === 100) && (maxZoomFactor === 1.0)) { return LatteCore.Types.PanelView; } return LatteCore.Types.DockView; } property bool blurEnabled: plasmoid.configuration.blurEnabled && (!forceTransparentPanel || forcePanelForBusyBackground) readonly property bool ignoreRegularFilesDragging: !root.editMode && (dragInfo.computationsAreValid || foreDropArea.dragInfo.computationsAreValid) && !root.dragInfo.isPlasmoid && !root.dragInfo.onlyLaunchers readonly property Item dragInfo: Item { property bool entered: backDropArea.dragInfo.entered || foreDropArea.dragInfo.entered property bool isTask: backDropArea.dragInfo.isTask || foreDropArea.dragInfo.isTask property bool isPlasmoid: backDropArea.dragInfo.isPlasmoid || foreDropArea.dragInfo.isPlasmoid property bool isSeparator: backDropArea.dragInfo.isSeparator || foreDropArea.dragInfo.isSeparator property bool isLatteTasks: backDropArea.dragInfo.isLatteTasks || foreDropArea.dragInfo.isLatteTasks property bool onlyLaunchers: backDropArea.dragInfo.onlyLaunchers || foreDropArea.dragInfo.onlyLaunchers // onIsPlasmoidChanged: console.log("isPlasmoid :: " + backDropArea.dragInfo.isPlasmoid + " _ " + foreDropArea.dragInfo.isPlasmoid ); // onEnteredChanged: console.log("entered :: " + backDropArea.dragInfo.entered + " _ " + foreDropArea.dragInfo.entered ); } property bool containsOnlyPlasmaTasks: false //this is flag to indicate when from tasks only a plasma based one is found property bool dockContainsMouse: latteView && latteView.visibility ? latteView.visibility.containsMouse : false property bool disablePanelShadowMaximized: plasmoid.configuration.disablePanelShadowForMaximized && LatteCore.WindowSystem.compositingActive property bool drawShadowsExternal: panelShadowsActive && behaveAsPlasmaPanel && !visibilityManager.inTempHiding property bool editMode: editModeVisual.inEditMode property bool windowIsTouching: latteView && latteView.windowsTracker && (latteView.windowsTracker.currentScreen.activeWindowTouching || hasExpandedApplet) property bool forceSolidPanel: (latteView && latteView.visibility && LatteCore.WindowSystem.compositingActive && !inConfigureAppletsMode && userShowPanelBackground && ( (plasmoid.configuration.solidBackgroundForMaximized && !(hasExpandedApplet && !plasmaBackgroundForPopups) && latteView.windowsTracker.currentScreen.existsWindowTouching) || (hasExpandedApplet && plasmaBackgroundForPopups) )) || solidBusyForTouchingBusyVerticalView || plasmaStyleBusyForTouchingBusyVerticalView || !LatteCore.WindowSystem.compositingActive property bool forceTransparentPanel: root.backgroundOnlyOnMaximized && latteView && latteView.visibility && LatteCore.WindowSystem.compositingActive && !inConfigureAppletsMode && !forceSolidPanel && !latteView.windowsTracker.currentScreen.existsWindowTouching && !(windowColors === LatteCore.Types.ActiveWindowColors && selectedWindowsTracker.existsWindowActive) property bool forcePanelForBusyBackground: userShowPanelBackground && (root.themeColors === LatteCore.Types.SmartThemeColors) && ( (root.forceTransparentPanel && colorizerManager.backgroundIsBusy) || normalBusyForTouchingBusyVerticalView ) property bool normalBusyForTouchingBusyVerticalView: (latteView && latteView.windowsTracker /*is touching a vertical view that is in busy state and the user prefers isBusy transparency*/ && latteView.windowsTracker.currentScreen.isTouchingBusyVerticalView && root.themeColors === LatteCore.Types.SmartThemeColors && plasmoid.configuration.backgroundOnlyOnMaximized /*&& !plasmoid.configuration.solidBackgroundForMaximized && !plasmaBackgroundForPopups*/) property bool solidBusyForTouchingBusyVerticalView: false //DISABLED, until to check if the normalBusyForTouchingBusyVerticalView is enough to catch and handle the case /*(latteView && latteView.windowsTracker /*is touching a vertical view that is in busy state and the user prefers solidness*/ /* && latteView.windowsTracker.currentScreen.isTouchingBusyVerticalView && root.themeColors === LatteCore.Types.SmartThemeColors && plasmoid.configuration.backgroundOnlyOnMaximized && plasmoid.configuration.solidBackgroundForMaximized && !plasmaBackgroundForPopups)*/ property bool plasmaStyleBusyForTouchingBusyVerticalView: false //DISABLED, until to check if the normalBusyForTouchingBusyVerticalView is enough to catch and handle the case //(latteView && latteView.windowsTracker /*is touching a vertical view that is in busy state and the user prefers solidness*/ /* && latteView.windowsTracker.currentScreen.isTouchingBusyVerticalView && root.themeColors === LatteCore.Types.SmartThemeColors && plasmoid.configuration.backgroundOnlyOnMaximized && plasmaBackgroundForPopups)*/ property bool hideThickScreenGap: screenEdgeMarginEnabled && plasmoid.configuration.hideScreenGapForMaximized && latteView && latteView.windowsTracker && latteView.windowsTracker.currentScreen.existsWindowMaximized property bool hideLengthScreenGaps: hideThickScreenGap && (latteView.visibility.mode === LatteCore.Types.AlwaysVisible || latteView.visibility.mode === LatteCore.Types.WindowsGoBelow) && (plasmoid.configuration.alignment === LatteCore.Types.Justify) && plasmoid.configuration.maxLength>85 && !root.editMode property int themeColors: plasmoid.configuration.themeColors property int windowColors: plasmoid.configuration.windowColors property bool colorizerEnabled: themeColors !== LatteCore.Types.PlasmaThemeColors || windowColors !== LatteCore.Types.NoneWindowColors property bool plasmaBackgroundForPopups: plasmoid.configuration.plasmaBackgroundForPopups readonly property bool hasExpandedApplet: latteView && latteView.extendedInterface.hasExpandedApplet; readonly property bool hasUserSpecifiedBackground: (latteView && latteView.layout && latteView.layout.background.startsWith("/")) ? true : false readonly property bool inConfigureAppletsMode: root.editMode && (plasmoid.configuration.inConfigureAppletsMode || !LatteCore.WindowSystem.compositingActive) readonly property bool parabolicEffectEnabled: zoomFactor>1 && !inConfigureAppletsMode property bool dockIsShownCompletely: !(dockIsHidden || inSlidingIn || inSlidingOut) && !root.editMode property bool closeActiveWindowEnabled: plasmoid.configuration.closeActiveWindowEnabled property bool dragActiveWindowEnabled: plasmoid.configuration.dragActiveWindowEnabled property bool immutable: plasmoid.immutable property bool inFullJustify: (plasmoid.configuration.alignment === LatteCore.Types.Justify) && (maxLengthPerCentage===100) property bool inSlidingIn: visibilityManager ? visibilityManager.inSlidingIn : false property bool inSlidingOut: visibilityManager ? visibilityManager.inSlidingOut : false property bool inStartup: true property bool isHalfShown: false //is used to disable the zoom hovering effect at sliding in-out the dock property bool isHorizontal: plasmoid.formFactor === PlasmaCore.Types.Horizontal property bool isReady: !(dockIsHidden || inSlidingIn || inSlidingOut) property bool isVertical: !isHorizontal property bool isHovered: latteApplet ? ((latteAppletHoveredIndex !== -1) || (layoutsContainer.hoveredIndex !== -1)) //|| wholeArea.containsMouse : (layoutsContainer.hoveredIndex !== -1) //|| wholeArea.containsMouse property bool mouseWheelActions: plasmoid.configuration.mouseWheelActions property bool onlyAddingStarup: true //is used for the initialization phase in startup where there aren't removals, this variable provides a way to grow icon size property bool shrinkThickMargins: plasmoid.configuration.shrinkThickMargins property bool showLatteShortcutBadges: false property bool showAppletShortcutBadges: false property bool showMetaBadge: false property int applicationLauncherId: -1 //FIXME: possibly this is going to be the default behavior, this user choice //has been dropped from the Dock Configuration Window //property bool smallAutomaticIconJumps: plasmoid.configuration.smallAutomaticIconJumps property bool smallAutomaticIconJumps: true property bool userShowPanelBackground: LatteCore.WindowSystem.compositingActive ? plasmoid.configuration.useThemePanel : true property bool useThemePanel: noApplets === 0 || !LatteCore.WindowSystem.compositingActive ? true : (plasmoid.configuration.useThemePanel || plasmoid.configuration.solidBackgroundForMaximized) property bool plasma515: LatteCore.Environment.plasmaDesktopVersion >= LatteCore.Environment.makeVersion(5,15,0) property bool plasma518: LatteCore.Environment.plasmaDesktopVersion >= LatteCore.Environment.makeVersion(5,18,0) property alias hoveredIndex: layoutsContainer.hoveredIndex property alias directRenderDelayerIsRunning: directRenderDelayerForEnteringTimer.running property int animationsNeedBothAxis:0 //animations need space in both axes, e.g zooming a task property int animationsNeedLength: 0 // animations need length, e.g. adding a task property int animationsNeedThickness: 0 // animations need thickness, e.g. bouncing animation readonly property bool thickAnimated: animationsNeedBothAxis>0 || animationsNeedThickness>0 property int animationTime: durationTime*2.8*root.longDuration property int appletsNeedWindowsTracking: 0 readonly property int minAppletLengthInConfigure: 64 readonly property int maxJustifySplitterSize: 96 property int latteAppletPos: -1 property int minLengthPerCentage: plasmoid.configuration.minLength property int maxLengthPerCentage: hideLengthScreenGaps ? 100 : plasmoid.configuration.maxLength property int minLength: { if (root.isHorizontal) { return behaveAsPlasmaPanel && LatteCore.WindowSystem.compositingActive ? width : width * (minLengthPerCentage/100) } else { return behaveAsPlasmaPanel && LatteCore.WindowSystem.compositingActive ? height : height * (minLengthPerCentage/100) } } property int maxLength: { if (root.isHorizontal) { return behaveAsPlasmaPanel ? width : width * (maxLengthPerCentage/100) } else { return behaveAsPlasmaPanel ? height : height * (maxLengthPerCentage/100) } } property int scrollAction: plasmoid.configuration.scrollAction property bool panelOutline: plasmoid.configuration.panelOutline property int panelEdgeSpacing: Math.max(panelBoxBackground.lengthMargins, 1.5*appShadowSize) property int panelTransparency: plasmoid.configuration.panelTransparency //user set property int currentPanelTransparency: 0 //application override readonly property real currentPanelOpacity: currentPanelTransparency/100 property bool panelShadowsActive: { if (!userShowPanelBackground) { return false; } if (inConfigureAppletsMode) { return plasmoid.configuration.panelShadows; } var forcedNoShadows = (plasmoid.configuration.panelShadows && disablePanelShadowMaximized && latteView && latteView.windowsTracker && latteView.windowsTracker.currentScreen.activeWindowMaximized); if (forcedNoShadows) { return false; } var transparencyCheck = (blurEnabled || (!blurEnabled && currentPanelTransparency>20)); //! Draw shadows for isBusy state only when current panelTransparency is greater than 10% if (plasmoid.configuration.panelShadows && root.forcePanelForBusyBackground && transparencyCheck) { return true; } if (( (plasmoid.configuration.panelShadows && !root.backgroundOnlyOnMaximized) || (plasmoid.configuration.panelShadows && root.backgroundOnlyOnMaximized && !root.forceTransparentPanel)) && !forcedNoShadows) { return true; } if (hasExpandedApplet && plasmaBackgroundForPopups) { return true; } return false; } property int appShadowOpacity: (plasmoid.configuration.shadowOpacity/100) * 255 property int appShadowSize: enableShadows ? (0.5*container.iconSize) * (plasmoid.configuration.shadowSize/100) : 0 property int appShadowSizeOriginal: enableShadows ? (0.5*container.maxIconSize) * (plasmoid.configuration.shadowSize/100) : 0 property string appChosenShadowColor: { if (plasmoid.configuration.shadowColorType === LatteCore.Types.ThemeColorShadow) { var strC = String(theme.textColor); return strC.indexOf("#") === 0 ? strC.substr(1) : strC; } else if (plasmoid.configuration.shadowColorType === LatteCore.Types.UserColorShadow) { return plasmoid.configuration.shadowColor; } // default shadow color return "080808"; } property string appShadowColor: "#" + decimalToHex(appShadowOpacity) + appChosenShadowColor property string appShadowColorSolid: "#" + appChosenShadowColor property int totalPanelEdgeSpacing: 0 //this is set by PanelBox property int offset: { if (behaveAsPlasmaPanel) { return 0; } if (root.isHorizontal) { return width * (plasmoid.configuration.offset/100); } else { height * (plasmoid.configuration.offset/100) } } //center the layout correctly when the user uses an offset property int offsetFixed: (offset===0 || panelAlignment === LatteCore.Types.Center || plasmoid.configuration.alignment === LatteCore.Types.Justify)? offset : offset+panelMarginLength/2+totalPanelEdgeSpacing/2 property int realPanelSize: 0 property int realPanelLength: 0 property int realPanelThickness: 0 //this is set by the PanelBox property int panelThickMarginBase: 0 property int panelThickMarginHigh: 0 property int panelMarginLength: 0 property int panelShadow: 0 //shadowsSize property int editShadow: { if (!LatteCore.WindowSystem.compositingActive) { return 0; } else if (latteView && latteView.screenGeometry) { return latteView.screenGeometry.height/90; } else { return 7; } } property int themePanelThickness: { var panelBase = root.panelThickMarginHigh + root.panelThickMarginBase; var margin = shrinkThickMargins ? 0 : thickMargins + localScreenEdgeMargin; var maxPanelSize = (container.iconSize + margin) - panelBase; var percentage = LatteCore.WindowSystem.compositingActive ? plasmoid.configuration.panelSize/100 : 1; return Math.max(panelBase, panelBase + percentage*maxPanelSize); } property int lengthIntMargin: lengthIntMarginFactor * container.iconSize property int lengthExtMargin: lengthExtMarginFactor * container.iconSize property real lengthIntMarginFactor: indicators.isEnabled ? indicators.padding : 0 property real lengthExtMarginFactor: plasmoid.configuration.lengthExtMargin / 100 property real lengthAppletIntMarginFactor: indicators.infoLoaded ? indicators.info.appletLengthPadding : -1 property real thickMarginFactor: { if (shrinkThickMargins) { return indicators.info.minThicknessPadding; } //0.075 old statesLineSize and 0.06 old default thickMargin return Math.max(indicators.info.minThicknessPadding, plasmoid.configuration.thickMargin / 100) } property int thickMargin: thickMarginFactor * container.iconSize property bool screenEdgeMarginEnabled: plasmoid.configuration.screenEdgeMargin >= 0 && !plasmoid.configuration.shrinkThickMargins property int screenEdgeMargin: { //! is used for window geometry calculations if (!screenEdgeMarginEnabled || (hideThickScreenGap && localScreenEdgeMargin === 0)) { /*window geometry is updated after the local screen margin animation was zeroed*/ return 0; } return plasmoid.configuration.screenEdgeMargin; } property int localScreenEdgeMargin: (screenEdgeMarginEnabled && behaveAsPlasmaPanel && !root.editMode) || !screenEdgeMarginEnabled || hideThickScreenGap ? 0 : plasmoid.configuration.screenEdgeMargin //! thickness margins are always two and equal in order for items //! to be always correctly centered property int thickMargins: 2 * thickMargin //it is used in order to not break the calculations for the thickness placement //especially in automatic icon sizes calculations property int maxThickMargin: thickMarginFactor * container.maxIconSize property int lengthMargin: lengthIntMargin + lengthExtMargin property int lengthMargins: 2 * lengthMargin property int widthMargins: root.isVertical ? thickMargins : lengthMargins property int heightMargins: root.isHorizontal ? thickMargins : lengthMargins ///FIXME: I can't remember why this is needed, maybe for the anchorings!!! In order for the Double Layout to not mess the anchorings... //property int layoutsContainer.mainLayoutPosition: !plasmoid.immutable ? LatteCore.Types.Center : (root.isVertical ? LatteCore.Types.Top : LatteCore.Types.Left) //property int panelAlignment: plasmoid.configuration.alignment !== LatteCore.Types.Justify ? plasmoid.configuration.alignment : layoutsContainer.mainLayoutPosition property int panelAlignment: !root.inConfigureAppletsMode ? plasmoid.configuration.alignment : ( plasmoid.configuration.alignment === LatteCore.Types.Justify ? LatteCore.Types.Center : plasmoid.configuration.alignment ) property int panelUserSetAlignment: plasmoid.configuration.alignment property real zoomFactor: LatteCore.WindowSystem.compositingActive && root.animationsEnabled ? ( 1 + (plasmoid.configuration.zoomLevel / 20) ) : 1 readonly property string plasmoidName: "org.kde.latte.plasmoid" property var badgesForActivate: { if (!shortcutsEngine) { return ['1','2','3','4','5','6','7','8','9','0', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.']; } return shortcutsEngine.badgesForActivate; } property var iconsArray: [16, 22, 32, 48, 64, 96, 128, 256] property Item dragOverlay property Item toolBox property Item latteAppletContainer property Item latteApplet readonly property Item autosize: _autosize readonly property Item container: _container readonly property Item indicatorsManager: indicators readonly property Item parabolicManager: _parabolicManager readonly property Item maskManager: visibilityManager readonly property Item layoutsContainerItem: layoutsContainer property QtObject latteView: null property QtObject shortcutsEngine: null property QtObject themeExtended: null property QtObject universalSettings: null property QtObject layoutsManager: null property QtObject viewLayout: latteView && latteView.layout ? latteView.layout : null property QtObject selectedWindowsTracker: { if (latteView && latteView.windowsTracker) { switch(plasmoid.configuration.activeWindowFilter) { case LatteContainment.Types.ActiveInCurrentScreen: return latteView.windowsTracker.currentScreen; case LatteContainment.Types.ActiveFromAllScreens: return latteView.windowsTracker.allScreens; } } return null; } // TO BE DELETED, if not needed: property int counter:0; ///BEGIN properties provided to Latte Plasmoid //shadows for applets, it should be removed as the appleitems don't need it any more property bool badges3DStyle: universalSettings ? universalSettings.badges3DStyle : true property bool enableShadows: plasmoid.configuration.shadows || (root.forceTransparentPanel && plasmoid.configuration.shadows>0) property bool dockIsHidden: latteView ? latteView.visibility.isHidden : true property bool titleTooltips: plasmoid.configuration.titleTooltips property bool unifiedGlobalShortcuts: true readonly property bool hasInternalSeparator: latteApplet ? latteApplet.hasInternalSeparator : false property int animationStep: { - if (!universalSettings || universalSettings.mouseSensitivity === LatteCore.Types.HighSensitivity) { + if (!universalSettings || universalSettings.sensitivity === LatteApp.Settings.HighMouseSensitivity) { return 1; - } else if (universalSettings.mouseSensitivity === LatteCore.Types.MediumSensitivity) { + } else if (universalSettings.sensitivity === LatteApp.Settings.MediumMouseSensitivity) { return Math.max(3, container.iconSize / 18); - } else if (universalSettings.mouseSensitivity === LatteCore.Types.LowSensitivity) { + } else if (universalSettings.sensitivity === LatteApp.Settings.LowMouseSensitivity) { return Math.max(5, container.iconSize / 10); } } property int latteAppletHoveredIndex: latteApplet ? latteApplet.hoveredIndex : -1 property int tasksCount: latteApplet ? latteApplet.tasksCount : 0 //! Animations property bool animationsEnabled: plasmoid.configuration.animationsEnabled && LatteCore.WindowSystem.compositingActive readonly property int shortDuration: LatteCore.Environment.shortDuration readonly property int longDuration: LatteCore.Environment.longDuration property real appliedDurationTime: animationsEnabled ? durationTime : animationsSpeed2 readonly property real animationsSpeed1: 0.75 readonly property real animationsSpeed2: 1.00 readonly property real animationsSpeed3: 1.15 property real durationTime: { if (!animationsEnabled || plasmoid.configuration.durationTime === 0) { return 0; } if (plasmoid.configuration.durationTime === 1 ) { return animationsSpeed1; } else if (plasmoid.configuration.durationTime === 2) { return animationsSpeed2; } else if (plasmoid.configuration.durationTime === 3) { return animationsSpeed3; } return animationsSpeed2; } property real animationsZoomFactor : { if (!animationsEnabled || !LatteCore.WindowSystem.compositingActive) { return 1; } /* if (latteApplet && (animationLauncherBouncing || animationWindowInAttention || animationWindowAddedInGroup)) { return 1.65; }*/ return 1; } property real maxZoomFactor: Math.max(zoomFactor, animationsZoomFactor) property rect screenGeometry: latteView ? latteView.screenGeometry : plasmoid.screenGeometry readonly property color minimizedDotColor: colorizerManager.minimizedDotColor ///END properties from latteApplet Plasmoid.backgroundHints: PlasmaCore.Types.NoBackground //// BEGIN properties in functions property int noApplets: { var count1 = 0; var count2 = 0; count1 = layoutsContainer.mainLayout.children.length; var tempLength = layoutsContainer.mainLayout.children.length; for (var i=tempLength-1; i>=0; --i) { var applet = layoutsContainer.mainLayout.children[i]; if (applet && (applet === dndSpacer || applet === lastSpacer || applet.isInternalViewSplitter)) count1--; } count2 = layoutsContainer.endLayout.children.length; tempLength = layoutsContainer.endLayout.children.length; for (var i=tempLength-1; i>=0; --i) { var applet = layoutsContainer.endLayout.children[i]; if (applet && (applet === dndSpacer || applet === lastSpacer || applet.isInternalViewSplitter)) count2--; } return (count1 + count2); } ///The index of user's current icon size property int currentIconIndex:{ for(var i=iconsArray.length-1; i>=0; --i){ if(iconsArray[i] === container.iconSize){ return i; } } return 3; } //// END properties in functions ////////////////END properties //// BEGIN OF Behaviors Behavior on thickMargin { NumberAnimation { duration: 0.8 * root.animationTime easing.type: Easing.OutCubic } } Behavior on lengthIntMargin { NumberAnimation { duration: 0.8 * root.animationTime easing.type: Easing.OutCubic } } Behavior on lengthExtMargin { NumberAnimation { duration: 0.8 * root.animationTime easing.type: Easing.OutCubic } } Behavior on localScreenEdgeMargin { enabled: !root.behaveAsPlasmaPanel && !editModeVisual.editAnimationRunning /*avoid slide-out animation when from editMode we change to real floating*/ NumberAnimation { duration: 0.8 * root.animationTime easing.type: Easing.OutCubic } } Behavior on offset { enabled: editModeVisual.editAnimationInFullThickness NumberAnimation { id: offsetAnimation duration: 0.8 * root.animationTime easing.type: Easing.OutCubic } } //// END OF Behaviors //////////////START OF CONNECTIONS onEditModeChanged: { if (editMode) { visibilityManager.updateMaskArea(); clearZoom(); } else { layoutsContainer.updateSizeForAppletsInFill(); } //! This is used in case the dndspacer has been left behind //! e.g. the user drops a folder and a context menu is appearing //! but the user decides to not make a choice for the applet type if (dndSpacer.parent !== root) { dndSpacer.parent = root; } } onInConfigureAppletsModeChanged: { if (inConfigureAppletsMode && panelUserSetAlignment===LatteCore.Types.Justify) { joinLayoutsToMainLayout(); } else if (!inConfigureAppletsMode) { splitMainLayoutToLayouts(); } updateIndexes(); } //! It is used only when the user chooses different alignment types //! and not during startup onPanelUserSetAlignmentChanged: { if (!root.editMode) { return; } if (!inConfigureAppletsMode){ if (panelUserSetAlignment===LatteCore.Types.Justify) { addInternalViewSplitters(); splitMainLayoutToLayouts(); } else { joinLayoutsToMainLayout(); root.destroyInternalViewSplitters(); } } else { if (panelUserSetAlignment===LatteCore.Types.Justify) { addInternalViewSplitters(); } else { root.destroyInternalViewSplitters(); } } LayoutManager.save(); updateIndexes(); } onLatteViewChanged: { if (latteView) { latteView.onXChanged.connect(visibilityManager.updateMaskArea); latteView.onYChanged.connect(visibilityManager.updateMaskArea); latteView.onWidthChanged.connect(visibilityManager.updateMaskArea); latteView.onHeightChanged.connect(visibilityManager.updateMaskArea); latteView.positioner.hideDockDuringLocationChangeStarted.connect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterLocationChangeFinished.connect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringScreenChangeStarted.connect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterScreenChangeFinished.connect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringMovingToLayoutStarted.connect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterMovingToLayoutFinished.connect(visibilityManager.slotShowDockAfterLocationChange); latteView.visibility.onContainsMouseChanged.connect(visibilityManager.slotContainsMouseChanged); latteView.visibility.onMustBeHide.connect(visibilityManager.slotMustBeHide); latteView.visibility.onMustBeShown.connect(visibilityManager.slotMustBeShown); updateContainsOnlyPlasmaTasks(); } } onDockContainsMouseChanged: { if (!dockContainsMouse) { initializeHoveredIndexes(); } } onMaxLengthChanged: { layoutsContainer.updateSizeForAppletsInFill(); } onToolBoxChanged: { if (toolBox) { toolBox.visible = false; } } onIsReadyChanged: { if (isReady && !titleTooltipDialog.visible && titleTooltipDialog.activeItemHovered){ titleTooltipDialog.show(titleTooltipDialog.activeItem, titleTooltipDialog.activeItemText); } } onIsVerticalChanged: { if (isVertical) { if (plasmoid.configuration.alignment === LatteCore.Types.Left) plasmoid.configuration.alignment = LatteCore.Types.Top; else if (plasmoid.configuration.alignment === LatteCore.Types.Right) plasmoid.configuration.alignment = LatteCore.Types.Bottom; } else { if (plasmoid.configuration.alignment === LatteCore.Types.Top) plasmoid.configuration.alignment = LatteCore.Types.Left; else if (plasmoid.configuration.alignment === LatteCore.Types.Bottom) plasmoid.configuration.alignment = LatteCore.Types.Right; } } Component.onCompleted: { // currentLayout.isLayoutHorizontal = isHorizontal LayoutManager.plasmoid = plasmoid; LayoutManager.root = root; LayoutManager.container = container; LayoutManager.layout = layoutsContainer.mainLayout; LayoutManager.layoutS = layoutsContainer.startLayout; LayoutManager.layoutE = layoutsContainer.endLayout; LayoutManager.lastSpacer = lastSpacer; upgrader_v010_alignment(); LayoutManager.restore(); plasmoid.action("configure").visible = !plasmoid.immutable; plasmoid.action("configure").enabled = !plasmoid.immutable; inStartupTimer.start(); } Component.onDestruction: { console.debug("Destroying Latte Dock Containment ui..."); if (latteView) { latteView.onXChanged.disconnect(visibilityManager.updateMaskArea); latteView.onYChanged.disconnect(visibilityManager.updateMaskArea); latteView.onWidthChanged.disconnect(visibilityManager.updateMaskArea); latteView.onHeightChanged.disconnect(visibilityManager.updateMaskArea); latteView.positioner.hideDockDuringLocationChangeStarted.disconnect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterLocationChangeFinished.disconnect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringScreenChangeStarted.disconnect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterScreenChangeFinished.disconnect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringMovingToLayoutStarted.disconnect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterMovingToLayoutFinished.disconnect(visibilityManager.slotShowDockAfterLocationChange); if (latteView.visibility) { latteView.visibility.onContainsMouseChanged.disconnect(visibilityManager.slotContainsMouseChanged); latteView.visibility.onMustBeHide.disconnect(visibilityManager.slotMustBeHide); latteView.visibility.onMustBeShown.disconnect(visibilityManager.slotMustBeShown); } } } Containment.onAppletAdded: { addApplet(applet, x, y); console.log(applet.pluginName); LayoutManager.save(); updateIndexes(); } Containment.onAppletRemoved: { LayoutManager.removeApplet(applet); var flexibleFound = false; for (var i = 0; i < layoutsContainer.mainLayout.children.length; ++i) { var applet = layoutsContainer.mainLayout.children[i].applet; if (applet && ((root.isHorizontal && applet.Layout.fillWidth) || (!root.isHorizontal && applet.Layout.fillHeight)) && applet.visible) { flexibleFound = true; break } } if (!flexibleFound) { lastSpacer.parent = layoutsContainer.mainLayout; } console.log(applet.pluginName); LayoutManager.save(); updateIndexes(); updateContainsOnlyPlasmaTasks(); } Plasmoid.onUserConfiguringChanged: { if (plasmoid.immutable) { if (dragOverlay) { dragOverlay.destroy(); } return; } // console.debug("user configuring", plasmoid.userConfiguring) if (plasmoid.userConfiguring) { // console.log("applets------"); for (var i = 0; i < plasmoid.applets.length; ++i) { // console.log("applet:"+i); plasmoid.applets[i].expanded = false; } if (!dragOverlay) { var component = Qt.createComponent("editmode/ConfigOverlay.qml"); if (component.status == Component.Ready) { dragOverlay = component.createObject(root); } else { console.log("Could not create ConfigOverlay"); console.log(component.errorString()); } component.destroy(); } else { dragOverlay.visible = true; } } else { if (dragOverlay) { dragOverlay.visible = false; dragOverlay.destroy(); } } } Plasmoid.onImmutableChanged: { plasmoid.action("configure").visible = !plasmoid.immutable; plasmoid.action("configure").enabled = !plasmoid.immutable; ///Set Preferred Sizes/// ///Notice: they are set here because if they are set with a binding ///they break the !immutable experience, the latteView becomes too small ///to add applets /* if (plasmoid.immutable) { if(root.isHorizontal) { root.Layout.preferredWidth = (plasmoid.configuration.alignment === LatteCore.Types.Justify ? layoutsContainer.width + 0.5*iconMargin : layoutsContainer.mainLayout.width + iconMargin); } else { root.Layout.preferredHeight = (plasmoid.configuration.alignment === LatteCore.Types.Justify ? layoutsContainer.height + 0.5*iconMargin : layoutsContainer.mainLayout.height + iconMargin); } } else { if (root.isHorizontal) { root.Layout.preferredWidth = Screen.width; } else { root.Layout.preferredHeight = Screen.height; } }*/ visibilityManager.updateMaskArea(); } //////////////END OF CONNECTIONS //////////////START OF FUNCTIONS function addApplet(applet, x, y) { var container = appletContainerComponent.createObject(dndSpacer.parent) container.applet = applet; applet.parent = container.appletWrapper; applet.anchors.fill = container.appletWrapper; applet.visible = true; // don't show applet if it chooses to be hidden but still make it // accessible in the panelcontroller container.visible = Qt.binding(function() { return applet.status !== PlasmaCore.Types.HiddenStatus || (!plasmoid.immutable && root.inConfigureAppletsMode) }) addContainerInLayout(container, applet, x, y); updateContainsOnlyPlasmaTasks(); } function addContainerInLayout(container, applet, x, y){ // Is there a DND placeholder? Replace it! if ( (dndSpacer.parent === layoutsContainer.mainLayout) || (dndSpacer.parent === layoutsContainer.startLayout) || (dndSpacer.parent===layoutsContainer.endLayout)) { LayoutManager.insertBeforeForLayout(dndSpacer.parent, dndSpacer, container); dndSpacer.parent = root; return; // If the provided position is valid, use it. } else if (x >= 0 && y >= 0) { var index = LayoutManager.insertAtCoordinates2(container, x , y); // Fall through to determining an appropriate insert position. } else { var before = null; container.animationsEnabled = false; if (lastSpacer.parent === layoutsContainer.mainLayout) { before = lastSpacer; } // Insert icons to the left of whatever is at the center (usually a Task Manager), // if it exists. // FIXME TODO: This is a real-world fix to produce a sensible initial position for // launcher icons added by launcher menu applets. The basic approach has been used // since Plasma 1. However, "add launcher to X" is a generic-enough concept and // frequent-enough occurrence that we'd like to abstract it further in the future // and get rid of the ugliness of parties external to the containment adding applets // of a specific type, and the containment caring about the applet type. In a better // system the containment would be informed of requested launchers, and determine by // itself what it wants to do with that information. if (applet.pluginName == "org.kde.plasma.icon") { var middle = layoutsContainer.mainLayout.childAt(root.width / 2, root.height / 2); if (middle) { before = middle; } // Otherwise if lastSpacer is here, enqueue before it. } if (before) { LayoutManager.insertBefore(before, container); // Fall through to adding at the end. } else { container.parent = layoutsContainer.mainLayout; } } //Important, removes the first children of the layoutsContainer.mainLayout after the first //applet has been added lastSpacer.parent = root; updateIndexes(); } function addInternalViewSplitters(){ if (internalViewSplittersCount() === 0) { addInternalViewSplitter(plasmoid.configuration.splitterPosition); addInternalViewSplitter(plasmoid.configuration.splitterPosition2); } } function addInternalViewSplitter(pos){ var splittersCount = internalViewSplittersCount(); if(splittersCount<2){ var container = appletContainerComponent.createObject(root); container.internalSplitterId = splittersCount+1; container.visible = true; if(pos>=0 ){ LayoutManager.insertAtIndex(container, pos); } else { LayoutManager.insertAtIndex(container, Math.floor(layoutsContainer.mainLayout.count / 2)); } } } //! it is used in order to check the right click position //! the only way to take into account the visual appearance //! of the applet (including its spacers) function appletContainsPos(appletId, pos){ for (var i = 0; i < layoutsContainer.startLayout.children.length; ++i) { var child = layoutsContainer.startLayout.children[i]; if (child && child.applet && child.applet.id === appletId && child.containsPos(pos)) return true; } for (var i = 0; i < layoutsContainer.mainLayout.children.length; ++i) { var child = layoutsContainer.mainLayout.children[i]; if (child && child.applet && child.applet.id === appletId && child.containsPos(pos)) return true; } for (var i = 0; i < layoutsContainer.endLayout.children.length; ++i) { var child = layoutsContainer.endLayout.children[i]; if (child && child.applet && child.applet.id === appletId && child.containsPos(pos)) return true; } return false; } function checkLastSpacer() { lastSpacer.parent = root var expands = false; if (isHorizontal) { for (var container in layoutsContainer.mainLayout.children) { var item = layoutsContainer.mainLayout.children[container]; if (item.Layout && item.Layout.fillWidth) { expands = true; } } } else { for (var container in layoutsContainer.mainLayout.children) { var item = layoutsContainer.mainLayout.children[container]; if (item.Layout && item.Layout.fillHeight) { expands = true; } } } if (!expands) { lastSpacer.parent = layoutsContainer.mainLayout } } function clearZoom(){ if (latteApplet){ latteApplet.clearZoom(); } root.clearZoomSignal(); } function containmentActions(){ return latteView.containmentActions(); } function decimalToHex(d, padding) { var hex = Number(d).toString(16); padding = typeof (padding) === "undefined" || padding === null ? padding = 2 : padding; while (hex.length < padding) { hex = "0" + hex; } return hex; } function disableDirectRender(){ // root.globalDirectRender = false; } function internalViewSplittersCount(){ var splitters = 0; for (var container in layoutsContainer.startLayout.children) { var item = layoutsContainer.startLayout.children[container]; if(item && item.isInternalViewSplitter) { splitters = splitters + 1; } } for (var container in layoutsContainer.mainLayout.children) { var item = layoutsContainer.mainLayout.children[container]; if(item && item.isInternalViewSplitter) { splitters = splitters + 1; } } for (var container in layoutsContainer.endLayout.children) { var item = layoutsContainer.endLayout.children[container]; if(item && item.isInternalViewSplitter) { splitters = splitters + 1; } } return splitters; } function initializeHoveredIndexes() { layoutsContainer.hoveredIndex = -1; layoutsContainer.currentSpot = -1000; if (latteApplet) { latteApplet.initializeHoveredIndex(); } } function layoutManager() { return LayoutManager; } function layoutManagerInsertBefore(place, item) { LayoutManager.insertBefore(place, item); } function layoutManagerInsertAfter(place, item) { LayoutManager.insertAfter(place, item); } function layoutManagerSave() { LayoutManager.save(); } function layoutManagerSaveOptions() { LayoutManager.saveOptions(); } function mouseInCanBeHoveredApplet(){ if (latteApplet && latteApplet.containsMouse()) return true; var applets = layoutsContainer.startLayout.children; for(var i=0; i=0; --i){ if(iconsArray[i] === size){ return true; } } return false; } function slotAnimationsNeedBothAxis(step) { if (step === 0) { return; } animationsNeedBothAxis = Math.max(animationsNeedBothAxis + step, 0); visibilityManager.updateMaskArea(); } function slotAnimationsNeedLength(step) { if (step === 0) { return; } animationsNeedLength = Math.max(animationsNeedLength + step, 0); //when need length animations are ended it would be a good idea //to update the tasks geometries in the plasmoid if(animationsNeedLength === 0 && latteApplet) { latteApplet.publishTasksGeometries(); } visibilityManager.updateMaskArea(); } function slotAnimationsNeedThickness(step) { if (step === 0) { return; } animationsNeedThickness = Math.max(animationsNeedThickness + step, 0); visibilityManager.updateMaskArea(); } function slotAppletsNeedWindowsTracking(step) { if (step === 0) { return; } appletsNeedWindowsTracking = Math.max(appletsNeedWindowsTracking + step, 0); } function slotPreviewsShown(){ if (latteView) { latteView.extendedInterface.deactivateApplets(); } } function startCheckRestoreZoomTimer(){ checkRestoreZoom.start(); } function stopCheckRestoreZoomTimer(){ checkRestoreZoom.stop(); } function startDirectRenderDelayerDuringEntering(){ directRenderDelayerForEnteringTimer.start(); } function setGlobalDirectRender(value) { if (latteApplet && latteApplet.tasksExtendedManager.waitingLaunchersLength() > 0) return; if (value === true) { if (mouseInCanBeHoveredApplet()) { root.globalDirectRender = true; } else { // console.log("direct render true ignored..."); } } else { root.globalDirectRender = false; } } function updateContainsOnlyPlasmaTasks() { if (latteView) { root.containsOnlyPlasmaTasks = (latteView.tasksPresent() && !latteApplet); } else { root.containsOnlyPlasmaTasks = false; } } function updateSizeForAppletsInFill() { layoutsContainer.updateSizeForAppletsInFill(); } function splitMainLayoutToLayouts() { if (internalViewSplittersCount() === 2) { console.log("LAYOUTS: Moving applets from MAIN to THREE Layouts mode..."); var splitter = -1; var splitter2 = -1; var totalChildren = layoutsContainer.mainLayout.children.length; for (var i=0; i=0 && splitter2 === -1) { splitter2 = i; } } // console.log("update layouts 1:"+splitter + " - "+splitter2); for (var i=0; i<=splitter; ++i){ var item = layoutsContainer.mainLayout.children[0]; item.parent = layoutsContainer.startLayout; } splitter2 = splitter2 - splitter - 1; // console.log("update layouts 2:"+splitter + " - "+splitter2); totalChildren = layoutsContainer.mainLayout.children.length; for (var i=splitter2+1; i=0; --i) { var item1 = layoutsContainer.mainLayout.children[0]; item1.parent = layoutsContainer.startLayout; } var totalChildren2 = layoutsContainer.endLayout.children.length; for (var i=totalChildren2-1; i>=0; --i) { var item2 = layoutsContainer.endLayout.children[0]; item2.parent = layoutsContainer.startLayout; } var totalChildrenL = layoutsContainer.startLayout.children.length; for (var i=totalChildrenL-1; i>=0; --i) { var itemL = layoutsContainer.startLayout.children[0]; itemL.parent = layoutsContainer.mainLayout; } } function upgrader_v010_alignment() { //! IMPORTANT, special case because it needs to be loaded on Component constructor if (!plasmoid.configuration.alignmentUpgraded) { plasmoid.configuration.alignment = plasmoid.configuration.panelPosition; plasmoid.configuration.alignmentUpgraded = true; } } //END functions ////BEGIN interfaces Connections { target: LatteCore.WindowSystem onCompositingActiveChanged: { visibilityManager.updateMaskArea(); } } Connections { target: latteView onContextMenuIsShownChanged: { if (!latteView.contextMenuIsShown) { checkRestoreZoom.start(); } else { root.setGlobalDirectRender(false); } } } Connections{ target: latteView && latteView.visibility ? latteView.visibility : root ignoreUnknownSignals : true onContainsMouseChanged: { if (mouseInHoverableArea()) { stopCheckRestoreZoomTimer(); } else { startCheckRestoreZoomTimer(); } } } Connections{ target: layoutsContainer onHoveredIndexChanged: { if (latteApplet && layoutsContainer.hoveredIndex>-1){ latteApplet.setHoveredIndex(-1); } if (latteApplet && latteApplet.windowPreviewIsShown && layoutsContainer.hoveredIndex>-1) { latteApplet.hidePreview(); } } } ////END interfaces /////BEGIN: Title Tooltip/////////// PlasmaCore.Dialog{ id: titleTooltipDialog type: PlasmaCore.Dialog.Tooltip flags: Qt.WindowStaysOnTopHint | Qt.WindowDoesNotAcceptFocus | Qt.ToolTip location: plasmoid.location mainItem: RowLayout{ Layout.fillWidth: true Layout.fillHeight: true PlasmaComponents.Label{ id:titleLbl Layout.leftMargin: 4 Layout.rightMargin: 4 Layout.topMargin: 2 Layout.bottomMargin: 2 text: titleTooltipDialog.title } } visible: false property string title: "" property bool activeItemHovered: false property Item activeItem: null property Item activeItemTooltipParent: null property string activeItemText: "" Component.onCompleted: { root.clearZoomSignal.connect(titleTooltipDialog.hide); } Component.onDestruction: { root.clearZoomSignal.disconnect(titleTooltipDialog.hide); } function hide(debug){ if (!root.titleTooltips) return; activeItemHovered = false; hideTitleTooltipTimer.start(); } function show(taskItem, text){ if (!root.titleTooltips || (latteApplet && latteApplet.contextMenu)){ return; } activeItemHovered = true; if (activeItem !== taskItem) { activeItem = taskItem; activeItemTooltipParent = taskItem.tooltipVisualParent; activeItemText = text; } if (isReady) { showTitleTooltipTimer.start(); } } function update() { activeItemHovered = true title = activeItemText; visualParent = activeItemTooltipParent; if (latteApplet && latteApplet.windowPreviewIsShown) { latteApplet.hidePreview(); } visible = true; } } Timer { id: showTitleTooltipTimer interval: 100 onTriggered: { if (latteView && latteView.visibility && latteView.visibility.containsMouse) { titleTooltipDialog.update(); } if (titleTooltipDialog.visible) { titleTooltipCheckerToNotShowTimer.start(); } if (root.debugModeTimers) { console.log("containment timer: showTitleTooltipTimer called..."); } } } Timer { id: hideTitleTooltipTimer interval: 200 onTriggered: { if (!titleTooltipDialog.activeItemHovered) { titleTooltipDialog.visible = false; } if (root.debugModeTimers) { console.log("containment timer: hideTitleTooltipTimer called..."); } } } //! Timer to fix #811, rare cases that both a window preview and context menu are //! shown Timer { id: titleTooltipCheckerToNotShowTimer interval: 250 onTriggered: { if (titleTooltipDialog.visible && latteApplet && (latteApplet.contextMenu || latteApplet.windowPreviewIsShown)) { titleTooltipDialog.visible = false; } } } /////END: Title Tooltip/////////// ///////////////BEGIN components Component { id: appletContainerComponent Applet.AppletItem{} } ParabolicManager{ id: _parabolicManager } Indicators.Manager{ id: indicators } Item { id: graphicsSystem readonly property bool isAccelerated: (GraphicsInfo.api !== GraphicsInfo.Software) && (GraphicsInfo.api !== GraphicsInfo.Unknown) } Upgrader { id: upgrader } ///////////////END components PlasmaCore.ColorScope{ id: colorScopePalette } ///////////////BEGIN UI elements //it is used to check if the mouse is outside the layoutsContainer borders, //so in that case the onLeave event behavior should be trigerred RootMouseArea{ id: rootMouseArea } Loader{ active: root.debugModeWindow sourceComponent: DebugWindow{} } EditMode.Visual{ id:editModeVisual // z: root.behaveAsPlasmaPanel ? 1 : 0 } Item { id: lastSpacer parent: layoutsContainer.mainLayout Layout.fillWidth: true Layout.fillHeight: true z:10 Rectangle{ anchors.fill: parent color: "transparent" border.color: "yellow" border.width: 1 } } Loader{ anchors.fill: parent active: root.debugMode z:10 sourceComponent: Item{ Rectangle{ anchors.fill: parent color: "yellow" opacity: 0.06 } } } VisibilityManager{ id: visibilityManager } DragDropArea { id: backDropArea anchors.fill: parent readonly property bool higherPriority: latteView && latteView.containsDrag && ((root.dragInfo.isPlasmoid && root.dragInfo.isSeparator) || (foreDropArea.dragInfo.computationsAreValid && !root.dragInfo.isPlasmoid && !root.dragInfo.onlyLaunchers)) Item{ id: panelBox anchors.fill: layoutsContainer PanelBox{ id: panelBoxBackground } } Layouts.LayoutsContainer { id: layoutsContainer } DragDropArea { id: foreDropArea anchors.fill: parent visible: !backDropArea.higherPriority isForeground: true /* Rectangle { anchors.fill: parent color: "blue" opacity: 0.5 }*/ } } Colorizer.Manager { id: colorizerManager } Item { id: dndSpacer width: root.isHorizontal ? length : thickness height: root.isHorizontal ? thickness : length readonly property int length: container.iconSize + root.lengthMargins readonly property int thickness: container.iconSize + root.thickMargins + root.localScreenEdgeMargin Layout.preferredWidth: width Layout.preferredHeight: height opacity: 0 z:1500 LatteComponents.AddItem{ id: dndSpacerAddItem width: root.isHorizontal ? parent.width : parent.width - root.localScreenEdgeMargin height: root.isHorizontal ? parent.height - root.localScreenEdgeMargin : parent.height states:[ State{ name: "bottom" when: plasmoid.location === PlasmaCore.Types.BottomEdge AnchorChanges{ target: dndSpacerAddItem; anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: undefined; anchors.bottom: parent.bottom; } PropertyChanges{ target: dndSpacerAddItem; anchors.leftMargin: 0; anchors.rightMargin: 0; anchors.topMargin:0; anchors.bottomMargin: root.localScreenEdgeMargin; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "top" when: plasmoid.location === PlasmaCore.Types.TopEdge AnchorChanges{ target: dndSpacerAddItem; anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: parent.top; anchors.bottom: undefined; } PropertyChanges{ target: dndSpacerAddItem; anchors.leftMargin: 0; anchors.rightMargin: 0; anchors.topMargin: root.localScreenEdgeMargin; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "left" when: plasmoid.location === PlasmaCore.Types.LeftEdge AnchorChanges{ target: dndSpacerAddItem; anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: undefined; anchors.left: parent.left; anchors.top: undefined; anchors.bottom: undefined; } PropertyChanges{ target: dndSpacerAddItem; anchors.leftMargin: root.localScreenEdgeMargin; anchors.rightMargin: 0; anchors.topMargin:0; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "right" when: plasmoid.location === PlasmaCore.Types.RightEdge AnchorChanges{ target: dndSpacerAddItem; anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: parent.right; anchors.left: undefined; anchors.top: undefined; anchors.bottom: undefined; } PropertyChanges{ target: dndSpacerAddItem; anchors.leftMargin: 0; anchors.rightMargin: root.localScreenEdgeMargin; anchors.topMargin:0; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } } ] } } ///////////////END UI elements ///////////////BEGIN ABILITIES Ability.Container{ id: _container autosize: _autosize } Ability.AutoSizePrivate { id: _autosize container: _container layouts: layoutsContainer visibility: visibilityManager } ///////////////END ABILITIES ///////////////BEGIN TIMER elements //Timer to check if the mouse is still outside the latteView in order to restore zooms to 1.0 Timer{ id:checkRestoreZoom interval: 90 onTriggered: { if (latteApplet && (latteApplet.previewContainsMouse() || latteApplet.contextMenu)) return; if (latteView.contextMenuIsShown) return; if (!mouseInHoverableArea()) { setGlobalDirectRender(false); root.initializeHoveredIndexes(); root.clearZoom(); } if (root.debugModeTimers) { console.log("containment timer: checkRestoreZoom called..."); } } } //! Delayer in order to not activate directRendering when the mouse //! enters until the timer has ended. This way we make sure that the //! zoom-in animations will have ended. Timer{ id:directRenderDelayerForEnteringTimer interval: 3.2 * root.durationTime * root.shortDuration } //this is a delayer to update mask area, it is used in cases //that animations can not catch up with animations signals //e.g. the automaicIconSize case Timer{ id:delayUpdateMaskArea repeat:false; interval:300; onTriggered: { if (layoutsContainer.animationSent) { root.slotAnimationsNeedLength(-1); layoutsContainer.animationSent = false; } visibilityManager.updateMaskArea(); if (root.debugModeTimers) { console.log("containment timer: delayUpdateMaskArea called..."); } } } //! It is used in order to slide-in the latteView on startup Timer{ id: inStartupTimer interval: 1500 repeat: false onTriggered: { if (inStartup) { visibilityManager.slotMustBeShown(); } } } ///////////////END TIMER elements Loader{ anchors.fill: parent active: root.debugModeLocalGeometry sourceComponent: Rectangle{ x: latteView.localGeometry.x y: latteView.localGeometry.y width: latteView.localGeometry.width height: latteView.localGeometry.height color: "blue" border.width: 2 border.color: "red" opacity: 0.35 } } }