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)