Double status bar with PySide and QML on Nokia N9 harmattan

527 views Asked by At

I'm trying to use PySide with QML on Nokia N9, and for some reason, my test app looks unlike the native N9 apps. For example, here I get a double status bar (they both react to tapping).

Double status bar

Here's the code for this:

main.py

import sys

from PySide.QtCore import *
from PySide.QtGui import *
from PySide.QtDeclarative import *

app = QApplication(sys.argv)
view = QDeclarativeView()
view.setResizeMode(QDeclarativeView.SizeViewToRootObject)
view.setSource('main.qml')
view.window().show()
app.exec_()

And the QML files:

main.qml

import QtQuick 1.1
import com.nokia.meego 1.1 

PageStackWindow {
  Component.onCompleted: {
    var pageComponent = Qt.createComponent("PageX.qml")
    pageStack.push(pageComponent)
  }
}

PageX.qml

import QtQuick 1.1
import com.nokia.meego 1.1

Page {
  id: pageOne
  Text {
    text: "Hello, this is page one"
  }
}

The file main.qml creates a PageStackWindow, and I suspect it's the ...Window part that makes the phone render the status bar again, like it tries to add a status bar to each window created (and here, maybe we have a window inside a window?). Also, there's a space between the window and the toolbar. Can someone point to the right way of doing this? I just want to use normal Pages inside a PageStack.

2

There are 2 answers

1
Edip Ahmet On BEST ANSWER

You can try "showStatusBar : false". I tryed your example on Qt Simulator, and it works without statusbar. I had a Meego - QML - PySide application, QML app worked without statusbar on Qt Simulator. But When I tryed it on android with Necessitas, I got same problem. After I use "showStatusBar : false" problem solved. Thank you, It is first time I ran my QML-Meego application on android after I saw your question :)

PageStackWindow {
  showStatusBar : false
  Component.onCompleted: {
    var pageComponent = Qt.createComponent("PageX.qml")
    pageStack.push(pageComponent)
  }
}
0
Edip Ahmet On

Sorry I am new to QML. You can try a different QML Harmattan example and try again with python using this view.window().showFullScreen() My application includes ListView and is based on an example application by Nokia Harmattan developer documentation site. First this is main.py for android:

#!/usr/bin/env python

# A simple PySide example

import sys
import os
import traceback

# log to file on Android

LOG_FOLDER = '/sdcard/'
fSock = open(os.path.join(LOG_FOLDER, 'pyside_example_log.txt'), 'w', 1)
rfSock = open(os.path.join(LOG_FOLDER, 'pyside_example_error_log.txt'), 'w', 1)
sys.stdout = fSock
sys.stderr = rfSock

print("** stdout diverted to file **")

# for some reason, the PySide bindings can't find the libshiboken.so and libshiboken,
# even though they are in a directory in LD_LIBRARY_PATH, resulting in errors like this:
#
# ImportError: Cannot load library: link_image[1965]:   157 could not load needed library
# 'libshiboken.so' for 'QtCore.so' (load_library[1120]: Library 'libshiboken.so' not found)
#
# if both are loaded to memory manually with ctypes, everything works fine
print('manual libshiboken.so and libpyside.so loading')
from ctypes import *
#PROJECT_FOLDER = '/data/data/org.modrana.PySideExample'

# PYSIDE_APPLICATION_FOLDER is set in main.h in the Example project
PROJECT_FOLDER = os.environ['PYSIDE_APPLICATION_FOLDER']
LIB_DIR = os.path.join(PROJECT_FOLDER, 'files/python/lib')
SHIBOKEN_SO = os.path.join(LIB_DIR, 'libshiboken.so')
PYSIDE_SO = os.path.join(LIB_DIR, 'libpyside.so')
print("path to libshiboken and libpyside:")
print(SHIBOKEN_SO)
print(PYSIDE_SO)
shibok = CDLL(SHIBOKEN_SO)
psde = CDLL(PYSIDE_SO)
print("manual loading done")

print("importing PySide")
from PySide import QtCore, QtGui
from PySide.QtCore import QObject
from PySide.QtGui import *
from PySide.QtDeclarative import *
print("PySide import done")

#print(os.environ)



# enable running this program from absolute path
os.chdir(os.path.dirname(os.path.abspath(__file__)))
print("dir changed")

