Example #1
0
 def __init__(self):
     super(CalendarController, self).__init__()
     self.__browserID = None
     self.__browserLoaded = False
     self.__showOnSplash = False
     self.__urlMacros = URLMarcos()
     return
 def __init__(self, ctx):
     super(PersonalMissionFirstEntryView, self).__init__(ctx)
     self.__currentVersionBrowserID = None
     self.__urlMacros = URLMarcos()
     self.__settings = GUI_SETTINGS.personalMissions.get('welcomeVideo', {})
     self.__cardsLen = len(self.__CARDS)
     return
class InternalLinksHandler(IInternalLinksController):
    browserCtrl = dependency.descriptor(IBrowserController)

    def __init__(self):
        super(InternalLinksHandler, self).__init__()
        self.__urlMarcos = None
        self._browserID = None
        return

    def init(self):
        self.__urlMarcos = URLMarcos()
        addListener = g_eventBus.addListener
        for eventType, handlerName in _LISTENERS.iteritems():
            handler = getattr(self, handlerName, None)
            if not handler:
                LOG_ERROR('Handler is not found', eventType, handlerName)
                continue
            if not callable(handler):
                LOG_ERROR('Handler is invalid', eventType, handlerName, handler)
                continue
            addListener(eventType, handler)

        return

    def fini(self):
        if self.__urlMarcos is not None:
            self.__urlMarcos.clear()
            self.__urlMarcos = None
        self._browserID = None
        removeListener = g_eventBus.removeListener
        for eventType, handlerName in _LISTENERS.iteritems():
            handler = getattr(self, handlerName, None)
            if handler:
                removeListener(eventType, handler)

        super(InternalLinksHandler, self).fini()
        return

    @async
    @process
    def getURL(self, name, callback):
        urlSettings = GUI_SETTINGS.lookup(name)
        if urlSettings:
            url = yield self.__urlMarcos.parse(str(urlSettings))
        else:
            url = yield lambda callback: callback('')
        callback(url)

    @process
    def __openInternalBrowse(self, urlName, title = '', browserSize = None, showActionBtn = True, showCloseBtn = False):
        parsedUrl = yield self.getURL(urlName)
        if parsedUrl:
            self._browserID = yield self.browserCtrl.load(parsedUrl, browserID=self._browserID, title=title, browserSize=browserSize, showActionBtn=showActionBtn, showCloseBtn=showCloseBtn)

    def _handleClubHelp(self, event):
        self.__openInternalBrowse(event.eventType, event.title, browserSize=gc_constants.BROWSER.CLUB_SIZE)

    def _handleVideoHelp(self, event):
        self.__openInternalBrowse(event.eventType, event.title, browserSize=gc_constants.BROWSER.VIDEO_SIZE, showActionBtn=False, showCloseBtn=True)
class InternalLinksHandler(Controller):

    def __init__(self, proxy):
        super(InternalLinksHandler, self).__init__(proxy)
        self.__urlMarcos = None
        self._browserID = None
        return

    def init(self):
        self.__urlMarcos = URLMarcos()
        addListener = g_eventBus.addListener
        for eventType, handlerName in _LISTENERS.iteritems():
            handler = getattr(self, handlerName, None)
            if not handler:
                LOG_ERROR('Handler is not found', eventType, handlerName)
                continue
            if not callable(handler):
                LOG_ERROR('Handler is invalid', eventType, handlerName, handler)
                continue
            addListener(eventType, handler)

        return

    def fini(self):
        if self.__urlMarcos is not None:
            self.__urlMarcos.clear()
            self.__urlMarcos = None
        self._browserID = None
        removeListener = g_eventBus.removeListener
        for eventType, handlerName in _LISTENERS.iteritems():
            handler = getattr(self, handlerName, None)
            if handler:
                removeListener(eventType, handler)

        super(InternalLinksHandler, self).fini()
        return

    @async
    @process
    def getURL(self, name, callback):
        urlSettings = GUI_SETTINGS.lookup(name)
        if urlSettings:
            url = yield self.__urlMarcos.parse(str(urlSettings))
        else:
            url = yield lambda callback: callback('')
        callback(url)

    @process
    def __openInternalBrowse(self, urlName, title = '', browserSize = None, showActionBtn = True, showCloseBtn = False):
        parsedUrl = yield self.getURL(urlName)
        if parsedUrl:
            self._browserID = yield self._proxy.getController(gc_constants.CONTROLLER.BROWSER).load(parsedUrl, browserID=self._browserID, title=title, browserSize=browserSize, showActionBtn=showActionBtn, showCloseBtn=showCloseBtn)

    def _handleClubHelp(self, event):
        self.__openInternalBrowse(event.eventType, event.title, browserSize=gc_constants.BROWSER.CLUB_SIZE)

    def _handleVideoHelp(self, event):
        self.__openInternalBrowse(event.eventType, event.title, browserSize=gc_constants.BROWSER.VIDEO_SIZE, showActionBtn=False, showCloseBtn=True)
Example #5
0
 def __init__(self, proxy):
     super(PromoController, self).__init__(proxy)
     self.__currentVersionPromoUrl = None
     self.__currentVersionBrowserID = None
     self.__currentVersionBrowserShown = False
     self.__promoShown = set()
     self.__availablePromo = set()
     self.__urlMacros = URLMarcos()
     self._isPromoShown = False
 def __init__(self, proxy):
     super(BrowserController, self).__init__(proxy)
     self.__browsers = {}
     self.__browsersCallbacks = {}
     self.__browserIDGenerator = SequenceIDGenerator()
     self.__eventMgr = Event.EventManager()
     self.onBrowserAdded = Event.Event(self.__eventMgr)
     self.onBrowserDeleted = Event.Event(self.__eventMgr)
     self.__urlMacros = URLMarcos()
 def __init__(self):
     super(BrowserController, self).__init__()
     self.__browsers = {}
     self.__browsersCallbacks = {}
     self.__browserIDGenerator = SequenceIDGenerator()
     self.__eventMgr = Event.EventManager()
     self.onBrowserAdded = Event.Event(self.__eventMgr)
     self.onBrowserDeleted = Event.Event(self.__eventMgr)
     self.__urlMacros = URLMarcos()
     self.__pendingBrowsers = {}
     self.__creatingBrowserID = None
     self.__filters = _getGlobalFilters()
     return
Example #8
0
 def __init__(self, data):
     super(MarathonEvent, self).__init__()
     self.__data = data
     self.__isEnabled = False
     self.__isAvailable = False
     self.__vehInInventory = False
     self.__state = ''
     self.__suspendFlag = False
     self.__quest = None
     self.__group = None
     self.__urlMacros = URLMarcos()
     self.__baseUrl = GUI_SETTINGS.lookup(data.url)
     return
Example #9
0
 def init(self):
     self.__urlMarcos = URLMarcos()
     addListener = g_eventBus.addListener
     for eventType, handlerName in _LISTENERS.iteritems():
         handler = getattr(self, handlerName, None)
         if not handler:
             LOG_ERROR('Handler is not found', eventType, handlerName)
             continue
         if not callable(handler):
             LOG_ERROR('Handler is invalid', eventType, handlerName,
                       handler)
             continue
         addListener(eventType, handler)
Example #10
0
 def __init__(self):
     super(PromoController, self).__init__()
     self.__currentVersionPromoUrl = None
     self.__currentVersionBrowserID = None
     self.__currentVersionBrowserShown = False
     self.__promoShown = set()
     self.__availablePromo = set()
     self.__urlMacros = URLMarcos()
     self.__guiActionsHandlers = None
     self.__isLobbyInited = False
     self.__pendingPromo = None
     self._isPromoShown = False
     return
 def __init__(self):
     super(MarathonEventController, self).__init__()
     self.__isEnabled = False
     self.__isAvailable = False
     self.__vehInInventory = False
     self.__state = ''
     self.__suspendFlag = False
     self.__marathonQuest = None
     self.__marathonGroup = None
     self.__urlMacros = URLMarcos()
     self.__baseUrl = GUI_SETTINGS.lookup('marathonUrl')
     self.__eventManager = Event.EventManager()
     self.onFlagUpdateNotify = Event.Event(self.__eventManager)
     return
def showBuyGoldWebOverlay(params=None):
    url = ingameshop_helpers.getBuyMoreGoldUrl()
    if url:
        url = yield URLMarcos().parse(url, params=params)
        g_eventBus.handleEvent(
            events.LoadViewEvent(VIEW_ALIAS.OVERLAY_WEB_STORE,
                                 ctx={'url': url}), EVENT_BUS_SCOPE.LOBBY)
 def __init__(self, proxy):
     super(BrowserController, self).__init__(proxy)
     self.__browsers = {}
     self.__browsersCallbacks = {}
     self.__browserIDGenerator = SequenceIDGenerator()
     self.__eventMgr = Event.EventManager()
     self.onBrowserAdded = Event.Event(self.__eventMgr)
     self.onBrowserDeleted = Event.Event(self.__eventMgr)
     self.__urlMacros = URLMarcos()
 def __init__(self, _=None):
     LobbySelectableView.__init__(self, 0)
     self.__currentCarouselAlias = None
     self.__isSpaceReadyForC11n = False
     self.__isVehicleReadyForC11n = False
     self.__isVehicleCameraReadyForC11n = False
     self.__urlMacros = URLMarcos()
     self.__teaser = None
     return
Example #15
0
 def __init__(self, proxy):
     super(PromoController, self).__init__(proxy)
     self.__currentVersionPromoUrl = None
     self.__currentVersionBrowserID = None
     self.__currentVersionBrowserShown = False
     self.__promoShown = set()
     self.__availablePromo = set()
     self.__urlMacros = URLMarcos()
     self._isPromoShown = False
Example #16
0
 def __init__(self):
     super(EncyclopediaController, self).__init__()
     self.__activated = False
     self.__recommendations = []
     self.__eventManager = Event.EventManager()
     self.__urlMacros = URLMarcos()
     self.__isLobbyStarted = False
     self.__hasNewRecommendations = False
     if GUI_SETTINGS.lookup('encyclopedia'):
         self.__baseUrl = GUI_SETTINGS.encyclopedia['url']
         self.__isSuitableLanguage = GUI_SETTINGS.encyclopedia['enabled']
     else:
         self.__baseUrl = None
         self.__isSuitableLanguage = False
     self.onNewRecommendationReceived = Event.Event(self.__eventManager)
     self.onStateChanged = Event.Event(self.__eventManager)
     self.__isStateSynced = False
     return
class PersonalMissionFirstEntryView(LobbySubView, PersonalMissionFirstEntryViewMeta):
    browserCtrl = dependency.descriptor(IBrowserController)
    __settingsCore = dependency.descriptor(ISettingsCore)
    _COMMON_SOUND_SPACE = PERSONAL_MISSIONS_SOUND_SPACE

    def __init__(self, ctx):
        super(PersonalMissionFirstEntryView, self).__init__(ctx)
        self.__currentVersionBrowserID = None
        self.__urlMacros = URLMarcos()
        self.__settings = GUI_SETTINGS.personalMissions.get('welcomeVideo', {})
        return

    def playVideo(self):
        if self.__settings.get('isEnabled', False):
            self.__showVideo()

    def backBtnClicked(self):
        self.__currentVersionBrowserID = None
        self.fireEvent(events.LoadViewEvent(VIEW_ALIAS.LOBBY_PERSONAL_MISSIONS), scope=EVENT_BUS_SCOPE.LOBBY)
        return

    def bigBtnClicked(self):
        self.__settingsCore.serverSettings.setPersonalMissionsFirstEntryState(_FES.TUTORIAL_WAS_SHOWN)
        self.fireEvent(events.LoadViewEvent(VIEW_ALIAS.LOBBY_PERSONAL_MISSIONS), scope=EVENT_BUS_SCOPE.LOBBY)

    def _populate(self):
        super(PersonalMissionFirstEntryView, self)._populate()
        self.as_setInitDataS({'titleLabel': PERSONAL_MISSIONS.PERSONALMISSIONFIRSTENTRYVIEW_TITLE,
         'subtitleLabel': PERSONAL_MISSIONS.PERSONALMISSIONFIRSTENTRYVIEW_SUBTITLE,
         'bigBtnLabel': PERSONAL_MISSIONS.PERSONALMISSIONFIRSTENTRYVIEW_ACKNOWLEDGEBTN,
         'playVideoBtnLabel': text_styles.concatStylesToSingleLine(icons.makeImageTag(RES_ICONS.MAPS_ICONS_PERSONALMISSIONS_PLAYICON, width=14, height=15, vSpace=-2), i18n.makeString(PERSONAL_MISSIONS.PERSONALMISSIONFIRSTENTRYVIEW_VIDEOBTNLABEL)),
         'playVideoBtnVisible': self.__settings.get('isEnabled', False),
         'bgSource': RES_ICONS.MAPS_ICONS_PERSONALMISSIONS_INFOSCREENBG,
         'tileList': [self.__makeTileData(RES_ICONS.MAPS_ICONS_PERSONALMISSIONS_FREE_SHEET_BIG, PERSONAL_MISSIONS.PERSONALMISSIONFIRSTENTRYVIEW_ITEM0_HEADER, PERSONAL_MISSIONS.PERSONALMISSIONFIRSTENTRYVIEW_ITEM0_DESCR), self.__makeTileData(RES_ICONS.MAPS_ICONS_PERSONALMISSIONS_GEAR_BIG, PERSONAL_MISSIONS.PERSONALMISSIONFIRSTENTRYVIEW_ITEM2_HEADER, PERSONAL_MISSIONS.PERSONALMISSIONFIRSTENTRYVIEW_ITEM2_DESCR), self.__makeTileData(RES_ICONS.MAPS_ICONS_PERSONALMISSIONS_BALANCE, PERSONAL_MISSIONS.PERSONALMISSIONFIRSTENTRYVIEW_ITEM1_HEADER, PERSONAL_MISSIONS.PERSONALMISSIONFIRSTENTRYVIEW_ITEM1_DESCR)],
         'backBtnLabel': PERSONAL_MISSIONS.HEADER_BACKBTN_LABEL,
         'isFirstEntry': self.__settingsCore.serverSettings.getPersonalMissionsFirstEntryState() == _FES.NOT_VISITED})

    @process
    def __showVideo(self):
        url = yield self.__urlMacros.parse(self.__settings.get('url'))
        webBrowser = self.__getCurrentBrowser()
        if not webBrowser or url != webBrowser.url:
            title = i18n.makeString(PERSONAL_MISSIONS.PERSONALMISSIONS_VIDEO_TITLE)
            self.__currentVersionBrowserID = yield self.browserCtrl.load(url, title, showActionBtn=False, browserID=self.__currentVersionBrowserID, browserSize=gc_constants.BROWSER.VIDEO_SIZE, isDefault=False, showCloseBtn=True, handlers=self.__createWebHandlers())

    @staticmethod
    def __makeTileData(iconSource, titleLabel, descriptionLabel):
        return {'iconSource': iconSource,
         'titleLabel': titleLabel,
         'descriptionLabel': descriptionLabel}

    def __getCurrentBrowser(self):
        return self.browserCtrl.getBrowser(self.__currentVersionBrowserID)

    def __createWebHandlers(self):
        return [createHangarSoundHandler(handleHangarSoundCommand, handleHangarSoundCommandFini)]
def showBuyVehicleOverlay(params=None):
    url = ingameshop_helpers.getVehicleUrl()
    if url:
        url = yield URLMarcos().parse(url, params=params)
        g_eventBus.handleEvent(
            events.LoadViewEvent(VIEW_ALIAS.OVERLAY_WEB_STORE,
                                 ctx={
                                     'url':
                                     url,
                                     'browserParams':
                                     makeBrowserParams(WAITING.BUYITEM, True)
                                 }), EVENT_BUS_SCOPE.LOBBY)
Example #19
0
 def init(self):
     self.__urlMarcos = URLMarcos()
     addListener = g_eventBus.addListener
     for eventType, handlerName in _LISTENERS.iteritems():
         handler = getattr(self, handlerName, None)
         if not handler:
             LOG_ERROR('Handler is not found', eventType, handlerName)
             continue
         if not callable(handler):
             LOG_ERROR('Handler is invalid', eventType, handlerName, handler)
             continue
         addListener(eventType, handler)
Example #20
0
 def __init__(self):
     super(PromoController, self).__init__()
     self.__urlMacros = URLMarcos()
     self.__externalCloseCallback = None
     self.__isLobbyInited = False
     self.__pendingPromo = None
     self.__promoCount = 0
     self.__lastUpdateTimeMark = 0
     self.__promoData = None
     self.__webBrgDataRequested = False
     self.__battlesFromLastTeaser = 0
     self.__wasInBattle = False
     self.__hasPendingTeaser = False
     self.__isPromoOpen = False
     self.__browserCreationCallbacks = {}
     self.__browserWatchers = {}
     self.__isInHangar = False
     self.__isTeaserOpen = False
     self.__em = EventManager()
     self.onNewTeaserReceived = Event(self.__em)
     self.onPromoCountChanged = Event(self.__em)
     return
 def __init__(self, proxy):
     super(BrowserController, self).__init__(proxy)
     self.__browsers = {}
     self.__browsersCallbacks = {}
     self.__browserIDGenerator = SequenceIDGenerator()
     self.__eventMgr = Event.EventManager()
     self.onBrowserAdded = Event.Event(self.__eventMgr)
     self.onBrowserDeleted = Event.Event(self.__eventMgr)
     self.__urlMacros = URLMarcos()
     self.__pendingBrowsers = {}
     self.__creatingBrowserID = None
     self.__filters = _getGlobalFilters()
     return
 def __init__(self, proxy):
     super(EncyclopediaController, self).__init__(proxy)
     self.__activated = False
     self.__recommendations = []
     self.__eventManager = Event.EventManager()
     self.__urlMacros = URLMarcos()
     self.__isLobbyStarted = False
     self.__hasNewRecommendations = False
     if GUI_SETTINGS.lookup('encyclopedia'):
         self.__baseUrl = GUI_SETTINGS.encyclopedia['url']
         self.__isSuitableLanguage = GUI_SETTINGS.encyclopedia['enabled']
     else:
         self.__baseUrl = None
         self.__isSuitableLanguage = False
     self.onNewRecommendationReceived = Event.Event(self.__eventManager)
     self.onStateChanged = Event.Event(self.__eventManager)
     self.__isStateSynced = False
     return
