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 [email protected] 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 [email protected] 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 [email protected] 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 [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/leo-editor/9b9d6744-4de0-4760-a65e-19228a0eab06n%40googlegroups.com.