1
0
mirror of https://github.com/KDE/latte-dock.git synced 2024-12-26 11:21:40 +03:00

fix #636,new approach for Layout,Global launchers

--changed the design totally and use only signals
between plasmoid in order to update their models. This
way the launcherList from their tasksmodel should be
updated only on the initialization phase of the Latte
plasmoid. Afterwards signaling between them takes
place, in order to inform each other for adding,
removing launchers, moving them and assigning them
to activities
This commit is contained in:
Michail Vourlakos 2017-07-31 03:53:39 +03:00
parent bd05c7dfed
commit eefbc5e9ec
9 changed files with 413 additions and 52 deletions

View File

@ -24,6 +24,7 @@ set(lattedock-app_SRCS
layoutsDelegates/colorcmbboxitemdelegate.cpp
layoutsDelegates/activitycmbboxdelegate.cpp
infoview.cpp
launcherssignals.cpp
main.cpp
)

View File

@ -26,6 +26,7 @@
#include "layoutmanager.h"
#include "universalsettings.h"
#include "../liblattedock/dock.h"
#include "launcherssignals.h"
#include <QObject>
@ -36,6 +37,7 @@ class ScreenPool;
class GlobalShortcuts;
class UniversalSettings;
class LayoutManager;
class LaunchersSignals;
namespace KActivities {
class Consumer;
@ -159,6 +161,7 @@ private:
friend class GlobalShortcuts;
friend class LayoutManager;
friend class LaunchersSignals;
};
}

234
app/launcherssignals.cpp Normal file
View File

