Ejemplo n.º 1
0
class ModRana(object):
    """
    core modRana functionality
    """
    def __init__(self, modrana, gui):
        self.modrana = modrana
        self.gui = gui
        self.modrana.watch("mode", self._modeChangedCB)
        self.modrana.watch("theme", self._themeChangedCB)
        self._theme = Theme(gui)

    # mode

    def _getMode(self):
        return self.modrana.get('mode', "car")

    def _setMode(self, mode):
        self.modrana.set('mode', mode)

    modeChanged = signal.Signal()

    def _modeChangedCB(self, *args):
        """notify when the mode key changes in options"""
        self.modeChanged()
Ejemplo n.º 2
0
class Theme(object):
    """modRana theme handling"""
    def __init__(self, gui):
        self.gui = gui
        # connect to the first time signal
        self.gui.firstTimeSignal.connect(self._firstTimeCB)
        self.themeModule = None
        self._themeDict = {}
        self.colors = None
        self.modrana = self.gui.modrana
        self.themeChanged.connect(self._notifyQMLCB)

    themeChanged = signal.Signal()

    def _firstTimeCB(self):
        # we need the theme module
        self.themeModule = self.gui.m.get('theme')
        theme = self.themeModule.theme
        # reload the theme dict so that
        # the dict is up to date and
        # then trigger the changed signal
        # and give it the current theme dict
        self.themeChanged(self._reloadTheme(theme))
        # connect to the core theme-modules theme-changed signal
        self.themeModule.themeChanged.connect(self._themeChangedCB)

    def _themeChangedCB(self, newTheme):
        """ Callback from the core theme module
        - reload theme and trigger our own themeChanged signal

        :param newTheme: new theme from the core theme module
        :type newTheme: Theme
        """
        self.themeChanged(self._reloadTheme(newTheme))

    def _notifyQMLCB(self, newTheme):
        """ Notify the QML context that the modRana theme changed

        :param newTheme: the new theme
        :type newTheme: dict
        """
        pyotherside.send("themeChanged", newTheme)

    @property
    def themeId(self):
        return self._themeDict.get("id")

    @themeId.setter
    def themeId(self, themeId):
        self.modrana.set('theme', themeId)

    @property
    def theme(self):
        return self._themeDict

    def _reloadTheme(self, theme):
        """Recreate the theme dict from the new theme object

        :param theme: new modRana Theme object instance
        :type theme: Theme
        """
        themeDict = {
            "id": theme.id,
            "name": theme.name,
            "color": {
                "main_fill":
                theme.getColor("main_fill", "#92aaf3"),
                "main_highlight_fill":
                theme.getColor("main_highlight_fill", "#f5f5f5"),
                "icon_grid_toggled":
                theme.getColor("icon_grid_toggled", "#c6d1f3"),
                "icon_button_normal":
                theme.getColor("icon_button_normal", "#c6d1f3"),
                "icon_button_toggled":
                theme.getColor("icon_button_toggled", "#3c60fa"),
                "icon_button_text":
                theme.getColor("icon_button_text", "black"),
                "page_background":
                theme.getColor("page_background", "black"),
                "list_view_background":
                theme.getColor("list_view_background", "#d2d2d2d"),
                "page_header_text":
                theme.getColor("page_header_text", "black"),
            }
        }
        self._themeDict = themeDict
        return themeDict
