code:
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
**     the names of its contributors may be used to endorse or promote
**     products derived from this software without specific prior written
**     permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
** $QT_END_LICENSE$
**
****************************************************************************/

import QtQuick 1.0

Rectangle {
    id: container

    property variant text
    signal clicked

    height: text.height + 10;
    width: text.width + 20
    border.width: 1
    radius: 4
    smooth: true

    gradient: Gradient {
        GradientStop {
            position: 0.0
            color: !mouseArea.pressed ? activePalette.light : activePalette.button
        }
        GradientStop {
            position: 1.0
            color: !mouseArea.pressed ? activePalette.button : activePalette.dark
        }
    }

    SystemPalette { id: activePalette }

    MouseArea {
        id: mouseArea
        anchors.fill: parent
        onClicked: container.clicked()
    }

    Text {
        id: text
        anchors.centerIn: parent
        font.pointSize: 20
        text: parent.text
        color: activePalette.buttonText
    }
}


code:
/*
* Copyright (c) 2011 Mladen Milankovic <mmlado at gmail.com>.
*
* This file is part of Demine application
*
* Demine is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Demine 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 General Public License for more details.

* You should have received a copy of the GNU General Public License
* along with Demine.  If not, see <http://www.gnu.org/licenses/>.
*/

import QtQuick 1.0

Rectangle {
    id: dialog
    anchors.fill: parent
    border.width: 1
    opacity: 0
    visible: opacity > 0
    color: 'black'

    signal closed
    signal opened

    Behavior on opacity {
        NumberAnimation { duration: 1000 }
    }

    Text {
        id: dialogText;
        anchors.centerIn: parent;
        color:  'white'
        font.pixelSize: 40
        text: ""
    }

    MouseArea {
        anchors.fill: parent;
        onClicked: forceClose();
    }

    function forceClose() {
        if(dialog.opacity == 0)
            return; //already closed
        dialog.closed();
        dialog.opacity = 0;
    }

    function show(txt) {
        dialog.opened();
        dialogText.text = txt;
        dialog.opacity = 0.5;
    }
}

repo_name: snapshot/demine

license: unknown


code:
/*
* Copyright (c) 2011 Mladen Milankovic <mmlado at gmail.com>.
*
* This file is part of Demine application
*
* Demine is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Demine 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 General Public License for more details.

* You should have received a copy of the GNU General Public License
* along with Demine.  If not, see <http://www.gnu.org/licenses/>.
*/

import QtQuick 1.0

Rectangle {
    id: options
    width: 800
    height: 480
    anchors.fill: parent
    border.width: 1
    opacity: 0
    visible: opacity > 0
    color: 'black'

    signal canceled
    signal saved(int numOfColumns, int numOfRows, int numOfMines)

    Behavior on opacity {
        NumberAnimation { duration: 1000 }
    }

    Grid {
        spacing: 5
        rows: 5
        columns: 2
        anchors.rightMargin: 20
        anchors.leftMargin: 20
        anchors.bottomMargin: 20
        anchors.topMargin: 20
        anchors.fill: parent

        Text {
            height: numOfColumns.height + 6
            width: parent.width/2
            verticalAlignment: Text.AlignVCenter
            horizontalAlignment: Text.AlignRight
            color: "white"
            text: "Columns:"
        }

        Rectangle {
            width: 50
            height: numOfColumns.height + 6
            color: "white"

            TextInput {
                id: numOfColumns
                text: main.columns
                anchors.rightMargin: 3
                anchors.leftMargin: 3
                anchors.bottomMargin: 3
                anchors.topMargin: 3
                anchors.fill: parent
                color: 'black'
                validator: IntValidator {
                    bottom: 2
                    top: 50
                }
            }
        }

        Text {
            height: numOfColumns.height + 6
            width: parent.width/2
            verticalAlignment: Text.AlignVCenter
            horizontalAlignment: Text.AlignRight
            color: "white"
            text: "Rows:"
        }

        Rectangle {
            width: 50
            height: numOfRows.height + 6
            color: "white"
            TextInput {
                id: numOfRows
                color: "black"
                text: main.rows
                anchors.fill: parent
                anchors.topMargin: 3
                anchors.rightMargin: 3
                anchors.bottomMargin: 3
                anchors.leftMargin: 3
                validator: IntValidator {
                    top: 50
                    bottom: 2
                }
            }
        }

        Text {
            height: numOfColumns.height + 6
            width: parent.width/2
            verticalAlignment: Text.AlignVCenter
            horizontalAlignment: Text.AlignRight
            color: "white"
            text: "Mines:"
        }

        Rectangle {
            width: 50
            height: numOfMines.height + 6
            color: "white"
            TextInput {
                id: numOfMines
                color: "black"
                text: main.mines
                anchors.fill: parent
                anchors.topMargin: 3
                anchors.rightMargin: 3
                anchors.bottomMargin: 3
                anchors.leftMargin: 3
                validator: IntValidator {
                    top: 100
                    bottom: 2
                }
            }
        }

        Rectangle {
            height:btnSave.height
            width: parent.width/2
            color: 'black'
            Button {
                id: btnSave
                text: 'Save'
                anchors.centerIn: parent
                onClicked: {
                    options.saved(parseInt(numOfColumns.text), parseInt(numOfRows.text), parseInt(numOfMines.text));
                    forceClose();
                }
            }
        }
        Rectangle {
            height:btnCancel.height
            width: parent.width/2
            color: 'black'
            Button {
                id: btnCancel
                text: 'Cancel'
                anchors.centerIn: parent
                onClicked: {
                    options.canceled();
                    forceClose();
                }
            }
        }

    }

    function forceClose() {
        if(options.opacity == 0)
            return; //already closed
        options.opacity = 0;
    }

    function show(txt) {
        options.opacity = 1;
    }
}


code:
/*
* Copyright (c) 2011 Mladen Milankovic <mmlado at gmail.com>.
*
* This file is part of Demine application
*
* Demine is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Demine 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 General Public License for more details.

* You should have received a copy of the GNU General Public License
* along with Demine.  If not, see <http://www.gnu.org/licenses/>.
*/

import QtQuick 1.0

Flipable {
    id: field
    //border.width: 1
    width: parent.width / 10
    height: parent.width / 10

    property bool mine: false
    property int hint: 0
    property bool flag: false
    property variant neighbors: new Array()
    property int angle: 0
    property bool flipped: false

    signal opened
    signal flagged(bool status)
    signal gameOver

    transform: Rotation {
        origin.x: field.width/2;
        origin.y: field.height/2;
        axis.x: 0;
        axis.y: 1;
        axis.z: 0;
        angle: field.angle
    }

    states: State {
            name: 'back'
            PropertyChanges { target: field; angle: 180 }
            when: field.flipped
            StateChangeScript {
                script: reveal();
            }
    }

    transitions: Transition {
        RotationAnimation { easing.type: Easing.InOutQuad; duration: 1000 }
    }

    front: Rectangle {
        id: cover
        color: '#00d300'
        anchors.fill: parent
        border.width: 3
        radius: width / 10

        Image {
            id: imgFlag
            source: "images/flag.svg"
            opacity: flag
            Behavior on opacity { NumberAnimation {} }
            anchors.fill: parent
        }

    }

    back: Rectangle {
        anchors.fill: parent
        border.width: 3
        radius: width / 10
        color: '#ab2b00'
        Text {
            id: content
            text: hint
            color: 'white'
            font.pixelSize: field.height * 0.8
            anchors.centerIn: parent
            opacity: !mine && hint > 0
        }

        Image {
            id: bomb
            source: "images/mine.svg"
            anchors.fill: parent
            opacity: mine
        }
    }

    MouseArea {
        anchors.fill: parent;
        acceptedButtons: Qt.LeftButton | Qt.RightButton
        onClicked: {
            if (field.state == 'opened') return;
            if (mouse.button == Qt.RightButton) {
                flag = !flag;
            } else {
                if (flipped || flag) return;
                field.flipped = true;
            }
        }
        onPressAndHold: {
            if (field.state == 'opened') return;
            flag = !flag;
            field.flagged(flag);
        }
    }

    function initialize() {
        mine = false;
        flag = false;
        hint = 0;
        angle = 0;
        flipped = false;
    }

    function setNeighbors(n) {
        neighbors = n;
    }

    function addMine() {
        mine = true;
        for (var i = 0; i < neighbors.length; i++) {
            neighbors[i].mineInNeighborhood();
        }
    }

    function mineInNeighborhood() {
        if (mine) return;
        hint++;
    }

    function reveal() {
        if (mine) {
            field.gameOver();
            return;
        }
        if (flag) {
            return;
        }
        field.opened();
        if (!hint) {
            for (var i = 0; i < neighbors.length; i++) {
                if (neighbors[i].flag) continue;
                neighbors[i].flipped = true;
            }
        }
    }
}


code:
/*
* Copyright (c) 2011 Mladen Milankovic <mmlado at gmail.com>.
*
* This file is part of Demine application
*
* Demine is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Demine 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 General Public License for more details.

* You should have received a copy of the GNU General Public License
* along with Demine.  If not, see <http://www.gnu.org/licenses/>.
*/

import QtQuick 1.0

Grid {
    id: table
    columns: 10
    rows: 10
    /*height:  (parent.width  / 10) * (rows * (1 + spacing) )
    width: (parent.width / 10) * (columns * (1 + spacing) )*/
    anchors.fill: parent
    spacing: 5
    property int fieldSize: 80
    property int openedFields: 0
    property int numOfMines: 14
    property int flags: 0

    signal lost
    signal won
    signal firstOpen
    signal flag(int number)

    Repeater {
        model: table.columns * table.rows
        delegate: Field {
            width: table.fieldSize -table.spacing
            height: table.fieldSize - table.spacing
            onOpened: table.fieldOpened()
            onGameOver:  table.gameOver()
            onFlagged: {
                if (status) flags++;
                else flags--;
                table.flag(flags);
            }
        }
    }

    Component.onCompleted: {
        initialize();
        newGame();
    }

    function initialize() {
        for (var pos = 0; pos < (table.columns * table.rows); pos++) {
            var neighbors = Array();
            var c;
            var row;
            var cols;
            for (var y = -1; y <= 1; y++) {
                for (var x = -1; x <= 1; x++) {
                    if (!x && !y) continue;
                    cols = pos % table.columns;
                    row = (pos - (cols)) / table.columns;
                    if ((cols + x < 0) || (cols + x >= table.columns) || (row + y < 0) || (row + y >= table.rows)) continue;
                    c = table.children[(row + y) * table.columns + cols + x];
                    if (c !== null) {
                        neighbors.push(c);
                    }
                }
            }
            table.children[pos].setNeighbors(neighbors);
        }
    }

    function newGame() {
        openedFields = 0;
        flags = 0;
        for (var i = 0; i < (table.columns * table.rows); i++) {
            table.children[i].initialize();
        }
        var position;
        for (var i = 0; i < numOfMines; i++) {
            position = Math.floor(Math.random()*(table.columns * table.rows));
            while (table.children[position].mine) {
                position = Math.floor(Math.random()*(table.columns * table.rows));
            }
            table.children[position].addMine(position);
        }
    }

    function fieldOpened() {
        if (!openedFields) table.firstOpen()
        openedFields++;
        if (openedFields == (table.columns * table.rows - table.numOfMines)) {
            table.won();
        }
    }

    function gameOver() {
        table.lost();
    }
}


code:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   width="64px"
   height="64px"
   id="svg2985"
   version="1.1"
   inkscape:version="0.48.1 r9760"
   sodipodi:docname="flag.svg">
  <defs
     id="defs2987" />
  <sodipodi:namedview
     id="base"
     pagecolor="#ffffff"
     bordercolor="#666666"
     borderopacity="1.0"
     inkscape:pageopacity="0.0"
     inkscape:pageshadow="2"
     inkscape:zoom="11"
     inkscape:cx="16.909091"
     inkscape:cy="30.493769"
     inkscape:current-layer="layer1"
     showgrid="true"
     inkscape:document-units="px"
     inkscape:grid-bbox="true"
     inkscape:window-width="1680"
     inkscape:window-height="995"
     inkscape:window-x="-4"
     inkscape:window-y="-1"
     inkscape:window-maximized="1">
    <inkscape:grid
       type="xygrid"
       id="grid2993" />
  </sodipodi:namedview>
  <metadata
     id="metadata2990">
    <rdf:RDF>
      <cc:Work
         rdf:about="">
        <dc:format>image/svg+xml</dc:format>
        <dc:type
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
        <dc:title />
      </cc:Work>
    </rdf:RDF>
  </metadata>
  <g
     id="layer1"
     inkscape:label="Layer 1"
     inkscape:groupmode="layer">
    <rect
       style="fill:#505050;fill-opacity:1;fill-rule:nonzero;stroke:none"
       id="rect3030"
       width="3"
       height="55"
       x="6"
       y="4" />
    <path
       style="fill:#a00000;stroke:none;fill-opacity:1"
       d="M 6,4 59,19 6,34 z"
       id="path3032"
       inkscape:connector-curvature="0" />
  </g>
</svg>


code:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
   xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:xlink="http://www.w3.org/1999/xlink"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   width="64px"
   height="64px"
   id="svg3104"
   version="1.1"
   inkscape:version="0.48.1 r9760"
   sodipodi:docname="New document 10">
  <defs
     id="defs3106">
    <linearGradient
       inkscape:collect="always"
       id="linearGradient5521">
      <stop
         style="stop-color:#626667;stop-opacity:1;"
         offset="0"
         id="stop5523" />
      <stop
         style="stop-color:#626667;stop-opacity:0;"
         offset="1"
         id="stop5525" />
    </linearGradient>
    <linearGradient
       id="linearGradient4063">
      <stop
         style="stop-color:#5b5f60;stop-opacity:1;"
         offset="0"
         id="stop4065" />
      <stop
         style="stop-color:#5b5f60;stop-opacity:0;"
         offset="1"
         id="stop4067" />
    </linearGradient>
    <linearGradient
       inkscape:collect="always"
       id="linearGradient4053"
       osb:paint="gradient">
      <stop
         style="stop-color:#000000;stop-opacity:1;"
         offset="0"
         id="stop4055" />
      <stop
         style="stop-color:#000000;stop-opacity:0;"
         offset="1"
         id="stop4057" />
    </linearGradient>
    <radialGradient
       inkscape:collect="always"
       xlink:href="#linearGradient5521"
       id="radialGradient5527"
       cx="29.965534"
       cy="37.925095"
       fx="29.965534"
       fy="37.925095"
       r="26.272728"
       gradientUnits="userSpaceOnUse"
       gradientTransform="matrix(5.1071169,-5.1891099,3.3633319,3.3101882,-242.76168,82.025601)" />
  </defs>
  <sodipodi:namedview
     id="base"
     pagecolor="#ffffff"
     bordercolor="#666666"
     borderopacity="1.0"
     inkscape:pageopacity="0.0"
     inkscape:pageshadow="2"
     inkscape:zoom="8.8122669"
     inkscape:cx="18.583977"
     inkscape:cy="36.968676"
     inkscape:current-layer="layer1"
     showgrid="true"
     inkscape:document-units="px"
     inkscape:grid-bbox="true"
     inkscape:snap-grids="false"
     showguides="false"
     inkscape:window-width="1680"
     inkscape:window-height="995"
     inkscape:window-x="-4"
     inkscape:window-y="-1"
     inkscape:window-maximized="1">
    <inkscape:grid
       type="xygrid"
       id="grid3134"
       empspacing="5"
       visible="true"
       enabled="true"
       snapvisiblegridlinesonly="true" />
  </sodipodi:namedview>
  <metadata
     id="metadata3109">
    <rdf:RDF>
      <cc:Work
         rdf:about="">
        <dc:format>image/svg+xml</dc:format>
        <dc:type
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
        <dc:title></dc:title>
      </cc:Work>
    </rdf:RDF>
  </metadata>
  <g
     id="layer1"
     inkscape:label="Base"
     inkscape:groupmode="layer">
    <path
       sodipodi:type="arc"
       style="fill:url(#radialGradient5527);fill-opacity:1;opacity:1;fill-rule:nonzero"
       id="path3130"
       sodipodi:cx="38.272728"
       sodipodi:cy="31.727272"
       sodipodi:rx="26.272728"
       sodipodi:ry="26.272728"
       d="m 64.545456,31.727272 a 26.272728,26.272728 0 1 1 -52.545456,0 26.272728,26.272728 0 1 1 52.545456,0 z"
       transform="matrix(1.0263929,0,0,1.0263929,-7.1562324,-0.59850525)" />
  </g>
  <g
     inkscape:groupmode="layer"
     id="layer3"
     inkscape:label="Circles">
    <path
       sodipodi:type="arc"
       style="fill:none;stroke:#000000;stroke-opacity:1"
       id="path5530"
       sodipodi:cx="32.000847"
       sodipodi:cy="30.750895"
       sodipodi:rx="26.894329"
       sodipodi:ry="26.894329"
       d="m 58.895176,30.750895 a 26.894329,26.894329 0 1 1 -53.7886582,0 26.894329,26.894329 0 1 1 53.7886582,0 z"
       transform="matrix(0.69720063,0,0,0.69720063,9.9382462,10.560457)" />
    <path
       sodipodi:type="arc"
       style="fill:none;stroke:#000000;stroke-opacity:1"
       id="path5530-4"
       sodipodi:cx="32.000847"
       sodipodi:cy="30.750895"
       sodipodi:rx="26.894329"
       sodipodi:ry="26.894329"
       d="m 58.895176,30.750895 a 26.894329,26.894329 0 1 1 -53.7886582,0 26.894329,26.894329 0 1 1 53.7886582,0 z"
       transform="matrix(0.60000282,0,0,0.60000282,13.208224,13.230246)" />
    <path
       sodipodi:type="arc"
       style="fill:none;stroke:#000000;stroke-opacity:1"
       id="path5530-4-4"
       sodipodi:cx="32.000847"
       sodipodi:cy="30.750895"
       sodipodi:rx="26.894329"
       sodipodi:ry="26.894329"
       d="m 58.895176,30.750895 a 26.894329,26.894329 0 1 1 -53.7886582,0 26.894329,26.894329 0 1 1 53.7886582,0 z"
       transform="matrix(0.52958208,0,0,0.52958208,15.507684,15.373597)" />
    <path
       sodipodi:type="arc"
       style="fill:none;stroke:#000000;stroke-opacity:1"
       id="path5530-4-4-0"
       sodipodi:cx="32.000847"
       sodipodi:cy="30.750895"
       sodipodi:rx="26.894329"
       sodipodi:ry="26.894329"
       d="m 58.895176,30.750895 a 26.894329,26.894329 0 1 1 -53.7886582,0 26.894329,26.894329 0 1 1 53.7886582,0 z"
       transform="matrix(0.45916134,0,0,0.45916134,17.647729,17.36888)" />
    <path
       sodipodi:type="arc"
       style="fill:none;stroke:#000000;stroke-opacity:1"
       id="path5530-4-4-0-8"
       sodipodi:cx="32.000847"
       sodipodi:cy="30.750895"
       sodipodi:rx="26.894329"
       sodipodi:ry="26.894329"
       d="m 58.895176,30.750895 a 26.894329,26.894329 0 1 1 -53.7886582,0 26.894329,26.894329 0 1 1 53.7886582,0 z"
       transform="matrix(0.3763134,0,0,0.3763134,20.46915,19.859788)" />
    <path
       sodipodi:type="arc"
       style="fill:none;stroke:#000000;stroke-opacity:1"
       id="path5530-4-4-0-8-4"
       sodipodi:cx="32.000847"
       sodipodi:cy="30.750895"
       sodipodi:rx="26.894329"
       sodipodi:ry="26.894329"
       d="m 58.895176,30.750895 a 26.894329,26.894329 0 1 1 -53.7886582,0 26.894329,26.894329 0 1 1 53.7886582,0 z"
       transform="matrix(0.28518066,0,0,0.28518066,23.271997,22.775681)" />
    <path
       sodipodi:type="arc"
       style="fill:#666666;stroke:#ffdd55;stroke-opacity:1;fill-opacity:1"
       id="path5626"
       sodipodi:cx="32.738453"
       sodipodi:cy="31.375023"
       sodipodi:rx="3.9149971"
       sodipodi:ry="3.9149971"
       d="m 36.65345,31.375023 a 3.9149971,3.9149971 0 1 1 -7.829994,0 3.9149971,3.9149971 0 1 1 7.829994,0 z"
       transform="translate(-0.34043454,0.22695636)" />
  </g>
  <g
     inkscape:groupmode="layer"
     id="layer2"
     inkscape:label="Holes">
    <path
       sodipodi:type="arc"
       style="fill:#000000;fill-opacity:1"
       id="path3137"
       sodipodi:cx="8.264843"
       sodipodi:cy="-16.642395"
       sodipodi:rx="2.166512"
       sodipodi:ry="2.166512"
       d="m 10.431355,-16.642395 a 2.166512,2.166512 0 1 1 -4.333024,0 2.166512,2.166512 0 1 1 4.333024,0 z"
       transform="translate(1.901669,48.642395)" />
    <path
       sodipodi:type="arc"
       style="fill:#000000;fill-opacity:1"
       id="path3137-4"
       sodipodi:cx="8.264843"
       sodipodi:cy="-16.642395"
       sodipodi:rx="2.166512"
       sodipodi:ry="2.166512"
       d="m 10.431355,-16.642395 a 2.166512,2.166512 0 1 1 -4.333024,0 2.166512,2.166512 0 1 1 4.333024,0 z"
       transform="translate(24.020724,26.616695)" />
    <path
       sodipodi:type="arc"
       style="fill:#000000;fill-opacity:1"
       id="path3137-9"
       sodipodi:cx="8.264843"
       sodipodi:cy="-16.642395"
       sodipodi:rx="2.166512"
       sodipodi:ry="2.166512"
       d="m 10.431355,-16.642395 a 2.166512,2.166512 0 1 1 -4.333024,0 2.166512,2.166512 0 1 1 4.333024,0 z"
       transform="translate(24.001254,70.621091)" />
    <path
       sodipodi:type="arc"
       style="fill:#000000;fill-opacity:1"
       id="path3137-9-4"
       sodipodi:cx="8.264843"
       sodipodi:cy="-16.642395"
       sodipodi:rx="2.166512"
       sodipodi:ry="2.166512"
       d="m 10.431355,-16.642395 a 2.166512,2.166512 0 1 1 -4.333024,0 2.166512,2.166512 0 1 1 4.333024,0 z"
       transform="translate(45.637292,48.414592)" />
    <path
       sodipodi:type="arc"
       style="fill:#000000;fill-opacity:1"
       id="path3137-40"
       sodipodi:cx="8.264843"
       sodipodi:cy="-16.642395"
       sodipodi:rx="2.166512"
       sodipodi:ry="2.166512"
       d="m 10.431355,-16.642395 a 2.166512,2.166512 0 1 1 -4.333024,0 2.166512,2.166512 0 1 1 4.333024,0 z"
       transform="translate(5.4660167,36.839818)" />
    <path
       sodipodi:type="arc"
       style="fill:#000000;fill-opacity:1"
       id="path3137-0"
       sodipodi:cx="8.264843"
       sodipodi:cy="-16.642395"
       sodipodi:rx="2.166512"
       sodipodi:ry="2.166512"
       d="m 10.431355,-16.642395 a 2.166512,2.166512 0 1 1 -4.333024,0 2.166512,2.166512 0 1 1 4.333024,0 z"
       transform="translate(12.72862,29.690693)" />
    <path
       sodipodi:type="arc"
       style="fill:#000000;fill-opacity:1"
       id="path3137-6"
       sodipodi:cx="8.264843"
       sodipodi:cy="-16.642395"
       sodipodi:rx="2.166512"
       sodipodi:ry="2.166512"
       d="m 10.431355,-16.642395 a 2.166512,2.166512 0 1 1 -4.333024,0 2.166512,2.166512 0 1 1 4.333024,0 z"
       transform="translate(34.743387,29.577215)" />
    <path
       sodipodi:type="arc"
       style="fill:#000000;fill-opacity:1"
       id="path3137-8"
       sodipodi:cx="8.264843"
       sodipodi:cy="-16.642395"
       sodipodi:rx="2.166512"
       sodipodi:ry="2.166512"
       d="m 10.431355,-16.642395 a 2.166512,2.166512 0 1 1 -4.333024,0 2.166512,2.166512 0 1 1 4.333024,0 z"
       transform="translate(42.573381,37.293731)" />
    <path
       sodipodi:type="arc"
       style="fill:#000000;fill-opacity:1"
       id="path3137-5"
       sodipodi:cx="8.264843"
       sodipodi:cy="-16.642395"
       sodipodi:rx="2.166512"
       sodipodi:ry="2.166512"
       d="m 10.431355,-16.642395 a 2.166512,2.166512 0 1 1 -4.333024,0 2.166512,2.166512 0 1 1 4.333024,0 z"
       transform="translate(43.25425,58.741106)" />
    <path
       sodipodi:type="arc"
       style="fill:#000000;fill-opacity:1"
       id="path3137-49"
       sodipodi:cx="8.264843"
       sodipodi:cy="-16.642395"
       sodipodi:rx="2.166512"
       sodipodi:ry="2.166512"
       d="m 10.431355,-16.642395 a 2.166512,2.166512 0 1 1 -4.333024,0 2.166512,2.166512 0 1 1 4.333024,0 z"
       transform="translate(34.516431,67.705882)" />
    <path
       sodipodi:type="arc"
       style="fill:#000000;fill-opacity:1"
       id="path3137-46"
       sodipodi:cx="8.264843"
       sodipodi:cy="-16.642395"
       sodipodi:rx="2.166512"
       sodipodi:ry="2.166512"
       d="m 10.431355,-16.642395 a 2.166512,2.166512 0 1 1 -4.333024,0 2.166512,2.166512 0 1 1 4.333024,0 z"
       transform="translate(13.069055,67.705882)" />
    <path
       sodipodi:type="arc"
       style="fill:#000000;fill-opacity:1"
       id="path3137-83"
       sodipodi:cx="8.264843"
       sodipodi:cy="-16.642395"
       sodipodi:rx="2.166512"
       sodipodi:ry="2.166512"
       d="m 10.431355,-16.642395 a 2.166512,2.166512 0 1 1 -4.333024,0 2.166512,2.166512 0 1 1 4.333024,0 z"
       transform="translate(5.0121038,59.535453)" />
  </g>
