Example #1
0
    def __init__(self, document, parentwin):
        """Initialise dock given document and parent widget."""
        qt4.QDockWidget.__init__(self, parentwin)
        self.parentwin = parentwin
        self.setWindowTitle(_("Editing - Veusz"))
        self.setObjectName("veuszeditingwindow")
        self.selwidgets = []

        self.document = document
        self.connect( self.document, qt4.SIGNAL("sigWiped"),
                      self.slotDocumentWiped )

        # construct tree
        self.treemodel = WidgetTreeModel(document)
        self.treeview = WidgetTreeView(self.treemodel)

        # receive change in selection
        self.connect(self.treeview.selectionModel(),
                     qt4.SIGNAL('selectionChanged(const QItemSelection &,'
                                ' const QItemSelection &)'),
                     self.slotTreeItemsSelected)

        # set tree as main widget
        self.setWidget(self.treeview)

        # toolbar to create widgets
        self.addtoolbar = qt4.QToolBar(_("Insert toolbar - Veusz"),
                                       parentwin)
        # note wrong description!: backwards compatibility
        self.addtoolbar.setObjectName("veuszeditingtoolbar")

        # toolbar for editting widgets
        self.edittoolbar = qt4.QToolBar(_("Edit toolbar - Veusz"),
                                        parentwin)
        self.edittoolbar.setObjectName("veuszedittoolbar")

        self._constructToolbarMenu()
        parentwin.addToolBarBreak(qt4.Qt.TopToolBarArea)
        parentwin.addToolBar(qt4.Qt.TopToolBarArea, self.addtoolbar)
        parentwin.addToolBar(qt4.Qt.TopToolBarArea, self.edittoolbar)

        # this sets various things up
        self.selectWidget(document.basewidget)

        # update paste button when clipboard changes
        self.connect(qt4.QApplication.clipboard(),
                     qt4.SIGNAL('dataChanged()'),
                     self.updatePasteButton)
        self.updatePasteButton()
Example #2
0
    def __init__(self, document, parent):
        """Initialise dock given document and parent widget."""
        qt4.QDockWidget.__init__(self, parent)
        self.parent = parent
        self.setWindowTitle("Editing - Veusz")
        self.setObjectName("veuszeditingwindow")
        self.selwidgets = []

        self.document = document
        self.connect( self.document, qt4.SIGNAL("sigWiped"),
                      self.slotDocumentWiped )

        # construct tree
        self.treemodel = WidgetTreeModel(document)
        self.treeview = WidgetTreeView(self.treemodel)

        # receive change in selection
        self.connect(self.treeview.selectionModel(),
                     qt4.SIGNAL('selectionChanged(const QItemSelection &,'
                                ' const QItemSelection &)'),
                     self.slotTreeItemsSelected)

        # set tree as main widget
        self.setWidget(self.treeview)

        # toolbar to create widgets
        self.addtoolbar = qt4.QToolBar("Insert toolbar - Veusz",
                                       parent)
        # note wrong description!: backwards compatibility
        self.addtoolbar.setObjectName("veuszeditingtoolbar")

        # toolbar for editting widgets
        self.edittoolbar = qt4.QToolBar("Edit toolbar - Veusz",
                                        parent)
        self.edittoolbar.setObjectName("veuszedittoolbar")

        self._constructToolbarMenu()
        parent.addToolBarBreak(qt4.Qt.TopToolBarArea)
        parent.addToolBar(qt4.Qt.TopToolBarArea, self.addtoolbar)
        parent.addToolBar(qt4.Qt.TopToolBarArea, self.edittoolbar)

        # this sets various things up
        self.selectWidget(document.basewidget)

        # update paste button when clipboard changes
        self.connect(qt4.QApplication.clipboard(),
                     qt4.SIGNAL('dataChanged()'),
                     self.updatePasteButton)
        self.updatePasteButton()
Example #3
0
class TreeEditDock(qt4.QDockWidget):
    """A dock window presenting widgets as a tree."""

    def __init__(self, document, parent):
        """Initialise dock given document and parent widget."""
        qt4.QDockWidget.__init__(self, parent)
        self.parent = parent
        self.setWindowTitle("Editing - Veusz")
        self.setObjectName("veuszeditingwindow")
        self.selwidgets = []

        self.document = document
        self.connect( self.document, qt4.SIGNAL("sigWiped"),
                      self.slotDocumentWiped )

        # construct tree
        self.treemodel = WidgetTreeModel(document)
        self.treeview = WidgetTreeView(self.treemodel)

        # receive change in selection
        self.connect(self.treeview.selectionModel(),
                     qt4.SIGNAL('selectionChanged(const QItemSelection &,'
                                ' const QItemSelection &)'),
                     self.slotTreeItemsSelected)

        # set tree as main widget
        self.setWidget(self.treeview)

        # toolbar to create widgets
        self.addtoolbar = qt4.QToolBar("Insert toolbar - Veusz",
                                       parent)
        # note wrong description!: backwards compatibility
        self.addtoolbar.setObjectName("veuszeditingtoolbar")

        # toolbar for editting widgets
        self.edittoolbar = qt4.QToolBar("Edit toolbar - Veusz",
                                        parent)
        self.edittoolbar.setObjectName("veuszedittoolbar")

        self._constructToolbarMenu()
        parent.addToolBarBreak(qt4.Qt.TopToolBarArea)
        parent.addToolBar(qt4.Qt.TopToolBarArea, self.addtoolbar)
        parent.addToolBar(qt4.Qt.TopToolBarArea, self.edittoolbar)

        # this sets various things up
        self.selectWidget(document.basewidget)

        # update paste button when clipboard changes
        self.connect(qt4.QApplication.clipboard(),
                     qt4.SIGNAL('dataChanged()'),
                     self.updatePasteButton)
        self.updatePasteButton()

    def slotDocumentWiped(self):
        """If the document is wiped, reselect root widget."""
        self.selectWidget(self.document.basewidget)

    def slotTreeItemsSelected(self, current, previous):
        """New item selected in tree.

        This updates the list of properties
        """

        # get selected widgets
        self.selwidgets = widgets = [
            self.treemodel.getWidget(idx)
            for idx in self.treeview.selectionModel().selectedRows() ]

        if len(widgets) == 0:
            setnsproxy = None
        elif len(widgets) == 1:
            setnsproxy = SettingsProxySingle(self.document, widgets[0].settings,
                                             actions=widgets[0].actions)
        else:
            setnsproxy = SettingsProxyMulti(self.document, widgets)

        self._enableCorrectButtons()
        self._checkPageChange()

        self.emit( qt4.SIGNAL('widgetsSelected'), self.selwidgets, setnsproxy )

    def contextMenuEvent(self, event):
        """Bring up context menu."""

        # no widgets selected
        if not self.selwidgets:
            return

        m = qt4.QMenu(self)

        # selection
        m.addMenu(self.parent.menus['edit.select'])
        m.addSeparator()

        # actions on widget(s)
        for act in ('edit.cut', 'edit.copy', 'edit.paste',
                    'edit.moveup', 'edit.movedown', 'edit.delete',
                    'edit.rename'):
            m.addAction(self.vzactions[act])

        # allow show or hides of selected widget
        anyhide = False
        anyshow = False
        for w in self.selwidgets:
            if 'hide' in w.settings:
                if w.settings.hide:
                    anyshow = True
                else:
                    anyhide = True

        for (enabled, menutext, showhide) in (
            (anyhide, 'Hide', True), (anyshow, 'Show', False) ):
            if enabled:
                m.addSeparator()
                act = qt4.QAction(menutext, self)
                self.connect(act, qt4.SIGNAL('triggered()'),
                             utils.BoundCaller(self.slotWidgetHideShow,
                                               self.selwidgets, showhide))
                m.addAction(act)

        m.exec_(self.mapToGlobal(event.pos()))
        event.accept()

    def _checkPageChange(self):
        """Check to see whether page has changed."""

        w = None
        if self.selwidgets:
            w = self.selwidgets[0]
        while w is not None and not isinstance(w, widgets.Page):
            w = w.parent

        if w is not None:
            # have page, so check what number we are in basewidget children
            try:
                i = self.document.basewidget.children.index(w)
                self.emit(qt4.SIGNAL("sigPageChanged"), i)
            except ValueError:
                pass

    def _enableCorrectButtons(self):
        """Make sure the create graph buttons are correctly enabled."""

        selw = None
        if self.selwidgets:
            selw = self.selwidgets[0]

        # has to be visible if is to be enabled (yuck)
        nonorth = self.vzactions['add.nonorthpoint'].setVisible(True)

        # check whether each button can have this widget
        # (or a parent) as parent
        for wc, action in self.addslots.iteritems():
            w = selw
            while w is not None and not wc.willAllowParent(w):
                w = w.parent

            self.vzactions['add.%s' % wc.typename].setEnabled(w is not None)

        # exclusive widgets
        nonorth = self.vzactions['add.nonorthpoint'].isEnabled()
        self.vzactions['add.nonorthpoint'].setVisible(nonorth)
        self.vzactions['add.xy'].setVisible(not nonorth)
        self.vzactions['add.nonorthfunc'].setVisible(nonorth)
        self.vzactions['add.function'].setVisible(not nonorth)

        # certain actions shouldn't work on root
        isnotroot = not any([isinstance(w, widgets.Root)
                             for w in self.selwidgets])

        for act in ('edit.cut', 'edit.copy', 'edit.delete',
                    'edit.moveup', 'edit.movedown', 'edit.rename'):
            self.vzactions[act].setEnabled(isnotroot)

        self.updatePasteButton()

    def _constructToolbarMenu(self):
        """Add items to edit/add graph toolbar and menu."""

        iconsize = setting.settingdb['toolbar_size']
        self.addtoolbar.setIconSize( qt4.QSize(iconsize, iconsize) )
        self.edittoolbar.setIconSize( qt4.QSize(iconsize, iconsize) )

        self.addslots = {}
        self.vzactions = actions = self.parent.vzactions
        for widgettype in ('page', 'grid', 'graph', 'axis',
                           'xy', 'bar', 'fit', 'function', 'boxplot',
                           'image', 'contour', 'vectorfield',
                           'key', 'label', 'colorbar',
                           'rect', 'ellipse', 'imagefile',
                           'line', 'polygon', 'polar', 'ternary',
                           'nonorthpoint', 'nonorthfunc'):

            wc = document.thefactory.getWidgetClass(widgettype)
            slot = utils.BoundCaller(self.slotMakeWidgetButton, wc)
            self.addslots[wc] = slot
            
            actionname = 'add.' + widgettype
            actions[actionname] = utils.makeAction(
                self,
                wc.description, 'Add %s' % widgettype,
                slot,
                icon='button_%s' % widgettype)

        a = utils.makeAction
        actions.update({
                'edit.cut':
                    a(self, 'Cut the selected item', 'Cu&t',
                      self.slotWidgetCut,
                      icon='veusz-edit-cut', key='Ctrl+X'),
                'edit.copy':
                    a(self, 'Copy the selected item', '&Copy',
                      self.slotWidgetCopy,
                      icon='kde-edit-copy', key='Ctrl+C'),
                'edit.paste':
                    a(self, 'Paste item from the clipboard', '&Paste',
                      self.slotWidgetPaste,
                      icon='kde-edit-paste', key='Ctrl+V'),
                'edit.moveup':
                    a(self, 'Move the selected item up', 'Move &up',
                      utils.BoundCaller(self.slotWidgetMove, -1),
                      icon='kde-go-up'),
                'edit.movedown':
                    a(self, 'Move the selected item down', 'Move d&own',
                      utils.BoundCaller(self.slotWidgetMove, 1),
                      icon='kde-go-down'),
                'edit.delete':
                    a(self, 'Remove the selected item', '&Delete',
                      self.slotWidgetDelete,
                      icon='kde-edit-delete'),
                'edit.rename':
                    a(self, 'Renames the selected item', '&Rename',
                      self.slotWidgetRename,
                      icon='kde-edit-rename'),

                'add.shapemenu':
                    a(self, 'Add a shape to the plot', 'Shape',
                      self.slotShowShapeMenu,
                      icon='veusz-shape-menu'),
                })

        # add actions to menus for adding widgets and editing
        addact = [('add.'+w) for w in 
                  ('page', 'grid', 'graph', 'axis',
                   'xy', 'nonorthpoint', 'bar', 'fit',
                   'function', 'nonorthfunc', 'boxplot',
                   'image', 'contour', 'vectorfield',
                   'key', 'label', 'colorbar', 'polar', 'ternary')]

        menuitems = [
            ('insert', '', addact + [
                    ['insert.shape', 'Add shape',
                     ['add.rect', 'add.ellipse', 'add.line', 'add.imagefile',
                      'add.polygon']
                     ]]),
            ('edit', '', [
                    'edit.cut', 'edit.copy', 'edit.paste',
                    'edit.moveup', 'edit.movedown',
                    'edit.delete', 'edit.rename'
                    ]),
            ]            
        utils.constructMenus( self.parent.menuBar(),
                              self.parent.menus,
                              menuitems,
                              actions )

        # create shape toolbar button
        # attach menu to insert shape button
        actions['add.shapemenu'].setMenu(self.parent.menus['insert.shape'])

        # add actions to toolbar to create widgets
        utils.addToolbarActions(self.addtoolbar, actions,
                                addact + ['add.shapemenu'])

        # add action to toolbar for editing
        utils.addToolbarActions(self.edittoolbar,  actions,
                                ('edit.cut', 'edit.copy', 'edit.paste',
                                 'edit.moveup', 'edit.movedown',
                                 'edit.delete', 'edit.rename'))

        self.connect( self.parent.menus['edit.select'],
                      qt4.SIGNAL('aboutToShow()'), self.updateSelectMenu )

    def slotMakeWidgetButton(self, wc):
        """User clicks button to make widget."""
        self.makeWidget(wc.typename)

    def slotShowShapeMenu(self):
        a = self.vzactions['add.shapemenu']
        a.menu().popup( qt4.QCursor.pos() )

    def makeWidget(self, widgettype, autoadd=True, name=None):
        """Called when an add widget button is clicked.
        widgettype is the type of widget
        autoadd specifies whether to add default children
        if name is set this name is used if possible (ie no other children have it)
        """

        # if no widget selected, bomb out
        if not self.selwidgets:
            return
        parent = document.getSuitableParent(widgettype, self.selwidgets[0])

        assert parent is not None

        if name in parent.childnames:
            name = None
        
        # make the new widget and update the document
        w = self.document.applyOperation(
            document.OperationWidgetAdd(parent, widgettype, autoadd=autoadd,
                                        name=name) )

        # select the widget
        self.selectWidget(w)

    def slotWidgetCut(self):
        """Cut the selected widget"""
        self.slotWidgetCopy()
        self.slotWidgetDelete()

    def slotWidgetCopy(self):
        """Copy selected widget to the clipboard."""

        if self.selwidgets:
            mimedata = document.generateWidgetsMime(self.selwidgets)
            clipboard = qt4.QApplication.clipboard()
            clipboard.setMimeData(mimedata)

    def updatePasteButton(self):
        """Is the data on the clipboard a valid paste at the currently
        selected widget? If so, enable paste button"""

        data = document.getClipboardWidgetMime()
        if len(self.selwidgets) == 0:
            show = False
        else:
            show = document.isMimePastable(self.selwidgets[0], data)
        self.vzactions['edit.paste'].setEnabled(show)

    def doInitialWidgetSelect(self):
        """Select a sensible initial widget."""
        w = self.document.basewidget
        for i in xrange(2):
            try:
                c = w.children[0]
            except IndexError:
                break
            if c:
                w = c
        self.selectWidget(w)

    def slotWidgetPaste(self):
        """Paste something from the clipboard"""

        data = document.getClipboardWidgetMime()
        if data:
            op = document.OperationWidgetPaste(self.selwidgets[0], data)
            widgets = self.document.applyOperation(op)
            if widgets:
                self.selectWidget(widgets[0])

    def slotWidgetDelete(self):
        """Delete the widget selected."""

        widgets = self.selwidgets
        # if no item selected, leave
        if not widgets:
            return

        # get list of widgets in order
        widgetlist = []
        self.document.basewidget.buildFlatWidgetList(widgetlist)
        
        # find indices of widgets to be deleted - find one to select after
        indexes = [widgetlist.index(w) for w in widgets]
        if -1 in indexes:
            raise RuntimeError, "Invalid widget in list of selected widgets"
        minindex = min(indexes)

        # delete selected widget
        self.document.applyOperation(
            document.OperationWidgetsDelete(widgets))

        # rebuild list
        widgetlist = []
        self.document.basewidget.buildFlatWidgetList(widgetlist)

        # find next to select
        if minindex < len(widgetlist):
            nextwidget = widgetlist[minindex]
        else:
            nextwidget = widgetlist[-1]

        # select the next widget (we have to select root first!)
        self.selectWidget(self.document.basewidget)
        self.selectWidget(nextwidget)

    def slotWidgetRename(self):
        """Allows the user to rename the selected widget."""

        selected = self.treeview.selectedIndexes()
        if len(selected) != 0:
            self.treeview.edit(selected[0])

    def selectWidget(self, widget):
        """Select the associated listviewitem for the widget w in the
        listview."""

        index = self.treemodel.getWidgetIndex(widget)
        if index is not None:
            self.treeview.scrollTo(index)
            self.treeview.selectionModel().select(
                index, qt4.QItemSelectionModel.Clear |
                qt4.QItemSelectionModel.Current |
                qt4.QItemSelectionModel.Rows |
                qt4.QItemSelectionModel.Select )

    def slotWidgetMove(self, direction):
        """Move the selected widget up/down in the hierarchy.

        a is the action (unused)
        direction is -1 for 'up' and +1 for 'down'
        """

        if not self.selwidgets:
            return
        # widget to move
        w = self.selwidgets[0]
        
        # actually move the widget
        self.document.applyOperation(
            document.OperationWidgetMoveUpDown(w, direction) )

        # re-highlight moved widget
        self.selectWidget(w)

    def slotWidgetHideShow(self, widgets, hideshow):
        """Hide or show selected widgets.
        hideshow is True for hiding, False for showing
        """
        ops = [ document.OperationSettingSet(w.settings.get('hide'), hideshow)
                for w in widgets ]
        descr = ('show', 'hide')[hideshow]
        self.document.applyOperation(
            document.OperationMultiple(ops, descr=descr))

    def checkWidgetSelected(self):
        """Check widget is selected."""
        if len(self.treeview.selectionModel().selectedRows()) == 0:
            self.selectWidget(self.document.basewidget)

    def _selectWidgetsTypeAndOrName(self, wtype, wname):
        """Select widgets with type or name given.
        Give None if you don't care for either."""
        def selectwidget(path, w):
            """Select widget if of type or name given."""
            if ( (wtype is None or w.typename == wtype) and
                 (wname is None or w.name == wname) ):
                idx = self.treemodel.getWidgetIndex(w)
                self.treeview.selectionModel().select(
                    idx, qt4.QItemSelectionModel.Select |
                    qt4.QItemSelectionModel.Rows)

        self.document.walkNodes(selectwidget, nodetypes=('widget',))

    def _selectWidgetSiblings(self, w, wtype):
        """Select siblings of widget given with type."""
        for c in w.parent.children:
            if c is not w and c.typename == wtype:
                idx = self.treemodel.getWidgetIndex(c)
                self.treeview.selectionModel().select(
                    idx, qt4.QItemSelectionModel.Select |
                    qt4.QItemSelectionModel.Rows)
                
    def updateSelectMenu(self):
        """Update edit.select menu."""
        menu = self.parent.menus['edit.select']
        menu.clear()

        if len(self.selwidgets) == 0:
            return

        wtype = self.selwidgets[0].typename
        name = self.selwidgets[0].name

        menu.addAction(
            "All '%s' widgets" % wtype,
            lambda: self._selectWidgetsTypeAndOrName(wtype, None))
        menu.addAction(
            "Siblings of '%s' with type '%s'" % (name, wtype),
            lambda: self._selectWidgetSiblings(self.selwidgets[0], wtype))
        menu.addAction(
            "All '%s' widgets called '%s'" % (wtype, name),
            lambda: self._selectWidgetsTypeAndOrName(wtype, name))
        menu.addAction(
            "All widgets called '%s'" % name,
            lambda: self._selectWidgetsTypeAndOrName(None, name))
