1
0
mirror of https://github.com/KDE/latte-dock.git synced 2025-01-03 09:17:50 +03:00

fix #96,FEATURE:AllScreens and AllSecondaryScreens

--This is a HUGE FEATURE and so important for multi-screens
users. It is introduced as one single commit because it
reimplements plenty of infrastructure changes and it will
be easier to identify newly introduced bugs.
--Users can now choose for their docks and panels to belong
at various screen groups. The first two screen groups introduced
are AllScreens and AllSecondayScreens. In the future it might
be possible to provide CustomScreensGroup that the user will
be able to define specific screens in which a dock or panel
should be always present.
--Current solution specifies an Original dock or panel and clones/copies
itself automatically to other screens. So docks and panels in other screens
are just real docks and panels that reference themselves to original
docks and panels.
--Clones are destroyed during layout startup and are automaticaly
recreated. It is suggested to export your layouts through the
official Layouts Editor in order to share them because in that case
clones are not included in the new generated layout file. If in any
case you do not this and you share your layout with any previous
versions then your clones will just appear as separate docks and
panels that belong to specific screens.
--Automatic syncing was introduced in order to keep up-to-date
the configuration of Original docks and panels with their referenced
Clones.
--Automatic syncing currently works for all docks and panels settings,
for all normal applets configurations and for all subcontaiments
configuration such as systrays.
--Automatic syncing does not work for applets inside subcontainments
such as Group Plasmoid. In such case it is suggested to configure
your applets inside your Group Plasmoid in the original dock or panel
and afterwards to trigger a recreation for the relevant clones
--Manual recreation of clones is easily possible by just choosing
the dock or panel to be OnPrimary or OnSpecificScreen and rechoosing
afterwards the AllScreensGroup or AllSecondaryScreensGroup
This commit is contained in:
Michail Vourlakos 2021-12-11 17:39:44 +02:00
parent 8a0f18326e
commit 60095bba3b
66 changed files with 2766 additions and 615 deletions

View File

@ -103,6 +103,12 @@ void Screen::init(const QString &screenId, const QString &serialized)
} }
} }
bool Screen::isScreensGroup() const
{
int sid = id.toInt();
return ((sid == ONALLSCREENSID) || (sid == ONALLSECONDARYSCREENSID));
}
QString Screen::serialize() const QString Screen::serialize() const
{ {
QStringList result; QStringList result;

View File

@ -23,7 +23,11 @@ class Screen : public Generic
public: public:
static constexpr const char* SERIALIZESPLITTER = ":::"; static constexpr const char* SERIALIZESPLITTER = ":::";
static const int ONPRIMARYID = 0; static const int ONPRIMARYID = 0;
static const int ONALLSCREENSID = -100;
static const int ONALLSECONDARYSCREENSID = -101;
static constexpr const char* ONPRIMARYNAME = "{primary-screen}"; static constexpr const char* ONPRIMARYNAME = "{primary-screen}";
static constexpr const char* ONALLSCREENSNAME = "{all-screens}";
static constexpr const char* ONALLSECONDARYSCREENSNAME = "{all-secondary-screens}";
Screen(); Screen();
Screen(Screen &&o); Screen(Screen &&o);
@ -43,6 +47,8 @@ public:
bool operator==(const Screen &rhs) const; bool operator==(const Screen &rhs) const;
bool operator!=(const Screen &rhs) const; bool operator!=(const Screen &rhs) const;
bool isScreensGroup() const;
void init(const QString &screenId, const QString &serialized); void init(const QString &screenId, const QString &serialized);
QString serialize() const; QString serialize() const;

View File

@ -8,6 +8,8 @@
namespace Latte { namespace Latte {
namespace Data { namespace Data {
const int View::ISCLONEDNULL = -1;
View::View() View::View()
: Generic() : Generic()
{ {
@ -19,8 +21,10 @@ View::View(View &&o)
isMoveOrigin(o.isMoveOrigin), isMoveOrigin(o.isMoveOrigin),
isMoveDestination(o.isMoveDestination), isMoveDestination(o.isMoveDestination),
onPrimary(o.onPrimary), onPrimary(o.onPrimary),
isClonedFrom(o.isClonedFrom),
screen(o.screen), screen(o.screen),
screenEdgeMargin(o.screenEdgeMargin), screenEdgeMargin(o.screenEdgeMargin),
screensGroup(o.screensGroup),
maxLength(o.maxLength), maxLength(o.maxLength),
edge(o.edge), edge(o.edge),
alignment(o.alignment), alignment(o.alignment),
@ -40,8 +44,10 @@ View::View(const View &o)
isMoveOrigin(o.isMoveOrigin), isMoveOrigin(o.isMoveOrigin),
isMoveDestination(o.isMoveDestination), isMoveDestination(o.isMoveDestination),
onPrimary(o.onPrimary), onPrimary(o.onPrimary),
isClonedFrom(o.isClonedFrom),
screen(o.screen), screen(o.screen),
screenEdgeMargin(o.screenEdgeMargin), screenEdgeMargin(o.screenEdgeMargin),
screensGroup(o.screensGroup),
maxLength(o.maxLength), maxLength(o.maxLength),
edge(o.edge), edge(o.edge),
alignment(o.alignment), alignment(o.alignment),
@ -68,8 +74,10 @@ View &View::operator=(const View &rhs)
isMoveOrigin = rhs.isMoveOrigin; isMoveOrigin = rhs.isMoveOrigin;
isMoveDestination = rhs.isMoveDestination; isMoveDestination = rhs.isMoveDestination;
onPrimary = rhs.onPrimary; onPrimary = rhs.onPrimary;
isClonedFrom = rhs.isClonedFrom;
screen = rhs.screen; screen = rhs.screen;
screenEdgeMargin = rhs.screenEdgeMargin, screenEdgeMargin = rhs.screenEdgeMargin;
screensGroup = rhs.screensGroup;
maxLength = rhs.maxLength; maxLength = rhs.maxLength;
edge = rhs.edge; edge = rhs.edge;
alignment = rhs.alignment; alignment = rhs.alignment;
@ -93,8 +101,10 @@ View &View::operator=(View &&rhs)
isMoveOrigin = rhs.isMoveOrigin; isMoveOrigin = rhs.isMoveOrigin;
isMoveDestination = rhs.isMoveDestination; isMoveDestination = rhs.isMoveDestination;
onPrimary = rhs.onPrimary; onPrimary = rhs.onPrimary;
isClonedFrom = rhs.isClonedFrom;
screen = rhs.screen; screen = rhs.screen;
screenEdgeMargin = rhs.screenEdgeMargin, screenEdgeMargin = rhs.screenEdgeMargin;
screensGroup = rhs.screensGroup;
maxLength = rhs.maxLength; maxLength = rhs.maxLength;
edge = rhs.edge; edge = rhs.edge;
alignment = rhs.alignment; alignment = rhs.alignment;
@ -118,8 +128,10 @@ bool View::operator==(const View &rhs) const
//&& (isMoveOrigin == rhs.isMoveOrigin) /*Disabled because this is not needed in order to track view changes for saving*/ //&& (isMoveOrigin == rhs.isMoveOrigin) /*Disabled because this is not needed in order to track view changes for saving*/
//&& (isMoveDestination == rhs.isMoveDestination) /*Disabled because this is not needed in order to track view changes for saving*/ //&& (isMoveDestination == rhs.isMoveDestination) /*Disabled because this is not needed in order to track view changes for saving*/
&& (onPrimary == rhs.onPrimary) && (onPrimary == rhs.onPrimary)
&& (isClonedFrom == rhs.isClonedFrom)
&& (screen == rhs.screen) && (screen == rhs.screen)
&& (screenEdgeMargin == rhs.screenEdgeMargin) && (screenEdgeMargin == rhs.screenEdgeMargin)
&& (screensGroup == rhs.screensGroup)
&& (maxLength == rhs.maxLength) && (maxLength == rhs.maxLength)
&& (edge == rhs.edge) && (edge == rhs.edge)
&& (alignment == rhs.alignment) && (alignment == rhs.alignment)
@ -168,6 +180,21 @@ View::operator QString() const
} }
result += " : "; result += " : ";
if (isCloned()) {
result += ("Cloned from:"+ isClonedFrom);
} else {
result += "Original";
}
result += " : ";
if (screensGroup == Latte::Types::SingleScreenGroup) {
result += onPrimary ? "Primary" : "Explicit";
} else if (screensGroup == Latte::Types::AllScreensGroup) {
result += "All Screens";
} else if (screensGroup == Latte::Types::AllSecondaryScreensGroup) {
result += "All Secondary Screens";
}
result += onPrimary ? "Primary" : "Explicit"; result += onPrimary ? "Primary" : "Explicit";
result += " : "; result += " : ";
result += QString::number(screen); result += QString::number(screen);
@ -212,6 +239,16 @@ bool View::isCreated() const
return m_state == IsCreated; return m_state == IsCreated;
} }
bool View::isOriginal() const
{
return !isCloned();
}
bool View::isCloned() const
{
return isClonedFrom != ISCLONEDNULL;
}
bool View::isValid() const bool View::isValid() const
{ {
return m_state != IsInvalid; return m_state != IsInvalid;

View File

@ -32,6 +32,8 @@ public:
OriginFromLayout /*used from duplicate, copy, move view functions*/ OriginFromLayout /*used from duplicate, copy, move view functions*/
}; };
static const int ISCLONEDNULL;
View(); View();
View(View &&o); View(View &&o);
View(const View &o); View(const View &o);
@ -40,11 +42,13 @@ public:
//! View data //! View data
bool isActive{false}; bool isActive{false};
bool onPrimary{true}; bool onPrimary{true};
int isClonedFrom{ISCLONEDNULL};
int screen{Latte::ScreenPool::FIRSTSCREENID}; int screen{Latte::ScreenPool::FIRSTSCREENID};
int screenEdgeMargin{0}; int screenEdgeMargin{0};
float maxLength{1.0}; float maxLength{1.0};
Plasma::Types::Location edge{Plasma::Types::BottomEdge}; Plasma::Types::Location edge{Plasma::Types::BottomEdge};
Latte::Types::Alignment alignment{Latte::Types::Center}; Latte::Types::Alignment alignment{Latte::Types::Center};
Latte::Types::ScreensGroup screensGroup{Latte::Types::SingleScreenGroup};
GenericTable<Data::Generic> subcontainments; GenericTable<Data::Generic> subcontainments;
int errors{0}; int errors{0};
@ -56,6 +60,8 @@ public:
bool isValid() const; bool isValid() const;
bool isCreated() const; bool isCreated() const;
bool isOriginal() const;
bool isCloned() const;
bool hasViewTemplateOrigin() const; bool hasViewTemplateOrigin() const;
bool hasLayoutOrigin() const; bool hasLayoutOrigin() const;
bool hasSubContainment(const QString &subId) const; bool hasSubContainment(const QString &subId) const;

View File

@ -90,6 +90,19 @@ ViewsTable ViewsTable::subtracted(const ViewsTable &rhs) const
return subtract; return subtract;
} }
ViewsTable ViewsTable::onlyOriginals() const
{
ViewsTable originals;
for(int i=0; i<m_list.count(); ++i) {
if (m_list[i].isOriginal()) {
originals << m_list[i];
}
}
return originals;
}
void ViewsTable::appendTemporaryView(const Data::View &view) void ViewsTable::appendTemporaryView(const Data::View &view)
{ {
int maxTempId = 0; int maxTempId = 0;

View File

@ -38,6 +38,7 @@ public:
bool operator==(const ViewsTable &rhs) const; bool operator==(const ViewsTable &rhs) const;
bool operator!=(const ViewsTable &rhs) const; bool operator!=(const ViewsTable &rhs) const;
ViewsTable subtracted(const ViewsTable &rhs) const; ViewsTable subtracted(const ViewsTable &rhs) const;
ViewsTable onlyOriginals() const;
}; };
} }

View File

