PDA

View Full Version : Error signal connection between 2 classes



mattia
30th October 2007, 16:25
Hello, I'd like to create a simple application to show an xml file into a QTreeWidget.
I created the QMainWindow with QT designer the results is the ui_xmleditor.h file, then i made the XMLEditor.h class to implemets the manù funcionts.like open, etc...
The open function call the DomParser SLOT (which is defined in the XMlParser.h class) but it doenst work, the consolle show me the message:
Object::connect: No such slot XMlParser::DomParser(QString)
Object::connect: (sender name: 'MainWindow')

I defined the XMlParser.h in this way cos i want to modify the QTreeWidget in ui_xmleditor.h.
Is my approach correct?
I post all the code down here.

XMLEditor.h


#include <QtGui/QWidget>
#include "ui_xmleditor.h"
#include "xmlParser.h"
#include <QtXml>

class XMLEditor : public QMainWindow
{
Q_OBJECT

public:
XMLEditor();
~XMLEditor();
signals:
void DomParser(const QString &fileName);
private slots:
void open();
private:
XMlParser *xmlParser;
public:
QString fileNameO;
private:
Ui::MainWindow ui;
};


XMLEditor.cpp


#include <QtGui/QWidget>
#include <QFileDialog>
#include "xmleditor.h"
#include "xmlParser.h"


XMLEditor::XMLEditor()
{
ui.setupUi(this);
xmlParser = new XMlParser;

connect(ui.actionOpen, SIGNAL(triggered()), this, SLOT(open()));
//connect(this, SIGNAL(parseFile(const QString &fileName)), xmlParser, SLOT(xmlParser->DomParser(&fileName)));
connect(this, SIGNAL(DomParser(const QString)), (XMlParser*)xmlParser, SLOT(DomParser(const QString)));
//connect(this, SIGNAL(DomParser(const QString)), this, SLOT(open()));

}

XMLEditor::~XMLEditor()
{

}


void XMLEditor::open()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Open XML"), ".", tr("XML files (*.xml)"));
emit DomParser("/home/mattia/workspace/XML/file.xml");
}


XMlparser.h


#include <QtGui/QWidget>
#include "ui_xmleditor.h"


class QDomElement;

class XMlParser : public QMainWindow
{
Q_OBJECT
public:
XMlParser();
~XMlParser();
public:
void parseEntry(const QDomElement &element);
public slots:
void DomParser(const QString *fileName);
private:
Ui::MainWindow ui;
};


xmlParser.cpp


#include "xmlParser.h"
#include "ui_xmleditor.h"
#include "xmleditor.h"
#include <QtGui/QWidget>
#include <QtXml>
#include <QMessageBox>

XMlParser::XMlParser(){}

XMlParser::~XMlParser(){}

void XMlParser::DomParser(const QString *fileName)
{
ui.treeWidget->setWindowTitle("laaaaa");
QFile device("/home/mattia/workspace/XML/file.xml");
QString errorStr;
int errorLine;
int errorColumn;
QDomDocument doc;
/*if (!doc.setContent(device, true, &errorStr, &errorLine,
&errorColumn)) {
QMessageBox::warning(0, QObject::tr("DOM Parser"),
QObject::tr("Parse error at line %1, "
"column %2:\n%3")
.arg(errorLine)
.arg(errorColumn)
.arg(errorStr));
return;
}*/
QDomElement root = doc.documentElement();
if (root.tagName() != "utenti")
return;
QDomNode node = root.firstChild();
while (!node.isNull()) {
if (node.toElement().tagName() == "utente")
parseEntry(node.toElement());
node = node.nextSibling();
}
}

void XMlParser::parseEntry(const QDomElement &element)
{
QDomNode node = element.firstChild();
ui.treeWidget->setWindowTitle("qui");
QTreeWidgetItem *__item = new QTreeWidgetItem(ui.treeWidget);
__item->setText(0,"persona");
while (!node.isNull()) {


if (node.toElement().tagName() == "nome") {
QDomNode childNodeName = node.firstChild();
QTreeWidgetItem *__item1 = new QTreeWidgetItem(__item);
__item1->setText(0, childNodeName.toText().data());

}else if (node.toElement().tagName() == "cognome") {
QDomNode childNodeSurname = node.firstChild();
QTreeWidgetItem *__item1 = new QTreeWidgetItem(__item);
__item1->setText(0, childNodeSurname.toText().data());

}else if (node.toElement().tagName() == "indirizzo") {
QDomNode childNodeAddress = node.firstChild();
QTreeWidgetItem *__item1 = new QTreeWidgetItem(__item);
__item1->setText(0, childNodeAddress.toText().data());
}
node = node.nextSibling();
}
}