Example #23
0
class BrowserController(IBrowserController):
    _BROWSER_TEXTURE = 'BrowserBg'
    _ALT_BROWSER_TEXTURE = 'AltBrowserBg'

    def __init__(self):
        super(BrowserController, self).__init__()
        self.__browsers = {}
        self.__browsersCallbacks = {}
        self.__browserCreationCallbacks = {}
        self.__browserIDGenerator = SequenceIDGenerator()
        self.__eventMgr = Event.EventManager()
        self.onBrowserAdded = Event.Event(self.__eventMgr)
        self.onBrowserDeleted = Event.Event(self.__eventMgr)
        self.__urlMacros = URLMarcos()
        self.__pendingBrowsers = {}
        self.__creatingBrowserID = None
        self.__filters = _getGlobalFilters()
        return

    def fini(self):
        self.__filters = None
        self.__eventMgr.clear()
        self.__eventMgr = None
        self.__urlMacros.clear()
        self.__urlMacros = None
        self.__browsersCallbacks.clear()
        self.__browsersCallbacks = None
        self.__browsers.clear()
        self.__browsers = None
        self.__pendingBrowsers.clear()
        self.__pendingBrowsers = None
        self.__browserIDGenerator = None
        super(BrowserController, self).fini()
        return

    def onAvatarBecomePlayer(self):
        self.__stop()

    def onDisconnected(self):
        self.__stop()

    def addFilterHandler(self, handler):
        self.__filters.add(handler)

    def removeFilterHandler(self, handler):
        self.__filters.discard(handler)

    @async
    @process
    def load(self, url=None, title=None, showActionBtn=True, showWaiting=True, browserID=None, isAsync=False, browserSize=None, isDefault=True, callback=None, showCloseBtn=False, useBrowserWindow=True, isModal=False, showCreateWaiting=False, handlers=None, showBrowserCallback=None, isSolidBorder=False):
        if showCreateWaiting:
            Waiting.show('browser/init')
        url = yield self.__urlMacros.parse(url or GUI_SETTINGS.browser.url)
        suffix = yield self.__urlMacros.parse(GUI_SETTINGS.browser.params)
        concatenator = '&' if '?' in url else '?'
        if suffix not in url:
            url = concatenator.join([url, suffix])
        size = browserSize or BROWSER.SIZE
        webBrowserID = browserID
        if browserID is None:
            browserID = self.__browserIDGenerator.next()
            webBrowserID = browserID
        elif type(browserID) is not int:
            webBrowserID = self.__browserIDGenerator.next()
        ctx = {'url': url,
         'title': title,
         'showActionBtn': showActionBtn,
         'showWaiting': showWaiting,
         'browserID': browserID,
         'size': size,
         'isAsync': isAsync,
         'showCloseBtn': showCloseBtn,
         'showWindow': useBrowserWindow,
         'alias': VIEW_ALIAS.BROWSER_WINDOW_MODAL if isModal else VIEW_ALIAS.BROWSER_WINDOW,
         'showCreateWaiting': showCreateWaiting,
         'handlers': handlers,
         'showBrowserCallback': showBrowserCallback,
         'isSolidBorder': isSolidBorder}
        if browserID not in self.__browsers and browserID not in self.__pendingBrowsers:
            texture = self._BROWSER_TEXTURE
            app = g_appLoader.getApp()
            if app is None:
                raise SoftException('Application can not be None')
            browser = WebBrowser(webBrowserID, app, texture, size, url, handlers=self.__filters)
            self.__browsers[browserID] = browser
            if self.__isCreatingBrowser():
                _logger.debug('CTRL: Queueing a browser creation: %r - %s', browserID, url)
                self.__pendingBrowsers[browserID] = ctx
            else:
                self.__createBrowser(ctx)
        elif browserID in self.__pendingBrowsers:
            _logger.debug('CTRL: Re-queuing a browser creation, overriding: %r - %s', browserID, url)
            self.__pendingBrowsers[browserID] = ctx
        elif browserID in self.__browsers:
            _logger.debug('CTRL: Re-navigating an existing browser: %r - %s', browserID, url)
            browser = self.__browsers[browserID]
            browser.navigate(url)
            browser.changeTitle(title)
        callback(browserID)
        return

    def getAllBrowsers(self):
        return self.__browsers

    def getBrowser(self, browserID):
        return self.__browsers.get(browserID)

    def delBrowser(self, browserID):
        if browserID in self.__browsers:
            _logger.debug('CTRL: Deleting a browser: %s', browserID)
            browser = self.__browsers.pop(browserID)
            self.__clearCallbacks(browserID, browser, True)
            browser.destroy()
            if self.__creatingBrowserID == browserID:
                self.__creatingBrowserID = None
                self.__tryCreateNextPendingBrowser()
            if browserID in self.__pendingBrowsers:
                del self.__pendingBrowsers[browserID]
        self.onBrowserDeleted(browserID)
        return

    def __isCreatingBrowser(self):
        return self.__creatingBrowserID is not None

    def __createDone(self, ctx):
        _logger.debug('CTRL: Finished creating a browser: %s', self.__creatingBrowserID)
        if ctx['showCreateWaiting']:
            Waiting.hide('browser/init')

    def __tryCreateNextPendingBrowser(self):
        self.__creatingBrowserID = None
        if self.__pendingBrowsers:
            nextCtx = self.__pendingBrowsers.popitem()[1]
            self.__createBrowser(nextCtx)
        return

    def __createBrowser(self, ctx):
        browserID = ctx['browserID']
        _logger.debug('CTRL: Creating a browser: %r - %s', browserID, ctx['url'])
        self.__creatingBrowserID = browserID
        browser = self.__browsers[browserID]
        if not browser.create():
            _logger.debug('CTRL: Failed the create step: %r', browserID)
            self.delBrowser(browserID)
            self.__tryCreateNextPendingBrowser()
            return
        else:
            self.onBrowserAdded(browserID)

            def createBrowserTimeout():
                _logger.debug('CTRL: Browser create timed out')
                createNextBrowser()

            timeoutid = BigWorld.callback(30.0, createBrowserTimeout)

            def createNextBrowser():
                _logger.debug('CTRL: Triggering create of next browser from: %s', browserID)
                BigWorld.cancelCallback(timeoutid)
                creation = self.__browserCreationCallbacks.pop(browserID, None)
                if creation is not None:
                    self.__browsers[browserID].onCanCreateNewBrowser -= creation
                BigWorld.callback(1.0, self.__tryCreateNextPendingBrowser)
                return

            def failedCreationCallback(url):
                _logger.debug('CTRL: Failed a creation: %r - %s', browserID, url)
                self.__clearCallbacks(browserID, self.__browsers[browserID], False)
                self.delBrowser(browserID)

            def successfulCreationCallback(url, isLoaded, httpStatusCode=None):
                _logger.debug('CTRL: Ready to show: %r - %r - %s', browserID, isLoaded, url)
                self.__clearCallbacks(browserID, self.__browsers[browserID], False)
                if isLoaded:
                    self.__showBrowser(browserID, ctx)
                else:
                    _logger.warning('Browser request url %s was not loaded!', url)
                g_eventBus.handleEvent(BrowserEvent(BrowserEvent.BROWSER_CREATED, ctx=ctx))
                self.__createDone(ctx)

            def titleUpdateCallback(title):
                ctx['title'] = title

            browser.onCanCreateNewBrowser += createNextBrowser
            self.__browserCreationCallbacks[browserID] = createNextBrowser
            browser.onFailedCreation += failedCreationCallback
            browser.onTitleChange += titleUpdateCallback
            if ctx['isAsync']:
                self.__browsersCallbacks[browserID] = (None,
                 successfulCreationCallback,
                 failedCreationCallback,
                 titleUpdateCallback)
                browser.onLoadEnd += successfulCreationCallback
            else:
                self.__browsersCallbacks[browserID] = (successfulCreationCallback,
                 None,
                 failedCreationCallback,
                 titleUpdateCallback)
                browser.onReady += successfulCreationCallback
            return

    def __stop(self):
        while self.__browsers:
            browserID, browser = self.__browsers.popitem()
            self.__clearCallbacks(browserID, browser, True)
            browser.destroy()

    def __clearCallbacks(self, browserID, browser, incDelayedCreation):
        ready, loadEnd, failed, title = self.__browsersCallbacks.pop(browserID, (None, None, None, None))
        if browser is not None:
            if failed is not None:
                browser.onFailedCreation -= failed
            if ready is not None:
                browser.onReady -= ready
            if loadEnd is not None:
                browser.onLoadEnd -= loadEnd
            if title is not None:
                browser.onTitleChange -= title
        if incDelayedCreation:
            creation = self.__browserCreationCallbacks.pop(browserID, None)
            if browser is not None and creation is not None:
                browser.onCanCreateNewBrowser -= creation
        return

    def __showBrowser(self, browserID, ctx):
        _logger.debug('CTRL: Showing a browser: %r - %s', browserID, ctx['url'])
        if ctx.get('showWindow'):
            alias = ctx['alias']
            g_eventBus.handleEvent(LoadViewEvent(alias, getViewName(alias, browserID), ctx=ctx), EVENT_BUS_SCOPE.LOBBY)
        showBrowserCallback = ctx.get('showBrowserCallback')
        if showBrowserCallback:
            showBrowserCallback()
Example #24
0
class PromoController(Controller):
    PROMO_AUTO_VIEWS_TEST_VALUE = 5

    def __init__(self, proxy):
        super(PromoController, self).__init__(proxy)
        self.__currentVersionPromoUrl = None
        self.__currentVersionBrowserID = None
        self.__currentVersionBrowserShown = False
        self.__promoShown = set()
        self.__availablePromo = set()
        self.__urlMacros = URLMarcos()
        self._isPromoShown = False
        return

    def fini(self):
        self._stop()
        self.__urlMacros.clear()
        self.__urlMacros = None
        super(PromoController, self).fini()
        return

    def onLobbyInited(self, event):
        self._updatePromo(self._getPromoEventNotifications())
        self._getEventsFotificationController().onEventNotificationsChanged += self.__onEventNotification
        self._getBrowserController().onBrowserDeleted += self.__onBrowserDeleted
        self._processPromo(self._getEventNotifications())

    def onAvatarBecomePlayer(self):
        self._stop()

    def onDisconnected(self):
        self._stop()
        self._isPromoShown = False

    @process
    def showPatchPromo(self, isAsync = False):
        self.__currentVersionBrowserID = yield self.__showPromoBrowser(self.__currentVersionPromoUrl, i18n.makeString(MENU.PROMO_PATCH_TITLE, version=getClientVersion()), browserID=self.__currentVersionBrowserID, isAsync=isAsync)

    def isPatchPromoAvailable(self):
        return self.__currentVersionPromoUrl is not None

    def _stop(self):
        self.__currentVersionPromoUrl = None
        self.__currentVersionBrowserID = None
        self.__currentVersionBrowserShown = False
        self._getBrowserController().onBrowserDeleted -= self.__onBrowserDeleted
        self._getEventsFotificationController().onEventNotificationsChanged -= self.__onEventNotification
        return

    @process
    def _processPromo(self, promo):
        yield lambda callback: callback(True)
        if self.isPatchPromoAvailable() and self.__currentVersionPromoUrl not in self.__promoShown and self.isPromoAutoViewsEnabled() and not self._isPromoShown:
            LOG_DEBUG('Showing patchnote promo:', self.__currentVersionPromoUrl)
            self.__promoShown.add(self.__currentVersionPromoUrl)
            self.__savePromoShown()
            self.__currentVersionBrowserShown = True
            self._isPromoShown = True
            self.showPatchPromo(isAsync=True)
            return
        actionsPromo = [ item for item in promo if item.eventType.startswith(gc_constants.PROMO.TEMPLATE.ACTION) ]
        for actionPromo in actionsPromo:
            promoUrl = yield self.__urlMacros.parse(actionPromo.data)
            promoTitle = actionPromo.text
            if promoUrl not in self.__promoShown and not self._isPromoShown:
                LOG_DEBUG('Showing action promo:', promoUrl)
                self.__promoShown.add(promoUrl)
                self.__savePromoShown()
                self._isPromoShown = True
                yield self.__showPromoBrowser(promoUrl, promoTitle)
                return

    @process
    def _updatePromo(self, promosData):
        yield lambda callback: callback(True)
        for item in filter(lambda item: item.eventType in (gc_constants.PROMO.TEMPLATE.PATCH, gc_constants.PROMO.TEMPLATE.ACTION), promosData):
            promoUrl = yield self.__urlMacros.parse(item.data)
            self.__availablePromo.add(promoUrl)
            if item.eventType == gc_constants.PROMO.TEMPLATE.PATCH and self.__currentVersionPromoUrl is None:
                self.__currentVersionPromoUrl = promoUrl

        promoShownSource = AccountSettings.getFilter(PROMO)
        self.__promoShown = {url for url in promoShownSource if url in self.__availablePromo}
        self.__savePromoShown()
        return

    def _getEventNotifications(self):
        return self._proxy.getController(gc_constants.CONTROLLER.EVENTS_NOTIFICATION).getEventsNotifications()

    def _getPromoEventNotifications(self):
        filterFunc = lambda item: item.eventType in (gc_constants.PROMO.TEMPLATE.PATCH, gc_constants.PROMO.TEMPLATE.ACTION)
        return self._getEventsFotificationController().getEventsNotifications(filterFunc)

    def _getBrowserController(self):
        return self._proxy.getController(gc_constants.CONTROLLER.BROWSER)

    def _getEventsFotificationController(self):
        return self._proxy.getController(gc_constants.CONTROLLER.EVENTS_NOTIFICATION)

    def __savePromoShown(self):
        AccountSettings.setFilter(PROMO, self.__promoShown)

    def __onEventNotification(self, added, removed):
        self._updatePromo(self._getPromoEventNotifications())
        self._processPromo(added)

    def __onBrowserDeleted(self, browserID):
        if self.__currentVersionBrowserID == browserID:
            self.__currentVersionBrowserID = None
            if self.__currentVersionBrowserShown:
                self.__currentVersionBrowserShown = False
                g_eventBus.handleEvent(events.BubbleTooltipEvent(events.BubbleTooltipEvent.SHOW, i18n.makeString(TOOLTIPS.HEADER_VERSIONINFOHINT)), scope=EVENT_BUS_SCOPE.LOBBY)
        return

    @async
    @process
    def __showPromoBrowser(self, promoUrl, promoTitle, browserID = None, isAsync = True, callback = None):
        browserID = yield self._getBrowserController().load(promoUrl, promoTitle, showActionBtn=False, isAsync=isAsync, browserID=browserID, browserSize=gc_constants.BROWSER.PROMO_SIZE, background=gc_constants.BROWSER.PROMO_BACKGROUND, isDefault=False, showCloseBtn=True)
        callback(browserID)

    @classmethod
    def isPromoAutoViewsEnabled(cls):
        return getAccountDatabaseID() % cls.PROMO_AUTO_VIEWS_TEST_VALUE != 0 and g_lobbyContext.getServerSettings().isPromoAutoViewsEnabled()
