diff options
Diffstat (limited to 'korundum/rubylib')
91 files changed, 14252 insertions, 0 deletions
diff --git a/korundum/rubylib/Makefile.am b/korundum/rubylib/Makefile.am new file mode 100644 index 00000000..754d1b00 --- /dev/null +++ b/korundum/rubylib/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = korundum rbkconfig_compiler diff --git a/korundum/rubylib/examples/RubberDoc.rb b/korundum/rubylib/examples/RubberDoc.rb new file mode 100755 index 00000000..604a9492 --- /dev/null +++ b/korundum/rubylib/examples/RubberDoc.rb @@ -0,0 +1,1265 @@ +#!/usr/bin/env ruby + +require 'Korundum' + +about = KDE::AboutData.new("one", "two", "three") +KDE::CmdLineArgs.init(ARGV, about) +app = KDE::Application.new() + +# Qt.debug_level = Qt::DebugLevel::High +# Qt.debug_level = Qt::DebugLevel::Extensive + +# TODO +# improve appearence of sidebar massively +# cut off after certain number of results? +# seperate title from proof of hit? +# when pressing return adjust the current node +# major speed ups for ctrl-n/p +# ... + +DEBUG = false +DEBUG_IDX = false +DEBUG_FAST = true +DEBUG_SEARCH = true +DEBUG_GOTO = false # crashes? + +def time_me str + t1 = Time.now + yield + t2 = Time.now + log "#{str}: #{"%.02f" % (t2 - t1).to_f}s" +end + +module DOMUtils + + def DOMUtils.each_child node + indent = 0 + until node.isNull + yield node + if not node.firstChild.isNull + node = node.firstChild + indent += 1 + elsif not node.nextSibling.isNull + node = node.nextSibling + else + while indent > 0 and !node.isNull and node.nextSibling.isNull + node = node.parentNode + indent -= 1 + end + if not node.isNull + node = node.nextSibling + end + end + break if indent == 0 + end + end + + def DOMUtils.find_node doc, path_a + n = doc + path_a.reverse.each { + |index| + top = n.childNodes.length + n = n.childNodes.item (top - index) + } + n + end + + def DOMUtils.each_parent node + n = node + until n.isNull + yield n + n = n.parentNode + end + end + + def DOMUtils.list_parent_node_types node + types_a = [] + each_parent(node) { + |n| types_a << { :nodeType => n.nodeType, :elementId => n.elementId } + } + types_a + end + + def DOMUtils.get_node_path node + n = node + path_a = [] + until n.isNull + top = n.parentNode.childNodes.length + idx = n.index + path_a << (top-idx) if (n.elementId != 0) + n = n.parentNode + end + path_a + end + +end + +class String + def trigrams + list = [] + 0.upto(self.length-3) { + |pos| + list << self.slice(pos, 3) + } + list + end +end + +class GenericTriGramIndex + attr_accessor :trigrams + + def initialize + clear + end + + def clear + @trigrams = {} + end + + def insert_with_key string, key + string.downcase.trigrams.each { + |trigram| + @trigrams[trigram] = [] unless @trigrams.has_key? trigram + @trigrams[trigram] << key + } + end + + # returns a list of matching keys + def search search_string + warn "searching for a nil???" if search_string.nil? + return [] if search_string.nil? + return [] if search_string.length < 3 + trigs = search_string.downcase.trigrams + key_subset = @trigrams[trigs.delete_at(0)] + return [] if key_subset.nil? + trigs.each { + |trigram| + trigram_subset = @trigrams[trigram] + return [] if trigram_subset.nil? + key_subset &= trigram_subset + } + key_subset + end +end + +module LoggedDebug + + def init_logger parent + @logger = Qt::TextEdit.new parent + @logger.setTextFormat Qt::LogText + end + + def log s + @logger.append s + puts "LOG: #{s}" + scrolldown_logger + end + + def scrolldown_logger + @logger.scrollToBottom + end + +end + +module MyGui + + def init_gui + buttons = Qt::HBox.new self + @panes = Qt::Splitter.new self + @panes.setOrientation Qt::Splitter::Horizontal + setStretchFactor @panes, 10 + + @results_pane = Qt::VBox.new @panes + + @rightpane = Qt::Splitter.new @panes + @rightpane.setOrientation Qt::Splitter::Vertical + @viewed = KDE::HTMLPart.new @rightpane + init_logger @rightpane + + @listbox = Qt::ListBox.new @results_pane + + @label = Qt::Label.new self + + Qt::Object.connect @listbox, SIGNAL("clicked(QListBoxItem*)"), + self, SLOT("clicked_result(QListBoxItem*)") + Qt::Object.connect @viewed, SIGNAL("completed()"), + self, SLOT("khtml_part_init_complete()") + + Qt::Object::connect @viewed, SIGNAL("setWindowCaption(const QString&)"), + @viewed.widget.topLevelWidget, + SLOT("setCaption(const QString&)") + + Qt::Object::connect @viewed.browserExtension, + SIGNAL("openURLRequest(const KURL&, const KParts::URLArgs&)"), + self, SLOT("open_url(const KURL&)") + + KDE::Action.new "&Quit", "quit", KDE::Shortcut.new(), + self, SLOT("quit()"), @main.actionCollection, "file_quit" + KDE::Action.new "&Index-All", KDE::Shortcut.new(), + self, SLOT("index_all()"), @main.actionCollection, "index_all" + @back = \ + KDE::Action.new "&Back", "back", KDE::Shortcut.new(Qt::ALT + Qt::Key_Left), + self, SLOT("go_back()"), @main.actionCollection, "back" + @forward = \ + KDE::Action.new "&Forward", "forward", KDE::Shortcut.new(Qt::ALT + Qt::Key_Right), + self, SLOT("go_forward()"), @main.actionCollection, "forward" + KDE::Action.new "&Home", "gohome", KDE::Shortcut.new(Qt::Key_Home), + self, SLOT("go_home()"), @main.actionCollection, "home" + KDE::Action.new "&Prev Match", "previous",KDE::Shortcut.new(Qt::CTRL + Qt::Key_P), + self, SLOT("goto_prev_match()"), @main.actionCollection, "prev_match" + KDE::Action.new "&Next Match", "next", KDE::Shortcut.new(Qt::CTRL + Qt::Key_N), + self, SLOT("goto_next_match()"), @main.actionCollection, "next_match" + KDE::Action.new "&Follow Match","down", KDE::Shortcut.new(Qt::Key_Return), + self, SLOT("goto_current_match_link()"), @main.actionCollection, "open_match" + + KDE::Action.new "Search", "find", KDE::Shortcut.new(Qt::Key_F6), + self, SLOT("focus_search()"), @main.actionCollection, "focus_search" + KDE::Action.new "New Search", "find", KDE::Shortcut.new(Qt::CTRL + Qt::Key_Slash), + self, SLOT("focus_and_clear_search()"), @main.actionCollection, "focus_and_clear_search" + + KDE::Action.new "&Create", "new", KDE::Shortcut.new(), + self, SLOT("project_create()"), @main.actionCollection, "project_create" + KDE::Action.new "&Choose...", "select", KDE::Shortcut.new(), + self, SLOT("project_goto()"), @main.actionCollection, "project_goto" + + clearLocation = KDE::Action.new "Clear Location Bar", "locationbar_erase", KDE::Shortcut.new(), + self, SLOT("clear_location()"), @main.actionCollection, "clear_location" + clearLocation.setWhatsThis "Clear Location bar<p>Clears the content of the location bar." + + @searchlabel = Qt::Label.new @main + @searchlabel.setText "Search: " + + @searchcombo = KDE::HistoryCombo.new @main + focus_search + Qt::Object.connect @searchcombo, SIGNAL("returnPressed()"), + self, SLOT("goto_search()") + Qt::Object.connect @searchcombo, SIGNAL("textChanged(const QString&)"), + self, SLOT("search(const QString&)") + + KDE::WidgetAction.new @searchlabel, "Search: ", KDE::Shortcut.new(Qt::Key_F6), nil, nil, @main.actionCollection, "location_label" + @searchlabel.setBuddy @searchcombo + + ca = KDE::WidgetAction.new @searchcombo, "Search", KDE::Shortcut.new, nil, nil, @main.actionCollection, "toolbar_url_combo" + ca.setAutoSized true + Qt::WhatsThis::add @searchcombo, "Search<p>Enter a search term." + end + + def focus_search + @searchcombo.setFocus + end + + def focus_and_clear_search + clear_location + focus_search + end + + def clear_location + @searchcombo.clearEdit + end + + def uri_anchor_split url + url =~ /(.*?)(#(.*))?$/ + return $1, $3 + end + + def open_url kurl + url, anchor = uri_anchor_split kurl.url + goto_url url, false unless id == @shown_doc_id + @viewed.gotoAnchor anchor unless anchor.nil? + end + + def gui_init_proportions + # todo - save these settings + desktop = Qt::Application::desktop + sx = (desktop.width * (2.0/3.0)).to_i + sy = (desktop.height * (2.0/3.0)).to_i + + @main.resize sx, sy + + logsize = 0 + resultssize = (sx / 5.0).to_i + + @rightpane.setSizes [sy-logsize, logsize] + @panes.setSizes [resultssize, sx-resultssize] + + @rightpane.setResizeMode @logger, Qt::Splitter::KeepSize + + @panes.setResizeMode @results_pane, Qt::Splitter::KeepSize + @panes.setResizeMode @rightpane, Qt::Splitter::KeepSize + end + +end + +module IndexStorage + + INDEX_VERSION = 3 + + IndexStore = Struct.new :index, :nodeindex, :textcache, :id2title, :id2uri, :id2depth, :version + + def index_fname + basedir = ENV["HOME"] + "/.rubberdocs" + prefix = basedir + "/." + @pref.gsub(/\//,",") + ".idx" + Dir.mkdir basedir unless File.exists? basedir + "#{prefix}.doc" + end + + def depth_debug + puts "depth_debug : begin" + @id2depth.each_key { + |id| + puts "indexed to depth #{@id2depth[id]} : #{@id2uri[id]}" + } + puts "end :" + end + + def load_indexes + return false unless File.exists? index_fname + Qt::Application::setOverrideCursor(Qt::Cursor.new Qt::WaitCursor) + File.open(index_fname, "r") { + |file| + w = Marshal.load file rescue nil + return false if w.nil? || w.version < INDEX_VERSION + @index = w.index + @nodeindex = w.nodeindex + @textcache = w.textcache + @id2title = w.id2title + @id2uri = w.id2uri + @id2depth = w.id2depth + @indexed_more = false + true + } + Qt::Application::restoreOverrideCursor + end + + def save_indexes + return unless @indexed_more + File.open(index_fname, "w") { + |file| + w = IndexStore.new + w.index = @index + w.nodeindex = @nodeindex + w.textcache = @textcache + w.id2title = @id2title + w.id2uri = @id2uri + w.id2depth = @id2depth + w.version = INDEX_VERSION + Marshal.dump w, file + } + end + +end + +module HTMLIndexer + + DocNodeRef = Struct.new :doc_idx, :node_path + + module IndexDepths + # TitleIndexed implies "LinkTitlesIndexed" + Allocated, TitleIndexed, LinksFollowed, Partial, Node = 0, 1, 2, 3, 4 + end + + def index_documents + # fix this to use kde's actual dir + @t1 = Time.now + @url = first_url + already_indexed = load_indexes + @top_doc_id = already_indexed ? @id2uri.keys.max + 1 : 0 + return if already_indexed + t1 = Time.now + @viewed.hide + @done = [] + @todo_links = [] + progress = KDE::ProgressDialog.new(self, "blah", "Indexing files...", "Abort Indexing", true) + total_num_files = Dir.glob("#{@pref}/**/*.html").length + progress.progressBar.setTotalSteps total_num_files + @todo_links = [ DOM::DOMString.new first_url.url ] + until @todo_links.empty? + @todo_next = [] + while more_to_do + progress.progressBar.setProgress @id2title.keys.length + end + @todo_links = @todo_next + fail "errr, you really didn't want to do that dave" if progress.wasCancelled + end + progress.progressBar.setProgress total_num_files + save_indexes + t2 = Time.now + log "all documents indexed in #{(t2 - t1).to_i}s" + end + + def should_follow? lhref + case lhref + when /source/, /members/ + ret = false + when /^file:#{@pref}/ + ret = true + else + ret = false + end + ret + end + + def gather_for_current_page + index_current_title + return [] if @id2depth[@shown_doc_id] >= IndexDepths::LinksFollowed + todo_links = [] + title_map = {} + anchors = @viewed.htmlDocument.links + f = anchors.firstItem + count = anchors.length + until (count -= 1) < 0 + text = "" + DOMUtils.each_child(f) { + |node| + text << node.nodeValue.string if node.nodeType == DOM::Node::TEXT_NODE + } + link = Qt::Internal::cast_object_to f, DOM::HTMLLinkElement + if should_follow? link.href.string + title_map[link.href.string] = text + urlonly, = uri_anchor_split link.href.string + add_link_to_index urlonly, text + todo_links << link.href unless DEBUG_FAST + end + f = anchors.nextItem + end + @id2depth[@shown_doc_id] = IndexDepths::LinksFollowed + return todo_links + end + + def find_allocated_uri uri + id = @id2uri.invert[uri] + return id + end + + # sets @shown_doc_id + def index_current_title + id = find_allocated_uri(@viewed.htmlDocument.URL.string) + return if !id.nil? and @id2depth[id] >= IndexDepths::TitleIndexed + log "making space for url #{@viewed.htmlDocument.URL.string.sub(@pref,"")}" + id = alloc_index_space @viewed.htmlDocument.URL.string if id.nil? + @indexed_more = true + @id2title[id] = @viewed.htmlDocument.title.string + @id2depth[id] = IndexDepths::TitleIndexed + @shown_doc_id = id + end + + def alloc_index_space uri + @indexed_more = true + id = @top_doc_id + @id2uri[@top_doc_id] = uri + @id2title[@top_doc_id] = nil + @id2depth[@top_doc_id] = IndexDepths::Allocated + @top_doc_id += 1 + id + end + + def add_link_to_index uri, title + return unless find_allocated_uri(uri).nil? + @indexed_more = true + new_id = alloc_index_space uri + @id2title[new_id] = title + @index.insert_with_key title, new_id + end + + def index_current_document + return if @id2depth[@shown_doc_id] >= IndexDepths::Partial + Qt::Application::setOverrideCursor(Qt::Cursor.new Qt::WaitCursor) + @indexed_more = true + @label.setText "Scanning : #{@url.prettyURL}" + log "indexing url #{@viewed.htmlDocument.URL.string.sub(@pref,"")}" + DOMUtils.each_child(@viewed.document) { + |node| + next unless node.nodeType == DOM::Node::TEXT_NODE + @index.insert_with_key node.nodeValue.string, @shown_doc_id + } + @id2depth[@shown_doc_id] = IndexDepths::Partial + @label.setText "Ready" + Qt::Application::restoreOverrideCursor + end + + def preload_text + return if @id2depth[@shown_doc_id] >= IndexDepths::Node + Qt::Application::setOverrideCursor(Qt::Cursor.new Qt::WaitCursor) + @indexed_more = true + index_current_document + log "deep indexing url #{@viewed.htmlDocument.URL.string.sub(@pref,"")}" + @label.setText "Indexing : #{@url.prettyURL}" + doc_text = "" + t1 = Time.now + DOMUtils.each_child(@viewed.document) { + |node| + next unless node.nodeType == DOM::Node::TEXT_NODE + ref = DocNodeRef.new @shown_doc_id, DOMUtils.get_node_path(node) + @nodeindex.insert_with_key node.nodeValue.string, ref + @textcache[ref] = node.nodeValue.string + doc_text << node.nodeValue.string + } + @id2depth[@shown_doc_id] = IndexDepths::Node + @label.setText "Ready" + Qt::Application::restoreOverrideCursor + end + +end + +# TODO - this sucks, use khtml to get the values +module IDS + A = 1 + META = 62 + STYLE = 85 + TITLE = 95 +end + +module TermHighlighter + + include IDS + + FORBIDDEN_TAGS = [IDS::TITLE, IDS::META, IDS::STYLE] + + def update_highlight + return if @search_text.nil? || @search_text.empty? + return if @in_update_highlight + @in_update_highlight = true + preload_text + highlighted_nodes = [] + @nodeindex.search(@search_text).each { + |ref| + next unless ref.doc_idx == @shown_doc_id + highlighted_nodes << ref.node_path + } + highlight_node_list highlighted_nodes + @in_update_highlight = false + end + + def mark_screwup + @screwups = 0 if @screwups.nil? + warn "if you see this, then alex screwed up!.... #{@screwups} times!" + @screwups += 1 + end + + def highlight_node_list highlighted_nodes + doc = @viewed.document + no_undo_buffer = @to_undo.nil? + current_doc_already_highlighted = (@shown_doc_id == @last_highlighted_doc_id) + undo_highlight @to_undo unless no_undo_buffer or !current_doc_already_highlighted + @last_highlighted_doc_id = @shown_doc_id + @to_undo = [] + return if highlighted_nodes.empty? + Qt::Application::setOverrideCursor(Qt::Cursor.new Qt::WaitCursor) + cursor_override = true + @current_matching_node_index = 0 if @current_matching_node_index.nil? + @current_matching_node_index = @current_matching_node_index.modulo highlighted_nodes.length + caretnode = DOMUtils.find_node doc, highlighted_nodes[@current_matching_node_index] + @viewed.setCaretVisible false + @viewed.setCaretPosition caretnode, 0 + caret_path = DOMUtils.get_node_path(caretnode) + count = 0 + @skipped_highlight_requests = false + @current_matched_href = nil + highlighted_nodes.sort.each { + |path| + node = DOMUtils.find_node doc, path + next mark_screwup if node.nodeValue.string.nil? + match_idx = node.nodeValue.string.downcase.index @search_text.downcase + next mark_screwup if match_idx.nil? + parent_info = DOMUtils.list_parent_node_types node + has_title_parent = !(parent_info.detect { |a| FORBIDDEN_TAGS.include? a[:elementId] }.nil?) + next if has_title_parent + if path == caret_path + DOMUtils.each_parent(node) { + |n| + next unless n.elementId == IDS::A + # link = DOM::HTMLLinkElement.new n # WTF? why doesn't this work??? + link = Qt::Internal::cast_object_to n, "DOM::HTMLLinkElement" + @current_matched_href = link.href.string + } + end + before = doc.createTextNode node.nodeValue.split(0) + matched = doc.createTextNode before.nodeValue.split(match_idx) + after = doc.createTextNode matched.nodeValue.split(@search_text.length) + DOM::CharacterData.new(DOM::Node.new after).setData DOM::DOMString.new("") \ + if after.nodeValue.string.nil? + span = doc.createElement DOM::DOMString.new("span") + spanelt = DOM::HTMLElement.new span + classname = (path == caret_path) ? "foundword" : "searchword" + spanelt.setClassName DOM::DOMString.new(classname) + span.appendChild matched + node.parentNode.insertBefore before, node + node.parentNode.insertBefore span, node + node.parentNode.insertBefore after, node + @to_undo << [node.parentNode, before] + node.parentNode.removeChild node + rate = (count > 50) ? 50 : 10 + allow_user_input = ((count+=1) % rate == 0) + if allow_user_input + Qt::Application::restoreOverrideCursor if cursor_override + cursor_override = false + @in_node_highlight = true + Qt::Application::eventLoop.processEvents Qt::EventLoop::AllEvents, 10 + @in_node_highlight = false + if @skipped_highlight_requests + @timer.start 50, true + return false + end + @viewed.view.layout + end + } + if @skipped_highlight_requests + @timer.start 50, true + end + Qt::Application::restoreOverrideCursor if cursor_override + end + + def undo_highlight to_undo + to_undo.reverse.each { + |pnn| pn, before = *pnn + mid = before.nextSibling + after = mid.nextSibling + beforetext = before.nodeValue + aftertext = after.nodeValue + pn.removeChild after + midtxtnode = mid.childNodes.item(0) + midtext = midtxtnode.nodeValue + str = DOM::DOMString.new "" + str.insert aftertext, 0 + str.insert midtext, 0 + str.insert beforetext, 0 + chardata = DOM::CharacterData.new(DOM::Node.new before) + chardata.setData str + pn.removeChild mid + } + end + +end + +class SmallIconSet + def SmallIconSet.[] name + loader = KDE::Global::instance.iconLoader + return loader.loadIconSet name, KDE::Icon::Small, 0 + end +end + +class ProjectEditDialog < Qt::Object + + slots "select_file()", "slot_ok()" + + def initialize project_name, parent=nil,name=nil,caption=nil + + super(parent, name) + @parent = parent + + @dialog = KDE::DialogBase.new(parent,name, true, caption, + KDE::DialogBase::Ok|KDE::DialogBase::Cancel, KDE::DialogBase::Ok, false) + + vbox = Qt::VBox.new @dialog + + grid = Qt::Grid.new 2, Qt::Horizontal, vbox + + titlelabel = Qt::Label.new "Name:", grid + @title = KDE::LineEdit.new grid + titlelabel.setBuddy @title + + urllabel = Qt::Label.new "Location:", grid + lochbox = Qt::HBox.new grid + @url = KDE::LineEdit.new lochbox + urllabel.setBuddy @url + locselc = Qt::PushButton.new lochbox + locselc.setIconSet SmallIconSet["up"] + + blub = Qt::HBox.new vbox + Qt::Label.new "Is main one?:", blub + @cb = Qt::CheckBox.new blub + + enabled = @parent.projects_data.project_list.empty? + + unless project_name.nil? + project_url = @parent.projects_data.project_list[project_name] + @title.setText project_name + @url.setText project_url + enabled = true if (project_name == @parent.projects_data.enabled_name) + end + + @cb.setChecked true if enabled + + Qt::Object.connect @dialog, SIGNAL("okClicked()"), + self, SLOT("slot_ok()") + + Qt::Object.connect locselc, SIGNAL("clicked()"), + self, SLOT("select_file()") + + @title.setFocus + + @dialog.setMainWidget vbox + + @modified = false + end + + def select_file + s = Qt::FileDialog::getOpenFileName ENV["HOME"], "HTML Files (*.html)", + @parent, "open file dialog", "Choose a file" + @url.setText s unless s.nil? + end + + def edit + @dialog.exec + return @modified + end + + def new_name + @title.text + end + + def new_url + @url.text + end + + def new_enabled + @cb.isChecked + end + + def slot_ok + @parent.projects_data.project_list[new_name] = new_url + @parent.projects_data.enabled_name = new_name if new_enabled + @modified = true + end + +end + +class ProjectSelectDialog < Qt::Object + + slots "edit_selected_project()", "delete_selected_project()", "project_create_button()", "project_selected()" + + def initialize parent=nil,name=nil,caption=nil + super(parent, name) + @parent = parent + + @dialog = KDE::DialogBase.new parent,name, true, caption, + KDE::DialogBase::Ok|KDE::DialogBase::Cancel, KDE::DialogBase::Ok, false + + vbox = Qt::VBox.new @dialog + + @listbox = Qt::ListBox.new vbox + + fill_listbox + + hbox = Qt::HBox.new vbox + button_new = Qt::PushButton.new "New...", hbox + button_del = Qt::PushButton.new "Delete", hbox + button_edit = Qt::PushButton.new "Edit...", hbox + + Qt::Object.connect button_new, SIGNAL("clicked()"), + self, SLOT("project_create_button()") + + Qt::Object.connect button_del, SIGNAL("clicked()"), + self, SLOT("delete_selected_project()") + + Qt::Object.connect button_edit, SIGNAL("clicked()"), + self, SLOT("edit_selected_project()") + + Qt::Object.connect @listbox, SIGNAL("doubleClicked(QListBoxItem *)"), + self, SLOT("project_selected()") + + @dialog.setMainWidget vbox + end + + def project_selected + return if @listbox.selectedItem.nil? + @parent.current_project_name = @listbox.selectedItem.text + @parent.blah_blah + @dialog.reject + end + + def fill_listbox + @listbox.clear + @parent.projects_data.project_list.keys.each { + |name| + enabled = (name == @parent.projects_data.enabled_name) + icon = enabled ? "forward" : "down" + pm = SmallIconSet[icon].pixmap(Qt::IconSet::Automatic, Qt::IconSet::Normal) + it = Qt::ListBoxPixmap.new pm, name + @listbox.insertItem it + } + end + + def edit_selected_project + return if @listbox.selectedItem.nil? + oldname = @listbox.selectedItem.text + dialog = ProjectEditDialog.new oldname, @parent + mod = dialog.edit + if mod and oldname != dialog.new_name + @parent.projects_data.project_list.delete oldname + end + fill_listbox if mod + end + + def project_create_button + mod = @parent.project_create + fill_listbox if mod + end + + def delete_selected_project + return if @listbox.selectedItem.nil? + # TODO - confirmation dialog + @parent.projects_data.project_list.delete @listbox.selectedItem.text + fill_listbox + end + + def select + @dialog.exec + end + +end + +module ProjectManager + + def project_create + dialog = ProjectEditDialog.new nil, self + dialog.edit + while @projects_data.project_list.empty? + dialog.edit + end + end + + def project_goto + dialog = ProjectSelectDialog.new self + dialog.select + if @projects_data.project_list.empty? + project_create + end + end + + require 'yaml' + + def yamlfname + ENV["HOME"] + "/.rubberdocs/projects.yaml" + end + + PROJECT_STORE_VERSION = 0 + + Projects = Struct.new :project_list, :enabled_name, :version + + def load_projects + okay = false + if File.exists? yamlfname + @projects_data = YAML::load File.open(yamlfname) + if (@projects_data.version rescue -1) >= PROJECT_STORE_VERSION + okay = true + end + end + if not okay or @projects_data.project_list.empty? + @projects_data = Projects.new({}, nil, PROJECT_STORE_VERSION) + project_create + end + if @projects_data.enabled_name.nil? + @projects_data.enabled_name = @projects_data.project_list.keys.first + end + end + + def save_projects + File.open(yamlfname, "w+") { + |file| + file.puts @projects_data.to_yaml + } + end + +end + +class RubberDoc < Qt::VBox + + slots "khtml_part_init_complete()", + "go_back()", "go_forward()", "go_home()", "goto_url()", + "goto_search()", "clicked_result(QListBoxItem*)", + "search(const QString&)", "update_highlight()", + "quit()", "open_url(const KURL&)", "index_all()", + "goto_prev_match()", "goto_next_match()", "clear_location()", "activated()", + "goto_current_match_link()", "focus_search()", "focus_and_clear_search()", + "project_create()", "project_goto()" + + attr_accessor :back, :forward, :url, :projects_data + + include LoggedDebug + include MyGui + include IndexStorage + include HTMLIndexer + include TermHighlighter + include ProjectManager + + def init_blah + @index = GenericTriGramIndex.new + @nodeindex = GenericTriGramIndex.new + @textcache = {} + @id2uri, @id2title, @id2depth = {}, {}, {} + + @history, @popped_history = [], [] + @shown_doc_id = 0 + @freq_sorted_idxs = nil + @last_highlighted_doc_id, @to_undo = nil, nil, nil + @search_text = nil + @current_matched_href = nil + + @in_update_highlight = false + @in_node_highlight = false + + @lvis = nil + end + + def initialize parent + super parent + @main = parent + + load_projects + @current_project_name = @projects_data.enabled_name + + init_blah + + init_gui + gui_init_proportions + + @timer = Qt::Timer.new self + Qt::Object.connect @timer, SIGNAL("timeout()"), + self, SLOT("update_highlight()") + + @viewed.openURL KDE::URL.new("about:blank") + + @init_connected = true + end + + def blah_blah + save_indexes + init_blah + khtml_part_init_complete + end + + def quit + @main.close + end + + def khtml_part_init_complete + Qt::Object.disconnect @viewed, SIGNAL("completed()"), + self, SLOT("khtml_part_init_complete()") if @init_connected + + @pref = File.dirname first_url.url.gsub("file:","") + + init_khtml_part_settings @viewed if @init_connected + index_documents + + # maybe make a better choice as to the start page??? + @shown_doc_id = 0 + goto_url @id2uri[@shown_doc_id], false + + @viewed.show + + search "qlistview" if DEBUG_SEARCH || DEBUG_GOTO + goto_search if DEBUG_GOTO + + @init_connected = false + end + + def finish + save_projects + save_indexes + end + + def init_khtml_part_settings khtmlpart + khtmlpart.setJScriptEnabled true + khtmlpart.setJavaEnabled false + khtmlpart.setPluginsEnabled false + khtmlpart.setAutoloadImages false + end + + def load_page + @viewed.setCaretMode true + @viewed.setCaretVisible false + @viewed.document.setAsync false + @viewed.document.load DOM::DOMString.new @url.url + @viewed.setUserStyleSheet "span.searchword { background-color: yellow } + span.foundword { background-color: green }" + Qt::Application::eventLoop.processEvents Qt::EventLoop::ExcludeUserInput + end + + attr_accessor :current_project_name + + def first_url + return KDE::URL.new @projects_data.project_list[@current_project_name] + end + + def search s + if @in_node_highlight + @skipped_highlight_requests = true + return + end + puts "search request: #{s}" + @search_text = s + + results = @index.search(s) + results += @nodeindex.search(s).collect { |docref| docref.doc_idx } + + idx_hash = Hash.new { |h,k| h[k] = 0 } + results.each { + |idx| idx_hash[idx] += 1 + } + @freq_sorted_idxs = idx_hash.to_a.sort_by { |val| val[1] }.reverse + + update_lv + + hl_timeout = 150 # continuation search should be slower? + @timer.start hl_timeout, true unless @freq_sorted_idxs.empty? + end + + def look_for_prefixes + prefixes = [] + # TODO - fix this crappy hack + @id2title.values.compact.sort.each { + |title| + title.gsub! "\n", "" + pos = title.index ":" + next if pos.nil? + prefix = title[0..pos-1] + prefixes << prefix + new_title = title[pos+1..title.length] + new_title.gsub! /(\s\s+|^\s+|\s+$)/, "" + title.replace new_title + } + end + + class ResultItem < Qt::ListBoxItem + def initialize header, text + super() + @text, @header = text, header + @font = Qt::Font.new("Helvetica", 8) + @flags = Qt::AlignLeft | Qt::WordBreak + end + def paint painter + w, h = width(listBox), height(listBox) + header_height = (text_height @font, @header) + 5 + painter.setFont @font + painter.fillRect 5, 5, w - 10, header_height, Qt::Brush.new(Qt::Color.new 150,100,150) + painter.drawText 5, 5, w - 10, header_height, @flags, @header + painter.fillRect 5, header_height, w - 10, h - 10, Qt::Brush.new(Qt::Color.new 100,150,150) + painter.setFont @font + painter.drawText 5, header_height + 2, w - 10, h - 10, @flags, @text + end + def text_height font, text + fm = Qt::FontMetrics.new font + br = fm.boundingRect 0, 0, width(listBox) - 20, 8192, @flags, text + br.height + end + def height listbox + h = 0 + h += text_height @font, @text + h += text_height @font, @header + return h + 10 + end + def width listbox + listBox.width - 5 + end + end + + CUTOFF = 100 + def update_lv + @listbox.clear + @lvis = {} + look_for_prefixes + return if @freq_sorted_idxs.nil? + @freq_sorted_idxs.each { + |a| idx, count = *a + title = @id2title[idx] + # we must re-search until we have a doc -> nodes list + matches_text = "" + @nodeindex.search(@search_text).each { + |ref| + break if matches_text.length > CUTOFF + next unless ref.doc_idx == idx + matches_text << @textcache[ref] << "\n" + } + matches_text = matches_text.slice 0..CUTOFF + lvi = ResultItem.new "(#{count}) #{title}", matches_text + @listbox.insertItem lvi + @lvis[lvi] = idx + } + end + + def goto_search + idx, count = *(@freq_sorted_idxs.first) + goto_id_and_hl idx + end + + def clicked_result i + return if i.nil? + idx = @lvis[i] + goto_id_and_hl idx + end + + def goto_id_and_hl idx + @current_matching_node_index = 0 + goto_url @id2uri[idx], true + @shown_doc_id = idx + update_highlight + end + + def goto_current_match_link + open_url KDE::URL.new(@current_matched_href) unless @current_matched_href.nil? + end + + def skip_matches n + @current_matching_node_index += n # autowraps + if @in_node_highlight + @skipped_highlight_requests = true + return + end + update_highlight + end + + def goto_prev_match + skip_matches -1 + end + + def goto_next_match + skip_matches +1 + end + + def more_to_do + return false if @todo_links.empty? + lhref = @todo_links.pop + do_for_link lhref + true + end + + def do_for_link lhref + idx = (lhref.string =~ /#/) + unless idx.nil? + lhref = lhref.copy + lhref.truncate idx + end + skip = @done.include? lhref.string + return [] if skip +time_me("loading") { + @viewed.document.setAsync false + @viewed.document.load lhref +} + @done << lhref.string + newlinks = gather_for_current_page + @todo_next += newlinks + end + + def update_ui_elements + @forward.setEnabled !@popped_history.empty? + @back.setEnabled !@history.empty? + end + + def go_back + @popped_history << @url + fail "ummm... already at the start, gui bug" if @history.empty? + goto_url @history.pop, false, false + update_loc + update_ui_elements + end + + def go_forward + fail "history bug" if @popped_history.empty? + goto_url @popped_history.pop, false, false + @history << @url + update_loc + update_ui_elements + end + + def update_loc + # @location.setText @url.prettyURL + end + + def go_home + goto_url first_url + end + + def index_all + @viewed.hide + @id2uri.keys.each { + |id| goto_id_and_hl id + } + @viewed.show + end + + def goto_url url = nil, history_store = true, clear_forward = true + @popped_history = [] if clear_forward + if history_store + @history << @url + end + @url = KDE::URL.new(url.nil? ? @location.text : url) + @label.setText "Loading : #{@url.prettyURL}" + urlonly, = uri_anchor_split @url.url + id = @id2uri.invert[@url.url] + if id.nil? and !(should_follow? urlonly) + warn "link points outside indexed space!" + return + end + load_page + if id.nil? + gather_for_current_page + id = @shown_doc_id + index_current_document + else + @shown_doc_id = id + end + @label.setText "Ready" + update_loc unless url.nil? + update_ui_elements + end + +end + +m = KDE::MainWindow.new +browser = RubberDoc.new m +browser.update_ui_elements +guixmlfname = Dir.pwd + "/RubberDoc.rc" +guixmlfname = File.dirname(File.readlink $0) + "/RubberDoc.rc" unless File.exists? guixmlfname +m.createGUI guixmlfname +m.setCentralWidget browser +app.setMainWidget(m) +m.show +app.exec() +browser.finish + +__END__ + +TESTCASE - +w = KDE::HTMLPart # notice the missing .new +w.begin +=> crashes badly + +(RECHECK) +./kde.rb:29:in `method_missing': Cannot handle 'const QIconSet&' as argument to QTabWidget::changeTab (ArgumentError) + from ./kde.rb:29:in `initialize' + from ./kde.rb:92:in `new' + from ./kde.rb:92 +for param nil given to param const QIconSet & +occurs frequently + +dum di dum + +can't get tabwidget working. umm... wonder what i'm messing up... (RECHECK) + + tabwidget = KDE::TabWidget.new browser + tabwidget.setTabPosition Qt::TabWidget::Top + @viewed = KDE::HTMLPart.new tabwidget + w2 = KDE::HTMLPart.new tabwidget + tabwidget.changeTab @viewed, Qt::IconSet.new, "blah blah" + tabwidget.showPage @viewed + tabwidget.show + @viewed.show + +# possible BUG DOM::Text.new(node).data.string # strange that this one doesn't work... (RECHECK) + +wierd khtml bug + @rightpane.setResizeMode @viewed, Qt::Splitter::KeepSize + +in order to use KURL's as constants one must place this KApplication init +at the top of the file otherwise KInstance isn't init'ed before KURL usage + +class ProjectSelectDialog < KDE::DialogBase + def initialize parent=nil,name=nil,caption=nil + super(parent,name, true, caption, + KDE::DialogBase::Ok|KDE::DialogBase::Cancel, KDE::DialogBase::Ok, false, KDE::GuiItem.new) + blah blah + end +end + +# painter.fillRect 5, 5, width(listBox) - 10, height(listBox) - 10, Qt::Color.new(255,0,0) diff --git a/korundum/rubylib/examples/RubberDoc.rc b/korundum/rubylib/examples/RubberDoc.rc new file mode 100644 index 00000000..8e544b1a --- /dev/null +++ b/korundum/rubylib/examples/RubberDoc.rc @@ -0,0 +1,35 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui name="xmlgui" version="2"> + +<MenuBar> + <Menu name="file" noMerge="1"><text>&File</text> + <Action name="index_all"/> + <Separator/> + <Action name="file_quit"/> + </Menu> +</MenuBar> + +<ToolBar name="projectToolbar" noMerge="1" fullWidth="true" iconText="icontextright"><text>Project Toolbar</text> + <Action name="project_create"/> + <Action name="project_delete"/> + <Action name="project_manage"/> + <Action name="project_goto"/> +</ToolBar> + +<ToolBar name="mainToolBar" noMerge="1" fullWidth="true" iconText="icontextright"><text>Main Toolbar</text> + <Action name="back"/> + <Action name="forward"/> + <Action name="home"/> + <Action name="prev_match"/> + <Action name="next_match"/> + <Action name="open_match"/> +</ToolBar> + +<ToolBar fullWidth="true" name="locationToolBar" newline="true"><text>Location Toolbar</text> + <Action name="clear_location" /> + <Action name="location_label" /> + <Action name="toolbar_url_combo" /> + <Action name="go_url" /> +</ToolBar> + +</kpartgui> diff --git a/korundum/rubylib/examples/dcop/dcopcall.rb b/korundum/rubylib/examples/dcop/dcopcall.rb new file mode 100755 index 00000000..f3b532ef --- /dev/null +++ b/korundum/rubylib/examples/dcop/dcopcall.rb @@ -0,0 +1,37 @@ +#!/usr/bin/env ruby + +require 'Korundum' +include KDE + +class SenderWidget < PushButton + def initialize(parent, name) + super + connect(self, SIGNAL('clicked()'), self, SLOT('doit()')) + end + + slots 'doit()' + + def doit() + dcopRef = DCOPRef.new("dcopslot", "MyWidget") + # + # Note that there are three different ways to make a DCOP call(): + # 1) result = dcopRef.call("getPoint(QString)", "Hello from dcopcall") + # 2) result = dcopRef.call("getPoint", "Hello from dcopcall") + # 3) result = dcopRef.getPoint("Hello from dcopcall") + # + result = dcopRef.getPoint("Hello from dcopcall") + if result.nil? + puts "DCOP call failed" + else + puts "result class: #{result.class.name} x: #{result.x} y: #{result.y}" + end + end +end + +about = AboutData.new("dcopcall", "DCOP Call Test", "0.1") +CmdLineArgs.init(ARGV, about) +a = UniqueApplication.new +calltest = SenderWidget.new(nil, "calltest") { setText 'DCOP Call Test' } +a.mainWidget = calltest +calltest.show +a.exec diff --git a/korundum/rubylib/examples/dcop/dcoppredicate.rb b/korundum/rubylib/examples/dcop/dcoppredicate.rb new file mode 100755 index 00000000..82a9c8b4 --- /dev/null +++ b/korundum/rubylib/examples/dcop/dcoppredicate.rb @@ -0,0 +1,41 @@ +#!/usr/bin/env ruby + +require 'Korundum' +include KDE + +class SenderWidget < PushButton + def initialize(parent, name) + super + connect(self, SIGNAL('clicked()'), self, SLOT('doit()')) + end + + slots 'doit()' + + def doit() + dcopRef = DCOPRef.new("dcopslot", "MyWidget") + # + # A synonym for isFoo() + result = dcopRef.foo? + if result.nil? + puts "DCOP predicate failed" + else + puts "foo? is #{result}" + end + + # A synonym for hasBar() + result = dcopRef.bar? + if result.nil? + puts "DCOP predicate failed" + else + puts "bar? is #{result}" + end + end +end + +about = AboutData.new("dcoppredicate", "DCOP Predicate Test", "0.1") +CmdLineArgs.init(ARGV, about) +a = UniqueApplication.new +calltest = SenderWidget.new(nil, "predicatetest") { setText 'DCOP Predicate Test' } +a.mainWidget = calltest +calltest.show +a.exec diff --git a/korundum/rubylib/examples/dcop/dcopsend.rb b/korundum/rubylib/examples/dcop/dcopsend.rb new file mode 100755 index 00000000..9365473b --- /dev/null +++ b/korundum/rubylib/examples/dcop/dcopsend.rb @@ -0,0 +1,35 @@ +#!/usr/bin/env ruby + +require 'Korundum' + +class SenderWidget < KDE::PushButton + def initialize(parent, name) + super + Qt::Object::connect(self, SIGNAL('clicked()'), self, SLOT('doit()')) + end + + slots 'doit()' + + def doit() + # + # Note that there are three different ways to make a DCOP send(): + # 1) dcopRef.send("mySlot(QString)", "Hello from dcopsend") + # 2) dcopRef.send("mySlot", "Hello from dcopsend") + # + dcopRef = KDE::DCOPRef.new("dcopslot", "MyWidget") + res = dcopRef.send("mySlot", "Hello from dcopsend") + if res + puts "Sent dcop message" + else + puts "DCOP send failed" + end + end +end + +about = KDE::AboutData.new("dcopsend", "DCOPSendTest", "0.1") +KDE::CmdLineArgs.init(ARGV, about) +a = KDE::Application.new() +sender = SenderWidget.new(nil, "senderwidget") { setText 'DCOP Send Test' } +a.setMainWidget(sender) +sender.show() +a.exec() diff --git a/korundum/rubylib/examples/dcop/dcopsignal.rb b/korundum/rubylib/examples/dcop/dcopsignal.rb new file mode 100755 index 00000000..07a6dfee --- /dev/null +++ b/korundum/rubylib/examples/dcop/dcopsignal.rb @@ -0,0 +1,26 @@ +#!/usr/bin/env ruby + +require 'Korundum' + +class SenderWidget < KDE::PushButton + k_dcop_signals 'void testEmitSignal(QString)' + + def initialize(parent, name) + super + Qt::Object::connect(self, SIGNAL('clicked()'), self, SLOT('doit()')) + end + + slots 'doit()' + + def doit() + emit testEmitSignal("Hello DCOP Slot") + end +end + +about = KDE::AboutData.new("dcopsignal", "DCOPSignalTest", "0.1") +KDE::CmdLineArgs.init(ARGV, about) +a = KDE::UniqueApplication.new() +signaltest = SenderWidget.new(nil, "foobar") { setText 'DCOP Signal Test' } +a.mainWidget = signaltest +signaltest.show() +a.exec() diff --git a/korundum/rubylib/examples/dcop/dcopslot.rb b/korundum/rubylib/examples/dcop/dcopslot.rb new file mode 100755 index 00000000..e600dfdb --- /dev/null +++ b/korundum/rubylib/examples/dcop/dcopslot.rb @@ -0,0 +1,88 @@ +#!/usr/bin/env ruby + +require 'Korundum' + +# This is an example of a KDE class that has 'k_dcop' slots declarations, but +# isn't a subclass of DCOPObject. The following four methods are added to your +# class: +# +# interfaces() +# functions() +# connectDCOPSignal() +# disconnectDCOPSignal() +# +# See the call to connectDCOPSignal() towards the end of the code as +# an example. The name of the dcop object is always the name of the +# ruby class, and they are Singletons - you can only instantiate one +# of them. +# +# The petshop.rb example in this directory demonstrates more complex +# use of korundum dcop by subclassing a DCOPObject. +# +class MyWidget < KDE::PushButton + + k_dcop 'void mySlot(QString)', + 'QPoint getPoint(QString)', + 'QMap<QCString,DCOPRef> actionMap()', + 'QValueList<DCOPRef> windowList()', + 'QValueList<QCString> propertyNames(bool)', + 'KURL::List urlList()', + 'bool isFoo()', + 'bool hasBar()' + + def initialize(parent, name) + super + end + + def mySlot(greeting) + puts "greeting: #{greeting}" + end + + def getPoint(msg) + puts "message: #{msg}" + return Qt::Point.new(50, 100) + end + + def actionMap() + map = {} + map['foobar'] = KDE::DCOPRef.new("myapp", "myobj") + return map + end + + def windowList() + list = [] + list[0] = KDE::DCOPRef.new("myapp", "myobj") + return list + end + + def propertyNames(b) + return ["thisProperty", "thatProperty"] + end + + def urlList() + list = [] + list << KDE::URL.new("http://www.kde.org/") << KDE::URL.new("http://dot.kde.org/") + return list + end + + def isFoo + true + end + + def hasBar + true + end +end + +about = KDE::AboutData.new("dcopslot", "dcopSlotTest", "0.1") +KDE::CmdLineArgs.init(ARGV, about) +a = KDE::UniqueApplication.new() +slottest = MyWidget.new(nil, "mywidget") { setText "DCOP Slot Test" } +a.mainWidget = slottest +slottest.caption = a.makeStdCaption("DCOP Slot Test") +result = slottest.connectDCOPSignal("dcopsignal", "SenderWidget", "testEmitSignal(QString)", "mySlot(QString)", true) +puts "result: #{result}" + +slottest.show() +# Qt::Internal::setDebug Qt::QtDebugChannel::QTDB_ALL +a.exec() diff --git a/korundum/rubylib/examples/dcop/dcoptest.rb b/korundum/rubylib/examples/dcop/dcoptest.rb new file mode 100755 index 00000000..7d42f76e --- /dev/null +++ b/korundum/rubylib/examples/dcop/dcoptest.rb @@ -0,0 +1,129 @@ +#!/usr/bin/env ruby +=begin +This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale +=end + +=begin +Copyright 2003 Jim Bublitz + +Terms and Conditions + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +Except as contained in this notice, the name of the copyright holder shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from the +copyright holder. +=end + + +require 'Korundum' + +module DCOPTest + + def DCOPTest.getAnyApplication(client, appName) + client.registeredApplications().each do |app| + if app == appName or app =~ Regexp.new("^#{appName}-") + puts app + puts + objList = client.remoteObjects(app) + objList.each do |obj| + puts " #{obj}" + funcs = client.remoteFunctions(app, obj) + funcs.each { |f| puts " #{f}" } + end + end + end + end + +end + +#-------------------- main ------------------------------------------------ + +description = "A basic application template" +version = "1.0" +aboutData = KDE::AboutData.new("testdcopext", "testdcopext", + version, description, KDE::AboutData::License_GPL, + "(C) 2003 whoever the author is") + +aboutData.addAuthor("author1", "whatever they did", "email@somedomain") +aboutData.addAuthor("author2", "they did something else", "another@email.address") + +KDE::CmdLineArgs.init(ARGV, aboutData) + +KDE::CmdLineArgs.addCmdLineOptions([["+files", "File to open", ""]]) + +app = KDE::Application.new +dcop = app.dcopClient +puts "DCOP Application: #{dcop.appId} starting" + +# DCOPTest.getAnyApplication(dcop, "konqueror") + +puts "--------------------------" +puts "The DCOPObjects for kicker:" + +d = KDE::DCOPRef.new('kicker') +objs = d.interfaces() +objs.each { |obj| puts obj } + +puts +puts "get kicker panel size via DCOP" +res = d.panelSize() +puts res +puts "--------------------------" + +puts +puts "Call a method that doesn't exist" +res = d.junk() +puts (res.nil? ? "Call failed" : "Call succeeded") +puts "--------------------------" + +puts +puts +puts "Start a kwrite instance" + +error = "" +dcopService = "" +pid = Qt::Integer.new + +errcode = KDE::Application.startServiceByDesktopName("kwrite", "", error, dcopService, pid) +dcopService = "kwrite-" + pid.to_s +puts "errcode: #{errcode.to_s} error: #{error} dcopService: #{dcopService} pid: #{pid.to_s}" +puts "--------------------------" +sleep(2) + +o1 = KDE::DCOPRef.new(dcopService, "EditInterface#1") +#puts "Check if insertLine is a valid function" +#puts "valid", o1.insertLine.valid +#puts "--------------------------" +#puts "insertLine's arg types and names" +# puts o1.insertLine.argtypes, o1.insertLine.argnames +puts "--------------------------" +puts "Insert a line into the kwrite instance we launched" + +res = o1.insertLine(0, 'Now is the time for all good men to come to the aid of their party') +if res.nil? + puts "call returns: failed" +else + puts "call returns: #{res.to_s}" +end + +app.exec + + diff --git a/korundum/rubylib/examples/dcop/petshop.rb b/korundum/rubylib/examples/dcop/petshop.rb new file mode 100755 index 00000000..0cce6277 --- /dev/null +++ b/korundum/rubylib/examples/dcop/petshop.rb @@ -0,0 +1,91 @@ +#!/usr/bin/env ruby + +# This is an example of a DCOP enabled application written in Ruby, using +# Korundum. Taken from the PyKDE example_dcopexport.py example which was +# derived from server.py example in kdebindings written by Torben Weis +# and Julian Rockey + +require 'Korundum' + +# An object with DCOP slots needn't be a subclass of DCOPObject, but +# this DeadParrotObject is one + +class DeadParrotObject < KDE::DCOPObject + + k_dcop 'QString getParrotType()', 'void setParrotType(QString)', + 'QString squawk()', 'QStringList adjectives()', + 'int age()', 'void setAge(int)' + + def initialize(id = 'dead parrot') + super(id) + @parrot_type = "Norwegian Blue" + @age = 7 + end + + def getParrotType() + @parrot_type + end + + def setParrotType(parrot_type) + @parrot_type = parrot_type + end + + def age() + @age + end + + def setAge(a) + @age = a + end + + def squawk + if rand(2) == 0 + "This parrot, a #{@parrot_type}, is pining for the fjords" + else + "This parrot, #{@age} months old, is a #{@parrot_type}" + end + end + + def adjectives + return ["passed on", "is no more", "ceased to be", "expired", "gone to meet his maker", + "a stiff", "bereft of life", "rests in peace", "metabolic processes are now history", + "off the twig", "kicked the bucket", "shuffled off his mortal coil", + "run down his curtain", "joined the bleedin' choir invisible", "THIS IS AN EX-PARROT"] + end +end + +description = "A basic application template" +version = "1.0" +aboutData = KDE::AboutData.new("petshop", "Dead Parrot Test", + version, description, KDE::AboutData::License_GPL, + "(C) 2003 whoever the author is") + +aboutData.addAuthor("author1", "whatever they did", "email@somedomain") +aboutData.addAuthor("author2", "they did something else", "another@email.address") + +KDE::CmdLineArgs.init(ARGV, aboutData) + +KDE::CmdLineArgs.addCmdLineOptions([["+files", "File to open", ""]]) + +app = KDE::UniqueApplication.new +dcop = app.dcopClient +puts "DCOP Application: #{dcop.appId} starting" + +parrot = DeadParrotObject.new +another_parrot = DeadParrotObject.new('polly') + +message = <<EOS +Run kdcop and look for the 'petshop' application instance. + +This program exports the DeadParrotObject object. +Double-clicking those object's methods will allow you to get or set data. + +To end the application, in kdcop choose the MainApplication-Interface +object and double-click the quit() method. +EOS + +print message + +app.exec + + diff --git a/korundum/rubylib/examples/kludgeror.rb b/korundum/rubylib/examples/kludgeror.rb new file mode 100644 index 00000000..535936b2 --- /dev/null +++ b/korundum/rubylib/examples/kludgeror.rb @@ -0,0 +1,138 @@ +#!/usr/bin/env ruby +# A quick and dirty web browser demonstrating the direct instantiation +# of a KHTML part. Needless to say: this is NOT a programming paragon :) +# -- gg. +# AK - ported to ruby + +require 'Korundum' + +opt = [ [ "+[url]", "An URL to open at startup.", "" ], + [ "z", "A dummy binary option.", "" ], + [ "baz <file>", "A long option with arg.", "" ], + [ "boz <file>", "Same as above with default value", "default.txt" ], + ] + +#Qt::Internal::setDebug Qt::QtDebugChannel::QTDB_ALL +# Qt.debug_level = Qt::DebugLevel::High + +about = KDE::AboutData.new("kludgeror", "Kludgeror", "0.1", "A basic web browser") +KDE::CmdLineArgs::init(ARGV, about) +KDE::CmdLineArgs::addCmdLineOptions opt +args = KDE::CmdLineArgs::parsedArgs + +a = KDE::Application.new # BUG, application shouldn't be needed at the top, lets fix this... + +class PartHolder < Qt::Object + signals "setLocBarText(const QString&)" + slots "reload()", "goToURL(const QString&)", "back()", "openURL(const KURL&)" # BUG - the slots should be normalize wrt spaces by the lib + + attr_accessor :part, :history + + def initialize part, *k + super(*k) + @part = part + @history = [] + end + + def openURL url + @part.openURL url + # BUG - a non existant slot emit says horrible things, nothing interesting for user.. very confusing + # BUG - signal emitting is *very* wrong + # emit setLocBarText(url.url) + @history.unshift url unless url == @history[0] + end + + def reload + @part.openURL @part.url + end + + def goToURL(url) + url = "http://#{url}" unless url =~ /^\w*:/ + openURL KDE::URL.new(url) + end + + def back + return unless @history.length > 1 + @history.shift + openURL @history[0] unless @history.empty? + end +end + +LOC_ED = 322 +ERASE_B = 323 +BACK_B = 324 + +url = (args.count > 1) ? args.url(0) : KDE::URL.new("http://loki:8080/xml/index.xml") + +puts "Dummy z option activated." if args.isSet "z" +puts "Dummy baz option has value: #{args.getOption "baz"}" if args.isSet "baz" +# puts "Dummy boz option has value: #{args.getOption "boz"}" if args.isSet "boz" # B0rked? + +toplevel = KDE::MainWindow.new +doc = KDE::HTMLPart.new toplevel, nil, toplevel, nil, 1 +# doc = KDE::HTMLPart.new toplevel, nil, toplevel, nil, 1 # KDE::HTMLPart::BrowserViewGUI +ph = PartHolder.new doc + +Qt::Object::connect doc.browserExtension, SIGNAL("openURLRequest(const KURL&, const KParts::URLArgs&)"), + ph, SLOT("openURL(const KURL&)") # BUG this slot must be screwing up wrt marshalling? + +ph.openURL url +toplevel.setCentralWidget doc.widget +toplevel.resize 700, 500 + +begin + d, viewMenu, fileMenu, locBar, e = nil + d = doc.domDocument + viewMenu = d.documentElement.firstChild.childNodes.item(2).toElement + e = d.createElement "action" + e.setAttribute "name", "debugRenderTree" + viewMenu.appendChild e + e = d.createElement "action" + e.setAttribute "name", "debugDOMTree" + viewMenu.appendChild e + fileMenu = d.documentElement.firstChild.firstChild.toElement + fileMenu.appendChild d.createElement("separator") + e = d.createElement "action" + e.setAttribute "name", "exit" + fileMenu.appendChild e + locBar = d.createElement "toolbar" + locBar.setAttribute "name", "locationBar" + e = d.createElement "action" + e.setAttribute "name", "reload" + locBar.appendChild e + d.documentElement.appendChild locBar +end + +a1 = KDE::Action.new( "Reload", "reload", KDE::Shortcut.new(Qt::Key_F5), ph, SLOT("reload()"), doc.actionCollection, "reload" ) +a2 = KDE::Action.new( "Exit", "exit", KDE::Shortcut.new(0), a, SLOT("quit()"), doc.actionCollection, "exit" ) + +toplevel.guiFactory.addClient doc + +locBar = toplevel.toolBar("locationBar"); +locBar.insertButton "back", BACK_B, SIGNAL("clicked()"), + ph, SLOT("back()"), true, "Go back" +locBar.insertLined url.url, LOC_ED, SIGNAL("returnPressed(const QString&)"), ph, SLOT("goToURL(const QString&)"), true, "Location" +locBar.insertButton "locationbar_erase", ERASE_B, SIGNAL("clicked()"), + locBar.getLined(LOC_ED), SLOT("clear()"), true, "Erase the location bar's content", 2 +locBar.setItemAutoSized LOC_ED, true +locBar.getLined(LOC_ED).createPopupMenu +comp = locBar.getLined(LOC_ED).completionObject +comp.setCompletionMode KDE::GlobalSettings::CompletionPopupAuto + +Qt::Object::connect(locBar.getLined(LOC_ED), SIGNAL("returnPressed(const QString&)"), + comp, SLOT("addItem(const QString&)")) +Qt::Object::connect(ph, SIGNAL("setLocBarText(const QString&)"), # BUG - once again... + locBar.getLined(LOC_ED), SLOT("setText(const QString&)")) + +doc.setJScriptEnabled true +doc.setJavaEnabled true +doc.setPluginsEnabled true +doc.setURLCursor Qt::Cursor.new(Qt::PointingHandCursor) + +a.setTopWidget doc.widget + +Qt::Object::connect doc, SIGNAL("setWindowCaption(const QString&)"), + doc.widget.topLevelWidget, SLOT("setCaption(const QString&)") +toplevel.show + +a.exec diff --git a/korundum/rubylib/examples/kurldemo.rb b/korundum/rubylib/examples/kurldemo.rb new file mode 100644 index 00000000..04fb9bce --- /dev/null +++ b/korundum/rubylib/examples/kurldemo.rb @@ -0,0 +1,110 @@ +=begin +This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale +=end + +=begin +Copyright 2003 Jim Bublitz + +Terms and Conditions + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +Except as contained in this notice, the name of the copyright holder shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from the +copyright holder. +=end + +require 'Korundum' + +class MainWin < KDE::MainWindow + def initialize(*args) + super + + @urls = ["http://slashdot.org", "http://www.kde.org", "http://www.riverbankcomputing.co.uk", "http://yahoo.com"] + setGeometry(0, 0, 400, 600) + + edit = KDE::TextEdit.new(self) + setCentralWidget(edit) + + edit.insert("KURL Demo\n") + edit.insert("\nAdding these urls:\n\n") + @urls.each do |url| + edit.insert(" #{url}\n") + end + + edit.insert("\nCreating KURLs (iterating to print):\n\n") + urlList = [] + @urls.each do |url| + urlList << KDE::URL.new(url) + end + + urlList.each do |url| + edit.insert(" #{url.url()}\n") + end + + edit.insert("\nFirst url -- urlList [0]:\n\n") + edit.insert(" #{urlList[0].to_s}\n") + edit.insert(" #{urlList[0].url()}\n") + + edit.insert("\nLast url -- urlList [-1]:\n\n") + edit.insert(" #{urlList[-1].to_s}\n") + edit.insert(" #{urlList[-1].url()}\n") + + edit.insert("\nMiddle urls -- urlList [2,4]:\n\n") + ulist = urlList[2,4] + ulist.each do |url| + edit.insert(" #{url.to_s}\n") + edit.insert(" #{url.url()}\n") + end + + edit.insert("\nLength of urlList -- len (urlList):\n\n") + edit.insert(" Length = #{urlList.length}\n") + + edit.insert("\nurl in urlList? -- KURL (\"http://yahoo.com\") in urlList\n\n") + edit.insert(" KDE::URL.new(\"http://yahoo.com\") in urlList = ") + tmp = KDE::URL.new("http://yahoo.com") + urlList.each do |url| + if url.url == tmp.url + edit.insert("true") + end + end + end +end + + +#-------------------- main ------------------------------------------------ + +description = "A basic application template" +version = "1.0" +aboutData = KDE::AboutData.new("", "", + version, description, KDE::AboutData::License_GPL, + "(C) 2003 whoever the author is") + +aboutData.addAuthor("author1", "whatever they did", "email@somedomain") +aboutData.addAuthor("author2", "they did something else", "another@email.address") + +KDE::CmdLineArgs.init(ARGV, aboutData) + +KDE::CmdLineArgs.addCmdLineOptions([["+files", "File to open", ""]]) + +app = KDE::Application.new() +mainWindow = MainWin.new(nil, "main window") +mainWindow.show() +app.exec() diff --git a/korundum/rubylib/examples/menudemo.rb b/korundum/rubylib/examples/menudemo.rb new file mode 100644 index 00000000..d5762ecd --- /dev/null +++ b/korundum/rubylib/examples/menudemo.rb @@ -0,0 +1,310 @@ +=begin +This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale +=end + +=begin +This template constructs an application with menus, toolbar and statusbar. +It uses KDE classes and methods that simplify the task of building and +operating a GUI. It is recommended that this approach be used, rather +than the primitive approach in menuapp1.py +=end + +=begin +Copyright 2003 Jim Bublitz + +Terms and Conditions + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +Except as contained in this notice, the name of the copyright holder shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from the +copyright holder. +=end + +require 'Korundum' +include KDE + +class MainWin < MainWindow + + slots 'slotNew()', 'slotOpen()', 'slotSave()', 'slotSaveAs()', 'slotPrint()', 'slotQuit()', 'slotUndo()', + 'slotRedo()', 'slotCut()', 'slotCopy()', 'slotPaste()', 'slotFind()', 'slotFindNext()', 'slotReplace()', + 'slotSpecial()', 'slotToggle2()', 'slotZoomIn()', 'slotZoomOut()' + + STATUSBAR_LEFT = 1 + STATUSBAR_MIDDLE = 2 + STATUSBAR_RIGHT = 3 + + def initialize(*args) + super + + initActions() + initMenus() + initToolBar() + initStatusBar() + + @saveAction.setEnabled(false) + @saveAsAction.setEnabled(false) + end + + def initActions() + # "File" menu items + @newAction = StdAction.openNew(self, SLOT('slotNew()'), actionCollection()) + @openAction = StdAction.open(self, SLOT('slotOpen()'), actionCollection()) + @saveAction = StdAction.save(self, SLOT('slotSave()'), actionCollection()) + @saveAsAction = StdAction.saveAs(self, SLOT('slotSaveAs()'), actionCollection()) + @printAction = StdAction.print(self, SLOT('slotPrint()'), actionCollection()) + @quitAction = StdAction.quit(self, SLOT('slotQuit()'), actionCollection()) + + # "Edit" menu items + @undoAction = StdAction.undo(self, SLOT('slotUndo()'), actionCollection()) + @redoAction = StdAction.redo(self, SLOT('slotRedo()'), actionCollection()) + @cutAction = StdAction.cut(self, SLOT('slotCut()'), actionCollection()) + @copyAction = StdAction.copy(self, SLOT('slotCopy()'), actionCollection()) + @pasteAction = StdAction.paste(self, SLOT('slotPaste()'), actionCollection()) + @findAction = StdAction.find(self, SLOT('slotFind()'), actionCollection()) + @findNextAction = StdAction.findNext(self, SLOT('slotFindNext()'), actionCollection()) + @replaceAction = StdAction.replace(self, SLOT('slotReplace()'), actionCollection()) + @specialAction = Action.new(i18n("Special"), Shortcut.new(), self, SLOT('slotSpecial()'), actionCollection(), "special") + + # Demo menu items + + # KToggleAction has an isChecked member and emits the "toggle" signal + @toggle1Action = ToggleAction.new("Toggle 1") + @toggle2Action = ToggleAction.new("Toggle 2", Shortcut.new(), self, SLOT('slotToggle2()'), nil) + + # A separator - create once/use everywhere + @separateAction = ActionSeparator.new() + + # Font stuff in menus or toolbar + @fontAction = FontAction.new("Font") + @fontSizeAction = FontSizeAction.new("Font Size") + + # Need to assign an icon to actionMenu below + icons = IconLoader.new() + iconSet = Qt::IconSet.new(icons.loadIcon("viewmag", Icon::Toolbar)) + + # Nested menus using KActions (also nested on toolbar) + @actionMenu = ActionMenu.new("Action Menu") + @actionMenu.setIconSet(iconSet) + @actionMenu.insert(StdAction.zoomIn(self, SLOT('slotZoomIn()'), actionCollection())) + @actionMenu.insert(StdAction.zoomOut(self, SLOT('slotZoomOut()'), actionCollection())) + + # Doesn't work in KDE 2.1.1 +# radio1Action = KRadioAction ("Radio 1") +# radio1Action.setExclusiveGroup ("Radio") +# radio2Action = KRadioAction ("Radio 2") +# radio2Action.setExclusiveGroup ("Radio") +# radio3Action = KRadioAction ("Radio 3") +# radio3Action.setExclusiveGroup ("Radio") + end + + def initMenus() + fileMenu = Qt::PopupMenu.new(self) + @newAction.plug(fileMenu) + @openAction.plug(fileMenu) + fileMenu.insertSeparator() + @saveAction.plug(fileMenu) + @saveAsAction.plug(fileMenu) + fileMenu.insertSeparator() + @printAction.plug(fileMenu) + fileMenu.insertSeparator() + @quitAction.plug(fileMenu) + menuBar().insertItem(i18n("&File"), fileMenu) + + editMenu = Qt::PopupMenu.new(self) + @undoAction.plug(editMenu) + @redoAction.plug(editMenu) + editMenu.insertSeparator() + @cutAction.plug(editMenu) + @copyAction.plug(editMenu) + @pasteAction.plug(editMenu) + editMenu.insertSeparator() + @findAction.plug(editMenu) + @findNextAction.plug(editMenu) + @replaceAction.plug(editMenu) + editMenu.insertSeparator() + @specialAction.plug(editMenu) + menuBar().insertItem(i18n("&Edit"), editMenu) + + demoMenu = Qt::PopupMenu.new(self) + @toggle1Action.plug(demoMenu) + @toggle2Action.plug(demoMenu) + @separateAction.plug(demoMenu) + @fontAction.plug(demoMenu) + @fontSizeAction.plug(demoMenu) + @actionMenu.plug(demoMenu) +# radio1Action.plug(demoMenu) +# radio2Action.plug(demoMenu) +# radio3Action.plug(demoMenu) + menuBar().insertItem(i18n("&Demo"), demoMenu) + + # This really belongs in Kicker, not here, + # but it actually works + # wlMenu = WindowListMenu.new(self) + # wlMenu.init() + # menuBar().insertItem(i18n("&WindowListMenu"), wlMenu) + + helpMenu = helpMenu("") + menuBar().insertItem(i18n("&Help"), helpMenu) + end + + def initToolBar() + @newAction.plug(toolBar()) + @openAction.plug(toolBar()) + @saveAction.plug(toolBar()) + @cutAction.plug(toolBar()) + @copyAction.plug(toolBar()) + @pasteAction.plug(toolBar()) + + @separateAction.plug(toolBar()) + @separateAction.plug(toolBar()) + @separateAction.plug(toolBar()) + + @fontAction.plug(toolBar()) + @separateAction.plug(toolBar()) + @fontAction.setComboWidth(150) + + @fontSizeAction.plug(toolBar()) + @fontSizeAction.setComboWidth(75) + + @separateAction.plug(toolBar()) + + # This works, but you have to hold down the + # button in the toolbar and wait a bit + @actionMenu.plug(toolBar()) + # This appears to do nothing + @actionMenu.setDelayed(false) + + # Need this to keep the font comboboxes from stretching + # to the full width of the toolbar when the window is + # maximized (comment out the next two lines to see + # what happens) + stretchlbl = Qt::Label.new("", toolBar()) + toolBar().setStretchableWidget(stretchlbl) + +# toolBar().setHorizontalStretchable(false) + end + + def initStatusBar() + statusBar().insertItem("", STATUSBAR_LEFT, 1000, true) + statusBar().insertItem("", STATUSBAR_MIDDLE, 1000, true) + statusBar().insertItem("", STATUSBAR_RIGHT, 1000, true) + end + +#-------------------- slots ----------------------------------------------- + + def slotNew(id = -1) + notImpl("New") + end + + def slotOpen(id = -1) + notImpl("Open") + end + + def slotSave(id = -1) + notImpl("Save") + end + + def slotSaveAs() + notImpl("Save As") + end + + def slotPrint() + notImpl("Print") + end + + def slotQuit() + notImpl("Quit") + end + + def slotUndo() + notImpl("Undo") + end + + def slotRedo() + notImpl("Redo") + end + + def slotCut (id = -1) + notImpl("Cut") + end + + def slotCopy(id = -1) + notImpl("Copy") + end + + def slotPaste(id = -1) + notImpl("Paste") + end + + def slotFind() + notImpl("Find") + end + + def slotFindNext() + notImpl("Find Next") + end + + def slotReplace() + notImpl("Replace") + end + + def slotSpecial() + notImpl("Special") + end + + def slotToggle2() + notImpl("Toggle") + end + + def slotZoomIn() + notImpl("Zoom In") + end + + def slotZoomOut() + notImpl("Zoom Out") + end + + def notImpl(item) + statusBar().changeItem("#{item} not implemented", STATUSBAR_LEFT) + MessageBox.error(self, "#{item} not implemented", "Not Implemented") + statusBar().changeItem("", STATUSBAR_LEFT) + end +end + +#-------------------- main ------------------------------------------------ + +description = "A basic application template" +version = "1.0" +aboutData = AboutData.new("menudemo", "MenuDemo", + version, description, AboutData::License_GPL, + "(C) 2003 whoever the author is") + +aboutData.addAuthor("author1", "whatever they did", "email@somedomain") +aboutData.addAuthor("author2", "they did something else", "another@email.address") + +CmdLineArgs.init(ARGV, aboutData) + +CmdLineArgs.addCmdLineOptions([["+files", "File to open", ""]]) + +app = Application.new() +mainWindow = MainWin.new(nil, "main window") +mainWindow.show() +app.exec() diff --git a/korundum/rubylib/examples/mimetype.rb b/korundum/rubylib/examples/mimetype.rb new file mode 100644 index 00000000..9f6db85f --- /dev/null +++ b/korundum/rubylib/examples/mimetype.rb @@ -0,0 +1,286 @@ +=begin +This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale +=end + +=begin +This program tests/demos some of the KSharedPtr related classes and +methods (KMimeType, KService, etc). It generally tests the *::List +methods for these classes (eg KService::List) since that also tests +the *::Ptr mapped type code (eg KService::Ptr) at the same time. + +This version is suitable for KDE >= 3.0.0 (some methods not available +in earlier versions) +=end + +=begin +Copyright 2003 Jim Bublitz + +Terms and Conditions + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +Except as contained in this notice, the name of the copyright holder shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from the +copyright holder. +=end + +require 'Korundum' +include KDE + +class MainWin < MainWindow + def initialize(*k) + super + + tabctl = KDE::TabCtl.new(self) + setGeometry(0, 0, 600, 400) + tabctl.setGeometry(10, 10, 550, 380) + + tabctl.addTab(KMimeTypeTab.new(tabctl), "KMimeType") + tabctl.addTab(KServiceTab.new(tabctl), "KService") + tabctl.addTab(KSycocaEntryTab.new(tabctl), "KSycocaEntry") + tabctl.addTab(KServiceTypeTab.new(tabctl), "KServiceType") + tabctl.addTab(OfferListTab.new(tabctl), "OfferList") + + tabctl.show() + end +end + + +class OfferListTab < Qt::Widget + def initialize(parent, name = "") + super(parent, name) + + setGeometry(0, 0, 500, 370) + lvLbl = Qt::Label.new("Offers - text/html", self) + lvLbl.setGeometry(10, 10, 150, 20) + + lv = Qt::ListView.new(self) + lv.setSorting(-1) + lv.addColumn("type", 75) + lv.addColumn("name", 100) + lv.addColumn("exec", 200) + lv.addColumn("library", 100) + lv.setGeometry(10, 30, 500, 300) + lv.setAllColumnsShowFocus(true) + + # insert list items in reverse order + + pref = KDE::ServiceTypeProfile.preferredService("Application", "image/jpeg") + Qt::ListViewItem.new(lv, pref.type(), pref.name(), pref.exec(), pref.library()) + Qt::ListViewItem.new(lv, "Preferred", "--------", "", "") + Qt::ListViewItem.new(lv, "", "", "", "") + + trader = KDE::Trader.self() + slist = trader.query("image/jpeg", "Type == 'Application'") +# print "KTrader returned:" + slist + slist.each do |s| + lvi = Qt::ListViewItem.new(lv, s.type(), s.name(), s.exec(), s.library()) + end + + lv.show() + end +end + +class KServiceTypeTab < Qt::Widget + def initialize(parent, name = "") + super(parent, name) + + setGeometry(0, 0, 500, 370) + lvLbl = Qt::Label.new("All Service Types", self) + lvLbl.setGeometry(10, 10, 250, 20) + + lv = Qt::ListView.new(self) + lv.addColumn("name", 150) + lv.addColumn("desktopEntryPath", 300) + lv.setGeometry(10, 30, 500, 300) + lv.setAllColumnsShowFocus(true) + + slist = KDE::ServiceType.allServiceTypes() + + slist.each do |s| + lvi = Qt::ListViewItem.new(lv, s.name(), s.desktopEntryPath()) + end + + lv.show() + end +end + +class KSycocaEntryTab < Qt::Widget + def initialize(parent, name = "") + super(parent, name) + + grp = KDE::ServiceGroup.baseGroup("screensavers") + if grp.nil? + return + end + setGeometry(0, 0, 500, 370) + lvLbl = Qt::Label.new("Entries - 'screensavers': " + grp.name(), self) + lvLbl.setGeometry(10, 10, 250, 20) + + lv = Qt::ListView.new(self) + lv.addColumn("name", 150) + lv.addColumn("entryPath", 300) + lv.setGeometry(10, 30, 500, 300) + lv.setAllColumnsShowFocus(true) + + slist = grp.entries(false, false) + + slist.each do |s| + lvi = Qt::ListViewItem.new(lv, s.name(), s.entryPath()) + end + + lv.show() + end +end + +class KServiceTab < Qt::Widget + def initialize(parent, name = "") + super(parent, name) + + setGeometry(0, 0, 500, 370) + lvLbl = Qt::Label.new("All Services", self) + lvLbl.setGeometry(10, 10, 150, 20) + + lv = Qt::ListView.new(self) + lv.addColumn("type", 75) + lv.addColumn("name", 100) + lv.addColumn("exec", 200) + lv.addColumn("library", 100) + lv.setGeometry(10, 30, 500, 300) + lv.setAllColumnsShowFocus(true) + + slist = KDE::Service.allServices() + slist.each do |s| + lvi = Qt::ListViewItem.new(lv, s.type(), s.name(), s.exec(), s.library()) + end + + lv.show() + end +end + +# svc = KService.serviceByDesktopName ("kcookiejar") +# print svc +# print svc.type_ () +# print svc.name ().latin1 () +# print svc.exec_ ().latin1 () +# print svc.library () + + +class KMimeTypeTab < Qt::Widget + def initialize(parent, name = "") + super(parent, name) + + setGeometry(0, 0, 500, 370) + lbLbl = Qt::Label.new("All Mimetypes", self) + lbLbl.setGeometry(10, 10, 150, 20) + lb = KDE::ListBox.new(self) + lb.setGeometry(10, 30, 200, 300) + mlist = KDE::MimeType.allMimeTypes() + lblist = [] + mlist.each do |mt| + lblist << mt.name() + end + + lblist.sort() + lb.insertStringList(lblist) + + lb.show() + + x = 250 + y = 10 + + mt = KDE::MimeType.mimeType("text/plain") + mtlbl = Qt::Label.new("KMimeType.mimeType('text/plain')", self) + mtlbl.setGeometry(x, y, 250, 20) + mtnamelbl = Qt::Label.new("name", self) + mtnamelbl.setGeometry(x + 15, y + 20, 100, 20) + mtname = Qt::Label.new(mt.name(), self) + mtname.setGeometry(x + 120, y + 20, 100, 20) + mtdesklbl = Qt::Label.new("desktopEntryPath", self) + mtdesklbl.setGeometry(x + 15, y + 40, 100, 20) + mtdesk = Qt::Label.new(mt.desktopEntryPath(), self) + mtdesk.setGeometry(x + 120, y + 40, 150, 20) + + y = y + 80 + + fp = KDE::MimeType.findByPath("mimetype.rb") + fplbl = Qt::Label.new("KDE::MimeType.findByPath('mimetype.rb')", self) + fplbl.setGeometry(x, y, 250, 20) + fpnamelbl = Qt::Label.new("name", self) + fpnamelbl.setGeometry(x + 15, y + 20, 100, 20) + fpname = Qt::Label.new(fp.name(), self) + fpname.setGeometry(x + 120, y + 20, 100, 20) + fpdesklbl = Qt::Label.new("desktopEntryPath", self) + fpdesklbl.setGeometry(x + 15, y + 40, 100, 20) + fpdesk = Qt::Label.new(fp.desktopEntryPath(), self) + fpdesk.setGeometry(x + 120, y + 40, 150, 20) + + y = y + 80 + + fu = KDE::MimeType.findByURL(KDE::URL.new("file://mimetype.rb")) + fulbl = Qt::Label.new("KDE::MimeType.findByURL('file://mimetype.rb')", self) + fulbl.setGeometry(x, y, 250, 20) + funamelbl = Qt::Label.new("name", self) + funamelbl.setGeometry(x + 15, y + 20, 100, 20) + funame = Qt::Label.new(fu.name(), self) + funame.setGeometry(x + 120, y + 20, 100, 20) + fudesklbl = Qt::Label.new("desktopEntryPath", self) + fudesklbl.setGeometry(x + 15, y + 40, 100, 20) + fudesk = Qt::Label.new(fu.desktopEntryPath(), self) + fudesk.setGeometry(x + 120, y + 40, 150, 20) + + y = y + 80 + + acc = Qt::Integer.new(0) # Create a mutable integer value to pass as an 'int*' arg + fc = KDE::MimeType.findByFileContent("mimetype.rb", acc) + fclbl = Qt::Label.new("KDE::MimeType.findByFileContent('mimetype.rb')", self) + fclbl.setGeometry(x, y, 250, 20) + fcnamelbl = Qt::Label.new("name", self) + fcnamelbl.setGeometry(x + 15, y + 20, 100, 20) + fcname = Qt::Label.new(fc.name(), self) + fcname.setGeometry(x + 120, y + 20, 100, 20) + fcdesklbl = Qt::Label.new("desktopEntryPath", self) + fcdesklbl.setGeometry(x + 15, y + 40, 100, 20) + fcdesk = Qt::Label.new(fc.desktopEntryPath(), self) + fcdesk.setGeometry(x + 120, y + 40, 100, 20) + fcacclbl = Qt::Label.new("accuracy", self) + fcacclbl.setGeometry(x + 15, y + 60, 100, 20) + fcacc = Qt::Label.new(acc.to_s, self) + fcacc.setGeometry(x + 120, y + 60, 150, 20) + end +end + + +#-------------------- main ------------------------------------------------ + +description = "Test/demo KSharedPtr related methods/classes" +version = "1.0" +aboutData = KDE::AboutData.new("mimetype", "MimeType", + version, description, KDE::AboutData.License_GPL, + "(C) 2003 Jim Bublitz") + +KDE::CmdLineArgs.init(ARGV, aboutData) + +KDE::CmdLineArgs.addCmdLineOptions([["+files", "File to open", ""]]) + +app = KDE::Application.new() +mainWindow = MainWin.new(nil, "main window") +mainWindow.show() +app.exec() diff --git a/korundum/rubylib/examples/rbKHTMLPart.rb b/korundum/rubylib/examples/rbKHTMLPart.rb new file mode 100644 index 00000000..e3beb927 --- /dev/null +++ b/korundum/rubylib/examples/rbKHTMLPart.rb @@ -0,0 +1,217 @@ +=begin +This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale +=end + +# +# pyParts.py (C) 2002 Jim Bublitz <jbublitz@nwinternet.com> +# + +=begin + +This is an extemely simple and crude example of using +a KHTMLPart - I put it together mostly to make sure +the openURL method worked correctly after some modifications +done in KParts::ReadOnlyPart. It took exactly four lines +added to a basic Korundum app framework to display a URL +via the 'net: + + w = KDE::HTMLPart.new(self, "HTMLPart", self) + w.openURL(KDE::URL.new("http://www.kde.org")) + w.view().setGeometry(30, 55, 500, 400) + w.show() + +You can play around with the commented out lines or add +additional code to make this do something useful. The +.rc for khtnmlpart (sorry, I never looked it up), doesn't +seem to provide much help. Also, to follow links, you +probably need to connect some signals to slots. I +haven't tried it, but this should work with a plain +KMainWindow or other widget too. + +The KDE website also incorporates gifs, jpegs, and +I believe CSS too. Playing around with some other +sites, it appears the font defaults could use some +improvement. + +NOTE!!! For this to work, you (obviously) need to have +a route to the internet established or specify a local +URL - PyKDE/KDE will take care of everything else. + +Perceptive users will notice the KHTMLPart code is +lifted from the KDE classref. + +=end + +require 'Korundum' + +# Note that we use KParts.MainWindow, not KMainWindow as the superclass +# (KParts.MainWindow subclasses KMainWindow). Also, be sure the 'apply' +# clause references KParts.MainWindow - it's a hard bug to track down +# if it doesn't. + +class RbPartsMW < KParts::MainWindow + slots 'close()', 'optionsShowToolbar()', 'optionsShowStatusbar()', 'optionsConfigureKeys()', + 'optionsConfigureToolbars()' + + TOOLBAR_EXIT = 0 + TOOLBAR_OPEN = 1 + + def initialize(*k) + super + + # Create the actions for our menu/toolbar to use + # Keep in mind that the part loaded will provide its + # own menu/toolbar entries + + # check out KParts.MainWindow's ancestry to see where + # some of this and later stuff (like self.actionCollection () ) + # comes from + + quitAction = KDE::StdAction.quit(self, SLOT('close()'), actionCollection()) + + createStandardStatusBarAction() +# @m_toolbarAction = KDE::StdAction.showToolbar(self, SLOT('optionsShowToolbar()'), actionCollection()) + @m_statusbarAction = KDE::StdAction.showStatusbar(self, SLOT('optionsShowStatusbar()'), actionCollection()) + + KDE::StdAction.keyBindings(self, SLOT('optionsConfigureKeys()'), actionCollection()) + KDE::StdAction.configureToolbars(self, SLOT('optionsConfigureToolbars()'), actionCollection()) + + path = Dir.getwd() + '/' + setGeometry(0, 0, 600, 500) + + # point to our XML file + setXMLFile(path + "rbParts.rc", false) + + # The next few lines are all that's necessary to + # create a web browser (of course you have to edit + # this file to change url's) + + w = KDE::HTMLPart.new(self, "HTMLPart", self) + w.openURL(KDE::URL.new("http://www.kde.org")) + + w.view().setGeometry(30, 55, 500, 400) + + +# self.v = KHTMLView (self.w, self) + +# self.setCentralWidget (self.v) + +# self.createGUI (self.w) + + w.show() + end + + + + + # slots for our actions + def optionsShowToolbar() + if @m_toolbarAction.isChecked() + toolBar().show() + else + toolBar().hide() + end + end + + def optionsShowStatusbar() + if @m_statusbarAction.isChecked() + statusBar().show() + else + statusBar().hide() + end + end + + + def optionsConfigureKeys() + KDE::KeyDialog.configureActionKeys(actionCollection(), xmlFile()) + end + + + def optionsConfigureToolbars() + dlg = KDE::EditToolbar.new(actionCollection(), xmlFile()) + if dlg.exec() + createGUI(self) + end + end + + + # some boilerplate left over from pyKLess/KLess + def queryClose() + res = KDE::MessageBox.warningYesNoCancel(self, + i18n("Save changes to Document?<br>(Does not make sense, we know, but it is just a programming example :-)")) + if res == KDE::MessageBox::Yes + #// save document here. If saving fails, return FALSE + return true + + elsif res == KDE::MessageBox::No + return true + + else #// cancel + return false + end + end + + def queryExit() + #// this slot is invoked in addition when the *last* window is going + #// to be closed. We could do some final cleanup here. + return true #// accept + end + + # I'm not sure the session mgmt stuff here works + + # Session management: save data + def saveProperties(config) + # This is provided just as an example. + # It is generally not so good to save the raw contents of an application + # in its configuration file (as this example does). + # It is preferable to save the contents in a file on the application's + # data zone and save an URL to it in the configuration resource. + config.writeEntry("text", edit.text()) + end + + + # Session management: read data again + def readProperties(config) + # See above + edit.setText(config.readEntry("text")) + end +end + + +#------------- main ---------------------------- + +# A Human readable description of your program +description = "KHTMLPart - simple example" +# The version +version = "0.1" + +# stuff for the "About" menu +aboutData = KDE::AboutData.new("rbKHTMLPart", "rbHTMLPart", + version, description, KDE::AboutData::License_GPL, + "(c) 2002, Jim Bublitz") + +aboutData.addAuthor("Jim Bublitz", "Example for PyKDE", "jbublitz@nwinternet.com") +aboutData.addAuthor('Richard Dale', 'Example for Korundum', 'Richard_Dale@tipitina.demon.co.uk') + +# This MUST go here (before KApplication () is called) +KDE::CmdLineArgs.init(ARGV, aboutData) + +app = KDE::Application.new() + +if app.isRestored() + KDE::MainWindow.kRestoreMainWindows(RbPartsMW) +else + # no session management: just create one window + # this is our KParts::MainWindow derived class + parts = RbPartsMW.new(nil, "rbParts") + if ARGV.length > 1 + # read kcmdlineargs.h for the full unabridged instructions + # on using KCmdLineArgs, it's pretty confusing at first, but it works + # This is pretty useless in this program - you might want to + # expand this in your app (to load a file, etc) + args = KDE::CmdLineArgs.parsedArgs() + end +end + +parts.show() +app.exec() diff --git a/korundum/rubylib/examples/rbtestimage.png b/korundum/rubylib/examples/rbtestimage.png Binary files differnew file mode 100644 index 00000000..550371b1 --- /dev/null +++ b/korundum/rubylib/examples/rbtestimage.png diff --git a/korundum/rubylib/examples/systray.rb b/korundum/rubylib/examples/systray.rb new file mode 100644 index 00000000..85b27366 --- /dev/null +++ b/korundum/rubylib/examples/systray.rb @@ -0,0 +1,66 @@ +=begin +This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale +=end + +=begin +Copyright 2003 Jim Bublitz + +Terms and Conditions + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +Except as contained in this notice, the name of the copyright holder shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from the +copyright holder. +=end + +require 'Korundum' + +class MainWin < KDE::MainWindow + def initialize(*args) + super + end +end + +#-------------------- main ------------------------------------------------ + +appName = "template" + +aboutData = KDE::AboutData.new("systry", "Systray test",\ + "0.1", "Systray test", KDE::AboutData::License_GPL,\ + "(c) 2002, Jim Bublitz") + +aboutData.addAuthor('Jim Bublitz', 'Example for PyKDE', 'jbublitz@nwinternet.com') +aboutData.addAuthor('Richard Dale', 'For Korundum', 'Richard_Dale@tipitina.demon.co.uk') + +# This MUST go here (before KApplication () is called) +KDE::CmdLineArgs.init(ARGV, aboutData) +app = KDE::Application.new() +mainWindow = MainWin.new(nil, "main window") +icons = KDE::IconLoader.new() + +systray = KDE::SystemTray.new(mainWindow) +systray.setPixmap(icons.loadIcon("stop", 0)) +systray.show() + +#mainWindow.show() +app.exec() + + diff --git a/korundum/rubylib/examples/uikmdi.rb b/korundum/rubylib/examples/uikmdi.rb new file mode 100644 index 00000000..df7d0e1d --- /dev/null +++ b/korundum/rubylib/examples/uikmdi.rb @@ -0,0 +1,187 @@ + +=begin +This is a ruby version of Jim Bublitz's python original. The ruby behaviour +is 'crash for crash' identical - so the the problems described below are +related to KMDI, and not the bindings. +=end + +=begin +A rough Python translation of the ideas presented in this KMDI tutorial: + + http://web.tiscali.it/andreabergia/kmditutorial.html + +What does work: + + IDEAlMode - yay! + + Adding and closing child views + + Two-way syncing between a tool widget and a matching child view + +All is not rosy, however: + + Instances of the KmdiExample maintain a dictionary of child views. Values + cannot be deleted from this dictionary during a window close (causes an + immediate segfault). + + Child views created after initialization aren't numbered correctly; given + the first problem, it's harder to do this than it's really worth. + + The example segfaults at shutdown if the tool (on the left) is is open but + is not in overlap-mode. + +=end + +require 'Korundum' +include KDE + +class KmdiExample < KDE::MdiMainFrm + + slots 'closeChild(KMdiChildView*)', + 'syncFromChildView(KMdiChildView*)', + 'syncFromMainTool(QListBoxItem*)', + 'activatedMessage(KMdiChildView*)', + 'newView()', 'close()', 'closeActiveChild()' + + def getIcon(name, group=Icon::NoGroup, size=Icon::SizeSmall) + # returns a kde icon by name + return Global.instance().iconLoader().loadIcon(name, group, size) + end + + def initialize(parent=nil) + super(parent, 'KmdiExample', Mdi::IDEAlMode) + + @viewIcons = ['network', 'email', 'stop', 'back', 'forward'] + @toolIcons = ['view_icon', 'configure'] + + openNewAction = StdAction.openNew(self, SLOT('newView()'), actionCollection()) + quitAction = StdAction.quit(self, SLOT('close()'), actionCollection()) + closeAction = StdAction.close(self, SLOT('closeActiveChild()'), actionCollection()) + + uifilebase = Dir.getwd + '/uikmdi.rc' + createGUI(uifilebase) + # The task bar is created in the KMdiMainFrm constructor + # and then deleted in the createGUI() call above.. + # So recreate it again to avoid a crash. + createTaskBar() + statusBar() + resize(400, 300) + + @tools = {} + @toolIcons.each_index do |idx| + ico = @toolIcons[idx] + wid = KDE::ListBox.new(self, "list#{idx.to_s}") + makeTool(wid, "Tool #{idx.to_s}", ico) + end + ## smells + @mainToolWidget = @maintool = @tools['Tool 0'][0] + + @childs = {} + @viewIcons.each_index do |idx| + ico = @viewIcons[idx] + makeView("View #{idx.to_s}", ico, ico) + end + + connect(self, SIGNAL('viewActivated(KMdiChildView*)'), self, SLOT('activatedMessage(KMdiChildView*)')) + connect(self, SIGNAL('viewActivated(KMdiChildView*)'), self, SLOT('syncFromChildView(KMdiChildView*)')) + connect(@maintool, SIGNAL('selectionChanged(QListBoxItem*)'), self, SLOT('syncFromMainTool(QListBoxItem*)')) + syncFromChildView(activeWindow()) + end + + def syncFromMainTool(item) + # activate the view that matches the item text + activateView(findWindow(item.text())) + end + + def syncFromChildView(child) + # sync the main tool to the indicated child + @maintool = @mainToolWidget + if child.nil? + return + end + item = @maintool.findItem(child.tabCaption()) + if !item.nil? + @maintool.setSelected(item, nil) + end + end + + def makeTool(widget, caption, icon, percent=50) + # makes a tool from the widget + tip = i18n("#{caption} Tool Tip") + dock = DockWidget::DockLeft + maindock = getMainDockWidget() + widget.setIcon(getIcon(icon)) + tool = addToolWindow(widget, dock, maindock, percent, tip, caption) + @tools[caption] = [widget, tool] + end + + def makeView(label, icon, text) + # makes a child view with a text label and a pixmap label + view = MdiChildView.new(label, self) + @childs[label] = view + view.setIcon(getIcon(icon)) + layout = Qt::VBoxLayout.new(view) + layout.setAutoAdd(true) + + lbl = Qt::Label.new(i18n("Label for a view with an icon named #{text}"), view) + pxm = Qt::Label.new('', view) + pxm.setPixmap(getIcon(icon, Icon::NoGroup, KDE::Icon::SizeLarge)) + addWindow(view) + @mainToolWidget.insertItem(label) + connect(view, SIGNAL('childWindowCloseRequest(KMdiChildView*)'), self, SLOT('closeChild(KMdiChildView*)')) + end + + def removeMainToolItem(view) + # remove item from the main list tool that corresponds to the view + @maintool = @mainToolWidget + @maintool.takeItem(@maintool.findItem(view.tabCaption(), 0)) + end + + def newView() + # make a view when the user invokes the new action + makeView("View ", 'network', 'A Fresh View') +# makeView("View #{@childs.length}", 'network', 'A Fresh View') + syncFromChildView(activeWindow()) + end + + def closeActiveChild() + # close the current view + removeMainToolItem(activeWindow()) + closeActiveView() + syncFromChildView(activeWindow()) + end + + def closeChild(which) + # called to close a view from its tab close button + caption = which.tabCaption() + removeMainToolItem(which) + which.close() + statusBar().message(i18n("#{caption} closed")) + syncFromChildView(activeWindow()) + end + + def activatedMessage(view) + # updates the status bar with the caption of the current view + statusBar().message(i18n("#{view.tabCaption()} activated")) + end +end + +if $0 == __FILE__ + aname = 'uikmdi' + desc = 'A Simple Korundum KMDI Sample' + ver = '1.0' + lic = AboutData::License_GPL + author = 'Troy Melhase' + authormail = 'troy@gci.net' + + about = AboutData.new(aname, aname, ver, desc, lic, "#{authormail} (c) 2004") + about.addAuthor(author, 'hi, mom!', authormail) + about.addAuthor('Jim Bublitz', 'For PyKDE', 'jbublitz@nwinternet.com') + about.addAuthor('Richard Dale', 'For Korundum', 'Richard_Dale@tipitina.demon.co.uk') + CmdLineArgs.init(ARGV, about) + app = KDE::Application.new + mainWindow = KmdiExample.new + mainWindow.show + app.exec +end + diff --git a/korundum/rubylib/examples/uikmdi.rc b/korundum/rubylib/examples/uikmdi.rc new file mode 100644 index 00000000..a7e21969 --- /dev/null +++ b/korundum/rubylib/examples/uikmdi.rc @@ -0,0 +1,11 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui name="testfoo" version="1"> +<MenuBar> + +<!-- <Menu name="custom"><text>C&ustom</text> + <Action name="custom_action" /> + </Menu> +--> + +</MenuBar> +</kpartgui> diff --git a/korundum/rubylib/examples/uimodules/uidialogs.rb b/korundum/rubylib/examples/uimodules/uidialogs.rb new file mode 100644 index 00000000..2d264a4b --- /dev/null +++ b/korundum/rubylib/examples/uimodules/uidialogs.rb @@ -0,0 +1,256 @@ +=begin +This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale +=end + +require 'Korundum' + +module UIDialogs + +class CustomDlg < KDE::Dialog + + slots 'dlgClicked()', 'okClicked()', 'cancelClicked()' + + def initialize(parent, name = "custom dlg", modal = false) + super(parent, name, modal) + + x = 20 + y = 10 + + rLbl = Qt::Label.new("r", self) + gLbl = Qt::Label.new("g", self) + bLbl = Qt::Label.new("b", self) + @rEd = Qt::LineEdit.new("64", self) + @gEd = Qt::LineEdit.new("64", self) + @bEd = Qt::LineEdit.new("64", self) + dlgBtn = Qt::PushButton.new("Set/Get Color", self) + okBtn = Qt::PushButton.new("OK", self) + canBtn = Qt::PushButton.new("Cancel", self) + + rLbl.setGeometry(x, y, 25, 20) + gLbl.setGeometry(x + 30, y, 25, 20) + bLbl.setGeometry(x + 60, y, 25, 20) + y = y + 20 + @rEd.setGeometry(x, y, 25, 20) + @gEd.setGeometry(x + 30, y, 25, 20) + @bEd.setGeometry(x + 60, y, 25, 20) + y = y + 30 + dlgBtn.setGeometry(x, y, 90, 22) + y = y + 30 + okBtn.setGeometry(x, y, 40, 22) + canBtn.setGeometry(x + 50, y, 40, 22) + + connect(dlgBtn, SIGNAL("clicked()"), SLOT('dlgClicked()')) + connect(okBtn, SIGNAL("clicked()"), SLOT('okClicked()')) + connect(canBtn, SIGNAL("clicked()"), SLOT('cancelClicked()')) + end + + def dlgClicked() + # get some(numerical) color values from the original dialog + red = @rEd.text().to_i + green = @gEd.text().to_i + blue = @bEd.text().to_I + + # convert the numbers to a Qt::Color + color = Qt::Color.new(red, green, blue) + + # invoke the dialog(getColor is a 'static' call) + # initialize with the colors from above(in color) + # color will also hold the new value chosen in the + # KDE::ColorDialog + result = KDE::ColorDialog.getColor(color, self) + + # get the numerical color values back +# red, green, blue = color.rgb() + + # update the Qt::LineEdits in the original dialog + @rEd.setText(red.to_s) + @gEd.setText(green.to_s) + @bEd.setText(blue.to_s) + end + + def okClicked() + done(1) + end + + def cancelClicked() + done(0) + end +end + +class MessageDlg < KDE::Dialog + + slots 'launch(int)' + + def initialize(parent, name = "message dlg", modal = false) + super(parent, name, modal) + + buttons = ["QuestionYesNo", "WarningYesNo", "WarningContinueCancel", "WarningYesNoCancel", + "Information", "SSLMessageBox", "Sorry", "Error", "QuestionYesNoCancel"] + + n = buttons.length + + grp = Qt::ButtonGroup.new(n, Qt::Vertical, "MessageBoxes", self, "button grp") + grp.setGeometry(10, 10, 200, 30*n) + (0...n).each { |i| Qt::RadioButton.new(buttons[i], grp) } + + connect(grp, SIGNAL("clicked(int)"), SLOT('launch(int)')) + end + + def launch(which) + which += 1 # Qt::ButtonGroup id's start at 0, but the KDE::MessageBox enum starts at 1 + + if which == KDE::MessageBox::QuestionYesNo + KDE::MessageBox.questionYesNo(self, "This is a questionYesNo message box\nThere is also a list version of this dialog",\ + "questionYesNo") + + elsif which == KDE::MessageBox::WarningYesNo + KDE::MessageBox.warningYesNo(self, "This is a warningYesNo message box", "warningYesNo") + + elsif which == KDE::MessageBox::WarningContinueCancel + KDE::MessageBox.warningContinueCancel(self, "This is a warningContinueCancel message box", "warningContinueCancel"); + + elsif which == KDE::MessageBox::WarningYesNoCancel + KDE::MessageBox.warningYesNoCancel(self, "This is a warningYesNoCancel message box", "warningYesNoCancel") + + elsif which == KDE::MessageBox::Information + KDE::MessageBox.information(self, "This is an information message box", "Information") + +# elsif which == KDE::MessageBox::SSLMessageBox +# KDE::MessageBox.SSLMessageBox(self, "This is an SSLMessageBox message box", "not implemented yet") + + elsif which == KDE::MessageBox::Sorry + KDE::MessageBox.sorry(self, "This is a 'sorry' message box", "Sorry") + + elsif which == KDE::MessageBox::Error + KDE::MessageBox.error(self, "No - this isn't really an error\nIt's an error message box\n", "Error") + + elsif which == KDE::MessageBox::QuestionYesNoCancel + KDE::MessageBox.questionYesNoCancel(self, "No - this isn't really an error\nIt's an QuestionYesNoCancel message box\n", "QuestionYesNoCancel") + end + end +end + + +def UIDialogs.dlgKAboutDialog(parent) + dlg = KDE::AboutDialog.new(parent, 'about dialog', false) + dlg.setLogo(Qt::Pixmap.new("rbtestimage.png")) + dlg.setTitle("UISampler for Korundum") + dlg.setAuthor("Jim Bublitz", "jbublitz@nwinternet.com", "http://www.riverbankcomputing.co.uk", + "\n\nPyKDE -- Python bindings\n\tfor KDE") + dlg.setMaintainer("Richard Dale", "Richard_Dale@tipitina.demon.co.uk", "http://developer.kde.org/language-bindings/ruby/",\ + "\n\nKorundum -- Ruby bindings\n\tfor KDE") + dlg.addContributor("KDE bindings list", "kde-bindings@kde.org", nil, nil) + + dlg.show() +end + + +def UIDialogs.dlgKBugReport(parent) + dlg = KDE::BugReport.new(parent) + dlg.exec() +end + +def UIDialogs.dlgKAboutKDE(parent) + dlg = KDE::AboutKDE.new(parent, "about kde", false) + dlg.show() +end + +def UIDialogs.dlgKColorDialog(parent) + dlg = KDE::ColorDialog.new(parent, "color dlg", false) + dlg.show() +end + +def UIDialogs.dlgKDialog(parent) + dlg = CustomDlg.new(parent) + dlg.show() +end + +def UIDialogs.dlgKDialogBase(parent) + caption = "KDialogBase sample" + text_ = "This is a KDialogBase example" + dlg = KDE::DialogBase.new(parent, "sample_dialog", false, caption, + KDE::DialogBase::Ok | KDE::DialogBase::Cancel, KDE::DialogBase::Ok, true ) + + page = dlg.makeVBoxMainWidget(); + + # making 'page' the parent inserts the widgets in + # the VBox created above + label = Qt::Label.new( caption, page, "caption" ); + + lineedit = Qt::LineEdit.new(text_, page, "lineedit" ); + lineedit.setMinimumWidth(dlg.fontMetrics().maxWidth()*20); + + label0 = Qt::Label.new("Border widths", page) +# widths = dlg.getBorderWidths() +# labelA = Qt::Label.new("Upper Left X: " + widths[0].to_s, page) +# labelB = Qt::Label.new("Upper Left Y: " + widths[0].to_s, page) +# labelC = Qt::Label.new("Lower Right X: " + str(c), page) +# labelD = Qt::Label.new("Lower Right Y: " + str(d), page) + + dlg.show() +end + +def UIDialogs.dlgKFontDialog(parent) + dlg = KDE::FontDialog.new(parent, "font dlg", false, false) + dlg.show() +end + +def UIDialogs.dlgKKeyDialog(parent) + # This really doesn't do anything except pop up the dlg + keys = KDE::Accel.new(parent) +# keys.insertItem( i18n( "Zoom in" ), "Zoom in", "+" ) + keys.readSettings(); + KDE::KeyDialog.configure(keys, true) +end + +def UIDialogs.dlgKInputDialog(parent) + ok = Qt::Boolean.new + result = KDE::InputDialog.getText("Enter text", "", "<Your input here>", ok) +# puts "result: %s" % result +# puts "ok: %s" % ok + + # pop up another dlg to show what happened in the KDE::LineEditDlg + if !ok.nil? + KDE::MessageBox.information(parent, "OK was pressed\nText: " + result, "KDE::InputDialog result") + else + KDE::MessageBox.information(parent, "Cancel pressed\nText", "KDE::InputDialog result") + end +end + +def UIDialogs.dlgKMessageBox(parent) + dlg = MessageDlg.new(parent) + dlg.show() +end + +def UIDialogs.dlgKPasswordDialog(parent) + password = "" + result = KDE::PasswordDialog.getPassword(password, "Enter password(just a test)") + puts "password: #{password}" +end + +def UIDialogs.dlgKWizard(parent) + wiz = KDE::Wizard.new(parent) + + page1 = Qt::Widget.new(wiz) + p1Lbl = Qt::Label.new("This is page 1", page1) + p1Lbl.setGeometry(20, 20, 100, 20) + page2 = Qt::Widget.new(wiz) + p2Lbl = Qt::Label.new("This is page 2", page2) + p2Lbl.setGeometry(50, 20, 100, 20) + page3 = Qt::Widget.new(wiz) + p3Lbl = Qt::Label.new("This is page 3", page3) + p3Lbl.setGeometry(80, 20, 100, 20) + + wiz.addPage(page1, "Page 1") + wiz.addPage(page2, "Page 2") + wiz.addPage(page3, "Page 3") + wiz.show() +end + +if $0 == __FILE__ + puts + puts "Please run uisampler.rb" + puts +end + +end diff --git a/korundum/rubylib/examples/uimodules/uimenus.rb b/korundum/rubylib/examples/uimodules/uimenus.rb new file mode 100644 index 00000000..4a8ff523 --- /dev/null +++ b/korundum/rubylib/examples/uimodules/uimenus.rb @@ -0,0 +1,137 @@ +=begin +This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale +=end + +require 'Korundum' + +module UIMenus + +class PageLaunch + def initialize(parent) + page = parent.addPage() + + x = 10 + y = 10 + + launchLbl = Qt::Label.new("Launching application ... please wait\n\nClose launched application to continue", page) + launchLbl.setGeometry(x, y, 300, 80) + launchLbl.show() + + page.show() + + $kapp.processEvents() + end +end + + +class PageNotImpl + def initialize(parent) + page = parent.addPage() + + x = 10 + y = 10 + + niLbl = Qt::Label.new("Nothing is currently implemented for this widget", page) + niLbl.setGeometry(x, y, 300, 20) + niLbl.show() + end +end + +def UIMenus.menuKAccelGen(parent) + parent.currentPageObj = PageNotImpl.new(parent) +end + +def UIMenus.menuKAccelMenu(parent) + parent.currentPageObj = PageNotImpl.new(parent) +end + +def UIMenus.menuKAction(parent) + parent.currentPageObj = PageLaunch.new(parent) + system("ruby menudemo.rb") +end + +def UIMenus.menuKActionMenu(parent) + parent.currentPageObj = PageLaunch.new(parent) + system("ruby menudemo.rb") +end + +def UIMenus.menuKActionSeparator(parent) + parent.currentPageObj = PageLaunch.new(parent) + system("ruby menudemo.rb") +end + +def UIMenus.menuKContextMenuManager(parent) +# pass +end + +def UIMenus.menuKDCOPActionProxy(parent) +# pass +end + +def UIMenus.menuKHelpMenu(parent) + parent.currentPageObj = PageLaunch.new(parent) + system("ruby menudemo.rb") +end + +def UIMenus.menuKMenuBar(parent) + parent.currentPageObj = PageLaunch.new(parent) + system("ruby menudemo.rb") +end + +def UIMenus.menuKPanelApplet(parent) + parent.currentPageObj = PageNotImpl.new(parent) +end + +def UIMenus.menuKPanelExtension(parent) + parent.currentPageObj = PageNotImpl.new(parent) +end + +def UIMenus.menuKPanelMenu(parent) + parent.currentPageObj = PageNotImpl.new(parent) +end + +def UIMenus.menuKPopupFrame(parent) +# pass +end + +def UIMenus.menuKPopupMenu(parent) +# pass +end + +def UIMenus.menuKPopupTitle(parent) +# pass +end + +def UIMenus.menuKStatusBar(parent) + parent.currentPageObj = PageLaunch.new(parent) + system("ruby menudemo.rb") +end + +def UIMenus.menuKStatusBarLabel(parent) + parent.currentPageObj = PageLaunch.new(parent) + system("ruby menudemo.rb") +end + +def UIMenus.menuKStdAction(parent) + parent.currentPageObj = PageLaunch.new(parent) + system("ruby menudemo.rb") +end + +def UIMenus.menuKToolBar(parent) + parent.currentPageObj = PageLaunch.new(parent) + system("ruby menudemo.rb") +end + +def UIMenus.menuKWindowListMenu(parent) +# pass +end + + +if $0 == __FILE__ + puts + puts "Please run uisampler.rb" + puts +end + +end + diff --git a/korundum/rubylib/examples/uimodules/uimisc.rb b/korundum/rubylib/examples/uimodules/uimisc.rb new file mode 100644 index 00000000..f9d70161 --- /dev/null +++ b/korundum/rubylib/examples/uimodules/uimisc.rb @@ -0,0 +1,273 @@ +=begin +This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale +=end + +require 'Korundum' + +module UIMisc + +class Page3 < Qt::Object + slots 'ivChanged()', 'fvChanged()', 'dvChanged()' + + def initialize(parent) + super + page = parent.addPage() + x = 10 + y = 15 + + green = Qt::Color.new(0, 255, 0) + yellow = Qt::Color.new(255, 255, 0) + red = Qt::Color.new(255, 0, 0) + + ivLbl = Qt::Label.new("KIntValidator", page) + ivLbl.setGeometry(x, y, 100, 20) + ivLbl.show() + + @iv = KDE::LineEdit.new(page) + @iv.setGeometry(x, y + 20, 100, 20) + @iv.show() + connect(@iv, SIGNAL("textChanged(const QString&)"), SLOT('ivChanged()')) + + @ivVal = KDE::IntValidator.new(page) + @ivVal.setRange(20, 50) + + ivRngLbl = Qt::Label.new("Range is 20 - 50", page) + ivRngLbl.setGeometry(x, y + 45, 100, 20) + ivRngLbl.show() + + ivAccLbl = Qt::Label.new("Acceptable", page) + ivAccLbl.setGeometry(x + 125, y + 45, 85, 20) + ivAccLbl.show() + ivInterLbl = Qt::Label.new("Intermediate", page) + ivInterLbl.setGeometry(x + 125, y + 20, 85, 20) + ivInterLbl.show() + ivInvalLbl = Qt::Label.new("Invalid", page) + ivInvalLbl.setGeometry(x + 125, y - 5, 85, 20) + ivInvalLbl.show() + @ivInvalLed = KDE::Led.new(red, KDE::Led::Off, KDE::Led::Sunken, KDE::Led::Circular,page) + @ivInvalLed.setGeometry(x + 215, y - 5, 18, 18) + @ivInvalLed.show() + @ivInterLed = KDE::Led.new(yellow, KDE::Led::Off, KDE::Led::Sunken, KDE::Led::Circular,page) + @ivInterLed.setGeometry(x + 215, y + 20, 18, 18) + @ivInterLed.show() + @ivAccLed = KDE::Led.new(green, KDE::Led::On, KDE::Led::Sunken, KDE::Led::Circular,page) + @ivAccLed.setGeometry(x + 215, y + 45, 18, 18) + @ivAccLed.show() + + y = y + 100 + + fvLbl = Qt::Label.new("KDoubleValidator", page) + fvLbl.setGeometry(x, y, 100, 20) + fvLbl.show() + + @fv = KDE::LineEdit.new(page) + @fv.setGeometry(x, y + 20, 100, 20) + @fv.show() + connect(@fv, SIGNAL("textChanged(const QString&)"), SLOT('fvChanged()')) + + @fvVal = KDE::DoubleValidator.new(page) + @fvVal.setRange(10.0, 40.0) + + fvRngLbl = Qt::Label.new("Range is 10.0 - 40.0", page) + fvRngLbl.setGeometry(x, y + 45, 100, 20) + fvRngLbl.show() + + fvAccLbl = Qt::Label.new("Acceptable", page) + fvAccLbl.setGeometry(x + 125, y + 45, 85, 20) + fvAccLbl.show() + fvInterLbl = Qt::Label.new("Intermediate", page) + fvInterLbl.setGeometry(x + 125, y + 20, 95, 20) + fvInterLbl.show() + fvInvalLbl = Qt::Label.new("Invalid", page) + fvInvalLbl.setGeometry(x + 125, y - 5, 85, 20) + fvInvalLbl.show() + @fvInvalLed = KDE::Led.new(red, KDE::Led::Off, KDE::Led::Sunken, KDE::Led::Circular,page) + @fvInvalLed.setGeometry(x + 215, y - 5, 18, 18) + @fvInvalLed.show() + @fvInterLed = KDE::Led.new(yellow, KDE::Led::Off, KDE::Led::Sunken, KDE::Led::Circular,page) + @fvInterLed.setGeometry(x + 215, y + 20, 18, 18) + @fvInterLed.show() + @fvAccLed = KDE::Led.new(green, KDE::Led::On, KDE::Led::Sunken, KDE::Led::Circular,page) + @fvAccLed.setGeometry(x + 215, y + 45, 18, 18) + @fvAccLed.show() + + y = y + 100 + + dvLbl = Qt::Label.new("KDateValidator", page) + dvLbl.setGeometry(x, y, 100, 20) + dvLbl.show() + + @dv = KDE::LineEdit.new(page) + @dv.setGeometry(x, y + 20, 100, 20) + @dv.show() +# connect(dv, SIGNAL("textChanged(const QString&)"), SLOT('dvChanged()')) + + @dvVal = KDE::DateValidator.new(page) +# dvVal.setRange(10.0, 40.0) + +# dvRngLbl = Qt::Label.new("Range is 10.0 - 40.0", page) +# dvRngLbl.setGeometry(x, y + 45, 100, 20) +# dvRngLbl.show() + + dvBtn = Qt::PushButton.new("Validate", page) + dvBtn.setGeometry(x, y + 45, 60, 22) + dvBtn.show() + connect(dvBtn, SIGNAL("clicked()"), SLOT('dvChanged()')) + + dvNoteLbl = Qt::Label.new("Format is locale dependent\nShort date only\nTry DD-MM-YY", page) + dvNoteLbl.setGeometry(x, y + 70, 150, 60) + dvNoteLbl.show() + + dvAccLbl = Qt::Label.new("Acceptable", page) + dvAccLbl.setGeometry(x + 125, y + 45, 85, 20) + dvAccLbl.show() + dvInterLbl = Qt::Label.new("Intermediate", page) + dvInterLbl.setGeometry(x + 125, y + 20, 85, 20) + dvInterLbl.show() + dvInvalLbl = Qt::Label.new("Invalid", page) + dvInvalLbl.setGeometry(x + 125, y - 5, 85, 20) + dvInvalLbl.show() + @dvInvalLed = KDE::Led.new(red, KDE::Led::Off, KDE::Led::Sunken, KDE::Led::Circular,page) + @dvInvalLed.setGeometry(x + 215, y - 5, 18, 18) + @dvInvalLed.show() + @dvInterLed = KDE::Led.new(yellow, KDE::Led::Off, KDE::Led::Sunken, KDE::Led::Circular,page) + @dvInterLed.setGeometry(x + 215, y + 20, 18, 18) + @dvInterLed.show() + @dvAccLed = KDE::Led.new(green, KDE::Led::On, KDE::Led::Sunken, KDE::Led::Circular,page) + @dvAccLed.setGeometry(x + 215, y + 45, 18, 18) + @dvAccLed.show() + end + + def ivChanged() + @ivInvalLed.off() + @ivInterLed.off() + @ivAccLed.off() + + i = Qt::Integer.new(0) + state = @ivVal.validate(@iv.text(), i) + + if state == Qt::Validator::Acceptable + @ivAccLed.on() + elsif state == Qt::Validator::Intermediate + @ivInterLed.on() + else + @ivInvalLed.on() + end + end + + def fvChanged() + @fvInvalLed.off() + @fvInterLed.off() + @fvAccLed.off() + + i = Qt::Integer.new(0) + state = @fvVal.validate(@fv.text(), i) + + if state == Qt::Validator::Acceptable + @fvAccLed.on() + elsif state == Qt::Validator::Intermediate + @fvInterLed.on() + else + @fvInvalLed.on() + end + end + + def dvChanged() + @dvInvalLed.off() + @dvInterLed.off() + @dvAccLed.off() + + i = Qt::Integer.new(0) + state = @dvVal.validate(@dv.text(), i) + + if state == Qt::Validator::Acceptable + @dvAccLed.on() + elsif state == Qt::Validator::Intermediate + @dvInterLed.on() + else + @dvInvalLed.on() + end + end +end + +class PageNotImpl + def initialize(parent) + page = parent.addPage() + + x = 10 + y = 10 + + niLbl = Qt::Label.new("Nothing is currently implemented for this widget", page) + niLbl.setGeometry(x, y, 300, 20) + niLbl.show() + end +end + +def UIMisc.miscKAlphaPainter(parent) + parent.currentPageObj = PageNotImpl.new(parent) +end + +def UIMisc.miscKCModule(parent) + parent.currentPageObj = PageNotImpl.new(parent) +end + +def UIMisc.miscKColor(parent) + parent.currentPageObj = PageNotImpl.new(parent) +end + +def UIMisc.miscKColorDrag(parent) + parent.currentPageObj = PageNotImpl.new(parent) +end + +def UIMisc.miscKCommand(parent) + parent.currentPageObj = PageNotImpl.new(parent) +end + +def UIMisc.miscKCommandHistory(parent) + parent.currentPageObj = PageNotImpl.new(parent) +end + +def UIMisc.miscKDockWindow(parent) + parent.currentPageObj = PageNotImpl.new(parent) +end + +def UIMisc.miscKDoubleValidator(parent) + parent.currentPageObj = Page3.new(parent) +end + +def UIMisc.miscKDateValidator(parent) + parent.currentPageObj = Page3.new(parent) +end + +def UIMisc.miscKIntValidator(parent) + parent.currentPageObj = Page3.new(parent) +end + +def UIMisc.miscKPixmapIO(parent) + parent.currentPageObj = PageNotImpl.new(parent) +end + +def UIMisc.miscKSharedPixmap(parent) + parent.currentPageObj = PageNotImpl.new(parent) +end + +def UIMisc.miscKSystemTray(parent) + KDE::MessageBox.information(parent, "See the systray.rb example in the templates/ subdirectories") +end + +def UIMisc.miscKThemeBase(parent) + parent.currentPageObj = PageNotImpl.new(parent) +end + +def UIMisc.miscQXEmbed(parent) + parent.currentPageObj = PageNotImpl.new(parent) +end + +if $0 == __FILE__ + puts + puts "Please run uisampler.rb" + puts +end + +end + diff --git a/korundum/rubylib/examples/uimodules/uiwidgets.rb b/korundum/rubylib/examples/uimodules/uiwidgets.rb new file mode 100644 index 00000000..8dd79d49 --- /dev/null +++ b/korundum/rubylib/examples/uimodules/uiwidgets.rb @@ -0,0 +1,827 @@ +=begin +This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale +=end + +require 'Korundum' + +module UIWidgets + +class Page1 < Qt::Object + slots 'restrict(int)' + + def initialize(parent) + super + page = parent.addPage() + + x = 10 + y = 10 + + editLbl = Qt::Label.new("KTextEdit", page) + editLbl.setGeometry(x, y, 50, 20) + editLbl.show() + + textList = ["Now is the winter of our discontent\n", + "made glorious summer by this sun of York;\n", + "and all the clouds that lour'd upon our house\n", + "in the deep bosom of the ocean buried.\n"] + + parent.edit = KDE::TextEdit.new(page) + parent.edit.setGeometry(x, y + 20, 300, 100) + textList.each do |line| + parent.edit.insert(line) + end + parent.edit.show() + + y = y + 125 + searchBtn = Qt::PushButton.new("Search", page) + replaceBtn = Qt::PushButton.new("Replace", page) + gotoBtn = Qt::PushButton.new("GoTo Line", page) + + searchBtn.setGeometry(x, y, 60, 22) + replaceBtn.setGeometry(x + 90, y, 60, 22) + gotoBtn.setGeometry(x + 180, y, 60, 22) + +# page.connect(searchBtn, SIGNAL("clicked()"), parent.edit, SLOT('search()')) +# page.connect(replaceBtn, SIGNAL("clicked()"), parent.edit, SLOT('replace()')) +# page.connect(gotoBtn, SIGNAL("clicked()"), parent.edit, SLOT('doGotoLine()')) + + searchBtn.show() + replaceBtn.show() + gotoBtn.show() + + y = y + 35 + + lineeditLbl = Qt::Label.new("KLineEdit", page) + lineeditLbl.setGeometry(x, y, 70, 20) + lineeditLbl.show() + + lineedit = KDE::LineEdit.new(page) + lineedit.setGeometry(x, y + 20, 100, 20) + lineedit.show() + + intLbl = Qt::Label.new("KIntNumInput", page) + intLbl.setGeometry(x + 195, y + 35, 95, 20) + intLbl.show() + + intNum = KDE::IntNumInput.new(5, page) + intNum.setGeometry(x + 195, y + 55, 175, 50) +# intNum.setSuffix(" GB") +# intNum.setPrefix("hdc ") + intNum.setLabel("Capacity") + intNum.setRange(0, 10, 1, true) + intNum.show() + + y = y + 50 + + dblLbl = Qt::Label.new("KDoubleNumInput", page) + dblLbl.setGeometry(x + 195, y + 80, 115, 20) + dblLbl.show() + + dblNum = KDE::DoubleNumInput.new(page) + dblNum.setValue(2.5) + dblNum.setGeometry(x + 195, y + 100, 175, 50) + dblNum.setLabel("Variable") + dblNum.setRange(0.0, 10.0, 0.5, true) + dblNum.show() + + restricteditLbl = Qt::Label.new("KRestrictedLine", page) + restricteditLbl.setGeometry(x, y, 95, 20) + restricteditLbl.show() + + @restrictlineedit = KDE::RestrictedLine.new(page) + @restrictlineedit.setGeometry(x, y + 20, 100, 20) + @restrictlineedit.show() + + buttons = ["Numbers Only", "Upper Case Only", "Lower Case Only"] + + n = buttons.length + + @validLbl = Qt::Label.new("", page) + @validLbl.setGeometry(x, y + 50, 250, 20) + @validLbl.show() + + grp = Qt::ButtonGroup.new(n, Qt::Vertical, "Select valid chars", page, "button grp") + grp.setGeometry(x, y + 75, 150, 5+30*n) + + (0...n).each { |i| Qt::RadioButton.new(buttons[i], grp) } + + connect(grp, SIGNAL("clicked(int)"), SLOT('restrict(int)')) + + grp.find(0).setChecked(true) + restrict(0) + + grp.show() + + page.show() + $kapp.processEvents() + + y = y + 195 + sqzLbl = Qt::Label.new("This text is too long to fit in the label below", page) + sqzLbl.setGeometry(x, y, 350, 20) + sqzLbl.show() + + sqzLbl1 = Qt::Label.new("KSqueezedTxtLabel:", page) + sqzLbl1.setGeometry(x, y + 20, 120, 20) + sqzLbl1.show() + + squeeze = KDE::SqueezedTextLabel.new("This text is too long to fit in the label below", page) + squeeze.setGeometry(x + 125, y + 20, 125, 20) + squeeze.setBackgroundMode(Qt::Widget::PaletteBase) + squeeze.show() + end + + def restrict(which) + r = {0 => "0123456789", 1 => "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 2 => "abcdefghijklmnopqrstuvwxyz"} + @restrictlineedit.setValidChars(r[which]) + @validLbl.setText("Valid: " + @restrictlineedit.validChars()) + end +end + +class Page2 + def initialize(parent) + page = parent.addPage() + + x1 = 10 + y1 = 10 + x2 = 240 + y2 = 100 + + cbLbl = Qt::Label.new("KComboBox", page) + cbLbl.setGeometry(x1, y1, 75, 20) + cbLbl.show() + + combo = KDE::ComboBox.new(page) + combo.insertStringList(["One", "Two", "Three"]) + combo.setGeometry(x1, y1 + 20, 100, 25) + combo.show() + + ccbLbl = Qt::Label.new("KColorCombo", page) + ccbLbl.setGeometry(x2, y1, 100, 20) + ccbLbl.show() + + colorCombo = KDE::ColorCombo.new(page) + colorCombo.setGeometry(x2, y1 + 20, 100, 25) + colorCombo.show() + + editListBox = KDE::EditListBox.new("KEditListBox", page) + editListBox.setGeometry(x1, y2, 220, 175) + editListBox.insertStringList(["One", "Two", "Three"]) + editListBox.show() + + lbLbl = Qt::Label.new("KListBox", page) + lbLbl.setGeometry(x2, y2, 100, 20) + lbLbl.show() + + listBox = KDE::ListBox.new(page) + listBox.setGeometry(x2, y2 + 20, 100, 100) + listBox.insertStringList(["One", "Two", "Three"]) + listBox.show() + end +end + +class Page3 + def initialize(parent) + page = parent.addPage() + + x = 10 + y = 10 + + fontLbl = Qt::Label.new("KFontChooser", page) + fontLbl.setGeometry(x, y, 95, 20) + fontLbl.show() + + fontChoose = KDE::FontChooser.new(page) + fontChoose.setGeometry(x, y + 20, 375, 300) + fontChoose.show() + + y = y + 330 + end +end + +class Page4 + def initialize(parent) + page = parent.addPage() + + x = 10 + y = 10 + + cbLbl = Qt::Label.new("KColorButton", page) + cbLbl.setGeometry(x, y, 75, 20) + cbLbl.show() + + cb = KDE::ColorButton.new(page) + cb.setColor(Qt::Color.new(255, 0, 0)) + cb.setGeometry(x, y + 20, 30, 30) + cb.show() + + ccbLbl = Qt::Label.new("KColorCombo", page) + ccbLbl.setGeometry(x + 150, y, 100, 20) + ccbLbl.show() + + colorCombo = KDE::ColorCombo.new(page) + colorCombo.setGeometry(x + 150, y + 20, 100, 25) + colorCombo.show() + + y = y + 60 + + cpLbl = Qt::Label.new("KColorPatch", page) + cpLbl.setGeometry(x, y, 75, 20) + cpLbl.show() + + cp = KDE::ColorPatch.new(page) + cp.setColor(Qt::Color.new(255, 0, 0)) + cp.setGeometry(x, y + 20, 20, 20) + cp.show() + + x = x + 150 + + ccLbl = Qt::Label.new("KColorCells", page) + ccLbl.setGeometry(x, y, 75, 20) + ccLbl.show() + + cc = KDE::ColorCells.new(page, 1, 5) + cc.setColor(0, Qt::Color.new(0, 0, 0)) + cc.setColor(1, Qt::Color.new(255, 0, 0)) + cc.setColor(2, Qt::Color.new(0, 255, 0)) + cc.setColor(3, Qt::Color.new(0, 0, 255)) + cc.setColor(4, Qt::Color.new(255, 255, 255)) + cc.setGeometry(x, y + 20, 100, 20) + cc.show() + + x = 10 + y = y + 50 + + dcLbl = Qt::Label.new("KDualColorButton", page) + dcLbl.setGeometry(x, y, 105, 20) + dcLbl.show() + + dc = KDE::DualColorButton.new(Qt::Color.new(255, 0, 0), Qt::Color.new(0, 0, 0), page) + dc.setGeometry(x, y + 20, 40, 40) + dc.show() + + gsLbl = Qt::Label.new("KGradientSelector", page) + gsLbl.setGeometry(x + 80, y + 30, 110, 20) + gsLbl.show() + + gs = KDE::GradientSelector.new(page) + gs.setGeometry(x + 80, y + 50, 250, 20) + gs.setColors(Qt::Color.new(255, 0, 0), Qt::Color.new(255, 255, 0)) + gs.show() + + y = y + 80 + + hsLbl = Qt::Label.new("KHSSelector", page) + hsLbl.setGeometry(x, y, 95, 20) + hsLbl.show() + + hs = KDE::HSSelector.new(page) + hs.setGeometry(x, y + 20, 350, 80) + hs.show() + + y = y + 110 + + ptLbl = Qt::Label.new("KPaletteTable", page) + ptLbl.setGeometry(x, y, 95, 20) + ptLbl.show() + + pt = KDE::PaletteTable.new(page, 340, 24) + pt.setPalette("Royal") + pt.setGeometry(x, y + 20, 340, 40) + pt.show() + end +end + +class Page5 + def initialize(parent) + page = parent.addPage() + + x = 10 + y = 10 + + rpLbl = Qt::Label.new("KRootPermsIcon", page) + rpLbl.setGeometry(x, y, 95, 20) + rpLbl.show() + + rp = KDE::RootPermsIcon.new(page) + rp.setGeometry(x, y + 20, 32, 32) + rp.show() + + wpLbl = Qt::Label.new("KWritePermsIcon", page) + wpLbl.setGeometry(x + 125, y, 95, 20) + wpLbl.show() + + wp = KDE::WritePermsIcon.new("/usr/bin/gcc", page) + wp.setGeometry(x + 125, y + 20, 32, 32) + wp.show() + + y = y + 75 + + pw1Lbl = Qt::Label.new("KPasswordEdit - echo *", page) + pw1Lbl.setGeometry(x, y, 150, 20) + pw1Lbl.show() + + pw1 = KDE::PasswordEdit.new(KDE::PasswordEdit::OneStar, page, "") + pw1.setGeometry(x, y + 20, 100, 20) + pw1.show() + + y = y + 50 + + pw2Lbl = Qt::Label.new("KPasswordEdit - echo ***", page) + pw2Lbl.setGeometry(x, y, 150, 20) + pw2Lbl.show() + + pw2 = KDE::PasswordEdit.new(KDE::PasswordEdit::ThreeStars, page, "") + pw2.setGeometry(x, y + 20, 100, 20) + pw2.show() + + y = y + 50 + + pw3Lbl = Qt::Label.new("KPasswordEdit - no echo", page) + pw3Lbl.setGeometry(x, y, 150, 20) + pw3Lbl.show() + + pw3 = KDE::PasswordEdit.new(KDE::PasswordEdit::NoEcho, page, "") + pw3.setGeometry(x, y + 20, 100, 20) + pw3.show() + + y = y + 50 + + urlLbl = Qt::Label.new("KURLLabel", page) + urlLbl.setGeometry(x, y, 100, 20) + urlLbl.show() + + url = KDE::URLLabel.new("http://developer.kde.org/language-bindings/ruby/", "Korundum", page) + url.setGeometry(x, y + 20, 100, 20) + url.setUseTips(true) + url.setTipText("http://developer.kde.org/language-bindings/ruby/") + url.show() + + x = 70 + y = y + 50 + + bbLbl = Qt::Label.new("KButtonBox", page) + bbLbl.setGeometry(x, y, 75, 20) + bbLbl.show() + + bbox = KDE::ButtonBox.new(page, Qt::Horizontal) + bbox.setGeometry(x, y + 20, 300, 22) + bbox.addButton("Button 1") + bbox.addButton("Button 2") + bbox.addButton("Button 3") + bbox.show() + + y = y + 50 + +# dbLbl = Qt::Label.new("KDirectionButton", page) +# dbLbl.setGeometry(x, y, 95, 20) +# dbLbl.show() + +# dbUp = KDE::DirectionButton.new(Qt::t::UpArrow, page) +# dbDown = KDE::DirectionButton.new(Qt::t::DownArrow, page) +# dbRight = KDE::DirectionButton.new(Qt::t::RightArrow, page) +# dbLeft = KDE::DirectionButton.new(Qt::t::LeftArrow, page) + +# dbUp.setGeometry(x, y + 20, 22, 22) +# dbDown.setGeometry(x + 30, y + 20, 22, 22) +# dbRight.setGeometry(x + 60, y + 20, 22, 22) +# dbLeft.setGeometry(x + 90, y + 20, 22, 22) + +# dbUp.show() +# dbDown.show() +# dbRight.show() +# dbLeft.show() + + x = x + 150 + +# kbLbl = Qt::Label.new("KKeyButton", page) +# kbLbl.setGeometry(x, y, 95, 20) +# kbLbl.show() + +# kb = KDE::KeyButton.new(page) +# kb.setText("Enter") +# kb.setGeometry(x, y + 20, 50, 32) +# kb.show() + + x = 70 + y = y + 50 + +# tbLbl = Qt::Label.new("KTabButton", page) +# tbLbl.setGeometry(x, y, 95, 20) +# tbLbl.show() + +# tbUp = KDE::TabButton.new(Qt::t::UpArrow, page) +# tbDown = KDE::TabButton.new(Qt::t::DownArrow, page) +# tbRight = KDE::TabButton.new(Qt::t::RightArrow, page) +# tbLeft = KDE::TabButton.new(Qt::t::LeftArrow, page) + +# tbUp.setGeometry(x, y + 20, 22, 25) +# tbDown.setGeometry(x + 30, y + 20, 22, 25) +# tbRight.setGeometry(x + 60, y + 20, 22, 25) +# tbLeft.setGeometry(x + 90, y + 20, 22, 25) + +# tbUp.show() +# tbDown.show() +# tbRight.show() +# tbLeft.show() + end +end + +class Page6 < Qt::Object + slots 'toggleClicked()' + + def initialize(parent) + super + page = parent.addPage() + + x = 20 + y = 10 + + red = Qt::Color.new(255, 0, 0) + green = Qt::Color.new(0, 255, 0) + yellow = Qt::Color.new(255, 255, 0) + blue = Qt::Color.new(0, 0, 255) + + ledcolor = [red, green, yellow, blue] + ledshape = [KDE::Led::Rectangular, KDE::Led::Circular] + ledlook = [KDE::Led::Flat, KDE::Led::Raised, KDE::Led::Sunken] + ledsize = [10, 18, 25] + @ledlist = [] + + ledlook.each do |look| + ledcolor.each do |color| + ledshape.each do |shape| + ledsize.each do |size| + led = KDE::Led.new(color, KDE::Led::On, look, shape, page) + led.setGeometry(x, y, size, size) + @ledlist << led + led.show() + x = x + 50 + end + x = x + 50 + end + x = 20 + y = y + 30 + end + y = y + 10 + end + + toggle = Qt::PushButton.new("Toggle", page) + toggle.setGeometry(150, 400, 60, 22) + toggle.show() + + connect(toggle, SIGNAL("clicked()"), SLOT('toggleClicked()')) + + page.show() + end + + def toggleClicked() + @ledlist.each { |led| led.toggle() } + end +end + +class Page7 < Qt::Object + slots 'add1()' + + def initialize(parent) + super + page = parent.addPage() + + x = 10 + y = 10 + + tabLbl = Qt::Label.new("KTabCtl", page) + tabLbl.setGeometry(x, y, 95, 20) + tabLbl.show() + + tab = KDE::TabCtl.new(page) + tab.setGeometry(x, y + 20, 300, 100) + + page1 = Qt::Widget.new(tab) + p1Lbl = Qt::Label.new("This is page 1", page1) + p1Lbl.setGeometry(20, 20, 100, 20) + page2 = Qt::Widget.new(tab) + p2Lbl = Qt::Label.new("This is page 2", page2) + p2Lbl.setGeometry(50, 20, 100, 20) + page3 = Qt::Widget.new(tab) + p3Lbl = Qt::Label.new("This is page 3", page3) + p3Lbl.setGeometry(20, 50, 100, 20) + + tab.addTab(page1, "Tab 1") + tab.addTab(page2, "Tab 2") + tab.addTab(page3, "Tab 3") + tab.show() + + x = 10 + y = 150 + + progLbl = Qt::Label.new("KProgress", page) + progLbl.setGeometry(x, y + 50, 95, 20) + progLbl.show() + + @p1 = KDE::Progress.new(page) + @p2 = KDE::Progress.new(15, page) + @p1.setTotalSteps(25) + @p2.setTotalSteps(25) + + @p1.setGeometry(x, y + 80, 125, 20) + @p2.setGeometry(x, y + 120, 125, 20) + + @p2.setPercentageVisible(false) + + @p1.show() + @p2.show() + + @total = 0 + + y = y + 150 + sepLbl = Qt::Label.new("KSeparator", page) + sepLbl.setGeometry(x, y, 95, 20) + sepLbl.show() + + sep = KDE::Separator.new(Qt::Frame::HLine, page) + sep.setGeometry(x, y + 20, 75, 10) + sep.show() + + page.show() + + @timer = Qt::Timer.new(page) + connect(@timer, SIGNAL('timeout()'), SLOT('add1()')) + @timer.start(100) + + add1() + end + + def add1() + @total = @total + 1 + @p1.advance(1) + @p2.advance(1) + + if @total == 26 + @timer.stop + end + end +end + +class Page8 + def initialize(parent) + page = parent.addPage() + + x = 40 + y = 10 + + dpLbl = Qt::Label.new("KDatePicker", page) + dpLbl.setGeometry(x, y, 95, 20) + dpLbl.show() + + dp = KDE::DatePicker.new(page) + dp.setGeometry(x, y + 20, 300, 170) + dp.show() + + y = y + 210 + + dtLbl = Qt::Label.new("KDateTable", page) + dtLbl.setGeometry(x, y, 95, 20) + dtLbl.show() + + dt = KDE::DateTable.new(page) + dt.setGeometry(x, y + 20, 300, 130) + dt.show() + end +end + +class PageThisApp + def initialize(parent) + page = parent.addPage() + + x = 10 + y = 10 + + taLbl = Qt::Label.new("This application uses KMainWindow as its top level widget\n and KListView in the"\ + " left-hand panel", page) + taLbl.setGeometry(x, y, 300, 60) + taLbl.show() + end +end + +class PageNotImpl + def initialize(parent) + page = parent.addPage() + + x = 10 + y = 10 + + niLbl = Qt::Label.new("Nothing is currently implemented for this widget", page) + niLbl.setGeometry(x, y, 300, 20) + niLbl.show() + end +end + +class CSDlg < KDE::Dialog + slots 'closeClicked()' + + def initialize(parent, name = "char select dlg", modal = false) + super(parent, name, modal) + + setGeometry(150, 50, 700, 320) + x = 10 + y = 10 + + csLbl = Qt::Label.new("KCharSelect", self) + csLbl.setGeometry(x, y, 95, 20) + csLbl.show() + cs = KDE::CharSelect.new(self, "chselect", nil, Qt::Char.new(0), 0) + cs.setGeometry(x, y + 20, 680, 250) + cs.show() + + closeBtn = Qt::PushButton.new("Close", self) + closeBtn.setGeometry( 610, 280, 60, 22) + closeBtn.show() + + connect(closeBtn, SIGNAL("clicked()"), SLOT('closeClicked()')) + end + + def closeClicked() + done(1) + end +end + +def UIWidgets.widKAnimWidget(parent) + parent.currentPageObj = PageNotImpl.new(parent) +end + +def UIWidgets.widKAuthIcon(parent) + parent.currentPageObj = Page5.new(parent) +end + +def UIWidgets.widKButtonBox(parent) + parent.currentPageObj = Page5.new(parent) +end + +def UIWidgets.widKCharSelect(parent) + dlg = CSDlg.new(parent) + dlg.show() +end + +def UIWidgets.widKColorButton(parent) + parent.currentPageObj = Page4.new(parent) +end + +def UIWidgets.widKColorCells(parent) + parent.currentPageObj = Page4.new(parent) +end + +def UIWidgets.widKColorCombo(parent) + parent.currentPageObj = Page2.new(parent) +end + +def UIWidgets.widKColorPatch(parent) + parent.currentPageObj = Page4.new(parent) +end + +def UIWidgets.widKComboBox(parent) + parent.currentPageObj = Page2.new(parent) +end + +def UIWidgets.widKCompletionBox(parent) + parent.currentPageObj = PageNotImpl.new(parent) +end + +def UIWidgets.widKContainerLayout(parent) + parent.currentPageObj = PageNotImpl.new(parent) +end + +def UIWidgets.widKCursor(parent) + parent.currentPageObj = PageNotImpl.new(parent) +end + +def UIWidgets.widKDatePicker(parent) + parent.currentPageObj = Page8.new(parent) +end + +def UIWidgets.widKDateTable(parent) + parent.currentPageObj = Page8.new(parent) +end + +def UIWidgets.widKDirectionButton(parent) + parent.currentPageObj = Page5.new(parent) +end + +def UIWidgets.widKDualColorButton(parent) + parent.currentPageObj = Page4.new(parent) +end + +def UIWidgets.widKTextEdit(parent) + parent.currentPageObj = Page1.new(parent) +end + +def UIWidgets.widKEditListBox(parent) + parent.currentPageObj = Page2.new(parent) +end + +def UIWidgets.widKFontChooser(parent) + parent.currentPageObj = Page3.new(parent) +end + +def UIWidgets.widKHSSelector(parent) + parent.currentPageObj = Page4.new(parent) +end + +def UIWidgets.widKIconView(parent) + parent.currentPageObj = PageNotImpl.new(parent) +end + +def UIWidgets.widKJanusWidget(parent) + parent.currentPageObj = PageNotImpl.new(parent) +end + +#def UIWidgets.widKKeyButton(parent) +# parent.currentPageObj = Page5.new(parent) + +def UIWidgets.widKKeyChooser(parent) + parent.currentPageObj = PageNotImpl.new(parent) +end + +def UIWidgets.widKLed(parent) + parent.currentPageObj = Page6.new(parent) +end + +def UIWidgets.widKLineEdit(parent) + parent.currentPageObj = Page1.new(parent) +end + +def UIWidgets.widKListBox(parent) + parent.currentPageObj = Page2.new(parent) +end + +def UIWidgets.widKListView(parent) + parent.currentPageObj = PageThisApp.new(parent) +end + +def UIWidgets.widKNumInput(parent) + parent.currentPageObj = Page1.new(parent) +end + +def UIWidgets.widKPaletteTable(parent) + parent.currentPageObj = Page4.new(parent) +end + +def UIWidgets.widKPasswordEdit(parent) + parent.currentPageObj = Page5.new(parent) +end + +def UIWidgets.widKProgress(parent) + parent.currentPageObj = Page7.new(parent) +end + +def UIWidgets.widKRootPixmap(parent) + parent.currentPageObj = PageNotImpl.new(parent) +end + +def UIWidgets.widKMainWindow(parent) + parent.currentPageObj = PageThisApp.new(parent) +end + +def UIWidgets.widKRestrictedLine(parent) + parent.currentPageObj = Page1.new(parent) +end + +def UIWidgets.widKRuler(parent) + parent.currentPageObj = PageNotImpl.new(parent) +end + +def UIWidgets.widKSelector(parent) + parent.currentPageObj = Page4.new(parent) +end + +def UIWidgets.widKSeparator(parent) + parent.currentPageObj = Page7.new(parent) +end + +def UIWidgets.widKSqueezedTextLabel(parent) + parent.currentPageObj = Page1.new(parent) +end + +def UIWidgets.widKTabButton(parent) + parent.currentPageObj = Page5.new(parent) +end + +def UIWidgets.widKTabCtl(parent) + parent.currentPageObj = Page7.new(parent) +end + +def UIWidgets.widKTextBrowser(parent) + parent.currentPageObj = PageNotImpl.new(parent) +end + +def UIWidgets.widKURLLabel(parent) + parent.currentPageObj = Page5.new(parent) +end + + +if $0 == __FILE__ + puts + puts "Please run uisampler.rb" + puts +end + +end diff --git a/korundum/rubylib/examples/uimodules/uixml.rb b/korundum/rubylib/examples/uimodules/uixml.rb new file mode 100644 index 00000000..67be21ac --- /dev/null +++ b/korundum/rubylib/examples/uimodules/uixml.rb @@ -0,0 +1,56 @@ +=begin +This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale +=end + +require 'Korundum' + +module UIXML + +class PageLaunch + def initialize(parent) + page = parent.addPage() + + x = 10 + y = 10 + + launchLbl = Qt::Label.new("Launching application ... please wait\n\nClose launched application to continue", page) + launchLbl.setGeometry(x, y, 300, 80) + launchLbl.show() + + page.show() + + $kapp.processEvents() + end +end + +def UIXML.xmlKActionCollection(parent) + parent.currentPageObj = PageLaunch.new(parent) + system("ruby xmlmenudemo.rb") +end + +def UIXML.xmlKEditToolbar(parent) + parent.currentPageObj = PageLaunch.new(parent) + system("ruby xmlmenudemo.rb") +end + +def UIXML.xmlKEditToolbarWidget(parent) + parent.currentPageObj = PageLaunch.new(parent) + system("ruby xmlmenudemo.rb") +end + +def UIXML.xmlKXMLGUIBuilder(parent) + parent.currentPageObj = PageLaunch.new(parent) + system("ruby xmlmenudemo.rb") +end + +def UIXML.xmlKXMLGUIClient(parent) + parent.currentPageObj = PageLaunch.new(parent) + system("ruby xmlmenudemo.rb") +end + +def UIXML.xmlKXMLGUIFactory(parent) + parent.currentPageObj = PageLaunch.new(parent) + system("ruby xmlmenudemo.rb") +end + +end diff --git a/korundum/rubylib/examples/uisampler.rb b/korundum/rubylib/examples/uisampler.rb new file mode 100644 index 00000000..10af08de --- /dev/null +++ b/korundum/rubylib/examples/uisampler.rb @@ -0,0 +1,238 @@ +=begin +This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale +=end + +require 'Korundum' + +require 'uimodules/uiwidgets.rb' +require 'uimodules/uidialogs.rb' +require 'uimodules/uimenus.rb' +require 'uimodules/uimisc.rb' +require 'uimodules/uixml.rb' + +$listItems = {"Dialogs" => + {"KDE::AboutDialog" => ["KDE::AboutApplication", "KDE::AboutContainer", "KDE::ImageTrackLabel", + "KDE::AboutContainerBase", "KDE::AboutContributor", "KDE::AboutWidget"], + "KDE::AboutKDE" => [], + "KDE::BugReport" => [], + "KDE::ColorDialog" => [], + "KDE::Dialog" => [], + "KDE::DialogBase" => ["KDE::DialogBaseButton", "KDE::DialogBase::SButton", "KDE::DialogBaseTile"], + "KDE::FontDialog" => [], + "KDE::KeyDialog" => [], + "KDE::InputDialog" => [], + "KDE::MessageBox" => [], + "KDE::PasswordDialog" => [], + "KDE::Wizard" => []}, + "Widgets" => + {"KDE::AnimWidget" => [], + "KDE::AuthIcon" => ["KDE::RootPermsIcon", "KDE::WritePermsIcon"], + "KDE::ButtonBox" => [], + "KDE::CharSelect" => ["KDE::CharSelectTable"], + "KDE::ColorButton" => [], + "KDE::ColorCells" => [], + "KDE::ColorCombo" => [], + "KDE::ColorPatch" => [], + "KDE::ComboBox" => [], + "KDE::CompletionBox" => [], + "KDE::ContainerLayout" => ["KDE::ContainerLayout::KContainerLayoutItem"], + "KDE::Cursor" => [], + "KDE::DatePicker" => ["KDE::DateInternalMonthPicker", "KDE::DateInternalYearSelector"], + "KDE::DateTable" => [], + "KDE::DualColorButton" => [], + "KDE::EditListBox" => [], + "KDE::FontChooser" => [], + "KDE::HSSelector" => [], + "KDE::IconView" => [], + "KDE::JanusWidget" => ["KDE::JanusWidget::IconListBox"], + "KDE::KeyChooser" => [], + "KDE::Led" => [], + "KDE::LineEdit" => [], + "KDE::ListBox" => [], + "KDE::ListView" => [], + "KDE::NumInput" => ["KDE::DoubleNumInput", "KDE::IntNumInput"], + "KDE::PaletteTable" => [], + "KDE::PasswordEdit" => [], + "KDE::Progress" => [], + "KDE::RootPixmap" => [], + "KDE::MainWindow" => [], + "KDE::RestrictedLine" => [], + "KDE::Ruler" => [], + "KDE::Selector" => ["KDE::GradientSelector", "KDE::ValueSelector", "KDE::HSSelector", "KDE::XYSelector"], + "KDE::Separator" => [], + "KDE::SqueezedTextLabel" => [], + "KDE::TabCtl" => [], + "KDE::TextBrowser" => [], + "KDE::TextEdit" => ["KDE::EdFind", "KDE::EdGotoLine", "KDE::EdReplace"], + "KDE::URLLabel" => []}, + "XML" => + {"KDE::ActionCollection" => [], + "KDE::EditToolbar" => [], + "KDE::EditToolbarWidget" => [], + "KDE::XMLGUIBuilder" => [], + "KDE::XMLGUIClient" => ["KDE::XMLGUIClient::DocStruct"], + "KDE::XMLGUIFactory" => []}, + "Menus/Toolbars" => + {"KDE::AccelMenu" => [], + "KDE::Action" => ["KDE::FontAction", "KDE::FontSizeAction", "KDE::ListAction", "KDE::RecentFilesAction", "KDE::RadioAction", + "KDE::SelectAction", "KDE::ToggleAction"], + "KDE::ActionMenu" => [], + "KDE::ActionSeparator" => [], + "KDE::ContextMenuManager" => [], + "KDE::DCOPActionProxy" => [], + "KDE::HelpMenu" => [], + "KDE::MenuBar" => [], + "KDE::PanelApplet" => [], + "KDE::PanelExtension" => [], + "KDE::PanelMenu" => [], + "KDE::PopupFrame" => [], + "KDE::PopupMenu" => [], + "KDE::PopupTitle" => [], + "KDE::StatusBar" => [], + "KDE::StatusBarLabel" => [], + "KDE::StdAction" => [], + "KDE::ToolBar" => ["KDE::ToolBarButton", "KDE::ToolBarButtonList", "KDE::ToolBarPopupAction", + "KDE::ToolBarRadioGroup", "KDE::ToolBarSeparator"], + "KDE::WindowListMenu" => []}, + "Other" => + {"KDE::AlphaPainter" => [], + "KDE::CModule" => [], + "KDE::Color" => [], + "KDE::ColorDrag" => [], + "KDE::Command" => ["KDE::MacroCommand"], + "KDE::CommandHistory" => [], + "KDE::DateValidator" => [], + "KDE::DockWindow" => ["KDE::DockButton_Private - KPanelMenu", "KDE::DockButton_Private", + "KDE::DockSplitter", "KDE::DockTabCtl_PrivateStruct", "KDE::DockWidgetAbstractHeader", + "KDE::DockWidgetAbstractHeaderDrag", "KDE::DockWidgetHeader", + "KDE::DockWidgetHeaderDrag", "KDE::DockWidgetPrivate"], + "KDE::DoubleValidator" => [], + "KDE::IntValidator" => [], + "KDE::PixmapIO" => [], + "KDE::SharedPixmap" => [], + "KDE::SystemTray" => [], + "KDE::ThemeBase" => ["KDE::ThemeCache", "KDE::ThemePixmap", "KDE::ThemeStyle"], + "QXEmbed" => []}} + +BLANK_MSG = <<END_OF_STRING +<b>UISampler</b> - provides examples of <b>Korundum</b> widgets<p> +Select a dialog/widget/menu/etc example from the tree at left +END_OF_STRING + + +class MainWin < KDE::MainWindow + TREE_WIDTH = 220 + + slots 'lvClicked(QListViewItem*)' + + attr_accessor :edit, :currentPageObj + + def initialize(*args) + super + + setCaption("Samples of Korundum widget usage") + # The following leave about 375 x 390 for the rt hand panel + mainGeom = Qt::Rect.new(0, 0, 640, 500) + setGeometry(mainGeom) + + # create the main view - list view on the left and an + # area to display frames on the right + @mainView = Qt::Splitter.new(self, "main view") + @tree = KDE::ListView.new(@mainView, "tree") + @page = Qt::WidgetStack.new(@mainView, "page") + blankPage = Qt::Widget.new(@page, "blank") + blankPage.setGeometry(0, 0, 375, 390) + blankPage.setBackgroundMode(Qt::Widget::PaletteBase) + + blankLbl = Qt::Label.new(BLANK_MSG, blankPage) + blankLbl.setGeometry(40, 10, 380, 150) + blankLbl.setBackgroundMode(Qt::Widget::PaletteBase) + + blankPM = Qt::Pixmap.new("rbtestimage.png") + pmLbl = Qt::Label.new("", blankPage) + pmLbl.setPixmap(blankPM) + pmLbl.setGeometry(40, 160, 300, 200) + pmLbl.setBackgroundMode(Qt::Widget::PaletteBase) + + @page.addWidget(blankPage, 1) + @page.raiseWidget(1) + + setCentralWidget(@mainView) + + initListView() + connect(@tree, SIGNAL("clicked(QListViewItem*)"), self, SLOT('lvClicked(QListViewItem*)')) + + @edit = nil + @currentPageObj = nil + @prefix = {"Dialogs" => "UIDialogs::dlg", "Widgets" => "UIWidgets::wid", "XML" => "UIXML::xml", + "Menus/Toolbars" => "UIMenus::menu", "Other" => "UIMisc::misc"} + end + + def initListView() + @tree.addColumn("Category", TREE_WIDTH - 21) +# tree.setMaximumWidth(treeWidth) + @mainView.setSizes([TREE_WIDTH, 375]) + @tree.setRootIsDecorated(true) + @tree.setVScrollBarMode(Qt::ScrollView::AlwaysOn) + topLevel = $listItems.keys() + topLevel.each do |item_1| + parent = Qt::ListViewItem.new(@tree, String.new(item_1)) + secondLevel = $listItems[item_1].keys() + secondLevel.each do |item_2| + child = Qt::ListViewItem.new(parent, String.new(item_2)) + $listItems[item_1][item_2].each do |item_3| + Qt::ListViewItem.new(child, String.new(item_3)) + end + end + end + end + + def lvClicked(lvItem) + if lvItem.nil? + return + end + + if $listItems.keys().include?(lvItem.text(0)) + return + end + + p = lvItem.parent() + if $listItems.keys().include?(p.text(0)) + pfx = @prefix[p.text(0)] + funcCall = pfx + lvItem.text(0).sub("KDE::","K") + "(self)" + else + pfx = @prefix[p.parent().text(0)] + funcCall = pfx + lvItem.parent().text(0).sub("KDE::","K") + "(self)" + end + eval funcCall + end + + def addPage() + @edit = nil + @currentPageObj = nil + current = @page.widget(2) + if !current.nil? + @page.removeWidget(current) + current.dispose + end + + newPage = Qt::Widget.new(@page) + newPage.setGeometry(0, 0, 375, 390) +# newPage.setBackgroundMode(QWidget.PaletteBase) + @page.addWidget(newPage, 2) + @page.raiseWidget(2) + + return newPage + end +end + +#-------------------- main ------------------------------------------------ + +appName = "UISampler" +about = KDE::AboutData.new("uisampler", appName, "0.1") +KDE::CmdLineArgs.init(ARGV, about) +app = KDE::Application.new() +mainWindow = MainWin.new(nil, "main window") +mainWindow.show +app.exec + diff --git a/korundum/rubylib/examples/xmlgui.rb b/korundum/rubylib/examples/xmlgui.rb new file mode 100755 index 00000000..8f021ccf --- /dev/null +++ b/korundum/rubylib/examples/xmlgui.rb @@ -0,0 +1,42 @@ +#!/usr/bin/env ruby + +require 'Korundum' +require 'tempfile' + +about = KDE::AboutData.new("one", "two", "three") +#KDE::CmdLineArgs.init(about) +KDE::CmdLineArgs.init(ARGV, about) +app = KDE::Application.new() + +class Receiver < Qt::Object + slots "pressed_up()", "close()", "quit()" + def initialize main, *k + super(*k) + @main = main + end + def quit + @main.close + end +end + +RAction = Struct.new :xmlgui_name, :string, :accel, :something +class RAction + def create receiver, slot, action_collection + p self.string + KDE::Action.new self.string, self.accel, receiver, slot, action_collection, self.xmlgui_name + end +end + +# { Quit, KStdAccel::Quit, "file_quit", I18N_NOOP("&Quit"), 0, "exit" }, +std_actions = { :quit => RAction.new( "file_quit", ("&Quit"), KDE::Shortcut.new(), "exit" ) } + +begin + m = KDE::MainWindow.new + @r = Receiver.new m + mActionCollection = m.actionCollection + action = std_actions[:quit].create @r, SLOT("quit()"), mActionCollection + m.createGUI Dir.pwd + "/xmlgui.rc" + app.setMainWidget(m) + m.show + app.exec() +end diff --git a/korundum/rubylib/examples/xmlgui.rc b/korundum/rubylib/examples/xmlgui.rc new file mode 100644 index 00000000..1c5d03fc --- /dev/null +++ b/korundum/rubylib/examples/xmlgui.rc @@ -0,0 +1,18 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui name="xmlgui" version="1"> + +<MenuBar> + + <Menu name="file" noMerge="1"><text>&File</text> + <Action name="file_open"/> + <Action name="file_save"/> + <Action name="file_save_as"/> + <Separator/> + <Action name="file_print"/> + <Separator/> + <Action name="file_quit"/> + </Menu> + +</MenuBar> + +</kpartgui> diff --git a/korundum/rubylib/examples/xmlmenudemo.rb b/korundum/rubylib/examples/xmlmenudemo.rb new file mode 100644 index 00000000..a246ac25 --- /dev/null +++ b/korundum/rubylib/examples/xmlmenudemo.rb @@ -0,0 +1,314 @@ +=begin +This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale +=end + +=begin +This template constructs an application with menus, toolbar and statusbar. +It uses KDE classes and methods that simplify the task of building and +operating a GUI. It is recommended that this approach be used, rather +than the primitive approach in menuapp1.py +=end + +=begin +Copyright 2003 Jim Bublitz + +Terms and Conditions + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +Except as contained in this notice, the name of the copyright holder shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from the +copyright holder. +=end + +require 'Korundum' + +class MainWin < KDE::MainWindow + + STATUSBAR_LEFT = 1 + STATUSBAR_MIDDLE = 2 + STATUSBAR_RIGHT = 3 + + slots 'slotFake()', 'slotNew()', 'slotOpen()', 'slotSave()', 'slotSaveAs()', 'slotPrint()', 'slotRadio()', + 'slotQuit()', 'slotUndo()', 'slotRedo()', 'slotCut()', 'slotCopy()', 'slotPaste()', 'slotFind()', + 'slotFindNext()', 'slotReplace()', 'slotSpecial()', 'slotToggle2()', 'slotZoomIn()', 'slotZoomOut()' + + def initialize(*args) + super + + initActions() + setGeometry(0, 0, 350, 200) + + # The second arg of createGUI needs to be 0(or false) + # to enable XMLGUI features like ActionList(in 'dynamicActions') + # If the default is used(true), the dynamic actions will not + # appear in the menus + uifilebase = Dir.getwd + '/xmlmenudemoui.rc' + createGUI(uifilebase, false) + + dynamicActions() + + # Can't do this until the toolBar has been created in createGUI + stretchlbl = Qt::Label.new("", toolBar()) + toolBar().setStretchableWidget(stretchlbl) + + initStatusBar() + + @saveAction.setEnabled(false) + @saveAsAction.setEnabled(false) + end + + def initActions() + # This is used in all of the KDE::Action/KDE::StdAction constructors -- + # Seems more efficient to only do the call once + acts = actionCollection() + + # "File" menu items + newAction = KDE::StdAction.openNew(self, SLOT('slotNew()'), acts) + openAction = KDE::StdAction.open(self, SLOT('slotOpen()'), acts) + @saveAction = KDE::StdAction.save(self, SLOT('slotSave()'), acts) + @saveAsAction = KDE::StdAction.saveAs(self, SLOT('slotSaveAs()'), acts) + printAction = KDE::StdAction.print(self, SLOT('slotPrint()'), acts) + quitAction = KDE::StdAction.quit(self, SLOT('slotQuit()'), acts) + + # "Edit" menu items + undoAction = KDE::StdAction.undo(self, SLOT('slotUndo()'), acts) + redoAction = KDE::StdAction.redo(self, SLOT('slotRedo()'), acts) + cutAction = KDE::StdAction.cut(self, SLOT('slotCut()'), acts) + copyAction = KDE::StdAction.copy(self, SLOT('slotCopy()'), acts) + pasteAction = KDE::StdAction.paste(self, SLOT('slotPaste()'), acts) + findAction = KDE::StdAction.find(self, SLOT('slotFind()'), acts) + findNextAction = KDE::StdAction.findNext(self, SLOT('slotFindNext()'), acts) + replaceAction = KDE::StdAction.replace(self, SLOT('slotReplace()'), acts) + + # NOTE!!!! You must specify a parent and name for the action object in its constructor + # Normally in a constructor like + # + # someObject(Qt::Widget *parent = 0, const char *name = 0) + # + # the parent may or may not be assigned, but widgets usually ignore the + # name argument. For an action of *any* type(other than KDE::StdAction), + # the 'name' argument is what is used to load the action into the menus + # and toolBar(in the line below, "specialActionName"). The XMLGUI mechanism + # has no way to find out about the action objects except through their + # object names - the variable the object is assigned to('specialAction') + # has no meaning in XNLGUI terms except through the objects 'name' member value + + specialAction = KDE::Action.new(i18n("Special"), KDE::Shortcut.new(0), self, SLOT('slotSpecial()'), acts, "specialActionName") + + # Demo menu items + + # KDE::ToggleAction has an isChecked member and emits the "toggle" signal + toggle1Action = KDE::ToggleAction.new("Toggle 1", KDE::Shortcut.new(0), acts, "toggle1Action") + toggle2Action = KDE::ToggleAction.new("Toggle 2", KDE::Shortcut.new(0), self, SLOT('slotToggle2()'), acts, "toggle2Action") + + # A separator - create once/use everywhere + separateAction = KDE::ActionSeparator.new(acts, "separateAction") + + # Font stuff in menus or toolbar + fontAction = KDE::FontAction.new("Font", KDE::Shortcut.new(0), acts, "fontAction") + fontSizeAction = KDE::FontSizeAction.new("Font Size", KDE::Shortcut.new(0), acts, "fontSizeAction") + + fontAction.setComboWidth(150) + fontSizeAction.setComboWidth(75) + + # Need to assign an icon to actionMenu below + icons = KDE::IconLoader.new() + iconSet = Qt::IconSet.new(icons.loadIcon("viewmag", KDE::Icon::Toolbar)) + + # Nested menus using KDE::Actions.new(also nested on toolbar) + actionMenu = KDE::ActionMenu.new("Action Menu", acts, "actionMenu") + actionMenu.setIconSet(iconSet) + + # By using KDE::StdAction here, the XMLGUI mechanism will automatically + # create a 'View' menu and insert "Zoom In" and "Zoom Out" objects + # in it. This happens because before parsing our *ui.rc file, + # the standard KDE::DE file config/ui/ui_standards.rc is parsed, and + # then our *ui.rc file is merged with the result - this gives KDE::DE + # menus and toolBars a standard "look" and item placement(including + # separators). Creating the KDE::StdActions alone is sufficient - you + # could delete their references from the *ui.rc file and the menu + # items would still be created via ui_standards.rc + actionMenu.insert(KDE::StdAction.zoomIn(self, SLOT('slotZoomIn()'), acts)) + actionMenu.insert(KDE::StdAction.zoomOut(self, SLOT('slotZoomOut()'), acts)) + + radio1Action = KDE::RadioAction.new("Radio 1", KDE::Shortcut.new(0), self, SLOT('slotRadio()'), acts, "radio1") + radio1Action.setExclusiveGroup("Radio") + radio1Action.setChecked(true) + radio2Action = KDE::RadioAction.new("Radio 2", KDE::Shortcut.new(0), self, SLOT('slotRadio()'), acts, "radio2") + radio2Action.setExclusiveGroup("Radio") + radio3Action = KDE::RadioAction.new("Radio 3", KDE::Shortcut.new(0), self, SLOT('slotRadio()'), acts, "radio3") + radio3Action.setExclusiveGroup("Radio") + end + + + def initStatusBar() + statusBar().insertItem("", STATUSBAR_LEFT, 1000, true) + statusBar().insertItem("", STATUSBAR_MIDDLE, 1000, true) + statusBar().insertItem("", STATUSBAR_RIGHT, 1000, true) + end + + def dynamicActions() + # This creates something like a 'recent files list' in the 'File' menu + # (There is a KDE::RecentFilesAction that probably should be used instead, + # but this demos the use of action lists) + # The code here corresponds to the <ActionList name="recent"/> entry + # in the rc file + + # Just fake some filenames for now + fakeFiles = ["kaction.sip", "kxmlguiclient.sip"] + + # Clear the old entries, so we don't end up accumulating entries in the menu + unplugActionList("recent"); + dynamicActionsList = [] + + # Create a KDE::Action for each entry and store the KDE::Actions in a list + # Use 'nil' for the KDE::ActionCollection argument in the KDE::Action constructor + # in this case only + (0...fakeFiles.length).each do |i| + act = KDE::Action.new(i18n(" &#{i.to_s} #{fakeFiles[i]}"), KDE::Shortcut.new(0), + self, SLOT('slotFake()'), nil, fakeFiles[i].sub(/.sip$/,'') + "open") + dynamicActionsList << act + end + + # Update the menu with the most recent KDE::Actions + plugActionList("recent", dynamicActionsList) + end + + +#-------------------- slots ----------------------------------------------- + + def slotFake() + # sender() should be called before anything else + # (including "notImpl") so the correct sender + # value is returned + sender = sender().name() + notImpl("Recent files(#{sender})") + end + + # 'id' is for toolbar button signals - ignored for menu signals + def slotNew(id = -1) + notImpl("New") + end + + def slotOpen(id = -1) + notImpl("Open") + end + + def slotSave(id = -1) + notImpl("Save") + end + + def slotSaveAs() + notImpl("Save As") + end + + def slotPrint() + notImpl("Print") + end + + def slotQuit() + notImpl("Quit") + end + + def slotUndo() + notImpl("Undo") + end + + def slotRedo() + notImpl("Redo") + end + + def slotCut(id = -1) + notImpl("Cut") + end + + def slotCopy(id = -1) + notImpl("Copy") + end + + def slotPaste(id = -1) + notImpl("Paste") + end + + def slotFind() + notImpl("Find") + end + + def slotFindNext() + notImpl("Find Next") + end + + def slotReplace() + notImpl("Replace") + end + + def slotSpecial() + notImpl("Special") + end + + def slotToggle2() + notImpl("Toggle") + end + + def slotZoomIn() + notImpl("Zoom In") + end + + def slotZoomOut() + notImpl("Zoom Out") + end + + def slotRadio() + sender = sender().name() + notImpl("Radio #{sender}") + end + + def notImpl(item = "Feature") + statusBar().changeItem("#{item} not implemented", STATUSBAR_LEFT) + KDE::MessageBox.error(self, "#{item} not implemented", "Not Implemented") + statusBar().changeItem("", STATUSBAR_LEFT) + end +end + + +#-------------------- main ------------------------------------------------ + +description = "A basic application template" +version = "1.0" + +# The appName(xmlmenudemo - first argument) is required +# if the program is to automatically locate it *ui.rc file +aboutData = KDE::AboutData.new("xmlmenudemo", "xmlmenudemo", + version, description, KDE::AboutData::License_GPL, + "(C) 2003 whoever the author is") + +aboutData.addAuthor("author1", "whatever they did", "email@somedomain") +aboutData.addAuthor("author2", "they did something else", "another@email.address") + +# mainpath = os.path.dirname(os.path.abspath(sys.argv[0])) +KDE::CmdLineArgs.init(ARGV, aboutData) + +KDE::CmdLineArgs.addCmdLineOptions([["+files", "File to open", ""]]) + +app = KDE::Application.new() +mainWindow = MainWin.new(nil, "main window") +mainWindow.show +app.exec diff --git a/korundum/rubylib/examples/xmlmenudemoui.rc b/korundum/rubylib/examples/xmlmenudemoui.rc new file mode 100644 index 00000000..58f07cf6 --- /dev/null +++ b/korundum/rubylib/examples/xmlmenudemoui.rc @@ -0,0 +1,49 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd" ><kpartgui name="xmlmenudemo" version="1"> +<MenuBar> + <Menu name="file"><text>&File</text> + <Action name="newAction"/> + <Action name="openAction"/> + <Action name="saveAction"/> + <Action name="saveAsAction"/> + <Action name="printAction"/> + <Action name="quitAction"/> + <ActionList name="recent" /> + </Menu> + <Menu name="edit"><text>&Edit</text> + <Action name="undoAction"/> + <Action name="redoAction"/> + <Action name="cutAction"/> + <Action name="copyAction"/> + <Action name="pasteAction"/> + <Action name="findAction"/> + <Action name="findNextAction"/> + <Action name="replaceAction"/> + <Action name="specialActionName"/> + </Menu> + <Menu name="demo"><text>&Demo</text> + <Action name="toggle1Action"/> + <Action name="toggle2Action"/> + <Action name="separateAction"/> + <Action name="fontAction"/> + <Action name="fontSizeAction"/> + <Action name="separateAction"/> + <Action name="actionMenu"/> + <Action name="radio1"/> + <Action name="radio2"/> + <Action name="radio3"/> + </Menu> +</MenuBar> +<ToolBar name="mainToolBar"> + <Action name="actionMenu"/> + <Action name="separateAction"/> + <Action name="separateAction"/> + <Action name="fontAction"/> + <Action name="separateAction"/> + <Action name="fontSizeAction" comboWidth="75"/> + <Action name="radio1"/> + <Action name="radio2"/> + <Action name="radio3"/> + <Merge/> +</ToolBar> +<ActionProperties /> +</kpartgui> diff --git a/korundum/rubylib/korundum/Korundum.cpp b/korundum/rubylib/korundum/Korundum.cpp new file mode 100644 index 00000000..6cd3045a --- /dev/null +++ b/korundum/rubylib/korundum/Korundum.cpp @@ -0,0 +1,1183 @@ +/*************************************************************************** + Korundum.cpp - Runtime for KDE services, DCOP etc + ------------------- + begin : Sun Sep 28 2003 + copyright : (C) 2003-2004 by Richard Dale + email : Richard_Dale@tipitina.demon.co.uk + ***************************************************************************/ + +/*************************************************************************** + * * + * This program 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; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include <qobject.h> +#include <qstringlist.h> +#include <qmap.h> +#include <qdatastream.h> + +#include <kdeversion.h> +#include <dcopclient.h> +#include <dcopobject.h> +#include <dcopref.h> +#include <kapplication.h> +#include <kurl.h> +#if KDE_VERSION >= 0x030200 +#include <kconfigskeleton.h> +#endif +#include <kio/global.h> +#include <kparts/browserextension.h> +#include <kde_terminal_interface.h> + +#include <ruby.h> + +#include <marshall.h> +#include <qtruby.h> +#include <smokeruby.h> +#include <smoke.h> + +extern "C" { +extern VALUE qt_internal_module; +extern VALUE kconfigskeleton_class; +extern VALUE kconfigskeleton_itemenum_choice_class; +extern VALUE kio_udsatom_class; +extern VALUE konsole_part_class; +extern VALUE set_obj_info(const char * className, smokeruby_object * o); +extern void set_kde_resolve_classname(const char * (*kde_resolve_classname) (Smoke*, int, void *)); +extern const char * kde_resolve_classname(Smoke* smoke, int classId, void * ptr); +}; + +extern TypeHandler KDE_handlers[]; +extern void install_handlers(TypeHandler *); +extern Smoke *qt_Smoke; + + +static VALUE kde_internal_module; +Marshall::HandlerFn getMarshallFn(const SmokeType &type); + +/* + Copy items from the stack to the stream, each item has a corresponding description in the + args array of MocArguments. Used for marshalling the args to DCOP calls and sends, emitting + DCOP signals, and converting the return value of a DCOP slot to a stream. +*/ +static void +smokeStackToStream(Marshall *m, Smoke::Stack stack, QDataStream* stream, int items, MocArgument* args) +{ + for(int i = 0; i < items; i++) { + switch(args[i].argType) { + case xmoc_bool: + *stream << stack[i].s_bool; + break; + case xmoc_int: + *stream << stack[i].s_int; + break; + case xmoc_double: + *stream << stack[i].s_double; + break; + case xmoc_charstar: + *stream << (char *) stack[i].s_voidp; + break; + case xmoc_QString: + { + QString temp((const QString&) *((QString *) stack[i].s_voidp)); + *stream << temp; + } + break; + default: + { + const SmokeType &t = args[i].st; + switch(t.elem()) { + case Smoke::t_bool: + *stream << stack[i].s_bool; + break; + case Smoke::t_char: + *stream << stack[i].s_char; + break; + case Smoke::t_uchar: + *stream << stack[i].s_uchar; + break; + case Smoke::t_short: + *stream << stack[i].s_short; + break; + case Smoke::t_ushort: + *stream << stack[i].s_ushort; + break; + case Smoke::t_int: + *stream << stack[i].s_int; + break; + case Smoke::t_uint: + *stream << stack[i].s_uint; + break; + case Smoke::t_long: + *stream << stack[i].s_long; + break; + case Smoke::t_ulong: + *stream << stack[i].s_ulong; + break; + case Smoke::t_float: + *stream << stack[i].s_float; + break; + case Smoke::t_double: + *stream << stack[i].s_double; + break; + case Smoke::t_enum: + m->unsupported(); + break; + case Smoke::t_class: + case Smoke::t_voidp: + { + // Special case any types which are in the Smoke runtime, but + // don't have QDataStream '<<' methods + if (strcmp(t.name(), "QCString") == 0) { + QCString temp((const QCString&) *((QCString *) stack[i].s_voidp)); + *stream << temp; + break; + } else if (strcmp(t.name(), "QCStringList") == 0) { + QCStringList temp((const QCStringList&) *((QCStringList *) stack[i].s_voidp)); + *stream << temp; + break; + } else if (strcmp(t.name(), "QStringList") == 0) { + QStringList temp((const QStringList&) *((QStringList *) stack[i].s_voidp)); + *stream << temp; + break; + } else if (strcmp(t.name(), "KURL::List") == 0) { + KURL::List temp((const KURL::List&) *((KURL::List *) stack[i].s_voidp)); + *stream << temp; + break; + } else if (strcmp(t.name(), "QMap<QCString,DCOPRef>") == 0) { + QMap<QCString,DCOPRef> temp((const QMap<QCString,DCOPRef>&) *((QMap<QCString,DCOPRef>*) stack[i].s_voidp)); + *stream << temp; + break; + } + + // Look for methods of the form: QDataStream & operator<<(QDataStream&, const MyClass&) + Smoke::Index meth = t.smoke()->findMethod("QGlobalSpace", "operator<<##"); + Smoke::Index ix; + if (meth > 0) { + ix = t.smoke()->methodMaps[meth].method; + ix = -ix; // turn into ambiguousMethodList index + while (t.smoke()->ambiguousMethodList[ix]) { + Smoke::Method &method = t.smoke()->methods[t.smoke()->ambiguousMethodList[ix]]; + QString refType("const "); + refType += t.name(); + refType += "&"; + if ( strcmp( "QDataStream&", + t.smoke()->types[t.smoke()->argumentList[method.args+0]].name ) == 0 + && strcmp( refType.latin1(), + t.smoke()->types[t.smoke()->argumentList[method.args+1]].name ) == 0 ) + { + Smoke::ClassFn fn = t.smoke()->classes[method.classId].classFn; + Smoke::StackItem local_stack[3]; + local_stack[1].s_voidp = stream; + local_stack[2].s_voidp = stack[i].s_voidp; + // Call the QDataStream marshaller write method + // with the instance to be marshalled + (*fn)(method.method, 0, local_stack); + break; + } + ix++; + } + } + } + break; + default: + break; + } + } + } + } + return; +} + +/* + Copy items from the stream to the stack, each item has a corresponding description in the + args array of MocArguments. Used for marshalling the arguments to a DCOP slot invocation, + and for converting a dcop reply to a ruby value. +*/ +static void +smokeStackFromStream(Marshall *m, Smoke::Stack stack, QDataStream* stream, int items, MocArgument* args) +{ + for(int i = 0; i < items; i++) { + switch(args[i].argType) { + case xmoc_bool: + { + *stream >> stack[i].s_bool; + break; + } + case xmoc_int: + { + *stream >> stack[i].s_int; + break; + } + case xmoc_double: + *stream >> stack[i].s_double; + break; + case xmoc_charstar: + *stream >> (char *&) stack[i].s_voidp; + break; + case xmoc_QString: + { + QString temp; + *stream >> temp; + stack[i].s_voidp = new QString(temp); + } + break; + default: // case xmoc_ptr: + { + const SmokeType &t = args[i].st; + switch(t.elem()) { + case Smoke::t_bool: + { + *stream >> stack[i].s_bool; + break; + } + case Smoke::t_char: + { + *stream >> stack[i].s_char; + break; + } + case Smoke::t_uchar: + { + *stream >> stack[i].s_uchar; + break; + } + case Smoke::t_short: + { + *stream >> stack[i].s_short; + break; + } + case Smoke::t_ushort: + { + *stream >> stack[i].s_ushort; + break; + } + case Smoke::t_int: + { + *stream >> stack[i].s_int; + break; + } + case Smoke::t_uint: + { + *stream >> stack[i].s_uint; + break; + } + case Smoke::t_long: + { + *stream >> stack[i].s_long; + break; + } + case Smoke::t_ulong: + { + *stream >> stack[i].s_ulong; + break; + } + case Smoke::t_float: + *stream >> stack[i].s_float; + break; + case Smoke::t_double: + *stream >> stack[i].s_double; + break; + case Smoke::t_enum: + m->unsupported(); + break; + case Smoke::t_class: + case Smoke::t_voidp: + { + // Special case any types which are in the Smoke runtime, but + // don't have QDataStream '>>' methods + if (strcmp(t.name(), "QCString") == 0) { + QCString temp; + *stream >> temp; + stack[i].s_voidp = new QCString(temp); + break; + } else if (strcmp(t.name(), "QCStringList") == 0) { + QCStringList temp; + *stream >> temp; + stack[i].s_voidp = new QCStringList(temp); + break; + } else if (strcmp(t.name(), "QStringList") == 0) { + QStringList temp; + *stream >> temp; + stack[i].s_voidp = new QStringList(temp); + break; + } else if (strcmp(t.name(), "KURL::List") == 0) { + KURL::List temp; + *stream >> temp; + stack[i].s_voidp = new KURL::List(temp); + break; + } else if (strcmp(t.name(), "QMap<QCString,DCOPRef>") == 0) { + QMap<QCString,DCOPRef> temp; + *stream >> temp; + stack[i].s_voidp = new QMap<QCString,DCOPRef>(temp); + break; + } + + // First construct an instance to read the QDataStream into, + // so look for a no args constructor + Smoke::Index ctorId = t.smoke()->idMethodName(t.name()); + Smoke::Index ctorMeth = t.smoke()->findMethod(t.classId(), ctorId); + Smoke::Index ctor = t.smoke()->methodMaps[ctorMeth].method; + if(ctor < 1) { + stack[i].s_voidp = 0; + m->unsupported(); + break; // Ambiguous or non-existent method, shouldn't happen with a no arg constructor + } + // Okay, ctor is the constructor. Time to call it. + Smoke::StackItem ctor_stack[1]; + ctor_stack[0].s_voidp = 0; + Smoke::ClassFn classfn = t.smoke()->classes[t.classId()].classFn; + (*classfn)(t.smoke()->methods[ctor].method, 0, ctor_stack); + stack[i].s_voidp = ctor_stack[0].s_voidp; + + // Look for methods of the form: QDataStream & operator>>(QDataStream&, MyClass&) + Smoke::Index meth = t.smoke()->findMethod("QGlobalSpace", "operator>>##"); + Smoke::Index ix; + if (meth > 0) { + ix = t.smoke()->methodMaps[meth].method; + ix = -ix; // turn into ambiguousMethodList index + while (t.smoke()->ambiguousMethodList[ix]) { + Smoke::Method &method = t.smoke()->methods[t.smoke()->ambiguousMethodList[ix]]; + QString refType(t.name()); + refType += "&"; + if ( strcmp( "QDataStream&", + t.smoke()->types[t.smoke()->argumentList[method.args+0]].name ) == 0 + && strcmp( refType.latin1(), + t.smoke()->types[t.smoke()->argumentList[method.args+1]].name ) == 0 ) + { + Smoke::ClassFn fn = t.smoke()->classes[method.classId].classFn; + Smoke::StackItem local_stack[3]; + local_stack[1].s_voidp = stream; + local_stack[2].s_voidp = stack[i].s_voidp; + // Call the QDataStream marshaller read method + // on the instance to be marshalled + (*fn)(method.method, 0, local_stack); + break; + } + ix++; + } + } + } + break; + } + } + } + } +} + +/* + Converts a QByteArray returned from a DCOP call to a ruby value. +*/ +class DCOPReturn : public Marshall { + MocArgument * _replyType; + Smoke::Stack _stack; + VALUE * _result; +public: + DCOPReturn(QDataStream & retval, VALUE * result, VALUE replyType) + { + _result = result; + VALUE temp = rb_funcall(qt_internal_module, rb_intern("getMocArguments"), 1, replyType); + Data_Get_Struct(rb_ary_entry(temp, 1), MocArgument, _replyType); + _stack = new Smoke::StackItem[1]; + smokeStackFromStream(this, _stack, &retval, 1, _replyType); + Marshall::HandlerFn fn = getMarshallFn(type()); + (*fn)(this); + } + + SmokeType type() { + return _replyType[0].st; + } + Marshall::Action action() { return Marshall::ToVALUE; } + Smoke::StackItem &item() { return _stack[0]; } + VALUE * var() { + return _result; + } + + void unsupported() + { + rb_raise(rb_eArgError, "Cannot handle '%s' as DCOP return-type", type().name()); + } + Smoke *smoke() { return type().smoke(); } + + void next() {} + + bool cleanup() { return false; } + + ~DCOPReturn() + { + delete[] _stack; + } +}; + +class DCOPCall : public Marshall { + VALUE _obj; + QCString & _remFun; + int _items; + VALUE *_sp; + QByteArray *_data; + QDataStream *_stream; + int _id; + MocArgument *_args; + bool _useEventLoop; + int _timeout; + int _cur; + Smoke::Stack _stack; + VALUE _result; + bool _called; +public: + DCOPCall(VALUE obj, QCString & remFun, int items, VALUE *sp, VALUE args, bool useEventLoop, int timeout) : + _obj(obj), _remFun(remFun), _items(items), _sp(sp), + _useEventLoop(useEventLoop), _timeout(timeout), _cur(-1), _called(false) + { + _data = new QByteArray(); + _stream = new QDataStream(*_data, IO_WriteOnly); + Data_Get_Struct(rb_ary_entry(args, 1), MocArgument, _args); + _stack = new Smoke::StackItem[_items]; + _result = Qnil; + } + + ~DCOPCall() + { + delete[] _stack; + delete _data; + delete _stream; + } + const MocArgument &arg() { return _args[_cur]; } + SmokeType type() { return arg().st; } + Marshall::Action action() { return Marshall::FromVALUE; } + Smoke::StackItem &item() { return _stack[_cur]; } + VALUE * var() { + if(_cur < 0) return &_result; + return _sp + _cur; + } + + void unsupported() + { + rb_raise(rb_eArgError, "Cannot handle '%s' as a DCOP call argument", type().name()); + } + + Smoke *smoke() { return type().smoke(); } + + void dcopCall() + { + if(_called) return; + _called = true; + + smokeStackToStream(this, _stack, _stream, _items, _args); + smokeruby_object *o = value_obj_info(_obj); + DCOPRef * dcopRef = (DCOPRef *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("DCOPRef")); + DCOPClient* dc = dcopRef->dcopClient(); + QCString replyType; + QByteArray dataReceived; +#if KDE_VERSION >= 0x030200 + bool ok = dc->call(dcopRef->app(), dcopRef->obj(), _remFun, *_data, replyType, dataReceived, _useEventLoop, _timeout); +#else + bool ok = dc->call(dcopRef->app(), dcopRef->obj(), _remFun, *_data, replyType, dataReceived, _useEventLoop); +#endif + + if (!ok) { + // Note that a failed dcop call returns 'nil', not 'false' + _result = Qnil; + return; + } else if (replyType == "void" || replyType == "ASYNC") { + _result = Qtrue; + return; + } + + QDataStream ds(dataReceived, IO_ReadOnly); + + if (replyType == "QValueList<DCOPRef>") { + // Special case QValueList<DCOPRef> as a QDataStream marshaller + // isn't in the Smoke runtime + QValueList<DCOPRef> valuelist; + ds >> valuelist; + _result = rb_ary_new(); + for (QValueListIterator<DCOPRef> it = valuelist.begin(); it != valuelist.end(); ++it) { + void *p = new DCOPRef(*it); + VALUE obj = getPointerObject(p); + + if (obj == Qnil) { + smokeruby_object * o = ALLOC(smokeruby_object); + o->classId = qt_Smoke->idClass("DCOPRef"); + o->smoke = qt_Smoke; + o->ptr = p; + o->allocated = true; + obj = set_obj_info("KDE::DCOPRef", o); + } + + rb_ary_push(_result, obj); + } + } else if (replyType == "QValueList<QCString>") { + // And special case this type too + QValueList<QCString> propertyList; + ds >> propertyList; + _result = rb_ary_new(); + for (QValueListIterator<QCString> it = propertyList.begin(); it != propertyList.end(); ++it) { + rb_ary_push(_result, rb_str_new2((const char *) *it)); + } + } else if (replyType == "QValueList<int>") { + // And special case this type too + QValueList<int> propertyList; + ds >> propertyList; + _result = rb_ary_new(); + for (QValueListIterator<int> it = propertyList.begin(); it != propertyList.end(); ++it) { + rb_ary_push(_result, INT2NUM(*it)); + } + } else if (replyType == "QMap<QString,DCOPRef>") { + // And another.. + QMap<QString,DCOPRef> actionMap; + ds >> actionMap; + _result = rb_hash_new(); + + QMap<QString,DCOPRef>::Iterator it; + for (it = actionMap.begin(); it != actionMap.end(); ++it) { + void *p = new DCOPRef(it.data()); + VALUE obj = getPointerObject(p); + + if (obj == Qnil) { + smokeruby_object * o = ALLOC(smokeruby_object); + o->classId = qt_Smoke->idClass("DCOPRef"); + o->smoke = qt_Smoke; + o->ptr = p; + o->allocated = true; + obj = set_obj_info("KDE::DCOPRef", o); + } + + rb_hash_aset(_result, rb_str_new2(it.key().latin1()), obj); + } + } else { + DCOPReturn dcopReturn(ds, &_result, rb_str_new2((const char *) replyType)); + } + } + + void next() + { + int oldcur = _cur; + _cur++; + + while(!_called && _cur < _items) { + Marshall::HandlerFn fn = getMarshallFn(type()); + (*fn)(this); + _cur++; + } + + dcopCall(); + _cur = oldcur; + } + + bool cleanup() { return true; } +}; + +class DCOPSend : public Marshall { + VALUE _obj; + QCString & _remFun; + QByteArray *_data; + QDataStream *_stream; + int _id; + MocArgument *_args; + int _items; + VALUE *_sp; + int _cur; + VALUE * _result; + Smoke::Stack _stack; + bool _called; +public: + DCOPSend(VALUE obj, QCString & remFun, int items, VALUE *sp, VALUE args, VALUE * result) : + _obj(obj), _remFun(remFun), _items(items), _sp(sp), _cur(-1), _result(result), _called(false) + { + _data = new QByteArray(); + _stream = new QDataStream(*_data, IO_WriteOnly); + Data_Get_Struct(rb_ary_entry(args, 1), MocArgument, _args); + _stack = new Smoke::StackItem[_items]; + } + + ~DCOPSend() + { + delete[] _stack; + delete _data; + delete _stream; + } + const MocArgument &arg() { return _args[_cur]; } + SmokeType type() { return arg().st; } + Marshall::Action action() { return Marshall::FromVALUE; } + Smoke::StackItem &item() { return _stack[_cur]; } + VALUE * var() { return _sp + _cur; } + + void unsupported() + { + rb_raise(rb_eArgError, "Cannot handle '%s' as a DCOP send argument", type().name()); + } + + Smoke *smoke() { return type().smoke(); } + + void dcopSend() + { + if(_called) return; + _called = true; + + smokeStackToStream(this, _stack, _stream, _items, _args); + smokeruby_object *o = value_obj_info(_obj); + DCOPRef * dcopRef = (DCOPRef *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("DCOPRef")); + DCOPClient* dc = dcopRef->dcopClient(); + bool ok = dc->send(dcopRef->app(), dcopRef->obj(), _remFun, *_data); + *_result = (ok ? Qtrue : Qfalse); + } + + void next() + { + int oldcur = _cur; + _cur++; + + while(!_called && _cur < _items) { + Marshall::HandlerFn fn = getMarshallFn(type()); + (*fn)(this); + _cur++; + } + + dcopSend(); + _cur = oldcur; + } + + bool cleanup() { return true; } +}; + +class EmitDCOPSignal : public Marshall { + VALUE _obj; + const char * _signalName; + QByteArray *_data; + QDataStream *_stream; + int _id; + MocArgument *_args; + VALUE *_sp; + int _items; + int _cur; + Smoke::Stack _stack; + bool _called; +public: + EmitDCOPSignal(VALUE obj, const char * signalName, int items, VALUE *sp, VALUE args) : + _obj(obj), _signalName(signalName), _sp(sp), _items(items), _cur(-1), _called(false) + { + _data = new QByteArray(); + _stream = new QDataStream(*_data, IO_WriteOnly); + Data_Get_Struct(rb_ary_entry(args, 1), MocArgument, _args); + _stack = new Smoke::StackItem[_items]; + } + + ~EmitDCOPSignal() + { + delete[] _stack; + delete _stream; + delete _data; + } + const MocArgument &arg() { return _args[_cur]; } + SmokeType type() { return arg().st; } + Marshall::Action action() { return Marshall::FromVALUE; } + Smoke::StackItem &item() { return _stack[_cur]; } + VALUE * var() { return _sp + _cur; } + + void unsupported() + { + rb_raise(rb_eArgError, "Cannot handle '%s' as a DCOP signal argument", type().name()); + } + + Smoke *smoke() { return type().smoke(); } + + void emitSignal() + { + if(_called) return; + _called = true; + + smokeStackToStream(this, _stack, _stream, _items, _args); + smokeruby_object *o = value_obj_info(_obj); + DCOPObject * dcopObject = (DCOPObject *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("DCOPObject")); + dcopObject->emitDCOPSignal(_signalName, *_data); + } + + void next() + { + int oldcur = _cur; + _cur++; + + while(!_called && _cur < _items) { + Marshall::HandlerFn fn = getMarshallFn(type()); + (*fn)(this); + _cur++; + } + + emitSignal(); + _cur = oldcur; + } + + bool cleanup() { return true; } +}; + +/* + Converts a ruby value returned by a DCOP slot invocation to a QByteArray +*/ +class DCOPReplyValue : public Marshall { + MocArgument * _replyType; + Smoke::Stack _stack; + VALUE * _result; +public: + DCOPReplyValue(QByteArray & retval, VALUE * result, VALUE replyType) + { + QDataStream _retval(retval, IO_WriteOnly); + _result = result; + Data_Get_Struct(rb_ary_entry(replyType, 1), MocArgument, _replyType); + _stack = new Smoke::StackItem[1]; + Marshall::HandlerFn fn = getMarshallFn(type()); + (*fn)(this); + smokeStackToStream(this, _stack, &_retval, 1, _replyType); + } + + SmokeType type() { + return _replyType[0].st; + } + Marshall::Action action() { return Marshall::FromVALUE; } + Smoke::StackItem &item() { return _stack[0]; } + VALUE * var() { + return _result; + } + + void unsupported() + { + rb_raise(rb_eArgError, "Cannot handle '%s' as DCOP reply-type", type().name()); + } + Smoke *smoke() { return type().smoke(); } + + void next() {} + + bool cleanup() { return false; } + + ~DCOPReplyValue() { + delete[] _stack; + } +}; + +class InvokeDCOPSlot : public Marshall { + VALUE _obj; + ID _slotname; + int _items; + MocArgument * _args; + QDataStream * _stream; + const char * _replyTypeName; + VALUE _replyType; + QByteArray * _retval; + int _cur; + bool _called; + VALUE * _sp; + Smoke::Stack _stack; +public: + const MocArgument &arg() { return _args[_cur]; } + SmokeType type() { return arg().st; } + Marshall::Action action() { return Marshall::ToVALUE; } + Smoke::StackItem &item() { return _stack[_cur]; } + VALUE * var() { return _sp + _cur; } + Smoke *smoke() { return type().smoke(); } + bool cleanup() { return false; } + + void unsupported() + { + rb_raise(rb_eArgError, "Cannot handle '%s' as DCOP slot argument\n", type().name()); + } + + void copyArguments() + { + smokeStackFromStream(this, _stack, _stream, _items, _args); + return; + } + + void invokeSlot() + { + if (_called) { + return; + } + _called = true; + VALUE result = rb_funcall2(_obj, _slotname, _items, _sp); + + if ( strcmp(_replyTypeName, "QValueList<DCOPRef>") == 0 + && TYPE(result) == T_ARRAY ) + { + // Special case QValueList<DCOPRef> as a QDataStream marshaller + // isn't in the Smoke runtime + QValueList<DCOPRef> windowList; + + for (long i = 0; i < RARRAY(result)->len; i++) { + VALUE item = rb_ary_entry(result, i); + smokeruby_object *o = value_obj_info(item); + if( !o || !o->ptr) + continue; + void * ptr = o->ptr; + ptr = o->smoke->cast(ptr, o->classId, o->smoke->idClass("DCOPRef")); + windowList.append((DCOPRef)*(DCOPRef*)ptr); + } + QDataStream retval(*_retval, IO_WriteOnly); + retval << windowList; + } else if ( strcmp(_replyTypeName, "QValueList<QCString>") == 0 + && TYPE(result) == T_ARRAY ) + { + // And special case this type too + QValueList<QCString> propertyList; + + for (long i = 0; i < RARRAY(result)->len; i++) { + VALUE item = rb_ary_entry(result, i); + propertyList.append(QCString(StringValuePtr(item))); + } + QDataStream retval(*_retval, IO_WriteOnly); + retval << propertyList; + } else if ( strcmp(_replyTypeName, "QMap<QString,DCOPRef>") == 0 + && TYPE(result) == T_HASH ) + { + // And another.. + QMap<QString,DCOPRef> actionMap; + // Convert the ruby hash to an array of key/value arrays + VALUE temp = rb_funcall(result, rb_intern("to_a"), 0); + + for (long i = 0; i < RARRAY(temp)->len; i++) { + VALUE action = rb_ary_entry(rb_ary_entry(temp, i), 0); + VALUE item = rb_ary_entry(rb_ary_entry(temp, i), 1); + + smokeruby_object *o = value_obj_info(item); + if( !o || !o->ptr) + continue; + void * ptr = o->ptr; + ptr = o->smoke->cast(ptr, o->classId, o->smoke->idClass("DCOPRef")); + + actionMap[QString(StringValuePtr(action))] = (DCOPRef)*(DCOPRef*)ptr; + } + QDataStream retval(*_retval, IO_WriteOnly); + retval << actionMap; + } else if (_replyType != Qnil) { + DCOPReplyValue dcopReply(*_retval, &result, _replyType); + } + } + + void next() + { + int oldcur = _cur; + _cur++; + + while(!_called && _cur < _items) { + Marshall::HandlerFn fn = getMarshallFn(type()); + (*fn)(this); + _cur++; + } + + invokeSlot(); + _cur = oldcur; + } + + InvokeDCOPSlot(VALUE obj, ID slotname, VALUE args, QByteArray& data, VALUE replyTypeName, VALUE replyType, QByteArray& returnValue) : + _obj(obj), _slotname(slotname), _replyType(replyType), _cur(-1), _called(false) + { + _replyTypeName = StringValuePtr(replyTypeName); + _items = NUM2INT(rb_ary_entry(args, 0)); + _stream = new QDataStream(data, IO_ReadOnly); + _retval = &returnValue; + + Data_Get_Struct(rb_ary_entry(args, 1), MocArgument, _args); + _sp = ALLOC_N(VALUE, _items); + _stack = new Smoke::StackItem[_items]; + + copyArguments(); + } + + ~InvokeDCOPSlot() { + delete[] _stack; + delete _stream; + for(int i=0;i<_items;++i) { + free(_sp++); + } + } +}; + +extern "C" { +extern void Init_qtruby(); +extern void set_new_kde(VALUE (*new_kde) (int, VALUE *, VALUE)); +extern void set_kconfigskeletonitem_immutable(VALUE (*kconfigskeletonitem_immutable) (VALUE)); +extern void set_kde_resolve_classname(const char * (*kde_resolve_classname) (Smoke*, int, void *)); +extern const char * kde_resolve_classname(Smoke* smoke, int classId, void * ptr); +extern VALUE new_qt(int argc, VALUE * argv, VALUE klass); +extern VALUE qt_module; +extern VALUE qt_internal_module; +extern VALUE qt_base_class; +extern VALUE kde_module; +extern VALUE kio_module; +extern VALUE kparts_module; +extern VALUE khtml_module; + +VALUE +getdcopinfo(VALUE self, QString & signalname) +{ + VALUE member = rb_funcall( kde_internal_module, + rb_intern("fullSignalName"), + 2, self, rb_str_new2(signalname) ); + signalname.setLatin1(StringValuePtr(member)); + return rb_funcall( qt_internal_module, + rb_intern("getMocArguments"), + 1, member ); +} + +VALUE +k_dcop_signal(int argc, VALUE * argv, VALUE self) +{ + VALUE dcopObject = rb_funcall(kde_module, rb_intern("createDCOPObject"), 1, self); + + QString signalname(rb_id2name(rb_frame_last_func())); + VALUE args = getdcopinfo(self, signalname); + + if(args == Qnil) return Qfalse; + + EmitDCOPSignal signal(dcopObject, signalname.latin1(), argc, argv, args); + signal.next(); + + return Qtrue; +} + +static VALUE +dcop_functions(VALUE self) +{ + VALUE dcopObject = rb_funcall(kde_module, rb_intern("createDCOPObject"), 1, self); + return rb_funcall(dcopObject, rb_intern("functions"), 0); +} + +static VALUE +dcop_interfaces(VALUE self) +{ + VALUE dcopObject = rb_funcall(kde_module, rb_intern("createDCOPObject"), 1, self); + return rb_funcall(dcopObject, rb_intern("interfaces"), 0); +} + +static VALUE +dcop_connect_signal(VALUE self, VALUE sender, VALUE senderObj, VALUE signal, VALUE slot, VALUE volatile_connect) +{ + VALUE dcopObject = rb_funcall(kde_module, rb_intern("createDCOPObject"), 1, self); + return rb_funcall(dcopObject, rb_intern("connectDCOPSignal"), 5, sender, senderObj, signal, slot, volatile_connect); +} + +static VALUE +dcop_disconnect_signal(VALUE self, VALUE sender, VALUE senderObj, VALUE signal, VALUE slot) +{ + VALUE dcopObject = rb_funcall(kde_module, rb_intern("createDCOPObject"), 1, self); + return rb_funcall(dcopObject, rb_intern("disconnectDCOPSignal"), 4, sender, senderObj, signal, slot); +} + +static VALUE +dcop_process(VALUE /*self*/, VALUE target, VALUE slotname, VALUE args, VALUE data, VALUE replyTypeName, VALUE replyType, VALUE replyData) +{ + smokeruby_object *o = value_obj_info(data); + if (o == 0 || o->ptr == 0) { + return Qfalse; + } + QByteArray * dataArray = (QByteArray*) o->ptr; + + o = value_obj_info(replyData); + if (o == 0 || o->ptr == 0) { + return Qfalse; + } + QByteArray * replyArray = (QByteArray*) o->ptr; + + InvokeDCOPSlot dcopSlot(target, rb_intern(StringValuePtr(slotname)), args, *dataArray, replyTypeName, replyType, *replyArray); + dcopSlot.next(); + + return Qtrue; +} + +static VALUE +dcop_call(int argc, VALUE * argv, VALUE /*self*/) +{ + QCString fun(StringValuePtr(argv[1])); + VALUE args = argv[2]; + bool useEventLoop = (argv[argc-2] == Qtrue ? true : false); + int timeout = NUM2INT(argv[argc-1]); + + DCOPCall dcopCall(argv[0], fun, argc-5, argv+3, args, useEventLoop, timeout); + dcopCall.next(); + + return *(dcopCall.var()); +} + +static VALUE +dcop_send(int argc, VALUE * argv, VALUE /*self*/) +{ + QCString fun(StringValuePtr(argv[1])); + VALUE args = argv[2]; + VALUE result = Qnil; + + DCOPSend dcopSend(argv[0], fun, argc-3, argv+3, args, &result); + dcopSend.next(); + + return result; +} + +static VALUE +new_kde(int argc, VALUE * argv, VALUE klass) +{ + VALUE instance = new_qt(argc, argv, klass); + + if (rb_funcall(kde_module, rb_intern("hasDCOPSignals"), 1, klass) == Qtrue) { + VALUE signalNames = rb_funcall(kde_module, rb_intern("getDCOPSignalNames"), 1, klass); + for (long index = 0; index < RARRAY(signalNames)->len; index++) { + VALUE signal = rb_ary_entry(signalNames, index); + rb_define_method(klass, StringValuePtr(signal), (VALUE (*) (...)) k_dcop_signal, -1); + } + } + + if ( rb_funcall(kde_module, rb_intern("hasDCOPSlots"), 1, klass) == Qtrue + || rb_funcall(kde_module, rb_intern("hasDCOPSignals"), 1, klass) == Qtrue ) + { + VALUE dcop_object = rb_funcall(kde_module, rb_intern("createDCOPObject"), 1, instance); + if (dcop_object != Qnil) { + rb_define_method(klass, "interfaces", (VALUE (*) (...)) dcop_interfaces, 0); + rb_define_method(klass, "functions", (VALUE (*) (...)) dcop_functions, 0); + rb_define_method(klass, "connectDCOPSignal", (VALUE (*) (...)) dcop_connect_signal, 5); + rb_define_method(klass, "disconnectDCOPSignal", (VALUE (*) (...)) dcop_disconnect_signal, 4); + } + } + + return instance; +} + +#if KDE_VERSION >= 0x030200 + +static VALUE +kconfigskeletonitem_immutable(VALUE self) +{ + smokeruby_object *o = value_obj_info(self); + KConfigSkeletonItem * item = (KConfigSkeletonItem *) o->ptr; + return item->isImmutable() ? Qtrue : Qfalse; +} + +static VALUE +config_additem(int argc, VALUE * argv, VALUE self) +{ + smokeruby_object *o = value_obj_info(self); + KConfigSkeleton * config = (KConfigSkeleton *) o->ptr; + + if (argc < 1 || argc > 2) { + rb_raise(rb_eArgError, "wrong number of arguments(%d for 2)\n", argc); + } + + if (TYPE(argv[0]) != T_DATA) { + rb_raise(rb_eArgError, "wrong argument type, expected KDE::ConfigSkeletonItem\n", argc); + } + + smokeruby_object *c = value_obj_info(argv[0]); + KConfigSkeletonItem * item = (KConfigSkeletonItem *) c->ptr; + + if (argc == 1) { + config->addItem(item); + } else { + config->addItem(item, QString(StringValuePtr(argv[1]))); + } + + return self; +} + +#endif + +static VALUE +konsole_part_startprogram(VALUE self, VALUE value_program, VALUE value_args) +{ + smokeruby_object * o = value_obj_info(self); + TerminalInterface * t = static_cast<TerminalInterface*>(((KParts::ReadOnlyPart*) o->ptr)->qt_cast("TerminalInterface")); + + QStrList *args = new QStrList; + + if (value_args != Qnil) { + for (long i = 0; i < RARRAY(value_args)->len; i++) { + VALUE item = rb_ary_entry(value_args, i); + args->append(QString::fromLatin1(StringValuePtr(item), RSTRING(item)->len)); + } + } + + t->startProgram(QString::fromLatin1(StringValuePtr(value_program)), args); + return self; +} + +static VALUE +konsole_part_showshellindir(VALUE self, VALUE value_dir) +{ + smokeruby_object * o = value_obj_info(self); + TerminalInterface * t = static_cast<TerminalInterface*>(((KParts::ReadOnlyPart*) o->ptr)->qt_cast("TerminalInterface")); + t->showShellInDir(StringValuePtr(value_dir)); + return self; +} + +static VALUE +konsole_part_sendinput(VALUE self, VALUE value_text) +{ + smokeruby_object * o = value_obj_info(self); + TerminalInterface * t = static_cast<TerminalInterface*>(((KParts::ReadOnlyPart*) o->ptr)->qt_cast("TerminalInterface")); + t->sendInput(StringValuePtr(value_text)); + return self; +} + +#if KDE_VERSION >= 0x030500 +static VALUE +konsole_part_setautostartshell(VALUE self, VALUE enabled) +{ + smokeruby_object * o = value_obj_info(self); + ExtTerminalInterface * t = static_cast<ExtTerminalInterface*>(((KParts::ReadOnlyPart*) o->ptr)->qt_cast("ExtTerminalInterface")); + t->setAutoStartShell(enabled == Qtrue); + return self; +} + +static VALUE +konsole_part_setautodestroy(VALUE self, VALUE enabled) +{ + smokeruby_object * o = value_obj_info(self); + ExtTerminalInterface * t = static_cast<ExtTerminalInterface*>(((KParts::ReadOnlyPart*) o->ptr)->qt_cast("ExtTerminalInterface")); + t->setAutoDestroy(enabled == Qtrue); + return self; +} +#endif + +void +Init_korundum() +{ + if (qt_internal_module != Qnil) { + rb_fatal("require 'Korundum' must not follow require 'Qt'\n"); + return; + } + + set_new_kde(new_kde); +#if KDE_VERSION >= 0x030200 + set_kconfigskeletonitem_immutable(kconfigskeletonitem_immutable); +#endif + set_kde_resolve_classname(kde_resolve_classname); + + // The Qt extension is linked against libsmokeqt.so, but Korundum links against + // libsmokekde.so only. Specifying both a 'require Qt' and a 'require Korundum', + // would give a link error (see the rb_fatal() error above). + // So call the Init_qtruby() initialization function explicitely, not via 'require Qt' + // (Qt.o is linked into libqtruby.so, as well as the Qt.so extension). + Init_qtruby(); + install_handlers(KDE_handlers); + + kde_internal_module = rb_define_module_under(kde_module, "Internal"); + rb_define_singleton_method(kde_module, "dcop_process", (VALUE (*) (...)) dcop_process, 7); + rb_define_singleton_method(kde_module, "dcop_call", (VALUE (*) (...)) dcop_call, -1); + rb_define_singleton_method(kde_module, "dcop_send", (VALUE (*) (...)) dcop_send, -1); + +#if KDE_VERSION >= 0x030200 + rb_define_method(kconfigskeleton_class, "addItem", (VALUE (*) (...)) config_additem, -1); +#endif + + rb_define_method(konsole_part_class, "startProgram", (VALUE (*) (...)) konsole_part_startprogram, 2); + rb_define_method(konsole_part_class, "showShellInDir", (VALUE (*) (...)) konsole_part_showshellindir, 1); + rb_define_method(konsole_part_class, "sendInput", (VALUE (*) (...)) konsole_part_sendinput, 1); +#if KDE_VERSION >= 0x030500 + rb_define_method(konsole_part_class, "setAutoStartShell", (VALUE (*) (...)) konsole_part_setautostartshell, 1); + rb_define_method(konsole_part_class, "autoStartShell=", (VALUE (*) (...)) konsole_part_setautostartshell, 1); + rb_define_method(konsole_part_class, "setAutoDestroy", (VALUE (*) (...)) konsole_part_setautodestroy, 1); + rb_define_method(konsole_part_class, "autoDestroy=", (VALUE (*) (...)) konsole_part_setautodestroy, 1); +#endif + + rb_require("KDE/korundum.rb"); +} + +}; diff --git a/korundum/rubylib/korundum/Makefile.am b/korundum/rubylib/korundum/Makefile.am new file mode 100644 index 00000000..c135f4e9 --- /dev/null +++ b/korundum/rubylib/korundum/Makefile.am @@ -0,0 +1,10 @@ +INCLUDES = -I$(top_srcdir)/smoke -I$(top_srcdir)/qtruby/rubylib/qtruby $(all_includes) -I$(RUBY_ARCHDIR) + +rubylibdir = $(RUBY_SITEARCHDIR) +rubylib_LTLIBRARIES = korundum.la +korundum_la_LDFLAGS = -module $(all_libraries) -version-info 0:0:0 +korundum_la_METASOURCES = AUTO +korundum_la_SOURCES = Korundum.cpp kdehandlers.cpp +korundum_la_LIBADD = $(LIB_KDE) $(top_builddir)/smoke/kde/libsmokekde.la $(top_builddir)/qtruby/rubylib/qtruby/libqtrubyinternal.la + +SUBDIRS = lib diff --git a/korundum/rubylib/korundum/configure.in.in b/korundum/rubylib/korundum/configure.in.in new file mode 100644 index 00000000..de265e6d --- /dev/null +++ b/korundum/rubylib/korundum/configure.in.in @@ -0,0 +1,15 @@ +AC_CHECK_PROG(RUBY, ruby, ruby) + +if test -z "$RUBY"; then + DO_NOT_COMPILE="$DO_NOT_COMPILE korundum" +else + AC_MSG_CHECKING(for ruby dirs) + RUBY_ARCHDIR=`ruby -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"archdir"@:>@)'` + RUBY_SITEARCHDIR=`ruby -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"sitearchdir"@:>@)'` + RUBY_SITEDIR=`ruby -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"sitelibdir"@:>@)'` + AC_MSG_RESULT([archdir $RUBY_ARCHDIR, sitearchdir $RUBY_SITEARCHDIR, sitedir $RUBY_SITEDIR]) + AC_SUBST(RUBY_ARCHDIR) + AC_SUBST(RUBY_SITEARCHDIR) + AC_SUBST(RUBY_SITEDIR) +fi + diff --git a/korundum/rubylib/korundum/kdehandlers.cpp b/korundum/rubylib/korundum/kdehandlers.cpp new file mode 100644 index 00000000..4d8d5741 --- /dev/null +++ b/korundum/rubylib/korundum/kdehandlers.cpp @@ -0,0 +1,1428 @@ +/*************************************************************************** + kdehandlers.cpp - KDE specific marshallers + ------------------- + begin : Sun Sep 28 2003 + copyright : (C) 2003 by Richard Dale + email : Richard_Dale@tipitina.demon.co.uk + ***************************************************************************/ + +/*************************************************************************** + * * + * This program 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; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include <qtruby.h> +#include <smokeruby.h> + +#include <kdeversion.h> +#include <dcopclient.h> +#include <dcopobject.h> +#include <dcopref.h> +#include <qptrlist.h> +#include <ktrader.h> +#include <kservicegroup.h> +#include <kservice.h> +#include <ksycocatype.h> +#include <kmainwindow.h> +#include <kfile.h> +#include <kfileview.h> +#include <kurl.h> +#include <kcmdlineargs.h> +#include <kaction.h> +#include <kdockwidget.h> +#include <kfiletreebranch.h> +#include <kfiletreeviewitem.h> +#include <khtml_part.h> +#include <kparts/plugin.h> +#include <kuserprofile.h> +#include <kaboutdata.h> +#include <karchive.h> +#if KDE_VERSION >= 0x030200 +#include <kconfigskeleton.h> +#include <kplugininfo.h> +#include <kmountpoint.h> +#endif +#include <kio/jobclasses.h> +#include <dom/dom_node.h> +#include <dom/dom_element.h> +#include <dom/dom_string.h> +#include <dom/html_element.h> + +extern "C" { +extern VALUE set_obj_info(const char * className, smokeruby_object * o); +}; + +extern bool isDerivedFromByName(Smoke *smoke, const char *className, const char *baseClassName); + +extern "C" { +/* + * Given an approximate classname and a kde instance, try to improve the resolution of the name + * by using the various KDE rtti mechanisms + */ +const char * +kde_resolve_classname(Smoke * smoke, int classId, void * ptr) +{ + if (isDerivedFromByName(smoke, smoke->classes[classId].className, "KArchiveEntry")) { + KArchiveEntry * entry = (KArchiveEntry *) smoke->cast(ptr, classId, smoke->idClass("KArchiveEntry")); + if (entry->isDirectory()) { + return "KDE::ArchiveDirectory"; + } else { + return "KDE::ArchiveFile"; + } + } else if (strcmp(smoke->classes[classId].className, "DOM::Node") == 0) { + DOM::Node * node = (DOM::Node *) smoke->cast(ptr, classId, smoke->idClass("DOM::Node")); + switch (node->nodeType()) { + case DOM::Node::ELEMENT_NODE: + if (((DOM::Element*)node)->isHTMLElement()) { + return "DOM::HTMLElement"; + } else { + return "DOM::Element"; + } + case DOM::Node::ATTRIBUTE_NODE: + return "DOM::Attr"; + case DOM::Node::TEXT_NODE: + return "DOM::Text"; + case DOM::Node::CDATA_SECTION_NODE: + return "DOM::CDATASection"; + case DOM::Node::ENTITY_REFERENCE_NODE: + return "DOM::EntityReference"; + case DOM::Node::ENTITY_NODE: + return "DOM::Entity"; + case DOM::Node::PROCESSING_INSTRUCTION_NODE: + return "DOM::ProcessingInstruction"; + case DOM::Node::COMMENT_NODE: + return "DOM::Comment"; + case DOM::Node::DOCUMENT_NODE: + return "DOM::Document"; + case DOM::Node::DOCUMENT_TYPE_NODE: + return "DOM::DocumentType"; + case DOM::Node::DOCUMENT_FRAGMENT_NODE: + return "DOM::DocumentFragment"; + case DOM::Node::NOTATION_NODE: + return "DOM::Notation"; + } + } + + return smoke->binding->className(classId); +} + +}; + +void marshall_QCStringList(Marshall *m) { + switch(m->action()) { + case Marshall::FromVALUE: + { + VALUE list = *(m->var()); + if (TYPE(list) != T_ARRAY) { + m->item().s_voidp = 0; + break; + } + + int count = RARRAY(list)->len; + QCStringList *stringlist = new QCStringList; + + for(long i = 0; i < count; i++) { + VALUE item = rb_ary_entry(list, i); + if(TYPE(item) != T_STRING) { + stringlist->append(QCString()); + continue; + } + stringlist->append(QCString(StringValuePtr(item), RSTRING(item)->len + 1)); + } + + m->item().s_voidp = stringlist; + m->next(); + + if(m->cleanup()) { + rb_ary_clear(list); + for(QCStringList::Iterator it = stringlist->begin(); it != stringlist->end(); ++it) + rb_ary_push(list, rb_str_new2(static_cast<const char *>(*it))); + delete stringlist; + } + break; + } + case Marshall::ToVALUE: + { + QCStringList *stringlist = static_cast<QCStringList *>(m->item().s_voidp); + if(!stringlist) { + *(m->var()) = Qnil; + break; + } + + VALUE av = rb_ary_new(); + for(QCStringList::Iterator it = stringlist->begin(); it != stringlist->end(); ++it) { + VALUE rv = rb_str_new2(static_cast<const char *>((*it))); + rb_ary_push(av, rv); + } + + if(m->cleanup()) + delete stringlist; + + *(m->var()) = av; + } + break; + default: + m->unsupported(); + break; + } +} + +#if defined (__i386__) && defined (__GNUC__) && __GNUC__ >= 2 +# define BREAKPOINT { __asm__ __volatile__ ("int $03"); } +#else +# define BREAKPOINT { fprintf(stderr, "hit ctrl-c\n"); int b = 0; while (b == 0) { ; } } +#endif + +void marshall_KCmdLineOptions(Marshall *m) { + switch(m->action()) { + case Marshall::FromVALUE: + { + VALUE optionslist = *(m->var()); + if (optionslist == Qnil + || TYPE(optionslist) != T_ARRAY + || RARRAY(optionslist)->len == 0 ) + { + m->item().s_voidp = 0; + break; + } + + // Allocate 'length + 1' entries, to include an all NULLs last entry + KCmdLineOptions *cmdLineOptions = (KCmdLineOptions *) calloc( RARRAY(optionslist)->len + 1, + sizeof(struct KCmdLineOptions) ); + + VALUE options; + long i; + for(i = 0; i < RARRAY(optionslist)->len; i++) { + options = rb_ary_entry(optionslist, i); + VALUE temp = rb_ary_entry(options, 0); + cmdLineOptions[i].name = StringValuePtr(temp); + temp = rb_ary_entry(options, 1); + cmdLineOptions[i].description = StringValuePtr(temp); + temp = rb_ary_entry(options, 2); + cmdLineOptions[i].def = StringValuePtr(temp); + } + cmdLineOptions[i].name = 0; + cmdLineOptions[i].description = 0; + cmdLineOptions[i].def = 0; + + + m->item().s_voidp = cmdLineOptions; + m->next(); + /* + if(m->cleanup()) { + rb_ary_clear(optionslist); + for(i = 0; cmdLineOptions[i].name; i++) + options = rb_ary_new(); + rb_ary_push(options, rb_str_new2(cmdLineOptions[i].name)); + rb_ary_push(options, rb_str_new2(cmdLineOptions[i].description)); + rb_ary_push(options, rb_str_new2(cmdLineOptions[i].def)); + rb_ary_push(optionslist, options); + } + */ + } + break; + case Marshall::ToVALUE: + { + } + break; + default: + m->unsupported(); + break; + } +} + +void marshall_WIdList(Marshall *m) { + switch(m->action()) { + case Marshall::FromVALUE: + { + VALUE list = *(m->var()); + if (TYPE(list) != T_ARRAY) { + m->item().s_voidp = 0; + break; + } + int count = RARRAY(list)->len; + QValueList<WId> *valuelist = new QValueList<WId>; + long i; + for(i = 0; i < count; i++) { + VALUE item = rb_ary_entry(list, i); + if(TYPE(item) != T_FIXNUM && TYPE(item) != T_BIGNUM) { + valuelist->append(0); + continue; + } + valuelist->append(NUM2LONG(item)); + } + + m->item().s_voidp = valuelist; + m->next(); + + if (!m->type().isConst()) { + rb_ary_clear(list); + for(QValueListIterator<WId> it = valuelist->begin(); + it != valuelist->end(); + ++it) + rb_ary_push(list, LONG2NUM((int)*it)); + } + + if (m->cleanup()) { + delete valuelist; + } + } + break; + case Marshall::ToVALUE: + { + QValueList<WId> *valuelist = (QValueList<WId>*)m->item().s_voidp; + if(!valuelist) { + *(m->var()) = Qnil; + break; + } + + VALUE av = rb_ary_new(); + + for(QValueListIterator<WId> it = valuelist->begin(); + it != valuelist->end(); + ++it) + rb_ary_push(av, LONG2NUM(*it)); + + *(m->var()) = av; + + if(m->cleanup()) + delete valuelist; + } + break; + default: + m->unsupported(); + break; + } +} + +void marshall_KMimeTypeList(Marshall *m) { + switch(m->action()) { + case Marshall::FromVALUE: + { + } + break; + case Marshall::ToVALUE: + { + KMimeType::List *offerList = (KMimeType::List*)m->item().s_voidp; + if(!offerList) { + *(m->var()) = Qnil; + break; + } + + VALUE av = rb_ary_new(); + + for(KMimeType::List::Iterator it = offerList->begin(); + it != offerList->end(); + ++it) { + KMimeType * item = new KMimeType (*(KMimeType*)((KMimeType::Ptr)(*it)).data()); + + VALUE obj = getPointerObject(item); + if(obj == Qnil) { + smokeruby_object * o = ALLOC(smokeruby_object); + o->smoke = m->smoke(); + o->classId = m->smoke()->idClass("KMimeType"); + o->ptr = item; + o->allocated = true; + obj = set_obj_info("KDE::MimeType", o); + } + rb_ary_push(av, obj); + } + + *(m->var()) = av; + + if(m->cleanup()) + delete offerList; + } + break; + default: + m->unsupported(); + break; + } +} + +void marshall_KMimeTypePtr(Marshall *m) { + switch(m->action()) { + case Marshall::FromVALUE: + { + } + break; + case Marshall::ToVALUE: + { + KMimeType::Ptr ptr(*(KMimeType::Ptr*)m->item().s_voidp); + if(ptr == 0) { + *(m->var()) = Qnil; + break; + } + KMimeType * mimeType = new KMimeType(*(KMimeType*)ptr); + + VALUE obj = getPointerObject(mimeType); + if(obj == Qnil) { + smokeruby_object * o = ALLOC(smokeruby_object); + o->smoke = m->smoke(); + o->classId = m->smoke()->idClass("KMimeType"); + o->ptr = mimeType; + o->allocated = true; + obj = set_obj_info("KDE::MimeType", o); + } + + *(m->var()) = obj; + + if(m->cleanup()) + ; + } + break; + default: + m->unsupported(); + break; + } +} + +void marshall_KServicePtr(Marshall *m) { + switch(m->action()) { + case Marshall::FromVALUE: + { + } + break; + case Marshall::ToVALUE: + { + KSharedPtr<KService> *ptr = new KSharedPtr<KService>(*(KSharedPtr<KService>*)m->item().s_voidp); + if(ptr == 0) { + *(m->var()) = Qnil; + break; + } + KService * service = ptr->data(); + + VALUE obj = getPointerObject(service); + if(obj == Qnil) { + smokeruby_object * o = ALLOC(smokeruby_object); + o->smoke = m->smoke(); + o->classId = m->smoke()->idClass("KService"); + o->ptr = service; + o->allocated = true; + obj = set_obj_info("KDE::Service", o); + } + + *(m->var()) = obj; + + if(m->cleanup()) + ; + } + break; + default: + m->unsupported(); + break; + } +} + +void marshall_KServiceList(Marshall *m) { + switch(m->action()) { + case Marshall::FromVALUE: + { + } + break; + case Marshall::ToVALUE: + { + KService::List *offerList = (KService::List*)m->item().s_voidp; + if(!offerList) { + *(m->var()) = Qnil; + break; + } + + VALUE av = rb_ary_new(); + + for(KService::List::Iterator it = offerList->begin(); + it != offerList->end(); + ++it) { + KSharedPtr<KService> *ptr = new KSharedPtr<KService>(*it); + KService * currentOffer = ptr->data(); + + VALUE obj = getPointerObject(currentOffer); + if(obj == Qnil) { + smokeruby_object * o = ALLOC(smokeruby_object); + o->smoke = m->smoke(); + o->classId = m->smoke()->idClass("KService"); + o->ptr = currentOffer; + o->allocated = false; + obj = set_obj_info("KDE::Service", o); + } + rb_ary_push(av, obj); + } + + *(m->var()) = av; + + if(m->cleanup()) + delete offerList; + } + break; + default: + m->unsupported(); + break; + } +} + +void marshall_KServiceGroupPtr(Marshall *m) { + switch(m->action()) { + case Marshall::FromVALUE: + { + } + break; + case Marshall::ToVALUE: + { + KServiceGroup::Ptr ptr(*(KServiceGroup::Ptr*)m->item().s_voidp); + if(ptr == 0) { + *(m->var()) = Qnil; + break; + } + KServiceGroup * serviceGroup = new KServiceGroup(*(KServiceGroup*)ptr); + + VALUE obj = getPointerObject(serviceGroup); + if(obj == Qnil) { + smokeruby_object * o = ALLOC(smokeruby_object); + o->smoke = m->smoke(); + o->classId = m->smoke()->idClass("KServiceGroup"); + o->ptr = serviceGroup; + o->allocated = true; + obj = set_obj_info("KDE::ServiceGroup", o); + } + + *(m->var()) = obj; + + if(m->cleanup()) + ; + } + break; + default: + m->unsupported(); + break; + } +} + +void marshall_KServiceTypeList(Marshall *m) { + switch(m->action()) { + case Marshall::FromVALUE: + { + } + break; + case Marshall::ToVALUE: + { + KServiceType::List *offerList = (KServiceType::List*)m->item().s_voidp; + if(!offerList) { + *(m->var()) = Qnil; + break; + } + + VALUE av = rb_ary_new(); + + for(KServiceType::List::Iterator it = offerList->begin(); + it != offerList->end(); + ++it) { + KServiceType * currentOffer = new KServiceType(*((KServiceType*)*it)); + + VALUE obj = getPointerObject(currentOffer); + if(obj == Qnil) { + smokeruby_object * o = ALLOC(smokeruby_object); + o->smoke = m->smoke(); + o->classId = m->smoke()->idClass("KServiceType"); + o->ptr = currentOffer; + o->allocated = true; + obj = set_obj_info("KDE::ServiceType", o); + } + rb_ary_push(av, obj); + } + + *(m->var()) = av; + + if(m->cleanup()) + delete offerList; + } + break; + default: + m->unsupported(); + break; + } +} + +void marshall_KServiceGroupList(Marshall *m) { + switch(m->action()) { + case Marshall::FromVALUE: + { + } + break; + case Marshall::ToVALUE: + { + KServiceGroup::List *offerList = (KServiceGroup::List*)m->item().s_voidp; + if(!offerList) { + *(m->var()) = Qnil; + break; + } + + VALUE av = rb_ary_new(); + + for(KServiceGroup::List::ConstIterator it = offerList->begin(); + it != offerList->end(); + ++it) { + KSycocaEntry *p = (*it); + VALUE obj = Qnil; + if (p->isType(KST_KService)) { + KService *s = static_cast<KService *>(p); + obj = getPointerObject(s); + if(obj == Qnil) { + smokeruby_object * o = ALLOC(smokeruby_object); + o->smoke = m->smoke(); + o->classId = m->smoke()->idClass("KService"); + o->ptr = s; + o->allocated = true; + obj = set_obj_info("KDE::Service", o); + } + } else if (p->isType(KST_KServiceGroup)) { + KServiceGroup *g = static_cast<KServiceGroup *>(p); + obj = getPointerObject(g); + if(obj == Qnil) { + smokeruby_object * o = ALLOC(smokeruby_object); + o->smoke = m->smoke(); + o->classId = m->smoke()->idClass("KServiceGroup"); + o->ptr = g; + o->allocated = true; + obj = set_obj_info("KDE::ServiceGroup", o); + } + } + + rb_ary_push(av, obj); + } + + *(m->var()) = av; + + if(m->cleanup()) + delete offerList; + } + break; + default: + m->unsupported(); + break; + } +} + +#if KDE_VERSION >= 0x030200 +void marshall_KMountPointList(Marshall *m) { + switch(m->action()) { + case Marshall::FromVALUE: + { + } + break; + case Marshall::ToVALUE: + { + KMountPoint::List *list = (KMountPoint::List*)m->item().s_voidp; + if(!list) { + *(m->var()) = Qnil; + break; + } + + VALUE av = rb_ary_new(); + + for(KMountPoint::List::Iterator it = list->begin(); + it != list->end(); + ++it) { + KMountPoint * item = new KMountPoint(*((KMountPoint*)*it)); + + VALUE obj = getPointerObject(item); + if(obj == Qnil) { + smokeruby_object * o = ALLOC(smokeruby_object); + o->smoke = m->smoke(); + o->classId = m->smoke()->idClass("KMountPoint"); + o->ptr = item; + o->allocated = true; + obj = set_obj_info("KDE::MountPoint", o); + } + rb_ary_push(av, obj); + } + + *(m->var()) = av; + + if(m->cleanup()) + delete list; + } + break; + default: + m->unsupported(); + break; + } +} + +void marshall_KPluginInfoList(Marshall *m) { + switch(m->action()) { + case Marshall::FromVALUE: + { + } + break; + case Marshall::ToVALUE: + { + KPluginInfo::List *valuelist = (KPluginInfo::List*)m->item().s_voidp; + if(!valuelist) { + *(m->var()) = Qnil; + break; + } + + VALUE av = rb_ary_new(); + + int ix = m->smoke()->idClass("KPluginInfo"); + const char * className = m->smoke()->binding->className(ix); + + for(KPluginInfo::List::Iterator it = valuelist->begin(); + it != valuelist->end(); + ++it) { + void *p = (*it); + + if(m->item().s_voidp == 0) { + *(m->var()) = Qnil; + break; + } + + VALUE obj = getPointerObject(p); + if(obj == Qnil) { + smokeruby_object * o = ALLOC(smokeruby_object); + o->smoke = m->smoke(); + o->classId = o->smoke->idClass("KPluginInfo"); + o->ptr = p; + o->allocated = false; + obj = set_obj_info(className, o); + } + rb_ary_push(av, obj); + } + + if(m->cleanup()) + delete valuelist; + else + *(m->var()) = av; + } + break; + default: + m->unsupported(); + break; + } +} +#endif + +void marshall_KActionPtrList(Marshall *m) { + switch(m->action()) { + case Marshall::FromVALUE: + { + } + break; + case Marshall::ToVALUE: + { + KActionPtrList *valuelist = (KActionPtrList*)m->item().s_voidp; + if (!valuelist) { + *(m->var()) = Qnil; + break; + } + + VALUE av = rb_ary_new(); + + int ix = m->smoke()->idClass("KAction"); + const char * className = m->smoke()->binding->className(ix); + + for ( KActionPtrList::Iterator it = valuelist->begin(); + it != valuelist->end(); + ++it ) + { + void *p = (*it); + + if (m->item().s_voidp == 0) { + *(m->var()) = Qnil; + break; + } + + VALUE obj = getPointerObject(p); + if (obj == Qnil) { + smokeruby_object * o = ALLOC(smokeruby_object); + o->smoke = m->smoke(); + o->classId = o->smoke->idClass("KAction"); + o->ptr = p; + o->allocated = false; + obj = set_obj_info(className, o); + } + rb_ary_push(av, obj); + } + + if (m->cleanup()) + delete valuelist; + else + *(m->var()) = av; + } + break; + default: + m->unsupported(); + break; + } +} + +void marshall_KTraderOfferList(Marshall *m) { + switch(m->action()) { + case Marshall::FromVALUE: + { + } + break; + case Marshall::ToVALUE: + { + KTrader::OfferList *offerList = (KTrader::OfferList*)m->item().s_voidp; + if(!offerList) { + *(m->var()) = Qnil; + break; + } + + VALUE av = rb_ary_new(); + + for(KTrader::OfferList::Iterator it = offerList->begin(); + it != offerList->end(); + ++it) { + KSharedPtr<KService> *ptr = new KSharedPtr<KService>(*it); + KService * currentOffer = ptr->data(); + + VALUE obj = getPointerObject(currentOffer); + if(obj == Qnil) { + smokeruby_object * o = ALLOC(smokeruby_object); + o->smoke = m->smoke(); + o->classId = m->smoke()->idClass("KService"); + o->ptr = currentOffer; + o->allocated = false; + obj = set_obj_info("KDE::Service", o); + } + rb_ary_push(av, obj); + } + + *(m->var()) = av; + + if(m->cleanup()) + delete offerList; + } + break; + default: + m->unsupported(); + break; + } +} + +void marshall_KURLList(Marshall *m) { + switch(m->action()) { + case Marshall::FromVALUE: + { + VALUE list = *(m->var()); + if (TYPE(list) != T_ARRAY) { + m->item().s_voidp = 0; + break; + } + int count = RARRAY(list)->len; + KURL::List *kurllist = new KURL::List; + long i; + for(i = 0; i < count; i++) { + VALUE item = rb_ary_entry(list, i); + // TODO do type checking! + smokeruby_object *o = value_obj_info(item); + if(!o || !o->ptr) + continue; + void *ptr = o->ptr; + ptr = o->smoke->cast( + ptr, // pointer + o->classId, // from + o->smoke->idClass("KURL") // to + ); + kurllist->append((KURL&)*(KURL*)ptr); + } + + m->item().s_voidp = kurllist; + m->next(); + + rb_ary_clear(list); + int ix = m->smoke()->idClass("KURL"); + const char * className = m->smoke()->binding->className(ix); + for ( KURL::List::Iterator it = kurllist->begin(); + it != kurllist->end(); + ++it ) + { + void *p = new KURL(*it); + VALUE obj = getPointerObject(p); + if(obj == Qnil) { + smokeruby_object * o = ALLOC(smokeruby_object); + o->smoke = m->smoke(); + o->classId = ix; + o->ptr = p; + o->allocated = true; + obj = set_obj_info(className, o); + } + rb_ary_push(list, obj); + } + + if(m->cleanup()) { + delete kurllist; + } + } + break; + case Marshall::ToVALUE: + { + KURL::List *kurllist = (KURL::List*)m->item().s_voidp; + if(!kurllist) { + *(m->var()) = Qnil; + break; + } + + VALUE av = rb_ary_new(); + + int ix = m->smoke()->idClass("KURL"); + const char * className = m->smoke()->binding->className(ix); + + for(KURL::List::Iterator it = kurllist->begin(); + it != kurllist->end(); + ++it) { + void *p = new KURL(*it); + + VALUE obj = getPointerObject(p); + if(obj == Qnil) { + smokeruby_object * o = ALLOC(smokeruby_object); + o->smoke = m->smoke(); + o->classId = ix; + o->ptr = p; + o->allocated = true; + obj = set_obj_info(className, o); + } + rb_ary_push(av, obj); + } + + *(m->var()) = av; + + if(m->cleanup()) { + delete kurllist; + } + } + break; + default: + m->unsupported(); + break; + } +} + +void marshall_UDSEntryList(Marshall *m) { + switch(m->action()) { + case Marshall::FromVALUE: + { + VALUE list = *(m->var()); + if (TYPE(list) != T_ARRAY) { + m->item().s_voidp = 0; + break; + } + + KIO::UDSEntryList *cpplist = new KIO::UDSEntryList; + + for(long i = 0; i < RARRAY(list)->len; i++) { + VALUE item = rb_ary_entry(list, i); + KIO::UDSEntry *cppsublist = new KIO::UDSEntry; + + for (int j = 0; j < RARRAY(item)->len; j++) { + VALUE subitem = rb_ary_entry(item, j); + smokeruby_object *o = value_obj_info(subitem); + if(!o || !o->ptr) + continue; + void *ptr = o->ptr; + ptr = o->smoke->cast(ptr, o->classId, o->smoke->idClass("KIO::UDSAtom")); + cppsublist->append(*(KIO::UDSAtom*)ptr); + } + + cpplist->append(*cppsublist); + } + + m->item().s_voidp = cpplist; + m->next(); + } + break; + case Marshall::ToVALUE: + { + KIO::UDSEntryList *valuelist = (KIO::UDSEntryList*)m->item().s_voidp; + if (!valuelist) { + *(m->var()) = Qnil; + break; + } + + VALUE av = rb_ary_new(); + + int ix = m->smoke()->idClass("KIO::UDSAtom"); + + for ( KIO::UDSEntryList::Iterator it = valuelist->begin(); + it != valuelist->end(); + ++it ) + { + KIO::UDSEntry * udsentry = &(*it); + VALUE subav = rb_ary_new(); + + for ( KIO::UDSEntry::Iterator it = udsentry->begin(); + it != udsentry->end(); + ++it ) + { + void * p = &(*it); + VALUE obj = getPointerObject(p); + if(obj == Qnil) { + smokeruby_object * o = ALLOC(smokeruby_object); + o->smoke = m->smoke(); + o->classId = ix; + o->ptr = p; + o->allocated = false; + obj = set_obj_info("KIO::UDSAtom", o); + } + + rb_ary_push(subav, obj); + } + + rb_ary_push(av, subav); + } + + *(m->var()) = av; + } + break; + default: + m->unsupported(); + break; + } +} + + +// Some time saving magic from Alex Kellett here.. +template <class Item, class ItemList, const char *ItemSTR > +void marshall_ItemList(Marshall *m) { + switch(m->action()) { + case Marshall::FromVALUE: + { + VALUE list = *(m->var()); + if (TYPE(list) != T_ARRAY) { + m->item().s_voidp = 0; + break; + } + int count = RARRAY(list)->len; + ItemList *cpplist = new ItemList; + long i; + for(i = 0; i < count; i++) { + VALUE item = rb_ary_entry(list, i); + // TODO do type checking! + smokeruby_object *o = value_obj_info(item); + if(!o || !o->ptr) + continue; + void *ptr = o->ptr; + ptr = o->smoke->cast( + ptr, // pointer + o->classId, // from + o->smoke->idClass(ItemSTR) // to + ); + cpplist->append((Item*)ptr); + } + + m->item().s_voidp = cpplist; + m->next(); + + if(m->cleanup()) { + rb_ary_clear(list); + for( Item * it = cpplist->first(); + it != 0; + it = cpplist->next()) { + VALUE obj = getPointerObject((void*)it); + rb_ary_push(list, obj); + } + delete cpplist; + } + } + break; + case Marshall::ToVALUE: + { + ItemList *valuelist = (ItemList*)m->item().s_voidp; + if(!valuelist) { + *(m->var()) = Qnil; + break; + } + + VALUE av = rb_ary_new(); + + int ix = m->smoke()->idClass(ItemSTR); + const char * className = m->smoke()->binding->className(ix); + + for(Item * it = valuelist->first(); + it != 0; + it = valuelist->next()) { + void *p = it; + + if(m->item().s_voidp == 0) { + *(m->var()) = Qnil; + break; + } + + VALUE obj = getPointerObject(p); + if(obj == Qnil) { + smokeruby_object * o = ALLOC(smokeruby_object); + o->smoke = m->smoke(); + o->classId = o->smoke->idClass(ItemSTR); + o->ptr = p; + o->allocated = false; + obj = set_obj_info(className, o); + } + rb_ary_push(av, obj); + } + + if(m->cleanup()) + delete valuelist; + else + *(m->var()) = av; + } + break; + default: + m->unsupported(); + break; + } +} + +#define DEF_LIST_MARSHALLER(ListIdent,ItemList,Item) namespace { char ListIdent##STR[] = #Item; }; \ + Marshall::HandlerFn marshall_##ListIdent = marshall_ItemList<Item,ItemList,ListIdent##STR>; + +DEF_LIST_MARSHALLER( KFileItemList, QPtrList<KFileItem>, KFileItem ) +DEF_LIST_MARSHALLER( KMainWindowList, QPtrList<KMainWindow>, KMainWindow ) +DEF_LIST_MARSHALLER( KActionList, QPtrList<KAction>, KAction ) +DEF_LIST_MARSHALLER( DCOPObjectList, QPtrList<DCOPObject>, DCOPObject ) +DEF_LIST_MARSHALLER( KDockWidgetList, QPtrList<KDockWidget>, KDockWidget ) +DEF_LIST_MARSHALLER( KFileTreeBranch, QPtrList<KFileTreeBranch>, KFileTreeBranch ) +DEF_LIST_MARSHALLER( KFileTreeViewItem, QPtrList<KFileTreeViewItem>, KFileTreeViewItem ) +DEF_LIST_MARSHALLER( KPartList, QPtrList<KParts::Part>, KParts::Part ) +DEF_LIST_MARSHALLER( KPartPluginList, QPtrList<KParts::Plugin>, KParts::Plugin ) +DEF_LIST_MARSHALLER( KPartReadOnlyPartList, QPtrList<KParts::ReadOnlyPart>, KParts::ReadOnlyPart ) +DEF_LIST_MARSHALLER( KServiceTypeProfileList, QPtrList<KServiceTypeProfile>, KServiceTypeProfile ) + +template <class Item, class ItemList, class ItemListIterator, const char *ItemSTR > +void marshall_ValueItemList(Marshall *m) { + switch(m->action()) { + case Marshall::FromVALUE: + { + VALUE list = *(m->var()); + if (TYPE(list) != T_ARRAY) { + m->item().s_voidp = 0; + break; + } + int count = RARRAY(list)->len; + ItemList *cpplist = new ItemList; + long i; + for(i = 0; i < count; i++) { + VALUE item = rb_ary_entry(list, i); + // TODO do type checking! + smokeruby_object *o = value_obj_info(item); + if(!o || !o->ptr) + continue; + void *ptr = o->ptr; + ptr = o->smoke->cast( + ptr, // pointer + o->classId, // from + o->smoke->idClass(ItemSTR) // to + ); + cpplist->append(*(Item*)ptr); + } + + m->item().s_voidp = cpplist; + m->next(); + + if(m->cleanup()) { + rb_ary_clear(list); + for(ItemListIterator it = cpplist->begin(); + it != cpplist->end(); + ++it) { + VALUE obj = getPointerObject((void*)&(*it)); + rb_ary_push(list, obj); + } + delete cpplist; + } + } + break; + case Marshall::ToVALUE: + { + ItemList *valuelist = (ItemList*)m->item().s_voidp; + if(!valuelist) { + *(m->var()) = Qnil; + break; + } + + VALUE av = rb_ary_new(); + + int ix = m->smoke()->idClass(ItemSTR); + const char * className = m->smoke()->binding->className(ix); + + for(ItemListIterator it = valuelist->begin(); + it != valuelist->end(); + ++it) { + void *p = &(*it); + + if(m->item().s_voidp == 0) { + *(m->var()) = Qnil; + break; + } + + VALUE obj = getPointerObject(p); + if(obj == Qnil) { + smokeruby_object * o = ALLOC(smokeruby_object); + o->smoke = m->smoke(); + o->classId = o->smoke->idClass(ItemSTR); + o->ptr = p; + o->allocated = false; + obj = set_obj_info(className, o); + } + rb_ary_push(av, obj); + } + + if(m->cleanup()) + delete valuelist; + else + *(m->var()) = av; + } + break; + default: + m->unsupported(); + break; + } +} + +#define DEF_VALUELIST_MARSHALLER(ListIdent,ItemList,Item,Itr) namespace { char ListIdent##STR[] = #Item; }; \ + Marshall::HandlerFn marshall_##ListIdent = marshall_ValueItemList<Item,ItemList,Itr,ListIdent##STR>; + +#if KDE_VERSION >= 0x030200 +DEF_VALUELIST_MARSHALLER( ChoicesList, QValueList<KConfigSkeleton::ItemEnum::Choice>, KConfigSkeleton::ItemEnum::Choice, QValueList<KConfigSkeleton::ItemEnum::Choice>::Iterator ) +#endif +DEF_VALUELIST_MARSHALLER( KAboutPersonList, QValueList<KAboutPerson>, KAboutPerson, QValueList<KAboutPerson>::Iterator ) +DEF_VALUELIST_MARSHALLER( KAboutTranslatorList, QValueList<KAboutTranslator>, KAboutTranslator, QValueList<KAboutTranslator>::Iterator ) +DEF_VALUELIST_MARSHALLER( KIOCopyInfoList, QValueList<KIO::CopyInfo>, KIO::CopyInfo, QValueList<KIO::CopyInfo>::Iterator ) +DEF_VALUELIST_MARSHALLER( KServiceOfferList, QValueList<KServiceOffer>, KServiceOffer, QValueList<KServiceOffer>::Iterator ) +DEF_VALUELIST_MARSHALLER( UDSEntry, QValueList<KIO::UDSAtom>, KIO::UDSAtom, QValueList<KIO::UDSAtom>::Iterator ) + +template <class Key, class Value, class ItemMapIterator, const char *KeySTR, const char *ValueSTR > +void marshall_Map(Marshall *m) { + switch(m->action()) { + case Marshall::FromVALUE: + { + VALUE hash = *(m->var()); + if (TYPE(hash) != T_HASH) { + m->item().s_voidp = 0; + break; + } + + QMap<Key,Value> * map = new QMap<Key,Value>; + + // Convert the ruby hash to an array of key/value arrays + VALUE temp = rb_funcall(hash, rb_intern("to_a"), 0); + + for (long i = 0; i < RARRAY(temp)->len; i++) { + VALUE key = rb_ary_entry(rb_ary_entry(temp, i), 0); + VALUE value = rb_ary_entry(rb_ary_entry(temp, i), 1); + + smokeruby_object *o = value_obj_info(key); + if( !o || !o->ptr) + continue; + void * key_ptr = o->ptr; + key_ptr = o->smoke->cast(key_ptr, o->classId, o->smoke->idClass(KeySTR)); + + o = value_obj_info(value); + if( !o || !o->ptr) + continue; + void * val_ptr = o->ptr; + val_ptr = o->smoke->cast(val_ptr, o->classId, o->smoke->idClass(ValueSTR)); + + (*map)[(Key)*(Key*)key_ptr] = (Value)*(Value*)val_ptr; + } + + m->item().s_voidp = map; + m->next(); + + if(m->cleanup()) + delete map; + } + break; + case Marshall::ToVALUE: + { + QMap<Key,Value> *map = (QMap<Key,Value>*)m->item().s_voidp; + if(!map) { + *(m->var()) = Qnil; + break; + } + + VALUE hv = rb_hash_new(); + + int key_ix = m->smoke()->idClass(KeySTR); + const char * key_className = m->smoke()->binding->className(key_ix); + + int val_ix = m->smoke()->idClass(ValueSTR); + const char * val_className = m->smoke()->binding->className(val_ix); + + ItemMapIterator it; + for (it = map->begin(); it != map->end(); ++it) { + void *key_p = new Key(it.key()); + VALUE key_obj = getPointerObject(key_p); + smokeruby_object * o; + + if (key_obj == Qnil) { + o = ALLOC(smokeruby_object); + o->classId = m->smoke()->idClass(KeySTR); + o->smoke = m->smoke(); + o->ptr = key_p; + o->allocated = true; + key_obj = set_obj_info(key_className, o); + } + + void *val_p = new Value(it.data()); + VALUE value_obj = getPointerObject(val_p); + + if (value_obj == Qnil) { + o = ALLOC(smokeruby_object); + o->classId = m->smoke()->idClass(ValueSTR); + o->smoke = m->smoke(); + o->ptr = val_p; + o->allocated = true; + value_obj = set_obj_info(val_className, o); + } + + rb_hash_aset(hv, key_obj, value_obj); + } + + *(m->var()) = hv; + m->next(); + + if(m->cleanup()) + delete map; + } + break; + default: + m->unsupported(); + break; + } +} + +#define DEF_MAP_MARSHALLER(MapIdent,Key,Value) namespace { char KeyIdent##STR[] = #Key; char ValueIdent##STR[] = #Value; }; \ + Marshall::HandlerFn marshall_##MapIdent = marshall_Map<Key, Value,QMap<Key,Value>::Iterator,KeyIdent##STR, ValueIdent##STR>; + +DEF_MAP_MARSHALLER( QMapKEntryKeyKEntry, KEntryKey, KEntry ) + +void marshall_QMapQCStringDCOPRef(Marshall *m) { + switch(m->action()) { + case Marshall::FromVALUE: + { + VALUE hash = *(m->var()); + if (TYPE(hash) != T_HASH) { + m->item().s_voidp = 0; + break; + } + + QMap<QCString,DCOPRef> * map = new QMap<QCString,DCOPRef>; + + // Convert the ruby hash to an array of key/value arrays + VALUE temp = rb_funcall(hash, rb_intern("to_a"), 0); + + for (long i = 0; i < RARRAY(temp)->len; i++) { + VALUE key = rb_ary_entry(rb_ary_entry(temp, i), 0); + VALUE value = rb_ary_entry(rb_ary_entry(temp, i), 1); + + smokeruby_object *o = value_obj_info(value); + if( !o || !o->ptr) + continue; + void * ptr = o->ptr; + ptr = o->smoke->cast(ptr, o->classId, o->smoke->idClass("DCOPRef")); + + (*map)[QCString(StringValuePtr(key))] = (DCOPRef)*(DCOPRef*)ptr; + } + + m->item().s_voidp = map; + m->next(); + + if(m->cleanup()) + delete map; + } + break; + case Marshall::ToVALUE: + { + QMap<QCString,DCOPRef> *map = (QMap<QCString,DCOPRef>*)m->item().s_voidp; + if(!map) { + *(m->var()) = Qnil; + break; + } + + VALUE hv = rb_hash_new(); + + QMap<QCString,DCOPRef>::Iterator it; + for (it = map->begin(); it != map->end(); ++it) { + void *p = new DCOPRef(it.data()); + VALUE obj = getPointerObject(p); + + if (obj == Qnil) { + smokeruby_object * o = ALLOC(smokeruby_object); + o->classId = m->smoke()->idClass("DCOPRef"); + o->smoke = m->smoke(); + o->ptr = p; + o->allocated = true; + obj = set_obj_info("KDE::DCOPRef", o); + } + + rb_hash_aset(hv, rb_str_new2((const char *) it.key()), obj); + } + + *(m->var()) = hv; + m->next(); + + if(m->cleanup()) + delete map; + } + break; + default: + m->unsupported(); + break; + } +} + +TypeHandler KDE_handlers[] = { + { "QCStringList", marshall_QCStringList }, + { "KCmdLineOptions*", marshall_KCmdLineOptions }, + { "KActionPtrList", marshall_KActionList }, + { "QPtrList<KAction>", marshall_KActionList }, + { "QPtrList<KAction>&", marshall_KActionList }, + { "KMimeType::List", marshall_KMimeTypeList }, + { "KMimeType::Ptr", marshall_KMimeTypePtr }, + { "KService::Ptr", marshall_KServicePtr }, + { "KService::List", marshall_KServiceList }, + { "KServiceGroup::List", marshall_KServiceGroupList }, + { "KServiceGroup::Ptr", marshall_KServiceGroupPtr }, +#if KDE_VERSION >= 0x030200 + { "KMountPoint::List", marshall_KMountPointList }, + { "KPluginInfo::List", marshall_KPluginInfoList }, + { "QValueList<KConfigSkeleton::ItemEnum::Choice>", marshall_ChoicesList }, + { "QValueList<KConfigSkeleton::ItemEnum::Choice>&", marshall_ChoicesList }, +#endif + { "KServiceType::List", marshall_KServiceTypeList }, + { "KTrader::OfferList", marshall_KTraderOfferList }, + { "KURL::List", marshall_KURLList }, + { "KURL::List&", marshall_KURLList }, + { "KFileItemList", marshall_KFileItemList }, + { "KFileItemList*", marshall_KFileItemList }, + { "QPtrList<KMainWindow>*", marshall_KMainWindowList }, + { "QPtrList<DCOPObject>", marshall_DCOPObjectList }, + { "QPtrList<KDockWidget>&", marshall_KDockWidgetList }, + { "QPtrList<KDockWidget>*", marshall_KDockWidgetList }, + { "KFileTreeBranchList&", marshall_KFileTreeBranch }, + { "KFileTreeViewItemList&", marshall_KFileTreeViewItem }, + { "QPtrList<KParts::Part>*", marshall_KPartList }, + { "QPtrList<KParts::Plugin>", marshall_KPartPluginList }, + { "QPtrList<KParts::ReadOnlyPart>", marshall_KPartReadOnlyPartList }, + { "QPtrList<KServiceTypeProfile>&", marshall_KServiceTypeProfileList }, + { "QValueList<KAction*>", marshall_KActionPtrList }, + { "KActionPtrList", marshall_KActionPtrList }, + { "QValueList<KAboutPerson>", marshall_KAboutPersonList }, + { "QValueList<KAboutTranslator>", marshall_KAboutTranslatorList }, + { "QValueList<KIO::CopyInfo>&", marshall_KIOCopyInfoList }, + { "KIO::UDSEntry&", marshall_UDSEntry }, + { "KIO::UDSEntryList&", marshall_UDSEntryList }, + { "KServiceTypeProfile::OfferList", marshall_KServiceOfferList }, + { "KEntryMap", marshall_QMapKEntryKeyKEntry }, + { "KEntryMap&", marshall_QMapKEntryKeyKEntry }, + { "KEntryMap*", marshall_QMapKEntryKeyKEntry }, + { "QMap<QCString,DCOPRef>", marshall_QMapQCStringDCOPRef }, + { "QValueList<WId>&", marshall_WIdList }, + { "QValueList<WId>", marshall_WIdList }, + { 0, 0 } +}; diff --git a/korundum/rubylib/korundum/lib/KDE/Korundum.rb b/korundum/rubylib/korundum/lib/KDE/Korundum.rb new file mode 100644 index 00000000..101d3e30 --- /dev/null +++ b/korundum/rubylib/korundum/lib/KDE/Korundum.rb @@ -0,0 +1 @@ +require 'korundum' diff --git a/korundum/rubylib/korundum/lib/KDE/Makefile.am b/korundum/rubylib/korundum/lib/KDE/Makefile.am new file mode 100644 index 00000000..3f7b0c53 --- /dev/null +++ b/korundum/rubylib/korundum/lib/KDE/Makefile.am @@ -0,0 +1,5 @@ +kderubylibdir = $(RUBY_SITEDIR)/KDE +kderubylib_DATA = korundum.rb + +rubylibdir = $(RUBY_SITEDIR) +rubylib_DATA = Korundum.rb diff --git a/korundum/rubylib/korundum/lib/KDE/korundum.rb b/korundum/rubylib/korundum/lib/KDE/korundum.rb new file mode 100644 index 00000000..40c87260 --- /dev/null +++ b/korundum/rubylib/korundum/lib/KDE/korundum.rb @@ -0,0 +1,1391 @@ +=begin +/*************************************************************************** + Korundum.rb - KDE specific ruby runtime, dcop etc. + ------------------- + begin : Sun Sep 28 2003 + copyright : (C) 2003-2006 by Richard Dale + email : Richard_Dale@tipitina.demon.co.uk + ***************************************************************************/ + +/*************************************************************************** + * * + * This program 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; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +=end + +module KDE + DCOPMeta = {} + + # An entry for each dcop signal or slot + # Example + # int foobar(QString,bool) + # :name is 'foobar' + # :full_name is 'foobar(QString,bool)' + # :arg_types is 'QString,bool' + # :reply_type is 'int' + DCOPMember = Struct.new :name, :full_name, :arg_types, :reply_type + + # If the class with the 'k_dcop' slots declaration is not a subclass of DCOPObject, + # then 'dcop_object' holds a instance of DCOPObject for the class to use as a + # proxy. For subclasses of DCOPObject, 'dcop_object' will always be nil + class DCOPMetaInfo + attr_accessor :dcop_object, :changed + attr_reader :k_dcop_signals, :k_dcop + + def initialize(aClass) + DCOPMeta[aClass.name] = self + @dcop_object = nil + @k_dcop_signals = {} + @k_dcop = {} + @changed = false + end + + def add_signals(signal_list) + signal_list.each do |signal| + signal = DCOPClient.normalizeFunctionSignature(signal) + if signal =~ /^([\w,<>:]*)\s+([^\s]*)\((.*)\)/ + args = DCOPClient.normalizeFunctionSignature($3) + @k_dcop_signals[$2] = DCOPMember.new($2, $2 + "(" + args + ")", args, $1) + else + qWarning( "Invalid DCOP signal format: '#{signal}'" ) + end + end + end + + def add_slots(slot_list) + slot_list.each do |slot| + if slot =~ /^([\w,<>:]*)\s+([^\s]*)\((.*)\)/ + args = DCOPClient.normalizeFunctionSignature($3) + @k_dcop[$2] = DCOPMember.new($2, $1 + ' ' + $2 + "(" + args + ")", args, $1) + else + qWarning( "Invalid DCOP slot format: '#{slot}'" ) + end + end + end + end # DCOPMetaInfo + + def KDE.hasDCOPSignals(aClass) + classname = aClass.name if aClass.is_a? Module + meta = DCOPMeta[classname] + return !meta.nil? && meta.k_dcop_signals.length > 0 + end + + def KDE.hasDCOPSlots(aClass) + classname = aClass.name if aClass.is_a? Module + meta = DCOPMeta[classname] + return !meta.nil? && meta.k_dcop.length > 0 + end + + def KDE.getDCOPSignalNames(aClass) + classname = aClass.name if aClass.is_a? Module + signals = DCOPMeta[classname].k_dcop_signals + return signals.keys + end + + module Internal + def Internal.fullSignalName(instance, signalName) + classname = instance.class.name if instance.class.is_a? Module + signals = DCOPMeta[classname].k_dcop_signals + return signals[signalName].full_name + end + end + + class KDE::DCOPObject + def initialize(*k) + super + end + + def process(fun, data, replyType, replyData) + if fun == 'functions()' or fun == 'interfaces()' + return super + end + + slots = DCOPMeta[@client.class.name].k_dcop + dcop_slot = slots[fun.sub(/\(.*/, '')] + if dcop_slot.nil? + # Can't find an entry for the slot being called? This shouldn't happen.. + return false + end + + replyType << dcop_slot.reply_type + KDE::dcop_process( @client, + dcop_slot.name, + Qt::Internal::getMocArguments(fun), + data, + replyType, + (replyType == 'void' or replyType == 'ASYNC') ? nil : Qt::Internal::getMocArguments(replyType), + replyData ) + end + + def interfaces() + ifaces = super() + return ifaces << @client.class.name + end + + def functions() + funcs = super() + return funcs + @functions + end + + def functions=(funcs) + @functions = funcs + end + + # If a ruby class has 'k_dcop' slots declarations, but isn't a + # subclass of DCOPObject, then keep an instance of it + def client=(obj) + @client = obj + end + + def inspect + str = super + if @functions != nil + str.sub(/>$/, " objId=%s, functions=Array (%d element(s))>" % [objId.inspect, functions.length]) + end + end + + def pretty_print(pp) + str = to_s + if @functions != nil + pp.text str.sub(/>$/, "\n objId=%s,\n functions=Array (%d element(s))>" % [objId.inspect, functions.length]) + end + end + end + + # If a class contains a k_dcop slots list declaration, then create a DCOPObject + # associated with it + def KDE.createDCOPObject(instance) + meta = DCOPMeta[instance.class.name] + return nil if meta.nil? + + if meta.dcop_object.nil? or meta.changed + funcs = [] + meta.k_dcop.each_value do |value| + sig = value.reply_type + ' ' + value.name + '(' + value.arg_types + ')' + funcs << sig + end + meta.changed = false + if instance.kind_of? DCOPObject + instance.functions = funcs + instance.client = instance + return nil + else + if meta.dcop_object.nil? + # Only ever allocate a single instance of a DCOPObject if the + # class isn't a subclass of DCOPObject + meta.dcop_object = DCOPObject.new(instance.class.name) + meta.dcop_object.client = instance + end + meta.dcop_object.functions = funcs + end + end + + return meta.dcop_object + end + + class DCOPRef < Qt::Base + def method_missing(*k) + # Enables DCOPRef calls to be made like this: + # + # dcopRef = DCOPRef.new("dcopslot", "MyWidget") + # result = dcopRef.getPoint("Hello from dcopcall") + begin + # First look for a method in the Smoke runtime. + # If not found, then throw an exception and try dcop. + super(*k) + rescue + dcopArgs = k[1, k.length-1] + dcopArgs << NoEventLoop << -1 + method = k[0].id2name + # Make 'parrot.age = 7' a synonym for 'parrot.setAge(7)' + method = 'set' + method[0,1].upcase + method[1,method.length].sub("=", "") if method =~ /.*[^-+%\/|]=$/ + + # If the method name contains underscores, convert to camel case + while method =~ /([^_]*)_(.)(.*)/ + method = $1 + $2.upcase + $3 + end + + # Get the functions() for this dcop ref and + # cache method_name => full_type_signature in a hash + if @functions.nil? + @functions = {} + funcs = call("functions()") + if funcs.nil? + return nil + end + funcs.each do |func| + if func =~ /^([\w,<>:]*)\s+(.*)(\(.*\))/ + return_type = $1 + name = $2 + args = $3 + if args =~ / / + # Remove any arg names + args.gsub!(/ \w*/, "") + end + + # Make thing? a synonym for isThing() or hasThing() + if name =~ /^(is|has)(.)(.*)/ + predicate = $2.downcase + $3 + '?' + if @functions[predicate].nil? + @functions[predicate] = return_type + " " + name + args + end + end + + if @functions[name].nil? + @functions[name] = return_type + " " + name + args + else + # If a function name is overloaded, just keep a single name entry in + # the hash, not all the full type signatures. Then leave dcopTypeNames() + # to try and resolve the ambiguous call from the ruby arg types passed. + @functions.delete(name) + @functions[name] = name + end + end + end + end + + method = @functions[method] + if method.nil? + qWarning( "DCOPRef: call #{k[0].id2name}() not found" ) + return + end + + return callExt(method, *dcopArgs) + end + end + + def dcopTypeNames(*k) + typeNames = "(" + k.each do |arg| + if arg.kind_of? Integer + typeNames << "int," + elsif arg.kind_of? Float + typeNames << "double," + elsif arg.kind_of? Array + typeNames << "QStringList," + elsif arg.kind_of? String + typeNames << "QString," + elsif arg.kind_of? Qt::Base + typeNames << arg.class.name + "," + elsif arg.instance_of? FalseClass or arg.instance_of? TrueClass + typeNames << "bool," + end + end + typeNames.sub!(/,$/, '') + typeNames.gsub!(/Qt::/, 'Q') + typeNames.gsub!(/KDE::/, 'K') + typeNames << ")" + return typeNames + end + + def call(fun, *k) + k << NoEventLoop << -1 + callExt(fun, *k) + end + + def callExt(fun, *k) + if isNull + qWarning( "DCOPRef: call #{fun} on null reference error" ) + return + end + sig = fun + if fun.index('(') == nil + sig << dcopTypeNames(*k[0, k.length - 2]) + end + dc = dcopClient() + if !dc || !dc.isAttached + qWarning( "DCOPRef::call(): no DCOP client or client not attached error" ) + return + end + if sig =~ /([^\s]*)(\(.*\))/ + full_name = $1+$2 + else + qWarning( "DCOPRef: call #{fun} invalid format, expecting '<function_name>(<args>)'" ) + return + end + return KDE::dcop_call( self, + full_name, + Qt::Internal::getMocArguments(full_name), + *k ) + end + + def send(fun, *k) + if isNull + qWarning( "DCOPRef: send #{fun} on null reference error" ) + end + sig = fun + if fun.index('(') == nil + sig << dcopTypeNames(*k) + end + dc = dcopClient() + if !dc || !dc.isAttached + qWarning( "DCOPRef::send(): no DCOP client or client not attached error" ) + return + end + if !sig =~ /^([^\s]*)(\(.*\))/ + qWarning( "DCOPRef: send #{sig} invalid format, expecting '<function_name>(<args>)'" ) + return + end + return KDE::dcop_send( self, + fun, + Qt::Internal::getMocArguments(sig), + *k ) + end + + def methods + if @functions.nil? + functions() + end + + result = super + @functions.keys.map {|k| k.sub(/^(set)([A-Z])(.*)/) { $2.downcase + $3 + '=' } } + return result.uniq + end + + def inspect + str = super + str.sub(/>$/, " app=%s, obj=%s>" % [app.inspect, obj.inspect]) + end + + def pretty_print(pp) + str = to_s + pp.text str.sub(/>$/, "\n app=%s,\n obj=%s>" % [app.inspect, obj.inspect]) + end + + def type(*args) + method_missing(:type, *args) + end + end + + def CmdLineArgs::init(*k) + if k.length > 0 + if k[0].kind_of? Array + # If init() is passed an array as the first argument, assume it's ARGV. + # Then convert to a pair of args 'ARGV.length+1, [$0]+ARGV' + array = k.shift + super(*([array.length+1] + [[$0] + array] + k)) + elsif k[0].kind_of? KDE::AboutData + super(1, [$0], k[0]) + end + else + super + end + end + + # A sane alternative to the strange looking C++ template version, + # this takes a variable number of ruby args as classes to restore + def MainWindow::kRestoreMainWindows(*k) + n = 1 + while MainWindow.canBeRestored(n) + className = MainWindow.classNameOfToplevel(n) + k.each do |klass| + if klass.name == className + klass.new.restore(n) + end + end + n += 1 + end + end + + class AboutData + def inspect + str = super + str.sub!(/>$/, " appName=%s, copyrightStatement=%s, programName=%s, version=%s, shortDescription=%s, homepage=%s, bugAddress=%s>" % + [appName.inspect, copyrightStatement.inspect, programName.inspect, version.inspect, + shortDescription.inspect, homepage.inspect, bugAddress.inspect] ) + length = authors.length + if length > 0 + str.sub!(/>$/, ", authors=Array (%d element(s))>" % length) + end + length = credits.length + if length > 0 + str.sub!(/>$/, ", credits=Array (%d element(s))>" % length) + end + length = translators.length + if length > 0 + str.sub!(/>$/, ", translators=Array (%d element(s))>" % length) + end + return str + end + + def pretty_print(pp) + str = to_s + str.sub!(/>$/, "\n appName=%s,\n copyrightStatement=%s,\n programName=%s,\n version=%s,\n shortDescription=%s,\n homepage=%s,\n bugAddress=%s>" % + [appName.inspect, copyrightStatement.inspect, programName.inspect, version.inspect, + shortDescription.inspect, homepage.inspect, bugAddress.inspect] ) + length = authors.length + if length > 0 + str.sub!(/>$/, ",\n authors=Array (%d element(s))>" % length) + end + length = credits.length + if length > 0 + str.sub!(/>$/, ",\n credits=Array (%d element(s))>" % length) + end + length = translators.length + if length > 0 + str.sub!(/>$/, ",\n translators=Array (%d element(s))>" % length) + end + pp.text str + end + end + + class AboutPerson + def inspect + str = super + str.sub(/>$/, " emailAddress=%s, name=%s, task=%s, webAddress=%s>" % + [emailAddress.inspect, name.inspect, task.inspect, webAddress.inspect] ) + end + + def pretty_print(pp) + str = to_s + pp.text str.sub(/>$/, "\n emailAddress=%s,\n name=%s,\n task=%s,\n webAddress=%s>" % + [emailAddress.inspect, name.inspect, task.inspect, webAddress.inspect] ) + end + + def name(*args) + method_missing(:name, *args) + end + end + + class AboutTranslator + def inspect + str = super + str.sub(/>$/, " emailAddress=%s, name=%s>" % + [emailAddress.inspect, name.inspect] ) + end + + def pretty_print(pp) + str = to_s + pp.text str.sub(/>$/, "\n emailAddress=%s,\n name=%s>" % + [emailAddress.inspect, name.inspect] ) + end + + def name(*args) + method_missing(:name, *args) + end + end + + class AccelShortcutList + def name(*args) + method_missing(:name, *args) + end + end + + class ActionPtrShortcutList + def name(*args) + method_missing(:name, *args) + end + end + + class ActionShortcutList + def name(*args) + method_missing(:name, *args) + end + end + + class Application + def initialize(*k) + super + $kapp = self + end + + # Delete the underlying C++ instance after exec returns + # Otherwise, rb_gc_call_finalizer_at_exit() can delete + # stuff that KDE::Application still needs for its cleanup. + def exec + method_missing(:exec) + self.dispose + Qt::Internal.application_terminated = true + end + end + + class Archive + def open(*args) + method_missing(:open, *args) + end + end + + class ArchiveEntry + def name(*args) + method_missing(:name, *args) + end + end + + class BookmarkDrag + def format(*args) + method_missing(:format, *args) + end + end + + class CModule + def load(*args) + method_missing(:load, *args) + end + end + + class Catalogue + def name(*args) + method_missing(:name, *args) + end + end + + class ColorDrag + def format(*args) + method_missing(:format, *args) + end + end + + class CustomMenuEditor + def load(*args) + method_missing(:load, *args) + end + end + + class FileItem + def name(*args) + method_missing(:name, *args) + end + end + + class FileMetaInfoGroup + def name(*args) + method_missing(:name, *args) + end + end + + class FileMetaInfoItem + def type(*args) + method_missing(:type, *args) + end + end + + class FileTreeBranch + def name(*args) + method_missing(:name, *args) + end + end + + class FilterDev + def open(*args) + method_missing(:open, *args) + end + end + + class HTMLView + def print(*args) + method_missing(:print, *args) + end + end + + class Icon + def type(*args) + method_missing(:type, *args) + end + end + + class ImageEffect + def hash(*args) + method_missing(:hash, *args) + end + end + + class ImageIO + def type(*args) + method_missing(:type, *args) + end + end + + class ListView + include Enumerable + + def each + it = Qt::ListViewItemIterator.new(self) + while it.current + yield it.current + it += 1 + end + end + + def sort(*args) + method_missing(:sort, *args) + end + end + + class ListViewItem + include Enumerable + + def each + it = Qt::ListViewItemIterator.new(self) + while it.current + yield it.current + it += 1 + end + end + + def sort(*args) + method_missing(:sort, *args) + end + + def inspect + str = super + str.sub!(/>$/, "") + for i in 0..(listView.columns - 1) + str << " text%d=%s," % [i, self.text(i)] + end + str.sub!(/,?$/, ">") + end + + def pretty_print(pp) + str = to_s + str.sub!(/>$/, "") + for i in 0..(listView.columns - 1) + str << " text%d=%s," % [i, self.text(i)] + end + str.sub!(/,?$/, ">") + pp.text str + end + end + + class MainWindowInterface + def raise(*args) + method_missing(:raise, *args) + end + end + + class MdiChildView + def raise(*args) + method_missing(:raise, *args) + end + end + + class MimeType + def load(*args) + method_missing(:load, *args) + end + end + + class MultiTabBarButton + def id(*args) + method_missing(:id, *args) + end + end + + class MultipleDrag + def format(*args) + method_missing(:format, *args) + end + end + + class NamedCommand + def name(*args) + method_missing(:name, *args) + end + end + + class NewStuff + def type(*args) + method_missing(:type, *args) + end + end + + class OCRDialog + def id(*args) + method_missing(:id, *args) + end + end + + class Palette + def name(*args) + method_missing(:name, *args) + end + end + + class PanelApplet + def type(*args) + method_missing(:type, *args) + end + end + + class PanelExtension + def type(*args) + method_missing(:type, *args) + end + end + + class Pixmap + def load(*args) + method_missing(:load, *args) + end + end + + class PixmapEffect + def hash(*args) + method_missing(:hash, *args) + end + end + + class PluginInfo + def load(*args) + method_missing(:load, *args) + end + + def name(*args) + method_missing(:name, *args) + end + end + + class PluginSelector + def load(*args) + method_missing(:load, *args) + end + end + + class PopupFrame + def exec(*args) + method_missing(:exec, *args) + end + end + + class PrintAction + def print(*args) + method_missing(:print, *args) + end + end + + class Printer + def abort(*args) + method_missing(:abort, *args) + end + end + + class Progress + def format(*args) + method_missing(:format, *args) + end + end + + class ProtocolInfo + def exec(*args) + method_missing(:exec, *args) + end + + def load(*args) + method_missing(:load, *args) + end + + def name(*args) + method_missing(:name, *args) + end + end + + class Pty + def open(*args) + method_missing(:open, *args) + end + end + + class Run + def abort(*args) + method_missing(:abort, *args) + end + end + + class SSLCertDlgRet + def send(*args) + method_missing(:send, *args) + end + end + + class SSLPKCS12 + def name(*args) + method_missing(:name, *args) + end + end + + class SSLPKCS7 + def name(*args) + method_missing(:name, *args) + end + end + + class SSLSettings + def load(*args) + method_missing(:load, *args) + end + end + + class SaveFile + def abort(*args) + method_missing(:abort, *args) + end + + def name(*args) + method_missing(:name, *args) + end + end + + class ScanDialog + def id(*args) + method_missing(:id, *args) + end + end + + class Service + def inspect + str = super + str.sub(/>$/, " library=%s, type=%s, name=%s>" % [library.inspect, type.inspect, name.inspect]) + end + + def pretty_print(pp) + str = to_s + pp.text str.sub(/>$/, "\n library=%s,\n type=%s,\n name=%s>" % [library.inspect, type.inspect, name.inspect]) + end + + def exec(*args) + method_missing(:exec, *args) + end + + def load(*args) + method_missing(:load, *args) + end + + def name(*args) + method_missing(:name, *args) + end + + def type(*args) + method_missing(:type, *args) + end + end + + class ServiceGroup + def load(*args) + method_missing(:load, *args) + end + + def name(*args) + method_missing(:name, *args) + end + end + + class ServiceSeparator + def load(*args) + method_missing(:load, *args) + end + + def name(*args) + method_missing(:name, *args) + end + end + + class ServiceType + def load(*args) + method_missing(:load, *args) + end + + def name(*args) + method_missing(:name, *args) + end + end + + class Socks + def select(*args) + method_missing(:select, *args) + end + + def send(*args) + method_missing(:send, *args) + end + end + + class StdAccel + def name(*args) + method_missing(:name, *args) + end + + def open(*args) + method_missing(:open, *args) + end + + def print(*args) + method_missing(:print, *args) + end + end + + class StdAccel::ShortcutList + def name(*args) + method_missing(:name, *args) + end + end + + class StdAction + def name(*args) + method_missing(:name, *args) + end + + def open(*args) + method_missing(:open, *args) + end + + def print(*args) + method_missing(:print, *args) + end + end + + class StdGuiItem + def open(*args) + method_missing(:open, *args) + end + + def print(*args) + method_missing(:print, *args) + end + + def test(*args) + method_missing(:test, *args) + end + end + + class TempDir + def name(*args) + method_missing(:name, *args) + end + end + + class TempFile + def name(*args) + method_missing(:name, *args) + end + end + + class ToolBarButton + def id(*args) + method_missing(:id, *args) + end + end + + class UniqueApplication + def initialize(*k) + super + $kapp = self + end + + # Delete the underlying C++ instance after exec returns + # Otherwise, rb_gc_call_finalizer_at_exit() can delete + # stuff that KDE::Application still needs for its cleanup. + def exec + method_missing(:exec) + self.dispose + Qt::Internal.application_terminated = true + end + end + + class URIFilterPlugin + def name(*args) + method_missing(:name, *args) + end + end + + class URL + def inspect + str = super + str.sub(/>$/, " url=%s, protocol=%s, host=%s, port=%d>" % [url.inspect, protocol.inspect, host.inspect, port]) + end + + def pretty_print(pp) + str = to_s + pp.text str.sub(/>$/, "\n url=%s,\n protocol=%s,\n host=%s,\n port=%d>" % [url.inspect, protocol.inspect, host.inspect, port]) + end + + def split(*args) + method_missing(:split, *args) + end + end + + class URLDrag + def format(*args) + method_missing(:format, *args) + end + end + + class VMAllocator + def allocate(*args) + method_missing(:allocate, *args) + end + end + + class WindowInfo + def display(*args) + method_missing(:display, *args) + end + end + +end + +module DOM + class Attr + def name(*args) + method_missing(:name, *args) + end + end + + class DOMString + def split(*args) + method_missing(:split, *args) + end + end + + class DocumentType + def name(*args) + method_missing(:name, *args) + end + end + + class Event + def type(*args) + method_missing(:type, *args) + end + end + + class HTMLAnchorElement + def name(*args) + method_missing(:name, *args) + end + end + + class HTMLAnchorElement + def type(*args) + method_missing(:type, *args) + end + end + + class HTMLAppletElement + def name(*args) + method_missing(:name, *args) + end + end + + class HTMLButtonElement + def name(*args) + method_missing(:name, *args) + end + end + + class HTMLButtonElement + def type(*args) + method_missing(:type, *args) + end + end + + class HTMLElement + def id(*args) + method_missing(:id, *args) + end + end + + class HTMLFormElement + def method(*args) + method_missing(:method, *args) + end + end + + class HTMLFormElement + def name(*args) + method_missing(:name, *args) + end + end + + class HTMLFrameElement + def name(*args) + method_missing(:name, *args) + end + end + + class HTMLIFrameElement + def name(*args) + method_missing(:name, *args) + end + end + + class HTMLImageElement + def name(*args) + method_missing(:name, *args) + end + end + + class HTMLInputElement + def name(*args) + method_missing(:name, *args) + end + end + + class HTMLInputElement + def type(*args) + method_missing(:type, *args) + end + end + + class HTMLLIElement + def type(*args) + method_missing(:type, *args) + end + end + + class HTMLLinkElement + def type(*args) + method_missing(:type, *args) + end + end + + class HTMLMapElement + def name(*args) + method_missing(:name, *args) + end + end + + class HTMLMetaElement + def name(*args) + method_missing(:name, *args) + end + end + + class HTMLOListElement + def type(*args) + method_missing(:type, *args) + end + end + + class HTMLObjectElement + def name(*args) + method_missing(:name, *args) + end + end + + class HTMLObjectElement + def type(*args) + method_missing(:type, *args) + end + end + + class HTMLParamElement + def name(*args) + method_missing(:name, *args) + end + end + + class HTMLParamElement + def type(*args) + method_missing(:type, *args) + end + end + + class HTMLScriptElement + def type(*args) + method_missing(:type, *args) + end + end + + class HTMLSelectElement + def name(*args) + method_missing(:name, *args) + end + end + + class HTMLSelectElement + def type(*args) + method_missing(:type, *args) + end + end + + class HTMLStyleElement + def type(*args) + method_missing(:type, *args) + end + end + + class HTMLTextAreaElement + def name(*args) + method_missing(:name, *args) + end + end + + class HTMLTextAreaElement + def type(*args) + method_missing(:type, *args) + end + end + + class HTMLUListElement + def type(*args) + method_missing(:type, *args) + end + end + + class StyleSheet + def type(*args) + method_missing(:type, *args) + end + end + + class CSSRule + def type(*args) + method_missing(:type, *args) + end + end + + class Document + def abort(*args) + method_missing(:abort, *args) + end + end + + class Document + def load(*args) + method_missing(:load, *args) + end + end + + class HTMLDocument + def open(*args) + method_missing(:open, *args) + end + end + + class HTMLInputElement + def select(*args) + method_missing(:select, *args) + end + end + + class HTMLTextAreaElement + def select(*args) + method_missing(:select, *args) + end + end +end # DOM + +module KIO + class Connection + def send(*args) + method_missing(:send, *args) + end + end + + class NetRC::AutoLogin + def type(*args) + method_missing(:type, *args) + end + end + + class Slave + def send(*args) + method_missing(:send, *args) + end + end + + class SlaveBase + def exit(*args) + method_missing(:exit, *args) + end + end +end # KIO + +module KNS + class Engine + def type(*args) + method_missing(:type, *args) + end + end + + class Entry + def name(*args) + method_missing(:name, *args) + end + + def type(*args) + method_missing(:type, *args) + end + end + + class Provider + def name(*args) + method_missing(:name, *args) + end + end + + class ProviderLoader + def load(*args) + method_missing(:load, *args) + end + end +end # KNS + +module KParts + class Event + def test(*args) + method_missing(:test, *args) + end + end + + class GUIActivateEvent + def test(*args) + method_missing(:test, *args) + end + end + + class OpenURLEvent + def test(*args) + method_missing(:test, *args) + end + end + + class PartActivateEvent + def test(*args) + method_missing(:test, *args) + end + end + + class PartSelectEvent + def test(*args) + method_missing(:test, *args) + end + end +end # KParts + +module Win + class Win::WindowInfo + def name(*args) + method_missing(:name, *args) + end + end +end + +class Object + def RESTORE(klass) + n = 1 + while MainWindow.canBeRestored(n) + klass.new.restore(n) + n += 1 + end + end + + def I18N_NOOP(x) x end + def I18N_NOOP2(comment, x) x end +end + +class Qt::Base + def self.k_dcop_signals(*signal_list) + meta = KDE::DCOPMeta[self.name] || KDE::DCOPMetaInfo.new(self) + meta.add_signals(signal_list) + meta.changed = true + end + + def self.k_dcop(*slot_list) + meta = KDE::DCOPMeta[self.name] || KDE::DCOPMetaInfo.new(self) + meta.add_slots(slot_list) + meta.changed = true + end +end diff --git a/korundum/rubylib/korundum/lib/Makefile.am b/korundum/rubylib/korundum/lib/Makefile.am new file mode 100644 index 00000000..fba7d258 --- /dev/null +++ b/korundum/rubylib/korundum/lib/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = KDE diff --git a/korundum/rubylib/rbkconfig_compiler/Makefile.am b/korundum/rubylib/rbkconfig_compiler/Makefile.am new file mode 100644 index 00000000..492c6882 --- /dev/null +++ b/korundum/rubylib/rbkconfig_compiler/Makefile.am @@ -0,0 +1,28 @@ +SUBDIRS = . tests + +RBUIC=rbuic + +%.rb: %.ui + $(RBUIC) -tr ${UIC_TR} -kde $*.ui -o $@ + +exampleprefs_base.rb: $(srcdir)/example.kcfg rbkconfig_compiler $(srcdir)/exampleprefs_base.kcfgc + ./rbkconfig_compiler $(srcdir)/example.kcfg $(srcdir)/exampleprefs_base.kcfgc + +AM_CPPFLAGS = -I$(top_srcdir)/kdecore -I$(top_srcdir) $(all_includes) + +bin_PROGRAMS = rbkconfig_compiler + +rbkconfig_compiler_LDFLAGS = $(all_libraries) $(KDE_RPATH) +rbkconfig_compiler_LDADD = $(LIB_KDECORE) +rbkconfig_compiler_SOURCES = rbkconfig_compiler.cpp + +METASOURCES = AUTO + +TESTFILES = test1.kcfg test2.kcfg test3.kcfg test4.kcfg test5.kcfg + +check-local: + for i in $(TESTFILES); \ + do xmllint --noout --schema $(srcdir)/kcfg.xsd $(srcdir)/tests/$$i; \ + perl $(top_srcdir)/korundum/rubylib/rbkconfig_compiler/checkkcfg.pl \ + $(top_srcdir)/korundum/rubylib/rbkconfig_compiler/tests/$$i; done + diff --git a/korundum/rubylib/rbkconfig_compiler/README.dox b/korundum/rubylib/rbkconfig_compiler/README.dox new file mode 100644 index 00000000..97da4dc9 --- /dev/null +++ b/korundum/rubylib/rbkconfig_compiler/README.dox @@ -0,0 +1,251 @@ +/** +\page rbkconfig_compiler The KDE Configuration Compiler for Ruby + +rbkconfig_compiler generates Ruby source code from an XML file containing +information about configuration options (.kcfg) and a file that provides +the code generation options (.kcfgc) The generated class is based on +KDE::ConfigSkeleton and provides an API for the application to access its +configuration data. + +<h2>XML description of the configuration options</h2> + +The structure of the .kcfg file is described by its DTD kcfg.dtd. + +The \<kcfgfile\> tag contains the name of the configuration file described. +Omitting the name will make the generated class use the default configuration +file ("<appname>rc"). + +The remaining entries in the XML file are grouped by the tag \<group\> +which describes the corresponding group in the configuration file. + +The individual entries must have at least a name or a key. The name is used to +create accessor and modifier functions. It's also used as the key in the config +file. If \<key\> is given, but not \<name\>, the name is constructed by removing +all spaces from \<key\>. + +An entry must also have a type. The list of allowable types is +specified in the DTD and loosely follows the list of types supported +by the Qt::Variant with exception of the clearly binary types +(e.g. Pixmap, Image...) which are not supported. Besides those basic +type the following special types are supported: + +- Path This is a string that is specially treated as a file-path. + In particular paths in the home directory are prefixed with $HOME in + when being stored in the configuration file. + +- Enum This indicates an enumeration. The possible enum values should + be provided via the \<choices\> tag. Enum values are accessed as integers + by the application but stored as string in the configuration file. This + makes it possible to add more values at a later date without breaking + compatibility. + +- IntList This indicates a list of integers. This information is provided + to the application as an Array of Integers. Useful for storing Qt::Splitter + geometries. + +An entry can optionally have a default value which is used as default when +the value isn't specified in any config file. Default values are interpreted +as literal constant values. If a default value needs to be computed +or if it needs to be obtained from a function call, the \<default\> tag +should contain the code="true" attribute. The contents of the \<default\> +tag is then considered to be a ruby expression. + +Additional code for computing default values can be provided via +the \<code\> tag. The contents of the \<code\> tag is inserted as-is. A +typical use for this is to compute a common default value which can +then be referenced by multiple entries that follow. + +<h2>Code generation options</h2> + +The options for generating the Ruby sources are read from the file with the +extension .kcfgc. To generate a class add the corresponding kcfgc file to the +SOURCES line in the Makefile.am. + +The following options are read from the kcfgc file: + +<table> +<tr> + <td><b><i>Name</i></b></td> + <td><b><i>Type</i></b></td> + <td><b><i>Default</i></b></td> + <td><b><i>Description</i></b></td> +</tr> +<tr> + <td><b>File</b></td> + <td>string</td> + <td>programname.kcfg</td> + <td>Name of kcfg file containing the options the class is generated for</td> +</tr> +<tr> + <td><b>NameSpace</b></td> + <td>string</td> + <td>-</td> + <td>Optional namespace for generated class</td> +</tr> +<tr> + <td><b>ClassName</b></td> + <td>string</td> + <td>-</td> + <td>Name of generated class (required)</td> +</tr> +<tr> + <td><b>Inherits</b></td> + <td>string</td> + <td>KConfigSkeleton</td> + <td>Class the generated class inherits from. This class must inherit + KConfigSkeleton.</td> +</tr> +<tr> + <td><b>Visibility</b></td> + <td>string</td> + <td>-</td> + <td>Inserts visibility directive (for example KDE_EXPORT) between "class" keyword and class + name in header file</td> +</tr> +<tr> + <td><b>Singleton</b></td> + <td>bool</td> + <td>false</td> + <td>Generated class is a singleton.</td> +</tr> +<tr> + <td><b>CustomAdditions</b></td> + <td>bool</td> + <td>-</td> + <td></td> +</tr> +<tr> + <td><b>MemberVariables</b></td> + <td>string: public|protected|private</td> + <td>private</td> + <td>C++ access modifier used for memeber variables holding the configuration + valuse</td> +</tr> +<tr> + <td><b>IncludeFiles</b></td> + <td>comma separated list of strings</td> + <td>-</td> + <td>Names of files to be included in the header of the generated class</td> +</tr> +<tr> + <td><b>Mutators</b></td> + <td>true, false or a comma seperated list of options</td> + <td>-</td> + <td>If true, mutator functions for all configuration options are generated. + If false, no mutator functions are generated. If a list is provided, + mutator functions are generated for the options that are listed.</td> +</tr> +<tr> + <td><b>ItemAccessors</b></td> + <td>bool</td> + <td>false</td> + <td>Generate accessor functions for the KConfigSkeletonItem objects + corresponding to the configuration options. If <b>SetUserTexts</b> is set, + <b>ItemAccessors</b> also has to be set.</td> +</tr> +<tr> + <td><b>SetUserTexts</b></td> + <td>bool</td> + <td>false</td> + <td>Set the label and whatthis texts of the items from the kcfg file.If + <b>SetUserTexts</b> is set, <b>ItemAccessors</b> also has to be set.</td> +</tr> +<tr> + <td><b>GlobalEnums</b></td> + <td>bool</td> + <td>false</td> + <td>If set to true all choices of Enum items will be created in the global + scope of the generated class. If set to false, each Enum item will get an own + namespace for its choices.</td> +</tr> +</table> + + +<h2>Advanced options</h2> + +There are several possibilities to parameterize entries. + +- Parameterized entries + +An entry can be parameterized using a fixed range parameter specified with +the \<parameter\> tag. Such parameter can either be an Enum or an int. An Enum +parameter should specify the possible enumeration values with the \<choices\> +tag. An int parameter should specify its maximum value. Its minimum value +is always 0. + +A parameterized entry is expanded to a number of entries, one for each +value in the parameter range. The name and key should contain a reference +to the parameter in the form of $(parameter-name). When expanding the entries +the $(parameter-name) part is replaced with the value of the parameter. +In the case of an Enum parameter it is replaced with the name of the +enumuration value. In the case of an int parameter it is replaced with +the numeric value of the parameter. + +Parameterized entries all share the same default value unless different +default values have been specified for specific parameter values. +This can be done with the param= attribute of the \<default\>. When a +param attribute is specified the default value only applies to that +particular parameter value. + +Example 1: +\verbatim + <entry name="Color$(ColorIndex)" type="Color" key="color_$(ColorIndex)"> + <parameter name="ColorIndex" type="Int" max="3"/> + <default param="0">#ff0000</default> + <default param="1">#00ff00</default> + <default param="2">#0000ff</default> + <default param="3">#ffff00</default> + </entry> +\endverbatim + +The above describes 4 color configuration entries with the following defaults: + +color_0=#ff0000 +color_1=#00ff00 +color_2=#0000ff +color_3=#ffff00 + +The configuration options will be accessible to the application via +a color(colorIndex) and a +setColor(colorIndex, v) method. + +Example 2: +\verbatim + <entry name="Sound$(SoundEvent)" type="String" key="sound_$(SoundEvent)"> + <parameter name="SoundEvent" type="Enum"> + <values> + <value>Explosion</value> + <value>Crash</value> + <value>Missile</value> + </values> + </parameter> + <default param="Explosion">boom.wav</default> + <default param="Crash">crash.wav</default> + <default param="Missile">missile.wav</default> + </entry> +\endverbatim + +The above describes 3 string configuration entries with the following defaults: + +sound_Explosion=boom.wav +sound_Crash=crash.wav +sound_Missile=missile.wav + +The configuration options will be accessible to the application via +a sound(soundEvent) and a +setSound(soundEvent, v) method. + +- Parameterized groups + +...STILL TODO... + + + + + +If you have questions or comments please contact Cornelius Schumacher +<schumacher@kde.org> or Waldo Bastian <bastian@kde.org> + +For Ruby specific questions please contact Richard Dale +<Richard_Dale@tipitina.demon.co.uk> +*/ diff --git a/korundum/rubylib/rbkconfig_compiler/TODO b/korundum/rubylib/rbkconfig_compiler/TODO new file mode 100644 index 00000000..db4137ed --- /dev/null +++ b/korundum/rubylib/rbkconfig_compiler/TODO @@ -0,0 +1 @@ +- Support linebreaks in whasthis texts in the kcfg file. diff --git a/korundum/rubylib/rbkconfig_compiler/autoexample.rb b/korundum/rubylib/rbkconfig_compiler/autoexample.rb new file mode 100644 index 00000000..8526c93d --- /dev/null +++ b/korundum/rubylib/rbkconfig_compiler/autoexample.rb @@ -0,0 +1,49 @@ +=begin + This file is part of KDE. + + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +=end + +require 'Korundum' +require 'exampleprefs_base.rb' +require 'general_base.rb' +require 'myoptions_base.rb' + + aboutData = KDE::AboutData.new( "example", I18N_NOOP("autoconfig example"), "0.1" ) + aboutData.addAuthor( "Cornelius Schumacher", nil, "schumacher@kde.org" ) + + KDE::CmdLineArgs.init( ARGV, aboutData ) + + app = KDE::Application.new + + configSkeleton = ExamplePrefsBase.new( "dummy1", "dummy2" ) + configSkeleton.readConfig() + + dialog = KDE::ConfigDialog.new( nil, "settings", configSkeleton ) + + general = GeneralBase.new(nil) + dialog.addPage( general, app.i18n("General"), "General", "" ) + + myOptions = MyOptionsBase.new( nil ) + dialog.addPage( myOptions, app.i18n("MyOptions"), "MyOptions", "" ) + + app.mainWidget = dialog + + dialog.show() + + app.exec diff --git a/korundum/rubylib/rbkconfig_compiler/checkkcfg.pl b/korundum/rubylib/rbkconfig_compiler/checkkcfg.pl new file mode 100755 index 00000000..2eddbeee --- /dev/null +++ b/korundum/rubylib/rbkconfig_compiler/checkkcfg.pl @@ -0,0 +1,83 @@ +#!/usr/bin/perl + +if ( @ARGV != 1 ) { + print STDERR "Missing arg: filename\n"; + exit 1; +} + +$file = $ARGV[0]; + +$file =~ /^(.*)\.[^\.]*$/; +$filebase = $1; + +$file_h = "$filebase.h"; +$file_cpp = "$filebase.cpp"; + +$kcfgc = $file . "c"; + +$cmd = "./kconfig_compiler $file $kcfgc"; + +#print "CMD $cmd\n"; + +if ( system( $cmd ) != 0 ) { + print STDERR "Unable to run kconfig_compiler\n"; + exit 1; +} + +checkfile( $file_h ); +checkfile( $file_cpp ); + +exit 0; + +sub checkfile() +{ + my $file = shift; + + $file =~ /\/([^\/]*)$/; + my $filename = $1; + + print "Checking '$filename':\n"; + + my @ref; + if ( !open( REF, "$file.ref" ) ) { + print STDERR "Unable to open $file.ref\n"; + exit 1; + } + while( <REF> ) { + push @ref, $_; + } + close REF; + + if ( !open( READ, $filename ) ) { + print STDERR "Unable to open $filename\n"; + exit 1; + } + + $error = 0; + $i = 0; + $line = 1; + while( <READ> ) { + $out = $_; + $ref = @ref[$i++]; + + if ( $out ne $ref ) { + $error++; + print " Line $line: Expected : $ref"; + print " Line $line: Compiler output : $out"; + } + + $line++; + } + + close READ; + + if ( $error > 0 ) { + print "\n FAILED: $error errors found.\n"; + if ( $error > 5 ) { + system( "diff -u $file.ref $filename" ); + } + exit 1; + } else { + print " OK\n"; + } +} diff --git a/korundum/rubylib/rbkconfig_compiler/example.kcfg b/korundum/rubylib/rbkconfig_compiler/example.kcfg new file mode 100644 index 00000000..89d1e646 --- /dev/null +++ b/korundum/rubylib/rbkconfig_compiler/example.kcfg @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="UTF-8"?> +<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 + http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" > + <include>qdir.h</include> + <kcfgfile name="examplerc"> + <parameter name="transport" /> + <parameter name="folder" /> + </kcfgfile> + <group name="General-$(folder)"> + <entry name="OneOption" type="Bool"> + <label>One option</label> + <default>true</default> + </entry> + <entry name="AnotherOption" type="Int" key="Another Option"> + <label>Another option</label> + <default>5</default> + </entry> + <entry name="ListOption" type="Enum"> + <label>This is some funky option</label> + <whatsthis>And this is a longer description of this option. Just wondering, how will the translations of those be handled?</whatsthis> + <choices> + <choice name="One"/> + <choice name="Two"/> + <choice name="Three"/> + </choices> + <default>One</default> + </entry> + </group> + <group name="MyOptions"> + <entry name="MyString" type="String"> + <label>This is a string</label> + <default>Default String</default> + </entry> + <entry name="MyPath" type="Path"> + <label>This is a path</label> + <default code="true">Qt::Dir.homeDirPath()+".hidden_file"</default> + </entry> + <entry name="AnotherOption2" type="Int" key="Another Option"> + <label>Another option</label> + <default>10</default> + </entry> + <entry name="MyStringList" type="StringList"> + <default>up,down</default> + </entry> + <entry name="MyStringListHidden" hidden="true" type="StringList"> + <default>up,down</default> + </entry> + <entry name="MyNumber" type="Int64" key="List-$(transport)-$(folder)"> + <label>List Number</label> + <default>1</default> + </entry> + </group> +</kcfg> diff --git a/korundum/rubylib/rbkconfig_compiler/example.rb b/korundum/rubylib/rbkconfig_compiler/example.rb new file mode 100644 index 00000000..d7ef38b1 --- /dev/null +++ b/korundum/rubylib/rbkconfig_compiler/example.rb @@ -0,0 +1,40 @@ +=begin + This file is part of KDE. + + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +=end + +require 'Korundum' +require 'exampleprefs_base.rb' + + aboutData = KDE::AboutData.new( "example", I18N_NOOP("cfgc example"), "0.1" ) + aboutData.addAuthor( "Cornelius Schumacher", nil, "schumacher@kde.org" ) + + KDE::CmdLineArgs.init( ARGV, aboutData ) + + app = KDE::Application.new + + prefs = ExamplePrefsBase.new("Trans1", "Folder2") + + prefs.readConfig() + + prefs.setAnotherOption(17) + + + qWarning("Another Option = %d" % prefs.anotherOption()) + qWarning("Another Option2 = %d" % prefs.anotherOption2()) diff --git a/korundum/rubylib/rbkconfig_compiler/exampleprefs_base.kcfgc b/korundum/rubylib/rbkconfig_compiler/exampleprefs_base.kcfgc new file mode 100644 index 00000000..957ed912 --- /dev/null +++ b/korundum/rubylib/rbkconfig_compiler/exampleprefs_base.kcfgc @@ -0,0 +1,18 @@ +# Code generation options for kconfig_compiler +ClassName=ExamplePrefsBase +# +# Singleton=false +# +# Inherits=KConfigSkeleton +# +# IncludeFiles=libkdepim/kpimprefs.h +# +# MemberVariables=public +# +### The following line includes the file exampleprefs_base_addon.h +### It can be used to add extra functions and variables to the +### class. +# CustomAdditions=true +# +### Provide setFooBar(int) style functions +Mutators=true diff --git a/korundum/rubylib/rbkconfig_compiler/general_base.ui b/korundum/rubylib/rbkconfig_compiler/general_base.ui new file mode 100644 index 00000000..9b41370c --- /dev/null +++ b/korundum/rubylib/rbkconfig_compiler/general_base.ui @@ -0,0 +1,46 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>GeneralBase</class> +<widget class="QWidget"> + <property name="name"> + <cstring>GeneralBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>600</width> + <height>486</height> + </rect> + </property> + <property name="caption"> + <string>AutoExampleDialog</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox" row="0" column="1"> + <property name="name"> + <cstring>kcfg_OneOption</cstring> + </property> + <property name="text"> + <string>OneOption</string> + </property> + </widget> + <widget class="QSpinBox" row="1" column="1"> + <property name="name"> + <cstring>kcfg_AnotherOption2</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>AnotherOption:</string> + </property> + </widget> + </grid> +</widget> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/korundum/rubylib/rbkconfig_compiler/kcfg.xsd b/korundum/rubylib/rbkconfig_compiler/kcfg.xsd new file mode 100644 index 00000000..61450d25 --- /dev/null +++ b/korundum/rubylib/rbkconfig_compiler/kcfg.xsd @@ -0,0 +1,191 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!-- kcfg XSD v1.0 --> +<xsd:schema + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns="http://www.kde.org/standards/kcfg/1.0" + xmlns:kcfg="http://www.kde.org/standards/kcfg/1.0" + targetNamespace="http://www.kde.org/standards/kcfg/1.0" + version="1.0" + elementFormDefault="qualified" > + + <xsd:annotation> + <xsd:documentation> + + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + Copyright (c) 2003 Waldo Bastian <bastian@kde.org> + Copyright (c) 2003 Zack Rusin <zack@kde.org> + Copyright (c) 2004 Frans Englich <frans.englich@telia.com> + + Permission to use, copy, modify and distribute this DTD + and its accompanying documentation for any purpose and without fee + is hereby granted in perpetuity, provided that the above copyright + notice and this paragraph appear in all copies. The copyright + holders make no representation about the suitability of the DTD for + any purpose. It is provided "as is" without expressed or implied + warranty. + + </xsd:documentation> + </xsd:annotation> + <xsd:annotation> + <xsd:documentation> + + A Schema for KDE's KConfigXT XML format. It is similar to the DTD + found at: + + http://www.kde.org/standards/kcfg/1.0/kcfg.dtd + + Documents valid against the Schema version are backwards compatible + to the DTD. Validating against the Schema instead of the DTD is + recommended, since the former provides better validation. + + A document instance of this Schema should have a declaration + looking like this: + + <![CDATA[ + + <?xml version="1.0" encoding="UTF-8" ?> + <kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 + http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" > + <!-- the content --> + </kcfg> + + ]]> + + </xsd:documentation> + </xsd:annotation> + + <xsd:element name="kcfg"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="include" minOccurs="0" maxOccurs="unbounded" type="xsd:string"/> + <xsd:element name="kcfgfile" > + <xsd:complexType> + <xsd:sequence> + <xsd:element name="parameter" type="kcfg:parameter" minOccurs="0" maxOccurs="unbounded" /> + <!-- FIXME: Are really unbounded occurances of parameter allowed? --> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="optional"/> + <xsd:attribute name="arg" type="xsd:boolean" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="group" maxOccurs="unbounded" > + <xsd:complexType> + <xsd:sequence> + <xsd:element name="entry" maxOccurs="unbounded"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="parameter" minOccurs="0" type="kcfg:parameter"/> + <xsd:element name="label" minOccurs="0" type="xsd:string"/> + <xsd:element name="whatsthis" minOccurs="0" type="xsd:string"/> + <xsd:element name="choices" minOccurs="0"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="choice" maxOccurs="unbounded"> + <xsd:complexType> + <xsd:all> + <xsd:element minOccurs="0" name="label" type="xsd:string"/> + <xsd:element minOccurs="0" name="whatsthis" type="xsd:string"/> + </xsd:all> + <xsd:attribute name="name" use="required" type="xsd:string"/> + </xsd:complexType> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + + <xsd:element name="code" minOccurs="0" type="kcfg:code"/> + + <xsd:element name="default" maxOccurs="unbounded" minOccurs="0" > + <xsd:complexType> + <xsd:simpleContent> + <xsd:extension base="xsd:string"> + <xsd:attribute use="optional" name="code" type="xsd:boolean"/> + <xsd:attribute use="optional" name="param" type="xsd:string"/> + </xsd:extension> + </xsd:simpleContent> + </xsd:complexType> + </xsd:element> + + <xsd:element name="min" minOccurs="0" > + <xsd:complexType> + <xsd:simpleContent> + <xsd:extension base="xsd:string"> + <xsd:attribute name="code" type="xsd:boolean"/> + </xsd:extension> + </xsd:simpleContent> + </xsd:complexType> + </xsd:element> + + <xsd:element name="max" minOccurs="0"> + <xsd:complexType> + <xsd:simpleContent> + <xsd:extension base="xsd:string"> + <xsd:attribute name="code" type="xsd:boolean"/> + </xsd:extension> + </xsd:simpleContent> + </xsd:complexType> + </xsd:element> + + </xsd:choice> + <xsd:attribute name="name" use="optional" type="xsd:string"/> + <xsd:attribute name="key" use="optional" type="xsd:string"/> + <xsd:attribute name="hidden" use="optional" type="xsd:boolean"/> + <xsd:attribute name="type" type="kcfg:datatype"/> + </xsd:complexType> + </xsd:element> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string"/> + </xsd:complexType> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + + <xsd:simpleType name="datatype"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="String"/> + <xsd:enumeration value="StringList"/> + <xsd:enumeration value="Font"/> + <xsd:enumeration value="Rect"/> + <xsd:enumeration value="Size"/> + <xsd:enumeration value="Color"/> + <xsd:enumeration value="Point"/> + <xsd:enumeration value="Int"/> + <xsd:enumeration value="UInt"/> + <xsd:enumeration value="Bool"/> + <xsd:enumeration value="Double"/> + <xsd:enumeration value="DateTime"/> + <xsd:enumeration value="Int64"/> + <xsd:enumeration value="UInt64"/> + <xsd:enumeration value="IntList"/> + <xsd:enumeration value="Enum"/> + <xsd:enumeration value="Path"/> + <xsd:enumeration value="Password"/> + </xsd:restriction> + </xsd:simpleType> + + <xsd:complexType name="parameter"> + <xsd:sequence> + <xsd:element minOccurs="0" name="values"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" maxOccurs="unbounded" type="xsd:string"/> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string"/> + <xsd:attribute name="type" use="optional" type="kcfg:datatype" /> + <xsd:attribute name="max" use="optional" type="xsd:positiveInteger"/> + </xsd:complexType> + + <xsd:complexType name="code"> + <xsd:simpleContent> + <xsd:extension base="xsd:string"/> + </xsd:simpleContent> + </xsd:complexType> + +</xsd:schema> + diff --git a/korundum/rubylib/rbkconfig_compiler/myoptions_base.ui b/korundum/rubylib/rbkconfig_compiler/myoptions_base.ui new file mode 100644 index 00000000..3c0c2e6c --- /dev/null +++ b/korundum/rubylib/rbkconfig_compiler/myoptions_base.ui @@ -0,0 +1,35 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>MyOptionsBase</class> +<widget class="QWidget"> + <property name="name"> + <cstring>MyOptionsBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>600</width> + <height>486</height> + </rect> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>MyString:</string> + </property> + </widget> + <widget class="QLineEdit" row="0" column="1"> + <property name="name"> + <cstring>kcfg_MyString</cstring> + </property> + </widget> + </grid> +</widget> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/korundum/rubylib/rbkconfig_compiler/rbkconfig_compiler.cpp b/korundum/rubylib/rbkconfig_compiler/rbkconfig_compiler.cpp new file mode 100644 index 00000000..6274e4bf --- /dev/null +++ b/korundum/rubylib/rbkconfig_compiler/rbkconfig_compiler.cpp @@ -0,0 +1,1330 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; -*- +/* + This file is part of KDE. + + Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + Copyright (c) 2003 Waldo Bastian <bastian@kde.org> + Copyright (c) 2003 Zack Rusin <zack@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qfile.h> +#include <qtextstream.h> +#include <qdom.h> +#include <qregexp.h> + +#include <kaboutdata.h> +#include <kapplication.h> +#include <kdebug.h> +#include <klocale.h> +#include <kcmdlineargs.h> +#include <kglobal.h> +#include <kconfig.h> +#include <ksimpleconfig.h> +#include <kstandarddirs.h> + +#include <iostream> + +static const KCmdLineOptions options[] = +{ + { "d", 0, 0 }, + { "directory <dir>", I18N_NOOP("Directory to generate files in"), "." }, + { "+file.kcfg", I18N_NOOP("Input kcfg XML file"), 0 }, + { "+file.kcfgc", I18N_NOOP("Code generation options file"), 0 }, + KCmdLineLastOption +}; + + +bool globalEnums; +bool itemAccessors; +QStringList allNames; +QRegExp *validNameRegexp; + +class CfgEntry +{ + public: + struct Choice + { + QString name; + QString label; + QString whatsThis; + }; + + CfgEntry( const QString &group, const QString &type, const QString &key, + const QString &name, const QString &label, + const QString &whatsThis, const QString &code, + const QString &defaultValue, const QValueList<Choice> &choices, + bool hidden ) + : mGroup( group ), mType( type ), mKey( key ), mName( name ), + mLabel( label ), mWhatsThis( whatsThis ), mCode( code ), + mDefaultValue( defaultValue ), + mChoices( choices ), mHidden( hidden ) + { + } + + void setGroup( const QString &group ) { mGroup = group; } + QString group() const { return mGroup; } + + void setType( const QString &type ) { mType = type; } + QString type() const { return mType; } + + void setKey( const QString &key ) { mKey = key; } + QString key() const { return mKey; } + + void setName( const QString &name ) { mName = name; } + QString name() const { return mName; } + + void setLabel( const QString &label ) { mLabel = label; } + QString label() const { return mLabel; } + + void setWhatsThis( const QString &whatsThis ) { mWhatsThis = whatsThis; } + QString whatsThis() const { return mWhatsThis; } + + void setDefaultValue( const QString &d ) { mDefaultValue = d; } + QString defaultValue() const { return mDefaultValue; } + + void setCode( const QString &d ) { mCode = d; } + QString code() const { return mCode; } + + void setMinValue( const QString &d ) { mMin = d; } + QString minValue() const { return mMin; } + + void setMaxValue( const QString &d ) { mMax = d; } + QString maxValue() const { return mMax; } + + void setParam( const QString &d ) { mParam = d; } + QString param() const { return mParam; } + + void setParamName( const QString &d ) { mParamName = d; } + QString paramName() const { return mParamName; } + + void setParamType( const QString &d ) { mParamType = d; } + QString paramType() const { return mParamType; } + + void setChoices( const QValueList<Choice> &d ) { mChoices = d; } + QValueList<Choice> choices() const { return mChoices; } + + void setParamValues( const QStringList &d ) { mParamValues = d; } + QStringList paramValues() const { return mParamValues; } + + void setParamDefaultValues( const QStringList &d ) { mParamDefaultValues = d; } + QString paramDefaultValue(int i) const { return mParamDefaultValues[i]; } + + void setParamMax( int d ) { mParamMax = d; } + int paramMax() const { return mParamMax; } + + bool hidden() const { return mHidden; } + + void dump() const + { + kdDebug() << "<entry>" << endl; + kdDebug() << " group: " << mGroup << endl; + kdDebug() << " type: " << mType << endl; + kdDebug() << " key: " << mKey << endl; + kdDebug() << " name: " << mName << endl; + kdDebug() << " label: " << mLabel << endl; +// whatsthis + kdDebug() << " code: " << mCode << endl; +// kdDebug() << " values: " << mValues.join(":") << endl; + + if (!param().isEmpty()) + { + kdDebug() << " param name: "<< mParamName << endl; + kdDebug() << " param type: "<< mParamType << endl; + kdDebug() << " paramvalues: " << mParamValues.join(":") << endl; + } + kdDebug() << " default: " << mDefaultValue << endl; + kdDebug() << " hidden: " << mHidden << endl; + kdDebug() << " min: " << mMin << endl; + kdDebug() << " max: " << mMax << endl; + kdDebug() << "</entry>" << endl; + } + + private: + QString mGroup; + QString mType; + QString mKey; + QString mName; + QString mLabel; + QString mWhatsThis; + QString mCode; + QString mDefaultValue; + QString mParam; + QString mParamName; + QString mParamType; + QValueList<Choice> mChoices; + QStringList mParamValues; + QStringList mParamDefaultValues; + int mParamMax; + bool mHidden; + QString mMin; + QString mMax; +}; + + +static QString varName(const QString &n) +{ + QString result = "@"+n; + result[1] = result[1].lower(); + return result; +} + +static QString enumName(const QString &n) +{ + QString result = "Enum"+n; + result[4] = result[4].upper(); + return result; +} + +static QString enumValue(const QString &n) +{ + QString result = n; + result[0] = result[0].upper(); + return result; +} + +static QString setFunction(const QString &n) +{ + QString result = "set"+n; + result[3] = result[3].upper(); + return result; +} + + +static QString getFunction(const QString &n) +{ + QString result = n; + result[0] = result[0].lower(); + return result; +} + + +static void addQuotes( QString &s ) +{ + if ( s.left( 1 ) != "\"" ) s.prepend( "\"" ); + if ( s.right( 1 ) != "\"" ) s.append( "\"" ); +} + +static QString quoteString( const QString &s ) +{ + QString r = s; + r.replace( "\\", "\\\\" ); + r.replace( "\"", "\\\"" ); + r.replace( "\r", "" ); + r.replace( "\n", "\\n\"\n\"" ); + return "\"" + r + "\""; +} + +static QString literalString( const QString &s ) +{ + bool isAscii = true; + for(int i = s.length(); i--;) + if (s[i].unicode() > 127) isAscii = false; + + return quoteString(s); + +// if (isAscii) +// return "QString::fromLatin1( " + quoteString(s) + " )"; +// else +// return "QString::fromUtf8( " + quoteString(s) + " )"; +} + +static QString dumpNode(const QDomNode &node) +{ + QString msg; + QTextStream s(&msg, IO_WriteOnly ); + node.save(s, 0); + + msg = msg.simplifyWhiteSpace(); + if (msg.length() > 40) + return msg.left(37)+"..."; + return msg; +} + +static QString filenameOnly(QString path) +{ + int i = path.findRev('/'); + if (i >= 0) + return path.mid(i+1); + return path; +} + +static void preProcessDefault( QString &defaultValue, const QString &name, + const QString &type, + const QValueList<CfgEntry::Choice> &choices, + QString &code ) +{ + if ( type == "String" && !defaultValue.isEmpty() ) { + defaultValue = literalString(defaultValue); + + } else if ( type == "Path" && !defaultValue.isEmpty() ) { + defaultValue = literalString( defaultValue ); + + } else if ( type == "StringList" && !defaultValue.isEmpty() ) { + QTextStream rb( &code, IO_WriteOnly | IO_Append ); + if (!code.isEmpty()) + rb << endl; + +// rb << " QStringList default" << name << ";" << endl; + rb << " default" << name << " = []" << endl; + QStringList defaults = QStringList::split( ",", defaultValue ); + QStringList::ConstIterator it; + for( it = defaults.begin(); it != defaults.end(); ++it ) { + rb << " default" << name << " << \"" << *it << "\"" + << endl; + } + defaultValue = "default" + name; + + } else if ( type == "Color" && !defaultValue.isEmpty() ) { + QRegExp colorRe("\\d+,\\s*\\d+,\\s*\\d+"); + if (colorRe.exactMatch(defaultValue)) + { + defaultValue = "Qt::Color.new( " + defaultValue + " )"; + } + else + { + defaultValue = "Qt::Color.new( \"" + defaultValue + "\" )"; + } + + } else if ( type == "Enum" ) { + if ( !globalEnums ) { + QValueList<CfgEntry::Choice>::ConstIterator it; + for( it = choices.begin(); it != choices.end(); ++it ) { + if ( (*it).name == defaultValue ) { + defaultValue.prepend( enumName(name) + "_"); + break; + } + } + } + + } else if ( type == "IntList" ) { + QTextStream rb( &code, IO_WriteOnly | IO_Append ); + if (!code.isEmpty()) + rb << endl; + + rb << " default" << name << " = []" << endl; + QStringList defaults = QStringList::split( ",", defaultValue ); + QStringList::ConstIterator it; + for( it = defaults.begin(); it != defaults.end(); ++it ) { + rb << " default" << name << " << " << *it << "" + << endl; + } + defaultValue = "default" + name; + } +} + + +CfgEntry *parseEntry( const QString &group, const QDomElement &element ) +{ + bool defaultCode = false; + QString type = element.attribute( "type" ); + QString name = element.attribute( "name" ); + QString key = element.attribute( "key" ); + QString hidden = element.attribute( "hidden" ); + QString label; + QString whatsThis; + QString defaultValue; + QString code; + QString param; + QString paramName; + QString paramType; + QValueList<CfgEntry::Choice> choices; + QStringList paramValues; + QStringList paramDefaultValues; + QString minValue; + QString maxValue; + int paramMax = 0; + + QDomNode n; + for ( n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) { + QDomElement e = n.toElement(); + QString tag = e.tagName(); + if ( tag == "label" ) label = e.text(); + else if ( tag == "whatsthis" ) whatsThis = e.text(); + else if ( tag == "min" ) minValue = e.text(); + else if ( tag == "max" ) maxValue = e.text(); + else if ( tag == "code" ) code = e.text(); + else if ( tag == "parameter" ) + { + param = e.attribute( "name" ); + paramType = e.attribute( "type" ); + if ( param.isEmpty() ) { + kdError() << "Parameter must have a name: " << dumpNode(e) << endl; + return 0; + } + if ( paramType.isEmpty() ) { + kdError() << "Parameter must have a type: " << dumpNode(e) << endl; + return 0; + } + if ((paramType == "Int") || (paramType == "UInt")) + { + bool ok; + paramMax = e.attribute("max").toInt(&ok); + if (!ok) + { + kdError() << "Integer parameter must have a maximum (e.g. max=\"0\"): " << dumpNode(e) << endl; + return 0; + } + } + else if (paramType == "Enum") + { + QDomNode n2; + for ( n2 = e.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) { + QDomElement e2 = n2.toElement(); + if (e2.tagName() == "values") + { + QDomNode n3; + for ( n3 = e2.firstChild(); !n3.isNull(); n3 = n3.nextSibling() ) { + QDomElement e3 = n3.toElement(); + if (e3.tagName() == "value") + { + paramValues.append( e3.text() ); + } + } + break; + } + } + if (paramValues.isEmpty()) + { + kdError() << "No values specified for parameter '" << param << "'." << endl; + return 0; + } + paramMax = paramValues.count()-1; + } + else + { + kdError() << "Parameter '" << param << "' has type " << paramType << " but must be of type int, uint or Enum." << endl; + return 0; + } + } + else if ( tag == "default" ) + { + if (e.attribute("param").isEmpty()) + { + defaultValue = e.text(); + if (e.attribute( "code" ) == "true") + defaultCode = true; + } + } + else if ( tag == "choices" ) { + QDomNode n2; + for( n2 = e.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) { + QDomElement e2 = n2.toElement(); + if ( e2.tagName() == "choice" ) { + QDomNode n3; + CfgEntry::Choice choice; + choice.name = e2.attribute( "name" ); + if ( choice.name.isEmpty() ) { + kdError() << "Tag <choice> requires attribute 'name'." << endl; + } + for( n3 = e2.firstChild(); !n3.isNull(); n3 = n3.nextSibling() ) { + QDomElement e3 = n3.toElement(); + if ( e3.tagName() == "label" ) choice.label = e3.text(); + if ( e3.tagName() == "whatsthis" ) choice.whatsThis = e3.text(); + } + choices.append( choice ); + } + } + } + } + + bool nameIsEmpty = name.isEmpty(); + if ( nameIsEmpty && key.isEmpty() ) { + kdError() << "Entry must have a name or a key: " << dumpNode(element) << endl; + return 0; + } + + if ( key.isEmpty() ) { + key = name; + } + + if ( nameIsEmpty ) { + name = key; + name.replace( " ", QString::null ); + } else if ( name.contains( ' ' ) ) { + kdWarning()<<"Entry '"<<name<<"' contains spaces! <name> elements can't contain speces!"<<endl; + name.remove( ' ' ); + } + + if (name.contains("$(")) + { + if (param.isEmpty()) + { + kdError() << "Name may not be parameterized: " << name << endl; + return 0; + } + } + else + { + if (!param.isEmpty()) + { + kdError() << "Name must contain '$(" << param << ")': " << name << endl; + return 0; + } + } + + if ( label.isEmpty() ) { + label = key; + } + + if ( type.isEmpty() ) type = "String"; // XXX : implicit type might be bad + + if (!param.isEmpty()) + { + // Adjust name + paramName = name; + name.replace("$("+param+")", QString::null); + // Lookup defaults for indexed entries + for(int i = 0; i <= paramMax; i++) + { + paramDefaultValues.append(QString::null); + } + + QDomNode n; + for ( n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) { + QDomElement e = n.toElement(); + QString tag = e.tagName(); + if ( tag == "default" ) + { + QString index = e.attribute("param"); + if (index.isEmpty()) + continue; + + bool ok; + int i = index.toInt(&ok); + if (!ok) + { + i = paramValues.findIndex(index); + if (i == -1) + { + kdError() << "Index '" << index << "' for default value is unknown." << endl; + return 0; + } + } + + if ((i < 0) || (i > paramMax)) + { + kdError() << "Index '" << i << "' for default value is out of range [0, "<< paramMax<<"]." << endl; + return 0; + } + + QString tmpDefaultValue = e.text(); + + if (e.attribute( "code" ) != "true") + preProcessDefault(tmpDefaultValue, name, type, choices, code); + + paramDefaultValues[i] = tmpDefaultValue; + } + } + } + + if (!validNameRegexp->exactMatch(name)) + { + if (nameIsEmpty) + kdError() << "The key '" << key << "' can not be used as name for the entry because " + "it is not a valid name. You need to specify a valid name for this entry." << endl; + else + kdError() << "The name '" << name << "' is not a valid name for an entry." << endl; + return 0; + } + + if (allNames.contains(name)) + { + if (nameIsEmpty) + kdError() << "The key '" << key << "' can not be used as name for the entry because " + "it does not result in a unique name. You need to specify a unique name for this entry." << endl; + else + kdError() << "The name '" << name << "' is not unique." << endl; + return 0; + } + allNames.append(name); + + if (!defaultCode) + { + preProcessDefault(defaultValue, name, type, choices, code); + } + + CfgEntry *result = new CfgEntry( group, type, key, name, label, whatsThis, + code, defaultValue, choices, + hidden == "true" ); + if (!param.isEmpty()) + { + result->setParam(param); + result->setParamName(paramName); + result->setParamType(paramType); + result->setParamValues(paramValues); + result->setParamDefaultValues(paramDefaultValues); + result->setParamMax(paramMax); + } + result->setMinValue(minValue); + result->setMaxValue(maxValue); + + return result; +} + +/** + Return parameter declaration for given type. +*/ +QString param( const QString &type ) +{ + if ( type == "String" ) return "const QString &"; + else if ( type == "StringList" ) return "const QStringList &"; + else if ( type == "Font" ) return "const QFont &"; + else if ( type == "Rect" ) return "const QRect &"; + else if ( type == "Size" ) return "const QSize &"; + else if ( type == "Color" ) return "const QColor &"; + else if ( type == "Point" ) return "const QPoint &"; + else if ( type == "Int" ) return "int"; + else if ( type == "UInt" ) return "uint"; + else if ( type == "Bool" ) return "bool"; + else if ( type == "Double" ) return "double"; + else if ( type == "DateTime" ) return "const QDateTime &"; + else if ( type == "Int64" ) return "Q_INT64"; + else if ( type == "UInt64" ) return "Q_UINT64"; + else if ( type == "IntList" ) return "const QValueList<int> &"; + else if ( type == "Enum" ) return "int"; + else if ( type == "Path" ) return "const QString &"; + else if ( type == "Password" ) return "const QString &"; + else { + kdError() <<"rbkconfig_compiler does not support type \""<< type <<"\""<<endl; + return "QString"; //For now, but an assert would be better + } +} + +/** + Actual Ruby initializer value to give a type. +*/ +QString rbType( const QString &type ) +{ + if ( type == "String" ) return "\"\""; + else if ( type == "StringList" ) return "[]"; + else if ( type == "Font" ) return "Qt::Font.new"; + else if ( type == "Rect" ) return "Qt::Rect.new"; + else if ( type == "Size" ) return "Qt::Size.new"; + else if ( type == "Color" ) return "Qt::Color.new"; + else if ( type == "Point" ) return "Qt::Point.new"; + else if ( type == "Int" ) return "0"; + else if ( type == "UInt" ) return "0"; + else if ( type == "Bool" ) return "false, 42"; + else if ( type == "Double" ) return "0.0"; + else if ( type == "DateTime" ) return "Qt::DateTime.new"; + else if ( type == "Int64" ) return "0"; + else if ( type == "UInt64" ) return "0"; + else if ( type == "IntList" ) return "[]"; + else if ( type == "Enum" ) return "0"; + else if ( type == "Path" ) return "\"\""; + else if ( type == "Password" ) return "\"\""; + else { + kdError()<<"rbkconfig_compiler does not support type \""<< type <<"\""<<endl; + return "nil"; //For now, but an assert would be better + } +} + +QString defaultValue( const QString &type ) +{ + if ( type == "String" ) return "\"\""; // Use empty string, not null string! + else if ( type == "StringList" ) return "[]"; + else if ( type == "Font" ) return "KDE::GlobalSettings.generalFont()"; + else if ( type == "Rect" ) return "Qt::Rect.new()"; + else if ( type == "Size" ) return "Qt::Size.new()"; + else if ( type == "Color" ) return "Qt::Color.new(128, 128, 128)"; + else if ( type == "Point" ) return "Qt::Point.new()"; + else if ( type == "Int" ) return "0"; + else if ( type == "UInt" ) return "0"; + else if ( type == "Bool" ) return "false"; + else if ( type == "Double" ) return "0.0"; + else if ( type == "DateTime" ) return "Qt::DateTime.new()"; + else if ( type == "Int64" ) return "0"; + else if ( type == "UInt64" ) return "0"; + else if ( type == "IntList" ) return "[]"; + else if ( type == "Enum" ) return "0"; + else if ( type == "Path" ) return "\"\""; // Use empty string, not null string! + else if ( type == "Password" ) return "\"\""; // Use empty string, not null string! + else { + kdWarning()<<"Error, rbkconfig_compiler doesn't support the \""<< type <<"\" type!"<<endl; + return "String"; //For now, but an assert would be better + } +} + +QString itemType( const QString &type ) +{ + QString t; + + t = type; + t.replace( 0, 1, t.left( 1 ).upper() ); + return t; +} + +static QString itemVar(const CfgEntry *e) +{ + if (itemAccessors) + return varName( e->name() ) + "Item"; + + return "item" + e->name(); + +} + +QString newItem( const QString &type, const QString &name, const QString &key, + const QString &defaultValue, const QString ¶m = QString::null) +{ + QString t = "Item" + itemType( type ) + + ".new( currentGroup(), " + key + ", " + varName( name ) + param; + if ( type == "Enum" ) { + t += ".toInt"; + t += ", values" + name; + } else if ( type == "Path" ) { + t += ".toString"; + } else if ( type == "Int64" ) { + t += ".toLongLong"; + } else { + t += ".to" + itemType( type ); + } + if ( !defaultValue.isEmpty() ) { + t += ", "; + if ( type == "String" ) t += defaultValue; + else t+= defaultValue; + } + t += " )"; + + return t; +} + +QString addItem( const QString &type, const QString &name, const QString &key, + const QString &defaultValue, const QString ¶m = QString::null, + const QString ¶mName = QString::null ) +{ + QString t = "addItem" + itemType( type ) + + "( " + key + ", " + varName( name ) + param; + if ( type == "Enum" ) t += ", values" + name; + if ( !defaultValue.isEmpty() ) { + t += ", "; + if ( type == "String" ) t += defaultValue; + else if ( type == "Enum" ) t += enumValue(defaultValue); + else t+= defaultValue; + } + + if (!paramName.isNull()) { + t += ", \"" + paramName + "\""; + } + + t += " )"; + + return t; +} + +QString paramString(const QString &s, const CfgEntry *e, int i) +{ + QString result = s; + QString needle = "$("+e->param()+")"; + if (result.contains(needle)) + { + QString tmp; + if (e->paramType() == "Enum") + { + tmp = e->paramValues()[i]; + } + else + { + tmp = QString::number(i); + } + + result.replace(needle, tmp); + } + return result; +} + +QString paramString(const QString &group, const QStringList ¶meters) +{ + QString paramString = group; + QString arguments; + int i = 0; + for( QStringList::ConstIterator it = parameters.begin(); + it != parameters.end(); ++it) + { + if (paramString.contains("$("+*it+")")) + { + i++; + paramString.replace("$("+*it+")", "%s"); + if (i > 1) { + arguments += ", "; + } + arguments += " @param"+*it; + } + } + if (arguments.isEmpty()) + return "\""+group+"\""; + + if (i == 1) { + return "\""+paramString+"\" % "+arguments; + } else { + return "\""+paramString+"\" % ["+arguments+"]"; + } +} + +/* int i is the value of the parameter */ +QString userTextsFunctions( CfgEntry *e, QString itemVarStr=QString::null, QString i=QString::null ) +{ + QString txt; + if (itemVarStr.isNull()) itemVarStr=itemVar(e); + if ( !e->label().isEmpty() ) { + txt += " " + itemVarStr + ".setLabel( i18n("; + if ( !e->param().isEmpty() ) + txt += quoteString(e->label().replace("$("+e->param()+")", i)); + else + txt+= quoteString(e->label()); + txt+= ") )\n"; + } + if ( !e->whatsThis().isEmpty() ) { + txt += " " + itemVarStr + ".setWhatsThis( i18n("; + if ( !e->param().isEmpty() ) + txt += quoteString(e->whatsThis().replace("$("+e->param()+")", i)); + else + txt+= quoteString(e->whatsThis()); + txt+=") )\n"; + } + return txt; +} + +int main( int argc, char **argv ) +{ + KAboutData aboutData( "rbkconfig_compiler", I18N_NOOP("KDE .kcfg compiler"), "0.3", + I18N_NOOP("Ruby KConfig Compiler") , KAboutData::License_LGPL ); + aboutData.addAuthor( "Cornelius Schumacher", 0, "schumacher@kde.org" ); + aboutData.addAuthor( "Waldo Bastian", 0, "bastian@kde.org" ); + aboutData.addAuthor( "Zack Rusin", 0, "zack@kde.org" ); + aboutData.addCredit( "Reinhold Kainhofer", "Fix for parametrized entries", + "reinhold@kainhofer.com", "http://reinhold.kainhofer.com" ); + aboutData.addCredit( "Richard Dale", "Ruby port", + "Richard_Dale@tipitina.demon.co.uk", "" ); + + KCmdLineArgs::init( argc, argv, &aboutData ); + KCmdLineArgs::addCmdLineOptions( options ); + + KInstance app( &aboutData ); + + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + + if ( args->count() < 2 ) { + kdError() << "Too few arguments." << endl; + return 1; + } + if ( args->count() > 2 ) { + kdError() << "Too many arguments." << endl; + return 1; + } + + validNameRegexp = new QRegExp("[a-zA-Z_][a-zA-Z0-9_]*"); + + QString baseDir = QFile::decodeName(args->getOption("directory")); + if (!baseDir.endsWith("/")) + baseDir.append("/"); + + QString inputFilename = args->url( 0 ).path(); + QString codegenFilename = args->url( 1 ).path(); + + if (!codegenFilename.endsWith(".kcfgc")) + { + kdError() << "Codegen options file must have extension .kcfgc" << endl; + return 1; + } + QString baseName = args->url( 1 ).fileName(); + baseName = baseName.left(baseName.length() - 6); + + KSimpleConfig codegenConfig( codegenFilename, true ); + + QString nameSpace = codegenConfig.readEntry("NameSpace"); + QString className = codegenConfig.readEntry("ClassName"); + QString inherits = codegenConfig.readEntry("Inherits"); + QString visibility = codegenConfig.readEntry("Visibility"); + if (!visibility.isEmpty()) visibility+=" "; + bool singleton = codegenConfig.readBoolEntry("Singleton", false); + bool customAddons = codegenConfig.readBoolEntry("CustomAdditions"); + QString memberVariables = codegenConfig.readEntry("MemberVariables"); + QStringList headerIncludes = codegenConfig.readListEntry("IncludeFiles"); + QStringList mutators = codegenConfig.readListEntry("Mutators"); + bool allMutators = false; + if ((mutators.count() == 1) && (mutators[0].lower() == "true")) + allMutators = true; + itemAccessors = codegenConfig.readBoolEntry( "ItemAccessors", false ); + bool setUserTexts = codegenConfig.readBoolEntry( "SetUserTexts", false ); + + globalEnums = codegenConfig.readBoolEntry( "GlobalEnums", false ); + + QFile input( inputFilename ); + + QDomDocument doc; + QString errorMsg; + int errorRow; + int errorCol; + if ( !doc.setContent( &input, &errorMsg, &errorRow, &errorCol ) ) { + kdError() << "Unable to load document." << endl; + kdError() << "Parse error in " << args->url( 0 ).fileName() << ", line " << errorRow << ", col " << errorCol << ": " << errorMsg << endl; + return 1; + } + + QDomElement cfgElement = doc.documentElement(); + + if ( cfgElement.isNull() ) { + kdError() << "No document in kcfg file" << endl; + return 1; + } + + QString cfgFileName; + bool cfgFileNameArg = false; + QStringList parameters; + QStringList includes; + + QPtrList<CfgEntry> entries; + entries.setAutoDelete( true ); + + QDomNode n; + for ( n = cfgElement.firstChild(); !n.isNull(); n = n.nextSibling() ) { + QDomElement e = n.toElement(); + + QString tag = e.tagName(); + + if ( tag == "include" ) { + QString includeFile = e.text(); + if (!includeFile.isEmpty()) + includes.append(includeFile); + + } else if ( tag == "kcfgfile" ) { + cfgFileName = e.attribute( "name" ); + cfgFileNameArg = e.attribute( "arg" ).lower() == "true"; + QDomNode n2; + for( n2 = e.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) { + QDomElement e2 = n2.toElement(); + if ( e2.tagName() == "parameter" ) { + parameters.append( e2.attribute( "name" ) ); + } + } + + } else if ( tag == "group" ) { + QString group = e.attribute( "name" ); + if ( group.isEmpty() ) { + kdError() << "Group without name" << endl; + return 1; + } + QDomNode n2; + for( n2 = e.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) { + QDomElement e2 = n2.toElement(); + if ( e2.tagName() != "entry" ) continue; + CfgEntry *entry = parseEntry( group, e2 ); + if ( entry ) entries.append( entry ); + else { + kdError() << "Can't parse entry." << endl; + return 1; + } + } + } + } + + if ( inherits.isEmpty() ) inherits = "KDE::ConfigSkeleton"; + + if ( className.isEmpty() ) { + kdError() << "Class name missing" << endl; + return 1; + } + + if ( singleton && !parameters.isEmpty() ) { + kdError() << "Singleton class can not have parameters" << endl; + return 1; + } + + if ( singleton && cfgFileNameArg) + { + kdError() << "Singleton class can not use filename as argument." << endl; + return 1; + } + + if ( !cfgFileName.isEmpty() && cfgFileNameArg) + { + kdError() << "Having both a fixed filename and a filename as argument is not possible." << endl; + return 1; + } + + if ( entries.isEmpty() ) { + kdWarning() << "No entries." << endl; + } + +#if 0 + CfgEntry *cfg; + for( cfg = entries.first(); cfg; cfg = entries.next() ) { + cfg->dump(); + } +#endif + + QString implementationFileName = baseName + ".rb"; + + QFile implementation( baseDir + implementationFileName ); + if ( !implementation.open( IO_WriteOnly ) ) { + kdError() << "Can't open '" << implementationFileName << "for writing." << endl; + return 1; + } + + QTextStream rb( &implementation ); + + rb << "# This file is generated by rbkconfig_compiler from " << args->url(0).fileName() << "." << endl; + rb << "# All changes you do to this file will be lost." << endl; + rb << endl << "require 'Korundum'" << endl; + + if (singleton) { + rb << "require 'singleton'" << endl; + } + + rb << endl; + +// rb << "#ifndef " << ( !nameSpace.isEmpty() ? nameSpace.upper() + "_" : "" ) +// << className.upper() << "_H" << endl; +// rb << "#define " << ( !nameSpace.isEmpty() ? nameSpace.upper() + "_" : "" ) +// << className.upper() << "_H" << endl << endl; + + // Includes +// QStringList::ConstIterator it; +// for( it = headerIncludes.begin(); it != headerIncludes.end(); ++it ) { +// rb << "#include <" << *it << ">" << endl; +// } + + if ( headerIncludes.count() > 0 ) rb << endl; + +// rb << "#include <kconfigskeleton.h>" << endl << endl; + + if ( !nameSpace.isEmpty() ) + rb << "module " << nameSpace << endl << endl; + + // Class declaration header + rb << "class " << className << " < " << inherits << endl; + + if (singleton) { + rb << " include Singleton" << endl << endl; + } + + // enums + CfgEntry *e; + for( e = entries.first(); e; e = entries.next() ) { + QValueList<CfgEntry::Choice> choices = e->choices(); + if ( !choices.isEmpty() ) { + QStringList values; + QValueList<CfgEntry::Choice>::ConstIterator itChoice; + for( itChoice = choices.begin(); itChoice != choices.end(); ++itChoice ) { + if (globalEnums) { + values.append( enumValue((*itChoice).name) ); + } else { + values.append( enumName(e->name()) + "_" + (*itChoice).name ); + } + } + if (!globalEnums) { + values.append( enumName(e->name()) + "_COUNT" ); + } + int count = 0; + for ( QStringList::Iterator it = values.begin(); it != values.end(); ++it, count++ ) { + rb << " " << *it << " = " << count << endl; + } + rb << endl; + } + + QStringList values = e->paramValues(); + if ( !values.isEmpty() ) { + int count = 0; + for ( QStringList::Iterator it = values.begin(); it != values.end(); ++it, count++ ) { + if (globalEnums) { + rb << " " << enumValue(*it) << " = " << count << endl; + } else { + rb << " " << enumName(e->param()) << "_" << *it << " = " << count << endl; + } + } + if (!globalEnums) { + rb << " " << enumName(e->param()) << "_COUNT = " << count << endl; + } + rb << endl; + + rb << " def " << enumName(e->param()) << "ToString(i)" << endl; + rb << " ["; + count = 0; + for ( QStringList::Iterator it = values.begin(); it != values.end(); ++it, count++ ) { + if (count > 0) { + rb << ", "; + } + + rb << "\"" << *it << "\""; + } + + rb << "].at(i)" << endl; + rb << " end" << endl; + } + } + + rb << endl; + + for( e = entries.first(); e; e = entries.next() ) { + QString n = e->name(); + QString t = e->type(); + + // Manipulator + if (allMutators || mutators.contains(n)) + { + rb << " #" << endl; + rb << " # Set " << e->label() << endl; + rb << " #" << endl; + rb << " def " << setFunction(n) << "( "; + if (!e->param().isEmpty()) + rb << " i, "; + rb << " v )" << endl; + rb << " item = findItem( \""; + if (!e->param().isEmpty()) { + rb << e->paramName().replace("$("+e->param()+")", "%s") << "\" % "; + if ( e->paramType() == "Enum" ) { + rb << " "; + if (globalEnums) + rb << enumName(e->param()) << "ToString(i)"; + else + rb << enumName(e->param()) << "ToString(i)"; + } else { + rb << "i"; + } + } else { + rb << n << "\""; + } + rb << " )" << endl; + rb << " if !item.immutable? " << endl; + rb << " item.property = " << varName(n); + if (!e->param().isEmpty()) + rb << "[i]"; + rb << " = Qt::Variant.new( v )" << endl; + rb << " end" << endl; + rb << " end" << endl << endl; + } + + // Accessor + rb << " #" << endl; + rb << " # Get " << e->label() << endl; + rb << " #" << endl; + rb << " def " << getFunction(n) << "("; + if (!e->param().isEmpty()) + rb << " " <<" i "; + rb << ")" << endl; + rb << " " << varName(n); + if (!e->param().isEmpty()) rb << "[i]"; + rb << " = findItem( \""; + if (!e->param().isEmpty()) { + rb << e->paramName().replace("$("+e->param()+")", "%s") << "\" % "; + if ( e->paramType() == "Enum" ) { + rb << " "; + if (globalEnums) + rb << enumName(e->param()) << "ToString(i)"; + else + rb << enumName(e->param()) << "ToString(i)"; + } else { + rb << "i"; + } + } else { + rb << n << "\""; + } + rb << " ).property" << endl; + rb << " return " << varName(n); + if (!e->param().isEmpty()) rb << "[i]"; + if ( e->type() == "Enum" ) { + rb << ".toInt" << endl; + } else if ( e->type() == "Int64" ) { + rb << ".toLongLong" << endl; + } else if ( e->type() == "Path" ) { + rb << ".toString" << endl; + } else { + rb << ".to" << itemType( e->type() ) << endl; + } + rb << " end" << endl; + + // Item accessor + if ( itemAccessors ) { + rb << endl; + rb << " #" << endl; + rb << " # Get Item object corresponding to " << n << "()" + << endl; + rb << " #" << endl; + rb << " def " + << getFunction( n ) << "Item("; + if (!e->param().isEmpty()) { + rb << " " << " i "; + } + rb << ")" << endl; + rb << " return " << itemVar(e); + if (!e->param().isEmpty()) rb << "[i]"; + rb << endl << " end" << endl; + } + + rb << endl; + } + + + if (customAddons) + { + rb << " # Include custom additions" << endl; + } + + + // Constructor + rb << " def initialize( "; + if (cfgFileNameArg) + rb << " config" << (parameters.isEmpty() ? " " : ", "); + for (QStringList::ConstIterator it = parameters.begin(); + it != parameters.end(); ++it) + { + if (it != parameters.begin()) + rb << ","; + rb << " " << *it; + } + rb << " )" << endl; + + rb << " super("; + if ( !cfgFileName.isEmpty() ) rb << " \"" << cfgFileName << "\" "; + if ( cfgFileNameArg ) rb << " config "; +// if ( !cfgFileName.isEmpty() ) rb << ") "; + rb << ")" << endl; + + // Store parameters + for (QStringList::ConstIterator it = parameters.begin(); + it != parameters.end(); ++it) + { + rb << " @param" << *it << " = Qt::Variant.new( " << *it << " )" << endl; + } + + QString group; + for( e = entries.first(); e; e = entries.next() ) { + if ( e->group() != group ) { + group = e->group(); + rb << endl; + rb << " # " << group << endl; + } + if (e->param().isEmpty()) { + rb << " " << varName(e->name()) << " = Qt::Variant.new( " << rbType(e->type()) << " )"; + } else { + rb << " " << varName(e->name()) << " = [ "; + for (int i = 0; i < e->paramMax()+1; i++) { + if (i > 0) { + rb << ", "; + } + rb << "Qt::Variant.new( " << rbType(e->type()) << " )"; + } + rb << " ]"; + } + rb << endl; + } + + rb << endl; + + + group = QString::null; + for( e = entries.first(); e; e = entries.next() ) { + if ( e->group() != group ) { + if ( !group.isEmpty() ) rb << endl; + group = e->group(); + rb << " setCurrentGroup( " << paramString(group, parameters) << " )" << endl << endl; + } + + QString key = paramString(e->key(), parameters); + if ( !e->code().isEmpty()) + { + rb << e->code() << endl; + } + if ( e->type() == "Enum" ) { + rb << " values" + << e->name() << " = []" << endl; + QValueList<CfgEntry::Choice> choices = e->choices(); + QValueList<CfgEntry::Choice>::ConstIterator it; + for( it = choices.begin(); it != choices.end(); ++it ) { + rb << " choice = ItemEnum::Choice.new" << endl; + rb << " choice.name = \"" << enumValue((*it).name) << "\" " << endl; + if ( setUserTexts ) { + if ( !(*it).label.isEmpty() ) + rb << " choice.label = i18n(" << quoteString((*it).label) << ")" << endl; + if ( !(*it).whatsThis.isEmpty() ) + rb << " choice.whatsThis = i18n(" << quoteString((*it).whatsThis) << ")" << endl; + } + rb << " values" << e->name() << " << choice" << endl; + } + } + + if (e->param().isEmpty()) + { + // Normal case + rb << " " << itemVar(e) << " = " + << newItem( e->type(), e->name(), key, e->defaultValue() ) << endl; + + rb << " " << itemVar(e) << ".property = " << varName(e->name()) << endl; + + if ( !e->minValue().isEmpty() ) + rb << " " << itemVar(e) << ".setMinValue(" << e->minValue() << ")" << endl; + if ( !e->maxValue().isEmpty() ) + rb << " " << itemVar(e) << ".setMaxValue(" << e->maxValue() << ")" << endl; + + if ( setUserTexts ) + rb << userTextsFunctions( e ); + + rb << " addItem( " << itemVar(e); + QString quotedName = e->name(); + addQuotes( quotedName ); + if ( quotedName != key ) rb << ", \"" << e->name() << "\""; + rb << " )" << endl; + } + else + { + // Indexed + rb << " " << itemVar(e) << " = Array.new(" << e->paramMax()+1 << ")" << endl; + for(int i = 0; i <= e->paramMax(); i++) + { + QString defaultStr; + QString itemVarStr(itemVar(e)+QString("[%1]").arg(i)); + + if ( !e->paramDefaultValue(i).isEmpty() ) + defaultStr = e->paramDefaultValue(i); + else if ( !e->defaultValue().isEmpty() ) + defaultStr = paramString(e->defaultValue(), e, i); + else + defaultStr = defaultValue( e->type() ); + + rb << " " << itemVarStr << " = " + << newItem( e->type(), e->name(), paramString(key, e, i), defaultStr, QString("[%1]").arg(i) ) + << endl; + + rb << " " << itemVarStr << ".property = " << varName(e->name())+QString("[%1]").arg(i) << endl; + + if ( setUserTexts ) + rb << userTextsFunctions( e, itemVarStr, e->paramName() ); + + // Make mutators for enum parameters work by adding them with $(..) replaced by the + // param name. The check for isImmutable in the set* functions doesn't have the param + // name available, just the corresponding enum value (int), so we need to store the + // param names in a separate static list!. + rb << " addItem( " << itemVarStr << ", \""; + if ( e->paramType()=="Enum" ) + rb << e->paramName().replace( "$("+e->param()+")", "%1").arg(e->paramValues()[i] ); + else + rb << e->paramName().replace( "$("+e->param()+")", "%1").arg(i); + rb << "\" )" << endl; + + } + } + } + + rb << " end" << endl << endl; + + rb << "end" << endl << endl; + + if ( !nameSpace.isEmpty() ) rb << "end" << endl << endl; + + implementation.close(); +} diff --git a/korundum/rubylib/rbkconfig_compiler/tests/Makefile.am b/korundum/rubylib/rbkconfig_compiler/tests/Makefile.am new file mode 100644 index 00000000..ce61f658 --- /dev/null +++ b/korundum/rubylib/rbkconfig_compiler/tests/Makefile.am @@ -0,0 +1,40 @@ +check_PROGRAMS = test1 test2 test3 test4 test5 + +CLEANFILES = test1.rb \ + test2.rb \ + test3.rb \ + test4.rb \ + test5.rb \ + md5sums + +all: $(SOURCES) + +# Splitting this with backslashses produces broken Makefiles +SOURCES = test1main.rb test1.rb test2main.rb test2.rb test3main.rb test3.rb test4main.rb test4.rb test5main.rb test5.rb + +# avoid running the below command in parallel +test1.rb: $(srcdir)/test1.kcfg ../rbkconfig_compiler $(srcdir)/test1.kcfgc + ../rbkconfig_compiler $(srcdir)/test1.kcfg $(srcdir)/test1.kcfgc + +# avoid running the below command in parallel +test2.rb: $(srcdir)/test2.kcfg ../rbkconfig_compiler $(srcdir)/test2.kcfgc + ../rbkconfig_compiler $(srcdir)/test2.kcfg $(srcdir)/test2.kcfgc + +# avoid running the below command in parallel +test3.rb: $(srcdir)/test3.kcfg ../rbkconfig_compiler $(srcdir)/test3.kcfgc + ../rbkconfig_compiler $(srcdir)/test3.kcfg $(srcdir)/test3.kcfgc + +# avoid running the below command in parallel +test4.rb: $(srcdir)/test4.kcfg ../rbkconfig_compiler $(srcdir)/test4.kcfgc + ../rbkconfig_compiler $(srcdir)/test4.kcfg $(srcdir)/test4.kcfgc + +# avoid running the below command in parallel +test5.rb: $(srcdir)/test5.kcfg ../rbkconfig_compiler $(srcdir)/test5.kcfgc + ../rbkconfig_compiler $(srcdir)/test5.kcfg $(srcdir)/test5.kcfgc + +md5sums: + $(MD5SUM) $(srcdir)/test*.ref | sed -e "s,$(srcdir)/,,; s,\.ref$$,," > md5sums + +md5check: test1.rb test2.rb test3.rb test4.rb test5.rb md5sums + $(MD5SUM) --check md5sums + diff --git a/korundum/rubylib/rbkconfig_compiler/tests/myprefs.rb b/korundum/rubylib/rbkconfig_compiler/tests/myprefs.rb new file mode 100644 index 00000000..a4f1f082 --- /dev/null +++ b/korundum/rubylib/rbkconfig_compiler/tests/myprefs.rb @@ -0,0 +1,5 @@ +class MyPrefs < KDE::ConfigSkeleton + def initialize( a ) + super( a ) + end +end diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test1.kcfg b/korundum/rubylib/rbkconfig_compiler/tests/test1.kcfg new file mode 100644 index 00000000..0c0c8216 --- /dev/null +++ b/korundum/rubylib/rbkconfig_compiler/tests/test1.kcfg @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="UTF-8"?> +<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 + http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" > + <include>qdir.h</include> + <kcfgfile name="examplerc"> + <parameter name="transport" /> + <parameter name="folder" /> + </kcfgfile> + <group name="General-$(folder)"> + <entry name="OneOption" type="Bool"> + <label>One option</label> + <default>true</default> + </entry> + <entry name="AnotherOption" type="Int" key="Another Option"> + <label>Another option</label> + <default>5</default> + </entry> + <entry name="ListOption" type="Enum"> + <label>This is some funky option</label> + <whatsthis>And this is a longer description of this option. Just wondering, how will the translations of those be handled?</whatsthis> + <choices> + <choice name="One"/> + <choice name="Two"/> + <choice name="Three"/> + </choices> + <default>One</default> + </entry> + </group> + <group name="MyOptions"> + <entry name="MyString" type="String"> + <label>This is a string</label> + <default>Default String</default> + </entry> + <entry name="MyPath" type="Path"> + <label>This is a path</label> + <default code="true">Qt::Dir.homeDirPath()+".hidden_file"</default> + </entry> + <entry name="AnotherOption2" type="Int" key="Another Option"> + <label>Another option</label> + <default>10</default> + </entry> + <entry name="MyStringList" type="StringList"> + <default>up,down</default> + </entry> + <entry name="MyStringListHidden" hidden="true" type="StringList"> + <default>up,down</default> + </entry> + <entry name="MyNumber" type="Int" key="List-$(transport)-$(folder)"> + <label>List Number</label> + <default>1</default> + </entry> + </group> +</kcfg> diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test1.kcfgc b/korundum/rubylib/rbkconfig_compiler/tests/test1.kcfgc new file mode 100644 index 00000000..6e0edd36 --- /dev/null +++ b/korundum/rubylib/rbkconfig_compiler/tests/test1.kcfgc @@ -0,0 +1,18 @@ +# Code generation options for kconfig_compiler +ClassName=Test1 +# +# Singleton=false +# +# Inherits=KConfigSkeleton +# +# IncludeFiles=libkdepim/kpimprefs.h +# +# MemberVariables=public +# +### The following line includes the file exampleprefs_base_addon.h +### It can be used to add extra functions and variables to the +### class. +# CustomAdditions=true +# +### Provide setFooBar(int) style functions +Mutators=true diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test1main.rb b/korundum/rubylib/rbkconfig_compiler/tests/test1main.rb new file mode 100644 index 00000000..88a151a6 --- /dev/null +++ b/korundum/rubylib/rbkconfig_compiler/tests/test1main.rb @@ -0,0 +1,4 @@ +require 'Korundum' +require 'test1.rb' + +t = Test1.new(nil, nil) diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test2.kcfg b/korundum/rubylib/rbkconfig_compiler/tests/test2.kcfg new file mode 100644 index 00000000..3b19e270 --- /dev/null +++ b/korundum/rubylib/rbkconfig_compiler/tests/test2.kcfg @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="UTF-8"?> +<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 + http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" > + <kcfgfile name="korganizerrc"/> + + <group name="General"> + <entry type="Bool" key="Auto Save"> + <label>Enable automatic saving of calendar</label> + <whatsthis>WhatsThis text for AutoSave option</whatsthis> + <default>false</default> + </entry> + <entry type="Int" key="Auto Save Interval"> + <default>10</default> + </entry> + <entry type="Bool" key="Confirm Deletes" name="Confirm"> + <label>Confirm deletes</label> + <default>true</default> + </entry> + <entry type="String" key="Archive File"> + </entry> + <entry type="Enum" key="Destination" name="Destination"> + <label>New Events/Todos Should</label> + <choices> + <choice name="standardDestination"> + </choice> + <choice name="askDestination"> + </choice> + <choice name="argl1"> + <label>Argl1 Label</label> + </choice> + <choice name="argl2"> + <whatsthis>Argl2 Whatsthis</whatsthis> + </choice> + <choice name="argl3"> + <label>Argl3 Label</label> + <whatsthis>Argl3 Whatsthis</whatsthis> + </choice> + </choices> + <default>standardDestination</default> + </entry> + </group> + + <group name="Views"> + <entry type="Int" key="Hour Size"> + <default>10</default> + </entry> + <entry type="Bool" name="SelectionStartsEditor"> + <label>Time range selection in agenda view starts event editor</label> + <default>false</default> + </entry> + </group> + + <group name="KOrganizer Plugins"> + <entry type="StringList" name="SelectedPlugins"> + <default>holidays,webexport</default> + </entry> + </group> + + <group name="Colors"> + <entry type="Color" key="Highlight Color"> + <label>Highlight color</label> + <default>100, 100, 255</default> + </entry> + <entry type="Color" key="Agenda Background Color" name="AgendaBgColor"> + <label>Agenda view background color</label> + <default>255, 255, 255</default> + </entry> + </group> + + <group name="Fonts"> + <entry type="Font" key="TimeBar Font"> + <label>Time bar</label> + </entry> + </group> + +</kcfg> diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test2.kcfgc b/korundum/rubylib/rbkconfig_compiler/tests/test2.kcfgc new file mode 100644 index 00000000..56620d2f --- /dev/null +++ b/korundum/rubylib/rbkconfig_compiler/tests/test2.kcfgc @@ -0,0 +1,11 @@ +# Code generation options for kconfig_compiler +File=test2.kcfg +ClassName=Test2 +Singleton=false +Mutators=true +Inherits=MyPrefs +IncludeFiles=myprefs.h +MemberVariables=public +GlobalEnums=true +ItemAccessors=true +SetUserTexts=true diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test2main.rb b/korundum/rubylib/rbkconfig_compiler/tests/test2main.rb new file mode 100644 index 00000000..85d18f07 --- /dev/null +++ b/korundum/rubylib/rbkconfig_compiler/tests/test2main.rb @@ -0,0 +1,5 @@ +require 'Korundum' +require 'myprefs.rb' +require 'test2.rb' + +t = Test2.new() diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test3.kcfg b/korundum/rubylib/rbkconfig_compiler/tests/test3.kcfg new file mode 100644 index 00000000..77916da4 --- /dev/null +++ b/korundum/rubylib/rbkconfig_compiler/tests/test3.kcfg @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 + http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" > + <kcfgfile name="test3rc"/> + + <group name="General"> + <entry type="Bool" key="Auto Save"> + <label>Enable automatic saving of calendar</label> + <whatsthis>WhatsThis text for AutoSave option</whatsthis> + <default>false</default> + </entry> + </group> + + <group name="Blah"> + <entry type="Int" name="Blubb"> + <default>10</default> + </entry> + <entry type="String" name="BlahBlah"> + <default>a string</default> + </entry> + <entry type="Password" name="MyPassword"/> + </group> + +</kcfg> diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test3.kcfgc b/korundum/rubylib/rbkconfig_compiler/tests/test3.kcfgc new file mode 100644 index 00000000..ca2c2205 --- /dev/null +++ b/korundum/rubylib/rbkconfig_compiler/tests/test3.kcfgc @@ -0,0 +1,12 @@ +# Code generation options for kconfig_compiler +File=test3.kcfg +NameSpace=TestNameSpace +ClassName=Test3 +#Singleton=false +Mutators=true +#Inherits=MyPrefs +#IncludeFiles=myprefs.h +#MemberVariables=public +GlobalEnums=true +ItemAccessors=true +#SetUserTexts=true diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test3main.rb b/korundum/rubylib/rbkconfig_compiler/tests/test3main.rb new file mode 100644 index 00000000..8c19b442 --- /dev/null +++ b/korundum/rubylib/rbkconfig_compiler/tests/test3main.rb @@ -0,0 +1,4 @@ +require 'Korundum' +require 'test3.rb' + +t = TestNameSpace::Test3.new() diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test4.kcfg b/korundum/rubylib/rbkconfig_compiler/tests/test4.kcfg new file mode 100644 index 00000000..1428bc0d --- /dev/null +++ b/korundum/rubylib/rbkconfig_compiler/tests/test4.kcfg @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="UTF-8"?> +<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 + http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" > + <kcfgfile name="test4rc"/> + + <group name="Foo"> + <entry name="Color$(Number)" type="Color" key="color #$(Number)"> + <parameter name="Number" type="Int" max="3"/> + <label>Block colors.</label> + <code>defaultColor = [ Qt::red, Qt::blue, Qt::green, Qt::black ]</code> + <default code="true">defaultColor[$(Number)]</default> + </entry> + <entry name="MouseAction$(Button)" type="Enum" key="$(Button)_mouse_action"> + <parameter name="Button" type="Enum"> + <values> + <value>right</value> + <value>mid</value> + <value>left</value> + </values> + </parameter> + <label>Mouse actions.</label> + <choices> + <choice name="Encrypt"/> + <choice name="Decrypt"/> + <choice name="CrashNBurn"/> + <choice name="PumpNDump"/> + </choices> + <default param="right">Decrypt</default> + <default param="mid">Encrypt</default> + <default param="left">PumpNDump</default> + </entry> + <entry name="FooBar" key="foo bar" type="String"/> + <entry name="Age" type="Int"> + <default>35</default> + <min>8</min> + <max>88</max> + </entry> + </group> + +</kcfg> diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test4.kcfgc b/korundum/rubylib/rbkconfig_compiler/tests/test4.kcfgc new file mode 100644 index 00000000..754706df --- /dev/null +++ b/korundum/rubylib/rbkconfig_compiler/tests/test4.kcfgc @@ -0,0 +1,11 @@ +# Code generation options for kconfig_compiler +File=test4.kcfg +ClassName=Test4 +Singleton=true +Mutators=true +#Inherits=MyPrefs +#IncludeFiles=myprefs.h +#MemberVariables=public +GlobalEnums=false +ItemAccessors=false +#SetUserTexts=true diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test4main.rb b/korundum/rubylib/rbkconfig_compiler/tests/test4main.rb new file mode 100644 index 00000000..c75f0995 --- /dev/null +++ b/korundum/rubylib/rbkconfig_compiler/tests/test4main.rb @@ -0,0 +1,4 @@ +require 'Korundum' +require 'test4.rb' + +t = Test4.instance() diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test5.kcfg b/korundum/rubylib/rbkconfig_compiler/tests/test5.kcfg new file mode 100644 index 00000000..1428bc0d --- /dev/null +++ b/korundum/rubylib/rbkconfig_compiler/tests/test5.kcfg @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="UTF-8"?> +<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 + http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" > + <kcfgfile name="test4rc"/> + + <group name="Foo"> + <entry name="Color$(Number)" type="Color" key="color #$(Number)"> + <parameter name="Number" type="Int" max="3"/> + <label>Block colors.</label> + <code>defaultColor = [ Qt::red, Qt::blue, Qt::green, Qt::black ]</code> + <default code="true">defaultColor[$(Number)]</default> + </entry> + <entry name="MouseAction$(Button)" type="Enum" key="$(Button)_mouse_action"> + <parameter name="Button" type="Enum"> + <values> + <value>right</value> + <value>mid</value> + <value>left</value> + </values> + </parameter> + <label>Mouse actions.</label> + <choices> + <choice name="Encrypt"/> + <choice name="Decrypt"/> + <choice name="CrashNBurn"/> + <choice name="PumpNDump"/> + </choices> + <default param="right">Decrypt</default> + <default param="mid">Encrypt</default> + <default param="left">PumpNDump</default> + </entry> + <entry name="FooBar" key="foo bar" type="String"/> + <entry name="Age" type="Int"> + <default>35</default> + <min>8</min> + <max>88</max> + </entry> + </group> + +</kcfg> diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test5.kcfgc b/korundum/rubylib/rbkconfig_compiler/tests/test5.kcfgc new file mode 100644 index 00000000..663005e5 --- /dev/null +++ b/korundum/rubylib/rbkconfig_compiler/tests/test5.kcfgc @@ -0,0 +1,11 @@ +# Code generation options for kconfig_compiler +File=test5.kcfg +ClassName=Test5 +Singleton=true +Mutators=true +#Inherits=MyPrefs +#IncludeFiles=myprefs.h +#MemberVariables=public +GlobalEnums=true +ItemAccessors=false +#SetUserTexts=true diff --git a/korundum/rubylib/rbkconfig_compiler/tests/test5main.rb b/korundum/rubylib/rbkconfig_compiler/tests/test5main.rb new file mode 100644 index 00000000..cd0fbeb7 --- /dev/null +++ b/korundum/rubylib/rbkconfig_compiler/tests/test5main.rb @@ -0,0 +1,4 @@ +require 'Korundum' +require 'test5.rb' + +t = Test5.instance() diff --git a/korundum/rubylib/templates/annotated/basicapp.rb b/korundum/rubylib/templates/annotated/basicapp.rb new file mode 100644 index 00000000..41f61bce --- /dev/null +++ b/korundum/rubylib/templates/annotated/basicapp.rb @@ -0,0 +1,106 @@ +=begin +This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale +=end + +=begin +Copyright 2003 Jim Bublitz + +Terms and Conditions + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KDE::IND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +Except as contained in this notice, the name of the copyright holder shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from the +copyright holder. +=end + +require 'Korundum' + +=begin +Most Korundum applications will need a main window - the is the top +level widget (the parent for all other widgets). KDE::MainWindow has +more functionality than shown here (see more complex templates). +It has the ability to create the other major parts of the user +interface - the main view, menus, toolbars, etc. + +Usually you provide a subclass of KDE::MainWindow, construct menus +and toolbars in the subclass' initialize method, and provide +slots for menu/toolbar actions in separate methods. +=end + +class MainWin < KDE::MainWindow + def initialize(*args) + super + end + +end +#-------------------- main ------------------------------------------------ + +# set up some basic information about the program in +# a KDE::AboutData object - this affects the application's +# title bar caption and makes it easy to set up a +# Help | About dialog box for your app +description = "A basic application template" +version = "1.0" +aboutData = KDE::AboutData.new("", "", + version, description, KDE::AboutData::License_GPL, + "(C) 2003 whoever the author is") + +# you can add the names of the app's authors here +aboutData.addAuthor("author1", "whatever they did", "email@somedomain") +aboutData.addAuthor("author2", "they did something else", "another@email.address") + +# Pass the command line arguments and aboutData to +# KDE::CmdLineArgs - this is where KDE will look for +# this information. The KDE::Application constructor +# used below *requires* the args are processed +# *before* KDE::Application is instantiated. There +# is an alternate constructor that takes ARGV +# as an argument (see minimal.rb) + +# Note that instead of argc/argv, this constructor +# only takes a single argument - ARGV - which +# is a Ruby list +KDE::CmdLineArgs.init(ARGV, aboutData) + +# Set up the command line options (switches) you +# want your app to be able to process (you could +# use Ruby's getopt module instead, but it works +# a little differently) + +# Note that the argument for this method is a list +# of three element lists +KDE::CmdLineArgs.addCmdLineOptions([["+files", "File to open", ""]]) + +# instantiate KDE::Application - no other QObject +# or QWidget based classes can be instantiated +# until there is a KApplication instance +app = KDE::Application.new() + +# instantiate the subclass of KMainWindow +mainWindow = MainWin.new(nil, "main window") + +# create the display +mainWindow.show + +# run KDE::Application's event loop until the +# program exits +app.exec + diff --git a/korundum/rubylib/templates/annotated/menuapp1.rb b/korundum/rubylib/templates/annotated/menuapp1.rb new file mode 100644 index 00000000..0553aa14 --- /dev/null +++ b/korundum/rubylib/templates/annotated/menuapp1.rb @@ -0,0 +1,278 @@ +=begin +This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale +=end + + +=begin +This template constructs an application with menus, toolbar and statusbar, +HOWEVER it is not recommended this template actually be used. It presents +the "KDE 1.0" method for constructing menus and toolbars - later versions +of KDE have introduced better(easier and more powerful) methods for +doing this job - see other menuapp*.rb templates for these methods +=end + +=begin +Copyright 2003 Jim Bublitz + +Terms and Conditions + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KDE::IND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +Except as contained in this notice, the name of the copyright holder shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from the +copyright holder. +=end + + +require 'Korundum' + +class MainWin < KDE::MainWindow + TOOLBAR_NEW = 1 + TOOLBAR_OPEN = 2 + TOOLBAR_SAVE = 3 + TOOLBAR_CUT = 4 + TOOLBAR_COPY = 5 + TOOLBAR_PASTE = 6 + + STATUSBAR_LEFT = 1 + STATUSBAR_MIDDLE = 2 + STATUSBAR_RIGHT = 3 + + slots 'slotNew()', 'slotOpen()', 'slotSave()', 'slotSaveAs()', 'slotPrint()', 'slotQuit()', 'slotUndo()', + 'slotRedo()', 'slotCut()', 'slotCopy()', 'slotPaste()', 'slotFind()', 'slotFindNext()', 'slotReplace()', + 'slotSpecial()' + + def initialize(*args) + super + + initMenus() + initToolBar() + initStatusBar() + end + + def initMenus() + # Create a QPopupMenu - all menus are "popup" menus + + fileMenu = Qt::PopupMenu.new(self) + + # This is the "simple" KDE-1.0 way. It is not suggested that this + # template actually be used in an application, but it's + # provided to show the underlying mechanics of menu construction + # that KDE makes much easier with other methods (see other + # menuapp*.rb templates for usable examples) + + # All menu item strings are wrapped with i18n - this allows + # internationalization + + # Predefined accelerators are in KDE::StdAccel - these are + # the standard accelerators. For custom accelerators, use + # KDE::Accel. All KDE::StdAccel methods are static, so there is no + # need to instantiate KDE::StdAccel + + # "File" menu items + fileMenu.insertItem(i18n("New"), self, SLOT('slotNew()'), Qt::KeySequence.new(KDE::StdAccel.openNew().keyCodeQt())) + fileMenu.insertItem(i18n("Open"), self, SLOT('slotOpen()'), Qt::KeySequence.new(KDE::StdAccel.open().keyCodeQt())) + fileMenu.insertSeparator() + fileMenu.insertItem(i18n("Save"), self, SLOT('slotSave()'), Qt::KeySequence.new(KDE::StdAccel.save().keyCodeQt())) + + # KStdAccel doesn't have a standard accelerator for 'Save As', + # so we omit it - insertItem uses the default value + fileMenu.insertItem(i18n("SaveAs"), self, SLOT('slotSaveAs()')) + + # This inserts a line between groups of items in a menu + + fileMenu.insertSeparator() + fileMenu.insertItem(i18n("Print"), self, SLOT('slotPrint()'), Qt::KeySequence.new(KDE::StdAccel.print().keyCodeQt())) + fileMenu.insertSeparator() + fileMenu.insertItem(i18n("&Quit"), self, SLOT('slotQuit()'), Qt::KeySequence.new(KDE::StdAccel.quit().keyCodeQt())) + + # Put fileMenu (as the File menu) into the menu bar + # 'menuBar' is a predefined object owned by KDE::MainWindow + menuBar().insertItem(i18n("&File"), fileMenu) + + editMenu = Qt::PopupMenu.new(self) + + # "Edit" menu items + editMenu.insertItem(i18n("Undo"), self, SLOT('slotUndo()'), Qt::KeySequence.new(KDE::StdAccel.undo().keyCodeQt())) + editMenu.insertItem(i18n("Redo"), self, SLOT('slotRedo()'), Qt::KeySequence.new(KDE::StdAccel.redo().keyCodeQt())) + editMenu.insertSeparator() + editMenu.insertItem(i18n("Cut"), self, SLOT('slotCut()'), Qt::KeySequence.new(KDE::StdAccel.cut().keyCodeQt())) + editMenu.insertItem(i18n("Copy"), self, SLOT('slotCopy()'), Qt::KeySequence.new(KDE::StdAccel.copy().keyCodeQt())) + editMenu.insertItem(i18n("Paste"), self, SLOT('slotPaste()'), Qt::KeySequence.new(KDE::StdAccel.paste().keyCodeQt())) + editMenu.insertSeparator() + editMenu.insertItem(i18n("Find"), self, SLOT('slotFind()'), Qt::KeySequence.new(KDE::StdAccel.find().keyCodeQt())) + editMenu.insertItem(i18n("Find Next"), self, SLOT('slotFindNext()'), Qt::KeySequence.new(KDE::StdAccel.findNext().keyCodeQt())) + editMenu.insertItem(i18n("Replace"), self, SLOT('slotReplace()'), Qt::KeySequence.new(KDE::StdAccel.replace().keyCodeQt())) + + # Put editMenu (as the Edit menu) into the menu bar + + menuBar().insertItem(i18n("&Edit"), editMenu) + + # Let KDE generate a nifty help menu + + # The KDE::AboutData/KDE::CmdLineArgs data from the main part of the program + # will be used to generate the About dialog + helpMenu = helpMenu("") + menuBar().insertItem(i18n("&Help"), helpMenu) + end + + def initToolBar() + # KDE::IconLoader will make it easy to locate the standard KDE icons for + # toolbar buttons. For custom icons, a complete path to the icon + # (without the loadIcon call) is needed + icons = KDE::IconLoader.new() + + # KDE::MainWindow owns at least one KDE::ToolBar instance, which is returned + # by 'toolBar()'. To obtain additional toolbars, add an argument + # to the call -- toolBar(1) will return another toolbar you can + # add buttons to. + + # Add buttons to the toolbar. The icon name, id value (eg TOOLBAR_NEW), + # signal to connect (eg clicked) and the slot to connect to all need + # to be specified,as does the tooltip (the last string argument). There + # are easier ways to do this - see other menuapp templates for easier + # methods using KDE::Action/KDE::StdAction + + toolBar().insertButton(icons.loadIcon("filenew", KDE::Icon::Toolbar), TOOLBAR_NEW, SIGNAL("clicked(int)"), + self, SLOT('slotNew()'), true, "New") + toolBar().insertButton(icons.loadIcon("fileopen", KDE::Icon::Toolbar), TOOLBAR_OPEN, SIGNAL("clicked(int)"), + self, SLOT('slotOpen()'), true, "Open") + toolBar().insertButton(icons.loadIcon("filesave", KDE::Icon::Toolbar), TOOLBAR_SAVE, SIGNAL("clicked(int)"), + self, SLOT('slotSave()'), true, "Save") + toolBar().insertButton(icons.loadIcon("editcut", KDE::Icon::Toolbar), TOOLBAR_CUT, SIGNAL("clicked(int)"), + self, SLOT('slotCut()'), true, "Cut") + toolBar().insertButton(icons.loadIcon("editcopy", KDE::Icon::Toolbar), TOOLBAR_COPY, SIGNAL("clicked(int)"), + self, SLOT('slotCopy()'), true, "Copy") + toolBar().insertButton(icons.loadIcon("editpaste", KDE::Icon::Toolbar), TOOLBAR_PASTE, SIGNAL("clicked(int)"), + self, SLOT('slotPaste()'), true, "Paste") + end + + def initStatusBar() + # KDE::MainWindow also owns a KDE::StatusBar instance. The first + # call creates a KDE::StatusBar instance. See 'notImpl' below + # for an example of writing to the status bar. You can + # also add widgets (labels, progress bars, etc) to the + # status bar + + statusBar().insertItem("", STATUSBAR_LEFT, 1000, true) + statusBar().insertItem("", STATUSBAR_MIDDLE, 1000, true) + statusBar().insertItem("", STATUSBAR_RIGHT, 1000, true) + end + + +#-------------------- slots ----------------------------------------------- + + # Slots which can be called from both the menu toolbar + # have a second parameter with a default value (id = -1) + # This is because menu signals expect to connect to a + # slot that takes no arguments, while toolbar signals + # expect to send a signal with an int argument for the + # id of the toolbar button. The default value allows + # both cases to work. + + def slotNew(id = -1) + notImpl("New") + end + + def slotOpen(id = -1) + notImpl("Open") + end + + def slotSave(id = -1) + notImpl("Save") + end + + def slotSaveAs() + notImpl("Save As") + end + + def slotPrint() + notImpl("Print") + end + + def slotQuit() + notImpl("Qt::uit") + end + + def slotUndo() + notImpl("Undo") + end + + def slotRedo() + notImpl("Redo") + end + + def slotCut(id = -1) + notImpl("Cut") + end + + def slotCopy(id = -1) + notImpl("Copy") + end + + def slotPaste(id = -1) + notImpl("Paste") + end + + def slotFind() + notImpl("Find") + end + + def slotFindNext() + notImpl("Find Next") + end + + def slotReplace() + notImpl("Replace") + end + + def notImpl(item = "Feature") + statusBar().changeItem("#{item} not implemented", STATUSBAR_LEFT) + KDE::MessageBox.error(self, "#{item} not implemented", "Not Implemented") + statusBar().changeItem("", STATUSBAR_LEFT) + end +end + +#-------------------- main ------------------------------------------------ + +# See athe minimal.rb and basicapp.rb templates for +# explantion of the basic app and main window setup + +# The following data is passed to KDE::CmdLineArgs, which in +# turn makes it available to the "about" box in the Help +# menu (when the Help menu is created as above) + +description = "A basic application template" +version = "1.0" +aboutData = KDE::AboutData.new("", "", + version, description, KDE::AboutData::License_GPL, + "(C) 2003 whoever the author is") + +aboutData.addAuthor("author1", "whatever they did", "email@somedomain") +aboutData.addAuthor("author2", "they did something else", "another@email.address") + +KDE::CmdLineArgs.init(ARGV, aboutData) + +KDE::CmdLineArgs.addCmdLineOptions([["+files", "File to open", ""]]) + +app = KDE::Application.new() +mainWindow = MainWin.new(nil, "main window") +mainWindow.show +app.exec diff --git a/korundum/rubylib/templates/annotated/menuapp2.rb b/korundum/rubylib/templates/annotated/menuapp2.rb new file mode 100644 index 00000000..d3eab60d --- /dev/null +++ b/korundum/rubylib/templates/annotated/menuapp2.rb @@ -0,0 +1,260 @@ + +=begin +This template constructs an application with menus, toolbar and statusbar. +It uses KDE classes and methods that simplify the task of building and +operating a GUI. It is recommended that this approach be used, rather +than the primitive approach in menuapp1.rb +=end + +=begin +Copyright 2003 Jim Bublitz + +Terms and Conditions + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KDE::IND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +Except as contained in this notice, the name of the copyright holder shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from the +copyright holder. +=end + + +require 'Korundum' + + + +class MainWin < KDE::MainWindow + STATUSBAR_LEFT = 1 + STATUSBAR_MIDDLE = 2 + STATUSBAR_RIGHT = 3 + + slots 'slotNew()', 'slotOpen()', 'slotSave()', 'slotSaveAs()', 'slotPrint()', 'slotQuit()', 'slotUndo()', + 'slotRedo()', 'slotCut()', 'slotCopy()', 'slotPaste()', 'slotFind()', 'slotFindNext()', 'slotReplace()', + 'slotSpecial()' + + def initialize(*args) + super + + # Create the actions that will populate + # the menus and toolbars + initActions() + + # Plug actions into menus + initMenus() + + # Plug actions into toolbars + initToolBar() + + # Create the status bar + initStatusBar() + + # Usings actions, only a single line is required + # to enable/disable both the menu item and corresponding + # toolbar button from anywhere in the program + @saveAction.setEnabled(false) + @saveAsAction.setEnabled(false) + end + + def initActions() + # Most of the functions selectable by menu are "standard" + # actions (open a file, cut, paste, etc) - you customize + # how they behave in your code, but menu, toolbar, and + # accelerator settings are the same across all programs. + # Standard actions also have tooltips already assigned + + # To create most of the actions below, KDE::StdAction is + # is used, since it takes care of everything with + # a single line of code. + + # The standard actions only need to specify the slot + # where the code for the action is located + + # "File" menu items + @newAction = KDE::StdAction.openNew(self, SLOT("slotNew()"), actionCollection()) + @openAction = KDE::StdAction.open(self, SLOT("slotOpen()"), actionCollection()) + @saveAction = KDE::StdAction.save(self, SLOT("slotSave()"), actionCollection()) + @saveAsAction = KDE::StdAction.saveAs(self, SLOT("slotSaveAs()"), actionCollection()) + @printAction = KDE::StdAction.print(self, SLOT("slotPrint()"), actionCollection()) + @quitAction = KDE::StdAction.quit(self, SLOT("slotQuit()"), actionCollection()) + + # "Edit" menu items + @undoAction = KDE::StdAction.undo(self, SLOT("slotUndo()"), actionCollection()) + @redoAction = KDE::StdAction.redo(self, SLOT("slotRedo()"), actionCollection()) + @cutAction = KDE::StdAction.cut(self, SLOT("slotCut()"), actionCollection()) + @copyAction = KDE::StdAction.copy(self, SLOT("slotCopy()"), actionCollection()) + @pasteAction = KDE::StdAction.paste(self, SLOT("slotPaste()"), actionCollection()) + @findAction = KDE::StdAction.find(self, SLOT("slotFind()"), actionCollection()) + @findNextAction = KDE::StdAction.findNext(self, SLOT("slotFindNext()"), actionCollection()) + @replaceAction = KDE::StdAction.replace(self, SLOT("slotReplace()"), actionCollection()) + + # For actions that are not "standard", you can create your + # own actions using KDE::Action. This example doesn't include + # an icon, but there is a KDE::Action constructor that will + # allow you to specify an icon (for toolbar use, for instance), + # or you can use KDE::Action.setIcon to set/change the icon. You + # can also add a tooltip with KDE::Action.setToolTip + + # This KAction constructor requires a string, an accelerator (0 + # in this case), a slot, and a QObject (None in this case) + + @specialAction = KDE::Action.new(i18n("Special"), KDE::Shortcut.new(0), self, SLOT('slotSpecial()'), actionCollection(), "specialActionName") + end + + def initMenus() + # plug the actions into the menus + + fileMenu = Qt::PopupMenu.new(self) + @newAction.plug(fileMenu) + @openAction.plug(fileMenu) + fileMenu.insertSeparator() + @saveAction.plug(fileMenu) + @saveAsAction.plug(fileMenu) + fileMenu.insertSeparator() + @printAction.plug(fileMenu) + fileMenu.insertSeparator() + @quitAction.plug(fileMenu) + menuBar().insertItem(i18n("&File"), fileMenu) + + editMenu = Qt::PopupMenu.new(self) + @undoAction.plug(editMenu) + @redoAction.plug(editMenu) + editMenu.insertSeparator() + @cutAction.plug(editMenu) + @copyAction.plug(editMenu) + @pasteAction.plug(editMenu) + editMenu.insertSeparator() + @findAction.plug(editMenu) + @findNextAction.plug(editMenu) + @replaceAction.plug(editMenu) + editMenu.insertSeparator() + @specialAction.plug(editMenu) + menuBar().insertItem(i18n("&Edit"), editMenu) + + # Uses the info from KAboutData (specified below) + # to construct the "About" box in the Help menu + + helpMenu = helpMenu("") + menuBar().insertItem(i18n("&Help"), helpMenu) + end + + def initToolBar() + # Add some (but not all) actions to the toolbar + + @newAction.plug(toolBar()) + @openAction.plug(toolBar()) + @saveAction.plug(toolBar()) + @cutAction.plug(toolBar()) + @copyAction.plug(toolBar()) + @pasteAction.plug(toolBar()) + end + + def initStatusBar() + # Initialize the status bar + + statusBar().insertItem("", STATUSBAR_LEFT, 1000, true) + statusBar().insertItem("", STATUSBAR_MIDDLE, 1000, true) + statusBar().insertItem("", STATUSBAR_RIGHT, 1000, true) + end + +#-------------------- slots ----------------------------------------------- + + def slotNew(id = -1) + notImpl("New") + end + + def slotOpen(id = -1) + notImpl("Open") + end + + def slotSave(id = -1) + notImpl("Save") + end + + def slotSaveAs() + notImpl("Save As") + end + + def slotPrint() + notImpl("Print") + end + + def slotQuit() + notImpl("Quit") + end + + def slotUndo() + notImpl("Undo") + end + + def slotRedo() + notImpl("Redo") + end + + def slotCut(id = -1) + notImpl("Cut") + end + + def slotCopy(id = -1) + notImpl("Copy") + end + + def slotPaste(id = -1) + notImpl("Paste") + end + + def slotFind() + notImpl("Find") + end + + def slotFindNext() + notImpl("Find Next") + end + + def slotReplace() + notImpl("Replace") + end + + def notImpl(item = "Feature") + statusBar().changeItem("#{item} not implemented", STATUSBAR_LEFT) + KDE::MessageBox.error(self, "#{item} not implemented", "Not Implemented") + statusBar().changeItem("", STATUSBAR_LEFT) + end +end + + +#-------------------- main ------------------------------------------------ + +description = "A basic application template" +version = "1.0" +aboutData = KDE::AboutData.new("", "", + version, description, KDE::AboutData::License_GPL, + "(C) 2003 whoever the author is") + +aboutData.addAuthor("author1", "whatever they did", "email@somedomain") +aboutData.addAuthor("author2", "they did something else", "another@email.address") + +KDE::CmdLineArgs.init(ARGV, aboutData) + +KDE::CmdLineArgs.addCmdLineOptions([["+files", "File to open", ""]]) + +app = KDE::Application.new() +mainWindow = MainWin.new(nil, "main window") +mainWindow.show +app.exec diff --git a/korundum/rubylib/templates/annotated/menuapp3.rb b/korundum/rubylib/templates/annotated/menuapp3.rb new file mode 100644 index 00000000..bd701d43 --- /dev/null +++ b/korundum/rubylib/templates/annotated/menuapp3.rb @@ -0,0 +1,221 @@ +=begin +This template constructs an application with menus, toolbar and statusbar. +It uses an XML file(menuapp3ui.rc) to specify the menu layout; all menu +items have a corresponding action defined, but no menus are created +explicitly in code. This app has the same menu layout as menuapp2.py +=end + +=begin +Copyright 2003 Jim Bublitz + +Terms and Conditions + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KDE::IND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +Except as contained in this notice, the name of the copyright holder shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from the +copyright holder. +=end + + +require 'Korundum' + +class MainWin < KDE::MainWindow + STATUSBAR_LEFT = 1 + STATUSBAR_MIDDLE = 2 + STATUSBAR_RIGHT = 3 + + slots 'slotNew()', 'slotOpen()', 'slotSave()', 'slotSaveAs()', 'slotPrint()', 'slotQuit()', 'slotUndo()', + 'slotRedo()', 'slotCut()', 'slotCopy()', 'slotPaste()', 'slotFind()', 'slotFindNext()', 'slotReplace()', + 'slotSpecial()' + + def initialize(*args) + super + + # Create actions that correspond to those in the XML file + initActions() + + # Parse the default XML file (<appName>ui.rc> and create + # the menus and toolbar. This single line (and the XML + # file it reads) replace initMenus and initToolBar from + # menuapp2.rb. Otherwise, the menuapp2 and menuapp3 + # are identical 'createGUI' expects to find 'menuapp3ui.rc' + # either in the directory menuapp3.rb is run from, or + # in $KDEDIR/apps/menuapp3/ + createGUI() + + # Create the status bar + initStatusBar() + + # Disable a couple of menu items using their actions + @saveAction.setEnabled(false) + @saveAsAction.setEnabled(false) + end + + def initActions() + # Most of the functions selectable by menu are "standard" + # actions (open a file, cut, paste, etc) - you customize + # how they behave in your code, but menu, toolbar, and + # accelerator settings are the same across all programs. + # Standard actions also have tooltips already assigned + + # To create most of the actions below, KDE::StdAction is + # is used, since it takes care of everything with + # a single line of code. + + # The standard actions only need to specify the slot + # where the code for the action is located + + # Because the XMLGUI mechanism parses $KDEDIR/config/ui/ui_standards.rc + # before parsing and merging menuapp3ui.rc, it actually isn't + # necessary to list KDE::StdAction actions in menuapp3.rc. THE XMLGUI + # code will create menu/toolbar items and place them *automatically* + # if you defined the KDE::StdActions as below. In fact, you can't override + # this behavior using KDE::StdActions - if you want menus to be "non-standard" + # KDE menus (eg 'Cut' in the 'File' menu), you'll need to create your + # actions from KDE::Action instead of KDE::StdAction. Obviously it makes more + # sense to use the mechanism provided to produce consistent menus and + # toolbars. You can "unplug" items if, for example, you don't want them + # in the toolBar. + + # "File" menu items + @newAction = KDE::StdAction.openNew(self, SLOT("slotNew()"), actionCollection()) + @openAction = KDE::StdAction.open(self, SLOT("slotOpen()"), actionCollection()) + @saveAction = KDE::StdAction.save(self, SLOT("slotSave()"), actionCollection()) + @saveAsAction = KDE::StdAction.saveAs(self, SLOT("slotSaveAs()"), actionCollection()) + @printAction = KDE::StdAction.print(self, SLOT("slotPrint()"), actionCollection()) + @quitAction = KDE::StdAction.quit(self, SLOT("slotQuit()"), actionCollection()) + + + # "Edit" menu items + @undoAction = KDE::StdAction.undo(self, SLOT("slotUndo()"), actionCollection()) + @redoAction = KDE::StdAction.redo(self, SLOT("slotRedo()"), actionCollection()) + @cutAction = KDE::StdAction.cut(self, SLOT("slotCut()"), actionCollection()) + @copyAction = KDE::StdAction.copy(self, SLOT("slotCopy()"), actionCollection()) + @pasteAction = KDE::StdAction.paste(self, SLOT("slotPaste()"), actionCollection()) + @findAction = KDE::StdAction.find(self, SLOT("slotFind()"), actionCollection()) + @findNextAction = KDE::StdAction.findNext(self, SLOT("slotFindNext()"), actionCollection()) + @replaceAction = KDE::StdAction.replace(self, SLOT("slotReplace()"), actionCollection()) + + # For ANYTHING constructed from KDE::Action or its descendants (KDE::ActionMenu, KDE::ActionSeparator, + # KDE::FontAction, etc) you MUST provide the actionCollection () parent and an object + # name ("specialActionName") or the XMLGUI mechanism will not be able to locate the + # action. XMLGUI finds the action via its member name value, NOT via its variable name. + @specialAction = KDE::Action.new(i18n("Special"), KDE::Shortcut.new(0), self, SLOT('slotSpecial()'), actionCollection(), "specialActionName") + end + + def initStatusBar() + statusBar().insertItem("", STATUSBAR_LEFT, 1000, true) + statusBar().insertItem("", STATUSBAR_MIDDLE, 1000, true) + statusBar().insertItem("", STATUSBAR_RIGHT, 1000, true) + end + +#-------------------- slots ----------------------------------------------- + + + def slotNew(id = -1) + notImpl("New") + end + + def slotOpen(id = -1) + notImpl("Open") + end + + def slotSave(id = -1) + notImpl("Save") + end + + def slotSaveAs() + notImpl("Save As") + end + + def slotPrint() + notImpl("Print") + end + + def slotQuit() + notImpl("Quit") + end + + def slotUndo() + notImpl("Undo") + end + + def slotRedo() + notImpl("Redo") + end + + def slotCut(id = -1) + notImpl("Cut") + end + + def slotCopy(id = -1) + notImpl("Copy") + end + + def slotPaste(id = -1) + notImpl("Paste") + end + + def slotFind() + notImpl("Find") + end + + def slotFindNext() + notImpl("Find Next") + end + + def slotReplace() + notImpl("Replace") + end + + def notImpl(item = "Feature") + statusBar().changeItem("#{item} not implemented", STATUSBAR_LEFT) + KDE::MessageBox.error(self, "#{item} not implemented", "Not Implemented") + statusBar().changeItem("", STATUSBAR_LEFT) + end +end + + +#-------------------- main ------------------------------------------------ + +description = "A basic application template" +version = "1.0" + +# To use the XMLGUI mechanism, you MUST provide an appName +# (the first argument to KDE::AboutData below) - the XML spec +# for the interface will be in <appName>ui.rc (don't forget +# the "ui" suffix to the application name) +aboutData = KDE::AboutData.new("menuapp3", "", + version, description, KDE::AboutData::License_GPL, + "(C) 2003 whoever the author is") + +aboutData.addAuthor("author1", "whatever they did", "email@somedomain") +aboutData.addAuthor("author2", "they did something else", "another@email.address") + +KDE::CmdLineArgs.init(ARGV, aboutData) + +KDE::CmdLineArgs.addCmdLineOptions([["+files", "File to open", ""]]) + +app = KDE::Application.new() +mainWindow = MainWin.new(nil, "main window") +mainWindow.show +app.exec + diff --git a/korundum/rubylib/templates/annotated/menuapp3ui.rc b/korundum/rubylib/templates/annotated/menuapp3ui.rc new file mode 100644 index 00000000..60120e21 --- /dev/null +++ b/korundum/rubylib/templates/annotated/menuapp3ui.rc @@ -0,0 +1,24 @@ +<!DOCTYPE kpartgui> +<kpartgui name = "menuapp3"> +<MenuBar> + <Menu name="file"><text>&File</text> + <Action name ="newAction"/> + <Action name ="openAction"/> + <Action name ="saveAction"/> + <Action name ="saveAsAction"/> + <Action name ="printAction"/> + <Action name ="quitAction"/> + </Menu> + <Menu name = "edit"><text>&Edit</text> + <Action name ="undoAction"/> + <Action name ="redoAction"/> + <Action name ="cutAction"/> + <Action name ="copyAction"/> + <Action name ="pasteAction"/> + <Action name ="findAction"/> + <Action name ="findNextAction"/> + <Action name ="replaceAction"/> + <Action name ="specialActionName"/> + </Menu> +</MenuBar> +</kpartgui>
\ No newline at end of file diff --git a/korundum/rubylib/templates/annotated/minimal.rb b/korundum/rubylib/templates/annotated/minimal.rb new file mode 100644 index 00000000..3ac9e23e --- /dev/null +++ b/korundum/rubylib/templates/annotated/minimal.rb @@ -0,0 +1,80 @@ +=begin +This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale +=end + +=begin +This is a minimal PyKDE app template - it constructs an application +and a main window, but does nothing else. +=end + +=begin +Copyright 2003 Jim Bublitz + +Terms and Conditions + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KDE::IND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +Except as contained in this notice, the name of the copyright holder shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from the +copyright holder. +=end + +require 'Korundum' + + +=begin +Most Korundum applications will need a main window - the is the top +level widget (the parent for all other widgets). KDE::MainWindow has +more functionality than shown here (see more complex templates). +It has the ability to create the other major parts of the user +interface - the main view, menus, toolbars, etc. + +Usually you provide a subclass of KDE::MainWindow, construct menus +and toolbars in the subclass' initialize method, and provide +slots for menu/toolbar actions in separate methods. +=end +class MainWin < KDE::MainWindow + def initialize(*args) + super + end +end + + +#-------------------- main ------------------------------------------------ + +# instantiate KDE::Application - no other Qt::Object +# or Qt::Widget based classes can be instantiated +# until there is a KDE::Application instance +appName = "template" +about = KDE::AboutData.new(appName, "A minimal application", "0.1") +KDE::CmdLineArgs.init(ARGV, about) +app = KDE::Application.new() + +# instantiate the subclass of KMainWindow +mainWindow = MainWin.new(nil, "main window") + +# create the display +mainWindow.show + +# run KDE::Application's event loop until the +# program exits +app.exec + + diff --git a/korundum/rubylib/templates/annotated/systray1.rb b/korundum/rubylib/templates/annotated/systray1.rb new file mode 100644 index 00000000..daf4f8ff --- /dev/null +++ b/korundum/rubylib/templates/annotated/systray1.rb @@ -0,0 +1,94 @@ +=begin +This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale +=end + +=begin +A basic system tray application - you can combine this with code from +menuapp2.rb or menuapp3.rb to quickly build a full-blown application +framework. +=end + +=begin +Copyright 2003 Jim Bublitz + +Terms and Conditions + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KDE::IND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +Except as contained in this notice, the name of the copyright holder shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from the +copyright holder. +=end + +require 'Korundum' + +# This template uses KDE::MainWindow as the main window widget +# It solves the problem described in systray.rb by using +# a flag to control the return value from queryClose - if +# :quit" is signalled from anywhere EXCEPT the system tray +# icon's menu, @exitFlag == false, and as the return +# value for queryClose, it stops the application from shutting +# down; if @exitFlag is true, the application shuts down + +class MainWin < KDE::MainWindow + slots 'slotQuitSelected()' + + def initialize(*args) + super + + @exitFlag = false + + icons = KDE::IconLoader.new() + + # KDE::SystemTray hides or shows its parent when the system tray icon is clicked + systray = KDE::SystemTray.new(self) + systray.setPixmap(icons.loadIcon("stop", 0)) + connect(systray, SIGNAL("quitSelected()"), self, SLOT('slotQuitSelected()')) + systray.show() + end + + # Controls whether or not the application really exits + def queryClose() + hide() + return @exitFlag + end + + # Receives the signal emitted when the user selects Quit from the + # system tray icon's menu + def slotQuitSelected() + @exitFlag = true + $kapp.quit() + end +end + +#-------------------- main ------------------------------------------------ + +# The usual stuff.. +appName = "template" +about = KDE::AboutData.new(appName, "A system tray", "0.1") +KDE::CmdLineArgs.init(ARGV, about) +app = KDE::Application.new() + +mainWindow = MainWin.new(nil, "main window") + +mainWindow.show +app.exec + + diff --git a/korundum/rubylib/templates/basic/basicapp.rb b/korundum/rubylib/templates/basic/basicapp.rb new file mode 100644 index 00000000..5297c571 --- /dev/null +++ b/korundum/rubylib/templates/basic/basicapp.rb @@ -0,0 +1,61 @@ +=begin +This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale +=end + +=begin +Copyright 2003 Jim Bublitz + +Terms and Conditions + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KDE::IND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +Except as contained in this notice, the name of the copyright holder shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from the +copyright holder. +=end + +require 'Korundum' + +class MainWin < KDE::MainWindow + def initialize(*args) + super + end + +end +#-------------------- main ------------------------------------------------ + +description = "A basic application template" +version = "1.0" +aboutData = KDE::AboutData.new("", "", + version, description, KDE::AboutData::License_GPL, + "(C) 2003 whoever the author is") + +aboutData.addAuthor("author1", "whatever they did", "email@somedomain") +aboutData.addAuthor("author2", "they did something else", "another@email.address") + +KDE::CmdLineArgs.init(ARGV, aboutData) + +KDE::CmdLineArgs.addCmdLineOptions([["+files", "File to open", ""]]) + +app = KDE::Application.new() +mainWindow = MainWin.new(nil, "main window") +mainWindow.show +app.exec + diff --git a/korundum/rubylib/templates/basic/menuapp1.rb b/korundum/rubylib/templates/basic/menuapp1.rb new file mode 100644 index 00000000..3c8c9f51 --- /dev/null +++ b/korundum/rubylib/templates/basic/menuapp1.rb @@ -0,0 +1,213 @@ +=begin +This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale +=end + + +=begin +This template constructs an application with menus, toolbar and statusbar, +HOWEVER it is not recommended this template actually be used. It presents +the "KDE 1.0" method for constructing menus and toolbars - later versions +of KDE have introduced better(easier and more powerful) methods for +doing this job - see other menuapp*.rb templates for these methods +=end + +=begin +Copyright 2003 Jim Bublitz + +Terms and Conditions + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KDE::IND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +Except as contained in this notice, the name of the copyright holder shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from the +copyright holder. +=end + + +require 'Korundum' + +class MainWin < KDE::MainWindow + TOOLBAR_NEW = 1 + TOOLBAR_OPEN = 2 + TOOLBAR_SAVE = 3 + TOOLBAR_CUT = 4 + TOOLBAR_COPY = 5 + TOOLBAR_PASTE = 6 + + STATUSBAR_LEFT = 1 + STATUSBAR_MIDDLE = 2 + STATUSBAR_RIGHT = 3 + + slots 'slotNew()', 'slotOpen()', 'slotSave()', 'slotSaveAs()', 'slotPrint()', 'slotQuit()', 'slotUndo()', + 'slotRedo()', 'slotCut()', 'slotCopy()', 'slotPaste()', 'slotFind()', 'slotFindNext()', 'slotReplace()', + 'slotSpecial()' + + def initialize(*args) + super + + initMenus() + initToolBar() + initStatusBar() + end + + def initMenus() + fileMenu = Qt::PopupMenu.new(self) + + # "File" menu items + fileMenu.insertItem(i18n("New"), self, SLOT('slotNew()'), Qt::KeySequence.new(KDE::StdAccel.openNew().keyCodeQt())) + fileMenu.insertItem(i18n("Open"), self, SLOT('slotOpen()'), Qt::KeySequence.new(KDE::StdAccel.open().keyCodeQt())) + fileMenu.insertSeparator() + fileMenu.insertItem(i18n("Save"), self, SLOT('slotSave()'), Qt::KeySequence.new(KDE::StdAccel.save().keyCodeQt())) + fileMenu.insertItem(i18n("SaveAs"), self, SLOT('slotSaveAs()')) + fileMenu.insertSeparator() + fileMenu.insertItem(i18n("Print"), self, SLOT('slotPrint()'), Qt::KeySequence.new(KDE::StdAccel.print().keyCodeQt())) + fileMenu.insertSeparator() + fileMenu.insertItem(i18n("&Quit"), self, SLOT('slotQuit()'), Qt::KeySequence.new(KDE::StdAccel.quit().keyCodeQt())) + + menuBar().insertItem(i18n("&File"), fileMenu) + + editMenu = Qt::PopupMenu.new(self) + + # "Edit" menu items + editMenu.insertItem(i18n("Undo"), self, SLOT('slotUndo()'), Qt::KeySequence.new(KDE::StdAccel.undo().keyCodeQt())) + editMenu.insertItem(i18n("Redo"), self, SLOT('slotRedo()'), Qt::KeySequence.new(KDE::StdAccel.redo().keyCodeQt())) + editMenu.insertSeparator() + editMenu.insertItem(i18n("Cut"), self, SLOT('slotCut()'), Qt::KeySequence.new(KDE::StdAccel.cut().keyCodeQt())) + editMenu.insertItem(i18n("Copy"), self, SLOT('slotCopy()'), Qt::KeySequence.new(KDE::StdAccel.copy().keyCodeQt())) + editMenu.insertItem(i18n("Paste"), self, SLOT('slotPaste()'), Qt::KeySequence.new(KDE::StdAccel.paste().keyCodeQt())) + editMenu.insertSeparator() + editMenu.insertItem(i18n("Find"), self, SLOT('slotFind()'), Qt::KeySequence.new(KDE::StdAccel.find().keyCodeQt())) + editMenu.insertItem(i18n("Find Next"), self, SLOT('slotFindNext()'), Qt::KeySequence.new(KDE::StdAccel.findNext().keyCodeQt())) + editMenu.insertItem(i18n("Replace"), self, SLOT('slotReplace()'), Qt::KeySequence.new(KDE::StdAccel.replace().keyCodeQt())) + + menuBar().insertItem(i18n("&Edit"), editMenu) + + helpMenu = helpMenu("") + menuBar().insertItem(i18n("&Help"), helpMenu) + end + + def initToolBar() + icons = KDE::IconLoader.new() + + toolBar().insertButton(icons.loadIcon("filenew", KDE::Icon::Toolbar), TOOLBAR_NEW, SIGNAL("clicked(int)"), + self, SLOT('slotNew()'), true, "New") + toolBar().insertButton(icons.loadIcon("fileopen", KDE::Icon::Toolbar), TOOLBAR_OPEN, SIGNAL("clicked(int)"), + self, SLOT('slotOpen()'), true, "Open") + toolBar().insertButton(icons.loadIcon("filesave", KDE::Icon::Toolbar), TOOLBAR_SAVE, SIGNAL("clicked(int)"), + self, SLOT('slotSave()'), true, "Save") + toolBar().insertButton(icons.loadIcon("editcut", KDE::Icon::Toolbar), TOOLBAR_CUT, SIGNAL("clicked(int)"), + self, SLOT('slotCut()'), true, "Cut") + toolBar().insertButton(icons.loadIcon("editcopy", KDE::Icon::Toolbar), TOOLBAR_COPY, SIGNAL("clicked(int)"), + self, SLOT('slotCopy()'), true, "Copy") + toolBar().insertButton(icons.loadIcon("editpaste", KDE::Icon::Toolbar), TOOLBAR_PASTE, SIGNAL("clicked(int)"), + self, SLOT('slotPaste()'), true, "Paste") + end + + def initStatusBar() + statusBar().insertItem("", STATUSBAR_LEFT, 1000, true) + statusBar().insertItem("", STATUSBAR_MIDDLE, 1000, true) + statusBar().insertItem("", STATUSBAR_RIGHT, 1000, true) + end + + +#-------------------- slots ----------------------------------------------- + + def slotNew(id = -1) + notImpl("New") + end + + def slotOpen(id = -1) + notImpl("Open") + end + + def slotSave(id = -1) + notImpl("Save") + end + + def slotSaveAs() + notImpl("Save As") + end + + def slotPrint() + notImpl("Print") + end + + def slotQuit() + notImpl("Qt::uit") + end + + def slotUndo() + notImpl("Undo") + end + + def slotRedo() + notImpl("Redo") + end + + def slotCut(id = -1) + notImpl("Cut") + end + + def slotCopy(id = -1) + notImpl("Copy") + end + + def slotPaste(id = -1) + notImpl("Paste") + end + + def slotFind() + notImpl("Find") + end + + def slotFindNext() + notImpl("Find Next") + end + + def slotReplace() + notImpl("Replace") + end + + def notImpl(item = "Feature") + statusBar().changeItem("#{item} not implemented", STATUSBAR_LEFT) + KDE::MessageBox.error(self, "#{item} not implemented", "Not Implemented") + statusBar().changeItem("", STATUSBAR_LEFT) + end +end + +#-------------------- main ------------------------------------------------ + +description = "A basic application template" +version = "1.0" +aboutData = KDE::AboutData.new("", "", + version, description, KDE::AboutData::License_GPL, + "(C) 2003 whoever the author is") + +aboutData.addAuthor("author1", "whatever they did", "email@somedomain") +aboutData.addAuthor("author2", "they did something else", "another@email.address") + +KDE::CmdLineArgs.init(ARGV, aboutData) + +KDE::CmdLineArgs.addCmdLineOptions([["+files", "File to open", ""]]) + +app = KDE::Application.new() +mainWindow = MainWin.new(nil, "main window") +mainWindow.show +app.exec diff --git a/korundum/rubylib/templates/basic/menuapp2.rb b/korundum/rubylib/templates/basic/menuapp2.rb new file mode 100644 index 00000000..63430fd0 --- /dev/null +++ b/korundum/rubylib/templates/basic/menuapp2.rb @@ -0,0 +1,216 @@ + +=begin +This template constructs an application with menus, toolbar and statusbar. +It uses KDE classes and methods that simplify the task of building and +operating a GUI. It is recommended that this approach be used, rather +than the primitive approach in menuapp1.py +=end + +=begin +Copyright 2003 Jim Bublitz + +Terms and Conditions + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KDE::IND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +Except as contained in this notice, the name of the copyright holder shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from the +copyright holder. +=end + + +require 'Korundum' + + + +class MainWin < KDE::MainWindow + STATUSBAR_LEFT = 1 + STATUSBAR_MIDDLE = 2 + STATUSBAR_RIGHT = 3 + + slots 'slotNew()', 'slotOpen()', 'slotSave()', 'slotSaveAs()', 'slotPrint()', 'slotQuit()', 'slotUndo()', + 'slotRedo()', 'slotCut()', 'slotCopy()', 'slotPaste()', 'slotFind()', 'slotFindNext()', 'slotReplace()', + 'slotSpecial()' + + def initialize(*args) + super + + initActions() + initMenus() + initToolBar() + initStatusBar() + + @saveAction.setEnabled(false) + @saveAsAction.setEnabled(false) + end + + def initActions() + # "File" menu items + @newAction = KDE::StdAction.openNew(self, SLOT("slotNew()"), actionCollection()) + @openAction = KDE::StdAction.open(self, SLOT("slotOpen()"), actionCollection()) + @saveAction = KDE::StdAction.save(self, SLOT("slotSave()"), actionCollection()) + @saveAsAction = KDE::StdAction.saveAs(self, SLOT("slotSaveAs()"), actionCollection()) + @printAction = KDE::StdAction.print(self, SLOT("slotPrint()"), actionCollection()) + @quitAction = KDE::StdAction.quit(self, SLOT("slotQuit()"), actionCollection()) + + # "Edit" menu items + @undoAction = KDE::StdAction.undo(self, SLOT("slotUndo()"), actionCollection()) + @redoAction = KDE::StdAction.redo(self, SLOT("slotRedo()"), actionCollection()) + @cutAction = KDE::StdAction.cut(self, SLOT("slotCut()"), actionCollection()) + @copyAction = KDE::StdAction.copy(self, SLOT("slotCopy()"), actionCollection()) + @pasteAction = KDE::StdAction.paste(self, SLOT("slotPaste()"), actionCollection()) + @findAction = KDE::StdAction.find(self, SLOT("slotFind()"), actionCollection()) + @findNextAction = KDE::StdAction.findNext(self, SLOT("slotFindNext()"), actionCollection()) + @replaceAction = KDE::StdAction.replace(self, SLOT("slotReplace()"), actionCollection()) + @specialAction = KDE::Action.new(i18n("Special"), KDE::Shortcut.new(0), self, SLOT('slotSpecial()'), actionCollection(), "specialActionName") + end + + def initMenus() + fileMenu = Qt::PopupMenu.new(self) + @newAction.plug(fileMenu) + @openAction.plug(fileMenu) + fileMenu.insertSeparator() + @saveAction.plug(fileMenu) + @saveAsAction.plug(fileMenu) + fileMenu.insertSeparator() + @printAction.plug(fileMenu) + fileMenu.insertSeparator() + @quitAction.plug(fileMenu) + menuBar().insertItem(i18n("&File"), fileMenu) + + editMenu = Qt::PopupMenu.new(self) + @undoAction.plug(editMenu) + @redoAction.plug(editMenu) + editMenu.insertSeparator() + @cutAction.plug(editMenu) + @copyAction.plug(editMenu) + @pasteAction.plug(editMenu) + editMenu.insertSeparator() + @findAction.plug(editMenu) + @findNextAction.plug(editMenu) + @replaceAction.plug(editMenu) + editMenu.insertSeparator() + @specialAction.plug(editMenu) + menuBar().insertItem(i18n("&Edit"), editMenu) + + helpMenu = helpMenu("") + menuBar().insertItem(i18n("&Help"), helpMenu) + end + + def initToolBar() + @newAction.plug(toolBar()) + @openAction.plug(toolBar()) + @saveAction.plug(toolBar()) + @cutAction.plug(toolBar()) + @copyAction.plug(toolBar()) + @pasteAction.plug(toolBar()) + end + + def initStatusBar() + statusBar().insertItem("", STATUSBAR_LEFT, 1000, true) + statusBar().insertItem("", STATUSBAR_MIDDLE, 1000, true) + statusBar().insertItem("", STATUSBAR_RIGHT, 1000, true) + end + +#-------------------- slots ----------------------------------------------- + + def slotNew(id = -1) + notImpl("New") + end + + def slotOpen(id = -1) + notImpl("Open") + end + + def slotSave(id = -1) + notImpl("Save") + end + + def slotSaveAs() + notImpl("Save As") + end + + def slotPrint() + notImpl("Print") + end + + def slotQuit() + notImpl("Quit") + end + + def slotUndo() + notImpl("Undo") + end + + def slotRedo() + notImpl("Redo") + end + + def slotCut(id = -1) + notImpl("Cut") + end + + def slotCopy(id = -1) + notImpl("Copy") + end + + def slotPaste(id = -1) + notImpl("Paste") + end + + def slotFind() + notImpl("Find") + end + + def slotFindNext() + notImpl("Find Next") + end + + def slotReplace() + notImpl("Replace") + end + + def notImpl(item = "Feature") + statusBar().changeItem("#{item} not implemented", STATUSBAR_LEFT) + KDE::MessageBox.error(self, "#{item} not implemented", "Not Implemented") + statusBar().changeItem("", STATUSBAR_LEFT) + end +end + + +#-------------------- main ------------------------------------------------ + +description = "A basic application template" +version = "1.0" +aboutData = KDE::AboutData.new("", "", + version, description, KDE::AboutData::License_GPL, + "(C) 2003 whoever the author is") + +aboutData.addAuthor("author1", "whatever they did", "email@somedomain") +aboutData.addAuthor("author2", "they did something else", "another@email.address") + +KDE::CmdLineArgs.init(ARGV, aboutData) + +KDE::CmdLineArgs.addCmdLineOptions([["+files", "File to open", ""]]) + +app = KDE::Application.new() +mainWindow = MainWin.new(nil, "main window") +mainWindow.show +app.exec diff --git a/korundum/rubylib/templates/basic/menuapp3.rb b/korundum/rubylib/templates/basic/menuapp3.rb new file mode 100644 index 00000000..7751e847 --- /dev/null +++ b/korundum/rubylib/templates/basic/menuapp3.rb @@ -0,0 +1,174 @@ +=begin +This template constructs an application with menus, toolbar and statusbar. +It uses an XML file(menuapp3ui.rc) to specify the menu layout; all menu +items have a corresponding action defined, but no menus are created +explicitly in code. This app has the same menu layout as menuapp2.py +=end + +=begin +Copyright 2003 Jim Bublitz + +Terms and Conditions + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KDE::IND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +Except as contained in this notice, the name of the copyright holder shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from the +copyright holder. +=end + + +require 'Korundum' + +class MainWin < KDE::MainWindow + STATUSBAR_LEFT = 1 + STATUSBAR_MIDDLE = 2 + STATUSBAR_RIGHT = 3 + + slots 'slotNew()', 'slotOpen()', 'slotSave()', 'slotSaveAs()', 'slotPrint()', 'slotQuit()', 'slotUndo()', + 'slotRedo()', 'slotCut()', 'slotCopy()', 'slotPaste()', 'slotFind()', 'slotFindNext()', 'slotReplace()', + 'slotSpecial()' + + def initialize(*args) + super + + initActions() + createGUI() + initStatusBar() + + @saveAction.setEnabled(false) + @saveAsAction.setEnabled(false) + end + + def initActions() + # "File" menu items + @newAction = KDE::StdAction.openNew(self, SLOT("slotNew()"), actionCollection()) + @openAction = KDE::StdAction.open(self, SLOT("slotOpen()"), actionCollection()) + @saveAction = KDE::StdAction.save(self, SLOT("slotSave()"), actionCollection()) + @saveAsAction = KDE::StdAction.saveAs(self, SLOT("slotSaveAs()"), actionCollection()) + @printAction = KDE::StdAction.print(self, SLOT("slotPrint()"), actionCollection()) + @quitAction = KDE::StdAction.quit(self, SLOT("slotQuit()"), actionCollection()) + + + # "Edit" menu items + @undoAction = KDE::StdAction.undo(self, SLOT("slotUndo()"), actionCollection()) + @redoAction = KDE::StdAction.redo(self, SLOT("slotRedo()"), actionCollection()) + @cutAction = KDE::StdAction.cut(self, SLOT("slotCut()"), actionCollection()) + @copyAction = KDE::StdAction.copy(self, SLOT("slotCopy()"), actionCollection()) + @pasteAction = KDE::StdAction.paste(self, SLOT("slotPaste()"), actionCollection()) + @findAction = KDE::StdAction.find(self, SLOT("slotFind()"), actionCollection()) + @findNextAction = KDE::StdAction.findNext(self, SLOT("slotFindNext()"), actionCollection()) + @replaceAction = KDE::StdAction.replace(self, SLOT("slotReplace()"), actionCollection()) + @specialAction = KDE::Action.new(i18n("Special"), KDE::Shortcut.new(0), self, SLOT('slotSpecial()'), actionCollection(), "specialActionName") + end + + def initStatusBar() + statusBar().insertItem("", STATUSBAR_LEFT, 1000, true) + statusBar().insertItem("", STATUSBAR_MIDDLE, 1000, true) + statusBar().insertItem("", STATUSBAR_RIGHT, 1000, true) + end + +#-------------------- slots ----------------------------------------------- + + + def slotNew(id = -1) + notImpl("New") + end + + def slotOpen(id = -1) + notImpl("Open") + end + + def slotSave(id = -1) + notImpl("Save") + end + + def slotSaveAs() + notImpl("Save As") + end + + def slotPrint() + notImpl("Print") + end + + def slotQuit() + notImpl("Quit") + end + + def slotUndo() + notImpl("Undo") + end + + def slotRedo() + notImpl("Redo") + end + + def slotCut(id = -1) + notImpl("Cut") + end + + def slotCopy(id = -1) + notImpl("Copy") + end + + def slotPaste(id = -1) + notImpl("Paste") + end + + def slotFind() + notImpl("Find") + end + + def slotFindNext() + notImpl("Find Next") + end + + def slotReplace() + notImpl("Replace") + end + + def notImpl(item = "Feature") + statusBar().changeItem("#{item} not implemented", STATUSBAR_LEFT) + KDE::MessageBox.error(self, "#{item} not implemented", "Not Implemented") + statusBar().changeItem("", STATUSBAR_LEFT) + end +end + + +#-------------------- main ------------------------------------------------ + +description = "A basic application template" +version = "1.0" +aboutData = KDE::AboutData.new("menuapp3", "", + version, description, KDE::AboutData::License_GPL, + "(C) 2003 whoever the author is") + +aboutData.addAuthor("author1", "whatever they did", "email@somedomain") +aboutData.addAuthor("author2", "they did something else", "another@email.address") + +KDE::CmdLineArgs.init(ARGV, aboutData) + +KDE::CmdLineArgs.addCmdLineOptions([["+files", "File to open", ""]]) + +app = KDE::Application.new() +mainWindow = MainWin.new(nil, "main window") +mainWindow.show +app.exec + diff --git a/korundum/rubylib/templates/basic/menuapp3ui.rc b/korundum/rubylib/templates/basic/menuapp3ui.rc new file mode 100644 index 00000000..60120e21 --- /dev/null +++ b/korundum/rubylib/templates/basic/menuapp3ui.rc @@ -0,0 +1,24 @@ +<!DOCTYPE kpartgui> +<kpartgui name = "menuapp3"> +<MenuBar> + <Menu name="file"><text>&File</text> + <Action name ="newAction"/> + <Action name ="openAction"/> + <Action name ="saveAction"/> + <Action name ="saveAsAction"/> + <Action name ="printAction"/> + <Action name ="quitAction"/> + </Menu> + <Menu name = "edit"><text>&Edit</text> + <Action name ="undoAction"/> + <Action name ="redoAction"/> + <Action name ="cutAction"/> + <Action name ="copyAction"/> + <Action name ="pasteAction"/> + <Action name ="findAction"/> + <Action name ="findNextAction"/> + <Action name ="replaceAction"/> + <Action name ="specialActionName"/> + </Menu> +</MenuBar> +</kpartgui>
\ No newline at end of file diff --git a/korundum/rubylib/templates/basic/minimal.rb b/korundum/rubylib/templates/basic/minimal.rb new file mode 100644 index 00000000..555875a2 --- /dev/null +++ b/korundum/rubylib/templates/basic/minimal.rb @@ -0,0 +1,56 @@ +=begin +This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale +=end + +=begin +Copyright 2003 Jim Bublitz + +Terms and Conditions + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KDE::IND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +Except as contained in this notice, the name of the copyright holder shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from the +copyright holder. +=end + +require 'Korundum' + + + +class MainWin < KDE::MainWindow + def initialize(*args) + super + end +end + + +#-------------------- main ------------------------------------------------ + +appName = "template" +about = KDE::AboutData.new(appName, "A minimal application", "0.1") +KDE::CmdLineArgs.init(ARGV, about) +app = KDE::Application.new() + +mainWindow = MainWin.new(nil, "main window") +mainWindow.show +app.exec + + diff --git a/korundum/rubylib/templates/basic/systray1.rb b/korundum/rubylib/templates/basic/systray1.rb new file mode 100644 index 00000000..34f26f04 --- /dev/null +++ b/korundum/rubylib/templates/basic/systray1.rb @@ -0,0 +1,75 @@ +=begin +This is a ruby version of Jim Bublitz's pykde program, translated by Richard Dale +=end + +=begin +Copyright 2003 Jim Bublitz + +Terms and Conditions + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KDE::IND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +Except as contained in this notice, the name of the copyright holder shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from the +copyright holder. +=end + +require 'Korundum' + +class MainWin < KDE::MainWindow + slots 'slotQuitSelected()' + + def initialize(*args) + super + + @exitFlag = false + + icons = KDE::IconLoader.new() + + systray = KDE::SystemTray.new(self) + systray.setPixmap(icons.loadIcon("stop", 0)) + connect(systray, SIGNAL("quitSelected()"), self, SLOT('slotQuitSelected()')) + systray.show() + end + + def queryClose() + hide() + return @exitFlag + end + + def slotQuitSelected() + @exitFlag = true + $kapp.quit() + end +end + +#-------------------- main ------------------------------------------------ + +appName = "template" +about = KDE::AboutData.new(appName, "A system tray", "0.1") +KDE::CmdLineArgs.init(ARGV, about) +app = KDE::Application.new() + +mainWindow = MainWin.new(nil, "main window") + +mainWindow.show +app.exec + + diff --git a/korundum/rubylib/tutorials/p1/p1.rb b/korundum/rubylib/tutorials/p1/p1.rb new file mode 100644 index 00000000..87e5e1b9 --- /dev/null +++ b/korundum/rubylib/tutorials/p1/p1.rb @@ -0,0 +1,13 @@ +require 'Qt'
+
+ a = Qt::Application.new( ARGV )
+
+ hello = Qt::PushButton.new( "Hello world!", nil )
+ hello.resize( 100, 30 )
+
+ Qt::Object::connect( hello, SIGNAL('clicked()'), a, SLOT('quit()') )
+
+ a.setMainWidget( hello )
+ hello.show()
+
+ a.exec()
\ No newline at end of file diff --git a/korundum/rubylib/tutorials/p2/p2.rb b/korundum/rubylib/tutorials/p2/p2.rb new file mode 100644 index 00000000..b2c6d03c --- /dev/null +++ b/korundum/rubylib/tutorials/p2/p2.rb @@ -0,0 +1,12 @@ +require 'Korundum'
+
+ about = KDE::AboutData.new("p2", "Hello World", "0.1")
+ KDE::CmdLineArgs.init(ARGV, about)
+ a = KDE::Application.new()
+ hello = Qt::PushButton.new( a.i18n("Hello World !"), nil )
+ hello.autoResize = true
+
+ a.mainWidget = hello
+ hello.show
+
+ a.exec
\ No newline at end of file diff --git a/korundum/rubylib/tutorials/p3/p3.rb b/korundum/rubylib/tutorials/p3/p3.rb new file mode 100644 index 00000000..fc575878 --- /dev/null +++ b/korundum/rubylib/tutorials/p3/p3.rb @@ -0,0 +1,61 @@ +require 'Korundum'
+
+class MainWindow < KDE::MainWindow
+ slots 'fileOpen()', 'fileSave()'
+
+ def initialize( name )
+ super(nil, name)
+ setCaption("KDE Tutorial - p3")
+
+ filemenu = Qt::PopupMenu.new
+ filemenu.insertItem( i18n( "&Open" ), self, SLOT('fileOpen()') )
+ filemenu.insertItem( i18n( "&Save" ), self, SLOT('fileSave()') )
+ filemenu.insertItem( i18n( "&Quit" ), $kapp, SLOT('quit()') )
+
+ about =
+ i18n("p3 1.0\n\n" +
+ "(C) 1999-2002 Antonio Larrosa Jimenez\n" +
+ "larrosa@kde.org\t\tantlarr@supercable.es\n" +
+ "Malaga (Spain)\n\n" +
+ "Simple KDE Tutorial\n" +
+ "This tutorial comes with ABSOLUTELY NO WARRANTY\n" +
+ "This is free software, and you are welcome to redistribute it\n" +
+ "under certain conditions\n")
+ helpmenu = helpMenu( about )
+
+ menu = menuBar()
+ menu.insertItem( i18n( "&File" ), filemenu )
+ menu.insertSeparator()
+ menu.insertItem( i18n( "&Help" ), helpmenu )
+
+ hello = Qt::TextEdit.new(
+ i18n("<H2>Hello World !</H2><BR>This is a simple" +
+ " window with <I><font size=5><B>R<font color=red" +
+ " size=5>ich </font><font color=blue size=5>Text" +
+ "</font></B></I> capabilities<BR>Try to resize" +
+ " this window, all this is automatic !"), "", self )
+ setCentralWidget(hello)
+ end
+
+ def fileOpen()
+ filename = KDE::FileDialog.getOpenURL( nil, "*", self )
+ msg = i18n("Now this app should open the url #{filename.url()}")
+ KDE::MessageBox.information( nil, msg, i18n( "Information" ),
+ "fileOpenInformationDialog" )
+ end
+
+ def fileSave()
+ filename = KDE::FileDialog.getSaveURL( nil, "*", self )
+ end
+end
+
+ about = KDE::AboutData.new("p3", "Tutorial - p3", "0.1")
+ KDE::CmdLineArgs.init(ARGV, about)
+ a = KDE::Application.new()
+ window = MainWindow.new( "Tutorial - p3" )
+ window.resize( 400, 300 )
+
+ a.mainWidget = window
+ window.show
+
+ a.exec
diff --git a/korundum/rubylib/tutorials/p4/p4.rb b/korundum/rubylib/tutorials/p4/p4.rb new file mode 100644 index 00000000..63777872 --- /dev/null +++ b/korundum/rubylib/tutorials/p4/p4.rb @@ -0,0 +1,67 @@ +require 'Korundum'
+
+class MainWindow < KDE::MainWindow
+ slots 'changeLocation()',
+ 'openURLRequest(const KURL &, const KParts::URLArgs & )'
+
+ def initialize( name )
+ super(nil, name)
+ setCaption("KDE Tutorial - p4")
+
+ filemenu = Qt::PopupMenu.new
+ filemenu.insertItem( i18n( "&Quit" ), $kapp, SLOT( 'quit()' ) )
+ about =
+ i18n("p4 1.0\n\n" +
+ "(C) 1999-2002 Antonio Larrosa Jimenez\n" +
+ "larrosa@kde.org\t\tantlarr@supercable.es\n" +
+ "Malaga (Spain)\n\n" +
+ "Simple KDE Tutorial\n" +
+ "This tutorial comes with ABSOLUTELY NO WARRANTY \n" +
+ "This is free software, and you are welcome to redistribute it\n" +
+ "under certain conditions\n");
+
+ helpmenu = helpMenu(about)
+ menu = menuBar()
+ menu.insertItem( i18n( "&File" ), filemenu)
+ menu.insertSeparator()
+ menu.insertItem(i18n("&Help"), helpmenu)
+
+ vbox = Qt::VBox.new( self )
+
+ @location = Qt::LineEdit.new( vbox )
+ @location.setText( "http://localhost" )
+
+ @browser = KDE::HTMLPart.new( vbox )
+ @browser.openURL( KDE::URL.new(@location.text()) )
+
+ connect( @location , SIGNAL( 'returnPressed()' ),
+ self, SLOT( 'changeLocation()' ) )
+
+ connect( @browser.browserExtension(),
+ SIGNAL( 'openURLRequest( const KURL &, const KParts::URLArgs & )' ),
+ self, SLOT( 'openURLRequest(const KURL &, const KParts::URLArgs & )' ) )
+
+ setCentralWidget(vbox)
+ end
+
+ def changeLocation()
+ @browser.openURL( KDE::URL.new(@location.text()) )
+ end
+
+ def openURLRequest(url, part)
+ @location.text = url.url()
+ changeLocation()
+ end
+end
+
+ about = KDE::AboutData.new("p4", "Tutorial - p4", "0.1")
+ KDE::CmdLineArgs.init(ARGV, about)
+ a = KDE::Application.new()
+
+ window = MainWindow.new( "Tutorial - p4" )
+ window.resize( 300, 200 )
+
+ a.mainWidget = window
+ window.show
+
+ a.exec
\ No newline at end of file diff --git a/korundum/rubylib/tutorials/p5/p5.rb b/korundum/rubylib/tutorials/p5/p5.rb new file mode 100644 index 00000000..8e16c2c8 --- /dev/null +++ b/korundum/rubylib/tutorials/p5/p5.rb @@ -0,0 +1,82 @@ +require 'Korundum'
+
+class MainWindow < KDE::MainWindow
+ slots 'changeLocation()',
+ 'openURLRequest(const KURL &, const KParts::URLArgs & )',
+ 'bookLocation()'
+
+ def initialize( name )
+ super(nil, name)
+ setCaption("KDE Tutorial - p5")
+
+ filemenu = Qt::PopupMenu.new
+ filemenu.insertItem( i18n( "&Quit" ), $kapp, SLOT( 'quit()' ) )
+ about =
+ i18n("p5 1.0\n\n" +
+ "(C) 1999-2002 Antonio Larrosa Jimenez\n" +
+ "larrosa@kde.org\t\tantlarr@supercable.es\n" +
+ "Malaga (Spain)\n\n" +
+ "Simple KDE Tutorial\n" +
+ "This tutorial comes with ABSOLUTELY NO WARRANTY \n" +
+ "This is free software, and you are welcome to redistribute it\n" +
+ "under certain conditions\n");
+
+ helpmenu = helpMenu(about)
+ menu = menuBar()
+ menu.insertItem( i18n( "&File" ), filemenu)
+ menu.insertSeparator()
+ menu.insertItem(i18n("&Help"), helpmenu)
+
+ vbox = Qt::VBox.new( self )
+
+ @location = Qt::LineEdit.new( vbox )
+ @location.setText( "http://localhost" )
+
+ connect( @location , SIGNAL( 'returnPressed()' ),
+ self, SLOT( 'changeLocation()' ) )
+
+ split = Qt::Splitter.new( vbox )
+ split.setOpaqueResize()
+
+ bookmark = Qt::PushButton.new( i18n("Add to Bookmarks"), split );
+
+ connect( bookmark, SIGNAL( 'clicked()' ), self, SLOT( 'bookLocation()' ) )
+
+ @browser = KDE::HTMLPart.new( split )
+ @browser.openURL( KDE::URL.new(@location.text()) )
+
+ connect( @browser.browserExtension(),
+ SIGNAL( 'openURLRequest( const KURL &, const KParts::URLArgs & )' ),
+ self, SLOT( 'openURLRequest(const KURL &, const KParts::URLArgs & )' ) )
+ setCentralWidget(vbox)
+ end
+
+
+ def changeLocation()
+ @browser.openURL( KDE::URL.new(@location.text()) )
+ end
+
+ def openURLRequest(url, part)
+ @location.text = url.url()
+ changeLocation()
+ end
+
+ def bookLocation()
+ dcopRef = KDE::DCOPRef.new("p6", "BookMarkList")
+ if ! dcopRef.add(@location.text())
+ qWarning("Error with DCOP\n")
+ end
+ end
+end
+
+ about = KDE::AboutData.new("p5", "Tutorial - p5", "0.1")
+ KDE::CmdLineArgs.init(ARGV, about)
+ a = KDE::Application.new()
+
+ window = MainWindow.new( "Tutorial - p5" )
+ window.resize( 300, 200 )
+
+ a.mainWidget = window
+ window.show
+
+ a.exec
diff --git a/korundum/rubylib/tutorials/p6/addurl.sh b/korundum/rubylib/tutorials/p6/addurl.sh new file mode 100644 index 00000000..6163dad4 --- /dev/null +++ b/korundum/rubylib/tutorials/p6/addurl.sh @@ -0,0 +1,3 @@ +#!/usr/bin/bash + +dcop p6 BookMarkList add "http://www.kde.org" diff --git a/korundum/rubylib/tutorials/p6/p6.rb b/korundum/rubylib/tutorials/p6/p6.rb new file mode 100644 index 00000000..ea7b2b1e --- /dev/null +++ b/korundum/rubylib/tutorials/p6/p6.rb @@ -0,0 +1,26 @@ +require 'Korundum'
+
+class BookMarkList < KDE::ListView
+ k_dcop 'void add( QString )'
+
+ def initialize()
+ super(nil, "Bookmarks")
+ addColumn( i18n("My Bookmarks") );
+ end
+
+ def add( s )
+ insertItem( KDE::ListViewItem.new( self , s ) )
+ end
+end
+
+ about = KDE::AboutData.new("p6", "Tutorial - p6", "0.1")
+ KDE::CmdLineArgs.init(ARGV, about)
+ a = KDE::UniqueApplication.new()
+
+ mylist = BookMarkList.new
+ mylist.resize( 300, 200 )
+
+ a.mainWidget = mylist
+ mylist.show
+
+ a.exec
\ No newline at end of file diff --git a/korundum/rubylib/tutorials/p7/p7.rb b/korundum/rubylib/tutorials/p7/p7.rb new file mode 100644 index 00000000..650f4db5 --- /dev/null +++ b/korundum/rubylib/tutorials/p7/p7.rb @@ -0,0 +1,127 @@ +require 'Korundum'
+
+class Browser < KDE::MainWindow
+ k_dcop 'void setURL(QString)'
+
+ slots 'fileSetDefaultPage()',
+ 'changeLocation()',
+ 'bookLocation()',
+ 'gotoPreviousPage()',
+ 'openURLRequest(const KURL&, const KParts::URLArgs&)'
+
+ TOOLBAR_ID_ADDBOOKMARK = 1
+ TOOLBAR_ID_BACK = 2
+ TOOLBAR_ID_QUIT = 3
+
+ def initialize( name )
+ super(nil, name)
+ setCaption("KDE Tutorial - p7")
+ @history = []
+
+ filemenu = Qt::PopupMenu.new
+ filemenu.insertItem( i18n( "&Set default page" ),
+ self, SLOT( 'fileSetDefaultPage()' ) )
+ filemenu.insertItem(i18n( "&Quit" ), $kapp, SLOT( 'quit()' ))
+ about =
+ i18n("p7 1.0\n\n" +
+ "(C) 1999-2002 Antonio Larrosa Jimenez\n" +
+ "larrosa@kde.org\t\tantlarr@supercable.es\n" +
+ "Malaga (Spain)\n\n" +
+ "Simple KDE Tutorial\n" +
+ "This tutorial comes with ABSOLUTELY NO WARRANTY \n" +
+ "This is free software, and you are welcome to redistribute it\n" +
+ "under certain conditions\n");
+
+ helpmenu = helpMenu(about)
+ menu = menuBar()
+ menu.insertItem( i18n( "&File" ), filemenu)
+ menu.insertSeparator()
+ menu.insertItem(i18n("&Help"), helpmenu)
+
+ toolbar = KDE::ToolBar.new(self)
+
+ icons = KDE::IconLoader.new()
+ toolbar.insertButton(icons.loadIcon("reload", KDE::Icon::Toolbar), TOOLBAR_ID_ADDBOOKMARK,
+ SIGNAL('clicked(int)'),self,SLOT('bookLocation()'),true,
+ i18n("Add to Bookmarks"))
+ toolbar.insertButton(icons.loadIcon("back", KDE::Icon::Toolbar), TOOLBAR_ID_BACK,
+ SIGNAL('clicked(int)'),self,SLOT('gotoPreviousPage()'),
+ false, i18n("Back to previous page"))
+ toolbar.insertButton(icons.loadIcon("exit", KDE::Icon::Toolbar), TOOLBAR_ID_QUIT,
+ SIGNAL('clicked(int)'),$kapp,SLOT('quit()'),true,
+ i18n("Quit the application"))
+ addToolBar(toolbar)
+
+ vbox = Qt::VBox.new( self )
+
+ @location = Qt::LineEdit.new( vbox )
+
+ config = $kapp.config()
+ config.setGroup("Settings")
+ @location.text = config.readEntry( "defaultPage", "http://localhost")
+
+ connect( @location , SIGNAL( 'returnPressed()' ),
+ self, SLOT( 'changeLocation()' ) )
+
+ split = Qt::Splitter.new( vbox )
+ split.setOpaqueResize()
+
+ @browser = KDE::HTMLPart.new( split )
+ @browser.openURL( KDE::URL.new(@location.text()) )
+
+ connect( @browser.browserExtension(),
+ SIGNAL( 'openURLRequest( const KURL&, const KParts::URLArgs& )' ),
+ self, SLOT( 'openURLRequest(const KURL&, const KParts::URLArgs& )' ) )
+ setCentralWidget(vbox)
+ end
+
+ def changeLocation()
+ @history.push( @browser.url().url() );
+ toolBar().setItemEnabled( TOOLBAR_ID_BACK, true)
+ @browser.openURL( KDE::URL.new(@location.text()) )
+ end
+
+ def setURL( url )
+ @location.text = url
+ changeLocation()
+ end
+
+ def openURLRequest(url, part)
+ setURL( url.url() )
+ end
+
+ def gotoPreviousPage()
+ @location.text = @history.pop()
+ if @history.empty?
+ toolBar().setItemEnabled(TOOLBAR_ID_BACK, false)
+ end
+ @browser.openURL( KDE::URL.new(@location.text()) )
+ end
+
+ def bookLocation()
+ dcopRef = KDE::DCOPRef.new("p8", "BookMarkList")
+ if ! dcopRef.add(@location.text())
+ qWarning("Error with DCOP\n")
+ end
+ end
+
+ def fileSetDefaultPage()
+ config = $kapp.config()
+
+ config.group = "Settings"
+ config.writeEntry( "defaultPage", @browser.url().url() )
+ end
+end
+
+ about = KDE::AboutData.new("p7", "Tutorial - p7", "0.1")
+ KDE::CmdLineArgs.init(ARGV, about)
+ a = KDE::UniqueApplication.new()
+
+ window = Browser.new( "Tutorial - p7" )
+ window.resize( 300, 200 )
+
+ a.mainWidget = window
+ window.show
+
+ a.exec
+
diff --git a/korundum/rubylib/tutorials/p8/p8.rb b/korundum/rubylib/tutorials/p8/p8.rb new file mode 100644 index 00000000..711fe021 --- /dev/null +++ b/korundum/rubylib/tutorials/p8/p8.rb @@ -0,0 +1,39 @@ +require 'Korundum'
+
+class BookMarkList < KDE::ListView
+ k_dcop 'void add(QString)'
+
+ slots 'setURLInBrowser(QListViewItem *)'
+
+ def initialize()
+ super(nil, "Bookmarks")
+ addColumn( i18n("My Bookmarks") );
+ connect( self, SIGNAL('clicked(QListViewItem *)'),
+ self, SLOT('setURLInBrowser(QListViewItem *)'))
+ end
+
+ def add( s )
+ insertItem( KDE::ListViewItem.new( self , s ) )
+ end
+
+ def setURLInBrowser( item )
+ if item.nil? then return end
+ dcopRef = KDE::DCOPRef.new("p7", "Browser")
+ if ! dcopRef.setURL(item.text(0))
+ qWarning("Error with DCOP\n")
+ end
+ end
+end
+
+ about = KDE::AboutData.new("p8", "Tutorial - p8", "0.1")
+ KDE::CmdLineArgs.init(ARGV, about)
+ a = KDE::UniqueApplication.new()
+
+ mylist = BookMarkList.new
+ mylist.resize( 300, 200 )
+
+ a.mainWidget = mylist
+ mylist.show
+
+ a.exec
+
diff --git a/korundum/rubylib/tutorials/p9/p9.rb b/korundum/rubylib/tutorials/p9/p9.rb new file mode 100644 index 00000000..98bb9d0e --- /dev/null +++ b/korundum/rubylib/tutorials/p9/p9.rb @@ -0,0 +1,110 @@ +require 'Korundum'
+
+class Browser < KDE::MainWindow
+ k_dcop 'void setURL(QString)'
+
+ slots 'fileSetDefaultPage()',
+ 'changeLocation()',
+ 'bookLocation()',
+ 'gotoPreviousPage()',
+ 'openURLRequest(const KURL&, const KParts::URLArgs&)'
+
+ def initialize( name )
+ super(nil, name)
+ @history = []
+
+ KDE::StdAction.quit(self, SLOT('close()'), actionCollection())
+
+ KDE::Action.new(i18n("&Set default page"), "gohome", KDE::Shortcut.new(0), self,
+ SLOT('fileSetDefaultPage()'), actionCollection(), "set_default_page")
+
+ KDE::Action.new(i18n("Add to Bookmarks"), "reload", KDE::Shortcut.new(0), self,
+ SLOT('bookLocation()'), actionCollection(), "add_to_bookmarks")
+
+ KDE::Action.new(i18n("Back to previous page"), "back", KDE::Shortcut.new(0), self,
+ SLOT('gotoPreviousPage()'), actionCollection(), "back")
+
+ actionCollection().action("back").setEnabled(false)
+
+ createGUI(Dir.getwd + "/p9ui.rc")
+
+ vbox = Qt::VBox.new( self )
+
+ @location = Qt::LineEdit.new( vbox )
+
+ config = $kapp.config()
+ config.setGroup("Settings")
+ @location.text = config.readEntry( "defaultPage", "http://localhost")
+
+ connect( @location , SIGNAL( 'returnPressed()' ),
+ self, SLOT( 'changeLocation()' ) )
+
+ @browser = KDE::HTMLPart.new( vbox )
+ @browser.openURL( KDE::URL.new(@location.text()) )
+
+ connect( @browser.browserExtension(),
+ SIGNAL( 'openURLRequest( const KURL&, const KParts::URLArgs& )' ),
+ self, SLOT( 'openURLRequest(const KURL&, const KParts::URLArgs& )' ) )
+ setCentralWidget(vbox)
+ end
+
+
+ def changeLocation()
+ @history.push( @browser.url().url() );
+ actionCollection().action("back").setEnabled(true)
+ @browser.openURL( KDE::URL.new(@location.text()) )
+ end
+
+ def setURL( url )
+ @location.text = url
+ changeLocation()
+ end
+
+ def openURLRequest(url, part)
+ setURL( url.url() )
+ end
+
+ def gotoPreviousPage()
+ @location.text = @history.pop()
+ if @history.empty?
+ actionCollection().action("back").setEnabled(false)
+ end
+ @browser.openURL( KDE::URL.new(@location.text()) )
+ end
+
+ def bookLocation()
+ dcopRef = KDE::DCOPRef.new("p8", "BookMarkList")
+ if ! dcopRef.add(@location.text())
+ qWarning("Error with DCOP\n")
+ end
+ end
+
+ def fileSetDefaultPage()
+ config = $kapp.config()
+
+ config.group = "Settings"
+ config.writeEntry( "defaultPage", @browser.url().url() )
+ end
+end
+
+ aboutdata = KDE::AboutData.new("p9", "Tutorial - p9",
+ "1.0", "Step 9 of a simple tutorial", KDE::AboutData::License_GPL,
+ "(C) 2000, 2001 Antonio Larrosa Jimenez","",
+ "http://devel-home.kde.org/~larrosa/tutorial.html")
+ aboutdata.addAuthor("Antonio Larrosa Jimenez",
+ "Original Developer/Mantainer","larrosa@kde.org",
+ "http://devel-home.kde.org/~larrosa/index.html")
+ aboutdata.addAuthor("Richard Dale",
+ "Ruby port","Richard_Dale@tipitina.demon.co.uk",
+ "")
+ KDE::CmdLineArgs.init(ARGV, aboutdata)
+
+ a = KDE::UniqueApplication.new()
+
+ window = Browser.new( "Tutorial - p9" )
+ window.resize( 300, 200 )
+
+ a.mainWidget = window
+ window.show
+
+ a.exec
diff --git a/korundum/rubylib/tutorials/p9/p9ui.rc b/korundum/rubylib/tutorials/p9/p9ui.rc new file mode 100644 index 00000000..9e194c20 --- /dev/null +++ b/korundum/rubylib/tutorials/p9/p9ui.rc @@ -0,0 +1,14 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd" >
+<kpartgui name="p9" version="1">
+<MenuBar>
+ <Menu name="file"><text>&File</text>
+ <Action name="set_default_page"/>
+ </Menu>
+</MenuBar>
+<ToolBar fullWidth="true" name="mainToolBar">
+ <Action name="add_to_bookmarks"/>
+ <Action name="back"/>
+ <Separator/>
+ <Action name="file_quit"/>
+</ToolBar>
+</kpartgui>
\ No newline at end of file |