class PropertyExample(QObject):
  """
  Python property provider
  """
  def __init__(self):
    QObject.__init__(self)
    self.rootObject = None
    #NOTE: the root object is needed only by Python properties
    # that call QML code directly

  """@QtCore.Slot(result=str)
  def getDate(self):
    return str(datetime.datetime.now())"""

  """@QtCore.Slot(str)
  def notify(self, text):

    #NOTE: QML uses <br> instead of \n for linebreaks
    self.rootObject.notify(text)
"""


class ImagesFromPython(QDeclarativeImageProvider):
  """
  Image provider example
  """
  def __init__(self):
    # this image provider supports QImage,
    # as specified by the ImageType
    QDeclarativeImageProvider.__init__(self, QDeclarativeImageProvider.ImageType.Image)



def main():
  app = QApplication(sys.argv) # create the application
  view = QDeclarativeView() # create the declarative view
  # add Python properties to the
  # QML root context
  rc = view.rootContext()
  # add the example property
  property = PropertyExample()
  rc.setContextProperty("example", property)

  # register image providers
  # NOTE: the image provider name in the Image.source URL is automatically lower-cased !!


  # NOTE2: view.engine().addImageProvider("from_python", ImagesFromPython())
  # doesn't work for some reason


  view.setResizeMode(QDeclarativeView.SizeRootObjectToView)
  view.setSource("main.qml")
  rootObject = view.rootObject()
  property.rootObject = rootObject

  #view.setWindowTitle(WINDOW_TITLE)
  # view.setResizeMode(QDeclarativeView.SizeRootObjectToView)
  #view.setResizeMode(QDeclarativeView.SizeViewToRootObject)
  view.window().showFullScreen()
  # view.resize(480,854)
  #view.resize(854,480)
  view.show()
  app.exec_()



if __name__ == '__main__':
  print("__main__")
  fSock.flush()
  try:
    main()
  except Exception:
    fp = open(os.path.join(LOG_FOLDER, 'pyside_example_exception_log.txt'), 'w', 0)
    traceback.print_exc(file=fp)
    fp.flush()
    fp.close()
    traceback.print_exc(file=fSock)
    fSock.flush()
  rfSock.flush()
  rfSock.close()
  fSock.flush()
  fSock.close()
  exit(0)

And QML codes:

//main.qml
 import QtQuick 1.1
 import com.nokia.meego 1.1

 PageStackWindow {
     id: rootWindow
     property int pageMargin: 16

     // ListPage is shown when the application starts, it links to
     // the component specific pages
     initialPage: MainPage { }

     // These tools are shared by most sub-pages by assigning the
     // id to a tools property of a page
     ToolBarLayout {
         id: commonTools
         visible: false
         ToolIcon {
             iconId: "toolbar-back";
             onClicked: { myMenu.close(); pageStack.pop(); }
         }
         ToolIcon {
             iconId: "toolbar-view-menu";
             onClicked: (myMenu.status == DialogStatus.Closed) ? myMenu.open() : myMenu.close()
         }
     }
 }