Ejemplo n.º 3
0
class _Search(object):
    _addressSignal = signal.Signal()

    changed = signal.Signal()

    test = signal.Signal()

    def __init__(self, gui):
        self.gui = gui
        self._addressSearchResults = None
        self._addressSearchStatus = "Searching..."
        self._addressSearchInProgress = False
        self._addressSearchThreadName = None
        self._localSearchResults = None
        self._wikipediaSearchResults = None
        self._routeSearchResults = None
        self._POIDBSearchResults = None
        # why are wee keeping our own dictionary of wrapped
        # objects and not just returning a newly wrapped object on demand ?
        # -> because PySide (1.1.1) segfaults if we don't hold any reference
        # on the object returned :)

        # register the thread status changed callback
        threadMgr.threadStatusChanged.connect(self._threadStatusCB)

    def _threadStatusCB(self, threadName, threadStatus):
        if threadName == self._addressSearchThreadName:
            self._addressSearchStatus = threadStatus
            self._addressSignal()

    def address(self, address):
        """Trigger an asynchronous address search for the given term

        :param address: address search query
        :type address: str
        """
        online = self.gui.m.get("onlineServices", None)
        if online:
            self._addressSearchThreadName = online.geocodeAsync(
                address, self._addressSearchCB)
        self._addressSearchInProgress = True
        self._addressSignal()

    def addressCancel(self):
        """Cancel the asynchronous address search"""
        threadMgr.cancel_thread(self._addressSearchThreadName)
        self._addressSearchInProgress = False
        self._addressSearchStatus = "Searching..."
        self._addressSignal()

    def _addressSearchCB(self, results):
        """Replace old address search results (if any) with
        new (wrapped) results

        :param results: address search results
        :type results: list
        """
        #self.gui._addressSearchListModel.set_objects(
        #    wrapList(results, wrappers.PointWrapper)
        #)

        self._addressSearchInProgress = False
        self._addressSignal.emit()
Ejemplo n.º 4
0
    def __init__(self, *args, **kwargs):
        GUIModule.__init__(self, *args, **kwargs)

        # some constants
        self.msLongPress = 400
        self.centeringDisableThreshold = 2048
        self.firstTimeSignal = signal.Signal()
        size = (800, 480)  # initial window size
        self._screen_size = None

        # positioning related
        self._pythonPositioning = False

        # we handle notifications by forwarding them to the QML context
        self.modrana.notificationTriggered.connect(
            self._dispatchNotificationCB)

        # register exit handler
        #pyotherside.atexit(self._shutdown)
        # FIXME: for some reason the exit handler is never
        # called on Sailfish OS, so we use a onDestruction
        # handler on the QML side to trigger shutdown

        # window state
        self._fullscreen = False

        # get screen resolution
        # TODO: implement this
        #screenWH = self.getScreenWH()
        #self.log.debug(" @ screen size: %dx%d" % screenWH)
        #if self.highDPI:
        #    self.log.debug(" @ high DPI")
        #else:
        #    self.log.debug(" @ normal DPI")

        # NOTE: what about multi-display devices ? :)

        ## add image providers

        self._imageProviders = {
            "icon": IconImageProvider(self),
            "tile": TileImageProvider(self),
        }

        # log what version of PyOtherSide we are using
        # - we log this without prefix as this shows up early
        #   during startup, so it looks nicer that way :-)
        no_prefix_log.info("using PyOtherSide %s", pyotherside.version)

        ## register the actual callback, that
        ## will call the appropriate provider base on
        ## image id prefix
        pyotherside.set_image_provider(self._selectImageProviderCB)

        # initialize theming
        self._theme = Theme(self)

        ## make constants accessible
        #self.constants = self.getConstants()
        #rc.setContextProperty("C", self.constants)

        ## connect to the close event
        #self.window.closeEvent = self._qtWindowClosed
        ##self.window.show()

        self._notificationQueue = []

        # provides easy access to modRana modules from QML
        self.modules = Modules(self)

        # search functionality for the QML context
        self.search = Search(self)

        # POI handling for the QML context
        self.POI = POI(self)

        # make the log manager easily accessible
        self.log_manager = modrana_log.log_manager

        # log for log messages from the QML context
        self.qml_log = qml_log
        # queue a notification to QML context that
        # a Python loggers is available
        pyotherside.send("loggerAvailable")

        # tracklogs
        self.tracklogs = Tracklogs(self)

        #routing
        self.routing = Routing(self)

        # turn by turn navigation
        self.navigation = Navigation(self)