Example #25
0
class PromoController(IPromoController):
    browserCtrl = dependency.descriptor(IBrowserController)
    eventsNotification = dependency.descriptor(IEventsNotificationsController)
    __webController = dependency.descriptor(IWebController)
    __settingsCore = dependency.descriptor(ISettingsCore)
    __lobbyContext = dependency.descriptor(ILobbyContext)
    __logger = dependency.descriptor(IPromoLogger)
    __bootcamp = dependency.descriptor(IBootcampController)
    _CHECK_FREQUENCY_IN_BATTLES = 10

    def __init__(self):
        super(PromoController, self).__init__()
        self.__urlMacros = URLMarcos()
        self.__externalCloseCallback = None
        self.__isLobbyInited = False
        self.__pendingPromo = None
        self.__promoCount = 0
        self.__lastUpdateTimeMark = 0
        self.__promoData = None
        self.__webBrgDataRequested = False
        self.__battlesFromLastTeaser = 0
        self.__wasInBattle = False
        self.__hasPendingTeaser = False
        self.__isPromoOpen = False
        self.__browserCreationCallbacks = {}
        self.__browserWatchers = {}
        self.__isInHangar = False
        self.__isTeaserOpen = False
        self.__em = EventManager()
        self.onNewTeaserReceived = Event(self.__em)
        self.onPromoCountChanged = Event(self.__em)
        return

    @sf_lobby
    def app(self):
        pass

    def fini(self):
        self.__stop()
        self.__pendingPromo = None
        self.__urlMacros.clear()
        self.__urlMacros = None
        self.__externalCloseCallback = None
        self.__em.clear()
        g_eventBus.removeListener(BrowserEvent.BROWSER_CREATED,
                                  self.__handleBrowserCreated)
        self.__browserCreationCallbacks = {}
        self.__browserWatchers = {}
        super(PromoController, self).fini()
        return

    def onLobbyInited(self, event):
        if not isPlayerAccount():
            return
        g_eventBus.addListener(BrowserEvent.BROWSER_CREATED,
                               self.__handleBrowserCreated)
        self.__isLobbyInited = True
        if self.__hasPendingTeaser:
            self.__tryToShowTeaser()
        elif self.__battlesFromLastTeaser % self._CHECK_FREQUENCY_IN_BATTLES == 0:
            self.__updateWebBrgData()
        self.eventsNotification.onEventNotificationsChanged += self.__onEventNotification
        if not isPopupsWindowsOpenDisabled():
            self.__processPromo(
                self.eventsNotification.getEventsNotifications())
        self.app.loaderManager.onViewLoaded += self.__onViewLoaded

    def setNewTeaserData(self, teaserData):
        timestamp = teaserData['timestamp']
        if self.__lastUpdateTimeMark < timestamp and not self.__isPromoOpen and not self.__isTeaserOpen:
            self.__updateTeaserData(teaserData)

    def showFieldPost(self):
        url = GUI_SETTINGS.promoscreens
        loadingCallback = self.__logger.getLoggingFuture(
            action=PromoLogActions.OPEN_FROM_MENU,
            type=PromoLogSubjectType.INDEX,
            url=url)
        self.__showBrowserView(url, loadingCallback)

    @process
    def showLastTeaserPromo(self):
        rowUrl = self.__promoData.get('url', '')
        loadingCallback = self.__logger.getLoggingFuture(
            self.__promoData,
            action=PromoLogActions.OPEN_FROM_TEASER,
            type=PromoLogSubjectType.PROMO_SCREEN,
            url=rowUrl)
        url = yield self.__addAuthParams(rowUrl)
        self.__showBrowserView(url, loadingCallback)

    def setUnreadPromoCount(self, count):
        self.__updatePromoCount(count)

    def onAvatarBecomePlayer(self):
        if self.__isLobbyInited:
            self.__battlesFromLastTeaser += 1
        self.__stop()

    def onDisconnected(self):
        self.__stop()

    def isActive(self):
        return self.__lobbyContext.getServerSettings().isFieldPostEnabled(
        ) and not self.__bootcamp.isInBootcamp()

    def getPromoCount(self):
        return self.__promoCount

    def showPromo(self, url, closeCallback=None, source=None):
        if self.__isLobbyInited:
            if not self.__isPromoOpen and not self.__webBrgDataRequested:
                self.__registerAndShowPromoBrowser(
                    url, closeCallback,
                    self.__logger.getLoggingFuture(
                        action=PromoLogActions.OPEN_IN_OLD,
                        type=PromoLogSubjectType.PROMO_SCREEN,
                        source=source,
                        url=url))
        else:
            self.__pendingPromo = _PromoData(url, closeCallback, source)

    def __onTeaserClosed(self, byUser=False):
        self.__isTeaserOpen = False
        if byUser:
            self.__showBubbleTooltip()

    def __showBubbleTooltip(self):
        storageData = self.__settingsCore.serverSettings.getUIStorage()
        if not storageData.get(UI_STORAGE_KEYS.FIELD_POST_HINT_IS_SHOWN):
            showBubbleTooltip(i18n.makeString(TOOLTIPS.HEADER_VERSIONINFOHINT))
            self.__settingsCore.serverSettings.saveInUIStorage(
                {UI_STORAGE_KEYS.FIELD_POST_HINT_IS_SHOWN: True})

    @process
    def __updateWebBrgData(self):
        ctx = PromoGetTeaserRequestCtx()
        if self.__battlesFromLastTeaser == 0:
            sourceType = PromoLogSourceType.FIRST_LOGIN
        else:
            sourceType = PromoLogSourceType.AFTER_BATTLE
        answerCallback = self.__logger.getLoggingFuture(
            action=PromoLogActions.GET_MOST_IMPORTANT, source=sourceType)
        self.__webBrgDataRequested = True
        response = yield self.__webController.sendRequest(ctx=ctx)
        if response.isSuccess():
            self.__updateTeaserData(ctx.getDataObj(response.getData()))
        self.__webBrgDataRequested = False
        if answerCallback:
            answerCallback(success=response.extraCode)

    def __onPromoClosed(self, **kwargs):
        self.__isPromoOpen = False
        self.__showBubbleTooltip()
        if self.__externalCloseCallback:
            self.__externalCloseCallback()
        self.__requestPromoCount()
        actionType = PromoLogActions.CLOSED_BY_USER if kwargs.get(
            'byUser') else PromoLogActions.KILLED_BY_SYSTEM
        self.__logger.logAction(action=actionType,
                                type=PromoLogSubjectType.PROMO_SCREEN_OR_INDEX,
                                url=kwargs.get('url'))

    @process
    def __requestPromoCount(self):
        if not self.isActive():
            _logger.warning(
                'Trying to request unread promos count when promo functionality is disabled'
            )
            return
        ctx = PromoGetUnreadCountRequestCtx()
        response = yield self.__webController.sendRequest(ctx=ctx)
        if response.isSuccess():
            self.__updatePromoCount(ctx.getCount(response))

    def __updatePromoCount(self, count):
        countChanged = count != self.__promoCount
        self.__promoCount = count
        if countChanged:
            self.onPromoCountChanged()

    def __updateTeaserData(self, teaserData):
        self.__lastUpdateTimeMark = teaserData['timestamp']
        self.__promoData = teaserData['lastPromo']
        self.__updatePromoCount(teaserData['count'])
        if self.__promoData.get('url'):
            self.__tryToShowTeaser()

    def __showTeaser(self):
        if self.isActive():
            self.__battlesFromLastTeaser = 0
            self.__hasPendingTeaser = False
            self.onNewTeaserReceived(self.__promoData, self.__onTeaserShown,
                                     self.__onTeaserClosed)
        else:
            _logger.warning(
                'Impossible to show teaser, functionality is disabled')

    @process
    def __onTeaserShown(self, promoID):
        self.__isTeaserOpen = True
        yield self.__webController.sendRequest(
            PromoSendTeaserShownRequestCtx(promoID))

    def __tryToShowTeaser(self):
        if self.__isLobbyInited and self.__isInHangar:
            self.__showTeaser()
        else:
            self.__hasPendingTeaser = True

    def __stop(self):
        if self.app and self.app.loaderManager:
            self.app.loaderManager.onViewLoaded -= self.__onViewLoaded
        self.__isLobbyInited = False
        self.__isPromoOpen = False
        self.__currentVersionBrowserID = None
        self.__externalCloseCallback = None
        self.__isTeaserOpen = False
        self.eventsNotification.onEventNotificationsChanged -= self.__onEventNotification
        g_eventBus.removeListener(BrowserEvent.BROWSER_CREATED,
                                  self.__handleBrowserCreated)
        self.__browserCreationCallbacks = {}
        watcherKeys = self.__browserWatchers.keys()
        for browserID in watcherKeys:
            self.__clearWatcher(browserID)

        return

    def __processPromo(self, promos):
        if not self.__isPromoOpen and not self.__webBrgDataRequested:
            logData = {
                'action': PromoLogActions.OPEN_IN_OLD,
                'type': PromoLogSubjectType.PROMO_SCREEN
            }
            if self.__pendingPromo is not None:
                promoData = self.__pendingPromo
                logData.update({
                    'source': promoData.source,
                    'url': promoData.url
                })
                loadingCallback = self.__logger.getLoggingFuture(**logData)
                self.__registerAndShowPromoBrowser(promoData.url,
                                                   promoData.closeCallback,
                                                   loadingCallback)
                self.__pendingPromo = None
                return
            promo = findFirst(
                lambda item: item.eventType.startswith(
                    gc_constants.PROMO.TEMPLATE.ACTION), promos)
            if promo:
                logData.update({
                    'source': PromoLogSourceType.SSE,
                    'url': promo.data
                })
                self.__showBrowserView(
                    promo.data, self.__logger.getLoggingFuture(**logData))
        return

    def __onEventNotification(self, added, _):
        self.__processPromo(added)

    def __registerAndShowPromoBrowser(self, url, closeCallback,
                                      loadingCallback):
        self.__externalCloseCallback = closeCallback
        self.__showBrowserView(url, loadingCallback)

    @process
    def __showBrowserView(self, url, loadingCallback=None):
        promoUrl = yield self.__urlMacros.parse(url)
        self.__registerLoadingCallback(promoUrl, loadingCallback)
        _showBrowserView(promoUrl, self.__onPromoClosed)
        self.__isPromoOpen = True

    def __registerLoadingCallback(self, url, callback):
        if callback is not None:
            self.__browserCreationCallbacks[url] = callback
        return

    def __handleBrowserCreated(self, event):
        url = event.ctx.get('url')
        if url in self.__browserCreationCallbacks:
            callback = self.__browserCreationCallbacks.pop(url)
            browserID = event.ctx.get('browserID')
            browser = self.browserCtrl.getBrowser(browserID)
            if browser is None:
                return

            def callbackWrapper(clbUrl, _, statusCode):
                if clbUrl == url:
                    callback(url=url, success=statusCode)
                    self.__clearWatcher(browserID)

            browser.onLoadEnd += callbackWrapper
            self.__browserWatchers[browserID] = callbackWrapper
        return

    def __clearWatcher(self, browserID):
        if browserID in self.__browserWatchers:
            watcher = self.__browserWatchers.pop(browserID)
            browser = self.browserCtrl.getBrowser(browserID)
            if browser is not None:
                browser.onLoadEnd -= watcher
        return

    @async
    @process
    def __addAuthParams(self, url, callback):
        if not url or not self.__webController:
            callback(url)
        accessTokenData = yield self.__webController.getAccessTokenData(
            force=True)
        params = {
            'access_token': str(accessTokenData.accessToken),
            'spa_id': BigWorld.player().databaseID
        }
        callback(url_formatters.addParamsToUrlQuery(url, params))

    def __onViewLoaded(self, pyView, _):
        if self.__isLobbyInited:
            if pyView.alias == VIEW_ALIAS.LOBBY_HANGAR:
                self.__isInHangar = True
                if self.__hasPendingTeaser:
                    self.__tryToShowTeaser()
            elif pyView.viewType == ViewTypes.LOBBY_SUB:
                self.__isInHangar = False
class BrowserController(IBrowserController):
    _BROWSER_TEXTURE = 'BrowserBg'
    _ALT_BROWSER_TEXTURE = 'AltBrowserBg'

    def __init__(self):
        super(BrowserController, self).__init__()
        self.__browsers = {}
        self.__browsersCallbacks = {}
        self.__browserCreationCallbacks = {}
        self.__browserIDGenerator = SequenceIDGenerator()
        self.__eventMgr = Event.EventManager()
        self.onBrowserAdded = Event.Event(self.__eventMgr)
        self.onBrowserDeleted = Event.Event(self.__eventMgr)
        self.__urlMacros = URLMarcos()
        self.__pendingBrowsers = {}
        self.__creatingBrowserID = None
        self.__filters = _getGlobalFilters()
        return

    def fini(self):
        self.__filters = None
        self.__eventMgr.clear()
        self.__eventMgr = None
        self.__urlMacros.clear()
        self.__urlMacros = None
        self.__browsersCallbacks.clear()
        self.__browsersCallbacks = None
        self.__browsers.clear()
        self.__browsers = None
        self.__pendingBrowsers.clear()
        self.__pendingBrowsers = None
        self.__browserIDGenerator = None
        super(BrowserController, self).fini()
        return

    def onAvatarBecomePlayer(self):
        self.__stop()

    def onDisconnected(self):
        self.__stop()

    def addFilterHandler(self, handler):
        """ Adds given @handler to the browser urls filter chain. Calls
        it if there is a @tag in url onto opened browser page.
        Handler should receive url and list of client-specific tags,
        return bool as flag that routine have to stop
        """
        self.__filters.add(handler)

    def removeFilterHandler(self, handler):
        """ Remove given @handler from filtering chain. Handler description
        can be seen in addFilterhandler method doc-string
        """
        self.__filters.discard(handler)

    @async
    @process
    def load(self,
             url=None,
             title=None,
             showActionBtn=True,
             showWaiting=True,
             browserID=None,
             isAsync=False,
             browserSize=None,
             isDefault=True,
             callback=None,
             showCloseBtn=False,
             useBrowserWindow=True,
             isModal=False,
             showCreateWaiting=False,
             handlers=None,
             showBrowserCallback=None,
             isSolidBorder=False):
        if constants.IS_BOOTCAMP_ENABLED:
            from bootcamp.Bootcamp import g_bootcamp
            if g_bootcamp.isRunning():
                return
        if showCreateWaiting:
            Waiting.show('browser/init')
        url = yield self.__urlMacros.parse(url or GUI_SETTINGS.browser.url)
        suffix = yield self.__urlMacros.parse(GUI_SETTINGS.browser.params)
        concatenator = '&' if '?' in url else '?'
        if suffix not in url:
            url = concatenator.join([url, suffix])
        size = browserSize or BROWSER.SIZE
        webBrowserID = browserID
        if browserID is None:
            browserID = self.__browserIDGenerator.next()
            webBrowserID = browserID
        elif type(browserID) is not int:
            webBrowserID = self.__browserIDGenerator.next()
        ctx = {
            'url': url,
            'title': title,
            'showActionBtn': showActionBtn,
            'showWaiting': showWaiting,
            'browserID': browserID,
            'size': size,
            'isAsync': isAsync,
            'showCloseBtn': showCloseBtn,
            'showWindow': useBrowserWindow,
            'alias': VIEW_ALIAS.BROWSER_WINDOW_MODAL
            if isModal else VIEW_ALIAS.BROWSER_WINDOW,
            'showCreateWaiting': showCreateWaiting,
            'handlers': handlers,
            'showBrowserCallback': showBrowserCallback,
            'isSolidBorder': isSolidBorder
        }
        texture = browserID not in self.__browsers and browserID not in self.__pendingBrowsers and self._BROWSER_TEXTURE
        app = g_appLoader.getApp()
        if not app:
            raise AssertionError('Application can not be None')
            browser = WebBrowser(webBrowserID,
                                 app,
                                 texture,
                                 size,
                                 url,
                                 handlers=self.__filters)
            self.__browsers[browserID] = browser
            if self.__isCreatingBrowser():
                LOG_BROWSER('CTRL: Queueing a browser creation: ', browserID,
                            url)
                self.__pendingBrowsers[browserID] = ctx
            else:
                self.__createBrowser(ctx)
        elif browserID in self.__pendingBrowsers:
            LOG_BROWSER('CTRL: Re-queuing a browser creation, overriding: ',
                        browserID, url)
            self.__pendingBrowsers[browserID] = ctx
        elif browserID in self.__browsers:
            LOG_BROWSER('CTRL: Re-navigating an existing browser: ', browserID,
                        url)
            browser = self.__browsers[browserID]
            browser.navigate(url)
            browser.changeTitle(title)
        callback(browserID)
        return

    def getBrowser(self, browserID):
        return self.__browsers.get(browserID)

    def delBrowser(self, browserID):
        if browserID in self.__browsers:
            LOG_BROWSER('CTRL: Deleting a browser: ', browserID)
            browser = self.__browsers.pop(browserID)
            self.__clearCallbacks(browserID, browser, True)
            browser.destroy()
            if self.__creatingBrowserID == browserID:
                self.__creatingBrowserID = None
                self.__tryCreateNextPendingBrowser()
            if browserID in self.__pendingBrowsers:
                del self.__pendingBrowsers[browserID]
        self.onBrowserDeleted(browserID)
        return

    def __isCreatingBrowser(self):
        return self.__creatingBrowserID is not None

    def __createDone(self, ctx):
        LOG_BROWSER('CTRL: Finished creating a browser: ',
                    self.__creatingBrowserID)
        if ctx['showCreateWaiting']:
            Waiting.hide('browser/init')

    def __tryCreateNextPendingBrowser(self):
        self.__creatingBrowserID = None
        if len(self.__pendingBrowsers) > 0:
            nextCtx = self.__pendingBrowsers.popitem()[1]
            self.__createBrowser(nextCtx)
        return

    def __createBrowser(self, ctx):
        browserID = ctx['browserID']
        LOG_BROWSER('CTRL: Creating a browser: ', browserID, ctx['url'])
        self.__creatingBrowserID = browserID
        if not self.__browsers[browserID].create():
            LOG_BROWSER('CTRL: Failed the create step: ', browserID)
            self.delBrowser(browserID)
            self.__tryCreateNextPendingBrowser()
            return
        else:
            self.onBrowserAdded(browserID)

            def createBrowserTimeout():
                LOG_BROWSER('CTRL: Browser create timed out')
                createNextBrowser()

            timeoutid = BigWorld.callback(30.0, createBrowserTimeout)

            def createNextBrowser():
                LOG_BROWSER('CTRL: Triggering create of next browser from: ',
                            browserID)
                BigWorld.cancelCallback(timeoutid)
                creation = self.__browserCreationCallbacks.pop(browserID, None)
                if creation is not None:
                    self.__browsers[
                        browserID].onCanCreateNewBrowser -= creation
                BigWorld.callback(1.0, self.__tryCreateNextPendingBrowser)
                return

            def failedCreationCallback(url):
                LOG_BROWSER('CTRL: Failed a creation: ', browserID, url)
                self.__clearCallbacks(browserID, self.__browsers[browserID],
                                      False)
                self.delBrowser(browserID)

            def successfulCreationCallback(url, isLoaded, httpStatusCode=None):
                LOG_BROWSER('CTRL: Ready to show: ', browserID, isLoaded, url)
                self.__clearCallbacks(browserID, self.__browsers[browserID],
                                      False)
                if isLoaded:
                    self.__showBrowser(browserID, ctx)
                else:
                    LOG_WARNING('Browser request url was not loaded!', url)
                g_eventBus.handleEvent(
                    BrowserEvent(BrowserEvent.BROWSER_CREATED, ctx=ctx))
                self.__createDone(ctx)

            self.__browsers[
                browserID].onCanCreateNewBrowser += createNextBrowser
            self.__browserCreationCallbacks[browserID] = createNextBrowser
            self.__browsers[
                browserID].onFailedCreation += failedCreationCallback
            if ctx['isAsync']:
                self.__browsersCallbacks[browserID] = (
                    None, successfulCreationCallback, failedCreationCallback)
                self.__browsers[
                    browserID].onLoadEnd += successfulCreationCallback
            else:
                self.__browsersCallbacks[browserID] = (
                    successfulCreationCallback, None, failedCreationCallback)
                self.__browsers[
                    browserID].onReady += successfulCreationCallback
            return

    def __stop(self):
        while self.__browsers:
            browserID, browser = self.__browsers.popitem()
            self.__clearCallbacks(browserID, browser, True)
            browser.destroy()

    def __clearCallbacks(self, browserID, browser, incDelayedCreation):
        ready, loadEnd, failed = self.__browsersCallbacks.pop(
            browserID, (None, None, None))
        if browser is not None:
            if failed is not None:
                browser.onFailedCreation -= failed
            if ready is not None:
                browser.onReady -= ready
            if loadEnd is not None:
                browser.onLoadEnd -= loadEnd
        if incDelayedCreation:
            creation = self.__browserCreationCallbacks.pop(browserID, None)
            if browser is not None and creation is not None:
                browser.onCanCreateNewBrowser -= creation
        return

    def __showBrowser(self, browserID, ctx):
        LOG_BROWSER('CTRL: Showing a browser: ', browserID, ctx['url'])
        if ctx.get('showWindow'):
            alias = ctx['alias']
            g_eventBus.handleEvent(
                LoadViewEvent(alias, getViewName(alias, browserID), ctx=ctx),
                EVENT_BUS_SCOPE.LOBBY)
        showBrowserCallback = ctx.get('showBrowserCallback')
        if showBrowserCallback:
            showBrowserCallback()
Example #27
0
class RssNewsFeed(RssNewsFeedMeta):
    UPDATE_INTERVAL = 60
    DESCRIPTION_MAX_LENGTH = 250
    DESCRIPTION_TAIL = '...'
    DESCRIPTION_CUT_LENGTH = DESCRIPTION_MAX_LENGTH - len(DESCRIPTION_TAIL)
    SHOW_NEWS_COUNT = 3
    externalBrowser = dependency.descriptor(IExternalLinksController)
    internalBrowser = dependency.descriptor(IBrowserController)

    def __init__(self):
        super(RssNewsFeed, self).__init__()
        self.__requestCbID = None
        self.__feed = []
        self.__urlMacros = URLMarcos()
        return

    def getFeed(self):
        return self.__feed

    def openBrowser(self, linkToOpen):
        if linkToOpen:
            openBrowser = self.externalBrowser.open
            if GUI_SETTINGS.loginRssFeed.internalBrowser:
                browser = self.internalBrowser
                if browser is not None:
                    openBrowser = browser.load
                else:
                    LOG_ERROR(
                        'Attempting to open internal browser, but browseris not exist. External browser will be opened',
                        str(linkToOpen))
            LOG_DEBUG('Open browser', linkToOpen)
            openBrowser(linkToOpen)
        return

    def _populate(self):
        super(RssNewsFeed, self)._populate()
        self.__updateCallback()

    def _dispose(self):
        self.__urlMacros.clear()
        self.__urlMacros = None
        self.__feed = []
        self.__clearCallback()
        super(RssNewsFeed, self)._dispose()
        return

    @process
    def __requestFeed(self):
        yield lambda callback: callback(True)
        if GUI_SETTINGS.loginRssFeed.show:
            requestUrl = yield self.__getRssUrl()
            from helpers.RSSDownloader import g_downloader as g_rss
            if g_rss is not None:
                g_rss.download(self.__onRssFeedReceived, url=requestUrl)
            LOG_DEBUG('Requesting login RSS news', requestUrl)
        return

    def __onRssFeedReceived(self, data):
        if self.isDisposed():
            return
        else:
            self.__feed = []
            for entry in reversed(data.get('entries', [])):
                data = self.__prepareData(entry)
                if data is not None:
                    self.__feed.append(data)

            LOG_DEBUG('RSS feed received, entries count', len(self.__feed))
            self.as_updateFeedS(self.__feed[:self.SHOW_NEWS_COUNT])
            return

    def __clearCallback(self):
        if self.__requestCbID is not None:
            BigWorld.cancelCallback(self.__requestCbID)
            self.__requestCbID = None
        return

    def __updateCallback(self):
        self.__requestFeed()
        self.__clearCallback()
        self.__requestCbID = BigWorld.callback(self.UPDATE_INTERVAL,
                                               self.__updateCallback)

    @async
    @process
    def __getRssUrl(self, callback):
        if constants.IS_CHINA:
            callback('http://wot.kongzhong.com/erji/login_ticker.xml')
        url = yield self.__urlMacros.parse(str(GUI_SETTINGS.loginRssFeed.url))
        callback(url)

    def __prepareData(self, entryData):
        description = entryData.get('description')
        if description is not None:
            try:
                section = ResMgr.DataSection()
                section.createSectionFromString(encodeUtf8(description))
                _, section = findFirst(lambda (name, _): name == 'div',
                                       section.items())
                description, _ = unicode_from_utf8(section.asString)
                if len(description) > self.DESCRIPTION_MAX_LENGTH:
                    description = description[:self.
                                              DESCRIPTION_CUT_LENGTH] + self.DESCRIPTION_TAIL
            except Exception:
                LOG_ERROR('Invalid RSS entry description', entryData,
                          description)
                LOG_CURRENT_EXCEPTION()
                return

        return {
            'id': entryData.get('id', str(uuid.uuid4())),
            'link': entryData.get('link'),
            'description': encodeUtf8(description)
        }
