Commit 6e8fc4dc authored by Aleksi Suomalainen's avatar Aleksi Suomalainen

Merge pull request #27 from faenil/header

[header] New header component and big changes to orientation handling
parents f36a19f5 458b27fb
...@@ -64,7 +64,10 @@ Item { ...@@ -64,7 +64,10 @@ Item {
text: modelData text: modelData
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: 30 anchors.leftMargin: 20
anchors.right: arrow.left
anchors.rightMargin: 20
clip: true
} }
Rectangle { Rectangle {
...@@ -76,6 +79,7 @@ Item { ...@@ -76,6 +79,7 @@ Item {
} }
Image { Image {
id: arrow
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: 20 anchors.rightMargin: 20
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
...@@ -86,6 +90,5 @@ Item { ...@@ -86,6 +90,5 @@ Item {
id: mouse id: mouse
anchors.fill: parent anchors.fill: parent
onClicked: root.clicked() onClicked: root.clicked()
} }
} }
...@@ -46,7 +46,8 @@ import QtQuick.Controls.Styles.Nemo 1.0 ...@@ -46,7 +46,8 @@ import QtQuick.Controls.Styles.Nemo 1.0
Page { Page {
id: root id: root
tools: ToolBarLayoutExample { title: "Buttons" } headerTools: HeaderToolsLayout { showBackButton: false; title: "Buttons (portrait only, no back arrow)" }
allowedOrientations: Qt.PortraitOrientation
Column { Column {
spacing: 40 spacing: 40
......
...@@ -37,7 +37,8 @@ import QtQuick.Controls.Styles.Nemo 1.0 ...@@ -37,7 +37,8 @@ import QtQuick.Controls.Styles.Nemo 1.0
Page { Page {
id: root id: root
tools: ToolBarLayoutExample { title: "ButtonRow" } headerTools: HeaderToolsLayout { showBackButton: true; title: "Button row (Landscape only)" }
allowedOrientations: Qt.LandscapeOrientation
Column { Column {
spacing: 40 spacing: 40
......
...@@ -37,7 +37,7 @@ import QtQuick.Controls.Styles.Nemo 1.0 ...@@ -37,7 +37,7 @@ import QtQuick.Controls.Styles.Nemo 1.0
Page { Page {
id: root id: root
tools: ToolBarLayoutExample { title: "Switch" } headerTools: HeaderToolsLayout { showBackButton: true; title: "Switch" }
Column { Column {
spacing: 40 spacing: 40
......
...@@ -37,7 +37,8 @@ import QtQuick.Controls.Styles.Nemo 1.0 ...@@ -37,7 +37,8 @@ import QtQuick.Controls.Styles.Nemo 1.0
Page { Page {
id: root id: root
tools: ToolBarLayoutExample { title: "Label" } headerTools: HeaderToolsLayout { showBackButton: true; title: "Label" }
allowedOrientations: Qt.PortraitOrientation | Qt.LandscapeOrientation | Qt.InvertedLandscapeOrientation | Qt.InvertedPortraitOrientation
Column { Column {
spacing: 40 spacing: 40
......
...@@ -28,7 +28,7 @@ Page { ...@@ -28,7 +28,7 @@ Page {
property var oldItem property var oldItem
property var newItem property var newItem
tools: ToolBarLayoutExample { title: "Live Coding Arena" } headerTools: HeaderToolsLayout { showBackButton: true; title: "Live Coding Arena" }
SplitView { SplitView {
anchors.fill: parent anchors.fill: parent
......
...@@ -62,7 +62,7 @@ Page { ...@@ -62,7 +62,7 @@ Page {
} }
} }
tools: ToolBarLayoutExample { title: "Progress Bars" } headerTools: HeaderToolsLayout { showBackButton: true; title: "Progress Bars" }
Column { Column {
spacing: 40 spacing: 40
......
...@@ -37,7 +37,7 @@ import QtQuick.Controls.Styles.Nemo 1.0 ...@@ -37,7 +37,7 @@ import QtQuick.Controls.Styles.Nemo 1.0
Page { Page {
id: root id: root
tools: ToolBarLayoutExample { title: "Query dialog example" } headerTools: HeaderToolsLayout { showBackButton: true; title: "Query dialog example" }
QueryDialog { QueryDialog {
cancelText: "Cancel" cancelText: "Cancel"
......
...@@ -46,7 +46,7 @@ import QtQuick.Controls.Styles.Nemo 1.0 ...@@ -46,7 +46,7 @@ import QtQuick.Controls.Styles.Nemo 1.0
Page { Page {
id: root id: root
tools: ToolBarLayoutExample { title: "Sliders" } headerTools: HeaderToolsLayout { showBackButton: true; title: "Sliders" }
Column { Column {
spacing: 12 spacing: 12
......
...@@ -37,7 +37,7 @@ import QtQuick.Controls.Styles.Nemo 1.0 ...@@ -37,7 +37,7 @@ import QtQuick.Controls.Styles.Nemo 1.0
Page { Page {
id: root id: root
tools: ToolBarLayoutExample { title: "Spinner" } headerTools: HeaderToolsLayout { showBackButton: true; title: "Spinner" }
Column { Column {
spacing: 40 spacing: 40
......
...@@ -46,7 +46,7 @@ import QtQuick.Controls.Styles.Nemo 1.0 ...@@ -46,7 +46,7 @@ import QtQuick.Controls.Styles.Nemo 1.0
Page { Page {
id: root id: root
tools: ToolBarLayoutExample { title: "Tab bars" } headerTools: HeaderToolsLayout { showBackButton: true; title: "Tab bars" }
TabView { TabView {
anchors.fill: parent anchors.fill: parent
......
...@@ -62,7 +62,7 @@ Page { ...@@ -62,7 +62,7 @@ Page {
} }
} }
tools: ToolBarLayoutExample { title: "Text input" } headerTools: HeaderToolsLayout { showBackButton: true; title: "Text input" }
Column { Column {
spacing: 40 spacing: 40
......
import QtQuick 2.0
import QtQuick.Controls.Nemo 1.0
Item {
id: toolsLayoutItem
anchors.fill: parent
property string title: ""
property StackView pageStack: findStackView(toolsLayoutItem)
//XXX: TEMPORARY CODE, MIGHT CAUSE LAG WHEN PUSHING A PAGE ON THE STACK
function findStackView(startingItem) {
var myStack = startingItem
while (myStack) {
if (myStack.hasOwnProperty("currentItem") && myStack.hasOwnProperty("initialItem"))
return myStack
myStack = myStack.parent
}
return null
}
Rectangle {
id: backButton
width: opacity ? 60 : 0
anchors.left: parent.left
anchors.leftMargin: 20
//check if Stack.view has already been initialized as well
opacity: (pageStack && (pageStack.depth > 1)) ? 1 : 0
anchors.verticalCenter: parent.verticalCenter
antialiasing: true
height: 60
radius: 4
color: backmouse.pressed ? "#222" : "transparent"
Behavior on opacity { NumberAnimation{} }
Image {
anchors.verticalCenter: parent.verticalCenter
source: "../images/navigation_previous_item.png"
}
MouseArea {
id: backmouse
anchors.fill: parent
anchors.margins: -10
onClicked: pageStack.pop()
}
}
Label {
font.pixelSize: 42
Behavior on x { NumberAnimation { easing.type: Easing.OutCubic } }
x: backButton.x + backButton.width + 20
anchors.verticalCenter: parent.verticalCenter
text: parent.title
}
}
...@@ -43,6 +43,7 @@ import QtQuick.Controls 1.0 ...@@ -43,6 +43,7 @@ import QtQuick.Controls 1.0
import QtQuick.Controls.Nemo 1.0 import QtQuick.Controls.Nemo 1.0
import QtQuick.Controls.Styles.Nemo 1.0 import QtQuick.Controls.Styles.Nemo 1.0
import QtQuick.Window 2.1 import QtQuick.Window 2.1
import QtQuick.Layouts 1.0
import "content" import "content"
ApplicationWindow { ApplicationWindow {
...@@ -68,7 +69,7 @@ ApplicationWindow { ...@@ -68,7 +69,7 @@ ApplicationWindow {
page: "content/LiveCoding.qml" page: "content/LiveCoding.qml"
} }
ListElement { ListElement {
title: "Buttons" title: "Buttons (locked to portrait)"
page: "content/ButtonPage.qml" page: "content/ButtonPage.qml"
} }
ListElement { ListElement {
...@@ -92,7 +93,7 @@ ApplicationWindow { ...@@ -92,7 +93,7 @@ ApplicationWindow {
page: "content/SpinnerPage.qml" page: "content/SpinnerPage.qml"
} }
ListElement { ListElement {
title: "Labels" title: "Labels (no orientation locks)"
page: "content/LabelPage.qml" page: "content/LabelPage.qml"
} }
ListElement { ListElement {
...@@ -100,7 +101,7 @@ ApplicationWindow { ...@@ -100,7 +101,7 @@ ApplicationWindow {
page: "content/CheckboxPage.qml" page: "content/CheckboxPage.qml"
} }
ListElement { ListElement {
title: "ButtonRow" title: "ButtonRow (locked to landscape)"
page: "content/ButtonRowPage.qml" page: "content/ButtonRowPage.qml"
} }
ListElement { ListElement {
...@@ -113,7 +114,98 @@ ApplicationWindow { ...@@ -113,7 +114,98 @@ ApplicationWindow {
initialPage: Page { initialPage: Page {
id: pageItem id: pageItem
tools: ToolBarLayoutExample { title: "Touch gallery" } headerTools: HeaderToolsLayout {
id: tools
title: "Nemo Touch Gallery"
tools: [ ToolButton { iconSource: "../images/icon_cog.png"},
ToolButton { iconSource: "../images/icon_edit.png"},
ToolButton { iconSource: "../images/icon_refresh.png"} ]
//The parent of these items is null when this ToolsLayout is not used
//(i.e. you're on a different page) so we need to check the parent,
//just like in MeeGo's ToolbarLayout (when you don't use the automatic layout)
//TODO: Add automatic layout logic (see ToolbarLayout in MeeGo)
drawerLevels: [
Button {
anchors.horizontalCenter: (parent==undefined) ? undefined : parent.horizontalCenter;
text: "Nemo"
},
Button {
anchors.horizontalCenter: (parent==undefined) ? undefined : parent.horizontalCenter;
text: "Mobile"
},
Button {
anchors.horizontalCenter: (parent==undefined) ? undefined : parent.horizontalCenter;
text: "FTW"
},
RowLayout {
anchors.left: (parent==undefined) ? undefined : parent.left
anchors.right: (parent==undefined) ? undefined : parent.right
anchors.margins: 20
Layout.preferredHeight: 100
Label {
anchors.left: parent.left;
anchors.verticalCenter: parent.verticalCenter
text: "Drawer Test"}
CheckBox {
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
width : 20
}
},
RowLayout {
anchors.left: (parent==undefined) ? undefined : parent.left
anchors.right: (parent==undefined) ? undefined : parent.right
anchors.margins: 20
Layout.preferredHeight: 100
Label {
anchors.left: parent.left;
anchors.verticalCenter: parent.verticalCenter
text: "Drawer Test 2"}
ToolButton {
id: tool1
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
iconSource: "../images/icon_cog.png"
}
ToolButton {
id: tool2
anchors.right: tool1.left
anchors.verticalCenter: parent.verticalCenter
iconSource: "../images/icon_edit.png"
}
ToolButton {
id: tool3
anchors.right: tool2.left
anchors.verticalCenter: parent.verticalCenter
iconSource: "../images/icon_refresh.png"
}
},
ButtonRow {
id: buttonRowExample
model: ListModel {
ListElement {
name: "swim"
}
ListElement {
name: "cruise"
}
ListElement {
name: "row"
}
ListElement {
name: "fish"
}
ListElement {
name: "dive"
}
}
}
]
}
ListView { ListView {
model: pageModel model: pageModel
...@@ -126,5 +218,3 @@ ApplicationWindow { ...@@ -126,5 +218,3 @@ ApplicationWindow {
} }
} }
} }
...@@ -16,11 +16,15 @@ ...@@ -16,11 +16,15 @@
<file>images/textinput.png</file> <file>images/textinput.png</file>
<file>images/toolbar.png</file> <file>images/toolbar.png</file>
<file>content/LiveCoding.qml</file> <file>content/LiveCoding.qml</file>
<file>content/ToolBarLayoutExample.qml</file>
<file>content/SpinnerPage.qml</file> <file>content/SpinnerPage.qml</file>
<file>content/LabelPage.qml</file> <file>content/LabelPage.qml</file>
<file>content/CheckboxPage.qml</file> <file>content/CheckboxPage.qml</file>
<file>content/ButtonRowPage.qml</file> <file>content/ButtonRowPage.qml</file>
<file>content/QueryDialogPage.qml</file> <file>content/QueryDialogPage.qml</file>
<file>images/dots-vertical.png</file>
<file>images/icon-triangle-left.png</file>
<file>images/icon_cog.png</file>
<file>images/icon_edit.png</file>
<file>images/icon_refresh.png</file>
</qresource> </qresource>
</RCC> </RCC>
...@@ -18,7 +18,6 @@ OTHER_FILES += \ ...@@ -18,7 +18,6 @@ OTHER_FILES += \
content/TabBarPage.qml \ content/TabBarPage.qml \
content/TextInputPage.qml \ content/TextInputPage.qml \
content/LiveCoding.qml \ content/LiveCoding.qml \
content/ToolBarLayoutExample.qml \
content/SpinnerPage.qml \ content/SpinnerPage.qml \
content/LabelPage.qml \ content/LabelPage.qml \
content/CheckboxPage.qml \ content/CheckboxPage.qml \
......
...@@ -29,8 +29,9 @@ NemoWindow { ...@@ -29,8 +29,9 @@ NemoWindow {
id: root id: root
width: 320 width: 320
height: 240 height: 640
property alias header: toolBar
/*! \internal */ /*! \internal */
default property alias data: contentArea.data default property alias data: contentArea.data
...@@ -38,13 +39,15 @@ NemoWindow { ...@@ -38,13 +39,15 @@ NemoWindow {
property alias initialPage: stackView.initialItem property alias initialPage: stackView.initialItem
property alias orientation: contentArea.uiOrientation property alias orientation: contentArea.uiOrientation
readonly property int isUiPortrait: orientation == Qt.PortraitOrientation || orientation == Qt.InvertedPortraitOrientation
//is this safe? can there be some situation in which it's neither portrait nor landscape?
readonly property int isUiLandscape: !isUiPortrait
readonly property var _bgColor: Theme.window.background readonly property var _bgColor: Theme.window.background
color: _bgColor color: _bgColor
readonly property int defaultAllowedOrientations: Qt.PortraitOrientation | Qt.LandscapeOrientation //README: allowedOrientations' default value is set in NemoWindow's c++ implementation
//The app developer can overwrite it from QML
//these are application-wise allowed orientations, i.e. what is used if the current Page doesn't set any
allowedOrientations: defaultAllowedOrientations
onAllowedOrientationsChanged: { onAllowedOrientationsChanged: {
orientationConstraintsChanged() orientationConstraintsChanged()
...@@ -61,10 +64,22 @@ NemoWindow { ...@@ -61,10 +64,22 @@ NemoWindow {
//if the current orientation is not allowed anymore, fallback to an allowed one //if the current orientation is not allowed anymore, fallback to an allowed one
//stackInitialized check prevents setting an orientation before the stackview //stackInitialized check prevents setting an orientation before the stackview
//(but more importantly the initialItem of the stack) has been created //(but more importantly the initialItem of the stack) has been created
if (stackView.stackInitialized && !isOrientationAllowed(contentArea.filteredOrientation)) { if (stackView.stackInitialized) {
//- This is to give priority to the current screen orientation
//- This case happens when, for example, you're on a landscape only page,
// the phone is in portrait, and a page allowing portrait mode is pushed on the stack.
// When the page is pushed, we don't get any orientationChanged signal from the Screen element
// because the phone was already held in portrait mode, se we have to enforce it here.
if (isOrientationAllowed(Screen.orientation)) {
contentArea.filteredOrientation = Screen.orientation
}
//- If neither the current screen orientation nor the one which the UI is already presented in (filteredOrientation)
// are allowed, then fallback to an allowed orientation.
else if (!isOrientationAllowed(contentArea.filteredOrientation)) {
fallbackToAnAllowedOrientation() fallbackToAnAllowedOrientation()
} }
} }
}
function fallbackToAnAllowedOrientation() function fallbackToAnAllowedOrientation()
{ {
...@@ -127,6 +142,8 @@ NemoWindow { ...@@ -127,6 +142,8 @@ NemoWindow {
id: backgroundItem id: backgroundItem
anchors.centerIn: parent anchors.centerIn: parent
// NOTE: Using Screen.height/width will cause issues when the app is not fullscreen (e.g. when testing using Qt desktop)
// because in that case the app window will be smaller but the content will still be for fullscreen size
width: __transpose ? Screen.height : Screen.width width: __transpose ? Screen.height : Screen.width
height: __transpose ? Screen.width : Screen.height height: __transpose ? Screen.width : Screen.height
rotation: rotationToTransposeToPortrait() rotation: rotationToTransposeToPortrait()
...@@ -153,9 +170,12 @@ NemoWindow { ...@@ -153,9 +170,12 @@ NemoWindow {
StackView { StackView {
id: stackView id: stackView
width: parent.width anchors.top: root.isUiPortrait ? toolBar.bottom : parent.top
height: parent.height anchors.right: parent.right
anchors.left: root.isUiPortrait ? parent.left : toolBar.right
anchors.bottom: parent.bottom
clip: true
Component.onCompleted: stackInitialized = true Component.onCompleted: stackInitialized = true
//IMPORTANT: this property makes it so that at app startup we wait for the initial page to be pushed //IMPORTANT: this property makes it so that at app startup we wait for the initial page to be pushed
//before determining the initial ui orientation (see the states logic below) //before determining the initial ui orientation (see the states logic below)
...@@ -182,8 +202,10 @@ NemoWindow { ...@@ -182,8 +202,10 @@ NemoWindow {
} }
//update orientation constraints when a Page is pushed/popped //update orientation constraints when a Page is pushed/popped
onCurrentItemChanged: if (_isCurrentItemNemoPage() && currentItem.allowedOrientations) onCurrentItemChanged: {
if (_isCurrentItemNemoPage())
root.orientationConstraintsChanged() root.orientationConstraintsChanged()
}
//This properties are accessible for free by the Page via Stack.view.<property> //This properties are accessible for free by the Page via Stack.view.<property>
readonly property int orientation: contentArea.uiOrientation readonly property int orientation: contentArea.uiOrientation
...@@ -241,6 +263,44 @@ NemoWindow { ...@@ -241,6 +263,44 @@ NemoWindow {
} }
} }
Header {
id: toolBar
stackView: root.pageStack
appWindow: root
//used to animate the dimmer when pages are pushed/popped (see Header's QML code)
property alias __dimmer: headerDimmerContainer
}
Item {
//This item handles the rotation of the dimmer.
//All this because QML doesn't have a horizontal gradient (unless you import GraphicalEffects)
//and having a container which doesn't rotate but just resizes makes it easier to rotate its inner
//child
id: headerDimmerContainer
//README: Don't use AnchorChanges for this item!
//Reason: state changes disable bindings while the transition from one state to another is running.
//This causes the dimmer not to follow the drawer when the drawer is closed right before the orientation change
anchors.top: isUiPortrait ? toolBar.bottom : parent.top
anchors.left: isUiPortrait ? parent.left : toolBar.right
anchors.right: isUiPortrait ? parent.right : undefined
anchors.bottom: isUiPortrait ? undefined : parent.bottom
//we only set the size in one orientation, the anchors will take care of the other
width: if (!isUiPortrait) Theme.header.dimmer.height
height: if (isUiPortrait) Theme.header.dimmer.height
//MAKE SURE THAT THE HEIGHT SPECIFIED BY THE THEME IS AN EVEN NUMBER, TO AVOID ROUNDING ERRORS IN THE LAYOUT
Rectangle {
id: headerDimmer
anchors.centerIn: parent
gradient: Gradient {
GradientStop { position: Theme.header.dimmer.startPosition; color: Theme.header.dimmer.startColor }
GradientStop { position: Theme.header.dimmer.endPosition; color: Theme.header.dimmer.endColor }
}
}
}
Item { Item {
id: orientationState id: orientationState
...@@ -262,6 +322,12 @@ NemoWindow { ...@@ -262,6 +322,12 @@ NemoWindow {
rotation: 0 rotation: 0
uiOrientation: Qt.PortraitOrientation uiOrientation: Qt.PortraitOrientation
} }
PropertyChanges {
target: headerDimmer
height: Theme.header.dimmer.height
width: parent.width
rotation: 0
}
}, },
State { State {
name: 'Landscape' name: 'Landscape'
...@@ -274,6 +340,12 @@ NemoWindow { ...@@ -274,6 +340,12 @@ NemoWindow {
rotation: 90 rotation: 90
uiOrientation: Qt.LandscapeOrientation uiOrientation: Qt.LandscapeOrientation
} }
PropertyChanges {
target: headerDimmer
height: Theme.header.dimmer.height
width: parent.height
rotation: -90
}
}, },
State { State {
name: 'PortraitInverted' name: 'PortraitInverted'
...@@ -286,6 +358,12 @@ NemoWindow { ...@@ -286,6 +358,12 @@ NemoWindow {
rotation: 180 rotation: 180
uiOrientation: Qt.InvertedPortraitOrientation uiOrientation: Qt.InvertedPortraitOrientation
} }
PropertyChanges {
target: headerDimmer
height: Theme.header.dimmer.height
width: parent.width
rotation: 0
}
}, },
State { State {
name: 'LandscapeInverted' name: 'LandscapeInverted'
...@@ -298,6 +376,12 @@ NemoWindow { ...@@ -298,6 +376,12 @@ NemoWindow {
rotation: 270 rotation: 270
uiOrientation: Qt.InvertedLandscapeOrientation uiOrientation: Qt.InvertedLandscapeOrientation
} }
PropertyChanges {
target: headerDimmer
height: Theme.header.dimmer.height
width: parent.height
rotation: -90
}
} }
] ]
...@@ -320,6 +404,13 @@ NemoWindow { ...@@ -320,6 +404,13 @@ NemoWindow {
target: contentArea target: contentArea
properties: 'width,height,rotation,uiOrientation' properties: 'width,height,rotation,uiOrientation'
} }
AnchorAnimation {
duration: 0
}
PropertyAction {
target: headerDimmer
properties: 'width,height,rotation'
}
NumberAnimation { NumberAnimation {
target: contentArea target: contentArea
property: 'opacity' property: 'opacity'
......
import QtQuick 2.1
import QtQuick.Window 2.0
import QtQuick.Controls 1.0
import QtQuick.Controls.Nemo 1.0
import QtQuick.Controls.Styles.Nemo 1.0
import QtQuick.Layouts 1.0
import QtGraphicalEffects 1.0
Item {
id: root
//TODO: Add logic/animations to handle dynamic change of tools and drawer levels in the same page
//make sure the header is aligned properly
Binding on y {
when: !appWindow.isUiPortrait
value: 0
}
Binding on x {
when: appWindow.isUiPortrait
value: 0
}
//Since the header drawer behaves differently in portrait/landscape modes
//we close the drawer when the UI rotates
Connections {
target: appWindow
onIsUiPortraitChanged: closeDrawer()
}
//Handle portrait/landscape orientation layout changes
//Using states is better than having "anchors.left: appWindow.isUiPortrait ? portraitanchor : landscapeanchor"
//because in the latter way when isUiPortrait changes, the order of reevaluation of the anchors bindings
//(hence the resulting layout) cannot be predicted. Using States we avoid that source of issues
states: [
State {
id: portraitState
when: appWindow && appWindow.isUiPortrait
AnchorChanges { target: toolBarRect; anchors.left: root.left}
AnchorChanges {
target: drawerContainer;
anchors.top: undefined
anchors.bottom: toolBarRect.top
anchors.left: root.left
anchors.right: root.right
}
AnchorChanges {
target: drawer;
anchors.right: undefined
anchors.bottom: drawerContainer.bottom
anchors.verticalCenter: undefined
anchors.horizontalCenter: drawerContainer.horizontalCenter
}
//having width/height as PropertyChanges avoids creating binding loops
PropertyChanges {
target: root
width: parent.width
//the height of the drawer in portrait is limited by the size of the shorter edge of the screen
height: (toolBarRect.height + Math.min(drawer.height, appWindow.__transpose ? Screen.height : Screen.width))
}
//remember: the PropertyChanges handle bindings by default, unless "explicit: true" is set
PropertyChanges {
target: toolBarRect
width: parent.width
height: 75
}
},
State {
id: landscapeState
when: appWindow && !appWindow.isUiPortrait
AnchorChanges { target: toolBarRect; anchors.left: undefined }
AnchorChanges {
target: drawerContainer;
anchors.top: root.top
anchors.bottom: root.bottom
anchors.left: undefined
anchors.right: toolBarRect.left
}
AnchorChanges {
target: drawer;
anchors.right: drawerContainer.right
anchors.bottom: undefined
anchors.verticalCenter: drawerContainer.verticalCenter
anchors.horizontalCenter: undefined
}
PropertyChanges {
target: root
//the width of the drawer in landscape is limited by the size of the shorter edge of the screen
width: (toolBarRect.width + Math.min(drawer.width, appWindow.__transpose ? Screen.height : Screen.width))
height: parent.height
}
PropertyChanges {
target: toolBarRect
width: 75
height: parent.height
}
}
]
//this is the value that will be used by toolBarContainer
//please pretty please don't turn it into an alias to toolBarContainer.data,
//because in that way you won't get change signals (.data doesn't have NOTIFY
//and is a Q_PRIVATE_PROPERTY) and you won't be able to access the toolbarLayout
//directly. So -> not a good idea :)
property variant toolBarLayout
function closeDrawer() {
x = Qt.binding(function() { return appWindow.isUiPortrait ? 0 : -drawer.width})
y = Qt.binding(function() { return appWindow.isUiPortrait ? -drawer.height : 0})
}
property double speedBumpThreshold: 3/5
property int closedY: - drawer.height
property int closedX: - drawer.width
property int closedCoord: appWindow.isUiPortrait ? closedY : closedX
//those properties are initialized when the header is created
//(See ApplicationWindow source)
property StackView stackView
property variant appWindow
//used for manual type checking when looking for items of type Header from other QML elements
property bool __isNemoHeader
//propagate header reference to headerTools which have the "header" property
//used by the headerTools to know when it should display the back button
//(i.e. to get header.stackView.depth value)
Connections {
target: stackView
onCurrentItemChanged: {
if (changeToolsLayoutAnim.running) {
changeToolsLayoutAnim.complete()
}
changeToolsLayoutAnim.start()
}
//Close drawer if a page transition is starting
onBusyChanged: if (stackView.busy) closeDrawer()
}
function propagateHeaderReference() {
if (toolBarLayout && toolBarLayout.hasOwnProperty("header")) {
toolBarLayout.header = toolBar
}
}
function updateHeaderTools() {
root.toolBarLayout = stackView.currentItem ? stackView.currentItem.headerTools : undefined
}
SequentialAnimation {
id: changeToolsLayoutAnim
NumberAnimation { id: fadeOut; target: root; property: "opacity"; to: 0;
duration: Theme.pageStack.transitionDuration/2; easing.type: Easing.OutQuad; loops: !toolBarLayout ? 0 : 1 }
//headerTools may change now, so we have to close the drawer
ScriptAction { script: closeDrawer() }
ScriptAction { script: updateHeaderTools() }
//tell the (maybe new) layout that we're its container
ScriptAction { script: propagateHeaderReference() }
NumberAnimation { id: fadeIn; target: root; property: "opacity"; to: 1;
duration: Theme.pageStack.transitionDuration/2; easing.type: Easing.OutQuad; loops: !toolBarLayout ? 0 : 1 }
}
NumberAnimation {
id: slidingAnim
target: root
property: appWindow.isUiPortrait ? "y" : "x"
from: appWindow.isUiPortrait ? root.y : root.x
easing.type: Easing.OutExpo
}
function slideDrawerTo(coord) {
slidingAnim.to = coord
slidingAnim.start()
}
//THIS ITEM AND ITS CHILDREN ARE THE TOOLBAR (i.e. NOT what's inside the drawer!)
//This item only resizes when UI rotates, while toolBarContainer is the one actually rotating
Rectangle {
id: toolBarRect
anchors.bottom: parent.bottom
anchors.right: parent.right
//README: the rest of the anchors/sizes will be set by AnchorChanges!
color: Theme.header.background
FilteringMouseArea {
id: mouseArea
anchors.fill: parent
property bool swiping: false
property int swipeThreshold: 10
property int gestureThreshold: drawer.width / 3 //this is only used in landscape
//container coordinate (x OR y, depending on UI orientation) relative to the parent
//of the header
property int startCoord: 0
//mouse coordinate (x OR y, depending on UI orientation) relative to the parent
//of the header
property int startMouseCoord: 0
property int deltaCoord: 0
//This is item which holds the toolbar and rotates with the UI
Item {
id: toolBarContainer
//no anchors here, as we're using the rotation to change between portrait/landscape modes
width: appWindow.isUiPortrait ? parent.width : parent.height
height: appWindow.isUiPortrait ? parent.height : parent.width
anchors.centerIn: parent
data: toolBarLayout ? toolBarLayout : null
rotation: appWindow.isUiPortrait ? 0 : -90
}
onPressed: {
if (swiping) {
console.log("[HEADER] Swiping enabled in onPressed, report this.")
swiping = false
}
if (appWindow.isUiPortrait) {
startMouseCoord = (pos.y + root.y)
startCoord = root.y
} else { //assuming that otherwise we're in landscape...is this safe?
startMouseCoord = (pos.x + root.x)
startCoord = root.x
}
}
onPositionChanged: {
if (appWindow.isUiPortrait) {
deltaCoord = (pos.y + root.y) - startMouseCoord
if (Math.abs(deltaCoord) > swipeThreshold && !swiping) { grabMouseEvents(); swiping = true; }
if (swiping) {
var swipingY = startCoord + deltaCoord
if ( swipingY > 0) {
root.y = Math.sqrt(swipingY)
} else {
if (swipingY < root.closedY) root.y = root.closedY
else root.y = swipingY
}
}
} else {
deltaCoord = (pos.x + root.x) - startMouseCoord
if (Math.abs(deltaCoord) > swipeThreshold && !swiping) { grabMouseEvents(); swiping = true; }
if (swiping) {
//this is the coord that the drawer would be at if it were following our finger
var swipingX = startCoord + deltaCoord
//if the left/top side of the drawer is entering the screen, pull the breaks!
//quadratic slowdown effect
if ( swipingX > 0) {
root.x = Math.sqrt(swipingX)
} else {
//don't let the toolbar go out of screen
if (swipingX < root.closedX) root.x = root.closedX
else root.x = swipingX
}
}
}
}
onReleased: {
if (appWindow.isUiPortrait) {
if (!swiping) {
//Fully Close/Open the drawer
root.slideDrawerTo((root.y == root.closedY) ? 0 : root.closedY)
} else {
//this is the y at the top of the screen, relative to the header dock (root)
var topY = -root.y
//We cannot use QML's childAt because it requires both x and y
//and we don't have an x to provide (and it wouldn't make sense to have one,
//given the current specced behaviour of the header)
var item = drawer.getItemAt(topY)
//item is undefined when there's no item at the y of the top edge of the screen
//(this happens for example when you pull down the drawer so that its y is > 0)
if (item == undefined) {
//if the drawer is closed or half open, we open it totally.
//if it was opened already, we close it ("pull down to close" feature)
root.slideDrawerTo(startCoord == 0 ? root.closedY : 0)
} else {
root.slideDrawerTo(((topY - item.y) <= (speedBumpThreshold * item.height)) ? -item.y : -(item.y + item.height))
}
}
} else {
if (!swiping) {
//Fully Close/Open the drawer
root.slideDrawerTo((root.x == root.closedX) ? 0 : root.closedX)
} else {
deltaCoord = (pos.x + root.x) - startMouseCoord
if (deltaCoord > gestureThreshold) {
root.slideDrawerTo(startCoord < 0 ? 0 : closedX)
} else if (deltaCoord < -gestureThreshold){
root.slideDrawerTo(closedX)
} else { //i.e (-gestureThreshold <= deltaCoord <= gestureThreshold)
root.slideDrawerTo((startCoord === root.closedX) ? root.closedX : 0)
}
}
}
swiping = false
}
}
}
Rectangle {
id: drawerContainer
color: Theme.header.background
Binding on width {
value: drawer.width
when: !appWindow.isUiPortrait
}
Binding on height {
value: drawer.height
when: appWindow.isUiPortrait
}
ColumnLayout {
id: drawer
//NOTE: if you set the spacing to something != 0 then you have to rewrite the logic which handles drawer speedbumps,
//which currently relies on "spacing" being 0
spacing: 0
function getItemAt(y) {
//skip the first child, which is the toolbar
for (var i=0; i < children.length; i++) {
if (y >=children[i].y && y <= (children[i].y + children[i].height))
return children[i]
}
}
children: if (toolBarLayout) toolBarLayout.drawerLevels
}
}
}
import QtQuick 2.0
import QtQuick.Controls.Nemo 1.0
import QtQuick.Controls.Styles.Nemo 1.0
import QtQuick.Layouts 1.0
import QtGraphicalEffects 1.0
//This item handles the UI representation for the toolbar
//The UI representation of the drawerLevels is inside the header
//(we may consider having a DrawerLayout element in the future)
Item {
id: toolsLayoutItem
anchors.fill: parent
property alias title: titleTxt.text
//these have to be initialized when the HeaderToolsLayout is instantiated
property Header header
property list<Item> tools
property list<Item> drawerLevels
//we'll get rid of this once we'll have the appWindow accessible everywhere
property bool isUiPortrait: header && header.appWindow.isUiPortrait
property bool showBackButton: false
Rectangle {
id: backButton
width: opacity ? 60 : 0
anchors.leftMargin: 20
//check if Stack.view has already been initialized as well
anchors.verticalCenter: parent.verticalCenter
antialiasing: true
height: width
radius: 4
color: backmouse.pressed ? "#222" : "transparent"
rotation: isUiPortrait ? 0 : 90
visible: showBackButton
Image {
anchors.centerIn: parent
source: "../Styles/Nemo/images/icon-triangle-left.png"
}
MouseArea {
id: backmouse
anchors.fill: parent
anchors.margins: -10
onClicked: header && header.stackView && header.stackView.pop()
}
}
Label {
id: titleTxt
anchors.right: toolButtonsContainer.left
anchors.left: backButton.visible ? backButton.right : parent.left
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: 20
anchors.rightMargin: 20
clip: true
font.family: Theme.fontFamily
color: Theme.label.color
font.pointSize: 24
font.weight: Font.Bold
LinearGradient {
anchors.right: parent.right
width: 50
height: parent.paintedHeight
visible: titleTxt.paintedWidth > titleTxt.width
start: Qt.point(0,0)
end: Qt.point(width,0)
gradient: Gradient { GradientStop { position: 0; color: "transparent"}
GradientStop {position: 0.9; color: Theme.header.background } }
}
}
Item {
id: toolButtonsContainer
anchors.right: dots.visible ? dots.left : parent.right
anchors.rightMargin: 20
anchors.verticalCenter: parent.verticalCenter
width: tools ? (50 * Math.min(maxNumberOfToolButtons, tools.length)) : 0
property int maxNumberOfToolButtons: 3
RowLayout {
id: toolsRow
anchors.centerIn: parent
function assignRotationBindings() {
for (var i=0; i<children.length; ++i) {
children[i].rotation = Qt.binding(function() { return isUiPortrait ? 0 : 90 })
}
}
//TODO: THIS IS STUPID :D This is run once every added item (i.e. EVEN IF you add 3 items at the same time)
//but it's not critical since it will always have a very limited amount of children
onChildrenChanged: {
assignRotationBindings()
}
children: tools
}
}
Image {
id: dots
anchors.right: parent.right
anchors.rightMargin: 20
anchors.verticalCenter: parent.verticalCenter
visible: drawerLevels && drawerLevels.length > 1
source: "../Styles/Nemo/images/dots-vertical.png"
rotation: isUiPortrait ? 0 : 90
}
}
...@@ -43,13 +43,9 @@ NemoPage { ...@@ -43,13 +43,9 @@ NemoPage {
property alias color: background.color property alias color: background.color
property int status: pageStack ? Stack.status : Stack.Inactive property int status: pageStack ? Stack.status : Stack.Inactive
property alias tools: toolBar.data property variant headerTools
property alias __dimmer: dimmer
readonly property StackView pageStack: Stack.view readonly property StackView pageStack: Stack.view
//TODO: ADD TOOLBARLAYOUT COMPONENT SO THAT USER WILL USE tools: ToolbarLayout { .... }
//instead of tools: [ ... , ... ]
//Children of "page" will be automatically reparented to "content" //Children of "page" will be automatically reparented to "content"
default property alias __content: content.data default property alias __content: content.data
...@@ -77,31 +73,8 @@ NemoPage { ...@@ -77,31 +73,8 @@ NemoPage {
color: Theme.page.background color: Theme.page.background
} }
ToolBar {
id: toolBar
z: 201
}
Item { Item {
id: content id: content
anchors.bottom: parent.bottom anchors.fill: parent
anchors.top: toolBar.bottom
anchors.right: parent.right
anchors.left: parent.left
}
Rectangle {
id: dimmer
height: Theme.page.dimmer.height
anchors.top: toolBar.bottom
anchors.left: parent.left
anchors.right: parent.right
gradient: Gradient {
GradientStop { position: Theme.page.dimmer.startPosition; color: Theme.page.dimmer.startColor }
GradientStop { position: Theme.page.dimmer.endPosition; color: Theme.page.dimmer.endColor }
}
} }
} }
...@@ -13,25 +13,27 @@ QML_FILES += \ ...@@ -13,25 +13,27 @@ QML_FILES += \
Spinner.qml \ Spinner.qml \
Label.qml \ Label.qml \
Checkbox.qml\ Checkbox.qml\
images/disabled-overlay.png ButtonRow.qml \
images/disabled-overlay-inverse.png QueryDialog.qml \
Header.qml \
HeaderToolsLayout.qml
OTHER_FILES += qmldir \ OTHER_FILES += qmldir \
$$QML_FILES \ $$QML_FILES
ButtonRow.qml \
QueryDialog.qml
HEADERS += \ HEADERS += \
qquicknemocontrolsextensionplugin.h \ qquicknemocontrolsextensionplugin.h \
hacks.h \ hacks.h \
nemowindow.h \ nemowindow.h \
nemopage.h nemopage.h \
qquickfilteringmousearea.h
SOURCES += \ SOURCES += \
qquicknemocontrolsextensionplugin.cpp \ qquicknemocontrolsextensionplugin.cpp \
hacks.cpp \ hacks.cpp \
nemowindow.cpp \ nemowindow.cpp \
nemopage.cpp nemopage.cpp \
qquickfilteringmousearea.cpp
target.path = $$[QT_INSTALL_QML]/$$PLUGIN_IMPORT_PATH target.path = $$[QT_INSTALL_QML]/$$PLUGIN_IMPORT_PATH
......
...@@ -32,5 +32,5 @@ bool Hacks::isOrientationMaskValid(Qt::ScreenOrientations orientations) { ...@@ -32,5 +32,5 @@ bool Hacks::isOrientationMaskValid(Qt::ScreenOrientations orientations) {
Qt::ScreenOrientations max = (Qt::PortraitOrientation | Qt::LandscapeOrientation Qt::ScreenOrientations max = (Qt::PortraitOrientation | Qt::LandscapeOrientation
| Qt::InvertedPortraitOrientation | Qt::InvertedLandscapeOrientation); | Qt::InvertedPortraitOrientation | Qt::InvertedLandscapeOrientation);
return (orientations <= max && orientations != 0); return (orientations <= max && orientations > 0);
} }
...@@ -2,7 +2,11 @@ ...@@ -2,7 +2,11 @@
#include "hacks.h" #include "hacks.h"
NemoPage::NemoPage(QQuickItem *parent) : NemoPage::NemoPage(QQuickItem *parent) :
QQuickItem(parent) QQuickItem(parent),
m_allowedOrientations(0) //- The value 0 means Page's allowedOrientations will be ignored
//- The value 0 can't be set from QML on purpose (see Hacks::isOrientationMaskValid impl.),
// so that we can use the value 0 to know that the app developer has not touched this value
// (in fact, as just said, once it's changed from QML, the app dev can't set it back to 0 from QML)
{ {
} }
...@@ -14,8 +18,12 @@ Qt::ScreenOrientations NemoPage::allowedOrientations() const ...@@ -14,8 +18,12 @@ Qt::ScreenOrientations NemoPage::allowedOrientations() const
void NemoPage::setAllowedOrientations(Qt::ScreenOrientations allowed) void NemoPage::setAllowedOrientations(Qt::ScreenOrientations allowed)
{ {
//This way no invalid values can get assigned to allowedOrientations //This way no invalid values can get assigned to allowedOrientations
if (m_allowedOrientations != allowed && Hacks::isOrientationMaskValid(allowed)) { if (m_allowedOrientations != allowed) {
if (Hacks::isOrientationMaskValid(allowed)) {
m_allowedOrientations = allowed; m_allowedOrientations = allowed;
emit allowedOrientationsChanged(); emit allowedOrientationsChanged();
} else {
qDebug() << "NemoPage: invalid allowedOrientation!";
}
} }
} }
...@@ -22,8 +22,10 @@ ...@@ -22,8 +22,10 @@
#include "hacks.h" #include "hacks.h"
NemoWindow::NemoWindow(QWindow *parent) : NemoWindow::NemoWindow(QWindow *parent) :
QQuickWindow(parent) QQuickWindow(parent),
m_defaultAllowedOrientations(Qt::PortraitOrientation | Qt::LandscapeOrientation)
{ {
m_allowedOrientations = m_defaultAllowedOrientations;
} }
Qt::ScreenOrientations NemoWindow::allowedOrientations() const Qt::ScreenOrientations NemoWindow::allowedOrientations() const
...@@ -31,11 +33,20 @@ Qt::ScreenOrientations NemoWindow::allowedOrientations() const ...@@ -31,11 +33,20 @@ Qt::ScreenOrientations NemoWindow::allowedOrientations() const
return m_allowedOrientations; return m_allowedOrientations;
} }
const Qt::ScreenOrientations NemoWindow::defaultAllowedOrientations() const
{
return m_defaultAllowedOrientations;
}
void NemoWindow::setAllowedOrientations(Qt::ScreenOrientations allowed) void NemoWindow::setAllowedOrientations(Qt::ScreenOrientations allowed)
{ {
//This way no invalid values can get assigned to allowedOrientations //This way no invalid values can get assigned to allowedOrientations
if (m_allowedOrientations != allowed && Hacks::isOrientationMaskValid(allowed)) { if (m_allowedOrientations != allowed) {
if (Hacks::isOrientationMaskValid(allowed)) {
m_allowedOrientations = allowed; m_allowedOrientations = allowed;
emit allowedOrientationsChanged(); emit allowedOrientationsChanged();
} else {
qDebug() << "NemoWindow: invalid allowedOrientation!";
}
} }
} }
...@@ -26,10 +26,14 @@ class NemoWindow : public QQuickWindow ...@@ -26,10 +26,14 @@ class NemoWindow : public QQuickWindow
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(Qt::ScreenOrientations allowedOrientations READ allowedOrientations WRITE setAllowedOrientations NOTIFY allowedOrientationsChanged) Q_PROPERTY(Qt::ScreenOrientations allowedOrientations READ allowedOrientations WRITE setAllowedOrientations NOTIFY allowedOrientationsChanged)
Q_PROPERTY(Qt::ScreenOrientations defaultAllowedOrientations READ allowedOrientations)
public: public:
explicit NemoWindow(QWindow *parent = 0); explicit NemoWindow(QWindow *parent = 0);
Qt::ScreenOrientations allowedOrientations() const; Qt::ScreenOrientations allowedOrientations() const;
const Qt::ScreenOrientations defaultAllowedOrientations() const;
void setAllowedOrientations(Qt::ScreenOrientations allowed); void setAllowedOrientations(Qt::ScreenOrientations allowed);
signals: signals:
...@@ -38,7 +42,12 @@ signals: ...@@ -38,7 +42,12 @@ signals:
public slots: public slots:
private: private:
//This is the global allowed orientations settings:
//it's the settings used when the current Page doesn't specify any allowedOrientations, otherwise
//allowedOrientations of that Page is used
Qt::ScreenOrientations m_allowedOrientations; Qt::ScreenOrientations m_allowedOrientations;
Qt::ScreenOrientations m_defaultAllowedOrientations;
}; };
#endif // NEMOWINDOW_H #endif // NEMOWINDOW_H
...@@ -16,6 +16,9 @@ Label 1.0 Label.qml ...@@ -16,6 +16,9 @@ Label 1.0 Label.qml
CheckBox 1.0 Checkbox.qml CheckBox 1.0 Checkbox.qml
ButtonRow 1.0 ButtonRow.qml ButtonRow 1.0 ButtonRow.qml
QueryDialog 1.0 QueryDialog.qml QueryDialog 1.0 QueryDialog.qml
Header 1.0 Header.qml
HeaderToolsLayout 1.0 HeaderToolsLayout.qml
# MIRRORED CONTROLS: # MIRRORED CONTROLS:
# These are the controls that we take directly from official QQC. # These are the controls that we take directly from official QQC.
# This is to avoid having to "import QtQuick.Controls" when using controls # This is to avoid having to "import QtQuick.Controls" when using controls
......
#include "qquickfilteringmousearea.h"
#include <QQuickWindow>
QQuickFilteringMouseArea::QQuickFilteringMouseArea(QQuickItem *parent) :
QQuickItem(parent),
m_pressed(false),
m_swipingX(false),
m_swipingY(false),
m_swipingThreshold(10)
{
setFiltersChildMouseEvents(true);
setAcceptedMouseButtons(Qt::LeftButton);
}
bool QQuickFilteringMouseArea::childMouseEventFilter(QQuickItem *i, QEvent *e)
{
if (!isVisible() || !isEnabled())
return QQuickItem::childMouseEventFilter(i, e);
switch (e->type()) {
case QEvent::MouseButtonPress:
case QEvent::MouseMove:
case QEvent::MouseButtonRelease:
return sendMouseEvent(i, static_cast<QMouseEvent *>(e));
case QEvent::UngrabMouse:
if (window() && window()->mouseGrabberItem() && window()->mouseGrabberItem() != this) {
// The grab has been taken away from a child and given to some other item.
mouseUngrabEvent();
}
break;
default:
break;
}
return QQuickItem::childMouseEventFilter(i, e);
}
void QQuickFilteringMouseArea::mouseMoveEvent(QMouseEvent *event) {
if (!isEnabled() || !isPressed()) {
QQuickItem::mouseMoveEvent(event);
return;
}
//TODO: we should only grab the mouse if there's a swipe ongoing.
//The move event is very easy to trigger with touchscreens
//so it's not a good measure of the fact that we want to swipe
//grabMouse();
setDeltaPos(QPointF(event->windowPos().x() - pressPos().x(), event->windowPos().y() - pressPos().y()));
if (event->windowPos().x() - pressPos().x() > swipingThreshold()) setSwipingX(true);
if (event->windowPos().y() - pressPos().y() > swipingThreshold()) setSwipingY(true);
setPosition(event->localPos());
}
void QQuickFilteringMouseArea::mousePressEvent(QMouseEvent *event) {
if (!isEnabled() || !(event->button() & acceptedMouseButtons())) {
QQuickItem::mousePressEvent(event);
} else {
setPressPos(event->windowPos());
emit pressed(event->localPos());
setPressed(true);
setPosition(event->localPos());
}
}
void QQuickFilteringMouseArea::mouseReleaseEvent(QMouseEvent *event) {
if (!isEnabled() && !isPressed()) {
QQuickItem::mouseReleaseEvent(event);
} else {
QQuickWindow *w = window();
if (w && w->mouseGrabberItem() == this && m_pressed){
emit released(event->localPos());
mouseUngrabEvent();
}
}
}
bool QQuickFilteringMouseArea::sendMouseEvent(QQuickItem *item, QMouseEvent *event) {
QPointF localPos = mapFromScene(event->windowPos());
QQuickWindow *c = window();
QQuickItem *grabber = c ? c->mouseGrabberItem() : 0;
if ((contains(localPos)) && (!grabber || !grabber->keepMouseGrab())) {
QMouseEvent mouseEvent(event->type(), localPos, event->windowPos(), event->screenPos(),
event->button(), event->buttons(), event->modifiers());
mouseEvent.setAccepted(false);
switch (event->type()) {
case QEvent::MouseMove:
mouseMoveEvent(&mouseEvent);
break;
case QEvent::MouseButtonPress:
mousePressEvent(&mouseEvent);
break;
case QEvent::MouseButtonRelease:
mouseReleaseEvent(&mouseEvent);
break;
default:
break;
}
}
return false;
}
void QQuickFilteringMouseArea::mouseUngrabEvent() {
setPressed(false);
setSwipingX(false);
setSwipingY(false);
QQuickWindow *w = window();
if (w && w->mouseGrabberItem() == this)
ungrabMouse();
}
void QQuickFilteringMouseArea::grabMouseEvents() {
qDebug() << "Glacier Header: Grabbing mouse!";
grabMouse();
}
void QQuickFilteringMouseArea::ungrabMouseEvents() {
ungrabMouse();
}
#ifndef QQUICKFILTERINGMOUSEAREA_H
#define QQUICKFILTERINGMOUSEAREA_H
#include <QQuickItem>
#include <QMouseEvent>
class QQuickFilteringMouseArea : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(bool pressed READ isPressed NOTIFY pressedChanged)
Q_PROPERTY(QPointF pressPos READ pressPos NOTIFY pressPosChanged)
Q_PROPERTY(QPointF deltaPos READ deltaPos NOTIFY deltaPosChanged)
Q_PROPERTY(bool swipingX READ isSwipingX NOTIFY swipingXChanged)
Q_PROPERTY(bool swipingY READ isSwipingY NOTIFY swipingYChanged)
Q_PROPERTY(int swipingThreshold READ swipingThreshold WRITE setSwipingThreshold NOTIFY swipingThresholdChanged)
public:
explicit QQuickFilteringMouseArea(QQuickItem *parent = 0);
bool handlePress();
bool handleMove();
bool handleRelease();
bool isPressed() const { return m_pressed; }
void setPressed(const bool pressed) {
if (m_pressed != pressed) {
m_pressed = pressed;
emit pressedChanged();
}
}
QPointF position() const { return m_lastPos; }
void setPosition(const QPointF &pos) {
if (m_lastPos != pos) {
m_lastPos = pos;
emit positionChanged(pos);
}
}
QPointF pressPos() const { return m_pressPos; }
void setPressPos(const QPointF &pos) {
if (m_pressPos != pos) {
m_pressPos = pos;
emit pressPosChanged();
}
}
QPointF deltaPos() const { return m_deltaPos; }
void setDeltaPos(const QPointF &pos) {
if (m_deltaPos != pos) {
m_deltaPos = pos;
emit deltaPosChanged();
}
}
bool isSwipingX() const { return m_swipingX; }
void setSwipingX(const bool swiping) {
if (m_swipingX != swiping) {
m_swipingX = swiping;
emit swipingXChanged();
}
}
bool isSwipingY() const { return m_swipingY; }
void setSwipingY(const bool swiping) {
if (m_swipingY != swiping) {
m_swipingY = swiping;
emit swipingYChanged();
}
}
int swipingThreshold() const { return m_swipingThreshold; }
void setSwipingThreshold(const int threshold) {
if (m_swipingThreshold != threshold) {
m_swipingThreshold = threshold;
emit swipingThresholdChanged();
}
}
signals:
void pressedChanged();
void pressed(const QPointF &pos);
void released(const QPointF &pos);
void positionChanged(const QPointF &pos);
void pressPosChanged();
void deltaPosChanged();
void swipingXChanged();
void swipingYChanged();
void swipingThresholdChanged();
public slots:
void grabMouseEvents();
void ungrabMouseEvents();
protected:
virtual bool childMouseEventFilter(QQuickItem *, QEvent *);
virtual void mousePressEvent(QMouseEvent *event);
virtual void mouseMoveEvent(QMouseEvent *event);
virtual void mouseReleaseEvent(QMouseEvent *event);
virtual void mouseUngrabEvent();
bool sendMouseEvent(QQuickItem *item, QMouseEvent *event);
private:
bool m_pressed;
QPointF m_lastPos;
QPointF m_pressPos;
QPointF m_deltaPos;
bool m_swipingX;
bool m_swipingY;
int m_swipingThreshold;
};
#endif // QQUICKFILTERINGMOUSEAREA_H
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "hacks.h" #include "hacks.h"
#include "nemowindow.h" #include "nemowindow.h"
#include "nemopage.h" #include "nemopage.h"
#include "qquickfilteringmousearea.h"
QQuickNemoControlsExtensionPlugin::QQuickNemoControlsExtensionPlugin(QObject *parent) : QQuickNemoControlsExtensionPlugin::QQuickNemoControlsExtensionPlugin(QObject *parent) :
QQmlExtensionPlugin(parent) QQmlExtensionPlugin(parent)
...@@ -41,6 +42,7 @@ void QQuickNemoControlsExtensionPlugin::registerTypes(const char *uri) ...@@ -41,6 +42,7 @@ void QQuickNemoControlsExtensionPlugin::registerTypes(const char *uri)
qmlRegisterSingletonType<QObject>(uri, 1, 0, "NemoHacks", nemo_hacks_singletontype_provider); qmlRegisterSingletonType<QObject>(uri, 1, 0, "NemoHacks", nemo_hacks_singletontype_provider);
qmlRegisterType<NemoWindow>(uri, 1, 0, "NemoWindow"); qmlRegisterType<NemoWindow>(uri, 1, 0, "NemoWindow");
qmlRegisterType<NemoPage>(uri, 1, 0, "NemoPage"); qmlRegisterType<NemoPage>(uri, 1, 0, "NemoPage");
qmlRegisterType<QQuickFilteringMouseArea>(uri, 1, 0, "FilteringMouseArea");
} }
void QQuickNemoControlsExtensionPlugin::initializeEngine(QQmlEngine *engine, const char *uri) void QQuickNemoControlsExtensionPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
......
...@@ -46,6 +46,7 @@ Style { ...@@ -46,6 +46,7 @@ Style {
Image { Image {
id: icon id: icon
anchors.fill: parent anchors.fill: parent
fillMode: Image.PreserveAspectFit
anchors.margins: 8 anchors.margins: 8
source: control.iconSource source: control.iconSource
} }
......
...@@ -50,6 +50,7 @@ NemoTheme::NemoTheme(QObject *parent) ...@@ -50,6 +50,7 @@ NemoTheme::NemoTheme(QObject *parent)
, m_label(new NemoThemeLabel(this)) , m_label(new NemoThemeLabel(this))
, m_checkbox(new NemoThemeCheckbox(this)) , m_checkbox(new NemoThemeCheckbox(this))
, m_buttonRow(new NemoThemeButtonRow(this)) , m_buttonRow(new NemoThemeButtonRow(this))
, m_header(new NemoThemeHeader(this))
{ {
loadFromFile(GLACIER_THEME); loadFromFile(GLACIER_THEME);
int id = QFontDatabase::addApplicationFont("/usr/share/fonts/google-opensans/OpenSans-Regular.ttf"); int id = QFontDatabase::addApplicationFont("/usr/share/fonts/google-opensans/OpenSans-Regular.ttf");
...@@ -147,6 +148,11 @@ NemoThemeButtonRow * NemoTheme::buttonRow() const ...@@ -147,6 +148,11 @@ NemoThemeButtonRow * NemoTheme::buttonRow() const
return m_buttonRow; return m_buttonRow;
} }
NemoThemeHeader * NemoTheme::header() const
{
return m_header;
}
QString NemoTheme::fontFamily() const QString NemoTheme::fontFamily() const
{ {
return m_fontFamily; return m_fontFamily;
...@@ -389,25 +395,6 @@ void NemoTheme::loadFromFile(const QString &fileName) ...@@ -389,25 +395,6 @@ void NemoTheme::loadFromFile(const QString &fileName)
// Setting properties for page // Setting properties for page
QJsonObject stylesPage = styles.value("page").toObject(); QJsonObject stylesPage = styles.value("page").toObject();
m_page->setBackground(jsonToColor(jsonValue(stylesPage, "background", "page"), defines)); m_page->setBackground(jsonToColor(jsonValue(stylesPage, "background", "page"), defines));
// Setting properties for dimmer
QJsonObject stylesPageDimmer = stylesPage.value("dimmer").toObject();
m_page->dimmer()->setStartColor(jsonToColor(jsonValue(stylesPageDimmer, "startColor", "dimmer"), defines));
m_page->dimmer()->setEndColor(jsonToColor(jsonValue(stylesPageDimmer, "endColor", "dimmer"), defines));
if (stylesPageDimmer.contains("height")) {
m_page->dimmer()->setHeight(jsonToInt(stylesPageDimmer.value("height"), defines));
} else {
m_page->dimmer()->setHeightDefault();
}
if (stylesPageDimmer.contains("startPosition")) {
m_page->dimmer()->setStartPosition(jsonToDouble(stylesPageDimmer.value("startPosition"), defines));
} else {
m_page->dimmer()->setStartPositionDefault();
}
if (stylesPageDimmer.contains("endPosition")) {
m_page->dimmer()->setEndPosition(jsonToDouble(stylesPageDimmer.value("endPosition"), defines));
} else {
m_page->dimmer()->setEndPositionDefault();
}
// Setting properties for pageStack // Setting properties for pageStack
QJsonObject stylesPageStack = styles.value("pageStack").toObject(); QJsonObject stylesPageStack = styles.value("pageStack").toObject();
if (stylesPageStack.contains("transitionDuration")) { if (stylesPageStack.contains("transitionDuration")) {
...@@ -460,4 +447,26 @@ void NemoTheme::loadFromFile(const QString &fileName) ...@@ -460,4 +447,26 @@ void NemoTheme::loadFromFile(const QString &fileName)
QJsonObject stylesButtonRow = styles.value("buttonRow").toObject(); QJsonObject stylesButtonRow = styles.value("buttonRow").toObject();
m_buttonRow->setBackground(jsonToColor(jsonValue(stylesButtonRow, "background", "buttonRow"), defines)); m_buttonRow->setBackground(jsonToColor(jsonValue(stylesButtonRow, "background", "buttonRow"), defines));
m_buttonRow->setButtonColor(jsonToColor(jsonValue(stylesButtonRow, "buttonColor", "buttonRow"), defines)); m_buttonRow->setButtonColor(jsonToColor(jsonValue(stylesButtonRow, "buttonColor", "buttonRow"), defines));
// Setting properties for header
QJsonObject stylesHeader = styles.value("header").toObject();
m_header->setBackground(jsonToColor(jsonValue(stylesHeader, "background", "header"), defines));
// Setting properties for dimmer
QJsonObject stylesHeaderDimmer = stylesHeader.value("dimmer").toObject();
m_header->dimmer()->setStartColor(jsonToColor(jsonValue(stylesHeaderDimmer, "startColor", "dimmer"), defines));
m_header->dimmer()->setEndColor(jsonToColor(jsonValue(stylesHeaderDimmer, "endColor", "dimmer"), defines));
if (stylesHeaderDimmer.contains("height")) {
m_header->dimmer()->setHeight(jsonToInt(stylesHeaderDimmer.value("height"), defines));
} else {
m_header->dimmer()->setHeightDefault();
}
if (stylesHeaderDimmer.contains("startPosition")) {
m_header->dimmer()->setStartPosition(jsonToDouble(stylesHeaderDimmer.value("startPosition"), defines));
} else {
m_header->dimmer()->setStartPositionDefault();
}
if (stylesHeaderDimmer.contains("endPosition")) {
m_header->dimmer()->setEndPosition(jsonToDouble(stylesHeaderDimmer.value("endPosition"), defines));
} else {
m_header->dimmer()->setEndPositionDefault();
}
} }
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include "nemothemelabel.h" #include "nemothemelabel.h"
#include "nemothemecheckbox.h" #include "nemothemecheckbox.h"
#include "nemothemebuttonrow.h" #include "nemothemebuttonrow.h"
#include "nemothemeheader.h"
class NemoTheme: public QObject class NemoTheme: public QObject
{ {
...@@ -54,6 +55,7 @@ class NemoTheme: public QObject ...@@ -54,6 +55,7 @@ class NemoTheme: public QObject
Q_PROPERTY(NemoThemeLabel * label READ label CONSTANT) Q_PROPERTY(NemoThemeLabel * label READ label CONSTANT)
Q_PROPERTY(NemoThemeCheckbox * checkbox READ checkbox CONSTANT) Q_PROPERTY(NemoThemeCheckbox * checkbox READ checkbox CONSTANT)
Q_PROPERTY(NemoThemeButtonRow * buttonRow READ buttonRow CONSTANT) Q_PROPERTY(NemoThemeButtonRow * buttonRow READ buttonRow CONSTANT)
Q_PROPERTY(NemoThemeHeader * header READ header CONSTANT)
Q_PROPERTY(QString fontFamily READ fontFamily CONSTANT) Q_PROPERTY(QString fontFamily READ fontFamily CONSTANT)
public: public:
explicit NemoTheme(QObject *parent = 0); explicit NemoTheme(QObject *parent = 0);
...@@ -73,6 +75,7 @@ public: ...@@ -73,6 +75,7 @@ public:
NemoThemeLabel * label() const; NemoThemeLabel * label() const;
NemoThemeCheckbox * checkbox() const; NemoThemeCheckbox * checkbox() const;
NemoThemeButtonRow * buttonRow() const; NemoThemeButtonRow * buttonRow() const;
NemoThemeHeader * header() const;
QString fontFamily() const; QString fontFamily() const;
public Q_SLOTS: public Q_SLOTS:
void loadFromFile(const QString &fileName); void loadFromFile(const QString &fileName);
...@@ -94,6 +97,7 @@ private: ...@@ -94,6 +97,7 @@ private:
NemoThemeLabel * m_label; NemoThemeLabel * m_label;
NemoThemeCheckbox * m_checkbox; NemoThemeCheckbox * m_checkbox;
NemoThemeButtonRow * m_buttonRow; NemoThemeButtonRow * m_buttonRow;
NemoThemeHeader * m_header;
QString m_fontFamily; QString m_fontFamily;
}; };
......
/*
* Copyright (C) 2013 Lucien Xu <sfietkonstantin@free.fr>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
// This class is autogenerated using themehelper.py
// Any modification done in this file will be overridden
#include "nemothemeheader.h"
NemoThemeHeader::NemoThemeHeader(QObject *parent)
: QObject(parent)
, m_dimmer(new NemoThemeHeaderDimmer(this))
{
}
QColor NemoThemeHeader::background() const
{
return m_background;
}
void NemoThemeHeader::setBackground(const QColor &background)
{
if (m_background != background) {
m_background = background;
emit backgroundChanged();
}
}
NemoThemeHeaderDimmer * NemoThemeHeader::dimmer() const
{
return m_dimmer;
}
/*
* Copyright (C) 2013 Lucien Xu <sfietkonstantin@free.fr>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
// This class is autogenerated using themehelper.py
// Any modification done in this file will be overridden
#ifndef NEMOTHEMEHEADER_H
#define NEMOTHEMEHEADER_H
#include <QtCore/QObject>
#include <QtGui/QColor>
#include "nemothemeheaderdimmer.h"
class NemoThemeHeader: public QObject
{
Q_OBJECT
Q_PROPERTY(QColor background READ background NOTIFY backgroundChanged)
Q_PROPERTY(NemoThemeHeaderDimmer * dimmer READ dimmer CONSTANT)
public:
explicit NemoThemeHeader(QObject *parent = 0);
QColor background() const;
void setBackground(const QColor &background);
NemoThemeHeaderDimmer * dimmer() const;
Q_SIGNALS:
void backgroundChanged();
private:
QColor m_background;
NemoThemeHeaderDimmer * m_dimmer;
};
#endif //NEMOTHEMEHEADER_H
/*
* Copyright (C) 2013 Lucien Xu <sfietkonstantin@free.fr>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
// This class is autogenerated using themehelper.py
// Any modification done in this file will be overridden
#include "nemothemeheaderdimmer.h"
NemoThemeHeaderDimmer::NemoThemeHeaderDimmer(QObject *parent)
: QObject(parent)
, m_height(16)
, m_startPosition(0)
, m_endPosition(1.0)
{
}
QColor NemoThemeHeaderDimmer::startColor() const
{
return m_startColor;
}
void NemoThemeHeaderDimmer::setStartColor(const QColor &startColor)
{
if (m_startColor != startColor) {
m_startColor = startColor;
emit startColorChanged();
}
}
QColor NemoThemeHeaderDimmer::endColor() const
{
return m_endColor;
}
void NemoThemeHeaderDimmer::setEndColor(const QColor &endColor)
{
if (m_endColor != endColor) {
m_endColor = endColor;
emit endColorChanged();
}
}
int NemoThemeHeaderDimmer::height() const
{
return m_height;
}
void NemoThemeHeaderDimmer::setHeight(int height)
{
if (m_height != height) {
m_height = height;
emit heightChanged();
}
}
void NemoThemeHeaderDimmer::setHeightDefault()
{
if (m_height != 16) {
m_height = 16;
emit heightChanged();
}
}
double NemoThemeHeaderDimmer::startPosition() const
{
return m_startPosition;
}
void NemoThemeHeaderDimmer::setStartPosition(double startPosition)
{
if (m_startPosition != startPosition) {
m_startPosition = startPosition;
emit startPositionChanged();
}
}
void NemoThemeHeaderDimmer::setStartPositionDefault()
{
if (m_startPosition != 0) {
m_startPosition = 0;
emit startPositionChanged();
}
}
double NemoThemeHeaderDimmer::endPosition() const
{
return m_endPosition;
}
void NemoThemeHeaderDimmer::setEndPosition(double endPosition)
{
if (m_endPosition != endPosition) {
m_endPosition = endPosition;
emit endPositionChanged();
}
}
void NemoThemeHeaderDimmer::setEndPositionDefault()
{
if (m_endPosition != 1.0) {
m_endPosition = 1.0;
emit endPositionChanged();
}
}
/*
* Copyright (C) 2013 Lucien Xu <sfietkonstantin@free.fr>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
// This class is autogenerated using themehelper.py
// Any modification done in this file will be overridden
#ifndef NEMOTHEMEHEADERDIMMER_H
#define NEMOTHEMEHEADERDIMMER_H
#include <QtCore/QObject>
#include <QtGui/QColor>
class NemoThemeHeaderDimmer: public QObject
{
Q_OBJECT
Q_PROPERTY(QColor startColor READ startColor NOTIFY startColorChanged)
Q_PROPERTY(QColor endColor READ endColor NOTIFY endColorChanged)
Q_PROPERTY(int height READ height NOTIFY heightChanged)
Q_PROPERTY(double startPosition READ startPosition NOTIFY startPositionChanged)
Q_PROPERTY(double endPosition READ endPosition NOTIFY endPositionChanged)
public:
explicit NemoThemeHeaderDimmer(QObject *parent = 0);
QColor startColor() const;
void setStartColor(const QColor &startColor);
QColor endColor() const;
void setEndColor(const QColor &endColor);
int height() const;
void setHeight(int height);
void setHeightDefault();
double startPosition() const;
void setStartPosition(double startPosition);
void setStartPositionDefault();
double endPosition() const;
void setEndPosition(double endPosition);
void setEndPositionDefault();
Q_SIGNALS:
void startColorChanged();
void endColorChanged();
void heightChanged();
void startPositionChanged();
void endPositionChanged();
private:
QColor m_startColor;
QColor m_endColor;
int m_height;
double m_startPosition;
double m_endPosition;
};
#endif //NEMOTHEMEHEADERDIMMER_H
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
NemoThemePage::NemoThemePage(QObject *parent) NemoThemePage::NemoThemePage(QObject *parent)
: QObject(parent) : QObject(parent)
, m_dimmer(new NemoThemePageDimmer(this))
{ {
} }
...@@ -40,8 +39,3 @@ void NemoThemePage::setBackground(const QColor &background) ...@@ -40,8 +39,3 @@ void NemoThemePage::setBackground(const QColor &background)
emit backgroundChanged(); emit backgroundChanged();
} }
} }
NemoThemePageDimmer * NemoThemePage::dimmer() const
{
return m_dimmer;
}
...@@ -25,23 +25,19 @@ ...@@ -25,23 +25,19 @@
#include <QtCore/QObject> #include <QtCore/QObject>
#include <QtGui/QColor> #include <QtGui/QColor>
#include "nemothemepagedimmer.h"
class NemoThemePage: public QObject class NemoThemePage: public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QColor background READ background NOTIFY backgroundChanged) Q_PROPERTY(QColor background READ background NOTIFY backgroundChanged)
Q_PROPERTY(NemoThemePageDimmer * dimmer READ dimmer CONSTANT)
public: public:
explicit NemoThemePage(QObject *parent = 0); explicit NemoThemePage(QObject *parent = 0);
QColor background() const; QColor background() const;
void setBackground(const QColor &background); void setBackground(const QColor &background);
NemoThemePageDimmer * dimmer() const;
Q_SIGNALS: Q_SIGNALS:
void backgroundChanged(); void backgroundChanged();
private: private:
QColor m_background; QColor m_background;
NemoThemePageDimmer * m_dimmer;
}; };
#endif //NEMOTHEMEPAGE_H #endif //NEMOTHEMEPAGE_H
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
NemoThemePageDimmer::NemoThemePageDimmer(QObject *parent) NemoThemePageDimmer::NemoThemePageDimmer(QObject *parent)
: QObject(parent) : QObject(parent)
, m_height(15) , m_height(16)
, m_startPosition(0) , m_startPosition(0)
, m_endPosition(1.0) , m_endPosition(1.0)
{ {
...@@ -71,8 +71,8 @@ void NemoThemePageDimmer::setHeight(int height) ...@@ -71,8 +71,8 @@ void NemoThemePageDimmer::setHeight(int height)
void NemoThemePageDimmer::setHeightDefault() void NemoThemePageDimmer::setHeightDefault()
{ {
if (m_height != 15) { if (m_height != 16) {
m_height = 15; m_height = 16;
emit heightChanged(); emit heightChanged();
} }
} }
......
...@@ -48,12 +48,12 @@ void QQuickNemoStyleExtensionPlugin::registerTypes(const char *uri) ...@@ -48,12 +48,12 @@ void QQuickNemoStyleExtensionPlugin::registerTypes(const char *uri)
qmlRegisterUncreatableType<NemoThemeToolBar>(uri, 1, 0, "NemoThemeToolBar", reason); qmlRegisterUncreatableType<NemoThemeToolBar>(uri, 1, 0, "NemoThemeToolBar", reason);
qmlRegisterUncreatableType<NemoThemeWindow>(uri, 1, 0, "NemoThemeWindow", reason); qmlRegisterUncreatableType<NemoThemeWindow>(uri, 1, 0, "NemoThemeWindow", reason);
qmlRegisterUncreatableType<NemoThemePage>(uri, 1, 0, "NemoThemePage", reason); qmlRegisterUncreatableType<NemoThemePage>(uri, 1, 0, "NemoThemePage", reason);
qmlRegisterUncreatableType<NemoThemePageDimmer>(uri, 1, 0, "NemoThemePageDimmer", reason);
qmlRegisterUncreatableType<NemoThemeSpinner>(uri, 1, 0, "NemoThemeSpinner", reason); qmlRegisterUncreatableType<NemoThemeSpinner>(uri, 1, 0, "NemoThemeSpinner", reason);
qmlRegisterUncreatableType<NemoThemeLabel>(uri, 1, 0, "NemoThemeLabel", reason); qmlRegisterUncreatableType<NemoThemeLabel>(uri, 1, 0, "NemoThemeLabel", reason);
qmlRegisterUncreatableType<NemoThemeCheckbox>(uri, 1, 0, "NemoThemeCheckbox", reason); qmlRegisterUncreatableType<NemoThemeCheckbox>(uri, 1, 0, "NemoThemeCheckbox", reason);
qmlRegisterUncreatableType<NemoThemePageStack>(uri, 1, 0, "NemoThemePageStack", reason); qmlRegisterUncreatableType<NemoThemePageStack>(uri, 1, 0, "NemoThemePageStack", reason);
qmlRegisterUncreatableType<NemoThemeHeader>(uri, 1, 0, "NemoThemeHeader", reason);
qmlRegisterUncreatableType<NemoThemeHeaderDimmer>(uri, 1, 0, "NemoThemeHeaderDimmer", reason);
qmlRegisterSingletonType<QObject>(uri, 1, 0, "Theme", nemo_theme_provider); qmlRegisterSingletonType<QObject>(uri, 1, 0, "Theme", nemo_theme_provider);
} }
......
...@@ -84,12 +84,13 @@ HEADERS += \ ...@@ -84,12 +84,13 @@ HEADERS += \
autogenerated/nemothemetoolbar.h \ autogenerated/nemothemetoolbar.h \
autogenerated/nemothemewindow.h \ autogenerated/nemothemewindow.h \
autogenerated/nemothemepage.h \ autogenerated/nemothemepage.h \
autogenerated/nemothemepagedimmer.h \
autogenerated/nemothemespinner.h \ autogenerated/nemothemespinner.h \
autogenerated/nemothemelabel.h \ autogenerated/nemothemelabel.h \
autogenerated/nemothemecheckbox.h \ autogenerated/nemothemecheckbox.h \
autogenerated/nemothemepagestack.h \ autogenerated/nemothemepagestack.h \
autogenerated/nemothemebuttonrow.h autogenerated/nemothemebuttonrow.h \
autogenerated/nemothemeheader.h \
autogenerated/nemothemeheaderdimmer.h
SOURCES += \ SOURCES += \
qquicknemostyleextensionplugin.cpp \ qquicknemostyleextensionplugin.cpp \
...@@ -103,12 +104,13 @@ SOURCES += \ ...@@ -103,12 +104,13 @@ SOURCES += \
autogenerated/nemothemetoolbar.cpp \ autogenerated/nemothemetoolbar.cpp \
autogenerated/nemothemewindow.cpp \ autogenerated/nemothemewindow.cpp \
autogenerated/nemothemepage.cpp \ autogenerated/nemothemepage.cpp \
autogenerated/nemothemepagedimmer.cpp \
autogenerated/nemothemespinner.cpp \ autogenerated/nemothemespinner.cpp \
autogenerated/nemothemelabel.cpp \ autogenerated/nemothemelabel.cpp \
autogenerated/nemothemecheckbox.cpp \ autogenerated/nemothemecheckbox.cpp \
autogenerated/nemothemepagestack.cpp \ autogenerated/nemothemepagestack.cpp \
autogenerated/nemothemebuttonrow.cpp autogenerated/nemothemebuttonrow.cpp \
autogenerated/nemothemeheader.cpp \
autogenerated/nemothemeheaderdimmer.cpp
INSTALLS += target images qmlfiles themes INSTALLS += target images qmlfiles themes
......
...@@ -45,11 +45,7 @@ ...@@ -45,11 +45,7 @@
"background": "#000000" "background": "#000000"
}, },
"page": { "page": {
"background": "#000000", "background": "#000000"
"dimmer": {
"startColor": "black",
"endColor": "transparent"
}
}, },
"spinner": { "spinner": {
"primaryColor": "#ffffff", "primaryColor": "#ffffff",
...@@ -65,6 +61,13 @@ ...@@ -65,6 +61,13 @@
"buttonRow": { "buttonRow": {
"background": "#313131", "background": "#313131",
"buttonColor": "#0091e5" "buttonColor": "#0091e5"
},
"header": {
"background": "#000000",
"dimmer": {
"startColor": "black",
"endColor": "transparent"
}
} }
} }
} }
...@@ -45,11 +45,7 @@ ...@@ -45,11 +45,7 @@
"background": "#000000" "background": "#000000"
}, },
"page": { "page": {
"background": "#000000", "background": "#000000"
"dimmer": {
"startColor": "black",
"endColor": "transparent"
}
}, },
"spinner": { "spinner": {
"primaryColor": "accentColor", "primaryColor": "accentColor",
...@@ -64,6 +60,13 @@ ...@@ -64,6 +60,13 @@
}, },
"pageStack": { "pageStack": {
"transitionDuration": 1500 "transitionDuration": 1500
},
"header": {
"background": "#000000",
"dimmer": {
"startColor": "black",
"endColor": "transparent"
}
} }
} }
} }
...@@ -73,10 +73,6 @@ ...@@ -73,10 +73,6 @@
{ {
"name": "background", "name": "background",
"type": "QColor" "type": "QColor"
},
{
"name": "dimmer",
"object": "PageDimmer"
} }
] ]
}, },
...@@ -141,34 +137,6 @@ ...@@ -141,34 +137,6 @@
} }
] ]
}, },
{
"name": "PageDimmer",
"properties": [
{
"name": "startColor",
"type": "QColor"
},
{
"name": "endColor",
"type": "QColor"
},
{
"name": "height",
"type": "int",
"default": 15
},
{
"name": "startPosition",
"type": "double",
"default": 0
},
{
"name": "endPosition",
"type": "double",
"default": 1.0
}
]
},
{ {
"name": "Spinner", "name": "Spinner",
"properties": [ "properties": [
...@@ -256,6 +224,47 @@ ...@@ -256,6 +224,47 @@
"type": "QColor" "type": "QColor"
} }
] ]
},
{
"name": "Header",
"properties": [
{
"name": "background",
"type": "QColor"
},
{
"name": "dimmer",
"object": "HeaderDimmer"
}
]
},
{
"name": "HeaderDimmer",
"properties": [
{
"name": "startColor",
"type": "QColor"
},
{
"name": "endColor",
"type": "QColor"
},
{
"name": "height",
"type": "int",
"default": 16
},
{
"name": "startPosition",
"type": "double",
"default": 0
},
{
"name": "endPosition",
"type": "double",
"default": 1.0
}
]
} }
], ],
"properties": [ "properties": [
...@@ -306,6 +315,10 @@ ...@@ -306,6 +315,10 @@
{ {
"name": "buttonRow", "name": "buttonRow",
"object": "ButtonRow" "object": "ButtonRow"
},
{
"name": "header",
"object": "Header"
} }
], ],
"font": "/usr/share/fonts/google-opensans/OpenSans-Regular.ttf" "font": "/usr/share/fonts/google-opensans/OpenSans-Regular.ttf"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment