Add image to break screen
|
@ -97,8 +97,8 @@ class BreakScreen:
|
||||||
"""
|
"""
|
||||||
Show the break screen with the given message on all displays.
|
Show the break screen with the given message on all displays.
|
||||||
"""
|
"""
|
||||||
def show_message(self, message):
|
def show_message(self, message, image_path):
|
||||||
GLib.idle_add(lambda: self.__show_break_screen(message))
|
GLib.idle_add(lambda: self.__show_break_screen(message, image_path))
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -115,7 +115,7 @@ class BreakScreen:
|
||||||
"""
|
"""
|
||||||
Show an empty break screen on all screens.
|
Show an empty break screen on all screens.
|
||||||
"""
|
"""
|
||||||
def __show_break_screen(self, message):
|
def __show_break_screen(self, message, image_path):
|
||||||
# Lock the keyboard
|
# Lock the keyboard
|
||||||
thread = threading.Thread(target=self.__lock_keyboard)
|
thread = threading.Thread(target=self.__lock_keyboard)
|
||||||
thread.start()
|
thread.start()
|
||||||
|
@ -138,12 +138,11 @@ class BreakScreen:
|
||||||
lbl_count = builder.get_object("lbl_count")
|
lbl_count = builder.get_object("lbl_count")
|
||||||
btn_skip = builder.get_object("btn_skip")
|
btn_skip = builder.get_object("btn_skip")
|
||||||
btn_postpone = builder.get_object("btn_postpone")
|
btn_postpone = builder.get_object("btn_postpone")
|
||||||
|
lbl_left = builder.get_object("lbl_left")
|
||||||
|
lbl_right = builder.get_object("lbl_right")
|
||||||
|
img_break = builder.get_object("img_break")
|
||||||
|
|
||||||
lbl_message.set_label(message)
|
window.move(x, y)
|
||||||
btn_skip.set_label(self.skip_button_text)
|
|
||||||
btn_skip.set_visible(not self.strict_break)
|
|
||||||
btn_postpone.set_label(self.postpone_button_text)
|
|
||||||
btn_postpone.set_visible(not self.strict_break)
|
|
||||||
|
|
||||||
self.windows.append(window)
|
self.windows.append(window)
|
||||||
self.count_labels.append(lbl_count)
|
self.count_labels.append(lbl_count)
|
||||||
|
@ -151,12 +150,26 @@ class BreakScreen:
|
||||||
# Set visual to apply css theme. It should be called before show method.
|
# Set visual to apply css theme. It should be called before show method.
|
||||||
window.set_visual(window.get_screen().get_rgba_visual())
|
window.set_visual(window.get_screen().get_rgba_visual())
|
||||||
|
|
||||||
window.move(x, y)
|
|
||||||
window.stick()
|
window.stick()
|
||||||
window.set_keep_above(True)
|
window.set_keep_above(True)
|
||||||
window.present()
|
window.present()
|
||||||
|
window.set_position(Gtk.WindowPosition.CENTER_ALWAYS)
|
||||||
|
window.resize(monitor_gemoetry.width, monitor_gemoetry.height)
|
||||||
window.fullscreen()
|
window.fullscreen()
|
||||||
|
|
||||||
|
# Set values
|
||||||
|
if image_path:
|
||||||
|
img_break.set_from_file(image_path)
|
||||||
|
lbl_message.set_label(message)
|
||||||
|
btn_skip.set_label(self.skip_button_text)
|
||||||
|
btn_postpone.set_label(self.postpone_button_text)
|
||||||
|
|
||||||
|
# Set the visibility of buttons
|
||||||
|
btn_postpone.set_visible(not self.strict_break)
|
||||||
|
btn_skip.set_visible(not self.strict_break)
|
||||||
|
|
||||||
|
window.present()
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Update the countdown on all break screens.
|
Update the countdown on all break screens.
|
||||||
|
|
|
@ -78,12 +78,14 @@ class SafeEyesCore:
|
||||||
|
|
||||||
break_time = short_break_config.get('time', self.short_break_duration)
|
break_time = short_break_config.get('time', self.short_break_duration)
|
||||||
audible_alert = short_break_config.get('audible_alert', config['audible_alert'])
|
audible_alert = short_break_config.get('audible_alert', config['audible_alert'])
|
||||||
|
image = short_break_config.get('image')
|
||||||
|
|
||||||
# Validate time value
|
# Validate time value
|
||||||
if not isinstance(break_time, int) or break_time <= 0:
|
if not isinstance(break_time, int) or break_time <= 0:
|
||||||
logging.error('Invalid time in short break: ' + str(short_break_config))
|
logging.error('Invalid time in short break: ' + str(short_break_config))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self.short_break_exercises.append([name, break_time, audible_alert])
|
self.short_break_exercises.append([name, break_time, audible_alert, image])
|
||||||
|
|
||||||
for long_break_config in config['long_breaks']:
|
for long_break_config in config['long_breaks']:
|
||||||
exercise_name = long_break_config['name']
|
exercise_name = long_break_config['name']
|
||||||
|
@ -96,13 +98,14 @@ class SafeEyesCore:
|
||||||
|
|
||||||
break_time = long_break_config.get('time', self.long_break_duration)
|
break_time = long_break_config.get('time', self.long_break_duration)
|
||||||
audible_alert = long_break_config.get('audible_alert', config['audible_alert'])
|
audible_alert = long_break_config.get('audible_alert', config['audible_alert'])
|
||||||
|
image = long_break_config.get('image')
|
||||||
|
|
||||||
# Validate time value
|
# Validate time value
|
||||||
if not isinstance(break_time, int) or break_time <= 0:
|
if not isinstance(break_time, int) or break_time <= 0:
|
||||||
logging.error('Invalid time in long break: ' + str(long_break_config))
|
logging.error('Invalid time in long break: ' + str(long_break_config))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self.long_break_exercises.append([name, break_time, audible_alert])
|
self.long_break_exercises.append([name, break_time, audible_alert, image])
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -270,6 +273,7 @@ class SafeEyesCore:
|
||||||
# User can disable SafeEyes during notification
|
# User can disable SafeEyes during notification
|
||||||
if self.__is_running():
|
if self.__is_running():
|
||||||
message = ""
|
message = ""
|
||||||
|
image = None
|
||||||
seconds = 0
|
seconds = 0
|
||||||
audible_alert = None
|
audible_alert = None
|
||||||
if self.__is_long_break():
|
if self.__is_long_break():
|
||||||
|
@ -278,15 +282,17 @@ class SafeEyesCore:
|
||||||
message = self.long_break_exercises[self.long_break_message_index][0]
|
message = self.long_break_exercises[self.long_break_message_index][0]
|
||||||
seconds = self.long_break_exercises[self.long_break_message_index][1]
|
seconds = self.long_break_exercises[self.long_break_message_index][1]
|
||||||
audible_alert = self.long_break_exercises[self.long_break_message_index][2]
|
audible_alert = self.long_break_exercises[self.long_break_message_index][2]
|
||||||
|
image = self.long_break_exercises[self.long_break_message_index][3]
|
||||||
else:
|
else:
|
||||||
logging.info("Count is {}; get a short beak message".format(self.break_count))
|
logging.info("Count is {}; get a short beak message".format(self.break_count))
|
||||||
self.short_break_message_index = (self.short_break_message_index + 1) % len(self.short_break_exercises)
|
self.short_break_message_index = (self.short_break_message_index + 1) % len(self.short_break_exercises)
|
||||||
message = self.short_break_exercises[self.short_break_message_index][0]
|
message = self.short_break_exercises[self.short_break_message_index][0]
|
||||||
seconds = self.short_break_exercises[self.short_break_message_index][1]
|
seconds = self.short_break_exercises[self.short_break_message_index][1]
|
||||||
audible_alert = self.short_break_exercises[self.short_break_message_index][2]
|
audible_alert = self.short_break_exercises[self.short_break_message_index][2]
|
||||||
|
image = self.short_break_exercises[self.short_break_message_index][3]
|
||||||
|
|
||||||
# Show the break screen
|
# Show the break screen
|
||||||
self.start_break(message)
|
self.start_break(message, image)
|
||||||
|
|
||||||
# Use self.active instead of self.__is_running to avoid idle pause interrupting the break
|
# Use self.active instead of self.__is_running to avoid idle pause interrupting the break
|
||||||
while seconds and self.active and not self.skipped and not self.postponed:
|
while seconds and self.active and not self.skipped and not self.postponed:
|
||||||
|
|
|
@ -25,9 +25,10 @@ import pyaudio, wave
|
||||||
bin_directory = os.path.dirname(os.path.realpath(__file__))
|
bin_directory = os.path.dirname(os.path.realpath(__file__))
|
||||||
home_directory = os.path.expanduser('~')
|
home_directory = os.path.expanduser('~')
|
||||||
system_language_directory = os.path.join(bin_directory, "config/lang")
|
system_language_directory = os.path.join(bin_directory, "config/lang")
|
||||||
|
config_directory = os.path.join(home_directory, '.config/safeeyes')
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Play the alert.mp3
|
Play the alert.wav
|
||||||
"""
|
"""
|
||||||
def play_notification():
|
def play_notification():
|
||||||
logging.info("Playing audible alert")
|
logging.info("Playing audible alert")
|
||||||
|
@ -35,7 +36,9 @@ def play_notification():
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Open the sound file
|
# Open the sound file
|
||||||
path = os.path.join(bin_directory, 'resource','alert.wav')
|
path = get_resource_path('alert.wav')
|
||||||
|
if path is None:
|
||||||
|
return
|
||||||
sound = wave.open(path, 'rb')
|
sound = wave.open(path, 'rb')
|
||||||
|
|
||||||
# Create a sound stream
|
# Create a sound stream
|
||||||
|
@ -61,6 +64,23 @@ def play_notification():
|
||||||
logging.warning('Unable to play audible alert')
|
logging.warning('Unable to play audible alert')
|
||||||
logging.exception(e)
|
logging.exception(e)
|
||||||
|
|
||||||
|
"""
|
||||||
|
Return the user-defined resource if a system resource is overridden by the user.
|
||||||
|
Otherwise, return the system resource. Return None if the specified resource does not exist.
|
||||||
|
"""
|
||||||
|
def get_resource_path(resource_name):
|
||||||
|
if resource_name is None:
|
||||||
|
return None
|
||||||
|
resource_location = os.path.join(config_directory, 'resource', resource_name)
|
||||||
|
if not os.path.isfile(resource_location):
|
||||||
|
resource_location = os.path.join(bin_directory, 'resource', resource_name)
|
||||||
|
if not os.path.isfile(resource_location):
|
||||||
|
logging.error('Resource not found: ' + resource_name)
|
||||||
|
resource_location = None
|
||||||
|
|
||||||
|
return resource_location
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Get system idle time in minutes.
|
Get system idle time in minutes.
|
||||||
Return the idle time if xprintidle is available, otherwise return 0.
|
Return the idle time if xprintidle is available, otherwise return 0.
|
||||||
|
@ -97,7 +117,10 @@ def execute_main_thread(target_function, args=None):
|
||||||
def is_active_window_skipped(skip_break_window_classes, take_break_window_classes, unfullscreen_allowed=False):
|
def is_active_window_skipped(skip_break_window_classes, take_break_window_classes, unfullscreen_allowed=False):
|
||||||
logging.info("Searching for full-screen application")
|
logging.info("Searching for full-screen application")
|
||||||
screen = Gdk.Screen.get_default()
|
screen = Gdk.Screen.get_default()
|
||||||
active_xid = str(screen.get_active_window().get_xid())
|
|
||||||
|
active_window = screen.get_active_window()
|
||||||
|
if active_window:
|
||||||
|
active_xid = str(active_window.get_xid())
|
||||||
cmdlist = ['xprop', '-root', '-notype','-id',active_xid, 'WM_CLASS', '_NET_WM_STATE']
|
cmdlist = ['xprop', '-root', '-notype','-id',active_xid, 'WM_CLASS', '_NET_WM_STATE']
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -117,7 +140,7 @@ def is_active_window_skipped(skip_break_window_classes, take_break_window_classe
|
||||||
elif process in take_break_window_classes:
|
elif process in take_break_window_classes:
|
||||||
if is_fullscreen and unfullscreen_allowed:
|
if is_fullscreen and unfullscreen_allowed:
|
||||||
try:
|
try:
|
||||||
screen.get_active_window().unfullscreen()
|
active_window.unfullscreen()
|
||||||
except:
|
except:
|
||||||
logging.error('Error in unfullscreen the window ' + process)
|
logging.error('Error in unfullscreen the window ' + process)
|
||||||
pass
|
pass
|
||||||
|
@ -125,6 +148,8 @@ def is_active_window_skipped(skip_break_window_classes, take_break_window_classe
|
||||||
|
|
||||||
return is_fullscreen
|
return is_fullscreen
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Return the system locale. If not available, return en_US.UTF-8.
|
Return the system locale. If not available, return en_US.UTF-8.
|
||||||
|
|
|
@ -43,7 +43,7 @@ system_style_sheet_path = os.path.join(Utility.bin_directory, "config/style/safe
|
||||||
|
|
||||||
is_active = True
|
is_active = True
|
||||||
CONFIGURATION_VERSION = 4
|
CONFIGURATION_VERSION = 4
|
||||||
SAFE_EYES_VERSION = "1.1.8"
|
SAFE_EYES_VERSION = "1.2.0"
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Listen to tray icon Settings action and send the signal to Settings dialog.
|
Listen to tray icon Settings action and send the signal to Settings dialog.
|
||||||
|
@ -72,10 +72,10 @@ def show_notification():
|
||||||
"""
|
"""
|
||||||
Receive the break signal from core and pass it to the break screen.
|
Receive the break signal from core and pass it to the break screen.
|
||||||
"""
|
"""
|
||||||
def show_alert(message):
|
def show_alert(message, image_name):
|
||||||
logging.info("Show the break screen")
|
logging.info("Show the break screen")
|
||||||
notification.close()
|
notification.close()
|
||||||
break_screen.show_message(message)
|
break_screen.show_message(message, Utility.get_resource_path(image_name))
|
||||||
if config['strict_break'] and is_active:
|
if config['strict_break'] and is_active:
|
||||||
Utility.execute_main_thread(tray_icon.unlock_menu)
|
Utility.execute_main_thread(tray_icon.unlock_menu)
|
||||||
|
|
||||||
|
@ -258,7 +258,7 @@ def running():
|
||||||
try:
|
try:
|
||||||
# Check if safeeyes is in process arguments
|
# Check if safeeyes is in process arguments
|
||||||
cmd_line = proc.cmdline()
|
cmd_line = proc.cmdline()
|
||||||
if 'python2' == cmd_line[0] and 'safeeyes' in cmd_line[1]:
|
if 'python3' == cmd_line[0] and 'safeeyes' in cmd_line[1]:
|
||||||
process_count += 1
|
process_count += 1
|
||||||
if process_count > 1:
|
if process_count > 1:
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -40,33 +40,42 @@
|
||||||
],
|
],
|
||||||
"short_breaks": [
|
"short_breaks": [
|
||||||
{
|
{
|
||||||
"name": "short_break_close_eyes"
|
"name": "short_break_close_eyes",
|
||||||
|
"image": "short_break_close_eyes.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "short_break_roll_eyes"
|
"name": "short_break_roll_eyes",
|
||||||
|
"image": "short_break_roll_eyes.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "short_break_rotate_clockwise"
|
"name": "short_break_rotate_clockwise",
|
||||||
|
"image": "short_break_rotate_clockwise.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "short_break_rotate_counter_clockwise"
|
"name": "short_break_rotate_counter_clockwise",
|
||||||
|
"image": "short_break_rotate_counter_clockwise.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "short_break_blink"
|
"name": "short_break_blink",
|
||||||
|
"image": "short_break_blink.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "short_break_focus_far_distance"
|
"name": "short_break_focus_far_distance",
|
||||||
|
"image": "short_break_focus_far_distance.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "short_break_drink_water"
|
"name": "short_break_drink_water",
|
||||||
|
"image": "short_break_drink_water.png"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"long_breaks": [
|
"long_breaks": [
|
||||||
{
|
{
|
||||||
"name": "long_break_walk"
|
"name": "long_break_walk",
|
||||||
|
"image": "long_break_walk.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "long_break_lean_back"
|
"name": "long_break_lean_back",
|
||||||
|
"image": "long_break_lean_back.png"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"custom_exercises": {
|
"custom_exercises": {
|
||||||
|
|
|
@ -71,3 +71,9 @@
|
||||||
font-size: 12pt;
|
font-size: 12pt;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.panel_left {
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel_right {
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!-- Generated with glade 3.18.3 -->
|
<!-- Generated with glade 3.18.3 -->
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
~ Safe Eyes is a utility to remind you to take break frequently
|
~ Safe Eyes is a utility to remind you to take break frequently
|
||||||
~ to protect your eyes from eye strain.
|
~ to protect your eyes from eye strain.
|
||||||
|
@ -20,7 +19,6 @@
|
||||||
~ You should have received a copy of the GNU General Public License
|
~ You should have received a copy of the GNU General Public License
|
||||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<interface>
|
<interface>
|
||||||
<requires lib="gtk+" version="3.10"/>
|
<requires lib="gtk+" version="3.10"/>
|
||||||
<object class="GtkWindow" id="window_main">
|
<object class="GtkWindow" id="window_main">
|
||||||
|
@ -33,20 +31,52 @@
|
||||||
<property name="focus_on_map">False</property>
|
<property name="focus_on_map">False</property>
|
||||||
<property name="decorated">False</property>
|
<property name="decorated">False</property>
|
||||||
<property name="deletable">False</property>
|
<property name="deletable">False</property>
|
||||||
|
<property name="gravity">center</property>
|
||||||
<signal name="delete-event" handler="on_window_delete" swapped="no"/>
|
<signal name="delete-event" handler="on_window_delete" swapped="no"/>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox" id="box1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="lbl_left">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="halign">start</property>
|
||||||
|
<property name="valign">start</property>
|
||||||
|
<property name="margin_left">10</property>
|
||||||
|
<property name="margin_top">10</property>
|
||||||
|
<property name="margin_bottom">10</property>
|
||||||
|
<style>
|
||||||
|
<class name="panel_left"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkGrid" id="grid1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="halign">center</property>
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<property name="row_spacing">10</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkGrid" id="grid_parent">
|
<object class="GtkGrid" id="grid_parent">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="halign">center</property>
|
<property name="halign">center</property>
|
||||||
<property name="valign">center</property>
|
<property name="valign">center</property>
|
||||||
<property name="row_spacing">5</property>
|
<property name="hexpand">True</property>
|
||||||
<property name="row_homogeneous">True</property>
|
<property name="row_spacing">15</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkLabel" id="lbl_message">
|
<object class="GtkLabel" id="lbl_message">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="label" translatable="yes">Hello World</property>
|
<property name="label" translatable="yes">Hello World</property>
|
||||||
|
<property name="justify">center</property>
|
||||||
<style>
|
<style>
|
||||||
<class name="lbl_message"/>
|
<class name="lbl_message"/>
|
||||||
</style>
|
</style>
|
||||||
|
@ -149,6 +179,49 @@
|
||||||
<placeholder/>
|
<placeholder/>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">0</property>
|
||||||
|
<property name="top_attach">1</property>
|
||||||
|
<property name="height">3</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkImage" id="img_break">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">0</property>
|
||||||
|
<property name="top_attach">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="lbl_right">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="halign">end</property>
|
||||||
|
<property name="valign">start</property>
|
||||||
|
<property name="margin_right">10</property>
|
||||||
|
<property name="margin_top">10</property>
|
||||||
|
<property name="margin_bottom">10</property>
|
||||||
|
<style>
|
||||||
|
<class name="panel_right"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<style>
|
<style>
|
||||||
<class name="window_main"/>
|
<class name="window_main"/>
|
||||||
|
|
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 975 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.4 KiB |