1
0
mirror of https://github.com/KDE/latte-dock.git synced 2025-01-25 14:03:58 +03:00
latte-dock/app/layouts/synchronizer.cpp
2020-10-25 17:00:17 +02:00

983 lines
29 KiB
C++

/*
* Copyright 2019 Michail Vourlakos <mvourlakos@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "synchronizer.h"
//! local
#include "importer.h"
#include "manager.h"
#include "../apptypes.h"
#include "../data/layoutdata.h"
#include "../lattecorona.h"
#include "../layout/centrallayout.h"
#include "../layout/genericlayout.h"
#include "../settings/universalsettings.h"
#include "../templates/templatesmanager.h"
#include "../view/view.h"
// Qt
#include <QDir>
#include <QFile>
// Plasma
#include <Plasma/Containment>
// KDE
#include <KActivities/Consumer>
#include <KActivities/Controller>
#include <KWindowSystem>
#define LAYOUTSINITINTERVAL 350
namespace Latte {
namespace Layouts {
Synchronizer::Synchronizer(QObject *parent)
: QObject(parent),
m_activitiesController(new KActivities::Controller)
{
m_manager = qobject_cast<Manager *>(parent);
connect(this, &Synchronizer::layoutsChanged, this, &Synchronizer::reloadAssignedLayouts);
//! KWin update Disabled Borders
connect(this, &Synchronizer::centralLayoutsChanged, this, &Synchronizer::updateKWinDisabledBorders);
connect(m_manager->corona()->universalSettings(), &UniversalSettings::canDisableBordersChanged, this, &Synchronizer::updateKWinDisabledBorders);
//! KActivities tracking
connect(m_manager->corona()->activitiesConsumer(), &KActivities::Consumer::activityRemoved,
this, &Synchronizer::onActivityRemoved);
connect(m_manager->corona()->activitiesConsumer(), &KActivities::Consumer::currentActivityChanged,
this, &Synchronizer::onCurrentActivityChanged);
connect(m_manager->corona()->activitiesConsumer(), &KActivities::Consumer::runningActivitiesChanged,
this, [&]() {
if (m_manager->memoryUsage() == MemoryUsage::MultipleLayouts) {
syncMultipleLayoutsToActivities();
}
});
}
Synchronizer::~Synchronizer()
{
m_activitiesController->deleteLater();
}
KActivities::Controller *Synchronizer::activitiesController() const
{
return m_activitiesController;
}
bool Synchronizer::latteViewExists(Latte::View *view) const
{
for (const auto layout : m_centralLayouts) {
for (const auto &v : layout->latteViews()) {
if (v == view) {
return true;
}
}
}
return false;
}
bool Synchronizer::layoutExists(QString layoutName) const
{
return m_layouts.containsName(layoutName);
}
bool Synchronizer::isAssigned(QString layoutName) const
{
for(auto activityid : m_assignedLayouts.keys()) {
if (m_assignedLayouts[activityid].contains(layoutName)) {
return true;
}
}
return false;
}
int Synchronizer::centralLayoutPos(QString id) const
{
for (int i = 0; i < m_centralLayouts.size(); ++i) {
CentralLayout *layout = m_centralLayouts.at(i);
if (layout->name() == id) {
return i;
}
}
return -1;
}
QString Synchronizer::layoutPath(QString layoutName)
{
QString path = Layouts::Importer::layoutUserFilePath(layoutName);
if (!QFile(path).exists()) {
path = "";
}
return path;
}
QStringList Synchronizer::activities()
{
return m_manager->corona()->activitiesConsumer()->activities();
}
QStringList Synchronizer::freeActivities()
{
QStringList frees = activities();
for(auto assigned : m_assignedLayouts.keys()) {
frees.removeAll(assigned);
}
return frees;
}
QStringList Synchronizer::runningActivities()
{
return m_manager->corona()->activitiesConsumer()->runningActivities();
}
QStringList Synchronizer::freeRunningActivities()
{
QStringList fActivities;
for (const auto &activity : runningActivities()) {
if (!m_assignedLayouts.contains(activity)) {
fActivities.append(activity);
}
}
return fActivities;
}
QStringList Synchronizer::validActivities(const QStringList &layoutActivities)
{
QStringList valids;
QStringList allactivities = activities();
for(auto activity : layoutActivities) {
if (allactivities.contains(activity)) {
valids << activity;
}
}
return valids;
}
QStringList Synchronizer::centralLayoutsNames()
{
QStringList names;
if (m_manager->memoryUsage() == MemoryUsage::SingleLayout) {
names << m_centralLayouts.at(0)->name();
} else {
for (int i = 0; i < m_centralLayouts.size(); ++i) {
CentralLayout *layout = m_centralLayouts.at(i);
names << layout->name();
}
}
return names;
}
QStringList Synchronizer::currentLayoutsNames() const
{
QList<CentralLayout *> currents = currentLayouts();
QStringList currentNames;
for (int i = 0; i < currents.size(); ++i) {
CentralLayout *layout = currents.at(i);
currentNames << layout->name();
}
return currentNames;
}
QStringList Synchronizer::layouts() const
{
return m_layouts.names();
}
QStringList Synchronizer::menuLayouts() const
{
QStringList menulayouts;
for (int i=0; i<m_layouts.rowCount(); ++i) {
if (!m_layouts[i].isShownInMenu) {
continue;
}
menulayouts << m_layouts[i].name;
}
for (const auto layout : m_centralLayouts) {
if (!menulayouts.contains(layout->name())) {
menulayouts.prepend(layout->name());
}
}
return menulayouts;
}
Data::LayoutsTable Synchronizer::layoutsTable() const
{
return m_layouts;
}
void Synchronizer::setLayoutsTable(const Data::LayoutsTable &table)
{
if (m_layouts == table) {
return;
}
m_layouts = table;
emit layoutsChanged();
}
void Synchronizer::updateLayoutsTable()
{
for (int i = 0; i < m_centralLayouts.size(); ++i) {
CentralLayout *layout = m_centralLayouts.at(i);
if (m_layouts.containsId(layout->file())) {
m_layouts[layout->file()] = layout->data();
}
}
for (int i = 0; i < m_layouts.rowCount(); ++i) {
if (m_layouts[i].isBroken && !m_layouts[i].isActive) {
CentralLayout central(this, m_layouts[i].id);
m_layouts[i].isBroken = central.isBroken();
}
}
}
CentralLayout *Synchronizer::centralLayout(QString layoutname) const
{
for (int i = 0; i < m_centralLayouts.size(); ++i) {
CentralLayout *layout = m_centralLayouts.at(i);
if (layout->name() == layoutname) {
return layout;
}
}
return nullptr;
}
QList<CentralLayout *> Synchronizer::currentLayouts() const
{
QList<CentralLayout *> layouts;
if (m_manager->memoryUsage() == MemoryUsage::SingleLayout) {
layouts << m_centralLayouts.at(0);
} else {
for (auto layout : m_centralLayouts) {
if (layout->isOnAllActivities() || layout->appliedActivities().contains(m_manager->corona()->activitiesConsumer()->currentActivity())) {
layouts << layout;
}
}
}
return layouts;
}
QList<CentralLayout *> Synchronizer::centralLayoutsForActivity(const QString activityid) const
{
QList<CentralLayout *> layouts;
if (m_manager->memoryUsage() == MemoryUsage::SingleLayout && m_centralLayouts.count() >= 1) {
layouts << m_centralLayouts.at(0);
} else {
for (auto layout : m_centralLayouts) {
if (layout->isOnAllActivities() || layout->appliedActivities().contains(activityid)) {
layouts << layout;
}
}
}
return layouts;
}
QList<Latte::View *> Synchronizer::currentViews() const
{
QList<Latte::View *> views;
for(auto layout : currentLayouts()) {
views << layout->latteViews();
}
return views;
}
QList<Latte::View *> Synchronizer::currentViewsWithPlasmaShortcuts() const
{
QList<Latte::View *> views;
for(auto layout : currentLayouts()) {
views << layout->viewsWithPlasmaShortcuts();
}
return views;
}
QList<Latte::View *> Synchronizer::sortedCurrentViews() const
{
QList<Latte::View *> views = currentViews();
return Layout::GenericLayout::sortedLatteViews(views);
}
QList<Latte::View *> Synchronizer::viewsBasedOnActivityId(const QString &id) const
{
QList<Latte::View *> views;
for(auto layout : centralLayoutsForActivity(id)) {
if (m_centralLayouts.contains(layout)) {
views << layout->latteViews();
}
}
return views;
}
Layout::GenericLayout *Synchronizer::layout(QString layoutname) const
{
Layout::GenericLayout *l = centralLayout(layoutname);
return l;
}
Latte::View *Synchronizer::viewForContainment(uint id)
{
for (auto layout : m_centralLayouts) {
Latte::View *view = layout->viewForContainment(id);
if (view) {
return view;
}
}
return nullptr;
}
Latte::View *Synchronizer::viewForContainment(Plasma::Containment *containment)
{
for (auto layout : m_centralLayouts) {
Latte::View *view = layout->viewForContainment(containment);
if (view) {
return view;
}
}
return nullptr;
}
void Synchronizer::addLayout(CentralLayout *layout)
{
if (!m_centralLayouts.contains(layout)) {
m_centralLayouts.append(layout);
layout->initToCorona(m_manager->corona());
}
}
void Synchronizer::onActivityRemoved(const QString &activityid)
{
if (!m_assignedLayouts.contains(activityid)) {
return;
}
//! remove any other explicit set layouts for the current activity
QStringList explicits = m_assignedLayouts[activityid];
for(auto explicitlayoutname : explicits) {
QString explicitlayoutid = m_layouts.idForName(explicitlayoutname);
m_layouts[explicitlayoutid].activities.removeAll(activityid);
m_manager->setOnActivities(explicitlayoutname, m_layouts[explicitlayoutid].activities);
emit layoutActivitiesChanged(m_layouts[explicitlayoutid]);
}
QStringList freelayoutnames;
if (m_assignedLayouts.contains(Data::Layout::FREEACTIVITIESID)) {
freelayoutnames = m_assignedLayouts[Data::Layout::FREEACTIVITIESID];
}
reloadAssignedLayouts();
for(auto freelayoutname : freelayoutnames) {
//! inform free activities layouts that their activities probably changed
CentralLayout *central = centralLayout(freelayoutname);
if (central) {
emit central->activitiesChanged();
}
}
}
void Synchronizer::onCurrentActivityChanged(const QString &activityid)
{
if (m_manager->memoryUsage() == MemoryUsage::MultipleLayouts) {
updateKWinDisabledBorders();
}
}
void Synchronizer::hideAllViews()
{
for (const auto layout : m_centralLayouts) {
emit currentLayoutIsSwitching(layout->name());
}
}
void Synchronizer::pauseLayout(QString layoutName)
{
if (m_manager->memoryUsage() == MemoryUsage::MultipleLayouts) {
CentralLayout *layout = centralLayout(layoutName);
if (layout->isOnAllActivities()) {
return;
}
QStringList appliedactivities = layout->appliedActivities();
if (layout && !appliedactivities.isEmpty()) {
int i = 0;
for (const auto &activityid : appliedactivities) {
//! Stopping the activities must be done asynchronous because otherwise
//! the activity manager cant close multiple activities
QTimer::singleShot(i * 1000, [this, activityid]() {
m_activitiesController->stopActivity(activityid);
});
i = i + 1;
}
}
}
}
void Synchronizer::syncActiveLayoutsToOriginalFiles()
{
if (m_manager->memoryUsage() == MemoryUsage::MultipleLayouts) {
for (const auto layout : m_centralLayouts) {
layout->syncToLayoutFile();
}
}
}
void Synchronizer::syncLatteViewsToScreens()
{
for (const auto layout : m_centralLayouts) {
layout->syncLatteViewsToScreens();
}
}
void Synchronizer::unloadCentralLayout(CentralLayout *layout)
{
int pos = m_centralLayouts.indexOf(layout);
if (pos>=0) {
CentralLayout *central = m_centralLayouts.takeAt(pos);
if (m_multipleModeInitialized) {
central->syncToLayoutFile(true);
}
central->unloadLatteViews();
central->unloadContainments();
if (m_multipleModeInitialized) {
m_manager->clearUnloadedContainmentsFromLinkedFile(central->unloadedContainmentsIds(), true);
}
delete central;
}
}
void Synchronizer::initLayouts()
{
m_layouts.clear();
QDir layoutDir(Layouts::Importer::layoutUserDir());
QStringList filter;
filter.append(QString("*.layout.latte"));
QStringList files = layoutDir.entryList(filter, QDir::Files | QDir::NoSymLinks);
for (const auto &layout : files) {
if (layout.contains(Layout::MULTIPLELAYOUTSHIDDENNAME)) {
//! IMPORTANT: DON'T ADD MultipleLayouts hidden file in layouts list
continue;
}
QString layoutpath = layoutDir.absolutePath() + "/" + layout;
onLayoutAdded(layoutpath);
}
emit layoutsChanged();
if (!m_isLoaded) {
m_isLoaded = true;
connect(m_manager->corona()->templatesManager(), &Latte::Templates::Manager::newLayoutAdded, this, &Synchronizer::onLayoutAdded);
connect(m_manager->importer(), &Latte::Layouts::Importer::newLayoutAdded, this, &Synchronizer::onLayoutAdded);
}
}
void Synchronizer::onLayoutAdded(const QString &layout)
{
CentralLayout centrallayout(this, layout);
m_layouts.insertBasedOnName(centrallayout.data());
if (m_isLoaded) {
emit layoutsChanged();
}
}
void Synchronizer::reloadAssignedLayouts()
{
m_assignedLayouts.clear();
for (int i=0; i< m_layouts.rowCount(); ++i) {
for (const auto &activity : m_layouts[i].activities) {
if (m_assignedLayouts.contains(activity)) {
m_assignedLayouts[activity] << m_layouts[i].name;
} else {
m_assignedLayouts[activity] = QStringList(m_layouts[i].name);
}
}
}
}
void Synchronizer::unloadLayouts()
{
//! Unload all CentralLayouts
while (!m_centralLayouts.isEmpty()) {
CentralLayout *layout = m_centralLayouts.at(0);
unloadCentralLayout(layout);
}
m_multipleModeInitialized = false;
}
bool Synchronizer::memoryInitialized() const
{
return ((m_manager->memoryUsage() == MemoryUsage::SingleLayout && m_centralLayouts.size()>0)
|| (m_manager->memoryUsage() == MemoryUsage::MultipleLayouts && m_multipleModeInitialized));
}
bool Synchronizer::initSingleMode(QString layoutName)
{
QString layoutpath = layoutName.isEmpty() ? layoutPath(m_manager->corona()->universalSettings()->singleModeLayoutName()) : layoutPath(layoutName);
if (layoutpath.isEmpty()) {
qDebug() << "Layout : " << layoutName << " was not found...";
return false;
}
if (m_centralLayouts.size() > 0) {
emit currentLayoutIsSwitching(m_centralLayouts[0]->name());
}
//! this code must be called asynchronously because it can create crashes otherwise.
//! Tasks plasmoid case that triggers layouts switching through its context menu
QTimer::singleShot(LAYOUTSINITINTERVAL, [this, layoutName, layoutpath]() {
qDebug() << " ... initializing layout in single mode : " << layoutName << " - " << layoutpath;
unloadLayouts();
//! load the main layout/corona file
CentralLayout *newLayout = new CentralLayout(this, layoutpath, layoutName);
addLayout(newLayout);
m_manager->loadLatteLayout(layoutpath);
emit centralLayoutsChanged();
m_manager->corona()->universalSettings()->setSingleModeLayoutName(layoutName);
});
return true;
}
bool Synchronizer::initMultipleMode(QString layoutName)
{
if (m_multipleModeInitialized) {
return false;
}
for (const auto layout : m_centralLayouts) {
emit currentLayoutIsSwitching(layout->name());
}
//! this code must be called asynchronously because it can create crashes otherwise.
//! Tasks plasmoid case that triggers layouts switching through its context menu
QTimer::singleShot(LAYOUTSINITINTERVAL, [this, layoutName]() {
qDebug() << " ... initializing layout in multiple mode : " << layoutName ;
unloadLayouts();
m_manager->loadLatteLayout(layoutPath(QString(Layout::MULTIPLELAYOUTSHIDDENNAME)));
m_multipleModeInitialized = true;
emit centralLayoutsChanged();
if (!layoutName.isEmpty()) {
switchToLayoutInMultipleModeBasedOnActivities(layoutName);
}
syncMultipleLayoutsToActivities();
});
return true;
}
bool Synchronizer::switchToLayoutInSingleMode(QString layoutName)
{
if (!memoryInitialized() || m_manager->memoryUsage() != MemoryUsage::SingleLayout) {
return false;
}
if (m_centralLayouts.size()>0 && m_centralLayouts[0]->name() == layoutName) {
return true;
}
return initSingleMode(layoutName);
}
bool Synchronizer::switchToLayoutInMultipleModeBasedOnActivities(const QString &layoutName)
{
Data::Layout layoutdata;
CentralLayout *central = centralLayout(layoutName);
if (central) {
layoutdata = central->data();
} else if (m_layouts.containsName(layoutName)) {
QString layoutid = m_layouts.idForName(layoutName);
CentralLayout storagedlayout(this, layoutid);
layoutdata = storagedlayout.data();
m_layouts[layoutid] = layoutdata;
}
if (layoutdata.isEmpty()) {
return false;
}
QString switchToActivity;
//! try to not remove activityids that belong to different machines that are not currently present
QStringList validlayoutactivities = validActivities(layoutdata.activities);
if (layoutdata.isOnAllActivities()) {
//! no reason to switch in any activity;
} else if (layoutdata.isForFreeActivities()) {
//! free-activities case
QStringList freerunningactivities = freeRunningActivities();
if (freerunningactivities.count() > 0) {
if (freerunningactivities.contains(layoutdata.lastUsedActivity)) {
switchToActivity = layoutdata.lastUsedActivity;
} else {
switchToActivity = freerunningactivities[0];
}
} else {
QStringList freepausedactivities = freeActivities();
if (freepausedactivities.count() > 0) {
switchToActivity = freepausedactivities[0];
}
}
} else if (!validlayoutactivities.isEmpty()) {
//! set on-explicit activities
QStringList allactivities = activities();
if (validlayoutactivities.contains(layoutdata.lastUsedActivity)) {
switchToActivity = layoutdata.lastUsedActivity;
} else {
switchToActivity = validlayoutactivities[0];
}
} else if (validlayoutactivities.isEmpty() && m_layouts.containsName(layoutName)) {
//! no-activities are set
//! has not been set in any activities but nonetheless it is requested probably by the user
//! requested layout is assigned explicitly in current activity and any remaining explicit layouts
//! are removing current activity from their activities list
QString layoutid = m_layouts.idForName(layoutName);
QString currentactivityid = m_activitiesController->currentActivity();
QStringList layoutIdsChanged;
m_layouts[layoutid].activities.append(currentactivityid);
m_manager->setOnActivities(layoutName, m_layouts[layoutid].activities);
emit layoutActivitiesChanged(m_layouts[layoutid]);
layoutIdsChanged << layoutid;
if (m_assignedLayouts.contains(currentactivityid)) {
//! remove any other explicit set layouts for the current activity
QStringList explicits = m_assignedLayouts[currentactivityid];
for(auto explicitlayoutname : explicits) {
QString explicitlayoutid = m_layouts.idForName(explicitlayoutname);
m_layouts[explicitlayoutid].activities.removeAll(currentactivityid);
m_manager->setOnActivities(explicitlayoutname, m_layouts[explicitlayoutid].activities);
emit layoutActivitiesChanged(m_layouts[explicitlayoutid]);
}
}
QStringList freelayoutnames;
if (m_assignedLayouts.contains(Data::Layout::FREEACTIVITIESID)) {
freelayoutnames = m_assignedLayouts[Data::Layout::FREEACTIVITIESID];
}
reloadAssignedLayouts();
for(auto freelayoutname : freelayoutnames) {
//! inform free activities layouts that their activities probably changed
CentralLayout *central = centralLayout(freelayoutname);
if (central) {
emit central->activitiesChanged();
}
}
}
if (!switchToActivity.isEmpty()) {
if (!m_manager->corona()->activitiesConsumer()->runningActivities().contains(switchToActivity)) {
m_activitiesController->startActivity(switchToActivity);
}
m_activitiesController->setCurrentActivity(switchToActivity);
}
return true;
}
bool Synchronizer::switchToLayoutInMultipleMode(QString layoutName)
{
if (!memoryInitialized() || m_manager->memoryUsage() != MemoryUsage::MultipleLayouts) {
return false;
}
CentralLayout *layout = centralLayout(layoutName);
if (layout) {
QStringList appliedActivities = layout->appliedActivities();
QString nextActivity = !layout->lastUsedActivity().isEmpty() ? layout->lastUsedActivity() : appliedActivities[0];
if (!appliedActivities.contains(m_manager->corona()->activitiesConsumer()->currentActivity())) {
//! it means we are at a foreign activity and we can switch to correct one
m_activitiesController->setCurrentActivity(nextActivity);
return true;
}
} else {
if (!layoutName.isEmpty()) {
switchToLayoutInMultipleModeBasedOnActivities(layoutName);
}
syncMultipleLayoutsToActivities();
}
return true;
}
bool Synchronizer::switchToLayout(QString layoutName, MemoryUsage::LayoutsMemory newMemoryUsage)
{
qDebug() << " >>>>> SWITCHING >> " << layoutName << " __ from memory: " << m_manager->memoryUsage() << " to memory: " << newMemoryUsage;
if (newMemoryUsage == MemoryUsage::Current) {
newMemoryUsage = m_manager->memoryUsage();
}
if (!memoryInitialized() || newMemoryUsage != m_manager->memoryUsage()) {
//! Initiate Layouts memory properly
m_manager->setMemoryUsage(newMemoryUsage);
return (newMemoryUsage == MemoryUsage::SingleLayout ? initSingleMode(layoutName) : initMultipleMode(layoutName));
}
if (m_manager->memoryUsage() == MemoryUsage::SingleLayout) {
return switchToLayoutInSingleMode(layoutName);
} else {
return switchToLayoutInMultipleMode(layoutName);
}
}
void Synchronizer::syncMultipleLayoutsToActivities()
{
qDebug() << " ---- --------- ------ syncMultipleLayoutsToActivities ------- ";
qDebug() << " ---- --------- ------ ------------------------------- ------- ";
QStringList layoutNamesToUnload;
QStringList layoutNamesToLoad;
QStringList currentNames = centralLayoutsNames();
//! discover OnAllActivities layouts
if (m_assignedLayouts.contains(Data::Layout::ALLACTIVITIESID)) {
layoutNamesToLoad << m_assignedLayouts[Data::Layout::ALLACTIVITIESID];
}
//! discover ForFreeActivities layouts
if (m_assignedLayouts.contains(Data::Layout::FREEACTIVITIESID) && freeRunningActivities().count()>0) {
layoutNamesToLoad << m_assignedLayouts[Data::Layout::FREEACTIVITIESID];
}
//! discover layouts assigned to explicit activities based on running activities
for (const auto &activity : runningActivities()) {
if (KWindowSystem::isPlatformWayland() && (m_activitiesController->currentActivity() != activity)){
//! Wayland Protection: Plasma wayland does not support yet Activities for windows
//! but we can load the layouts that belong OnAllActivities + (ForFreeActivities OR SpecificActivity)
continue;
}
if (m_assignedLayouts.contains(activity)) {
layoutNamesToLoad << m_assignedLayouts[activity];
}
}
//! discover layouts that must be unloaded because of running activities changes
for (const auto layout : m_centralLayouts) {
if (!layoutNamesToLoad.contains(layout->name())) {
layoutNamesToUnload << layout->name();
}
}
QString defaultForcedLayout;
//! Safety
if (layoutNamesToLoad.isEmpty()) {
//! If no layout is found then force loading Default Layout
QString layoutPath = m_manager->corona()->templatesManager()->newLayout("", i18n(Templates::DEFAULTLAYOUTTEMPLATENAME));
layoutNamesToLoad << Layout::AbstractLayout::layoutName(layoutPath);
m_manager->setOnAllActivities(layoutNamesToLoad[0]);
defaultForcedLayout = layoutNamesToLoad[0];
}
QStringList newlyActivatedLayouts;
//! Add needed Layouts based on Activities settings
for (const auto &layoutname : layoutNamesToLoad) {
if (!centralLayout(layoutname)) {
CentralLayout *newLayout = new CentralLayout(this, QString(layoutPath(layoutname)), layoutname);
if (newLayout) {
qDebug() << "ACTIVATING LAYOUT ::::: " << layoutname;
addLayout(newLayout);
newLayout->importToCorona();
if (!defaultForcedLayout.isEmpty() && defaultForcedLayout == layoutname) {
emit newLayoutAdded(newLayout->data());
}
newlyActivatedLayouts << newLayout->name();
}
}
}
if (m_manager->corona()->universalSettings()->showInfoWindow()) {
if (newlyActivatedLayouts.count() == 1) {
m_manager->showInfoWindow(i18n("Activating layout: <b>%0</b> ...").arg(newlyActivatedLayouts[0]), 4000, QStringList(Data::Layout::ALLACTIVITIESID));
} else if (newlyActivatedLayouts.count() > 1) {
m_manager->showInfoWindow(i18n("Activating layouts: <b>%0</b> ...").arg(newlyActivatedLayouts.join(", ")), 4000, QStringList(Data::Layout::ALLACTIVITIESID));
}
}
//! Unload no needed Layouts
//! hide layouts that will be removed in the end
if (!layoutNamesToUnload.isEmpty()) {
for (const auto layoutname : layoutNamesToUnload) {
emit currentLayoutIsSwitching(layoutname);
}
QTimer::singleShot(LAYOUTSINITINTERVAL, [this, layoutNamesToUnload]() {
unloadLayouts(layoutNamesToUnload);
});
}
qSort(currentNames);
qSort(layoutNamesToLoad);
if (currentNames != layoutNamesToLoad) {
emit centralLayoutsChanged();
}
}
void Synchronizer::unloadLayouts(const QStringList &layoutNames)
{
if (layoutNames.isEmpty()) {
return;
}
//! Unload no needed Layouts
for (const auto &layoutname : layoutNames) {
CentralLayout *layout = centralLayout(layoutname);
int posLayout = centralLayoutPos(layoutname);
if (posLayout >= 0) {
qDebug() << "REMOVING LAYOUT ::::: " << layoutname;
m_centralLayouts.removeAt(posLayout);
layout->syncToLayoutFile(true);
layout->unloadContainments();
layout->unloadLatteViews();
m_manager->clearUnloadedContainmentsFromLinkedFile(layout->unloadedContainmentsIds());
delete layout;
}
}
emit centralLayoutsChanged();
}
void Synchronizer::updateKWinDisabledBorders()
{
if (!m_manager->corona()->universalSettings()->canDisableBorders()) {
m_manager->corona()->universalSettings()->kwin_setDisabledMaximizedBorders(false);
} else {
if (m_manager->corona()->layoutsManager()->memoryUsage() == MemoryUsage::SingleLayout) {
m_manager->corona()->universalSettings()->kwin_setDisabledMaximizedBorders(m_centralLayouts.at(0)->disableBordersForMaximizedWindows());
} else if (m_manager->corona()->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts) {
QList<CentralLayout *> centrals = centralLayoutsForActivity(m_manager->corona()->activitiesConsumer()->currentActivity());
for (int i = 0; i < centrals.size(); ++i) {
CentralLayout *layout = centrals.at(i);
if (layout->disableBordersForMaximizedWindows()) {
m_manager->corona()->universalSettings()->kwin_setDisabledMaximizedBorders(true);
return;
}
}
m_manager->corona()->universalSettings()->kwin_setDisabledMaximizedBorders(false);
}
}
}
}
} // end of namespace