@ -0,0 +1,234 @@
/*
* Copyright 2017 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 "launcherssignals.h"
namespace Latte {
LaunchersSignals::LaunchersSignals(QObject *parent)
: QObject(parent)
{
m_manager = qobject_cast<LayoutManager *>(parent);
}
LaunchersSignals::~LaunchersSignals()
{
}
QList<Plasma::Applet *> LaunchersSignals::lattePlasmoids()
{
QList<Plasma::Applet *> applets;
foreach (auto containment, m_manager->corona()->containments()) {
for (auto *applet : containment->applets()) {
KPluginMetaData meta = applet->kPackage().metadata();
if (meta.pluginId() == "org.kde.latte.plasmoid") {
applets.append(applet);
}
}
}
return applets;
}
void LaunchersSignals::addLauncher(int launcherGroup, QString launcher)
{
if ((Dock::LaunchersGroup)launcherGroup == Dock::UniqueLaunchers) {
return;
}
foreach (auto applet, lattePlasmoids()) {
if (QQuickItem *appletInterface = applet->property("_plasma_graphicObject").value<QQuickItem *>()) {
const auto &childItems = appletInterface->childItems();
if (childItems.isEmpty()) {
continue;
}
for (QQuickItem *item : childItems) {
if (auto *metaObject = item->metaObject()) {
int methodIndex = metaObject->indexOfMethod("extSignalAddLauncher(QVariant,QVariant)");
if (methodIndex == -1) {
continue;
}
QMetaMethod method = metaObject->method(methodIndex);
method.invoke(item, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launcher));
}
}
}
}
}
void LaunchersSignals::removeLauncher(int launcherGroup, QString launcher)
{
if ((Dock::LaunchersGroup)launcherGroup == Dock::UniqueLaunchers) {
return;
}
foreach (auto applet, lattePlasmoids()) {
if (QQuickItem *appletInterface = applet->property("_plasma_graphicObject").value<QQuickItem *>()) {
const auto &childItems = appletInterface->childItems();
if (childItems.isEmpty()) {
continue;
}
for (QQuickItem *item : childItems) {
if (auto *metaObject = item->metaObject()) {
int methodIndex = metaObject->indexOfMethod("extSignalRemoveLauncher(QVariant,QVariant)");
if (methodIndex == -1) {
continue;
}
QMetaMethod method = metaObject->method(methodIndex);
method.invoke(item, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launcher));
}
}
}
}
}
void LaunchersSignals::addLauncherToActivity(int launcherGroup, QString launcher, QString activity)
{
if ((Dock::LaunchersGroup)launcherGroup == Dock::UniqueLaunchers) {
return;
}
foreach (auto applet, lattePlasmoids()) {
if (QQuickItem *appletInterface = applet->property("_plasma_graphicObject").value<QQuickItem *>()) {
const auto &childItems = appletInterface->childItems();
if (childItems.isEmpty()) {
continue;
}
for (QQuickItem *item : childItems) {
if (auto *metaObject = item->metaObject()) {
int methodIndex = metaObject->indexOfMethod("extSignalAddLauncherToActivity(QVariant,QVariant,QVariant)");
if (methodIndex == -1) {
continue;
}
QMetaMethod method = metaObject->method(methodIndex);
method.invoke(item, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launcher), Q_ARG(QVariant, activity));
}
}
}
}
}
void LaunchersSignals::removeLauncherFromActivity(int launcherGroup, QString launcher, QString activity)
{
if ((Dock::LaunchersGroup)launcherGroup == Dock::UniqueLaunchers) {
return;
}
foreach (auto applet, lattePlasmoids()) {
if (QQuickItem *appletInterface = applet->property("_plasma_graphicObject").value<QQuickItem *>()) {
const auto &childItems = appletInterface->childItems();
if (childItems.isEmpty()) {
continue;
}
for (QQuickItem *item : childItems) {
if (auto *metaObject = item->metaObject()) {
int methodIndex = metaObject->indexOfMethod("extSignalRemoveLauncherFromActivity(QVariant,QVariant,QVariant)");
if (methodIndex == -1) {
continue;
}
QMetaMethod method = metaObject->method(methodIndex);
method.invoke(item, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launcher), Q_ARG(QVariant, activity));
}
}
}
}
}
void LaunchersSignals::urlsDropped(int launcherGroup, QStringList urls)
{
if ((Dock::LaunchersGroup)launcherGroup == Dock::UniqueLaunchers) {
return;
}
foreach (auto applet, lattePlasmoids()) {
if (QQuickItem *appletInterface = applet->property("_plasma_graphicObject").value<QQuickItem *>()) {
const auto &childItems = appletInterface->childItems();
if (childItems.isEmpty()) {
continue;
}
for (QQuickItem *item : childItems) {
if (auto *metaObject = item->metaObject()) {
int methodIndex = metaObject->indexOfMethod("extSignalUrlsDropped(QVariant,QVariant)");
if (methodIndex == -1) {
continue;
}
QMetaMethod method = metaObject->method(methodIndex);
method.invoke(item, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, urls));
}
}
}
}
}
void LaunchersSignals::moveTask(int launcherGroup, int from, int to)
{
if ((Dock::LaunchersGroup)launcherGroup == Dock::UniqueLaunchers) {
return;
}
foreach (auto applet, lattePlasmoids()) {
if (QQuickItem *appletInterface = applet->property("_plasma_graphicObject").value<QQuickItem *>()) {
const auto &childItems = appletInterface->childItems();
if (childItems.isEmpty()) {
continue;
}
for (QQuickItem *item : childItems) {
if (auto *metaObject = item->metaObject()) {
int methodIndex = metaObject->indexOfMethod("extSignalMoveTask(QVariant,QVariant,QVariant)");
if (methodIndex == -1) {
continue;
}
QMetaMethod method = metaObject->method(methodIndex);
method.invoke(item, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, from), Q_ARG(QVariant, to));
}
}
}
}
}
} //end of namespace

63
app/launcherssignals.h Normal file
View File

@ -0,0 +1,63 @@
/*
* Copyright 2017 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/>.
*/
#ifndef LAUNCHERSSIGNALS_H
#define LAUNCHERSSIGNALS_H
#include "layoutmanager.h"
#include "../liblattedock/dock.h"
#include <QObject>
class LayoutManager;
namespace Latte {
//! in order to support property the launcher groups Layout and Global
//! the latte plasmoids must communicate between them with signals when
//! there are changes in their models. This way we are trying to avoid
//! crashes that occur by setting the launcherList of the tasksModel so
//! often. The plasma devs of libtaskmanager have designed the launchers
//! model to be initialized only once during startup
class LaunchersSignals : public QObject {
Q_OBJECT
public:
LaunchersSignals(QObject *parent);
~LaunchersSignals() override;
public slots:
Q_INVOKABLE void addLauncher(int launcherGroup, QString launcher);
Q_INVOKABLE void removeLauncher(int launcherGroup, QString launcher);
Q_INVOKABLE void addLauncherToActivity(int launcherGroup, QString launcher, QString activity);
Q_INVOKABLE void removeLauncherFromActivity(int launcherGroup, QString launcher, QString activity);
Q_INVOKABLE void urlsDropped(int launcherGroup, QStringList urls);
Q_INVOKABLE void moveTask(int launcherGroup, int from, int to);
private:
QList<Plasma::Applet *> lattePlasmoids();
private:
LayoutManager *m_manager{nullptr};
};
}
#endif

