[Bf-blender-cvs] [1f223b9a1fc] master: UI: Windows Shell Links & Improved Mac Aliases

Harley Acheson noreply at git.blender.org
Tue May 26 17:15:58 CEST 2020


Commit: 1f223b9a1fcef8b6eb69af9e2def351e2255a08e
Author: Harley Acheson
Date:   Tue May 26 08:14:41 2020 -0700
Branches: master
https://developer.blender.org/rB1f223b9a1fcef8b6eb69af9e2def351e2255a08e

UI: Windows Shell Links & Improved Mac Aliases

Adds support for Windows Shell Links (shortcuts) to the File Browser. Extended Mac Alias usage. Better visualization of linked items.

Differential Revision: https://developer.blender.org/D7380

Reviewed by Campbell Barton

===================================================================

M	source/blender/blenlib/intern/storage.c
M	source/blender/editors/space_file/file_draw.c
M	source/blender/editors/space_file/file_ops.c
M	source/blender/editors/space_file/filelist.c

===================================================================

diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c
index 87536ea8116..fbfb258693b 100644
--- a/source/blender/blenlib/intern/storage.c
+++ b/source/blender/blenlib/intern/storage.c
@@ -55,6 +55,7 @@
 #  include "utfconv.h"
 #  include <direct.h>
 #  include <io.h>
+#  include <shobjidl_core.h>
 #  include <stdbool.h>
 #else
 #  include <pwd.h>
@@ -226,12 +227,18 @@ size_t BLI_file_size(const char *path)
   return stats.st_size;
 }
 
