Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Native Development

Reply
Contributor
Posts: 31
Registered: ‎09-25-2012
My Device: N/A
My Carrier: Rogers
Accepted Solution

Destructor of C++ class not called on application close

[ Edited ]

I starting to play around with cascade and C++ development but im having an issue where I can bind my class to the qml and use it within but on application close the something about my class hangs the application and its icon in the emulator goes a little transparent and can no longer be clicked.

This is the call to add it to the qml

 

 

File: Applicationui.cpp

 

ApplicationUI::ApplicationUI(bb::cascades::Application *app)
: QObject(app)
{
// create scene document from main.qml asset
// set parent to created document to ensure it exists for the whole application lifetime
QmlDocument *qml = QmlDocument::create("asset:///main.qml").parent(this);

 

//My class
GpsCommunicator* gps = new GpsCommunicator();

 

//Add the Class
qml->setContextProperty("_gps",gps);

 

// create root object for the UI
AbstractPane *root = qml->createRootObject<AbstractPane>();

 

// set created root object as a scene
app->setScene(root);

}

 

Here is the class.hpp

 

class GpsCommunicator : public QObject {

Q_OBJECT

Q_PROPERTY(double latitude READ latitude)
Q_PROPERTY(double longitude READ longitude)
Q_PROPERTY(double accuracy READ accuracy)
Q_PROPERTY(double altitude READ altitude)
Q_PROPERTY(double heading READ heading)
Q_PROPERTY(double satellites READ satellites)
Q_PROPERTY(double speed READ speed)

Q_PROPERTY(bool isRegistered READ isRegistered)
Q_PROPERTY(bool isAltitudeValid READ isAltitudeValid)
Q_PROPERTY(bool isAccuracyValid READ isAccuracyValid)
Q_PROPERTY(bool isHeadingValid READ isHeadingValid)
Q_PROPERTY(bool isSpeedValid READ isSpeedValid)

public:
GpsCommunicator(QObject *parent = 0);
virtual ~GpsCommunicator();

//Latitude Property
double latitude();

//Latitude Property
double longitude();

//Accuracy Property
double accuracy();
bool isAccuracyValid();

//Altitude Property
double altitude();
bool isAltitudeValid();

//Heading Property
double heading();
bool isHeadingValid();

//Speed Property
double speed();
bool isSpeedValid();

//Number of Satellite Property
double satellites();

//Registered successfully to geolocation events
bool isRegistered();

Q_INVOKABLE void StartPollTimer(int i = 0);
Q_INVOKABLE void StopPollTimer();

signals:

private:

//Bool to track if this class is registered to receive geo-location events
bool m_isRegistered;

double m_latitude;
double m_longitude;
double m_accuracy;
bool m_accuracy_valid;
double m_altitude;
bool m_altitude_valid;
double m_altitude_accuracy;
bool m_altitude_accuracy_valid;
double m_heading;
bool m_heading_valid;
double m_speed;
bool m_speed_valid;
double m_num_satellites;
bool m_num_satellites_valid;

void InitializeGps();
void InitializeCommunicator();

//Poll timer
QTimer *pollTimer;

 

public slots:

void CheckForGPSEvent();

};

 

Here is the .cpp for it 

 

GpsCommunicator::GpsCommunicator(QObject *parent): QObject(parent) {
//Start up sequence
this->InitializeCommunicator();
this->InitializeGps();
}

void GpsCommunicator::InitializeCommunicator() {
this->m_isRegistered = false;
}

GpsCommunicator::~GpsCommunicator() {
// TODO Auto-generated destructor stub
this->StopPollTimer();
delete this->pollTimer;
geolocation_stop_events(0);
bps_shutdown();
}

double GpsCommunicator::latitude() {
return this->m_latitude;
}

double GpsCommunicator::speed() {
return this->m_speed;
}

double GpsCommunicator::altitude() {
return this->m_altitude;
}

double GpsCommunicator::longitude() {
return this->m_longitude;
}

double GpsCommunicator::accuracy() {
return this->m_accuracy;
}

double GpsCommunicator::heading() {
return this->m_heading;
}

double GpsCommunicator::satellites() {
return this->m_num_satellites;
}

bool GpsCommunicator::isRegistered(){
return this->m_isRegistered;
}

bool GpsCommunicator::isSpeedValid() {
return this->m_speed_valid;
}

bool GpsCommunicator::isAccuracyValid() {
return this->m_accuracy_valid;
}

bool GpsCommunicator::isAltitudeValid() {
return this->m_altitude_valid;
}

bool GpsCommunicator::isHeadingValid() {
return this->m_heading_valid;
}

void GpsCommunicator::StartPollTimer(int i) {
this->pollTimer->start(i);
}

void GpsCommunicator::StopPollTimer() {
this->pollTimer->stop();
}

void GpsCommunicator::InitializeGps() {

if( bps_initialize() != BPS_FAILURE)
{
if ( geolocation_request_events( 0 ) != BPS_SUCCESS )
{
//Report that the initialize failed
this->m_isRegistered = false;
//emit this->registeredChanged(this->m_isRegistered);
}
else
{
geolocation_set_period(1);

//Update that the communicator is now registered and emit the signal
this->m_isRegistered = true;
//emit this->registeredChanged(this->m_isRegistered);

//Create the timer instance
this->pollTimer = new QTimer();

//Connect it to the polling function
this->connect(this->pollTimer, SIGNAL(timeout()), this, SLOT(CheckForGPSEvent()));
this->StartPollTimer(100);
}
}
}

void GpsCommunicator::CheckForGPSEvent() {

bps_event_t *event = NULL;
bps_get_event(&event, 100); // -1 means that the function waits
// for an event before returning
if (event) {

if (bps_event_get_domain(event) == geolocation_get_domain()) {

if (event == NULL || bps_event_get_code(event) != GEOLOCATION_INFO) {
return;
}

// TODO: change this so the emit is only called if the information is new

this->m_latitude = geolocation_event_get_latitude(event);
//emit this->latitudeChanged(this->m_latitude);

this->m_longitude = geolocation_event_get_longitude(event);
//emit this->longitudeChanged(this->m_longitude);

this->m_accuracy = geolocation_event_get_accuracy(event);
//emit this->accuracyChanged(this->m_accuracy);

this->m_altitude = geolocation_event_get_altitude(event);
//emit this->altitudeChanged(this->m_altitude);

this->m_altitude_valid = geolocation_event_is_altitude_valid(event);

this->m_altitude_accuracy = geolocation_event_get_altitude_accuracy(event);

this->m_altitude_accuracy_valid = geolocation_event_is_altitude_accuracy_valid(event);

this->m_heading = geolocation_event_get_heading(event);
//emit this->headingChanged(this->m_heading);

this->m_heading_valid = geolocation_event_is_heading_valid(event);

this->m_speed = geolocation_event_get_speed(event);
//emit this->speedChanged(this->m_speed);

this->m_speed_valid = geolocation_event_is_speed_valid(event);

this->m_num_satellites = geolocation_event_get_num_satellites_used(event);
//emit this->satellitesChanged(this->m_num_satellites);

this->m_num_satellites_valid = geolocation_event_is_num_satellites_valid(event);
}
}

return;
}

I was checking to see if the deconstructor was being called but it does not appear to be. So I think it might be the QTimer not being cleaned up but I also don't know how I would get it to be called on close since I thought once i registered with the qml my QObject class would be deconstructed with all the other resources in some order.

 

 

 

Thanks in advance for any help

Developer
Posts: 1,524
Registered: ‎12-18-2012
My Device: Z30, Z10 LE, DevAlpha C, PlayBook

Re: Destructor of C++ class not called on application close

QML won't destruct 'gps' object. You're exposing it to QML, but C++ is still responsible for it's lifetime.

Easiest method of destroying it is setting it's parent to ApplicationUI class instance.

 

In Qt there's parent-child relationship mechanism which simplifies object destruction. When parent object is destroyed it destroys all children automatically.

 

GpsCommunicator* gps = new GpsCommunicator(this); // this will set GpsCommunicator's parent to ApplicationUI instance

 

You can do the same inside of GpsCommunicator class as well:

this->pollTimer = new QTimer(this); // so the timer is destroyed when GpsCommunicator is destroyed

This way it's not neccessary to delete pollTimer in destructor. Btw, on destruction it's automatically stopped, so stopping it manually is not necessary.

 

Destructor is still needed for C-style APIs though (bps_* etc).

 


Andrey Fidrya, @zmeyc on twitter
Contributor
Posts: 31
Registered: ‎09-25-2012
My Device: N/A
My Carrier: Rogers

Re: Destructor of C++ class not called on application close

Thanks for the quick reply. I have made the changes but the application icon still goes transparent on close. I am also not hitting the breakpoints in the dtor of the GpsCommunicator class (Momentics IDE). Is there something else that could be going wrong. The set-up code is all base from the cascade project for application with ui adaptability support.

-J
Developer
Posts: 115
Registered: ‎10-22-2012
My Device: Developer
My Carrier: Mobifone

Re: Destructor of C++ class not called on application close

In your

ApplicationUI::ApplicationUI(bb::cascades::Application *app)

 Change

GpsCommunicator* gps = new GpsCommunicator();

 to

GpsCommunicator* gps = new GpsCommunicator(this);

 may work



Like my answer if it's helpful. Mark as answer if it help you solve the problem.
Contributor
Posts: 31
Registered: ‎09-25-2012
My Device: N/A
My Carrier: Rogers

Re: Destructor of C++ class not called on application close

[ Edited ]

Zmey had already suggested this solution I have it implemented same with the QTimer taking in my GpsCommunicator as its parent, but i still don't see my dtor being called in the GpsCommunicator.

Developer
Posts: 115
Registered: ‎10-22-2012
My Device: Developer
My Carrier: Mobifone

Re: Destructor of C++ class not called on application close

If you make the GpsCommunicator as parent of pollTimer, when GpsCommunicator is destroyed, it will destroy pollTimer too, but when pollTimer is destroyed, GpsCommunicator isn't destroyed



Like my answer if it's helpful. Mark as answer if it help you solve the problem.
Contributor
Posts: 31
Registered: ‎09-25-2012
My Device: N/A
My Carrier: Rogers

Re: Destructor of C++ class not called on application close

[ Edited ]

I do understand that this should happen, but once I add the ApplicationUI as my GpsCommunicator parent and I close the application on the emulator for some reason the dtor is never called on my class or the QTimer which leaves it open and the phone emulator puts my app into some form of blocked state so it can not be launched again.

 

[UPDATE] It appears that the timer and hte application work as long as i dont make a call to bps_get_event once i make that call the application on close will go into the blocked state. Not sure whats going.

Contributor
Posts: 31
Registered: ‎09-25-2012
My Device: N/A
My Carrier: Rogers

Re: Destructor of C++ class not called on application close

After using qDebug() and attaching to the simulators slogger using slog2info -w I notice that my application is actually not being ended the timer still ticks and it fishes out gps events from the bps_get_event. Debug on what i thought was a close is as follows.


May 13 13:55:53.749 com.example.Test1.testDev_ample_Test1de2daa8e.7835795..0 default 900
0 GOT GPS EVENT
May 13 13:55:53.749 com.example.Test1.testDev_ample_Test1de2daa8e.7835795..0 default 900
0 Sent signal that new data is available
May 13 13:55:54.404 com.example.Test1.testDev_ample_Test1de2daa8e.7835795..0 default
0 NavigatorEventHandler::Received - BPS - NAVIGATOR_WINDOW_STATE - NAVIGATOR_WINDOW_INVISIBLE
May 13 13:55:54.404 com.example.Test1.testDev_ample_Test1de2daa8e.7835795..0 default
0 NavigatorEventHandler::new WindowStateInternal INVISIBLE
May 13 13:55:54.404 com.example.Test1.testDev_ample_Test1de2daa8e.7835795..0 default
0 EventManager:Smiley Tonguerocessed 1 events over the last 3687ms or 4 processEvents() calls.
May 13 13:55:54.404 com.example.Test1.testDev_ample_Test1de2daa8e.7835795..0 default
0 QNXApplicationEngineImpl::Application window not visible, pausing rendering
May 13 13:55:55.749 com.example.Test1.testDev_ample_Test1de2daa8e.7835795..0 default 900
0 GOT GPS EVENT
May 13 13:55:55.749 com.example.Test1.testDev_ample_Test1de2daa8e.7835795..0 default 900
0 Sent signal that new data is available

when the window state is set to not visible is when I hit the close button on the application from the application view in the currently running view of the OS (via slide up from bottom Bessel of the device).
Retired
Posts: 47
Registered: ‎04-19-2013
My Device: I love them all!
My Carrier: Carriers rock!

Re: Destructor of C++ class not called on application close

Don't call bps_get_event from within a Cascades application as you could steal events from the main event loop.  Instead implement AbstractBpsEventHandler to have the BPS events delivered on your event thread.

Highlighted
Contributor
Posts: 31
Registered: ‎09-25-2012
My Device: N/A
My Carrier: Rogers

Re: Destructor of C++ class not called on application close

you sir a god amongst men, thank you