# Copyright (c) 2009-2010 Paolo Capriotti
#
# This library is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 3 of the
# License, or (at your option) any later version.
require 'rui/factory'
module RUI
#
# Helper module used to interpret a GUI descriptor and build a Qt GUI.
#
# Classes in this module correspond to valid descriptor tags.
#
module GuiBuilder
def self.build(window, gui)
Gui.new.build(window, nil, gui)
end
def build(window, parent, desc)
element = create_element(window, parent, desc)
desc.children.each do |child|
b = builder(child.tag).new
b.build(window, element, child)
end
element
end
def setup_widget(widget, parent, layout, desc)
layout.add_widget(widget)
if desc.opts[:name]
parent.add_accessor(desc.opts[:name], widget)
end
end
def builder(name)
GuiBuilder.const_get(name.to_s.capitalize.camelize)
end
#
# Root tag for a GUI descriptor.
#
# Created automatically by {RUI.autogui}.
#
class Gui
include GuiBuilder
def create_element(window, parent, desc)
window
end
end
#
# Menu bar.
#
# This tag must be a child of a gui descriptor.
#
class MenuBar
include GuiBuilder
def create_element(window, parent, desc)
window.menu_bar
end
end
#
# A menu.
#
# This tag must be a child of a menu_bar descriptor.
#
class Menu
include GuiBuilder
def create_element(window, parent, desc)
menu = Qt::Menu.new(desc.opts[:text].to_s, window)
parent.add_menu(menu)
menu
end
end
#
# Menu or toolbar action.
#
# This tag must be a child of a menu or toolbar descriptor.
#
class Action
include GuiBuilder
def create_element(window, parent, desc)
action = window.action_collection[desc.opts[:name]]
if action
parent.add_action(action)
end
action
end
end
#
# Menu or toolbar separator.
#
# This tag must be a child of a menu or toolbar descriptor.
#
class Separator
include GuiBuilder
def create_element(window, parent, desc)
parent.add_separator
end
end
#
# A descriptor group.
#
# This can be used to affect how merging of descriptor is performed
# (together with merge points).
#
# @see Descriptor
#
class Group
include GuiBuilder
def create_element(window, parent, desc)
parent
end
end
#
# An action list is a placeholder for dynamically pluggable actions.
#
# Action lists can be plugged by using {ActionHandler#plug_action_list} and
# removed with {ActionHandler#unplug_action_list}.
#
class ActionList
include GuiBuilder
class Entry
attr_reader :parent
def initialize(parent)
@parent = parent
@actions = []
end
def add_action(action)
@parent.add_action(action)
@actions << action
end
def clear
@actions.each do |action|
action.dispose
end
@actions = []
end
end
def create_element(window, parent, desc)
entry = Entry.new(parent)
window.action_list_entries[desc.opts[:name]] << entry
parent
end
end
#
# A toolbar.
#
# This tag must be a child of a gui descriptor.
#
class ToolBar
include GuiBuilder
def create_element(window, parent, desc)
tb = Qt::ToolBar.new(desc.opts[:text].to_s, parent)
tb.object_name = desc.opts[:name].to_s
parent.add_tool_bar(Qt::TopToolBarArea, tb)
tb
end
end
#
# A widget layout.
#
# Two orientations are supported: horizontal and vertical. The orientation
# is controlled by the type attribute of this descriptor.
#
# A margin can also be specified using the margin attribute.
#
class Layout
include GuiBuilder
def create_element(window, parent, desc)
factory = if desc.opts[:type] == :horizontal
Qt::HBoxLayout
else
Qt::VBoxLayout
end
layout = factory.new
layout.margin = desc.opts[:margin] if desc.opts[:margin]
parent.add_layout(layout)
layout
end
end
#
# A stretch element.
#
# Used to separate consecutive elements of a layout.
#
class Stretch
include GuiBuilder
def create_element(window, parent, desc)
parent.add_stretch
end
end
#
# A label.
#
# The label text is specified by the text attribute.
#
# A buddy attribute can also be specified as a widget id. The widget with
# the given id will be set as the buddy of this label as GUI construction
# time.
#
class Label
include GuiBuilder
def create_element(window, parent, desc)
label = Qt::Label.new(desc.opts[:text].to_s, window)
setup_widget(label, window, parent, desc)
if desc.opts[:buddy]
window.buddies[label] = desc.opts[:buddy]
end
label
end
end
#
# A TabWidget.
#
class TabWidget
include GuiBuilder
def create_element(window, parent, desc)
widget = KDE::TabWidget.new(window)
setup_widget(widget, window, parent, desc)
widget.owner = window.owner
widget
end
end
#
# A generic widget.
#
# To use this tag, the factory descriptor property must be set to
# the Factory to use to create the widget. The {Factory} class can be
# useful when the widget to create needs special initialization. Note that
# the given factory will be invoked passing only the parent widget as a
# parameter, so any extra parameters must be preset by the factory itself.
#
class Widget
include GuiBuilder
def create_element(window, parent, desc)
widget = factory(desc).new(window)
setup_widget(widget, window, parent, desc)
widget
end
def factory(desc)
desc.opts[:factory]
end
end
#
# An individual tab in a tab_widget.
#
# This tag must be a child of tab_widget descriptor.
#
class Tab
include GuiBuilder
class Helper
def initialize(parent, text)
@parent = parent
@text = text
end
def add_widget(widget)
@parent.add_tab(widget, @text)
end
end
def build(window, parent, desc)
desc.children.each do |child|
b = builder(child.tag).new
b.build(parent, Helper.new(parent, desc.opts[:text]), child)
end
end
end
#
# A url requester widget.
#
class UrlRequester < Widget
def factory(desc)
KDE::UrlRequester
end
end
#
# A line edit widget.
#
class LineEdit < Widget
def factory(desc)
Qt::LineEdit
end
end
#
# A combobox.
#
class ComboBox < Widget
def factory(desc)
KDE::ComboBox
end
end
#
# A list widget.
#
class List < Widget
def factory(desc)
Qt::ListView
end
end
#
# A checkbox.
#
# The checked property specifies whether the checkbox is checked.
#
class CheckBox < Widget
def factory(desc)
Factory.new do |parent|
check = Qt::CheckBox.new(parent)
check.text = desc.opts[:text].to_s
check.checked = desc.opts[:checked]
check
end
end
end
#
# A push button.
#
class Button < Widget
def factory(desc)
Factory.new do |parent|
KDE::PushButton.new(KDE::Icon.from_theme(desc.opts[:icon]),
desc.opts[:text], parent)
end
end
end
end
end