Reply
Thread Tools
Posts: 432 | Thanked: 645 times | Joined on Mar 2009
#11
Hi,

just a small hint. Since the thread started there have been some news. So you could have a look at the QtMobility project for getting the location as well. There is a first tech preview in extras-devel. It is not ready yet, but definitely worth to have a look!

Daniel
 
Posts: 5 | Thanked: 20 times | Joined on Dec 2009
#12
Originally Posted by kimitake View Post
tmsha,
you can build the sample as follow.
gcc main.c `pkg-config --cflags --libs gtk+-2.0 hildon-1 liblocation`
I just compiled the example as you described and copied over to the device and run. it compiles and runs without any errors but the program never gets a fix location. is this example working? do I need to do something else to give permission for location services?

thanks
 
Posts: 2 | Thanked: 5 times | Joined on Apr 2010 @ Pori, Finland
#13
Originally Posted by brink View Post
Well, I figured it out also. I guess there was no documentation because it was so simple.

Liblocation (and any glib libs, as far as I understood) will run fine inside the Qt event loop. You basically just use the library as you would in a Gtk application.
Hi

I am trying to use location API in a very simple Python QT application but it ends up with a segmentation fault. The code is actually modified from the version using gobject main loop.

It seems that the code crashes (on N900) when I call control.start(). The code can not be obviously tested on scratchbox because there is no GPS available. Any ideas what is wrong?

-- JariM

Code:
import sys
import pdb
from PyQt4 import QtCore, QtGui
import location


def on_error(control, error, data):
    print "location error: %d... quitting" % error
    data.quit()

def on_changed(device, data):
    if not device:
        return
    if device.fix:
        if device.fix[1] & location.GPS_DEVICE_LATLONG_SET:
            print "lat = %f, long = %f" % device.fix[4:6]
            data.stop()

def on_stop(control, data):
    print "quitting"
    data.quit()

def start_location(data):
    data.start()
    return False
    
    
#loop = gobject.MainLoop()

app = QtGui.QApplication(sys.argv)
myWindow = QtGui.QMainWindow()

control = location.GPSDControl.get_default()
device = location.GPSDevice()
control.set_properties(preferred_method=location.METHOD_USER_SELECTED, preferred_interval=location.INTERVAL_DEFAULT)

control.connect("error-verbose", on_error, app)
device.connect("changed", on_changed, control)
control.connect("gpsd-stopped", on_stop, app)
pdb.set_trace()
print device.status

control.start()
#gobject.idle_add(start_location, control)
#loop.run()


myWindow.show()

# Now we can start the UI.
sys.exit(app.exec_())
 
Posts: 3 | Thanked: 2 times | Joined on Apr 2010
#14
@multisil: Have you been able to fix your problem with the segmentation fault?

Greetings,
bartenst
 
Posts: 2 | Thanked: 5 times | Joined on Apr 2010 @ Pori, Finland
#15
Originally Posted by bartenst View Post
@multisil: Have you been able to fix your problem with the segmentation fault?

Greetings,
bartenst
Yes. I have a solution for having QT Main Loop for UI and GTK+ loop for GPS device. The solution is to create a separate thread for GPS (as a QThread). In your main app you have to initialize the thread, but not actually start it before your QT main loop has started. So you have to post a QTimer event to your QT Main Loop to start the GTK+ loop. Also, you have to take care of closing the thread when your app is closing, so you have to implement a method for this in you main app class.

So my main.py would be (I suppose you have a simple QT Designer created UI file my_ui.py with one button (myBtn) and text label (msgLabel)):

Code:
import sys
from my_ui import *
from GPSConnection import *

class myWindow(QtGui.QMainWindow):

#
# Constructor
#
    def __init__(self, parent=None):
      super(myWindow, self).__init__()

#
#  UI myBtn button click handler.
#     
    def myBtnClicked(self):
        if self.gps.fix:
            msg = "Lat: " + str(self.gps.lat) + " Lon: " + str(self.gps.lon)
            self.ui.msgLabel.setText(QtGui.QApplication.translate("MainWindow", msg, None, QtGui.QApplication.UnicodeUTF8))

#
# Application is about to close. We have to clean up the GPS related things, namely
# close the GPS device and quit the GPSConnection thread.
#
    def closingApp(self):
        print "Closing..."
        if self.gps.running:
            self.gps.control.stop()
            self.gps.loop.quit()
       
#
# Handler for a timer event that should happen when the QT Main Loop has started.
# We can safely start the GPSConnection thread, that has its own GTK+ event loop.
#      	
    def singleUpdate(self):
        print "Start timer"
        if self.gps.running == False:
            self.gps.run()

#****************************************************************#
#* MAIN APPLICATION                                             *#
#****************************************************************#

#       
# We instantiate a QApplication
#
app = QtGui.QApplication(sys.argv)
MainWindow = myWindow()
MainWindow.ui = Ui_MainWindow()
MainWindow.ui.setupUi(MainWindow)
MainWindow.gps = GPSConnection(app)
MainWindow.show()

