BTW [Edward], isn't this documentation, from https://leo-editor.github.io/leo-editor/customizing.html#simple-settings-nodes, incorrect - or am I misunderstanding something?
""" Simple settings nodes have headlines of the form @<type> name = val. These settings set the value of name to val, with the indicated type: """ ISTM that the headlines are of the form @type val or can you actually write @path = <some path> etc? I can find no examples of this... On Saturday, March 23, 2024 at 10:55:16 PM UTC jkn wrote: > 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/a759456a-3923-4931-ac82-d24c25a9c83en%40googlegroups.com.