Logo Search packages:      
Sourcecode: iceme version File versions  Download package

IceMenuTree.py

from gtk import *
from DndCTree import DndCTree
from MenuParser import *
from constants import *


NORMAL_FONT = load_font("-*-helvetica-medium-r-normal-*-12-*")
BOLD_FONT   = load_font("-*-helvetica-medium-o-normal-*-12-*")


class IceMenuTree(DndCTree):

    def __init__(self, app):
        DndCTree.__init__(self, 2, 0, ["Menu", "Command"])
        self.app = app
        self.set_selection_mode(SELECTION_BROWSE)
        self.column_titles_passive()
        self.connect("tree-expand", self.on_tree_expand)


    def on_tree_expand(self, tree, node):
        for i in range(0,2):
            wid = self.get_column_width(i)
            opt = self.optimal_column_width(i)
            if wid < opt:
                self.set_column_width(i, opt)


    def init(self, menufile = None, programsfile = None, toolbarfile = None):
        self.clear()
        self.freeze()
        # insert root node:
        root = self.__insertNode(None, None, MENUTREE_SUBMENU,
                                 "", "$ice_me_icewm$", None, TRUE)
        self.expand(root)
        # insert main menu:
        if menufile:
            m = MenuParser(menufile)
            self.__insertMenu(root, m)
        # insert separator:
        self.__insertSep(root, None, TRUE)
        # insert programs menu:
        node = self.__insertNode(root, None, MENUTREE_SUBMENU,
                                 "Programs", "folder", None, TRUE)
        if programsfile:
            m = MenuParser(programsfile)
            self.__insertMenu(node, m)
        # insert separator:
        self.__insertSep(None, None, TRUE)
        # insert toolbar menu:
        node = self.__insertNode(None, None, MENUTREE_SUBMENU,
                                 "Toolbar", "folder", None, TRUE)
        if toolbarfile:
            m = MenuParser(toolbarfile)
            self.__insertMenu(node, m)
        # insert separator:
        self.__insertSep(None, None, TRUE)
        # insert special clipboard menu:
        self.clipboard = self.__insertNode(None, None, MENUTREE_SUBMENU,
                                           "Clipboard", "$ice_me_clipboard$",
                                           None, TRUE)
        self.columns_autosize()
        self.thaw()
        return root


    def __insertMenu(self, parent, menuparser):
        parent_stack = [parent, ]
        while 1:
            entry = menuparser.getNextEntry()
            if entry is None:
                break
            if entry[0] == MENUTREE_UNKNOWN:
                continue
            if entry[0] == MENUTREE_SUBMENU_END:
                parent_stack.pop()
                parent = parent_stack[-1]
            else:
                params = (parent, None) + tuple(entry)
                node = apply(self.__insertNode, params)
                if entry[0] == MENUTREE_SUBMENU:
                    parent = node
                    parent_stack.append(parent)


    def __insertSep(self, parent, sibling, inactive = FALSE):
        return self.__insertNode(parent, sibling, MENUTREE_SEPARATOR,
                                 "", None, None, inactive)


    def __insertNode(self, parent, sibling,
                     type, text, iconname, command,
                     inactive = FALSE):
        if type not in (MENUTREE_PROG, MENUTREE_RESTART):
            command = ""
        if type == MENUTREE_SEPARATOR:
            text = SEP_STRING
            pix = mask = iconname = None
        else:
            dummy, pix, mask = self.app.getCachedIcon(iconname)
        is_leaf = (type != MENUTREE_SUBMENU)
        # insert node:
        node = self.insert_node(parent, sibling, [text, command], 5,
                                pix, mask, pix, mask, is_leaf)
        # store additional data: iconname, whether it's a restart button
        # and whether the entry is inactive:
        self.node_set_row_data(node, [iconname, type, inactive])
        # it the node should be inactive, change its color to grey:
        style = self.get_style().copy()
        if inactive:
            style.font = BOLD_FONT
        else:
            style.font = NORMAL_FONT
        self.node_set_row_style(node, style)
        return node


    def insertNode(self, node, type, text, iconname, command):
        "Insert a new entry under node 'node'."
        if self.isInactive(node):
            parent = node
            self.expand(parent)
            if node.children:
                sibling = node.children[0]
            else:
                sibling = None
        else:
            parent = node.parent
            sibling = node.sibling
        return self.__insertNode(parent, sibling, type, text, iconname, command)


    def getNodeName(self, node):
        return self.__getNodeText(node, 0)

    def getNodeCommand(self, node):
        return self.__getNodeText(node, 1)

    def __getNodeText(self, node, col):
        cell_type = self.node_get_cell_type(node, col)
        if cell_type == CELL_TEXT:
            return self.node_get_text(node, col)
        elif cell_type == CELL_PIXTEXT:
            return self.node_get_pixtext(node, col)[0]
        return ""

    def setNodeName(self, node, name):
        self.__setNodeText(node, name, 0)

    def setNodeCommand(self, node, name):
        self.__setNodeText(node, name, 1)

    def __setNodeText(self, node, name, col):
        cell_type = self.node_get_cell_type(node, col)
        if cell_type == CELL_TEXT:
            self.node_set_text(node, col, name)
        elif cell_type == CELL_PIXTEXT:
            old_text, sp, pix, mask = self.node_get_pixtext(node, col)
            if pix == None:
                self.node_set_text(node, col, name)
            else:
                self.node_set_pixtext(node, col, name, sp, pix, mask)

    def getNodeIcon(self, node):
        cell_type = self.node_get_cell_type(node, 0)
        if cell_type == CELL_PIXTEXT:
            text, sp, pix, mask = self.node_get_pixtext(node, 0)
            return (pix, mask)
        elif cell_type == CELL_PIXMAP:
            return self.node_get_pixmap(node, 0)
        else:
            return (None, None)

    def setNodeIcon(self, node, pix, mask):
        cell_type = self.node_get_cell_type(node, 0)
        if cell_type == CELL_PIXTEXT:
            text, sp, old_pix, old_mask = self.node_get_pixtext(node, 0)
            self.node_set_pixtext(node, 0, text, sp, pix, mask)
        elif cell_type == CELL_PIXMAP:
            self.node_set_pixmap(node, 0, pix, mask)

    def getNodeUpperSibling(self, node):
        """In contrast to node.sibling, this function returns the node
        _above_ the current node.

        Returns None, if there is no node above the current node in the
        same level.
        This function is really missing in pygtk.
        """
        if node.parent is None:
            nodes = self.base_nodes()
        else:
            nodes = node.parent.children
        upper_sibling = None
        for n in nodes:
            if n == node:
                return upper_sibling
            upper_sibling = n
        return None

    def isSeparator(self, node):
        return self.getNodeType(node) == MENUTREE_SEPARATOR

    def isInactive(self, node):
        return self.node_get_row_data(node)[2]

    def getNodeType(self, node):
        return self.node_get_row_data(node)[1]

    def setNodeType(self, node, type):
        self.node_get_row_data(node)[1] = type

    def getNodeIconName(self, node):
        return self.node_get_row_data(node)[0]

    def setNodeIconName(self, node, iconname):
        self.node_get_row_data(node)[0] = iconname

    def getMainMenuNode(self):
        # the main menu node is always the first root node
        return self.base_nodes()[0]

    def getProgramsNode(self):
        # the programs node is always the last child of the
        # first root node (the "IceWM" node)
        return self.base_nodes()[0].children[-1]

    def getToolbarNode(self):
        # the toolbar node is always the third root node
        return self.base_nodes()[2]

    def isOnClipboard(self, node):
        "Check whether the node is currently on the clipboard."
        return self.is_ancestor(self.clipboard, node)

    def canMoveUp(self, node):
        "Check whether the node can be moved up in the current subtree."
        upper_sibling = self.getNodeUpperSibling(node)
        if upper_sibling is None: return 0
        return not self.isInactive(upper_sibling)

    def canMoveDown(self, node):
        "Check whether the node can be moved down in the current subtree."
        if node.sibling is None: return 0
        return not self.isInactive(node.sibling)

    def canDelete(self, node):
        "Check whether the node may be deleted."
        return not self.isInactive(node)

    def canInsertOn(self, node):
        "Check whether something may be inserted below/after the node."
        # insert is allowed if the node is not an inactive separator
        return not (self.isInactive(node) and self.isSeparator(node))

    def move_is_permitted(self, source_node, target_node,
                          new_parent, new_sibling):
        """Check whether source_node may be moved via drag and drop to the
        new location at target_node, ie.: position (new_parent,new_sibling)"""
        return self.canDelete(source_node) and self.canInsertOn(target_node)

    def cut(self, node):
        if not self.canDelete(node) or self.isOnClipboard(node):
            gdk_beep()
            return
        # empty the current contents of the clipboard:
        if self.clipboard.children:
            for c in self.clipboard.children:
                self.remove_node(c)
        # move node to the clibboard:
        self.move(node, self.clipboard, None)

    def copy(self, node):
        if self.isOnClipboard(node):
            gdk_beep()
            return
        # empty the current contents of the clipboard:
        if self.clipboard.children:
            for c in self.clipboard.children:
                self.remove_node(c)
        # copy node and decessors recursively to the clipboard:
        self.freeze()
        self.__copy_recursive(self.clipboard, node, 1)
        self.thaw()

    def paste(self, node):
        if not self.clipboard.children:
            # the clipboard is empty
            gdk_beep()
            return
        if not self.canInsertOn(node) or self.isOnClipboard(node):
            # contents of clipboard may not be copied to the node:
            gdk_beep()
            return
        self.freeze()
        self.__copy_recursive(node, self.clipboard.children[0])
        self.thaw()

    def delete(self, node):
        if not self.canDelete(node):
            gdk_beep()
            return
        self.remove_node(node)

    def hasPasteData(self):
        return len(self.clipboard.children)

    def __copy_recursive(self, target_node,
                         source_node, as_child=0):
        if self.isInactive(target_node) or as_child:
            parent = target_node
            self.expand(parent)
            if target_node.children:
                sibling = target_node.children[0]
            else:
                sibling = None
        else:
            parent = target_node.parent
            sibling = target_node.sibling

        new_node = self.__insertNode(parent, sibling,
                                     self.getNodeType(source_node),
                                     self.getNodeName(source_node),
                                     self.getNodeIconName(source_node),
                                     self.getNodeCommand(source_node))

        if not source_node.is_leaf:
            for c in source_node.children:
                self.__copy_recursive(new_node, c, 1)


Generated by  Doxygen 1.6.0   Back to index