#
# Timer for launching the GPS when app starts. The GPSConnection can not be started
# before the QT Main Loop, so this ensures that it starts after we have started
# processing events in the QT Main Loop. GPSConnection class uses GTK+ main loop
# and that is just ok, since we are running GPSConnection in its own thread.
#
gpsLaunchTimer = QtCore.QTimer()
gpsLaunchTimer.singleShot(1000, MainWindow.singleUpdate)

#
# Signals that enable us to catch the event when app is closing 
# so we can close the GPS device and thread. We propably do not need both.
#
QtCore.QObject.connect(app,QtCore.SIGNAL("aboutToQuit()"), MainWindow.closingApp)
#QtCore.QObject.connect(app,QtCore.SIGNAL("lastWindowClosed()"), MainWindow.closingApp)

# 
# Now we can start the UI & QT Main Loop.
#
sys.exit(app.exec_())
and GPSConnection class in GPSConnection.py:

Code:
import os
import location
from PyQt4 import QtCore
import gobject

# This class implements a GPS connection class to the gps device.
# The class can be safely used in QT applications, because this
# class is supposed to be running in its own thread. Also, the
# class implements its own GTK+ event loop.
#
# The GPSConnection thread must not be started before the QT Main
# loop. Instead, use QTimer to generate a start event for the 
# GPSConnection thread. This way, the even is prosessed
# in the QT Main Loop after the loop has been started.
#
# Also, you should implement closingApp method in your QT main loop 
# (in you main window QObject) that takes care of shutting down the 
# GPS device and stops the GPSConnection thread.
#
class GPSConnection (QtCore.QThread) :

#
# Constructor
#
    def __init__(self, app, parent=None):
        super(GPSConnection, self).__init__()
        self.control = location.GPSDControl.get_default()
        self.GPSDevice = location.GPSDevice()
        self.control.set_properties(preferred_method=location.METHOD_USER_SELECTED, preferred_interval=location.INTERVAL_DEFAULT)
        self.GPSDevice.connect("changed", self.onChanged, self.control)
        self.control.connect("error-verbose", self.onError, self)
        self.control.connect("gpsd-stopped", self.onStop, self.control)
        self.lat = 0.0
        self.lon = 0.0
        self.fix = False
        self.running = False
        self.app = app
        self.loop = None
 
#
# GPS error callback handler
#
    def onError (self, control, error, data):
        print "location error: %d... quitting" % error
        self.running = False
        
        if error == location.ERROR_USER_REJECTED_DIALOG:
            print "User didn't enable requested methods"
        elif error == location.ERROR_USER_REJECTED_SETTINGS:
            print "User changed settings, which disabled location"
        elif error == location.ERROR_BT_GPS_NOT_AVAILABLE:
            print "Problems with BT GPS"
        elif error == location.ERROR_METHOD_NOT_ALLOWED_IN_OFFLINE_MODE:
            print "Requested method is not allowed in offline mode"
        elif error == location.ERROR_SYSTEM:
            print "System error"
    
#
# Handler for stopping the GPS device.
#
    def onStop (self, control, data):
        if self.running:
            self.running = False
            print "In onStop method"
            data.stop()

#
# Callback handler for the event when location fix has changed.
#    
    def onChanged (self, device, data):
        print "In inChanged method"
        if not device:
            return
        if device.fix:
            if device.fix[1] & location.GPS_DEVICE_LATLONG_SET:
                self.lat = device.fix[4]
                self.lon = device.fix[5]
                self.fix = True
                    
#
# Start the GPS device.
#
    def start_location(self, data):
        data.start() 
        return False

#
# Start the GTK+ main loop. The loop initializes the start_location callback which actually
# runs the GPS device.
#
    def run(self):
        print "In run"
        self.running = True
        self.loop = gobject.MainLoop()
        gobject.idle_add(self.start_location, self.control)
        self.loop.run()
Hope this helps!
 

The Following 5 Users Say Thank You to multisil For This Useful Post:
Posts: 3 | Thanked: 2 times | Joined on Apr 2010
#16
@multisil: Thanks a lot for your posting - it helps me a lot!
 
Posts: 37 | Thanked: 21 times | Joined on May 2010
#17
@multisil: Thanks, it works... but the Segmentation fault comes anyway

I have taken your GPSConnection class unchanged, and initialised it in the way you have done it in the second file. My stripped down application window has a single QListWidget and opens QMessageBox on demand. The application works flawlessly unless I allow start of GPSConnection thread, only start, NO data manipulations. Within a minute or two of using QListWidget and QMessageBox there comes SIGSEGV.

Sorry it does not work in my case, but thanks anyway for the idea and sort of working example.
 
Reply


 
Forum Jump


All times are GMT. The time now is 14:08.