View File

@ -21,7 +21,6 @@
#include "layoutmanager.h"
#include "infoview.h"
#include <QDir>
#include <QFile>
#include <QQmlProperty>
@ -35,7 +34,8 @@ namespace Latte {
LayoutManager::LayoutManager(QObject *parent)
: QObject(parent),
m_importer(new Importer(this))
m_importer(new Importer(this)),
m_launchersSignals(new LaunchersSignals(this))
{
m_corona = qobject_cast<DockCorona *>(parent);
@ -58,6 +58,7 @@ LayoutManager::LayoutManager(QObject *parent)
LayoutManager::~LayoutManager()
{
m_importer->deleteLater();
m_launchersSignals->deleteLater();
if (m_currentLayout) {
m_currentLayout->deleteLater();
@ -115,6 +116,11 @@ LayoutSettings *LayoutManager::currentLayout()
return m_currentLayout;
}
LaunchersSignals *LayoutManager::launchersSignals()
{
return m_launchersSignals;
}
QString LayoutManager::currentLayoutName() const
{
if (m_corona && m_corona->universalSettings()) {

View File

@ -25,6 +25,7 @@
#include "importer.h"
#include "layoutsettings.h"
#include "layoutconfigdialog.h"
#include "launcherssignals.h"
#include <QAction>
#include <QObject>
@ -34,6 +35,7 @@
class Importer;
class LayoutSettings;
class LayoutConfigDialog;
class LaunchersSignals;
namespace Latte {
@ -50,6 +52,7 @@ class LayoutManager : public QObject {
Q_PROPERTY(QAction *addWidgetsAction READ addWidgetsAction NOTIFY addWidgetsActionChanged)
Q_PROPERTY(LayoutSettings *currentLayout READ currentLayout NOTIFY currentLayoutChanged)
Q_PROPERTY(LaunchersSignals *launchersSignals READ launchersSignals NOTIFY launchersSignalsChanged)
public:
LayoutManager(QObject *parent = nullptr);
@ -71,6 +74,7 @@ public:
QAction *addWidgetsAction();
LayoutSettings *currentLayout();
LaunchersSignals *launchersSignals();
QStringList activities();
@ -89,6 +93,7 @@ signals:
void addWidgetsActionChanged();
void currentLayoutChanged();
void currentLayoutNameChanged();
void launchersSignalsChanged();
void layoutsChanged();
void menuLayoutsChanged();
@ -110,6 +115,7 @@ private:
Importer *m_importer{nullptr};
LayoutSettings *m_currentLayout{nullptr};
LaunchersSignals *m_launchersSignals{nullptr};
QString m_shouldSwitchToLayout;

View File

@ -624,10 +624,22 @@ PlasmaComponents.ContextMenu {
onClicked: {
if (tasksModel.launcherPosition(get(atm.LauncherUrlWithoutIcon)) != -1) {
root.launcherForRemoval = get(atm.LauncherUrlWithoutIcon);
tasksModel.requestRemoveLauncher(get(atm.LauncherUrlWithoutIcon));
var launcher = get(atm.LauncherUrl);
if (latteDock && latteDock.launchersGroup >= Latte.Dock.LayoutLaunchers) {
latteDock.universalLayoutManager.launchersSignals.removeLauncher(latteDock.launchersGroup, launcher);
} else {
tasksModel.requestAddLauncher(get(atm.LauncherUrl));
root.launcherForRemoval = launcher;
tasksModel.requestRemoveLauncher(launcher);
}
} else {
var launcher = get(atm.LauncherUrl);
if (latteDock && latteDock.launchersGroup >= Latte.Dock.LayoutLaunchers) {
latteDock.universalLayoutManager.launchersSignals.addLauncher(latteDock.launchersGroup, launcher);
} else {
tasksModel.requestAddLauncher(launcher);
}
}
}
}
@ -669,12 +681,22 @@ PlasmaComponents.ContextMenu {
result.clicked.connect(
function() {
if (result.checked) {
tasksModel.requestAddLauncherToActivity(url, id);
if (latteDock && latteDock.launchersGroup >= Latte.Dock.LayoutLaunchers) {
latteDock.universalLayoutManager.launchersSignals.addLauncherToActivity(latteDock.launchersGroup, url, id);
} else {
tasksModel.requestAddLauncherToActivity(url, id);
}
} else {
if (latteDock && latteDock.launchersGroup >= Latte.Dock.LayoutLaunchers) {
latteDock.universalLayoutManager.launchersSignals.removeLauncherFromActivity(latteDock.launchersGroup, url, id);
} else {
if (id === tasksModel.activity) {
root.launcherForRemoval = url;
}
tasksModel.requestRemoveLauncherFromActivity(url, id);
}
}
}
);
return result;
@ -718,8 +740,14 @@ PlasmaComponents.ContextMenu {
text: i18nc("Remove launcher button for application shown while it is not running", "Unpin")
onClicked: {
root.launcherForRemoval = get(atm.LauncherUrlWithoutIcon);
tasksModel.requestRemoveLauncher(get(atm.LauncherUrlWithoutIcon));
var launcher = get(atm.LauncherUrlWithoutIcon);
if (latteDock && latteDock.launchersGroup >= Latte.Dock.LayoutLaunchers) {
latteDock.universalLayoutManager.launchersSignals.removeLauncher(latteDock.launchersGroup, launcher);
} else {
root.launcherForRemoval = launcher
tasksModel.requestRemoveLauncher(launcher);
}
}
}

View File

@ -25,7 +25,8 @@ import org.kde.draganddrop 2.0
import org.kde.taskmanager 0.1 as TaskManager
//import "../code/layout.js" as LayoutManager
import org.kde.latte 0.1 as Latte
import "../code/tools.js" as TaskTools
Item {
@ -141,7 +142,12 @@ Item {
if (root.dragSource != above && root.dragSource.itemIndex != insertAt) {
// console.log(root.dragSource.itemIndex + " - "+insertAt);
root.dragSource.z = 100;
if (latteDock && latteDock.launchersGroup >= Latte.Dock.LayoutLaunchers) {
latteDock.universalLayoutManager.launchersSignals.moveTask(latteDock.launchersGroup, root.dragSource.itemIndex, insertAt);
} else {
tasksModel.move(root.dragSource.itemIndex, insertAt);
}
ignoredItem = above;
ignoreItemTimer.restart();
}

View File

@ -256,46 +256,10 @@ Item {
}
}
Connections{
target: currentLayout && latteDock.universalSettings ?
latteDock : null
onLaunchersGroupChanged: {
if(currentLayout) {
if (latteDock.launchersGroup === Latte.Dock.UniqueLaunchers) {
tasksModel.launcherList = plasmoid.configuration.launchers59;
} else if (latteDock.launchersGroup === Latte.Dock.LayoutLaunchers) {
tasksModel.launcherList = latteDock.universalLayoutManager.currentLayout.launchers;
} else if (latteDock.launchersGroup === Latte.Dock.GlobalLaunchers) {
tasksModel.launcherList = latteDock.universalSettings.launchers;
}
}
}
}
Connections{
target: currentLayout ? currentLayout : null
onLaunchersChanged: {
if (currentLayout && latteDock.launchersGroup === Latte.Dock.LayoutLaunchers) {
tasksModel.launcherList = latteDock.universalLayoutManager.currentLayout.launchers;
}
}
}
Connections{
target: currentLayout && latteDock.universalSettings ?
latteDock.universalSettings : null
onLaunchersChanged: {
if (currentLayout && latteDock.universalSettings && latteDock.launchersGroup === Latte.Dock.GlobalLaunchers) {
tasksModel.launcherList = latteDock.universalSettings.launchers;
}
}
}
property bool loadLaunchersFirstTime: false;
onCurrentLayoutChanged: {
if (currentLayout) {
if (currentLayout && !loadLaunchersFirstTime) {
if (latteDock.universalSettings
&& (latteDock.launchersGroup === Latte.Dock.LayoutLaunchers
|| latteDock.launchersGroup === Latte.Dock.GlobalLaunchers)) {
@ -307,6 +271,8 @@ Item {
} else {
tasksModel.launcherList = plasmoid.configuration.launchers59;
}
loadLaunchersFirstTime = true;
}
}
@ -314,7 +280,6 @@ Item {
PlasmaCore.ColorScope{
id: colorScopePalette
}
/////
function launchersDropped(urls){
@ -999,9 +964,13 @@ Item {
}
onUrlsDropped: {
if (latteDock && latteDock.launchersGroup >= Latte.Dock.LayoutLaunchers) {
latteDock.universalLayoutManager.launchersSignals.urlsDropped(latteDock.launchersGroup, urls);
} else {
urlsDroppedOnArea(urls);
}
}
}
ListView {
@ -1377,6 +1346,51 @@ Item {
return plasmoid.configuration.launchers59;
}
//! BEGIN ::: external launchers signals in order to update the tasks model
function extSignalAddLauncher(group, launcher) {
if (group === latteDock.launchersGroup) {
tasksModel.requestAddLauncher(launcher);
}
}
function extSignalRemoveLauncher(group, launcher) {
if (group === latteDock.launchersGroup) {
root.launcherForRemoval = launcher;
tasksModel.requestRemoveLauncher(launcher);
}
}
function extSignalAddLauncherToActivity(group, launcher, activity) {
if (group === latteDock.launchersGroup) {
tasksModel.requestAddLauncherToActivity(launcher, activity);
}
}
function extSignalRemoveLauncherFromActivity(group, launcher, activity) {
if (group === latteDock.launchersGroup) {
if (activity === tasksModel.activity) {
root.launcherForRemoval = launcher;
}
tasksModel.requestRemoveLauncherFromActivity(launcher, activity);
}
}
function extSignalUrlsDropped(group, urls) {
if (group === latteDock.launchersGroup) {
mouseHandler.urlsDroppedOnArea(urls);
}
}
function extSignalMoveTask(group, from, to) {
if (group === latteDock.launchersGroup) {
tasksModel.move(from, to);
}
}
//! END ::: external launchers signals in order to update the tasks model
//! it is used to add the fake desktop file which represents
//! the separator (fake launcher)
function addSeparator(){