Saturday, October 6, 2007

Translating "finddialog"

As my first task; I am currently translating the finddialog source file to python. Currently I have translated the UI part. I have to still enable the signal and slot. Last night I was stuck with the 'emit'. Today after reading through example code, I found an hint with t8.pyw. I am exploring it currently.

UI only code ..


import sys
from PyQt4 import QtCore, QtGui

class MyForm(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)

self.label = QtGui.QLabel("Find what : ",self)
self.lineEdit = QtGui.QLineEdit(self)
self.label.setBuddy(self.lineEdit)
self.caseCheckBox=QtGui.QCheckBox("Match case",self)
self.backwardCheckBox = QtGui.QCheckBox("Search backward",self);
self.findButton = QtGui.QPushButton("Find",self)
self.closeButton = QtGui.QPushButton("Close",self)

topLeftLayout = QtGui.QHBoxLayout()
topLeftLayout.addWidget(self.label)
topLeftLayout.addWidget(self.lineEdit)

leftLayout = QtGui.QVBoxLayout()
leftLayout.addLayout(topLeftLayout)
leftLayout.addWidget(self.caseCheckBox)
leftLayout.addWidget(self.backwardCheckBox)

rightLayout = QtGui.QVBoxLayout()
rightLayout.addWidget(self.findButton);
rightLayout.addWidget(self.closeButton);
rightLayout.addStretch();

mainLayout = QtGui.QHBoxLayout()
mainLayout.addLayout(leftLayout)
mainLayout.addLayout(rightLayout)
self.setLayout(mainLayout)
self.setWindowTitle("Find")
self.setFixedHeight(self.sizeHint().height())

def findClicked(self):
pass

def enableFindButton(self):
pass

if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MyForm()
myapp.show()
sys.exit(app.exec_())

Now I have to enable the signal and slot mechanisms. I am wondering how the c++ pre-processor statements like QOBJECT, signal, slot, emit are supported in python. Let's see ...


I do not know how to translate the following piece of code for time being. I will look at that in the future.


Qt::CaseSensitivity cs =
caseCheckBox->isChecked() ? Qt::CaseSensitive
: Qt::CaseInsensitive;

The problem here is I don't know how to use Qt::... For time being I will just check if it is ticked or not.

Yet another problem..
I am not sure how I am going to define the signals as they have done in the header file as

signals:
void findNext(const QString &str, Qt::CaseSensitivity cs);
void findPrevious(const QString &str, Qt::CaseSensitivity cs);


With this also in the TODO list: I am continuing.

Somehow I could make a simple signal-slot work.

I made the following connection in __init__(..)

QtCore.QObject.connect(self.findButton, QtCore.SIGNAL("clicked()"),self.findClicked)


The above works

The syntax for signal-slot is as follows.

connect (SENDER,SIGNAL,RECEIVER,SLOT)

Assuming the sender is the findButton, and the signal is 'clicked()' and the receiver is not mentioned here. I would assume if noting is specified 'self' will be the receiver. Now look at the implementation of the slot (self.findClicked())


def findClicked(self):
str = self.lineEdit.setText('aaa')


This is just a test code to see if it works or not. Here we extract the lineEdit control from the self and set some value.

So I am surprised why the following doesn't work ?


QtCore.QObject.connect(self.findButton, QtCore.SIGNAL("clicked()"),self, QtCore.SLOT("self.findClicked()"))


I get the following error message.

Object::connect: No such slot MyForm::self.findClicked()


Does that mean I have to explicitly define signal and slot ?

Lets investigate ..

The problem I am really facing is I don't know how to define a custom signal. In the cpp example, they have defined custom signals as


signals:
void findNext(const QString &str, Qt::CaseSensitivity cs);
void findPrevious(const QString &str, Qt::CaseSensitivity cs);

Reading the PyQt3 it seems that we don't have to define signals in the C++ way. It would be enough just to emit the signals. Now we have to see how the slots has to used.

Also, it is not sure how to emit a custom signal in PyQt4. Any hint?

Info : Looking through the examples, it seems while connecting to a C++ signal, it we have to preserve the signature as in C++.


self.connect(self.fontCombo, QtCore.SIGNAL("activated(const QString &)"),
self.findStyles)


Seems it is clear now..
You can emit any signal. And the slot can be connected as with any C++ slot. We don't require any special syntax for it.

I tried the following example and it works.


import sys
from PyQt4 import QtCore, QtGui

class MyForm(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)

self.label = QtGui.QLabel("Find what : ",self)
self.lineEdit = QtGui.QLineEdit(self)
self.label.setBuddy(self.lineEdit)
self.caseCheckBox=QtGui.QCheckBox("Match case",self)
self.backwardCheckBox = QtGui.QCheckBox("Search backward",self);
self.findButton = QtGui.QPushButton("Find",self)
self.closeButton = QtGui.QPushButton("Close",self)


QtCore.QObject.connect(self.findButton, QtCore.SIGNAL("clicked()"),self.findClicked)

QtCore.QObject.connect(self, QtCore.SIGNAL("enableFindButton()"),self.Test)

topLeftLayout = QtGui.QHBoxLayout()
topLeftLayout.addWidget(self.label)
topLeftLayout.addWidget(self.lineEdit)

leftLayout = QtGui.QVBoxLayout()
leftLayout.addLayout(topLeftLayout)
leftLayout.addWidget(self.caseCheckBox)
leftLayout.addWidget(self.backwardCheckBox)

rightLayout = QtGui.QVBoxLayout()
rightLayout.addWidget(self.findButton);
rightLayout.addWidget(self.closeButton);
rightLayout.addStretch();

mainLayout = QtGui.QHBoxLayout()
mainLayout.addLayout(leftLayout)
mainLayout.addLayout(rightLayout)
self.setLayout(mainLayout)
self.setWindowTitle("Find")
self.setFixedHeight(self.sizeHint().height())

def findClicked(self):
str = self.lineEdit.setText('aaa')
self.emit(QtCore.SIGNAL('enableFindButton()'))

def enableFindButton(self):
#str = self.lineEdit.setText('ttt')
pass


def Test(self):
str = self.lineEdit.setText('ttt')

if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MyForm()
myapp.show()
sys.exit(app.exec_())

No comments: