Friday, March 13, 2009

OOP YaST GUI: event handling

OOP in YaST GUI: Event handling
------------------------------

Hello, here I am again ...

I played with idea of event handling, but if possible better way than we do in ycp now.
Also using inheritance: when you define some behavior, you can inherit class and override handling method or just use objects and handling will be done automatically (using composition).
So the basic idea is that event loop is done automatically and it executes handle function of object that is responsible for such event or which is listening.

Event loop is implemented in parent object (root object in hierarchy - CDialog). Because of this, all inherited objects (MainDialog, PopupDialog) will have this functionality automatically.


class CDialog:
def __init__(self):
self.factory = yui.YUI.widgetFactory()

def listen(self, newList):
self.listeners = newList
etype=-1
while etype!=5:
event = self.dialog.waitForEvent()
etype = event.eventType()
for item in self.listeners:
if (item.getInstance()==event.widget()): item.handle(event)

class CButton:
def __init__(self, factory, parent, label):
self.button = factory.createPushButton( parent, label )
def getInstance(self):
return self.button

...
self.pbAdd = CButton(self.f, hbox2, "&Add")
self.pbEdit = CButton(self.f, hbox2, "&Edit")
self.pbDel = CButton(self.f, hbox2, "&Delete")
...
d.listen([self.pbAdd, self.pbEdit, self.pbDel])
...




When you want to handle something (button click for example), you need to:
- define function that will executed
- connect function to the object
- start event loop with list of "listeners" (objects with connected functions)

There are 3 kinds of functons:
1 - function without any connection to object

self.pbAdd.handle = self.handleAdd

2 - function with connection just to object

self.pbAdd.handle = new.instancemethod(mujhandler, self.pbAdd, self.pbAdd.__class__)

3 - function with visibility outside of the object (example: function can see whole dialog)

self.pbAdd.handle = new.instancemethod(self.handleAdd.im_func, self.pbAdd, self.pbAdd.__class__)


Code is submitted into subversion

How to test this code:
- svn checkout http://svn.opensuse.org/svn/yast/branches/tmp/mzugec/python-yui/
- make sure you have installed packages: python-yui, yast2-libyui, yast2-qt, yast2-ncurses
- run "./main.py" to see Qt version, "unset DISPLAY;./main.py" for ncurses version (unfortunately,in ncurses only way how to terminate application is to kill it, TODO)

Tuesday, February 17, 2009

Object Oriented UI for YaST

Hello!

After my last blog I worked on YaST (what a surprise) and didn't have any time to post anything until now.
Meanwhile I read some chapters from the "Thinking in Java" book. There are some chapters about OOP in general and it brings me to idea, how it would be great in YaST. As a side effect it also means get away from ycp ;-). Thanks to UI independence I can use Python with the YaST UI.

Here's some code example:

widget_library.py:

#!/usr/bin/python
# -*- coding: utf-8 -*-
import yui

class MainDialog:
def __init__(self):
self.factory = yui.YUI.widgetFactory()
self.dialog = self.factory.createMainDialog()
def __del__(self):
self.dialog.destroy()

class Popup:
def __init__(self):
self.factory = yui.YUI.widgetFactory()
self.dialog = self.factory.createPopupDialog()
def __del__(self):
self.dialog.destroy()


class TableDialog:
def __init__(self, d):
self.f = d.factory
vbox1 =self.f.createVBox( d.dialog )
self.f.createVStretch(vbox1)
hbox1 =self.f.createHBox( vbox1 )
self.f.createHStretch(hbox1)
self.f.createHSpacing(hbox1,1)
vbox2 =self.f.createVBox( hbox1 )

self.Table( vbox2 )

vspace =self.f.createVSpacing(vbox1,2)
self.f.createHSpacing(hbox1,1)
self.f.createHStretch(hbox1)
self.f.createVStretch(vbox1)

etype=-1
while etype!=5:
event = d.dialog.waitForEvent()
etype = event.eventType()
self.HandleEvent( event )
print etype

def Table(self,parent):
vbox3 =self.f.createVBox( parent )
self.customWidget(vbox3)
theader = yui.YTableHeader()
theader.addColumn("Targets")
self.table =self.f.createTable( vbox3, theader )
hbox2 =self.f.createHBox( vbox3 )
self.pbAdd =self.f.createPushButton( hbox2, "&Add" )
self.pbEdit =self.f.createPushButton( hbox2, "&Edit" )
self.pbDel =self.f.createPushButton( hbox2, "&Delete")
self.enableDisableButtons()

def customWidget(self,parent):
pass

def HandleEvent(self,event):
if (event.widget()==self.pbAdd):
self.handleAdd(event)
elif (event.widget()==self.pbEdit):
self.handleEdit(event)
elif (event.widget()==self.pbDel):
self.handleDel(event)
self.enableDisableButtons()

def enableDisableButtons(self):
self.pbEdit.setEnabled(self.table.itemsCount()>0)
self.pbDel.setEnabled(self.table.itemsCount()>0)


main.py:

#!/usr/bin/python
# -*- coding: utf-8 -*-
import yui
from widget_library import *

class TargetDialog(TableDialog):
def __init__(self,d):
TableDialog.__init__(self,d)

def customWidget(self,parent):
hbox =self.f.createHBox( parent )
self.f.createInputField(hbox, "Target")
self.f.createInputField(hbox, "Identifier")

def handleAdd(self, event):
print "add target item"
def handleEdit(self,event):
print "edit target item ..."
def handleDel(self,event):
print "delete target item ..."

class MyTable(TableDialog):
def __init__(self,d):
TableDialog.__init__(self,d)

def handleAdd(self,event):
print "adding ..."
TargetDialog(Popup())

def handleEdit(self,event):
print "edit item ..."
def handleDel(self,event):
print "delete item ..."

if __name__== "__main__":
td = TargetDialog(MainDialog())



I know that code is not nice and not very useful, but here's some nice OOP examples:
inheritance, composition, etc ...

Easily put into constructor, what kind of dialog I want:
TableDialog(MainDialog()) or TargetDialog(Popup())

Inherit some class and override methods you want (see MyTable.handle*())
This is much better than generate file from template (as we do now).

I like this way and I'll keep working on it during my ITO.

Bye,
Michal

Monday, August 11, 2008

New YaST2 printer configuration module

Today I submitted new version of yast2-printer (2.17.2). This version contains big (major) changes. It uses Johannes Meixner's code from Build service, based on some ideas to improve current status.



Please anybody interested in improving current status of printing configuration - test it and give me (any) feedback.

Thank you,
Michal

Thursday, August 7, 2008

Installation via wireless network

I fixed some issues in yast2-network-2.17.16 and did some tests and the result is : it works fine!

1 - Boot into any already installed linux, download kernel & initrd, create /boot/grub/menu.lst entry - some documentation here, also possible to use miniISO

2 - Into bootloader pass install=$custom_or_public_NETWORK_repository option

3 - Unplug your wired card

4 - With this setup will Linuxrc try to use your wireless network card to connect network repository. There are some dialogs to specify ESSID, WEP/WPA and sharedkey

5 - In case of connection succeed, do installation as usual (via wireless ;-))

6 - Before first reboot this network setup will be saved as persistent (into /etc/sysconfig/network/ifcfg-wlan0)

7 - During next boot (2nd stage of installation) wireless network is automatically up and you can finish installation

Monday, August 4, 2008

YaST network and Tunnels

From version yast2-network-2.17.14 YaST has support for creating tunnels. This is good for virtual networking, VPN and virtualization.
But theory you can read on many places (including wikipedia), so here is practical example of configuration:

My previous "usual" configuration

urchin:/home/mzugec/svn/trunk/network # ip a
1: lo: <loopback,up,lower_up> mtu 16436 qdisc noqueue
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 brd 127.255.255.255 scope host lo
inet 127.0.0.2/8 brd 127.255.255.255 scope host secondary lo
2: eth0: <broadcast,multicast,promisc,up,lower_up> mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:11:d8:39:4e:d0 brd ff:ff:ff:ff:ff:ff
inet 10.20.1.28/21 brd 10.20.7.255 scope global eth0
3: eth1: <broadcast,multicast> mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:11:d8:39:5c:e4 brd ff:ff:ff:ff:ff:ff



