Merge branch 'plasma/mart/fullscreenDialog'

This commit is contained in:
Marco Martin 2012-01-09 17:49:28 +01:00
commit a95425a7d5
8 changed files with 590 additions and 35 deletions

View File

@ -1,12 +1,14 @@
project(plasmacomponents)
set(plasmacomponents_SRCS
fullscreendialog.cpp
plasmacomponentsplugin.cpp
qrangemodel.cpp
enums.cpp
qmenu.cpp
qmenuitem.cpp
kdialogproxy.cpp
../core/declarativeitemcontainer.cpp
)
INCLUDE_DIRECTORIES(
@ -19,7 +21,7 @@ qt4_automoc(${plasmacomponents_SRCS})
add_library(plasmacomponentsplugin SHARED ${plasmacomponents_SRCS})
target_link_libraries(plasmacomponentsplugin ${QT_QTCORE_LIBRARY} ${QT_QTDECLARATIVE_LIBRARY} ${QT_QTGUI_LIBRARY} ${KDE4_KDEUI_LIBRARY})
target_link_libraries(plasmacomponentsplugin ${QT_QTCORE_LIBRARY} ${QT_QTDECLARATIVE_LIBRARY} ${QT_QTGUI_LIBRARY} ${KDE4_KDEUI_LIBRARY} ${KDE4_PLASMA_LIBS})
install(TARGETS plasmacomponentsplugin DESTINATION ${IMPORTS_INSTALL_DIR}/org/kde/plasma/components)

View File

@ -0,0 +1,304 @@
/***************************************************************************
* Copyright 2012 Marco Martin <mart@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* 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 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 "fullscreendialog.h"
#include "../core/declarativeitemcontainer_p.h"
#include "plasmacomponentsplugin.h"
#include <QDeclarativeItem>
#include <QDeclarativeContext>
#include <QGraphicsObject>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsWidget>
#include <QLayout>
#include <QTimer>
#include <KWindowSystem>
#include <KStandardDirs>
#include <Plasma/Corona>
uint FullScreenDialog::s_numItems = 0;
FullScreenDialog::FullScreenDialog(QDeclarativeItem *parent)
: QDeclarativeItem(parent),
m_declarativeItemContainer(0)
{
m_view = new QGraphicsView();
m_view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_view->installEventFilter(this);
m_view->setAutoFillBackground(false);
m_view->viewport()->setAutoFillBackground(false);
m_view->setAttribute(Qt::WA_TranslucentBackground);
m_view->setAttribute(Qt::WA_NoSystemBackground);
m_view->viewport()->setAttribute(Qt::WA_NoSystemBackground);
m_view->setCacheMode(QGraphicsView::CacheNone);
m_view->setWindowFlags(m_view->windowFlags() | Qt::FramelessWindowHint | Qt::CustomizeWindowHint);
m_view->setFrameShape(QFrame::NoFrame);
KWindowSystem::setOnAllDesktops(m_view->winId(), true);
unsigned long state = NET::Sticky | NET::StaysOnTop | NET::KeepAbove | NET::SkipTaskbar | NET::SkipPager | NET::MaxVert | NET::MaxHoriz;
KWindowSystem::setState(m_view->effectiveWinId(), state);
//Try to figure out the path of the dialog component
QString componentsPlatform = getenv("KDE_PLASMA_COMPONENTS_PLATFORM");
if (componentsPlatform.isEmpty()) {
KConfigGroup cg(KSharedConfig::openConfig("kdeclarativerc"), "Components-platform");
componentsPlatform = cg.readEntry("name", "desktop");
}
QString filePath;
if (componentsPlatform == "desktop") {
foreach(const QString &importPath, KGlobal::dirs()->findDirs("module", "imports/")) {
filePath = importPath % "org/kde/plasma/components/Dialog.qml";
QFile f(filePath);
if (f.exists()) {
break;
}
}
} else {
foreach(const QString &importPath, KGlobal::dirs()->findDirs("module", "platformimports/" % componentsPlatform)) {
filePath = importPath % "org/kde/plasma/components/Dialog.qml";
QFile f(filePath);
if (f.exists()) {
break;
}
}
}
QDeclarativeEngine *engine = EngineBookKeeping::self()->engineFor(this);
QDeclarativeComponent *component = new QDeclarativeComponent(engine, filePath, this);
QDeclarativeContext *creationContext = component->creationContext();
m_rootObject = component->create(creationContext);
if (component->status() == QDeclarativeComponent::Error) {
kWarning()<<component->errors();
}
if (m_rootObject) {
setMainItem(qobject_cast<QGraphicsObject *>(m_rootObject.data()));
connect(m_rootObject.data(), SIGNAL(statusChanged()), this, SLOT(statusHasChanged()));
connect(m_rootObject.data(), SIGNAL(accepted()), this, SIGNAL(accepted()));
connect(m_rootObject.data(), SIGNAL(rejected()), this, SIGNAL(rejected()));
connect(m_rootObject.data(), SIGNAL(clickedOutside()), this, SIGNAL(clickedOutside()));
}
}
FullScreenDialog::~FullScreenDialog()
{
delete m_view;
}
QGraphicsObject *FullScreenDialog::mainItem() const
{
return m_mainItem.data();
}
void FullScreenDialog::setMainItem(QGraphicsObject *mainItem)
{
if (m_mainItem.data() != mainItem) {
if (m_mainItem) {
m_mainItem.data()->setParent(mainItem->parent());
m_mainItem.data()->removeEventFilter(this);
m_mainItem.data()->setY(0);
m_scene = 0;
}
m_mainItem = mainItem;
if (mainItem) {
mainItem->setParentItem(0);
mainItem->setParent(this);
m_scene = mainItem->scene();
}
mainItem->installEventFilter(this);
//if this is called in Compenent.onCompleted we have to wait a loop the item is added to a scene
QTimer::singleShot(0, this, SLOT(syncMainItem()));
}
}
void FullScreenDialog::syncMainItem()
{
if (!m_mainItem) {
return;
}
//not have a scene? go up in the hyerarchy until we find something with a scene
QGraphicsScene *scene = m_mainItem.data()->scene();
if (!scene) {
QObject *parent = m_mainItem.data();
while ((parent = parent->parent())) {
QGraphicsObject *qo = qobject_cast<QGraphicsObject *>(parent);
if (qo) {
scene = qo->scene();
if (scene) {
scene->addItem(m_mainItem.data());
++s_numItems;
Plasma::Corona *corona = qobject_cast<Plasma::Corona *>(scene);
QDeclarativeItem *di = qobject_cast<QDeclarativeItem *>(m_mainItem.data());
if (corona && di) {
if (!m_declarativeItemContainer) {
m_declarativeItemContainer = new DeclarativeItemContainer();
scene->addItem(m_declarativeItemContainer);
corona->addOffscreenWidget(m_declarativeItemContainer);
}
m_declarativeItemContainer->setDeclarativeItem(di);
} else {
m_mainItem.data()->setY(-10000*s_numItems);
m_mainItem.data()->setY(10000*s_numItems);
}
break;
}
}
}
}
if (!scene) {
return;
}
m_view->setScene(scene);
if (m_declarativeItemContainer) {
m_declarativeItemContainer->resize(m_view->size());
m_view->setSceneRect(m_declarativeItemContainer->geometry());
} else {
m_mainItem.data()->setProperty("width", m_view->size().width());
m_mainItem.data()->setProperty("height", m_view->size().height());
QRectF itemGeometry(QPointF(m_mainItem.data()->x(), m_mainItem.data()->y()),
QSizeF(m_mainItem.data()->boundingRect().size()));
m_view->setSceneRect(itemGeometry);
}
}
bool FullScreenDialog::isVisible() const
{
return m_view->isVisible();
}
void FullScreenDialog::setVisible(const bool visible)
{
if (m_view->isVisible() != visible) {
m_view->setVisible(visible);
if (visible) {
unsigned long state = NET::Sticky | NET::StaysOnTop | NET::KeepAbove | NET::SkipTaskbar | NET::SkipPager | NET::MaxVert | NET::MaxHoriz;
m_view->setVisible(visible);
KWindowSystem::setState(m_view->effectiveWinId(), state);
m_view->raise();
}
}
}
QDeclarativeListProperty<QGraphicsObject> FullScreenDialog::title()
{
if (m_rootObject) {
return m_rootObject.data()->property("title").value<QDeclarativeListProperty<QGraphicsObject> >();
} else {
return QDeclarativeListProperty<QGraphicsObject>(this, m_dummyTitleElements);
}
}
QDeclarativeListProperty<QGraphicsObject> FullScreenDialog::content()
{
if (m_rootObject) {
return m_rootObject.data()->property("content").value<QDeclarativeListProperty<QGraphicsObject> >();
} else {
return QDeclarativeListProperty<QGraphicsObject>(this, m_dummyContentElements);
}
}
QDeclarativeListProperty<QGraphicsObject> FullScreenDialog::buttons()
{
if (m_rootObject) {
return m_rootObject.data()->property("buttons").value<QDeclarativeListProperty<QGraphicsObject> >();
} else {
return QDeclarativeListProperty<QGraphicsObject>(this, m_dummyButtonsElements);
}
}
DialogStatus::Status FullScreenDialog::status() const
{
if (m_rootObject) {
return (DialogStatus::Status)m_rootObject.data()->property("status").toInt();
} else {
return DialogStatus::Closed;
}
}
void FullScreenDialog::statusHasChanged()
{
if (status() == DialogStatus::Closed) {
setVisible(false);
} else {
setVisible(true);
}
emit statusChanged();
}
void FullScreenDialog::open()
{
if (m_rootObject) {
QMetaObject::invokeMethod(m_rootObject.data(), "open");
}
}
void FullScreenDialog::accept()
{
if (m_rootObject) {
QMetaObject::invokeMethod(m_rootObject.data(), "accept");
}
}
void FullScreenDialog::reject()
{
if (m_rootObject) {
QMetaObject::invokeMethod(m_rootObject.data(), "reject");
}
}
void FullScreenDialog::close()
{
if (m_rootObject) {
QMetaObject::invokeMethod(m_rootObject.data(), "close");
}
}
bool FullScreenDialog::eventFilter(QObject *watched, QEvent *event)
{
if (watched == m_view &&
(event->type() == QEvent::Resize || event->type() == QEvent::Move)) {
syncMainItem();
}
return false;
}
#include "fullscreendialog.moc"

View File

@ -0,0 +1,96 @@
/***************************************************************************
* Copyright 2012 Marco Martin <mart@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* 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 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 FULLSCREENDIALOG_P
#define FULLSCREENDIALOG_P
#include <QObject>
#include <QPoint>
#include <QRect>
#include <QWeakPointer>
#include <QDeclarativeListProperty>
#include <QDeclarativeItem>
#include "enums.h"
class QGraphicsObject;
class QGraphicsView;
class QGraphicsScene;
class DeclarativeItemContainer;
class FullScreenDialog : public QDeclarativeItem
{
Q_OBJECT
Q_PROPERTY(QDeclarativeListProperty<QGraphicsObject> title READ title DESIGNABLE false)
Q_PROPERTY(QDeclarativeListProperty<QGraphicsObject> content READ content DESIGNABLE false)
Q_PROPERTY(QDeclarativeListProperty<QGraphicsObject> buttons READ buttons DESIGNABLE false)
Q_PROPERTY(DialogStatus::Status status READ status NOTIFY statusChanged)
public:
FullScreenDialog(QDeclarativeItem *parent = 0);
~FullScreenDialog();
QGraphicsObject *mainItem() const;
void setMainItem(QGraphicsObject *mainItem);
bool isVisible() const;
void setVisible(const bool visible);
//QML properties
QDeclarativeListProperty<QGraphicsObject> title();
QDeclarativeListProperty<QGraphicsObject> content();
QDeclarativeListProperty<QGraphicsObject> buttons();
DialogStatus::Status status() const;
Q_INVOKABLE void open();
Q_INVOKABLE void accept();
Q_INVOKABLE void reject();
Q_INVOKABLE void close();
Q_SIGNALS:
void accepted();
void rejected();
void clickedOutside();
void statusChanged();
private Q_SLOTS:
void syncMainItem();
void statusHasChanged();
protected:
bool eventFilter(QObject *watched, QEvent *event);
private:
QGraphicsView *m_view;
QWeakPointer<QGraphicsObject> m_mainItem;
DeclarativeItemContainer *m_declarativeItemContainer;
QGraphicsScene *m_scene;
QWeakPointer<QObject> m_rootObject;
static uint s_numItems;
//those only used in case of error, to not make plasma crash
QList<QGraphicsObject *> m_dummyTitleElements;
QList<QGraphicsObject *> m_dummyContentElements;
QList<QGraphicsObject *> m_dummyButtonsElements;
};
#endif

View File

@ -21,15 +21,65 @@
#include <QtDeclarative/qdeclarative.h>
#include <QtDeclarative/QDeclarativeEngine>
#include <QtDeclarative/QDeclarativeContext>
#include <QtDeclarative/QDeclarativeItem>
#include "qrangemodel.h"
#include <KSharedConfig>
#include <KDebug>
#include "enums.h"
#include "qmenu.h"
#include "qmenuitem.h"
#include "kdialogproxy.h"
#include "fullscreendialog.h"
Q_EXPORT_PLUGIN2(plasmacomponentsplugin, PlasmaComponentsPlugin)
class BKSingleton
{
public:
EngineBookKeeping self;
};
K_GLOBAL_STATIC(BKSingleton, privateBKSelf)
EngineBookKeeping::EngineBookKeeping()
{
}
EngineBookKeeping *EngineBookKeeping::self()
{
return &privateBKSelf->self;
}
QDeclarativeEngine *EngineBookKeeping::engineFor(QObject *item) const
{return m_engines.values().first();
foreach (QDeclarativeEngine *engine, m_engines) {
QObject *root = engine->rootContext()->contextObject();
QObject *candidate = item;
while (candidate) {
if (candidate == root) {
return engine;
}
candidate = candidate->parent();
}
}
return 0;
}
void EngineBookKeeping::insertEngine(QDeclarativeEngine *engine)
{
m_engines.insert(engine);
}
void PlasmaComponentsPlugin::initializeEngine(QDeclarativeEngine *engine, const char *uri)
{
QDeclarativeExtensionPlugin::initializeEngine(engine, uri);
EngineBookKeeping::self()->insertEngine(engine);
}
void PlasmaComponentsPlugin::registerTypes(const char *uri)
{
@ -41,11 +91,15 @@ void PlasmaComponentsPlugin::registerTypes(const char *uri)
componentsPlatform = cg.readEntry("name", "desktop");
}
//platform specific c++ components
if (componentsPlatform == "desktop") {
qmlRegisterType<KDialogProxy>(uri, 0, 1, "QueryDialog");
qmlRegisterType<QMenuProxy>(uri, 0, 1, "Menu");
qmlRegisterType<QMenuItem>(uri, 0, 1, "MenuItem");
//on touch systems the dialog is fullscreen, c++ needed to do that
} else {
qmlRegisterType<FullScreenDialog>(uri, 0, 1, "Dialog");
}
qmlRegisterType<Plasma::QRangeModel>(uri, 0, 1, "RangeModel");

View File

@ -21,15 +21,32 @@
#define PLASMACOMPONENTSPLUGIN_H
#include <QDeclarativeExtensionPlugin>
#include <QSet>
class QDeclarativeEngine;
class QDeclarativeItem;
class PlasmaComponentsPlugin;
class EngineBookKeeping
{
public:
EngineBookKeeping();
static EngineBookKeeping *self();
void insertEngine(QDeclarativeEngine *engine);
QDeclarativeEngine *engineFor(QObject *item) const;
private:
QSet <QDeclarativeEngine*> m_engines;
};
class PlasmaComponentsPlugin : public QDeclarativeExtensionPlugin
{
Q_OBJECT
public:
void initializeEngine(QDeclarativeEngine *engine, const char *uri);
void registerTypes(const char *uri);
};
Q_EXPORT_PLUGIN2(plasmacomponentsplugin, PlasmaComponentsPlugin)
#endif

View File

@ -64,58 +64,76 @@ Item {
function open()
{
var pos = dialog.popupPosition(null, Qt.alignCenter)
dialog.x = pos.x
dialog.y = pos.y
dialog.visible = true
dialog.activateWindow()
status = DialogStatus.Opening
delayOpenTimer.restart()
}
function accept()
{
if (status == DialogStatus.Open) {
dialog.visible = false
status = DialogStatus.Closing
accepted()
dialog.state = "closed"
}
}
function reject() {
function reject()
{
if (status == DialogStatus.Open) {
dialog.visible = false
status = DialogStatus.Closing
dialog.state = "closed"
rejected()
}
}
function close() {
dialog.visible = false
function close()
{
dialog.state = "closed"
}
visible: false
PlasmaCore.Dialog {
id: dialog
windowFlags: Qt.Dialog
//onFaderClicked: root.clickedOutside()
property Item rootItem
//state: "Hidden"
visible: false
onVisibleChanged: {
if (visible) {
status = DialogStatus.Open
} else {
status = DialogStatus.Closed
}
Rectangle {
id: fader
property double alpha: 0
color: Qt.rgba(0.0, 0.0, 0.0, alpha)
anchors.fill: parent
}
MouseArea {
anchors.fill: parent
onClicked: {
clickedOutside()
close()
}
onActiveWindowChanged: if (!activeWindow) dialog.visible = false
}
Timer {
id: delayOpenTimer
running: false
interval: 100
onTriggered: dialog.state = ""
}
mainItem: Item {
PlasmaCore.FrameSvgItem {
id: dialog
width: mainItem.width + margins.left + margins.right
height: mainItem.height + margins.top + margins.bottom
anchors.centerIn: parent
imagePath: "dialogs/background"
state: "closed"
transform: Translate {
id: dialogTransform
y: root.height - dialog.y
}
//state: "Hidden"
Item {
id: mainItem
x: dialog.margins.left
y: dialog.margins.top
width: theme.defaultFont.mSize.width * 40
height: titleBar.childrenRect.height + contentItem.childrenRect.height + buttonItem.childrenRect.height + 8
// Consume all key events that are not processed by children
Keys.onPressed: event.accepted = true
Keys.onReleased: event.accepted = true
@ -160,5 +178,70 @@ Item {
Component.onCompleted: {
rootItem = Utils.rootObject()
}
states: [
State {
name: "closed"
PropertyChanges {
target: dialogTransform
y: root.height - dialog.y
}
PropertyChanges {
target: fader
alpha: 0
}
},
State {
name: ""
PropertyChanges {
target: dialogTransform
y: 0
}
PropertyChanges {
target: fader
alpha: 0.6
}
}
]
transitions: [
// Transition between open and closed states.
Transition {
from: ""
to: "closed"
reversible: false
SequentialAnimation {
ScriptAction {
script: root.status = DialogStatus.Closing
}
PropertyAnimation {
properties: "y, alpha"
easing.type: Easing.InOutQuad
duration: 250
}
ScriptAction {
script: root.status = DialogStatus.Closed
}
}
},
Transition {
from: "closed"
to: ""
reversible: false
SequentialAnimation {
ScriptAction {
script: root.status = DialogStatus.Opening
}
PropertyAnimation {
properties: "y, alpha"
easing.type: Easing.InOutQuad
duration: 250
}
ScriptAction {
script: root.status = DialogStatus.Open
}
}
}
]
}
}

View File

@ -26,6 +26,7 @@
#include <QGraphicsView>
#include <QDeclarativeItem>
#include "plasmacomponentsplugin.h"
QMenuProxy::QMenuProxy (QObject *parent)
: QObject(parent),
m_status(DialogStatus::Closed)

View File

@ -81,8 +81,6 @@ CommonDialog {
property int selectedIndex: -1
property Component delegate: defaultDelegate
privateCloseIcon: true
Component {
id: defaultDelegate