最初に
ここで言う「Simple OLE Browser」というのは、RubyライブラリWin32OLEの作者でいらっしゃる助田さん作成のツールです。
オリジナルはこちらからダウンロードできます→ http://homepage1.nifty.com/markey/ruby/win32ole/
前回のSimple OLE Browserは!
ふつうに添付のsoleb.rbを動かすスキルを持たなかったdoju_mは無謀にもwxRubyで書き直そうと目論んだ!
奇跡的にそれは動作したが、新たな敵がdoju_mを待ち受ける!
「wxRubyはRuby2.0に対応していない……だと……」
そんなわけで
新たなガワを探す旅に出た私でしたが紆余曲折あって「Qtでいこか」と決めたのでした。
もっとも使ってるのがmingw版ということでqtruby4がgemで入らず、
「どうすればいいんだ」
とひとしきり悩んだ後qtbindingsで大丈夫だ、問題ないということに気がつくのですが。
そんなことよりおうどんたべたいコードはどうした
例によってWindowsでしか動きませんのでご注意を。
起動時に分単位で待たされるのも相変わらずですorz
# -*- encoding: utf-8 -*-
require 'thread' # workaround for https://github.com/ryanmelt/qtbindings/issues/69
require 'Qt'
require 'win32ole'
WIN32OLE.codepage = WIN32OLE::CP_UTF8
class OLEINFO
def initialize
@members = []
@tlibs = nil
end
def typelibs
if @tlibs.nil?
@tlibs = WIN32OLE_TYPELIB.typelibs.select{|t|
t.name.size > 0
}.sort {|a, b| a.name <=> b.name}
end
@tlibs
end
def ole_classes(tlib)
WIN32OLE_TYPE.ole_classes(tlib).collect {|t|
t.name
}.sort
end
def ole_members(tlib, klass)
@members = []
k = WIN32OLE_TYPE.ole_classes(tlib).find {|t|
t.name == klass
}
return [] if !k
@members = (k.ole_methods + k.variables).sort{|m1, m2|
m1.name <=> m2.name
}
(@members).collect {|m|
m.name
}
end
def ole_class_info(tlib, klass)
k = WIN32OLE_TYPE.ole_classes(tlib).find {|t|
t.name == klass
}
return "" if !k
"#{k.ole_type} #{k.name}\r\n" +
" GUID : #{k.guid}\r\n" +
" PROGID : #{k.progid}\r\n" +
" DESCRIPTION : #{k.helpstring}\r\n\r\n"
end
def method_info(m)
info = ""
info += "Event " if m.event?
info += m.invoke_kind
info += " "
info += m.return_type
info += " "
info += m.name
info += "\r\n"
info += " Dispatch ID : #{m.dispid}\r\n"
info += " DESCRIPTION : #{m.helpstring}\r\n"
m.params.each_with_index do |param, i|
pinfos = []
pinfos.push "IN" if param.input?
pinfos.push "OUT" if param.output?
pinfos.push "OPTION" if param.optional?
pinfo = "arg#{i+1} - #{param.ole_type} #{param.name} [#{pinfos.join(',')}]"
pinfo += " = #{param.default}" if param.default
info += " #{pinfo}\r\n"
end
info += "\r\n"
info += " Event Interface : #{m.event_interface}\r\n" if m.event?
info
end
def variable_info(m)
info = "\r\n #{m.variable_kind} #{m.ole_type} #{m.name}"
info += " = #{m.value}" if m.value
info
end
def ole_member_info(tlib, klass, member, i)
k = WIN32OLE_TYPE.ole_classes(tlib).find {|t|
t.name == klass
}
return "" if !k
m = (k.ole_methods + k.variables).find {|mm|
mm.name == member
}
m = @members[i]
return "" if !m
if m.kind_of?(WIN32OLE_METHOD)
return method_info(m)
else
return variable_info(m)
end
end
end
module SOleB
class App
VERSION = '0.0.1a'
def initialize(argv)
@app = Qt::Application.new(argv)
@frame = SOleB::MainWindow.new(self)
end
def version
VERSION
end
def exec
@frame.show
@app.exec
end
end
class MainWindow < Qt::MainWindow
def initialize(app)
super()
@main_wid = SOleB::MainFrame.new
self.window_title = "Simple OLE Browser #{app.version}"
#resize(400, 300)
setCentralWidget(@main_wid)
end
end
class MainFrame < Qt::Widget
slots 'tlib_selchanged(const QModelIndex&)'
slots 'class_selchanged(const QModelIndex&)'
slots 'member_selchanged(const QModelIndex&)'
def initialize
super
ole_info = OLEINFO.new
frame = self
if_list = nil
method_list = nil
desc_area = nil
setLayout(Qt::VBoxLayout.new {
lib_list = Qt::ListView.new
lib_model = Qt::StringListModel.new
lib_model.stringList = ole_info.typelibs.collect {|e| e.name}
lib_list.model = lib_model
connect(lib_list, SIGNAL('clicked(const QModelIndex&)'),
frame, SLOT('tlib_selchanged(const QModelIndex&)'))
addWidget lib_list
addLayout Qt::HBoxLayout.new {
if_list = Qt::ListView.new
connect(if_list, SIGNAL('clicked(const QModelIndex&)'),
frame, SLOT('class_selchanged(const QModelIndex&)'))
addWidget if_list
method_list = Qt::ListView.new
connect(method_list, SIGNAL('clicked(const QModelIndex&)'),
frame, SLOT('member_selchanged(const QModelIndex&)'))
addWidget method_list
}
desc_area = Qt::TextEdit.new
desc_area.readOnly = true
addWidget desc_area
})
@ole_info = ole_info
@if_list = if_list
@method_list = method_list
@desc_area = desc_area
@current_guid = nil
end
def tlib_selchanged(model_idx)
if_model = Qt::StringListModel.new
@current_guid = @ole_info.typelibs[model_idx.row].guid
if_model.stringList = @ole_info.ole_classes(@current_guid)
@if_list.model = if_model
end
def class_selchanged(model_idx)
@current_class_name = @if_list.model.data(model_idx).toString()
#puts @current_class_name
method_model = Qt::StringListModel.new
method_model.stringList = @ole_info.ole_members(
@current_guid, @current_class_name)
@method_list.model = method_model
@desc_area.plainText = get_classinfo(@current_guid, @current_class_name)
end
def member_selchanged(model_idx)
member_name = @method_list.model.data(model_idx).toString()
#puts member_name
@desc_area.plainText =
get_classinfo(@current_guid, @current_class_name) +
@ole_info.ole_member_info(
@current_guid, @current_class_name, member_name, model_idx.row)
end
def get_classinfo(guid, class_name)
@ole_info.ole_class_info(guid, class_name)
end
end
end
SOleB::App.new(ARGV).exec
基本ガワ固有部分以外はほぼ共通のはずです。
(WIN32OLE.codepageなんてあったんだ、ということでUTF-8に統一したくらいかと)
付け足し
前回同様、ライセンスはオリジナルにならい
You can redistribute it under the terms specified in the COPYING file of the Ruby distribution.
THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
PURPOSE.
と致します。改変もご自由に。