• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

Plasma

popupapplet.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright 2008 by Montel Laurent <montel@kde.org>
00003  * Copyright 2008 by Marco Martin <notmart@gmail.com>
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2.1 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public
00016  * License along with this library; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin St, Fifth Floor,
00018  * Boston, MA  02110-1301  USA
00019  */
00020 
00021 #include "popupapplet.h"
00022 #include "private/popupapplet_p.h"
00023 #include "private/dialog_p.h"
00024 
00025 #include <QApplication>
00026 #include <QGraphicsProxyWidget>
00027 #include <QGraphicsLinearLayout>
00028 #include <QTimer>
00029 #include <QVBoxLayout>
00030 
00031 #ifdef Q_WS_X11
00032 #include <QX11Info>
00033 #endif
00034 
00035 #include <kicon.h>
00036 #include <kiconloader.h>
00037 #include <kwindowsystem.h>
00038 #include <kglobalsettings.h>
00039 #include <netwm.h>
00040 
00041 #include "plasma/private/applet_p.h"
00042 #include "plasma/private/extenderitemmimedata_p.h"
00043 #include "plasma/corona.h"
00044 #include "plasma/containment.h"
00045 #include "plasma/private/containment_p.h"
00046 #include "plasma/dialog.h"
00047 #include "plasma/extenders/extender.h"
00048 #include "plasma/extenders/extenderitem.h"
00049 #include "plasma/package.h"
00050 #include "plasma/theme.h"
00051 #include "plasma/scripting/appletscript.h"
00052 #include "plasma/tooltipmanager.h"
00053 #include "plasma/widgets/iconwidget.h"
00054 
00055 namespace Plasma
00056 {
00057 
00058 PopupApplet::PopupApplet(QObject *parent, const QVariantList &args)
00059     : Plasma::Applet(parent, args),
00060       d(new PopupAppletPrivate(this))
00061 {
00062 }
00063 
00064 PopupApplet::PopupApplet(const QString &packagePath, uint appletId, const QVariantList &args)
00065     : Plasma::Applet(packagePath, appletId, args),
00066       d(new PopupAppletPrivate(this))
00067 {
00068 }
00069 
00070 PopupApplet::~PopupApplet()
00071 {
00072     delete widget();
00073     delete d;
00074 }
00075 
00076 void PopupApplet::setPopupIcon(const QIcon &icon)
00077 {
00078     if (icon.isNull()) {
00079         if (d->icon) {
00080             delete d->icon;
00081             d->icon = 0;
00082             setLayout(0);
00083             setAspectRatioMode(d->savedAspectRatio);
00084         }
00085 
00086         return;
00087     }
00088 
00089     if (!d->icon) {
00090         d->icon = new Plasma::IconWidget(icon, QString(), this);
00091         connect(d->icon, SIGNAL(clicked()), this, SLOT(internalTogglePopup()));
00092 
00093         QGraphicsLinearLayout *layout = new QGraphicsLinearLayout();
00094         layout->setContentsMargins(0, 0, 0, 0);
00095         layout->setSpacing(0);
00096         layout->setOrientation(Qt::Horizontal);
00097 
00098         setLayout(layout);
00099     } else {
00100         d->icon->setIcon(icon);
00101     }
00102 }
00103 
00104 void PopupApplet::setPopupIcon(const QString &iconName)
00105 {
00106     if (package()) {
00107         //Attempt1: is it in the plasmoid package?
00108         const QString file = package()->filePath("images", iconName);
00109         if (!file.isEmpty()) {
00110             setPopupIcon(KIcon(file));
00111             return;
00112         }
00113     //Attempt2: is it a svg in the icons directory?
00114     }
00115     QString name = QString("icons/") + iconName.split("-").first();
00116     if (!Plasma::Theme::defaultTheme()->imagePath(name).isEmpty()) {
00117         if (!d->icon) {
00118             d->icon = new Plasma::IconWidget(this);
00119             d->icon->setSvg(name, iconName);
00120             if (d->icon->svg().isEmpty()) {
00121                 setPopupIcon(KIcon(iconName));
00122             }
00123             connect(d->icon, SIGNAL(clicked()), this, SLOT(internalTogglePopup()));
00124 
00125             QGraphicsLinearLayout *layout = new QGraphicsLinearLayout();
00126             layout->setContentsMargins(0, 0, 0, 0);
00127             layout->setSpacing(0);
00128             layout->setOrientation(Qt::Horizontal);
00129 
00130             setLayout(layout);
00131         } else {
00132             d->icon->setSvg(name, iconName);
00133             if (d->icon->svg().isEmpty()) {
00134                 setPopupIcon(KIcon(iconName));
00135             }
00136         }
00137     // Final Attempt: use KIcon
00138     } else {
00139         setPopupIcon(KIcon(iconName));
00140     }
00141 }
00142 
00143 QIcon PopupApplet::popupIcon() const
00144 {
00145     return d->icon ? d->icon->icon() : QIcon();
00146 }
00147 
00148 QWidget *PopupApplet::widget()
00149 {
00150     return d->widget;
00151 }
00152 
00153 void PopupApplet::setWidget(QWidget *widget)
00154 {
00155     if (d->widget) {
00156         Plasma::Dialog *dialog = d->dialogPtr.data();
00157         if (dialog) {
00158             dialog->setGraphicsWidget(0);
00159             QVBoxLayout *lay = 0;
00160 
00161             QLayout *existingLayout = dialog->layout();
00162             if (existingLayout) {
00163                 lay = dynamic_cast<QVBoxLayout *>(existingLayout);
00164                 if (!lay) {
00165                     delete existingLayout;
00166                 }
00167             }
00168 
00169             if (!lay) {
00170                 lay = new QVBoxLayout;
00171                 dialog->setLayout(lay);
00172             }
00173 
00174             lay->removeWidget(d->widget);
00175             lay->addWidget(widget);
00176         } else if (d->proxy) {
00177             d->proxy.data()->setWidget(widget);
00178         }
00179     }
00180 
00181     d->widget = widget;
00182 }
00183 
00184 QGraphicsWidget *PopupApplet::graphicsWidget()
00185 {
00186     if (d->graphicsWidget != 0) {
00187         return d->graphicsWidget;
00188     } else {
00189         return static_cast<Applet*>(this)->d->extender.data();
00190     }
00191 }
00192 
00193 void PopupApplet::setGraphicsWidget(QGraphicsWidget *graphicsWidget)
00194 {
00195     if (d->graphicsWidget) {
00196         if (d->dialogPtr) {
00197             d->dialogPtr.data()->setGraphicsWidget(graphicsWidget);
00198         } else {
00199             QGraphicsLinearLayout *lay = static_cast<QGraphicsLinearLayout *>(layout());
00200             lay->removeAt(0);
00201             lay->addItem(graphicsWidget);
00202         }
00203     }
00204 
00205     d->graphicsWidget = graphicsWidget;
00206 }
00207 
00208 void PopupAppletPrivate::checkExtenderAppearance(Plasma::FormFactor f)
00209 {
00210     Extender *extender = qobject_cast<Extender*>(q->graphicsWidget());
00211     if (extender) {
00212         if (f != Plasma::Horizontal && f != Plasma::Vertical) {
00213             extender->setAppearance(Extender::NoBorders);
00214         } else if (q->location() == TopEdge) {
00215             extender->setAppearance(Extender::TopDownStacked);
00216         } else {
00217             extender->setAppearance(Extender::BottomUpStacked);
00218         }
00219 
00220         if (dialogPtr) {
00221             dialogPtr.data()->setGraphicsWidget(extender);
00222         }
00223     }
00224 }
00225 
00226 void PopupAppletPrivate::popupConstraintsEvent(Plasma::Constraints constraints)
00227 {
00228     Plasma::FormFactor f = q->formFactor();
00229 
00230     if (constraints & Plasma::LocationConstraint) {
00231         checkExtenderAppearance(f);
00232     }
00233 
00234     if (constraints & Plasma::FormFactorConstraint ||
00235         constraints & Plasma::StartupCompletedConstraint ||
00236         (constraints & Plasma::SizeConstraint &&
00237          (f == Plasma::Vertical || f == Plasma::Horizontal))) {
00238         QGraphicsLinearLayout *lay = dynamic_cast<QGraphicsLinearLayout *>(q->layout());
00239 
00240         if (icon && lay && lay->count() > 0) {
00241             lay->removeAt(0);
00242         }
00243 
00244         QSizeF minimum;
00245         QSizeF parentSize;
00246 
00247         QGraphicsWidget *gWidget = q->graphicsWidget();
00248         //kDebug() << "graphics widget is" << (QObject*)gWidget;
00249         QWidget *qWidget = q->widget();
00250 
00251         if (gWidget) {
00252             minimum = gWidget->minimumSize();
00253             // our layout may have been replaced on us in the call to graphicsWidget!
00254             lay = dynamic_cast<QGraphicsLinearLayout *>(q->layout());
00255 
00256             if (!(constraints & LocationConstraint)) {
00257                 checkExtenderAppearance(f);
00258             }
00259         } else if (qWidget) {
00260             minimum = qWidget->minimumSizeHint();
00261         }
00262 
00263         //99% of the times q->parentWidget() is the containment, but using it  we can also manage the applet-in-applet case (i.e. systray)
00264         //there are also cases where the parentlayoutitem is bigger than the containment (e.g. newspaper)
00265         if (q->parentLayoutItem()) {
00266             parentSize = q->parentLayoutItem()->geometry().size();
00267         } else if (q->parentWidget()) {
00268             parentSize = q->parentWidget()->size();
00269         }
00270 
00271         //check if someone did the nasty trick of applets in applets, in this case we always want to be collapsed
00272         QGraphicsWidget *candidateParentApplet = q;
00273         Plasma::Applet *parentApplet = 0;
00274         //this loop should be executed normally a single time, at most 2-3 times for quite complex containments
00275         while (candidateParentApplet) {
00276             candidateParentApplet = candidateParentApplet->parentWidget();
00277             parentApplet = qobject_cast<Plasma::Applet *>(candidateParentApplet);
00278             if (parentApplet) {
00279                 break;
00280             }
00281         }
00282 
00283         //Applet on desktop
00284         if ((!parentApplet || parentApplet->isContainment() ) && icon && (!icon->svg().isEmpty() || !icon->icon().isNull()) && ((f != Plasma::Vertical && f != Plasma::Horizontal) ||
00285             ((f == Plasma::Vertical && parentSize.width() >= minimum.width()) ||
00286              (f == Plasma::Horizontal && parentSize.height() >= minimum.height())))) {
00287             //kDebug() << "we are expanding the popupapplet";
00288 
00289 
00290             // we only switch to expanded if we aren't horiz/vert constrained and
00291             // this applet has an icon.
00292             // otherwise, we leave it up to the applet itself to figure it out
00293             if (icon) {
00294                 icon->hide();
00295             }
00296 
00297             if (savedAspectRatio != Plasma::InvalidAspectRatioMode) {
00298                 q->setAspectRatioMode(savedAspectRatio);
00299             }
00300 
00301             Dialog *dialog = dialogPtr.data();
00302             if (dialog) {
00303                 if (dialog->layout() && qWidget) {
00304                     //we don't want to delete Widget inside the dialog layout
00305                     dialog->layout()->removeWidget(qWidget);
00306                 }
00307 
00308                 if (qWidget) {
00309                     qWidget->setParent(0);
00310                 }
00311 
00312                 delete dialog;
00313             }
00314 
00315             if (!lay) {
00316                 lay = new QGraphicsLinearLayout();
00317                 lay->setContentsMargins(0, 0, 0, 0);
00318                 lay->setSpacing(0);
00319                 lay->setOrientation(Qt::Horizontal);
00320                 q->setLayout(lay);
00321             }
00322 
00323             QSize prefSize;
00324 
00325             if (gWidget) {
00326                 if (proxy) {
00327                     proxy.data()->setWidget(0);
00328                     delete proxy.data();
00329                 }
00330 
00331                 Corona *corona = qobject_cast<Corona *>(gWidget->scene());
00332 
00333                 if (corona) {
00334                     corona->removeOffscreenWidget(gWidget);
00335                 }
00336 
00337                 lay->addItem(gWidget);
00338                 prefSize = gWidget->preferredSize().toSize();
00339             } else if (qWidget) {
00340                 if (!proxy) {
00341                     proxy = new QGraphicsProxyWidget(q);
00342                     proxy.data()->setWidget(qWidget);
00343                     proxy.data()->show();
00344                 }
00345 
00346                 lay->addItem(proxy.data());
00347                 prefSize = qWidget->sizeHint();
00348             }
00349 
00350             //we could be on a big panel, but in that case we will be able to resize
00351             //more than the natural minimum size, because we'll transform into an icon
00352             if (f == Plasma::Horizontal) {
00353                 minimum.setHeight(0);
00354             } else if (f == Plasma::Vertical) {
00355                 minimum.setWidth(0);
00356             }
00357 
00358             qreal left, top, right, bottom;
00359             q->getContentsMargins(&left, &top, &right, &bottom);
00360             QSizeF oldSize(q->size());
00361 
00362             //size not saved/invalid size saved
00363             if (oldSize.width() < q->minimumSize().width() || oldSize.height() < q->minimumSize().height()) {
00364                 q->resize(prefSize);
00365                 emit q->appletTransformedItself();
00366             }
00367         //Applet on popup
00368         } else {
00369             //kDebug() << "about to switch to a popup";
00370             if (proxy) {
00371                 proxy.data()->setWidget(0); // prevent it from deleting our widget!
00372                 delete proxy.data();
00373             }
00374 
00375             if (!dialogPtr) {
00376                 //save the aspect ratio mode in case we drag'n drop in the Desktop later
00377                 savedAspectRatio = q->aspectRatioMode();
00378 
00379                 if (icon) {
00380                     icon->show();
00381                     q->setAspectRatioMode(Plasma::ConstrainedSquare);
00382                 }
00383 
00384                 Dialog *dialog = new Dialog();
00385                 dialog->d->appletPtr = q;
00386                 dialogPtr = dialog;
00387 
00388                 dialog->setAspectRatioMode(savedAspectRatio);
00389 
00390                 //no longer use Qt::Popup since that seems to cause a lot of problem when you drag
00391                 //stuff out of your Dialog (extenders). Monitor WindowDeactivate events so we can
00392                 //emulate the same kind of behavior as Qt::Popup (close when you click somewhere
00393                 //else.
00394 
00395                 if (gWidget) {
00396                     Corona *corona = qobject_cast<Corona *>(gWidget->scene());
00397 
00398                     if (corona) {
00399                         corona->addOffscreenWidget(gWidget);
00400                     }
00401 
00402                     dialog->setGraphicsWidget(gWidget);
00403                     gWidget->resize(gWidget->preferredSize());
00404                     dialog->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | (gWidget->windowFlags() & Qt::X11BypassWindowManagerHint));
00405                 } else if (qWidget) {
00406                     QVBoxLayout *l_layout = new QVBoxLayout(dialog);
00407                     l_layout->setSpacing(0);
00408                     l_layout->setMargin(0);
00409                     l_layout->addWidget(qWidget);
00410                     dialog->adjustSize();
00411                     dialog->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | (qWidget->windowFlags() & Qt::X11BypassWindowManagerHint));
00412                 } else {
00413                     dialog->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
00414                 }
00415 
00416                 restoreDialogSize();
00417                 KWindowSystem::setState(dialog->winId(), NET::SkipTaskbar | NET::SkipPager);
00418                 dialog->installEventFilter(q);
00419 
00420                 QObject::connect(dialog, SIGNAL(dialogResized()), q, SLOT(dialogSizeChanged()));
00421                 QObject::connect(dialog, SIGNAL(dialogVisible(bool)), q, SLOT(dialogStatusChanged(bool)));
00422             }
00423 
00424             if (icon && lay) {
00425                 lay->addItem(icon);
00426             }
00427         }
00428     }
00429 
00430     if (constraints & Plasma::PopupConstraint) {
00431         updateDialogPosition();
00432     }
00433 
00434     emit q->sizeHintChanged(Qt::PreferredSize);
00435 }
00436 
00437 void PopupAppletPrivate::appletActivated()
00438 {
00439     q->setStatus(Plasma::NeedsAttentionStatus);
00440     q->showPopup();
00441 }
00442 
00443 QSizeF PopupApplet::sizeHint(Qt::SizeHint which, const QSizeF & constraint) const
00444 {
00445     if (!d->dialogPtr || which != Qt::PreferredSize) {
00446         return Applet::sizeHint(which, constraint);
00447     }
00448 
00449     switch (formFactor()) {
00450         case Vertical:
00451         case Horizontal: {
00452             const int size = IconSize(KIconLoader::Panel);
00453             return QSizeF(size, size);
00454             break;
00455         }
00456         default:
00457             break;
00458     }
00459 
00460     const int size = IconSize(KIconLoader::Desktop);
00461     return QSizeF(size, size);
00462 }
00463 
00464 void PopupApplet::mousePressEvent(QGraphicsSceneMouseEvent *event)
00465 {
00466     if (!d->icon && !d->popupLostFocus && event->buttons() == Qt::LeftButton) {
00467         d->clicked = scenePos().toPoint();
00468         event->setAccepted(true);
00469         return;
00470     } else {
00471         d->popupLostFocus = false;
00472         Applet::mousePressEvent(event);
00473     }
00474 }
00475 
00476 void PopupApplet::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
00477 {
00478     if (!d->icon &&
00479         (d->clicked - scenePos().toPoint()).manhattanLength() < KGlobalSettings::dndEventDelay()) {
00480         d->internalTogglePopup();
00481     } else {
00482         Applet::mouseReleaseEvent(event);
00483     }
00484 }
00485 
00486 bool PopupApplet::eventFilter(QObject *watched, QEvent *event)
00487 {
00488     if (!d->passive && watched == d->dialogPtr.data() && (event->type() == QEvent::WindowDeactivate)) {
00489         d->popupLostFocus = true;
00490         QTimer::singleShot(100, this, SLOT(clearPopupLostFocus()));
00491     }
00492 
00493     if (watched == d->dialogPtr.data() && event->type() == QEvent::ContextMenu) {
00494         //pass it up to the applet
00495         //well, actually we have to pass it to the *containment*
00496         //because all the code for showing an applet's contextmenu is actually in Containment.
00497         Containment *c = containment();
00498         if (c) {
00499             Applet *applet = this;
00500             Dialog *dialog = d->dialogPtr.data();
00501             if (dialog && dialog->graphicsWidget()) {
00502                 int left, top, right, bottom;
00503                 dialog->getContentsMargins(&left, &top, &right, &bottom);
00504                 const QPoint eventPos = static_cast<QContextMenuEvent*>(event)->pos() - QPoint(left, top);
00505                 QPointF pos = dialog->graphicsWidget()->mapToScene(eventPos);
00506 
00507                 if (Applet *actual = c->d->appletAt(pos)) {
00508                     applet = actual;
00509                 }
00510             }
00511 
00512             KMenu desktopMenu;
00513             c->d->addAppletActions(desktopMenu, applet, event);
00514 
00515             if (!desktopMenu.isEmpty()) {
00516                 desktopMenu.exec(static_cast<QContextMenuEvent*>(event)->globalPos());
00517                 return true;
00518             }
00519 
00520             return false;
00521         }
00522     }
00523 
00524     return Applet::eventFilter(watched, event);
00525 }
00526 
00527 //FIXME: some duplication between the drag events... maybe add some simple helper function?
00528 void PopupApplet::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
00529 {
00530     if (event->mimeData()->hasFormat(ExtenderItemMimeData::mimeType())) {
00531         const ExtenderItemMimeData *mimeData =
00532             qobject_cast<const ExtenderItemMimeData*>(event->mimeData());
00533         if (mimeData && qobject_cast<Extender*>(graphicsWidget())) {
00534             event->accept();
00535             showPopup();
00536         }
00537     }
00538 }
00539 
00540 void PopupApplet::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
00541 {
00542     if (event->mimeData()->hasFormat(ExtenderItemMimeData::mimeType())) {
00543         const ExtenderItemMimeData *mimeData =
00544             qobject_cast<const ExtenderItemMimeData*>(event->mimeData());
00545         if (mimeData && qobject_cast<Extender*>(graphicsWidget())) {
00546             //We want to hide the popup if we're not moving onto the popup AND it is not the popup
00547             //we started.
00548             if (d->dialogPtr && !d->dialogPtr.data()->geometry().contains(event->screenPos()) &&
00549                 mimeData->extenderItem()->extender() != qobject_cast<Extender*>(graphicsWidget())) {
00550                 //We actually try to hide the popup, with a call to showPopup, with a smal timeout,
00551                 //so if the user moves into the popup fast enough, it remains open (the extender
00552                 //will call showPopup which will cancel the timeout.
00553                 showPopup(250);
00554             }
00555         }
00556     }
00557 }
00558 
00559 void PopupApplet::dropEvent(QGraphicsSceneDragDropEvent *event)
00560 {
00561     if (event->mimeData()->hasFormat(ExtenderItemMimeData::mimeType())) {
00562         const ExtenderItemMimeData *mimeData =
00563             qobject_cast<const ExtenderItemMimeData*>(event->mimeData());
00564         if (mimeData && qobject_cast<Extender*>(graphicsWidget())) {
00565             mimeData->extenderItem()->setExtender(extender());
00566             QApplication::restoreOverrideCursor();
00567         }
00568     }
00569 }
00570 
00571 void PopupApplet::showPopup(uint popupDuration)
00572 {
00573     // use autohideTimer to store when the next show should be
00574     if (popupDuration > 0 || d->autohideTimer) {
00575         if (!d->autohideTimer) {
00576             d->autohideTimer = new QTimer(this);
00577             d->autohideTimer->setSingleShot(true);
00578             connect(d->autohideTimer, SIGNAL(timeout()), this, SLOT(hideTimedPopup()));
00579         }
00580 
00581         d->autohideTimer->stop();
00582         d->autohideTimer->setInterval(popupDuration);
00583     }
00584 
00585     //kDebug() << "starting delayed show, duration for popup is" << popupDuration;
00586     d->delayedShowTimer.start(0, this);
00587 }
00588 
00589 void PopupApplet::timerEvent(QTimerEvent *event)
00590 {
00591     if (event->timerId() == d->delayedShowTimer.timerId()) {
00592         d->delayedShowTimer.stop();
00593         Dialog *dialog = d->dialogPtr.data();
00594         if (dialog) {
00595             // move the popup before its fist show, even if the show isn't triggered by
00596             // a click, this should fix the first random position seen in some widgets
00597             if (!dialog->isVisible()) {
00598                 d->internalTogglePopup();
00599             }
00600 
00601             const int popupDuration = d->autohideTimer ? d->autohideTimer->interval() : 0;
00602             //kDebug() << "popupDuration is:" << (d->autohideTimer ? d->autohideTimer->interval() : 0);
00603             if (popupDuration > 0) {
00604                 d->autohideTimer->start();
00605             } else if (d->autohideTimer) {
00606                 d->autohideTimer->stop();
00607             }
00608         }
00609     } else {
00610         Applet::timerEvent(event);
00611     }
00612 }
00613 
00614 void PopupApplet::hidePopup()
00615 {
00616     d->delayedShowTimer.stop();
00617 
00618     Dialog *dialog = d->dialogPtr.data();
00619     if (dialog) {
00620         if (location() != Floating) {
00621             dialog->animatedHide(locationToInverseDirection(location()));
00622         } else {
00623             dialog->hide();
00624         }
00625     }
00626 }
00627 
00628 void PopupApplet::togglePopup()
00629 {
00630     d->internalTogglePopup();
00631 }
00632 
00633 Plasma::PopupPlacement PopupApplet::popupPlacement() const
00634 {
00635     return d->popupPlacement;
00636 }
00637 
00638 void PopupApplet::setPopupAlignment(Qt::AlignmentFlag alignment)
00639 {
00640     d->popupAlignment = alignment;
00641 }
00642 
00643 Qt::AlignmentFlag PopupApplet::popupAlignment() const
00644 {
00645     return d->popupAlignment;
00646 }
00647 
00648 void PopupApplet::popupEvent(bool popped)
00649 {
00650     if (Applet::d->script) {
00651         emit Applet::d->script->popupEvent(popped);
00652     }
00653 }
00654 
00655 void PopupApplet::setPassivePopup(bool passive)
00656 {
00657     d->passive = passive;
00658 }
00659 
00660 bool PopupApplet::isPassivePopup() const
00661 {
00662     return d->passive;
00663 }
00664 
00665 bool PopupApplet::isPopupShowing() const
00666 {
00667     return d->dialogPtr && d->dialogPtr.data()->isVisible();
00668 }
00669 
00670 bool PopupApplet::isIconified() const
00671 {
00672     return d->dialogPtr;
00673 }
00674 
00675 PopupAppletPrivate::PopupAppletPrivate(PopupApplet *applet)
00676         : q(applet),
00677           icon(0),
00678           widget(0),
00679           graphicsWidget(0),
00680           popupPlacement(Plasma::FloatingPopup),
00681           popupAlignment(Qt::AlignLeft),
00682           savedAspectRatio(Plasma::InvalidAspectRatioMode),
00683           autohideTimer(0),
00684           popupLostFocus(false),
00685           passive(false)
00686 {
00687     int iconSize = IconSize(KIconLoader::Desktop);
00688     q->resize(iconSize, iconSize);
00689     q->setAcceptDrops(true);
00690     QObject::disconnect(q, SIGNAL(activate()), static_cast<Applet*>(q), SLOT(setFocus()));
00691     QObject::connect(q, SIGNAL(activate()), q, SLOT(appletActivated()));
00692     QObject::connect(KGlobalSettings::self(), SIGNAL(iconChanged(int)), q, SLOT(iconSizeChanged(int)));
00693 }
00694 
00695 PopupAppletPrivate::~PopupAppletPrivate()
00696 {
00697     if (proxy) {
00698         proxy.data()->setWidget(0);
00699     }
00700 
00701     delete dialogPtr.data();
00702     delete icon;
00703 }
00704 
00705 void PopupAppletPrivate::iconSizeChanged(int group)
00706 {
00707     if (icon && (group == KIconLoader::Desktop || group == KIconLoader::Panel)) {
00708         q->updateGeometry();
00709     }
00710 }
00711 
00712 void PopupAppletPrivate::internalTogglePopup()
00713 {
00714     if (autohideTimer) {
00715         autohideTimer->stop();
00716     }
00717 
00718     delayedShowTimer.stop();
00719 
00720     Plasma::Dialog *dialog = dialogPtr.data();
00721     if (!dialog) {
00722         q->setFocus(Qt::ShortcutFocusReason);
00723         return;
00724     }
00725 
00726     if (!q->view()) {
00727         return;
00728     }
00729 
00730     if (dialog->isVisible()) {
00731         if (q->location() != Floating) {
00732             dialog->animatedHide(locationToInverseDirection(q->location()));
00733         } else {
00734             dialog->hide();
00735         }
00736 
00737         dialog->clearFocus();
00738     } else {
00739         if (q->graphicsWidget() &&
00740             q->graphicsWidget() == static_cast<Applet*>(q)->d->extender.data() &&
00741             static_cast<Applet*>(q)->d->extender.data()->isEmpty()) {
00742             // we have nothing to show, so let's not.
00743             return;
00744         }
00745 
00746         ToolTipManager::self()->hide(q);
00747         updateDialogPosition();
00748 
00749         KWindowSystem::setOnAllDesktops(dialog->winId(), true);
00750         KWindowSystem::setState(dialog->winId(), NET::SkipTaskbar | NET::SkipPager);
00751 
00752         dialog->setAspectRatioMode(savedAspectRatio);
00753 
00754         if (q->location() != Floating) {
00755             dialog->animatedShow(locationToDirection(q->location()));
00756         } else {
00757             dialog->show();
00758         }
00759 
00760         if (!(dialog->windowFlags() & Qt::X11BypassWindowManagerHint)) {
00761             KWindowSystem::activateWindow(dialog->winId());
00762         }
00763     }
00764 }
00765 
00766 void PopupAppletPrivate::hideTimedPopup()
00767 {
00768     autohideTimer->stop();
00769     q->hidePopup();
00770 }
00771 
00772 void PopupAppletPrivate::clearPopupLostFocus()
00773 {
00774     if (!icon || !icon->isDown()) {
00775         q->hidePopup();
00776     }
00777 
00778     popupLostFocus = false;
00779 }
00780 
00781 KConfigGroup PopupAppletPrivate::popupConfigGroup()
00782 {
00783     KConfigGroup *mainGroup = static_cast<Applet*>(q)->d->mainConfigGroup();
00784     return KConfigGroup(mainGroup, "PopupApplet");
00785 }
00786 
00787 void PopupAppletPrivate::dialogSizeChanged()
00788 {
00789     //Reposition the dialog
00790     Plasma::Dialog *dialog = dialogPtr.data();
00791     if (dialog) {
00792         KConfigGroup sizeGroup = popupConfigGroup();
00793         sizeGroup.writeEntry("DialogHeight", dialog->height());
00794         sizeGroup.writeEntry("DialogWidth", dialog->width());
00795 
00796         updateDialogPosition();
00797 
00798         emit q->configNeedsSaving();
00799         emit q->appletTransformedByUser();
00800     }
00801 }
00802 
00803 void PopupAppletPrivate::dialogStatusChanged(bool status)
00804 {
00805     q->popupEvent(status);
00806 }
00807 
00808 void PopupAppletPrivate::restoreDialogSize()
00809 {
00810     Plasma::Dialog *dialog = dialogPtr.data();
00811     if (!dialog) {
00812         return;
00813     }
00814 
00815     Corona *corona = qobject_cast<Corona *>(q->scene());
00816     if (!corona) {
00817         return;
00818     }
00819 
00820     KConfigGroup sizeGroup = popupConfigGroup();
00821 
00822     int preferredWidth = 0;
00823     int preferredHeight = 0;
00824     if (dialog->graphicsWidget()) {
00825         preferredWidth = dialog->graphicsWidget()->preferredSize().width();
00826         preferredHeight = dialog->graphicsWidget()->preferredSize().height();
00827     }
00828 
00829     const int width = qMin(sizeGroup.readEntry("DialogWidth", preferredWidth),
00830                            corona->screenGeometry(-1).width() - 50);
00831     const int height = qMin(sizeGroup.readEntry("DialogHeight", preferredHeight),
00832                             corona->screenGeometry(-1).height() - 50);
00833 
00834     QSize saved(width, height);
00835 
00836     if (saved.isNull()) {
00837         saved = dialog->sizeHint();
00838     } else {
00839         saved = saved.expandedTo(dialog->minimumSizeHint());
00840     }
00841 
00842     if (saved.width() != dialog->width() || saved.height() != dialog->height()) {
00843         dialog->resize(saved);
00844     }
00845 }
00846 
00847 void PopupAppletPrivate::updateDialogPosition()
00848 {
00849     Plasma::Dialog *dialog = dialogPtr.data();
00850     if (!dialog) {
00851         return;
00852     }
00853 
00854     Corona *corona = qobject_cast<Corona *>(q->scene());
00855     if (!corona) {
00856         return;
00857     }
00858 
00859     QGraphicsView *view = q->view();
00860     if (!view) {
00861         return;
00862     }
00863 
00864     QSize s = dialog->size();
00865     QPoint pos = view->mapFromScene(q->scenePos());
00866 
00867     if (!q->containment() || view == q->containment()->view()) {
00868         pos = corona->popupPosition(q, s, popupAlignment);
00869     } else {
00870         pos = corona->popupPosition(q->parentItem(), s, popupAlignment);
00871     }
00872 
00873     bool reverse = false;
00874     if (q->formFactor() == Plasma::Vertical) {
00875         if (view->mapToGlobal(view->mapFromScene(q->scenePos())).y() + q->size().height()/2 < pos.y() + dialog->size().width()/2) {
00876             reverse = true;
00877         }
00878     } else {
00879         if (view->mapToGlobal(view->mapFromScene(q->scenePos())).x() + q->size().width()/2 < pos.x() + dialog->size().width()/2) {
00880             reverse = true;
00881         }
00882     }
00883 
00884     switch (q->location()) {
00885     case BottomEdge:
00886         if (pos.x() >= q->pos().x()) {
00887             dialog->setResizeHandleCorners(Dialog::NorthEast);
00888         } else {
00889             dialog->setResizeHandleCorners(Dialog::NorthWest);
00890         }
00891 
00892         if (reverse) {
00893             popupPlacement = Plasma::TopPosedLeftAlignedPopup;
00894         } else {
00895             popupPlacement = Plasma::TopPosedRightAlignedPopup;
00896         }
00897         break;
00898     case TopEdge:
00899         if (pos.x() >= q->pos().x()) {
00900             dialog->setResizeHandleCorners(Dialog::SouthEast);
00901         } else {
00902             dialog->setResizeHandleCorners(Dialog::SouthWest);
00903         }
00904 
00905         if (reverse) {
00906             popupPlacement = Plasma::BottomPosedLeftAlignedPopup;
00907         } else {
00908             popupPlacement = Plasma::BottomPosedRightAlignedPopup;
00909         }
00910         break;
00911     case LeftEdge:
00912         if (pos.y() >= q->pos().y()) {
00913             dialog->setResizeHandleCorners(Dialog::SouthEast);
00914         } else {
00915             dialog->setResizeHandleCorners(Dialog::NorthEast);
00916         }
00917 
00918         if (reverse) {
00919             popupPlacement = Plasma::RightPosedTopAlignedPopup;
00920         } else {
00921             popupPlacement = Plasma::RightPosedBottomAlignedPopup;
00922         }
00923         break;
00924 
00925     case RightEdge:
00926         if (pos.y() >= q->pos().y()) {
00927             dialog->setResizeHandleCorners(Dialog::SouthWest);
00928         } else {
00929             dialog->setResizeHandleCorners(Dialog::NorthWest);
00930         }
00931 
00932         if (reverse) {
00933             popupPlacement = Plasma::LeftPosedTopAlignedPopup;
00934         } else {
00935             popupPlacement = Plasma::LeftPosedBottomAlignedPopup;
00936         }
00937         break;
00938     default:
00939         dialog->setResizeHandleCorners(Dialog::NorthEast);
00940     }
00941 
00942     dialog->move(pos);
00943 }
00944 
00945 } // Plasma namespace
00946 
00947 #include "popupapplet.moc"
00948 

Plasma

Skip menu "Plasma"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal