1
0
mirror of https://github.com/KDE/latte-dock.git synced 2025-01-11 13:18:13 +03:00
latte-dock/app/dockview.cpp

1185 lines
34 KiB
C++
Raw Normal View History

2016-12-31 00:22:28 +03:00
/*
2017-01-03 01:05:30 +03:00
* 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/>.
*/
2016-12-31 00:22:28 +03:00
2016-12-31 00:25:27 +03:00
#include "dockview.h"
#include "dockconfigview.h"
2016-12-31 03:26:48 +03:00
#include "dockcorona.h"
2016-12-31 00:22:28 +03:00
#include "visibilitymanager.h"
#include "panelshadows_p.h"
2017-01-13 10:07:27 +03:00
#include "../liblattedock/extras.h"
2016-12-31 00:22:28 +03:00
#include <QAction>
#include <QQmlContext>
#include <QQmlEngine>
#include <QQmlProperty>
#include <QQuickItem>
#include <QMenu>
2016-12-31 00:22:28 +03:00
#include <QMetaEnum>
#include <KActionCollection>
#include <KAuthorized>
2016-12-31 00:22:28 +03:00
#include <KLocalizedContext>
#include <KLocalizedString>
#include <Plasma/Containment>
#include <Plasma/ContainmentActions>
#include <PlasmaQuick/AppletQuickItem>
2016-12-31 00:22:28 +03:00
namespace Latte {
2016-12-31 00:25:27 +03:00
DockView::DockView(Plasma::Corona *corona, QScreen *targetScreen)
: PlasmaQuick::ContainmentView(corona),
m_contextMenu(nullptr)
2016-12-31 00:22:28 +03:00
{
setVisible(false);
setTitle(corona->kPackage().metadata().name());
setIcon(QIcon::fromTheme(corona->kPackage().metadata().iconName()));
setResizeMode(QuickViewSharedEngine::SizeRootObjectToView);
setClearBeforeRendering(true);
setFlags(Qt::FramelessWindowHint
| Qt::WindowStaysOnTopHint
| Qt::NoDropShadowWindowHint
| Qt::WindowDoesNotAcceptFocus);
2017-01-16 22:07:49 +03:00
2016-12-31 00:22:28 +03:00
if (targetScreen)
setScreenToFollow(targetScreen);
2016-12-31 00:22:28 +03:00
else
setScreenToFollow(qGuiApp->primaryScreen());
2017-01-16 22:07:49 +03:00
2016-12-31 00:25:27 +03:00
connect(this, &DockView::containmentChanged
, this, [&]() {
qDebug() << "entered creating step 1...";
if (!this->containment())
2016-12-31 00:22:28 +03:00
return;
qDebug() << "entered creating step 2...";
2017-01-16 22:07:49 +03:00
2016-12-31 00:22:28 +03:00
if (!m_visibility) {
m_visibility = new VisibilityManager(this);
}
2017-01-16 22:07:49 +03:00
QAction *lockWidgetsAction = this->containment()->actions()->action("lock widgets");
this->containment()->actions()->removeAction(lockWidgetsAction);
QAction *removeAction = containment()->actions()->action("remove");
removeAction->setVisible(false);
//containment()->actions()->removeAction(removeAction);
2017-01-03 17:17:28 +03:00
//FIX: hide and not delete in order to disable a nasty behavior from
//ContainmentInterface. If only one action exists for containment the
//this action is triggered directly
QAction *addWidgetsAction = this->containment()->actions()->action("add widgets");
2017-01-03 17:17:28 +03:00
addWidgetsAction->setVisible(false);
//containment()->actions()->removeAction(addWidgetsAction);
connect(this->containment(), SIGNAL(statusChanged(Plasma::Types::ItemStatus)), SLOT(statusChanged(Plasma::Types::ItemStatus)));
2016-12-31 00:22:28 +03:00
}, Qt::DirectConnection);
2017-01-16 21:24:46 +03:00
auto *dockCorona = qobject_cast<DockCorona *>(this->corona());
2017-01-16 22:07:49 +03:00
if (dockCorona) {
2017-01-16 21:24:46 +03:00
connect(dockCorona, &DockCorona::docksCountChanged, this, &DockView::docksCountChanged);
connect(dockCorona, &DockCorona::dockLocationChanged, this, &DockView::dockLocationChanged);
}
2016-12-31 00:22:28 +03:00
}
2016-12-31 00:25:27 +03:00
DockView::~DockView()
2016-12-31 00:22:28 +03:00
{
qDebug() << "dock view deleting...";
2017-01-22 01:40:16 +03:00
rootContext()->setContextProperty(QStringLiteral("dock"), nullptr);
this->disconnect();
qDebug() << "dock view connections deleted...";
2017-01-16 22:07:49 +03:00
if (m_configView) {
m_configView->hide();
m_configView->deleteLater();
}
if (m_visibility) {
delete m_visibility;
}
2016-12-31 00:22:28 +03:00
}
2016-12-31 00:25:27 +03:00
void DockView::init()
2016-12-31 00:22:28 +03:00
{
connect(this, &QQuickWindow::screenChanged, this, &DockView::screenChanged);
connect(qGuiApp, &QGuiApplication::screenAdded, this, &DockView::screenChanged);
connect(qGuiApp, &QGuiApplication::primaryScreenChanged, this, &DockView::screenChanged);
connect(this, &DockView::screenGeometryChanged, this, &DockView::syncGeometry);
connect(this, &QQuickWindow::xChanged, this, &DockView::xChanged);
connect(this, &QQuickWindow::yChanged, this, &DockView::yChanged);
connect(this, &QQuickWindow::widthChanged, this, &DockView::widthChanged);
connect(this, &QQuickWindow::heightChanged, this, &DockView::heightChanged);
connect(corona(), &Plasma::Corona::availableScreenRectChanged, this, [&]() {
2017-02-11 06:12:17 +03:00
if (formFactor() == Plasma::Types::Vertical)
syncGeometry();
});
connect(this, &DockView::drawShadowsChanged, this, &DockView::syncGeometry);
connect(this, &DockView::maxLengthChanged, this, &DockView::syncGeometry);
connect(this, &DockView::alignmentChanged, this, &DockView::updateEnabledBorders);
connect(this, &DockView::locationChanged, this, [&]() {
updateFormFactor();
syncGeometry();
});
2017-01-22 01:40:16 +03:00
rootContext()->setContextProperty(QStringLiteral("dock"), this);
2016-12-31 00:25:27 +03:00
setSource(corona()->kPackage().filePath("lattedockui"));
setVisible(true);
2017-01-12 21:04:27 +03:00
syncGeometry();
qDebug() << "SOURCE:" << source();
2016-12-31 00:22:28 +03:00
}
2016-12-31 00:25:27 +03:00
void DockView::adaptToScreen(QScreen *screen)
2016-12-31 00:22:28 +03:00
{
/* if (!screen) {
return;
}
qDebug() << "adapting to screen...";
2016-12-31 00:22:28 +03:00
setScreen(screen);
2017-01-16 22:07:49 +03:00
//FIXME:: This code in a multi-screen environment that
//primary screen is not set to 0 it creates an endless
//showing loop at startup (catch-up race) between screen:0 and primaryScreen
if (this->containment())
this->containment()->reactToScreenChange();
syncGeometry(); */
}
void DockView::setCurrentScreen(const QString id)
{
if (!m_screenToFollow || m_screenToFollow->name() == id){
return;
}
QScreen *nextScreen{nullptr};
foreach(auto scr, qGuiApp->screens()){
if (scr && scr->name() == id){
nextScreen = scr;
break;
}
}
if (nextScreen)
setScreenToFollow(nextScreen);
}
void DockView::setScreenToFollow(QScreen *screen)
{
if (!screen || m_screenToFollow == screen) {
return;
}
m_screenToFollow = screen;
m_screenToFollowId = screen->name();
qDebug() << "adapting to screen...";
setScreen(screen);
if (this->containment())
this->containment()->reactToScreenChange();
2017-01-16 22:07:49 +03:00
2017-01-12 21:04:27 +03:00
syncGeometry();
2016-12-31 00:22:28 +03:00
}
void DockView::reconsiderScreen()
{
qDebug() << " Delayer ";
foreach(auto scr, qGuiApp->screens()){
qDebug() << " D, found screen: "<<scr->name();
}
foreach(auto scr, qGuiApp->screens()){
if (scr && scr->name() == m_screenToFollowId){
connect(scr, &QScreen::geometryChanged, this, &DockView::screenGeometryChanged);
setScreenToFollow(scr);
syncGeometry();
}
}
emit docksCountChanged();
}
void DockView::screenChanged(QScreen *scr)
{
// if (!scr || m_screenToFollow == scr) {
// return;
// }
// qDebug() << "Screen inconsistency!!! :" << scr->name() << " - " <<m_screenToFollow->name();
QTimer::singleShot(2500, this, &DockView::reconsiderScreen);
/*bool found{false};
foreach(auto scr, qGuiApp->screens()){
qDebug() << "Found screen: "<<scr->name();
if (scr && scr == m_screenToFollow){
found=true;
//break;
}
}
if (found) {
//IMPORTAT!!! this code creates crashes when changing plasma
//layouts it needs inverstigation!!!
setScreen(m_screenToFollow);
syncGeometry();
}*/
// emit docksCountChanged();
}
2016-12-31 00:25:27 +03:00
void DockView::addNewDock()
2016-12-31 00:22:28 +03:00
{
2017-01-16 21:24:46 +03:00
auto *dockCorona = qobject_cast<DockCorona *>(this->corona());
2017-01-16 22:07:49 +03:00
2017-01-16 21:24:46 +03:00
if (dockCorona) {
dockCorona->loadDefaultLayout();
2016-12-31 00:22:28 +03:00
}
}
2016-12-31 00:25:27 +03:00
void DockView::removeDock()
2016-12-31 00:22:28 +03:00
{
2017-01-16 21:24:46 +03:00
if (docksCount() > 1) {
QAction *removeAct = this->containment()->actions()->action(QStringLiteral("remove"));
2017-01-16 22:07:49 +03:00
2016-12-31 00:22:28 +03:00
if (removeAct) {
removeAct->trigger();
}
}
}
2016-12-31 00:25:27 +03:00
QQmlListProperty<QScreen> DockView::screens()
2016-12-31 00:22:28 +03:00
{
return QQmlListProperty<QScreen>(this, nullptr, &countScreens, &atScreens);
}
2016-12-31 00:25:27 +03:00
int DockView::countScreens(QQmlListProperty<QScreen> *property)
2016-12-31 00:22:28 +03:00
{
Q_UNUSED(property)
return qGuiApp->screens().count();
}
2016-12-31 00:25:27 +03:00
QScreen *DockView::atScreens(QQmlListProperty<QScreen> *property, int index)
2016-12-31 00:22:28 +03:00
{
Q_UNUSED(property)
return qGuiApp->screens().at(index);
}
QString DockView::currentScreen() const
{
return m_screenToFollowId;
}
2016-12-31 00:25:27 +03:00
void DockView::showConfigurationInterface(Plasma::Applet *applet)
2016-12-31 00:22:28 +03:00
{
if (!applet || !applet->containment())
return;
2017-01-16 22:07:49 +03:00
2016-12-31 00:22:28 +03:00
Plasma::Containment *c = qobject_cast<Plasma::Containment *>(applet);
2017-01-16 22:07:49 +03:00
if (m_configView && c && c->isContainment() && c == this->containment()) {
2016-12-31 00:22:28 +03:00
if (m_configView->isVisible()) {
m_configView->hide();
} else {
m_configView->show();
}
2017-01-16 22:07:49 +03:00
2016-12-31 00:22:28 +03:00
return;
} else if (m_configView) {
if (m_configView->applet() == applet) {
m_configView->show();
m_configView->requestActivate();
return;
} else {
m_configView->hide();
m_configView->deleteLater();
}
}
2017-01-16 22:07:49 +03:00
bool delayConfigView = false;
2017-01-16 22:07:49 +03:00
if (c && containment() && c->isContainment() && c->id() == this->containment()->id()) {
2016-12-31 00:22:28 +03:00
m_configView = new DockConfigView(c, this);
delayConfigView = true;
2016-12-31 00:22:28 +03:00
} else {
m_configView = new PlasmaQuick::ConfigView(applet);
}
2017-01-16 22:07:49 +03:00
m_configView.data()->init();
2017-01-16 22:07:49 +03:00
if (!delayConfigView) {
m_configView.data()->show();
} else {
//add a timer for showing the configuration window the first time it is
//created in order to give the containmnent's layouts the time to
//calculate the window's height
QTimer::singleShot(150, m_configView, SLOT(show()));
}
2016-12-31 00:22:28 +03:00
}
2016-12-31 00:25:27 +03:00
void DockView::resizeWindow()
2016-12-31 00:22:28 +03:00
{
if (formFactor() == Plasma::Types::Vertical) {
QSize screenSize = corona()->availableScreenRect(this->containment()->screen()).size();
QSize size{maxThickness(), screenSize.height()};
if (m_drawShadows) {
size.setWidth(normalThickness());
2017-02-06 04:55:41 +03:00
size.setHeight(static_cast<int>(maxLength() * screenSize.height()));
}
2016-12-31 00:22:28 +03:00
setMinimumSize(size);
setMaximumSize(size);
resize(size);
} else {
2017-02-13 19:53:54 +03:00
QSize screenSize = this->screen()->size();
QSize size{screenSize.width(), maxThickness()};
if (m_drawShadows) {
2017-02-06 04:55:41 +03:00
size.setWidth(static_cast<int>(maxLength() * screenSize.width()));
size.setHeight(normalThickness());
}
2016-12-31 00:22:28 +03:00
setMinimumSize(size);
setMaximumSize(size);
resize(size);
2017-02-11 06:12:17 +03:00
if (corona())
emit corona()->availableScreenRectChanged();
2016-12-31 00:22:28 +03:00
}
}
2016-12-31 03:26:48 +03:00
void DockView::setLocalDockGeometry(const QRect &geometry)
{
2017-02-11 06:12:17 +03:00
updateAbsDockGeometry(geometry);
2016-12-31 03:26:48 +03:00
}
2017-02-11 06:12:17 +03:00
void DockView::updateAbsDockGeometry(const QRect &localDockGeometry)
2016-12-31 03:26:48 +03:00
{
2017-02-11 06:12:17 +03:00
QRect absGeometry {x() + localDockGeometry.x(), y() + localDockGeometry.y()
, localDockGeometry.width() - 1, localDockGeometry.height() - 1};
2017-02-11 06:12:17 +03:00
if (m_absGeometry == absGeometry)
return;
2017-01-16 22:07:49 +03:00
2017-02-11 06:12:17 +03:00
m_absGeometry = absGeometry;
syncGeometry();
emit absGeometryChanged(m_absGeometry);
2016-12-31 03:26:48 +03:00
}
void DockView::updatePosition()
2016-12-31 00:22:28 +03:00
{
2017-02-11 06:12:17 +03:00
QRect screenGeometry;
2016-12-31 00:22:28 +03:00
QPoint position;
position = {0, 0};
2017-01-16 22:07:49 +03:00
const auto length = [&](int length) -> int {
return static_cast<int>(length * (1 - maxLength()) / 2);
};
int cleanThickness = normalThickness() - shadow();
2016-12-31 00:22:28 +03:00
switch (location()) {
case Plasma::Types::TopEdge:
screenGeometry = this->screen()->geometry();
if (m_drawShadows) {
position = {screenGeometry.x() + length(screenGeometry.width()), screenGeometry.y()};
} else {
position = {screenGeometry.x(), screenGeometry.y()};
}
break;
case Plasma::Types::BottomEdge:
screenGeometry = this->screen()->geometry();
qDebug() << "screen geometry: "<<screenGeometry;
if (m_drawShadows) {
position = {screenGeometry.x() + length(screenGeometry.width()),
screenGeometry.y() + screenGeometry.height() - cleanThickness
};
} else {
position = {screenGeometry.x(), screenGeometry.y() + screenGeometry.height() - height()};
}
break;
case Plasma::Types::RightEdge:
screenGeometry = corona()->availableScreenRect(this->containment()->screen());
if (m_drawShadows && !mask().isNull()) {
position = {screenGeometry.x() + screenGeometry.width() - cleanThickness,
screenGeometry.y() + length(screenGeometry.height())
};
} else {
position = {screenGeometry.x() + screenGeometry.width() - width(), screenGeometry.y()};
}
break;
case Plasma::Types::LeftEdge:
screenGeometry = corona()->availableScreenRect(this->containment()->screen());
if (m_drawShadows && !mask().isNull()) {
position = {screenGeometry.x(), screenGeometry.y() + length(screenGeometry.height())};
} else {
position = {screenGeometry.x(), screenGeometry.y()};
}
break;
default:
qWarning() << "wrong location, couldn't update the panel position"
<< location();
2016-12-31 00:22:28 +03:00
}
2017-01-16 22:07:49 +03:00
setPosition(position);
2016-12-31 00:22:28 +03:00
}
2017-01-12 21:04:27 +03:00
inline void DockView::syncGeometry()
{
2017-02-13 19:53:54 +03:00
if (!(this->screen() && this->containment()))
2017-02-11 06:12:17 +03:00
return;
//if (qGuiApp->primaryScreen() && screen() != qGuiApp->primaryScreen()){
// setScreen(qGuiApp->primaryScreen());
//}
bool found{false};
if (this->screen() != m_screenToFollow) {
qDebug() << "Sync Geometry screens incosistent!!!!";
foreach(auto scr, qGuiApp->screens()){
qDebug() << "Found screen: "<<scr->name();
if (scr && scr->name() == m_screenToFollowId){
qDebug() << " found ... ";
//setScreenToFollow(scr);
// found=true;
}
}
QTimer::singleShot(2500, this, &DockView::reconsiderScreen);
//if (found)
// setScreenToFollow(m_screenToFollow);
} else {
found = true;
}
if (found) {
updateEnabledBorders();
resizeWindow();
updatePosition();
}
2017-01-28 20:34:03 +03:00
// qDebug() << "dock geometry:" << qRectToStr(geometry());
2017-01-12 21:04:27 +03:00
}
void DockView::statusChanged(Plasma::Types::ItemStatus status)
{
if (containment()) {
if (containment()->status() >= Plasma::Types::NeedsAttentionStatus &&
containment()->status() != Plasma::Types::HiddenStatus) {
m_visibility->setBlockHiding(true);
} else {
m_visibility->setBlockHiding(false);
}
}
}
2016-12-31 00:25:27 +03:00
int DockView::currentThickness() const
2016-12-31 00:22:28 +03:00
{
if (formFactor() == Plasma::Types::Vertical) {
return m_maskArea.isNull() ? width() : m_maskArea.width() - m_shadow;
2016-12-31 00:22:28 +03:00
} else {
return m_maskArea.isNull() ? height() : m_maskArea.height() - m_shadow;
2016-12-31 00:22:28 +03:00
}
}
int DockView::normalThickness() const
{
return m_normalThickness;
}
void DockView::setNormalThickness(int thickness)
{
if (m_normalThickness == thickness) {
return;
}
m_normalThickness = thickness;
emit normalThicknessChanged();
}
int DockView::docksCount() const
{
auto dockCorona = qobject_cast<DockCorona *>(corona());
2017-01-16 22:07:49 +03:00
if (!dockCorona || !this->containment())
return 0;
2017-01-16 22:07:49 +03:00
return dockCorona->docksCount(this->containment()->screen());
}
void DockView::updateFormFactor()
2016-12-31 00:22:28 +03:00
{
if (!this->containment())
return;
2017-01-16 22:07:49 +03:00
switch (location()) {
case Plasma::Types::TopEdge:
case Plasma::Types::BottomEdge:
this->containment()->setFormFactor(Plasma::Types::Horizontal);
break;
case Plasma::Types::LeftEdge:
case Plasma::Types::RightEdge:
this->containment()->setFormFactor(Plasma::Types::Vertical);
break;
default:
qWarning() << "wrong location, couldn't update the panel position" << location();
}
}
2016-12-31 00:22:28 +03:00
bool DockView::drawShadows() const
{
return m_drawShadows;
}
void DockView::setDrawShadows(bool draw)
{
if (m_drawShadows == draw) {
return;
}
m_drawShadows = draw;
if (m_drawShadows) {
PanelShadows::self()->addWindow(this, enabledBorders());
} else {
PanelShadows::self()->removeWindow(this);
m_enabledBorders = Plasma::FrameSvg::AllBorders;
emit enabledBordersChanged();
}
emit drawShadowsChanged();
}
float DockView::maxLength() const
{
return m_maxLength;
}
void DockView::setMaxLength(float length)
{
if (m_maxLength == length) {
return;
}
m_maxLength = length;
emit maxLengthChanged();
}
2016-12-31 00:25:27 +03:00
int DockView::maxThickness() const
2016-12-31 00:22:28 +03:00
{
return m_maxThickness;
}
2016-12-31 00:25:27 +03:00
void DockView::setMaxThickness(int thickness)
2016-12-31 00:22:28 +03:00
{
if (m_maxThickness == thickness)
return;
2017-01-16 22:07:49 +03:00
2016-12-31 00:22:28 +03:00
m_maxThickness = thickness;
2017-01-12 21:04:27 +03:00
syncGeometry();
2016-12-31 00:22:28 +03:00
emit maxThicknessChanged();
}
int DockView::alignment() const
{
2017-02-11 06:12:17 +03:00
return m_alignment;
}
void DockView::setAlignment(int alignment)
{
2017-02-11 06:12:17 +03:00
Dock::Alignment align = static_cast<Dock::Alignment>(alignment);
2017-02-11 06:12:17 +03:00
if (m_alignment == alignment) {
return;
}
m_alignment = align;
emit alignmentChanged();
}
2016-12-31 00:25:27 +03:00
QRect DockView::maskArea() const
2016-12-31 00:22:28 +03:00
{
return m_maskArea;
}
2016-12-31 00:25:27 +03:00
void DockView::setMaskArea(QRect area)
2016-12-31 00:22:28 +03:00
{
if (m_maskArea == area)
2016-12-31 00:22:28 +03:00
return;
2017-01-16 22:07:49 +03:00
2016-12-31 00:22:28 +03:00
m_maskArea = area;
setMask(m_maskArea);
//qDebug() << "dock mask set:" << m_maskArea;
emit maskAreaChanged();
}
2017-02-11 06:12:17 +03:00
QRect DockView::absGeometry() const
{
return m_absGeometry;
}
QRect DockView::screenGeometry() const
{
if (this->screen()) {
QRect geom = this->screen()->geometry();
return geom;
}
return QRect();
}
int DockView::shadow() const
{
return m_shadow;
}
void DockView::setShadow(int shadow)
{
2017-01-16 21:24:46 +03:00
if (m_shadow == shadow)
return;
2017-01-16 22:07:49 +03:00
m_shadow = shadow;
if (m_drawShadows) {
syncGeometry();
}
emit shadowChanged();
}
bool DockView::tasksPresent()
{
foreach (Plasma::Applet *applet, this->containment()->applets()) {
KPluginMetaData meta = applet->kPackage().metadata();
2017-01-16 22:07:49 +03:00
2017-01-16 21:24:46 +03:00
if (meta.pluginId() == "org.kde.latte.plasmoid")
return true;
}
2017-01-16 22:07:49 +03:00
return false;
}
VisibilityManager *DockView::visibility() const
2016-12-31 00:22:28 +03:00
{
return m_visibility;
}
2016-12-31 00:25:27 +03:00
bool DockView::event(QEvent *e)
2016-12-31 00:22:28 +03:00
{
emit eventTriggered(e);
2017-02-26 20:37:46 +03:00
if (e->type() == QEvent::Leave) {
engine()->collectGarbage();
engine()->clearComponentCache();
engine()->trimComponentCache();
}
2016-12-31 00:22:28 +03:00
return ContainmentView::event(e);
}
2016-12-31 00:25:27 +03:00
QList<int> DockView::freeEdges() const
2016-12-31 00:22:28 +03:00
{
if (!this->corona() || !this->containment()) {
const QList<int> emptyEdges;
return emptyEdges;
}
const auto edges = corona()->freeEdges(this->containment()->screen());
2016-12-31 00:22:28 +03:00
QList<int> edgesInt;
2017-01-16 22:07:49 +03:00
2016-12-31 00:22:28 +03:00
foreach (Plasma::Types::Location edge, edges) {
2016-12-31 03:26:48 +03:00
edgesInt.append(static_cast<int>(edge));
2016-12-31 00:22:28 +03:00
}
2017-01-16 22:07:49 +03:00
2016-12-31 00:22:28 +03:00
return edgesInt;
}
void DockView::closeApplication()
{
2017-01-16 21:24:46 +03:00
DockCorona *dockCorona = qobject_cast<DockCorona *>(this->corona());
2017-01-16 22:07:49 +03:00
if (dockCorona)
2017-01-16 21:24:46 +03:00
dockCorona->closeApplication();
}
QVariantList DockView::containmentActions()
{
QVariantList actions;
/*if (containment()->corona()->immutability() != Plasma::Types::Mutable) {
return actions;
}*/
//FIXME: the trigger string it should be better to be supported this way
//const QString trigger = Plasma::ContainmentActions::eventToString(event);
const QString trigger = "RightButton;NoModifier";
Plasma::ContainmentActions *plugin = this->containment()->containmentActions().value(trigger);
2017-01-16 22:07:49 +03:00
if (!plugin) {
return actions;
}
2017-01-16 22:07:49 +03:00
if (plugin->containment() != this->containment()) {
plugin->setContainment(this->containment());
// now configure it
KConfigGroup cfg(this->containment()->corona()->config(), "ActionPlugins");
cfg = KConfigGroup(&cfg, QString::number(this->containment()->containmentType()));
KConfigGroup pluginConfig = KConfigGroup(&cfg, trigger);
plugin->restore(pluginConfig);
}
2017-01-16 22:07:49 +03:00
foreach (QAction *ac, plugin->contextualActions()) {
actions << QVariant::fromValue<QAction *>(ac);
}
2017-01-16 22:07:49 +03:00
return actions;
}
//!BEGIN overriding context menus behavior
void DockView::menuAboutToHide()
{
m_contextMenu = 0;
m_visibility->setBlockHiding(false);
}
void DockView::mouseReleaseEvent(QMouseEvent *event)
{
if (!event || !this->containment()) {
return;
}
2017-01-16 22:07:49 +03:00
PlasmaQuick::ContainmentView::mouseReleaseEvent(event);
event->setAccepted(this->containment()->containmentActions().contains(Plasma::ContainmentActions::eventToString(event)));
}
void DockView::mousePressEvent(QMouseEvent *event)
{
//qDebug() << "Step -1 ...";
if (!event || !this->containment()) {
return;
}
2017-01-16 22:07:49 +03:00
//qDebug() << "Step 0...";
2017-01-16 22:07:49 +03:00
//even if the menu is executed synchronously, other events may be processed
//by the qml incubator when plasma is loading, so we need to guard there
if (m_contextMenu) {
2017-02-19 21:17:24 +03:00
//qDebug() << "Step 0.5 ...";
m_contextMenu->close();
m_contextMenu = 0;
PlasmaQuick::ContainmentView::mousePressEvent(event);
return;
}
2017-01-16 22:07:49 +03:00
//qDebug() << "1 ...";
const QString trigger = Plasma::ContainmentActions::eventToString(event);
2017-01-16 22:07:49 +03:00
if (trigger == "RightButton;NoModifier") {
Plasma::ContainmentActions *plugin = this->containment()->containmentActions().value(trigger);
2017-01-16 22:07:49 +03:00
if (!plugin || plugin->contextualActions().isEmpty()) {
event->setAccepted(false);
return;
}
2017-01-16 22:07:49 +03:00
//qDebug() << "2 ...";
//the plugin can be a single action or a context menu
//Don't have an action list? execute as single action
//and set the event position as action data
/*if (plugin->contextualActions().length() == 1) {
QAction *action = plugin->contextualActions().at(0);
action->setData(event->pos());
action->trigger();
event->accept();
return;
}*/
//FIXME: very inefficient appletAt() implementation
Plasma::Applet *applet = 0;
2017-01-27 21:03:24 +03:00
bool inSystray = false;
2017-01-16 22:07:49 +03:00
foreach (Plasma::Applet *appletTemp, this->containment()->applets()) {
PlasmaQuick::AppletQuickItem *ai = appletTemp->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
if (ai && ai->isVisible() && ai->contains(ai->mapFromItem(contentItem(), event->pos()))) {
applet = ai->applet();
2017-01-27 21:03:24 +03:00
KPluginMetaData meta = applet->kPackage().metadata();
2017-01-27 21:03:24 +03:00
//Try to find applets inside a systray
if (meta.pluginId() == "org.kde.plasma.systemtray") {
auto systrayId = applet->config().readEntry("SystrayContainmentId");
2017-01-27 21:03:24 +03:00
applet = 0;
inSystray = true;
Plasma::Containment *cont = containmentById(systrayId.toInt());
2017-01-27 21:03:24 +03:00
if (cont) {
foreach (Plasma::Applet *appletCont, cont->applets()) {
PlasmaQuick::AppletQuickItem *ai2 = appletCont->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
if (ai2 && ai2->isVisible() && ai2->contains(ai2->mapFromItem(contentItem(), event->pos()))) {
applet = ai2->applet();
break;
}
}
}
break;
} else {
ai = 0;
}
}
}
2017-01-16 22:07:49 +03:00
2017-01-27 21:03:24 +03:00
if (!applet && !inSystray) {
applet = this->containment();
}
//qDebug() << "3 ...";
2017-02-19 20:06:37 +03:00
if (applet) {
2017-01-03 21:44:14 +03:00
KPluginMetaData meta = applet->kPackage().metadata();
2017-01-16 22:07:49 +03:00
//qDebug() << "3.5 ...";
2017-02-19 20:06:37 +03:00
if (meta.pluginId() != "org.kde.latte.plasmoid") {
2017-02-19 21:25:05 +03:00
//qDebug() << "4...";
QMenu *desktopMenu = new QMenu;
desktopMenu->setAttribute(Qt::WA_DeleteOnClose);
m_contextMenu = desktopMenu;
2017-01-16 22:07:49 +03:00
if (this->mouseGrabberItem()) {
//workaround, this fixes for me most of the right click menu behavior
this->mouseGrabberItem()->ungrabMouse();
2017-01-16 22:07:49 +03:00
return;
}
2017-01-16 22:07:49 +03:00
//qDebug() << "5 ...";
2017-01-16 22:07:49 +03:00
if (applet) {
//qDebug() << "5.3 ...";
emit applet->contextualActionsAboutToShow();
addAppletActions(desktopMenu, applet, event);
} else {
//qDebug() << "5.6 ...";
emit this->containment()->contextualActionsAboutToShow();
addContainmentActions(desktopMenu, event);
}
2017-01-16 22:07:49 +03:00
//this is a workaround where Qt now creates the menu widget
//in .exec before oxygen can polish it and set the following attribute
desktopMenu->setAttribute(Qt::WA_TranslucentBackground);
//end workaround
QPoint pos = event->globalPos();
2017-01-16 22:07:49 +03:00
if (applet) {
//qDebug() << "6 ...";
desktopMenu->adjustSize();
2017-01-16 22:07:49 +03:00
if (this->screen()) {
const QRect scr = this->screen()->geometry();
int smallStep = 3;
int x = event->globalPos().x() + smallStep;
int y = event->globalPos().y() + smallStep;
2017-01-16 22:07:49 +03:00
//qDebug()<<x << " - "<<y;
2017-01-16 22:07:49 +03:00
if (event->globalPos().x() > scr.center().x()) {
x = event->globalPos().x() - desktopMenu->width() - smallStep;
}
2017-01-16 22:07:49 +03:00
if (event->globalPos().y() > scr.center().y()) {
y = event->globalPos().y() - desktopMenu->height() - smallStep;
}
2017-01-16 22:07:49 +03:00
pos = QPoint(x, y);
}
}
2017-01-16 22:07:49 +03:00
//qDebug() << "7...";
2017-01-16 22:07:49 +03:00
if (desktopMenu->isEmpty()) {
//qDebug() << "7.5 ...";
delete desktopMenu;
event->accept();
return;
}
2017-01-16 22:07:49 +03:00
connect(desktopMenu, SIGNAL(aboutToHide()), this, SLOT(menuAboutToHide()));
m_visibility->setBlockHiding(true);
desktopMenu->popup(pos);
event->setAccepted(true);
return;
}
2017-02-19 20:06:37 +03:00
//qDebug() << "8 ...";
}
2017-02-19 20:06:37 +03:00
//qDebug() << "9 ...";
}
2017-01-16 22:07:49 +03:00
//qDebug() << "10 ...";
PlasmaQuick::ContainmentView::mousePressEvent(event);
}
void DockView::addAppletActions(QMenu *desktopMenu, Plasma::Applet *applet, QEvent *event)
{
if (!this->containment()) {
return;
}
2017-01-16 22:07:49 +03:00
foreach (QAction *action, applet->contextualActions()) {
if (action) {
desktopMenu->addAction(action);
}
}
2017-01-16 22:07:49 +03:00
if (!applet->failedToLaunch()) {
QAction *runAssociatedApplication = applet->actions()->action(QStringLiteral("run associated application"));
2017-01-16 22:07:49 +03:00
if (runAssociatedApplication && runAssociatedApplication->isEnabled()) {
desktopMenu->addAction(runAssociatedApplication);
}
2017-01-16 22:07:49 +03:00
QAction *configureApplet = applet->actions()->action(QStringLiteral("configure"));
2017-01-16 22:07:49 +03:00
if (configureApplet && configureApplet->isEnabled()) {
desktopMenu->addAction(configureApplet);
}
2017-01-16 22:07:49 +03:00
QAction *appletAlternatives = applet->actions()->action(QStringLiteral("alternatives"));
2017-01-16 22:07:49 +03:00
if (appletAlternatives && appletAlternatives->isEnabled()) {
desktopMenu->addAction(appletAlternatives);
}
}
2017-01-16 22:07:49 +03:00
QMenu *containmentMenu = new QMenu(i18nc("%1 is the name of the containment", "%1 Options", this->containment()->title()), desktopMenu);
addContainmentActions(containmentMenu, event);
2017-01-16 22:07:49 +03:00
if (!containmentMenu->isEmpty()) {
int enabled = 0;
//count number of real actions
QListIterator<QAction *> actionsIt(containmentMenu->actions());
2017-01-16 22:07:49 +03:00
while (enabled < 3 && actionsIt.hasNext()) {
QAction *action = actionsIt.next();
2017-01-16 22:07:49 +03:00
if (action->isVisible() && !action->isSeparator()) {
++enabled;
}
}
2017-01-16 22:07:49 +03:00
2017-01-03 17:21:59 +03:00
desktopMenu->addSeparator();
2017-01-16 22:07:49 +03:00
if (enabled) {
//if there is only one, don't create a submenu
if (enabled < 2) {
foreach (QAction *action, containmentMenu->actions()) {
if (action->isVisible() && !action->isSeparator()) {
desktopMenu->addAction(action);
}
}
} else {
desktopMenu->addMenu(containmentMenu);
}
}
}
2017-01-16 22:07:49 +03:00
if (this->containment()->immutability() == Plasma::Types::Mutable &&
(this->containment()->containmentType() != Plasma::Types::PanelContainment || this->containment()->isUserConfiguring())) {
QAction *closeApplet = applet->actions()->action(QStringLiteral("remove"));
2017-01-16 22:07:49 +03:00
//qDebug() << "checking for removal" << closeApplet;
if (closeApplet) {
if (!desktopMenu->isEmpty()) {
desktopMenu->addSeparator();
}
2017-01-16 22:07:49 +03:00
//qDebug() << "adding close action" << closeApplet->isEnabled() << closeApplet->isVisible();
desktopMenu->addAction(closeApplet);
}
}
}
void DockView::addContainmentActions(QMenu *desktopMenu, QEvent *event)
{
if (!this->containment()) {
return;
}
2017-01-16 22:07:49 +03:00
if (this->containment()->corona()->immutability() != Plasma::Types::Mutable &&
!KAuthorized::authorizeAction(QStringLiteral("plasma/containment_actions"))) {
//qDebug() << "immutability";
return;
}
2017-01-16 22:07:49 +03:00
//this is what ContainmentPrivate::prepareContainmentActions was
const QString trigger = Plasma::ContainmentActions::eventToString(event);
//"RightButton;NoModifier"
Plasma::ContainmentActions *plugin = this->containment()->containmentActions().value(trigger);
2017-01-16 22:07:49 +03:00
if (!plugin) {
return;
}
2017-01-16 22:07:49 +03:00
if (plugin->containment() != this->containment()) {
plugin->setContainment(this->containment());
// now configure it
KConfigGroup cfg(this->containment()->corona()->config(), "ActionPlugins");
cfg = KConfigGroup(&cfg, QString::number(this->containment()->containmentType()));
KConfigGroup pluginConfig = KConfigGroup(&cfg, trigger);
plugin->restore(pluginConfig);
}
2017-01-16 22:07:49 +03:00
QList<QAction *> actions = plugin->contextualActions();
2017-01-16 22:07:49 +03:00
if (actions.isEmpty()) {
//it probably didn't bother implementing the function. give the user a chance to set
//a better plugin. note that if the user sets no-plugin this won't happen...
if ((this->containment()->containmentType() != Plasma::Types::PanelContainment &&
this->containment()->containmentType() != Plasma::Types::CustomPanelContainment) &&
this->containment()->actions()->action(QStringLiteral("configure"))) {
desktopMenu->addAction(this->containment()->actions()->action(QStringLiteral("configure")));
}
} else {
desktopMenu->addActions(actions);
}
2017-01-16 22:07:49 +03:00
return;
}
2017-01-27 21:03:24 +03:00
2017-02-06 04:55:41 +03:00
Plasma::Containment *DockView::containmentById(uint id)
2017-01-27 21:03:24 +03:00
{
foreach (auto containment, corona()->containments()) {
if (id == containment->id()) {
return containment;
}
}
return 0;
}
//!END overriding context menus behavior
//!BEGIN draw panel shadows outside the dock window
Plasma::FrameSvg::EnabledBorders DockView::enabledBorders() const
{
return m_enabledBorders;
}
void DockView::updateEnabledBorders()
{
// qDebug() << "draw shadow!!!! :" << m_drawShadows;
if (!this->screen()) {
return;
}
Plasma::FrameSvg::EnabledBorders borders = Plasma::FrameSvg::AllBorders;
switch (location()) {
case Plasma::Types::TopEdge:
borders &= ~Plasma::FrameSvg::TopBorder;
break;
case Plasma::Types::LeftEdge:
borders &= ~Plasma::FrameSvg::LeftBorder;
break;
case Plasma::Types::RightEdge:
borders &= ~Plasma::FrameSvg::RightBorder;
break;
case Plasma::Types::BottomEdge:
borders &= ~Plasma::FrameSvg::BottomBorder;
break;
default:
break;
}
if ((location() == Plasma::Types::LeftEdge || location() == Plasma::Types::RightEdge)) {
if (maxLength() == 1 && m_alignment == Dock::Justify) {
borders &= ~Plasma::FrameSvg::TopBorder;
borders &= ~Plasma::FrameSvg::BottomBorder;
}
if (m_alignment == Dock::Top) {
borders &= ~Plasma::FrameSvg::TopBorder;
}
if (m_alignment == Dock::Bottom) {
borders &= ~Plasma::FrameSvg::BottomBorder;
}
}
if (location() == Plasma::Types::TopEdge || location() == Plasma::Types::BottomEdge) {
if (maxLength() == 1 && m_alignment == Dock::Justify) {
borders &= ~Plasma::FrameSvg::LeftBorder;
borders &= ~Plasma::FrameSvg::RightBorder;
}
if (m_alignment == Dock::Left) {
borders &= ~Plasma::FrameSvg::LeftBorder;
}
if (m_alignment == Dock::Right) {
borders &= ~Plasma::FrameSvg::RightBorder;
}
}
if (m_enabledBorders != borders) {
m_enabledBorders = borders;
emit enabledBordersChanged();
}
if (!m_drawShadows) {
PanelShadows::self()->removeWindow(this);
} else {
PanelShadows::self()->setEnabledBorders(this, borders);
}
}
//!END draw panel shadows outside the dock window
2016-12-31 00:22:28 +03:00
}
//!END namespace