2017-11-09 19:01:09 +03:00
|
|
|
""" Common module for showing dialogs """
|
2018-03-06 11:34:06 +03:00
|
|
|
import locale
|
2019-05-04 11:21:20 +03:00
|
|
|
import os
|
2017-12-09 16:25:54 +03:00
|
|
|
from enum import Enum
|
|
|
|
|
|
2018-02-18 17:14:02 +03:00
|
|
|
from app.commons import run_idle
|
2018-04-16 18:50:48 +03:00
|
|
|
from .uicommons import Gtk, UI_RESOURCES_PATH, TEXT_DOMAIN
|
2017-11-09 19:01:09 +03:00
|
|
|
|
2019-05-08 23:05:32 +03:00
|
|
|
_IS_GNOME_SESSION = int(bool(os.environ.get("GNOME_DESKTOP_SESSION_ID")))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Button(Enum):
|
|
|
|
|
def __str__(self):
|
|
|
|
|
return self.value
|
|
|
|
|
|
|
|
|
|
OK = """
|
|
|
|
|
<child type="action">
|
|
|
|
|
<object class="GtkButton" id="ok_button">
|
|
|
|
|
<property name="label">gtk-ok</property>
|
|
|
|
|
<property name="visible">True</property>
|
|
|
|
|
<property name="can_focus">True</property>
|
|
|
|
|
<property name="receives_default">True</property>
|
|
|
|
|
<property name="use_stock">True</property>
|
|
|
|
|
<property name="always_show_image">True</property>
|
|
|
|
|
</object>
|
|
|
|
|
</child>
|
|
|
|
|
"""
|
|
|
|
|
CANCEL = """
|
|
|
|
|
<child type="action">
|
|
|
|
|
<object class="GtkButton" id="cancel_button">
|
|
|
|
|
<property name="label">gtk-cancel</property>
|
|
|
|
|
<property name="visible">True</property>
|
|
|
|
|
<property name="can_focus">True</property>
|
|
|
|
|
<property name="receives_default">True</property>
|
|
|
|
|
<property name="use_stock">True</property>
|
|
|
|
|
<property name="always_show_image">True</property>
|
|
|
|
|
</object>
|
|
|
|
|
</child>
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ButtonAction(Enum):
|
|
|
|
|
def __str__(self):
|
|
|
|
|
return self.value
|
|
|
|
|
|
|
|
|
|
CANCEL = '<action-widget response="-6">cancel_button</action-widget>'
|
|
|
|
|
OK = '<action-widget response="-5">ok_button</action-widget>'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Dialog(Enum):
|
|
|
|
|
def __str__(self):
|
|
|
|
|
return self.value
|
|
|
|
|
|
|
|
|
|
INPUT = """
|
|
|
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
|
<interface>
|
|
|
|
|
<requires lib="gtk+" version="3.20"/>
|
|
|
|
|
<object class="GtkDialog" id="input_dialog">
|
|
|
|
|
<property name="use-header-bar">{use_header}</property>
|
|
|
|
|
<property name="default_width">320</property>
|
|
|
|
|
<property name="resizable">False</property>
|
|
|
|
|
<property name="modal">True</property>
|
|
|
|
|
<property name="title" translatable="yes">{title}</property>
|
|
|
|
|
<property name="can_focus">False</property>
|
|
|
|
|
<property name="type_hint">dialog</property>
|
|
|
|
|
{cancel_button}
|
|
|
|
|
{ok_button}
|
|
|
|
|
<child>
|
|
|
|
|
<placeholder/>
|
|
|
|
|
</child>
|
|
|
|
|
<child internal-child="vbox">
|
|
|
|
|
<object class="GtkBox">
|
|
|
|
|
<property name="can_focus">False</property>
|
|
|
|
|
<property name="orientation">vertical</property>
|
|
|
|
|
<property name="spacing">2</property>
|
|
|
|
|
<child>
|
|
|
|
|
<object class="GtkEntry" id="input_entry">
|
|
|
|
|
<property name="visible">True</property>
|
|
|
|
|
<property name="can_focus">True</property>
|
|
|
|
|
<property name="primary_icon_stock">gtk-edit</property>
|
|
|
|
|
<property name="primary_icon_activatable">False</property>
|
|
|
|
|
<property name="secondary_icon_activatable">False</property>
|
|
|
|
|
<property name="secondary_icon_sensitive">False</property>
|
|
|
|
|
</object>
|
|
|
|
|
<packing>
|
|
|
|
|
<property name="expand">False</property>
|
|
|
|
|
<property name="fill">True</property>
|
|
|
|
|
<property name="position">1</property>
|
|
|
|
|
</packing>
|
|
|
|
|
</child>
|
|
|
|
|
</object>
|
|
|
|
|
</child>
|
|
|
|
|
<action-widgets>
|
|
|
|
|
{cancel_action}
|
|
|
|
|
{ok_action}
|
|
|
|
|
</action-widgets>
|
|
|
|
|
</object>
|
|
|
|
|
</interface>
|
|
|
|
|
"""
|
2019-05-04 11:21:20 +03:00
|
|
|
|
2017-11-09 19:01:09 +03:00
|
|
|
|
2018-03-11 21:52:10 +03:00
|
|
|
class Action(Enum):
|
|
|
|
|
EDIT = 0
|
|
|
|
|
ADD = 1
|
|
|
|
|
|
|
|
|
|
|
2017-12-09 16:25:54 +03:00
|
|
|
class DialogType(Enum):
|
|
|
|
|
INPUT = "input_dialog"
|
|
|
|
|
CHOOSER = "path_chooser_dialog"
|
|
|
|
|
ERROR = "error_dialog"
|
|
|
|
|
QUESTION = "question_dialog"
|
|
|
|
|
ABOUT = "about_dialog"
|
2018-02-18 17:14:02 +03:00
|
|
|
WAIT = "wait_dialog"
|
2019-05-01 17:19:31 +03:00
|
|
|
INFO = "info_dialog"
|
2018-02-18 17:14:02 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class WaitDialog:
|
2018-04-09 21:28:19 +03:00
|
|
|
def __init__(self, transient, text=None):
|
2018-02-18 17:14:02 +03:00
|
|
|
builder, dialog = get_dialog_from_xml(DialogType.WAIT, transient)
|
|
|
|
|
self._dialog = dialog
|
|
|
|
|
self._dialog.set_transient_for(transient)
|
2018-04-09 21:28:19 +03:00
|
|
|
if text is not None:
|
|
|
|
|
builder.get_object("wait_dialog_label").set_text(text)
|
2018-02-18 17:14:02 +03:00
|
|
|
|
|
|
|
|
def show(self):
|
|
|
|
|
self._dialog.show()
|
|
|
|
|
|
|
|
|
|
@run_idle
|
|
|
|
|
def hide(self):
|
|
|
|
|
self._dialog.hide()
|
2017-12-09 16:25:54 +03:00
|
|
|
|
2018-04-09 21:28:19 +03:00
|
|
|
@run_idle
|
|
|
|
|
def destroy(self):
|
|
|
|
|
self._dialog.destroy()
|
|
|
|
|
|
2017-12-09 16:25:54 +03:00
|
|
|
|
|
|
|
|
def show_dialog(dialog_type: DialogType, transient, text=None, options=None, action_type=None, file_filter=None):
|
2017-11-09 19:01:09 +03:00
|
|
|
""" Shows dialogs by name """
|
2019-05-01 17:19:31 +03:00
|
|
|
if dialog_type is DialogType.INFO:
|
|
|
|
|
return get_info_dialog(transient, text)
|
2019-05-04 11:21:20 +03:00
|
|
|
elif dialog_type is DialogType.CHOOSER and options:
|
|
|
|
|
return get_file_chooser_dialog(transient, text, options, action_type, file_filter)
|
|
|
|
|
elif dialog_type is DialogType.INPUT:
|
|
|
|
|
return get_input_dialog(transient, text)
|
|
|
|
|
else:
|
|
|
|
|
builder, dialog = get_dialog_from_xml(dialog_type, transient)
|
|
|
|
|
if text:
|
|
|
|
|
dialog.set_markup(get_message(text))
|
|
|
|
|
response = dialog.run()
|
|
|
|
|
dialog.destroy()
|
2019-05-01 17:19:31 +03:00
|
|
|
|
2019-05-04 11:21:20 +03:00
|
|
|
return response
|
2017-11-09 19:01:09 +03:00
|
|
|
|
2017-12-30 21:51:57 +03:00
|
|
|
|
2019-05-04 11:21:20 +03:00
|
|
|
def get_chooser_dialog(transient, options, pattern, name):
|
|
|
|
|
file_filter = Gtk.FileFilter()
|
|
|
|
|
file_filter.add_pattern(pattern)
|
|
|
|
|
file_filter.set_name(name)
|
|
|
|
|
|
|
|
|
|
return show_dialog(dialog_type=DialogType.CHOOSER,
|
|
|
|
|
transient=transient,
|
|
|
|
|
options=options,
|
|
|
|
|
action_type=Gtk.FileChooserAction.OPEN,
|
|
|
|
|
file_filter=file_filter)
|
2017-12-09 16:25:54 +03:00
|
|
|
|
|
|
|
|
|
2019-05-04 11:21:20 +03:00
|
|
|
def get_file_chooser_dialog(transient, text, options, action_type, file_filter):
|
|
|
|
|
dialog = Gtk.FileChooserDialog(get_message(text) if text else "", transient,
|
|
|
|
|
action_type if action_type is not None else Gtk.FileChooserAction.SELECT_FOLDER,
|
|
|
|
|
(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK),
|
|
|
|
|
use_header_bar=_IS_GNOME_SESSION)
|
|
|
|
|
if file_filter is not None:
|
|
|
|
|
dialog.add_filter(file_filter)
|
|
|
|
|
|
|
|
|
|
path = options.get("data_dir_path")
|
|
|
|
|
dialog.set_current_folder(path)
|
|
|
|
|
response = dialog.run()
|
|
|
|
|
if response == Gtk.ResponseType.OK:
|
|
|
|
|
if dialog.get_filename():
|
|
|
|
|
path = dialog.get_filename()
|
|
|
|
|
if action_type is not Gtk.FileChooserAction.OPEN:
|
|
|
|
|
path = path + "/"
|
2017-12-09 16:25:54 +03:00
|
|
|
response = path
|
2019-05-04 11:21:20 +03:00
|
|
|
dialog.destroy()
|
2017-12-09 16:25:54 +03:00
|
|
|
|
2019-05-04 11:21:20 +03:00
|
|
|
return response
|
2017-11-09 19:01:09 +03:00
|
|
|
|
2017-12-09 16:25:54 +03:00
|
|
|
|
2019-05-04 11:21:20 +03:00
|
|
|
def get_info_dialog(transient, text):
|
|
|
|
|
dialog = Gtk.MessageDialog(text=get_message(text),
|
|
|
|
|
parent=transient,
|
|
|
|
|
type=Gtk.MessageType.INFO,
|
|
|
|
|
buttons=Gtk.ButtonsType.OK,
|
|
|
|
|
use_header_bar=_IS_GNOME_SESSION)
|
|
|
|
|
dialog.run()
|
|
|
|
|
dialog.destroy()
|
2017-11-09 19:01:09 +03:00
|
|
|
|
2019-05-04 11:21:20 +03:00
|
|
|
|
|
|
|
|
def get_input_dialog(transient, text):
|
2019-05-08 23:05:32 +03:00
|
|
|
builder = Gtk.Builder()
|
|
|
|
|
builder.add_from_string(Dialog.INPUT.format(use_header=_IS_GNOME_SESSION, title="",
|
|
|
|
|
ok_button=Button.OK, cancel_button=Button.CANCEL,
|
|
|
|
|
cancel_action=ButtonAction.CANCEL, ok_action=ButtonAction.OK))
|
|
|
|
|
dialog = builder.get_object("input_dialog")
|
|
|
|
|
dialog.set_transient_for(transient)
|
2019-05-04 11:21:20 +03:00
|
|
|
entry = builder.get_object("input_entry")
|
|
|
|
|
entry.set_text(text if text else "")
|
2017-11-09 19:01:09 +03:00
|
|
|
response = dialog.run()
|
2019-05-04 11:21:20 +03:00
|
|
|
txt = entry.get_text()
|
2018-03-13 10:42:56 +03:00
|
|
|
dialog.destroy()
|
2017-11-09 19:01:09 +03:00
|
|
|
|
2019-05-04 11:21:20 +03:00
|
|
|
return txt if response == Gtk.ResponseType.OK else Gtk.ResponseType.CANCEL
|
2017-11-09 19:01:09 +03:00
|
|
|
|
|
|
|
|
|
2018-02-18 17:14:02 +03:00
|
|
|
def get_dialog_from_xml(dialog_type, transient):
|
|
|
|
|
builder = Gtk.Builder()
|
2018-03-02 17:06:53 +03:00
|
|
|
builder.set_translation_domain(TEXT_DOMAIN)
|
2018-03-13 10:42:56 +03:00
|
|
|
builder.add_objects_from_file(UI_RESOURCES_PATH + "dialogs.glade", (dialog_type.value,))
|
2018-02-18 17:14:02 +03:00
|
|
|
dialog = builder.get_object(dialog_type.value)
|
|
|
|
|
dialog.set_transient_for(transient)
|
2018-03-13 10:42:56 +03:00
|
|
|
|
2018-02-18 17:14:02 +03:00
|
|
|
return builder, dialog
|
|
|
|
|
|
|
|
|
|
|
2018-03-06 11:34:06 +03:00
|
|
|
def get_message(message):
|
|
|
|
|
""" returns translated message """
|
|
|
|
|
return locale.dgettext(TEXT_DOMAIN, message)
|
|
|
|
|
|
|
|
|
|
|
2017-11-09 19:01:09 +03:00
|
|
|
if __name__ == "__main__":
|
|
|
|
|
pass
|