Example #1
0
class ZNavigatorView(ZBoxedView, IZAccountStoreListener,
                     IZDocumentIndexListener):
    def __init__(self, parent):
        self.indexEventQueue = Queue()
        self.accountEventQueue = Queue()
        self.model = None

        ZBoxedView.__init__(self, parent)

        self.treeView.refresh()
        self._restoreTreeSelection()

    # end __init__()

    def getViewId(self):
        return IZViewIds.NAVIGATOR_VIEW

    # end getViewId()

    def _getHeaderBitmap(self):
        return getResourceRegistry().getBitmap(
            u"images/perspectives/standard/navigator/navigator.png"
        )  #$NON-NLS-1$

    # end _getHeaderBitmap()

    def _getHeaderLabel(self):
        return _extstr(u"navigator.AccountNavigator")  #$NON-NLS-1$

    # end _getHeaderLabel()

    def _createHeaderWidgets(self, parent, widgetList):
        # Register for events before creating the model so that we don't miss any.
        # Register for events after init'ing WX!
        self._registerAsListener()
        self.model = ZNavigatorModel()

        # Collapse All button
        bitmap = getResourceRegistry().getBitmap(
            u"images/perspectives/standard/navigator/collapseAll.png"
        )  #$NON-NLS-1$
        self.collapseAllButton = ZImageButton(parent, bitmap, False, None,
                                              True)
        self.collapseAllButton.SetToolTipString(
            _extstr(u"navigator.CollapseAllTooltip"))  #$NON-NLS-1$
        # Dashboard button
        bitmap = getResourceRegistry().getBitmap(
            u"images/perspectives/standard/dashboard.png")  #$NON-NLS-1$
        self.dashboardButton = ZImageButton(parent, bitmap, False, None, True)
        self.dashboardButton.SetToolTipString(
            _extstr(u"navigator.DashboardTooltip"))  #$NON-NLS-1$

        widgetList.append(self.collapseAllButton)
        widgetList.append(self.dashboardButton)

    # end _createHeaderWidgets()

    def _createContentWidgets(self, parent):
        self.treeImageList = self._createTreeImageList()
        self.treeProvider = ZTreeNodeBasedContentProvider(
            self.model.getNavigatorTreeRoot(), self.treeImageList)
        treeStyle = wx.NO_BORDER | wx.TR_HIDE_ROOT | wx.TR_LINES_AT_ROOT | wx.TR_SINGLE | wx.TR_HAS_BUTTONS
        self.treeView = ZTreeView(self.treeProvider, parent, style=treeStyle)
        dropTarget = ZNavigatorViewDropTarget(self.treeView, self)
        self.treeView.SetDropTarget(dropTarget)

    # end _createContentWidgets()

    def _layoutContentWidgets(self):
        box = wx.BoxSizer(wx.VERTICAL)
        box.Add(self.treeView, 1, wx.EXPAND)

        return box

    # end _layoutContentWidgets()

    def _createTreeImageList(self):
        registry = getResourceRegistry()
        imgList = ZMappedImageList()
        for img in [
                u"unpublished", u"account", u"blog", u"posts", u"links",
                u"images", u"tags"
        ]:  #$NON-NLS-1$ #$NON-NLS-2$ #$NON-NLS-3$ #$NON-NLS-4$ #$NON-NLS-5$ #$NON-NLS-6$ #$NON-NLS-7$ #$NON-NLS-8$
            imgList.addImage(
                img,
                registry.getBitmap(
                    u"images/perspectives/standard/navigator/%s.png" %
                    img))  #$NON-NLS-1$

        return imgList

    # end _createTreeImageList()

    def _bindWidgetEvents(self):
        ZBoxedView._bindWidgetEvents(self)

        self.Bind(wx.EVT_TREE_SEL_CHANGED, self.onSelectionChanged,
                  self.treeView)
        self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.onItemRightClick,
                  self.treeView)
        self.Bind(wx.EVT_BUTTON, self.onDashboardButton, self.dashboardButton)
        self.Bind(wx.EVT_BUTTON, self.onCollapseAllButton,
                  self.collapseAllButton)
        self.Bind(ZEVT_REFRESH, self.onZoundryRefresh, self)

        wx.EVT_SET_FOCUS(self.treeView, self.onFocus)
        wx.EVT_KILL_FOCUS(self.treeView, self.onUnFocus)

    # end _bindWidgetEvents()

    def onFocus(self, event):
        selection = self._getCurrentSelection()
        if selection:
            fireViewSelectionEvent(selection, self)
        event.Skip()

    # end onFocus()

    def onUnFocus(self, event):
        selection = self._getCurrentSelection()
        if selection:
            fireViewUnselectionEvent()
        event.Skip()

    # end onUnFocus()

    def onDashboardButton(self, event):
        self.treeView.UnselectAll()
        fireViewSelectionEvent(
            ZViewSelection(IZViewSelectionTypes.UNPUBLISHED_ACCOUNT_SELECTION,
                           None), self)
        event.Skip()

    # end onDashboardButton()

    def onCollapseAllButton(self, event):
        self.treeView.UnselectAll()
        self.treeView.collapseAll()
        fireViewSelectionEvent(
            ZViewSelection(IZViewSelectionTypes.UNPUBLISHED_ACCOUNT_SELECTION,
                           None), self)
        event.Skip()

    # end onCollapseAllButton()

    def onItemRightClick(self, event):
        itemId = event.GetItem()
        node = self.treeView.GetPyData(itemId)
        nodeType = node.getType()
        if nodeType == NODE_TYPE_ACCOUNT:
            account = node.getAccount()
            menu = self._createAccountCtxMenu(account)
            self.PopupMenu(menu)
            menu.Destroy()
        if nodeType == NODE_TYPE_BLOG:
            blog = node.getBlog()
            menu = self._createBlogCtxMenu(blog)
            self.PopupMenu(menu)
            menu.Destroy()
        event.Skip()

    # end onItemRightClick()

    def _createAccountCtxMenu(self, account):
        menuContext = ZAccountMenuActionContext(self, account)
        menuModel = ZBlogAccountMenuModel()
        provider = ZModelBasedMenuContentProvider(menuModel, menuContext)
        eventHandler = ZModelBasedMenuEventHandler(menuModel, menuContext)
        return ZMenu(self, menuModel.getRootNode(), provider, eventHandler)

    # end _createAccountCtxMenu()

    def _createBlogCtxMenu(self, blog):
        menuContext = ZBlogMenuActionContext(self, blog)
        menuModel = ZBlogMenuModel()
        provider = ZModelBasedMenuContentProvider(menuModel, menuContext)
        eventHandler = ZModelBasedMenuEventHandler(menuModel, menuContext)
        return ZMenu(self, menuModel.getRootNode(), provider, eventHandler)

    # end _createBlogCtxMenu()

    def onSelectionChanged(self, event):
        selection = self._getCurrentSelection()
        if selection:
            fireViewSelectionEvent(selection, self)
        else:
            fireViewUnselectionEvent()
        event.Skip()

    # end _onSelectionChanged()

    def onAccountAdded(self, account):
        self.accountEventQueue.put((ACCOUNT_EVENT_ADD, account))
        self.model.addAccount(account)
        fireRefreshEvent(self)

    # end onAccountAdded()

    def onAccountChanged(self, account):
        self.accountEventQueue.put((ACCOUNT_EVENT_UPDATE, account))
        self.model.updateAccount(account)
        fireRefreshEvent(self)

    # end onAccountChange()

    def onAccountDeleted(self, account):
        self.accountEventQueue.put((ACCOUNT_EVENT_DELETE, account))
        self.model.removeAccount(account)
        fireRefreshEvent(self)

    # end onAccountDeleted()

    def onIndexChange(self, event):
        shouldRefresh = event.getEventType() == IZDocIndexEvent.DOCINDEX_EVENTTYPE_ADD or \
                        event.getEventType() == IZDocIndexEvent.DOCINDEX_EVENTTYPE_REMOVE
        if shouldRefresh:
            self.indexEventQueue.put(event)
            fireRefreshEvent(self)

    # end onIndexChange()

    def onBlogEntryDropped(self, blogId, node):
        getLoggerService().debug(
            u"Dropped blog entry '%s' onto blog node '%s'." %
            (blogId, node.getBlog().getId()))  #$NON-NLS-1$
        ZShowNotYetImplementedMessage(self)

    # end onBlogEntryDropped()

    def onZoundryRefresh(self, event):  #@UnusedVariable
        nodesToRefresh = self._getNodesToRefresh()
        self.treeView.refresh(nodesToRefresh)

    # end onZoundryRefresh()

    # Gets the list of nodes to refresh based on the current queue of index events.
    def _getNodesToRefresh(self):
        nodesToRefresh = []

        # If there are any account events, refresh the whole tree
        if not self.accountEventQueue.empty():
            # Clear out the account event queue
            while not self.accountEventQueue.empty():
                self.accountEventQueue.get()
            return None

        # If there are index events, then we can refresh only parts of the tree
        while not self.indexEventQueue.empty():
            event = self.indexEventQueue.get()
            dirtyNodes = None
            if event.getEventType() == IZDocIndexEvent.DOCINDEX_EVENTTYPE_ADD:
                if event.getDataType(
                ) == IZDocIndexEvent.DOCINDEX_DATATYPE_DOCUMENT:
                    dirtyNodes = self.model.addDocumentIDO(
                        event.getDocumentIDO())
                elif event.getDataType(
                ) == IZDocIndexEvent.DOCINDEX_DATATYPE_IMAGE:
                    dirtyNodes = self.model.addImageIDO(event.getImageIDO())
                elif event.getDataType(
                ) == IZDocIndexEvent.DOCINDEX_DATATYPE_LINK:
                    dirtyNodes = self.model.addLinkIDO(event.getLinkIDO())
                elif event.getDataType(
                ) == IZDocIndexEvent.DOCINDEX_DATATYPE_TAG:
                    dirtyNodes = self.model.addTagIDO(event.getTagIDO())

            elif event.getEventType(
            ) == IZDocIndexEvent.DOCINDEX_EVENTTYPE_REMOVE:
                if event.getDataType(
                ) == IZDocIndexEvent.DOCINDEX_DATATYPE_DOCUMENT:
                    dirtyNodes = self.model.removeDocumentIDO(
                        event.getDocumentIDO())
                elif event.getDataType(
                ) == IZDocIndexEvent.DOCINDEX_DATATYPE_IMAGE:
                    dirtyNodes = self.model.removeImageIDO(event.getImageIDO())
                elif event.getDataType(
                ) == IZDocIndexEvent.DOCINDEX_DATATYPE_LINK:
                    dirtyNodes = self.model.removeLinkIDO(event.getLinkIDO())
                elif event.getDataType(
                ) == IZDocIndexEvent.DOCINDEX_DATATYPE_TAG:
                    dirtyNodes = self.model.removeTagIDO(event.getTagIDO())
            if dirtyNodes is not None:
                nodesToRefresh.extend(dirtyNodes)

        return nodesToRefresh

    # end _getNodesToRefresh()

    def _getCurrentSelection(self):
        treeIDs = self.treeView.GetSelections()
        nodes = map(self.treeView.GetPyData, treeIDs)
        # Just return the 1st node - currently multi-selection is disabled.
        for node in nodes:
            return createViewSelection(node)

        return None

    # end _getCurrentSelection()

    def destroy(self):
        self._saveTreeLayout()

        self._unregisterAsListener()

    # end destroy()

    def _saveTreeLayout(self):
        visitor = ZTreeLayoutSaveVisitor()
        self.treeView.accept(visitor)
        self._saveTreeSelection()

        # Save the properties
        getApplicationModel().getUserProfile().getProperties().save()

    # end _saveTreeLayout()

    def _saveTreeSelection(self):
        nodes = self.treeView.getSelectedNodes()
        hashValue = 0
        if nodes:
            node = nodes[0]
            hashValue = node.hashCode()
        userPrefs = getApplicationModel().getUserProfile().getPreferences()
        userPrefs.setUserPreference(
            IZBlogAppUserPrefsKeys.NAVIGATOR_VIEW_SELECTION,
            unicode(hashValue))

    # end _saveTreeSelection()

    def _restoreTreeSelection(self):
        userPrefs = getApplicationModel().getUserProfile().getPreferences()
        hashValue = userPrefs.getUserPreferenceInt(
            IZBlogAppUserPrefsKeys.NAVIGATOR_VIEW_SELECTION, 0)
        if hashValue != 0:
            visitor = ZTreeSelectionRestoreVisitor(self, hashValue)
            self.treeView.accept(visitor)

    # end _restoreTreeSelection()

    def _registerAsListener(self):
        self._registerAsAccountListener()
        self._registerAsIndexListener()

    # end _registerAsListener()

    def _unregisterAsListener(self):
        self._unregisterAsAccountListener()
        self._unregisterAsIndexListener()

    # end _unregisterAsListener()

    def _registerAsAccountListener(self):
        engine = getApplicationModel().getEngine()
        accountStore = engine.getService(
            IZBlogAppServiceIDs.ACCOUNT_STORE_SERVICE_ID)
        accountStore.addListener(self)

    # end _registerAsAccountListener()

    def _unregisterAsAccountListener(self):
        engine = getApplicationModel().getEngine()
        accountStore = engine.getService(
            IZBlogAppServiceIDs.ACCOUNT_STORE_SERVICE_ID)
        accountStore.removeListener(self)

    # end _unregisterAsAccountListener()

    def _registerAsIndexListener(self):
        engine = getApplicationModel().getEngine()
        accountStore = engine.getService(
            IZBlogAppServiceIDs.DOCUMENT_INDEX_SERVICE_ID)
        accountStore.addListener(self)

    # end _registerAsIndexListener()

    def _unregisterAsIndexListener(self):
        engine = getApplicationModel().getEngine()
        accountStore = engine.getService(
            IZBlogAppServiceIDs.DOCUMENT_INDEX_SERVICE_ID)
        accountStore.removeListener(self)