File indexing completed on 2024-04-21 05:31:15

0001 /*
0002     SPDX-FileCopyrightText: 2016 Smith AR <audoban@openmaibox.org>
0003     SPDX-FileCopyrightText: 2016 Michail Vourlakos <mvourlakos@gmail.com>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "lattecorona.h"
0009 
0010 // local
0011 #include <coretypes.h>
0012 #include "alternativeshelper.h"
0013 #include "apptypes.h"
0014 #include "lattedockadaptor.h"
0015 #include "screenpool.h"
0016 #include "data/generictable.h"
0017 #include "data/layouticondata.h"
0018 #include "declarativeimports/interfaces.h"
0019 #include "declarativeimports/contextmenulayerquickitem.h"
0020 #include "indicator/factory.h"
0021 #include "layout/abstractlayout.h"
0022 #include "layout/centrallayout.h"
0023 #include "layout/genericlayout.h"
0024 #include "layouts/importer.h"
0025 #include "layouts/manager.h"
0026 #include "layouts/synchronizer.h"
0027 #include "shortcuts/globalshortcuts.h"
0028 #include "package/lattepackage.h"
0029 #include "plasma/extended/backgroundcache.h"
0030 #include "plasma/extended/backgroundtracker.h"
0031 #include "plasma/extended/screengeometries.h"
0032 #include "plasma/extended/screenpool.h"
0033 #include "plasma/extended/theme.h"
0034 #include "settings/universalsettings.h"
0035 #include "templates/templatesmanager.h"
0036 #include "view/originalview.h"
0037 #include "view/view.h"
0038 #include "view/settings/viewsettingsfactory.h"
0039 #include "view/windowstracker/windowstracker.h"
0040 #include "view/windowstracker/allscreenstracker.h"
0041 #include "view/windowstracker/currentscreentracker.h"
0042 #include "wm/abstractwindowinterface.h"
0043 #include "wm/schemecolors.h"
0044 #include "wm/waylandinterface.h"
0045 #include "wm/xwindowinterface.h"
0046 #include "wm/tracker/lastactivewindow.h"
0047 #include "wm/tracker/schemes.h"
0048 #include "wm/tracker/windowstracker.h"
0049 
0050 // Qt
0051 #include <QAction>
0052 #include <QApplication>
0053 #include <QScreen>
0054 #include <QDBusConnection>
0055 #include <QDebug>
0056 #include <QDesktopWidget>
0057 #include <QFile>
0058 #include <QFontDatabase>
0059 #include <QQmlContext>
0060 #include <QProcess>
0061 
0062 // Plasma
0063 #include <Plasma>
0064 #include <Plasma/Corona>
0065 #include <Plasma/Containment>
0066 #include <PlasmaQuick/ConfigView>
0067 
0068 // KDE
0069 #include <KActionCollection>
0070 #include <KPluginMetaData>
0071 #include <KGlobalAccel>
0072 #include <KLocalizedString>
0073 #include <KPackage/Package>
0074 #include <KPackage/PackageLoader>
0075 #include <KAboutData>
0076 #include <KActivities/Consumer>
0077 #include <KDeclarative/QmlObjectSharedEngine>
0078 #include <KWindowSystem>
0079 #include <KWayland/Client/connection_thread.h>
0080 #include <KWayland/Client/registry.h>
0081 #include <KWayland/Client/plasmashell.h>
0082 #include <KWayland/Client/plasmawindowmanagement.h>
0083 
0084 namespace Latte {
0085 
0086 Corona::Corona(bool defaultLayoutOnStartup, QString layoutNameOnStartUp, QString addViewTemplateName, int userSetMemoryUsage, QObject *parent)
0087     : Plasma::Corona(parent),
0088       m_defaultLayoutOnStartup(defaultLayoutOnStartup),
0089       m_startupAddViewTemplateName(addViewTemplateName),
0090       m_userSetMemoryUsage(userSetMemoryUsage),
0091       m_layoutNameOnStartUp(layoutNameOnStartUp),
0092       m_activitiesConsumer(new KActivities::Consumer(this)),
0093       m_screenPool(new ScreenPool(KSharedConfig::openConfig(), this)),
0094       m_indicatorFactory(new Indicator::Factory(this)),
0095       m_universalSettings(new UniversalSettings(KSharedConfig::openConfig(), this)),
0096       m_globalShortcuts(new GlobalShortcuts(this)),
0097       m_plasmaScreenPool(new PlasmaExtended::ScreenPool(this)),
0098       m_themeExtended(new PlasmaExtended::Theme(KSharedConfig::openConfig(), this)),
0099       m_viewSettingsFactory(new ViewSettingsFactory(this)),
0100       m_templatesManager(new Templates::Manager(this)),
0101       m_layoutsManager(new Layouts::Manager(this)),
0102       m_plasmaGeometries(new PlasmaExtended::ScreenGeometries(this)),
0103       m_dialogShadows(new PanelShadows(this, QStringLiteral("dialogs/background")))
0104 {
0105     connect(qApp, &QApplication::aboutToQuit, this, &Corona::onAboutToQuit);
0106 
0107     //! create the window manager
0108     if (KWindowSystem::isPlatformWayland()) {
0109         m_wm = new WindowSystem::WaylandInterface(this);
0110     } else {
0111         m_wm = new WindowSystem::XWindowInterface(this);
0112     }
0113 
0114     setupWaylandIntegration();
0115 
0116     KPackage::Package package(new Latte::Package(this));
0117 
0118     m_screenPool->load();
0119 
0120     if (!package.isValid()) {
0121         qWarning() << staticMetaObject.className()
0122                    << "the package" << package.metadata().rawData() << "is invalid!";
0123         return;
0124     } else {
0125         qDebug() << staticMetaObject.className()
0126                  << "the package" << package.metadata().rawData() << "is valid!";
0127     }
0128 
0129     setKPackage(package);
0130     //! universal settings / extendedtheme must be loaded after the package has been set
0131     m_universalSettings->load();
0132     m_themeExtended->load();
0133 
0134     qmlRegisterTypes();
0135 
0136     if (m_activitiesConsumer && (m_activitiesConsumer->serviceStatus() == KActivities::Consumer::Running)) {
0137         load();
0138     }
0139 
0140     connect(m_activitiesConsumer, &KActivities::Consumer::serviceStatusChanged, this, &Corona::load);
0141 
0142     m_viewsScreenSyncTimer.setSingleShot(true);
0143     m_viewsScreenSyncTimer.setInterval(m_universalSettings->screenTrackerInterval());
0144     connect(&m_viewsScreenSyncTimer, &QTimer::timeout, this, &Corona::syncLatteViewsToScreens);
0145     connect(m_universalSettings, &UniversalSettings::screenTrackerIntervalChanged, this, [this]() {
0146         m_viewsScreenSyncTimer.setInterval(m_universalSettings->screenTrackerInterval());
0147     });
0148 
0149     //! Dbus adaptor initialization
0150     new LatteDockAdaptor(this);
0151     QDBusConnection dbus = QDBusConnection::sessionBus();
0152     dbus.registerObject(QStringLiteral("/Latte"), this);
0153 }
0154 
0155 Corona::~Corona()
0156 {
0157     /*m_inQuit = true;
0158 
0159     //! BEGIN: Give the time to slide-out views when closing
0160     m_layoutsManager->synchronizer()->hideAllViews();
0161     m_viewSettingsFactory->deleteLater();
0162 
0163     m_viewsScreenSyncTimer.stop();
0164 
0165     if (m_layoutsManager->memoryUsage() == MemoryUsage::SingleLayout) {
0166         cleanConfig();
0167     }
0168 
0169     qDebug() << "Latte Corona - unload: containments ...";
0170     m_layoutsManager->unload();*/
0171 
0172     m_plasmaGeometries->deleteLater();
0173     m_wm->deleteLater();
0174     m_dialogShadows->deleteLater();
0175     m_globalShortcuts->deleteLater();
0176     m_layoutsManager->deleteLater();
0177     m_screenPool->deleteLater();
0178     m_universalSettings->deleteLater();
0179     m_plasmaScreenPool->deleteLater();
0180     m_themeExtended->deleteLater();
0181     m_indicatorFactory->deleteLater();
0182 
0183     disconnect(m_activitiesConsumer, &KActivities::Consumer::serviceStatusChanged, this, &Corona::load);
0184     delete m_activitiesConsumer;
0185 
0186     qDebug() << "Latte Corona - deleted...";
0187 
0188     if (!m_importFullConfigurationFile.isEmpty()) {
0189         //!NOTE: Restart latte to import the new configuration
0190         QString importCommand = "latte-dock --import-full \"" + m_importFullConfigurationFile + "\"";
0191         qDebug() << "Executing Import Full Configuration command : " << importCommand;
0192 
0193         QProcess::startDetached(importCommand);
0194     }
0195 }
0196 
0197 void Corona::onAboutToQuit()
0198 {
0199     m_inQuit = true;
0200 
0201     //! BEGIN: Give the time to slide-out views when closing
0202     m_layoutsManager->synchronizer()->hideAllViews();
0203     m_viewSettingsFactory->deleteLater();
0204 
0205     m_viewsScreenSyncTimer.stop();
0206 
0207     if (m_layoutsManager->memoryUsage() == MemoryUsage::SingleLayout) {
0208         cleanConfig();
0209     }
0210 
0211     if (m_layoutsManager->memoryUsage() == Latte::MemoryUsage::MultipleLayouts) {
0212         m_layoutsManager->importer()->setMultipleLayoutsStatus(Latte::MultipleLayouts::Paused);
0213     }
0214 
0215     qDebug() << "Latte Corona - unload: containments ...";
0216     m_layoutsManager->unload();
0217 }
0218 
0219 void Corona::load()
0220 {
0221     if (m_activitiesConsumer && (m_activitiesConsumer->serviceStatus() == KActivities::Consumer::Running) && m_activitiesStarting) {
0222         m_activitiesStarting = false;
0223 
0224         disconnect(m_activitiesConsumer, &KActivities::Consumer::serviceStatusChanged, this, &Corona::load);
0225 
0226         m_templatesManager->init();
0227         m_layoutsManager->init();
0228 
0229         connect(this, &Corona::availableScreenRectChangedFrom, this, &Plasma::Corona::availableScreenRectChanged, Qt::UniqueConnection);
0230         connect(this, &Corona::availableScreenRegionChangedFrom, this, &Plasma::Corona::availableScreenRegionChanged, Qt::UniqueConnection);
0231         connect(m_screenPool, &ScreenPool::primaryScreenChanged, this, &Corona::onScreenCountChanged, Qt::UniqueConnection);
0232 
0233         QString loadLayoutName = "";
0234 
0235         if (m_userSetMemoryUsage != -1) {
0236             MemoryUsage::LayoutsMemory usage = static_cast<MemoryUsage::LayoutsMemory>(m_userSetMemoryUsage);
0237             m_universalSettings->setLayoutsMemoryUsage(usage);
0238         }
0239 
0240         if (!m_defaultLayoutOnStartup && m_layoutNameOnStartUp.isEmpty()) {
0241             if (m_universalSettings->layoutsMemoryUsage() == MemoryUsage::MultipleLayouts) {
0242                 loadLayoutName = "";
0243             } else {
0244                 loadLayoutName = m_universalSettings->singleModeLayoutName();
0245 
0246                 if (!m_layoutsManager->synchronizer()->layoutExists(loadLayoutName)) {
0247                     //! If chosen layout does not exist, force Default layout loading
0248                     QString defaultLayoutTemplateName = i18n(Templates::DEFAULTLAYOUTTEMPLATENAME);
0249                     loadLayoutName = defaultLayoutTemplateName;
0250 
0251                     if (!m_layoutsManager->synchronizer()->layoutExists(defaultLayoutTemplateName)) {
0252                         //! If Default layout does not exist at all, create it
0253                         QString path = m_templatesManager->newLayout("", defaultLayoutTemplateName);
0254                         m_layoutsManager->setOnAllActivities(Layout::AbstractLayout::layoutName(path));
0255                     }
0256                 }
0257             }
0258         } else if (m_defaultLayoutOnStartup) {
0259             //! force loading a NEW default layout even though a default layout may already exists
0260             QString newDefaultLayoutPath = m_templatesManager->newLayout("", i18n(Templates::DEFAULTLAYOUTTEMPLATENAME));
0261             loadLayoutName = Layout::AbstractLayout::layoutName(newDefaultLayoutPath);
0262             m_universalSettings->setLayoutsMemoryUsage(MemoryUsage::SingleLayout);
0263         } else {
0264             loadLayoutName = m_layoutNameOnStartUp;
0265             m_universalSettings->setLayoutsMemoryUsage(MemoryUsage::SingleLayout);
0266         }
0267 
0268         m_layoutsManager->loadLayoutOnStartup(loadLayoutName);
0269 
0270         //! load screens signals such screenGeometryChanged in order to support
0271         //! plasmoid.screenGeometry properly
0272         for (QScreen *screen : qGuiApp->screens()) {
0273             onScreenAdded(screen);
0274         }
0275 
0276         connect(m_layoutsManager->synchronizer(), &Layouts::Synchronizer::initializationFinished, [this]() {
0277             if (!m_startupAddViewTemplateName.isEmpty()) {
0278                 //! user requested through cmd startup to add view from specific view template and we can add it after the startup
0279                 //! sequence has loaded all required layouts properly
0280                 addView(0, m_startupAddViewTemplateName);
0281                 m_startupAddViewTemplateName = "";
0282             }
0283         });
0284 
0285         m_inStartup = false;
0286 
0287         connect(qGuiApp, &QGuiApplication::screenAdded, this, &Corona::onScreenAdded, Qt::UniqueConnection);
0288         connect(qGuiApp, &QGuiApplication::screenRemoved, this, &Corona::onScreenRemoved, Qt::UniqueConnection);
0289     }
0290 }
0291 
0292 void Corona::unload()
0293 {
0294     qDebug() << "unload: removing containments...";
0295 
0296     while (!containments().isEmpty()) {
0297         //deleting a containment will remove it from the list due to QObject::destroyed connect in Corona
0298         //this form doesn't crash, while qDeleteAll(containments()) does
0299         delete containments().first();
0300     }
0301 }
0302 
0303 void Corona::setupWaylandIntegration()
0304 {
0305     if (!KWindowSystem::isPlatformWayland()) {
0306         return;
0307     }
0308 
0309     using namespace KWayland::Client;
0310 
0311     auto connection = ConnectionThread::fromApplication(this);
0312 
0313     if (!connection) {
0314         return;
0315     }
0316 
0317     Registry *registry{new Registry(this)};
0318     registry->create(connection);
0319 
0320     connect(registry, &Registry::plasmaShellAnnounced, this
0321             , [this, registry](quint32 name, quint32 version) {
0322         m_waylandCorona = registry->createPlasmaShell(name, version, this);
0323     });
0324 
0325     QObject::connect(registry, &KWayland::Client::Registry::plasmaWindowManagementAnnounced,
0326                      [this, registry](quint32 name, quint32 version) {
0327         KWayland::Client::PlasmaWindowManagement *pwm = registry->createPlasmaWindowManagement(name, version, this);
0328 
0329         WindowSystem::WaylandInterface *wI = qobject_cast<WindowSystem::WaylandInterface *>(m_wm);
0330 
0331         if (wI) {
0332             wI->initWindowManagement(pwm);
0333         }
0334     });
0335 
0336 
0337     QObject::connect(registry, &KWayland::Client::Registry::plasmaVirtualDesktopManagementAnnounced,
0338                      [this, registry] (quint32 name, quint32 version) {
0339         KWayland::Client::PlasmaVirtualDesktopManagement *vdm = registry->createPlasmaVirtualDesktopManagement(name, version, this);
0340 
0341         WindowSystem::WaylandInterface *wI = qobject_cast<WindowSystem::WaylandInterface *>(m_wm);
0342 
0343         if (wI) {
0344             wI->initVirtualDesktopManagement(vdm);
0345         }
0346     });
0347 
0348 
0349     registry->setup();
0350     connection->roundtrip();
0351 }
0352 
0353 KWayland::Client::PlasmaShell *Corona::waylandCoronaInterface() const
0354 {
0355     return m_waylandCorona;
0356 }
0357 
0358 void Corona::cleanConfig()
0359 {
0360     auto containmentsEntries = config()->group("Containments");
0361     bool changed = false;
0362 
0363     for(const auto &cId : containmentsEntries.groupList()) {
0364         if (!containmentExists(cId.toUInt())) {
0365             //cleanup obsolete containments
0366             containmentsEntries.group(cId).deleteGroup();
0367             changed = true;
0368             qDebug() << "obsolete containment configuration deleted:" << cId;
0369         } else {
0370             //cleanup obsolete applets of running containments
0371             auto appletsEntries = containmentsEntries.group(cId).group("Applets");
0372 
0373             for(const auto &appletId : appletsEntries.groupList()) {
0374                 if (!appletExists(cId.toUInt(), appletId.toUInt())) {
0375                     appletsEntries.group(appletId).deleteGroup();
0376                     changed = true;
0377                     qDebug() << "obsolete applet configuration deleted:" << appletId;
0378                 }
0379             }
0380         }
0381     }
0382 
0383     if (changed) {
0384         config()->sync();
0385         qDebug() << "configuration file cleaned...";
0386     }
0387 }
0388 
0389 bool Corona::containmentExists(uint id) const
0390 {
0391     for(const auto containment : containments()) {
0392         if (id == containment->id()) {
0393             return true;
0394         }
0395     }
0396 
0397     return false;
0398 }
0399 
0400 bool Corona::appletExists(uint containmentId, uint appletId) const
0401 {
0402     Plasma::Containment *containment = nullptr;
0403 
0404     for(const auto cont : containments()) {
0405         if (containmentId == cont->id()) {
0406             containment = cont;
0407             break;
0408         }
0409     }
0410 
0411     if (!containment) {
0412         return false;
0413     }
0414 
0415     for(const auto applet : containment->applets()) {
0416         if (applet->id() == appletId) {
0417             return true;
0418         }
0419     }
0420 
0421     return false;
0422 }
0423 
0424 bool Corona::inQuit() const
0425 {
0426     return m_inQuit;
0427 }
0428 
0429 KActivities::Consumer *Corona::activitiesConsumer() const
0430 {
0431     return m_activitiesConsumer;
0432 }
0433 
0434 PanelShadows *Corona::dialogShadows() const
0435 {
0436     return m_dialogShadows;
0437 }
0438 
0439 GlobalShortcuts *Corona::globalShortcuts() const
0440 {
0441     return m_globalShortcuts;
0442 }
0443 
0444 ScreenPool *Corona::screenPool() const
0445 {
0446     return m_screenPool;
0447 }
0448 
0449 UniversalSettings *Corona::universalSettings() const
0450 {
0451     return m_universalSettings;
0452 }
0453 
0454 ViewSettingsFactory *Corona::viewSettingsFactory() const
0455 {
0456     return m_viewSettingsFactory;
0457 }
0458 
0459 WindowSystem::AbstractWindowInterface *Corona::wm() const
0460 {
0461     return m_wm;
0462 }
0463 
0464 Indicator::Factory *Corona::indicatorFactory() const
0465 {
0466     return m_indicatorFactory;
0467 }
0468 
0469 Layouts::Manager *Corona::layoutsManager() const
0470 {
0471     return m_layoutsManager;
0472 }
0473 
0474 Templates::Manager *Corona::templatesManager() const
0475 {
0476     return m_templatesManager;
0477 }
0478 
0479 PlasmaExtended::ScreenPool *Corona::plasmaScreenPool() const
0480 {
0481     return m_plasmaScreenPool;
0482 }
0483 
0484 PlasmaExtended::Theme *Corona::themeExtended() const
0485 {
0486     return m_themeExtended;
0487 }
0488 
0489 int Corona::numScreens() const
0490 {
0491     return qGuiApp->screens().count();
0492 }
0493 
0494 QRect Corona::screenGeometry(int id) const
0495 {
0496     const auto screens = qGuiApp->screens();
0497     const QScreen *screen{m_screenPool->primaryScreen()};
0498 
0499     QString screenName;
0500 
0501     if (m_screenPool->hasScreenId(id)) {
0502         screenName = m_screenPool->connector(id);
0503     }
0504 
0505     for(const auto scr : screens) {
0506         if (scr->name() == screenName) {
0507             screen = scr;
0508             break;
0509         }
0510     }
0511 
0512     return screen->geometry();
0513 }
0514 
0515 CentralLayout *Corona::centralLayout(QString name) const
0516 {
0517     CentralLayout *result{nullptr};
0518 
0519     if (!name.isEmpty()) {
0520         result = m_layoutsManager->synchronizer()->centralLayout(name);
0521     }
0522 
0523     return result;
0524 }
0525 
0526 Layout::GenericLayout *Corona::layout(QString name) const
0527 {
0528     Layout::GenericLayout *result{nullptr};
0529 
0530     if (!name.isEmpty()) {
0531         result = m_layoutsManager->synchronizer()->layout(name);
0532     }
0533 
0534     return result;
0535 }
0536 
0537 QRegion Corona::availableScreenRegion(int id) const
0538 {   
0539     //! ignore modes are added in order for notifications to be placed
0540     //! in better positioning and not overlap with sidebars or usually hidden views
0541     QList<Types::Visibility> ignoremodes({Latte::Types::AutoHide,
0542                                           Latte::Types::SidebarOnDemand,
0543                                           Latte::Types::SidebarAutoHide});
0544 
0545 
0546     return availableScreenRegionWithCriteria(id,
0547                                              QString(),
0548                                              ignoremodes);
0549 }
0550 
0551 QRegion Corona::availableScreenRegionWithCriteria(int id,
0552                                                   QString activityid,
0553                                                   QList<Types::Visibility> ignoreModes,
0554                                                   QList<Plasma::Types::Location> ignoreEdges,
0555                                                   bool ignoreExternalPanels,
0556                                                   bool desktopUse) const
0557 {
0558     const QScreen *screen = m_screenPool->screenForId(id);
0559     bool inCurrentActivity{activityid.isEmpty()};
0560 
0561     if (!screen) {
0562         return {};
0563     }
0564 
0565     QRegion available = ignoreExternalPanels ? screen->geometry() : screen->availableGeometry();
0566 
0567     QList<Latte::View *> views;
0568 
0569     if (inCurrentActivity) {
0570         views = m_layoutsManager->synchronizer()->viewsBasedOnActivityId(m_activitiesConsumer->currentActivity());
0571     } else {
0572         views = m_layoutsManager->synchronizer()->viewsBasedOnActivityId(activityid);
0573     }
0574 
0575     if (views.isEmpty()) {
0576         return available;
0577     }
0578 
0579     //! blacklist irrelevant visibility modes
0580     if (!ignoreModes.contains(Latte::Types::None)) {
0581         ignoreModes << Latte::Types::None;
0582     }
0583 
0584     if (!ignoreModes.contains(Latte::Types::NormalWindow)) {
0585         ignoreModes << Latte::Types::NormalWindow;
0586     }
0587 
0588     bool allEdges = ignoreEdges.isEmpty();
0589 
0590     for (const auto *view : views) {
0591         bool inDesktopOffScreenStartup = desktopUse && view && view->positioner() && view->positioner()->isOffScreen();
0592 
0593         if (view && view->containment() && view->screen() == screen && !inDesktopOffScreenStartup
0594                 && ((allEdges || !ignoreEdges.contains(view->location()))
0595                     && (view->visibility() && !ignoreModes.contains(view->visibility()->mode())))) {
0596             int realThickness = view->normalThickness();
0597 
0598             int x = 0; int y = 0; int w = 0; int h = 0;
0599 
0600             switch (view->formFactor()) {
0601             case Plasma::Types::Horizontal:
0602                 if (view->behaveAsPlasmaPanel()) {
0603                     w = view->width();
0604                     x = view->x();
0605                 } else {
0606                     w = view->maxLength() * view->width();
0607                     int offsetW = view->offset() * view->width();
0608 
0609                     switch (view->alignment()) {
0610                     case Latte::Types::Left:
0611                         x = view->x() + offsetW;
0612                         break;
0613 
0614                     case Latte::Types::Center:
0615                     case Latte::Types::Justify:
0616                         x = (view->geometry().center().x() - w/2) + 1 + offsetW;
0617                         break;
0618 
0619                     case Latte::Types::Right:
0620                         x = view->geometry().right() + 1 - w - offsetW;
0621                         break;
0622                     }
0623                 }
0624                 break;
0625             case Plasma::Types::Vertical:
0626                 if (view->behaveAsPlasmaPanel()) {
0627                     h = view->height();
0628                     y = view->y();
0629                 } else {
0630                     h = view->maxLength() * view->height();
0631                     int offsetH = view->offset() * view->height();
0632 
0633                     switch (view->alignment()) {
0634                     case Latte::Types::Top:
0635                         y = view->y() + offsetH;
0636                         break;
0637 
0638                     case Latte::Types::Center:
0639                     case Latte::Types::Justify:
0640                         y = (view->geometry().center().y() - h/2) + 1 + offsetH;
0641                         break;
0642 
0643                     case Latte::Types::Bottom:
0644                         y = view->geometry().bottom() - h - offsetH;
0645                         break;
0646                     }
0647                 }
0648                 break;
0649             }
0650 
0651             // Usually availableScreenRect is used by the desktop,
0652             // but Latte don't have desktop, then here just
0653             // need calculate available space for top and bottom location,
0654             // because the left and right are those who dodge others views
0655             switch (view->location()) {
0656             case Plasma::Types::TopEdge:
0657                 if (view->behaveAsPlasmaPanel()) {
0658                     QRect viewGeometry = view->geometry();
0659 
0660                     if (desktopUse) {
0661                         //! ignore any real window slide outs in all cases
0662                         viewGeometry.moveTop(view->screen()->geometry().top() + view->screenEdgeMargin());
0663                     }
0664 
0665                     available -= viewGeometry;
0666                 } else {                  
0667                     y = view->y();
0668                     available -= QRect(x, y, w, realThickness);
0669                 }
0670 
0671                 break;
0672 
0673             case Plasma::Types::BottomEdge:
0674                 if (view->behaveAsPlasmaPanel()) {
0675                     QRect viewGeometry = view->geometry();
0676 
0677                     if (desktopUse) {
0678                         //! ignore any real window slide outs in all cases
0679                         viewGeometry.moveTop(view->screen()->geometry().bottom() - view->screenEdgeMargin() - viewGeometry.height());
0680                     }
0681 
0682                     available -= viewGeometry;
0683                 } else {
0684                     y = view->geometry().bottom() - realThickness + 1;
0685                     available -= QRect(x, y, w, realThickness);
0686                 }
0687 
0688                 break;
0689 
0690             case Plasma::Types::LeftEdge:
0691                 if (view->behaveAsPlasmaPanel()) {
0692                     QRect viewGeometry = view->geometry();
0693 
0694                     if (desktopUse) {
0695                         //! ignore any real window slide outs in all cases
0696                         viewGeometry.moveLeft(view->screen()->geometry().left() + view->screenEdgeMargin());
0697                     }
0698 
0699                     available -= viewGeometry;
0700                 } else {
0701                     x = view->x();
0702                     available -= QRect(x, y, realThickness, h);
0703                 }
0704 
0705                 break;
0706 
0707             case Plasma::Types::RightEdge:
0708                 if (view->behaveAsPlasmaPanel()) {
0709                     QRect viewGeometry = view->geometry();
0710 
0711                     if (desktopUse) {
0712                         //! ignore any real window slide outs in all cases
0713                         viewGeometry.moveLeft(view->screen()->geometry().right() - view->screenEdgeMargin() - viewGeometry.width());
0714                     }
0715 
0716                     available -= viewGeometry;
0717                 } else {                    
0718                     x = view->geometry().right() - realThickness + 1;
0719                     available -= QRect(x, y, realThickness, h);
0720                 }
0721 
0722                 break;
0723 
0724             default:
0725                 //! bypass clang warnings
0726                 break;
0727             }
0728         }
0729     }
0730 
0731     /*qDebug() << "::::: FREE AREAS :::::";
0732 
0733     for (int i = 0; i < available.rectCount(); ++i) {
0734         qDebug() << available.rects().at(i);
0735     }
0736 
0737     qDebug() << "::::: END OF FREE AREAS :::::";*/
0738 
0739     return available;
0740 }
0741 
0742 QRect Corona::availableScreenRect(int id) const
0743 {
0744     //! ignore modes are added in order for notifications to be placed
0745     //! in better positioning and not overlap with sidebars or usually hidden views
0746     QList<Types::Visibility> ignoremodes({Latte::Types::AutoHide,
0747                                           Latte::Types::SidebarOnDemand,
0748                                           Latte::Types::SidebarAutoHide});
0749 
0750     return availableScreenRectWithCriteria(id,
0751                                            QString(),
0752                                            ignoremodes);
0753 }
0754 
0755 QRect Corona::availableScreenRectWithCriteria(int id,
0756                                               QString activityid,
0757                                               QList<Types::Visibility> ignoreModes,
0758                                               QList<Plasma::Types::Location> ignoreEdges,
0759                                               bool ignoreExternalPanels,
0760                                               bool desktopUse) const
0761 {
0762     const QScreen *screen = m_screenPool->screenForId(id);
0763     bool inCurrentActivity{activityid.isEmpty()};
0764 
0765     if (!screen) {
0766         return {};
0767     }
0768 
0769     QRect available = ignoreExternalPanels ? screen->geometry() : screen->availableGeometry();
0770 
0771     QList<Latte::View *> views;
0772 
0773     if (inCurrentActivity) {
0774         views = m_layoutsManager->synchronizer()->viewsBasedOnActivityId(m_activitiesConsumer->currentActivity());
0775     } else {
0776         views = m_layoutsManager->synchronizer()->viewsBasedOnActivityId(activityid);
0777     }
0778 
0779     if (views.isEmpty()) {
0780         return available;
0781     }
0782 
0783     //! blacklist irrelevant visibility modes
0784     if (!ignoreModes.contains(Latte::Types::None)) {
0785         ignoreModes << Latte::Types::None;
0786     }
0787 
0788     if (!ignoreModes.contains(Latte::Types::NormalWindow)) {
0789         ignoreModes << Latte::Types::NormalWindow;
0790     }
0791 
0792     bool allEdges = ignoreEdges.isEmpty();
0793 
0794     for (const auto *view : views) {
0795         bool inDesktopOffScreenStartup = desktopUse && view && view->positioner() && view->positioner()->isOffScreen();
0796 
0797         if (view && view->containment() && view->screen() == screen && !inDesktopOffScreenStartup
0798                 && ((allEdges || !ignoreEdges.contains(view->location()))
0799                     && (view->visibility() && !ignoreModes.contains(view->visibility()->mode())))) {
0800 
0801             int appliedThickness = view->behaveAsPlasmaPanel() ? view->screenEdgeMargin() + view->normalThickness() : view->normalThickness();
0802 
0803             // Usually availableScreenRect is used by the desktop,
0804             // but Latte don't have desktop, then here just
0805             // need calculate available space for top and bottom location,
0806             // because the left and right are those who dodge others docks
0807             switch (view->location()) {
0808             case Plasma::Types::TopEdge:
0809                 if (view->behaveAsPlasmaPanel() && desktopUse) {
0810                     //! ignore any real window slide outs in all cases
0811                     available.setTop(qMax(available.top(), view->screen()->geometry().top() + appliedThickness));
0812                 } else {
0813                     available.setTop(qMax(available.top(), view->y() + appliedThickness));
0814                 }
0815                 break;
0816 
0817             case Plasma::Types::BottomEdge:
0818                 if (view->behaveAsPlasmaPanel() && desktopUse) {
0819                     //! ignore any real window slide outs in all cases
0820                     available.setBottom(qMin(available.bottom(), view->screen()->geometry().bottom() - appliedThickness));
0821                 } else {
0822                     available.setBottom(qMin(available.bottom(), view->y() + view->height() - appliedThickness));
0823                 }
0824                 break;
0825 
0826             case Plasma::Types::LeftEdge:
0827                 if (view->behaveAsPlasmaPanel() && desktopUse) {
0828                     //! ignore any real window slide outs in all cases
0829                     available.setLeft(qMax(available.left(), view->screen()->geometry().left() + appliedThickness));
0830                 } else {
0831                     available.setLeft(qMax(available.left(), view->x() + appliedThickness));
0832                 }
0833                 break;
0834 
0835             case Plasma::Types::RightEdge:
0836                 if (view->behaveAsPlasmaPanel() && desktopUse) {
0837                     //! ignore any real window slide outs in all cases
0838                     available.setRight(qMin(available.right(), view->screen()->geometry().right() - appliedThickness));
0839                 } else {
0840                     available.setRight(qMin(available.right(), view->x() + view->width() - appliedThickness));
0841                 }
0842                 break;
0843 
0844             default:
0845                 //! bypass clang warnings
0846                 break;
0847             }
0848         }
0849     }
0850 
0851     return available;
0852 }
0853 
0854 void Corona::onScreenAdded(QScreen *screen)
0855 {
0856     Q_ASSERT(screen);
0857 
0858     int id = m_screenPool->id(screen->name());
0859 
0860     if (id == -1) {
0861         m_screenPool->insertScreenMapping(screen->name());
0862     }
0863 
0864     connect(screen, &QScreen::geometryChanged, this, &Corona::onScreenGeometryChanged);
0865 
0866     emit availableScreenRectChanged();
0867     emit screenAdded(m_screenPool->id(screen->name()));
0868 
0869     onScreenCountChanged();
0870 }
0871 
0872 void Corona::onScreenRemoved(QScreen *screen)
0873 {
0874     disconnect(screen, &QScreen::geometryChanged, this, &Corona::onScreenGeometryChanged);
0875     onScreenCountChanged();
0876 }
0877 
0878 void Corona::onScreenCountChanged()
0879 {
0880     m_viewsScreenSyncTimer.start();
0881 }
0882 
0883 void Corona::onScreenGeometryChanged(const QRect &geometry)
0884 {
0885     Q_UNUSED(geometry);
0886 
0887     QScreen *screen = qobject_cast<QScreen *>(sender());
0888 
0889     if (!screen) {
0890         return;
0891     }
0892 
0893     const int id = m_screenPool->id(screen->name());
0894 
0895     if (id >= 0) {
0896         emit screenGeometryChanged(id);
0897         emit availableScreenRegionChanged();
0898         emit availableScreenRectChanged();
0899     }
0900 }
0901 
0902 //! the central functions that updates loading/unloading latteviews
0903 //! concerning screen changed (for multi-screen setups mainly)
0904 void Corona::syncLatteViewsToScreens()
0905 {
0906     m_layoutsManager->synchronizer()->syncLatteViewsToScreens();
0907 }
0908 
0909 int Corona::primaryScreenId() const
0910 {
0911     return m_screenPool->primaryScreenId();
0912 }
0913 
0914 void Corona::quitApplication()
0915 {
0916     m_inQuit = true;
0917 
0918     //! this code must be called asynchronously because it is called
0919     //! also from qml (Settings window).
0920     QTimer::singleShot(300, [this]() {
0921         m_layoutsManager->hideLatteSettingsDialog();
0922         m_layoutsManager->synchronizer()->hideAllViews();
0923     });
0924 
0925     //! give the time for the views to hide themselves
0926     QTimer::singleShot(800, [this]() {
0927         qGuiApp->quit();
0928     });
0929 }
0930 
0931 void Corona::aboutApplication()
0932 {
0933     if (aboutDialog) {
0934         aboutDialog->hide();
0935         aboutDialog->deleteLater();
0936     }
0937 
0938     aboutDialog = new KAboutApplicationDialog(KAboutData::applicationData());
0939     connect(aboutDialog.data(), &QDialog::finished, aboutDialog.data(), &QObject::deleteLater);
0940     m_wm->skipTaskBar(*aboutDialog);
0941     m_wm->setKeepAbove(aboutDialog->winId(), true);
0942 
0943     aboutDialog->show();
0944 }
0945 
0946 void Corona::loadDefaultLayout()
0947 {
0948   //disabled
0949 }
0950 
0951 int Corona::screenForContainment(const Plasma::Containment *containment) const
0952 {
0953     //FIXME: indexOf is not a proper way to support multi-screen
0954     // as for environment to environment the indexes change
0955     // also there is the following issue triggered
0956     // from latteView adaptToScreen()
0957     //
0958     // in a multi-screen environment that
0959     // primary screen is not set to 0 it was
0960     // created an endless showing loop at
0961     // startup (catch-up race) between
0962     // screen:0 and primaryScreen
0963 
0964     //case in which this containment is child of an applet, hello systray :)
0965     if (Plasma::Applet *parentApplet = qobject_cast<Plasma::Applet *>(containment->parent())) {
0966         if (Plasma::Containment *cont = parentApplet->containment()) {
0967             return screenForContainment(cont);
0968         } else {
0969             return -1;
0970         }
0971     }
0972 
0973     Plasma::Containment *c = const_cast<Plasma::Containment *>(containment);
0974     int scrId = m_layoutsManager->synchronizer()->screenForContainment(c);
0975 
0976     if (scrId >= 0) {
0977         return scrId;
0978     }
0979 
0980     return containment->lastScreen();
0981 }
0982 
0983 void Corona::showAlternativesForApplet(Plasma::Applet *applet)
0984 {
0985     const QString alternativesQML = kPackage().filePath("appletalternativesui");
0986 
0987     if (alternativesQML.isEmpty()) {
0988         return;
0989     }
0990 
0991     Latte::View *latteView =  m_layoutsManager->synchronizer()->viewForContainment(applet->containment());
0992 
0993     KDeclarative::QmlObjectSharedEngine *qmlObj{nullptr};
0994 
0995     if (latteView) {
0996         latteView->setAlternativesIsShown(true);
0997         qmlObj = new KDeclarative::QmlObjectSharedEngine(latteView);
0998     } else {
0999         qmlObj = new KDeclarative::QmlObjectSharedEngine(this);
1000     }
1001 
1002     qmlObj->setInitializationDelayed(true);
1003     qmlObj->setSource(QUrl::fromLocalFile(alternativesQML));
1004 
1005     AlternativesHelper *helper = new AlternativesHelper(applet, qmlObj);
1006     qmlObj->rootContext()->setContextProperty(QStringLiteral("alternativesHelper"), helper);
1007 
1008     m_alternativesObjects << qmlObj;
1009     qmlObj->completeInitialization();
1010 
1011     //! Alternative dialog signals
1012     connect(helper, &QObject::destroyed, this, [latteView]() {
1013         latteView->setAlternativesIsShown(false);
1014     });
1015 
1016     connect(qmlObj->rootObject(), SIGNAL(visibleChanged(bool)),
1017             this, SLOT(alternativesVisibilityChanged(bool)));
1018 
1019     connect(applet, &Plasma::Applet::destroyedChanged, this, [this, qmlObj](bool destroyed) {
1020         if (!destroyed) {
1021             return;
1022         }
1023 
1024         QMutableListIterator<KDeclarative::QmlObjectSharedEngine *> it(m_alternativesObjects);
1025 
1026         while (it.hasNext()) {
1027             KDeclarative::QmlObjectSharedEngine *obj = it.next();
1028 
1029             if (obj == qmlObj) {
1030                 it.remove();
1031                 obj->deleteLater();
1032             }
1033         }
1034     });
1035 }
1036 
1037 void Corona::alternativesVisibilityChanged(bool visible)
1038 {
1039     if (visible) {
1040         return;
1041     }
1042 
1043     QObject *root = sender();
1044 
1045     QMutableListIterator<KDeclarative::QmlObjectSharedEngine *> it(m_alternativesObjects);
1046 
1047     while (it.hasNext()) {
1048         KDeclarative::QmlObjectSharedEngine *obj = it.next();
1049 
1050         if (obj->rootObject() == root) {
1051             it.remove();
1052             obj->deleteLater();
1053         }
1054     }
1055 }
1056 
1057 QStringList Corona::containmentsIds()
1058 {
1059     QStringList ids;
1060 
1061     for(const auto containment : containments()) {
1062         ids << QString::number(containment->id());
1063     }
1064 
1065     return ids;
1066 }
1067 
1068 QStringList Corona::appletsIds()
1069 {
1070     QStringList ids;
1071 
1072     for(const auto containment : containments()) {
1073         auto applets = containment->config().group("Applets");
1074         ids << applets.groupList();
1075     }
1076 
1077     return ids;
1078 }
1079 
1080 //! Activate launcher menu through dbus interface
1081 void Corona::activateLauncherMenu()
1082 {
1083     m_globalShortcuts->activateLauncherMenu();
1084 }
1085 
1086 void Corona::windowColorScheme(QString windowIdAndScheme)
1087 {
1088     int firstSlash = windowIdAndScheme.indexOf("-");
1089     QString windowIdStr = windowIdAndScheme.mid(0, firstSlash);
1090     QString schemeStr = windowIdAndScheme.mid(firstSlash + 1);
1091 
1092     if (KWindowSystem::isPlatformWayland()) {
1093         QTimer::singleShot(200, [this, schemeStr]() {
1094             //! [Wayland Case] - give the time to be informed correctly for the active window id
1095             //! otherwise the active window id may not be the same with the one trigerred
1096             //! the color scheme dbus signal
1097             QString windowIdStr = m_wm->activeWindow().toString();
1098             m_wm->schemesTracker()->setColorSchemeForWindow(windowIdStr.toUInt(), schemeStr);
1099         });
1100     } else {
1101         m_wm->schemesTracker()->setColorSchemeForWindow(windowIdStr.toUInt(), schemeStr);
1102     }
1103 }
1104 
1105 //! update badge for specific view item
1106 void Corona::updateDockItemBadge(QString identifier, QString value)
1107 {
1108     m_globalShortcuts->updateViewItemBadge(identifier, value);
1109 }
1110 
1111 void Corona::setAutostart(const bool &enabled)
1112 {
1113     m_universalSettings->setAutostart(enabled);
1114 }
1115 
1116 void Corona::switchToLayout(QString layout)
1117 {
1118     if ((layout.startsWith("file:/") || layout.startsWith("/")) && layout.endsWith(".layout.latte")) {
1119         importLayoutFile(layout);
1120     } else {
1121         m_layoutsManager->switchToLayout(layout);
1122     }
1123 }
1124 
1125 void Corona::importLayoutFile(const QString &filepath, const QString &suggestedLayoutName)
1126 {
1127     bool isFilepathValid = (filepath.startsWith("file:/") || filepath.startsWith("/")) && filepath.endsWith(".layout.latte");
1128 
1129     if (!isFilepathValid) {
1130         qDebug() << i18n("The layout cannot be imported from file :: ") << filepath;
1131         return;
1132     }
1133 
1134     //! Import and load runtime a layout through dbus interface
1135     //! It can be used from external programs that want to update runtime
1136     //! the Latte shown layout
1137     QString layoutPath = filepath;
1138 
1139     //! cleanup layout path
1140     if (layoutPath.startsWith("file:///")) {
1141         layoutPath = layoutPath.remove("file://");
1142     } else if (layoutPath.startsWith("file://")) {
1143         layoutPath = layoutPath.remove("file:/");
1144     }
1145 
1146     //! check out layoutpath existence
1147     if (QFileInfo(layoutPath).exists()) {
1148         qDebug() << " Layout is going to be imported and loaded from file :: " << layoutPath << " with suggested name :: " << suggestedLayoutName;
1149 
1150         QString importedLayout = m_layoutsManager->importer()->importLayout(layoutPath, suggestedLayoutName);
1151 
1152         if (importedLayout.isEmpty()) {
1153             qDebug() << i18n("The layout cannot be imported from file :: ") << layoutPath;
1154         } else {
1155            m_layoutsManager->switchToLayout(importedLayout, MemoryUsage::SingleLayout);
1156         }
1157     } else {
1158         qDebug() << " Layout from missing file can not be imported and loaded :: " << layoutPath;
1159     }
1160 }
1161 
1162 void Corona::showSettingsWindow(int page)
1163 {
1164     if (m_inStartup) {
1165         return;
1166     }
1167 
1168     Settings::Dialog::ConfigurationPage p = Settings::Dialog::LayoutPage;
1169 
1170     if (page >= Settings::Dialog::LayoutPage && page <= Settings::Dialog::PreferencesPage) {
1171         p = static_cast<Settings::Dialog::ConfigurationPage>(page);
1172     }
1173 
1174     m_layoutsManager->showLatteSettingsDialog(p);
1175 }
1176 
1177 QStringList Corona::contextMenuData(const uint &containmentId)
1178 {
1179     QStringList data;
1180     Types::ViewType viewType{Types::DockView};
1181     auto view = m_layoutsManager->synchronizer()->viewForContainment(containmentId);
1182 
1183     if (view) {
1184         viewType = view->type();
1185     }
1186 
1187     data << QString::number((int)m_layoutsManager->memoryUsage()); // Memory Usage
1188     data << m_layoutsManager->centralLayoutsNames().join(";;"); // All Active layouts
1189     data << m_layoutsManager->synchronizer()->currentLayoutsNames().join(";;"); // All Current layouts
1190     data << m_universalSettings->contextMenuActionsAlwaysShown().join(";;");
1191 
1192     QStringList layoutsmenu;
1193 
1194     for(const auto &layoutName : m_layoutsManager->synchronizer()->menuLayouts()) {
1195         if (m_layoutsManager->synchronizer()->centralLayout(layoutName)
1196                 || m_layoutsManager->memoryUsage() == Latte::MemoryUsage::SingleLayout) {
1197             QStringList layoutdata;
1198             Data::LayoutIcon layouticon = m_layoutsManager->iconForLayout(layoutName);
1199             layoutdata << layoutName;
1200             layoutdata << QString::number(layouticon.isBackgroundFile);
1201             layoutdata << layouticon.name;
1202             layoutsmenu << layoutdata.join("**");
1203         }
1204     }
1205 
1206     data << layoutsmenu.join(";;");
1207     data << (view ? view->layout()->name() : QString());   //Selected View layout*/
1208 
1209     QStringList viewtype;
1210     viewtype << QString::number((int)viewType); //Selected View type
1211 
1212     if (view && view->isOriginal()) { /*View*/
1213         auto originalview = qobject_cast<Latte::OriginalView *>(view);
1214         viewtype << "0";              //original view
1215         viewtype <<  QString::number(originalview->clonesCount());
1216     } else if (view && view->isCloned()) {
1217         viewtype << "1";              //cloned view
1218         viewtype << "0";              //has no clones
1219     } else {
1220         viewtype << "0";              //original view
1221         viewtype << "0";              //has no clones
1222     }
1223 
1224     data << viewtype.join(";;");
1225 
1226     return data;
1227 }
1228 
1229 QStringList Corona::viewTemplatesData()
1230 {
1231     QStringList data;
1232 
1233     Latte::Data::GenericTable<Data::Generic> viewtemplates = m_templatesManager->viewTemplates();
1234 
1235     for(int i=0; i<viewtemplates.rowCount(); ++i) {
1236         data << viewtemplates[i].name;
1237         data << viewtemplates[i].id;
1238     }
1239 
1240     return data;
1241 }
1242 
1243 void Corona::addView(const uint &containmentId, const QString &templateId)
1244 {
1245     if (containmentId <= 0) {
1246         auto currentlayouts = m_layoutsManager->currentLayouts();
1247         if (currentlayouts.count() > 0) {
1248             currentlayouts[0]->newView(templateId);
1249         }
1250     } else {
1251         auto view = m_layoutsManager->synchronizer()->viewForContainment((int)containmentId);
1252         if (view) {
1253             view->newView(templateId);
1254         }
1255     }
1256 }
1257 
1258 void Corona::duplicateView(const uint &containmentId)
1259 {
1260     auto view = m_layoutsManager->synchronizer()->viewForContainment((int)containmentId);
1261     if (view) {
1262         view->duplicateView();
1263     }
1264 }
1265 
1266 void Corona::exportViewTemplate(const uint &containmentId)
1267 {
1268     auto view = m_layoutsManager->synchronizer()->viewForContainment((int)containmentId);
1269     if (view) {
1270         view->exportTemplate();
1271     }
1272 }
1273 
1274 void Corona::moveViewToLayout(const uint &containmentId, const QString &layoutName)
1275 {
1276     auto view = m_layoutsManager->synchronizer()->viewForContainment((int)containmentId);
1277     if (view && !layoutName.isEmpty() && view->layout()->name() != layoutName) {
1278         Latte::Types::ScreensGroup screensgroup{Latte::Types::SingleScreenGroup};
1279 
1280         if (view->isOriginal()) {
1281             auto originalview = qobject_cast<Latte::OriginalView *>(view);
1282             screensgroup = originalview->screensGroup();
1283         }
1284 
1285         view->positioner()->setNextLocation(layoutName, screensgroup, "", Plasma::Types::Floating, Latte::Types::NoneAlignment);
1286     }
1287 }
1288 
1289 void Corona::removeView(const uint &containmentId)
1290 {
1291     auto view = m_layoutsManager->synchronizer()->viewForContainment((int)containmentId);
1292     if (view) {
1293         view->removeView();
1294     }
1295 }
1296 
1297 void Corona::setBackgroundFromBroadcast(QString activity, QString screenName, QString filename)
1298 {
1299     if (filename.startsWith("file://")) {
1300         filename = filename.remove(0,7);
1301     }
1302 
1303     PlasmaExtended::BackgroundCache::self()->setBackgroundFromBroadcast(activity, screenName, filename);
1304 }
1305 
1306 void Corona::setBroadcastedBackgroundsEnabled(QString activity, QString screenName, bool enabled)
1307 {
1308     PlasmaExtended::BackgroundCache::self()->setBroadcastedBackgroundsEnabled(activity, screenName, enabled);
1309 }
1310 
1311 void Corona::toggleHiddenState(QString layoutName, QString viewName, QString screenName, int screenEdge)
1312 {
1313     if (layoutName.isEmpty()) {
1314         for(auto layout : m_layoutsManager->currentLayouts()) {
1315             layout->toggleHiddenState(viewName, screenName, (Plasma::Types::Location)screenEdge);
1316         }
1317     } else {
1318         Layout::GenericLayout *gLayout = layout(layoutName);
1319 
1320         if (gLayout) {
1321             gLayout->toggleHiddenState(viewName, screenName, (Plasma::Types::Location)screenEdge);
1322         }
1323     }
1324 }
1325 
1326 void Corona::importFullConfiguration(const QString &file)
1327 {
1328     m_importFullConfigurationFile = file;
1329     quitApplication();
1330 }
1331 
1332 inline void Corona::qmlRegisterTypes() const
1333 {   
1334     qmlRegisterUncreatableMetaObject(Latte::Settings::staticMetaObject,
1335                                      "org.kde.latte.private.app",          // import statement
1336                                      0, 1,                                 // major and minor version of the import
1337                                      "Settings",                           // name in QML
1338                                      "Error: only enums of latte app settings");
1339 
1340     qmlRegisterType<Latte::BackgroundTracker>("org.kde.latte.private.app", 0, 1, "BackgroundTracker");
1341     qmlRegisterType<Latte::Interfaces>("org.kde.latte.private.app", 0, 1, "Interfaces");
1342     qmlRegisterType<Latte::ContextMenuLayerQuickItem>("org.kde.latte.private.app", 0, 1, "ContextMenuLayer");
1343     qmlRegisterAnonymousType<QScreen>("latte-dock", 1);
1344     qmlRegisterAnonymousType<Latte::View>("latte-dock", 1);
1345     qmlRegisterAnonymousType<Latte::ViewPart::WindowsTracker>("latte-dock", 1);
1346     qmlRegisterAnonymousType<Latte::ViewPart::TrackerPart::CurrentScreenTracker>("latte-dock", 1);
1347     qmlRegisterAnonymousType<Latte::ViewPart::TrackerPart::AllScreensTracker>("latte-dock", 1);
1348     qmlRegisterAnonymousType<Latte::WindowSystem::SchemeColors>("latte-dock", 1);
1349     qmlRegisterAnonymousType<Latte::WindowSystem::Tracker::LastActiveWindow>("latte-dock", 1);
1350     qmlRegisterAnonymousType<Latte::Types>("latte-dock", 1);
1351 
1352 }
1353 
1354 }