class BrowserController(Controller):
    _BROWSER_TEXTURE = 'BrowserBg'
    _ALT_BROWSER_TEXTURE = 'AltBrowserBg'

    def __init__(self, proxy):
        super(BrowserController, self).__init__(proxy)
        self.__browsers = {}
        self.__browsersCallbacks = {}
        self.__browserIDGenerator = SequenceIDGenerator()
        self.__eventMgr = Event.EventManager()
        self.onBrowserAdded = Event.Event(self.__eventMgr)
        self.onBrowserDeleted = Event.Event(self.__eventMgr)
        self.__urlMacros = URLMarcos()
        self.__pendingBrowsers = {}
        self.__creatingBrowserID = None
        self.__filters = _getGlobalFilters()
        return

    def fini(self):
        self.__filters = None
        self.__eventMgr.clear()
        self.__eventMgr = None
        self.__urlMacros.clear()
        self.__urlMacros = None
        self.__browserIDGenerator = None
        super(BrowserController, self).fini()
        return

    def onAvatarBecomePlayer(self):
        self.__stop()

    def onDisconnected(self):
        self.__stop()

    def addFilterHandler(self, handler):
        """ Adds given @handler to the browser urls filter chain. Calls
        it if there is a @tag in url onto opened browser page.
        Handler should receive url and list of client-specific tags,
        return bool as flag that routine have to stop
        """
        self.__filters.add(handler)

    def removeFilterHandler(self, handler):
        """ Remove given @handler from filtering chain. Handler description
        can be seen in addFilterhandler method doc-string
        """
        self.__filters.discard(handler)

    @async
    @process
    def load(self, url = None, title = None, showActionBtn = True, showWaiting = True, browserID = None, isAsync = False, browserSize = None, isDefault = True, callback = None, showCloseBtn = False, useBrowserWindow = True):
        url = yield self.__urlMacros.parse(url or GUI_SETTINGS.browser.url)
        suffix = yield self.__urlMacros.parse(GUI_SETTINGS.browser.params)
        concatenator = '&' if '?' in url else '?'
        if suffix not in url:
            url = concatenator.join([url, suffix])
        size = browserSize or BROWSER.SIZE
        webBrowserID = browserID
        if browserID is None:
            browserID = self.__browserIDGenerator.next()
            webBrowserID = browserID
        elif type(browserID) is not int:
            webBrowserID = self.__browserIDGenerator.next()
        ctx = {'url': url,
         'title': title,
         'showActionBtn': showActionBtn,
         'showWaiting': showWaiting,
         'browserID': browserID,
         'size': size,
         'isAsync': isAsync,
         'showCloseBtn': showCloseBtn,
         'showWindow': useBrowserWindow}
        texture = browserID not in self.__browsers and browserID not in self.__pendingBrowsers and self._BROWSER_TEXTURE
        app = g_appLoader.getApp()
        if not app:
            raise AssertionError('Application can not be None')
            browser = WebBrowser(webBrowserID, app, texture, size, url, handlers=self.__filters)
            self.__browsers[browserID] = browser
            if self.__isCreatingBrowser():
                self.__pendingBrowsers[browserID] = ctx
            else:
                self.__createBrowser(ctx)
        elif browserID in self.__pendingBrowsers:
            self.__pendingBrowsers[browserID] = ctx
        elif browserID in self.__browsers:
            self.__browsers[browserID].navigate(url)
        callback(browserID)
        return

    def getBrowser(self, browserID):
        return self.__browsers.get(browserID)

    def delBrowser(self, browserID):
        if browserID in self.__browsers:
            browser = self.__browsers.pop(browserID)
            loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None))
            if loadStart is not None:
                browser.onLoadStart -= loadStart
            if loadEnd is not None:
                browser.onLoadEnd -= loadEnd
            browser.destroy()
            if self.__creatingBrowserID == browserID:
                self.__creatingBrowserID = None
                self.__tryCreateNextPendingBrowser()
        self.onBrowserDeleted(browserID)
        return

    def __isCreatingBrowser(self):
        return self.__creatingBrowserID is not None

    def __createDone(self, ctx):
        self.__creatingBrowserID = None
        g_eventBus.handleEvent(BrowserEvent(BrowserEvent.BROWSER_CREATED, ctx=ctx))
        self.__tryCreateNextPendingBrowser()
        return

    def __tryCreateNextPendingBrowser(self):
        if len(self.__pendingBrowsers) > 0:
            nextCtx = self.__pendingBrowsers.popitem()[1]
            self.__createBrowser(nextCtx)

    def __createBrowser(self, ctx):
        browserID = ctx['browserID']
        self.__creatingBrowserID = browserID
        self.__browsers[browserID].create()
        self.onBrowserAdded(browserID)

        def browserCallback(url, isLoaded):
            self.__clearCallback(browserID)
            if isLoaded:
                self.__showBrowser(browserID, ctx)
            else:
                LOG_WARNING('Browser request url was not loaded!', url)
            self.__createDone(browserID)

        if ctx['isAsync']:
            self.__browsersCallbacks[browserID] = (None, browserCallback)
            self.__browsers[browserID].onLoadEnd += browserCallback
        else:
            self.__browsersCallbacks[browserID] = (browserCallback, None)
            self.__browsers[browserID].onReady += browserCallback
        return

    def __stop(self):
        while self.__browsers:
            browserID, browser = self.__browsers.popitem()
            ready, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None))
            if ready is not None:
                browser.onReady -= ready
            if loadEnd is not None:
                browser.onLoadEnd -= loadEnd
            browser.destroy()

        return

    def __clearCallback(self, browserID):
        ready, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None))
        if ready is not None:
            self.__browsers[browserID].onReady -= ready
        if loadEnd is not None:
            self.__browsers[browserID].onLoadEnd -= loadEnd
        return

    def __showBrowser(self, browserID, ctx):
        if ctx.get('showWindow'):
            g_eventBus.handleEvent(LoadViewEvent(VIEW_ALIAS.BROWSER_WINDOW, getViewName(VIEW_ALIAS.BROWSER_WINDOW, browserID), ctx=ctx), EVENT_BUS_SCOPE.LOBBY)
Example #29
0
class PromoController(IPromoController):
    PROMO_AUTO_VIEWS_TEST_VALUE = 5
    browserCtrl = dependency.descriptor(IBrowserController)
    eventsNotification = dependency.descriptor(IEventsNotificationsController)
    lobbyContext = dependency.descriptor(ILobbyContext)

    class GUI_EVENTS(CONST_CONTAINER):
        CLOSE_GUI_EVENT = 'close_window'

    def __init__(self):
        super(PromoController, self).__init__()
        self.__currentVersionPromoUrl = None
        self.__currentVersionBrowserID = None
        self.__currentVersionBrowserShown = False
        self.__promoShown = set()
        self.__availablePromo = set()
        self.__urlMacros = URLMarcos()
        self.__guiActionsHandlers = None
        self.__isLobbyInited = False
        self.__pendingPromo = None
        self._isPromoShown = False
        return

    def fini(self):
        self._stop()
        self.__pendingPromo = None
        self.__urlMacros.clear()
        self.__urlMacros = None
        self.__guiActionsHandlers = None
        super(PromoController, self).fini()
        return

    def onLobbyInited(self, event):
        if not isPlayerAccount():
            return
        self.__isLobbyInited = True
        self._updatePromo(self._getPromoEventNotifications())
        self.eventsNotification.onEventNotificationsChanged += self.__onEventNotification
        self.browserCtrl.onBrowserDeleted += self.__onBrowserDeleted
        popupsWindowsDisabled = isPopupsWindowsOpenDisabled()
        if not popupsWindowsDisabled:
            self._processPromo(
                self.eventsNotification.getEventsNotifications())

    def onAvatarBecomePlayer(self):
        self._stop()

    def onDisconnected(self):
        self._stop()
        self._isPromoShown = False

    @process
    def showVersionsPatchPromo(self):
        promoUrl = yield self.__urlMacros.parse(GUI_SETTINGS.promoscreens)
        webBrowser = self.__getCurrentBrowser()
        if not webBrowser or promoUrl != webBrowser.url:
            promoTitle = i18n.makeString(MENU.PROMO_PATCH_TITLE)
            self.__currentVersionBrowserID = yield self.__showPromoBrowser(
                promoUrl,
                promoTitle,
                browserID=self.__currentVersionBrowserID,
                isAsync=False,
                showWaiting=True)

    def showPromo(self, url, title, forced=False, handlers=None):
        """
        :param url: url that should be opened in the browser:
        :param title: the title of browser window:
        :param forced: True - promowindow with new URL will be shown in any case,
                       False - new promowindow will be shown
                       if there has not been already shown promowindow during the session:
        :param handlers: Dict:
                key - gui action self.GUI_EVENTS.*
                value - functions that should to be invoked when particular gui action has happened
        """
        if forced:
            self.__registerAndShowPromoBrowser(url, title, handlers)
            self._isPromoShown = True
        elif self.__isLobbyInited:
            if not self._isPromoShown:
                self.__registerAndShowPromoBrowser(url, title, handlers)
                self._isPromoShown = True
        else:
            self.__pendingPromo = _PromoData(url, title, handlers)

    def getCurrentVersionBrowserID(self):
        return self.__currentVersionBrowserID

    @classmethod
    def isPromoAutoViewsEnabled(cls):
        return getAccountDatabaseID(
        ) % cls.PROMO_AUTO_VIEWS_TEST_VALUE != 0 and cls.lobbyContext.getServerSettings(
        ).isPromoAutoViewsEnabled()

    def isPatchPromoAvailable(self):
        return self.__currentVersionPromoUrl is not None and GUI_SETTINGS.isPatchPromoEnabled

    def isPatchChanged(self):
        mainVersion = getClientMainVersion()
        return mainVersion is not None and AccountSettings.getSettings(
            LAST_PROMO_PATCH_VERSION) != mainVersion

    def _stop(self):
        self.__isLobbyInited = False
        self.__currentVersionPromoUrl = None
        self.__currentVersionBrowserID = None
        self.__currentVersionBrowserShown = False
        self.browserCtrl.onBrowserDeleted -= self.__onBrowserDeleted
        self.__cleanupGuiActionHandlers()
        self.eventsNotification.onEventNotificationsChanged -= self.__onEventNotification
        return

    @process
    def _showCurrentVersionPatchPromo(self, isAsync=False):
        self.__currentVersionBrowserID = yield self.__showPromoBrowser(
            self.__currentVersionPromoUrl,
            i18n.makeString(MENU.PROMO_PATCH_TITLE),
            browserID=self.__currentVersionBrowserID,
            isAsync=isAsync,
            showWaiting=not isAsync)

    @process
    def _processPromo(self, promo):
        yield lambda callback: callback(True)
        if self.isPatchPromoAvailable() and self.isPatchChanged(
        ) and self.isPromoAutoViewsEnabled() and not self._isPromoShown:
            LOG_DEBUG('Showing patchnote promo:',
                      self.__currentVersionPromoUrl)
            AccountSettings.setSettings(LAST_PROMO_PATCH_VERSION,
                                        getClientMainVersion())
            self.__currentVersionBrowserShown = True
            self._isPromoShown = True
            self._showCurrentVersionPatchPromo(isAsync=True)
            return
        elif not self._isPromoShown and self.__pendingPromo is not None:
            self.__registerAndShowPromoBrowser(*self.__pendingPromo)
            self.__pendingPromo = None
            return
        else:
            actionsPromo = [
                item for item in promo if item.eventType.startswith(
                    gc_constants.PROMO.TEMPLATE.ACTION)
            ]
            for actionPromo in actionsPromo:
                promoUrl = yield self.__urlMacros.parse(actionPromo.data)
                promoTitle = actionPromo.text
                if promoUrl not in self.__promoShown and not self._isPromoShown and promoUrl != self.__currentVersionPromoUrl:
                    LOG_DEBUG('Showing action promo:', promoUrl)
                    self.__promoShown.add(promoUrl)
                    self.__savePromoShown()
                    self._isPromoShown = True
                    yield self.__showPromoBrowser(promoUrl, promoTitle)
                    return

            return

    @process
    def _updatePromo(self, promosData):
        yield lambda callback: callback(True)
        for item in filter(
                lambda item: item.eventType == gc_constants.PROMO.TEMPLATE.
                ACTION, promosData):
            promoUrl = yield self.__urlMacros.parse(item.data)
            self.__availablePromo.add(promoUrl)

        if self.__currentVersionPromoUrl is None:
            self.__currentVersionPromoUrl = yield self.__urlMacros.parse(
                GUI_SETTINGS.currentVersionPromo)
        promoShownSource = AccountSettings.getFilter(PROMO)
        self.__promoShown = {
            url
            for url in promoShownSource if url in self.__availablePromo
        }
        self.__savePromoShown()
        return

    def _getPromoEventNotifications(self):
        def filterFunc(item):
            return item.eventType == gc_constants.PROMO.TEMPLATE.ACTION

        return self.eventsNotification.getEventsNotifications(filterFunc)

    def __onUserRequestToClose(self):
        self.__guiActionsHandlers[self.GUI_EVENTS.CLOSE_GUI_EVENT]()
        self.__cleanupGuiActionHandlers()

    def __savePromoShown(self):
        AccountSettings.setFilter(PROMO, self.__promoShown)

    def __onEventNotification(self, added, removed):
        self._updatePromo(self._getPromoEventNotifications())
        self._processPromo(added)

    def __onBrowserDeleted(self, browserID):
        if self.__currentVersionBrowserID == browserID:
            self.__currentVersionBrowserID = None
            if self.__currentVersionBrowserShown:
                self.__currentVersionBrowserShown = False
                g_eventBus.handleEvent(events.BubbleTooltipEvent(
                    events.BubbleTooltipEvent.SHOW,
                    i18n.makeString(TOOLTIPS.HEADER_VERSIONINFOHINT)),
                                       scope=EVENT_BUS_SCOPE.LOBBY)
        return

    def __registerGuiActionHandlers(self, handlers):
        self.__guiActionsHandlers = handlers
        if handlers:
            webBrowser = self.__getCurrentBrowser()
            if webBrowser is not None:
                webBrowser.onUserRequestToClose += self.__onUserRequestToClose
            else:
                LOG_WARNING('Browser with id = "{}" has not been found'.format(
                    self.__currentVersionBrowserID))
        return

    def __cleanupGuiActionHandlers(self):
        webBrowser = self.__getCurrentBrowser()
        if self.__guiActionsHandlers is not None and webBrowser:
            webBrowser.onUserRequestToClose -= self.__onUserRequestToClose
            self.__guiActionsHandlers = None
        return

    @process
    def __registerAndShowPromoBrowser(self, url, title, handlers):
        promoUrl = yield self.__urlMacros.parse(url)
        LOG_DEBUG('Showing promo:', promoUrl)
        webBrowser = self.__getCurrentBrowser()
        if not webBrowser or promoUrl != webBrowser.url:
            self.__cleanupGuiActionHandlers()
            self.__currentVersionBrowserID = yield self.__showPromoBrowser(
                promoUrl,
                title,
                browserID=self.__currentVersionBrowserID,
                isAsync=False,
                showWaiting=True)
            self.__registerGuiActionHandlers(handlers)

    def __getCurrentBrowser(self):
        return self.browserCtrl.getBrowser(self.__currentVersionBrowserID)

    @async
    @process
    def __showPromoBrowser(self,
                           promoUrl,
                           promoTitle,
                           browserID=None,
                           isAsync=True,
                           showWaiting=False,
                           callback=None):
        browserID = yield self.browserCtrl.load(
            promoUrl,
            promoTitle,
            showActionBtn=False,
            isAsync=isAsync,
            browserID=browserID,
            browserSize=gc_constants.BROWSER.PROMO_SIZE,
            isDefault=False,
            showCloseBtn=True,
            showWaiting=showWaiting,
            handlers=self.__createPromoWebHandlers())
        callback(browserID)

    def __createPromoWebHandlers(self):
        return [
            createHangarSoundHandler(handleHangarSoundCommand,
                                     handleHangarSoundCommandFini)
        ]
class BrowserController(Controller):
    _BROWSER_TEXTURE = 'BrowserBg'
    _ALT_BROWSER_TEXTURE = 'AltBrowserBg'

    def __init__(self, proxy):
        super(BrowserController, self).__init__(proxy)
        self.__browsers = {}
        self.__browsersCallbacks = {}
        self.__browserIDGenerator = SequenceIDGenerator()
        self.__eventMgr = Event.EventManager()
        self.onBrowserAdded = Event.Event(self.__eventMgr)
        self.onBrowserDeleted = Event.Event(self.__eventMgr)
        self.__urlMacros = URLMarcos()

    def fini(self):
        self.__eventMgr.clear()
        self.__eventMgr = None
        self.__urlMacros.clear()
        self.__urlMacros = None
        self.__browserIDGenerator = None
        super(BrowserController, self).fini()
        return

    def onAvatarBecomePlayer(self):
        self.__stop()

    def onDisconnected(self):
        self.__stop()

    @async
    @process
    def load(self, url = None, title = None, showActionBtn = True, showWaiting = True, browserID = None, isAsync = False, browserSize = None, isDefault = True, callback = None, showCloseBtn = False):
        url = yield self.__urlMacros.parse(url or GUI_SETTINGS.browser.url)
        suffix = yield self.__urlMacros.parse(GUI_SETTINGS.browser.params)
        concatenator = '&' if '?' in url else '?'
        if suffix not in url:
            url = concatenator.join([url, suffix])
        size = browserSize or BROWSER.SIZE
        if browserID is None:
            browserID = self.__browserIDGenerator.next()
        if browserID not in self.__browsers:
            texture = self._BROWSER_TEXTURE if isDefault else self._ALT_BROWSER_TEXTURE
            app = g_appLoader.getApp()
            if not app:
                raise AssertionError('Application can not be None')
                self.__browsers[browserID] = WebBrowser(browserID, app, texture, size, url)
                self.onBrowserAdded(browserID)
            ctx = {'url': url,
             'title': title,
             'showActionBtn': showActionBtn,
             'showWaiting': showWaiting,
             'browserID': browserID,
             'size': size,
             'isDefault': isDefault,
             'isAsync': isAsync,
             'showCloseBtn': showCloseBtn}

            def browserCallback(*args):
                self.__clearCallback(browserID)
                self.__showBrowser(browserID, ctx)

            def browserAsyncCallback(url, isLoaded):
                self.__clearCallback(browserID)
                if isLoaded:
                    self.__showBrowser(browserID, ctx)
                else:
                    LOG_WARNING('Browser async request url was not loaded!', url)

            self.__browsersCallbacks[browserID] = isAsync and (None, browserCallback)
            self.__browsers[browserID].onLoadEnd += browserAsyncCallback
        else:
            self.__browsersCallbacks[browserID] = (browserCallback, None)
            self.__browsers[browserID].onLoadStart += browserCallback
        callback(browserID)
        return

    def getBrowser(self, browserID):
        return self.__browsers.get(browserID)

    def delBrowser(self, browserID):
        if browserID in self.__browsers:
            browser = self.__browsers.pop(browserID)
            loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None))
            if loadStart is not None:
                browser.onLoadStart -= loadStart
            if loadEnd is not None:
                browser.onLoadEnd -= loadEnd
            browser.destroy()
        self.onBrowserDeleted(browserID)
        return

    def __stop(self):
        while self.__browsers:
            browserID, browser = self.__browsers.popitem()
            loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None))
            if loadStart is not None:
                browser.onLoadStart -= loadStart
            if loadEnd is not None:
                browser.onLoadEnd -= loadEnd
            browser.destroy()

        return

    def __clearCallback(self, browserID):
        if browserID in self.__browsersCallbacks:
            loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None))
            if loadStart is not None:
                self.__browsers[browserID].onLoadStart -= loadStart
            if loadEnd is not None:
                self.__browsers[browserID].onLoadEnd -= loadEnd
        return

    def __showBrowser(self, browserID, ctx):
        g_eventBus.handleEvent(LoadViewEvent(VIEW_ALIAS.BROWSER_WINDOW, getViewName(VIEW_ALIAS.BROWSER_WINDOW, browserID), ctx=ctx), EVENT_BUS_SCOPE.LOBBY)
