Skip to content

Commit bc2816c

Browse files
montezdesousaDidierRLopeshjoaquimminhhoang1023colin99d
authored
Autogenerated screenshots and plotshots (#2558)
* add screenshot and plotshot * handle 0 plots * black * change logo * change path spec * get window name automatically * create screenshot frame * merge commands * fix parser help * minor refactors * rewrite parser help * save img * small improvs (#2562) * prevent non windows users to use screenshot now * minor msg change * refine frames * update dependencies * black * flake8 * flake8 * change pyautogui import * update dependencies to avoid mouseinfo * update poetry and requirements * remove pygetwindow * revert dependency files to main * remove terminal ref * black * minor image change * black * move images to timages folder * move images to timages folder * remove unused var Co-authored-by: DidierRLopes <[email protected]> Co-authored-by: hjoaquim <[email protected]> Co-authored-by: minhhoang1023 <[email protected]> Co-authored-by: Colin Delahunty <[email protected]>
1 parent cb5e610 commit bc2816c

File tree

4 files changed

+124
-0
lines changed

4 files changed

+124
-0
lines changed

images/background.png

324 KB
Loading

images/openbb_horizontal_logo.png

897 Bytes
Loading

openbb_terminal/helper_funcs.py

+106
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
__docformat__ = "numpy"
33
# pylint: disable=too-many-lines
44
import argparse
5+
import io
56
import logging
67
from pathlib import Path
78
from typing import List, Union, Optional, Dict
@@ -35,6 +36,8 @@
3536
import yfinance as yf
3637
import numpy as np
3738

39+
from PIL import Image, ImageDraw
40+
3841
from openbb_terminal.rich_config import console
3942
from openbb_terminal import feature_flags as obbff
4043
from openbb_terminal import config_plot as cfgPlot
@@ -1671,6 +1674,109 @@ def search_wikipedia(expression: str) -> None:
16711674
)
16721675

16731676

1677+
def screenshot() -> None:
1678+
"""
1679+
Screenshot the terminal window or the plot window
1680+
1681+
Parameters
1682+
----------
1683+
terminal_window_target: bool
1684+
Target the terminal window
1685+
"""
1686+
try:
1687+
if plt.get_fignums():
1688+
img_buf = io.BytesIO()
1689+
plt.savefig(img_buf, format="png")
1690+
shot = Image.open(img_buf)
1691+
screenshot_to_canvas(shot, plot_exists=True)
1692+
console.print("")
1693+
1694+
else:
1695+
console.print("No plots found.\n")
1696+
1697+
except Exception as e:
1698+
console.print(f"Cannot reach window - {e}\n")
1699+
1700+
1701+
def screenshot_to_canvas(shot, plot_exists: bool = False):
1702+
"""
1703+
Frame image to OpenBB canvas.
1704+
1705+
Parameters
1706+
----------
1707+
shot
1708+
Image to frame with OpenBB Canvas
1709+
plot_exists: bool
1710+
Variable to say whether the image is a plot or screenshot of terminal
1711+
"""
1712+
1713+
WHITE_LINE_WIDTH = 3
1714+
OUTSIDE_CANVAS_WIDTH = shot.width + 4 * WHITE_LINE_WIDTH + 5
1715+
OUTSIDE_CANVAS_HEIGHT = shot.height + 4 * WHITE_LINE_WIDTH + 5
1716+
UPPER_SPACE = 40
1717+
BACKGROUND_WIDTH_SLACK = 150
1718+
BACKGROUND_HEIGHT_SLACK = 150
1719+
1720+
background = Image.open(Path("images/background.png"))
1721+
logo = Image.open(Path("images/openbb_horizontal_logo.png"))
1722+
1723+
try:
1724+
if plot_exists:
1725+
HEADER_HEIGHT = 0
1726+
RADIUS = 8
1727+
1728+
background = background.resize(
1729+
(
1730+
shot.width + BACKGROUND_WIDTH_SLACK,
1731+
shot.height + BACKGROUND_HEIGHT_SLACK,
1732+
)
1733+
)
1734+
1735+
x = int((background.width - OUTSIDE_CANVAS_WIDTH) / 2)
1736+
y = UPPER_SPACE
1737+
1738+
white_shape = [
1739+
(x, y),
1740+
(x + OUTSIDE_CANVAS_WIDTH, y + OUTSIDE_CANVAS_HEIGHT),
1741+
]
1742+
img = ImageDraw.Draw(background)
1743+
img.rounded_rectangle(
1744+
white_shape,
1745+
fill="black",
1746+
outline="white",
1747+
width=WHITE_LINE_WIDTH,
1748+
radius=RADIUS,
1749+
)
1750+
background.paste(shot, (x + WHITE_LINE_WIDTH + 5, y + WHITE_LINE_WIDTH + 5))
1751+
1752+
# Logo
1753+
background.paste(
1754+
logo,
1755+
(
1756+
int((background.width - logo.width) / 2),
1757+
UPPER_SPACE
1758+
+ OUTSIDE_CANVAS_HEIGHT
1759+
+ HEADER_HEIGHT
1760+
+ int(
1761+
(
1762+
background.height
1763+
- UPPER_SPACE
1764+
- OUTSIDE_CANVAS_HEIGHT
1765+
- HEADER_HEIGHT
1766+
- logo.height
1767+
)
1768+
/ 2
1769+
),
1770+
),
1771+
logo,
1772+
)
1773+
1774+
background.show(title="screenshot")
1775+
1776+
except Exception:
1777+
console.print("Shot failed.")
1778+
1779+
16741780
@lru_cache
16751781
def load_json(path: str) -> Dict[str, str]:
16761782
"""Loads a dictionary from a json file path

openbb_terminal/parent_classes.py

+18
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
load_json,
4343
parse_and_split_input,
4444
search_wikipedia,
45+
screenshot,
4546
)
4647
from openbb_terminal.config_terminal import theme
4748
from openbb_terminal.rich_config import console, get_ordered_list_sources
@@ -92,6 +93,7 @@ class BaseController(metaclass=ABCMeta):
9293
"wiki",
9394
"record",
9495
"stop",
96+
"screenshot",
9597
]
9698

9799
CHOICES_COMMANDS: List[str] = []
@@ -623,6 +625,22 @@ def call_stop(self, _) -> None:
623625
RECORD_SESSION = False
624626
SESSION_RECORDED = list()
625627

628+
@log_start_end(log=logger)
629+
def call_screenshot(self, other_args: List[str]) -> None:
630+
"""Process screenshot command"""
631+
parser = argparse.ArgumentParser(
632+
add_help=False,
633+
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
634+
prog="screenshot",
635+
description="Screenshot terminal window or plot figure open into an OpenBB frame. "
636+
"Default target is plot if there is one open, otherwise it's terminal window. "
637+
" In case the user wants the terminal window, it can be forced with '-t` or '--terminal' flag passed.",
638+
)
639+
ns_parser = parse_simple_args(parser, other_args)
640+
641+
if ns_parser:
642+
screenshot()
643+
626644
def parse_known_args_and_warn(
627645
self,
628646
parser: argparse.ArgumentParser,

0 commit comments

Comments
 (0)