</svg>


code:
import QtQuick 1.1
import com.nokia.meego 1.0
import "core"
import "harmattan"

PageStackWindow {
    id: appWindow

    initialPage: game

    states: [
        State {
            name: "fullsize-visible"
            when: platformWindow.viewMode == WindowState.Fullsize && platformWindow.visible
            StateChangeScript {
                script: {
                    if (pageStack.currentPage == standbyPage) { pageStack.pop() }
                    game.resume();
                    console.log("Visibility: Fullsize and visible!")
                }
            }
        },
        State {
            name: "thumbnail-or-invisible"
            when: platformWindow.viewMode == WindowState.Thumbnail || !platformWindow.visible
            StateChangeScript {
                script: {
                    if (pageStack.currentPage == game) { pageStack.push(standbyPage) }
                    game.pause();
                    console.log("Visibility: Not fullsize (Thumbnail and/or invisible)")
                }
            }
        }
    ]

    QueryDialog {
        id: endDialog
        titleText : 'You ' + (won ? 'won' : 'lost') + '!'
        message: 'You ' + (won ? 'won' : 'lost') + ' the Game!'+ (won ? '\nYour time: ' + (game.getTime()) : '') + '\nPlay another?';
        acceptButtonText: 'Play'
        rejectButtonText: 'Exit'
        onAccepted:  {
            game.newGame();
            endDialog.close();
        }
        onRejected: Qt.quit();

        property bool won: false
    }

    Game {
        id: game
        tools: commonTools
        columns: settingsCont.value('table/columns', 10)
        rows: settingsCont.value('table/rows', 10)
        mines: settingsCont.value('table/mines', 10)

        onEnd: {
            endDialog.won = won;
            endDialog.open();
        }
    }

    StandByPage {
        id: standbyPage
    }

    Settings {
        id: settings
        onSet: {
            game.columns = numOfColumns;
            game.rows = numOfRows;
            game.mines = numOfMines;
            settingsCont.setValue('table/columns', numOfColumns);
            settingsCont.setValue('table/rows', numOfRows);
            settingsCont.setValue('table/mines', numOfMines);
            game.initialize();
            game.newGame();
            appWindow.pageStack.pop();
        }
        onClose: {
            game.resume();
            appWindow.pageStack.pop()
        }
    }

    About {
        id: about
        onClose: {
            game.resume();
            appWindow.pageStack.pop()
        }
    }

    ToolBarLayout {
        id: commonTools
        visible: true
        ToolButton {
            text: '' + game.flags + ' / ' + game.mines
            iconSource: 'core/images/flag.svg'
        }
        ToolButton {
            id: timeCount
            text: '00:00'
        }
        ToolIcon {
            platformIconId: "toolbar-view-menu";
            anchors.right: parent===undefined ? undefined : parent.right
            onClicked: (myMenu.status == DialogStatus.Closed) ? myMenu.open() : myMenu.close()
        }
    }

    Menu {
        id: myMenu
        visualParent: pageStack
        MenuLayout {
            MenuItem {
                text: "New Game";
                onClicked : {
                    game.newGame();
                }
            }
            MenuItem {
                text: "Settings";
                onClicked: {
                    game.pause();
                    appWindow.pageStack.push(settings);
                }
            }
            MenuItem {
                text: "About";
                onClicked: {
                    game.pause();
                    appWindow.pageStack.push(about);
                }
            }
        }
    }
}


code:
/*
* Copyright (c) 2011 Mladen Milankovic <mmlado at gmail.com>.
*
* This file is part of Demine application
*
* Demine is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Demine 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 General Public License for more details.

* You should have received a copy of the GNU General Public License
* along with Demine.  If not, see <http://www.gnu.org/licenses/>.
*/

import QtQuick 1.1
import com.nokia.meego 1.0

Page {
    id: about
    tools: ToolBarLayout {
        visible: true
        ToolIcon {
            iconId: "toolbar-back";
            onClicked: { about.close(); }
        }
    }

    signal close()

    Flickable {
        anchors.fill: parent
        contentWidth: parent.width
        contentHeight: content.height + 20
        Column {
            id: content
            width: parent.width
            spacing: 20

            Label {
                text: 'Demine'
                anchors.horizontalCenter: parent.horizontalCenter
                platformStyle: LabelStyle {
                    fontPixelSize: 40
                }
            }

            Button {
                text: 'Home'

                anchors.horizontalCenter: parent.horizontalCenter
                onClicked: {
                    Qt.openUrlExternally('http://projects.developer.nokia.com/demine');
                }
            }

            Column {
                width: parent.width
                spacing: 20
                Row {
                    spacing: 20
                    width: parent.width - 20
                    Label {
                        id: lblDeveloper
                        text: 'Developer:'
                    }
                    Label {
                        text: 'Mladen Milanković'
                    }
                }

                Row {
                    spacing: 20
                    width: parent.width - 20
                    Label {
                        text: 'Contact:'
                        width: lblDeveloper.width
                    }
                    Button {
                        text: 'developer@mmlado.com'
                        height: lblDeveloper.height

                        onClicked: {
                            Qt.openUrlExternally('mailto:developer@mmlado.com?subject=Demine feedback');
                        }
                    }
                }

                Row {
                    spacing: 20
                    width: parent.width - 20
                    Label {
                        text: 'Donate:'
                        width: lblDeveloper.width
                    }

                    Image {
                        width: 140
                        height: 30
                        source: '../core/images/flattr-badge-large.png'

                        MouseArea {
                            anchors.fill: parent
                            onClicked: {
                                Qt.openUrlExternally('http://flattr.com/thing/453120/Demine');
                            }
                        }
                    }

                    Image {
                        width: 106
                        height: 30
                        source: '../core/images/paypal.gif'

                        MouseArea {
                            anchors.fill: parent
                            onClicked: {
                                Qt.openUrlExternally('https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=U5RX65H9SM4JE&lc=HU&item_name=Demine&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted')
                            }
                        }
                    }
                }
            }

            Label {
                text: 'Between you and victory stands a few mines that are hidden under some of the fields.
Your mission: reveal all the fields that don\'t have any of the mines.
Help will come in the form of numbers under the fields adjacent to a mine. The higher the number the more mines are around that field.
Help also comes in form of flags, that you can place on a field where you suspect there is a mine. This way you won\'t accidentally dig on a field there might be a mine.'
                //anchors.fill: parent
                width: parent.width - 20
                anchors.horizontalCenter: parent.horizontalCenter
                horizontalAlignment: Text.AlignJustify
            }

            Label {
                text: 'Instructions'
                anchors.horizontalCenter: parent.horizontalCenter
                platformStyle: LabelStyle {
                    fontPixelSize: 30
                }
            }

            Label {
                text: 'tap - turn/flip field
tap and hold - put flag on field
drag/flick - move table around'
                width: parent.width - 20
                anchors.horizontalCenter: parent.horizontalCenter
                horizontalAlignment: Text.AlignJustify
            }

            Label {
                text: 'Conditions'
                anchors.horizontalCenter: parent.horizontalCenter
                platformStyle: LabelStyle {
                    fontPixelSize: 30
                }
            }

            Label {
                text: 'Win = reveal all the fields that don\'t have mines.
Loose = reveal a field that has a mine.'
                width: parent.width - 20
                anchors.horizontalCenter: parent.horizontalCenter
                horizontalAlignment: Text.AlignJustify
            }
        }
    }
}


code:
/*
* Copyright (c) 2011 Mladen Milankovic <mmlado at gmail.com>.
*
* This file is part of Demine application
*
* Demine is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Demine 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 General Public License for more details.

* You should have received a copy of the GNU General Public License
* along with Demine.  If not, see <http://www.gnu.org/licenses/>.
*/

import QtQuick 1.1
import com.nokia.meego 1.0
import QtMobility.feedback 1.1
import "../core"

Page {
    id: game

    property int columns: 10
    property int rows: 10
    property int mines: 14
    property int flags: 0
    property int fieldSize: (width > height ? width : height) / 10
    property int time: 0
    property bool running: false

    signal end(bool won)

    /*HapticsEffect {
        id: rumbleEffect
        attackIntensity: 0.0
        attackTime: 250
        intensity: 1.0
        duration: 100
        fadeTime: 250
        fadeIntensity: 0.0
    }*/

    Rectangle{
        color: '#00d300'
        anchors.fill: game
        /*PinchArea {
            //width: table.width
            //height: table.height
            anchors.fill: parent
            pinch.target: table
            //enabled: true
            pinch.minimumScale: 1
            pinch.maximumScale: 2
            //pinch.dragAxis: Pinch.XandYAxis

            /*onPinchStarted: {
                //console.debug(table.height*table.scale);
                //console.debug(pinch.scale);
                if (pinch.scale > 2) {
                    pinch.scale = 2
                }
                if (pinch.scale < 1) {
                    pinch.scale = 1
                }
                flickable.contentHeight = table.height*pinch.scale;
                flickable.contentWidth = table.width*pinch.scale;
            }*/

            /*onPinchUpdated: {
                //console.debug(table.height*table.scale);
                console.debug(pinch.scale);
                if (flickable.contentWidth * pinch.scale < main.width) return;
                if (flickable.contentWidth * pinch.scale > main.width*2) return;
                flickable.contentHeight = main.width*pinch.scale;
                flickable.contentWidth = main.width*pinch.scale;
            }

            onPinchFinished: {
                //main.contentX = table.x
                //main.contentY = table.y
                console.debug(table.height * table.scale);
                console.debug(table.width * table.scale);

                flickable.contentHeight = table.height * table.scale;
                flickable.contentWidth = table.width * table.scale;
            }
        }*/

        Flickable {
            id:  flickable
            anchors.fill: parent
            contentWidth: game.fieldSize * game.columns
            contentHeight: game.fieldSize * game.rows
            Table {
                id: table
                /*width: (main.width / 10) * (columns * (1 + table.spacing) )
                height: (main.width / 10) * (rows * (1 + table.spacing) )*/
                onLost: game.lost()
                onWon: game.won()
                columns: game.columns
                rows: game.rows
                numOfMines: game.mines
                fieldSize: game.fieldSize
                onFlag: {
                    game.flags = number;
                    //rumbleEffect.start();
                }
                onFirstOpen: {
                    running = true;
                    tmrTime.start();
                }
            }
        }
    }

    Timer {
        id: tmrTime
        interval: 1000
        running: false
        repeat: true
        onTriggered: {
            timeCount.text = humanizeTime(++game.time);
        }
    }

    function humanizeTime(seconds) {
        var hours = Math.floor(seconds / (60 * 60));
        seconds -= hours * 60 * 60;
        var minutes = Math.floor(seconds / 60);
        seconds -= minutes * 60;
        if (!hours) return '' + ((minutes >= 10) ? minutes : '0' + minutes) + ':' + ((seconds >= 10) ? seconds : '0' + seconds);
        return '' + ((hours >= 10) ? hours : '0' + hours) + ':' + ((minutes >= 10) ? minutes : '0' + minutes) + ':' + ((seconds >= 10) ? seconds : '0' + seconds);
    }

    function getTime() {
        return humanizeTime(game.time);
    }

    function initialize() {
        table.initialize();
    }

    function newGame() {
        table.newGame();
        flickable.contentX = 0;
        flickable.contentY = 0;
        flags = 0;
        time = 0;
        timeCount.text = humanizeTime(game.time);
        tmrTime.stop();
    }

    function pause() {
        if (!running) return false;
        tmrTime.stop();
    }

    function resume() {
        if (!running) return false;
        tmrTime.start();
    }

    function lost() {
        tmrTime.stop();
        running = false;
        end(false);
    }

    function won() {
        tmrTime.stop();
        running = false;
        end(true);
    }
}


code:
/*
* Copyright (c) 2011 Mladen Milankovic <mmlado at gmail.com>.
*
* This file is part of Demine application
*
* Demine is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Demine 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 General Public License for more details.

* You should have received a copy of the GNU General Public License
* along with Demine.  If not, see <http://www.gnu.org/licenses/>.
*/

import QtQuick 1.1
import com.nokia.meego 1.0

Page {
    id: settings
    anchors.fill: parent
    signal set(int numOfColumns, int numOfRows, int numOfMines)
    signal close()

    tools: ToolBarLayout {
        visible: true
        ToolIcon {
            iconId: "toolbar-back";
            onClicked: { settings.close(); }
        }
    }
    Column {
        id: options
        width: parent.width
        anchors.centerIn: parent
        Row {
            width: parent.width
            Label {
                text: 'Rows: '
                width: lblColumns.width
            }
            Label {
                text: rowSlider.value
                width: 50
            }
            Slider {
                id: rowSlider
                minimumValue: 2
                maximumValue: 50
                stepSize:1
                value: game.rows
                width: parent.width - lblColumns.width - 50
            }
        }
        Row {
            width: parent.width
            Label {
                id: lblColumns
                text: 'Columns: '
            }
            Label {
                text: columnSlider.value
                width: 50
            }
            Slider {
                id: columnSlider
                minimumValue: 2
                maximumValue: 50
                stepSize:1
                value: game.columns
                width: parent.width - lblColumns.width - 50
            }
        }
        Row {
            width: parent.width
            Label {
                text: 'Mines: '
                width: lblColumns.width
            }
            Label {
                text: mineSlider.value
                width: 50
            }
            Slider {
                id: mineSlider
                minimumValue: 2
                maximumValue: columnSlider.value * rowSlider.value - 1
                stepSize:1
                value: game.mines
                width: parent.width - lblColumns.width - 50
            }
        }
    }
    Button {
        text: 'Save'
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.top: options.bottom

        /*platformStyle: ButtonStyle {
            fontPixelSize: 30
            position: "[horizontal-center]"
        }*/
        onClicked: {
            settings.set(columnSlider.value, rowSlider.value, mineSlider.value)
        }
    }
}


code:
import QtQuick 1.1
import com.nokia.meego 1.0

Page {
    Rectangle {
        anchors.fill: parent
        color: '#00d300'

        Image {
            width: 240
            height: 240
            source: '../core/images/mine.svg'
            anchors.centerIn: parent
        }
    }
}


code:
/*
* Copyright (c) 2011 Mladen Milankovic <mmlado at gmail.com>.
*
* This file is part of Demine application
*
* Demine is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Demine 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 General Public License for more details.

* You should have received a copy of the GNU General Public License
* along with Demine.  If not, see <http://www.gnu.org/licenses/>.
*/

import QtQuick 1.0

import "core"
import "common"

Rectangle {
    id: main
    width: 800
    height: 480
    color: '#00d300'

    property int columns: 10
    property int rows: 10
    property int mines: 14

    Flickable {
        id:  flickable
        anchors.fill: parent
        contentWidth: (main.width / 10) * columns
        contentHeight: (main.width / 10) * rows
        Table {
            id: table
            /*width: (main.width / 10) * (columns * (1 + table.spacing) )
            height: (main.width / 10) * (rows * (1 + table.spacing) )*/
            onLost: main.lost()
            onWon: main.won()
            columns: main.columns
            rows: main.rows
            numOfMines: main.mines
            fieldSize: main.width / 10
        }
    }

    Dialog {
        id: dialog
        onClosed: main.newGame();
    }

    Options {
        id: options
        onSaved: {
            columns = numOfColumns;
            rows = numOfRows;
            mines = numOfMines;
            table.initialize();
            flickable.contentHeight = (main.width / 10) * rows;
            flickable.contentWidth = (main.width / 10) * columns;
            newGame();
        }
        onCanceled: {

        }
    }

    function openOptions() {
        options.show();
    }

    function newGame() {
        table.newGame();
        flickable.contentX = 0;
        flickable.contentY = 0;
    }

    function lost() {
        dialog.show('Game over.');
    }

    function won() {
        dialog.show('You won!');
    }
}


code:
// checksum 0xee24 version 0x70013
/*
  This file was generated by the Qt Quick Application wizard of Qt Creator.
  QmlApplicationViewer is a convenience class containing mobile device specific
  code such as screen orientation handling. Also QML paths and debugging are
  handled here.
  It is recommended not to modify this file, since newer versions of Qt Creator
  may offer an updated version of it.
*/

#include "qmlapplicationviewer.h"

#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtGui/QApplication>
#include <QtDeclarative/QDeclarativeComponent>
#include <QtDeclarative/QDeclarativeEngine>
#include <QtDeclarative/QDeclarativeContext>

#include <qplatformdefs.h> // MEEGO_EDITION_HARMATTAN

#ifdef HARMATTAN_BOOSTER
#include <MDeclarativeCache>
#endif

#if defined(QMLJSDEBUGGER) && QT_VERSION < 0x040800

#include <qt_private/qdeclarativedebughelper_p.h>

#if !defined(NO_JSDEBUGGER)
#include <jsdebuggeragent.h>
#endif
#if !defined(NO_QMLOBSERVER)
#include <qdeclarativeviewobserver.h>
#endif

// Enable debugging before any QDeclarativeEngine is created
struct QmlJsDebuggingEnabler
{
    QmlJsDebuggingEnabler()
    {
        QDeclarativeDebugHelper::enableDebugging();
    }
};

// Execute code in constructor before first QDeclarativeEngine is instantiated
static QmlJsDebuggingEnabler enableDebuggingHelper;

#endif // QMLJSDEBUGGER

class QmlApplicationViewerPrivate
{
    QString mainQmlFile;
    friend class QmlApplicationViewer;
    static QString adjustPath(const QString &path);
};

QString QmlApplicationViewerPrivate::adjustPath(const QString &path)
{
#ifdef Q_OS_UNIX
#ifdef Q_OS_MAC
    if (!QDir::isAbsolutePath(path))
        return QString::fromLatin1("%1/../Resources/%2")
                .arg(QCoreApplication::applicationDirPath(), path);
#else
    const QString pathInInstallDir =
            QString::fromLatin1("%1/../%2").arg(QCoreApplication::applicationDirPath(), path);
    if (QFileInfo(pathInInstallDir).exists())
        return pathInInstallDir;
#endif
#endif
    return path;
}

QmlApplicationViewer::QmlApplicationViewer(QWidget *parent)
    : QDeclarativeView(parent)
    , d(new QmlApplicationViewerPrivate())
{
    connect(engine(), SIGNAL(quit()), SLOT(close()));
    setResizeMode(QDeclarativeView::SizeRootObjectToView);
    // Qt versions prior to 4.8.0 don't have QML/JS debugging services built in
#if defined(QMLJSDEBUGGER) && QT_VERSION < 0x040800
#if !defined(NO_JSDEBUGGER)
    new QmlJSDebugger::JSDebuggerAgent(engine());
#endif
#if !defined(NO_QMLOBSERVER)
    new QmlJSDebugger::QDeclarativeViewObserver(this, this);
#endif
#endif
}