class BrowserController(Controller):
    _BROWSER_TEXTURE = "BrowserBg"
    _ALT_BROWSER_TEXTURE = "AltBrowserBg"

    def __init__(self, proxy):
        super(BrowserController, self).__init__(proxy)
        self.__browsers = {}
        self.__browsersCallbacks = {}
        self.__browserIDGenerator = SequenceIDGenerator()
        self.__eventMgr = Event.EventManager()
        self.onBrowserAdded = Event.Event(self.__eventMgr)
        self.onBrowserDeleted = Event.Event(self.__eventMgr)
        self.__urlMacros = URLMarcos()

    def fini(self):
        self.__eventMgr.clear()
        self.__eventMgr = None
        self.__urlMacros.clear()
        self.__urlMacros = None
        self.__browserIDGenerator = None
        super(BrowserController, self).fini()
        return

    def onAvatarBecomePlayer(self):
        self.__stop()

    def onDisconnected(self):
        self.__stop()

    @async
    @process
    def load(
        self,
        url=None,
        title=None,
        showActionBtn=True,
        showWaiting=True,
        browserID=None,
        isAsync=False,
        browserSize=None,
        background=None,
        isDefault=True,
        callback=None,
        showCloseBtn=False,
    ):
        url = url or GUI_SETTINGS.browser.url
        suffix = yield self.__urlMacros.parse(GUI_SETTINGS.browser.params)
        concatenator = "&" if "?" in url else "?"
        if suffix not in url:
            url = concatenator.join([url, suffix])
        size = browserSize or BROWSER.SIZE
        background = background or BROWSER.BACKGROUND
        if browserID is None:
            browserID = self.__browserIDGenerator.next()
        if browserID not in self.__browsers:
            texture = self._BROWSER_TEXTURE if isDefault else self._ALT_BROWSER_TEXTURE
            app = g_appLoader.getApp()
            if not app:
                raise AssertionError("Application can not be None")
                self.__browsers[browserID] = WebBrowser(browserID, app, texture, size, url, backgroundUrl=background)
                self.onBrowserAdded(browserID)
            ctx = {
                "url": url,
                "title": title,
                "showActionBtn": showActionBtn,
                "showWaiting": showWaiting,
                "browserID": browserID,
                "size": size,
                "isDefault": isDefault,
                "isAsync": isAsync,
                "showCloseBtn": showCloseBtn,
            }

            def browserCallback(*args):
                self.__clearCallback(browserID)
                self.__showBrowser(browserID, ctx)

            self.__browsersCallbacks[browserID] = isAsync and (None, browserCallback)
            self.__browsers[browserID].onLoadEnd += browserCallback
        else:
            self.__browsersCallbacks[browserID] = (browserCallback, None)
            self.__browsers[browserID].onLoadStart += browserCallback
        callback(browserID)
        return

    def getBrowser(self, browserID):
        return self.__browsers.get(browserID)

    def delBrowser(self, browserID):
        if browserID in self.__browsers:
            browser = self.__browsers.pop(browserID)
            loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None))
            if loadStart is not None:
                browser.onLoadStart -= loadStart
            if loadEnd is not None:
                browser.onLoadEnd -= loadEnd
            browser.destroy()
        self.onBrowserDeleted(browserID)
        return

    def __stop(self):
        while self.__browsers:
            browserID, browser = self.__browsers.popitem()
            loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None))
            if loadStart is not None:
                browser.onLoadStart -= loadStart
            if loadEnd is not None:
                browser.onLoadEnd -= loadEnd
            browser.destroy()

        return

    def __clearCallback(self, browserID):
        if browserID in self.__browsersCallbacks:
            loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None))
            if loadStart is not None:
                self.__browsers[browserID].onLoadStart -= loadStart
            if loadEnd is not None:
                self.__browsers[browserID].onLoadEnd -= loadEnd
        return

    def __showBrowser(self, browserID, ctx):
        g_eventBus.handleEvent(
            LoadViewEvent(VIEW_ALIAS.BROWSER_WINDOW, getViewName(VIEW_ALIAS.BROWSER_WINDOW, browserID), ctx=ctx),
            EVENT_BUS_SCOPE.LOBBY,
        )
