UNO: copy a slide between 2 impress documents

asked 2019-08-15 01:35:35 +0200

Hi-Angel gravatar image

updated 2019-08-15 02:37:06 +0200

As title says it. So far I found this post which has code to copy a slide: it is done with:

dispatcher.executeDispatch(srcController.Frame, ".uno:Copy", "", 0, ())
dispatcher.executeDispatch(dstController.Frame, ".uno:Paste", "", 0, ())

The Paste part works for me, but the Copy doesn't. And I think I know why: this likely supposed to work the same as Ctrl+c would. But just after a document opened EditCopy menu is grayed out, so the hotkey wouldn't do anything either. Any ideas how to make it work?

Bonus points if you know how to copy a slide without using the dispatcher, which creates this overloaded complex function as in code below. I wonder why such simple task requires that much code, I'd really expect to just do something like dstController.copySlide(slide).

For reference, below is a python code that connects to LO server, opens 2 odp documents (with hardcoded paths), and tries to copy a slide from one document to another (but since Copy doesn't work, it simply pastes random content from the clipboard):

import uno
import os

# run libreoffice as:
# soffice --calc --accept="socket,host=localhost,port=2002;urp;StarOffice.ServiceManager"

def connectToLO():
    # get the uno component context from the PyUNO runtime
    localContext = uno.getComponentContext()
    resolver = localContext.ServiceManager.createInstanceWithContext(
        "", localContext )
    # connect to the running office
    ctx = resolver.resolve( "uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext" )
    smgr = ctx.ServiceManager
    desktop = smgr.createInstanceWithContext( "",ctx)
    return (desktop, smgr)

def absoluteUrl(filename):
    """Constructs absolute path to the current dir in format required by PyUNO"""
    mbPrefix = '' if filename[0] in '/~' else os.path.realpath('.') + '/'
    return 'file:///' + mbPrefix + os.path.expanduser(filename)

def copySlideTo(srcApp, dstApp, slide, insert_after, smgr):
    srcController = srcApp.CurrentController
    dstController = dstApp.CurrentController
    dispatcher = smgr.createInstance("")
    dispatcher.executeDispatch(srcController.Frame, ".uno:Copy", "", 0, ())
    dispatcher.executeDispatch(dstController.Frame, ".uno:Paste", "", 0, ())

(desktop, smgr) = connectToLO()
app1 = desktop.loadComponentFromURL(absoluteUrl("/tmp/SlideTablesSample.odp") ,"_blank", 0, ())
app2 = desktop.loadComponentFromURL(absoluteUrl("/tmp/SlideTablesSample.odp") ,"_blank", 0, ())
slide = app1.DrawPages.getByIndex(0)
copySlideTo(app1, app2, slide, 0, smgr)
edit retag flag offensive close merge delete


FWIW, I figured I can execute for src and dst before copy-paste code like this dispatcher.executeDispatch(srcController.Frame, ".uno:DiaMode", "", 0, ()). I noticed it in the original code I referenced to. I kind of makes it work, but for some reason it breaks all the other code, like for example slide I was using does not have Model field anymore. Also it seems that this line of code with a real document takes noticeable amount of time, CPU, and RAM (probably because it changes visual representation in the appeared window). So, well, this is pretty bad.

Hi-Angel gravatar imageHi-Angel ( 2019-08-15 03:02:05 +0200 )edit