1
0
mirror of https://github.com/KDE/latte-dock.git synced 2025-01-18 02:04:32 +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
{
QStringList result;

View File

@ -23,7 +23,11 @@ class Screen : public Generic
public:
static constexpr const char* SERIALIZESPLITTER = ":::";
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* ONALLSCREENSNAME = "{all-screens}";
static constexpr const char* ONALLSECONDARYSCREENSNAME = "{all-secondary-screens}";
Screen();
Screen(Screen &&o);
@ -43,6 +47,8 @@ public:
bool operator==(const Screen &rhs) const;
bool operator!=(const Screen &rhs) const;
bool isScreensGroup() const;
void init(const QString &screenId, const QString &serialized);
QString serialize() const;

View File

@ -8,6 +8,8 @@
namespace Latte {
namespace Data {
const int View::ISCLONEDNULL = -1;
View::View()
: Generic()
{
@ -19,8 +21,10 @@ View::View(View &&o)
isMoveOrigin(o.isMoveOrigin),
isMoveDestination(o.isMoveDestination),
onPrimary(o.onPrimary),
isClonedFrom(o.isClonedFrom),
screen(o.screen),
screenEdgeMargin(o.screenEdgeMargin),
screensGroup(o.screensGroup),
maxLength(o.maxLength),
edge(o.edge),
alignment(o.alignment),
@ -40,8 +44,10 @@ View::View(const View &o)
isMoveOrigin(o.isMoveOrigin),
isMoveDestination(o.isMoveDestination),
onPrimary(o.onPrimary),
isClonedFrom(o.isClonedFrom),
screen(o.screen),
screenEdgeMargin(o.screenEdgeMargin),
screensGroup(o.screensGroup),
maxLength(o.maxLength),
edge(o.edge),
alignment(o.alignment),
@ -68,8 +74,10 @@ View &View::operator=(const View &rhs)
isMoveOrigin = rhs.isMoveOrigin;
isMoveDestination = rhs.isMoveDestination;
onPrimary = rhs.onPrimary;
isClonedFrom = rhs.isClonedFrom;
screen = rhs.screen;
screenEdgeMargin = rhs.screenEdgeMargin,
screenEdgeMargin = rhs.screenEdgeMargin;
screensGroup = rhs.screensGroup;
maxLength = rhs.maxLength;
edge = rhs.edge;
alignment = rhs.alignment;
@ -93,8 +101,10 @@ View &View::operator=(View &&rhs)
isMoveOrigin = rhs.isMoveOrigin;
isMoveDestination = rhs.isMoveDestination;
onPrimary = rhs.onPrimary;
isClonedFrom = rhs.isClonedFrom;
screen = rhs.screen;
screenEdgeMargin = rhs.screenEdgeMargin,
screenEdgeMargin = rhs.screenEdgeMargin;
screensGroup = rhs.screensGroup;
maxLength = rhs.maxLength;
edge = rhs.edge;
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*/
//&& (isMoveDestination == rhs.isMoveDestination) /*Disabled because this is not needed in order to track view changes for saving*/
&& (onPrimary == rhs.onPrimary)
&& (isClonedFrom == rhs.isClonedFrom)
&& (screen == rhs.screen)
&& (screenEdgeMargin == rhs.screenEdgeMargin)
&& (screensGroup == rhs.screensGroup)
&& (maxLength == rhs.maxLength)
&& (edge == rhs.edge)
&& (alignment == rhs.alignment)
@ -168,6 +180,21 @@ View::operator QString() const
}
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 += " : ";
result += QString::number(screen);
@ -212,6 +239,16 @@ bool View::isCreated() const
return m_state == IsCreated;
}
bool View::isOriginal() const
{
return !isCloned();
}
bool View::isCloned() const
{
return isClonedFrom != ISCLONEDNULL;
}
bool View::isValid() const
{
return m_state != IsInvalid;

View File

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

View File

@ -90,6 +90,19 @@ ViewsTable ViewsTable::subtracted(const ViewsTable &rhs) const
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)
{
int maxTempId = 0;

View File

@ -38,6 +38,7 @@ public:
bool operator==(const ViewsTable &rhs) const;
bool operator!=(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 "settings/universalsettings.h"
#include "templates/templatesmanager.h"
#include "view/originalview.h"
#include "view/view.h"
#include "view/settings/viewsettingsfactory.h"
#include "view/windowstracker/windowstracker.h"
@ -1192,9 +1193,25 @@ QStringList Corona::contextMenuData(const uint &containmentId)
}
data << layoutsmenu.join(";;");
data << QString::number((int)viewType); //Selected View type
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;
}
@ -1247,7 +1264,14 @@ void Corona::moveViewToLayout(const uint &containmentId, const QString &layoutNa
{
auto view = m_layoutsManager->synchronizer()->viewForContainment((int)containmentId);
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);
}
void CentralLayout::initToCorona(Latte::Corona *corona)
bool CentralLayout::initCorona()
{
if (GenericLayout::initToCorona(corona)) {
if (GenericLayout::initCorona()) {
onSchemeFileChanged();
connect(this, &CentralLayout::disableBordersForMaximizedWindowsChanged,
@ -56,7 +56,10 @@ void CentralLayout::initToCorona(Latte::Corona *corona)
connect(this, &Layout::AbstractLayout::schemeFileChanged, this, &CentralLayout::onSchemeFileChanged);
connect(m_corona->wm()->schemesTracker(), &WindowSystem::Tracker::Schemes::defaultSchemeChanged, this, &CentralLayout::onSchemeFileChanged);
return true;
}
return false;
}
bool CentralLayout::disableBordersForMaximizedWindows() const

View File

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

View File

@ -17,8 +17,10 @@
#include "../layouts/synchronizer.h"
#include "../shortcuts/shortcutstracker.h"
#include "../templates/templatesmanager.h"
#include "../view/view.h"
#include "../view/clonedview.h"
#include "../view/originalview.h"
#include "../view/positioner.h"
#include "../view/view.h"
// Qt
#include <QDebug>
@ -143,7 +145,7 @@ void GenericLayout::setBlockAutomaticLatteViewCreation(bool block)
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()
@ -155,6 +157,16 @@ bool GenericLayout::isCurrent()
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 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;
}
@ -449,6 +467,19 @@ QList<Latte::View *> GenericLayout::latteViews()
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()
{
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()) {
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;
}
qDebug() << "step 1...";
qDebug() << "Adding View:" << containment->id() << "- Step 1...";
if (!Layouts::Storage::self()->isLatteContainment(containment)) {
return;
}
qDebug() << "step 2...";
qDebug() << "Adding View:" << containment->id() << "- Step 2...";
for (auto *dock : m_latteViews) {
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];
if (hasLatteView(containment)) {
return;
}
if (Layouts::Storage::isValid(id) && !onPrimary && !forceOnPrimary) {
qDebug() << "Add view - connector : " << connector;
bool found{false};
qDebug() << "Adding View:" << containment->id() << "- Step 3...";
if (m_corona->screenPool()->hasScreenId(id)) {
for (const auto scr : qGuiApp->screens()) {
if (scr && scr->name() == connector) {
found = true;
nextScreen = scr;
break;
}
}
QScreen *nextScreen{qGuiApp->primaryScreen()};
Data::View viewdata = Layouts::Storage::self()->view(this, containment);
viewdata.screen = Layouts::Storage::self()->expectedViewScreenId(m_corona, viewdata);
QString nextScreenName = m_corona->screenPool()->hasScreenId(viewdata.screen) ? m_corona->screenPool()->connector(viewdata.screen) : "";
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) {
qDebug() << "Rejected : adding explicit view, screen not available ! : " << connector;
if (!foundNextExplicitScreen) {
qDebug().noquote() << "Adding View:" << viewdata.id << "- Rejected because Screen is not available :: " << nextScreenName;
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
//! of the window... This of course is also used during
//! 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);
}
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->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);
//! 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
//! the copied dock under X11
@ -959,8 +944,6 @@ void GenericLayout::addView(Plasma::Containment *containment, bool forceOnPrimar
latteView->show();
//}
m_latteViews[containment] = latteView;
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;
}
m_corona = corona;
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();
connect(m_corona, &Plasma::Corona::containmentAdded, this, &GenericLayout::addContainment);
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::runningActivitiesChanged, this, &GenericLayout::updateLastUsedActivity);
connect(m_corona, &Plasma::Corona::containmentAdded, this, &GenericLayout::addContainment);
connect(this, &GenericLayout::lastConfigViewForChanged, m_corona->layoutsManager(), &Layouts::Manager::lastConfigViewChangedFrom);
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::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;
}
@ -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) {
return false;
@ -1254,119 +1254,55 @@ bool GenericLayout::mapContainsId(const Layout::ViewsMap *map, uint viewId) cons
return false;
}
//! screen name, location, containmentId
Layout::ViewsMap GenericLayout::validViewsMap(Layout::ViewsMap *occupiedMap)
QString GenericLayout::mapScreenName(const ViewsMap *map, uint viewId) const
{
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;
if (!m_corona) {
return map;
}
if (occupiedMap != nullptr) {
map = (*occupiedMap);
}
QString prmScreenName = qGuiApp->primaryScreen()->name();
//! first step: primary docks must be placed in primary screen free edges
for (const auto containment : m_containments) {
if (Layouts::Storage::self()->isLatteContainment(containment)) {
int screenId{Layouts::Storage::IDNULL};
if (Layouts::Storage::self()->isLatteContainment(containment)
&& !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 (latteViewExists(containment)) {
screenId = m_latteViews[containment]->positioner()->currentScreenId();
if (view.onPrimary) {
map[prmScreenName][view.edge] << containment->id();
} else {
screenId = containment->screen();
QString expScreenName = m_corona->screenPool()->connector(view.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) {
map[prmScreenName][location] << containment->id();
} else {
QString expScreenName = m_corona->screenPool()->connector(screenId);
if (m_corona->screenPool()->isScreenActive(screenId)) {
map[expScreenName][location] << containment->id();
if (m_corona->screenPool()->isScreenActive(view.screen)) {
map[expScreenName][view.edge] << 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;
}
//! the central functions that updates loading/unloading latteviews
//! concerning screen changed (for multi-screen setups mainly)
void GenericLayout::syncLatteViewsToScreens(Layout::ViewsMap *occupiedMap)
void GenericLayout::syncLatteViewsToScreens()
{
if (!m_corona) {
return;
@ -1400,11 +1336,7 @@ void GenericLayout::syncLatteViewsToScreens(Layout::ViewsMap *occupiedMap)
}
//! use valid views map based on active screens
Layout::ViewsMap viewsMap = validViewsMap(occupiedMap);
if (occupiedMap != nullptr) {
qDebug() << "Occupied map used :: " << *occupiedMap;
}
Layout::ViewsMap viewsMap = validViewsMap();
QString prmScreenName = qGuiApp->primaryScreen()->name();
@ -1413,14 +1345,8 @@ void GenericLayout::syncLatteViewsToScreens(Layout::ViewsMap *occupiedMap)
//! add views
for (const auto containment : m_containments) {
int screenId = containment->screen();
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);
if (!hasLatteView(containment) && mapContainsId(&viewsMap, containment->id())) {
qDebug() << "syncLatteViewsToScreens: view must be added... for containment:" << containment->id() << " at screen:" << mapScreenName(&viewsMap, containment->id());
addView(containment);
}
}
@ -1430,7 +1356,7 @@ void GenericLayout::syncLatteViewsToScreens(Layout::ViewsMap *occupiedMap)
for (auto view : m_latteViews) {
auto containment = view->containment();
if (containment && !mapContainsId(&viewsMap, containment->id())) {
if (containment && view->isOriginal() && !mapContainsId(&viewsMap, containment->id())) {
viewsToDelete << containment;
}
}
@ -1445,7 +1371,7 @@ void GenericLayout::syncLatteViewsToScreens(Layout::ViewsMap *occupiedMap)
//! reconsider views
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 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();
@ -1607,7 +1533,7 @@ void GenericLayout::updateView(const Latte::Data::View &viewData)
}
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;
} else {
//! viewMustBeDeleted

View File

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

View File

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

View File

@ -12,6 +12,7 @@
#include "../lattecorona.h"
#include "../screenpool.h"
#include "../data/errordata.h"
#include "../data/viewdata.h"
#include "../layout/abstractlayout.h"
#include "../view/view.h"
@ -99,13 +100,13 @@ bool Storage::isLatteContainment(const KConfigGroup &group) const
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;
}
for (const auto containment : *layout->containments()) {
for (const auto containment : corona->containments()) {
Plasma::Applet *parentApplet = qobject_cast<Plasma::Applet *>(containment->parent());
if (parentApplet && parentApplet == applet) {
return true;
@ -178,14 +179,14 @@ int Storage::subIdentityIndex(const KConfigGroup &appletGroup) const
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;
}
if (isSubContainment(layout, applet)) {
for (const auto containment : *layout->containments()) {
if (isSubContainment(corona, applet)) {
for (const auto containment : corona->containments()) {
Plasma::Applet *parentApplet = qobject_cast<Plasma::Applet *>(containment->parent());
if (parentApplet && parentApplet == applet) {
return containment;
@ -224,6 +225,8 @@ void Storage::importToCorona(const Layout::GenericLayout *layout)
//! Setting mutable for create a containment
layout->corona()->setImmutability(Plasma::Types::Mutable);
removeAllClonedViews(layout->file());
QString temp1FilePath = m_storageTmpDir.path() + "/" + layout->name() + ".multiple.views";
//! we need to copy first the layout file because the kde cache
//! may not have yet been updated (KSharedConfigPtr)
@ -240,8 +243,9 @@ void Storage::importToCorona(const Layout::GenericLayout *layout)
tempLayoutFile.remove();
}
if (copyFile.exists())
if (copyFile.exists()) {
copyFile.remove();
}
layoutOriginalFile.copy(tempLayoutFilePath);
@ -329,7 +333,7 @@ QString Storage::newUniqueIdsFile(QString originFile, const Layout::GenericLayou
QString currentdestinationname = destinationLayout->name();
QString currentdestinationfile = "";
if (!destinationLayout->isActive()) {
if (!destinationLayout->hasCorona()) {
currentdestinationfile = destinationLayout->file();
}
@ -344,7 +348,7 @@ QString Storage::newUniqueIdsFile(QString originFile, const Layout::GenericLayou
//! BEGIN updating the ids in the temp file
QStringList allIds;
if (destinationLayout->isActive()) {
if (destinationLayout->hasCorona()) {
allIds << destinationLayout->corona()->containmentsIds();
allIds << destinationLayout->corona()->appletsIds();
} 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
investigate_conts.group(cId).writeEntry("layoutId", destinationLayout->name());
} else {
@ -560,6 +564,7 @@ void Storage::syncToLayoutFile(const Layout::GenericLayout *layout, bool removeL
}
filePtr->reparseConfiguration();
removeAllClonedViews(layout->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);
auto newContainments = layout->corona()->importLayout(KConfigGroup(filePtr, ""));
qDebug() << " imported containments ::: " << newContainments.length();
QList<Plasma::Containment *> importedViews;
for (const auto containment : newContainments) {
if (isLatteContainment(containment)) {
qDebug() << "new latte containment id: " << containment->id();
importedViews << containment;
}
}
@ -609,7 +611,7 @@ Data::View Storage::newView(const Layout::GenericLayout *destinationLayout, cons
qDebug() << "new view for layout";
if (destinationLayout->isActive()) {
if (destinationLayout->hasCorona()) {
//! Setting mutable for create a containment
destinationLayout->corona()->setImmutability(Plasma::Types::Mutable);
}
@ -650,7 +652,7 @@ Data::View Storage::newView(const Layout::GenericLayout *destinationLayout, cons
return Data::View();
}
if (destinationLayout->isActive()) {
if (destinationLayout->hasCorona()) {
//! import views for active layout
QList<Plasma::Containment *> importedViews = importLayoutFile(destinationLayout, temp2File);
@ -732,6 +734,7 @@ bool Storage::exportTemplate(const QString &originFile, const QString &destinati
KConfigGroup layoutSettingsGrp(destFilePtr, "LayoutSettings");
clearExportedLayoutSettings(layoutSettingsGrp);
destFilePtr->reparseConfiguration();
removeAllClonedViews(destinationFile);
return true;
}
@ -828,6 +831,7 @@ bool Storage::exportTemplate(const Layout::GenericLayout *layout, Plasma::Contai
KConfigGroup layoutSettingsGrp(destFilePtr, "LayoutSettings");
clearExportedLayoutSettings(layoutSettingsGrp);
destFilePtr->reparseConfiguration();
removeAllClonedViews(destinationFile);
return true;
}
@ -1271,7 +1275,7 @@ Data::AppletsTable Storage::plugins(const Layout::GenericLayout *layout, const i
}
for (auto applet : containment->applets()) {
if (isSubContainment(layout, applet)) {
if (isSubContainment(layout->corona(), applet)) {
validcontainmentids << subContainmentId(applet->config());
}
}
@ -1426,6 +1430,51 @@ bool Storage::hasContainment(const Layout::GenericLayout *layout, const int &id)
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
{
@ -1505,8 +1554,10 @@ Data::View Storage::view(const KConfigGroup &containmentGroup)
vdata.id = containmentGroup.name();
vdata.name = containmentGroup.readEntry("name", QString());
vdata.isActive = false;
vdata.screensGroup = static_cast<Latte::Types::ScreensGroup>(containmentGroup.readEntry("screensGroup", (int)Latte::Types::SingleScreenGroup));
vdata.onPrimary = containmentGroup.readEntry("onPrimary", true);
vdata.screen = containmentGroup.readEntry("lastScreen", IDNULL);
vdata.isClonedFrom = containmentGroup.readEntry("isClonedFrom", Data::View::ISCLONEDNULL);
vdata.screenEdgeMargin = containmentGroup.group("General").readEntry("screenEdgeMargin", (int)-1);
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("screensGroup", (int)viewData.screensGroup);
viewGroup.writeEntry("onPrimary", viewData.onPrimary);
viewGroup.writeEntry("isClonedFrom", viewData.isClonedFrom);
viewGroup.writeEntry("lastScreen", viewData.screen);
viewGroup.group("General").writeEntry("screenEdgeMargin", viewData.screenEdgeMargin);
viewGroup.writeEntry("location", (int)viewData.edge);
@ -1677,6 +1730,38 @@ QString Storage::storedView(const Layout::GenericLayout *layout, const int &cont
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 vtable;

View File

@ -24,6 +24,7 @@
#include <Plasma/Containment>
namespace Latte {
class Corona;
namespace Layout {
class GenericLayout;
}
@ -51,14 +52,18 @@ public:
bool isWritable(const Layout::GenericLayout *layout) const;
bool isLatteContainment(const Plasma::Containment *containment) 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 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;
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 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 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
//! Check if an applet config group is valid or belongs to removed applet
static bool appletGroupIsValid(const KConfigGroup &appletGroup);
static bool isValid(const int &id);
//! AppletsData Information
Data::Applet metadata(const QString &pluginId);
Data::AppletsTable plugins(const Layout::GenericLayout *layout, const int containmentid = IDNULL);

View File

@ -6,7 +6,6 @@
#include "syncedlaunchers.h"
// local
#include <coretypes.h>
#include "../lattecorona.h"
#include "../layout/centrallayout.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;
if (!layoutName.isEmpty()) {
for(const auto client: m_clients) {
QString cLayoutName = client->property("layoutName").toString();
if (cLayoutName == layoutName) {
items << client;
}
for(const auto client: m_clients) {
QString cLayoutName = layoutName.isEmpty() ? QString() : client->property("layoutName").toString();
int gid = client->property("syncedGroupId").toInt();
if (cLayoutName == layoutName && gid == groupId) {
items << client;
}
} else {
items = m_clients;
}
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) {
return;
if (launcherGroup == Types::UniqueLaunchers && launcherGroupId < 0) {
//! 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 : "";
for(const auto client : clients(lName)) {
if (auto *metaObject = client->metaObject()) {
for(const auto c : clients(lName, senderId, group, launcherGroupId)) {
if (auto *metaObject = c->metaObject()) {
int methodIndex = metaObject->indexOfMethod("addSyncedLauncher(QVariant,QVariant)");
if (methodIndex == -1) {
@ -101,23 +125,18 @@ void SyncedLaunchers::addLauncher(QString layoutName, int launcherGroup, QString
}
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);
if ((Types::LaunchersGroup)group == Types::UniqueLaunchers) {
return;
}
QString lName = (group == Types::LayoutLaunchers) ? layoutName : "";
for(const auto client : clients(lName)) {
if (auto *metaObject = client->metaObject()) {
for(const auto c : clients(lName, senderId, group, launcherGroupId)) {
if (auto *metaObject = c->metaObject()) {
int methodIndex = metaObject->indexOfMethod("removeSyncedLauncher(QVariant,QVariant)");
if (methodIndex == -1) {
@ -126,23 +145,18 @@ void SyncedLaunchers::removeLauncher(QString layoutName, int launcherGroup, QStr
}
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);
if ((Types::LaunchersGroup)group == Types::UniqueLaunchers) {
return;
}
QString lName = (group == Types::LayoutLaunchers) ? layoutName : "";
for(const auto client : clients(lName)) {
if (auto *metaObject = client->metaObject()) {
for(const auto c : clients(lName, senderId, group, launcherGroupId)) {
if (auto *metaObject = c->metaObject()) {
int methodIndex = metaObject->indexOfMethod("addSyncedLauncherToActivity(QVariant,QVariant,QVariant)");
if (methodIndex == -1) {
@ -151,23 +165,18 @@ void SyncedLaunchers::addLauncherToActivity(QString layoutName, int launcherGrou
}
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);
if ((Types::LaunchersGroup)group == Types::UniqueLaunchers) {
return;
}
QString lName = (group == Types::LayoutLaunchers) ? layoutName : "";
for(const auto client : clients(lName)) {
if (auto *metaObject = client->metaObject()) {
for(const auto c : clients(lName, senderId, group, launcherGroupId)) {
if (auto *metaObject = c->metaObject()) {
int methodIndex = metaObject->indexOfMethod("removeSyncedLauncherFromActivity(QVariant,QVariant,QVariant)");
if (methodIndex == -1) {
@ -176,23 +185,18 @@ void SyncedLaunchers::removeLauncherFromActivity(QString layoutName, int launche
}
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);
if ((Types::LaunchersGroup)group == Types::UniqueLaunchers) {
return;
}
QString lName = (group == Types::LayoutLaunchers) ? layoutName : "";
for(const auto client : clients(lName)) {
if (auto *metaObject = client->metaObject()) {
for(const auto c : clients(lName, senderId, group, launcherGroupId)) {
if (auto *metaObject = c->metaObject()) {
int methodIndex = metaObject->indexOfMethod("dropSyncedUrls(QVariant,QVariant)");
if (methodIndex == -1) {
@ -201,26 +205,21 @@ void SyncedLaunchers::urlsDropped(QString layoutName, int launcherGroup, QString
}
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);
if ((Types::LaunchersGroup)group == Types::UniqueLaunchers) {
return;
}
QString lName = (group == Types::LayoutLaunchers) ? layoutName : "";
for(const auto client : clients(lName)) {
uint clientId = client->property("clientId").toUInt();
for(const auto c : clients(lName, senderId, group, launcherGroupId)) {
auto tc = client(senderId);
if (clientId != senderId) {
if (auto *metaObject = client->metaObject()) {
if (c != tc) {
if (auto *metaObject = c->metaObject()) {
int methodIndex = metaObject->indexOfMethod("validateSyncedLaunchersOrder(QVariant,QVariant)");
if (methodIndex == -1) {
@ -229,7 +228,7 @@ void SyncedLaunchers::validateLaunchersOrder(QString layoutName, uint senderId,
}
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
#define SYNCEDLAUNCHERS_H
// local
#include <coretypes.h>
// Qt
#include <QList>
#include <QObject>
@ -42,15 +45,17 @@ public slots:
Q_INVOKABLE void addAbilityClient(QQuickItem *client);
Q_INVOKABLE void removeAbilityClient(QQuickItem *client);
Q_INVOKABLE void addLauncher(QString layoutName, int launcherGroup, QString launcher);
Q_INVOKABLE void removeLauncher(QString layoutName, int launcherGroup, QString launcher);
Q_INVOKABLE void addLauncherToActivity(QString layoutName, int launcherGroup, QString launcher, QString activity);
Q_INVOKABLE void removeLauncherFromActivity(QString layoutName, int launcherGroup, QString launcher, QString activity);
Q_INVOKABLE void urlsDropped(QString layoutName, int launcherGroup, QStringList urls);
Q_INVOKABLE void validateLaunchersOrder(QString layoutName, uint senderId, int launcherGroup, QStringList launchers);
Q_INVOKABLE void addLauncher(QString layoutName, uint senderId, int launcherGroup, int launcherGroupId, QString launcher);
Q_INVOKABLE void removeLauncher(QString layoutName, uint senderId, int launcherGroup, int launcherGroupId, QString launcher);
Q_INVOKABLE void addLauncherToActivity(QString layoutName, uint senderId, int launcherGroup,int launcherGroupId, 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, uint senderId, int launcherGroup, int launcherGroupId, QStringList urls);
Q_INVOKABLE void validateLaunchersOrder(QString layoutName, uint senderId, int launcherGroup, int launcherGroupId, QStringList launchers);
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:
void removeClientObject(QObject *obj);

View File

@ -191,7 +191,9 @@ QStringList Synchronizer::centralLayoutsNames()
QStringList names;
if (m_manager->memoryUsage() == MemoryUsage::SingleLayout) {
names << m_centralLayouts.at(0)->name();
if (m_centralLayouts.count() > 0) {
names << m_centralLayouts.at(0)->name();
}
} else {
for (int i = 0; i < m_centralLayouts.size(); ++i) {
CentralLayout *layout = m_centralLayouts.at(i);
@ -357,6 +359,17 @@ QList<Latte::View *> Synchronizer::currentViews() const
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 *> views;
@ -370,9 +383,12 @@ QList<Latte::View *> Synchronizer::currentViewsWithPlasmaShortcuts() 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
@ -436,7 +452,6 @@ void Synchronizer::addLayout(CentralLayout *layout)
{
if (!m_centralLayouts.contains(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;
unloadLayouts();
//! load the main layout/corona file
//! load the main single layout/corona file
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();
@ -939,8 +963,18 @@ void Synchronizer::syncMultipleLayoutsToActivities()
if (newLayout) {
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) {
emit newLayoutAdded(newLayout->data());

View File

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

View File

@ -168,6 +168,21 @@ int ScreenPool::primaryScreenId() const
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()
{
QMap<int, QString>::const_iterator i;
@ -214,7 +229,7 @@ void ScreenPool::insertScreenMapping(const QString &connector)
int ScreenPool::id(const QString &connector) const
{
QString screenId = m_screensTable.idForName(connector);
return screenId.isEmpty() ? -1 : screenId.toInt();
return screenId.isEmpty() ? NOSCREENID : screenId.toInt();
}
QString ScreenPool::connector(int id) const

View File

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

View File

@ -502,7 +502,7 @@ int screenMaxLength(const QStyleOption &option, const int &maxIconSize)
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;
@ -512,7 +512,7 @@ QRect remainedFromScreenDrawing(const QStyleOption &option, const int &maxIconSi
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();
bool isVertical = (scr_ratio < 1.0);
@ -565,13 +565,24 @@ QRect drawScreen(QPainter *painter, const QStyleOption &option, QRect screenGeom
painter->setPen(pen);
painter->drawRect(screenRect);
//! draw screen base
pen.setWidth(1);
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 basey = screenRect.y() + screenRect.height() + 2;
painter->setRenderHint(QPainter::Antialiasing, false);
painter->drawLine(basex , basey, basex + 8, basey);
// 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);
//! screen icon
QRect remainedFromScreenDrawing(const QStyleOption &option, 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 remainedFromScreenDrawing(const QStyleOption &option, bool drawMultipleScreens, const int &maxIconSize = -1);
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);

View File

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

View File

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

View File

@ -21,6 +21,7 @@
#include "../../layout/centrallayout.h"
#include "../../layouts/importer.h"
#include "../../layouts/manager.h"
#include "../../layouts/storage.h"
#include "../../templates/templatesmanager.h"
#include "../../tools/commontools.h"
@ -658,6 +659,9 @@ void TabLayouts::exportLayoutForBackup()
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);
layoutS.setActivities(QStringList());
layoutS.clearLastUsedActivity();

View File

@ -89,8 +89,8 @@ void CustomMenuItemWidget::paintEvent(QPaintEvent* e)
if (!m_screen.id.isEmpty()) {
int maxiconsize = 26;
remained = Latte::remainedFromScreenDrawing(opt, maxiconsize);
QRect availableScreenRect = Latte::drawScreen(&painter, opt, m_screen.geometry, maxiconsize);
remained = Latte::remainedFromScreenDrawing(opt, m_screen.isScreensGroup(), maxiconsize);
QRect availableScreenRect = Latte::drawScreen(&painter, opt, m_screen.isScreensGroup(), m_screen.geometry, maxiconsize);
if (!m_view.id.isEmpty()) {
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
{
editor->setGeometry(Latte::remainedFromScreenDrawing(option));
editor->setGeometry(Latte::remainedFromScreenDrawing(option, false));
}
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
int maxiconsize = -1; //disabled
remainedrect = Latte::remainedFromScreenDrawing(myOptions, maxiconsize);
QRect availableScreenRect = Latte::drawScreen(painter, myOptions, screen.geometry, maxiconsize, textopacity);
remainedrect = Latte::remainedFromScreenDrawing(myOptions, screen.isScreensGroup(), maxiconsize);
QRect availableScreenRect = Latte::drawScreen(painter, myOptions, screen.isScreensGroup(), screen.geometry, maxiconsize, textopacity);
Latte::drawView(painter, myOptions, view, availableScreenRect, textopacity);
myOptions.rect = remainedrect;

View File

@ -424,16 +424,26 @@ Latte::Data::Screen Views::screenData(const QString &viewId) const
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);
if (m_viewsTable[row].onPrimary && s_screens.containsId(primaryid)) {
return s_screens[primaryid];
Data::Screen scrData = s_screens[0]; //default
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)) {
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
@ -486,14 +496,21 @@ void Views::clearErrorsAndWarnings()
void Views::populateScreens()
{
s_screens.clear();
Data::Screen primary(QString::number(Data::Screen::ONPRIMARYID),
i18nc("primary screen", " - Follow Primary Screen - "));
Data::Screen primary(QString::number(Data::Screen::ONPRIMARYID), i18n(" - On 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 << allscreens;
s_screens << allsecscreens;
int defcount = s_screens.rowCount();
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());
}
}
@ -662,22 +679,30 @@ bool Views::setData(const QModelIndex &index, const QVariant &value, int role)
if (role == Qt::UserRole) {
int screen = value.toString().toInt();
bool onprimary = (screen == Latte::Data::Screen::ONPRIMARYID);
if ((m_viewsTable[row].onPrimary == onprimary) && (m_viewsTable[row].screen == screen)) {
return false;
}
bool onallscreens = (screen == Latte::Data::Screen::ONALLSCREENSID);
bool onallsecscreens = (screen == Latte::Data::Screen::ONALLSECONDARYSCREENSID);
if (onprimary) {
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)) {
//! we need to update screen also in order to not show that there are changes even though
//! they are not any
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);
@ -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))) {
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);
}
@ -838,18 +863,30 @@ QVariant Views::data(const QModelIndex &index, int role) const
break;
case SCREENCOLUMN:
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");
} 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 {
QString scrId = QString::number(m_viewsTable[row].screen);
if (s_screens.containsId(scrId)) {
return s_screens[scrId].name;
} else {
return i18nc("unknown screen", "Unknown : [%1]", scrId);
return i18nc("unknown screen", "Unknown: [%1]", scrId);
}
}
} 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) {
return (isNewView
|| (m_viewsTable[row].onPrimary != o_viewsTable[origviewid].onPrimary)

View File

@ -487,7 +487,7 @@ bool GlobalShortcuts::viewsToHideAreValid()
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
if (sortedViews.count() > 0) {

View File

@ -1,5 +1,6 @@
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}/contextmenu.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}/tasksmodel.cpp
${CMAKE_CURRENT_SOURCE_DIR}/view.cpp
${CMAKE_CURRENT_SOURCE_DIR}/originalview.cpp
${CMAKE_CURRENT_SOURCE_DIR}/visibilitymanager.cpp
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 "../lattecorona.h"
#include "../layout/genericlayout.h"
#include "../layouts/importer.h"
#include "../layouts/storage.h"
#include "../settings/universalsettings.h"
// Qt
#include <QDebug>
#include <QDir>
#include <QLatin1String>
// Plasma
@ -25,6 +27,7 @@
#include <KDesktopFile>
#include <KLocalizedString>
#include <KPluginMetaData>
#include <KDeclarative/ConfigPropertyMap>
namespace Latte {
namespace ViewPart {
@ -41,13 +44,16 @@ ContainmentInterface::ContainmentInterface(Latte::View *parent)
m_appletsExpandedConnectionsTimer.setInterval(2000);
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_view, &View::containmentChanged
, this, [&]() {
if (m_view->containment()) {
connect(m_view->containment(), &Plasma::Containment::appletAdded, this, &ContainmentInterface::onAppletAdded);
m_appletsExpandedConnectionsTimer.start();
}
});
@ -423,7 +429,7 @@ bool ContainmentInterface::appletIsExpandable(const int id) const
for (const auto applet : m_view->containment()->applets()) {
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;
}
@ -446,7 +452,7 @@ bool ContainmentInterface::appletIsExpandable(PlasmaQuick::AppletQuickItem *appl
return ((appletQuickItem->fullRepresentation() != nullptr
&& 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
@ -457,7 +463,7 @@ bool ContainmentInterface::appletIsActivationTogglesExpanded(const int id) const
for (const auto applet : m_view->containment()->applets()) {
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;
}
@ -487,6 +493,148 @@ bool ContainmentInterface::hasPlasmaTasks() const
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)
{
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()
{
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()) {
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 *>();
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()
{
if (!m_view->containment()) {
@ -608,6 +890,69 @@ void ContainmentInterface::updateAppletsTracking()
for (const auto applet : m_view->containment()->applets()) {
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)
@ -616,10 +961,15 @@ void ContainmentInterface::onAppletAdded(Plasma::Applet *applet)
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
Plasma::Containment *subContainment = Layouts::Storage::self()->subContainmentOf(m_view->layout(), applet);
PlasmaQuick::AppletQuickItem *contAi = applet->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
Plasma::Containment *subContainment = Layouts::Storage::self()->subContainmentOf(m_view->corona(), applet);
PlasmaQuick::AppletQuickItem *contAi = ai;
if (contAi && !m_appletsExpandedConnections.contains(contAi)) {
m_appletsExpandedConnections[contAi] = connect(contAi, &PlasmaQuick::AppletQuickItem::expandedChanged, this, &ContainmentInterface::onAppletExpandedChanged);
@ -642,13 +992,7 @@ void ContainmentInterface::onAppletAdded(Plasma::Applet *applet)
});
}
}
} else {
PlasmaQuick::AppletQuickItem *ai = applet->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
if (!ai) {
return;
}
} else if (ai) {
KPluginMetaData meta = applet->kPackage().metadata();
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"
// Qt
#include <QMetaMethod>
#include <QHash>
#include <QMetaMethod>
#include <QObject>
#include <QPointer>
#include <QQuickItem>
@ -26,6 +26,10 @@ namespace PlasmaQuick {
class AppletQuickItem;
}
namespace KDeclarative {
class ConfigPropertyMap;
}
namespace Latte {
class Corona;
class View;
@ -34,6 +38,16 @@ class View;
namespace Latte {
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
{
Q_OBJECT
@ -41,9 +55,14 @@ class ContainmentInterface: public QObject
Q_PROPERTY(bool hasLatteTasks READ hasLatteTasks NOTIFY hasLatteTasksChanged)
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 *plasmaTasksModel READ plasmaTasksModel() NOTIFY plasmaTasksModelChanged)
//! specified from containment qml side
Q_PROPERTY(QObject* layoutManager READ layoutManager WRITE setLayoutManager NOTIFY layoutManagerChanged)
public:
ContainmentInterface(Latte::View *parent);
virtual ~ContainmentInterface();
@ -73,6 +92,17 @@ public:
int applicationLauncherId() const;
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 *plasmaTasksModel() const;
@ -86,13 +116,39 @@ public slots:
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:
void expandedAppletStateChanged();
void hasExpandedAppletChanged();
void hasLatteTasksChanged();
void hasPlasmaTasksChanged();
void initializationCompleted();
void latteTasksModelChanged();
void layoutManagerChanged();
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);
@ -100,7 +156,12 @@ private slots:
void identifyShortcutsHost();
void identifyMethods();
void updateAppletsOrder();
void updateAppletsInLockedZoom();
void updateAppletsDisabledColoring();
void updateAppletsTracking();
void updateAppletDelayedConfiguration();
void onAppletAdded(Plasma::Applet *applet);
void onAppletExpandedChanged();
void onLatteTasksCountChanged();
@ -109,9 +170,14 @@ private slots:
private:
void addExpandedApplet(PlasmaQuick::AppletQuickItem * appletQuickItem);
void removeExpandedApplet(PlasmaQuick::AppletQuickItem *appletQuickItem);
void initAppletConfigurationSignals(const int &id, KDeclarative::ConfigPropertyMap *configuration);
bool appletIsExpandable(PlasmaQuick::AppletQuickItem *appletQuickItem) const;
KDeclarative::ConfigPropertyMap *appletConfiguration(const Plasma::Applet *applet);
QList<int> toIntList(const QVariantList &list);
private:
bool m_hasLatteTasks{false};
bool m_hasPlasmaTasks{false};
@ -132,9 +198,21 @@ private:
TasksModel *m_latteTasksModel;
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
QHash<PlasmaQuick::AppletQuickItem *, int> m_expandedAppletIds;
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)
|| (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);
} else {
return popUpRelevantToParent(globalItemRect, popUpRect);
@ -267,8 +267,8 @@ bool ContextMenu::mousePressEvent(QMouseEvent *event)
if (ai && ai->isVisible() && appletContainsMouse) {
applet = ai->applet();
if (m_latteView && Layouts::Storage::self()->isSubContainment(m_latteView->layout(), applet)) {
Plasma::Containment *subContainment = Layouts::Storage::self()->subContainmentOf(m_latteView->layout(), applet);
if (m_latteView && Layouts::Storage::self()->isSubContainment(m_latteView->corona(), applet)) {
Plasma::Containment *subContainment = Layouts::Storage::self()->subContainmentOf(m_latteView->corona(), applet);
if (subContainment) {
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
#include <coretypes.h>
#include "effects.h"
#include "originalview.h"
#include "view.h"
#include "visibilitymanager.h"
#include "../lattecorona.h"
@ -347,6 +348,7 @@ void Positioner::onStartupFinished()
if (m_inStartup) {
m_inStartup = false;
syncGeometry();
emit isOffScreenChanged();
}
}
@ -1045,6 +1047,12 @@ void Positioner::initSignalingForLocationChangeSliding()
m_view->setAlignment(m_nextAlignment);
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);
}
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 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
if (!screenName.isEmpty()) {
bool nextonprimary = (screenName == Latte::Data::Screen::ONPRIMARYNAME);
@ -1200,6 +1232,11 @@ void Positioner::setNextLocation(const QString layoutName, const QString screenN
haschanges = true;
}
if (haschanges && m_view->isOriginal()) {
auto originalview = qobject_cast<Latte::OriginalView *>(m_view);
originalview->setNextLocationForClones(layoutName, edge, alignment);
}
m_repositionIsAnimated = isanimated;
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 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 isStickedOnBottomEdge READ isStickedOnBottomEdge WRITE setIsStickedOnBottomEdge NOTIFY isStickedOnBottomEdgeChanged)
@ -90,7 +91,7 @@ public:
Latte::WindowSystem::WindowId trackedWindowId();
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();
void syncGeometry();
@ -126,6 +127,7 @@ signals:
void inRelocationAnimationChanged();
void inRelocationShowingChanged();
void inSlideAnimationChanged();
void isOffScreenChanged();
void isStickedOnTopEdgeChanged();
void isStickedOnBottomEdgeChanged();
@ -193,6 +195,7 @@ private:
bool m_repositionIsAnimated{false};
QString m_nextLayoutName;
Latte::Types::ScreensGroup m_nextScreensGroup{Latte::Types::SingleScreenGroup};
QString m_nextScreenName;
QScreen *m_nextScreen{nullptr};
Plasma::Types::Location m_nextScreenEdge{Plasma::Types::Floating};

View File

@ -89,6 +89,7 @@ void WidgetExplorerView::initParentView(Latte::View *view)
SubConfigView::initParentView(view);
rootContext()->setContextProperty(QStringLiteral("containmentFromView"), m_latteView->containment());
rootContext()->setContextProperty(QStringLiteral("latteView"), m_latteView);
updateEnabledBorders();
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_interface, &ViewPart::ContainmentInterface::hasExpandedAppletChanged, this, &View::updateTransientWindowsTracking);
connect(this, &View::containmentChanged, this, &View::groupIdChanged);
connect(this, &View::containmentChanged
, this, [ &, byPassX11WM]() {
qDebug() << "dock view c++ containment changed 1...";
@ -1017,6 +1018,15 @@ void View::setOnPrimary(bool flag)
emit onPrimaryChanged();
}
int View::groupId() const
{
if (!containment()) {
return -1;
}
return containment()->id();
}
float View::maxLength() const
{
return m_maxLength;
@ -1389,6 +1399,8 @@ Latte::Data::View View::data() const
vdata.screen = containment()->lastScreen();
}
vdata.screensGroup = screensGroup();
//!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);
@ -1738,8 +1750,9 @@ void View::mousePressEvent(QMouseEvent *event)
//!BEGIN configuration functions
void View::saveConfig()
{
if (!this->containment())
if (!this->containment()) {
return;
}
auto config = this->containment()->config();
config.writeEntry("onPrimary", onPrimary());
@ -1751,8 +1764,9 @@ void View::saveConfig()
void View::restoreConfig()
{
if (!this->containment())
if (!this->containment()) {
return;
}
auto config = this->containment()->config();
m_onPrimary = config.readEntry("onPrimary", true);

View File

@ -70,6 +70,7 @@ class View : public PlasmaQuick::ContainmentView
{
Q_OBJECT
Q_PROPERTY(int groupId READ groupId NOTIFY groupIdChanged)
Q_PROPERTY(Latte::Types::ViewType type READ type WRITE setType NOTIFY typeChanged)
Q_PROPERTY(bool alternativesIsShown READ alternativesIsShown NOTIFY alternativesIsShownChanged)
@ -160,7 +161,7 @@ public:
bool isFloatingPanel() const;
bool isPreferredForShortcuts() const;
virtual bool isPreferredForShortcuts() const;
void setIsPreferredForShortcuts(bool preferred);
bool inSettingsAdvancedMode() const;
@ -174,6 +175,8 @@ public:
bool screenEdgeMarginEnabled() const;
void setScreenEdgeMarginEnabled(bool enabled);
virtual int groupId() const;
int fontPixelSize() const;
void setFontPixelSize(int size);
@ -229,16 +232,21 @@ public:
QQuickItem *metrics() const;
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;
QQuickView *configView();
Latte::Data::View data() const;
virtual Latte::Data::View data() const;
ViewPart::Effects *effects() const;
ViewPart::ContextMenu *contextMenu() const;
ViewPart::ContainmentInterface *extendedInterface() const;
ViewPart::Indicator *indicator() const;
virtual ViewPart::Indicator *indicator() const;
ViewPart::Parabolic *parabolic() const;
ViewPart::Positioner *positioner() const;
ViewPart::EventsSink *sink() const;
@ -256,7 +264,7 @@ public:
//! release grab and restore mouse state
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
//! when its containment is destroyed
@ -309,6 +317,7 @@ signals:
void fontPixelSizeChanged();
void forcedShown(); //[workaround] forced shown to avoid a KWin issue that hides windows when closing activities
void geometryChanged();
void groupIdChanged();
void widthChanged();
void headThicknessGapChanged();
void heightChanged();
@ -334,6 +343,7 @@ signals:
void screenEdgeMarginChanged();
void screenEdgeMarginEnabledChanged();
void screenGeometryChanged();
void sinkChanged();
void typeChanged();
void visibilityChanged();
@ -352,6 +362,9 @@ signals:
void availableScreenRectChangedFrom(Latte::View *origin);
void availableScreenRegionChangedFrom(Latte::View *origin);
protected:
QPointer<Latte::Corona> m_corona;
private slots:
void applyActivitiesToWindows();
void availableScreenRectChangedFromSlot(View *origin);
@ -457,8 +470,6 @@ private:
//! track transientWindows
QList<QWindow *> m_transientWindows;
QPointer<Latte::Corona> m_corona;
KWayland::Client::PlasmaShellSurface *m_shellSurface{nullptr};
};

View File

@ -17,7 +17,8 @@ target_link_libraries(lattecontainmentplugin
Qt5::Qml
Qt5::Quick
KF5::Declarative
KF5::Plasma)
KF5::Plasma
KF5::PlasmaQuick)
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)

View File

@ -337,5 +337,18 @@ Item {
&& 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) {
root.launchers.addDroppedLaunchersInStealingApplet(event.mimeData.urls);
} 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);
}
dndSpacer.opacity = 0;
// if (dragInfo.isPlasmoid && root.myView.alignment === LatteCore.Types.Justify) {
// fastLayoutManager.moveAppletsBasedOnJustifyAlignment();
// }
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -414,6 +414,7 @@ MouseArea {
closeButton.visible = !currentApplet.isInternalViewSplitter && currentApplet.applet.action("remove") && currentApplet.applet.action("remove").enabled;
lockButton.visible = !currentApplet.isInternalViewSplitter
&& !currentApplet.communicator.indexerIsSupported
&& !currentApplet.communicator.appletBlocksParabolicEffect
&& !currentApplet.isSeparator;
colorizingButton.visible = root.colorizerEnabled && !currentApplet.appletBlocksColorizing && !currentApplet.isInternalViewSplitter;
@ -469,8 +470,8 @@ MouseArea {
iconSource: "color-picker"
tooltip: i18n("Enable painting for this applet")
onCheckedChanged: {
currentApplet.userBlocksColorizing = !checked;
onClicked: {
fastLayoutManager.setOption(currentApplet.applet.id, "userBlocksColorizing", !checked);
}
}
@ -480,8 +481,8 @@ MouseArea {
iconSource: checked ? "lock" : "unlock"
tooltip: i18n("Disable parabolic effect for this applet")
onCheckedChanged: {
currentApplet.lockZoom = checked;
onClicked: {
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);
Plasmoid.onUserConfiguringChanged: {
@ -572,18 +580,21 @@ Item {
//////////////START OF FUNCTIONS
function createAppletItem(applet) {
var appletItem = appletItemComponent.createObject(dndSpacer.parent);
appletItem.applet = applet;
applet.parent = appletItem.appletWrapper;
applet.anchors.fill = appletItem.appletWrapper;
applet.visible = true;
var appletContainer = appletItemComponent.createObject(dndSpacer.parent);
initAppletContainer(appletContainer, applet);
// don't show applet if it chooses to be hidden but still make it accessible in the panelcontroller
appletItem.visible = Qt.binding(function() {
return applet.status !== PlasmaCore.Types.HiddenStatus || (!plasmoid.immutable && root.inConfigureAppletsMode)
appletContainer.visible = Qt.binding(function() {
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() {
@ -743,23 +754,9 @@ Item {
endLayout: layoutsContainer.endLayout
metrics: _metrics
onLockedZoomAppletsChanged: plasmoid.configuration.lockedZoomApplets = fastLayoutManager.lockedZoomApplets;
onUserBlocksColorizingAppletsChanged: plasmoid.configuration.userBlocksColorizingApplets = fastLayoutManager.userBlocksColorizingApplets;
onAppletOrderChanged: {
plasmoid.configuration.appletOrder = fastLayoutManager.appletOrder;
root.updateIndexes();
}
onSplitterPositionChanged: {
plasmoid.configuration.splitterPosition = fastLayoutManager.splitterPosition;
root.updateIndexes();
}
onSplitterPosition2Changed: {
plasmoid.configuration.splitterPosition2 = fastLayoutManager.splitterPosition2;
root.updateIndexes();
}
onAppletOrderChanged: root.updateIndexes();
onSplitterPositionChanged: root.updateIndexes();
onSplitterPosition2Changed: root.updateIndexes();
}
///////////////BEGIN UI elements

View File

@ -16,7 +16,11 @@
// Plasma
#include <Plasma>
#include <Plasma/Applet>
#include <PlasmaQuick/AppletQuickItem>
#define ISAPPLETLOCKEDOPTION "lockZoom"
#define ISCOLORINGBLOCKEDOPTION "userBlocksColorizing"
namespace Latte{
namespace Containment{
@ -24,8 +28,8 @@ namespace Containment{
LayoutManager::LayoutManager(QObject *parent)
: QObject(parent)
{
m_option["lockZoom"] = "lockedZoomApplets";
m_option["userBlocksColorizing"] = "userBlocksColorizingApplets";
m_option[ISAPPLETLOCKEDOPTION] = "lockedZoomApplets";
m_option[ISCOLORINGBLOCKEDOPTION] = "userBlocksColorizingApplets";
connect(this, &LayoutManager::rootItemChanged, this, &LayoutManager::onRootItemChanged);
@ -72,12 +76,12 @@ void LayoutManager::setSplitterPosition2(const int &position)
emit splitterPosition2Changed();
}
QString LayoutManager::appletOrder() const
QList<int> LayoutManager::appletOrder() const
{
return m_appletOrder;
}
void LayoutManager::setAppletOrder(const QString &order)
void LayoutManager::setAppletOrder(const QList<int> &order)
{
if (m_appletOrder == order) {
return;
@ -87,12 +91,12 @@ void LayoutManager::setAppletOrder(const QString &order)
emit appletOrderChanged();
}
QString LayoutManager::lockedZoomApplets() const
QList<int> LayoutManager::lockedZoomApplets() const
{
return m_lockedZoomApplets;
}
void LayoutManager::setLockedZoomApplets(const QString &applets)
void LayoutManager::setLockedZoomApplets(const QList<int> &applets)
{
if (m_lockedZoomApplets == applets) {
return;
@ -102,12 +106,27 @@ void LayoutManager::setLockedZoomApplets(const QString &applets)
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;
}
void LayoutManager::setUserBlocksColorizingApplets(const QString &applets)
void LayoutManager::setUserBlocksColorizingApplets(const QList<int> &applets)
{
if (m_userBlocksColorizingApplets == applets) {
return;
@ -117,6 +136,23 @@ void LayoutManager::setUserBlocksColorizingApplets(const QString &applets)
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
{
return m_plasmoid;
@ -227,6 +263,20 @@ void LayoutManager::setMetrics(QQuickItem *metrics)
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()
{
if (!m_rootItem) {
@ -239,6 +289,9 @@ void LayoutManager::onRootItemChanged()
int createJustifySplitterIndex = rootMetaObject->indexOfMethod("createJustifySplitter()");
m_createJustifySplitterMethod = rootMetaObject->method(createJustifySplitterIndex);
int initAppletContainerIndex = rootMetaObject->indexOfMethod("initAppletContainer(QVariant,QVariant)");
m_initAppletContainerMethod = rootMetaObject->method(initAppletContainerIndex);
}
bool LayoutManager::isValidApplet(const int &id)
@ -263,18 +316,13 @@ bool LayoutManager::isValidApplet(const int &id)
//! Actions
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 *>>();
Latte::Types::Alignment alignment = static_cast<Latte::Types::Alignment>((*m_configuration)["alignment"].toInt());
int splitterPosition = (*m_configuration)["splitterPosition"].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 (splitterPosition!=-1 && splitterPosition2!=-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) {
uint id = applets[i]->property("id").toUInt();
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 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 produced order ?? " << validateAppletsOrder;
@ -393,49 +441,61 @@ void LayoutManager::restore()
}
restoreOptions();
save();
save(); //will restore also a valid applets ids order
cleanupOptions();
initSaveConnections();
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()
{
restoreOption("lockZoom");
restoreOption("userBlocksColorizing");
restoreOption(ISAPPLETLOCKEDOPTION);
restoreOption(ISCOLORINGBLOCKEDOPTION);
}
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) {
return;
if (option == ISAPPLETLOCKEDOPTION) {
setLockedZoomApplets(applets);
} else if (option == ISCOLORINGBLOCKEDOPTION) {
setUserBlocksColorizingApplets(applets);
}
}
for (int i=0; i<=2; ++i) {
QQuickItem *layout = (i==0 ? m_startLayout : (i==1 ? m_mainLayout : m_endLayout));
bool LayoutManager::isJustifySplitter(const QQuickItem *item) const
{
return item && (item->property("isInternalViewSplitter").toBool() == true);
}
for (int j=layout->childItems().count()-1; j>=0; --j) {
QQuickItem *item = layout->childItems()[j];
bool issplitter = item->property("isInternalViewSplitter").toBool();
if (!issplitter) {
QVariant appletVariant = item->property("applet");
if (!appletVariant.isValid()) {
continue;
}
bool LayoutManager::isMasqueradedIndex(const int &x, const int &y)
{
return (x==y && x<=MASQUERADEDINDEXTOPOINTBASE && y<=MASQUERADEDINDEXTOPOINTBASE);
}
QObject *applet = appletVariant.value<QObject *>();
uint id = applet->property("id").toUInt();
int LayoutManager::masquearadedIndex(const int &x, const int &y)
{
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()
{
QStringList appletIds;
QList<int> appletIds;
int startChilds{0};
for(int i=0; i<m_startLayout->childItems().count(); ++i) {
@ -457,7 +517,7 @@ void LayoutManager::save()
if (id>0) {
startChilds++;
appletIds << QString::number(id);
appletIds << id;
}
}
}
@ -482,7 +542,7 @@ void LayoutManager::save()
if (id>0) {
mainChilds++;
appletIds << QString::number(id);
appletIds << id;
}
}
}
@ -507,7 +567,7 @@ void LayoutManager::save()
if (id>0) {
endChilds++;
appletIds << QString::number(id);
appletIds << id;
}
}
}
@ -530,56 +590,67 @@ void LayoutManager::save()
//(*m_configuration)["splitterPosition2"] = QVariant(startChilds + 1 + mainChilds + 1);
//(*m_configuration)["appletOrder"] = appletIds.join(";");
setAppletOrder(appletIds.join(";"));
//qDebug() << "org.kde.latte saving applets:: " << appletOrder() << " :: " << splitterPosition() << " : " << splitterPosition2();
setAppletOrder(appletIds);
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()
{
saveOption("lockZoom");
saveOption("userBlocksColorizing");
//qDebug() << "org.kde.latte saving properties:: " << lockedZoomApplets() << " :: " << userBlocksColorizingApplets();
{
QString lockedserialized = toStr(m_lockedZoomApplets);
if ((*m_configuration)[m_option[ISAPPLETLOCKEDOPTION]] != lockedserialized) {
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) {
return;
}
if (property == ISAPPLETLOCKEDOPTION) {
bool enabled = value.toBool();
QStringList applets;
for (int i=0; i<=2; ++i) {
QQuickItem *layout = (i==0 ? m_startLayout : (i==1 ? m_mainLayout : m_endLayout));
for (int j=0; j<layout->childItems().count(); ++j) {
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);
}
if (enabled && !m_lockedZoomApplets.contains(appletId)) {
QList<int> applets = m_lockedZoomApplets; applets << appletId;
setLockedZoomApplets(applets);
} else if (!enabled && m_lockedZoomApplets.contains(appletId)) {
QList<int> applets = m_lockedZoomApplets; applets.removeAll(appletId);
setLockedZoomApplets(applets);
}
}
} else if (property == ISCOLORINGBLOCKEDOPTION) {
bool enabled = value.toBool();
if (option == "lockZoom") {
setLockedZoomApplets(applets.join(";"));
} else if (option == "userBlocksColorizing") {
setUserBlocksColorizingApplets(applets.join(";"));
if (enabled && !m_userBlocksColorizingApplets.contains(appletId)) {
QList<int> applets = m_userBlocksColorizingApplets; applets << appletId;
setUserBlocksColorizingApplets(applets);
} 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->stackBefore(hoveredItem);
}
void LayoutManager::insertAfter(QQuickItem *hoveredItem, QQuickItem *item)
@ -611,7 +681,12 @@ void LayoutManager::insertAtLayoutTail(QQuickItem *layout, QQuickItem *item)
}
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;
}
@ -627,7 +702,12 @@ void LayoutManager::insertAtLayoutHead(QQuickItem *layout, QQuickItem *item)
int count = layout->childItems().count();
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;
}
@ -692,8 +772,8 @@ bool LayoutManager::insertAtLayoutCoordinates(QQuickItem *layout, QQuickItem *it
}
if (hovered) {
if ((vertical && y < (hovered->y() + hovered->height()/2)) ||
(horizontal && x < hovered->x() + hovered->width()/2)) {
if ((vertical && y < (hovered->y() + hovered->height()/2) && hovered->height() > 1) ||
(horizontal && x < (hovered->x() + hovered->width()/2) && hovered->width() > 1)) {
insertBefore(hovered, item);
} else {
insertAfter(hovered, item);
@ -705,6 +785,202 @@ bool LayoutManager::insertAtLayoutCoordinates(QQuickItem *layout, QQuickItem *it
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
{
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)
{
if (!m_startLayout || !m_mainLayout || !m_endLayout) {
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;
@ -827,31 +1184,85 @@ void LayoutManager::removeAppletItem(QObject *applet)
return;
}
for (int i=0; i<=2; ++i) {
QQuickItem *layout = (i==0 ? m_startLayout : (i==1 ? m_mainLayout : m_endLayout));
PlasmaQuick::AppletQuickItem *aqi = qobject_cast<PlasmaQuick::AppletQuickItem *>(applet);
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");
if (!appletVariant.isValid()) {
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();
return;
destroyed = true;
break;
}
}
}
}
}
save();
if (destroyed) {
save();
}
}
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
{
Q_OBJECT
Q_OBJECT
Q_PROPERTY(QObject *plasmoidObj READ plasmoid() WRITE setPlasmoid NOTIFY plasmoidChanged)
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
Q_PROPERTY(int splitterPosition READ splitterPosition NOTIFY splitterPositionChanged)
Q_PROPERTY(int splitterPosition2 READ splitterPosition2 NOTIFY splitterPosition2Changed)
Q_PROPERTY(QString appletOrder READ appletOrder NOTIFY appletOrderChanged)
Q_PROPERTY(QString lockedZoomApplets READ lockedZoomApplets NOTIFY lockedZoomAppletsChanged)
Q_PROPERTY(QString userBlocksColorizingApplets READ userBlocksColorizingApplets NOTIFY userBlocksColorizingAppletsChanged)
Q_PROPERTY(QList<int> appletOrder READ appletOrder NOTIFY appletOrderChanged)
Q_PROPERTY(QList<int> order READ order NOTIFY orderChanged) //includes also splitters
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:
static const int JUSTIFYSPLITTERID = -10;
LayoutManager(QObject *parent = nullptr);
bool hasRestoredApplets() const;
int splitterPosition() const;
int splitterPosition2() const;
QString appletOrder() const;
QString lockedZoomApplets() const;
QString userBlocksColorizingApplets() const;
QList<int> appletOrder() const;
QList<int> lockedZoomApplets() const;
QList<int> order() const;
QList<int> userBlocksColorizingApplets() const;
QList<int> appletsInScheduledDestruction() const;
QObject *plasmoid() const;
void setPlasmoid(QObject *plasmoid);
@ -81,8 +87,10 @@ public slots:
Q_INVOKABLE void restore();
Q_INVOKABLE void save();
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 index);
Q_INVOKABLE void removeAppletItem(QObject *applet);
Q_INVOKABLE void addJustifySplittersInMainLayout();
@ -92,8 +100,21 @@ public slots:
Q_INVOKABLE void insertAfter(QQuickItem *hoveredItem, QQuickItem *item);
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:
void appletOrderChanged();
void appletsInScheduledDestructionChanged();
void hasRestoredAppletsChanged();
void plasmoidChanged();
void rootItemChanged();
@ -103,6 +124,7 @@ signals:
void mainLayoutChanged();
void metricsChanged();
void orderChanged();
void splitterPositionChanged();
void splitterPosition2Changed();
void startLayoutChanged();
@ -112,36 +134,58 @@ private slots:
void onRootItemChanged();
void destroyJustifySplitters();
void updateOrder();
void cleanupOptions();
private:
void restoreOptions();
void restoreOption(const char *option);
void saveOption(const char *option);
void destroyAppletContainer(QObject *applet);
void initSaveConnections();
void insertAtLayoutTail(QQuickItem *layout, QQuickItem *item);
void insertAtLayoutHead(QQuickItem *layout, QQuickItem *item);
void setSplitterPosition(const int &position);
void setSplitterPosition2(const int &position);
void setAppletOrder(const QString &order);
void setLockedZoomApplets(const QString &applets);
void setUserBlocksColorizingApplets(const QString &applets);
void setAppletOrder(const QList<int> &order);
void setOrder(const QList<int> &order);
void setLockedZoomApplets(const QList<int> &applets);
void setUserBlocksColorizingApplets(const QList<int> &applets);
void reorderSplitterInStartLayout();
void reorderSplitterInEndLayout();
bool isJustifySplitter(const QQuickItem *item) const;
bool isValidApplet(const int &id);
bool insertAtLayoutCoordinates(QQuickItem *layout, QQuickItem *item, int x, int y);
int distanceFromTail(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:
//! 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_splitterPosition2{-1};
QString m_appletOrder;
QString m_lockedZoomApplets;
QString m_userBlocksColorizingApplets;
QList<int> m_appletOrder;
QList<int> m_lockedZoomApplets;
QList<int> m_order;
QList<int> m_userBlocksColorizingApplets;
QQuickItem *m_rootItem{nullptr};
QQuickItem *m_dndSpacer{nullptr};
@ -154,8 +198,11 @@ private:
QObject *m_plasmoid{nullptr};
KDeclarative::ConfigPropertyMap *m_configuration{nullptr};
QHash<int, QQuickItem *> m_appletsInScheduledDestruction;
QMetaMethod m_createAppletItemMethod;
QMetaMethod m_createJustifySplitterMethod;
QMetaMethod m_initAppletContainerMethod;
bool m_hasRestoredApplets{false};
QTimer m_hasRestoredAppletsTimer;

View File

@ -32,14 +32,8 @@ const int ACTIVELAYOUTSINDEX = 1;
const int CURRENTLAYOUTSINDEX = 2;
const int ACTIONSALWAYSSHOWN = 3;
const int LAYOUTMENUINDEX = 4;
const int VIEWTYPEINDEX = 5;
const int VIEWLAYOUTINDEX = 6;
enum ViewType
{
DockView = 0,
PanelView
};
const int VIEWLAYOUTINDEX = 5;
const int VIEWTYPEINDEX = 6;
enum LayoutsMemoryUsage
{
@ -240,22 +234,25 @@ QList<QAction *> Menu::contextualActions()
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);
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);
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_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);
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);
updateVisibleActions();
@ -302,6 +299,13 @@ void Menu::updateVisibleActions()
m_actions[Latte::Data::ContextMenu::EDITVIEWACTION]->setVisible(!configuring);
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
for(auto actionName: m_actions.keys()) {
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()
{
m_addViewMenu->clear();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -12,8 +12,11 @@ import org.kde.latte.core 0.2 as LatteCore
Item {
id:_syncer
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
// 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
Component.onCompleted: {

View File

@ -84,9 +84,15 @@ PlasmaComponents.Page {
screensCount = universalSettings.screens.length;
screensModel.clear();
var primary = {name: i18n("Follow Primary Screen"), icon: 'favorite'};
var primary = {name: i18n("On Primary Screen"), icon: 'favorite'};
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
//the view automatically to primaryScreen in order for the user
//to has always a view with tasks shown
@ -107,8 +113,12 @@ PlasmaComponents.Page {
screensModel.append(scr);
}
if (latteView.onPrimary) {
if (latteView.onPrimary && latteView.screensGroup === LatteCore.Types.SingleScreenGroup) {
screenCmb.currentIndex = 0;
} else if (latteView.screensGroup === LatteCore.Types.AllScreensGroup) {
screenCmb.currentIndex = 1;
} else if (latteView.screensGroup === LatteCore.Types.AllSecondaryScreensGroup) {
screenCmb.currentIndex = 2;
} else {
screenCmb.currentIndex = screenCmb.findScreen(latteView.positioner.currentScreenName);
}
@ -135,10 +145,14 @@ PlasmaComponents.Page {
Component.onCompleted: screenRow.updateScreens();
onActivated: {
if (index === 0) {
latteView.positioner.setNextLocation("", "{primary-screen}", PlasmaCore.Types.Floating, LatteCore.Types.NoneAlignment);
} else if (index>0 && (index !== findScreen(latteView.positioner.currentScreenName) || latteView.onPrimary)) {
latteView.positioner.setNextLocation("", textAt(index), PlasmaCore.Types.Floating, LatteCore.Types.NoneAlignment);
if (index === 0) { // primary
latteView.positioner.setNextLocation("", LatteCore.Types.SingleScreenGroup, "{primary-screen}", PlasmaCore.Types.Floating, LatteCore.Types.NoneAlignment);
} else if (index === 1) { // all screens
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: {
//! clicked event is more wayland friendly because it release focus from the button before hiding the window
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: {
//! clicked event is more wayland friendly because it release focus from the button before hiding the window
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: {
//! clicked event is more wayland friendly because it release focus from the button before hiding the window
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: {
//! clicked event is more wayland friendly because it release focus from the button before hiding the window
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: {
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: {
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: {
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: {
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
onDoubleClicked: {
if (!delegate.pendingUninstall) {
widgetExplorer.addApplet(pluginName)
widgetExplorer.addApplet(pluginName);
latteView.extendedInterface.appletCreated(pluginName);
}
}
onEntered: delegate.GridView.view.currentIndex = index

View File

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