quickMove.py :  » Development » Leo » Leo-4.7.1-final » leo » plugins » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Development » Leo 
Leo » Leo 4.7.1 final » leo » plugins » quickMove.py
# coding: utf-8
#@+leo-ver=4-thin
#@+node:tbrown.20070117104409:@thin quickMove.py
#@@first
#@<< docstring >>
#@+node:tbrown.20070117104409.1:<< docstring >>
"""Create buttons to quickly move nodes to other nodes

Quickly move nodes from around the tree to one or more target nodes.

Adds 'Move/Clone/Copy To Last Child Button' and 'Move/Clone/Copy To First Child
Button' commands to the Move submenu on the Outline menu, and the context menu,
if contextmenu.py is enabled.

Select a node 'Foo' and then use the 'To Last Child Button' command. The adds a
'to Foo' button to the button bar. Now select another node and click the 'to
Foo' button. The selected node will be moved or cloned to the last child of the
node 'Foo'.

'To First Child Button' works the same way, except that moved nodes are inserted
as the first child of the target node.

"""
#@nonl
#@-node:tbrown.20070117104409.1:<< docstring >>
#@nl

__version__ = '0.7'
#@<< version history >>
#@+node:tbrown.20070117104409.6:<< version history >>
#@+at
# 0.1 by Terry Brown, 2007-01-12
# 0.2 EKR:
# - Revised docstring.
# - Use positions and position methods rather than vnodes.
# - Use checkMoveWithParentWithWarning.
# - Support undo.
# - Clearer command names.
# 0.3 EKR: Various small mods suggested by Terry.
# 0.4 EKR: Added checkMove method.
# 0.5 EKR: Added c arg to p.visNext & p.visBack.
# 0.6 TNB: Store vnodes rather than positions, vnodes are more durable
# 0.7 TNB: Added "clone to" as well as "move to"
#@-at
#@nonl
#@-node:tbrown.20070117104409.6:<< version history >>
#@nl

#@<< imports >>
#@+node:tbrown.20070117104409.2:<< imports >>
import types

import leo.core.leoGlobals as g
import leo.core.leoPlugins as leoPlugins
from mod_scripting import scriptingController
if g.app.gui.guiName() == "qt":
    # for the right click context menu
    from PyQt4 import QtCore
#@-node:tbrown.20070117104409.2:<< imports >>
#@nl

#@+others
#@+node:tbrown.20070117104409.3:init and onCreate
def init():
    leoPlugins.registerHandler('after-create-leo-frame', onCreate)
    g.plugin_signon(__name__)
    return True

def onCreate(tag, keywords):
    quickMove(keywords['c'])
#@nonl
#@-node:tbrown.20070117104409.3:init and onCreate
#@+node:tbrown.20070117104409.4:class quickMove
class quickMove(object):

    """quickMove binds to a controller, adds menu entries for
       creating buttons, and creates buttons as needed
    """

    flavors = [
      # name   first/last  long  short
      ('move', True, "Move", "to"),
      ('copy', True, "Copy", "to"),
      ('clone', True, "Clone", "to"),
      ('bkmk', True, "Bookmark", "to"),
      ('linkTo', False, "Link", "to"),
      ('linkFrom', False, "Link", "from"),
      ('jump', False, "Jump to", ""),
    ]

    #@    @+others
    #@+node:ekr.20070117113133:ctor
    def __init__(self, c):

        self.table = (
            ("Make Buttons Here Permanent",None,self.permanentButton),
            ("Clear Permanent Buttons Here",None,self.clearButton),
        )

        self.imps = []  # implementations, (func,name,text)
        self.txts = {}  # get short from name, for permanent buttons
                        # filled in below

        # build callables for imp list

        for name, first_last, long, short in quickMove.flavors:

            self.txts[name] = short

            if first_last:
                todo = [(True, 'first'), (False, 'last')]
            else:
                todo = [(None, '')]

            for ftrue, which in todo:

                def func(self=self, ftrue=ftrue, name=name, event=None):
                    self.addButton(first=ftrue, type_=name)
                # func = types.MethodType(func, None, quickMove)
                fname = 'func_'+name+'_'+short+'_' +which
                # setattr(quickMove, fname, func)
                if which:
                    which = " "+which.title()+" Child"
                self.imps.append((func, fname, long+" "+short+which+" Button"))

        self.c = c

        c.quickMove = self

        self.buttons = []

        for nd in c.all_unique_nodes():
            if 'quickMove' in nd.u:
                for rec in nd.u['quickMove']:
                    if len(rec) != 2:
                        continue  # silently drop old style permanent button
                    first,type_ = rec
                    self.addButton(first,type_,v=nd)

        c.frame.menu.createNewMenu('Move', 'Outline')

        self.local_imps = []  # make table for createMenuItemsFromTable()
        for func, name, text in self.imps:
            self.local_imps.append((text, None, func))

        self.local_imps.extend(self.table)
        c.frame.menu.createMenuItemsFromTable('Move', self.table)

        if g.app.gui.guiName() == "qt":
                g.tree_popup_handlers.append(self.popup)
    #@-node:ekr.20070117113133:ctor
    #@+node:tbrown.20091207120031.5356:dtor
    def __del__(self, c):

        if g.app.gui.guiName() == "qt":
                g.tree_popup_handlers.remove(self.popup)
    #@-node:tbrown.20091207120031.5356:dtor
    #@+node:ekr.20070117113133.2:addButton
    def addButton (self, first, type_="move", v=None):

        '''Add a button that creates a target for future moves.'''

        c = self.c ; p = c.p
        if v is None:
            v = p.v
        sc = scriptingController(c)

        mb = quickMoveButton(self,v,first,type_=type_)

        txt=self.txts[type_]

        b = sc.createIconButton(
            text = txt + ":" + v.h, # createButton truncates text.
            command = mb.moveCurrentNodeToTarget,
            shortcut = None,
            statusLine = 'Move current node to %s child of %s' % (g.choose(first,'first','last'),v.h),
            bg = "LightBlue"
        )

        self.buttons.append((mb,b))
    #@-node:ekr.20070117113133.2:addButton
    #@+node:tbrown.20091217114654.5372:permanentButton
    def permanentButton (self,event=None):
        """make buttons on this node permanent

        WARNING: includes buttons deleted"""

        c = self.c ; p = c.p

        qm = c.quickMove

        p.v.u['quickMove'] = []
        for mover, button in qm.buttons:
            if mover.target == p.v:
                p.v.u['quickMove'].append((mover.first, mover.type_))

        g.es('Set {0} buttons'.format(len(p.v.u['quickMove'])))
    #@-node:tbrown.20091217114654.5372:permanentButton
    #@+node:tbrown.20091217114654.5374:clearButton
    def clearButton (self,event=None):
        """clear permanent buttons specs from uA"""
        c = self.c ; p = c.p
        g.es('Removing {0} buttons'.format(len(p.v.u.get('quickMove',[]))))
        if 'quickMove' in p.v.u:
            del p.v.u['quickMove']
    #@-node:tbrown.20091217114654.5374:clearButton
    #@+node:tbrown.20091207102637.11494:popup
    def popup(self, c, p, menu):
        """make popup menu entry"""

        if c != self.c:
            return  # wrong commander

        pathmenu = menu.addMenu("Move")

        for name,dummy,command in self.local_imps:
            a = pathmenu.addAction(name)
            a.connect(a, QtCore.SIGNAL("triggered()"), command)
    #@-node:tbrown.20091207102637.11494:popup
    #@-others

