I think I have an earlier version of this snippet from you somewhere - I 
was going to take a look at it for this purpose. So thanks!

    J^n


On Saturday, March 23, 2024 at 10:42:32 PM UTC tbp1...@gmail.com wrote:

> 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/9b9d6744-4de0-4760-a65e-19228a0eab06n%40googlegroups.com.

Reply via email to