Merge branch 'mart/basicDeleteUndo'
REVIEW:120885
This commit is contained in:
commit
78ab028d52
@ -58,6 +58,7 @@ find_package(KF5KIO ${KF5_DEP_VERSION} REQUIRED)
|
||||
find_package(KF5Service ${KF5_DEP_VERSION} REQUIRED)
|
||||
find_package(KF5WindowSystem ${KF5_DEP_VERSION} REQUIRED)
|
||||
find_package(KF5XmlGui ${KF5_DEP_VERSION} REQUIRED)
|
||||
find_package(KF5Notifications ${KF5_DEP_VERSION} REQUIRED)
|
||||
|
||||
find_package(KF5DocTools ${KF5_DEP_VERSION})
|
||||
set_package_properties(KF5DocTools PROPERTIES DESCRIPTION "Tools to generate documentation"
|
||||
|
@ -125,6 +125,7 @@ PRIVATE
|
||||
KF5::Declarative #runtimePlatform
|
||||
KF5::XmlGui #KActionCollection
|
||||
KF5::GlobalAccel #Applet::setGlobalShortcut
|
||||
KF5::Notifications
|
||||
${PLASMA_EXTRA_LIBS}
|
||||
)
|
||||
|
||||
@ -201,6 +202,7 @@ install(FILES
|
||||
install(FILES data/operations/dataengineservice.operations DESTINATION ${PLASMA_DATA_INSTALL_DIR}/services)
|
||||
install(FILES data/operations/plasmoidservice.operations DESTINATION ${PLASMA_DATA_INSTALL_DIR}/services)
|
||||
install(FILES data/operations/storage.operations DESTINATION ${PLASMA_DATA_INSTALL_DIR}/services)
|
||||
install(FILES data/notifications/plasmashell.notifyrc DESTINATION ${KNOTIFYRC_INSTALL_DIR})
|
||||
|
||||
install(TARGETS KF5Plasma EXPORT KF5PlasmaTargets ${KF5_INSTALL_TARGETS_DEFAULT_ARGS})
|
||||
|
||||
|
@ -104,6 +104,9 @@ Applet::Applet(const QString &packagePath, uint appletId)
|
||||
|
||||
Applet::~Applet()
|
||||
{
|
||||
if (d->transient) {
|
||||
d->resetConfigurationObject();
|
||||
}
|
||||
//let people know that i will die
|
||||
emit appletDeleted(this);
|
||||
|
||||
@ -255,6 +258,7 @@ void Applet::destroy()
|
||||
}
|
||||
|
||||
d->transient = true;
|
||||
emit destroyedChanged(true);
|
||||
//FIXME: an animation on leave if !isContainment() would be good again .. which should be handled by the containment class
|
||||
d->cleanUpAndDelete();
|
||||
}
|
||||
|
@ -383,6 +383,13 @@ Q_SIGNALS:
|
||||
*/
|
||||
void statusChanged(Plasma::Types::ItemStatus status);
|
||||
|
||||
/**
|
||||
* Emitted when the applet has been scheduled for destruction
|
||||
* or the destruction has been undone
|
||||
* @since 5.4
|
||||
*/
|
||||
void destroyedChanged(bool destroyed);
|
||||
|
||||
//CONFIGURATION
|
||||
/**
|
||||
* Emitted when an applet has changed values in its configuration
|
||||
|
9
src/plasma/data/notifications/plasmashell.notifyrc
Normal file
9
src/plasma/data/notifications/plasmashell.notifyrc
Normal file
@ -0,0 +1,9 @@
|
||||
[Global]
|
||||
IconName=plasma
|
||||
Comment=Plasma Workspace
|
||||
Name=Plasma
|
||||
|
||||
[Event/plasmoidDeleted]
|
||||
Name=Widget deleted
|
||||
Comment=A widget has been deleted
|
||||
Action=Popup
|
@ -27,6 +27,7 @@
|
||||
|
||||
#include <QFile>
|
||||
#include <qstandardpaths.h>
|
||||
#include <QTimer>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QMessageBox>
|
||||
@ -61,7 +62,8 @@ AppletPrivate::AppletPrivate(KService::Ptr service, const KPluginInfo *info, int
|
||||
actions(AppletPrivate::defaultActions(applet)),
|
||||
activationAction(0),
|
||||
itemStatus(Types::UnknownStatus),
|
||||
modificationsTimer(0),
|
||||
modificationsTimer(Q_NULLPTR),
|
||||
deleteNotificationTimer(Q_NULLPTR),
|
||||
hasConfigurationInterface(false),
|
||||
failed(false),
|
||||
transient(false),
|
||||
@ -89,6 +91,10 @@ AppletPrivate::~AppletPrivate()
|
||||
KGlobalAccel::self()->removeAllShortcuts(activationAction);
|
||||
}
|
||||
|
||||
if (deleteNotification) {
|
||||
deleteNotification->close();
|
||||
}
|
||||
|
||||
delete script;
|
||||
script = 0;
|
||||
delete package;
|
||||
@ -220,28 +226,83 @@ void AppletPrivate::askDestroy()
|
||||
return; //don't double delete
|
||||
}
|
||||
|
||||
if (q->isContainment()) {
|
||||
QMessageBox *box = new QMessageBox(QMessageBox::Warning, i18nc("@title:window %1 is the name of the containment", "Remove %1", q->title()), i18nc("%1 is the name of the containment", "Do you really want to remove this %1?", q->title()), QMessageBox::StandardButtons(QMessageBox::Yes | QMessageBox::No));
|
||||
box->setWindowFlags((Qt::WindowFlags)(box->windowFlags() | Qt::WA_DeleteOnClose));
|
||||
box->open();
|
||||
if (transient) {
|
||||
cleanUpAndDelete();
|
||||
} else {
|
||||
//There is no confirmation anymore for panels removal:
|
||||
//this needs users feedback
|
||||
transient = true;
|
||||
emit q->destroyedChanged(true);
|
||||
//no parent, but it won't leak, since it will be closed both in case of timeout
|
||||
//or direct action
|
||||
deleteNotification = new KNotification("plasmoidDeleted", KNotification::Persistent, 0);
|
||||
QStringList actions;
|
||||
deleteNotification->setIconName(q->icon());
|
||||
Plasma::Containment *asContainment = qobject_cast<Plasma::Containment *>(q);
|
||||
|
||||
QObject::connect(q, &Applet::immutabilityChanged, [=] () {
|
||||
box->close();
|
||||
});
|
||||
QObject::connect(q, &QObject::destroyed, [=] () {
|
||||
box->close();
|
||||
});
|
||||
QObject::connect(box->button(QMessageBox::Yes), &QAbstractButton::clicked,
|
||||
[ = ]() {
|
||||
transient = true;
|
||||
cleanUpAndDelete();
|
||||
});
|
||||
if (!q->isContainment()) {
|
||||
deleteNotification->setText(i18n("The widget \"%1\" has been removed.", q->title()));
|
||||
} else if (asContainment && (asContainment->containmentType() == Types::PanelContainment || asContainment->containmentType() == Types::CustomPanelContainment)) {
|
||||
deleteNotification->setText(i18n("A Panel has been removed."));
|
||||
//This will never happen with our current shell, but could with a custom one
|
||||
} else {
|
||||
deleteNotification->setText(i18n("A Desktop has been removed."));
|
||||
}
|
||||
|
||||
return;
|
||||
actions.append(i18n("Undo"));
|
||||
deleteNotification->setActions(actions);
|
||||
QObject::connect(deleteNotification.data(), &KNotification::action1Activated,
|
||||
[=]() {
|
||||
transient = false;
|
||||
emit q->destroyedChanged(false);
|
||||
if (!q->isContainment() && q->containment()) {
|
||||
//make sure the applets are sorted by id
|
||||
auto position = std::lower_bound(q->containment()->d->applets.begin(), q->containment()->d->applets.end(), q, [](Plasma::Applet *a1, Plasma::Applet *a2) {
|
||||
return a1->id() < a2->id();
|
||||
});
|
||||
q->containment()->d->applets.insert(position, q);
|
||||
emit q->containment()->appletAdded(q);
|
||||
}
|
||||
if (deleteNotification) {
|
||||
deleteNotification->close();
|
||||
}
|
||||
if (deleteNotificationTimer) {
|
||||
delete deleteNotificationTimer;
|
||||
deleteNotificationTimer = 0;
|
||||
}
|
||||
});
|
||||
QObject::connect(deleteNotification.data(), &KNotification::closed,
|
||||
[=]() {
|
||||
//If the timer still exists, it means the undo action was NOT triggered
|
||||
if (deleteNotificationTimer) {
|
||||
transient = true;
|
||||
emit q->destroyedChanged(true);
|
||||
cleanUpAndDelete();
|
||||
}
|
||||
});
|
||||
|
||||
deleteNotification->sendEvent();
|
||||
if (!deleteNotificationTimer) {
|
||||
deleteNotificationTimer = new QTimer(q);
|
||||
//really delete after a minute
|
||||
deleteNotificationTimer->setInterval(60 * 1000);
|
||||
deleteNotificationTimer->setSingleShot(true);
|
||||
QObject::connect(deleteNotificationTimer, &QTimer::timeout,
|
||||
[=]() {
|
||||
if (deleteNotification) {
|
||||
deleteNotification->close();
|
||||
}
|
||||
transient = true;
|
||||
emit q->destroyedChanged(true);
|
||||
cleanUpAndDelete();
|
||||
});
|
||||
deleteNotificationTimer->start();
|
||||
}
|
||||
if (!q->isContainment() && q->containment()) {
|
||||
q->containment()->d->applets.removeAll(q);
|
||||
emit q->containment()->appletRemoved(q);
|
||||
}
|
||||
}
|
||||
|
||||
transient = true;
|
||||
cleanUpAndDelete();
|
||||
}
|
||||
|
||||
void AppletPrivate::globalShortcutChanged()
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <kconfigskeleton.h>
|
||||
#include <kservice.h>
|
||||
#include <kplugininfo.h>
|
||||
#include <KNotification>
|
||||
|
||||
#include "plasma/applet.h"
|
||||
|
||||
@ -104,6 +105,9 @@ public:
|
||||
QBasicTimer constraintsTimer;
|
||||
QBasicTimer *modificationsTimer;
|
||||
|
||||
QPointer <KNotification> deleteNotification;
|
||||
QTimer *deleteNotificationTimer;
|
||||
|
||||
// a great green field of booleans :)
|
||||
bool hasConfigurationInterface : 1;
|
||||
bool failed : 1;
|
||||
|
@ -59,7 +59,8 @@ AppletInterface::AppletInterface(DeclarativeAppletScript *script, const QVariant
|
||||
m_appletScriptEngine(script),
|
||||
m_backgroundHints(Plasma::Types::StandardBackground),
|
||||
m_busy(false),
|
||||
m_hideOnDeactivate(true)
|
||||
m_hideOnDeactivate(true),
|
||||
m_positionBeforeRemoval(QPointF(-1, -1))
|
||||
{
|
||||
qmlRegisterType<QAction>();
|
||||
|
||||
@ -72,6 +73,12 @@ AppletInterface::AppletInterface(DeclarativeAppletScript *script, const QVariant
|
||||
|
||||
connect(applet(), &Plasma::Applet::statusChanged,
|
||||
this, &AppletInterface::statusChanged);
|
||||
|
||||
connect(applet(), &Plasma::Applet::destroyedChanged,
|
||||
this, [=] () {
|
||||
setVisible(!applet()->destroyed());
|
||||
});
|
||||
|
||||
connect(applet(), &Plasma::Applet::activated,
|
||||
this, &AppletInterface::activated);
|
||||
|
||||
@ -124,6 +131,11 @@ AppletInterface::AppletInterface(Plasma::Applet *a, const QVariantList &args, QQ
|
||||
connect(applet(), &Plasma::Applet::statusChanged,
|
||||
this, &AppletInterface::statusChanged);
|
||||
|
||||
connect(applet(), &Plasma::Applet::destroyedChanged,
|
||||
[=] () {
|
||||
setVisible(!applet()->destroyed());
|
||||
});
|
||||
|
||||
connect(appletScript(), &DeclarativeAppletScript::formFactorChanged,
|
||||
this, &AppletInterface::formFactorChanged);
|
||||
connect(appletScript(), &DeclarativeAppletScript::locationChanged,
|
||||
|
@ -369,7 +369,10 @@ private:
|
||||
Plasma::Types::BackgroundHints m_backgroundHints;
|
||||
bool m_busy : 1;
|
||||
bool m_hideOnDeactivate : 1;
|
||||
|
||||
friend class ContainmentInterface;
|
||||
//This is used by ContainmentInterface
|
||||
QPointF m_positionBeforeRemoval;
|
||||
};
|
||||
|
||||
QML_DECLARE_TYPEINFO(AppletInterface, QML_HAS_ATTACHED_PROPERTIES)
|
||||
|
@ -554,8 +554,8 @@ void ContainmentInterface::appletAddedForward(Plasma::Applet *applet)
|
||||
return;
|
||||
}
|
||||
|
||||
QObject *appletGraphicObject = applet->property("_plasma_graphicObject").value<QObject *>();
|
||||
QObject *contGraphicObject = m_containment->property("_plasma_graphicObject").value<QObject *>();
|
||||
AppletInterface *appletGraphicObject = applet->property("_plasma_graphicObject").value<AppletInterface *>();
|
||||
AppletInterface *contGraphicObject = m_containment->property("_plasma_graphicObject").value<AppletInterface *>();
|
||||
|
||||
// qDebug() << "Applet added on containment:" << m_containment->title() << contGraphicObject
|
||||
// << "Applet: " << applet << applet->title() << appletGraphicObject;
|
||||
@ -572,14 +572,15 @@ void ContainmentInterface::appletAddedForward(Plasma::Applet *applet)
|
||||
}
|
||||
|
||||
m_appletInterfaces << appletGraphicObject;
|
||||
emit appletAdded(appletGraphicObject, -1, -1);
|
||||
emit appletAdded(appletGraphicObject, appletGraphicObject->m_positionBeforeRemoval.x(), appletGraphicObject->m_positionBeforeRemoval.y());
|
||||
emit appletsChanged();
|
||||
}
|
||||
|
||||
void ContainmentInterface::appletRemovedForward(Plasma::Applet *applet)
|
||||
{
|
||||
QObject *appletGraphicObject = applet->property("_plasma_graphicObject").value<QObject *>();
|
||||
AppletInterface *appletGraphicObject = applet->property("_plasma_graphicObject").value<AppletInterface *>();
|
||||
m_appletInterfaces.removeAll(appletGraphicObject);
|
||||
appletGraphicObject->m_positionBeforeRemoval = appletGraphicObject->mapToItem(this, QPointF());
|
||||
emit appletRemoved(appletGraphicObject);
|
||||
emit appletsChanged();
|
||||
}
|
||||
@ -719,7 +720,7 @@ void ContainmentInterface::mousePressEvent(QMouseEvent *event)
|
||||
Plasma::Applet *applet = 0;
|
||||
foreach (QObject *appletObject, m_appletInterfaces) {
|
||||
if (AppletInterface *ai = qobject_cast<AppletInterface *>(appletObject)) {
|
||||
if (ai->contains(ai->mapFromItem(this, event->posF()))) {
|
||||
if (ai->isVisible() && ai->contains(ai->mapFromItem(this, event->posF()))) {
|
||||
applet = ai->applet();
|
||||
emit ai->contextualActionsAboutToShow();
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user