mit neuen venv und exe-Files
This commit is contained in:
@@ -0,0 +1,265 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQml 2.14 as Qml
|
||||
import QtQuick.Window 2.2
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQuick.Controls.Private 1.0
|
||||
|
||||
/*!
|
||||
\qmltype ApplicationWindow
|
||||
\since 5.1
|
||||
\inqmlmodule QtQuick.Controls
|
||||
\ingroup applicationwindow
|
||||
\ingroup controls
|
||||
\brief Provides a top-level application window.
|
||||
|
||||
\image applicationwindow.png
|
||||
|
||||
ApplicationWindow is a \l Window that adds convenience for positioning items,
|
||||
such as \l MenuBar, \l ToolBar, and \l StatusBar in a platform independent
|
||||
manner.
|
||||
|
||||
\code
|
||||
ApplicationWindow {
|
||||
id: window
|
||||
visible: true
|
||||
|
||||
menuBar: MenuBar {
|
||||
Menu { MenuItem {...} }
|
||||
Menu { MenuItem {...} }
|
||||
}
|
||||
|
||||
toolBar: ToolBar {
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
ToolButton {...}
|
||||
}
|
||||
}
|
||||
|
||||
TabView {
|
||||
id: myContent
|
||||
anchors.fill: parent
|
||||
...
|
||||
}
|
||||
}
|
||||
\endcode
|
||||
|
||||
\note By default, an ApplicationWindow is not visible.
|
||||
|
||||
The \l{Qt Quick Controls 1 - Gallery} example is a good starting
|
||||
point to explore this type.
|
||||
*/
|
||||
|
||||
Window {
|
||||
id: root
|
||||
|
||||
/*!
|
||||
\qmlproperty MenuBar ApplicationWindow::menuBar
|
||||
|
||||
This property holds the \l MenuBar.
|
||||
|
||||
By default, this value is not set.
|
||||
*/
|
||||
property MenuBar menuBar: null
|
||||
|
||||
/*!
|
||||
\qmlproperty Item ApplicationWindow::toolBar
|
||||
|
||||
This property holds the toolbar \l Item.
|
||||
|
||||
It can be set to any Item type, but is generally used with \l ToolBar.
|
||||
|
||||
By default, this value is not set. When you set the toolbar item, it will
|
||||
be anchored automatically into the application window.
|
||||
*/
|
||||
property Item toolBar
|
||||
|
||||
/*!
|
||||
\qmlproperty Item ApplicationWindow::statusBar
|
||||
|
||||
This property holds the status bar \l Item.
|
||||
|
||||
It can be set to any Item type, but is generally used with \l StatusBar.
|
||||
|
||||
By default, this value is not set. When you set the status bar item, it
|
||||
will be anchored automatically into the application window.
|
||||
*/
|
||||
property Item statusBar
|
||||
|
||||
// The below documentation was supposed to be written as a grouped property, but qdoc would
|
||||
// not render it correctly due to a bug (QTBUG-34206)
|
||||
/*!
|
||||
\qmlproperty ContentItem ApplicationWindow::contentItem
|
||||
|
||||
This group holds the size constraints of the content item. This is the area between the
|
||||
\l ToolBar and the \l StatusBar.
|
||||
The \l ApplicationWindow will use this as input when calculating the effective size
|
||||
constraints of the actual window.
|
||||
It holds these 6 properties for describing the minimum, implicit and maximum sizes:
|
||||
\table
|
||||
\header \li Grouped property \li Description
|
||||
\row \li contentItem.minimumWidth \li The minimum width of the content item.
|
||||
\row \li contentItem.minimumHeight \li The minimum height of the content item.
|
||||
\row \li contentItem.implicitWidth \li The implicit width of the content item.
|
||||
\row \li contentItem.implicitHeight \li The implicit height of the content item.
|
||||
\row \li contentItem.maximumWidth \li The maximum width of the content item.
|
||||
\row \li contentItem.maximumHeight \li The maximum height of the content item.
|
||||
\endtable
|
||||
*/
|
||||
property alias contentItem : contentArea
|
||||
|
||||
/*! The style Component for the window.
|
||||
\sa {Qt Quick Controls 1 Styles QML Types}
|
||||
*/
|
||||
property Component style: Settings.styleComponent(Settings.style, "ApplicationWindowStyle.qml", root)
|
||||
|
||||
/*! \internal */
|
||||
property alias __style: styleLoader.item
|
||||
|
||||
/*! \internal */
|
||||
property alias __panel: panelLoader.item
|
||||
|
||||
/*! \internal */
|
||||
property real __topBottomMargins: __panel.contentArea.y + __panel.statusBarArea.height
|
||||
/*! \internal
|
||||
There is a similar macro QWINDOWSIZE_MAX in qwindow_p.h that is used to limit the
|
||||
range of QWindow::maximum{Width,Height}
|
||||
However, in case we have a very big number (> 2^31) conversion will fail, and it will be
|
||||
converted to 0, resulting in that we will call setMaximumWidth(0)....
|
||||
We therefore need to enforce the limit at a level where we are still operating on
|
||||
floating point values.
|
||||
*/
|
||||
readonly property real __qwindowsize_max: (1 << 24) - 1
|
||||
|
||||
/*! \internal */
|
||||
property real __width: 0
|
||||
Qml.Binding {
|
||||
target: root
|
||||
property: "__width"
|
||||
when: (root.minimumWidth <= root.maximumWidth) && !contentArea.__noImplicitWidthGiven
|
||||
value: Math.max(Math.min(root.maximumWidth, contentArea.implicitWidth), root.minimumWidth)
|
||||
restoreMode: Binding.RestoreBinding
|
||||
}
|
||||
/*! \internal */
|
||||
property real __height: 0
|
||||
Qml.Binding {
|
||||
target: root
|
||||
property: "__height"
|
||||
when: (root.minimumHeight <= root.maximumHeight) && !contentArea.__noImplicitHeightGiven
|
||||
value: Math.max(Math.min(root.maximumHeight, contentArea.implicitHeight + __topBottomMargins), root.minimumHeight)
|
||||
restoreMode: Binding.RestoreBinding
|
||||
}
|
||||
/* As soon as an application developer writes
|
||||
width: 200
|
||||
this binding will be broken. This is the reason for this indirection
|
||||
via __width (and __height)
|
||||
*/
|
||||
width: __width
|
||||
height: __height
|
||||
|
||||
minimumWidth: contentArea.__noMinimumWidthGiven ? 0 : contentArea.minimumWidth
|
||||
minimumHeight: contentArea.__noMinimumHeightGiven ? 0 : (contentArea.minimumHeight + __topBottomMargins)
|
||||
|
||||
maximumWidth: Math.min(__qwindowsize_max, contentArea.maximumWidth)
|
||||
maximumHeight: Math.min(__qwindowsize_max, contentArea.maximumHeight + __topBottomMargins)
|
||||
|
||||
/*! \internal */
|
||||
default property alias data: contentArea.data
|
||||
|
||||
flags: Qt.Window | Qt.WindowFullscreenButtonHint |
|
||||
Qt.WindowTitleHint | Qt.WindowSystemMenuHint | Qt.WindowMinMaxButtonsHint |
|
||||
Qt.WindowCloseButtonHint | Qt.WindowFullscreenButtonHint
|
||||
// QTBUG-35049: Windows is removing features we didn't ask for, even though Qt::CustomizeWindowHint is not set
|
||||
// Otherwise Qt.Window | Qt.WindowFullscreenButtonHint would be enough
|
||||
|
||||
Loader {
|
||||
id: panelLoader
|
||||
anchors.fill: parent
|
||||
sourceComponent: __style ? __style.panel : null
|
||||
onStatusChanged: if (status === Loader.Error) console.error("Failed to load Style for", root)
|
||||
focus: true
|
||||
Loader {
|
||||
id: styleLoader
|
||||
sourceComponent: style
|
||||
property var __control: root
|
||||
property QtObject styleData: QtObject {
|
||||
readonly property bool hasColor: root.color != "#ffffff"
|
||||
}
|
||||
onStatusChanged: if (status === Loader.Error) console.error("Failed to load Style for", root)
|
||||
}
|
||||
|
||||
Qml.Binding {
|
||||
target: toolBar
|
||||
property: "parent"
|
||||
value: __panel.toolBarArea
|
||||
restoreMode: Binding.RestoreBinding
|
||||
}
|
||||
Qml.Binding {
|
||||
target: statusBar
|
||||
property: "parent"
|
||||
value: __panel.statusBarArea
|
||||
restoreMode: Binding.RestoreBinding
|
||||
}
|
||||
|
||||
Qml.Binding {
|
||||
property: "parent"
|
||||
target: menuBar ? menuBar.__contentItem : null
|
||||
when: menuBar && !menuBar.__isNative
|
||||
value: __panel.menuBarArea
|
||||
restoreMode: Binding.RestoreBinding
|
||||
}
|
||||
Qml.Binding {
|
||||
target: menuBar
|
||||
property: "__parentWindow"
|
||||
value: root
|
||||
restoreMode: Binding.RestoreBinding
|
||||
}
|
||||
|
||||
Keys.forwardTo: menuBar ? [menuBar.__contentItem, __panel] : []
|
||||
|
||||
ContentItem {
|
||||
id: contentArea
|
||||
anchors.fill: parent
|
||||
parent: __panel.contentArea
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,85 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Controls.Private 1.0
|
||||
|
||||
/*!
|
||||
\qmltype BusyIndicator
|
||||
\inqmlmodule QtQuick.Controls
|
||||
\since 5.2
|
||||
\ingroup controls
|
||||
\brief A busy indicator.
|
||||
|
||||
\image busyindicator.png
|
||||
|
||||
The busy indicator should be used to indicate activity while content is
|
||||
being loaded or the UI is blocked waiting for a resource to become available.
|
||||
|
||||
The following snippet shows how to use the BusyIndicator:
|
||||
|
||||
\qml
|
||||
BusyIndicator {
|
||||
running: image.status === Image.Loading
|
||||
}
|
||||
\endqml
|
||||
|
||||
You can create a custom appearance for a Busy Indicator by
|
||||
assigning a \l {BusyIndicatorStyle}.
|
||||
*/
|
||||
Control {
|
||||
id: indicator
|
||||
|
||||
/*! \qmlproperty bool BusyIndicator::running
|
||||
|
||||
This property holds whether the busy indicator is currently indicating
|
||||
activity.
|
||||
|
||||
\note The indicator is only visible when this property is set to \c true.
|
||||
|
||||
The default value is \c true.
|
||||
*/
|
||||
property bool running: true
|
||||
|
||||
Accessible.role: Accessible.Indicator
|
||||
Accessible.name: "busy"
|
||||
|
||||
style: Settings.styleComponent(Settings.style, "BusyIndicatorStyle.qml", indicator)
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,134 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQml 2.14 as Qml
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Controls.Private 1.0
|
||||
|
||||
/*!
|
||||
\qmltype Button
|
||||
\inqmlmodule QtQuick.Controls
|
||||
\since 5.1
|
||||
\ingroup controls
|
||||
\brief A push button with a text label.
|
||||
|
||||
\image button.png
|
||||
|
||||
The push button is perhaps the most commonly used widget in any graphical
|
||||
user interface. Pushing (or clicking) a button commands the computer to
|
||||
perform some action or answer a question. Common examples of buttons are
|
||||
OK, Apply, Cancel, Close, Yes, No, and Help buttons.
|
||||
|
||||
\qml
|
||||
Button {
|
||||
text: "Button"
|
||||
}
|
||||
\endqml
|
||||
|
||||
Button is similar to the QPushButton widget.
|
||||
|
||||
You can create a custom appearance for a Button by
|
||||
assigning a \l {ButtonStyle}.
|
||||
*/
|
||||
BasicButton {
|
||||
id: button
|
||||
|
||||
/*! This property holds whether the push button is the default button.
|
||||
Default buttons decide what happens when the user presses enter in a
|
||||
dialog without giving a button explicit focus. \note This property only
|
||||
changes the appearance of the button. The expected behavior needs to be
|
||||
implemented by the user.
|
||||
|
||||
The default value is \c false.
|
||||
*/
|
||||
property bool isDefault: false
|
||||
|
||||
/*! Assign a \l Menu to this property to get a pull-down menu button.
|
||||
|
||||
The default value is \c null.
|
||||
*/
|
||||
property Menu menu: null
|
||||
|
||||
__effectivePressed: __behavior.effectivePressed || menu && menu.__popupVisible
|
||||
|
||||
activeFocusOnTab: true
|
||||
|
||||
Accessible.name: text
|
||||
|
||||
style: Settings.styleComponent(Settings.style, "ButtonStyle.qml", button)
|
||||
|
||||
Qml.Binding {
|
||||
target: menu
|
||||
property: "__minimumWidth"
|
||||
value: button.__panel.width
|
||||
restoreMode: Binding.RestoreBinding
|
||||
}
|
||||
|
||||
Qml.Binding {
|
||||
target: menu
|
||||
property: "__visualItem"
|
||||
value: button
|
||||
restoreMode: Binding.RestoreBinding
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: __behavior
|
||||
function onEffectivePressedChanged() {
|
||||
if (!Settings.hasTouchScreen && __behavior.effectivePressed && menu)
|
||||
popupMenuTimer.start()
|
||||
}
|
||||
function onReleased() {
|
||||
if (Settings.hasTouchScreen && __behavior.containsMouse && menu)
|
||||
popupMenuTimer.start()
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: popupMenuTimer
|
||||
interval: 10
|
||||
onTriggered: {
|
||||
__behavior.keyPressed = false
|
||||
if (Qt.application.layoutDirection === Qt.RightToLeft)
|
||||
menu.__popup(Qt.rect(button.width, button.height, 0, 0), 0)
|
||||
else
|
||||
menu.__popup(Qt.rect(0, button.height, 0, 0), 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,456 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 1.5
|
||||
import QtQuick.Controls.Styles 1.1
|
||||
import QtQuick.Controls.Private 1.0
|
||||
|
||||
/*!
|
||||
\qmltype Calendar
|
||||
\inqmlmodule QtQuick.Controls
|
||||
\since 5.3
|
||||
\ingroup controls
|
||||
\brief Provides a way to select dates from a calendar.
|
||||
|
||||
\image calendar.png
|
||||
|
||||
Calendar allows selection of dates from a grid of days, similar to
|
||||
QCalendarWidget.
|
||||
|
||||
The dates on the calendar can be selected with the mouse, or navigated
|
||||
with the keyboard.
|
||||
|
||||
The selected date can be set through \l selectedDate.
|
||||
A minimum and maximum date can be set through \l minimumDate and
|
||||
\l maximumDate. The earliest minimum date that can be set is 1 January, 1
|
||||
AD. The latest maximum date that can be set is 25 October, 275759 AD.
|
||||
|
||||
\code
|
||||
Calendar {
|
||||
minimumDate: new Date(2017, 0, 1)
|
||||
maximumDate: new Date(2018, 0, 1)
|
||||
}
|
||||
\endcode
|
||||
|
||||
The selected date is displayed using the format in the application's
|
||||
default locale.
|
||||
|
||||
Week numbers can be displayed by setting the weekNumbersVisible property to
|
||||
\c true.
|
||||
|
||||
\qml
|
||||
Calendar {
|
||||
weekNumbersVisible: true
|
||||
}
|
||||
\endqml
|
||||
|
||||
You can create a custom appearance for Calendar by assigning a
|
||||
\l {CalendarStyle}.
|
||||
*/
|
||||
|
||||
Control {
|
||||
id: calendar
|
||||
|
||||
/*!
|
||||
\qmlproperty date Calendar::selectedDate
|
||||
|
||||
The date that has been selected by the user.
|
||||
|
||||
This property is subject to the following validation:
|
||||
|
||||
\list
|
||||
\li If selectedDate is outside the range of \l minimumDate and
|
||||
\l maximumDate, it will be clamped to be within that range.
|
||||
|
||||
\li selectedDate will not be changed if \c undefined or some other
|
||||
invalid value is assigned.
|
||||
|
||||
\li If there are hours, minutes, seconds or milliseconds set, they
|
||||
will be removed.
|
||||
\endlist
|
||||
|
||||
The default value is the current date, which is equivalent to:
|
||||
|
||||
\code
|
||||
new Date()
|
||||
\endcode
|
||||
*/
|
||||
property alias selectedDate: rangedDate.date
|
||||
|
||||
/*!
|
||||
\qmlproperty date Calendar::minimumDate
|
||||
|
||||
The earliest date that this calendar will accept.
|
||||
|
||||
By default, this property is set to the earliest minimum date
|
||||
(1 January, 1 AD).
|
||||
*/
|
||||
property alias minimumDate: rangedDate.minimumDate
|
||||
|
||||
/*!
|
||||
\qmlproperty date Calendar::maximumDate
|
||||
|
||||
The latest date that this calendar will accept.
|
||||
|
||||
By default, this property is set to the latest maximum date
|
||||
(25 October, 275759 AD).
|
||||
*/
|
||||
property alias maximumDate: rangedDate.maximumDate
|
||||
|
||||
/*!
|
||||
This property determines which month in visibleYear is shown on the
|
||||
calendar.
|
||||
|
||||
The month is from \c 0 to \c 11 to be consistent with the JavaScript
|
||||
Date object.
|
||||
|
||||
\sa visibleYear
|
||||
*/
|
||||
property int visibleMonth: selectedDate.getMonth()
|
||||
|
||||
/*!
|
||||
This property determines which year is shown on the
|
||||
calendar.
|
||||
|
||||
\sa visibleMonth
|
||||
*/
|
||||
property int visibleYear: selectedDate.getFullYear()
|
||||
|
||||
onSelectedDateChanged: {
|
||||
// When the selected date changes, the view should move back to that date.
|
||||
visibleMonth = selectedDate.getMonth();
|
||||
visibleYear = selectedDate.getFullYear();
|
||||
}
|
||||
|
||||
RangedDate {
|
||||
id: rangedDate
|
||||
date: new Date()
|
||||
minimumDate: CalendarUtils.minimumCalendarDate
|
||||
maximumDate: CalendarUtils.maximumCalendarDate
|
||||
}
|
||||
|
||||
/*!
|
||||
This property determines the visibility of the frame
|
||||
surrounding the calendar.
|
||||
|
||||
The default value is \c true.
|
||||
*/
|
||||
property bool frameVisible: true
|
||||
|
||||
/*!
|
||||
This property determines the visibility of week numbers.
|
||||
|
||||
The default value is \c false.
|
||||
*/
|
||||
property bool weekNumbersVisible: false
|
||||
|
||||
/*!
|
||||
This property determines the visibility of the navigation bar.
|
||||
\since QtQuick.Controls 1.3
|
||||
|
||||
The default value is \c true.
|
||||
*/
|
||||
property bool navigationBarVisible: true
|
||||
|
||||
/*!
|
||||
\qmlproperty enum Calendar::dayOfWeekFormat
|
||||
|
||||
The format in which the days of the week (in the header) are displayed.
|
||||
|
||||
\c Locale.ShortFormat is the default and recommended format, as
|
||||
\c Locale.NarrowFormat may not be fully supported by each locale (see
|
||||
\l {Locale String Format Types}) and
|
||||
\c Locale.LongFormat may not fit within the header cells.
|
||||
*/
|
||||
property int dayOfWeekFormat: Locale.ShortFormat
|
||||
|
||||
/*!
|
||||
\qmlproperty object Calendar::locale
|
||||
\since QtQuick.Controls 1.6
|
||||
|
||||
This property controls the locale that this calendar uses to display
|
||||
itself.
|
||||
|
||||
The locale affects how dates and day names are localized, as well as
|
||||
which day is considered the first in a week.
|
||||
|
||||
The following example sets an Australian locale:
|
||||
|
||||
\code
|
||||
locale: Qt.locale("en_AU")
|
||||
\endcode
|
||||
|
||||
The default value is equivalent to \c Qt.locale().
|
||||
*/
|
||||
property var locale: Qt.locale()
|
||||
|
||||
// left for compatibility reasons; can be removed in next minor version/Qt 6
|
||||
property alias __locale: calendar.locale
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
This property holds the model that will be used by the Calendar to
|
||||
populate the dates available to the user.
|
||||
*/
|
||||
property CalendarModel __model: CalendarModel {
|
||||
locale: calendar.locale
|
||||
|
||||
// TODO: don't set the hour when QTBUG-56787 is fixed
|
||||
visibleDate: new Date(visibleYear, visibleMonth, 1, 12)
|
||||
}
|
||||
|
||||
style: Settings.styleComponent(Settings.style, "CalendarStyle.qml", calendar)
|
||||
|
||||
/*!
|
||||
\qmlsignal Calendar::hovered(date date)
|
||||
|
||||
Emitted when the mouse hovers over a valid date in the calendar.
|
||||
|
||||
\e date is the date that was hovered over.
|
||||
|
||||
The corresponding handler is \c onHovered.
|
||||
*/
|
||||
signal hovered(date date)
|
||||
|
||||
/*!
|
||||
\qmlsignal Calendar::pressed(date date)
|
||||
|
||||
Emitted when the mouse is pressed on a valid date in the calendar.
|
||||
|
||||
This is also emitted when dragging the mouse to another date while it is pressed.
|
||||
|
||||
\e date is the date that the mouse was pressed on.
|
||||
|
||||
The corresponding handler is \c onPressed.
|
||||
*/
|
||||
signal pressed(date date)
|
||||
|
||||
/*!
|
||||
\qmlsignal Calendar::released(date date)
|
||||
|
||||
Emitted when the mouse is released over a valid date in the calendar.
|
||||
|
||||
\e date is the date that the mouse was released over.
|
||||
|
||||
The corresponding handler is \c onReleased.
|
||||
*/
|
||||
signal released(date date)
|
||||
|
||||
/*!
|
||||
\qmlsignal Calendar::clicked(date date)
|
||||
|
||||
Emitted when the mouse is clicked on a valid date in the calendar.
|
||||
|
||||
\e date is the date that the mouse was clicked on.
|
||||
|
||||
The corresponding handler is \c onClicked.
|
||||
*/
|
||||
signal clicked(date date)
|
||||
|
||||
/*!
|
||||
\qmlsignal Calendar::doubleClicked(date date)
|
||||
|
||||
Emitted when the mouse is double-clicked on a valid date in the calendar.
|
||||
|
||||
\e date is the date that the mouse was double-clicked on.
|
||||
|
||||
The corresponding handler is \c onDoubleClicked.
|
||||
*/
|
||||
signal doubleClicked(date date)
|
||||
|
||||
/*!
|
||||
\qmlsignal Calendar::pressAndHold(date date)
|
||||
\since QtQuick.Controls 1.3
|
||||
|
||||
Emitted when the mouse is pressed and held on a valid date in the calendar.
|
||||
|
||||
\e date is the date that the mouse was pressed on.
|
||||
|
||||
The corresponding handler is \c onPressAndHold.
|
||||
*/
|
||||
signal pressAndHold(date date)
|
||||
|
||||
/*!
|
||||
\qmlmethod void Calendar::showPreviousMonth()
|
||||
Sets visibleMonth to the previous month.
|
||||
*/
|
||||
function showPreviousMonth() {
|
||||
if (visibleMonth === 0) {
|
||||
visibleMonth = CalendarUtils.monthsInAYear - 1;
|
||||
--visibleYear;
|
||||
} else {
|
||||
--visibleMonth;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\qmlmethod void Calendar::showNextMonth()
|
||||
Sets visibleMonth to the next month.
|
||||
*/
|
||||
function showNextMonth() {
|
||||
if (visibleMonth === CalendarUtils.monthsInAYear - 1) {
|
||||
visibleMonth = 0;
|
||||
++visibleYear;
|
||||
} else {
|
||||
++visibleMonth;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\qmlmethod void Calendar::showPreviousYear()
|
||||
Sets visibleYear to the previous year.
|
||||
*/
|
||||
function showPreviousYear() {
|
||||
if (visibleYear - 1 >= minimumDate.getFullYear()) {
|
||||
--visibleYear;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\qmlmethod void Calendar::showNextYear()
|
||||
Sets visibleYear to the next year.
|
||||
*/
|
||||
function showNextYear() {
|
||||
if (visibleYear + 1 <= maximumDate.getFullYear()) {
|
||||
++visibleYear;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Selects the month before the current month in \l selectedDate.
|
||||
*/
|
||||
function __selectPreviousMonth() {
|
||||
calendar.selectedDate = CalendarUtils.setMonth(calendar.selectedDate, calendar.selectedDate.getMonth() - 1);
|
||||
}
|
||||
|
||||
/*!
|
||||
Selects the month after the current month in \l selectedDate.
|
||||
*/
|
||||
function __selectNextMonth() {
|
||||
calendar.selectedDate = CalendarUtils.setMonth(calendar.selectedDate, calendar.selectedDate.getMonth() + 1);
|
||||
}
|
||||
|
||||
/*!
|
||||
Selects the week before the current week in \l selectedDate.
|
||||
*/
|
||||
function __selectPreviousWeek() {
|
||||
var newDate = new Date(calendar.selectedDate);
|
||||
newDate.setDate(newDate.getDate() - CalendarUtils.daysInAWeek);
|
||||
calendar.selectedDate = newDate;
|
||||
}
|
||||
|
||||
/*!
|
||||
Selects the week after the current week in \l selectedDate.
|
||||
*/
|
||||
function __selectNextWeek() {
|
||||
var newDate = new Date(calendar.selectedDate);
|
||||
newDate.setDate(newDate.getDate() + CalendarUtils.daysInAWeek);
|
||||
calendar.selectedDate = newDate;
|
||||
}
|
||||
|
||||
/*!
|
||||
Selects the first day of the current month in \l selectedDate.
|
||||
*/
|
||||
function __selectFirstDayOfMonth() {
|
||||
var newDate = new Date(calendar.selectedDate);
|
||||
newDate.setDate(1);
|
||||
calendar.selectedDate = newDate;
|
||||
}
|
||||
|
||||
/*!
|
||||
Selects the last day of the current month in \l selectedDate.
|
||||
*/
|
||||
function __selectLastDayOfMonth() {
|
||||
var newDate = new Date(calendar.selectedDate);
|
||||
newDate.setDate(CalendarUtils.daysInMonth(newDate));
|
||||
calendar.selectedDate = newDate;
|
||||
}
|
||||
|
||||
/*!
|
||||
Selects the day before the current day in \l selectedDate.
|
||||
*/
|
||||
function __selectPreviousDay() {
|
||||
var newDate = new Date(calendar.selectedDate);
|
||||
newDate.setDate(newDate.getDate() - 1);
|
||||
calendar.selectedDate = newDate;
|
||||
}
|
||||
|
||||
/*!
|
||||
Selects the day after the current day in \l selectedDate.
|
||||
*/
|
||||
function __selectNextDay() {
|
||||
var newDate = new Date(calendar.selectedDate);
|
||||
newDate.setDate(newDate.getDate() + 1);
|
||||
calendar.selectedDate = newDate;
|
||||
}
|
||||
|
||||
Keys.onLeftPressed: {
|
||||
calendar.__selectPreviousDay();
|
||||
}
|
||||
|
||||
Keys.onUpPressed: {
|
||||
calendar.__selectPreviousWeek();
|
||||
}
|
||||
|
||||
Keys.onDownPressed: {
|
||||
calendar.__selectNextWeek();
|
||||
}
|
||||
|
||||
Keys.onRightPressed: {
|
||||
calendar.__selectNextDay();
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
if (event.key === Qt.Key_Home) {
|
||||
calendar.__selectFirstDayOfMonth();
|
||||
event.accepted = true;
|
||||
} else if (event.key === Qt.Key_End) {
|
||||
calendar.__selectLastDayOfMonth();
|
||||
event.accepted = true;
|
||||
} else if (event.key === Qt.Key_PageUp) {
|
||||
calendar.__selectPreviousMonth();
|
||||
event.accepted = true;
|
||||
} else if (event.key === Qt.Key_PageDown) {
|
||||
calendar.__selectNextMonth();
|
||||
event.accepted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,197 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Controls.Private 1.0
|
||||
|
||||
/*!
|
||||
\qmltype CheckBox
|
||||
\inqmlmodule QtQuick.Controls
|
||||
\since 5.1
|
||||
\ingroup controls
|
||||
\brief A checkbox with a text label.
|
||||
|
||||
\image checkbox.png
|
||||
|
||||
A CheckBox is an option button that can be toggled on (checked) or off
|
||||
(unchecked). Checkboxes are typically used to represent features in an
|
||||
application that can be enabled or disabled without affecting others.
|
||||
|
||||
The state of the checkbox can be set with the \l {AbstractCheckable::checked}{checked} property.
|
||||
|
||||
In addition to the checked and unchecked states, there is a third state:
|
||||
partially checked. This state indicates that the
|
||||
regular checked/unchecked state can not be determined; generally because of
|
||||
other states that affect the checkbox. This state is useful when several
|
||||
child nodes are selected in a treeview, for example.
|
||||
|
||||
The partially checked state can be made available to the user by setting
|
||||
\l partiallyCheckedEnabled to \c true, or set directly by setting
|
||||
\l checkedState to \c Qt.PartiallyChecked. \l checkedState behaves
|
||||
identically to \l {AbstractCheckable::checked}{checked} when \l partiallyCheckedEnabled
|
||||
is \c false; setting one will appropriately set the other.
|
||||
|
||||
The label is shown next to the checkbox, and you can set the label text using its
|
||||
\l {AbstractCheckable::text}{text} property.
|
||||
|
||||
\qml
|
||||
Column {
|
||||
CheckBox {
|
||||
text: qsTr("Breakfast")
|
||||
checked: true
|
||||
}
|
||||
CheckBox {
|
||||
text: qsTr("Lunch")
|
||||
}
|
||||
CheckBox {
|
||||
text: qsTr("Dinner")
|
||||
checked: true
|
||||
}
|
||||
}
|
||||
\endqml
|
||||
|
||||
Whenever a CheckBox is clicked, it emits the \l {AbstractCheckable::clicked}{clicked()} signal.
|
||||
|
||||
You can create a custom appearance for a CheckBox by
|
||||
assigning a \l {CheckBoxStyle}.
|
||||
*/
|
||||
|
||||
AbstractCheckable {
|
||||
id: checkBox
|
||||
|
||||
/*!
|
||||
\qmlproperty enumeration CheckBox::checkedState
|
||||
|
||||
This property indicates the current checked state of the checkbox.
|
||||
|
||||
Possible values:
|
||||
\c Qt.UnChecked - The checkbox is not checked (default).
|
||||
\c Qt.Checked - The checkbox is checked.
|
||||
\c Qt.PartiallyChecked - The checkbox is in a partially checked (or
|
||||
"mixed") state.
|
||||
|
||||
The \l {AbstractCheckable::checked}{checked} property also determines whether
|
||||
this property is \c Qt.Checked or \c Qt.UnChecked, and vice versa.
|
||||
*/
|
||||
property int checkedState: checked ? Qt.Checked : Qt.Unchecked
|
||||
|
||||
/*!
|
||||
This property determines whether the \c Qt.PartiallyChecked state is
|
||||
available.
|
||||
|
||||
A checkbox may be in a partially checked state when the regular checked
|
||||
state can not be determined.
|
||||
|
||||
Setting \l checkedState to \c Qt.PartiallyChecked will implicitly set
|
||||
this property to \c true.
|
||||
|
||||
If this property is \c true, \l {AbstractCheckable::checked}{checked} will be \c false.
|
||||
|
||||
By default, this property is \c false.
|
||||
*/
|
||||
property bool partiallyCheckedEnabled: false
|
||||
|
||||
/*!
|
||||
\internal
|
||||
True if onCheckedChanged should be ignored because we were reacting
|
||||
to onCheckedStateChanged.
|
||||
*/
|
||||
property bool __ignoreChecked: false
|
||||
|
||||
/*!
|
||||
\internal
|
||||
True if onCheckedStateChanged should be ignored because we were reacting
|
||||
to onCheckedChanged.
|
||||
*/
|
||||
property bool __ignoreCheckedState: false
|
||||
|
||||
style: Settings.styleComponent(Settings.style, "CheckBoxStyle.qml", checkBox)
|
||||
|
||||
activeFocusOnTab: true
|
||||
|
||||
Accessible.role: Accessible.CheckBox
|
||||
Accessible.name: text
|
||||
|
||||
__cycleStatesHandler: __cycleCheckBoxStates
|
||||
|
||||
onCheckedChanged: {
|
||||
if (!__ignoreChecked) {
|
||||
__ignoreCheckedState = true;
|
||||
checkedState = checked ? Qt.Checked : Qt.Unchecked;
|
||||
__ignoreCheckedState = false;
|
||||
}
|
||||
}
|
||||
|
||||
onCheckedStateChanged: {
|
||||
__ignoreChecked = true;
|
||||
if (checkedState === Qt.PartiallyChecked) {
|
||||
partiallyCheckedEnabled = true;
|
||||
checked = false;
|
||||
} else if (!__ignoreCheckedState) {
|
||||
checked = checkedState === Qt.Checked;
|
||||
}
|
||||
__ignoreChecked = false;
|
||||
}
|
||||
|
||||
onPartiallyCheckedEnabledChanged: {
|
||||
if (exclusiveGroup && partiallyCheckedEnabled) {
|
||||
console.warn("Cannot have partially checked boxes in an ExclusiveGroup.");
|
||||
}
|
||||
}
|
||||
|
||||
onExclusiveGroupChanged: {
|
||||
if (exclusiveGroup && partiallyCheckedEnabled) {
|
||||
console.warn("Cannot have partially checked boxes in an ExclusiveGroup.");
|
||||
}
|
||||
}
|
||||
|
||||
/*! \internal */
|
||||
function __cycleCheckBoxStates() {
|
||||
if (!partiallyCheckedEnabled) {
|
||||
checked = !checked;
|
||||
} else {
|
||||
switch (checkedState) {
|
||||
case Qt.Unchecked: checkedState = Qt.Checked; break;
|
||||
case Qt.Checked: checkedState = Qt.PartiallyChecked; break;
|
||||
case Qt.PartiallyChecked: checkedState = Qt.Unchecked; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,717 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQml 2.14 as Qml
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Controls.Private 1.0
|
||||
|
||||
/*!
|
||||
\qmltype ComboBox
|
||||
\inqmlmodule QtQuick.Controls
|
||||
\since 5.1
|
||||
\ingroup controls
|
||||
\brief Provides a drop-down list functionality.
|
||||
|
||||
\image combobox.png
|
||||
|
||||
Add items to the ComboBox by assigning it a ListModel, or a list of strings
|
||||
to the \l model property.
|
||||
|
||||
\qml
|
||||
ComboBox {
|
||||
width: 200
|
||||
model: [ "Banana", "Apple", "Coconut" ]
|
||||
}
|
||||
\endqml
|
||||
|
||||
In this example we are demonstrating how to use a ListModel with a combo box.
|
||||
|
||||
\qml
|
||||
ComboBox {
|
||||
currentIndex: 2
|
||||
model: ListModel {
|
||||
id: cbItems
|
||||
ListElement { text: "Banana"; color: "Yellow" }
|
||||
ListElement { text: "Apple"; color: "Green" }
|
||||
ListElement { text: "Coconut"; color: "Brown" }
|
||||
}
|
||||
width: 200
|
||||
onCurrentIndexChanged: console.debug(cbItems.get(currentIndex).text + ", " + cbItems.get(currentIndex).color)
|
||||
}
|
||||
\endqml
|
||||
|
||||
You can make a combo box editable by setting the \l editable property. An editable combo box will
|
||||
autocomplete its text based on what is available in the model.
|
||||
|
||||
In the next example we demonstrate how you can append content to an editable combo box by
|
||||
reacting to the \l accepted signal. Note that you have to explicitly prevent duplicates.
|
||||
|
||||
\qml
|
||||
ComboBox {
|
||||
editable: true
|
||||
model: ListModel {
|
||||
id: model
|
||||
ListElement { text: "Banana"; color: "Yellow" }
|
||||
ListElement { text: "Apple"; color: "Green" }
|
||||
ListElement { text: "Coconut"; color: "Brown" }
|
||||
}
|
||||
onAccepted: {
|
||||
if (find(currentText) === -1) {
|
||||
model.append({text: editText})
|
||||
currentIndex = find(editText)
|
||||
}
|
||||
}
|
||||
}
|
||||
\endqml
|
||||
|
||||
|
||||
You can create a custom appearance for a ComboBox by
|
||||
assigning a \l {ComboBoxStyle}.
|
||||
*/
|
||||
|
||||
Control {
|
||||
id: comboBox
|
||||
|
||||
/*! \qmlproperty model ComboBox::model
|
||||
The model to populate the ComboBox from.
|
||||
|
||||
Changing the model after initialization will reset \l currentIndex to \c 0.
|
||||
*/
|
||||
property alias model: popupItems.model
|
||||
|
||||
/*! The model role used for populating the ComboBox. */
|
||||
property string textRole: ""
|
||||
|
||||
/*! \qmlproperty int ComboBox::currentIndex
|
||||
The index of the currently selected item in the ComboBox.
|
||||
|
||||
Setting currentIndex to \c -1 will reset the selection and clear the text
|
||||
label. If \l editable is \c true, you may also need to manually clear \l editText.
|
||||
|
||||
\sa model
|
||||
*/
|
||||
property alias currentIndex: popup.__selectedIndex
|
||||
|
||||
/*! \qmlproperty string ComboBox::currentText
|
||||
The text of the currently selected item in the ComboBox.
|
||||
|
||||
\note Since \c currentText depends on \c currentIndex, there's no way to ensure \c currentText
|
||||
will be up to date whenever a \c onCurrentIndexChanged handler is called.
|
||||
*/
|
||||
readonly property alias currentText: popup.currentText
|
||||
|
||||
/*! This property holds whether the combo box can be edited by the user.
|
||||
The default value is \c false.
|
||||
\since QtQuick.Controls 1.1
|
||||
*/
|
||||
property bool editable: false
|
||||
|
||||
/*! \qmlproperty string ComboBox::editText
|
||||
\since QtQuick.Controls 1.1
|
||||
This property specifies text being manipulated by the user for an editable combo box.
|
||||
*/
|
||||
property alias editText: input.text
|
||||
|
||||
/*! \qmlproperty enumeration ComboBox::inputMethodHints
|
||||
\since QtQuick.Controls 1.5
|
||||
Provides hints to the input method about the expected content of the combo box and how it
|
||||
should operate.
|
||||
|
||||
The value is a bit-wise combination of flags or \c Qt.ImhNone if no hints are set.
|
||||
|
||||
Flags that alter behavior are:
|
||||
|
||||
\list
|
||||
\li Qt.ImhHiddenText - Characters should be hidden, as is typically used when entering passwords.
|
||||
\li Qt.ImhSensitiveData - Typed text should not be stored by the active input method
|
||||
in any persistent storage like predictive user dictionary.
|
||||
\li Qt.ImhNoAutoUppercase - The input method should not try to automatically switch to upper case
|
||||
when a sentence ends.
|
||||
\li Qt.ImhPreferNumbers - Numbers are preferred (but not required).
|
||||
\li Qt.ImhPreferUppercase - Upper case letters are preferred (but not required).
|
||||
\li Qt.ImhPreferLowercase - Lower case letters are preferred (but not required).
|
||||
\li Qt.ImhNoPredictiveText - Do not use predictive text (i.e. dictionary lookup) while typing.
|
||||
|
||||
\li Qt.ImhDate - The text editor functions as a date field.
|
||||
\li Qt.ImhTime - The text editor functions as a time field.
|
||||
\endlist
|
||||
|
||||
Flags that restrict input (exclusive flags) are:
|
||||
|
||||
\list
|
||||
\li Qt.ImhDigitsOnly - Only digits are allowed.
|
||||
\li Qt.ImhFormattedNumbersOnly - Only number input is allowed. This includes decimal point and minus sign.
|
||||
\li Qt.ImhUppercaseOnly - Only upper case letter input is allowed.
|
||||
\li Qt.ImhLowercaseOnly - Only lower case letter input is allowed.
|
||||
\li Qt.ImhDialableCharactersOnly - Only characters suitable for phone dialing are allowed.
|
||||
\li Qt.ImhEmailCharactersOnly - Only characters suitable for email addresses are allowed.
|
||||
\li Qt.ImhUrlCharactersOnly - Only characters suitable for URLs are allowed.
|
||||
\endlist
|
||||
|
||||
Masks:
|
||||
|
||||
\list
|
||||
\li Qt.ImhExclusiveInputMask - This mask yields nonzero if any of the exclusive flags are used.
|
||||
\endlist
|
||||
*/
|
||||
property alias inputMethodHints: input.inputMethodHints
|
||||
|
||||
/*! This property specifies whether the combobox should gain active focus when pressed.
|
||||
The default value is \c false. */
|
||||
property bool activeFocusOnPress: false
|
||||
|
||||
/*! \qmlproperty bool ComboBox::pressed
|
||||
|
||||
This property holds whether the button is being pressed. */
|
||||
readonly property bool pressed: mouseArea.effectivePressed || popup.__popupVisible
|
||||
|
||||
/*! \qmlproperty bool ComboBox::hovered
|
||||
|
||||
This property indicates whether the control is being hovered.
|
||||
*/
|
||||
readonly property bool hovered: mouseArea.containsMouse || input.containsMouse
|
||||
|
||||
/*! \qmlproperty int ComboBox::count
|
||||
\since QtQuick.Controls 1.1
|
||||
This property holds the number of items in the combo box.
|
||||
*/
|
||||
readonly property alias count: popupItems.count
|
||||
|
||||
/*! \qmlmethod string ComboBox::textAt(int index)
|
||||
Returns the text for a given \a index.
|
||||
If an invalid index is provided, \c null is returned
|
||||
\since QtQuick.Controls 1.1
|
||||
*/
|
||||
function textAt (index) {
|
||||
if (index >= count || index < 0)
|
||||
return null;
|
||||
return popupItems.objectAt(index).text;
|
||||
}
|
||||
|
||||
/*! \qmlmethod int ComboBox::find(string text)
|
||||
Finds and returns the index of a given \a text
|
||||
If no match is found, \c -1 is returned. The search is case sensitive.
|
||||
\since QtQuick.Controls 1.1
|
||||
*/
|
||||
function find (text) {
|
||||
return input.find(text, Qt.MatchExactly)
|
||||
}
|
||||
|
||||
/*!
|
||||
\qmlproperty Validator ComboBox::validator
|
||||
\since QtQuick.Controls 1.1
|
||||
|
||||
Allows you to set a text validator for an editable ComboBox.
|
||||
When a validator is set,
|
||||
the text field will only accept input which leaves the text property in
|
||||
an intermediate state. The accepted signal will only be sent
|
||||
if the text is in an acceptable state when enter is pressed.
|
||||
|
||||
Currently supported validators are \l[QtQuick]{IntValidator},
|
||||
\l[QtQuick]{DoubleValidator}, and \l[QtQuick]{RegExpValidator}. An
|
||||
example of using validators is shown below, which allows input of
|
||||
integers between 11 and 31 into the text field:
|
||||
|
||||
\note This property is only applied when \l editable is \c true
|
||||
|
||||
\qml
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
|
||||
ComboBox {
|
||||
editable: true
|
||||
model: 10
|
||||
validator: IntValidator {bottom: 0; top: 10;}
|
||||
focus: true
|
||||
}
|
||||
\endqml
|
||||
|
||||
\sa acceptableInput, accepted, editable
|
||||
*/
|
||||
property alias validator: input.validator
|
||||
|
||||
/*!
|
||||
\since QtQuick.Controls 1.3
|
||||
|
||||
This property contains the edit \l Menu for working
|
||||
with text selection. Set it to \c null if no menu
|
||||
is wanted.
|
||||
|
||||
\note The menu is only in use when \l editable is \c true
|
||||
*/
|
||||
property Component menu: input.editMenu.defaultMenu
|
||||
|
||||
/*!
|
||||
\qmlproperty bool ComboBox::acceptableInput
|
||||
\since QtQuick.Controls 1.1
|
||||
|
||||
Returns \c true if the combo box contains acceptable
|
||||
text in the editable text field.
|
||||
|
||||
If a validator was set, this property will return \c
|
||||
true if the current text satisfies the validator or mask as
|
||||
a final string (not as an intermediate string).
|
||||
|
||||
\sa validator, accepted
|
||||
|
||||
*/
|
||||
readonly property alias acceptableInput: input.acceptableInput
|
||||
|
||||
/*!
|
||||
\qmlproperty bool ComboBox::selectByMouse
|
||||
\since QtQuick.Controls 1.3
|
||||
|
||||
This property determines if the user can select the text in
|
||||
the editable text field with the mouse.
|
||||
|
||||
The default value is \c true.
|
||||
*/
|
||||
property bool selectByMouse: true
|
||||
|
||||
/*!
|
||||
\qmlproperty bool ComboBox::inputMethodComposing
|
||||
\since QtQuick.Controls 1.3
|
||||
|
||||
This property holds whether an editable ComboBox has partial text input from an input method.
|
||||
|
||||
While it is composing an input method may rely on mouse or key events from the ComboBox
|
||||
to edit or commit the partial text. This property can be used to determine when to disable
|
||||
events handlers that may interfere with the correct operation of an input method.
|
||||
*/
|
||||
readonly property bool inputMethodComposing: !!input.inputMethodComposing
|
||||
|
||||
/*!
|
||||
\qmlsignal ComboBox::accepted()
|
||||
\since QtQuick.Controls 1.1
|
||||
|
||||
This signal is emitted when the Return or Enter key is pressed on an
|
||||
\l editable combo box. If the confirmed string is not currently in the model,
|
||||
the currentIndex will be set to -1 and the \l currentText will be updated
|
||||
accordingly.
|
||||
|
||||
\note If there is a \l validator set on the combobox,
|
||||
the signal will only be emitted if the input is in an acceptable state.
|
||||
|
||||
The corresponding handler is \c onAccepted.
|
||||
*/
|
||||
signal accepted
|
||||
|
||||
/*!
|
||||
\qmlsignal ComboBox::activated(int index)
|
||||
\since QtQuick.Controls 1.1
|
||||
|
||||
This signal is similar to currentIndex changed, but will only
|
||||
be emitted if the combo box index was changed by the user, not
|
||||
when set programmatically.
|
||||
|
||||
\e index is the activated model index, or \c -1 if a new string is
|
||||
accepted.
|
||||
|
||||
The corresponding handler is \c onActivated.
|
||||
*/
|
||||
signal activated(int index)
|
||||
|
||||
/*!
|
||||
\qmlmethod void ComboBox::selectAll()
|
||||
\since QtQuick.Controls 1.1
|
||||
|
||||
Causes all \l editText to be selected.
|
||||
*/
|
||||
function selectAll() {
|
||||
input.selectAll()
|
||||
}
|
||||
|
||||
/*! \internal */
|
||||
function __selectPrevItem() {
|
||||
input.blockUpdate = true
|
||||
if (currentIndex > 0) {
|
||||
currentIndex--;
|
||||
input.text = popup.currentText;
|
||||
activated(currentIndex);
|
||||
}
|
||||
input.blockUpdate = false;
|
||||
}
|
||||
|
||||
/*! \internal */
|
||||
function __selectNextItem() {
|
||||
input.blockUpdate = true;
|
||||
if (currentIndex < popupItems.count - 1) {
|
||||
currentIndex++;
|
||||
input.text = popup.currentText;
|
||||
activated(currentIndex);
|
||||
}
|
||||
input.blockUpdate = false;
|
||||
}
|
||||
|
||||
/*! \internal */
|
||||
property var __popup: popup
|
||||
|
||||
style: Settings.styleComponent(Settings.style, "ComboBoxStyle.qml", comboBox)
|
||||
|
||||
activeFocusOnTab: true
|
||||
|
||||
Accessible.name: editable ? editText : currentText
|
||||
Accessible.role: Accessible.ComboBox
|
||||
Accessible.editable: editable
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
property bool overridePressed: false
|
||||
readonly property bool effectivePressed: (pressed || overridePressed) && containsMouse
|
||||
anchors.fill: parent
|
||||
hoverEnabled: Settings.hoverEnabled
|
||||
onPressed: {
|
||||
if (comboBox.activeFocusOnPress)
|
||||
forceActiveFocus()
|
||||
if (!Settings.hasTouchScreen)
|
||||
popup.toggleShow()
|
||||
else
|
||||
overridePressed = true
|
||||
}
|
||||
onCanceled: overridePressed = false
|
||||
onClicked: {
|
||||
if (Settings.hasTouchScreen)
|
||||
popup.toggleShow()
|
||||
overridePressed = false
|
||||
}
|
||||
onWheel: {
|
||||
if (wheel.angleDelta.y > 0) {
|
||||
__selectPrevItem();
|
||||
} else if (wheel.angleDelta.y < 0){
|
||||
__selectNextItem();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (currentIndex === -1)
|
||||
currentIndex = 0
|
||||
|
||||
popup.ready = true
|
||||
popup.resolveTextValue(textRole)
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
// Perform one-character based lookup for non-editable combo box
|
||||
if (!editable && event.text.length > 0) {
|
||||
var index = input.find(event.text, Qt.MatchStartsWith);
|
||||
if (index >= 0 && index !== currentIndex) {
|
||||
currentIndex = index;
|
||||
activated(currentIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TextInputWithHandles {
|
||||
id: input
|
||||
|
||||
visible: editable
|
||||
enabled: editable
|
||||
focus: true
|
||||
clip: contentWidth > width
|
||||
|
||||
control: comboBox
|
||||
cursorHandle: __style ? __style.__cursorHandle : undefined
|
||||
selectionHandle: __style ? __style.__selectionHandle : undefined
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: __style ? __style.padding.left : 0
|
||||
anchors.topMargin: __style ? __style.padding.top : 0
|
||||
anchors.rightMargin: __style ? __panel.dropDownButtonWidth + __style.padding.right : 0
|
||||
anchors.bottomMargin: __style ? __style.padding.bottom: 0
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
font: __panel && __panel.font !== undefined ? __panel.font : TextSingleton.font
|
||||
renderType: __style ? __style.renderType : Text.NativeRendering
|
||||
color: __panel ? __panel.textColor : "black"
|
||||
selectionColor: __panel ? __panel.selectionColor : "blue"
|
||||
selectedTextColor: __panel ? __panel.selectedTextColor : "white"
|
||||
onAccepted: {
|
||||
var idx = input.find(editText, Qt.MatchFixedString)
|
||||
if (idx > -1) {
|
||||
editTextMatches = true;
|
||||
currentIndex = idx;
|
||||
editText = textAt(idx);
|
||||
} else {
|
||||
editTextMatches = false;
|
||||
currentIndex = -1;
|
||||
popup.currentText = editText;
|
||||
}
|
||||
comboBox.accepted();
|
||||
}
|
||||
|
||||
property bool blockUpdate: false
|
||||
property string prevText
|
||||
property bool editTextMatches: true
|
||||
|
||||
function find (text, searchType) {
|
||||
for (var i = 0 ; i < popupItems.count ; ++i) {
|
||||
var currentString = popupItems.objectAt(i).text
|
||||
if (searchType === Qt.MatchExactly) {
|
||||
if (text === currentString)
|
||||
return i;
|
||||
} else if (searchType === Qt.CaseSensitive) {
|
||||
if (currentString.indexOf(text) === 0)
|
||||
return i;
|
||||
} else if (searchType === Qt.MatchFixedString) {
|
||||
if (currentString.toLowerCase().indexOf(text.toLowerCase()) === 0
|
||||
&& currentString.length === text.length)
|
||||
return i;
|
||||
} else if (currentString.toLowerCase().indexOf(text.toLowerCase()) === 0) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Finds first entry and shortest entry. Used by editable combo
|
||||
function tryComplete (inputText) {
|
||||
var candidate = "";
|
||||
var shortestString = "";
|
||||
for (var i = 0 ; i < popupItems.count ; ++i) {
|
||||
var currentString = popupItems.objectAt(i).text;
|
||||
|
||||
if (currentString.toLowerCase().indexOf(inputText.toLowerCase()) === 0) {
|
||||
if (candidate.length) { // Find smallest possible match
|
||||
var cmp = 0;
|
||||
|
||||
// We try to complete the shortest string that matches our search
|
||||
if (currentString.length < candidate.length)
|
||||
candidate = currentString
|
||||
|
||||
while (cmp < Math.min(currentString.length, shortestString.length)
|
||||
&& shortestString[cmp].toLowerCase() === currentString[cmp].toLowerCase())
|
||||
cmp++;
|
||||
shortestString = shortestString.substring(0, cmp);
|
||||
} else { // First match, select as current index and find other matches
|
||||
candidate = currentString;
|
||||
shortestString = currentString;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (candidate.length)
|
||||
return inputText + candidate.substring(inputText.length, candidate.length);
|
||||
return inputText;
|
||||
}
|
||||
|
||||
property bool allowComplete: false
|
||||
Keys.forwardTo: comboBox
|
||||
Keys.onPressed: allowComplete = (event.key !== Qt.Key_Backspace && event.key !== Qt.Key_Delete);
|
||||
|
||||
onTextChanged: {
|
||||
if (editable && !blockUpdate && allowComplete && text.length > 0) {
|
||||
var completed = input.tryComplete(text)
|
||||
if (completed.length > text.length) {
|
||||
var oldtext = input.text;
|
||||
input.text = completed;
|
||||
input.select(text.length, oldtext.length);
|
||||
}
|
||||
}
|
||||
prevText = text
|
||||
}
|
||||
}
|
||||
|
||||
Qml.Binding {
|
||||
target: input
|
||||
property: "text"
|
||||
value: popup.currentText
|
||||
when: input.editTextMatches
|
||||
restoreMode: Binding.RestoreBinding
|
||||
}
|
||||
|
||||
onTextRoleChanged: popup.resolveTextValue(textRole)
|
||||
|
||||
ExclusiveGroup { id: eg }
|
||||
|
||||
Menu {
|
||||
id: popup
|
||||
objectName: "popup"
|
||||
|
||||
style: isPopup ? __style.__popupStyle : __style.__dropDownStyle
|
||||
|
||||
property string currentText: selectedText
|
||||
onSelectedTextChanged: popup.currentText = selectedText
|
||||
|
||||
property string selectedText
|
||||
property int triggeredIndex: -1
|
||||
on__SelectedIndexChanged: {
|
||||
if (__selectedIndex === -1)
|
||||
popup.currentText = ""
|
||||
else
|
||||
updateSelectedText()
|
||||
if (triggeredIndex >= 0 && triggeredIndex == __selectedIndex) {
|
||||
activated(currentIndex)
|
||||
triggeredIndex = -1
|
||||
}
|
||||
}
|
||||
property string textRole: ""
|
||||
|
||||
property bool ready: false
|
||||
property bool isPopup: !editable && !!__panel && __panel.popup
|
||||
|
||||
property int y: isPopup ? (comboBox.__panel.height - comboBox.__panel.implicitHeight) / 2.0 : comboBox.__panel.height
|
||||
__minimumWidth: comboBox.width
|
||||
__visualItem: comboBox
|
||||
|
||||
property bool modelIsArray: false
|
||||
|
||||
Instantiator {
|
||||
id: popupItems
|
||||
active: false
|
||||
|
||||
property bool updatingModel: false
|
||||
onModelChanged: {
|
||||
popup.modelIsArray = !!model ? model.constructor === Array : false
|
||||
if (active) {
|
||||
if (updatingModel && popup.__selectedIndex === 0) {
|
||||
// We still want to update the currentText
|
||||
popup.updateSelectedText()
|
||||
} else {
|
||||
updatingModel = true
|
||||
popup.__selectedIndex = 0
|
||||
}
|
||||
}
|
||||
popup.resolveTextValue(comboBox.textRole)
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
text: popup.textRole === '' ?
|
||||
modelData :
|
||||
((popup.modelIsArray ? modelData[popup.textRole] : model[popup.textRole]) || '')
|
||||
onTriggered: {
|
||||
popup.triggeredIndex = index
|
||||
comboBox.editText = text
|
||||
}
|
||||
onTextChanged: if (index === currentIndex) popup.updateSelectedText();
|
||||
checkable: true
|
||||
exclusiveGroup: eg
|
||||
}
|
||||
onObjectAdded: {
|
||||
popup.insertItem(index, object)
|
||||
if (!updatingModel && index === popup.__selectedIndex)
|
||||
popup.selectedText = object["text"]
|
||||
}
|
||||
onObjectRemoved: popup.removeItem(object)
|
||||
|
||||
}
|
||||
|
||||
function resolveTextValue(initialTextRole) {
|
||||
if (!ready || !model) {
|
||||
popupItems.active = false
|
||||
return;
|
||||
}
|
||||
|
||||
var get = model['get'];
|
||||
if (!get && popup.modelIsArray && !!model[0]) {
|
||||
if (model[0].constructor !== String && model[0].constructor !== Number)
|
||||
get = function(i) { return model[i]; }
|
||||
}
|
||||
|
||||
var modelMayHaveRoles = get !== undefined
|
||||
textRole = initialTextRole
|
||||
if (textRole === "" && modelMayHaveRoles && get(0)) {
|
||||
// No text role set, check whether model has a suitable role
|
||||
// If 'text' is found, or there's only one role, pick that.
|
||||
var listElement = get(0)
|
||||
var roleName = ""
|
||||
var roleCount = 0
|
||||
for (var role in listElement) {
|
||||
if (listElement[role].constructor === Function)
|
||||
continue;
|
||||
if (role === "text") {
|
||||
roleName = role
|
||||
break
|
||||
} else if (!roleName) {
|
||||
roleName = role
|
||||
}
|
||||
++roleCount
|
||||
}
|
||||
if (roleCount > 1 && roleName !== "text") {
|
||||
console.warn("No suitable 'textRole' found for ComboBox.")
|
||||
} else {
|
||||
textRole = roleName
|
||||
}
|
||||
}
|
||||
|
||||
if (!popupItems.active)
|
||||
popupItems.active = true
|
||||
else
|
||||
updateSelectedText()
|
||||
}
|
||||
|
||||
function toggleShow() {
|
||||
if (popup.__popupVisible) {
|
||||
popup.__dismissAndDestroy()
|
||||
} else {
|
||||
if (items[__selectedIndex])
|
||||
items[__selectedIndex].checked = true
|
||||
__currentIndex = comboBox.currentIndex
|
||||
if (Qt.application.layoutDirection === Qt.RightToLeft)
|
||||
__popup(Qt.rect(comboBox.width, y, 0, 0), isPopup ? __selectedIndex : 0)
|
||||
else
|
||||
__popup(Qt.rect(0, y, 0, 0), isPopup ? __selectedIndex : 0)
|
||||
}
|
||||
}
|
||||
|
||||
function updateSelectedText() {
|
||||
var selectedItem;
|
||||
if (__selectedIndex !== -1 && (selectedItem = items[__selectedIndex])) {
|
||||
input.editTextMatches = true
|
||||
selectedText = Qt.binding(function () { return selectedItem.text })
|
||||
if (currentText !== selectedText) // __selectedIndex went form -1 to 0
|
||||
selectedTextChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The key bindings below will only be in use when popup is
|
||||
// not visible. Otherwise, native popup key handling will take place:
|
||||
Keys.onSpacePressed: {
|
||||
if (!editable)
|
||||
popup.toggleShow()
|
||||
else
|
||||
event.accepted = false
|
||||
}
|
||||
|
||||
Keys.onUpPressed: __selectPrevItem()
|
||||
Keys.onDownPressed: __selectNextItem()
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,232 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Controls.Private 1.0
|
||||
import QtQuick.Controls.Styles 1.1
|
||||
import QtQuick.Layouts 1.0
|
||||
|
||||
/*!
|
||||
\qmltype GroupBox
|
||||
\inqmlmodule QtQuick.Controls
|
||||
\since 5.1
|
||||
\ingroup controls
|
||||
\brief GroupBox provides a group box frame with a title.
|
||||
|
||||
\image groupbox.png
|
||||
|
||||
A group box provides a frame, a title on top and displays various other controls inside itself. Group boxes can also be checkable.
|
||||
|
||||
Child controls in checkable group boxes are enabled or disabled depending on whether or not the group box is checked.
|
||||
|
||||
You can minimize the space consumption of a group box by enabling the flat property.
|
||||
In most styles, enabling this property results in the removal of the left, right and bottom edges of the frame.
|
||||
|
||||
To add content to a group box, you can reparent it to its contentItem property.
|
||||
|
||||
The implicit size of the GroupBox is calculated based on the size of its content. If you want to anchor
|
||||
items inside the group box, you must specify an explicit width and height on the GroupBox itself.
|
||||
|
||||
The following example shows how we use a GroupBox:
|
||||
|
||||
\qml
|
||||
GroupBox {
|
||||
title: "Joining for?"
|
||||
|
||||
Column {
|
||||
spacing: 10
|
||||
|
||||
CheckBox {
|
||||
text: "Breakfast"
|
||||
checked: true
|
||||
}
|
||||
CheckBox {
|
||||
text: "Lunch"
|
||||
checked: false
|
||||
}
|
||||
CheckBox {
|
||||
text: "Dinner"
|
||||
checked: true
|
||||
}
|
||||
}
|
||||
}
|
||||
\endqml
|
||||
|
||||
\sa CheckBox, RadioButton, Layout
|
||||
|
||||
*/
|
||||
|
||||
FocusScope {
|
||||
id: groupbox
|
||||
|
||||
/*!
|
||||
This property holds the group box title text.
|
||||
|
||||
There is no default title text.
|
||||
*/
|
||||
property string title
|
||||
|
||||
/*!
|
||||
This property holds whether the group box is painted flat or has a frame.
|
||||
|
||||
A group box usually consists of a surrounding frame with a title at the top.
|
||||
If this property is enabled, only the top part of the frame is drawn in most styles;
|
||||
otherwise, the whole frame is drawn.
|
||||
|
||||
By default, this property is disabled, so group boxes are not flat unless explicitly specified.
|
||||
|
||||
\note In some styles, flat and non-flat group boxes have similar representations and may not be as
|
||||
distinguishable as they are in other styles.
|
||||
*/
|
||||
property bool flat: false
|
||||
|
||||
/*!
|
||||
This property holds whether the group box has a checkbox in its title.
|
||||
|
||||
If this property is true, the group box displays its title using a checkbox in place of an ordinary label.
|
||||
If the checkbox is checked, the group box's children are enabled; otherwise, they are disabled and inaccessible.
|
||||
|
||||
By default, group boxes are not checkable.
|
||||
*/
|
||||
property bool checkable: false
|
||||
|
||||
/*!
|
||||
\qmlproperty bool GroupBox::checked
|
||||
|
||||
This property holds whether the group box is checked.
|
||||
|
||||
If the group box is checkable, it is displayed with a check box. If the check box is checked, the group
|
||||
box's children are enabled; otherwise, the children are disabled and are inaccessible to the user.
|
||||
|
||||
By default, checkable group boxes are also checked.
|
||||
*/
|
||||
property alias checked: check.checked
|
||||
|
||||
|
||||
/*! \internal */
|
||||
default property alias __content: container.data
|
||||
|
||||
/*!
|
||||
\qmlproperty Item GroupBox::contentItem
|
||||
|
||||
This property holds the content Item of the group box.
|
||||
|
||||
Items declared as children of a GroupBox are automatically parented to the GroupBox's contentItem.
|
||||
Items created dynamically need to be explicitly parented to the contentItem:
|
||||
|
||||
\note The implicit size of the GroupBox is calculated based on the size of its content. If you want to anchor
|
||||
items inside the group box, you must specify an explicit width and height on the GroupBox itself.
|
||||
*/
|
||||
readonly property alias contentItem: container
|
||||
|
||||
/*! \internal */
|
||||
property Component style: Settings.styleComponent(Settings.style, "GroupBoxStyle.qml", groupbox)
|
||||
|
||||
/*! \internal */
|
||||
property alias __checkbox: check
|
||||
|
||||
/*! \internal */
|
||||
property alias __style: styleLoader.item
|
||||
|
||||
implicitWidth: Math.max((!anchors.fill ? container.calcWidth() : 0) + loader.leftMargin + loader.rightMargin,
|
||||
sizeHint.implicitWidth + (checkable ? 24 : 6))
|
||||
implicitHeight: (!anchors.fill ? container.calcHeight() : 0) + loader.topMargin + loader.bottomMargin
|
||||
|
||||
Layout.minimumWidth: implicitWidth
|
||||
Layout.minimumHeight: implicitHeight
|
||||
|
||||
Accessible.role: Accessible.Grouping
|
||||
Accessible.name: title
|
||||
|
||||
activeFocusOnTab: false
|
||||
|
||||
|
||||
data: [
|
||||
Loader {
|
||||
id: loader
|
||||
anchors.fill: parent
|
||||
property int topMargin: __style ? __style.padding.top : 0
|
||||
property int bottomMargin: __style ? __style.padding.bottom : 0
|
||||
property int leftMargin: __style ? __style.padding.left : 0
|
||||
property int rightMargin: __style ? __style.padding.right : 0
|
||||
sourceComponent: styleLoader.item ? styleLoader.item.panel : null
|
||||
onLoaded: item.z = -1
|
||||
Text { id: sizeHint ; visible: false ; text: title }
|
||||
Loader {
|
||||
id: styleLoader
|
||||
property alias __control: groupbox
|
||||
sourceComponent: groupbox.style
|
||||
}
|
||||
},
|
||||
CheckBox {
|
||||
id: check
|
||||
objectName: "check"
|
||||
checked: true
|
||||
text: groupbox.title
|
||||
visible: checkable
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: loader.topMargin
|
||||
activeFocusOnTab: groupbox.checkable
|
||||
style: CheckBoxStyle { panel: Item{} }
|
||||
},
|
||||
Item {
|
||||
id: container
|
||||
objectName: "container"
|
||||
z: 1
|
||||
focus: true
|
||||
anchors.fill: parent
|
||||
|
||||
anchors.topMargin: loader.topMargin
|
||||
anchors.leftMargin: loader.leftMargin
|
||||
anchors.rightMargin: loader.rightMargin
|
||||
anchors.bottomMargin: loader.bottomMargin
|
||||
enabled: (!groupbox.checkable || groupbox.checked)
|
||||
|
||||
property Item layoutItem: container.children.length === 1 ? container.children[0] : null
|
||||
function calcWidth () { return (layoutItem ? (layoutItem.implicitWidth || layoutItem.width) +
|
||||
(layoutItem.anchors.fill ? layoutItem.anchors.leftMargin +
|
||||
layoutItem.anchors.rightMargin : 0) : container.childrenRect.width) }
|
||||
function calcHeight () { return (layoutItem ? (layoutItem.implicitHeight || layoutItem.height) +
|
||||
(layoutItem.anchors.fill ? layoutItem.anchors.topMargin +
|
||||
layoutItem.anchors.bottomMargin : 0) : container.childrenRect.height) }
|
||||
}]
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,92 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.6
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Controls.Private 1.0
|
||||
|
||||
/*!
|
||||
\qmltype Label
|
||||
\inqmlmodule QtQuick.Controls
|
||||
\since 5.1
|
||||
\ingroup controls
|
||||
\brief A text label.
|
||||
|
||||
\image label.png
|
||||
|
||||
In addition to the normal \l Text type, Label follows the font and
|
||||
color scheme of the system.
|
||||
Use the \c text property to assign a text to the label. For other properties
|
||||
check \l Text.
|
||||
|
||||
A simple label looks like this:
|
||||
\qml
|
||||
Label {
|
||||
text: "Hello world"
|
||||
}
|
||||
\endqml
|
||||
|
||||
You can use the properties of \l Text to change the appearance
|
||||
of the text as desired:
|
||||
\qml
|
||||
Label {
|
||||
text: "Hello world"
|
||||
font.pixelSize: 22
|
||||
font.italic: true
|
||||
color: "steelblue"
|
||||
}
|
||||
\endqml
|
||||
|
||||
\sa Text, TextField, TextEdit
|
||||
*/
|
||||
|
||||
Text {
|
||||
/*!
|
||||
\qmlproperty string Label::text
|
||||
|
||||
The text to display. Use this property to get and set it.
|
||||
*/
|
||||
|
||||
id: label
|
||||
color: SystemPaletteSingleton.windowText(enabled)
|
||||
activeFocusOnTab: false
|
||||
renderType: Settings.isMobile ? Text.QtRendering : Text.NativeRendering
|
||||
Accessible.name: text
|
||||
Accessible.role: Accessible.StaticText
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,180 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Controls.Styles 1.1
|
||||
import QtQuick.Controls.Private 1.0
|
||||
|
||||
/*!
|
||||
\qmltype Menu
|
||||
\inqmlmodule QtQuick.Controls
|
||||
\since 5.1
|
||||
\ingroup menus
|
||||
\ingroup controls
|
||||
\brief Provides a menu component for use as a context menu, popup menu, or
|
||||
as part of a menu bar.
|
||||
|
||||
\image menu.png
|
||||
|
||||
\code
|
||||
Menu {
|
||||
title: "Edit"
|
||||
|
||||
MenuItem {
|
||||
text: "Cut"
|
||||
shortcut: "Ctrl+X"
|
||||
onTriggered: ...
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
text: "Copy"
|
||||
shortcut: "Ctrl+C"
|
||||
onTriggered: ...
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
text: "Paste"
|
||||
shortcut: "Ctrl+V"
|
||||
onTriggered: ...
|
||||
}
|
||||
|
||||
MenuSeparator { }
|
||||
|
||||
Menu {
|
||||
title: "More Stuff"
|
||||
|
||||
MenuItem {
|
||||
text: "Do Nothing"
|
||||
}
|
||||
}
|
||||
}
|
||||
\endcode
|
||||
|
||||
The main uses for menus:
|
||||
\list
|
||||
\li
|
||||
as a \e top-level menu in a \l MenuBar
|
||||
\li
|
||||
as a \e submenu inside another menu
|
||||
\li
|
||||
as a standalone or \e context menu
|
||||
\endlist
|
||||
|
||||
Note that some properties, such as \c enabled, \c text, or \c iconSource,
|
||||
only make sense in a particular use case of the menu.
|
||||
|
||||
\sa MenuBar, MenuItem, MenuSeparator
|
||||
*/
|
||||
|
||||
MenuPrivate {
|
||||
id: root
|
||||
|
||||
/*! \internal
|
||||
\omit
|
||||
Documented in qqquickmenu.cpp.
|
||||
\endomit
|
||||
*/
|
||||
function addMenu(title) {
|
||||
return root.insertMenu(items.length, title)
|
||||
}
|
||||
|
||||
/*! \internal
|
||||
\omit
|
||||
Documented in qquickmenu.cpp.
|
||||
\endomit
|
||||
*/
|
||||
function insertMenu(index, title) {
|
||||
if (!__selfComponent)
|
||||
__selfComponent = Qt.createComponent("Menu.qml", root)
|
||||
var submenu = __selfComponent.createObject(__selfComponent, { "title": title })
|
||||
root.insertItem(index, submenu)
|
||||
return submenu
|
||||
}
|
||||
|
||||
/*! \internal */
|
||||
property Component __selfComponent: null
|
||||
|
||||
/*! \qmlproperty Component Menu::style
|
||||
\since QtQuick.Controls.Styles 1.2
|
||||
|
||||
The style Component for this control.
|
||||
\sa {MenuStyle}
|
||||
|
||||
*/
|
||||
property Component style
|
||||
|
||||
Component.onCompleted: {
|
||||
if (!style) {
|
||||
__usingDefaultStyle = true
|
||||
style = Qt.binding(function() { return Settings.styleComponent(Settings.style, "MenuStyle.qml", root) })
|
||||
}
|
||||
}
|
||||
|
||||
/*! \internal */
|
||||
property bool __usingDefaultStyle: false
|
||||
/*! \internal */
|
||||
property var __parentContentItem: __parentMenu ? __parentMenu.__contentItem : null
|
||||
/*! \internal */
|
||||
property int __currentIndex: -1
|
||||
/*! \internal */
|
||||
onAboutToHide: __currentIndex = -1
|
||||
on__MenuPopupDestroyed: contentLoader.active = false
|
||||
onPopupVisibleChanged: {
|
||||
if (__popupVisible)
|
||||
contentLoader.active = true
|
||||
}
|
||||
|
||||
/*! \internal */
|
||||
__contentItem: Loader {
|
||||
id: contentLoader
|
||||
Component {
|
||||
id: menuContent
|
||||
MenuContentItem {
|
||||
__menu: root
|
||||
}
|
||||
}
|
||||
|
||||
sourceComponent: root.__isNative ? null : menuContent
|
||||
active: false
|
||||
focus: true
|
||||
Keys.forwardTo: item ? [item, root.__parentContentItem] : []
|
||||
property bool altPressed: root.__parentContentItem ? root.__parentContentItem.altPressed : false
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,347 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQml 2.14 as Qml
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Controls.Styles 1.1
|
||||
import QtQuick.Controls.Private 1.0
|
||||
|
||||
/*!
|
||||
\qmltype MenuBar
|
||||
\inqmlmodule QtQuick.Controls
|
||||
\since 5.1
|
||||
\ingroup applicationwindow
|
||||
\ingroup controls
|
||||
\brief Provides a horizontal menu bar.
|
||||
|
||||
\image menubar.png
|
||||
|
||||
MenuBar can be added to an \l ApplicationWindow, providing menu options
|
||||
to access additional functionality of the application.
|
||||
|
||||
\code
|
||||
ApplicationWindow {
|
||||
...
|
||||
menuBar: MenuBar {
|
||||
Menu {
|
||||
title: "File"
|
||||
MenuItem { text: "Open..." }
|
||||
MenuItem { text: "Close" }
|
||||
}
|
||||
|
||||
Menu {
|
||||
title: "Edit"
|
||||
MenuItem { text: "Cut" }
|
||||
MenuItem { text: "Copy" }
|
||||
MenuItem { text: "Paste" }
|
||||
}
|
||||
}
|
||||
}
|
||||
\endcode
|
||||
|
||||
\sa ApplicationWindow::menuBar
|
||||
*/
|
||||
|
||||
MenuBarPrivate {
|
||||
id: root
|
||||
|
||||
/*! \qmlproperty Component MenuBar::style
|
||||
\since QtQuick.Controls.Styles 1.2
|
||||
|
||||
The style Component for this control.
|
||||
\sa {MenuBarStyle}
|
||||
|
||||
*/
|
||||
property Component style: Settings.styleComponent(Settings.style, "MenuBarStyle.qml", root)
|
||||
|
||||
/*! \internal */
|
||||
property QtObject __style: styleLoader.item
|
||||
|
||||
__isNative: !__style.hasOwnProperty("__isNative") || __style.__isNative
|
||||
|
||||
/*! \internal */
|
||||
__contentItem: Loader {
|
||||
id: topLoader
|
||||
sourceComponent: __menuBarComponent
|
||||
active: !root.__isNative
|
||||
focus: true
|
||||
Keys.forwardTo: [item]
|
||||
property real preferredWidth: parent && active ? parent.width : 0
|
||||
property bool altPressed: item ? item.__altPressed : false
|
||||
|
||||
Loader {
|
||||
id: styleLoader
|
||||
property alias __control: topLoader.item
|
||||
sourceComponent: root.style
|
||||
onStatusChanged: {
|
||||
if (status === Loader.Error)
|
||||
console.error("Failed to load Style for", root)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*! \internal */
|
||||
property Component __menuBarComponent: Loader {
|
||||
id: menuBarLoader
|
||||
|
||||
Accessible.role: Accessible.MenuBar
|
||||
|
||||
onStatusChanged: if (status === Loader.Error) console.error("Failed to load panel for", root)
|
||||
|
||||
visible: status === Loader.Ready
|
||||
sourceComponent: d.style ? d.style.background : undefined
|
||||
|
||||
width: implicitWidth || root.__contentItem.preferredWidth
|
||||
height: Math.max(row.height + d.heightPadding, item ? item.implicitHeight : 0)
|
||||
|
||||
Qml.Binding {
|
||||
// Make sure the styled menu bar is in the background
|
||||
target: menuBarLoader.item
|
||||
property: "z"
|
||||
value: menuMouseArea.z - 1
|
||||
restoreMode: Binding.RestoreBinding
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
property Style style: __style
|
||||
|
||||
property int openedMenuIndex: -1
|
||||
property bool preselectMenuItem: false
|
||||
property real heightPadding: style ? style.padding.top + style.padding.bottom : 0
|
||||
|
||||
property bool altPressed: false
|
||||
property bool altPressedAgain: false
|
||||
property var mnemonicsMap: ({})
|
||||
|
||||
function openMenuAtIndex(index) {
|
||||
if (openedMenuIndex === index)
|
||||
return;
|
||||
|
||||
var oldIndex = openedMenuIndex
|
||||
openedMenuIndex = index
|
||||
|
||||
if (oldIndex !== -1) {
|
||||
var menu = root.menus[oldIndex]
|
||||
if (menu.__popupVisible)
|
||||
menu.__dismissAndDestroy()
|
||||
}
|
||||
|
||||
if (openedMenuIndex !== -1) {
|
||||
menu = root.menus[openedMenuIndex]
|
||||
if (menu.enabled) {
|
||||
if (menu.__usingDefaultStyle)
|
||||
menu.style = d.style.menuStyle
|
||||
|
||||
var xPos = row.LayoutMirroring.enabled ? menuItemLoader.width : 0
|
||||
menu.__popup(Qt.rect(xPos, menuBarLoader.height - d.heightPadding, 0, 0), 0)
|
||||
|
||||
if (preselectMenuItem)
|
||||
menu.__currentIndex = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function dismissActiveFocus(event, reason) {
|
||||
if (reason) {
|
||||
altPressedAgain = false
|
||||
altPressed = false
|
||||
openMenuAtIndex(-1)
|
||||
root.__contentItem.parent.forceActiveFocus()
|
||||
} else {
|
||||
event.accepted = false
|
||||
}
|
||||
}
|
||||
|
||||
function maybeOpenFirstMenu(event) {
|
||||
if (altPressed && openedMenuIndex === -1) {
|
||||
preselectMenuItem = true
|
||||
openMenuAtIndex(0)
|
||||
} else {
|
||||
event.accepted = false
|
||||
}
|
||||
}
|
||||
}
|
||||
property alias __altPressed: d.altPressed // Needed for the menu contents
|
||||
|
||||
focus: true
|
||||
|
||||
Keys.onPressed: {
|
||||
var action = null
|
||||
if (event.key === Qt.Key_Alt) {
|
||||
if (!d.altPressed)
|
||||
d.altPressed = true
|
||||
else
|
||||
d.altPressedAgain = true
|
||||
} else if (d.altPressed && (action = d.mnemonicsMap[event.text.toUpperCase()])) {
|
||||
d.preselectMenuItem = true
|
||||
action.trigger()
|
||||
event.accepted = true
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onReleased: d.dismissActiveFocus(event, d.altPressedAgain && d.openedMenuIndex === -1)
|
||||
Keys.onEscapePressed: d.dismissActiveFocus(event, d.openedMenuIndex === -1)
|
||||
|
||||
Keys.onUpPressed: d.maybeOpenFirstMenu(event)
|
||||
Keys.onDownPressed: d.maybeOpenFirstMenu(event)
|
||||
|
||||
Keys.onLeftPressed: {
|
||||
if (d.openedMenuIndex > 0) {
|
||||
var idx = d.openedMenuIndex - 1
|
||||
while (idx >= 0 && !(root.menus[idx].enabled && root.menus[idx].visible))
|
||||
idx--
|
||||
if (idx >= 0) {
|
||||
d.preselectMenuItem = true
|
||||
d.openMenuAtIndex(idx)
|
||||
}
|
||||
} else {
|
||||
event.accepted = false;
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onRightPressed: {
|
||||
if (d.openedMenuIndex !== -1 && d.openedMenuIndex < root.menus.length - 1) {
|
||||
var idx = d.openedMenuIndex + 1
|
||||
while (idx < root.menus.length && !(root.menus[idx].enabled && root.menus[idx].visible))
|
||||
idx++
|
||||
if (idx < root.menus.length) {
|
||||
d.preselectMenuItem = true
|
||||
d.openMenuAtIndex(idx)
|
||||
}
|
||||
} else {
|
||||
event.accepted = false;
|
||||
}
|
||||
}
|
||||
|
||||
Keys.forwardTo: d.openedMenuIndex !== -1 ? [root.menus[d.openedMenuIndex].__contentItem] : []
|
||||
|
||||
Row {
|
||||
id: row
|
||||
x: d.style ? d.style.padding.left : 0
|
||||
y: d.style ? d.style.padding.top : 0
|
||||
width: parent.width - (d.style ? d.style.padding.left + d.style.padding.right : 0)
|
||||
LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft
|
||||
|
||||
Repeater {
|
||||
id: itemsRepeater
|
||||
model: root.menus
|
||||
Loader {
|
||||
id: menuItemLoader
|
||||
|
||||
Accessible.role: Accessible.MenuItem
|
||||
Accessible.name: StyleHelpers.removeMnemonics(opts.text)
|
||||
Accessible.onPressAction: d.openMenuAtIndex(opts.index)
|
||||
|
||||
property var styleData: QtObject {
|
||||
id: opts
|
||||
readonly property int index: __menuItemIndex
|
||||
readonly property string text: !!__menuItem && __menuItem.title
|
||||
readonly property bool enabled: !!__menuItem && __menuItem.enabled
|
||||
readonly property bool selected: menuMouseArea.hoveredItem === menuItemLoader
|
||||
readonly property bool open: !!__menuItem && __menuItem.__popupVisible || d.openedMenuIndex === index
|
||||
readonly property bool underlineMnemonic: d.altPressed
|
||||
}
|
||||
|
||||
height: Math.max(menuBarLoader.height - d.heightPadding,
|
||||
menuItemLoader.item ? menuItemLoader.item.implicitHeight : 0)
|
||||
|
||||
readonly property var __menuItem: modelData
|
||||
readonly property int __menuItemIndex: index
|
||||
sourceComponent: d.style ? d.style.itemDelegate : null
|
||||
visible: __menuItem.visible
|
||||
|
||||
Connections {
|
||||
target: __menuItem
|
||||
function onAboutToHide() {
|
||||
if (d.openedMenuIndex === index) {
|
||||
d.openMenuAtIndex(-1)
|
||||
menuMouseArea.hoveredItem = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: __menuItem.__action
|
||||
function onTriggered() { d.openMenuAtIndex(__menuItemIndex) }
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
__menuItem.__visualItem = menuItemLoader
|
||||
|
||||
var title = __menuItem.title
|
||||
var ampersandPos = title.indexOf("&")
|
||||
if (ampersandPos !== -1)
|
||||
d.mnemonicsMap[title[ampersandPos + 1].toUpperCase()] = __menuItem.__action
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: menuMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: Settings.hoverEnabled
|
||||
|
||||
onPositionChanged: updateCurrentItem(mouse)
|
||||
onPressed: updateCurrentItem(mouse)
|
||||
onExited: hoveredItem = null
|
||||
|
||||
property Item currentItem: null
|
||||
property Item hoveredItem: null
|
||||
function updateCurrentItem(mouse) {
|
||||
var pos = mapToItem(row, mouse.x, mouse.y)
|
||||
if (pressed || !hoveredItem
|
||||
|| !hoveredItem.contains(Qt.point(pos.x - currentItem.x, pos.y - currentItem.y))) {
|
||||
hoveredItem = row.childAt(pos.x, pos.y)
|
||||
if (!hoveredItem)
|
||||
return false;
|
||||
currentItem = hoveredItem
|
||||
if (pressed || d.openedMenuIndex !== -1) {
|
||||
d.preselectMenuItem = false
|
||||
d.openMenuAtIndex(currentItem.__menuItemIndex)
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,178 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Controls.Private 1.0
|
||||
import QtQuick.Window 2.2
|
||||
|
||||
/*!
|
||||
\qmltype AbstractCheckable
|
||||
\inqmlmodule QtQuick.Controls
|
||||
\brief An abstract representation of a checkable control with a label
|
||||
\qmlabstract
|
||||
\internal
|
||||
|
||||
A checkable control is one that has two states: checked (on) and
|
||||
unchecked (off). AbstractCheckable encapsulates the basic behavior and
|
||||
states that are required by checkable controls.
|
||||
|
||||
Examples of checkable controls are RadioButton and
|
||||
CheckBox. CheckBox extends AbstractCheckable's behavior by adding a third
|
||||
state: partially checked.
|
||||
*/
|
||||
|
||||
Control {
|
||||
id: abstractCheckable
|
||||
|
||||
/*!
|
||||
Emitted whenever the control is clicked.
|
||||
*/
|
||||
signal clicked
|
||||
|
||||
/*!
|
||||
\qmlproperty bool AbstractCheckable::pressed
|
||||
|
||||
This property is \c true if the control is being pressed.
|
||||
Set this property to manually invoke a mouse click.
|
||||
*/
|
||||
property alias pressed: mouseArea.effectivePressed
|
||||
|
||||
/*! \qmlproperty bool AbstractCheckcable::hovered
|
||||
|
||||
This property indicates whether the control is being hovered.
|
||||
*/
|
||||
readonly property alias hovered: mouseArea.containsMouse
|
||||
|
||||
/*!
|
||||
This property is \c true if the control is checked.
|
||||
*/
|
||||
property bool checked: false
|
||||
Accessible.checked: checked
|
||||
Accessible.checkable: true
|
||||
|
||||
/*!
|
||||
This property is \c true if the control takes the focus when it is
|
||||
pressed; \l{QQuickItem::forceActiveFocus()}{forceActiveFocus()} will be
|
||||
called on the control.
|
||||
*/
|
||||
property bool activeFocusOnPress: false
|
||||
|
||||
/*!
|
||||
This property stores the ExclusiveGroup that the control belongs to.
|
||||
*/
|
||||
property ExclusiveGroup exclusiveGroup: null
|
||||
|
||||
/*!
|
||||
This property holds the text that the label should display.
|
||||
*/
|
||||
property string text
|
||||
|
||||
/*!
|
||||
This property holds the button tooltip.
|
||||
|
||||
\since QtQuick.Controls 1.7
|
||||
*/
|
||||
property string tooltip
|
||||
Accessible.description: tooltip
|
||||
|
||||
/*! \internal */
|
||||
property var __cycleStatesHandler: cycleRadioButtonStates
|
||||
|
||||
activeFocusOnTab: true
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
focus: true
|
||||
anchors.fill: parent
|
||||
hoverEnabled: Settings.hoverEnabled
|
||||
enabled: !keyPressed
|
||||
|
||||
property bool keyPressed: false
|
||||
property bool effectivePressed: pressed && containsMouse || keyPressed
|
||||
|
||||
onClicked: abstractCheckable.clicked();
|
||||
|
||||
onPressed: if (activeFocusOnPress) forceActiveFocus();
|
||||
|
||||
onExited: Tooltip.hideText()
|
||||
onCanceled: Tooltip.hideText()
|
||||
|
||||
onReleased: {
|
||||
if (containsMouse && (!exclusiveGroup || !checked))
|
||||
__cycleStatesHandler();
|
||||
}
|
||||
|
||||
Timer {
|
||||
interval: 1000
|
||||
running: mouseArea.containsMouse && !pressed && tooltip.length && mouseArea.Window.visibility !== Window.Hidden
|
||||
onTriggered: Tooltip.showText(mouseArea, Qt.point(mouseArea.mouseX, mouseArea.mouseY), tooltip)
|
||||
}
|
||||
}
|
||||
|
||||
/*! \internal */
|
||||
onExclusiveGroupChanged: {
|
||||
if (exclusiveGroup)
|
||||
exclusiveGroup.bindCheckable(abstractCheckable)
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
if (event.key === Qt.Key_Space && !event.isAutoRepeat && !mouseArea.pressed)
|
||||
mouseArea.keyPressed = true;
|
||||
}
|
||||
|
||||
Keys.onReleased: {
|
||||
if (event.key === Qt.Key_Space && !event.isAutoRepeat && mouseArea.keyPressed) {
|
||||
mouseArea.keyPressed = false;
|
||||
if (!exclusiveGroup || !checked)
|
||||
__cycleStatesHandler();
|
||||
clicked();
|
||||
}
|
||||
}
|
||||
|
||||
Action {
|
||||
// handle mnemonic
|
||||
text: abstractCheckable.text
|
||||
onTriggered: {
|
||||
if (!abstractCheckable.exclusiveGroup || !abstractCheckable.checked)
|
||||
abstractCheckable.__cycleStatesHandler();
|
||||
abstractCheckable.clicked();
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,241 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Controls.Private 1.0
|
||||
import QtQuick.Controls.Styles 1.1
|
||||
import QtQuick.Window 2.2
|
||||
|
||||
/*!
|
||||
\qmltype BasicButton
|
||||
\internal
|
||||
\qmlabstract
|
||||
\inqmlmodule QtQuick.Controls.Private
|
||||
*/
|
||||
|
||||
Control {
|
||||
id: button
|
||||
|
||||
/*! This signal is emitted when the button is clicked. */
|
||||
signal clicked
|
||||
|
||||
/*! \qmlproperty bool BasicButton::pressed
|
||||
|
||||
This property holds whether the button is being pressed. */
|
||||
readonly property alias pressed: button.__effectivePressed
|
||||
|
||||
/*! \qmlproperty bool BasicButton::hovered
|
||||
|
||||
This property indicates whether the control is being hovered.
|
||||
*/
|
||||
readonly property alias hovered: behavior.containsMouse
|
||||
|
||||
/*! This property holds whether the button is checkable.
|
||||
|
||||
The default value is \c false. */
|
||||
property bool checkable: false
|
||||
Accessible.checkable: checkable
|
||||
|
||||
/*! This property holds whether the button is checked.
|
||||
|
||||
Only checkable buttons can be checked.
|
||||
|
||||
The default value is \c false. */
|
||||
property bool checked: false
|
||||
Accessible.checked: checked
|
||||
|
||||
/*! This property holds the ExclusiveGroup that the button belongs to.
|
||||
|
||||
The default value is \c null. */
|
||||
property ExclusiveGroup exclusiveGroup: null
|
||||
|
||||
/*! This property holds the associated button action.
|
||||
|
||||
If a button has an action associated, the action defines the
|
||||
button's properties like checked, text, tooltip etc.
|
||||
|
||||
When an action is set, it's still possible to override the \l text,
|
||||
\l tooltip, \l iconSource, and \l iconName properties.
|
||||
|
||||
The default value is \c null. */
|
||||
property Action action: null
|
||||
|
||||
/*! This property specifies whether the button should gain active focus when pressed.
|
||||
|
||||
The default value is \c false. */
|
||||
property bool activeFocusOnPress: false
|
||||
|
||||
/*! This property holds the text shown on the button. If the button has no
|
||||
text, the \l text property will be an empty string.
|
||||
|
||||
The default value is the empty string.
|
||||
*/
|
||||
property string text: action ? action.text : ""
|
||||
|
||||
/*! This property holds the button tooltip. */
|
||||
property string tooltip: action ? (action.tooltip || StyleHelpers.removeMnemonics(action.text)) : ""
|
||||
|
||||
/*! This property holds the icon shown on the button. If the button has no
|
||||
icon, the iconSource property will be an empty string.
|
||||
|
||||
The default value is the empty string.
|
||||
*/
|
||||
property url iconSource: action ? action.iconSource : ""
|
||||
|
||||
/*! The image label source as theme name.
|
||||
When an icon from the platform icon theme is found, this takes
|
||||
precedence over iconSource.
|
||||
|
||||
\include icons.qdocinc iconName
|
||||
*/
|
||||
property string iconName: action ? action.iconName : ""
|
||||
|
||||
/*! \internal */
|
||||
property string __position: "only"
|
||||
/*! \internal */
|
||||
readonly property bool __iconOverriden: button.action && (button.action.iconSource !== button.iconSource || button.action.iconName !== button.iconName)
|
||||
/*! \internal */
|
||||
property Action __action: action || ownAction
|
||||
/*! \internal */
|
||||
readonly property Action __iconAction: __iconOverriden ? ownAction : __action
|
||||
|
||||
/*! \internal */
|
||||
onExclusiveGroupChanged: {
|
||||
if (exclusiveGroup)
|
||||
exclusiveGroup.bindCheckable(button)
|
||||
}
|
||||
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.description: tooltip
|
||||
|
||||
/*! \internal */
|
||||
function accessiblePressAction() {
|
||||
__action.trigger(button)
|
||||
}
|
||||
|
||||
Action {
|
||||
id: ownAction
|
||||
enabled: button.enabled
|
||||
iconSource: !button.action || __iconOverriden ? button.iconSource : ""
|
||||
iconName: !button.action || __iconOverriden ? button.iconName : ""
|
||||
|
||||
// let ownAction handle mnemonic if and only if the button does
|
||||
// not already have an action assigned to avoid ambiguous shortcuts
|
||||
text: button.action ? "" : button.text
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: __action
|
||||
function onTriggered() { button.clicked() }
|
||||
}
|
||||
|
||||
activeFocusOnTab: true
|
||||
|
||||
Keys.onPressed: {
|
||||
if (event.key === Qt.Key_Space && !event.isAutoRepeat && !behavior.pressed) {
|
||||
behavior.keyPressed = true;
|
||||
event.accepted = true;
|
||||
}
|
||||
}
|
||||
|
||||
onFocusChanged: if (!focus) behavior.keyPressed = false
|
||||
|
||||
Keys.onReleased: {
|
||||
if (event.key === Qt.Key_Space && !event.isAutoRepeat && behavior.keyPressed) {
|
||||
behavior.keyPressed = false;
|
||||
__action.trigger(button)
|
||||
behavior.toggle()
|
||||
event.accepted = true;
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: behavior
|
||||
property bool keyPressed: false
|
||||
property bool effectivePressed: pressed && containsMouse || keyPressed
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: Settings.hoverEnabled
|
||||
enabled: !keyPressed
|
||||
|
||||
function toggle() {
|
||||
if (button.checkable && !button.action && !(button.checked && button.exclusiveGroup))
|
||||
button.checked = !button.checked
|
||||
}
|
||||
|
||||
onReleased: {
|
||||
if (containsMouse) {
|
||||
toggle()
|
||||
__action.trigger(button)
|
||||
}
|
||||
}
|
||||
onExited: Tooltip.hideText()
|
||||
onCanceled: Tooltip.hideText()
|
||||
onPressed: {
|
||||
if (activeFocusOnPress)
|
||||
button.forceActiveFocus()
|
||||
}
|
||||
|
||||
Timer {
|
||||
interval: 1000
|
||||
running: behavior.containsMouse && !pressed && tooltip.length && behavior.Window.visibility !== Window.Hidden
|
||||
onTriggered: Tooltip.showText(behavior, Qt.point(behavior.mouseX, behavior.mouseY), tooltip)
|
||||
}
|
||||
}
|
||||
|
||||
/*! \internal */
|
||||
property var __behavior: behavior
|
||||
|
||||
/*! \internal */
|
||||
property bool __effectivePressed: behavior.effectivePressed
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "boundAction"
|
||||
when: action !== null
|
||||
PropertyChanges {
|
||||
target: button
|
||||
enabled: action.enabled
|
||||
checkable: action.checkable
|
||||
checked: action.checked
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,792 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
import QtQml 2.14 as Qml
|
||||
import QtQuick 2.6
|
||||
import QtQuick.Controls 1.5
|
||||
import QtQuick.Controls.Private 1.0
|
||||
import QtQuick.Controls.Styles 1.2
|
||||
import QtQuick.Window 2.2
|
||||
|
||||
/*!
|
||||
\qmltype BasicTableView
|
||||
\qmlabstract
|
||||
\inqmlmodule QtQuick.Controls.Private
|
||||
*/
|
||||
|
||||
ScrollView {
|
||||
id: root
|
||||
|
||||
/*! \qmlproperty bool BasicTableView::alternatingRowColors
|
||||
|
||||
This property is set to \c true if the view alternates the row color.
|
||||
The default value is \c true.
|
||||
*/
|
||||
property bool alternatingRowColors: true
|
||||
|
||||
/*! \qmlproperty bool BasicTableView::headerVisible
|
||||
|
||||
This property determines if the header is visible.
|
||||
The default value is \c true.
|
||||
*/
|
||||
property bool headerVisible: true
|
||||
|
||||
/*! \qmlproperty bool BasicTableView::backgroundVisible
|
||||
|
||||
This property determines if the background should be filled or not.
|
||||
|
||||
The default value is \c true.
|
||||
|
||||
\note The rowDelegate is not affected by this property
|
||||
*/
|
||||
property alias backgroundVisible: colorRect.visible
|
||||
|
||||
/*! \qmlproperty Component BasicTableView::itemDelegate
|
||||
\internal
|
||||
|
||||
Documentation differs between TableView and TreeView.
|
||||
See qtquickcontrols-treeview.qdoc and qtquickcontrols-tableview.qdoc
|
||||
*/
|
||||
property Component itemDelegate: __style ? __style.itemDelegate : null
|
||||
|
||||
/*! \qmlproperty Component BasicTableView::rowDelegate
|
||||
|
||||
This property defines a delegate to draw a row.
|
||||
|
||||
In the row delegate you have access to the following special properties:
|
||||
\list
|
||||
\li styleData.alternate - true when the row uses the alternate background color
|
||||
\li styleData.selected - true when the row is currently selected
|
||||
\li styleData.row - the index of the row
|
||||
\li styleData.hasActiveFocus - true when the row has focus (since QtQuick.Controls 1.3)
|
||||
\li styleData.pressed - true when the row is pressed (since QtQuick.Controls 1.3)
|
||||
\endlist
|
||||
|
||||
\note For performance reasons, created delegates can be recycled
|
||||
across multiple table rows. This implies that when you make use of implicit
|
||||
properties such as \c styleData.row or \c model, these values can change
|
||||
after the delegate has been constructed. This means that you should not assume
|
||||
that content is fixed when \c Component.onCompleted is called, but instead rely on
|
||||
bindings to such properties.
|
||||
*/
|
||||
property Component rowDelegate: __style ? __style.rowDelegate : null
|
||||
|
||||
/*! \qmlproperty Component BasicTableView::headerDelegate
|
||||
|
||||
This property defines a delegate to draw a header.
|
||||
|
||||
In the header delegate you have access to the following special properties:
|
||||
\list
|
||||
\li styleData.value - the value or text for this item
|
||||
\li styleData.column - the index of the column
|
||||
\li styleData.pressed - true when the column is being pressed
|
||||
\li styleData.containsMouse - true when the column is under the mouse
|
||||
\li styleData.textAlignment - the horizontal text alignment of the column (since QtQuickControls 1.1)
|
||||
\endlist
|
||||
*/
|
||||
property Component headerDelegate: __style ? __style.headerDelegate : null
|
||||
|
||||
/*! \qmlproperty int BasicTableView::sortIndicatorColumn
|
||||
|
||||
Index of the current sort column.
|
||||
The default value is \c {0}.
|
||||
*/
|
||||
property int sortIndicatorColumn
|
||||
|
||||
/*! \qmlproperty bool BasicTableView::sortIndicatorVisible
|
||||
|
||||
This property shows or hides the sort indicator
|
||||
The default value is \c false.
|
||||
\note The view itself does not sort the data.
|
||||
*/
|
||||
property bool sortIndicatorVisible: false
|
||||
|
||||
/*! \qmlproperty enumeration BasicTableView::sortIndicatorOrder
|
||||
|
||||
This sets the sorting order of the sort indicator
|
||||
The allowed values are:
|
||||
\list
|
||||
\li Qt.AscendingOrder - the default
|
||||
\li Qt.DescendingOrder
|
||||
\endlist
|
||||
*/
|
||||
property int sortIndicatorOrder: Qt.AscendingOrder
|
||||
|
||||
/*! \qmlproperty Component BasicTableView::contentHeader
|
||||
This is the content header of the view.
|
||||
*/
|
||||
property alias contentHeader: listView.header
|
||||
|
||||
/*! \qmlproperty Component BasicTableView::contentFooter
|
||||
This is the content footer of the view.
|
||||
*/
|
||||
property alias contentFooter: listView.footer
|
||||
|
||||
/*! \qmlproperty int BasicTableView::columnCount
|
||||
The current number of columns
|
||||
*/
|
||||
readonly property alias columnCount: columnModel.count
|
||||
|
||||
/*! \qmlpropertygroup BasicTableView::section
|
||||
\internal
|
||||
\qmlproperty string BasicTableView::section.property
|
||||
\qmlproperty enumeration BasicTableView::section.criteria
|
||||
\qmlproperty Component BasicTableView::section.delegate
|
||||
\qmlproperty enumeration BasicTableView::section.labelPositioning
|
||||
|
||||
Moved to the qdoc files to keep the grouped property layout.
|
||||
See qtquickcontrols-treeview.qdoc and qtquickcontrols-tableview.qdoc
|
||||
*/
|
||||
property alias section: listView.section
|
||||
|
||||
/*!
|
||||
\qmlproperty enumeration BasicTableView::selectionMode
|
||||
\since QtQuick.Controls 1.1
|
||||
|
||||
This enum indicates how the view responds to user selections:
|
||||
|
||||
The possible modes are:
|
||||
|
||||
\list
|
||||
|
||||
\li SelectionMode.NoSelection - Items cannot be selected.
|
||||
|
||||
\li SelectionMode.SingleSelection - When the user selects an item,
|
||||
any already-selected item becomes unselected, and the user cannot
|
||||
unselect the selected item. (Default)
|
||||
|
||||
\li SelectionMode.MultiSelection - When the user selects an item in the usual way,
|
||||
the selection status of that item is toggled and the other items are left alone.
|
||||
|
||||
\li SelectionMode.ExtendedSelection - When the user selects an item in the usual way,
|
||||
the selection is cleared and the new item selected. However, if the user presses the
|
||||
Ctrl key when clicking on an item, the clicked item gets toggled and all other items
|
||||
are left untouched. If the user presses the Shift key while clicking
|
||||
on an item, all items between the current item and the clicked item are selected or unselected,
|
||||
depending on the state of the clicked item. Multiple items can be selected by dragging the
|
||||
mouse over them.
|
||||
|
||||
\li SelectionMode.ContiguousSelection - When the user selects an item in the usual way,
|
||||
the selection is cleared and the new item selected. However, if the user presses the Shift key while
|
||||
clicking on an item, all items between the current item and the clicked item are selected.
|
||||
|
||||
\endlist
|
||||
*/
|
||||
property int selectionMode: SelectionMode.SingleSelection
|
||||
|
||||
/*!
|
||||
\qmlmethod TableViewColumn BasicTableView::addColumn(object column)
|
||||
|
||||
Adds a \a column and returns the added column.
|
||||
|
||||
The \a column argument can be an instance of TableViewColumn,
|
||||
or a Component. The component has to contain a TableViewColumn.
|
||||
Otherwise \c null is returned.
|
||||
*/
|
||||
function addColumn(column) {
|
||||
return insertColumn(columnCount, column)
|
||||
}
|
||||
|
||||
/*!
|
||||
\qmlmethod TableViewColumn BasicTableView::insertColumn(int index, object column)
|
||||
|
||||
Inserts a \a column at the given \a index and returns the inserted column.
|
||||
|
||||
The \a column argument can be an instance of TableViewColumn,
|
||||
or a Component. The component has to contain a TableViewColumn.
|
||||
Otherwise \c null is returned.
|
||||
*/
|
||||
function insertColumn(index, column) {
|
||||
if (__isTreeView && index === 0 && columnCount > 0) {
|
||||
console.warn(__viewTypeName + "::insertColumn(): Can't replace column 0")
|
||||
return null
|
||||
}
|
||||
var object = column
|
||||
if (typeof column['createObject'] === 'function') {
|
||||
object = column.createObject(root)
|
||||
} else if (object.__view) {
|
||||
console.warn(__viewTypeName + "::insertColumn(): you cannot add a column to multiple views")
|
||||
return null
|
||||
}
|
||||
if (index >= 0 && index <= columnCount && object.accessibleRole === Accessible.ColumnHeader) {
|
||||
object.__view = root
|
||||
columnModel.insert(index, {columnItem: object})
|
||||
if (root.__columns[index] !== object) {
|
||||
// The new column needs to be put into __columns at the specified index
|
||||
// so the list needs to be recreated to be correct
|
||||
var arr = []
|
||||
for (var i = 0; i < index; ++i)
|
||||
arr.push(root.__columns[i])
|
||||
arr.push(object)
|
||||
for (i = index; i < root.__columns.length; ++i)
|
||||
arr.push(root.__columns[i])
|
||||
root.__columns = arr
|
||||
}
|
||||
return object
|
||||
}
|
||||
|
||||
if (object !== column)
|
||||
object.destroy()
|
||||
console.warn(__viewTypeName + "::insertColumn(): invalid argument")
|
||||
return null
|
||||
}
|
||||
|
||||
/*!
|
||||
\qmlmethod void BasicTableView::removeColumn(int index)
|
||||
|
||||
Removes and destroys a column at the given \a index.
|
||||
*/
|
||||
function removeColumn(index) {
|
||||
if (index < 0 || index >= columnCount) {
|
||||
console.warn(__viewTypeName + "::removeColumn(): invalid argument")
|
||||
return
|
||||
}
|
||||
if (__isTreeView && index === 0) {
|
||||
console.warn(__viewTypeName + "::removeColumn(): Can't remove column 0")
|
||||
return
|
||||
}
|
||||
var column = columnModel.get(index).columnItem
|
||||
columnModel.remove(index, 1)
|
||||
column.destroy()
|
||||
}
|
||||
|
||||
/*!
|
||||
\qmlmethod void BasicTableView::moveColumn(int from, int to)
|
||||
|
||||
Moves a column \a from index \a to another.
|
||||
*/
|
||||
function moveColumn(from, to) {
|
||||
if (from < 0 || from >= columnCount || to < 0 || to >= columnCount) {
|
||||
console.warn(__viewTypeName + "::moveColumn(): invalid argument")
|
||||
return
|
||||
}
|
||||
if (__isTreeView && to === 0) {
|
||||
console.warn(__viewTypeName + "::moveColumn(): Can't move column 0")
|
||||
return
|
||||
}
|
||||
if (sortIndicatorColumn === from)
|
||||
sortIndicatorColumn = to
|
||||
columnModel.move(from, to, 1)
|
||||
}
|
||||
|
||||
/*!
|
||||
\qmlmethod TableViewColumn BasicTableView::getColumn(int index)
|
||||
|
||||
Returns the column at the given \a index
|
||||
or \c null if the \a index is invalid.
|
||||
*/
|
||||
function getColumn(index) {
|
||||
if (index < 0 || index >= columnCount)
|
||||
return null
|
||||
return columnModel.get(index).columnItem
|
||||
}
|
||||
|
||||
/*!
|
||||
\qmlmethod void BasicTableView::resizeColumnsToContents()
|
||||
|
||||
Resizes all columns to ensure that the column contents and the headers will fit.
|
||||
\since QtQuick.Controls 1.2
|
||||
*/
|
||||
function resizeColumnsToContents () {
|
||||
for (var i = 0; i < __columns.length; ++i) {
|
||||
var col = getColumn(i)
|
||||
var header = __listView.headerItem.headerRepeater.itemAt(i)
|
||||
if (col) {
|
||||
col.resizeToContents()
|
||||
if (col.width < header.implicitWidth)
|
||||
col.width = header.implicitWidth
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Internal stuff. Do not look
|
||||
|
||||
Component.onCompleted: {
|
||||
for (var i = 0; i < __columns.length; ++i) {
|
||||
var column = __columns[i]
|
||||
if (column.accessibleRole === Accessible.ColumnHeader)
|
||||
addColumn(column)
|
||||
}
|
||||
}
|
||||
|
||||
activeFocusOnTab: true
|
||||
|
||||
implicitWidth: 200
|
||||
implicitHeight: 150
|
||||
|
||||
frameVisible: true
|
||||
__scrollBarTopMargin: headerVisible && (listView.transientScrollBars || Qt.platform.os === "osx")
|
||||
? listView.headerItem.height : 0
|
||||
|
||||
/*! \internal
|
||||
Use this to display user-friendly messages in TableView and TreeView common functions.
|
||||
*/
|
||||
property string __viewTypeName
|
||||
|
||||
/*! \internal */
|
||||
readonly property bool __isTreeView: __viewTypeName === "TreeView"
|
||||
|
||||
/*! \internal */
|
||||
default property alias __columns: root.data
|
||||
|
||||
/*! \internal */
|
||||
property alias __currentRowItem: listView.currentItem
|
||||
|
||||
/*! \internal
|
||||
This property is forwarded to TableView::currentRow, but not to any TreeView property.
|
||||
*/
|
||||
property alias __currentRow: listView.currentIndex
|
||||
|
||||
/*! \internal */
|
||||
readonly property alias __listView: listView
|
||||
|
||||
/*! \internal */
|
||||
property Component __itemDelegateLoader: null
|
||||
|
||||
/*! \internal
|
||||
Allows to override the model property in cases like TreeView,
|
||||
where we want to use a proxy/adaptor model between the user's model
|
||||
and whatever a ListView can swallow.
|
||||
*/
|
||||
property var __model
|
||||
|
||||
/*! \internal */
|
||||
property bool __activateItemOnSingleClick: __style ? __style.activateItemOnSingleClick : false
|
||||
|
||||
/*! \internal */
|
||||
property Item __mouseArea
|
||||
|
||||
ListView {
|
||||
id: listView
|
||||
focus: true
|
||||
activeFocusOnTab: false
|
||||
Keys.forwardTo: [__mouseArea]
|
||||
anchors.fill: parent
|
||||
contentWidth: headerItem.headerRow.width + listView.vScrollbarPadding
|
||||
// ### FIXME Late configuration of the header item requires
|
||||
// this binding to get the header visible after creation
|
||||
contentY: -headerItem.height
|
||||
|
||||
currentIndex: -1
|
||||
visible: columnCount > 0
|
||||
interactive: Settings.hasTouchScreen
|
||||
property var rowItemStack: [] // Used as a cache for rowDelegates
|
||||
|
||||
readonly property bool transientScrollBars: __style && !!__style.transientScrollBars
|
||||
readonly property real vScrollbarPadding: __scroller.verticalScrollBar.visible
|
||||
&& !transientScrollBars && Qt.platform.os === "osx" ?
|
||||
__verticalScrollBar.width + __scroller.scrollBarSpacing + root.__style.padding.right : 0
|
||||
|
||||
Qml.Binding {
|
||||
// On Mac, we reserve the vSB space in the contentItem because the vSB should
|
||||
// appear under the header. Unfortunately, the ListView header won't expand
|
||||
// beyond the ListView's boundaries, that's why we need to ressort to this.
|
||||
target: root.__scroller
|
||||
when: Qt.platform.os === "osx"
|
||||
property: "verticalScrollbarOffset"
|
||||
value: 0
|
||||
restoreMode: Binding.RestoreBinding
|
||||
}
|
||||
|
||||
function incrementCurrentIndexBlocking() {
|
||||
var oldIndex = __listView.currentIndex
|
||||
__scroller.blockUpdates = true;
|
||||
incrementCurrentIndex();
|
||||
__scroller.blockUpdates = false;
|
||||
return oldIndex !== __listView.currentIndex
|
||||
}
|
||||
|
||||
function decrementCurrentIndexBlocking() {
|
||||
var oldIndex = __listView.currentIndex
|
||||
__scroller.blockUpdates = true;
|
||||
decrementCurrentIndex();
|
||||
__scroller.blockUpdates = false;
|
||||
return oldIndex !== __listView.currentIndex
|
||||
}
|
||||
|
||||
function scrollIfNeeded(key) {
|
||||
var diff = key === Qt.Key_PageDown ? height :
|
||||
key === Qt.Key_PageUp ? -height : 0
|
||||
if (diff !== 0)
|
||||
__verticalScrollBar.value += diff
|
||||
}
|
||||
|
||||
SystemPalette {
|
||||
id: palette
|
||||
colorGroup: enabled ? SystemPalette.Active : SystemPalette.Disabled
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: colorRect
|
||||
parent: viewport
|
||||
anchors.fill: parent
|
||||
color: __style ? __style.backgroundColor : palette.base
|
||||
z: -2
|
||||
}
|
||||
|
||||
// Fills extra rows with alternate color
|
||||
Column {
|
||||
id: rowfiller
|
||||
Loader {
|
||||
id: rowSizeItem
|
||||
sourceComponent: root.rowDelegate
|
||||
visible: false
|
||||
property QtObject styleData: QtObject {
|
||||
property bool alternate: false
|
||||
property bool selected: false
|
||||
property bool hasActiveFocus: false
|
||||
property bool pressed: false
|
||||
}
|
||||
}
|
||||
property int rowHeight: Math.floor(rowSizeItem.implicitHeight)
|
||||
property int paddedRowCount: rowHeight != 0 ? height/rowHeight : 0
|
||||
|
||||
y: listView.contentHeight - listView.contentY + listView.originY
|
||||
width: parent.width
|
||||
visible: alternatingRowColors
|
||||
height: listView.model && listView.model.count ? (viewport.height - listView.contentHeight) : 0
|
||||
Repeater {
|
||||
model: visible ? parent.paddedRowCount : 0
|
||||
Loader {
|
||||
width: rowfiller.width
|
||||
height: rowfiller.rowHeight
|
||||
sourceComponent: root.rowDelegate
|
||||
property QtObject styleData: QtObject {
|
||||
readonly property bool alternate: (index + __listView.count) % 2 === 1
|
||||
readonly property bool selected: false
|
||||
readonly property bool hasActiveFocus: false
|
||||
readonly property bool pressed: false
|
||||
}
|
||||
readonly property var model: null
|
||||
readonly property var modelData: null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: columnModel
|
||||
}
|
||||
|
||||
highlightFollowsCurrentItem: true
|
||||
model: root.__model
|
||||
|
||||
delegate: FocusScope {
|
||||
id: rowItemContainer
|
||||
|
||||
activeFocusOnTab: false
|
||||
z: rowItem.activeFocus ? 0.7 : rowItem.itemSelected ? 0.5 : 0
|
||||
|
||||
property Item rowItem
|
||||
// We recycle instantiated row items to speed up list scrolling
|
||||
|
||||
Component.onDestruction: {
|
||||
// move the rowItem back in cache
|
||||
if (rowItem) {
|
||||
rowItem.visible = false;
|
||||
rowItem.parent = null;
|
||||
rowItem.rowIndex = -1;
|
||||
listView.rowItemStack.push(rowItem); // return rowItem to cache
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
// retrieve row item from cache
|
||||
if (listView.rowItemStack.length > 0)
|
||||
rowItem = listView.rowItemStack.pop();
|
||||
else
|
||||
rowItem = rowComponent.createObject(listView);
|
||||
|
||||
// Bind container to item size
|
||||
rowItemContainer.width = Qt.binding( function() { return rowItem.width });
|
||||
rowItemContainer.height = Qt.binding( function() { return rowItem.height });
|
||||
|
||||
// Reassign row-specific bindings
|
||||
rowItem.rowIndex = Qt.binding( function() { return model.index });
|
||||
rowItem.itemModelData = Qt.binding( function() { return typeof modelData === "undefined" ? null : modelData });
|
||||
rowItem.itemModel = Qt.binding( function() { return model });
|
||||
rowItem.parent = rowItemContainer;
|
||||
rowItem.visible = true;
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: rowComponent
|
||||
|
||||
FocusScope {
|
||||
id: rowitem
|
||||
visible: false
|
||||
|
||||
property int rowIndex
|
||||
property var itemModelData
|
||||
property var itemModel
|
||||
property bool itemSelected: __mouseArea.selected(rowIndex)
|
||||
property bool alternate: alternatingRowColors && rowIndex % 2 === 1
|
||||
readonly property color itemTextColor: itemSelected ? __style.highlightedTextColor : __style.textColor
|
||||
property Item branchDecoration: null
|
||||
|
||||
width: itemrow.width
|
||||
height: rowstyle.height
|
||||
|
||||
onActiveFocusChanged: {
|
||||
if (activeFocus)
|
||||
listView.currentIndex = rowIndex
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: rowstyle
|
||||
// row delegate
|
||||
sourceComponent: rowitem.itemModel !== undefined ? root.rowDelegate : null
|
||||
// Row fills the view width regardless of item size
|
||||
// But scrollbar should not adjust to it
|
||||
height: item ? item.height : 16
|
||||
width: parent.width + __horizontalScrollBar.width
|
||||
x: listView.contentX
|
||||
|
||||
// these properties are exposed to the row delegate
|
||||
// Note: these properties should be mirrored in the row filler as well
|
||||
property QtObject styleData: QtObject {
|
||||
readonly property int row: rowitem.rowIndex
|
||||
readonly property bool alternate: rowitem.alternate
|
||||
readonly property bool selected: rowitem.itemSelected
|
||||
readonly property bool hasActiveFocus: rowitem.activeFocus
|
||||
readonly property bool pressed: rowitem.rowIndex === __mouseArea.pressedRow
|
||||
}
|
||||
readonly property var model: rowitem.itemModel
|
||||
readonly property var modelData: rowitem.itemModelData
|
||||
}
|
||||
Row {
|
||||
id: itemrow
|
||||
height: parent.height
|
||||
Repeater {
|
||||
model: columnModel
|
||||
|
||||
delegate: __itemDelegateLoader
|
||||
|
||||
onItemAdded: {
|
||||
var columnItem = columnModel.get(index).columnItem
|
||||
item.__rowItem = rowitem
|
||||
item.__column = columnItem
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
headerPositioning: ListView.OverlayHeader
|
||||
header: Item {
|
||||
id: tableHeader
|
||||
visible: headerVisible
|
||||
width: Math.max(headerRow.width + listView.vScrollbarPadding, root.viewport.width)
|
||||
height: visible ? headerRow.height : 0
|
||||
|
||||
property alias headerRow: row
|
||||
property alias headerRepeater: repeater
|
||||
Row {
|
||||
id: row
|
||||
|
||||
Repeater {
|
||||
id: repeater
|
||||
|
||||
property int targetIndex: -1
|
||||
property int dragIndex: -1
|
||||
|
||||
model: columnModel
|
||||
|
||||
delegate: Item {
|
||||
id: headerRowDelegate
|
||||
readonly property int column: index
|
||||
z:-index
|
||||
width: modelData.width
|
||||
implicitWidth: columnCount === 1 ? viewport.width + __verticalScrollBar.width : headerStyle.implicitWidth
|
||||
visible: modelData.visible
|
||||
height: headerStyle.height
|
||||
|
||||
readonly property bool treeViewMovable: !__isTreeView || index > 0
|
||||
|
||||
Loader {
|
||||
id: headerStyle
|
||||
sourceComponent: root.headerDelegate
|
||||
width: parent.width
|
||||
property QtObject styleData: QtObject {
|
||||
readonly property string value: modelData.title
|
||||
readonly property bool pressed: headerClickArea.pressed
|
||||
readonly property bool containsMouse: headerClickArea.containsMouse
|
||||
readonly property int column: index
|
||||
readonly property int textAlignment: modelData.horizontalAlignment
|
||||
readonly property bool resizable: modelData.resizable
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle{
|
||||
id: targetmark
|
||||
width: parent.width
|
||||
height:parent.height
|
||||
opacity: (treeViewMovable && index === repeater.targetIndex && repeater.targetIndex !== repeater.dragIndex) ? 0.5 : 0
|
||||
Behavior on opacity { NumberAnimation { duration: 160 } }
|
||||
color: palette.highlight
|
||||
visible: modelData.movable
|
||||
}
|
||||
|
||||
MouseArea{
|
||||
id: headerClickArea
|
||||
drag.axis: Qt.YAxis
|
||||
hoverEnabled: Settings.hoverEnabled
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
if (sortIndicatorColumn === index)
|
||||
sortIndicatorOrder = sortIndicatorOrder === Qt.AscendingOrder ? Qt.DescendingOrder : Qt.AscendingOrder
|
||||
sortIndicatorColumn = index
|
||||
}
|
||||
// Here we handle moving header sections
|
||||
// NOTE: the direction is different from the master branch
|
||||
// so this indicates that I am using an invalid assumption on item ordering
|
||||
onPositionChanged: {
|
||||
if (drag.active && modelData.movable && pressed && columnCount > 1) { // only do this while dragging
|
||||
for (var h = columnCount-1 ; h >= 0 ; --h) {
|
||||
if (headerRow.children[h].visible && drag.target.x + headerRowDelegate.width/2 > headerRow.children[h].x) {
|
||||
repeater.targetIndex = h
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onPressed: {
|
||||
repeater.dragIndex = index
|
||||
}
|
||||
|
||||
onReleased: {
|
||||
if (repeater.targetIndex >= 0 && repeater.targetIndex !== index ) {
|
||||
var targetColumn = columnModel.get(repeater.targetIndex).columnItem
|
||||
if (targetColumn.movable && (!__isTreeView || repeater.targetIndex > 0)) {
|
||||
if (sortIndicatorColumn === index)
|
||||
sortIndicatorColumn = repeater.targetIndex
|
||||
columnModel.move(index, repeater.targetIndex, 1)
|
||||
}
|
||||
}
|
||||
repeater.targetIndex = -1
|
||||
repeater.dragIndex = -1
|
||||
}
|
||||
drag.target: treeViewMovable && modelData.movable && columnCount > 1 ? draghandle : null
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: draghandle
|
||||
property QtObject styleData: QtObject{
|
||||
readonly property string value: modelData.title
|
||||
readonly property bool pressed: headerClickArea.pressed
|
||||
readonly property bool containsMouse: headerClickArea.containsMouse
|
||||
readonly property int column: index
|
||||
readonly property int textAlignment: modelData.horizontalAlignment
|
||||
}
|
||||
parent: tableHeader
|
||||
x: __implicitX
|
||||
property double __implicitX: headerRowDelegate.x
|
||||
width: modelData.width
|
||||
height: parent.height
|
||||
sourceComponent: root.headerDelegate
|
||||
visible: headerClickArea.pressed
|
||||
onVisibleChanged: {
|
||||
if (!visible)
|
||||
x = Qt.binding(function () { return __implicitX })
|
||||
}
|
||||
opacity: 0.5
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
id: headerResizeHandle
|
||||
property int offset: 0
|
||||
readonly property int minimumSize: 20
|
||||
preventStealing: true
|
||||
anchors.rightMargin: -width/2
|
||||
width: Settings.hasTouchScreen ? Screen.pixelDensity * 3.5 : 16
|
||||
height: parent.height
|
||||
anchors.right: parent.right
|
||||
enabled: modelData.resizable && columnCount > 0
|
||||
onPositionChanged: {
|
||||
var newHeaderWidth = modelData.width + (mouseX - offset)
|
||||
modelData.width = Math.max(minimumSize, newHeaderWidth)
|
||||
}
|
||||
|
||||
onDoubleClicked: getColumn(index).resizeToContents()
|
||||
onPressedChanged: if (pressed) offset=mouseX
|
||||
cursorShape: enabled && repeater.dragIndex==-1 ? Qt.SplitHCursor : Qt.ArrowCursor
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
property QtObject styleData: QtObject{
|
||||
readonly property string value: ""
|
||||
readonly property bool pressed: false
|
||||
readonly property bool containsMouse: false
|
||||
readonly property int column: -1
|
||||
readonly property int textAlignment: Text.AlignLeft
|
||||
}
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: headerRow.bottom
|
||||
sourceComponent: root.headerDelegate
|
||||
readonly property real __remainingWidth: parent.width - headerRow.width
|
||||
visible: __remainingWidth > 0
|
||||
width: __remainingWidth
|
||||
z:-1
|
||||
}
|
||||
}
|
||||
|
||||
function columnAt(offset) {
|
||||
var item = listView.headerItem.headerRow.childAt(offset, 0)
|
||||
return item ? item.column : -1
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,109 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.2
|
||||
|
||||
/*
|
||||
CalendarHeaderModel contains a list of the days of a week,
|
||||
according to a \l locale. The \l locale affects which day of the week
|
||||
is first in the model.
|
||||
|
||||
The only role provided by the model is \c dayOfWeek, which is one of the
|
||||
following JavaScript values:
|
||||
|
||||
\list
|
||||
\li \c Locale.Sunday
|
||||
\li \c Locale.Monday
|
||||
\li \c Locale.Tuesday
|
||||
\li \c Locale.Wednesday
|
||||
\li \c Locale.Thursday
|
||||
\li \c Locale.Friday
|
||||
\li \c Locale.Saturday
|
||||
\endlist
|
||||
*/
|
||||
|
||||
ListModel {
|
||||
id: root
|
||||
|
||||
/*
|
||||
The locale that this model should be based on.
|
||||
This affects which day of the week is first in the model.
|
||||
*/
|
||||
property var locale
|
||||
|
||||
ListElement {
|
||||
dayOfWeek: Locale.Sunday
|
||||
}
|
||||
ListElement {
|
||||
dayOfWeek: Locale.Monday
|
||||
}
|
||||
ListElement {
|
||||
dayOfWeek: Locale.Tuesday
|
||||
}
|
||||
ListElement {
|
||||
dayOfWeek: Locale.Wednesday
|
||||
}
|
||||
ListElement {
|
||||
dayOfWeek: Locale.Thursday
|
||||
}
|
||||
ListElement {
|
||||
dayOfWeek: Locale.Friday
|
||||
}
|
||||
ListElement {
|
||||
dayOfWeek: Locale.Saturday
|
||||
}
|
||||
|
||||
Component.onCompleted: updateFirstDayOfWeek()
|
||||
onLocaleChanged: updateFirstDayOfWeek()
|
||||
|
||||
function updateFirstDayOfWeek() {
|
||||
var daysOfWeek = [Locale.Sunday, Locale.Monday, Locale.Tuesday,
|
||||
Locale.Wednesday, Locale.Thursday, Locale.Friday, Locale.Saturday];
|
||||
var firstDayOfWeek = root.locale.firstDayOfWeek;
|
||||
|
||||
var shifted = daysOfWeek.splice(firstDayOfWeek, daysOfWeek.length - firstDayOfWeek);
|
||||
daysOfWeek = shifted.concat(daysOfWeek)
|
||||
|
||||
if (firstDayOfWeek !== root.get(0).dayOfWeek) {
|
||||
for (var i = 0; i < daysOfWeek.length; ++i) {
|
||||
root.setProperty(i, "dayOfWeek", daysOfWeek[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,137 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
.pragma library
|
||||
|
||||
var daysInAWeek = 7;
|
||||
var monthsInAYear = 12;
|
||||
|
||||
// Not the number of weeks per month, but the number of weeks that are
|
||||
// shown on a typical calendar.
|
||||
var weeksOnACalendarMonth = 6;
|
||||
|
||||
// Can't create year 1 directly...
|
||||
var minimumCalendarDate = new Date(-1, 0, 1);
|
||||
minimumCalendarDate.setFullYear(minimumCalendarDate.getFullYear() + 2);
|
||||
var maximumCalendarDate = new Date(275759, 9, 25);
|
||||
|
||||
function daysInMonth(date) {
|
||||
// Passing 0 as the day will give us the previous month, which will be
|
||||
// date.getMonth() since we added 1 to it.
|
||||
return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a copy of \a date with its month set to \a month, keeping the same
|
||||
day if possible. Does not modify \a date.
|
||||
*/
|
||||
function setMonth(date, month) {
|
||||
var oldDay = date.getDate();
|
||||
var newDate = new Date(date);
|
||||
// Set the day first, because setting the month could cause it to skip ahead
|
||||
// a month if the day is larger than the latest day in that month.
|
||||
newDate.setDate(1);
|
||||
newDate.setMonth(month);
|
||||
// We'd like to have the previous day still selected when we change
|
||||
// months, but it might not be possible, so use the smallest of the two.
|
||||
newDate.setDate(Math.min(oldDay, daysInMonth(newDate)));
|
||||
return newDate;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the cell rectangle for the cell at the given \a index, assuming
|
||||
that the grid has a number of columns equal to \a columns and rows
|
||||
equal to \a rows, with an available width of \a availableWidth and height
|
||||
of \a availableHeight.
|
||||
|
||||
If \a gridLineWidth is greater than \c 0, the cell rectangle will be
|
||||
calculated under the assumption that there is a grid between the cells:
|
||||
|
||||
31 | 1 | 2 | 3 | 4 | 5 | 6
|
||||
--------------------------------
|
||||
7 | 8 | 9 | 10 | 11 | 12 | 13
|
||||
--------------------------------
|
||||
14 | 15 | 16 | 17 | 18 | 19 | 20
|
||||
--------------------------------
|
||||
21 | 22 | 23 | 24 | 25 | 26 | 27
|
||||
--------------------------------
|
||||
28 | 29 | 30 | 31 | 1 | 2 | 3
|
||||
--------------------------------
|
||||
4 | 5 | 6 | 7 | 8 | 9 | 10
|
||||
*/
|
||||
function cellRectAt(index, columns, rows, availableWidth, availableHeight, gridLineWidth) {
|
||||
var col = Math.floor(index % columns);
|
||||
var row = Math.floor(index / columns);
|
||||
|
||||
var availableWidthMinusGridLines = availableWidth - ((columns - 1) * gridLineWidth);
|
||||
var availableHeightMinusGridLines = availableHeight - ((rows - 1) * gridLineWidth);
|
||||
var remainingHorizontalSpace = Math.floor(availableWidthMinusGridLines % columns);
|
||||
var remainingVerticalSpace = Math.floor(availableHeightMinusGridLines % rows);
|
||||
var baseCellWidth = Math.floor(availableWidthMinusGridLines / columns);
|
||||
var baseCellHeight = Math.floor(availableHeightMinusGridLines / rows);
|
||||
|
||||
var rect = Qt.rect(0, 0, 0, 0);
|
||||
|
||||
rect.x = baseCellWidth * col;
|
||||
rect.width = baseCellWidth;
|
||||
if (remainingHorizontalSpace > 0) {
|
||||
if (col < remainingHorizontalSpace) {
|
||||
++rect.width;
|
||||
}
|
||||
|
||||
// This cell's x position should be increased by 1 for every column above it.
|
||||
rect.x += Math.min(remainingHorizontalSpace, col);
|
||||
}
|
||||
|
||||
rect.y = baseCellHeight * row;
|
||||
rect.height = baseCellHeight;
|
||||
if (remainingVerticalSpace > 0) {
|
||||
if (row < remainingVerticalSpace) {
|
||||
++rect.height;
|
||||
}
|
||||
|
||||
// This cell's y position should be increased by 1 for every row above it.
|
||||
rect.y += Math.min(remainingVerticalSpace, row);
|
||||
}
|
||||
|
||||
rect.x += col * gridLineWidth;
|
||||
rect.y += row * gridLineWidth;
|
||||
|
||||
return rect;
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,252 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQml 2.14 as Qml
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Controls.Private 1.0
|
||||
|
||||
Item {
|
||||
id: content
|
||||
|
||||
property Component menuItemDelegate
|
||||
property Component scrollIndicatorStyle
|
||||
property Component scrollerStyle
|
||||
property var itemsModel
|
||||
property int minWidth: 100
|
||||
property real maxHeight: 800
|
||||
readonly property bool mousePressed: hoverArea.pressed
|
||||
|
||||
signal triggered(var item)
|
||||
|
||||
function menuItemAt(index) {
|
||||
list.currentIndex = index
|
||||
return list.currentItem
|
||||
}
|
||||
|
||||
width: Math.max(list.contentWidth, minWidth)
|
||||
height: Math.min(list.contentHeight, fittedMaxHeight)
|
||||
|
||||
readonly property int currentIndex: __menu.__currentIndex
|
||||
property Item currentItem: null
|
||||
property int itemHeight: 23
|
||||
|
||||
Component.onCompleted: {
|
||||
var children = list.contentItem.children
|
||||
for (var i = 0; i < list.count; i++) {
|
||||
var child = children[i]
|
||||
if (child.visible && child.styleData.type === MenuItemType.Item) {
|
||||
itemHeight = children[i].height
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
readonly property int fittingItems: Math.floor((maxHeight - downScroller.height) / itemHeight)
|
||||
readonly property real fittedMaxHeight: itemHeight * fittingItems + downScroller.height
|
||||
readonly property bool shouldUseScrollers: scrollView.style === emptyScrollerStyle && itemsModel.length > fittingItems
|
||||
readonly property real upScrollerHeight: upScroller.visible ? upScroller.height : 0
|
||||
readonly property real downScrollerHeight: downScroller.visible ? downScroller.height : 0
|
||||
property var oldMousePos: undefined
|
||||
property var openedSubmenu: null
|
||||
|
||||
function updateCurrentItem(mouse) {
|
||||
var pos = mapToItem(list.contentItem, mouse.x, mouse.y)
|
||||
var dx = 0
|
||||
var dy = 0
|
||||
var dist = 0
|
||||
if (openedSubmenu && oldMousePos !== undefined) {
|
||||
dx = mouse.x - oldMousePos.x
|
||||
dy = mouse.y - oldMousePos.y
|
||||
dist = Math.sqrt(dx * dx + dy * dy)
|
||||
}
|
||||
oldMousePos = mouse
|
||||
if (openedSubmenu && dist > 5) {
|
||||
var menuRect = __menu.__popupGeometry
|
||||
var submenuRect = openedSubmenu.__popupGeometry
|
||||
var angle = Math.atan2(dy, dx)
|
||||
var ds = 0
|
||||
if (submenuRect.x > menuRect.x) {
|
||||
ds = menuRect.width - oldMousePos.x
|
||||
} else {
|
||||
angle = Math.PI - angle
|
||||
ds = oldMousePos.x
|
||||
}
|
||||
var above = submenuRect.y - menuRect.y - oldMousePos.y
|
||||
var below = submenuRect.height - above
|
||||
var minAngle = Math.atan2(above, ds)
|
||||
var maxAngle = Math.atan2(below, ds)
|
||||
// This tests that the current mouse position is in
|
||||
// the triangle defined by the previous mouse position
|
||||
// and the submenu's top-left and bottom-left corners.
|
||||
if (minAngle < angle && angle < maxAngle) {
|
||||
sloppyTimer.start()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (!currentItem || !currentItem.contains(Qt.point(pos.x - currentItem.x, pos.y - currentItem.y))) {
|
||||
if (currentItem && !hoverArea.pressed
|
||||
&& currentItem.styleData.type === MenuItemType.Menu) {
|
||||
currentItem.__closeSubMenu()
|
||||
openedSubmenu = null
|
||||
}
|
||||
currentItem = list.itemAt(pos.x, pos.y)
|
||||
if (currentItem) {
|
||||
__menu.__currentIndex = currentItem.__menuItemIndex
|
||||
if (currentItem.styleData.type === MenuItemType.Menu) {
|
||||
showCurrentItemSubMenu(false)
|
||||
}
|
||||
} else {
|
||||
__menu.__currentIndex = -1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function showCurrentItemSubMenu(immediately) {
|
||||
if (!currentItem.__menuItem.__popupVisible) {
|
||||
currentItem.__showSubMenu(immediately)
|
||||
openedSubmenu = currentItem.__menuItem
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: sloppyTimer
|
||||
interval: 1000
|
||||
|
||||
// Stop timer as soon as we hover one of the submenu items
|
||||
property int currentIndex: openedSubmenu ? openedSubmenu.__currentIndex : -1
|
||||
onCurrentIndexChanged: if (currentIndex !== -1) stop()
|
||||
|
||||
onTriggered: {
|
||||
if (openedSubmenu && openedSubmenu.__currentIndex === -1)
|
||||
updateCurrentItem(oldMousePos)
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: emptyScrollerStyle
|
||||
Style {
|
||||
padding { left: 0; right: 0; top: 0; bottom: 0 }
|
||||
property bool scrollToClickedPosition: false
|
||||
property Component frame: Item { visible: false }
|
||||
property Component corner: Item { visible: false }
|
||||
property Component __scrollbar: Item { visible: false }
|
||||
}
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
id: scrollView
|
||||
anchors {
|
||||
fill: parent
|
||||
topMargin: upScrollerHeight
|
||||
bottomMargin: downScrollerHeight
|
||||
}
|
||||
|
||||
style: scrollerStyle || emptyScrollerStyle
|
||||
__wheelAreaScrollSpeed: itemHeight
|
||||
|
||||
ListView {
|
||||
id: list
|
||||
model: itemsModel
|
||||
delegate: menuItemDelegate
|
||||
snapMode: ListView.SnapToItem
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
highlightFollowsCurrentItem: true
|
||||
highlightMoveDuration: 0
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: hoverArea
|
||||
anchors.left: scrollView.left
|
||||
width: scrollView.width - scrollView.__verticalScrollBar.width
|
||||
height: parent.height
|
||||
|
||||
hoverEnabled: Settings.hoverEnabled
|
||||
acceptedButtons: Qt.AllButtons
|
||||
|
||||
onPositionChanged: updateCurrentItem({ "x": mouse.x, "y": mouse.y })
|
||||
onPressed: updateCurrentItem({ "x": mouse.x, "y": mouse.y })
|
||||
onReleased: {
|
||||
if (currentItem && currentItem.__menuItem.enabled) {
|
||||
if (currentItem.styleData.type === MenuItemType.Menu) {
|
||||
showCurrentItemSubMenu(true)
|
||||
} else {
|
||||
content.triggered(currentItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
onExited: {
|
||||
if (currentItem && !currentItem.__menuItem.__popupVisible) {
|
||||
currentItem = null
|
||||
__menu.__currentIndex = -1
|
||||
}
|
||||
}
|
||||
|
||||
MenuContentScroller {
|
||||
id: upScroller
|
||||
direction: Qt.UpArrow
|
||||
visible: shouldUseScrollers && !list.atYBeginning
|
||||
function scrollABit() { list.contentY -= itemHeight }
|
||||
}
|
||||
|
||||
MenuContentScroller {
|
||||
id: downScroller
|
||||
direction: Qt.DownArrow
|
||||
visible: shouldUseScrollers && !list.atYEnd
|
||||
function scrollABit() { list.contentY += itemHeight }
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
interval: 1
|
||||
running: true
|
||||
repeat: false
|
||||
onTriggered: list.positionViewAtIndex(currentIndex, !scrollView.__style
|
||||
? ListView.Center : ListView.Beginning)
|
||||
}
|
||||
|
||||
Qml.Binding {
|
||||
target: scrollView.__verticalScrollBar
|
||||
property: "singleStep"
|
||||
value: itemHeight
|
||||
restoreMode: Binding.RestoreBinding
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,108 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Layouts 1.1
|
||||
|
||||
Item {
|
||||
id: contentItem
|
||||
property real minimumWidth: __calcMinimum('Width')
|
||||
property real minimumHeight: __calcMinimum('Height')
|
||||
property real maximumWidth: Number.POSITIVE_INFINITY
|
||||
property real maximumHeight: Number.POSITIVE_INFINITY
|
||||
implicitWidth: __calcImplicitWidth()
|
||||
implicitHeight: __calcImplicitHeight()
|
||||
|
||||
/*! \internal */
|
||||
property Item __layoutItem: contentItem.visibleChildren.length === 1 ? contentItem.visibleChildren[0] : null
|
||||
/*! \internal */
|
||||
property real __marginsWidth: __layoutItem ? __layoutItem.anchors.leftMargin + __layoutItem.anchors.rightMargin : 0
|
||||
/*! \internal */
|
||||
property real __marginsHeight: __layoutItem ? __layoutItem.anchors.topMargin + __layoutItem.anchors.bottomMargin : 0
|
||||
|
||||
/*! \internal */
|
||||
property bool __noMinimumWidthGiven : false
|
||||
/*! \internal */
|
||||
property bool __noMinimumHeightGiven : false
|
||||
/*! \internal */
|
||||
property bool __noImplicitWidthGiven : false
|
||||
/*! \internal */
|
||||
property bool __noImplicitHeightGiven : false
|
||||
|
||||
function __calcImplicitWidth() {
|
||||
if (__layoutItem && __layoutItem.anchors.fill)
|
||||
return __calcImplicit('Width')
|
||||
return contentItem.childrenRect.x + contentItem.childrenRect.width
|
||||
}
|
||||
|
||||
function __calcImplicitHeight() {
|
||||
if (__layoutItem && __layoutItem.anchors.fill)
|
||||
return __calcImplicit('Height')
|
||||
return contentItem.childrenRect.y + contentItem.childrenRect.height
|
||||
}
|
||||
|
||||
function __calcImplicit(hw) {
|
||||
var pref = __layoutItem.Layout['preferred' + hw]
|
||||
if (pref < 0) {
|
||||
pref = __layoutItem['implicit' + hw]
|
||||
}
|
||||
contentItem['__noImplicit' + hw + 'Given'] = (pref === 0 ? true : false)
|
||||
pref += contentItem['__margins' + hw]
|
||||
return pref
|
||||
}
|
||||
|
||||
function __calcMinimum(hw) { // hw is 'Width' or 'Height'
|
||||
return (__layoutItem && __layoutItem.anchors.fill) ? __calcMinMax('minimum', hw) : 0
|
||||
}
|
||||
|
||||
function __calcMaximum(hw) { // hw is 'Width' or 'Height'
|
||||
return (__layoutItem && __layoutItem.anchors.fill) ? __calcMinMax('maximum', hw) : Number.POSITIVE_INFINITY
|
||||
}
|
||||
|
||||
function __calcMinMax(minMaxConstraint, hw) {
|
||||
var attachedPropName = minMaxConstraint + hw
|
||||
var extent = __layoutItem.Layout[attachedPropName]
|
||||
|
||||
if (minMaxConstraint === 'minimum')
|
||||
contentItem['__noMinimum' + hw + 'Given'] = (extent === 0 ? true : false)
|
||||
|
||||
extent += contentItem['__margins' + hw]
|
||||
return extent
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,94 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls.Styles 1.1
|
||||
|
||||
/*!
|
||||
\qmltype Control
|
||||
\internal
|
||||
\qmlabstract
|
||||
\inqmlmodule QtQuick.Controls.Private
|
||||
*/
|
||||
FocusScope {
|
||||
id: root
|
||||
|
||||
/*! \qmlproperty Component Control::style
|
||||
|
||||
The style Component for this control.
|
||||
\sa {Qt Quick Controls Styles QML Types}
|
||||
|
||||
*/
|
||||
property Component style
|
||||
|
||||
/*! \internal */
|
||||
property QtObject __style: styleLoader.item
|
||||
|
||||
/*! \internal */
|
||||
property Item __panel: panelLoader.item
|
||||
|
||||
/*! \internal */
|
||||
property var styleHints
|
||||
|
||||
implicitWidth: __panel ? __panel.implicitWidth: 0
|
||||
implicitHeight: __panel ? __panel.implicitHeight: 0
|
||||
baselineOffset: __panel ? __panel.baselineOffset: 0
|
||||
activeFocusOnTab: false
|
||||
|
||||
/*! \internal */
|
||||
property alias __styleData: styleLoader.styleData
|
||||
|
||||
Loader {
|
||||
id: styleLoader
|
||||
sourceComponent: style
|
||||
property Item __control: root
|
||||
property QtObject styleData: null
|
||||
onStatusChanged: {
|
||||
if (status === Loader.Error)
|
||||
console.error("Failed to load Style for", root)
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: panelLoader
|
||||
anchors.fill: parent
|
||||
sourceComponent: __style ? __style.panel : null
|
||||
onStatusChanged: if (status === Loader.Error) console.error("Failed to load Style for", root)
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,88 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Controls.Private 1.0
|
||||
|
||||
Loader {
|
||||
property Item control
|
||||
property Item input
|
||||
property Item cursorHandle
|
||||
property Item selectionHandle
|
||||
property Flickable flickable
|
||||
property Component defaultMenu: item && item.defaultMenu ? item.defaultMenu : null
|
||||
property QtObject menuInstance: null
|
||||
property MouseArea mouseArea
|
||||
property QtObject style: __style
|
||||
|
||||
Connections {
|
||||
target: control
|
||||
function onMenuChanged() {
|
||||
if (menuInstance !== null) {
|
||||
menuInstance.destroy()
|
||||
menuInstance = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getMenuInstance()
|
||||
{
|
||||
// Lazy load menu when first requested
|
||||
if (!menuInstance && control.menu) {
|
||||
menuInstance = control.menu.createObject(input);
|
||||
}
|
||||
return menuInstance;
|
||||
}
|
||||
|
||||
function syncStyle() {
|
||||
if (!style)
|
||||
return;
|
||||
|
||||
if (style.__editMenu)
|
||||
sourceComponent = style.__editMenu;
|
||||
else {
|
||||
// todo: get ios/android/base menus from style as well
|
||||
source = (Qt.resolvedUrl(Qt.platform.os === "ios" ? ""
|
||||
: Qt.platform.os === "android" ? "" : "EditMenu_base.qml"));
|
||||
}
|
||||
}
|
||||
onStyleChanged: syncStyle();
|
||||
Component.onCompleted: syncStyle();
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,173 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Controls.Private 1.0
|
||||
|
||||
Item {
|
||||
id: editMenuBase
|
||||
anchors.fill: parent
|
||||
|
||||
Component {
|
||||
id: undoAction
|
||||
Action {
|
||||
text: qsTr("&Undo")
|
||||
shortcut: StandardKey.Undo
|
||||
iconName: "edit-undo"
|
||||
enabled: input.canUndo
|
||||
onTriggered: input.undo()
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: redoAction
|
||||
Action {
|
||||
text: qsTr("&Redo")
|
||||
shortcut: StandardKey.Redo
|
||||
iconName: "edit-redo"
|
||||
enabled: input.canRedo
|
||||
onTriggered: input.redo()
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: cutAction
|
||||
Action {
|
||||
text: qsTr("Cu&t")
|
||||
shortcut: StandardKey.Cut
|
||||
iconName: "edit-cut"
|
||||
enabled: !input.readOnly && selectionStart !== selectionEnd
|
||||
onTriggered: {
|
||||
input.cut();
|
||||
input.select(input.cursorPosition, input.cursorPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: copyAction
|
||||
Action {
|
||||
text: qsTr("&Copy")
|
||||
shortcut: StandardKey.Copy
|
||||
iconName: "edit-copy"
|
||||
enabled: input.selectionStart !== input.selectionEnd
|
||||
onTriggered: {
|
||||
input.copy();
|
||||
input.select(input.cursorPosition, input.cursorPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: pasteAction
|
||||
Action {
|
||||
text: qsTr("&Paste")
|
||||
shortcut: StandardKey.Paste
|
||||
iconName: "edit-paste"
|
||||
enabled: input.canPaste
|
||||
onTriggered: input.paste()
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: deleteAction
|
||||
Action {
|
||||
text: qsTr("Delete")
|
||||
shortcut: StandardKey.Delete
|
||||
iconName: "edit-delete"
|
||||
enabled: !input.readOnly && input.selectionStart !== input.selectionEnd
|
||||
onTriggered: input.remove(input.selectionStart, input.selectionEnd)
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: clearAction
|
||||
Action {
|
||||
text: qsTr("Clear")
|
||||
shortcut: StandardKey.DeleteCompleteLine
|
||||
iconName: "edit-clear"
|
||||
enabled: !input.readOnly && input.length > 0
|
||||
onTriggered: input.remove(0, input.length)
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: selectAllAction
|
||||
Action {
|
||||
text: qsTr("Select All")
|
||||
shortcut: StandardKey.SelectAll
|
||||
enabled: !(input.selectionStart === 0 && input.selectionEnd === input.length)
|
||||
onTriggered: input.selectAll()
|
||||
}
|
||||
}
|
||||
|
||||
property Component defaultMenu: Menu {
|
||||
MenuItem { action: undoAction.createObject(editMenuBase) }
|
||||
MenuItem { action: redoAction.createObject(editMenuBase) }
|
||||
MenuSeparator {}
|
||||
MenuItem { action: cutAction.createObject(editMenuBase) }
|
||||
MenuItem { action: copyAction.createObject(editMenuBase) }
|
||||
MenuItem { action: pasteAction.createObject(editMenuBase) }
|
||||
MenuItem { action: deleteAction.createObject(editMenuBase) }
|
||||
MenuItem { action: clearAction.createObject(editMenuBase) }
|
||||
MenuSeparator {}
|
||||
MenuItem { action: selectAllAction.createObject(editMenuBase) }
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: mouseArea
|
||||
|
||||
function onClicked() {
|
||||
if (input.selectionStart === input.selectionEnd) {
|
||||
var cursorPos = input.positionAt(mouse.x, mouse.y)
|
||||
input.moveHandles(cursorPos, cursorPos)
|
||||
}
|
||||
|
||||
input.activate()
|
||||
|
||||
if (control.menu) {
|
||||
var menu = getMenuInstance();
|
||||
menu.__dismissAndDestroy();
|
||||
var menuPos = mapToItem(null, mouse.x, mouse.y)
|
||||
menu.__popup(Qt.rect(menuPos.x, menuPos.y, 0, 0), -1, MenuPrivate.EditMenu);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,330 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.4
|
||||
|
||||
Item {
|
||||
id: rootItem
|
||||
property variant source
|
||||
property real spread: 0.0
|
||||
property real blur: 0.0
|
||||
property color color: "white"
|
||||
property bool transparentBorder: false
|
||||
property bool cached: false
|
||||
|
||||
SourceProxy {
|
||||
id: sourceProxy
|
||||
input: rootItem.source
|
||||
}
|
||||
|
||||
ShaderEffectSource {
|
||||
id: cacheItem
|
||||
anchors.fill: shaderItem
|
||||
visible: rootItem.cached
|
||||
smooth: true
|
||||
sourceItem: shaderItem
|
||||
live: true
|
||||
hideSource: visible
|
||||
}
|
||||
|
||||
property string __internalBlurVertexShader: "qrc:/QtQuick/Controls/Shaders/blur.vert"
|
||||
|
||||
property string __internalBlurFragmentShader: "qrc:/QtQuick/Controls/Shaders/blur.frag"
|
||||
|
||||
ShaderEffect {
|
||||
id: level0
|
||||
property variant source: sourceProxy.output
|
||||
anchors.fill: parent
|
||||
visible: false
|
||||
smooth: true
|
||||
}
|
||||
|
||||
ShaderEffectSource {
|
||||
id: level1
|
||||
width: Math.ceil(shaderItem.width / 32) * 32
|
||||
height: Math.ceil(shaderItem.height / 32) * 32
|
||||
sourceItem: level0
|
||||
hideSource: rootItem.visible
|
||||
sourceRect: transparentBorder ? Qt.rect(-64, -64, shaderItem.width, shaderItem.height) : Qt.rect(0,0,0,0)
|
||||
smooth: true
|
||||
visible: false
|
||||
}
|
||||
|
||||
ShaderEffect {
|
||||
id: effect1
|
||||
property variant source: level1
|
||||
property real yStep: 1/height
|
||||
property real xStep: 1/width
|
||||
anchors.fill: level2
|
||||
visible: false
|
||||
smooth: true
|
||||
vertexShader: __internalBlurVertexShader
|
||||
fragmentShader: __internalBlurFragmentShader
|
||||
}
|
||||
|
||||
ShaderEffectSource {
|
||||
id: level2
|
||||
width: level1.width / 2
|
||||
height: level1.height / 2
|
||||
sourceItem: effect1
|
||||
hideSource: rootItem.visible
|
||||
visible: false
|
||||
smooth: true
|
||||
}
|
||||
|
||||
ShaderEffect {
|
||||
id: effect2
|
||||
property variant source: level2
|
||||
property real yStep: 1/height
|
||||
property real xStep: 1/width
|
||||
anchors.fill: level3
|
||||
visible: false
|
||||
smooth: true
|
||||
vertexShader: __internalBlurVertexShader
|
||||
fragmentShader: __internalBlurFragmentShader
|
||||
}
|
||||
|
||||
ShaderEffectSource {
|
||||
id: level3
|
||||
width: level2.width / 2
|
||||
height: level2.height / 2
|
||||
sourceItem: effect2
|
||||
hideSource: rootItem.visible
|
||||
visible: false
|
||||
smooth: true
|
||||
}
|
||||
|
||||
ShaderEffect {
|
||||
id: effect3
|
||||
property variant source: level3
|
||||
property real yStep: 1/height
|
||||
property real xStep: 1/width
|
||||
anchors.fill: level4
|
||||
visible: false
|
||||
smooth: true
|
||||
vertexShader: __internalBlurVertexShader
|
||||
fragmentShader: __internalBlurFragmentShader
|
||||
}
|
||||
|
||||
ShaderEffectSource {
|
||||
id: level4
|
||||
width: level3.width / 2
|
||||
height: level3.height / 2
|
||||
sourceItem: effect3
|
||||
hideSource: rootItem.visible
|
||||
visible: false
|
||||
smooth: true
|
||||
}
|
||||
|
||||
ShaderEffect {
|
||||
id: effect4
|
||||
property variant source: level4
|
||||
property real yStep: 1/height
|
||||
property real xStep: 1/width
|
||||
anchors.fill: level5
|
||||
visible: false
|
||||
smooth: true
|
||||
vertexShader: __internalBlurVertexShader
|
||||
fragmentShader: __internalBlurFragmentShader
|
||||
}
|
||||
|
||||
ShaderEffectSource {
|
||||
id: level5
|
||||
width: level4.width / 2
|
||||
height: level4.height / 2
|
||||
sourceItem: effect4
|
||||
hideSource: rootItem.visible
|
||||
visible: false
|
||||
smooth: true
|
||||
}
|
||||
|
||||
ShaderEffect {
|
||||
id: effect5
|
||||
property variant source: level5
|
||||
property real yStep: 1/height
|
||||
property real xStep: 1/width
|
||||
anchors.fill: level6
|
||||
visible: false
|
||||
smooth: true
|
||||
vertexShader: __internalBlurVertexShader
|
||||
fragmentShader: __internalBlurFragmentShader
|
||||
}
|
||||
|
||||
ShaderEffectSource {
|
||||
id: level6
|
||||
width: level5.width / 2
|
||||
height: level5.height / 2
|
||||
sourceItem: effect5
|
||||
hideSource: rootItem.visible
|
||||
visible: false
|
||||
smooth: true
|
||||
}
|
||||
|
||||
Item {
|
||||
id: dummysource
|
||||
width: 1
|
||||
height: 1
|
||||
visible: false
|
||||
}
|
||||
|
||||
ShaderEffectSource {
|
||||
id: dummy
|
||||
width: 1
|
||||
height: 1
|
||||
sourceItem: dummysource
|
||||
visible: false
|
||||
smooth: false
|
||||
live: false
|
||||
}
|
||||
|
||||
ShaderEffect {
|
||||
id: shaderItem
|
||||
x: transparentBorder ? -64 : 0
|
||||
y: transparentBorder ? -64 : 0
|
||||
width: transparentBorder ? parent.width + 128 : parent.width
|
||||
height: transparentBorder ? parent.height + 128 : parent.height
|
||||
|
||||
property variant source1: level1
|
||||
property variant source2: level2
|
||||
property variant source3: level3
|
||||
property variant source4: level4
|
||||
property variant source5: level5
|
||||
property variant source6: level6
|
||||
property real lod: rootItem.blur
|
||||
|
||||
property real weight1;
|
||||
property real weight2;
|
||||
property real weight3;
|
||||
property real weight4;
|
||||
property real weight5;
|
||||
property real weight6;
|
||||
|
||||
property real spread: 1.0 - (rootItem.spread * 0.98)
|
||||
property alias color: rootItem.color
|
||||
|
||||
function weight(v) {
|
||||
if (v <= 0.0)
|
||||
return 1
|
||||
if (v >= 0.5)
|
||||
return 0
|
||||
|
||||
return 1.0 - v / 0.5
|
||||
}
|
||||
|
||||
function calculateWeights() {
|
||||
|
||||
var w1 = weight(Math.abs(lod - 0.100))
|
||||
var w2 = weight(Math.abs(lod - 0.300))
|
||||
var w3 = weight(Math.abs(lod - 0.500))
|
||||
var w4 = weight(Math.abs(lod - 0.700))
|
||||
var w5 = weight(Math.abs(lod - 0.900))
|
||||
var w6 = weight(Math.abs(lod - 1.100))
|
||||
|
||||
var sum = w1 + w2 + w3 + w4 + w5 + w6;
|
||||
weight1 = w1 / sum;
|
||||
weight2 = w2 / sum;
|
||||
weight3 = w3 / sum;
|
||||
weight4 = w4 / sum;
|
||||
weight5 = w5 / sum;
|
||||
weight6 = w6 / sum;
|
||||
|
||||
upateSources()
|
||||
}
|
||||
|
||||
function upateSources() {
|
||||
var sources = new Array();
|
||||
var weights = new Array();
|
||||
|
||||
if (weight1 > 0) {
|
||||
sources.push(level1)
|
||||
weights.push(weight1)
|
||||
}
|
||||
|
||||
if (weight2 > 0) {
|
||||
sources.push(level2)
|
||||
weights.push(weight2)
|
||||
}
|
||||
|
||||
if (weight3 > 0) {
|
||||
sources.push(level3)
|
||||
weights.push(weight3)
|
||||
}
|
||||
|
||||
if (weight4 > 0) {
|
||||
sources.push(level4)
|
||||
weights.push(weight4)
|
||||
}
|
||||
|
||||
if (weight5 > 0) {
|
||||
sources.push(level5)
|
||||
weights.push(weight5)
|
||||
}
|
||||
|
||||
if (weight6 > 0) {
|
||||
sources.push(level6)
|
||||
weights.push(weight6)
|
||||
}
|
||||
|
||||
for (var j = sources.length; j < 6; j++) {
|
||||
sources.push(dummy)
|
||||
weights.push(0.0)
|
||||
}
|
||||
|
||||
source1 = sources[0]
|
||||
source2 = sources[1]
|
||||
source3 = sources[2]
|
||||
source4 = sources[3]
|
||||
source5 = sources[4]
|
||||
source6 = sources[5]
|
||||
|
||||
weight1 = weights[0]
|
||||
weight2 = weights[1]
|
||||
weight3 = weights[2]
|
||||
weight4 = weights[3]
|
||||
weight5 = weights[4]
|
||||
weight6 = weights[5]
|
||||
}
|
||||
|
||||
Component.onCompleted: calculateWeights()
|
||||
|
||||
onLodChanged: calculateWeights()
|
||||
|
||||
fragmentShader: "qrc:/QtQuick/Controls/Shaders/glow.frag"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,67 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Controls.Private 1.0
|
||||
|
||||
/*!
|
||||
\qmltype FocusFrame
|
||||
\internal
|
||||
\inqmlmodule QtQuick.Controls.Private
|
||||
*/
|
||||
Item {
|
||||
id: root
|
||||
activeFocusOnTab: false
|
||||
Accessible.role: Accessible.StatusBar
|
||||
|
||||
anchors.topMargin: focusMargin
|
||||
anchors.leftMargin: focusMargin
|
||||
anchors.rightMargin: focusMargin
|
||||
anchors.bottomMargin: focusMargin
|
||||
|
||||
property int focusMargin: loader.item ? loader.item.margin : -3
|
||||
|
||||
Loader {
|
||||
id: loader
|
||||
z: 2
|
||||
anchors.fill: parent
|
||||
sourceComponent: Settings.styleComponent(Settings.style, "FocusFrameStyle.qml", root)
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,79 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Controls.Private 1.0
|
||||
|
||||
Item {
|
||||
id: button
|
||||
property alias source: image.source
|
||||
signal clicked
|
||||
|
||||
Rectangle {
|
||||
id: fillRect
|
||||
anchors.fill: parent
|
||||
color: "black"
|
||||
opacity: mouse.pressed ? 0.07 : mouse.containsMouse ? 0.02 : 0.0
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
border.color: gridColor
|
||||
anchors.fill: parent
|
||||
anchors.margins: -1
|
||||
color: "transparent"
|
||||
opacity: fillRect.opacity * 10
|
||||
}
|
||||
|
||||
Image {
|
||||
id: image
|
||||
width: Math.min(implicitWidth, parent.width * 0.4)
|
||||
height: Math.min(implicitHeight, parent.height * 0.4)
|
||||
anchors.centerIn: parent
|
||||
fillMode: Image.PreserveAspectFit
|
||||
opacity: 0.6
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouse
|
||||
anchors.fill: parent
|
||||
onClicked: button.clicked()
|
||||
hoverEnabled: Settings.hoverEnabled
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,282 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQml 2.14 as Qml
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Controls.Styles 1.1
|
||||
import QtQuick.Controls.Private 1.0
|
||||
|
||||
Loader {
|
||||
id: menuFrameLoader
|
||||
|
||||
property var __menu
|
||||
|
||||
Accessible.role: Accessible.PopupMenu
|
||||
|
||||
visible: status === Loader.Ready
|
||||
width: content.width + (d.style ? d.style.padding.left + d.style.padding.right : 0)
|
||||
height: content.height + (d.style ? d.style.padding.top + d.style.padding.bottom : 0)
|
||||
|
||||
Loader {
|
||||
id: styleLoader
|
||||
active: !__menu.isNative
|
||||
sourceComponent: __menu.style
|
||||
property alias __control: menuFrameLoader
|
||||
onStatusChanged: {
|
||||
if (status === Loader.Error)
|
||||
console.error("Failed to load Style for", __menu)
|
||||
}
|
||||
}
|
||||
sourceComponent: d.style ? d.style.frame : undefined
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
property var mnemonicsMap: ({})
|
||||
readonly property Style style: styleLoader.item
|
||||
readonly property Component menuItemPanel: style ? style.menuItemPanel : null
|
||||
|
||||
function canBeHovered(index) {
|
||||
var item = content.menuItemAt(index)
|
||||
if (item && item.visible && item.styleData.type !== MenuItemType.Separator && item.styleData.enabled) {
|
||||
__menu.__currentIndex = index
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function triggerCurrent() {
|
||||
var item = content.menuItemAt(__menu.__currentIndex)
|
||||
if (item)
|
||||
triggerAndDismiss(item)
|
||||
}
|
||||
|
||||
function triggerAndDismiss(item) {
|
||||
if (!item)
|
||||
return;
|
||||
if (item.styleData.type === MenuItemType.Separator)
|
||||
__menu.__dismissAndDestroy()
|
||||
else if (item.styleData.type === MenuItemType.Item)
|
||||
item.__menuItem.trigger()
|
||||
}
|
||||
}
|
||||
|
||||
focus: true
|
||||
|
||||
Keys.onPressed: {
|
||||
var item = null
|
||||
if (!(event.modifiers & Qt.AltModifier)
|
||||
&& (item = d.mnemonicsMap[event.text.toUpperCase()])) {
|
||||
if (item.styleData.type === MenuItemType.Menu) {
|
||||
__menu.__currentIndex = item.__menuItemIndex
|
||||
item.__showSubMenu(true)
|
||||
item.__menuItem.__currentIndex = 0
|
||||
} else {
|
||||
d.triggerAndDismiss(item)
|
||||
}
|
||||
event.accepted = true
|
||||
} else {
|
||||
event.accepted = false
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onEscapePressed: __menu.__dismissAndDestroy()
|
||||
|
||||
Keys.onDownPressed: {
|
||||
if (__menu.__currentIndex < 0)
|
||||
__menu.__currentIndex = -1
|
||||
|
||||
for (var i = __menu.__currentIndex + 1;
|
||||
i < __menu.items.length && !d.canBeHovered(i); i++)
|
||||
;
|
||||
event.accepted = true
|
||||
}
|
||||
|
||||
Keys.onUpPressed: {
|
||||
for (var i = __menu.__currentIndex - 1;
|
||||
i >= 0 && !d.canBeHovered(i); i--)
|
||||
;
|
||||
event.accepted = true
|
||||
}
|
||||
|
||||
Keys.onLeftPressed: {
|
||||
if ((event.accepted = __menu.__parentMenu.hasOwnProperty("title")))
|
||||
__menu.__closeAndDestroy()
|
||||
}
|
||||
|
||||
Keys.onRightPressed: {
|
||||
var item = content.menuItemAt(__menu.__currentIndex)
|
||||
if (item && item.styleData.type === MenuItemType.Menu
|
||||
&& !item.__menuItem.__popupVisible) {
|
||||
item.__showSubMenu(true)
|
||||
item.__menuItem.__currentIndex = 0
|
||||
event.accepted = true
|
||||
} else {
|
||||
event.accepted = false
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onSpacePressed: d.triggerCurrent()
|
||||
Keys.onReturnPressed: d.triggerCurrent()
|
||||
Keys.onEnterPressed: d.triggerCurrent()
|
||||
|
||||
Qml.Binding {
|
||||
// Make sure the styled frame is in the background
|
||||
target: item
|
||||
property: "z"
|
||||
value: content.z - 1
|
||||
restoreMode: Binding.RestoreBinding
|
||||
}
|
||||
|
||||
ColumnMenuContent {
|
||||
id: content
|
||||
x: d.style ? d.style.padding.left : 0
|
||||
y: d.style ? d.style.padding.top : 0
|
||||
menuItemDelegate: menuItemComponent
|
||||
scrollIndicatorStyle: d.style && d.style.scrollIndicator || null
|
||||
scrollerStyle: d.style && d.style.__scrollerStyle
|
||||
itemsModel: __menu.items
|
||||
minWidth: __menu.__minimumWidth
|
||||
maxHeight: d.style ? d.style.__maxPopupHeight : 0
|
||||
onTriggered: d.triggerAndDismiss(item)
|
||||
}
|
||||
|
||||
Component {
|
||||
id: menuItemComponent
|
||||
Loader {
|
||||
id: menuItemLoader
|
||||
|
||||
Accessible.role: opts.type === MenuItemType.Item || opts.type === MenuItemType.Menu ?
|
||||
Accessible.MenuItem : Accessible.NoRole
|
||||
Accessible.name: StyleHelpers.removeMnemonics(opts.text)
|
||||
Accessible.checkable: opts.checkable
|
||||
Accessible.checked: opts.checked
|
||||
Accessible.onPressAction: {
|
||||
if (opts.type === MenuItemType.Item) {
|
||||
d.triggerAndDismiss(menuItemLoader)
|
||||
} else if (opts.type === MenuItemType.Menu) {
|
||||
__showSubMenu(true /*immediately*/)
|
||||
}
|
||||
}
|
||||
|
||||
property QtObject styleData: QtObject {
|
||||
id: opts
|
||||
readonly property int index: __menuItemIndex
|
||||
readonly property int type: __menuItem ? __menuItem.type : -1
|
||||
readonly property bool selected: type !== MenuItemType.Separator && __menu.__currentIndex === index
|
||||
readonly property bool pressed: type !== MenuItemType.Separator && __menu.__currentIndex === index
|
||||
&& content.mousePressed // TODO Add key pressed condition once we get delayed menu closing
|
||||
readonly property string text: type === MenuItemType.Menu ? __menuItem.title :
|
||||
type !== MenuItemType.Separator ? __menuItem.text : ""
|
||||
readonly property bool underlineMnemonic: __menu.__contentItem.altPressed
|
||||
readonly property string shortcut: !!__menuItem && __menuItem["shortcut"] || ""
|
||||
readonly property var iconSource: !!__menuItem && __menuItem["iconSource"] || undefined
|
||||
readonly property bool enabled: type !== MenuItemType.Separator && !!__menuItem && __menuItem.enabled
|
||||
readonly property bool checked: !!__menuItem && !!__menuItem["checked"]
|
||||
readonly property bool checkable: !!__menuItem && !!__menuItem["checkable"]
|
||||
readonly property bool exclusive: !!__menuItem && !!__menuItem["exclusiveGroup"]
|
||||
readonly property int scrollerDirection: Qt.NoArrow
|
||||
}
|
||||
|
||||
readonly property var __menuItem: modelData
|
||||
readonly property int __menuItemIndex: index
|
||||
|
||||
sourceComponent: d.menuItemPanel
|
||||
enabled: visible && opts.enabled
|
||||
visible: !!__menuItem && __menuItem.visible
|
||||
active: visible
|
||||
|
||||
function __showSubMenu(immediately) {
|
||||
if (!__menuItem.enabled)
|
||||
return;
|
||||
if (immediately) {
|
||||
if (__menu.__currentIndex === __menuItemIndex) {
|
||||
if (__menuItem.__usingDefaultStyle)
|
||||
__menuItem.style = __menu.style
|
||||
__menuItem.__popup(Qt.rect(menuFrameLoader.width - (d.style.submenuOverlap + d.style.padding.right), -d.style.padding.top, 0, 0), -1)
|
||||
}
|
||||
} else {
|
||||
openMenuTimer.start()
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: openMenuTimer
|
||||
interval: d.style.submenuPopupDelay
|
||||
onTriggered: menuItemLoader.__showSubMenu(true)
|
||||
}
|
||||
|
||||
function __closeSubMenu() {
|
||||
if (openMenuTimer.running)
|
||||
openMenuTimer.stop()
|
||||
else if (__menuItem.__popupVisible)
|
||||
closeMenuTimer.start()
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: closeMenuTimer
|
||||
interval: 1
|
||||
onTriggered: {
|
||||
if (__menu.__currentIndex !== __menuItemIndex)
|
||||
__menuItem.__closeAndDestroy()
|
||||
}
|
||||
}
|
||||
|
||||
onLoaded: {
|
||||
__menuItem.__visualItem = menuItemLoader
|
||||
|
||||
if (content.width < item.implicitWidth)
|
||||
content.width = item.implicitWidth
|
||||
|
||||
var title = opts.text
|
||||
var ampersandPos = title.indexOf("&")
|
||||
if (ampersandPos !== -1)
|
||||
d.mnemonicsMap[title[ampersandPos + 1].toUpperCase()] = menuItemLoader
|
||||
}
|
||||
|
||||
Qml.Binding {
|
||||
target: menuItemLoader.item
|
||||
property: "width"
|
||||
property alias menuItem: menuItemLoader.item
|
||||
value: menuItem ? Math.max(__menu.__minimumWidth, content.width) - 2 * menuItem.x : 0
|
||||
restoreMode: Binding.RestoreBinding
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,83 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Controls.Private 1.0
|
||||
|
||||
MouseArea {
|
||||
id: scrollIndicator
|
||||
property int direction: 0
|
||||
|
||||
anchors {
|
||||
top: direction === Qt.UpArrow ? parent.top : undefined
|
||||
bottom: direction === Qt.DownArrow ? parent.bottom : undefined
|
||||
}
|
||||
|
||||
hoverEnabled: visible && Settings.hoverEnabled
|
||||
height: scrollerLoader.height
|
||||
width: parent.width
|
||||
|
||||
Loader {
|
||||
id: scrollerLoader
|
||||
|
||||
width: parent.width
|
||||
sourceComponent: scrollIndicatorStyle
|
||||
// Extra property values for desktop style
|
||||
property var __menuItem: null
|
||||
property var styleData: {
|
||||
"index": -1,
|
||||
"type": MenuItemType.ScrollIndicator,
|
||||
"text": "",
|
||||
"selected": scrollIndicator.containsMouse,
|
||||
"scrollerDirection": scrollIndicator.direction,
|
||||
"checkable": false,
|
||||
"checked": false,
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
interval: 100
|
||||
repeat: true
|
||||
triggeredOnStart: true
|
||||
running: parent.containsMouse
|
||||
onTriggered: scrollABit()
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,48 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.2
|
||||
|
||||
QtObject {
|
||||
property Component background: null
|
||||
property Component label: null
|
||||
property Component submenuIndicator: null
|
||||
property Component shortcut: null
|
||||
property Component checkmarkIndicator: null
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,134 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.2
|
||||
|
||||
// KNOWN ISSUES
|
||||
// none
|
||||
|
||||
/*!
|
||||
\qmltype ModalPopupBehavior
|
||||
\internal
|
||||
\inqmlmodule QtQuick.Controls.Private
|
||||
*/
|
||||
Item {
|
||||
id: popupBehavior
|
||||
|
||||
property bool showing: false
|
||||
property bool whenAlso: true // modifier to the "showing" property
|
||||
property bool consumeCancelClick: true
|
||||
property int delay: 0 // delay before popout becomes visible
|
||||
property int deallocationDelay: 3000 // 3 seconds
|
||||
|
||||
property Component popupComponent
|
||||
|
||||
property alias popup: popupLoader.item // read-only
|
||||
property alias window: popupBehavior.root // read-only
|
||||
|
||||
signal prepareToShow
|
||||
signal prepareToHide
|
||||
signal cancelledByClick
|
||||
|
||||
// implementation
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
onShowingChanged: notifyChange()
|
||||
onWhenAlsoChanged: notifyChange()
|
||||
function notifyChange() {
|
||||
if(showing && whenAlso) {
|
||||
if(popupLoader.sourceComponent == undefined) {
|
||||
popupLoader.sourceComponent = popupComponent;
|
||||
}
|
||||
} else {
|
||||
mouseArea.enabled = false; // disable before opacity is changed in case it has fading behavior
|
||||
if(Qt.isQtObject(popupLoader.item)) {
|
||||
popupBehavior.prepareToHide();
|
||||
popupLoader.item.opacity = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
property Item root: findRoot()
|
||||
function findRoot() {
|
||||
var p = parent;
|
||||
while(p.parent != undefined)
|
||||
p = p.parent;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
enabled: false // enabled only when popout is showing
|
||||
onPressed: {
|
||||
popupBehavior.showing = false;
|
||||
mouse.accepted = consumeCancelClick;
|
||||
cancelledByClick();
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: popupLoader
|
||||
}
|
||||
|
||||
Timer { // visibility timer
|
||||
running: Qt.isQtObject(popupLoader.item) && showing && whenAlso
|
||||
interval: delay
|
||||
onTriggered: {
|
||||
popupBehavior.prepareToShow();
|
||||
mouseArea.enabled = true;
|
||||
popup.opacity = 1;
|
||||
}
|
||||
}
|
||||
|
||||
Timer { // deallocation timer
|
||||
running: Qt.isQtObject(popupLoader.item) && popupLoader.item.opacity == 0
|
||||
interval: deallocationDelay
|
||||
onTriggered: popupLoader.sourceComponent = undefined
|
||||
}
|
||||
|
||||
states: State {
|
||||
name: "active"
|
||||
when: Qt.isQtObject(popupLoader.item) && popupLoader.item.opacity > 0
|
||||
ParentChange { target: popupBehavior; parent: root }
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,237 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Controls.Private 1.0
|
||||
|
||||
/*!
|
||||
\qmltype ScrollBar
|
||||
\internal
|
||||
\inqmlmodule QtQuick.Controls.Private
|
||||
*/
|
||||
Item {
|
||||
id: scrollbar
|
||||
|
||||
property bool isTransient: false
|
||||
property bool active: false
|
||||
property int orientation: Qt.Horizontal
|
||||
property alias minimumValue: slider.minimumValue
|
||||
property alias maximumValue: slider.maximumValue
|
||||
property alias value: slider.value
|
||||
property int singleStep: 20
|
||||
|
||||
activeFocusOnTab: false
|
||||
|
||||
Accessible.role: Accessible.ScrollBar
|
||||
implicitWidth: panelLoader.implicitWidth
|
||||
implicitHeight: panelLoader.implicitHeight
|
||||
|
||||
property bool upPressed
|
||||
property bool downPressed
|
||||
property bool pageUpPressed
|
||||
property bool pageDownPressed
|
||||
property bool handlePressed
|
||||
|
||||
|
||||
property Item __panel: panelLoader.item
|
||||
Loader {
|
||||
id: panelLoader
|
||||
anchors.fill: parent
|
||||
sourceComponent: __style ? __style.__scrollbar : null
|
||||
onStatusChanged: if (status === Loader.Error) console.error("Failed to load Style for", root)
|
||||
property alias __control: scrollbar
|
||||
property QtObject __styleData: QtObject {
|
||||
readonly property alias horizontal: internal.horizontal
|
||||
readonly property alias upPressed: scrollbar.upPressed
|
||||
readonly property alias downPressed: scrollbar.downPressed
|
||||
readonly property alias handlePressed: scrollbar.handlePressed
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: internal
|
||||
property bool horizontal: orientation === Qt.Horizontal
|
||||
property int pageStep: internal.horizontal ? width : height
|
||||
property bool scrollToClickposition: internal.scrollToClickPosition
|
||||
anchors.fill: parent
|
||||
cursorShape: __panel && __panel.visible ? Qt.ArrowCursor : Qt.IBeamCursor // forces a cursor change
|
||||
|
||||
property bool autoincrement: false
|
||||
property bool scrollToClickPosition: __style ? __style.scrollToClickedPosition : 0
|
||||
|
||||
// Update hover item
|
||||
onEntered: if (!pressed) __panel.activeControl = __panel.hitTest(mouseX, mouseY)
|
||||
onExited: if (!pressed) __panel.activeControl = "none"
|
||||
onMouseXChanged: if (!pressed) __panel.activeControl = __panel.hitTest(mouseX, mouseY)
|
||||
hoverEnabled: Settings.hoverEnabled
|
||||
preventStealing: true
|
||||
property var pressedX
|
||||
property var pressedY
|
||||
property int oldPosition
|
||||
property int grooveSize
|
||||
|
||||
Timer {
|
||||
running: upPressed || downPressed || pageUpPressed || pageDownPressed
|
||||
interval: 350
|
||||
onTriggered: internal.autoincrement = true
|
||||
}
|
||||
|
||||
Timer {
|
||||
running: internal.autoincrement
|
||||
interval: 60
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (upPressed && internal.containsMouse)
|
||||
internal.decrement();
|
||||
else if (downPressed && internal.containsMouse)
|
||||
internal.increment();
|
||||
else if (pageUpPressed)
|
||||
internal.decrementPage();
|
||||
else if (pageDownPressed)
|
||||
internal.incrementPage();
|
||||
}
|
||||
}
|
||||
|
||||
onPositionChanged: {
|
||||
if (handlePressed) {
|
||||
if (!horizontal)
|
||||
slider.position = oldPosition + (mouseY - pressedY)
|
||||
else
|
||||
slider.position = oldPosition + (mouseX - pressedX)
|
||||
}
|
||||
}
|
||||
|
||||
onPressed: {
|
||||
if (mouse.source !== Qt.MouseEventNotSynthesized) {
|
||||
mouse.accepted = false
|
||||
return
|
||||
}
|
||||
__panel.activeControl = __panel.hitTest(mouseX, mouseY)
|
||||
scrollToClickposition = scrollToClickPosition
|
||||
var handleRect = __panel.subControlRect("handle")
|
||||
var grooveRect = __panel.subControlRect("groove")
|
||||
grooveSize = horizontal ? grooveRect.width - handleRect.width:
|
||||
grooveRect.height - handleRect.height;
|
||||
if (__panel.activeControl === "handle") {
|
||||
pressedX = mouseX;
|
||||
pressedY = mouseY;
|
||||
handlePressed = true;
|
||||
oldPosition = slider.position;
|
||||
} else if (__panel.activeControl === "up") {
|
||||
decrement();
|
||||
upPressed = Qt.binding(function() {return containsMouse});
|
||||
} else if (__panel.activeControl === "down") {
|
||||
increment();
|
||||
downPressed = Qt.binding(function() {return containsMouse});
|
||||
} else if (!scrollToClickposition){
|
||||
if (__panel.activeControl === "upPage") {
|
||||
decrementPage();
|
||||
pageUpPressed = true;
|
||||
} else if (__panel.activeControl === "downPage") {
|
||||
incrementPage();
|
||||
pageDownPressed = true;
|
||||
}
|
||||
} else { // scroll to click position
|
||||
slider.position = horizontal ? mouseX - handleRect.width/2 - grooveRect.x
|
||||
: mouseY - handleRect.height/2 - grooveRect.y
|
||||
pressedX = mouseX;
|
||||
pressedY = mouseY;
|
||||
handlePressed = true;
|
||||
oldPosition = slider.position;
|
||||
}
|
||||
}
|
||||
|
||||
onReleased: {
|
||||
__panel.activeControl = __panel.hitTest(mouseX, mouseY);
|
||||
autoincrement = false;
|
||||
upPressed = false;
|
||||
downPressed = false;
|
||||
handlePressed = false;
|
||||
pageUpPressed = false;
|
||||
pageDownPressed = false;
|
||||
}
|
||||
|
||||
onWheel: {
|
||||
var stepCount = -(wheel.angleDelta.x ? wheel.angleDelta.x : wheel.angleDelta.y) / 120
|
||||
if (stepCount != 0) {
|
||||
if (wheel.modifiers & Qt.ControlModifier || wheel.modifiers & Qt.ShiftModifier)
|
||||
incrementPage(stepCount)
|
||||
else
|
||||
increment(stepCount)
|
||||
}
|
||||
}
|
||||
|
||||
function incrementPage(stepCount) {
|
||||
value = boundValue(value + getSteps(pageStep, stepCount))
|
||||
}
|
||||
|
||||
function decrementPage(stepCount) {
|
||||
value = boundValue(value - getSteps(pageStep, stepCount))
|
||||
}
|
||||
|
||||
function increment(stepCount) {
|
||||
value = boundValue(value + getSteps(singleStep, stepCount))
|
||||
}
|
||||
|
||||
function decrement(stepCount) {
|
||||
value = boundValue(value - getSteps(singleStep, stepCount))
|
||||
}
|
||||
|
||||
function boundValue(val) {
|
||||
return Math.min(Math.max(val, minimumValue), maximumValue)
|
||||
}
|
||||
|
||||
function getSteps(step, count) {
|
||||
if (count)
|
||||
step *= count
|
||||
return step
|
||||
}
|
||||
|
||||
RangeModel {
|
||||
id: slider
|
||||
minimumValue: 0.0
|
||||
maximumValue: 1.0
|
||||
value: 0
|
||||
stepSize: 0.0
|
||||
inverted: false
|
||||
positionAtMaximum: internal.grooveSize
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,234 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQml 2.14 as Qml
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Controls.Private 1.0
|
||||
|
||||
/*!
|
||||
\qmltype ScrollViewHeader
|
||||
\internal
|
||||
\inqmlmodule QtQuick.Controls.Private
|
||||
*/
|
||||
Item {
|
||||
id: scrollHelper
|
||||
|
||||
property alias horizontalScrollBar: hscrollbar
|
||||
property alias verticalScrollBar: vscrollbar
|
||||
property bool blockUpdates: false
|
||||
property int availableHeight
|
||||
property int availableWidth
|
||||
property int contentHeight
|
||||
property int contentWidth
|
||||
property bool active
|
||||
property int horizontalScrollBarPolicy: Qt.ScrollBarAsNeeded
|
||||
property int verticalScrollBarPolicy: Qt.ScrollBarAsNeeded
|
||||
|
||||
|
||||
property int leftMargin: outerFrame && root.__style ? root.__style.padding.left : 0
|
||||
property int rightMargin: outerFrame && root.__style ? root.__style.padding.right : 0
|
||||
property int topMargin: outerFrame && root.__style ? root.__style.padding.top : 0
|
||||
property int bottomMargin: outerFrame && root.__style ? root.__style.padding.bottom : 0
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
Timer {
|
||||
id: layoutTimer
|
||||
interval: 0;
|
||||
onTriggered: {
|
||||
blockUpdates = true;
|
||||
scrollHelper.contentWidth = flickableItem !== null ? flickableItem.contentWidth : 0
|
||||
scrollHelper.contentHeight = flickableItem !== null ? flickableItem.contentHeight : 0
|
||||
scrollHelper.availableWidth = viewport.width
|
||||
scrollHelper.availableHeight = viewport.height
|
||||
blockUpdates = false;
|
||||
hscrollbar.valueChanged();
|
||||
vscrollbar.valueChanged();
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: viewport
|
||||
function onWidthChanged() { layoutTimer.running = true }
|
||||
function onHeightChanged() { layoutTimer.running = true }
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: flickableItem
|
||||
function onContentWidthChanged() { layoutTimer.running = true }
|
||||
function onContentHeightChanged() { layoutTimer.running = true }
|
||||
function onContentXChanged() {
|
||||
hscrollbar.flash()
|
||||
vscrollbar.flash()
|
||||
}
|
||||
function onContentYChanged() {
|
||||
hscrollbar.flash()
|
||||
vscrollbar.flash()
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: cornerFill
|
||||
z: 1
|
||||
sourceComponent: __style ? __style.corner : null
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: bottomMargin
|
||||
anchors.rightMargin: rightMargin
|
||||
width: visible ? vscrollbar.width : 0
|
||||
height: visible ? hscrollbar.height : 0
|
||||
visible: hscrollbar.visible && !hscrollbar.isTransient && vscrollbar.visible && !vscrollbar.isTransient
|
||||
}
|
||||
|
||||
ScrollBar {
|
||||
id: hscrollbar
|
||||
readonly property int scrollAmount: contentWidth - availableWidth
|
||||
readonly property bool scrollable: scrollAmount > 0
|
||||
isTransient: !!__panel && !!__panel.isTransient
|
||||
active: !!__panel && (__panel.sunken || __panel.activeControl !== "none")
|
||||
enabled: !isTransient || __panel.visible
|
||||
orientation: Qt.Horizontal
|
||||
visible: horizontalScrollBarPolicy == Qt.ScrollBarAsNeeded ? scrollable : horizontalScrollBarPolicy == Qt.ScrollBarAlwaysOn
|
||||
height: visible ? implicitHeight : 0
|
||||
z: 1
|
||||
maximumValue: scrollable ? scrollAmount : 0
|
||||
minimumValue: 0
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: cornerFill.left
|
||||
anchors.leftMargin: leftMargin
|
||||
anchors.bottomMargin: bottomMargin
|
||||
onScrollAmountChanged: {
|
||||
var scrollableAmount = scrollable ? scrollAmount : 0
|
||||
if (flickableItem && (flickableItem.atXBeginning || flickableItem.atXEnd)) {
|
||||
value = Math.min(scrollableAmount, flickableItem.contentX - flickableItem.originX);
|
||||
} else if (value > scrollableAmount) {
|
||||
value = scrollableAmount;
|
||||
}
|
||||
}
|
||||
onValueChanged: {
|
||||
if (flickableItem && !blockUpdates) {
|
||||
flickableItem.contentX = value + flickableItem.originX
|
||||
}
|
||||
}
|
||||
Qml.Binding {
|
||||
target: hscrollbar.__panel
|
||||
property: "raised"
|
||||
value: vscrollbar.active || scrollHelper.active
|
||||
when: hscrollbar.isTransient
|
||||
restoreMode: Binding.RestoreBinding
|
||||
}
|
||||
Qml.Binding {
|
||||
target: hscrollbar.__panel
|
||||
property: "visible"
|
||||
value: true
|
||||
when: !hscrollbar.isTransient || scrollHelper.active
|
||||
restoreMode: Binding.RestoreBinding
|
||||
}
|
||||
function flash() {
|
||||
if (hscrollbar.isTransient) {
|
||||
hscrollbar.__panel.on = true
|
||||
hscrollbar.__panel.visible = true
|
||||
hFlasher.start()
|
||||
}
|
||||
}
|
||||
Timer {
|
||||
id: hFlasher
|
||||
interval: 10
|
||||
onTriggered: hscrollbar.__panel.on = false
|
||||
}
|
||||
}
|
||||
|
||||
ScrollBar {
|
||||
id: vscrollbar
|
||||
readonly property int scrollAmount: contentHeight - availableHeight
|
||||
readonly property bool scrollable: scrollAmount > 0
|
||||
isTransient: !!__panel && !!__panel.isTransient
|
||||
active: !!__panel && (__panel.sunken || __panel.activeControl !== "none")
|
||||
enabled: !isTransient || __panel.visible
|
||||
orientation: Qt.Vertical
|
||||
visible: verticalScrollBarPolicy === Qt.ScrollBarAsNeeded ? scrollable : verticalScrollBarPolicy === Qt.ScrollBarAlwaysOn
|
||||
width: visible ? implicitWidth : 0
|
||||
z: 1
|
||||
anchors.bottom: cornerFill.top
|
||||
maximumValue: scrollable ? scrollAmount + __viewTopMargin : 0
|
||||
minimumValue: 0
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: __scrollBarTopMargin + topMargin
|
||||
anchors.rightMargin: rightMargin
|
||||
onScrollAmountChanged: {
|
||||
if (flickableItem && (flickableItem.atYBeginning || flickableItem.atYEnd)) {
|
||||
value = flickableItem.contentY - flickableItem.originY
|
||||
}
|
||||
}
|
||||
onValueChanged: {
|
||||
if (flickableItem && !blockUpdates && enabled) {
|
||||
flickableItem.contentY = value + flickableItem.originY
|
||||
}
|
||||
}
|
||||
Qml.Binding {
|
||||
target: vscrollbar.__panel
|
||||
property: "raised"
|
||||
value: hscrollbar.active || scrollHelper.active
|
||||
when: vscrollbar.isTransient
|
||||
restoreMode: Binding.RestoreBinding
|
||||
}
|
||||
Qml.Binding {
|
||||
target: vscrollbar.__panel
|
||||
property: "visible"
|
||||
value: true
|
||||
when: !vscrollbar.isTransient || scrollHelper.active
|
||||
restoreMode: Binding.RestoreBinding
|
||||
}
|
||||
function flash() {
|
||||
if (vscrollbar.isTransient) {
|
||||
vscrollbar.__panel.on = true
|
||||
vscrollbar.__panel.visible = true
|
||||
vFlasher.start()
|
||||
}
|
||||
}
|
||||
Timer {
|
||||
id: vFlasher
|
||||
interval: 10
|
||||
onTriggered: vscrollbar.__panel.on = false
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,136 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.2
|
||||
|
||||
Item {
|
||||
id: rootItem
|
||||
property variant input
|
||||
property variant output
|
||||
property variant sourceRect
|
||||
visible: false
|
||||
|
||||
Component.onCompleted: evaluateInput()
|
||||
|
||||
onInputChanged: evaluateInput()
|
||||
|
||||
onSourceRectChanged: evaluateInput()
|
||||
|
||||
function evaluateInput() {
|
||||
if (input == undefined) {
|
||||
output = input
|
||||
}
|
||||
else if (sourceRect != undefined && sourceRect != Qt.rect(0, 0, 0, 0) && !isQQuickShaderEffectSource(input)) {
|
||||
proxySource.sourceItem = input
|
||||
output = proxySource
|
||||
proxySource.sourceRect = sourceRect
|
||||
}
|
||||
else if (isQQuickItemLayerEnabled(input)) {
|
||||
output = input
|
||||
}
|
||||
else if ((isQQuickImage(input) && !hasTileMode(input) && !hasChildren(input))) {
|
||||
output = input
|
||||
}
|
||||
else if (isQQuickShaderEffectSource(input)) {
|
||||
output = input
|
||||
}
|
||||
else {
|
||||
proxySource.sourceItem = input
|
||||
output = proxySource
|
||||
proxySource.sourceRect = Qt.rect(0, 0, 0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
function isQQuickItemLayerEnabled(item) {
|
||||
if (item.hasOwnProperty("layer")) {
|
||||
var l = item["layer"]
|
||||
if (l.hasOwnProperty("enabled") && l["enabled"].toString() == "true")
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function isQQuickImage(item) {
|
||||
var imageProperties = [ "fillMode", "progress", "asynchronous", "sourceSize", "status", "smooth" ]
|
||||
return hasProperties(item, imageProperties)
|
||||
}
|
||||
|
||||
function isQQuickShaderEffectSource(item) {
|
||||
var shaderEffectSourceProperties = [ "hideSource", "format", "sourceItem", "mipmap", "wrapMode", "live", "recursive", "sourceRect" ]
|
||||
return hasProperties(item, shaderEffectSourceProperties)
|
||||
}
|
||||
|
||||
function hasProperties(item, properties) {
|
||||
var counter = 0
|
||||
for (var j = 0; j < properties.length; j++) {
|
||||
if (item.hasOwnProperty(properties [j]))
|
||||
counter++
|
||||
}
|
||||
return properties.length == counter
|
||||
}
|
||||
|
||||
function hasChildren(item) {
|
||||
if (item.hasOwnProperty("childrenRect")) {
|
||||
if (item["childrenRect"].toString() != "QRectF(0, 0, 0, 0)")
|
||||
return true
|
||||
else
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function hasTileMode(item) {
|
||||
if (item.hasOwnProperty("fillMode")) {
|
||||
if (item["fillMode"].toString() != "0")
|
||||
return true
|
||||
else
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
ShaderEffectSource {
|
||||
id: proxySource
|
||||
live: rootItem.input != rootItem.output
|
||||
hideSource: false
|
||||
smooth: true
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,66 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
var stackView = [];
|
||||
|
||||
function push(p)
|
||||
{
|
||||
if (!p)
|
||||
return
|
||||
stackView.push(p)
|
||||
__depth++
|
||||
return p
|
||||
}
|
||||
|
||||
function pop()
|
||||
{
|
||||
if (stackView.length === 0)
|
||||
return null
|
||||
var p = stackView.pop()
|
||||
__depth--
|
||||
return p
|
||||
}
|
||||
|
||||
function current()
|
||||
{
|
||||
if (stackView.length === 0)
|
||||
return null
|
||||
return stackView[stackView.length-1]
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,141 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
|
||||
/*!
|
||||
\qmltype StackViewSlideTransition
|
||||
\internal
|
||||
\inqmlmodule QtQuick.Controls.Private
|
||||
*/
|
||||
StackViewDelegate {
|
||||
id: root
|
||||
|
||||
property bool horizontal: true
|
||||
|
||||
function getTransition(properties)
|
||||
{
|
||||
return root[horizontal ? "horizontalSlide" : "verticalSlide"][properties.name]
|
||||
}
|
||||
|
||||
function transitionFinished(properties)
|
||||
{
|
||||
properties.exitItem.x = 0
|
||||
properties.exitItem.y = 0
|
||||
}
|
||||
|
||||
property QtObject horizontalSlide: QtObject {
|
||||
property Component pushTransition: StackViewTransition {
|
||||
PropertyAnimation {
|
||||
target: enterItem
|
||||
property: "x"
|
||||
from: target.width
|
||||
to: 0
|
||||
duration: 400
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
PropertyAnimation {
|
||||
target: exitItem
|
||||
property: "x"
|
||||
from: 0
|
||||
to: -target.width
|
||||
duration: 400
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
|
||||
property Component popTransition: StackViewTransition {
|
||||
PropertyAnimation {
|
||||
target: enterItem
|
||||
property: "x"
|
||||
from: -target.width
|
||||
to: 0
|
||||
duration: 400
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
PropertyAnimation {
|
||||
target: exitItem
|
||||
property: "x"
|
||||
from: 0
|
||||
to: target.width
|
||||
duration: 400
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
property Component replaceTransition: pushTransition
|
||||
}
|
||||
|
||||
property QtObject verticalSlide: QtObject {
|
||||
property Component pushTransition: StackViewTransition {
|
||||
PropertyAnimation {
|
||||
target: enterItem
|
||||
property: "y"
|
||||
from: target.height
|
||||
to: 0
|
||||
duration: 300
|
||||
}
|
||||
PropertyAnimation {
|
||||
target: exitItem
|
||||
property: "y"
|
||||
from: 0
|
||||
to: -target.height
|
||||
duration: 300
|
||||
}
|
||||
}
|
||||
|
||||
property Component popTransition: StackViewTransition {
|
||||
PropertyAnimation {
|
||||
target: enterItem
|
||||
property: "y"
|
||||
from: -target.height
|
||||
to: 0
|
||||
duration: 300
|
||||
}
|
||||
PropertyAnimation {
|
||||
target: exitItem
|
||||
property: "y"
|
||||
from: 0
|
||||
to: target.height
|
||||
duration: 300
|
||||
}
|
||||
}
|
||||
property Component replaceTransition: pushTransition
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,53 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Controls.Private 1.0
|
||||
|
||||
/*!
|
||||
\qmltype Style
|
||||
\internal
|
||||
\inqmlmodule QtQuick.Controls.Private
|
||||
*/
|
||||
|
||||
AbstractStyle {
|
||||
/*! The control this style is attached to. */
|
||||
readonly property Item control: __control
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,61 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
pragma Singleton
|
||||
import QtQuick 2.2
|
||||
|
||||
QtObject {
|
||||
property SystemPalette active: SystemPalette { colorGroup: SystemPalette.Active }
|
||||
property SystemPalette disabled: SystemPalette { colorGroup: SystemPalette.Disabled }
|
||||
|
||||
function alternateBase(enabled) { return enabled ? active.alternateBase : disabled.alternateBase }
|
||||
function base(enabled) { return enabled ? active.base : disabled.base }
|
||||
function button(enabled) { return enabled ? active.button : disabled.button }
|
||||
function buttonText(enabled) { return enabled ? active.buttonText : disabled.buttonText }
|
||||
function dark(enabled) { return enabled ? active.dark : disabled.dark }
|
||||
function highlight(enabled) { return enabled ? active.highlight : disabled.highlight }
|
||||
function highlightedText(enabled) { return enabled ? active.highlightedText : disabled.highlightedText }
|
||||
function light(enabled) { return enabled ? active.light : disabled.light }
|
||||
function mid(enabled) { return enabled ? active.mid : disabled.mid }
|
||||
function midlight(enabled) { return enabled ? active.midlight : disabled.midlight }
|
||||
function shadow(enabled) { return enabled ? active.shadow : disabled.shadow }
|
||||
function text(enabled) { return enabled ? active.text : disabled.text }
|
||||
function window(enabled) { return enabled ? active.window : disabled.window }
|
||||
function windowText(enabled) { return enabled ? active.windowText : disabled.windowText }
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,331 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQml 2.14 as Qml
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Controls.Private 1.0
|
||||
|
||||
/*!
|
||||
\qmltype TabBar
|
||||
\internal
|
||||
\inqmlmodule QtQuick.Controls.Private
|
||||
*/
|
||||
FocusScope {
|
||||
id: tabbar
|
||||
height: Math.max(tabrow.height, Math.max(leftCorner.height, rightCorner.height))
|
||||
width: tabView.width
|
||||
|
||||
activeFocusOnTab: true
|
||||
|
||||
Keys.onRightPressed: {
|
||||
if (tabView && tabView.currentIndex < tabView.count - 1)
|
||||
tabView.currentIndex = tabView.currentIndex + 1
|
||||
}
|
||||
Keys.onLeftPressed: {
|
||||
if (tabView && tabView.currentIndex > 0)
|
||||
tabView.currentIndex = tabView.currentIndex - 1
|
||||
}
|
||||
|
||||
onTabViewChanged: parent = tabView
|
||||
visible: tabView ? tabView.tabsVisible : true
|
||||
|
||||
property var tabView
|
||||
property var style
|
||||
property var styleItem: tabView.__styleItem ? tabView.__styleItem : null
|
||||
|
||||
property bool tabsMovable: styleItem ? styleItem.tabsMovable : false
|
||||
|
||||
property int tabsAlignment: styleItem ? styleItem.tabsAlignment : Qt.AlignLeft
|
||||
|
||||
property int tabOverlap: styleItem ? styleItem.tabOverlap : 0
|
||||
|
||||
property int elide: Text.ElideRight
|
||||
|
||||
property real availableWidth: tabbar.width - leftCorner.width - rightCorner.width
|
||||
|
||||
property var __selectedTabRect
|
||||
|
||||
function tab(index) {
|
||||
for (var i = 0; i < tabrow.children.length; ++i) {
|
||||
if (tabrow.children[i].tabindex == index) {
|
||||
return tabrow.children[i]
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/*! \internal */
|
||||
function __isAncestorOf(item, child) {
|
||||
//TODO: maybe removed from 5.2 if the function was merged in qtdeclarative
|
||||
if (child === item)
|
||||
return false;
|
||||
|
||||
while (child) {
|
||||
child = child.parent;
|
||||
if (child === item)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Loader {
|
||||
id: background
|
||||
anchors.fill: parent
|
||||
sourceComponent: styleItem ? styleItem.tabBar : undefined
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: tabrow
|
||||
objectName: "tabrow"
|
||||
Accessible.role: Accessible.PageTabList
|
||||
LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft
|
||||
spacing: -tabOverlap
|
||||
orientation: Qt.Horizontal
|
||||
interactive: false
|
||||
focus: true
|
||||
clip: true
|
||||
|
||||
// Note this will silence the binding loop warnings caused by QTBUG-35038
|
||||
// and should be removed when this issue is resolved.
|
||||
property int contentWidthWorkaround: contentWidth > 0 ? contentWidth: 0
|
||||
width: Math.min(availableWidth, count ? contentWidthWorkaround : availableWidth)
|
||||
height: currentItem ? currentItem.height : 0
|
||||
|
||||
highlightMoveDuration: 0
|
||||
|
||||
// We cannot bind directly to the currentIndex because the actual model is
|
||||
// populated after the listview is completed, resulting in an invalid contentItem
|
||||
currentIndex: tabView.currentIndex < model.count ? tabView.currentIndex : -1
|
||||
onCurrentIndexChanged: tabrow.positionViewAtIndex(currentIndex, ListView.Contain)
|
||||
|
||||
moveDisplaced: Transition {
|
||||
NumberAnimation {
|
||||
property: "x"
|
||||
duration: 125
|
||||
easing.type: Easing.OutQuad
|
||||
}
|
||||
}
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "left"
|
||||
when: tabsAlignment === Qt.AlignLeft
|
||||
AnchorChanges { target:tabrow ; anchors.left: parent.left }
|
||||
PropertyChanges { target:tabrow ; anchors.leftMargin: leftCorner.width }
|
||||
},
|
||||
State {
|
||||
name: "center"
|
||||
when: tabsAlignment === Qt.AlignHCenter
|
||||
AnchorChanges { target:tabrow ; anchors.horizontalCenter: tabbar.horizontalCenter }
|
||||
},
|
||||
State {
|
||||
name: "right"
|
||||
when: tabsAlignment === Qt.AlignRight
|
||||
AnchorChanges { target:tabrow ; anchors.right: parent.right }
|
||||
PropertyChanges { target:tabrow ; anchors.rightMargin: rightCorner.width }
|
||||
}
|
||||
]
|
||||
|
||||
model: tabView.__tabs
|
||||
|
||||
delegate: MouseArea {
|
||||
id: tabitem
|
||||
objectName: "mousearea"
|
||||
hoverEnabled: Settings.hoverEnabled
|
||||
focus: true
|
||||
enabled: modelData.enabled
|
||||
|
||||
Qml.Binding {
|
||||
target: tabbar
|
||||
when: selected
|
||||
property: "__selectedTabRect"
|
||||
value: Qt.rect(x, y, width, height)
|
||||
restoreMode: Binding.RestoreBinding
|
||||
}
|
||||
|
||||
drag.target: tabsMovable ? tabloader : null
|
||||
drag.axis: Drag.XAxis
|
||||
drag.minimumX: drag.active ? 0 : -Number.MAX_VALUE
|
||||
drag.maximumX: tabrow.width - tabitem.width
|
||||
|
||||
property int tabindex: index
|
||||
property bool selected : tabView.currentIndex === index
|
||||
property string title: modelData.title
|
||||
property bool nextSelected: tabView.currentIndex === index + 1
|
||||
property bool previousSelected: tabView.currentIndex === index - 1
|
||||
|
||||
property bool keyPressed: false
|
||||
property bool effectivePressed: pressed && containsMouse || keyPressed
|
||||
|
||||
z: selected ? 1 : -index
|
||||
implicitWidth: tabloader.implicitWidth
|
||||
implicitHeight: tabloader.implicitHeight
|
||||
|
||||
function changeTab() {
|
||||
tabView.currentIndex = index;
|
||||
var next = tabbar.nextItemInFocusChain(true);
|
||||
if (__isAncestorOf(tabView.getTab(currentIndex), next))
|
||||
next.forceActiveFocus();
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
if (tabrow.interactive) {
|
||||
changeTab()
|
||||
}
|
||||
}
|
||||
onPressed: {
|
||||
if (!tabrow.interactive) {
|
||||
changeTab()
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
if (event.key === Qt.Key_Space && !event.isAutoRepeat && !tabitem.pressed)
|
||||
tabitem.keyPressed = true
|
||||
}
|
||||
Keys.onReleased: {
|
||||
if (event.key === Qt.Key_Space && !event.isAutoRepeat && tabitem.keyPressed)
|
||||
tabitem.keyPressed = false
|
||||
}
|
||||
onFocusChanged: if (!focus) tabitem.keyPressed = false
|
||||
|
||||
Loader {
|
||||
id: tabloader
|
||||
|
||||
property Item control: tabView
|
||||
property int index: tabindex
|
||||
|
||||
property QtObject styleData: QtObject {
|
||||
readonly property alias index: tabitem.tabindex
|
||||
readonly property alias selected: tabitem.selected
|
||||
readonly property alias title: tabitem.title
|
||||
readonly property alias nextSelected: tabitem.nextSelected
|
||||
readonly property alias previousSelected: tabitem.previousSelected
|
||||
readonly property alias pressed: tabitem.effectivePressed
|
||||
readonly property alias hovered: tabitem.containsMouse
|
||||
readonly property alias enabled: tabitem.enabled
|
||||
readonly property bool activeFocus: tabitem.activeFocus
|
||||
readonly property real availableWidth: tabbar.availableWidth
|
||||
readonly property real totalWidth: tabrow.contentWidth
|
||||
}
|
||||
|
||||
sourceComponent: loader.item ? loader.item.tab : null
|
||||
|
||||
Drag.keys: "application/x-tabbartab"
|
||||
Drag.active: tabitem.drag.active
|
||||
Drag.source: tabitem
|
||||
|
||||
property real __prevX: 0
|
||||
property real __dragX: 0
|
||||
onXChanged: {
|
||||
if (Drag.active) {
|
||||
// keep track for the snap back animation
|
||||
__dragX = tabitem.mapFromItem(tabrow, tabloader.x, 0).x
|
||||
|
||||
// when moving to the left, the hot spot is the left edge and vice versa
|
||||
Drag.hotSpot.x = x < __prevX ? 0 : width
|
||||
__prevX = x
|
||||
}
|
||||
}
|
||||
|
||||
width: tabitem.width
|
||||
state: Drag.active ? "drag" : ""
|
||||
|
||||
transitions: [
|
||||
Transition {
|
||||
to: "drag"
|
||||
PropertyAction { target: tabloader; property: "parent"; value: tabrow }
|
||||
},
|
||||
Transition {
|
||||
from: "drag"
|
||||
SequentialAnimation {
|
||||
PropertyAction { target: tabloader; property: "parent"; value: tabitem }
|
||||
NumberAnimation {
|
||||
target: tabloader
|
||||
duration: 50
|
||||
easing.type: Easing.OutQuad
|
||||
property: "x"
|
||||
from: tabloader.__dragX
|
||||
to: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Accessible.role: Accessible.PageTab
|
||||
Accessible.name: modelData.title
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: leftCorner
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
sourceComponent: styleItem ? styleItem.leftCorner : undefined
|
||||
width: item ? item.implicitWidth : 0
|
||||
height: item ? item.implicitHeight : 0
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: rightCorner
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
sourceComponent: styleItem ? styleItem.rightCorner : undefined
|
||||
width: item ? item.implicitWidth : 0
|
||||
height: item ? item.implicitHeight : 0
|
||||
}
|
||||
|
||||
DropArea {
|
||||
anchors.fill: tabrow
|
||||
keys: "application/x-tabbartab"
|
||||
onPositionChanged: {
|
||||
var source = drag.source
|
||||
var target = tabrow.itemAt(drag.x, drag.y)
|
||||
if (source && target && source !== target) {
|
||||
source = source.drag.target
|
||||
target = target.drag.target
|
||||
var center = target.parent.x + target.width / 2
|
||||
if ((source.index > target.index && source.x < center)
|
||||
|| (source.index < target.index && source.x + source.width > center))
|
||||
tabView.moveTab(source.index, target.index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,102 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
|
||||
/*!
|
||||
\qmltype TableViewItemDelegateLoader
|
||||
\internal
|
||||
\qmlabstract
|
||||
\inqmlmodule QtQuick.Controls.Private
|
||||
*/
|
||||
|
||||
Loader {
|
||||
id: itemDelegateLoader
|
||||
|
||||
width: __column ? __column.width : 0
|
||||
height: parent ? parent.height : 0
|
||||
visible: __column ? __column.visible : false
|
||||
|
||||
property bool isValid: false
|
||||
sourceComponent: (__model === undefined || !isValid) ? null
|
||||
: __column && __column.delegate ? __column.delegate : __itemDelegate
|
||||
|
||||
// All these properties are internal
|
||||
property int __index: index
|
||||
property Item __rowItem: null
|
||||
property var __model: __rowItem ? __rowItem.itemModel : undefined
|
||||
property var __modelData: __rowItem ? __rowItem.itemModelData : undefined
|
||||
property TableViewColumn __column: null
|
||||
property Component __itemDelegate: null
|
||||
property var __mouseArea: null
|
||||
property var __style: null
|
||||
|
||||
// These properties are exposed to the item delegate
|
||||
readonly property var model: __model
|
||||
readonly property var modelData: __modelData
|
||||
|
||||
property QtObject styleData: QtObject {
|
||||
readonly property int row: __rowItem ? __rowItem.rowIndex : -1
|
||||
readonly property int column: __index
|
||||
readonly property int elideMode: __column ? __column.elideMode : Text.ElideLeft
|
||||
readonly property int textAlignment: __column ? __column.horizontalAlignment : Text.AlignLeft
|
||||
readonly property bool selected: __rowItem ? __rowItem.itemSelected : false
|
||||
readonly property bool hasActiveFocus: __rowItem ? __rowItem.activeFocus : false
|
||||
readonly property bool pressed: __mouseArea && row === __mouseArea.pressedRow && column === __mouseArea.pressedColumn
|
||||
readonly property color textColor: __rowItem ? __rowItem.itemTextColor : "black"
|
||||
readonly property string role: __column ? __column.role : ""
|
||||
readonly property var value: model && model.hasOwnProperty(role) ? model[role] // Qml ListModel and QAbstractItemModel
|
||||
: modelData && modelData.hasOwnProperty(role) ? modelData[role] // QObjectList / QObject
|
||||
: modelData != undefined ? modelData : "" // Models without role
|
||||
onRowChanged: if (row !== -1) itemDelegateLoader.isValid = true
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,196 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.2
|
||||
|
||||
QtObject {
|
||||
|
||||
property int count: 0
|
||||
signal selectionChanged
|
||||
|
||||
property bool __dirty: false
|
||||
property var __ranges: []
|
||||
|
||||
function forEach (callback) {
|
||||
if (!(callback instanceof Function)) {
|
||||
console.warn("TableViewSelection.forEach: argument is not a function")
|
||||
return;
|
||||
}
|
||||
__forEach(callback, -1)
|
||||
}
|
||||
|
||||
function contains(index) {
|
||||
for (var i = 0 ; i < __ranges.length ; ++i) {
|
||||
if (__ranges[i][0] <= index && index <= __ranges[i][1])
|
||||
return true;
|
||||
else if (__ranges[i][0] > index)
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function clear() {
|
||||
__ranges = []
|
||||
__dirty = true
|
||||
count = 0
|
||||
selectionChanged()
|
||||
}
|
||||
|
||||
function selectAll() { select(0, rowCount - 1) }
|
||||
function select(first, last) { __select(true, first, last) }
|
||||
function deselect(first, last) { __select(false, first, last) }
|
||||
|
||||
// --- private section ---
|
||||
|
||||
function __printRanges() {
|
||||
var out = ""
|
||||
for (var i = 0 ; i < __ranges.length ; ++ i)
|
||||
out += ("{" + __ranges[i][0] + "," + __ranges[i][1] + "} ")
|
||||
print(out)
|
||||
}
|
||||
|
||||
function __count() {
|
||||
var sum = 0
|
||||
for (var i = 0 ; i < __ranges.length ; ++i) {
|
||||
sum += (1 + __ranges[i][1] - __ranges[i][0])
|
||||
}
|
||||
return sum
|
||||
}
|
||||
|
||||
function __forEach (callback, startIndex) {
|
||||
__dirty = false
|
||||
var i, j
|
||||
|
||||
for (i = 0 ; i < __ranges.length && !__dirty ; ++i) {
|
||||
for (j = __ranges[i][0] ; !__dirty && j <= __ranges[i][1] ; ++j) {
|
||||
if (j >= startIndex)
|
||||
callback.call(this, j)
|
||||
}
|
||||
}
|
||||
|
||||
// Restart iteration at last index if selection changed
|
||||
if (__dirty)
|
||||
return __forEach(callback, j)
|
||||
}
|
||||
|
||||
function __selectOne(index) {
|
||||
__ranges = [[index, index]]
|
||||
__dirty = true
|
||||
count = 1
|
||||
selectionChanged();
|
||||
}
|
||||
|
||||
function __select(select, first, last) {
|
||||
|
||||
var i, range
|
||||
var start = first
|
||||
var stop = first
|
||||
var startRangeIndex = -1
|
||||
var stopRangeIndex = -1
|
||||
var newRangePos = 0
|
||||
|
||||
if (first < 0 || last < 0 || first >= rowCount || last >=rowCount) {
|
||||
console.warn("TableViewSelection: index out of range")
|
||||
return
|
||||
}
|
||||
|
||||
if (last !== undefined) {
|
||||
start = first <= last ? first : last
|
||||
stop = first <= last ? last : first
|
||||
}
|
||||
|
||||
if (select) {
|
||||
|
||||
// Find beginning and end ranges
|
||||
for (i = 0 ; i < __ranges.length; ++ i) {
|
||||
range = __ranges[i]
|
||||
if (range[0] > stop + 1) continue; // above range
|
||||
if (range[1] < start - 1) { // below range
|
||||
newRangePos = i + 1
|
||||
continue;
|
||||
}
|
||||
if (startRangeIndex === -1)
|
||||
startRangeIndex = i
|
||||
stopRangeIndex = i
|
||||
}
|
||||
|
||||
if (startRangeIndex !== -1)
|
||||
start = Math.min(__ranges[startRangeIndex][0], start)
|
||||
if (stopRangeIndex !== -1)
|
||||
stop = Math.max(__ranges[stopRangeIndex][1], stop)
|
||||
|
||||
if (startRangeIndex === -1)
|
||||
startRangeIndex = newRangePos
|
||||
|
||||
__ranges.splice(Math.max(0, startRangeIndex),
|
||||
1 + stopRangeIndex - startRangeIndex, [start, stop])
|
||||
|
||||
} else {
|
||||
|
||||
// Find beginning and end ranges
|
||||
for (i = 0 ; i < __ranges.length; ++ i) {
|
||||
range = __ranges[i]
|
||||
if (range[1] < start) continue; // below range
|
||||
if (range[0] > stop) continue; // above range
|
||||
if (startRangeIndex === -1)
|
||||
startRangeIndex = i
|
||||
stopRangeIndex = i
|
||||
}
|
||||
|
||||
// Slice ranges accordingly
|
||||
if (startRangeIndex >= 0 && stopRangeIndex >= 0) {
|
||||
var startRange = __ranges[startRangeIndex]
|
||||
var stopRange = __ranges[stopRangeIndex]
|
||||
var length = 1 + stopRangeIndex - startRangeIndex
|
||||
if (start <= startRange[0] && stop >= stopRange[1]) { //remove
|
||||
__ranges.splice(startRangeIndex, length)
|
||||
} else if (start - 1 < startRange[0] && stop <= stopRange[1]) { //cut front
|
||||
__ranges.splice(startRangeIndex, length, [stop + 1, stopRange[1]])
|
||||
} else if (start - 1 < startRange[1] && stop >= stopRange[1]) { // cut back
|
||||
__ranges.splice(startRangeIndex, length, [startRange[0], start - 1])
|
||||
} else { //split
|
||||
__ranges.splice(startRangeIndex, length, [startRange[0], start - 1], [stop + 1, stopRange[1]])
|
||||
}
|
||||
}
|
||||
}
|
||||
__dirty = true
|
||||
count = __count() // forces a re-evaluation of indexes in the delegates
|
||||
selectionChanged()
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,126 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Controls.Private 1.0
|
||||
|
||||
Loader {
|
||||
id: handle
|
||||
|
||||
property Item editor
|
||||
property int minimum: -1
|
||||
property int maximum: -1
|
||||
property int position: -1
|
||||
property alias delegate: handle.sourceComponent
|
||||
|
||||
readonly property alias pressed: mouse.pressed
|
||||
|
||||
readonly property real handleX: x + (item ? item.x : 0)
|
||||
readonly property real handleY: y + (item ? item.y : 0)
|
||||
readonly property real handleWidth: item ? item.width : 0
|
||||
readonly property real handleHeight: item ? item.height : 0
|
||||
|
||||
property Item control
|
||||
property QtObject styleData: QtObject {
|
||||
id: styleData
|
||||
signal activated()
|
||||
readonly property alias pressed: mouse.pressed
|
||||
readonly property alias position: handle.position
|
||||
readonly property bool hasSelection: editor.selectionStart !== editor.selectionEnd
|
||||
readonly property real lineHeight: position !== -1 ? editor.positionToRectangle(position).height
|
||||
: editor.cursorRectangle.height
|
||||
}
|
||||
|
||||
function activate() {
|
||||
styleData.activated()
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouse
|
||||
anchors.fill: item
|
||||
enabled: item && item.visible
|
||||
preventStealing: true
|
||||
property real pressX
|
||||
property point offset
|
||||
property bool handleDragged: false
|
||||
|
||||
onPressed: {
|
||||
Qt.inputMethod.commit()
|
||||
handleDragged = false
|
||||
pressX = mouse.x
|
||||
var handleRect = editor.positionToRectangle(handle.position)
|
||||
var centerX = handleRect.x + (handleRect.width / 2)
|
||||
var centerY = handleRect.y + (handleRect.height / 2)
|
||||
var center = mapFromItem(editor, centerX, centerY)
|
||||
offset = Qt.point(mouseX - center.x, mouseY - center.y)
|
||||
}
|
||||
onReleased: {
|
||||
if (!handleDragged) {
|
||||
// The user just clicked on the handle. In that
|
||||
// case clear the selection.
|
||||
var mousePos = editor.mapFromItem(item, mouse.x, mouse.y)
|
||||
var editorPos = editor.positionAt(mousePos.x, mousePos.y)
|
||||
editor.select(editorPos, editorPos)
|
||||
}
|
||||
}
|
||||
onPositionChanged: {
|
||||
handleDragged = true
|
||||
var pt = mapToItem(editor, mouse.x - offset.x, mouse.y - offset.y)
|
||||
|
||||
// limit vertically within mix/max coordinates or content bounds
|
||||
var min = (minimum !== -1) ? minimum : 0
|
||||
var max = (maximum !== -1) ? maximum : editor.length
|
||||
pt.y = Math.max(pt.y, editor.positionToRectangle(min).y)
|
||||
pt.y = Math.min(pt.y, editor.positionToRectangle(max).y)
|
||||
|
||||
var pos = editor.positionAt(pt.x, pt.y)
|
||||
|
||||
// limit horizontally within min/max character positions
|
||||
if (minimum !== -1)
|
||||
pos = Math.max(pos, minimum)
|
||||
pos = Math.max(pos, 0)
|
||||
if (maximum !== -1)
|
||||
pos = Math.min(pos, maximum)
|
||||
pos = Math.min(pos, editor.length)
|
||||
|
||||
handle.position = pos
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,201 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Window 2.2
|
||||
import QtQuick.Controls.Private 1.0
|
||||
|
||||
TextInput {
|
||||
id: input
|
||||
|
||||
property Item control
|
||||
property alias cursorHandle: cursorHandle.delegate
|
||||
property alias selectionHandle: selectionHandle.delegate
|
||||
|
||||
property bool blockRecursion: false
|
||||
property bool hasSelection: selectionStart !== selectionEnd
|
||||
readonly property int selectionPosition: selectionStart !== cursorPosition ? selectionStart : selectionEnd
|
||||
readonly property alias containsMouse: mouseArea.containsMouse
|
||||
property alias editMenu: editMenu
|
||||
cursorDelegate: __style && __style.__cursorDelegate ? __style.__cursorDelegate : null
|
||||
|
||||
selectByMouse: control.selectByMouse && (!Settings.isMobile || !cursorHandle.delegate || !selectionHandle.delegate)
|
||||
|
||||
// force re-evaluation when selection moves:
|
||||
// - cursorRectangle changes => content scrolled
|
||||
// - contentWidth changes => text layout changed
|
||||
property rect selectionRectangle: cursorRectangle.x && contentWidth ? positionToRectangle(selectionPosition)
|
||||
: positionToRectangle(selectionPosition)
|
||||
|
||||
onSelectionStartChanged: syncHandlesWithSelection()
|
||||
onCursorPositionChanged: syncHandlesWithSelection()
|
||||
|
||||
function syncHandlesWithSelection()
|
||||
{
|
||||
if (!blockRecursion && selectionHandle.delegate) {
|
||||
blockRecursion = true
|
||||
// We cannot use property selectionPosition since it gets updated after onSelectionStartChanged
|
||||
cursorHandle.position = cursorPosition
|
||||
selectionHandle.position = (selectionStart !== cursorPosition) ? selectionStart : selectionEnd
|
||||
blockRecursion = false
|
||||
}
|
||||
}
|
||||
|
||||
function activate() {
|
||||
if (activeFocusOnPress) {
|
||||
forceActiveFocus()
|
||||
if (!readOnly)
|
||||
Qt.inputMethod.show()
|
||||
}
|
||||
cursorHandle.activate()
|
||||
selectionHandle.activate()
|
||||
}
|
||||
|
||||
function moveHandles(cursor, selection) {
|
||||
blockRecursion = true
|
||||
cursorPosition = cursor
|
||||
if (selection === -1) {
|
||||
selectWord()
|
||||
selection = selectionStart
|
||||
}
|
||||
selectionHandle.position = selection
|
||||
cursorHandle.position = cursorPosition
|
||||
blockRecursion = false
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: Settings.hoverEnabled
|
||||
cursorShape: Qt.IBeamCursor
|
||||
acceptedButtons: (input.selectByMouse ? Qt.NoButton : Qt.LeftButton) | (control.menu ? Qt.RightButton : Qt.NoButton)
|
||||
onClicked: {
|
||||
if (editMenu.item)
|
||||
return;
|
||||
var pos = input.positionAt(mouse.x, mouse.y)
|
||||
input.moveHandles(pos, pos)
|
||||
input.activate()
|
||||
}
|
||||
onPressAndHold: {
|
||||
if (editMenu.item)
|
||||
return;
|
||||
var pos = input.positionAt(mouse.x, mouse.y)
|
||||
input.moveHandles(pos, control.selectByMouse ? -1 : pos)
|
||||
input.activate()
|
||||
}
|
||||
}
|
||||
|
||||
EditMenu {
|
||||
id: editMenu
|
||||
input: parent
|
||||
mouseArea: mouseArea
|
||||
control: parent.control
|
||||
cursorHandle: cursorHandle
|
||||
selectionHandle: selectionHandle
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
ScenePosListener {
|
||||
id: listener
|
||||
item: input
|
||||
enabled: input.activeFocus && Qt.platform.os !== "ios" && Settings.isMobile
|
||||
}
|
||||
|
||||
TextHandle {
|
||||
id: selectionHandle
|
||||
|
||||
editor: input
|
||||
z: 1000001 // DefaultWindowDecoration+1
|
||||
parent: !input.activeFocus || Qt.platform.os === "ios" ? control : Window.contentItem // float (QTBUG-42538)
|
||||
control: input.control
|
||||
active: control.selectByMouse && Settings.isMobile
|
||||
maximum: cursorHandle.position - 1
|
||||
|
||||
readonly property var mappedOrigin: editor.mapToItem(parent, 0,0)
|
||||
|
||||
// Mention scenePos in the mappedPos binding to force re-evaluation if it changes
|
||||
readonly property var mappedPos: listener.scenePos.x !== listener.scenePos.y !== Number.MAX_VALUE ?
|
||||
editor.mapToItem(parent, editor.selectionRectangle.x, editor.selectionRectangle.y) : -1
|
||||
x: mappedPos.x
|
||||
y: mappedPos.y
|
||||
|
||||
visible: pressed || (input.hasSelection && handleX + handleWidth >= -1 && handleX - mappedOrigin.x <= control.width + 1)
|
||||
|
||||
onPositionChanged: {
|
||||
if (!input.blockRecursion) {
|
||||
input.blockRecursion = true
|
||||
input.select(selectionHandle.position, cursorHandle.position)
|
||||
if (pressed)
|
||||
input.ensureVisible(position)
|
||||
input.blockRecursion = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TextHandle {
|
||||
id: cursorHandle
|
||||
|
||||
editor: input
|
||||
z: 1000001 // DefaultWindowDecoration+1
|
||||
parent: !input.activeFocus || Qt.platform.os === "ios" ? control : Window.contentItem // float (QTBUG-42538)
|
||||
control: input.control
|
||||
active: control.selectByMouse && Settings.isMobile
|
||||
minimum: input.hasSelection ? selectionHandle.position + 1 : -1
|
||||
|
||||
readonly property var mappedOrigin: editor.mapToItem(parent, 0,0)
|
||||
|
||||
// Mention scenePos in the mappedPos binding to force re-evaluation if it changes
|
||||
readonly property var mappedPos: listener.scenePos.x !== listener.scenePos.y !== Number.MAX_VALUE ?
|
||||
editor.mapToItem(parent, editor.cursorRectangle.x, editor.cursorRectangle.y) : -1
|
||||
x: mappedPos.x
|
||||
y: mappedPos.y
|
||||
|
||||
visible: pressed || ((input.cursorVisible || input.hasSelection) && handleX + handleWidth >= -1 && handleX - mappedOrigin.x <= control.width + 1)
|
||||
|
||||
onPositionChanged: {
|
||||
if (!input.blockRecursion) {
|
||||
input.blockRecursion = true
|
||||
if (!input.hasSelection)
|
||||
selectionHandle.position = cursorHandle.position
|
||||
input.select(selectionHandle.position, cursorHandle.position)
|
||||
input.blockRecursion = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,43 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
pragma Singleton
|
||||
import QtQuick 2.2
|
||||
Text {
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,127 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQml 2.14 as Qml
|
||||
import QtQuick 2.4
|
||||
import QtQuick.Controls 1.3
|
||||
import QtQuick.Controls.Private 1.0
|
||||
|
||||
FocusScope {
|
||||
id: button
|
||||
|
||||
property Menu menu
|
||||
readonly property bool pressed: behavior.containsPress || behavior.keyPressed
|
||||
readonly property alias hovered: behavior.containsMouse
|
||||
|
||||
property alias panel: loader.sourceComponent
|
||||
property alias __panel: loader.item
|
||||
|
||||
activeFocusOnTab: true
|
||||
Accessible.role: Accessible.Button
|
||||
implicitWidth: __panel ? __panel.implicitWidth : 0
|
||||
implicitHeight: __panel ? __panel.implicitHeight : 0
|
||||
|
||||
Loader {
|
||||
id: loader
|
||||
anchors.fill: parent
|
||||
property QtObject styleData: QtObject {
|
||||
readonly property alias pressed: button.pressed
|
||||
readonly property alias hovered: button.hovered
|
||||
readonly property alias activeFocus: button.activeFocus
|
||||
}
|
||||
onStatusChanged: if (status === Loader.Error) console.error("Failed to load Style for", button)
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
if (event.key === Qt.Key_Space && !event.isAutoRepeat && !behavior.keyPressed)
|
||||
behavior.keyPressed = true
|
||||
}
|
||||
Keys.onReleased: {
|
||||
if (event.key === Qt.Key_Space && !event.isAutoRepeat && behavior.keyPressed)
|
||||
behavior.keyPressed = false
|
||||
}
|
||||
onFocusChanged: {
|
||||
if (!focus)
|
||||
behavior.keyPressed = false
|
||||
}
|
||||
onPressedChanged: {
|
||||
if (!Settings.hasTouchScreen && !pressed && menu)
|
||||
popupMenuTimer.start()
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: behavior
|
||||
property bool keyPressed: false
|
||||
|
||||
anchors.fill: parent
|
||||
enabled: !keyPressed
|
||||
hoverEnabled: Settings.hoverEnabled
|
||||
|
||||
onReleased: {
|
||||
if (Settings.hasTouchScreen && containsMouse && menu)
|
||||
popupMenuTimer.start()
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: popupMenuTimer
|
||||
interval: 10
|
||||
onTriggered: {
|
||||
behavior.keyPressed = false
|
||||
if (Qt.application.layoutDirection === Qt.RightToLeft)
|
||||
menu.__popup(Qt.rect(button.width, button.height, 0, 0), 0)
|
||||
else
|
||||
menu.__popup(Qt.rect(0, 0, button.width, button.height), 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Qml.Binding {
|
||||
target: menu
|
||||
property: "__minimumWidth"
|
||||
value: button.width
|
||||
restoreMode: Binding.RestoreBinding
|
||||
}
|
||||
|
||||
Qml.Binding {
|
||||
target: menu
|
||||
property: "__visualItem"
|
||||
value: button
|
||||
restoreMode: Binding.RestoreBinding
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,109 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import QtQuick.Controls.Private 1.0
|
||||
|
||||
/*!
|
||||
\qmltype TreeViewItemDelegateLoader
|
||||
\internal
|
||||
\qmlabstract
|
||||
\inqmlmodule QtQuick.Controls.Private
|
||||
*/
|
||||
|
||||
TableViewItemDelegateLoader {
|
||||
id: itemDelegateLoader
|
||||
|
||||
/* \internal */
|
||||
readonly property int __itemIndentation: __style && __index === 0
|
||||
? __style.__indentation * (styleData.depth + 1) : 0
|
||||
/* \internal */
|
||||
property TreeModelAdaptor __treeModel: null
|
||||
|
||||
// Exposed to the item delegate
|
||||
styleData: QtObject {
|
||||
readonly property int row: __rowItem ? __rowItem.rowIndex : -1
|
||||
readonly property int column: __index
|
||||
readonly property int elideMode: __column ? __column.elideMode : Text.ElideLeft
|
||||
readonly property int textAlignment: __column ? __column.horizontalAlignment : Text.AlignLeft
|
||||
readonly property bool selected: __rowItem ? __rowItem.itemSelected : false
|
||||
readonly property bool hasActiveFocus: __rowItem ? __rowItem.activeFocus : false
|
||||
readonly property bool pressed: __mouseArea && row === __mouseArea.pressedRow && column === __mouseArea.pressedColumn
|
||||
readonly property color textColor: __rowItem ? __rowItem.itemTextColor : "black"
|
||||
readonly property string role: __column ? __column.role : ""
|
||||
readonly property var value: model && model.hasOwnProperty(role) ? model[role] : ""
|
||||
readonly property var index: model ? model["_q_TreeView_ModelIndex"] : __treeModel.index(-1,-1)
|
||||
readonly property int depth: model && column === 0 ? model["_q_TreeView_ItemDepth"] : 0
|
||||
readonly property bool hasChildren: model ? model["_q_TreeView_HasChildren"] : false
|
||||
readonly property bool hasSibling: model ? model["_q_TreeView_HasSibling"] : false
|
||||
readonly property bool isExpanded: model ? model["_q_TreeView_ItemExpanded"] : false
|
||||
}
|
||||
|
||||
onLoaded: {
|
||||
item.x = Qt.binding(function() { return __itemIndentation})
|
||||
item.width = Qt.binding(function() { return width - __itemIndentation })
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: branchDelegateLoader
|
||||
active: __model !== undefined
|
||||
&& __index === 0
|
||||
&& styleData.hasChildren
|
||||
visible: itemDelegateLoader.width > __itemIndentation
|
||||
sourceComponent: __style && __style.__branchDelegate || null
|
||||
anchors.right: parent.item ? parent.item.left : undefined
|
||||
anchors.rightMargin: __style.__indentation > width ? (__style.__indentation - width) / 2 : 0
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
property QtObject styleData: itemDelegateLoader.styleData
|
||||
onLoaded: if (__rowItem) __rowItem.branchDecoration = item
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,37 @@
|
||||
module QtQuick.Controls.Private
|
||||
AbstractCheckable 1.0 AbstractCheckable.qml
|
||||
CalendarHeaderModel 1.0 CalendarHeaderModel.qml
|
||||
Control 1.0 Control.qml
|
||||
CalendarUtils 1.0 CalendarUtils.js
|
||||
FocusFrame 1.0 FocusFrame.qml
|
||||
Margins 1.0 Margins.qml
|
||||
BasicButton 1.0 BasicButton.qml
|
||||
ScrollBar 1.0 ScrollBar.qml
|
||||
ScrollViewHelper 1.0 ScrollViewHelper.qml
|
||||
Style 1.0 Style.qml
|
||||
MenuItemSubControls 1.0 MenuItemSubControls.qml
|
||||
TabBar 1.0 TabBar.qml
|
||||
StackViewSlideDelegate 1.0 StackViewSlideDelegate.qml
|
||||
StyleHelpers 1.0 style.js
|
||||
JSArray 1.0 StackView.js
|
||||
TableViewSelection 1.0 TableViewSelection.qml
|
||||
FastGlow 1.0 FastGlow.qml
|
||||
SourceProxy 1.0 SourceProxy.qml
|
||||
GroupBoxStyle 1.0 ../Styles/Base/GroupBoxStyle.qml
|
||||
FocusFrameStyle 1.0 ../Styles/Base/FocusFrameStyle.qml
|
||||
ToolButtonStyle 1.0 ../Styles/Base/ToolButtonStyle.qml
|
||||
MenuContentItem 1.0 MenuContentItem.qml
|
||||
MenuContentScroller 1.0 MenuContentScroller.qml
|
||||
ColumnMenuContent 1.0 ColumnMenuContent.qml
|
||||
ContentItem 1.0 ContentItem.qml
|
||||
HoverButton 1.0 HoverButton.qml
|
||||
singleton SystemPaletteSingleton 1.0 SystemPaletteSingleton.qml
|
||||
singleton TextSingleton 1.0 TextSingleton.qml
|
||||
TextHandle 1.0 TextHandle.qml
|
||||
TextInputWithHandles 1.0 TextInputWithHandles.qml
|
||||
EditMenu 1.0 EditMenu.qml
|
||||
EditMenu_base 1.0 EditMenu_base.qml
|
||||
ToolMenuButton 1.0 ToolMenuButton.qml
|
||||
BasicTableView 1.0 BasicTableView.qml
|
||||
TableViewItemDelegateLoader 1.0 TableViewItemDelegateLoader.qml
|
||||
TreeViewItemDelegateLoader 1.0 TreeViewItemDelegateLoader.qml
|
||||
@@ -0,0 +1,62 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
.pragma library
|
||||
|
||||
function underlineAmpersands(match, p1, p2, p3) {
|
||||
if (p2 === "&")
|
||||
return p1.concat(p2, p3)
|
||||
return p1.concat("<u>", p2, "</u>", p3)
|
||||
}
|
||||
|
||||
function removeAmpersands(match, p1, p2, p3) {
|
||||
return p1.concat(p2, p3)
|
||||
}
|
||||
|
||||
function replaceAmpersands(text, replaceFunction) {
|
||||
return text.replace(/([^&]*)&(.)([^&]*)/g, replaceFunction)
|
||||
}
|
||||
|
||||
function stylizeMnemonics(text) {
|
||||
return replaceAmpersands(text, underlineAmpersands)
|
||||
}
|
||||
|
||||
function removeMnemonics(text) {
|
||||
return replaceAmpersands(text, removeAmpersands)
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,167 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Controls.Private 1.0
|
||||
|
||||
/*!
|
||||
\qmltype ProgressBar
|
||||
\inqmlmodule QtQuick.Controls
|
||||
\since 5.1
|
||||
\ingroup controls
|
||||
\brief A progress indicator.
|
||||
|
||||
\image progressbar.png
|
||||
|
||||
The ProgressBar is used to give an indication of the progress of an operation.
|
||||
\l value is updated regularly and must be between \l minimumValue and \l maximumValue.
|
||||
|
||||
\code
|
||||
Column {
|
||||
ProgressBar {
|
||||
value: 0.5
|
||||
}
|
||||
ProgressBar {
|
||||
indeterminate: true
|
||||
}
|
||||
}
|
||||
\endcode
|
||||
|
||||
You can create a custom appearance for a ProgressBar by
|
||||
assigning a \l {ProgressBarStyle}.
|
||||
*/
|
||||
|
||||
Control {
|
||||
id: progressbar
|
||||
|
||||
/*! This property holds the progress bar's current value.
|
||||
Attempting to change the current value to one outside the minimum-maximum
|
||||
range has no effect on the current value.
|
||||
|
||||
The default value is \c{0}.
|
||||
*/
|
||||
property real value: 0
|
||||
|
||||
/*! This property is the progress bar's minimum value.
|
||||
The \l value is clamped to this value.
|
||||
The default value is \c{0}.
|
||||
*/
|
||||
property real minimumValue: 0
|
||||
|
||||
/*! This property is the progress bar's maximum value.
|
||||
The \l value is clamped to this value.
|
||||
If maximumValue is smaller than \l minimumValue, \l minimumValue will be enforced.
|
||||
The default value is \c{1}.
|
||||
*/
|
||||
property real maximumValue: 1
|
||||
|
||||
/*! This property toggles indeterminate mode.
|
||||
When the actual progress is unknown, use this option.
|
||||
The progress bar will be animated as a busy indicator instead.
|
||||
The default value is \c false.
|
||||
*/
|
||||
property bool indeterminate: false
|
||||
|
||||
/*! \qmlproperty enumeration orientation
|
||||
|
||||
This property holds the orientation of the progress bar.
|
||||
|
||||
\list
|
||||
\li Qt.Horizontal - Horizontal orientation. (Default)
|
||||
\li Qt.Vertical - Vertical orientation.
|
||||
\endlist
|
||||
*/
|
||||
property int orientation: Qt.Horizontal
|
||||
|
||||
/*! \qmlproperty bool ProgressBar::hovered
|
||||
|
||||
This property indicates whether the control is being hovered.
|
||||
*/
|
||||
readonly property alias hovered: hoverArea.containsMouse
|
||||
|
||||
/*! \internal */
|
||||
style: Settings.styleComponent(Settings.style, "ProgressBarStyle.qml", progressbar)
|
||||
|
||||
/*! \internal */
|
||||
property bool __initialized: false
|
||||
/*! \internal */
|
||||
onMaximumValueChanged: setValue(value)
|
||||
/*! \internal */
|
||||
onMinimumValueChanged: setValue(value)
|
||||
/*! \internal */
|
||||
onValueChanged: if (__initialized) setValue(value)
|
||||
/*! \internal */
|
||||
Component.onCompleted: {
|
||||
__initialized = true;
|
||||
setValue(value)
|
||||
}
|
||||
|
||||
activeFocusOnTab: false
|
||||
|
||||
Accessible.role: Accessible.ProgressBar
|
||||
Accessible.name: value
|
||||
|
||||
implicitWidth:(__panel ? __panel.implicitWidth : 0)
|
||||
implicitHeight: (__panel ? __panel.implicitHeight: 0)
|
||||
|
||||
MouseArea {
|
||||
id: hoverArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: Settings.hoverEnabled
|
||||
}
|
||||
|
||||
/*! \internal */
|
||||
function setValue(v) {
|
||||
var newval = parseFloat(v)
|
||||
if (!isNaN(newval)) {
|
||||
// we give minimumValue priority over maximum if they are inconsistent
|
||||
if (newval > maximumValue) {
|
||||
if (maximumValue >= minimumValue)
|
||||
newval = maximumValue;
|
||||
else
|
||||
newval = minimumValue
|
||||
} else if (v < minimumValue) {
|
||||
newval = minimumValue
|
||||
}
|
||||
if (value !== newval)
|
||||
value = newval
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,99 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Controls.Private 1.0
|
||||
|
||||
/*!
|
||||
\qmltype RadioButton
|
||||
\inqmlmodule QtQuick.Controls
|
||||
\since 5.1
|
||||
\ingroup controls
|
||||
\brief A radio button with a text label.
|
||||
|
||||
\image radiobutton.png
|
||||
|
||||
A RadioButton is an option button that can be switched on (checked) or off
|
||||
(unchecked). Radio buttons typically present the user with a "one of many"
|
||||
choices. In a group of radio buttons, only one radio button can be
|
||||
checked at a time; if the user selects another button, the previously
|
||||
selected button is switched off.
|
||||
|
||||
\qml
|
||||
GroupBox {
|
||||
title: "Tab Position"
|
||||
|
||||
RowLayout {
|
||||
ExclusiveGroup { id: tabPositionGroup }
|
||||
RadioButton {
|
||||
text: "Top"
|
||||
checked: true
|
||||
exclusiveGroup: tabPositionGroup
|
||||
}
|
||||
RadioButton {
|
||||
text: "Bottom"
|
||||
exclusiveGroup: tabPositionGroup
|
||||
}
|
||||
}
|
||||
}
|
||||
\endqml
|
||||
|
||||
You can create a custom appearance for a RadioButton by
|
||||
assigning a \l {RadioButtonStyle}.
|
||||
*/
|
||||
|
||||
AbstractCheckable {
|
||||
id: radioButton
|
||||
|
||||
activeFocusOnTab: true
|
||||
|
||||
Accessible.name: text
|
||||
Accessible.role: Accessible.RadioButton
|
||||
|
||||
/*!
|
||||
The style that should be applied to the radio button. Custom style
|
||||
components can be created with:
|
||||
|
||||
\codeline Qt.createComponent("path/to/style.qml", radioButtonId);
|
||||
*/
|
||||
style: Settings.styleComponent(Settings.style, "RadioButtonStyle.qml", radioButton)
|
||||
|
||||
__cycleStatesHandler: function() { checked = !checked; }
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,374 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQml 2.14 as Qml
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Controls.Private 1.0
|
||||
import QtQuick.Controls.Styles 1.1
|
||||
|
||||
/*!
|
||||
\qmltype ScrollView
|
||||
\inqmlmodule QtQuick.Controls
|
||||
\since 5.1
|
||||
\ingroup views
|
||||
\ingroup controls
|
||||
\brief Provides a scrolling view within another Item.
|
||||
|
||||
\image scrollview.png
|
||||
|
||||
A ScrollView can be used either to replace a \l Flickable or decorate an
|
||||
existing \l Flickable. Depending on the platform, it will add scroll bars and
|
||||
a content frame.
|
||||
|
||||
Only one Item can be a direct child of the ScrollView and the child is implicitly anchored
|
||||
to fill the scroll view.
|
||||
|
||||
Example:
|
||||
\code
|
||||
ScrollView {
|
||||
Image { source: "largeImage.png" }
|
||||
}
|
||||
\endcode
|
||||
|
||||
In the previous example the Image item will implicitly get scroll behavior as if it was
|
||||
used within a \l Flickable. The width and height of the child item will be used to
|
||||
define the size of the content area.
|
||||
|
||||
Example:
|
||||
\code
|
||||
ScrollView {
|
||||
ListView {
|
||||
...
|
||||
}
|
||||
}
|
||||
\endcode
|
||||
|
||||
In this case the content size of the ScrollView will simply mirror that of its contained
|
||||
\l flickableItem.
|
||||
|
||||
You can create a custom appearance for a ScrollView by
|
||||
assigning a \l {ScrollViewStyle}.
|
||||
*/
|
||||
|
||||
FocusScope {
|
||||
id: root
|
||||
|
||||
implicitWidth: 240
|
||||
implicitHeight: 150
|
||||
|
||||
/*!
|
||||
This property tells the ScrollView if it should render
|
||||
a frame around its content.
|
||||
|
||||
The default value is \c false.
|
||||
*/
|
||||
property bool frameVisible: false
|
||||
|
||||
/*! \qmlproperty enumeration ScrollView::horizontalScrollBarPolicy
|
||||
\since QtQuick.Controls 1.3
|
||||
|
||||
This property holds the policy for showing the horizontal scrollbar.
|
||||
It can be any of the following values:
|
||||
\list
|
||||
\li Qt.ScrollBarAsNeeded
|
||||
\li Qt.ScrollBarAlwaysOff
|
||||
\li Qt.ScrollBarAlwaysOn
|
||||
\endlist
|
||||
|
||||
The default policy is \c Qt.ScrollBarAsNeeded.
|
||||
*/
|
||||
property alias horizontalScrollBarPolicy: scroller.horizontalScrollBarPolicy
|
||||
|
||||
/*! \qmlproperty enumeration ScrollView::verticalScrollBarPolicy
|
||||
\since QtQuick.Controls 1.3
|
||||
|
||||
This property holds the policy for showing the vertical scrollbar.
|
||||
It can be any of the following values:
|
||||
\list
|
||||
\li Qt.ScrollBarAsNeeded
|
||||
\li Qt.ScrollBarAlwaysOff
|
||||
\li Qt.ScrollBarAlwaysOn
|
||||
\endlist
|
||||
|
||||
The default policy is \c Qt.ScrollBarAsNeeded.
|
||||
*/
|
||||
property alias verticalScrollBarPolicy: scroller.verticalScrollBarPolicy
|
||||
|
||||
/*!
|
||||
This property controls if there should be a highlight
|
||||
around the frame when the ScrollView has input focus.
|
||||
|
||||
The default value is \c false.
|
||||
|
||||
\note This property is only applicable on some platforms, such
|
||||
as Mac OS.
|
||||
*/
|
||||
property bool highlightOnFocus: false
|
||||
|
||||
/*!
|
||||
\qmlproperty Item ScrollView::viewport
|
||||
|
||||
The viewport determines the current "window" on the contentItem.
|
||||
In other words, it clips it and the size of the viewport tells you
|
||||
how much of the content area is visible.
|
||||
*/
|
||||
property alias viewport: viewportItem
|
||||
|
||||
/*!
|
||||
\qmlproperty Item ScrollView::flickableItem
|
||||
|
||||
The flickableItem of the ScrollView. If the contentItem provided
|
||||
to the ScrollView is a Flickable, it will be the \l contentItem.
|
||||
*/
|
||||
readonly property alias flickableItem: internal.flickableItem
|
||||
|
||||
/*!
|
||||
The contentItem of the ScrollView. This is set by the user.
|
||||
|
||||
Note that the definition of contentItem is somewhat different to that
|
||||
of a Flickable, where the contentItem is implicitly created.
|
||||
*/
|
||||
default property Item contentItem
|
||||
|
||||
/*! \internal */
|
||||
property alias __scroller: scroller
|
||||
/*! \internal */
|
||||
property alias __verticalScrollbarOffset: scroller.verticalScrollbarOffset
|
||||
/*! \internal */
|
||||
property alias __wheelAreaScrollSpeed: wheelArea.scrollSpeed
|
||||
/*! \internal */
|
||||
property int __scrollBarTopMargin: 0
|
||||
/*! \internal */
|
||||
property int __viewTopMargin: 0
|
||||
/*! \internal */
|
||||
property alias __horizontalScrollBar: scroller.horizontalScrollBar
|
||||
/*! \internal */
|
||||
property alias __verticalScrollBar: scroller.verticalScrollBar
|
||||
/*! \qmlproperty Component ScrollView::style
|
||||
|
||||
The style Component for this control.
|
||||
\sa {Qt Quick Controls 1 Styles QML Types}
|
||||
|
||||
*/
|
||||
property Component style: Settings.styleComponent(Settings.style, "ScrollViewStyle.qml", root)
|
||||
|
||||
/*! \internal */
|
||||
property Style __style: styleLoader.item
|
||||
|
||||
activeFocusOnTab: false
|
||||
|
||||
onContentItemChanged: {
|
||||
|
||||
if (contentItem.hasOwnProperty("contentY") && // Check if flickable
|
||||
contentItem.hasOwnProperty("contentHeight")) {
|
||||
internal.flickableItem = contentItem // "Use content if it is a flickable
|
||||
internal.flickableItem.parent = viewportItem
|
||||
} else {
|
||||
internal.flickableItem = flickableComponent.createObject(viewportItem)
|
||||
contentItem.parent = internal.flickableItem.contentItem
|
||||
}
|
||||
internal.flickableItem.anchors.fill = viewportItem
|
||||
if (!Settings.hasTouchScreen)
|
||||
internal.flickableItem.interactive = false
|
||||
}
|
||||
|
||||
|
||||
children: Item {
|
||||
id: internal
|
||||
|
||||
property Flickable flickableItem
|
||||
|
||||
Loader {
|
||||
id: styleLoader
|
||||
sourceComponent: style
|
||||
onStatusChanged: {
|
||||
if (status === Loader.Error)
|
||||
console.error("Failed to load Style for", root)
|
||||
}
|
||||
property alias __control: root
|
||||
}
|
||||
|
||||
Qml.Binding {
|
||||
target: flickableItem
|
||||
property: "contentHeight"
|
||||
when: contentItem !== flickableItem
|
||||
value: contentItem ? contentItem.height : 0
|
||||
restoreMode: Binding.RestoreBinding
|
||||
}
|
||||
|
||||
Qml.Binding {
|
||||
target: flickableItem
|
||||
when: contentItem !== flickableItem
|
||||
property: "contentWidth"
|
||||
value: contentItem ? contentItem.width : 0
|
||||
restoreMode: Binding.RestoreBinding
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: flickableItem
|
||||
|
||||
function onContentYChanged() {
|
||||
scroller.blockUpdates = true
|
||||
scroller.verticalScrollBar.value = flickableItem.contentY - flickableItem.originY
|
||||
scroller.blockUpdates = false
|
||||
}
|
||||
|
||||
function onContentXChanged() {
|
||||
scroller.blockUpdates = true
|
||||
scroller.horizontalScrollBar.value = flickableItem.contentX - flickableItem.originX
|
||||
scroller.blockUpdates = false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
Component {
|
||||
id: flickableComponent
|
||||
Flickable {}
|
||||
}
|
||||
|
||||
WheelArea {
|
||||
id: wheelArea
|
||||
parent: flickableItem
|
||||
z: -1
|
||||
// ### Note this is needed due to broken mousewheel behavior in Flickable.
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
property int acceleration: 40
|
||||
property int flickThreshold: Settings.dragThreshold
|
||||
property real speedThreshold: 3
|
||||
property real ignored: 0.001 // ## flick() does not work with 0 yVelocity
|
||||
property int maxFlick: 400
|
||||
|
||||
property bool horizontalRecursionGuard: false
|
||||
property bool verticalRecursionGuard: false
|
||||
|
||||
horizontalMinimumValue: 0
|
||||
horizontalMaximumValue: flickableItem ? flickableItem.contentWidth - viewport.width : 0
|
||||
onHorizontalMaximumValueChanged: {
|
||||
wheelArea.horizontalRecursionGuard = true
|
||||
//if horizontalMaximumValue changed, horizontalValue may be actually synced with
|
||||
wheelArea.horizontalValue = flickableItem.contentX - flickableItem.originX;
|
||||
wheelArea.horizontalRecursionGuard = false
|
||||
}
|
||||
|
||||
verticalMinimumValue: 0
|
||||
verticalMaximumValue: flickableItem ? flickableItem.contentHeight - viewport.height + __viewTopMargin : 0
|
||||
onVerticalMaximumValueChanged: {
|
||||
wheelArea.verticalRecursionGuard = true
|
||||
//if verticalMaximumValue changed, verticalValue may be actually synced with
|
||||
wheelArea.verticalValue = flickableItem.contentY - flickableItem.originY;
|
||||
wheelArea.verticalRecursionGuard = false
|
||||
}
|
||||
|
||||
// The default scroll speed for typical angle-based mouse wheels. The value
|
||||
// comes originally from QTextEdit, which sets 20px steps by default, as well as
|
||||
// QQuickWheelArea.
|
||||
// TODO: centralize somewhere, QPlatformTheme?
|
||||
scrollSpeed: 20 * (__style && __style.__wheelScrollLines || 1)
|
||||
|
||||
Connections {
|
||||
target: flickableItem
|
||||
|
||||
function onContentYChanged() {
|
||||
wheelArea.verticalRecursionGuard = true
|
||||
wheelArea.verticalValue = flickableItem.contentY - flickableItem.originY
|
||||
wheelArea.verticalRecursionGuard = false
|
||||
}
|
||||
function onContentXChanged() {
|
||||
wheelArea.horizontalRecursionGuard = true
|
||||
wheelArea.horizontalValue = flickableItem.contentX - flickableItem.originX
|
||||
wheelArea.horizontalRecursionGuard = false
|
||||
}
|
||||
}
|
||||
|
||||
onVerticalValueChanged: {
|
||||
if (!verticalRecursionGuard) {
|
||||
var effectiveContentY = flickableItem.contentY - flickableItem.originY
|
||||
if (effectiveContentY < flickThreshold && verticalDelta > speedThreshold) {
|
||||
flickableItem.flick(ignored, Math.min(maxFlick, acceleration * verticalDelta))
|
||||
} else if (effectiveContentY > flickableItem.contentHeight - flickThreshold - viewport.height
|
||||
&& verticalDelta < -speedThreshold) {
|
||||
flickableItem.flick(ignored, Math.max(-maxFlick, acceleration * verticalDelta))
|
||||
} else {
|
||||
flickableItem.contentY = verticalValue + flickableItem.originY
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onHorizontalValueChanged: {
|
||||
if (!horizontalRecursionGuard)
|
||||
flickableItem.contentX = horizontalValue + flickableItem.originX
|
||||
}
|
||||
}
|
||||
|
||||
ScrollViewHelper {
|
||||
id: scroller
|
||||
anchors.fill: parent
|
||||
active: wheelArea.active
|
||||
property bool outerFrame: !frameVisible || !(__style ? __style.__externalScrollBars : 0)
|
||||
property int scrollBarSpacing: outerFrame ? 0 : (__style ? __style.__scrollBarSpacing : 0)
|
||||
property int verticalScrollbarOffset: verticalScrollBar.visible && !verticalScrollBar.isTransient ?
|
||||
verticalScrollBar.width + scrollBarSpacing : 0
|
||||
property int horizontalScrollbarOffset: horizontalScrollBar.visible && !horizontalScrollBar.isTransient ?
|
||||
horizontalScrollBar.height + scrollBarSpacing : 0
|
||||
Loader {
|
||||
id: frameLoader
|
||||
sourceComponent: __style ? __style.frame : null
|
||||
anchors.fill: parent
|
||||
anchors.rightMargin: scroller.outerFrame ? 0 : scroller.verticalScrollbarOffset
|
||||
anchors.bottomMargin: scroller.outerFrame ? 0 : scroller.horizontalScrollbarOffset
|
||||
}
|
||||
|
||||
Item {
|
||||
id: viewportItem
|
||||
anchors.fill: frameLoader
|
||||
anchors.topMargin: frameVisible ? __style.padding.top : 0
|
||||
anchors.leftMargin: frameVisible ? __style.padding.left : 0
|
||||
anchors.rightMargin: (frameVisible ? __style.padding.right : 0) + (scroller.outerFrame ? scroller.verticalScrollbarOffset : 0)
|
||||
anchors.bottomMargin: (frameVisible ? __style.padding.bottom : 0) + (scroller.outerFrame ? scroller.horizontalScrollbarOffset : 0)
|
||||
clip: true
|
||||
}
|
||||
}
|
||||
FocusFrame { visible: highlightOnFocus && root.activeFocus }
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,347 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQml 2.14 as Qml
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Controls.Private 1.0
|
||||
|
||||
/*!
|
||||
\qmltype Slider
|
||||
\inqmlmodule QtQuick.Controls
|
||||
\since 5.1
|
||||
\ingroup controls
|
||||
\brief Provides a vertical or horizontal slider control.
|
||||
|
||||
\image slider.png
|
||||
|
||||
The slider is the classic control for providing a bounded value. It lets
|
||||
the user move a slider handle along a horizontal or vertical groove
|
||||
and translates the handle's position into a value within the legal range.
|
||||
|
||||
\code
|
||||
Slider {
|
||||
value: 0.5
|
||||
}
|
||||
\endcode
|
||||
|
||||
The slider value is by default in the range [0, 1]. If integer values are
|
||||
needed, you can set the \l stepSize.
|
||||
|
||||
You can create a custom appearance for a Slider by
|
||||
assigning a \l {SliderStyle}.
|
||||
*/
|
||||
|
||||
Control {
|
||||
id: slider
|
||||
|
||||
/*!
|
||||
\qmlproperty enumeration Slider::orientation
|
||||
|
||||
This property holds the layout orientation of the slider.
|
||||
The default value is \c Qt.Horizontal.
|
||||
*/
|
||||
property int orientation: Qt.Horizontal
|
||||
|
||||
/*!
|
||||
\qmlproperty real Slider::minimumValue
|
||||
|
||||
This property holds the minimum value of the slider.
|
||||
The default value is \c{0.0}.
|
||||
*/
|
||||
property alias minimumValue: range.minimumValue
|
||||
|
||||
/*!
|
||||
\qmlproperty real Slider::maximumValue
|
||||
|
||||
This property holds the maximum value of the slider.
|
||||
The default value is \c{1.0}.
|
||||
*/
|
||||
property alias maximumValue: range.maximumValue
|
||||
|
||||
/*!
|
||||
\qmlproperty bool Slider::updateValueWhileDragging
|
||||
|
||||
This property indicates whether the current \l value should be updated while
|
||||
the user is moving the slider handle, or only when the button has been released.
|
||||
This property could for instance be modified if changing the slider value would turn
|
||||
out to be too time consuming.
|
||||
|
||||
The default value is \c true.
|
||||
*/
|
||||
property bool updateValueWhileDragging: true
|
||||
|
||||
/*!
|
||||
\qmlproperty bool Slider::pressed
|
||||
|
||||
This property indicates whether the slider handle is being pressed.
|
||||
*/
|
||||
readonly property alias pressed: mouseArea.pressed
|
||||
|
||||
/*!
|
||||
\qmlproperty bool Slider::hovered
|
||||
|
||||
This property indicates whether the slider handle is being hovered.
|
||||
*/
|
||||
readonly property alias hovered: mouseArea.handleHovered
|
||||
|
||||
/*!
|
||||
\qmlproperty real Slider::stepSize
|
||||
|
||||
This property indicates the slider step size.
|
||||
|
||||
A value of 0 indicates that the value of the slider operates in a
|
||||
continuous range between \l minimumValue and \l maximumValue.
|
||||
|
||||
Any non 0 value indicates a discrete stepSize. The following example
|
||||
will generate a slider with integer values in the range [0-5].
|
||||
|
||||
\qml
|
||||
Slider {
|
||||
maximumValue: 5.0
|
||||
stepSize: 1.0
|
||||
}
|
||||
\endqml
|
||||
|
||||
The default value is \c{0.0}.
|
||||
*/
|
||||
property alias stepSize: range.stepSize
|
||||
|
||||
/*!
|
||||
\qmlproperty real Slider::value
|
||||
|
||||
This property holds the current value of the slider.
|
||||
The default value is \c{0.0}.
|
||||
*/
|
||||
property alias value: range.value
|
||||
|
||||
/*!
|
||||
\qmlproperty bool Slider::activeFocusOnPress
|
||||
|
||||
This property indicates whether the slider should receive active focus when
|
||||
pressed.
|
||||
*/
|
||||
property bool activeFocusOnPress: false
|
||||
|
||||
/*!
|
||||
\qmlproperty bool Slider::tickmarksEnabled
|
||||
|
||||
This property indicates whether the slider should display tickmarks
|
||||
at step intervals. Tick mark spacing is calculated based on the
|
||||
\l stepSize property.
|
||||
|
||||
The default value is \c false.
|
||||
|
||||
\note This property may be ignored on some platforms when using the native style (e.g. Android).
|
||||
*/
|
||||
property bool tickmarksEnabled: false
|
||||
|
||||
/*!
|
||||
\qmlproperty bool Slider::wheelEnabled
|
||||
|
||||
This property determines whether the control handles wheel events.
|
||||
The default value is \c true.
|
||||
|
||||
\since QtQuick.Controls 1.6
|
||||
*/
|
||||
property alias wheelEnabled: wheelarea.enabled
|
||||
|
||||
/*! \internal */
|
||||
property bool __horizontal: orientation === Qt.Horizontal
|
||||
|
||||
/*! \internal
|
||||
The extra arguments positionAtMinimum and positionAtMaximum are there to force
|
||||
re-evaluation of the handle position when the constraints change (QTBUG-41255),
|
||||
and the same for range.minimumValue (QTBUG-51765) and range.maximumValue (QTBUG-63354).
|
||||
*/
|
||||
property real __handlePos: range.valueForPosition(__horizontal ? fakeHandle.x : fakeHandle.y,
|
||||
range.positionAtMinimum, range.positionAtMaximum, range.minimumValue, range.maximumValue)
|
||||
|
||||
activeFocusOnTab: true
|
||||
|
||||
Accessible.role: Accessible.Slider
|
||||
/*! \internal */
|
||||
function accessibleIncreaseAction() {
|
||||
range.increaseSingleStep()
|
||||
}
|
||||
/*! \internal */
|
||||
function accessibleDecreaseAction() {
|
||||
range.decreaseSingleStep()
|
||||
}
|
||||
|
||||
style: Settings.styleComponent(Settings.style, "SliderStyle.qml", slider)
|
||||
|
||||
Keys.onRightPressed: if (__horizontal) range.increaseSingleStep()
|
||||
Keys.onLeftPressed: if (__horizontal) range.decreaseSingleStep()
|
||||
Keys.onUpPressed: if (!__horizontal) range.increaseSingleStep()
|
||||
Keys.onDownPressed: if (!__horizontal) range.decreaseSingleStep()
|
||||
|
||||
RangeModel {
|
||||
id: range
|
||||
minimumValue: 0.0
|
||||
maximumValue: 1.0
|
||||
value: 0
|
||||
stepSize: 0.0
|
||||
inverted: __horizontal ? false : true
|
||||
|
||||
positionAtMinimum: 0
|
||||
positionAtMaximum: __horizontal ? slider.width - fakeHandle.width : slider.height - fakeHandle.height
|
||||
}
|
||||
|
||||
Item {
|
||||
id: fakeHandle
|
||||
anchors.verticalCenter: __horizontal ? parent.verticalCenter : undefined
|
||||
anchors.horizontalCenter: !__horizontal ? parent.horizontalCenter : undefined
|
||||
width: __panel.handleWidth
|
||||
height: __panel.handleHeight
|
||||
|
||||
function updatePos() {
|
||||
if (updateValueWhileDragging && !mouseArea.drag.active)
|
||||
range.position = __horizontal ? x : y
|
||||
}
|
||||
|
||||
onXChanged: updatePos();
|
||||
onYChanged: updatePos();
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: Settings.hoverEnabled
|
||||
property int clickOffset: 0
|
||||
property real pressX: 0
|
||||
property real pressY: 0
|
||||
property bool handleHovered: false
|
||||
|
||||
function clamp ( val ) {
|
||||
return Math.max(range.positionAtMinimum, Math.min(range.positionAtMaximum, val))
|
||||
}
|
||||
|
||||
function updateHandlePosition(mouse, force) {
|
||||
var pos, overThreshold
|
||||
if (__horizontal) {
|
||||
pos = clamp (mouse.x + clickOffset - fakeHandle.width/2)
|
||||
overThreshold = Math.abs(mouse.x - pressX) >= Settings.dragThreshold
|
||||
if (overThreshold)
|
||||
preventStealing = true
|
||||
if (overThreshold || force)
|
||||
fakeHandle.x = pos
|
||||
} else if (!__horizontal) {
|
||||
pos = clamp (mouse.y + clickOffset- fakeHandle.height/2)
|
||||
overThreshold = Math.abs(mouse.y - pressY) >= Settings.dragThreshold
|
||||
if (overThreshold)
|
||||
preventStealing = true
|
||||
if (overThreshold || force)
|
||||
fakeHandle.y = pos
|
||||
}
|
||||
}
|
||||
|
||||
onPositionChanged: {
|
||||
if (pressed)
|
||||
updateHandlePosition(mouse, !Settings.hasTouchScreen || preventStealing)
|
||||
|
||||
var point = mouseArea.mapToItem(fakeHandle, mouse.x, mouse.y)
|
||||
handleHovered = fakeHandle.contains(Qt.point(point.x, point.y))
|
||||
}
|
||||
|
||||
onPressed: {
|
||||
if (slider.activeFocusOnPress)
|
||||
slider.forceActiveFocus();
|
||||
|
||||
if (handleHovered) {
|
||||
var point = mouseArea.mapToItem(fakeHandle, mouse.x, mouse.y)
|
||||
clickOffset = __horizontal ? fakeHandle.width/2 - point.x : fakeHandle.height/2 - point.y
|
||||
}
|
||||
pressX = mouse.x
|
||||
pressY = mouse.y
|
||||
updateHandlePosition(mouse, !Settings.hasTouchScreen)
|
||||
}
|
||||
|
||||
onReleased: {
|
||||
updateHandlePosition(mouse, Settings.hasTouchScreen)
|
||||
// If we don't update while dragging, this is the only
|
||||
// moment that the range is updated.
|
||||
if (!slider.updateValueWhileDragging)
|
||||
range.position = __horizontal ? fakeHandle.x : fakeHandle.y;
|
||||
clickOffset = 0
|
||||
preventStealing = false
|
||||
}
|
||||
|
||||
onExited: handleHovered = false
|
||||
}
|
||||
|
||||
|
||||
// During the drag, we simply ignore the position set from the range, this
|
||||
// means that setting a value while dragging will not "interrupt" the
|
||||
// dragging activity.
|
||||
Qml.Binding {
|
||||
when: !mouseArea.drag.active
|
||||
target: fakeHandle
|
||||
property: __horizontal ? "x" : "y"
|
||||
value: range.position
|
||||
restoreMode: Binding.RestoreBinding
|
||||
}
|
||||
|
||||
WheelArea {
|
||||
id: wheelarea
|
||||
anchors.fill: parent
|
||||
verticalValue: slider.value
|
||||
horizontalValue: slider.value
|
||||
horizontalMinimumValue: slider.minimumValue
|
||||
horizontalMaximumValue: slider.maximumValue
|
||||
verticalMinimumValue: slider.minimumValue
|
||||
verticalMaximumValue: slider.maximumValue
|
||||
property real step: (slider.maximumValue - slider.minimumValue)/(range.positionAtMaximum - range.positionAtMinimum)
|
||||
|
||||
onVerticalWheelMoved: {
|
||||
if (verticalDelta !== 0) {
|
||||
var delta = Math.abs(verticalDelta)*step > stepSize ? verticalDelta*step : verticalDelta/Math.abs(verticalDelta)*stepSize
|
||||
range.position = range.positionForValue(value - delta * (inverted ? 1 : -1))
|
||||
}
|
||||
}
|
||||
|
||||
onHorizontalWheelMoved: {
|
||||
if (horizontalDelta !== 0) {
|
||||
var delta = Math.abs(horizontalDelta)*step > stepSize ? horizontalDelta*step : horizontalDelta/Math.abs(horizontalDelta)*stepSize
|
||||
range.position = range.positionForValue(value + delta * (inverted ? 1 : -1))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,397 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Controls.Private 1.0
|
||||
|
||||
/*!
|
||||
\qmltype SpinBox
|
||||
\inqmlmodule QtQuick.Controls
|
||||
\since 5.1
|
||||
\ingroup controls
|
||||
\brief Provides a spin box control.
|
||||
|
||||
\image spinbox.png
|
||||
|
||||
SpinBox allows the user to choose a value by clicking the up or down buttons, or by
|
||||
pressing up or down on the keyboard. The user can also type the value in manually.
|
||||
|
||||
By default the SpinBox provides discrete values in the range [0-99] with a \l stepSize of 1 and 0 \l decimals.
|
||||
|
||||
\code
|
||||
SpinBox {
|
||||
id: spinbox
|
||||
}
|
||||
\endcode
|
||||
|
||||
Note that if you require decimal values you will need to set the \l decimals to a non 0 value.
|
||||
|
||||
\code
|
||||
SpinBox {
|
||||
id: spinbox
|
||||
decimals: 2
|
||||
}
|
||||
\endcode
|
||||
|
||||
*/
|
||||
|
||||
Control {
|
||||
id: spinbox
|
||||
|
||||
/*!
|
||||
\qmlproperty real SpinBox::value
|
||||
|
||||
The value of this SpinBox, clamped to \l minimumValue and \l maximumValue.
|
||||
|
||||
The default value is \c{0.0}.
|
||||
*/
|
||||
property alias value: validator.value
|
||||
|
||||
/*!
|
||||
\qmlproperty real SpinBox::minimumValue
|
||||
|
||||
The minimum value of the SpinBox range.
|
||||
The \l value is clamped to this value.
|
||||
|
||||
The default value is \c{0.0}.
|
||||
*/
|
||||
property alias minimumValue: validator.minimumValue
|
||||
|
||||
/*!
|
||||
\qmlproperty real SpinBox::maximumValue
|
||||
|
||||
The maximum value of the SpinBox range.
|
||||
The \l value is clamped to this value. If maximumValue is smaller than
|
||||
\l minimumValue, \l minimumValue will be enforced.
|
||||
|
||||
The default value is \c{99}.
|
||||
*/
|
||||
property alias maximumValue: validator.maximumValue
|
||||
|
||||
/*! \qmlproperty real SpinBox::stepSize
|
||||
The amount by which the \l value is incremented/decremented when a
|
||||
spin button is pressed.
|
||||
|
||||
The default value is \c{1.0}.
|
||||
*/
|
||||
property alias stepSize: validator.stepSize
|
||||
|
||||
/*! \qmlproperty string SpinBox::suffix
|
||||
The suffix for the value. I.e "cm" */
|
||||
property alias suffix: validator.suffix
|
||||
|
||||
/*! \qmlproperty string SpinBox::prefix
|
||||
The prefix for the value. I.e "$" */
|
||||
property alias prefix: validator.prefix
|
||||
|
||||
/*! \qmlproperty int SpinBox::decimals
|
||||
This property indicates the amount of decimals.
|
||||
Note that if you enter more decimals than specified, they will
|
||||
be truncated to the specified amount of decimal places.
|
||||
The default value is \c{0}.
|
||||
*/
|
||||
property alias decimals: validator.decimals
|
||||
|
||||
/*! \qmlproperty font SpinBox::font
|
||||
|
||||
This property indicates the current font used by the SpinBox.
|
||||
*/
|
||||
property alias font: input.font
|
||||
|
||||
/*!
|
||||
\qmlproperty int SpinBox::cursorPosition
|
||||
\since QtQuick.Controls 1.5
|
||||
|
||||
This property holds the position of the cursor in the SpinBox.
|
||||
*/
|
||||
property alias cursorPosition: input.cursorPosition
|
||||
|
||||
|
||||
/*! This property indicates whether the Spinbox should get active
|
||||
focus when pressed.
|
||||
The default value is \c true.
|
||||
*/
|
||||
property bool activeFocusOnPress: true
|
||||
|
||||
/*! \qmlproperty enumeration horizontalAlignment
|
||||
\since QtQuick.Controls 1.1
|
||||
|
||||
This property indicates how the content is horizontally aligned
|
||||
within the text field.
|
||||
|
||||
The supported values are:
|
||||
\list
|
||||
\li Qt.AlignLeft
|
||||
\li Qt.AlignHCenter
|
||||
\li Qt.AlignRight
|
||||
\endlist
|
||||
|
||||
The default value is style dependent.
|
||||
*/
|
||||
property int horizontalAlignment: __panel ? __panel.horizontalAlignment : Qt.AlignLeft
|
||||
|
||||
/*!
|
||||
\qmlproperty bool SpinBox::hovered
|
||||
|
||||
This property indicates whether the control is being hovered.
|
||||
*/
|
||||
readonly property bool hovered: mouseArea.containsMouse || input.containsMouse
|
||||
|| mouseUp.containsMouse || mouseDown.containsMouse
|
||||
|
||||
/*!
|
||||
\qmlsignal SpinBox::editingFinished()
|
||||
\since QtQuick.Controls 1.1
|
||||
|
||||
This signal is emitted when the Return or Enter key is pressed or
|
||||
the control loses focus.
|
||||
|
||||
The corresponding handler is \c onEditingFinished.
|
||||
*/
|
||||
signal editingFinished()
|
||||
|
||||
/*!
|
||||
\qmlproperty bool SpinBox::selectByMouse
|
||||
\since QtQuick.Controls 1.3
|
||||
|
||||
This property determines if the user can select the text with the
|
||||
mouse.
|
||||
|
||||
The default value is \c true.
|
||||
*/
|
||||
property bool selectByMouse: true
|
||||
|
||||
/*!
|
||||
\qmlproperty bool SpinBox::inputMethodComposing
|
||||
\since QtQuick.Controls 1.3
|
||||
|
||||
This property holds whether the SpinBox has partial text input from an input method.
|
||||
|
||||
While it is composing an input method may rely on mouse or key events from the SpinBox
|
||||
to edit or commit the partial text. This property can be used to determine when to disable
|
||||
events handlers that may interfere with the correct operation of an input method.
|
||||
*/
|
||||
readonly property bool inputMethodComposing: !!input.inputMethodComposing
|
||||
|
||||
/*!
|
||||
\since QtQuick.Controls 1.3
|
||||
|
||||
This property contains the edit \l Menu for working
|
||||
with text selection. Set it to \c null if no menu
|
||||
is wanted.
|
||||
*/
|
||||
property Component menu: input.editMenu.defaultMenu
|
||||
|
||||
style: Settings.styleComponent(Settings.style, "SpinBoxStyle.qml", spinbox)
|
||||
|
||||
/*! \internal */
|
||||
function __increment() {
|
||||
validator.increment()
|
||||
if (activeFocus)
|
||||
input.selectValue()
|
||||
}
|
||||
|
||||
/*! \internal */
|
||||
function __decrement() {
|
||||
validator.decrement()
|
||||
if (activeFocus)
|
||||
input.selectValue()
|
||||
}
|
||||
|
||||
/*! \internal */
|
||||
property alias __text: input.text
|
||||
|
||||
/*! \internal */
|
||||
property alias __baselineOffset: input.baselineOffset
|
||||
|
||||
__styleData: QtObject {
|
||||
readonly property bool upEnabled: value != maximumValue;
|
||||
readonly property alias upHovered: mouseUp.containsMouse
|
||||
readonly property alias upPressed: mouseUp.pressed
|
||||
|
||||
readonly property bool downEnabled: value != minimumValue;
|
||||
readonly property alias downPressed: mouseDown.pressed
|
||||
readonly property alias downHovered: mouseDown.containsMouse
|
||||
|
||||
readonly property int contentHeight: Math.max(input.implicitHeight, 16)
|
||||
readonly property int contentWidth: Math.max(maxSizeHint.implicitWidth, minSizeHint.implicitWidth)
|
||||
}
|
||||
|
||||
Text {
|
||||
id: maxSizeHint
|
||||
text: prefix + maximumValue.toFixed(decimals) + suffix
|
||||
font: input.font
|
||||
visible: false
|
||||
}
|
||||
|
||||
Text {
|
||||
id: minSizeHint
|
||||
text: prefix + minimumValue.toFixed(decimals) + suffix
|
||||
font: input.font
|
||||
visible: false
|
||||
}
|
||||
|
||||
activeFocusOnTab: true
|
||||
|
||||
onActiveFocusChanged: if (activeFocus) input.selectValue()
|
||||
|
||||
Accessible.name: input.text
|
||||
Accessible.role: Accessible.SpinBox
|
||||
Accessible.editable: true
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: Settings.hoverEnabled
|
||||
onPressed: if (activeFocusOnPress) input.forceActiveFocus()
|
||||
onWheel: {
|
||||
if (wheel.angleDelta.y > 0)
|
||||
__increment();
|
||||
else
|
||||
__decrement();
|
||||
}
|
||||
}
|
||||
|
||||
TextInputWithHandles {
|
||||
id: input
|
||||
clip: contentWidth > width
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: __style ? __style.padding.left : 0
|
||||
anchors.topMargin: __style ? __style.padding.top : 0
|
||||
anchors.rightMargin: __style ? __style.padding.right: 0
|
||||
anchors.bottomMargin: __style ? __style.padding.bottom: 0
|
||||
|
||||
control: spinbox
|
||||
cursorHandle: __style ? __style.__cursorHandle : undefined
|
||||
selectionHandle: __style ? __style.__selectionHandle : undefined
|
||||
|
||||
focus: true
|
||||
activeFocusOnPress: spinbox.activeFocusOnPress
|
||||
|
||||
horizontalAlignment: spinbox.horizontalAlignment
|
||||
verticalAlignment: __panel ? __panel.verticalAlignment : Qt.AlignVCenter
|
||||
inputMethodHints: Qt.ImhFormattedNumbersOnly
|
||||
|
||||
validator: SpinBoxValidator {
|
||||
id: validator
|
||||
property bool ready: false // Delay validation until all properties are ready
|
||||
onTextChanged: if (ready) input.text = validator.text
|
||||
Component.onCompleted: {input.text = validator.text ; ready = true}
|
||||
}
|
||||
onAccepted: {
|
||||
input.text = validator.text
|
||||
selectValue()
|
||||
}
|
||||
|
||||
Keys.forwardTo: spinbox
|
||||
|
||||
onEditingFinished: spinbox.editingFinished()
|
||||
|
||||
font: __panel ? __panel.font : TextSingleton.font
|
||||
color: __panel ? __panel.foregroundColor : "black"
|
||||
selectionColor: __panel ? __panel.selectionColor : "black"
|
||||
selectedTextColor: __panel ? __panel.selectedTextColor : "black"
|
||||
|
||||
opacity: parent.enabled ? 1 : 0.5
|
||||
renderType: __style ? __style.renderType : Text.NativeRendering
|
||||
|
||||
function selectValue() {
|
||||
select(prefix.length, text.length - suffix.length)
|
||||
}
|
||||
}
|
||||
|
||||
// Spinbox increment button
|
||||
|
||||
MouseArea {
|
||||
id: mouseUp
|
||||
objectName: "mouseUp"
|
||||
hoverEnabled: Settings.hoverEnabled
|
||||
|
||||
property var upRect: __panel ? __panel.upRect : null
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
|
||||
anchors.leftMargin: upRect ? upRect.x : 0
|
||||
anchors.topMargin: upRect ? upRect.y : 0
|
||||
|
||||
width: upRect ? upRect.width : 0
|
||||
height: upRect ? upRect.height : 0
|
||||
|
||||
onClicked: __increment()
|
||||
onPressed: if (!Settings.hasTouchScreen && activeFocusOnPress) input.forceActiveFocus()
|
||||
|
||||
property bool autoincrement: false;
|
||||
onReleased: autoincrement = false
|
||||
onExited: autoincrement = false
|
||||
Timer { running: mouseUp.pressed; interval: 350 ; onTriggered: mouseUp.autoincrement = true }
|
||||
Timer { running: mouseUp.autoincrement && mouseUp.containsMouse; interval: 60 ; repeat: true ; onTriggered: __increment() }
|
||||
}
|
||||
|
||||
// Spinbox decrement button
|
||||
|
||||
MouseArea {
|
||||
id: mouseDown
|
||||
objectName: "mouseDown"
|
||||
hoverEnabled: Settings.hoverEnabled
|
||||
|
||||
onClicked: __decrement()
|
||||
onPressed: if (!Settings.hasTouchScreen && activeFocusOnPress) input.forceActiveFocus()
|
||||
|
||||
property var downRect: __panel ? __panel.downRect : null
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
|
||||
anchors.leftMargin: downRect ? downRect.x : 0
|
||||
anchors.topMargin: downRect ? downRect.y : 0
|
||||
|
||||
width: downRect ? downRect.width : 0
|
||||
height: downRect ? downRect.height : 0
|
||||
|
||||
property bool autoincrement: false;
|
||||
onReleased: autoincrement = false
|
||||
onExited: autoincrement = false
|
||||
Timer { running: mouseDown.pressed; interval: 350 ; onTriggered: mouseDown.autoincrement = true }
|
||||
Timer { running: mouseDown.autoincrement && mouseDown.containsMouse; interval: 60 ; repeat: true ; onTriggered: __decrement() }
|
||||
}
|
||||
|
||||
Keys.onUpPressed: __increment()
|
||||
Keys.onDownPressed: __decrement()
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,633 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQuick.Controls.Private 1.0 as Private
|
||||
import QtQuick.Window 2.1
|
||||
|
||||
/*!
|
||||
\qmltype SplitView
|
||||
\inqmlmodule QtQuick.Controls
|
||||
\since 5.1
|
||||
\ingroup views
|
||||
\ingroup controls
|
||||
\brief Lays out items with a draggable splitter between each item.
|
||||
|
||||
\image splitview.png
|
||||
|
||||
SplitView is a control that lays out items horizontally or
|
||||
vertically with a draggable splitter between each item.
|
||||
|
||||
There will always be one (and only one) item in the SplitView that has \l{Layout::fillWidth}{Layout.fillWidth}
|
||||
set to \c true (or \l{Layout::fillHeight}{Layout.fillHeight}, if orientation is Qt.Vertical). This means that the
|
||||
item will get all leftover space when other items have been laid out.
|
||||
By default, the last visible child of the SplitView will have this set, but
|
||||
it can be changed by explicitly setting fillWidth to \c true on another item.
|
||||
|
||||
As the fillWidth item will automatically be resized to fit the extra space, explicit assignments
|
||||
to its width and height properties will be ignored (but \l{Layout::minimumWidth}{Layout.minimumWidth} and
|
||||
\l{Layout::maximumWidth}{Layout.maximumWidth} will still be respected).
|
||||
The initial sizes of other items should be set via their width and height properties.
|
||||
Any binding assignment to an item's width or height will be broken as soon as the user
|
||||
drags that item's splitter handle.
|
||||
|
||||
A handle can belong to the item either on the left or top side, or on the right or bottom side:
|
||||
\list
|
||||
\li If the fillWidth item is to the right: the handle belongs to the left item.
|
||||
\li if the fillWidth item is on the left: the handle belongs to the right item.
|
||||
\endlist
|
||||
|
||||
This will again control which item gets resized when the user drags a handle,
|
||||
and which handle gets hidden when an item is told to hide.
|
||||
|
||||
SplitView supports setting attached Layout properties on child items, which
|
||||
means that you can set the following attached properties for each child:
|
||||
\list
|
||||
\li \l{Layout::minimumWidth}{Layout.minimumWidth}
|
||||
\li \l{Layout::minimumHeight}{Layout.minimumHeight}
|
||||
\li \l{Layout::maximumWidth}{Layout.maximumWidth}
|
||||
\li \l{Layout::maximumHeight}{Layout.maximumHeight}
|
||||
\li \l{Layout::fillWidth}{Layout.fillWidth} (\c true for only one child)
|
||||
\li \l{Layout::fillHeight}{Layout.fillHeight} (\c true for only one child)
|
||||
\endlist
|
||||
|
||||
\note import QtQuick.Layouts 1.0 in your QML file in order to use the Layout
|
||||
attached properties inside SplitView.
|
||||
|
||||
Example:
|
||||
|
||||
To create a SplitView with three items, and let the center item get superfluous space, one
|
||||
could do the following:
|
||||
|
||||
\qml
|
||||
SplitView {
|
||||
anchors.fill: parent
|
||||
orientation: Qt.Horizontal
|
||||
|
||||
Rectangle {
|
||||
width: 200
|
||||
Layout.maximumWidth: 400
|
||||
color: "lightblue"
|
||||
Text {
|
||||
text: "View 1"
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
id: centerItem
|
||||
Layout.minimumWidth: 50
|
||||
Layout.fillWidth: true
|
||||
color: "lightgray"
|
||||
Text {
|
||||
text: "View 2"
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
width: 200
|
||||
color: "lightgreen"
|
||||
Text {
|
||||
text: "View 3"
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
\endqml
|
||||
*/
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
/*!
|
||||
\qmlproperty enumeration SplitView::orientation
|
||||
|
||||
This property holds the orientation of the SplitView.
|
||||
The value can be either \c Qt.Horizontal or \c Qt.Vertical.
|
||||
The default value is \c Qt.Horizontal.
|
||||
*/
|
||||
property int orientation: Qt.Horizontal
|
||||
|
||||
/*!
|
||||
This property holds the delegate that will be instantiated between each
|
||||
child item. Inside the delegate the following properties are available:
|
||||
|
||||
\table
|
||||
\row \li readonly property bool styleData.index \li Specifies the index of the splitter handle. The handle
|
||||
between the first and the second item will get index 0,
|
||||
the next handle index 1 etc.
|
||||
\row \li readonly property bool styleData.hovered \li The handle is being hovered.
|
||||
\row \li readonly property bool styleData.pressed \li The handle is being pressed.
|
||||
\row \li readonly property bool styleData.resizing \li The handle is being dragged.
|
||||
\endtable
|
||||
|
||||
*/
|
||||
property Component handleDelegate: Rectangle {
|
||||
width: 1
|
||||
height: 1
|
||||
color: Qt.darker(pal.window, 1.5)
|
||||
}
|
||||
|
||||
/*!
|
||||
This propery is \c true when the user is resizing any of the items by
|
||||
dragging on the splitter handles.
|
||||
*/
|
||||
property bool resizing: false
|
||||
|
||||
/*! \internal */
|
||||
default property alias __contents: contents.data
|
||||
/*! \internal */
|
||||
property alias __items: splitterItems.children
|
||||
/*! \internal */
|
||||
property alias __handles: splitterHandles.children
|
||||
|
||||
clip: true
|
||||
Component.onCompleted: d.init()
|
||||
onWidthChanged: d.updateLayout()
|
||||
onHeightChanged: d.updateLayout()
|
||||
onOrientationChanged: d.changeOrientation()
|
||||
|
||||
/*! \qmlmethod void SplitView::addItem(Item item)
|
||||
Add an \a item to the end of the view.
|
||||
\since QtQuick.Controls 1.3 */
|
||||
function addItem(item) {
|
||||
d.updateLayoutGuard = true
|
||||
d.addItem_impl(item)
|
||||
d.calculateImplicitSize()
|
||||
d.updateLayoutGuard = false
|
||||
d.updateFillIndex()
|
||||
}
|
||||
|
||||
/*! \qmlmethod void SplitView::removeItem(Item item)
|
||||
Remove \a item from the view.
|
||||
\since QtQuick.Controls 1.4 */
|
||||
function removeItem(item) {
|
||||
d.updateLayoutGuard = true
|
||||
var result = d.removeItem_impl(item)
|
||||
if (result !== null) {
|
||||
d.calculateImplicitSize()
|
||||
d.updateLayoutGuard = false
|
||||
d.updateFillIndex()
|
||||
}
|
||||
else {
|
||||
d.updateLayoutGuard = false
|
||||
}
|
||||
}
|
||||
|
||||
SystemPalette { id: pal }
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
readonly property string leftMargin: horizontal ? "leftMargin" : "topMargin"
|
||||
readonly property string topMargin: horizontal ? "topMargin" : "leftMargin"
|
||||
readonly property string rightMargin: horizontal ? "rightMargin" : "bottomMargin"
|
||||
|
||||
property bool horizontal: orientation == Qt.Horizontal
|
||||
readonly property string minimum: horizontal ? "minimumWidth" : "minimumHeight"
|
||||
readonly property string maximum: horizontal ? "maximumWidth" : "maximumHeight"
|
||||
readonly property string otherMinimum: horizontal ? "minimumHeight" : "minimumWidth"
|
||||
readonly property string otherMaximum: horizontal ? "maximumHeight" : "maximumWidth"
|
||||
readonly property string offset: horizontal ? "x" : "y"
|
||||
readonly property string otherOffset: horizontal ? "y" : "x"
|
||||
readonly property string size: horizontal ? "width" : "height"
|
||||
readonly property string otherSize: horizontal ? "height" : "width"
|
||||
readonly property string implicitSize: horizontal ? "implicitWidth" : "implicitHeight"
|
||||
readonly property string implicitOtherSize: horizontal ? "implicitHeight" : "implicitWidth"
|
||||
|
||||
property int fillIndex: -1
|
||||
property bool updateLayoutGuard: true
|
||||
|
||||
function extraMarginSize(item, other) {
|
||||
if (typeof(other) === 'undefined')
|
||||
other = false;
|
||||
if (other === horizontal)
|
||||
// vertical
|
||||
return item.Layout.topMargin + item.Layout.bottomMargin
|
||||
return item.Layout.leftMargin + item.Layout.rightMargin
|
||||
}
|
||||
|
||||
function addItem_impl(item)
|
||||
{
|
||||
// temporarily set fillIndex to new item
|
||||
fillIndex = __items.length
|
||||
if (splitterItems.children.length > 0)
|
||||
handleLoader.createObject(splitterHandles, {"__handleIndex":splitterItems.children.length - 1})
|
||||
|
||||
item.parent = splitterItems
|
||||
d.initItemConnections(item)
|
||||
}
|
||||
|
||||
function initItemConnections(item)
|
||||
{
|
||||
// should match disconnections in terminateItemConnections
|
||||
item.widthChanged.connect(d.updateLayout)
|
||||
item.heightChanged.connect(d.updateLayout)
|
||||
item.Layout.maximumWidthChanged.connect(d.updateLayout)
|
||||
item.Layout.minimumWidthChanged.connect(d.updateLayout)
|
||||
item.Layout.maximumHeightChanged.connect(d.updateLayout)
|
||||
item.Layout.minimumHeightChanged.connect(d.updateLayout)
|
||||
item.Layout.leftMarginChanged.connect(d.updateLayout)
|
||||
item.Layout.topMarginChanged.connect(d.updateLayout)
|
||||
item.Layout.rightMarginChanged.connect(d.updateLayout)
|
||||
item.Layout.bottomMarginChanged.connect(d.updateLayout)
|
||||
item.visibleChanged.connect(d.updateFillIndex)
|
||||
item.Layout.fillWidthChanged.connect(d.updateFillIndex)
|
||||
item.Layout.fillHeightChanged.connect(d.updateFillIndex)
|
||||
}
|
||||
|
||||
function terminateItemConnections(item)
|
||||
{
|
||||
// should match connections in initItemConnections
|
||||
item.widthChanged.disconnect(d.updateLayout)
|
||||
item.heightChanged.disconnect(d.updateLayout)
|
||||
item.Layout.maximumWidthChanged.disconnect(d.updateLayout)
|
||||
item.Layout.minimumWidthChanged.disconnect(d.updateLayout)
|
||||
item.Layout.maximumHeightChanged.disconnect(d.updateLayout)
|
||||
item.Layout.minimumHeightChanged.disconnect(d.updateLayout)
|
||||
item.visibleChanged.disconnect(d.updateFillIndex)
|
||||
item.Layout.fillWidthChanged.disconnect(d.updateFillIndex)
|
||||
item.Layout.fillHeightChanged.disconnect(d.updateFillIndex)
|
||||
}
|
||||
|
||||
function removeItem_impl(item)
|
||||
{
|
||||
var pos = itemPos(item)
|
||||
|
||||
// Check pos range
|
||||
if (pos < 0 || pos >= __items.length)
|
||||
return null
|
||||
|
||||
// Temporary unset the fillIndex
|
||||
fillIndex = __items.length - 1
|
||||
|
||||
// Remove the handle at the left/right of the item that
|
||||
// is going to be removed
|
||||
var handlePos = -1
|
||||
var hasPrevious = pos > 0
|
||||
var hasNext = (pos + 1) < __items.length
|
||||
|
||||
if (hasPrevious)
|
||||
handlePos = pos-1
|
||||
else if (hasNext)
|
||||
handlePos = pos
|
||||
if (handlePos >= 0) {
|
||||
var handle = __handles[handlePos]
|
||||
handle.visible = false
|
||||
handle.parent = null
|
||||
handle.destroy()
|
||||
for (var i = handlePos; i < __handles.length; ++i)
|
||||
__handles[i].__handleIndex = i
|
||||
}
|
||||
|
||||
// Remove the item.
|
||||
// Disconnect the item to be removed
|
||||
terminateItemConnections(item)
|
||||
item.parent = null
|
||||
|
||||
return item
|
||||
}
|
||||
|
||||
function itemPos(item)
|
||||
{
|
||||
for (var i = 0; i < __items.length; ++i)
|
||||
if (item === __items[i])
|
||||
return i
|
||||
return -1
|
||||
}
|
||||
|
||||
function init()
|
||||
{
|
||||
for (var i=0; i<__contents.length; ++i) {
|
||||
var item = __contents[i];
|
||||
if (!item.hasOwnProperty("x"))
|
||||
continue
|
||||
addItem_impl(item)
|
||||
i-- // item was removed from list
|
||||
}
|
||||
|
||||
d.calculateImplicitSize()
|
||||
d.updateLayoutGuard = false
|
||||
d.updateFillIndex()
|
||||
}
|
||||
|
||||
function updateFillIndex()
|
||||
{
|
||||
if (lastItem.visible !== root.visible)
|
||||
return
|
||||
var policy = (root.orientation === Qt.Horizontal) ? "fillWidth" : "fillHeight"
|
||||
for (var i=0; i<__items.length-1; ++i) {
|
||||
if (__items[i].Layout[policy] === true)
|
||||
break;
|
||||
}
|
||||
|
||||
d.fillIndex = i
|
||||
d.updateLayout()
|
||||
}
|
||||
|
||||
function changeOrientation()
|
||||
{
|
||||
if (__items.length == 0)
|
||||
return;
|
||||
d.updateLayoutGuard = true
|
||||
|
||||
// Swap width/height for items and handles:
|
||||
for (var i=0; i<__items.length; ++i) {
|
||||
var item = __items[i]
|
||||
var tmp = item.x
|
||||
item.x = item.y
|
||||
item.y = tmp
|
||||
tmp = item.width
|
||||
item.width = item.height
|
||||
item.height = tmp
|
||||
|
||||
var handle = __handles[i]
|
||||
if (handle) {
|
||||
tmp = handle.x
|
||||
handle.x = handle.y
|
||||
handle.y = handle.x
|
||||
tmp = handle.width
|
||||
handle.width = handle.height
|
||||
handle.height = tmp
|
||||
}
|
||||
}
|
||||
|
||||
// Change d.horizontal explicit, since the binding will change too late:
|
||||
d.horizontal = orientation == Qt.Horizontal
|
||||
d.updateLayoutGuard = false
|
||||
d.updateFillIndex()
|
||||
}
|
||||
|
||||
function calculateImplicitSize()
|
||||
{
|
||||
var implicitSize = 0
|
||||
var implicitOtherSize = 0
|
||||
|
||||
for (var i=0; i<__items.length; ++i) {
|
||||
var item = __items[i];
|
||||
implicitSize += clampedMinMax(item[d.size], item.Layout[minimum], item.Layout[maximum]) + extraMarginSize(item)
|
||||
var os = clampedMinMax(item[otherSize], item.Layout[otherMinimum], item.Layout[otherMaximum]) + extraMarginSize(item, true)
|
||||
implicitOtherSize = Math.max(implicitOtherSize, os)
|
||||
|
||||
var handle = __handles[i]
|
||||
if (handle)
|
||||
implicitSize += handle[d.size] //### Can handles have margins??
|
||||
}
|
||||
|
||||
root[d.implicitSize] = implicitSize
|
||||
root[d.implicitOtherSize] = implicitOtherSize
|
||||
}
|
||||
|
||||
function clampedMinMax(value, minimum, maximum)
|
||||
{
|
||||
if (value < minimum)
|
||||
value = minimum
|
||||
if (value > maximum)
|
||||
value = maximum
|
||||
return value
|
||||
}
|
||||
|
||||
function accumulatedSize(firstIndex, lastIndex, includeFillItemMinimum)
|
||||
{
|
||||
// Go through items and handles, and
|
||||
// calculate their accummulated width.
|
||||
var w = 0
|
||||
for (var i=firstIndex; i<lastIndex; ++i) {
|
||||
|
||||
var item = __items[i]
|
||||
if (item.visible || i == d.fillIndex) {
|
||||
if (i !== d.fillIndex)
|
||||
w += item[d.size] + extraMarginSize(item)
|
||||
else if (includeFillItemMinimum && item.Layout[minimum] !== undefined)
|
||||
w += item.Layout[minimum] + extraMarginSize(item)
|
||||
}
|
||||
|
||||
var handle = __handles[i]
|
||||
if (handle && handle.visible)
|
||||
w += handle[d.size]
|
||||
}
|
||||
return w
|
||||
}
|
||||
|
||||
function updateLayout()
|
||||
{
|
||||
// This function will reposition both handles and
|
||||
// items according to the their width/height:
|
||||
if (__items.length === 0)
|
||||
return;
|
||||
if (!lastItem.visible)
|
||||
return;
|
||||
if (d.updateLayoutGuard === true)
|
||||
return
|
||||
d.updateLayoutGuard = true
|
||||
|
||||
// Ensure all items within their min/max:
|
||||
for (var i=0; i<__items.length; ++i) {
|
||||
if (i !== d.fillIndex) {
|
||||
var item = __items[i];
|
||||
var clampedSize = clampedMinMax(item[d.size], item.Layout[d.minimum], item.Layout[d.maximum])
|
||||
if (clampedSize != item[d.size])
|
||||
item[d.size] = clampedSize
|
||||
}
|
||||
}
|
||||
|
||||
// Set size of fillItem to remaining available space.
|
||||
// Special case: If SplitView size is zero, we leave fillItem with the size
|
||||
// it already got, and assume that SplitView ends up with implicit size as size:
|
||||
if (root[d.size] != 0) {
|
||||
var fillItem = __items[fillIndex]
|
||||
var superfluous = root[d.size] - d.accumulatedSize(0, __items.length, false)
|
||||
fillItem[d.size] = clampedMinMax(superfluous - extraMarginSize(fillItem), fillItem.Layout[minimum], fillItem.Layout[maximum]);
|
||||
}
|
||||
|
||||
// Position items and handles according to their width:
|
||||
var lastVisibleItem, lastVisibleHandle, handle
|
||||
var pos = 0;
|
||||
for (i=0; i<__items.length; ++i) {
|
||||
// Position item to the right of the previous visible handle:
|
||||
item = __items[i];
|
||||
if (item.visible || i == d.fillIndex) {
|
||||
pos += item.Layout[leftMargin]
|
||||
item[d.offset] = pos
|
||||
item[d.otherOffset] = item.Layout[topMargin]
|
||||
item[d.otherSize] = clampedMinMax(root[otherSize], item.Layout[otherMinimum], item.Layout[otherMaximum]) - extraMarginSize(item, true)
|
||||
lastVisibleItem = item
|
||||
pos += Math.max(0, item[d.size]) + item.Layout[rightMargin]
|
||||
}
|
||||
|
||||
handle = __handles[i]
|
||||
if (handle && handle.visible) {
|
||||
handle[d.offset] = pos
|
||||
handle[d.otherOffset] = 0 //### can handles have margins?
|
||||
handle[d.otherSize] = root[d.otherSize]
|
||||
lastVisibleHandle = handle
|
||||
pos += handle[d.size]
|
||||
}
|
||||
}
|
||||
|
||||
d.updateLayoutGuard = false
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: handleLoader
|
||||
Loader {
|
||||
id: itemHandle
|
||||
|
||||
property int __handleIndex: -1
|
||||
property QtObject styleData: QtObject {
|
||||
readonly property int index: __handleIndex
|
||||
readonly property alias hovered: mouseArea.containsMouse
|
||||
readonly property alias pressed: mouseArea.pressed
|
||||
readonly property bool resizing: mouseArea.drag.active
|
||||
onResizingChanged: root.resizing = resizing
|
||||
}
|
||||
property bool resizeLeftItem: (d.fillIndex > __handleIndex)
|
||||
visible: __items[__handleIndex + (resizeLeftItem ? 0 : 1)].visible
|
||||
sourceComponent: handleDelegate
|
||||
onWidthChanged: d.updateLayout()
|
||||
onHeightChanged: d.updateLayout()
|
||||
onXChanged: moveHandle()
|
||||
onYChanged: moveHandle()
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
property real defaultMargin: Private.Settings.hasTouchScreen ? Screen.pixelDensity * 3.5 : 2
|
||||
anchors.leftMargin: (parent.width <= 1) ? -defaultMargin : 0
|
||||
anchors.rightMargin: (parent.width <= 1) ? -defaultMargin : 0
|
||||
anchors.topMargin: (parent.height <= 1) ? -defaultMargin : 0
|
||||
anchors.bottomMargin: (parent.height <= 1) ? -defaultMargin : 0
|
||||
hoverEnabled: Private.Settings.hoverEnabled
|
||||
drag.threshold: 0
|
||||
drag.target: parent
|
||||
drag.axis: root.orientation === Qt.Horizontal ? Drag.XAxis : Drag.YAxis
|
||||
cursorShape: root.orientation === Qt.Horizontal ? Qt.SplitHCursor : Qt.SplitVCursor
|
||||
}
|
||||
|
||||
function moveHandle() {
|
||||
// Moving the handle means resizing an item. Which one,
|
||||
// left or right, depends on where the fillItem is.
|
||||
// 'updateLayout' will be overridden in case new width violates max/min.
|
||||
// 'updateLayout' will be triggered when an item changes width.
|
||||
if (d.updateLayoutGuard)
|
||||
return
|
||||
|
||||
var leftHandle, leftItem, rightItem, rightHandle
|
||||
var leftEdge, rightEdge, newWidth, leftStopX, rightStopX
|
||||
var i
|
||||
|
||||
if (resizeLeftItem) {
|
||||
// Ensure that the handle is not crossing other handles. So
|
||||
// find the first visible handle to the left to determine the left edge:
|
||||
leftEdge = 0
|
||||
for (i=__handleIndex-1; i>=0; --i) {
|
||||
leftHandle = __handles[i]
|
||||
if (leftHandle.visible) {
|
||||
leftEdge = leftHandle[d.offset] + leftHandle[d.size]
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure: leftStopX >= itemHandle[d.offset] >= rightStopX
|
||||
var min = d.accumulatedSize(__handleIndex+1, __items.length, true)
|
||||
rightStopX = root[d.size] - min - itemHandle[d.size]
|
||||
leftStopX = Math.max(leftEdge, itemHandle[d.offset])
|
||||
itemHandle[d.offset] = Math.min(rightStopX, Math.max(leftStopX, itemHandle[d.offset]))
|
||||
|
||||
newWidth = itemHandle[d.offset] - leftEdge
|
||||
leftItem = __items[__handleIndex]
|
||||
// The next line will trigger 'updateLayout':
|
||||
leftItem[d.size] = newWidth
|
||||
} else {
|
||||
// Resize item to the right.
|
||||
// Ensure that the handle is not crossing other handles. So
|
||||
// find the first visible handle to the right to determine the right edge:
|
||||
rightEdge = root[d.size]
|
||||
for (i=__handleIndex+1; i<__handles.length; ++i) {
|
||||
rightHandle = __handles[i]
|
||||
if (rightHandle.visible) {
|
||||
rightEdge = rightHandle[d.offset]
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure: leftStopX <= itemHandle[d.offset] <= rightStopX
|
||||
min = d.accumulatedSize(0, __handleIndex+1, true)
|
||||
leftStopX = min - itemHandle[d.size]
|
||||
rightStopX = Math.min((rightEdge - itemHandle[d.size]), itemHandle[d.offset])
|
||||
itemHandle[d.offset] = Math.max(leftStopX, Math.min(itemHandle[d.offset], rightStopX))
|
||||
|
||||
newWidth = rightEdge - (itemHandle[d.offset] + itemHandle[d.size])
|
||||
rightItem = __items[__handleIndex+1]
|
||||
// The next line will trigger 'updateLayout':
|
||||
rightItem[d.size] = newWidth
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: contents
|
||||
visible: false
|
||||
anchors.fill: parent
|
||||
}
|
||||
Item {
|
||||
id: splitterItems
|
||||
anchors.fill: parent
|
||||
}
|
||||
Item {
|
||||
id: splitterHandles
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
Item {
|
||||
id: lastItem
|
||||
onVisibleChanged: d.updateFillIndex()
|
||||
}
|
||||
|
||||
Component.onDestruction: {
|
||||
for (var i=0; i<splitterItems.children.length; ++i) {
|
||||
var item = splitterItems.children[i];
|
||||
d.terminateItemConnections(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,996 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Quick Controls module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Controls.Private 1.0
|
||||
|
||||
/*!
|
||||
\qmltype StackView
|
||||
\inherits Item
|
||||
\ingroup views
|
||||
\ingroup controls
|
||||
\inqmlmodule QtQuick.Controls
|
||||
\since 5.1
|
||||
|
||||
\brief Provides a stack-based navigation model.
|
||||
|
||||
\image stackview.png
|
||||
|
||||
StackView implements a stack-based navigation model, which can be used
|
||||
with a set of interlinked information pages. Items are pushed onto the stack
|
||||
as the user navigates deeper into the material, and popped off again when he
|
||||
chooses to go back.
|
||||
|
||||
The \l{Qt Quick Controls 1 - Touch Gallery}{touch gallery} example is a good
|
||||
starting point to understand how StackView works. The following snippet
|
||||
from the example shows how it can be used:
|
||||
|
||||
\qml
|
||||
StackView {
|
||||
id: stack
|
||||
initialItem: view
|
||||
|
||||
Component {
|
||||
id: view
|
||||
|
||||
MouseArea {
|
||||
Text {
|
||||
text: stack.depth
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
onClicked: stack.push(view)
|
||||
}
|
||||
}
|
||||
}
|
||||
\endqml
|
||||
|
||||
\section1 Using StackView in an Application
|
||||
Using StackView in an application is typically a simple matter of adding
|
||||
the StackView as a child of a Window. The stack is usually anchored to the
|
||||
edges of the window, except at the top or bottom where it might be anchored
|
||||
to a status bar, or some other similar UI component. The stack can then be
|
||||
used by invoking its navigation methods. The first item to show in the StackView
|
||||
is the one that was assigned to \l initialItem.
|
||||
|
||||
\note Items pushed onto the stack view have \l{Supported Attached Properties}{Stack attached properties}.
|
||||
|
||||
\section1 Basic Navigation
|
||||
There are three primary navigation operations in StackView: push(), pop(), and
|
||||
replace (replace by specifying argument \c replace to push()).
|
||||
These correspond to classic stack operations where "push" adds an item to the
|
||||
top of a stack, "pop" removes the top item from the stack, and "replace" is like a
|
||||
pop followed by a push, in that it replaces the topmost item on the stack with
|
||||
a new item (but the applied transtition might be different). The topmost item
|
||||
in the stack corresponds to the one that is \l{StackView::currentItem} {currently}
|
||||
visible on the screen. That means that "push" is the logical equivalent of navigating
|
||||
forward or deeper into the application, "pop" is the equivalent of navigating back,
|
||||
and "replace" is the equivalent of replacing the current item.
|
||||
|
||||
Sometimes it is necessary to go back more than a single step in the stack, for
|
||||
example, to return to a "main" item or some kind of section item in the application.
|
||||
For this use case, it is possible to specify an item as a parameter for pop().
|
||||
This is called an "unwind" operation as the stack gets unwound to the specified item.
|
||||
If the item is not found, then the stack unwinds until there is only a single item in
|
||||
the stack, which then becomes the current item. To explicitly unwind to the bottom
|
||||
of the stack, it is recommended to use \l{pop()} {pop(null)}, though technically any
|
||||
non-existent item will do.
|
||||
|
||||
Given the stack [A, B, C]:
|
||||
|
||||
\list
|
||||
\li \l{push()}{push(D)} => [A, B, C, D] - "push" transition animation between C and D
|
||||
\li pop() => [A, B] - "pop" transition animation between C and B
|
||||
\li \l{push()}{push(D, replace)} => [A, B, D] - "replace" transition between C and D
|
||||
\li \l{pop()}{pop(A)} => [A] - "pop" transition between C and A
|
||||
\endlist
|
||||
|
||||
\note When the stack is empty, a push() will not perform a
|
||||
transition animation because there is nothing to transition from (typically during
|
||||
application start-up). A pop() on a stack with depth 1 or 0 is a no-operation.
|
||||
If all items need to be removed from the stack, a separate function clear() is
|
||||
available.
|
||||
|
||||
Calling push() returns the item that was pushed onto the stack.
|
||||
Calling pop() returns the item that was popped off the stack. When pop() is
|
||||
called in an unwind operation, the top-most item (the first item that was
|
||||
popped, which will also be the one transitioning out) is returned.
|
||||
|
||||
\section1 Deep Linking
|
||||
\e{Deep linking} means launching an application into a particular state. For example,
|
||||
a newspaper application could be launched into showing a particular article,
|
||||
bypassing the front item (and possibly a section item) that would normally have
|
||||
to be navigated through to get to the article concerned. In terms of StackView, deep
|
||||
linking means the ability to modify the state of the stack, so much so that it is
|
||||
possible to push a set of items to the top of the stack, or to completely reset
|
||||
the stack to a given state.
|
||||
|
||||
The API for deep linking in StackView is the same as for basic navigation. Pushing
|
||||
an array instead of a single item, will involve that all the items in that array will
|
||||
be pushed onto the stack. The transition animation, however, will be conducted as
|
||||
if only the last item in the array was pushed onto the stack. The normal semantics
|
||||
of push() apply for deep linking, meaning that push() adds whatever is pushed onto
|
||||
the stack. Note also that only the last item of the array will be loaded.
|
||||
The rest will be lazy-loaded as needed when entering the screen upon subsequent
|
||||
calls to pop (or when requesting the item by using \a get).
|
||||
|
||||
This gives us the following result, given the stack [A, B, C]:
|
||||
|
||||
\list
|
||||
\li \l{push()}{push([D, E, F])} => [A, B, C, D, E, F] - "push" transition animation between C and F
|
||||
\li \l{push()}{push([D, E, F], replace)} => [A, B, D, E, F] - "replace" transition animation between C and F
|
||||
\li clear(); \l{push()}{push([D, E, F])} => [D, E, F] - no transition animation (since the stack was empty)
|
||||
\endlist
|
||||
|
||||
\section1 Pushing items
|
||||
|
||||
An item pushed onto the StackView can be either an Item, a URL, a string
|
||||
containing a URL, or a Component. To push it, assign it to a property "item"
|
||||
inside a property list, and pass it as an argument to \l{StackView::push}{push}:
|
||||
|
||||
\code
|
||||
stackView.push({item: yourItem})
|
||||
\endcode
|
||||
|
||||
The list can contain several properties that control how the item should be pushed:
|
||||
\list
|
||||
\li \c item: this property is required, and holds the item to be pushed.
|
||||
\li \c properties: a list of QML properties to be assigned to the item upon push. These
|
||||
properties will be copied into the item at load time, or when the item will become
|
||||
the current item (normally upon push).
|
||||
\li \c immediate: set this property to \c true to skip transition effects. When pushing
|
||||
an array, this property only needs to be set on the first element to make the
|
||||
whole operation immediate.
|
||||
\li \c replace: set this property to replace the current item on the stack. When pushing
|
||||
an array, you only need to set this property on the first element to replace
|
||||
as many elements on the stack as inside the array.
|
||||
\li \c destroyOnPop: set this boolean to \c true if StackView needs to destroy the item when
|
||||
it is popped off the stack. By default (if \a destroyOnPop is not specified), StackView
|
||||
will destroy items pushed as components or URLs. Items not destroyed will be re-parented
|
||||
back to the original parents they had before being pushed onto the stack and hidden.
|
||||
If you need to set this property, do it with care, so that items are not leaked.
|
||||
\endlist
|
||||
|
||||
If the only argument needed is "item", the following short-hand notation can be applied:
|
||||
|
||||
\code
|
||||
stackView.push(yourItem)
|
||||
\endcode
|
||||
|
||||
You can push several items in one go by using an array of property lists. This is
|
||||
more efficient than pushing items one by one, as StackView can then load only the
|
||||
last item in the list. The rest will be loaded as they are about to become
|
||||
the current item (which happens when the stack is popped). The following example shows how
|
||||
to push an array of items:
|
||||
|
||||
\code
|
||||
stackView.push([{item: yourItem1}, {item: yourItem2}])
|
||||
\endcode
|
||||
|
||||
If an inline item is pushed, the item is temporarily re-parented into the StackView. When the item
|
||||
is later popped off, it gets re-parented back to its original owner again.
|
||||
If, however, an item is pushed as a component or a URL, the actual item will be created as an
|
||||
item from that component. This happens automatically when the item is about to become the current
|
||||
item in the stack. Ownership of the item will then normally be taken by the StackView, which will
|
||||
automatically destroy the item when it is later popped off. The component that declared the item, by
|
||||
contrast, remains in the ownership of the application and is not destroyed by the stack.
|
||||
This can be overridden by explicitly setting \c{destroyOnPop} in the list of arguments given to push.
|
||||
|
||||
If the \c properties to be pushed are specified, they will be copied into the item at loading time
|
||||
(in case of a component or URL), or when the item becomes the current item (in case of an inline
|
||||
item). The following example shows how this can be done:
|
||||
|
||||
\code
|
||||
stackView.push({item: someItem, properties: {fgcolor: "red", bgcolor: "blue"}})
|
||||
\endcode
|
||||
|
||||
|
||||
\note If an item is declared inside another item, and that parent gets destroyed,
|
||||
(even if a component was used), that child item will also be destroyed.
|
||||
This follows normal Qt parent-child destruction rules, but sometimes comes as a surprise
|
||||
for developers.
|
||||
|
||||
\section1 Lifecycle
|
||||
An item's lifecycle in the StackView can have the following transitions:
|
||||
\list 1
|
||||
\li instantiation
|
||||
\li inactive
|
||||
\li activating
|
||||
\li active
|
||||
\li deactivating
|
||||
\li inactive
|
||||
\li destruction
|
||||
\endlist
|
||||
|
||||
It can move any number of times between inactive and active. When an item is activated,
|
||||
it's visible on the screen and is considered to be the current item. An item
|
||||
in a StackView that is not visible is not activated, even if the item is currently the
|
||||
top-most item in the stack. When the stack becomes visible, the item that is top-most gets
|
||||
activated. Likewise if the stack is then hidden, the topmost item would be deactivated.
|
||||
Popping the item off the top of the stack at this point would not result in further
|
||||
deactivation since the item is not active.
|
||||
|
||||
There is an attached \l{Stack::status}{Stack.status} property that tracks the lifecycle. This
|
||||
property is an enumeration with the following values: \c Stack.Inactive, \c Stack.Activating,
|
||||
\c Stack.Active and \c Stack.Deactivating. Combined with the normal \c Component.onComplete and
|
||||
\c Component.onDestruction signals, the entire lifecycle is thus:
|
||||
|
||||
\list
|
||||
\li Created: Component.onCompleted()
|
||||
\li Activating: Stack.onStatusChanged (Stack.status is Stack.Activating)
|
||||
\li Acivated: Stack.onStatusChanged (Stack.status is Stack.Active)
|
||||
\li Deactivating: Stack.onStatusChanged (Stack.status is Stack.Deactivating)
|
||||
\li Deactivated: Stack.onStatusChanged (Stack.status is Stack.Inactive)
|
||||
\li Destruction: Component.onDestruction()
|
||||
\endlist
|
||||
|
||||
\section1 Finding items
|
||||
Sometimes it is necessary to search for an item, for example, in order to unwind the stack to
|
||||
an item to which the application does not have a reference. This is facilitated using a
|
||||
function find() in StackView. The find() function takes a callback function as its
|
||||
only argument. The callback gets invoked for each item in the stack (starting at the top).
|
||||
If the callback returns true, then it signals that a match has been found and the find()
|
||||
function returns that item. If the callback fails to return true (no match is found),
|
||||
then find() returns \c null.
|
||||
|
||||
The code below searches for an item in the stack that has a name "order_id" and then unwinds to
|
||||
that item. Note that since find() returns \c {null} if no item is found, and since pop unwinds to
|
||||
the bottom of the stack if null is given as the target item, the code works well even in
|
||||
case no matching item is found.
|
||||
|
||||
\code
|
||||
stackView.pop(stackView.find(function(item) {
|
||||
return item.name == "order_id";
|
||||
}));
|
||||
\endcode
|
||||
|
||||
You can also get to an item in the stack using \l {get()}{get(index)}. You should use
|
||||
this function if your item depends on another item in the stack, as the function will
|
||||
ensure that the item at the given index gets loaded before it is returned.
|
||||
|
||||
\code
|
||||
previousItem = stackView.get(myItem.Stack.index - 1));
|
||||
\endcode
|
||||
|
||||
\section1 Transitions
|
||||
|
||||
A transition is performed whenever a item is pushed or popped, and consists of
|
||||
two items: enterItem and exitItem. The StackView itself will never move items
|
||||
around, but instead delegates the job to an external animation set provided
|
||||
by the style or the application developer. How items should visually enter and leave the stack
|
||||
(and the geometry they should end up with) is therefore completely controlled from the outside.
|
||||
|
||||
When the transition starts, the StackView will search for a transition that
|
||||
matches the operation executed. There are three transitions to choose
|
||||
from: \l {StackViewDelegate::}{pushTransition}, \l {StackViewDelegate::}{popTransition},
|
||||
and \l {StackViewDelegate::}{replaceTransition}. Each implements how
|
||||
\c enterItem should animate in, and \c exitItem out. The transitions are
|
||||
collected inside a StackViewDelegate object assigned to
|
||||
\l {StackView::delegate}{delegate}. By default, popTransition and
|
||||
replaceTransition will be the same as pushTransition, unless you set them
|
||||
to something else.
|
||||
|
||||
A simple fade transition could be implemented as:
|
||||
|
||||
\qml
|
||||
StackView {
|
||||
delegate: StackViewDelegate {
|
||||
function transitionFinished(properties)
|
||||
{
|
||||
properties.exitItem.opacity = 1
|
||||
}
|
||||
|
||||
pushTransition: StackViewTransition {
|
||||
PropertyAnimation {
|
||||
target: enterItem
|
||||
property: "opacity"
|
||||
from: 0
|
||||
to: 1
|
||||
}
|
||||
PropertyAnimation {
|
||||
target: exitItem
|
||||
property: "opacity"
|
||||
from: 1
|
||||
to: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
\endqml
|
||||
|
||||
PushTransition needs to inherit from StackViewTransition, which is a ParallelAnimation that
|
||||
contains the properties \c enterItem and \c exitItem. These items should be assigned to the
|
||||
\c target property of animations within the transition. Since the same items instance can
|
||||
be pushed several times to a StackView, you should always override
|
||||
\l {StackViewDelegate::transitionFinished()}{StackViewDelegate.transitionFinished()}.
|
||||
Implement this function to reset any properties animated on the exitItem so that later
|
||||
transitions can expect the items to be in a default state.
|
||||
|
||||
A more complex example could look like the following. Here, the items are lying on the side before
|
||||
being rotated to an upright position:
|
||||
|
||||
\qml
|
||||
StackView {
|
||||
delegate: StackViewDelegate {
|
||||
function transitionFinished(properties)
|
||||
{
|
||||
properties.exitItem.x = 0
|
||||
properties.exitItem.rotation = 0
|
||||
}
|
||||
|
||||
pushTransition: StackViewTransition {
|
||||
SequentialAnimation {
|
||||
ScriptAction {
|
||||
script: enterItem.rotation = 90
|
||||
}
|
||||
PropertyAnimation {
|
||||
target: enterItem
|
||||
property: "x"
|
||||
from: enterItem.width
|
||||
to: 0
|
||||
}
|
||||
PropertyAnimation {
|
||||
target: enterItem
|
||||
property: "rotation"
|
||||
from: 90
|
||||
to: 0
|
||||
}
|
||||
}
|
||||
PropertyAnimation {
|
||||
target: exitItem
|
||||
property: "x"
|
||||
from: 0
|
||||
to: -exitItem.width
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
\endqml
|
||||
|
||||
\section2 Advanced usage
|
||||
|
||||
When the StackView needs a new transition, it first calls
|
||||
\l {StackViewDelegate::getTransition()}{StackViewDelegate.getTransition()}.
|
||||
The base implementation of this function just looks for a property named \c properties.name inside
|
||||
itself (root), which is how it finds \c {property Component pushTransition} in the examples above.
|
||||
|
||||
\code
|
||||
function getTransition(properties)
|
||||
{
|
||||
return root[properties.name]
|
||||
}
|
||||
\endcode
|
||||
|
||||
You can override this function for your delegate if you need extra logic to decide which
|
||||
transition to return. You could for example introspect the items, and return different animations
|
||||
depending on the their internal state. StackView will expect you to return a Component that
|
||||
contains a StackViewTransition, or a StackViewTransition directly. The former is easier, as StackView will
|
||||
then create the transition and later destroy it when it's done, while avoiding any side effects
|
||||
caused by the transition being alive long after it has run. Returning a StackViewTransition directly
|
||||
can be useful if you need to write some sort of transition caching for performance reasons.
|
||||
As an optimization, you can also return \c null to signal that you just want to show/hide the items
|
||||
immediately without creating or running any transitions. You can also override this function if
|
||||
you need to alter the items in any way before the transition starts.
|
||||
|
||||
\c properties contains the properties that will be assigned to the StackViewTransition before
|
||||
it runs. In fact, you can add more properties to this object during the call
|
||||
if you need to initialize additional properties of your custom StackViewTransition when the returned
|
||||
component is instantiated.
|
||||
|
||||
The following example shows how you can decide which animation to use at runtime:
|
||||
|
||||
\qml
|
||||
StackViewDelegate {
|
||||
function getTransition(properties)
|
||||
{
|
||||
return (properties.enterItem.Stack.index % 2) ? horizontalTransition : verticalTransition
|
||||
}
|
||||
|
||||
function transitionFinished(properties)
|
||||
{
|
||||
properties.exitItem.x = 0
|
||||
properties.exitItem.y = 0
|
||||
}
|
||||
|
||||
property Component horizontalTransition: StackViewTransition {
|
||||
PropertyAnimation {
|
||||
target: enterItem
|
||||
property: "x"
|
||||
from: target.width
|
||||
to: 0
|
||||
duration: 300
|
||||
}
|
||||
PropertyAnimation {
|
||||
target: exitItem
|
||||
property: "x"
|
||||
from: 0
|
||||
to: target.width
|
||||
duration: 300
|
||||
}
|
||||
}
|
||||
|
||||
property Component verticalTransition: StackViewTransition {
|
||||
PropertyAnimation {
|
||||
target: enterItem
|
||||
property: "y"
|
||||
from: target.height
|
||||
to: 0
|
||||
duration: 300
|
||||
}
|
||||
PropertyAnimation {
|
||||
target: exitItem
|
||||
property: "y"
|
||||
from: 0
|
||||
to: target.height
|
||||
duration: 300
|
||||
}
|
||||
}
|
||||
}
|
||||
\endqml
|
||||
|
||||
\section1 Supported Attached Properties
|
||||
|
||||
Items in a StackView support these attached properties:
|
||||
\list
|
||||
\li \l{Stack::index}{Stack.index} - Contains the index of the item inside the StackView
|
||||
\li \l{Stack::view}{Stack.view} - Contains the StackView the item is in
|
||||
\li \l{Stack::status}{Stack.status} - Contains the status of the item
|
||||
\endlist
|
||||
*/
|
||||
|
||||
FocusScope {
|
||||
id: root
|
||||
|
||||
/*! \qmlproperty int StackView::depth
|
||||
\readonly
|
||||
The number of items currently pushed onto the stack.
|
||||
*/
|
||||
readonly property alias depth: root.__depth
|
||||
|
||||
/*! \qmlproperty Item StackView::currentItem
|
||||
\readonly
|
||||
The currently top-most item in the stack.
|
||||
*/
|
||||
readonly property alias currentItem: root.__currentItem
|
||||
|
||||
/*! The first item that should be shown when the StackView is created.
|
||||
\a initialItem can take same value as the first argument to \l{StackView::push()}
|
||||
{StackView.push()}. Note that this is just a convenience for writing
|
||||
\c{Component.onCompleted: stackView.push(myInitialItem)}
|
||||
|
||||
Examples:
|
||||
|
||||
\list
|
||||
\li initialItem: Qt.resolvedUrl("MyItem.qml")
|
||||
\li initialItem: myItem
|
||||
\li initialItem: {"item" : Qt.resolvedUrl("MyRectangle.qml"), "properties" : {"color" : "red"}}
|
||||
\endlist
|
||||
\sa push
|
||||
*/
|
||||
property var initialItem: null
|
||||
|
||||
/*! \readonly
|
||||
\a busy is \c true if a transition is running, and \c false otherwise. */
|
||||
readonly property bool busy: __currentTransition !== null
|
||||
|
||||
/*! The transitions to use when pushing or popping items.
|
||||
For better understanding on how to apply custom transitions, read \l{Transitions}.
|
||||
\sa {Transitions} */
|
||||
property StackViewDelegate delegate: StackViewSlideDelegate {}
|
||||
|
||||
/*! \qmlmethod Item StackView::push(Item item)
|
||||
Pushes an \a item onto the stack.
|
||||
|
||||
The function can also take a property list as argument - \c {Item StackView::push(jsobject dict)}, which
|
||||
should contain one or more of the following properties:
|
||||
\list
|
||||
\li \a item: this property is required, and holds the item you want to push.
|
||||
\li \e properties: a list of QML properties that should be assigned
|
||||
to the item upon push. These properties will be copied into the item when it is
|
||||
loaded (in case of a component or URL), or when it becomes the current item for the
|
||||
first time (normally upon push).
|
||||
\li \e immediate: set this property to \c true to skip transition effects. When pushing
|
||||
an array, you only need to set this property on the first element to make the
|
||||
whole operation immediate.
|
||||
\li \e replace: set this property to replace the current item on the stack. When pushing
|
||||
an array, you only need to set this property on the first element to replace
|
||||
as many elements on the stack as inside the array.
|
||||
\li \e destroyOnPop: set this property to specify if the item needs to be destroyed
|
||||
when its popped off the stack. By default (if \e destroyOnPop is not specified),
|
||||
StackView will destroy items pushed as components or URLs. Items
|
||||
not destroyed will be re-parented to the original parents they had before being
|
||||
pushed onto the stack, and hidden. If you need to set this property, do it with
|
||||
care, so that items are not leaked.
|
||||
\endlist
|
||||
|
||||
You can also push an array of items (property lists) if you need to push several items
|
||||
in one go. A transition will then only occur between the current item and the last
|
||||
item in the list. Loading the other items will be deferred until needed.
|
||||
|
||||
Examples:
|
||||
\list
|
||||
\li stackView.push({item:anItem})
|
||||
\li stackView.push({item:aURL, immediate: true, replace: true})
|
||||
\li stackView.push({item:aRectangle, properties:{color:"red"}})
|
||||
\li stackView.push({item:aComponent, properties:{color:"red"}})
|
||||
\li stackView.push({item:aComponent.createObject(), destroyOnPop:true})
|
||||
\li stackView.push([{item:anitem, immediate:true}, {item:aURL}])
|
||||
\endlist
|
||||
|
||||
\note If the only argument needed is "item", you can apply the following short-
|
||||
hand notation: \c{stackView.push(anItem)}.
|
||||
|
||||
Returns the item that became current.
|
||||
|
||||
\sa initialItem
|
||||
\sa {Pushing items}
|
||||
*/
|
||||
function push(item) {
|
||||
// Note: we support two different APIs in this function; The old meego API, and
|
||||
// the new "property list" API. Hence the reason for hiding the fact that you
|
||||
// can pass more arguments than shown in the signature:
|
||||
if (__recursionGuard(true))
|
||||
return
|
||||
var properties = arguments[1]
|
||||
var immediate = arguments[2]
|
||||
var replace = arguments[3]
|
||||
var arrayPushed = (item instanceof Array)
|
||||
var firstItem = arrayPushed ? item[0] : item
|
||||
immediate = (immediate || JSArray.stackView.length === 0)
|
||||
|
||||
if (firstItem && firstItem.item && firstItem.hasOwnProperty("x") === false) {
|
||||
// Property list API used:
|
||||
immediate = immediate || firstItem.immediate
|
||||
replace = replace || firstItem.replace
|
||||
}
|
||||
|
||||
// Create, and push, a new javascript object, called "element", onto the stack.
|
||||
// This element contains all the information necessary to construct the item, and
|
||||
// will, after loaded, also contain the loaded item:
|
||||
if (arrayPushed) {
|
||||
if (item.length === 0)
|
||||
return
|
||||
var outElement = replace ? JSArray.pop() : JSArray.current()
|
||||
for (var i=0; i<item.length; ++i)
|
||||
JSArray.push({itemComponent:item[i], loaded: false, index: __depth, properties: properties});
|
||||
} else {
|
||||
outElement = replace ? JSArray.pop() : JSArray.current()
|
||||
JSArray.push({itemComponent:item, loaded: false, index: __depth, properties: properties})
|
||||
}
|
||||
|
||||
var currentElement = JSArray.current()
|
||||
var transition = {
|
||||
inElement: currentElement,
|
||||
outElement: outElement,
|
||||
immediate: immediate,
|
||||
replace: replace,
|
||||
push: true
|
||||
}
|
||||
__performTransition(transition)
|
||||
__recursionGuard(false)
|
||||
return __currentItem
|
||||
}
|
||||
|
||||
/*! \qmlmethod Item StackView::pop(Item item = undefined)
|
||||
Pops one or more items off the stack.
|
||||
|
||||
The function can also take a property list as argument - \c {Item StackView::pop(jsobject dict)},
|
||||
which can contain one or more of the following properties:
|
||||
\list
|
||||
\li \c item: if specified, all items down to (but not including) \a item will be
|
||||
popped off. If \a item is \c null, all items down to (but not including) the
|
||||
first item will be popped. If not specified, only the current item will be
|
||||
popped.
|
||||
\li \c immediate: set this property to \c true to skip transition effects.
|
||||
\endlist
|
||||
|
||||
Examples:
|
||||
\list
|
||||
\li stackView.pop()
|
||||
\li stackView.pop({item:someItem, immediate: true})
|
||||
\li stackView.pop({immediate: true})
|
||||
\li stackView.pop(null)
|
||||
\endlist
|
||||
|
||||
\note If the only argument needed is "item", you can apply the following short-
|
||||
hand notation: \c{stackView.pop(anItem)}.
|
||||
|
||||
Returns the item that was popped off
|
||||
\sa clear()
|
||||
*/
|
||||
function pop(item) {
|
||||
if (__depth <= 1)
|
||||
return null
|
||||
if (item && item.hasOwnProperty("x") === false) {
|
||||
// Property list API used:
|
||||
var immediate = (item.immediate === true)
|
||||
item = item.item
|
||||
} else {
|
||||
immediate = (arguments[1] === true)
|
||||
}
|
||||
|
||||
if (item === __currentItem)
|
||||
return
|
||||
|
||||
if (__recursionGuard(true))
|
||||
return
|
||||
|
||||
var outElement = JSArray.pop()
|
||||
var inElement = JSArray.current()
|
||||
|
||||
if (__depth > 1 && item !== undefined && item !== inElement.item) {
|
||||
// Pop from the top until we find 'item', and return the corresponding
|
||||
// element. Skip all non-loaded items (except the first), since no one
|
||||
// has any references to such items anyway:
|
||||
while (__depth > 1 && !JSArray.current().loaded)
|
||||
JSArray.pop()
|
||||
inElement = JSArray.current()
|
||||
while (__depth > 1 && item !== inElement.item) {
|
||||
JSArray.pop()
|
||||
__cleanup(inElement)
|
||||
while (__depth > 1 && !JSArray.current().loaded)
|
||||
JSArray.pop()
|
||||
inElement = JSArray.current()
|
||||
}
|
||||
}
|
||||
|
||||
var transition = {
|
||||
inElement: inElement,
|
||||
outElement: outElement,
|
||||
immediate: immediate,
|
||||
replace: false,
|
||||
push: false
|
||||
}
|
||||
__performTransition(transition)
|
||||
__recursionGuard(false)
|
||||
return outElement.item;
|
||||
}
|
||||
|
||||
/*! \qmlmethod void StackView::clear()
|
||||
Remove all items from the stack. No animations will be applied. */
|
||||
function clear() {
|
||||
if (__recursionGuard(true))
|
||||
return
|
||||
if (__currentTransition)
|
||||
__currentTransition.animation.complete()
|
||||
__currentItem = null
|
||||
var count = __depth
|
||||
for (var i=0; i<count; ++i) {
|
||||
var element = JSArray.pop()
|
||||
if (element.item)
|
||||
__cleanup(element);
|
||||
}
|
||||
__recursionGuard(false)
|
||||
}
|
||||
|
||||
/*! \qmlmethod Item StackView::find(function, bool onlySearchLoadedItems = false)
|
||||
Search for a specific item inside the stack. \a function will
|
||||
be called for each item in the stack (with the item as argument)
|
||||
until the function returns true. Return value will be the item found. For
|
||||
example:
|
||||
find(function(item, index) { return item.isTheOne })
|
||||
Set \a onlySearchLoadedItems to \c true to not load items that are
|
||||
not loaded into memory */
|
||||
function find(func, onlySearchLoadedItems) {
|
||||
for (var i=__depth-1; i>=0; --i) {
|
||||
var element = JSArray.stackView[i];
|
||||
if (onlySearchLoadedItems !== true)
|
||||
__loadElement(element)
|
||||
else if (!element.item)
|
||||
continue
|
||||
if (func(element.item))
|
||||
return element.item
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/*! \qmlmethod Item StackView::get(int index, bool dontLoad = false)
|
||||
Returns the item at position \a index in
|
||||
the stack. If \a dontLoad is true, the
|
||||
item will not be forced to load (and \c null
|
||||
will be returned if not yet loaded) */
|
||||
function get(index, dontLoad)
|
||||
{
|
||||
if (index < 0 || index >= JSArray.stackView.length)
|
||||
return null
|
||||
var element = JSArray.stackView[index]
|
||||
if (dontLoad !== true) {
|
||||
__loadElement(element)
|
||||
return element.item
|
||||
} else if (element.item) {
|
||||
return element.item
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/*! \qmlmethod void StackView::completeTransition()
|
||||
Immediately completes any ongoing transition.
|
||||
/sa Animation.complete
|
||||
*/
|
||||
function completeTransition()
|
||||
{
|
||||
if (__recursionGuard(true))
|
||||
return
|
||||
if (__currentTransition)
|
||||
__currentTransition.animation.complete()
|
||||
__recursionGuard(false)
|
||||
}
|
||||
|
||||
/********* DEPRECATED API *********/
|
||||
|
||||
/*! \internal
|
||||
\deprecated Use Push() instead */
|
||||
function replace(item, properties, immediate) {
|
||||
push(item, properties, immediate, true)
|
||||
}
|
||||
|
||||
/********* PRIVATE API *********/
|
||||
|
||||
/*! \internal The currently top-most item on the stack. */
|
||||
property Item __currentItem: null
|
||||
/*! \internal The number of items currently pushed onto the stack. */
|
||||
property int __depth: 0
|
||||
/*! \internal Stores the transition info while a transition is ongoing */
|
||||
property var __currentTransition: null
|
||||
/*! \internal Stops the user from pushing items while preparing a transition */
|
||||
property bool __guard: false
|
||||
|
||||
Component.onCompleted: {
|
||||
if (initialItem)
|
||||
push(initialItem)
|
||||
}
|
||||
|
||||
Component.onDestruction: {
|
||||
if (__currentTransition)
|
||||
__currentTransition.animation.complete()
|
||||
__currentItem = null
|
||||
}
|
||||
|
||||
/*! \internal */
|
||||
function __recursionGuard(use)
|
||||
{
|
||||
if (use && __guard) {
|
||||
console.warn("Warning: StackView: You cannot push/pop recursively!")
|
||||
console.trace()
|
||||
return true
|
||||
}
|
||||
__guard = use
|
||||
}
|
||||
|
||||
/*! \internal */
|
||||
function __loadElement(element)
|
||||
{
|
||||
if (element.loaded) {
|
||||
if (!element.item) {
|
||||
element.item = invalidItemReplacement.createObject(root)
|
||||
element.item.text = "\nError: The item has been deleted outside StackView!"
|
||||
}
|
||||
return
|
||||
}
|
||||
if (!element.itemComponent) {
|
||||
element.item = invalidItemReplacement.createObject(root)
|
||||
element.item.text = "\nError: Invalid item (item was 'null'). "
|
||||
+ "This might indicate that the item was deleted outside StackView!"
|
||||
return
|
||||
}
|
||||
|
||||
var comp = __resolveComponent(element.itemComponent, element)
|
||||
|
||||
// Assign properties to item:
|
||||
if (!element.properties)
|
||||
element.properties = {}
|
||||
|
||||
if (comp.hasOwnProperty("createObject")) {
|
||||
if (comp.status === Component.Error) {
|
||||
element.item = invalidItemReplacement.createObject(root)
|
||||
element.item.text = "\nError: Could not load: " + comp.errorString()
|
||||
} else {
|
||||
element.item = comp.createObject(root, element.properties)
|
||||
// Destroy items we create unless the user specified something else:
|
||||
if (!element.hasOwnProperty("destroyOnPop"))
|
||||
element.destroyOnPop = true
|
||||
}
|
||||
} else {
|
||||
// comp is already an Item, so just re-parent it into the StackView:
|
||||
element.item = comp
|
||||
element.originalParent = parent
|
||||
element.item.parent = root
|
||||
for (var prop in element.properties) {
|
||||
if (element.item.hasOwnProperty(prop))
|
||||
element.item[prop] = element.properties[prop];
|
||||
}
|
||||
// Do not destroy items we didn't create, unless the user specified something else:
|
||||
if (!element.hasOwnProperty("destroyOnPop"))
|
||||
element.destroyOnPop = false
|
||||
}
|
||||
|
||||
element.item.Stack.__index = element.index
|
||||
element.item.Stack.__view = root
|
||||
// Let item fill all available space by default:
|
||||
element.item.width = Qt.binding(function() { return root.width })
|
||||
element.item.height = Qt.binding(function() { return root.height })
|
||||
element.loaded = true
|
||||
}
|
||||
|
||||
/*! \internal */
|
||||
function __resolveComponent(unknownObjectType, element)
|
||||
{
|
||||
// We need this extra resolve function since we don't really
|
||||
// know what kind of object the user pushed. So we try to
|
||||
// figure it out by inspecting the object:
|
||||
if (unknownObjectType.hasOwnProperty("createObject")) {
|
||||
return unknownObjectType
|
||||
} else if (typeof unknownObjectType == "string") {
|
||||
return Qt.createComponent(unknownObjectType)
|
||||
} else if (unknownObjectType.hasOwnProperty("x")) {
|
||||
return unknownObjectType
|
||||
} else if (unknownObjectType.hasOwnProperty("item")) {
|
||||
// INVARIANT: user pushed a JS-object
|
||||
element.properties = unknownObjectType.properties
|
||||
if (!unknownObjectType.item)
|
||||
unknownObjectType.item = invalidItemReplacement
|
||||
if (unknownObjectType.hasOwnProperty("destroyOnPop"))
|
||||
element.destroyOnPop = unknownObjectType.destroyOnPop
|
||||
return __resolveComponent(unknownObjectType.item, element)
|
||||
} else {
|
||||
// We cannot determine the type, so assume its a URL:
|
||||
return Qt.createComponent(unknownObjectType)
|
||||
}
|
||||
}
|
||||
|
||||
/*! \internal */
|
||||
function __cleanup(element) {
|
||||
// INVARIANT: element has been removed from JSArray. Destroy its
|
||||
// item, or re-parent it back to the parent it had before it was pushed:
|
||||
var item = element.item
|
||||
if (element.destroyOnPop) {
|
||||
item.destroy()
|
||||
} else {
|
||||
// Mark the item as no longer part of the StackView. It
|
||||
// might reenter on pop if pushed several times:
|
||||
item.visible = false
|
||||
__setStatus(item, Stack.Inactive)
|
||||
item.Stack.__view = null
|
||||
item.Stack.__index = -1
|
||||
if (element.originalParent)
|
||||
item.parent = element.originalParent
|
||||
}
|
||||
}
|
||||
|
||||
/*! \internal */
|
||||
function __setStatus(item, status) {
|
||||
item.Stack.__status = status
|
||||
}
|
||||
|
||||
/*! \internal */
|
||||
function __performTransition(transition)
|
||||
{
|
||||
// Animate item in "outElement" out, and item in "inElement" in. Set a guard to protect
|
||||
// the user from pushing new items on signals that will fire while preparing for the transition
|
||||
// (e.g Stack.onCompleted, Stack.onStatusChanged, Stack.onIndexChanged etc). Otherwise, we will enter
|
||||
// this function several times, which causes the items to be updated half-way.
|
||||
if (__currentTransition)
|
||||
__currentTransition.animation.complete()
|
||||
__loadElement(transition.inElement)
|
||||
|
||||
transition.name = transition.replace ? "replaceTransition" : (transition.push ? "pushTransition" : "popTransition")
|
||||
var enterItem = transition.inElement.item
|
||||
transition.enterItem = enterItem
|
||||
|
||||
// Since an item can be pushed several times, we need to update its properties:
|
||||
enterItem.parent = root
|
||||
enterItem.Stack.__view = root
|
||||
enterItem.Stack.__index = transition.inElement.index
|
||||
__currentItem = enterItem
|
||||
|
||||
if (!transition.outElement) {
|
||||
// A transition consists of two items, but we got just one. So just show the item:
|
||||
enterItem.visible = true
|
||||
__setStatus(enterItem, Stack.Activating)
|
||||
__setStatus(enterItem, Stack.Active)
|
||||
return
|
||||
}
|
||||
|
||||
var exitItem = transition.outElement.item
|
||||
transition.exitItem = exitItem
|
||||
if (enterItem === exitItem)
|
||||
return
|
||||
|
||||
if (root.delegate) {
|
||||
transition.properties = {
|
||||
"name":transition.name,
|
||||
"enterItem":transition.enterItem,
|
||||
"exitItem":transition.exitItem,
|
||||
"immediate":transition.immediate }
|
||||
var anim = root.delegate.getTransition(transition.properties)
|
||||
if (anim.createObject) {
|
||||
anim = anim.createObject(null, transition.properties)
|
||||
anim.runningChanged.connect(function(){ if (anim.running === false) anim.destroy() })
|
||||
}
|
||||
transition.animation = anim
|
||||
}
|
||||
|
||||
if (!transition.animation) {
|
||||
console.warn("Warning: StackView: no", transition.name, "found!")
|
||||
return
|
||||
}
|
||||
if (enterItem.anchors.fill || exitItem.anchors.fill)
|
||||
console.warn("Warning: StackView: cannot transition an item that is anchored!")
|
||||
|
||||
__currentTransition = transition
|
||||
__setStatus(exitItem, Stack.Deactivating)
|
||||
enterItem.visible = true
|
||||
__setStatus(enterItem, Stack.Activating)
|
||||
transition.animation.runningChanged.connect(animationFinished)
|
||||
transition.animation.start()
|
||||
// NB! For empty animations, "animationFinished" is already
|
||||
// executed at this point, leaving __animation === null:
|
||||
if (transition.immediate === true && transition.animation)
|
||||
transition.animation.complete()
|
||||
}
|
||||
|
||||
/*! \internal */
|
||||
function animationFinished()
|
||||
{
|
||||
if (!__currentTransition || __currentTransition.animation.running)
|
||||
return
|
||||
|
||||
__currentTransition.animation.runningChanged.disconnect(animationFinished)
|
||||
__currentTransition.exitItem.visible = false
|
||||
__setStatus(__currentTransition.exitItem, Stack.Inactive);
|
||||
__setStatus(__currentTransition.enterItem, Stack.Active);
|
||||
__currentTransition.properties.animation = __currentTransition.animation
|
||||
root.delegate.transitionFinished(__currentTransition.properties)
|
||||
|
||||
if (!__currentTransition.push || __currentTransition.replace)
|
||||
__cleanup(__currentTransition.outElement)
|
||||
|
||||
__currentTransition = null
|
||||
}
|
||||
|
||||
/*! \internal */
|
||||
property Component invalidItemReplacement: Component {
|
||||
Text {
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user