@ -32,6 +32,7 @@
#include "plasma/extended/theme.h" #include "plasma/extended/theme.h"
#include "settings/universalsettings.h" #include "settings/universalsettings.h"
#include "templates/templatesmanager.h" #include "templates/templatesmanager.h"
#include "view/originalview.h"
#include "view/view.h" #include "view/view.h"
#include "view/settings/viewsettingsfactory.h" #include "view/settings/viewsettingsfactory.h"
#include "view/windowstracker/windowstracker.h" #include "view/windowstracker/windowstracker.h"
@ -1192,9 +1193,25 @@ QStringList Corona::contextMenuData(const uint &containmentId)
} }
data << layoutsmenu.join(";;"); data << layoutsmenu.join(";;");
data << QString::number((int)viewType); //Selected View type
data << (view ? view->layout()->name() : QString()); //Selected View layout*/ data << (view ? view->layout()->name() : QString()); //Selected View layout*/
QStringList viewtype;
viewtype << QString::number((int)viewType); //Selected View type
if (view && view->isOriginal()) { /*View*/
auto originalview = qobject_cast<Latte::OriginalView *>(view);
viewtype << "0"; //original view
viewtype << QString::number(originalview->clonesCount());
} else if (view && view->isCloned()) {
viewtype << "1"; //cloned view
viewtype << "0"; //has no clones
} else {
viewtype << "0"; //original view
viewtype << "0"; //has no clones
}
data << viewtype.join(";;");
return data; return data;
} }
@ -1247,7 +1264,14 @@ void Corona::moveViewToLayout(const uint &containmentId, const QString &layoutNa
{ {
auto view = m_layoutsManager->synchronizer()->viewForContainment((int)containmentId); auto view = m_layoutsManager->synchronizer()->viewForContainment((int)containmentId);
if (view && !layoutName.isEmpty() && view->layout()->name() != layoutName) { if (view && !layoutName.isEmpty() && view->layout()->name() != layoutName) {
view->positioner()->setNextLocation(layoutName, "", Plasma::Types::Floating, Latte::Types::NoneAlignment); Latte::Types::ScreensGroup screensgroup{Latte::Types::SingleScreenGroup};
if (view->isOriginal()) {
auto originalview = qobject_cast<Latte::OriginalView *>(view);
screensgroup = originalview->screensGroup();
}
view->positioner()->setNextLocation(layoutName, screensgroup, "", Plasma::Types::Floating, Latte::Types::NoneAlignment);
} }
} }

View File

@ -46,9 +46,9 @@ void CentralLayout::init()
connect(this, &CentralLayout::showInMenuChanged, this, &CentralLayout::saveConfig); connect(this, &CentralLayout::showInMenuChanged, this, &CentralLayout::saveConfig);
} }
void CentralLayout::initToCorona(Latte::Corona *corona) bool CentralLayout::initCorona()
{ {
if (GenericLayout::initToCorona(corona)) { if (GenericLayout::initCorona()) {
onSchemeFileChanged(); onSchemeFileChanged();
connect(this, &CentralLayout::disableBordersForMaximizedWindowsChanged, connect(this, &CentralLayout::disableBordersForMaximizedWindowsChanged,
@ -56,7 +56,10 @@ void CentralLayout::initToCorona(Latte::Corona *corona)
connect(this, &Layout::AbstractLayout::schemeFileChanged, this, &CentralLayout::onSchemeFileChanged); connect(this, &Layout::AbstractLayout::schemeFileChanged, this, &CentralLayout::onSchemeFileChanged);
connect(m_corona->wm()->schemesTracker(), &WindowSystem::Tracker::Schemes::defaultSchemeChanged, this, &CentralLayout::onSchemeFileChanged); connect(m_corona->wm()->schemesTracker(), &WindowSystem::Tracker::Schemes::defaultSchemeChanged, this, &CentralLayout::onSchemeFileChanged);
return true;
} }
return false;
} }
bool CentralLayout::disableBordersForMaximizedWindows() const bool CentralLayout::disableBordersForMaximizedWindows() const

View File

@ -41,7 +41,7 @@ public:
CentralLayout(QObject *parent, QString layoutFile, QString layoutName = QString()); CentralLayout(QObject *parent, QString layoutFile, QString layoutName = QString());
~CentralLayout() override; ~CentralLayout() override;
void initToCorona(Latte::Corona *corona); bool initCorona() override;
bool disableBordersForMaximizedWindows() const; bool disableBordersForMaximizedWindows() const;
void setDisableBordersForMaximizedWindows(bool disable); void setDisableBordersForMaximizedWindows(bool disable);

View File

@ -17,8 +17,10 @@
#include "../layouts/synchronizer.h" #include "../layouts/synchronizer.h"
#include "../shortcuts/shortcutstracker.h" #include "../shortcuts/shortcutstracker.h"
#include "../templates/templatesmanager.h" #include "../templates/templatesmanager.h"
#include "../view/view.h" #include "../view/clonedview.h"
#include "../view/originalview.h"
#include "../view/positioner.h" #include "../view/positioner.h"
#include "../view/view.h"
// Qt // Qt
#include <QDebug> #include <QDebug>
@ -143,7 +145,7 @@ void GenericLayout::setBlockAutomaticLatteViewCreation(bool block)
bool GenericLayout::isActive() const bool GenericLayout::isActive() const
{ {
return m_corona && (m_corona->layoutsManager()->synchronizer()->layout(m_layoutName) != nullptr); return m_corona && m_hasInitializedContainments && (m_corona->layoutsManager()->synchronizer()->layout(m_layoutName) != nullptr);
} }
bool GenericLayout::isCurrent() bool GenericLayout::isCurrent()
@ -155,6 +157,16 @@ bool GenericLayout::isCurrent()
return m_corona->layoutsManager()->currentLayoutsNames().contains(name()); return m_corona->layoutsManager()->currentLayoutsNames().contains(name());
} }
bool GenericLayout::hasCorona() const
{
return (m_corona!=nullptr);
}
void GenericLayout::setCorona(Latte::Corona *corona)
{
m_corona = corona;
}
QString GenericLayout::background() const QString GenericLayout::background() const
{ {
QString colorsPath = m_corona->kPackage().path() + "../../shells/org.kde.latte.shell/contents/images/canvas/"; QString colorsPath = m_corona->kPackage().path() + "../../shells/org.kde.latte.shell/contents/images/canvas/";
@ -368,6 +380,12 @@ Latte::View *GenericLayout::viewForContainment(uint id) const
} }
} }
for(auto view : m_waitingLatteViews) {
if (view && view->containment()->id() == id) {
return view;
}
}
return nullptr; return nullptr;
} }
@ -449,6 +467,19 @@ QList<Latte::View *> GenericLayout::latteViews()
return m_latteViews.values(); return m_latteViews.values();
} }
QList<Latte::View *> GenericLayout::onlyOriginalViews()
{
QList<Latte::View *> viewslist;
for (const auto v : m_latteViews) {
if (v->isOriginal()) {
viewslist << v;
}
}
return viewslist;
}
QList<Latte::View *> GenericLayout::sortedLatteViews() QList<Latte::View *> GenericLayout::sortedLatteViews()
{ {
return sortedLatteViews(latteViews()); return sortedLatteViews(latteViews());
@ -819,109 +850,55 @@ void GenericLayout::renameLayout(QString newName)
} }
} }
void GenericLayout::addView(Plasma::Containment *containment, bool forceOnPrimary, int explicitScreen, Layout::ViewsMap *occupied) void GenericLayout::addView(Plasma::Containment *containment)
{ {
qDebug() << "Layout :::: " << m_layoutName << " ::: addView was called... m_containments :: " << m_containments.size(); qDebug().noquote() << "Adding View: Called for layout:" << m_layoutName << "with m_containments.size() ::" << m_containments.size();
if (!containment || !m_corona || !containment->kPackage().isValid()) { if (!containment || !m_corona || !containment->kPackage().isValid()) {
qWarning() << "the requested containment plugin can not be located or loaded"; qWarning() << "Adding View: The requested containment plugin can not be located or loaded";
return; return;
} }
qDebug() << "step 1..."; qDebug() << "Adding View:" << containment->id() << "- Step 1...";
if (!Layouts::Storage::self()->isLatteContainment(containment)) { if (!Layouts::Storage::self()->isLatteContainment(containment)) {
return; return;
} }
qDebug() << "step 2..."; qDebug() << "Adding View:" << containment->id() << "- Step 2...";
for (auto *dock : m_latteViews) { if (hasLatteView(containment)) {
if (dock->containment() == containment)
return;
}
qDebug() << "step 3...";
QScreen *nextScreen{qGuiApp->primaryScreen()};
bool onPrimary = containment->config().readEntry("onPrimary", true);
int id = containment->screen();
if (!Layouts::Storage::isValid(id) && !Layouts::Storage::isValid(explicitScreen)) {
id = containment->lastScreen();
}
if (onPrimary) {
id = m_corona->screenPool()->primaryScreenId();
} else if (Layouts::Storage::isValid(explicitScreen)) {
id = explicitScreen;
}
Plasma::Types::Location edge = containment->location();
QString connector = m_corona->screenPool()->hasScreenId(id) ? m_corona->screenPool()->connector(id) : "";
qDebug() << "Adding view - containment id:" << containment->id() << " ,screen :" << id << " - " << connector
<< " ,onprimary:" << onPrimary << " - " << " edge:" << edge << " ,screenName:" << qGuiApp->primaryScreen()->name() << " ,forceOnPrimary:" << forceOnPrimary;
if (occupied && m_corona->screenPool()->hasScreenId(id) && (*occupied).contains(connector) && (*occupied)[connector].contains(edge)) {
qDebug() << "Rejected : adding view because the edge is already occupied by a higher priority view ! : " << (*occupied)[connector][edge];
return; return;
} }
if (Layouts::Storage::isValid(id) && !onPrimary && !forceOnPrimary) { qDebug() << "Adding View:" << containment->id() << "- Step 3...";
qDebug() << "Add view - connector : " << connector;
bool found{false};
if (m_corona->screenPool()->hasScreenId(id)) { QScreen *nextScreen{qGuiApp->primaryScreen()};
for (const auto scr : qGuiApp->screens()) { Data::View viewdata = Layouts::Storage::self()->view(this, containment);
if (scr && scr->name() == connector) { viewdata.screen = Layouts::Storage::self()->expectedViewScreenId(m_corona, viewdata);
found = true;
nextScreen = scr; QString nextScreenName = m_corona->screenPool()->hasScreenId(viewdata.screen) ? m_corona->screenPool()->connector(viewdata.screen) : "";
break;
} qDebug().noquote() << "Adding View:" << viewdata.id << "-"
} << "IsClonedFrom:" << viewdata.isClonedFrom
<< ", NextScreen:" << viewdata.screen << "-" << nextScreenName
<< ", OnPrimary:" << viewdata.onPrimary
<< ", Edge:" << viewdata.edge;
if (!viewdata.onPrimary && Layouts::Storage::isValid(viewdata.screen)) {
bool foundNextExplicitScreen{false};
if (m_corona->screenPool()->isScreenActive(viewdata.screen)) {
foundNextExplicitScreen = true;
nextScreen = m_corona->screenPool()->screenForId(viewdata.screen);
} }
if (!found) { if (!foundNextExplicitScreen) {
qDebug() << "Rejected : adding explicit view, screen not available ! : " << connector; qDebug().noquote() << "Adding View:" << viewdata.id << "- Rejected because Screen is not available :: " << nextScreenName;
return; return;
} }
//! explicit dock can not be added at explicit screen when that screen is the same with
//! primary screen and that edge is already occupied by a primary dock
//! CAN BE REMOVED because we now accept primary and explicit views on ACTIVE SCREENS at ALL CASES
//if (nextScreen == qGuiApp->primaryScreen() && primaryDockOccupyEdge(containment->location())) {
// qDebug() << "Rejected : adding explicit view, primary dock occupies edge at screen ! : " << connector;
// return;
// }
} }
if (Layouts::Storage::isValid(id) && onPrimary) {
qDebug() << "add dock - connector : " << connector;
for (const Plasma::Containment *testContainment : m_latteViews.keys()) {
int testScreenId = testContainment->screen();
if (!Layouts::Storage::isValid(testScreenId)) {
testScreenId = testContainment->lastScreen();
}
bool testOnPrimary = testContainment->config().readEntry("onPrimary", true);
Plasma::Types::Location testLocation = static_cast<Plasma::Types::Location>((int)testContainment->config().readEntry("location", (int)Plasma::Types::BottomEdge));
if (!testOnPrimary && m_corona->screenPool()->primaryScreenId() == testScreenId && testLocation == containment->location()) {
qDebug() << "Rejected explicit latteView and removing it in order add an onPrimary with higher priority at screen: " << connector;
auto viewToDelete = m_latteViews.take(testContainment);
viewToDelete->disconnectSensitiveSignals();
viewToDelete->deleteLater();
}
}
}
qDebug() << "Adding view passed ALL checks" << " ,onPrimary:" << onPrimary << " ,screen:" << nextScreen->name() << " !!!";
//! it is used to set the correct flag during the creation //! it is used to set the correct flag during the creation
//! of the window... This of course is also used during //! of the window... This of course is also used during
//! recreations of the window between different visibility modes //! recreations of the window between different visibility modes
@ -937,21 +914,29 @@ void GenericLayout::addView(Plasma::Containment *containment, bool forceOnPrimar
byPassWM = containment->config().readEntry("byPassWM", false); byPassWM = containment->config().readEntry("byPassWM", false);
} }
auto latteView = new Latte::View(m_corona, nextScreen, byPassWM); Latte::View *latteView;
if (!viewdata.isCloned()) {
latteView = new Latte::OriginalView(m_corona, nextScreen, byPassWM);
} else {
auto view = viewForContainment((uint)viewdata.isClonedFrom);
if (!containsView(viewdata.isClonedFrom) || !view) {
qDebug().noquote() << "Adding View:" << viewdata.id << "- Clone did not find OriginalView and as such was stopped!!!";
return;
}
auto originalview = qobject_cast<Latte::OriginalView *>(view);
latteView = new Latte::ClonedView(m_corona, originalview, nextScreen, byPassWM);
}
qDebug().noquote() << "Adding View:" << viewdata.id << "- Passed ALL checks !!!";
m_latteViews[containment] = latteView;
latteView->init(containment); latteView->init(containment);
latteView->setContainment(containment); latteView->setContainment(containment);
//! force this special dock case to become primary
//! even though it isnt
if (forceOnPrimary) {
qDebug() << "Enforcing onPrimary:true as requested for LatteView...";
latteView->setOnPrimary(true);
}
latteView->setLayout(this); latteView->setLayout(this);
//! Qt 5.9 creates a crash for this in wayland, that is why the check is used //! Qt 5.9 creates a crash for this in wayland, that is why the check is used
//! but on the other hand we need this for copy to work correctly and show //! but on the other hand we need this for copy to work correctly and show
//! the copied dock under X11 //! the copied dock under X11
@ -959,8 +944,6 @@ void GenericLayout::addView(Plasma::Containment *containment, bool forceOnPrimar
latteView->show(); latteView->show();
//} //}
m_latteViews[containment] = latteView;
emit viewsCountChanged(); emit viewsCountChanged();
} }
@ -996,27 +979,13 @@ void GenericLayout::toggleHiddenState(QString viewName, QString screenName, Plas
} }
} }
bool GenericLayout::initToCorona(Latte::Corona *corona) bool GenericLayout::initCorona()
{ {
if (m_corona) { if (!m_corona) {
return false; return false;
} }
m_corona = corona; connect(m_corona, &Plasma::Corona::containmentAdded, this, &GenericLayout::addContainment);
for (const auto containment : m_corona->containments()) {
if (m_corona->layoutsManager()->memoryUsage() == MemoryUsage::SingleLayout) {
addContainment(containment);
} else if (m_corona->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts) {
QString layoutId = containment->config().readEntry("layoutId", QString());
if (!layoutId.isEmpty() && (layoutId == m_layoutName)) {
addContainment(containment);
}
}
}
qDebug() << "Layout ::::: " << name() << " added containments ::: " << m_containments.size();
updateLastUsedActivity(); updateLastUsedActivity();
@ -1025,8 +994,6 @@ bool GenericLayout::initToCorona(Latte::Corona *corona)
connect(m_corona->activitiesConsumer(), &KActivities::Consumer::currentActivityChanged, this, &GenericLayout::updateLastUsedActivity); connect(m_corona->activitiesConsumer(), &KActivities::Consumer::currentActivityChanged, this, &GenericLayout::updateLastUsedActivity);
connect(m_corona->activitiesConsumer(), &KActivities::Consumer::runningActivitiesChanged, this, &GenericLayout::updateLastUsedActivity); connect(m_corona->activitiesConsumer(), &KActivities::Consumer::runningActivitiesChanged, this, &GenericLayout::updateLastUsedActivity);
connect(m_corona, &Plasma::Corona::containmentAdded, this, &GenericLayout::addContainment);
connect(this, &GenericLayout::lastConfigViewForChanged, m_corona->layoutsManager(), &Layouts::Manager::lastConfigViewChangedFrom); connect(this, &GenericLayout::lastConfigViewForChanged, m_corona->layoutsManager(), &Layouts::Manager::lastConfigViewChangedFrom);
connect(m_corona->layoutsManager(), &Layouts::Manager::lastConfigViewChangedFrom, this, &GenericLayout::onLastConfigViewChangedFrom); connect(m_corona->layoutsManager(), &Layouts::Manager::lastConfigViewChangedFrom, this, &GenericLayout::onLastConfigViewChangedFrom);
@ -1034,8 +1001,41 @@ bool GenericLayout::initToCorona(Latte::Corona *corona)
connect(this, &GenericLayout::viewsCountChanged, m_corona, &Plasma::Corona::availableScreenRectChanged); connect(this, &GenericLayout::viewsCountChanged, m_corona, &Plasma::Corona::availableScreenRectChanged);
connect(this, &GenericLayout::viewsCountChanged, m_corona, &Plasma::Corona::availableScreenRegionChanged); connect(this, &GenericLayout::viewsCountChanged, m_corona, &Plasma::Corona::availableScreenRegionChanged);
emit viewsCountChanged(); return true;
}
bool GenericLayout::initContainments()
{
if (!m_corona || m_hasInitializedContainments) {
return false;
}
qDebug() << "Layout ::::: " << name() << " added containments ::: " << m_containments.size();
for(int pass=1; pass<=2; ++pass) {
for (const auto containment : m_corona->containments()) {
//! in first pass we load subcontainments
//! in second pass we load main dock and panel containments
//! this way subcontainments will be always available to find when the layout is activating
//! for example during startup that clones must be created and subcontainments should be taken into account
if ((pass==1 && Layouts::Storage::self()->isLatteContainment(containment)
|| (pass==2 && !Layouts::Storage::self()->isLatteContainment(containment)))) {
continue;
}
if (m_corona->layoutsManager()->memoryUsage() == MemoryUsage::SingleLayout) {
addContainment(containment);
} else if (m_corona->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts) {
QString layoutId = containment->config().readEntry("layoutId", QString());
if (!layoutId.isEmpty() && (layoutId == m_layoutName)) {
addContainment(containment);
}
}
}
}
m_hasInitializedContainments = true;
emit viewsCountChanged();
return true; return true;
} }
@ -1163,7 +1163,7 @@ void GenericLayout::recreateView(Plasma::Containment *containment, bool delayed)
} }
bool GenericLayout::latteViewExists(Plasma::Containment *containment) bool GenericLayout::hasLatteView(Plasma::Containment *containment)
{ {
if (!m_corona) { if (!m_corona) {
return false; return false;
@ -1254,119 +1254,55 @@ bool GenericLayout::mapContainsId(const Layout::ViewsMap *map, uint viewId) cons
return false; return false;
} }
//! screen name, location, containmentId QString GenericLayout::mapScreenName(const ViewsMap *map, uint viewId) const
Layout::ViewsMap GenericLayout::validViewsMap(Layout::ViewsMap *occupiedMap) {
for(const auto &scr : map->keys()) {
for(const auto &edge : (*map)[scr].keys()) {
if ((*map)[scr][edge].contains(viewId)) {
return scr;
}
}
}
return QString::number(Latte::ScreenPool::NOSCREENID);
}
//! screen name, location, containmentId
Layout::ViewsMap GenericLayout::validViewsMap()
{ {
//! Shared Views occupy the screen edge first
//! Primary Views occupy the screen edge if Shared Views do not exist already on that screen edge
//! Explicity Views occypy the screen edge if Shared Views and Primary Views do not exist already on that screen edge
Layout::ViewsMap map; Layout::ViewsMap map;
if (!m_corona) { if (!m_corona) {
return map; return map;
} }
if (occupiedMap != nullptr) {
map = (*occupiedMap);
}
QString prmScreenName = qGuiApp->primaryScreen()->name(); QString prmScreenName = qGuiApp->primaryScreen()->name();
//! first step: primary docks must be placed in primary screen free edges
for (const auto containment : m_containments) { for (const auto containment : m_containments) {
if (Layouts::Storage::self()->isLatteContainment(containment)) { if (Layouts::Storage::self()->isLatteContainment(containment)
int screenId{Layouts::Storage::IDNULL}; && !Layouts::Storage::self()->isClonedView(containment)) {
Data::View view = hasLatteView(containment) ? m_latteViews[containment]->data() : Latte::Layouts::Storage::self()->view(this, containment);
view.screen = Layouts::Storage::self()->expectedViewScreenId(m_corona, view);
//! valid screen id if (view.onPrimary) {
if (latteViewExists(containment)) { map[prmScreenName][view.edge] << containment->id();
screenId = m_latteViews[containment]->positioner()->currentScreenId();
} else { } else {
screenId = containment->screen(); QString expScreenName = m_corona->screenPool()->connector(view.screen);
if (!Layouts::Storage::isValid(screenId)) { if (m_corona->screenPool()->isScreenActive(view.screen)) {
screenId = containment->lastScreen(); map[expScreenName][view.edge] << containment->id();
}
}
bool onPrimary{true};
//! valid onPrimary flag
if (latteViewExists(containment)) {
onPrimary = m_latteViews[containment]->onPrimary();
} else {
onPrimary = containment->config().readEntry("onPrimary", true);
}
//! valid location
Plasma::Types::Location location = containment->location();
if (onPrimary) {
map[prmScreenName][location] << containment->id();
} else {
QString expScreenName = m_corona->screenPool()->connector(screenId);
if (m_corona->screenPool()->isScreenActive(screenId)) {
map[expScreenName][location] << containment->id();
} }
} }
} }
} }
/*
//! CAN BE REMOVED because we now accept primary and explicit views on ACTIVE SCREENS at ALL CASES
Layout::ViewsMap explicitMap;
//! second step: explicit docks must be placed in their screens if the screen edge is free
for (const auto containment : m_containments) {
if (Layouts::Storage::self()->isLatteContainment(containment)) {
int screenId{Layouts::Storage::IDNULL};
//! valid screen id
if (latteViewExists(containment)) {
screenId = m_latteViews[containment]->positioner()->currentScreenId();
} else {
screenId = containment->screen();
if (!Layouts::Storage::isValid(screenId)) {
screenId = containment->lastScreen();
}
}
bool onPrimary{true};
//! valid onPrimary flag
if (latteViewExists(containment)) {
onPrimary = m_latteViews[containment]->onPrimary();
} else {
onPrimary = containment->config().readEntry("onPrimary", true);
}
//! valid location
Plasma::Types::Location location = containment->location();
if (!onPrimary) {
QString expScreenName = m_corona->screenPool()->connector(screenId);
if (m_corona->screenPool()->isScreenActive(screenId) && !map[expScreenName].contains(location)) {
explicitMap[expScreenName][location] << containment->id();
}
}
}
}
for(const QString &expScreenName : explicitMap.keys()) {
for(const Plasma::Types::Location &expLocation : explicitMap[expScreenName].keys()) {
map[expScreenName][expLocation] << explicitMap[expScreenName][expLocation];
}
}*/
return map; return map;
} }
//! the central functions that updates loading/unloading latteviews //! the central functions that updates loading/unloading latteviews
//! concerning screen changed (for multi-screen setups mainly) //! concerning screen changed (for multi-screen setups mainly)
void GenericLayout::syncLatteViewsToScreens(Layout::ViewsMap *occupiedMap) void GenericLayout::syncLatteViewsToScreens()
{ {
if (!m_corona) { if (!m_corona) {
return; return;
@ -1400,11 +1336,7 @@ void GenericLayout::syncLatteViewsToScreens(Layout::ViewsMap *occupiedMap)
} }
//! use valid views map based on active screens //! use valid views map based on active screens
Layout::ViewsMap viewsMap = validViewsMap(occupiedMap); Layout::ViewsMap viewsMap = validViewsMap();
if (occupiedMap != nullptr) {
qDebug() << "Occupied map used :: " << *occupiedMap;
}
QString prmScreenName = qGuiApp->primaryScreen()->name(); QString prmScreenName = qGuiApp->primaryScreen()->name();
@ -1413,14 +1345,8 @@ void GenericLayout::syncLatteViewsToScreens(Layout::ViewsMap *occupiedMap)
//! add views //! add views
for (const auto containment : m_containments) { for (const auto containment : m_containments) {
int screenId = containment->screen(); if (!hasLatteView(containment) && mapContainsId(&viewsMap, containment->id())) {
qDebug() << "syncLatteViewsToScreens: view must be added... for containment:" << containment->id() << " at screen:" << mapScreenName(&viewsMap, containment->id());
if (!Layouts::Storage::isValid(screenId)) {
screenId = containment->lastScreen();
}
if (!latteViewExists(containment) && mapContainsId(&viewsMap, containment->id())) {
qDebug() << "syncLatteViewsToScreens: view must be added... for containment:" << containment->id() << " at screen:" << m_corona->screenPool()->connector(screenId);
addView(containment); addView(containment);
} }
} }
@ -1430,7 +1356,7 @@ void GenericLayout::syncLatteViewsToScreens(Layout::ViewsMap *occupiedMap)
for (auto view : m_latteViews) { for (auto view : m_latteViews) {
auto containment = view->containment(); auto containment = view->containment();
if (containment && !mapContainsId(&viewsMap, containment->id())) { if (containment && view->isOriginal() && !mapContainsId(&viewsMap, containment->id())) {
viewsToDelete << containment; viewsToDelete << containment;
} }
} }
@ -1445,7 +1371,7 @@ void GenericLayout::syncLatteViewsToScreens(Layout::ViewsMap *occupiedMap)
//! reconsider views //! reconsider views
for (const auto view : m_latteViews) { for (const auto view : m_latteViews) {
if (view->containment() && mapContainsId(&viewsMap, view->containment()->id())) { if (view->containment() && view->isOriginal() && mapContainsId(&viewsMap, view->containment()->id())) {
//! if the dock will not be deleted its a very good point to reconsider //! if the dock will not be deleted its a very good point to reconsider
//! if the screen in which is running is the correct one //! if the screen in which is running is the correct one
qDebug() << "syncLatteViewsToScreens: view must consider its screen... for containment:" << view->containment()->id() << " at screen:" << view->positioner()->currentScreenName(); qDebug() << "syncLatteViewsToScreens: view must consider its screen... for containment:" << view->containment()->id() << " at screen:" << view->positioner()->currentScreenName();
@ -1607,7 +1533,7 @@ void GenericLayout::updateView(const Latte::Data::View &viewData)
} }
view->setName(viewData.name); view->setName(viewData.name);
view->positioner()->setNextLocation(nextactivelayoutname, scrName, viewData.edge, viewData.alignment); view->positioner()->setNextLocation(nextactivelayoutname, viewData.screensGroup, scrName, viewData.edge, viewData.alignment);
return; return;
} else { } else {
//! viewMustBeDeleted //! viewMustBeDeleted

View File

@ -55,12 +55,15 @@ public:
virtual const QStringList appliedActivities() = 0; // to move at an interface virtual const QStringList appliedActivities() = 0; // to move at an interface
virtual bool initCorona();
void importToCorona(); void importToCorona();
bool initToCorona(Latte::Corona *corona); bool initContainments();
void setCorona(Latte::Corona *corona);
bool isActive() const; //! is loaded and running bool isActive() const; //! is loaded and running
virtual bool isCurrent(); virtual bool isCurrent();
bool isWritable() const; bool isWritable() const;
bool hasCorona() const;
virtual int viewsCount(int screen) const; virtual int viewsCount(int screen) const;
virtual int viewsCount(QScreen *screen) const; virtual int viewsCount(QScreen *screen) const;
@ -92,8 +95,9 @@ public:
QList<Latte::View *> sortedLatteViews(); QList<Latte::View *> sortedLatteViews();
virtual QList<Latte::View *> viewsWithPlasmaShortcuts(); virtual QList<Latte::View *> viewsWithPlasmaShortcuts();
virtual QList<Latte::View *> latteViews(); virtual QList<Latte::View *> latteViews();
ViewsMap validViewsMap(ViewsMap *occupiedMap = nullptr); virtual QList<Latte::View *> onlyOriginalViews();
virtual void syncLatteViewsToScreens(Layout::ViewsMap *occupiedMap = nullptr); ViewsMap validViewsMap();
virtual void syncLatteViewsToScreens();
void syncToLayoutFile(bool removeLayoutId = false); void syncToLayoutFile(bool removeLayoutId = false);
@ -106,10 +110,10 @@ public:
virtual void setLastConfigViewFor(Latte::View *view); virtual void setLastConfigViewFor(Latte::View *view);
virtual Latte::View *lastConfigViewFor(); virtual Latte::View *lastConfigViewFor();
//! this function needs the layout to have first set the corona through initToCorona() function //! this function needs the layout to have first set the corona through setCorona() function
virtual void addView(Plasma::Containment *containment, bool forceOnPrimary = false, int explicitScreen = -1, Layout::ViewsMap *occupied = nullptr); virtual void addView(Plasma::Containment *containment);
void recreateView(Plasma::Containment *containment, bool delayed = true); void recreateView(Plasma::Containment *containment, bool delayed = true);
bool latteViewExists(Plasma::Containment *containment); bool hasLatteView(Plasma::Containment *containment);
bool newView(const QString &templateName); bool newView(const QString &templateName);
Data::View newView(const Latte::Data::View &nextViewData); Data::View newView(const Latte::Data::View &nextViewData);
@ -190,6 +194,7 @@ private:
bool viewDataAtLowerStatePriority(const Latte::Data::View &test, const Latte::Data::View &base) const; bool viewDataAtLowerStatePriority(const Latte::Data::View &test, const Latte::Data::View &base) const;
bool mapContainsId(const ViewsMap *map, uint viewId) const; bool mapContainsId(const ViewsMap *map, uint viewId) const;
QString mapScreenName(const ViewsMap *map, uint viewId) const;
QList<int> subContainmentsOf(Plasma::Containment *containment) const; QList<int> subContainmentsOf(Plasma::Containment *containment) const;
@ -199,7 +204,7 @@ private:
private: private:
bool m_blockAutomaticLatteViewCreation{false}; bool m_blockAutomaticLatteViewCreation{false};
bool m_hasInitializedContainments{false};
QPointer<Latte::View> m_lastConfigViewFor; QPointer<Latte::View> m_lastConfigViewFor;
QStringList m_unloadedContainmentsIds; QStringList m_unloadedContainmentsIds;

View File

@ -16,6 +16,7 @@
#include "../data/generictable.h" #include "../data/generictable.h"
#include "../layout/abstractlayout.h" #include "../layout/abstractlayout.h"
#include "../layout/centrallayout.h" #include "../layout/centrallayout.h"
#include "../layouts/storage.h"
#include "../settings/universalsettings.h" #include "../settings/universalsettings.h"
#include "../templates/templatesmanager.h" #include "../templates/templatesmanager.h"
#include "../tools/commontools.h" #include "../tools/commontools.h"
@ -332,6 +333,8 @@ void Manager::setOnActivities(QString layoutName, QStringList activities)
void Manager::cleanupOnStartup(QString path) void Manager::cleanupOnStartup(QString path)
{ {
Layouts::Storage::self()->removeAllClonedViews(path);
KSharedConfigPtr filePtr = KSharedConfig::openConfig(path); KSharedConfigPtr filePtr = KSharedConfig::openConfig(path);
KConfigGroup actionGroups = KConfigGroup(filePtr, "ActionPlugins"); KConfigGroup actionGroups = KConfigGroup(filePtr, "ActionPlugins");

View File

@ -12,6 +12,7 @@
#include "../lattecorona.h" #include "../lattecorona.h"
#include "../screenpool.h" #include "../screenpool.h"
#include "../data/errordata.h" #include "../data/errordata.h"
#include "../data/viewdata.h"
#include "../layout/abstractlayout.h" #include "../layout/abstractlayout.h"
#include "../view/view.h" #include "../view/view.h"
@ -99,13 +100,13 @@ bool Storage::isLatteContainment(const KConfigGroup &group) const
return pluginId == QLatin1String("org.kde.latte.containment"); return pluginId == QLatin1String("org.kde.latte.containment");
} }
bool Storage::isSubContainment(const Layout::GenericLayout *layout, const Plasma::Applet *applet) const bool Storage::isSubContainment(const Plasma::Corona *corona, const Plasma::Applet *applet) const
{ {
if (!layout || !applet) { if (!corona || !applet) {
return false; return false;
} }
for (const auto containment : *layout->containments()) { for (const auto containment : corona->containments()) {
Plasma::Applet *parentApplet = qobject_cast<Plasma::Applet *>(containment->parent()); Plasma::Applet *parentApplet = qobject_cast<Plasma::Applet *>(containment->parent());
if (parentApplet && parentApplet == applet) { if (parentApplet && parentApplet == applet) {
return true; return true;
@ -178,14 +179,14 @@ int Storage::subIdentityIndex(const KConfigGroup &appletGroup) const
return IDNULL; return IDNULL;
} }
Plasma::Containment *Storage::subContainmentOf(const Layout::GenericLayout *layout, const Plasma::Applet *applet) Plasma::Containment *Storage::subContainmentOf(const Plasma::Corona *corona, const Plasma::Applet *applet)
{ {
if (!layout || !applet) { if (!corona || !applet) {
return nullptr; return nullptr;
} }
if (isSubContainment(layout, applet)) { if (isSubContainment(corona, applet)) {
for (const auto containment : *layout->containments()) { for (const auto containment : corona->containments()) {
Plasma::Applet *parentApplet = qobject_cast<Plasma::Applet *>(containment->parent()); Plasma::Applet *parentApplet = qobject_cast<Plasma::Applet *>(containment->parent());
if (parentApplet && parentApplet == applet) { if (parentApplet && parentApplet == applet) {
return containment; return containment;
@ -224,6 +225,8 @@ void Storage::importToCorona(const Layout::GenericLayout *layout)
//! Setting mutable for create a containment //! Setting mutable for create a containment
layout->corona()->setImmutability(Plasma::Types::Mutable); layout->corona()->setImmutability(Plasma::Types::Mutable);
removeAllClonedViews(layout->file());
QString temp1FilePath = m_storageTmpDir.path() + "/" + layout->name() + ".multiple.views"; QString temp1FilePath = m_storageTmpDir.path() + "/" + layout->name() + ".multiple.views";
//! we need to copy first the layout file because the kde cache //! we need to copy first the layout file because the kde cache
//! may not have yet been updated (KSharedConfigPtr) //! may not have yet been updated (KSharedConfigPtr)
@ -240,8 +243,9 @@ void Storage::importToCorona(const Layout::GenericLayout *layout)
tempLayoutFile.remove(); tempLayoutFile.remove();
} }
if (copyFile.exists()) if (copyFile.exists()) {
copyFile.remove(); copyFile.remove();
}
layoutOriginalFile.copy(tempLayoutFilePath); layoutOriginalFile.copy(tempLayoutFilePath);
@ -329,7 +333,7 @@ QString Storage::newUniqueIdsFile(QString originFile, const Layout::GenericLayou
QString currentdestinationname = destinationLayout->name(); QString currentdestinationname = destinationLayout->name();
QString currentdestinationfile = ""; QString currentdestinationfile = "";
if (!destinationLayout->isActive()) { if (!destinationLayout->hasCorona()) {
currentdestinationfile = destinationLayout->file(); currentdestinationfile = destinationLayout->file();
} }
@ -344,7 +348,7 @@ QString Storage::newUniqueIdsFile(QString originFile, const Layout::GenericLayou
//! BEGIN updating the ids in the temp file //! BEGIN updating the ids in the temp file
QStringList allIds; QStringList allIds;
if (destinationLayout->isActive()) { if (destinationLayout->hasCorona()) {
allIds << destinationLayout->corona()->containmentsIds(); allIds << destinationLayout->corona()->containmentsIds();
allIds << destinationLayout->corona()->appletsIds(); allIds << destinationLayout->corona()->appletsIds();
} else { } else {
@ -475,7 +479,7 @@ QString Storage::newUniqueIdsFile(QString originFile, const Layout::GenericLayou
} }
} }
if (destinationLayout->isActive() && destinationLayout->corona()->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts) { if (destinationLayout->hasCorona() && destinationLayout->corona()->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts) {
//! will be added in main corona multiple layouts file //! will be added in main corona multiple layouts file
investigate_conts.group(cId).writeEntry("layoutId", destinationLayout->name()); investigate_conts.group(cId).writeEntry("layoutId", destinationLayout->name());
} else { } else {
@ -560,6 +564,7 @@ void Storage::syncToLayoutFile(const Layout::GenericLayout *layout, bool removeL
} }
filePtr->reparseConfiguration(); filePtr->reparseConfiguration();
removeAllClonedViews(layout->file());
} }
QList<Plasma::Containment *> Storage::importLayoutFile(const Layout::GenericLayout *layout, QString file) QList<Plasma::Containment *> Storage::importLayoutFile(const Layout::GenericLayout *layout, QString file)
@ -567,13 +572,10 @@ QList<Plasma::Containment *> Storage::importLayoutFile(const Layout::GenericLayo
KSharedConfigPtr filePtr = KSharedConfig::openConfig(file); KSharedConfigPtr filePtr = KSharedConfig::openConfig(file);
auto newContainments = layout->corona()->importLayout(KConfigGroup(filePtr, "")); auto newContainments = layout->corona()->importLayout(KConfigGroup(filePtr, ""));
qDebug() << " imported containments ::: " << newContainments.length();
QList<Plasma::Containment *> importedViews; QList<Plasma::Containment *> importedViews;
for (const auto containment : newContainments) { for (const auto containment : newContainments) {
if (isLatteContainment(containment)) { if (isLatteContainment(containment)) {
qDebug() << "new latte containment id: " << containment->id();
importedViews << containment; importedViews << containment;
} }
} }
@ -609,7 +611,7 @@ Data::View Storage::newView(const Layout::GenericLayout *destinationLayout, cons
qDebug() << "new view for layout"; qDebug() << "new view for layout";
if (destinationLayout->isActive()) { if (destinationLayout->hasCorona()) {
//! Setting mutable for create a containment //! Setting mutable for create a containment
destinationLayout->corona()->setImmutability(Plasma::Types::Mutable); destinationLayout->corona()->setImmutability(Plasma::Types::Mutable);
} }
@ -650,7 +652,7 @@ Data::View Storage::newView(const Layout::GenericLayout *destinationLayout, cons
return Data::View(); return Data::View();
} }
if (destinationLayout->isActive()) { if (destinationLayout->hasCorona()) {
//! import views for active layout //! import views for active layout
QList<Plasma::Containment *> importedViews = importLayoutFile(destinationLayout, temp2File); QList<Plasma::Containment *> importedViews = importLayoutFile(destinationLayout, temp2File);
@ -732,6 +734,7 @@ bool Storage::exportTemplate(const QString &originFile, const QString &destinati
KConfigGroup layoutSettingsGrp(destFilePtr, "LayoutSettings"); KConfigGroup layoutSettingsGrp(destFilePtr, "LayoutSettings");
clearExportedLayoutSettings(layoutSettingsGrp); clearExportedLayoutSettings(layoutSettingsGrp);
destFilePtr->reparseConfiguration(); destFilePtr->reparseConfiguration();
removeAllClonedViews(destinationFile);
return true; return true;
} }
@ -828,6 +831,7 @@ bool Storage::exportTemplate(const Layout::GenericLayout *layout, Plasma::Contai
KConfigGroup layoutSettingsGrp(destFilePtr, "LayoutSettings"); KConfigGroup layoutSettingsGrp(destFilePtr, "LayoutSettings");
clearExportedLayoutSettings(layoutSettingsGrp); clearExportedLayoutSettings(layoutSettingsGrp);
destFilePtr->reparseConfiguration(); destFilePtr->reparseConfiguration();
removeAllClonedViews(destinationFile);
return true; return true;
} }
@ -1271,7 +1275,7 @@ Data::AppletsTable Storage::plugins(const Layout::GenericLayout *layout, const i
} }
for (auto applet : containment->applets()) { for (auto applet : containment->applets()) {
if (isSubContainment(layout, applet)) { if (isSubContainment(layout->corona(), applet)) {
validcontainmentids << subContainmentId(applet->config()); validcontainmentids << subContainmentId(applet->config());
} }
} }
@ -1426,6 +1430,51 @@ bool Storage::hasContainment(const Layout::GenericLayout *layout, const int &id)
return false; return false;
} }
bool Storage::isClonedView(const Plasma::Containment *containment) const
{
if (!containment) {
return false;
}
return isClonedView(containment->config());
}
bool Storage::isClonedView(const KConfigGroup &containmentGroup) const
{
if (!isLatteContainment(containmentGroup)) {
return false;
}
int isClonedFrom = containmentGroup.readEntry("isClonedFrom", Data::View::ISCLONEDNULL);
return (isClonedFrom != IDNULL);
}
void Storage::removeAllClonedViews(const QString &filepath)
{
KSharedConfigPtr lFile = KSharedConfig::openConfig(filepath);
KConfigGroup containmentGroups = KConfigGroup(lFile, "Containments");
QList<Data::View> clones;
for (const auto &contId : containmentGroups.groupList()) {
if (isClonedView(containmentGroups.group(contId))) {
clones << view(containmentGroups.group(contId));
}
}
if (clones.size() <= 0) {
return;
}
if (clones.count()>0) {
qDebug() << "org.kde.layout :: Removing clones from file: " << filepath;
}
for (const auto &clonedata : clones) {
qDebug() << "org.kde.layout :: Removing clone:" << clonedata.id << " and its subcontainments:" << clonedata.subcontainments;
removeView(filepath, clonedata);
}
}
Data::GenericTable<Data::Generic> Storage::subcontainments(const Layout::GenericLayout *layout, const Plasma::Containment *lattecontainment) const Data::GenericTable<Data::Generic> Storage::subcontainments(const Layout::GenericLayout *layout, const Plasma::Containment *lattecontainment) const
{ {
@ -1505,8 +1554,10 @@ Data::View Storage::view(const KConfigGroup &containmentGroup)
vdata.id = containmentGroup.name(); vdata.id = containmentGroup.name();
vdata.name = containmentGroup.readEntry("name", QString()); vdata.name = containmentGroup.readEntry("name", QString());
vdata.isActive = false; vdata.isActive = false;
vdata.screensGroup = static_cast<Latte::Types::ScreensGroup>(containmentGroup.readEntry("screensGroup", (int)Latte::Types::SingleScreenGroup));
vdata.onPrimary = containmentGroup.readEntry("onPrimary", true); vdata.onPrimary = containmentGroup.readEntry("onPrimary", true);
vdata.screen = containmentGroup.readEntry("lastScreen", IDNULL); vdata.screen = containmentGroup.readEntry("lastScreen", IDNULL);
vdata.isClonedFrom = containmentGroup.readEntry("isClonedFrom", Data::View::ISCLONEDNULL);
vdata.screenEdgeMargin = containmentGroup.group("General").readEntry("screenEdgeMargin", (int)-1); vdata.screenEdgeMargin = containmentGroup.group("General").readEntry("screenEdgeMargin", (int)-1);
int location = containmentGroup.readEntry("location", (int)Plasma::Types::BottomEdge); int location = containmentGroup.readEntry("location", (int)Plasma::Types::BottomEdge);
@ -1530,7 +1581,9 @@ void Storage::updateView(KConfigGroup viewGroup, const Data::View &viewData)
} }
viewGroup.writeEntry("name", viewData.name); viewGroup.writeEntry("name", viewData.name);
viewGroup.writeEntry("screensGroup", (int)viewData.screensGroup);
viewGroup.writeEntry("onPrimary", viewData.onPrimary); viewGroup.writeEntry("onPrimary", viewData.onPrimary);
viewGroup.writeEntry("isClonedFrom", viewData.isClonedFrom);
viewGroup.writeEntry("lastScreen", viewData.screen); viewGroup.writeEntry("lastScreen", viewData.screen);
viewGroup.group("General").writeEntry("screenEdgeMargin", viewData.screenEdgeMargin); viewGroup.group("General").writeEntry("screenEdgeMargin", viewData.screenEdgeMargin);
viewGroup.writeEntry("location", (int)viewData.edge); viewGroup.writeEntry("location", (int)viewData.edge);
@ -1677,6 +1730,38 @@ QString Storage::storedView(const Layout::GenericLayout *layout, const int &cont
return nextTmpStoredViewAbsolutePath; return nextTmpStoredViewAbsolutePath;
} }
int Storage::expectedViewScreenId(const Latte::Corona *corona, const KConfigGroup &containmentGroup) const
{
return expectedViewScreenId(corona, self()->view(containmentGroup));
}
int Storage::expectedViewScreenId(const Layout::GenericLayout *layout, const Plasma::Containment *lattecontainment) const
{
if (!layout || !layout->corona()) {
return Latte::ScreenPool::NOSCREENID;
}
return expectedViewScreenId(layout->corona(), self()->view(layout, lattecontainment));
}
int Storage::expectedViewScreenId(const Latte::Corona *corona, const Data::View &view) const
{
if (!corona || !view.isValid()) {
return Latte::ScreenPool::NOSCREENID;
}
if (view.screensGroup == Latte::Types::SingleScreenGroup || view.isCloned()) {
return view.onPrimary ? corona->screenPool()->primaryScreenId() : view.screen;
} else if (view.screensGroup == Latte::Types::AllScreensGroup) {
return corona->screenPool()->primaryScreenId();
} else if (view.screensGroup == Latte::Types::AllSecondaryScreensGroup) {
QList<int> secondaryscreens = corona->screenPool()->secondaryScreenIds();
return secondaryscreens.contains(view.screen) || secondaryscreens.isEmpty() ? view.screen : secondaryscreens[0];
}
return Latte::ScreenPool::NOSCREENID;
}
Data::ViewsTable Storage::views(const Layout::GenericLayout *layout) Data::ViewsTable Storage::views(const Layout::GenericLayout *layout)
{ {
Data::ViewsTable vtable; Data::ViewsTable vtable;

View File

@ -24,6 +24,7 @@
#include <Plasma/Containment> #include <Plasma/Containment>
namespace Latte { namespace Latte {
class Corona;
namespace Layout { namespace Layout {
class GenericLayout; class GenericLayout;
} }
@ -51,14 +52,18 @@ public:
bool isWritable(const Layout::GenericLayout *layout) const; bool isWritable(const Layout::GenericLayout *layout) const;
bool isLatteContainment(const Plasma::Containment *containment) const; bool isLatteContainment(const Plasma::Containment *containment) const;
bool isLatteContainment(const KConfigGroup &group) const; bool isLatteContainment(const KConfigGroup &group) const;
bool isSubContainment(const Layout::GenericLayout *layout, const Plasma::Applet *applet) const; bool isSubContainment(const Plasma::Corona *corona, const Plasma::Applet *applet) const;
bool hasContainment(const Layout::GenericLayout *layout, const int &id); bool hasContainment(const Layout::GenericLayout *layout, const int &id);
bool containsView(const QString &filepath, const int &viewId); bool containsView(const QString &filepath, const int &viewId);
bool isClonedView(const Plasma::Containment *containment) const;
bool isClonedView(const KConfigGroup &containmentGroup) const;
void removeAllClonedViews(const QString &filepath);
int subContainmentId(const KConfigGroup &appletGroup) const; int subContainmentId(const KConfigGroup &appletGroup) const;
Plasma::Containment *subContainmentOf(const Layout::GenericLayout *layout, const Plasma::Applet *applet); Plasma::Containment *subContainmentOf(const Plasma::Corona *corona, const Plasma::Applet *applet);
void lock(const Layout::GenericLayout *layout); //! make it only read-only void lock(const Layout::GenericLayout *layout); //! make it only read-only
void unlock(const Layout::GenericLayout *layout); //! make it writable which it should be the default void unlock(const Layout::GenericLayout *layout); //! make it writable which it should be the default
@ -77,12 +82,15 @@ public:
bool exportTemplate(const QString &originFile, const QString &destinationFile, const Data::AppletsTable &approvedApplets); bool exportTemplate(const QString &originFile, const QString &destinationFile, const Data::AppletsTable &approvedApplets);
bool exportTemplate(const Layout::GenericLayout *layout, Plasma::Containment *containment, const QString &destinationFile, const Data::AppletsTable &approvedApplets); bool exportTemplate(const Layout::GenericLayout *layout, Plasma::Containment *containment, const QString &destinationFile, const Data::AppletsTable &approvedApplets);
int expectedViewScreenId(const Latte::Corona *corona, const Data::View &view) const;
int expectedViewScreenId(const Latte::Corona *corona, const KConfigGroup &containmentGroup) const;
int expectedViewScreenId(const Layout::GenericLayout *layout, const Plasma::Containment *lattecontainment) const;
/// STATIC /// STATIC
//! Check if an applet config group is valid or belongs to removed applet //! Check if an applet config group is valid or belongs to removed applet
static bool appletGroupIsValid(const KConfigGroup &appletGroup); static bool appletGroupIsValid(const KConfigGroup &appletGroup);
static bool isValid(const int &id); static bool isValid(const int &id);
//! AppletsData Information //! AppletsData Information
Data::Applet metadata(const QString &pluginId); Data::Applet metadata(const QString &pluginId);
Data::AppletsTable plugins(const Layout::GenericLayout *layout, const int containmentid = IDNULL); Data::AppletsTable plugins(const Layout::GenericLayout *layout, const int containmentid = IDNULL);

View File

@ -6,7 +6,6 @@
#include "syncedlaunchers.h" #include "syncedlaunchers.h"
// local // local
#include <coretypes.h>
#include "../lattecorona.h" #include "../lattecorona.h"
#include "../layout/centrallayout.h" #include "../layout/centrallayout.h"
#include "../layouts/manager.h" #include "../layouts/manager.h"
@ -63,36 +62,61 @@ void SyncedLaunchers::removeClientObject(QObject *obj)
} }
} }
QList<QQuickItem *> SyncedLaunchers::clients(QString layoutName) QQuickItem *SyncedLaunchers::client(const int &id)
{
if (id <= 0) {
return nullptr;
}
for(const auto client: m_clients) {
int clientid = client->property("clientId").toInt();
if (clientid == id) {
return client;
}
}
return nullptr;
}
QList<QQuickItem *> SyncedLaunchers::clients(QString layoutName, int groupId)
{ {
QList<QQuickItem *> items; QList<QQuickItem *> items;
if (!layoutName.isEmpty()) { for(const auto client: m_clients) {
for(const auto client: m_clients) { QString cLayoutName = layoutName.isEmpty() ? QString() : client->property("layoutName").toString();
QString cLayoutName = client->property("layoutName").toString(); int gid = client->property("syncedGroupId").toInt();
if (cLayoutName == layoutName) { if (cLayoutName == layoutName && gid == groupId) {
items << client; items << client;
}
} }
} else {
items = m_clients;
} }
return items; return items;
} }
void SyncedLaunchers::addLauncher(QString layoutName, int launcherGroup, QString launcher) QList<QQuickItem *> SyncedLaunchers::clients(QString layoutName, uint senderId, Latte::Types::LaunchersGroup launcherGroup, int launcherGroupId)
{ {
Types::LaunchersGroup group = static_cast<Types::LaunchersGroup>(launcherGroup); QList<QQuickItem *> temclients;
if ((Types::LaunchersGroup)group == Types::UniqueLaunchers) { if (launcherGroup == Types::UniqueLaunchers && launcherGroupId < 0) {
return; //! on its own, single taskmanager
auto c = client(senderId);
if (c) {
temclients << client(senderId);
}
} else {
temclients << clients(layoutName, launcherGroupId);
} }
return temclients;
}
void SyncedLaunchers::addLauncher(QString layoutName, uint senderId, int launcherGroup, int launcherGroupId, QString launcher)
{
Types::LaunchersGroup group = static_cast<Types::LaunchersGroup>(launcherGroup);
QString lName = (group == Types::LayoutLaunchers) ? layoutName : ""; QString lName = (group == Types::LayoutLaunchers) ? layoutName : "";
for(const auto client : clients(lName)) { for(const auto c : clients(lName, senderId, group, launcherGroupId)) {
if (auto *metaObject = client->metaObject()) { if (auto *metaObject = c->metaObject()) {
int methodIndex = metaObject->indexOfMethod("addSyncedLauncher(QVariant,QVariant)"); int methodIndex = metaObject->indexOfMethod("addSyncedLauncher(QVariant,QVariant)");
if (methodIndex == -1) { if (methodIndex == -1) {
@ -101,23 +125,18 @@ void SyncedLaunchers::addLauncher(QString layoutName, int launcherGroup, QString
} }
QMetaMethod method = metaObject->method(methodIndex); QMetaMethod method = metaObject->method(methodIndex);
method.invoke(client, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launcher)); method.invoke(c, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launcher));
} }
} }
} }
void SyncedLaunchers::removeLauncher(QString layoutName, int launcherGroup, QString launcher) void SyncedLaunchers::removeLauncher(QString layoutName, uint senderId, int launcherGroup, int launcherGroupId, QString launcher)
{ {
Types::LaunchersGroup group = static_cast<Types::LaunchersGroup>(launcherGroup); Types::LaunchersGroup group = static_cast<Types::LaunchersGroup>(launcherGroup);
if ((Types::LaunchersGroup)group == Types::UniqueLaunchers) {
return;
}
QString lName = (group == Types::LayoutLaunchers) ? layoutName : ""; QString lName = (group == Types::LayoutLaunchers) ? layoutName : "";
for(const auto client : clients(lName)) { for(const auto c : clients(lName, senderId, group, launcherGroupId)) {
if (auto *metaObject = client->metaObject()) { if (auto *metaObject = c->metaObject()) {
int methodIndex = metaObject->indexOfMethod("removeSyncedLauncher(QVariant,QVariant)"); int methodIndex = metaObject->indexOfMethod("removeSyncedLauncher(QVariant,QVariant)");
if (methodIndex == -1) { if (methodIndex == -1) {
@ -126,23 +145,18 @@ void SyncedLaunchers::removeLauncher(QString layoutName, int launcherGroup, QStr
} }
QMetaMethod method = metaObject->method(methodIndex); QMetaMethod method = metaObject->method(methodIndex);
method.invoke(client, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launcher)); method.invoke(c, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launcher));
} }
} }
} }
void SyncedLaunchers::addLauncherToActivity(QString layoutName, int launcherGroup, QString launcher, QString activity) void SyncedLaunchers::addLauncherToActivity(QString layoutName, uint senderId, int launcherGroup, int launcherGroupId, QString launcher, QString activity)
{ {
Types::LaunchersGroup group = static_cast<Types::LaunchersGroup>(launcherGroup); Types::LaunchersGroup group = static_cast<Types::LaunchersGroup>(launcherGroup);
if ((Types::LaunchersGroup)group == Types::UniqueLaunchers) {
return;
}
QString lName = (group == Types::LayoutLaunchers) ? layoutName : ""; QString lName = (group == Types::LayoutLaunchers) ? layoutName : "";
for(const auto client : clients(lName)) { for(const auto c : clients(lName, senderId, group, launcherGroupId)) {
if (auto *metaObject = client->metaObject()) { if (auto *metaObject = c->metaObject()) {
int methodIndex = metaObject->indexOfMethod("addSyncedLauncherToActivity(QVariant,QVariant,QVariant)"); int methodIndex = metaObject->indexOfMethod("addSyncedLauncherToActivity(QVariant,QVariant,QVariant)");
if (methodIndex == -1) { if (methodIndex == -1) {
@ -151,23 +165,18 @@ void SyncedLaunchers::addLauncherToActivity(QString layoutName, int launcherGrou
} }
QMetaMethod method = metaObject->method(methodIndex); QMetaMethod method = metaObject->method(methodIndex);
method.invoke(client, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launcher), Q_ARG(QVariant, activity)); method.invoke(c, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launcher), Q_ARG(QVariant, activity));
} }
} }
} }
void SyncedLaunchers::removeLauncherFromActivity(QString layoutName, int launcherGroup, QString launcher, QString activity) void SyncedLaunchers::removeLauncherFromActivity(QString layoutName, uint senderId, int launcherGroup, int launcherGroupId, QString launcher, QString activity)
{ {
Types::LaunchersGroup group = static_cast<Types::LaunchersGroup>(launcherGroup); Types::LaunchersGroup group = static_cast<Types::LaunchersGroup>(launcherGroup);
if ((Types::LaunchersGroup)group == Types::UniqueLaunchers) {
return;
}
QString lName = (group == Types::LayoutLaunchers) ? layoutName : ""; QString lName = (group == Types::LayoutLaunchers) ? layoutName : "";
for(const auto client : clients(lName)) { for(const auto c : clients(lName, senderId, group, launcherGroupId)) {
if (auto *metaObject = client->metaObject()) { if (auto *metaObject = c->metaObject()) {
int methodIndex = metaObject->indexOfMethod("removeSyncedLauncherFromActivity(QVariant,QVariant,QVariant)"); int methodIndex = metaObject->indexOfMethod("removeSyncedLauncherFromActivity(QVariant,QVariant,QVariant)");
if (methodIndex == -1) { if (methodIndex == -1) {
@ -176,23 +185,18 @@ void SyncedLaunchers::removeLauncherFromActivity(QString layoutName, int launche
} }
QMetaMethod method = metaObject->method(methodIndex); QMetaMethod method = metaObject->method(methodIndex);
method.invoke(client, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launcher), Q_ARG(QVariant, activity)); method.invoke(c, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launcher), Q_ARG(QVariant, activity));
} }
} }
} }
void SyncedLaunchers::urlsDropped(QString layoutName, int launcherGroup, QStringList urls) void SyncedLaunchers::urlsDropped(QString layoutName, uint senderId, int launcherGroup, int launcherGroupId, QStringList urls)
{ {
Types::LaunchersGroup group = static_cast<Types::LaunchersGroup>(launcherGroup); Types::LaunchersGroup group = static_cast<Types::LaunchersGroup>(launcherGroup);
if ((Types::LaunchersGroup)group == Types::UniqueLaunchers) {
return;
}
QString lName = (group == Types::LayoutLaunchers) ? layoutName : ""; QString lName = (group == Types::LayoutLaunchers) ? layoutName : "";
for(const auto client : clients(lName)) { for(const auto c : clients(lName, senderId, group, launcherGroupId)) {
if (auto *metaObject = client->metaObject()) { if (auto *metaObject = c->metaObject()) {
int methodIndex = metaObject->indexOfMethod("dropSyncedUrls(QVariant,QVariant)"); int methodIndex = metaObject->indexOfMethod("dropSyncedUrls(QVariant,QVariant)");
if (methodIndex == -1) { if (methodIndex == -1) {
@ -201,26 +205,21 @@ void SyncedLaunchers::urlsDropped(QString layoutName, int launcherGroup, QString
} }
QMetaMethod method = metaObject->method(methodIndex); QMetaMethod method = metaObject->method(methodIndex);
method.invoke(client, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, urls)); method.invoke(c, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, urls));
} }
} }
} }
void SyncedLaunchers::validateLaunchersOrder(QString layoutName, uint senderId, int launcherGroup, QStringList launchers) void SyncedLaunchers::validateLaunchersOrder(QString layoutName, uint senderId, int launcherGroup, int launcherGroupId, QStringList launchers)
{ {
Types::LaunchersGroup group = static_cast<Types::LaunchersGroup>(launcherGroup); Types::LaunchersGroup group = static_cast<Types::LaunchersGroup>(launcherGroup);
if ((Types::LaunchersGroup)group == Types::UniqueLaunchers) {
return;
}
QString lName = (group == Types::LayoutLaunchers) ? layoutName : ""; QString lName = (group == Types::LayoutLaunchers) ? layoutName : "";
for(const auto client : clients(lName)) { for(const auto c : clients(lName, senderId, group, launcherGroupId)) {
uint clientId = client->property("clientId").toUInt(); auto tc = client(senderId);
if (clientId != senderId) { if (c != tc) {
if (auto *metaObject = client->metaObject()) { if (auto *metaObject = c->metaObject()) {
int methodIndex = metaObject->indexOfMethod("validateSyncedLaunchersOrder(QVariant,QVariant)"); int methodIndex = metaObject->indexOfMethod("validateSyncedLaunchersOrder(QVariant,QVariant)");
if (methodIndex == -1) { if (methodIndex == -1) {
@ -229,7 +228,7 @@ void SyncedLaunchers::validateLaunchersOrder(QString layoutName, uint senderId,
} }
QMetaMethod method = metaObject->method(methodIndex); QMetaMethod method = metaObject->method(methodIndex);
method.invoke(client, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launchers)); method.invoke(c, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launchers));
} }
} }
} }

View File

@ -6,6 +6,9 @@
#ifndef SYNCEDLAUNCHERS_H #ifndef SYNCEDLAUNCHERS_H
#define SYNCEDLAUNCHERS_H #define SYNCEDLAUNCHERS_H
// local
#include <coretypes.h>
// Qt // Qt
#include <QList> #include <QList>
#include <QObject> #include <QObject>
@ -42,15 +45,17 @@ public slots:
Q_INVOKABLE void addAbilityClient(QQuickItem *client); Q_INVOKABLE void addAbilityClient(QQuickItem *client);
Q_INVOKABLE void removeAbilityClient(QQuickItem *client); Q_INVOKABLE void removeAbilityClient(QQuickItem *client);
Q_INVOKABLE void addLauncher(QString layoutName, int launcherGroup, QString launcher); Q_INVOKABLE void addLauncher(QString layoutName, uint senderId, int launcherGroup, int launcherGroupId, QString launcher);
Q_INVOKABLE void removeLauncher(QString layoutName, int launcherGroup, QString launcher); Q_INVOKABLE void removeLauncher(QString layoutName, uint senderId, int launcherGroup, int launcherGroupId, QString launcher);
Q_INVOKABLE void addLauncherToActivity(QString layoutName, int launcherGroup, QString launcher, QString activity); Q_INVOKABLE void addLauncherToActivity(QString layoutName, uint senderId, int launcherGroup,int launcherGroupId, QString launcher, QString activity);
Q_INVOKABLE void removeLauncherFromActivity(QString layoutName, int launcherGroup, QString launcher, QString activity); Q_INVOKABLE void removeLauncherFromActivity(QString layoutName, uint senderId, int launcherGroup, int launcherGroupId, QString launcher, QString activity);
Q_INVOKABLE void urlsDropped(QString layoutName, int launcherGroup, QStringList urls); Q_INVOKABLE void urlsDropped(QString layoutName, uint senderId, int launcherGroup, int launcherGroupId, QStringList urls);
Q_INVOKABLE void validateLaunchersOrder(QString layoutName, uint senderId, int launcherGroup, QStringList launchers); Q_INVOKABLE void validateLaunchersOrder(QString layoutName, uint senderId, int launcherGroup, int launcherGroupId, QStringList launchers);
private: private:
QList<QQuickItem *> clients(QString layoutName = QString()); QList<QQuickItem *> clients(QString layoutName, int groupId);
QList<QQuickItem *> clients(QString layoutName, uint senderId, Latte::Types::LaunchersGroup launcherGroup, int launcherGroupId);
QQuickItem *client(const int &id);
private slots: private slots:
void removeClientObject(QObject *obj); void removeClientObject(QObject *obj);

View File

@ -191,7 +191,9 @@ QStringList Synchronizer::centralLayoutsNames()
QStringList names; QStringList names;
if (m_manager->memoryUsage() == MemoryUsage::SingleLayout) { if (m_manager->memoryUsage() == MemoryUsage::SingleLayout) {
names << m_centralLayouts.at(0)->name(); if (m_centralLayouts.count() > 0) {
names << m_centralLayouts.at(0)->name();
}
} else { } else {
for (int i = 0; i < m_centralLayouts.size(); ++i) { for (int i = 0; i < m_centralLayouts.size(); ++i) {
CentralLayout *layout = m_centralLayouts.at(i); CentralLayout *layout = m_centralLayouts.at(i);
@ -357,6 +359,17 @@ QList<Latte::View *> Synchronizer::currentViews() const
return views; return views;
} }
QList<Latte::View *> Synchronizer::currentOriginalViews() const
{
QList<Latte::View *> views;
for(auto layout : currentLayouts()) {
views << layout->onlyOriginalViews();
}
return views;
}
QList<Latte::View *> Synchronizer::currentViewsWithPlasmaShortcuts() const QList<Latte::View *> Synchronizer::currentViewsWithPlasmaShortcuts() const
{ {
QList<Latte::View *> views; QList<Latte::View *> views;
@ -370,9 +383,12 @@ QList<Latte::View *> Synchronizer::currentViewsWithPlasmaShortcuts() const
QList<Latte::View *> Synchronizer::sortedCurrentViews() const QList<Latte::View *> Synchronizer::sortedCurrentViews() const
{ {
QList<Latte::View *> views = currentViews(); return Layout::GenericLayout::sortedLatteViews(currentViews());
}
return Layout::GenericLayout::sortedLatteViews(views); QList<Latte::View *> Synchronizer::sortedCurrentOriginalViews() const
{
return Layout::GenericLayout::sortedLatteViews(currentOriginalViews());
} }
QList<Latte::View *> Synchronizer::viewsBasedOnActivityId(const QString &id) const QList<Latte::View *> Synchronizer::viewsBasedOnActivityId(const QString &id) const
@ -436,7 +452,6 @@ void Synchronizer::addLayout(CentralLayout *layout)
{ {
if (!m_centralLayouts.contains(layout)) { if (!m_centralLayouts.contains(layout)) {
m_centralLayouts.append(layout); m_centralLayouts.append(layout);
layout->initToCorona(m_manager->corona());
} }
} }
@ -644,11 +659,20 @@ bool Synchronizer::initSingleMode(QString layoutName)
qDebug() << " ... initializing layout in single mode : " << layoutName << " - " << layoutpath; qDebug() << " ... initializing layout in single mode : " << layoutName << " - " << layoutpath;
unloadLayouts(); unloadLayouts();
//! load the main layout/corona file //! load the main single layout/corona file
CentralLayout *newLayout = new CentralLayout(this, layoutpath, layoutName); CentralLayout *newLayout = new CentralLayout(this, layoutpath, layoutName);
addLayout(newLayout);
m_manager->loadLatteLayout(layoutpath); //! Order of initialization steps is very important and guarantees correct startup initialization
//! Step1: corona is set for the layout
//! Step2: containments from file are loaded into main corona
//! Step3: layout connects to corona signals and slots
//! Step4: layout is added in manager and is accesible for others to find
//! Step5: layout is attaching its initial containmens and is now considered ACTIVE
newLayout->setCorona(m_manager->corona()); //step1
m_manager->loadLatteLayout(layoutpath); //step2
newLayout->initCorona(); //step3
addLayout(newLayout); //step4
newLayout->initContainments(); //step5
emit centralLayoutsChanged(); emit centralLayoutsChanged();
@ -939,8 +963,18 @@ void Synchronizer::syncMultipleLayoutsToActivities()
if (newLayout) { if (newLayout) {
qDebug() << "ACTIVATING LAYOUT ::::: " << layoutname; qDebug() << "ACTIVATING LAYOUT ::::: " << layoutname;
addLayout(newLayout);
newLayout->importToCorona(); //! Order of initialization steps is very important and guarantees correct startup initialization
//! Step1: corona is set for the layout
//! Step2: containments from the layout file are adjusted and are imported into main corona
//! Step3: layout connects to corona signals and slots
//! Step4: layout is added in manager and is accesible for others to find
//! Step5: layout is attaching its initial containmens and is now considered ACTIVE
newLayout->setCorona(m_manager->corona()); //step1
newLayout->importToCorona(); //step2
newLayout->initCorona(); //step3
addLayout(newLayout); //step4
newLayout->initContainments(); //step5
if (!defaultForcedLayout.isEmpty() && defaultForcedLayout == layoutname) { if (!defaultForcedLayout.isEmpty() && defaultForcedLayout == layoutname) {
emit newLayoutAdded(newLayout->data()); emit newLayoutAdded(newLayout->data());

View File

@ -95,7 +95,9 @@ public:
QList<CentralLayout *> currentLayouts() const; QList<CentralLayout *> currentLayouts() const;
QList<Latte::View *> currentViews() const; QList<Latte::View *> currentViews() const;
QList<Latte::View *> currentViewsWithPlasmaShortcuts() const; QList<Latte::View *> currentViewsWithPlasmaShortcuts() const;
QList<Latte::View *> currentOriginalViews() const;
QList<Latte::View *> sortedCurrentViews() const; QList<Latte::View *> sortedCurrentViews() const;
QList<Latte::View *> sortedCurrentOriginalViews() const;
QList<Latte::View *> viewsBasedOnActivityId(const QString &id) const; QList<Latte::View *> viewsBasedOnActivityId(const QString &id) const;
CentralLayout *centralLayout(QString layoutname) const; CentralLayout *centralLayout(QString layoutname) const;

View File

@ -168,6 +168,21 @@ int ScreenPool::primaryScreenId() const
return id(qGuiApp->primaryScreen()->name()); return id(qGuiApp->primaryScreen()->name());
} }
QList<int> ScreenPool::secondaryScreenIds() const
{
QList<int> secondaryscreens;
for (const auto scr : qGuiApp->screens()) {
if (scr == qGuiApp->primaryScreen()) {
continue;
}
secondaryscreens << id(scr->name());
}
return secondaryscreens;
}
void ScreenPool::save() void ScreenPool::save()
{ {
QMap<int, QString>::const_iterator i; QMap<int, QString>::const_iterator i;
@ -214,7 +229,7 @@ void ScreenPool::insertScreenMapping(const QString &connector)
int ScreenPool::id(const QString &connector) const int ScreenPool::id(const QString &connector) const
{ {
QString screenId = m_screensTable.idForName(connector); QString screenId = m_screensTable.idForName(connector);
return screenId.isEmpty() ? -1 : screenId.toInt(); return screenId.isEmpty() ? NOSCREENID : screenId.toInt();
} }
QString ScreenPool::connector(int id) const QString ScreenPool::connector(int id) const

View File

@ -30,6 +30,7 @@ class ScreenPool : public QObject, public QAbstractNativeEventFilter
public: public:
static const int FIRSTSCREENID = 10; static const int FIRSTSCREENID = 10;
static const int NOSCREENID = -1;
ScreenPool(KSharedConfig::Ptr config, QObject *parent = nullptr); ScreenPool(KSharedConfig::Ptr config, QObject *parent = nullptr);
void load(); void load();
@ -38,6 +39,7 @@ public:
bool hasScreenId(int screenId) const; bool hasScreenId(int screenId) const;
bool isScreenActive(int screenId) const; bool isScreenActive(int screenId) const;
int primaryScreenId() const; int primaryScreenId() const;
QList<int> secondaryScreenIds() const;
void insertScreenMapping(const QString &connector); void insertScreenMapping(const QString &connector);
void reload(QString path); void reload(QString path);

View File

@ -502,7 +502,7 @@ int screenMaxLength(const QStyleOption &option, const int &maxIconSize)
return scr_maxlength; return scr_maxlength;
} }
QRect remainedFromScreenDrawing(const QStyleOption &option, const int &maxIconSize) QRect remainedFromScreenDrawing(const QStyleOption &option, bool drawMultipleScreens, const int &maxIconSize)
{ {
int total_length = screenMaxLength(option, maxIconSize) + MARGIN * 2 + 1; int total_length = screenMaxLength(option, maxIconSize) + MARGIN * 2 + 1;
@ -512,7 +512,7 @@ QRect remainedFromScreenDrawing(const QStyleOption &option, const int &maxIconSi
return optionRemainedRect; return optionRemainedRect;
} }
QRect drawScreen(QPainter *painter, const QStyleOption &option, QRect screenGeometry, const int &maxIconSize, const float brushOpacity) QRect drawScreen(QPainter *painter, const QStyleOption &option, bool drawMultipleScreens, QRect screenGeometry, const int &maxIconSize, const float brushOpacity)
{ {
float scr_ratio = (float)screenGeometry.width() / (float)screenGeometry.height(); float scr_ratio = (float)screenGeometry.width() / (float)screenGeometry.height();
bool isVertical = (scr_ratio < 1.0); bool isVertical = (scr_ratio < 1.0);
@ -565,13 +565,24 @@ QRect drawScreen(QPainter *painter, const QStyleOption &option, QRect screenGeom
painter->setPen(pen); painter->setPen(pen);
painter->drawRect(screenRect); painter->drawRect(screenRect);
//! draw screen base
pen.setWidth(1); pen.setWidth(1);
painter->setPen(pen); painter->setPen(pen);
painter->setRenderHint(QPainter::Antialiasing, false);
//! draw multiple
if (drawMultipleScreens) {
int multiplemargin = 3;
int curx = screenRect.x()-multiplemargin;
painter->drawLine(screenRect.x() - multiplemargin, screenRect.y() - multiplemargin,
screenRect.x() - multiplemargin, screenRect.y() - multiplemargin + screenRect.height());
painter->drawLine(screenRect.x() - multiplemargin, screenRect.y() - multiplemargin,
screenRect.x() - multiplemargin + screenRect.width(), screenRect.y() - multiplemargin);
}
int basex = screenRect.x() + (screenRect.width()/2) - 4; int basex = screenRect.x() + (screenRect.width()/2) - 4;
int basey = screenRect.y() + screenRect.height() + 2; int basey = screenRect.y() + screenRect.height() + 2;
painter->setRenderHint(QPainter::Antialiasing, false);
painter->drawLine(basex , basey, basex + 8, basey); painter->drawLine(basex , basey, basex + 8, basey);
// debug screen maximum available rect // debug screen maximum available rect

View File

@ -60,8 +60,8 @@ QRect remainedFromCheckBox(const QStyleOptionButton &option, Qt::AlignmentFlag a
void drawCheckBox(QPainter *painter, const QStyleOptionButton &option, Qt::AlignmentFlag alignment = Qt::AlignLeft, const QWidget *widget = nullptr); void drawCheckBox(QPainter *painter, const QStyleOptionButton &option, Qt::AlignmentFlag alignment = Qt::AlignLeft, const QWidget *widget = nullptr);
//! screen icon //! screen icon
QRect remainedFromScreenDrawing(const QStyleOption &option, const int &maxIconSize = -1); QRect remainedFromScreenDrawing(const QStyleOption &option, bool drawMultipleScreens, const int &maxIconSize = -1);
QRect drawScreen(QPainter *painter, const QStyleOption &option, QRect screenGeometry, const int &maxIconSize = -1, const float brushOpacity = 1.0); // returns screen available rect QRect drawScreen(QPainter *painter, const QStyleOption &option, bool drawMultipleScreens, QRect screenGeometry, const int &maxIconSize = -1, const float brushOpacity = 1.0); // returns screen available rect
int screenMaxLength(const QStyleOption &option, const int &maxIconSize = -1); int screenMaxLength(const QStyleOption &option, const int &maxIconSize = -1);

View File

@ -111,8 +111,8 @@ void CheckBox::paint(QPainter *painter, const QStyleOptionViewItem &option, cons
//! screen //! screen
int maxiconsize = -1; //disabled int maxiconsize = -1; //disabled
remainedrect = Latte::remainedFromScreenDrawing(adjustedOption, maxiconsize); remainedrect = Latte::remainedFromScreenDrawing(adjustedOption, false, maxiconsize);
Latte::drawScreen(painter, adjustedOption, screen.geometry, maxiconsize); Latte::drawScreen(painter, adjustedOption, false, screen.geometry, maxiconsize);
adjustedOption.rect = remainedrect; adjustedOption.rect = remainedrect;
//! screen id //! screen id

View File

@ -236,7 +236,7 @@ const Latte::Data::ViewsTable Layouts::selectedLayoutViews()
central = new CentralLayout(this, selectedCurrentData.id); central = new CentralLayout(this, selectedCurrentData.id);
} }
selectedCurrentData.views = central->viewsTable(); selectedCurrentData.views = central->viewsTable().onlyOriginals();
selectedCurrentData.views.isInitialized = true; selectedCurrentData.views.isInitialized = true;
if (!islayoutactive) { if (!islayoutactive) {

View File

@ -21,6 +21,7 @@
#include "../../layout/centrallayout.h" #include "../../layout/centrallayout.h"
#include "../../layouts/importer.h" #include "../../layouts/importer.h"
#include "../../layouts/manager.h" #include "../../layouts/manager.h"
#include "../../layouts/storage.h"
#include "../../templates/templatesmanager.h" #include "../../templates/templatesmanager.h"
#include "../../tools/commontools.h" #include "../../tools/commontools.h"
@ -658,6 +659,9 @@ void TabLayouts::exportLayoutForBackup()
QFile(file).setPermissions(QFileDevice::ReadUser | QFileDevice::WriteUser | QFileDevice::ReadGroup | QFileDevice::ReadOther); QFile(file).setPermissions(QFileDevice::ReadUser | QFileDevice::WriteUser | QFileDevice::ReadGroup | QFileDevice::ReadOther);
} }
// cleanup clones from exported file
Latte::Layouts::Storage::self()->removeAllClonedViews(file);
CentralLayout layoutS(this, file); CentralLayout layoutS(this, file);
layoutS.setActivities(QStringList()); layoutS.setActivities(QStringList());
layoutS.clearLastUsedActivity(); layoutS.clearLastUsedActivity();

View File

@ -89,8 +89,8 @@ void CustomMenuItemWidget::paintEvent(QPaintEvent* e)
if (!m_screen.id.isEmpty()) { if (!m_screen.id.isEmpty()) {
int maxiconsize = 26; int maxiconsize = 26;
remained = Latte::remainedFromScreenDrawing(opt, maxiconsize); remained = Latte::remainedFromScreenDrawing(opt, m_screen.isScreensGroup(), maxiconsize);
QRect availableScreenRect = Latte::drawScreen(&painter, opt, m_screen.geometry, maxiconsize); QRect availableScreenRect = Latte::drawScreen(&painter, opt, m_screen.isScreensGroup(), m_screen.geometry, maxiconsize);
if (!m_view.id.isEmpty()) { if (!m_view.id.isEmpty()) {
Latte::drawView(&painter, opt, m_view, availableScreenRect); Latte::drawView(&painter, opt, m_view, availableScreenRect);

View File

@ -27,7 +27,7 @@ NameDelegate::NameDelegate(QObject *parent)
void NameDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const void NameDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{ {
editor->setGeometry(Latte::remainedFromScreenDrawing(option)); editor->setGeometry(Latte::remainedFromScreenDrawing(option, false));
} }
void NameDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const void NameDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
@ -90,8 +90,8 @@ void NameDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
// draw screen icon // draw screen icon
int maxiconsize = -1; //disabled int maxiconsize = -1; //disabled
remainedrect = Latte::remainedFromScreenDrawing(myOptions, maxiconsize); remainedrect = Latte::remainedFromScreenDrawing(myOptions, screen.isScreensGroup(), maxiconsize);
QRect availableScreenRect = Latte::drawScreen(painter, myOptions, screen.geometry, maxiconsize, textopacity); QRect availableScreenRect = Latte::drawScreen(painter, myOptions, screen.isScreensGroup(), screen.geometry, maxiconsize, textopacity);
Latte::drawView(painter, myOptions, view, availableScreenRect, textopacity); Latte::drawView(painter, myOptions, view, availableScreenRect, textopacity);
myOptions.rect = remainedrect; myOptions.rect = remainedrect;

View File

@ -424,16 +424,26 @@ Latte::Data::Screen Views::screenData(const QString &viewId) const
return Latte::Data::Screen(); return Latte::Data::Screen();
} }
QString primaryid = QString::number(m_corona->screenPool()->primaryScreenId()); // QString primaryid = QString::number(m_corona->screenPool()->primaryScreenId());
QString explicitid = QString::number(m_viewsTable[row].screen); QString explicitid = QString::number(m_viewsTable[row].screen);
if (m_viewsTable[row].onPrimary && s_screens.containsId(primaryid)) { Data::Screen scrData = s_screens[0]; //default
return s_screens[primaryid];
if (m_viewsTable[row].onPrimary || (m_viewsTable[row].screensGroup == Latte::Types::AllScreensGroup)) {
scrData = s_screens[0]; //primary, allscreens
} else if (m_viewsTable[row].screensGroup == Latte::Types::AllSecondaryScreensGroup) {
scrData = s_screens[2]; //allsecondaryscreens
} else if (!m_viewsTable[row].onPrimary && s_screens.containsId(explicitid)) { } else if (!m_viewsTable[row].onPrimary && s_screens.containsId(explicitid)) {
return s_screens[explicitid]; scrData = s_screens[explicitid]; //explicit
} }
return Latte::Data::Screen(); if (m_viewsTable[row].screensGroup == Latte::Types::AllScreensGroup) {
scrData.id = QString::number(Data::Screen::ONALLSCREENSID);
} else if (m_viewsTable[row].screensGroup == Latte::Types::AllSecondaryScreensGroup) {
scrData.id = QString::number(Data::Screen::ONALLSECONDARYSCREENSID);
}
return scrData;
} }
Latte::Data::ViewsTable Views::alteredViews() const Latte::Data::ViewsTable Views::alteredViews() const
@ -486,14 +496,21 @@ void Views::clearErrorsAndWarnings()
void Views::populateScreens() void Views::populateScreens()
{ {
s_screens.clear(); s_screens.clear();
Data::Screen primary(QString::number(Data::Screen::ONPRIMARYID), Data::Screen primary(QString::number(Data::Screen::ONPRIMARYID), i18n(" - On Primary Screen - "));
i18nc("primary screen", " - Follow Primary Screen - ")); Data::Screen allscreens(QString::number(Data::Screen::ONALLSCREENSID), i18n(" - On All Screens - "));
Data::Screen allsecscreens(QString::number(Data::Screen::ONALLSECONDARYSCREENSID), i18n(" - On All Secondary Screens - "));
primary.isActive = true;
allscreens.isActive = true;
allsecscreens.isActive = (m_corona->screenPool()->secondaryScreenIds().count() > 0);
primary.isActive = true;
s_screens << primary; s_screens << primary;
s_screens << allscreens;
s_screens << allsecscreens;
int defcount = s_screens.rowCount();
s_screens << m_corona->screenPool()->screensTable(); s_screens << m_corona->screenPool()->screensTable();
for (int i=1; i<s_screens.rowCount(); ++i) { for (int i=defcount; i<s_screens.rowCount(); ++i) {
s_screens[i].isActive = m_corona->screenPool()->isScreenActive(s_screens[i].id.toInt()); s_screens[i].isActive = m_corona->screenPool()->isScreenActive(s_screens[i].id.toInt());
} }
} }
@ -662,22 +679,30 @@ bool Views::setData(const QModelIndex &index, const QVariant &value, int role)
if (role == Qt::UserRole) { if (role == Qt::UserRole) {
int screen = value.toString().toInt(); int screen = value.toString().toInt();
bool onprimary = (screen == Latte::Data::Screen::ONPRIMARYID); bool onprimary = (screen == Latte::Data::Screen::ONPRIMARYID);
bool onallscreens = (screen == Latte::Data::Screen::ONALLSCREENSID);
if ((m_viewsTable[row].onPrimary == onprimary) && (m_viewsTable[row].screen == screen)) { bool onallsecscreens = (screen == Latte::Data::Screen::ONALLSECONDARYSCREENSID);
return false;
}
if (onprimary) { if (onprimary) {
m_viewsTable[row].onPrimary = true; m_viewsTable[row].onPrimary = true;
m_viewsTable[row].screensGroup = Latte::Types::SingleScreenGroup;
} else if (onallscreens) {
m_viewsTable[row].onPrimary = true;
m_viewsTable[row].screensGroup = Latte::Types::AllScreensGroup;
} else if (onallsecscreens) {
m_viewsTable[row].onPrimary = false;
m_viewsTable[row].screensGroup = Latte::Types::AllSecondaryScreensGroup;
} else {
m_viewsTable[row].onPrimary = false;
m_viewsTable[row].screensGroup = Latte::Types::SingleScreenGroup;
m_viewsTable[row].screen = screen;
}
if (onprimary || onallscreens || onallsecscreens) {
if (o_viewsTable.containsId(m_viewsTable[row].id)) { if (o_viewsTable.containsId(m_viewsTable[row].id)) {
//! we need to update screen also in order to not show that there are changes even though //! we need to update screen also in order to not show that there are changes even though
//! they are not any //! they are not any
m_viewsTable[row].screen = o_viewsTable[m_viewsTable[row].id].screen; m_viewsTable[row].screen = o_viewsTable[m_viewsTable[row].id].screen;
} }
} else {
m_viewsTable[row].onPrimary = false;
m_viewsTable[row].screen = screen;
} }
emit dataChanged(this->index(row, NAMECOLUMN), this->index(row, ALIGNMENTCOLUMN), roles); emit dataChanged(this->index(row, NAMECOLUMN), this->index(row, ALIGNMENTCOLUMN), roles);
@ -759,7 +784,7 @@ QVariant Views::data(const QModelIndex &index, int role) const
if (!m_viewsTable[row].onPrimary && !currentScreens.containsId(QString::number(m_viewsTable[row].screen))) { if (!m_viewsTable[row].onPrimary && !currentScreens.containsId(QString::number(m_viewsTable[row].screen))) {
Data::Screen explicitScr(QString::number(m_viewsTable[row].screen), Data::Screen explicitScr(QString::number(m_viewsTable[row].screen),
i18nc("unknown screen", "Unknown : [%1]", explicitScr.id)); i18nc("unknown screen", "Unknown: [%1]", explicitScr.id));
currentScreens.insertBasedOnId(explicitScr); currentScreens.insertBasedOnId(explicitScr);
} }
@ -838,18 +863,30 @@ QVariant Views::data(const QModelIndex &index, int role) const
break; break;
case SCREENCOLUMN: case SCREENCOLUMN:
if (role == Qt::DisplayRole){ if (role == Qt::DisplayRole){
if (m_viewsTable[row].onPrimary) { if (m_viewsTable[row].screensGroup == Latte::Types::SingleScreenGroup && m_viewsTable[row].onPrimary) {
return i18nc("primary screen", "Primary"); return i18nc("primary screen", "Primary");
} else if (m_viewsTable[row].screensGroup == Latte::Types::AllScreensGroup) {
return i18n("All Screens");
} else if (m_viewsTable[row].screensGroup == Latte::Types::AllSecondaryScreensGroup) {
return i18n("Secondary Screens");
} else { } else {
QString scrId = QString::number(m_viewsTable[row].screen); QString scrId = QString::number(m_viewsTable[row].screen);
if (s_screens.containsId(scrId)) { if (s_screens.containsId(scrId)) {
return s_screens[scrId].name; return s_screens[scrId].name;
} else { } else {
return i18nc("unknown screen", "Unknown : [%1]", scrId); return i18nc("unknown screen", "Unknown: [%1]", scrId);
} }
} }
} else if (role == Qt::UserRole) { } else if (role == Qt::UserRole) {
return m_viewsTable[row].onPrimary ? QString::number(Data::Screen::ONPRIMARYID) : QString::number(m_viewsTable[row].screen); if (m_viewsTable[row].screensGroup == Latte::Types::SingleScreenGroup && m_viewsTable[row].onPrimary) {
return QString::number(Data::Screen::ONPRIMARYID);
} else if (m_viewsTable[row].screensGroup == Latte::Types::AllScreensGroup) {
return QString::number(Data::Screen::ONALLSCREENSID);
} else if (m_viewsTable[row].screensGroup == Latte::Types::AllSecondaryScreensGroup) {
return QString::number(Data::Screen::ONALLSECONDARYSCREENSID);
} else {
return QString::number(m_viewsTable[row].screen);
}
} else if (role == ISCHANGEDROLE) { } else if (role == ISCHANGEDROLE) {
return (isNewView return (isNewView
|| (m_viewsTable[row].onPrimary != o_viewsTable[origviewid].onPrimary) || (m_viewsTable[row].onPrimary != o_viewsTable[origviewid].onPrimary)

View File

@ -487,7 +487,7 @@ bool GlobalShortcuts::viewsToHideAreValid()
void GlobalShortcuts::showSettings() void GlobalShortcuts::showSettings()
{ {
QList<Latte::View *> sortedViews = m_corona->layoutsManager()->synchronizer()->sortedCurrentViews(); QList<Latte::View *> sortedViews = m_corona->layoutsManager()->synchronizer()->sortedCurrentOriginalViews();
//! find which is the next view to show its settings //! find which is the next view to show its settings
if (sortedViews.count() > 0) { if (sortedViews.count() > 0) {

View File

@ -1,5 +1,6 @@
set(lattedock-app_SRCS set(lattedock-app_SRCS
${lattedock-app_SRCS} ${lattedock-app_SRCS}
${CMAKE_CURRENT_SOURCE_DIR}/clonedview.cpp
${CMAKE_CURRENT_SOURCE_DIR}/containmentinterface.cpp ${CMAKE_CURRENT_SOURCE_DIR}/containmentinterface.cpp
${CMAKE_CURRENT_SOURCE_DIR}/contextmenu.cpp ${CMAKE_CURRENT_SOURCE_DIR}/contextmenu.cpp
${CMAKE_CURRENT_SOURCE_DIR}/effects.cpp ${CMAKE_CURRENT_SOURCE_DIR}/effects.cpp
@ -9,6 +10,7 @@ set(lattedock-app_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/positioner.cpp ${CMAKE_CURRENT_SOURCE_DIR}/positioner.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tasksmodel.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tasksmodel.cpp
${CMAKE_CURRENT_SOURCE_DIR}/view.cpp ${CMAKE_CURRENT_SOURCE_DIR}/view.cpp
${CMAKE_CURRENT_SOURCE_DIR}/originalview.cpp
${CMAKE_CURRENT_SOURCE_DIR}/visibilitymanager.cpp ${CMAKE_CURRENT_SOURCE_DIR}/visibilitymanager.cpp
PARENT_SCOPE PARENT_SCOPE
) )

355
app/view/clonedview.cpp Normal file
View File

@ -0,0 +1,355 @@
/*
SPDX-FileCopyrightText: 2021 Michail Vourlakos <mvourlakos@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "clonedview.h"
#include "containmentinterface.h"
#include "visibilitymanager.h"
#include "../data/viewdata.h"
#include "../layouts/storage.h"
namespace Latte {
QStringList ClonedView::CONTAINMENTMANUALSYNCEDPROPERTIES = QStringList()
<< QString("appletOrder")
<< QString("lockedZoomApplets")
<< QString("userBlocksColorizingApplets");
ClonedView::ClonedView(Plasma::Corona *corona, Latte::OriginalView *originalView, QScreen *targetScreen, bool byPassX11WM)
: View(corona, targetScreen, byPassX11WM),
m_originalView(originalView)
{
m_originalView->addClone(this);
initSync();
}
ClonedView::~ClonedView()
{
}
void ClonedView::initSync()
{
connect(m_originalView, &View::containmentChanged, this, &View::groupIdChanged);
//! Update Visibility From Original
connect(m_originalView->visibility(), &Latte::ViewPart::VisibilityManager::modeChanged, this, [&]() {
visibility()->setMode(m_originalView->visibility()->mode());
});
connect(m_originalView->visibility(), &Latte::ViewPart::VisibilityManager::raiseOnDesktopChanged, this, [&]() {
visibility()->setRaiseOnDesktop(m_originalView->visibility()->raiseOnDesktop());
});
connect(m_originalView->visibility(), &Latte::ViewPart::VisibilityManager::raiseOnActivityChanged, this, [&]() {
visibility()->setRaiseOnActivity(m_originalView->visibility()->raiseOnActivity());
});
connect(m_originalView->visibility(), &Latte::ViewPart::VisibilityManager::enableKWinEdgesChanged, this, [&]() {
visibility()->setEnableKWinEdges(m_originalView->visibility()->enableKWinEdges());
});
connect(m_originalView->visibility(), &Latte::ViewPart::VisibilityManager::timerShowChanged, this, [&]() {
visibility()->setTimerShow(m_originalView->visibility()->timerShow());
});
connect(m_originalView->visibility(), &Latte::ViewPart::VisibilityManager::timerHideChanged, this, [&]() {
visibility()->setTimerHide(m_originalView->visibility()->timerHide());
});
//! Update Applets from Clone -> OriginalView
connect(extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletConfigPropertyChanged, this, &ClonedView::updateOriginalAppletConfigProperty);
connect(extendedInterface(), &Latte::ViewPart::ContainmentInterface::initializationCompleted, this, &ClonedView::updateAppletIdsHash);
connect(extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletsOrderChanged, this, &ClonedView::updateAppletIdsHash);
connect(extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletDataCreated, this, &ClonedView::updateAppletIdsHash);
connect(extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletCreated, this, [&](const QString &pluginId) {
m_originalView->addApplet(pluginId, containment()->id());
});
connect(extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletDropped, this, [&](QObject *data, int x, int y) {
m_originalView->addApplet(data, x, y, containment()->id());
});
//! Update Applets and Containment from OrigalView -> Clone
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::containmentConfigPropertyChanged, this, &ClonedView::updateContainmentConfigProperty);
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletConfigPropertyChanged, this, &ClonedView::onOriginalAppletConfigPropertyChanged);
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletInScheduledDestructionChanged, this, &ClonedView::onOriginalAppletInScheduledDestructionChanged);
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletRemoved, this, &ClonedView::onOriginalAppletRemoved);
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletsOrderChanged, this, &ClonedView::onOriginalAppletsOrderChanged);
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletsInLockedZoomChanged, this, &ClonedView::onOriginalAppletsInLockedZoomChanged);
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletsDisabledColoringChanged, this, &ClonedView::onOriginalAppletsDisabledColoringChanged);
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletDataCreated, this, &ClonedView::updateAppletIdsHash);
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletCreated, this->extendedInterface(), [&](const QString &pluginId) {
extendedInterface()->addApplet(pluginId);
});
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletDropped, this->extendedInterface(), [&](QObject *data, int x, int y) {
extendedInterface()->addApplet(data, x, y);
});
//! Indicator
connect(m_originalView, &Latte::View::indicatorChanged, this, &ClonedView::indicatorChanged);
}
bool ClonedView::isSingle() const
{
return false;
}
bool ClonedView::isOriginal() const
{
return false;
}
bool ClonedView::isCloned() const
{
return true;
}
bool ClonedView::isPreferredForShortcuts() const
{
return false;
}
int ClonedView::groupId() const
{
if (!m_originalView->containment()) {
return -1;
}
return m_originalView->containment()->id();
}
Latte::Types::ScreensGroup ClonedView::screensGroup() const
{
return Latte::Types::SingleScreenGroup;
}
ViewPart::Indicator *ClonedView::indicator() const
{
return m_originalView->indicator();
}
bool ClonedView::hasOriginalAppletId(const int &clonedid)
{
if (clonedid < 0) {
return false;
}
QHash<int, int>::const_iterator i = m_currentAppletIds.constBegin();
while (i != m_currentAppletIds.constEnd()) {
if (i.value() == clonedid) {
return true;
}
++i;
}
return false;
}
int ClonedView::originalAppletId(const int &clonedid)
{
if (clonedid < 0) {
return -1;
}
QHash<int, int>::const_iterator i = m_currentAppletIds.constBegin();
while (i != m_currentAppletIds.constEnd()) {
if (i.value() == clonedid) {
return i.key();
}
++i;
}
return -1;
}
bool ClonedView::isTranslatableToClonesOrder(const QList<int> &originalOrder)
{
for(int i=0; i<originalOrder.count(); ++i) {
int oid = originalOrder[i];
if (oid < 0 ) {
continue;
}
if (!m_currentAppletIds.contains(oid)) {
return false;
}
}
return true;
}
Latte::Data::View ClonedView::data() const
{
Latte::Data::View vdata = View::data();
vdata.isClonedFrom = m_originalView->containment()->id();
return vdata;
}
void ClonedView::updateAppletIdsHash()
{
QList<int> originalids = m_originalView->extendedInterface()->appletsOrder();
QList<int> clonedids = extendedInterface()->appletsOrder();
for (int i=0; i<originalids.count(); ++i) {
int oid = originalids[i];
if (oid < 0 || (m_currentAppletIds.contains(oid) && m_currentAppletIds[oid] > 0)) {
continue;
}
int oindex = m_originalView->extendedInterface()->indexOfApplet(oid);
ViewPart::AppletInterfaceData originalapplet = m_originalView->extendedInterface()->appletDataForId(oid);
ViewPart::AppletInterfaceData clonedapplet = extendedInterface()->appletDataAtIndex(oindex);
bool registeredclonedid = (originalAppletId(clonedapplet.id) > 0);
if (originalapplet.id>0 && clonedapplet.id>0 && originalapplet.plugin == clonedapplet.plugin && !registeredclonedid) {
m_currentAppletIds[originalapplet.id] = clonedapplet.id;
}
}
}
QList<int> ClonedView::translateToClonesOrder(const QList<int> &originalIds)
{
QList<int> ids;
for (int i=0; i<originalIds.count(); ++i) {
int originalid = originalIds[i];
if (originalid < 0 ) {
ids << originalid;
continue;
}
if (m_currentAppletIds.contains(originalid)) {
ids << m_currentAppletIds[originalid];
} else {
ids << ERRORAPPLETID; //error
}
}
return ids;
}
void ClonedView::showConfigurationInterface(Plasma::Applet *applet)
{
Plasma::Containment *c = qobject_cast<Plasma::Containment *>(applet);
if (Layouts::Storage::self()->isLatteContainment(c)) {
m_originalView->showSettingsWindow();
} else {
View::showConfigurationInterface(applet);
}
}
void ClonedView::onOriginalAppletRemoved(const int &id)
{
if (!m_currentAppletIds.contains(id)) {
return;
}
extendedInterface()->removeApplet(m_currentAppletIds[id]);
m_currentAppletIds.remove(id);
}
void ClonedView::onOriginalAppletConfigPropertyChanged(const int &id, const QString &key, const QVariant &value)
{
if (!m_currentAppletIds.contains(id)) {
return;
}
extendedInterface()->updateAppletConfigProperty(m_currentAppletIds[id], key, value);
}
void ClonedView::onOriginalAppletInScheduledDestructionChanged(const int &id, const bool &enabled)
{
if (!m_currentAppletIds.contains(id)) {
return;
}
extendedInterface()->setAppletInScheduledDestruction(m_currentAppletIds[id], enabled);
}
void ClonedView::updateContainmentConfigProperty(const QString &key, const QVariant &value)
{
if (!CONTAINMENTMANUALSYNCEDPROPERTIES.contains(key)) {
extendedInterface()->updateContainmentConfigProperty(key, value);
} else {
//qDebug() << "org.kde.sync :: containment config value syncing blocked :: " << key;
}
}
void ClonedView::updateOriginalAppletConfigProperty(const int &clonedid, const QString &key, const QVariant &value)
{
if (!hasOriginalAppletId(clonedid)) {
return;
}
m_originalView->extendedInterface()->updateAppletConfigProperty(originalAppletId(clonedid), key, value);
}
void ClonedView::onOriginalAppletsOrderChanged()
{
updateAppletIdsHash();
QList<int> originalorder = m_originalView->extendedInterface()->appletsOrder();
if (originalorder.count() != extendedInterface()->appletsOrder().count()) {
//probably an applet was removed or added and clone has not been updated yet
return;
}
if (!isTranslatableToClonesOrder(originalorder)) {
qDebug() << "org.kde.sync ::: original applets order changed but unfortunately original order can not be translated to cloned ids...";
return;
}
QList<int> newclonesorder = translateToClonesOrder(originalorder);
if (newclonesorder.contains(ERRORAPPLETID)) {
qDebug() << "org.kde.sync ::: original applets order changed but unfortunately original and clones order map can not be generated...";
return;
}
extendedInterface()->setAppletsOrder(newclonesorder);
}
void ClonedView::onOriginalAppletsInLockedZoomChanged(const QList<int> &originalapplets)
{
if (!isTranslatableToClonesOrder(originalapplets)) {
qDebug() << "org.kde.sync ::: original applets order changed but unfortunately original order can not be translated to cloned ids...";
return;
}
QList<int> newclonesorder = translateToClonesOrder(originalapplets);
if (newclonesorder.contains(ERRORAPPLETID)) {
qDebug() << "org.kde.sync ::: original applets order changed but unfortunately original and clones order map can not be generated...";
return;
}
extendedInterface()->setAppletsInLockedZoom(newclonesorder);
}
void ClonedView::onOriginalAppletsDisabledColoringChanged(const QList<int> &originalapplets)
{
if (!isTranslatableToClonesOrder(originalapplets)) {
qDebug() << "org.kde.sync ::: original applets order changed but unfortunately original order can not be translated to cloned ids...";
return;
}
QList<int> newclonesorder = translateToClonesOrder(originalapplets);
if (newclonesorder.contains(ERRORAPPLETID)) {
qDebug() << "org.kde.sync ::: original applets order changed but unfortunately original and clones order map can not be generated...";
return;
}
extendedInterface()->setAppletsDisabledColoring(newclonesorder);
}
}

72
app/view/clonedview.h Normal file
View File

@ -0,0 +1,72 @@
/*
SPDX-FileCopyrightText: 2021 Michail Vourlakos <mvourlakos@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef CLONEDVIEW_H
#define CLONEDVIEW_H
// local
#include <coretypes.h>
#include "originalview.h"
#include "indicator/indicator.h"
#include "view.h"
namespace Latte {
class ClonedView : public View
{
Q_OBJECT
public:
static const int ERRORAPPLETID = -999;
ClonedView(Plasma::Corona *corona, Latte::OriginalView *originalView, QScreen *targetScreen = nullptr, bool byPassX11WM = false);
~ClonedView();
bool isOriginal() const override;
bool isCloned() const override;
bool isSingle() const override;
bool isPreferredForShortcuts() const override;
int groupId() const override;
Latte::Types::ScreensGroup screensGroup() const override;
ViewPart::Indicator *indicator() const override;
Latte::Data::View data() const override;
protected:
void showConfigurationInterface(Plasma::Applet *applet) override;
private slots:
void initSync();
void onOriginalAppletConfigPropertyChanged(const int &id, const QString &key, const QVariant &value);
void onOriginalAppletInScheduledDestructionChanged(const int &id, const bool &enabled);
void onOriginalAppletRemoved(const int &id);
void onOriginalAppletsOrderChanged();
void onOriginalAppletsInLockedZoomChanged(const QList<int> &originalapplets);
void onOriginalAppletsDisabledColoringChanged(const QList<int> &originalapplets);
void updateContainmentConfigProperty(const QString &key, const QVariant &value);
void updateOriginalAppletConfigProperty(const int &clonedid, const QString &key, const QVariant &value);
void updateAppletIdsHash();
private:
bool isTranslatableToClonesOrder(const QList<int> &originalOrder);
bool hasOriginalAppletId(const int &clonedid);
int originalAppletId(const int &clonedid);
QList<int> translateToClonesOrder(const QList<int> &originalIds);
private:
static QStringList CONTAINMENTMANUALSYNCEDPROPERTIES;
QPointer<Latte::OriginalView> m_originalView;
QHash<int, int> m_currentAppletIds;
};
}
#endif

View File

@ -9,11 +9,13 @@
#include "view.h" #include "view.h"
#include "../lattecorona.h" #include "../lattecorona.h"
#include "../layout/genericlayout.h" #include "../layout/genericlayout.h"
#include "../layouts/importer.h"
#include "../layouts/storage.h" #include "../layouts/storage.h"
#include "../settings/universalsettings.h" #include "../settings/universalsettings.h"
// Qt // Qt
#include <QDebug> #include <QDebug>
#include <QDir>
#include <QLatin1String> #include <QLatin1String>
// Plasma // Plasma
@ -25,6 +27,7 @@
#include <KDesktopFile> #include <KDesktopFile>
#include <KLocalizedString> #include <KLocalizedString>
#include <KPluginMetaData> #include <KPluginMetaData>
#include <KDeclarative/ConfigPropertyMap>
namespace Latte { namespace Latte {
namespace ViewPart { namespace ViewPart {
@ -41,13 +44,16 @@ ContainmentInterface::ContainmentInterface(Latte::View *parent)
m_appletsExpandedConnectionsTimer.setInterval(2000); m_appletsExpandedConnectionsTimer.setInterval(2000);
m_appletsExpandedConnectionsTimer.setSingleShot(true); m_appletsExpandedConnectionsTimer.setSingleShot(true);
m_appletDelayedConfigurationTimer.setInterval(1000);
m_appletDelayedConfigurationTimer.setSingleShot(true);
connect(&m_appletDelayedConfigurationTimer, &QTimer::timeout, this, &ContainmentInterface::updateAppletDelayedConfiguration);
connect(&m_appletsExpandedConnectionsTimer, &QTimer::timeout, this, &ContainmentInterface::updateAppletsTracking); connect(&m_appletsExpandedConnectionsTimer, &QTimer::timeout, this, &ContainmentInterface::updateAppletsTracking);
connect(m_view, &View::containmentChanged connect(m_view, &View::containmentChanged
, this, [&]() { , this, [&]() {
if (m_view->containment()) { if (m_view->containment()) {
connect(m_view->containment(), &Plasma::Containment::appletAdded, this, &ContainmentInterface::onAppletAdded); connect(m_view->containment(), &Plasma::Containment::appletAdded, this, &ContainmentInterface::onAppletAdded);
m_appletsExpandedConnectionsTimer.start(); m_appletsExpandedConnectionsTimer.start();
} }
}); });
@ -423,7 +429,7 @@ bool ContainmentInterface::appletIsExpandable(const int id) const
for (const auto applet : m_view->containment()->applets()) { for (const auto applet : m_view->containment()->applets()) {
if (applet && applet->id() == (uint)id) { if (applet && applet->id() == (uint)id) {
if (Layouts::Storage::self()->isSubContainment(m_view->layout(), applet)) { if (Layouts::Storage::self()->isSubContainment(m_view->corona(), applet)) {
return true; return true;
} }
@ -446,7 +452,7 @@ bool ContainmentInterface::appletIsExpandable(PlasmaQuick::AppletQuickItem *appl
return ((appletQuickItem->fullRepresentation() != nullptr return ((appletQuickItem->fullRepresentation() != nullptr
&& appletQuickItem->preferredRepresentation() != appletQuickItem->fullRepresentation()) && appletQuickItem->preferredRepresentation() != appletQuickItem->fullRepresentation())
|| Latte::Layouts::Storage::self()->isSubContainment(m_view->layout(), appletQuickItem->applet())); || Latte::Layouts::Storage::self()->isSubContainment(m_view->corona(), appletQuickItem->applet()));
} }
bool ContainmentInterface::appletIsActivationTogglesExpanded(const int id) const bool ContainmentInterface::appletIsActivationTogglesExpanded(const int id) const
@ -457,7 +463,7 @@ bool ContainmentInterface::appletIsActivationTogglesExpanded(const int id) const
for (const auto applet : m_view->containment()->applets()) { for (const auto applet : m_view->containment()->applets()) {
if (applet && applet->id() == (uint)id) { if (applet && applet->id() == (uint)id) {
if (Layouts::Storage::self()->isSubContainment(m_view->layout(), applet)) { if (Layouts::Storage::self()->isSubContainment(m_view->corona(), applet)) {
return true; return true;
} }
@ -487,6 +493,148 @@ bool ContainmentInterface::hasPlasmaTasks() const
return (m_plasmaTasksModel->count() > 0); return (m_plasmaTasksModel->count() > 0);
} }
int ContainmentInterface::indexOfApplet(const int &id)
{
if (m_appletOrder.contains(id)) {
return m_appletOrder.indexOf(id);
} else if (m_appletData.contains(id)) {
return m_appletData[id].lastValidIndex;
}
return -1;
}
ViewPart::AppletInterfaceData ContainmentInterface::appletDataAtIndex(const int &index)
{
ViewPart::AppletInterfaceData data;
if (index<0 || (index > (m_appletOrder.count()-1))) {
return data;
}
return m_appletData[m_appletOrder[index]];
}
ViewPart::AppletInterfaceData ContainmentInterface::appletDataForId(const int &id)
{
ViewPart::AppletInterfaceData data;
if (!m_appletData.contains(id)) {
return data;
}
return m_appletData[id];
}
QObject *ContainmentInterface::plasmoid() const
{
return m_plasmoid;
}
void ContainmentInterface::setPlasmoid(QObject *plasmoid)
{
if (m_plasmoid == plasmoid) {
return;
}
m_plasmoid = plasmoid;
if (m_plasmoid) {
m_configuration = qobject_cast<KDeclarative::ConfigPropertyMap *>(m_plasmoid->property("configuration").value<QObject *>());
if (m_configuration) {
connect(m_configuration, &QQmlPropertyMap::valueChanged, this, &ContainmentInterface::containmentConfigPropertyChanged);
}
}
emit plasmoidChanged();
}
QObject *ContainmentInterface::layoutManager() const
{
return m_layoutManager;
}
void ContainmentInterface::setLayoutManager(QObject *manager)
{
if (m_layoutManager == manager) {
return;
}
m_layoutManager = manager;
// applets order
int metaorderindex = m_layoutManager->metaObject()->indexOfProperty("order");
if (metaorderindex >= 0) {
QMetaProperty metaorder = m_layoutManager->metaObject()->property(metaorderindex);
if (metaorder.hasNotifySignal()) {
QMetaMethod metaorderchanged = metaorder.notifySignal();
QMetaMethod metaupdateappletorder = this->metaObject()->method(this->metaObject()->indexOfSlot("updateAppletsOrder()"));
connect(m_layoutManager, metaorderchanged, this, metaupdateappletorder);
updateAppletsOrder();
}
}
// applets in locked zoom
metaorderindex = m_layoutManager->metaObject()->indexOfProperty("lockedZoomApplets");
if (metaorderindex >= 0) {
QMetaProperty metaorder = m_layoutManager->metaObject()->property(metaorderindex);
if (metaorder.hasNotifySignal()) {
QMetaMethod metaorderchanged = metaorder.notifySignal();
QMetaMethod metaupdateapplets = this->metaObject()->method(this->metaObject()->indexOfSlot("updateAppletsInLockedZoom()"));
connect(m_layoutManager, metaorderchanged, this, metaupdateapplets);
updateAppletsInLockedZoom();
}
}
// applets disabled their autocoloring
metaorderindex = m_layoutManager->metaObject()->indexOfProperty("userBlocksColorizingApplets");
if (metaorderindex >= 0) {
QMetaProperty metaorder = m_layoutManager->metaObject()->property(metaorderindex);
if (metaorder.hasNotifySignal()) {
QMetaMethod metaorderchanged = metaorder.notifySignal();
QMetaMethod metaupdateapplets = this->metaObject()->method(this->metaObject()->indexOfSlot("updateAppletsDisabledColoring()"));
connect(m_layoutManager, metaorderchanged, this, metaupdateapplets);
updateAppletsDisabledColoring();
}
}
emit layoutManagerChanged();
}
void ContainmentInterface::addApplet(const QString &pluginId)
{
if (pluginId.isEmpty()) {
return;
}
QStringList paths = Latte::Layouts::Importer::standardPaths();
QString pluginpath;
for(int i=0; i<paths.count(); ++i) {
QString cpath = paths[i] + "/plasma/plasmoids/" + pluginId;
if (QDir(cpath).exists()) {
pluginpath = cpath;
break;
}
}
if (!pluginpath.isEmpty()) {
m_view->containment()->createApplet(pluginId);
}
}
void ContainmentInterface::addApplet(QObject *metadata, int x, int y)
{
int processmimedataindex = m_plasmoid->metaObject()->indexOfMethod("processMimeData(QObject*,int,int)");
QMetaMethod processmethod = m_plasmoid->metaObject()->method(processmimedataindex);
processmethod.invoke(m_plasmoid,
Q_ARG(QObject *, metadata),
Q_ARG(int, x),
Q_ARG(int, y));
}
void ContainmentInterface::addExpandedApplet(PlasmaQuick::AppletQuickItem * appletQuickItem) void ContainmentInterface::addExpandedApplet(PlasmaQuick::AppletQuickItem * appletQuickItem)
{ {
if (appletQuickItem && m_expandedAppletIds.contains(appletQuickItem) && appletIsExpandable(appletQuickItem)) { if (appletQuickItem && m_expandedAppletIds.contains(appletQuickItem) && appletIsExpandable(appletQuickItem)) {
@ -555,6 +703,68 @@ void ContainmentInterface::onAppletExpandedChanged()
} }
} }
QList<int> ContainmentInterface::appletsOrder() const
{
return m_appletOrder;
}
void ContainmentInterface::updateAppletsOrder()
{
if (!m_layoutManager) {
return;
}
QList<int> neworder = m_layoutManager->property("order").value<QList<int>>();
if (m_appletOrder == neworder) {
return;
}
m_appletOrder = neworder;
//! update applets last recorded index, this is needed for example when an applet is removed
//! to know in which index was located before the removal
for(const auto &id: m_appletOrder) {
if (m_appletData.contains(id)) {
m_appletData[id].lastValidIndex = m_appletOrder.indexOf(id);
}
}
emit appletsOrderChanged();
}
void ContainmentInterface::updateAppletsInLockedZoom()
{
if (!m_layoutManager) {
return;
}
QList<int> appletslockedzoom = m_layoutManager->property("lockedZoomApplets").value<QList<int>>();
if (m_appletsInLockedZoom == appletslockedzoom) {
return;
}
m_appletsInLockedZoom = appletslockedzoom;
emit appletsInLockedZoomChanged(m_appletsInLockedZoom);
}
void ContainmentInterface::updateAppletsDisabledColoring()
{
if (!m_layoutManager) {
return;
}
QList<int> appletsdisabledcoloring = m_layoutManager->property("userBlocksColorizingApplets").value<QList<int>>();
if (m_appletsDisabledColoring == appletsdisabledcoloring) {
return;
}
m_appletsDisabledColoring = appletsdisabledcoloring;
emit appletsDisabledColoringChanged(appletsdisabledcoloring);
}
void ContainmentInterface::onLatteTasksCountChanged() void ContainmentInterface::onLatteTasksCountChanged()
{ {
if ((m_hasLatteTasks && m_latteTasksModel->count()>0) if ((m_hasLatteTasks && m_latteTasksModel->count()>0)
@ -589,7 +799,7 @@ void ContainmentInterface::toggleAppletExpanded(const int id)
} }
for (const auto applet : m_view->containment()->applets()) { for (const auto applet : m_view->containment()->applets()) {
if (applet->id() == (uint)id && !Layouts::Storage::self()->isSubContainment(m_view->layout(), applet)/*block for sub-containments*/) { if (applet->id() == (uint)id && !Layouts::Storage::self()->isSubContainment(m_view->corona(), applet)/*block for sub-containments*/) {
PlasmaQuick::AppletQuickItem *ai = applet->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>(); PlasmaQuick::AppletQuickItem *ai = applet->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
if (ai) { if (ai) {
@ -599,6 +809,78 @@ void ContainmentInterface::toggleAppletExpanded(const int id)
} }
} }
void ContainmentInterface::removeApplet(const int &id)
{
if (!m_appletData.contains(id)) {
return;
}
auto applet = m_appletData[id].applet;
emit applet->appletDeleted(applet); //! this signal should be part of Plasma Frameworks AppletPrivate::destroy() function...
applet->destroy();
}
void ContainmentInterface::setAppletsOrder(const QList<int> &order)
{
QMetaObject::invokeMethod(m_layoutManager,
"requestAppletsOrder",
Qt::DirectConnection,
Q_ARG(QList<int>, order));
}
void ContainmentInterface::setAppletsInLockedZoom(const QList<int> &applets)
{
QMetaObject::invokeMethod(m_layoutManager,
"requestAppletsInLockedZoom",
Qt::DirectConnection,
Q_ARG(QList<int>, applets));
}
void ContainmentInterface::setAppletsDisabledColoring(const QList<int> &applets)
{
QMetaObject::invokeMethod(m_layoutManager,
"requestAppletsDisabledColoring",
Qt::DirectConnection,
Q_ARG(QList<int>, applets));
}
void ContainmentInterface::setAppletInScheduledDestruction(const int &id, const bool &enabled)
{
QMetaObject::invokeMethod(m_layoutManager,
"setAppletInScheduledDestruction",
Qt::DirectConnection,
Q_ARG(int, id),
Q_ARG(bool, enabled));
}
void ContainmentInterface::updateContainmentConfigProperty(const QString &key, const QVariant &value)
{
if (!m_configuration || !m_configuration->keys().contains(key)) {
}
if (m_configuration->keys().contains(key)
&& (*m_configuration)[key] != value) {
m_configuration->insert(key, value);
emit m_configuration->valueChanged(key, value);
}
}
void ContainmentInterface::updateAppletConfigProperty(const int &id, const QString &key, const QVariant &value)
{
if (!m_appletData.contains(id) || !m_appletData[id].configuration || !m_appletData[id].configuration->keys().contains(key)) {
return;
}
if (m_appletData[id].configuration->keys().contains(key)
&& (*m_appletData[id].configuration)[key] != value) {
m_appletData[id].configuration->insert(key, value);
emit m_appletData[id].configuration->valueChanged(key, value);
}
}
void ContainmentInterface::updateAppletsTracking() void ContainmentInterface::updateAppletsTracking()
{ {
if (!m_view->containment()) { if (!m_view->containment()) {
@ -608,6 +890,69 @@ void ContainmentInterface::updateAppletsTracking()
for (const auto applet : m_view->containment()->applets()) { for (const auto applet : m_view->containment()->applets()) {
onAppletAdded(applet); onAppletAdded(applet);
} }
emit initializationCompleted();
}
void ContainmentInterface::updateAppletDelayedConfiguration()
{
for (const auto id : m_appletData.keys()) {
if (!m_appletData[id].configuration) {
m_appletData[id].configuration = appletConfiguration(m_appletData[id].applet);
if (m_appletData[id].configuration) {
qDebug() << "org.kde.sync delayed applet configuration was successful for : " << id;
initAppletConfigurationSignals(id, m_appletData[id].configuration);
}
}
}
}
void ContainmentInterface::initAppletConfigurationSignals(const int &id, KDeclarative::ConfigPropertyMap *configuration)
{
if (!configuration) {
return;
}
connect(configuration, &QQmlPropertyMap::valueChanged,
this, [&, id](const QString &key, const QVariant &value) {
//qDebug() << "org.kde.sync applet property changed : " << currentAppletId << " __ " << m_appletData[currentAppletId].plugin << " __ " << key << " __ " << value;
emit appletConfigPropertyChanged(id, key, value);
});
}
KDeclarative::ConfigPropertyMap *ContainmentInterface::appletConfiguration(const Plasma::Applet *applet)
{
if (!m_view->containment() || !applet) {
return nullptr;
}
PlasmaQuick::AppletQuickItem *ai = applet->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
bool isSubContainment = Layouts::Storage::self()->isSubContainment(m_view->corona(), applet); //we use corona() to make sure that returns true even when it is first created from user
int currentAppletId = applet->id();
KDeclarative::ConfigPropertyMap *configuration{nullptr};
//! set configuration object properly for applets and subcontainments
if (!isSubContainment) {
int metaconfigindex = ai->metaObject()->indexOfProperty("configuration");
if (metaconfigindex >=0 ){
configuration = qobject_cast<KDeclarative::ConfigPropertyMap *>((ai->property("configuration")).value<QObject *>());
}
} else {
Plasma::Containment *subcontainment = Layouts::Storage::self()->subContainmentOf(m_view->corona(), applet);
if (subcontainment) {
PlasmaQuick::AppletQuickItem *subcai = subcontainment->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
if (subcai) {
int metaconfigindex = subcai->metaObject()->indexOfProperty("configuration");
if (metaconfigindex >=0 ){
configuration = qobject_cast<KDeclarative::ConfigPropertyMap *>((subcai->property("configuration")).value<QObject *>());
}
}
}
}
return configuration;
} }
void ContainmentInterface::onAppletAdded(Plasma::Applet *applet) void ContainmentInterface::onAppletAdded(Plasma::Applet *applet)
@ -616,10 +961,15 @@ void ContainmentInterface::onAppletAdded(Plasma::Applet *applet)
return; return;
} }
if (Layouts::Storage::self()->isSubContainment(m_view->layout(), applet)) { PlasmaQuick::AppletQuickItem *ai = applet->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
bool isSubContainment = Layouts::Storage::self()->isSubContainment(m_view->corona(), applet); //we use corona() to make sure that returns true even when it is first created from user
int currentAppletId = applet->id();
//! Track expanded/able applets and Tasks applets
if (isSubContainment) {
//! internal containment case //! internal containment case
Plasma::Containment *subContainment = Layouts::Storage::self()->subContainmentOf(m_view->layout(), applet); Plasma::Containment *subContainment = Layouts::Storage::self()->subContainmentOf(m_view->corona(), applet);
PlasmaQuick::AppletQuickItem *contAi = applet->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>(); PlasmaQuick::AppletQuickItem *contAi = ai;
if (contAi && !m_appletsExpandedConnections.contains(contAi)) { if (contAi && !m_appletsExpandedConnections.contains(contAi)) {
m_appletsExpandedConnections[contAi] = connect(contAi, &PlasmaQuick::AppletQuickItem::expandedChanged, this, &ContainmentInterface::onAppletExpandedChanged); m_appletsExpandedConnections[contAi] = connect(contAi, &PlasmaQuick::AppletQuickItem::expandedChanged, this, &ContainmentInterface::onAppletExpandedChanged);
@ -642,13 +992,7 @@ void ContainmentInterface::onAppletAdded(Plasma::Applet *applet)
}); });
} }
} }
} else { } else if (ai) {
PlasmaQuick::AppletQuickItem *ai = applet->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
if (!ai) {
return;
}
KPluginMetaData meta = applet->kPackage().metadata(); KPluginMetaData meta = applet->kPackage().metadata();
const auto &provides = KPluginMetaData::readStringList(meta.rawData(), QStringLiteral("X-Plasma-Provides")); const auto &provides = KPluginMetaData::readStringList(meta.rawData(), QStringLiteral("X-Plasma-Provides"));
@ -668,6 +1012,56 @@ void ContainmentInterface::onAppletAdded(Plasma::Applet *applet)
} }
} }
//! Track All Applets, for example to support syncing between different docks and panels
if (ai) {
bool initializing{!m_appletData.contains(currentAppletId)};
KPluginMetaData meta = applet->kPackage().metadata();
ViewPart::AppletInterfaceData data;
data.id = currentAppletId;
data.plugin = meta.pluginId();
data.applet = applet;
data.plasmoid = ai;
data.lastValidIndex = m_appletOrder.indexOf(data.id);
//! set configuration object properly for applets and subcontainments
data.configuration = appletConfiguration(applet);
//! track property changes in applets
if (data.configuration) {
initAppletConfigurationSignals(data.id, data.configuration);
} else {
qDebug() << "org.kde.sync Unfortunately configuration syncing for :: " << currentAppletId << " was not established, configuration object was missing!";
m_appletDelayedConfigurationTimer.start();
}
if (initializing) {
//! track applet destroyed flag
connect(applet, &Plasma::Applet::destroyedChanged, this, [&, currentAppletId](bool destroyed) {
emit appletInScheduledDestructionChanged(currentAppletId, destroyed);
});
//! remove on applet destruction
connect(applet, &QObject::destroyed, this, [&, data](){
emit appletRemoved(data.id);
//qDebug() << "org.kde.sync: removing applet ::: " << data.id << " __ " << data.plugin << " remained : " << m_appletData.keys();
m_appletData.remove(data.id);
});
}
m_appletData[data.id] = data;
emit appletDataCreated(data.id);
}
}
QList<int> ContainmentInterface::toIntList(const QVariantList &list)
{
QList<int> converted;
for(const QVariant &item: list) {
converted << item.toInt();
}
return converted;
} }
} }

View File

@ -10,8 +10,8 @@
#include "tasksmodel.h" #include "tasksmodel.h"
// Qt // Qt
#include <QMetaMethod>
#include <QHash> #include <QHash>
#include <QMetaMethod>
#include <QObject> #include <QObject>
#include <QPointer> #include <QPointer>
#include <QQuickItem> #include <QQuickItem>
@ -26,6 +26,10 @@ namespace PlasmaQuick {
class AppletQuickItem; class AppletQuickItem;
} }
namespace KDeclarative {
class ConfigPropertyMap;
}
namespace Latte { namespace Latte {
class Corona; class Corona;
class View; class View;
@ -34,6 +38,16 @@ class View;
namespace Latte { namespace Latte {
namespace ViewPart { namespace ViewPart {
struct AppletInterfaceData
{
int id{-1};
QString plugin;
int lastValidIndex{-1};
Plasma::Applet *applet{nullptr};
PlasmaQuick::AppletQuickItem *plasmoid{nullptr};
KDeclarative::ConfigPropertyMap *configuration{nullptr};
};
class ContainmentInterface: public QObject class ContainmentInterface: public QObject
{ {
Q_OBJECT Q_OBJECT
@ -41,9 +55,14 @@ class ContainmentInterface: public QObject
Q_PROPERTY(bool hasLatteTasks READ hasLatteTasks NOTIFY hasLatteTasksChanged) Q_PROPERTY(bool hasLatteTasks READ hasLatteTasks NOTIFY hasLatteTasksChanged)
Q_PROPERTY(bool hasPlasmaTasks READ hasPlasmaTasks NOTIFY hasPlasmaTasksChanged) Q_PROPERTY(bool hasPlasmaTasks READ hasPlasmaTasks NOTIFY hasPlasmaTasksChanged)
Q_PROPERTY(QObject *plasmoid READ plasmoid() WRITE setPlasmoid NOTIFY plasmoidChanged)
Q_PROPERTY(QAbstractListModel *latteTasksModel READ latteTasksModel() NOTIFY latteTasksModelChanged) Q_PROPERTY(QAbstractListModel *latteTasksModel READ latteTasksModel() NOTIFY latteTasksModelChanged)
Q_PROPERTY(QAbstractListModel *plasmaTasksModel READ plasmaTasksModel() NOTIFY plasmaTasksModelChanged) Q_PROPERTY(QAbstractListModel *plasmaTasksModel READ plasmaTasksModel() NOTIFY plasmaTasksModelChanged)
//! specified from containment qml side
Q_PROPERTY(QObject* layoutManager READ layoutManager WRITE setLayoutManager NOTIFY layoutManagerChanged)
public: public:
ContainmentInterface(Latte::View *parent); ContainmentInterface(Latte::View *parent);
virtual ~ContainmentInterface(); virtual ~ContainmentInterface();
@ -73,6 +92,17 @@ public:
int applicationLauncherId() const; int applicationLauncherId() const;
int appletIdForVisualIndex(const int index); int appletIdForVisualIndex(const int index);
int indexOfApplet(const int &id);
QList<int> appletsOrder() const;
ViewPart::AppletInterfaceData appletDataAtIndex(const int &index);
ViewPart::AppletInterfaceData appletDataForId(const int &id);
QObject *plasmoid() const;
void setPlasmoid(QObject *plasmoid);
QObject *layoutManager() const;
void setLayoutManager(QObject *manager);
QAbstractListModel *latteTasksModel() const; QAbstractListModel *latteTasksModel() const;
QAbstractListModel *plasmaTasksModel() const; QAbstractListModel *plasmaTasksModel() const;
@ -86,13 +116,39 @@ public slots:
Q_INVOKABLE bool isApplication(const QUrl &url) const; Q_INVOKABLE bool isApplication(const QUrl &url) const;
void addApplet(const QString &pluginId);
void addApplet(QObject *metadata, int x, int y);
void removeApplet(const int &id);
void setAppletsOrder(const QList<int> &order);
void setAppletsInLockedZoom(const QList<int> &applets);
void setAppletsDisabledColoring(const QList<int> &applets);
void setAppletInScheduledDestruction(const int &id, const bool &enabled);
void updateContainmentConfigProperty(const QString &key, const QVariant &value);
void updateAppletConfigProperty(const int &id, const QString &key, const QVariant &value);
signals: signals:
void expandedAppletStateChanged(); void expandedAppletStateChanged();
void hasExpandedAppletChanged(); void hasExpandedAppletChanged();
void hasLatteTasksChanged(); void hasLatteTasksChanged();
void hasPlasmaTasksChanged(); void hasPlasmaTasksChanged();
void initializationCompleted();
void latteTasksModelChanged(); void latteTasksModelChanged();
void layoutManagerChanged();
void plasmaTasksModelChanged(); void plasmaTasksModelChanged();
void plasmoidChanged();
//! syncing signals
void appletRemoved(const int &id);
void appletConfigPropertyChanged(const int &id, const QString &key, const QVariant &value);
void appletCreated(const QString &pluginId);
void appletDataCreated(const int &id);
void appletDropped(QObject *data, int x, int y);
void containmentConfigPropertyChanged(const QString &key, const QVariant &value);
void appletsOrderChanged();
void appletsInLockedZoomChanged(const QList<int> &applets);
void appletsDisabledColoringChanged(const QList<int> &applets);
void appletInScheduledDestructionChanged(const int &id, const bool &enabled);
void appletRequestedVisualIndicator(const int &plasmoidId); void appletRequestedVisualIndicator(const int &plasmoidId);
@ -100,7 +156,12 @@ private slots:
void identifyShortcutsHost(); void identifyShortcutsHost();
void identifyMethods(); void identifyMethods();
void updateAppletsOrder();
void updateAppletsInLockedZoom();
void updateAppletsDisabledColoring();
void updateAppletsTracking(); void updateAppletsTracking();
void updateAppletDelayedConfiguration();
void onAppletAdded(Plasma::Applet *applet); void onAppletAdded(Plasma::Applet *applet);
void onAppletExpandedChanged(); void onAppletExpandedChanged();
void onLatteTasksCountChanged(); void onLatteTasksCountChanged();
@ -109,9 +170,14 @@ private slots:
private: private:
void addExpandedApplet(PlasmaQuick::AppletQuickItem * appletQuickItem); void addExpandedApplet(PlasmaQuick::AppletQuickItem * appletQuickItem);
void removeExpandedApplet(PlasmaQuick::AppletQuickItem *appletQuickItem); void removeExpandedApplet(PlasmaQuick::AppletQuickItem *appletQuickItem);
void initAppletConfigurationSignals(const int &id, KDeclarative::ConfigPropertyMap *configuration);
bool appletIsExpandable(PlasmaQuick::AppletQuickItem *appletQuickItem) const; bool appletIsExpandable(PlasmaQuick::AppletQuickItem *appletQuickItem) const;
KDeclarative::ConfigPropertyMap *appletConfiguration(const Plasma::Applet *applet);
QList<int> toIntList(const QVariantList &list);
private: private:
bool m_hasLatteTasks{false}; bool m_hasLatteTasks{false};
bool m_hasPlasmaTasks{false}; bool m_hasPlasmaTasks{false};
@ -132,9 +198,21 @@ private:
TasksModel *m_latteTasksModel; TasksModel *m_latteTasksModel;
TasksModel *m_plasmaTasksModel; TasksModel *m_plasmaTasksModel;
//!follow containment plasmoid
QPointer<QObject> m_plasmoid;
QPointer<QObject> m_layoutManager;
QPointer<KDeclarative::ConfigPropertyMap> m_configuration;
//!keep record of applet ids and avoid crashes when trying to access ids for already destroyed applets //!keep record of applet ids and avoid crashes when trying to access ids for already destroyed applets
QHash<PlasmaQuick::AppletQuickItem *, int> m_expandedAppletIds; QHash<PlasmaQuick::AppletQuickItem *, int> m_expandedAppletIds;
QHash<PlasmaQuick::AppletQuickItem *, QMetaObject::Connection> m_appletsExpandedConnections; QHash<PlasmaQuick::AppletQuickItem *, QMetaObject::Connection> m_appletsExpandedConnections;
//!all applet data
QList<int> m_appletOrder; //includes justify splitters
QList<int> m_appletsInLockedZoom;
QList<int> m_appletsDisabledColoring;
QHash<int, ViewPart::AppletInterfaceData> m_appletData;
QTimer m_appletDelayedConfigurationTimer;
}; };
} }

View File

@ -117,7 +117,7 @@ QPoint ContextMenu::popUpTopLeft(Plasma::Applet *applet, const QRect popUpRect)
if ((itemLength > menuLength) if ((itemLength > menuLength)
|| (applet == m_latteView->containment()) || (applet == m_latteView->containment())
|| (m_latteView && Layouts::Storage::self()->isSubContainment(m_latteView->layout(), applet)) ) { || (m_latteView && Layouts::Storage::self()->isSubContainment(m_latteView->corona(), applet)) ) {
return popUpRelevantToGlobalPoint(globalItemRect, popUpRect); return popUpRelevantToGlobalPoint(globalItemRect, popUpRect);
} else { } else {
return popUpRelevantToParent(globalItemRect, popUpRect); return popUpRelevantToParent(globalItemRect, popUpRect);
@ -267,8 +267,8 @@ bool ContextMenu::mousePressEvent(QMouseEvent *event)
if (ai && ai->isVisible() && appletContainsMouse) { if (ai && ai->isVisible() && appletContainsMouse) {
applet = ai->applet(); applet = ai->applet();
if (m_latteView && Layouts::Storage::self()->isSubContainment(m_latteView->layout(), applet)) { if (m_latteView && Layouts::Storage::self()->isSubContainment(m_latteView->corona(), applet)) {
Plasma::Containment *subContainment = Layouts::Storage::self()->subContainmentOf(m_latteView->layout(), applet); Plasma::Containment *subContainment = Layouts::Storage::self()->subContainmentOf(m_latteView->corona(), applet);
if (subContainment) { if (subContainment) {
Plasma::Applet *internalApplet{nullptr}; Plasma::Applet *internalApplet{nullptr};

282
app/view/originalview.cpp Normal file
View File

@ -0,0 +1,282 @@
/*
SPDX-FileCopyrightText: 2021 Michail Vourlakos <mvourlakos@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "originalview.h"
#include "clonedview.h"
#include "positioner.h"
#include "../lattecorona.h"
#include "../screenpool.h"
#include "../layouts/storage.h"
// KDE
#include <KLocalizedString>
namespace Latte {
OriginalView::OriginalView(Plasma::Corona *corona, QScreen *targetScreen, bool byPassX11WM)
: View(corona, targetScreen, byPassX11WM)
{
connect(this, &View::containmentChanged, this, [&]() {
if (!this->containment()) {
return;
}
connect(containment(), &Plasma::Applet::destroyedChanged, this, &OriginalView::syncClonesToScreens);
restoreConfig();
});
connect(this, &View::layoutChanged, this, &OriginalView::syncClonesToScreens);
connect(this, &OriginalView::screensGroupChanged, this, &OriginalView::syncClonesToScreens);
connect(this, &OriginalView::screensGroupChanged, this, &OriginalView::saveConfig);
}
OriginalView::~OriginalView()
{
cleanClones();
}
bool OriginalView::isSingle() const
{
return m_screensGroup == Latte::Types::SingleScreenGroup;
}
bool OriginalView::isOriginal() const
{
return true;
}
bool OriginalView::isCloned() const
{
return !isOriginal();
}
int OriginalView::clonesCount() const
{
return m_clones.count();
}
int OriginalView::expectedScreenIdFromScreenGroup(const Latte::Types::ScreensGroup &nextScreensGroup) const
{
Data::View view = data();
view.screensGroup = nextScreensGroup;
return Latte::Layouts::Storage::self()->expectedViewScreenId(m_corona, view);
}
Latte::Types::ScreensGroup OriginalView::screensGroup() const
{
return m_screensGroup;
}
void OriginalView::setScreensGroup(const Latte::Types::ScreensGroup &group)
{
if (m_screensGroup == group) {
return;
}
m_screensGroup = group;
emit screensGroupChanged();
}
void OriginalView::addClone(Latte::ClonedView *view)
{
if (m_clones.contains(view)) {
return;
}
m_clones << view;
m_waitingCreation.removeAll(view->positioner()->currentScreenId());
}
void OriginalView::removeClone(Latte::ClonedView *view)
{
if (!m_clones.contains(view)) {
return;
}
int idx = m_clones.indexOf(view);
auto cloned = m_clones.takeAt(idx);
if (!cloned->layout()) {
return;
}
cloned->positioner()->slideOutDuringExit();
cloned->layout()->removeView(cloned->data());
}
void OriginalView::createClone(int screenId)
{
if (!layout() || !containment()) {
return;
}
QString templateFile = layout()->storedView(containment()->id());
if (templateFile.isEmpty()) {
return;
}
Data::ViewsTable templateviews = Layouts::Storage::self()->views(templateFile);
if (templateviews.rowCount() <= 0) {
return;
}
Data::View nextdata = templateviews[0];
nextdata.name = i18nc("clone of original dock panel, name","Clone of %1", name());
nextdata.onPrimary = false;
nextdata.screensGroup = Latte::Types::SingleScreenGroup;
nextdata.isClonedFrom = containment()->id();
nextdata.screen = screenId;
nextdata.setState(Data::View::OriginFromViewTemplate, templateFile);
if (!m_waitingCreation.contains(screenId)) {
m_waitingCreation << screenId;
layout()->newView(nextdata);
}
}
void OriginalView::cleanClones()
{
if (m_clones.count()==0) {
return;
}
while(!m_clones.isEmpty()) {
removeClone(m_clones[0]);
}
}
void OriginalView::reconsiderScreen()
{
View::reconsiderScreen();
syncClonesToScreens();
}
void OriginalView::setNextLocationForClones(const QString layoutName, int edge, int alignment)
{
if (m_clones.count()==0) {
return;
}
for (const auto clone : m_clones) {
clone->positioner()->setNextLocation(layoutName, Latte::Types::SingleScreenGroup, "", edge, alignment);
}
}
void OriginalView::addApplet(const QString &pluginId, const int &excludecloneid)
{
if (m_clones.count() == 0) {
return;
}
// add applet in original view
extendedInterface()->addApplet(pluginId);
// add applet in clones and exclude the one that probably produced this triggering
for(const auto clone: m_clones) {
if (clone->containment()->id() == excludecloneid) {
// this way we make sure that an applet will not be double added
continue;
}
clone->extendedInterface()->addApplet(pluginId);
}
}
void OriginalView::addApplet(QObject *mimedata, const int &x, const int &y, const int &excludecloneid)
{
if (m_clones.count() == 0) {
return;
}
// add applet in original view
extendedInterface()->addApplet(mimedata, x, y);
// add applet in clones and exclude the one that probably produced this triggering
for(const auto clone: m_clones) {
if (clone->containment()->id() == excludecloneid) {
// this way we make sure that an applet will not be double added
continue;
}
clone->extendedInterface()->addApplet(mimedata, x, y);
}
}
void OriginalView::syncClonesToScreens()
{
if (isSingle() || (containment() && containment()->destroyed())) {
cleanClones();
return;
}
QList<int> secondaryscreens = m_corona->screenPool()->secondaryScreenIds();
for (const auto scrid : secondaryscreens) {
if (m_waitingCreation.contains(scrid)) {
secondaryscreens.removeAll(scrid);
}
}
if (m_screensGroup == Latte::Types::AllSecondaryScreensGroup) {
//! occuped screen from original view in "allsecondaryscreensgroup" must be ignored
secondaryscreens.removeAll(expectedScreenIdFromScreenGroup(m_screensGroup));
}
QList<Latte::ClonedView *> removable;
for (const auto clone : m_clones) {
if (secondaryscreens.contains(clone->positioner()->currentScreenId())) {
// do nothing valid clone
secondaryscreens.removeAll(clone->positioner()->currentScreenId());
} else {
// must be removed the screen is not active
removable << clone;
}
}
for (const auto scrid : secondaryscreens) {
if (removable.count() > 0) {
//! move deprecated and available clone to valid secondary screen
auto clone = removable.takeFirst();
clone->positioner()->setScreenToFollow(m_corona->screenPool()->screenForId(scrid));
} else {
//! create a new clone
createClone(scrid);
}
}
for (auto removableclone : removable) {
//! remove deprecated clones
removeClone(removableclone);
}
}
void OriginalView::saveConfig()
{
if (!this->containment()) {
return;
}
auto config = this->containment()->config();
config.writeEntry("screensGroup", (int)m_screensGroup);
}
void OriginalView::restoreConfig()
{
if (!this->containment()) {
return;
}
auto config = this->containment()->config();
m_screensGroup = static_cast<Latte::Types::ScreensGroup>(config.readEntry("screensGroup", (int)Latte::Types::SingleScreenGroup));
//! Send changed signals at the end in order to be sure that saveConfig
//! wont rewrite default/invalid values
emit screensGroupChanged();
}
}

72
app/view/originalview.h Normal file
View File

@ -0,0 +1,72 @@
/*
SPDX-FileCopyrightText: 2021 Michail Vourlakos <mvourlakos@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef ORIGINALVIEW_H
#define ORIGINALVIEW_H
// local
#include <coretypes.h>
#include "view.h"
// Qt
#include <QList>
namespace Latte {
class ClonedView;
class OriginalView : public View
{
Q_OBJECT
Q_PROPERTY(Latte::Types::ScreensGroup screensGroup READ screensGroup NOTIFY screensGroupChanged)
public:
OriginalView(Plasma::Corona *corona, QScreen *targetScreen = nullptr, bool byPassX11WM = false);
~OriginalView();
bool isOriginal() const override;
bool isCloned() const override;
bool isSingle() const override;
int clonesCount() const;
int expectedScreenIdFromScreenGroup(const Latte::Types::ScreensGroup &nextScreensGroup) const;
Latte::Types::ScreensGroup screensGroup() const override;
void setScreensGroup(const Latte::Types::ScreensGroup &group);
void addClone(Latte::ClonedView *view);
void setNextLocationForClones(const QString layoutName, int edge, int alignment);
void addApplet(const QString &pluginId, const int &excludecloneid);
void addApplet(QObject *mimedata, const int &x, const int &y, const int &excludecloneid);
void reconsiderScreen() override;
public slots:
void cleanClones();
signals:
void screensGroupChanged();
private slots:
void syncClonesToScreens();
void restoreConfig();
void saveConfig();
private:
void createClone(int screenId);
void removeClone(Latte::ClonedView *view);
private:
Latte::Types::ScreensGroup m_screensGroup{Latte::Types::SingleScreenGroup};
QList<Latte::ClonedView *> m_clones;
QList<int> m_waitingCreation;
};
}
#endif

View File

@ -8,6 +8,7 @@
// local // local
#include <coretypes.h> #include <coretypes.h>
#include "effects.h" #include "effects.h"
#include "originalview.h"
#include "view.h" #include "view.h"
#include "visibilitymanager.h" #include "visibilitymanager.h"
#include "../lattecorona.h" #include "../lattecorona.h"
@ -347,6 +348,7 @@ void Positioner::onStartupFinished()
if (m_inStartup) { if (m_inStartup) {
m_inStartup = false; m_inStartup = false;
syncGeometry(); syncGeometry();
emit isOffScreenChanged();
} }
} }
@ -1045,6 +1047,12 @@ void Positioner::initSignalingForLocationChangeSliding()
m_view->setAlignment(m_nextAlignment); m_view->setAlignment(m_nextAlignment);
m_nextAlignment = Latte::Types::NoneAlignment; m_nextAlignment = Latte::Types::NoneAlignment;
} }
//! SCREENSGROUP
if (m_view->isOriginal()) {
auto originalview = qobject_cast<Latte::OriginalView *>(m_view);
originalview->setScreensGroup(m_nextScreensGroup);
}
}); });
} }
@ -1139,7 +1147,7 @@ bool Positioner::isLastHidingRelocationEvent() const
return (events <= 1); return (events <= 1);
} }
void Positioner::setNextLocation(const QString layoutName, const QString screenName, int edge, int alignment) void Positioner::setNextLocation(const QString layoutName, const int screensGroup, QString screenName, int edge, int alignment)
{ {
bool isanimated{false}; bool isanimated{false};
bool haschanges{false}; bool haschanges{false};
@ -1164,6 +1172,30 @@ void Positioner::setNextLocation(const QString layoutName, const QString screenN
} }
} }
//! SCREENSGROUP
if (m_view->isOriginal()) {
auto originalview = qobject_cast<Latte::OriginalView *>(m_view);
//!initialize screens group
m_nextScreensGroup = originalview->screensGroup();
if (m_nextScreensGroup != screensGroup) {
haschanges = true;
m_nextScreensGroup = static_cast<Latte::Types::ScreensGroup>(screensGroup);
if (m_nextScreensGroup == Latte::Types::AllScreensGroup) {
screenName = Latte::Data::Screen::ONPRIMARYNAME;
} else if (m_nextScreensGroup == Latte::Types::AllSecondaryScreensGroup) {
int scrid = originalview->expectedScreenIdFromScreenGroup(m_nextScreensGroup);
if (scrid != Latte::ScreenPool::NOSCREENID) {
screenName = m_corona->screenPool()->connector(scrid);
}
}
}
} else {
m_nextScreensGroup = Latte::Types::SingleScreenGroup;
}
//! SCREEN //! SCREEN
if (!screenName.isEmpty()) { if (!screenName.isEmpty()) {
bool nextonprimary = (screenName == Latte::Data::Screen::ONPRIMARYNAME); bool nextonprimary = (screenName == Latte::Data::Screen::ONPRIMARYNAME);
@ -1200,6 +1232,11 @@ void Positioner::setNextLocation(const QString layoutName, const QString screenN
haschanges = true; haschanges = true;
} }
if (haschanges && m_view->isOriginal()) {
auto originalview = qobject_cast<Latte::OriginalView *>(m_view);
originalview->setNextLocationForClones(layoutName, edge, alignment);
}
m_repositionIsAnimated = isanimated; m_repositionIsAnimated = isanimated;
m_repositionFromViewSettingsWindow = m_view->settingsWindowIsShown(); m_repositionFromViewSettingsWindow = m_view->settingsWindowIsShown();

View File

@ -40,6 +40,7 @@ class Positioner: public QObject
Q_PROPERTY(bool inRelocationShowing READ inRelocationShowing WRITE setInRelocationShowing NOTIFY inRelocationShowingChanged) Q_PROPERTY(bool inRelocationShowing READ inRelocationShowing WRITE setInRelocationShowing NOTIFY inRelocationShowingChanged)
Q_PROPERTY(bool inSlideAnimation READ inSlideAnimation WRITE setInSlideAnimation NOTIFY inSlideAnimationChanged) Q_PROPERTY(bool inSlideAnimation READ inSlideAnimation WRITE setInSlideAnimation NOTIFY inSlideAnimationChanged)
Q_PROPERTY(bool isOffScreen READ isOffScreen NOTIFY isOffScreenChanged)
Q_PROPERTY(bool isStickedOnTopEdge READ isStickedOnTopEdge WRITE setIsStickedOnTopEdge NOTIFY isStickedOnTopEdgeChanged) Q_PROPERTY(bool isStickedOnTopEdge READ isStickedOnTopEdge WRITE setIsStickedOnTopEdge NOTIFY isStickedOnTopEdgeChanged)
Q_PROPERTY(bool isStickedOnBottomEdge READ isStickedOnBottomEdge WRITE setIsStickedOnBottomEdge NOTIFY isStickedOnBottomEdgeChanged) Q_PROPERTY(bool isStickedOnBottomEdge READ isStickedOnBottomEdge WRITE setIsStickedOnBottomEdge NOTIFY isStickedOnBottomEdgeChanged)
@ -90,7 +91,7 @@ public:
Latte::WindowSystem::WindowId trackedWindowId(); Latte::WindowSystem::WindowId trackedWindowId();
public slots: public slots:
Q_INVOKABLE void setNextLocation(const QString layoutName, const QString screenId, int edge, int alignment); Q_INVOKABLE void setNextLocation(const QString layoutName, const int screensGroup, QString screenName, int edge, int alignment);
Q_INVOKABLE void slideInDuringStartup(); Q_INVOKABLE void slideInDuringStartup();
void syncGeometry(); void syncGeometry();
@ -126,6 +127,7 @@ signals:
void inRelocationAnimationChanged(); void inRelocationAnimationChanged();
void inRelocationShowingChanged(); void inRelocationShowingChanged();
void inSlideAnimationChanged(); void inSlideAnimationChanged();
void isOffScreenChanged();
void isStickedOnTopEdgeChanged(); void isStickedOnTopEdgeChanged();
void isStickedOnBottomEdgeChanged(); void isStickedOnBottomEdgeChanged();
@ -193,6 +195,7 @@ private:
bool m_repositionIsAnimated{false}; bool m_repositionIsAnimated{false};
QString m_nextLayoutName; QString m_nextLayoutName;
Latte::Types::ScreensGroup m_nextScreensGroup{Latte::Types::SingleScreenGroup};
QString m_nextScreenName; QString m_nextScreenName;
QScreen *m_nextScreen{nullptr}; QScreen *m_nextScreen{nullptr};
Plasma::Types::Location m_nextScreenEdge{Plasma::Types::Floating}; Plasma::Types::Location m_nextScreenEdge{Plasma::Types::Floating};

View File

@ -89,6 +89,7 @@ void WidgetExplorerView::initParentView(Latte::View *view)
SubConfigView::initParentView(view); SubConfigView::initParentView(view);
rootContext()->setContextProperty(QStringLiteral("containmentFromView"), m_latteView->containment()); rootContext()->setContextProperty(QStringLiteral("containmentFromView"), m_latteView->containment());
rootContext()->setContextProperty(QStringLiteral("latteView"), m_latteView);
updateEnabledBorders(); updateEnabledBorders();
syncGeometry(); syncGeometry();

View File

@ -120,6 +120,7 @@ View::View(Plasma::Corona *corona, QScreen *targetScreen, bool byPassX11WM)
connect(m_contextMenu, &ViewPart::ContextMenu::menuChanged, this, &View::updateTransientWindowsTracking); connect(m_contextMenu, &ViewPart::ContextMenu::menuChanged, this, &View::updateTransientWindowsTracking);
connect(m_interface, &ViewPart::ContainmentInterface::hasExpandedAppletChanged, this, &View::updateTransientWindowsTracking); connect(m_interface, &ViewPart::ContainmentInterface::hasExpandedAppletChanged, this, &View::updateTransientWindowsTracking);
connect(this, &View::containmentChanged, this, &View::groupIdChanged);
connect(this, &View::containmentChanged connect(this, &View::containmentChanged
, this, [ &, byPassX11WM]() { , this, [ &, byPassX11WM]() {
qDebug() << "dock view c++ containment changed 1..."; qDebug() << "dock view c++ containment changed 1...";
@ -1017,6 +1018,15 @@ void View::setOnPrimary(bool flag)
emit onPrimaryChanged(); emit onPrimaryChanged();
} }
int View::groupId() const
{
if (!containment()) {
return -1;
}
return containment()->id();
}
float View::maxLength() const float View::maxLength() const
{ {
return m_maxLength; return m_maxLength;
@ -1389,6 +1399,8 @@ Latte::Data::View View::data() const
vdata.screen = containment()->lastScreen(); vdata.screen = containment()->lastScreen();
} }
vdata.screensGroup = screensGroup();
//!screen edge margin can be more accurate in the config file //!screen edge margin can be more accurate in the config file
vdata.screenEdgeMargin = m_screenEdgeMargin > 0 ? m_screenEdgeMargin : containment()->config().group("General").readEntry("screenEdgeMargin", (int)-1); vdata.screenEdgeMargin = m_screenEdgeMargin > 0 ? m_screenEdgeMargin : containment()->config().group("General").readEntry("screenEdgeMargin", (int)-1);
@ -1738,8 +1750,9 @@ void View::mousePressEvent(QMouseEvent *event)
//!BEGIN configuration functions //!BEGIN configuration functions
void View::saveConfig() void View::saveConfig()
{ {
if (!this->containment()) if (!this->containment()) {
return; return;
}
auto config = this->containment()->config(); auto config = this->containment()->config();
config.writeEntry("onPrimary", onPrimary()); config.writeEntry("onPrimary", onPrimary());
@ -1751,8 +1764,9 @@ void View::saveConfig()
void View::restoreConfig() void View::restoreConfig()
{ {
if (!this->containment()) if (!this->containment()) {
return; return;
}
auto config = this->containment()->config(); auto config = this->containment()->config();
m_onPrimary = config.readEntry("onPrimary", true); m_onPrimary = config.readEntry("onPrimary", true);

View File

@ -70,6 +70,7 @@ class View : public PlasmaQuick::ContainmentView
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(int groupId READ groupId NOTIFY groupIdChanged)
Q_PROPERTY(Latte::Types::ViewType type READ type WRITE setType NOTIFY typeChanged) Q_PROPERTY(Latte::Types::ViewType type READ type WRITE setType NOTIFY typeChanged)
Q_PROPERTY(bool alternativesIsShown READ alternativesIsShown NOTIFY alternativesIsShownChanged) Q_PROPERTY(bool alternativesIsShown READ alternativesIsShown NOTIFY alternativesIsShownChanged)
@ -160,7 +161,7 @@ public:
bool isFloatingPanel() const; bool isFloatingPanel() const;
bool isPreferredForShortcuts() const; virtual bool isPreferredForShortcuts() const;
void setIsPreferredForShortcuts(bool preferred); void setIsPreferredForShortcuts(bool preferred);
bool inSettingsAdvancedMode() const; bool inSettingsAdvancedMode() const;
@ -174,6 +175,8 @@ public:
bool screenEdgeMarginEnabled() const; bool screenEdgeMarginEnabled() const;
void setScreenEdgeMarginEnabled(bool enabled); void setScreenEdgeMarginEnabled(bool enabled);
virtual int groupId() const;
int fontPixelSize() const; int fontPixelSize() const;
void setFontPixelSize(int size); void setFontPixelSize(int size);
@ -229,16 +232,21 @@ public:
QQuickItem *metrics() const; QQuickItem *metrics() const;
void setMetrics(QQuickItem *metrics); void setMetrics(QQuickItem *metrics);
virtual bool isCloned() const = 0; //means that this view is a clone of an original view
virtual bool isOriginal() const = 0; //means that this view is an original view that can be autocloned to other screens
virtual bool isSingle() const = 0; //means that this view is not related to clones and screen groups in any way
virtual Latte::Types::ScreensGroup screensGroup() const = 0;
QVariantList containmentActions() const; QVariantList containmentActions() const;
QQuickView *configView(); QQuickView *configView();
Latte::Data::View data() const; virtual Latte::Data::View data() const;
ViewPart::Effects *effects() const; ViewPart::Effects *effects() const;
ViewPart::ContextMenu *contextMenu() const; ViewPart::ContextMenu *contextMenu() const;
ViewPart::ContainmentInterface *extendedInterface() const; ViewPart::ContainmentInterface *extendedInterface() const;
ViewPart::Indicator *indicator() const; virtual ViewPart::Indicator *indicator() const;
ViewPart::Parabolic *parabolic() const; ViewPart::Parabolic *parabolic() const;
ViewPart::Positioner *positioner() const; ViewPart::Positioner *positioner() const;
ViewPart::EventsSink *sink() const; ViewPart::EventsSink *sink() const;
@ -256,7 +264,7 @@ public:
//! release grab and restore mouse state //! release grab and restore mouse state
void unblockMouse(int x, int y); void unblockMouse(int x, int y);
void reconsiderScreen(); virtual void reconsiderScreen();
//! these are signals that create crashes, such a example is the availableScreenRectChanged from corona //! these are signals that create crashes, such a example is the availableScreenRectChanged from corona
//! when its containment is destroyed //! when its containment is destroyed
@ -309,6 +317,7 @@ signals:
void fontPixelSizeChanged(); void fontPixelSizeChanged();
void forcedShown(); //[workaround] forced shown to avoid a KWin issue that hides windows when closing activities void forcedShown(); //[workaround] forced shown to avoid a KWin issue that hides windows when closing activities
void geometryChanged(); void geometryChanged();
void groupIdChanged();
void widthChanged(); void widthChanged();
void headThicknessGapChanged(); void headThicknessGapChanged();
void heightChanged(); void heightChanged();
@ -334,6 +343,7 @@ signals:
void screenEdgeMarginChanged(); void screenEdgeMarginChanged();
void screenEdgeMarginEnabledChanged(); void screenEdgeMarginEnabledChanged();
void screenGeometryChanged(); void screenGeometryChanged();
void sinkChanged(); void sinkChanged();
void typeChanged(); void typeChanged();
void visibilityChanged(); void visibilityChanged();
@ -352,6 +362,9 @@ signals:
void availableScreenRectChangedFrom(Latte::View *origin); void availableScreenRectChangedFrom(Latte::View *origin);
void availableScreenRegionChangedFrom(Latte::View *origin); void availableScreenRegionChangedFrom(Latte::View *origin);
protected:
QPointer<Latte::Corona> m_corona;
private slots: private slots:
void applyActivitiesToWindows(); void applyActivitiesToWindows();
void availableScreenRectChangedFromSlot(View *origin); void availableScreenRectChangedFromSlot(View *origin);
@ -457,8 +470,6 @@ private:
//! track transientWindows //! track transientWindows
QList<QWindow *> m_transientWindows; QList<QWindow *> m_transientWindows;
QPointer<Latte::Corona> m_corona;
KWayland::Client::PlasmaShellSurface *m_shellSurface{nullptr}; KWayland::Client::PlasmaShellSurface *m_shellSurface{nullptr};
}; };

View File

@ -17,7 +17,8 @@ target_link_libraries(lattecontainmentplugin
Qt5::Qml Qt5::Qml
Qt5::Quick Qt5::Quick
KF5::Declarative KF5::Declarative
KF5::Plasma) KF5::Plasma
KF5::PlasmaQuick)
install(TARGETS lattecontainmentplugin DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/latte/private/containment) install(TARGETS lattecontainmentplugin DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/latte/private/containment)
install(FILES plugin/qmldir DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/latte/private/containment) install(FILES plugin/qmldir DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/latte/private/containment)

View File

@ -337,5 +337,18 @@ Item {
&& plasmoid.configuration.hideFloatingGapForMaximized) && plasmoid.configuration.hideFloatingGapForMaximized)
} }
//! View::ExtendedInterface bindings
Binding{
target: latteView && latteView.extendedInterface ? latteView.extendedInterface : null
property: "plasmoid"
when: latteView && latteView.extendedInterface
value: plasmoid
}
Binding{
target: latteView && latteView.extendedInterface ? latteView.extendedInterface : null
property: "layoutManager"
when: latteView && latteView.extendedInterface
value: fastLayoutManager
}
} }

View File

@ -181,14 +181,22 @@ DragDrop.DropArea {
if (root.launchers.hasStealingApplet && dragInfo.onlyLaunchers) { if (root.launchers.hasStealingApplet && dragInfo.onlyLaunchers) {
root.launchers.addDroppedLaunchersInStealingApplet(event.mimeData.urls); root.launchers.addDroppedLaunchersInStealingApplet(event.mimeData.urls);
} else { } else {
plasmoid.processMimeData(event.mimeData, event.x, event.y); var dndindex = fastLayoutManager.dndSpacerIndex();
var eventx = event.x;
var eventy = event.y;
if (dndindex >= 0) {
var masquearadedIndexFromPoint = fastLayoutManager.indexToMasquearadedPoint(fastLayoutManager.dndSpacerIndex());
eventx = masquearadedIndexFromPoint.x;
eventy = masquearadedIndexFromPoint.y;
}
plasmoid.processMimeData(event.mimeData, eventx, eventy);
//! inform others what plasmoid was drag n' dropped to be added
latteView.extendedInterface.appletDropped(event.mimeData, eventx, eventy);
event.accept(event.proposedAction); event.accept(event.proposedAction);
} }
dndSpacer.opacity = 0; dndSpacer.opacity = 0;
// if (dragInfo.isPlasmoid && root.myView.alignment === LatteCore.Types.Justify) {
// fastLayoutManager.moveAppletsBasedOnJustifyAlignment();
// }
} }
} }

View File

@ -59,10 +59,9 @@ Item {
Connections { Connections {
target: root target: root
onContainsOnlyPlasmaTasksChanged: sizer.updateIconSize(); onContainsOnlyPlasmaTasksChanged: sizer.updateIconSize();
onMaxLengthChanged: { onMaxLengthChanged: {
if (root.editMode) { if (latteView && latteView.positioner && !latteView.positioner.isOffScreen) {
sizer.updateIconSize(); sizer.updateIconSize();
} }
} }
@ -93,6 +92,15 @@ Item {
} }
} }
Connections {
target: latteView && latteView.positioner ? latteView.positioner : null
onIsOffScreenChanged: {
if (!latteView.positioner.isOffScreen) {
sizer.updateIconSize();
}
}
}
Connections { Connections {
target: visibilityManager target: visibilityManager
onInNormalStateChanged: { onInNormalStateChanged: {

View File

@ -30,42 +30,53 @@ Ability.LaunchersPrivate {
layoutsManager.syncedLaunchers.removeAbilityClient(client); layoutsManager.syncedLaunchers.removeAbilityClient(client);
} }
function addSyncedLauncher(group, launcherUrl) { function addSyncedLauncher(senderId, group, groupId, launcherUrl) {
layoutsManager.syncedLaunchers.addLauncher(layoutName, layoutsManager.syncedLaunchers.addLauncher(layoutName,
senderId,
group, group,
groupId,
launcherUrl); launcherUrl);
} }
function removeSyncedLauncher(group, launcherUrl) { function removeSyncedLauncher(senderId, group,groupId, launcherUrl) {
layoutsManager.syncedLaunchers.removeLauncher(layoutName, layoutsManager.syncedLaunchers.removeLauncher(layoutName,
senderId,
group, group,
groupId,
launcherUrl); launcherUrl);
} }
function addSyncedLauncherToActivity(group, launcherUrl, activityId) { function addSyncedLauncherToActivity(senderId, group, groupId, launcherUrl, activityId) {
layoutsManager.syncedLaunchers.addLauncherToActivity(layoutName, layoutsManager.syncedLaunchers.addLauncherToActivity(layoutName,
senderId,
group, group,
groupId,
launcherUrl, launcherUrl,
activityId); activityId);
} }
function removeSyncedLauncherFromActivity(group, launcherUrl, activityId) { function removeSyncedLauncherFromActivity(senderId, group, groupId, launcherUrl, activityId) {
layoutsManager.syncedLaunchers.removeLauncherFromActivity(layoutName, layoutsManager.syncedLaunchers.removeLauncherFromActivity(layoutName,
senderId,
group, group,
groupId,
launcherUrl, launcherUrl,
activityId); activityId);
} }
function addDroppedLaunchers(group, urls) { function addDroppedLaunchers(senderId, group, groupId, urls) {
layoutsManager.syncedLaunchers.urlsDropped(layoutName, layoutsManager.syncedLaunchers.urlsDropped(layoutName,
senderId,
group, group,
groupId,
urls); urls);
} }
function validateSyncedLaunchersOrder(senderId, group, orderedlaunchers) { function validateSyncedLaunchersOrder(senderId, group, groupId, orderedlaunchers) {
layoutsManager.syncedLaunchers.validateLaunchersOrder(layoutName, layoutsManager.syncedLaunchers.validateLaunchersOrder(layoutName,
senderId, senderId,
group, group,
groupId,
orderedlaunchers); orderedlaunchers);
} }

View File

@ -13,6 +13,7 @@ import "./privates" as Ability
Ability.MyViewPrivate { Ability.MyViewPrivate {
view: latteView view: latteView
isReady: view && view.visibility && view.layout && view.effects && view.positioner isReady: view && view.visibility && view.layout && view.effects && view.positioner
groupId: view ? view.groupId : -1
inNormalState: ((animations.needBothAxis.count === 0) && (animations.needLength.count === 0)) inNormalState: ((animations.needBothAxis.count === 0) && (animations.needLength.count === 0))
|| (isReady && view.visibility.isHidden && !view.visibility.containsMouse && animations.needThickness.count === 0) || (isReady && view.visibility.isHidden && !view.visibility.containsMouse && animations.needThickness.count === 0)

View File

@ -24,8 +24,6 @@ import "../debugger" as Debugger
Item { Item {
id: appletItem id: appletItem
visible: false
width: isInternalViewSplitter && !root.inConfigureAppletsMode ? 0 : computeWidth width: isInternalViewSplitter && !root.inConfigureAppletsMode ? 0 : computeWidth
height: isInternalViewSplitter && !root.inConfigureAppletsMode ? 0 : computeHeight height: isInternalViewSplitter && !root.inConfigureAppletsMode ? 0 : computeHeight
@ -78,10 +76,13 @@ Item {
&& root.dragOverlay.currentApplet && root.dragOverlay.currentApplet
&& root.dragOverlay.pressed && root.dragOverlay.pressed
property bool userBlocksColorizing: false
property bool appletBlocksColorizing: !communicator.requires.latteSideColoringEnabled || communicator.indexerIsSupported property bool appletBlocksColorizing: !communicator.requires.latteSideColoringEnabled || communicator.indexerIsSupported
property bool appletBlocksParabolicEffect: communicator.requires.parabolicEffectLocked property bool appletBlocksParabolicEffect: communicator.requires.parabolicEffectLocked
property bool lockZoom: false readonly property bool lockZoom: !parabolicEffectIsSupported
|| appletBlocksParabolicEffect
|| (fastLayoutManager && applet && (fastLayoutManager.lockedZoomApplets.indexOf(applet.id)>=0))
readonly property bool userBlocksColorizing: appletBlocksColorizing
|| (fastLayoutManager && applet && (fastLayoutManager.userBlocksColorizingApplets.indexOf(applet.id)>=0))
property bool isActive: (isExpanded property bool isActive: (isExpanded
&& !appletItem.communicator.indexerIsSupported && !appletItem.communicator.indexerIsSupported
@ -90,8 +91,8 @@ Item {
property bool isExpanded: false property bool isExpanded: false
property bool isHidden: !root.inConfigureAppletsMode property bool isScheduledForDestruction: (fastLayoutManager && applet && fastLayoutManager.appletsInScheduledDestruction.indexOf(applet.id)>=0)
&& ((applet && applet.status === PlasmaCore.Types.HiddenStatus ) || isInternalViewSplitter) property bool isHidden: (!root.inConfigureAppletsMode && ((applet && applet.status === PlasmaCore.Types.HiddenStatus ) || isInternalViewSplitter)) || isScheduledForDestruction
property bool isInternalViewSplitter: (internalSplitterId > 0) property bool isInternalViewSplitter: (internalSplitterId > 0)
property bool isZoomed: false property bool isZoomed: false
property bool isPlaceHolder: false property bool isPlaceHolder: false
@ -574,9 +575,6 @@ Item {
onIsAutoFillAppletChanged: updateParabolicEffectIsSupported(); onIsAutoFillAppletChanged: updateParabolicEffectIsSupported();
onLockZoomChanged: fastLayoutManager.saveOptions();
onUserBlocksColorizingChanged: fastLayoutManager.saveOptions();
Component.onCompleted: { Component.onCompleted: {
checkIndex(); checkIndex();
root.updateIndexes.connect(checkIndex); root.updateIndexes.connect(checkIndex);

View File

@ -23,6 +23,10 @@ Item{
height: root.isHorizontal ? thickness : length height: root.isHorizontal ? thickness : length
readonly property real length: { readonly property real length: {
if (appletItem.isScheduledForDestruction) {
return 0;
}
if (appletItem.isInternalViewSplitter) { if (appletItem.isInternalViewSplitter) {
if (!root.inConfigureAppletsMode) { if (!root.inConfigureAppletsMode) {
return 0; return 0;

View File

@ -414,6 +414,7 @@ MouseArea {
closeButton.visible = !currentApplet.isInternalViewSplitter && currentApplet.applet.action("remove") && currentApplet.applet.action("remove").enabled; closeButton.visible = !currentApplet.isInternalViewSplitter && currentApplet.applet.action("remove") && currentApplet.applet.action("remove").enabled;
lockButton.visible = !currentApplet.isInternalViewSplitter lockButton.visible = !currentApplet.isInternalViewSplitter
&& !currentApplet.communicator.indexerIsSupported && !currentApplet.communicator.indexerIsSupported
&& !currentApplet.communicator.appletBlocksParabolicEffect
&& !currentApplet.isSeparator; && !currentApplet.isSeparator;
colorizingButton.visible = root.colorizerEnabled && !currentApplet.appletBlocksColorizing && !currentApplet.isInternalViewSplitter; colorizingButton.visible = root.colorizerEnabled && !currentApplet.appletBlocksColorizing && !currentApplet.isInternalViewSplitter;
@ -469,8 +470,8 @@ MouseArea {
iconSource: "color-picker" iconSource: "color-picker"
tooltip: i18n("Enable painting for this applet") tooltip: i18n("Enable painting for this applet")
onCheckedChanged: { onClicked: {
currentApplet.userBlocksColorizing = !checked; fastLayoutManager.setOption(currentApplet.applet.id, "userBlocksColorizing", !checked);
} }
} }
@ -480,8 +481,8 @@ MouseArea {
iconSource: checked ? "lock" : "unlock" iconSource: checked ? "lock" : "unlock"
tooltip: i18n("Disable parabolic effect for this applet") tooltip: i18n("Disable parabolic effect for this applet")
onCheckedChanged: { onClicked: {
currentApplet.lockZoom = checked; fastLayoutManager.setOption(currentApplet.applet.id, "lockZoom", checked);
} }
} }

View File

@ -553,7 +553,15 @@ Item {
} }
} }
Containment.onAppletAdded: fastLayoutManager.addAppletItem(applet, x, y); Containment.onAppletAdded: {
if (fastLayoutManager.isMasqueradedIndex(x, y)) {
var index = fastLayoutManager.masquearadedIndex(x, y);
fastLayoutManager.addAppletItem(applet, index);
} else {
fastLayoutManager.addAppletItem(applet, x, y);
}
}
Containment.onAppletRemoved: fastLayoutManager.removeAppletItem(applet); Containment.onAppletRemoved: fastLayoutManager.removeAppletItem(applet);
Plasmoid.onUserConfiguringChanged: { Plasmoid.onUserConfiguringChanged: {
@ -572,18 +580,21 @@ Item {
//////////////START OF FUNCTIONS //////////////START OF FUNCTIONS
function createAppletItem(applet) { function createAppletItem(applet) {
var appletItem = appletItemComponent.createObject(dndSpacer.parent); var appletContainer = appletItemComponent.createObject(dndSpacer.parent);
appletItem.applet = applet; initAppletContainer(appletContainer, applet);
applet.parent = appletItem.appletWrapper;
applet.anchors.fill = appletItem.appletWrapper;
applet.visible = true;
// don't show applet if it chooses to be hidden but still make it accessible in the panelcontroller // don't show applet if it chooses to be hidden but still make it accessible in the panelcontroller
appletItem.visible = Qt.binding(function() { appletContainer.visible = Qt.binding(function() {
return applet.status !== PlasmaCore.Types.HiddenStatus || (!plasmoid.immutable && root.inConfigureAppletsMode) return (appletContainer.applet && appletContainer.applet.status !== PlasmaCore.Types.HiddenStatus || (!plasmoid.immutable && root.inConfigureAppletsMode)) && !appletContainer.isHidden;
}); });
return appletContainer;
}
return appletItem; function initAppletContainer(appletContainer, applet) {
appletContainer.applet = applet;
applet.parent = appletContainer.appletWrapper;
applet.anchors.fill = appletContainer.appletWrapper;
applet.visible = true;
} }
function createJustifySplitter() { function createJustifySplitter() {
@ -743,23 +754,9 @@ Item {
endLayout: layoutsContainer.endLayout endLayout: layoutsContainer.endLayout
metrics: _metrics metrics: _metrics
onLockedZoomAppletsChanged: plasmoid.configuration.lockedZoomApplets = fastLayoutManager.lockedZoomApplets; onAppletOrderChanged: root.updateIndexes();
onUserBlocksColorizingAppletsChanged: plasmoid.configuration.userBlocksColorizingApplets = fastLayoutManager.userBlocksColorizingApplets; onSplitterPositionChanged: root.updateIndexes();
onSplitterPosition2Changed: root.updateIndexes();
onAppletOrderChanged: {
plasmoid.configuration.appletOrder = fastLayoutManager.appletOrder;
root.updateIndexes();
}
onSplitterPositionChanged: {
plasmoid.configuration.splitterPosition = fastLayoutManager.splitterPosition;
root.updateIndexes();
}
onSplitterPosition2Changed: {
plasmoid.configuration.splitterPosition2 = fastLayoutManager.splitterPosition2;
root.updateIndexes();
}
} }
///////////////BEGIN UI elements ///////////////BEGIN UI elements

View File

@ -16,7 +16,11 @@
// Plasma // Plasma
#include <Plasma> #include <Plasma>
#include <Plasma/Applet>
#include <PlasmaQuick/AppletQuickItem>
#define ISAPPLETLOCKEDOPTION "lockZoom"
#define ISCOLORINGBLOCKEDOPTION "userBlocksColorizing"
namespace Latte{ namespace Latte{
namespace Containment{ namespace Containment{
@ -24,8 +28,8 @@ namespace Containment{
LayoutManager::LayoutManager(QObject *parent) LayoutManager::LayoutManager(QObject *parent)
: QObject(parent) : QObject(parent)
{ {
m_option["lockZoom"] = "lockedZoomApplets"; m_option[ISAPPLETLOCKEDOPTION] = "lockedZoomApplets";
m_option["userBlocksColorizing"] = "userBlocksColorizingApplets"; m_option[ISCOLORINGBLOCKEDOPTION] = "userBlocksColorizingApplets";
connect(this, &LayoutManager::rootItemChanged, this, &LayoutManager::onRootItemChanged); connect(this, &LayoutManager::rootItemChanged, this, &LayoutManager::onRootItemChanged);
@ -72,12 +76,12 @@ void LayoutManager::setSplitterPosition2(const int &position)
emit splitterPosition2Changed(); emit splitterPosition2Changed();
} }
QString LayoutManager::appletOrder() const QList<int> LayoutManager::appletOrder() const
{ {
return m_appletOrder; return m_appletOrder;
} }
void LayoutManager::setAppletOrder(const QString &order) void LayoutManager::setAppletOrder(const QList<int> &order)
{ {
if (m_appletOrder == order) { if (m_appletOrder == order) {
return; return;
@ -87,12 +91,12 @@ void LayoutManager::setAppletOrder(const QString &order)
emit appletOrderChanged(); emit appletOrderChanged();
} }
QString LayoutManager::lockedZoomApplets() const QList<int> LayoutManager::lockedZoomApplets() const
{ {
return m_lockedZoomApplets; return m_lockedZoomApplets;
} }
void LayoutManager::setLockedZoomApplets(const QString &applets) void LayoutManager::setLockedZoomApplets(const QList<int> &applets)
{ {
if (m_lockedZoomApplets == applets) { if (m_lockedZoomApplets == applets) {
return; return;
@ -102,12 +106,27 @@ void LayoutManager::setLockedZoomApplets(const QString &applets)
emit lockedZoomAppletsChanged(); emit lockedZoomAppletsChanged();
} }
QString LayoutManager::userBlocksColorizingApplets() const QList<int> LayoutManager::order() const
{
return m_order;
}
void LayoutManager::setOrder(const QList<int> &order)
{
if (m_order == order) {
return;
}
m_order = order;
emit orderChanged();
}
QList<int> LayoutManager::userBlocksColorizingApplets() const
{ {
return m_userBlocksColorizingApplets; return m_userBlocksColorizingApplets;
} }
void LayoutManager::setUserBlocksColorizingApplets(const QString &applets) void LayoutManager::setUserBlocksColorizingApplets(const QList<int> &applets)
{ {
if (m_userBlocksColorizingApplets == applets) { if (m_userBlocksColorizingApplets == applets) {
return; return;
@ -117,6 +136,23 @@ void LayoutManager::setUserBlocksColorizingApplets(const QString &applets)
emit userBlocksColorizingAppletsChanged(); emit userBlocksColorizingAppletsChanged();
} }
QList<int> LayoutManager::appletsInScheduledDestruction() const
{
return m_appletsInScheduledDestruction.keys();
}
void LayoutManager::setAppletInScheduledDestruction(const int &id, const bool &enabled)
{
if (m_appletsInScheduledDestruction.contains(id) && !enabled) {
m_appletsInScheduledDestruction.remove(id);
emit appletsInScheduledDestructionChanged();
} else if (!m_appletsInScheduledDestruction.contains(id) && enabled) {
m_appletsInScheduledDestruction[id] = appletItem(id);
emit appletsInScheduledDestructionChanged();
}
}
QObject *LayoutManager::plasmoid() const QObject *LayoutManager::plasmoid() const
{ {
return m_plasmoid; return m_plasmoid;
@ -227,6 +263,20 @@ void LayoutManager::setMetrics(QQuickItem *metrics)
emit metricsChanged(); emit metricsChanged();
} }
void LayoutManager::updateOrder()
{
Latte::Types::Alignment alignment = static_cast<Latte::Types::Alignment>((*m_configuration)["alignment"].toInt());
auto nextorder = m_appletOrder;
if (alignment==Latte::Types::Justify) {
nextorder.insert(m_splitterPosition-1, JUSTIFYSPLITTERID);
nextorder.insert(m_splitterPosition2-1, JUSTIFYSPLITTERID);
}
setOrder(nextorder);
}
void LayoutManager::onRootItemChanged() void LayoutManager::onRootItemChanged()
{ {
if (!m_rootItem) { if (!m_rootItem) {
@ -239,6 +289,9 @@ void LayoutManager::onRootItemChanged()
int createJustifySplitterIndex = rootMetaObject->indexOfMethod("createJustifySplitter()"); int createJustifySplitterIndex = rootMetaObject->indexOfMethod("createJustifySplitter()");
m_createJustifySplitterMethod = rootMetaObject->method(createJustifySplitterIndex); m_createJustifySplitterMethod = rootMetaObject->method(createJustifySplitterIndex);
int initAppletContainerIndex = rootMetaObject->indexOfMethod("initAppletContainer(QVariant,QVariant)");
m_initAppletContainerMethod = rootMetaObject->method(initAppletContainerIndex);
} }
bool LayoutManager::isValidApplet(const int &id) bool LayoutManager::isValidApplet(const int &id)
@ -263,18 +316,13 @@ bool LayoutManager::isValidApplet(const int &id)
//! Actions //! Actions
void LayoutManager::restore() void LayoutManager::restore()
{ {
QStringList appletStringIdsOrder = (*m_configuration)["appletOrder"].toString().split(";"); QList<int> appletIdsOrder = toIntList((*m_configuration)["appletOrder"].toString());
QList<QObject *> applets = m_plasmoid->property("applets").value<QList<QObject *>>(); QList<QObject *> applets = m_plasmoid->property("applets").value<QList<QObject *>>();
Latte::Types::Alignment alignment = static_cast<Latte::Types::Alignment>((*m_configuration)["alignment"].toInt()); Latte::Types::Alignment alignment = static_cast<Latte::Types::Alignment>((*m_configuration)["alignment"].toInt());
int splitterPosition = (*m_configuration)["splitterPosition"].toInt(); int splitterPosition = (*m_configuration)["splitterPosition"].toInt();
int splitterPosition2 = (*m_configuration)["splitterPosition2"].toInt(); int splitterPosition2 = (*m_configuration)["splitterPosition2"].toInt();
QList<int> appletIdsOrder;
for (int i=0; i<appletStringIdsOrder.count(); ++i) {
appletIdsOrder << appletStringIdsOrder[i].toInt();
}
if (alignment==Latte::Types::Justify) { if (alignment==Latte::Types::Justify) {
if (splitterPosition!=-1 && splitterPosition2!=-1) { if (splitterPosition!=-1 && splitterPosition2!=-1) {
appletIdsOrder.insert(splitterPosition-1, -1); appletIdsOrder.insert(splitterPosition-1, -1);
@ -318,12 +366,12 @@ void LayoutManager::restore()
} }
} }
QStringList orphanedIds; QList<int> orphanedIds;
for(int i=0; i<applets.count(); ++i) { for(int i=0; i<applets.count(); ++i) {
uint id = applets[i]->property("id").toUInt(); uint id = applets[i]->property("id").toUInt();
if (!appletIdsOrder.contains(id)) { if (!appletIdsOrder.contains(id)) {
orphanedIds << QString::number(id); orphanedIds << id;
} }
} }
@ -346,7 +394,7 @@ void LayoutManager::restore()
} }
qDebug() << "org.kde.latte ::: applets found :: " << applets.count() << " : " << appletIdsOrder << " :: " << splitterPosition << " : " << splitterPosition2 << " | " << alignment; qDebug() << "org.kde.latte ::: applets found :: " << applets.count() << " : " << appletIdsOrder << " :: " << splitterPosition << " : " << splitterPosition2 << " | " << alignment;
qDebug() << "org.kde.latte ::: applets orphaned added in the end:: " << orphanedIds.join(";"); qDebug() << "org.kde.latte ::: applets orphaned added in the end:: " << orphanedIds;
qDebug() << "org.kde.latte ::: applets recorded order :: " << appletIdsOrder; qDebug() << "org.kde.latte ::: applets recorded order :: " << appletIdsOrder;
qDebug() << "org.kde.latte ::: applets produced order ?? " << validateAppletsOrder; qDebug() << "org.kde.latte ::: applets produced order ?? " << validateAppletsOrder;
@ -393,49 +441,61 @@ void LayoutManager::restore()
} }
restoreOptions(); restoreOptions();
save(); save(); //will restore also a valid applets ids order
cleanupOptions();
initSaveConnections();
m_hasRestoredAppletsTimer.start(); m_hasRestoredAppletsTimer.start();
} }
void LayoutManager::initSaveConnections()
{
connect(this, &LayoutManager::appletOrderChanged, this, &LayoutManager::cleanupOptions);
connect(this, &LayoutManager::splitterPositionChanged, this, &LayoutManager::saveOptions);
connect(this, &LayoutManager::splitterPosition2Changed, this, &LayoutManager::saveOptions);
connect(this, &LayoutManager::lockedZoomAppletsChanged, this, &LayoutManager::saveOptions);
connect(this, &LayoutManager::userBlocksColorizingAppletsChanged, this, &LayoutManager::saveOptions);
}
void LayoutManager::restoreOptions() void LayoutManager::restoreOptions()
{ {
restoreOption("lockZoom"); restoreOption(ISAPPLETLOCKEDOPTION);
restoreOption("userBlocksColorizing"); restoreOption(ISCOLORINGBLOCKEDOPTION);
} }
void LayoutManager::restoreOption(const char *option) void LayoutManager::restoreOption(const char *option)
{ {
QStringList applets = (*m_configuration)[m_option[option]].toString().split(";"); QList<int> applets = toIntList((*m_configuration)[m_option[option]].toString());
if (!m_startLayout || !m_mainLayout || !m_endLayout) { if (option == ISAPPLETLOCKEDOPTION) {
return; setLockedZoomApplets(applets);
} else if (option == ISCOLORINGBLOCKEDOPTION) {
setUserBlocksColorizingApplets(applets);
} }
}
for (int i=0; i<=2; ++i) { bool LayoutManager::isJustifySplitter(const QQuickItem *item) const
QQuickItem *layout = (i==0 ? m_startLayout : (i==1 ? m_mainLayout : m_endLayout)); {
return item && (item->property("isInternalViewSplitter").toBool() == true);
}
for (int j=layout->childItems().count()-1; j>=0; --j) { bool LayoutManager::isMasqueradedIndex(const int &x, const int &y)
QQuickItem *item = layout->childItems()[j]; {
bool issplitter = item->property("isInternalViewSplitter").toBool(); return (x==y && x<=MASQUERADEDINDEXTOPOINTBASE && y<=MASQUERADEDINDEXTOPOINTBASE);
if (!issplitter) { }
QVariant appletVariant = item->property("applet");
if (!appletVariant.isValid()) {
continue;
}
QObject *applet = appletVariant.value<QObject *>(); int LayoutManager::masquearadedIndex(const int &x, const int &y)
uint id = applet->property("id").toUInt(); {
return qAbs(x - MASQUERADEDINDEXTOPOINTBASE);
}
item->setProperty(option, applets.contains(QString::number(id))); QPoint LayoutManager::indexToMasquearadedPoint(const int &index)
} {
} return QPoint(MASQUERADEDINDEXTOPOINTBASE-index, MASQUERADEDINDEXTOPOINTBASE-index);
}
} }
void LayoutManager::save() void LayoutManager::save()
{ {
QStringList appletIds; QList<int> appletIds;
int startChilds{0}; int startChilds{0};
for(int i=0; i<m_startLayout->childItems().count(); ++i) { for(int i=0; i<m_startLayout->childItems().count(); ++i) {
@ -457,7 +517,7 @@ void LayoutManager::save()
if (id>0) { if (id>0) {
startChilds++; startChilds++;
appletIds << QString::number(id); appletIds << id;
} }
} }
} }
@ -482,7 +542,7 @@ void LayoutManager::save()
if (id>0) { if (id>0) {
mainChilds++; mainChilds++;
appletIds << QString::number(id); appletIds << id;
} }
} }
} }
@ -507,7 +567,7 @@ void LayoutManager::save()
if (id>0) { if (id>0) {
endChilds++; endChilds++;
appletIds << QString::number(id); appletIds << id;
} }
} }
} }
@ -530,56 +590,67 @@ void LayoutManager::save()
//(*m_configuration)["splitterPosition2"] = QVariant(startChilds + 1 + mainChilds + 1); //(*m_configuration)["splitterPosition2"] = QVariant(startChilds + 1 + mainChilds + 1);
//(*m_configuration)["appletOrder"] = appletIds.join(";"); //(*m_configuration)["appletOrder"] = appletIds.join(";");
setAppletOrder(appletIds.join(";")); setAppletOrder(appletIds);
//qDebug() << "org.kde.latte saving applets:: " << appletOrder() << " :: " << splitterPosition() << " : " << splitterPosition2();
saveOptions(); //! publish updated order
updateOrder();
//! save applet order
QString appletsserialized = toStr(appletIds);
if ((*m_configuration)["appletOrder"] != appletsserialized) {
m_configuration->insert("appletOrder", appletsserialized);
emit m_configuration->valueChanged("appletOrder", appletsserialized);
}
} }
void LayoutManager::saveOptions() void LayoutManager::saveOptions()
{ {
saveOption("lockZoom"); QString lockedserialized = toStr(m_lockedZoomApplets);
saveOption("userBlocksColorizing"); if ((*m_configuration)[m_option[ISAPPLETLOCKEDOPTION]] != lockedserialized) {
//qDebug() << "org.kde.latte saving properties:: " << lockedZoomApplets() << " :: " << userBlocksColorizingApplets(); m_configuration->insert(m_option[ISAPPLETLOCKEDOPTION], lockedserialized);
emit m_configuration->valueChanged(m_option[ISAPPLETLOCKEDOPTION], lockedserialized);
}
QString colorsserialized = toStr(m_userBlocksColorizingApplets);
if ((*m_configuration)[m_option[ISCOLORINGBLOCKEDOPTION]] != colorsserialized) {
m_configuration->insert(m_option[ISCOLORINGBLOCKEDOPTION], colorsserialized);
emit m_configuration->valueChanged(m_option[ISCOLORINGBLOCKEDOPTION], colorsserialized);
}
if ((*m_configuration)["splitterPosition"] != m_splitterPosition) {
m_configuration->insert("splitterPosition", m_splitterPosition);
emit m_configuration->valueChanged(m_option["splitterPosition"], m_splitterPosition);
}
if ((*m_configuration)["splitterPosition2"] != m_splitterPosition2) {
m_configuration->insert("splitterPosition2", m_splitterPosition2);
emit m_configuration->valueChanged(m_option["splitterPosition2"], m_splitterPosition2);
}
} }
void LayoutManager::saveOption(const char *option) void LayoutManager::setOption(const int &appletId, const QString &property, const QVariant &value)
{ {
if (!m_startLayout || !m_mainLayout || !m_endLayout) { if (property == ISAPPLETLOCKEDOPTION) {
return; bool enabled = value.toBool();
}
QStringList applets; if (enabled && !m_lockedZoomApplets.contains(appletId)) {
QList<int> applets = m_lockedZoomApplets; applets << appletId;
for (int i=0; i<=2; ++i) { setLockedZoomApplets(applets);
QQuickItem *layout = (i==0 ? m_startLayout : (i==1 ? m_mainLayout : m_endLayout)); } else if (!enabled && m_lockedZoomApplets.contains(appletId)) {
QList<int> applets = m_lockedZoomApplets; applets.removeAll(appletId);
for (int j=0; j<layout->childItems().count(); ++j) { setLockedZoomApplets(applets);
QQuickItem *item = layout->childItems()[j];
bool issplitter = item->property("isInternalViewSplitter").toBool();
if (issplitter) {
continue;
}
bool enabled = item->property(option).toBool();
if (enabled) {
QVariant appletVariant = item->property("applet");
if (!appletVariant.isValid()) {
continue;
}
QObject *applet = appletVariant.value<QObject *>();
uint id = applet->property("id").toUInt();
applets << QString::number(id);
}
} }
} } else if (property == ISCOLORINGBLOCKEDOPTION) {
bool enabled = value.toBool();
if (option == "lockZoom") { if (enabled && !m_userBlocksColorizingApplets.contains(appletId)) {
setLockedZoomApplets(applets.join(";")); QList<int> applets = m_userBlocksColorizingApplets; applets << appletId;
} else if (option == "userBlocksColorizing") { setUserBlocksColorizingApplets(applets);
setUserBlocksColorizingApplets(applets.join(";")); } else if (!enabled && m_userBlocksColorizingApplets.contains(appletId)) {
QList<int> applets = m_userBlocksColorizingApplets; applets.removeAll(appletId);
setUserBlocksColorizingApplets(applets);
}
} }
} }
@ -591,7 +662,6 @@ void LayoutManager::insertBefore(QQuickItem *hoveredItem, QQuickItem *item)
item->setParentItem(hoveredItem->parentItem()); item->setParentItem(hoveredItem->parentItem());
item->stackBefore(hoveredItem); item->stackBefore(hoveredItem);
} }
void LayoutManager::insertAfter(QQuickItem *hoveredItem, QQuickItem *item) void LayoutManager::insertAfter(QQuickItem *hoveredItem, QQuickItem *item)
@ -611,7 +681,12 @@ void LayoutManager::insertAtLayoutTail(QQuickItem *layout, QQuickItem *item)
} }
if (layout->childItems().count() > 0) { if (layout->childItems().count() > 0) {
insertBefore(layout->childItems()[0], item); if (layout == m_endLayout && isJustifySplitter(layout->childItems()[0])) {
//! this way we ignore the justify splitter in start layout
insertAfter(layout->childItems()[0], item);
} else {
insertBefore(layout->childItems()[0], item);
}
return; return;
} }
@ -627,7 +702,12 @@ void LayoutManager::insertAtLayoutHead(QQuickItem *layout, QQuickItem *item)
int count = layout->childItems().count(); int count = layout->childItems().count();
if (count > 0) { if (count > 0) {
insertAfter(layout->childItems()[count-1], item); if (layout == m_startLayout && isJustifySplitter(layout->childItems()[count-1])) {
//! this way we ignore the justify splitter in end layout
insertBefore(layout->childItems()[count-1], item);
} else {
insertAfter(layout->childItems()[count-1], item);
}
return; return;
} }
@ -692,8 +772,8 @@ bool LayoutManager::insertAtLayoutCoordinates(QQuickItem *layout, QQuickItem *it
} }
if (hovered) { if (hovered) {
if ((vertical && y < (hovered->y() + hovered->height()/2)) || if ((vertical && y < (hovered->y() + hovered->height()/2) && hovered->height() > 1) ||
(horizontal && x < hovered->x() + hovered->width()/2)) { (horizontal && x < (hovered->x() + hovered->width()/2) && hovered->width() > 1)) {
insertBefore(hovered, item); insertBefore(hovered, item);
} else { } else {
insertAfter(hovered, item); insertAfter(hovered, item);
@ -705,6 +785,202 @@ bool LayoutManager::insertAtLayoutCoordinates(QQuickItem *layout, QQuickItem *it
return false; return false;
} }
QQuickItem *LayoutManager::firstSplitter()
{
for(int i=0; i<m_startLayout->childItems().count(); ++i) {
QQuickItem *item = m_startLayout->childItems()[i];
bool isInternalSplitter = item->property("isInternalViewSplitter").toBool();
if (isInternalSplitter) {
return item;
}
}
for(int i=0; i<m_mainLayout->childItems().count(); ++i) {
QQuickItem *item = m_mainLayout->childItems()[i];
bool isInternalSplitter = item->property("isInternalViewSplitter").toBool();
if (isInternalSplitter) {
return item;
}
}
for(int i=0; i<m_endLayout->childItems().count(); ++i) {
QQuickItem *item = m_endLayout->childItems()[i];
bool isInternalSplitter = item->property("isInternalViewSplitter").toBool();
if (isInternalSplitter) {
return item;
}
}
return nullptr;
}
QQuickItem *LayoutManager::lastSplitter()
{
for(int i=m_endLayout->childItems().count()-1; i>=0; --i) {
QQuickItem *item = m_endLayout->childItems()[i];
bool isInternalSplitter = item->property("isInternalViewSplitter").toBool();
if (isInternalSplitter) {
return item;
}
}
for(int i=m_mainLayout->childItems().count()-1; i>=0; --i) {
QQuickItem *item = m_mainLayout->childItems()[i];
bool isInternalSplitter = item->property("isInternalViewSplitter").toBool();
if (isInternalSplitter) {
return item;
}
}
for(int i=m_endLayout->childItems().count()-1; i>=0; --i) {
QQuickItem *item = m_endLayout->childItems()[i];
bool isInternalSplitter = item->property("isInternalViewSplitter").toBool();
if (isInternalSplitter) {
return item;
}
}
return nullptr;
}
QQuickItem *LayoutManager::appletItemInLayout(QQuickItem *layout, const int &id)
{
if (!layout) {
return nullptr;
}
for(int i=0; i<layout->childItems().count(); ++i) {
QQuickItem *item = layout->childItems()[i];
bool isInternalSplitter = item->property("isInternalViewSplitter").toBool();
if (!isInternalSplitter) {
QVariant appletVariant = item->property("applet");
if (!appletVariant.isValid()) {
continue;
}
QObject *applet = appletVariant.value<QObject *>();
if (!applet) {
continue;
}
int tempid = applet->property("id").toInt();
if (id == tempid) {
return item;
}
}
}
return nullptr;
}
QQuickItem *LayoutManager::appletItem(const int &id)
{
QQuickItem *item = appletItemInLayout(m_mainLayout, id);
if (!item) {
item = appletItemInLayout(m_startLayout, id);
}
if (!item) {
item = appletItemInLayout(m_endLayout, id);
}
return item;
}
int LayoutManager::dndSpacerIndex()
{
if (m_dndSpacer->parentItem() != m_startLayout
&& m_dndSpacer->parentItem() != m_mainLayout
&& m_dndSpacer->parentItem() != m_endLayout) {
return -1;
}
Latte::Types::Alignment alignment = static_cast<Latte::Types::Alignment>((*m_configuration)["alignment"].toInt());
int index = -1;
if (alignment == Latte::Types::Justify) {
for(int i=0; i<m_startLayout->childItems().count(); ++i) {
index++;
QQuickItem *item = m_startLayout->childItems()[i];
if (item == m_dndSpacer) {
return index;
}
}
}
for(int i=0; i<m_mainLayout->childItems().count(); ++i) {
index++;
QQuickItem *item = m_mainLayout->childItems()[i];
if (item == m_dndSpacer) {
return index;
}
}
if (alignment == Latte::Types::Justify) {
for(int i=0; i<m_endLayout->childItems().count(); ++i) {
index++;
QQuickItem *item = m_endLayout->childItems()[i];
if (item == m_dndSpacer) {
return index;
}
}
}
return -1;
}
void LayoutManager::requestAppletsOrder(const QList<int> &order)
{
Latte::Types::Alignment alignment = static_cast<Latte::Types::Alignment>((*m_configuration)["alignment"].toInt());
QQuickItem *nextlayout = alignment != Latte::Types::Justify ? m_mainLayout : m_startLayout;
QQuickItem *previousitem = nullptr;
int addedsplitters{0};
for (int i=0; i<order.count(); ++i) {
QQuickItem *currentitem;
if (alignment != Latte::Types::Justify || order[i] != JUSTIFYSPLITTERID) {
currentitem = appletItem(order[i]);
} else if (alignment == Latte::Types::Justify && order[i] == JUSTIFYSPLITTERID) {
currentitem = addedsplitters == 0 ? firstSplitter() : lastSplitter();
addedsplitters++;
}
if (previousitem) {
insertAfter(previousitem, currentitem);
} else {
insertAtLayoutTail(nextlayout, currentitem);
}
previousitem = currentitem;
if (alignment == Latte::Types::Justify && order[i] == JUSTIFYSPLITTERID) {
nextlayout = addedsplitters == 1 ? m_mainLayout : m_endLayout;
}
}
if (alignment == Latte::Types::Justify) {
moveAppletsBasedOnJustifyAlignment();
save();
}
}
void LayoutManager::requestAppletsInLockedZoom(const QList<int> &applets)
{
setLockedZoomApplets(applets);
}
void LayoutManager::requestAppletsDisabledColoring(const QList<int> &applets)
{
setUserBlocksColorizingApplets(applets);
}
int LayoutManager::distanceFromTail(QQuickItem *layout, QPointF pos) const int LayoutManager::distanceFromTail(QQuickItem *layout, QPointF pos) const
{ {
return (int)qSqrt(qPow(pos.x() - 0, 2) + qPow(pos.y() - 0, 2)); return (int)qSqrt(qPow(pos.x() - 0, 2) + qPow(pos.y() - 0, 2));
@ -786,10 +1062,91 @@ void LayoutManager::insertAtCoordinates(QQuickItem *item, const int &x, const in
} }
} }
void LayoutManager::cleanupOptions()
{
auto inlockedzoomcurrent = m_lockedZoomApplets;
QList<int> inlockedzoomnext;
for(int i=0; i<inlockedzoomcurrent.count(); ++i) {
if (m_appletOrder.contains(inlockedzoomcurrent[i])) {
inlockedzoomnext << inlockedzoomcurrent[i];
}
}
setLockedZoomApplets(inlockedzoomnext);
auto disabledcoloringcurrent = m_userBlocksColorizingApplets;
QList <int> disabledcoloringnext;
for(int i=0; i<disabledcoloringcurrent.count(); ++i) {
if (m_appletOrder.contains(disabledcoloringcurrent[i])) {
disabledcoloringnext << disabledcoloringcurrent[i];
}
}
setUserBlocksColorizingApplets(disabledcoloringnext);
}
void LayoutManager::addAppletItem(QObject *applet, int index)
{
if (!m_startLayout || !m_mainLayout || !m_endLayout || index < 0) {
return;
}
Latte::Types::Alignment alignment = static_cast<Latte::Types::Alignment>((*m_configuration)["alignment"].toInt());
QVariant appletItemVariant;
QVariant appletVariant; appletVariant.setValue(applet);
m_createAppletItemMethod.invoke(m_rootItem, Q_RETURN_ARG(QVariant, appletItemVariant), Q_ARG(QVariant, appletVariant));
QQuickItem *aitem = appletItemVariant.value<QQuickItem *>();
if (m_dndSpacer) {
m_dndSpacer->setParentItem(m_rootItem);
}
QQuickItem *previousItem{nullptr};
if (index >= m_order.count()) {
// do nothing it should be added at the end
} else {
if (alignment == Latte::Types::Justify && m_order[index] == JUSTIFYSPLITTERID) {
if (index<m_splitterPosition2-1) {
previousItem = firstSplitter();
} else {
previousItem = lastSplitter();
}
} else {
previousItem = appletItem(m_order[index]);
}
}
if (previousItem) {
insertBefore(previousItem, aitem);
} else {
if (alignment == Latte::Types::Justify) {
insertAtLayoutHead(m_endLayout, aitem);
} else {
insertAtLayoutHead(m_mainLayout, aitem);
}
}
if (alignment == Latte::Types::Justify) {
moveAppletsBasedOnJustifyAlignment();
}
save();
}
void LayoutManager::addAppletItem(QObject *applet, int x, int y) void LayoutManager::addAppletItem(QObject *applet, int x, int y)
{ {
if (!m_startLayout || !m_mainLayout || !m_endLayout) { if (!m_startLayout || !m_mainLayout || !m_endLayout) {
return; return;
}
PlasmaQuick::AppletQuickItem *aqi = qobject_cast<PlasmaQuick::AppletQuickItem *>(applet);
if (aqi && aqi->applet() && !aqi->applet()->destroyed() && m_appletsInScheduledDestruction.contains(aqi->applet()->id())) {
int id = aqi->applet()->id();
QVariant appletContainerVariant; appletContainerVariant.setValue(m_appletsInScheduledDestruction[id]);
QVariant appletVariant; appletVariant.setValue(applet);
m_initAppletContainerMethod.invoke(m_rootItem, Q_ARG(QVariant, appletContainerVariant), Q_ARG(QVariant, appletVariant));
setAppletInScheduledDestruction(id, false);
return;
} }
QVariant appletItemVariant; QVariant appletItemVariant;
@ -827,31 +1184,85 @@ void LayoutManager::removeAppletItem(QObject *applet)
return; return;
} }
for (int i=0; i<=2; ++i) { PlasmaQuick::AppletQuickItem *aqi = qobject_cast<PlasmaQuick::AppletQuickItem *>(applet);
QQuickItem *layout = (i==0 ? m_startLayout : (i==1 ? m_mainLayout : m_endLayout));
if (!aqi) {
return;
}
int id = aqi->applet()->id();
if (aqi->applet() && aqi->applet()->destroyed() && !m_appletsInScheduledDestruction.contains(id)/*this way we really delete it in the end*/) {
setAppletInScheduledDestruction(id, true);
return;
}
destroyAppletContainer(aqi->applet());
}
void LayoutManager::destroyAppletContainer(QObject *applet)
{
if (!applet || !m_startLayout || !m_mainLayout || !m_endLayout) {
return;
}
Plasma::Applet *ca = qobject_cast<Plasma::Applet *>(applet);
if (!ca) {
qDebug() << "org.kde.destroy destroying applet could not succeed Plasma/Applet was not identified...";
return;
}
int id = ca->id();
bool destroyed{false};
if (m_appletsInScheduledDestruction.contains(id)) {
//! when deleted from scheduled destruction
m_appletsInScheduledDestruction[id]->setVisible(false);
m_appletsInScheduledDestruction[id]->setParentItem(m_rootItem);
m_appletsInScheduledDestruction[id]->deleteLater();
setAppletInScheduledDestruction(id, false);
destroyed = true;
} else {
//! when deleted directly for Plasma::Applet destruction e.g. synced applets
for (int i=0; i<=2; ++i) {
if (destroyed) {
break;
}
QQuickItem *layout = (i==0 ? m_startLayout : (i==1 ? m_mainLayout : m_endLayout));
if (layout->childItems().count() > 0) {
int size = layout->childItems().count();
for (int j=size-1; j>=0; --j) {
QQuickItem *item = layout->childItems()[j];
bool issplitter = item->property("isInternalViewSplitter").toBool();
if (issplitter) {
continue;
}
if (layout->childItems().count() > 0) {
int size = layout->childItems().count();
for (int j=size-1; j>=0; --j) {
QQuickItem *item = layout->childItems()[j];
bool issplitter = item->property("isInternalViewSplitter").toBool();
if (!issplitter) {
QVariant appletVariant = item->property("applet"); QVariant appletVariant = item->property("applet");
if (!appletVariant.isValid()) { if (!appletVariant.isValid()) {
continue; continue;
} }
QObject *currentapplet = appletVariant.value<QObject *>(); PlasmaQuick::AppletQuickItem *appletitem = appletVariant.value<PlasmaQuick::AppletQuickItem *>();
if (currentapplet == applet) { if (appletitem && appletitem->applet() == applet) {
item->setVisible(false);
item->setParentItem(m_rootItem);
item->deleteLater(); item->deleteLater();
return; destroyed = true;
break;
} }
} }
} }
} }
} }
save(); if (destroyed) {
save();
}
} }
void LayoutManager::reorderSplitterInStartLayout() void LayoutManager::reorderSplitterInStartLayout()
@ -1103,5 +1514,30 @@ void LayoutManager::moveAppletsBasedOnJustifyAlignment()
} }
} }
QList<int> LayoutManager::toIntList(const QString &serialized)
{
QList<int> list;
QStringList items = serialized.split(";");
items.removeAll(QString());
for(const auto &item: items) {
list << item.toInt();
}
return list;
}
QString LayoutManager::toStr(const QList<int> &list)
{
QString str;
QStringList strlist;
for(const auto &num: list) {
strlist << QString::number(num);
}
return strlist.join(";");
}
} }
} }

View File

@ -23,7 +23,7 @@ namespace Containment{
class LayoutManager : public QObject class LayoutManager : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QObject *plasmoidObj READ plasmoid() WRITE setPlasmoid NOTIFY plasmoidChanged) Q_PROPERTY(QObject *plasmoidObj READ plasmoid() WRITE setPlasmoid NOTIFY plasmoidChanged)
Q_PROPERTY(QQuickItem *rootItem READ rootItem WRITE setRootItem NOTIFY rootItemChanged) Q_PROPERTY(QQuickItem *rootItem READ rootItem WRITE setRootItem NOTIFY rootItemChanged)
@ -41,20 +41,26 @@ class LayoutManager : public QObject
//! appletsOrder is not stored when needed and applets additions/removals are not valid on next startup //! appletsOrder is not stored when needed and applets additions/removals are not valid on next startup
Q_PROPERTY(int splitterPosition READ splitterPosition NOTIFY splitterPositionChanged) Q_PROPERTY(int splitterPosition READ splitterPosition NOTIFY splitterPositionChanged)
Q_PROPERTY(int splitterPosition2 READ splitterPosition2 NOTIFY splitterPosition2Changed) Q_PROPERTY(int splitterPosition2 READ splitterPosition2 NOTIFY splitterPosition2Changed)
Q_PROPERTY(QString appletOrder READ appletOrder NOTIFY appletOrderChanged) Q_PROPERTY(QList<int> appletOrder READ appletOrder NOTIFY appletOrderChanged)
Q_PROPERTY(QString lockedZoomApplets READ lockedZoomApplets NOTIFY lockedZoomAppletsChanged) Q_PROPERTY(QList<int> order READ order NOTIFY orderChanged) //includes also splitters
Q_PROPERTY(QString userBlocksColorizingApplets READ userBlocksColorizingApplets NOTIFY userBlocksColorizingAppletsChanged) Q_PROPERTY(QList<int> lockedZoomApplets READ lockedZoomApplets NOTIFY lockedZoomAppletsChanged)
Q_PROPERTY(QList<int> userBlocksColorizingApplets READ userBlocksColorizingApplets NOTIFY userBlocksColorizingAppletsChanged)
Q_PROPERTY(QList<int> appletsInScheduledDestruction READ appletsInScheduledDestruction NOTIFY appletsInScheduledDestructionChanged)
public: public:
static const int JUSTIFYSPLITTERID = -10;
LayoutManager(QObject *parent = nullptr); LayoutManager(QObject *parent = nullptr);
bool hasRestoredApplets() const; bool hasRestoredApplets() const;
int splitterPosition() const; int splitterPosition() const;
int splitterPosition2() const; int splitterPosition2() const;
QString appletOrder() const; QList<int> appletOrder() const;
QString lockedZoomApplets() const; QList<int> lockedZoomApplets() const;
QString userBlocksColorizingApplets() const; QList<int> order() const;
QList<int> userBlocksColorizingApplets() const;
QList<int> appletsInScheduledDestruction() const;
QObject *plasmoid() const; QObject *plasmoid() const;
void setPlasmoid(QObject *plasmoid); void setPlasmoid(QObject *plasmoid);
@ -81,8 +87,10 @@ public slots:
Q_INVOKABLE void restore(); Q_INVOKABLE void restore();
Q_INVOKABLE void save(); Q_INVOKABLE void save();
Q_INVOKABLE void saveOptions(); Q_INVOKABLE void saveOptions();
Q_INVOKABLE void setOption(const int &appletId, const QString &property, const QVariant &value);
Q_INVOKABLE void addAppletItem(QObject *applet, int x, int y); Q_INVOKABLE void addAppletItem(QObject *applet, int x, int y);
Q_INVOKABLE void addAppletItem(QObject *applet, int index);
Q_INVOKABLE void removeAppletItem(QObject *applet); Q_INVOKABLE void removeAppletItem(QObject *applet);
Q_INVOKABLE void addJustifySplittersInMainLayout(); Q_INVOKABLE void addJustifySplittersInMainLayout();
@ -92,8 +100,21 @@ public slots:
Q_INVOKABLE void insertAfter(QQuickItem *hoveredItem, QQuickItem *item); Q_INVOKABLE void insertAfter(QQuickItem *hoveredItem, QQuickItem *item);
Q_INVOKABLE void insertAtCoordinates(QQuickItem *item, const int &x, const int &y); Q_INVOKABLE void insertAtCoordinates(QQuickItem *item, const int &x, const int &y);
Q_INVOKABLE int dndSpacerIndex();
Q_INVOKABLE bool isMasqueradedIndex(const int &x, const int &y);
Q_INVOKABLE int masquearadedIndex(const int &x, const int &y);
Q_INVOKABLE QPoint indexToMasquearadedPoint(const int &index);
void requestAppletsOrder(const QList<int> &order);
void requestAppletsInLockedZoom(const QList<int> &applets);
void requestAppletsDisabledColoring(const QList<int> &applets);
void setAppletInScheduledDestruction(const int &id, const bool &enabled);
signals: signals:
void appletOrderChanged(); void appletOrderChanged();
void appletsInScheduledDestructionChanged();
void hasRestoredAppletsChanged(); void hasRestoredAppletsChanged();
void plasmoidChanged(); void plasmoidChanged();
void rootItemChanged(); void rootItemChanged();
@ -103,6 +124,7 @@ signals:
void mainLayoutChanged(); void mainLayoutChanged();
void metricsChanged(); void metricsChanged();
void orderChanged();
void splitterPositionChanged(); void splitterPositionChanged();
void splitterPosition2Changed(); void splitterPosition2Changed();
void startLayoutChanged(); void startLayoutChanged();
@ -112,36 +134,58 @@ private slots:
void onRootItemChanged(); void onRootItemChanged();
void destroyJustifySplitters(); void destroyJustifySplitters();
void updateOrder();
void cleanupOptions();
private: private:
void restoreOptions(); void restoreOptions();
void restoreOption(const char *option); void restoreOption(const char *option);
void saveOption(const char *option); void saveOption(const char *option);
void destroyAppletContainer(QObject *applet);
void initSaveConnections();
void insertAtLayoutTail(QQuickItem *layout, QQuickItem *item); void insertAtLayoutTail(QQuickItem *layout, QQuickItem *item);
void insertAtLayoutHead(QQuickItem *layout, QQuickItem *item); void insertAtLayoutHead(QQuickItem *layout, QQuickItem *item);
void setSplitterPosition(const int &position); void setSplitterPosition(const int &position);
void setSplitterPosition2(const int &position); void setSplitterPosition2(const int &position);
void setAppletOrder(const QString &order); void setAppletOrder(const QList<int> &order);
void setLockedZoomApplets(const QString &applets); void setOrder(const QList<int> &order);
void setUserBlocksColorizingApplets(const QString &applets); void setLockedZoomApplets(const QList<int> &applets);
void setUserBlocksColorizingApplets(const QList<int> &applets);
void reorderSplitterInStartLayout(); void reorderSplitterInStartLayout();
void reorderSplitterInEndLayout(); void reorderSplitterInEndLayout();
bool isJustifySplitter(const QQuickItem *item) const;
bool isValidApplet(const int &id); bool isValidApplet(const int &id);
bool insertAtLayoutCoordinates(QQuickItem *layout, QQuickItem *item, int x, int y); bool insertAtLayoutCoordinates(QQuickItem *layout, QQuickItem *item, int x, int y);
int distanceFromTail(QQuickItem *layout, QPointF pos) const; int distanceFromTail(QQuickItem *layout, QPointF pos) const;
int distanceFromHead(QQuickItem *layout, QPointF pos) const; int distanceFromHead(QQuickItem *layout, QPointF pos) const;
QQuickItem *firstSplitter();
QQuickItem *lastSplitter();
QQuickItem *appletItem(const int &id);
QQuickItem *appletItemInLayout(QQuickItem *layout, const int &id);
QList<int> toIntList(const QString &serialized);
QString toStr(const QList<int> &list);
private: private:
//! This is needed in order to overcome plasma frameworks limitations and instead of adding dropped widgets
//! based on coordinates, to be able to add them directly at the correct index
static const int MASQUERADEDINDEXTOPOINTBASE = -23456;
int m_splitterPosition{-1}; int m_splitterPosition{-1};
int m_splitterPosition2{-1}; int m_splitterPosition2{-1};
QString m_appletOrder; QList<int> m_appletOrder;
QString m_lockedZoomApplets; QList<int> m_lockedZoomApplets;
QString m_userBlocksColorizingApplets; QList<int> m_order;
QList<int> m_userBlocksColorizingApplets;
QQuickItem *m_rootItem{nullptr}; QQuickItem *m_rootItem{nullptr};
QQuickItem *m_dndSpacer{nullptr}; QQuickItem *m_dndSpacer{nullptr};
@ -154,8 +198,11 @@ private:
QObject *m_plasmoid{nullptr}; QObject *m_plasmoid{nullptr};
KDeclarative::ConfigPropertyMap *m_configuration{nullptr}; KDeclarative::ConfigPropertyMap *m_configuration{nullptr};
QHash<int, QQuickItem *> m_appletsInScheduledDestruction;
QMetaMethod m_createAppletItemMethod; QMetaMethod m_createAppletItemMethod;
QMetaMethod m_createJustifySplitterMethod; QMetaMethod m_createJustifySplitterMethod;
QMetaMethod m_initAppletContainerMethod;
bool m_hasRestoredApplets{false}; bool m_hasRestoredApplets{false};
QTimer m_hasRestoredAppletsTimer; QTimer m_hasRestoredAppletsTimer;

View File

@ -32,14 +32,8 @@ const int ACTIVELAYOUTSINDEX = 1;
const int CURRENTLAYOUTSINDEX = 2; const int CURRENTLAYOUTSINDEX = 2;
const int ACTIONSALWAYSSHOWN = 3; const int ACTIONSALWAYSSHOWN = 3;
const int LAYOUTMENUINDEX = 4; const int LAYOUTMENUINDEX = 4;
const int VIEWTYPEINDEX = 5; const int VIEWLAYOUTINDEX = 5;
const int VIEWLAYOUTINDEX = 6; const int VIEWTYPEINDEX = 6;
enum ViewType
{
DockView = 0,
PanelView
};
enum LayoutsMemoryUsage enum LayoutsMemoryUsage
{ {
@ -240,22 +234,25 @@ QList<QAction *> Menu::contextualActions()
m_actionsAlwaysShown = m_data[ACTIONSALWAYSSHOWN].split(";;"); m_actionsAlwaysShown = m_data[ACTIONSALWAYSSHOWN].split(";;");
ViewType viewType{static_cast<ViewType>((m_data[VIEWTYPEINDEX]).toInt())}; updateViewData();
const QString configureActionText = (viewType == DockView) ? i18n("&Edit Dock...") : i18n("&Edit Panel..."); QString configureActionText = (m_view.type == DockView) ? i18n("&Edit Dock...") : i18n("&Edit Panel...");
if (m_view.isCloned) {
configureActionText = (m_view.type == DockView) ? i18n("&Edit Original Dock...") : i18n("&Edit Original Panel...");
}
m_actions[Latte::Data::ContextMenu::EDITVIEWACTION]->setText(configureActionText); m_actions[Latte::Data::ContextMenu::EDITVIEWACTION]->setText(configureActionText);
const QString duplicateActionText = (viewType == DockView) ? i18n("&Duplicate Dock") : i18n("&Duplicate Panel"); const QString duplicateActionText = (m_view.type == DockView) ? i18n("&Duplicate Dock") : i18n("&Duplicate Panel");
m_actions[Latte::Data::ContextMenu::DUPLICATEVIEWACTION]->setText(duplicateActionText); m_actions[Latte::Data::ContextMenu::DUPLICATEVIEWACTION]->setText(duplicateActionText);
const QString exportTemplateText = (viewType == DockView) ? i18n("E&xport Dock as Template") : i18n("E&xport Panel as Template"); const QString exportTemplateText = (m_view.type == DockView) ? i18n("E&xport Dock as Template") : i18n("E&xport Panel as Template");
m_actions[Latte::Data::ContextMenu::EXPORTVIEWTEMPLATEACTION]->setText(exportTemplateText); m_actions[Latte::Data::ContextMenu::EXPORTVIEWTEMPLATEACTION]->setText(exportTemplateText);
m_activeLayoutNames = m_data[ACTIVELAYOUTSINDEX].split(";;"); m_activeLayoutNames = m_data[ACTIVELAYOUTSINDEX].split(";;");
const QString moveText = (viewType == DockView) ? i18n("&Move Dock To Layout") : i18n("&Move Panel To Layout"); const QString moveText = (m_view.type == DockView) ? i18n("&Move Dock To Layout") : i18n("&Move Panel To Layout");
m_actions[Latte::Data::ContextMenu::MOVEVIEWACTION]->setText(moveText); m_actions[Latte::Data::ContextMenu::MOVEVIEWACTION]->setText(moveText);
const QString removeActionText = (viewType == DockView) ? i18n("&Remove Dock") : i18n("&Remove Panel"); const QString removeActionText = (m_view.type == DockView) ? i18n("&Remove Dock") : i18n("&Remove Panel");
m_actions[Latte::Data::ContextMenu::REMOVEVIEWACTION]->setText(removeActionText); m_actions[Latte::Data::ContextMenu::REMOVEVIEWACTION]->setText(removeActionText);
updateVisibleActions(); updateVisibleActions();
@ -302,6 +299,13 @@ void Menu::updateVisibleActions()
m_actions[Latte::Data::ContextMenu::EDITVIEWACTION]->setVisible(!configuring); m_actions[Latte::Data::ContextMenu::EDITVIEWACTION]->setVisible(!configuring);
m_actions[Latte::Data::ContextMenu::SECTIONACTION]->setVisible(true); m_actions[Latte::Data::ContextMenu::SECTIONACTION]->setVisible(true);
if (m_view.isCloned) {
m_actions[Latte::Data::ContextMenu::DUPLICATEVIEWACTION]->setVisible(false);
m_actions[Latte::Data::ContextMenu::EXPORTVIEWTEMPLATEACTION]->setVisible(false);
m_actions[Latte::Data::ContextMenu::MOVEVIEWACTION]->setVisible(false);
m_actions[Latte::Data::ContextMenu::REMOVEVIEWACTION]->setVisible(false);
}
// because sometimes they are disabled unexpectedly, we should reenable them // because sometimes they are disabled unexpectedly, we should reenable them
for(auto actionName: m_actions.keys()) { for(auto actionName: m_actions.keys()) {
m_actions[actionName]->setEnabled(true); m_actions[actionName]->setEnabled(true);
@ -411,6 +415,14 @@ void Menu::populateMoveToLayouts()
} }
} }
void Menu::updateViewData()
{
QStringList vdata = m_data[VIEWTYPEINDEX].split(";;");
m_view.type = static_cast<ViewType>((vdata[0]).toInt());
m_view.isCloned = vdata[1].toInt();
m_view.clonesCount = vdata[2].toInt();
}
void Menu::populateViewTemplates() void Menu::populateViewTemplates()
{ {
m_addViewMenu->clear(); m_addViewMenu->clear();

View File

@ -15,12 +15,24 @@
class QAction; class QAction;
class QMenu; class QMenu;
enum ViewType
{
DockView = 0,
PanelView
};
struct LayoutInfo { struct LayoutInfo {
QString layoutName; QString layoutName;
bool isBackgroundFileIcon; bool isBackgroundFileIcon;
QString iconName; QString iconName;
}; };
struct ViewTypeData {
ViewType type{ViewType::DockView};
bool isCloned{true};
int clonesCount{0};
};
class Menu : public Plasma::ContainmentActions class Menu : public Plasma::ContainmentActions
{ {
Q_OBJECT Q_OBJECT
@ -40,6 +52,7 @@ private Q_SLOTS:
void quitApplication(); void quitApplication();
void requestConfiguration(); void requestConfiguration();
void requestWidgetExplorer(); void requestWidgetExplorer();
void updateViewData();
void updateVisibleActions(); void updateVisibleActions();
void addView(QAction *action); void addView(QAction *action);
@ -53,6 +66,8 @@ private:
QStringList m_actionsAlwaysShown; QStringList m_actionsAlwaysShown;
QStringList m_activeLayoutNames; QStringList m_activeLayoutNames;
ViewTypeData m_view;
QHash<QString, QAction *> m_actions; QHash<QString, QAction *> m_actions;
QMenu *m_addViewMenu{nullptr}; QMenu *m_addViewMenu{nullptr};

View File

@ -14,6 +14,7 @@ AbilityDefinition.MyView {
readonly property bool isBridgeActive: bridge !== null readonly property bool isBridgeActive: bridge !== null
isReady: ref.myView.isReady isReady: ref.myView.isReady
groupId: ref.myView.groupId
inNormalState: ref.myView.inNormalState inNormalState: ref.myView.inNormalState

View File

@ -11,7 +11,9 @@ import org.kde.latte.core 0.2 as LatteCore
import "./myview" as MyViewTypes import "./myview" as MyViewTypes
Item { Item {
property int groupId: -1
property bool isReady: false property bool isReady: false
property bool inNormalState: true property bool inNormalState: true

View File

@ -22,6 +22,7 @@ AbilityDefinition.MyView {
readonly property Item publicApi: Item { readonly property Item publicApi: Item {
readonly property alias isReady: apis.isReady readonly property alias isReady: apis.isReady
readonly property alias groupId: apis.groupId
readonly property alias inNormalState: apis.inNormalState readonly property alias inNormalState: apis.inNormalState

View File

@ -81,6 +81,14 @@ public:
GlobalLaunchers = 2 GlobalLaunchers = 2
}; };
Q_ENUM(LaunchersGroup); Q_ENUM(LaunchersGroup);
enum ScreensGroup
{
SingleScreenGroup = 0,
AllScreensGroup,
AllSecondaryScreensGroup
};
Q_ENUM(ScreensGroup)
}; };
}//end of namespace }//end of namespace

View File

@ -23,6 +23,7 @@ AbilityClient.AppletAbilities {
bridge: _abilityContainer.bridge bridge: _abilityContainer.bridge
layout: _abilityContainer.layout layout: _abilityContainer.layout
tasksModel: _abilityContainer.tasksModel tasksModel: _abilityContainer.tasksModel
view: _abilityContainer.myView
} }
//! local properties //! local properties

View File

@ -31,8 +31,11 @@ Item {
property bool __isLoadedDuringViewStartup: false property bool __isLoadedDuringViewStartup: false
property int group: LatteCore.Types.UniqueLaunchers property int group: LatteCore.Types.UniqueLaunchers
property int groupId: view && group === LatteCore.Types.UniqueLaunchers ? view.groupId : -1
property Item bridge: null property Item bridge: null
property Item layout: null property Item layout: null
property Item view: null
property QtObject tasksModel: null property QtObject tasksModel: null
readonly property LaunchersPart.Syncer syncer: LaunchersPart.Syncer{} readonly property LaunchersPart.Syncer syncer: LaunchersPart.Syncer{}
@ -87,8 +90,10 @@ Item {
} }
function addLauncher(launcherUrl) { function addLauncher(launcherUrl) {
if (bridge && !inUniqueGroup()) { if (bridge) {
bridge.launchers.host.addSyncedLauncher(launchers.group, bridge.launchers.host.addSyncedLauncher(syncer.clientId,
launchers.group,
launchers.groupId,
launcherUrl); launcherUrl);
} else { } else {
_launchers.tasksModel.requestAddLauncher(launcherUrl); _launchers.tasksModel.requestAddLauncher(launcherUrl);
@ -115,8 +120,10 @@ Item {
function addDroppedLaunchers(urls) { function addDroppedLaunchers(urls) {
//! inform synced docks for new dropped launchers //! inform synced docks for new dropped launchers
if (bridge && !launchers.inUniqueGroup()) { if (bridge) {
bridge.launchers.host.addDroppedLaunchers(launchers.group, bridge.launchers.host.addDroppedLaunchers(syncer.clientId,
launchers.group,
launchers.groupId,
urls); urls);
} else { } else {
urls.forEach(function (item) { urls.forEach(function (item) {
@ -143,8 +150,10 @@ Item {
} }
function removeLauncher(launcherUrl) { function removeLauncher(launcherUrl) {
if (bridge && !inUniqueGroup()) { if (bridge) {
bridge.launchers.host.removeSyncedLauncher(launchers.group, bridge.launchers.host.removeSyncedLauncher(syncer.clientId,
launchers.group,
launchers.groupId,
launcherUrl); launcherUrl);
} else { } else {
_launchers.launcherInRemoving(launcherUrl); _launchers.launcherInRemoving(launcherUrl);
@ -154,8 +163,10 @@ Item {
} }
function addLauncherToActivity(launcherUrl, activityId) { function addLauncherToActivity(launcherUrl, activityId) {
if (bridge && !inUniqueGroup()) { if (bridge) {
bridge.launchers.host.addSyncedLauncherToActivity(launchers.group, bridge.launchers.host.addSyncedLauncherToActivity(syncer.clientId,
launchers.group,
launchers.groupId,
launcherUrl, launcherUrl,
activityId); activityId);
} else { } else {
@ -169,8 +180,10 @@ Item {
} }
function removeLauncherFromActivity(launcherUrl, activityId) { function removeLauncherFromActivity(launcherUrl, activityId) {
if (bridge && !inUniqueGroup()) { if (bridge) {
bridge.launchers.host.removeSyncedLauncherFromActivity(launchers.group, bridge.launchers.host.removeSyncedLauncherFromActivity(syncer.clientId,
launchers.group,
launchers.groupId,
launcherUrl, launcherUrl,
activityId); activityId);
} else { } else {
@ -183,9 +196,10 @@ Item {
} }
function validateSyncedLaunchersOrder() { function validateSyncedLaunchersOrder() {
if (bridge && !_launchers.inUniqueGroup()) { if (bridge) {
bridge.launchers.host.validateSyncedLaunchersOrder(syncer.clientId, bridge.launchers.host.validateSyncedLaunchersOrder(syncer.clientId,
group, launchers.group,
launchers.groupId,
currentShownLauncherList()); currentShownLauncherList());
} else { } else {
/*validator.stop(); /*validator.stop();
@ -372,13 +386,13 @@ Item {
} else if (_launchers.inGlobalGroup()) { } else if (_launchers.inGlobalGroup()) {
bridge.launchers.host.setUniversalLaunchers(_launchers.tasksModel.launcherList); bridge.launchers.host.setUniversalLaunchers(_launchers.tasksModel.launcherList);
} }
if (inDraggingPhase) {
_launchers.validateSyncedLaunchersOrder();
}
} else { } else {
plasmoid.configuration.launchers59 = _launchers.tasksModel.launcherList; plasmoid.configuration.launchers59 = _launchers.tasksModel.launcherList;
} }
if (inDraggingPhase) {
_launchers.validateSyncedLaunchersOrder();
}
} else if (!appletAbilities.myView.isReady) { } else if (!appletAbilities.myView.isReady) {
// This way we make sure that a delayed view.layout initialization does not store irrelevant launchers from different // This way we make sure that a delayed view.layout initialization does not store irrelevant launchers from different
// group to UNIQUE launchers group // group to UNIQUE launchers group

View File

@ -12,8 +12,11 @@ import org.kde.latte.core 0.2 as LatteCore
Item { Item {
id:_syncer id:_syncer
property bool isBlocked: false property bool isBlocked: false
readonly property bool isActive: bridge !== null && bridge.launchers.host !==null && group !== LatteCore.Types.UniqueLaunchers readonly property bool isActive: bridge !== null && bridge.launchers.host !==null
readonly property int clientId: plasmoid.id readonly property int clientId: plasmoid.id
// used to identify launchers that need to be synced event though their launchers group type
// does not support it e.g. taskmanagers synced in different screens
readonly property int syncedGroupId: _launchers.groupId
//! Connections //! Connections
Component.onCompleted: { Component.onCompleted: {

View File

@ -84,9 +84,15 @@ PlasmaComponents.Page {
screensCount = universalSettings.screens.length; screensCount = universalSettings.screens.length;
screensModel.clear(); screensModel.clear();
var primary = {name: i18n("Follow Primary Screen"), icon: 'favorite'}; var primary = {name: i18n("On Primary Screen"), icon: 'favorite'};
screensModel.append(primary); screensModel.append(primary);
var allscreens = {name: i18n("On All Screens"), icon: 'favorite'};
screensModel.append(allscreens);
var allsecscreens = {name: i18n("On All Secondary Screens"), icon: 'favorite'};
screensModel.append(allsecscreens);
//check if the screen exists, it is used in cases Latte is moving //check if the screen exists, it is used in cases Latte is moving
//the view automatically to primaryScreen in order for the user //the view automatically to primaryScreen in order for the user
//to has always a view with tasks shown //to has always a view with tasks shown
@ -107,8 +113,12 @@ PlasmaComponents.Page {
screensModel.append(scr); screensModel.append(scr);
} }
if (latteView.onPrimary) { if (latteView.onPrimary && latteView.screensGroup === LatteCore.Types.SingleScreenGroup) {
screenCmb.currentIndex = 0; screenCmb.currentIndex = 0;
} else if (latteView.screensGroup === LatteCore.Types.AllScreensGroup) {
screenCmb.currentIndex = 1;
} else if (latteView.screensGroup === LatteCore.Types.AllSecondaryScreensGroup) {
screenCmb.currentIndex = 2;
} else { } else {
screenCmb.currentIndex = screenCmb.findScreen(latteView.positioner.currentScreenName); screenCmb.currentIndex = screenCmb.findScreen(latteView.positioner.currentScreenName);
} }
@ -135,10 +145,14 @@ PlasmaComponents.Page {
Component.onCompleted: screenRow.updateScreens(); Component.onCompleted: screenRow.updateScreens();
onActivated: { onActivated: {
if (index === 0) { if (index === 0) { // primary
latteView.positioner.setNextLocation("", "{primary-screen}", PlasmaCore.Types.Floating, LatteCore.Types.NoneAlignment); latteView.positioner.setNextLocation("", LatteCore.Types.SingleScreenGroup, "{primary-screen}", PlasmaCore.Types.Floating, LatteCore.Types.NoneAlignment);
} else if (index>0 && (index !== findScreen(latteView.positioner.currentScreenName) || latteView.onPrimary)) { } else if (index === 1) { // all screens
latteView.positioner.setNextLocation("", textAt(index), PlasmaCore.Types.Floating, LatteCore.Types.NoneAlignment); latteView.positioner.setNextLocation("", LatteCore.Types.AllScreensGroup, "{primary-screen}", PlasmaCore.Types.Floating, LatteCore.Types.NoneAlignment);
} else if (index === 2) { // all secondary screens
latteView.positioner.setNextLocation("", LatteCore.Types.AllSecondaryScreensGroup, "", PlasmaCore.Types.Floating, LatteCore.Types.NoneAlignment);
} else if (index>2 && (index !== findScreen(latteView.positioner.currentScreenName) || latteView.onPrimary)) {// explicit screen
latteView.positioner.setNextLocation("", LatteCore.Types.SingleScreenGroup, textAt(index), PlasmaCore.Types.Floating, LatteCore.Types.NoneAlignment);
} }
} }
@ -184,7 +198,7 @@ PlasmaComponents.Page {
onClicked: { onClicked: {
//! clicked event is more wayland friendly because it release focus from the button before hiding the window //! clicked event is more wayland friendly because it release focus from the button before hiding the window
if (viewConfig.isReady && plasmoid.location !== edge) { if (viewConfig.isReady && plasmoid.location !== edge) {
latteView.positioner.setNextLocation("", "", edge, LatteCore.Types.NoneAlignment); latteView.positioner.setNextLocation("", latteView.screensGroup, "", edge, LatteCore.Types.NoneAlignment);
} }
} }
} }
@ -203,7 +217,7 @@ PlasmaComponents.Page {
onClicked: { onClicked: {
//! clicked event is more wayland friendly because it release focus from the button before hiding the window //! clicked event is more wayland friendly because it release focus from the button before hiding the window
if (viewConfig.isReady && plasmoid.location !== edge) { if (viewConfig.isReady && plasmoid.location !== edge) {
latteView.positioner.setNextLocation("", "", edge, LatteCore.Types.NoneAlignment); latteView.positioner.setNextLocation("", latteView.screensGroup, "", edge, LatteCore.Types.NoneAlignment);
} }
} }
} }
@ -222,7 +236,7 @@ PlasmaComponents.Page {
onClicked: { onClicked: {
//! clicked event is more wayland friendly because it release focus from the button before hiding the window //! clicked event is more wayland friendly because it release focus from the button before hiding the window
if (viewConfig.isReady && plasmoid.location !== edge) { if (viewConfig.isReady && plasmoid.location !== edge) {
latteView.positioner.setNextLocation("", "", edge, LatteCore.Types.NoneAlignment); latteView.positioner.setNextLocation("", latteView.screensGroup, "", edge, LatteCore.Types.NoneAlignment);
} }
} }
} }
@ -241,7 +255,7 @@ PlasmaComponents.Page {
onClicked: { onClicked: {
//! clicked event is more wayland friendly because it release focus from the button before hiding the window //! clicked event is more wayland friendly because it release focus from the button before hiding the window
if (viewConfig.isReady && plasmoid.location !== edge) { if (viewConfig.isReady && plasmoid.location !== edge) {
latteView.positioner.setNextLocation("", "", edge, LatteCore.Types.NoneAlignment); latteView.positioner.setNextLocation("", latteView.screensGroup, "", edge, LatteCore.Types.NoneAlignment);
} }
} }
} }
@ -286,7 +300,7 @@ PlasmaComponents.Page {
onPressedChanged: { onPressedChanged: {
if (pressed) { if (pressed) {
latteView.positioner.setNextLocation("", "", PlasmaCore.Types.Floating, alignment); latteView.positioner.setNextLocation("", latteView.screensGroup, "", PlasmaCore.Types.Floating, alignment);
} }
} }
} }
@ -303,7 +317,7 @@ PlasmaComponents.Page {
onPressedChanged: { onPressedChanged: {
if (pressed) { if (pressed) {
latteView.positioner.setNextLocation("", "", PlasmaCore.Types.Floating, alignment); latteView.positioner.setNextLocation("", latteView.screensGroup, "", PlasmaCore.Types.Floating, alignment);
} }
} }
} }
@ -320,7 +334,7 @@ PlasmaComponents.Page {
onPressedChanged: { onPressedChanged: {
if (pressed) { if (pressed) {
latteView.positioner.setNextLocation("", "", PlasmaCore.Types.Floating, alignment); latteView.positioner.setNextLocation("", latteView.screensGroup, "", PlasmaCore.Types.Floating, alignment);
} }
} }
} }
@ -338,7 +352,7 @@ PlasmaComponents.Page {
onPressedChanged: { onPressedChanged: {
if (pressed) { if (pressed) {
latteView.positioner.setNextLocation("", "", PlasmaCore.Types.Floating, alignment); latteView.positioner.setNextLocation("", latteView.screensGroup, "", PlasmaCore.Types.Floating, alignment);
} }
} }
} }

View File

@ -48,7 +48,8 @@ Item {
hoverEnabled: true hoverEnabled: true
onDoubleClicked: { onDoubleClicked: {
if (!delegate.pendingUninstall) { if (!delegate.pendingUninstall) {
widgetExplorer.addApplet(pluginName) widgetExplorer.addApplet(pluginName);
latteView.extendedInterface.appletCreated(pluginName);
} }
} }
onEntered: delegate.GridView.view.currentIndex = index onEntered: delegate.GridView.view.currentIndex = index

View File

@ -83,7 +83,8 @@ Item {
function addCurrentApplet() { function addCurrentApplet() {
var pluginName = list.currentItem ? list.currentItem.pluginName : "" var pluginName = list.currentItem ? list.currentItem.pluginName : ""
if (pluginName) { if (pluginName) {
widgetExplorer.addApplet(pluginName) widgetExplorer.addApplet(pluginName);
latteView.extendedInterface.appletCreated(pluginName);
} }
} }