mirror of https://github.com/KLayout/klayout.git
598 lines
15 KiB
Ruby
598 lines
15 KiB
Ruby
|
|
$:.push(File::dirname($0))
|
|
|
|
load("test_prologue.rb")
|
|
|
|
# an event filter class
|
|
|
|
# don't create a class twice since the alias orgEventFilter will
|
|
# refer to itself
|
|
if !Object.const_defined?("EventFilter")
|
|
|
|
class EventFilter < RBA::QObject
|
|
|
|
alias orgEventFilter eventFilter
|
|
|
|
def initialize
|
|
@log = []
|
|
end
|
|
|
|
def log
|
|
@log
|
|
end
|
|
|
|
def eventFilter(obj, event)
|
|
@log << (event.class.to_s + ": " + event.type.inspect)
|
|
self.orgEventFilter(obj, event)
|
|
end
|
|
|
|
end
|
|
|
|
# implementation
|
|
|
|
class MyAction < RBA::QAction
|
|
|
|
def initialize(p, n)
|
|
super(p)
|
|
self.objectName = n
|
|
@ce = nil
|
|
end
|
|
|
|
def childEvent(ev)
|
|
if @ce
|
|
@ce.call(ev)
|
|
end
|
|
end
|
|
|
|
def on_child_event(&ce)
|
|
@ce = ce
|
|
end
|
|
|
|
end
|
|
|
|
class MyObject < RBA::QObject
|
|
|
|
def initialize
|
|
@ef = nil
|
|
super(nil)
|
|
end
|
|
|
|
alias baseEventFilter eventFilter
|
|
|
|
def eventFilter(watched, event)
|
|
if @ef.call(watched, event)
|
|
return true
|
|
end
|
|
baseEventFilter(watched, event)
|
|
end
|
|
|
|
def on_event_filter(&ef)
|
|
@ef = ef
|
|
end
|
|
|
|
end
|
|
|
|
class MyStandardItemModel < RBA::QStandardItemModel
|
|
|
|
def srn(rn)
|
|
if self.respond_to?(:setRoleNames, true)
|
|
self.setRoleNames(rn)
|
|
else
|
|
self.setItemRoleNames(rn)
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
class QtBinding_TestClass < TestBase
|
|
|
|
def test_00
|
|
|
|
# initial test
|
|
|
|
end
|
|
|
|
def test_10
|
|
|
|
a = MyAction.new(nil, "a")
|
|
a.text = "mytext"
|
|
a.checkable = true
|
|
assert_equal(a.isChecked, false)
|
|
a.checked = true
|
|
assert_equal(a.text, "mytext")
|
|
assert_equal(a.objectName, "a")
|
|
a.text += "."
|
|
assert_equal(a.text, "mytext.")
|
|
assert_equal(a.isChecked, true)
|
|
|
|
t = ""
|
|
a.triggered do |checked|
|
|
t += "[#{checked}]";
|
|
end
|
|
assert_equal(t, "")
|
|
a.trigger # also toggles checked state
|
|
assert_equal(t, "[false]")
|
|
t = ""
|
|
a.trigger # also toggles checked state
|
|
assert_equal(t, "[true]")
|
|
|
|
# force GC and destruction
|
|
a = nil
|
|
GC.start
|
|
a = MyAction.new(nil, "anew")
|
|
assert_equal(a.objectName, "anew")
|
|
a = nil
|
|
GC.start
|
|
|
|
end
|
|
|
|
def test_11
|
|
|
|
a = RBA::QAction.new(nil)
|
|
aa = MyAction.new(a, "aa")
|
|
assert_equal(aa.objectName, "aa")
|
|
|
|
# destroying a will also destroy aa
|
|
a.destroy
|
|
assert_equal(a.destroyed?, true)
|
|
assert_equal(aa.destroyed?, true)
|
|
|
|
end
|
|
|
|
def test_12
|
|
|
|
a = RBA::QAction.new(nil)
|
|
aa = RBA::QAction.new(a)
|
|
aa.objectName = "aa"
|
|
|
|
# destroying in the GC will also destroy aa
|
|
a = nil
|
|
GC.start
|
|
a = RBA::QAction.new(nil)
|
|
a = nil
|
|
GC.start
|
|
|
|
assert_equal(aa.destroyed?, true)
|
|
|
|
end
|
|
|
|
def test_13
|
|
|
|
a = RBA::QAction.new(nil)
|
|
aa = RBA::QAction.new(a)
|
|
aa.objectName = "aa"
|
|
aa.text = "aatext"
|
|
|
|
cc = []
|
|
a.children.each do |c|
|
|
cc.push(c.objectName)
|
|
end
|
|
assert_equal(cc.join(","), "aa")
|
|
|
|
# aa now is kept by a
|
|
aa = nil
|
|
GC.start
|
|
aa = RBA::QAction.new(nil)
|
|
aa = nil
|
|
GC.start
|
|
|
|
# fetch aa again
|
|
a.children.each do |c|
|
|
if c.objectName == "aa"
|
|
aa = c
|
|
end
|
|
end
|
|
assert_equal(aa != nil, true)
|
|
assert_equal(aa.class.to_s, "RBA::QAction")
|
|
assert_equal(aa.text, "aatext")
|
|
assert_equal(aa.destroyed?, false)
|
|
|
|
end
|
|
|
|
def test_20
|
|
|
|
no_event = false
|
|
|
|
x = []
|
|
ef = MyObject.new
|
|
ef.on_event_filter do |watched,event|
|
|
x.push(watched.inspect + ":" + event.inspect)
|
|
no_event
|
|
end
|
|
|
|
ce_log = []
|
|
a = MyAction.new(nil, "a")
|
|
a.on_child_event do |ce|
|
|
ce_log.push("#{ce.added}:#{ce.child.objectName}")
|
|
end
|
|
|
|
a.installEventFilter(ef)
|
|
|
|
aa = MyAction.new(nil, "aa1")
|
|
assert_equal(ce_log.join(","), "")
|
|
aa.setParent(a)
|
|
assert_equal(ce_log.join(","), "true:aa1")
|
|
ce_log = []
|
|
|
|
# destroy aa
|
|
aa.destroy
|
|
aa = nil
|
|
assert_equal(ce_log.join(","), "false:aa1")
|
|
ce_log = []
|
|
|
|
no_event = true
|
|
aa = MyAction.new(nil, "aa2")
|
|
aa.setParent(a)
|
|
assert_equal(ce_log.join(","), "")
|
|
ce_log = []
|
|
|
|
no_event = false
|
|
aa.destroy
|
|
aa = nil
|
|
assert_equal(ce_log.join(","), "false:aa2")
|
|
ce_log = []
|
|
|
|
end
|
|
|
|
def test_30
|
|
|
|
# dialog construction, cleanup, object dependency ...
|
|
|
|
mw = nil # more fun than with RBA::Application::instance.main_window because Ruby's GC does all the cleanup
|
|
|
|
dialog = RBA::QDialog::new(mw)
|
|
label = RBA::QLabel::new(dialog)
|
|
layout = RBA::QHBoxLayout::new(dialog)
|
|
layout.addWidget(label)
|
|
GC.start
|
|
|
|
dialog = RBA::QDialog::new(mw)
|
|
label = RBA::QLabel::new(dialog)
|
|
layout = RBA::QHBoxLayout::new(dialog)
|
|
layout.addWidget(label)
|
|
label.destroy
|
|
GC.start
|
|
|
|
dialog = RBA::QDialog::new(mw)
|
|
label = RBA::QLabel::new(dialog)
|
|
layout = RBA::QHBoxLayout::new(dialog)
|
|
layout.addWidget(label)
|
|
layout.destroy
|
|
GC.start
|
|
|
|
dialog = RBA::QDialog::new(mw)
|
|
label = RBA::QLabel::new(dialog)
|
|
layout = RBA::QHBoxLayout::new(dialog)
|
|
layout.addWidget(label)
|
|
dialog.destroy
|
|
GC.start
|
|
|
|
dialog = RBA::QDialog::new(mw)
|
|
label = RBA::QLabel::new(dialog)
|
|
layout = RBA::QHBoxLayout::new(dialog)
|
|
layout.addWidget(label)
|
|
GC.start
|
|
|
|
end
|
|
|
|
def test_31
|
|
|
|
# Optional arguments, enums, QFlag's
|
|
|
|
mw = nil # more fun than with RBA::Application::instance.main_window because Ruby's GC does all the cleanup
|
|
|
|
mb = RBA::QMessageBox::new(RBA::QMessageBox::Critical, "title", "text")
|
|
assert_equal(mb.icon.to_i != RBA::QMessageBox::Warning.to_i, true)
|
|
assert_equal(mb.icon.to_i == RBA::QMessageBox::Critical.to_i, true)
|
|
assert_equal(mb.standardButtons.to_i == RBA::QMessageBox::NoButton.to_i, true)
|
|
|
|
mb = RBA::QMessageBox::new(RBA::QMessageBox::Critical, "title", "text", RBA::QMessageBox::Ok)
|
|
assert_equal(mb.standardButtons.to_i == RBA::QMessageBox::Ok.to_i, true)
|
|
|
|
mb = RBA::QMessageBox::new(RBA::QMessageBox::Critical, "title", "text", RBA::QMessageBox::Ok | RBA::QMessageBox::Cancel)
|
|
assert_equal(mb.standardButtons.to_i == RBA::QMessageBox::Ok.to_i + RBA::QMessageBox::Cancel.to_i, true)
|
|
|
|
end
|
|
|
|
def test_40
|
|
|
|
# Lifetime management of objects/methods not using QObject::parent
|
|
# QTreeWidget (parent)/QTreeWidgetItem (child)
|
|
|
|
# constructor with parent-like argument:
|
|
tw = RBA::QTreeWidget::new
|
|
ti = RBA::QTreeWidgetItem::new(tw)
|
|
# strange, but true:
|
|
assert_equal(ti.parent, nil)
|
|
assert_equal(tw.topLevelItemCount, 1)
|
|
ti = nil
|
|
# force delete of the ti item unless it's referenced
|
|
# NOTE: it's not sufficient to just set ti to nil, we also
|
|
# have to create a new QTreeWidgetItem (special for Ruby >1.9?)
|
|
ti = RBA::QTreeWidgetItem::new
|
|
GC.start
|
|
# gives 1, because the tree widget item is kept by
|
|
# the tree widget:
|
|
assert_equal(tw.topLevelItemCount, 1)
|
|
|
|
# the tree item belongs to the widget, hence it's destroyed with
|
|
# the widget
|
|
ti = tw.topLevelItem(0)
|
|
tw._destroy
|
|
# gives true, because tw owns ti too.
|
|
assert_equal(ti._destroyed?, true)
|
|
|
|
# The same works for insert too
|
|
tw = RBA::QTreeWidget::new
|
|
ti = RBA::QTreeWidgetItem::new
|
|
tw.insertTopLevelItem(0, ti)
|
|
assert_equal(tw.topLevelItemCount, 1)
|
|
ti = nil
|
|
# force delete of the ti item unless it's referenced
|
|
ti = RBA::QTreeWidgetItem::new
|
|
GC.start
|
|
# gives 1, because the tree widget item is kept by
|
|
# the tree widget:
|
|
assert_equal(tw.topLevelItemCount, 1)
|
|
|
|
# the tree item belongs to the widget, hence it's destroyed with
|
|
# the widget
|
|
ti = tw.topLevelItem(0)
|
|
tw._destroy
|
|
# gives true, because tw owns ti
|
|
assert_equal(ti._destroyed?, true)
|
|
|
|
# And add:
|
|
tw = RBA::QTreeWidget::new
|
|
ti = RBA::QTreeWidgetItem::new
|
|
tw.addTopLevelItem(ti)
|
|
assert_equal(tw.topLevelItemCount, 1)
|
|
ti = nil
|
|
# force delete of the ti item unless it's referenced
|
|
ti = RBA::QTreeWidgetItem::new
|
|
GC.start
|
|
# gives 1, because the tree widget item is kept by
|
|
# the tree widget:
|
|
assert_equal(tw.topLevelItemCount, 1)
|
|
|
|
# the tree item belongs to the widget, hence it's destroyed with
|
|
# the widget
|
|
ti = tw.topLevelItem(0)
|
|
tw._destroy
|
|
# gives true, because tw owns ti
|
|
assert_equal(ti._destroyed?, true)
|
|
|
|
# But the item is released when we take it and add:
|
|
tw = RBA::QTreeWidget::new
|
|
ti = RBA::QTreeWidgetItem::new
|
|
tw.addTopLevelItem(ti)
|
|
assert_equal(tw.topLevelItemCount, 1)
|
|
ti = nil
|
|
# force delete of the ti item unless it's referenced
|
|
ti = RBA::QTreeWidgetItem::new
|
|
GC.start
|
|
# gives 1, because the tree widget item is kept by
|
|
# the tree widget:
|
|
assert_equal(tw.topLevelItemCount, 1)
|
|
|
|
ti = tw.takeTopLevelItem(0)
|
|
tw._destroy
|
|
# gives false, because we took ti and tw no longer owns it
|
|
assert_equal(ti._destroyed?, false)
|
|
|
|
# And we can destroy a child too
|
|
tw = RBA::QTreeWidget::new
|
|
ti = RBA::QTreeWidgetItem::new
|
|
tw.addTopLevelItem(ti)
|
|
assert_equal(tw.topLevelItemCount, 1)
|
|
ti._destroy
|
|
assert_equal(tw.topLevelItemCount, 0)
|
|
|
|
end
|
|
|
|
def test_41
|
|
|
|
# Lifetime management of objects/methods not using QObject::parent
|
|
# QTreeWidgetItem (parent)/QTreeWidgetItem (child)
|
|
|
|
# constructor with parent-like argument (supported by QObject parent/child relationship):
|
|
tw = RBA::QTreeWidgetItem::new
|
|
ti = RBA::QTreeWidgetItem::new(tw)
|
|
# that's not QObject::parent - this one still is 0 (not seen by RBA)
|
|
assert_equal(ti.parent, tw)
|
|
assert_equal(tw.childCount, 1)
|
|
ti = nil
|
|
# force delete of the ti item unless it's referenced
|
|
# NOTE: it's not sufficient to just set ti to nil, we also
|
|
# have to create a new QTreeWidgetItem (special for Ruby >1.9?)
|
|
ti = RBA::QTreeWidgetItem::new
|
|
GC.start
|
|
# gives 1, because the tree widget item is kept by
|
|
# the tree widget:
|
|
assert_equal(tw.childCount, 1)
|
|
|
|
# the tree item belongs to the widget, hence it's destroyed with
|
|
# the widget
|
|
ti = tw.child(0)
|
|
tw._destroy
|
|
# gives true, because tw owns ti too.
|
|
assert_equal(ti._destroyed?, true)
|
|
|
|
# The same works for insert too
|
|
tw = RBA::QTreeWidgetItem::new
|
|
ti = RBA::QTreeWidgetItem::new
|
|
tw.insertChild(0, ti)
|
|
assert_equal(tw.childCount, 1)
|
|
ti = nil
|
|
# force delete of the ti item unless it's referenced
|
|
ti = RBA::QTreeWidgetItem::new
|
|
GC.start
|
|
# gives 1, because the tree widget item is kept by
|
|
# the tree widget:
|
|
assert_equal(tw.childCount, 1)
|
|
|
|
# the tree item belongs to the widget, hence it's destroyed with
|
|
# the widget
|
|
ti = tw.child(0)
|
|
tw._destroy
|
|
# gives true, because tw owns ti
|
|
assert_equal(ti._destroyed?, true)
|
|
|
|
# And add:
|
|
tw = RBA::QTreeWidgetItem::new
|
|
ti = RBA::QTreeWidgetItem::new
|
|
tw.addChild(ti)
|
|
assert_equal(tw.childCount, 1)
|
|
ti = nil
|
|
# force delete of the ti item unless it's referenced
|
|
ti = RBA::QTreeWidgetItem::new
|
|
GC.start
|
|
# gives 1, because the tree widget item is kept by
|
|
# the tree widget:
|
|
assert_equal(tw.childCount, 1)
|
|
|
|
# the tree item belongs to the widget, hence it's destroyed with
|
|
# the widget
|
|
ti = tw.child(0)
|
|
tw._destroy
|
|
# gives true, because tw owns ti
|
|
assert_equal(ti._destroyed?, true)
|
|
|
|
# But the item is released when we take it and add:
|
|
tw = RBA::QTreeWidgetItem::new
|
|
ti = RBA::QTreeWidgetItem::new
|
|
tw.addChild(ti)
|
|
assert_equal(tw.childCount, 1)
|
|
ti = nil
|
|
# force delete of the ti item unless it's referenced
|
|
ti = RBA::QTreeWidgetItem::new
|
|
GC.start
|
|
# gives 1, because the tree widget item is kept by
|
|
# the tree widget:
|
|
assert_equal(tw.childCount, 1)
|
|
|
|
ti = tw.takeChild(0)
|
|
tw._destroy
|
|
# gives false, because we took ti and tw no longer owns it
|
|
assert_equal(ti._destroyed?, false)
|
|
|
|
# And we can destroy a child too
|
|
tw = RBA::QTreeWidgetItem::new
|
|
ti = RBA::QTreeWidgetItem::new
|
|
tw.addChild(ti)
|
|
assert_equal(tw.childCount, 1)
|
|
ti._destroy
|
|
assert_equal(tw.childCount, 0)
|
|
|
|
end
|
|
|
|
def test_42
|
|
|
|
# QKeyEvent and related issues
|
|
|
|
ef = EventFilter::new
|
|
|
|
widget = RBA::QLineEdit::new
|
|
widget.setText("ABC")
|
|
|
|
RBA::QApplication::processEvents
|
|
|
|
widget.installEventFilter(ef)
|
|
|
|
ke = RBA::QKeyEvent::new(RBA::QEvent::KeyPress, RBA::Qt::Key_O.to_i, RBA::Qt::ShiftModifier, "O")
|
|
RBA::QCoreApplication::postEvent(widget, ke)
|
|
|
|
ke = RBA::QKeyEvent::new(RBA::QEvent::KeyPress, RBA::Qt::Key_Left.to_i, RBA::Qt::NoModifier)
|
|
RBA::QCoreApplication::postEvent(widget, ke)
|
|
|
|
ke = RBA::QKeyEvent::new(RBA::QEvent::KeyPress, RBA::Qt::Key_P.to_i, RBA::Qt::NoModifier, "p")
|
|
RBA::QCoreApplication::postEvent(widget, ke)
|
|
|
|
RBA::QApplication::processEvents
|
|
|
|
GC.start
|
|
|
|
assert_equal(ef.log.select { |s| s !~ /RBA::QKeyEvent: ShortcutOverride/ }.join("\n"), "RBA::QKeyEvent: KeyPress (6)\nRBA::QKeyEvent: KeyPress (6)\nRBA::QKeyEvent: KeyPress (6)")
|
|
ef = nil
|
|
ef = EventFilter::new
|
|
GC.start
|
|
|
|
assert_equal(widget.text, "ABCpO")
|
|
ef = nil
|
|
widget = nil
|
|
GC.start
|
|
|
|
end
|
|
|
|
def test_43
|
|
|
|
# QHash bindings
|
|
|
|
slm = MyStandardItemModel::new
|
|
rn = slm.roleNames
|
|
assert_equal(rn.keys.sort.collect { |k| "#{k}=>\"#{rn[k]}\"" }.join(", "), "0=>\"display\", 1=>\"decoration\", 2=>\"edit\", 3=>\"toolTip\", 4=>\"statusTip\", 5=>\"whatsThis\"")
|
|
rn[7] = "blabla"
|
|
slm.srn(rn)
|
|
rn = slm.roleNames
|
|
assert_equal(rn.keys.sort.collect { |k| "#{k}=>\"#{rn[k]}\"" }.join(", "), "0=>\"display\", 1=>\"decoration\", 2=>\"edit\", 3=>\"toolTip\", 4=>\"statusTip\", 5=>\"whatsThis\", 7=>\"blabla\"")
|
|
|
|
end
|
|
|
|
def test_44
|
|
|
|
# Ability to monitor native child objects
|
|
|
|
parent = RBA::QScrollArea::new
|
|
parent.show # this makes resize actually change the widget's size
|
|
child = parent.viewport
|
|
|
|
# ensure parent and child are working
|
|
assert_equal(child.destroyed?, false)
|
|
|
|
parent.resize(200, 200)
|
|
assert_equal(child.width() > 100, true)
|
|
assert_equal(child.height() > 100, true)
|
|
|
|
parent.resize(100, 100)
|
|
assert_equal(child.width() < 100, true)
|
|
assert_equal(child.height() < 100, true)
|
|
|
|
# now if we delete the parent, the child needs to become disconnected
|
|
|
|
parent._destroy()
|
|
assert_equal(parent.destroyed?, true)
|
|
assert_equal(child.destroyed?, true)
|
|
|
|
end
|
|
|
|
def test_45
|
|
|
|
# Ability to connect to signals while ignoring arguments and
|
|
# to emit signals
|
|
|
|
b = RBA::QPushButton::new
|
|
|
|
triggered = ""
|
|
b.clicked { |checked| triggered += (checked ? "1" : "0") }
|
|
|
|
assert_equal(triggered, "")
|
|
b.emit_clicked(true)
|
|
assert_equal(triggered, "1")
|
|
b.emit_clicked(false)
|
|
assert_equal(triggered, "10")
|
|
|
|
b.clicked { triggered += "*" }
|
|
|
|
b.emit_clicked(true)
|
|
assert_equal(triggered, "10*")
|
|
b.emit_clicked(false)
|
|
assert_equal(triggered, "10**")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
load("test_epilogue.rb")
|