In YaST, remove configuration from eth0 (because this configuration belongs to bridge - see later)


Create new TAP device, click Next


Leave default "Persistent Tunnel" and set owner and/or group to access this device from user account



Configuration overview


Create new network interface type bridge


Put eth0 and tap0 into bridge and configure bridge with DHCP (as eth0 before)


Configuration overview



urchin:/home/mzugec/svn/trunk/network/src # ip a
1: lo: <loopback,up,lower_up> mtu 16436 qdisc noqueue
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 brd 127.255.255.255 scope host lo
inet 127.0.0.2/8 brd 127.255.255.255 scope host secondary lo
2: eth0: <broadcast,multicast,promisc,up,lower_up> mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:11:d8:39:4e:d0 brd ff:ff:ff:ff:ff:ff
3: eth1: <broadcast,multicast> mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:11:d8:39:5c:e4 brd ff:ff:ff:ff:ff:ff
24: tap0: <broadcast,multicast,up,lower_up> mtu 1500 qdisc pfifo_fast qlen 500
link/ether 00:ff:1c:00:23:8b brd ff:ff:ff:ff:ff:ff
25: br0: <broadcast,multicast,up,lower_up> mtu 1500 qdisc noqueue
link/ether 00:11:d8:39:4e:d0 brd ff:ff:ff:ff:ff:ff
inet 10.20.1.28/21 brd 10.20.7.255 scope global br0

urchin:/home/mzugec/svn/trunk/network/src # brctl show
bridge name bridge id STP enabled interfaces
br0 8000.0011d8394ed0 no eth0
tap0


Using TAP device with VirtualBox.

Virtualized machine through tunnel connected into bridge is accessible from outside network!

Monday, July 21, 2008

AutoYaST, network device names

Everybody probably knows YaST. You should use it, at least for installation. And what about AutoYaST? AutoYaST is a great tool for automatic installation and configuration. I did some work regarding automatic installation & network setup during installation. Documented here
I did 4 tests:

1 - When installation starts, udev will create configuration file for persistent naming (based on MAC address). At the end of 1st stage (before first reboot) YaST will copy this file into installed system, so after reboot all network devices will have same device names.

2 - Same as 1, but during AutoYaST installation. That means when no rule in AutoYaST profile about this file, keep it, not replace by empty file.

3 - Use AutoYaST profile. When there is defined some rule about this file, use it and replace the original one. This example from networking section creates corresponded udev rule to keep eth0 name for interface with 08:00:27:07:a2:2d MAC address (and replaces udev rule file from 1):

part of AY.xml

<networking>
...
<net-udev type=list>
<rule>
<rule>ATTR{address}</rule>
<value>08:00:27:07:a2:2d</value>
<name>eth0</name>
</rule>
</net-udev>
...
</networking>


/etc/udev/rules.d/70-persistent-net.rules file as a result:

# Generated by autoyast
# program run by the persistent-net-generator.rules rules file.
#
# You can modify it, as long as you keep each rule on a single line.
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="08:00:27:07:a2:2d", NAME="eth0"


4 - Migration from SLES10-style syntax. When you use your old profile (from <=SLES10x), it's something like:

<networking>
...
<interfaces config:type=list>
<interface>
<bootproto>dhcp</bootproto>
<device>eth-id-08:00:27:07:a2:2d</device>
<name>79c970 [PCnet32 LANCE]</name>
<startmode>auto</startmode>
<usercontrol>no</usercontrol>
</interface>
</interfaces>
...
</networking>


YaST will convert device name eth-id-08:00:27:07:a2:2d into rule for udev:

# Generated by autoyast
# program run by the persistent-net-generator.rules rules file.
#
# You can modify it, as long as you keep each rule on a single line.
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="08:00:27:07:a2:2d", NAME="eth0"


and rename configuration name into eth0

And that's all for now ...
... have a lot of fun
Bye,
Michal

Wednesday, July 9, 2008

Network Documentation

I started to document some exceptions or special cases of network during installation. But this is I already know (I don't know what users don't know or wants to know ;-)) so if anybody wants to some parts be more detailed or something is missing there, your feedback is welcome.