remove classes that weren't built anymore
PopupApplet Dialog ToolTip ToolTipManager ToolTipContent
This commit is contained in:
parent
4e08835046
commit
81d2a33a0f
@ -133,7 +133,6 @@ set(plasma_LIB_SRCS
|
||||
private/serviceprovider.cpp
|
||||
private/storage.cpp
|
||||
private/storagethread.cpp
|
||||
private/tooltip.cpp
|
||||
private/wallpaperrenderthread.cpp
|
||||
private/windowpreview.cpp
|
||||
private/windowshadows.cpp
|
||||
@ -166,9 +165,6 @@ set(plasma_LIB_SRCS
|
||||
servicejob.cpp
|
||||
svg.cpp
|
||||
theme.cpp
|
||||
tooltipcontent.cpp
|
||||
#FIXME: re-enable
|
||||
#tooltipmanager.cpp
|
||||
version.cpp
|
||||
wallpaper.cpp
|
||||
|
||||
@ -186,34 +182,11 @@ set(plasma_LIB_SRCS
|
||||
private/qtjolie-branch/qtjolie/pendingreply.cpp
|
||||
private/qtjolie-branch/qtjolie/server.cpp
|
||||
private/qtjolie-branch/qtjolie/serverthread.cpp
|
||||
|
||||
#FIXME: all these must move into the qgv library
|
||||
#view.cpp
|
||||
applet.cpp
|
||||
containment.cpp
|
||||
corona.cpp
|
||||
#dialog.cpp
|
||||
#should popupapplet still exist?
|
||||
#popupapplet.cpp
|
||||
)
|
||||
|
||||
#TODO: all those files will have to be deleted
|
||||
# set (plasmaqgv_LIB_SRCS
|
||||
# dialog.cpp
|
||||
# view.cpp
|
||||
# private/themedwidgetinterface.cpp
|
||||
# widgets/iconwidget.cpp
|
||||
# #FIXME: this is duplicated with libplasma because iconwidget requires it!
|
||||
# private/themedwidgetinterface.cpp
|
||||
#
|
||||
# graphicsview/private/graphicsviewappletprivate.cpp
|
||||
#
|
||||
# private/declarative/declarativenetworkaccessmanagerfactory.cpp
|
||||
# private/declarative/dataenginebindings.cpp
|
||||
#
|
||||
# widgets/declarativewidget.cpp
|
||||
# )
|
||||
|
||||
kconfig_add_kcfg_files(plasma_LIB_SRCS data/kconfigxt/libplasma-theme-global.kcfgc)
|
||||
|
||||
kde4_add_ui_files(plasma_LIB_SRCS
|
||||
@ -272,7 +245,6 @@ set(plasma_LIB_INCLUDES
|
||||
corona.h
|
||||
datacontainer.h
|
||||
dataengine.h
|
||||
dialog.h
|
||||
pluginloader.h
|
||||
paintutils.h
|
||||
framesvg.h
|
||||
@ -280,7 +252,6 @@ set(plasma_LIB_INCLUDES
|
||||
packagestructure.h
|
||||
plasma.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/plasma_export.h
|
||||
popupapplet.h
|
||||
querymatch.h
|
||||
remote/accessappletjob.h
|
||||
remote/accessmanager.h
|
||||
@ -297,8 +268,6 @@ set(plasma_LIB_INCLUDES
|
||||
servicejob.h
|
||||
svg.h
|
||||
theme.h
|
||||
tooltipcontent.h
|
||||
tooltipmanager.h
|
||||
version.h
|
||||
view.h
|
||||
wallpaper.h)
|
||||
@ -319,7 +288,6 @@ install(FILES
|
||||
|
||||
install(FILES
|
||||
data/servicetypes/plasma-applet.desktop
|
||||
data/servicetypes/plasma-applet-popupapplet.desktop
|
||||
data/servicetypes/plasma-containment.desktop
|
||||
data/servicetypes/plasma-containmentactions.desktop
|
||||
data/servicetypes/plasma-dataengine.desktop
|
||||
|
@ -84,7 +84,6 @@
|
||||
#include "remote/authorizationmanager.h"
|
||||
#include "remote/authorizationmanager_p.h"
|
||||
#include "theme.h"
|
||||
#include "tooltipmanager.h"
|
||||
#include "wallpaper.h"
|
||||
#include "paintutils.h"
|
||||
#include "abstractdialogmanager.h"
|
||||
|
@ -45,7 +45,6 @@
|
||||
#include "pluginloader.h"
|
||||
#include "private/applet_p.h"
|
||||
#include "private/containment_p.h"
|
||||
#include "tooltipmanager.h"
|
||||
#include "view.h"
|
||||
|
||||
using namespace Plasma;
|
||||
|
@ -1,73 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Type=ServiceType
|
||||
X-KDE-ServiceType=Plasma/PopupApplet
|
||||
|
||||
Comment=Plasma scripting popup applet
|
||||
Comment[ar]=بريمج منبثق بواسطة سكربت بلازما
|
||||
Comment[ast]=Miniaplicación emerxente de script pa Plasma
|
||||
Comment[be@latin]=Skryptavy vypłyŭny aplet „Plasma”
|
||||
Comment[bg]=Аплет за Plasma за скриптове за изскачащи прозорци
|
||||
Comment[bs]=Plazma skriptovani iskačući aplet
|
||||
Comment[ca]=Miniaplicació emergent d'scripting del Plasma
|
||||
Comment[ca@valencia]=Miniaplicació emergent d'scripting del Plasma
|
||||
Comment[cs]=Skriptovací vyskakující Plasma applet
|
||||
Comment[da]=Popop-applet til Plasma-scripting
|
||||
Comment[de]=Plasma-Skript-Miniprogramm
|
||||
Comment[el]=Αναδυόμενη μικροεφαρμογή σεναρίου plasma
|
||||
Comment[en_GB]=Plasma scripting popup applet
|
||||
Comment[es]=Miniaplicación emergente de script para Plasma
|
||||
Comment[et]=Plasma skriptimise hüpikaplett
|
||||
Comment[eu]=Plasma scripting popup appleta
|
||||
Comment[fi]=Skriptikielellä tehty Plasma-ponnahdussovelma
|
||||
Comment[fr]=Applet de script Plasma
|
||||
Comment[fy]=Plasma scripting popup applet
|
||||
Comment[ga]=Feidhmchláirín aníos scriptithe Plasma
|
||||
Comment[gl]=Applet contextual de scripts de Plasma
|
||||
Comment[gu]=પ્લાઝમા સ્ક્રિપ્ટીંગ પોપઅપ એપ્લેટ
|
||||
Comment[he]=תפריט מוקפץ עבור יישומון תסריט של Plasma
|
||||
Comment[hr]=Plasmin skriptni skočni applet
|
||||
Comment[hu]=Szkriptkezelő kisalkalmazás a Plasmához
|
||||
Comment[ia]=Applet popup de scripting de Plasma
|
||||
Comment[id]=Applet popup skrip Plasma
|
||||
Comment[is]=Plasma smáforrit fyrir skriftun
|
||||
Comment[it]=Applet Plasma scripting a comparsa
|
||||
Comment[ja]=Plasma スクリプティング・ポップアップアプレット
|
||||
Comment[kk]=Қалқымалы Plasma скрипт апплеті
|
||||
Comment[km]=អាប់ភ្លេតលេចឡើងរបស់ស្គ្រីបប្លាស្មា
|
||||
Comment[kn]=ಪ್ಲಾಸ್ಮಾ ವಿಧಿಗುಚ್ಛ (ಸ್ಕ್ರಿಪ್ಟ್) ವಿಕಸನ ಪುಟಿಕೆ (ಪಾಪಪ್) ಅನ್ವಯಾಂಶ (ಆಪ್ಲೆಟ್)
|
||||
Comment[ko]=Plasma 스크립팅 팝업 애플릿
|
||||
Comment[ku]=Sepanoka skrîptkirina agahiyan ya Plasma
|
||||
Comment[lv]=Plasma skriptu uznirstošais logs
|
||||
Comment[ml]=പ്ലാസ്മ സ്ക്രിപ്റ്റിങ്ങിന്റെ പൊങ്ങിവരുന്ന ലഘുപ്രയോഗം
|
||||
Comment[nb]=Oppsprett-miniprogram for Plasma-skripting
|
||||
Comment[nds]=Skript-Opduklüttprogramm vun Plasma
|
||||
Comment[nl]=Plasma-applet voor scripting-popup
|
||||
Comment[nn]=Sprettoppelement for Plasma-skript
|
||||
Comment[pa]=ਪਾਲਜ਼ਮਾ ਸਕ੍ਰਿਪਟਿੰਗ ਪੋਪਅੱਪ ਐਪਲਿਟ
|
||||
Comment[pl]=Aplet Plazmy do skryptów
|
||||
Comment[pt]='Applet' de programação do Plasma
|
||||
Comment[pt_BR]=Miniaplicativo de script do Plasma
|
||||
Comment[ro]=Miniaplicație Plasma de indicii ale scripturilor
|
||||
Comment[ru]=Аплет программируемого контекстного окна Plasma
|
||||
Comment[se]=Plasma-skripten báhccanprográmmaš
|
||||
Comment[si]=ප්ලස්මා ස්ක්රිප්ට් පොප්-අප් යෙදුම්පත
|
||||
Comment[sk]=Skriptovací vyskakujúci Plasma aplet
|
||||
Comment[sl]=Plasma skriptni pojavni programček
|
||||
Comment[sr]=Плазма скриптовани искачући аплет
|
||||
Comment[sr@ijekavian]=Плазма скриптовани искачући аплет
|
||||
Comment[sr@ijekavianlatin]=Plasma skriptovani iskačući aplet
|
||||
Comment[sr@latin]=Plasma skriptovani iskačući aplet
|
||||
Comment[sv]=Plasmaskript-miniprogram
|
||||
Comment[ta]=பிளாஸ்மா scripting popup applet
|
||||
Comment[tg]=Барномаи скрипти пайдошавандаи Plasma
|
||||
Comment[th]=แอพเพล็ตผุดการใช้สคริปต์ของพลาสมา
|
||||
Comment[tr]=Plasma betik kullanan açılabilir gereci
|
||||
Comment[tt]=Plasma контекст тәрәзә өчен программалау кушымтасы
|
||||
Comment[ug]=Plasma قوليازماسىمان قاڭقىشچان قوللانچاق
|
||||
Comment[uk]=Аплет програмованого контекстного вікна Плазми
|
||||
Comment[wa]=Aplikete di scriptaedje d' aspitant purnea di Plasma
|
||||
Comment[x-test]=xxPlasma scripting popup appletxx
|
||||
Comment[zh_CN]=Plasma 脚本型弹出小程序
|
||||
Comment[zh_TW]=Plasma 文稿彈出小程式
|
||||
|
||||
|
864
dialog.cpp
864
dialog.cpp
@ -1,864 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008 by Alessandro Diaferia <alediaferia@gmail.com>
|
||||
* Copyright 2007 by Alexis Ménard <darktears31@gmail.com>
|
||||
* Copyright 2007 Sebastian Kuegler <sebas@kde.org>
|
||||
* Copyright 2006 Aaron Seigo <aseigo@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
|
||||
*/
|
||||
|
||||
#include "dialog.h"
|
||||
#include "private/dialog_p.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QSvgRenderer>
|
||||
#include <QResizeEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <QBitmap>
|
||||
#include <QTimer>
|
||||
#include <QVBoxLayout>
|
||||
#include <QGraphicsSceneEvent>
|
||||
#include <QGraphicsView>
|
||||
#include <QGraphicsWidget>
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
#include <QVarLengthArray>
|
||||
#include <QGraphicsLayout>
|
||||
|
||||
#include <kdebug.h>
|
||||
#include <kwindoweffects.h>
|
||||
#include <kwindowsystem.h>
|
||||
#include <netwm.h>
|
||||
|
||||
#include "plasma/applet.h"
|
||||
#include "plasma/animator.h"
|
||||
#include "plasma/containment.h"
|
||||
#include "plasma/corona.h"
|
||||
#include "plasma/framesvg.h"
|
||||
#include "plasma/theme.h"
|
||||
#include "plasma/widgets/scrollwidget.h"
|
||||
#include "plasma/private/windowshadows_p.h"
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
void DialogPrivate::scheduleBorderCheck(bool triggeredByResize)
|
||||
{
|
||||
//kDebug();
|
||||
if (triggeredByResize) {
|
||||
resizeChecksWithBorderCheck = true;
|
||||
|
||||
// to keep the UI as fluid as possible, we call checkBorders
|
||||
// immediately when there is a resize, and therefore stop any
|
||||
// move-triggered scheduled calls to it. this keeps things
|
||||
// looking reasonable during resize while avoiding as many
|
||||
// calls to checkBorders as possible
|
||||
if (moveTimer) {
|
||||
moveTimer->stop();
|
||||
}
|
||||
|
||||
checkBorders();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!moveTimer) {
|
||||
moveTimer = new QTimer(q);
|
||||
moveTimer->setSingleShot(true);
|
||||
QObject::connect(moveTimer, SIGNAL(timeout()), q, SLOT(checkBorders()));
|
||||
}
|
||||
|
||||
moveTimer->start(0);
|
||||
}
|
||||
|
||||
void DialogPrivate::themeChanged()
|
||||
{
|
||||
checkBorders(false);
|
||||
if (background->hasElement("shadow-top")) {
|
||||
WindowShadows::self()->addWindow(q);
|
||||
} else {
|
||||
WindowShadows::self()->removeWindow(q);
|
||||
}
|
||||
|
||||
const bool translucency = Plasma::Theme::defaultTheme()->windowTranslucencyEnabled();
|
||||
// WA_NoSystemBackground is going to fail combined with sliding popups, but is needed
|
||||
// when we aren't compositing
|
||||
q->setAttribute(Qt::WA_NoSystemBackground, !translucency);
|
||||
updateMask();
|
||||
q->update();
|
||||
}
|
||||
|
||||
void DialogPrivate::updateMask()
|
||||
{
|
||||
const bool translucency = Plasma::Theme::defaultTheme()->windowTranslucencyEnabled();
|
||||
KWindowEffects::enableBlurBehind(q->winId(), translucency,
|
||||
translucency ? background->mask() : QRegion());
|
||||
if (translucency) {
|
||||
q->clearMask();
|
||||
} else {
|
||||
q->setMask(background->mask());
|
||||
}
|
||||
}
|
||||
|
||||
void DialogPrivate::checkBorders()
|
||||
{
|
||||
checkBorders(true);
|
||||
}
|
||||
|
||||
void DialogPrivate::delayedAdjustSize()
|
||||
{
|
||||
q->syncToGraphicsWidget();
|
||||
}
|
||||
|
||||
void DialogPrivate::checkBorders(bool updateMaskIfNeeded)
|
||||
{
|
||||
if (resizeChecksWithBorderCheck) {
|
||||
background->resizeFrame(q->size());
|
||||
}
|
||||
|
||||
QGraphicsWidget *graphicsWidget = graphicsWidgetPtr.data();
|
||||
const FrameSvg::EnabledBorders currentBorders = background->enabledBorders();
|
||||
FrameSvg::EnabledBorders borders = FrameSvg::AllBorders;
|
||||
|
||||
Plasma::Applet *applet = appletPtr.data();
|
||||
|
||||
//used to remove borders at the edge of the desktop
|
||||
QRect avail;
|
||||
QRect screenGeom;
|
||||
QDesktopWidget *desktop = QApplication::desktop();
|
||||
Plasma::Corona *c = 0;
|
||||
if (applet) {
|
||||
c = qobject_cast<Plasma::Corona *>(applet->scene());
|
||||
} else if (graphicsWidget) {
|
||||
c = qobject_cast<Plasma::Corona *>(graphicsWidget->scene());
|
||||
}
|
||||
if (c) {
|
||||
QRegion r = c->availableScreenRegion(desktop->screenNumber(q));
|
||||
QRect maxRect;
|
||||
foreach (QRect rect, r.rects()) {
|
||||
if (rect.width() > maxRect.width() && rect.height() > maxRect.height()) {
|
||||
maxRect = rect;
|
||||
}
|
||||
}
|
||||
avail = maxRect;
|
||||
screenGeom = c->screenGeometry(desktop->screenNumber(q));
|
||||
} else {
|
||||
avail = desktop->availableGeometry(desktop->screenNumber(q));
|
||||
screenGeom = desktop->screenGeometry(desktop->screenNumber(q));
|
||||
}
|
||||
|
||||
QRect dialogGeom = q->geometry();
|
||||
|
||||
qreal topHeight(0);
|
||||
qreal leftWidth(0);
|
||||
qreal rightWidth(0);
|
||||
qreal bottomHeight(0);
|
||||
|
||||
//decide about disabling the border attached to the panel
|
||||
//don't cut borders on tooltips
|
||||
if (applet && !q->testAttribute(Qt::WA_X11NetWmWindowTypeToolTip)) {
|
||||
background->getMargins(leftWidth, topHeight, rightWidth, bottomHeight);
|
||||
|
||||
switch (applet->location()) {
|
||||
case BottomEdge:
|
||||
if (applet->containment() &&
|
||||
dialogGeom.bottom() + 2 >= screenGeom.bottom() - applet->containment()->size().height() &&
|
||||
dialogGeom.width() <= applet->containment()->size().width()) {
|
||||
borders &= ~FrameSvg::BottomBorder;
|
||||
leftWidth = 0;
|
||||
rightWidth = 0;
|
||||
bottomHeight = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case TopEdge:
|
||||
if (applet->containment() &&
|
||||
dialogGeom.top() <= screenGeom.top() + applet->containment()->size().height() &&
|
||||
dialogGeom.width() <= applet->containment()->size().width()) {
|
||||
borders &= ~FrameSvg::TopBorder;
|
||||
topHeight = 0;
|
||||
leftWidth = 0;
|
||||
rightWidth = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case LeftEdge:
|
||||
if (applet->containment() &&
|
||||
dialogGeom.left() <= screenGeom.left() + applet->containment()->size().width() &&
|
||||
dialogGeom.height() <= applet->containment()->size().height()) {
|
||||
borders &= ~FrameSvg::LeftBorder;
|
||||
leftWidth = 0;
|
||||
rightWidth = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case RightEdge:
|
||||
if (applet->containment() &&
|
||||
dialogGeom.right() + 2 >= screenGeom.right() - applet->containment()->size().width() &&
|
||||
dialogGeom.height() <= applet->containment()->size().height()) {
|
||||
borders &= ~FrameSvg::RightBorder;
|
||||
leftWidth = 0;
|
||||
rightWidth = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//decide if to disable the other borders
|
||||
if (q->isVisible() && !q->testAttribute(Qt::WA_X11NetWmWindowTypeToolTip)) {
|
||||
if (dialogGeom.left() <= avail.left()) {
|
||||
borders &= ~FrameSvg::LeftBorder;
|
||||
}
|
||||
if (dialogGeom.top() <= avail.top()) {
|
||||
borders &= ~FrameSvg::TopBorder;
|
||||
}
|
||||
//FIXME: that 2 pixels offset has probably something to do with kwin
|
||||
if (dialogGeom.right() + 2 > avail.right()) {
|
||||
borders &= ~FrameSvg::RightBorder;
|
||||
}
|
||||
if (dialogGeom.bottom() + 2 > avail.bottom()) {
|
||||
borders &= ~FrameSvg::BottomBorder;
|
||||
}
|
||||
}
|
||||
|
||||
background->setEnabledBorders(borders);
|
||||
background->getMargins(leftWidth, topHeight, rightWidth, bottomHeight);
|
||||
|
||||
//kDebug() << leftWidth << topHeight << rightWidth << bottomHeight;
|
||||
q->setContentsMargins(leftWidth, topHeight, rightWidth, bottomHeight);
|
||||
|
||||
if (resizeChecksWithBorderCheck) {
|
||||
updateResizeCorners();
|
||||
updateMask();
|
||||
q->update();
|
||||
} else if (currentBorders != borders) {
|
||||
if (updateMaskIfNeeded) {
|
||||
updateMask();
|
||||
}
|
||||
|
||||
q->update();
|
||||
}
|
||||
|
||||
resizeChecksWithBorderCheck = false;
|
||||
}
|
||||
|
||||
void Dialog::syncToGraphicsWidget()
|
||||
{
|
||||
d->adjustViewTimer->stop();
|
||||
QGraphicsWidget *graphicsWidget = d->graphicsWidgetPtr.data();
|
||||
if (d->view && graphicsWidget && d->resizeStartCorner != -1) {
|
||||
const int prevStartCorner = d->resizeStartCorner;
|
||||
d->resizeStartCorner = -1;
|
||||
QSize prevSize = size();
|
||||
/*
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "Widget size:" << graphicsWidget->size()
|
||||
#endif
|
||||
<< "| Widget size hint:" << graphicsWidget->effectiveSizeHint(Qt::PreferredSize)
|
||||
<< "| Widget minsize hint:" << graphicsWidget->minimumSize()
|
||||
<< "| Widget maxsize hint:" << graphicsWidget->maximumSize()
|
||||
<< "| Widget bounding rect:" << graphicsWidget->sceneBoundingRect();
|
||||
*/
|
||||
//set the sizehints correctly:
|
||||
int left, top, right, bottom;
|
||||
getContentsMargins(&left, &top, &right, &bottom);
|
||||
|
||||
QDesktopWidget *desktop = QApplication::desktop();
|
||||
QSize maxSize = desktop->availableGeometry(desktop->screenNumber(this)).size();
|
||||
|
||||
setMinimumSize(0, 0);
|
||||
setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
|
||||
|
||||
QSize newSize(qMin(int(graphicsWidget->size().width()) + left + right, maxSize.width()),
|
||||
qMin(int(graphicsWidget->size().height()) + top + bottom, maxSize.height()));
|
||||
|
||||
const QSizeF minimum = graphicsWidget->effectiveSizeHint(Qt::MinimumSize);
|
||||
QSize newMinimumSize(qMin(int(minimum.width()) + left + right, maxSize.width()),
|
||||
qMin(int(minimum.height()) + top + bottom, maxSize.height()));
|
||||
|
||||
|
||||
QSize newMaximumSize(qMin(int(graphicsWidget->maximumSize().width()) + left + right, maxSize.width()),
|
||||
qMin(int(graphicsWidget->maximumSize().height()) + top + bottom, maxSize.height()));
|
||||
|
||||
|
||||
Plasma::Applet *applet = d->appletPtr.data();
|
||||
if (applet) {
|
||||
QRect currentGeometry(geometry());
|
||||
currentGeometry.setSize(newSize);
|
||||
if (applet->location() == Plasma::TopEdge ||
|
||||
applet->location() == Plasma::LeftEdge) {
|
||||
currentGeometry.setSize(newSize);
|
||||
} else if (applet->location() == Plasma::RightEdge) {
|
||||
currentGeometry.moveTopRight(geometry().topRight());
|
||||
//BottomEdge and floating
|
||||
} else {
|
||||
currentGeometry.moveBottomLeft(geometry().bottomLeft());
|
||||
}
|
||||
setGeometry(currentGeometry);
|
||||
} else {
|
||||
resize(newSize);
|
||||
}
|
||||
|
||||
setMinimumSize(newMinimumSize);
|
||||
setMaximumSize(newMaximumSize);
|
||||
|
||||
|
||||
updateGeometry();
|
||||
|
||||
//reposition and resize the view.
|
||||
//force a valid rect, otherwise it will take up the whole scene
|
||||
QRectF sceneRect(graphicsWidget->sceneBoundingRect());
|
||||
|
||||
sceneRect.setWidth(qMax(qreal(1), sceneRect.width()));
|
||||
sceneRect.setHeight(qMax(qreal(1), sceneRect.height()));
|
||||
d->view->setSceneRect(sceneRect);
|
||||
|
||||
//d->view->resize(graphicsWidget->size().toSize());
|
||||
d->view->centerOn(graphicsWidget);
|
||||
|
||||
if (size() != prevSize) {
|
||||
//the size of the dialog has changed, emit the signal:
|
||||
emit dialogResized();
|
||||
}
|
||||
|
||||
d->resizeStartCorner = prevStartCorner;
|
||||
}
|
||||
}
|
||||
|
||||
int DialogPrivate::calculateWidthForHeightAndRatio(int height, qreal ratio)
|
||||
{
|
||||
switch (aspectRatioMode) {
|
||||
case KeepAspectRatio:
|
||||
return qRound(height * ratio);
|
||||
break;
|
||||
case Square:
|
||||
return height;
|
||||
break;
|
||||
case ConstrainedSquare:
|
||||
return height;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
Dialog::Dialog(QWidget *parent, Qt::WindowFlags f)
|
||||
: QWidget(parent, f | Qt::FramelessWindowHint),
|
||||
d(new DialogPrivate(this))
|
||||
{
|
||||
setMouseTracking(true);
|
||||
setAttribute(Qt::WA_TranslucentBackground);
|
||||
d->background = new FrameSvg(this);
|
||||
d->background->setImagePath("dialogs/background");
|
||||
d->background->setEnabledBorders(FrameSvg::AllBorders);
|
||||
d->background->resizeFrame(size());
|
||||
connect(d->background, SIGNAL(repaintNeeded()), this, SLOT(themeChanged()));
|
||||
|
||||
QPalette pal = palette();
|
||||
pal.setColor(backgroundRole(), Qt::transparent);
|
||||
setPalette(pal);
|
||||
KWindowEffects::overrideShadow(winId(), true);
|
||||
|
||||
d->adjustViewTimer = new QTimer(this);
|
||||
d->adjustViewTimer->setSingleShot(true);
|
||||
connect(d->adjustViewTimer, SIGNAL(timeout()), this, SLOT(syncToGraphicsWidget()));
|
||||
|
||||
d->adjustSizeTimer = new QTimer(this);
|
||||
d->adjustSizeTimer->setSingleShot(true);
|
||||
connect(d->adjustSizeTimer, SIGNAL(timeout()), this, SLOT(delayedAdjustSize()));
|
||||
|
||||
d->themeChanged();
|
||||
}
|
||||
|
||||
Dialog::~Dialog()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
void Dialog::paintEvent(QPaintEvent *e)
|
||||
{
|
||||
QPainter p(this);
|
||||
p.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
d->background->paintFrame(&p, e->rect(), e->rect());
|
||||
}
|
||||
|
||||
void Dialog::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
if (event->modifiers() == Qt::AltModifier) {
|
||||
unsetCursor();
|
||||
} else if (d->resizeAreas[Dialog::NorthEast].contains(event->pos())) {
|
||||
setCursor(Qt::SizeBDiagCursor);
|
||||
} else if (d->resizeAreas[Dialog::NorthWest].contains(event->pos())) {
|
||||
setCursor(Qt::SizeFDiagCursor);
|
||||
} else if (d->resizeAreas[Dialog::SouthEast].contains(event->pos())) {
|
||||
setCursor(Qt::SizeFDiagCursor);
|
||||
} else if (d->resizeAreas[Dialog::SouthWest].contains(event->pos())) {
|
||||
setCursor(Qt::SizeBDiagCursor);
|
||||
} else if (!(event->buttons() & Qt::LeftButton)) {
|
||||
unsetCursor();
|
||||
}
|
||||
|
||||
// here we take care of resize..
|
||||
if (d->resizeStartCorner != Dialog::NoCorner) {
|
||||
int newWidth;
|
||||
int newHeight;
|
||||
QPoint position;
|
||||
|
||||
qreal aspectRatio = (qreal)width() / (qreal)height();
|
||||
|
||||
switch(d->resizeStartCorner) {
|
||||
case Dialog::NorthEast:
|
||||
newHeight = qMin(maximumHeight(), qMax(minimumHeight(), height() - event->y()));
|
||||
newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
|
||||
if (newWidth == -1) {
|
||||
newWidth = qMin(maximumWidth(), qMax(minimumWidth(), event->x()));
|
||||
}
|
||||
position = QPoint(x(), y() + height() - newHeight);
|
||||
break;
|
||||
case Dialog::NorthWest:
|
||||
newHeight = qMin(maximumHeight(), qMax(minimumHeight(), height() - event->y()));
|
||||
newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
|
||||
if (newWidth == -1) {
|
||||
newWidth = qMin(maximumWidth(), qMax(minimumWidth(), width() - event->x()));
|
||||
}
|
||||
position = QPoint(x() + width() - newWidth, y() + height() - newHeight);
|
||||
break;
|
||||
case Dialog::SouthWest:
|
||||
newHeight = qMin(maximumHeight(), qMax(minimumHeight(), event->y()));
|
||||
newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
|
||||
if (newWidth == -1) {
|
||||
newWidth = qMin(maximumWidth(), qMax(minimumWidth(), width() - event->x()));
|
||||
}
|
||||
position = QPoint(x() + width() - newWidth, y());
|
||||
break;
|
||||
case Dialog::SouthEast:
|
||||
newHeight = qMin(maximumHeight(), qMax(minimumHeight(), event->y()));
|
||||
newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
|
||||
if (newWidth == -1) {
|
||||
newWidth = qMin(maximumWidth(), qMax(minimumWidth(), event->x()));
|
||||
}
|
||||
position = QPoint(x(), y());
|
||||
break;
|
||||
default:
|
||||
newHeight = qMin(maximumHeight(), qMax(minimumHeight(), height()));
|
||||
newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
|
||||
if (newWidth == -1) {
|
||||
newWidth = qMin(maximumWidth(), qMax(minimumWidth(), width()));
|
||||
}
|
||||
position = QPoint(x(), y());
|
||||
break;
|
||||
}
|
||||
|
||||
QRect newGeom(position, QSize(newWidth, newHeight));
|
||||
|
||||
// now sanity check the resize results again min constraints, if any
|
||||
if (d->leftResizeMin > -1 && newGeom.left() > d->leftResizeMin) {
|
||||
newGeom.setLeft(d->leftResizeMin);
|
||||
}
|
||||
|
||||
if (d->topResizeMin > -1 && newGeom.top() > d->topResizeMin) {
|
||||
newGeom.setTop(d->topResizeMin);
|
||||
}
|
||||
|
||||
if (d->rightResizeMin > -1 && newGeom.right() < d->rightResizeMin) {
|
||||
newGeom.setRight(d->rightResizeMin);
|
||||
}
|
||||
|
||||
if (d->bottomResizeMin > -1 && newGeom.bottom() < d->bottomResizeMin) {
|
||||
newGeom.setBottom(d->bottomResizeMin);
|
||||
}
|
||||
|
||||
if ((newGeom.width() >= minimumSize().width()) && (newGeom.height() >= minimumSize().height())) {
|
||||
setGeometry(newGeom);
|
||||
}
|
||||
}
|
||||
|
||||
QWidget::mouseMoveEvent(event);
|
||||
}
|
||||
|
||||
void Dialog::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
if (d->resizeAreas[Dialog::NorthEast].contains(event->pos())) {
|
||||
d->resizeStartCorner = Dialog::NorthEast;
|
||||
} else if (d->resizeAreas[Dialog::NorthWest].contains(event->pos())) {
|
||||
d->resizeStartCorner = Dialog::NorthWest;
|
||||
} else if (d->resizeAreas[Dialog::SouthEast].contains(event->pos())) {
|
||||
d->resizeStartCorner = Dialog::SouthEast;
|
||||
} else if (d->resizeAreas[Dialog::SouthWest].contains(event->pos())) {
|
||||
d->resizeStartCorner = Dialog::SouthWest;
|
||||
} else {
|
||||
d->resizeStartCorner = Dialog::NoCorner;
|
||||
}
|
||||
|
||||
QWidget::mousePressEvent(event);
|
||||
}
|
||||
|
||||
void Dialog::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
if (d->resizeStartCorner != Dialog::NoCorner) {
|
||||
emit dialogResized();
|
||||
d->resizeStartCorner = Dialog::NoCorner;
|
||||
unsetCursor();
|
||||
}
|
||||
|
||||
QWidget::mouseReleaseEvent(event);
|
||||
}
|
||||
|
||||
void Dialog::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
if (event->key() == Qt::Key_Escape) {
|
||||
hide();
|
||||
}
|
||||
}
|
||||
|
||||
bool Dialog::event(QEvent *event)
|
||||
{
|
||||
return QWidget::event(event);
|
||||
}
|
||||
|
||||
void Dialog::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
//kDebug();
|
||||
d->scheduleBorderCheck(true);
|
||||
|
||||
if (d->resizeStartCorner != -1 && d->view && d->graphicsWidgetPtr) {
|
||||
QGraphicsWidget *graphicsWidget = d->graphicsWidgetPtr.data();
|
||||
graphicsWidget->resize(d->view->size());
|
||||
|
||||
QRectF sceneRect(graphicsWidget->sceneBoundingRect());
|
||||
sceneRect.setWidth(qMax(qreal(1), sceneRect.width()));
|
||||
sceneRect.setHeight(qMax(qreal(1), sceneRect.height()));
|
||||
d->view->setSceneRect(sceneRect);
|
||||
d->view->centerOn(graphicsWidget);
|
||||
}
|
||||
}
|
||||
|
||||
void DialogPrivate::updateResizeCorners()
|
||||
{
|
||||
const int resizeAreaMargin = 20;
|
||||
const QRect r = q->rect();
|
||||
const FrameSvg::EnabledBorders borders = background->enabledBorders();
|
||||
|
||||
// IMPLEMENTATION NOTE: we set resize corners for the corners set, but also
|
||||
// for the complimentary corners if we've cut out an edge of our SVG background
|
||||
// which implies we are up against an immovable edge (e.g. a screen edge)
|
||||
|
||||
resizeAreas.clear();
|
||||
if (resizeCorners & Dialog::NorthEast ||
|
||||
(resizeCorners & Dialog::NorthWest && !(borders & FrameSvg::LeftBorder)) ||
|
||||
(resizeCorners & Dialog::SouthEast && !(borders & FrameSvg::BottomBorder))) {
|
||||
resizeAreas[Dialog::NorthEast] = QRect(r.right() - resizeAreaMargin, 0,
|
||||
resizeAreaMargin, resizeAreaMargin);
|
||||
}
|
||||
|
||||
if (resizeCorners & Dialog::NorthWest ||
|
||||
(resizeCorners & Dialog::NorthEast && !(borders & FrameSvg::RightBorder)) ||
|
||||
(resizeCorners & Dialog::SouthWest && !(borders & FrameSvg::BottomBorder))) {
|
||||
resizeAreas[Dialog::NorthWest] = QRect(0, 0, resizeAreaMargin, resizeAreaMargin);
|
||||
}
|
||||
|
||||
if (resizeCorners & Dialog::SouthEast ||
|
||||
(resizeCorners & Dialog::SouthWest && !(borders & FrameSvg::LeftBorder)) ||
|
||||
(resizeCorners & Dialog::NorthEast && !(borders & FrameSvg::TopBorder))) {
|
||||
resizeAreas[Dialog::SouthEast] = QRect(r.right() - resizeAreaMargin,
|
||||
r.bottom() - resizeAreaMargin,
|
||||
resizeAreaMargin, resizeAreaMargin);
|
||||
}
|
||||
|
||||
if (resizeCorners & Dialog::SouthWest ||
|
||||
(resizeCorners & Dialog::SouthEast && !(borders & FrameSvg::RightBorder)) ||
|
||||
(resizeCorners & Dialog::NorthWest && !(borders & FrameSvg::TopBorder))) {
|
||||
resizeAreas[Dialog::SouthWest] = QRect(0, r.bottom() - resizeAreaMargin,
|
||||
resizeAreaMargin, resizeAreaMargin);
|
||||
}
|
||||
}
|
||||
|
||||
void Dialog::setGraphicsWidget(QGraphicsWidget *widget)
|
||||
{
|
||||
if (d->graphicsWidgetPtr) {
|
||||
d->graphicsWidgetPtr.data()->removeEventFilter(this);
|
||||
}
|
||||
|
||||
d->graphicsWidgetPtr = widget;
|
||||
|
||||
if (widget) {
|
||||
Plasma::Corona *c = qobject_cast<Plasma::Corona *>(widget->scene());
|
||||
if (c) {
|
||||
c->addOffscreenWidget(widget);
|
||||
}
|
||||
|
||||
if (!layout()) {
|
||||
QVBoxLayout *lay = new QVBoxLayout(this);
|
||||
lay->setMargin(0);
|
||||
lay->setSpacing(0);
|
||||
}
|
||||
|
||||
d->checkBorders();
|
||||
|
||||
if (!d->view) {
|
||||
d->view = new QGraphicsView(this);
|
||||
d->view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
d->view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
d->view->setFrameShape(QFrame::NoFrame);
|
||||
d->view->viewport()->setAutoFillBackground(false);
|
||||
layout()->addWidget(d->view);
|
||||
}
|
||||
|
||||
d->view->setScene(widget->scene());
|
||||
|
||||
//try to have the proper size -before- showing the dialog
|
||||
d->view->centerOn(widget);
|
||||
if (widget->layout()) {
|
||||
widget->layout()->activate();
|
||||
}
|
||||
static_cast<QGraphicsLayoutItem *>(widget)->updateGeometry();
|
||||
widget->resize(widget->size().expandedTo(widget->effectiveSizeHint(Qt::MinimumSize)));
|
||||
|
||||
syncToGraphicsWidget();
|
||||
|
||||
//d->adjustSizeTimer->start(150);
|
||||
|
||||
widget->installEventFilter(this);
|
||||
d->view->installEventFilter(this);
|
||||
} else {
|
||||
delete d->view;
|
||||
d->view = 0;
|
||||
}
|
||||
}
|
||||
|
||||
QGraphicsWidget *Dialog::graphicsWidget() const
|
||||
{
|
||||
return d->graphicsWidgetPtr.data();
|
||||
}
|
||||
|
||||
bool Dialog::eventFilter(QObject *watched, QEvent *event)
|
||||
{
|
||||
if (d->resizeStartCorner == Dialog::NoCorner && watched == d->graphicsWidgetPtr.data() &&
|
||||
(event->type() == QEvent::GraphicsSceneResize || event->type() == QEvent::GraphicsSceneMove)) {
|
||||
d->adjustViewTimer->start(150);
|
||||
}
|
||||
|
||||
// when moving the cursor with a 45° angle from the outside
|
||||
// to the inside passing over a resize angle the cursor changes its
|
||||
// shape to a resize cursor. As a side effect this is the only case
|
||||
// when the cursor immediately enters the view without giving
|
||||
// the dialog the chance to restore the original cursor shape.
|
||||
if (event->type() == QEvent::Enter && watched == d->view) {
|
||||
unsetCursor();
|
||||
}
|
||||
|
||||
return QWidget::eventFilter(watched, event);
|
||||
}
|
||||
|
||||
void Dialog::hideEvent(QHideEvent * event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
emit dialogVisible(false);
|
||||
}
|
||||
|
||||
void Dialog::showEvent(QShowEvent * event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
|
||||
//check if the widget size is still synced with the view
|
||||
d->checkBorders();
|
||||
d->updateResizeCorners();
|
||||
|
||||
QGraphicsWidget *graphicsWidget = d->graphicsWidgetPtr.data();
|
||||
if (graphicsWidget &&
|
||||
((d->view && graphicsWidget->size().toSize() != d->view->size()) ||
|
||||
d->oldGraphicsWidgetMinimumSize != graphicsWidget->minimumSize() ||
|
||||
d->oldGraphicsWidgetMaximumSize != graphicsWidget->maximumSize())) {
|
||||
//here have to be done immediately, ideally should have to be done -before- shwing, but is not possible to catch show() so early
|
||||
syncToGraphicsWidget();
|
||||
d->oldGraphicsWidgetMinimumSize = graphicsWidget->minimumSize().toSize();
|
||||
d->oldGraphicsWidgetMaximumSize = graphicsWidget->maximumSize().toSize();
|
||||
}
|
||||
|
||||
if (d->view) {
|
||||
d->view->setFocus();
|
||||
}
|
||||
|
||||
if (graphicsWidget) {
|
||||
graphicsWidget->setFocus();
|
||||
}
|
||||
|
||||
emit dialogVisible(true);
|
||||
KWindowEffects::overrideShadow(winId(), true);
|
||||
}
|
||||
|
||||
void Dialog::focusInEvent(QFocusEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
|
||||
if (d->view) {
|
||||
d->view->setFocus();
|
||||
}
|
||||
|
||||
QGraphicsWidget *graphicsWidget = d->graphicsWidgetPtr.data();
|
||||
if (graphicsWidget) {
|
||||
graphicsWidget->setFocus();
|
||||
}
|
||||
}
|
||||
|
||||
void Dialog::moveEvent(QMoveEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
//kDebug();
|
||||
d->scheduleBorderCheck();
|
||||
}
|
||||
|
||||
void Dialog::setResizeHandleCorners(ResizeCorners corners)
|
||||
{
|
||||
if ((d->resizeCorners != corners) && (aspectRatioMode() != FixedSize)) {
|
||||
d->resizeCorners = corners;
|
||||
d->updateResizeCorners();
|
||||
}
|
||||
}
|
||||
|
||||
Dialog::ResizeCorners Dialog::resizeCorners() const
|
||||
{
|
||||
return d->resizeCorners;
|
||||
}
|
||||
|
||||
bool Dialog::isUserResizing() const
|
||||
{
|
||||
return d->resizeStartCorner > NoCorner;
|
||||
}
|
||||
|
||||
void Dialog::setMinimumResizeLimits(int left, int top, int right, int bottom)
|
||||
{
|
||||
d->leftResizeMin = left;
|
||||
d->topResizeMin = top;
|
||||
d->rightResizeMin = right;
|
||||
d->bottomResizeMin = bottom;
|
||||
}
|
||||
|
||||
void Dialog::getMinimumResizeLimits(int *left, int *top, int *right, int *bottom)
|
||||
{
|
||||
if (left) {
|
||||
*left = d->leftResizeMin;
|
||||
}
|
||||
|
||||
if (top) {
|
||||
*top = d->topResizeMin;
|
||||
}
|
||||
|
||||
if (right) {
|
||||
*right = d->rightResizeMin;
|
||||
}
|
||||
|
||||
if (bottom) {
|
||||
*bottom = d->bottomResizeMin;
|
||||
}
|
||||
}
|
||||
|
||||
void Dialog::animatedHide(Plasma::Direction direction)
|
||||
{
|
||||
if (!isVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Plasma::Theme::defaultTheme()->windowTranslucencyEnabled()) {
|
||||
hide();
|
||||
return;
|
||||
}
|
||||
|
||||
KWindowEffects::SlideFromLocation location = KWindowEffects::NoEdge;
|
||||
switch (direction) {
|
||||
case Down:
|
||||
location = KWindowEffects::BottomEdge;
|
||||
break;
|
||||
case Right:
|
||||
location = KWindowEffects::RightEdge;
|
||||
break;
|
||||
case Left:
|
||||
location = KWindowEffects::LeftEdge;
|
||||
break;
|
||||
case Up:
|
||||
location = KWindowEffects::TopEdge;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
KWindowEffects::slideWindow(this, location);
|
||||
hide();
|
||||
}
|
||||
|
||||
void Dialog::animatedShow(Plasma::Direction direction)
|
||||
{
|
||||
if (!Plasma::Theme::defaultTheme()->windowTranslucencyEnabled()) {
|
||||
show();
|
||||
return;
|
||||
}
|
||||
|
||||
//copied to not add new api
|
||||
KWindowEffects::SlideFromLocation location = KWindowEffects::NoEdge;
|
||||
switch (direction) {
|
||||
case Up:
|
||||
location = KWindowEffects::BottomEdge;
|
||||
break;
|
||||
case Left:
|
||||
location = KWindowEffects::RightEdge;
|
||||
break;
|
||||
case Right:
|
||||
location = KWindowEffects::LeftEdge;
|
||||
break;
|
||||
case Down:
|
||||
location = KWindowEffects::TopEdge;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (Plasma::Theme::defaultTheme()->windowTranslucencyEnabled()) {
|
||||
KWindowEffects::slideWindow(this, location);
|
||||
}
|
||||
|
||||
show();
|
||||
}
|
||||
|
||||
bool Dialog::inControlArea(const QPoint &point)
|
||||
{
|
||||
foreach (const QRect &r, d->resizeAreas) {
|
||||
if (r.contains(point)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Plasma::AspectRatioMode Dialog::aspectRatioMode() const
|
||||
{
|
||||
return d->aspectRatioMode;
|
||||
}
|
||||
|
||||
void Dialog::setAspectRatioMode(Plasma::AspectRatioMode mode)
|
||||
{
|
||||
if (mode == FixedSize) {
|
||||
setResizeHandleCorners(NoCorner);
|
||||
}
|
||||
|
||||
d->aspectRatioMode = mode;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "moc_dialog.cpp"
|
215
dialog.h
215
dialog.h
@ -1,215 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008 by Alessandro Diaferia <alediaferia@gmail.com>
|
||||
* Copyright 2007 by Alexis Ménard <darktears31@gmail.com>
|
||||
* Copyright 2007 Sebastian Kuegler <sebas@kde.org>
|
||||
* Copyright 2006 Aaron Seigo <aseigo@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 PLASMA_DIALOG_H
|
||||
#define PLASMA_DIALOG_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QGraphicsSceneEvent>
|
||||
#include <QGraphicsView>
|
||||
|
||||
#include <plasma/plasma_export.h>
|
||||
#include <plasma/plasma.h>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class DialogPrivate;
|
||||
|
||||
/**
|
||||
* @class Dialog plasma/dialog.h <Plasma/Dialog>
|
||||
*
|
||||
* @short A dialog that uses the Plasma style
|
||||
*
|
||||
* Dialog provides a dialog-like widget that can be used to display additional
|
||||
* information.
|
||||
*
|
||||
* Dialog uses the plasma theme, and usually has no window decoration. It's meant
|
||||
* as an interim solution to display widgets as extension to plasma applets, for
|
||||
* example when you click on an applet like the devicenotifier or the clock, the
|
||||
* widget that is then displayed, is a Dialog.
|
||||
*/
|
||||
class PLASMA_EXPORT Dialog : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* Use these flags to choose the active resize corners.
|
||||
*/
|
||||
enum ResizeCorner {
|
||||
NoCorner = 0,
|
||||
NorthEast = 1,
|
||||
SouthEast = 2,
|
||||
NorthWest = 4,
|
||||
SouthWest = 8,
|
||||
All = NorthEast | SouthEast | NorthWest | SouthWest
|
||||
};
|
||||
Q_DECLARE_FLAGS(ResizeCorners, ResizeCorner)
|
||||
|
||||
/**
|
||||
* @param parent the parent widget, for plasmoids, this is usually 0.
|
||||
* @param f the Qt::WindowFlags, default is to not show a windowborder.
|
||||
*/
|
||||
explicit Dialog(QWidget * parent = 0, Qt::WindowFlags f = Qt::Window);
|
||||
virtual ~Dialog();
|
||||
|
||||
/**
|
||||
* Sets a QGraphicsWidget to be shown as the content in this dialog.
|
||||
* The dialog will then set up a QGraphicsView and coordinate geometry with
|
||||
* the widget automatically.
|
||||
*
|
||||
* @param widget the QGraphicsWidget to display in this dialog
|
||||
*/
|
||||
void setGraphicsWidget(QGraphicsWidget *widget);
|
||||
|
||||
/**
|
||||
* @return the graphics widget shown in this dialog
|
||||
*/
|
||||
QGraphicsWidget *graphicsWidget() const;
|
||||
|
||||
/**
|
||||
* @param corners the corners the resize handlers should be placed in.
|
||||
*/
|
||||
void setResizeHandleCorners(ResizeCorners corners);
|
||||
|
||||
/**
|
||||
* Convenience method to get the enabled resize corners.
|
||||
* @return which resize corners are active.
|
||||
*/
|
||||
ResizeCorners resizeCorners() const;
|
||||
|
||||
/**
|
||||
* @return true if currently being resized by the user
|
||||
*/
|
||||
bool isUserResizing() const;
|
||||
|
||||
/**
|
||||
* Sets the minimum values that each of four sides of the rect may expand to or from
|
||||
*
|
||||
* @param left the screen coordinate that the left may not go beyond; -1 for no limit
|
||||
* @param top the screen coordinate that the top may not go beyond; -1 for no limit
|
||||
* @param right the screen coordinate that the right may not go beyond; -1 for no limit
|
||||
* @param bottom the screen coordinate that the bottom may not go beyond; -1 for no limit
|
||||
*/
|
||||
void setMinimumResizeLimits(int left, int top, int right, int bottom);
|
||||
|
||||
/**
|
||||
* Retrives the minimum resize limits for the dialog
|
||||
*
|
||||
* @param left the screen coordinate that the left may not go beyond; -1 for no limit
|
||||
* @param top the screen coordinate that the top may not go beyond; -1 for no limit
|
||||
* @param right the screen coordinate that the right may not go beyond; -1 for no limit
|
||||
* @param bottom the screen coordinate that the bottom may not go beyond; -1 for no limit
|
||||
*/
|
||||
void getMinimumResizeLimits(int *left, int *top, int *right, int *bottom);
|
||||
|
||||
/**
|
||||
* Causes an animated hide; requires compositing to work, otherwise
|
||||
* the dialog will simply hide.
|
||||
* @since 4.3
|
||||
*/
|
||||
void animatedHide(Plasma::Direction direction);
|
||||
|
||||
/**
|
||||
* Causes an animated show; requires compositing to work, otherwise
|
||||
* the dialog will simply show.
|
||||
* @since 4.3
|
||||
*/
|
||||
void animatedShow(Plasma::Direction direction);
|
||||
|
||||
/**
|
||||
* @return the preferred aspect ratio mode for placement and resizing
|
||||
* @since 4.4
|
||||
*/
|
||||
Plasma::AspectRatioMode aspectRatioMode() const;
|
||||
|
||||
/**
|
||||
* Sets the preferred aspect ratio mode for placement and resizing
|
||||
* @since 4.4
|
||||
*/
|
||||
void setAspectRatioMode(Plasma::AspectRatioMode mode);
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
* Fires when the dialog automatically resizes.
|
||||
*/
|
||||
void dialogResized();
|
||||
|
||||
/**
|
||||
* Emit a signal when the dialog become visible/invisible
|
||||
*/
|
||||
void dialogVisible(bool status);
|
||||
|
||||
public Q_SLOTS:
|
||||
/**
|
||||
* Adjusts the dialog to the associated QGraphicsWidget's geometry
|
||||
* Should not normally need to be called by users of Dialog as Dialog
|
||||
* does it automatically. Event compression may cause unwanted delays,
|
||||
* however, and so this method may be called to immediately cause a
|
||||
* synchronization.
|
||||
* @since 4.5
|
||||
*/
|
||||
void syncToGraphicsWidget();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Reimplemented from QWidget
|
||||
*/
|
||||
void paintEvent(QPaintEvent *e);
|
||||
bool event(QEvent *event);
|
||||
void resizeEvent(QResizeEvent *e);
|
||||
bool eventFilter(QObject *watched, QEvent *event);
|
||||
void hideEvent(QHideEvent *event);
|
||||
void showEvent(QShowEvent *event);
|
||||
void focusInEvent(QFocusEvent *event);
|
||||
void mouseMoveEvent(QMouseEvent *event);
|
||||
void mousePressEvent(QMouseEvent *event);
|
||||
void mouseReleaseEvent(QMouseEvent *event);
|
||||
void keyPressEvent(QKeyEvent *event);
|
||||
void moveEvent(QMoveEvent *event);
|
||||
|
||||
/**
|
||||
* Convenience method to know whether the point is in a control area (e.g. resize area)
|
||||
* or not.
|
||||
* @return true if the point is in the control area.
|
||||
*/
|
||||
bool inControlArea(const QPoint &point);
|
||||
|
||||
private:
|
||||
DialogPrivate *const d;
|
||||
|
||||
friend class DialogPrivate;
|
||||
/**
|
||||
* React to theme changes
|
||||
*/
|
||||
Q_PRIVATE_SLOT(d, void themeChanged())
|
||||
Q_PRIVATE_SLOT(d, void checkBorders())
|
||||
Q_PRIVATE_SLOT(d, void delayedAdjustSize())
|
||||
|
||||
friend class PopupAppletPrivate;
|
||||
};
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(Plasma::Dialog::ResizeCorners)
|
||||
|
||||
#endif
|
896
popupapplet.cpp
896
popupapplet.cpp
@ -1,896 +0,0 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
#include <kiconloader.h>
|
||||
#include <kwindowsystem.h>
|
||||
#include <kglobalsettings.h>
|
||||
#include <netwm.h>
|
||||
|
||||
#include "plasma/private/applet_p.h"
|
||||
#include "plasma/corona.h"
|
||||
#include "plasma/containment.h"
|
||||
#include "plasma/private/containment_p.h"
|
||||
#include "plasma/dialog.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)
|
||||
: Applet(parent, args),
|
||||
d(new PopupAppletPrivate(this))
|
||||
{
|
||||
}
|
||||
|
||||
PopupApplet::PopupApplet(const QString &packagePath, uint appletId, const QVariantList &args)
|
||||
: 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);
|
||||
d->popupConstraintsEvent(FormFactorConstraint);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
d->createIconWidget();
|
||||
d->icon->setIcon(icon);
|
||||
}
|
||||
|
||||
void PopupApplet::setPopupIcon(const QString &iconName)
|
||||
{
|
||||
// Attempt 1: is it in the plasmoid package?
|
||||
if (package().isValid()) {
|
||||
const QString file = package().filePath("images", iconName);
|
||||
if (!file.isEmpty()) {
|
||||
setPopupIcon(KDE::icon(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(KDE::icon(iconName));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Final Attempt: use KDE::icon
|
||||
setPopupIcon(KDE::icon(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()
|
||||
{
|
||||
return d->graphicsWidget.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::popupConstraintsEvent(Plasma::Constraints constraints)
|
||||
{
|
||||
Plasma::FormFactor f = q->formFactor();
|
||||
|
||||
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());
|
||||
} 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() < QApplication::startDragDistance()) {
|
||||
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);
|
||||
}
|
||||
|
||||
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 (!graphicsWidget) {
|
||||
// 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);
|
||||
showDialogTimer.start(0, q);
|
||||
}
|
||||
}
|
||||
|
||||
void PopupAppletPrivate::showDialog()
|
||||
{
|
||||
Plasma::Dialog *dialog = dialogPtr.data();
|
||||
if (!dialog) {
|
||||
return;
|
||||
}
|
||||
|
||||
updateDialogPosition();
|
||||
|
||||
KWindowSystem::setOnAllDesktops(dialog->winId(), true);
|
||||
KWindowSystem::setState(dialog->winId(), NET::SkipTaskbar | NET::SkipPager);
|
||||
|
||||
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(!dialog->isUserResizing());
|
||||
|
||||
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(bool move)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
const QPoint appletPos = view->mapToGlobal(view->mapFromScene(q->scenePos()));
|
||||
|
||||
QPoint dialogPos = dialog->pos();
|
||||
if (move) {
|
||||
if (!q->containment() || view == q->containment()->view()) {
|
||||
dialogPos = corona->popupPosition(q, dialog->size(), popupAlignment);
|
||||
} else {
|
||||
dialogPos = corona->popupPosition(q->parentItem(), dialog->size(), popupAlignment);
|
||||
}
|
||||
}
|
||||
|
||||
bool reverse = false;
|
||||
if (q->formFactor() == Plasma::Vertical) {
|
||||
reverse = (appletPos.y() + (q->size().height() / 2)) < (dialogPos.y() + (dialog->size().height() / 2));
|
||||
dialog->setMinimumResizeLimits(-1, appletPos.y(), -1, appletPos.y() + q->size().height());
|
||||
} else {
|
||||
reverse = (appletPos.x() + (q->size().width() / 2)) < (dialogPos.x() + (dialog->size().width() / 2));
|
||||
dialog->setMinimumResizeLimits(appletPos.x(), -1, appletPos.x() + q->size().width(), -1);
|
||||
}
|
||||
|
||||
Dialog::ResizeCorners resizeCorners = Dialog::NoCorner;
|
||||
switch (q->location()) {
|
||||
case BottomEdge:
|
||||
resizeCorners = Dialog::NorthEast | Dialog::NorthWest;
|
||||
popupPlacement = reverse ? TopPosedLeftAlignedPopup : TopPosedRightAlignedPopup;
|
||||
break;
|
||||
case TopEdge:
|
||||
resizeCorners = Dialog::SouthEast | Dialog::SouthWest;
|
||||
popupPlacement = reverse ? Plasma::BottomPosedLeftAlignedPopup : Plasma::BottomPosedRightAlignedPopup;
|
||||
break;
|
||||
case LeftEdge:
|
||||
resizeCorners = Dialog::SouthEast | Dialog::NorthEast;
|
||||
popupPlacement = reverse ? RightPosedTopAlignedPopup : RightPosedBottomAlignedPopup;
|
||||
break;
|
||||
|
||||
case RightEdge:
|
||||
resizeCorners = Dialog::SouthWest | Dialog::NorthWest;
|
||||
popupPlacement = reverse ? LeftPosedTopAlignedPopup : LeftPosedBottomAlignedPopup;
|
||||
break;
|
||||
|
||||
default:
|
||||
popupPlacement = FloatingPopup;
|
||||
resizeCorners = Dialog::All;
|
||||
break;
|
||||
}
|
||||
|
||||
dialog->setResizeHandleCorners(resizeCorners);
|
||||
if (move) {
|
||||
dialog->move(dialogPos);
|
||||
}
|
||||
}
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
|
||||
|
||||
#include "moc_popupapplet.cpp"
|
221
popupapplet.h
221
popupapplet.h
@ -1,221 +0,0 @@
|
||||
/*
|
||||
* 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 PLASMA_POPUPAPPLET_H
|
||||
#define PLASMA_POPUPAPPLET_H
|
||||
|
||||
#include <plasma/applet.h>
|
||||
#include <plasma/plasma_export.h>
|
||||
#include <plasma/plasma.h>
|
||||
|
||||
class QGraphicsProxyWidget;
|
||||
class QGraphicsLinearLayout;
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class PopupAppletPrivate;
|
||||
|
||||
/**
|
||||
* Allows applets to automatically 'collapse' into an icon when put in an panel.
|
||||
*
|
||||
* Applets that subclass this class should implement either widget() or graphicsWidget() to return a
|
||||
* widget that will be displayed in the applet if the applet is in a Planar or MediaCenter form
|
||||
* factor. If the applet is put in a panel, an icon will be displayed instead, which shows the
|
||||
* widget in a popup when clicked.
|
||||
*/
|
||||
|
||||
class PLASMA_EXPORT PopupApplet : public Plasma::Applet
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(Qt::AlignmentFlag popupAlignment READ popupAlignment WRITE setPopupAlignment)
|
||||
|
||||
public:
|
||||
PopupApplet(QObject *parent, const QVariantList &args);
|
||||
~PopupApplet();
|
||||
|
||||
/**
|
||||
* @param icon the icon that has to be displayed when the applet is in a panel.
|
||||
* Passing in a null icon means that the popup applet itself
|
||||
* will provide an interface for when the PopupApplet is not showing
|
||||
* the widget() or graphicsWidget() directly.
|
||||
*/
|
||||
void setPopupIcon(const QIcon &icon);
|
||||
|
||||
/**
|
||||
* @param icon the icon that has to be displayed when the applet is in a panel.
|
||||
* Passing in an empty QString() means that the popup applet itself
|
||||
* will provide an interface for when the PopupApplet is not showing
|
||||
* the widget() or graphicsWidget() directly.
|
||||
|
||||
* If you set a popup icon you must also set a minimum size of the applet. When the applet
|
||||
* is smaller than this minimum size, it will be displayed as that icon.
|
||||
*/
|
||||
void setPopupIcon(const QString &iconName);
|
||||
|
||||
/**
|
||||
* @return the icon that is displayed when the applet is in a panel.
|
||||
*/
|
||||
QIcon popupIcon() const;
|
||||
|
||||
/**
|
||||
* Implement either this function or graphicsWidget().
|
||||
* @return the widget that will get shown in either a layout, in the applet or in a Dialog,
|
||||
* depending on the form factor of the applet.
|
||||
*/
|
||||
virtual QWidget *widget();
|
||||
void setWidget(QWidget * widget);
|
||||
|
||||
/**
|
||||
* Implement either this function or widget().
|
||||
* @return the widget that will get shown in either a layout, in the applet or in a Dialog,
|
||||
* depending on the form factor of the applet.
|
||||
* If you set a popup icon you must also set a minimum size of the applet. When the applet
|
||||
* is smaller than this minimum size, it will be displayed as that icon.
|
||||
*/
|
||||
virtual QGraphicsWidget *graphicsWidget();
|
||||
void setGraphicsWidget(QGraphicsWidget * widget);
|
||||
|
||||
/**
|
||||
* @return the placement of the popup relating to the applet
|
||||
*/
|
||||
Plasma::PopupPlacement popupPlacement() const;
|
||||
|
||||
/**
|
||||
* Sets the default alignment of the popup relative to the applet
|
||||
* @param alignment the alignment to use; Qt::AlignLeft or Qt::AlignRight
|
||||
* @since 4.6
|
||||
*/
|
||||
void setPopupAlignment(Qt::AlignmentFlag alignment);
|
||||
|
||||
/**
|
||||
* @return the default alignment of the popup relative to the applet
|
||||
* @since 4.6
|
||||
*/
|
||||
Qt::AlignmentFlag popupAlignment() const;
|
||||
|
||||
/**
|
||||
* Sets whether or not the dialog popup that gets created should be a "passive" popup
|
||||
* that does not steal focus from other windows or not.
|
||||
*
|
||||
* @param passive true if the dialog should be treated as a passive popup
|
||||
*/
|
||||
void setPassivePopup(bool passive);
|
||||
|
||||
/**
|
||||
* @return true if the dialog will be treated as a passive poup
|
||||
*/
|
||||
bool isPassivePopup() const;
|
||||
|
||||
/**
|
||||
* @return true if the applet is popped up
|
||||
*/
|
||||
bool isPopupShowing() const;
|
||||
|
||||
/**
|
||||
* @return true if the applet is collapsed to an icon
|
||||
* @since 4.6
|
||||
*/
|
||||
bool isIconified() const;
|
||||
|
||||
|
||||
public Q_SLOTS:
|
||||
/**
|
||||
* Hides the popup.
|
||||
*/
|
||||
void hidePopup();
|
||||
|
||||
/**
|
||||
* Shows the dialog showing the widget if the applet is in a panel.
|
||||
* @param displayTime the time in ms that the popup should be displayed, defaults to 0 which means
|
||||
* always (until the user closes it again, that is).
|
||||
*/
|
||||
void showPopup(uint displayTime = 0);
|
||||
|
||||
/**
|
||||
* Toggles the popup.
|
||||
*/
|
||||
void togglePopup();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* This event handler can be reimplemented in a subclass to receive an
|
||||
* event before the popup is shown or hidden.
|
||||
* @param show true if the popup is going to be shown, false if the popup
|
||||
* is going to be hidden.
|
||||
* Note that showing and hiding the popup on click is already done in PopupApplet.
|
||||
*/
|
||||
virtual void popupEvent(bool show);
|
||||
|
||||
/**
|
||||
* Reimplemented from QGraphicsLayoutItem
|
||||
*/
|
||||
QSizeF sizeHint(Qt::SizeHint which, const QSizeF & constraint = QSizeF()) const;
|
||||
|
||||
/**
|
||||
* Reimplemented from QGraphicsLayoutItem
|
||||
*/
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent *event);
|
||||
|
||||
/**
|
||||
* Reimplemented from QGraphicsLayoutItem
|
||||
*/
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
|
||||
|
||||
/**
|
||||
* Reimplemented from QGraphicsLayoutItem
|
||||
*/
|
||||
bool eventFilter(QObject *watched, QEvent *event);
|
||||
|
||||
/**
|
||||
* Reimplemented from QGraphicsLayoutItem
|
||||
*/
|
||||
void timerEvent(QTimerEvent *event);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @internal This constructor is to be used with the Package loading system.
|
||||
*
|
||||
* @param parent a QObject parent; you probably want to pass in 0
|
||||
* @param args a list of strings containing two entries: the service id
|
||||
* and the applet id
|
||||
* @since 4.3
|
||||
*/
|
||||
PopupApplet(const QString &packagePath, uint appletId, const QVariantList &args);
|
||||
|
||||
Q_PRIVATE_SLOT(d, void internalTogglePopup())
|
||||
Q_PRIVATE_SLOT(d, void hideTimedPopup())
|
||||
Q_PRIVATE_SLOT(d, void clearPopupLostFocus())
|
||||
Q_PRIVATE_SLOT(d, void dialogSizeChanged())
|
||||
Q_PRIVATE_SLOT(d, void dialogStatusChanged(bool))
|
||||
Q_PRIVATE_SLOT(d, void updateDialogPosition())
|
||||
Q_PRIVATE_SLOT(d, void appletActivated())
|
||||
Q_PRIVATE_SLOT(d, void iconSizeChanged(int))
|
||||
Q_PRIVATE_SLOT(d, void statusChangeWhileShown(Plasma::ItemStatus status))
|
||||
|
||||
friend class Applet;
|
||||
friend class AppletPrivate;
|
||||
friend class PopupAppletPrivate;
|
||||
PopupAppletPrivate * const d;
|
||||
};
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
#endif /* POPUPAPPLET_H */
|
||||
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
* 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 IconWidget;
|
||||
class Dialog;
|
||||
|
||||
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(bool move = true);
|
||||
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
|
||||
|
@ -1,402 +0,0 @@
|
||||
/*
|
||||
* Copyright 2007 by Dan Meltzer <hydrogen@notyetimplemented.com>
|
||||
* Copyright (C) 2008 by Alexis Ménard <darktears31@gmail.com>
|
||||
*
|
||||
* This program 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, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 Library General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "tooltip_p.h"
|
||||
#include "windowpreview_p.h"
|
||||
|
||||
#include <QAbstractTextDocumentLayout>
|
||||
#include <QBitmap>
|
||||
#include <QGridLayout>
|
||||
#include <QLabel>
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
#include <QPalette>
|
||||
#include <QTextDocument>
|
||||
#include <QPropertyAnimation>
|
||||
#include <QTextBlock>
|
||||
|
||||
#include <kdebug.h>
|
||||
#include <kglobalsettings.h>
|
||||
#include <kwindoweffects.h>
|
||||
|
||||
#include <plasma/plasma.h>
|
||||
#include <plasma/paintutils.h>
|
||||
#include <plasma/theme.h>
|
||||
#include <plasma/framesvg.h>
|
||||
|
||||
namespace Plasma {
|
||||
|
||||
class TipTextWidget : public QWidget
|
||||
{
|
||||
public:
|
||||
TipTextWidget(ToolTip *parent)
|
||||
: QWidget(parent),
|
||||
m_toolTip(parent),
|
||||
m_document(new QTextDocument(this))
|
||||
{
|
||||
QTextOption option = m_document->defaultTextOption();
|
||||
option.setWrapMode(QTextOption::WordWrap);
|
||||
m_document->setDefaultTextOption(option);
|
||||
}
|
||||
|
||||
void setStyleSheet(const QString &css)
|
||||
{
|
||||
m_document->setDefaultStyleSheet(css);
|
||||
}
|
||||
|
||||
void setContent(const ToolTipContent &data)
|
||||
{
|
||||
QString html;
|
||||
QString mainText = data.mainText();
|
||||
if (!mainText.isEmpty()) {
|
||||
if (mainText.size() < 50) {
|
||||
// don't let short texts wrap on us!
|
||||
mainText = mainText.replace(" ", " ");
|
||||
}
|
||||
html.append("<div align=\"center\"><b>" + mainText + "</b></div>");
|
||||
}
|
||||
html.append(data.subText());
|
||||
|
||||
m_anchor.clear();
|
||||
m_document->clear();
|
||||
data.registerResources(m_document);
|
||||
if (!html.isEmpty()) {
|
||||
m_document->setHtml("<p>" + html + "</p>");
|
||||
} else {
|
||||
m_document->clear();
|
||||
}
|
||||
m_document->adjustSize();
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
QSize minimumSizeHint() const
|
||||
{
|
||||
const int margin = 6;
|
||||
return m_document->size().toSize() + QSize(margin, margin)*2;
|
||||
}
|
||||
|
||||
QSize maximumSizeHint() const
|
||||
{
|
||||
return minimumSizeHint();
|
||||
}
|
||||
|
||||
void paintEvent(QPaintEvent *event)
|
||||
{
|
||||
QPainter p(this);
|
||||
m_document->drawContents(&p, event->rect());
|
||||
}
|
||||
|
||||
void mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
QAbstractTextDocumentLayout *layout = m_document->documentLayout();
|
||||
if (layout) {
|
||||
m_anchor = layout->anchorAt(event->pos());
|
||||
}
|
||||
}
|
||||
|
||||
void mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
QAbstractTextDocumentLayout *layout = m_document->documentLayout();
|
||||
if (layout) {
|
||||
QString anchor = layout->anchorAt(event->pos());
|
||||
if (anchor == m_anchor) {
|
||||
m_toolTip->linkActivated(m_anchor, event);
|
||||
}
|
||||
|
||||
m_anchor.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
ToolTip *m_toolTip;
|
||||
QTextDocument *m_document;
|
||||
QString m_anchor;
|
||||
};
|
||||
|
||||
class ToolTipPrivate
|
||||
{
|
||||
public:
|
||||
ToolTipPrivate()
|
||||
: text(0),
|
||||
imageLabel(0),
|
||||
preview(0),
|
||||
direction(Plasma::Up),
|
||||
autohide(true)
|
||||
{ }
|
||||
|
||||
TipTextWidget *text;
|
||||
QLabel *imageLabel;
|
||||
WindowPreview *preview;
|
||||
FrameSvg *background;
|
||||
QWeakPointer<QObject> source;
|
||||
QPropertyAnimation *animation;
|
||||
Plasma::Direction direction;
|
||||
bool autohide;
|
||||
};
|
||||
|
||||
ToolTip::ToolTip(QWidget *parent)
|
||||
: QWidget(parent),
|
||||
d(new ToolTipPrivate())
|
||||
{
|
||||
setAttribute(Qt::WA_TranslucentBackground);
|
||||
setWindowFlags(Qt::ToolTip);
|
||||
d->preview = new WindowPreview(this);
|
||||
d->text = new TipTextWidget(this);
|
||||
d->imageLabel = new QLabel(this);
|
||||
|
||||
d->imageLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft);
|
||||
d->animation = new QPropertyAnimation(this, "pos", this);
|
||||
d->animation->setEasingCurve(QEasingCurve::InOutQuad);
|
||||
d->animation->setDuration(250);
|
||||
|
||||
d->background = new FrameSvg(this);
|
||||
d->background->setImagePath("widgets/tooltip");
|
||||
d->background->setEnabledBorders(FrameSvg::AllBorders);
|
||||
updateTheme();
|
||||
connect(d->background, SIGNAL(repaintNeeded()), this, SLOT(updateTheme()));
|
||||
connect(d->preview, SIGNAL(windowPreviewClicked(WId,Qt::MouseButtons,Qt::KeyboardModifiers,QPoint)),
|
||||
this, SIGNAL(activateWindowByWId(WId,Qt::MouseButtons,Qt::KeyboardModifiers,QPoint)));
|
||||
|
||||
QHBoxLayout *previewHBoxLayout = new QHBoxLayout;
|
||||
previewHBoxLayout->addWidget(d->preview);
|
||||
|
||||
QHBoxLayout *iconTextHBoxLayout = new QHBoxLayout;
|
||||
iconTextHBoxLayout->addWidget(d->imageLabel);
|
||||
iconTextHBoxLayout->setAlignment(d->imageLabel, Qt::AlignTop | Qt::AlignHCenter);
|
||||
iconTextHBoxLayout->addWidget(d->text);
|
||||
iconTextHBoxLayout->setAlignment(d->text, Qt::AlignLeft | Qt::AlignVCenter);
|
||||
iconTextHBoxLayout->setStretchFactor(d->text, 1);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(previewHBoxLayout);
|
||||
mainLayout->addLayout(iconTextHBoxLayout);
|
||||
|
||||
setLayout(mainLayout);
|
||||
}
|
||||
|
||||
ToolTip::~ToolTip()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
void ToolTip::showEvent(QShowEvent *e)
|
||||
{
|
||||
checkSize();
|
||||
QWidget::showEvent(e);
|
||||
d->preview->setInfo();
|
||||
KWindowEffects::overrideShadow(winId(), true);
|
||||
}
|
||||
|
||||
void ToolTip::hideEvent(QHideEvent *e)
|
||||
{
|
||||
QWidget::hideEvent(e);
|
||||
d->animation->stop();
|
||||
|
||||
QObject *source = d->source.data();
|
||||
if (source && source->metaObject()->indexOfMethod("toolTipHidden()") != -1) {
|
||||
QMetaObject::invokeMethod(source, "toolTipHidden");
|
||||
}
|
||||
|
||||
KWindowEffects::highlightWindows(winId(), QList<WId>());
|
||||
}
|
||||
|
||||
void ToolTip::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
if (rect().contains(event->pos()) &&
|
||||
(!d->preview || !d->preview->geometry().contains(event->pos()))) {
|
||||
hide();
|
||||
}
|
||||
}
|
||||
|
||||
void ToolTip::enterEvent(QEvent *)
|
||||
{
|
||||
emit hovered(true);
|
||||
}
|
||||
|
||||
void ToolTip::leaveEvent(QEvent *)
|
||||
{
|
||||
emit hovered(false);
|
||||
}
|
||||
|
||||
void ToolTip::checkSize()
|
||||
{
|
||||
//FIXME: layout bugs even on qlayouts? oh, please, no.
|
||||
d->text->setMinimumSize(0, 0);
|
||||
d->text->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
|
||||
d->text->setMinimumSize(d->text->minimumSizeHint());
|
||||
d->text->setMaximumSize(d->text->maximumSizeHint());
|
||||
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
void ToolTip::adjustPosition(const QSize &previous, const QSize ¤t)
|
||||
{
|
||||
if (previous != current) {
|
||||
//offsets to stop tooltips from jumping when they resize
|
||||
int deltaX = 0;
|
||||
int deltaY = 0;
|
||||
if (d->direction == Plasma::Up) {
|
||||
/*
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "resizing from" << current << "to" << hint
|
||||
#endif
|
||||
<< "and moving from" << pos() << "to"
|
||||
<< x() << y() + (current.height() - hint.height())
|
||||
<< current.height() - hint.height();
|
||||
*/
|
||||
deltaY = previous.height() - current.height();
|
||||
} else if (d->direction == Plasma::Left) {
|
||||
/*
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "vertical resizing from" << current << "to" << hint
|
||||
#endif
|
||||
<< "and moving from" << pos() << "to"
|
||||
<< x() + (current.width() - hint.width()) << y()
|
||||
<< current.width() - hint.width(); */
|
||||
deltaX = previous.width() - current.width();
|
||||
}
|
||||
|
||||
// resize then move if we're getting smaller, vice versa when getting bigger
|
||||
// this prevents overlap with the item in the smaller case, and a repaint of
|
||||
// the tipped item when getting bigger
|
||||
|
||||
move(x() + deltaX, y() + deltaY);
|
||||
}
|
||||
}
|
||||
|
||||
void ToolTip::setContent(QObject *tipper, const ToolTipContent &data)
|
||||
{
|
||||
//reset our size
|
||||
d->text->setContent(data);
|
||||
if (data.image().isNull()) {
|
||||
d->imageLabel->hide();
|
||||
} else {
|
||||
d->imageLabel->show();
|
||||
d->imageLabel->setPixmap(data.image());
|
||||
}
|
||||
|
||||
if (data.highlightWindows() && !data.windowsToPreview().isEmpty()) {
|
||||
KWindowEffects::highlightWindows(winId(), QList<WId>() << winId() << data.windowsToPreview());
|
||||
}
|
||||
|
||||
d->preview->setWindowIds(data.windowsToPreview());
|
||||
d->preview->setHighlightWindows(data.highlightWindows());
|
||||
|
||||
d->autohide = data.autohide();
|
||||
d->source = tipper;
|
||||
|
||||
if (isVisible()) {
|
||||
d->preview->setInfo();
|
||||
//kDebug() << "about to check size";
|
||||
checkSize();
|
||||
}
|
||||
}
|
||||
|
||||
void ToolTip::prepareShowing()
|
||||
{
|
||||
// show/hide the preview area
|
||||
d->preview->setVisible(!d->preview->isEmpty());
|
||||
|
||||
layout()->activate();
|
||||
d->preview->setInfo();
|
||||
//kDebug() << "about to check size";
|
||||
checkSize();
|
||||
}
|
||||
|
||||
void ToolTip::moveTo(const QPoint &to)
|
||||
{
|
||||
if (!isVisible() ||
|
||||
!(KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects)) {
|
||||
move(to);
|
||||
return;
|
||||
}
|
||||
|
||||
d->animation->stop();
|
||||
d->animation->setEndValue(to);
|
||||
d->animation->start();
|
||||
}
|
||||
|
||||
void ToolTip::resizeEvent(QResizeEvent *e)
|
||||
{
|
||||
QWidget::resizeEvent(e);
|
||||
d->background->resizeFrame(size());
|
||||
if (Plasma::Theme::defaultTheme()->windowTranslucencyEnabled()) {
|
||||
KWindowEffects::enableBlurBehind(winId(), true, d->background->mask());
|
||||
clearMask();
|
||||
} else {
|
||||
setMask(d->background->mask());
|
||||
}
|
||||
d->preview->setInfo();
|
||||
|
||||
if (isVisible()) {
|
||||
adjustPosition(e->oldSize(), e->size());
|
||||
}
|
||||
}
|
||||
|
||||
void ToolTip::paintEvent(QPaintEvent *e)
|
||||
{
|
||||
QPainter painter(this);
|
||||
painter.setClipRect(e->rect());
|
||||
painter.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
painter.fillRect(e->rect(), Qt::transparent);
|
||||
|
||||
d->background->paintFrame(&painter);
|
||||
}
|
||||
|
||||
bool ToolTip::autohide() const
|
||||
{
|
||||
return d->autohide;
|
||||
}
|
||||
|
||||
void ToolTip::setDirection(Plasma::Direction direction)
|
||||
{
|
||||
d->direction = direction;
|
||||
}
|
||||
|
||||
void ToolTip::linkActivated(const QString &anchor, QMouseEvent *event)
|
||||
{
|
||||
emit linkActivated(anchor, event->buttons(), event->modifiers(), event->globalPos());
|
||||
}
|
||||
|
||||
void ToolTip::updateTheme()
|
||||
{
|
||||
const int topHeight = d->background->marginSize(Plasma::TopMargin);
|
||||
const int leftWidth = d->background->marginSize(Plasma::LeftMargin);
|
||||
const int rightWidth = d->background->marginSize(Plasma::RightMargin);
|
||||
const int bottomHeight = d->background->marginSize(Plasma::BottomMargin);
|
||||
setContentsMargins(leftWidth, topHeight, rightWidth, bottomHeight);
|
||||
|
||||
// Make the tooltip use Plasma's colorscheme
|
||||
QColor textColor = Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor);
|
||||
QPalette plasmaPalette = QPalette();
|
||||
plasmaPalette.setColor(QPalette::Window,
|
||||
Plasma::Theme::defaultTheme()->color(Plasma::Theme::BackgroundColor));
|
||||
plasmaPalette.setColor(QPalette::WindowText, textColor);
|
||||
setAutoFillBackground(true);
|
||||
setPalette(plasmaPalette);
|
||||
d->text->setStyleSheet(QString("p { color: %1; }").arg(textColor.name()));
|
||||
update();
|
||||
}
|
||||
|
||||
} // namespace Plasma
|
||||
|
||||
#include "moc_tooltip_p.cpp"
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Copyright 2007 by Dan Meltzer <hydrogen@notyetimplemented.com>
|
||||
* Copyright (C) 2008 by Alexis Ménard <darktears31@gmail.com>
|
||||
*
|
||||
* This program 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, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 Library General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef PLASMA_TOOLTIP_P_H
|
||||
#define PLASMA_TOOLTIP_P_H
|
||||
|
||||
#include <QWidget> // base class
|
||||
|
||||
#include <plasma/tooltipmanager.h> //Content struct
|
||||
|
||||
namespace Plasma {
|
||||
|
||||
class ToolTipPrivate;
|
||||
|
||||
class ToolTip : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ToolTip(QWidget *parent);
|
||||
~ToolTip();
|
||||
|
||||
void setContent(QObject *tipper, const ToolTipContent &data);
|
||||
void prepareShowing();
|
||||
void moveTo(const QPoint &to);
|
||||
bool autohide() const;
|
||||
void setDirection(Plasma::Direction);
|
||||
void linkActivated(const QString &anchor, QMouseEvent *event);
|
||||
|
||||
Q_SIGNALS:
|
||||
void activateWindowByWId(WId wid,
|
||||
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers,
|
||||
const QPoint& screenPos);
|
||||
void linkActivated(const QString &anchor,
|
||||
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers,
|
||||
const QPoint& screenPos);
|
||||
void hovered(bool hovered);
|
||||
|
||||
protected:
|
||||
void checkSize();
|
||||
void adjustPosition(const QSize &previous, const QSize ¤t);
|
||||
void showEvent(QShowEvent *);
|
||||
void hideEvent(QHideEvent *);
|
||||
void mouseReleaseEvent(QMouseEvent *);
|
||||
void enterEvent(QEvent *);
|
||||
void leaveEvent(QEvent *);
|
||||
|
||||
void resizeEvent(QResizeEvent *);
|
||||
void paintEvent(QPaintEvent *);
|
||||
|
||||
private Q_SLOTS:
|
||||
void updateTheme();
|
||||
|
||||
private:
|
||||
ToolTipPrivate * const d;
|
||||
};
|
||||
|
||||
} // namespace Plasma
|
||||
|
||||
#endif // PLASMA_TOOLTIP_P_H
|
||||
|
@ -1,256 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008 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 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 "tooltipcontent.h"
|
||||
|
||||
#include <QGraphicsWidget>
|
||||
#include <QHash>
|
||||
#include <QTextDocument>
|
||||
|
||||
#include <kiconloader.h>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
struct ToolTipResource
|
||||
{
|
||||
ToolTipResource()
|
||||
{
|
||||
}
|
||||
|
||||
ToolTipResource(ToolTipContent::ResourceType t, const QVariant &v)
|
||||
: type(t),
|
||||
data(v)
|
||||
{
|
||||
}
|
||||
|
||||
ToolTipContent::ResourceType type;
|
||||
QVariant data;
|
||||
};
|
||||
|
||||
const int MAXIMUM_TEXT_LENGTH = 5000;
|
||||
|
||||
class ToolTipContentPrivate
|
||||
{
|
||||
public:
|
||||
ToolTipContentPrivate()
|
||||
: autohide(true),
|
||||
instantPopup(false),
|
||||
clickable(false),
|
||||
highlightWindows(false)
|
||||
{
|
||||
}
|
||||
|
||||
QString mainText;
|
||||
QString subText;
|
||||
QPixmap image;
|
||||
QList<WId> windowsToPreview;
|
||||
QHash<QUrl, ToolTipResource> resources;
|
||||
QWeakPointer<QGraphicsWidget> graphicsWidget;
|
||||
bool autohide : 1;
|
||||
bool instantPopup : 1;
|
||||
bool clickable : 1;
|
||||
bool highlightWindows : 1;
|
||||
};
|
||||
|
||||
ToolTipContent::ToolTipContent()
|
||||
: d(new ToolTipContentPrivate)
|
||||
{
|
||||
}
|
||||
|
||||
ToolTipContent::ToolTipContent(const ToolTipContent &other)
|
||||
: d(new ToolTipContentPrivate(*other.d))
|
||||
{
|
||||
}
|
||||
|
||||
ToolTipContent::~ToolTipContent()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
ToolTipContent &ToolTipContent::operator=(const ToolTipContent &other)
|
||||
{
|
||||
*d = *other.d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ToolTipContent::ToolTipContent(const QString &mainText,
|
||||
const QString &subText,
|
||||
const QPixmap &image)
|
||||
: d(new ToolTipContentPrivate)
|
||||
{
|
||||
setMainText(mainText);
|
||||
setSubText(subText);
|
||||
setImage(image);
|
||||
}
|
||||
|
||||
ToolTipContent::ToolTipContent(const QString &mainText,
|
||||
const QString &subText,
|
||||
const QIcon &icon)
|
||||
: d(new ToolTipContentPrivate)
|
||||
{
|
||||
setMainText(mainText);
|
||||
setSubText(subText);
|
||||
setImage(icon);
|
||||
}
|
||||
|
||||
bool ToolTipContent::isEmpty() const
|
||||
{
|
||||
return d->mainText.isEmpty() &&
|
||||
d->subText.isEmpty() &&
|
||||
d->image.isNull() &&
|
||||
(d->windowsToPreview.size() == 0);
|
||||
}
|
||||
|
||||
void ToolTipContent::setMainText(const QString &text)
|
||||
{
|
||||
d->mainText = text.trimmed();
|
||||
}
|
||||
|
||||
QString ToolTipContent::mainText() const
|
||||
{
|
||||
QString text = d->mainText;
|
||||
text.truncate(MAXIMUM_TEXT_LENGTH);
|
||||
return text;
|
||||
}
|
||||
|
||||
void ToolTipContent::setSubText(const QString &text)
|
||||
{
|
||||
d->subText = text.trimmed();
|
||||
}
|
||||
|
||||
QString ToolTipContent::subText() const
|
||||
{
|
||||
QString text = d->subText;
|
||||
text.truncate(MAXIMUM_TEXT_LENGTH);
|
||||
return text;
|
||||
}
|
||||
|
||||
void ToolTipContent::setImage(const QPixmap &image)
|
||||
{
|
||||
d->image = image;
|
||||
}
|
||||
|
||||
void ToolTipContent::setImage(const QIcon &icon)
|
||||
{
|
||||
d->image = icon.pixmap(IconSize(KIconLoader::Desktop));
|
||||
}
|
||||
|
||||
QPixmap ToolTipContent::image() const
|
||||
{
|
||||
return d->image;
|
||||
}
|
||||
|
||||
void ToolTipContent::setWindowsToPreview(const QList<WId> & ids)
|
||||
{
|
||||
d->windowsToPreview = ids;
|
||||
}
|
||||
|
||||
QList<WId> ToolTipContent::windowsToPreview() const
|
||||
{
|
||||
return d->windowsToPreview;
|
||||
}
|
||||
|
||||
void ToolTipContent::setHighlightWindows(bool highlight)
|
||||
{
|
||||
d->highlightWindows = highlight;
|
||||
}
|
||||
|
||||
bool ToolTipContent::highlightWindows() const
|
||||
{
|
||||
return d->highlightWindows;
|
||||
}
|
||||
|
||||
void ToolTipContent::setAutohide(bool autohide)
|
||||
{
|
||||
d->autohide = autohide;
|
||||
}
|
||||
|
||||
bool ToolTipContent::autohide() const
|
||||
{
|
||||
return d->autohide;
|
||||
}
|
||||
|
||||
void ToolTipContent::setInstantPopup(bool enabled)
|
||||
{
|
||||
d->instantPopup = enabled;
|
||||
}
|
||||
|
||||
bool ToolTipContent::isInstantPopup() const
|
||||
{
|
||||
return d->instantPopup;
|
||||
}
|
||||
|
||||
void ToolTipContent::addResource(ResourceType type, const QUrl &path, const QVariant &resource)
|
||||
{
|
||||
d->resources.insert(path, ToolTipResource(type, resource));
|
||||
}
|
||||
|
||||
void ToolTipContent::registerResources(QTextDocument *document) const
|
||||
{
|
||||
if (!document) {
|
||||
return;
|
||||
}
|
||||
|
||||
QHashIterator<QUrl, ToolTipResource> it(d->resources);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
const ToolTipResource &r = it.value();
|
||||
QTextDocument::ResourceType t = QTextDocument::ImageResource;
|
||||
|
||||
switch (r.type) {
|
||||
case ImageResource:
|
||||
break;
|
||||
case HtmlResource:
|
||||
t = QTextDocument::HtmlResource;
|
||||
break;
|
||||
case CssResource:
|
||||
t = QTextDocument::StyleSheetResource;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
document->addResource(t, it.key(), r.data);
|
||||
}
|
||||
}
|
||||
|
||||
void ToolTipContent::setClickable(bool clickable)
|
||||
{
|
||||
d->clickable = clickable;
|
||||
}
|
||||
|
||||
bool ToolTipContent::isClickable() const
|
||||
{
|
||||
return d->clickable;
|
||||
}
|
||||
|
||||
void ToolTipContent::setGraphicsWidget(QGraphicsWidget *widget)
|
||||
{
|
||||
d->graphicsWidget = widget;
|
||||
}
|
||||
|
||||
QGraphicsWidget *ToolTipContent::graphicsWidget() const
|
||||
{
|
||||
return d->graphicsWidget.data();
|
||||
}
|
||||
|
||||
} // namespace Plasma
|
||||
|
||||
|
216
tooltipcontent.h
216
tooltipcontent.h
@ -1,216 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008 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 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 PLASMA_TOOLTIPCONTENT_H
|
||||
#define PLASMA_TOOLTIPCONTENT_H
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QUrl>
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtCore/QList>
|
||||
#include <QPixmap>
|
||||
#include <QIcon>
|
||||
|
||||
#include <plasma/plasma_export.h>
|
||||
|
||||
class QTextDocument;
|
||||
class QGraphicsWidget;
|
||||
|
||||
/**
|
||||
* This provides the content for a tooltip.
|
||||
*
|
||||
* Normally you will want to set at least the @p mainText and
|
||||
* @p subText.
|
||||
*/
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class ToolTipContentPrivate;
|
||||
|
||||
class PLASMA_EXPORT ToolTipContent
|
||||
{
|
||||
public:
|
||||
enum ResourceType { ImageResource = 0, HtmlResource, CssResource };
|
||||
|
||||
/**
|
||||
* Creates an empty Content
|
||||
*/
|
||||
ToolTipContent();
|
||||
|
||||
~ToolTipContent();
|
||||
|
||||
/**
|
||||
* Copy constructor
|
||||
*/
|
||||
ToolTipContent(const ToolTipContent &other);
|
||||
|
||||
/**
|
||||
* Constructor that sets the common fields
|
||||
*/
|
||||
ToolTipContent(const QString &mainText,
|
||||
const QString &subText,
|
||||
const QPixmap &image = QPixmap());
|
||||
|
||||
/**
|
||||
* Constructor that sets the common fields
|
||||
*/
|
||||
ToolTipContent(const QString &mainText,
|
||||
const QString &subText,
|
||||
const QIcon &icon);
|
||||
|
||||
ToolTipContent &operator=(const ToolTipContent &other);
|
||||
|
||||
/**
|
||||
* @return true if all the fields are empty
|
||||
*/
|
||||
bool isEmpty() const;
|
||||
|
||||
/**
|
||||
* Sets the main text which containts important information, e.g. the title
|
||||
*/
|
||||
void setMainText(const QString &text);
|
||||
|
||||
/**
|
||||
* Important information, e.g. the title
|
||||
*/
|
||||
QString mainText() const;
|
||||
|
||||
/**
|
||||
* Sets text which elaborates on the @p mainText
|
||||
*/
|
||||
void setSubText(const QString &text) ;
|
||||
|
||||
/**
|
||||
* Elaborates on the @p mainText
|
||||
*/
|
||||
QString subText() const;
|
||||
|
||||
/**
|
||||
* Sets the icon to show
|
||||
*/
|
||||
void setImage(const QPixmap &image);
|
||||
|
||||
/**
|
||||
* Sets the icon to show
|
||||
*/
|
||||
void setImage(const QIcon &icon);
|
||||
|
||||
/**
|
||||
* An icon to display
|
||||
*/
|
||||
QPixmap image() const;
|
||||
|
||||
/**
|
||||
* Sets the IDS of the windows to show a preview for
|
||||
* @since 4.3
|
||||
*/
|
||||
void setWindowsToPreview(const QList<WId> &ids);
|
||||
|
||||
/**
|
||||
* Ids of a windows if you want to show a preview
|
||||
* @since 4.3
|
||||
*/
|
||||
QList<WId> windowsToPreview() const;
|
||||
|
||||
/**
|
||||
* sets if when the mouse will be over a thumbnail the corresponding window
|
||||
* will be highlighted by reducing opacity of all the other windows
|
||||
* @since 4.4
|
||||
*/
|
||||
void setHighlightWindows(bool highlight);
|
||||
|
||||
/**
|
||||
* true if when the mouse will be over a thumbnail the corresponding window
|
||||
* will be highlighted by reducing opacity of all the other windows
|
||||
* @since 4.4
|
||||
*/
|
||||
bool highlightWindows() const;
|
||||
|
||||
/** Sets whether or not to autohide the tooltip, defaults to true
|
||||
*/
|
||||
void setAutohide(bool autohide);
|
||||
|
||||
/**
|
||||
* Whether or not to autohide the tooltip, defaults to true
|
||||
*/
|
||||
bool autohide() const;
|
||||
|
||||
/**
|
||||
* Sets whether or not the tooltip should popup instantly when
|
||||
* the widget is hovered, defaults to false.
|
||||
*
|
||||
* @since 4.7
|
||||
*/
|
||||
void setInstantPopup(bool enabled);
|
||||
|
||||
/**
|
||||
* Whether or not the tooltip should popup instantly when
|
||||
* the widget is hovered, defaults to false.
|
||||
*
|
||||
* @since 4.7
|
||||
*/
|
||||
bool isInstantPopup() const;
|
||||
|
||||
/**
|
||||
* Adds a resource that can then be referenced from the text elements
|
||||
* using rich text
|
||||
*/
|
||||
void addResource(ResourceType type, const QUrl &path, const QVariant &resource);
|
||||
|
||||
/**
|
||||
* Registers all resources with a given document
|
||||
*/
|
||||
void registerResources(QTextDocument *document) const;
|
||||
|
||||
/**
|
||||
* Sets whether or not the tooltip contains clickable content, such as
|
||||
* window previews. Defaults to false, or not clickable.
|
||||
*
|
||||
* @since 4.3
|
||||
*/
|
||||
void setClickable(bool clickable);
|
||||
|
||||
/**
|
||||
* @return true if the tooltip is clickabel
|
||||
*
|
||||
* @since 4.3
|
||||
*/
|
||||
bool isClickable() const;
|
||||
|
||||
/**
|
||||
* Sets an optional graphicsWidget that will be used for positioning the tooltip
|
||||
* @since 4.6
|
||||
*/
|
||||
void setGraphicsWidget(QGraphicsWidget *widget);
|
||||
|
||||
/**
|
||||
* the graphicsWidget used for positioning the tooltip, if any
|
||||
* @since 4.6
|
||||
*/
|
||||
QGraphicsWidget *graphicsWidget() const;
|
||||
|
||||
private:
|
||||
ToolTipContentPrivate * const d;
|
||||
};
|
||||
|
||||
} // namespace Plasma
|
||||
|
||||
#endif
|
||||
|
@ -1,493 +0,0 @@
|
||||
/*
|
||||
* Copyright 2007 by Dan Meltzer <hydrogen@notyetimplemented.com>
|
||||
* Copyright 2008 by Aaron Seigo <aseigo@kde.org>
|
||||
* Copyright 2008 by Alexis Ménard <darktears31@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 "tooltipmanager.h"
|
||||
|
||||
//Qt
|
||||
#include <QCoreApplication>
|
||||
#include <QLabel>
|
||||
#include <QTimer>
|
||||
#include <QGridLayout>
|
||||
#include <QGraphicsView>
|
||||
#include <QGraphicsSceneHoverEvent>
|
||||
|
||||
//KDE
|
||||
#include <kwindowsystem.h>
|
||||
|
||||
//Plasma
|
||||
#include "plasma/applet.h"
|
||||
#include "plasma/containment.h"
|
||||
#include "plasma/corona.h"
|
||||
#include "plasma/framesvg.h"
|
||||
#include "plasma/popupapplet.h"
|
||||
#include "plasma/theme.h"
|
||||
#include "plasma/view.h"
|
||||
#include "plasma/private/tooltip_p.h"
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class ToolTipManagerPrivate
|
||||
{
|
||||
public :
|
||||
ToolTipManagerPrivate(ToolTipManager *manager)
|
||||
: q(manager),
|
||||
currentWidget(0),
|
||||
showTimer(new QTimer(manager)),
|
||||
hideTimer(new QTimer(manager)),
|
||||
tipWidget(0),
|
||||
state(ToolTipManager::Activated),
|
||||
isShown(false),
|
||||
delayedHide(false),
|
||||
clickable(false)
|
||||
{
|
||||
}
|
||||
|
||||
~ToolTipManagerPrivate()
|
||||
{
|
||||
if (!QCoreApplication::closingDown()) {
|
||||
delete tipWidget;
|
||||
}
|
||||
}
|
||||
|
||||
void showToolTip();
|
||||
void resetShownState();
|
||||
|
||||
/**
|
||||
* called when a widget inside the tooltip manager is deleted
|
||||
*/
|
||||
void onWidgetDestroyed(QObject * object);
|
||||
void removeWidget(QGraphicsWidget *w, bool canSafelyAccess = true);
|
||||
void clearTips();
|
||||
void doDelayedHide();
|
||||
void toolTipHovered(bool);
|
||||
void createTipWidget();
|
||||
void hideTipWidget();
|
||||
|
||||
ToolTipManager *q;
|
||||
QGraphicsWidget *currentWidget;
|
||||
QTimer *showTimer;
|
||||
QTimer *hideTimer;
|
||||
QHash<QGraphicsWidget *, ToolTipContent> tooltips;
|
||||
ToolTip *tipWidget;
|
||||
ToolTipManager::State state;
|
||||
bool isShown : 1;
|
||||
bool delayedHide : 1;
|
||||
bool clickable : 1;
|
||||
};
|
||||
|
||||
//TOOLTIP IMPLEMENTATION
|
||||
class ToolTipManagerSingleton
|
||||
{
|
||||
public:
|
||||
ToolTipManagerSingleton()
|
||||
{
|
||||
}
|
||||
ToolTipManager self;
|
||||
};
|
||||
Q_GLOBAL_STATIC(ToolTipManagerSingleton, privateInstance)
|
||||
|
||||
ToolTipManager *ToolTipManager::self()
|
||||
{
|
||||
return &privateInstance()->self;
|
||||
}
|
||||
|
||||
ToolTipManager::ToolTipManager(QObject *parent)
|
||||
: QObject(parent),
|
||||
d(new ToolTipManagerPrivate(this))
|
||||
{
|
||||
d->showTimer->setSingleShot(true);
|
||||
connect(d->showTimer, SIGNAL(timeout()), SLOT(showToolTip()));
|
||||
|
||||
d->hideTimer->setSingleShot(true);
|
||||
connect(d->hideTimer, SIGNAL(timeout()), SLOT(resetShownState()));
|
||||
}
|
||||
|
||||
ToolTipManager::~ToolTipManager()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
void ToolTipManager::show(QGraphicsWidget *widget)
|
||||
{
|
||||
if (!d->tooltips.contains(widget)) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->delayedHide = false;
|
||||
d->hideTimer->stop();
|
||||
d->showTimer->stop();
|
||||
const int defaultDelay = Theme::defaultTheme()->toolTipDelay();
|
||||
|
||||
if (defaultDelay < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ToolTipContent content = d->tooltips[widget];
|
||||
qreal delay = content.isInstantPopup() ? 0.0 : defaultDelay;
|
||||
|
||||
d->currentWidget = widget;
|
||||
|
||||
if (d->isShown) {
|
||||
// small delay to prevent unnecessary showing when the mouse is moving quickly across items
|
||||
// which can be too much for less powerful CPUs to keep up with
|
||||
d->showTimer->start(200);
|
||||
} else {
|
||||
d->showTimer->start(qMax(qreal(200), delay));
|
||||
}
|
||||
}
|
||||
|
||||
bool ToolTipManager::isVisible(QGraphicsWidget *widget) const
|
||||
{
|
||||
return d->currentWidget == widget && d->tipWidget && d->tipWidget->isVisible();
|
||||
}
|
||||
|
||||
void ToolTipManagerPrivate::doDelayedHide()
|
||||
{
|
||||
showTimer->stop(); // stop the timer to show the tooltip
|
||||
delayedHide = true;
|
||||
|
||||
if (isShown && clickable) {
|
||||
// leave enough time for user to choose
|
||||
hideTimer->start(1000);
|
||||
} else {
|
||||
hideTimer->start(250);
|
||||
}
|
||||
}
|
||||
|
||||
void ToolTipManager::hide(QGraphicsWidget *widget)
|
||||
{
|
||||
if (d->currentWidget != widget) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->currentWidget = 0;
|
||||
d->showTimer->stop(); // stop the timer to show the tooltip
|
||||
d->delayedHide = false;
|
||||
d->hideTipWidget();
|
||||
}
|
||||
|
||||
void ToolTipManager::registerWidget(QGraphicsWidget *widget)
|
||||
{
|
||||
if (d->state == Deactivated || d->tooltips.contains(widget)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//the tooltip is not registered we add it in our map of tooltips
|
||||
d->tooltips.insert(widget, ToolTipContent());
|
||||
widget->installEventFilter(this);
|
||||
connect(widget, SIGNAL(destroyed(QObject*)), this, SLOT(onWidgetDestroyed(QObject*)));
|
||||
}
|
||||
|
||||
void ToolTipManager::unregisterWidget(QGraphicsWidget *widget)
|
||||
{
|
||||
if (!d->tooltips.contains(widget)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (widget == d->currentWidget) {
|
||||
d->currentWidget = 0;
|
||||
d->showTimer->stop(); // stop the timer to show the tooltip
|
||||
d->delayedHide = false;
|
||||
d->hideTipWidget();
|
||||
}
|
||||
|
||||
widget->removeEventFilter(this);
|
||||
d->removeWidget(widget);
|
||||
}
|
||||
|
||||
void ToolTipManager::setContent(QGraphicsWidget *widget, const ToolTipContent &data)
|
||||
{
|
||||
if (d->state == Deactivated || !widget) {
|
||||
return;
|
||||
}
|
||||
|
||||
registerWidget(widget);
|
||||
d->tooltips.insert(widget, data);
|
||||
|
||||
if (d->currentWidget == widget && d->tipWidget && d->tipWidget->isVisible()) {
|
||||
if (data.isEmpty()) {
|
||||
// after this call, d->tipWidget will be null
|
||||
hide(widget);
|
||||
} else {
|
||||
d->delayedHide = data.autohide();
|
||||
d->clickable = data.isClickable();
|
||||
if (d->delayedHide) {
|
||||
//kDebug() << "starting authoide";
|
||||
d->hideTimer->start(3000);
|
||||
} else {
|
||||
d->hideTimer->stop();
|
||||
}
|
||||
}
|
||||
|
||||
if (d->tipWidget) {
|
||||
d->tipWidget->setContent(widget, data);
|
||||
d->tipWidget->prepareShowing();
|
||||
|
||||
//look if the data prefers aother graphicswidget, otherwise use the one used as event catcher
|
||||
QGraphicsWidget *referenceWidget = data.graphicsWidget() ? data.graphicsWidget() : widget;
|
||||
Corona *corona = qobject_cast<Corona *>(referenceWidget->scene());
|
||||
|
||||
if (corona) {
|
||||
d->tipWidget->moveTo(corona->popupPosition(referenceWidget, d->tipWidget->size(), Qt::AlignCenter));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ToolTipManager::clearContent(QGraphicsWidget *widget)
|
||||
{
|
||||
setContent(widget, ToolTipContent());
|
||||
}
|
||||
|
||||
void ToolTipManager::setState(ToolTipManager::State state)
|
||||
{
|
||||
d->state = state;
|
||||
|
||||
switch (state) {
|
||||
case Activated:
|
||||
break;
|
||||
case Deactivated:
|
||||
d->clearTips();
|
||||
//fallthrough
|
||||
case Inhibited:
|
||||
d->resetShownState();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ToolTipManager::State ToolTipManager::state() const
|
||||
{
|
||||
return d->state;
|
||||
}
|
||||
|
||||
void ToolTipManagerPrivate::createTipWidget()
|
||||
{
|
||||
if (tipWidget) {
|
||||
return;
|
||||
}
|
||||
|
||||
tipWidget = new ToolTip(0);
|
||||
QObject::connect(tipWidget, SIGNAL(activateWindowByWId(WId,Qt::MouseButtons,Qt::KeyboardModifiers,QPoint)),
|
||||
q, SIGNAL(windowPreviewActivated(WId,Qt::MouseButtons,Qt::KeyboardModifiers,QPoint)));
|
||||
QObject::connect(tipWidget, SIGNAL(linkActivated(QString,Qt::MouseButtons,Qt::KeyboardModifiers,QPoint)),
|
||||
q, SIGNAL(linkActivated(QString,Qt::MouseButtons,Qt::KeyboardModifiers,QPoint)));
|
||||
QObject::connect(tipWidget, SIGNAL(hovered(bool)), q, SLOT(toolTipHovered(bool)));
|
||||
}
|
||||
|
||||
void ToolTipManagerPrivate::hideTipWidget()
|
||||
{
|
||||
if (tipWidget) {
|
||||
tipWidget->hide();
|
||||
tipWidget->deleteLater();
|
||||
tipWidget = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ToolTipManagerPrivate::onWidgetDestroyed(QObject *object)
|
||||
{
|
||||
if (!object) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we do a static_cast here since it really isn't a QGraphicsWidget by this
|
||||
// point anymore since we are in the QObject dtor. we don't actually
|
||||
// try and do anything with it, we just need the value of the pointer
|
||||
// so this unsafe looking code is actually just fine.
|
||||
//
|
||||
// NOTE: DO NOT USE THE w VARIABLE FOR ANYTHING OTHER THAN COMPARING
|
||||
// THE ADDRESS! ACTUALLY USING THE OBJECT WILL RESULT IN A CRASH!!!
|
||||
QGraphicsWidget *w = static_cast<QGraphicsWidget*>(object);
|
||||
removeWidget(w, false);
|
||||
}
|
||||
|
||||
void ToolTipManagerPrivate::removeWidget(QGraphicsWidget *w, bool canSafelyAccess)
|
||||
{
|
||||
if (currentWidget == w && currentWidget) {
|
||||
currentWidget = 0;
|
||||
showTimer->stop(); // stop the timer to show the tooltip
|
||||
hideTipWidget();
|
||||
delayedHide = false;
|
||||
}
|
||||
|
||||
if (w && canSafelyAccess) {
|
||||
QObject::disconnect(q, 0, w, 0);
|
||||
}
|
||||
|
||||
tooltips.remove(w);
|
||||
}
|
||||
|
||||
void ToolTipManagerPrivate::clearTips()
|
||||
{
|
||||
tooltips.clear();
|
||||
}
|
||||
|
||||
void ToolTipManagerPrivate::resetShownState()
|
||||
{
|
||||
if (!tipWidget || !tipWidget->isVisible() || delayedHide) {
|
||||
//One might have moused out and back in again
|
||||
showTimer->stop();
|
||||
delayedHide = false;
|
||||
isShown = false;
|
||||
currentWidget = 0;
|
||||
hideTipWidget();
|
||||
}
|
||||
}
|
||||
|
||||
void ToolTipManagerPrivate::showToolTip()
|
||||
{
|
||||
if (state != ToolTipManager::Activated ||
|
||||
!currentWidget ||
|
||||
QApplication::activePopupWidget() ||
|
||||
QApplication::activeModalWidget()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PopupApplet *popup = qobject_cast<PopupApplet*>(currentWidget);
|
||||
if (popup && popup->isPopupShowing()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentWidget->metaObject()->indexOfMethod("toolTipAboutToShow()") != -1) {
|
||||
// toolTipAboutToShow may call into methods such as setContent which play
|
||||
// with the current widget; so let's just pretend for a moment that we don't have
|
||||
// a current widget
|
||||
QGraphicsWidget *temp = currentWidget;
|
||||
currentWidget = 0;
|
||||
QMetaObject::invokeMethod(temp, "toolTipAboutToShow");
|
||||
currentWidget = temp;
|
||||
}
|
||||
|
||||
QHash<QGraphicsWidget *, ToolTipContent>::const_iterator tooltip = tooltips.constFind(currentWidget);
|
||||
|
||||
if (tooltip == tooltips.constEnd() || tooltip.value().isEmpty()) {
|
||||
if (isShown) {
|
||||
delayedHide = true;
|
||||
hideTimer->start(250);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
createTipWidget();
|
||||
|
||||
Containment *c = dynamic_cast<Containment *>(currentWidget->topLevelItem());
|
||||
//kDebug() << "about to show" << (QObject*)c;
|
||||
if (c) {
|
||||
tipWidget->setDirection(Plasma::locationToDirection(c->location()));
|
||||
}
|
||||
|
||||
clickable = tooltip.value().isClickable();
|
||||
tipWidget->setContent(currentWidget, tooltip.value());
|
||||
tipWidget->prepareShowing();
|
||||
QGraphicsWidget *referenceWidget = tooltip.value().graphicsWidget() ? tooltip.value().graphicsWidget() : currentWidget;
|
||||
Corona *corona = qobject_cast<Corona *>(referenceWidget->scene());
|
||||
|
||||
if (corona) {
|
||||
tipWidget->moveTo(corona->popupPosition(referenceWidget, tipWidget->size(), Qt::AlignCenter));
|
||||
}
|
||||
tipWidget->show();
|
||||
isShown = true; //ToolTip is visible
|
||||
|
||||
delayedHide = tooltip.value().autohide();
|
||||
if (delayedHide) {
|
||||
//kDebug() << "starting authoide";
|
||||
hideTimer->start(3000);
|
||||
} else {
|
||||
hideTimer->stop();
|
||||
}
|
||||
}
|
||||
|
||||
void ToolTipManagerPrivate::toolTipHovered(bool hovered)
|
||||
{
|
||||
if (!clickable) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (hovered) {
|
||||
hideTimer->stop();
|
||||
} else {
|
||||
hideTimer->start(500);
|
||||
}
|
||||
}
|
||||
|
||||
bool ToolTipManager::eventFilter(QObject *watched, QEvent *event)
|
||||
{
|
||||
QGraphicsWidget * widget = dynamic_cast<QGraphicsWidget *>(watched);
|
||||
if (d->state != Activated || !widget) {
|
||||
return QObject::eventFilter(watched, event);
|
||||
}
|
||||
|
||||
switch (event->type()) {
|
||||
case QEvent::GraphicsSceneHoverMove:
|
||||
// If the tooltip isn't visible, run through showing the tooltip again
|
||||
// so that it only becomes visible after a stationary hover
|
||||
if (Plasma::ToolTipManager::self()->isVisible(widget)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Don't restart the show timer on a mouse move event if there hasn't
|
||||
// been an enter event or the current widget has been cleared by a click
|
||||
// or wheel event.
|
||||
{
|
||||
QGraphicsSceneHoverEvent *me = static_cast<QGraphicsSceneHoverEvent *>(event);
|
||||
//FIXME: seems that wheel events generate hovermoves as well, with 0 delta
|
||||
if (!d->currentWidget || (me->pos() == me->lastPos())) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
case QEvent::GraphicsSceneHoverEnter:
|
||||
{
|
||||
// Check that there is a tooltip to show
|
||||
if (!d->tooltips.contains(widget)) {
|
||||
break;
|
||||
}
|
||||
|
||||
show(widget);
|
||||
break;
|
||||
}
|
||||
|
||||
case QEvent::GraphicsSceneHoverLeave:
|
||||
if (d->currentWidget == widget) {
|
||||
d->doDelayedHide();
|
||||
}
|
||||
break;
|
||||
|
||||
case QEvent::GraphicsSceneMousePress:
|
||||
if (d->currentWidget == widget) {
|
||||
hide(widget);
|
||||
}
|
||||
break;
|
||||
|
||||
case QEvent::GraphicsSceneWheel:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return QObject::eventFilter(watched, event);
|
||||
}
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
|
||||
|
||||
#include "moc_tooltipmanager.cpp"
|
217
tooltipmanager.h
217
tooltipmanager.h
@ -1,217 +0,0 @@
|
||||
/*
|
||||
* Copyright 2007 by Dan Meltzer <hydrogen@notyetimplemented.com>
|
||||
* Copyright 2008 by Aaron Seigo <aseigo@kde.org>
|
||||
* Copyright 2008 by Alexis Ménard <darktears31@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
|
||||
*/
|
||||
|
||||
#ifndef PLASMA_TOOLTIP_MANAGER_H
|
||||
#define PLASMA_TOOLTIP_MANAGER_H
|
||||
|
||||
#include <kurl.h>
|
||||
|
||||
#include <plasma/plasma.h>
|
||||
#include <plasma/plasma_export.h>
|
||||
#include <plasma/tooltipcontent.h>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class ToolTipManagerPrivate;
|
||||
class Applet;
|
||||
class Corona;
|
||||
|
||||
/**
|
||||
* @class ToolTipManager plasma/tooltipmanager.h <Plasma/ToolTipManager>
|
||||
*
|
||||
* @short Manages tooltips for QGraphicsWidgets in Plasma
|
||||
*
|
||||
* If you want a widget to have a tooltip displayed when the mouse is hovered over
|
||||
* it, you should do something like:
|
||||
*
|
||||
* @code
|
||||
* // widget is a QGraphicsWidget*
|
||||
* Plasma::ToolTipContent data;
|
||||
* data.mainText = i18n("My Title");
|
||||
* data.subText = i18n("This is a little tooltip");
|
||||
* data.image = KDE::icon("some-icon").pixmap(IconSize(KIconLoader::Desktop));
|
||||
* Plasma::ToolTipManager::self()->setContent(widget, data);
|
||||
* @endcode
|
||||
*
|
||||
* Note that, since a Plasma::Applet is a QGraphicsWidget, you can use
|
||||
* Plasma::ToolTipManager::self()->setContent(this, data); in the
|
||||
* applet's init() method to set a tooltip for the whole applet.
|
||||
*
|
||||
* The tooltip will be registered automatically by setContent(). It will be
|
||||
* automatically unregistered when the associated widget is deleted, freeing the
|
||||
* memory used by the tooltip, but you can manually unregister it at any time by
|
||||
* calling unregisterWidget().
|
||||
*
|
||||
* When a tooltip for a widget is about to be shown, the widget's toolTipAboutToShow() slot will be
|
||||
* invoked if it exists. Similarly, when a tooltip is hidden, the widget's toolTipHidden() slot
|
||||
* will be invoked if it exists. This allows widgets to provide on-demand tooltip data.
|
||||
*/
|
||||
|
||||
class PLASMA_EXPORT ToolTipManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
enum State {
|
||||
Activated = 0 /**<< Will accept tooltip data and show tooltips */,
|
||||
Inhibited /**<< Will accept tooltip data, but not show tooltips */,
|
||||
Deactivated /**<< Will discard tooltip data, and not attempt to show them */
|
||||
};
|
||||
|
||||
/**
|
||||
* @return The singleton instance of the manager.
|
||||
*/
|
||||
static ToolTipManager *self();
|
||||
|
||||
/**
|
||||
* Show the tooltip for a widget registered in the tooltip manager
|
||||
*
|
||||
* @param widget the widget for which the tooltip will be displayed
|
||||
*/
|
||||
void show(QGraphicsWidget *widget);
|
||||
|
||||
/**
|
||||
* Find out whether the tooltip for a given widget is currently being displayed.
|
||||
*
|
||||
* @param widget the widget to check the tooltip for
|
||||
* @return true if the tooltip of the widget is currently displayed,
|
||||
* false if not
|
||||
*/
|
||||
bool isVisible(QGraphicsWidget *widget) const;
|
||||
|
||||
/**
|
||||
* Hides the tooltip for a widget immediately.
|
||||
*
|
||||
* @param widget the widget to hide the tooltip for
|
||||
*/
|
||||
void hide(QGraphicsWidget *widget);
|
||||
|
||||
/**
|
||||
* Registers a widget with the tooltip manager.
|
||||
*
|
||||
* Note that setContent() will register the widget if it
|
||||
* has not already been registered, and so you do not normally
|
||||
* need to use the method.
|
||||
*
|
||||
* This is useful for creating tooltip content on demand. You can
|
||||
* register your widget with registerWidget(), then implement
|
||||
* a slot named toolTipAboutToShow for the widget. This will be
|
||||
* called before the tooltip is shown, allowing you to set the
|
||||
* data with setContent().
|
||||
*
|
||||
* If the widget also has a toolTipHidden slot, this will be called
|
||||
* after the tooltip is hidden.
|
||||
*
|
||||
* @param widget the desired widget
|
||||
*/
|
||||
void registerWidget(QGraphicsWidget *widget);
|
||||
|
||||
/**
|
||||
* Unregisters a widget from the tooltip manager.
|
||||
*
|
||||
* This will free the memory used by the tooltip associated with the widget.
|
||||
*
|
||||
* @param widget the desired widget to delete
|
||||
*/
|
||||
void unregisterWidget(QGraphicsWidget *widget);
|
||||
|
||||
/**
|
||||
* Sets the content for the tooltip associated with a widget.
|
||||
*
|
||||
* Note that this will register the widget with the ToolTipManager if
|
||||
* necessary, so there is usually no need to call registerWidget().
|
||||
*
|
||||
* @param widget the widget the tooltip should be associated with
|
||||
* @param data the content of the tooltip. If an empty Content
|
||||
* is passed in, the tooltip content will be reset.
|
||||
*/
|
||||
void setContent(QGraphicsWidget *widget,
|
||||
const ToolTipContent &data);
|
||||
|
||||
/**
|
||||
* Clears the tooltip data associated with this widget, but keeps
|
||||
* the widget registered.
|
||||
*/
|
||||
void clearContent(QGraphicsWidget *widget);
|
||||
|
||||
/**
|
||||
* Sets the current state of the manager.
|
||||
* @see State
|
||||
* @param state the state to put the manager in
|
||||
*/
|
||||
void setState(ToolTipManager::State state);
|
||||
|
||||
/**
|
||||
* @return the current state of the manager; @see State
|
||||
*/
|
||||
ToolTipManager::State state() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
* This signal is emitted when a window preview in the tooltip is clicked.
|
||||
* @param window the id of the window that was clicked
|
||||
* @param buttons the mouse buttons involved in the activation
|
||||
* @param modifiers the keyboard modifiers involved in the activation, if any
|
||||
* @since 4.4
|
||||
*/
|
||||
void windowPreviewActivated(WId window, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers,
|
||||
const QPoint &screenPos);
|
||||
|
||||
/**
|
||||
* This signal is emitted when a link in the tooltip is clicked.
|
||||
* @param anchor the achor text (e.g. url) that was clicked on
|
||||
* @param buttons the mouse buttons involved in the activation
|
||||
* @param modifiers the keyboard modifiers involved in the activation, if any
|
||||
* @since 4.4
|
||||
*/
|
||||
void linkActivated(const QString &anchor, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers,
|
||||
const QPoint &screenPos);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Default constructor.
|
||||
*
|
||||
* You should normall use self() instead.
|
||||
*/
|
||||
explicit ToolTipManager(QObject *parent = 0);
|
||||
|
||||
/**
|
||||
* Default destructor.
|
||||
*/
|
||||
~ToolTipManager();
|
||||
|
||||
friend class ToolTipManagerSingleton;
|
||||
friend class Corona; // The corona needs to register itself
|
||||
friend class ToolTipManagerPrivate;
|
||||
bool eventFilter(QObject *watched, QEvent *event);
|
||||
|
||||
ToolTipManagerPrivate *const d;
|
||||
|
||||
Q_PRIVATE_SLOT(d, void showToolTip())
|
||||
Q_PRIVATE_SLOT(d, void toolTipHovered(bool))
|
||||
Q_PRIVATE_SLOT(d, void resetShownState())
|
||||
Q_PRIVATE_SLOT(d, void onWidgetDestroyed(QObject*))
|
||||
};
|
||||
|
||||
} // namespace Plasma
|
||||
|
||||
#endif // PLASMA_TOOL_TIP_MANAGER_H
|
Loading…
Reference in New Issue
Block a user