QmlApplicationViewer::~QmlApplicationViewer()
{
    delete d;
}

QmlApplicationViewer *QmlApplicationViewer::create()
{
    return new QmlApplicationViewer();
}

void QmlApplicationViewer::setMainQmlFile(const QString &file)
{
    d->mainQmlFile = QmlApplicationViewerPrivate::adjustPath(file);
    setSource(QUrl::fromLocalFile(d->mainQmlFile));
}

void QmlApplicationViewer::addImportPath(const QString &path)
{
    engine()->addImportPath(QmlApplicationViewerPrivate::adjustPath(path));
}

void QmlApplicationViewer::setOrientation(ScreenOrientation orientation)
{
#if defined(Q_OS_SYMBIAN)
    // If the version of Qt on the device is < 4.7.2, that attribute won't work
    if (orientation != ScreenOrientationAuto) {
        const QStringList v = QString::fromAscii(qVersion()).split(QLatin1Char('.'));
        if (v.count() == 3 && (v.at(0).toInt() << 16 | v.at(1).toInt() << 8 | v.at(2).toInt()) < 0x040702) {
            qWarning("Screen orientation locking only supported with Qt 4.7.2 and above");
            return;
        }
    }
#endif // Q_OS_SYMBIAN

    Qt::WidgetAttribute attribute;
    switch (orientation) {
#if QT_VERSION < 0x040702
    // Qt < 4.7.2 does not yet have the Qt::WA_*Orientation attributes
    case ScreenOrientationLockPortrait:
        attribute = static_cast<Qt::WidgetAttribute>(128);
        break;
    case ScreenOrientationLockLandscape:
        attribute = static_cast<Qt::WidgetAttribute>(129);
        break;
    default:
    case ScreenOrientationAuto:
        attribute = static_cast<Qt::WidgetAttribute>(130);
        break;
#else // QT_VERSION < 0x040702
    case ScreenOrientationLockPortrait:
        attribute = Qt::WA_LockPortraitOrientation;
        break;
    case ScreenOrientationLockLandscape:
        attribute = Qt::WA_LockLandscapeOrientation;
        break;
    default:
    case ScreenOrientationAuto:
        attribute = Qt::WA_AutoOrientation;
        break;
#endif // QT_VERSION < 0x040702
    };
    setAttribute(attribute, true);
}

void QmlApplicationViewer::showExpanded()
{
#if defined(Q_OS_SYMBIAN) || defined(MEEGO_EDITION_HARMATTAN) || defined(Q_WS_SIMULATOR)
    showFullScreen();
#elif defined(Q_WS_MAEMO_5)
    showMaximized();
#else
    show();
#endif
}

QApplication *createApplication(int &argc, char **argv)
{
#ifdef HARMATTAN_BOOSTER
    return MDeclarativeCache::qApplication(argc, argv);
#else
    return new QApplication(argc, argv);
#endif
}


code:
// checksum 0x898f version 0x70013
/*
  This file was generated by the Qt Quick Application wizard of Qt Creator.
  QmlApplicationViewer is a convenience class containing mobile device specific
  code such as screen orientation handling. Also QML paths and debugging are
  handled here.
  It is recommended not to modify this file, since newer versions of Qt Creator
  may offer an updated version of it.
*/

#ifndef QMLAPPLICATIONVIEWER_H
#define QMLAPPLICATIONVIEWER_H

#include <QtDeclarative/QDeclarativeView>

class QmlApplicationViewer : public QDeclarativeView
{
    Q_OBJECT

public:
    enum ScreenOrientation {
        ScreenOrientationLockPortrait,
        ScreenOrientationLockLandscape,
        ScreenOrientationAuto
    };

    explicit QmlApplicationViewer(QWidget *parent = 0);
    virtual ~QmlApplicationViewer();

    static QmlApplicationViewer *create();

    void setMainQmlFile(const QString &file);
    void addImportPath(const QString &path);

    // Note that this will only have an effect on Symbian and Fremantle.
    void setOrientation(ScreenOrientation orientation);

    void showExpanded();

private:
    class QmlApplicationViewerPrivate *d;
};

QApplication *createApplication(int &argc, char **argv);

#endif // QMLAPPLICATIONVIEWER_H


code:
# checksum 0x5b42 version 0x70013
# This file was generated by the Qt Quick Application wizard of Qt Creator.
# The code below adds the QmlApplicationViewer to the project and handles the
# activation of QML debugging.
# It is recommended not to modify this file, since newer versions of Qt Creator
# may offer an updated version of it.

QT += declarative

SOURCES += $$PWD/qmlapplicationviewer.cpp
HEADERS += $$PWD/qmlapplicationviewer.h
INCLUDEPATH += $$PWD

# Include JS debugger library if QMLJSDEBUGGER_PATH is set
!isEmpty(QMLJSDEBUGGER_PATH) {
    include($$QMLJSDEBUGGER_PATH/qmljsdebugger-lib.pri)
} else {
    DEFINES -= QMLJSDEBUGGER
}

contains(CONFIG,qdeclarative-boostable):contains(MEEGO_EDITION,harmattan) {
    DEFINES += HARMATTAN_BOOSTER
}
# This file was generated by an application wizard of Qt Creator.
# The code below handles deployment to Symbian and Maemo, aswell as copying
# of the application data to shadow build directories on desktop.
# It is recommended not to modify this file, since newer versions of Qt Creator
# may offer an updated version of it.

defineTest(qtcAddDeployment) {
for(deploymentfolder, DEPLOYMENTFOLDERS) {
    item = item$${deploymentfolder}
    itemsources = $${item}.sources
    $$itemsources = $$eval($${deploymentfolder}.source)
    itempath = $${item}.path
    $$itempath= $$eval($${deploymentfolder}.target)
    export($$itemsources)
    export($$itempath)
    DEPLOYMENT += $$item
}

MAINPROFILEPWD = $$PWD

symbian {
    isEmpty(ICON):exists($${TARGET}.svg):ICON = $${TARGET}.svg
    isEmpty(TARGET.EPOCHEAPSIZE):TARGET.EPOCHEAPSIZE = 0x20000 0x2000000
} else:win32 {
    copyCommand =
    for(deploymentfolder, DEPLOYMENTFOLDERS) {
        source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source)
        source = $$replace(source, /, \\)
        sourcePathSegments = $$split(source, \\)
        target = $$OUT_PWD/$$eval($${deploymentfolder}.target)/$$last(sourcePathSegments)
        target = $$replace(target, /, \\)
        target ~= s,\\\\\\.?\\\\,\\,
        !isEqual(source,$$target) {
            !isEmpty(copyCommand):copyCommand += &&
            isEqual(QMAKE_DIR_SEP, \\) {
                copyCommand += $(COPY_DIR) \"$$source\" \"$$target\"
            } else {
                source = $$replace(source, \\\\, /)
                target = $$OUT_PWD/$$eval($${deploymentfolder}.target)
                target = $$replace(target, \\\\, /)
                copyCommand += test -d \"$$target\" || mkdir -p \"$$target\" && cp -r \"$$source\" \"$$target\"
            }
        }
    }
    !isEmpty(copyCommand) {
        copyCommand = @echo Copying application data... && $$copyCommand
        copydeploymentfolders.commands = $$copyCommand
        first.depends = $(first) copydeploymentfolders
        export(first.depends)
        export(copydeploymentfolders.commands)
        QMAKE_EXTRA_TARGETS += first copydeploymentfolders
    }
} else:unix {
    maemo5 {
        desktopfile.files = $${TARGET}.desktop
        desktopfile.path = /usr/share/applications/hildon
        icon.files = $${TARGET}64.png
        icon.path = /usr/share/icons/hicolor/64x64/apps
    } else:!isEmpty(MEEGO_VERSION_MAJOR) {
        desktopfile.files = $${TARGET}_harmattan.desktop
        desktopfile.path = /usr/share/applications
        icon.files = $${TARGET}80.png
        icon.path = /usr/share/icons/hicolor/80x80/apps
        splashscreen.files = splash.png
        splashscreen.path = /opt/$${TARGET}
        export(splashscreen.files)
        export(splashscreen.path)
        INSTALLS += splashscreen
    } else { # Assumed to be a Desktop Unix
        copyCommand =
        for(deploymentfolder, DEPLOYMENTFOLDERS) {
            source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source)
            source = $$replace(source, \\\\, /)
            macx {
                target = $$OUT_PWD/$${TARGET}.app/Contents/Resources/$$eval($${deploymentfolder}.target)
            } else {
                target = $$OUT_PWD/$$eval($${deploymentfolder}.target)
            }
            target = $$replace(target, \\\\, /)
            sourcePathSegments = $$split(source, /)
            targetFullPath = $$target/$$last(sourcePathSegments)
            targetFullPath ~= s,/\\.?/,/,
            !isEqual(source,$$targetFullPath) {
                !isEmpty(copyCommand):copyCommand += &&
                copyCommand += $(MKDIR) \"$$target\"
                copyCommand += && $(COPY_DIR) \"$$source\" \"$$target\"
            }
        }
        !isEmpty(copyCommand) {
            copyCommand = @echo Copying application data... && $$copyCommand
            copydeploymentfolders.commands = $$copyCommand
            first.depends = $(first) copydeploymentfolders
            export(first.depends)
            export(copydeploymentfolders.commands)
            QMAKE_EXTRA_TARGETS += first copydeploymentfolders
        }
    }
    installPrefix = /opt/$${TARGET}
    for(deploymentfolder, DEPLOYMENTFOLDERS) {
        item = item$${deploymentfolder}
        itemfiles = $${item}.files
        $$itemfiles = $$eval($${deploymentfolder}.source)
        itempath = $${item}.path
        $$itempath = $${installPrefix}/$$eval($${deploymentfolder}.target)
        export($$itemfiles)
        export($$itempath)
        INSTALLS += $$item
    }

    !isEmpty(desktopfile.path) {
        export(icon.files)
        export(icon.path)
        export(desktopfile.files)
        export(desktopfile.path)
        INSTALLS += icon desktopfile
    }

    target.path = $${installPrefix}/bin
    export(target.path)
    INSTALLS += target
}

export (ICON)
export (INSTALLS)
export (DEPLOYMENT)
export (TARGET.EPOCHEAPSIZE)
export (TARGET.CAPABILITY)
export (LIBS)
export (QMAKE_EXTRA_TARGETS)
}


code:
#ifndef SETTINGS_H
#define SETTINGS_H

#include <QtGui/QApplication>
#include <QtCore/QSettings>

class Settings : public QSettings
{
    Q_OBJECT

    public:
        explicit Settings(QObject *parent = 0) : QSettings(QSettings::IniFormat,
                                                           QSettings::UserScope,
                                                           QCoreApplication::instance()->organizationName(),
                                                           QCoreApplication::instance()->applicationName(),
                                                           parent) {}

        Q_INVOKABLE inline void setValue(const QString &key, const QVariant &value) { QSettings::setValue(key, value); QSettings::sync(); }
        Q_INVOKABLE inline QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const { return QSettings::value(key, defaultValue); }
};

