1
0
mirror of https://github.com/KDE/latte-dock.git synced 2025-01-27 06:03:51 +03:00
latte-dock/app/dockcorona.cpp
Michail Vourlakos fba9d62ee2 fix #50, update config window location
--fix also some crashes concerning the existence
of multiple config windows from different docks.
2017-01-11 02:30:35 +02:00

278 lines
7.8 KiB
C++

/*
* Copyright 2016 Smith AR <audoban@openmailbox.org>
* Michail Vourlakos <mvourlakos@gmail.com>
*
* This file is part of Latte-Dock
*
* Latte-Dock is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* Latte-Dock is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dockcorona.h"
#include "dockview.h"
#include "packageplugins/shell/dockpackage.h"
#include <QAction>
#include <QScreen>
#include <QDebug>
#include <Plasma>
#include <Plasma/Corona>
#include <Plasma/Containment>
#include <KActionCollection>
#include <KPluginMetaData>
#include <KLocalizedString>
#include <KPackage/Package>
#include <KPackage/PackageLoader>
#include <kactivities/consumer.h>
namespace Latte {
DockCorona::DockCorona(QObject *parent)
: Plasma::Corona(parent),
m_activityConsumer(new KActivities::Consumer(this))
{
KPackage::Package package(new DockPackage(this));
if (!package.isValid()) {
qWarning() << staticMetaObject.className()
<< "the package" << package.metadata().rawData() << "is invalid!";
return;
} else {
qDebug() << staticMetaObject.className()
<< "the package" << package.metadata().rawData() << "is valid!";
}
setKPackage(package);
qmlRegisterTypes();
connect(this, &Corona::containmentAdded, this, &DockCorona::addDock);
connect(m_activityConsumer, &KActivities::Consumer::serviceStatusChanged, this, &DockCorona::load);
}
DockCorona::~DockCorona()
{
while (!containments().isEmpty()) {
//deleting a containment will remove it from the list due to QObject::destroyed connect in Corona
delete containments().first();
}
qDeleteAll(m_dockViews);
m_dockViews.clear();
disconnect(m_activityConsumer, &KActivities::Consumer::serviceStatusChanged, this, &DockCorona::load);
delete m_activityConsumer;
qDebug() << "deleted" << this;
}
void DockCorona::load()
{
loadLayout();
}
int DockCorona::numScreens() const
{
return qGuiApp->screens().count();
}
QRect DockCorona::screenGeometry(int id) const
{
const auto screens = qGuiApp->screens();
if (id >= 0 && id < screens.count()) {
return screens[id]->geometry();
}
return qGuiApp->primaryScreen()->geometry();
}
QRegion DockCorona::availableScreenRegion(int id) const
{
const auto screens = qGuiApp->screens();
if (id >= 0 && id < screens.count()) {
return screens[id]->geometry();
}
return qGuiApp->primaryScreen()->availableGeometry();
}
QRect DockCorona::availableScreenRect(int id) const
{
const auto screens = qGuiApp->screens();
if (id >= 0 && id < screens.count()) {
return screens[id]->availableGeometry();
}
return qGuiApp->primaryScreen()->availableGeometry();
}
int DockCorona::primaryScreenId() const
{
const auto screens = qGuiApp->screens();
int id = -1;
for (int i = 0; i < screens.size(); ++i) {
auto *scr = screens.at(i);
if (scr == qGuiApp->primaryScreen()) {
id = i;
break;
}
}
return id;
}
int DockCorona::numDocks()
{
return m_dockViews.size();
}
void DockCorona::closeApplication()
{
qGuiApp->quit();
}
QList<Plasma::Types::Location> DockCorona::freeEdges(int screen) const
{
using Plasma::Types;
QList<Types::Location> edges{Types::BottomEdge, Types::LeftEdge,
Types::TopEdge, Types::RightEdge};
//when screen=-1 is passed then the primaryScreenid is used
int fixedScreen = (screen == -1) ? primaryScreenId() : screen;
for (const DockView *cont : m_dockViews) {
if (cont && cont->containment()->screen() == fixedScreen)
edges.removeOne(cont->location());
}
return edges;
}
int DockCorona::screenForContainment(const Plasma::Containment *containment) const
{
for (auto *view : m_dockViews) {
if (view && view->containment() && view->containment()->id() == containment->id())
if (view->screen())
return qGuiApp->screens().indexOf(view->screen());
}
return -1;
}
void DockCorona::addDock(Plasma::Containment *containment)
{
if (!containment || !containment->kPackage().isValid()) {
qWarning() << "the requested containment plugin can not be located or loaded";
return;
}
// the system tray is a containment that behaves as an applet
// so a dockview shouldnt be created for it
KPluginMetaData metadata = containment->kPackage().metadata();
if (metadata.pluginId() == "org.kde.plasma.private.systemtray") {
return;
}
foreach (DockView *dock, m_dockViews) {
if (dock->containment() == containment) {
return;
}
}
qDebug() << "Adding dock for container...";
auto dockView = new DockView(this);
dockView->init();
dockView->setContainment(containment);
connect(containment, &QObject::destroyed, this, &DockCorona::dockContainmentDestroyed);
dockView->show();
m_dockViews[containment] = dockView;
emit containmentsNoChanged();
}
void DockCorona::dockContainmentDestroyed(QObject *cont)
{
auto view = m_dockViews.take(static_cast<Plasma::Containment *>(cont));
delete view;
//view->deleteLater();
emit containmentsNoChanged();
}
void DockCorona::loadDefaultLayout()
{
qDebug() << "loading default layout";
//! Settting mutable for create a containment
setImmutability(Plasma::Types::Mutable);
QVariantList args;
auto defaultContainment = createContainmentDelayed("org.kde.latte.containment", args);
defaultContainment->setContainmentType(Plasma::Types::PanelContainment);
defaultContainment->init();
if (!defaultContainment || !defaultContainment->kPackage().isValid()) {
qWarning() << "the requested containment plugin can not be located or loaded";
return;
}
auto config = defaultContainment->config();
defaultContainment->restore(config);
QList<Plasma::Types::Location> edges = freeEdges(defaultContainment->screen());
if (edges.count() > 0) {
defaultContainment->setLocation(edges.at(0));
} else {
defaultContainment->setLocation(Plasma::Types::BottomEdge);
}
defaultContainment->updateConstraints(Plasma::Types::StartupCompletedConstraint);
defaultContainment->save(config);
requestConfigSync();
defaultContainment->flushPendingConstraintsEvents();
emit containmentAdded(defaultContainment);
emit containmentCreated(defaultContainment);
addDock(defaultContainment);
defaultContainment->createApplet(QStringLiteral("org.kde.latte.plasmoid"));
defaultContainment->createApplet(QStringLiteral("org.kde.plasma.analogclock"));
}
inline void DockCorona::qmlRegisterTypes() const
{
constexpr auto uri = "org.kde.latte.shell";
constexpr auto vMajor = 0;
constexpr auto vMinor = 2;
// qmlRegisterUncreatableType<Candil::Dock>(uri, vMajor, vMinor, "Dock", "class Dock uncreatable");
// qmlRegisterUncreatableType<Candil::VisibilityManager>(uri, vMajor, vMinor, "VisibilityManager", "class VisibilityManager uncreatable");
// qmlRegisterUncreatableType<NowDockView>(uri, vMajor, vMinor, "DockView", "class DockView uncreatable");
qmlRegisterType<QScreen>();
}
}