Upgrading to 10.0 beta 3

This document lists the major changes that affect applications built using the 10.0 beta 2 release of the BlackBerry 10 Native SDK.

For more information about functionality that is new in this release, see the 10.0 beta 3 Release Notes.

Common errors that you might encounter

'class bb::cascades::QmlDocument' has no member named 'createRootNode'
createRootNode was replaced by createRootObject. See Application changes.
no matching function for call to 'bb::cascades::QmlDocument::create()'
Typically the change is from: QmlDocument *qml = QmlDocument::create().load("main.qml"); to QmlDocument *qml = QmlDocument::create("asset:///main.qml"); See Application changes.
no matching function for call to 'MyApp::append(QVariantList&)'
Populate a list using the following:
foreach(QVariant v, mAppData){
    if(v.toMap().value("status") == filter) {
        filteredAppData << v;
        append(v.toMap());
    }
}
Cannot assign to non-existent property "multiSelectAction" multiSelectAction: MultiSelectActionItem
Property multiSelectAction on Page, ActionSet and MultiSelectHandler have been removed. Add your MultiSelectActionItem directly to the list of AbstractActionItem. See Multiselect changes.
Cannot assign to non-existent property "deleteAction" deleteAction: DeleteActionItem {
Add your DeleteActionItem directly to the list of AbstractActionItem. See Multiselect changes.
Cannot assign to non-existent property "reserveImageSpace"
Property renamed to imageSpaceReserved.
Cannot assign to non-existent property "topPadding" or "leftPadding" and so on
Padding properties moved from StackLayout and DockLayout to the Control class. See Layout and padding changes.
Cannot assign to non-existent property "horizontalAlignment"
The alignment properties have moved to the Control class. See Layout and padding changes.
Cannot assign to non-existent property "selectionMode"
Property removed, no longer necessary.
TypeError: Result of expression 'segmented.selectedValue' [todo] is not a function.
Change someModel.filter = segmented.selectedValue(); to someModel.filter = selectedValue;
Result of expression 'nav.deprecatedPushQmlByString' [undefined] is not a function.
Removed deprecatedPushQmlByString() from NavigationPane. See Navigation changes.
Cannot assign to non-existent property "alignment"
Property alignment removed from TextArea.

Application changes

Static methods removed from Application

The static methods Application::setScene, ::setMenu, ::setMenuEnabled, and ::isMenuEnabled were removed. An Application::instance() static method was added, returning the instance of Application. The static methods were converted to properties of Application objects (which also made them available to QML).

Replace uses of static methods in the Application class to getting an instance of the application class and calling a member method:

Old:

Application::setScene(page); 
Application::setMenu(menu);   

New:

Application::instance()->setScene(page);
Application::instance()->setMenu(menu);

Convenience methods added for connecting to signals in builder

Previously in C++, in many cases you had to construct the object first using a builder and then connect to its signals:

Button *button;
Container *container = Container::create()
.add(button = Button::create().title("Stuff"));

// Connection has to be done later. 

// If any Q_ASSERT statement(s) indicate that the slot failed to connect to 
// the signal, make sure you know exactly why this has happened. This is not
// normal, and will cause your app to stop working!!
bool res;

// Since the variable is not used in the app, this is added to avoid a 
// compiler warning.
Q_UNUSED(res);

res = QObject::connect(button,SIGNAL(clicked()), this, SLOT(onClickedHandler())); 

// This is only available in Debug builds.
Q_ASSERT(res);

Now a new convenience method was added to BaseObject's builder to connect to any constructed object's signal. This helps simplify code when constructing a scene:

Container *container = Container::create() 
.add(Button::create().title("Stuff").connect(SIGNAL(clicked()),
    this, SLOT(onClickedHandler())));  

In addition, shortcut builder methods were added for several frequently used signals. Specifically, Button::clicked(), Option::selectedChanged(), ProgressIndicator::progressChanged(), Slider::valueChanged(), AbstractActionItem::triggered(), VisualNode::touch() and ::touchCapture() have new dedicated convenience builder methods.

Button *button = Button::create().title("Stuff").onClicked(this, 
    SLOT(onClickedHandler()));
ActionItem *action = ActionItem::create().text("Stuff").onTriggered(this, 
    SLOT(onTriggeredHandler()));

Enhanced error handling with QmlDocument, ComponentDefinition, and ControlDelegate

It is now possible to listen to errors coming from ComponentDefinition and ControlDelegate QML elements. For example:

Container {
  Button {
     text: "Click to create control"
     onClicked: {
        // checks whether the component has been correctly loaded and
        // creates borderedTextComponent control and appends it to container
        if (! borderedTextComponent.hasError())
            var createdControl = borderedTextComponent.createControl(container);
            createdControl.textString = "Hello Component";
            createdControl.padding = 30;
            createdControl.textColor = Color.DarkGray;
        } else {
             console.log("Problem with loading borderedTextComponent: "
                       +borderedTextComponent.errorString());
        }
     }
  }
  Container {
     id: container
  }
  attachedObjects [
     ComponentDefinition {
        id: borderedTextComponent
        source: "BorderedTextComponent.qml"
     }
  ]
}
 

and this:

ControlDelegate {
    id: controlDelegate
    delegateActive: checkBox.checked
    onError: {
        console.log("Error while loading the delegate: "+errorMessage)
    }
}

Changes to QmlDocument

The signature of QmlDocument has changed. You must specify the document in the create() function. The load() call is optional (and can be deferred if needed). The createRootNode() function has been changed to support BaseObject and the function name has been changed to createRootObject().

QmlDocument no longer sets the Application instance as a default parent. This was changed in order to make the object behave more like any other QObject. To upgrade your code, add parent() or setParent() calls. For example, you should change your code from QmlDocument::create("asset:///mydoc.qml"); to QmlDocument::create("asset:///mydoc.qml").parent(this).

For example:

#include <bb/cascades/Application>
#include <bb/cascades/QmlDocument>
#include <bb/cascades/AbstractPane>
#include <bb/cascades/Page> 

...
    // Create scene document from main.qml asset
    QmlDocument *qml = QmlDocument::create("asset:///main.qml").parent(&app);

    if (!qml->hasErrors()) {
        Page *page= qml->createRootObject<Page>();
        if (page) {
             Application::instance()->setScene(page);
        }
    }

Changes to relative paths for QmlDocument

In order to align the behavior of QmlDocument with the Image resources, when specifying relative path, the QmlDocument now loads the files from the current working directory (previously from the assets directory). To obtain the former behavior, please use "asset:///" scheme to load the document. Typically the change is from QmlDocument::create("mydoc.qml")  to QmlDocument::create("asset:///mydoc.qml").

Changes to ownership policy for all remove() functions

In order to make sure the objects in QML are not garbage collected unexpectedly, the ownership policy has been changed for all remove functions. All remove() functions no longer set the removed item's parent to "0". From now on when an object is removed from its container, it is still owned by the container (that is, has container as its parent), but you are allowed to take its ownership by calling setParent().

WARNING: The following pseudo code that worked before will crash now because of this change:

myContainer.remove(myObject); 
delete myContainer; 
myObject->setSomething(...);

After removing myObject from myContainer, myContainer will still own it (be the parent of myControl). Deleting myContainer will delete myControl as well and then trying to access myObject will lead to a crash. So make sure you don't have code that look like above. Or if you want to be on the safe side and ensure that everything works as before, you could add a setParent(0) after each call to a remove function in your C++ code:

myContainer.remove(myObject); 
myObject.setParent(0);

Affected APIs:

  • ActionSet::remove()
  • Container::remove()
  • Container::replace()
  • Control::removeActionSet()
  • DropDown::remove()
  • Page::removeAction()
  • Menu::removeAction()
  • MultiSelectHandler::removeAction()
  • NavigationPane::remove()
  • RadioGroup::remove()
  • SegmentedControl::remove()
  • TitleBar::removeOption()
  • VisualNode::removeAnimation()
  • VisualNode::removeGestureHandler()
  • VisualNode::removeTouchBehaviour()

Data and filesystem changes

Data access changes

Support for accessing data from SQL and JSON was extended to include XML. The concept of a DataSource was introduced to allow QML access to any of the three data types as well as supporting network access for XML/JSON data.

New classes:

  • bb::data::DataSource
    • Defines data access properties: source url, type, query(SQL/XML), remote
    • Represents the QML interface to data
    • Uses data access features to load data
    • Data can be passed to data model using simple JavaScript or C++ code
  • bb::data::XmlDataAccess
    • Can be used to load or save XML data in a similar pattern as JsonDataAccess and SqlDataAccess

Removed classes:

  • bb::data::DataAccess:

    Defines standard methods for error handling which were used by its derived classes JsonDataAccess, SqlDataAccess and XmlDataAccess. This pattern still exists in these three classes without the need for a base class so DataAccess was removed.

  • bb::data::DataSet:

    Was previously deprecated and has now been removed. Data model classes in bb::cascades such as bb::cascades::GroupDataModel provided this functionality.

File system access changes

Image suffixes are now required when referencing image filenames. It is no longer possible to reference image assets as <image>, suffixes always must be used (if the source file has a suffix). If image metadata should be used then the application must reference the metadata file instead of the image source file (that is, <image.amd> instead of <image.png>).

The amd file format has been changed. Please update to the following format:

#RimCascadesAssetMetaData version=1.0 
sliceMargins:63 62 51 123 
source: "domo_sliced.png"         

Foreign window changes

ForeignWindow control API changed to ForeignWindowControl

After platform API review the following changes were made:

  • ForeignWindow control was renamed to ForeignWindowControl to reduce confusion with bb::cascades::Window API
  • Instead of unsigned long, methods and properties that deal with window handles use the screen_window_t type. This includes:
    • The C++ setters for and getters for the windowHandle property (note that from QML it is accessed as a Qvariant since JavaScript doesn't support the long type)
    • windowAttached signal
    • bindToWindow
  • UpdatedWindowProperties class was renamed to WindowProperty, with Type representing different properties and Types flags representing combinations of properties

Old:

// QML
ForeignWindow {
    updatedProperties: UpdatedWindowProperties.Size | 
                       UpdatedWindowProperties.Location
    }
// C++
#include <bb/cascades/ForeignWindow>
#include <bb/cascades/UpdatedWindowProperties>
ForeignWindow *fw = ForeignWindow::create().updatedProperties(
                    UpdatedWindowProperties::Size | 
                    UpdatedWindowProperties::Location);
                    
                    
    // If any Q_ASSERT statement(s) indicate that the slot failed to connect to 
    // the signal, make sure you know exactly why this has happened. This is not
    // normal, and will cause your app to stop working!!
    bool connectResult;
    
    // Since the variable is not used in the app, this is added to avoid a 
    // compiler warning.
    Q_UNUSED(connectResult);
    
    connectResult = connect(fw, SIGNAL(windowAttached(unsigned long, QString, QString)),
    SLOT(onWindowAttached(unsigned long, QString, QString)));
    unsigned long handle = fw.windowHandle();

New:

// QML
ForeignWindowControl {
    updatedProperties: WindowProperty.Size | 
                       WindowProperty.Location
    }
// C++
#include <bb/cascades/ForeignWindowControl>
#include <bb/cascades/WindowProperty>
#include <screen/screen.h>  

ForeignWindowControl *fw = ForeignWindowControl::create().updatedProperties(
                    UpdatedWindowProperties::Size);
    connectResult = connect(fw, SIGNAL(windowAttached(screen_window_t, QString, QString)),
    SLOT(onWindowAttached(screen_window_t, QString, QString)));
screen_window_t handle = fw.windowHandle();

ForeignWindowControl updated to address usability

Changes in the ForeignWindowControl were made to address issues introduced when ForeignWindowControl started to update source size as well as window size. The changes will also allow a better way to add more properties controlled by the ForeignWindowControl .

The following API changes were made:

Separation of window attached/detached and control associated/disassociated from a window.

APIs in the ForeignWindowControl have been revised to avoid confusion with “a window attaching or joining the group” and “the control being associated with a window”.

API Changes:

  • attachToWindow/detachFromWindow are renamed to bindToWindow/unbindFromWindow
  • attached property was renamed to boundToWindow (along with corresponding getters and signal: isAttached() is renamed to isBoundToWindow(), attachedChanged() to boundToWindowChanged) because it really only shows when the control is bound to a window, not when window is attached or detached to a group. For example when the control is no longer bound to a window (unbindFromWindow is called), the window may still exist in the group. Same if user uses bindToWindow() call, it doesn't guarantee that the window has been attached yet, so changing attached to true doesn't make sense.

Old:

// QML 
ForeignWindow{ 
    visible: attached  // become visible when attached 
    onAttachedChanged: console.log(attached ? "Attached!" : "Detached!"); 
} 
// C++ 
pFW->attachToWindow(handle, "Group", "Id"); 
pFW->detachFromWindow(); 
  
  
if (pFW->isAttached()) {}

New:

// QML 
ForeignWindowControl{ 
    visible: boundToWindow // become visible when bound 
    onBoundToWindowChanged: console.log(boundToWindow ? "Bound!" : "Unbound!"); 
} 
 
// C++ 
pFW->bindToWindow(handle, "Group", "Id"); 
pFW->unbindFromWindow(); 
  
  
if (pFW->isBoundToWindow()) {}

Builder methods id(), group() and handle() renamed to windowId(), windowGroup() and windowHandle()

API Changes:

  • id() got renamed to windowId() to match corresponding property name
  • group() got renamed to windowGroup() to match corresponding property name

Old:

ForeignWindow *fw = ForeignWindow::create() 
        .id(id) 
        .group(group) 
        .handle(handle) 
        .windowFrameUpdateEnabled(false);
 

New:

ForeignWindowControl *fw = ForeignWindowControl::create() 
        .windowId(id) 
        .windowGroup(group) 
        .windowHandle(handle) 
        .updatedProperties(UpdatedWindowProperties::None);
 

Removed temporary static ForeignWindowControl::mainWindowGroupId() method

The static ForeignWindow::mainWindowGroupId() method was temporary until proper Window API was added, so it has been removed now that we have Window. Note that by default a control's windowId property is initialized to the main application window group so there's no need to set this property unless your window is joining some other group.

API Changes:

  • ForeignWindowControl::mainWindowGroupId() has been removed. To get the window group ID, use the bb::cascades::Application::instance()->mainWindow()-->groupId  property which returns the same thing.

Old:

QString mainWindowGroup = ForeignWindow::mainWindowGroupId(); 

New:

#include <bb/cascades/Application>
#include <bb/cascades/Window>

QString mainWindowGroup = bb::cascades::Application::instance()
    ->mainWindow()->groupId();

ForeignWindowControl::windowFrameUpdateEnabled replaced with updatedProperties property

Changes were made to allow fine grain control over window properties automatically updated by the ForeignWindowControl. Previously the ForeignWindowControl could either update the three properties position, size and source size, or update none. However, some applications needed to change only position and size. Updating all three is not desirable - some don't want to update source size, and some do (the effect is whether the contents of the libscreen window are scaled or not). In addition we will soon need an automatic handling of the window's Z order property so that the window is positioned in Z hierarchy according to the position of the ForeignWindowControl it is bound to as well as visibility property. So instead of creating three or four new properties we created an updatedProperties property which holds a Q_FLAG composed of various window properties, which replaces the bool windowFrameUpdateEnabled property.

API change:

  • windowFrameUpdateEnabled has been removed
  • an updatedProperties property has been added, which holds a combination of flags representing different properties of the window: UpdatedWindowProperties::Type .

Old:

// QML 
ForeignWindow { 
    windowFrameUpdateEnabled: true
} 
ForeignWindow { 
    updatedProperties: false
} 
 
  
// C++ 
pForeignWindow->setWindowFrameUpdateEnabled(true); 
// or 
pForeignWindow->setWindowFrameUpdateEnabled(false);

New:

// QML
ForeignWindowControl {
    updatedProperties: UpdatedWindowProperties.SourceSize | 
                       UpdatedWindowProperties.Size | 
                       UpdatedWindowProperties.Position 
}
ForeignWindowControl {
    // or any other combination of flags or single flag
    updatedProperties: UpdatedWindowProperties.None
} 
// C++
pForeignWindowControl->setUpdatedProperties(UpdatedWindowProperties.SourceSize | 
    UpdatedWindowProperties.Size | 
    UpdatedWindowProperties.Position);

// or just call reset function to do the same:
pForeignWindowControl->resetUpdatedProperties();

// you can specify any other combination of flags or a single flag
pForeignWindowControl->setUpdatedProperties(UpdatedWindowProperties::Position);

Parameters removed from windowDetached()

In the windowDetached() signal, which is sent when the bound window is closed/destroyed and detached from the group, the parameters are useless: by the time the signal is sent the window has been destroyed so you can't use the parameters for anything useful.

API Change:

  • In windowDetached() the parameters were removed.

Old (C++):

// C++ 
connectResult = QObject::connect(m_foreignWindow, 
                       SIGNAL(windowDetached(unsigned long,QString,QString)), 
                       this, 
                       SLOT(onWindowDetached(unsigned long,QString,QString))); 
Q_ASSERT(connectResult);
 

New (C++):

// C++ 
connectResult = QObject::connect(m_foreignWindow, 
                       SIGNAL(windowDetached()), 
                       this, 
                       SLOT(onWindowDetached())); 
Q_ASSERT(connectResult);
 

Behavior change when windowDetached() is received or unbindFromWindow is called: windowHandle is now set to 0.

Previously windowHandle was not changed when window was detached. However in most use cases this is something that the application has to do anyway (typically unbindFromWindow() is used to share the same ForeignWindowControl with multiple windows), so now when unbindFromWindow() is called or after the windowDetached() signal is emitted the windowHandle property will be set to 0.

Parameters in controlFrameUpdated changed

To make it consistent with LayoutUpdateHandler the parameters of controlFrameUpdated() signal were changed from four floats to const QRect&.

API Change:

  • controlFrameUpdated(float x,float y,float width, float height) changed to controlFrameUpdated(const QRectF &rect)

Old:

// QML 
ForeignWindow { 
    onControlFrameChanged: { 
        updateWindow(x, y, width, height); 
    } 
} 
// C++: 
connectResult = QObject::connect(m_foreignWindow, 
                       SIGNAL(controlFrameChanged(float,float,float,float)), 
                       this, 
                       SLOT(updateWindow(float,float,float,float))); 
Q_ASSERT(connectResult);

New:

// QML 
ForeignWindowControl { 
    onControlFrameChanged: { 
        updateWindow(frame.x, frame.y, frame.width, frame.height); 
    } 
} 
// C++: 
connectResult = QObject::connect(m_foreignWindowControl, 
                       SIGNAL(controlFrameChanged(QRectF)), 
                       this, 
                       SLOT(updateWindow(QRectF))); 
Q_ASSERT(connectResult);

Layout and padding changes

Padding properties moved from StackLayout and DockLayout to the Control class

Old (QML):

Container {
    layout: StackLayout {
        topPadding: 10
	}
}

New (QML):

Container {
    layout: StackLayout { }
    topPadding: 10
}

Old (C++):

Container *pMyContainer = Container::create(); 
StackLayout *pMyLayout = StackLayout::create(); 
  
  
pMyContainer->setLayout(pMyLayout); 
pMyLayout->setLeftPadding(10.0f); 

New (C++):

Container *pMyContainer = Container::create();
StackLayout *pMyLayout = StackLayout::create(); 

pMyContainer->setLayout(pMyLayout);pMyContainer->setLeftPadding(10.0f);

Renamed layoutDirection to orientation

The property layoutDirection has changed to orientation and its class name has changed from LayoutDirection to LayoutOrientation.

Old (QML):

StackLayout { layoutDirection: LayoutDirection.TopToBottom }

New (QML):

StackLayout { orientation: LayoutOrientation.TopToBottom }

Old (C++):

pStackLayout->setLayoutDirection( LayoutDirection::TopToBottom ); 

New (C++):

pStackLayout->setOrientation( LayoutOrientation::TopToBottom ); 

Moved alignment from LayoutProperties to Control

DockLayoutProperties and StackLayoutProperties used to share a similar property called alignment. These properties have moved to the Control class.

Old (QML):

Label {  
    layoutProperties: DockLayoutProperties { 
        horizontalAlignment: HorizontalAlignment.Left }  
} 

New (QML):

Label {  
    horizontalAlignment: HorizontalAlignment.Left  
}

Old (C++):

DockLayoutProperties\* properties = new DockLayoutProperties;  
properties->setHorizontalAlignment(HorizontalAlignment::Left);  
control->setLayoutProperties(properties); 

New (C++):

control->setHorizontalAlignment(HorizontalAlignment::Left); 

Removed DockLayoutProperties

Since alignment has moved to Control, DockLayoutProperties has been removed.

Visual border of all Controls are aligned

All controls now align perfectly against other controls. Affected controls:

Slider

The aura is no longer included in the height, this is the most significant change that may affect applications. Use margins or padding to adapt to this change.

ToggleButton

Removed one pixel transparent border.

ActivityIndicator

Removed one pixel transparent border.

Button

Removed one pixel transparent border.

CheckBox

Removed one pixel transparent border.

Divider

Removed one pixel transparent border.

SegmentedControl

Removed one pixel transparent border.

ToggleButton

Removed one pixel transparent border. 

StackLayout propagates the minSize of its static children

By adding support to propagate the minSize of the children in a StackLayout, the distribution of space in nested layouts will be the same as non-nested layouts. This reduces the risk of overlaps or clips of some children when the scene holds enough space in other areas. This will improve the honoring of minSize but will also shift the current layout balance in some cases.

Moved lose focus policy from AbstractTextControl to Control

The code that implements policies for losing focus has moved from AbstractTextControl to Control.

The syntax for setting focus policy is identical but applied to a Control.

Renamed Focusable to FocusPolicy

Changed Focus and Titlebar APIs to conform to API guidelines.

Improved focus handling

There is now improved focus handling functionality available. The old APIs will soon be deprecated so you should upgrade your apps to use the new APIs instead.

To be deprecated (C++):

bb::cascades::FocusRetentionPolicy::Type
Q_SLOT void setFocusRetentionPolicy(
            bb::cascades::FocusRetentionPolicy::Type 
            policy);
bb::cascades::FocusRetentionPolicy::Type focusRetentionPolicy();
Q_SLOT void resetFocusRetentionPolicy();
void focusRetentionPolicyChanged(
            bb::cascades::FocusRetentionPolicy::Type 
            policy);

New (C++):

bb::cascades::FocusRetentionPolicy::Types 
Q_SLOT void setFocusRetentionPolicyFlags(
            bb::cascades::FocusRetentionPolicy::Types 
            policy); 
bb::cascades::FocusRetentionPolicy::Types focusRetentionPolicyFlags(); 
Q_SLOT void resetFocusRetentionPolicyFlags(); 
void focusRetentionPolicyFlagsChanged(
            bb::cascades::FocusRetentionPolicy::Types 
            policy); 

FocusRetentionPolicy is now a flag-property so you can use it as intended, that is, to combine different policies.

To be deprecated (QML):

focusRetentionPolicy 

New (QML):

focusRetentionPolicyFlags

Example of how to combine flags in QML:

TextArea {  
    focusRetentionPolicyFlags: FocusRetentionPolicy.LoseToNonFocusable |
         FocusRetentionPolicy.LoseOnScroll  
    text: "myText"} 

Other behavioral changes related to focus handling:

  • No longer possible to focus a control (programmatically) that's not in the UI or invalid in some other way.
  • No longer possible to focus a control (using touch) that has focusPolicy=key.
  • Calling loseFocus() now only affects the control it's being called on.
  • Controls will now lose focus if they become invalid for focus (that is, not the UI or disabled).
  • Controls with disabled parents now can't get focus.
  • Controls under a SceneCover now can't get focus (SceneCover should be non-interactive).
  • All controls will now report "Default" as default focus policy.
  • FocusPolicy/Retentions signals are now emitted as they should.

Name change for onValueChanging signal in Slider

The onValueChanging() signal in Slider has been renamed to onImmediateValueChanged(). The functionality has not changed.

List changes

ListItemManager renamed to ListItemProvider

Old (QML):

ListView {
    listItemManager: theListItemManager
    onListItemManagerChanged: {
    // ...
    }
}

New (QML):

ListView {
    listItemProvider: theListItemProvider
    onListItemProviderChanged: {
    // ...
    }
}

Old (C++):

QObject::connect(mListView,
    SIGNAL(listItemManagerChanged(bb::cascades::ListItemManager *)),
    this,
    SLOT(onItemManagerChanged(bb::cascades::ListItemManager *)));
    mListView->setListItemManager(mListItemManager);

New (C++):

QObject::connect(mListView,
    SIGNAL(listItemProviderChanged(bb::cascades::ListItemProvider *)),
    this,
    SLOT(onItemProviderChanged(bb::cascades::ListItemProvider *)));
    mListView->setListItemProvider(mListItemProvider);

ListView SnapMode::Front changed name to SnapMode::LeadingEdge

Old (QML):

ListView {snapMode: SnapMode.Front}

New (QML):

ListView {snapMode: SnapMode.LeadingEdge}

Old (C++):

pListView->setSnapMode(SnapMode::Front);

New (C++):

pListView->setSnapMode(SnapMode::LeadingEdge);

ListLayout paddings removed

The padding properties of ListLayout have been removed. The functionality now depends on the padding attributes of ListView. ListView inherits these attributes from Control. To fully support previous functionality it is now possible to set the padding attributes of Control to negative values. The only control that supports this at the moment is ListView.

Old (QML):

ListView { 
    layout: FlowListLayout {
        leftPadding: 10 
        rightPadding: 10 
        topPadding: -50 
        bottomPadding: 0 
    } 
} 

New (QML):

ListView { 
    leftPadding: 10 
    rightPadding: 10 
    topPadding: -50 
    bottomPadding: 0   
    layout: FlowListLayout {} 
}  

Old (C++):

mListLayout->setTopPadding(fPadding); 
mListLayout->setRightPadding(fPadding); 
mListLayout->setBottomPadding(fPadding); 
mListLayout->setLeftPadding(fPadding); 
mListView->setListLayout(mListLayout);   
QObject::connect(mListLayout, SIGNAL(topPaddingChanged(float newTopPadding)), 
    this, SLOT(topPaddingChanged(float newTopPadding))); 

New (C++):

mListView->setTopPadding(fPadding); 
mListView->setRightPadding(fPadding); 
mListView->setBottomPadding(fPadding); 
mListView->setLeftPadding(fPadding);   
QObject::connect(mListView, SIGNAL(topPaddingChanged(float newTopPadding)), 
this, SLOT(topPaddingChanged(float newTopPadding)));  

ListView scrollTo(ScrollPosition::Type) renamed to scrollToPosition(ScrollPosition::Type)

The ListView method Q_SLOT void scrollTo(bb::cascades::ScrollPosition::Type position, bb::cascades::ScrollAnimation::Type scrollAnimation); has been renamed to: Q_SLOT void scrollToPosition(bb::cascades::ScrollPosition::Type position, bb::cascades::ScrollAnimation::Type scrollAnimation);

Old (C++):

mListView->scrollTo(ScrollPosition::Beginning,
    bb::cascades::ScrollAnimation::None);

New (C++):

mListView->scrollToPosition(ScrollPosition::Beginning,
    bb::cascades::ScrollAnimation::None);

Old (QML):

Button {
    text: "Scroll to top"
    onClicked: thelistview.scrollTo(ScrollPosition.Beginning, 
        ScrollAnimation.None)
}

New (QML):

Button {
    text: "Scroll to top"
    onClicked: thelistview.scrollToPosition(ScrollPosition.Beginning, 
        ScrollAnimation.None)
}

HeaderListItem renamed to Header

Old:

HeaderListItem {
    title: "I'm a header list item."
} 

New:

Header {
    title: "I'm still a header list item."
} 

ListView selection behavior changes

A list item is selected when a user touches and holds the item to display the context menu, and then releases the item. The signal selectionChanged() in the ListView is emitted.

The property selectionMode in ListView has been removed. When using the selection APIs in ListView (for example, select(), toggleSelection(), clearSelection(), selectAll()), the ListView behaves as if it is in multiple selection mode. This gives you maximum freedom to implement any selection behavior.

In order to implement what was previously known as Selection::Single, you can use the following QML:

ListView { 
    onTriggered: { 
        clearSelection() 
        select(indexPath); 
    } 
}

In order to implement what was previously known as Selection::Multi, you must connect the triggered() signal with toggleSelection(). For example:

ListView { 
    onTriggered: { 
        toggleSelection(indexPath); 
    } 
}

Multiselect changes

SelectionMode removed from ListView

Setting selection modes in a List is no longer necessary to enable single or multiple selection in the List. The Context Menu automatically handles single and multi-selection based on the presence of an ActionSet and a MultiSelectHandler with an ActionSet.

Selection::Multi behavior changes

A list item is selected when a user touches and holds the item to display the context menu, and then releases the item. The signal selectionChanged() in the ListView is emitted.

The property selectionMode in ListView has been removed. When using the selection APIs in ListView (for example, select(), toggleSelection(), clearSelection(), selectAll()), the ListView behaves as if it is in multiple selection mode. This gives you maximum freedom to implement any selection behavior.

In order to implement what was previously known as Selection::Multi, you must connect the triggered() signal with toggleSelection(). For example:

ListView { 
    onTriggered: { 
        toggleSelection(indexPath); 
    } 
}

And in order to implement what was previously known as Selection::Single, you can use the following QML:

ListView { 
    onTriggered: { 
        clearSelection() 
        select(indexPath); 
    } 
}

Multi-select properties changes

Properties deleteAction and multiSelectAction on Page, ActionSet and MultiSelectHandler have been removed. From now on you need to add your DeleteActionItem and MultiSelectActionItem directly to the list of AbstractActionItem.

Old (QML):

Page {  
    actions: [  
        ActionItem { title: "Page Action 1" },
        ActionItem { title: "Page Action 2" }
        ]
        deleteAction: DeleteActionItem { title: "Page Delete" }
        multiSelectAction: MultiSelectActionItem { title: "Page Select" }

    ListView {
        multiSelectHandler { 
        actions: [
            ActionItem { title: "Handler Action 1" },
            ActionItem { title: "Handler Action 2" }
            ]
            deleteAction: DeleteActionItem { title: "Handler Delete" }
        }
    }

    ImageView {
        contextActions: [
            ActionSet {
            ActionItem { title: "Context Action 1" },
            ActionItem { title: "Context Action 2" }
            deleteAction: DeleteActionItem { title: "Context Delete" } 
            multiSelectAction: MultiSelectActionItem { title: "Context Select" }
            }
        ]
    }
}

New (QML):

Page {
    actions: [ 
        ActionItem { title: "Page Action 1" },
        ActionItem { title: "Page Action 2" },
        DeleteActionItem { title: "Page Delete" },
        MultiSelectActionItem { title: "Page Select" }
        ]

    ListView {
        multiSelectHandler {
        actions: [
            ActionItem { title: "Handler Action 1" },  
            ActionItem { title: "Handler Action 2" },
            DeleteActionItem { title: "Handler Delete" },
            ]
        }
    } 

    ImageView {
        contextActions: [
            ActionSet {
            ActionItem { title: "Context Action 1" },
            ActionItem { title: "Context Action 2" } 
            DeleteActionItem { title: "Context Delete" }
            MultiSelectActionItem { title: "Context Select" }
            }
        ]
    }
}

ListView.multiSelectHandler.multiSelectActionItem property moved to ListView.multiSelectActionItem

Old (QML):

ListView {  
    multiSelectHandler {  
    multiSelectAction: MultiSelectActionItem { title: "Global Select" }  
    }  
}

New (QML):

ListView {  
    multiSelectAction: MultiSelectActionItem { title: "Global Select" }  
    multiSelectHandler {  
    }  
}

This property is a convenience property for setting a global multiSelectAction for every item in the ListView. Setting ListView.multiSelectActionItem adds a MultiSelectActionItem to all ActionSet objects and selecting these actions will automatically trigger ListView.multiSelecthandler.

Multi-Select cancel() signal added and cancelAction property removed

You can't override the behavior of the Cancel button during multi-select. Also, you can't change the appearance of the button.

Navigation changes

Removed deprecatedPushQmlByString() from NavigationPane

You can now use the component definition approach to push pages from QML instead of the function deprecatedPushQmlByString.

Old (QML):

NavigationPane {  
  id: navigationPane     
  Page {  
     content: Container {  
         background: Color.Gray  
         Label { text: "Pre-pushed Page QML" }  
     }  
     actions: [  
        ActionItem {  
           title: "Push"  
           ActionBar.placement: ActionBarPlacement.OnBar  
           onTriggered: {  
               var page = navigationPane.deprecatedPushQmlByString
               ("navigationpane/basicqml/page.qml");  
           }  
        }  
     ]  
  }  
} 

New (QML):

NavigationPane {  
    id: navigationPane    
    Page { 
        content: Container { 
            background: Color.Gray
            Label { text: "Pre-pushed Page QML" }
        }
        actions: [ 
            ActionItem {
                title: "Push"
                ActionBar.placement: ActionBarPlacement.OnBar
                onTriggered: {
                    var page = pageDefinition.createObject();
                    navigationPane.push(page);
                }
                attachedObjects: ComponentDefinition { 
                    id: pageDefinition
                    source: "page.qml"
                } 
            } 
        ]
    } 
}

Removed stack property and added first page handling in QML for Navigation Pane

The stack property on the NavigationPane has been replaced by a firstPage property. The reason is to discourage the practice of adding more than one page at initialization. This change does not affect those writing apps in C++. For those writing apps in QML it means that it is no longer possible to add more than one page at initialization of a NavigationPane. However, it will still be possible to start the NavigationPane with more than one page. Below is an example of how to do that.   If you have code that looks something like this:

NavigationPane {
    id: navigationPane
    Page {
        id: firstPage
        content: Container {
            Label { text: "first page" }
        }
    }
    Page {
        id: secondPage
        content: Container {
            Label { text: "second page" }
        }
    }
} 

You need to change the code so it looks like this:

NavigationPane {
    id: navigationPane
    Page {
        id: firstPage
        content: Container {
            Label { text: "first page" }
        }
    }

    attachedObjects: [
        ComponentDefinition {
            id: secondPageDefinition
            Page {
                id: secondPage
                content: Container {
                    Label { text: "second page" }
                }
            }
        }
    ]
          
    onCreationCompleted: {
        var page = secondPageDefinition.createObject();
        push(page);
    }
} 

Removed popAndDelete function from NavigationPane

The function NavigationPane::popAndDelete() has been removed from the API. The function NavigationPane::pop() should be used instead. To achieve the same functionality as for popAndDelete(), use pop() and then explicitly do delete on the page in callback to the signal popTransitionEnded().

After pop() has been called, the NavigationPane that popped the page now keeps the ownership of the page. The page can be safely deleted at any time after the call to pop(). If the Page happens to be deleted before the popTransitionEnded() signal has been emitted, that signal will still be sent but will set the reference to the popped page to 0. If the popAndDelete() functionality is desired it can also be done programmatically in the app by calling pop() and then doing delete on the page returned from the pop() call (and thus does not have to delete the page in the callback)

The popped page must not be pushed to another control until after the popTransitionEnded() signal has been received. In order to be able to push a popped page to another control, its parent must first be explicitly set to zero.

Note: If you do not wish to keep the popped page for future use, you must release the Page yourself (for example, by listening to the signal popTransitionEnded and then freeing the appropriate memory). If you do not release the memory, popped pages will keep memory allocated until the app closes down (that is, until the NavigationPane is deleted), which may cause memory consumption to increase as the user interacts with the app.

Window API changes

Window class was changed to use screen_window_t type instead of "unsigned long" to represent window type.

  • The handle property's C++ accessors use screen_window_t
  • The handle property is exposed to QML as a QVariant

Old (C++):

/ C++  
#include <bb/cascades/Application>  
#include <bb/cascades/Window> 
    
unsigned long handle = Application::instance()->mainWindow()->handle();  

New (C++):

#include <bb/cascades/Application>  
#include <bb/cascades/Window>     
#include <screen/screen.h>  
   
screen_window_t handle = Application::instance()->mainWindow()->handle();  

Platform and C++ API changes

Camera changes

  1. The video file name has been added as an argument to the videoCaptureStopped signal.
  2. Changed() signals have been added for Camera setting values.
  3. New methods cameraRollPath and setCameraRollPath have been added.
  4. The CameraTypes extensionless header is replaced with extensionless headers for individual classes.

    Before:

    #include <bb/cascades/multimedia/CameraTypes>

    After:

    #include <bb/cascades/multimedia/CameraUnit>

  5. Enumeration classes are now declared using the name Type.

    Before:

    connect(this,
        SIGNAL(cameraOpenFailed(bb::cascades::multimedia::CameraError::Error)),
        this, 
        SLOT(onCameraOpenFailed(bb::cascades::multimedia::CameraError::Error))); 

    After:

    connect(this, 
        SIGNAL(cameraOpenFailed(bb::cascades::multimedia::CameraError::Type)),
        this,
        SLOT(onCameraOpenFailed(bb::cascades::multimedia::CameraError::Type))); 

Device API changes

  • In bb::device::BatteryInfo, the levelChanged() signal signature has changed.

    Old:

    BatteryInfo::levelChanged ( int level, 
        BatteryInfo::ChargingState chargingState )

    New:

    BatteryInfo::levelChanged ( int level, 
        BatteryChargingState::Type newChargingState )
  • In bb::device::HardwareInfo, added instance methods:
    HardwareInfo::deviceName();
    HardwareInfo::deviceName();
    HardwareInfo::imei();
    HardwareInfo::meid();
    HardwareInfo::pin();
    HardwareInfo::serialNumber(); 

    Also, removed static methods pin() and serialNumber(). Use the identical instance methods instead.

  • In the bb::device::VibrationController class, the static method isSupported has been removed. Use the identical instance method instead.
  • The bb::device::Display class has been replaced by the bb::device::DisplayInfo class.

HomeScreen API changes

  • bb::platform::Homescreen has been renamed to bb::platform::HomeScreen (note the capitalization)
  • The enum bb::platform::Homescreen::LockState::Type is now in its own header and has been renamed to bb::platform::DeviceLockState. The enumeration element UnknownLockState has been renamed to Unknown.
  • bb::platform::HomeScreen::setWallpaper (const QString &userWallpaperFilePath) is now bb::platform::HomeScreen::setWallpaper(const QUrl &userWallpaperFilePath).
  • bb::platform::HomeScreen::addShortcut (const QString &iconPath, const QString &iconLabel, const QUrl &url) is now bb::platform::HomeScreen::addShortcut(const QUrl &iconPath, const QString &iconLabel, const QUrl &url). The path to the icon for the shortcut is now a QUrl rather than a QString.
  • bb::platform::HomeScreen::setIconBadge() moved to bb::Application::setIconBadge().
  • Window covers have been moved from bb::platform::HomeScreen to bb::Application. Supporting classes moved from libbbplatform to libbb.
  • There is a new signal, bb::platform::wallpaperFinished(), that will provide the results of a request to set the device wallpaper via bb::platform::HomeScreen::setWallpaper(). If you have been using this already, note too that the enumeration bb::platform::SetWallpaperResult has been renamed to bb::platform::WallpaperResult and the prefix Wallpaper has been removed from the enumeration elements.
  • bb::platform::HomeScreen::setWallpaper() now uses the new PPS Navigator interface to set the wallpaper. The previous PPS object for this was disabled.

Invocation API changes

  • InvokeTarget::Type enumeration values changed. Value 0 was "ALL", is now "Unspecified".
  • InvokeQueryTargetsRequest::setTargetType() was removed.
  • InvokeQueryTargetsRequest::targetType() was removed.
  • InvokeManager::StartupMode changed to ApplicationStartupMode::Type.
  • InvokeQueryTargetsRequest::BrokerModifier changed to InvokeQueryTargetsRequestBrokerModifier::Type.
  • InvokeReply::Error changed to InvokeReplyError::Type.
  • InvokeViewerMessageReply::Error changed to InvokeViewerMessageReplyError::Type.
  • InvokeRequest::source() returns InvokeSource instead of QString.
  • InvokeManager::invoke() returns InvokeTargetReply* instead of InvokeReply*
  • InvokeRequest::setSource() was removed.

libbb changes

bb::Application

  • The windowGroupId parameter has been removed from all signals.

    Old:

    Application::asleep( QString windowGroupId );
    Application::awake( QString windowGroupId );
    Application::fullscreen( QString windowGroupId );
    Application::invisible( QString windowGroupId );
    Application::thumbnail( QString windowGroupId );

    New:

    Application::asleep();
    Application::awake();
    Application::fullscreen();
    Application::invisible();
    Application::thumbnail(); 
  • Removed urlHandlerInvoked. Use the Invoke API instead.

bb::AbstractBpsEventHandler

  • This QThread parameter has been removed from subscribe and unsubscribe. To subscribe or unsubscribe a given thread for BPS events you must perform the subscribe/unsubscribe call on the desired thread instead. The parameter defaulted to NULL previously, so this is a source-compatible change if a thread affinity was not previously desired.

    Old:

    AbstractBpsEventHandler::subscribe( int domain, QThread * thread ); 
    AbstractBpsEventHandler::unsubscribe( int domain, QThread * thread ); 

    New:

    AbstractBpsEventHandler::subscribe( int domain );
    AbstractBpsEventHandler::unsubscribe( int domain ); 

bb::MemoryInfo

  • Added methods:
    MemoryInfo::availableDeviceMemory();
    MemoryInfo::memoryUsedByCurrentProcess();
    MemoryInfo::totalDeviceMemory(); 

bb::PpsObject

  • Added method decodeWithFlags that includes the meta-information about the PPS channel, such as creation and deletion of the clients. This utilized the new PpsAttribute class.
  • The open() method has changed signature:

    Old:

    PpsObject::open( PpsObject::OpenMode mode ); 

    New:

    PpsObject::open( PpsOpenMode::Types mode );
  • The PpsObject::read( QByteArray& byteArray ) method has been removed. Use QByteArray read(bool * ok = 0) instead.

bb::Exception

  • This class has been removed, we do not support exceptions being thrown outside of library boundaries.

bb::Navigator

  • This class has been removed. Appropriate signals have been moved to bb::Application. (asleep, awake, etc).

bb::PpsAccessor

  • This class has been removed. The encode and decode functionality was added to bb::PpsObject instead.


Menu Service data property changes

Old (QML):

InvokeActionItem {       
    query {         
        mimeType: "image/png"         
        invokeActionId: "bb.action.OPEN"         
        invokeTargetId: "net.rim.test.app_handler1"       
        }       
        data: "data"       
        title: "Bound AB (open)"       
        ActionBar.placement: ActionBarPlacement.OnBar     
    }       
    

New (QML):

InvokeActionItem {       
    query {         
        mimeType: "image/png"         
        data: "Q-data"         
        invokeActionId: "bb.action.OPEN"         
        invokeTargetId: "net.rim.test.app_handler1"       
        }       
        title: "Bound AB (open)"       
        ActionBar.placement: ActionBarPlacement.OnBar     
    }

Multimedia API changes

The changes in multimedia APIs involved moving most of the enums out to separate classes.

In R6, to use the MediaPlayer API, all of the following libraries were required to be linked: lbbmultimedia, lmmrndclient, lstrm, and lasound.

For R9, the following library is sufficient: lbbmultimedia.

New Classes

  • bb::multimedia::AudioOutput: This enum class represents different outputs audio playback.
  • bb::multimedia::BufferStatus: This enum class represents the current buffer status of the media player.
  • bb::multimedia::MediaKey: This enum class represents the hardware media keys on a device.
  • bb::multimedia::MediaKeyWatcher: This class allows developers to be notified of hardware media key presses.
  • bb::multimedia::MediaState: This enum class represents the different media states.
  • bb::multimedia::RepeatMode: This enum class represents the various repeat modes.
  • bb::multimedia::VideoOutput: This enum class represents the various video output devices.

API Changes

  • bb::multimedia::AudioRecorder
    • enums definitions moved into standalone classes.

    • added a property to set an audio manager handle for recording to use.

    • duration and position properties are now unsigned integers, including related signals.

      Old API:

      AudioRecorder recorder;
      QObject::connect(&recorder, SIGNAL(durationChanged(int)), this, 
          SLOT(onDurationChanged(int)); 

      New API:

      AudioRecorder recorder;
      QObject::connect(&recorder, SIGNAL(durationChanged(unsigned int)), this, 
          SLOT(onDurationChanged(unsigned int)); 
    • recording, paused, prepared properties are replaced by a single mediaState property.

      Old API:

      AudioRecorder recorder; Q
      Object::connect(&recorder, SIGNAL(recording()), this, SLOT(onRecording()); 
      QObject::connect(&recorder, SIGNAL(preparedChanged(bool)), this, 
          SLOT(onPreparedChanged(bool)); 
      QObject::connect(&recorder, SIGNAL(paused()), this, SLOT(onPaused()); 
      QObject::connect(&recorder, SIGNAL(stopped()), this, SLOT(onStopped()); 

      New API:

      AudioRecorder recorder; 
      
      QObject::connect(&recorder, 
          SIGNAL(mediaStateChanged(bb::multimedia::MediaState::Type)),
          this, 
          SLOT(onMediaStateChanged(bb::multimedia::MediaState::Type)); 
        
      void MyClass::onMediaStateChanged(bb::multimedia::MediaState::Type mediaState) 
      {   
          if (mediaState == MediaState.Started) { // recording
         ...   
          } else if (mediaState == MediaState.Prepared) { // prepared   
          ...   
          } else if (mediaState == MediaState.Paused) { // paused   
          ...   
          } else if (mediaState == MediaState.Stopped) { // stopped   
          ...   
          } else if ... 
      } 
    • outputUri property has been renamed to outputUrl and changed type to QUrl from QString.
    • stop method has been renamed to reset.
  • bb::multimedia::MediaPlayer
    • enums definitions moved into standalone classes.
    • added a property to set an audio manager handle for playback to use.
    • added the ability to set the audio tuning type.
    • duration, position, track and track count properties are now unsigned integers, including related signals

      Old API:

      MediaPlayer player;
      
      QObject::connect(&player, 
          SIGNAL(durationChanged(int)), 
          this, 
          SLOT(onDurationChanged(int)); 

      New API:

      MediaPlayer player;
      
      QObject::connect(&player, 
          SIGNAL(durationChanged(unsigned int)), 
          this, 
          SLOT(onDurationChanged(unsigned int)); 
    • playing, paused, prepared properties are replaced by a single mediaState property.

      Old API:

      MediaPlayer player;
       
      QObject::connect(&player, SIGNAL(playing()), this, SLOT(onPlaying());
       
      QObject::connect(&player, SIGNAL(preparedChanged(bool)), this, 
          SLOT(onPreparedChanged(bool)); 
      QObject::connect(&player, SIGNAL(paused()), this, SLOT(onPaused()); 
      QObject::connect(&player, SIGNAL(stopped()), this, SLOT(onStopped()); 

      New API:

      MediaPlayer player; 
      
      QObject::connect(&player, 
          SIGNAL(mediaStateChanged(bb::multimedia::MediaState::Type)),
          this, 
          SLOT(onMediaStateChanged(bb::multimedia::MediaState::Type));   
      
      void MyClass::onMediaStateChanged(bb::multimedia::MediaState::Type mediaState) 
      {   
          if (mediaState == MediaState.Started) { // playing   
          ...   
          } else if (mediaState == MediaState.Prepared) { // prepared   
          ...   
          } else if (mediaState == MediaState.Paused) { // paused   
          ...   
          } else if (mediaState == MediaState.Stopped) { // stopped   
          ...   
          } else if ... 
      } 
    • added property to give the seek status of the current track.
    • added the ability to set the status update interval from the default of ~1s.
    • source property has been renamed to sourceUrl and changed type to QUrl from QString.
  • bb::multimedia::MetaData
    • added the Seekable value.
  • bb::multimedia::NowPlayingConnection
    • duration and position properties are now unsigned integers.
    • iconUri property renamed to iconUrl and and changed type to QUrl from QString.
  • bb::multimedia::SystemSound
    • renamed enum SystemSound::Sound to SystemSound::Type.
    • added SystemSound::CameraBurstEvent value.

Notifications API updates

The Notifications APIs were updated to allow for blocking and non-blocking requests. As a result, some porting is necessary for applications switching to R9.

Class changes and additions:

  • NotificationPopup is now NotificationDialog
  • NotificationErrors is now NotificationError
  • NotificationResult was added.

API Changes to NotificationDialog

  • The exec() function was added to allow for synchronous request. The show function should be used to make asynchronous requests. It is now possible to specify a custom sound for a notification dialog. This will override any settings set by the user, and as such should be used sparingly.
  • The signals emitted by the various dialog classes were modified.
    • Button selection previously resulted in buttonSelected. In the new API, the finished signal is emitted when a button is selected. The finished signal and the result function both provide access to the result of the request. If a button was selected, this can be checked against the value of this result. To get the button selected, the buttonSelection button can be used.

      Old API:

      NotificationPopup *dialog = new NotificationPopup; 
      QObject::connect(dialog, 
          SIGNAL(buttonSelected()), 
          this, 
          SLOT(onButtonSelected());
         
      /* slot */ void onButtonSelected() 
      {     
      // do something 
      } 

      New API:

      NotificationDialog *dialog = new NotificationDialog;
      QObject::connect(dialog, 
          SIGNAL(finished(bb::platform::NotificationResult::Type)), 
          this, 
          SLOT(onFinished(bb::platform::NotificationResult::Type)); 
      
      /* slot */ void onFinished(bb::platform::NotificationResult::Type r)
      {    
          if (r == bb::platform::NotificationResult::ButtonSelection) {        
              // do something    
          } else {        
              ...    
          }    
          ...
      } 
  • The error signal was removed. As with button selection, errors are communicated using the finished signal and result function. To get the error that occurred use the error function.

    Old API:

    NotificationPopup *dialog = new NotificationPopup; 
    
    QObject::connect(dialog, 
        SIGNAL(error(bb::popup::NotificationErrors::Type)), 
        this, 
        SLOT(onError(bb::platform::NotificationErrors:Type));   
    
    /* slot */ void onError(bb::platform::NotificationErrors:Type err) 
    {     
        // do something 
    } 

    New API:

    NotificationDialog *dialog = new NotificationDialog;
    
    QObject::connect(dialog, 
        SIGNAL(finished(bb::platform::NotificationResult::Type)), 
        this, 
        SLOT(onFinished(bb::platform::NotificationResult::Type)); 
    
    /* slot */ void onFinished(bb::platform::NotificationResult::Type r)
    {    
        if (r == bb::platform::NotificationResult::Error) {        
            // retrieve the error        
            NotificationError::Type err = dialog->error();        
            // do something    
        } else {        
            ...    
        }    
        ...
    } 

Payment Service API changes

  • The PaymentService API has been removed and replaced with the PaymentManager API.
  • PaymentServiceException has been removed. It was never actually being thrown by the PaymentService API.
  • Renamed CancelSubscriptionResponseInfo to CancelSubscriptionReply
  • Renamed DigitalGoodResponse to DigitalGoodReply
  • Renamed ExistingPurchasesResponseInfo to ExistingPurchasesReply
  • Renamed PriceResponseInfo to PriceReply
  • Renamed CheckStatusResponseInfo to SubscriptionStatusReply
  • Renamed PurchaseResponseInfo to PurchaseReply
  • Renamed SubscriptionTermsResponseInfo to SubscriptionTermsReply
  • Renamed ExistingPurchasesResponseInfo to ExistingPurchasesReply
  • Renamed DigitalGoodResponse to DigitalGoodReply
  • Renamed PriceResponseInfo to PriceReply
  • Added PaymentConnectionMode
  • Added PaymentReply
  • Added DigitalGoodState

System Toasts and Dialogs API changes

New classes:

  • bb::system::SystemUiInputMode

    This class represents the various input modes that can be used when entering text in a prompt dialog. This feature controls the appearance of text in the input field as well as the keyboard layout.

  • bb::system::SystemUiPosition

    This class represents the placement of the UI. Only SystemToast instances can be customized this way.

  • bb::system::SystemUiModality

    This class represents the whether the UI will be application modal or system modal.

  • bb::system::SystemUiError

    bb::system::SystemUiErrors is renamed to SystemUiError.

Compatible changes:

  • The exec() function was added to allow for synchronous request. The show function should be used to make asynchronous requests. The exec function returns SystemUiResult to indicate the result of the request.
  • Input mode is added for selecting the keyboard type.
  • Position is added for toasts.
  • Icons are supported.
  • SystemUiResult is added to include result of operations.
  • PPS connections are made only when needed.

Incompatible changes:

  • The SystemUiErrors enum is now SystemUiError.
  • The show() function (blocking) requests will no longer trigger a number of signals. Instead when the request is completed a finished() signal will be emitted with the result.
  • The exec() function (non-blocking) requests behave as show requests, but in addition they return the result.
  • The errors, buttons selected, text entered during a request will be available as functions. Previously this information was included

Additional Notes:

  • By default, we support the new service. To use the legacy service, applications can specify a new property called "legacy".

To specify the property, the applications can do the following (using legacy as an example):

In C++:

dialog.setProperty("legacy", true);

In QML:

SystemDialog {    ...    property bool legacy: true    ...}

This work around is temporary, they're designed so that in the future when they are no longer needed, libbbsystem will change only and apps will not be affected.


Text changes

Renamed size to fontSize

Old:

Label {
    text: "This was how it was done”
    textStyle {
        size: 100
    }
}

New:

Label {
    text: "meow meow"
    textStyle {
        fontSize: FontSize.Large
    }
}

And:

Label {
    text: "woof woof"
    textStyle {
        fontSizeValue: 100
    }
}

Renamed InputProperties to TextInputProperties

For clarity, InputProperties has been renamed to TextInputProperties.

New weight sizes in FontWeight

FontWeight.Light was replaced by 9 new weight sizes: W100, W200, etc up to, W900

W100, W200, W300 are considered Light.

fontStyleHint removed

The fontStyleHint property has been removed.

Changes to lineSpacing

The lineSpacing property has changed to lineHeight.

User Interface changes

Removed scaling of Action Icons from Context Menu, ActionBar, tab menu, and action menu

Icons used on the Context Menu, ActionBar, action menu, and tab menu will no longer scale to fill the icon space. Instead smaller icons will be centered in the space, while larger icons will be cropped to fit the space.

Changed behavior for controls that fill up a parent by default

Some controls previously had an internal fill functionality that made them, by default, take up all the space of the parent (and also basically asking their parent to fill its parent). The idea was that controls like the text area and the list don't have a natural default value but rather want to fill up the whole area parent. This worked really well when these controls were the only child (or in a DockLayout) but in a StackLayout it means that other controls did get less space.

These controls are now softer in their approach and will by default get their space after controls with a more specific size when competing for space in the StackLayout - similar to having the spaceQuota set to a positive value. One important change came with this behavioral change, namely that the StackLayout now honors the min and max size of its dynamic children (controls with spaceQuota set or with this new functionality).

There will be consequences to layouts in some cases, particularly if the application has workarounds to match the previous solution.

API changes to Sheets and Dialogs

  • Renamed CustomDialog to Dialog.
  • Sheet and Dialog inherits from an abstract class called AbstractDialog.
  • Changed the visible API to an opened property.
  • Added open() and close() slots. (replaces setVisible(bool)).
  • Added convenience signals, opened() and closed().

Property changes to DropDown, RadioGroup, SegmentedControl, TitleBar

Properties and methods with common functionality have the same names.

Property changes to ScrollView

The default ScrollMode in the ScrollView has been changed to Vertical scroll mode.

OverlapTouch class renamed to OverlapTouchPolicy

The OverlapTouch class has been renamed to OverlapTouchPolicy.

Changes to the OrientationHandler class

The signals, uiOrientationChanging() and uiOrientationChanged(), which were previously in OrientationHandler, have moved to the OrientationSupport class and changed names. The uiOrientationChanging() signal is now orientationAboutToChange(), and the uiOrientationChanged() signal is now orientationChanged().

PixelBufferData class replaced by ImageData

The PixelBufferData class has been replaced with the core ImageData class.

Momentics IDE changes

This section lists changes in the BlackBerry 10 Native SDK, that might affect your development.

Changes to Project templates

When you create a new BlackBerry Cascades C++ Project, the <app>.cpp and <app>.hpp classes take the name of the project itself. If you are porting an existing app to this release, you must make sure that you update the class names as well.

Changes to application permissions

  • The following permissions have been removed: access_led_control, set_audio_volume, and play_audio permissions

  • The permission read_geolocation has been deprecated. Use the permission access_location_services instead.

  • A number of new permissions are now available:
    • bbm_connect
    • access_pimdomain_calendars
    • access_pimdomain_contacts
    • access_pimdomain_messages
    • access_location_services
    • access_pimdomain_notebooks
    • access_sms_mms
    • run_when_backgrounded
  • You should no longer use the <action> element to specify application permissions. Use the <permissions> element instead. For example, if you previously specified app requests for a permission using <action>record_audio</action>, in BlackBerry 10, you should use <permissions>record_audio<permissions> instead.

Sending output to the console

In this release, the qDebug() and the console.log() functions do not work the same way as they did in previous releases. Previously, when you used one of these functions in your JavaScript or QML code, the function sent the debug information to the console, and you could view the information in the Console view in the Momentics IDE. Now, these functions do not send output to the console. Instead, these functions send debug information to the slogger2 log.

Workaround 1):  You can use the fprintf() function with stdout or stderr as the output stream to receive output directly to the console. Or, you can use a function similar to the following:

void myMessageOutput(QtMsgType type, const char* msg){
        fprintf(stdout, "%s\n", msg);
        fflush(stdout);
}

Then, you can register this handler function with qDebug by calling the qInstallMsgHandler() function in your main function after the default Application creation, similar to the following:

To see debug information that is output from qDebug(), you need to access the slogger2 logs as follows:

int main(int argc, char **argv)
{
    Application app(argc, argv);
    qInstallMsgHandler(myMessageOutput);
    ...
}

After this, qDebug() calls will be logged to the console.

Workaround 2):  To see debug information that is output from qDebug(), you can access the slogger2 logs as follows:

  1. In the Momentics IDE, in the Target Navigator view, right-click the device target. Click Launch SSH Session.
  2. In the terminal that appears, do one of the following:
    1. To view the current slogger2 logs, type slog2info.
    2. To view real-time output for the processes that are being debugged (for applications that are running in development mode), type slog2info -w.
    3. To view help information on slogger2, type slog2info -h.

You can also access the log files directly in the /tmp/slogger22 on the device and run these logs through slog2info at a later time.

Qt and Qt Mobility library changes

Cascades has been upgraded to use Qt 4.8.3. For more information, see the Qt 4.8.3 Release notes.

Qt 4.8.2 changes to Application mkspecs

Application projects that build with Cascades, or directly with Qt, have previously been specifying unsupported/blackberry-armv7le-g++. Application projects should move to specifying unsupported/blackberry-armv7le-qcc instead. The old unsupported/blackberry-armv7le-g++ files will be updated to contain the same content as the new files to avoid breaking applications immediately.

Although Qt 4.8.3 has started to list BlackBerry mkspecs as a supported platform, you still need to specify the mkspecs as noted here for beta 3.

Project Makefiles that invoke qmake must updated

Old:

Makefile: FORCE  
$(QMAKE) -spec unsupported/blackberry-armv7le-g++ -o arm/Makefile 
$(QMAKE_TARGET).pro CONFIG+=device  
$(QMAKE) -spec unsupported/blackberry-x86-g++ -o x86/Makefile 
$(QMAKE_TARGET).pro CONFIG+=simulator  

New:

Makefile: FORCE  
$(QMAKE) -spec unsupported/blackberry-armv7le-qcc -o arm/Makefile 
$(QMAKE_TARGET).pro CONFIG+=device  
$(QMAKE) -spec unsupported/blackberry-x86-qcc -o x86/Makefile 
$(QMAKE_TARGET).pro CONFIG+=simulator 

Changes to Qt plugin mkspecs

The change in mkspecs used by the qmake tool has an additional impact on the use of Qt plugin shared objects. These .so files are loaded by the Qt library to provide device specific functionality. The set of mkspecs used to build the plugins must match the mkspecs used to build the Qt libraries that load the plugins. Thus, a device which is running a Trunk-preview bundle, with the qcc mkspecs will only load plugins that were created with the NDK preview tools.

Conversely, a device which is running a Trunk bundle, with the g++ mkspecs will only load plugins that were created with the matching NDK tools.

If you bundle libraries with your application, you must make sure that they are complied with the mkspecs matching the target device.

Using Qt Sensors and Qt MultimediaKit components

You can use the Qt Sensors and Qt MultimediaKit components by adding to the CONFIG line and including a MOBILITY line in the Qt project file (also known as the .pro file). To use the Qt Sensors subset, the following change can be made to the project .pro file.

Old:

CONFIG += qt warn_on debug_and_release cascades 

New:

CONFIG += qt warn_on debug_and_release cascades mobility  
MOBILITY += sensors

Use of the Qt MultimediaKit component is similar except that instead of sensors, the MOBILITY value is augmented with multimedia. These changes are only needed if the Qt Sensors or Qt MultimediaKit components are being used.

Last modified: 2015-03-31



Got questions about leaving a comment? Get answers from our Disqus FAQ.

comments powered by Disqus