diff --git a/examples/swipenavigator/main.qml b/examples/swipenavigator/main.qml
new file mode 100644
index 00000000..59db2315
--- /dev/null
+++ b/examples/swipenavigator/main.qml
@@ -0,0 +1,26 @@
+import QtQuick 2.0
+import org.kde.kirigami 2.13 as Kirigami
+
+Kirigami.ApplicationWindow {
+ Kirigami.SwipeNavigator {
+ anchors.fill: parent
+ Kirigami.Page {
+ icon.name: "globe"
+ title: "World Clocks"
+ }
+ Kirigami.Page {
+ icon.name: "clock"
+ title: "Alarms"
+ needsAttention: true
+ }
+ Kirigami.Page {
+ icon.name: "clock"
+ title: "Stopwatch"
+ }
+ Kirigami.Page {
+ icon.name: "clock"
+ title: "Timers"
+ progress: 0.5
+ }
+ }
+}
diff --git a/kirigami.qrc b/kirigami.qrc
index 7437e366..dd41a686 100644
--- a/kirigami.qrc
+++ b/kirigami.qrc
@@ -1,97 +1,104 @@
src/controls/AbstractApplicationWindow.qml
src/controls/ContextDrawer.qml
src/controls/Action.qml
src/controls/Page.qml
src/controls/PageRow.qml
src/controls/AbstractListItem.qml
src/controls/Theme.qml
src/controls/AbstractCard.qml
src/controls/templates/AbstractCard.qml
src/controls/Card.qml
src/controls/CardsLayout.qml
src/controls/CardsListView.qml
src/controls/CardsGridView.qml
src/controls/ActionToolBar.qml
src/controls/templates/InlineMessage.qml
src/controls/InlineMessage.qml
src/controls/ToolBarApplicationHeader.qml
src/controls/ActionTextField.qml
src/controls/SearchField.qml
src/controls/PasswordField.qml
src/controls/private/GlobalDrawerActionItem.qml
src/controls/private/ContextDrawerActionItem.qml
src/controls/private/RefreshableScrollView.qml
src/controls/private/SwipeItemEventFilter.qml
src/controls/private/PageActionPropertyGroup.qml
src/controls/private/ActionIconGroup.qml
src/controls/private/CornerShadow.qml
src/controls/private/ActionButton.qml
src/controls/private/DefaultListItemBackground.qml
src/controls/private/DefaultCardBackground.qml
src/controls/private/BannerImage.qml
src/controls/private/EdgeShadow.qml
src/controls/private/ActionToolBarLayoutDetails.qml
src/controls/private/globaltoolbar/AbstractPageHeader.qml
src/controls/private/globaltoolbar/PageRowGlobalToolBarStyleGroup.qml
src/controls/private/globaltoolbar/PageRowGlobalToolBarUI.qml
src/controls/private/PrivateActionToolButton.qml
src/controls/private/globaltoolbar/TitlesPageHeader.qml
src/controls/private/globaltoolbar/ToolBarPageHeader.qml
src/controls/private/globaltoolbar/BreadcrumbControl.qml
src/controls/private/globaltoolbar/TabBarControl.qml
src/controls/private/ActionsMenu.qml
src/controls/private/ActionMenuItem.qml
src/controls/private/CardsGridViewPrivate.qml
src/controls/private/CardsListViewPrivate.qml
src/controls/Separator.qml
src/controls/OverlayDrawer.qml
src/controls/OverlaySheet.qml
src/controls/GlobalDrawer.qml
src/controls/templates/AbstractListItem.qml
src/controls/templates/private/MenuIcon.qml
src/controls/templates/private/GenericDrawerIcon.qml
src/controls/templates/private/PassiveNotification.qml
src/controls/templates/private/ContextIcon.qml
src/controls/templates/private/ScrollView.qml
src/controls/templates/private/BackButton.qml
src/controls/templates/private/IconPropertiesGroup.qml
src/controls/templates/private/ForwardButton.qml
src/controls/templates/private/BorderPropertiesGroup.qml
src/controls/templates/OverlayDrawer.qml
src/controls/templates/OverlaySheet.qml
src/controls/templates/SwipeListItem.qml
src/controls/templates/ApplicationHeader.qml
src/controls/templates/AbstractApplicationHeader.qml
src/controls/Units.qml
src/controls/SwipeListItem.qml
src/controls/ApplicationWindow.qml
src/controls/AbstractApplicationItem.qml
src/controls/ApplicationItem.qml
src/controls/ApplicationHeader.qml
src/controls/Heading.qml
src/controls/ScrollablePage.qml
src/controls/AboutPage.qml
src/controls/UrlButton.qml
src/controls/LinkButton.qml
src/controls/Label.qml
src/controls/BasicListItem.qml
src/controls/AbstractApplicationHeader.qml
src/controls/FormLayout.qml
src/controls/ListItemDragHandle.qml
src/controls/ShadowedImage.qml
src/controls/Avatar.qml
+ src/controls/swipenavigator/PrivateSwipeHighlight.qml
+ src/controls/swipenavigator/PrivateSwipeProgress.qml
+ src/controls/swipenavigator/PrivateSwipeStack.qml
+ src/controls/swipenavigator/PrivateSwipeTab.qml
+ src/controls/swipenavigator/PrivateSwipeTabBar.qml
+ src/controls/swipenavigator/PrivateSwipeTabBarLoader.qml
+ src/controls/swipenavigator/SwipeNavigator.qml
src/styles/Material/AbstractListItem.qml
src/styles/Material/Theme.qml
src/styles/Material/SwipeListItem.qml
src/styles/Material/Label.qml
src/styles/org.kde.desktop/AbstractListItem.qml
src/styles/org.kde.desktop/Theme.qml
src/styles/org.kde.desktop/Units.qml
src/styles/org.kde.desktop/SwipeListItem.qml
src/styles/org.kde.desktop/ApplicationWindow.qml
src/styles/org.kde.desktop/AbstractApplicationHeader.qml
src/controls/PlaceholderMessage.qml
diff --git a/src/controls/Page.qml b/src/controls/Page.qml
index cd6ad6e5..a78518ff 100644
--- a/src/controls/Page.qml
+++ b/src/controls/Page.qml
@@ -1,405 +1,427 @@
/*
* SPDX-FileCopyrightText: 2015 Marco Martin
*
* SPDX-License-Identifier: LGPL-2.0-or-later
*/
import QtQuick 2.5
import QtQuick.Layouts 1.2
import org.kde.kirigami 2.10 as Kirigami
import "private"
import QtQuick.Templates 2.1 as T2
import QtQuick.Controls 2.1 as QQC2
/**
* Page is a container for all the app pages: everything pushed to the
* ApplicationWindow stackView should be a Page instance (or a subclass,
* such as ScrollablePage)
* @see ScrollablePage
* @inherit QtQuick.Templates.Page
*/
QQC2.Page {
id: root
/**
* leftPadding: int
* default contents padding at left
*/
leftPadding: Kirigami.Units.gridUnit
/**
* topPadding: int
* default contents padding at top
*/
topPadding: Kirigami.Units.gridUnit
/**
* rightPadding: int
* default contents padding at right
*/
rightPadding: Kirigami.Units.gridUnit
/**
* bottomPadding: int
* default contents padding at bottom
*/
bottomPadding: actionButtons.item ? actionButtons.height : Kirigami.Units.gridUnit
/**
* flickable: Flickable
* if the central element of the page is a Flickable
* (ListView and Gridview as well) you can set it there.
* normally, you wouldn't need to do that, but just use the
* ScrollablePage element instead
* @see ScrollablePage
* Use this if your flickable has some non standard properties, such as not covering the whole Page
*/
property Flickable flickable
/**
* actions.contextualActions: list
* Defines the contextual actions for the page:
* an easy way to assign actions in the right sliding panel
*
* Example usage:
* @code
* import org.kde.kirigami 2.4 as Kirigami
*
* Kirigami.ApplicationWindow {
* [...]
* contextDrawer: Kirigami.ContextDrawer {
* id: contextDrawer
* }
* [...]
* }
* @endcode
*
* @code
* import org.kde.kirigami 2.4 as Kirigami
*
* Kirigami.Page {
* [...]
* actions.contextualActions: [
* Kirigami.Action {
* iconName: "edit"
* text: "Action text"
* onTriggered: {
* // do stuff
* }
* },
* Kirigami.Action {
* iconName: "edit"
* text: "Action text"
* onTriggered: {
* // do stuff
* }
* }
* ]
* [...]
* }
* @endcode
*/
//TODO: remove
property alias contextualActions: actionsGroup.contextualActions
/**
* actions.main: Action
* An optional single action for the action button.
* it can be a Kirigami.Action or a QAction
*
* Example usage:
*
* @code
* import org.kde.kirigami 2.4 as Kirigami
* Kirigami.Page {
* actions.main: Kirigami.Action {
* iconName: "edit"
* onTriggered: {
* // do stuff
* }
* }
* }
* @endcode
*/
//TODO: remove
property alias mainAction: actionsGroup.main
/**
* actions.left: Action
* An optional extra action at the left of the main action button.
* it can be a Kirigami.Action or a QAction
*
* Example usage:
*
* @code
* import org.kde.kirigami 2.4 as Kirigami
* Kirigami.Page {
* actions.left: Kirigami.Action {
* iconName: "edit"
* onTriggered: {
* // do stuff
* }
* }
* }
* @endcode
*/
//TODO: remove
property alias leftAction: actionsGroup.left
/**
* actions.right: Action
* An optional extra action at the right of the main action button.
* it can be a Kirigami.Action or a QAction
*
* Example usage:
*
* @code
* import org.kde.kirigami 2.4 as Kirigami
* Kirigami.Page {
* actions.right: Kirigami.Action {
* iconName: "edit"
* onTriggered: {
* // do stuff
* }
* }
* }
* @endcode
*/
//TODO: remove
property alias rightAction: actionsGroup.right
/**
* Actions properties are grouped.
*
* @code
* import org.kde.kirigami 2.4 as Kirigami
* Kirigami.Page {
* actions {
* main: Kirigami.Action {...}
* left: Kirigami.Action {...}
* right: Kirigami.Action {...}
* contextualActions: [
* Kirigami.Action {...},
* Kirigami.Action {...}
* ]
* }
* }
* @endcode
*/
readonly property alias actions: actionsGroup
/**
* contextualActionsAboutToShow: signal
* Emitted when a visualization for the actions is about to be shown,
* such as the toolbar menu or the contextDrawer
* @since 2.7
*/
signal contextualActionsAboutToShow
/**
* isCurrentPage: bool
*
* Specifies if it's the currently selected page in the window's pages row.
*
* @since 2.1
*/
readonly property bool isCurrentPage: Kirigami.ColumnView.view ? Kirigami.ColumnView.index == Kirigami.ColumnView.view.currentIndex : true
/**
* overlay: Item
* an item which stays on top of every other item in the page,
* if you want to make sure some elements are completely in a
* layer on top of the whole content, parent items to this one.
* It's a "local" version of ApplicationWindow's overlay
* @since 2.5
*/
readonly property alias overlay: overlayItem
+ /**
+ * icon: variant
+ *
+ * The icon that represents this page.
+ */
+ property ActionIconGroup icon: ActionIconGroup {}
+
+ /**
+ * needsAttention: bool
+ *
+ * Whether this page needs user attention.
+ */
+ property bool needsAttention
+
+ /**
+ * progress: real
+ *
+ * Progress of a task this page is doing. Set to undefined to indicate
+ * that there are no ongoing tasks.
+ */
+ property var progress: undefined
+
/**
* titleDelegate: Component
* The delegate which will be used to draw the page title. It can be customized to put any kind of Item in there.
* @since 2.7
*/
property Component titleDelegate: Kirigami.Heading {
id: title
level: 1
Layout.fillWidth: true
Layout.maximumWidth: implicitWidth + 1 // The +1 is to make sure we do not trigger eliding at max width
Layout.minimumWidth: 0
opacity: root.isCurrentPage ? 1 : 0.4
maximumLineCount: 1
elide: Text.ElideRight
text: root.title
}
/**
* emitted When the application requests a Back action
* For instance a global "back" shortcut or the Android
* Back button has been pressed.
* The page can manage the back event by itself,
* and if it set event.accepted = true, it will stop the main
* application to manage the back event.
*/
signal backRequested(var event);
// Look for sheets and cose them
//FIXME: port Sheets to Popup?
onBackRequested: {
for(var i in root.resources) {
var item = root.resources[i];
if (item.hasOwnProperty("close") && item.hasOwnProperty("sheetOpen") && item.sheetOpen) {
item.close()
event.accepted = true;
return;
}
}
}
/**
* globalToolBarItem: Item
* The item used as global toolbar for the page
* present only if we are in a PageRow as a page or as a layer,
* and the style is either Titles or ToolBar
* @since 2.5
*/
readonly property Item globalToolBarItem: globalToolBar.item
/**
* The style for the automatically generated global toolbar: by default the Page toolbar is the one set globally in the PageRow in its globalToolBar.style property.
* A single page can override the application toolbar style for itself.
* It is discouraged to use this, except very specific exceptions, like a chat
* application which can't have controls on the bottom except the text field.
*/
property int globalToolBarStyle: {
if (globalToolBar.row && !globalToolBar.stack) {
return globalToolBar.row.globalToolBar.actualStyle;
} else if (globalToolBar.stack) {
return Kirigami.Settings.isMobile ? Kirigami.ApplicationHeaderStyle.Titles : Kirigami.ApplicationHeaderStyle.ToolBar;
} else {
return Kirigami.ApplicationHeaderStyle.None;
}
}
//NOTE: contentItem will be created if not existing (and contentChildren of Page would become its children) This with anchors enforces the geometry we want, where globalToolBar is a super-header, on top of header
contentItem: Item {
anchors {
top: root.header
? root.header.bottom
: (globalToolBar.visible ? globalToolBar.bottom : parent.top)
topMargin: root.topPadding + root.spacing
bottom: root.footer ? root.footer.top : parent.bottom
bottomMargin: root.bottomPadding + root.spacing
}
}
background: Rectangle {
color: Kirigami.Theme.backgroundColor
}
implicitHeight: (header ? header.implicitHeight : 0) + (footer ? footer.implicitHeight : 0) + contentItem.implicitHeight + topPadding + bottomPadding
implicitWidth: contentItem.implicitWidth + leftPadding + rightPadding
//FIXME: on material the shadow would bleed over
clip: root.header != null;
onHeaderChanged: {
if (header) {
header.anchors.top = Qt.binding(function() {return globalToolBar.visible ? globalToolBar.bottom : root.top});
}
}
Component.onCompleted: {
headerChanged();
parentChanged(root.parent);
}
onParentChanged: {
if (!parent) {
return;
}
globalToolBar.stack = null;
globalToolBar.row = null;
if (root.Kirigami.ColumnView.view) {
globalToolBar.row = root.Kirigami.ColumnView.view.__pageRow;
}
if (root.T2.StackView.view) {
globalToolBar.stack = root.T2.StackView.view;
globalToolBar.row = root.T2.StackView.view ? root.T2.StackView.view.parent : null;
}
if (globalToolBar.row) {
root.globalToolBarStyleChanged.connect(globalToolBar.syncSource);
globalToolBar.syncSource();
}
}
//in data in order for them to not be considered for contentItem, contentChildren, contentData
data: [
PageActionPropertyGroup {
id: actionsGroup
},
Item {
id: overlayItem
parent: root
z: 9997
anchors {
fill: parent
topMargin: globalToolBar.height
}
},
//global top toolbar if we are in a PageRow (in the row or as a layer)
Loader {
id: globalToolBar
z: 9999
height: item ? item.implicitHeight : 0
anchors {
left: parent.left
right: parent.right
top: parent.top
}
property Kirigami.PageRow row
property T2.StackView stack
visible: active
active: (row || stack) && (root.globalToolBarStyle === Kirigami.ApplicationHeaderStyle.ToolBar || root.globalToolBarStyle == Kirigami.ApplicationHeaderStyle.Titles)
function syncSource() {
if (row && active) {
setSource(Qt.resolvedUrl(root.globalToolBarStyle === Kirigami.ApplicationHeaderStyle.ToolBar ? "private/globaltoolbar/ToolBarPageHeader.qml" : "private/globaltoolbar/TitlesPageHeader.qml"),
//TODO: find container reliably, remove assumption
{"pageRow": Qt.binding(function() {return row}),
"page": root,
"current": Qt.binding(function() {return stack || row.currentIndex === root.Kirigami.ColumnView.level})});
}
}
},
//bottom action buttons
Loader {
id: actionButtons
z: 9999
parent: root
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
}
//if the page doesn't inherit, assume it has custom colors we want to use them here too
Kirigami.Theme.inherit: !root.Kirigami.Theme.inherit
Kirigami.Theme.colorSet: Kirigami.Theme.Button
//It should be T2.Page, Qt 5.7 doesn't like it
property Item page: root
height: item ? item.implicitHeight : 0
active: typeof applicationWindow !== "undefined" && (!globalToolBar.row || root.globalToolBarStyle !== Kirigami.ApplicationHeaderStyle.ToolBar) &&
root.actions && (root.actions.main || root.actions.left || root.actions.right || root.actions.contextualActions.length) &&
//Legacy
(typeof applicationWindow === "undefined" ||
(!applicationWindow().header || applicationWindow().header.toString().indexOf("ToolBarApplicationHeader") === -1) &&
(!applicationWindow().footer || applicationWindow().footer.toString().indexOf("ToolBarApplicationHeader") === -1))
source: Qt.resolvedUrl("./private/ActionButton.qml")
}
]
Layout.fillWidth: true
}
diff --git a/src/controls/swipenavigator/PrivateSwipeHighlight.qml b/src/controls/swipenavigator/PrivateSwipeHighlight.qml
new file mode 100644
index 00000000..087ae4d0
--- /dev/null
+++ b/src/controls/swipenavigator/PrivateSwipeHighlight.qml
@@ -0,0 +1,33 @@
+/*
+ * SPDX-FileCopyrightText: 2020 Carson Black
+ *
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+import QtQuick 2.12
+import QtQuick.Layouts 1.12
+import QtQuick.Controls 2.12
+import org.kde.kirigami 2.12 as Kirigami
+
+Rectangle {
+ Accessible.ignored: true
+
+ anchors {
+ bottom: Kirigami.Settings.isMobile ? undefined : parent.bottom
+ top: Kirigami.Settings.isMobile ? parent.top : undefined
+ left: parent.left
+ right: parent.right
+ }
+
+ color: {
+ if (state == "highlighted") {
+ return Kirigami.Theme.activeTextColor
+ } else if (state == "requestingAttention") {
+ return Kirigami.Theme.negativeTextColor
+ }
+ return "transparent"
+ }
+
+ // Unlike most things, we don't want to scale with the em grid, so we don't use a Unit.
+ height: 2
+}
\ No newline at end of file
diff --git a/src/controls/swipenavigator/PrivateSwipeProgress.qml b/src/controls/swipenavigator/PrivateSwipeProgress.qml
new file mode 100644
index 00000000..d3aaf050
--- /dev/null
+++ b/src/controls/swipenavigator/PrivateSwipeProgress.qml
@@ -0,0 +1,68 @@
+/*
+ * SPDX-FileCopyrightText: 2020 Carson Black
+ *
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+import QtQuick 2.12
+import QtQuick.Layouts 1.12
+import QtQuick.Controls 2.12
+import org.kde.kirigami 2.12 as Kirigami
+
+Item {
+ id: __progressRoot
+ property var progress
+
+ Rectangle {
+ Accessible.ignored: true
+
+ anchors {
+ top: parent.top
+ bottom: parent.bottom
+ left: parent.left
+ }
+ width: parent.width * __progressRoot.progress
+ color: Kirigami.ColorUtils.adjustColor(Kirigami.Theme.positiveTextColor, {"alpha": 0.2*255})
+
+ Rectangle {
+ anchors {
+ bottom: Kirigami.Settings.isMobile ? undefined : parent.bottom
+ top: Kirigami.Settings.isMobile ? parent.top : undefined
+ left: parent.left
+ right: parent.right
+ }
+
+ color: Kirigami.Theme.positiveTextColor
+
+ // Unlike most things, we don't want to scale with the em grid, so we don't use a Unit.
+ height: 2
+ }
+ }
+
+
+ Rectangle {
+ Accessible.ignored: true
+
+ anchors {
+ top: parent.top
+ bottom: parent.bottom
+ right: parent.right
+ }
+ width: parent.width - (parent.width * __progressRoot.progress)
+ color: Kirigami.ColorUtils.adjustColor(Kirigami.Theme.textColor, {"alpha": 0.1*255})
+
+ Rectangle {
+ anchors {
+ bottom: Kirigami.Settings.isMobile ? undefined : parent.bottom
+ top: Kirigami.Settings.isMobile ? parent.top : undefined
+ left: parent.left
+ right: parent.right
+ }
+
+ color: Kirigami.ColorUtils.adjustColor(Kirigami.Theme.textColor, {"alpha": 0.1*255})
+
+ // Unlike most things, we don't want to scale with the em grid, so we don't use a Unit.
+ height: 2
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/controls/swipenavigator/PrivateSwipeStack.qml b/src/controls/swipenavigator/PrivateSwipeStack.qml
new file mode 100644
index 00000000..76f8e9c2
--- /dev/null
+++ b/src/controls/swipenavigator/PrivateSwipeStack.qml
@@ -0,0 +1,100 @@
+/*
+ * SPDX-FileCopyrightText: 2020 Carson Black
+ *
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+import QtQuick 2.12
+import QtQuick.Layouts 1.12
+import QtQuick.Controls 2.12
+import org.kde.kirigami 2.12 as Kirigami
+
+StackView {
+ popEnter: Transition {
+ OpacityAnimator {
+ from: 0
+ to: 1
+ duration: Kirigami.Units.longDuration
+ easing.type: Easing.InOutCubic
+ }
+ }
+ popExit: Transition {
+ ParallelAnimation {
+ OpacityAnimator {
+ from: 1
+ to: 0
+ duration: Kirigami.Units.longDuration
+ easing.type: Easing.InOutCubic
+ }
+ YAnimator {
+ from: 0
+ to: height/2
+ duration: Kirigami.Units.longDuration
+ easing.type: Easing.InCubic
+ }
+ }
+ }
+
+ pushEnter: Transition {
+ ParallelAnimation {
+ //NOTE: It's a PropertyAnimation instead of an Animator because with an animator the item will be visible for an instant before starting to fade
+ PropertyAnimation {
+ property: "opacity"
+ from: 0
+ to: 1
+ duration: Kirigami.Units.longDuration
+ easing.type: Easing.InOutCubic
+ }
+ YAnimator {
+ from: height/2
+ to: 0
+ duration: Kirigami.Units.longDuration
+ easing.type: Easing.OutCubic
+ }
+ }
+ }
+
+
+ pushExit: Transition {
+ OpacityAnimator {
+ from: 1
+ to: 0
+ duration: Kirigami.Units.longDuration
+ easing.type: Easing.InOutCubic
+ }
+ }
+
+ replaceEnter: Transition {
+ ParallelAnimation {
+ OpacityAnimator {
+ from: 0
+ to: 1
+ duration: Kirigami.Units.longDuration
+ easing.type: Easing.InOutCubic
+ }
+ YAnimator {
+ from: height/2
+ to: 0
+ duration: Kirigami.Units.longDuration
+ easing.type: Easing.OutCubic
+ }
+ }
+ }
+
+ replaceExit: Transition {
+ ParallelAnimation {
+ OpacityAnimator {
+ from: 1
+ to: 0
+ duration: Kirigami.Units.longDuration
+ easing.type: Easing.InCubic
+ }
+ YAnimator {
+ from: 0
+ to: -height/2
+ duration: Kirigami.Units.longDuration
+ easing.type: Easing.InOutCubic
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/controls/swipenavigator/PrivateSwipeTab.qml b/src/controls/swipenavigator/PrivateSwipeTab.qml
new file mode 100644
index 00000000..3e0efc05
--- /dev/null
+++ b/src/controls/swipenavigator/PrivateSwipeTab.qml
@@ -0,0 +1,160 @@
+/*
+ * SPDX-FileCopyrightText: 2020 Carson Black
+ *
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+import QtQuick 2.12
+import QtQuick.Layouts 1.12
+import QtQuick.Controls 2.12
+import org.kde.kirigami 2.12 as Kirigami
+
+Rectangle {
+ id: tabRoot
+ property bool small: false
+ signal indexChanged(real xPos, real tabWidth)
+
+ Keys.onPressed: {
+ if (event.key == Qt.Key_Enter || event.key == Qt.Key_Return) {
+ columnView.currentIndex = index
+ }
+ }
+ activeFocusOnTab: true
+ implicitHeight: swipeNavigatorRoot.big
+ ? small ? Kirigami.Units.gridUnit*5 : Kirigami.Units.gridUnit*4
+ : small ? Kirigami.Units.gridUnit*3 : Kirigami.Units.gridUnit*2
+
+ onActiveFocusChanged: {
+ if (activeFocus) {
+ tabRoot.indexChanged(tabRoot.x, tabRoot.width)
+ }
+ }
+ Connections {
+ target: columnView
+ function onCurrentIndexChanged() {
+ if (index == columnView.currentIndex) {
+ tabRoot.indexChanged(tabRoot.x, tabRoot.width)
+ }
+ }
+ }
+
+ Accessible.name: modelData.title
+ Accessible.description: {
+ if (!!modelData.progress) {
+ if (index == columnView.currentIndex) {
+ return i18nc("Accessibility text for a page tab. Keep the text as concise as possible and don't use a percent sign.", "Current page. Progress: %1 percent.", Math.round(modelData.progress*100))
+ } else {
+ return i18nc("Accessibility text for a page tab. Keep the text as concise as possible.", "Navigate to %1. Progress: %1 percent.", modelData.title, Math.round(modelData.progress*100))
+ }
+ } else {
+ if (index == columnView.currentIndex) {
+ return i18nc("Accessibility text for a page tab. Keep the text as concise as possible.", "Current page.")
+ } else if (modelData.needsAttention) {
+ return i18nc("Accessibility text for a page tab that's requesting the user's attention. Keep the text as concise as possible.", "Navigate to %1. Demanding attention.", modelData.title)
+ } else {
+ return i18nc("Accessibility text for a page tab that's requesting the user's attention. Keep the text as concise as possible.", "Navigate to %1.", modelData.title)
+ }
+ }
+ }
+ Accessible.role: Accessible.PageTab
+ Accessible.focusable: true
+ Accessible.onPressAction: columnView.currentIndex = index
+
+ implicitWidth: small ? smallTitleRow.implicitWidth : largeTitleRow.implicitWidth
+ border {
+ width: activeFocus ? 2 : 0
+ color: Kirigami.Theme.textColor
+ }
+ color: {
+ if (index == columnView.currentIndex) {
+ return Kirigami.ColorUtils.adjustColor(Kirigami.Theme.activeTextColor, {"alpha": 0.2*255})
+ } else if (modelData.needsAttention) {
+ return Kirigami.ColorUtils.adjustColor(Kirigami.Theme.negativeTextColor, {"alpha": 0.2*255})
+ } else {
+ return "transparent"
+ }
+ }
+
+ PrivateSwipeHighlight {
+ states: [
+ State { name: "highlighted"; when: index == columnView.currentIndex },
+ State { name: "requestingAttention"; when: modelData.needsAttention }
+ ]
+ }
+
+ PrivateSwipeProgress {
+ anchors.fill: parent
+ visible: modelData.progress != undefined
+ progress: modelData.progress
+ }
+
+ RowLayout {
+ id: smallTitleRow
+ anchors.fill: parent
+ Accessible.ignored: true
+ visible: small
+
+ ColumnLayout {
+ Layout.margins: Kirigami.Settings.isMobile ? Kirigami.Units.smallSpacing : Kirigami.Units.largeSpacing
+ Layout.alignment: Qt.AlignVCenter
+
+ Kirigami.Icon {
+ visible: !!modelData.icon.name
+ source: modelData.icon.name
+
+ Layout.preferredHeight: swipeNavigatorRoot.big ? Kirigami.Units.iconSizes.medium : Kirigami.Units.iconSizes.small
+ Layout.preferredWidth: Layout.preferredHeight
+
+ Layout.alignment: (Qt.AlignHCenter | Qt.AlignBottom)
+ }
+ Kirigami.Heading {
+ level: swipeNavigatorRoot.big ? 2 : 5
+ text: modelData.title
+
+ Layout.fillWidth: true
+ Layout.alignment: (Qt.AlignLeft | Qt.AlignVCenter)
+ }
+ }
+ }
+
+ RowLayout {
+ id: largeTitleRow
+ anchors.fill: parent
+ Accessible.ignored: true
+ visible: !small
+
+ RowLayout {
+ Layout.margins: swipeNavigatorRoot.big ? Kirigami.Units.largeSpacing*2 : Kirigami.Units.largeSpacing
+ Layout.alignment: Qt.AlignVCenter
+
+ Kirigami.Icon {
+ visible: !!modelData.icon.name
+ source: modelData.icon.name
+
+ Layout.preferredHeight: swipeNavigatorRoot.big ? Kirigami.Units.iconSizes.medium : Kirigami.Units.iconSizes.small
+ Layout.preferredWidth: Layout.preferredHeight
+
+ Layout.alignment: (Qt.AlignLeft | Qt.AlignVCenter)
+ }
+ Kirigami.Heading {
+ level: swipeNavigatorRoot.big ? 1 : 2
+ text: modelData.title
+
+ Layout.fillWidth: true
+ Layout.alignment: (Qt.AlignLeft | Qt.AlignVCenter)
+ }
+ }
+ }
+
+ MouseArea {
+ id: mouse
+ anchors.fill: parent
+ Accessible.ignored: true
+ onClicked: {
+ columnView.currentIndex = index
+ }
+ }
+
+ Layout.fillHeight: true
+ Layout.alignment: Qt.AlignHCenter
+}
\ No newline at end of file
diff --git a/src/controls/swipenavigator/PrivateSwipeTabBar.qml b/src/controls/swipenavigator/PrivateSwipeTabBar.qml
new file mode 100644
index 00000000..bd05d9b0
--- /dev/null
+++ b/src/controls/swipenavigator/PrivateSwipeTabBar.qml
@@ -0,0 +1,36 @@
+/*
+ * SPDX-FileCopyrightText: 2020 Carson Black
+ *
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+import QtQuick 2.12
+import QtQuick.Layouts 1.12
+import QtQuick.Controls 2.12
+import org.kde.kirigami 2.12 as Kirigami
+
+RowLayout {
+ id: swipeTabBarRoot
+ spacing: 0
+ signal indexChanged(real xPos, real tabWidth)
+
+ property Item layouter: Item {
+ Row {
+ id: expandedLayouter
+ Repeater {
+ model: swipeNavigatorRoot.pages
+ delegate: PrivateSwipeTab { small: false }
+ }
+ }
+ }
+
+ Repeater {
+ model: swipeNavigatorRoot.pages
+ delegate: PrivateSwipeTab {
+ Layout.fillHeight: true
+ Layout.alignment: Qt.AlignHCenter
+ small: expandedLayouter.width > swipeNavigatorRoot.width
+ onIndexChanged: swipeTabBarRoot.indexChanged(xPos, tabWidth)
+ }
+ }
+}
diff --git a/src/controls/swipenavigator/PrivateSwipeTabBarLoader.qml b/src/controls/swipenavigator/PrivateSwipeTabBarLoader.qml
new file mode 100644
index 00000000..471d52d5
--- /dev/null
+++ b/src/controls/swipenavigator/PrivateSwipeTabBarLoader.qml
@@ -0,0 +1,62 @@
+/*
+ * SPDX-FileCopyrightText: 2020 Carson Black
+ *
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+import QtQuick 2.12
+import QtQuick.Layouts 1.12
+import QtQuick.Controls 2.12
+import org.kde.kirigami 2.12 as Kirigami
+
+Loader {
+ id: __loader
+ readonly property bool shouldScroll: shrunkLayouter.width > swipeNavigatorRoot.width
+ property Item layouter: Item {
+ Row {
+ id: shrunkLayouter
+ Repeater {
+ model: swipeNavigatorRoot.pages
+ delegate: PrivateSwipeTab { small: true }
+ }
+ }
+ }
+ Component {
+ id: nonScrollable
+ PrivateSwipeTabBar {}
+ }
+ Component {
+ id: scrollable
+ ScrollView {
+ id: view
+ ScrollBar.horizontal.visible: false
+ Timer {
+ interval: 5000
+ running: true
+ repeat: true
+ }
+ PrivateSwipeTabBar {
+ id: bar
+ property real targetDestination
+ NumberAnimation {
+ id: scrollAni
+ target: view.ScrollBar.horizontal
+ property: "position"
+ to: bar.targetDestination
+ duration: Kirigami.Units.longDuration
+ easing.type: Easing.OutExpo
+ }
+ onIndexChanged: {
+ if (xPos > (bar.width)/2) {
+ bar.targetDestination = (1-view.ScrollBar.horizontal.size) * ((xPos+tabWidth) / bar.width)
+ scrollAni.restart()
+ } else {
+ bar.targetDestination = (1-view.ScrollBar.horizontal.size) * ((xPos) / bar.width)
+ scrollAni.restart()
+ }
+ }
+ }
+ }
+ }
+ sourceComponent: shouldScroll ? scrollable : nonScrollable
+}
\ No newline at end of file
diff --git a/src/controls/swipenavigator/SwipeNavigator.qml b/src/controls/swipenavigator/SwipeNavigator.qml
new file mode 100644
index 00000000..1170fbc8
--- /dev/null
+++ b/src/controls/swipenavigator/SwipeNavigator.qml
@@ -0,0 +1,185 @@
+/*
+ * SPDX-FileCopyrightText: 2020 Carson Black
+ *
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+import QtQuick 2.12
+import QtQuick.Layouts 1.12
+import QtQuick.Controls 2.12
+import org.kde.kirigami 2.13 as Kirigami
+
+/**
+ * SwipeNavigator is a control providing for lateral navigation.
+ *
+ * @include swipenavigator/main.qml
+ */
+GridLayout {
+ id: swipeNavigatorRoot
+ rowSpacing: 0
+ columns: 1
+
+ /**
+ * pages: list
+ *
+ * A list of pages to swipe between.
+ */
+ default property list pages
+
+ /**
+ * layers: StackView
+ *
+ * The StackView holding the core item, allowing users of a SwipeNavigator
+ * in order to push pages on top of the SwipeNavigator.
+ */
+ property alias layers: stackView
+
+ /**
+ * big: bool
+ *
+ * Whether or not to present the SwipeNavigator in a larger format
+ * suitable for rendering on televisions.
+ */
+ property bool big: false
+
+ /**
+ * header: Item
+ *
+ * The item that will be displayed before the tabs.
+ */
+ property Component header: Item {visible: false}
+
+ /**
+ * footer: Item
+ *
+ * The item that will be displayed after the tabs.
+ */
+ property Component footer: Item {visible: false}
+
+ QtObject {
+ id: _gridManager
+ readonly property bool tall: (_header.width + __main.item.width + Math.abs(__main.offset) + _footer.width) > swipeNavigatorRoot.width
+ readonly property int rowOne: Kirigami.Settings.isMobile ? 1 : 0
+ readonly property int rowTwo: Kirigami.Settings.isMobile ? 0 : 1
+ readonly property int rowDirection: Kirigami.Settings.isMobile ? 1 : -1
+ property Item item: Item {
+ states: [
+ State {
+ name: "small"
+ when: !_gridManager.tall
+ },
+ State {
+ name: "tall"
+ when: _gridManager.tall
+ }
+ ]
+ transitions: [
+ Transition {
+ to: "tall"
+ ScriptAction {
+ script: {
+ // Let's take these out of the layout first...
+ _dummyOne.visible = false
+ _dummyTwo.visible = false
+ // Now we move the header and footer up
+ _header.Layout.row += _gridManager.rowDirection
+ _footer.Layout.row += _gridManager.rowDirection
+ // Now that the header and footer are out of the way,
+ // let's expand the tabs
+ __main.Layout.column--
+ __main.Layout.columnSpan = 3
+ }
+ }
+ },
+ Transition {
+ to: "small"
+ ScriptAction {
+ script: {
+ // Let's move the tabs back to where they belong
+ __main.Layout.columnSpan = 1
+ __main.Layout.column++
+ // Move the header and footer down into the empty space
+ _header.Layout.row -= _gridManager.rowDirection
+ _footer.Layout.row -= _gridManager.rowDirection
+ // Now we can bring these guys back in
+ _dummyOne.visible = false
+ _dummyTwo.visible = false
+ }
+ }
+ }
+ ]
+ }
+ }
+
+ ToolBar {
+ id: topToolBar
+
+ padding: 0
+ bottomPadding: 1
+ position: Kirigami.Settings.isMobile ? ToolBar.Footer : ToolBar.Header
+
+ Layout.row: Kirigami.Settings.isMobile ? 1 : 0
+
+ GridLayout {
+ id: _grid
+
+ rowSpacing: 0
+ columnSpacing: 0
+ anchors.fill: parent
+ rows: 2
+ columns: 3
+
+ // Row one
+ Item { id: _spacer; Layout.row: 0; Layout.column: 1; Layout.fillWidth: true }
+ Item { id: _dummyOne; Layout.row: 0; Layout.column: 0 }
+ Item { id: _dummyTwo; Layout.row: 0; Layout.column: 2 }
+
+ // Row two
+ Loader { id: _header; sourceComponent: swipeNavigatorRoot.header; Layout.row: 1; Layout.column: 0 }
+ PrivateSwipeTabBarLoader {
+ id: __main
+ readonly property int offset: _header.width - _footer.width
+ readonly property int effectiveOffset: _gridManager.tall ? 0 : offset
+ Layout.rightMargin: effectiveOffset > 0 ? effectiveOffset : 0
+ Layout.leftMargin: effectiveOffset < 0 ? -effectiveOffset : 0
+ Layout.fillHeight: true
+ Layout.alignment: Qt.AlignHCenter
+ Layout.row: 1
+ Layout.column: 1
+ states: [
+ State {
+ name: "shouldScroll"
+ when: __main.shouldScroll
+ PropertyChanges { target: __main; Layout.fillWidth: true }
+ }
+ ]
+ }
+ Loader { id: _footer; sourceComponent: swipeNavigatorRoot.footer; Layout.row: 1; Layout.column: 2 }
+ }
+
+ Layout.fillWidth: true
+
+ Accessible.role: Accessible.PageTabList
+ }
+
+ StackView {
+ id: stackView
+
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ Layout.row: Kirigami.Settings.isMobile ? 0 : 1
+
+ Kirigami.ColumnView {
+ id: columnView
+ columnResizeMode: Kirigami.ColumnView.SingleColumn
+
+ contentChildren: swipeNavigatorRoot.pages
+ anchors.fill: parent
+
+ Component.onCompleted: {
+ columnView.currentIndex = 0
+ }
+ }
+ }
+}
diff --git a/src/kirigamiplugin.cpp b/src/kirigamiplugin.cpp
index 5753ef5d..acdefbc4 100644
--- a/src/kirigamiplugin.cpp
+++ b/src/kirigamiplugin.cpp
@@ -1,274 +1,275 @@
/*
* SPDX-FileCopyrightText: 2009 Alan Alpert
* SPDX-FileCopyrightText: 2010 Ménard Alexis
* SPDX-FileCopyrightText: 2010 Marco Martin
*
* SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "kirigamiplugin.h"
#include "columnview.h"
#include "enums.h"
#include "icon.h"
#include "settings.h"
#include "formlayoutattached.h"
#include "mnemonicattached.h"
#include "delegaterecycler.h"
#include "pagepool.h"
#include "scenepositionattached.h"
#include "wheelhandler.h"
#include "shadowedrectangle.h"
#include "shadowedtexture.h"
#include "colorutils.h"
#include "pagerouter.h"
#include "imagecolors.h"
#include "avatar.h"
#include
#include
#include
#include
#include
#include
#include "libkirigami/platformtheme.h"
static QString s_selectedStyle;
//Q_INIT_RESOURCE(kirigami);
#ifdef KIRIGAMI_BUILD_TYPE_STATIC
#include
#endif
class CopyHelperPrivate : public QObject
{
Q_OBJECT
public:
Q_INVOKABLE static void copyTextToClipboard(const QString& text)
{
qGuiApp->clipboard()->setText(text);
}
};
// we can't do this in the plugin object directly, as that can live in a different thread
// and event filters are only allowed in the same thread as the filtered object
class LanguageChangeEventFilter : public QObject
{
Q_OBJECT
public:
bool eventFilter(QObject *receiver, QEvent *event) override
{
if (event->type() == QEvent::LanguageChange && receiver == QCoreApplication::instance()) {
emit languageChangeEvent();
}
return QObject::eventFilter(receiver, event);
}
Q_SIGNALS:
void languageChangeEvent();
};
KirigamiPlugin::KirigamiPlugin(QObject *parent)
: QQmlExtensionPlugin(parent)
{
auto filter = new LanguageChangeEventFilter;
filter->moveToThread(QCoreApplication::instance()->thread());
QCoreApplication::instance()->installEventFilter(filter);
connect(filter, &LanguageChangeEventFilter::languageChangeEvent, this, &KirigamiPlugin::languageChangeEvent);
}
QUrl KirigamiPlugin::componentUrl(const QString &fileName) const
{
for (const QString &style : qAsConst(m_stylesFallbackChain)) {
const QString candidate = QStringLiteral("styles/") + style + QLatin1Char('/') + fileName;
if (QFile::exists(resolveFilePath(candidate))) {
#ifdef KIRIGAMI_BUILD_TYPE_STATIC
return QUrl(QStringLiteral("qrc:/org/kde/kirigami/styles/") + style + QLatin1Char('/') + fileName);
#else
return QUrl(resolveFileUrl(candidate));
#endif
}
}
#ifdef KIRIGAMI_BUILD_TYPE_STATIC
return QUrl(QStringLiteral("qrc:/org/kde/kirigami/") + fileName);
#else
return QUrl(resolveFileUrl(fileName));
#endif
}
void KirigamiPlugin::registerTypes(const char *uri)
{
#if defined(Q_OS_ANDROID) && QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
QResource::registerResource(QStringLiteral("assets:/android_rcc_bundle.rcc"));
#endif
Q_ASSERT(QLatin1String(uri) == QLatin1String("org.kde.kirigami"));
const QString style = QQuickStyle::name();
if (QIcon::themeName().isEmpty() && !qEnvironmentVariableIsSet("XDG_CURRENT_DESKTOP")) {
QIcon::setThemeSearchPaths({resolveFilePath(QStringLiteral(".")), QStringLiteral(":/icons")});
QIcon::setThemeName(QStringLiteral("breeze-internal"));
}
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
//org.kde.desktop.plasma is a couple of files that fall back to desktop by purpose
if ((style.isEmpty() || style == QStringLiteral("org.kde.desktop.plasma")) && QFile::exists(resolveFilePath(QStringLiteral("/styles/org.kde.desktop")))) {
m_stylesFallbackChain.prepend(QStringLiteral("org.kde.desktop"));
}
#elif defined(Q_OS_ANDROID)
if (!m_stylesFallbackChain.contains(QLatin1String("Material"))) {
m_stylesFallbackChain.prepend(QStringLiteral("Material"));
}
#else // do we have an iOS specific style?
if (!m_stylesFallbackChain.contains(QLatin1String("Material"))) {
m_stylesFallbackChain.prepend(QStringLiteral("Material"));
}
#endif
if (!style.isEmpty() && QFile::exists(resolveFilePath(QStringLiteral("/styles/") + style)) && !m_stylesFallbackChain.contains(style)) {
m_stylesFallbackChain.prepend(style);
//if we have plasma deps installed, use them for extra integration
if (style == QStringLiteral("org.kde.desktop") && QFile::exists(resolveFilePath(QStringLiteral("/styles/org.kde.desktop.plasma")))) {
m_stylesFallbackChain.prepend(QStringLiteral("org.kde.desktop.plasma"));
}
} else {
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
m_stylesFallbackChain.prepend(QStringLiteral("org.kde.desktop"));
#endif
}
//At this point the fallback chain will be selected->org.kde.desktop->Fallback
s_selectedStyle = m_stylesFallbackChain.first();
qmlRegisterSingletonType(uri, 2, 0, "Settings",
[](QQmlEngine *e, QJSEngine*) -> QObject* {
Settings *settings = Settings::self();
//singleton managed internally, qml should never delete it
e->setObjectOwnership(settings, QQmlEngine::CppOwnership);
settings->setStyle(s_selectedStyle);
return settings;
}
);
qmlRegisterUncreatableType(uri, 2, 0, "ApplicationHeaderStyle", QStringLiteral("Cannot create objects of type ApplicationHeaderStyle"));
//old legacy retrocompatible Theme
qmlRegisterSingletonType(componentUrl(QStringLiteral("Theme.qml")), uri, 2, 0, "Theme");
qmlRegisterSingletonType(componentUrl(QStringLiteral("Units.qml")), uri, 2, 0, "Units");
qmlRegisterType(componentUrl(QStringLiteral("Action.qml")), uri, 2, 0, "Action");
qmlRegisterType(componentUrl(QStringLiteral("AbstractApplicationHeader.qml")), uri, 2, 0, "AbstractApplicationHeader");
qmlRegisterType(componentUrl(QStringLiteral("AbstractApplicationWindow.qml")), uri, 2, 0, "AbstractApplicationWindow");
qmlRegisterType(componentUrl(QStringLiteral("AbstractListItem.qml")), uri, 2, 0, "AbstractListItem");
qmlRegisterType(componentUrl(QStringLiteral("ApplicationHeader.qml")), uri, 2, 0, "ApplicationHeader");
qmlRegisterType(componentUrl(QStringLiteral("ToolBarApplicationHeader.qml")), uri, 2, 0, "ToolBarApplicationHeader");
qmlRegisterType(componentUrl(QStringLiteral("ApplicationWindow.qml")), uri, 2, 0, "ApplicationWindow");
qmlRegisterType(componentUrl(QStringLiteral("BasicListItem.qml")), uri, 2, 0, "BasicListItem");
qmlRegisterType(componentUrl(QStringLiteral("OverlayDrawer.qml")), uri, 2, 0, "OverlayDrawer");
qmlRegisterType(componentUrl(QStringLiteral("ContextDrawer.qml")), uri, 2, 0, "ContextDrawer");
qmlRegisterType(componentUrl(QStringLiteral("GlobalDrawer.qml")), uri, 2, 0, "GlobalDrawer");
qmlRegisterType(componentUrl(QStringLiteral("Heading.qml")), uri, 2, 0, "Heading");
qmlRegisterType(componentUrl(QStringLiteral("Separator.qml")), uri, 2, 0, "Separator");
qmlRegisterType(componentUrl(QStringLiteral("PageRow.qml")), uri, 2, 0, "PageRow");
qmlRegisterType(uri, 2, 0, "Icon");
qmlRegisterType(componentUrl(QStringLiteral("Label.qml")), uri, 2, 0, "Label");
//TODO: uncomment for 2.3 release
//qmlRegisterTypeNotAvailable(uri, 2, 3, "Label", "Label type not supported anymore, use QtQuick.Controls.Label 2.0 instead");
qmlRegisterType(componentUrl(QStringLiteral("OverlaySheet.qml")), uri, 2, 0, "OverlaySheet");
qmlRegisterType(componentUrl(QStringLiteral("Page.qml")), uri, 2, 0, "Page");
qmlRegisterType(componentUrl(QStringLiteral("ScrollablePage.qml")), uri, 2, 0, "ScrollablePage");
qmlRegisterType(componentUrl(QStringLiteral("SplitDrawer.qml")), uri, 2, 0, "SplitDrawer");
qmlRegisterType(componentUrl(QStringLiteral("SwipeListItem.qml")), uri, 2, 0, "SwipeListItem");
//2.1
qmlRegisterType(componentUrl(QStringLiteral("AbstractItemViewHeader.qml")), uri, 2, 1, "AbstractItemViewHeader");
qmlRegisterType(componentUrl(QStringLiteral("ItemViewHeader.qml")), uri, 2, 1, "ItemViewHeader");
qmlRegisterType(componentUrl(QStringLiteral("AbstractApplicationItem.qml")), uri, 2, 1, "AbstractApplicationItem");
qmlRegisterType(componentUrl(QStringLiteral("ApplicationItem.qml")), uri, 2, 1, "ApplicationItem");
//2.2
//Theme changed from a singleton to an attached property
qmlRegisterUncreatableType(uri, 2, 2, "Theme", QStringLiteral("Cannot create objects of type Theme, use it as an attached property"));
//2.3
qmlRegisterType(componentUrl(QStringLiteral("FormLayout.qml")), uri, 2, 3, "FormLayout");
qmlRegisterUncreatableType(uri, 2, 3, "FormData", QStringLiteral("Cannot create objects of type FormData, use it as an attached property"));
qmlRegisterUncreatableType(uri, 2, 3, "MnemonicData", QStringLiteral("Cannot create objects of type MnemonicData, use it as an attached property"));
//2.4
qmlRegisterType(componentUrl(QStringLiteral("AbstractCard.qml")), uri, 2, 4, "AbstractCard");
qmlRegisterType(componentUrl(QStringLiteral("Card.qml")), uri, 2, 4, "Card");
qmlRegisterType(componentUrl(QStringLiteral("CardsListView.qml")), uri, 2, 4, "CardsListView");
qmlRegisterType(componentUrl(QStringLiteral("CardsGridView.qml")), uri, 2, 4, "CardsGridView");
qmlRegisterType(componentUrl(QStringLiteral("CardsLayout.qml")), uri, 2, 4, "CardsLayout");
qmlRegisterType(componentUrl(QStringLiteral("InlineMessage.qml")), uri, 2, 4, "InlineMessage");
qmlRegisterUncreatableType(uri, 2, 4, "MessageType", QStringLiteral("Cannot create objects of type MessageType"));
qmlRegisterType(uri, 2, 4, "DelegateRecycler");
//2.5
qmlRegisterType(componentUrl(QStringLiteral("ListItemDragHandle.qml")), uri, 2, 5, "ListItemDragHandle");
qmlRegisterType(componentUrl(QStringLiteral("ActionToolBar.qml")), uri, 2, 5, "ActionToolBar");
qmlRegisterUncreatableType(uri, 2, 5, "ScenePosition", QStringLiteral("Cannot create objects of type ScenePosition, use it as an attached property"));
//2.6
qmlRegisterType(componentUrl(QStringLiteral("AboutPage.qml")), uri, 2, 6, "AboutPage");
qmlRegisterType(componentUrl(QStringLiteral("LinkButton.qml")), uri, 2, 6, "LinkButton");
qmlRegisterType(componentUrl(QStringLiteral("UrlButton.qml")), uri, 2, 6, "UrlButton");
qmlRegisterSingletonType("org.kde.kirigami.private", 2, 6, "CopyHelperPrivate", [] (QQmlEngine*, QJSEngine*) -> QObject* { return new CopyHelperPrivate; });
//2.7
qmlRegisterType(uri, 2, 7, "ColumnView");
qmlRegisterType(componentUrl(QStringLiteral("ActionTextField.qml")), uri, 2, 7, "ActionTextField");
//2.8
qmlRegisterType(componentUrl(QStringLiteral("SearchField.qml")), uri, 2, 8, "SearchField");
qmlRegisterType(componentUrl(QStringLiteral("PasswordField.qml")), uri, 2, 8, "PasswordField");
//2.9
qmlRegisterType(uri, 2, 9, "WheelHandler");
qmlRegisterUncreatableType(uri, 2, 9, "WheelEvent", QStringLiteral("Cannot create objects of type WheelEvent."));
//2.10
qmlRegisterType(componentUrl(QStringLiteral("ListSectionHeader.qml")), uri, 2, 10, "ListSectionHeader");
// 2.11
qmlRegisterType(uri, 2, 11, "PagePool");
qmlRegisterType(componentUrl(QStringLiteral("PagePoolAction.qml")), uri, 2, 11, "PagePoolAction");
//TODO: remove
qmlRegisterType(componentUrl(QStringLiteral("SwipeListItem2.qml")), uri, 2, 11, "SwipeListItem2");
// 2.12
qmlRegisterType(uri, 2, 12, "ShadowedRectangle");
qmlRegisterType(uri, 2, 12, "ShadowedTexture");
qmlRegisterType(componentUrl(QStringLiteral("ShadowedImage.qml")), uri, 2, 12, "ShadowedImage");
qmlRegisterType(componentUrl(QStringLiteral("PlaceholderMessage.qml")), uri, 2, 12, "PlaceholderMessage");
qmlRegisterUncreatableType(uri, 2, 12, "BorderGroup", QStringLiteral("Used as grouped property"));
qmlRegisterUncreatableType(uri, 2, 12, "ShadowGroup", QStringLiteral("Used as grouped property"));
qmlRegisterSingletonType(uri, 2, 12, "ColorUtils", [] (QQmlEngine*, QJSEngine*) -> QObject* { return new ColorUtils; });
qmlRegisterUncreatableType(uri, 2, 12, "CornersGroup", QStringLiteral("Used as grouped property"));
qmlRegisterType(uri, 2, 12, "PageRouter");
qmlRegisterType(uri, 2, 12, "PageRoute");
qmlRegisterUncreatableType(uri, 2, 12, "PageRouterAttached", QStringLiteral("PageRouterAttached cannot be created"));
qmlRegisterType(componentUrl(QStringLiteral("RouterWindow.qml")), uri, 2, 12, "RouterWindow");
// 2.13
qmlRegisterType(uri, 2, 13, "ImageColors");
qmlRegisterSingletonType("org.kde.kirigami.private", 2, 13, "AvatarPrivate", [] (QQmlEngine*, QJSEngine*) -> QObject* { return new AvatarPrivate; });
qmlRegisterType(componentUrl(QStringLiteral("Avatar.qml")), uri, 2, 13, "Avatar");
+ qmlRegisterType(componentUrl(QStringLiteral("swipenavigator/SwipeNavigator.qml")), uri, 2, 13, "SwipeNavigator");
qmlProtectModule(uri, 2);
}
void KirigamiPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
{
Q_UNUSED(uri);
connect(this, &KirigamiPlugin::languageChangeEvent, engine, &QQmlEngine::retranslate);
}
#include "kirigamiplugin.moc"