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/ef0418c9-0577-4f39-9246-886674f62fbbn%40googlegroups.com.

Reply via email to