Skip to content

Commit 4c5a47c

Browse files
committed
Qt scraper: Fix thumbnail generation for sphinx-gallery subdirectories
1 parent cea6c46 commit 4c5a47c

File tree

2 files changed

+76
-8
lines changed

2 files changed

+76
-8
lines changed

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44

55
🛠️ Bug fixes:
66

7-
*
7+
* **Qt scraper**: Fixed thumbnail generation for sphinx-gallery examples in subdirectories
8+
* The `qt_scraper` now correctly detects and handles examples organized in subsections (e.g., `examples/features/`, `examples/advanced/`)
9+
* Thumbnails are now saved in the correct subdirectory-specific `images/thumb/` folders instead of the top-level directory
10+
* Image paths in generated RST files now include the subdirectory path
11+
* Added new `_get_example_subdirectory()` helper function to extract subdirectory from source file path and avoid code duplication
812

913
## Version 3.13.0 ##
1014

guidata/utils/qt_scraper.py

Lines changed: 71 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -214,11 +214,55 @@ def _ensure_qapplication() -> QApplication | None:
214214
return None
215215

216216

217-
def _get_image_directory(gallery_conf: dict[str, Any]) -> Path | None:
217+
def _get_example_subdirectory(
218+
gallery_conf: dict[str, Any], block_vars: dict[str, Any] | None
219+
) -> str:
220+
"""Extract subdirectory from example source file path.
221+
222+
Args:
223+
gallery_conf: Sphinx-Gallery configuration.
224+
block_vars: Variables from the executed code block.
225+
226+
Returns:
227+
Subdirectory name (e.g., "features", "advanced") or empty string if not found.
228+
"""
229+
if not block_vars or "src_file" not in block_vars:
230+
return ""
231+
232+
src_file = Path(str(block_vars["src_file"]))
233+
examples_dirs = gallery_conf.get("examples_dirs", "examples")
234+
235+
# Handle both string and list cases for examples_dirs
236+
if isinstance(examples_dirs, list):
237+
examples_dir = examples_dirs[0] if examples_dirs else "examples"
238+
else:
239+
examples_dir = examples_dirs
240+
241+
# Try to extract subdirectory from source file path
242+
# e.g., "examples/features/convolution.py" -> "features"
243+
try:
244+
if examples_dir in src_file.parts:
245+
idx = src_file.parts.index(examples_dir)
246+
# Check if there's a subdirectory between examples_dir and the file
247+
if idx + 2 < len(src_file.parts):
248+
subdirectory = src_file.parts[idx + 1]
249+
logger.debug("Detected subdirectory: %s", subdirectory)
250+
return subdirectory
251+
except (ValueError, IndexError) as exc:
252+
logger.debug("Could not determine subdirectory: %s", exc)
253+
254+
return ""
255+
256+
257+
def _get_image_directory(
258+
gallery_conf: dict[str, Any], block_vars: dict[str, Any] | None = None
259+
) -> Path | None:
218260
"""Get the image directory for saving screenshots.
219261
220262
Args:
221263
gallery_conf: Sphinx-Gallery configuration.
264+
block_vars: Variables from the executed code block (optional).
265+
Used to determine subdirectory for examples in subsections.
222266
223267
Returns:
224268
Path to image directory or None if cannot be determined.
@@ -236,20 +280,32 @@ def _get_image_directory(gallery_conf: dict[str, Any]) -> Path | None:
236280
else:
237281
gallery_dir = gallery_dirs
238282

239-
img_dir = src_dir / gallery_dir / "images"
283+
# Determine subdirectory from source file if available
284+
subdirectory = _get_example_subdirectory(gallery_conf, block_vars)
285+
286+
if subdirectory:
287+
img_dir = src_dir / gallery_dir / subdirectory / "images"
288+
else:
289+
img_dir = src_dir / gallery_dir / "images"
290+
240291
img_dir.mkdir(parents=True, exist_ok=True)
241292
return img_dir
242293

243294

244295
def _generate_rst_block(
245-
image_name: str, gallery_conf: dict[str, Any], widget_index: int
296+
image_name: str,
297+
gallery_conf: dict[str, Any],
298+
widget_index: int,
299+
block_vars: dict[str, Any] | None = None,
246300
) -> str:
247301
"""Generate RST code block for an image.
248302
249303
Args:
250304
image_name: Name of the image file.
251305
gallery_conf: Sphinx-Gallery configuration.
252306
widget_index: Index of the widget (for alt text).
307+
block_vars: Variables from the executed code block (optional).
308+
Used to determine subdirectory for examples in subsections.
253309
254310
Returns:
255311
RST code block.
@@ -260,8 +316,16 @@ def _generate_rst_block(
260316
else:
261317
rst_gallery_dir = gallery_dirs
262318

319+
# Determine subdirectory from source file if available
320+
subdirectory = _get_example_subdirectory(gallery_conf, block_vars)
321+
322+
if subdirectory:
323+
image_path = f"/{rst_gallery_dir}/{subdirectory}/images/{image_name}"
324+
else:
325+
image_path = f"/{rst_gallery_dir}/images/{image_name}"
326+
263327
return f"""
264-
.. image:: /{rst_gallery_dir}/images/{image_name}
328+
.. image:: {image_path}
265329
:alt: Qt widget {widget_index + 1}
266330
:class: sphx-glr-single-img
267331
"""
@@ -336,8 +400,8 @@ def qt_scraper(
336400
if not widgets:
337401
return ""
338402

339-
# Get image directory
340-
img_dir = _get_image_directory(gallery_conf)
403+
# Get image directory (pass block_vars to determine subdirectory)
404+
img_dir = _get_image_directory(gallery_conf, block_vars)
341405
if img_dir is None:
342406
logger.error("Cannot determine image directory")
343407
return ""
@@ -369,7 +433,7 @@ def qt_scraper(
369433
success = _capture_widget(widget, image_path)
370434

371435
if success:
372-
rst_block = _generate_rst_block(image_name, gallery_conf, i)
436+
rst_block = _generate_rst_block(image_name, gallery_conf, i, block_vars)
373437
rst_blocks.append(rst_block)
374438
successful_widgets.append(widget)
375439
successful_indices.append(i)

0 commit comments

Comments
 (0)