#endif // SETTINGS_H


code:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
   xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:xlink="http://www.w3.org/1999/xlink"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   width="854"
   height="480"
   id="svg3104"
   version="1.1"
   inkscape:version="0.48.2 r9819"
   sodipodi:docname="splash.svg">
  <defs
     id="defs3106">
    <linearGradient
       inkscape:collect="always"
       id="linearGradient5521">
      <stop
         style="stop-color:#626667;stop-opacity:1;"
         offset="0"
         id="stop5523" />
      <stop
         style="stop-color:#626667;stop-opacity:0;"
         offset="1"
         id="stop5525" />
    </linearGradient>
    <linearGradient
       id="linearGradient4063">
      <stop
         style="stop-color:#5b5f60;stop-opacity:1;"
         offset="0"
         id="stop4065" />
      <stop
         style="stop-color:#5b5f60;stop-opacity:0;"
         offset="1"
         id="stop4067" />
    </linearGradient>
    <linearGradient
       id="linearGradient4053"
       osb:paint="gradient">
      <stop
         style="stop-color:#000000;stop-opacity:1;"
         offset="0"
         id="stop4055" />
      <stop
         style="stop-color:#000000;stop-opacity:0;"
         offset="1"
         id="stop4057" />
    </linearGradient>
    <radialGradient
       inkscape:collect="always"
       xlink:href="#linearGradient5521"
       id="radialGradient5527"
       cx="29.965534"
       cy="37.925095"
       fx="29.965534"
       fy="37.925095"
       r="26.272728"
       gradientUnits="userSpaceOnUse"
       gradientTransform="matrix(5.1071169,-5.1891099,3.3633319,3.3101882,-242.76168,82.025601)" />
    <radialGradient
       inkscape:collect="always"
       xlink:href="#linearGradient5521"
       id="radialGradient3928"
       gradientUnits="userSpaceOnUse"
       gradientTransform="matrix(5.1071169,-5.1891099,3.3633319,3.3101882,-242.76168,82.025601)"
       cx="29.965534"
       cy="37.925095"
       fx="29.965534"
       fy="37.925095"
       r="26.272728" />
    <radialGradient
       inkscape:collect="always"
       xlink:href="#linearGradient5521"
       id="radialGradient4002"
       gradientUnits="userSpaceOnUse"
       gradientTransform="matrix(5.1071169,-5.1891099,3.3633319,3.3101882,-242.76168,82.025601)"
       cx="29.965534"
       cy="37.925095"
       fx="29.965534"
       fy="37.925095"
       r="26.272728" />
  </defs>
  <sodipodi:namedview
     id="base"
     pagecolor="#ffffff"
     bordercolor="#666666"
     borderopacity="1.0"
     inkscape:pageopacity="0.0"
     inkscape:pageshadow="2"
     inkscape:zoom="0.98375"
     inkscape:cx="240"
     inkscape:cy="400"
     inkscape:current-layer="layer2"
     showgrid="true"
     inkscape:document-units="px"
     inkscape:grid-bbox="true"
     inkscape:snap-grids="false"
     showguides="false"
     inkscape:window-width="1680"
     inkscape:window-height="995"
     inkscape:window-x="-2"
     inkscape:window-y="-3"
     inkscape:window-maximized="1">
    <inkscape:grid
       type="xygrid"
       id="grid3134"
       empspacing="5"
       visible="true"
       enabled="true"
       snapvisiblegridlinesonly="true" />
  </sodipodi:namedview>
  <metadata
     id="metadata3109">
    <rdf:RDF>
      <cc:Work
         rdf:about="">
        <dc:format>image/svg+xml</dc:format>
        <dc:type
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
        <dc:title />
      </cc:Work>
    </rdf:RDF>
  </metadata>
  <g
     inkscape:groupmode="layer"
     id="layer4"
     inkscape:label="Background"
     transform="translate(0,416)">
    <rect
       style="fill:#00d300;fill-opacity:1;fill-rule:evenodd;stroke:#00d300;stroke-width:12.69770908px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
       id="rect3120"
       width="841.30231"
       height="467.30228"
       x="6.3488545"
       y="-409.65121" />
  </g>
  <g
     id="layer1"
     inkscape:label="Base"
     inkscape:groupmode="layer"
     transform="translate(0,416)" />
  <g
     inkscape:groupmode="layer"
     id="layer3"
     inkscape:label="Circles"
     transform="translate(0,416)" />
  <g
     inkscape:groupmode="layer"
     id="layer2"
     inkscape:label="Holes"
     transform="translate(0,416)">
    <g
       id="g3960"
       transform="matrix(2.7812655,0,0,2.7812655,337.64733,-264.90633)">
      <path
         transform="matrix(1.0263929,0,0,1.0263929,-7.1562324,-0.59850525)"
         d="M 64.545456,31.727272 C 64.545456,46.237299 52.782755,58 38.272728,58 23.762701,58 12,46.237299 12,31.727272 12,17.217245 23.762701,5.4545441 38.272728,5.4545441 c 14.510027,0 26.272728,11.7627009 26.272728,26.2727279 z"
         sodipodi:ry="26.272728"
         sodipodi:rx="26.272728"
         sodipodi:cy="31.727272"
         sodipodi:cx="38.272728"
         id="path3130"
         style="fill:url(#radialGradient4002);fill-opacity:1;fill-rule:nonzero"
         sodipodi:type="arc" />
      <path
         transform="matrix(0.69720063,0,0,0.69720063,9.9382462,10.560457)"
         d="m 58.895176,30.750895 c 0,14.853327 -12.041001,26.894329 -26.894329,26.894329 -14.853328,0 -26.8943292,-12.041002 -26.8943292,-26.894329 0,-14.853328 12.0410012,-26.8943295 26.8943292,-26.8943295 14.853328,0 26.894329,12.0410015 26.894329,26.8943295 z"
         sodipodi:ry="26.894329"
         sodipodi:rx="26.894329"
         sodipodi:cy="30.750895"
         sodipodi:cx="32.000847"
         id="path5530"
         style="fill:none;stroke:#000000;stroke-opacity:1"
         sodipodi:type="arc" />
      <path
         transform="matrix(0.60000282,0,0,0.60000282,13.208224,13.230246)"
         d="m 58.895176,30.750895 c 0,14.853327 -12.041001,26.894329 -26.894329,26.894329 -14.853328,0 -26.8943292,-12.041002 -26.8943292,-26.894329 0,-14.853328 12.0410012,-26.8943295 26.8943292,-26.8943295 14.853328,0 26.894329,12.0410015 26.894329,26.8943295 z"
         sodipodi:ry="26.894329"
         sodipodi:rx="26.894329"
         sodipodi:cy="30.750895"
         sodipodi:cx="32.000847"
         id="path5530-4"
         style="fill:none;stroke:#000000;stroke-opacity:1"
         sodipodi:type="arc" />
      <path
         transform="matrix(0.52958208,0,0,0.52958208,15.507684,15.373597)"
         d="m 58.895176,30.750895 c 0,14.853327 -12.041001,26.894329 -26.894329,26.894329 -14.853328,0 -26.8943292,-12.041002 -26.8943292,-26.894329 0,-14.853328 12.0410012,-26.8943295 26.8943292,-26.8943295 14.853328,0 26.894329,12.0410015 26.894329,26.8943295 z"
         sodipodi:ry="26.894329"
         sodipodi:rx="26.894329"
         sodipodi:cy="30.750895"
         sodipodi:cx="32.000847"
         id="path5530-4-4"
         style="fill:none;stroke:#000000;stroke-opacity:1"
         sodipodi:type="arc" />
      <path
         transform="matrix(0.45916134,0,0,0.45916134,17.647729,17.36888)"
         d="m 58.895176,30.750895 c 0,14.853327 -12.041001,26.894329 -26.894329,26.894329 -14.853328,0 -26.8943292,-12.041002 -26.8943292,-26.894329 0,-14.853328 12.0410012,-26.8943295 26.8943292,-26.8943295 14.853328,0 26.894329,12.0410015 26.894329,26.8943295 z"
         sodipodi:ry="26.894329"
         sodipodi:rx="26.894329"
         sodipodi:cy="30.750895"
         sodipodi:cx="32.000847"
         id="path5530-4-4-0"
         style="fill:none;stroke:#000000;stroke-opacity:1"
         sodipodi:type="arc" />
      <path
         transform="matrix(0.3763134,0,0,0.3763134,20.46915,19.859788)"
         d="m 58.895176,30.750895 c 0,14.853327 -12.041001,26.894329 -26.894329,26.894329 -14.853328,0 -26.8943292,-12.041002 -26.8943292,-26.894329 0,-14.853328 12.0410012,-26.8943295 26.8943292,-26.8943295 14.853328,0 26.894329,12.0410015 26.894329,26.8943295 z"
         sodipodi:ry="26.894329"
         sodipodi:rx="26.894329"
         sodipodi:cy="30.750895"
         sodipodi:cx="32.000847"
         id="path5530-4-4-0-8"
         style="fill:none;stroke:#000000;stroke-opacity:1"
         sodipodi:type="arc" />
      <path
         transform="matrix(0.28518066,0,0,0.28518066,23.271997,22.775681)"
         d="m 58.895176,30.750895 c 0,14.853327 -12.041001,26.894329 -26.894329,26.894329 -14.853328,0 -26.8943292,-12.041002 -26.8943292,-26.894329 0,-14.853328 12.0410012,-26.8943295 26.8943292,-26.8943295 14.853328,0 26.894329,12.0410015 26.894329,26.8943295 z"
         sodipodi:ry="26.894329"
         sodipodi:rx="26.894329"
         sodipodi:cy="30.750895"
         sodipodi:cx="32.000847"
         id="path5530-4-4-0-8-4"
         style="fill:none;stroke:#000000;stroke-opacity:1"
         sodipodi:type="arc" />
      <path
         transform="translate(-0.34043454,0.22695636)"
         d="m 36.65345,31.375023 c 0,2.162193 -1.752804,3.914997 -3.914997,3.914997 -2.162193,0 -3.914997,-1.752804 -3.914997,-3.914997 0,-2.162193 1.752804,-3.914997 3.914997,-3.914997 2.162193,0 3.914997,1.752804 3.914997,3.914997 z"
         sodipodi:ry="3.9149971"
         sodipodi:rx="3.9149971"
         sodipodi:cy="31.375023"
         sodipodi:cx="32.738453"
         id="path5626"
         style="fill:#666666;fill-opacity:1;stroke:#ffdd55;stroke-opacity:1"
         sodipodi:type="arc" />
      <path
         transform="translate(1.901669,48.642395)"
         d="m 10.431355,-16.642395 c 0,1.196532 -0.9699805,2.166512 -2.166512,2.166512 -1.1965316,0 -2.166512,-0.96998 -2.166512,-2.166512 0,-1.196532 0.9699804,-2.166512 2.166512,-2.166512 1.1965315,0 2.166512,0.96998 2.166512,2.166512 z"
         sodipodi:ry="2.166512"
         sodipodi:rx="2.166512"
         sodipodi:cy="-16.642395"
         sodipodi:cx="8.264843"
         id="path3137"
         style="fill:#000000;fill-opacity:1"
         sodipodi:type="arc" />
      <path
         transform="translate(24.020724,26.616695)"
         d="m 10.431355,-16.642395 c 0,1.196532 -0.9699805,2.166512 -2.166512,2.166512 -1.1965316,0 -2.166512,-0.96998 -2.166512,-2.166512 0,-1.196532 0.9699804,-2.166512 2.166512,-2.166512 1.1965315,0 2.166512,0.96998 2.166512,2.166512 z"
         sodipodi:ry="2.166512"
         sodipodi:rx="2.166512"
         sodipodi:cy="-16.642395"
         sodipodi:cx="8.264843"
         id="path3137-4"
         style="fill:#000000;fill-opacity:1"
         sodipodi:type="arc" />
      <path
         transform="translate(24.001254,70.621091)"
         d="m 10.431355,-16.642395 c 0,1.196532 -0.9699805,2.166512 -2.166512,2.166512 -1.1965316,0 -2.166512,-0.96998 -2.166512,-2.166512 0,-1.196532 0.9699804,-2.166512 2.166512,-2.166512 1.1965315,0 2.166512,0.96998 2.166512,2.166512 z"
         sodipodi:ry="2.166512"
         sodipodi:rx="2.166512"
         sodipodi:cy="-16.642395"
         sodipodi:cx="8.264843"
         id="path3137-9"
         style="fill:#000000;fill-opacity:1"
         sodipodi:type="arc" />
      <path
         transform="translate(45.637292,48.414592)"
         d="m 10.431355,-16.642395 c 0,1.196532 -0.9699805,2.166512 -2.166512,2.166512 -1.1965316,0 -2.166512,-0.96998 -2.166512,-2.166512 0,-1.196532 0.9699804,-2.166512 2.166512,-2.166512 1.1965315,0 2.166512,0.96998 2.166512,2.166512 z"
         sodipodi:ry="2.166512"
         sodipodi:rx="2.166512"
         sodipodi:cy="-16.642395"
         sodipodi:cx="8.264843"
         id="path3137-9-4"
         style="fill:#000000;fill-opacity:1"
         sodipodi:type="arc" />
      <path
         transform="translate(5.4660167,36.839818)"
         d="m 10.431355,-16.642395 c 0,1.196532 -0.9699805,2.166512 -2.166512,2.166512 -1.1965316,0 -2.166512,-0.96998 -2.166512,-2.166512 0,-1.196532 0.9699804,-2.166512 2.166512,-2.166512 1.1965315,0 2.166512,0.96998 2.166512,2.166512 z"
         sodipodi:ry="2.166512"
         sodipodi:rx="2.166512"
         sodipodi:cy="-16.642395"
         sodipodi:cx="8.264843"
         id="path3137-40"
         style="fill:#000000;fill-opacity:1"
         sodipodi:type="arc" />
      <path
         transform="translate(12.72862,29.690693)"
         d="m 10.431355,-16.642395 c 0,1.196532 -0.9699805,2.166512 -2.166512,2.166512 -1.1965316,0 -2.166512,-0.96998 -2.166512,-2.166512 0,-1.196532 0.9699804,-2.166512 2.166512,-2.166512 1.1965315,0 2.166512,0.96998 2.166512,2.166512 z"
         sodipodi:ry="2.166512"
         sodipodi:rx="2.166512"
         sodipodi:cy="-16.642395"
         sodipodi:cx="8.264843"
         id="path3137-0"
         style="fill:#000000;fill-opacity:1"
         sodipodi:type="arc" />
      <path
         transform="translate(34.743387,29.577215)"
         d="m 10.431355,-16.642395 c 0,1.196532 -0.9699805,2.166512 -2.166512,2.166512 -1.1965316,0 -2.166512,-0.96998 -2.166512,-2.166512 0,-1.196532 0.9699804,-2.166512 2.166512,-2.166512 1.1965315,0 2.166512,0.96998 2.166512,2.166512 z"
         sodipodi:ry="2.166512"
         sodipodi:rx="2.166512"
         sodipodi:cy="-16.642395"
         sodipodi:cx="8.264843"
         id="path3137-6"
         style="fill:#000000;fill-opacity:1"
         sodipodi:type="arc" />
      <path
         transform="translate(42.573381,37.293731)"
         d="m 10.431355,-16.642395 c 0,1.196532 -0.9699805,2.166512 -2.166512,2.166512 -1.1965316,0 -2.166512,-0.96998 -2.166512,-2.166512 0,-1.196532 0.9699804,-2.166512 2.166512,-2.166512 1.1965315,0 2.166512,0.96998 2.166512,2.166512 z"
         sodipodi:ry="2.166512"
         sodipodi:rx="2.166512"
         sodipodi:cy="-16.642395"
         sodipodi:cx="8.264843"
         id="path3137-8"
         style="fill:#000000;fill-opacity:1"
         sodipodi:type="arc" />
      <path
         transform="translate(43.25425,58.741106)"
         d="m 10.431355,-16.642395 c 0,1.196532 -0.9699805,2.166512 -2.166512,2.166512 -1.1965316,0 -2.166512,-0.96998 -2.166512,-2.166512 0,-1.196532 0.9699804,-2.166512 2.166512,-2.166512 1.1965315,0 2.166512,0.96998 2.166512,2.166512 z"
         sodipodi:ry="2.166512"
         sodipodi:rx="2.166512"
         sodipodi:cy="-16.642395"
         sodipodi:cx="8.264843"
         id="path3137-5"
         style="fill:#000000;fill-opacity:1"
         sodipodi:type="arc" />
      <path
         transform="translate(34.516431,67.705882)"
         d="m 10.431355,-16.642395 c 0,1.196532 -0.9699805,2.166512 -2.166512,2.166512 -1.1965316,0 -2.166512,-0.96998 -2.166512,-2.166512 0,-1.196532 0.9699804,-2.166512 2.166512,-2.166512 1.1965315,0 2.166512,0.96998 2.166512,2.166512 z"
         sodipodi:ry="2.166512"
         sodipodi:rx="2.166512"
         sodipodi:cy="-16.642395"
         sodipodi:cx="8.264843"
         id="path3137-49"
         style="fill:#000000;fill-opacity:1"
         sodipodi:type="arc" />
      <path
         transform="translate(13.069055,67.705882)"
         d="m 10.431355,-16.642395 c 0,1.196532 -0.9699805,2.166512 -2.166512,2.166512 -1.1965316,0 -2.166512,-0.96998 -2.166512,-2.166512 0,-1.196532 0.9699804,-2.166512 2.166512,-2.166512 1.1965315,0 2.166512,0.96998 2.166512,2.166512 z"
         sodipodi:ry="2.166512"
         sodipodi:rx="2.166512"
         sodipodi:cy="-16.642395"
         sodipodi:cx="8.264843"
         id="path3137-46"
         style="fill:#000000;fill-opacity:1"
         sodipodi:type="arc" />
      <path
         transform="translate(5.0121038,59.535453)"
         d="m 10.431355,-16.642395 c 0,1.196532 -0.9699805,2.166512 -2.166512,2.166512 -1.1965316,0 -2.166512,-0.96998 -2.166512,-2.166512 0,-1.196532 0.9699804,-2.166512 2.166512,-2.166512 1.1965315,0 2.166512,0.96998 2.166512,2.166512 z"
         sodipodi:ry="2.166512"
         sodipodi:rx="2.166512"
         sodipodi:cy="-16.642395"
         sodipodi:cx="8.264843"
         id="path3137-83"
         style="fill:#000000;fill-opacity:1"
         sodipodi:type="arc" />
    </g>
  </g>
