client/securedrop_client/resources/__init__.py (49 lines of code) (raw):
"""
Functions needed to work with non-code resources such as images (icons and SVG
files) and CSS (for configuring the look of the UI).
Copyright (C) 2018 The Freedom of the Press Foundation.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from pathlib import Path
from PyQt5.QtCore import QDir
from PyQt5.QtGui import QFontDatabase, QIcon, QMovie, QPixmap
from PyQt5.QtSvg import QSvgWidget
RESOURCES_DIR = Path(__file__).parent
# Add resource directories to the search path.
QDir.addSearchPath("images", str(RESOURCES_DIR / "images"))
QDir.addSearchPath("css", str(RESOURCES_DIR / "css"))
def path(name: str) -> str:
"""
Return the filename for the referenced image.
Qt uses unix path conventions.
"""
return str(RESOURCES_DIR / "images" / name)
def load_all_fonts() -> None:
"""Load all the fonts in the fonts/ directory"""
for font in (RESOURCES_DIR / "fonts").glob("**/*.ttf"):
QFontDatabase.addApplicationFont(str(font.absolute()))
def load_icon(
normal: str,
disabled: str | None = None,
active: str | None = None,
selected: str | None = None,
normal_off: str | None = None,
disabled_off: str | None = None,
active_off: str | None = None,
selected_off: str | None = None,
) -> QIcon:
"""
Add the contents of Scalable Vector Graphics (SVG) files provided for associated icon modes and
states, see https://doc.qt.io/qt-5/qicon.html#Mode-enum. If the widget containing this icon is
set to checkable, then the *_off states will be displayed.
Parameters
----------
normal: str
The name of the SVG file to add to the icon for QIcon.Normal mode.
disabled: str or None, optional
The name of the SVG file to add to the icon for QIcon.Disabled mode.
active: str, optional
The name of the SVG file to add to the icon for QIcon.Active mode.
selected: str, optional
The name of the SVG file to add to the icon for QIcon.Selected mode.
normal_off: str
The name of the SVG file to add to the icon for QIcon.Normal mode.
disabled_off: str or None, optional
The name of the SVG file to add to the icon for QIcon.Disabled mode.
active_off: str, optional
The name of the SVG file to add to the icon for QIcon.Active mode.
selected_off: str, optional
The name of the SVG file to add to the icon for QIcon.Selected mode.
Returns
-------
QIcon
The icon that displays the contents of the SVG files.
"""
icon = QIcon()
icon.addFile(path(normal), mode=QIcon.Normal, state=QIcon.On)
if disabled:
icon.addFile(path(disabled), mode=QIcon.Disabled, state=QIcon.On)
if active:
icon.addFile(path(active), mode=QIcon.Active, state=QIcon.On)
if selected:
icon.addFile(path(selected), mode=QIcon.Selected, state=QIcon.On)
if normal_off:
icon.addFile(path(normal_off), mode=QIcon.Normal, state=QIcon.Off)
if disabled_off:
icon.addFile(path(disabled_off), mode=QIcon.Disabled, state=QIcon.Off)
if active_off:
icon.addFile(path(active_off), mode=QIcon.Active, state=QIcon.Off)
if selected_off:
icon.addFile(path(selected_off), mode=QIcon.Selected, state=QIcon.Off)
return icon
def load_svg(name: str) -> QSvgWidget:
"""
Return a QSvgWidget representation of a file in the resources.
"""
return QSvgWidget(path(name))
def load_image(name: str) -> QPixmap:
"""
Return a QPixmap representation of a file in the resources.
"""
return QPixmap(path(name))
def load_css(name: str) -> str:
"""
Return the contents of the referenced CSS file in the resources.
"""
return (RESOURCES_DIR / "css" / name).read_text()
def load_relative_css(file: str, name: str) -> str:
"""
Load CSS that's in the same directory as the file calling this.
The first argument should be __name__ and the second is the name of the CSS
"""
return (Path(file).parent / name).read_text()
def load_movie(name: str) -> QMovie:
"""
Return a GIF animation to use in the UI.
"""
return QMovie(path(name))