Example #4
0
class TreeEditDock(qt4.QDockWidget):
    """A dock window presenting widgets as a tree."""

    def __init__(self, document, parentwin):
        """Initialise dock given document and parent widget."""
        qt4.QDockWidget.__init__(self, parentwin)
        self.parentwin = parentwin
        self.setWindowTitle(_("Editing - Veusz"))
        self.setObjectName("veuszeditingwindow")
        self.selwidgets = []

        self.document = document
        self.connect( self.document, qt4.SIGNAL("sigWiped"),
                      self.slotDocumentWiped )

        # construct tree
        self.treemodel = WidgetTreeModel(document)
        self.treeview = WidgetTreeView(self.treemodel)

        # receive change in selection
        self.connect(self.treeview.selectionModel(),
                     qt4.SIGNAL('selectionChanged(const QItemSelection &,'
                                ' const QItemSelection &)'),
                     self.slotTreeItemsSelected)

        # set tree as main widget
        self.setWidget(self.treeview)

        # toolbar to create widgets
        self.addtoolbar = qt4.QToolBar(_("Insert toolbar - Veusz"),
                                       parentwin)
        # note wrong description!: backwards compatibility
        self.addtoolbar.setObjectName("veuszeditingtoolbar")

        # toolbar for editting widgets
        self.edittoolbar = qt4.QToolBar(_("Edit toolbar - Veusz"),
                                        parentwin)
        self.edittoolbar.setObjectName("veuszedittoolbar")

        self._constructToolbarMenu()
        parentwin.addToolBarBreak(qt4.Qt.TopToolBarArea)
        parentwin.addToolBar(qt4.Qt.TopToolBarArea, self.addtoolbar)
        parentwin.addToolBar(qt4.Qt.TopToolBarArea, self.edittoolbar)

        # this sets various things up
        self.selectWidget(document.basewidget)

        # update paste button when clipboard changes
        self.connect(qt4.QApplication.clipboard(),
                     qt4.SIGNAL('dataChanged()'),
                     self.updatePasteButton)
        self.updatePasteButton()

    def slotDocumentWiped(self):
        """If the document is wiped, reselect root widget."""
        self.selectWidget(self.document.basewidget)

    def slotTreeItemsSelected(self, current, previous):
        """New item selected in tree.

        This updates the list of properties
        """

        # get selected widgets
        self.selwidgets = swidget = [
            self.treemodel.getWidget(idx)
            for idx in self.treeview.selectionModel().selectedRows() ]

        if len(swidget) == 0:
            setnsproxy = None
        elif len(swidget) == 1:
            setnsproxy = SettingsProxySingle(self.document, swidget[0].settings,
                                             actions=swidget[0].actions)
        else:
            setnsproxy = SettingsProxyMulti(self.document, swidget)

        self._enableCorrectButtons()
        self._checkPageChange()

        self.emit( qt4.SIGNAL('widgetsSelected'), swidget, setnsproxy )

    def contextMenuEvent(self, event):
        """Bring up context menu."""

        # no widgets selected
        if not self.selwidgets:
            return

        m = qt4.QMenu(self)

        # selection
        m.addMenu(self.parentwin.menus['edit.select'])
        m.addSeparator()

        # actions on widget(s)
        for act in ('edit.cut', 'edit.copy', 'edit.paste',
                    'edit.moveup', 'edit.movedown', 'edit.delete',
                    'edit.rename'):
            m.addAction(self.vzactions[act])

        # allow show or hides of selected widget
        anyhide = False
        anyshow = False
        for w in self.selwidgets:
            if 'hide' in w.settings:
                if w.settings.hide:
                    anyshow = True
                else:
                    anyhide = True

        for (enabled, menutext, showhide) in (
            (anyhide, 'Hide', True), (anyshow, 'Show', False) ):
            if enabled:
                m.addSeparator()
                act = qt4.QAction(menutext, self)
                self.connect(act, qt4.SIGNAL('triggered()'),
                             utils.BoundCaller(self.slotWidgetHideShow,
                                               self.selwidgets, showhide))
                m.addAction(act)

        m.exec_(self.mapToGlobal(event.pos()))
        event.accept()

    def _checkPageChange(self):
        """Check to see whether page has changed."""

        w = None
        if self.selwidgets:
            w = self.selwidgets[0]
        while w is not None and not isinstance(w, widgets.Page):
            w = w.parent

        if w is not None:
            # have page, so check what number we are in basewidget children
            try:
                i = self.document.basewidget.children.index(w)
                self.emit(qt4.SIGNAL("sigPageChanged"), i)
            except ValueError:
                pass

    def _enableCorrectButtons(self):
        """Make sure the create graph buttons are correctly enabled."""

        selw = None
        if self.selwidgets:
            selw = self.selwidgets[0]

        # has to be visible if is to be enabled (yuck)
        nonorth = self.vzactions['add.nonorthpoint'].setVisible(True)

        # check whether each button can have this widget
        # (or a parent) as parent
        for wc, action in self.addslots.iteritems():
            w = selw
            while w is not None and not wc.willAllowParent(w):
                w = w.parent

            self.vzactions['add.%s' % wc.typename].setEnabled(w is not None)

        # exclusive widgets
        nonorth = self.vzactions['add.nonorthpoint'].isEnabled()
        self.vzactions['add.nonorthpoint'].setVisible(nonorth)
        self.vzactions['add.xy'].setVisible(not nonorth)
        self.vzactions['add.nonorthfunc'].setVisible(nonorth)
        self.vzactions['add.function'].setVisible(not nonorth)

        # certain actions shouldn't work on root
        isnotroot = not any([isinstance(w, widgets.Root)
                             for w in self.selwidgets])

        for act in ('edit.cut', 'edit.copy', 'edit.delete',
                    'edit.moveup', 'edit.movedown', 'edit.rename'):
            self.vzactions[act].setEnabled(isnotroot)

        self.updatePasteButton()

    def _constructToolbarMenu(self):
        """Add items to edit/add graph toolbar and menu."""

        iconsize = setting.settingdb['toolbar_size']
        self.addtoolbar.setIconSize( qt4.QSize(iconsize, iconsize) )
        self.edittoolbar.setIconSize( qt4.QSize(iconsize, iconsize) )

        self.addslots = {}
        self.vzactions = actions = self.parentwin.vzactions
        for widgettype in ('page', 'grid', 'graph', 'axis',
                           'xy', 'bar', 'fit', 'function', 'boxplot',
                           'image', 'contour', 'vectorfield',
                           'key', 'label', 'colorbar',
                           'rect', 'ellipse', 'imagefile',
                           'line', 'polygon', 'polar', 'ternary',
                           'nonorthpoint', 'nonorthfunc'):

            wc = document.thefactory.getWidgetClass(widgettype)
            slot = utils.BoundCaller(self.slotMakeWidgetButton, wc)
            self.addslots[wc] = slot
            
            actionname = 'add.' + widgettype
            actions[actionname] = utils.makeAction(
                self,
                wc.description, _('Add %s') % widgettype,
                slot,
                icon='button_%s' % widgettype)

        a = utils.makeAction
        actions.update({
                'edit.cut':
                    a(self, _('Cut the selected widget'), _('Cu&t'),
                      self.slotWidgetCut,
                      icon='veusz-edit-cut', key='Ctrl+X'),
                'edit.copy':
                    a(self, _('Copy the selected widget'), _('&Copy'),
                      self.slotWidgetCopy,
                      icon='kde-edit-copy', key='Ctrl+C'),
                'edit.paste':
                    a(self, _('Paste widget from the clipboard'), _('&Paste'),
                      self.slotWidgetPaste,
                      icon='kde-edit-paste', key='Ctrl+V'),
                'edit.moveup':
                    a(self, _('Move the selected widget up'), _('Move &up'),
                      utils.BoundCaller(self.slotWidgetMove, -1),
                      icon='kde-go-up'),
                'edit.movedown':
                    a(self, _('Move the selected widget down'), _('Move d&own'),
                      utils.BoundCaller(self.slotWidgetMove, 1),
                      icon='kde-go-down'),
                'edit.delete':
                    a(self, _('Remove the selected widget'), _('&Delete'),
                      self.slotWidgetDelete,
                      icon='kde-edit-delete'),
                'edit.rename':
                    a(self, _('Renames the selected widget'), _('&Rename'),
                      self.slotWidgetRename,
                      icon='kde-edit-rename'),

                'add.shapemenu':
                    a(self, _('Add a shape to the plot'), _('Shape'),
                      self.slotShowShapeMenu,
                      icon='veusz-shape-menu'),
                })

        # add actions to menus for adding widgets and editing
        addact = [('add.'+w) for w in 
                  ('page', 'grid', 'graph', 'axis',
                   'xy', 'nonorthpoint', 'bar', 'fit',
                   'function', 'nonorthfunc', 'boxplot',
                   'image', 'contour', 'vectorfield',
                   'key', 'label', 'colorbar', 'polar', 'ternary')]

        menuitems = [
            ('insert', '', addact + [
                    ['insert.shape', 'Add shape',
                     ['add.rect', 'add.ellipse', 'add.line', 'add.imagefile',
                      'add.polygon']
                     ]]),
            ('edit', '', [
                    'edit.cut', 'edit.copy', 'edit.paste',
                    'edit.moveup', 'edit.movedown',
                    'edit.delete', 'edit.rename'
                    ]),
            ]            
        utils.constructMenus( self.parentwin.menuBar(),
                              self.parentwin.menus,
                              menuitems,
                              actions )

        # create shape toolbar button
        # attach menu to insert shape button
        actions['add.shapemenu'].setMenu(self.parentwin.menus['insert.shape'])

        # add actions to toolbar to create widgets
        utils.addToolbarActions(self.addtoolbar, actions,
                                addact + ['add.shapemenu'])

        # add action to toolbar for editing
        utils.addToolbarActions(self.edittoolbar,  actions,
                                ('edit.cut', 'edit.copy', 'edit.paste',
                                 'edit.moveup', 'edit.movedown',
                                 'edit.delete', 'edit.rename'))

        self.connect( self.parentwin.menus['edit.select'],
                      qt4.SIGNAL('aboutToShow()'), self.updateSelectMenu )

    def slotMakeWidgetButton(self, wc):
        """User clicks button to make widget."""
        self.makeWidget(wc.typename)

    def slotShowShapeMenu(self):
        a = self.vzactions['add.shapemenu']
        a.menu().popup( qt4.QCursor.pos() )

    def makeWidget(self, widgettype, autoadd=True, name=None):
        """Called when an add widget button is clicked.
        widgettype is the type of widget
        autoadd specifies whether to add default children
        if name is set this name is used if possible (ie no other children have it)
        """

        # if no widget selected, bomb out
        if not self.selwidgets:
            return
        parent = document.getSuitableParent(widgettype, self.selwidgets[0])

        assert parent is not None

        if name in parent.childnames:
            name = None
        
        # make the new widget and update the document
        w = self.document.applyOperation(
            document.OperationWidgetAdd(parent, widgettype, autoadd=autoadd,
                                        name=name) )

        # select the widget
        self.selectWidget(w)

    def slotWidgetCut(self):
        """Cut the selected widget"""
        self.slotWidgetCopy()
        self.slotWidgetDelete()

    def slotWidgetCopy(self):
        """Copy selected widget to the clipboard."""

        if self.selwidgets:
            mimedata = document.generateWidgetsMime(self.selwidgets)
            clipboard = qt4.QApplication.clipboard()
            clipboard.setMimeData(mimedata)

    def updatePasteButton(self):
        """Is the data on the clipboard a valid paste at the currently
        selected widget? If so, enable paste button"""

        data = document.getClipboardWidgetMime()
        if len(self.selwidgets) == 0:
            show = False
        else:
            show = document.isWidgetMimePastable(self.selwidgets[0], data)
        self.vzactions['edit.paste'].setEnabled(show)

    def doInitialWidgetSelect(self):
        """Select a sensible initial widget."""
        w = self.document.basewidget
        for i in xrange(2):
            try:
                c = w.children[0]
            except IndexError:
                break
            if c:
                w = c
        self.selectWidget(w)

    def slotWidgetPaste(self):
        """Paste something from the clipboard"""

        data = document.getClipboardWidgetMime()
        if data:
            op = document.OperationWidgetPaste(self.selwidgets[0], data)
            widgets = self.document.applyOperation(op)
            if widgets:
                self.selectWidget(widgets[0])

    def slotWidgetDelete(self):
        """Delete the widget selected."""

        widgets = self.selwidgets
        # if no item selected, leave
        if not widgets:
            return

        # get list of widgets in order
        widgetlist = []
        self.document.basewidget.buildFlatWidgetList(widgetlist)
        
        # find indices of widgets to be deleted - find one to select after
        indexes = [widgetlist.index(w) for w in widgets]
        if -1 in indexes:
            raise RuntimeError, "Invalid widget in list of selected widgets"
        minindex = min(indexes)

        # delete selected widget
        self.document.applyOperation(
            document.OperationWidgetsDelete(widgets))

        # rebuild list
        widgetlist = []
        self.document.basewidget.buildFlatWidgetList(widgetlist)

        # find next to select
        if minindex < len(widgetlist):
            nextwidget = widgetlist[minindex]
        else:
            nextwidget = widgetlist[-1]

        # select the next widget (we have to select root first!)
        self.selectWidget(self.document.basewidget)
        self.selectWidget(nextwidget)

    def slotWidgetRename(self):
        """Allows the user to rename the selected widget."""

        selected = self.treeview.selectedIndexes()
        if len(selected) != 0:
            self.treeview.edit(selected[0])

    def selectWidget(self, widget):
        """Select the associated listviewitem for the widget w in the
        listview."""

        index = self.treemodel.getWidgetIndex(widget)
        if index is not None:
            self.treeview.scrollTo(index)
            self.treeview.selectionModel().select(
                index, qt4.QItemSelectionModel.Clear |
                qt4.QItemSelectionModel.Current |
                qt4.QItemSelectionModel.Rows |
                qt4.QItemSelectionModel.Select )

    def slotWidgetMove(self, direction):
        """Move the selected widget up/down in the hierarchy.

        a is the action (unused)
        direction is -1 for 'up' and +1 for 'down'
        """

        if not self.selwidgets:
            return
        # widget to move
        w = self.selwidgets[0]
        
        # actually move the widget
        self.document.applyOperation(
            document.OperationWidgetMoveUpDown(w, direction) )

        # re-highlight moved widget
        self.selectWidget(w)

    def slotWidgetHideShow(self, widgets, hideshow):
        """Hide or show selected widgets.
        hideshow is True for hiding, False for showing
        """
        ops = [ document.OperationSettingSet(w.settings.get('hide'), hideshow)
                for w in widgets ]
        descr = ('show', 'hide')[hideshow]
        self.document.applyOperation(
            document.OperationMultiple(ops, descr=descr))

    def checkWidgetSelected(self):
        """Check widget is selected."""
        if len(self.treeview.selectionModel().selectedRows()) == 0:
            self.selectWidget(self.document.basewidget)

    def _selectWidgetsTypeAndOrName(self, wtype, wname):
        """Select widgets with type or name given.
        Give None if you don't care for either."""
        def selectwidget(path, w):
            """Select widget if of type or name given."""
            if ( (wtype is None or w.typename == wtype) and
                 (wname is None or w.name == wname) ):
                idx = self.treemodel.getWidgetIndex(w)
                self.treeview.selectionModel().select(
                    idx, qt4.QItemSelectionModel.Select |
                    qt4.QItemSelectionModel.Rows)

        self.document.walkNodes(selectwidget, nodetypes=('widget',))

    def _selectWidgetSiblings(self, w, wtype):
        """Select siblings of widget given with type."""
        for c in w.parent.children:
            if c is not w and c.typename == wtype:
                idx = self.treemodel.getWidgetIndex(c)
                self.treeview.selectionModel().select(
                    idx, qt4.QItemSelectionModel.Select |
                    qt4.QItemSelectionModel.Rows)
                
    def updateSelectMenu(self):
        """Update edit.select menu."""
        menu = self.parentwin.menus['edit.select']
        menu.clear()

        if len(self.selwidgets) == 0:
            return

        wtype = self.selwidgets[0].typename
        name = self.selwidgets[0].name

        menu.addAction(
            _("All '%s' widgets") % wtype,
            lambda: self._selectWidgetsTypeAndOrName(wtype, None))
        menu.addAction(
            _("Siblings of '%s' with type '%s'") % (name, wtype),
            lambda: self._selectWidgetSiblings(self.selwidgets[0], wtype))
        menu.addAction(
            _("All '%s' widgets called '%s'") % (wtype, name),
            lambda: self._selectWidgetsTypeAndOrName(wtype, name))
        menu.addAction(
            _("All widgets called '%s'") % name,
            lambda: self._selectWidgetsTypeAndOrName(None, name))