diff --git a/declarativeimports/CMakeLists.txt b/declarativeimports/CMakeLists.txt index 00b54222f..5774a12b2 100644 --- a/declarativeimports/CMakeLists.txt +++ b/declarativeimports/CMakeLists.txt @@ -3,4 +3,4 @@ add_subdirectory(draganddrop) add_subdirectory(graphicslayouts) add_subdirectory(graphicswidgets) add_subdirectory(qtextracomponents) - +add_subdirectory(plasmacomponents) \ No newline at end of file diff --git a/declarativeimports/plasmacomponents/CMakeLists.txt b/declarativeimports/plasmacomponents/CMakeLists.txt new file mode 100644 index 000000000..bf0c4c280 --- /dev/null +++ b/declarativeimports/plasmacomponents/CMakeLists.txt @@ -0,0 +1,22 @@ +project(plasmacomponents) + +set(plasmacomponents_SRCS + plasmacomponentsplugin.cpp + qrangemodel.cpp + ) + +INCLUDE_DIRECTORIES( + ${CMAKE_SOURCE_DIR} + ${CMAKE_BINARY_DIR} + ${KDE4_INCLUDES} +) + +qt4_automoc(${plasmacomponents_SRCS}) + + +add_library(plasmacomponentsplugin SHARED ${plasmacomponents_SRCS}) +target_link_libraries(plasmacomponentsplugin ${QT_QTCORE_LIBRARY} ${QT_QTDECLARATIVE_LIBRARY}) + +install(TARGETS plasmacomponentsplugin DESTINATION ${IMPORTS_INSTALL_DIR}/org/kde/plasma/components) + +install(DIRECTORY qml/ DESTINATION ${IMPORTS_INSTALL_DIR}/org/kde/plasma/components) diff --git a/declarativeimports/plasmacomponents/plasmacomponentsplugin.cpp b/declarativeimports/plasmacomponents/plasmacomponentsplugin.cpp new file mode 100644 index 000000000..b1f7bd607 --- /dev/null +++ b/declarativeimports/plasmacomponents/plasmacomponentsplugin.cpp @@ -0,0 +1,36 @@ +/* + * Copyright 2011 by Marco Martin + + * 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 "plasmacomponentsplugin.h" + +#include + +#include "qrangemodel.h" + + +void PlasmaComponentsPlugin::registerTypes(const char *uri) +{ + Q_ASSERT(uri == QLatin1String("org.kde.plasma.components")); + + qmlRegisterType(uri, 0, 1, "RangeModel"); +} + + +#include "plasmacomponentsplugin.moc" + diff --git a/declarativeimports/plasmacomponents/plasmacomponentsplugin.h b/declarativeimports/plasmacomponents/plasmacomponentsplugin.h new file mode 100644 index 000000000..65ca8bdca --- /dev/null +++ b/declarativeimports/plasmacomponents/plasmacomponentsplugin.h @@ -0,0 +1,35 @@ +/* + * Copyright 2011 by Marco Martin + + * 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 PLASMACOMPONENTSPLUGIN_H +#define PLASMACOMPONENTSPLUGIN_H + +#include + +class PlasmaComponentsPlugin : public QDeclarativeExtensionPlugin +{ + Q_OBJECT + +public: + void registerTypes(const char *uri); +}; + +Q_EXPORT_PLUGIN2(plasmacomponentsplugin, PlasmaComponentsPlugin) + +#endif diff --git a/declarativeimports/plasmacomponents/qml/BusyIndicator.qml b/declarativeimports/plasmacomponents/qml/BusyIndicator.qml new file mode 100644 index 000000000..5335d4328 --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/BusyIndicator.qml @@ -0,0 +1,64 @@ +/* +* Copyright (C) 2010 by Artur Duque de Souza +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* 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. +*/ + +import QtQuick 1.1 +import org.kde.plasma.core 0.1 as PlasmaCore + +Item { + id: busy + + // Common API + property bool running: false + + // Plasma API + property bool smoothAnimation: true + + implicitWidth: 52 + implicitHeight: 52 + + // Should use animation's pause to keep the + // rotation smooth when running changes but + // it has lot's of side effects on + // initialization. + onRunningChanged: { + rotationAnimation.from = rotation; + rotationAnimation.to = rotation + 360; + } + + RotationAnimation on rotation { + id: rotationAnimation + + from: 0 + to: 360 + duration: 1500 + running: busy.running + loops: Animation.Infinite + } + + PlasmaCore.SvgItem { + id: widget + + anchors.centerIn: parent + width: busy.width + height: busy.height + smooth: !running || smoothAnimation + svg: PlasmaCore.Svg { imagePath: "widgets/busywidget" } + } +} diff --git a/declarativeimports/plasmacomponents/qml/Button.qml b/declarativeimports/plasmacomponents/qml/Button.qml new file mode 100644 index 000000000..48bb71791 --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/Button.qml @@ -0,0 +1,191 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* 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. +*/ + +import QtQuick 1.0 +import org.kde.plasma.core 0.1 as PlasmaCore + +Item { + id: button + + // Commmon API + property bool checked: false + property bool checkable: false + property alias pressed: mouse.pressed + property alias text: label.text + property alias iconSource: icon.source + property alias font: label.font + + signal clicked() + + // Plasma API + property QtObject theme: PlasmaCore.Theme { } + + function pressButton() { + if (button.enabled) + surface.prefix = "pressed"; + } + + function releaseButton() { + if (!button.enabled) + return; + + if (button.checkable) + button.checked = !button.checked; + + // TODO: "checked" state must have special graphics? + if (button.checked) + surface.prefix = "pressed"; + else + surface.prefix = "normal"; + + button.clicked(); + button.forceActiveFocus(); + } + + width: 50 + height: 20 + // TODO: needs to define if there will be specific graphics for + // disabled buttons + opacity: enabled ? 1.0 : 0.5 + + Keys.onSpacePressed: pressButton(); + Keys.onReturnPressed: pressButton(); + Keys.onReleased: { + if (event.key == Qt.Key_Space || + event.key == Qt.Key_Return) + releaseButton(); + } + + onActiveFocusChanged: { + if (activeFocus) { + shadow.opacity = 0; + hover.opacity = 1; + }else { + shadow.opacity = 1; + hover.opacity = 0; + } + } + + PlasmaCore.FrameSvgItem { + id: hover + + anchors.fill: parent + opacity: 0 + anchors.leftMargin: -margins.left + anchors.topMargin: -margins.top + anchors.rightMargin: -margins.right + anchors.bottomMargin: -margins.bottom + imagePath: "widgets/button" + prefix: "hover" + + Behavior on opacity { + PropertyAnimation { duration: 250 } + } + } + + PlasmaCore.FrameSvgItem { + id: shadow + + anchors { + fill: parent + leftMargin: -margins.left + topMargin: -margins.top + rightMargin: -margins.right + bottomMargin: -margins.bottom + } + imagePath: "widgets/button" + prefix: "shadow" + + Behavior on opacity { + PropertyAnimation { duration: 250 } + } + } + + PlasmaCore.FrameSvgItem { + id: surface + + anchors.fill: parent + imagePath: "widgets/button" + prefix: "normal" + } + + Item { + anchors { + fill: parent + leftMargin: surface.margins.left + topMargin: surface.margins.top + rightMargin: surface.margins.right + bottomMargin: surface.margins.bottom + } + + Image { + id: icon + + anchors { + fill: label.text ? undefined : parent + top: label.text ? parent.top : undefined + left: label.text ? parent.left : undefined + bottom: label.text ? parent.bottom : undefined + } + fillMode: Image.PreserveAspectFit + } + + Text { + id: label + + anchors { + top: parent.top + bottom: parent.bottom + left: icon.right + right: parent.right + } + color: theme.buttonTextColor + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + } + + MouseArea { + id: mouse + + anchors.fill: parent + hoverEnabled: true + + onPressed: { + pressButton(); + } + onReleased: { + releaseButton(); + } + onEntered: { + shadow.opacity = 0; + hover.opacity = 1; + } + onExited: { + if (button.activeFocus) { + shadow.opacity = 0; + hover.opacity = 1; + } else { + shadow.opacity = 1; + hover.opacity = 0; + } + } + } +} + diff --git a/declarativeimports/plasmacomponents/qml/ButtonColumn.qml b/declarativeimports/plasmacomponents/qml/ButtonColumn.qml new file mode 100644 index 000000000..752481c26 --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/ButtonColumn.qml @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Components project. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import Qt 4.7 +import "ButtonGroup.js" as Behavior + +/* + Class: ButtonColumn + A ButtonColumn allows you to group Buttons in a column. It provides a selection-behavior as well. + + Note: This component don't support the enabled property. + If you need to disable it you should disable all the buttons inside it. + + + ButtonColumn { + Button { text: "Top" } + Button { text: "Bottom" } + } + +*/ +Column { + id: root + + /* + * Property: exclusive + * [bool=true] Specifies the grouping behavior. If enabled, the checked property on buttons contained + * in the group will be exclusive. + * + * Note that a button in an exclusive group will allways be checkable + */ + property bool exclusive: true + + /* + * Property: checkedButton + * [string] Contains the last checked Button. + */ + property Item checkedButton; + + Component.onCompleted: { + Behavior.create(root, {direction: Qt.Vertical}); + } + + Component.onDestruction: { + Behavior.destroy(); + } + +} diff --git a/declarativeimports/plasmacomponents/qml/ButtonGroup.js b/declarativeimports/plasmacomponents/qml/ButtonGroup.js new file mode 100644 index 000000000..ea8ca7485 --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/ButtonGroup.js @@ -0,0 +1,178 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Components project. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +var self; +var checkHandlers = []; +var visibleButtons = []; +var nonVisibleButtons = []; +var direction; + +function create(that, options) { + self = that; + direction = options.direction || Qt.Horizontal; + self.childrenChanged.connect(rebuild); +// self.widthChanged.connect(resizeChildren); + build(); +} + +function isButton(item) { + if (item && item.hasOwnProperty("__position")) + return true; + return false; +} + +function hasChecked(item) { + return (item && item.hasOwnProperty("checked")); +} + +function destroy() { + self.childrenChanged.disconnect(rebuild); +// self.widthChanged.disconnect(resizeChildren); + cleanup(); +} + +function build() { + visibleButtons = []; + nonVisibleButtons = []; + + for (var i = 0, item; (item = self.children[i]); i++) { + if (!hasChecked(item)) + continue; + + item.visibleChanged.connect(rebuild); // Not optimal, but hardly a bottleneck in your app + if (!item.visible) { + nonVisibleButtons.push(item); + continue; + } + visibleButtons.push(item); + + if (self.exclusive && item.hasOwnProperty("checkable")) + item.checkable = true; + + if (self.exclusive) { + item.checked = false; + checkHandlers.push(checkExclusive(item)); + item.checkedChanged.connect(checkHandlers[checkHandlers.length - 1]); + } + } + + var nrButtons = visibleButtons.length; + if (nrButtons == 0) + return; + + if (self.checkedButton) + self.checkedButton.checked = true; + else if (self.exclusive) { + self.checkedButton = visibleButtons[0]; + self.checkedButton.checked = true; + } + + if (nrButtons == 1) { + finishButton(visibleButtons[0], "only"); + } else { + finishButton(visibleButtons[0], direction == Qt.Horizontal ? "leftmost" : "top"); + for (var i = 1; i < nrButtons - 1; i++) + finishButton(visibleButtons[i], direction == Qt.Horizontal ? "h_middle": "v_middle"); + finishButton(visibleButtons[nrButtons - 1], direction == Qt.Horizontal ? "rightmost" : "bottom"); + } +} + +function finishButton(button, position) { + if (isButton(button)) { + button.__position = position; + if (direction == Qt.Vertical) { + button.anchors.left = self.left //mm How to make this not cause binding loops? see QTBUG-17162 + button.anchors.right = self.right + } + } +} + +function cleanup() { + visibleButtons.forEach(function(item, i) { + if (checkHandlers[i]) + item.checkedChanged.disconnect(checkHandlers[i]); + item.visibleChanged.disconnect(rebuild); + }); + checkHandlers = []; + + nonVisibleButtons.forEach(function(item, i) { + item.visibleChanged.disconnect(rebuild); + }); +} + +function rebuild() { + if (self == undefined) + return; + + cleanup(); + build(); +} + +function resizeChildren() { + if (direction != Qt.Horizontal) + return; + + var extraPixels = self.width % visibleButtons; + var buttonSize = (self.width - extraPixels) / visibleButtons; + visibleButtons.forEach(function(item, i) { + if (!item || !item.visible) + return; + item.width = buttonSize + (extraPixels > 0 ? 1 : 0); + if (extraPixels > 0) + extraPixels--; + }); +} + +function checkExclusive(item) { + var button = item; + return function() { + for (var i = 0, ref; (ref = visibleButtons[i]); i++) { + if (ref.checked == (button === ref)) + continue; + + // Disconnect the signal to avoid recursive calls + ref.checkedChanged.disconnect(checkHandlers[i]); + ref.checked = !ref.checked; + ref.checkedChanged.connect(checkHandlers[i]); + } + self.checkedButton = button; + } +} diff --git a/declarativeimports/plasmacomponents/qml/ButtonRow.qml b/declarativeimports/plasmacomponents/qml/ButtonRow.qml new file mode 100644 index 000000000..e88b015d4 --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/ButtonRow.qml @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Components project. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import "ButtonGroup.js" as Behavior + +/* + Class: ButtonRow + A ButtonRow allows you to group Buttons in a row. It provides a selection-behavior as well. + + Note: This component don't support the enabled property. + If you need to disable it you should disable all the buttons inside it. + + + ButtonRow { + Button { text: "Left" } + Button { text: "Right" } + } + +*/ +Row { + id: root + + /* + * Property: exclusive + * [bool=true] Specifies the grouping behavior. If enabled, the checked property on buttons contained + * in the group will be exclusive. + * + * Note that a button in an exclusive group will allways be checkable + */ + property bool exclusive: true + + /* + * Property: checkedButton + * [string] Contains the last checked Button. + */ + property Item checkedButton; + + Component.onCompleted: { + Behavior.create(root, {direction: Qt.Horizontal}); + } + + Component.onDestruction: { + Behavior.destroy(); + } +} diff --git a/declarativeimports/plasmacomponents/qml/CheckBox.qml b/declarativeimports/plasmacomponents/qml/CheckBox.qml new file mode 100644 index 000000000..3191d32fa --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/CheckBox.qml @@ -0,0 +1,46 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* 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. +*/ + +import QtQuick 1.0 +import org.kde.plasma.core 0.1 as PlasmaCore + +DualStateButton { + id: checkBox + view: PlasmaCore.FrameSvgItem { + imagePath: "widgets/button" + prefix: "normal" + width: 16 + height: 16 + PlasmaCore.SvgItem { + svg: PlasmaCore.Svg { + id: checkmarkSvg + imagePath: "widgets/checkmarks" + } + elementId: "checkbox" + opacity: checked ? 1 : 0 + anchors.fill: parent + Behavior on opacity { + NumberAnimation { + duration: 250 + easing.type: Easing.InOutQuad + } + } + } + } +} \ No newline at end of file diff --git a/declarativeimports/plasmacomponents/qml/DualStateButton.qml b/declarativeimports/plasmacomponents/qml/DualStateButton.qml new file mode 100644 index 000000000..c8613fea2 --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/DualStateButton.qml @@ -0,0 +1,143 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* 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. +*/ + +import QtQuick 1.0 +import org.kde.plasma.core 0.1 as PlasmaCore + +Item { + id: dualButton + + // Common API + property bool checked + property alias pressed: mouseArea.pressed + + signal clicked() + + // Plasma API + property alias text: label.text // TODO: Not yet part of the common API + property QtObject theme: PlasmaCore.Theme { } + property alias view: surface.sourceComponent + + width: surface.width + label.paintedWidth + height: surface.height + // TODO: needs to define if there will be specific graphics for + // disabled buttons + opacity: dualButton.enabled ? 1.0 : 0.5 + + function entered() { + if (dualButton.enabled) { + shadow.opacity = 0; + hover.opacity = 1; + } + } + + function released() { + if (dualButton.enabled) { + dualButton.checked = !dualButton.checked; + dualButton.clicked(); + } + } + + Keys.onSpacePressed: entered(); + Keys.onReturnPressed: entered(); + Keys.onReleased: { + if(event.key == Qt.Key_Space || + event.key == Qt.Key_Return) + released(); + } + + PlasmaCore.FrameSvgItem { + id: hover + + anchors { + fill: surface + leftMargin: -margins.left + topMargin: -margins.top + rightMargin: -margins.right + bottomMargin: -margins.bottom + } + opacity: 0 + imagePath: "widgets/button" + prefix: "hover" + + Behavior on opacity { + PropertyAnimation { duration: 250 } + } + } + + PlasmaCore.FrameSvgItem { + id: shadow + + anchors { + fill: surface + leftMargin: -margins.left + topMargin: -margins.top + rightMargin: -margins.right + bottomMargin: -margins.bottom + } + imagePath: "widgets/button" + prefix: "shadow" + + Behavior on opacity { + PropertyAnimation { duration: 250 } + } + } + + Loader { + id: surface + + anchors { + verticalCenter: parent.verticalCenter + left: text ? parent.left : undefined + horizontalCenter: text ? undefined : parent.horizontalCenter + } + } + + Text { + id: label + + text: dualButton.text + anchors { + top: parent.top + bottom: parent.bottom + left: surface.right + right: parent.right + // XXX: see how this margin will be set + leftMargin: hover.margins.right + } + color: theme.textColor + verticalAlignment: Text.AlignVCenter + } + + MouseArea { + id: mouseArea + + anchors.fill: parent + hoverEnabled: true + + onReleased: dualButton.released(); + onEntered: dualButton.entered(); + onPressed: dualButton.forceActiveFocus(); + onExited: { + shadow.opacity = 1; + hover.opacity = 0; + } + } +} + diff --git a/declarativeimports/plasmacomponents/qml/Highlight.qml b/declarativeimports/plasmacomponents/qml/Highlight.qml new file mode 100644 index 000000000..9670c2837 --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/Highlight.qml @@ -0,0 +1,49 @@ +/* + * Copyright 2011 Daker Fernandes Pinheiro + * + * 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. + */ +import QtQuick 1.1 +import org.kde.plasma.core 0.1 as PlasmaCore + +Item { + id: highlight + + property bool hover: false + property bool pressed: false + + PlasmaCore.FrameSvgItem { + id: background + imagePath: "widgets/viewitem" + prefix: { + if (pressed) + return hover ? "selected+hover" : "selected"; + + if (hover) + return "hover"; + + return "normal"; + } + + anchors { + fill: parent + topMargin: -background.margins.top + leftMargin: -background.margins.left + bottomMargin: -background.margins.bottom + rightMargin: -background.margins.right + } + } +} diff --git a/declarativeimports/plasmacomponents/qml/ProgressBar.qml b/declarativeimports/plasmacomponents/qml/ProgressBar.qml new file mode 100644 index 000000000..efce6f20f --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/ProgressBar.qml @@ -0,0 +1,99 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* 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. +*/ + +import QtQuick 1.0 +import org.kde.plasma.core 0.1 as PlasmaCore + +Item { + id: progressBar + + // Common API + property alias minimumValue: range.minimumValue + property alias maximumValue: range.maximumValue + property alias value: range.value + property alias indeterminate: indeterminateAnimation.running + + // Plasma API + property int orientation: Qt.Horizontal + + // Convinience API + property bool _isVertical: orientation == Qt.Vertical + + width: 100 + height: 20 + opacity: enabled ? 1.0 : 0.5 + + RangeModel { + id: range + + // default values + minimumValue: 0.0 + maximumValue: 1.0 + value: 0 + + positionAtMinimum: 0 + positionAtMaximum: contents.width + } + + Item { + id: contents + + width: _isVertical ? progressBar.height : progressBar.width + height: _isVertical ? progressBar.width : progressBar.height + rotation: _isVertical ? 90 : 0 + anchors.centerIn: parent + + PlasmaCore.FrameSvgItem { + id: background + + anchors.fill: parent + imagePath: "widgets/bar_meter_horizontal" + prefix: "bar-inactive" + } + + PlasmaCore.FrameSvgItem { + id: bar + + width: indeterminate ? contents.width / 4 : range.position + height: contents.height + imagePath: "widgets/bar_meter_horizontal" + prefix: "bar-active" + visible: indeterminate || value > 0 + + SequentialAnimation { + id: indeterminateAnimation + + loops: Animation.Infinite + + PropertyAnimation { + target: bar; + property: "x" + duration: 800 + to: 0 + } + PropertyAnimation { + target: bar; + property: "x" + duration: 800 + to: background.width - bar.width + } + } + } + } +} \ No newline at end of file diff --git a/declarativeimports/plasmacomponents/qml/RadioButton.qml b/declarativeimports/plasmacomponents/qml/RadioButton.qml new file mode 100644 index 000000000..de14324c5 --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/RadioButton.qml @@ -0,0 +1,48 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* 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. +*/ + +import QtQuick 1.0 +import org.kde.plasma.core 0.1 as PlasmaCore + + +//FIXME: this should be round, DualStateButton shouldn't draw the shadow +DualStateButton { + id: radioButton + view: PlasmaCore.FrameSvgItem { + imagePath: "widgets/button" + prefix: "normal" + width: 16 + height: 16 + PlasmaCore.SvgItem { + svg: PlasmaCore.Svg { + id: checkmarkSvg + imagePath: "widgets/checkmarks" + } + elementId: "radiobutton" + opacity: checked ? 1 : 0 + anchors.fill: parent + Behavior on opacity { + NumberAnimation { + duration: 250 + easing.type: Easing.InOutQuad + } + } + } + } +} \ No newline at end of file diff --git a/declarativeimports/plasmacomponents/qml/ScrollBar.qml b/declarativeimports/plasmacomponents/qml/ScrollBar.qml new file mode 100644 index 000000000..8adc8b615 --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/ScrollBar.qml @@ -0,0 +1,349 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* 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. +*/ + +import QtQuick 1.1 +import org.kde.plasma.core 0.1 as PlasmaCore + +// TODO: add support mouse wheel and key events +Item { + id: scrollbar + + // Common API + property Flickable flickableItem: null + + // Plasma API + property int orientation: Qt.Horizontal + property bool animated: true + property bool inverted: false + property bool updateValueWhileDragging: true + property alias stepSize: range.stepSize + property alias pressed: mouseArea.pressed + property real scrollButtonInterval: 50 + + // Convinience API + property bool _isVertical: orientation == Qt.Vertical + property bool _showButtons: stepSize != 0 + property bool _inverted: _isVertical ? + !scrollbar.inverted : scrollbar.inverted + + implicitWidth: _isVertical ? 22 : 200 + implicitHeight: _isVertical ? 200 : 22 + // TODO: needs to define if there will be specific graphics for + // disabled scroll bars + opacity: enabled ? 1.0 : 0.5 + + visible: flickableItem && handle.width < contents.width + + function incrementValue(increment) { + if (!flickableItem) + return; + + if (_isVertical) { + flickableItem.contentY = Math.min(flickableItem.contentHeight, + flickableItem.contentY + increment); + } else { + flickableItem.contentX = Math.min(flickableItem.contentWidth, + flickableItem.contentX + increment); + } + } + + Keys.onUpPressed: { + if (!enabled || !_isVertical) + return; + + if (_inverted) + incrementValue(-stepSize); + else + incrementValue(stepSize); + } + + Keys.onDownPressed: { + if (!enabled || !_isVertical) + return; + + if (_inverted) + incrementValue(stepSize); + else + incrementValue(-stepSize); + } + + Keys.onLeftPressed: { + if (!enabled || _isVertical) + return; + + if (_inverted) + incrementValue(stepSize); + else + incrementValue(-stepSize); + } + + Keys.onRightPressed: { + if (!enabled || _isVertical) + return; + + if (_inverted) + incrementValue(-stepSize); + else + incrementValue(stepSize); + } + + + Item { + + width: _isVertical ? scrollbar.height : scrollbar.width + height: _isVertical ? scrollbar.width : scrollbar.height + rotation: _isVertical ? -90 : 0 + + anchors.centerIn: parent + PlasmaCore.Svg { + id: scrollbarSvg + imagePath: "widgets/scrollbar" + } + + PlasmaCore.SvgItem { + id: leftButton + + anchors { + left: parent.left + verticalCenter: parent.verticalCenter + } + height: 18 + width: _showButtons ? 18 : 0 + svg: scrollbarSvg + elementId: { + if (leftMousArea.pressed) + return "sunken-arrow-left"; + + if (scrollbar.activeFocus || leftMousArea.containsMouse) + return "mouseover-arrow-left"; + else + return "arrow-left"; + } + + MouseArea { + id: leftMousArea + + anchors.fill: parent + enabled: scrollbar.enabled + Timer { + id: leftTimer + interval: scrollbar.scrollButtonInterval; + running: parent.pressed + repeat: true + onTriggered: { + scrollbar.forceActiveFocus(); + if (_inverted) + incrementValue(stepSize); + else + incrementValue(-stepSize); + } + } + } + } + + PlasmaCore.SvgItem { + id: rightButton + + anchors { + right: parent.right + verticalCenter: parent.verticalCenter + } + height: 18 + width: _showButtons ? 18 : 0 + svg: scrollbarSvg + elementId: { + if (rightMousArea.pressed) + return "sunken-arrow-right"; + + if (scrollbar.activeFocus || rightMousArea.containsMouse) + return "mouseover-arrow-right"; + else + return "arrow-right"; + } + + MouseArea { + id: rightMousArea + + anchors.fill: parent + enabled: scrollbar.enabled + Timer { + id: rightTimer + interval: scrollbar.scrollButtonInterval; + running: parent.pressed; + repeat: true + onTriggered: { + scrollbar.forceActiveFocus(); + if (_inverted) + incrementValue(-stepSize); + else + incrementValue(stepSize); + } + } + } + } + + Item { + id: contents + + anchors { + left: leftButton.right + top: parent.top + bottom: parent.bottom + right: rightButton.left + } + + RangeModel { + id: range + + minimumValue: 0 + maximumValue: { + var diff; + if (_isVertical) + diff = flickableItem.contentHeight - flickableItem.height; + else + diff = flickableItem.contentWidth - flickableItem.width; + + return Math.max(0, diff); + } + stepSize: 0.0 + inverted: _inverted + positionAtMinimum: 0 + handle.width / 2 + positionAtMaximum: contents.width - handle.width / 2 + value: _isVertical ? flickableItem.contentY : flickableItem.contentX + onValueChanged: { + if (flickableItem.flicking) + return; + + if (_isVertical) + flickableItem.contentY = value; + else + flickableItem.contentX = value; + } + position: handle.x + onPositionChanged: { handle.x = position; } + } + + PlasmaCore.FrameSvgItem { + id: groove + + anchors.fill: parent + imagePath: "widgets/scrollbar" + prefix: "background-horizontal" + } + + PlasmaCore.FrameSvgItem { + id: handle + + transform: Translate { x: - handle.width / 2 } + x: fakeHandle.x + anchors.verticalCenter: groove.verticalCenter + width: { + var ratio; + if (_isVertical) + ratio = flickableItem.visibleArea.heightRatio; + else + ratio = flickableItem.visibleArea.widthRatio; + + return ratio * parent.width; + } + height: parent.height - margins.top // TODO: check mergin + imagePath: "widgets/scrollbar" + prefix: { + if (scrollbar.pressed) + return "sunken-slider"; + + if (scrollbar.activeFocus || mouseArea.containsMouse) + return "mouseover-slider"; + else + return "slider"; + } + + Behavior on x { + id: behavior + enabled: !mouseArea.drag.active && scrollbar.animated && + !flickableItem.flicking + + PropertyAnimation { + duration: behavior.enabled ? 150 : 0 + easing.type: Easing.OutSine + } + } + } + + Item { + id: fakeHandle + width: handle.width + height: handle.height + transform: Translate { x: - handle.width / 2 } + } + + MouseArea { + id: mouseArea + + anchors.fill: parent + enabled: scrollbar.enabled + drag { + target: fakeHandle + axis: Drag.XAxis + minimumX: range.positionAtMinimum + maximumX: range.positionAtMaximum + } + + onPressed: { + // Clamp the value + var newX = Math.max(mouse.x, drag.minimumX); + newX = Math.min(newX, drag.maximumX); + + // Debounce the press: a press event inside the handler will not + // change its position, the user needs to drag it. + if (Math.abs(newX - fakeHandle.x) > handle.width / 2) + range.position = newX; + + scrollbar.forceActiveFocus(); + } + onReleased: { + // If we don't update while dragging, this is the only + // moment that the range is updated. + if (!scrollbar.updateValueWhileDragging) + range.position = fakeHandle.x; + } + } + } + + // Range position normally follow fakeHandle, except when + // 'updateValueWhileDragging' is false. In this case it will only follow + // if the user is not pressing the handle. + Binding { + when: updateValueWhileDragging || !mouseArea.pressed + target: range + property: "position" + value: fakeHandle.x + } + + // During the drag, we simply ignore position set from the range, this + // means that setting a value while dragging will not "interrupt" the + // dragging activity. + Binding { + when: !mouseArea.drag.active + target: fakeHandle + property: "x" + value: range.position + } + } +} diff --git a/declarativeimports/plasmacomponents/qml/ScrollDecorator.qml b/declarativeimports/plasmacomponents/qml/ScrollDecorator.qml new file mode 100644 index 000000000..5ef663828 --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/ScrollDecorator.qml @@ -0,0 +1,126 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* 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. +*/ + +import QtQuick 1.1 +import org.kde.plasma.core 0.1 as PlasmaCore + +Item { + id: scrollDecorator + + // Common API + property Flickable flickableItem: null + + // Plasma API + property int orientation: Qt.Horizontal + property bool inverted: false + + // Convinience API + property bool _isVertical: orientation == Qt.Vertical + property bool _inverted: _isVertical ? + !scrollDecorator.inverted : scrollDecorator.inverted + property alias _value: range.value + + implicitWidth: _isVertical ? 22 : 200 + implicitHeight: _isVertical ? 200 : 22 + + visible: flickableItem && handle.width < contents.width + + Item { + width: _isVertical ? scrollDecorator.height : scrollDecorator.width + height: _isVertical ? scrollDecorator.width : scrollDecorator.height + rotation: _isVertical ? -90 : 0 + + anchors.centerIn: parent + + PlasmaCore.Svg { + id: scrollDecoratorSvg + imagePath: "widgets/scrollDecorator" + } + + Item { + id: contents + + anchors.fill: parent + + RangeModel { + id: range + + minimumValue: 0 + maximumValue: { + var diff; + if (_isVertical) + diff = flickableItem.contentHeight - flickableItem.height; + else + diff = flickableItem.contentWidth - flickableItem.width; + + return Math.max(0, diff); + } + stepSize: 0.0 + inverted: _inverted + positionAtMinimum: 0 + handle.width / 2 + positionAtMaximum: contents.width - handle.width / 2 + value: _isVertical ? flickableItem.contentY : flickableItem.contentX + } + + PlasmaCore.FrameSvgItem { + id: handle + + x: range.position + transform: Translate { x: - handle.width / 2 } + anchors.verticalCenter: parent.verticalCenter + width: { + var ratio; + if (_isVertical) + ratio = flickableItem.visibleArea.heightRatio; + else + ratio = flickableItem.visibleArea.widthRatio; + + return ratio * parent.width; + } + height: parent.height - margins.top // TODO: check mergin + imagePath: "widgets/scrollbar" + prefix: "slider" + opacity: flickableItem && flickableItem.flicking ? 1 : 0 + + Connections { + target: flickableItem + onMovementStarted: handle.opacity = 1 + onMovementEnded: opacityAnimation.start() + } + + Behavior on x { + PropertyAnimation { + duration: 150 + easing.type: Easing.OutSine + } + } + + PropertyAnimation { + id: opacityAnimation + + target: handle + property: "opacity" + from: 1; to: 0 + duration: 500 + easing.type: Easing.Linear + } + } + } + } +} \ No newline at end of file diff --git a/declarativeimports/plasmacomponents/qml/Slider.qml b/declarativeimports/plasmacomponents/qml/Slider.qml new file mode 100644 index 000000000..1931abf2b --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/Slider.qml @@ -0,0 +1,257 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* 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. +*/ + +import QtQuick 1.0 +import org.kde.plasma.core 0.1 as PlasmaCore + +// TODO: create a value indicator for plasma? +Item { + id: slider + + // Common API + property alias stepSize: range.stepSize + property alias minimumValue: range.minimumValue + property alias maximumValue: range.maximumValue + property alias value: range.value + property int orientation: Qt.Horizontal + property alias pressed: mouseArea.pressed + property bool valueIndicatorVisible: false + property string valueIndicatorText: value + + // Plasma API + property bool animated: false + property alias inverted: range.inverted + property bool updateValueWhileDragging: true + property real handleSize: 22 + + // Convinience API + property bool _isVertical: orientation == Qt.Vertical + + width: _isVertical ? 22 : 200 + height: _isVertical ? 200 : 22 + // TODO: needs to define if there will be specific graphics for + // disabled sliders + opacity: enabled ? 1.0 : 0.5 + + Keys.onUpPressed: { + if (!enabled || !_isVertical) + return; + + if (inverted) + value -= stepSize; + else + value += stepSize; + } + + Keys.onDownPressed: { + if (!enabled || !enabled) + return; + + if (!_isVertical) + return; + + if (inverted) + value += stepSize; + else + value -= stepSize; + } + + Keys.onLeftPressed: { + if (!enabled || _isVertical) + return; + + if (inverted) + value += stepSize; + else + value -= stepSize; + } + + Keys.onRightPressed: { + if (!enabled || _isVertical) + return; + + if (inverted) + value -= stepSize; + else + value += stepSize; + } + + Item { + id: contents + + width: _isVertical ? slider.height : slider.width + height: _isVertical ? slider.width : slider.height + rotation: _isVertical ? -90 : 0 + + anchors.centerIn: parent + + RangeModel { + id: range + + minimumValue: 0.0 + maximumValue: 1.0 + value: 0 + stepSize: 0.0 + inverted: false + positionAtMinimum: 0 + handle.width / 2 + positionAtMaximum: contents.width - handle.width / 2 + } + + PlasmaCore.SvgItem { + id: groove + + anchors { + left: parent.left + right: parent.right + verticalCenter: parent.verticalCenter + } + height: 3 + svg: PlasmaCore.Svg { imagePath: "widgets/slider" } + elementId: "horizontal-slider-line" + } + + PlasmaCore.SvgItem { + id: focus + + transform: Translate { x: - handle.width / 2 } + anchors { + fill: handle + margins: -1 // Hardcoded + } + opacity: slider.activeFocus ? 1 : 0 + svg: PlasmaCore.Svg { imagePath: "widgets/slider" } + elementId: "horizontal-slider-hover" + + Behavior on opacity { + PropertyAnimation { duration: 250 } + } + } + + PlasmaCore.SvgItem { + id: hover + + transform: Translate { x: - handle.width / 2 } + anchors { + fill: handle + margins: -2 // Hardcoded + } + opacity: 0 + svg: PlasmaCore.Svg { imagePath: "widgets/slider" } + elementId: "horizontal-slider-hover" + + Behavior on opacity { + PropertyAnimation { duration: 250 } + } + } + + PlasmaCore.SvgItem { + id: handle + + transform: Translate { x: - handle.width / 2 } + x: fakeHandle.x + anchors { + verticalCenter: groove.verticalCenter + } + width: handleSize + height: handleSize + svg: PlasmaCore.Svg { imagePath: "widgets/slider" } + elementId: "horizontal-slider-handle" + + Behavior on x { + id: behavior + enabled: !mouseArea.drag.active && slider.animated + + PropertyAnimation { + duration: behavior.enabled ? 150 : 0 + easing.type: Easing.OutSine + } + } + } + + Item { + id: fakeHandle + width: handle.width + height: handle.height + transform: Translate { x: - handle.width / 2 } + } + + MouseArea { + id: mouseArea + + anchors.fill: parent + enabled: slider.enabled + drag { + target: fakeHandle + axis: Drag.XAxis + minimumX: range.positionAtMinimum + maximumX: range.positionAtMaximum + } + hoverEnabled: true + + onEntered: { + hover.opacity = 1; + } + onExited: { + if (!pressed) + hover.opacity = 0; + } + onPressed: { + // Clamp the value + var newX = Math.max(mouse.x, drag.minimumX); + newX = Math.min(newX, drag.maximumX); + + // Debounce the press: a press event inside the handler will not + // change its position, the user needs to drag it. + if (Math.abs(newX - fakeHandle.x) > handle.width / 2) + range.position = newX; + + slider.forceActiveFocus(); + } + onReleased: { + // If we don't update while dragging, this is the only + // moment that the range is updated. + if (!slider.updateValueWhileDragging) + range.position = fakeHandle.x; + + if (!containsMouse) + hover.opacity = 0; + } + } + } + + // Range position normally follow fakeHandle, except when + // 'updateValueWhileDragging' is false. In this case it will only follow + // if the user is not pressing the handle. + Binding { + when: updateValueWhileDragging || !mouseArea.pressed + target: range + property: "position" + value: fakeHandle.x + } + + // During the drag, we simply ignore position set from the range, this + // means that setting a value while dragging will not "interrupt" the + // dragging activity. + Binding { + when: !mouseArea.drag.active + target: fakeHandle + property: "x" + value: range.position + } +} \ No newline at end of file diff --git a/declarativeimports/plasmacomponents/qml/Switch.qml b/declarativeimports/plasmacomponents/qml/Switch.qml new file mode 100644 index 000000000..7b7bf1815 --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/Switch.qml @@ -0,0 +1,45 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* 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. +*/ + +import QtQuick 1.0 +import org.kde.plasma.core 0.1 as PlasmaCore + +DualStateButton { + id: switchItem + view: PlasmaCore.FrameSvgItem { + imagePath: "widgets/frame" + prefix: "sunken" + width: 32 + height: 16 + PlasmaCore.FrameSvgItem { + imagePath: "widgets/button" + prefix: "normal" + anchors { + top: parent.top + bottom: parent.bottom + } + width: parent.width / 2 + x: checked ? width : 0 + Behavior on x { + PropertyAnimation { duration: 100 } + } + } + } +} + diff --git a/declarativeimports/plasmacomponents/qml/TextArea.qml b/declarativeimports/plasmacomponents/qml/TextArea.qml new file mode 100644 index 000000000..f3a7a3471 --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/TextArea.qml @@ -0,0 +1,220 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* 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. +*/ + +import QtQuick 1.1 +import org.kde.plasma.core 0.1 as PlasmaCore + +Item { + id: textArea + + // Common API + property alias font: textEdit.font // alias to textEdit.font + property int inputMethodHints + property bool errorHighlight + property alias cursorPosition: textEdit.cursorPosition + property alias horizontalAlignment: textEdit.cursorPosition + property alias verticalAlignment: textEdit.cursorPosition + property alias readOnly: textEdit.readOnly + property alias selectedText: textEdit.selectedText // read-only + property alias selectionEnd: textEdit.selectionEnd // read-only + property alias selectionStart: textEdit.selectionStart // read-only + property alias text: textEdit.text + property alias textFormat: textEdit.textFormat // enumeration + property alias wrapMode: textEdit.wrapMode // enumeration + property string placeholderText + + // functions + function copy() { + textEdit.copy(); + } + + function paste() { + textEdit.paste(); + } + + function cut() { + textEdit.cut(); + } + + function select(start, end) { + textEdit.select(start, end); + } + + function selectAll() { + textEdit.selectAll(); + } + + function selectWord() { + textEdit.selectWord(); + } + + function positionAt(pos) { + textEdit.positionAt(pos); + } + + function positionToRectangle(pos) { + textEdit.positionToRectangle(pos); + } + + // Plasma API + property alias interactive: flickArea.interactive + property alias contentMaxWidth: textEdit.width + property alias contentMaxHeight: textEdit.height + property real scrollWidth: 22 + + // Set active focus to it's internal textInput. + // Overriding QtQuick.Item forceActiveFocus function. + function forceActiveFocus() { + textEdit.forceActiveFocus(); + } + + // Overriding QtQuick.Item activeFocus property. + property alias activeFocus: textEdit.activeFocus + + opacity: enabled ? 1.0 : 0.5 + + PlasmaCore.FrameSvgItem { + id: base + + // TODO: see what is the best policy for margins + anchors { + fill: flickArea + leftMargin: -2 * base.margins.left + rightMargin: -2 * base.margins.right + topMargin: -2 * base.margins.top + bottomMargin: -2 * base.margins.bottom + } + imagePath: "widgets/lineedit" + prefix: "base" + + PlasmaCore.FrameSvgItem { + id: hover + + anchors { + fill: parent + leftMargin: -margins.left + topMargin: -margins.top + rightMargin: -margins.right + bottomMargin: -margins.bottom + } + imagePath: "widgets/lineedit" + prefix: { + // XXX: missing hover state + if (textEdit.activeFocus) + return "focus"; + else + return ""; + } + } + } + + Flickable { + id: flickArea + anchors { + fill: parent + rightMargin: scrollWidth + bottomMargin: scrollWidth + } + interactive: false //textArea.activeFocus + contentWidth: { + if (textEdit.wrapMode == TextEdit.NoWrap) + return textEdit.paintedWidth; + + return Math.min(textEdit.paintedWidth, textEdit.width); + } + contentHeight: Math.min(textEdit.paintedHeight, textEdit.height) + clip: true + + TextEdit { + id: textEdit + + width: flickArea.width + height: flickArea.height + clip: true + wrapMode: TextEdit.Wrap + enabled: textArea.enabled + + onCursorPositionChanged: { + if (cursorRectangle.x < flickArea.contentX) { + flickArea.contentX = cursorRectangle.x; + return; + } + + if (cursorRectangle.x > flickArea.contentX + + flickArea.width - cursorRectangle.width) { + flickArea.contentX = cursorRectangle.x - + cursorRectangle.width; + return; + } + + if (cursorRectangle.y < flickArea.contentY) { + flickArea.contentY = cursorRectangle.y; + return; + } + + if (cursorRectangle.y > flickArea.contentY + + flickArea.height - cursorRectangle.height) { + flickArea.contentY = cursorRectangle.y - + cursorRectangle.height; + return; + } + } + + // Proxying keys events is not required by the + // common API but is desired in the plasma API. + Keys.onPressed: textArea.Keys.pressed(event); + Keys.onReleased: textArea.Keys.released(event); + + Text { + anchors.fill: parent + text: textArea.placeholderText + visible: textEdit.text == "" && !textArea.activeFocus + opacity: 0.5 + } + } + } + + ScrollBar { + id: horizontalScroll + anchors { + bottom: parent.bottom + left: parent.left + right: flickArea.right + } + enabled: parent.enabled + flickableItem: flickArea + height: visible ? scrollWidth : 0 + orientation: Qt.Horizontal + stepSize: textEdit.font.pixelSize + } + + ScrollBar { + id: verticalScroll + anchors { + right: parent.right + top: parent.top + bottom: flickArea.bottom + } + enabled: parent.enabled + flickableItem: flickArea + width: visible ? scrollWidth : 0 + orientation: Qt.Vertical + stepSize: textEdit.font.pixelSize + } +} \ No newline at end of file diff --git a/declarativeimports/plasmacomponents/qml/TextField.qml b/declarativeimports/plasmacomponents/qml/TextField.qml new file mode 100644 index 000000000..beaa68158 --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/TextField.qml @@ -0,0 +1,156 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* 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. +*/ + +import QtQuick 1.1 +import org.kde.plasma.core 0.1 as PlasmaCore + +Item { + id: textField + + // Common API + property bool errorHighlight: false // TODO + property string placeholderText + property alias inputMethodHints: textInput.inputMethodHints + property alias font: textInput.font + + property alias cursorPosition: textInput.cursorPosition + property alias readOnly: textInput.readOnly + property alias echoMode: textInput.echoMode // Supports TextInput.Normal,TextInput.Password, TextInput.NoEcho, TextInput.PasswordEchoOnEdit + property alias acceptableInput: textInput.acceptableInput // read-only + property alias inputMask: textInput.inputMask + property alias validator: textInput.validator + property alias selectedText: textInput.selectedText // read-only + property alias selectionEnd: textInput.selectionEnd // read-only + property alias selectionStart: textInput.selectionStart // read-only + property alias text: textInput.text + property alias maximumLength: textInput.maximumLength + + function copy() { + textInput.copy(); + } + + function paste() { + textInput.paste(); + } + + function cut() { + textInput.cut(); + } + + function select(start, end) { + textInput.select(start, end); + } + + function selectAll() { + textInput.selectAll(); + } + + function selectWord() { + textInput.selectWord(); + } + + function positionAt(pos) { + textInput.positionAt(pos); + } + + function positionToRectangle(pos) { + textInput.positionToRectangle(pos); + } + + // Plasma API + property QtObject theme: PlasmaCore.Theme { } + + // Set active focus to it's internal textInput. + // Overriding QtQuick.Item forceActiveFocus function. + function forceActiveFocus() { + textInput.forceActiveFocus(); + } + + // Overriding QtQuick.Item activeFocus property. + property alias activeFocus: textInput.activeFocus + + // TODO: fix default size + implicitWidth: 100 + implicitHeight: 26 + // TODO: needs to define if there will be specific graphics for + // disabled text fields + opacity: enabled ? 1.0 : 0.5 + + PlasmaCore.FrameSvgItem { + id: base + + // TODO: see what is the correct policy for margins + anchors.fill: parent + imagePath: "widgets/lineedit" + prefix: "base" + } + + PlasmaCore.FrameSvgItem { + id: hover + + anchors { + fill: parent + leftMargin: -margins.left + topMargin: -margins.top + rightMargin: -margins.right + bottomMargin: -margins.bottom + } + imagePath: "widgets/lineedit" + prefix: { + // XXX: missing hover state + if (textField.activeFocus) + return "focus"; + else + return ""; + } + } + + Text { + anchors.fill: textInput + text: placeholderText + visible: textInput.text == "" && !textField.activeFocus + // XXX: using textColor and low opacity for theming placeholderText + color: theme.textColor + opacity: 0.5 + elide: Text.ElideRight + clip: true + } + + TextInput { + id: textInput + + anchors { + left: parent.left + right: parent.right + // TODO: see what is the correct policy for margins + leftMargin: 2 * base.margins.left + rightMargin: 2 * base.margins.right + } + y: (height - font.pixelSize) * 0.4 // XXX: verticalCenter anchor is not centering the text + height: Math.min(2 * font.pixelSize, parent.height) + color: theme.textColor + enabled: textField.enabled + clip: true + + // Proxying keys events is not required by the + // common API but is desired in the plasma API. + Keys.onPressed: textField.Keys.pressed(event); + Keys.onReleased: textField.Keys.released(event); + } +} \ No newline at end of file diff --git a/declarativeimports/plasmacomponents/qml/qmldir b/declarativeimports/plasmacomponents/qml/qmldir new file mode 100644 index 000000000..7a12f9c9f --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/qmldir @@ -0,0 +1,23 @@ +plugin plasmacomponentsplugin + +BusyIndicator 0.1 BusyIndicator.qml +Button 0.1 Button.qml +ButtonGroup 0.1 ButtonGroup.js +ButtonRow 0.1 ButtonRow.qml +ButtonColumn 0.1 ButtonColumn.qml +CheckBox 0.1 CheckBox.qml +DualStateButton 0.1 DualStateButton.qml +FlashingLabel 0.1 FlashingLabel.qml +Frame 0.1 Frame.qml +IconWidget 0.1 IconWidget.qml +Highlight 0.1 Highlight.qml +PushButton 0.1 PushButton.qml +ProgressBar 0.1 ProgressBar.qml +RadioButton 0.1 RadioButton.qml +ScrollBar 0.1 ScrollBar.qml +ScrollDecorator 0.1 ScrollDecorator.qml +Slider 0.1 Slider.qml +Switch 0.1 Switch.qml +TextField 0.1 TextField.qml +TextArea 0.1 TextArea.qml +ToolButton 0.1 ToolButton.qml diff --git a/declarativeimports/plasmacomponents/qrangemodel.cpp b/declarativeimports/plasmacomponents/qrangemodel.cpp new file mode 100644 index 000000000..fab6d1d9a --- /dev/null +++ b/declarativeimports/plasmacomponents/qrangemodel.cpp @@ -0,0 +1,522 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Components project on Qt Labs. +** +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions contained +** in the Technology Preview License Agreement accompanying this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +****************************************************************************/ + +/*! + \class QRangeModel + \brief The QRangeModel class, helps users to build components that depend + on some value and/or position to be in a certain range previously defined + + With this class, the user sets a value range and a position range, which + represent the valid values/positions the model can assume. It is worth telling + that the value property always has priority over the position property. A nice use + case, would be a Slider implementation with the help of QRangeModel. If the user sets + a value range to [0,100], a position range to [50,100] and sets the value + to 80, the equivalent position would be 90. After that, if the user decides to + resize the slider, the value would be the same, but the knob position would + be updated due to the new position range. + + \ingroup qt-components +*/ + +#ifndef QT_NO_ACCESSIBILITY +#include +#endif + +#include "qrangemodel.h" +#include "qrangemodel_p.h" + +namespace Plasma +{ + +QRangeModelPrivate::QRangeModelPrivate(QRangeModel *qq) + : q_ptr(qq) +{ +} + +QRangeModelPrivate::~QRangeModelPrivate() +{ +} + +void QRangeModelPrivate::init() +{ + minimum = 0; + maximum = 99; + stepSize = 0; + value = 0; + pos = 0; + posatmin = 0; + posatmax = 0; + inverted = false; +} + +/*! + Calculates the position that is going to be seen outside by the component + that is using QRangeModel. It takes into account the \l stepSize, + \l positionAtMinimum, \l positionAtMaximum properties + and \a position that is passed as parameter. +*/ + +qreal QRangeModelPrivate::publicPosition(qreal position) const +{ + // Calculate the equivalent stepSize for the position property. + const qreal min = effectivePosAtMin(); + const qreal max = effectivePosAtMax(); + const qreal valueRange = maximum - minimum; + const qreal positionValueRatio = valueRange ? (max - min) / valueRange : 0; + const qreal positionStep = stepSize * positionValueRatio; + + if (positionStep == 0) + return (min < max) ? qBound(min, position, max) : qBound(max, position, min); + + const int stepSizeMultiplier = (position - min) / positionStep; + + // Test whether value is below minimum range + if (stepSizeMultiplier < 0) + return min; + + qreal leftEdge = (stepSizeMultiplier * positionStep) + min; + qreal rightEdge = ((stepSizeMultiplier + 1) * positionStep) + min; + + if (min < max) { + leftEdge = qMin(leftEdge, max); + rightEdge = qMin(rightEdge, max); + } else { + leftEdge = qMax(leftEdge, max); + rightEdge = qMax(rightEdge, max); + } + + if (qAbs(leftEdge - position) <= qAbs(rightEdge - position)) + return leftEdge; + return rightEdge; +} + +/*! + Calculates the value that is going to be seen outside by the component + that is using QRangeModel. It takes into account the \l stepSize, + \l minimumValue, \l maximumValue properties + and \a value that is passed as parameter. +*/ + +qreal QRangeModelPrivate::publicValue(qreal value) const +{ + // It is important to do value-within-range check this + // late (as opposed to during setPosition()). The reason is + // QML bindings; a position that is initially invalid because it lays + // outside the range, might become valid later if the range changes. + + if (stepSize == 0) + return qBound(minimum, value, maximum); + + const int stepSizeMultiplier = (value - minimum) / stepSize; + + // Test whether value is below minimum range + if (stepSizeMultiplier < 0) + return minimum; + + const qreal leftEdge = qMin(maximum, (stepSizeMultiplier * stepSize) + minimum); + const qreal rightEdge = qMin(maximum, ((stepSizeMultiplier + 1) * stepSize) + minimum); + const qreal middle = (leftEdge + rightEdge) / 2; + + return (value <= middle) ? leftEdge : rightEdge; +} + +/*! + Checks if the \l value or \l position, that is seen by the user, has changed and emits the changed signal if it + has changed. +*/ + +void QRangeModelPrivate::emitValueAndPositionIfChanged(const qreal oldValue, const qreal oldPosition) +{ + Q_Q(QRangeModel); + + // Effective value and position might have changed even in cases when e.g. d->value is + // unchanged. This will be the case when operating with values outside range: + const qreal newValue = q->value(); + const qreal newPosition = q->position(); + if (!qFuzzyCompare(newValue, oldValue)) + emit q->valueChanged(newValue); + if (!qFuzzyCompare(newPosition, oldPosition)) + emit q->positionChanged(newPosition); +} + +/*! + Constructs a QRangeModel with \a parent +*/ + +QRangeModel::QRangeModel(QObject *parent) + : QObject(parent), d_ptr(new QRangeModelPrivate(this)) +{ + Q_D(QRangeModel); + d->init(); +} + +/*! + \internal + Constructs a QRangeModel with private class pointer \a dd and \a parent +*/ + +QRangeModel::QRangeModel(QRangeModelPrivate &dd, QObject *parent) + : QObject(parent), d_ptr(&dd) +{ + Q_D(QRangeModel); + d->init(); +} + +/*! + Destroys the QRangeModel +*/ + +QRangeModel::~QRangeModel() +{ + delete d_ptr; + d_ptr = 0; +} + +/*! + Sets the range of valid positions, that \l position can assume externally, with + \a min and \a max. + Such range is represented by \l positionAtMinimum and \l positionAtMaximum +*/ + +void QRangeModel::setPositionRange(qreal min, qreal max) +{ + Q_D(QRangeModel); + + bool emitPosAtMinChanged = !qFuzzyCompare(min, d->posatmin); + bool emitPosAtMaxChanged = !qFuzzyCompare(max, d->posatmax); + + if (!(emitPosAtMinChanged || emitPosAtMaxChanged)) + return; + + const qreal oldPosition = position(); + d->posatmin = min; + d->posatmax = max; + + // When a new positionRange is defined, the position property must be updated based on the value property. + // For instance, imagine that you have a valueRange of [0,100] and a position range of [20,100], + // if a user set the value to 50, the position would be 60. If this positionRange is updated to [0,100], then + // the new position, based on the value (50), will be 50. + // If the newPosition is different than the old one, it must be updated, in order to emit + // the positionChanged signal. + d->pos = d->equivalentPosition(d->value); + + if (emitPosAtMinChanged) + emit positionAtMinimumChanged(d->posatmin); + if (emitPosAtMaxChanged) + emit positionAtMaximumChanged(d->posatmax); + + d->emitValueAndPositionIfChanged(value(), oldPosition); +} +/*! + Sets the range of valid values, that \l value can assume externally, with + \a min and \a max. The range has the following constraint: \a min must be less or equal \a max + Such range is represented by \l minimumValue and \l maximumValue +*/ + +void QRangeModel::setRange(qreal min, qreal max) +{ + Q_D(QRangeModel); + + bool emitMinimumChanged = !qFuzzyCompare(min, d->minimum); + bool emitMaximumChanged = !qFuzzyCompare(max, d->maximum); + + if (!(emitMinimumChanged || emitMaximumChanged)) + return; + + const qreal oldValue = value(); + const qreal oldPosition = position(); + + d->minimum = min; + d->maximum = qMax(min, max); + + // Update internal position if it was changed. It can occurs if internal value changes, due to range update + d->pos = d->equivalentPosition(d->value); + + if (emitMinimumChanged) + emit minimumChanged(d->minimum); + if (emitMaximumChanged) + emit maximumChanged(d->maximum); + + d->emitValueAndPositionIfChanged(oldValue, oldPosition); +} + +/*! + \property QRangeModel::minimumValue + \brief the minimum value that \l value can assume + + This property's default value is 0 +*/ + +void QRangeModel::setMinimum(qreal min) +{ + Q_D(const QRangeModel); + setRange(min, d->maximum); +} + +qreal QRangeModel::minimum() const +{ + Q_D(const QRangeModel); + return d->minimum; +} + +/*! + \property QRangeModel::maximumValue + \brief the maximum value that \l value can assume + + This property's default value is 99 +*/ + +void QRangeModel::setMaximum(qreal max) +{ + Q_D(const QRangeModel); + // if the new maximum value is smaller than + // minimum, update minimum too + setRange(qMin(d->minimum, max), max); +} + +qreal QRangeModel::maximum() const +{ + Q_D(const QRangeModel); + return d->maximum; +} + +/*! + \property QRangeModel::stepSize + \brief the value that is added to the \l value and \l position property + + Example: If a user sets a range of [0,100] and stepSize + to 30, the valid values that are going to be seen externally would be: 0, 30, 60, 90, 100. +*/ + +void QRangeModel::setStepSize(qreal stepSize) +{ + Q_D(QRangeModel); + + stepSize = qMax(qreal(0.0), stepSize); + if (qFuzzyCompare(stepSize, d->stepSize)) + return; + + const qreal oldValue = value(); + const qreal oldPosition = position(); + d->stepSize = stepSize; + + emit stepSizeChanged(d->stepSize); + d->emitValueAndPositionIfChanged(oldValue, oldPosition); +} + +qreal QRangeModel::stepSize() const +{ + Q_D(const QRangeModel); + return d->stepSize; +} + +/*! + Returns a valid position, respecting the \l positionAtMinimum, + \l positionAtMaximum and the \l stepSize properties. + Such calculation is based on the parameter \a value (which is valid externally). +*/ + +qreal QRangeModel::positionForValue(qreal value) const +{ + Q_D(const QRangeModel); + + const qreal unconstrainedPosition = d->equivalentPosition(value); + return d->publicPosition(unconstrainedPosition); +} + +/*! + \property QRangeModel::position + \brief the current position of the model + + Represents a valid external position, based on the \l positionAtMinimum, + \l positionAtMaximum and the \l stepSize properties. + The user can set it internally with a position, that is not within the current position range, + since it can become valid if the user changes the position range later. +*/ + +qreal QRangeModel::position() const +{ + Q_D(const QRangeModel); + + // Return the internal position but observe boundaries and + // stepSize restrictions. + return d->publicPosition(d->pos); +} + +void QRangeModel::setPosition(qreal newPosition) +{ + Q_D(QRangeModel); + + if (qFuzzyCompare(newPosition, d->pos)) + return; + + const qreal oldPosition = position(); + const qreal oldValue = value(); + + // Update position and calculate new value + d->pos = newPosition; + d->value = d->equivalentValue(d->pos); + d->emitValueAndPositionIfChanged(oldValue, oldPosition); +} + +/*! + \property QRangeModel::positionAtMinimum + \brief the minimum value that \l position can assume + + This property's default value is 0 +*/ + +void QRangeModel::setPositionAtMinimum(qreal min) +{ + Q_D(QRangeModel); + setPositionRange(min, d->posatmax); +} + +qreal QRangeModel::positionAtMinimum() const +{ + Q_D(const QRangeModel); + return d->posatmin; +} + +/*! + \property QRangeModel::positionAtMaximum + \brief the maximum value that \l position can assume + + This property's default value is 0 +*/ + +void QRangeModel::setPositionAtMaximum(qreal max) +{ + Q_D(QRangeModel); + setPositionRange(d->posatmin, max); +} + +qreal QRangeModel::positionAtMaximum() const +{ + Q_D(const QRangeModel); + return d->posatmax; +} + +/*! + Returns a valid value, respecting the \l minimumValue, + \l maximumValue and the \l stepSize properties. + Such calculation is based on the parameter \a position (which is valid externally). +*/ + +qreal QRangeModel::valueForPosition(qreal position) const +{ + Q_D(const QRangeModel); + + const qreal unconstrainedValue = d->equivalentValue(position); + return d->publicValue(unconstrainedValue); +} + +/*! + \property QRangeModel::value + \brief the current value of the model + + Represents a valid external value, based on the \l minimumValue, + \l maximumValue and the \l stepSize properties. + The user can set it internally with a value, that is not within the current range, + since it can become valid if the user changes the range later. +*/ + +qreal QRangeModel::value() const +{ + Q_D(const QRangeModel); + + // Return internal value but observe boundaries and + // stepSize restrictions + return d->publicValue(d->value); +} + +void QRangeModel::setValue(qreal newValue) +{ + Q_D(QRangeModel); + + if (qFuzzyCompare(newValue, d->value)) + return; + + const qreal oldValue = value(); + const qreal oldPosition = position(); + + // Update relative value and position + d->value = newValue; + d->pos = d->equivalentPosition(d->value); + d->emitValueAndPositionIfChanged(oldValue, oldPosition); +} + +/*! + \property QRangeModel::inverted + \brief the model is inverted or not + + The model can be represented with an inverted behavior, e.g. when \l value assumes + the maximum value (represented by \l maximumValue) the \l position will be at its + minimum (represented by \l positionAtMinimum). +*/ + +void QRangeModel::setInverted(bool inverted) +{ + Q_D(QRangeModel); + if (inverted == d->inverted) + return; + + d->inverted = inverted; + emit invertedChanged(d->inverted); + + // After updating the internal value, the position property can change. + setPosition(d->equivalentPosition(d->value)); +} + +bool QRangeModel::inverted() const +{ + Q_D(const QRangeModel); + return d->inverted; +} + +/*! + Sets the \l value to \l minimumValue. +*/ + +void QRangeModel::toMinimum() +{ + Q_D(const QRangeModel); + setValue(d->minimum); +} + +/*! + Sets the \l value to \l maximumValue. +*/ + +void QRangeModel::toMaximum() +{ + Q_D(const QRangeModel); + setValue(d->maximum); +} + +} // Plasma namespace + +#include "qrangemodel.moc" diff --git a/declarativeimports/plasmacomponents/qrangemodel.h b/declarativeimports/plasmacomponents/qrangemodel.h new file mode 100644 index 000000000..bdc8122e7 --- /dev/null +++ b/declarativeimports/plasmacomponents/qrangemodel.h @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Components project on Qt Labs. +** +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions contained +** in the Technology Preview License Agreement accompanying this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +****************************************************************************/ + +#ifndef QRANGEMODEL_H +#define QRANGEMODEL_H + +#include + +namespace Plasma +{ + +class QRangeModelPrivate; + +class QRangeModel : public QObject +{ + Q_OBJECT + + Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged USER true) + Q_PROPERTY(qreal minimumValue READ minimum WRITE setMinimum NOTIFY minimumChanged) + Q_PROPERTY(qreal maximumValue READ maximum WRITE setMaximum NOTIFY maximumChanged) + Q_PROPERTY(qreal stepSize READ stepSize WRITE setStepSize NOTIFY stepSizeChanged) + Q_PROPERTY(qreal position READ position WRITE setPosition NOTIFY positionChanged) + Q_PROPERTY(qreal positionAtMinimum READ positionAtMinimum WRITE setPositionAtMinimum NOTIFY positionAtMinimumChanged) + Q_PROPERTY(qreal positionAtMaximum READ positionAtMaximum WRITE setPositionAtMaximum NOTIFY positionAtMaximumChanged) + Q_PROPERTY(bool inverted READ inverted WRITE setInverted NOTIFY invertedChanged) + +public: + QRangeModel(QObject *parent = 0); + virtual ~QRangeModel(); + + void setRange(qreal min, qreal max); + void setPositionRange(qreal min, qreal max); + + void setStepSize(qreal stepSize); + qreal stepSize() const; + + void setMinimum(qreal min); + qreal minimum() const; + + void setMaximum(qreal max); + qreal maximum() const; + + void setPositionAtMinimum(qreal posAtMin); + qreal positionAtMinimum() const; + + void setPositionAtMaximum(qreal posAtMax); + qreal positionAtMaximum() const; + + void setInverted(bool inverted); + bool inverted() const; + + qreal value() const; + qreal position() const; + + Q_INVOKABLE qreal valueForPosition(qreal position) const; + Q_INVOKABLE qreal positionForValue(qreal value) const; + +public Q_SLOTS: + void toMinimum(); + void toMaximum(); + void setValue(qreal value); + void setPosition(qreal position); + +Q_SIGNALS: + void valueChanged(qreal value); + void positionChanged(qreal position); + + void stepSizeChanged(qreal stepSize); + + void invertedChanged(bool inverted); + + void minimumChanged(qreal min); + void maximumChanged(qreal max); + void positionAtMinimumChanged(qreal min); + void positionAtMaximumChanged(qreal max); + +protected: + QRangeModel(QRangeModelPrivate &dd, QObject *parent); + QRangeModelPrivate* d_ptr; + +private: + Q_DISABLE_COPY(QRangeModel) + Q_DECLARE_PRIVATE(QRangeModel) + +}; + +} // Plasma namespace + +#endif // QRANGEMODEL_H diff --git a/declarativeimports/plasmacomponents/qrangemodel_p.h b/declarativeimports/plasmacomponents/qrangemodel_p.h new file mode 100644 index 000000000..5eb628671 --- /dev/null +++ b/declarativeimports/plasmacomponents/qrangemodel_p.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Components project on Qt Labs. +** +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions contained +** in the Technology Preview License Agreement accompanying this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +****************************************************************************/ + +#ifndef QRANGEMODEL_P_H +#define QRANGEMODEL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Components API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qrangemodel.h" + +namespace Plasma +{ + +class QRangeModelPrivate +{ + Q_DECLARE_PUBLIC(QRangeModel) +public: + QRangeModelPrivate(QRangeModel *qq); + virtual ~QRangeModelPrivate(); + + void init(); + + qreal posatmin, posatmax; + qreal minimum, maximum, stepSize, pos, value; + + uint inverted : 1; + + QRangeModel *q_ptr; + + inline qreal effectivePosAtMin() const { + return inverted ? posatmax : posatmin; + } + + inline qreal effectivePosAtMax() const { + return inverted ? posatmin : posatmax; + } + + inline qreal equivalentPosition(qreal value) const { + // Return absolute position from absolute value + const qreal valueRange = maximum - minimum; + if (valueRange == 0) + return effectivePosAtMin(); + + const qreal scale = (effectivePosAtMax() - effectivePosAtMin()) / valueRange; + return (value - minimum) * scale + effectivePosAtMin(); + } + + inline qreal equivalentValue(qreal pos) const { + // Return absolute value from absolute position + const qreal posRange = effectivePosAtMax() - effectivePosAtMin(); + if (posRange == 0) + return minimum; + + const qreal scale = (maximum - minimum) / posRange; + return (pos - effectivePosAtMin()) * scale + minimum; + } + + qreal publicPosition(qreal position) const; + qreal publicValue(qreal value) const; + void emitValueAndPositionIfChanged(const qreal oldValue, const qreal oldPosition); +}; + +} // Plasma namespace + +#endif // QRANGEMODEL_P_H diff --git a/declarativeimports/test/gallery/Busy.qml b/declarativeimports/test/gallery/Busy.qml new file mode 100644 index 000000000..8e77db1ec --- /dev/null +++ b/declarativeimports/test/gallery/Busy.qml @@ -0,0 +1,78 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* 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. +*/ + +import QtQuick 1.0 +import org.kde.plasma.components 0.1 as PlasmaComponents + +Column { + spacing: 20 + + Text { + font.pixelSize: 20 + text: "Busy Indicator" + } + + PlasmaComponents.BusyIndicator { } + + PlasmaComponents.BusyIndicator { running: true } + + Text { + font.pixelSize: 20 + text: "Progress Bar" + } + + Text { text: "Horizontal" } + + PlasmaComponents.ProgressBar { + value: 0.3 + } + + PlasmaComponents.ProgressBar { + indeterminate: true + } + + PlasmaComponents.ProgressBar { + minimumValue: 0 + maximumValue: 100 + value: 30 + } + + Text { text: "Vertical" } + Row { + spacing: 20 + PlasmaComponents.ProgressBar { + value: 0.3 + orientation: Qt.Vertical + width: 20 + height: 100 + } + PlasmaComponents.ProgressBar { + value: 0.4 + orientation: Qt.Vertical + width: 20 + height: 120 + } + PlasmaComponents.ProgressBar { + orientation: Qt.Vertical + width: 20 + height: 100 + indeterminate: true + } + } +} diff --git a/declarativeimports/test/gallery/Buttons.qml b/declarativeimports/test/gallery/Buttons.qml new file mode 100644 index 000000000..b1d9ecf7b --- /dev/null +++ b/declarativeimports/test/gallery/Buttons.qml @@ -0,0 +1,99 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* 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. +*/ + +import QtQuick 1.0 +import org.kde.plasma.components 0.1 as PlasmaComponents + +Column { + spacing: 20 + + Text { + font.pixelSize: 20 + text: "Buttons" + } + + PlasmaComponents.Button { + id: bt1 + width: 140 + height: 30 + text: "Button" + + onClicked: { + console.log("Clicked"); + } + + Keys.onTabPressed: bt2.forceActiveFocus(); + } + + PlasmaComponents.Button { + id: bt2 + width: 140 + height: 30 + text: "Checkable Button" + checkable: true + + onCheckedChanged: { + if (checked) + console.log("Button Checked"); + else + console.log("Button Unchecked"); + } + + Keys.onTabPressed: bt3.forceActiveFocus(); + } + + PlasmaComponents.Button { + id: bt3 + width: 140 + height: 30 + text: "Different Font" + font { + pixelSize: 20 + family: "Helvetica" + } + + Keys.onTabPressed: bt4.forceActiveFocus(); + } + + PlasmaComponents.Button { + id: bt4 + width: 140 + height: 30 + text: "Icon Button" + iconSource: "/home/dakerfp/work/comics-reader/ui/images/random.png" + + Keys.onTabPressed: bt5.forceActiveFocus(); + } + + PlasmaComponents.Button { + id: bt5 + width: 140 + height: 30 + iconSource: "/home/dakerfp/work/comics-reader/ui/images/random.png" + + Keys.onTabPressed: bt1.forceActiveFocus(); + } + + PlasmaComponents.Button { + width: 140 + height: 30 + text: "Disabled Button" + enabled: false + } +} diff --git a/declarativeimports/test/gallery/CheckableButtons.qml b/declarativeimports/test/gallery/CheckableButtons.qml new file mode 100644 index 000000000..fee6032b4 --- /dev/null +++ b/declarativeimports/test/gallery/CheckableButtons.qml @@ -0,0 +1,107 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* 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. +*/ + +import QtQuick 1.0 +import org.kde.plasma.components 0.1 as PlasmaComponents + +Column { + spacing: 20 + + Text { + font.pixelSize: 20 + text: "Check Box" + } + + PlasmaComponents.CheckBox { + width: 140 + height: 30 + text: "Check Box 1" + + onCheckedChanged: { + if (checked) + console.log("CheckBox checked"); + else + console.log("CheckBox unchecked"); + } + onClicked: { + console.log("CheckBox clicked"); + } + } + + PlasmaComponents.CheckBox { + height: 30 + text: "Disabled" + enabled: false + } + + PlasmaComponents.CheckBox { + height: 30 + text: "" + } + + PlasmaComponents.CheckBox { + height: 30 + text: "A loooooooooooooong text" + } + + Text { + font.pixelSize: 20 + text: "Radio Button" + } + + PlasmaComponents.RadioButton { + width: 140 + height: 30 + text: "RadioButton" + + onCheckedChanged: { + if (checked) + console.log("RadioButton Checked"); + else + console.log("RadioButton Unchecked"); + } + } + + PlasmaComponents.Switch { } + + Text { + font.pixelSize: 20 + text: "Button Row" + } + + PlasmaComponents.ButtonRow { + spacing: 20 + PlasmaComponents.RadioButton { text: "A" } + PlasmaComponents.RadioButton { text: "B" } + PlasmaComponents.RadioButton { text: "C" } + } + + Text { + font.pixelSize: 20 + text: "Button Column" + } + + PlasmaComponents.ButtonColumn { + spacing: 20 + PlasmaComponents.RadioButton { text: "Alice" } + PlasmaComponents.RadioButton { text: "Bob" } + PlasmaComponents.RadioButton { text: "Charles" } + } + +} diff --git a/declarativeimports/test/gallery/Gallery.qml b/declarativeimports/test/gallery/Gallery.qml new file mode 100644 index 000000000..9ef246e3e --- /dev/null +++ b/declarativeimports/test/gallery/Gallery.qml @@ -0,0 +1,86 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* 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. +*/ + +import QtQuick 1.0 +import org.kde.plasma.components 0.1 as PlasmaComponents + +Rectangle { + width: 1000 + height: 800 + color: "lightgrey" + + Flickable { + id: page + + anchors.fill: parent + contentWidth: 2200 + contentHeight: 1000 + + Row { + x: 30 + anchors { + top: parent.top + bottom: parent.bottom + margins: 20 + } + spacing: 30 + + Buttons{ } + + CheckableButtons { } + + Busy { } + + Sliders { } + + Scrollers { } + + Texts { } + } + } + + PlasmaComponents.ScrollBar { + id: horizontalScrollBar + + stepSize: 30 + + flickableItem: page + animated: true + anchors { + left: parent.left + right: verticalScrollBar.left + bottom: parent.bottom + } + } + + PlasmaComponents.ScrollBar { + id: verticalScrollBar + + stepSize: 30 + + orientation: Qt.Vertical + flickableItem: page + animated: true + anchors { + top: parent.top + right: parent.right + bottom: horizontalScrollBar.top + } + } +} diff --git a/declarativeimports/test/gallery/Scrollers.qml b/declarativeimports/test/gallery/Scrollers.qml new file mode 100644 index 000000000..dea2d8c81 --- /dev/null +++ b/declarativeimports/test/gallery/Scrollers.qml @@ -0,0 +1,131 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* 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. +*/ + +import QtQuick 1.0 +import org.kde.plasma.components 0.1 as PlasmaComponents + +Column { + spacing: 20 + + Text { + font.pixelSize: 20 + text: "Scroll Bar" + } + + ListView { + id: scrollList + + width: 200 + height: 200 + clip: true + model: 20 + delegate: Text { + width: 200 + height: 30 + text: index + font.pixelSize: 18 + } + + Rectangle { + anchors.fill: parent + color: "grey" + opacity: 0.3 + } + + PlasmaComponents.ScrollBar { + id: scrollBar + orientation: Qt.Vertical + flickableItem: scrollList + animated: true + stepSize: 40 + scrollButtonInterval: 50 + anchors { + top: scrollList.top + right: scrollList.right + bottom: scrollList.bottom + } + } + } + + Text { + font.pixelSize: 20 + text: "Scroll Decorator" + } + + Item { + width: 200 + height: 200 + PlasmaComponents.Highlight { anchors.fill: parent } + Flickable { + id: scrollArea + anchors.fill: parent + clip: true + contentWidth: 400 + contentHeight: 400 + + // Flickable Contents + Rectangle { + color: "green" + width: 100 + height: 100 + } + Rectangle { + x: 80 + y: 80 + color: "blue" + width: 200 + height: 200 + } + Rectangle { + x: 200 + y: 200 + color: "red" + width: 150 + height: 150 + } + } + + // Scroll Decorators + PlasmaComponents.ScrollDecorator { + orientation: Qt.Vertical + flickableItem: scrollArea + inverted: true + anchors { + top: scrollArea.top + right: scrollArea.right + bottom: scrollArea.bottom + } + Text { + y: parent.height / 2 + x: 13 + rotation: -90 + text: "inverted" + } + } + PlasmaComponents.ScrollDecorator { + orientation: Qt.Horizontal + flickableItem: scrollArea + anchors { + left: scrollArea.left + right: scrollArea.right + bottom: scrollArea.bottom + } + } + } +} diff --git a/declarativeimports/test/gallery/Sliders.qml b/declarativeimports/test/gallery/Sliders.qml new file mode 100644 index 000000000..79825e622 --- /dev/null +++ b/declarativeimports/test/gallery/Sliders.qml @@ -0,0 +1,121 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* 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. +*/ + +import QtQuick 1.0 +import org.kde.plasma.components 0.1 as PlasmaComponents + +Column { + spacing: 20 + + Text { + font.pixelSize: 20 + text: "Slider" + } + + PlasmaComponents.Highlight { + width: 300 + height: 400 + Column { + anchors { + fill: parent + } + spacing: 10 + + Text { text: "Color Selector"; font.pixelSize: 20 } + + Text { text: "Red" } + + PlasmaComponents.Slider { + id: redSlider + height: 20 + width: 255 + orientation: Qt.Horizontal + minimumValue: 0 + maximumValue: 255 + stepSize: 10 + animated: true + Keys.onTabPressed: greenSlider.forceActiveFocus() + } + + Text { text: "Green" } + + PlasmaComponents.Slider { + id: greenSlider + height: 20 + width: 255 + orientation: Qt.Horizontal + minimumValue: 0 + maximumValue: 255 + stepSize: 10 + animated: true + Keys.onTabPressed: blueSlider.forceActiveFocus() + } + + Text { text: "Blue" } + + PlasmaComponents.Slider { + id: blueSlider + height: 20 + width: 255 + orientation: Qt.Horizontal + minimumValue: 0 + maximumValue: 255 + stepSize: 10 + animated: true + Keys.onTabPressed: redSlider.forceActiveFocus() + } + + Rectangle { + anchors.horizontalCenter: parent.horizontalCenter + width: parent.width / 2 + height: width + color: Qt.rgba(redSlider.value / 255, greenSlider.value / 255, blueSlider.value / 255, 1) + } + } + } + + Text { text: "Disabled Horizontal Slider" } + + PlasmaComponents.Slider { + id: horizontalSlider + width: 140 + height: 20 + animated: true + enabled: false + } + + Text { text: "Vertical Slider" } + + Row { + spacing: 30 + PlasmaComponents.Slider { + id: verticalSlider + width: 20 + height: 140 + orientation: Qt.Vertical + minimumValue: 10 + maximumValue: 1000 + stepSize: 50 + inverted: true + animated: true + } + Text { text: verticalSlider.value } + } + +} diff --git a/declarativeimports/test/gallery/Texts.qml b/declarativeimports/test/gallery/Texts.qml new file mode 100644 index 000000000..ae3d0df48 --- /dev/null +++ b/declarativeimports/test/gallery/Texts.qml @@ -0,0 +1,99 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* 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. +*/ + +import QtQuick 1.1 +import org.kde.plasma.components 0.1 as PlasmaComponents + +Column { + spacing: 30 + Text { + text: "Text Fields" + font.pixelSize: 20 + } + + PlasmaComponents.Highlight { + width: 200 + height: 100 + Column { + spacing: 10 + Row { + Text { + text: "Username: " + anchors.verticalCenter: tf1.verticalCenter + } + PlasmaComponents.TextField { + id: tf1 + placeholderText: "login" + Keys.onTabPressed: tf2.forceActiveFocus(); + } + } + + Row { + Text { + text: "Password: " + anchors.verticalCenter: tf2.verticalCenter + } + PlasmaComponents.TextField { + id: tf2 + width: 120 + echoMode: TextInput.Password + Keys.onTabPressed: loginButton.forceActiveFocus(); + } + } + + PlasmaComponents.Button { + id: loginButton + text: "Login" + anchors { + right: parent.right + rightMargin: 0 + } + width: 100 + } + } + } + + PlasmaComponents.TextField { + width: 120 + placeholderText: "Disabled Text Field" + Keys.onTabPressed: loginButton.forceActiveFocus(); + enabled: false + } + + Text { + text: "Text Area" + font.pixelSize: 20 + } + + PlasmaComponents.TextArea { + width: 200 + height: 200 + placeholderText: "Lorem ipsum et dolor" + wrapMode: TextEdit.WordWrap + contentMaxWidth: 400 + contentMaxHeight: 400 + } + + PlasmaComponents.TextArea { + width: 200 + height: 100 + enabled: false + text: "Disabled Text Area" + } +}