feat: lockscreen closes #1490
This commit is contained in:
@@ -34,6 +34,12 @@ The options listed here are not editable from within the user interface.
|
||||
# Define one or more moonraker power devices that turn on/off with the screensaver (CSV list)
|
||||
# screen_on_devices: example1, example2
|
||||
# screen_off_devices: example1, example2
|
||||
|
||||
# Define the password to use when locking the screen, this is not secure
|
||||
# it's saved as plain text, it's meant to be a deterrent for kids or people at shows
|
||||
# it will be redacted from the logs.
|
||||
# default is no password
|
||||
# lock_password: example_password
|
||||
```
|
||||
|
||||
!!! tip
|
||||
|
@@ -168,6 +168,7 @@ class KlipperScreenConfig:
|
||||
strs = (
|
||||
'default_printer', 'language', 'print_sort_dir', 'theme', 'screen_blanking_printing', 'font_size',
|
||||
'print_estimate_method', 'screen_blanking', "screen_on_devices", "screen_off_devices", 'print_view',
|
||||
"lock_password"
|
||||
)
|
||||
numbers = (
|
||||
'job_complete_timeout', 'job_error_timeout', 'move_speed_xy', 'move_speed_z',
|
||||
@@ -584,14 +585,16 @@ class KlipperScreenConfig:
|
||||
self.config.set(section, name, value)
|
||||
|
||||
def log_config(self, config):
|
||||
sensitive_keys = [
|
||||
r'(moonraker_api_key\s*(?:=|:)\s*)\S+',
|
||||
r'(lock_password\s*(?:=|:)\s*)\S+',
|
||||
]
|
||||
config_str = self._build_config_string(config)
|
||||
for pattern in sensitive_keys:
|
||||
config_str = re.sub(pattern, r'\1[redacted]', config_str)
|
||||
lines = [
|
||||
" "
|
||||
"===== Config File =====",
|
||||
re.sub(
|
||||
r'(moonraker_api_key\s*=\s*\S+)',
|
||||
'moonraker_api_key = [redacted]',
|
||||
self._build_config_string(config)
|
||||
),
|
||||
config_str,
|
||||
"======================="
|
||||
]
|
||||
logging.info("\n".join(lines))
|
||||
|
@@ -10,7 +10,7 @@ from gi.repository import Gtk, GLib
|
||||
class Keyboard(Gtk.Box):
|
||||
langs = ["de", "en", "fr", "es"]
|
||||
|
||||
def __init__(self, screen, close_cb, entry=None):
|
||||
def __init__(self, screen, close_cb, entry=None, box=None):
|
||||
super().__init__(orientation=Gtk.Orientation.VERTICAL)
|
||||
self.shift = []
|
||||
self.shift_active = False
|
||||
@@ -20,6 +20,7 @@ class Keyboard(Gtk.Box):
|
||||
self.timeout = self.clear_timeout = None
|
||||
self.entry = entry
|
||||
self.purpose = self.entry.get_input_purpose()
|
||||
self.box = box or None
|
||||
|
||||
language = self.detect_language(screen._config.get_main_config().get("language", None))
|
||||
|
||||
@@ -218,7 +219,7 @@ class Keyboard(Gtk.Box):
|
||||
if key == "⌫":
|
||||
Gtk.Entry.do_backspace(self.entry)
|
||||
elif key == "↓":
|
||||
self.close_cb(entry=self.entry)
|
||||
self.close_cb(entry=self.entry, box=self.box)
|
||||
return
|
||||
elif key == "↑":
|
||||
self.toggle_shift()
|
||||
|
96
ks_includes/widgets/lockscreen.py
Normal file
96
ks_includes/widgets/lockscreen.py
Normal file
@@ -0,0 +1,96 @@
|
||||
import logging
|
||||
import gi
|
||||
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
|
||||
class LockScreen:
|
||||
def __init__(self, screen):
|
||||
self.screen = screen
|
||||
self.lock_box = None
|
||||
self.unlock_box = None
|
||||
|
||||
def lock(self, widget):
|
||||
self.screen._menu_go_back(None, True)
|
||||
logging.info("Locked the screen")
|
||||
close = Gtk.Button()
|
||||
close.connect("clicked", self.unlock)
|
||||
self.lock_box = Gtk.Box(
|
||||
width_request=self.screen.width, height_request=self.screen.height,
|
||||
halign=Gtk.Align.CENTER
|
||||
)
|
||||
self.lock_box.pack_start(close, True, True, 0)
|
||||
self.lock_box.get_style_context().add_class("lock")
|
||||
self.screen.overlay.add_overlay(self.lock_box)
|
||||
close.grab_focus()
|
||||
self.lock_box.show_all()
|
||||
|
||||
def unlock(self, widget):
|
||||
if not self.unlock_box:
|
||||
self.unlock_box = self.create_unlock_box()
|
||||
self.screen.overlay.add_overlay(self.unlock_box)
|
||||
self.unlock_box.show_all()
|
||||
self.screen.overlay.get_children()[0].hide()
|
||||
|
||||
def create_unlock_box(self):
|
||||
box = Gtk.Box(
|
||||
orientation=Gtk.Orientation.VERTICAL,
|
||||
width_request=self.screen.width, height_request=self.screen.height,
|
||||
valign=Gtk.Align.CENTER
|
||||
)
|
||||
entry = Gtk.Entry(hexpand=True, vexpand=False, placeholder_text=_("Password"))
|
||||
entry.set_input_purpose(Gtk.InputPurpose.PASSWORD)
|
||||
entry.set_visibility(False)
|
||||
entry.connect("focus-in-event", self.screen.show_keyboard, box, self.relock)
|
||||
entry.connect("activate", self.unlock_attempt, entry)
|
||||
entry.get_style_context().add_class("lockscreen_entry")
|
||||
entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, "view-reveal-symbolic")
|
||||
entry.connect("icon-press", self.show_pass)
|
||||
ok = Gtk.Button(label=_("Unlock"))
|
||||
ok.connect("clicked", self.unlock_attempt, entry)
|
||||
ok.get_style_context().add_class("lockscreen_button")
|
||||
entry_row = Gtk.Box(hexpand=True, vexpand=True, valign=Gtk.Align.CENTER)
|
||||
entry_row.pack_start(entry, True, True, 0)
|
||||
entry_row.pack_start(ok, False, True, 0)
|
||||
box.pack_start(entry_row, True, True, 0)
|
||||
return box
|
||||
|
||||
@staticmethod
|
||||
def show_pass(entry, icon_pos, event):
|
||||
entry.grab_focus()
|
||||
visible = not entry.get_visibility()
|
||||
entry.set_visibility(visible)
|
||||
if visible:
|
||||
entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, "view-conceal-symbolic")
|
||||
entry.get_style_context().add_class("active")
|
||||
else:
|
||||
entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, "view-reveal-symbolic")
|
||||
entry.get_style_context().remove_class("active")
|
||||
|
||||
def relock(self, entry=None, box=None):
|
||||
if not self.lock_box:
|
||||
return
|
||||
if self.unlock_box:
|
||||
self.screen.overlay.remove(self.unlock_box)
|
||||
self.unlock_box = None
|
||||
self.lock_box.get_children()[0].grab_focus()
|
||||
self.screen.overlay.get_children()[0].show_all()
|
||||
|
||||
def unlock_attempt(self, widget, entry):
|
||||
if entry.get_text() != self.screen._config.get_main_config().get("lock_password", ""):
|
||||
logging.info("Failed unlock")
|
||||
self.screen.show_popup_message(_("Unlock failed"))
|
||||
return
|
||||
self.clear_lock()
|
||||
|
||||
def clear_lock(self):
|
||||
if self.lock_box:
|
||||
self.screen.overlay.remove(self.lock_box)
|
||||
if self.unlock_box:
|
||||
self.screen.overlay.remove(self.unlock_box)
|
||||
self.lock_box = None
|
||||
self.unlock_box = None
|
||||
self.screen.remove_keyboard()
|
||||
self.screen.overlay.get_children()[0].show()
|
||||
logging.info("Unlocked")
|
@@ -24,12 +24,16 @@ class Panel(ScreenPanel):
|
||||
restart_ks = self._gtk.Button("refresh", _("Restart") + " KlipperScreen", "color3")
|
||||
restart_ks.connect("clicked", self._screen.restart_ks)
|
||||
|
||||
lock_screen = self._gtk.Button("lock", _("Lock"), "color3")
|
||||
lock_screen.connect("clicked", self._screen.lock_screen.lock)
|
||||
|
||||
self.main = Gtk.Grid(row_homogeneous=True, column_homogeneous=True)
|
||||
if self._printer and self._printer.state not in {'disconnected', 'startup', 'shutdown', 'error'}:
|
||||
self.main.attach(estop, 0, 0, 1, 1)
|
||||
self.main.attach(estop, 0, 0, 1, 2)
|
||||
self.main.attach(restart_ks, 1, 0, 1, 1)
|
||||
self.main.attach(poweroff, 0, 1, 1, 1)
|
||||
self.main.attach(restart, 1, 1, 1, 1)
|
||||
self.main.attach(lock_screen, 2, 0, 1, 1)
|
||||
self.main.attach(poweroff, 1, 1, 1, 1)
|
||||
self.main.attach(restart, 2, 1, 1, 1)
|
||||
self.content.add(self.main)
|
||||
|
||||
def reboot_poweroff(self, widget, method):
|
||||
|
37
screen.py
37
screen.py
@@ -29,9 +29,11 @@ from ks_includes.KlippyGtk import KlippyGtk
|
||||
from ks_includes.printer import Printer
|
||||
from ks_includes.widgets.keyboard import Keyboard
|
||||
from ks_includes.widgets.prompts import Prompt
|
||||
from ks_includes.widgets.lockscreen import LockScreen
|
||||
from ks_includes.config import KlipperScreenConfig
|
||||
from panels.base_panel import BasePanel
|
||||
|
||||
|
||||
logging.getLogger("urllib3").setLevel(logging.WARNING)
|
||||
|
||||
klipperscreendir = pathlib.Path(__file__).parent.resolve()
|
||||
@@ -77,6 +79,7 @@ class KlipperScreen(Gtk.Window):
|
||||
prompt = None
|
||||
tempstore_timeout = None
|
||||
|
||||
|
||||
def __init__(self, args):
|
||||
self.server_info = None
|
||||
try:
|
||||
@@ -150,7 +153,9 @@ class KlipperScreen(Gtk.Window):
|
||||
self.set_icon_from_file(os.path.join(klipperscreendir, "styles", "icon.svg"))
|
||||
self.base_panel = BasePanel(self)
|
||||
self.change_theme(self.theme)
|
||||
self.add(self.base_panel.main_grid)
|
||||
self.overlay = Gtk.Overlay()
|
||||
self.add(self.overlay)
|
||||
self.overlay.add_overlay(self.base_panel.main_grid)
|
||||
self.show_all()
|
||||
self.update_cursor(self.show_cursor)
|
||||
min_ver = (3, 8)
|
||||
@@ -167,6 +172,7 @@ class KlipperScreen(Gtk.Window):
|
||||
return
|
||||
self.base_panel.activate()
|
||||
self.set_screenblanking_timeout(self._config.get_main_config().get('screen_blanking'))
|
||||
self.lock_screen = LockScreen(self)
|
||||
self.log_notification("KlipperScreen Started", 1)
|
||||
self.initial_connection()
|
||||
|
||||
@@ -639,8 +645,7 @@ class KlipperScreen(Gtk.Window):
|
||||
box = Gtk.Box(halign=Gtk.Align.CENTER, width_request=self.width, height_request=self.height)
|
||||
box.pack_start(close, True, True, 0)
|
||||
box.get_style_context().add_class("screensaver")
|
||||
self.remove(self.base_panel.main_grid)
|
||||
self.add(box)
|
||||
self.overlay.add_overlay(box)
|
||||
|
||||
# Avoid leaving a cursor-handle
|
||||
close.grab_focus()
|
||||
@@ -655,9 +660,8 @@ class KlipperScreen(Gtk.Window):
|
||||
if self.screensaver is None:
|
||||
return False
|
||||
logging.debug("Closing Screensaver")
|
||||
self.remove(self.screensaver)
|
||||
self.overlay.remove(self.screensaver)
|
||||
self.screensaver = None
|
||||
self.add(self.base_panel.main_grid)
|
||||
if self.use_dpms:
|
||||
self.wake_screen()
|
||||
else:
|
||||
@@ -666,8 +670,8 @@ class KlipperScreen(Gtk.Window):
|
||||
logging.info(f"Restoring Dialog {dialog}")
|
||||
dialog.show()
|
||||
self.gtk.set_cursor(self.show_cursor, window=self.get_window())
|
||||
self.show_all()
|
||||
self.power_devices(None, self._config.get_main_config().get("screen_on_devices", ""), on=True)
|
||||
self.lock_screen.relock()
|
||||
|
||||
def check_dpms_state(self):
|
||||
if not self.use_dpms:
|
||||
@@ -1187,12 +1191,16 @@ class KlipperScreen(Gtk.Window):
|
||||
self.remove_tempstore_timeout()
|
||||
return self.init_tempstore()
|
||||
|
||||
def show_keyboard(self, entry=None, event=None):
|
||||
def show_keyboard(self, entry=None, event=None, box=None, close_cb=None):
|
||||
if entry is None:
|
||||
logging.debug("Error: no entry provided for keyboard")
|
||||
return
|
||||
if box is None:
|
||||
box = self.base_panel.content
|
||||
if close_cb is None:
|
||||
close_cb = self.remove_keyboard
|
||||
if self.keyboard is not None:
|
||||
self.remove_keyboard()
|
||||
self.remove_keyboard(box=box)
|
||||
entry.grab_focus()
|
||||
kbd_grid = Gtk.Grid()
|
||||
kbd_grid.set_size_request(self.gtk.content_width, self.gtk.keyboard_height)
|
||||
@@ -1206,11 +1214,12 @@ class KlipperScreen(Gtk.Window):
|
||||
kbd_grid.set_column_homogeneous(True)
|
||||
kbd_width = 2 if purpose == Gtk.InputPurpose.DIGITS else 3
|
||||
kbd_grid.attach(Gtk.Box(), 0, 0, 1, 1)
|
||||
kbd_grid.attach(Keyboard(self, self.remove_keyboard, entry=entry), 1, 0, kbd_width, 1)
|
||||
kbd = Keyboard(self, close_cb, entry=entry, box=box)
|
||||
kbd_grid.attach(kbd, 1, 0, kbd_width, 1)
|
||||
kbd_grid.attach(Gtk.Box(), kbd_width + 1, 0, 1, 1)
|
||||
self.keyboard = {"box": kbd_grid}
|
||||
self.base_panel.content.pack_end(kbd_grid, False, False, 0)
|
||||
self.base_panel.content.show_all()
|
||||
box.pack_end(kbd_grid, False, False, 0)
|
||||
box.show_all()
|
||||
|
||||
def _show_matchbox_keyboard(self, kbd_grid):
|
||||
env = os.environ.copy()
|
||||
@@ -1240,12 +1249,14 @@ class KlipperScreen(Gtk.Window):
|
||||
}
|
||||
return
|
||||
|
||||
def remove_keyboard(self, entry=None, event=None):
|
||||
def remove_keyboard(self, entry=None, event=None, box=None):
|
||||
if self.keyboard is None:
|
||||
return
|
||||
if box is None:
|
||||
box = self.base_panel.content
|
||||
if 'process' in self.keyboard:
|
||||
os.kill(self.keyboard['process'].pid, SIGTERM)
|
||||
self.base_panel.content.remove(self.keyboard['box'])
|
||||
box.remove(self.keyboard['box'])
|
||||
self.keyboard = None
|
||||
if entry:
|
||||
entry.set_sensitive(False) # Move the focus
|
||||
|
@@ -563,6 +563,24 @@ popover button {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.lock
|
||||
.lock button
|
||||
.lock button:hover,
|
||||
.lock button:focus,
|
||||
.lock button:active {
|
||||
border: 0;
|
||||
margin: 0;
|
||||
background-color: Transparent;
|
||||
}
|
||||
|
||||
.lockscreen_entry {
|
||||
margin: 2em;
|
||||
}
|
||||
|
||||
.lockscreen_button {
|
||||
padding: 2em;
|
||||
}
|
||||
|
||||
.screensaver,
|
||||
.screensaver button,
|
||||
.screensaver button:hover,
|
||||
|
93
styles/colorized/images/lock.svg
Normal file
93
styles/colorized/images/lock.svg
Normal file
@@ -0,0 +1,93 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
version="1.1"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
id="svg957"
|
||||
sodipodi:docname="lock.svg"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs961" />
|
||||
<sodipodi:namedview
|
||||
id="namedview959"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#ffffff"
|
||||
borderopacity="1"
|
||||
inkscape:pageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="13"
|
||||
inkscape:cx="9.5384615"
|
||||
inkscape:cy="10.692308"
|
||||
inkscape:window-width="1600"
|
||||
inkscape:window-height="828"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg957"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:deskcolor="#505050"
|
||||
showguides="true">
|
||||
<sodipodi:guide
|
||||
position="7.5334069,21.1875"
|
||||
orientation="0,1"
|
||||
id="guide1503"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="11.15053,22.721769"
|
||||
orientation="0,-1"
|
||||
id="guide1505"
|
||||
inkscape:locked="false" />
|
||||
</sodipodi:namedview>
|
||||
<path
|
||||
d="M 7.625,12.125 V 8.3750002 C 7.625,7.1645835 8.0515627,6.1328127 8.904688,5.2796878 9.757812,4.4265626 10.789582,4 11.999998,4 13.210416,4 14.242188,4.4265626 15.095313,5.2796878 15.948438,6.1328127 16.375,7.1645835 16.375,8.3750002 V 12.125 Z m 1.75,0 h 5.25 V 8.3750002 C 14.625,7.6458336 14.369792,7.0260419 13.859375,6.5156251 13.348958,6.0052084 12.729166,5.75 11.999998,5.75 11.270833,5.75 10.651041,6.0052084 10.140624,6.5156251 9.630208,7.0260419 9.375,7.6458336 9.375,8.3750002 Z"
|
||||
id="path233"
|
||||
style="font-variation-settings:normal;opacity:0.998;vector-effect:none;fill:#839496;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1"
|
||||
sodipodi:nodetypes="csssssccccsssssc" />
|
||||
<rect
|
||||
style="font-variation-settings:normal;opacity:0.998;vector-effect:none;fill:#839496;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1"
|
||||
id="rect676"
|
||||
width="12.25"
|
||||
height="10.208334"
|
||||
x="5.875"
|
||||
y="10.895833" />
|
||||
<rect
|
||||
style="opacity:0.998;fill:#657b83;fill-opacity:1;stroke:none;stroke-width:2.00001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stop-color:#000000"
|
||||
id="rect1039-5"
|
||||
width="12.25"
|
||||
height="3.0625"
|
||||
x="5.875"
|
||||
y="10.895833" />
|
||||
<rect
|
||||
style="opacity:0.998;fill:#657b83;fill-opacity:1;stroke:none;stroke-width:2.00001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stop-color:#000000"
|
||||
id="rect1039-5-6"
|
||||
width="12.25"
|
||||
height="3.0625"
|
||||
x="5.875"
|
||||
y="18.041666" />
|
||||
<circle
|
||||
style="font-variation-settings:normal;opacity:0.998;vector-effect:none;fill:#93a1a1;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1"
|
||||
id="path1722"
|
||||
cx="12"
|
||||
cy="16"
|
||||
r="3" />
|
||||
<circle
|
||||
style="font-variation-settings:normal;opacity:0.998;vector-effect:none;fill:#839496;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1"
|
||||
id="path1722-0"
|
||||
cx="12"
|
||||
cy="16"
|
||||
r="2" />
|
||||
<rect
|
||||
style="font-variation-settings:normal;opacity:0.998;vector-effect:none;fill:#073642;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1"
|
||||
id="rect1965"
|
||||
width="1"
|
||||
height="3"
|
||||
x="11.5"
|
||||
y="14.5" />
|
||||
</svg>
|
After Width: | Height: | Size: 4.3 KiB |
40
styles/material-dark/images/lock.svg
Normal file
40
styles/material-dark/images/lock.svg
Normal file
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
version="1.1"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
id="svg957"
|
||||
sodipodi:docname="lock.svg"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs961" />
|
||||
<sodipodi:namedview
|
||||
id="namedview959"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#ffffff"
|
||||
borderopacity="1"
|
||||
inkscape:pageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="13"
|
||||
inkscape:cx="8.4230769"
|
||||
inkscape:cy="13.615385"
|
||||
inkscape:window-width="1600"
|
||||
inkscape:window-height="828"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg957"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:deskcolor="#505050" />
|
||||
<path
|
||||
d="m 6.75,21.1875 q -0.721876,0 -1.235938,-0.514062 Q 5,20.159375 5,19.4375 v -8.75 Q 5,9.9656252 5.514062,9.4515625 6.028124,8.9375001 6.75,8.9375001 H 7.625 V 7.1875002 Q 7.625,5.3718751 8.904688,4.0921878 10.184374,2.8125 11.999998,2.8125 q 1.815627,0 3.095315,1.2796878 Q 16.375,5.3718751 16.375,7.1875002 v 1.7499999 h 0.875 q 0.721875,0 1.235938,0.5140624 Q 19,9.9656252 19,10.6875 v 8.75 q 0,0.721875 -0.514062,1.235938 Q 17.971875,21.1875 17.25,21.1875 Z m 0,-1.75 h 10.5 v -8.75 H 6.75 Z m 5.249998,-2.625 q 0.721875,0 1.23594,-0.514062 Q 13.75,15.784375 13.75,15.062501 q 0,-0.721875 -0.514062,-1.235939 -0.514065,-0.514061 -1.23594,-0.514061 -0.721875,0 -1.235935,0.514061 Q 10.25,14.340626 10.25,15.062501 q 0,0.721874 0.514063,1.235937 0.51406,0.514062 1.235935,0.514062 z M 9.375,8.9375001 h 5.25 V 7.1875002 q 0,-1.0937499 -0.765625,-1.8593751 Q 13.09375,4.5625 11.999998,4.5625 10.90625,4.5625 10.140624,5.3281251 9.375,6.0937503 9.375,7.1875002 Z M 6.75,19.4375 v -8.75 z"
|
||||
id="path233"
|
||||
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#e2e2e2;fill-opacity:1;stroke-width:0.999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1" />
|
||||
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
41
styles/material-darker/images/lock.svg
Normal file
41
styles/material-darker/images/lock.svg
Normal file
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
version="1.1"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
id="svg957"
|
||||
sodipodi:docname="lock.svg"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs961" />
|
||||
<sodipodi:namedview
|
||||
id="namedview959"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#ffffff"
|
||||
borderopacity="1"
|
||||
inkscape:pageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="13"
|
||||
inkscape:cx="-1.6923077"
|
||||
inkscape:cy="13.615385"
|
||||
inkscape:window-width="1600"
|
||||
inkscape:window-height="828"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg957"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:deskcolor="#505050" />
|
||||
<path
|
||||
d="m 6.75,21.1875 c -0.4812507,0 -0.89323,-0.171354 -1.235938,-0.514062 C 5.171354,20.330729 5,19.91875 5,19.4375 v -8.75 C 5,10.20625 5.171354,9.794271 5.514062,9.4515625 5.85677,9.1088542 6.2687493,8.9375001 6.75,8.9375001 H 7.625 V 7.1875002 C 7.625,5.9770835 8.0515627,4.9453127 8.904688,4.0921878 9.757812,3.2390626 10.789582,2.8125 11.999998,2.8125 c 1.210418,0 2.24219,0.4265626 3.095315,1.2796878 C 15.948438,4.9453127 16.375,5.9770835 16.375,7.1875002 v 1.7499999 h 0.875 c 0.48125,0 0.893229,0.1713541 1.235938,0.5140624 C 18.828646,9.794271 19,10.20625 19,10.6875 v 8.75 c 0,0.48125 -0.171354,0.893229 -0.514062,1.235938 C 18.143229,21.016146 17.73125,21.1875 17.25,21.1875 Z m 5.249998,-4.375 c 0.48125,0 0.89323,-0.171354 1.23594,-0.514062 C 13.578646,15.955729 13.75,15.54375 13.75,15.062501 c 0,-0.48125 -0.171354,-0.89323 -0.514062,-1.235939 -0.34271,-0.342707 -0.75469,-0.514061 -1.23594,-0.514061 -0.48125,0 -0.893228,0.171354 -1.235935,0.514061 C 10.421354,14.169271 10.25,14.581251 10.25,15.062501 c 0,0.481249 0.171354,0.893228 0.514063,1.235937 0.342707,0.342708 0.754685,0.514062 1.235935,0.514062 z M 9.375,8.9375001 h 5.25 V 7.1875002 C 14.625,6.4583336 14.369792,5.8385419 13.859375,5.3281251 13.348958,4.8177084 12.729166,4.5625 11.999998,4.5625 c -0.729165,0 -1.348957,0.2552084 -1.859374,0.7656251 C 9.630208,5.8385419 9.375,6.4583336 9.375,7.1875002 Z"
|
||||
id="path233"
|
||||
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#e2e2e2;fill-opacity:1;stroke-width:0.999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1"
|
||||
sodipodi:nodetypes="sssssscssssscssssssssssssssssccsssssc" />
|
||||
</svg>
|
After Width: | Height: | Size: 2.8 KiB |
40
styles/material-light/images/lock.svg
Normal file
40
styles/material-light/images/lock.svg
Normal file
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
version="1.1"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
id="svg957"
|
||||
sodipodi:docname="lock.svg"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs961" />
|
||||
<sodipodi:namedview
|
||||
id="namedview959"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#ffffff"
|
||||
borderopacity="1"
|
||||
inkscape:pageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="13"
|
||||
inkscape:cx="-1.6923077"
|
||||
inkscape:cy="13.615385"
|
||||
inkscape:window-width="1600"
|
||||
inkscape:window-height="828"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg957"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:deskcolor="#505050" />
|
||||
<path
|
||||
d="m 6.75,21.1875 q -0.721876,0 -1.235938,-0.514062 Q 5,20.159375 5,19.4375 v -8.75 Q 5,9.9656252 5.514062,9.4515625 6.028124,8.9375001 6.75,8.9375001 H 7.625 V 7.1875002 Q 7.625,5.3718751 8.904688,4.0921878 10.184374,2.8125 11.999998,2.8125 q 1.815627,0 3.095315,1.2796878 Q 16.375,5.3718751 16.375,7.1875002 v 1.7499999 h 0.875 q 0.721875,0 1.235938,0.5140624 Q 19,9.9656252 19,10.6875 v 8.75 q 0,0.721875 -0.514062,1.235938 Q 17.971875,21.1875 17.25,21.1875 Z m 0,-1.75 h 10.5 v -8.75 H 6.75 Z m 5.249998,-2.625 q 0.721875,0 1.23594,-0.514062 Q 13.75,15.784375 13.75,15.062501 q 0,-0.721875 -0.514062,-1.235939 -0.514065,-0.514061 -1.23594,-0.514061 -0.721875,0 -1.235935,0.514061 Q 10.25,14.340626 10.25,15.062501 q 0,0.721874 0.514063,1.235937 0.51406,0.514062 1.235935,0.514062 z M 9.375,8.9375001 h 5.25 V 7.1875002 q 0,-1.0937499 -0.765625,-1.8593751 Q 13.09375,4.5625 11.999998,4.5625 10.90625,4.5625 10.140624,5.3281251 9.375,6.0937503 9.375,7.1875002 Z M 6.75,19.4375 v -8.75 z"
|
||||
id="path233"
|
||||
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1" />
|
||||
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
97
styles/z-bolt/images/lock.svg
Normal file
97
styles/z-bolt/images/lock.svg
Normal file
@@ -0,0 +1,97 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="64"
|
||||
height="64"
|
||||
viewBox="0 0 64 64"
|
||||
version="1.1"
|
||||
id="svg10"
|
||||
sodipodi:docname="lock.svg"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<metadata
|
||||
id="metadata16">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title>folder</dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs14" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#bfbfbf"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1600"
|
||||
inkscape:window-height="828"
|
||||
id="namedview12"
|
||||
showgrid="false"
|
||||
inkscape:pagecheckerboard="false"
|
||||
inkscape:zoom="10.827586"
|
||||
inkscape:cx="26.229299"
|
||||
inkscape:cy="44.423567"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg10"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:document-rotation="0"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:deskcolor="#bfbfbf" />
|
||||
<!-- Generator: Sketch 52.5 (67469) - http://www.bohemiancoding.com/sketch -->
|
||||
<title
|
||||
id="title2">folder</title>
|
||||
<desc
|
||||
id="desc4">Created with Sketch.</desc>
|
||||
<ellipse
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path5114"
|
||||
cx="31.929701"
|
||||
cy="41.06234"
|
||||
rx="4.3648357"
|
||||
ry="4.4511104" />
|
||||
<rect
|
||||
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1"
|
||||
id="rect602"
|
||||
width="32"
|
||||
height="27"
|
||||
x="16"
|
||||
y="27.5" />
|
||||
<g
|
||||
id="g745"
|
||||
transform="translate(0,1)">
|
||||
<path
|
||||
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1"
|
||||
id="path680"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="32"
|
||||
sodipodi:cy="18"
|
||||
sodipodi:rx="11"
|
||||
sodipodi:ry="11"
|
||||
sodipodi:start="3.1415927"
|
||||
sodipodi:end="0"
|
||||
sodipodi:arc-type="arc"
|
||||
d="M 21,18 A 11,11 0 0 1 32,7 11,11 0 0 1 43,18"
|
||||
sodipodi:open="true" />
|
||||
<path
|
||||
id="path738"
|
||||
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1"
|
||||
d="m 43,18 v 8.5 M 21,18 v 8.5 h 22" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.6 KiB |
Reference in New Issue
Block a user