#@-node:tbrown.20070117104409.4:class quickMove
#@+node:tbrown.20070117104409.5:class quickMoveButton
class quickMoveButton:

    """contains target data and function for moving node"""

    #@    @+others
    #@+node:ekr.20070117121326:ctor
    def __init__(self, owner, target, first, type_):

        self.c = owner.c
        self.owner = owner
        self.target = target
        self.targetHeadString = target.h
        self.first = first
        self.type_ = type_
    #@-node:ekr.20070117121326:ctor
    #@+node:ekr.20070117121326.1:moveCurrentNodeToTarget
    def moveCurrentNodeToTarget(self):

        '''Move the current position to the last child of self.target.'''

        c = self.c
        p = c.p
        p2 = c.vnode2position(self.target)
        u = c.undoer

        if not c.positionExists(p2):
            g.es('Target no longer exists: %s' % self.targetHeadString,color='red')
            return

        if self.type_ in ('clone', 'move'):  # all others are always valid?
            if p.v == p2.v or not self.checkMove(p,p2):
                g.es('Invalid move: %s' % (self.targetHeadString),color='red')
                return

        bunch = c.undoer.beforeMoveNode(p)
        p2.expand()
        nxt = p.visNext(c) or p.visBack(c)
        nxt = nxt.v
        # store a vnode instead of position as positions are too easily lost

        if self.type_ == 'clone':
            p = p.clone()

        if self.type_ in ('move', 'clone'):
            if self.first:
                p.moveToFirstChildOf(p2)
            else:
                p.moveToLastChildOf(p2)
        elif self.type_ == 'bkmk':
            unl = self.computeUNL(p)  # before tree changes
            if self.first:
                nd = p2.insertAsNthChild(0)
            else:
                nd = p2.insertAsLastChild()
            nd.h = p.h
            nd.b = unl

        elif self.type_ == 'copy':
            if self.first:
                nd = p2.insertAsNthChild(0)
                p.copyTreeFromSelfTo(nd)
            else:
                nd = p2.insertAsLastChild()
                p.copyTreeFromSelfTo(nd)

        elif self.type_ in ('linkTo', 'linkFrom'):
            blc = getattr(c, 'backlinkController', None)
            if blc is None:
                g.es("Linking requires backlink.py plugin")
                return
            if self.type_ == 'linkTo':
                blc.vlink(p.v, p2.v)
            else:
                blc.vlink(p2.v, p.v)

        if self.type_ in ('bkmk', 'clone', 'copy', 'move'):
            nxt = c.vnode2position(nxt)
        elif self.type_ == 'jump':
            nxt = c.vnode2position(self.target)
        else:
            nxt = None  # linkTo / linkFrom don't move

        if nxt is not None and c.positionExists(nxt):
            c.selectPosition(nxt)
        c.undoer.afterMoveNode(p,'Quick Move', bunch)
        c.setChanged(True)
        c.redraw()
    #@-node:ekr.20070117121326.1:moveCurrentNodeToTarget
    #@+node:ekr.20070123061606:checkMove
    def checkMove (self,p,p2):

        c = self.c

        for z in p2.parents():
            if z == p:
                return False

        return (
            c.checkMoveWithParentWithWarning (p,p2,warningFlag=False) and
            c.checkMoveWithParentWithWarning (p2,p,warningFlag=False)
        )
    #@-node:ekr.20070123061606:checkMove
    #@+node:tbrown.20100114111020.15726:computeUNL
    def computeUNL(self, p):

        p = p.copy()
        heads = []
        while p:
            heads.insert(0, p.h)
            p = p.parent()
        return "@url "+"-->".join(heads)
    #@-node:tbrown.20100114111020.15726:computeUNL
    #@-others
#@-node:tbrown.20070117104409.5:class quickMoveButton
#@-others
#@-node:tbrown.20070117104409:@thin quickMove.py
#@-leo
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.