ui_xmleditor.h


#ifndef UI_XMLEDITOR_H
#define UI_XMLEDITOR_H

#include <QtCore/QVariant>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QButtonGroup>
#include <QtGui/QMainWindow>
#include <QtGui/QMenu>
#include <QtGui/QMenuBar>
#include <QtGui/QStatusBar>
#include <QtGui/QTreeWidget>
#include <QtGui/QWidget>

class Ui_MainWindow
{
public:
QAction *actionOpen;
QAction *actionSave;
QAction *actionAdd;
QAction *actionDelete;
QWidget *centralwidget;
QTreeWidget *treeWidget;
QMenuBar *menubar;
QMenu *menuFile;
QMenu *menuEdit;
QStatusBar *statusbar;

void setupUi(QMainWindow *MainWindow)
{
if (MainWindow->objectName().isEmpty())
MainWindow->setObjectName(QString::fromUtf8("MainWindow"));
MainWindow->resize(427, 542);
actionOpen = new QAction(MainWindow);
actionOpen->setObjectName(QString::fromUtf8("actionOpen"));
actionSave = new QAction(MainWindow);
actionSave->setObjectName(QString::fromUtf8("actionSave"));
actionAdd = new QAction(MainWindow);
actionAdd->setObjectName(QString::fromUtf8("actionAdd"));
actionDelete = new QAction(MainWindow);
actionDelete->setObjectName(QString::fromUtf8("actionDelete"));
centralwidget = new QWidget(MainWindow);
centralwidget->setObjectName(QString::fromUtf8("centralwidget"));
treeWidget = new QTreeWidget(centralwidget);
treeWidget->setObjectName(QString::fromUtf8("treeWidget"));
treeWidget->setGeometry(QRect(30, 10, 371, 481));
MainWindow->setCentralWidget(centralwidget);
menubar = new QMenuBar(MainWindow);
menubar->setObjectName(QString::fromUtf8("menubar"));
menubar->setGeometry(QRect(0, 0, 427, 28));
menuFile = new QMenu(menubar);
menuFile->setObjectName(QString::fromUtf8("menuFile"));
menuEdit = new QMenu(menubar);
menuEdit->setObjectName(QString::fromUtf8("menuEdit"));
MainWindow->setMenuBar(menubar);
statusbar = new QStatusBar(MainWindow);
statusbar->setObjectName(QString::fromUtf8("statusbar"));
MainWindow->setStatusBar(statusbar);

menubar->addAction(menuFile->menuAction());
menubar->addAction(menuEdit->menuAction());
menuFile->addAction(actionOpen);
menuFile->addAction(actionSave);
menuEdit->addAction(actionAdd);
menuEdit->addAction(actionDelete);

retranslateUi(MainWindow);

QMetaObject::connectSlotsByName(MainWindow);
} // setupUi

void retranslateUi(QMainWindow *MainWindow)
{
MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", 0, QApplication::UnicodeUTF8));
actionOpen->setText(QApplication::translate("MainWindow", "Open", 0, QApplication::UnicodeUTF8));
actionSave->setText(QApplication::translate("MainWindow", "Save", 0, QApplication::UnicodeUTF8));
actionAdd->setText(QApplication::translate("MainWindow", "Add", 0, QApplication::UnicodeUTF8));
actionDelete->setText(QApplication::translate("MainWindow", "Delete", 0, QApplication::UnicodeUTF8));
treeWidget->headerItem()->setText(0, QApplication::translate("MainWindow", "XML", 0, QApplication::UnicodeUTF8));
menuFile->setTitle(QApplication::translate("MainWindow", "File", 0, QApplication::UnicodeUTF8));
menuEdit->setTitle(QApplication::translate("MainWindow", "Edit", 0, QApplication::UnicodeUTF8));
} // retranslateUi

};

namespace Ui {
class MainWindow: public Ui_MainWindow {};
} // namespace Ui

#endif // UI_XMLEDITOR_H

jpn
30th October 2007, 16:46
I'd say, don't waste your time replicating the DOM tree structure to QTreeWidgetItems. Rather, use the model-view approach and wrap the existing DOM tree to a QAbstractItemModel. ;)

