Contents |
This tutorial will demonstrate a simple (but non-trivial) app which uses
This tutorial assumes you have the MeeGo SDK installed on Linux
See: http://wiki.meego.com/SDK/Docs/1.2/MeeGo_SDK_1.2_Preview
Also assumed: you have a a chroot / Xephyr environment set up.
This tutorial will use meego-ux-components objects like:
For other uses of Meego UX Components, and another tutorial of Book Menus, See:
Other QML Tutorials:
qtcreator &>/dev/null &
... screen shots ...
import QtQuick 1.0
Rectangle {
width: 360
height: 360
Text {
text: "Hello World"
anchors.centerIn: parent
}
MouseArea {
anchors.fill: parent
onClicked: {
Qt.quit();
}
}
}
(CTRL-R or Green "Play" Button)
<screen shot>
Clicking it closes the app (Qt.quit())
The last 2 Component statements are commented out so the app will run as is before creating more files.
import Qt 4.7
import MeeGo.Components 0.1
Window {
id: window
bookMenuModel: [ qsTr("Button Demo"), qsTr("Book 2") ]
bookMenuPayload: [ gallery, book2 ]
bookMenuTitle: qsTr("Book Menu")
Component.onCompleted: switchBook( gallery )
//Component { id: gallery; MainPage {} }
//Component { id: book2; Book2 {} }
}
Run the app and see the Book Menu. If you click on one of the menu items, you'll notice an error because of the commented out Component statements.
(from the meego-ux-widgetgallery example)
/*
* Copyright 2011 Intel Corporation.
*
* This program is licensed under the terms and conditions of the
* LGPL, version 2.1. The full text of the LGPL Licence is at
* http://www.gnu.org/licenses/lgpl.html
*/
/* This file contains relativy empty pages and is meant to demonstrate the
book/page concept */
import Qt 4.7
PageDummy {
id: pageDummy
innerText: qsTr("book 2, page 1")
rectColor: "lightblue"
showButton: true
buttonLabel: qsTr("Page 2")
pageTitle: qsTr("Dummy book 2")
onClicked: { addPage( page2 ) }
Component{
id: page2;
PageDummy {
id: pageDummy2
innerText: qsTr("book 2, page 2")
rectColor: "lightgreen"
showButton: true
buttonLabel: qsTr("Page 3")
pageTitle: qsTr("Dummy book 2")
onClicked: { addPage( page3 )
}
}
}
Component{
id: page3;
PageDummy {
id: pageDummy3
innerText: qsTr("book 2, page 3")
rectColor: "orange"
showButton: true
buttonLabel: qsTr("Page 4")
pageTitle: qsTr("Dummy book 2")
onClicked: { addPage( page4 )
}
}
}
Component{
id: page4;
PageDummy {
id: pageDummy4
innerText: qsTr("book 2, page 4")
rectColor: "darkgrey"
pageTitle: qsTr("Dummy book 2")
}
}
}
The file Book2.qml references PageDummy.qml, so create it the same way as Book2.qml
/*
* Copyright 2011 Intel Corporation.
*
* This program is licensed under the terms and conditions of the
* LGPL, version 2.1. The full text of the LGPL Licence is at
* http://www.gnu.org/licenses/lgpl.html
*/
/* This file is just meant as a dummy to quickly create pages for
demonstrating the book/page concept. */
import Qt 4.7
import MeeGo.Components 0.1
AppPage {
id: pageDummy
property alias innerText: rectText.text //text shown in the rect
property alias rectColor: innerRect.color //color of the rect in the middle
property alias showButton: nextButton.visible //nextButton visible?
property alias buttonLabel: nextButton.text //nextButton label
property string bookTitle: "book title" //shown in the title bar
signal clicked()
anchors.fill: parent
Rectangle { z: -1; anchors.fill: parent; color: "grey" } //background
Rectangle {
id: innerRect
anchors.fill: parent
anchors.margins: 50
color: "lightgreen"
Text {
id: rectText
text: "dummy page"
anchors.centerIn: parent
font.pixelSize: 40
color: "black"
}
}
Button {
id: nextButton
visible: false
text: "next page >"
anchors.right: innerRect.right
anchors.bottom: innerRect.bottom
anchors.margins: 10
onClicked: { pageDummy.clicked() }
}
}
You will see the use of the meego-ux-components "Button" and "AppPage" components in PageDummy.qml
Component {
id: gallery;
AppPage {id: dummy2}
}
// Dummy page until MainPage.qml is defined
AppPage { id: gallery; }
//Component { id: gallery; MainPage {} }
Component { id: book2; Book2 {} }
Since the MainPage.qml file isn't created yet, we use a dummy AppPage placeholder temporarily to prevent a run-time error when invoking the menu.
You can now click on the Book2 menu and see a new page.
We will use a C++ QAbstractListModel to repersent out list.
Create the file mymodel.h by right-clicking on the simple-app project name and "Add New..." a C++ Header File
Paste this into mymodel.h
#ifndef MYMODEL_H
#define MYMODEL_H
#include <QAbstractListModel>
#include <QColor>
struct Data {
Data( const char* name, const QString& flag, double population )
: name(name), flag(flag), population(population) {}
QString name;
QString flag;
double population;
};
const int FlagRole = Qt::UserRole + 1;
const int PopulationRole = Qt::UserRole + 2;
class MyModel : public QAbstractListModel
{
public:
MyModel();
int rowCount( const QModelIndex& ) const;
QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const;
QList< Data > m_data;
};
#endif // MYMODEL_H
#include "mymodel.h"
#include <QByteArray>
MyModel::MyModel()
{
m_data
<< Data("Denmark", "qrc:images/denmark.jpg", 5.4)
<< Data("Sweden", "qrc:images/sweden.jpg", 9.3)
<< Data("Iceland", "qrc:images/iceland.jpg", 3.2)
<< Data("Norway", "qrc:images/norway.jpg", 4.8)
<< Data("Finland", "qrc:images/finland.jpg", 5.3);
// By default the DisplayRole is mapped to the propery "display"
QHash<int, QByteArray> mapping =roleNames();
mapping.insert( FlagRole, "flag");
mapping.insert( PopulationRole, "population");
setRoleNames( mapping );
}
int MyModel::rowCount( const QModelIndex& ) const
{
return m_data.count();
}
QVariant MyModel::data(const QModelIndex &index, int role) const
{
if ( !index.isValid() )
return QVariant();
Data data = m_data[index.row()];
if ( role == Qt::DisplayRole )
return data.name;
else if ( role == FlagRole )
return data.flag;
else if ( role == PopulationRole )
return data.population;
else
return QVariant();
}
Modify main.cpp by replacing its contents with this:
#include <QtGui/QApplication>
#include <QDeclarativeEngine>
#include <QDeclarativeContext>
#include "qmlapplicationviewer.h"
#include "mymodel.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MyModel model;
QmlApplicationViewer viewer;
viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
viewer.setMainQmlFile(QLatin1String("qml/simple-app/main.qml"));
viewer.showExpanded();
// Register the model "myModel" with QML
QDeclarativeContext *context = viewer.engine()->rootContext();
context->setContextProperty("myModel", &model);
return app.exec();
}
A Component called MainPage.qml which will display row of Buttons that act like Tabs in a QTabView.
The area below the buttons are filled with one of two mini-apps (List View sample, and mini file browser)
/*
* Copyright 2011 Intel Corporation.
*
* This program is licensed under the terms and conditions of the
* LGPL, version 2.1. The full text of the LGPL Licence is at
* http://www.gnu.org/licenses/lgpl.html
*/
/* The MainPage lets the user switch between different contents which
show the widgets available in these components. */
//import Qt 4.7
import QtQuick 1.0
import MeeGo.Components 0.1
AppPage {
id: mainPage
// This will be the first app / content displayed in the Button Demo page
state: "flags"
pageTitle: qsTr("Button Demo")
// Demo an Action Menu......
// Comment the block below to see a new Action Menu
// actionMenuModel: [ qsTr("Landscape"),
// qsTr("Portrait"),
// qsTr("Inv. Landscape"),
// qsTr("Inv. Portrait") ]
// actionMenuPayload: [ 1, 2, 3, 4 ]
// actionMenuTitle: qsTr("Action Menu")
// onActionMenuTriggered: {
// if( selectedItem == 1) {
// window.orientation = 1
// } else if( selectedItem == 2) {
// window.orientation = 2
// } else if( selectedItem == 3) {
// window.orientation = 3
// } else if( selectedItem == 4) {
// window.orientation = 0
// }
// }
Item {
id: contentButtons
// Some Debug output to stderr ...
onVisibleChanged: {
console.log("xxxxxxxxxxxxxx 1 Parent wid ", parent.width);
console.log("xxxxxxxxxxxxxx 2 Wid ", width);
}
onWidthChanged: {
console.log("wwwwwwwwwwwwww 1 Parent wid ", parent.width);
console.log("wwwwwwwwwwwwww 2 Wid ", width);
}
property int buttonWidth: parent.width * 0.2;
property int buttonHeight: 60;
property int buttonMargins: 2;
property string activeButtonImage: "image://themedimage/widgets/common/button/button-default"
property string buttonImage: "image://themedimage/widgets/common/button/button"
property string buttonImagePressed: "image://themedimage/widgets/common/button/button-default-pressed"
//width: 2 * buttonWidth + 3 * buttonMargins
height: buttonHeight
anchors.top: parent.top
anchors.topMargin: 10
anchors.horizontalCenter: parent.horizontalCenter
Button {
id: flagsButton
active: true
width: parent.buttonWidth; height: parent.buttonHeight
// Since there are only two buttons, the right of this button is near the center.
anchors { margins: parent.buttonMargins; right: parent.horizontalCenter;}
text: qsTr("Flags")
onClicked: {
mainPage.state = "flags"
active = true
browserButton.active = false
}
}
Button {
id: browserButton
width: parent.buttonWidth; height: parent.buttonHeight
// This button is to the right of the flags button
anchors { margins: parent.buttonMargins; left: flagsButton.right }
text: qsTr("File Browser")
onClicked: {
mainPage.state = "browser"
active = true
flagsButton.active = false
}
}
}
// This item holds the contents of the selected button and fills the rest of the window
Item {
id: contentSpace
anchors { top: contentButtons.bottom; bottom: parent.bottom; left: parent.left; right: parent.right }
}
// One of these two components will fill the contentSpace Item above.
FlagContent { id: flagContent; anchors.fill: contentSpace; anchors.top: contentButtons.bottom }
//Placeholder until BrowserContent.qml is present
Rectangle { id: browserContent; anchors.fill: contentSpace; anchors.top: contentButtons.bottom; color: "red"; }
//BrowserContent { id: browserContent; anchors.fill: contentSpace }
Rectangle { z: -1; anchors.fill: parent; color: "grey" } //background
states: [
State {
name: "flags"
PropertyChanges { target: flagContent; visible: true }
PropertyChanges { target: browserContent; visible: false }
},
State {
name: "browser"
PropertyChanges { target: flagContent; visible: false }
PropertyChanges { target: browserContent; visible: true }
}
]
}
This shows an example of using a QML ListView - which uses a delegate for a row to be displayed
The model statement references a C++ model called "myModel" defined in mymodel.{h,cpp}
import QtQuick 1.0
ListView {
clip: true
model: myModel
anchors.top: parent.bottom
anchors.fill: parent
delegate: Rectangle {
color: Qt.rgba(0.9,0.9,0.9)
height: childrenRect.height
width: parent.width
Image {
id: image
source: flag
width: 64
height: 64
fillMode: Image.PreserveAspectFit
anchors { left:parent.left; leftMargin:30}
}
Text {
text: display + "\n" +"population: " + population + " mill."
anchors { left:image.right; verticalCenter: image.verticalCenter; leftMargin: 5 }
}
}
}
Remove this:
AppPage { id: gallery; }
Uncomment this line:
Component { id: gallery; MainPage {} }
Copy the images and .qrc file from the solution directory:
Media:Qml-button-ex-rename-to-tgz.jpg
Add this to your simple-app.pro
RESOURCES += resources.qrc
Since we added new .cpp and .h files, it would be a good idea to Build->Run Qmake; Build->Rebuild All
Run...
To see another mini-app for the "Browser" button, copy these files to your project from the solution directory:
Media:Qml-button-ex-rename-to-tgz.jpg
Move these files to your project's qml directory (sub directory of project) BrowserContent.qml FileSystemView.qml ImageViewer.qml PathDisplay.qml Move these files to your project's top-level directory dirmodel.cpp dirmodel.h main.cpp (new code added to register a Directory Model with QML named "_model"
Modify your project's .pro file by adding
We were using a generic red rectangle to hold a space for the BrowserContent Component, we can now use it.
Rectangle { id: browserContent; anchors.fill: contentSpace; anchors.top: contentButtons.bottom; color: "red"; }
//BrowserContent { id: browserContent; anchors.fill: contentSpace }
With...
BrowserContent { id: browserContent; anchors.fill: contentSpace }
Clicking on the Browser button should allow you to browse the file system. If you click on a jpg or png, the image will be previewed.