+/* Return file attributes. Apple version of this function is defined in storage_apple.mm */
 #ifndef __APPLE__
 eFileAttributes BLI_file_attributes(const char *path)
 {
   int ret = 0;
 
 #  ifdef WIN32
+
+  if (BLI_path_extension_check(path, ".lnk")) {
+    return FILE_ATTR_ALIAS;
+  }
+
   WCHAR wline[FILE_MAXDIR];
   if (conv_utf_8_to_16(path, wline, ARRAY_SIZE(wline)) != 0) {
     return ret;
@@ -284,15 +291,52 @@ eFileAttributes BLI_file_attributes(const char *path)
 }
 #endif
 
-/**
- * Returns the target path of a file-based redirection, like Mac Alias or Win32 Shortcut file.
- */
+/* Return alias/shortcut file target. Apple version is defined in storage_apple.mm */
 #ifndef __APPLE__
-bool BLI_file_alias_target(char UNUSED(target[FILE_MAXDIR]), const char *UNUSED(filepath))
+bool BLI_file_alias_target(char target[FILE_MAXDIR], const char *filepath)
 {
-  /* TODO: Find target in Win32 Shortcut - Shell Link (.lnk) file.
-   * Format: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-shllink/ */
+#  ifdef WIN32
+  if (!BLI_path_extension_check(filepath, ".lnk")) {
+    return false;
+  }
+
+  IShellLinkW *Shortcut = NULL;
+  bool success = false;
+  CoInitializeEx(NULL, COINIT_MULTITHREADED);
+
+  HRESULT hr = CoCreateInstance(
+      &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLinkW, (LPVOID *)&Shortcut);
+  if (SUCCEEDED(hr)) {
+    IPersistFile *PersistFile;
+    hr = Shortcut->lpVtbl->QueryInterface(Shortcut, &IID_IPersistFile, (LPVOID *)&PersistFile);
+    if (SUCCEEDED(hr)) {
+      WCHAR path_utf16[FILE_MAXDIR] = {0};
+      if (conv_utf_8_to_16(filepath, path_utf16, ARRAY_SIZE(path_utf16)) == 0) {
+        hr = PersistFile->lpVtbl->Load(PersistFile, path_utf16, STGM_READ);
+        if (SUCCEEDED(hr)) {
+          hr = Shortcut->lpVtbl->Resolve(Shortcut, 0, SLR_NO_UI | SLR_UPDATE);
+          if (SUCCEEDED(hr)) {
+            wchar_t target_utf16[FILE_MAXDIR] = {0};
+            hr = Shortcut->lpVtbl->GetPath(Shortcut, target_utf16, FILE_MAXDIR, NULL, 0);
+            if (SUCCEEDED(hr)) {
+              success = (conv_utf_16_to_8(target_utf16, target, FILE_MAXDIR) == 0);
+            }
+          }
+          PersistFile->lpVtbl->Release(PersistFile);
+        }
+      }
+    }
+    Shortcut->lpVtbl->Release(Shortcut);
+  }
+
+  return (success && target[0]);
+#  endif
+
+#  ifdef __linux__
+  UNUSED_VARS(target, filepath);
+  /* File-based redirection not supported. */
   return false;
+#  endif
 }
 #endif
 
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index 226e7ae6b22..8d14664c0fa 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -220,7 +220,8 @@ static void file_draw_preview(uiBlock *block,
                               const bool is_icon,
                               const int typeflags,
                               const bool drag,
-                              const bool dimmed)
+                              const bool dimmed,
+                              const bool is_link)
 {
   uiBut *but;
   float fx, fy;
@@ -312,37 +313,57 @@ static void file_draw_preview(uiBlock *block,
   GPU_blend_set_func_separate(
       GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
 
-  if (icon && !(typeflags & FILE_TYPE_FTFONT)) {
-    /* size of center icon is scaled to fit container and UI scale */
+  if (icon && is_icon) {
+    /* Small icon in the middle of large image, scaled to fit container and UI scale */
     float icon_x, icon_y;
-
-    if (is_icon) {
-      const float icon_size = 16.0f / icon_aspect * U.dpi_fac;
-      float icon_opacity = 0.3f;
-      uchar icon_color[4] = {0, 0, 0, 255};
-      float bgcolor[4];
-      UI_GetThemeColor4fv(TH_ICON_FOLDER, bgcolor);
-      if (rgb_to_grayscale(bgcolor) < 0.5f) {
-        icon_color[0] = 255;
-        icon_color[1] = 255;
-        icon_color[2] = 255;
-      }
-      icon_x = xco + (ex / 2.0f) - (icon_size / 2.0f);
-      icon_y = yco + (ey / 2.0f) - (icon_size * ((typeflags & FILE_TYPE_DIR) ? 0.78f : 0.75f));
-      UI_icon_draw_ex(
-          icon_x, icon_y, icon, icon_aspect / U.dpi_fac, icon_opacity, 0.0f, icon_color, false);
+    const float icon_size = 16.0f / icon_aspect * U.dpi_fac;
+    float icon_opacity = 0.3f;
+    uchar icon_color[4] = {0, 0, 0, 255};
+    float bgcolor[4];
+    UI_GetThemeColor4fv(TH_ICON_FOLDER, bgcolor);
+    if (rgb_to_grayscale(bgcolor) < 0.5f) {
+      icon_color[0] = 255;
+      icon_color[1] = 255;
+      icon_color[2] = 255;
     }
-    else {
+    icon_x = xco + (ex / 2.0f) - (icon_size / 2.0f);
+    icon_y = yco + (ey / 2.0f) - (icon_size * ((typeflags & FILE_TYPE_DIR) ? 0.78f : 0.75f));
+    UI_icon_draw_ex(
+        icon_x, icon_y, icon, icon_aspect / U.dpi_fac, icon_opacity, 0.0f, icon_color, false);
+  }
+
+  if (is_link) {
+    /* Arrow icon to indicate it is a shortcut, link, or alias. */
+    float icon_x, icon_y;
+    icon_x = xco + (2.0f * UI_DPI_FAC);
+    icon_y = yco + (2.0f * UI_DPI_FAC);
+    const int arrow = ICON_LOOP_FORWARDS;
+    if (!is_icon) {
+      /* Arrow at very bottom-left if preview style. */
       const uchar dark[4] = {0, 0, 0, 255};
       const uchar light[4] = {255, 255, 255, 255};
-
-      /* Smaller, fainter icon for preview image thumbnail. */
-      icon_x = xco + (2.0f * UI_DPI_FAC);
-      icon_y = yco + (2.0f * UI_DPI_FAC);
-
-      UI_icon_draw_ex(icon_x + 1, icon_y - 1, icon, 1.0f / U.dpi_fac, 0.2f, 0.0f, dark, false);
-      UI_icon_draw_ex(icon_x, icon_y, icon, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false);
+      UI_icon_draw_ex(icon_x + 1, icon_y - 1, arrow, 1.0f / U.dpi_fac, 0.2f, 0.0f, dark, false);
+      UI_icon_draw_ex(icon_x, icon_y, arrow, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false);
     }
+    else {
+      /* Link to folder or non-previewed file. */
+      uchar icon_color[4];
+      UI_GetThemeColor4ubv(TH_BACK, icon_color);
+      icon_x = xco + ((typeflags & FILE_TYPE_DIR) ? 0.14f : 0.23f) * scaledx;
+      icon_y = yco + ((typeflags & FILE_TYPE_DIR) ? 0.24f : 0.14f) * scaledy;
+      UI_icon_draw_ex(
+          icon_x, icon_y, arrow, icon_aspect / U.dpi_fac * 1.8, 0.3f, 0.0f, icon_color, false);
+    }
+  }
+  else if (icon && !is_icon && !(typeflags & FILE_TYPE_FTFONT)) {
+    /* Smaller, fainter icon at bottom-left for preview image thumbnail, but not for fonts. */
+    float icon_x, icon_y;
+    const uchar dark[4] = {0, 0, 0, 255};
+    const uchar light[4] = {255, 255, 255, 255};
+    icon_x = xco + (2.0f * UI_DPI_FAC);
+    icon_y = yco + (2.0f * UI_DPI_FAC);
+    UI_icon_draw_ex(icon_x + 1, icon_y - 1, icon, 1.0f / U.dpi_fac, 0.2f, 0.0f, dark, false);
+    UI_icon_draw_ex(icon_x, icon_y, icon, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false);
   }
 
   /* Contrasting outline around some preview types. */
@@ -788,6 +809,7 @@ void file_draw_list(const bContext *C, ARegion *region)
     /* don't drag parent or refresh items */
     do_drag = !(FILENAME_IS_CURRPAR(file->relpath));
     const bool is_hidden = (file->attributes & FILE_ATTR_HIDDEN);
+    const bool is_link = (file->attributes & FILE_ATTR_ANY_LINK);
 
     if (FILE_IMGDISPLAY == params->display) {
       const int icon = filelist_geticon(files, i, false);
@@ -809,7 +831,8 @@ void file_draw_list(const bContext *C, ARegion *region)
                         is_icon,
                         file->typeflag,
                         do_drag,
-                        is_hidden);
+                        is_hidden,
+                        is_link);
     }
     else {
       file_draw_icon(block,
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index a5263378850..41d32fda088 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -1469,9 +1469,12 @@ void file_sfile_to_operator_ex(bContext *C, wmOperator *op, SpaceFile *sfile, ch
       for (i = 0; i < numfiles; i++) {
         if (filelist_entry_select_index_get(sfile->files, i, CHECK_FILES)) {
           FileDirEntry *file = filelist_file(sfile->files, i);
-          RNA_property_collection_add(op->ptr, prop, &itemptr);
-          RNA_string_set(&itemptr, "name", file->relpath);
-          num_files++;
+          /* Cannot (currently) mix regular items and alias/shortcuts in multiple selection. */
+          if (!file->redirection_path) {
+            RNA_property_collection_add(op->ptr, prop, &itemptr);
+            RNA_string_set(&itemptr, "name", file->relpath);
+            num_files++;
+          }
         }
       }
       /* make sure the file specified in the filename button is added even if no
@@ -1617,9 +1620,23 @@ static int file_exec(bContext *C, wmOperator *exec_op)
   Main *bmain = CTX_data_main(C);
   wmWindowManager *wm = CTX_wm_manager(C);
   SpaceFile *sfile = CTX_wm_space_file(C);
-  const struct FileDirEntry *file = filelist_file(sfile->files, sfile->params->active_file);
+  struct FileDirEntry *file = filelist_file(sfile->files, sfile->params->active_file);
   char filepath[FILE_MAX];
 
+  if (file && file->redirection_path) {
+    /* redirection_path is an absolute path that takes precedence
+     * over using sfile->params->dir + sfile->params->file. */
+    BLI_split_dirfile(file->redirection_path,
+                      sfile->params->dir,
+                      sfile->params->file,
+                      sizeof(sfile->params->dir),
+                      sizeof(sfile->params->file));
+    /* Update relpath with redirected filename as well so that the alternative
+     * combination of sfile->params->dir + relpath remains valid as well. */
+    MEM_freeN(file->relpath);
+    file->relpa

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list