PS. There's an example available: Simple DOM Model (http://doc.trolltech.com/4.3/itemviews-simpledommodel.html).

PPS. The solution to your signal-slot connection problem is to refactor

void DomParser(const QString *fileName);
as

void DomParser(const QString &fileName);

mattia
30th October 2007, 17:29
I got it, but i have some problems to understand what's the parent id and what's its functions.
For example if I have created a layout wiht QT Designer and i want to implement other function i have to include the ui_class.h into my class.h, i'll add some functions into class.h and i'll implement them in class.cpp.
Now i want to modify, for example a Widget, that is declared in ui_class.h but to do this i want to create another class just to handling the data into the Widget, what have i to do to have a riferiment at the elements in ui_class.h?
I hope you understant it cos i know that my english isn't so good :o

jpn
30th October 2007, 17:45
I got it, but i have some problems to understand what's the parent id and what's its functions.
I'm sorry, what parent id are you talking about?


For example if I have created a layout wiht QT Designer and i want to implement other function i have to include the ui_class.h into my class.h, i'll add some functions into class.h and i'll implement them in class.cpp.
Correct. :)


Now i want to modify, for example a Widget, that is declared in ui_class.h but to do this i want to create another class just to handling the data into the Widget, what have i to do to have a riferiment at the elements in ui_class.h?
Yes, you might want to implement the model in separate files. In this case you would place a QTreeView on the form in Qt Designer. Then, in class.cpp you would a) include model.h (or whatever it's called), b) create an instance of the model, and c) anywhere after calling setupUi() (which creates the treeview) you would set the model to the treeview with QAbstractItemView::setModel().



// class.cpp
#include "class.h"
#include "model.h" // <-- a

Class::Class(QWidget* parent) : QWidget(parent)
{
ui.setupUi(this);

Model* model = new Model(ui.treeView); // <-- b
ui.treeView->setModel(model); // <-- c
}



I hope you understant it cos i know that my english isn't so good :o
It's ok. Mine is not that good either.. :)

mattia
31st October 2007, 08:40
Ok, thanks so much for your suggestion, I made as you told me and if I pass a Widget to another class i can modify it.
But what's happen if i want to pass to another class a pointer to QMainWindow to have acces at all the interface members(I mean the ui_class Widget put with QT Designer).
Down here the code.
In ui_guiwid.h I just added a QLabel labelPark and an menù action actionChangeLabel.
On doSmt.cpp the main error.
Thanks

guiwid.h


#include <QtGui/QWidget>
#include "ui_guiwid.h"

class guiwid : public QMainWindow
{
Q_OBJECT

public:
guiwid();
~guiwid();
private slots:
void callDoStm();
private:
Ui::MainWindow ui;
};



guiwid.cpp


#include "guiwid.h"
#include "doSmt.h"
#include <QtGui/QWidget>

guiwid::guiwid()
{
ui.setupUi(this);
connect(ui.actionChangeLabel, SIGNAL(triggered()), this, SLOT(callDoStm()));
}

guiwid::~guiwid()
{

}

void guiwid::callDoStm(){
doSmt *ds = new doSmt(ui.MainWindow);
ds->changeLabel();
}



doSmt.h


#include <QtGui/QWidget>
#include <QMainWindow>

class doSmt
{
public:
doSmt(QMainWindow *mainWindow);
~doSmt();
public:
void changeLabel();
QMainWindow *mainWindow;
};



doSmt.cpp


#include "doSmt.h"
#include <QtGui/QWidget>
#include <QLabel>

doSmt::doSmt(QMainWindow *mainWindow)
{
this->mainWindow = mainWindow;
}

doSmt::~doSmt()
{

}

void doSmt::changeLabel()
{
mainWindow->labelPark->setText("Yeap!"); //I can't access on this member
}

jpn
31st October 2007, 08:55
Well, to be honest, I think that's quite bad design. Contents of "Ui::MainWindow ui" is private part of "guiwid". Nobody else should be able to access them, really. Rather, "guiwid" should provide an interface to allow needed tasks to be done. Thanks to Qt's signals and slots, you could even keep "doSmt" unware of "guiwid". "doSmt" could for example just emit a signal which is connected to a slot in "guiwid".

mattia
31st October 2007, 09:36
Ok, i got it. Thanks so much again, now i know something more about how to design class on QT. ;)