</svg>


code:
/buildroot
/buildroot-*
/brrootfs/*
!/brrootfs/stage.sh

repo_name: arsv/minibase

path: .gitignore


code:
[submodule "minibase"]
	path = minibase
	url = git://github.com/arsv/minibase

path: .gitmodules


code:
This repository contains build scripts and filesystem skeletons for
bootable minibase images based on Buildroot. When built, the images
will contain just enough to run X, Weston and (if the hardware is there)
connect to a wifi network.

The images should be bootable with qemu as well as with reasonably recent
x86_64 hardware with Intel or AMD graphics.

Pre-built images
~~~~~~~~~~~~~~~~
To try the system without going through the whole build process,
download either sys-plain.tar.xz or sys-crypt.tar from

  https://github.com/arsv/minibase-br/releases

To see How the system is assembled without having to mess with
Buildroot, download prebuilt.tar.xz and skip the buildroot part below.

System contents
~~~~~~~~~~~~~~~
The resulting images contain

	* ~3MB kernel
	* ~6MB of kernel modules
	* ~7MB of firmware blobs for iwlwifi
	* ~650KB of minibase tools

	* ~600KB musl (not needed for minibase)
	* ~200KB dropbear
	* ~100KB of kilo and dash (needed for X)

	* about 30MB of X, weston and their dependencies
	  (hard to tell apart at this point)

Current configuration does *not* include busybox and runs solely
on minibase. The point of these images is to showcase minibase,
not to be usable.

Prerequisites
~~~~~~~~~~~~~
The host system needs a usable GNU toolchain:

	* common POSIX tools
	* binutils, gcc, make
	* wget to download the sources

and also

	* mtools
	* syslinux, with files in /usr/share/syslinux
	  (tweak the scripts if the files are in another location)

Syslinux is difficult to work with, so for now the scripts rely
on the host distro to provide it.

How to build the images
~~~~~~~~~~~~~~~~~~~~~~~
(Skip until "Update ./minibase ..." if working with prebuilt.tar.bz2)

Download https://buildroot.org/downloads/buildroot-2017.08.tar.bz2,
unpack it and rename the directory into ./buildroot.

# If the host system runs glibc-2.26:
#
#	cp brvendor/package/flex/0002*.patch \
#	   buildroot/package/flex/
#
# otherwise the build will fail.

Build the system:

	cd buildroot
	make BR2_EXTERNAL=../brvendor minibase_defconfig
	make            # this will take lots of time

Stage resulting rootfs:

	cd brrootfs
	./stage.sh

Update ./minibase and build it:

	git submodule update --init
	cd minibase
	./configure
	make
	make install    # this will install into ./out

Assemble plaintext image:

	cd sys-1-plain
	make

Assemble encrypted image:

	cd sys-2-crypt
	make

The first sys-crypt build will generate image encryptions keys which will
then be re-used unless removed manually. The tool will ask for passphrase
when generating the keys, and then once again to unwrap the keys when
encrypting the image. Any subsequent run will only ask for passphrase to
unwrap the keys.

Booting with qemu
~~~~~~~~~~~~~~~~~
Run xqemu.sh in respective directories:

	cd sys-1-plain
	./xqemu.sh

The scripts will attempt to run qemu with -enable-kvm.

The password for sys-2-crypt is "swordfish".

Booting with real hardware
~~~~~~~~~~~~~~~~~~~~~~~~~~
Write the image onto usb stick:

	cd sys-1-plain
	dd if=whole.img of=/dev/sdb   # make sure it's the right device

and try to persuade the box to boot from that.

The image should be both BIOS and UEFI bootable on x86_64 hardware.
Mixed-mode UEFI (32-bit UEFI on 64-bit CPU) may or may not work.

There is absolutely nothing minibase-specific about booting the system,
any configuration that will get the kernel and initrd into the memory
should work. Feel free to experiment.

The system uses MBR ID 0x11223344 to find its boot media.

Getting around the system
~~~~~~~~~~~~~~~~~~~~~~~~~
The system is configured to be usable in qemu.

    C-F2: switch to VT2 (root shell)
    C-F3: switch to VT3 (Xorg, default VT)
    C-F4: switch to VT4 (Weston, 1st instance)
    C-F5: switch to VT5 (Weston, 2nd instance)
    C-Esc: bring up the greeter. Commands there:

        Esc: return back
	Shift-R: reboot
	Shift-P: poweroff
	Shift-S: sleep (real hw only, does nothing in qemu)
	Shift-L: lock

The system boots into X/Fluxbox running on VT3.
Right-click on desktop and run urxvt.

There's another root console on ttyS0 (serial).
In qemu, press C-A-2 to access it, C-A-1 to go back.
(some qemu versions may need C-A-3 not C-A-2)

Inspect system state:

	pstree                 # processes
	logcat                 # syslog contents

Use `svctl` to query top-level supervisor:

	svctl                  # process list
	svctl stop udevmod
	svctl start udevmod
	svctl poweroff

	svctl show keymon      # properly running service
	svctl show badsrv      # failed service

Use `vtctl` to control vtmux:

	vtctl 4                # switch to VT4

Use `wictl` to scan/connect to network:

	wifi scan              # scan wifi
	wifi connect blackhole # ask passphrase and connect to a named AP

The above only works if there are any wifi devices available.
Wired interfaces may be queried and initialized using ifctl:

	ifctl                  # show networking devices
	ifctl -a [dev]         # bring up and dhpc dev

If running on real hardware, press C-Power to power the system off,
and hold C-A-Del for about a second to reboot.

Troubleshooting and caveats
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Errors at "Waiting for devices" stage indicate lack of necessary modules,
especially USB-related.

Emulated keyboard in some qemu versions (?) sends bogus scancodes for arrow
keys. This can be verified using `inputs -r`. Does not seem to happen on real
hardware. No fix atm, and it's probably not something that should be fixed in
minibase.

Weston degrades into unusable mess when running in non-KVM qemu. Apparently
the slow emulated CPU breaks some frame sync assumptions. Without KVM, it may
also take something like 5+ seconds to start, showing blank screen in process.

While the kernel is modular, the supplied configuration only includes modules
for the stuff I have at hand (Intel based laptops). Feel free to reconfigure
if necessary. Sadly enabling everything is not an option for a system that aims
to be "small" in any sense of the word.

No wireless interfaces on HW with a supported Intel card likely likely means
no firmware for this particular card. Try to figure out which file it needs,
and drop it to /lib/firmware.

path: README


code:
#!/bin/sh

rm -fr prebuilt
rm -fr sys-1-plain
rm -fr sys-2-crypt

rm -f prebuilt.tar.xz
rm -f sys-1-plain.tar.xz
rm -f sys-2-crypt.tar


code:
#!/bin/sh

rm -fr sys-1-plain
rm -fr sys-2-crypt
rm -fr prebuilt

rm -f prebuilt.tar.xz
rm -f sys-1-plain.tar.xz
rm -f sys-2-crypt.tar

mkdir sys-2-crypt
cp -at sys-2-crypt ../sys-2-crypt/whole.img
cp -at sys-2-crypt ../sys-2-crypt/xqemu.sh
sed -ne '/^Booting with qemu/,$p' ../README > sys-2-crypt/USAGE

mkdir sys-1-plain
cp -at sys-1-plain ../sys-1-plain/whole.img
cp -at sys-1-plain ../sys-1-plain/xqemu.sh
sed -ne '/^Booting with qemu/,$p' ../README > sys-1-plain/USAGE

mkdir prebuilt
git --git-dir ../.git archive HEAD | tar -x -C prebuilt --exclude _release
git --git-dir ../.git/modules/minibase archive HEAD | tar -x -C prebuilt/minibase
cp -at prebuilt ../brrootfs

tar -Jcvf sys-1-plain.tar.xz sys-1-plain
tar -cvf sys-2-crypt.tar sys-2-crypt
tar -Jcvf prebuilt.tar.xz prebuilt


code:
#!/bin/sh

set -e

rm -fr ./{bin,etc,lib,usr}
cp -at . ../buildroot/output/target/{bin,etc,lib,usr}
cp -at . ../buildroot/output/images/bzImage

rm -fr etc/network
rm -fr etc/profile.d
rm -f etc/fstab
rm -f etc/hostname
rm -f etc/profile
rm -f etc/shadow
rm -f etc/os-release
rm -f etc/services
rm -f etc/protocols
rm -f etc/issue
rm -f etc/drirc
rm -f THIS_IS_NOT_YOUR_ROOT_FILESYSTEM
rm -f lib/rcrt1.o

ln -sf /run/resolv.conf etc/resolv.conf
#rm -f var/run; ln -sf /run var/run

# udev package is a dependency for X and weston but it never actually
# runs with minibase.
rm -fr etc/udev
rm -fr usr/lib/udev
rm -fr lib/udev
rm -f usr/bin/udevadm

# Some stuff we do not need

rm -fr usr/share/wayland-sessions
rm -fr usr/share/polkit-1
rm -fr usr/share/libdrm
rm -fr usr/share/xml
rm -fr usr/share/fontconfig
rm -fr usr/share/weston/*ivi*
rm -fr usr/lib/python2.7

rm -f usr/lib/xml2Conf.sh
rm -f usr/lib/*.py

rm -f usr/lib64

rm -f usr/libexec/*ivi*

rm -f usr/bin/xmllint     # ?!
rm -f usr/bin/xmlcatalog
rm -f usr/bin/urxvtd      # surprisingly large
rm -f usr/bin/urxvtc
rm -f usr/bin/strace-log-merge

# Weston demos, no need to keep them
mkdir -p usr/bin/tmp
mv -t usr/bin/tmp usr/bin/weston-*
mv -t usr/bin/ usr/bin/tmp/weston-terminal
mv -t usr/bin/ usr/bin/tmp/weston-info
rm -fr usr/bin/tmp

rm -f usr/bin/{cvt,gtf}
rm -f usr/bin/wayland-scanner
rm -f usr/bin/fc-*
rm -f usr/bin/libinput-*
rm -f usr/bin/libevdev-*
rm -f usr/bin/wcap-decode
rm -f usr/bin/mtdev-test
rm -f usr/bin/mouse-dpi-tool
rm -f usr/bin/touchpad-edge-detector

rm -f usr/bin/fluxbox-*
rm -f usr/bin/startfluxbox

# Xorg config is in /etc/X11. The default ones only clutter the logs.
rm -fr usr/share/X11/xorg.conf.d

# XCB protocol description files are HUGE
rm -fr usr/share/xcb

# X core fonts. Lots of unnecessary stuff there.
# The default fixed font is 6x13.
rm -fr usr/share/fonts/X11/encodings/large

misc=usr/share/fonts/X11/misc

rm -fr $misc/12x13*
rm -fr $misc/18x18*
rm -fr $misc/k14*
rm -fr $misc/4x6*
rm -fr $misc/5x7*
rm -fr $misc/5x8*
rm -fr $misc/6x9*
rm -fr $misc/6x10*
rm -fr $misc/6x12*
rm -fr $misc/7x*
rm -fr $misc/8x*
rm -fr $misc/9x15*
rm -fr $misc/10x*

(cd $misc && mkfontdir || true)

unset misc

# Liberation fonts are rather large, and we only maybe need regulars?
# (and even that only for Fluxbox menus)
rm -fr usr/share/fonts/liberation/*-Italic.ttf
rm -fr usr/share/fonts/liberation/*-BoldItalic.ttf

# XKB stuff takes *lots* of space. We only need the bare minimum.
# No way to do it with a simple rm, the goal is to remove everything
# except certain files.
xkb=usr/share/X11/xkb
tmp=$xkb.tmp

cp -a $xkb $tmp
rm -fr $xkb/*/*

cp -t $xkb/compat   $tmp/compat/*
cp -t $xkb/geometry $tmp/geometry/pc
cp -t $xkb/keycodes $tmp/keycodes/{xfree86,evdev,aliases}
cp -t $xkb/rules    $tmp/rules/{base,evdev}
cp -t $xkb/symbols  $tmp/symbols/{empty,latin,compose,group,keypad,terminate}
cp -t $xkb/symbols  $tmp/symbols/{parens,srvr_ctrl,shift,level3,level5,pc,us}
cp -t $xkb/symbols  $tmp/symbols/{capslock,ctrl,eurosign,gb,nbsp,altwin,inet}
cp -t $xkb/types    $tmp/types/*

rm -fr $tmp
unset xkb tmp

# Fluxbox installs lots of rather heavy themes

fls=usr/share/fluxbox/styles
tmp=$fls.tmp

cp -a $fls $tmp
rm -fr $fls
mkdir $fls
cp -at $fls $tmp/bloe # default theme

rm -fr $tmp
unset fls tmp

# Mesa builds two distinct .so libraries: one with all Gallium drivers
# and one with all non-Gallium drivers. They get installed as hard links
# but for this system it's much better to have them as symlinks instead.

gallium="usr/lib/dri/kms_swrast_dri.so"
nongallium="usr/lib/dri/i965_dri.so"

for i in usr/lib/dri/*.so; do
	if [ "$i" = "$nongallium" ]; then
		continue
	elif [ "$i" = "$gallium" ]; then
		continue
	elif diff -q "$i" "$nongallium" >& /dev/null; then
		ln -sf `basename $nongallium` $i
	elif diff -q "$i" "$gallium" >& /dev/null; then
		ln -sf `basename $gallium` $i
	fi
done

# linux-firmware installs multiple versions of iwlwifi blobs because reasons.
# We are running a fixed, reasonably recent kernel version so we only need
# the latest blob in each set.
#
#     iwlwifi-8000C-13.ucode <-- drop
#     iwlwifi-8000C-16.ucode <-- drop
#     iwlwifi-8000C-21.ucode <-- drop
#     iwlwifi-8000C-22.ucode <-- drop
#     iwlwifi-8000C-27.ucode <-- drop
#     iwlwifi-8000C-31.ucode <-- drop
#     iwlwifi-8000C-34.ucode <-- keep
#
# These blobs take lots of space (~40MB before trimming) so it is curcial
# to get them out of the image.

cd lib/firmware

last=''
for i in `ls -vr | grep '\.ucode$'`; do
	stem=`echo "$i" | sed -e 's/-[^-]*\.ucode$//'`;

	if [ "$stem" = "$last" ]; then
		rm $i
	else
		last="$stem"
	fi
done


code:
source "$BR2_EXTERNAL_MINIBASE_PATH/package/kilo/Config.in"
source "$BR2_EXTERNAL_MINIBASE_PATH/package/xorg-server-wl/Config.in"

if BR2_PACKAGE_XORG_SERVER_WL

source "$BR2_EXTERNAL_MINIBASE_PATH/package/xf86-input-evdev/Config.in"
source "$BR2_EXTERNAL_MINIBASE_PATH/package/xf86-input-synaptics/Config.in"
source "$BR2_EXTERNAL_MINIBASE_PATH/package/xf86-input-libinput/Config.in"
source "$BR2_EXTERNAL_MINIBASE_PATH/package/xf86-video-intel/Config.in"

endif

source "$BR2_EXTERNAL_MINIBASE_PATH/package/fluxbox-patched/Config.in"
source "$BR2_EXTERNAL_MINIBASE_PATH/package/rxvt-unicode/Config.in"