Bugs, bugs, and then some features…

October 13, 2011 at 8:34 am | Posted in Uncategorized | Leave a comment

Well, needless to say the quick submission to Ovi Store did not work. There were bugs that needed to be corrected:

1. The Qt SDK overwrote the qmlapplicationviewer.cpp code at the last build so the application did not show any QML.
2. The playing of morse code disabled the UI, creating a warning message.
3. When rotating the device while inputing text the playbutton took over the entire screen.
4. (This one I found myself), there is need for about information so this needed to be added.

So back to the SDK to clean things up.

The first bug is easy to fix as I just started using code version control – a quick revert and we’re done.

The second bug is much more tricky. My first idea was to use a WorkerScript inside my existing QML code to run the morse playback. This was a mistake, as it seems there is no way to access a QML object from within a WorkerScript (especially a C++ object). So the way forward was to insert the threading into the MorsePlayer C++ object. As a side-effect I was able to include a stop functionality, so a user can stop morse playback.

morseplayer.cpp:

...
class MorseThread : public QThread {

public:
    MorseThread ( MorsePlayer* player ) : 
          m_player( player ), m_text( "" ), 
          m_stop(false), m_mutex() {}

    void setText( const QString& text ) { m_text = text; }

    void run() {
        m_stop = false;
        QString morseString( m_text.toUpper() );
        m_player->setSending( true );
        for ( int i = 0; i playLetter( morseString.at( i ) );
            QMutexLocker locker(&m_mutex);
            if ( m_stop ) {
                break;
            }
        }
        m_player->setSending( false );
    }
public slots:
    void stopFlag( bool stopFlagValue ) {
        QMutexLocker locker(&m_mutex);
        m_stop = stopFlagValue;
    }

public:
    MorsePlayer* m_player;
    QString m_text;
    bool m_stop;
    QMutex m_mutex;
};
...

The third bug was also tricky. After trying to detect rotation using the Window orientationChangeFinished signal, and noticing that the virtual keyboard interferes with the result, the method I chose was to remove the button when the TextArea was active – this improves the usability as it is unlikely a user will want to input and playback at the same time. This also gave me a chance to play around with QML animations, and states.

MainPage.qml:

...
   Behavior on height { PropertyAnimation { duration: 500 } }
   Behavior on font.pixelSize { PropertyAnimation { duration: 500 } }
   states: [
     State {
       name: "active"
       when: morseText.activeFocus
       PropertyChanges {
         target: playButton
         height: 0
       }
       PropertyChanges {
         target: playButton
         font.pixelSize: 1
       }
     },
     State {
       name: "inactive"
       when: !morseText.activeFocus
       PropertyChanges {
         target: playButton
         height: ( parent.height*0.2 )
       }
       PropertyChanges {
         target: playButton
         font.pixelSize: ( parent.height*0.1 )
       }
    }
  ]
...

The last bug was interesting too. Just for the fun of it I decided to make a QML splash screen and to reuse it inside the application. This meant I had to play around with the application’s page stack.

main.qml:

...
  initialPage: SplashScreen {
    id: splashPage
    Timer {
      id: timer
      interval: 300
      running: true
      onTriggered: {
        var component = 
          Qt.createQmlObject( 'import QtQuick 1.1; MainPage { }', 
          appWindow );
        appWindow.pageStack.push( component );
      }
    }
  }
...

To activate the about screen from within the application I added a toolbar, and got hit by a gotcha. The final code:

main.qml:

...
  ToolBarLayout {
    id: commonTools
    visible: false
    ToolIcon {
      platformIconId: "toolbar-view-menu"
      anchors.right: (parent === undefined) ? undefined : parent.right
      onClicked: {
        var component = 
          Qt.createQmlObject( 
          'import QtQuick 1.1; SplashScreen { tools: backgroundTools }',
                   appWindow );
        appWindow.pageStack.push( component )
      }
   }
  }

  ToolBarLayout {
    id: backgroundTools
    visible: false
    ToolIcon {
      platformIconId: "toolbar-back"
      anchors.left: (parent === undefined) ? undefined : parent.left
      onClicked: {
        appWindow.pageStack.pop();
       }
    }
  }
...

The gotcha is to make the toolbars invisible in the PageStackWindow, and only to enable them in the Page code using tools property.

I also heard that it is possible to create another splash screen using the Nokia N9 program (see “Enabling a splash screen for an application”). This requires images 854×480, so out with the GIMP program and following the Drive application approach I created two images with the MP logo. The next step is to hack the _harmattan.desktop file:

...
Exec=/usr/bin/invoker --type=d --splash=/opt/morseplayer/morseplayer_portraitSplash.png 
                     --splash-landscape=/opt/morseplayer/morseplayer_landscapeSplash.png 
                     -s /opt/morseplayer/bin/morseplayer
...

Now it is time to re-submit.
(The updated source code is here.)

Advertisements

Simple Morse Player for the N950, now for the N9 and submitted to Store.

October 4, 2011 at 3:27 pm | Posted in Uncategorized | Leave a comment

Store Submission done!

Well, I thought I would share my code with the world by putting the application on the Nokia Store. This was pretty easy once I had cleaned up the code a bit.

The big thing for me was placing the qml files inside the binary. The files where put inside a resource file, and the QmlApplicationViewer setMainQmlFile function hacked to remove the adjustPath function call, and to use a QUrl instead of a local file.

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

Then the main.cpp needed to be changed to point to the resource file;

...
    viewer->setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
    viewer->setMainQmlFile("qrc:/qml/qml/morseplayer/main.qml");
    viewer->showExpanded();
...

Additionally, I created a configuration file for linking the application to the resource management framework:

[classify media]
/opt/morseplayer/bin/morseplayer

And altered the .pro file to install this file into the right location on the device:

...
contains(MEEGO_EDITION,harmattan) {
    desktopfile.files = $${TARGET}.desktop
    desktopfile.path = /usr/share/applications
    rsrc_config.files = morseplayer.conf
    rsrc_config.path = /usr/share/policy/etc/syspart.conf.d
    INSTALLS += desktopfile rsrc_config
}
...

To make things proper I also did some editing to the debian packaging tools, see the source code for more information.

Once the software was ready, it was time to put it in the Store. So after quickly running through the quality criteria, I started the publish process.

For those of you who will do this later, you will need a screenshot in two formats square, and in the N9 resolution. I created the screenshot using the screenshot tool, and then made it square using GIMP. The Store also wants a 256×256 icon, this I created using GIMP and scaling up the application icon.

The rest of the information is pretty straightforward:
1. A web site (this blog)
2. A maintainer email (my own)

And then it is there.
Here is the source code.

Now all I have to do is wait for Store QA to get back to me.

Create a free website or blog at WordPress.com.
Entries and comments feeds.