Commit 458b27fb authored by Andrea Bernabei's avatar Andrea Bernabei

[header] New header component and big changes to orientation handling

First of all, this is a big commit, I'm sorry guys...I couldn't find
a decent way to split the big changes into many commits as they're
all strongly related one to the other...so I decided to just push it
into one commit instead of splitting it into non-working mini-commits.

So, the main changes which this commit brings are:
- Header component!
  It's basically a toolbar + "drawer" with
  levels of customizable heights providing speedbumps
  (yeah, I can understand this is not that self-explaining,
  refer to https://github.com/qwazix/glacier-controls-spec/blob/master/header/header.pdf
  for more info :D )
  I'm sure there are lots of things which can be improved,
  look for the "TODO" comments in the sourcecode.
  But it's generally complete and working.
  The header behaves different in portrait and landscape modes,
  as requested in the spec above.

- Header dimmer:
  this is a separate component because of technical reasons,
  but it's basically the dimmer which is anchored at the bottom
  of the header, and partially covers the current page.

- Added a new HeaderToolsLayout, which replaces the temporary
  ToolBarLayoutExample.
  This component currently only handles the layout of the toolbar,
  not the drawer (decision making required, here).

- Added FilteringMouseArea QML component, with c++ implementation:
  this was needed to implement the header, and I'm sure it will be useful
  in the future for other purposes. It's basically a MouseArea which
  receives the events, handles them, and sends them underneath if
  it wishes to (while in MouseArea, if you accept the first event the areas
  below you won't receive it, and if you don't accept the first event,
  you'll miss all the others as well)

- The toolbar/header element has been moved from Page to ApplicationWindow.
  This means there's only one Header in the app, what changes is its
  content (just like in MeeGo's Qt Components), which means we don't have
  to create a new Header everytime we push a Page on the stack.

- Moved some QML properties to C++

- Improved UI orientation change handling:
  the orientation locks now work correctly, plus we can both specify
  a Page orientation lock, *and* a global orientation lock, which is used
  when no lock is specified for the current page.

- Updated components example Gallery:
  many modifications here and there as a consequence to the big changes,
  plus I've replaced the Toolbar with the Header in all pages,and
  put a few levels in the drawer of the main Page.
  I also set orientation locks in a few pages, to make it easier
  in the future to check that everything is working.

Have fun! :)

faenil
parent f36a19f5
......@@ -64,7 +64,10 @@ Item {
text: modelData
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 30
anchors.leftMargin: 20
anchors.right: arrow.left
anchors.rightMargin: 20
clip: true
}
Rectangle {
......@@ -76,6 +79,7 @@ Item {
}
Image {
id: arrow
anchors.right: parent.right
anchors.rightMargin: 20
anchors.verticalCenter: parent.verticalCenter
......@@ -86,6 +90,5 @@ Item {
id: mouse
anchors.fill: parent
onClicked: root.clicked()
}
}
......@@ -46,7 +46,8 @@ import QtQuick.Controls.Styles.Nemo 1.0
Page {
id: root
tools: ToolBarLayoutExample { title: "Buttons" }
headerTools: HeaderToolsLayout { showBackButton: false; title: "Buttons (portrait only, no back arrow)" }
allowedOrientations: Qt.PortraitOrientation
Column {
spacing: 40
......
......@@ -37,7 +37,8 @@ import QtQuick.Controls.Styles.Nemo 1.0
Page {
id: root
tools: ToolBarLayoutExample { title: "ButtonRow" }
headerTools: HeaderToolsLayout { showBackButton: true; title: "Button row (Landscape only)" }
allowedOrientations: Qt.LandscapeOrientation
Column {
spacing: 40
......
......@@ -37,7 +37,7 @@ import QtQuick.Controls.Styles.Nemo 1.0
Page {
id: root
tools: ToolBarLayoutExample { title: "Switch" }
headerTools: HeaderToolsLayout { showBackButton: true; title: "Switch" }
Column {
spacing: 40
......
......@@ -37,7 +37,8 @@ import QtQuick.Controls.Styles.Nemo 1.0
Page {
id: root
tools: ToolBarLayoutExample { title: "Label" }
headerTools: HeaderToolsLayout { showBackButton: true; title: "Label" }
allowedOrientations: Qt.PortraitOrientation | Qt.LandscapeOrientation | Qt.InvertedLandscapeOrientation | Qt.InvertedPortraitOrientation
Column {
spacing: 40
......
......@@ -28,7 +28,7 @@ Page {
property var oldItem
property var newItem
tools: ToolBarLayoutExample { title: "Live Coding Arena" }
headerTools: HeaderToolsLayout { showBackButton: true; title: "Live Coding Arena" }
SplitView {
anchors.fill: parent
......
......@@ -62,7 +62,7 @@ Page {
}
}
tools: ToolBarLayoutExample { title: "Progress Bars" }
headerTools: HeaderToolsLayout { showBackButton: true; title: "Progress Bars" }
Column {
spacing: 40
......
......@@ -37,7 +37,7 @@ import QtQuick.Controls.Styles.Nemo 1.0
Page {
id: root
tools: ToolBarLayoutExample { title: "Query dialog example" }
headerTools: HeaderToolsLayout { showBackButton: true; title: "Query dialog example" }
QueryDialog {
cancelText: "Cancel"
......
......@@ -46,7 +46,7 @@ import QtQuick.Controls.Styles.Nemo 1.0
Page {
id: root
tools: ToolBarLayoutExample { title: "Sliders" }
headerTools: HeaderToolsLayout { showBackButton: true; title: "Sliders" }
Column {
spacing: 12
......
......@@ -37,7 +37,7 @@ import QtQuick.Controls.Styles.Nemo 1.0
Page {
id: root
tools: ToolBarLayoutExample { title: "Spinner" }
headerTools: HeaderToolsLayout { showBackButton: true; title: "Spinner" }
Column {
spacing: 40
......
......@@ -46,7 +46,7 @@ import QtQuick.Controls.Styles.Nemo 1.0
Page {
id: root
tools: ToolBarLayoutExample { title: "Tab bars" }
headerTools: HeaderToolsLayout { showBackButton: true; title: "Tab bars" }
TabView {
anchors.fill: parent
......
......@@ -62,7 +62,7 @@ Page {
}
}
tools: ToolBarLayoutExample { title: "Text input" }
headerTools: HeaderToolsLayout { showBackButton: true; title: "Text input" }
Column {
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
import QtQuick.Controls.Nemo 1.0
import QtQuick.Controls.Styles.Nemo 1.0
import QtQuick.Window 2.1
import QtQuick.Layouts 1.0
import "content"
ApplicationWindow {
......@@ -68,7 +69,7 @@ ApplicationWindow {
page: "content/LiveCoding.qml"
}
ListElement {
title: "Buttons"
title: "Buttons (locked to portrait)"
page: "content/ButtonPage.qml"
}
ListElement {
......@@ -92,7 +93,7 @@ ApplicationWindow {
page: "content/SpinnerPage.qml"
}
ListElement {
title: "Labels"
title: "Labels (no orientation locks)"
page: "content/LabelPage.qml"
}
ListElement {
......@@ -100,7 +101,7 @@ ApplicationWindow {
page: "content/CheckboxPage.qml"
}
ListElement {
title: "ButtonRow"
title: "ButtonRow (locked to landscape)"
page: "content/ButtonRowPage.qml"
}
ListElement {
......@@ -113,7 +114,98 @@ ApplicationWindow {
initialPage: Page {
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 {
model: pageModel
......@@ -126,5 +218,3 @@ ApplicationWindow {
}
}
}
......@@ -16,11 +16,15 @@
<file>images/textinput.png</file>
<file>images/toolbar.png</file>
<file>content/LiveCoding.qml</file>
<file>content/ToolBarLayoutExample.qml</file>
<file>content/SpinnerPage.qml</file>
<file>content/LabelPage.qml</file>
<file>content/CheckboxPage.qml</file>
<file>content/ButtonRowPage.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>
</RCC>
......@@ -18,7 +18,6 @@ OTHER_FILES += \
content/TabBarPage.qml \
content/TextInputPage.qml \
content/LiveCoding.qml \
content/ToolBarLayoutExample.qml \
content/SpinnerPage.qml \
content/LabelPage.qml \
content/CheckboxPage.qml \
......
......@@ -29,8 +29,9 @@ NemoWindow {
id: root
width: 320
height: 240
height: 640
property alias header: toolBar
/*! \internal */
default property alias data: contentArea.data
......@@ -38,13 +39,15 @@ NemoWindow {
property alias initialPage: stackView.initialItem
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
color: _bgColor
readonly property int defaultAllowedOrientations: Qt.PortraitOrientation | Qt.LandscapeOrientation
//these are application-wise allowed orientations, i.e. what is used if the current Page doesn't set any
allowedOrientations: defaultAllowedOrientations
//README: allowedOrientations' default value is set in NemoWindow's c++ implementation
//The app developer can overwrite it from QML
onAllowedOrientationsChanged: {
orientationConstraintsChanged()
......@@ -61,8 +64,20 @@ NemoWindow {
//if the current orientation is not allowed anymore, fallback to an allowed one
//stackInitialized check prevents setting an orientation before the stackview
//(but more importantly the initialItem of the stack) has been created
if (stackView.stackInitialized && !isOrientationAllowed(contentArea.filteredOrientation)) {
fallbackToAnAllowedOrientation()
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()
}
}
}
......@@ -127,6 +142,8 @@ NemoWindow {
id: backgroundItem
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
height: __transpose ? Screen.width : Screen.height
rotation: rotationToTransposeToPortrait()
......@@ -153,9 +170,12 @@ NemoWindow {
StackView {
id: stackView
width: parent.width
height: parent.height
anchors.top: root.isUiPortrait ? toolBar.bottom : parent.top
anchors.right: parent.right
anchors.left: root.isUiPortrait ? parent.left : toolBar.right
anchors.bottom: parent.bottom
clip: true
Component.onCompleted: stackInitialized = true
//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)
......@@ -182,8 +202,10 @@ NemoWindow {
}
//update orientation constraints when a Page is pushed/popped
onCurrentItemChanged: if (_isCurrentItemNemoPage() && currentItem.allowedOrientations)
root.orientationConstraintsChanged()
onCurrentItemChanged: {
if (_isCurrentItemNemoPage())
root.orientationConstraintsChanged()
}
//This properties are accessible for free by the Page via Stack.view.<property>
readonly property int orientation: contentArea.uiOrientation
......@@ -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 {
id: orientationState
......@@ -262,6 +322,12 @@ NemoWindow {
rotation: 0
uiOrientation: Qt.PortraitOrientation
}
PropertyChanges {
target: headerDimmer
height: Theme.header.dimmer.height
width: parent.width
rotation: 0
}
},
State {
name: 'Landscape'
......@@ -274,6 +340,12 @@ NemoWindow {
rotation: 90
uiOrientation: Qt.LandscapeOrientation
}
PropertyChanges {
target: headerDimmer
height: Theme.header.dimmer.height
width: parent.height
rotation: -90
}
},
State {
name: 'PortraitInverted'
......@@ -286,6 +358,12 @@ NemoWindow {
rotation: 180
uiOrientation: Qt.InvertedPortraitOrientation
}
PropertyChanges {
target: headerDimmer
height: Theme.header.dimmer.height
width: parent.width
rotation: 0
}
},
State {
name: 'LandscapeInverted'
......@@ -298,6 +376,12 @@ NemoWindow {
rotation: 270
uiOrientation: Qt.InvertedLandscapeOrientation
}
PropertyChanges {
target: headerDimmer
height: Theme.header.dimmer.height
width: parent.height
rotation: -90
}
}
]
......@@ -320,6 +404,13 @@ NemoWindow {
target: contentArea
properties: 'width,height,rotation,uiOrientation'
}
AnchorAnimation {
duration: 0
}
PropertyAction {
target: headerDimmer
properties: 'width,height,rotation'
}
NumberAnimation {
target: contentArea
property: 'opacity'
......
This diff is collapsed.
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 {
property alias color: background.color
property int status: pageStack ? Stack.status : Stack.Inactive
property alias tools: toolBar.data
property alias __dimmer: dimmer
property variant headerTools
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"
default property alias __content: content.data
......@@ -77,31 +73,8 @@ NemoPage {
color: Theme.page.background
}
ToolBar {
id: toolBar
z: 201
}
Item {
id: content
anchors.bottom: parent.bottom
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 }
}
anchors.fill: parent
}
}
......@@ -13,25 +13,27 @@ QML_FILES += \
Spinner.qml \
Label.qml \
Checkbox.qml\
images/disabled-overlay.png
images/disabled-overlay-inverse.png
ButtonRow.qml \
QueryDialog.qml \
Header.qml \
HeaderToolsLayout.qml
OTHER_FILES += qmldir \
$$QML_FILES \
ButtonRow.qml \
QueryDialog.qml
$$QML_FILES
HEADERS += \
qquicknemocontrolsextensionplugin.h \
hacks.h \
nemowindow.h \
nemopage.h
nemopage.h \
qquickfilteringmousearea.h
SOURCES += \
qquicknemocontrolsextensionplugin.cpp \
hacks.cpp \
nemowindow.cpp \
nemopage.cpp
nemopage.cpp \
qquickfilteringmousearea.cpp
target.path = $$[QT_INSTALL_QML]/$$PLUGIN_IMPORT_PATH
......
......@@ -32,5 +32,5 @@ bool Hacks::isOrientationMaskValid(Qt::ScreenOrientations orientations) {
Qt::ScreenOrientations max = (Qt::PortraitOrientation | Qt::LandscapeOrientation
| Qt::InvertedPortraitOrientation | Qt::InvertedLandscapeOrientation);
return (orientations <= max && orientations != 0);
return (orientations <= max && orientations > 0);
}
......@@ -2,7 +2,11 @@
#include "hacks.h"
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
void NemoPage::setAllowedOrientations(Qt::ScreenOrientations allowed)
{
//This way no invalid values can get assigned to allowedOrientations
if (m_allowedOrientations != allowed && Hacks::isOrientationMaskValid(allowed)) {
m_allowedOrientations = allowed;
emit allowedOrientationsChanged();
if (m_allowedOrientations != allowed) {
if (Hacks::isOrientationMaskValid(allowed)) {
m_allowedOrientations = allowed;
emit allowedOrientationsChanged();
} else {
qDebug() << "NemoPage: invalid allowedOrientation!";
}
}
}
......@@ -22,8 +22,10 @@
#include "hacks.h"
NemoWindow::NemoWindow(QWindow *parent) :
QQuickWindow(parent)
QQuickWindow(parent),
m_defaultAllowedOrientations(Qt::PortraitOrientation | Qt::LandscapeOrientation)
{
m_allowedOrientations = m_defaultAllowedOrientations;
}
Qt::ScreenOrientations NemoWindow::allowedOrientations() const
......@@ -31,11 +33,20 @@ Qt::ScreenOrientations NemoWindow::allowedOrientations() const
return m_allowedOrientations;
}
const Qt::ScreenOrientations NemoWindow::defaultAllowedOrientations() const
{
return m_defaultAllowedOrientations;
}
void NemoWindow::setAllowedOrientations(Qt::ScreenOrientations allowed)
{
//This way no invalid values can get assigned to allowedOrientations
if (m_allowedOrientations != allowed && Hacks::isOrientationMaskValid(allowed)) {
m_allowedOrientations = allowed;
emit allowedOrientationsChanged();
if (m_allowedOrientations != allowed) {
if (Hacks::isOrientationMaskValid(allowed)) {
m_allowedOrientations = allowed;
emit allowedOrientationsChanged();
} else {
qDebug() << "NemoWindow: invalid allowedOrientation!";
}
}
}
......@@ -26,10 +26,14 @@ class NemoWindow : public QQuickWindow
{
Q_OBJECT
Q_PROPERTY(Qt::ScreenOrientations allowedOrientations READ allowedOrientations WRITE setAllowedOrientations NOTIFY allowedOrientationsChanged)
Q_PROPERTY(Qt::ScreenOrientations defaultAllowedOrientations READ allowedOrientations)
public:
explicit NemoWindow(QWindow *parent = 0);
Qt::ScreenOrientations allowedOrientations() const;
const Qt::ScreenOrientations defaultAllowedOrientations() const;
void setAllowedOrientations(Qt::ScreenOrientations allowed);
signals:
......@@ -38,7 +42,12 @@ signals:
public slots:
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_defaultAllowedOrientations;
};
#endif // NEMOWINDOW_H
......@@ -16,6 +16,9 @@ Label 1.0 Label.qml
CheckBox 1.0 Checkbox.qml
ButtonRow 1.0 ButtonRow.qml
QueryDialog 1.0 QueryDialog.qml
Header 1.0 Header.qml
HeaderToolsLayout 1.0 HeaderToolsLayout.qml
# MIRRORED CONTROLS:
# These are the controls that we take directly from official QQC.
# 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 @@
#include "hacks.h"
#include "nemowindow.h"
#include "nemopage.h"
#include "qquickfilteringmousearea.h"
QQuickNemoControlsExtensionPlugin::QQuickNemoControlsExtensionPlugin(QObject *parent) :
QQmlExtensionPlugin(parent)
......@@ -41,6 +42,7 @@ void QQuickNemoControlsExtensionPlugin::registerTypes(const char *uri)
qmlRegisterSingletonType<QObject>(uri, 1, 0, "NemoHacks", nemo_hacks_singletontype_provider);
qmlRegisterType<NemoWindow>(uri, 1, 0, "NemoWindow");
qmlRegisterType<NemoPage>(uri, 1, 0, "NemoPage");
qmlRegisterType<QQuickFilteringMouseArea>(uri, 1, 0, "FilteringMouseArea");
}
void QQuickNemoControlsExtensionPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
......
......@@ -46,6 +46,7 @@ Style {
Image {
id: icon
anchors.fill: parent
fillMode: Image.PreserveAspectFit
anchors.margins: 8
source: control.iconSource
}
......
......@@ -50,6 +50,7 @@ NemoTheme::NemoTheme(QObject *parent)
, m_label(new NemoThemeLabel(this))
, m_checkbox(new NemoThemeCheckbox(this))
, m_buttonRow(new NemoThemeButtonRow(this))
, m_header(new NemoThemeHeader(this))
{
loadFromFile(GLACIER_THEME);
int id = QFontDatabase::addApplicationFont("/usr/share/fonts/google-opensans/OpenSans-Regular.ttf");
......@@ -147,6 +148,11 @@ NemoThemeButtonRow * NemoTheme::buttonRow() const
return m_buttonRow;
}
NemoThemeHeader * NemoTheme::header() const
{
return m_header;
}
QString NemoTheme::fontFamily() const
{
return m_fontFamily;
......@@ -389,25 +395,6 @@ void NemoTheme::loadFromFile(const QString &fileName)
// Setting properties for page
QJsonObject stylesPage = styles.value("page").toObject();
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
QJsonObject stylesPageStack = styles.value("pageStack").toObject();
if (stylesPageStack.contains("transitionDuration")) {
......@@ -460,4 +447,26 @@ void NemoTheme::loadFromFile(const QString &fileName)
QJsonObject stylesButtonRow = styles.value("buttonRow").toObject();
m_buttonRow->setBackground(jsonToColor(jsonValue(stylesButtonRow, "background", "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 @@
#include "nemothemelabel.h"
#include "nemothemecheckbox.h"
#include "nemothemebuttonrow.h"
#include "nemothemeheader.h"
class NemoTheme: public QObject
{
......@@ -54,6 +55,7 @@ class NemoTheme: public QObject
Q_PROPERTY(NemoThemeLabel * label READ label CONSTANT)
Q_PROPERTY(NemoThemeCheckbox * checkbox READ checkbox CONSTANT)
Q_PROPERTY(NemoThemeButtonRow * buttonRow READ buttonRow CONSTANT)
Q_PROPERTY(NemoThemeHeader * header READ header CONSTANT)
Q_PROPERTY(QString fontFamily READ fontFamily CONSTANT)
public:
explicit NemoTheme(QObject *parent = 0);
......@@ -73,6 +75,7 @@ public:
NemoThemeLabel * label() const;
NemoThemeCheckbox * checkbox() const;
NemoThemeButtonRow * buttonRow() const;
NemoThemeHeader * header() const;
QString fontFamily() const;
public Q_SLOTS:
void loadFromFile(const QString &fileName);
......@@ -94,6 +97,7 @@ private:
NemoThemeLabel * m_label;
NemoThemeCheckbox * m_checkbox;
NemoThemeButtonRow * m_buttonRow;
NemoThemeHeader * m_header;
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 @@
NemoThemePage::NemoThemePage(QObject *parent)
: QObject(parent)
, m_dimmer(new NemoThemePageDimmer(this))
{
}
......@@ -40,8 +39,3 @@ void NemoThemePage::setBackground(const QColor &background)
emit backgroundChanged();
}
}
NemoThemePageDimmer * NemoThemePage::dimmer() const
{
return m_dimmer;
}
......@@ -25,23 +25,19 @@
#include <QtCore/QObject>
#include <QtGui/QColor>
#include "nemothemepagedimmer.h"
class NemoThemePage: public QObject
{
Q_OBJECT
Q_PROPERTY(QColor background READ background NOTIFY backgroundChanged)
Q_PROPERTY(NemoThemePageDimmer * dimmer READ dimmer CONSTANT)
public:
explicit NemoThemePage(QObject *parent = 0);
QColor background() const;
void setBackground(const QColor &background);
NemoThemePageDimmer * dimmer() const;
Q_SIGNALS:
void backgroundChanged();
private:
QColor m_background;
NemoThemePageDimmer * m_dimmer;
};
#endif //NEMOTHEMEPAGE_H
......@@ -24,7 +24,7 @@
NemoThemePageDimmer::NemoThemePageDimmer(QObject *parent)
: QObject(parent)
, m_height(15)
, m_height(16)
, m_startPosition(0)
, m_endPosition(1.0)
{
......@@ -71,8 +71,8 @@ void NemoThemePageDimmer::setHeight(int height)
void NemoThemePageDimmer::setHeightDefault()
{
if (m_height != 15) {
m_height = 15;
if (m_height != 16) {
m_height = 16;
emit heightChanged();
}
}
......
......@@ -48,12 +48,12 @@ void QQuickNemoStyleExtensionPlugin::registerTypes(const char *uri)
qmlRegisterUncreatableType<NemoThemeToolBar>(uri, 1, 0, "NemoThemeToolBar", reason);
qmlRegisterUncreatableType<NemoThemeWindow>(uri, 1, 0, "NemoThemeWindow", reason);
qmlRegisterUncreatableType<NemoThemePage>(uri, 1, 0, "NemoThemePage", reason);
qmlRegisterUncreatableType<NemoThemePageDimmer>(uri, 1, 0, "NemoThemePageDimmer", reason);
qmlRegisterUncreatableType<NemoThemeSpinner>(uri, 1, 0, "NemoThemeSpinner", reason);
qmlRegisterUncreatableType<NemoThemeLabel>(uri, 1, 0, "NemoThemeLabel", reason);
qmlRegisterUncreatableType<NemoThemeCheckbox>(uri, 1, 0, "NemoThemeCheckbox", 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);
}
......
......@@ -84,12 +84,13 @@ HEADERS += \
autogenerated/nemothemetoolbar.h \
autogenerated/nemothemewindow.h \
autogenerated/nemothemepage.h \
autogenerated/nemothemepagedimmer.h \
autogenerated/nemothemespinner.h \
autogenerated/nemothemelabel.h \
autogenerated/nemothemecheckbox.h \
autogenerated/nemothemepagestack.h \
autogenerated/nemothemebuttonrow.h
autogenerated/nemothemebuttonrow.h \
autogenerated/nemothemeheader.h \
autogenerated/nemothemeheaderdimmer.h
SOURCES += \
qquicknemostyleextensionplugin.cpp \
......@@ -103,12 +104,13 @@ SOURCES += \
autogenerated/nemothemetoolbar.cpp \
autogenerated/nemothemewindow.cpp \
autogenerated/nemothemepage.cpp \
autogenerated/nemothemepagedimmer.cpp \
autogenerated/nemothemespinner.cpp \
autogenerated/nemothemelabel.cpp \
autogenerated/nemothemecheckbox.cpp \
autogenerated/nemothemepagestack.cpp \
autogenerated/nemothemebuttonrow.cpp
autogenerated/nemothemebuttonrow.cpp \
autogenerated/nemothemeheader.cpp \
autogenerated/nemothemeheaderdimmer.cpp
INSTALLS += target images qmlfiles themes
......
......@@ -45,11 +45,7 @@
"background": "#000000"
},
"page": {
"background": "#000000",
"dimmer": {
"startColor": "black",
"endColor": "transparent"
}
"background": "#000000"
},
"spinner": {
"primaryColor": "#ffffff",
......@@ -65,6 +61,13 @@
"buttonRow": {
"background": "#313131",
"buttonColor": "#0091e5"
},
"header": {
"background": "#000000",
"dimmer": {
"startColor": "black",
"endColor": "transparent"
}
}
}
}
......@@ -45,11 +45,7 @@
"background": "#000000"
},
"page": {
"background": "#000000",
"dimmer": {
"startColor": "black",
"endColor": "transparent"
}
"background": "#000000"
},
"spinner": {
"primaryColor": "accentColor",
......@@ -64,6 +60,13 @@
},
"pageStack": {
"transitionDuration": 1500
},
"header": {
"background": "#000000",
"dimmer": {
"startColor": "black",
"endColor": "transparent"
}
}
}
}
......@@ -73,10 +73,6 @@
{
"name": "background",
"type": "QColor"
},
{
"name": "dimmer",
"object": "PageDimmer"
}
]
},
......@@ -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",
"properties": [
......@@ -256,6 +224,47 @@
"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": [
......@@ -306,6 +315,10 @@
{
"name": "buttonRow",
"object": "ButtonRow"
},
{
"name": "header",
"object": "Header"
}
],
"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