Home Rotating QWidget-Based Applications

Rotating QWidget-Based Applications

 

Introduction

Qt is a framework used to develop application software with a graphical user interface (GUI). It allows developers to write the application GUI using QWidget(pure C++), QtComponents(C++/QML/JS) or HTML(C++/HTML/JS).
MeeGo 1.2 Harmattan, Nokia’s latest platform in the market, offers to application developers a set of QML Components which can be used to design amazing interfaces where touch input, fluid animations and user experience are crucial. QML Components have been optimized to squeeze out all the GPU power, providing developers with an easy way of coding which doesn’t cause performance loss as QWidget sometimes does. For this and other reasons Harmattan doesn’t support QWidgets. Porting a Symbian or Maemo QWidget-based application to the new platform requires the re-writing of the entire UI. Writing a UI with QML is much easier than with QWidget and the porting doesn’t really take so much time. However, some developers don’t really want to spend time on QML and they want to run the app on MeeGo as it is.

Limitations of QWidgets on Harmattan

QWidgets have many limitations on Harmattan; the most important are:

  • Application orientation locked in landscape
  • No MeeGo Style

In this article we will talk about the first limitation and how it can be worked around.

Why don’t QWidget-based apps rotate on Harmattan?

A mobile application can be locked in landscape or potrait or even be left free to change according to the device orientation value provided by the accelerometer sensor. QWidget class provides a setAttribute method that was largely used on Symbian and Maemo to set the application orientation. QWidget::setAttribute(orientation) on Harmattan doesn’t work anymore because X11 server has been built without RandR extension ( X Resize, Rotate and Reflect ). This means that the screen cannot rotate anymore and therefore it is the application itself which has to rotate. This is an important feature, allowing MeeGo to have a fancy and smooth transition effect when an application switches from one orientation mode to another.

How to work around this problem

In order to make the application work in portrait mode QWidgets need to be rotated. Unfortuantely QWidgets, originally designed for Desktop, are not able to rotate. The only way to rotate a QWidget is to paint it in a canvas and rotate it. Qt canvas is called QGraphicsScene. The scene is displayed to the user by a QGraphicsView and the items in the QGraphicsScene are QGraphicsItems. In order to paint a QWidget in a QGraphicsScene we need a QGraphicsProxyWidget. The easiest solution to rotate the app would be to paint the main window on QGraphicsScene and then rotate the scene. Unfortunately this is not really the best solution because developers would need to write the animation code of the transition between the two orientation modes and to adapt the application so that it displays the system bar on the top part of the screen.
A better option would be to transform the QWidget graphics item into a QML element.

The solution: “Embedding” a QWidget in a MeeGo Components-based application

As we said before, MeeGo applications use MeeGo QML components. A MeeGo Components-based application is made up of a [Window] and some [Pages]. To rotate the application we need to paint the QWidget main view on the page. Therefore we have to “transform” the MainWindow widget into a QDeclarataiveItem as shown in the code below.

ProxyWidget::ProxyWidget(QDeclarativeItem *parent) :
    QDeclarativeItem(parent),
    mEmbeddedWidget(new MainWindow())
{
    mEmbeddedWidget->setStyleSheet(STYLE);
    mProxyWidget = new QGraphicsProxyWidget(this);
    mProxyWidget->setWidget(mEmbeddedWidget);
    //mEmbeddedWidget->setAutoFillBackground(false);
    mEmbeddedWidget->setAttribute(Qt::WA_TranslucentBackground);
}
void ProxyWidget::geometryChanged(const QRectF &newGeometry, const QRectF & oldGeometry)
{
    Q_UNUSED(oldGeometry)
    mProxyWidget->setGeometry(newGeometry);
}

The new object type is registered and available to the declarative view

qmlRegisterType<ProxyWidget>("ProxyWidget", 1, 0, "ProxyWidgetItem");

The object is created in QML as shown below

import ProxyWidget 1.0
Page {
    tools: commonTools
    Label {
        id: label
        anchors.centerIn: parent
        text: qsTr("Hello world!")
        visible: false
    }
    Button{
        anchors {
            horizontalCenter: parent.horizontalCenter
            top: label.bottom
            topMargin: 10
        }
        text: qsTr("Click here!")
        onClicked: label.visible = true
    }
    ProxyWidgetItem {
        anchors.fill: parent
    }
}

This code is all you need to rotate the application, so the line below can be removed from the main.cpp

viewer->setOrientation(QmlApplicationViewer::ScreenOrientationAuto);

Canned Solution

To make it easier for you, I made a template which you could re-use. Step-by-step instructions are available here. The code is divided into 2 parts: the first one contains the procedure described previously and the second one should contain the code of your application. This code is built as static library and its main widget is used by the proxy widget described before.

Limitations

The main limitations of this solution are:

  • QTreeWidget::setItemWidget doesn’t work as expected: the bug has been reported here.
  • QDialogs should not be used.
  • Rotation doesn’t really work on the Qt SDK Simulator.
  • WebView microfocus doesn’t work correctly. The virtual keyboard doesn’t disappear when input html elements lose the focus. Solution is described in the block below:
  • The virtual keyboard cannot be closed by tapping outside the text field (QLineEdit): The following code snippet fix this problem too.
In applications developed with Qt WebKit the virtual keyboard is not
automatically hidden when it is unfocused. A workaround consists of
adding an event filter to the affected view instance:
class EventFilter : public QObject
{
protected:
    bool eventFilter(QObject *obj, QEvent *event) {
        QInputContext *ic = qApp->inputContext();
        if (ic) {
            if (ic->focusWidget() == 0 && prevFocusWidget) {
                QEvent closeSIPEvent(QEvent::CloseSoftwareInputPanel);
                ic->filterEvent(&closeSIPEvent);
            } else if (prevFocusWidget == 0 && ic->focusWidget()) {
                QEvent openSIPEvent(QEvent::RequestSoftwareInputPanel);
                ic->filterEvent(&openSIPEvent);
            }
            prevFocusWidget = ic->focusWidget();
        }
        return QObject::eventFilter(obj,event);
    }
private:
    QWidget *prevFocusWidget;
};
This filter can be installed on a QGraphicsView or (in QML) on a
QDeclarativeView instance:
EventFilter ef;
view.installEventFilter(&ef);

 
Source QtExperts

About ReadWrite’s Editorial Process

The ReadWrite Editorial policy involves closely monitoring the tech industry for major developments, new product launches, AI breakthroughs, video game releases and other newsworthy events. Editors assign relevant stories to staff writers or freelance contributors with expertise in each particular topic area. Before publication, articles go through a rigorous round of editing for accuracy, clarity, and to ensure adherence to ReadWrite's style guidelines.

Get the biggest tech headlines of the day delivered to your inbox

    By signing up, you agree to our Terms and Privacy Policy. Unsubscribe anytime.

    Tech News

    Explore the latest in tech with our Tech News. We cut through the noise for concise, relevant updates, keeping you informed about the rapidly evolving tech landscape with curated content that separates signal from noise.

    In-Depth Tech Stories

    Explore tech impact in In-Depth Stories. Narrative data journalism offers comprehensive analyses, revealing stories behind data. Understand industry trends for a deeper perspective on tech's intricate relationships with society.

    Expert Reviews

    Empower decisions with Expert Reviews, merging industry expertise and insightful analysis. Delve into tech intricacies, get the best deals, and stay ahead with our trustworthy guide to navigating the ever-changing tech market.