Example #32
0
class MarathonEvent(object):
    _eventsCache = dependency.descriptor(IEventsCache)
    _bootcamp = dependency.descriptor(IBootcampController)

    def __init__(self, data):
        super(MarathonEvent, self).__init__()
        self.__data = data
        self.__isEnabled = False
        self.__isAvailable = False
        self.__vehInInventory = False
        self.__state = ''
        self.__suspendFlag = False
        self.__quest = None
        self.__group = None
        self.__urlMacros = URLMarcos()
        self.__baseUrl = GUI_SETTINGS.lookup(data.url)
        return

    @property
    def prefix(self):
        return self.__data.prefix

    @property
    def data(self):
        return self.__data

    @prbEntityProperty
    def prbEntity(self):
        return None

    @async
    @process
    def getUrl(self, callback):
        if self.__baseUrl is None:
            LOG_ERROR(
                'Requesting URL for marathon when base URL is not specified')
            yield lambda clb: clb(None)
        else:
            url = yield self.__urlMacros.parse(self.__baseUrl)
            callback(url)
        return

    def isEnabled(self):
        return self.__isEnabled and not self._bootcamp.isInBootcamp()

    def isAvailable(self):
        return self.__isAvailable

    def getTooltipData(self):
        return self.__data.tooltips

    def getIconsData(self):
        return self.__data.icons

    def getQuestsData(self, prefix=None, postfix=None):
        return self.__getProgress('quests', prefix, postfix)

    def getTokensData(self, prefix=None, postfix=None):
        return self.__getProgress('tokens', prefix, postfix)

    def getMarathonProgress(self, byCompletedTokensCount=True):
        tokens = self.getTokensData(prefix=self.prefix,
                                    postfix=self.data.completedTokenPostfix)
        if byCompletedTokensCount:
            return (len(tokens), self.data.questsInChain)
        tokenPrefixLen = len(self.data.tokenPrefix)
        res = []
        for tokenNames in tokens.keys():
            name = str(tokenNames[tokenPrefixLen:])
            res.append(int(filter(str.isdigit, name)))

        currentStep = sorted(res)[-1] if res else 0
        return (currentStep, self.data.questsInChain)

    def getState(self):
        return self.__state

    def getTooltipHeader(self):
        if self.data.tooltipHeaderType == PROGRESS_TOOLTIP_HEADER:
            return self.getFormattedDaysStatus()
        else:
            return self.getFormattedRemainingTime(
            ) if self.data.tooltipHeaderType == COUNTDOWN_TOOLTIP_HEADER else None

    def getMarathonFlagState(self, vehicle):
        return {
            'flagHeaderIcon': self.__getHangarFlagHeaderIcon(),
            'flagStateIcon': self.__getHangarFlagStateIcon(vehicle),
            'flagMain': self.__getHangarFlagMain(),
            'tooltip': self.__getTooltip(),
            'enable': self.isAvailable(),
            'visible': self.isEnabled()
        }

    def checkForWarnings(self, _):
        wrongBattleType = self.prbEntity.getEntityType(
        ) != constants.ARENA_GUI_TYPE.RANDOM
        return MARATHON_WARNING.WRONG_BATTLE_TYPE if wrongBattleType else ''

    def isVehicleObtained(self):
        return self.__vehInInventory

    def getMarathonQuests(self):
        return self._eventsCache.getHiddenQuests(self.__marathonFilterFunc)

    def getFormattedDaysStatus(self):
        icon = RES_ICONS.MAPS_ICONS_LIBRARY_INPROGRESSICON
        text = self.__getProgressInDays(self.__getTimeFromGroupStart())
        return (icon, text)

    def getFormattedRemainingTime(self):
        firstQuestStartTimeLeft, firstQuestFinishTimeLeft = self.__getQuestTimeInterval(
        )
        if self.__state == MARATHON_STATE.NOT_STARTED:
            icon = RES_ICONS.MAPS_ICONS_LIBRARY_TIME_ICON
            text = self.__getTillTimeStart(firstQuestStartTimeLeft)
        elif self.__state == MARATHON_STATE.IN_PROGRESS:
            text = self.__getTillTimeEnd(firstQuestFinishTimeLeft)
            if firstQuestFinishTimeLeft > ONE_DAY:
                icon = RES_ICONS.MAPS_ICONS_LIBRARY_INPROGRESSICON
            else:
                icon = RES_ICONS.MAPS_ICONS_LIBRARY_TIME_ICON
        else:
            icon = RES_ICONS.MAPS_ICONS_LIBRARY_INPROGRESSICON
            text = text_styles.main(_ms(TOOLTIPS.MARATHON_STATE_COMPLETE))
        return (icon, text)

    def getExtraDaysToBuy(self):
        if self.__state == MARATHON_STATE.FINISHED:
            _, groupFinishTimeLeft = self.__getGroupTimeInterval()
            if groupFinishTimeLeft < ONE_DAY:
                groupFinishTimeLeft += ONE_DAY
            fmtText = text_styles.neutral(
                _ms(self.data.tooltips.daysShort,
                    value=str(int(groupFinishTimeLeft // ONE_DAY))))
            return fmtText

    def getMarathonDiscount(self):
        passQuests, allQuests = self.getMarathonProgress()
        return int(
            passQuests *
            100) / allQuests if passQuests and self.data.questsInChain else 0

    def isShowInPostBattle(self):
        return self.__data.showInPostBattle

    def setState(self):
        if not self.__group:
            self.__isEnabled = False
            self.__isAvailable = False
            self.__state = MARATHON_STATE.UNKNOWN
            return self.__state
        if self.__suspendFlag:
            self.__state = MARATHON_STATE.SUSPENDED
            self.__isEnabled = True
            self.__isAvailable = False
            return self.__state
        groupStartTimeLeft, groupFinishTimeLeft = self.__getGroupTimeInterval()
        zeroTime = ZERO_TIME
        if groupStartTimeLeft > zeroTime or groupFinishTimeLeft <= zeroTime:
            self.__isEnabled = False
            self.__isAvailable = False
            self.__state = MARATHON_STATE.DISABLED
            return self.__state
        if groupStartTimeLeft <= zeroTime < groupFinishTimeLeft:
            self.__isEnabled = True
            self.__isAvailable = True
        firstQuestStartTimeLeft, firstQuestFinishTimeLeft = self.__getQuestTimeInterval(
        )
        if firstQuestStartTimeLeft > zeroTime:
            self.__state = MARATHON_STATE.NOT_STARTED
        elif firstQuestStartTimeLeft <= zeroTime < firstQuestFinishTimeLeft:
            self.__state = MARATHON_STATE.IN_PROGRESS
        elif firstQuestFinishTimeLeft <= zeroTime < groupFinishTimeLeft:
            self.__state = MARATHON_STATE.FINISHED
        return self.__state

    def updateQuestsData(self):
        self.__suspendFlag = False
        quests = self._eventsCache.getHiddenQuests(self.__marathonFilterFunc)
        if quests:
            sortedIndexList = sorted(quests)
            for q in sortedIndexList:
                if self.data.suspend in q:
                    self.__suspendFlag = True
                    break

            self.__quest = quests[sortedIndexList[0]]
        groups = self._eventsCache.getGroups(self.__marathonFilterFunc)
        if groups:
            sortedGroups = sorted(groups)
            self.__group = groups[sortedGroups[0]]
        else:
            self.__group = None
        tokens = self.getTokensData(prefix=self.prefix).keys()
        self.__vehInInventory = any(
            (t in tokens for t in self.data.awardTokens))
        return

    def getClosestStatusUpdateTime(self):
        if self.__state == MARATHON_STATE.NOT_STARTED:
            timeLeft, _ = self.__getQuestTimeInterval()
            return timeLeft + 1
        if self.__state == MARATHON_STATE.IN_PROGRESS:
            _, timeLeft = self.__getQuestTimeInterval()
            return timeLeft + 1
        if self.__state == MARATHON_STATE.FINISHED:
            _, timeLeft = self.__getGroupTimeInterval()
            return timeLeft

    def __marathonFilterFunc(self, q):
        return q.getID().startswith(self.prefix)

    def __getProgress(self, progressType, prefix=None, postfix=None):
        progress = self._eventsCache.questsProgress.getCacheValue(
            progressType, {})
        if prefix:
            progress = {
                k: v
                for k, v in progress.iteritems() if k.startswith(prefix)
            }
        if postfix:
            progress = {
                k: v
                for k, v in progress.iteritems() if k.endswith(postfix)
            }
        return progress

    def __getHangarFlagHeaderIcon(self):
        for key, imgPath in MAP_FLAG_HEADER_ICON.iteritems():
            if self.__state in key:
                return imgPath

    def __getHangarFlagMain(self):
        return self.data.icons.mainHangarFlag

    def __getHangarFlagStateIcon(self, vehicle):
        if self.__state not in MARATHON_STATE.ENABLED_STATE:
            return ''
        if self.__vehInInventory:
            return self.data.icons.okIcon
        if self.__state == MARATHON_STATE.NOT_STARTED:
            return self.data.icons.timeIcon
        if self.__state == MARATHON_STATE.IN_PROGRESS:
            warning = self.checkForWarnings(vehicle)
            if warning:
                return self.data.icons.alertIcon
            _, firstQuestFinishTimeLeft = self.__getQuestTimeInterval()
            if firstQuestFinishTimeLeft > ONE_DAY:
                return self.data.icons.iconFlag
            if firstQuestFinishTimeLeft <= ONE_DAY:
                return self.data.icons.timeIcon
        return self.data.icons.saleIcon if self.__state == MARATHON_STATE.FINISHED else ''

    def __getTillTimeEnd(self, value):
        return self.__getFormattedTillTimeString(value,
                                                 self.data.tooltips.stateEnd)

    def __getTillTimeStart(self, value):
        return self.__getFormattedTillTimeString(value,
                                                 self.data.tooltips.stateStart,
                                                 extraFmt=True)

    def __getProgressInDays(self, value):
        return self.__getTextInDays(value, self.data.tooltips.stateProgress)

    def __getTextInDays(self, timeValue, keyNamespace):
        gmtime = time.gmtime(timeValue)
        text = text_styles.stats(
            _ms(self.data.tooltips.daysShort,
                value=str(time.struct_time(gmtime).tm_yday)))
        return text_styles.main(_ms(keyNamespace, value=text))

    def __getFormattedTillTimeString(self,
                                     timeValue,
                                     keyNamespace,
                                     isRoundUp=True,
                                     extraFmt=False):
        gmtime = time.gmtime(timeValue)
        if isRoundUp and gmtime.tm_sec > 0:
            timeValue += ONE_HOUR
            gmtime = time.gmtime(timeValue)
        if timeValue >= ONE_DAY:
            gmtime = time.gmtime(timeValue - ONE_DAY)
            text = text_styles.stats(
                _ms(self.data.tooltips.daysShort,
                    value=str(time.struct_time(gmtime).tm_yday)))
            return text_styles.main(_ms(keyNamespace, value=text))
        if extraFmt:
            text = text_styles.stats(
                _ms(self.data.tooltips.hoursShort,
                    value=str(time.struct_time(gmtime).tm_hour)))
            return text_styles.main(_ms(keyNamespace, value=text))
        text = _ms(self.data.tooltips.hoursShort,
                   value=str(time.struct_time(gmtime).tm_hour))
        return text_styles.tutorial(_ms(keyNamespace, value=text))

    def __getTooltip(self):
        return TOOLTIPS_CONSTANTS.MARATHON_QUESTS_PREVIEW if self.isAvailable(
        ) else TOOLTIPS.MARATHON_OFF

    def __getTimeFromGroupStart(self):
        return self.__group.getTimeFromStartTillNow(
        ) if self.__group else ZERO_TIME

    def __getGroupTimeInterval(self):
        if self.__group:
            return (self.__group.getStartTimeLeft(),
                    self.__group.getFinishTimeLeft())
        zeroTime = ZERO_TIME
        return (zeroTime, zeroTime)

    def __getQuestTimeInterval(self):
        if self.__quest:
            return (self.__quest.getStartTimeLeft(),
                    self.__quest.getFinishTimeLeft())
        zeroTime = ZERO_TIME
        return (zeroTime, zeroTime)
Example #33
0
class PromoController(IPromoController):
    PROMO_AUTO_VIEWS_TEST_VALUE = 5
    browserCtrl = dependency.descriptor(IBrowserController)
    eventsNotification = dependency.descriptor(IEventsNotificationsController)

    def __init__(self):
        super(PromoController, self).__init__()
        self.__currentVersionPromoUrl = None
        self.__currentVersionBrowserID = None
        self.__currentVersionBrowserShown = False
        self.__promoShown = set()
        self.__availablePromo = set()
        self.__urlMacros = URLMarcos()
        self._isPromoShown = False
        return

    def fini(self):
        self._stop()
        self.__urlMacros.clear()
        self.__urlMacros = None
        super(PromoController, self).fini()
        return

    def onLobbyInited(self, event):
        if not isPlayerAccount():
            return
        self._updatePromo(self._getPromoEventNotifications())
        self.eventsNotification.onEventNotificationsChanged += self.__onEventNotification
        self.browserCtrl.onBrowserDeleted += self.__onBrowserDeleted
        self._processPromo(self.eventsNotification.getEventsNotifications())

    def onAvatarBecomePlayer(self):
        self._stop()

    def onDisconnected(self):
        self._stop()
        self._isPromoShown = False

    @process
    def showCurrentVersionPatchPromo(self, isAsync=False):
        self.__currentVersionBrowserID = yield self.__showPromoBrowser(
            self.__currentVersionPromoUrl,
            i18n.makeString(MENU.PROMO_PATCH_TITLE),
            browserID=self.__currentVersionBrowserID,
            isAsync=isAsync,
            showWaiting=not isAsync)

    @process
    def showVersionsPatchPromo(self):
        promoUrl = yield self.__urlMacros.parse(GUI_SETTINGS.promoscreens)
        promoTitle = i18n.makeString(MENU.PROMO_PATCH_TITLE)
        self.__currentVersionBrowserID = yield self.__showPromoBrowser(
            promoUrl,
            promoTitle,
            browserID=self.__currentVersionBrowserID,
            isAsync=False,
            showWaiting=True)

    @process
    def showPromo(self, url, title):
        promoUrl = yield self.__urlMacros.parse(url)
        self.__currentVersionBrowserID = yield self.__showPromoBrowser(
            promoUrl,
            title,
            browserID=self.__currentVersionBrowserID,
            isAsync=False,
            showWaiting=True)

    def isPatchPromoAvailable(self):
        return self.__currentVersionPromoUrl is not None and GUI_SETTINGS.isPatchPromoEnabled

    def isPatchChanged(self):
        mainVersion = getClientMainVersion()
        return mainVersion is not None and AccountSettings.getSettings(
            LAST_PROMO_PATCH_VERSION) != mainVersion

    def _stop(self):
        self.__currentVersionPromoUrl = None
        self.__currentVersionBrowserID = None
        self.__currentVersionBrowserShown = False
        self.browserCtrl.onBrowserDeleted -= self.__onBrowserDeleted
        self.eventsNotification.onEventNotificationsChanged -= self.__onEventNotification
        return

    @process
    def _processPromo(self, promo):
        yield lambda callback: callback(True)
        if self.isPatchPromoAvailable() and self.isPatchChanged(
        ) and self.isPromoAutoViewsEnabled() and not self._isPromoShown:
            LOG_DEBUG('Showing patchnote promo:',
                      self.__currentVersionPromoUrl)
            AccountSettings.setSettings(LAST_PROMO_PATCH_VERSION,
                                        getClientMainVersion())
            self.__currentVersionBrowserShown = True
            self._isPromoShown = True
            self.showCurrentVersionPatchPromo(isAsync=True)
            return
        actionsPromo = [
            item for item in promo
            if item.eventType.startswith(gc_constants.PROMO.TEMPLATE.ACTION)
        ]
        for actionPromo in actionsPromo:
            promoUrl = yield self.__urlMacros.parse(actionPromo.data)
            promoTitle = actionPromo.text
            if promoUrl not in self.__promoShown and not self._isPromoShown and promoUrl != self.__currentVersionPromoUrl:
                LOG_DEBUG('Showing action promo:', promoUrl)
                self.__promoShown.add(promoUrl)
                self.__savePromoShown()
                self._isPromoShown = True
                yield self.__showPromoBrowser(promoUrl, promoTitle)
                return

    @process
    def _updatePromo(self, promosData):
        yield lambda callback: callback(True)
        for item in filter(
                lambda item: item.eventType == gc_constants.PROMO.TEMPLATE.
                ACTION, promosData):
            promoUrl = yield self.__urlMacros.parse(item.data)
            self.__availablePromo.add(promoUrl)

        if self.__currentVersionPromoUrl is None:
            self.__currentVersionPromoUrl = yield self.__urlMacros.parse(
                GUI_SETTINGS.currentVersionPromo)
        promoShownSource = AccountSettings.getFilter(PROMO)
        self.__promoShown = {
            url
            for url in promoShownSource if url in self.__availablePromo
        }
        self.__savePromoShown()
        return

    def _getPromoEventNotifications(self):
        def filterFunc(item):
            return item.eventType == gc_constants.PROMO.TEMPLATE.ACTION

        return self.eventsNotification.getEventsNotifications(filterFunc)

    def __savePromoShown(self):
        AccountSettings.setFilter(PROMO, self.__promoShown)

    def __onEventNotification(self, added, removed):
        self._updatePromo(self._getPromoEventNotifications())
        self._processPromo(added)

    def __onBrowserDeleted(self, browserID):
        if self.__currentVersionBrowserID == browserID:
            self.__currentVersionBrowserID = None
            if self.__currentVersionBrowserShown:
                self.__currentVersionBrowserShown = False
                g_eventBus.handleEvent(events.BubbleTooltipEvent(
                    events.BubbleTooltipEvent.SHOW,
                    i18n.makeString(TOOLTIPS.HEADER_VERSIONINFOHINT)),
                                       scope=EVENT_BUS_SCOPE.LOBBY)
        return

    @async
    @process
    def __showPromoBrowser(self,
                           promoUrl,
                           promoTitle,
                           browserID=None,
                           isAsync=True,
                           showWaiting=False,
                           callback=None):
        browserID = yield self.browserCtrl.load(
            promoUrl,
            promoTitle,
            showActionBtn=False,
            isAsync=isAsync,
            browserID=browserID,
            browserSize=gc_constants.BROWSER.PROMO_SIZE,
            isDefault=False,
            showCloseBtn=True,
            showWaiting=showWaiting)
        callback(browserID)

    @classmethod
    def isPromoAutoViewsEnabled(cls):
        return getAccountDatabaseID(
        ) % cls.PROMO_AUTO_VIEWS_TEST_VALUE != 0 and g_lobbyContext.getServerSettings(
        ).isPromoAutoViewsEnabled()
class MarathonEventController(IMarathonEventController, Notifiable):
    _eventsCache = dependency.descriptor(IEventsCache)
    _bootcamp = dependency.descriptor(IBootcampController)

    def __init__(self):
        super(MarathonEventController, self).__init__()
        self.__isEnabled = False
        self.__isAvailable = False
        self.__vehInInventory = False
        self.__state = ''
        self.__suspendFlag = False
        self.__marathonQuest = None
        self.__marathonGroup = None
        self.__urlMacros = URLMarcos()
        self.__baseUrl = GUI_SETTINGS.lookup('marathonUrl')
        self.__eventManager = Event.EventManager()
        self.onFlagUpdateNotify = Event.Event(self.__eventManager)
        return

    def fini(self):
        self.__stop()
        super(MarathonEventController, self).fini()

    def onLobbyStarted(self, ctx):
        super(MarathonEventController, self).onLobbyStarted(ctx)
        self._eventsCache.onSyncCompleted += self.__onSyncCompleted
        self._eventsCache.onProgressUpdated += self.__onSyncCompleted
        self.__onSyncCompleted()

    def onAvatarBecomePlayer(self):
        self.__stop()

    def onDisconnected(self):
        self.__stop()

    @prbEntityProperty
    def prbEntity(self):
        return None

    @async
    @process
    def getURL(self, callback):
        if self.__baseUrl is None:
            LOG_ERROR(
                'Requesting URL for marathon when base URL is not specified')
            yield lambda clb: clb(False)
        else:
            url = yield self.__urlMacros.parse(self.__baseUrl)
            callback(url)
        return

    def isEnabled(self):
        return self.__isEnabled and not self._bootcamp.isInBootcamp()

    def isAvailable(self):
        return self.__isAvailable

    def getQuestsData(self, prefix=None, postfix=None):
        return self.__getProgress('quests', prefix, postfix)

    def getTokensData(self, prefix=None, postfix=None):
        return self.__getProgress('tokens', prefix, postfix)

    def getMarathonProgress(self):
        tokens = self.getTokensData(prefix=MARATHON_PREFIX,
                                    postfix=MARATHON_COMPLETED_TOKEN_POSTFIX)
        tokenPrefixLen = len('event_marathon:IM18')
        res = []
        for tokenNames in tokens.keys():
            name = str(tokenNames[tokenPrefixLen:])
            res.append(int(filter(str.isdigit, name)))

        currentStep = sorted(res)[-1] if res else 0
        return (currentStep, MARATHON_QUESTS_IN_CHAIN)

    def getState(self):
        return self.__state

    def getMarathonFlagState(self, vehicle):
        return {
            'flagHeaderIcon': self.__getHangarFlagHeaderIcon(),
            'flagStateIcon': self.__getHangarFlagStateIcon(vehicle),
            'tooltip': self.__getTooltip(),
            'enable': self.isAvailable(),
            'visible': self.isEnabled()
        }

    def checkForWarnings(self, _):
        wrongBattleType = self.prbEntity.getEntityType(
        ) != constants.ARENA_GUI_TYPE.RANDOM
        return MARATHON_WARNING.WRONG_BATTLE_TYPE if wrongBattleType else ''

    def isVehicleObtained(self):
        return self.__vehInInventory

    def getMarathonQuests(self):
        return self._eventsCache.getHiddenQuests(marathonFilterFunc)

    def getFormattedRemainingTime(self):
        firstQuestStartTimeLeft, firstQuestFinishTimeLeft = self.__getQuestTimeInterval(
        )
        if self.__state == MARATHON_STATE.NOT_STARTED:
            icon = RES_ICONS.MAPS_ICONS_LIBRARY_TIME_ICON
            text = self.__getTillTimeStart(firstQuestStartTimeLeft)
        elif self.__state == MARATHON_STATE.IN_PROGRESS:
            text = self.__getTillTimeEnd(firstQuestFinishTimeLeft)
            if firstQuestFinishTimeLeft > ONE_DAY:
                icon = RES_ICONS.MAPS_ICONS_LIBRARY_INPROGRESSICON
            else:
                icon = RES_ICONS.MAPS_ICONS_LIBRARY_TIME_ICON
        else:
            icon = RES_ICONS.MAPS_ICONS_LIBRARY_INPROGRESSICON
            text = text_styles.main(_ms(TOOLTIPS.MARATHON_STATE_COMPLETE))
        return (icon, text)

    def getExtraDaysToBuy(self):
        if self.__state == MARATHON_STATE.FINISHED:
            _, groupFinishTimeLeft = self.__getGroupTimeInterval()
            if groupFinishTimeLeft < ONE_DAY:
                groupFinishTimeLeft += ONE_DAY
            fmtText = text_styles.neutral(
                _ms(TOOLTIPS.TEMPLATE_DAYS_SHORT,
                    value=str(int(groupFinishTimeLeft // ONE_DAY))))
            return fmtText

    def getMarathonDiscount(self):
        passQuests, allQuests = self.getMarathonProgress()
        return int(
            passQuests *
            100) / allQuests if passQuests and MARATHON_QUESTS_IN_CHAIN else 0

    def __onSyncCompleted(self, *args):
        self.__checkEvents()
        self.__reloadNotification()

    def __checkEvents(self):
        self.__updateQuestsData()
        self.__setState()

    def __setState(self):
        if not self.__marathonGroup:
            self.__isEnabled = False
            self.__isAvailable = False
            self.__state = MARATHON_STATE.UNKNOWN
            return self.__state
        if self.__suspendFlag:
            self.__state = MARATHON_STATE.SUSPENDED
            self.__isEnabled = True
            self.__isAvailable = False
            return self.__state
        groupStartTimeLeft, groupFinishTimeLeft = self.__getGroupTimeInterval()
        if groupStartTimeLeft > ZERO_TIME or groupFinishTimeLeft <= ZERO_TIME:
            self.__isEnabled = False
            self.__isAvailable = False
            self.__state = MARATHON_STATE.DISABLED
            return self.__state
        if groupStartTimeLeft <= ZERO_TIME < groupFinishTimeLeft:
            self.__isEnabled = True
            self.__isAvailable = True
        firstQuestStartTimeLeft, firstQuestFinishTimeLeft = self.__getQuestTimeInterval(
        )
        if firstQuestStartTimeLeft > ZERO_TIME:
            self.__state = MARATHON_STATE.NOT_STARTED
        elif firstQuestStartTimeLeft <= ZERO_TIME < firstQuestFinishTimeLeft:
            self.__state = MARATHON_STATE.IN_PROGRESS
        elif firstQuestFinishTimeLeft <= ZERO_TIME < groupFinishTimeLeft:
            self.__state = MARATHON_STATE.FINISHED
        return self.__state

    def __updateQuestsData(self):
        self.__suspendFlag = False
        quests = self._eventsCache.getHiddenQuests(marathonFilterFunc)
        if quests:
            sortedIndexList = sorted(quests)
            for q in sortedIndexList:
                if MARATHON_SUSPEND in q:
                    self.__suspendFlag = True
                    break

            self.__marathonQuest = quests[sortedIndexList[0]]
        groups = self._eventsCache.getGroups(marathonFilterFunc)
        if groups:
            sortedGroups = sorted(groups)
            self.__marathonGroup = groups[sortedGroups[0]]
        tokens = self.getTokensData(prefix=MARATHON_PREFIX).keys()
        self.__vehInInventory = any(
            (t in tokens for t in MARATHON_AWARD_TOKENS))

    def __getProgress(self, progressType, prefix=None, postfix=None):
        progress = self._eventsCache.questsProgress.getCacheValue(
            progressType, {})
        if prefix:
            progress = {
                k: v
                for k, v in progress.iteritems() if k.startswith(prefix)
            }
        if postfix:
            progress = {
                k: v
                for k, v in progress.iteritems() if k.endswith(postfix)
            }
        return progress

    def __getHangarFlagHeaderIcon(self):
        for key, imgPath in MAP_FLAG_HEADER_ICON.iteritems():
            if self.__state in key:
                return imgPath

    def __getHangarFlagStateIcon(self, vehicle):
        if self.__state not in MARATHON_STATE.ENABLED_STATE:
            return ''
        if self.__vehInInventory:
            return RES_ICONS.MAPS_ICONS_LIBRARY_MARATHON_OK_ICON
        if self.__state == MARATHON_STATE.NOT_STARTED:
            return RES_ICONS.MAPS_ICONS_LIBRARY_MARATHON_TIME_ICON
        if self.__state == MARATHON_STATE.IN_PROGRESS:
            warning = self.checkForWarnings(vehicle)
            if warning:
                return RES_ICONS.MAPS_ICONS_LIBRARY_MARATHON_ALERT_ICON
            _, firstQuestFinishTimeLeft = self.__getQuestTimeInterval()
            if firstQuestFinishTimeLeft > ONE_DAY:
                return RES_ICONS.MAPS_ICONS_LIBRARY_MARATHON_ICON_FLAG
            if firstQuestFinishTimeLeft <= ONE_DAY:
                return RES_ICONS.MAPS_ICONS_LIBRARY_MARATHON_TIME_ICON
        return RES_ICONS.MAPS_ICONS_LIBRARY_MARATHON_SALE_ICON if self.__state == MARATHON_STATE.FINISHED else None

    def __getTillTimeEnd(self, value):
        return self.__getFormattedTillTimeString(value,
                                                 TOOLTIPS.MARATHON_STATE_END)

    def __getTillTimeStart(self, value):
        return self.__getFormattedTillTimeString(value,
                                                 TOOLTIPS.MARATHON_STATE_START,
                                                 extraFmt=True)

    def __getFormattedTillTimeString(self,
                                     timeValue,
                                     keyNamespace,
                                     isRoundUp=True,
                                     extraFmt=False):
        gmtime = time.gmtime(timeValue)
        if isRoundUp and gmtime.tm_sec > 0:
            timeValue += ONE_HOUR
            gmtime = time.gmtime(timeValue)
        if timeValue >= ONE_DAY:
            gmtime = time.gmtime(timeValue - ONE_DAY)
            text = text_styles.stats(
                _ms(TOOLTIPS.TEMPLATE_DAYS_SHORT,
                    value=str(time.struct_time(gmtime).tm_yday)))
            return text_styles.main(_ms(keyNamespace, value=text))
        if extraFmt:
            text = text_styles.stats(
                _ms(TOOLTIPS.TEMPLATE_HOURS_SHORT,
                    value=str(time.struct_time(gmtime).tm_hour)))
            return text_styles.main(_ms(keyNamespace, value=text))
        text = _ms(TOOLTIPS.TEMPLATE_HOURS_SHORT,
                   value=str(time.struct_time(gmtime).tm_hour))
        return text_styles.tutorial(_ms(keyNamespace, value=text))

    def __getTooltip(self):
        return TOOLTIPS_CONSTANTS.MARATHON_QUESTS_PREVIEW if self.isAvailable(
        ) else TOOLTIPS.MARATHON_OFF

    def __getGroupTimeInterval(self):
        return (self.__marathonGroup.getStartTimeLeft(),
                self.__marathonGroup.getFinishTimeLeft()
                ) if self.__marathonGroup else (ZERO_TIME, ZERO_TIME)

    def __getQuestTimeInterval(self):
        return (self.__marathonQuest.getStartTimeLeft(),
                self.__marathonQuest.getFinishTimeLeft()
                ) if self.__marathonQuest else (ZERO_TIME, ZERO_TIME)

    def __stop(self):
        self.clearNotification()
        self._eventsCache.onSyncCompleted -= self.__onSyncCompleted
        self._eventsCache.onProgressUpdated -= self.__onSyncCompleted

    def __getClosestStatusUpdateTime(self):
        if self.__state == MARATHON_STATE.NOT_STARTED:
            timeLeft, _ = self.__getQuestTimeInterval()
            return timeLeft + 1
        if self.__state == MARATHON_STATE.IN_PROGRESS:
            _, timeLeft = self.__getQuestTimeInterval()
            return timeLeft + 1
        if self.__state == MARATHON_STATE.FINISHED:
            _, timeLeft = self.__getGroupTimeInterval()
            return timeLeft

    def __updateFlagState(self):
        self.__checkEvents()
        self.onFlagUpdateNotify()

    def __reloadNotification(self):
        self.clearNotification()
        timePeriod = self.__getClosestStatusUpdateTime()
        if timePeriod:
            self.addNotificator(
                PeriodicNotifier(self.__getClosestStatusUpdateTime,
                                 self.__updateFlagState))
            self.startNotification()
class ExternalLinksHandler(Controller):

    def __init__(self, proxy):
        super(ExternalLinksHandler, self).__init__(proxy)
        self.__urlMarcos = None
        return

    def init(self):
        self.__urlMarcos = URLMarcos()
        addListener = g_eventBus.addListener
        for eventType, handlerName in _LISTENERS.iteritems():
            handler = getattr(self, handlerName, None)
            if not handler:
                LOG_ERROR('Handler is not found', eventType, handlerName)
                continue
            if not callable(handler):
                LOG_ERROR('Handler is invalid', eventType, handlerName, handler)
                continue
            addListener(eventType, handler)

        return

    def fini(self):
        if self.__urlMarcos is not None:
            self.__urlMarcos.clear()
            self.__urlMarcos = None
        removeListener = g_eventBus.removeListener
        for eventType, handlerName in _LISTENERS.iteritems():
            handler = getattr(self, handlerName, None)
            if handler:
                removeListener(eventType, handler)

        super(ExternalLinksHandler, self).fini()
        return

    def open(self, url):
        if not url:
            LOG_ERROR('URL is empty', url)
            return
        try:
            BigWorld.wg_openWebBrowser(url)
        except Exception:
            LOG_ERROR('There is error while opening web browser at page:', url)
            LOG_CURRENT_EXCEPTION()

    @async
    @process
    def getURL(self, name, callback):
        urlSettings = GUI_SETTINGS.lookup(name)
        if urlSettings:
            url = yield self.__urlMarcos.parse(str(urlSettings))
        else:
            url = yield lambda callback: callback('')
        callback(url)

    def _handleSpecifiedURL(self, event):
        self.open(event.url)

    @process
    def __openParsedUrl(self, urlName):
        parsedUrl = yield self.getURL(urlName)
        self.open(parsedUrl)

    def _handleOpenRegistrationURL(self, _):
        self.__openParsedUrl('registrationURL')

    def _handleOpenRecoveryPasswordURL(self, _):
        self.__openParsedUrl('recoveryPswdURL')

    def _handleOpenPaymentURL(self, _):
        self.__openParsedUrl('paymentURL')

    def _handleSecuritySettingsURL(self, _):
        self.__openParsedUrl('securitySettingsURL')

    def _handleSupportURL(self, _):
        self.__openParsedUrl('supportURL')

    def _handleMigrationURL(self):
        self.__openParsedUrl('migrationURL')

    def _handleFortDescription(self, _):
        self.__openParsedUrl('fortDescription')

    def _handleClanSearch(self, _):
        self.__openParsedUrl('clanSearch')

    def _handleClanCreate(self, _):
        self.__openParsedUrl('clanCreate')

    def _handleClubSettings(self, _):
        self.__openParsedUrl('clubSettings')

    def _handleInvitesManagementURL(self, _):
        self.__openParsedUrl('invitesManagementURL')

    def _handleGmSummaryURL(self, _):
        self.__openParsedUrl('globalMapSummary')

    def _handleGmPromoSummaryURL(self, _):
        self.__openParsedUrl('globalMapPromoSummary')

    def _handleGmCapURL(self, _):
        self.__openParsedUrl('globalMapCap')

    def _handleGmPromoURL(self, _):
        self.__openParsedUrl('globalMapPromo')
class ExternalLinksHandler(IExternalLinksController):
    def __init__(self):
        super(ExternalLinksHandler, self).__init__()
        self.__urlMarcos = None
        return

    def init(self):
        self.__urlMarcos = URLMarcos()
        addListener = g_eventBus.addListener
        for eventType, handlerName in _LISTENERS.iteritems():
            handler = getattr(self, handlerName, None)
            if not handler:
                LOG_ERROR('Handler is not found', eventType, handlerName)
                continue
            if not callable(handler):
                LOG_ERROR('Handler is invalid', eventType, handlerName,
                          handler)
                continue
            addListener(eventType, handler)

        return

    def fini(self):
        if self.__urlMarcos is not None:
            self.__urlMarcos.clear()
            self.__urlMarcos = None
        removeListener = g_eventBus.removeListener
        for eventType, handlerName in _LISTENERS.iteritems():
            handler = getattr(self, handlerName, None)
            if handler:
                removeListener(eventType, handler)

        super(ExternalLinksHandler, self).fini()
        return

    def open(self, url):
        if not url:
            LOG_ERROR('URL is empty', url)
            return
        try:
            BigWorld.wg_openWebBrowser(url)
        except Exception:
            LOG_ERROR('There is error while opening web browser at page:', url)
            LOG_CURRENT_EXCEPTION()

    @async
    @process
    def getURL(self, name, params=None, callback=lambda *args: None):
        urlSettings = GUI_SETTINGS.lookup(name)
        if urlSettings:
            url = yield self.__urlMarcos.parse(str(urlSettings), params)
        else:
            url = yield lambda callback: callback('')
        callback(url)

    def _handleSpecifiedURL(self, event):
        self.open(event.url)

    @process
    def __openParsedUrl(self, urlName, params=None):
        parsedUrl = yield self.getURL(urlName, params)
        self.open(parsedUrl)

    def _handleOpenRegistrationURL(self, _):
        self.__openParsedUrl('registrationURL')

    def _handleOpenRecoveryPasswordURL(self, _):
        self.__openParsedUrl('recoveryPswdURL')

    def _handleOpenPaymentURL(self, _):
        self.__openParsedUrl('paymentURL')

    def _handleSecuritySettingsURL(self, _):
        self.__openParsedUrl('securitySettingsURL')

    def _handleSupportURL(self, _):
        self.__openParsedUrl('supportURL')

    def _handleMigrationURL(self):
        self.__openParsedUrl('migrationURL')

    def _handleFortDescription(self, _):
        self.__openParsedUrl('fortDescription')

    def _handleClanSearch(self, _):
        self.__openParsedUrl('clanSearch')

    def _handleClanCreate(self, _):
        self.__openParsedUrl('clanCreate')

    def _handleInvitesManagementURL(self, _):
        self.__openParsedUrl('invitesManagementURL')

    def _handleGmSummaryURL(self, _):
        self.__openParsedUrl('globalMapSummary')

    def _handleGmPromoSummaryURL(self, _):
        self.__openParsedUrl('globalMapPromoSummary')

    def _handleGmCapURL(self, _):
        self.__openParsedUrl('globalMapCap')

    def _handleGmPromoURL(self, _):
        self.__openParsedUrl('globalMapPromo')

    def _handleOpenPremShopURL(self, _):
        self.__openParsedUrl('premShopURL')

    def _handleTokenShopURL(self, event):
        self.__openParsedUrl('tokenShopURL', event.params)
class EncyclopediaController(Controller):
    """
    Manages queue of encyclopedia recommendations and activation state of encyclopedia feature
    """

    def __init__(self, proxy):
        super(EncyclopediaController, self).__init__(proxy)
        self.__activated = False
        self.__recommendations = []
        self.__eventManager = Event.EventManager()
        self.__urlMacros = URLMarcos()
        self.__isLobbyStarted = False
        self.__hasNewRecommendations = False
        if GUI_SETTINGS.lookup('encyclopedia'):
            self.__baseUrl = GUI_SETTINGS.encyclopedia['url']
            self.__isSuitableLanguage = GUI_SETTINGS.encyclopedia['enabled']
        else:
            self.__baseUrl = None
            self.__isSuitableLanguage = False
        self.onNewRecommendationReceived = Event.Event(self.__eventManager)
        self.onStateChanged = Event.Event(self.__eventManager)
        self.__isStateSynced = False
        return

    def onAccountBecomePlayer(self):
        g_settingsCache.onSyncCompleted += self.__updateRecommendations

    def onConnected(self):
        if GUI_SETTINGS.lookup('encyclopedia'):
            self.__baseUrl = GUI_SETTINGS.encyclopedia['url']
            self.__isSuitableLanguage = GUI_SETTINGS.encyclopedia['enabled']

    def onLobbyStarted(self, _):
        self.__isLobbyStarted = True
        self.__updateRecommendations()
        self.__updateActivationState()

    def onAvatarBecomePlayer(self):
        self.__isLobbyStarted = False
        g_settingsCache.onSyncCompleted -= self.__updateRecommendations

    def onDisconnected(self):
        self.__isStateSynced = False

    def fini(self):
        self.__eventManager.clear()
        super(EncyclopediaController, self).fini()

    def isActivated(self):
        return self.__activated

    def hasNewRecommendations(self):
        return self.__hasNewRecommendations

    def getRecommendations(self):
        return self.__recommendations

    def addEncyclopediaRecommendation(self, recId):
        if not self.__isLobbyStarted:
            return
        recId = int(recId)
        if 0 <= recId > _MAX_RECOMMENDATION_ID:
            LOG_ERROR('Recommendation ID is out of range', recId)
            return
        if self.__recommendations and self.__recommendations[0] == recId:
            return
        if recId in self.__recommendations:
            self.__recommendations.remove(recId)
        self.__recommendations.insert(0, recId)
        self.__recommendations = self.__recommendations[:_RECOMMENDATIONS_COUNT]
        _setEncyclopediaRecommendationsSections(self.__recommendations)
        g_settingsCore.serverSettings.setHasNewEncyclopediaRecommendations()
        self.onNewRecommendationReceived()
        if self.isActivated():
            pushI18nMessage(SYSTEM_MESSAGES.PRMP_NOTIFICATION_NEWENCYCLOPEDIARECOMMENDATION, priority=NotificationPriorityLevel.MEDIUM)

    def moveEncyclopediaRecommendationToEnd(self, recId):
        recId = int(recId)
        if recId in self.__recommendations:
            self.__recommendations.remove(recId)
            self.__recommendations.append(recId)
            _setEncyclopediaRecommendationsSections(self.__recommendations)

    def resetHasNew(self):
        self.__hasNewRecommendations = False
        g_settingsCore.serverSettings.setHasNewEncyclopediaRecommendations(False)

    @async
    @process
    def buildUrl(self, callback):
        if self.__baseUrl is None:
            LOG_ERROR('Requesting URL for encyclopedia when base URL is not specified')
            yield lambda clb: clb(False)
        else:
            queryParams = {'id': self.getRecommendations()}
            url = yield self.__urlMacros.parse(self.__baseUrl)
            callback(addParamsToUrlQuery(url, queryParams))
        return

    def __updateRecommendations(self):
        self.__recommendations = _getEncyclopediaRecommendations()
        self.__hasNewRecommendations = g_settingsCore.serverSettings.getHasNewEncyclopediaRecommendations()

    def __updateActivationState(self, *_):
        if self.__baseUrl is None or not self.__isSuitableLanguage or self.__isStateSynced:
            return False
        else:
            tokensCount = g_eventsCache.questsProgress.getTokenCount(_ACTIVATION_TOKEN)
            newState = g_lobbyContext.getServerSettings().isEncyclopediaEnabled(tokensCount)
            self.__isStateSynced = True
            if newState != self.__activated:
                self.__activated = newState
                self.onStateChanged()
            return
class PersonalMissionFirstEntryView(LobbySubView,
                                    PersonalMissionFirstEntryViewMeta):
    browserCtrl = dependency.descriptor(IBrowserController)
    _COMMON_SOUND_SPACE = PERSONAL_MISSIONS_SOUND_SPACE
    __settingsCore = dependency.descriptor(ISettingsCore)
    __CARDS = (3, 3, 4, 4)

    def __init__(self, ctx):
        super(PersonalMissionFirstEntryView, self).__init__(ctx)
        self.__currentVersionBrowserID = None
        self.__urlMacros = URLMarcos()
        self.__settings = GUI_SETTINGS.personalMissions.get('welcomeVideo', {})
        self.__cardsLen = len(self.__CARDS)
        return

    def playVideo(self):
        if self.__settings.get('isEnabled', False):
            self.__showVideo()

    def backBtnClicked(self):
        self.__currentVersionBrowserID = None
        self.fireEvent(events.LoadViewEvent(
            VIEW_ALIAS.LOBBY_PERSONAL_MISSIONS),
                       scope=EVENT_BUS_SCOPE.LOBBY)
        return

    def onViewClose(self, isAcceptBtnClick=False):
        if isAcceptBtnClick:
            self.__settingsCore.serverSettings.saveInUIStorage(
                {PM_TUTOR_FIELDS.GREETING_SCREEN_SHOWN: True})
            self.fireEvent(events.LoadViewEvent(
                VIEW_ALIAS.LOBBY_PERSONAL_MISSIONS),
                           scope=EVENT_BUS_SCOPE.LOBBY)
        else:
            self.fireEvent(events.LoadViewEvent(VIEW_ALIAS.LOBBY_HANGAR),
                           scope=EVENT_BUS_SCOPE.LOBBY)

    def onCardClick(self, cardIndex):
        self.__updateDetailedData(cardIndex)

    def onNextCardClick(self, cardIndex):
        self.__updateDetailedData(cardIndex + 1)

    def onPrevCardClick(self, cardIndex):
        self.__updateDetailedData(cardIndex - 1)

    def _populate(self):
        super(PersonalMissionFirstEntryView, self)._populate()
        infoBlocks = [
            self.__makeTileData(cardIndex)
            for cardIndex in xrange(0, self.__cardsLen)
        ]
        firstEntry = not self.__settingsCore.serverSettings.getUIStorage().get(
            PM_TUTOR_FIELDS.GREETING_SCREEN_SHOWN)
        self.as_setInitDataS({
            'titleLabel':
            PERSONAL_MISSIONS.PERSONALMISSIONFIRSTENTRYVIEW_TITLE,
            'bigBtnLabel':
            PERSONAL_MISSIONS.PERSONALMISSIONFIRSTENTRYVIEW_ACKNOWLEDGEBTN,
            'playVideoBtnLabel':
            text_styles.concatStylesToSingleLine(
                icons.makeImageTag(
                    RES_ICONS.MAPS_ICONS_PERSONALMISSIONS_PLAYICON,
                    width=14,
                    height=15,
                    vSpace=-2),
                i18n.makeString(PERSONAL_MISSIONS.
                                PERSONALMISSIONFIRSTENTRYVIEW_VIDEOBTNLABEL)),
            'playVideoBtnVisible':
            self.__settings.get('isEnabled', False),
            'bgSource':
            RES_ICONS.MAPS_ICONS_PERSONALMISSIONS_INFOSCREENBG,
            'infoBlocks':
            infoBlocks,
            'backBtnLabel':
            PERSONAL_MISSIONS.HEADER_BACKBTN_LABEL,
            'isFirstEntry':
            firstEntry
        })
        self.soundManager.setRTPC(SOUNDS.RTCP_OVERLAY,
                                  SOUNDS.MAX_MISSIONS_ZOOM)

    def _dispose(self):
        self.soundManager.setRTPC(SOUNDS.RTCP_OVERLAY,
                                  SOUNDS.MIN_MISSIONS_ZOOM)
        super(PersonalMissionFirstEntryView, self)._dispose()

    def __updateDetailedData(self, cardIndex):
        cardIndex = self.__normalizeSlotIndex(cardIndex)
        blocksLen = self.__CARDS[cardIndex]
        blocks = []
        for blockIndex in xrange(0, blocksLen):
            blocks.append({
                'title':
                PERSONAL_MISSIONS.getBlockTitle(cardIndex, blockIndex),
                'description':
                PERSONAL_MISSIONS.getBlockDescription(cardIndex, blockIndex),
                'image':
                RES_ICONS.getBlockImageByStep(cardIndex, blockIndex)
            })

        data = {
            'index':
            cardIndex,
            'icon':
            RES_ICONS.getInfoIcon(cardIndex),
            'title':
            PERSONAL_MISSIONS.getCardHeader(cardIndex),
            'description':
            PERSONAL_MISSIONS.getCardInnerDescription(cardIndex),
            'blocks':
            blocks,
            'notificationIcon':
            RES_ICONS.MAPS_ICONS_LIBRARY_WARNINGICON_1,
            'notificationLabel':
            i18n.makeString(PERSONAL_MISSIONS.getBlockWarning(cardIndex))
        }
        self.as_setDetailedCardDataS(data)

    @process
    def __showVideo(self):
        url = yield self.__urlMacros.parse(self.__settings.get('url'))
        webBrowser = self.__getCurrentBrowser()
        if not webBrowser or url != webBrowser.url:
            title = i18n.makeString(
                PERSONAL_MISSIONS.PERSONALMISSIONS_VIDEO_TITLE)
            self.__currentVersionBrowserID = yield self.browserCtrl.load(
                url,
                title,
                showActionBtn=False,
                browserID=self.__currentVersionBrowserID,
                browserSize=gc_constants.BROWSER.VIDEO_SIZE,
                isDefault=False,
                showCloseBtn=True,
                handlers=webApiCollection(HangarSoundWebApi))

    @staticmethod
    def __makeTileData(cardIndex):
        return {
            'index': cardIndex,
            'iconSource': RES_ICONS.getInfoIcon(cardIndex),
            'titleLabel': PERSONAL_MISSIONS.getCardHeader(cardIndex),
            'descriptionLabel': PERSONAL_MISSIONS.getCardDescription(cardIndex)
        }

    def __getCurrentBrowser(self):
        return self.browserCtrl.getBrowser(self.__currentVersionBrowserID)

    def __normalizeSlotIndex(self, slotIndex):
        if slotIndex >= self.__cardsLen:
            return 0
        return self.__cardsLen - 1 if slotIndex < 0 else slotIndex
Example #39
0
class RssNewsFeed(RssNewsFeedMeta):
    UPDATE_INTERVAL = 60
    DESCRIPTION_MAX_LENGTH = 250
    DESCRIPTION_TAIL = '...'
    DESCRIPTION_CUT_LENGTH = DESCRIPTION_MAX_LENGTH - len(DESCRIPTION_TAIL)
    SHOW_NEWS_COUNT = 3

    def __init__(self):
        super(RssNewsFeed, self).__init__()
        self.__requestCbID = None
        self.__feed = []
        self.__urlMacros = URLMarcos()
        return

    def getFeed(self):
        return self.__feed

    def openBrowser(self, linkToOpen):
        if linkToOpen:
            openBrowser = game_control.g_instance.links.open
            if GUI_SETTINGS.loginRssFeed.internalBrowser:
                browser = game_control.g_instance.browser
                if browser is not None:
                    openBrowser = browser.load
                else:
                    LOG_ERROR('Attempting to open internal browser, but browseris not exist. External browser will be opened', str(linkToOpen))
            LOG_DEBUG('Open browser', linkToOpen)
            openBrowser(linkToOpen)
        return

    def _populate(self):
        super(RssNewsFeed, self)._populate()
        self.__updateCallback()

    def _dispose(self):
        self.__urlMacros.clear()
        self.__urlMacros = None
        self.__feed = []
        self.__clearCallback()
        super(RssNewsFeed, self)._dispose()
        return

    @process
    def __requestFeed(self):
        yield lambda callback: callback(True)
        if GUI_SETTINGS.loginRssFeed.show:
            requestUrl = yield self.__getRssUrl()
            from helpers.RSSDownloader import g_downloader as g_rss
            if g_rss is not None:
                g_rss.download(self.__onRssFeedReceived, url=requestUrl)
            LOG_DEBUG('Requesting login RSS news', requestUrl)
        return

    def __onRssFeedReceived(self, data):
        if self.isDisposed():
            return
        else:
            self.__feed = []
            for entry in reversed(data.get('entries', [])):
                data = self.__prepareData(entry)
                if data is not None:
                    self.__feed.append(data)

            LOG_DEBUG('RSS feed received, entries count', len(self.__feed))
            self.as_updateFeedS(self.__feed[:self.SHOW_NEWS_COUNT])
            return

    def __clearCallback(self):
        if self.__requestCbID is not None:
            BigWorld.cancelCallback(self.__requestCbID)
            self.__requestCbID = None
        return

    def __updateCallback(self):
        self.__requestFeed()
        self.__clearCallback()
        self.__requestCbID = BigWorld.callback(self.UPDATE_INTERVAL, self.__updateCallback)

    @async
    @process
    def __getRssUrl(self, callback):
        if constants.IS_CHINA:
            callback('http://wot.kongzhong.com/erji/login_ticker.xml')
        url = yield self.__urlMacros.parse(str(GUI_SETTINGS.loginRssFeed.url))
        callback(url)

    def __prepareData(self, entryData):
        description = entryData.get('description')
        if description is not None:
            try:
                section = ResMgr.DataSection()
                section.createSectionFromString(encodeUtf8(description))
                _, section = findFirst(lambda (name, _): name == 'div', section.items())
                description, _ = unicode_from_utf8(section.asString)
                if len(description) > self.DESCRIPTION_MAX_LENGTH:
                    description = description[:self.DESCRIPTION_CUT_LENGTH] + self.DESCRIPTION_TAIL
            except Exception:
                LOG_ERROR('Invalid RSS entry description', entryData, description)
                LOG_CURRENT_EXCEPTION()
                return

        return {'id': entryData.get('id', str(uuid.uuid4())),
         'link': entryData.get('link'),
         'description': encodeUtf8(description)}
Example #40
0
 def __init__(self):
     super(RssNewsFeed, self).__init__()
     self.__requestCbID = None
     self.__feed = []
     self.__urlMacros = URLMarcos()
     return
Example #41
0
 def __init__(self):
     super(RssNewsFeed, self).__init__()
     self.__requestCbID = None
     self.__feed = []
     self.__urlMacros = URLMarcos()
     return
class EncyclopediaController(IEncyclopediaController):
    eventsCache = dependency.descriptor(IEventsCache)
    settingsCache = dependency.descriptor(ISettingsCache)
    settingsCore = dependency.descriptor(ISettingsCore)
    lobbyContext = dependency.descriptor(ILobbyContext)

    def __init__(self):
        super(EncyclopediaController, self).__init__()
        self.__activated = False
        self.__recommendations = []
        self.__eventManager = Event.EventManager()
        self.__urlMacros = URLMarcos()
        self.__isLobbyStarted = False
        self.__hasNewRecommendations = False
        if GUI_SETTINGS.lookup('encyclopedia'):
            self.__baseUrl = GUI_SETTINGS.encyclopedia['url']
            self.__isSuitableLanguage = getClientLanguage(
            ) in GUI_SETTINGS.encyclopedia.get('languages', ())
        else:
            self.__baseUrl = None
            self.__isSuitableLanguage = False
        self.onNewRecommendationReceived = Event.Event(self.__eventManager)
        self.onStateChanged = Event.Event(self.__eventManager)
        self.__isStateSynced = False
        return

    def onAccountBecomePlayer(self):
        self.settingsCache.onSyncCompleted += self.__updateRecommendations

    def onConnected(self):
        if GUI_SETTINGS.lookup('encyclopedia'):
            self.__baseUrl = GUI_SETTINGS.encyclopedia['url']
            self.__isSuitableLanguage = getClientLanguage(
            ) in GUI_SETTINGS.encyclopedia.get('languages', ())

    def onLobbyStarted(self, _):
        self.__isLobbyStarted = True
        self.__updateRecommendations()
        self.__updateActivationState()

    def onAvatarBecomePlayer(self):
        self.__isLobbyStarted = False
        self.settingsCache.onSyncCompleted -= self.__updateRecommendations

    def onDisconnected(self):
        self.__isStateSynced = False

    def fini(self):
        self.__eventManager.clear()
        super(EncyclopediaController, self).fini()

    def isActivated(self):
        return self.__activated

    def hasNewRecommendations(self):
        return self.__hasNewRecommendations

    def getRecommendations(self):
        return self.__recommendations

    def addEncyclopediaRecommendation(self, recId):
        if not self.__isLobbyStarted:
            return
        recId = int(recId)
        if 0 <= recId > _MAX_RECOMMENDATION_ID:
            LOG_ERROR('Recommendation ID is out of range', recId)
            return
        if self.__recommendations and self.__recommendations[0] == recId:
            return
        if recId in self.__recommendations:
            self.__recommendations.remove(recId)
        self.__recommendations.insert(0, recId)
        self.__recommendations = self.__recommendations[:
                                                        _RECOMMENDATIONS_COUNT]
        _setEncyclopediaRecommendationsSections(self.__recommendations,
                                                self.settingsCore)
        self.settingsCore.serverSettings.setHasNewEncyclopediaRecommendations()
        self.onNewRecommendationReceived()
        if self.isActivated():
            pushI18nMessage(SYSTEM_MESSAGES.
                            PRMP_NOTIFICATION_NEWENCYCLOPEDIARECOMMENDATION,
                            priority=NotificationPriorityLevel.MEDIUM)

    def moveEncyclopediaRecommendationToEnd(self, recId):
        recId = int(recId)
        if recId in self.__recommendations:
            self.__recommendations.remove(recId)
            self.__recommendations.append(recId)
            _setEncyclopediaRecommendationsSections(self.__recommendations,
                                                    self.settingsCore)

    def resetHasNew(self):
        self.__hasNewRecommendations = False
        self.settingsCore.serverSettings.setHasNewEncyclopediaRecommendations(
            False)

    @async
    @process
    def buildUrl(self, callback):
        if self.__baseUrl is None:
            LOG_ERROR(
                'Requesting URL for encyclopedia when base URL is not specified'
            )
            yield lambda clb: clb(False)
        else:
            queryParams = {'id': self.getRecommendations()}
            url = yield self.__urlMacros.parse(self.__baseUrl)
            callback(addParamsToUrlQuery(url, queryParams))
        return

    def __updateRecommendations(self):
        self.__recommendations = _getEncyclopediaRecommendations(
            self.settingsCore)
        self.__hasNewRecommendations = self.settingsCore.serverSettings.getHasNewEncyclopediaRecommendations(
        )

    def __updateActivationState(self, *_):
        if self.__baseUrl is None or not self.__isSuitableLanguage or self.__isStateSynced:
            return False
        else:
            tokensCount = self.eventsCache.questsProgress.getTokenCount(
                _ACTIVATION_TOKEN)
            newState = self.lobbyContext.getServerSettings(
            ).isEncyclopediaEnabled(tokensCount)
            self.__isStateSynced = True
            if newState != self.__activated:
                self.__activated = newState
                self.onStateChanged()
            return
Example #43
0
class CalendarController(ICalendarController):
    """Advent calendar controller.
    
    This controller shows the in-game browser pointing to the advent calendar web-app in following scenarios:
      * The player clicks on related item in the Hangar.
      * The player clicks on related Action in the Shop.
      * On lobby startup once in a day, if allowed by server.
    """
    browserCtrl = dependency.descriptor(IBrowserController)
    eventsCache = dependency.descriptor(IEventsCache)

    def __init__(self):
        super(CalendarController, self).__init__()
        self.__browserID = None
        self.__browserLoaded = False
        self.__showOnSplash = False
        self.__urlMacros = URLMarcos()
        return

    def init(self):
        self.eventsCache.onSyncCompleted += self.__onSyncCompleted
        self.browserCtrl.onBrowserDeleted += self.__onBrowserDeleted
        g_eventBus.addListener(events.BrowserEvent.BROWSER_CREATED, self.__onBrowserCreated)

    def fini(self):
        self.__urlMacros.clear()
        self.__urlMacros = None
        self.hideCalendar()
        g_eventBus.removeListener(events.BrowserEvent.BROWSER_CREATED, self.__onBrowserCreated)
        self.browserCtrl.onBrowserDeleted -= self.__onBrowserDeleted
        self.eventsCache.onSyncCompleted -= self.__onSyncCompleted
        super(CalendarController, self).fini()
        return

    def onLobbyStarted(self, event):
        if self.__showOnSplash:
            lastShowTstamp = self.__getShowTimestamp()
            now = time_utils.getServerUTCTime()
            if lastShowTstamp is not None:
                today = time_utils.getDayTimeBoundsForUTC(now)[0]
                offset = _START_OF_DAY_OFFSET.get(constants.CURRENT_REALM, timedelta(0)).total_seconds()
                dayStart = today + offset
                mustShow = lastShowTstamp < dayStart <= now or lastShowTstamp > now
            else:
                mustShow = True
            if mustShow:
                self.showCalendar(CalendarInvokeOrigin.SPLASH)
                self.__setShowTimestamp(now)
        return

    def onAvatarBecomePlayer(self):
        self.hideCalendar()

    def onDisconnected(self):
        self.hideCalendar()

    def showCalendar(self, invokedFrom):
        """Show the advent calendar in browser window."""
        if self.__browserID is not None:
            if self.__browserLoaded:
                _logger.debug('Calendar already opened, bringing window to focus (browserID=%d)' % self.__browserID)
                g_eventBus.handleEvent(events.LoadViewEvent(VIEW_ALIAS.ADVENT_CALENDAR, name=_genWindowName(self.__browserID)), scope=EVENT_BUS_SCOPE.LOBBY)
            return
        else:
            try:
                while self.__browserID is None:
                    browserID = next(_browserIDGen)
                    if self.browserCtrl.getBrowser(browserID) is None:
                        self.__browserID = browserID

            except StopIteration:
                _logger.error('Could not allocate a browser ID for calendar')
                return

            self.__openBrowser(self.__browserID, _BROWSER_SIZE, invokedFrom)
            _logger.debug('Calendar opening scheduled (browserID=%d)' % self.__browserID)
            return

    def hideCalendar(self):
        if self.__browserID is None:
            return
        else:
            self.browserCtrl.delBrowser(self.__browserID)
            return

    def __onSyncCompleted(self, *_):

        def calendarEnabledActionFilter(act):
            return any((isinstance(mod, CalendarSplashModifier) for mod in act.getModifiers()))

        self.__showOnSplash = len(self.eventsCache.getActions(calendarEnabledActionFilter)) > 0

    def __onBrowserDeleted(self, browserID):
        if browserID == self.__browserID:
            _logger.debug('Calendar WebBrowser instance destroyed (browserID=%d)' % browserID)
            self.__browserID = None
            self.__browserLoaded = False
        return

    def __onBrowserCreated(self, event):
        browserID = event.ctx.get('browserID')
        if browserID == self.__browserID:
            _logger.debug('Calendar WebBrowser instance created (browserID=%d)' % browserID)
            browser = self.browserCtrl.getBrowser(browserID)
            browser.useSpecialKeys = False
            self.__browserLoaded = True

    def __getShowTimestamp(self):
        tstampStr = AccountSettings.getSettings(LAST_CALENDAR_SHOW_TIMESTAMP)
        if tstampStr:
            try:
                return float(tstampStr)
            except (TypeError, ValueError):
                _logger.warning('Invalid calendar show timestamp')

        return None

    def __setShowTimestamp(self, tstamp):
        AccountSettings.setSettings(LAST_CALENDAR_SHOW_TIMESTAMP, str(tstamp))

    @process
    def __openBrowser(self, browserID, browserSize, invokedFrom):
        """Shows the event calendar browser window, pointing to remote calendar
        single-page web application.
        """
        url = yield self.__urlMacros.parse(GUI_SETTINGS.adventCalendarBaseURL, params={'called': invokedFrom})
        if not url:
            _logger.error('Invalid calendar URL')
            return
        browserHandlers = [createRequestHandler(handleRequestCommand)]

        def showBrowserWindow():
            ctx = {'size': browserSize,
             'handlers': browserHandlers,
             'browserID': browserID,
             'alias': VIEW_ALIAS.ADVENT_CALENDAR,
             'showCloseBtn': False,
             'showWaiting': True,
             'showActionBtn': False}
            g_eventBus.handleEvent(events.LoadViewEvent(VIEW_ALIAS.ADVENT_CALENDAR, name=_genWindowName(browserID), ctx=ctx), scope=EVENT_BUS_SCOPE.LOBBY)
            _logger.debug('Calendar browser window shown (browserID=%d)' % browserID)

        yield self.browserCtrl.load(url=url, browserID=browserID, browserSize=browserSize, isAsync=False, useBrowserWindow=False, showBrowserCallback=showBrowserWindow, showCreateWaiting=False)
class BrowserController(Controller):
    _BROWSER_TEXTURE = 'BrowserBg'
    _ALT_BROWSER_TEXTURE = 'AltBrowserBg'

    def __init__(self, proxy):
        super(BrowserController, self).__init__(proxy)
        self.__browsers = {}
        self.__browsersCallbacks = {}
        self.__browserIDGenerator = SequenceIDGenerator()
        self.__eventMgr = Event.EventManager()
        self.onBrowserAdded = Event.Event(self.__eventMgr)
        self.onBrowserDeleted = Event.Event(self.__eventMgr)
        self.__urlMacros = URLMarcos()
        self.__pendingBrowsers = {}
        self.__creatingBrowser = False

    def fini(self):
        self.__eventMgr.clear()
        self.__eventMgr = None
        self.__urlMacros.clear()
        self.__urlMacros = None
        self.__browserIDGenerator = None
        super(BrowserController, self).fini()
        return

    def onAvatarBecomePlayer(self):
        self.__stop()

    def onDisconnected(self):
        self.__stop()

    @async
    @process
    def load(self, url = None, title = None, showActionBtn = True, showWaiting = True, browserID = None, isAsync = False, browserSize = None, isDefault = True, callback = None, showCloseBtn = False, useWhitelisting = False):
        url = yield self.__urlMacros.parse(url or GUI_SETTINGS.browser.url)
        suffix = yield self.__urlMacros.parse(GUI_SETTINGS.browser.params)
        concatenator = '&' if '?' in url else '?'
        if suffix not in url:
            url = concatenator.join([url, suffix])
        size = browserSize or BROWSER.SIZE
        webBrowserID = browserID
        if browserID is None:
            browserID = self.__browserIDGenerator.next()
            webBrowserID = browserID
        elif type(browserID) is not int:
            webBrowserID = self.__browserIDGenerator.next()
        ctx = {'url': url,
         'title': title,
         'showActionBtn': showActionBtn,
         'showWaiting': showWaiting,
         'browserID': browserID,
         'size': size,
         'isDefault': isDefault,
         'isAsync': isAsync,
         'showCloseBtn': showCloseBtn}
        texture = browserID not in self.__browsers and browserID not in self.__pendingBrowsers and (self._BROWSER_TEXTURE if isDefault else self._ALT_BROWSER_TEXTURE)
        app = g_appLoader.getApp()
        if not app:
            raise AssertionError('Application can not be None')
            browser = WebBrowser(webBrowserID, app, texture, size, url, useWhitelisting)
            self.__browsers[browserID] = browser
            if self.__creatingBrowser:
                self.__pendingBrowsers[browserID] = ctx
            else:
                self.__createBrowser(ctx)
        elif browserID in self.__pendingBrowsers:
            self.__pendingBrowsers[browserID] = ctx
        elif browserID in self.__browsers:
            self.__browsers[browserID].navigate(url)
        callback(browserID)
        return

    def __createDone(self, browserID):
        self.__creatingBrowser = False
        if len(self.__pendingBrowsers) > 0:
            ctx = self.__pendingBrowsers.popitem()[1]
            self.__createBrowser(ctx)

    def __createBrowser(self, ctx):
        self.__creatingBrowser = True
        browserID = ctx['browserID']
        self.__browsers[browserID].create()
        self.onBrowserAdded(browserID)

        def browserCallback(*args):
            self.__clearCallback(browserID)
            self.__showBrowser(browserID, ctx)
            self.__createDone(browserID)

        def browserAsyncCallback(url, isLoaded):
            self.__clearCallback(browserID)
            if isLoaded:
                self.__showBrowser(browserID, ctx)
            else:
                LOG_WARNING('Browser async request url was not loaded!', url)
            self.__createDone(browserID)

        if ctx['isAsync']:
            self.__browsersCallbacks[browserID] = (None, browserAsyncCallback)
            self.__browsers[browserID].onLoadEnd += browserAsyncCallback
        else:
            self.__browsersCallbacks[browserID] = (browserCallback, None)
            self.__browsers[browserID].onReady += browserCallback
        return

    def getBrowser(self, browserID):
        return self.__browsers.get(browserID)

    def delBrowser(self, browserID):
        if browserID in self.__browsers:
            browser = self.__browsers.pop(browserID)
            loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None))
            if loadStart is not None:
                browser.onLoadStart -= loadStart
            if loadEnd is not None:
                browser.onLoadEnd -= loadEnd
            browser.destroy()
        self.onBrowserDeleted(browserID)
        return

    def __stop(self):
        while self.__browsers:
            browserID, browser = self.__browsers.popitem()
            ready, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None))
            if ready is not None:
                browser.onReady -= ready
            if loadEnd is not None:
                browser.onLoadEnd -= loadEnd
            browser.destroy()

        return

    def __clearCallback(self, browserID):
        ready, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None))
        if ready is not None:
            self.__browsers[browserID].onReady -= ready
        if loadEnd is not None:
            self.__browsers[browserID].onLoadEnd -= loadEnd
        return

    def __showBrowser(self, browserID, ctx):
        g_eventBus.handleEvent(LoadViewEvent(VIEW_ALIAS.BROWSER_WINDOW, getViewName(VIEW_ALIAS.BROWSER_WINDOW, browserID), ctx=ctx), EVENT_BUS_SCOPE.LOBBY)
Example #45
0
class BrowserController(Controller, AppRef):
    _BROWSER_TEXTURE = 'BrowserBg'
    _ALT_BROWSER_TEXTURE = 'AltBrowserBg'

    def __init__(self, proxy):
        super(BrowserController, self).__init__(proxy)
        self.__browsers = {}
        self.__browsersCallbacks = {}
        self.__browserIDGenerator = SequenceIDGenerator()
        self.__eventMgr = Event.EventManager()
        self.onBrowserAdded = Event.Event(self.__eventMgr)
        self.onBrowserDeleted = Event.Event(self.__eventMgr)
        self.__urlMacros = URLMarcos()

    def fini(self):
        self.__eventMgr.clear()
        self.__eventMgr = None
        self.__urlMacros.clear()
        self.__urlMacros = None
        self.__browserIDGenerator = None
        super(BrowserController, self).fini()
        return

    def onBattleStarted(self):
        self.__stop()

    def onDisconnected(self):
        self.__stop()

    @async
    @process
    def load(self, url = None, title = None, showActionBtn = True, showWaiting = True, browserID = None, isAsync = False, browserSize = None, background = None, isDefault = True, callback = None):
        url = url or GUI_SETTINGS.browser.url
        suffix = yield self.__urlMacros.parse(GUI_SETTINGS.browser.params)
        concatenator = '&' if '?' in url else '?'
        if suffix not in url:
            url = concatenator.join([url, suffix])
        size = browserSize or BROWSER.SIZE
        background = background or BROWSER.BACKGROUND
        if browserID not in self.__browsers:
            browserID = self.__browserIDGenerator.next()
            texture = self._BROWSER_TEXTURE if isDefault else self._ALT_BROWSER_TEXTURE
            self.__browsers[browserID] = WebBrowser(browserID, self.app, texture, size, url, backgroundUrl=background)
            self.onBrowserAdded(browserID)
        ctx = {'url': url,
         'title': title,
         'showActionBtn': showActionBtn,
         'showWaiting': showWaiting,
         'browserID': browserID,
         'size': size,
         'isDefault': isDefault,
         'isAsync': isAsync}

        def browserCallback(*args):
            self.__clearCallback(browserID)
            self.__showBrowser(browserID, ctx)

        if isAsync:
            self.__browsersCallbacks[browserID] = (None, browserCallback)
            self.__browsers[browserID].onLoadEnd += browserCallback
        else:
            self.__browsersCallbacks[browserID] = (browserCallback, None)
            self.__browsers[browserID].onLoadStart += browserCallback
        callback(browserID)
        return

    def getBrowser(self, browserID):
        return self.__browsers.get(browserID)

    def delBrowser(self, browserID):
        if browserID in self.__browsers:
            browser = self.__browsers.pop(browserID)
            loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None))
            if loadStart is not None:
                browser.onLoadStart -= loadStart
            if loadEnd is not None:
                browser.onLoadEnd -= loadEnd
            browser.destroy()
        self.onBrowserDeleted(browserID)
        return

    def __stop(self):
        while self.__browsers:
            browserID, browser = self.__browsers.popitem()
            loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None))
            if loadStart is not None:
                browser.onLoadStart -= loadStart
            if loadEnd is not None:
                browser.onLoadEnd -= loadEnd
            browser.destroy()

        return

    def __clearCallback(self, browserID):
        if browserID in self.__browsersCallbacks:
            loadStart, loadEnd = self.__browsersCallbacks.pop(browserID, (None, None))
            if loadStart is not None:
                self.__browsers[browserID].onLoadStart -= loadStart
            if loadEnd is not None:
                self.__browsers[browserID].onLoadEnd -= loadEnd
        return

    def __showBrowser(self, browserID, ctx):
        self.app.fireEvent(LoadViewEvent(VIEW_ALIAS.BROWSER_WINDOW, getViewName(VIEW_ALIAS.BROWSER_WINDOW, browserID), ctx=ctx), EVENT_BUS_SCOPE.LOBBY)