Ejemplo n.º 5
0
    def __init__(self, *args, **kwargs):
        GUIModule.__init__(self, *args, **kwargs)

        # some constants
        self.msLongPress = 400
        self.centeringDisableThreshold = 2048
        self.firstTimeSignal = signal.Signal()
        size = (800, 480)  # initial window size

        # window state
        self.fullscreen = False

        # Create Qt application and the QDeclarative view
        class ModifiedQDeclarativeView(QDeclarativeView):
            def __init__(self, modrana):
                QDeclarativeView.__init__(self)
                self.modrana = modrana

            def closeEvent(self, event):
                print("shutting down")
                self.modrana.shutdown()

        self.app = QApplication(sys.argv)
        startDragDistance = self.modrana.dmod.getStartDragDistance()
        if startDragDistance:
            self.app.setStartDragDistance(startDragDistance)

        # get screen resolution
        screenWH = self.getScreenWH()
        print(" @ screen size: %dx%d" % screenWH)
        if self.highDPI:
            print(" @ high DPI")
        else:
            print(" @ normal DPI")

        # NOTE: what about multi-display devices ? :)

        # register custom modRana types
        # NOTE: custom types need to be registered AFTER
        # QApplication is created but BEFORE QDeclarativeView
        # is instantiated, or else horrible breakage occurs :)
        qmlRegisterType(drawing.PieChart, 'Charts', 1, 0, 'PieChart')
        qmlRegisterType(drawing.PieSlice, "Charts", 1, 0, "PieSlice")

        # m-declarative stuff implemented in Python
        qmlRegisterType(Screen, "mpBackend", 1, 0, "Screen")
        qmlRegisterType(Snapshot, "mpBackend", 1, 0, "Snapshot")

        self.view = ModifiedQDeclarativeView(self.modrana)
        self.window = QMainWindow()
        self.window.setWindowTitle("modRana")
        self.window.resize(*size)
        self.window.setCentralWidget(self.view)
        self.view.setResizeMode(QDeclarativeView.SizeRootObjectToView)
        #    self.view.setResizeMode(QDeclarativeView.SizeViewToRootObject)

        # add image providers
        self.iconProvider = IconImageProvider(self)
        self.view.engine().addImageProvider("icons", self.iconProvider)
        # add tiles provider
        self.tilesProvider = TileImageProvider(self)
        self.view.engine().addImageProvider("tiles", self.tilesProvider)

        rc = self.view.rootContext()
        # make core modRana functionality accessible from QML
        modRanaCore = ModRana(self.modrana, self)
        rc.setContextProperty("modrana", modRanaCore)
        # make options accessible from QML
        options = Options(self.modrana)
        rc.setContextProperty("options", options)
        # make GPS accessible from QML
        gps = GPSDataWrapper(self.modrana, self)
        rc.setContextProperty("gps", gps)
        # make the platform accessible from QML
        platform = Platform(self.modrana)
        rc.setContextProperty("platform", platform)
        # make the modules accessible from QML
        modules = Modules(self.modrana)
        rc.setContextProperty("modules", modules)
        # make tile loading accessible from QML
        tiles = MapTiles(self)
        rc.setContextProperty("mapTiles", tiles)
        # make map layers accessible from QML
        layers = MapLayers(self)
        rc.setContextProperty("mapLayers", layers)
        # make search accessible from QML
        search = Search(self)
        rc.setContextProperty("search", search)

        # make constants accessible
        self.constants = self.getConstants()
        rc.setContextProperty("C", self.constants)

        # connect to the close event
        self.window.closeEvent = self._qtWindowClosed
        #self.window.show()

        self.rootObject = None

        self._location = None  # location module
        self._mapTiles = None  # map tiles module
        self._mapLayers = None  # map tiles module

        self._notificationQueue = []

        # list models
        self._addressSearchListModel = None
        self._layersListModel = None