Commit 74b815b0 authored by Philipp Hörist's avatar Philipp Hörist

Add base Assistant class

parent 06844f23
Pipeline #4659 passed with stages
in 6 minutes and 7 seconds
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkGrid" id="main_grid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="row_spacing">6</property>
<child>
<object class="GtkBox" id="content_area">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkStack" id="stack">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<signal name="notify::visible-child-name" handler="_on_visible_child_name" swapped="no"/>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="action_area">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">12</property>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<style>
<class name="assistant-grid"/>
</style>
</object>
</interface>
......@@ -273,4 +273,7 @@ button.flat.link { padding: 0; border: 0; }
.gajim-scrolled { border: 1px solid; border-color:@unfocused_borders; }
#GroupchatJoin > box {padding: 18px; }
\ No newline at end of file
#GroupchatJoin > box {padding: 18px; }
.assistant-grid { padding: 18px; margin: 6px;}
.assistant-grid > box stack { padding: 18px; }
# This file is part of Gajim.
#
# Gajim is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published
# by the Free Software Foundation; version 3 only.
#
# Gajim 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
from gi.repository import Gdk
from gi.repository import Gtk
from gi.repository import Gio
from gi.repository import GObject
from gajim.gtk.util import get_builder
from gajim.gtk.util import EventHelper
class Assistant(Gtk.ApplicationWindow, EventHelper):
__gsignals__ = dict(
button_clicked=(
GObject.SignalFlags.RUN_LAST | GObject.SignalFlags.ACTION,
None,
(str, )
),
page_changed=(
GObject.SignalFlags.RUN_LAST | GObject.SignalFlags.ACTION,
None,
(str, )
))
def __init__(self, transient_for=None,
width=550,
height=400,
transition_duration=200):
Gtk.ApplicationWindow.__init__(self)
EventHelper.__init__(self)
self.set_application(Gio.Application.get_default())
self.set_position(Gtk.WindowPosition.CENTER)
self.set_show_menubar(False)
self.set_name('Assistant')
self.set_default_size(width, height)
self.set_resizable(True)
self.set_transient_for(transient_for)
self._pages = {}
self._buttons = {}
self._button_visible_func = None
self._ui = get_builder('assistant.ui')
self.add(self._ui.main_grid)
self._ui.stack.set_transition_duration(transition_duration)
self.connect('key-press-event', self._on_key_press_event)
self.connect('destroy', self.__on_destroy)
self._ui.connect_signals(self)
def show_all(self):
page_name = self._ui.stack.get_visible_child_name()
buttons = self._button_visible_func(self, page_name)
self._set_buttons_visible(buttons)
self.emit('page-changed', page_name)
Gtk.ApplicationWindow.show_all(self)
def _on_key_press_event(self, _widget, event):
if event.keyval == Gdk.KEY_Escape:
self.destroy()
def set_button_visible_func(self, func):
self._button_visible_func = func
def set_default_button(self, button_name):
self._buttons[button_name].grab_default()
def add_button(self, name, label, css_class=None):
button = Gtk.Button(label=label,
can_default=True,
no_show_all=True)
button.connect('clicked', self.__on_button_clicked)
if css_class is not None:
button.get_style_context().add_class(css_class)
self._buttons[name] = button
self._ui.action_area.pack_end(button, False, False, 0)
def add_pages(self, pages):
self._pages = pages
for name, widget in pages.items():
self._ui.stack.add_named(widget, name)
def add_default_page(self, name):
if name == 'success':
page = SuccessPage()
elif name == 'error':
page = ErrorPage()
else:
raise ValueError('Unknown page: %s' % name)
self._pages[name] = page
self._ui.stack.add_named(page, name)
def get_current_page(self):
return self._ui.stack.get_visible_child_name()
def show_page(self, name, transition=Gtk.StackTransitionType.NONE):
buttons = self._button_visible_func(self, name)
self._set_buttons_visible(buttons)
self._ui.stack.set_visible_child_full(name, transition)
def get_error_page(self):
return self._pages['error']
def get_success_page(self):
return self._pages['success']
def _set_buttons_visible(self, buttons):
for button in self._buttons.values():
button.hide()
if buttons is None:
return
for button_name in buttons:
self._buttons[button_name].show()
def _on_visible_child_name(self, stack, _param):
self.set_title(stack.get_visible_child().title)
self.emit('page-changed', stack.get_visible_child_name())
def __on_button_clicked(self, button):
for button_name, button_ in self._buttons.items():
if button_ == button:
self.emit('button-clicked', button_name)
return
def __on_destroy(self, *args):
self._pages.clear()
self._buttons.clear()
class Page(Gtk.Box):
def __init__(self, icon_name, icon_css_class):
super().__init__(orientation=Gtk.Orientation.VERTICAL)
self.set_spacing(18)
self.set_valign(Gtk.Align.CENTER)
self.title = ''
self._heading = Gtk.Label()
self._heading.get_style_context().add_class('large-header')
self._heading.set_max_width_chars(30)
self._heading.set_line_wrap(True)
self._heading.set_halign(Gtk.Align.CENTER)
self._heading.set_justify(Gtk.Justification.CENTER)
icon = Gtk.Image.new_from_icon_name(icon_name, Gtk.IconSize.DIALOG)
icon.get_style_context().add_class(icon_css_class)
self._label = Gtk.Label()
self._label.set_max_width_chars(50)
self._label.set_line_wrap(True)
self._label.set_halign(Gtk.Align.CENTER)
self._label.set_justify(Gtk.Justification.CENTER)
self.pack_start(self._heading, False, True, 0)
self.pack_start(icon, False, True, 0)
self.pack_start(self._label, False, True, 0)
self.show_all()
def set_heading(self, heading):
self._heading.set_text(heading)
def set_text(self, text):
self._label.set_text(text)
def set_title(self, title):
self.title = title
class ErrorPage(Page):
def __init__(self):
Page.__init__(self,
icon_name='dialog-error-symbolic',
icon_css_class='error-color')
class SuccessPage(Page):
def __init__(self):
Page.__init__(self,
icon_name='object-select-symbolic',
icon_css_class='success-color')
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gajim.common.const import CSSPriority
from gajim.gtk.assistant import Assistant
from test.gtk import util
util.load_style('gajim.css', CSSPriority.APPLICATION)
class TestAssistant(Assistant):
def __init__(self):
Assistant.__init__(self)
self.add_pages({'start': Start(),
'progress': Progress()})
self.add_default_page('error')
self.add_default_page('success')
self.add_button('forward', 'Forward', 'suggested-action')
self.add_button('close', 'Close', 'destructive-action')
self.add_button('back', 'Back')
self.set_button_visible_func(self._visible_func)
self.connect('button-clicked', self._on_button_clicked)
self.connect('page-changed', self._on_page_changed)
self.show_all()
@staticmethod
def _visible_func(_assistant, page_name):
if page_name == 'start':
return ['forward']
if page_name == 'progress':
return ['forward', 'back']
if page_name == 'success':
return ['forward', 'back']
if page_name == 'error':
return ['back', 'close']
raise ValueError('page %s unknown' % page_name)
def _on_button_clicked(self, _assistant, button_name):
page = self.get_current_page()
if button_name == 'forward':
if page == 'start':
self.show_page('progress', Gtk.StackTransitionType.SLIDE_LEFT)
elif page == 'progress':
self.show_page('success', Gtk.StackTransitionType.SLIDE_LEFT)
elif page == 'success':
self.show_page('error', Gtk.StackTransitionType.SLIDE_LEFT)
return
if button_name == 'back':
if page == 'progress':
self.show_page('start')
if page == 'success':
self.show_page('progress')
if page == 'error':
self.show_page('success')
return
if button_name == 'close':
self.destroy()
def _on_page_changed(self, _assistant, page_name):
if page_name == 'start':
self.set_default_button('forward')
elif page_name == 'progress':
self.set_default_button('forward')
elif page_name == 'success':
success_page = self.get_success_page()
success_page.set_title('Success')
success_page.set_heading('Success Heading')
success_page.set_text('This is the success text')
self.set_default_button('forward')
elif page_name == 'error':
error_page = self.get_error_page()
error_page.set_title('Error')
error_page.set_heading('Error Heading')
error_page.set_text('This is the error text')
self.set_default_button('back')
class Progress(Gtk.Box):
title = 'Progress'
def __init__(self):
super().__init__(orientation=Gtk.Orientation.VERTICAL)
self.set_spacing(18)
self.set_valign(Gtk.Align.CENTER)
label = Gtk.Label(label='Test label...')
label.set_max_width_chars(50)
label.set_line_wrap(True)
label.set_halign(Gtk.Align.CENTER)
label.set_justify(Gtk.Justification.CENTER)
spinner = Gtk.Spinner()
self.pack_start(label, False, True, 0)
self.pack_start(spinner, False, True, 0)
spinner.start()
self.show_all()
class Start(Gtk.Box):
title = 'Start'
def __init__(self):
super().__init__(orientation=Gtk.Orientation.VERTICAL)
self.set_spacing(18)
self.set_valign(Gtk.Align.CENTER)
heading = Gtk.Label(label='Test Assistant')
heading.get_style_context().add_class('large-header')
label1 = Gtk.Label(label='This is label 1 with some text')
label1.set_max_width_chars(50)
label1.set_line_wrap(True)
label1.set_halign(Gtk.Align.CENTER)
label1.set_justify(Gtk.Justification.CENTER)
label1.set_margin_bottom(24)
label2 = Gtk.Label(label='This is label 2 with some more text')
label2.set_max_width_chars(50)
label2.set_line_wrap(True)
label2.set_halign(Gtk.Align.CENTER)
label2.set_justify(Gtk.Justification.CENTER)
self._server = Gtk.CheckButton.new_with_mnemonic('A fancy checkbox')
self._server.set_halign(Gtk.Align.CENTER)
self.pack_start(heading, False, True, 0)
self.pack_start(label1, False, True, 0)
self.pack_start(label2, False, True, 0)
self.pack_start(self._server, False, True, 0)
self.show_all()
win = TestAssistant()
win.connect('destroy', Gtk.main_quit)
win.show_all()
Gtk.main()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment