Add image to break screen
|
@ -97,8 +97,8 @@ class BreakScreen:
|
|||
"""
|
||||
Show the break screen with the given message on all displays.
|
||||
"""
|
||||
def show_message(self, message):
|
||||
GLib.idle_add(lambda: self.__show_break_screen(message))
|
||||
def show_message(self, message, image_path):
|
||||
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.
|
||||
"""
|
||||
def __show_break_screen(self, message):
|
||||
def __show_break_screen(self, message, image_path):
|
||||
# Lock the keyboard
|
||||
thread = threading.Thread(target=self.__lock_keyboard)
|
||||
thread.start()
|
||||
|
@ -138,12 +138,11 @@ class BreakScreen:
|
|||
lbl_count = builder.get_object("lbl_count")
|
||||
btn_skip = builder.get_object("btn_skip")
|
||||
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)
|
||||
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)
|
||||
window.move(x, y)
|
||||
|
||||
self.windows.append(window)
|
||||
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.
|
||||
window.set_visual(window.get_screen().get_rgba_visual())
|
||||
|
||||
window.move(x, y)
|
||||
window.stick()
|
||||
window.set_keep_above(True)
|
||||
window.present()
|
||||
window.set_position(Gtk.WindowPosition.CENTER_ALWAYS)
|
||||
window.resize(monitor_gemoetry.width, monitor_gemoetry.height)
|
||||
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.
|
||||
|
|
|
@ -78,12 +78,14 @@ class SafeEyesCore:
|
|||
|
||||
break_time = short_break_config.get('time', self.short_break_duration)
|
||||
audible_alert = short_break_config.get('audible_alert', config['audible_alert'])
|
||||
image = short_break_config.get('image')
|
||||
|
||||
# Validate time value
|
||||
if not isinstance(break_time, int) or break_time <= 0:
|
||||
logging.error('Invalid time in short break: ' + str(short_break_config))
|
||||
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']:
|
||||
exercise_name = long_break_config['name']
|
||||
|
@ -96,13 +98,14 @@ class SafeEyesCore:
|
|||
|
||||
break_time = long_break_config.get('time', self.long_break_duration)
|
||||
audible_alert = long_break_config.get('audible_alert', config['audible_alert'])
|
||||
image = long_break_config.get('image')
|
||||
|
||||
# Validate time value
|
||||
if not isinstance(break_time, int) or break_time <= 0:
|
||||
logging.error('Invalid time in long break: ' + str(long_break_config))
|
||||
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
|
||||
if self.__is_running():
|
||||
message = ""
|
||||
image = None
|
||||
seconds = 0
|
||||
audible_alert = None
|
||||
if self.__is_long_break():
|
||||
|
@ -278,15 +282,17 @@ class SafeEyesCore:
|
|||
message = self.long_break_exercises[self.long_break_message_index][0]
|
||||
seconds = self.long_break_exercises[self.long_break_message_index][1]
|
||||
audible_alert = self.long_break_exercises[self.long_break_message_index][2]
|
||||
image = self.long_break_exercises[self.long_break_message_index][3]
|
||||
else:
|
||||
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)
|
||||
message = self.short_break_exercises[self.short_break_message_index][0]
|
||||
seconds = self.short_break_exercises[self.short_break_message_index][1]
|
||||
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
|
||||
self.start_break(message)
|
||||
self.start_break(message, image)
|
||||
|
||||
# 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:
|
||||
|
|
|
@ -25,9 +25,10 @@ import pyaudio, wave
|
|||
bin_directory = os.path.dirname(os.path.realpath(__file__))
|
||||
home_directory = os.path.expanduser('~')
|
||||
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():
|
||||
logging.info("Playing audible alert")
|
||||
|
@ -35,7 +36,9 @@ def play_notification():
|
|||
|
||||
try:
|
||||
# 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')
|
||||
|
||||
# Create a sound stream
|
||||
|
@ -61,6 +64,23 @@ def play_notification():
|
|||
logging.warning('Unable to play audible alert')
|
||||
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.
|
||||
Return the idle time if xprintidle is available, otherwise return 0.
|
||||
|
@ -97,33 +117,38 @@ def execute_main_thread(target_function, args=None):
|
|||
def is_active_window_skipped(skip_break_window_classes, take_break_window_classes, unfullscreen_allowed=False):
|
||||
logging.info("Searching for full-screen application")
|
||||
screen = Gdk.Screen.get_default()
|
||||
active_xid = str(screen.get_active_window().get_xid())
|
||||
cmdlist = ['xprop', '-root', '-notype','-id',active_xid, 'WM_CLASS', '_NET_WM_STATE']
|
||||
|
||||
try:
|
||||
stdout = subprocess.check_output(cmdlist).decode('utf-8')
|
||||
except subprocess.CalledProcessError:
|
||||
logging.warning("Error in finding full-screen application")
|
||||
pass
|
||||
else:
|
||||
if stdout:
|
||||
is_fullscreen = 'FULLSCREEN' in stdout
|
||||
# Extract the process name
|
||||
process_names = re.findall('"(.+?)"', stdout)
|
||||
if process_names:
|
||||
process = process_names[1].lower()
|
||||
if process in skip_break_window_classes:
|
||||
return True
|
||||
elif process in take_break_window_classes:
|
||||
if is_fullscreen and unfullscreen_allowed:
|
||||
try:
|
||||
screen.get_active_window().unfullscreen()
|
||||
except:
|
||||
logging.error('Error in unfullscreen the window ' + process)
|
||||
pass
|
||||
return False
|
||||
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']
|
||||
|
||||
return is_fullscreen
|
||||
try:
|
||||
stdout = subprocess.check_output(cmdlist).decode('utf-8')
|
||||
except subprocess.CalledProcessError:
|
||||
logging.warning("Error in finding full-screen application")
|
||||
pass
|
||||
else:
|
||||
if stdout:
|
||||
is_fullscreen = 'FULLSCREEN' in stdout
|
||||
# Extract the process name
|
||||
process_names = re.findall('"(.+?)"', stdout)
|
||||
if process_names:
|
||||
process = process_names[1].lower()
|
||||
if process in skip_break_window_classes:
|
||||
return True
|
||||
elif process in take_break_window_classes:
|
||||
if is_fullscreen and unfullscreen_allowed:
|
||||
try:
|
||||
active_window.unfullscreen()
|
||||
except:
|
||||
logging.error('Error in unfullscreen the window ' + process)
|
||||
pass
|
||||
return False
|
||||
|
||||
return is_fullscreen
|
||||
|
||||
return False
|
||||
|
||||
|
||||
"""
|
||||
|
|
|
@ -43,7 +43,7 @@ system_style_sheet_path = os.path.join(Utility.bin_directory, "config/style/safe
|
|||
|
||||
is_active = True
|
||||
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.
|
||||
|
@ -72,10 +72,10 @@ def show_notification():
|
|||
"""
|
||||
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")
|
||||
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:
|
||||
Utility.execute_main_thread(tray_icon.unlock_menu)
|
||||
|
||||
|
@ -258,7 +258,7 @@ def running():
|
|||
try:
|
||||
# Check if safeeyes is in process arguments
|
||||
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
|
||||
if process_count > 1:
|
||||
return True
|
||||
|
|
|
@ -40,33 +40,42 @@
|
|||
],
|
||||
"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": [
|
||||
{
|
||||
"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": {
|
||||
|
|
|
@ -71,3 +71,9 @@
|
|||
font-size: 12pt;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.panel_left {
|
||||
}
|
||||
|
||||
.panel_right {
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.18.3 -->
|
||||
|
||||
<!--
|
||||
~ Safe Eyes is a utility to remind you to take break frequently
|
||||
~ to protect your eyes from eye strain.
|
||||
|
@ -20,7 +19,6 @@
|
|||
~ You should have received a copy of the GNU General Public License
|
||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.10"/>
|
||||
<object class="GtkWindow" id="window_main">
|
||||
|
@ -33,120 +31,195 @@
|
|||
<property name="focus_on_map">False</property>
|
||||
<property name="decorated">False</property>
|
||||
<property name="deletable">False</property>
|
||||
<property name="gravity">center</property>
|
||||
<signal name="delete-event" handler="on_window_delete" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid_parent">
|
||||
<object class="GtkBox" id="box1">
|
||||
<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">5</property>
|
||||
<property name="row_homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="lbl_message">
|
||||
<object class="GtkLabel" id="lbl_left">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Hello World</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="lbl_message"/>
|
||||
<class name="panel_left"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="width">3</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="yscale">0.20000000298023224</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="lbl_count">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">00</property>
|
||||
<style>
|
||||
<class name="lbl_count"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="box_buttons">
|
||||
<object class="GtkGrid" id="grid1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="spacing">50</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="row_spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="btn_postpone">
|
||||
<property name="label" translatable="yes">Postpone</property>
|
||||
<object class="GtkGrid" id="grid_parent">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<signal name="clicked" handler="on_postpone_clicked" swapped="no"/>
|
||||
<style>
|
||||
<class name="btn_postpone"/>
|
||||
</style>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="row_spacing">15</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="lbl_message">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Hello World</property>
|
||||
<property name="justify">center</property>
|
||||
<style>
|
||||
<class name="lbl_message"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="width">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="alignment_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="yscale">0.20000000298023224</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="lbl_count">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">00</property>
|
||||
<style>
|
||||
<class name="lbl_count"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="box_buttons">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="spacing">50</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="btn_postpone">
|
||||
<property name="label" translatable="yes">Postpone</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="valign">center</property>
|
||||
<signal name="clicked" handler="on_postpone_clicked" swapped="no"/>
|
||||
<style>
|
||||
<class name="btn_postpone"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="btn_skip">
|
||||
<property name="label" translatable="yes">Skip</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="valign">center</property>
|
||||
<signal name="clicked" handler="on_skip_clicked" swapped="no"/>
|
||||
<style>
|
||||
<class name="btn_skip"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="height">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="btn_skip">
|
||||
<property name="label" translatable="yes">Skip</property>
|
||||
<object class="GtkImage" id="img_break">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="valign">center</property>
|
||||
<signal name="clicked" handler="on_skip_clicked" swapped="no"/>
|
||||
<style>
|
||||
<class name="btn_skip"/>
|
||||
</style>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
<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>
|
||||
|
|
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 |