Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F16568868
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
48 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/plasma/popupapplet.cpp b/plasma/popupapplet.cpp
index 07ea3f1083..bb407ca12c 100644
--- a/plasma/popupapplet.cpp
+++ b/plasma/popupapplet.cpp
@@ -1,993 +1,1007 @@
/*
* Copyright 2008 by Montel Laurent <montel@kde.org>
* Copyright 2008 by Marco Martin <notmart@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
#include "popupapplet.h"
#include "private/popupapplet_p.h"
#include "private/dialog_p.h"
#include <QApplication>
#include <QGraphicsProxyWidget>
#include <QGraphicsLinearLayout>
#include <QTimer>
#include <QVBoxLayout>
#ifdef Q_WS_X11
#include <QX11Info>
#endif
#include <kicon.h>
#include <kiconloader.h>
#include <kwindowsystem.h>
#include <kglobalsettings.h>
#include <netwm.h>
#include "plasma/private/applet_p.h"
#include "plasma/private/extenderitemmimedata_p.h"
#include "plasma/corona.h"
#include "plasma/containment.h"
#include "plasma/private/containment_p.h"
#include "plasma/dialog.h"
#include "plasma/extenders/extender.h"
#include "plasma/extenders/extenderitem.h"
#include "plasma/package.h"
#include "plasma/theme.h"
#include "plasma/scripting/appletscript.h"
#include "plasma/tooltipmanager.h"
#include "plasma/widgets/iconwidget.h"
namespace Plasma
{
PopupApplet::PopupApplet(QObject *parent, const QVariantList &args)
: Plasma::Applet(parent, args),
d(new PopupAppletPrivate(this))
{
}
PopupApplet::PopupApplet(const QString &packagePath, uint appletId, const QVariantList &args)
: Plasma::Applet(packagePath, appletId, args),
d(new PopupAppletPrivate(this))
{
}
PopupApplet::~PopupApplet()
{
delete widget();
delete d;
}
void PopupApplet::setPopupIcon(const QIcon &icon)
{
if (icon.isNull()) {
if (d->icon) {
delete d->icon;
d->icon = 0;
setLayout(0);
setAspectRatioMode(d->savedAspectRatio);
}
return;
}
d->createIconWidget();
d->icon->setIcon(icon);
}
void PopupApplet::setPopupIcon(const QString &iconName)
{
// Attempt 1: is it in the plasmoid package?
if (package()) {
const QString file = package()->filePath("images", iconName);
if (!file.isEmpty()) {
setPopupIcon(KIcon(file));
return;
}
}
// Attempt 2: is it a svg in the icons directory?
QString name = QString("icons/") + iconName.split("-").first();
if (!Plasma::Theme::defaultTheme()->imagePath(name).isEmpty()) {
d->createIconWidget();
d->icon->setSvg(name, iconName);
if (d->icon->svg().isEmpty()) {
setPopupIcon(KIcon(iconName));
}
return;
}
// Final Attempt: use KIcon
setPopupIcon(KIcon(iconName));
}
QIcon PopupApplet::popupIcon() const
{
return d->icon ? d->icon->icon() : QIcon();
}
QWidget *PopupApplet::widget()
{
return d->widget;
}
void PopupApplet::setWidget(QWidget *widget)
{
if (d->widget) {
Plasma::Dialog *dialog = d->dialogPtr.data();
if (dialog) {
dialog->setGraphicsWidget(0);
QVBoxLayout *lay = 0;
QLayout *existingLayout = dialog->layout();
if (existingLayout) {
lay = dynamic_cast<QVBoxLayout *>(existingLayout);
if (!lay) {
delete existingLayout;
}
}
if (!lay) {
lay = new QVBoxLayout;
dialog->setLayout(lay);
}
lay->removeWidget(d->widget);
lay->addWidget(widget);
} else if (d->proxy) {
d->proxy.data()->setWidget(widget);
}
}
d->widget = widget;
}
QGraphicsWidget *PopupApplet::graphicsWidget()
{
if (d->graphicsWidget) {
return d->graphicsWidget.data();
} else {
return static_cast<Applet*>(this)->d->extender.data();
}
}
void PopupApplet::setGraphicsWidget(QGraphicsWidget *graphicsWidget)
{
if (d->graphicsWidget) {
if (d->dialogPtr) {
d->dialogPtr.data()->setGraphicsWidget(graphicsWidget);
} else if (layout()) {
QGraphicsLinearLayout *lay = static_cast<QGraphicsLinearLayout *>(layout());
lay->removeAt(0);
if (graphicsWidget) {
lay->addItem(graphicsWidget);
}
}
}
d->graphicsWidget = graphicsWidget;
}
void PopupAppletPrivate::checkExtenderAppearance(Plasma::FormFactor f)
{
Extender *extender = qobject_cast<Extender*>(q->graphicsWidget());
if (extender) {
if (f != Plasma::Horizontal && f != Plasma::Vertical) {
extender->setAppearance(Extender::NoBorders);
} else if (q->location() == TopEdge) {
extender->setAppearance(Extender::TopDownStacked);
} else {
extender->setAppearance(Extender::BottomUpStacked);
}
if (dialogPtr) {
dialogPtr.data()->setGraphicsWidget(extender);
}
}
}
void PopupAppletPrivate::popupConstraintsEvent(Plasma::Constraints constraints)
{
Plasma::FormFactor f = q->formFactor();
if (constraints & Plasma::LocationConstraint) {
checkExtenderAppearance(f);
}
if (constraints & Plasma::FormFactorConstraint ||
constraints & Plasma::StartupCompletedConstraint ||
(constraints & Plasma::SizeConstraint &&
(f == Plasma::Vertical || f == Plasma::Horizontal))) {
QGraphicsLinearLayout *lay = dynamic_cast<QGraphicsLinearLayout *>(q->layout());
if (icon && lay && lay->count() > 0) {
lay->removeAt(0);
}
QSizeF minimum;
QSizeF parentSize;
QGraphicsWidget *gWidget = q->graphicsWidget();
//kDebug() << "graphics widget is" << (QObject*)gWidget;
QWidget *qWidget = q->widget();
if (gWidget) {
minimum = gWidget->minimumSize();
// our layout may have been replaced on us in the call to graphicsWidget!
lay = dynamic_cast<QGraphicsLinearLayout *>(q->layout());
if (!(constraints & LocationConstraint)) {
checkExtenderAppearance(f);
}
} else if (qWidget) {
minimum = qWidget->minimumSizeHint();
}
//99% of the times q->parentWidget() is the containment, but using it we can also manage the applet-in-applet case (i.e. systray)
//there are also cases where the parentlayoutitem is bigger than the containment (e.g. newspaper)
if (q->parentLayoutItem()) {
parentSize = q->parentLayoutItem()->geometry().size();
} else if (q->parentWidget()) {
parentSize = q->parentWidget()->size();
}
//check if someone did the nasty trick of applets in applets, in this case we always want to be collapsed
QGraphicsWidget *candidateParentApplet = q;
Plasma::Applet *parentApplet = 0;
//this loop should be executed normally a single time, at most 2-3 times for quite complex containments
while (candidateParentApplet) {
candidateParentApplet = candidateParentApplet->parentWidget();
parentApplet = qobject_cast<Plasma::Applet *>(candidateParentApplet);
if (parentApplet) {
break;
}
}
//Applet on desktop
if ((!parentApplet || parentApplet->isContainment() ) && icon && (!icon->svg().isEmpty() || !icon->icon().isNull()) && ((f != Plasma::Vertical && f != Plasma::Horizontal) ||
((f == Plasma::Vertical && parentSize.width() >= minimum.width()) ||
(f == Plasma::Horizontal && parentSize.height() >= minimum.height())))) {
//kDebug() << "we are expanding the popupapplet";
// we only switch to expanded if we aren't horiz/vert constrained and
// this applet has an icon.
// otherwise, we leave it up to the applet itself to figure it out
if (icon) {
icon->hide();
}
if (savedAspectRatio != Plasma::InvalidAspectRatioMode) {
q->setAspectRatioMode(savedAspectRatio);
}
Dialog *dialog = dialogPtr.data();
if (dialog) {
if (dialog->layout() && qWidget) {
//we don't want to delete Widget inside the dialog layout
dialog->layout()->removeWidget(qWidget);
}
if (qWidget) {
qWidget->setParent(0);
}
delete dialog;
}
if (!lay) {
lay = new QGraphicsLinearLayout();
lay->setContentsMargins(0, 0, 0, 0);
lay->setSpacing(0);
lay->setOrientation(Qt::Horizontal);
q->setLayout(lay);
}
QSize prefSize;
if (gWidget) {
if (proxy) {
proxy.data()->setWidget(0);
delete proxy.data();
}
Corona *corona = qobject_cast<Corona *>(gWidget->scene());
if (corona) {
corona->removeOffscreenWidget(gWidget);
}
lay->addItem(gWidget);
prefSize = gWidget->preferredSize().toSize();
} else if (qWidget) {
if (!proxy) {
proxy = new QGraphicsProxyWidget(q);
proxy.data()->setWidget(qWidget);
proxy.data()->show();
}
lay->addItem(proxy.data());
prefSize = qWidget->sizeHint();
}
//we could be on a big panel, but in that case we will be able to resize
//more than the natural minimum size, because we'll transform into an icon
if (f == Plasma::Horizontal) {
minimum.setHeight(0);
} else if (f == Plasma::Vertical) {
minimum.setWidth(0);
}
qreal left, top, right, bottom;
q->getContentsMargins(&left, &top, &right, &bottom);
QSizeF oldSize(q->size());
//size not saved/invalid size saved
if (oldSize.width() < q->minimumSize().width() || oldSize.height() < q->minimumSize().height()) {
q->resize(prefSize);
emit q->appletTransformedItself();
}
} else {
//Applet on popup
if (icon && lay) {
lay->addItem(icon);
}
//kDebug() << "about to switch to a popup";
if (!qWidget && !gWidget) {
delete dialogPtr.data();
return;
}
//there was already a dialog? don't make the switch again
if (dialogPtr) {
return;
}
if (proxy) {
proxy.data()->setWidget(0); // prevent it from deleting our widget!
delete proxy.data();
}
//save the aspect ratio mode in case we drag'n drop in the Desktop later
savedAspectRatio = q->aspectRatioMode();
if (icon) {
icon->show();
q->setAspectRatioMode(Plasma::ConstrainedSquare);
}
Dialog *dialog = new Dialog();
dialog->d->appletPtr = q;
dialogPtr = dialog;
if (icon) {
dialog->setAspectRatioMode(savedAspectRatio);
}
//no longer use Qt::Popup since that seems to cause a lot of problem when you drag
//stuff out of your Dialog (extenders). Monitor WindowDeactivate events so we can
//emulate the same kind of behavior as Qt::Popup (close when you click somewhere
//else.
if (gWidget) {
Corona *corona = qobject_cast<Corona *>(gWidget->scene());
if (!corona) {
corona = qobject_cast<Corona *>(q->scene());
}
if (corona) {
corona->addOffscreenWidget(gWidget);
}
gWidget->show();
dialog->setGraphicsWidget(gWidget);
dialog->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | (gWidget->windowFlags() & Qt::X11BypassWindowManagerHint));
} else if (qWidget) {
QVBoxLayout *l_layout = new QVBoxLayout(dialog);
l_layout->setSpacing(0);
l_layout->setMargin(0);
l_layout->addWidget(qWidget);
dialog->adjustSize();
dialog->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | (qWidget->windowFlags() & Qt::X11BypassWindowManagerHint));
} else {
dialog->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
}
restoreDialogSize();
KWindowSystem::setState(dialog->winId(), NET::SkipTaskbar | NET::SkipPager);
dialog->installEventFilter(q);
QObject::connect(dialog, SIGNAL(dialogResized()), q, SLOT(dialogSizeChanged()));
QObject::connect(dialog, SIGNAL(dialogVisible(bool)), q, SLOT(dialogStatusChanged(bool)));
}
}
if (constraints & Plasma::PopupConstraint) {
updateDialogPosition();
}
if (icon) {
// emit the size hint changing stuff for our applet as we are handling
// the size changings
emit q->sizeHintChanged(Qt::PreferredSize);
}
}
void PopupAppletPrivate::appletActivated()
{
internalTogglePopup(true);
}
QSizeF PopupApplet::sizeHint(Qt::SizeHint which, const QSizeF & constraint) const
{
if (!d->dialogPtr || which != Qt::PreferredSize) {
return Applet::sizeHint(which, constraint);
}
switch (formFactor()) {
case Vertical:
case Horizontal: {
const int size = IconSize(KIconLoader::Panel);
return QSizeF(size, size);
}
default:
break;
}
const int size = IconSize(KIconLoader::Desktop);
return QSizeF(size, size);
}
void PopupApplet::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if (!d->icon && !d->popupLostFocus && event->buttons() == Qt::LeftButton) {
d->clicked = scenePos().toPoint();
event->setAccepted(true);
return;
} else {
d->popupLostFocus = false;
Applet::mousePressEvent(event);
}
}
void PopupApplet::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
if (!d->icon &&
(d->clicked - scenePos().toPoint()).manhattanLength() < KGlobalSettings::dndEventDelay()) {
d->internalTogglePopup();
} else {
Applet::mouseReleaseEvent(event);
}
}
bool PopupApplet::eventFilter(QObject *watched, QEvent *event)
{
if (!d->passive && watched == d->dialogPtr.data() && (event->type() == QEvent::WindowDeactivate)) {
d->popupLostFocus = true;
QTimer::singleShot(100, this, SLOT(clearPopupLostFocus()));
}
if (watched == d->dialogPtr.data() && event->type() == QEvent::ContextMenu) {
//pass it up to the applet
//well, actually we have to pass it to the *containment*
//because all the code for showing an applet's contextmenu is actually in Containment.
Containment *c = containment();
if (c) {
Applet *applet = this;
Dialog *dialog = d->dialogPtr.data();
if (dialog && dialog->graphicsWidget()) {
int left, top, right, bottom;
dialog->getContentsMargins(&left, &top, &right, &bottom);
const QPoint eventPos = static_cast<QContextMenuEvent*>(event)->pos() - QPoint(left, top);
QPointF pos = dialog->graphicsWidget()->mapToScene(eventPos);
if (Applet *actual = c->d->appletAt(pos)) {
applet = actual;
}
}
KMenu desktopMenu;
c->d->addAppletActions(desktopMenu, applet, event);
if (!desktopMenu.isEmpty()) {
desktopMenu.exec(static_cast<QContextMenuEvent*>(event)->globalPos());
return true;
}
return false;
}
}
return Applet::eventFilter(watched, event);
}
//FIXME: some duplication between the drag events... maybe add some simple helper function?
void PopupApplet::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
{
if (event->mimeData()->hasFormat(ExtenderItemMimeData::mimeType())) {
const ExtenderItemMimeData *mimeData =
qobject_cast<const ExtenderItemMimeData*>(event->mimeData());
if (mimeData && qobject_cast<Extender*>(graphicsWidget())) {
event->accept();
showPopup();
}
}
}
void PopupApplet::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
{
if (event->mimeData()->hasFormat(ExtenderItemMimeData::mimeType())) {
const ExtenderItemMimeData *mimeData =
qobject_cast<const ExtenderItemMimeData*>(event->mimeData());
if (mimeData && qobject_cast<Extender*>(graphicsWidget())) {
//We want to hide the popup if we're not moving onto the popup AND it is not the popup
//we started.
if (d->dialogPtr && !d->dialogPtr.data()->geometry().contains(event->screenPos()) &&
mimeData->extenderItem()->extender() != qobject_cast<Extender*>(graphicsWidget())) {
//We actually try to hide the popup, with a call to showPopup, with a smal timeout,
//so if the user moves into the popup fast enough, it remains open (the extender
//will call showPopup which will cancel the timeout.
showPopup(250);
}
}
}
}
void PopupApplet::dropEvent(QGraphicsSceneDragDropEvent *event)
{
if (event->mimeData()->hasFormat(ExtenderItemMimeData::mimeType())) {
const ExtenderItemMimeData *mimeData =
qobject_cast<const ExtenderItemMimeData*>(event->mimeData());
if (mimeData && qobject_cast<Extender*>(graphicsWidget())) {
mimeData->extenderItem()->setExtender(extender());
QApplication::restoreOverrideCursor();
}
}
}
void PopupApplet::showPopup(uint popupDuration)
{
// use autohideTimer to store when the next show should be
if (popupDuration > 0 || d->autohideTimer) {
if (!d->autohideTimer) {
d->autohideTimer = new QTimer(this);
d->autohideTimer->setSingleShot(true);
connect(d->autohideTimer, SIGNAL(timeout()), this, SLOT(hideTimedPopup()));
}
d->autohideTimer->stop();
d->autohideTimer->setInterval(popupDuration);
}
//kDebug() << "starting delayed show, duration for popup is" << popupDuration;
d->delayedShowTimer.start(0, this);
}
void PopupApplet::timerEvent(QTimerEvent *event)
{
if (event->timerId() == d->delayedShowTimer.timerId()) {
d->delayedShowTimer.stop();
Dialog *dialog = d->dialogPtr.data();
if (dialog) {
// move the popup before its fist show, even if the show isn't triggered by
// a click, this should fix the first random position seen in some widgets
if (!dialog->isVisible()) {
d->internalTogglePopup();
}
const int popupDuration = d->autohideTimer ? d->autohideTimer->interval() : 0;
//kDebug() << "popupDuration is:" << (d->autohideTimer ? d->autohideTimer->interval() : 0);
if (popupDuration > 0) {
d->autohideTimer->start();
} else if (d->autohideTimer) {
d->autohideTimer->stop();
}
}
+ } else if (event->timerId() == d->showDialogTimer.timerId()) {
+ d->showDialogTimer.stop();
+ d->showDialog();
} else {
Applet::timerEvent(event);
}
}
void PopupApplet::hidePopup()
{
+ d->showDialogTimer.stop();
d->delayedShowTimer.stop();
Dialog *dialog = d->dialogPtr.data();
if (dialog && dialog->isVisible()) {
if (location() != Floating) {
dialog->animatedHide(locationToInverseDirection(location()));
} else {
dialog->hide();
}
}
}
void PopupApplet::togglePopup()
{
d->internalTogglePopup();
}
Plasma::PopupPlacement PopupApplet::popupPlacement() const
{
return d->popupPlacement;
}
void PopupApplet::setPopupAlignment(Qt::AlignmentFlag alignment)
{
d->popupAlignment = alignment;
}
Qt::AlignmentFlag PopupApplet::popupAlignment() const
{
return d->popupAlignment;
}
void PopupApplet::popupEvent(bool popped)
{
if (Applet::d->script) {
emit Applet::d->script->popupEvent(popped);
}
}
void PopupApplet::setPassivePopup(bool passive)
{
d->passive = passive;
}
bool PopupApplet::isPassivePopup() const
{
return d->passive;
}
bool PopupApplet::isPopupShowing() const
{
return d->dialogPtr && d->dialogPtr.data()->isVisible();
}
bool PopupApplet::isIconified() const
{
return d->dialogPtr;
}
PopupAppletPrivate::PopupAppletPrivate(PopupApplet *applet)
: q(applet),
icon(0),
widget(0),
popupPlacement(Plasma::FloatingPopup),
popupAlignment(Qt::AlignLeft),
savedAspectRatio(Plasma::InvalidAspectRatioMode),
autohideTimer(0),
preShowStatus(UnknownStatus),
popupLostFocus(false),
passive(false)
{
int iconSize = IconSize(KIconLoader::Desktop);
q->resize(iconSize, iconSize);
q->setAcceptDrops(true);
QObject::disconnect(q, SIGNAL(activate()), static_cast<Applet*>(q), SLOT(setFocus()));
QObject::connect(q, SIGNAL(activate()), q, SLOT(appletActivated()));
QObject::connect(KGlobalSettings::self(), SIGNAL(iconChanged(int)), q, SLOT(iconSizeChanged(int)));
}
PopupAppletPrivate::~PopupAppletPrivate()
{
if (proxy) {
proxy.data()->setWidget(0);
}
delete dialogPtr.data();
delete icon;
}
void PopupAppletPrivate::iconSizeChanged(int group)
{
if (icon && (group == KIconLoader::Desktop || group == KIconLoader::Panel)) {
q->updateGeometry();
}
}
void PopupAppletPrivate::internalTogglePopup(bool fromActivatedSignal)
{
if (autohideTimer) {
autohideTimer->stop();
}
delayedShowTimer.stop();
Plasma::Dialog *dialog = dialogPtr.data();
if (!dialog) {
q->setFocus(Qt::ShortcutFocusReason);
if (!fromActivatedSignal) {
QObject::disconnect(q, SIGNAL(activate()), q, SLOT(appletActivated()));
emit q->activate();
QObject::connect(q, SIGNAL(activate()), q, SLOT(appletActivated()));
}
return;
}
if (!q->view()) {
return;
}
if (dialog->isVisible()) {
if (q->location() != Floating) {
dialog->animatedHide(locationToInverseDirection(q->location()));
} else {
dialog->hide();
}
dialog->clearFocus();
} else {
if (q->graphicsWidget() &&
q->graphicsWidget() == static_cast<Applet*>(q)->d->extender.data() &&
static_cast<Applet*>(q)->d->extender.data()->isEmpty()) {
// we have nothing to show, so let's not.
if (!fromActivatedSignal) {
QObject::disconnect(q, SIGNAL(activate()), q, SLOT(appletActivated()));
emit q->activate();
QObject::connect(q, SIGNAL(activate()), q, SLOT(appletActivated()));
}
return;
}
ToolTipManager::self()->hide(q);
- updateDialogPosition();
+ showDialogTimer.start(0, q);
+ }
+}
- KWindowSystem::setOnAllDesktops(dialog->winId(), true);
- KWindowSystem::setState(dialog->winId(), NET::SkipTaskbar | NET::SkipPager);
+void PopupAppletPrivate::showDialog()
+{
+ Plasma::Dialog *dialog = dialogPtr.data();
+ if (!dialog) {
+ return;
+ }
- if (icon) {
- dialog->setAspectRatioMode(savedAspectRatio);
- }
+ updateDialogPosition();
- if (q->location() != Floating) {
- dialog->animatedShow(locationToDirection(q->location()));
- } else {
- dialog->show();
- }
+ KWindowSystem::setOnAllDesktops(dialog->winId(), true);
+ KWindowSystem::setState(dialog->winId(), NET::SkipTaskbar | NET::SkipPager);
- if (!(dialog->windowFlags() & Qt::X11BypassWindowManagerHint)) {
- KWindowSystem::activateWindow(dialog->winId());
- }
+ if (icon) {
+ dialog->setAspectRatioMode(savedAspectRatio);
+ }
+
+ if (q->location() != Floating) {
+ dialog->animatedShow(locationToDirection(q->location()));
+ } else {
+ dialog->show();
+ }
+
+ if (!(dialog->windowFlags() & Qt::X11BypassWindowManagerHint)) {
+ KWindowSystem::activateWindow(dialog->winId());
}
}
void PopupAppletPrivate::hideTimedPopup()
{
autohideTimer->stop();
q->hidePopup();
}
void PopupAppletPrivate::clearPopupLostFocus()
{
if (!icon || !icon->isDown()) {
q->hidePopup();
}
popupLostFocus = false;
}
KConfigGroup PopupAppletPrivate::popupConfigGroup()
{
KConfigGroup *mainGroup = static_cast<Applet*>(q)->d->mainConfigGroup();
return KConfigGroup(mainGroup, "PopupApplet");
}
void PopupAppletPrivate::dialogSizeChanged()
{
//Reposition the dialog
Plasma::Dialog *dialog = dialogPtr.data();
if (dialog) {
KConfigGroup sizeGroup = popupConfigGroup();
sizeGroup.writeEntry("DialogHeight", dialog->height());
sizeGroup.writeEntry("DialogWidth", dialog->width());
updateDialogPosition();
emit q->configNeedsSaving();
emit q->appletTransformedByUser();
}
}
void PopupAppletPrivate::dialogStatusChanged(bool shown)
{
if (shown) {
preShowStatus = q->status();
q->setStatus(NeedsAttentionStatus);
QObject::connect(q, SIGNAL(newStatus(Plasma::ItemStatus)),
q, SLOT(statusChangeWhileShown(Plasma::ItemStatus)),
Qt::UniqueConnection);
} else {
QObject::disconnect(q, SIGNAL(newStatus(Plasma::ItemStatus)),
q, SLOT(statusChangeWhileShown(Plasma::ItemStatus)));
q->setStatus(preShowStatus);
}
q->popupEvent(shown);
}
void PopupAppletPrivate::statusChangeWhileShown(Plasma::ItemStatus status)
{
preShowStatus = status;
}
void PopupAppletPrivate::createIconWidget()
{
if (icon) {
return;
}
icon = new Plasma::IconWidget(q);
QObject::connect(icon, SIGNAL(clicked()), q, SLOT(internalTogglePopup()));
QGraphicsLinearLayout *layout = new QGraphicsLinearLayout();
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(0);
layout->setOrientation(Qt::Horizontal);
layout->addItem(icon);
layout->setAlignment(icon, Qt::AlignCenter);
q->setLayout(layout);
}
void PopupAppletPrivate::restoreDialogSize()
{
Plasma::Dialog *dialog = dialogPtr.data();
if (!dialog) {
return;
}
Corona *corona = qobject_cast<Corona *>(q->scene());
if (!corona) {
return;
}
KConfigGroup sizeGroup = popupConfigGroup();
int preferredWidth = 0;
int preferredHeight = 0;
QGraphicsWidget *gWidget = dialog->graphicsWidget();
if (gWidget) {
preferredWidth = gWidget->preferredSize().width();
preferredHeight = gWidget->preferredSize().height();
}
const int width = qMin(sizeGroup.readEntry("DialogWidth", preferredWidth),
corona->screenGeometry(-1).width() - 50);
const int height = qMin(sizeGroup.readEntry("DialogHeight", preferredHeight),
corona->screenGeometry(-1).height() - 50);
QSize saved(width, height);
if (saved.isNull()) {
saved = dialog->sizeHint();
} else {
saved = saved.expandedTo(dialog->minimumSizeHint());
}
if (saved.width() != dialog->width() || saved.height() != dialog->height()) {
dialog->resize(saved);
/*if (gWidget) {
gWidget->resize(saved);
}*/
}
}
void PopupAppletPrivate::updateDialogPosition()
{
Plasma::Dialog *dialog = dialogPtr.data();
if (!dialog) {
return;
}
Corona *corona = qobject_cast<Corona *>(q->scene());
if (!corona) {
return;
}
QGraphicsView *view = q->view();
if (!view) {
return;
}
QSize s = dialog->size();
QPoint pos = view->mapFromScene(q->scenePos());
if (!q->containment() || view == q->containment()->view()) {
pos = corona->popupPosition(q, s, popupAlignment);
} else {
pos = corona->popupPosition(q->parentItem(), s, popupAlignment);
}
bool reverse = false;
if (q->formFactor() == Plasma::Vertical) {
if (view->mapToGlobal(view->mapFromScene(q->scenePos())).y() + q->size().height()/2 < pos.y() + dialog->size().width()/2) {
reverse = true;
}
} else {
if (view->mapToGlobal(view->mapFromScene(q->scenePos())).x() + q->size().width()/2 < pos.x() + dialog->size().width()/2) {
reverse = true;
}
}
switch (q->location()) {
case BottomEdge:
if (pos.x() >= q->pos().x()) {
dialog->setResizeHandleCorners(Dialog::NorthEast);
} else {
dialog->setResizeHandleCorners(Dialog::NorthWest);
}
if (reverse) {
popupPlacement = Plasma::TopPosedLeftAlignedPopup;
} else {
popupPlacement = Plasma::TopPosedRightAlignedPopup;
}
break;
case TopEdge:
if (pos.x() >= q->pos().x()) {
dialog->setResizeHandleCorners(Dialog::SouthEast);
} else {
dialog->setResizeHandleCorners(Dialog::SouthWest);
}
if (reverse) {
popupPlacement = Plasma::BottomPosedLeftAlignedPopup;
} else {
popupPlacement = Plasma::BottomPosedRightAlignedPopup;
}
break;
case LeftEdge:
if (pos.y() >= q->pos().y()) {
dialog->setResizeHandleCorners(Dialog::SouthEast);
} else {
dialog->setResizeHandleCorners(Dialog::NorthEast);
}
if (reverse) {
popupPlacement = Plasma::RightPosedTopAlignedPopup;
} else {
popupPlacement = Plasma::RightPosedBottomAlignedPopup;
}
break;
case RightEdge:
if (pos.y() >= q->pos().y()) {
dialog->setResizeHandleCorners(Dialog::SouthWest);
} else {
dialog->setResizeHandleCorners(Dialog::NorthWest);
}
if (reverse) {
popupPlacement = Plasma::LeftPosedTopAlignedPopup;
} else {
popupPlacement = Plasma::LeftPosedBottomAlignedPopup;
}
break;
default:
dialog->setResizeHandleCorners(Dialog::NorthEast);
}
dialog->move(pos);
}
} // Plasma namespace
#include "popupapplet.moc"
diff --git a/plasma/private/packages.cpp b/plasma/private/packages.cpp
index f85d5f724b..15db229240 100644
--- a/plasma/private/packages.cpp
+++ b/plasma/private/packages.cpp
@@ -1,373 +1,374 @@
/******************************************************************************
* Copyright 2007-2009 by Aaron Seigo <aseigo@kde.org> *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library 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 *
* Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public License *
* along with this library; see the file COPYING.LIB. If not, write to *
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
* Boston, MA 02110-1301, USA. *
*******************************************************************************/
#include "plasma/private/packages_p.h"
#include <math.h>
#include <float.h> // FLT_MAX
#include <QCoreApplication>
#include <QFileInfo>
#include <kconfiggroup.h>
#include <kdesktopfile.h>
#include <klocale.h>
#include <kmessagebox.h>
#ifndef PLASMA_NO_KNEWSTUFF
#include <knewstuff3/downloaddialog.h>
#endif
#include "plasma/private/wallpaper_p.h"
namespace Plasma
{
PlasmoidPackage::PlasmoidPackage(QObject *parent)
: Plasma::PackageStructure(parent, QString("Plasmoid"))
{
QString pathsString(getenv("PLASMA_CUSTOM_PREFIX_PATHS"));
if (!pathsString.isEmpty()) {
QStringList prefixPaths(pathsString.split(":"));
if (!prefixPaths.isEmpty()) {
setContentsPrefixPaths(prefixPaths);
}
}
addDirectoryDefinition("images", "images", i18n("Images"));
QStringList mimetypes;
mimetypes << "image/svg+xml" << "image/png" << "image/jpeg";
setMimetypes("images", mimetypes);
addDirectoryDefinition("config", "config", i18n("Configuration Definitions"));
mimetypes.clear();
mimetypes << "text/xml";
setMimetypes("config", mimetypes);
addDirectoryDefinition("ui", "ui", i18n("User Interface"));
setMimetypes("ui", mimetypes);
addDirectoryDefinition("data", "data", i18n("Data Files"));
addDirectoryDefinition("scripts", "code", i18n("Executable Scripts"));
mimetypes.clear();
mimetypes << "text/plain";
setMimetypes("scripts", mimetypes);
addDirectoryDefinition("translations", "locale", i18n("Translations"));
addFileDefinition("mainconfigui", "ui/config.ui", i18n("Main Config UI File"));
addFileDefinition("mainconfigxml", "config/main.xml", i18n("Configuration XML file"));
addFileDefinition("mainscript", "code/main", i18n("Main Script File"));
addFileDefinition("defaultconfig", "config/default-configrc", i18n("Default configuration"));
addDirectoryDefinition("animations", "animations", i18n("Animation scripts"));
setRequired("mainscript", true);
}
PlasmoidPackage::~PlasmoidPackage()
{
#ifndef PLASMA_NO_KNEWSTUFF
if (!QCoreApplication::closingDown()) {
// let it "leak" on application close as this causes crashes otherwise, BUG 288153
delete m_knsDialog.data();
}
#endif
}
void PlasmoidPackage::pathChanged()
{
KDesktopFile config(path() + "/metadata.desktop");
KConfigGroup cg = config.desktopGroup();
QString mainScript = cg.readEntry("X-Plasma-MainScript", QString());
if (!mainScript.isEmpty()) {
addFileDefinition("mainscript", mainScript, i18n("Main Script File"));
setRequired("mainscript", true);
}
}
void PlasmoidPackage::createNewWidgetBrowser(QWidget *parent)
{
#ifndef PLASMA_NO_KNEWSTUFF
KNS3::DownloadDialog *knsDialog = m_knsDialog.data();
if (!knsDialog) {
m_knsDialog = knsDialog = new KNS3::DownloadDialog("plasmoids.knsrc", parent);
+ knsDialog->setProperty("DoNotCloseController", true);
connect(knsDialog, SIGNAL(accepted()), this, SIGNAL(newWidgetBrowserFinished()));
}
knsDialog->show();
knsDialog->raise();
#endif
}
DataEnginePackage::DataEnginePackage(QObject *parent)
: Plasma::PackageStructure(parent, QString("DataEngine"))
{
setServicePrefix("plasma-dataengine-");
setDefaultPackageRoot("plasma/dataengine/");
addDirectoryDefinition("data", "data", i18n("Data Files"));
addDirectoryDefinition("scripts", "code", i18n("Executable Scripts"));
QStringList mimetypes;
mimetypes << "text/plain";
setMimetypes("scripts", mimetypes);
addDirectoryDefinition("services", "services/", i18n("Service Descriptions"));
setMimetypes("services", mimetypes);
addDirectoryDefinition("translations", "locale", i18n("Translations"));
addFileDefinition("mainscript", "code/main", i18n("Main Script File"));
setRequired("mainscript", true);
}
DataEnginePackage::~DataEnginePackage()
{
}
void DataEnginePackage::pathChanged()
{
KDesktopFile config(path() + "/metadata.desktop");
KConfigGroup cg = config.desktopGroup();
QString mainScript = cg.readEntry("X-Plasma-MainScript", QString());
if (!mainScript.isEmpty()) {
addFileDefinition("mainscript", mainScript, i18n("Main Script File"));
setRequired("mainscript", true);
}
}
ThemePackage::ThemePackage(QObject *parent)
: Plasma::PackageStructure(parent, QString("Plasma Theme"))
{
addDirectoryDefinition("dialogs", "dialogs/", i18n("Images for dialogs"));
addFileDefinition("dialogs/background", "dialogs/background.svg",
i18n("Generic dialog background"));
addFileDefinition("dialogs/shutdowndialog", "dialogs/shutdowndialog.svg",
i18n("Theme for the logout dialog"));
addDirectoryDefinition("wallpapers", "wallpapers/", i18n("Wallpaper packages"));
addDirectoryDefinition("animations", "animations/", i18n("Animation scripts"));
addDirectoryDefinition("widgets", "widgets/", i18n("Images for widgets"));
addFileDefinition("widgets/background", "widgets/background.svg",
i18n("Background image for widgets"));
addFileDefinition("widgets/clock", "widgets/clock.svg",
i18n("Analog clock face"));
addFileDefinition("widgets/panel-background", "widgets/panel-background.svg",
i18n("Background image for panels"));
addFileDefinition("widgets/plot-background", "widgets/plot-background.svg",
i18n("Background for graphing widgets"));
addFileDefinition("widgets/tooltip", "widgets/tooltip.svg",
i18n("Background image for tooltips"));
addDirectoryDefinition("opaque/dialogs", "opaque/dialogs/", i18n("Opaque images for dialogs"));
addFileDefinition("opaque/dialogs/background", "opaque/dialogs/background.svg",
i18n("Opaque generic dialog background"));
addFileDefinition("opaque/dialogs/shutdowndialog", "opaque/dialogs/shutdowndialog.svg",
i18n("Opaque theme for the logout dialog"));
addDirectoryDefinition("opaque/widgets", "opaque/widgets/", i18n("Opaque images for widgets"));
addFileDefinition("opaque/widgets/panel-background", "opaque/widgets/panel-background.svg",
i18n("Opaque background image for panels"));
addFileDefinition("opaque/widgets/tooltip", "opaque/widgets/tooltip.svg",
i18n("Opaque background image for tooltips"));
addDirectoryDefinition("locolor/dialogs", "locolor/dialogs/",
i18n("Low color images for dialogs"));
addFileDefinition("locolor/dialogs/background", "locolor/dialogs/background.svg",
i18n("Low color generic dialog background"));
addFileDefinition("locolor/dialogs/shutdowndialog", "locolor/dialogs/shutdowndialog.svg",
i18n("Low color theme for the logout dialog"));
addDirectoryDefinition("locolor/widgets", "locolor/widgets/", i18n("Images for widgets"));
addFileDefinition("locolor/widgets/background", "locolor/widgets/background.svg",
i18n("Low color background image for widgets"));
addFileDefinition("locolor/widgets/clock", "locolor/widgets/clock.svg",
i18n("Low color analog clock face"));
addFileDefinition("locolor/widgets/panel-background", "locolor/widgets/panel-background.svg",
i18n("Low color background image for panels"));
addFileDefinition("locolor/widgets/plot-background", "locolor/widgets/plot-background.svg",
i18n("Low color background for graphing widgets"));
addFileDefinition("locolor/widgets/tooltip", "locolor/widgets/tooltip.svg",
i18n("Low color background image for tooltips"));
addFileDefinition("colors", "colors", i18n("KColorScheme configuration file"));
QStringList mimetypes;
mimetypes << "image/svg+xml";
setDefaultMimetypes(mimetypes);
}
WallpaperPackage::WallpaperPackage(Wallpaper *paper, QObject *parent)
: PackageStructure(parent, "Background"),
m_paper(paper),
m_fullPackage(true),
m_targetSize(100000, 100000),
m_resizeMethod(Wallpaper::ScaledResize)
{
QStringList mimetypes;
mimetypes << "image/svg" << "image/png" << "image/jpeg" << "image/jpg";
setDefaultMimetypes(mimetypes);
addDirectoryDefinition("images", "images/", i18n("Images"));
setRequired("images", true);
addFileDefinition("screenshot", "screenshot.png", i18n("Screenshot"));
setAllowExternalPaths(true);
if (m_paper) {
m_targetSize = m_paper->d->targetSize.toSize();
m_resizeMethod = m_paper->d->lastResizeMethod;
connect(m_paper, SIGNAL(renderHintsChanged()), this, SLOT(renderHintsChanged()));
connect(m_paper, SIGNAL(destroyed(QObject*)), this, SLOT(paperDestroyed()));
}
}
void WallpaperPackage::renderHintsChanged()
{
if (m_paper) {
m_targetSize = m_paper->d->targetSize.toSize();
m_resizeMethod = m_paper->d->lastResizeMethod;
}
if (m_fullPackage) {
findBestPaper();
}
}
void WallpaperPackage::pathChanged()
{
static bool guard = false;
if (guard) {
return;
}
guard = true;
QFileInfo info(path());
m_fullPackage = info.isDir();
removeDefinition("preferred");
setRequired("images", m_fullPackage);
if (m_fullPackage) {
setContentsPrefixPaths(QStringList() << "contents/");
findBestPaper();
} else {
// dirty trick to support having a file passed in instead of a directory
addFileDefinition("preferred", info.fileName(), i18n("Recommended wallpaper file"));
setContentsPrefixPaths(QStringList());
//kDebug() << "changing" << path() << "to" << info.path();
setPath(info.path());
}
guard = false;
}
QSize WallpaperPackage::resSize(const QString &str) const
{
int index = str.indexOf('x');
if (index != -1) {
return QSize(str.left(index).toInt(),
str.mid(index + 1).toInt());
} else {
return QSize();
}
}
void WallpaperPackage::findBestPaper()
{
QStringList images = entryList("images");
if (images.empty()) {
return;
}
//kDebug() << "wanted" << size;
// choose the nearest resolution
float best = FLT_MAX;
QString bestImage;
foreach (const QString &entry, images) {
QSize candidate = resSize(QFileInfo(entry).baseName());
if (candidate == QSize()) {
continue;
}
double dist = distance(candidate, m_targetSize, m_resizeMethod);
//kDebug() << "candidate" << candidate << "distance" << dist;
if (bestImage.isEmpty() || dist < best) {
bestImage = entry;
best = dist;
//kDebug() << "best" << bestImage;
if (dist == 0) {
break;
}
}
}
//kDebug() << "best image" << bestImage;
addFileDefinition("preferred", path("images") + bestImage, i18n("Recommended wallpaper file"));
}
float WallpaperPackage::distance(const QSize& size, const QSize& desired,
Plasma::Wallpaper::ResizeMethod method) const
{
// compute difference of areas
float delta = size.width() * size.height() -
desired.width() * desired.height();
// scale down to about 1.0
delta /= ((desired.width() * desired.height())+(size.width() * size.height()))/2;
switch (method) {
case Plasma::Wallpaper::ScaledResize: {
// Consider first the difference in aspect ratio,
// then in areas. Prefer scaling down.
float deltaRatio = 1.0;
if (size.height() > 0 && desired.height() > 0) {
deltaRatio = float(size.width()) / float(size.height()) -
float(desired.width()) / float(desired.height());
}
return fabs(deltaRatio) * 3.0 + (delta >= 0.0 ? delta : -delta + 5.0);
}
case Plasma::Wallpaper::ScaledAndCroppedResize:
// Difference of areas, slight preference to scale down
return delta >= 0.0 ? delta : -delta + 2.0;
default:
// Difference in areas
return fabs(delta);
}
}
void WallpaperPackage::paperDestroyed()
{
m_paper = 0;
}
ContainmentActionsPackage::ContainmentActionsPackage(QObject *parent)
: Plasma::PackageStructure(parent, QString("ContainmentActions"))
{
//FIXME how do I do the mimetypes stuff?
}
} // namespace Plasma
#include "packages_p.moc"
diff --git a/plasma/private/popupapplet_p.h b/plasma/private/popupapplet_p.h
index 5bcede4707..5bb7723c9c 100644
--- a/plasma/private/popupapplet_p.h
+++ b/plasma/private/popupapplet_p.h
@@ -1,73 +1,75 @@
/*
* Copyright 2008 by Montel Laurent <montel@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
#ifndef POPUPAPPLET_P_H
#define POPUPAPPLET_P_H
#include <QBasicTimer>
#include <QWeakPointer>
#include <plasma/plasma.h>
namespace Plasma
{
class PopupAppletPrivate
{
public:
PopupAppletPrivate(PopupApplet *applet);
~PopupAppletPrivate();
void iconSizeChanged(int group);
void internalTogglePopup(bool fromActivatedSignal = false);
+ void showDialog();
void hideTimedPopup();
void clearPopupLostFocus();
void dialogSizeChanged();
void dialogStatusChanged(bool status);
void restoreDialogSize();
void updateDialogPosition();
void popupConstraintsEvent(Plasma::Constraints constraints);
void checkExtenderAppearance(Plasma::FormFactor f);
KConfigGroup popupConfigGroup();
void appletActivated();
void statusChangeWhileShown(Plasma::ItemStatus status);
void createIconWidget();
PopupApplet *q;
Plasma::IconWidget *icon;
QWeakPointer<Plasma::Dialog> dialogPtr;
QWeakPointer<QGraphicsProxyWidget>proxy;
QWidget *widget;
QWeakPointer<QGraphicsWidget> graphicsWidget;
Plasma::PopupPlacement popupPlacement;
Qt::AlignmentFlag popupAlignment;
Plasma::AspectRatioMode savedAspectRatio;
QTimer *autohideTimer;
QBasicTimer delayedShowTimer;
+ QBasicTimer showDialogTimer;
QPoint clicked;
ItemStatus preShowStatus;
bool popupLostFocus : 1;
bool passive : 1;
};
} // Plasma namespace
#endif
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Fri, Nov 1, 8:01 AM (1 d, 3 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
10074660
Default Alt Text
(48 KB)
Attached To
Mode
rKL kdelibs
Attached
Detach File
Event Timeline
Log In to Comment