diff --git a/README.md b/README.md index ab85a75..9caf3c4 100644 --- a/README.md +++ b/README.md @@ -30,9 +30,7 @@ If you do not like Gloobus, you can define a custom QuickLook command: ## Installing on Windows -On Windows, you must first install a QuickLook tool. By default, ZoteroQuickLook is set up to work with [QuickLook](https://github.com/QL-Win/QuickLook/releases). - -Note that you must install QuickLook using the `.msi` installer, not by installing through the Windows Store. The Windows Store version of QuickLook does not provide a way for other programs to integrate with it. You can use the `.zip` version of QuickLook, but you must follow the steps below to set up a custom view command. +On Windows, you must first install a QuickLook tool. By default, ZoteroQuickLook is set up to work with [QuickLook](https://github.com/QL-Win/QuickLook/releases). Note that you must install QuickLook using either the `.msi` installer or through the Windows Store. If you use the `.zip` version of QuickLook, you must also set up a custom view command. Alternative QuickLook tools for Windows include [Seer](http://1218.io), [WinQuickLook](https://github.com/shibayan/WinQuickLook), and the paid software [MaComfort](https://leonardo.re/macomfort/). In my experience, the default option, QuickLook, is the most stable and powerful and least resource intensive option. You can choose another QuickLook program if you like. The software must be able to take a file name as a command line parameter. diff --git a/chrome/content/Bridge.cs b/chrome/content/Bridge.cs new file mode 100644 index 0000000..694f21e --- /dev/null +++ b/chrome/content/Bridge.cs @@ -0,0 +1,49 @@ +using System; +using System.IO; +using System.IO.Pipes; +using System.Security.Principal; +using System.Windows.Forms; + +namespace Bridge +{ + internal static class Program + { + private static void Main(string[] args) + { + if (args.Length != 1) + { + MessageBox.Show("Usage: Bridge.exe \"\""); + return; + } + + SendMessage(Toggle, args[0]); + } + + private static readonly string PipeName = "QuickLook.App.Pipe." + WindowsIdentity.GetCurrent().User?.Value; + private const string Toggle = "QuickLook.App.PipeMessages.Toggle"; + + private static void SendMessage(string pipeMessage, string path = null) + { + if (path == null) + path = ""; + + try + { + using (var client = new NamedPipeClientStream(".", PipeName, PipeDirection.Out)) + { + client.Connect(1000); + + using (var writer = new StreamWriter(client)) + { + writer.WriteLine($"{pipeMessage}|{path}"); + writer.Flush(); + } + } + } + catch (Exception e) + { + MessageBox.Show("QuickLook not found. Please install QuickLook (http://pooi.moe/QuickLook/) or specify a custom view command instead."); + } + } + } +} \ No newline at end of file diff --git a/chrome/content/Bridge.exe b/chrome/content/Bridge.exe new file mode 100644 index 0000000..e0de08e Binary files /dev/null and b/chrome/content/Bridge.exe differ diff --git a/chrome/content/zoteroquicklook.js b/chrome/content/zoteroquicklook.js index bfdf057..58bec48 100644 --- a/chrome/content/zoteroquicklook.js +++ b/chrome/content/zoteroquicklook.js @@ -14,7 +14,7 @@ Zotero.ZoteroQuickLook = { document.getElementById('zotero-items-tree').addEventListener("keydown",this.onKey,false); if (!this.initialized) { - Zotero.debug("ZoterQuickLook: starts init",3); + Zotero.debug("ZoteroQuickLook: starts init",3); //Trim the preference to avoid problems of extra spaces this.customviewcommand = this.getPref('customviewcommand').replace(/^\s+|\s+$/g, ''); @@ -32,8 +32,8 @@ Zotero.ZoteroQuickLook = { } } - // Get the path of the embedded Perl script (Mac/Linux) and word processor plugins scripts (Mac) - if (!Zotero.isWin && this.customviewcommand == "") { + // Get the path of the embedded Perl script (Mac/Linux) or QuickLook bridge executable (Win) + if (this.customviewcommand == "") { await new Promise(function (resolve) { var MY_ID = "zoteroquicklook@gmail.com"; Components.utils.import("resource://gre/modules/AddonManager.jsm"); @@ -43,8 +43,7 @@ Zotero.ZoteroQuickLook = { resolve(); }.bind(this)); }.bind(this)); - } - else { + } else { this.initExecutable(); } @@ -62,8 +61,15 @@ Zotero.ZoteroQuickLook = { * Initializes external scripts */ initScripts: async function (scriptURL) { - let path = await this.copyURLToTempDir(scriptURL + "/zoteroquicklook.pl"); - Zotero.ZoteroQuickLook.initExecutable(path); + if (!Zotero.isWin) { + let path = await this.copyURLToTempDir(scriptURL + "/zoteroquicklook.pl"); + Zotero.debug("ZoteroQuickLook: Copying zoteroquicklook.pl file to: " + path); + Zotero.ZoteroQuickLook.initExecutable(path); + } else { + let path = await this.copyURLToTempDir(scriptURL + "/Bridge.exe"); + Zotero.debug("ZoteroQuickLook: Copying Bridge.exe file to: " + path); + Zotero.ZoteroQuickLook.initExecutable(path); + } /* // Check if the word processor integration for Zotero is installed and install the quicklook word processor script @@ -116,6 +122,7 @@ Zotero.ZoteroQuickLook = { */ }, + /* initIntegration: function(){ Zotero.Integration.Interface.prototype.quickLook = function() { @@ -166,8 +173,11 @@ Zotero.ZoteroQuickLook = { } } }, + */ initExecutable: function(scriptLocation) { + Zotero.debug("ZoteroQuickLook: Script location is " + scriptLocation, 3); + //Initialize the command that is used. //TODO: The script fails when custom view command is bogus. @@ -221,13 +231,28 @@ Zotero.ZoteroQuickLook = { } - else if(Zotero.isWin){ + else if(Zotero.isWin){ + /* TODO: Checking for existence of Windows Store Apps isn't working + // Check if QuickLook is installed. localappdata = Components.classes["@mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties).get("LocalAppData", Components.interfaces.nsIFile).path; - this.viewerExecutable = Zotero.File.pathToFile(localappdata + "\\Programs\\QuickLook\\QuickLook.exe"); - if(this.viewerExecutable.exists() === false){ + qlMsiLocation = Zotero.File.pathToFile(localappdata + "\\Programs\\QuickLook\\QuickLook.exe"); + winApps = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile).initWithPath("C:\\Program Files\\WindowsApps\\").directoryEntries; + winAppsArray = []; + while(winApps.hasMoreElements()) { + var entry = winApps.getNext(); + entry.QueryInterface(Components.interfaces.nsIFile); + winAppsArray.push(entry); + } + qlPublisher = /PaddyXu\.QuickLook/g ; + qlWinStoreInstalled = winAppsArray.some(e => qlPublisher.test(e)); + if(qlMsiLocation.exists() === false && qlWinStoreInstalled === false){ alert("QuickLook not found. Please install QuickLook (http://pooi.moe/QuickLook/) or specify a custom view command instead."); + return; } - this.viewerBaseArguments=['']; + */ + + this.viewerExecutable = Zotero.File.pathToFile(scriptLocation); + this.viewerBaseArguments=['']; } }, @@ -256,7 +281,7 @@ Zotero.ZoteroQuickLook = { }, closeQuickLook: function(){ - Zotero.debug("ZoterQuickLook: is killing quicklook viewer."); + Zotero.debug("ZoteroQuickLook: is killing quicklook viewer."); Zotero.ZoteroQuickLook.proc.kill(); Zotero.ZoteroQuickLook.proc=null; }, @@ -329,7 +354,7 @@ Checks the attachment file or writes a content of a note to a file and then push let iCloudPath = Zotero.File.getEvictedICloudPath(path); if (await OS.File.exists(iCloudPath)) { // Launching qlmanage should trigger an iCloud download - Zotero.debug("ZoterQuickLook: Triggering download of iCloud file"); + Zotero.debug("ZoteroQuickLook: Triggering download of iCloud file"); await args.push(Zotero.ZoteroQuickLook.cleanFileName(path)); return; } @@ -422,7 +447,7 @@ Checks the attachment file or writes a content of a note to a file and then push openQuickLook: async function(items) { - Zotero.debug("ZoterQuickLook: opening viewer",3); + Zotero.debug("ZoteroQuickLook: opening viewer",3); var args=this.viewerBaseArguments.slice(); @@ -474,7 +499,7 @@ Checks the attachment file or writes a content of a note to a file and then push ///If no files are specified, exit. if (! filesFound ) { - Zotero.debug("ZoterQuickLook: thinks that no files are selected",3); + Zotero.debug("ZoteroQuickLook: thinks that no files are selected",3); return false; } @@ -495,20 +520,17 @@ Checks the attachment file or writes a content of a note to a file and then push // If no file arguments were added to the base arguments, exit. if (argsString == baseArgsString) { - Zotero.debug("ZoterQuickLook: Only linked URLs are selected",3); + Zotero.debug("ZoteroQuickLook: Only linked URLs are selected",3); return false; } //Write to debug what is called - Zotero.debug("ZoterQuickLook: calling a shell command: " +this.viewerExecutable.path +argsString,3); - + Zotero.debug("ZoteroQuickLook: calling a shell command: " +this.viewerExecutable.path +argsString,3); + Zotero.ZoteroQuickLook.proc = Components.classes["@mozilla.org/process/util;1"]. createInstance(Components.interfaces.nsIProcess); - Zotero.ZoteroQuickLook.proc.init(Zotero.ZoteroQuickLook.viewerExecutable); - Zotero.ZoteroQuickLook.proc.runw(false, args, args.length); - return true; }, @@ -546,12 +568,12 @@ Checks the attachment file or writes a content of a note to a file and then push } // 38 is arrow up and 40 is arrow down. If quick look is active, we will close it and open it again with the new selection. else if((event.keyCode==38 || event.keyCode==40)&& !(event.ctrlKey || event.altKey || event.metaKey) && (Zotero.ZoteroQuickLook.isActive() || Zotero.ZoteroQuickLook.isBrowseMode)) { - Zotero.debug("ZoterQuickLook: is browsing"); + Zotero.debug("ZoteroQuickLook: is browsing"); if (! Zotero.ZoteroQuickLook.isBrowseMode) Zotero.ZoteroQuickLook.closeQuickLook(); success=Zotero.ZoteroQuickLook.openQuickLook(items); // If the items were not found, the viewer stays closed. However, if we are browsing through a list of items, we want to reopen the viewer when we hit the next item that has an attachment. Zotero.ZoteroQuickLook.isBrowseMode = ! success; - Zotero.debug("ZoterQuickLook: has browse mode set to " + Zotero.ZoteroQuickLook.isBrowseMode,3); + Zotero.debug("ZoteroQuickLook: has browse mode set to " + Zotero.ZoteroQuickLook.isBrowseMode,3); } return;