rui 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,350 @@
1
+ # Copyright (c) 2009-2010 Paolo Capriotti <p.capriotti@gmail.com>
2
+ #
3
+ # This library is free software; you can redistribute it and/or modify
4
+ # it under the terms of the GNU Lesser General Public License as
5
+ # published by the Free Software Foundation; either version 3 of the
6
+ # License, or (at your option) any later version.
7
+
8
+ require 'rui/toolkits/qtbase/qt'
9
+
10
+ module KDE
11
+ def self.ki18n(str)
12
+ str
13
+ end
14
+
15
+ def self.i18n(str)
16
+ str
17
+ end
18
+
19
+ def self.i18nc(context, str)
20
+ str
21
+ end
22
+
23
+ def self.active_color
24
+ $qApp.palette.color(Qt::Palette::Highlight)
25
+ end
26
+
27
+ def self.std_shortcut(name)
28
+ code = Qt::KeySequence.send(name.to_s.capitalize)
29
+ Qt::KeySequence.new(code)
30
+ end
31
+ end
32
+
33
+ class Qt::UrlRequester < Qt::LineEdit
34
+ def url=(val)
35
+ self.text = val.to_string
36
+ end
37
+
38
+ def url
39
+ Qt::Url.new(text)
40
+ end
41
+ end
42
+
43
+ class Qt::MainWindow
44
+ attr_reader :guis
45
+
46
+ def initialize(parent)
47
+ super(parent)
48
+
49
+ setToolButtonStyle(Qt::ToolButtonFollowStyle)
50
+
51
+ # create basic GUI
52
+ @guis = []
53
+ @gui = Qt::gui(:qt_base) do |g|
54
+ g.menu_bar do |mb|
55
+ mb.merge_point
56
+ mb.menu(:settings, :text => KDE::i18n("&Settings"))
57
+ mb.menu(:help, :text => KDE::i18n("&Help")) do |m|
58
+ m.action :about
59
+ m.action :about_qt
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ def setGUI(gui)
66
+ regular_action(:about, :text => KDE::i18n("&About")) do
67
+ Qt::MessageBox.about(nil,
68
+ $qApp.data[:name],
69
+ [$qApp.data[:description],
70
+ $qApp.data[:copyright]].join("\n"))
71
+ end
72
+ regular_action(:about_qt, :text => KDE::i18n("About &Qt")) { $qApp.about_qt }
73
+
74
+ @gui.merge!(gui)
75
+ @guis.each {|g| @gui.merge! g }
76
+ RUI::GuiBuilder.build(self, @gui)
77
+
78
+ # restore state
79
+ settings = Qt::Settings.new
80
+ state = nil
81
+ geometry = nil
82
+ if settings.contains("mainwindow/state")
83
+ state = settings.value("mainwindow/state").toByteArray
84
+ geometry = settings.value("mainwindow/geometry").toByteArray
85
+ restore_geometry(geometry)
86
+ restore_state(state)
87
+ end
88
+ end
89
+
90
+ def saveGUI
91
+ settings = Qt::Settings.new
92
+ settings.begin_group("mainwindow")
93
+ settings.set_value("geometry", Qt::Variant.new(save_geometry))
94
+ settings.set_value("state", Qt::Variant.new(save_state))
95
+ settings.end_group
96
+ settings.sync
97
+ end
98
+
99
+ def caption=(title)
100
+ self.window_title = $qApp.application_name.capitalize +
101
+ " - " + title
102
+ end
103
+ end
104
+
105
+ class Qt::Dialog
106
+ include Layoutable
107
+
108
+ def setGUI(gui)
109
+ self.window_title = gui.opts[:caption]
110
+ layout = Qt::VBoxLayout.new(self)
111
+ widget = Qt::Widget.new(self)
112
+ widget.owner = self
113
+ widget.setGUI(gui)
114
+ buttons = Qt::DialogButtonBox.new
115
+ buttons.add_button(Qt::DialogButtonBox::Ok)
116
+ buttons.add_button(Qt::DialogButtonBox::Cancel)
117
+ layout.add_widget(widget)
118
+ layout.add_widget(buttons)
119
+
120
+ buttons.on(:accepted) { fire :ok_clicked; accept }
121
+ buttons.on(:rejected) { reject }
122
+ end
123
+ end
124
+
125
+ class Qt::XMLGUIClient < Qt::Object
126
+ def setGUI(gui)
127
+ parent.guis << gui
128
+ end
129
+ end
130
+
131
+ module ActionHandler
132
+ def action_collection
133
+ @action_collection ||= { }
134
+ end
135
+
136
+ def action_list_entries
137
+ @action_list_entries ||= Hash.new {|h, x| h[x] = [] }
138
+ end
139
+
140
+ def plug_action_list(name, actions)
141
+ action_list_entries[name].each do |entry|
142
+ actions.each do |action|
143
+ puts "adding action to #{entry.parent}: #{action.text}"
144
+ entry.add_action(action)
145
+ end
146
+ end
147
+ end
148
+
149
+ def unplug_action_list(name)
150
+ action_list_entries[name].each do |entry|
151
+ entry.clear
152
+ end
153
+ end
154
+
155
+ def add_action(name, a)
156
+ action_parent.action_collection[name] = a
157
+ end
158
+
159
+ def std_action(name, &blk)
160
+ text, icon_name = Qt::STD_ACTIONS[name]
161
+ if text
162
+ icon = Qt::Icon.from_theme(icon_name)
163
+ a = Qt::Action.new(icon, text, action_parent)
164
+ add_action(name, a)
165
+ a.on(:triggered, &blk)
166
+ a
167
+ end
168
+ end
169
+
170
+ def regular_action(name, opts = { }, &blk)
171
+ a = Qt::Action.new(opts[:text], action_parent)
172
+ add_action(name, a)
173
+ a.on(:triggered, &blk)
174
+ if (opts[:icon])
175
+ a.icon = Qt::Icon.from_theme(opts[:icon])
176
+ end
177
+ a.shortcut = opts[:shortcut] if opts[:shortcut]
178
+ a.tool_tip = opts[:tooltip] if opts[:tooltip]
179
+ a
180
+ end
181
+
182
+ def action_parent
183
+ self
184
+ end
185
+ end
186
+
187
+ module Qt
188
+ STD_ACTIONS = {
189
+ :undo => [KDE::i18n("&Undo"), 'edit-undo'],
190
+ :redo => [KDE::i18n("&Redo"), 'edit-redo']
191
+ }
192
+
193
+ def self.gui(name, opts = { }, &blk)
194
+ self.autogui(name, opts, &blk)
195
+ end
196
+ end
197
+
198
+ class Qt::Application
199
+ attr_accessor :data
200
+
201
+ def self.init(data)
202
+ app = new(ARGV)
203
+ app.application_name = data[:id]
204
+ app.organization_name = data[:id]
205
+ app.data = data
206
+
207
+ if block_given?
208
+ yield app
209
+ app.exec
210
+ end
211
+ app
212
+ end
213
+ end
214
+
215
+ class KDE::CmdLineArgs
216
+ def self.parsed_args
217
+ new(ARGV)
218
+ end
219
+
220
+ def initialize(args)
221
+ @args = args
222
+ end
223
+
224
+ def [](i)
225
+ @args[i]
226
+ end
227
+
228
+ def count
229
+ @args.size
230
+ end
231
+
232
+ def is_set(name)
233
+ false
234
+ end
235
+ end
236
+
237
+ class KDE::Global
238
+ def self.config
239
+ Qt::Settings::Group.new(Qt::Settings.new, "")
240
+ end
241
+ end
242
+
243
+ class Qt::Settings
244
+ class Group
245
+ def initialize(settings, prefix)
246
+ @settings = settings
247
+ @prefix = prefix
248
+ end
249
+
250
+ def exists
251
+ in_group do
252
+ not @settings.all_keys.empty?
253
+ end
254
+ end
255
+
256
+ def delete_group
257
+ @settings.remove(@prefix)
258
+ end
259
+
260
+ def group(name)
261
+ Group.new(@settings, prefixed(name))
262
+ end
263
+
264
+ def write_entry(key, value)
265
+ @settings.set_value(prefixed(key),
266
+ Qt::Variant.new(value))
267
+ end
268
+
269
+ def read_entry(key, default_value = nil)
270
+ @settings.value(prefixed(key)).toString || default_value
271
+ end
272
+
273
+ def sync
274
+ @settings.sync
275
+ end
276
+
277
+ def group_list
278
+ in_group do
279
+ @settings.child_groups
280
+ end
281
+ end
282
+
283
+ def entry_map
284
+ in_group do
285
+ @settings.child_keys.inject({}) do |res, key|
286
+ res[key] = @settings.value(key).toString
287
+ res
288
+ end
289
+ end
290
+ end
291
+
292
+ def each_group
293
+ names = in_group do
294
+ @settings.child_groups
295
+ end
296
+ names.each do |name|
297
+ yield group(name)
298
+ end
299
+ end
300
+
301
+ def name
302
+ if @prefix =~ /\/([^\/]+)$/
303
+ $1
304
+ else
305
+ @prefix
306
+ end
307
+ end
308
+
309
+ private
310
+
311
+ def prefixed(key)
312
+ if @prefix.empty?
313
+ key
314
+ else
315
+ [@prefix, key].join('/')
316
+ end
317
+ end
318
+
319
+ def in_group
320
+ @settings.begin_group(@prefix)
321
+ result = yield
322
+ @settings.end_group
323
+ result
324
+ end
325
+ end
326
+ end
327
+
328
+ class Qt::TabWidget
329
+ include Layoutable
330
+ end
331
+
332
+ class Qt::Process
333
+ def output_channel_mode=(val)
334
+ case val
335
+ when :only_stdout
336
+ setProcessChannelMode(Qt::Process::SeparateChannels)
337
+ setReadChannel(Qt::Process::StandardOutput)
338
+ else
339
+ raise "Unsupported output mode #{val}"
340
+ end
341
+ end
342
+
343
+ def self.split_args(str)
344
+ str.split(/\s+/)
345
+ end
346
+
347
+ def run(path, args)
348
+ start(path, args)
349
+ end
350
+ end
@@ -0,0 +1,344 @@
1
+ # Copyright (c) 2009-2010 Paolo Capriotti <p.capriotti@gmail.com>
2
+ #
3
+ # This library is free software; you can redistribute it and/or modify
4
+ # it under the terms of the GNU Lesser General Public License as
5
+ # published by the Free Software Foundation; either version 3 of the
6
+ # License, or (at your option) any later version.
7
+
8
+ require 'rui/factory'
9
+
10
+ module RUI
11
+ #
12
+ # Helper module used to interpret a GUI descriptor and build a Qt GUI.
13
+ #
14
+ # Classes in this module correspond to valid descriptor tags.
15
+ #
16
+ module GuiBuilder
17
+ def self.build(window, gui)
18
+ Gui.new.build(window, nil, gui)
19
+ end
20
+
21
+ def build(window, parent, desc)
22
+ element = create_element(window, parent, desc)
23
+ desc.children.each do |child|
24
+ b = builder(child.tag).new
25
+ b.build(window, element, child)
26
+ end
27
+ element
28
+ end
29
+
30
+ def setup_widget(widget, parent, layout, desc)
31
+ layout.add_widget(widget)
32
+ if desc.opts[:name]
33
+ parent.add_accessor(desc.opts[:name], widget)
34
+ end
35
+ end
36
+
37
+ def builder(name)
38
+ GuiBuilder.const_get(name.to_s.capitalize.camelize)
39
+ end
40
+
41
+ #
42
+ # Root tag for a GUI descriptor.
43
+ #
44
+ # Created automatically by {RUI.autogui}.
45
+ #
46
+ class Gui
47
+ include GuiBuilder
48
+ def create_element(window, parent, desc)
49
+ window
50
+ end
51
+ end
52
+
53
+ #
54
+ # Menu bar.
55
+ #
56
+ # This tag must be a child of a gui descriptor.
57
+ #
58
+ class MenuBar
59
+ include GuiBuilder
60
+
61
+ def create_element(window, parent, desc)
62
+ window.menu_bar
63
+ end
64
+ end
65
+
66
+ #
67
+ # A menu.
68
+ #
69
+ # This tag must be a child of a menu_bar descriptor.
70
+ #
71
+ class Menu
72
+ include GuiBuilder
73
+
74
+ def create_element(window, parent, desc)
75
+ menu = Qt::Menu.new(desc.opts[:text].to_s, window)
76
+ parent.add_menu(menu)
77
+ menu
78
+ end
79
+ end
80
+
81
+ #
82
+ # Menu or toolbar action.
83
+ #
84
+ # This tag must be a child of a menu or toolbar descriptor.
85
+ #
86
+ class Action
87
+ include GuiBuilder
88
+
89
+ def create_element(window, parent, desc)
90
+ action = window.action_collection[desc.opts[:name]]
91
+ if action
92
+ parent.add_action(action)
93
+ end
94
+ action
95
+ end
96
+ end
97
+
98
+ #
99
+ # Menu or toolbar separator.
100
+ #
101
+ # This tag must be a child of a menu or toolbar descriptor.
102
+ #
103
+ class Separator
104
+ include GuiBuilder
105
+
106
+ def create_element(window, parent, desc)
107
+ parent.add_separator
108
+ end
109
+ end
110
+
111
+ #
112
+ # A descriptor group.
113
+ #
114
+ # This can be used to affect how merging of descriptor is performed
115
+ # (together with merge points).
116
+ #
117
+ # @see Descriptor
118
+ #
119
+ class Group
120
+ include GuiBuilder
121
+
122
+ def create_element(window, parent, desc)
123
+ parent
124
+ end
125
+ end
126
+
127
+ #
128
+ # An action list is a placeholder for dynamically pluggable actions.
129
+ #
130
+ # Action lists can be plugged by using {ActionHandler#plug_action_list} and
131
+ # removed with {ActionHandler#unplug_action_list}.
132
+ #
133
+ class ActionList
134
+ include GuiBuilder
135
+
136
+ def create_element(window, parent, desc)
137
+ parent
138
+ end
139
+ end
140
+
141
+ #
142
+ # A toolbar.
143
+ #
144
+ # This tag must be a child of a gui descriptor.
145
+ #
146
+ class ToolBar
147
+ include GuiBuilder
148
+
149
+ def create_element(window, parent, desc)
150
+ tb = Qt::ToolBar.new(desc.opts[:text].to_s, parent)
151
+ tb.object_name = desc.opts[:name].to_s
152
+ parent.add_tool_bar(Qt::TopToolBarArea, tb)
153
+ tb
154
+ end
155
+ end
156
+
157
+ #
158
+ # A widget layout.
159
+ #
160
+ # Two orientations are supported: horizontal and vertical. The orientation
161
+ # is controlled by the <tt>type</tt> attribute of this descriptor.
162
+ #
163
+ # A margin can also be specified using the <tt>margin</tt> attribute.
164
+ #
165
+ class Layout
166
+ include GuiBuilder
167
+
168
+ def create_element(window, parent, desc)
169
+ factory = if desc.opts[:type] == :horizontal
170
+ Qt::HBoxLayout
171
+ else
172
+ Qt::VBoxLayout
173
+ end
174
+ layout = factory.new
175
+ layout.margin = desc.opts[:margin] if desc.opts[:margin]
176
+ parent.add_layout(layout)
177
+ layout
178
+ end
179
+ end
180
+
181
+ #
182
+ # A stretch element.
183
+ #
184
+ # Used to separate consecutive elements of a layout.
185
+ #
186
+ class Stretch
187
+ include GuiBuilder
188
+
189
+ def create_element(window, parent, desc)
190
+ parent.add_stretch
191
+ end
192
+ end
193
+
194
+ #
195
+ # A label.
196
+ #
197
+ # The label text is specified by the <tt>text</tt> attribute.
198
+ #
199
+ # A <tt>buddy</tt> attribute can also be specified as a widget id. The widget with
200
+ # the given id will be set as the buddy of this label as GUI construction
201
+ # time.
202
+ #
203
+ class Label
204
+ include GuiBuilder
205
+
206
+ def create_element(window, parent, desc)
207
+ label = Qt::Label.new(desc.opts[:text].to_s, window)
208
+ setup_widget(label, window, parent, desc)
209
+ if desc.opts[:buddy]
210
+ window.buddies[label] = desc.opts[:buddy]
211
+ end
212
+ label
213
+ end
214
+ end
215
+
216
+ #
217
+ # A TabWidget.
218
+ #
219
+ class TabWidget
220
+ include GuiBuilder
221
+
222
+ def create_element(window, parent, desc)
223
+ widget = KDE::TabWidget.new(window)
224
+ setup_widget(widget, window, parent, desc)
225
+ widget.owner = window.owner
226
+ widget
227
+ end
228
+ end
229
+
230
+ #
231
+ # A generic widget.
232
+ #
233
+ # To use this tag, the <tt>factory</tt> descriptor property must be set to
234
+ # the Factory to use to create the widget. The {Factory} class can be
235
+ # useful when the widget to create needs special initialization. Note that
236
+ # the given factory will be invoked passing only the parent widget as a
237
+ # parameter, so any extra parameters must be preset by the factory itself.
238
+ #
239
+ class Widget
240
+ include GuiBuilder
241
+
242
+ def create_element(window, parent, desc)
243
+ widget = factory(desc).new(window)
244
+ setup_widget(widget, window, parent, desc)
245
+ widget
246
+ end
247
+
248
+ def factory(desc)
249
+ desc.opts[:factory]
250
+ end
251
+ end
252
+
253
+ #
254
+ # An individual tab in a tab_widget.
255
+ #
256
+ # This tag must be a child of tab_widget descriptor.
257
+ #
258
+ class Tab
259
+ include GuiBuilder
260
+
261
+ class Helper
262
+ def initialize(parent, text)
263
+ @parent = parent
264
+ @text = text
265
+ end
266
+
267
+ def add_widget(widget)
268
+ @parent.add_tab(widget, @text)
269
+ end
270
+ end
271
+
272
+ def build(window, parent, desc)
273
+ desc.children.each do |child|
274
+ b = builder(child.tag).new
275
+ b.build(parent, Helper.new(parent, desc.opts[:text]), child)
276
+ end
277
+ end
278
+ end
279
+
280
+ #
281
+ # A url requester widget.
282
+ #
283
+ class UrlRequester < Widget
284
+ def factory(desc)
285
+ KDE::UrlRequester
286
+ end
287
+ end
288
+
289
+ #
290
+ # A line edit widget.
291
+ #
292
+ class LineEdit < Widget
293
+ def factory(desc)
294
+ Qt::LineEdit
295
+ end
296
+ end
297
+
298
+ #
299
+ # A combobox.
300
+ #
301
+ class ComboBox < Widget
302
+ def factory(desc)
303
+ KDE::ComboBox
304
+ end
305
+ end
306
+
307
+ #
308
+ # A list widget.
309
+ #
310
+ class List < Widget
311
+ def factory(desc)
312
+ Qt::ListView
313
+ end
314
+ end
315
+
316
+ #
317
+ # A checkbox.
318
+ #
319
+ # The <tt>checked</tt> property specifies whether the checkbox is checked.
320
+ #
321
+ class CheckBox < Widget
322
+ def factory(desc)
323
+ Factory.new do |parent|
324
+ check = Qt::CheckBox.new(parent)
325
+ check.text = desc.opts[:text].to_s
326
+ check.checked = desc.opts[:checked]
327
+ check
328
+ end
329
+ end
330
+ end
331
+
332
+ #
333
+ # A push button.
334
+ #
335
+ class Button < Widget
336
+ def factory(desc)
337
+ Factory.new do |parent|
338
+ KDE::PushButton.new(KDE::Icon.from_theme(desc.opts[:icon]),
339
+ desc.opts[:text], parent)
340
+ end
341
+ end
342
+ end
343
+ end
344
+ end