//MainPage.qml
 import QtQuick 1.1
 import com.nokia.meego 1.1

 Page {
     id: listPage
     anchors.margins: rootWindow.pageMargin

     function openFile(file) {
         var component = Qt.createComponent(file)
         if (component.status == Component.Ready)
             pageStack.push(component);
         else
             console.log("Error loading component:", component.errorString());
     }

     ListModel {
         id: pagesModel
         ListElement {
             page: "SimpleExamplesPage.qml"
             title: "Simple examples"
             subtitle: "Buttons, TextField, ToolBar and ViewMenu"
         }
         ListElement {
             page: "DialogsPage.qml"
             title: "Dialogs"
             subtitle: "How to use different dialogs"
         }
     }

     ListView {
         id: listView
         anchors.fill: parent
         model: pagesModel

         delegate:  Item {
             id: listItem
             height: 88
             width: parent.width

             BorderImage {
                 id: background
                 anchors.fill: parent
                 // Fill page borders
                 anchors.leftMargin: -listPage.anchors.leftMargin
                 anchors.rightMargin: -listPage.anchors.rightMargin
                 visible: mouseArea.pressed
                 source: "image://theme/meegotouch-list-background-pressed-center"
             }

             Row {
                 anchors.fill: parent

                 Column {
                     anchors.verticalCenter: parent.verticalCenter

                     Label {
                         id: mainText
                         text: model.title
                         font.weight: Font.Bold
                         font.pixelSize: 26
                     }

                     Label {
                         id: subText
                         text: model.subtitle
                         font.weight: Font.Light
                         font.pixelSize: 22
                         color: "#cc6633"

                         visible: text != ""
                     }
                 }
             }

             Image {
                 source: "image://theme/icon-m-common-drilldown-arrow" + (theme.inverted ? "-inverse" : "")
                 anchors.right: parent.right;
                 anchors.verticalCenter: parent.verticalCenter
             }

             MouseArea {
                 id: mouseArea
                 anchors.fill: background
                 onClicked: {
                     listPage.openFile(page)
                 }
             }
         }
     }
     ScrollDecorator {
         flickableItem: listView
     }
 }




 //DialogsPage.qml
     import QtQuick 1.1
     import com.nokia.meego 1.1

     Page {
         id: root
         tools: tabTools
         anchors.margins: rootWindow.pageMargin

         QueryDialog {
             id: query

             icon: "image://theme/icon-l-contacts"
             titleText: "Query Dialog Example"
             message: "Press accept or reject button"
             acceptButtonText: "Accept"
             rejectButtonText: "Reject"
             onAccepted: labelQueryResult.text = "Result: Accepted";
             onRejected: labelQueryResult.text = "Result: Rejected";
         }

         SelectionDialog {
             id: singleSelectionDialog

             titleText: "Single Selection Dialog Header"
             selectedIndex: 1

             model: ListModel {
                 ListElement { name: "ListElement #1" }
                 ListElement { name: "ListElement #2" }
                 ListElement { name: "ListElement #3" }
                 ListElement { name: "ListElement #4" }
                 ListElement { name: "ListElement #5" }
                 ListElement { name: "ListElement #6" }
                 ListElement { name: "ListElement #7" }
                 ListElement { name: "ListElement #8" }
                 ListElement { name: "ListElement #9" }
                 ListElement { name: "ListElement #10" }
             }
         }

     // Create page and buttons
     ScrollDecorator {
         flickableItem: container
     }

     Flickable {
         id: container

         x: 0 // we need to set the width and height
         y: 0
         width: root.width
         height: root.height
         contentWidth: dialogs.width
         contentHeight: dialogs.height

         flickableDirection: Flickable.VerticalFlick
         pressDelay: 100

         Column {
             id: dialogs
             spacing: 24

             Row {
                 spacing: 32

                 Button {
                     text: "Query"
                     width: 200
                     onClicked: {
                         query.open();
                     }
                 }

                 Label {
                     id: labelQueryResult
                     text: "Result: N/A"
                 }
             }

             Row {
                 spacing: 32

                 Button {
                     text: "SingleSelection"
                     width: 200
                     onClicked: {
                         singleSelectionDialog.open();
                     }
                 }

                 Grid {
                     rows: screen.orientation == Screen.Landscape || screen.orientation == Screen.LandscapeInverted ? 1 : 2

                     Rectangle {
                         width: 200
                         height: 30
                         color: "white"

                         Text {
                             y: 10
                             anchors.centerIn: parent
                             text: "Selected:"
                             font.pixelSize: 15
                             font.bold: true
                         }
                     }

                     Rectangle {
                         width: 200
                         height: 30
                         color: "lightgray"

                         Text {
                             anchors.centerIn: parent
                             text: singleSelectionDialog.model.get(singleSelectionDialog.selectedIndex).name
                             font.pixelSize: 15
                             font.bold: true
                         }
                     }
                 }
             }

             Row {
                 spacing: 32

                 Button {
                     text: "Color menu"
                     width: 200
                     onClicked: {
                         colorMenu.open();
                     }
                 }

                 Rectangle {
                     id : colorRect
                     width: 50; height: 50;
                     color : "black"

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

     ToolBarLayout {
         id: tabTools

         ToolIcon { iconId: "toolbar-back"; onClicked: { colorMenu.close(); pageStack.pop(); }  }
         ToolIcon { iconId: "toolbar-view-menu" ; onClicked: colorMenu.open(); }
     }

     Menu {
         id: colorMenu
         visualParent: pageStack

         MenuLayout {
             MenuItem {text: "Red"; onClicked: { colorRect.color = "darkred" } }
             MenuItem {text: "Green"; onClicked: { colorRect.color = "darkgreen" }}
             MenuItem {text: "Blue"; onClicked: { colorRect.color = "darkblue" }}
             MenuItem {text: "Yellow"; onClicked: { colorRect.color = "yellow" }}
         }
     }
 }