I've been using an "images" subdirectory under the location of the outline, 
or under the @path location if you use one.  It would make backup or 
sharing easier than some random location in the file system.  The script 
could check for its existence and create it if needed.  

Here's how I get the path of the node or it's @path into the clipboard:

"""Copy the effective path of the current node to the clipboard.

This command honors @path directives.
"""
from pathlib import Path

pth = Path(c.fullPath(p))
if pth.exists():
    if pth.is_file():
        direc = pth.parent
    else:
        direc = pth
else:
    direc = Path(g.scanAllAtPathDirectives(c, p))

if direc:
    normdir = str(direc.resolve())
    g.app.gui.replaceClipboardWith(normdir)
else:
    g.es(f"Path {direc} doesn't exist")

BTW, I have this script linked to a button, which is very convenient 
sometimes.
On Saturday, March 23, 2024 at 6:30:21 PM UTC-4 jkn wrote:

> Hi Thomas
>     not sure what an undoer would do here? maybe delete the file? There is 
> no leo-relevant action here (yet)
>
> I'm well aware I don't *need* the main(), but I prefer to write this way. 
> Same as with bash scripts etc. It helps for future modularity, I find. Of 
> course, 'YAGNI', but still. f course you are right that main() could be 
> more descriptive, this is only a POC.
>
> The tricky bit is deciding where to store the clipboard files. Obsidian 
> has a special action when you click on inserted 'snippet' images; it just 
> stores the filename in the 'body', and uses its knowledge of where the 
> snippets are located when you do the equivalent of CTRL-click on the URL
>
> Linking the location of the 'snippets' to the leo file and/or node is an 
> interesting challenge...
>
>
>
> On Saturday, March 23, 2024 at 10:09:59 PM UTC tbp1...@gmail.com wrote:
>
>> Looks pretty straightforward.  Perhaps you'll want to make it undoable 
>> (so far as Leo is concerned).  As a matter of Python programming, defining 
>> a main() function here isn't needed.  If you are only going to use it as a 
>> script, then you don't need a function at all. Just unindent those lines of 
>> code (and delete the "main()" line) and they will run when the script 
>> runs.  No need to call main() at all.   If you want that clipboard part of 
>> the block to run and if it succeeds then insert the markdown text into a 
>> node, then the function shouldn't be called "main" but something more 
>> descriptive.
>>
>> On Saturday, March 23, 2024 at 4:59:25 PM UTC-4 jkn wrote:
>>
>>> OK, here is a simple demonstration of part of the feature I am 
>>> interested in.
>>>
>>> When run with an image in the (global) clipboard, it saves this to a 
>>> local timestamped file (under ~/tmp), and indicates how a markdown 
>>> reference to that file could be inserted.
>>>
>>> There's plenty more needed but this is the QClipboard part, I think.
>>>
>>> import os
>>> import time
>>>     
>>> def unique_png_fname():
>>>     """ return a unique (timestamped) filename to use
>>>     """
>>>     FORMAT="%Y-%m-%d-%H-%M-%S.png"
>>>     return time.strftime(FORMAT)
>>>
>>> def link_string_md(fname):
>>>     """ get markdown format to insert a filename
>>>     """
>>>     return "![[%s]]" % fname
>>>
>>> def main():
>>>     # get clipboard contents - default mode is global clipboard
>>>     cb = g.app.gui.qtApp.clipboard()
>>>     # is it in image format?
>>>     img = cb.image()
>>>     if not img.isNull():
>>>         basefiledir = os.path.expanduser("~/tmp")
>>>         fqfilepath = os.path.join(basefiledir, unique_png_fname())
>>>         img.save(fqfilepath, "PNG")
>>>         g.es("wrote clipboard to:", fqfilepath)
>>>         g.es("could insert:", link_string_md(fqfilepath))
>>>     else:
>>>         g.es("clipboard not in image format")
>>>
>>> main()
>>>
>>>
>>> On Monday, March 11, 2024 at 8:23:42 PM UTC jkn wrote:
>>>
>>>> Doh! should have read the documentation better.
>>>>
>>>> you have to test for a 'null image' using eg. img.isnull()
>>>>
>>>> on with my trivial experiments...
>>>>
>>>>
>>>> On Monday, March 11, 2024 at 8:10:03 PM UTC jkn wrote:
>>>>
>>>>> Has anyone played much with class QClipboard? I did a couple of 
>>>>> trivial experiments but I must be misunderstanding something.
>>>>>
>>>>> for instance, QClipboard.image() returns a non-null value even if the 
>>>>> clipboard does not contain an image.
>>>>>
>>>>>     J^n
>>>>>
>>>>>
>>>>> On Monday, March 11, 2024 at 4:33:23 PM UTC tbp1...@gmail.com wrote:
>>>>>
>>>>>> It turns out that to get the relative path conversion w have to 
>>>>>> remove any quotation marks around the path before running os.relpath(). 
>>>>>> So 
>>>>>> the script becomes:
>>>>>>
>>>>>> """Insert RsT code at cursor to display an image.
>>>>>>
>>>>>> The path to the image file will come from a file dialog.
>>>>>> This action is undoable.
>>>>>> """
>>>>>> PATH = g.app.gui.runOpenFileDialog(c,
>>>>>>     title="Import File",
>>>>>>     filetypes=[("All files", "*"),],
>>>>>>     defaultextension=".*",
>>>>>>     multiple=False)
>>>>>>
>>>>>> if PATH:
>>>>>>     from os.path import relpath
>>>>>>     PATH = PATH.replace('"', '').replace("'", '')
>>>>>>     PATH = relpath(PATH)
>>>>>>     PATH = PATH.replace('\\', '/')
>>>>>>
>>>>>>     IMAGE_TEMPLATE = f'''
>>>>>>
>>>>>> .. figure:: {PATH}
>>>>>>     :scale: 50%
>>>>>>
>>>>>> '''
>>>>>>
>>>>>>     w = c.frame.body.wrapper
>>>>>>     p = c.p
>>>>>>     s = p.b
>>>>>>     u = c.undoer
>>>>>>
>>>>>>     start, _ = w.getSelectionRange()
>>>>>>
>>>>>>     undoType = 'insert-rst-image-code'
>>>>>>     undoData = u.beforeChangeNodeContents(p)
>>>>>>
>>>>>>     head, tail = s[:start], s[start:]
>>>>>>     p.b = head + IMAGE_TEMPLATE + tail
>>>>>>
>>>>>>     c.setChanged()
>>>>>>     p.setDirty()
>>>>>>     u.afterChangeNodeContents(p, undoType, undoData)
>>>>>>     c.redraw()
>>>>>>
>>>>>> On Saturday, March 9, 2024 at 2:04:19 PM UTC-5 Thomas Passin wrote:
>>>>>>
>>>>>>> We can't directly insert an image into a standard Leo node because 
>>>>>>> they are text-only.  I find this very annoying sometimes, especially 
>>>>>>> when I 
>>>>>>> am writing a note and want to include an image.  
>>>>>>>
>>>>>>> But we can do the next best thing - insert an ReStructuredText (RsT) 
>>>>>>> instruction to display an image so that we can view it with the 
>>>>>>> viewrendered3 plugin (VR3). The instruction is short and easy, but it's 
>>>>>>> still annoying to type and I usually forget the exact details. I have a 
>>>>>>> button that toggles VR3 on and off so that it's easy to view an 
>>>>>>> embedded 
>>>>>>> image once the RsT instruction is there. An embedding command would 
>>>>>>> make 
>>>>>>> embedding with Leo as easy as embedding an image in a word processor.  
>>>>>>>  Aha, this is Leo, let's write a script!
>>>>>>>
>>>>>>> Here is a script that pops up a file dialog and inserts a relative 
>>>>>>> path to the chosen file.  There are several small variations which I 
>>>>>>> discuss after the code.
>>>>>>>
>>>>>>> """Insert RsT code at cursor to display an image.
>>>>>>>
>>>>>>> The path to the image file will come from a file dialog.
>>>>>>> This action is undoable.
>>>>>>> """
>>>>>>> PATH = g.app.gui.runOpenFileDialog(c,
>>>>>>>     title="Import File",
>>>>>>>     filetypes=[("All files", "*"),],
>>>>>>>     defaultextension=".*",
>>>>>>>     multiple=False)
>>>>>>>
>>>>>>> if PATH:
>>>>>>>     from os.path import relpath
>>>>>>>     PATH = relpath(PATH)
>>>>>>>     PATH = PATH.replace('\\', '/').replace('"', '').replace("'", '')
>>>>>>>     IMAGE_TEMPLATE = f'''
>>>>>>>
>>>>>>> .. figure:: {PATH}
>>>>>>>     :scale: 50%
>>>>>>>
>>>>>>> '''
>>>>>>>     w = c.frame.body.wrapper
>>>>>>>     p = c.p
>>>>>>>     s = p.b
>>>>>>>     u = c.undoer
>>>>>>>
>>>>>>>     start, _ = w.getSelectionRange()
>>>>>>>
>>>>>>>     undoType = 'insert-rst-image-code'
>>>>>>>     undoData = u.beforeChangeNodeContents(p)
>>>>>>>
>>>>>>>     head, tail = s[:start], s[start:]
>>>>>>>     p.b = head + IMAGE_TEMPLATE + tail
>>>>>>>
>>>>>>>     c.setChanged()
>>>>>>>     p.setDirty()
>>>>>>>     u.afterChangeNodeContents(p, undoType, undoData)
>>>>>>>     c.redraw()
>>>>>>>
>>>>>>> Variations:
>>>>>>> 1.  If you want an absolute path instead of a relative path, delete 
>>>>>>> the lines
>>>>>>>     from os.path import relpath
>>>>>>>     PATH = relpath(PATH)
>>>>>>> with
>>>>>>>
>>>>>>> 2. If you  want to get the path from the clipboard instead of a file 
>>>>>>> dialog, replace the lines
>>>>>>>
>>>>>>> PATH = g.app.gui.runOpenFileDialog(c,
>>>>>>>     title="Import File",
>>>>>>>     filetypes=[("All files", "*"),],
>>>>>>>     defaultextension=".*",
>>>>>>>     multiple=False)
>>>>>>>
>>>>>>> with the line 
>>>>>>>
>>>>>>>     PATH = g.app.gui.getTextFromClipboard()
>>>>>>>
>>>>>>> 3. If you want the embedded image to be full width instead of 50%, 
>>>>>>> delete the line
>>>>>>>
>>>>>>>     :scale: 50%
>>>>>>>
>>>>>>> 4. You can make this work with Markdown or Asciidoc by using their 
>>>>>>> embedding instruction in the TEMPLATE instead of the RsT one.
>>>>>>>
>>>>>>> I have added the command to my own local menu.  VR3 can open in a 
>>>>>>> tab in the log pane; the command for toggling in a tab is 
>>>>>>> *vr3-toggle-tab. * I usually like opening it in the log pane 
>>>>>>> instead of in its own separate pane.
>>>>>>>
>>>>>>> If you would like to create a local menu of your own and don't know 
>>>>>>> how, it's easy.  Just ask and I'll show what to add to 
>>>>>>> myLeoSettings,leo.
>>>>>>>
>>>>>>

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/leo-editor/22a3e7ff-0914-4615-9c72-03b88eef96d5n%40googlegroups.com.

Reply via email to