kaiuweheinz

Q: AppleScript to create thumbnail of selected file with hyperlink to the URL of the file

Hi,

 

I need an AppleScript to copy to the clipboard a thumbnail of a selected file (s. image 1 below) with a hyperlink to the URL of that selected file. Bildschirmfoto 2016-09-11 um 23.57.44.png

 

I have a script that allows me to get the URL of the selected file and copy it to the clipboard. But then I have to paste the URL in my Document, go back to finder, make a screenshot of the file's thumbnail, paste that screenshot and insert the (manually copied) URL of the file (chosing the context menu of the image) (s. image 2 below):

 

Bildschirmfoto 2016-09-12 um 00.06.31.png

 

Is there a way to automate this?

 

I could make the screenshot manually, that is actually no problem, but then I'd need to attribute this screenshot to a clipboard 1, go back and get the URL of the file and attribute it to clipboard 2 and then go to my document and paste clipboard 1 first, chose the context menu 'hyperlink' and paste clipboard 2.

 

I'd be thankful for help !!

 

(I am a high school language teacher and this is a daylily repetitive task)

 

Regards,

Kai-Uwe

MacBook Air, OS X El Capitan (10.11.6)

Posted on Sep 11, 2016 3:16 PM

Close

Q: AppleScript to create thumbnail of selected file with hyperlink to the URL of the file

  • All replies
  • Helpful answers

first Previous Page 4 of 4
  • by VikingOSX,

    VikingOSX VikingOSX Sep 19, 2016 6:05 AM in response to kaiuweheinz
    Level 7 (21,014 points)
    Mac OS X
    Sep 19, 2016 6:05 AM in response to kaiuweheinz

    What an interesting coding journey.

     

    May I suggest that you update the v2.1 code by replacing:

     

    -- Finder selected documents are made into a file list

    tell application "Finder"

           set inPath to the selection as alias list

    end tell


    with the following:


    -- Finder selected documents are made into a file list

    -- Error handling if nothing selected before script is run.

    tell application "Finder"

           set sel to selection as alias list

           if sel = {} then

                my error_handler(-128, "No documents selected in Finder.")

                return

           end if

    end tell

    return

  • by kaiuweheinz,

    kaiuweheinz kaiuweheinz Sep 19, 2016 6:13 AM in response to VikingOSX
    Level 1 (8 points)
    Mac OS X
    Sep 19, 2016 6:13 AM in response to VikingOSX

    Dear VikingOSX,

     

    I was just about to write you too when your message came in - I will replace the suggested lines!

     

    Here is why I was going to write to you: Today I came to school, started the projector, opened my protocol: no thumbnails, just links I had to click through in order to know what was hidden behind. I later understood: it is because the thumbnails were stored locally on my computer at home. Is there a way to implement the thumbnail.pngs into the document itself (which would make it bigger but environment independent)? Is there a way display visually in any way the filename?

     

    Thank you so much in advance for any further assistance,

    Kai-Uwe

  • by Hiroto,

    Hiroto Hiroto Sep 19, 2016 6:30 AM in response to kaiuweheinz
    Level 5 (7,306 points)
    Sep 19, 2016 6:30 AM in response to kaiuweheinz

    My pleasure! And thank you for your kind words.

     

    Some supplement.

     

    1) I noticed document link in odt file becomes invalid when the file is moved to different location because link is saved as relative link by default. If you're experiencing this, you can change the behaviour by Preferences… > Load/Save > General > 'Save URLs relative to file system' check box.

     

    h.png

     

    cf.

    Relative and Absolute Links

    https://help.libreoffice.org/Common/Relative_and_Absolute_Links

     

     

     

    2) Regarding my last script creating thumbnail image for single file in Finder selection and putting the thumbnail jpeg data in the clipboard, I noticed it does not corretly resize thumbnail image obtained from icon image. Creating thumbnail from icon is a fallback measure in case QLThumbnailImageCreate() function fails, e.g., in case selection is directory etc, and it is not in your original requests. Anyway, I have fixed the code so as to handle this case correctly. The revised and corrected version is as follows.

     

     

    --APPLESCRIPT
    tell application "Finder"
        set ff to selection as alias list
    end tell
    set args to ""
    repeat with a in ff
        set args to args & a's POSIX path's quoted form & space
    end repeat
    
    do shell script "/usr/bin/python <<'EOF' - " & args & "
    # coding: utf-8
    # 
    #   file:
    #       qlthumbnail_single.py
    # 
    #   function:
    #       create thumbnail of the first file and put image data in the clipboard
    #       * if QLThumbnailImageCreate() fails, create thumbnail from icon image
    # 
    #   usage:
    #       ./qlthumbnail_single.py file
    # 
    #   version:
    #       0.11
    #           - fixed code to obtain thumbnail image data of specified size from icon image
    #       0.10a
    #           - using -
    #               import Quartz.CoreGraphics as CG
    #               import AppKit as OSX
    #       0.10
    #           - draft
    # 
    #   written by Hiroto, 2016-09
    # 
    import sys, os, objc
    import Quartz.CoreGraphics as CG    # required for QLThumbnailImageCreate() using CG symbols
    import AppKit as OSX
    
    QL_BRIDGESUPPORT = '''<?xml version=\"1.0\" standalone=\"yes\"?>
    <!DOCTYPE signatures SYSTEM \"file://localhost/System/Library/DTDs/BridgeSupport.dtd\">
    <signatures version=\"0.9\">
       <constant type=\"^{__CFString=}\" name=\"kQLThumbnailOptionIconModeKey\"></constant>
        <constant type=\"^{__CFString=}\" name=\"kQLThumbnailOptionScaleFactorKey\"></constant>
        <function name=\"QLThumbnailImageCreate\">
            <arg type=\"^{__CFAllocator=}\"></arg>
            <arg type=\"^{__CFURL=}\"></arg>
            <arg type=\"{CGSize=ff}\" type64=\"{CGSize=dd}\"></arg>
            <arg type=\"^{__CFDictionary=}\"></arg>
            <retval type=\"^{CGImage=}\"></retval>
        </function>
    </signatures>'''
    
    objc.parseBridgeSupport(
        QL_BRIDGESUPPORT, 
        globals(),
        objc.pathForFramework('/System/Library/Frameworks/QuickLook.framework')
    )
    
    def main():
        data = None
        for f in [ a.decode('utf-8') for a in sys.argv[1:2] ]:  # process the first file only
            iurl = OSX.NSURL.fileURLWithPath_(f)
            cgi = QLThumbnailImageCreate(
                OSX.kCFAllocatorDefault,
                iurl,
                CG.CGSizeMake(*IMAGE_SIZE),
                { kQLThumbnailOptionIconModeKey : OSX.kCFBooleanTrue }
            )
            if not cgi:
                ctx = CG.CGBitmapContextCreate(
                    None, IMAGE_SIZE[0], IMAGE_SIZE[1], 8, 0, 
                    CG.CGColorSpaceCreateWithName(CG.kCGColorSpaceGenericRGB), 
                    CG.kCGImageAlphaPremultipliedLast)
                icon = OSX.NSWorkspace.sharedWorkspace().iconForFile_(iurl.path())
                if icon:
                    cgi = OSX.NSBitmapImageRep.imageRepWithData_(icon.TIFFRepresentation()).CGImage()
                    CG.CGContextDrawImage(ctx, CG.CGRectMake(0, 0, *IMAGE_SIZE), cgi)
                cgi = CG.CGBitmapContextCreateImage(ctx)
    
            brep = OSX.NSBitmapImageRep.alloc().initWithCGImage_(cgi)
            data = brep.representationUsingType_properties_(OSX.NSJPEGFileType, {})
    
        if data:
            # put jpeg data in clipboard
            pboard = OSX.NSPasteboard.generalPasteboard()
            pbtype = 'public.jpeg'
            pboard.declareTypes_owner_([pbtype], None)
            pboard.setData_forType_(data, pbtype)
    
    IMAGE_SIZE = (200.0, 200.0)
    main()
    EOF"
    --END OF APPLESCRIPT
    

     

     

     

    And in case, the original python script is as follows:

     

     

    #!/usr/bin/python
    # coding: utf-8
    # 
    #   file:
    #       qlthumbnail_single.py
    # 
    #   function:
    #       create thumbnail of the first file and put image data in the clipboard
    # 
    #   usage:
    #       ./qlthumbnail_single.py file
    # 
    #   version:
    #       0.11
    #           - fixed code to obtain thumbnail image data of specified size from icon image
    #       0.10a
    #           - using -
    #               import Quartz.CoreGraphics as CG
    #               import AppKit as OSX
    #       0.10
    #           - draft
    # 
    #   written by Hiroto, 2016-09
    # 
    import sys, os, objc
    import Quartz.CoreGraphics as CG    # required for QLThumbnailImageCreate() using CG symbols
    import AppKit as OSX
    
    QL_BRIDGESUPPORT = '''<?xml version="1.0" standalone="yes"?>
    <!DOCTYPE signatures SYSTEM "file://localhost/System/Library/DTDs/BridgeSupport.dtd">
    <signatures version="0.9">
       <constant type="^{__CFString=}" name="kQLThumbnailOptionIconModeKey"></constant>
        <constant type="^{__CFString=}" name="kQLThumbnailOptionScaleFactorKey"></constant>
        <function name="QLThumbnailImageCreate">
            <arg type="^{__CFAllocator=}"></arg>
            <arg type="^{__CFURL=}"></arg>
            <arg type="{CGSize=ff}" type64="{CGSize=dd}"></arg>
            <arg type="^{__CFDictionary=}"></arg>
            <retval type="^{CGImage=}"></retval>
        </function>
    </signatures>'''
    
    objc.parseBridgeSupport(
        QL_BRIDGESUPPORT, 
        globals(),
        objc.pathForFramework('/System/Library/Frameworks/QuickLook.framework')
    )
    
    def main():
        data = None
        for f in [ a.decode('utf-8') for a in sys.argv[1:2] ]:  # process the first file only
            iurl = OSX.NSURL.fileURLWithPath_(f)
            cgi = QLThumbnailImageCreate(
                OSX.kCFAllocatorDefault,
                iurl,
                CG.CGSizeMake(*IMAGE_SIZE),
                { kQLThumbnailOptionIconModeKey : OSX.kCFBooleanTrue }
            )
            if not cgi:
                ctx = CG.CGBitmapContextCreate(
                    None, IMAGE_SIZE[0], IMAGE_SIZE[1], 8, 0, 
                    CG.CGColorSpaceCreateWithName(CG.kCGColorSpaceGenericRGB), 
                    CG.kCGImageAlphaPremultipliedLast)
                icon = OSX.NSWorkspace.sharedWorkspace().iconForFile_(iurl.path())
                if icon:
                    cgi = OSX.NSBitmapImageRep.imageRepWithData_(icon.TIFFRepresentation()).CGImage()
                    CG.CGContextDrawImage(ctx, CG.CGRectMake(0, 0, *IMAGE_SIZE), cgi)
                cgi = CG.CGBitmapContextCreateImage(ctx)
    
            brep = OSX.NSBitmapImageRep.alloc().initWithCGImage_(cgi)
            data = brep.representationUsingType_properties_(OSX.NSJPEGFileType, {})
    
        if data:
            # put jpeg data in clipboard
            pboard = OSX.NSPasteboard.generalPasteboard()
            pbtype = 'public.jpeg'
            pboard.declareTypes_owner_([pbtype], None)
            pboard.setData_forType_(data, pbtype)
    
    IMAGE_SIZE = (200.0, 200.0)
    main()
    

     

     

     

    Best wishes from Japan.

    Hiroto

  • by kaiuweheinz,

    kaiuweheinz kaiuweheinz Sep 19, 2016 8:15 AM in response to Hiroto
    Level 1 (8 points)
    Mac OS X
    Sep 19, 2016 8:15 AM in response to Hiroto

    Dear Hiroto,

     

    concerning 1): I unchecked the relative URLs. Here is the result:

    Bildschirmfoto 2016-09-19 um 17.02.31.png

     

    Is there any explanation for this?

     

    Concerning 2) I need to run that this evening. Thank you very much!

     

    Kind regards,

    Kai-Uwe

  • by VikingOSX,

    VikingOSX VikingOSX Sep 19, 2016 11:34 AM in response to kaiuweheinz
    Level 7 (21,014 points)
    Mac OS X
    Sep 19, 2016 11:34 AM in response to kaiuweheinz

    I am currently testing a portable solution that takes advantage of mounted external media (e.g. USB stick, SDHC card). It will generate a work.html file that has links to files and thumbnails on that media, and when you generate the ODT from LibreOffice, back onto the media, it too will retain this information. Then you open the ODT from the media at school, and projector away.

     

    I probably won't have something until tomorrow, as two yards to mow, and other distractions.

  • by Hiroto,

    Hiroto Hiroto Sep 19, 2016 12:53 PM in response to kaiuweheinz
    Level 5 (7,306 points)
    Sep 19, 2016 12:53 PM in response to kaiuweheinz

    Hello

     

    I'd guess those thumbnails in your screenshot are not from my script because my script embedds thumbnail images into html document by means of data uri.

     

    Generally, missing thumbnail means the thumbnail image file is not found in the location specified by its URL and missing target file means the file is not found in the location specified by its URL.

     

    If you're going to move around the odt document which includes hyperlinks to local files, you'd better create an enclosing directory and move the directory. E.g., create a directory tree such as:

     

    dir/a.odt
    dir/a_files/target_file_1.txt
    dir/a_files/target_file_2.docx
    dir/a_files/thumbnails/thumbnail_1.jpg
    dir/a_files/thumbnails/thumbnail_2.jpg
    

     

     

    and move enclosing directory dir in order to move a.odt along with its linked resources, provided that URLs in a.odt document are relative URLs by saving the document with the Preferences… > Load/Save > General > 'Save URLs relative to file system' being checked.

     

    * If thumbnails are created by my script (qlthumbnail.py, but not qlthumbnail_single.py), the thumbnail images are embedded in a.odt file itself and thus dir/a_files/thumbnails directory and its contents are not necessary.

     

    * In this scheme, you'd need to have dir/a_files directory and its contents ready before creating hyperlinks to them in dir/a.odt, and a.odt must be either a new document which is to be saved as dir/a.odt or an existing document which has been saved as dir/a.odt. (If you create links in other_dir/a.odt and move it to dir/a.odt, relative links won't survive unless dir and other_dir are in the same directory)

     

    Hope this explains the issue and possible solution.

    H

  • by kaiuweheinz,

    kaiuweheinz kaiuweheinz Sep 19, 2016 7:51 PM in response to Hiroto
    Level 1 (8 points)
    Mac OS X
    Sep 19, 2016 7:51 PM in response to Hiroto

    Dear Hiroto,

     

    the reason why I preferred VikingOSX's script to yours was the 1-step-facility. But it is true that your script embeds the thumbnails and thus turns out to be more practical. I have several thousand sheets - I must choose if I want to collect all the thumbnails in a thumb folder that needs to be synced but that keeps the file size small or if I want to embed the thumbnails.

    That's why I tend to the latter, which means choosing your solution. But first: in order to have the same visual output the URLs above the thumbnails and any other character (like for example the "~") would have to be removed. Second: the 3-step-procedure would need to be shortened: Therefor I added to your script that the out.html is automatically opened in LibreOffice. Still 2 more steps than in VikingOSX's solution. how can I make the script wait until out.html is opened in LibreOffice? That would reduce the procedure to only 1 step. That's what I am currently trying to code: when the "Save as" dialog appears, instead of clicking OK I launch a second Applescript that clicks OK for me, has OpenOffice open out.odt and makes LibreOffice close. Only then there would be equality between your approach and VikingOSX'. And as yours has the beating advantage of embedding the thumbnails, this would be the direction to go but ...

     

    ... my script (put together with fragments of yours and VikingOSX_) doesn't work yet as I want it to:

     

    -- Save out.html as out.odt

    tell application "libreOffice"

      activate

      tell application "System Events"

      try

      keystroke "s" using {command down, shift down}

      delay 0.1

      end try

     

    -- Problem n°1: I don't know how to make the script choose the file type so I have to do it manually and then click ok to make the script continue

      display dialog "Hast Du 'Save as ... odt.file' gewählt?" -- buttons {"Ja", "Nein"}

      tell application "libreOffice"

      activate

     

      tell application "System Events"

      keystroke return

      delay 1

      tell application "libreOffice"

      quit

      end tell

      end tell

      end tell

      end tell

    end tell

     

     

    set out to (path to desktop)'s POSIX path & "/out.odt"

    do shell script "/Applications/OpenOffice.app/Contents/MacOS/soffice --writer " & out's quoted form & " &>/dev/null &"

     

    tell application "NeoOffice"

      activate

    -- problem n° 2: I don't know how to make the script wait for the appearance out.odt in OpenOffice

      display dialog "Hat OpenOffice 'outodt' geöffnet?" -- buttons {"Ja", "Nein"} -- translated: "Has OpenOffice opened out.odt yet?"

      activate

      tell application "System Events"

      try

      keystroke "a" using {command down}

      delay 0.1

      keystroke "x" using {command down}

      delay 0.1

      keystroke "w" using {command down}

      delay 0.1

      -- LEFT: (key code 123)

      -- RIGHT: key code 124)

      -- UP: (key code 126)

      -- DOWN: (key code 125)

      end try

      try

      key code 124

      keystroke return

      end try

      end tell

    end tell

    delay 3

    tell application "Finder"

      try

      delete the file "out.odt" of the desktop

      end try

      try

      delete the file "out.html" of the desktop

      end try

    end tell

     

    Dear VikingOSX,

    please don't bother to code a portable solution given the fact that you invested already more than I could ever imagine and because for the above mentioned reasons imbedded thumbnails are more practical for me. If Hiroto removes the characters and URLS so that I have just the thumbnails that would suit me already. If then the following procedure could be automated (I you have some time left you could give me a hint as to how to solve problem n°1 and 2 in my script), then I'd be really happy.

     

     

    Thank you both so much for all investment which will be - as I wrote - rewarded.

     

    Kind regards,

    Kai-Uwe

     

     

    Thank you for all effort

  • by Hiroto,

    Hiroto Hiroto Sep 20, 2016 12:29 PM in response to kaiuweheinz
    Level 5 (7,306 points)
    Sep 20, 2016 12:29 PM in response to kaiuweheinz

    Hello

     

    You might try the following AppleScript script which uses GUI scripting on LibreOffice save-as dialogue.

     

    It will create ~/Desktop/out.html, open out.html in LibreOffice Writer, save it as ~/Desktop/out.odt and open out.odt in NeoOffice Writer. NeoOffice code is not tested because I don't have NeoOffice. Briefly tested with OpenOffice instead.

     

    Also qlthumbnail.py is revised so as to create thumbnail from icon in case QLThumbnailImageCreate() fails, along with other minor changes in html output.

     

    Tested with pyobjc 2.2b3 and python 2.6.1 and LibreOffice 4.3.7.2 and OpenOffice 4.0.1 under OS X 10.6.8.

     

    * You need to enable GUI scripting in order for this script to work.

     

    cf.

    OS X: Using AppleScript with Accessibility and Security features in Mavericks

    https://support.apple.com/HT202802

     

    Automating the User Interface

    https://developer.apple.com/library/content/documentation/LanguagesUtilities/Con ceptual/MacAutomationScriptingGuide/AutomatetheUserInterface.html

     

     

     

    --APPLESCRIPT
    _main()
    on _main()
        -- get Finder selection
        tell application "Finder"
            set aa to selection as alias list
        end tell
        repeat with a in aa
            set a's contents to a's POSIX path
        end repeat
        
        -- create out.html
        set out_html to (path to desktop)'s POSIX path & "out.html"
        create_qlthumbnails_html(aa, out_html)
        
        -- create out.odt
        set out_odt to libreoffice_save_as_odt(out_html)
    
        -- open out.odt in OpenOffice / NeoOffice by its soffice executable (* NeoOffice command is not tested)
        --do shell script "/Applications/OpenOffice.app/Contents/MacOS/soffice --writer " & out_odt's quoted form & " &>/dev/null &"
        do shell script "/Applications/NeoOffice.app/Contents/MacOS/soffice --writer " & out_odt's quoted form & " &>/dev/null &"
    end _main
    
    on create_qlthumbnails_html(argv, out)
        (*
            list argv : list of POSIX path of source files
            string out : POSIX path of output html file
            * this handler puts output html data in the clipboard as well
        *)
        set args to ""
        repeat with a in {} & argv
            set args to args & a's quoted form & space
        end repeat
        do shell script "/usr/bin/python <<'EOF' - " & args & " > " & out's quoted form & "
    # coding: utf-8
    # 
    #   file:
    #       qlthumbnail.py
    # 
    #   function:
    #       print html text of hyperlinked thumbnail(s) of given file(s) and put html data in the clipboard
    #       * if QLThumbnailImageCreate() fails, create thumbnail from icon image
    # 
    #   usage:
    #       ./qlthumbnail.py file [file ...] > out.html
    # 
    #   version:
    #       0.11a
    #           - increased pyobjc performance (for recent versions of pyobjc) by using: 
    #               - import Quartz.CoreGraphics as CG
    #               - import AppKit as OSX
    #       0.11
    #           - added code to generate thumbnail from icon if QLThumbnailImageCreate() fails
    #           - modified html output:
    #               - let each entry be contained in div.container
    #               - defined style on div.container
    #               - removed anchor from file name
    #               - added title attribute with value as file name to anchor element
    #       0.10b
    #           - modified html output:
    #               - changed path to file name in output
    #               - removed separator (~) for each entry in output
    #       0.10a
    #           - modified html output:
    #               - added anchor element for path string
    #       0.10
    #           - draft
    # 
    #   written by Hiroto, 2016-09
    # 
    import sys, os, objc
    import base64, re
    import Quartz.CoreGraphics as CG    # required for QLThumbnailImageCreate() using CG symbols
    import AppKit as OSX
    
    QL_BRIDGESUPPORT = '''<?xml version=\"1.0\" standalone=\"yes\"?>
    <!DOCTYPE signatures SYSTEM \"file://localhost/System/Library/DTDs/BridgeSupport.dtd\">
    <signatures version=\"0.9\">
       <constant type=\"^{__CFString=}\" name=\"kQLThumbnailOptionIconModeKey\"></constant>
        <constant type=\"^{__CFString=}\" name=\"kQLThumbnailOptionScaleFactorKey\"></constant>
        <function name=\"QLThumbnailImageCreate\">
            <arg type=\"^{__CFAllocator=}\"></arg>
            <arg type=\"^{__CFURL=}\"></arg>
            <arg type=\"{CGSize=ff}\" type64=\"{CGSize=dd}\"></arg>
            <arg type=\"^{__CFDictionary=}\"></arg>
            <retval type=\"^{CGImage=}\"></retval>
        </function>
    </signatures>'''
    
    objc.parseBridgeSupport(
        QL_BRIDGESUPPORT, 
        globals(),
        objc.pathForFramework('/System/Library/Frameworks/QuickLook.framework')
    )
    
    def html_escape(s):
        s = re.sub(r'&', '&amp;', s)
        s = re.sub(r'<', '&lt;', s)
        s = re.sub(r'>', '&gt;', s)
        return s
    
    def main():
        # html opening
        s = u'''<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">
    <html>
    <head>
        <meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">
        <style>
            div.container { display: inline-block; margin: 10px; text-align: center; }
        </style>
    </head>
    <body>'''
    
        # html entry template
        tmpl = u'''
    <div class=\"container\">
        <p>
            <a href=\"%s\" title=\"%s\">
                <img src=\"data:%s;base64,%s\" />
            </a>
        </p>
        <p>%s</p>
    </div>
    '''
        for f in [ a.decode('utf-8') for a in sys.argv[1:] ]:
            iurl = OSX.CFURLCreateFromFileSystemRepresentation(OSX.kCFAllocatorDefault, f.encode('utf-8'), len(f.encode('utf-8')), False)
            cgi = QLThumbnailImageCreate(
                OSX.kCFAllocatorDefault,
                iurl,
                CG.CGSizeMake(*IMAGE_SIZE),
                { kQLThumbnailOptionIconModeKey : OSX.kCFBooleanTrue }
            )
            if not cgi:
                ctx = CG.CGBitmapContextCreate(
                    None, IMAGE_SIZE[0], IMAGE_SIZE[1], 8, 0, 
                    CG.CGColorSpaceCreateWithName(CG.kCGColorSpaceGenericRGB), 
                    CG.kCGImageAlphaPremultipliedLast)
                icon = OSX.NSWorkspace.sharedWorkspace().iconForFile_(iurl.path())
                if icon:
                    cgi = OSX.NSBitmapImageRep.imageRepWithData_(icon.TIFFRepresentation()).CGImage()
                    CG.CGContextDrawImage(ctx, CG.CGRectMake(0, 0, *IMAGE_SIZE), cgi)
                cgi = CG.CGBitmapContextCreateImage(ctx)
            brep = OSX.NSBitmapImageRep.alloc().initWithCGImage_(cgi)
            data = brep.representationUsingType_properties_(OSX.NSJPEGFileType, {})
            byts = data.getBytes_length_(None, data.length())
            b64s = base64.b64encode(byts)
    
            # append html entry for this file
            name_e = html_escape(os.path.basename(iurl.path()))
            s += tmpl % (iurl.absoluteString(), name_e, 'image/jpeg', b64s, name_e)
    
        # html closing
        s += u'</body></html>'
        
        # print html
        print s.encode('utf-8')
    
        # put html data in clipboard
        html = OSX.NSString.stringWithString_(s).dataUsingEncoding_(OSX.NSUTF8StringEncoding)
        pboard = OSX.NSPasteboard.generalPasteboard()
        pbtype = 'public.html'
        pboard.declareTypes_owner_([pbtype], None)
        pboard.setData_forType_(html, pbtype)
    
    IMAGE_SIZE = (200.0, 200.0)
    main()
    EOF"
    end create_qlthumbnails_html
    
    on libreoffice_save_as_odt(f)
        (*
            string f : POSIX path of input file
            return string: POSIX path of resultant file
        *)
        -- check whether libreoffice is already running in order to quit it at end only if it is not
        tell application id "org.libreoffice.script" to set _was_running to running
        
        -- open f in LibreOffice Writer
        do shell script "/Applications/LibreOffice.app/Contents/MacOS/soffice --writer " & f's quoted form & " &>/dev/null &"
        
        -- perform save as odt
        tell application "System Events"
            set furl to (disk item f)'s URL
            tell (process 1 whose bundle identifier = "org.libreoffice.script")
                -- wait for target document ready
                tell (window 1 whose subrole = "AXStandardWindow")
                    repeat until (exists) and attribute "AXDocument"'s value = furl
                        tell current application to delay 0.2
                    end repeat
                end tell
                -- make process front most
                set frontmost to true
                -- perform save-as
                keystroke "s" using {command down, shift down} -- invoke save-as
                tell (window 1 whose subrole = "AXDialog") -- save-as dialogue
                    -- wait for dialogue ready
                    repeat until exists
                        tell current application to delay 0.2
                    end repeat
                    -- show file type popup menu
                    tell group 1 -- file type part
                        tell pop up button 1 -- file type popup menu
                            perform action "AXShowMenu"
                        end tell
                    end tell
                end tell
                keystroke "ODF" & return -- select "ODF Text Document (.odt)"
                keystroke return -- invoke save
                -- replace existing destination if present
                tell (window 1 whose subrole = "AXDialog") -- save-as dialogue
                    tell sheet 1 -- sheet asking whether to replace existing file or not
                        if exists then click (button 1 whose focused is false) -- replace button
                    end tell
                end tell
                -- close front document
                tell (window 1 whose subrole = "AXStandardWindow")
                    set furl1 to attribute "AXDocument"'s value -- get file url of resultant file
                    click (button 1 whose subrole = "AXCloseButton") -- close
                end tell
            end tell
        end tell
        -- quit libreoffice if it is not originally running
        if not _was_running then tell application id "org.libreoffice.script" to quit
        
        -- return POSIX path of resultant file
        return do shell script "perl -CA -MURI::file -e 'print URI->new($ARGV[0])->file;' " & furl1's quoted form without altering line endings
    end libreoffice_save_as_odt
    --END OF APPLESCRIPT
    

     

     

     

    And in case, the core python script is as follows.

     

     

    #!/usr/bin/python
    # coding: utf-8
    # 
    #   file:
    #       qlthumbnail.py
    # 
    #   function:
    #       print html text of hyperlinked thumbnail(s) of given file(s) and put html data in the clipboard
    #       * if QLThumbnailImageCreate() fails, create thumbnail from icon image
    # 
    #   usage:
    #       ./qlthumbnail.py file [file ...] > out.html
    # 
    #   version:
    #       0.11a
    #           - increased pyobjc performance (for recent versions of pyobjc) by using: 
    #               - import Quartz.CoreGraphics as CG
    #               - import AppKit as OSX
    #       0.11
    #           - added code to generate thumbnail from icon if QLThumbnailImageCreate() fails
    #           - modified html output:
    #               - let each entry be contained in div.container
    #               - defined style on div.container
    #               - removed anchor from file name
    #               - added title attribute with value as file name to anchor element
    #       0.10b
    #           - modified html output:
    #               - changed path to file name in output
    #               - removed separator (~) for each entry in output
    #       0.10a
    #           - modified html output:
    #               - added anchor element for path string
    #       0.10
    #           - draft
    # 
    #   written by Hiroto, 2016-09
    # 
    import sys, os, objc
    import base64, re
    import Quartz.CoreGraphics as CG    # required for QLThumbnailImageCreate() using CG symbols
    import AppKit as OSX
    
    QL_BRIDGESUPPORT = '''<?xml version="1.0" standalone="yes"?>
    <!DOCTYPE signatures SYSTEM "file://localhost/System/Library/DTDs/BridgeSupport.dtd">
    <signatures version="0.9">
       <constant type="^{__CFString=}" name="kQLThumbnailOptionIconModeKey"></constant>
        <constant type="^{__CFString=}" name="kQLThumbnailOptionScaleFactorKey"></constant>
        <function name="QLThumbnailImageCreate">
            <arg type="^{__CFAllocator=}"></arg>
            <arg type="^{__CFURL=}"></arg>
            <arg type="{CGSize=ff}" type64="{CGSize=dd}"></arg>
            <arg type="^{__CFDictionary=}"></arg>
            <retval type="^{CGImage=}"></retval>
        </function>
    </signatures>'''
    
    objc.parseBridgeSupport(
        QL_BRIDGESUPPORT, 
        globals(),
        objc.pathForFramework('/System/Library/Frameworks/QuickLook.framework')
    )
    
    def html_escape(s):
        s = re.sub(r'&', '&amp;', s)
        s = re.sub(r'<', '&lt;', s)
        s = re.sub(r'>', '&gt;', s)
        return s
    
    def main():
        # html opening
        s = u'''<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
    <html>
    <head>
        <meta http-equiv="content-type" content="text/html; charset=UTF-8">
        <style>
            div.container { display: inline-block; margin: 10px; text-align: center; }
        </style>
    </head>
    <body>'''
    
        # html entry template
        tmpl = u'''
    <div class="container">
        <p>
            <a href="%s" title="%s">
                <img src="data:%s;base64,%s" />
            </a>
        </p>
        <p>%s</p>
    </div>
    '''
        for f in [ a.decode('utf-8') for a in sys.argv[1:] ]:
            iurl = OSX.CFURLCreateFromFileSystemRepresentation(OSX.kCFAllocatorDefault, f.encode('utf-8'), len(f.encode('utf-8')), False)
            cgi = QLThumbnailImageCreate(
                OSX.kCFAllocatorDefault,
                iurl,
                CG.CGSizeMake(*IMAGE_SIZE),
                { kQLThumbnailOptionIconModeKey : OSX.kCFBooleanTrue }
            )
            if not cgi:
                ctx = CG.CGBitmapContextCreate(
                    None, IMAGE_SIZE[0], IMAGE_SIZE[1], 8, 0, 
                    CG.CGColorSpaceCreateWithName(CG.kCGColorSpaceGenericRGB), 
                    CG.kCGImageAlphaPremultipliedLast)
                icon = OSX.NSWorkspace.sharedWorkspace().iconForFile_(iurl.path())
                if icon:
                    cgi = OSX.NSBitmapImageRep.imageRepWithData_(icon.TIFFRepresentation()).CGImage()
                    CG.CGContextDrawImage(ctx, CG.CGRectMake(0, 0, *IMAGE_SIZE), cgi)
                cgi = CG.CGBitmapContextCreateImage(ctx)
            brep = OSX.NSBitmapImageRep.alloc().initWithCGImage_(cgi)
            data = brep.representationUsingType_properties_(OSX.NSJPEGFileType, {})
            byts = data.getBytes_length_(None, data.length())
            b64s = base64.b64encode(byts)
    
            # append html entry for this file
            name_e = html_escape(os.path.basename(iurl.path()))
            s += tmpl % (iurl.absoluteString(), name_e, 'image/jpeg', b64s, name_e)
    
        # html closing
        s += u'</body></html>'
        
        # print html
        print s.encode('utf-8')
    
        # put html data in clipboard
        html = OSX.NSString.stringWithString_(s).dataUsingEncoding_(OSX.NSUTF8StringEncoding)
        pboard = OSX.NSPasteboard.generalPasteboard()
        pbtype = 'public.html'
        pboard.declareTypes_owner_([pbtype], None)
        pboard.setData_forType_(html, pbtype)
    
    IMAGE_SIZE = (200.0, 200.0)
    main()
    

     

     

    Regards,

    H

  • by VikingOSX,

    VikingOSX VikingOSX Sep 20, 2016 7:26 PM in response to kaiuweheinz
    Level 7 (21,014 points)
    Mac OS X
    Sep 20, 2016 7:26 PM in response to kaiuweheinz

    Thought I would give you an update. Today has been crazy with interruptions, coding/testing/debugging, and finally I have another iteration of my AppleScript that will give you self-contained portability for thumbnails and files on a USB stick or SDHC/SDXC card. I now embed the thumbnail images in the document, and links on these thumbnails now point to duplicates of your originally selected Finder documents that are now on the portable media. You run your slideshow from the portable media and do not encounter any missing file references.

     

    It is about 22:30 right now, and I have to get up at 05:45 to run a friend to the airport. When I get back, I will review the AppleScript once more, run it, and then post it here for you.

  • by VikingOSX,

    VikingOSX VikingOSX Sep 21, 2016 12:03 PM in response to kaiuweheinz
    Level 7 (21,014 points)
    Mac OS X
    Sep 21, 2016 12:03 PM in response to kaiuweheinz

    This version of my AppleScript is focused on the portability of your ODT document, newly integrated, base64 encoded thumbnails, and their hyperlinks. Everything is designed to be self-contained on that removeable media, including the thumbnail image hyperlinks that point to documents on that media. Command-clicks on the ODT document hyperlinks will launch the appropriate application for the file type.

     

    Notice the revised floating hyperlink destination:

    Screen Shot 2016-09-21 at 1.14.58 PM.png

     

    I have upgraded the code to check for the presence of LibreOffice, and if found, it will automatically generate the ODT document from the HTML created by Pandoc, and this is written directly into the Media_files folder on the removable media. The only LibreOffice touchups would be to remove the LibreOffice thumbnail borders in the Properties panel for each, and switch off Comments in the View menu, as LibreOffice is still picking up some of the HTML header content.

     

    There only needs to be one line of code change, and that is the first property which is the displayed name of the mounted media on the Desktop. My SDXC card is called UTILITY. Do not use white-space for this name, or the folder name on the media card, if you care to change it at all.

     

    I took some additional time to install macOS Sierra and test the script on it too. It runs cleanly on El Capitan as well.

     

    AppleScript:

    -- qllink.applescript

    --

    -- Portability version

    --

    -- Checks if mounted, removable media (USB stick and card reader) is present. If true,

    -- it will create a folder on the mounted media, and duplicate the selected Finder

    -- documents to that location. A documents list is made from those on the media, and

    -- thumbnail images are generated for each document, base64 encoded, and written to a

    -- markdown metafile along with the URL hyperlink to the respective media document.

    --

    -- The third-party pandoc application converts the markdown content to HTML (work.html)

    -- and one the script will automatically use LibreOffice to convert from HTML to ODT if the

    -- application is present. Otherwise, one can use the LibreOffice command-line invocation

    -- shown below to generate an ODT document. By placing the ODT document onto the removeable

    -- media, one has a self-contained ODT document whose image hyperlinks find documents on the media card.

     

    -- Required:

    --              • Pandoc 1.15.1 (tested) or later. (pandoc.org) installed into /usr/local/bin.

    --              • LibreOffice 5.2.1.2 (tested) or later. For HTML to ODT conversion.

    --              • Write-enabled USB stick, SDHC/SDXC card, etc.

    -- Output:

    --              • custom.css -- input to Pandoc

    --              • meta.md - markdown file. Input to Pandoc.

    --              • work.html - output from Pandoc, Input to LibreOffice command-line

    --              • work.odt - output from LibreOffice command-line. Moved to media card afterward.

    --

    -- Use following (wrapped) LibreOffice command-line tool in Terminal:

    -- Note: there is a space between the --outdir destination and the input work.html file.

    -- Example:

    -- Removeable media (UTILITY) is mounted to the Desktop. The Desktop work.html exists.

    -- Convert work.html into work.odt, and place it in the removeable media location.

    -- /Applications/LibreOffice.app/Contents/MacOS/soffice --headless --convert-to odt --outdir /Volumes/UTILITY/Media_files work.html

    --

    -- Version 2.5, Revision with substantial updates for a portability solution.

    -- Tested: OS X 10.11.6 (15G1004), macOS Sierra 10.12 (16A323), AppleScript v2.4, 2.5

    -- VikingOSX, Sept 20, 2016, Apple Support Communities

    --

    -- change this non-whitespace value to match the name of your mounted media

    property volumeName : "UTILITY"

     

    property mediaPath : "/Volumes/" & volumeName & "/"

    property mediaFiles : "Media_files" -- name of folder on mounted media

    property volPath : (mediaPath & mediaFiles) as POSIX file

    property metafile : (path to desktop as Unicode text) & "meta.md"

    property mfile : POSIX path of metafile

    property cssfile : (path to desktop as Unicode text) & "custom.css"

    property cfile : POSIX path of cssfile

    property thumbpath : (path to desktop as text) & "Thumbs:"

    property workHTML : POSIX path of ((path to desktop as text) & "work.html")

    property dataURI : "data:image/png;base64,"

    property fileCnt : missing value

     

    use scripting additions

     

    tell application "Finder"

      activate

      -- check if media is mounted and warn otherwise

      if not (exists disk volumeName) then

      display alert "Media: [" & volumeName & " ] is not mounted." message "Please mount again, and retry this script." as critical giving up after 10

      return

      end if

     

      -- if target folder is not present on the mounted media, then make it.

      if not (exists volPath) then

      make new folder at (mediaPath as POSIX file) with properties {name:mediaFiles}

      end if

     

      if not (exists folder thumbpath) then

      make new folder at (path to desktop) as alias with properties {name:"Thumbs"}

      end if

     

      -- Finder selected documents are made into a file list

      set inPath to the selection as alias list

      if inPath = {} then

      display alert "Finder" message "You must select Finder items before executing this script." as critical giving up after 10

      return

      end if

     

      if exists file cssfile then

      delete file cssfile

      end if

     

      if exists file metafile then

      delete file metafile

      end if

     

      -- In order to solve ODT file reference issues, we copy the selected Finder items

      -- to the mounted media folder, where we will build file links to them from there.

      repeat with xfile in inPath

      duplicate xfile to folder (volPath as alias) with replacing

      end repeat

      -- get a list of all the files that we want to process off of the mounted media

      set mediaList to (every item in entire contents of folder (volPath as alias) whose name extension is not in {"html", "odt"}) as alias list

     

      if mediaList = {} then

      display alert "Finder" message "No files found in mounted media folder." as critical giving up after 5

      return

      end if

      set fileCnt to (count of mediaList)

    end tell

     

    -- create and populate new css file for pandoc

    set fcRef to openFileHandle(cssfile, true)

    log class of fcRef

    init_cssfile(fcRef)

     

    -- get metadata file handle for writing

    set fRef to openFileHandle(metafile, true)

    if fRef is false then return

     

    repeat with afile in mediaList

      tell application "Finder"

      set theURL to (afile's URL) as «class utf8»

      set theName to (afile's name) as «class utf8»

      set ImgPath to ""

      -- because qlmanager generates name.extension.png image names!!

      set ImgPath to POSIX path of (thumbpath & afile's name & ".png") as «class utf8»

      log ImgPath

      set inFile to (afile's POSIX path)'s quoted form

      end tell

      try

      -- use the QuickLook manager to generate a (78%) 200 pixel icon. Better to downsample.

      do shell script "/usr/bin/qlmanage -tf 0.78 -s 256 " & inFile & " -o " & POSIX path of (thumbpath as alias) & " >& /dev/null"

     

      write_metadata(fRef, theURL, theName, ImgPath)

      on error errmsg number errnbr

      my error_handler(errnbr, errmsg)

      close access the fRef

      return

      end try

    end repeat

    close access the fRef

     

    -- Transform markdown to HTML retaining embedded images and hyperlinks

    do shell script "/usr/local/bin/pandoc -H " & cfile & " -f markdown -t html -o " & workHTML & space & mfile

     

    if exists "LibreOffice.app" then

      set LO_CMD to "/Applications/LibreOffice.app/Contents/MacOS/soffice --headless --convert-to odt --outdir " & mediaPath & mediaFiles & space & workHTML

      do shell script LO_CMD

    end if

     

    tell application "SystemUIServer"

      if exists ((volPath as alias) & "work.odt") then

      display dialog "Files processed: " & (fileCnt as text) & return & return & ¬

      "The output ODT document has been written to your mounted media card. Processing has completed."

      else

      display dialog "Files processed: " & (fileCnt as text) & return & return & "The automatic generation of your ODT document did not occur for some reason. Adapt the example at the beginning of this script to manually generate your ODT onto your mounted media card."

      end if

    end tell

     

    set fileCnt to (0 as integer)

    return

     

    -- Handlers --

    on openFileHandle(filePath, overwrite)

      try

      set the filePath to the filePath as Unicode text

      set the fp to open for access file filePath with write permission

      if overwrite is true then set eof of the fp to 0 -- truncate file

      on error errmsg number errnbr

      my error_handler(errnbr, errmsg)

      return false

      end try

     

      return fp

     

    end openFileHandle

     

    on init_cssfile(fh)

      -- this CSS will be provided to pandoc on its command-line with the -H flag to

      -- alter the flow in the HTML to horizontal image wrap.

      set eof of fh to 0

      write "<style type=\"text/css\">" & linefeed as «class utf8» to fh starting at eof

      write "img {display:inline-block;margin:5px 20px;padding:5px;}" & linefeed as «class utf8» ¬

      to fh starting at eof

      write " p {display:inline;margin:0;padding:0;}" & linefeed as «class utf8» ¬

      to fh starting at eof

      write "</style>" as «class utf8» to fh starting at eof

      close access fh

      return

    end init_cssfile

     

    on write_metadata(fh, aURL, aName, theImgPath)

     

      -- write base64 encoded thumbnail images to metadata file with associated file links

      set encoded64 to do shell script "/usr/bin/base64 " & theImgPath's quoted form

      set imgBase64 to dataURI & encoded64

      write "[![](" & contents of imgBase64 & space & "\"" & aName & "\")](" & ¬

      aURL & ")" & linefeed & linefeed to fh starting at eof as «class utf8»

      return

     

    end write_metadata

     

    on error_handler(nbr, msg)

      return display alert "[ " & nbr & " ] " & msg as critical giving up after 10

    end error_handler

  • by kaiuweheinz,

    kaiuweheinz kaiuweheinz Sep 28, 2016 1:49 PM in response to VikingOSX
    Level 1 (8 points)
    Mac OS X
    Sep 28, 2016 1:49 PM in response to VikingOSX

    Dear VikingOSX,

     

    I am very much impressed by the work you have done. You are generous. I am sorry for responding only now but from Friday to Sunday I had my children at home whom I see only every third weekend. Before and after those weekends there is always a lot to do.

     

    I have tried your Script a few minutes ago and it only worked when a removable media is mounted and then again only if its name is UTILITY. Once this is the case it says the following:

    Bildschirmfoto 2016-09-28 um 22.00.48.png

     

    Translated this means: "SystemUIServer" has received an error: {alias "UTILITY:Media_files:", "work.odt"} doesn't understand the message "exists". "
    You must understand that for the sake of portability I only need to sync the thumb folder as I always take with me the macbook air. I only didn't sync the folder and that's why I found myself without images in front of the class. My dream solution would rather point to images that are fully contained in the linked thumbnails. This is the strategy Hiroto pursues but I have to admit that at the "frontline" at school I only use your script 2.2 because it requires only 1 step and is really fast and every other lesson I need to include in realtime a new link because while talking to the students we touch an important subject that needs "immediate treatment". So making the script include the linked thumbnails without referring to a thumb folder (which in the course of the years will grow bigger and bigger and once I should delete it all the old protocols wouldn't be visually "readable" anymore).
    Your portability solution however is a class of its own: right now one of my latin students is at the hospital, his parents asked me to send him all the documents we treat in class. So now I do not only send him the lesson's protocol that I send to all students anyway but have to pick manually the documents related to by the linked thumbnails as well. Here your portability solution comes in. As described above I haven't seen it work yet but as far as I have understood it creates a folder with all the documents I selected to create a linked thumbnail that I want to include in my lesson's protocol.
    First, it should not only work if there is a removable media (named UTILITY) mounted but create a folder on the HD. Second, in the process of preparing a lesson sometimes one or two thumbnails get kicked out, what will happen to the documents copied in the folder? And if during the lesson I adapted the protocol, would the added documents be in the folder as well?
    Sometimes two students from different classes are sick. After sending the protocol via e-mail I'd need to collect for each of the absent students the corresponding documents. So rather than monitoring the creation of the protocol, i.e. copying the included documents, a script that would check for all the links in a document and put them into a folder named after the protocols name (see name architecture below) would only be of help.
    Bildschirmfoto 2016-09-28 um 22.35.41.png
    But, dear VikingOSX, you have already invested an incredible amount of time. So please do consider if you can afford to help any further. You have a big heart, ready to help wherever there is need (mowing, driving, coding), you fervently seek a solution to help others. My impression is: God wants to lift YOU, he is interested in promoting YOU more than seeing you helping OTHERS at the expense of your own forthcoming. I can be wrong of course and don't want to offend you by being too personal but this is what I kept pondering on since your last message. Although I feel deeply honored that a man of your skills invests time in dealing with my concerns, I don't want to use your time and thought exceedingly.
    Gratefully and respectfully,
    Kai-Uwe
  • by kaiuweheinz,

    kaiuweheinz kaiuweheinz Sep 28, 2016 2:07 PM in response to Hiroto
    Level 1 (8 points)
    Mac OS X
    Sep 28, 2016 2:07 PM in response to Hiroto

    Dear Hiroto,

     

    as I wrote to VikingOSX, I am very very grateful for the work you have done. I am sorry for responding only now but from Friday to Sunday I had my children at home whom I see only every third weekend. Before and after those weekends there is always a lot to do.

     

    I have tried your Script a few minutes ago and it did open a LibreOffice document but after that it didn't move on:

    Bildschirmfoto 2016-09-28 um 22.54.50 Kopieb.png

    The wheel indicating "Executing ..." kept spinning. What needs to be done?

    I haven't managed to activate GUI scripting as my privacy dialogue doesn't offer the options suggested by your link:

    Bildschirmfoto 2016-09-28 um 23.02.20.png

    ... whereas the apple site suggests this:

    Bildschirmfoto 2016-09-28 um 23.03.43.png

     

    has this to do with the script not coming to an end during execution?

     

    Thank you for all your efforts and advice, dear Hiroto,

    I told my students that I was working on the perfectioning of their protocol and that I was collaborating with a (supposedly) American (is that correct VikingOSX) and Hiroto from Japan. They were deeply impressed

     

    Kind regards,

    Kai-Uwe

  • by VikingOSX,

    VikingOSX VikingOSX Sep 28, 2016 5:48 PM in response to kaiuweheinz
    Level 7 (21,014 points)
    Mac OS X
    Sep 28, 2016 5:48 PM in response to kaiuweheinz

    I am in the U.S.

     

    Between the age of 10 and 16, I was restricted to time with my Father during the summer after school ended. We were 965 km apart.

     

    As for AppleScript, my v2.5 script was exclusively a mounted media solution that expected you to change the script code from my volumeName property (UTILITY) example to your mounted media name. In reviewing your most recent post, would it help if the next script revision that I post would prompt you for your choice of local (e.g. Desktop), or mounted media solution? Seems that would give you the most flexibility. Not sure how much more code would be involved yet.

     

    In either case, the images are embedded within the ODT document, and each image would be hyperlinked to its respective file in the same folder as the ODT document. Presently, one can double-click these hyperlinked thumbnails and this results in the associated document opening in its default application.

     

    I have fixed the SystemUIServer error, and the existing 2.5 code runs correctly.

  • by kaiuweheinz,

    kaiuweheinz kaiuweheinz Sep 29, 2016 12:21 AM in response to VikingOSX
    Level 1 (8 points)
    Mac OS X
    Sep 29, 2016 12:21 AM in response to VikingOSX

    Dear VikingOSX,

     

    thank you for your reply!! My divorced wife moved 420km away. It is hard for a father and probably even more for a child. In either one there needs to be restoration of the heart.

     

     

    Thank you for evolving v2.5. I am currently using "at the frontline" at school, when all has to be fast, v2.22. Here is the exact code:

     

    -- ql_link.applescript

    -- Writes custom.css, and markdown files. The latter contains content

    -- that enables hyperlinked thumbnails with hover filenames shown.

    -- When processing is complete, the third-party pandoc (pandoc.org) application is used

    -- to convert markdown content to an HTML web page.

    --

    -- Optional: use the LibreOffice command-line tool soffice to convert the

    -- HTML content to either ODT, or DOCX documents. This will preserve

    -- all HTML functionality including hyperlinks on thumbnails and hover text

    -- The following commands have wrapped, it is a single-line invocation. Output work.odt, or work.docx.

    --

    -- /Applications/LibreOffice.app/Contents/MacOS/soffice --headless --convert-to odt --outdir ~/Desktop work.html

    -- /Applications/LibreOffice.app/Contents/MacOS/soffice --headless --convert-to docx:"MS Word 2007 XML" --outdir ~/Desktop work.html

    --

    -- Version 2.1. • Rewrite. Switched from LaTeX to markdown metadata for improved f(x).

    --                     • Include custom CSS to assist pandoc generation of horizontal html content.

    --                     • allows horizontal 200 px thumbnails that wrap on web page.

    --                     • A single-click on a thumbnail in Safari 9.1.3 (or Firefox 48.0.1) will open

    --                       that document in its default application, or Finder window.

    --                     • Replaced choose file with Finder selection(s)

    --                     • All comments now suppressed in html and odt documents.

    -- VikingOSX, Sept 18, 2016, Apple Support Communities

    tell application "Finder"

      try

      delete the file "out.odt" of the desktop

      end try

      try

      delete the file "out.html" of the desktop

      end try

    end tell

     

    property default_loc : ((path to desktop) as text) as alias

    property qmesg : "Choose file(s) to generate thumbnails"

    property metafile : (path to desktop as Unicode text) & "meta.md"

    property mfile : POSIX path of metafile

    property cssfile : (path to desktop as Unicode text) & "custom.css"

    property cfile : POSIX path of cssfile

    property thumbpath : (path to desktop as text) & "Thumbs:"

    property fileCnt : missing value

     

    use scripting additions

     

    tell application "Finder"

      if exists file metafile then

      delete file metafile

      end if

      if exists file cssfile then

      delete file cssfile

      end if

      if not (exists folder thumbpath) = true then

      make new folder at (path to desktop as text) with properties {name:"Thumbs"}

      end if

    end tell

     

    -- set inPath to (choose file with prompt qmesg default location default_loc with multiple selections allowed without invisibles and showing package contents)

    -- Finder selected documents are made into a file list

    tell application "Finder"

      set inPath to the selection as alias list

    end tell

     

    -- create new cssfile and initialize it

    set fcRef to openFileHandle(cssfile, true)

    init_cssfile(fcRef)

     

    set fRef to openFileHandle(metafile, true)

    if fRef is false then return

     

    set fileCnt to (count of inPath)

    repeat with afile in inPath

      tell application "Finder"

      set ImgPath to ""

      set theURL to (afile's URL) as «class utf8»

      set theName to (afile's name) as «class utf8»

      -- because qlmanager generates name.extension.png image names!!

      set ImgPath to POSIX path of (thumbpath & theName & ".png") as «class utf8»

      set inFile to (afile's POSIX path)'s quoted form

      end tell

     

      try

      -- use the QuickLook manager to generate a 200 pixel icon. Better to downsample.

      do shell script "/usr/bin/qlmanage -tif 0.78 -s 256 " & inFile & " -o " & POSIX path of thumbpath & " >& /dev/null"

      tell application "Finder" to set imgURL to URL of (POSIX file ImgPath as alias)

      log imgURL

      write_metadata(fRef, theURL, theName, imgURL)

      on error errmsg number errnbr

      my error_handler(errnbr, errmsg)

      close access the fRef

      return

      end try

    end repeat

    close access the fRef

    do shell script "/usr/local/bin/pandoc -H " & cfile & " -f markdown -t html -o ~/Desktop/work.html " & mfile

    -- do shell script "open ~/Desktop/work.html"

    set out to (path to desktop)'s POSIX path & "work.html"

    do shell script "/Applications/neoOffice.app/Contents/MacOS/soffice --writer " & out's quoted form & " &>/dev/null &"

    set fileCnt to (0 as integer)

    return

     

    on openFileHandle(filePath, overwrite)

      try

      set the filePath to the filePath as Unicode text

      set the fp to open for access file filePath with write permission

      if overwrite is true then set eof of the fp to 0 -- truncate file

      on error errmsg number errnbr

      try

      close access the fp

      set fp to (open for access filePath with write permission)

      if overwrite is true then set eof of fp to 0

      on error

      my error_handler(errnbr, errmsg)

      return false

      end try

      end try

     

      return fp

     

    end openFileHandle

     

    on init_cssfile(fh)

      -- Override the pandoc generated HTML

      -- this CSS will be provided to pandoc on its command-line with the -H flag

      set eof of fh to 0

      write "<style type=\"text/css\">" & linefeed as «class utf8» to fh starting at eof

      write "img {display:inline-block;margin:5px 20px;padding:5px;}" & linefeed as «class utf8» ¬

      to fh starting at eof

      write " p {display:inline;margin:0;padding:0;}" & linefeed as «class utf8» ¬

      to fh starting at eof

      write "</style>" as «class utf8» to fh starting at eof

      close access fh

      return

    end init_cssfile

     

    on write_metadata(fh, aURL, aName, theImgURL)

     

      -- markdown syntax to make hyperlinked thumbnails

      write "[![](" & theImgURL & space & "\"" & aName & "\")](" & aURL & ")" & ¬

      linefeed & linefeed to fh starting at eof as «class utf8»

      return

     

    end write_metadata

    tell application "NeoOffice"

      activate

    end tell

     

    on error_handler(nbr, msg)

      return display alert "[ " & nbr & " ] " & msg as critical giving up after 10

    end error_handler

     

     

    If the same result (output doc opened automatically in NeoOffice)

    with the same speed (usually I select 1-3 files at a time - taking about 4-5 seconds)

    could be achieved with embedded images everything would be fine.

     

    The portability solution to me looks like an evolution of the whole process and is a script apart. Prompting me to choose local or portable solution would be good.

     

    Is it possible to code a script that asks me to select the protocol that needs to be stored on a mounted media or sent via e-mail which tracks down all included document links and saves them in a folder named after the protocol?

     

    Your current v2.5 seems to take note of all the documents I select in order to include them into a protocol but doesn't distinguish between various protocols. To give you an example: I prepare my latin lesson for the 10th grade "L10bc", I then save the protocol as "Protokoll L10bc 2016-09-29". The ideal solution would be: all documents used during the lesson are included in a folder named Protokoll L10bc 2016-09-29. If after that I prepare an italian lesson I would saved it as "Protokoll I8a 2016-09-29" with a folder containing all the documents to be treated in that lesson. If then I should be in a hurry I can pick that folder quickly and rush to high school. If after school I send all the protocols to the corresponding classes I can check in which class a student was missing and send him the protocol plus the treated documents: sending Protokoll L10bc 2016-09-29 plus docs to the absent student from 10th grade or to all the mailing list L10 and Protokoll I8a 2016-09-29 plus docs to the absent student from 8th grade or to the whole mailing list I8.

     

    I may appear repetitive but all I can express is my thankfulness,

     

    gbu,

    Kai-Uwe

  • by Hiroto,

    Hiroto Hiroto Sep 29, 2016 7:35 PM in response to kaiuweheinz
    Level 5 (7,306 points)
    Sep 29, 2016 7:35 PM in response to kaiuweheinz

    Hello

     

    As far as I can tell from your screenshot, you have already granted Script Editor to access GUI element. So it is not the cause of failure.

     

    GUI scripting is quite fragile and prone to failure with different version of pertinent software because it depends upon implementation details of interface elements. In current case, you're using different version of LibreOffice and OS X from mine and thus I'm not so surprised by the failure in GUI scripting. It would not be difficult to fix the script if I were to test it with the very specific versions of software in your environment.

     

    Anyway, here's another script not resorting GUI scripting but using:

     

    LibreOffice.app/Contents/MacOS/soffice --headless --convert-to odt:writerweb8_writer out.html
    

     

     

    Also I changed NeoOffice executable to:

     

    NeoOffice.app/Contents/MacOS/soffice.bin
    

     

     

    although I'm not really sure this is correct, for I don't have NeoOffice at hand.

     

    Script is tested with pyobjc 2.2b3 and python 2.6.1 and LibreOffice 4.3.7.2 and OpenOffice 4.0.1 under OS X 10.6.8.

     

    * create_qlthumbnails_html() handler is the same as the previous.

     

     

    --APPLESCRIPT
    _main()
    on _main()
        -- get Finder selection
        tell application "Finder"
            set aa to selection as alias list
        end tell
        repeat with a in aa
            set a's contents to a's POSIX path
        end repeat
        
        -- create out.html
        set out_html to (path to desktop)'s POSIX path & "out.html"
        create_qlthumbnails_html(aa, out_html)
        
        -- create out.odt
        set out_odt to libreoffice_convert_to_odt(out_html)
        
        -- open out.odt in OpenOffice / NeoOffice by its soffice executable (* NeoOffice command is not tested)
        --do shell script "/Applications/OpenOffice.app/Contents/MacOS/soffice --writer " & out_odt's quoted form & " &>/dev/null &"
        do shell script "/Applications/NeoOffice.app/Contents/MacOS/soffice.bin --writer " & out_odt's quoted form & " &>/dev/null &"
    end _main
    
    on create_qlthumbnails_html(argv, out)
        (*
            list argv : list of POSIX path of source files
            string out : POSIX path of output html file
            * this handler puts output html data in the clipboard as well
        *)
        set args to ""
        repeat with a in {} & argv
            set args to args & a's quoted form & space
        end repeat
        do shell script "/usr/bin/python <<'EOF' - " & args & " > " & out's quoted form & "
    # coding: utf-8
    # 
    #   file:
    #       qlthumbnail.py
    # 
    #   function:
    #       print html text of hyperlinked thumbnail(s) of given file(s) and put html data in the clipboard
    #       * if QLThumbnailImageCreate() fails, create thumbnail from icon image
    # 
    #   usage:
    #       ./qlthumbnail.py file [file ...] > out.html
    # 
    #   version:
    #       0.11a
    #           - increased pyobjc performance (for recent versions of pyobjc) by using: 
    #               - import Quartz.CoreGraphics as CG
    #               - import AppKit as OSX
    #       0.11
    #           - added code to generate thumbnail from icon if QLThumbnailImageCreate() fails
    #           - modified html output:
    #               - let each entry be contained in div.container
    #               - defined style on div.container
    #               - removed anchor from file name
    #               - added title attribute with value as file name to anchor element
    #       0.10b
    #           - modified html output:
    #               - changed path to file name in output
    #               - removed separator (~) for each entry in output
    #       0.10a
    #           - modified html output:
    #               - added anchor element for path string
    #       0.10
    #           - draft
    # 
    #   written by Hiroto, 2016-09
    # 
    import sys, os, objc
    import base64, re
    import Quartz.CoreGraphics as CG    # required for QLThumbnailImageCreate() using CG symbols
    import AppKit as OSX
    
    QL_BRIDGESUPPORT = '''<?xml version=\"1.0\" standalone=\"yes\"?>
    <!DOCTYPE signatures SYSTEM \"file://localhost/System/Library/DTDs/BridgeSupport.dtd\">
    <signatures version=\"0.9\">
       <constant type=\"^{__CFString=}\" name=\"kQLThumbnailOptionIconModeKey\"></constant>
        <constant type=\"^{__CFString=}\" name=\"kQLThumbnailOptionScaleFactorKey\"></constant>
        <function name=\"QLThumbnailImageCreate\">
            <arg type=\"^{__CFAllocator=}\"></arg>
            <arg type=\"^{__CFURL=}\"></arg>
            <arg type=\"{CGSize=ff}\" type64=\"{CGSize=dd}\"></arg>
            <arg type=\"^{__CFDictionary=}\"></arg>
            <retval type=\"^{CGImage=}\"></retval>
        </function>
    </signatures>'''
    
    objc.parseBridgeSupport(
        QL_BRIDGESUPPORT, 
        globals(),
        objc.pathForFramework('/System/Library/Frameworks/QuickLook.framework')
    )
    
    def html_escape(s):
        s = re.sub(r'&', '&amp;', s)
        s = re.sub(r'<', '&lt;', s)
        s = re.sub(r'>', '&gt;', s)
        return s
    
    def main():
        # html opening
        s = u'''<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">
    <html>
    <head>
        <meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">
        <style>
            div.container { display: inline-block; margin: 10px; text-align: center; }
        </style>
    </head>
    <body>'''
    
        # html entry template
        tmpl = u'''
    <div class=\"container\">
        <p>
            <a href=\"%s\" title=\"%s\">
                <img src=\"data:%s;base64,%s\" />
            </a>
        </p>
        <p>%s</p>
    </div>
    '''
        for f in [ a.decode('utf-8') for a in sys.argv[1:] ]:
            iurl = OSX.CFURLCreateFromFileSystemRepresentation(OSX.kCFAllocatorDefault, f.encode('utf-8'), len(f.encode('utf-8')), False)
            cgi = QLThumbnailImageCreate(
                OSX.kCFAllocatorDefault,
                iurl,
                CG.CGSizeMake(*IMAGE_SIZE),
                { kQLThumbnailOptionIconModeKey : OSX.kCFBooleanTrue }
            )
            if not cgi:
                ctx = CG.CGBitmapContextCreate(
                    None, IMAGE_SIZE[0], IMAGE_SIZE[1], 8, 0, 
                    CG.CGColorSpaceCreateWithName(CG.kCGColorSpaceGenericRGB), 
                    CG.kCGImageAlphaPremultipliedLast)
                icon = OSX.NSWorkspace.sharedWorkspace().iconForFile_(iurl.path())
                if icon:
                    cgi = OSX.NSBitmapImageRep.imageRepWithData_(icon.TIFFRepresentation()).CGImage()
                    CG.CGContextDrawImage(ctx, CG.CGRectMake(0, 0, *IMAGE_SIZE), cgi)
                cgi = CG.CGBitmapContextCreateImage(ctx)
            brep = OSX.NSBitmapImageRep.alloc().initWithCGImage_(cgi)
            data = brep.representationUsingType_properties_(OSX.NSJPEGFileType, {})
            byts = data.getBytes_length_(None, data.length())
            b64s = base64.b64encode(byts)
    
            # append html entry for this file
            name_e = html_escape(os.path.basename(iurl.path()))
            s += tmpl % (iurl.absoluteString(), name_e, 'image/jpeg', b64s, name_e)
    
        # html closing
        s += u'</body></html>'
        
        # print html
        print s.encode('utf-8')
    
        # put html data in clipboard
        html = OSX.NSString.stringWithString_(s).dataUsingEncoding_(OSX.NSUTF8StringEncoding)
        pboard = OSX.NSPasteboard.generalPasteboard()
        pbtype = 'public.html'
        pboard.declareTypes_owner_([pbtype], None)
        pboard.setData_forType_(html, pbtype)
    
    IMAGE_SIZE = (200.0, 200.0)
    main()
    EOF"
    end create_qlthumbnails_html
    
    on libreoffice_convert_to_odt(f)
        (*
            string f : POSIX path of input file
            return string: POSIX path of resultant file
            
            * tested with LibreOffice 4.3.7.2 under OS X 10.6.8
        *)
        -- quit libreoffice if it is running
        (* this is required for the following conversion by soffice to work properly *)
        tell application id "org.libreoffice.script"
            if running then quit
        end tell
        tell application "System Events"
            repeat while exists (process 1 whose bundle identifier = "org.libreoffice.script")
                tell current application to delay 0.2
            end repeat
        end tell
        
        -- convert f to odt
        return do shell script "INFILE=" & f's quoted form & "
    argv=(
        --headless
    #   --convert-to odt:writer8            # NG: this yields Writer/Web document
        --convert-to odt:writerweb8_writer  # OK: this yields Writer document
        --outdir \"$(dirname \"$INFILE\")\"
        \"$INFILE\"
    )
    /Applications/LibreOffice.app/Contents/MacOS/soffice \"${argv[@]}\" &>/dev/null
    echo \"${INFILE%.*}.odt\""
    end libreoffice_convert_to_odt
    --END OF APPLESCRIPT
    

     

     

     

    Good luck,

    H

first Previous Page 4 of 4